From 956f26f6bf5efa34ed8a8f30cb8c943feecee74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois?= Date: Sun, 24 May 2026 01:20:45 +0200 Subject: [PATCH] doc: reframe programming-backends note around a universal SVF player MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Capture the vision: a single SVF player is a near-universal backend (Xilinx fabric config, Lattice, Microsemi IGLOO2, Altera, CPLDs from vendor-exported files); native backends are exceptions where streaming/ speed/control matter — chiefly Xilinx external SPI flash via the proxy. Adds a per-target path table and what an SVF player must implement. --- CLAUDE.md | 103 ++++++++++++++++++++++++++---------------------------- 1 file changed, 50 insertions(+), 53 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 81908bf..8d88369 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -121,68 +121,65 @@ 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`. -## Extending to other FPGA families (design note) +## Programming backends: beyond Xilinx external flash (design note) -Not yet implemented — captured here so the design is ready when needed. -Targets in mind: small Lattice MachXO2/MachXO3 (PSU sequencing/glue) and -Microsemi/Microchip IGLOO2 / SmartFusion2. +Not yet implemented — captured so the design is ready. Guiding vision: +**one generic SVF player as a near-universal backend, with native +backends only where streaming / speed / control justify them.** -**Key difference from Xilinx.** Our Xilinx path programs an *external* -SPI flash via a BSCAN proxy bitstream. Both Lattice MachXO2/3 and -Microsemi IGLOO2 instead hold their config in *internal* flash, -programmed *directly over JTAG* — no external flash, no proxy. So -`bscan_spi/` and `spi_flash/` do **not** apply to them; they need a -different programming backend. +### Why two layers -**What already generalises (reuse as-is):** -- probe drivers, `jtag_core`, and the `bscan_set_ir` / `bscan_shift_dr` - primitives in `bscan_spi/` — vendor-neutral, and exactly what any - JTAG programming sequence drives; -- IDCODE detection + BSDL load (BSDL is a standard); -- the `fpga_target` registry concept and the script-command framework. +Practically every JTAG-programmable device (Xilinx fabric config, +Lattice MachXO2/3, Microsemi IGLOO2/SmartFusion2, Altera, CPLDs, …) can +be programmed from an **SVF** file exported by its vendor tool. SVF is a +flat list of `SIR`/`SDR`/`RUNTEST` ops with the vendor's algorithm +already baked in — so a single SVF player, built on our existing +`bscan_set_ir` / `bscan_shift_dr` primitives, programs almost anything +with no per-vendor algorithm code. -**Two strategies for the programming backend:** +Native backends are the *exception*, justified only when you want fine +control, speed, or no vendor-export step. Our Xilinx **external SPI +flash** path is the prime example and stays native: load the BSCAN proxy +once, then stream raw binary with separate read/erase/program/verify, +progress and partial ops. The equivalent SVF ("indirect flash") is huge +(tens of MB of ASCII) and inflexible. -1. **Native per-family backend.** Implement the vendor's JTAG flow on - top of our IR/DR primitives. - - *Lattice MachXO2/3*: the IEEE 1532 / ISC sequence — `ISC_ENABLE` → - `ISC_ERASE` → `LSC_INIT_ADDRESS` → `LSC_PROG_INCR_NV` (page loop) → - `ISC_PROGRAM_DONE`, with BUSY polling. Well documented (Lattice - TN1204, IEEE 1532 BSDL `ISC_*` attributes) → very feasible. Needs a - `.jed` parser for the payload. - - *Microsemi IGLOO2*: the on-chip programming algorithm is - proprietary and complex (sys-services, eNVM/fabric) — reimplementing - it natively is a large, fragile effort. Not recommended. +### Where each path applies -2. **Generic SVF / STAPL player (higher leverage).** Execute the JTAG - programming file the vendor tool exports, instead of re-deriving the - algorithm. The vendor's algorithm is *baked into the file*. - - **SVF** = a flat list of `SIR`/`SDR`/`RUNTEST` ops → a small player - on `bscan_set_ir`/`bscan_shift_dr` covers it; vendor-neutral - (Lattice, Microsemi, Altera all export SVF). - - **STAPL** (`.stp`/`.jam`) = a full language (loops, conditionals) → - needs an interpreter, more work, but it's Microsemi's/Lattice's - native portable format. - - **For IGLOO2 this is the pragmatic route**: let Libero/FlashPro - export SVF (or STAPL) and just play it. One player → many vendors. +| Target | Recommended path | +|--------|------------------| +| Xilinx external SPI config flash | **native proxy** (`bscan_spi/`+`spi_flash/`, done). SVF works but is bloated. | +| Xilinx fabric config (volatile) | SVF, or our `bscan_load_bitstream` (equivalent) | +| Lattice MachXO2/3 (internal flash) | **SVF** (Diamond/Radiant export). Native IEEE-1532 ISC optional, only for a self-contained `.jed` flow. | +| Microsemi IGLOO2 / SmartFusion2 | **SVF/STAPL** (Libero/FlashPro export). Native algorithm too complex/proprietary. | +| Altera, CPLDs, misc JTAG | SVF | - Recommendation: an **SVF player** is the single highest-value - addition — it unlocks IGLOO2 *and* most other JTAG parts at once, - with the vendor owning the algorithm. Add native Lattice ISC only if - a self-contained `.jed` flow (no vendor export step) is wanted. +### The SVF player (the real work) -**Registry / dispatch adjustments:** -1. `fpga_target` is Xilinx-flavoured today (`ir_cfg_in`, `ir_user1`, - `ir_jprogram`, …). Generalise it — per-family opcode sets, or a small - "programming method" tag (`proxy_spi` / `lattice_isc` / `svf`) that - selects the backend. -2. The existing `family` enum is the natural dispatch point - (`FPGA_FAMILY_XILINX_*`, add `FPGA_FAMILY_LATTICE_*`, - `FPGA_FAMILY_MICROSEMI_*`). An SVF player is family-agnostic and - needs no per-part opcodes at all. +A player is more than shifting bits. It must handle: +- `SIR`/`SDR` with `TDI`/`TDO`/`MASK` — the **masked TDO compare** is + what detects prog/erase failures; that's the main addition over + today's primitives; +- `RUNTEST` delays (erase/program waits, in TCK or time) → reuse + `bscan_idle_cycles` + a sleep; +- `HIR/HDR/TIR/TDR` headers/trailers and `ENDIR/ENDDR/STATE` (multi- + device chains, TAP state) — a standard subset covers ~all files. -**Scope caveat.** Lattice MachXO2/3 and IGLOO2/SmartFusion2 are genuinely -JTAG-programmable. iCE40 is usually programmed over SPI directly (or +It reuses probe drivers, `jtag_core`, `bscan_set_ir`/`bscan_shift_dr` +and IDCODE/BSDL detection unchanged. **STAPL** (`.stp`/`.jam`) is the +richer native format (a full language → needs an interpreter); more +work, defer — do SVF first. + +### Registry / dispatch + +`fpga_target` is Xilinx-flavoured today (`ir_cfg_in`, `ir_user1`, …). +Add a "programming method" tag (`proxy_spi` / `svf` / optional +`lattice_isc`) selected off the `family` enum (add +`FPGA_FAMILY_LATTICE_*`, `FPGA_FAMILY_MICROSEMI_*`). An SVF player is +family-agnostic and needs no per-part opcodes — it can even run without +a registry entry. + +**Scope caveat.** iCE40 is usually programmed over SPI directly (or one-time NVCM) with minimal JTAG — out of scope for this JTAG-centric tool.