testbench-gen · git:20260711.0e18132 · 2026-07-11 · sha256 dfb9b81ec6ee6148
testbench-gen git:20260711.0e18132A
Immutable. This exact content is served forever at /api/v1/blob/dfb9b81ec6ee6148.
--- name: testbench-gen description: "Generate a PROFESSIONAL, high-coverage testbench for a design directly from its Phase-1 L-docs — the Phase-2 'Simulation' step (canonical flow Step 4). Use whenever a design needs functional verification: derive the interface (L1/L9), clock/reset (L8/L9), a reference model, a scoreboard, functional coverage, and assertions, then run cocotb. Program-first: the deterministic generator `professional_tb_gen.py` (MCP `eda_professional_tb`) does the derivation; this skill is the judgment layer for filling a non-closed-form reference model and reviewing coverage. Triggers on: 'write a testbench', 'generate testbench', 'verify this design', 'functional verification', 'coverage', '幫我寫 testbench', '產生 testbench', after Phase-2 RTL is authored and before Phase-3." --- # testbench-gen — deterministic professional testbench generation The canonical flow's **Step 4 (Simulation)** derives a professional, high-coverage testbench from the Phase-1 layers — never a hand-waved skeleton. The load-bearing work is a PROGRAM: `programs/professional_tb_gen.py` (exposed as MCP tool `eda_professional_tb`). This skill is the judgment layer around it. ## What the program does (program-first) `professional_tb_gen.py <project>` reads the project's `phase1/generated_docs/L*.json` and emits, under `phase2/stage1/sim_professional/<top>/`: - `tb_<top>.py` — a **cocotb** testbench: clock/reset from L8/L9, a reference model, a SCOREBOARD, functional coverage (cocotb-coverage covergroups), and a directed-corner + constrained-random stimulus loop. - `<top>_coverage_model.json` (an **L28** coverage model), `<top>_assertions.sva` (an **L29** assertion set), a cocotb `Makefile`, and `verification_plan.json`. It **combines open-source** frameworks rather than re-inventing them: **cocotb** (TB base) + **cocotb-coverage** (functional coverage + constrained-random) + **Verilator/Icarus** (sim) + an **SVA bind** for Verilator/SymbiYosys. Add `cocotb-coverage` to the runtime (see mcp-eda/INSTALL_GUIDE.md). ## The reference-model strategy — 3 tiers (honest, never a vacuous pass) 1. **Closed-form** (arithmetic primitives `c = a OP b`): reuses `arith_oracle_tb_gen.compute_golden` — the single source of truth. 2. **Bounded-latency streaming scoreboard** (serial datapaths — one parallel operand + a 1-bit serial operand + a 1-bit serial result, e.g. a bit-serial multiplier): the scoreboard AUTO-DERIVES the output `(latency, bit_order)` from a calibration vector, then checks every vector against the closed-form reference. **This closes the serial-datapath DEFER** that `arith_oracle_tb_gen` punts on entirely (proven: spm bit-serial multiplier, 208/208 vs `(x*y) mod 2^N`, `order=lsb latency=1` auto-derived). 3. **Reference hook** (classes with no closed form — CPU/SoC/DSP): the generated TB emits a clearly-marked `reference_model` hook that **`TestSkip`s until filled** — NEVER a silent vacuous pass. The judgment layer (this skill / spec-to-refmodel) fills it from L10 vectors or a spec-derived model, with the program-vs-AI cross-check (dual-track convergence). ## When YOU (the judgment layer) act - **Fill a Tier-3 reference model**: read the L-docs (L2 function, L3 protocol, L10 vectors) and author the Python reference the hook needs — then re-run so the scoreboard is real. This is the only place an LLM is needed; the interface, clock/reset, coverage bins, and (for Tier-1/2) the reference are all derived by the program. - **Review coverage**: after a run, read `coverage_<top>.xml` + the L28 model; if functional bins are unhit, add directed vectors or tighten the constrained-random constraints. Loop until the closure policy (functional bins 100% + code coverage targets) is met. - **Formalise assertions**: the L29 SVA carries reset→known-state + protocol handshake properties deterministically; L16 must/shall prose is emitted as `TODO(spec-to-assertion)` stubs for you to formalise (never fabricated as a passing SVA). ## Capture Any recovery here (a new reference-model pattern, a new coverage-derivation rule, a streaming-alignment case) is captured per `benchmark-enhancement-capture`: program-first into `professional_tb_gen.py` (a deterministic derivation rule) so the next design gets it automatically — and, if the gap is in a forked sim tool (Verilator/Icarus/cocotb), as a **Bucket-T** forked-tool item. ## Gaps to grow into (from the 2026-07-11 verification research) - Fill the currently-empty **L22 verification plan** fields (coverage_goals / formal_properties / regression_matrix) and wire them to L28/L29. - Add **L30 stimulus/constraints** (constrained-random weights, sequences). - Widen code coverage to FSM-transition / expression / condition (Verilator `--coverage-user`) and gate sign-off on it. - pyuvm structural env + riscv-dv for CPU-class constrained-random.