From bbb99ba35ca88de96d50b3fabce9c012e2e65b51 Mon Sep 17 00:00:00 2001 From: francois Date: Wed, 20 May 2026 22:41:13 +0200 Subject: [PATCH] add CLAUDE.md with project guide Durable project context (architecture, roadmap, key decisions, external references, commit conventions) so any Claude Code session on any machine has the same baseline understanding. Machine-local facts stay out of the repo, in ~/.claude/. Co-Authored-By: Claude Opus 4.7 --- CLAUDE.md | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f6bb116 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,155 @@ +# Project guide for Claude Code + +This file is loaded automatically when working on `bs_explorer` in any +Claude Code session, on any machine where the repo is cloned. Keep +machine-specific or user-specific facts out of here — they belong in +`~/.claude/` memory, not in the repo. + +Project status, decisions, and roadmap below are durable: update them +when reality changes, not for every transient task. + +## What this project is + +`bs_explorer` is an application layer on top of Viveris's +[jtag-boundary-scanner](https://github.com/viveris/jtag-boundary-scanner) +library (LGPL). End goal: program SPI configuration memories attached +to FPGAs (Xilinx KU15P first, then others) over JTAG, from a CLI tool +running on a host with an FTDI probe. + +The Viveris library itself lives unchanged in `modules/`. Everything +new is in `bs/` (the REPL) and future modules (`fpga/`, `bscan_spi/`, +`spi_flash/`) sitting alongside the Viveris ones. + +## Architecture + +``` +bs/ Application (readline REPL, no business logic) +modules/ — Viveris's library (LGPL, unchanged) — +├── jtag_core/ TAP state machine, IR/DR shifts +├── bsdl_parser/ .bsd loader +├── bus_over_jtag/ SPI/I²C/MDIO/parallel mem bit-bang over EXTEST +├── drivers/ FTDI, J-Link, Linux GPIO, LPT +├── script/ Script engine (40+ commands, the real UI) +├── config/ Built-in config.script +├── os_interface/ Portable fs/network wrappers +└── natsort/ Natural pin-name sorting +bsdl_files/ BSDL files for target FPGAs +scripts/ Example scripts +libs/libftd2xx/ Vendored FTDI SDK +``` + +User interacts with the project through the script engine commands +(`jtag_*`, `set`, `if`, …), exposed via the REPL or piped script files. +Adding a feature usually means adding a new script command in +`modules/script/script.c` and the supporting C in a new module. + +## Roadmap + +| Phase | Module | Status | Summary | +|-------|--------|--------|---------| +| 1 | `bs/` cleanup, REPL polish, README | **done** (commit `7cb3627`) | Fix format-strings, delete dead code, tab-completion, banner | +| 2 | `fpga/` | planned | Per-target descriptor (IDCODE, BSDL, IR codes, proxy path, quirks). Compile-time registry. | +| 2.5 | `bscan_spi/` | planned | Load BSCAN proxy bitstream via `CFG_IN`, expose fast `bscan_spi_xfer()` via `USER1`. Required for realistic flashing speeds. | +| 3 | `spi_flash/` | planned | Chip database (JEDEC ID → page/sector/cmd set). Generic `read/erase/program/verify` over either backend. | +| 4 | script commands | planned | `flash_detect`, `flash_read/write/erase/verify`. | + +Move forward phase by phase: validate one with the user before starting +the next. Don't break the validated path +`jtag_open_probe → jtag_autoinit → jtag_set_mode 0 EXTEST` while +refactoring. + +## Key technical decisions + +### Flashing path: BSCAN proxy, not EXTEST + +The Viveris library has `bus_over_jtag/spi_over_jtag.c` which bit-bangs +SPI on FPGA pins placed in EXTEST. **This is not usable for actual +flashing.** Each SPI bit costs 2 full boundary-scan-register shifts +through JTAG, plus USB latency on the FTDI side. Order of magnitude: +~30 bytes/s effective, i.e. **weeks** to flash a 128 MB part. Useful +only for one-shot operations (read JEDEC ID, check wiring). + +Real flashing path: load a small "BSCAN proxy" bitstream into the FPGA +fabric via standard JTAG configuration (`CFG_IN`). The proxy uses a +`BSCANE2` primitive to bridge the JTAG `USER1` instruction's DR shift +to the physical SPI pins, running at fabric speed (CCLK driven +internally — the `STARTUPE3` problem disappears). Realistic throughput +50–200 KB/s, so ~10–40 min for 128 MB. This is what Vivado, OpenOCD's +`jtagspi` driver, and `xc3sprog` all do. + +### Per-FPGA descriptor + +`fpga_target` struct (Phase 2) holds the per-target facts that can't be +derived from the BSDL alone: +- `idcode` + `idcode_mask` — match the device on the chain +- `bsdl_filename` — BSDL to auto-load +- `cfg_in_ir_code`, `user1_ir_code`, `jprogram_ir_code` — Xilinx-specific + private IR opcodes (read from BSDL when available) +- `proxy_bitstream_path` — path to the BSCAN proxy `.bit` for this part +- `quirks` — flags for known caveats (e.g. CCLK via STARTUPE3) + +Registry is a compile-time array. Adding a part = one entry + its +`.bsd` in `bsdl_files/` + its proxy `.bit` in `bscan_proxies/`. + +### Xilinx caveats + +On 7-Series / UltraScale / UltraScale+, `CCLK` is not a regular I/O +pin — it goes through the `STARTUPE3` primitive. Cannot be driven +directly in EXTEST. Non-issue once we use the BSCAN proxy (CCLK is +driven by the fabric clock inside the proxy). + +The FPGA must be in a configurable state before loading the proxy. +Issue `JPROGRAM` first to reset, then `CFG_IN` + shift the bitstream, +then `JSTART` and check `DONE`. + +## External references + +- **BSCAN proxy bitstreams**: `quartiq/bscan_spi_bitstreams` (BSD-2). + Pre-built `.bit` for most Xilinx parts; Migen sources to rebuild any + part that's missing (needs Vivado). +- **Reference host-side implementation**: `openocd/src/flash/nor/jtagspi.c`. + Defines the proxy protocol (header with bit count + CS state, then + payload). Don't reinvent — match what OpenOCD does so we share the + same bitstreams. +- **Viveris library docs**: `modules/jtag_core/` headers are well + commented. `modules/config/config.script` documents every runtime + variable. + +## Build & test + +```sh +mkdir build && cd build && cmake .. && make +./bs/bs # interactive REPL +``` + +No automated tests yet. Smoke test = banner appears, `exit` works. +After changes touching `jtag_core`, `drivers/ftdi_jtag`, or the +`autoinit` flow, manual hardware test required: probe + KU15P board +should scan and load `xcku15p_ffve1517.bsd`. + +The FTDI driver compiles with int-to-pointer-cast warnings (Viveris's +code on 64-bit Linux). Don't fix in this repo — that's upstream. + +## Commit conventions + +- Messages in English, lowercase first word, imperative or short + descriptive (match existing style: "phase 1: cleanup, REPL polish, + README", "translate README to English"). +- Title ≤ ~70 chars. Body wrapped ~80 chars, with bullets for what + changed. Mention the why for non-obvious choices. +- Sign-off block: + ``` + Co-Authored-By: Claude Opus 4.7 + ``` +- One logical change per commit. Don't bundle README + bugfix + + refactor. + +## What does NOT belong here + +- User preferences (tone, language used in chat, "always do X first") + → `~/.claude/` +- Machine-local facts (which probes are physically attached, paths + outside the repo, validated-on-this-machine notes) → `~/.claude/` +- Transient task state, in-progress decisions → conversation, not file +- Generated artifacts (`build/`, downloaded proxy `.bit` if we choose + not to vendor) → `.gitignore`