CVA6 - Verilator model and VCD generation
Introduction
CVA6 is a processor from the OpenHW Group: 64-bit, Linux-capable and written in SystemVerilog.
Requirements
In order to generate a CVA6 model with export, Verilator must be installed from sources as the Makefile requires a C++ file https://github.com/pcotret/cva6/blob/vcd_patch/Makefile#L551. For this tutorial, Verilator 4.110 was chosen as it is used in the official CI flow.
git clone https://github.com/verilator/verilator
cd verilator
git pull
git checkout v4.110
export VERILATOR_ROOT=`pwd`
autoconf
./configure
make -j$(nproc)
Verilator binaries are generated in <verilator_cloned_repo/bin>
and must be added to PATH
.
Environment variables
export VERILATOR_ROOT=<verilator_cloned_repo>
: path for C++ files required to generate a VCD-capable model.export CVA6_REPO_DIR=<cva6_cloned_repo>
: CVA6 repository.export RISCV=<riscv_toolchain>
: RISC-V toolchain.export PATH=<verilator_cloned_repo>/bin:$PATH
: Verilator binaries added toPATH
.
Verilator model
It is assumed you have cloned the CVA6 repository and its submodules.
make verilate DEBUG=1 TRACE_FAST=1
The model is generated at: work-ver/Variane_testharness
. Please note that make verilate
will generate a model without VCD if needed.
Default simulation
./work-ver/Variane_testharness riscv-tests/isa/rv64ui-p-add
Simulation and VCD exploitation
./work-ver/Variane_testharness -v rv64ui-p-add.vcd riscv-tests/isa/rv64ui-p-add
-v
specifies the name of the VCD file.
Binaries support
Bare metal binaries generated from https://github.com/riscv-software-src/riscv-tests should work without modifications.
Example of CVA6 and GTKWave on a simple test
cd work-ver
./Variane_testharness -v rv64ui-p-add.vcd riscv-tests/isa/rv64ui-p-add
gtkwave rv64ui-p-add.vcd
Let’s say we want to analyze/check the tests 3 and 4 of rv64ui-p-add
.
In GTKWave, we will watch:
- The instruction address.
- The instruction value.
- Register addresses (
rs1
,rs2
andrd
as we check a R-type instruction). - Result of the ALU.
Reading the dump of the test, we will look at this part:
000000008000010c <test_3>:
8000010c: 00100093 li ra,1
80000110: 00100113 li sp,1
80000114: 00208733 add a4,ra,sp
80000118: 00200393 li t2,2
8000011c: 00300193 li gp,3
80000120: 4c771463 bne a4,t2,800005e8 <fail>
0000000080000124 <test_4>:
80000124: 00300093 li ra,3
80000128: 00700113 li sp,7
8000012c: 00208733 add a4,ra,sp
80000130: 00a00393 li t2,10
80000134: 00400193 li gp,4
80000138: 4a771863 bne a4,t2,800005e8 <fail>
TEST_RR_OP( 3, add, 0x00000002, 0x00000001, 0x00000001 );
TEST_RR_OP( 4, add, 0x0000000a, 0x00000003, 0x00000007 );
Signals observed in GTKWave
Note: sometimes, it’s helpful to have the Vivado project opened. Much easier to explore the CPU hierarchy
TOP.ariane_testharness.i_ariane.i_cva6.id_stage_i.fetch_entry_i.address[63:0]
TOP.ariane_testharness.i_ariane.i_cva6.id_stage_i.fetch_entry_i.instruction[31:0]
TOP.ariane_testharness.i_ariane.i_cva6.id_stage_i.decoder_i.instr.rtype.rs1[19:15]
TOP.ariane_testharness.i_ariane.i_cva6.id_stage_i.decoder_i.instr.rtype.rs2[24:20]
TOP.ariane_testharness.i_ariane.i_cva6.id_stage_i.decoder_i.instr.rtype.rd[11:7]
TOP.ariane_testharness.i_ariane.i_cva6.ex_stage_i.alu_i.result_o[63:0]
RISC-V register values can be found at: https://en.wikichip.org/wiki/risc-v/registers
Test 3 1+1=2
- reg(@1)+reg(@2)=reg(@E)
- Values: 1 + 1 = 2
- 895 ps :
rs1
operand - 897 ps : it should be
rs2
operand. However, as it’s equal tors1
, nothing is generated - 899 ps :
rd
operand
Test 4 3+7=0xA
- reg(@1)+reg(@2)=reg(@E)
- Values: 3 + 7 = 0xA
- 917 ps :
rs1
operand - 919 ps :
rs2
operand - 921 ps :
rd
operand