bare-metal-bringup
Use when bringing up bare-metal or kernel code on a new architecture, SoC, or board (RISC-V, ARM, x86, ESP32) and it won't boot, hangs after boot, or faults…
Use when verifying a hardware DUT (a CPU core, FPGA, or netlist) against a golden reference model, building coverage-guided fuzzing, or detecting where silicon diverges from a simulator like Spike, an emulator, or SPICE
$ npx -y skills add Midstall/claude-for-hardware --skill differential-verification --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/differential-verificationContext preview
The summary Claude sees to decide when to auto-load this skill.
Use when verifying a hardware DUT (a CPU core, FPGA, or netlist) against a golden reference model, building coverage-guided fuzzing, or detecting where silicon diverges from a simulator like Spike, an emulator, or SPICE
name: differential-verification description: Use when verifying a hardware DUT (a CPU core, FPGA, or netlist) against a golden reference model, building coverage-guided fuzzing, or detecting where silicon diverges from a simulator like Spike, an emulator, or SPICE
You trust a design by running it against something you already trust and comparing. The DUT (device under test) executes a stimulus; a golden reference model executes the same stimulus; you compare the resulting state. A mismatch is a bug in one of them, and finding which is the work.
**Core principle:** Same stimulus, two executors, compare state. Everything else (fuzzing, coverage, campaigns) exists to generate good stimulus and to localize the divergence. The comparison is only as good as the state you capture and how honestly you name it.
generate stimulus -> run on DUT -> capture DUT state
-> run on golden model -> capture golden state
-> compare -> divergence? report : record coverage1. **One stimulus, two runs.** Drive the DUT and the reference with the identical input (the same program, the same vector, the same netlist excitation). 2. **Capture comparable state.** Final register file, memory regions, PC, retired-instruction trace, or node activity, whatever both sides can produce. 3. **Compare honestly.** A field you read but record as "absent" or `false` is a false pass waiting to happen. Make sure a captured value is actually compared.
Capture and compare register state under raw hardware names: `x0..x31`, `pc`, raw CSR names. ABI aliases (`a0`, `ra`, `sp`) are a rendering concern for the frontend only. If the comparison layer speaks ABI names, two tools will eventually disagree about which physical register `a0` is and you'll chase a phantom mismatch.
Random stimulus plateaus fast. Close the loop with coverage:
Track coverage on *both* the simulator and the silicon. When the same stimulus exercises different coverage on the two, that divergence is a finding in its own right, even before an architectural state mismatch shows up. An optional strict mode can flip the verdict on coverage divergence alone.
When state mismatches:
1. Confirm the stimulus was truly identical (same entry PC, same loaded segments, same memory init). Plenty of "bugs" are setup skew. 2. Shrink the stimulus to the minimal failing case. 3. Compare step-by-step (per-instruction or per-cycle) to find the first point of divergence, not just the end state. 4. Then decide which side is wrong. The golden model is not automatically right; reference models have bugs too.
| Smell | Do instead | |-------|------------| | Reading a value but recording it as absent/false | Verify captured fields are actually compared | | State keyed by ABI names | Key by hardware names, render ABI on the frontend | | Pure random fuzzing | Coverage-guided with a novelty scheduler | | Only comparing final state | Find the first diverging step | | Assuming the golden model is correct | Localize, then decide which side is wrong | | Strict checks toggled off to get a pass | Fix the divergence; see silicon-grade-discipline | | Test checks only that the transaction completed | Assert the read-back data, not just the handshake | | Model ignores byte-enables or leaves DQ/DQS as X | Compare on a channel-faithful model or on hardware | | Blaming silicon before the emulator ran | Reproduce on a golden model with perfect memory first | | Two "identical" builds differ, editing RTL | FASM-diff the bitstreams; byte-identical means a physical difference | | Rebuilding the toolchain on a theorized root cause | Validate a cheap fix empirically first; the cause may be secondary | | Testing writes and reads together on a dead lane | Bisect with a read-only oracle (DDR MPR or pre-written pattern) |
Claude Code skills for hardware design, validation, and bring-up. A plugin of focused skills that teach Claude how to do real hardware work: designing reusable HDL, integrating an SoC, bringing up FPGAs and bare-metal targets, building firmware boot chains,
Repo: Midstall/claude-for-hardware
Use when bringing up bare-metal or kernel code on a new architecture, SoC, or board (RISC-V, ARM, x86, ESP32) and it won't boot, hangs after boot, or faults…
Use when building or debugging a compiler backend, codegen, or assembler and you need to prove the generated machine code is correct by executing it on a real…
Use when building or debugging a firmware and boot chain (RISC-V SBI, UEFI, ACPI, a bootloader handoff like Limine to an OS) or adding measured boot with a…
Use when loading a bitstream onto a physical FPGA and driving or observing it over JTAG or GPIO, especially bit-banged JTAG from a host like a Raspberry Pi, or…
Use when synthesizing RTL to an FPGA with yosys/nextpnr (ECP5/Lattice and similar), fighting area or routing congestion, measuring Fmax, deciding why a design…
Use when writing, refactoring, or deciding how to test an HDL module, component, or IP block (ROHD, Chisel, SpinalHDL, Verilog, VHDL) and you need it…