diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index 748275d0..d58f72fd 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/google/riscv-dv - rev: 46ec4bc48bc1eebc5a2bcd48fe4ce4c77105fead + rev: cce71d24b56f641d994fbf69b8b50aa3756b9322 } } diff --git a/vendor/google_riscv-dv/HANDSHAKE.md b/vendor/google_riscv-dv/HANDSHAKE.md new file mode 100644 index 00000000..c18bd786 --- /dev/null +++ b/vendor/google_riscv-dv/HANDSHAKE.md @@ -0,0 +1,250 @@ +## Overview + +While the `RISCV-DV` Instruction Generator provides a `debug_rom` section as +well as various interrupt and exception handlers, from a verification +standpoint this is not enough to help ensure that a core's internal state is being +updated correctly upon receiving external stimulus such as interrupts or debug +requests, such as the values of any relevant CSRs. +To help with this issue, the instruction generator also provides a mechanism by +which to communicate information to a RTL simulation environment by means of a +handshaking protocol. + +## Usage + +Every handshake produced by the instruction generator is just a small segment of +RISC-V assembly code, that end in one or more `sw` instructions to a specified memory +address `signature_addr`. +This `signature_addr` is completely customizable, and +can be specified through a `plusarg` runtime option to the generator. +There is also an enable bit `require_signature_addr` that must be set through +another `plusarg` argument to enable these handshake code segments to be +generated in the main random assembly program. + +An RTL simulation environment that utilizes +this handshaking mechanism should provide a basic set of tasks to monitor this +`signature_addr` for any writes, as this will indicate that the core under test is +executing a particular handshake assembly sequence and is transmitting some +information to the testbench for analysis. +As a result, this `signature_addr` +acts as sort of memory-mapped address that the testbench will monitor, and as +such, case should be taken when setting this address to ensure that the generator's +program randomization will not somehow create a sequence of random load/store +instructions that access the same `signature_addr`. +A suggested value for this `signature_addr` is the value `0x8ffffffc`. +More details, and an example, as to how to interface the testbench with this +handshake mechanism will be provided below. + +## Handshake Sequence Architecture + +The function `gen_signature_handshake(...)` contained in +[src/riscv_asm_program_gen.sv](https://github.com/google/riscv-dv/blob/master/src/riscv_asm_program_gen.sv) +is used to actually generate the handshaking code and push it into the specified +instruction queue. Its usage can be seen repeatedly throughout the program +generation in various places, such as trap handlers and the debug ROM, where it +is important to send information to a testbench for further verification. +The `signature_type_t`, `core_status_t`, and `test_result_t` enums specified as +input values to this function are defined in +[src/riscv_signature_pkg.sv](https://github.com/google/riscv-dv/blob/master/src/riscv_signature_pkg.sv). +Note that all of these definitions are within a standalone package, this is so +that an RTL simulation environment can also import this package to gain access +to these enums. +The `signature_type_t` enum is by far the most important enum value, as +this specifies what kind of handshake will be generated. + +There are currently 4 defined values of `signature_type`, each corresponding +to a different handshake type that will be generated; each will be explained below. +Note that two GPRs must be used to temporarily hold the store address and the +actual data to store to this address; the generator randomizes these two GPRs +for every generated program, but for the purposes of this document, `x1` and +`x2` will be used, and `0x8ffffffc` will be used as the example `signature_addr`. + +#### CORE_STATUS + +When the `signature_type` argument is specified as `CORE_STATUS`, a single word +of data will be written to the `signature_addr`. As the actual `signature_type` +value is 8 bits wide, as specified in the `riscv_signature_pkg`, this generated +data word will contain the `CORE_STATUS` value in its bottom 8 bits, and will +contain the specified value of `core_status_t` in the upper 24 bits. This +signature handshake is intended to convey basic information about the core's +execution state to an RTL simulation environment; a handshake containing a +`core_status` of `IN_DEBUG_MODE` is added to the debug ROM to indicate to a +testbench that the core has jumped into Debug Mode and is executing the debug +ROM, a handshake containing a `core_status` of `ILLEGAL_INSTR_EXCEPTION` is +added to the illegal instruction exception handler code created by the generator +to indicate to a testbench that the core has trapped to and is executing the +proper handler after encountering an illegal instruction, and so on for the rest +of the defined `core_status_t` enum values. + +Note that when generating these specific handshakes, it is only necessary to +specify the parameters `instr`, `signature_type`, and `core_status`. For +example, to generate this handshake to signal status `IN_MACHINE_MODE` to the +testbench, the call to the function looks like this: +``` +gen_signature_handshake(.instr(instr_string_queue), + .signature_type(CORE_STATUS), + .core_status(IN_MACHINE_MODE)); +``` +The sequence of assembly code generated by this call looks like the following: +``` +# First, load the signature address into a GPR +li x2, 0x8ffffffc +# Load the intended core_status_t enum value into +# a second GPR +li x1, 0x2 +# Left-shift the core_status value by 8 bits +# to make room for the signature_type +slli x1, x1, 8 +# Load the intended signature_type_t enum value into +# the bottom 8 bits of the data word +addi x1, x1, 0x0 +# Store the data word to memory at the location of the signature_addr +sw x1, 0(x2) +``` + +#### TEST_RESULT + +As before, when `signature_type` is set to `TEST_RESULT` a single word of data +will be written to the signature address, and the value `TEST_RESULT` will be +placed in the bottom 8 bits. The upper 24 bits will then contain a value of type +`test_result_t`, either `TEST_PASS` or `TEST_FAIL`, to indicate to the testbench +the exit status of the test. As the ISS co-simulation flow provides a robust +end-of-test correctness check, the only time that this signature handshake is +used is in the `riscv_csr_test`. Since this test is generated with a Python +script and is entirely self-checking, we must send an exit status of `TEST_PASS` +or `TEST_FAIL` to the testbench to indicate to either throw an error or end the +test correctly. + +Note that when generating these handshakes, the only arguments that need to be +specified are `instr`, `signature_type`, and `test_result`. For example, to +generate a handshake to communicate `TEST_PASS` to a testbench, the function +call would look like this: +``` +gen_signature_handshake(.instr(instr_string_queue), + .signature_type(TEST_RESULT), + .test_result(TEST_PASS)); +``` +The sequence of generated assembly code with this function call would look like +the following: +``` +# Load the signature address into a GPR +li x2 0x8ffffffc +# Load the intended test_result_t enum value +li x1, 0x0 +# Left-shift the test_result value by 8 bits +slli x1, x1, 8 +# Load the intended signature_type_t enum value into +# the bottom 8 bits of the data word +addi x1, x1, 0x1 +# Store this formatted word to memory at the signature address +sw x1, 0(x2) +``` + +#### WRITE_GPR + +When a `signature_type` of `WRITE_GPR` is passed to the +`gen_signature_handshake(...)` function, one data word will initially be written +to the signature address, containing the `signature_type` of `WRITE_GPR` in the +lower 8 bits. After this, the value held by each of the 32 RISC-V general +purpose registers from `x0` to `x31` will be written to the signature address +with `sw` instructions. + +For this particular handshake, the only function arguments that need to be +specified are `instr` and `signature_type`. A function call to generate this +particular handshake would look like the following: +``` +gen_signature_handshake(.instr(instr_string_queue), + .signature_type(WRITE_GPR)); +``` +The generated assembly sequence would look like this: +``` +# Load the signature address into a GPR +li x2, 0x8ffffffc +# Load the value of WRITE_GPR into a second GPR +li x1, 0x2 +# Store this word to memory at the signature address +sw x1, 0(x2) +# Iterate through all 32 GPRs and write each one to +# memory at the signature address +sw x0, 0(x2) +sw x1, 0(x2) +sw x2, 0(x2) +sw x3, 0(x2) +... +sw x30, 0(x2) +sw x31, 0(x2) +``` + +#### WRITE_CSR + +When `gen_signature_handshake(...)` is called with `WRITE_CSR` as the +`signature_type` argument, we will generate a first `sw` instruction that writes a +data word to the `signature_addr` that contains the value `WRITE_CSR` in the +bottom 8 bits, and the address of the desired CSR in the upper 24 bits, to +indicate to the testbench which CSR will be written. +This first generated `sw` instruction is then followed by a second one, which +writes the actual data contained in the specified CSR to the signature address. + +Note the only function arguments that have to be specified to generate this +handshake are `instr`, `signature_type`, and `csr`. As an example, to generate a +handshake that writes the value of the `mie` CSR to the RTL simulation +environment, the function call would look like this: +``` +gen_signature_handshake(.instr(instr_string_queue), + .signature_type(WRITE_CSR), + .csr(MIE)); +``` +The sequence of assembly generated by this call would look like the following: +``` +# Load the signature address into a GPR +li x2, 0x8ffffffc +# Load the address of MIE into the second GPR +li x1, 0x304 +# Left-shift the CSR address by 8 bits +slli x1, x1, 8 +# Load the WRITE_CSR signature_type value into +# the bottom 8 bits of the data word. +# At this point, the data word is 0x00030403 +addi x1, x1, 0x3 +# Store this formatted word to memory at the signature address +sw x1, 0(x2) +# Read the actual CSR value into the second GPR +csrr x1, 0x304 +# Write the value held by the CSR into memory at the signature address +sw x1, 0(x2) +``` + +## Sample Testbench Integration + +Everything previously outlined has been relating to how this handshake +generation is implemented from the perspective of the `RISCV-DV` instruction +generator, but some work must be done in the RTL simulation environment to +actually interface with and use these handshakes to improve verification with +this mechanism. +This handshaking mechanism has been put to use for verification of the [Ibex +RISC-V core](https://github.com/lowRISC/ibex), in collaboration with LowRISC. To +interface with the handshaking code produced in the generator, this testbench +makes heavy use of the task `wait_for_mem_txn(...)` found in +[core_ibex_base_test.sv](https://github.com/lowRISC/ibex/blob/master/dv/uvm/tests/core_ibex_base_test.sv). +This task polls the Ibex core's data memory interface for any writes to the +chosen signature address (`0x8ffffffc`), and then based on the value of +`signature_type` encoded by the generated handshake code, this task takes +appropriate action and stores the relevant data into a queue instantiated in the +base test class. + +For example upon detecting a transaction written to the +signature address that has a `signature_type` of `WRITE_CSR`, it right-shifts +the collected data word by 8 to obtain the CSR address, which is then stored to +the local queue. However, since for `WRITE_CSR` signatures there is a second +data word that gets written to memory at the signature address, the task waits +for the second write containing the CSR data to arrive, and then stores that + into the queue as well. After this task completes, it is now possible to pop + the stored data off of the queue for analysis anywhere else in the test class, + in this case examining the values of various CSR fields. + +Additionally, the Ibex testbench provides a fairly basic API of some tasks +wrapping `wait_for_mem_txn(...)` for frequently used functionalities in various +test classes. This API is also found in +[core_ibex_base_test.sv](https://github.com/lowRISC/ibex/blob/master/dv/uvm/tests/core_ibex_base_test.sv). +Examples of use-cases for these API functions can be found throughout the +library of tests written for the Ibex core, found at +[core_ibex_test_lib.sv](https://github.com/lowRISC/ibex/blob/master/dv/uvm/tests/core_ibex_test_lib.sv), as these are heavily used to verify the core's response to external debug and interrupt stimulus. diff --git a/vendor/google_riscv-dv/README.md b/vendor/google_riscv-dv/README.md index 7a924b2e..2f03c789 100644 --- a/vendor/google_riscv-dv/README.md +++ b/vendor/google_riscv-dv/README.md @@ -10,14 +10,14 @@ processor verification. It currently supports the following features: - Privileged CSR test suite - Trap/interrupt handling - Test suite to stress test MMU -- Support sub-programs and random program calls -- Support illegal instruction and HINT instruction +- Sub-program generation and random program calls +- Illegal instruction and HINT instruction generation - Random forward/backward branch instructions - Supports mixing directed instructions with random instruction stream - Debug mode support, with fully randomized debug ROM - Instruction generation coverage model - Communication of information to any integrated SV testbench -- Supports co-simulation with multiple ISS : spike, riscv-ovpsim +- Co-simulation with multiple ISS : spike, riscv-ovpsim A CSR test generation script written in Python is also provided, to generate a directed test suite that stresses all CSR instructions on all of the CSRs that @@ -32,15 +32,11 @@ which supports SystemVerilog and UVM 1.2. This generator has been verified with Synopsys VCS, Cadence Incisive/Xcelium, and Mentor Questa simulators. Please make sure the EDA tool environment is properly setup before running the generator. -To be able to run the CSR generation script, the open-source `bitstring` -Python library is required ([bitstring](https://github.com/scott-griffiths/bitstring)). -To install this library, either clone the repository and run the `setup.py` -setup script, or run only one of the below commands: -``` -1) sudo apt-get install python3-bitstring (or your OS-specific package manager) -2) pip install bitstring -``` +Install YAML python package: +```bash +pip3 install PyYAML +``` ### Setup RISCV-GCC compiler toolchain @@ -50,12 +46,11 @@ setup script, or run only one of the below commands: - Set environment variable RISCV_OBJCOPY to RISC-v objcopy executable executable. (example: /bin/riscv32-unknown-elf-objcopy) -``` -// Sample .bashrc setup +```bash +# Sample .bashrc setup export RISCV_TOOLCHAIN= export RISCV_GCC="$RISCV_TOOLCHAIN/bin/riscv32-unknown-elf-gcc" export RISCV_OBJCOPY="$RISCV_TOOLCHAIN/bin/riscv32-unknown-elf-objcopy" -export SPIKE_PATH=$RISCV_TOOLCHAIN/bin ``` ### Setup ISS (instruction set simulator) @@ -65,7 +60,7 @@ one of below to run ISS simulation. - [spike](https://github.com/riscv/riscv-isa-sim#) setup - Follow the [steps](https://github.com/riscv/riscv-isa-sim#build-steps) to build spike - - Install spike with "--enable-commitlog" + - Build spike with "--enable-commitlog" - Set environment variable SPIKE_PATH to the directory of the spike binary - [riscv-ovpsim](https://github.com/riscv/riscv-ovpsim) setup - Download the riscv-ovpsim binary @@ -74,24 +69,28 @@ one of below to run ISS simulation. - Follow the [steps](https://github.com/rems-project/sail-riscv/blob/master/README.md) to install sail-riscv - Set environment variable SAIL_RISCV to the sail-riscv binary +```bash +export SPIKE_PATH=$RISCV_TOOLCHAIN/bin +``` + ## Running the generator A simple script "run.py" is provided for you to run a single test or a regression. You can use --help to get the complete command reference: -``` +```bash python3 run.py --help ``` Here is the command to run a single test: -``` +```bash python3 run.py --test=riscv_arithmetic_basic_test ``` You can specify the simulator by "-simulator" option -``` +```bash python3 run.py --test riscv_arithmetic_basic_test --simulator ius python3 run.py --test riscv_arithmetic_basic_test --simulator vcs python3 run.py --test riscv_arithmetic_basic_test --simulator questa @@ -100,35 +99,35 @@ python3 run.py --test riscv_arithmetic_basic_test --simulator dsim The complete test list can be found in [yaml/testlist.yaml](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml). To run a full regression, simply use below command -``` +```bash python3 run.py ``` You can also run multiple generator jobs in parallel through LSF -``` +```bash python3 run.py --lsf_cmd="bsub -Is" ``` Here's a few more examples of the run command: -``` -// Run a single test 10 times +```bash +# Run a single test 10 times python3 run.py --test riscv_arithmetic_basic_test --iterations 10 -// Run a test with verbose logging +# Run a test with verbose logging python3 run.py --test riscv_arithmetic_basic_test --verbose -// Run a test with a specified seed +# Run a test with a specified seed python3 run.py --test riscv_arithmetic_basic_test --seed 123 -// Skip the generation, run ISS simulation with previously generated program +# Skip the generation, run ISS simulation with previously generated program python3 run.py --test riscv_arithmetic_basic_test --steps iss_sim -// Run the generator only, do not compile and simluation with ISS +# Run the generator only, do not compile and simluation with ISS python3 run.py --test riscv_arithmetic_basic_test --steps gen -// Compile the generator only, do not simulate +# Compile the generator only, do not simulate python3 run.py --test riscv_arithmetic_basic_test --co .... @@ -138,22 +137,22 @@ python3 run.py --test riscv_arithmetic_basic_test --co You can use -iss to run with different ISS. -``` -// Run ISS with spike +```bash +# Run ISS with spike python3 run.py --test riscv_arithmetic_basic_test --iss spike -// Run ISS with riscv-ovpsim +# Run ISS with riscv-ovpsim python3 run.py --test riscv_rand_instr_test --iss ovpsim -// Run ISS with sail-riscv +# Run ISS with sail-riscv python3 run.py --test riscv_rand_instr_test --iss sail ``` To run with ISS simulation for RV32IMC, you can specify ISA and ABI from command line like this: -``` -// Run a full regression with RV32IMC +```bash +# Run a full regression with RV32IMC python3 run.py --isa rv32imc --mabi ilp32 ``` @@ -162,7 +161,7 @@ the instruction trace from these runs will be cross compared. This could greatly speed up your development of new test without the need to simulate against a real RISC-V processor. -``` +```bash python3 run.py --test=riscv_rand_instr_test --iss=spike,ovpsim python3 run.py --test=riscv_rand_instr_test --iss=spike,sail ``` @@ -171,13 +170,23 @@ python3 run.py --test=riscv_rand_instr_test --iss=spike,sail ### Configure the generator to match your processor features -The default configuration of the instruction generator is for **RV64GC** RISC-V -processors with address translation capability. You might want to configure the -generator according the feature of your processor. - -The static setting of the processor src/riscv_core_setting.sv +The default configuration of the instruction generator is **RV32IMC** (machine +mode only). A few pre-defined configurations can be found under "target" directory, +you can run with these targets if it matches your processor specification. +```bash +python3 run.py # Default target rv32imc +python3 run.py --target rv32i # rv32i, machine mode only +python3 run.py --target rv32imc # rv32imc, machine mode only +python3 run.py --target rv64imc # rv64imc, machine mode only +python3 run.py --target rv64gc # rv64gc, SV39, M/S/U mode ``` + +If you want to have a custom setting for your processor, you can make a copy of +existing target directory as the template, and modify riscv_core_setting.sv to +match your processor capability. + +```verilog // Bit width of RISC-V GPR parameter int XLEN = 64; @@ -198,14 +207,13 @@ riscv_instr_group_t supported_isa[] = {RV32I, RV32M, RV64I, RV64M}; ... ``` -A few pre-defined configurations can be found under "target" directory, you can -run with these targets if it matches your processor specification. +You can then run the generator with "--custom_target " +```bash +# You need to manually specify isa and mabi for your custom target +python3 run.py --custom_target --isa --mabi +... ``` -// Run regression with RV32IMC configuration -python3 run.py --target rv32imc -``` - ### Setup the memory map @@ -220,7 +228,7 @@ sections to match the actual memory map You can configure the memory map in [riscv_instr_gen_config.sv](https://github.com/google/riscv-dv/blob/master/src/riscv_instr_gen_config.sv) -``` +```verilog mem_region_t mem_region[$] = '{ '{name:"region_0", size_in_bytes: 4096, xwr: 3'b111}, '{name:"region_1", size_in_bytes: 4096 * 4, xwr: 3'b111}, @@ -241,7 +249,7 @@ conditions for the load/store testing. [Test list in YAML format](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml) -``` +```yaml # test : Assembly test name # description : Description of this test # gen_opts : Instruction generator options @@ -306,7 +314,7 @@ file above. | randomize_csr | Fully randomize main CSRs (xSTATUS, xIE) | 0 | -### Setup Privileged CSR description +### Setup Privileged CSR description (optional) This YAML description file of all CSRs is only required for the privileged CSR test. All other standard tests do not use this description. @@ -314,7 +322,7 @@ test. All other standard tests do not use this description. [CSR descriptions in YAML format](https://github.com/google/riscv-dv/blob/master/yaml/csr_template.yaml) -``` +```yaml - csr: CSR_NAME description: > BRIEF_DESCRIPTION @@ -353,7 +361,17 @@ format](https://github.com/google/riscv-dv/blob/master/yaml/csr_template.yaml) To specify what ISA width should be generated in the test, simply include the matching rv32/rv64/rv128 entry and fill in the appropriate CSR field entries. -### Privileged CSR Test Generation +### Privileged CSR Test Generation (optional) + +To be able to run the CSR generation script, the open-source `bitstring` +Python library is required ([bitstring](https://github.com/scott-griffiths/bitstring)). +To install this library, either clone the repository and run the `setup.py` +setup script, or run only one of the below commands: + +```bash +sudo apt-get install python3-bitstring (or your OS-specific package manager) +pip install bitstring +``` The CSR generation script is located at [scripts/gen_csr_test.py](https://github.com/google/riscv-dv/blob/master/scripts/gen_csr_test.py). @@ -366,7 +384,7 @@ continue executing, allowing it to be completely self checking. This script has been integrated with run.py. If you want to run it separately, you can get the command reference with --help: -``` +```bash python3 scripts/gen_csr_test.py --help ``` @@ -377,16 +395,20 @@ add a new instruction stream. After the new instruction stream is created, you can use a runtime option to mix it with random instructions -``` +```bash //+directed_instr_n=instr_sequence_name,frequency(number of insertions per 1000 instructions) +directed_instr_5=riscv_multi_page_load_store_instr_stream,4 + +// An alternative command line options for directed instruction stream ++stream_name_0=riscv_multi_page_load_store_instr_stream ++stream_freq_0=4 ``` ## Integrate a new ISS You can add a new entry in [iss.yaml](https://github.com/google/riscv-dv/blob/master/yaml/iss.yaml) -``` +```yaml - iss: new_iss_name path_var: ISS_PATH cmd: > @@ -395,7 +417,7 @@ You can add a new entry in [iss.yaml](https://github.com/google/riscv-dv/blob/ma Simulate with the new ISS -``` +```bash python3 run.py --test riscv_arithmetic_basic_test --iss new_iss_name ``` @@ -404,30 +426,41 @@ python3 run.py --test riscv_arithmetic_basic_test --iss new_iss_name We have collaborated with LowRISC to apply this flow for [IBEX RISC-V core verification](https://github.com/lowRISC/ibex/blob/master/doc/verification.rst). You can use it as a reference to setup end-to-end co-simulation flow. -This repo is still under active development, here's recommended approach to -customize the instruction generator while keeping the minimum effort of merging -upstream changes. +This repo is still under active development, this is the recommended approach to +customize the instruction generator while keeping the effort of merging +upstream changes to a minimum. - Do not modify the upstream classes directly. When possible, extend from the upstream classses and implement your own functionalities. - Add your extensions under user_extension directory, and add the files to user_extension/user_extension.svh. If you prefer to put your extensions in a different directory, you can use "-ext " to override the user extension path. -- Create a new file for riscv_core_setting.sv, add the path with below option: - "-cs " +- Create a new target directory and customize the setting and testlist +- Run the generator with "--custom_target --isa --mabi " - Use command line type override to use your extended classes. --sim_opts="+uvm_set_type_override=," You can refer to [riscv-dv extension for ibex](https://github.com/lowRISC/ibex/blob/master/dv/uvm/Makefile#L68) for a working example. -We have plan to open-source the end-to-end environment of other advanced RISC-V +We have plan to open-source the end-to-end environments of other advanced RISC-V processors. Stay tuned! +## Handshaking Mechanism + +This mechanism allows the generator to generate small, directed sequences of +instructions that write critical information to a specified address in memory, +that the testbench monitors for write accesses to. +This allows for more in-depth verification of scenarios that involve external +stimulus to the core, such as interrupts and debug requests. + +For more information, detailed documentation of this mechanism can be found in +[HANDSHAKE.md](./HANDSHAKE.md). + ## Functional coverage (work in progress) -This flow extracts funcitonal coverage information from the +This flow extracts functional coverage information from the instruction trace generated by ISS. It's indepdent of the instruction generation -flow and does not require a tracer implmentation in the RTL. You can use this +flow and does not require a tracer implementation in the RTL. You can use this flow as long as your program can be run with the ISS supported in this flow. The flow parses the instruction trace log and converts it to a CSV trace format. After that, a SV test will be run to process the CSV trace files and sample functional @@ -447,17 +480,20 @@ The functional covergroup is defined in [riscv_instr_cover_group.sv](https://git - Exception and interrupt The functional covergroup is still under active development. Please feel free to -add anything you are interested or file a bug for any feature request. +add anything you are interested or file a bug for any feature request. -Before start, please check the you have modified [riscv_core_setting.sv](https://github.com/google/riscv-dv/blob/master/setting/riscv_core_setting.sv) to reflect your processor capabilities. The covergroup is selectively instantiated based on this setting so that you don't need to deal with excluding unrelated coverpoint later. You also need to get spike ISS setup before running this flow. +Before start, please check the you have modified [riscv_core_setting.sv](https://github.com/google/riscv-dv/blob/master/setting/riscv_core_setting.sv) to reflect your processor capabilities. The covergroup is selectively instantiated based on this setting so that you don't need to deal with excluding unrelated coverpoints later. You also need to get the Spike ISS setup before running this flow. -``` -// Process spike simulation log and collect functional coverage +```bash +# Process spike simulation log and collect functional coverage python3 cov.py --dir out/spike_sim -// Get the command reference +# Get the command reference python3 cov.py --help + +# Run the coverage flow with predefined targets +python3 cov.py --dir out/spike_sim --target rv32imc ``` The coverage sampling from the CSV could be time consuming if you have a large @@ -465,7 +501,7 @@ number of log to process. You can split them to small batches and run with LSF in parallel. ``` -// Split the run to process 5 CSV at a time, and run with LSF +# Split the run to process 5 CSV at a time, and run with LSF python3 cov.py --dir out/spike_sim --lsf_cmd "bsub ....." -bz 5 ``` @@ -473,8 +509,8 @@ There is also a debug mode which allow you randomize the instruction and sample coverage directly. This is only used to test the new functional coverage implmentation. -``` -// Randomly generate 100000 instructions, split to 20000 instructions per batch +```bash +# Randomly generate 100000 instructions, split to 20000 instructions per batch python3 cov.py -d -i 100000 -bz 20000 ``` diff --git a/vendor/google_riscv-dv/cov.py b/vendor/google_riscv-dv/cov.py index 8fd6bea4..b1f06d6c 100644 --- a/vendor/google_riscv-dv/cov.py +++ b/vendor/google_riscv-dv/cov.py @@ -32,7 +32,7 @@ from scripts.sail_log_to_trace_csv import * LOGGER = logging.getLogger() def collect_cov(log_dir, out, iss, testlist, batch_size, lsf_cmd, steps, \ - opts, timeout, simulator, simulator_yaml, core_setting_dir): + opts, timeout, simulator, simulator_yaml, custom_target, target): """Collect functional coverage from the instruction trace Args: @@ -47,8 +47,10 @@ def collect_cov(log_dir, out, iss, testlist, batch_size, lsf_cmd, steps, \ timeout : Timeout limit in seconds simulator : RTL simulator used to run simulator_yaml : RTL simulator configuration file in YAML format - core_setting_dir : Path for riscv_core_setting.sv + custom_target : Path for the custom target dir + target : Predefined target """ + cwd = os.path.dirname(os.path.realpath(__file__)) log_list = [] csv_list = [] trace_log = ("%s/%s_trace_log" % (out, iss)) @@ -73,13 +75,21 @@ def collect_cov(log_dir, out, iss, testlist, batch_size, lsf_cmd, steps, \ logging.error("Full trace for %s is not supported yet" % iss) sys.exit(1) if steps == "all" or re.match("cov", steps): - build_cmd = ("python3 run.py --simulator %s --simulator_yaml %s " - "--core_setting_dir %s --co -o %s --cov -tl %s %s " % - (simulator, simulator_yaml, core_setting_dir, out, testlist, opts)) - base_sim_cmd = ("python3 run.py --simulator %s --simulator_yaml %s " - "--core_setting_dir %s --so -o %s --cov -tl %s %s " + build_cmd = ("python3 %s/run.py --simulator %s --simulator_yaml %s " + " --co -o %s --cov -tl %s %s " % + (cwd, simulator, simulator_yaml, out, testlist, opts)) + base_sim_cmd = ("python3 %s/run.py --simulator %s --simulator_yaml %s " + "--so -o %s --cov -tl %s %s " "-tn riscv_instr_cov_test --steps gen --sim_opts \"\"" % - (simulator, simulator_yaml, core_setting_dir, out, testlist, opts)) + (cwd, simulator, simulator_yaml, out, testlist, opts)) + if target: + build_cmd += (" --target %s" % target) + if custom_target: + build_cmd += (" --custom_target %s" % custom_target) + if target: + base_sim_cmd += (" --target %s" % target) + if custom_target: + base_sim_cmd += (" --custom_target %s" % custom_target) logging.info("Building the coverage collection framework") run_cmd(build_cmd) file_idx = 0 @@ -115,7 +125,7 @@ def collect_cov(log_dir, out, iss, testlist, batch_size, lsf_cmd, steps, \ def run_cov_debug_test(out, instr_cnt, testlist, batch_size, opts, lsf_cmd,\ - timeout, simulator, simulator_yaml, core_setting_dir): + timeout, simulator, simulator_yaml, custom_target, target): """Collect functional coverage from the instruction trace Args: @@ -128,19 +138,29 @@ def run_cov_debug_test(out, instr_cnt, testlist, batch_size, opts, lsf_cmd,\ timeout : Timeout limit in seconds simulator : RTL simulator used to run simulator_yaml : RTL simulator configuration file in YAML format - core_setting_dir : Path for riscv_core_setting.sv + custom_target : Path for the custom target dir + target : Predefined target """ + cwd = os.path.dirname(os.path.realpath(__file__)) sim_cmd_list = [] logging.info("Building the coverage collection framework") - build_cmd = ("python3 run.py --simulator %s --simulator_yaml %s " - "--core_setting_dir %s --co -o %s --cov -tl %s %s" % - (simulator, simulator_yaml, core_setting_dir, out, testlist, opts)) + build_cmd = ("python3 %s/run.py --simulator %s --simulator_yaml %s " + "--co -o %s --cov -tl %s %s" % + (cwd, simulator, simulator_yaml, out, testlist, opts)) + if target: + build_cmd += (" --target %s" % target) + if custom_target: + build_cmd += (" --custom_target %s" % custom_target) run_cmd(build_cmd) - base_sim_cmd = ("python3 run.py --simulator %s --simulator_yaml %s " - "--core_setting_dir %s --so -o %s --cov -tl %s %s " + base_sim_cmd = ("python3 %s/run.py --simulator %s --simulator_yaml %s " + "--so -o %s --cov -tl %s %s " "-tn riscv_instr_cov_debug_test --steps gen " "--sim_opts \"+num_of_iterations=\"" % - (simulator, simulator_yaml, core_setting_dir, out, testlist, opts)) + (cwd, simulator, simulator_yaml, out, testlist, opts)) + if target: + base_sim_cmd += (" --target %s" % target) + if custom_target: + base_sim_cmd += (" --custom_target %s" % custom_target) if batch_size > 0: batch_cnt = int((instr_cnt+batch_size-1)/batch_size) logging.info("Batch size: %0d, Batch cnt:%0d" % (batch_size, batch_cnt)) @@ -200,13 +220,15 @@ def setup_parser(): parser.add_argument("--lsf_cmd", type=str, default="", help="LSF command. Run in local sequentially if lsf \ command is not specified") - parser.add_argument("--target", type=str, default="", + parser.add_argument("--target", type=str, default="rv32imc", help="Run the generator with pre-defined targets: \ - rv32imc, rv32i, rv64imc") + rv32imc, rv32i, rv64imc, rv64gc") parser.add_argument("-si", "--simulator", type=str, default="vcs", help="Simulator used to run the generator, default VCS", dest="simulator") parser.add_argument("--simulator_yaml", type=str, default="", help="RTL simulator setting YAML") + parser.add_argument("-ct", "--custom_target", type=str, default="", + help="Directory name of the custom target") parser.add_argument("-cs", "--core_setting_dir", type=str, default="", help="Path for the riscv_core_setting.sv") parser.set_defaults(verbose=False) @@ -229,10 +251,22 @@ def main(): if not args.simulator_yaml: args.simulator_yaml = cwd + "/yaml/simulator.yaml" - if args.target: + # Debug mode only works for RV64GC target + if args.debug_mode: + args.target = "rv64gc" + + # Keep the core_setting_dir option to be backward compatible, suggest to use + # --custom_target + if args.core_setting_dir: + if not args.custom_target: + args.custom_target = args.core_setting_dir + else: + args.core_setting_dir = args.custom_target + + if not args.custom_target: args.core_setting_dir = cwd + "/target/"+ args.target - elif not args.core_setting_dir: - args.core_setting_dir = cwd + "/setting/" + else: + args.testlist = args.custom_target + "/testlist.yaml" # Create output directory if args.o is None: @@ -245,11 +279,11 @@ def main(): if args.debug_mode: run_cov_debug_test(output_dir, args.instr_cnt, args.testlist, args.batch_size, args.opts, args.lsf_cmd, args.timeout, - args.simulator, args.simulator_yaml, args.core_setting_dir) + args.simulator, args.simulator_yaml, args.custom_target, args.target) else: collect_cov(args.dir, output_dir, args.iss, args.testlist, args.batch_size, args.lsf_cmd, args.steps, args.opts, args.timeout, - args.simulator, args.simulator_yaml, args.core_setting_dir) + args.simulator, args.simulator_yaml, args.custom_target, args.target) if __name__ == "__main__": main() diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index 74495066..d8cd3b75 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -72,29 +72,28 @@ def get_generator_cmd(simulator, simulator_yaml, cov): sys.exit(1) -def parse_iss_yaml(iss, iss_yaml, isa): +def parse_iss_yaml(iss, iss_yaml, isa, setting_dir): """Parse ISS YAML to get the simulation command Args: - iss : target ISS used to look up in ISS YAML - iss_yaml : ISS configuration file in YAML format - isa : ISA variant passed to the ISS + iss : target ISS used to look up in ISS YAML + iss_yaml : ISS configuration file in YAML format + isa : ISA variant passed to the ISS + setting_dir : Generator setting directory Returns: - cmd : ISS run command + cmd : ISS run command """ logging.info("Processing ISS setup file : %s" % iss_yaml) yaml_data = read_yaml(iss_yaml) + cwd = os.path.dirname(os.path.realpath(__file__)) # Search for matched ISS for entry in yaml_data: if entry['iss'] == iss: logging.info("Found matching ISS: %s" % entry['iss']) cmd = entry['cmd'].rstrip() cmd = re.sub("\", get_env_var(entry['path_var']), cmd) - if iss == "ovpsim": - cmd = re.sub("\", isa, cmd) - else: - cmd = re.sub("\", isa, cmd) + cmd = re.sub("\", isa, cmd) return cmd logging.error("Cannot find ISS %0s" % iss) sys.exit(1) @@ -159,10 +158,7 @@ def gen(test_list, csr_file, end_signature_addr, isa, simulator, logging.info("Building RISC-V instruction generator") for cmd in compile_cmd: cmd = re.sub("", os.path.abspath(output_dir), cmd) - if core_setting_dir == "": - cmd = re.sub("", "/setting", cmd) - else: - cmd = re.sub("", core_setting_dir, cmd) + cmd = re.sub("", core_setting_dir, cmd) if ext_dir == "": cmd = re.sub("", "/user_extension", cmd) else: @@ -253,6 +249,7 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts): isa : ISA variant passed to GCC mabi : MABI variant passed to GCC """ + cwd = os.path.dirname(os.path.realpath(__file__)) for test in test_list: for i in range(0, test['iterations']): if 'no_gcc' in test and test['no_gcc'] == 1: @@ -261,20 +258,24 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts): asm = prefix + ".S" elf = prefix + ".o" binary = prefix + ".bin" + test_isa = isa # gcc comilation cmd = ("%s -static -mcmodel=medany \ -fvisibility=hidden -nostdlib \ -nostartfiles %s \ -I%s/user_extension \ -T%s/scripts/link.ld %s -o %s " % \ - (get_env_var("RISCV_GCC"), asm, get_env_var("RISCV_DV_ROOT"), - get_env_var("RISCV_DV_ROOT"), opts, elf)) + (get_env_var("RISCV_GCC"), asm, cwd, cwd, opts, elf)) if 'gcc_opts' in test: cmd += test['gcc_opts'] + if 'gen_opts' in test: + # Disable compressed instruction + if re.search('disable_compressed_instr', test['gen_opts']): + test_isa = re.sub("c", "", test_isa) # If march/mabi is not defined in the test gcc_opts, use the default # setting from the command line. if not re.search('march', cmd): - cmd += (" -march=%s" % isa) + cmd += (" -march=%s" % test_isa) if not re.search('mabi', cmd): cmd += (" -mabi=%s" % mabi) logging.info("Compiling %s" % asm) @@ -298,6 +299,7 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, iss): mabi : MABI variant passed to GCC iss : Instruction set simulators """ + cwd = os.path.dirname(os.path.realpath(__file__)) asm = asm_test elf = asm_test + ".o" binary = asm_test + ".bin" @@ -309,8 +311,7 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, iss): -nostartfiles %s \ -I%s/user_extension \ -T%s/scripts/link.ld -o %s " % \ - (get_env_var("RISCV_GCC"), asm, get_env_var("RISCV_DV_ROOT"), - get_env_var("RISCV_DV_ROOT"), elf)) + (get_env_var("RISCV_GCC"), asm, cwd, cwd, elf)) cmd += (" -march=%s" % isa) cmd += (" -mabi=%s" % mabi) logging.info("Compiling %s" % asm) @@ -327,20 +328,21 @@ def run_assembly(asm_test, iss_yaml, isa, mabi, iss): logging.info("[%0s] Running ISS simulation: %s ...done" % (iss, elf)) -def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, timeout_s): +def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, setting_dir, timeout_s): """Run ISS simulation with the generated test program Args: - test_list : List of assembly programs to be compiled - output_dir : Output directory of the ELF files - iss_list : List of instruction set simulators - iss_yaml : ISS configuration file in YAML format - isa : ISA variant passed to the ISS - timeout_s : Timeout limit in seconds + test_list : List of assembly programs to be compiled + output_dir : Output directory of the ELF files + iss_list : List of instruction set simulators + iss_yaml : ISS configuration file in YAML format + isa : ISA variant passed to the ISS + setting_dir : Generator setting directory + timeout_s : Timeout limit in seconds """ for iss in iss_list.split(","): log_dir = ("%s/%s_sim" % (output_dir, iss)) - base_cmd = parse_iss_yaml(iss, iss_yaml, isa) + base_cmd = parse_iss_yaml(iss, iss_yaml, isa, setting_dir) logging.info("%s sim log dir: %s" % (iss, log_dir)) subprocess.run(["mkdir", "-p", log_dir]) for test in test_list: @@ -408,6 +410,9 @@ def setup_parser(): # Parse input arguments parser = argparse.ArgumentParser() + parser.add_argument("--target", type=str, default="rv64imc", + help="Run the generator with pre-defined targets: \ + rv32imc, rv32i, rv64imc, rv64gc") parser.add_argument("-o", "--output", type=str, help="Output directory name", dest="o") parser.add_argument("-tl", "--testlist", type=str, default="", @@ -441,15 +446,15 @@ def setup_parser(): parser.add_argument("--lsf_cmd", type=str, default="", help="LSF command. Run in local sequentially if lsf \ command is not specified") - parser.add_argument("--isa", type=str, default="rv64gc", + parser.add_argument("--isa", type=str, default="", help="RISC-V ISA subset") - parser.add_argument("-m", "--mabi", type=str, default="lp64", - help="mabi used for compilation, lp32 or lp64", dest="mabi") + parser.add_argument("-m", "--mabi", type=str, default="", + help="mabi used for compilation", dest="mabi") parser.add_argument("--gen_timeout", type=int, default=360, help="Generator timeout limit in seconds") parser.add_argument("--end_signature_addr", type=str, default="0", help="Address that privileged CSR test writes to at EOT") - parser.add_argument("--iss_timeout", type=int, default=25, + parser.add_argument("--iss_timeout", type=int, default=10, help="ISS sim timeout limit in seconds") parser.add_argument("--iss_yaml", type=str, default="", help="ISS setting YAML") @@ -460,15 +465,14 @@ def setup_parser(): parser.add_argument("--seed_yaml", type=str, default="", help="Rerun the generator with the seed specification \ from a prior regression") + parser.add_argument("-ct", "--custom_target", type=str, default="", + help="Directory name of the custom target") parser.add_argument("-cs", "--core_setting_dir", type=str, default="", help="Path for the riscv_core_setting.sv") parser.add_argument("-ext", "--user_extension_dir", type=str, default="", help="Path for the user extension directory") parser.add_argument("--asm_test", type=str, default="", help="Directed assembly test") - parser.add_argument("--target", type=str, default="", - help="Run the generator with pre-defined targets: \ - rv32imc, rv32i, rv64imc") parser.add_argument("--log_suffix", type=str, default="", help="Simulation log name suffix") parser.add_argument("-bz", "--batch_size", type=int, default=0, @@ -483,10 +487,10 @@ def setup_parser(): def main(): """This is the main entry point.""" - check_riscv_dv_setting() parser = setup_parser() args = parser.parse_args() cwd = os.path.dirname(os.path.realpath(__file__)) + os.environ["RISCV_DV_ROOT"] = cwd setup_logging(args.verbose) if not args.csr_yaml: @@ -498,8 +502,17 @@ def main(): if not args.simulator_yaml: args.simulator_yaml = cwd + "/yaml/simulator.yaml" - if args.target: - args.testlist = cwd + "/target/"+ args.target +"/testlist.yaml" + # Keep the core_setting_dir option to be backward compatible, suggest to use + # --custom_target + if args.core_setting_dir: + if not args.custom_target: + args.custom_target = args.core_setting_dir + else: + args.core_setting_dir = args.custom_target + + if not args.custom_target: + if not args.testlist: + args.testlist = cwd + "/target/"+ args.target +"/testlist.yaml" args.core_setting_dir = cwd + "/target/"+ args.target if args.target == "rv32imc": args.mabi = "ilp32" @@ -510,10 +523,16 @@ def main(): elif args.target == "rv64imc": args.mabi = "lp64" args.isa = "rv64imc" + elif args.target == "ml": + args.mabi = "lp64" + args.isa = "rv64imc" else: - print ("Unsupported target: %0s" % args.target) - elif not args.testlist: - args.testlist = cwd + "/yaml/testlist.yaml" + print ("Unsupported pre-defined target: %0s" % args.target) + else: + if (not args.mabi) or (not args.isa): + sys.exit("mabi and isa must be specified for custom target %0s" % args.custom_target) + if not args.testlist: + args.testlist = args.custom_target + "/testlist.yaml" if args.asm_test != "": run_assembly(args.asm_test, args.iss_yaml, args.isa, args.mabi, args.iss) @@ -553,7 +572,7 @@ def main(): # Run ISS simulation if args.steps == "all" or re.match(".*iss_sim.*", args.steps): iss_sim(matched_list, output_dir, args.iss, args.iss_yaml, - args.isa, args.iss_timeout) + args.isa, args.core_setting_dir, args.iss_timeout) # Compare ISS simulation result if args.steps == "all" or re.match(".*iss_cmp.*", args.steps): diff --git a/vendor/google_riscv-dv/scripts/__init__.py b/vendor/google_riscv-dv/scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/vendor/google_riscv-dv/scripts/instr_trace_compare.py b/vendor/google_riscv-dv/scripts/instr_trace_compare.py index dc9dab2d..2ebf9243 100644 --- a/vendor/google_riscv-dv/scripts/instr_trace_compare.py +++ b/vendor/google_riscv-dv/scripts/instr_trace_compare.py @@ -47,8 +47,8 @@ def compare_trace_csv(csv1, csv2, name1, name2, log, with open(csv1, "r") as fd1, open(csv2, "r") as fd2: instr_trace_1 = [] instr_trace_2 = [] - trace_csv_1 = RiscvInstructiontTraceCsv(fd1) - trace_csv_2 = RiscvInstructiontTraceCsv(fd2) + trace_csv_1 = RiscvInstructionTraceCsv(fd1) + trace_csv_2 = RiscvInstructionTraceCsv(fd2) trace_csv_1.read_trace(instr_trace_1) trace_csv_2.read_trace(instr_trace_2) trace_1_index = 0 @@ -173,7 +173,7 @@ def compare_trace_csv(csv1, csv2, name1, name2, log, name1, len(gpr_trace_1[gpr]), name2, len(gpr_trace_2[gpr]))) else: if not gpr_trace_2.get(gpr): - trace = RiscvInstructiontTraceEntry() + trace = RiscvInstructionTraceEntry() trace.rd_val = "0" trace.rd = gpr trace.instr_str = "" diff --git a/vendor/google_riscv-dv/scripts/lib.py b/vendor/google_riscv-dv/scripts/lib.py index 5c2b0660..695fb0ad 100644 --- a/vendor/google_riscv-dv/scripts/lib.py +++ b/vendor/google_riscv-dv/scripts/lib.py @@ -75,15 +75,6 @@ def get_env_var(var): return val -def check_riscv_dv_setting(): - """Check the RISCV-DV directory setting, default "." - """ - try: - val = os.environ["RISCV_DV_ROOT"] - except KeyError: - os.environ["RISCV_DV_ROOT"] = "." - - def get_seed(seed): """Get the seed to run the generator @@ -112,6 +103,7 @@ def run_cmd(cmd, timeout_s = 999): try: ps = subprocess.Popen("exec " + cmd, shell=True, + executable='/bin/bash', universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -141,6 +133,7 @@ def run_parallel_cmd(cmd_list, timeout_s = 999): for cmd in cmd_list: ps = subprocess.Popen("exec " + cmd, shell=True, + executable='/bin/bash', universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) diff --git a/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py b/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py index 57c1a42b..e3129ab0 100644 --- a/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py +++ b/vendor/google_riscv-dv/scripts/ovpsim_log_to_trace_csv.py @@ -70,7 +70,52 @@ def process_if_compressed(prev_trace): prev_trace.instr = "c."+prev_trace.instr # logging.debug("process_if_compressed(%s, %s)" % (prev_trace.instr, prev_trace.binary)) -def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0): +pseudos={ + 'mv' :'addi', + 'not' :'xori', + 'neg' :'sub', + 'negw' :'subw', + 'sext.w' :'addiw', + 'seqz' :'sltiu', + 'snez' :'sltu', + 'sltz' :'slt', + 'sgtz' :'slt', + 'beqz' :'beg', + 'bnez' :'bnez', + 'bgez' :'bgez', + 'bltz' :'blt', + 'blez' :'bge', + 'bgtz' :'blt', + 'csrr' :'csrrw', + 'csrw' :'csrrw', + 'csrs' :'csrrs', + 'csrc' :'csrrc', + 'csrwi' :'csrrwi', + 'csrsi' :'csrrsi', + 'csrci' :'csrrci', + 'j' :'jal', + 'jr' :'jal', + } +def check_conversion(entry, stop_on_first_error): + instr_str_0 =entry.instr_str.split(" ")[0] + instr =entry.instr.split(" ")[0] + if "c." in instr[0:2]: + instr = instr[2:] + if instr in instr_str_0: + return # same + #logging.debug("converted pseudo %10s -> %s" % (instr_str_0, instr)) + if instr_str_0 in pseudos: + p_instr = pseudos[instr_str_0] + if p_instr in instr: + return # is pseudo, converted ok + logging.error("converted %10s -> %s <<-- not correct pseudo (%s)" % (instr_str_0, instr, p_instr)) + if stop_on_first_error: + sys.exit(-1) + logging.error("converted %10s -> %s <<-- not correct at all" % (instr_str_0, instr)) + if stop_on_first_error: + sys.exit(-1) + +def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0, stop_on_first_error = 1): """Process OVPsim simulation log. Extract instruction and affected register information from ovpsim simulation @@ -95,7 +140,7 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0): gpr[g] = 0 with open(ovpsim_log, "r") as f, open(csv, "w") as csv_fd: - trace_csv = RiscvInstructiontTraceCsv(csv_fd) + trace_csv = RiscvInstructionTraceCsv(csv_fd) trace_csv.start_new_trace() prev_trace = 0 for line in f: @@ -104,20 +149,22 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0): "(?P[A-Za-z]*?)\s+(?P[a-f0-9]*?)\s+(?P.*?)$", line) if m: if prev_trace: # if not yet written as it had no data following it + check_conversion(prev_trace, stop_on_first_error) trace_csv.write_trace_entry(prev_trace) prev_trace = 0 trace_bin = m.group("bin") trace_instr_str = m.group("instr") trace_addr = m.group("addr") - trace_section = m.group("section") # not yet used - #trace_mode = convert_mode(m.group("mode"), line) + trace_section = m.group("section") + trace_mode = convert_mode(m.group("mode"), line) + trace_instr = trace_instr_str.split(" ")[0] instr_cnt += 1 - prev_trace = RiscvInstructiontTraceEntry() + prev_trace = RiscvInstructionTraceEntry() prev_trace.instr_str = trace_instr_str prev_trace.binary = trace_bin prev_trace.addr = trace_addr - #prev_trace.privileged_mode = trace_mode - prev_trace.instr = trace_instr # wrong + prev_trace.privileged_mode = trace_mode + prev_trace.instr = trace_instr if 0: print ("line ::"+line) @@ -126,18 +173,13 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0): print ("ins ::"+trace_instr) print ("addr ::"+trace_addr) print ("sect ::"+trace_section) - #print ("mode ::"+prev_trace.privileged_mode) + print ("mode ::"+trace_mode) sys.exit(-1) if full_trace: i = re.search (r"(?P[a-z]*?)\s", trace_instr_str) if i: trace_instr = i.group("instr") - if trace_instr_str == "nop" or \ - trace_instr_str == "mret" or \ - trace_instr_str == "ecall" : - # this will probably need also doing for things like wfi too - trace_instr = trace_instr_str prev_trace.instr = trace_instr process_if_compressed(prev_trace) o = re.search (r"(?P[a-z]*?)\s(?P.*)", trace_instr_str) @@ -148,7 +190,6 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0): process_jalr(prev_trace, operands, gpr) else: assign_operand(prev_trace, operands, gpr) - # sys.exit(-1) else: # print("no operand for [%s] in [%s]" % (trace_instr, trace_instr_str)) pass @@ -164,29 +205,28 @@ def process_ovpsim_sim_log(ovpsim_log, csv, full_trace = 0): # Write the extracted instruction to a csvcol buffer file # print("%0s %0s = %0s" % (trace_instr_str, m.group("rd"), m.group("val"))) if n.group("rd") != "frm": - rv_instr_trace = RiscvInstructiontTraceEntry() - rv_instr_trace.rd = n.group("rd") - rv_instr_trace.rd_val = n.group("val") - rv_instr_trace.rs1 = prev_trace.rs1 - rv_instr_trace.rs1_val = prev_trace.rs1_val - rv_instr_trace.rs2 = prev_trace.rs2 - rv_instr_trace.rs2_val = prev_trace.rs2_val - rv_instr_trace.instr_str = trace_instr_str - rv_instr_trace.instr = prev_trace.instr - rv_instr_trace.binary = trace_bin - rv_instr_trace.addr = trace_addr - #rv_instr_trace.privileged_mode = trace_mode - gpr[rv_instr_trace.rd] = rv_instr_trace.rd_val - if full_trace: - rv_instr_trace.instr = prev_trace.instr + rv_instr_trace = RiscvInstructionTraceEntry() + rv_instr_trace.rd = n.group("rd") + rv_instr_trace.rd_val = n.group("val") + rv_instr_trace.rs1 = prev_trace.rs1 + rv_instr_trace.rs1_val = prev_trace.rs1_val + rv_instr_trace.rs2 = prev_trace.rs2 + rv_instr_trace.rs2_val = prev_trace.rs2_val + rv_instr_trace.instr_str = trace_instr_str + rv_instr_trace.instr = prev_trace.instr + rv_instr_trace.binary = trace_bin + rv_instr_trace.addr = trace_addr + rv_instr_trace.privileged_mode = trace_mode + gpr[rv_instr_trace.rd] = rv_instr_trace.rd_val + check_conversion(rv_instr_trace, stop_on_first_error) trace_csv.write_trace_entry(rv_instr_trace) prev_trace = 0 # we wrote out as it had data, so no need to write it next time round if 0: - print ("write entry [[%d]]: rd[%s] val[%s] instr(%s) bin(%s) addr(%s)" - % (instr_cnt, rv_instr_trace.rd, rv_instr_trace.rd_val, - trace_instr_str, trace_bin, trace_addr)) - print (rv_instr_trace.__dict__) - sys.exit(-1) + print ("write entry [[%d]]: rd[%s] val[%s] instr(%s) bin(%s) addr(%s)" + % (instr_cnt, rv_instr_trace.rd, rv_instr_trace.rd_val, + trace_instr_str, trace_bin, trace_addr)) + print (rv_instr_trace.__dict__) + sys.exit(-1) else: if 0: print ("write previous entry: [%s] %s " % (str(instr_cnt), line)) diff --git a/vendor/google_riscv-dv/scripts/riscv_trace_csv.py b/vendor/google_riscv-dv/scripts/riscv_trace_csv.py index 9f4cf0ac..b3a06d7d 100644 --- a/vendor/google_riscv-dv/scripts/riscv_trace_csv.py +++ b/vendor/google_riscv-dv/scripts/riscv_trace_csv.py @@ -20,7 +20,7 @@ import csv import re import logging -class RiscvInstructiontTraceEntry(object): +class RiscvInstructionTraceEntry(object): """RISC-V instruction trace entry""" def __init__(self): self.rd = "" @@ -43,7 +43,7 @@ class RiscvInstructiontTraceEntry(object): return ("%s -> %s(0x%s) addr:0x%s" % (self.instr_str, self.rd, self.rd_val, self.addr)) -class RiscvInstructiontTraceCsv(object): +class RiscvInstructionTraceCsv(object): """RISC-V instruction trace CSV class This class provides functions to read/write trace CSV @@ -66,7 +66,7 @@ class RiscvInstructiontTraceCsv(object): """Read instruction trace from CSV file""" csv_reader = csv.DictReader(self.csv_fd) for row in csv_reader: - new_trace = RiscvInstructiontTraceEntry() + new_trace = RiscvInstructionTraceEntry() new_trace.rd = row['rd'] new_trace.rd_val = row['rd_val'] new_trace.addr = row['addr'] diff --git a/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py b/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py index 061da717..91c5e4d2 100644 --- a/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py +++ b/vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py @@ -45,7 +45,7 @@ def process_sail_sim_log(sail_log, csv): with open(sail_log, "r") as f, open(csv, "w") as csv_fd: search_start = 0 instr_start = 0 - trace_csv = RiscvInstructiontTraceCsv(csv_fd) + trace_csv = RiscvInstructionTraceCsv(csv_fd) trace_csv.start_new_trace() instr = None for line in f: @@ -71,7 +71,7 @@ def process_sail_sim_log(sail_log, csv): if m: # Write the extracted instruction to a csvcol buffer file instr_cnt += 1 - rv_instr_trace = RiscvInstructiontTraceEntry() + rv_instr_trace = RiscvInstructionTraceEntry() rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("reg")) rv_instr_trace.rd_val = m.group("val").lower() rv_instr_trace.privileged_mode = pri diff --git a/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py b/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py index ba7f713e..25c47a54 100644 --- a/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py +++ b/vendor/google_riscv-dv/scripts/spike_log_to_trace_csv.py @@ -59,7 +59,7 @@ def process_spike_sim_log(spike_log, csv, full_trace = 0): gpr["zero"] = 0 with open(spike_log, "r") as f, open(csv, "w") as csv_fd: - trace_csv = RiscvInstructiontTraceCsv(csv_fd) + trace_csv = RiscvInstructionTraceCsv(csv_fd) trace_csv.start_new_trace() for line in f: # Extract instruction infromation @@ -67,7 +67,7 @@ def process_spike_sim_log(spike_log, csv, full_trace = 0): if m: spike_instr = m.group("instr").replace("pc + ", "") spike_instr = spike_instr.replace("pc - ", "-") - rv_instr_trace = RiscvInstructiontTraceEntry() + rv_instr_trace = RiscvInstructionTraceEntry() rv_instr_trace.instr_str = spike_instr rv_instr_trace.addr = m.group("addr") rv_instr_trace.binary = m.group("bin") diff --git a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv index 2e579d16..bb1791f1 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -340,13 +340,14 @@ class riscv_asm_program_gen extends uvm_object; init_floating_point_gpr(); end core_is_initialized(); + gen_dummy_csr_write(); endfunction // Setup MISA based on supported extensions virtual function void setup_misa(); bit [XLEN-1:0] misa; - misa[XLEN-1:XLEN-3] = (XLEN == 32) ? 1 : - (XLEN == 64) ? 2 : 3; + misa[XLEN-1:XLEN-2] = (XLEN == 32) ? 2'b01 : + (XLEN == 64) ? 2'b10 : 2'b11; if (cfg.check_misa_init_val) begin instr_stream.push_back({indent, "csrr x15, misa"}); end @@ -384,6 +385,37 @@ class riscv_asm_program_gen extends uvm_object; end endfunction + // Generate some dummy writes to xSTATUS/xIE at the beginning of the test to check + // repeated writes to these CSRs. + virtual function void gen_dummy_csr_write(); + string instr[$]; + case (cfg.init_privileged_mode) + MACHINE_MODE: begin + instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[0], MSTATUS)); + instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[1], MIE)); + instr.push_back($sformatf("csrw 0x%0x, x%0d", MSTATUS, cfg.gpr[0])); + instr.push_back($sformatf("csrw 0x%0x, x%0d", MIE, cfg.gpr[1])); + end + SUPERVISOR_MODE: begin + instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[0], SSTATUS)); + instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[1], SIE)); + instr.push_back($sformatf("csrw 0x%0x, x%0d", SSTATUS, cfg.gpr[0])); + instr.push_back($sformatf("csrw 0x%0x, x%0d", SIE, cfg.gpr[1])); + end + USER_MODE: begin + instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[0], USTATUS)); + instr.push_back($sformatf("csrr x%0d, 0x%0x", cfg.gpr[1], UIE)); + instr.push_back($sformatf("csrw 0x%0x, x%0d", USTATUS, cfg.gpr[0])); + instr.push_back($sformatf("csrw 0x%0x, x%0d", UIE, cfg.gpr[1])); + end + default: begin + `uvm_fatal(`gfn, "Unsupported boot mode") + end + endcase + format_section(instr); + instr_stream = {instr_stream, instr}; + endfunction + // Initialize general purpose registers with random value virtual function void init_gpr(); string str; @@ -1103,9 +1135,14 @@ class riscv_asm_program_gen extends uvm_object; virtual function void get_directed_instr_stream(); string args, val; + string stream_name_opts, stream_freq_opts; + string stream_name; + int stream_freq; string opts[$]; for (int i=0; i $signed(rs2_value)); BLTU : is_branch_hit = (rs1_value < rs2_value); BGEU : is_branch_hit = (rs1_value > rs2_value); - BGEU : is_branch_hit = (rs1_value > rs2_value); default: `uvm_error(get_name(), $sformatf("Unexpected instr %0s", instr_name.name())) endcase return is_branch_hit; diff --git a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv index e3e89f33..f101baf9 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv @@ -122,7 +122,7 @@ class riscv_instr_gen_config extends uvm_object; riscv_instr_base instr_template[riscv_instr_name_t]; riscv_instr_name_t basic_instr[$]; riscv_instr_name_t instr_group[riscv_instr_group_t][$]; - riscv_instr_name_t instr_category[riscv_instr_cateogry_t][$]; + riscv_instr_name_t instr_category[riscv_instr_category_t][$]; //----------------------------------------------------------------------------- // Command line options or control knobs @@ -152,7 +152,10 @@ class riscv_instr_gen_config extends uvm_object; // A name suffix for the generated assembly program string asm_test_suffix; // Enable interrupt bit in MSTATUS (MIE, SIE, UIE) - int enable_interrupt; + bit enable_interrupt; + // We need a separate control knob for enabling timer interrupts, as Spike + // throws an exception if xIE.xTIE is enabled + bit enable_timer_irq; // Generate a bare program without any init/exit/error handling/page table routines // The generated program can be integrated with a larger program. // Note that the bare mode program is not expected to run in standalone mode @@ -204,6 +207,12 @@ class riscv_instr_gen_config extends uvm_object; // Floating point support bit enable_floating_point; + //----------------------------------------------------------------------------- + // Command line options for instruction distribution control + //----------------------------------------------------------------------------- + int dist_control_mode; + int unsigned category_dist[riscv_instr_category_t]; + uvm_cmdline_processor inst; constraint default_c { @@ -381,7 +390,8 @@ class riscv_instr_gen_config extends uvm_object; inst = uvm_cmdline_processor::get_inst(); get_int_arg_value("+num_of_tests=", num_of_tests); get_int_arg_value("+enable_page_table_exception=", enable_page_table_exception); - get_int_arg_value("+enable_interrupt=", enable_interrupt); + get_bool_arg_value("+enable_interrupt=", enable_interrupt); + get_bool_arg_value("+enable_timer_irq=", enable_timer_irq); get_int_arg_value("+num_of_sub_program=", num_of_sub_program); get_int_arg_value("+instr_cnt=", instr_cnt); get_bool_arg_value("+no_ebreak=", no_ebreak); @@ -449,6 +459,30 @@ class riscv_instr_gen_config extends uvm_object; if (!(RV32C inside {supported_isa})) begin disable_compressed_instr = 1; end + setup_instr_distribution(); + endfunction + + function void setup_instr_distribution(); + string opts; + int val; + get_int_arg_value("+dist_control_mode=", dist_control_mode); + if (dist_control_mode == 1) begin + riscv_instr_category_t category; + category = category.first; + do begin + opts = {$sformatf("dist_%0s=", category.name()), "%d"}; + opts = opts.tolower(); + if ($value$plusargs(opts, val)) begin + category_dist[category] = val; + end else begin + category_dist[category] = 10; // Default ratio + end + `uvm_info(`gfn, $sformatf("Set dist[%0s] = %0d", + category.name(), category_dist[category]), UVM_LOW) + category = category.next; + end + while(category != category.first); + end endfunction // Initialize the exception/interrupt delegation associate array, set all delegation default to 0 diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index 67092d9b..6439deb0 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -372,7 +372,7 @@ package riscv_instr_pkg; TRAP, INTERRUPT, AMO - } riscv_instr_cateogry_t; + } riscv_instr_category_t; typedef bit [11:0] riscv_csr_t; diff --git a/vendor/google_riscv-dv/src/riscv_instr_stream.sv b/vendor/google_riscv-dv/src/riscv_instr_stream.sv index 88512dee..7b9dfd1b 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_stream.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_stream.sv @@ -157,6 +157,7 @@ class riscv_rand_instr_stream extends riscv_instr_stream; riscv_instr_gen_config cfg; bit kernel_mode; riscv_instr_name_t allowed_instr[$]; + int unsigned category_dist[riscv_instr_category_t]; `uvm_object_utils(riscv_rand_instr_stream) `uvm_object_new @@ -177,6 +178,21 @@ class riscv_rand_instr_stream extends riscv_instr_stream; if (no_load_store == 0) begin allowed_instr = {allowed_instr, cfg.instr_category[LOAD], cfg.instr_category[STORE]}; end + setup_instruction_dist(no_branch, no_load_store); + endfunction + + function setup_instruction_dist(bit no_branch = 1'b0, bit no_load_store = 1'b1); + if (cfg.dist_control_mode) begin + category_dist = cfg.category_dist; + if (no_branch) begin + category_dist[BRANCH] = 0; + end + if (no_load_store) begin + category_dist[LOAD] = 0; + category_dist[STORE] = 0; + end + `uvm_info(`gfn, $sformatf("setup_instruction_dist: %0d", category_dist.size()), UVM_LOW) + end endfunction virtual function void gen_instr(bit no_branch = 1'b0, bit no_load_store = 1'b1, @@ -199,11 +215,28 @@ class riscv_rand_instr_stream extends riscv_instr_stream; bit skip_rs2 = 1'b0, bit skip_rd = 1'b0, bit skip_imm = 1'b0, - bit skip_csr = 1'b0); + bit skip_csr = 1'b0, + bit disable_dist = 1'b0); riscv_instr_name_t instr_name; + if ((cfg.dist_control_mode == 1) && !disable_dist) begin + riscv_instr_category_t category; + int unsigned idx; + `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(category, + category dist {LOAD := category_dist[LOAD], + STORE := category_dist[STORE], + SHIFT := category_dist[SHIFT], + ARITHMETIC := category_dist[ARITHMETIC], + LOGICAL := category_dist[LOGICAL], + COMPARE := category_dist[COMPARE], + BRANCH := category_dist[BRANCH], + SYNCH := category_dist[SYNCH], + CSR := category_dist[CSR]};) + idx = $urandom_range(0, cfg.instr_category[category].size() - 1); + instr_name = cfg.instr_category[category][idx]; // if set_dcsr_ebreak is set, we do not want to generate any ebreak // instructions inside the debug_rom - if ((cfg.no_ebreak && !is_in_debug) || (!cfg.enable_ebreak_in_debug_rom && is_in_debug)) begin + end else if ((cfg.no_ebreak && !is_in_debug) || + (!cfg.enable_ebreak_in_debug_rom && is_in_debug)) begin `DV_CHECK_STD_RANDOMIZE_WITH_FATAL(instr_name, instr_name inside {allowed_instr}; !(instr_name inside {EBREAK, C_EBREAK});) diff --git a/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv b/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv index 849cf063..e26e9350 100644 --- a/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv +++ b/vendor/google_riscv-dv/src/riscv_load_store_instr_lib.sv @@ -164,7 +164,7 @@ class riscv_load_store_base_instr_stream extends riscv_mem_access_stream; end end end - randomize_instr(instr, .skip_rs1(1'b1), .skip_imm(1'b1)); + randomize_instr(instr, .skip_rs1(1'b1), .skip_imm(1'b1), .disable_dist(1'b1)); instr.rs1 = rs1_reg; instr.set_imm(offset[i]); instr.process_load_store = 0; @@ -182,7 +182,7 @@ class riscv_single_load_store_instr_stream extends riscv_load_store_base_instr_s num_mixed_instr < 5; } - `uvm_object_utils(riscv_load_store_base_instr_stream) + `uvm_object_utils(riscv_single_load_store_instr_stream) `uvm_object_new endclass diff --git a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv index 3f25079c..d0986326 100644 --- a/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv +++ b/vendor/google_riscv-dv/src/riscv_privileged_common_seq.sv @@ -95,12 +95,9 @@ class riscv_privileged_common_seq extends uvm_sequence; mie.set_field("USIE", cfg.enable_interrupt); mie.set_field("SSIE", cfg.enable_interrupt); mie.set_field("MSIE", cfg.enable_interrupt); - // TODO(udinator) - since full CSRs are being randomized, it's necessary to hardwire the xTIE - // fields to 1'b0, as it causes some timer interrupts to be triggered in Spike after a certain - // amount of simulation time. - mie.set_field("MTIE", 1'b0); - mie.set_field("STIE", 1'b0); - mie.set_field("UTIE", 1'b0); + mie.set_field("MTIE", cfg.enable_interrupt & cfg.enable_timer_irq); + mie.set_field("STIE", cfg.enable_interrupt & cfg.enable_timer_irq); + mie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq); regs.push_back(mie); end endfunction @@ -136,8 +133,8 @@ class riscv_privileged_common_seq extends uvm_sequence; sie.set_field("SEIE", cfg.enable_interrupt); sie.set_field("USIE", cfg.enable_interrupt); sie.set_field("SSIE", cfg.enable_interrupt); - sie.set_field("STIE", 1'b0); - sie.set_field("UTIE", 1'b0); + sie.set_field("STIE", cfg.enable_interrupt & cfg.enable_timer_irq); + sie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq); regs.push_back(sie); end endfunction @@ -160,7 +157,7 @@ class riscv_privileged_common_seq extends uvm_sequence; end uie.set_field("UEIE", cfg.enable_interrupt); uie.set_field("USIE", cfg.enable_interrupt); - uie.set_field("UTIE", 1'b0); + uie.set_field("UTIE", cfg.enable_interrupt & cfg.enable_timer_irq); regs.push_back(uie); end endfunction diff --git a/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic b/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic new file mode 100644 index 00000000..8712e05c --- /dev/null +++ b/vendor/google_riscv-dv/target/ml/riscvOVPsim.ic @@ -0,0 +1,19 @@ +# riscOVPsim configuration file converted from YAML +--variant RV64I +--override riscvOVPsim/cpu/add_Extensions=MC +--override riscvOVPsim/cpu/misa_MXL=2 +--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 +--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 +--override riscvOVPsim/cpu/unaligned=T +--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 +--override riscvOVPsim/cpu/user_version=2.3 +--override riscvOVPsim/cpu/priv_version=1.11 +--override riscvOVPsim/cpu/mvendorid=0 +--override riscvOVPsim/cpu/marchid=0 +--override riscvOVPsim/cpu/mimpid=0 +--override riscvOVPsim/cpu/mhartid=0 +--override riscvOVPsim/cpu/cycle_undefined=F +--override riscvOVPsim/cpu/instret_undefined=F +--override riscvOVPsim/cpu/time_undefined=T +--override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/simulateexceptions=T diff --git a/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv b/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv new file mode 100644 index 00000000..207df4d2 --- /dev/null +++ b/vendor/google_riscv-dv/target/ml/riscv_core_setting.sv @@ -0,0 +1,104 @@ +/* + * Copyright 2019 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//----------------------------------------------------------------------------- +// Processor feature configuration +//----------------------------------------------------------------------------- +// XLEN +parameter int XLEN = 64; + +// Parameter for SATP mode, set to BARE if address translation is not supported +parameter satp_mode_t SATP_MODE = BARE; + +// Supported Privileged mode +privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE}; + +// Unsupported instructions +riscv_instr_name_t unsupported_instr[]; + +// ISA supported by the processor +riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C}; + +// Interrupt mode support +mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED}; + +// The number of interrupt vectors to be generated, only used if VECTORED interrupt mode is +// supported +int max_interrupt_vector_num = 16; + +// Debug mode support +bit support_debug_mode = 0; + +// Support delegate trap to user mode +bit support_umode_trap = 0; + +// Support sfence.vma instruction +bit support_sfence = 0; + +// ---------------------------------------------------------------------------- +// Previleged CSR implementation +// ---------------------------------------------------------------------------- + +// Implemented previlieged CSR list +`ifdef DSIM +privileged_reg_t implemented_csr[] = { +`else +parameter privileged_reg_t implemented_csr[] = { +`endif + // Machine mode mode CSR + MVENDORID, // Vendor ID + MARCHID, // Architecture ID + MIMPID, // Implementation ID + MHARTID, // Hardware thread ID + MSTATUS, // Machine status + MISA, // ISA and extensions + MIE, // Machine interrupt-enable register + MTVEC, // Machine trap-handler base address + MCOUNTEREN, // Machine counter enable + MSCRATCH, // Scratch register for machine trap handlers + MEPC, // Machine exception program counter + MCAUSE, // Machine trap cause + MTVAL, // Machine bad address or instruction + MIP // Machine interrupt pending +}; + +// ---------------------------------------------------------------------------- +// Supported interrupt/exception setting, used for functional coverage +// ---------------------------------------------------------------------------- + +`ifdef DSIM +interrupt_cause_t implemented_interrupt[] = { +`else +parameter interrupt_cause_t implemented_interrupt[] = { +`endif + M_SOFTWARE_INTR, + M_TIMER_INTR, + M_EXTERNAL_INTR +}; + +`ifdef DSIM +exception_cause_t implemented_exception[] = { +`else +parameter exception_cause_t implemented_exception[] = { +`endif + INSTRUCTION_ADDRESS_MISALIGNED, + INSTRUCTION_ACCESS_FAULT, + ILLEGAL_INSTRUCTION, + BREAKPOINT, + LOAD_ADDRESS_MISALIGNED, + LOAD_ACCESS_FAULT, + ECALL_MMODE +}; diff --git a/vendor/google_riscv-dv/target/ml/testlist.yaml b/vendor/google_riscv-dv/target/ml/testlist.yaml new file mode 100644 index 00000000..171b0a20 --- /dev/null +++ b/vendor/google_riscv-dv/target/ml/testlist.yaml @@ -0,0 +1,64 @@ +# Copyright Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# ================================================================================ +# Regression test list format +# -------------------------------------------------------------------------------- +# test : Assembly test name +# description : Description of this test +# gen_opts : Instruction generator options +# iterations : Number of iterations of this test +# no_iss : Enable/disable ISS simulator (Optional) +# gen_test : Test name used by the instruction generator +# rtl_test : RTL simulation test name +# cmp_opts : Compile options passed to the instruction generator +# sim_opts : Simulation options passed to the instruction generator +# no_post_compare : Enable/disable comparison of trace log and ISS log (Optional) +# compare_opts : Options for the RTL & ISS trace comparison +# gcc_opts : gcc compile options +# -------------------------------------------------------------------------------- + +- test: riscv_rand_test + description: > + Random test with all useful knobs + gen_opts: > + +instr_cnt=10000 + +num_of_sub_program=5 + +illegal_instr_ratio=5 + +hint_instr_ratio=5 + +stream_name_0=riscv_load_store_rand_instr_stream + +stream_freq_0=4 + +stream_name_1=riscv_loop_instr + +stream_freq_1=4 + +stream_name_2=riscv_hazard_instr_stream + +stream_freq_2=4 + +stream_name_3=riscv_load_store_hazard_instr_stream + +stream_freq_3=4 + +stream_name_4=riscv_mem_region_stress_test + +stream_freq_4=4 + +stream_name_5=riscv_jal_instr + +stream_freq_5=4 + +dist_control_mode=1 + +dist_shift=10 + +dist_arithmetic=10 + +dist_logical=10 + +dist_compare=10 + +dist_branch=10 + +dist_synch=10 + +dist_csr=10 + iterations: 1 + gcc_opts: > + -mno-strict-align + gen_test: riscv_ml_test + rtl_test: core_base_test diff --git a/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic index 0a584743..4281a3c8 100644 --- a/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/rv32i/riscvOVPsim.ic @@ -1,12 +1,10 @@ # riscOVPsim configuration file converted from YAML ---variant RVB32I +--variant RV32I --override riscvOVPsim/cpu/misa_MXL=1 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 --override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 --override riscvOVPsim/cpu/unaligned=T --override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 ---override riscvOVPsim/cpu/mtvec_is_ro=T ---override riscvOVPsim/cpu/mtvec=0x80000081 # 2147483777 --override riscvOVPsim/cpu/user_version=2.3 --override riscvOVPsim/cpu/priv_version=1.11 --override riscvOVPsim/cpu/mvendorid=0 @@ -16,6 +14,5 @@ --override riscvOVPsim/cpu/cycle_undefined=F --override riscvOVPsim/cpu/instret_undefined=F --override riscvOVPsim/cpu/time_undefined=T ---override riscvOVPsim/cpu/nmi_address=0x800000fc # 2147483900 ---override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/reset_address=0x80000000 --override riscvOVPsim/cpu/simulateexceptions=T diff --git a/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic index 4747b8ef..c7e9d0ab 100644 --- a/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/rv32imc/riscvOVPsim.ic @@ -1,13 +1,11 @@ # riscOVPsim configuration file converted from YAML ---variant RVB32I +--variant RV32I --override riscvOVPsim/cpu/add_Extensions=MC --override riscvOVPsim/cpu/misa_MXL=1 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 --override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 --override riscvOVPsim/cpu/unaligned=T --override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 ---override riscvOVPsim/cpu/mtvec_is_ro=T ---override riscvOVPsim/cpu/mtvec=0x80000081 # 2147483777 --override riscvOVPsim/cpu/user_version=2.3 --override riscvOVPsim/cpu/priv_version=1.11 --override riscvOVPsim/cpu/mvendorid=0 @@ -17,6 +15,5 @@ --override riscvOVPsim/cpu/cycle_undefined=F --override riscvOVPsim/cpu/instret_undefined=F --override riscvOVPsim/cpu/time_undefined=T ---override riscvOVPsim/cpu/nmi_address=0x800000fc # 2147483900 ---override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/reset_address=0x80000000 --override riscvOVPsim/cpu/simulateexceptions=T diff --git a/vendor/google_riscv-dv/target/rv32imc/testlist.yaml b/vendor/google_riscv-dv/target/rv32imc/testlist.yaml index 928ff811..688bb666 100644 --- a/vendor/google_riscv-dv/target/rv32imc/testlist.yaml +++ b/vendor/google_riscv-dv/target/rv32imc/testlist.yaml @@ -90,8 +90,6 @@ gen_test: riscv_rand_instr_test gen_opts: > +disable_compressed_instr=1 - gcc_opts: > - -march=rv32im rtl_test: core_base_test - test: riscv_rand_jump_test diff --git a/vendor/google_riscv-dv/target/rv64gc/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv64gc/riscvOVPsim.ic new file mode 100644 index 00000000..efe857bc --- /dev/null +++ b/vendor/google_riscv-dv/target/rv64gc/riscvOVPsim.ic @@ -0,0 +1,18 @@ +# riscOVPsim configuration file converted from YAML +--variant RV64GC +--override riscvOVPsim/cpu/misa_MXL=2 +--override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 +--override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 +--override riscvOVPsim/cpu/unaligned=T +--override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 +--override riscvOVPsim/cpu/user_version=2.3 +--override riscvOVPsim/cpu/priv_version=1.11 +--override riscvOVPsim/cpu/mvendorid=0 +--override riscvOVPsim/cpu/marchid=0 +--override riscvOVPsim/cpu/mimpid=0 +--override riscvOVPsim/cpu/mhartid=0 +--override riscvOVPsim/cpu/cycle_undefined=F +--override riscvOVPsim/cpu/instret_undefined=F +--override riscvOVPsim/cpu/time_undefined=T +--override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/simulateexceptions=T diff --git a/vendor/google_riscv-dv/setting/riscv_core_setting.sv b/vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv similarity index 100% rename from vendor/google_riscv-dv/setting/riscv_core_setting.sv rename to vendor/google_riscv-dv/target/rv64gc/riscv_core_setting.sv diff --git a/vendor/google_riscv-dv/yaml/testlist.yaml b/vendor/google_riscv-dv/target/rv64gc/testlist.yaml similarity index 99% rename from vendor/google_riscv-dv/yaml/testlist.yaml rename to vendor/google_riscv-dv/target/rv64gc/testlist.yaml index fcd726bf..6642b34f 100644 --- a/vendor/google_riscv-dv/yaml/testlist.yaml +++ b/vendor/google_riscv-dv/target/rv64gc/testlist.yaml @@ -90,7 +90,8 @@ gen_opts: > +instr_cnt=5000 +num_of_sub_program=5 - +directed_instr_1=riscv_jal_instr,20 + +stream_name_0=riscv_jal_instr + +stream_freq_0=10 rtl_test: core_base_test - test: riscv_loop_test @@ -111,8 +112,6 @@ gen_test: riscv_rand_instr_test gen_opts: > +disable_compressed_instr=1 - gcc_opts: > - -march=rv64im rtl_test: core_base_test - test: riscv_rand_jump_test diff --git a/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic b/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic index 91957941..8712e05c 100644 --- a/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic +++ b/vendor/google_riscv-dv/target/rv64imc/riscvOVPsim.ic @@ -1,13 +1,11 @@ # riscOVPsim configuration file converted from YAML ---variant RVB64I +--variant RV64I --override riscvOVPsim/cpu/add_Extensions=MC --override riscvOVPsim/cpu/misa_MXL=2 --override riscvOVPsim/cpu/misa_MXL_mask=0x0 # 0 --override riscvOVPsim/cpu/misa_Extensions_mask=0x0 # 0 --override riscvOVPsim/cpu/unaligned=T --override riscvOVPsim/cpu/mtvec_mask=0x0 # 0 ---override riscvOVPsim/cpu/mtvec_is_ro=T ---override riscvOVPsim/cpu/mtvec=0x80000081 # 2147483777 --override riscvOVPsim/cpu/user_version=2.3 --override riscvOVPsim/cpu/priv_version=1.11 --override riscvOVPsim/cpu/mvendorid=0 @@ -17,6 +15,5 @@ --override riscvOVPsim/cpu/cycle_undefined=F --override riscvOVPsim/cpu/instret_undefined=F --override riscvOVPsim/cpu/time_undefined=T ---override riscvOVPsim/cpu/nmi_address=0x800000fc # 2147483900 ---override riscvOVPsim/cpu/reset_address=0x80000000 +--override riscvOVPsim/cpu/reset_address=0x80000000 --override riscvOVPsim/cpu/simulateexceptions=T diff --git a/vendor/google_riscv-dv/target/rv64imc/testlist.yaml b/vendor/google_riscv-dv/target/rv64imc/testlist.yaml index 10089fc7..944da6e4 100644 --- a/vendor/google_riscv-dv/target/rv64imc/testlist.yaml +++ b/vendor/google_riscv-dv/target/rv64imc/testlist.yaml @@ -91,8 +91,6 @@ gen_test: riscv_rand_instr_test gen_opts: > +disable_compressed_instr=1 - gcc_opts: > - -march=rv64im rtl_test: core_base_test - test: riscv_rand_jump_test diff --git a/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv b/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv index 6c811f67..8d93b8b4 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv @@ -40,3 +40,21 @@ class riscv_rand_instr_test extends riscv_instr_base_test; endfunction endclass + +class riscv_ml_test extends riscv_instr_base_test; + + `uvm_component_utils(riscv_ml_test) + `uvm_component_new + + virtual function void randomize_cfg(); + cfg.no_fence = 0; + cfg.no_ebreak = 0; + cfg.init_privileged_mode = MACHINE_MODE; + cfg.init_privileged_mode.rand_mode(0); + cfg.enable_unaligned_load_store = 1'b1; + `DV_CHECK_RANDOMIZE_FATAL(cfg) + `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", + cfg.sprint()), UVM_LOW) + endfunction + +endclass diff --git a/vendor/google_riscv-dv/yaml/iss.yaml b/vendor/google_riscv-dv/yaml/iss.yaml index 0accb2a9..30a882a9 100644 --- a/vendor/google_riscv-dv/yaml/iss.yaml +++ b/vendor/google_riscv-dv/yaml/iss.yaml @@ -21,7 +21,7 @@ path_var: OVPSIM_PATH cmd: > /riscvOVPsim.exe - --controlfile ../riscv-dv/target//riscvOVPsim.ic + --controlfile target//riscvOVPsim.ic --objfilenoentry --override riscvOVPsim/cpu/PMP_registers=0 --override riscvOVPsim/cpu/simulateexceptions=T