Skip to content

Verilator Testbench

7FM edited this page Aug 22, 2021 · 5 revisions

For examining internal signals it can be useful to debug the core in a simulated environment. The following sections describe how to setup a system where gdb can be used to communicate with a simulated version of the core. The setup is similar to the one shown in this diagram. However, instead of the TaPaSCo Application forwarding the signals to the AXI interface of a live device, they are sent to the Verilator simulated core.

Building & Installing Verilator in place

  1. Building Verilator in place
    • git clone https://github.com/verilator/verilator.git
    • cd verilator
    • export VERILATOR_ROOT=`pwd`
    • autoconf
    • ./configure
    • make -j$(nprocs)
    • cd ..
  2. Add the compiled Verilator binaries to your PATH
    • export PATH=`pwd`/verilator/bin:$PATH
  3. Check the selected C++ standard in verilator/include/verilated.mk:
    • to build the testbench at least the C++17 standard is required -> modify CFG_CXXFLAGS_STD_NEWEST accordingly if an older standard is set, i.e. change -std=gnu++14 to -std=gnu++17

Build & Run the SCR1 or CVA6 Verilator Testbench

  1. Build & install Verilator
  2. Install OpenOCD & C Cap'n Proto
  3. Set CAPN_PATH: i.e. export CAPN_PATH=`pwd`/c-capnproto
  4. Compile Testbench
    • cd tapasco-riscv/debugging/logdbg
    • cd scr1_sim or cd cva6_sim
    • make preparebuild
    • make sim
  5. Start testbench: ./sim_build/scr1_top_tb_axi_dmi/Vscr1_top_tb_axi_dmi -o or ./sim_build/ariane_custom_tb_top/Variane_custom_tb_top -o
  6. Connect with OpenOCD to the created socket /tmp/riscv-debug.sock
  7. Start debugging with i.e. gdb
  8. When done: stop the testbench with CTRL+C

Testbench Options

Option Description
-o Start socket /tmp/riscv-debug.sock for patched OpenOCD
-t <trace.vcd> Create a gtkwave compatible .vcd trace of the debug session
-v <N> Set the verbosity level. Currently unused.
-s <N> Set count of cycles to execute before recording a trace or starting the socket for OpenOCD. Should not be required.

Reuse the Makefile for other cores

The used Makefiles for the simulation is quite versatile and should be "easy" to adapt for other cores too. However, there are some pitfalls and naming conventions.

  1. To adapt the Makefile for a new core, specify the following settings as required: SRC, SRC_FILES, SRC_PREFIX, ADD_SRCS, INCLUDE_DIR, DEFAULT_TOP_MODULE and V_FLAGS.
  2. Change the make target preparebuild to get the sources for the new core

Naming conventions

By default the following folder structure is assumed:

  • debugging/logdbg/: root of all core simulations, i.e. for CVA6 and SCR1
  • debugging/logdbg/common: folder containing code that is required by all simulation, i.e. the openocd interface
  • debugging/logdbg/*/: core simulation folder, where * is i.e. cva6_sim

Conventions within a core simulation folder, in the following cva6_sim is used as example:

  • cva6_sim/Makefile: location of the makefile, may not be changed else relative paths to the common folder break

  • cva6_sim/sim_src: directory that contains the C++ verilator testbenches/simulations for different top modules

  • cva6_sim/sim_src/sim_*.cpp: C++ code for the simulation of a top module named *

    • i.e. the file sim_ariane_custom_tb_top.cpp corresponds to the SystemVerilog top module ariane_custom_tb_top
    • if a simulation needs dedicated C++ files that are not shared, then they can be placed inside in the subdirectory named as the module itself: i.e for the top module ariane_custom_tb_top the folder cva6_sim/sim_src/ariane_custom_tb_top should be used
  • cva6_sim/sim_build: root build directory for the simulations, may be changed via V_DIR and ensures out of tree builds. Creates a subfolder for each simulation top module: i.e. cva6_sim/sim_build/ariane_custom_tb_top/

  • the make targets are named accordingly: make sim_ariane_custom_tb_top to run the simulation for the top module ariane_custom_tb_top. If only one top module is present you can also set it as DEFAULT_TOP_MODULE in the Makefile (i.e. DEFAULT_TOP_MODULE := ariane_custom_tb_top) and just call make sim.

Expected simulation top module ports:

General interface:

  • clk: input clock signal
  • rst_n: low active reset signal

Debug module interface:

  • dmi_req: issue request signal, high active
  • dmi_wr: signal to indicate whether the request is a write (set to high) or a read (set to low) request
  • dmi_addr: address port, for both read & write requests
  • dmi_wdata: write data port

Pitfalls

Generally the order in which the source files are listed should not matter. However, this changes as soon as the SystemVerilog Interfaces are used. Verilator requires the definition of the interfaces before they are used in other sources. Hence, files with interfaces should be listed first to avoid compilation problems.

Reuse a verilator simulation

If you want to reuse i.e. the verilator simulation file cva6_sim/sim_src/sim_ariane_custom_tb_top.cpp for another top module top_x (not necessarily the same core), then consider the following:

  1. Ensure that the naming conventions & top module ports are met
  2. change #define TOP_MODULE Variane_custom_tb_top to #define TOP_MODULE Vtop_x
  3. change #include "Variane_custom_tb_top.h" to #include "Vtop_x.h"
  4. change #include "Variane_custom_tb_top__Syms.h" to #include "Vtop_x__Syms.h"