[riscv-vip] Users’ Guide
Running riscv-vip 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
For pre-silicon developers of RISC-V systems, the riscv-vip project:
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.
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 |
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.
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.
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.
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.
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.
The instruction history tests are run as follows, assuming you are in the riscv-vip/src directory:
% make ihist_ut
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.
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.
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.
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.
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.
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
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
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
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.