Skip to content

Netlist & Ingest

warptap.netlist

Thin object-model layer over Yosys's JSON netlist format (plan §4.2).

Yosys JSON shape: {"modules": {name: {"attributes", "ports", "cells", "memories", "netnames"}}}. Every module has its own flat namespace of small integer bit IDs, shared between ports, cells' connections, and netnames: two references to the same integer are the same net. A constant-driven bit is instead one of the strings "0"/"1"/"x"/"z" and never collides with a real integer ID.

This module never invents its own schema: it edits the exact dicts read_json/write_json already produce (backends/json/json.cc). Critically, wrapping a dict in :class:Module/:class:Netlist must never itself mutate that dict (no setdefault-style "fill in the missing keys" on load): only an explicit edit call (new_wire, add_cell, connect, set_keep) may change it. A wrap that silently normalized missing/empty keys on load would make the golden-file no-op round-trip test (plan §4.3) worthless, since "loaded and immediately dumped, unedited" needs to be byte-for-byte identical to the input.

Netlist

Wraps a full Yosys JSON document (one or more modules).

add_module

add_module(name: str, data: dict[str, Any]) -> Module

Import another module's raw JSON dict (typically captured via yosys_io.ingest() on a small hand-authored cell-template .v file, plan §4.2) into this netlist's modules dict, so a cell anywhere else in this netlist can reference it by type=name as an ordinary hierarchical instance. This is completely standard Yosys JSON/RTLIL: a cell whose type names a module present in the same modules dict just is a submodule instance, no bit-cloning of the template's internals required (confirmed empirically: a plain instance's JSON carries only its own top-level connection bits, referencing the submodule purely by name).

warptap.yosys_io

Subprocess wrapper around a Yosys executable (plan §4.1).

warptap never links against Yosys; it shells out to it, exactly like faultflow does for its own Yosys usage. The executable is configurable (yosys_command, or the WARPTAP_YOSYS_CMD environment variable) so tests can point at a pip-installed WASM build (yowasp-yosys) while a real install defaults to the yosys binary on PATH.

YosysError

Bases: WarptapError

Raised when a Yosys subprocess invocation exits nonzero.

ingest

ingest(verilog_files: list[Path | str], top: str, *, yosys_command: str | None = None, use_sv: bool = False) -> dict[str, Any]

Ingest pass (plan §4.1 step 1): lower Verilog source(s) for top into Yosys's JSON netlist representation.

Runs read_verilog; hierarchy -top <top>; proc; memory_collect; write_json. This step is mandatory, not optional, before any pure-Python JSON surgery: write_json rejects modules that still contain unlowered behavioral processes ($proc/always blocks).

use_sv, when set, adds -sv to read_verilog so SystemVerilog constructs (always_comb/always_ff, logic) parse. Off by default: every existing caller passes plain Verilog-2001 sources, and this keeps their output byte-for-byte unaffected (plan §7 Stage 9 §5.3).

write_verilog_from_json

write_verilog_from_json(netlist_json: dict[str, Any], *, yosys_command: str | None = None) -> str

Reload a Yosys JSON netlist dict and emit it back out as Verilog text.

Used by the golden-file round-trip test (plan §4.3) and, later, by the final synthesis step's output stage.