SV Arch View
See a SystemVerilog design as a block diagram, straight from its file list:
each instance is a block that holds its children, wired to the blocks it
talks to. The view shows what is inside what and what drives what, and each
block jumps to its source.
- Point it at a file list and the top is found for you. Verilator elaborates
the design (
--json-only), so generate loops are unrolled and parameters
resolved, as they are in a real build.
- A block diagram, not just a tree. Inside an expanded block, its children
are laid out left to right by dataflow, with the module's inputs on the left
edge and its outputs on the right. Ports are pins and connections are
wires, traced bit by bit through slices, concatenations and
assigns. A
block grows with its pins and with the hierarchy below it.
- Hierarchy side panel. The SV Arch view in the activity bar lists every
instance under the top. Click one to show it in the diagram. Use the inline
buttons to zoom the diagram into it or open its module definition.
- Save it, reopen it. Save writes a
.svarch file with the file list,
tops, defines, zoom and expanded blocks, plus the elaborated hierarchy.
Opening that file brings back the diagram and the side panel at once, with
no elaboration step.
Requirements
One of: Verilator 5.x (the default), Siemens Questa, Cadence Xcelium, Synopsys
VCS, or any simulator you add yourself. Pick it, and set where it lives, in
the Tools view.
Use
| To |
Do |
| Draw a list |
Right-click a .f / .flist / .vc → Open File List…, the button in the editor title of an open list, or SV Arch: Open File List… |
| Pick other tops |
Top… in the diagram, or the hierarchy icon in the side panel. Select several to draw them side by side, or type a name that isn't listed |
| Re-elaborate after RTL edits |
Rebuild |
| Save |
Save (the first save asks where; later saves go to the same file). Save Architecture As… is in the side panel's … menu |
| Reopen |
Open the .svarch file. If a source has changed since the save, you are offered a Rebuild |
In the diagram, click a block to expand or collapse it and double-click
to zoom into it. Click the grey module name to open its definition, and
alt-click a block to open the line that instantiates it. Repeated
instances of one module (gen_tile[0..83].i_core) show their first three side
by side and then a …+81 chip; click it to draw them all, and less to
fold them again. depth ±, group arrays and find are in the header. Clicking a block also selects it
in the side panel.
The diagram's header also has:
| Control |
What it does |
| wires |
Block diagram with pins and wires. Off: the nested view, blocks only |
| bundle |
On (the default): one pin per neighbor and one wire per pair of blocks, with an arrowhead at each end that data flows to; a wire's thickness follows its total width. Off: a pin per port and a wire per signal |
| clk/rst |
Also draw clock and reset nets (one-bit nets named clk, rst, reset …), which otherwise reach every block |
zoom − + fit |
Scale the drawing; Ctrl/Cmd+wheel does the same |
Hover a wire or a pin to trace it: its wires light up, the rest fade, and
the tooltip lists every signal with its width and where it goes.
With Verilator, wires come from its elaborated tree, bit by bit. With
Questa, Xcelium, VCS or your own tool, they come from the sources: the
instantiations' port connections (.port(sig), .port, .*, positional) and
plain assigns, each assign inside a generate loop once per iteration. Loop
indices come from the scope names (gen_tile[3]); parameters (Tile,
Peer) and widths from the VCD; enum constants from the sources. A select of
a plain vector is a bit range, any other index an array element
(req_in[Tile][dir]). A connection through logic reaches every signal it
reads; a select whose position cannot be worked out connects nothing.
In the side panel, click an instance to reveal and outline it in the
diagram. The inline buttons zoom the diagram into it and open its
definition. The context menu adds Open Instantiation and Copy Instance
Path. Arrays of the same module (gen_tile[0..83].i_core ×84) fold into one
node, the same way the diagram groups them.
Variables
The Variables view (SV Arch side bar) lists every $VAR / ${VAR} the
open file list uses, including through its -f includes, with its value and
where it comes from. Variables that are set nowhere are marked in red, and
the view shows how many are missing.
Opening a list that uses an unset variable (test_opentitan.f and
$PRJ_HOME, say) runs nothing. An error names the variable and offers to set
it, and the diagram builds as soon as every variable has a value. Click a
variable to type a value or browse for a folder. Values are stored in
svArch.env, in workspace settings when a folder is open, and are also passed
to the tool's environment.
The Tools view lists Verilator, Questa, Xcelium, VCS and the tools you add.
The one in use is ticked, and any executable that cannot be found is flagged.
- Use This Tool (the check icon on a tool) switches to it.
- Path is a tool's
bin directory, or the executable itself. When it is
empty the tool is looked up on PATH. $VAR is allowed, e.g. $QUESTA_HOME/bin.
- Commands. Click a command line to edit it. Steps can also be added,
removed and reordered. Reset to Default undoes your edits to a
built-in tool.
- Add Your Own Tool… (the
+ in the view title) defines a new one from
its command lines.
Verilator is read with --json-only, so parameters and generate loops come out
exactly as Verilator elaborates them. Its command is the executable plus any
extra arguments. SV Arch adds --json-only, --top-module and -f.
Every other tool runs its command lines in order, in a scratch directory. The
list is compiled with a small probe module as a second top. The probe calls
$dumpvars on your top and stops after one time step, and SV Arch reads the
instance hierarchy from the VCD scope tree. Module names come from scanning
each module's source for its instantiations. Placeholders:
|
|
${flist} |
flat list of absolute paths SV Arch writes (+incdir+, +define+, sources, the probe) |
${top} |
the top module |
${probe} |
the probe module (svarch_probe), to compile as a second top |
${vcd} |
where the probe writes the VCD |
${work} |
the scratch directory, also the working directory |
The built-in defaults:
Questa vlib svarch_lib
vlog -sv -work svarch_lib -f ${flist}
vsim -c -lib svarch_lib -voptargs=+acc ${top} ${probe} -do "run -all; quit -f"
Xcelium xrun -sv -q -access +r -f ${flist} -top ${top} -top ${probe} -xmlibdirname svarch.d
VCS vcs -full64 -sverilog -q -debug_access+r -f ${flist} -top ${top} -top ${probe} -o ${work}/svarch_simv
${work}/svarch_simv
With these tools, missing definitions in fragment lists are not looked up in
the workspace, because that relies on Verilator's messages. Tops, contexts and
Top module: / Context: directives work the same way. When a tool is missing
or a step fails, an error names the executable and shows its errors. The full
output is in Output ▸ SV Arch.
Lists that are fragments
Many lists name a single module and leave out what it depends on.
npu_dma.f, for example, names npu_dma.sv but none of the packages it
imports. When Verilator reports something missing (a package, a module, an
include or a macro), SV Arch finds where the workspace defines it,
adds that file and runs Verilator again. This repeats until the list
elaborates. It follows chains of dependencies, such as a package that imports
another package.
- Several definitions of one name. Some names are defined in more than one
file, such as a config package with one variant per configuration. The pick
goes to the definition nearest the list, and the rest are kept as
alternatives. The diagram's status line shows "+N files from workspace".
Click it, or use Found Dependencies…, to switch to another definition.
The switch is saved in the
.svarch. The svArch.prefer setting (e.g.
["dense64x64"]) picks a variant without switching each time.
- Fragments that fail for other reasons. A fragment can still fail because
of file order or configuration, not a missing file. It is then retried inside
the nearest checked-in lists that include it with
-f, keeping its own top.
For example, clusters.f is elaborated inside clusters_attention4x128.f.
Context… picks that enclosing list yourself.
Turn these off with svArch.autoResolve / svArch.autoContext.
What a list can say about itself
Two header comments in the list you open take priority over any guessing:
// Top module: cva6, npu_cvxif_top tops to draw, side by side
// Top module: cheshire_soc #(.Cfg(cheshire_pkg::DefaultCfg))
// Context: ../../local_verif2x2.f the list this one compiles inside
- A
Top module: with #(...) is elaborated through a one-line wrapper that
SV Arch writes into its own work directory, so no RTL is added to your repo.
- With
Context:, the tops are elaborated inside that list. If a top still
cannot elaborate on its own there, for example because its type parameters
only make sense when a parent sets them, the context's own top is
elaborated instead. The drawing then starts at the first instance of the
module, exactly as that parent instantiates it.
- A trailing
(reason) on a directive line is ignored.
- A list with no modules is linted, and its packages are drawn as blocks.
- A list with no sources at all (only include directories and defines) says
so instead of failing.
How the top is chosen
With no Top module: line, a candidate is any module in the list that no other source in the list names.
Each candidate is scored on two things: how many -f levels below the list
you opened its file is named, and how many of the list's modules it reaches
through textual instantiation.
- The candidates the list was written for sit near it. Leftover modules from
vendored IP sit deeper. The non-leaf candidates at the shallowest level, plus
the substantial ones one level below, are drawn side by side. This covers
a die list of cluster blocks with no die top. At most
svArch.maxAutoTops are
drawn this way (default 6).
- If there are more than that, the likeliest single candidate is used. If it
fails to elaborate, the next substantial candidate is tried. A failed real
top is reported as an error rather than replaced by a stray leaf.
Top… lists every candidate with its depth and reach.
This is JSON. The settings are at the top and easy to read (flist, tops,
defines, view, savedAt). The cached model follows on one line. A path
near the .svarch file is stored relative to it, so the file can be checked in
next to the list. A path that climbs far out stays absolute. To see the raw
file, use Reopen Editor With… → Text Editor.
Settings
| Setting |
Default |
|
svArch.tool |
verilator |
Tool in use: verilator, questa, xcelium, vcs, or one you added (set from the Tools view) |
svArch.tools |
{} |
Tool paths and commands edited from the Tools view, and your own tools |
svArch.verilator |
verilator |
Verilator executable; the Verilator path in the Tools view takes over when set |
svArch.extraArgs |
[] |
Extra Verilator arguments, e.g. ["-GNUM_CORES=4"] |
svArch.env |
{} |
Values for $VAR in lists, on top of the environment, also passed to the tool; ${workspaceFolder} is expanded (set from the Variables view) |
svArch.interfaces |
false |
Also draw interface instances |
svArch.defaultDepth |
2 |
Levels expanded when a diagram opens |
svArch.repeatShown |
3 |
Repeated instances drawn before the …+N chip |
svArch.maxAutoTops |
6 |
Peer tops drawn side by side automatically |
svArch.autoTries |
3 |
Candidates tried when the likeliest top fails |
svArch.autoResolve |
true |
Add missing packages, modules, includes and macros found in the workspace |
svArch.autoContext |
true |
Retry a failing list inside the lists that include it |
svArch.prefer |
[] |
Path fragments that win when several definitions or enclosing lists fit |
The Output ▸ SV Arch channel logs each elaboration: which top was tried, the
tool's command lines and its errors.
Develop
npm install # jsdom, for the webview test only
npm test # fixture design; or: node test/run.js path/to/list.f
scripts/deploy # unit tests, then vsix/sv-arch-view-<version>.vsix
scripts/deploy --no-test --install # package only, and install into VS Code
scripts/publish patch # bump 0.5.0 -> 0.5.1, test, build, upload to the Marketplace
scripts/publish --dry-run # everything but the upload
scripts/publish reads the token from VSCE_PAT (Azure DevOps, Marketplace ▸
Manage scope), or uses a login saved with npx @vscode/vsce login ahassan. It
stops early if the version is already on the Marketplace. --pre-release
publishes a pre-release, and --ovsx also uploads to Open VSX (with OVSX_PAT).
There is no build step. The extension is plain JavaScript under src/, and the
diagram page is media/view.html.