Examples¶
Basic counter test¶
# test_counter.py
def test_counter_basic(test_session):
test_session.run(test_module="cocotb_counter")
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv
Parametrised tests¶
Combine pytest.mark.parametrize with test_session to run the same
cocotb testbench against different configurations:
import pytest
@pytest.mark.parametrize("width", [8, 16, 32])
def test_counter_widths(test_session, width):
test_session.run(
test_module="cocotb_counter",
parameters={"WIDTH": width},
)
Each parametrised variant gets its own output directory automatically.
Overriding test_module in run()¶
The test_session fixture derives test_module from the test file’s
module name by default. Override it to point at a different cocotb module:
def test_with_custom_module(test_session):
test_session.run(test_module="my_other_cocotb_tests")
Using --waves¶
Enable waveform dumping for a debugging session:
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv --waves
When --waves is enabled the build is placed in a separate build_waves/
directory, so you can switch between wave and non-wave runs without triggering
a rebuild.
Using --defines¶
Pass preprocessor defines as name/value pairs:
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv \
--defines WIDTH 16 --defines DEPTH 32
Using --parameters¶
Pass HDL parameters (Verilog generics) as name/value pairs. The plugin
passes these directly to runner.build(parameters={...}), so the cocotb
runner formats them correctly for the target simulator (e.g. -GNAME=VALUE
for Verilator):
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv \
--parameters WIDTH 16 --parameters ItcmInitFile firmware.vmem
This is the recommended way to set string parameters. Unlike --build-args,
values are not passed through shlex.split, so no quoting issues arise.
Using --filelist¶
Point at a .f filelist instead of listing source files individually:
pytest --simulator verilator --hdl-toplevel counter --filelist sources.f
The filelist path is resolved to absolute before being passed as -f <path>
to the simulator build command, so relative paths in pytest.ini work
correctly.
Using --includes¶
Add include directories for \`include directives:
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv \
--includes rtl/includes --includes rtl/common
Using --build-args¶
Pass extra arguments to the simulator build step. Arguments are shlex-split, so quoting works as expected:
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv \
--build-args "--trace-fst" --build-args "-Wno-fatal"
Using --regress¶
Create a timestamped output directory for each run, useful for regression tracking:
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv --regress
This produces a layout like sim_build/20250101_120000/build/ instead of
sim_build/build/.
Using --modules¶
Load environment modules before simulation (useful on HPC clusters):
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv \
--modules verilator/5.024
See HPC support for more details on HPC integration.
Setting defaults in conftest.py¶
Rather than repeating CLI flags, you can set defaults in conftest.py:
# conftest.py
def pytest_addoption(parser):
"""Override defaults for this project."""
parser.addini("simulator", default="verilator")
parser.addini("hdl_toplevel", default="counter")
Or more commonly, use addopts in pyproject.toml:
[tool.pytest.ini_options]
addopts = "--simulator verilator --hdl-toplevel counter --sources rtl/counter.sv"
Log file behaviour¶
When pytest output capture is active (the default), the test_session
fixture automatically sets log_file to <test_dir>/sim.log. This
captures all simulator output to a file.
To disable capture and see simulator output live, run with -s:
pytest -s --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv
You can also provide a custom log file path in run():
def test_counter_basic(test_session):
test_session.run(
test_module="cocotb_counter",
log_file="custom.log", # relative to the test directory
)