From chipdev-method
Designs the contracts that hold across performance model, behavior model, and RTL — single-source-of-truth interface DSL, hierarchy DSL, global constants, protocol annotations, state contracts, observability hooks, and alignment points. Activate when the user explicitly invokes /chipdev-method:define-contracts, or when they describe defining new module boundaries, designing an interface DSL, planning difftest probes, asking "怎么定义接口", "interface DSL", "single source of truth", or starting any chip frontend project that will have more than one artifact.
npx claudepluginhub curryfromuestc/dev-guide --plugin chipdev-methodThis skill uses the workspace's default tool permissions.
Use this skill when the user is about to commit any structure that more than
Monitors deployed URLs for regressions after deploys, merges, or upgrades by checking HTTP status, console errors, network failures, performance (LCP/CLS/INP), content, and API health.
Share bugs, ideas, or general feedback.
Use this skill when the user is about to commit any structure that more than one artifact will share — interfaces, hierarchies, global constants, state shape, observation hooks. Do not autoload.
This is the most important skill in the plugin. Contracts decided here propagate to performance model, behavior model, RTL, and difftest. Drift between artifacts is almost always rooted in a contract that was implicit or convention-only.
When triggered:
build-* skill once contracts are defined.If the user has already started hand-coding interfaces in C++ headers or
SystemVerilog interface blocks without a DSL, surface this as a risk
immediately. The cost of switching to a DSL early is hours; the cost
in Phase 4 is weeks.
[abstract]Three observations drive this:
valid+ready mistake
in one place that should have been valid-only causes occasional
simulation hangs three months later. A formal annotation closes this.[abstract]A complete contract for an interconnected design includes all four. Skipping any one of them creates a class of integration failure.
What signals carry data, what signals carry handshake, who drives what.
valid-only: sender drives valid, receiver always accepts. Use for
unbounded fan-out, broadcast, or upstream-rate-limited paths.valid + ready: full handshake with backpressure. Use whenever the
receiver has a bounded queue.The annotation must travel with the interface definition, not as a sidecar comment. See "DSL design rules" below.
What is the architectural state of this module? — the state that survives
across reset and is sampled during difftest.
Where can an external probe (difftest, dump, trace) sample the module?
The observability contract is not the same as "every signal is exposed during debug". It is the curated set of points where two artifacts must agree.
Across artifacts, where do they meet?
align-and-difftest.[industry-pattern]A proven pattern is to maintain three DSL layers that together generate all downstream artifacts:
A small DSL for project-wide constants (number of cores, address widths, memory size class). Emits headers in three formats:
The same constant flows into all artifacts; changing it in one place updates everywhere.
A SystemVerilog-flavored DSL for declaring interfaces:
(* prot_validRdy = 1 *)
interface CMD_PACKET_IF;
logic [7:0] tag;
logic [3:0] opcode;
logic [63:0] payload;
endinterface
Key elements:
prot_valid,
prot_validRdy, prot_no). The parser inserts handshake signals
automatically — the writer never types valid or ready themselves.(* diff_skip = 1 *) — skip this field in difftest comparison
(e.g., a sequence number that is not architectural).
(* ack = 1 *) — mark as a reverse-direction signal.(* sel_… *)
attributes mapping enum values to union branches.Each .idf (or whatever extension you choose) file emits:
interface (for RTL).A second DSL declaring how interfaces connect into modules and how modules nest into the chip:
module SHADER_CORE(
CMD_PACKET_IF.in cmd_in,
DATA_RESPONSE_IF.out data_out
);
FRONTEND fe(.*);
PIPELINE pipe(.*);
BACKEND be(.*);
endmodule
Key elements:
.in / .out selectors on the interface..* for auto-name-matched binding (eliminates
most boilerplate).DEFINE_LANE(0); DEFINE_LANE(1); DEFINE_LANE(2); — same body
parameterized by index.Each .hdf (or chosen extension) file emits:
proc_<port> callbacks (one per input).[abstract]Layer A (constants .gdf)
│ python emitter
▼
*.h *.vh *.macro — consumed by C++, RTL, and DSL layers below
Layer B (interfaces .idf) + Layer A macros
│ M4 / Jinja2 / chosen macro processor
▼
*.idf.proc
│ parser (FLEX/BISON or hand-written or ANTLR)
▼
*_idf.h *_idf.cpp *.svh — interface bindings for all artifacts
Layer C (hierarchy .hdf) + Layer A macros
│ M4 / Jinja2 expansion
▼
*.hdf.proc
│ parser
▼
{Mod}Base.{h,cpp} — generated abstract base class
{Mod}Conn.{h,cpp} — generated connection / socket wiring
{Mod}Impl.h — handwritten-implementation skeleton
CreateModule.{h,cpp} — factory function
{Hier}.sv — RTL hierarchy
This pipeline is the operational form of "Generation over hand-writing" (invariant 1). Once it works end-to-end, adding a new module is:
.idf for new interfaces..hdf declaring the module and its ports.{Mod}Impl extending the generated {Mod}Base.Steps 1, 2, 4 take minutes. Step 3 is where engineering judgment lives.
[industry-pattern]| Stage | Mature options | Tradeoffs |
|---|---|---|
| Macro expansion | M4 / Jinja2 / ERB / Mako / Mustache | M4 is dependency-free and CMake-native; Jinja2 needs Python but is more readable. |
| Parser generator | FLEX + BISON / ANTLR / hand-written recursive descent | FLEX/BISON is mature, low-dependency, generates fast C; ANTLR is more powerful but pulls Java; hand-written gives flexibility but high maintenance. |
| Constants emitter | A small Python script reading a Python dict is enough. | Python is universal; YAML/TOML are alternatives if you want to forbid code in the constants file. |
| RTL DSL alternative | Chisel / SpinalHDL / Bluespec / Magma | Higher-level than IDF/HDF but constrains the team to one ecosystem; harder to also emit a SystemC simulator from the same source. |
A pragmatic default for a project that wants to emit both SystemC C++ and SystemVerilog from one source: GDF in Python + IDF/HDF in SystemVerilog-flavored syntax + M4 + FLEX/BISON parser. This is dependency-light and battle-tested.
[abstract]diff_skip or equivalent. Every field is compared in difftest;
legitimate differences (sequence numbers, latency-dependent counters)
flag as mismatches. Plan field-level skip semantics from day one.choose-artifact — what to build before defining contracts for it.build-perf-model — how the performance model consumes generated bases.build-behavior-model — how the behavior model uses the same contracts
with timing dropped.build-rtl — how RTL consumes generated interface and hierarchy SV.align-and-difftest — how the observability and alignment contracts
feed the difftest probe.references/dsl-survey.md — survey of public chip-design DSLs.references/interface-protocol-patterns.md — concrete protocol patterns.references/observability-hook-design.md — probe contract design.