mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 13:07:46 -04:00
Update google_riscv-dv to google/riscv-dv@cce71d2 (#445)
Update code from upstream repository https://github.com/google/riscv- dv to revision cce71d24b56f641d994fbf69b8b50aa3756b9322 * Add handshake documentation (Udi) * Fix coverage debug mode (google/riscv-dv#281) (taoliug) * Fix coverage script issue (google/riscv-dv#280) (taoliug) * code block highlight (google/riscv-dv#279) (taoliug) * Replace setting directory with a default target (google/riscv- dv#278) (taoliug) * fixed trace handling issues (google/riscv-dv#274) (eroom) * Allow running the script from other directory (google/riscv-dv#277) (taoliug) * Add dummy writes to status and ie CSRs (Udi) * Script typo fix (google/riscv-dv#272) (Dan Petrisko) * Fix misa setup issue (google/riscv-dv#271) (taoliug) * Enable mie.mtie for timer interrupts (Udi) * Update illegal system instr generation (Udi) * Fix duplicate (google/riscv-dv#268) (taoliug) * Add experimental instruction distribution control (google/riscv- dv#267) (taoliug) * Update README to clarify the flow setup instructions (google/riscv- dv#265) (taoliug) * Remove debug logging (google/riscv-dv#264) (taoliug) * Fix compressed instruction test setup (google/riscv-dv#263) (taoliug) * adding __init__ in the scripts dir since python3.7 requires that for directories to be recognized as modules (google/riscv-dv#252) (Jielun Tan) * Fix riscvOVPsim.ic (google/riscv-dv#261) (taoliug) * Fix ovpsim sim problem (google/riscv-dv#260) (taoliug) * Add alternative command options for directed instruction stream (google/riscv-dv#254) (taoliug) * Fix dsim compilation issue (google/riscv-dv#253) (taoliug)
This commit is contained in:
parent
48adda0b47
commit
f3f3f3de09
35 changed files with 960 additions and 239 deletions
2
vendor/google_riscv-dv.lock.hjson
vendored
2
vendor/google_riscv-dv.lock.hjson
vendored
|
@ -9,6 +9,6 @@
|
|||
upstream:
|
||||
{
|
||||
url: https://github.com/google/riscv-dv
|
||||
rev: 46ec4bc48bc1eebc5a2bcd48fe4ce4c77105fead
|
||||
rev: cce71d24b56f641d994fbf69b8b50aa3756b9322
|
||||
}
|
||||
}
|
||||
|
|
250
vendor/google_riscv-dv/HANDSHAKE.md
vendored
Normal file
250
vendor/google_riscv-dv/HANDSHAKE.md
vendored
Normal file
|
@ -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.
|
176
vendor/google_riscv-dv/README.md
vendored
176
vendor/google_riscv-dv/README.md
vendored
|
@ -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: <install_dir>/bin/riscv32-unknown-elf-objcopy)
|
||||
|
||||
```
|
||||
// Sample .bashrc setup
|
||||
```bash
|
||||
# Sample .bashrc setup
|
||||
export RISCV_TOOLCHAIN=<riscv_gcc_install_path>
|
||||
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 <target_dir>"
|
||||
|
||||
```bash
|
||||
# You need to manually specify isa and mabi for your custom target
|
||||
python3 run.py --custom_target <target_dir> --isa <isa> --mabi <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 <user_extension_path>" to override the
|
||||
user extension path.
|
||||
- Create a new file for riscv_core_setting.sv, add the path with below option:
|
||||
"-cs <new_core_setting_path>"
|
||||
- Create a new target directory and customize the setting and testlist
|
||||
- Run the generator with "--custom_target <target_dir> --isa <isa> --mabi <mabi>"
|
||||
- Use command line type override to use your extended classes.
|
||||
--sim_opts="+uvm_set_type_override=<upstream_class>,<extended_class>"
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
|
|
80
vendor/google_riscv-dv/cov.py
vendored
80
vendor/google_riscv-dv/cov.py
vendored
|
@ -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 \"<trace_csv_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=<instr_cnt>\"" %
|
||||
(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()
|
||||
|
|
99
vendor/google_riscv-dv/run.py
vendored
99
vendor/google_riscv-dv/run.py
vendored
|
@ -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("\<path_var\>", get_env_var(entry['path_var']), cmd)
|
||||
if iss == "ovpsim":
|
||||
cmd = re.sub("\<variant\>", isa, cmd)
|
||||
else:
|
||||
cmd = re.sub("\<variant\>", isa, cmd)
|
||||
cmd = re.sub("\<variant\>", 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("<out>", os.path.abspath(output_dir), cmd)
|
||||
if core_setting_dir == "":
|
||||
cmd = re.sub("<setting>", "<cwd>/setting", cmd)
|
||||
else:
|
||||
cmd = re.sub("<setting>", core_setting_dir, cmd)
|
||||
cmd = re.sub("<setting>", core_setting_dir, cmd)
|
||||
if ext_dir == "":
|
||||
cmd = re.sub("<user_extension>", "<cwd>/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):
|
||||
|
|
0
vendor/google_riscv-dv/scripts/__init__.py
vendored
Normal file
0
vendor/google_riscv-dv/scripts/__init__.py
vendored
Normal file
|
@ -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 = ""
|
||||
|
|
11
vendor/google_riscv-dv/scripts/lib.py
vendored
11
vendor/google_riscv-dv/scripts/lib.py
vendored
|
@ -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)
|
||||
|
|
|
@ -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<mode>[A-Za-z]*?)\s+(?P<bin>[a-f0-9]*?)\s+(?P<instr>.*?)$", 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<instr>[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<instr>[a-z]*?)\s(?P<operand>.*)", 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))
|
||||
|
|
|
@ -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']
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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<cfg.max_directed_instr_stream_seq; i++) begin
|
||||
args = $sformatf("directed_instr_%0d=", i);
|
||||
stream_name_opts = $sformatf("stream_name_%0d=", i);
|
||||
stream_freq_opts = $sformatf("stream_freq_%0d=", i);
|
||||
if ($value$plusargs({args,"%0s"}, val)) begin
|
||||
uvm_split_string(val, ",", opts);
|
||||
if (opts.size() != 2) begin
|
||||
|
@ -1114,6 +1151,9 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
end else begin
|
||||
add_directed_instr_stream(opts[0], opts[1].atoi());
|
||||
end
|
||||
end else if ($value$plusargs({stream_name_opts,"%0s"}, stream_name) &&
|
||||
$value$plusargs({stream_freq_opts,"%0d"}, stream_freq)) begin
|
||||
add_directed_instr_stream(stream_name, stream_freq);
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
|
|
@ -184,7 +184,7 @@ class riscv_jal_instr extends riscv_rand_instr_stream;
|
|||
riscv_instr_base jump_start;
|
||||
riscv_instr_base jump_end;
|
||||
rand int unsigned num_of_jump_instr;
|
||||
riscv_instr_name_t jal[];
|
||||
riscv_instr_name_t jal[$];
|
||||
|
||||
constraint instr_c {
|
||||
num_of_jump_instr inside {[10:30]};
|
||||
|
@ -207,7 +207,10 @@ class riscv_jal_instr extends riscv_rand_instr_stream;
|
|||
setup_allowed_instr(1, 1);
|
||||
jal = {JAL};
|
||||
if (!cfg.disable_compressed_instr) begin
|
||||
jal = (XLEN == 32) ? {jal, C_J, C_JAL} : {jal, C_J};
|
||||
jal.push_back(C_J);
|
||||
if (XLEN == 32) begin
|
||||
jal.push_back(C_JAL);
|
||||
end
|
||||
end
|
||||
// First instruction
|
||||
jump_start = riscv_instr_base::type_id::create("jump_start");
|
||||
|
|
|
@ -29,7 +29,8 @@ class riscv_illegal_instr extends uvm_object;
|
|||
kIllegalFunc3,
|
||||
kIllegalFunc7,
|
||||
kReservedCompressedInstr,
|
||||
kHintInstr
|
||||
kHintInstr,
|
||||
kIllegalSystemInstr
|
||||
} illegal_instr_type_e;
|
||||
|
||||
// Default legal opcode for RV32I instructions
|
||||
|
@ -65,15 +66,17 @@ class riscv_illegal_instr extends uvm_object;
|
|||
rand bit [1:0] c_op;
|
||||
rand bit [2:0] c_msb;
|
||||
riscv_instr_gen_config cfg;
|
||||
privileged_reg_t csrs[$];
|
||||
|
||||
constraint exception_dist_c {
|
||||
exception dist {
|
||||
kIllegalOpcode := 4,
|
||||
kIllegalOpcode := 3,
|
||||
kIllegalCompressedOpcode := 1,
|
||||
kIllegalFunc3 := 1,
|
||||
kIllegalFunc7 := 1,
|
||||
kReservedCompressedInstr := 1,
|
||||
kHintInstr := 3
|
||||
kHintInstr := 3,
|
||||
kIllegalSystemInstr := 3
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -97,6 +100,25 @@ class riscv_illegal_instr extends uvm_object;
|
|||
}
|
||||
}
|
||||
|
||||
// Invalid SYSTEM instructions
|
||||
constraint system_instr_c {
|
||||
if (exception == kIllegalSystemInstr) {
|
||||
opcode == 7'b1110011;
|
||||
// ECALL/EBREAK/xRET/WFI
|
||||
if (func3 == 3'b000) {
|
||||
// Constrain RS1 and RD to be non-zero
|
||||
instr_bin[19:15] != 0;
|
||||
instr_bin[11:7] != 0;
|
||||
// Valid SYSTEM instructions considered by this
|
||||
// Constrain the upper 12 bits to be invalid
|
||||
!(instr_bin[31:20] inside {12'h0, 12'h1, 12'h2, 12'h102, 12'h302, 12'h7b2, 12'h105});
|
||||
} else {
|
||||
// Invalid CSR instructions
|
||||
!(instr_bin[31:20] inside {csrs});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constraint legal_rv32_c_slli {
|
||||
if ((c_msb == 3'b000) && (c_op == 2'b10) && (XLEN == 32)) {
|
||||
if (exception == kReservedCompressedInstr) {
|
||||
|
@ -111,7 +133,7 @@ class riscv_illegal_instr extends uvm_object;
|
|||
if (compressed) {
|
||||
exception inside {kReservedCompressedInstr, kIllegalCompressedOpcode, kHintInstr};
|
||||
} else {
|
||||
exception inside {kIllegalOpcode, kIllegalFunc3, kIllegalFunc7};
|
||||
exception inside {kIllegalOpcode, kIllegalFunc3, kIllegalFunc7, kIllegalSystemInstr};
|
||||
}
|
||||
if (!has_func7) {
|
||||
exception != kIllegalFunc7;
|
||||
|
@ -269,6 +291,7 @@ class riscv_illegal_instr extends uvm_object;
|
|||
`uvm_object_new
|
||||
|
||||
function void init(riscv_instr_gen_config cfg);
|
||||
privileged_reg_t csr;
|
||||
this.cfg = cfg;
|
||||
if ((riscv_instr_pkg::RV32F inside {riscv_instr_pkg::supported_isa}) ||
|
||||
riscv_instr_pkg::RV32D inside {riscv_instr_pkg::supported_isa}) begin
|
||||
|
@ -289,6 +312,11 @@ class riscv_illegal_instr extends uvm_object;
|
|||
legal_c00_opcode = {legal_c00_opcode, 3'b011, 3'b111};
|
||||
legal_c10_opcode = {legal_c10_opcode, 3'b011, 3'b111};
|
||||
end
|
||||
csr = csr.first();
|
||||
for (int i = 0; i < csr.num(); i = i + 1) begin
|
||||
csrs.push_back(csr);
|
||||
csr = csr.next();
|
||||
end
|
||||
endfunction
|
||||
|
||||
function string get_bin_str();
|
||||
|
@ -297,6 +325,8 @@ class riscv_illegal_instr extends uvm_object;
|
|||
end else begin
|
||||
get_bin_str = $sformatf("%8h", instr_bin[31:0]);
|
||||
end
|
||||
`uvm_info(`gfn, $sformatf("Illegal instruction type: %0s, illegal instruction: 0x%0x",
|
||||
exception.name(), instr_bin), UVM_HIGH)
|
||||
endfunction
|
||||
|
||||
endclass
|
||||
|
|
10
vendor/google_riscv-dv/src/riscv_instr_base.sv
vendored
10
vendor/google_riscv-dv/src/riscv_instr_base.sv
vendored
|
@ -18,7 +18,7 @@ class riscv_instr_base extends uvm_object;
|
|||
|
||||
rand riscv_instr_group_t group;
|
||||
rand riscv_instr_format_t format;
|
||||
rand riscv_instr_cateogry_t category;
|
||||
rand riscv_instr_category_t category;
|
||||
rand riscv_instr_name_t instr_name;
|
||||
rand bit [11:0] csr;
|
||||
|
||||
|
@ -159,6 +159,12 @@ class riscv_instr_base extends uvm_object;
|
|||
}
|
||||
}
|
||||
|
||||
constraint jal_c {
|
||||
if (XLEN != 32) {
|
||||
soft instr_name != C_JAL;
|
||||
}
|
||||
}
|
||||
|
||||
constraint system_instr_c {
|
||||
if (category inside {SYSTEM, SYNCH}) {
|
||||
rd == ZERO;
|
||||
|
@ -942,8 +948,6 @@ class riscv_instr_base extends uvm_object;
|
|||
AND : get_func7 = 7'b0000000;
|
||||
FENCE : get_func7 = 7'b0000000;
|
||||
FENCE_I : get_func7 = 7'b0000000;
|
||||
ECALL : get_func7 = 7'b0000000;
|
||||
EBREAK : get_func7 = 7'b0000000;
|
||||
SLLIW : get_func7 = 7'b0000000;
|
||||
SRLIW : get_func7 = 7'b0000000;
|
||||
SRAIW : get_func7 = 7'b0100000;
|
||||
|
|
|
@ -181,7 +181,6 @@ class riscv_instr_cov_item extends riscv_instr_base;
|
|||
BGE : is_branch_hit = ($signed(rs1_value) > $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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
37
vendor/google_riscv-dv/src/riscv_instr_stream.sv
vendored
37
vendor/google_riscv-dv/src/riscv_instr_stream.sv
vendored
|
@ -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});)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
19
vendor/google_riscv-dv/target/ml/riscvOVPsim.ic
vendored
Normal file
19
vendor/google_riscv-dv/target/ml/riscvOVPsim.ic
vendored
Normal file
|
@ -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
|
104
vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
vendored
Normal file
104
vendor/google_riscv-dv/target/ml/riscv_core_setting.sv
vendored
Normal file
|
@ -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
|
||||
};
|
64
vendor/google_riscv-dv/target/ml/testlist.yaml
vendored
Normal file
64
vendor/google_riscv-dv/target/ml/testlist.yaml
vendored
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
18
vendor/google_riscv-dv/target/rv64gc/riscvOVPsim.ic
vendored
Normal file
18
vendor/google_riscv-dv/target/rv64gc/riscvOVPsim.ic
vendored
Normal file
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
2
vendor/google_riscv-dv/yaml/iss.yaml
vendored
2
vendor/google_riscv-dv/yaml/iss.yaml
vendored
|
@ -21,7 +21,7 @@
|
|||
path_var: OVPSIM_PATH
|
||||
cmd: >
|
||||
<path_var>/riscvOVPsim.exe
|
||||
--controlfile ../riscv-dv/target/<variant>/riscvOVPsim.ic
|
||||
--controlfile target/<variant>/riscvOVPsim.ic
|
||||
--objfilenoentry <elf>
|
||||
--override riscvOVPsim/cpu/PMP_registers=0
|
||||
--override riscvOVPsim/cpu/simulateexceptions=T
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue