This repository explores writing cocotb-style tests in modern C++, using coroutines and strong typing, with the goal of maintaining a Python-like test style while potentially improving simulation performance.
Project also iclude demonstration of Python nanobind wrapper enables seamless top-level test control from Python while using high-performance C++ underneath.
Thanks to recent changes to cocotb (shoutout to @ktbarrett), it is now possible to build directly against the GPI interface.
#include <cocotb.h>
using namespace cocotb;
COCOTB_TEST(test_dff)
task<> test_dff(Dut &dut) {
dut["d"].value = 0;
auto clk = start_soon(Clock(dut, 10, unit::us));
co_await RisingEdge(dut["clk"]);
dut["d"].value = 1;
co_await RisingEdge(dut["clk"]);
assert(dut["q"].value == 0, "q should be 0");
}You need a supported simulator (currently tested with Icarus Verilog), Python with cocotb master, and a C++20-capable compiler.
pip install https://github.com/cocotb/cocotb/archive/refs/heads/master.zipBuild the C++ test shared library (requires C++20):
g++ -shared -std=c++20 -fPIC -O3 \
-I./src -I$(cocotb-config --share)/include \
tests/test_dff.cpp src/cocotb_core.cpp \
-o lib_dff.soCompile the Design:
iverilog -g2012 tests/dff.sv -o dff.vvpSet GPI_USERS (loads the C++ shared library and registers the cocotb entry point) and run simulation:
GPI_USERS=./lib_dff.so,cocotb_entry_point vvp -M $(cocotb-config --lib-dir) -m $(cocotb-config --lib-name vpi icarus) dff.vvpExpected Output:
-.--ns INFO gpi ../gpi/GpiCommon.cpp:231 in gpi_load_users Running entry func 'cocotb_entry_point' from loaded library './lib_dff.so'
-.--ns INFO gpi ./src/cocotb.h:1017 in cocotb_entry_point Entry point registered
-.--ns INFO gpi ./src/cocotb.h:957 in on_sim_start Start of simulation
0.00ns INFO cocotb.regression Running tests
0.00ns INFO cocotb.regression running test_dff (1/2)
0.00ns INFO cocotb Starting test_dff coroutine
115000.00ns INFO cocotb test_dff completed successfully
115000.00ns INFO cocotb.regression test_dff passed execution time: 0.000 s
115000.00ns INFO cocotb.regression running test_dff_post (2/2)
135940.00ns INFO cocotb.regression test_dff_post passed execution time: 0.000 s
135940.00ns INFO cocotb.regression ***************************************************************************************
135940.00ns INFO cocotb.regression ** TEST STATUS REAL TIME (s) **
135940.00ns INFO cocotb.regression ***************************************************************************************
135940.00ns INFO cocotb.regression ** test_dff PASS 0.000 **
135940.00ns INFO cocotb.regression ** test_dff_post PASS 0.000 **
135940.00ns INFO cocotb.regression ***************************************************************************************
135940.00ns INFO cocotb.regression ** TESTS=2 PASS=2 FAIL=0 **
135940.00ns INFO cocotb.regression ***************************************************************************************
You can find more examples and tests in the tests folder.
Install in editable mode:
pip install -e .Install the AXI extension project:
pip install -e examples/axil_extThen run the Python + C++ AXI-Lite path:
pytest -q examples/axil_ext/tests/test_axil_ext.pyThe AXI-Lite extension is intentionally separated as an example of a user-defined cocotb-cpp extension:
examples/axil_ext
This is the reference pattern for adding custom C++ drivers/monitors and exposing them to Python.
Run the core cocotb-cpp tests (tests/):
nox -s testsRun the AXI extension tests (examples/axil_ext/tests/):
nox -s axil_ext_testsThe following table compares simulation runtime for the reference AXI-Lite memory test (tests/axil.sv, random access, 1,000,000 writre/read transactions) with different cocotb/cocotb-cpp configurations. All results measured with Icarus Verilog 12.0 on the same machine.
| Approach | Execution Time | Speedup vs cocotb |
|---|---|---|
| cocotb | 53.67s | 1.00x |
| cocotb-cpp | 12.63s | 4.25x |
| cocotb-cpp + Python | 31.42s | 1.71x |
| cocotb-cpp + axil-cpp + Python | 17.52s | 3.01x |
- cocotb: Standard Python-based cocotb testbench/driver (
tests/test_axil.py). - cocotb-cpp: Testbench, driver, and transaction logic implemented fully in C++ with cocotb-cpp API (
tests/test_axil.cpp). - cocotb-cpp + Python : Python test via cocotb-cpp bridge (
tests/test_axil.py) - cocotb-cpp + axil-cpp + Python : Mixed testbench, C++ driver invoked from Python test via cocotb-cpp bridge with AXI transtions in C++ (
examples/axil_ext/tests/test_axil_ext.py).
This is an experimental playground. APIs, build steps, and cocotb compatibility may change without notice.
Parts of code generated by LLMs.