|
slang-netlist
0.9.0
|
Currently there are no pre-built binaries, so you will need to build from source.
Make sure you have the following prerequisites:
Then:
When using the Python bindings, it is recommended to use the pyslang shared object file that is produced as part of the build. Different versions of the upstream slang Python bindings may not work.
There are two command-line tools available: slang-netlist exposes the netlist-graph building and querying functions of the library; and slang-report provides extra AST-based reporting functions beyond the standard slang driver. Both tools accept SystemVerilog source files and the standard slang compilation options. Run either with --help for the full option list.
-h, --help — display available options.--version — print version information and exit.--no-colours — disable coloured output.-q, --quiet — suppress non-essential output.-d, --debug — enable debug logging (debug builds only).-j, --threads <N> — set the number of threads (0 = hardware concurrency, 1 = sequential).--stats — print phase timings and peak memory to stderr.--stats-json — print phase timings and peak memory in JSON format to stdout.--no-resolve-assign-bits — disable bit-aligned dependency resolution of concatenations, replications, conversions, and equal-width conditional operators in assignments and port connections; see Bit dependency resolution.--no-prop-cuts-across-ports — disable propagation of concat-induced cut points across module port boundaries. With this set, port nodes and module-internal assignments stay whole-word at port boundaries and paths through concatenated ports become bit-imprecise; see Bit dependency resolution.--black-box <pattern> — treat instances whose definition name or hierarchical path matches the wildcard pattern (* and ?) as black boxes. Black-boxed instances get port nodes and external wiring, but their body is not traversed, so paths terminate at the boundary. The option may be repeated to supply multiple patterns.--from <name> --to <name> — find a path between two named points. Names are hierarchical paths such as top.sub.signal. The path is printed with source locations when available.
A path query prints an alternating sequence of nodes and edges from the start signal to the end signal. Each step shows a source location and a description:
When the design has been compiled with the slang AST available, source locations are available and the output includes annotated source lines; otherwise after loading a serialised netlist, a plain file:line:col format is used.
--fan-out <name> — report the combinational fan-out cone from a named node (all nodes reachable via combinational edges, stopping at registers).
--fan-in <name> — report the combinational fan-in cone to a named node.
--find <pattern> — find named nodes matching a wildcard pattern (using * and ? characters to match any substring and any character respectively).
--find-regex <pattern> — find named nodes matching a regex pattern.
--report-registers — list all registers (State nodes) in the design. A State node is created for any variable that is assigned inside a clocked procedural block (always_ff or an always block with an edge-sensitive event list). Each entry shows the hierarchical path and source location.
--comb-loops — detect and report combinational loops. Reports cycles in the graph that consist entirely of combinational (non-clocked) edges. Each loop is printed as a path from a node back to itself. A reported loop means the tool found a structural cycle in the source-level dependency graph; see Bit dependency resolution for caveats on precision.
For AST-level reports (variables, ports, drivers, AST JSON dump) use slang-report — see slang-report below.
--netlist-dot <file> — write the netlist graph in DOT format. Use - for stdout. The output contains one graph node per NetlistNode and one graph edge per NetlistEdge. Node labels show the node kind and hierarchical path where applicable; edge labels show the driven signal and bit range. The DOT output can be rendered with Graphviz tools such as dot, neato, or fdp:
--save-netlist <file> — serialize the netlist graph to a JSON file for later reloading.
--load-netlist <file> — load a previously saved netlist (skips compilation). Analysis commands such as --from/ --to,--comb-loops, and --report-registers work on loaded netlists.
slang-report runs reports against the elaborated AST without building the netlist graph. It accepts the standard slang compilation options plus one of the following actions:
--ports — list all ports in the design (hierarchical path, direction, source location).--variables — list all variables in the design (hierarchical path, source location).--drivers — list all drivers for each value symbol. Runs slang's analysis pass; each entry shows the driving expression, bit range, driver kind (procedural or continuous), and source location.--ast-json <file> — dump the compiled AST in JSON format. Use - for stdout. Restrict the dump to specific scopes with --ast-json-scope <path> (may be repeated).The pyslang_netlist module (enabled with -DENABLE_PY_BINDINGS=ON) exposes the graph data structures and analysis routines to Python. It depends on pyslang for the compilation and analysis types.
The build pipeline has four steps: force lazy AST construction with VisitAll, freeze the compilation, run AnalysisManager, then unfreeze the compilation so NetlistGraph.build can keep elaborating.
NetlistGraph.build accepts these keyword arguments:
parallel (default True) — dispatch DFA work and R-value resolution across a thread pool.num_threads (default 0) — thread pool size; 0 uses hardware concurrency.resolve_assign_bits (default True) — bit-aligned dependency resolution; see Bit dependency resolution.prop_cuts_across_ports (default True) — propagate concat-induced cut points across port boundaries; see Bit dependency resolution.black_boxes (default []) — list of glob patterns (*, ?) matched against each instance's definition name and hierarchical path. Matched instances skip body traversal and record only port-boundary connectivity.Available node types and their properties:
Port — name, path, direction, bounds, is_input(), is_output(), is_driven() Variable — name, path, bounds State — name, path, bounds Constant — width, value (string form of the constant value). Created for literal RHSs, constant-foldable expressions, zero-extension padding bits, literal port connections, and constant arms of conditional operators.Assignment, Conditional, Case, Merge — no additional propertiesThe bounds property on nodes and edges is a DriverBitRange with lower, upper, and width accessors; it also unpacks as a (lower, upper) tuple.
Edge properties: symbol_name, symbol_path, bounds, disabled.
Use -j <N> to set the number of threads. The default (-j 0) uses hardware concurrency. For small designs the overhead of thread management can outweigh the benefit; -j 1 forces sequential execution.
The parallel phases of construction are Phase 2 (DFA dispatch) and Phase 4 (R-value resolution). Phase 2 dispatches one task per procedural block and continuous assignment, so designs with many independent blocks benefit most from additional threads. Phase 4 only parallelises when the number of pending R-values exceeds an internal threshold (1000 by default).
Use --stats to print a human-readable timing breakdown to stderr:
The output shows per-phase timings (collect, parallel DFA, drain, resolve R-values), per-task statistics (min/max/mean/median), and peak RSS. Use --stats-json for machine-readable JSON output.
There are various factors that affect performance and how much multithreading improves this. Here are some to consider; note that the execution phases of the netlist construction are detailed in Graph construction.
always / initial block is a separate DFA task in Phase 2; designs with many small blocks parallelise well, while designs dominated by a few large blocks may be limited by the longest task.Slang Netlist builds its dependency graph by analysing the SystemVerilog source directly, without performing logic synthesis. This makes it fast, portable across target technologies, and able to operate on partial or non-synthesisable designs. However, because the tool does not flatten the design down to a gate- or LUT-level netlist, the analysis is necessarily more conservative than what a synthesis tool could provide. The key differences are described below.
A synthesis tool resolves every operator, generate construct, and hierarchical reference into a flat network of primitive gates or technology cells. Slang Netlist instead works at the SystemVerilog source level: it preserves the original module hierarchy, treats each assignment as an atomic operation and records data dependencies between the variables that appear on each side. This means the graph is a faithful representation of the source structure, but it does not always capture the Boolean-level logic that a synthesised netlist would expose.
When an assignment connects symbols on its left- and right-hand sides, the graph records dependencies bit-by-bit wherever the source structure makes the per-bit correspondence clear. Concatenations, replications, and width-changing conversions are tracked precisely, so the bits of one symbol are connected only to the bits they actually drive on the other side:
This holds across the structural rearrangements you can write in SystemVerilog: nesting concatenations, replicating with a constant count, widening to a larger type (the extra bits are recorded as zero- or sign-extension and have no driver), and using a conditional operator ?: where both arms have the same width as the result (the condition itself becomes an extra dependency on every bit).
The same rules apply to port connections, which are treated as assignments. A hookup such as .in({x,y}) on a two-bit input port connects x and y to the matching individual bits of the port.
Bit precision also carries through the port itself. When a concat appears on a port connection, the cut points are propagated inward so that the formal port nodes and the module-internal assignments are split at the same bit boundaries. For example, given:
The graph reports a→c and b→d but no cross-bit paths.
+, -, *, …), a bitwise or relational operator, a reduction, a function call, a streaming concatenation, a non-constant select, a narrowing conversion, or a pattern-bearing conditional, every symbol read inside that expression is treated as contributing to every bit the expression produces. So in y = a & b the graph still records that every bit of y depends on every bit of a and b, even though & is bitwise in nature.Bit-aligned resolution can be turned off with --no-resolve-assign-bits on the slang-netlist CLI, or by passing resolve_assign_bits=False to NetlistGraph.build in the Python bindings. With it off, every symbol on one side of an assignment is connected to every symbol on the other side, matching the behaviour of releases before bit-aligned resolution landed.
Cross-port cut propagation can be turned off with --no-prop-cuts-across-ports on the slang-netlist CLI or by passing prop_cuts_across_ports=False to NetlistGraph.build in the Python bindings. With it off, port nodes and module-internal assignments stay whole-word at port boundaries even when the actual side of the connection is a concat.
In every fallback case the resulting graph is still sound (no real connection is missed) but path and dependency queries over the affected symbols may report paths that a deeper Boolean analysis could rule out.
Instances can be black-boxed to stop the netlist builder from descending into their bodies. A black-boxed instance still receives port nodes and external port-connection wiring, but its internal assignments and sub-instances are not traversed, so fan-in/fan-out paths terminate at the port boundary. This is useful for excluding vendor IP, technology cells, or any sub-tree whose internals are irrelevant to the analysis at hand.
Patterns are glob expressions (* and ?) and are matched against either an instance's definition name or its hierarchical instance path, so the same pattern can target a single instance or every instantiation of a module:
The Python equivalent passes a list of patterns to NetlistGraph.build:
The following SystemVerilog constructs are handled during netlist construction:
assign).always, always_ff, always_comb, initial.= and non-blocking <=).if/else) and case statements within procedural blocks, including static constant folding of unreachable branches.SystemVerilog constructs that are not currently supported or have limited handling:
$display, etc.) are ignored.force/release and deassign are not modelled.Here are some ideas for ways in which Slang Netlist can be used in digital design.