CORE-V-VERIF Quick Start Guide

Many people who come to CORE-V-VERIF for the first time are anxious to ‘get something running’ and this section is written to satisfy that itch.

Note: in several places in this chapter a reference is made to $CORE_V_VERIF. This is used as short hand for the absolute path to your local working directory. You will not need to set this shell environment variable yourself.

A good place to start is the CV32E40P core testbench since the CV32E40P is mature, and the core testbench is very simple and runs with open-source tools. You will need:

  1. A Linux machine (CORE-V-VERIF has been successfully run under Ubuntu, Debian and CentOS).

  2. Python3 and a set of plug-ins. The current plug-in list is kept in $CORE_V_VERIF/bin/requirements.txt.

  3. A GCC cross-compiler (aka “the Toolchain”). Even if you already have a RISC-V toolchain, please do follow that link and read for recommended ENV variables to point to it.

  4. Verilator.

An easy way to get the Python plug-ins installed on your machine is:

$ git clone $CORE_V_VERIF
$ cd $CORE_V_VERIF/bin
$ pip3 install -r requirements.txt

Note: Virtual python environments can be used if desired.

Once the above is in place type the following:

$ cd $CORE_V_VERIF/cv32e40p/sim/core
$ make

Note: Check the required shell environment variables (variables).

The above will compile the RTL and the core testbench using Verilator, compile the ‘hello-world’ test-program using the Toolchain and run it on the “Verilated” model. The simulation run should produce the following:

This is the OpenHW Group CV32E40P CORE-V processor core.
CV32E40P is a RISC-V ISA compliant core with the following attributes:
    mvendorid = 0x602
    marchid   = 0x4
    mimpid    = 0x0
    misa      = 0x40001104
    XLEN is 32-bits
    Supported Instructions Extensions: MIC

The README in the cv32e40p/sim/core directory will explain how to run other tests and use other simulators.

Where is the RTL?

As CORE-V-VERIF is a single repository for the verification of several different CORE-V cores, you will not find the RTL here. Each CORE-V core is managed in its own repository, and is automatically cloned into $CORE_V_VERIF/core-v-cores/<core_name> by the Makefiles, as needed. If you have successfully run the hello-world test above, then you may have noticed that the RTL was cloned to $CORE_V_VERIF/core-v-cores/cv32e40p/rtl (take a look!). The URL, branch and hash of the cloned RTL is obtained from $CORE_V_VERIF/cv32e40p/sim/ (again, take a look!). You can override these variables on the make command line or by setting shell environment variables.


Up to this point, the discussion has been about the “core” testbench, which is intended as demonstration vehicle only. The primary verification environments implemented in CORE-V-VERIF are all based on the UVM. The UVM enviroment for CV32E40P is completely separate from the core testbench and uses a different set of Makefiles.

In order to use the UVM environments you will need items 1, 2 and 3 from the list above, plus a SystemVerilog simulator capable of supporting the UVM and the Imperas OVPsim Instruction Set Simulator (ISS). You should also review the README in $CORE_V_VERIF/mk for a description of the shell ENV vars used by the UVM environment. With these in place you can do the following:

$ git clone
$ cd core-v-verif/cv32e40p/sim/uvmt
$ make test TEST=hello-world CV_SIMULATOR=<xrun|vcs|vsim|riveria|dsim>

The above will compile the RTL and the UVM testbench using the selected simulator and run the ‘hello-world’ test-program. Note that this is the same test-program as was used in the core testbench example above. The simulation run will produce similar results, with lots of additional UVM messaging.

If you do not have access to the Imperas ISS you can disable it at run-time:

$ make test TEST=hello-world CV_SIMULATOR=<xrun|vcs|vsim|riveria|dsim> USE_ISS=NO

Why UVM?

There are three reasons why the UVM was selected as the verification methodology used by CORE-V-VERIF:

  1. Using a standard methodology provides a common framework making it practical for verification IP from multiple and diverse teams to inter-operate.

  2. To date, all of the cores in the OpenHW Group CORE-V family are implemented in SystemVerilog and the SystemVerilog implementation of the UVM is both complete and robust.

  3. CORE-V-VERIF was specifically created to bring industrial practises to bear for CORE-V verification, and the UVM is the most popular simulation verification methodology used in industry today.

Do I need an ISS?

The short answer is yes. CORE-V-VERIF uses an Instruction Set Simulator (ISS) as a reference model of the CORE-V core (the Device Under Test). A key feature of the CORE-V-VERIF UVM environments is that the state of the DUT is compared to the state of the reference model after each instruction is retired. Without a comparison to a reference model, the pass/fail status of a given simulation is mostly vacuous.

There are several popular options for a RISC-V ISS, including Spike, Whisper and Imperas OVPsim. Both Spike and Whisper are open-source ISS models. At the time of this update (2022-11-08) CORE-V-VERIF uses a commercial version of Imperas OVPsim for the CV32E4 cores. A contribution to integrate another reference model into CORE-V-VERIF would be welcome.

Doing More in CORE-V-VERIF

As far as is practical, CORE-V-VERIF maintains “in place” documentation. That is, most directries will have a that provides information relavent to that directory and/or its sub-directories. GitHub renders these to HTML automatically, providing easy to read and use content. In keeping with the DRY principle of good documentation, whenever practical this document will point you to an in-place README.

At the top-level of CORE-V-VERIF, there is a subdirectory for each supported core. All of the verification code specific to that core will be in this directory. Look at the README in cv32e40p to get a sense of the directory structure of the cv32e40p-specific testbenches. The structure of the other cores will be similar, but need not be identical.

The cv32e40p sub-tree supports a simple “core” testbench and a complete UVM environment. Partial instructions to run the core testbench are provided above; see the README at $CORE_V_VERIF/cv32e40p/sim/core for full details. To run the CV32E40P UVM environment, go to $CORE_V_VERIF/cv32e40p/sim/uvmt and read the README.

This chapter uses the CV32E40P as its example, but there are equivalent READMEs in directories for the other supported cores.

Supported Simulators

It is a goal of the OpenHW Verification Task Group for core-v-verif to support all known SystemVerilog 1800-2017 compliant simulators. The Makefiles for the UVM environments have a variable CV_SIMULATOR which is used to select the simulator used to compile and run a testcase. So you can run hello-world with Cadence Xcelium like this:

$ make test TEST=hello-world CV_SIMULATOR=xrun

To run the same test with Metrics Dsim:

$ make test TEST=hello-world CV_SIMULATOR=dsim

The variable is used to select one of a set of simulator-specific Makefiles that are located at $CORE_V_VERIF/mk/uvmt.

Note that CORE-V-VERIF tries to support all simulators and this requires support from OpenHW Group members. From time to time a Makefile for a specific simulator will not see a lot of use and will inevidibly suffer from bit-rot. If you notice an issue with a simulator-specific Makefile, please either raise a GitHub issue, or better yet, a pull-request with a fix.

Verifying other Cores

At the time of this update (2022-11-08), CORE-V-VERIF supports verification of multiple CORE-V cores:

  • CV32E40P: the UVM environment is stable and v1.0.0 is complete. Work on v2.0.0 has started. A simple “core” testbench which can be run with open-source tools is available.

  • CV32E40X: the UVM environment is stable, and verification is on-going.

  • CV32E40S: the UVM environment is stable, and verification is on-going.

  • CVA6: the UVM environment is in the early stages of development.

  • CVE2: Coming soon!

CV32E40P Directory Tree (simplified)

Below $CORE_V_VERIF you will find a directory named cv32e40p. This directory contains all of the CV32E40P-specific sources to compile and run simulations on the CV32E40P CORE-V core. The tree below is a somewhat simplified expansion of the directory highlighting the names, locations and purposes of key directories and files. Other cores, e.g. CV32E40X will implement a similar directory tree.

  ├── bsp                                         // Board-support Package
  ├── docs
  │   └── VerifPlans
  ├── env                                         // UVM environment
  │   ├── corev-dv
  │   └── uvme
  │       ├── cov
  │       └── vseq
  ├── regress                                     // Regression configurations
  ├── sim
  │   ├──
  │   ├──
  │   ├── core                                    // Place to run simulations of the "core" testbench
  │   ├──
  │   ├── tools
  │   └── uvmt                                    // Place to run simulations of the "uvm" environment
  │       ├── Makefile
  │       └──
  ├── tb
  │   ├──
  │   ├── core                                    // the "core" testbench
  │   │   ├──
  │   │   ├──
  │   │   ├──
  │   │   ├── tb_top_verilator.cpp
  │   │   └──
  │   └── uvmt                                    // the UVM environment
  │       ├──
  │       ├──
  │       ├── ...
  │       └──
  ├── tests                                       // test-programs and UVM testcases.
  │   ├── cfg
  │   │   ├── default.yaml
  │   │   ├── no_pulp.yaml
  │   │   ├── num_mhpmcounter_29.yaml
  │   │   ├── ovpsim_no_pulp.ic
  │   │   └── pulp.yaml
  │   ├── programs
  │   │   ├── corev-dv                            // configurations for randomly generated test-programs
  │   │   │   ├── corev_rand_arithmetic_base_test
  │   │   │   │   ├── corev-dv.yaml
  │   │   │   │   └── test.yaml
  │   │   |   ├── ...
  │   │   |   |
  │   │   │   └── corev_rand_jump_stress_test
  │   │   │       ├── corev-dv.yaml
  │   │   │       └── test.yaml
  │   │   └── custom                              // "custom" (manually written) test-programs
  │   │       ├── hello-world
  │   │       │   ├── hello-world.c
  │   │       │   └── test.yaml
  │   │       ├── ...
  │   │       |
  │   │       └── debug_test
  │   │           ├── debug_test.c
  │   │           └── test.yaml
  │   └── uvmt                                    // UVM testcase(s) and virtual sequences
  └── vendor_lib                                  // Libraries from third-parties
      ├── google
      ├── imperas
      ├── riscv
      └── verilab