# CVA6 - Verilator model and VCD generation


## Introduction

CVA6 is a processor from the [OpenHW Group](https://github.com/openhwgroup/cva6): 64-bit, Linux-capable and written in SystemVerilog. 

```bash
git clone https://github.com/openhwgroup/cva6
cd cva6
git submodule update --init --recursive
```

## Toolchain

Then, you need a toolchain as explained [here](https://github.com/openhwgroup/cva6/blob/master/util/toolchain-builder/README.md). Just follow the **Prerequisites** and **Getting started** sections in `util/toolchain-builder` directory.

## Simulators

```bash
cd <cva6_repo_root>
cd verif/regress
# Install Verilator
./install-verilator.sh
# Install Spike
./install-spike.sh
```

## Standalone simulations

```bash
# Toolchain path
$ export RISCV=/opt/riscv_cva6
# Set environment variables
$ source verif/sim/setup-env.sh
# If needed
# export NUM_JOBS=
# Which simulator to be used, Verilator here
$ export DV_SIMULATORS=veri-testharness
# Launch default hello world simulation for cv32a65x variant
$ cd ./verif/sim
```

### Default simulation - Hello world

```bash
$ python3 cva6.py --target cv32a65x --iss=$DV_SIMULATORS --iss_yaml=cva6.yaml \
--c_tests ../tests/custom/hello_world/hello_world.c \
--linker=../../config/gen_from_riscv_config/linker/link.ld \
--gcc_opts="-static -mcmodel=medany -fvisibility=hidden -nostdlib \
-nostartfiles -g ../tests/custom/common/syscalls.c \
../tests/custom/common/crt.S -lgcc \
-I../tests/custom/env -I../tests/custom/common"
GCC Version: 13.1.0
Spike Version: 1.1.1-dev 60e57248
Verilator Version: Verilator 5.008 2023-03-04 rev v5.008 (mod)
Creating output directory: /home/user/cva6/verif/sim/out_2025-07-25

Iteration number: 1
Compiling test: ../tests/custom/hello_world/hello_world.c
Compilation cmd: /opt/riscv_cva6/bin/riscv-none-elf-gcc ../tests/custom/hello_world/hello_world.c               -I/home/user/cva6/verif/sim/dv/user_extension                 -T../../config/gen_from_riscv_config/linker/link.ld -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g ../tests/custom/common/syscalls.c ../tests/custom/common/crt.S -lgcc -I../tests/custom/env -I../tests/custom/common -o /home/user/cva6/verif/sim/out_2025-07-25/directed_tests/hello_world.o  -march=rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei -mabi=ilp32
Processing ISS setup file: cva6.yaml
Found matching ISS: veri-testharness
Target: cv32a65x
ISA rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
/home/user/cva6/verif/sim/out_2025-07-25/directed_tests/hello_world.o
[veri-testharness] Running ISS simulation: make veri-testharness target=cv32a65x variant=rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei elf=/home/user/cva6/verif/sim/out_2025-07-25/directed_tests/hello_world.o path_var=/home/user/cva6/ tool_path=/home/user/cva6/tools/spike/bin isscomp_opts="" issrun_opts="+debug_disable=1 +ntb_random_seed=787586395" isspostrun_opts="0x0000000080000000" log=/home/user/cva6/verif/sim/out_2025-07-25/veri-testharness_sim/hello_world.cv32a65x.log &> /home/user/cva6/verif/sim/out_2025-07-25/veri-testharness_sim/hello_world.cv32a65x.log.iss
[veri-testharness] Running ISS simulation: /home/user/cva6/verif/sim/out_2025-07-25/directed_tests/hello_world.o ...done
Processing ISS setup file: cva6.yaml
Found matching ISS: veri-testharness
Target: cv32a65x
ISA rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
veri-testharness sim log dir: /home/user/cva6/verif/sim/out_2025-07-25/veri-testharness_sim
```

### Simulation and VCD exploitation

Before launching the Python script, you just need to `export TRACE_FAST=1`

```bash
$ export TRACE_FAST=1
$ python3 cva6.py --target cv32a65x --iss=$DV_SIMULATORS --iss_yaml=cva6.yaml \
--c_tests ../tests/custom/hello_world/hello_world.c \
--linker=../../config/gen_from_riscv_config/linker/link.ld \
--gcc_opts="-static -mcmodel=medany -fvisibility=hidden -nostdlib \
-nostartfiles -g ../tests/custom/common/syscalls.c \
../tests/custom/common/crt.S -lgcc \
-I../tests/custom/env -I../tests/custom/common"
```

It will generate a VCD file in `out_2025-07-25/veri-testharness_sim` which can be analyzed with GTKWave.

### Default simulation - Assembly test

#### Running the script

```bash
$ export TRACE_FAST=1
$ python3 cva6.py --target cv32a65x --iss=$DV_SIMULATORS --iss_yaml=cva6.yaml \
--asm_tests ../tests/custom/hello_world/custom_test_template.S \
--linker=../../config/gen_from_riscv_config/linker/link.ld \
--gcc_opts="-static -mcmodel=medany -fvisibility=hidden -nostdlib \
-nostartfiles -g ../tests/custom/common/syscalls.c \
../tests/custom/common/crt.S -lgcc \
-I../tests/custom/env -I../tests/custom/common"
GCC Version: 13.1.0
Spike Version: 1.1.1-dev 60e57248
Verilator Version: Verilator 5.008 2023-03-04 rev v5.008 (mod)
Creating output directory: /home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25

Iteration number: 1
Compiling test: ../tests/custom/hello_world/custom_test_template.S
Compilation cmd: /opt/riscv_cva6/bin/riscv-none-elf-gcc ../tests/custom/hello_world/custom_test_template.S               -I/home/pascal/Documents/ensta/work/test/cva6/verif/sim/dv/user_extension                 -T../../config/gen_from_riscv_config/linker/link.ld -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g ../tests/custom/common/syscalls.c ../tests/custom/common/crt.S -lgcc -I../tests/custom/env -I../tests/custom/common -o /home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/directed_tests/custom_test_template.o  -march=rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei -mabi=ilp32
Processing ISS setup file: cva6.yaml
Found matching ISS: veri-testharness
Target: cv32a65x
ISA rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
/home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/directed_tests/custom_test_template.o
[veri-testharness] Running ISS simulation: make veri-testharness target=cv32a65x variant=rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei elf=/home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/directed_tests/custom_test_template.o path_var=/home/pascal/Documents/ensta/work/test/cva6/ tool_path=/home/pascal/Documents/ensta/work/test/cva6/tools/spike/bin isscomp_opts="" issrun_opts="+debug_disable=1 +ntb_random_seed=313885687" isspostrun_opts="0x0000000080000000" log=/home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/veri-testharness_sim/custom_test_template.cv32a65x.log &> /home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/veri-testharness_sim/custom_test_template.cv32a65x.log.iss
[veri-testharness] Running ISS simulation: /home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/directed_tests/custom_test_template.o ...done
Processing ISS setup file: cva6.yaml
Found matching ISS: veri-testharness
Target: cv32a65x
ISA rv32imc_zba_zbb_zbs_zbc_zicsr_zifencei
veri-testharness sim log dir: /home/pascal/Documents/ensta/work/test/cva6/verif/sim/out_2025-07-25/veri-testharness_sim

```

#### Waveform analysis

todo





## Example of CVA6 and GTKWave on a simple test

```bash
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`](https://github.com/riscv-software-src/riscv-tests/blob/master/isa/rv64ui/add.S#L21-L22).

In GTKWave, we will watch:

- The instruction address.
- The instruction value.
- Register addresses (`rs1`, `rs2` and `rd` as we check a R-type instruction).
- Result of the ALU.

Reading the dump of the test, we will look at this part:

```bash
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>
```

```bash
  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

![](../img/test3.jpg)

- 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 to `rs1`, nothing is generated

- 899 ps : `rd` operand
  
  ### Test 4 3+7=0xA
  
  ![](../img/test4.jpg)

- reg(@1)+reg(@2)=reg(@E)

- Values:  3 + 7 = 0xA

- 917 ps : `rs1` operand

- 919 ps : `rs2` operand

- 921 ps : `rd` operand

