AgentStack
SKILL verified Apache-2.0 Self-run

Gen Tb

skill-gokeshenzhen-gen-tb-skill-gen-tb-skill · by gokeshenzhen

Generate a complete UVM testbench scaffold for a single IP from its spec documents (docx/pdf/md) and register table (xlsx/csv/md/IP-XACT). Use whenever the user asks to "generate a UVM tb", "build a verification environment", "scaffold a testbench", "create a UVC", "set up DV for this IP", or anything equivalent in Chinese ("帮我生成验证环境", "搭一个 tb", "做 UVM 环境", "做这个 IP 的验证"). Also trigger when the us…

No reviews yet
0 installs
5 views
0.0% view→install

Install

$ agentstack add skill-gokeshenzhen-gen-tb-skill-gen-tb-skill

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Gen Tb? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

gen-tb — UVM Testbench Scaffold Generator

Purpose

Generate a directory-aligned UVM testbench for one IP from:

Built-in first-class buses: APB slave, AHB-Lite (slave or master), AXI4-Lite (slave or master). Other single-channel request/response buses (I2C, SPI, Wishbone, OBI, custom register buses, …) are handled by a generic fallback that reuses the same layout, sim flow, and tb_api surface — see §Scope below.

Inputs:

  • behavioral spec: *.docx, *.pdf, *.md
  • register table: *.xlsx, *.csv, markdown table, IP-XACT XML
  • RTL in place, an external RTL path, or a generated stub

The result must compile, run _sanity_test, run _reg_access_test, and provide two usage surfaces:

  • DV persona: UVM tests, sequences, agent, monitor, RAL hooks
  • DE persona: tb_api::write/read/expect_reg task-style BFM

Scope

| Dimension | Built-in (high-quality scaffold) | Generic fallback | Planned | |---|---|---|---| | Bus | APB slave, AHB-Lite (slave or master), AXI4-Lite (slave or master) | any single-channel request/response bus the scaffold sub-agent can infer from spec + the three built-in exemplars (e.g. I2C, SPI, Wishbone, OBI, custom register buses) | AXI4 full | | Simulator | VCS, Questa (vlog/vsim — static-only, see note), xrun (Cadence Xcelium) | VCS, Questa, xrun | — | | Ref model | none, SV, C-DPI | none, SV, C-DPI | Python-DPI | | Spec input | docx, pdf, md | docx, pdf, md | — | | Reg input | xlsx, csv, md, IP-XACT | xlsx, csv, md, IP-XACT (optional — set register_semantics: no for non-register buses) | — |

Generic fallback is a best-effort path: directory layout and sim flow stay authoritative, but the bus-shaped pieces (_if.sv, agent, sequence library, tb_api body) are inferred per-IP by a constrained scaffold sub-agent that pattern-matches on the three built-in references. Tell the user up-front that scaffold correctness is lower and the chance of an unresolved.md delivery is higher than in built-in mode. Load references/generic_bus.md only when entering this path.

AXI4 full (bursts/IDs/outstanding) is out of scope in both modes — it must never be routed to generic. If the DUT has AXI ports, follow the AXI4-full detector in Phase 1 and the mandatory question in Phase 2. For DUTs that expose AXI signals but use only single-beat transfers, generate the AXI4-Lite environment with a monitor-side assertion that AWLEN == 0 && ARLEN == 0, so any later burst use fails loud at sim time rather than relying on user review.

Do not use this skill for debugging an existing UVM environment, formal verification, gate-level sim, DFT, or a multi-master SoC subsystem.

Pipeline

Each phase writes audit artifacts under /work/_gen_audit/. Do not collapse phases; resumability and auditability are part of the deliverable.

  1. Discover: identify IP, spec, regs, RTL, optional external VIP
  2. Intake: ask only unresolved questions
  3. Normalize: produce registers.yaml, behavior.md, parse_report.md
  4. Scaffold: write the generated tree
  5. Compile-fix: run compile and use a constrained sub-agent if needed
  6. Sanity: run mandatory tests and runtime-fix loop if needed
  7. Hand-off: write CLAUDE.md, unresolved.md, and concise summary

Pipeline Hooks (Optional)

After each phase finishes writing its audit artifacts, call:

python3 scripts/hooks.py  

with `{discover, intake, normalize, scaffold, compilefix, sanity, handoff}. The script looks for /.gentbhooks/[.strict].{py,sh} and is a no-op when absent (zero cost in the common case). Non-strict hook failures are logged to work/genaudit/hooks/.log and do not block the pipeline; .strict. hooks abort the phase on non-zero exit. Hooks receive a JSON payload on stdin and GENTBPHASE / GENTBIPROOT / GENTBAUDIT_DIR` in env. Do not invoke hooks before audit artifacts for the phase are on disk.

Phase 1: Discover

IP Selection

Pick the IP root in this order:

  1. Explicit IP name/path from the user
  2. Current directory if its basename looks like an IP name
  3. The only child directory containing spec files
  4. Otherwise ask the user to choose

Show the selected IP name and path once so the user can correct it.

Spec And Registers

Search spec/, doc/, docs/, then IP root. Classify:

  • register table: *reg*table*.xlsx/csv, *regs*.xlsx/csv, IP-XACT XML
  • behavior spec: large *.pdf, *.docx, *spec*.md
  • markdown tables that look like regs: confirm if ambiguous

Do not ingest README, license, unrelated datasheets, draft/old/bak files.

RTL

Prefer an existing filelist. Otherwise scan rtl/, src/, design/, hdl/, and / for RTL, excluding tb/test/sim/bench paths. If no RTL exists, generate a stub only when the user confirms.

Infer top module using AST tooling if available; regex inference is medium confidence. If top is ambiguous, ask. Record exact APB / AHB / AXI4-Lite signal names and widths in rtl_discovery.yaml; never normalize case. For AHB-Lite and AXI4-Lite, also record which side of the bus the DUT sits on (bus_direction: slave|master) — slave is the default and means the TB drives a master BFM; master means the TB provides a memory-backed slave responder.

For buses that fall through to generic mode, rtl_discovery.yaml does not record bus_direction. The direction is collected in Phase 2 into bus_handshake.yaml.direction and that is the single source of truth for generic mode.

For details, load references/rtl_discovery.md and references/rtl_stub.md.

Bus Classification

After signal recording, classify the bus:

  1. If the top's port set matches the APB / AHB-Lite / AXI4-Lite

signature, set bus_protocol accordingly. Unchanged path.

  1. AXI4-full detector. If any of `awlen | arlen | awburst |

arburst | awid | arid is present with width > 0, set axifullsignature: true in rtldiscovery.yaml. The Phase 2 mandatory question below decides whether to refuse or degrade to AXI4-Lite. An AXI signal set must never be routed to busprotocol: generic`.

  1. Otherwise set bus_protocol: unknown and emit a

candidate_signals: block (the request/response-looking port group) into rtl_discovery.yaml. Do not guess a name — the bus name is collected in Phase 2.

Existing Bus VIP

If the user says they already have an APB, AHB, or AXI4-Lite VIP, ask for only:

  • _vip_path
  • desired reuse level: import_only or drive_with_vip

Use:

bus_protocol: apb                  # or ahb, axi_lite
apb_vip_source: reuse_my_vip       # or ahb_vip_source / axi_lite_vip_source
apb_vip_path:                # or ahb_vip_path / axi_lite_vip_path
apb_vip_reuse_level: import_only   # or ahb_vip_reuse_level / axi_lite_vip_reuse_level; default

import_only means scaffold imports the VIP into the compile tree and keeps built-in tests on tb_api. drive_with_vip means Phase 5 must also generate/adapt glue so the user's VIP can drive a minimal bus read/write smoke sequence — not implemented in v1; scaffold.py refuses drive_with_vip and the skill must default to import_only or hand-author the VIP-driven smoke test post-hoc. Do not guess third-party VIP APIs in Phase 4. For import_only, scaffold may skip vendor *_test_pkg.sv files that only serve the VIP's standalone harness.

Load references/apb_external_vip.md, references/ahb_external_vip.md, or references/axi_lite_external_vip.md before implementing or fixing external VIP reuse.

At phase end, if /.gen_tb_hooks/ exists, run python3 scripts/hooks.py discover .

Phase 2: Intake

Ask unresolved items in small batches. Questions to ask only when not already known.

Preset bundles are allowed (e.g. "Default config" / "Add C-DPI" / "VCS + xrun"), but every preset menu must satisfy:

  1. The currently supported simulators (vcs, questa, xrun) must

all appear at least once across the offered presets, or be reachable via an explicit "Customize simulators" / "Type something" path that lists them. Never present a simulator-related preset that names only a subset (e.g. listing "VCS / xrun" while omitting Questa) — it misleads the user into thinking the missing one is unsupported.

  1. The same rule applies to any other dimension with >1 first-class

value (bus protocol, refmodel language). If a preset hides a first-class option, the menu must include a visible "Customize" escape that surfaces the full set.

  1. The AXI4-full mandatory question (see below) is never allowed

inside a preset bundle — it must be its own AskUserQuestion turn.

Fields to ask about when not already pinned by Phase 1:

  • RTL state: found, external path, generated stub, none
  • bus protocol: APB, AHB, AXI4-Lite, or generic (when Phase 1 set

bus_protocol: unknown)

  • bus direction (AHB-Lite, AXI4-Lite, generic): DUT is slave (default) or master
  • bus VIP source: generate fresh, reuse existing VIP
  • external VIP reuse level: import only, drive with VIP
  • reference model language: none, SV, C-DPI (Python-DPI schema exists but is

not yet emitted — see references/refm_dpi.md)

  • clock/reset: pclk/presetn, hclk/hresetn, or aclk/aresetn frequency, polarity, reset cycles
  • UVM version: default 1.2 unless user specifies otherwise
  • simulator toolchain (multi-select): vcs, questa, xrun.

Default [vcs] when unanswered. Record in intake.yaml as simulators: [vcs] / [vcs, questa] / [vcs, xrun] / [vcs, questa, xrun] / etc. At least one must be selected. Per-sim emission:

  • vcsscript/makefile (canonical make all SV_CASE=).
  • questascript/makefile_questa

(make -f makefile_questa all SV_CASE=). Static-only — gen-tb has no Questa install to validate against; tell the user to verify locally before trusting it in CI.

  • xrunscript/makefile_xrun

(make -f makefile_xrun all SV_CASE=). When vcs is not selected, script/makefile becomes a thin shim that includes whichever sim-specific makefile is present, so the canonical make all SV_CASE=... still works. scripts/compile_and_sanity.py drives VCS by default; for questa-only or xrun-only configurations, run the mandatory tests with make -f makefile_ all SV_CASE= manually. Recommended user-facing wording: "Which simulators should I generate makefiles for? VCS / Questa / xrun (multi-select; default VCS)."

  • tcsh/csh setup helper: default no. If the user uses tcsh/csh,

record emit_setup_csh: true in intake.yaml; scaffold still emits script/setup.sh and additionally emits script/setup.csh. Do not infer this from $SHELL; generated trees may be used by other users or CI shells.

  • address width: paddr_width, haddr_width, or axi_addr_width, default 12
  • endianness for multi-word arrays
  • coverage: enabled or skipped
  • required extra smoke tests

AXI4-full Mandatory Question

When rtl_discovery.yaml has axi_full_signature: true, ask exactly: "Does this DUT use bursts (>1 beat), IDs, or outstanding?" This question is mandatory and cannot be skipped. Record the answer in intake.yaml as axi4_full_features: none (No) or axi4_full_features: present (Yes) — scaffold.py refuses to run without it.

  • Yes (axi4_full_features: present) → hard refuse. Write

unresolved.md pointing to planned AXI4-full work and exit. Do not enter Phase 3.

  • No (axi4_full_features: none) → route to the built-in AXI4-Lite

path. Phase 4 must emit a monitor-side assertion that AWLEN == 0 && ARLEN == 0, so any later burst use fails loud at sim time.

  • Unanswered / skipped → treat as Yes (refuse). scaffold.py exits

FATAL when axi_full_signature: true and the intake key is absent.

Generic Bus Intake Sub-Batch

When bus_protocol resolves to generic, collect the structured handshake description into work/_gen_audit/bus_handshake.yaml:

bus_name: 
direction: slave | master
clock: { name: , freq_mhz:  }
reset: { name: , polarity: low|high, cycles:  }
addr:  { port: , width:  } | null     # null = non-addressed
data:  { write_port: , read_port: , width:  }
handshake:
  kind: req_ack | valid_ready | strobe | custom
  req:   
  ack:   
  extra: [  ]
burst: none | simple_incr
register_semantics: yes | no
notes: |
  Free-form. Primary handshake hint to the scaffold sub-agent.

Confirm register_semantics explicitly. no means RAL and _reg_access_test are not generated and Phase 6 degrades to _responder_smoke_test.

All generated tests must be named __test.

Every question turn must include an abort/restart option. Save partial answers to work/_gen_audit/intake.yaml and bus_handshake.yaml, and resume from them if present.

At phase end, if /.gen_tb_hooks/ exists, run python3 scripts/hooks.py intake .

Phase 3: Normalize

Create:

work/_gen_audit/spec_normalized/registers.yaml
work/_gen_audit/spec_normalized/behavior.md
work/_gen_audit/spec_normalized/parse_report.md

Never proceed to Phase 4 without valid registers.yaml, except when bus_handshake.yaml.register_semantics == no in generic mode — that case has no register table by design, and registers.yaml is optional. behavior.md and parse_report.md are still required in all cases. Missing behavior parsers may degrade to warnings, but a missing/unparseable register table is blocking outside the register_semantics: no exception.

Field-level reset values win over register-level reset values. Emit warnings for unparseable offsets, widths, bit ranges, PDF tables, ambiguous aliases, and contradictions. The user must be told to read parse_report.md.

Load references/spec_parsing.md and references/registers_yaml_schema.md for schemas and parser rules.

At phase end, if /.gen_tb_hooks/ exists, run python3 scripts/hooks.py normalize .

Phase 4: Scaffold

Use scripts/scaffold.py with the audit inputs. The generated layout is fixed; load references/directory_layout.md for the authoritative tree.

Key scaffold rules:

  • write script/design.f, not rtl/design.f
  • write lowercase script/makefile
  • write script/tb.f for tb-side sources
  • always write bash-compatible script/setup.sh; when

emit_setup_csh: true, also write script/setup.csh

  • never copy or modify user RTL
  • if _vip_source: generate_fresh, emit tb/_agt_top/
  • if reuse_my_vip, emit tb/external_vip.f and skip fresh agent files
  • external VIP reuse is supported only for built-in buses; generic

mode always generates fresh (no generic_vip_source: reuse_my_vip)

  • keep tb_api generated in all modes
  • generate top/_tb_top.sv, tb/_if.sv, tests, audit
  • RAL is generated when the configuration has register semantics: i.e.

built-in slave direction, or generic slave direction with register_semantics: yes. Master direction in either mode skips RAL; generic register_semantics: no skips RAL.

For APB generation, load references/apb.md. For AHB generation, load references/ahb.md. For AXI4-Lite generation, load references/axi_lite.md. For external VIP reuse, load references/apb_external_vip.md, references/ahb_external_vip.md, or references/axi_lite_external_vip.md. For top wiring, load references/top_sv.md. For Makefile, load references/makefile_contract.md. For tb_api, load references/tb_api.md. For DPI, load references/refm_dpi.md.

Generic Bus Branch

When bus_protocol == generic:

  1. scripts/scaffold.py emits the bus-agnostic skeleton it already

knows: top tree, script/design.f, lowercase script/makefile, script/tb.f, test directory, audit dirs, empty tb/_agt_top/ with placeholder files, and a stub tb/_if.sv containing only the ports from bus_handshake.yaml. RAL is generated iff register_semantics: yes.

  1. Invoke the scaffold sub-agent defined in

references/sub_agent_generic_scaffold.md. Inputs:

  • references/generic_bus.md (contract)
  • references/apb.md, ahb.md, axi_lite.md (exemplars)

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.