--- name: fpga-imx6-flow description: > Run the fpga-imx6-flow LangGraph workflow at E:\LangGraph_Design\FPGA-imx6-flow — the closed-loop SMOD (FPGA + i.MX6) hardware-in-the-loop design/debug pipeline: power on the board, connect JTAG, program bitstream/flash, restart the imx6 app, analyze (ILA + COM6 serial), judge against design requirements, and iterate by modifying RTL/imx6 code. It drives the graph in-process (no langgraph dev) and hands the 5 interrupts (analyze / meets-requirement / propose / modify-FPGA / modify-imx6) back to this Claude session to execute. ALWAYS use this skill whenever the user wants to run, start, drive, resume, or continue the fpga-imx6-flow workflow / SMOD FPGA+imx6 design loop, or says things like "启动 fpga-imx6-flow", "跑 imx6 设计流程", "run the imx6 FPGA flow", "执行 SMOD 设计任务", "继续 imx6 工作流", "resume the imx6 design loop", even if they don't name the project path. Before driving the workflow this skill first confirms the langgraph conda environment from /langgraph-vivado-install is in place. --- ## What this skill does Drives the **fpga-imx6-flow** graph (24 nodes / 34 flow-edges, 1:1 with `Notes/fpga-imx6-flow.excalidraw`). The graph's deterministic hardware/check nodes (power, JTAG, program, restart) run in-process; its **5 interrupt nodes** pause and hand control to **this Claude session**, which performs the real work (analysis, judgment, RTL/app edits) and resumes the same thread. Persistence is a SqliteSaver file, so `start`/`resume` survive across separate process calls. | Item | Value | |---|---| | Project root | `E:\LangGraph_Design\FPGA-imx6-flow` | | Conda env | `langgraph` (`C:\Users\bowei\.conda\envs\langgraph`) | | Graph | `app.main_graph:build_graph` (in-process; no langgraph dev) | | Driver | `C:\Users\bowei\.claude\skills\fpga-imx6-flow\scripts\run_imx6_flow.py` | | Checkpoint | `\runs\skill_checkpoint.sqlite` (keyed by `--thread-id`) | | Design source | `Notes/fpga-imx6-flow.excalidraw`, plan `Notes/Task00.md` | ## ⚠️ 硬件时序铁律(上电 / USB-Blast / 烧写,务必遵守) **每次给 SMOD 上电之前,USB-Blast 必须先断开;上电完成之后再重新连接。** 绝不在 USB-Blast 处于连接状态时给板卡上电或断电(保护 JTAG 适配器与板卡)。 标准时序(图拓扑已按此实现,手动操作或写 `tools_*` / 真机脚本时也必须遵守): ``` 断电(COM8 power_off) → 确认已断电 → 断开USB-Blast(COM4 blast_off) → 确认已断开 → 上电(COM8 power_on) → 确认已上电 → 连接USB-Blast(COM4 blast_on) → 连接JTAG/烧写/抓ILA ``` **烧写 flash 的完整闭环**(固化后必须断电重启从 flash 加载再验证): ``` 断电 → 断开USB-Blast → 上电 → 连接USB-Blast → 用 /fpga_flash 烧写flash → 断电 → 断开USB-Blast → 上电 → 连接USB-Blast → 通过ILA验证flash内容正确 ``` - 在 LangGraph 图里:`power_off → check_power_off →(是) blast_off_a → check_blast_off →(是) power_on → check_power →(是) blast_on → check_hw`。`flash_burn` 烧写后回到 `power_off` 做整机断电重启,再次走完上述上电时序后才 `analyze`(抓ILA验证)。 - **强化确认**:`power_on` 节点在上电前调用 `_ensure_blast_off_before_power()` 兜底确认 USB-Blast 已断开;若发现仍连接会强制断开并在 `history` 标记 `rule_violation=True`。 - vivado-mcp 工具:`power_on`/`power_off`(COM8 继电器)、`USB_Blast_on`/`USB_Blast_off`(COM4)。 > **Run via the env python directly** (not bare `conda run`): on this Windows GBK > console, `conda run` re-prints the child's UTF-8 stdout through a GBK codec and > **crashes on the Chinese interrupt payloads**. Use the env `python.exe`, or > `conda run --no-capture-output`. The driver also re-configures its stdout to UTF-8. ``` PY = C:\Users\bowei\.conda\envs\langgraph\python.exe RUN = C:\Users\bowei\.claude\skills\fpga-imx6-flow\scripts\run_imx6_flow.py ``` ## Step 0 — Confirm the environment (REQUIRED before driving) The workflow runs in the `langgraph` conda env created by **`/langgraph-vivado-install`**. Verify it before starting, so a missing env surfaces as a clear instruction rather than a cryptic import error mid-run: ```powershell $py = "C:\Users\bowei\.conda\envs\langgraph\python.exe" if (-not (Test-Path $py)) { Write-Host "[MISSING] langgraph env" } else { & $py -c "import langgraph; from langgraph.checkpoint.sqlite import SqliteSaver; from langgraph.types import Command; print('[OK] langgraph + checkpoint-sqlite')" } ``` - **If `[OK]`** → proceed to Step 1. - **If missing / import fails** → tell the user the env isn't ready and to run **`/langgraph-vivado-install`** first (it creates the `langgraph` env with `langgraph` + `langgraph-checkpoint-sqlite` and the Vivado link). Do not proceed until it succeeds. **For a real-hardware run** (`--real`), additionally confirm: `env_config.json`'s `VIVADO_BIN_PATH` is valid; the vivado-mcp `power_on`/`USB_Blast_on` tools are available; COM4/COM6/COM8 are present (`[System.IO.Ports.SerialPort]::GetPortNames()`). **Default runs are MOCK** (dry-run of the design loop with no hardware), because the workflow's `tools_*` real-hardware paths are still TODO — see "Mock vs real" below. ## Step 1 — Start the workflow Ask the user (or infer) the first-pass program mode (`bitstream` default, or `flash`) and any `--bit-path`/`--flash-path`. Then start: ```powershell & $py $RUN start --project-dir "E:\LangGraph_Design\FPGA-imx6-flow" ` --thread-id "imx6-" --program-mode bitstream # add --real only when hardware tools are wired and the board is connected ``` The driver prints **one JSON line** and exits: | Exit | `status` | Meaning | |---|---|---| | 0 | `done` | Workflow finished (符合设计要求 / 迭代到上限) → Step 3 | | 1 | `error` | Read `error`, diagnose, report to user | | 2 | `interrupt` | An interrupt fired → read `interrupt.action` → Step 2 | ## Step 2 — Handle the interrupt, then resume On exit 2, the JSON's `interrupt.action` tells you what the session must do. Perform it, then resume the **same `--thread-id`** with a JSON payload. Repeat until exit 0. | `action` | excalidraw node | What you (the session) do | Resume JSON | |---|---|---|---| | `analyze` | 通过ila/串口分析 | Grab COM6 serial log + pull ILA waveform (vivado-mcp); summarize | `{"analysis_log":"<摘要/路径>"}` | | `meets_requirement` | 符合设计要求? | Judge the analysis against the design requirement | `{"meets": true}` or `{"meets": false}` | | `propose` | 分析原因,提出修改方案 | Diagnose root cause; decide what to change + next program mode | `{"reason":"...","need_fpga": true/false,"need_imx6": true/false,"program_mode":"bitstream"或"flash"}` | | `modify_fpga` | 改 RTL→综合→出 bit/flash | Edit RTL, run Vivado synth/impl, produce bit + flash files | `{"bit_path":"...","flash_path":"...","program_mode":"flash"}` | | `modify_imx6` | VM 改 app→交叉编译 | In the Ubuntu VM (`bowei@192.168.223.128`) edit app + cross-compile | `{"app_path":"..."}` | Resume command: ```powershell & $py $RUN resume --project-dir "E:\LangGraph_Design\FPGA-imx6-flow" ` --thread-id "imx6-" --resume-json '{"meets": false}' ``` Notes: - Always pass the **same `--thread-id`** used at `start` — that's how the sqlite checkpoint reattaches to the run (concurrency-safe: different tasks → different thread ids → isolated state). - `propose` fans out to BOTH `decide_fpga` and `decide_imx6`; with `need_fpga:false` and `need_imx6:false` the loop goes straight to `round_done` → re-program. Setting either true fires the corresponding `modify_*` interrupt next. - After `round_done` the graph re-asks the program-mode decision; `program_mode` you set in `propose`/`modify_fpga` chooses bitstream (download bit) vs flash (re-burn + full power/connect re-sequence). This is the big closed loop. ## Step 3 — Finish On exit 0 (`status: done`), report to the user: iterations completed and that the design met requirements (or hit the iteration cap). Offer to inspect `\runs\` artifacts or the per-step `history`. To abandon a paused run and start clean, delete `\runs\skill_checkpoint.sqlite` (or use a fresh `--thread-id`). ## Mock vs real - **MOCK (default)** — `FPGA_IMX6_MOCK=1`; hardware/check nodes return success immediately. Use this to dry-run the *design-loop logic* and the 5 interrupts with no board attached. Great for demonstrating/validating the flow. - **Real (`--real`)** — drives actual hardware. Requires the project's `app/tools_hw.py` / `tools_vivado.py` / `tools_imx6.py` real paths to be implemented (they currently raise `NotImplementedError` as TODO — they will reuse the proven vivado-mcp serial/Vivado logic). Until then, `--real` fails at the first hardware node; tell the user to wire the tools first (see `Notes/Task00.md` §7). ## Troubleshooting | Symptom | Fix | |---|---| | `UnicodeEncodeError: 'gbk' ...` | Don't use bare `conda run`; use the env `python.exe` or `conda run --no-capture-output`. | | `import failed ... Run /langgraph-vivado-install` | The `langgraph` env is missing/incomplete → run `/langgraph-vivado-install`. | | Exit 1 `NotImplementedError ... tools_*` | A `--real` run hit an unwired hardware tool. Run without `--real` (mock), or implement `tools_*`. | | `resume` seems to start over | You passed a different `--thread-id` than `start`. Use the same one. | | Need to see the graph visually | Optional: `langgraph dev` via the project's `langgraph.json` opens Studio — not required to run. |