SPICE netlist export
Reticle recognises transistors from layout geometry (device
recognition: DeviceKind, terminal nets, and channel
W/L in DBU) and writes that as a SPICE subcircuit, for exchange with external
simulators and schematic-capture tools. The writer lives in reticle-extract
(spice.rs), a sibling of device recognition, not a change to it: it consumes
an already-built DeviceNetlist and adds no new extraction logic.
The exchange subset
The interchange subset is fixed by the committed contract fixture
crates/reticle-extract/tests/fixtures/contracts/spice_exchange_inverter.spice
(with its structural companion .json):
*full-line comments and blank lines, skipped on read, optional on write.- One
.subckt NAME <ports...>/.endswrapper. - One
Xdevice-instance card per device:Xn <drain> <gate> <source> <bulk> <model> w=<W> l=<L>,nthe device’s index inDeviceNetlist::devices. - Decimal-micron
w=/l=params, and.end.
The netlist lane’s writer (to_spice_subckt, format_spice, write_spice)
emits this subset; the xschem lane reads it back. Both lanes build against
the committed fixture before the other lane’s half exists (see ADR
0108), so neither blocks on the
other.
What is written, and from where
- Ports are the nets any device terminal references, kept in the extracted netlist’s own stable (lowest-member-index) order – the writer invents no ordering of its own.
- W/L convert from the
DeviceDBU fields to decimal microns by exact integer long division, never a float:650DBU at1000DBU/micron is the literal string"0.65", with no0.6500000001-style formatting drift. - The model name comes from
SpiceTech, a small table the caller supplies, keyed only onDeviceKind(NMOS/PMOS). Device recognition reads no threshold-voltage flavour, body-bias variant, or other model-selection detail from geometry, so the table cannot honestly derive one either; see ADR 0108 for why this is caller-supplied rather than baked into a single “sky130” default.
What is honestly absent
- Area/perimeter parameters (
ad/pd/as/ps):Devicecarries no diffusion-area data, so these are never invented. - A guessed node name: a terminal
extract_devicescould not bind to a net (Option::None) is written as the documented placeholder nodeNC. - A general SPICE importer:
parse_spicereads back only the subsetformat_spicewrites, enough to round-trip the writer’s own output and validate the committed contract fixture. It never panics on malformed input – every failure is aSpiceParseError– but it is not a hardened importer for arbitrary, untrusted decks, and has not been through a fuzz campaign the way Reticle’s binary-format readers (GDS, OASIS) have.
Cross-test
crates/reticle-extract/tests/spice_writer.rs extracts a hand-built SKY130
inverter (separate VPB/VNB body-tie straps, so the bulk terminals bind to
their own nets rather than shorting into the power rails the way the smaller
device-recognition fixture does), writes it, and checks the result three ways:
the structured output matches the contract JSON’s kind/terminals/model/W/L;
the emitted text parses back to the same structure; and the committed
.spice fixture itself parses and agrees with the writer’s structural output.