RustSys user manual¶
RustSys turns synthesizable SystemVerilog RTL into a flat gate-level netlist of standard cells
from one or more Liberty libraries. The synthesis checker (rustsys check synth) proves that a
netlist implements its RTL.
Synthesize¶
rustsys synth --top counter --lib cells.lib --out counter_mapped.v --report counter.json counter.sv
| Option | Meaning |
|---|---|
--top NAME |
top module; optional when exactly one module is not instantiated by another |
-D NAME[=VALUE] |
define a preprocessor macro (SYNTHESIS is predefined) |
-I DIR |
include directory |
-P NAME=EXPR |
override a top-level parameter (-P W=16, -P "Seed=16'hACE1") |
--lib FILE |
Liberty library; repeat for several |
--dont-use GLOB |
never use matching cells (--dont-use '*_x8') |
--effort low\|medium\|high |
optimization and mapping effort (default medium); high adds SAT-based node merging, zero-gain rewriting and a larger cut search, and runs several times longer |
--goal delay\|area |
mapping objective |
--delay-relax R |
allowed delay increase during area recovery (default 0.1) |
--backend cpu\|gpu\|cuda |
where the mapper's cut passes run (default cpu); the netlist is the same for every backend |
--out FILE |
output netlist |
--report FILE |
JSON report: cell counts, area, depth, estimated delay, runtime |
Exit status: 0 on success, 1 when the input is rejected (diagnostics on standard error), 2 on an internal failure.
The global option --threads N, placed before the command (rustsys --threads 8 synth ...), sets
the number of worker threads of the parallel phases; the default uses one per available CPU. The
netlist does not depend on it.
GPU mapping¶
With --backend gpu or cuda, the delay and area-flow passes of the mapper
run on a GPU; the exact area-recovery passes stay on the CPU. gpu takes the first runtime of the
build that passes a device self-test; cuda runs kernels written in CUDA C on NVIDIA GPUs. There is
no Metal runtime for Apple GPUs yet (planned for Phase 4). The CUDA runtime needs
a CUDA toolkit (CUDA_PATH set to its root, its libraries including NVRTC visible to the dynamic
loader). The device is prepared while the design is read and optimized. The report's map_backend
names the runtime that ran and map_phase_s the time of each mapping step. A missing or failing
runtime is an error (S0530), never a silent fallback.
Check¶
rustsys check synth --top counter --lib cells.lib --netlist counter_mapped.v counter.sv
The checker accepts the same front-end options as rustsys synth.
| Option | Meaning |
|---|---|
--netlist FILE |
netlist to check; ports may be declared in the module header or in the body |
--seed N |
seed of the random simulation (reported) |
--cycles N |
also simulate both designs for N clock cycles from a common random state (single clock domain, no latches; otherwise skipped with a reason in the report) |
--budget N |
SAT conflict budget of each proof obligation (default 2000000); a proof that reaches it leaves the check undecided |
--model-budget N |
SAT conflict budget of each proof that the checker's own RTL model needs (default 200000), for example whether a combinational bit is written on every path |
--sweep-max-candidates N |
optional equivalence-sweeping candidates (default 32768; 0 uses structural hashing only); final proofs are still required |
--verbose |
phase times on standard error |
--report FILE |
JSON report with the verdict, mismatches and statistics |
Its verdict is one of:
| Verdict | Exit status | Meaning |
|---|---|---|
equivalent |
0 | every output and state obligation is proved |
initial-state-refinement |
0 | proved for the reported choices of unspecified initial state (--uninitialized-dont-care) |
not-equivalent |
3 | a difference, with counterexamples in the JSON report |
undecided |
5 | no difference found, but a proof or search stopped at its budget; a warning[C0005] names it, and --budget or --model-budget raises the conflict budgets |
error |
1 | the input is erroneous or outside what the checker models (2 when the checker itself failed: internal_error in the report) |
A counterexample decides even when another proof ran out of its budget, and a port difference
even when the search for state correspondences stopped at its limit: the verdict is
not-equivalent (exit status 3) and a warning[C0005] still names the budget. A netlist that
the checker rejects is error (exit status 1) even when a proof of its RTL model ran out of its
budget.
Netlists with constructs the checker does not model are rejected, not checked in part: high
impedance and drive strengths, that is cells with three-state outputs or a driver_type
(open-drain, open-source, pull-up, pull-down, bus-hold), highz0/highz1 drive strengths and
primitives such as bufif1 or pullup (C0101); dual-edge or master-slave flip-flops and latch
pairs (clocked_on_also, enable_also, C0102); x or z literals, on power and ground pins
too (C0103); cells described by a state table, with bus or bundle pins, several sequential
groups or banked ones, with x_function, internal nodes or retention, with sequential group
attributes the checker does not read, or clock-gating cells without their enable latch; cell
functions that read internal pins; connections to bidirectional or internal pins (C0104); and
nets that resolve several drivers, pull or store charge (wand, wor, tri0, tri1, trireg
and the like), logic ports declared as supply nets and driven supply nets (C0105). An undriven
supply0 or supply1 net is a constant. A cell that two libraries define differently, or that
its library describes with errors, is rejected (C0003). The checker reads the Liberty
attributes that the library reader does not keep from the library text, so none is skipped.
Power and ground connections are not evaluated: every cell is taken to be powered.
BLIF, AIGER and gate-level netlists¶
Besides SystemVerilog, rustsys synth and rustsys check synth take logic networks in BLIF
(.blif), and-inverter graphs in AIGER (.aag, .aig), and structural netlists of the cells of
another library (docs/specs/synth/inputs.md). The format of the positional sources is chosen by
their extension; one run reads one format, and one AIGER file.
rustsys synth --lib cells.lib --out adder_mapped.v adder.aig
rustsys check synth --lib cells.lib --netlist adder_mapped.v adder.aig
rustsys synth --lib cells.lib --gate-lib mapped.lib --out top.v design.blif
rustsys synth --lib cells.lib --gate-netlist golden.v --gate-lib other.lib --out resynth.v
rustsys check synth --lib cells.lib --netlist resynth.v --gate-netlist golden.v --gate-lib other.lib
| Option | Meaning |
|---|---|
--top NAME |
BLIF: the top model (default the first model of the first file); AIGER: the module name (default the file name without extension); gate-level netlist: must name its module |
--gate-netlist FILE |
a structural netlist of --gate-lib cells as the source (synth) or the reference (check synth); its logic is taken from the Liberty cell functions |
--gate-lib FILE |
Liberty library of the cells of --gate-netlist and of BLIF .gate and .mlatch (repeatable) |
--initial-values reset\|arbitrary |
BLIF and AIGER: reset (default) implements declared initial values (BLIF .latch init 0 or 1, AIGER reset 0 or 1) with an asynchronous control from a generated init input port; arbitrary leaves every state uninitialized and warns (S0913). check synth must be given the same mode |
Ports of BLIF and AIGER sources are scalar and named after their signals or symbols (AIGER
default names i<k>, o<k>, latches l<k>). BLIF latches without a clock and AIGER latches use
a generated input port clk; BLIF init 2 and 3 and uninitialized AIGER latches have no
initial value. -D, -I, -P, --no-predefined-macros and the case assumptions apply to
SystemVerilog only. BLIF constructs that would change the function if ignored (.search, state
transition tables, black boxes, latch type as, unknown commands) are errors; timing and
annotation constructs and .exdc are skipped with a warning. The checker reads these sources
with readers of its own; with --from-run it takes them, and the mode, from the synthesis run.
What the netlist looks like¶
- One module named as the top module, with the RTL ports in RTL order; multi-bit ports are
declared
[W-1:0], bitkbeing bitkof the RTL value. - Every register or latch bit is visible as a wire named after the RTL variable, for example
\u_fifo.mem_q[3][7](instance path, unpacked indices, bit). A one-bit output port that is a register is its own state wire. - Constants come from tie cells when the library has them.
Language support¶
Supported: modules, packages, parameters (value and type), typedef, enumerations, packed
structures and unions, packed and unpacked arrays, always_comb, always_ff, always_latch,
always @*/@(...), continuous assignments, gate primitives, generate loops, conditionals and
case, functions and tasks (including return, break, continue and output arguments),
for/while/do/repeat/foreach loops with constant bounds, case/casez/casex/
case inside with unique/priority, assignment patterns, casts, and the system functions
$clog2, $bits, $signed, $unsigned, $size, $left, $right, $high, $low,
$countones, $onehot, $onehot0. Assertions, initial blocks and simulation tasks are ignored.
Not supported in this version: interfaces and modports, arrays of instances, defparam,
tri-state logic (z is treated as 0), asynchronous load, registers with two asynchronous controls,
real numbers and dynamic data types.
Semantics that differ from a four-valued simulator: x and z are 0; uninitialized registers
have no initial value; variables declared inside procedural blocks are automatic.
Libraries¶
RustSys uses single-output combinational cells with up to six inputs, D flip-flops and latches
with optional asynchronous clear or preset, and tie cells. Scan, enable, multi-output,
three-state, clock-gating and dont_use cells are not used. Missing negative-edge or active-high
variants are built with inverters; a missing preset is built by storing the inverted value.
Runs and reports¶
--record, --run-dir, --label, --print and --from-run, run references such as @synth,
rustsys show for the sections of a report, and the exit statuses common to every command are
described in docs/user/cli/README.md.
Electrical constraints¶
For an ideal-clock target, add --timing-period NS. Times are in ns and --output-load is in
pF regardless of Liberty units. For example:
rustsys synth --lib cells.lib --goal area --timing-period 10 --area-limit 100000 \
--input-delay 2 --output-delay 2 --input-slew 0.1 --clock-slew 0.1 \
--output-load 0.01 --timing-margin 0.05 --buffer-fanout 16 --out mapped.v top.sv
The target enables sparse arithmetic carry structures, cover compaction, critical-load
buffering and cell sizing. --goal still controls the initial Boolean cover. An area limit
reserves room for sizing after buffering; it cannot guarantee that the initial design fits.
The JSON electrical object reports initial, compacted and final area, transformation counts,
estimated worst setup slack and explicit area/timing feasibility flags. An infeasible target
still produces a netlist and reports the unmet target in JSON, the displayed summary and
diagnostics S0532/S0533. The older estimated_delay is the Boolean cover estimate before
electrical refinement; logic_depth and the electrical statistics describe the final netlist.
The estimate uses Liberty NLDM, actual connected pin loads, uniform input/output budgets and
ideal clocks. Check the emitted netlist with a static timing analysis under the intended timing
constraints. Hold, clock phases, latch borrowing, exceptions and interconnect parasitics require
that separate analysis. Without --timing-period, the existing synthesis flow is retained. The
same constraints are available in the typed job's optional electrical object.