This repository pins Bazel 7.7.1 in .bazelversion. The final supported host is
Red Hat Linux with Python 3.12; macOS checks are useful for rule generation but
do not replace licensed VCS/Xcelium runs on Red Hat.
Add the following to your WORKSPACE file:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
RULES_VERILOG_COMMIT = "<40-character commit SHA>"
http_archive(
name = "rules_verilog",
urls = ["https://github.com/justin371/new_rules_verilog/archive/{}.tar.gz".format(RULES_VERILOG_COMMIT)],
sha256 = "<sha256 of the archive>",
strip_prefix = "new_rules_verilog-{}".format(RULES_VERILOG_COMMIT),
)
load("@rules_verilog//:deps.bzl", "verilog_dependencies")
verilog_dependencies()
load("@rules_python//python:repositories.bzl", "py_repositories")
py_repositories()
The second load/call initializes the pinned rules_python 0.40 repositories after
verilog_dependencies declares @rules_python. Pin a reviewed commit and its
archive SHA rather than tracking main directly.
The rules use the workstation Python 3.12 environment so simulator-side Python
packages remain available. Ensure python3.12 is on PATH, then add:
build --incompatible_use_python_toolchains=false
build --python_path=python3.12
build --action_env=PATH
Cadence Xcelium needs both HOME and LM_LICENSE_FILE; add them to your .bazelrc file:
test --action_env=HOME
test --action_env=LM_LICENSE_FILE
For Synopsys VCS flows, you can add a named Bazel config in .bazelrc and invoke it explicitly. Example:
build:vcs --@rules_verilog//:verilog_unit_test_simulator=VCS
build:vcs --@rules_verilog//:verilog_dv_unit_test_command_vcs="runmod vcs -- vcs"
build:vcs --@rules_verilog//:verilog_rtl_lint_test_command_vcs="runmod vcs -- vcs"
build:vcs --@rules_verilog//:verilog_rtl_svunit_test_command_vcs="runmod vcs --"
build:vcs --@rules_verilog//:verilog_rtl_unit_test_command_vcs="runmod vcs -- vcs"
build:vcs --@rules_verilog//:verilog_vcs_unit_test_runner="runmod vcs --"
Then run the test suite with VCS selected for one-step unit tests and RTL lint
tests that do not set simulator explicitly:
bsub -I -q syn bazel test --config=vcs //... --test_tag_filters=-no_ci_gate \
--cache_test_results=no --jobs 8 --test_output=all 2>&1An explicit simulator = "XRUN" or simulator = "VCS" on a target takes
precedence over the config default. VCS one-step unit tests compile with vcs
and then execute the generated simv through verilog_vcs_unit_test_runner,
so the compile and runtime processes share the same tool environment. VCS
one-step FSDB dumping is currently disabled; the wave commands remain in the
Synopsys templates as comments.
The bundled SVUnit template follows the configured simulator. Under VCS it
uses runSVUnit -s vcs through verilog_rtl_svunit_test_command_vcs; explicit
simulator = "XRUN" still takes precedence.
For RTL unit tests, put compile/elaboration controls in pre_flist_args or
post_flist_args and runtime plusargs in run_args. The VCS compatibility
path also moves legacy non-compiler plusargs from the flist argument attributes
to the generated simv invocation.
For RTL lint, legacy rulefile values remain associated with Cadence/HAL when
VCS is selected by --config=vcs; rules_verilog uses its built-in VCS policy
instead. Set rulefile_vcs when a target needs project-specific VCS lint
options. Targets that explicitly set simulator = "VCS" may continue using
rulefile for backward compatibility.
For simmer VCS runs, --simulator VCS is enough. The VCS, simv, and Verdi launcher prefix defaults to runmod vcs --.
simmer -t //hw/dv/project_benches/sys/tb:some_vcs_test --simulator VCSOverride the launcher with RV_VCS_RUNNER or --vcs-runner only when a project needs a different module wrapper.
During an interactive run, Ctrl-C opens a terminal menu. Choose stop for bounded SIGTERM/SIGKILL cleanup and
interrupted-history persistence, pause to stop active process groups and prevent new jobs from launching, continue
to keep running, or status/logs to print active job directories and log paths. A paused regression can then be resumed
or stopped. Non-interactive runs stop immediately so batch jobs and CI never wait for input.
Large VCS regressions continue to use the reusable two-step
verilog_dv_tb + simmer flow. Bazel one-step DV and RTL unit tests support
both Xcelium and VCS.
VCS wave capture uses FSDB. These commands cover the generated simmer flow:
# Default hdl_top scope, all hierarchy, full simulation.
simmer -t 'sys_tb:smoke_test@1' --simulator VCS --waves
# Selected scopes at UCLI depth 8: each scope plus seven nested levels.
simmer -t 'sys_tb:smoke_test@1' --simulator VCS \
--waves hdl_top.dut hdl_top.env --wave-depth 8
# Capture only the 1000 ns through 50000 ns interval.
simmer -t 'sys_tb:smoke_test@1' --simulator VCS \
--waves hdl_top.dut --wave-start 1000 --wave-end 50000
# Use a project-owned UCLI file for per-scope depth and advanced FSDB controls.
simmer -t 'sys_tb:smoke_test@1' --simulator VCS --waves \
--wave-tcl ./debug/vcs_fsdb_dump.tclThe generated FSDB controls are:
| simmer argument | Effect |
|---|---|
--waves [scope ...] |
Enables FSDB, glitch capture, and force/release/deposit metadata; no scope defaults to hdl_top. |
--wave-depth N |
Applies depth N to every selected scope. The default captures all hierarchy. |
--wave-start NS |
Starts dumping at an absolute, non-negative simulation time in ns. |
--wave-end NS |
Stops dumping at an absolute time in ns; it must be greater than --wave-start. |
--wave-tcl FILE |
Uses a VCS UCLI file instead of generated scope, depth, and time commands. |
Copy the VCS FSDB Tcl example when different
scopes need different depths or when dump -add needs advanced UCLI options.
The generated flow keeps -aggregates and
-fsdb_opt +packedmda+struct+parameter; -fsdb_opt is still needed to select
those object types and is independent of glitch and force capture. Other useful
revisions include -ports/-in/-out/-inout and -fsdb_opt values such as
+mda, +sva, +strength, +Reg_Only, +IO_Only, or +by_file=<file>.
UCLI also supports dump -suppress_file, dump -suppress_instance, and
dump -deltaCycle; follow the installed VCS guide because ordering and setup
requirements vary by option.
For generated Tcl, simmer passes +fsdb+glitch=0 and +fsdb+force, then runs
dump -glitch on on the returned FSDB file ID. +fsdb+force records force,
release, and deposit information for Verdi; UCLI dump -forceEvent is VPD-only
and must not be used for FSDB.
With --wave-tcl, the Tcl file owns scopes, depths, dump timing, and the
file-ID-specific dump -glitch on command. Simmer still passes both runtime
FSDB options. Keep the output at $::env(SIMRESULTS)/waves.fsdb so simmer can
find it and generate run_waves.sh. Open Verdi locally or through the site LSF
queue:
./run_waves.sh
SIMMER_WAVE_LAUNCHER="bsub -I -q syn" ./run_waves.shOne-step unit-test targets can select a simulator explicitly:
verilog_rtl_unit_test(
name = "counter_test_xrun",
deps = [":counter_test_top"],
simulator = "XRUN",
)Configure the Xcelium site wrappers independently from the VCS regression flow:
build:xrun --@rules_verilog//:verilog_dv_unit_test_command="runmod -t xrun --"
build:xrun --@rules_verilog//:verilog_rtl_unit_test_command="runmod -t xrun --"
Run the Xcelium unit test on the Red Hat workstation:
bazel test --config=xrun //path/to:counter_test_xrunTo let --config=vcs select VCS for RTL/DV unit tests and RTL lint tests,
omit the target-level simulator attribute and use the VCS build settings shown
above.
The bundled SVUnit template supports Xcelium and VCS. A project-specific custom
template remains simulator-specific unless it implements both backends.
runmod is a site-provided command from a separate repository and is assumed
to be available on PATH.
VCS enables automatic compile fingerprint reuse and Partition Compile by
default. An unchanged fingerprint bypasses VCS; a changed build uses the
allocation-aware partition flow. The writable partition database is
<tb>__VCS_VCOMP/partitionlib; --waves and --gui use sibling
partitionlib_waves and partitionlib_gui databases so incompatible KDB
options do not invalidate each other. Stable third-party IP/VIP
partitions are reused while changed project RTL and testbench partitions are
rebuilt. Tune parallel compilation after measuring the workstation:
simmer -t 'sys_tb:smoke_test@1' --simulator VCS \
--vcs-partcomp-jobs 16 --vcs-profileUse --no-vcs-partcomp for an unsupported VCS release or a regular -Mupdate
comparison. Use --no-vcs-auto-compile-cache to invoke VCS even when the
fingerprint matches. Shared partition databases and the full compatibility
guidance are documented in VCS and Xcelium
workflow.
ICO, VSO.ai CSO and VSO.ai Coverage Directed Solver are separate opt-in flows:
simmer -t 'sys_tb:*@20' --simulator VCS --ico \
--ico-shared-record /nfs/project/ico/shared_record
simmer -t 'sys_tb:*@100' --simulator VCS --vso --vso-cbv --vcs-cm line \
--vso-dbdir /nfs/project/vso/model --vso-phase stress:3
simmer -t 'sys_tb:*@20' --simulator VCS --vso-ccex \
--vso-ccex-auto-merge-dir /nfs/project/ccex/sharedICO uses the runtime-only shared-CDB model from the Y-2026.03 ICO Guide. VSO.ai
CSO uses the documented simplified init/ask-all/execute/finalize+merge model;
CCEX adds -vso ccex at compile and runtime. They cannot be combined in one
invocation and still require licensed Red Hat validation.
For heavy gate-level simulation, keep the stable gate netlist in
msie_primary_deps and the changing testbench/tests in
msie_incremental_deps. Simmer generates both Xcelium filelists through Bazel;
do not maintain source-tree msie/*_prim.f or *_incr.f files.
Run the same test target with the same SIMRESULTS and --dir-suffix through
the three multi-step stages:
MSIE_KEY='XCELIUM-25.03:netlist-r42:sdf_wc'
simmer -t 'gate_tb:smoke_test@1' --simulator XRUN \
--msie-href dut --dir-suffix _sdf_wc
simmer -t 'gate_tb:smoke_test@1' --simulator XRUN \
--msie-prim dut --msie-primary-name dut_sdf_wc \
--msie-primary-key "$MSIE_KEY" --dir-suffix _sdf_wc
simmer -t 'gate_tb:smoke_test@1' --simulator XRUN \
--msie-incr dut_sdf_wc --msie-primary-key "$MSIE_KEY" \
--dir-suffix _sdf_wcThe incremental stage validates the primary top/name, corner key, generated filelist, primary inputs, href/externs, coverage/debug configuration and Xcelium environment before XRUN starts. Full BUILD configuration, coverage rules and rebuild instructions are in the Xcelium MSIE gatesim workflow.
The retained static HTML dashboard is generated by default when a simmer
regression plans more than one simulation. A single test/iteration does not
generate a report unless --report is explicit; --no-report disables reports
for a regression. Always quote test globs so the shell does not expand them.
Override the report root for a VCS or Xcelium regression with:
simmer -t 'sys_tb:*@2' --simulator VCS \
--report-dir "$PWD/report-output"
simmer -t 'sys_tb:*@2' --simulator XRUN \
--report-dir "$PWD/report-output"Add simulator-specific coverage when coverage results should appear in the dashboard:
simmer -t 'sys_tb:*@10' --simulator VCS --vcs-cm A \
--report-dir "$PWD/report-output"
simmer -t 'sys_tb:*@10' --simulator XRUN --coverage A \
--report-dir "$PWD/report-output"For VCS, --vcs-cm-cond obs+event, --vcs-cm-tgl portsonly,
--vcs-urg-parallel, and --vcs-urg-show-tests expose the documented coverage
collection and merge controls without leaking them into XRUN.
Configure coverage files on the matching testbench target: use vcs_cm_hier
for VCS or xcelium_covfile for Xcelium, plus dut_top/dut_instance when the
defaults do not match the design hierarchy. Failed tests and stale databases
are excluded from the current-run coverage merge; unavailable metrics display
as N/A rather than a false zero.
Coverage totals follow the two-level average used by OpenTitan's pinned DVSim
1.34.1. Code Coverage is the arithmetic mean of the available Line/Statement,
Branch, Condition/Expression, Toggle and FSM metrics; Block is shown when
reported but is not part of that average. Total Coverage is the arithmetic mean
of the available Code Coverage, Assertion Coverage and Functional CoverGroup
Coverage values. Missing values are omitted from each denominator. A simulator
SCORE/Overall value is retained as cov_vendor_score in regressions.json
for reference, but is not used as Code Coverage or Total Coverage.
The dashboard entry point and drill-down pages are written under:
<report-dir>/regression_report/index.html
<report-dir>/regression_report/<project>/index.html
<report-dir>/regression_report/<project>/<bench>/index.html
<report-dir>/regression_report/<project>/<bench>/<timestamp>.html
<report-dir>/regression_report/open_<timestamp>.sh
At completion, simmer prints the executable launcher for that exact run. Open
the report on a Red Hat workstation with the printed command, for example:
/path/to/regression_report/project/open_reports/open_20260716_140000_000001.shFor a remote workstation, serve the static files on its loopback interface:
python3.12 -m http.server 8000 \
--bind 127.0.0.1 \
--directory "$PWD/report-output/regression_report"Forward that port from the local machine, then open http://localhost:8000/:
ssh -N -L 8000:127.0.0.1:8000 user@redhat-hostThe default report root is <regression-dir>/regression_results, derived from
the current user's simulation result directory and checkout. It is not a fixed
user or project path. Override the report per command with --report-dir, or
configure shared result and report locations and a public URL:
export SIMRESULTS=/nfs/regression
export SIMMER_REPORT_DIR="$SIMRESULTS/webroot"
export SIMMER_REPORT_URL=https://regression.example.com/regression_report
simmer -t 'sys_tb:*' --simulator VCSSIMMER_REPORT_URL only changes the report link printed by simmer; a web
server must expose <SIMMER_REPORT_DIR>/regression_report at that URL. Run
simmer --help for the complete CLI. From this repository, the same help is
available without installing a wrapper:
bazel run //bin:simmer -- --helpThe simmer command cookbook collects ready-to-adapt commands for normal runs, reuse, waves, coverage, reporting, MSIE, Palladium, ICO, VSO.ai and CCEX.
--no-compile reuse is rejected when source/runfile content, an external
compile configuration, or the selected simulator tool environment changes.
Recent normal-run compile/start failures remain visible through simmer --history.
rules_verilog uses the Python libraries listed in requirements.txt, but it
does not create a pip repository or install them. The top-level project owns
Python dependency installation so that every external rules repository shares
the same environment. Install the requirements into the Python 3.12 environment
used by Bazel before running simmer:
python3.12 -m pip install -r path/to/rules_verilog/requirements.txtrules_verilog BUILD packages intentionally avoid workspace-owned Python
requirement labels so @rules_verilog//bin:simmer can be loaded from an
external repository.
The workstation must expose Python 3.12 as python3.12 and Bazel 7.7.1 as
bazel. Run the no-license portability checks before licensed VCS/Xcelium
tests:
./tests/redhat_smoke.shThe script prints the failing line and command before it exits. Licensed unit
tests still need to be run separately with both --config=xrun and
--config=vcs on the configured Red Hat EDA host.
Load rules into your BUILD files from @rules_verilog//verilog:defs.bzl
- verilog_rtl_library
- verilog_rtl_pkg
- verilog_rtl_shell
- verilog_rtl_unit_test
- verilog_rtl_lint_test
- verilog_rtl_cdc_test
Load rules into your BUILD files from @rules_verilog//verilog:defs.bzl
Load rules into your BUILD files from @rules_verilog//verilog:defs.bzl
- The SVUnit package always adds svunit_pkg.sv to the compiler command line after the user flists. Without compiler library discovery, user flists cannot include/import anything that depends on svunit_pkg.
- To work around this ordering dependency, the project Bazel rules must create the verilog_rtl_lib using the module files as headers, and use a dummy .sv file as the top module.
- By declaring the module files as headers, they will not get put on the compiler command line via flists - rather their parents directory appears as an incdir.
- This allows SVUnit's generated flist to appear last on the compiler command line, without violating any compiler ordering dependencies.
These rules were written with the Cadence and Synopsys tools as the underlying compiler and simulator. Abstraction leaks are prevalent throughout the rules.
Use one-step verilog_dv_unit_test/verilog_rtl_unit_test for small Xcelium
or VCS tests. Large VCS simulations should use
verilog_dv_tb,
verilog_dv_test_cfg, and simmer so the
compiled simv can be reused across tests.