Quickstart¶
pytest-cocotb is a pytest plugin that lets you drive cocotb HDL simulations from pytest. HDL is compiled once per session, and each test function launches the simulator with its own cocotb test module.
Installation¶
pip install -e .
Minimal example¶
Given a simple counter RTL file rtl/counter.sv:
module counter (
input logic clk,
input logic rst,
output logic [7:0] count
);
always_ff @(posedge clk)
if (rst) count <= '0;
else count <= count + 1;
endmodule
Write a cocotb testbench in cocotb_counter.py:
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
@cocotb.test()
async def counter_basic(dut):
clock = Clock(dut.clk, 10, unit="ns")
cocotb.start_soon(clock.start())
dut.rst.value = 1
for _ in range(3):
await RisingEdge(dut.clk)
dut.rst.value = 0
await RisingEdge(dut.clk)
prev = int(dut.count.value)
await RisingEdge(dut.clk)
curr = int(dut.count.value)
assert curr == prev + 1
Then write a pytest test that uses the test_session fixture:
def test_counter_basic(test_session):
test_session.run(test_module="cocotb_counter")
Single-file tests¶
The test_session fixture defaults test_module to the current pytest
file’s __name__. This means you can put cocotb coroutines and pytest
tests in the same file and omit the test_module argument entirely:
# test_counter.py
import cocotb
from cocotb.clock import Clock
from cocotb.triggers import RisingEdge
@cocotb.test()
async def counter_basic(dut):
clock = Clock(dut.clk, 10, unit="ns")
cocotb.start_soon(clock.start())
dut.rst.value = 1
for _ in range(3):
await RisingEdge(dut.clk)
dut.rst.value = 0
await RisingEdge(dut.clk)
prev = int(dut.count.value)
await RisingEdge(dut.clk)
curr = int(dut.count.value)
assert curr == prev + 1
def test_counter(test_session):
test_session.run() # uses this file as the cocotb test module
Running¶
pytest --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv
Setting defaults¶
To avoid repeating CLI flags on every invocation, add them to addopts in
any of pytest’s configuration files.
pytest.ini¶
[pytest]
addopts = --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv
pyproject.toml¶
[tool.pytest.ini_options]
addopts = "--simulator verilator --hdl-toplevel counter --sources rtl/counter.sv"
setup.cfg¶
[tool:pytest]
addopts = --simulator verilator --hdl-toplevel counter --sources rtl/counter.sv