[riscv-vip]  Users’ Guide

Overview        1

License        1

Community        2

Files and directories        2

Instruction Decode Model        3

Core to Coverage plumbing        4

RAW Hazard coverage example        5

Running riscv-vip unit tests        6

Instruction unit tests        6

Instruction History unit tests        8

HEX file analyzer unit tests        8

View the functional coverage of scanning the HEX files        9

Generating the HEX files from source, for the hex_file_analyzer        10

Adding riscv-vip to an existing RISC-V core        11

Update your build process to compile and include riscv-vip files        11

Update your testbench        11

Simulator flags        14

Locating the trace file        14

Overview

For pre-silicon developers of RISC-V systems, the riscv-vip project:

License

The riscv-vip project is licensed under the Apache Version 2.0 license.  

The hex files committed in the riscv-vip/riscv_tests_hexgen/build/ directory are generated from assembly *.S files from the riscv-test project, available at https://github.com/riscv/riscv-tests and licensed under its own license.

Community

Files and directories

The main files and directories are shown in the following table.

riscv-vip/

Root of repo

riscv-vip/LICENSE.txt

Apache License

riscv-vip/README.md

Readme file

riscv-vip/RELEASE.txt

Release notes

riscv-vip/doc/

Documentation dir

riscv-vip/doc/index.html

Open in your web browser for documentation.  Also available at https://jerralph.github.io/riscv-vip/doc/index.html 

riscv-vip/src/

Source folder

riscv-vip/src/csrs.sv

Passive CSR model and white box monitor for CSRs.  Not currently integrated into UVC and model - FUTURE.  

riscv-vip/src/csrs_unit_test.sv

Unit test for csrs.sv

riscv-vip/src/decoder.svh

Decoder class

riscv-vip/src/hex_file_analyzer.svh

Hex file Analyzer class

riscv-vip/src/hex_file_analyzer_unit_test.sv

Hex file Analyzer unit tests

riscv-vip/src/inst_history.svh

Instruction history class and the raw_hazard_examiner class, which covers interesting read after write (RAW) register hazards between instructions.

riscv-vip/src/inst_history_unit_test.sv

Unit tests for inst_history.svh

riscv-vip/src/instruction.svh

Instruction Classes

riscv-vip/src/instruction_unit_test.sv

Instruction unit tests

riscv-vip/src/Makefile

Makefile for running unit tests

riscv-vip/src/pipeline.svh

Passive instruction pipeline model.  Placeholder currently, not much here yet.  Will be used for identifying data hazards, etc. FUTURE.

riscv-vip/src/reg_fetcher.svh

Register file value fetcher. Given an instruction, uses regfile to set the data values of the source registers used by the instruction.

riscv-vip/src/reg_fetcher_unit_test.sv

Regfetcher unit test

riscv-vip/src/regfile.svh

Passive regfile model and white box monitor.

riscv-vip/src/regfile_unit_test.sv

Regfile unit test

riscv-vip/src/riscv_vip_class_pkg.sv

Package of non-UVM classes.

riscv-vip/src/riscv_vip_csr_if.sv

CSR whitebox interface

riscv-vip/src/riscv_vip_defines.svh

`defines

riscv-vip/src/risc_vip.do

Mentor do file

riscv-vip/src/riscv_vip.f

File list

riscv-vip/src/riscv_vip_inst_if.sv

Instruction interface file

riscv-vip/src/riscv_vip_pkg.sv

Package of parameters, types, structures, constants

riscv-vip/src/riscv_vip_regfile_if.sv

Regfile whitebox interface

riscv-vip/src/uvm/

Folder containing UVM related files

riscv-vip/src/uvm/i32_agent.svh

Passive RV32I UVM Agent

riscv-vip/src/uvm/i32_agent_unit_test.sv

Unit test for RV32I UVM agent

riscv-vip/src/uvm/i32_cov_subscriber.svh

RV32I Coverage subscriber

riscv-vip/src/uvm/i32_item.svh

RV32I Transaction item

riscv-vip/src/uvm/i32_monitor.svh

RV32I Passive monitor

riscv-vip/src/uvm/Makefile

Makefile for running tests

riscv-vip/src/uvm/riscv_vip_uvc.f

UVC file list

riscv-vip/src/uvm/riscv_vip_uvc_pkg.sv

UVC package

riscv-vip/src/uvm/uvc_env.svh

UVC environment

riscv-vip/src/uvm/uvc_env_unit_test.sv

UVC environment unit test

riscv-vip/riscv_tests_hexgen/

Dir for building HEX files from riscv-test source.

riscv-vip/riscv_tests_hexgen/build/

Build dir populated by running make

riscv-vip/riscv_tests_hexgen/build/hex_files.txt

List of HEX files for reading in by the hex_file_analyzer class.

riscv-vip/riscv_tests_hexgen/build/*.hex

Pre-committed HEX files for RV32UI tests generated from the riscv-tests project assembly files from https://github.com/riscv/riscv-tests 

riscv-vip/riscv_tests_hexgen/link.ld

Linker script for generating HEX files from riscv-tests assembly.

riscv-vip/riscv_tests_hexgen/Makefile

Makefile for generated HEX files from riscv-tests assembly

Instruction Decode Model

The decoder class decodes raw bits into the riscv-vip instruction decode model.  The instruction class hierarchy is as follows where the specific formats are derived from the general inst32 class.  For simplicity, many methods are omitted from this diagram.

For example, consider the following code:

       decoder decoder0 = new();

       bit[31:0] inst_bits = 32'hfff08193;    

       inst32 i32 = decoder0.decode_inst32(inst_bits);

       $display("decode of 0x%0H is [ %s ]", inst_bits, i32.to_string());

This will display the following output:

 decode of 0xfff08193 is [ fff08193 I ADDI X3_GP, X1_RA, -1 ]

This is an I format add immediate, addi, instruction with an immediate value of -1, using x1 as the source and x3 for the destination register.  For more details on instruction formats and how this is encoded/decoded, refer to the RISC-V specification.

In the inst32_iformat class, there is a coverage bin for non-special I instructions with immediates of -1 (or all 1s in binary), as shown below:

    i32i_imm_cp : coverpoint imm iff ((inst inside {I_NONSPECIAL_INSTS})) {

      bins basics[] = {0,1,2,4};

      bins max_pos =  {`IMM_MAX_POS(imm)};

      bins all_ones = {`IMM_ALL_ONES(imm)};

      bins min_neg =  {`IMM_MIN_NEG(imm)};

    }

Non-special refers to standard I format instructions like ADDI and ANDI.  Non-special I instructions include all I instructions except {SLLI, SRLI, SRAI, FENCE, FENCE.I, ECALL, EBREAK, CSRR*}, which are special -- they have something special/different about them and need to be covered a bit differently.

The following illustrates how coverage is sampled and a generic inst32 is cast to a specific inst32_iformat class:

        //Cast the general inst32 into the more specific inst32_iformat once we're sure it

        //really is an I format.  The coverage should be 0 before sampling then

        //have one bin hit after sampling

        inst32_iformat i32i;        

        assert(i32.is_i_format());

        $cast(i32i,i32);

        cov = i32i.get_nonspecial_imm_cov();

        assert(cov == 0);        

        i32i.sample_cov();

        cov = i32i.get_nonspecial_imm_cov();

        $display("after sample_cov of 0x%0H get_nonspecial_imm_cov() yields %0f", inst_bits, cov);

The resulting output is:

after sample_cov of 0xfff08193 get_nonspecial_imm_cov() yields 14.285714

This is the coverage we expect since 1/7 coverage bins are hit. Such coverage will also show up in the simulator’s coverage database and analysis interfaces.

Core to Coverage plumbing

The riscv-vip monitors attached to the internal interfaces of the RISC-V core RTL to extract the instruction, address, and register values.  From these interfaces, the riscv-vip object model and the instruction history are populated and the contained functional coverage becomes available.  The following diagram illustrates the plumbing in a conceptual, simplified way.

RAW Hazard coverage example

The Instruction History class is used to capture coverage of important inter-instruction cases, like a read-after-write (RAW) hazard.The RAW hazard is when an instruction uses a source register that has a stale value in the register file and its value is in the process of getting updated by an earlier instruction in the pipeline.

Consider the following coverage requirement:

Cross all RV32I instructions that use rs1 and/or rs2 with case they have a read after write (RAW) data hazard, whereby a previous instruction {1,2,3} cycles ago modified the reg that is used by the instruction for {rs1 only, rs2 only, and both rs1/2} cases.  For instructions that only have rs1 ignore the irrelevant bins.

The SystemVerilog code in the inst_history.svh file to achieve this coverage is as follows:

covergroup raw_cg;

    read_inst_cp : coverpoint m_rd_inst.get_inst_enum(){

      ignore_bins ignore_has_no_rs_insts = {`INSTS_WITH_NO_RS_LIST};

      ignore_bins unknown_inst = {UNKNOWN_INST};

    }

    rs_case_cp : coverpoint raw_rs_case iff(raw_rs_case != NONE){

      ignore_bins ignore_none = {NONE};

    }

    cyc_apart_cp : coverpoint m_cycles_apart {

      bins cycs[] = {[1:MAX_CYCLES_APART_OF_INTEREST]};

    }

    inst_x_rs_case_x_cyc_apart : cross read_inst_cp, rs_case_cp, cyc_apart_cp{

      //for insts w/o rs2 fields, only look at the RS1 case (ignore rs2 cases).

      ignore_bins ignore_rs2_for_non_rs2_insts = inst_x_rs_case_x_cyc_apart with

        ( !(read_inst_cp inside {`INSTS_W_RS2_LIST}) && (rs_case_cp != RS1_ONLY) );

    }

}

The read_inst_cp has 37 bins  -- 47 RV32I instruction less 10 ignored since they don’t have source register fields.  

The rs_case_cp has 3 bins -- RS1_ONLY, RS1_ONLY, and RS1ANDRS2;

The cyc_apart_cp has 3 bins, for instructions that are 1, 2 or 3 cycles apart.

The cross, inst_x_rs_case_x_cyc_apart has 225 bins.  19/37 have rs1 and rs2 fields, and 18/37 have only rs2, so the cross multiplies out as 19*3*3 + 18*3*1 = 225.

As an illustrative example, consider the following sequence of instructions and the related coverage coverage report for the inst_x_rs_case_x_cyc_apart cross coverage.

0 401080b3 R SUB X1, X1, X1

1 40210133 R SUB X2, X2, X2

2 403181b3 R SUB X3, X3, X3

3 40420233 R SUB X4, X4, X4

4 005102b3 R ADD X5, X2, X5   ← ADD, RS1_ONLY case, RAW with inst 3 cycles ago

5 00618333 R ADD X6, X3, X6   ← ADD, RS1_ONLY case, RAW with inst 3 cycles ago

6 0052c3b3 R XOR X7, X5, X5   ← XOR, RS1AND2 case,  RAW with inst 2 cycles ago

The expected inst_x_rs_case_x_cyc_apart coverage from the sequence of instructions is 2/225 = 0.88% and the simulator rounds down to the nearest tenth in this case.

Running riscv-vip unit tests

During development, unit testing of riscv-vip is done to improve quality and capture usage examples.  Running and examining the unit tests is a great way to better understand the riscv-vip.  Users can easily create their own unit tests to verify their understanding and the workings of the code.

The unit tests will have names of the form *_unit_test.sv.  SVUnit is used for the unit testing framework, this can be obtained from https://github.com/nosnhojn/svunit-code.  Follow the instructions posted there to install.

Instruction unit tests

The instruction unit tests in the instruction_unit_test.sv file exercise and test the decoder and instruction use- cases and functional coverage.

With SVUnit is installed, the tests are run as follows, assuming you are in the riscv-vip/src directory:

% make inst_ut

By default, this will run using Modelsim.  To run in Cadence ius, append SIMR=ius to the above command.

The output looks like this:

runSVUnit -t instruction_unit_test.sv -s modelsim   -f riscv_vip.f

SVUNIT: Output File: ./.__testsuite.sv

SVUNIT: Creating class __testsuite:

SVUNIT: Creating instances for:

...

-- Compiling module testrunner

Top level modules:

        testrunner

End time: 17:08:06 on Jun 08,2018, Elapsed time: 0:00:00

Errors: 0, Warnings: 2

Reading pref.tcl

# 10.6c

# vsim -c -lib work -do "run -all; quit" -l run.log testrunner

# Start time: 17:08:07 on Jun 08,2018

# ** Note: (vsim-3813) Design is being optimized due to module recompilation...

# ** Warning: hex_file_analyzer.sv(54): (vopt-2252) Missing incrementer in "FOR" statement.

# //  Questa Sim

# //  Version 10.6c linux Jul 25 2017

...

# run -all

# INFO:  [0][__ts]: Registering Unit Test Case inst32_ut

# INFO:  [0][testrunner]: Registering Test Suite __ts

# INFO:  [0][__ts]: RUNNING

# INFO:  [0][inst32_ut]: RUNNING

# INFO:  [0][inst32_ut]: ug_example1::RUNNING

# My addi from code is [ fff08193 I ADDI X3_GP, X1_RA, -1 ]

# INFO:  [0][inst32_ut]: ug_example1::PASSED

# INFO:  [0][inst32_ut]: ug_example2::RUNNING

# decode of 0xfff08193 is [ fff08193 I ADDI X3_GP, X1_RA, -1 ]

# INFO:  [0][inst32_ut]: ug_example2::PASSED

# INFO:  [0][inst32_ut]: test1::RUNNING

# 0ff0a2f3 I CSRRS X5_T0, X1_RA, 255

# 0010a133 R SLT X2_SP, X1_RA, X1_RA

# INFO:  [0][inst32_ut]: test1::PASSED

# INFO:  [0][inst32_ut]: inst32_sformat_cov::RUNNING

# INFO:  [0][inst32_ut]: inst32_sformat_cov::PASSED

# INFO:  [0][inst32_ut]: inst32_uformat_cov::RUNNING

# INFO:  [0][inst32_ut]: inst32_uformat_cov::PASSED

# INFO:  [0][inst32_ut]: inst32_jformat_cov::RUNNING

# INFO:  [0][inst32_ut]: inst32_jformat_cov::PASSED

# INFO:  [0][inst32_ut]: inst32_bformat_cov::RUNNING

# INFO:  [0][inst32_ut]: inst32_bformat_cov::PASSED

# INFO:  [0][inst32_ut]: inst32_iformat_cov::RUNNING

# INFO:  [0][inst32_ut]: inst32_iformat_cov::PASSED

# INFO:  [0][inst32_ut]: store_to_string::RUNNING

# INFO:  [0][inst32_ut]: store_to_string::PASSED

# INFO:  [0][inst32_ut]: PASSED (9 of 9 tests passing)

#

# INFO:  [0][__ts]: PASSED (1 of 1 testcases passing)

#

# INFO:  [0][testrunner]: PASSED (1 of 1 suites passing) [SVUnit v3.26]

# ** Note: $finish    : .testrunner.sv(40)

#    Time: 0 ns  Iteration: 9  Instance: /testrunner

# End time: 17:08:08 on Jun 08,2018, Elapsed time: 0:00:01

# Errors: 0, Warnings: 1

Have a look into the instruction_unit_test.sv file to better understand what is going on here.  

Instruction History unit tests

The instruction history tests are run as follows, assuming you are in the riscv-vip/src directory:

% make ihist_ut

HEX file analyzer unit tests

The unit test for hex_file_analyzer.sv reads in a list of RV32UI HEX files from the riscv-tests project.  It then dumps out the associated riscv-vip trace and also sampled coverage of every instruction in the HEX files.  

The HEX files for RV32UI generated from the riscv-test project are committed to the riscv-vip repository.  These files were generated from the riscv-test assembly files, as described by the Generating the HEX files from source section, below.  These files have been included for convenience so the user doesn’t need to install the riscv-tools project.

Run the test as follows,  assuming you are in the riscv-vip/src directory:

% make hex_ut

Observe a trace output scroll by, like shown below.  

...

# INFO:  [0][hex_file_analyzer_ut]: analyze_hex_files::RUNNING

# 00000000 04c0006f J JAL X0_ZERO, 76

# 00000004 34202f73 I CSRRS X30_T5, X0_ZERO, 834

# 00000008 00800f93 I ADDI X31_T6, X0_ZERO, 8

# 0000000c 03ff0a63 B BEQ X30_T5, X31_T6 52

# 00000010 00900f93 I ADDI X31_T6, X0_ZERO, 9

# 00000014 03ff0663 B BEQ X30_T5, X31_T6 44

# 00000018 00b00f93 I ADDI X31_T6, X0_ZERO, 11

# 0000001c 03ff0263 B BEQ X30_T5, X31_T6 36

# 00000020 00000f17 U AUIPC X30_T5, 0

# 00000024 fe0f0f13 I ADDI X30_T5, X30_T5, -32

# 00000028 000f0463 B BEQ X30_T5, X0_ZERO 8

...

# 000005c8 0011e193 I ORI X3_GP, X3_GP, 1

# 000005cc 00000073 I ECALL X0_ZERO, X0_ZERO, 0

# 000005d0 0ff0000f I FENCE X0_ZERO, X0_ZERO, 255

# 000005d4 00100193 I ADDI X3_GP, X0_ZERO, 1

# 000005d8 00000073 I ECALL X0_ZERO, X0_ZERO, 0

# 000005dc c0001073 I CSRRW X0_ZERO, X0_ZERO, -1024

# INFO:  [0][hex_file_analyzer_ut]: analyze_hex_files::PASSED

# INFO:  [0][hex_file_analyzer_ut]: PASSED (1 of 1 tests passing)

#

# INFO:  [0][__ts]: PASSED (1 of 1 testcases passing)

#

# INFO:  [0][testrunner]: PASSED (1 of 1 suites passing) [SVUnit v3.26]

# ** Note: $finish    : .testrunner.sv(40)

#    Time: 0 ns  Iteration: 1  Instance: /testrunner

# Saving coverage database on exit...

# End time: 18:49:58 on Jun 11,2018, Elapsed time: 0:00:12

# Errors: 0, Warnings: 0

This is essentially the disassembly of each HEX file. These outputs can be cross referenced / checked against the related disassembly *.DUMP file produced the toolchain.  

View the functional coverage of scanning the HEX files

The coverage scored by sampling HEX file instructions can be analyzed.  It’s important to note that this is not the way coverage is typically done in a verif env, yet it is an interesting experiment none-the-less.  Any execution of these HEX programs would cover a subset of all instructions in the file as scored by the file analyzer.  

The most interesting part is what is missing from the HEX file coverage -- this indicates things that cannot possibly be covered by running the program and potential areas where there could be bugs.

Run the following command, assuming you are in the riscv-vip/src directory and using QuestaSim:

% make cov

The Questa GUI should open.  Goto Window > Covergroups to browse the coverage of the different covergroups.   For example, the following shows what instructions were observed.

Generating the HEX files from source, for the hex_file_analyzer

To generate the RV32UI HEX files from the riscv-test project you must have the riscv-tools project installed from https://github.com/riscv/riscv-tools, this contains the needed gcc compiler toolchain and also contains the riscv-tests as a submodule.  The RISCV_TEST environment variable needs to point to your https://github.com/riscv/riscv-tests installation. If you are installing riscv-tests be sure to follow the instructions in the riscv-tests README.  The RISCV_TEST environment variable can be set by running the following in the riscv-tests install directory:

% export RISCV_TESTS=`pwd`

Now, from the root of your riscv-vip clone:

% cd riscv_tests_hexgen/

% make clean

% make

This hex_file_list target will:

The new HEX files can be run through the hex_file_analyzer class as described in the HEX file analyzer unit tests section.

Adding riscv-vip to an existing RISC-V core

This section is written assuming you have no existing UVM environment and that you want to passively add the riscv-vip to monitor and score coverage for your test.  For those with existing UVM environments, the integration is similar but you will already have a UVM test in place.

Syntacore SCR1 riscv-vip integration demo project example

A demo repository and accompanying documentation has been created on GitHub to show how the riscv-vip can be instantiated and connected into the existing SCR1’s non-UVM testbench and simulation environment.  The project is located at https://github.com/jerralph/riscv-vip-scr1-demo. This integration requires some glue logic since the SCR1 does not carry the instruction bits thru the pipeline and a lookup table is required to associate the instruction bits with the completed instruction at the writeback stage of the pipeline.

General integration steps

Update your build process to compile and include riscv-vip files

Include the following files in your simulation build process, where riscv-vip is your clone of the riscv-vip repo.  

riscv-vip/src/riscv_vip_pkg.sv

riscv-vip/src/riscv_vip_class_pkg.sv

riscv-vip/src/uvm/riscv_vip_uvc_pkg.sv

riscv-vip/src/uvm/test/riscv_vip_test_pkg.sv

Add the following paths to the incdir so the *.svh files included by the pkg files can be located by the simulator.

riscv-vip/src

riscv-vip/src/uvm

riscv-vip/src/uvm/test

Update your testbench

In the module where you instantiate the design under test (DUT) -- generally the testbench or _tb file -- tap into instruction and address of the instructions executed on the RISC-V core you are using.  Where and how this interface is connected depends on the implementation of the DUT and what the user wants to accomplish.  

Ideally you tap into completed instructions from the final stage of the pipeline where the register file values are written back to the register file.  Tapping into instruction from earlier stages can result in false coverage and trace data since instructions fetched in earlier stages of the pipeline may not actually be completed.  For example, instructions following a conditional branch are a common cause of fetched instructions that don’t get executed when branches are taken.

Some glue logic in the testbench may be needed to present only fully-completed instructions to the riscv-vip instruction interface.  Some logic may be required to identify exactly when the instruction is completed.  Also, some RISC-V implementations may not carry the raw instruction bits, as required by the riscv-vip instruction interface, into the later stages of the pipeline.  In such cases, glue logic may be needed to lookup the instruction bits from the history of fetched instruction address and data.  The open source Syntacore SCR1 riscv-vip demo integration is one example requiring and illustrating such glue logic.

Additionally, by sourcing the instruction interface values from completed instructions and resolving the rs1 and rs2 values from the register file at the time of completion, you should not need to be concerned values in the register file being stale for the instruction.  If instructions were sample from earlier stages of the pipeline,register value forwarding would be required to accommodate data hazard cases where the register file values do not reflect the most recent to-be-written-back values of more mature instructions in the pipeline. Care must also be taken that the result of the instruction has not been written back and reflected into the register file before the source register values, rs1, and rs2, are resolved.  Eventually/ideally a simple assembly program will be provided with the riscv-vip to test that the instruction and regfile are tapped/white-boxed correctly.  

The instruction interface contains the following and is defined in the riscv_vip_inst_if.sv file:

interface riscv_vip_inst_if (input clk, input rstn);

   logic[31:0] curr_pc;

   logic [31:0] curr_inst;  

endinterface

The interface used to connect to the riscv-vip to the RTL values of the register file is in riscv_vip_regfile_if.sv , and looks as follows:

interface riscv_vip_regfile_if (input clk, input rstn);

  //NOTE regfile is 1-31 and index 0 is not included since it's always zero

   riscv_vip_pkg::x_regfile_array_t x;

endinterface

Update the testbench to import and include the needed items.

import uvm_pkg::*;

import riscv_vip_uvc_pkg::*;

import riscv_vip_test_pkg::*;

`include "uvm_macros.svh"

Instantiate the instruction and general purpose register file interface in the testbench and pass this as a virtual interface into the UVM world using the UVM configuration database, as shown by the code below.  Again, recall that some glue logic may be needed in the testbench to only present fully completed instruction and pc to the riscv-vip interface -- such code is implementation specific and not shown here.  Finally, at the end of the code segment to be added to the testbench, the UVM portion of the test is run.  This will run alongside your pre-existing tests.  Note that uvm_test_top.m_uvc_env is the hierarchical path to the reusable riscv-vip Universal Verification Component (UVC).

//riscv-vip virtual if instantiation

riscv_vip_inst_if rv_vip_inst_if(

  `SOME_XMR_TO_CORE.clk,

  `SOME_XMR_TO_CORE.rstn

);

//use xmrs to connect up the interface

assign rv_vip_inst_if.curr_pc = `SOME_XMR_TO_CORE.pc;      

assign rv_vip_inst_if.curr_inst = `SOME_XMR_TO_CORE.instr;

riscv_vip_regfile_if rv_vip_rf_if(

  `SOME_XMR_TO_CORE.clk,

  `SOME_XMR_TO_CORE.rstn

);

assign rv_vip_rf_if.x[01] = `SOME_XMR_TO_RF.x01;

assign rv_vip_rf_if.x[02] = `SOME_XMR_TO_RF.x02;

assign rv_vip_rf_if.x[03] = `SOME_XMR_TO_RF.x03;

assign rv_vip_rf_if.x[04] = `SOME_XMR_TO_RF.x04;

assign rv_vip_rf_if.x[05] = `SOME_XMR_TO_RF.x05;

assign rv_vip_rf_if.x[06] = `SOME_XMR_TO_RF.x06;

assign rv_vip_rf_if.x[07] = `SOME_XMR_TO_RF.x07;

assign rv_vip_rf_if.x[08] = `SOME_XMR_TO_RF.x08;

assign rv_vip_rf_if.x[09] = `SOME_XMR_TO_RF.x09;

assign rv_vip_rf_if.x[10] = `SOME_XMR_TO_RF.x10;

assign rv_vip_rf_if.x[11] = `SOME_XMR_TO_RF.x11;

assign rv_vip_rf_if.x[12] = `SOME_XMR_TO_RF.x12;

assign rv_vip_rf_if.x[13] = `SOME_XMR_TO_RF.x13;

assign rv_vip_rf_if.x[14] = `SOME_XMR_TO_RF.x14;

assign rv_vip_rf_if.x[15] = `SOME_XMR_TO_RF.x15;

assign rv_vip_rf_if.x[16] = `SOME_XMR_TO_RF.x16;

assign rv_vip_rf_if.x[17] = `SOME_XMR_TO_RF.x17;

assign rv_vip_rf_if.x[18] = `SOME_XMR_TO_RF.x18;

assign rv_vip_rf_if.x[19] = `SOME_XMR_TO_RF.x19;

assign rv_vip_rf_if.x[20] = `SOME_XMR_TO_RF.x20;

assign rv_vip_rf_if.x[21] = `SOME_XMR_TO_RF.x21;

assign rv_vip_rf_if.x[22] = `SOME_XMR_TO_RF.x22;

assign rv_vip_rf_if.x[23] = `SOME_XMR_TO_RF.x23;

assign rv_vip_rf_if.x[24] = `SOME_XMR_TO_RF.x24;

assign rv_vip_rf_if.x[25] = `SOME_XMR_TO_RF.x25;

assign rv_vip_rf_if.x[26] = `SOME_XMR_TO_RF.x26;

assign rv_vip_rf_if.x[27] = `SOME_XMR_TO_RF.x27;

assign rv_vip_rf_if.x[28] = `SOME_XMR_TO_RF.x28;

assign rv_vip_rf_if.x[29] = `SOME_XMR_TO_RF.x29;

assign rv_vip_rf_if.x[30] = `SOME_XMR_TO_RF.x30;

assign rv_vip_rf_if.x[31] = `SOME_XMR_TO_RF.x31;

//CSR interface (currently not implemented, but things will error if not set into

//config db)

riscv_vip_csr_if rv_vip_csr_if(clk,rst_n);

genvar core;

generate

  for (core = 0; core < `NUM_CORES; core++) begin : gen_cores

    const static string agent_xmr = $psprintf("uvm_test_top.m_uvc_env.m_i32_agent[%0d]",core);

       

    initial begin : set_riscv_vip_vif_to_db

                     

      uvm_config_db#(virtual riscv_vip_inst_if)::set(

        null,

        agent_xmr,

        "m_vi",

        rv_vip_inst_if

      );

      uvm_config_db#(virtual riscv_vip_regfile_if)::set(

        null,

        agent_xmr,

        "m_rf_vi",

        rv_vip_rf_if

      );

      uvm_config_db#(virtual riscv_vip_csr_if)::set(

        null,

        agent_xmr,

        "m_csr_vi",

        rv_vip_csr_if

      );

           

      uvm_config_db#(int)::set(

        null,

        agent_xmr,

        "m_core_id",

        core

        );

     

    end      

  end : gen_cores

endgenerate

//Run UVM test

initial begin

  run_test();

end

Simulator flags

For Cadence ius the flags used are

-uvm -sv -exit +licq +nowarn+CUVWSP +nowarn+LIBNOU +nowarn+SPDUSD -linedebug -uvmlinedebug -coverage all -covoverwrite +define+DUMP+TRN +access+rc +UVM_TESTNAME=riscv_vip_base_test

Note that the +UVM_TEST_NAME is passed to the simulator at runtime, as a SystemVerilog plus argument.  

For Mentor Questasim the flags are

-mfcu -incr -sv "+nowarn8233" -warning vlog-2997 "+acc" -R -voptargs="+cover=bcefst" -coverage -do "coverage save -onexit coverage.ucdb" UVM_TESTNAME=riscv_vip_base_test

Locating the trace file

After running a simulation with the riscv_vip_base_test, if things are working correctly, you should find a trace file named riscv_tracker_<core_id>.log in the directory where the simulation is run.