| 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)
- Closed-form (arithmetic primitives
c = a OP b): reuses
arith_oracle_tb_gen.compute_golden — the single source of truth.
- 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).
- Reference hook (classes with no closed form — CPU/SoC/DSP): the generated
TB emits a clearly-marked
reference_model hook that TestSkips 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.
Compliance gate (mandatory)
After producing your output, save it to a file and run:
python3 plugins/vibe-ic/_shared/skill_compliance_check.py \
--requirements plugins/vibe-ic/skills/testbench-gen/compliance.yaml \
<your_output_file>
Exit 0 = PASS, exit 1 = FAIL with specific missing elements listed.
compliance.yaml in the corresponding skill directory enumerates
every required element of your output: section headers, metadata fields,
handoff lines, tool invocations.
Your task is not complete until the audit returns PASS. Missing
elements are the single largest source of skill-execution non-determinism
across different agents.