This directory contains a basic sample testbench in C++ for testing correctness of some CS registers implemented in Ibex.
It is a work in progress and only tests a handful of registers, and is missing many features.
(from this directory)
Verilator version:
make TOOL=verilator ./build/lowrisc_ibex_tb_cs_registers_0/sim-verilator/Vtb_cs_registers
VCS version:
make TOOL=vcs ./build/lowrisc_ibex_tb_cs_registers_0/sim-vcs/lowrisc_ibex_tb_cs_registers_0
tb/tb_cs_registers.sv - Is the verilog top level, it instantiates the DUT and DPI calls
tb/tb_cs_registers.cc - Is the C++ top level, it sets up the testbench components
driver/ - Contains components to generate and drive random register transactions
env/ - Contains components to generate and drive other signals
model/ - Contains a model of the register state and checking functions
The testbench relies on DPI calls to interface between the RTL and the C++ driver/checker components. This methodology allows the testbench to support both Verilator and commercial simulators.
Each DPI call has a function in SV (which is called in the SV top-level), and a corresponding C function. To support the instantiation of multiple instances of TB components, some DPI modules can register their objects referenced by name. Each DPI call from the RTL then calls into the correct instance by matching the name.
The driver component contains one DPI “interface” to drive new random transactions into the DUT, and another to monitor issued transactions including the DUT's responses. Each time a new transaction is detected by the monitor component, it is captured and sent to the model. The model reads incoming transactions, updates its internal state and checks that the DUT outputs matches its own predictions.