VLSI
API reference for chia.vlsi. These pages are generated from the docstrings in the source, so they stay in sync with the code.
Hammer
chia.vlsi.hammer — Hammer-vlsi nodes.
HammerNode.run() wraps one hammer-vlsi CLI call. Hammer’s CLI is
uniform across actions (syn, par, drc, lvs, sim, power, and the -to- bridge
actions): configs in via repeated -p, an --obj_dir for build output,
an -o output config that feeds the next action, and the action name. One
node therefore covers the whole flow, with the action as a parameter.
obj_dir is PATH-BASED: it lives on the worker that ran the action, so chained
actions (syn -> syn-to-par -> par) and report fetches
(HammerNode.collect()) must land on the SAME worker. HammerNode
enforces that via a placement group (see chia.base.colocated
.ColocatedNode for the given / reserved / no-PG construction modes).
HammerNode.<fn>.chia_remote(...) (the class attribute) is the raw,
unpinned form for callers that handle placement themselves.
This module knows nothing about technologies, tools, or sites — all of that arrives via the project’s configs.
- class chia.vlsi.hammer.HammerResult(success: bool, returncode: int, action: str, obj_dir: str, stdout: str, stderr: str, output: dict = <factory>, listing: dict[str, int]=<factory>)[source]
Bases:
object
- class chia.vlsi.hammer.HammerCollectResult(obj_dir: str, files: dict[str, str], skipped: dict[str, int], listing: dict[str, int])[source]
Bases:
object
- class chia.vlsi.hammer.HammerMatchResult(obj_dir: str, matches: list[tuple[str, int]], skipped: dict[str, int])[source]
Bases:
object
- class chia.vlsi.hammer.HammerCollectFsResult(obj_dir: str, dest_dir: str, copied: dict[str, int], skipped: dict[str, int])[source]
Bases:
object
- class chia.vlsi.hammer.HammerNode(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:
ColocatedNodeHammer run / collect primitives sharing one placement.
The members are
@staticmethod @ChiaFunction(resources={"hammer": 1});__init__re-binds each into a per-instance pinned form sonode.<fn>.chia_remote(...)lands on this node’s bundle:with HammerNode() as node: # reserves a {"CPU": 1, "hammer": 1} PG syn = get(node.run.chia_remote( "syn", configs=[...], obj_dir="/scratch/build/run1")) rpts = get(node.collect.chia_remote( syn.obj_dir, ["syn-rundir/reports/**"])) par = get(node.run.chia_remote("syn-to-par", ...)) # same worker
collectrequires the default bundle’s hammer slot, so a collect dispatched while a run executes on this bundle waits for it in the default case — it cannot read half-written reports.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 run(action: str, configs: list[str] | None = None, config_contents: dict[str, str] | None = None, obj_dir: str = 'build', extra_args: list[str] | None = None, hammer_bin: str = 'hammer-vlsi', timeout_seconds: int = 86400) HammerResult[source]
Run one
hammer-vlsiaction on a worker.- Parameters:
action – Any action hammer-vlsi accepts: “syn”, “par”, “syn-to-par”, …
configs – Paths to config YAML/JSON files that exist on the worker (baked into the image or mounted), passed as
-pin order (later files override earlier ones).config_contents – filename -> YAML/JSON text, written into
obj_dir/configs/on the worker and appended as-pafterconfigs. This is how a flow ships configs (or a previous action’soutput) by value to a remote worker.obj_dir – Hammer build directory on the worker.
extra_args – Extra CLI args, inserted before the action.
hammer_bin – The hammer executable, or a custom CLIDriver script.
timeout_seconds – Wall-clock limit for the subprocess.
- static collect(obj_dir: str, patterns: list[str], max_bytes_per_file: int | None = None) HammerCollectResult[source]
Fetch text files from a previous action’s obj_dir on this worker.
Dispatch via the pinned instance member (
node.collect.chia_remote) so it lands on the worker that owns obj_dir — an unpinned call may not.- Parameters:
obj_dir – The build directory a previous action ran in.
patterns – Globs relative to obj_dir (
**is recursive), e.g.["syn-rundir/reports/**", "syn-rundir/*.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.
- static list_matches(obj_dir: str, patterns: list[str], max_bytes_per_file: int | None = None) HammerMatchResult[source]
Resolve patterns against obj_dir on the worker and return the manifest of matching files (relpath + size) without reading contents.
The planning half of
collect_fs(): it tells the caller what to stream and how big each file is. Same glob/dedup/cap rules ascollect().
- static read_chunk(obj_dir: str, rel: str, offset: int, length: int) bytes[source]
Read
lengthbytes atoffsetfromobj_dir/relon the worker. The transfer primitive behindcollect_fs(); returnsb""at or past EOF.relis confined to obj_dir.
- collect_fs(obj_dir: str, patterns: list[str], dest_dir: str, max_bytes_per_file: int | None = None, chunk_bytes: int = 16777216) HammerCollectFsResult[source]
Stream matching files from a previous action’s obj_dir onto the filesystem of THIS (the calling) process, a chunk at a time.
Unlike
collect(), which returns every file’s contents in one object-store payload, this writes each file todest_diron the caller’s local disk incrementally — peak memory is ~``chunk_bytes``, not the size of the whole collection. Use it to pull large report trees / gate-level netlists back from the worker to a machine that does NOT share a filesystem with it.This is a caller-side orchestrator, not a
@ChiaFunction: it runs wherever you call it and writes to that machine’s disk, pulling bytes from the obj_dir worker via the node’s pinnedlist_matches()/read_chunk()members. It therefore needs a placement group so both members hit the one worker that owns obj_dir — construct the node withrequire_colocated=Trueor passplacement_group=....Files keep their path relative to obj_dir: a match at
obj_dir/syn-rundir/reports/x.rptlands atdest_dir/syn-rundir/reports/x.rpt.- Parameters:
obj_dir – The build directory a previous action ran in (on the worker).
patterns – Globs relative to obj_dir (
**recursive); same matching/dedup/cap rules ascollect().dest_dir – Destination directory on the calling machine; created as needed.
max_bytes_per_file – When set, files over this size are recorded in
skippedand not streamed.None(and 0) means no cap.chunk_bytes – Bytes per worker read — the memory bound per file.
SRAM characterization (CACTI)
CACTI Runner
Methods to run CACTI 7, and return characterization results.
- class chia.vlsi.sram_cacti.cacti_runner.CACTIResult(access_time_ns: float, cycle_time_ns: float, read_energy_nj: float, leakage_power_mw: float, height_mm: float, width_mm: float, area_um2: float, full_out: str)[source]
Bases:
object
- chia.vlsi.sram_cacti.cacti_runner.run_cacti(spec: SRAMSpec, technology_um: float = 0.13, cacti_path: str = 'cacti') CACTIResult | None[source]
Run CACTI for a single SRAM spec and return parsed results.
Returns None if CACTI fails.
- chia.vlsi.sram_cacti.cacti_runner.analytical_area_estimate(spec: SRAMSpec, cell_area_per_bit_um2: float = 1.0) CACTIResult[source]
Fallback area estimate when CACTI fails.
Uses a simple model: area = depth * width * cell_area_per_bit. Timing is estimated from simple RC scaling.
CACTI Macrocompiler
CACTI-specific adapter over the generic Chipyard MacroCompiler glue.
The generic MacroCompiler support — MDF library generation and the
tapeout.jar remap step — lives in chia.chipyard.macrocompiler. This
module just wraps it with the cacti_ cell-name prefix used by the CACTI
characterization flow.
- chia.vlsi.sram_cacti.cacti_macrocompiler.generate_cacti_macrocompiler_lib(sram_specs: list[SRAMSpec], cell_prefix: str = 'cacti_') str[source]
Generate the MacroCompiler MDF library for CACTI-characterized SRAMs.
Thin wrapper over
generate_macrocompiler_lib()that defaults the cell-name prefix tocacti_.
SRAM Characterize
Top-level orchestration: characterize SRAMs with CACTI and generate Liberty files.
Parses .top.mems.conf from generated_src, runs CACTI for large SRAMs, generates Liberty files, and optionally runs MacroCompiler to remap synflop _ext modules to CACTI-characterized library macros.
- class chia.vlsi.sram_cacti.sram_characterize.CharacterizedSRAM(name: str, spec: SRAMSpec, result: CACTIResult, lib_contents: dict[str, str], lef_content: str)[source]
Bases:
objectA single CACTI-characterized SRAM and its generated collateral.
- class chia.vlsi.sram_cacti.sram_characterize.CactiCharacterization(generated_src_files: list[tuple[str, str]], srams: list[~chia.vlsi.sram_cacti.sram_characterize.CharacterizedSRAM] = <factory>)[source]
Bases:
objectResult of
characterize_top_mems_conf_with_cacti().The
sram_libs/sram_namesviews are derived fromsramsso the existing dict-based consumers keep working, whilesramsexposes the full per-SRAM CACTI result.
- chia.vlsi.sram_cacti.sram_characterize.characterize_top_mems_conf_with_cacti(generated_src_files: list[tuple[str, str]], cacti_path: str, synflop_threshold_bytes: int = 256, technology_um: float = 0.13, cell_prefix: str = 'cacti_', corners: Sequence[LibertyCorner] = (LibertyCorner(name='ff', temperature=-40, voltage=1.95, pvt_name='PVT_1P95V_-40C', lib_suffix='ff_n40C_1v95'), LibertyCorner(name='ss', temperature=100, voltage=1.6, pvt_name='PVT_1P6V_100C', lib_suffix='ss_100C_1v60'), LibertyCorner(name='tt', temperature=25, voltage=1.8, pvt_name='PVT_1P8V_25C', lib_suffix='tt_025C_1v80'))) CactiCharacterization[source]
Firtool specific characterize SRAMs with CACTI and generate Liberty files.
Finds .top.mems.conf in generated_src_files, runs CACTI for each large SRAM, generates .lib files, and replaces .top.mems.v to remove synflop definitions for SRAMs that become library cells.
Small SRAMs (< synflop_threshold_bytes) keep their synflop implementations and are synthesized as flip-flop arrays by Genus.
- Parameters:
generated_src_files – List of (filename, contents) from the build.
cacti_path – Path to the CACTI binary.
synflop_threshold_bytes – SRAMs smaller than this stay as synflops.
technology_um – Technology node in microns (default 0.130 for Sky130).
cell_prefix – Prefix on the Liberty/LEF cell name. Default
cacti_disambiguates from chipyard’s .top.mems.v synflop wrapper for the MacroCompiler remap step. Pass “” when the caller’s Verilog refers to the bare _ext module directly (e.g. firtool –repl-seq-mem), so Genus can link the extmodule reference to the Liberty cell without an intervening rewrite.corners – Liberty corners to characterize each SRAM at. Defaults to SKY130_CORNERS (ff/ss/tt). Each corner produces one entry in the per-SRAM lib_contents dict, keyed by its lib_suffix.
- Returns:
generated_src_files: the (unmodified) input files
srams: a CharacterizedSRAM per large SRAM (name, spec, CACTI result, per-corner Liberty contents, and LEF content)
It also exposes .sram_libs (legacy list-of-dicts) and .sram_names views.
- Return type:
A CactiCharacterization with
- chia.vlsi.sram_cacti.sram_characterize.characterize_srams_with_cacti(sram_specs: list[SRAMSpec], generated_src_files: list[tuple[str, str]], cacti_path: str, synflop_threshold_bytes: int = 256, technology_um: float = 0.13, cell_prefix: str = 'cacti_', corners: Sequence[LibertyCorner] = (LibertyCorner(name='ff', temperature=-40, voltage=1.95, pvt_name='PVT_1P95V_-40C', lib_suffix='ff_n40C_1v95'), LibertyCorner(name='ss', temperature=100, voltage=1.6, pvt_name='PVT_1P6V_100C', lib_suffix='ss_100C_1v60'), LibertyCorner(name='tt', temperature=25, voltage=1.8, pvt_name='PVT_1P8V_25C', lib_suffix='tt_025C_1v80'))) CactiCharacterization[source]
Characterize SRAM specs with CACTI and generate Liberty/LEF.
Splits sram_specs into tiny SRAMs (kept as synflops, below synflop_threshold_bytes) and large SRAMs (CACTI-characterized), runs CACTI for the large ones, and returns a CactiCharacterization. generated_src_files is passed through into the result unchanged.
See characterize_top_mems_conf_with_cacti for the variant that first parses the specs out of a .top.mems.conf in generated_src_files.
Liberty Gen
Generate minimal Liberty (.lib) files for SRAM macros from CACTI results.
Produces Liberty files with area, timing arcs, and pin definitions that match the Chisel-generated _ext module port names. Uses scalar delay model (no NLDM tables) — sufficient for synthesis area estimation and basic timing.
- class chia.vlsi.sram_cacti.liberty_gen.LibertyCorner(name: str, temperature: int, voltage: float, pvt_name: str, lib_suffix: str)[source]
Bases:
object
- chia.vlsi.sram_cacti.liberty_gen.generate_liberty(spec: SRAMSpec, result: CACTIResult, corner: LibertyCorner | None = None, cell_prefix: str = 'cacti_') str[source]
Generate a Liberty .lib file for an SRAM macro at a specific corner.
The cell name and pin names match the Chisel-generated _ext module so Genus can use this as a drop-in library cell.
If corner is None, defaults to typical (tt_025C_1v80).
cell_prefix defaults to
cacti_so the Liberty cell name doesn’t collide with the synflop wrapper named<spec.name>in chipyard’s .top.mems.v (MacroCompiler then rewrites synflop refs to point atcacti_<name>). Pass “” when the upstream Verilog references <spec.name> directly as an extmodule (e.g. firtool –repl-seq-mem) so the Liberty cell name lines up.
LEF Gen
Generate minimal LEF (.lef) files for SRAM macros from CACTI results.
Produces LEF files with macro dimensions, pin shapes, and obstruction layers matching the CACTI-characterized SRAM area. Pin names match the Liberty cell and Verilog blackbox stubs (cacti_<name>).
LEF is geometry-only (no timing) so ONE file is generated per SRAM, not per corner like Liberty.
Uses CLASS BLOCK BLACKBOX per LEF 5.7 spec – designed for blocks that contain a SIZE statement estimating total area with approximate pin locations.
- chia.vlsi.sram_cacti.lef_gen.generate_lef(spec: SRAMSpec, result: CACTIResult, pin_layer: str = 'met4', obs_layers: list[str] | None = None, cell_prefix: str = 'cacti_') str[source]
Generate a minimal LEF file for an SRAM macro.
- Parameters:
spec – SRAM specification (pin names, depth, width, ports).
result – CACTI characterization result (physical dimensions).
pin_layer – Metal layer name for pin geometry (default “met4” for Sky130).
obs_layers – Metal layers for obstruction block. Defaults to [“met1”, “met2”, “met3”] for Sky130.
cell_prefix – Prefix on the LEF MACRO name (must match Liberty cell name). See generate_liberty for the disambiguation rationale.
- Returns:
Complete LEF file content as a string.