Skip to content

Symbols, arenas, names and the gate-level netlist

This document specifies the netlist data structures of rusteda-core (crates/core/rusteda-core, modules symbol, arena, names, and netlist). See README.md for the crate overview.

Symbol interning (symbol)

CORE-REQ-0100 Every database owns its SymbolInterner; there is no global symbol table. intern(s) assigns dense SymbolId values (0, 1, 2, ...) in insertion order and returns the existing id when s is already interned. get(s) looks up an interned string without adding it. resolve(id) and try_resolve(id) return the string of a symbol made by the interner (try_resolve returns None for an out-of-range id).

Generational arenas (arena)

CORE-REQ-0101 An Arena<T> addresses entries by typed Id<T> values holding a 32-bit slot index and a 32-bit generation. Lookups (get, get_mut, remove) check both the slot index and its generation; removing an entry increments the slot's generation so that any previously issued id for that slot is stale and reported (None or StaleId) rather than reaching a later entry.

CORE-REQ-0102 Freed slots are reused last-freed-first (LIFO) with their incremented generation, so the sequence of assigned ids is a deterministic function of the insert/remove sequence.

CORE-REQ-0103 A slot whose generation reaches u32::MAX is retired when its entry is removed and is never handed out again, so generations never wrap.

Object names (names)

CORE-REQ-0110 Every netlist name (module, cell, cell pin, port, net, or instance) is non-empty and consists of printable ASCII characters (byte values 33 ! to 126 ~). check_verbatim enforces this rule for module, cell, and cell pin names.

CORE-REQ-0111 Port, net, and instance names are hierarchical (check_hierarchical): in addition to CORE-REQ-0110, a hierarchical name is one or more non-empty segments separated by unescaped /, where inside a segment \ escapes the next character, which must be / or \.

CORE-REQ-0112 escape_segment escapes \ as \\ and / as \/ in a raw segment text; join escapes each segment and joins them with /; unescape converts \/ to / and \\ to \ across the whole name; segments splits a hierarchical name at unescaped / and unescapes each segment.

CORE-REQ-0113 is_simple_identifier(s) is true when s matches [A-Za-z_][A-Za-z0-9_$]*.

Editable gate-level netlist (netlist::GateNetlist)

CORE-REQ-0120 GateNetlist represents one flat module: cell types with their pins in library order (PinDir: Input, Output, Inout, Other), module ports (PortDir: Input, Output, Inout), scalar and indexed nets (plus anonymous nets), cell instances with their pins, and continuous assignments (lhs = rhs, where rhs is a net or constant 0/1).

CORE-REQ-0121 Every operation preserves the netlist invariants: all names satisfy their kind's rules; cell, port, and instance names are unique; named nets have unique (name, index) pairs and do not mix scalar and indexed nets under the same name; nets named after a port are exactly its bits; each instance has one pin per cell pin in cell pin order and lists its connected pins once in connection order; a net's pin list equals the set of instance pins connected to that net.

CORE-REQ-0122 Every fallible operation validates all ids, names, and preconditions before mutating state: on error it returns NetlistError and leaves the netlist and its SymbolInterner unchanged.

CORE-REQ-0123 Every operation that accepts a name checks it against CORE-REQ-0110 (for module, cell, and cell pin names) or CORE-REQ-0111 (for port, net, and instance names) and reports NetlistError::InvalidName on violation.

CORE-REQ-0124 add_instance creates an instance with unconnected pins in cell pin order; connect, disconnect, and move_pin manage pin connections while preserving connection order on the instance when a connected pin is moved to another net or constant; add_assign and remove_assign manage continuous assignments in order.

CORE-REQ-0125 remove_instance disconnects and removes an instance and its pins, leaving their ids stale; remove_net removes a net only when no instance pin, port bit, or assignment references it, freeing its name and leaving its NetId stale.

CORE-REQ-0126 swap_cell replaces an instance's cell type with another cell type whose pins have the same names and directions in any order, remapping every pin of the instance to the matching pin of the new cell type.

CORE-REQ-0127 insert_buffer inserts a single-input, single-output buffer instance on a net and moves the selected sink pins and assignments to the new net; remove_buffer is its inverse, reconnecting all sinks of the buffer's output net back to its input net and removing the buffer instance and output net.

CORE-REQ-0128 A bus port range (msb, lsb) may run in either direction (msb >= lsb or msb < lsb), creates bit nets in declaration order from msb to lsb without signed-integer overflow, and has at most MAX_RANGE_WIDTH (2^24) bits.

Frozen netlist (netlist::FrozenNetlist)

CORE-REQ-0130 FrozenNetlist holds the 18 dense tables of the NETLIST v1 representation in host byte order (str_bytes, str_offs, module, cells, cell_pin_start, cell_pin_name, cell_pin_dir, ports, port_bit_start, port_bit_net, nets, instances, inst_pin_start, pin_cellpin, pin_net, assigns, net_pin_start, net_pins) as Cow<'a, [T]> slices.

CORE-REQ-0131 Record layouts (PortRec, NetRec, InstRec, AssignRec) are bytemuck::Pod and Zeroable. A scalar port has is_bus == 0 and msb == lsb == 0; a bus port has is_bus == 1 and its declared msb and lsb.

CORE-REQ-0132 Special sentinel values in the frozen tables: CONST0 = 0xFFFF_FFFE and CONST1 = 0xFFFF_FFFF in pin_net and AssignRec::rhs; ANONYMOUS = u32::MAX for an anonymous net's NetRec::name; SCALAR = i32::MIN for a scalar net's NetRec::index.

CORE-REQ-0133 GateNetlist::freeze numbers live cells, ports, nets, and instances densely in arena slot order, stores each instance's connected pins in connection order (with distinct pin_cellpin values per instance), and lists net_pins in strictly increasing global connected-pin order for each net.

CORE-REQ-0134 GateNetlist::freeze compacts the string table into canonical first-use order: module name, each cell name followed by its pin names, port names, net names, and instance names, with no duplicate or unreferenced strings.

CORE-REQ-0135 FrozenNetlist::validate checks all 18 sections, header counts, CSR offset arrays, string UTF-8 and name rules (CORE-REQ-0110 and CORE-REQ-0111 according to every role a string plays), uniqueness, port bit naming, pin directions, connection uniqueness, net_pins CSR consistency, and canonical string ordering without panicking on any input.

CORE-REQ-0136 FrozenNetlist::thaw validates the tables and reconstructs a GateNetlist in row order in time proportional to the table sizes, such that freeze(thaw(f)) == f for every valid FrozenNetlist.

CORE-REQ-0137 FrozenNetlist::validate bounds the total number of pins across all instances (connected or unconnected) by MAX_TOTAL_PINS (2^28) before thaw allocates instance pins.

CORE-REQ-0138 FrozenNetlist provides direct query methods (string, module/cell/port/net/ instance/pin/assign accessors) over validated tables without thawing; string never panics even on unvalidated tables or ANONYMOUS.