Chipyard Nodes
API reference for the Chipyard library nodes in chia.chipyard. These
pages are generated automatically from the docstrings in the source, so they
stay in sync with the code.
State definitions
- class chia.chipyard.state_def.BuildTarget(*values)[source]
Bases:
str,EnumWhich Chipyard simulator flavor
ChiselBuildNodebuilds. Maps tomaketargets in ``chipyard/sims/verilator`- VERILATOR
Default fast Verilator sim (
makeinsims/verilator). No waveform capability; binarysimulator-<pkg>.harness-<config>.
- VERILATOR_DEBUG
Waveform/VCD-capable Verilator sim (
make debug). Binary suffixed-debug. Required forwf_scopes(build-time spatial trace filter) and runtime wave windows / VCD capture.
- FIRESIM_METASIM_VERILATOR
A FireSim metasim (
VFireSim) built undersims/firesim/sim; binary name uses the FireSim quintuplet<PLATFORM>-firesim-<DESIGN>-<config>-<PLATFORM_CONFIG>.
- class chia.chipyard.state_def.WaveWindow(pc: int, cyc: int, n: int = 1)[source]
Bases:
objectOne PC-triggered waveform-capture window.
Waveform collection is captured on the Nth retired commit of pc happens and dumps for cyc BOOM-core cycles thereafter. Each window fires at most once; overlapping windows merge into a single contiguous dump segment.
- class chia.chipyard.state_def.BuildArtifact(name: str, simulator_binary_content: bytes, simulator_binary_name: str, config: str, config_package: str, target: BuildTarget, success: bool, stdout: str, stderr: str, returncode: int, generated_src_files: list[tuple[str, str]]=<factory>)[source]
Bases:
objectResult of a
ChiselBuildNode.build(): a compiled simulator + metadata.The compiled simulator is shipped by value (the ELF bytes travel inside this object).
- name
Free-form label carried from
ChiselBuildNode.name(default"chipyard") for downstream identification.- Type:
str
- simulator_binary_content
Raw ELF bytes of the compiled simulator binary. Empty (
b"") when the build failed or timed out.- Type:
bytes
- simulator_binary_name
Filename of the simulator, e.g.
"simulator-chipyard.harness-MegaBoomV3Config".- Type:
str
- config
Chipyard
CONFIGthe binary was built for (e.g."MegaBoomV3Config").- Type:
str
- config_package
Chipyard
CONFIG_PACKAGE(Scala package, e.g."chipyard").- Type:
str
- target
The
BuildTargetthat produced this binary.
- success
True iff the build’s
makeexited 0 and the binary exists.- Type:
bool
- stdout
Captured stdout of the build command.
- Type:
str
- stderr
Captured stderr of the build command.
- Type:
str
- returncode
Exit code of the build command;
-1on timeout.- Type:
int
- generated_src_files
(filename, contents)pairs of generated.v/.svand.top.mems.confcollateral: populated only when the build was run withcollect_generated_src=True.- Type:
list[tuple[str, str]]
- class chia.chipyard.state_def.RiscvBuildArtifact(binary_name: str, binary_content: bytes, target: str, success: bool, stdout: str, stderr: str, returncode: int, dump: str = '')[source]
Bases:
objectResult of a
RiscvBuildNode.build(): a cross-compiled RISC-V ELF.- binary_name
Output filename, e.g.
"hello.riscv"or"hello".- Type:
str
- binary_content
Raw ELF bytes of the produced binary. Empty (
b"") when the build failed or timed out.- Type:
bytes
- target
Which toolchain/output convention was used:
"verilator"(baremetal) or"linux"(userspace).- Type:
str
- success
True iff
makeexited 0 and a non-empty binary was produced.- Type:
bool
- stdout
Captured stdout of the build command.
- Type:
str
- stderr
Captured stderr of the build command (includes a timeout note on expiry).
- Type:
str
- returncode
Exit code of the build command;
-1on timeout.- Type:
int
- dump
objdump -Ddisassembly of the ELF;""unlessbuild()was called withinclude_dump=True.- Type:
str
- class chia.chipyard.state_def.RiscvObjdumpArtifact(binary_name: str, dump: str, target: str, success: bool, stdout: str, stderr: str, returncode: int)[source]
Bases:
objectResult of a
RiscvObjdumpNode.dump(): a RISC-V ELF disassembly.- binary_name
Filename of the input ELF.
- Type:
str
- dump
The disassembly (stdout of the
objdumpinvocation);""on failure.- Type:
str
- target
Which toolchain prefix was used:
"verilator"(riscv64-unknown-elf-) or"linux"(riscv64-unknown-linux-gnu-).- Type:
str
- success
True iff
objdumpexited 0 and produced non-empty output.- Type:
bool
- stdout
Captured stdout of the objdump invocation (same content as
dump).- Type:
str
- stderr
Captured stderr (includes a timeout note on expiry).
- Type:
str
- returncode
Exit code of the objdump invocation;
-1on timeout.- Type:
int
- class chia.chipyard.state_def.RunResult(test_binary_name: str, log: str, out: str, returncode: int, success: bool, vcd_s3_path: str = '', vcd_size_bytes: int = 0, out_s3_path: str = '', log_s3_path: str = '', wave_windows: list[WaveWindow] = <factory>)[source]
Bases:
objectResult of a
VerilatorRunNode.run(): captured simulator output.- test_binary_name
Filename of the input test ELF that was run.
- Type:
str
- log
Simulator stdout captured to
<stem>.log(program / HTIF output).- Type:
str
- out
the
.outfile, containsspike-dasmdisassembly of the simulator’s stderr (the human-readable committed-instruction trace).- Type:
str
- returncode
Exit code of the simulator process.
- Type:
int
- success
True iff
returncode == 0.- Type:
bool
- vcd_s3_path
Full
s3://…URI of the uploaded VCD;""when no waveform was captured or no upload occurred (the VCD is too large to return inline).- Type:
str
- vcd_size_bytes
Local VCD size at upload time;
0when no upload.- Type:
int
- out_s3_path
s3://…URI of the uploaded.out;""when not uploaded.- Type:
str
- log_s3_path
s3://…URI of the uploaded.log;""when not uploaded.- Type:
str
- wave_windows
Echo of the
WaveWindowlist the run was configured with.- Type:
- class chia.chipyard.state_def.CosimResult(elf_name: str, match: bool, matched: int, completed: bool, first_divergence: dict | None, sim_cycles: int | None, failing_trace_gz: bytes | None)[source]
Bases:
objectResult of a
CosimNode.run(): the lockstep cospike verdict for one ELF.- elf_name
Filename of the ELF that was co-simulated.
- Type:
str
- match
True iff the DUT agreed with Spike (no divergence aborted the run).
- Type:
bool
- matched
Committed instructions Spike checked before the run stopped.
- Type:
int
- completed
True iff the program reached its end-of-test marker.
- Type:
bool
- first_divergence
{line, spike, dut}describing the first mismatch, orNoneon a match.- Type:
dict | None
- sim_cycles
Simulation cycles executed, or
Noneif not reported.- Type:
int | None
- failing_trace_gz
gzip’d tail window around the abort (DUT + Spike commit logs interleaved);
Noneon a match.- Type:
bytes | None
- class chia.chipyard.state_def.SpikeResult(test_binary_name: str, isa: str, log: str, commit_log: str, returncode: int, success: bool)[source]
Bases:
objectResult of running a RISC-V ELF on the Spike ISA simulator.
- test_binary_name
Filename of the input ELF that was executed.
- Type:
str
- isa
The
--isa=<...>string Spike ran with (e.g."rv64gc").- Type:
str
- log
Spike stdout, i.e. the program / HTIF output.
- Type:
str
- commit_log
Committed-instruction trace. Empty (
"") unless the run requested it vialog_commits=True.- Type:
str
- returncode
Exit code of the Spike process.
- Type:
int
- success
True iff the run succeeded. For self-checking riscv-tests this is exit code 0 reported over HTIF.
- Type:
bool
- class chia.chipyard.state_def.SpikeBuildArtifact(success: bool, spike_bin: str, stdout: str, stderr: str, returncode: int)[source]
Bases:
objectResult of (re)building the Spike simulator binary from source.
- spike_bin
Path to the (re)built spike binary (in-container).
- Type:
str
- stdout
Captured stdout of the build command.
- Type:
str
- stderr
Captured stderr of the build command.
- Type:
str
- returncode
Exit code of the build command.
- Type:
int
- class chia.chipyard.state_def.TortureMode(*values)[source]
Bases:
str,EnumHow a RISC-V Torture run generates and checks tests.
- SINGLE
Generate one test, run it, and diff signatures (
make rgentest).
- OVERNIGHT
Generate-and-test loop until
Nfailures orTminutes elapse (make rnight).
- REPLAY
Take a pre-supplied
test.S, run it, and diff signatures (make rtest).
- class chia.chipyard.state_def.TortureTestRun(name: str, success: bool, test_s: str, test_dump: str, spike_sig: str, rtlsim_sig: str, pseg_test_s: str | None = None)[source]
Bases:
objectArtifacts produced for one generated Torture test, pass or fail.
A test passes when the Spike reference signature matches the DUT (RTL simulation) signature.
- name
Basename of the test, e.g.
"test"or"test_1714571234".- Type:
str
- success
True iff the Spike signature matched the DUT signature.
- Type:
bool
- test_s
The generated assembly source (
.S).- Type:
str
- test_dump
objdumpoutput, if Torture produced one (else"").- Type:
str
- spike_sig
The Spike reference signature.
- Type:
str
- rtlsim_sig
The DUT (RTL simulation) signature.
- Type:
str
- pseg_test_s
The narrowed program segment from
testrun’s seek mode. Populated for failures only;Noneotherwise.- Type:
str | None
- class chia.chipyard.state_def.TortureResult(name: str, config: str, config_package: str, mode: TortureMode, success: bool, num_tests: int, num_failures: int, tests: list[TortureTestRun], stdout: str, stderr: str, returncode: int, build_artifact: BuildArtifact | None = None)[source]
Bases:
objectResult of a RISC-V Torture run against a built simulator.
- name
Free-form label carried from the run for downstream identification.
- Type:
str
- config
Chipyard
CONFIGthe simulator was built for (e.g."MegaBoomV3Config").- Type:
str
- config_package
Chipyard
CONFIG_PACKAGE(Scala package, e.g."chipyard").- Type:
str
- mode
The
TortureModethe run used.
- success
True iff all signatures matched and the run completed.
- Type:
bool
- num_tests
Number of tests run —
1forSINGLE/REPLAY,NforOVERNIGHT.- Type:
int
- num_failures
Number of tests whose signatures mismatched.
- Type:
int
- tests
Per-test artifacts. Includes passing and failing tests for
SINGLE/REPLAY; failing tests only forOVERNIGHT.- Type:
- stdout
Captured stdout of the Torture run.
- Type:
str
- stderr
Captured stderr of the Torture run.
- Type:
str
- returncode
Exit code of the Torture run.
- Type:
int
- build_artifact
The
BuildArtifactthat produced the simulator. Populated bytorture_from_config;Noneotherwise.- Type:
Chisel build
- class chia.chipyard.chisel_build_node.ChiselBuildNode(chipyard_path: str, config: str, config_package: str = 'chipyard', target: BuildTarget = BuildTarget.VERILATOR, make_jobs: int = 32, timeout_seconds: int = 600, extra_make_args: dict = {}, collect_generated_src: bool = False, clean_sim: bool = False, clean: bool = True, wf_scopes: list[str] | tuple[str, ...] = (), clean_wf_stamp: bool = True, logging_level: int = 10, name: str = 'chipyard')[source]
Bases:
objectElaborates a Chipyard config into a Verilator simulator binary.
Wraps the Chipyard
sims/verilator(and FireSimsims/firesim/sim) Make flow: it shells out tomakeinside the appropriate sims directory to run the Chisel generator and Verilator, then reads the resulting simulator ELF back into aBuildArtifactso it can be shipped to aVerilatorRunNodefor execution. By default runs on cluster nodes tagged withchipyard=1resource.Configure a single Chipyard Verilator build.
- Parameters:
chipyard_path – Absolute path to the Chipyard checkout (the
chia_artifactbranch) on the build node. Set to/home/ray/chipyardwhen using the CHIA chipyard container. The Make flow runs inside<chipyard_path>/sims/verilator(or, for FireSim metasims,<chipyard_path>/sims/firesim/sim).config – Chipyard
CONFIG: the ChiselConfigclass name that parametrizes the SoC to elaborate (e.g."RocketConfig","MegaBoomV3Config"). Passed to Make asCONFIG=<config>and becomes the suffix of the produced binary’s name.config_package – Chipyard
CONFIG_PACKAGE: the Scala package theConfigclass lives in (passed asCONFIG_PACKAGE=). Defaults to"chipyard"; the generated binary is namedsimulator-<config_package>.harness-<config>.target – Which simulator to build (see
BuildTarget):VERILATOR(fast, no waveforms),VERILATOR_DEBUG(make debug; VCD/waveform-capable, required forwf_scopesand runtime wave windows), orFIRESIM_METASIM_VERILATOR(a FireSim metasimVFireSimbinary built undersims/firesim/sim).make_jobs – Value passed to
make -jcontrolling build parallelism (number of concurrent compile jobs).timeout_seconds – Wall-clock limit for the main
makebuild. On expiry the build is killed and a failedBuildArtifact(returncode=-1) is returned. The precedingcleansteps have their own fixed 600s timeouts.extra_make_args – Additional
KEY=valueMake variables to append to the build command (e.g.{"VERILATOR_THREADS": 4}). ForFIRESIM_METASIM_VERILATORthese may includeDESIGN/PLATFORM/PLATFORM_CONFIGand are merged over the FireSim defaults. Note: passingWF_SCOPEShere conflicts withwf_scopes(below).collect_generated_src – If True, after a successful build read every generated
.v/.svfile (skippingTestDriver.vand any DPI-C files) plus the.top.mems.conffrom thegen-collateraldirectory intoBuildArtifact.generated_src_files.clean_sim – If True, run
make clean-simbefore building. This removes the simulator binaries but leaves the cachedchipyard.jarand generated FIRRTL/Verilog (gen_dir) in place: so it can relink against stale Verilog.clean – If True (default), run
make cleanbefore building. This also clears the Chisel-generator cache (chipyard.jar) andgen_dir, guaranteeing the build reflects the current Scala sources. Slower but correct.wf_scopes – chia_artifact-specific spatial waveform filter: a list of module-hierarchy scope paths (e.g.
"TestHarness.chiptop0.system...") restricting which modules Verilator traces into the VCD. Joined with spaces into theWF_SCOPESMake variable. At most_MAX_WF_SCOPES(8) paths, and only valid withtarget=VERILATOR_DEBUG(the Makefile wires the filter only into the debug model).clean_wf_stamp – If True and
wf_scopesis set, deletesims/verilator/.wf_scopes.stampbefore building so Make re-applies the scope filter even when it would otherwise consider nothing changed (mirrorsrun_wave.sh).logging_level – Python logging level for this node’s logger.
name – Label copied into the resulting
BuildArtifact.name; purely for downstream identification/traceability.
- build() BuildArtifact[source]
Run the Chipyard Make flow and return the compiled simulator.
Takes no arguments: every input comes from the attributes set in
__init__. Selects the sims directory, binary name andmakecommand line fromself.target/self.config/self.config_package(plusself.extra_make_args), optionally clears the WF_SCOPES stamp and runsmake clean/clean-sim, then invokes the build underself.timeout_seconds.- Returns:
On success, carries the simulator ELF bytes plus
config/config_package/targetand (ifcollect_generated_src) the generated source files. On a build failure or timeout,success=Falsewith empty binary content and the captured stdout/stderr and returncode (-1on timeout).- Return type:
CIRCT
General-purpose CIRCT chia nodes — firtool lowering, circt-opt invocation, custom-pass rebuild, ninja builds, lit runs, plus async MCP tool wrappers — usable from any chia flow.
These primitives wrap the CIRCT toolchain (firtool, circt-opt) plus chipyard’s
Chisel elaboration target so that any CHIA user can compose a CIRCT-driven flow
without re-implementing subprocess glue. They run as @ChiaFunction tasks on
a worker with the circt resource (advertised by the chia-circt image, which
ships /opt/circt-sdk and a source tree at /workspace/circt).
chisel_elaborate_to_chirrtl additionally needs Java + sbt; pair it with a chia-chipyard worker
or layer chipyard’s build deps into chia-circt if you need it co-located.
Usage example:
fir = chisel_elaborate_to_chirrtl(chipyard_path, "RocketConfig")["fir_text"]
hw = firtool_lower_chirrtl_to_hw(fir, repl_seq_mem=True)["hw_mlir"]
sv = circt_opt_lower_hw_to_verilog(hw)["verilog"]
- chia.chipyard.circt.firtool_lower_chirrtl_to_hw(chirrtl_text: str, repl_seq_mem: bool = True, extra_args: tuple[str, ...] = (), timeout_seconds: int = 600) dict[str, str][source]
Lower CHIRRTL FIRRTL text to HW-dialect MLIR via firtool.
Wraps
firtool --ir-hw [--repl-seq-mem --repl-seq-mem-file=<path>]against/opt/circt-sdk/bin/firtool. Withrepl_seq_mem=Truethe sequential memories are split off into a.mems.conffile (the same file Chipyard’s MacroCompiler consumes) and that text is returned in themems_confkey; otherwise it is the empty string.- Parameters:
chirrtl_text – Contents of a
.fir(CHIRRTL) file.repl_seq_mem – Pass
--repl-seq-mem --repl-seq-mem-file=...so seq-mems become external instances + a mems.conf sidecar.extra_args – Additional CLI flags appended verbatim to the firtool command line (e.g.
("--disable-all-randomization",)).timeout_seconds – subprocess timeout.
- Returns:
Dict with keys
hw_mlir(transformed MLIR text),mems_conf(empty ifrepl_seq_mem=False),stdout,stderr,returncode, andsuccess.
Example:
out = firtool_lower_chirrtl_to_hw(open("Top.fir").read()) assert out["success"]; print(out["hw_mlir"][:200])
- chia.chipyard.circt.circt_opt_run(mlir_text: str, pass_pipeline: str, extra_args: tuple[str, ...] = (), timeout_seconds: int = 600) dict[str, str][source]
Run
circt-opt --pass-pipeline='<pipeline>'on MLIR text.Thin wrapper that prefers
/workspace/circt/build/bin/circt-opt(so custom passes linked viarebuild_circt_opt_with_custom_pass()are picked up) and falls back to/opt/circt-sdk/bin/circt-opt.- Parameters:
mlir_text – Input MLIR (any dialect circt-opt understands).
pass_pipeline – Pipeline string passed verbatim to
--pass-pipeline(e.g."builtin.module(hw.module(canonicalize))").extra_args – Additional CLI flags appended after the pipeline.
timeout_seconds – subprocess timeout.
- Returns:
Dict with keys
stdout(transformed MLIR),stderr,returncode, andsuccess.
Example:
out = circt_opt_run(hw_mlir, "builtin.module(canonicalize)") print(out["stdout"])
- chia.chipyard.circt.circt_opt_lower_hw_to_verilog(hw_mlir_text: str, extra_args: tuple[str, ...] = (), timeout_seconds: int = 600) dict[str, str][source]
Lower HW-dialect MLIR to SystemVerilog via firtool’s
--ir-hw -> svpath.Convenience wrapper that runs firtool with
--format=mlirto consume HW MLIR and emit Verilog with the standard lowering options applied (mirrors what chipyard’s flow uses by default).- Parameters:
hw_mlir_text – HW-dialect MLIR (as produced by
firtool_lower_chirrtl_to_hw()).extra_args – Additional CLI flags appended verbatim.
timeout_seconds – subprocess timeout.
- Returns:
Dict with keys
verilog(emitted SV text on success, empty otherwise),stdout,stderr,returncode,success.
Example:
out = circt_opt_lower_hw_to_verilog(hw_mlir) print(out["verilog"][:200])
- chia.chipyard.circt.rebuild_circt_opt_with_custom_pass(pass_cpp_path: str, td_snippet_path: str | None = None, transforms_subdir: str = 'lib/Dialect/HW/Transforms', passes_td_path: str = 'include/circt/Dialect/HW/Passes.td', num_cpus: int = 16, timeout_seconds: int = 3600) dict[str, str][source]
Drop a user
.cppinto the CIRCT source tree, patchPasses.td, rebuildcirct-opt.Copy
pass_cpp_pathinto/workspace/circt/<transforms_subdir>/.Append the filename to the matching
CMakeLists.txtif not present.If
td_snippet_pathis given, splice it intoPasses.tdright before the closing#endifguard (idempotent).ninja -C /workspace/circt/build circt-opt(with-j ninja_jobswhen nonzero, else ninja’s default).
- Parameters:
pass_cpp_path – Absolute host path to the
.cppto inject.td_snippet_path – Optional
.tdsnippet to splice intoPasses.td. IfNone,Passes.tdis left untouched (useful when the pass already has its own .td definition).transforms_subdir – Subdirectory under
/workspace/circt/where the.cppshould land (and itsCMakeLists.txtlives). Defaults to the HW Transforms dir.passes_td_path – Path under
/workspace/circt/to thePasses.tdfile to patch.num_cpus –
-jvalue for ninja. Default 16 keeps headroom on a 32-core host. Pair with.options(num_cpus=N)at the call site if you also want Ray to reserve N CPUs per dispatch.timeout_seconds – subprocess timeout for the ninja build.
- Returns:
Dict with keys
success("True"/"False"),log(combined stdout/stderr from ninja), andbinary_path(the rebuiltcirct-optlocation on success, empty otherwise).
Example:
r = rebuild_circt_opt_with_custom_pass("/work/passes/MyPass.cpp", "/work/my_pass_def.td") print(r["success"], r["binary_path"])
- chia.chipyard.circt.list_circt_passes(category: str | None = None, timeout_seconds: int = 60) list[str][source]
List available
circt-optpasses, optionally filtered by dialect prefix.Runs
circt-opt --helpand parses out lines beginning with--that look like pass flags (single-token, no spaces, not a built-in option).- Parameters:
category – Optional pass-name prefix to filter by (e.g.
"hw-","firrtl-").Nonereturns every parsed pass.timeout_seconds – subprocess timeout.
- Returns:
Sorted list of pass names (without the leading
--).
Example:
hw_passes = list_circt_passes(category="hw-") print(hw_passes[:5])
- chia.chipyard.circt.chisel_elaborate_to_chirrtl(chipyard_path: str, config: str, config_package: str = 'chipyard', num_cpus: int = 16, timeout_seconds: int = 1800) dict[str, str][source]
Elaborate a chipyard Chisel config and return its CHIRRTL
.firtext.Drives the chipyard make target that produces the
.firand.anno.jsonfor a givenCONFIG/CONFIG_PACKAGEpair, so the output is ready to pipe straight intofirtool_lower_chirrtl_to_hw(). Runs in<chipyard>/sims/verilator(the canonical entry point that re-exportsfirrtl).- Parameters:
chipyard_path – Path to the chipyard installation.
config – Chisel config name (e.g.
"RocketConfig").config_package – Scala package holding the config (default
"chipyard").num_cpus –
-jfor the make invocation. Default 16 keeps headroom on a 32-core host. Pair with.options(num_cpus=N)at the call site if you also want Ray to reserve N CPUs per dispatch.timeout_seconds – subprocess timeout.
- Returns:
Dict with keys
fir_text(CHIRRTL contents on success, empty otherwise),anno_json(annotations JSON, empty otherwise),stdout,stderr,returncode,success.
Example:
r = chisel_elaborate_to_chirrtl("/scratch/chipyard", "RocketConfig") print(r["fir_text"][:200])
- chia.chipyard.circt.circt_ninja_build(targets: tuple[str, ...] = ('circt-opt',), num_cpus: int = 16, timeout_seconds: int = 1800) dict[source]
Build CIRCT targets with
ninja -C /workspace/circt/build [-j N].Generalises the build step of
rebuild_circt_opt_with_custom_pass()to any target set (circt-opt,firtool,arcilator, …). Incremental: only the touched objects + the affected tools relink.Runs ninja in its OWN process group (
start_new_session) and SIGKILLs the whole group on timeout. Without this, a lingering child (clang/lld) that keeps the stdout pipe open wedgescommunicate()forever — even after ninja exits. Returns{success: bool, returncode: int, log_tail: str}.
- chia.chipyard.circt.circt_warm_build(targets: tuple[str, ...] = ('circt-opt', 'firtool'), num_cpus: int = 16, timeout_seconds: int = 5400) dict[source]
Idempotent per-container warm-up: ensure
litis installed and targets are built, then drop a sentinel so repeat calls are no-ops.The chia-circt image bakes only
circt-opt; warming the other tool targets here is cheap (shared dialect libs are already built). Safe to call at the start of every task — only the first call on a given container does work.Returns
{success: bool, warmed: bool, log_tail: str}(warmed=Falsemeans the sentinel already existed).
- chia.chipyard.circt.circt_run_lit(test_paths: tuple[str, ...], extra_args: tuple[str, ...] = (), timeout_seconds: int = 1800, filter_out: str = '') dict[source]
Run
liton build/test path(s) (relative to /workspace/circt/build).Resolves the py_worker
lit(installed bycirct_warm_build()), falls back to PATH. FileCheck/not/count come from the SDK on PATH. Emptytest_paths→ success with zero tests (nothing to regress).filter_outis a regex passed to lit’s--filter-outto skip matching test names.Returns
{success: bool, passed: int, failed: int, failures: list[str], log_tail: str}.
- class chia.chipyard.circt.BuildTool(name: str, num_cpus: int = 16, task_options=None)[source]
Bases:
AsyncJobToolMCP tool: rebuild CIRCT tool target(s) with ninja, ASYNCHRONOUSLY.
Initializes ChiaTool with a name and optional resource requirements.
- build(targets: list[str] | None = None) dict[source]
Start a ninja build of CIRCT target(s) in the BACKGROUND and return IMMEDIATELY (does NOT wait). Then poll <name>_build_status until it returns done=true to get {success, returncode, log_tail}.
- Parameters:
targets – e.g. [“circt-opt”] (default) or [“firtool”].
- class chia.chipyard.circt.LitTool(name: str, task_options=None)[source]
Bases:
AsyncJobToolMCP tool: run lit regression tests, ASYNCHRONOUSLY (same rationale as build — a whole-dialect lit run can take minutes).
Initializes ChiaTool with a name and optional resource requirements.
Macro compiler
Chipyard MacroCompiler glue for SRAMs.
Parses the Chipyard/firtool .top.mems.conf into SRAMSpecs, generates the
MacroCompiler MDF JSON library describing each macro, and runs Chipyard’s
tapeout.jar MacroCompiler to remap the synflop SRAMs onto those macros.
- class chia.chipyard.macrocompiler.SRAMSpec(name: str, depth: int, width: int, ports: str, mask_gran: int | None, num_rw_ports: int = 0, num_read_ports: int = 0, num_write_ports: int = 0, parsed_ports: list[tuple[str, bool]]=<factory>)[source]
Bases:
object
- chia.chipyard.macrocompiler.rename_ports(ports_str: str) tuple[list[tuple[str, bool]], int, int, int][source]
Parse a comma-separated port string into named ports with counts.
Mirrors Chipyard ConfReader.renamePorts(). Each token becomes a (prefix, masked) tuple with incrementing per-type counters.
Example: “write,write,read” -> ([(“W0”, False), (“W1”, False), (“R0”, False)], 1, 2, 0)
- chia.chipyard.macrocompiler.parse_mems_conf(content: str) list[SRAMSpec][source]
Parse a .top.mems.conf file into a list of SRAMSpec.
- chia.chipyard.macrocompiler.generate_macrocompiler_lib(sram_specs: list[SRAMSpec], cell_prefix: str = 'mapped_') str[source]
Generate MDF JSON library for MacroCompiler from SRAM specs.
Each SRAM gets a library entry named
<cell_prefix><name>with exact-match depth/width/ports/mask_gran so MacroCompiler maps 1:1 without splitting.
- chia.chipyard.macrocompiler.remap_with_macrocompiler(mems_conf_content: str, macrocompiler_lib_json: str, chipyard_path: str) str | None[source]
Run MacroCompiler to remap synflop SRAMs to library macros.
Runs on a chipyard node where Java + tapeout.jar are available. This is the only function in this module that touches a Chipyard resource (it shells out to
java -cp <chipyard>/.classpath_cache/tapeout.jar tapeout.macros.MacroCompiler), so it is the only one decorated with@ChiaFunction(resources={"chipyard": 1}). The generators above (parse/lib/stub/assemble) are pure Python and stay plain callables.- Parameters:
mems_conf_content – Contents of .top.mems.conf
macrocompiler_lib_json – MDF JSON library with SRAM entries
chipyard_path – Path to chipyard installation (for tapeout.jar)
- Returns:
Remapped .top.mems.v content, or None on failure.
- chia.chipyard.macrocompiler.assemble_generated_src_with_macros(generated_src_files: list[tuple[str, str]], remapped_mems_v: str, macro_stubs: list[tuple[str, str]]) list[tuple[str, str]][source]
Swap in the MacroCompiler-remapped .top.mems.v and add macro stubs.
Library-agnostic: works for any MacroCompiler remap output (CACTI, SRAM22, etc.), since it only matches on module names, not the macro contents.
- Parameters:
generated_src_files – Original generated_src from build.
remapped_mems_v – MacroCompiler output instantiating the library macros.
macro_stubs – List of (filename, content) blackbox stub modules for the mapped macros.
- Returns:
Modified generated_src with the remapped .top.mems.v swapped in, any gen-collateral .sv files that redefine the remapped modules removed, and the macro stubs appended. The .top.mems.conf is left untouched.
- chia.chipyard.macrocompiler.generate_macro_stubs(sram_specs: list[SRAMSpec], cell_prefix: str = 'mapped_') list[tuple[str, str]][source]
Generate blackbox Verilog stubs for mapped SRAM macros.
Each stub declares the port interface matching the MacroCompiler instantiation (and the Liberty cell) with no body. Library-agnostic: the cell_prefix selects the macro family (e.g.
"cacti_","sram22_").
Chipyard / Hammer
chia.chipyard.chipyard_hammer — Chipyard VLSI (hammer) makefile nodes.
Chipyard wraps hammer-vlsi behind make in <chipyard>/vlsi: the
buildfile target elaborates the design and generates $(OBJ_DIR)/
hammer.d, a make fragment that is -include``d to provide the flow targets
(``syn, par, drc, lvs, power, redo-<action>, …).
Everything is parameterized by make variables — CONFIG, tech_name,
TOOLS_CONF / TECH_CONF / INPUT_CONFS, VLSI_TOP, OBJ_DIR,
HAMMER_EXTRA_ARGS, … — so one generic target runner covers the whole
flow. ChipyardHammerNode.make() is that runner.
The chipyard checkout, its generated RTL, and the OBJ_DIR are PATH-BASED on
the worker, so chained targets (buildfile -> syn -> par) and report fetches
(ChipyardHammerNode.collect()) must land on the SAME worker.
ChipyardHammerNode enforces that via a placement group (see
chia.base.colocated.ColocatedNode for the given / reserved / no-PG
construction modes). ChipyardHammerNode.<fn>.chia_remote(...) (the class
attribute) is the raw, unpinned form for callers that handle placement
themselves.
Like chia.chipyard.chisel_build_node, this module assumes the worker’s
environment is already chipyard-ready (the chipyard docker images source the
env in their setup commands); use the env argument for per-call overrides.
This module is deliberately independent of chia.vlsi.hammer, which wraps
bare hammer-vlsi CLI calls: here hammer is an implementation detail behind
chipyard’s Makefile.
- class chia.chipyard.chipyard_hammer.ChipyardHammerResult(success: bool, returncode: int, target: str, vlsi_dir: str, obj_dir: str | None, stdout: str, stderr: str, listing: dict[str, int]=<factory>)[source]
Bases:
object
- class chia.chipyard.chipyard_hammer.ChipyardHammerCollectResult(base_dir: str, files: dict[str, str], skipped: dict[str, int], listing: dict[str, int])[source]
Bases:
object
- class chia.chipyard.chipyard_hammer.ChipyardHammerNode(placement_group=None, require_colocated: bool = True, *, bundle_index: int = 0, reserve_bundle: dict | None = None, pg_strategy: str = 'STRICT_PACK', wait_for_pg: bool = True, pg_ready_timeout_s: float | None = None)[source]
Bases:
ColocatedNodeChipyard VLSI make / collect primitives sharing one placement.
The members are
@staticmethod @ChiaFunction(resources={"chipyard": 1});__init__re-binds each into a per-instance pinned form sonode.<fn>.chia_remote(...)lands on this node’s bundle:with ChipyardHammerNode() as node: # reserves {"CPU": 1, "chipyard": 1} obj_dir = "/scratch/vlsi-build/run1" bf = get(node.make.chia_remote( "/home/ray/chipyard", "buildfile", config="RocketConfig", obj_dir=obj_dir, make_vars={"tech_name": "sky130"})) syn = get(node.make.chia_remote( "/home/ray/chipyard", "syn", config="RocketConfig", obj_dir=obj_dir, make_vars={"tech_name": "sky130"})) rpts = get(node.collect.chia_remote( obj_dir, ["syn-rundir/reports/**"])) # same worker, guaranteed
Set up placement and bind the member functions.
- Parameters:
placement_group – an existing Ray
PlacementGroupto schedule onto. If given,require_colocatedis moot (placement is already fixed) and this node will not remove the PG on close.require_colocated – when no PG is given, reserve one so all members co-locate. When False, leave placement to the caller.
bundle_index – which bundle of the (given or reserved) PG to pin to.
reserve_bundle – resource shape of a self-reserved bundle (default
_DEFAULT_BUNDLE). A bundle too small for some members is allowed — those members just can’t dispatch through this node (a construction-time warning lists them).pg_strategy – placement strategy for a self-reserved PG.
wait_for_pg – block on
pg.ready()for a self-reserved PG so the node is usable immediately.pg_ready_timeout_s – optional timeout for that wait.
- static make(chipyard_path: str, target: str, config: str | None = None, obj_dir: str | None = None, make_vars: dict[str, str] | None = None, jobs: int = 1, env: dict[str, str] | None = None, timeout_seconds: int = 86400) ChipyardHammerResult[source]
Run one
make -C <chipyard>/vlsi <target>on a worker.- Parameters:
chipyard_path – Chipyard checkout root on the worker.
target – Any vlsi Makefile target: “buildfile”, “syn”, “par”, “drc”, “lvs”, “power”, “redo-syn”, “clean”, … (the flow targets exist after “buildfile” has generated hammer.d).
config – Chipyard CONFIG (e.g. “RocketConfig”). Convenience for
make_vars={"CONFIG": ...}.obj_dir – Hammer build directory, passed as
OBJ_DIR=and used forlisting. When None, chipyard derives its default (vlsi/build/<long_name>-<TOP>) andlistingis empty. Pass the same value across buildfile/syn/par calls.make_vars – Any other vlsi Makefile variables, e.g.
{"tech_name": "sky130", "VLSI_TOP": "ChipTop", "INPUT_CONFS": "a.yml b.yml", "HAMMER_EXTRA_ARGS": "-p x.yml"}. Appended last, so they win overconfig/obj_dir.jobs – make -j level (elaboration in “buildfile” benefits; the hammer flow targets manage their own parallelism).
env – Extra environment variables layered over the worker’s (assumed chipyard-ready) environment.
timeout_seconds – Wall-clock limit for the subprocess.
- static collect(base_dir: str, patterns: list[str], max_bytes_per_file: int | None = None) ChipyardHammerCollectResult[source]
Fetch text files from a previous make’s OBJ_DIR (or any directory) on this worker.
Dispatch via the pinned instance member (
node.collect.chia_remote) so it lands on the worker that owns the files — an unpinned call may not.- Parameters:
base_dir – Directory a previous target ran in (typically the
obj_dirpassed tomake()).patterns – Globs relative to base_dir (
**is recursive), e.g.["syn-rundir/reports/**", "*.log"]. Files matched by multiple patterns appear once.max_bytes_per_file – When set, files over this size are recorded in
skippedinstead of shipped through the object store — protects against a glob accidentally matching a netlist.None(and 0, the falsy edge) means no cap: everything matched is shipped.
RISC-V build
Cross-compile a C/asm source into a RISC-V ELF.
- Environment this node needs:
riscv64-unknown-elf-* baremetal toolchain on PATH (target=verilator).
riscv64-unknown-linux-gnu-* Linux toolchain on PATH (target=linux).
The harness Makefile at /opt/riscv-harness/Makefile plus its include/ headers (rocc.h, mmio.h, marchid.h).
All three are provisioned by the chia-riscv-cross Docker image (dockerfiles/RiscvCrossDockerfile).
Where it sits in the pipeline:
Source bytes gets passed into RiscvBuildNode.build(target=”verilator” | “linux”), which calls make -f /opt/riscv-harness/Makefile …
RiscvBuildNode.build returns RiscvBuildArtifact (binary_content + target + success + std{out,err} + rc)
- class chia.chipyard.riscv_build_node.RiscvBuildNode(timeout_seconds: int = 300, logging_level: int = 10)[source]
Bases:
objectCross-compiles a C/asm source into a RISC-V ELF via the harness Makefile.
Each
build()writes its source into an isolated per-call task dir and shells out to the baked-in harness Makefile. Runs inside thechia-riscv-crossimage on workers tagged with theriscv_buildresource (see module docstring for the toolchain/Makefile it depends on).- Parameters:
timeout_seconds – Wall-clock limit applied to each
makeinvocation inbuild(). On expiry the build returnsreturncode=-1(never raises); defaults to 300s.logging_level – Python logging level for this node’s logger.
- build(source_content: bytes, program_name: str, work_dir: str, target: Literal['verilator', 'linux'] = 'verilator', extra_cflags: str = '', extra_ldflags: str = '', include_dump: bool = False, cleanup_task_dir: bool = True, lang: Literal['c', 'asm'] = 'c') RiscvBuildArtifact[source]
Cross-compile source_content into a RISC-V ELF.
- Parameters:
source_content – Raw bytes of the source file to compile.
program_name – Base name of the program. Names the source file (
<program_name>.c/.S), thePROGRAM=Make variable, and the output binary.work_dir – Base directory; a uuid-namespaced task subdir is created under it so concurrent builds on one worker don’t collide.
target –
"verilator"for a baremetal ELF (output<program_name>.riscv) or"linux"for a userspace ELF (output<program_name>). Selects the toolchain prefix.extra_cflags – Forwarded verbatim as
EXTRA_CFLAGS=to the harness Makefile (e.g."-march=rv64gc_zba_zbb"for extension ISAs).extra_ldflags – Forwarded verbatim as
EXTRA_LDFLAGS=.include_dump – If True, also run the Makefile’s
dumptarget and read theobjdump -Doutput back into the artifact’sdump.cleanup_task_dir – If True (default), remove the task dir after the build (and after reading back the binary/dump).
lang –
"c"writes<program_name>.c;"asm"writes<program_name>.S(preprocessed assembly). Both compile via the same Makefile rules.
- Returns:
Carries the compiled ELF bytes, output
binary_name,target, and (ifinclude_dump) the disassembly. On compile failure/timeout,success=Falsewith emptybinary_contentand the captured stdout/stderr/returncode.- Return type:
- Raises:
ValueError – If
targetorlangis not a recognized value.
RISC-V objdump
Disassemble a RISC-V ELF with objdump.
Environment this node needs:
riscv64-unknown-elf-objdumpon PATH (target=verilator).riscv64-unknown-linux-gnu-objdumpon PATH (target=linux).
Both are provisioned by the chia-riscv-cross Docker image (dockerfiles/RiscvCrossDockerfile).
Where it sits in the pipeline:
Binary bytes (from RiscvBuildNode, S3, or anywhere else) get passed into RiscvObjdumpNode.dump(target="verilator" | "linux"), which
shells out to `<TOOL_PREFIX>objdump <flags> <binary>`.
RiscvObjdumpNode.dump returns RiscvObjdumpArtifact (dump + target + success + std{out,err} + rc)
This is the standalone counterpart to RiscvBuildNode.build(include_dump=True): use the build flag when you’re compiling and want both outputs in one step, use this node when you already have an ELF and just want its disassembly.
- class chia.chipyard.riscv_objdump_node.RiscvObjdumpNode(timeout_seconds: int = 120, logging_level: int = 10)[source]
Bases:
objectDisassembles a RISC-V ELF with
objdump.`- Parameters:
timeout_seconds – Wall-clock limit applied to each
objdumpinvocation indump(). On expiry the dump returnsreturncode=-1(never raises); defaults to 120s.logging_level – Python logging level for this node’s logger.
- dump(binary_content: bytes, binary_name: str, work_dir: str, target: Literal['verilator', 'linux'] = 'verilator', objdump_flags: str = '-D', cleanup_task_dir: bool = True) RiscvObjdumpArtifact[source]
Disassemble binary_content with <TOOL_PREFIX>objdump.
- Parameters:
binary_content – Raw bytes of the RISC-V ELF to disassemble.
binary_name – Filename to give the ELF on disk (echoed into the returned artifact for traceability).
work_dir – Base directory; a uuid-namespaced task subdir is created under it so concurrent runs on one worker don’t collide.
target –
"verilator"selects theriscv64-unknown-elf-prefix (baremetal ELF);"linux"selectsriscv64-unknown-linux-gnu-(userspace ELF).objdump_flags – Flags forwarded verbatim to
objdump(split on whitespace); defaults to"-D"(disassemble all sections).cleanup_task_dir – If True (default), remove the task dir after the disassembly is captured.
- Returns:
Carries the disassembly (
dump), the echoedbinary_nameandtarget, and stdout/stderr/returncode.success=False(with emptydump) on failure or timeout.- Return type:
- Raises:
ValueError – If
targetis not a recognized value.
RISC-V DV generation
Generate random RISC-V test ELFs with riscv-dv (run.py –steps gen,gcc_compile: generate assembly, then link with the riscv64-unknown-elf toolchain in chia-riscv-dv).
Backends (the simulator arg): pyflow is free (no license) but covers only the base ISA plus partial/draft bitmanip; xlm/vcs/questa run the full SV flow (bitmanip/vector/crypto) and each need their CAD tool plus a FlexLM seat, sourced from cad_setup.
- class chia.chipyard.riscv_dv_gen_node.GenSpec(test: str, iterations: int = 1, instr_cnt: int | None = None, plusargs: dict[str, object]=<factory>, gen_timeout: int | None = None, seed: int | None = None, extra_args: tuple[str, ...]=())[source]
Bases:
objectOne riscv-dv test to generate: a testlist.yaml entry name plus optional per-run overrides. instr_cnt and plusargs are appended as –sim_opts, overriding the entry’s gen_opts without editing the yaml; extra_args is raw run.py CLI for anything not modelled here. A None plusarg value is a bare flag (+foo).
- test
Name of the
testlist.yamlentry to generate (the instruction mix, e.g."riscv_arithmetic_basic_test","riscv_b_ext_test"). Passed as--test.- Type:
str
- iterations
Number of test programs to generate (
--iterations).- Type:
int
- instr_cnt
Optional override for the instruction count per program; emitted via
--sim_opts +instr_cnt=<n>when set.- Type:
int | None
- plusargs
Extra generator plusargs emitted via
--sim_opts.{k: v}becomes+k=v; aNonevalue becomes a bare+k.- Type:
dict[str, object]
- gen_timeout
Optional per-generation timeout forwarded as
--gen_timeouttorun.py.- Type:
int | None
- seed
Optional fixed RNG seed (
--seed) for reproducible generation;Nonelets riscv-dv pick.- Type:
int | None
- extra_args
Raw additional
run.pyCLI tokens, appended verbatim, for flags not modelled here.- Type:
tuple[str, …]
- class chia.chipyard.riscv_dv_gen_node.RiscvDvGenNode(riscv_dv_dir: str = '/home/ray/riscv-dv', simulator: str = 'pyflow', target: str | None = None, custom_target: str | None = None, testlist: str | None = None, isa: str | None = None, mabi: str | None = None, user_extension_dir: str | None = None, custom_instr_dir: str | None = None, cad_setup: str = '/ecad/tools/vlsi.bashrc', timeout_seconds: int = 900, logging_level: int = 10)[source]
Bases:
objectGenerates random RISC-V test ELFs with riscv-dv as cosim stimulus.
Thin pass-through to riscv-dv’s run.py: each flag is forwarded only when set. Use GenSpec.extra_args for any flag we don’t surface.
Configs are presented as filepaths that are expected to exist in the node’s environment:
custom_target: your core config (dir holding riscv_core_setting.sv)
testlist: your test catalog (a testlist.yaml)
user_extension_dir: your custom generator .sv (a riscv-dv user_extension/ layout); referenced by class name from the testlist and compiled in during gen
custom_instr_dir: your custom-instruction .sv (an isa/custom/ layout: riscv_instr_name_t enum entries + instr classes), overlaid into the generator’s src/isa/custom/ so they generate. Defaults to <custom_target>/isa/custom/. (NOT a run.py flag — the enum is sealed before the include hooks, so it must land in src/; see _install_custom_instrs.)
The rest map 1:1 to run.py flags: simulator (pyflow=free, xlm/vcs/questa= CAD+FlexLM), target (a built-in core-config name), isa, mabi.
- Parameters:
riscv_dv_dir – Path to the riscv-dv checkout containing
run.py(defaults to the location inside thechia-riscv-dvimage).simulator – riscv-dv backend /
--simulator:"pyflow"(no license; base ISA + partial bitmanip) or"xlm"/"vcs"/"questa"(SV flow; full bitmanip/vector/crypto, needs the CAD tool + a FlexLM seat sourced fromcad_setup).target – Built-in core-config name (
--target);Noneto omit.custom_target – Path to a directory holding your
riscv_core_setting.sv(--custom_target). Shipped to the worker via the Ray working dir. Takes precedence overtarget.testlist – Path to a custom
testlist.yaml(--testlist); overrides the target dir’s default test catalog.isa – Target ISA string (
--isa, e.g."rv64gc");Noneomits.mabi – Target ABI string (
--mabi, e.g."lp64d");Noneomits.user_extension_dir – Path to a riscv-dv
user_extension/layout with your custom generator.sv(--user_extension_dir), referenced by class name from the testlist.custom_instr_dir – Path to an
isa/custom/layout (riscv_instr_name_tenum entries + instr classes) overlaid into the generator’ssrc/isa/custom/before compile so the instructions generate. Defaults to<custom_target>/isa/custom/. NOT a run.py flag — the enum is sealed before the include hooks, so it must land insrc/(see_install_custom_instrs()).cad_setup – Path to the bashrc sourced before SV-flow runs to put the CAD tool + FlexLM license on PATH (ignored for
pyflow).timeout_seconds – Wall-clock limit per
run.pyinvocation; on expiry the process group is killed (never raises).logging_level – Python logging level for this node’s logger.
- compile_generator(build_dir: str, test: str) str[source]
Compile the generator testbench once into build_dir (riscv-dv -co), so later generate(sim_only=True) runs skip the testbench recompile and just simulate against it. test is any entry in the active testlist. Returns build_dir, to pass to generate() as build_dir. Multiple generate(sim_only=True) runs can reuse one build concurrently.
- Parameters:
build_dir – Directory to compile the generator testbench into (
--outputwith-co); created if absent. This same path is later passed togenerate()asbuild_dir.test – Any entry in the active testlist.
run.pyneeds one to load the list, but the-cobuild itself is test-independent.
- Returns:
The
build_dirpath, ready to hand togenerate(sim_only=True).
- generate(spec: GenSpec, work_dir: str, cleanup_task_dir: bool = True, sim_only: bool = False, build_dir: str | None = None) list[tuple[str, bytes, str]][source]
Generate + compile spec and return [(name, elf_bytes, asm_text)] for every ELF produced. Never raises: on failure it returns the (possibly empty) list found.
sim_only=True skips the testbench compile (riscv-dv -so) and reuses the build from a prior compile_generator(), passed as build_dir. Multiple sim_only gens can share one build_dir concurrently without colliding.
- Parameters:
spec – The
GenSpecdescribing the test, iteration count, and any per-run overrides to generate.work_dir – Base directory; a uuid-namespaced task subdir is created under it per call for isolation.
cleanup_task_dir – If True (default), remove the task dir after collecting ELFs (unlinks any symlinks; the shared build is left intact).
sim_only – If True, skip the testbench compile (
-so) and reuse a prebuilt generator frombuild_dir. Requiresbuild_dir.build_dir – Path returned by
compile_generator(); symlinked read-only into the task dir whensim_only=True. Must be local to this worker.
- Returns:
A list of
(name, elf_bytes, asm_text)tuples — one per ELF riscv-dv produced (the sibling.Ssource, or""if absent). Never raises: on failure returns the (possibly empty) list found.- Raises:
ValueError – If
sim_only=Truebut nobuild_dirwas provided.
Torture
Run RISC-V Torture against a compiled Chipyard/BOOM RTL simulator and diff the Spike vs RTL architectural signatures.
- class chia.chipyard.torture_run_node.TortureRunNode(chipyard_path: str, sbt_override: str = 'java -Djava.security.manager=allow -Xmx2G -Xss8M -jar sbt-launch.jar', timeout_seconds: int = 1800, logging_level: int = 10)[source]
Bases:
objectRuns RISC-V Torture against a compiled Chipyard/BOOM RTL simulator.
Torture randomly generates RISC-V assembly tests, runs each on both Spike (the ISA reference model) and the RTL simulator under test (the DUT), and diffs their architectural signatures. This node drives the
makeflow in<chipyard_path>/tools/torture: it writes the simulator binary from aBuildArtifactto disk, passes it as the TortureR_SIM, invokes the appropriate target for the requestedTortureMode, and collects the generated test, disassembly, and Spike/RTL signatures for each run.Because Torture writes into a shared
tools/torture/outputdirectory, concurrent runs on the same checkout are serialized with a file lock.Configure a Torture runner against a Chipyard checkout.
- Parameters:
chipyard_path – Absolute path to the Chipyard checkout on the build node. Torture is driven out of
<chipyard_path>/tools/torture(with its sharedoutput/subdirectory). Path for the CHIA chipyard container is/home/ray/chipyardsbt_override – The
SBT=command handed tomake, overriding the Makefile’s default launcher.timeout_seconds – Wall-clock timeout for the
makesubprocess (default 30 min). ForTortureMode.OVERNIGHTthe effective timeout is raised to at leastovernight_minutes * 60 + 600so the make process outlives the overnight loop.logging_level – Logging level for this node’s logger.
- torture(artifact: BuildArtifact, mode: TortureMode = TortureMode.SINGLE, work_dir: str = '/tmp/chia-torture', torture_config_file: str | None = None, overnight_minutes: int = 30, overnight_max_failures: int = 1, replay_test_s: str | None = None) TortureResult[source]
Run Torture against a pre-built simulator and collect the results.
The simulator binary from
artifactis written to a per-run task directory underwork_dirand passed to Torture asR_SIM. The make target invoked depends onmode:TortureMode.SINGLE→make rgentest— generate one test, run it on the DUT and Spike, and diff signatures.TortureMode.OVERNIGHT→make rnight— loop generating and running tests untilovernight_max_failuresfailures accumulate orovernight_minuteselapse; failing tests are saved underfailedtests/.TortureMode.REPLAY→make rtest— run a caller-supplied assembly test (replay_test_s) instead of generating one.
If
artifact.successis False the run is skipped and an unsuccessfulTortureResultis returned immediately. Runs are serialized on a per-checkout file lock.- Parameters:
artifact – Compiled RTL simulator to test, from a
ChiselBuildNodebuild. Its ELF bytes become the TortureR_SIM(the DUT); Spike is the implicit reference model.mode – Which Torture flow to run — see
TortureMode.work_dir – Base directory under which a fresh per-run task directory (random 8-hex name) is created to hold the simulator binary and collected artifacts.
torture_config_file – Optional Torture generator config, passed as
-C <file>(Torture’s--config). Controls the generated instruction mix / sequences.Noneuses Torture’s default.overnight_minutes – OVERNIGHT only — how long the generate-and-test loop runs, passed as
-m <minutes>. Also extends the make subprocess timeout. Ignored in other modes.overnight_max_failures – OVERNIGHT only — stop after this many failing tests, passed as Torture’s
-t <count>threshold. Ignored in other modes.replay_test_s – REPLAY only — the assembly source to replay. Written to
replay.Sand passed asTEST=(Torture’s-a). Required for REPLAY; raisesValueErrorif missing.
- Returns:
A
TortureResultwith overallsuccess, the test/failure counts, per-test artifacts (TortureTestRun), and the raw makestdout/stderr/returncode.build_artifactis leftNonehere;torture_from_config()populates it.
Verilator run
- class chia.chipyard.verilator_run_node.VerilatorRunNode(logging_level: int = 10)[source]
Bases:
objectRuns one test ELF on a prebuilt chipyard Verilator simulator.
Construct a run node.
- Parameters:
logging_level – Python logging level for this node’s logger. The node is otherwise stateless at construction time; per-run state (task dir, binary path) is created in
_setupwhenrunis invoked.
- run(artifact: BuildArtifact, test_binary_content: bytes, test_binary_name: str, work_dir: str, plusargs: dict = {}, timeout_cycles: int | None = None, timeout_seconds: int | None = None, dramsim_ini_files: dict[str, bytes] = {}, capture_waveform: bool = False, verbose: bool = True, cleanup_task_dir: bool = True, numactl: bool = False, wave_windows: list[WaveWindow] = (), dump_all_waveform: bool = False, upload_to_s3: bool = False, s3_path: str = '', aws_access_key_id: str = '', aws_secret_access_key: str = '', aws_session_token: str = '', aws_region: str = '') RunResult[source]
Run one test ELF on the prebuilt Chipyard Verilator simulator.
Writes the simulator and test binaries into an isolated per-task directory, assembles the simulator’s
+plusargcommand line, executes it (piping the committed-instruction stderr throughspike-dasm), and returns the captured output. By default, runs on nodes tagged with theverilator_runresource.- Parameters:
artifact – The
BuildArtifactproduced byChiselBuildNode.build(). Supplies the simulator ELF bytes and its name; the binary is materialized into the task dir and marked executable.test_binary_content – Raw bytes of the RISC-V test ELF to run (the program the simulator loads over the front-end server / HTIF).
test_binary_name – Filename to give that ELF on disk; its stem also names the
.logand.outoutput files.work_dir – Base working directory. A unique 8-hex-char subdirectory is created under it per run so concurrent runs sharing the same container/work_dir don’t collide.
plusargs – Extra simulator
+plusargsas a dict. Each entry is emitted as+keywhen the value is falsy, else+key=value(e.g.{"+loadmem": path}or{"+verbose": ""}).timeout_cycles – Simulated-cycle budget; passed as
+max-cycles=<n>. The simulator self-terminates when reached.Noneomits the plusarg (no cycle limit).timeout_seconds – Wall-clock limit. On expiry the simulator process is killed and whatever was captured so far is returned.
dramsim_ini_files – DRAMSim2 model config as
{filename: bytes}. When non-empty they’re written to adramsim_inidir and the sim is launched with+dramsim +dramsim_ini_dir=<dir>to use the cycle-accurate DRAM model instead of the simple memory.capture_waveform – If True, emit a VCD via
+vcdfile=<task>/<stem>.vcd. Requires the simulator to have been built withtarget=VERILATOR_DEBUG. Auto-enabled ifwave_windowsordump_all_waveformis set.verbose – If True, append
+verbose(commit-log / verbose sim output).cleanup_task_dir – If True (default), delete the per-task directory after the run (and after any S3 upload) to bound disk usage.
numactl – If True, prefix the simulator argv with the platform’s
numactlbinding (fromget_numa_prefix()) to pin it to a NUMA node.wave_windows – chia_artifact-specific temporal waveform filter — a list of
WaveWindowPC-triggered dump windows. Each is emitted as+wf_pc_<i>=<hex> +wf_n_<i> +wf_cyc_<i>: dump forcyctestbench cycles starting at then-th retired commit ofpc. At most_MAX_WAVE_WINDOWS(64); each is validated forpc>0, n>=1, cyc>0.dump_all_waveform – If True, append
+wf_dump_all=1to bypass the window filter and dump the entire run (combine withwf_scopesat build time to still bound it spatially).upload_to_s3 – If True (and
s3_pathis set), upload the produced.vcd(if any),.outand.logto S3 before the task dir is cleaned up. A missing VCD is a soft skip.s3_path – Destination
s3://bucket/prefixfor uploads. Files land under<s3_path>/<basename>. Required whenupload_to_s3=True.aws_access_key_id – Explicit AWS access key for the upload. If set,
aws_secret_access_keymust also be set; otherwise boto3’s default credential chain (env vars / profile / instance role) is used.aws_secret_access_key – Explicit AWS secret key (see above).
aws_session_token – Optional session token for temporary (STS) credentials; only used when explicit keys are given.
aws_region – Optional AWS region name for the S3 client.
- Returns:
Captured
log(simulator stdout) andout(spike-dasm disassembly of stderr), the process returncode/success, any S3 URIs for uploaded artifacts, and an echo of the configuredwave_windows.- Return type:
- run_metasim(artifact: BuildArtifact, test_binary_content: bytes, test_binary_name: str, work_dir: str, fesvr_step_size: int = 128, plusargs: dict = {}, timeout_cycles: int | None = None, timeout_seconds: int | None = None, verbose: bool = True, cleanup_task_dir: bool = True, numactl: bool = False) RunResult[source]
Run a FireSim metasim (VFireSim) binary.
Unlike
run, this method:omits
+loadmem,+dramsim, and+dramsim_ini_dir(metasim uses FASED memory modeling)omits waveform capture (metasim uses
+waveformfilewith a-debugbuild variant, not+vcdfile)always passes
+fesvr-step-size(required for metasim)
Spike cosim
Spike<->Verilator lockstep co-simulation of one ELF via chipyard’s Cospike.
Spike is compiled into the simulator (WithCospike + WithTraceIO) and checks every committed instruction in-process; the run aborts at the first architectural divergence. The embedded spike takes its ISA from the DUT’s isaDTS, so this node needs no isa argument. Cosim requires a zero-initialized DUT (a RANDOM=0 build predefine) so unspecified reset state matches spike’s zeros; Cospike forwards the legitimately non-deterministic reads (counters, IDs, LR/SC, device loads).
On a mismatch the run is repeated with +verbose to capture the interleaved
DUT/spike commit logs around the abort (the ctx-line debug window). Composes
VerilatorRunNode for the simulation, adding the cospike plusargs, divergence
parsing, and the verbose re-run.