rules_cocotb
Bazel rules that run cocotb Python testbenches against Verilog/SystemVerilog and VHDL modules using open-source HDL simulators (Verilator, Icarus Verilog, GHDL).
Overview
A cocotb_test is a Bazel test target that pairs:
- a Verilog or VHDL
*_librarytarget (fromrules_verilogorrules_vhdl) as the module under test, - one or more Python
cocotbtest sources, and - a
cocotb_toolchainthat picks the simulator.
The top-level rules are documented under Rules; the per-simulator integrations live under Simulators.
End-to-end example
The walkthrough below builds a tiny 8-bit adder, drives it from a Python cocotb testbench, and runs the test with Verilator.
MODULE.bazel
bazel_dep(name = "rules_verilog", version = "1.1.1")
bazel_dep(name = "rules_cocotb", version = "{version}")
rules_cocotb registers a default toolchain
(//cocotb/toolchain:toolchain) wired to Verilator (default), Icarus
Verilog, and GHDL. No further register_toolchains call is required to
use the bundled simulators.
adder.sv
module adder (
input [7:0] x,
input [7:0] y,
input carry_in,
output carry_output_bit,
output [7:0] sum
);
logic [8:0] result;
assign result = x + y + carry_in;
assign sum = result[7:0];
assign carry_output_bit = result[8];
endmodule
adder_test.py
import cocotb
from cocotb.handle import HierarchyObject
from cocotb.triggers import Timer
@cocotb.test()
async def test_adder(dut: HierarchyObject) -> None:
"""Drive a handful of vectors through the 8-bit adder."""
vectors = [
# (x, y, carry_in, expected_sum, expected_carry_out)
(0x00, 0x00, 0, 0x00, 0),
(0xFF, 0x01, 0, 0x00, 1),
(0x55, 0xAA, 1, 0x00, 1),
]
for x, y, cin, exp_sum, exp_cout in vectors:
dut.x.value = x
dut.y.value = y
dut.carry_in.value = cin
await Timer(1, units="ns")
sum_val = int(dut.sum.value)
cout_val = int(dut.carry_output_bit.value)
assert sum_val == exp_sum and cout_val == exp_cout, (
f"adder mismatch for x={x:#04x} y={y:#04x} cin={cin}"
)
BUILD.bazel
load("@rules_verilog//verilog:defs.bzl", "verilog_library")
load("@rules_cocotb//cocotb:cocotb_test.bzl", "cocotb_test")
verilog_library(
name = "adder",
srcs = ["adder.sv"],
)
cocotb_test(
name = "adder_test",
srcs = ["adder_test.py"],
module = ":adder",
sim = "verilator",
)
Run it
$ bazel test //path/to:adder_test
//path/to:adder_test PASSED
To rerun under Icarus instead, change sim = "verilator" to
sim = "icarus". To swap to a VHDL toplevel, replace verilog_library
with vhdl_library from rules_vhdl and pick sim = "ghdl".
Going further
- The
cocotb_testreference covers the full attribute set (params,sim_opts,env, etc.). - The
cocotb_toolchainreference shows how to define a custom toolchain — for selecting a different default simulator, narrowing the set of simulators, or wiring in a bring-your-own-installcocotb_*_sim. - The
cocotb_stubgenreference covers generating typed Python stubs from an HDL library, so a testbench'sdutparameter type-checks instead of being an untypedHierarchyObject. - The Simulators section lists every built-in simulator integration and per-simulator status.
Rules
cocotb_test
Rules
cocotb_test
load("@rules_cocotb//cocotb:cocotb_test.bzl", "cocotb_test")
cocotb_test(name, deps, srcs, data, env, module, params, precompiled_libs, sim, sim_opts)
Run a test using cocotb on a given Verilog/VHDL module.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Python dependencies required by the test sources. | List of labels | optional | [] |
| srcs | Sources containing the test code to run. | List of labels | required | |
| data | Additional runtime data used by the test. | List of labels | optional | [] |
| env | Environment variables to set for the test. | Dictionary: String -> String | optional | {} |
| module | The Verilog/VHDL module to test. | Label | required | |
| params | Verilog parameters or VHDL generics. | List of strings | optional | [] |
| precompiled_libs | Precompiled simulator library sets to link before the test's own compile step. Each target must produce a CocotbPrecompiledLibraryInfo whose format matches this test's resolved simulator's format family (analysis-time check). At runtime the per-format runner patch in cocotb_process_wrapper emits the vendor's link directive (vmap -link for Aldec, -modelsimini for Mentor, etc.) so DUT wrappers that reference libraries inside the precompiled set (e.g. Xilinx's xil_defaultlib) resolve. | List of labels | optional | [] |
| sim | The name of the simulator to use. Must match a key in the cocotb_toolchain's simulators dict. | String | optional | "" |
| sim_opts | Additional command line arguments to pass only to the simulator during code-generation. | List of strings | optional | [] |
cocotb_toolchain
Rules
cocotb_toolchain
load("@rules_cocotb//cocotb:cocotb_toolchain.bzl", "cocotb_toolchain")
cocotb_toolchain(name, cocotb, default_sim, env, simulators, vhdl_libraries)
Define a toolchain for cocotb_* rules.
The toolchain bundles a cocotb Python library with a set of HDL
simulators that cocotb_test targets can select between via their sim
attribute. Register an instance with the standard toolchain(...)
wrapper to make it discoverable.
Registering simulators
Each entry in simulators is a cocotb_*_sim target keyed by the
string name that cocotb_test(sim = ...) will use to select it.
Names are user-chosen — common conventions are "verilator",
"icarus", "ghdl". Each name must be unique within the dict.
load("@rules_cocotb//cocotb:cocotb_ghdl_sim.bzl", "cocotb_ghdl_sim")
load("@rules_cocotb//cocotb:cocotb_icarus_sim.bzl", "cocotb_icarus_sim")
load("@rules_cocotb//cocotb:cocotb_toolchain.bzl", "cocotb_toolchain")
load("@rules_cocotb//cocotb:cocotb_verilator_sim.bzl", "cocotb_verilator_sim")
# Instantiate the sim rules you want to ship.
cocotb_verilator_sim(
name = "cocotb_verilator",
# ... (see //cocotb/toolchain:BUILD.bazel for the full attr set)
)
cocotb_ghdl_sim(
name = "cocotb_ghdl",
ghdl = "@ghdl",
vhdl_libs = ["@ghdl//:vhdl_libs_v08"],
)
cocotb_icarus_sim(
name = "cocotb_icarus",
iverilog = "@iverilog//:iverilog",
vvp = "@iverilog//:vvp",
ivl_files = {
"@iverilog//:ivl": "ivl",
# ... (see //cocotb/toolchain:BUILD.bazel for the full map)
},
)
cocotb_toolchain(
name = "my_cocotb_toolchain",
cocotb = "//path/to:cocotb_py_library",
default_sim = "verilator",
simulators = {
":cocotb_ghdl": "ghdl",
":cocotb_icarus": "icarus",
":cocotb_verilator": "verilator",
},
)
toolchain(
name = "my_toolchain",
toolchain = ":my_cocotb_toolchain",
toolchain_type = "@rules_cocotb//cocotb:toolchain_type",
)
Add register_toolchains("//path/to:my_toolchain") to MODULE.bazel
ahead of //cocotb/toolchain to override the default. default_sim
chooses which simulator runs when a cocotb_test omits its own sim
attribute; it's optional, but if set must name one of the keys in
simulators.
Supplying VHDL standard libraries
vhdl_libraries is optional and empty by default, and is the only part
of this toolchain that cocotb_stubgen reads. It reads it optionally:
stub generation is static analysis of HDL sources and runs no simulator,
so a project that only wants typed DUT handles need not register a
cocotb_toolchain at all.
The generator shipped today works from the parse tree alone — it maps
each port's terminal type mark (std_logic, unsigned, integer, ...)
onto a cocotb handle class, which covers designs whose ports are declared
in terms of the standard types directly — and so ignores these
sources. The attr reserves the interface for full elaboration, which
would additionally resolve project-local aliases and subtypes through to
their base types; until that lands, setting it only adds the files to
each stubgen action's inputs:
vhdl_library(
name = "std",
srcs = glob(["std/*.vhdl"]),
)
vhdl_library(
name = "ieee",
srcs = glob(["ieee2008/*.vhdl"]),
deps = [":std"],
)
cocotb_toolchain(
name = "my_cocotb_toolchain",
cocotb = "//path/to:cocotb_py_library",
simulators = {":cocotb_ghdl": "ghdl"},
vhdl_libraries = [":ieee"],
)
Each entry is a vhdl_library; the VHDL library name comes from its
library attr, which defaults to the target name. Libraries reached
through deps count too, so listing :ieee above is enough to pull in
:std. Several targets may share a library name.
Only ieee and std are accepted, and the set must be complete: a
partial set is rejected rather than honored, because unresolved types
degrade to Any silently instead of erroring.
Note that @ghdl//:vhdl_libs_v08 is not usable here: it is a compiled
GHDL library artifact for cocotb_ghdl_sim(vhdl_libs = ...), whereas
this attr wants VHDL sources for the parser.
Per-simulator API and wiring details live in the Simulators section.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| cocotb | The cocotb python library. | Label | required | |
| default_sim | An optional default simulator to use. | String | optional | "" |
| env | Environment variables to set whenever the toolchain invokes a simulator. Applied to every sim registered in simulators; for sim-specific vars (license server, install root, etc.) prefer the per-cocotb_*_sim env attr instead. Precedence at test time: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| simulators | A mapping of cocotb_*_sim targets to their matching simulator names. Every target must provide CocotbSimInfo. | Dictionary: Label -> String | required | |
| vhdl_libraries | Optional VHDL standard library sources for stubgen, as vhdl_library targets. Supply all of ["ieee", "std"] (counting libraries reached through deps) or leave this empty. Reserved for full elaboration; the generator shipped today ignores them. | List of labels | optional | [] |
cocotb_stubgen
Rules
cocotb_stubgen
load("@rules_cocotb//cocotb:cocotb_stubgen.bzl", "cocotb_stubgen")
cocotb_stubgen(name, module)
Generate typed cocotb DUT stubs for an HDL library.
Point module at a vhdl_library or verilog_library and the rule
produces a PyInfo target you add to any Python rule's deps (most
commonly cocotb_test.deps) to make the DUT's ports and signals
type-check.
Example — a VHDL DUT tests/foo/dut.vhd:
vhdl_library(
name = "dut",
srcs = ["dut.vhd"],
)
cocotb_stubgen(
name = "dut_stubs",
module = ":dut",
)
cocotb_test(
name = "dut_test",
srcs = ["dut_test.py"],
module = ":dut",
deps = [":dut_stubs"],
sim = "ghdl",
)
One class is emitted per entity / module found in each HDL source, each
subclassing cocotb.handle.HierarchyObject so it can stand in as the
DUT parameter's type directly. The import path mirrors the HDL source's
own package and basename — tests/foo/dut.vhd yields a Dut class
importable as:
from tests.foo.dut import Dut
async def test(dut: Dut) -> None:
dut.clk.value = 0
VHDL ports / generics / architecture signals are typed against cocotb's
handle hierarchy (LogicObject, LogicArrayObject, IntegerObject, ...).
Verilog ports, parameters and nets fall back to typing.Any — Verilog
declarations are effectively untyped once logic / wire / reg are
flattened. Instantiations in either language type as the instantiated
entity's own stub class.
Verilog is parsed without preprocessing, so ports supplied by a macro
(module m(`MY_PORTS);) are omitted rather than guessed at.
The generator is the one rules_cocotb ships and is not swappable. No
cocotb_toolchain is required either — stub generation is static
analysis and runs no simulator. Registering one contributes only its
optional vhdl_libraries, which the generator shipped today ignores;
see cocotb_toolchain.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| module | HDL library (vhdl_library / verilog_library) to stub. | Label | required |
Simulators
A simulator integration is a Bazel rule that wires a specific HDL
simulator into the cocotb test harness. cocotb_test doesn't talk to
simulators directly — it picks one of the simulators registered in the
active cocotb_toolchain by name (via its sim attribute), and the
toolchain dispatches compile + run through the matching cocotb_*_sim
target.
Each cocotb_*_sim rule produces a CocotbSimInfo provider that the
shared cocotb_test rule consumes. New simulator integrations can be
added by writing a rule that returns the same provider and registering
it in a cocotb_toolchain.simulators dict.
Built-in integrations
| Rule | HDL languages | Source | CI-verified |
|---|---|---|---|
cocotb_verilator_sim | Verilog / SystemVerilog | BCR verilator + rules_verilator | ✅ |
cocotb_icarus_sim | Verilog / SystemVerilog | BCR iverilog | ✅ |
cocotb_ghdl_sim | VHDL | BCR ghdl | ✅ |
cocotb_nvc_sim | VHDL | bring-your-own (no BCR module yet) | — |
cocotb_questa_sim | Verilog / SystemVerilog / VHDL | bring-your-own (commercial; also covers ModelSim) | — |
cocotb_xcelium_sim | Verilog / SystemVerilog / VHDL | bring-your-own (commercial; also covers Incisive) | — |
cocotb_vcs_sim | Verilog / SystemVerilog | bring-your-own (commercial) | — |
cocotb_dsim_sim | Verilog / SystemVerilog / VHDL | bring-your-own (commercial) | — |
cocotb_riviera_sim | Verilog / SystemVerilog / VHDL | bring-your-own (commercial) | — |
cocotb_activehdl_sim | Verilog / SystemVerilog / VHDL | bring-your-own (commercial; cocotb runner support pending) | — |
The default toolchain (//cocotb/toolchain:toolchain) registers only
the CI-verified row — Verilator (default), Icarus Verilog, and GHDL.
For any other simulator, define your own
cocotb_toolchain that wires the relevant
cocotb_*_sim to your install and register it ahead of the default.
The "CI-verified" column is what rules_cocotb's own
//tests/... exercises. The other rules are wired
correctly against cocotb's runner
classes,
but rules_cocotb can't ship the binaries (commercial license or no
BCR module yet), so we can't validate them ourselves — please file
issues if you hit problems wiring one up.
Other simulators
Tachyon DA CVC
has no cocotb_tools.runner class as of the cocotb version pinned by
this module, so there's no cocotb_cvc_sim rule. If/when cocotb adds
runner support upstream we can add the wiring.
Per-simulator status, known limitations, and any downstream-wiring patterns are inline on each simulator's reference page.
cocotb_ghdl_sim
Rules
cocotb_ghdl_sim
load("@rules_cocotb//cocotb:cocotb_ghdl_sim.bzl", "cocotb_ghdl_sim")
cocotb_ghdl_sim(name, env, ghdl, ghdl_coverage, ghdl_prefix, vhdl_libs)
A simulator configuration for running GHDL simulations in cocotb tests.
Status
Working against the BCR ghdl module from version 6.0.0.bcr.1 onward,
which links the ghdl binary with -Wl,--export-dynamic and the
upstream src/grt/grt.ver version script so cocotb's
libcocotbvpi_ghdl.so can resolve unprefixed vpi_* symbols at dlopen
time. Earlier ghdl@6.0.0 is missing those linker flags and fails at
sim time with undefined symbol: vpi_register_cb.
The backend is selectable with --@ghdl//:backend={mcode, llvm-jit}
(default mcode on x86_64, llvm-jit elsewhere).
Notes
GHDL only supports VHDL (VhdlInfo); pair it with a vhdl_library
target as the module. The integration is build-at-test-time: cocotb's
runner runs ghdl -a/-m in a writable build_dir via
Runner.build(). Pre-compiling at Bazel time isn't viable because the
JIT backends bake absolute sandbox paths into the .cf files.
The vhdl_libs attribute should point at the pre-compiled IEEE/std
libraries from the BCR ghdl module — most projects want
["@ghdl//:vhdl_libs_v08"].
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| ghdl | The ghdl binary. | Label | required | |
| ghdl_coverage | The ghdl binary to invoke at test time under bazel coverage to translate *.cov files to lcov via ghdl coverage --format=lcov. Defaults to the same ghdl binary (target config so the runtime wrapper can invoke it). NOTE: requires a gcc-backed ghdl; the BCR mcode/llvm-jit backends don't produce coverage data. | Label | optional | None |
| ghdl_prefix | Literal value to set as GHDL_PREFIX at simulation time. Use this for ghdl installs where the prefix is a stable absolute path on disk — typically a system/.deb/Homebrew install (e.g. "/usr/lib/ghdl").When unset (default), GHDL_PREFIX is auto-derived from vhdl_libs if it's populated (BCR-shaped layout), otherwise left unset so ghdl falls back to its own compiled-in search paths. | String | optional | "" |
| vhdl_libs | Pre-compiled VHDL standard libraries (e.g. @ghdl//:vhdl_libs_v08). Assumes the BCR ghdl module's layout — <root>/{std,ieee}/v<XX>/<name>-objXX.cf — from which GHDL_PREFIX is derived. If you ship ghdl differently and the IEEE/std libs are already discoverable by the binary, leave this empty and (optionally) set ghdl_prefix to a literal path, or skip both for a system install that uses its compiled-in defaults. | List of labels | optional | [] |
cocotb_icarus_sim
Rules
cocotb_icarus_sim
load("@rules_cocotb//cocotb:cocotb_icarus_sim.bzl", "cocotb_icarus_sim")
cocotb_icarus_sim(name, env, iverilog, ivl_base, ivl_files, vvp)
A simulator configuration for running Icarus Verilog binaries in cocotb tests.
Status
Fully functional. Sourced from the BCR iverilog module
(bazel_dep(name = "iverilog", version = "13.0.bcr.1")). The default
toolchain wires iverilog, vvp, and the IVL backend components.
Exercised end-to-end by the in-tree adder_icarus_test.
Notes
The iverilog driver locates its backend components (ivl,
vvp.tgt, system.vpi, etc.) via the IVL_BASE environment variable.
For the BCR iverilog module, the components are exposed as individual
labels; this rule's ivl_files attribute maps each label to its
expected filename and assembles them into a directory for IVL_BASE.
Icarus only supports Verilog/SystemVerilog (VerilogInfo); pair it
with a verilog_library target as the module.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| iverilog | The iverilog compiler binary. | Label | required | |
| ivl_base | A pre-assembled IVL_BASE directory (e.g. a filegroup wrapping /usr/lib/ivl for a system iverilog). The rule sets IVL_BASE to this directory's path during compilation. Mutually exclusive with ivl_files. | Label | optional | None |
| ivl_files | Components to assemble into an IVL_BASE directory. Maps source labels to destination filenames (e.g. {"@iverilog//:ivl": "ivl", "@iverilog//tgt-vvp:vvp_tgt": "vvp.tgt"}). Designed for the BCR iverilog module's per-component layout — for an IVL_BASE directory that already exists on disk, use ivl_base instead. Mutually exclusive with ivl_base. | Dictionary: Label -> String | optional | {} |
| vvp | The vvp simulation runner binary. | Label | required |
cocotb_verilator_sim
Rules
cocotb_verilator_sim
load("@rules_cocotb//cocotb:cocotb_verilator_sim.bzl", "cocotb_verilator_sim")
cocotb_verilator_sim(name, deps, cocotb, copts, copy_tree, env, process_wrapper, verilator,
verilator_coverage)
A simulator configuration for compiling Verilator binaries to be run in cocotb tests.
Status
Fully functional. Sourced from the verilator and rules_verilator BCR
modules; the default toolchain wires @verilator//:verilator_executable
together with cocotb's share/lib/verilator/verilator.cpp entrypoint.
Used by the in-tree adder_test smoke test, which passes end-to-end.
Notes
Verilator only supports Verilog/SystemVerilog (VerilogInfo); pair it
with a verilog_library target as the module. The sim_opts
attribute on cocotb_test is forwarded to the underlying verilator
invocation — e.g. sim_opts = ["--trace-fst"] enables FST waveform
capture.
The BCR verilator binary needs the rules_verilator process wrapper
to set up its include / lib paths, and cocotb's verilator.cpp
front-end plus its VPI shared libraries to link against. The rule
locates those inside the cocotb pip wheel automatically — point
cocotb at any py_library wrapping @cocotb_pip_deps//cocotb and
the rule extracts what it needs internally.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| deps | Additional CcInfo-providing dependencies to link into the verilator executable (e.g. @verilator//:verilated and your project's C++ shims). | List of labels | optional | [] |
| cocotb | The cocotb pip package (a py_library wrapping @cocotb_pip_deps//cocotb). Used to extract verilator.cpp and the cocotb VPI shared libraries. | Label | required | |
| copts | Additional C++ compiler flags for the verilator model sources. Appended after the toolchain's own flags and after --copt / --cxxopt, so these win on conflict. Verilator's headers emit a large number of -Wsign-compare warnings; copts = ["-Wno-sign-compare"] silences them for every model this simulator builds. | List of strings | optional | [] |
| copy_tree | A tool for copying a tree of files. Defaults to the rules_verilator helper. | Label | optional | "@rules_verilator//verilator/private:verilator_copy_tree" |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| process_wrapper | A process wrapper for verilator. Defaults to the rules_verilator helper. | Label | optional | "@rules_verilator//verilator/private:verilator_process_wrapper" |
| verilator | The Verilator binary to use (e.g. @verilator//:verilator_executable). | Label | required | |
| verilator_coverage | verilator_coverage_bin — invoked at test time under bazel coverage to translate coverage.dat into lcov. | Label | optional | "@verilator//:verilator_coverage_executable" |
cocotb_nvc_sim
Rules
cocotb_nvc_sim
load("@rules_cocotb//cocotb:cocotb_nvc_sim.bzl", "cocotb_nvc_sim")
cocotb_nvc_sim(name, env, nvc, nvc_libpath, vhdl_libs)
A simulator configuration for running NVC (open-source VHDL simulator) in cocotb tests.
Status
Working against the BCR nvc module from version 1.21.0 onward,
which links the nvc binary with -Wl,--dynamic-list=src/symbols.txt
so cocotb's libcocotbvpi_nvc.so plugin can resolve unprefixed
vpi_* / vhpi_* symbols at dlopen time.
Notes
NVC only supports VHDL (VhdlInfo); pair it with a vhdl_library
target as the module. The integration is build-at-test-time:
cocotb's runner runs nvc -a / -e / -r in a writable build_dir
via Runner.build() / Runner.test().
vhdl_libs accepts a list of per-library TreeArtifact targets —
typically ["@nvc//:vhdl_libs"], the BCR nvc module's filegroup
of per-library directories laid out exactly like a system install
under <prefix>/lib/nvc/<library>/. The rule's implementation
stages those TreeArtifacts side-by-side under a single root and
points NVC_LIBPATH at it so nvc finds every shipped library (STD,
IEEE, NVC, plus the SYNOPSYS / VITAL extras inside IEEE) at
simulation time.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| nvc | The nvc simulator binary. | Label | required | |
| nvc_libpath | Literal value to set as NVC_LIBPATH at simulation time. Use this for nvc installs where the prefix is a stable absolute path on disk — typically a system / .deb / Homebrew install (e.g. "/usr/local/lib/nvc").When unset (default), NVC_LIBPATH is auto-derived from vhdl_libs if it's populated (per-library TreeArtifacts staged into one root by this rule), otherwise left unset so nvc falls back to its own compiled-in search paths. | String | optional | "" |
| vhdl_libs | Per-library TreeArtifact targets to stage side-by-side under a single NVC_LIBPATH root. Typically ["@nvc//:vhdl_libs"] — the BCR nvc module's filegroup of per-library directories. Empty (the default) leaves NVC_LIBPATH unset. | List of labels | optional | [] |
cocotb_questa_sim
Rules
cocotb_questa_sim
load("@rules_cocotb//cocotb:cocotb_questa_sim.bzl", "cocotb_questa_sim")
cocotb_questa_sim(name, env, vcom, vlib, vlog, vsim)
A simulator configuration for running Mentor/Siemens
EDA Questa (and the older
ModelSim — cocotb uses the same questa runner for both) simulations
in cocotb tests.
Status
Infrastructure only. Questa/ModelSim is commercial, with no BCR
module and no redistributable binary; rules_cocotb cannot validate
this rule in CI. Wire it up downstream by pointing the binary attrs at
your own install (e.g. via new_local_repository over $MODEL_TECH or
the equivalent Questa install directory) and registering a
cocotb_toolchain that routes sim = "questa" through this rule.
Cocotb's runner handles the actual build/sim via Runner.build /
Runner.test.
Notes
Questa accepts both Verilog/SystemVerilog (VerilogInfo) and VHDL
(VhdlInfo) modules. The rule defers the vlib / vlog / vcom
invocations to cocotb's runner at test time rather than running them
during the Bazel build, so the simulator only needs to be present on
the test execution environment.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| vcom | The vcom VHDL compiler binary. | Label | required | |
| vlib | The vlib library manager binary. | Label | required | |
| vlog | The vlog Verilog/SystemVerilog compiler binary. | Label | required | |
| vsim | The vsim simulator binary. | Label | required |
cocotb_xcelium_sim
Rules
cocotb_xcelium_sim
load("@rules_cocotb//cocotb:cocotb_xcelium_sim.bzl", "cocotb_xcelium_sim")
cocotb_xcelium_sim(name, env, xrun)
A simulator configuration for running Cadence
Xcelium
(and the older Incisive — cocotb uses the same xcelium runner for
both) simulations in cocotb tests.
Status
Infrastructure only. Xcelium/Incisive is commercial, with no BCR
module and no redistributable binary; rules_cocotb cannot validate
this rule in CI. Wire it up downstream by pointing xrun at your own
install and registering a cocotb_toolchain that routes
sim = "xcelium" through this rule. Cocotb's runner handles the
actual build/sim via Runner.build / Runner.test.
Notes
Xcelium accepts both Verilog/SystemVerilog (VerilogInfo) and VHDL
(VhdlInfo) modules. The xrun driver dispatches to the appropriate
compiler internally, so only the one binary attr is needed.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| xrun | The xrun driver binary. | Label | required |
cocotb_vcs_sim
Rules
cocotb_vcs_sim
load("@rules_cocotb//cocotb:cocotb_vcs_sim.bzl", "cocotb_vcs_sim")
cocotb_vcs_sim(name, env, vcs)
A simulator configuration for running Synopsys VCS simulations in cocotb tests.
Status
Infrastructure only. VCS is commercial, with no BCR module and no
redistributable binary; rules_cocotb cannot validate this rule in
CI. Wire it up downstream by pointing vcs at your own install and
registering a cocotb_toolchain that routes sim = "vcs" through
this rule. Cocotb's runner handles the actual build/sim (cocotb's VCS
runner produces a simv binary and executes it for the run).
Notes
VCS accepts Verilog/SystemVerilog (VerilogInfo) modules. The cocotb
runner internally manages vcs's build flow and the simv output
binary, so only the vcs compiler binary is needed as a rule
attribute.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| vcs | The vcs compiler binary. | Label | required |
cocotb_dsim_sim
Rules
cocotb_dsim_sim
load("@rules_cocotb//cocotb:cocotb_dsim_sim.bzl", "cocotb_dsim_sim")
cocotb_dsim_sim(name, dsim, env)
A simulator configuration for running Siemens DSim (formerly Metrics DSim) simulations in cocotb tests.
Status
Infrastructure only. DSim is commercial, with no BCR module and no
redistributable binary; rules_cocotb cannot validate this rule in
CI. Wire it up downstream by pointing dsim at your own install and
registering a cocotb_toolchain that routes sim = "dsim" through
this rule. Cocotb's runner handles the actual build/sim via
Runner.build / Runner.test.
Notes
DSim accepts both Verilog/SystemVerilog (VerilogInfo) and VHDL
(VhdlInfo) modules. The dsim driver handles compile and run
phases internally, so only the one binary attr is needed.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| dsim | The dsim simulator binary. | Label | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
cocotb_riviera_sim
Rules
cocotb_riviera_sim
load("@rules_cocotb//cocotb:cocotb_riviera_sim.bzl", "cocotb_riviera_sim")
cocotb_riviera_sim(name, coverage_args, coverage_data_glob, coverage_tool, env, vsimsa)
A simulator configuration for running Aldec Riviera-PRO simulations in cocotb tests.
Status
Infrastructure only. Riviera-PRO is commercial, with no BCR module and
no redistributable binary; rules_cocotb cannot validate this rule in
CI. Wire it up downstream by pointing the binary attrs at your own
install and registering a cocotb_toolchain that routes
sim = "riviera" through this rule. Cocotb's runner handles the
actual build/sim via Runner.build / Runner.test.
Downstream wiring
Expose vsimsa to Bazel and register a custom cocotb_toolchain.
vsimsa is the only binary cocotb's Riviera runner invokes; the rest
of the Aldec install (alib/alog/acom/asim engines, libraries, license
config) is loaded internally by vsimsa through $RIVIERA_HOME. Pull
those into the action sandbox by attaching them as data on the
vsimsa target — anything reachable through its runfiles will be
staged alongside the binary.
Typically this means a local repository (e.g. new_local_repository
or a custom repository rule pointed at $RIVIERA_HOME) whose
BUILD.bazel wraps vsimsa as a native_binary (or sh_binary)
target with the rest of the install as its data deps, then:
load("@rules_cocotb//cocotb:cocotb_riviera_sim.bzl", "cocotb_riviera_sim")
load("@rules_cocotb//cocotb:cocotb_toolchain.bzl", "cocotb_toolchain")
cocotb_riviera_sim(
name = "cocotb_riviera",
vsimsa = "@riviera//:vsimsa",
)
cocotb_toolchain(
name = "my_cocotb_toolchain",
cocotb = "//path/to:cocotb_py_library",
simulators = {":cocotb_riviera": "riviera"},
)
Then register_toolchains("//path/to:my_cocotb_toolchain") in
MODULE.bazel (ahead of the default //cocotb/toolchain registration)
and cocotb_test(sim = "riviera", ...) will resolve through it.
Riviera-PRO accepts both Verilog/SystemVerilog (VerilogInfo) and VHDL
(VhdlInfo) modules.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| coverage_args | Template fragments forwarded to coverage_tool after the cocotb runner exits under bazel coverage. {output} is substituted with $COVERAGE_OUTPUT_FILE; {data_files} is expanded into one positional arg per file matched by coverage_data_glob. Only meaningful when coverage_tool is set. | List of strings | optional | [] |
| coverage_data_glob | Shell glob (relative to the cocotb sim's build dir) selecting the raw coverage data files coverage_tool consumes. For Riviera-PRO, **/coverage.acdb matches every per-test ACDB the run produces. Only meaningful when coverage_tool is set. | String | optional | "" |
| coverage_tool | Optional Riviera coverage post-processor. When set AND the test's HDL module is exercised under bazel coverage (via ctx.coverage_instrumented(module)), the rules_cocotb process wrapper invokes this binary after the cocotb runner exits with the coverage_args template (substituting {output} and {data_files}) so it can translate the raw ACDBs into lcov at $COVERAGE_OUTPUT_FILE. Leave unset to ship raw ACDBs under the test outputs dir without an lcov roll-up. | Label | optional | None |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| vsimsa | The vsimsa standalone batch simulator binary. Cocotb's Riviera runner invokes only vsimsa; the rest of the Aldec install (alib/alog/acom/asim engines, libraries, license config) is loaded internally by vsimsa via $RIVIERA_HOME. Attach those install files as data deps on the target you pass here so they're staged alongside the binary. | Label | required |
cocotb_activehdl_sim
Rules
cocotb_activehdl_sim
load("@rules_cocotb//cocotb:cocotb_activehdl_sim.bzl", "cocotb_activehdl_sim")
cocotb_activehdl_sim(name, env, vcom, vlib, vlog, vsimsa)
A simulator configuration for running Aldec Active-HDL simulations in cocotb tests.
Status
Infrastructure only. Active-HDL is commercial, with no BCR module and
no redistributable binary; rules_cocotb cannot validate this rule in
CI. Wire it up downstream by pointing the binary attrs at your own
install and registering a cocotb_toolchain that routes
sim = "activehdl" through this rule. Cocotb's runner handles the
actual build/sim via Runner.build / Runner.test.
Downstream wiring
The pattern matches cocotb_riviera_sim — wrap the installed vlib,
vlog, vcom, and vsimsa binaries via a local repository, then:
load("@rules_cocotb//cocotb:cocotb_activehdl_sim.bzl", "cocotb_activehdl_sim")
load("@rules_cocotb//cocotb:cocotb_toolchain.bzl", "cocotb_toolchain")
cocotb_activehdl_sim(
name = "cocotb_activehdl",
vlib = "@activehdl//:vlib",
vlog = "@activehdl//:vlog",
vcom = "@activehdl//:vcom",
vsimsa = "@activehdl//:vsimsa",
)
cocotb_toolchain(
name = "my_cocotb_toolchain",
cocotb = "//path/to:cocotb_py_library",
simulators = {":cocotb_activehdl": "activehdl"},
)
Register the toolchain in MODULE.bazel ahead of //cocotb/toolchain
and use cocotb_test(sim = "activehdl", ...).
Active-HDL accepts both Verilog/SystemVerilog (VerilogInfo) and VHDL
(VhdlInfo) modules.
ATTRIBUTES
| Name | Description | Type | Mandatory | Default |
|---|---|---|---|---|
| name | A unique name for this target. | Name | required | |
| env | Environment variables to set when the cocotb runner invokes this simulator at test time (license-server pointers, install root vars, …). Precedence: toolchain env < sim env < rule-level cocotb_test(env = ...). | Dictionary: String -> String | optional | {} |
| vcom | The vcom VHDL compiler binary. | Label | required | |
| vlib | The vlib library manager binary. | Label | required | |
| vlog | The vlog Verilog compiler binary. | Label | required | |
| vsimsa | The vsimsa batch simulation runner binary. | Label | required |