mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 13:07:46 -04:00
Update google_riscv-dv to a07e0a7 (#203)
Update code from upstream repository https://github.com/google/riscv- dv to revision a07e0a726edf0230314c08d31546eecbed23054b * Merge pull request #53 from google/flow (taoliug) * Update README file for the new flow (Tao Liu) * Merge pull request #52 from google/flow (taoliug) * Add timeout mechanism to the flow (Tao Liu) * Merge pull request #51 from google/flow (taoliug) * Simulation flow update (Tao Liu) * Merge pull request #50 from udinator/master (taoliug) * added license for csr_template.yaml (Udi) * Merge pull request #49 from google/dev (taoliug) * Update log process script (Tao Liu) * Merge pull request #48 from google/dev (taoliug) * Fix illegal instruction issue (Tao Liu) * Merge pull request #47 from google/dev (taoliug) * Refactor the simulation flow (Tao Liu) * Merge pull request #45 from danghai/master (taoliug) * Add .gitignore to remove untracked files (danghai) * Fix warning from Questa optmize (danghai) * Add optimize log file for Questa simulator (danghai) * New YAML based simulation flow (Tao Liu) * Merge pull request #40 from scottj97/typos-redone (taoliug) * Fix typos in comments (Scott Johnson) * Fix typos/grammar in README (Scott Johnson) * Merge pull request #43 from udinator/master (taoliug) * use hex format in YAML description (Udi) * CSR test description (Udi) * removed run script (Udi) * Modified CSR test generation code to adhere to style guidelines. (Udi) * Merge pull request #41 from vandanaprabhu/questa (taoliug) * CSR Generation Script and YAML template (Udi) * Prevent Xcelium from attempting to run a simulation during the compile step (Scott Johnson) * Document support for Questa (Scott Johnson) * Fix simulation-time warnings from Mentor Questa (Scott Johnson) * Fix compile warnings from Mentor Questa (Scott Johnson) * Fix warning from Questa compiler (Scott Johnson) * Fix warning from Questa compiler (Scott Johnson) * Adding support for using the Questa simulator (Vandana Prabhu) * Pass proper seed to Cadence Xcelium simulator (Scott Johnson) * Convert compile commands to functions instead of variables (Scott Johnson)
This commit is contained in:
parent
76ac3ef658
commit
ba5c63b8d1
25 changed files with 1629 additions and 238 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: 112dcc2e669f124dfe48c35a09477603c3ccb180
|
||||
rev: a07e0a726edf0230314c08d31546eecbed23054b
|
||||
}
|
||||
}
|
||||
|
|
4
vendor/google_riscv-dv/.gitignore
vendored
Normal file
4
vendor/google_riscv-dv/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
*.ini
|
||||
*.bin
|
||||
out_*/
|
||||
work/
|
344
vendor/google_riscv-dv/README.md
vendored
344
vendor/google_riscv-dv/README.md
vendored
|
@ -12,23 +12,254 @@ processor verification. It currently supports the following features:
|
|||
- Support sub-programs and random program calls
|
||||
- Support illegal instruction and HINT instruction
|
||||
- Random forward/backward branch instructions
|
||||
- Support mix directed instruciton with random instruction stream
|
||||
- Support co-simulation with multiple ISS : spike, riscv-ovpsim
|
||||
- Supports mixing directed instructions with random instruction stream
|
||||
- Supports co-simulation with multiple ISS : spike, riscv-ovpsim
|
||||
|
||||
## Getting Started
|
||||
|
||||
### Prerequisites
|
||||
|
||||
To be able to run the instruction generator, you need to have an RTL simulator
|
||||
which supports Systemverilog and UVM 1.2. This generator has been verified with
|
||||
Synopsys VCS and Cadence Incisive/Xcelium simulator. Please make sure the EDA
|
||||
tool environment is properly setup before running the generator.
|
||||
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.
|
||||
|
||||
### Running the generator
|
||||
|
||||
A simple script "run" is provided for you to run a single test or a regression.
|
||||
Here is the command to run a single test:
|
||||
|
||||
```
|
||||
python3 run.py --test=riscv_arithmetic_basic_test
|
||||
```
|
||||
You can specify the simulator by "-simulator" option
|
||||
|
||||
```
|
||||
python3 run.py --test=riscv_arithmetic_basic_test --simulator=irun
|
||||
python3 run.py --test=riscv_arithmetic_basic_test --simulator=vcs
|
||||
python3 run.py --test=riscv_arithmetic_basic_test --simulator=questa
|
||||
```
|
||||
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
|
||||
|
||||
```
|
||||
python3 run.py
|
||||
```
|
||||
|
||||
You can also run multiple generator jobs in parallel through LSF
|
||||
|
||||
```
|
||||
python3 run.py --lsf_cmd="bsub -Is"
|
||||
```
|
||||
|
||||
Here's a few more examples of the run command:
|
||||
|
||||
```
|
||||
// Get the complete command reference info
|
||||
python3 run.py --help
|
||||
|
||||
// Run a single test 10 times
|
||||
python3 run.py --test=riscv_page_table_exception_test --iterations=10
|
||||
|
||||
// Run a test with a specified seed
|
||||
python3 run.py --test=riscv_page_table_exception_test --seed=123
|
||||
|
||||
// Skip the generation, run ISS simulation with previously generated program
|
||||
python3 run.py --test=riscv_page_table_exception_test --steps=iss_sim
|
||||
....
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### Setup regression test list
|
||||
|
||||
[Test list in YAML format](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml)
|
||||
|
||||
```
|
||||
# test : Assembly test name
|
||||
# description : Description of this test
|
||||
# gen_opts : Instruction generator options
|
||||
# iterations : Number of iterations of this test
|
||||
# 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
|
||||
# compare_opts : Options for the RTL & ISS trace comparison
|
||||
|
||||
- test: riscv_arithmetic_basic_test
|
||||
description: >
|
||||
Arithmetic instruction test, no load/store/branch instructions
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=0
|
||||
+no_fence=1
|
||||
+no_data_page=1'b1
|
||||
+no_branch_jump=1'b1
|
||||
+boot_mode=m
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
rtl_test: core_base_test
|
||||
|
||||
```
|
||||
|
||||
### Configure the generator to match your processor features
|
||||
|
||||
The default configuration of the instruction generator is for RV64IMC 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
|
||||
|
||||
```
|
||||
// Bit width of RISC-V GPR
|
||||
parameter int XLEN = 64;
|
||||
|
||||
// Parameter for SATP mode, set to BARE if address translation is not supported
|
||||
parameter satp_mode_t SATP_MODE = SV39;
|
||||
|
||||
// Supported Privileged mode
|
||||
privileged_mode_t supported_privileged_mode[] = {USER_MODE,
|
||||
SUPERVISOR_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};
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
### Runtime options of the generator
|
||||
|
||||
| Option | Description | default |
|
||||
|----------|:-------------:|:------:|
|
||||
| num_of_tests | Number of assembly tests to be generated | 1 |
|
||||
| num_of_sub_program | Number of sub-program in one test | 5 |
|
||||
| instr_cnt | Instruction count per test | 200 |
|
||||
| enable_page_table_exception | Enable page table exception | 0 |
|
||||
| no_ebreak | Disable ebreak instruction | 1 |
|
||||
| no_wfi | Disable WFI instruction | 1 |
|
||||
| no_branch_jump | Disable branch/jump instruction | 0 |
|
||||
| no_load_store | Disable load/store instruction | 0 |
|
||||
| no_csr_instr | Disable CSR instruction | 0 |
|
||||
| no_fence | Disable fence instruction | 0 |
|
||||
| enable_illegal_instruction | Enable illegal instructions | 0 |
|
||||
| enable_hint_instruction | Enable HINT instruction | 0 |
|
||||
| boot_mode | m:Machine mode, s:Supervisor mode, u:User mode | m |
|
||||
| no_directed_instr | Disable directed instruction stream | 0 |
|
||||
| enable_interrupt | Enable MStatus.MIE, used in interrupt test | 0 |
|
||||
|
||||
### Adding new instruction stream and test
|
||||
|
||||
Please refer to src/src/riscv_load_store_instr_lib.sv for an example on how to
|
||||
add a new instruction stream.
|
||||
After the new instruction stream is created, you can use a runtime option to mix
|
||||
it with random instructions
|
||||
|
||||
```
|
||||
//+directed_instr_n=instr_sequence_name,frequency(number of insertions per 1000 instructions)
|
||||
+directed_instr_5=riscv_multi_page_load_store_instr_stream,4
|
||||
```
|
||||
|
||||
## Run ISS(Instruction Set Simulator) simulation
|
||||
|
||||
The default ISS is spike. Thanks for the great support from Imperas Software Ltd.,
|
||||
we have added the support for [riscv-ovpsim](https://github.com/riscv/riscv-ovpsim).
|
||||
|
||||
- spike setup
|
||||
- Follow the [steps](https://github.com/riscv/riscv-isa-sim#build-steps) to build spike
|
||||
- Make sure RISCV_ENABLE_COMMITLOG is defined in [config.h.in](https://github.com/riscv/riscv-isa-sim/blob/master/config.h.in)
|
||||
- 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
|
||||
- Set environment variable OVPSIM_PATH to the directory of the ovpsim binary
|
||||
|
||||
|
||||
You can use -iss to run with different ISS.
|
||||
|
||||
```
|
||||
// Run ISS with spike
|
||||
python3 run.py --test=riscv_page_table_exception_test --iss=spike
|
||||
|
||||
// Run ISS with riscv-ovpsim
|
||||
python3 run.py --test=riscv_rand_instr_test --iss=ovpsim
|
||||
```
|
||||
|
||||
To run with ISS simulation for RV32IMC, you can specify ISA and ABI from command
|
||||
line like this:
|
||||
|
||||
```
|
||||
// Run a full regression with RV32IMC
|
||||
python3 run.py --isa=rv32imc --mabi=ilp32
|
||||
```
|
||||
|
||||
We have added a flow to run ISS simulation with both spike and riscv-ovpsim,
|
||||
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.
|
||||
|
||||
```
|
||||
python3 run.py --test=riscv_rand_instr_test --iss=spike,ovpsim
|
||||
```
|
||||
|
||||
### Integrate a new ISS
|
||||
|
||||
You can add a new entry in [iss.yaml](https://github.com/google/riscv-dv/blob/master/yaml/iss.yaml)
|
||||
|
||||
```
|
||||
- iss: new_iss_name
|
||||
path_var: ISS_PATH
|
||||
cmd: >
|
||||
<path_var>/iss_executable --isa=<variant> -l <elf>
|
||||
```
|
||||
|
||||
Simulate with the new ISS
|
||||
|
||||
```
|
||||
python3 run.py --test=riscv_page_table_exception_test --iss=new_iss_name
|
||||
```
|
||||
|
||||
## End-to-end RTL and ISS co-simulation flow
|
||||
|
||||
We have collaborated with LowRISC to apply this flow for [IBEX RISC-V core
|
||||
verification](https://github.com/lowRISC/ibex/tree/master/dv/uvm). You can use
|
||||
it as a reference to setup end-to-end co-simulation flow. It's also a good
|
||||
reference for [customizing the generator](https://github.com/lowRISC/ibex/tree/master/dv/uvm/riscv_dv_extension) without getting impacted by upstream
|
||||
changes.
|
||||
We have plan to open-source the end-to-end environment of other advanced RISC-V
|
||||
processors. Stay tuned!
|
||||
|
||||
## Supporting model
|
||||
|
||||
Please file an issue under this repository for any bug report / integration
|
||||
issue / feature request. We are looking forward to knowing your experience of
|
||||
using this flow and how we can make it better together.
|
||||
|
||||
## External contributions
|
||||
|
||||
We definitely welcome external contributions. We hope it could be a
|
||||
collaborative effort to build a strong open source RISC-V processor
|
||||
verification platform. Free feel to submit your pull request for review.
|
||||
Please refer to CONTRIBUTING.md for license related questions.
|
||||
|
||||
## Future release plan
|
||||
|
||||
We have some work in progress which will be part of future releases:
|
||||
|
||||
- Privileged CSR test suite.
|
||||
- Coverage model.
|
||||
- Debug mode support
|
||||
|
||||
### DEPRECATED simulation flow
|
||||
|
||||
Note: The flow mentioned below will soon be deprecated. Please switch to new
|
||||
flow.
|
||||
|
||||
A simple script "run" is provided for you to run a single test or a regression.
|
||||
Here is the command to run a single test:
|
||||
|
||||
```
|
||||
./run -test riscv_instr_base_test
|
||||
```
|
||||
|
@ -37,6 +268,7 @@ You can specify the simulator by "-tool" option
|
|||
```
|
||||
./run -test riscv_instr_base_test -tool irun
|
||||
./run -test riscv_instr_base_test -tool vcs
|
||||
./run -test riscv_instr_base_test -tool questa
|
||||
```
|
||||
The complete test list can be found in testlist. To run a full regression, you
|
||||
can just specify the test name to "all".
|
||||
|
@ -67,7 +299,9 @@ following output:
|
|||
./out_2018-11-20/asm_tests/riscv_rand_jump_test.0.S
|
||||
./out_2018-11-20/asm_tests/riscv_sfence_exception_test.0.S
|
||||
```
|
||||
|
||||
Here's a few more examples of the run command:
|
||||
|
||||
```
|
||||
// Run a single test 10 times
|
||||
./run -test riscv_page_table_exception_test -n 10
|
||||
|
@ -85,106 +319,6 @@ Here's a few more examples of the run command:
|
|||
./run -so -test riscv_mmu_stress_test -n 20
|
||||
....
|
||||
```
|
||||
|
||||
### Use the generated test in your RTL and ISS simulation
|
||||
|
||||
You need to use the RISC-V gcc/llvm compiler to compile the assembly tests to an ELF
|
||||
file and feed into your TB. We currently don't provide a reference TB for the
|
||||
co-simulation as it could be quite different based on the processor and ISS
|
||||
implementation. A reference script "iss_sim" is provided to compile the program
|
||||
with the RISC-V gcc compiler and simulate with spike.
|
||||
```
|
||||
./run -test all; ./iss_sim
|
||||
```
|
||||
|
||||
To run with ISS simulation for RV32IMC, you can specify ISA and ABI from command
|
||||
line like this:
|
||||
```
|
||||
./iss_sim -isa rv32imc -abi ilp32
|
||||
```
|
||||
|
||||
The default ISS is spike. Thanks for the great support from Imperas Software Ltd.,
|
||||
we have added the support for [riscv-ovpsim](https://github.com/riscv/riscv-ovpsim).
|
||||
You can use -iss to run with different ISS.
|
||||
```
|
||||
./iss_sim -iss spike # Use spike as ISS
|
||||
./iss_sim -iss ovpsim # Use riscv-ovpsim as ISS
|
||||
```
|
||||
|
||||
We have added a flow to run ISS simulation with both spike and riscv-ovpsim,
|
||||
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.
|
||||
```
|
||||
./iss_sim -iss all # Run ISS simulation with spike + riscv-ovpsim
|
||||
```
|
||||
|
||||
## Configure the generator to match your processor features
|
||||
|
||||
The default configuration of the instruction generator is for RV64IMC 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
|
||||
|
||||
```
|
||||
// Bit width of RISC-V GPR
|
||||
parameter int XLEN = 64;
|
||||
|
||||
// Parameter for SATP mode, set to BARE if address translation is not supported
|
||||
parameter satp_mode_t SATP_MODE = SV39;
|
||||
|
||||
// Supported Privileged mode
|
||||
privileged_mode_t supported_privileged_mode[] = {USER_MODE,
|
||||
SUPERVISOR_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};
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
## Runtime options of the generator
|
||||
|
||||
|
||||
|
||||
## Adding new instruction stream and test
|
||||
|
||||
Please refer to src/src/riscv_load_store_instr_lib.sv for an example on how to
|
||||
add a new instruction stream.
|
||||
```
|
||||
virtual function void apply_directed_instr();
|
||||
asm_gen.add_directed_instr_stream("my_new_instr_stream_class_name", 10);
|
||||
endfunction
|
||||
```
|
||||
After the new instruction stream is created, you
|
||||
can refer to test/riscv_instr_test_lib.sv to see how an instruction stream can
|
||||
be mixed with existing random instruction stream.
|
||||
|
||||
## Supporting model
|
||||
|
||||
Please file an issue under this repository for any bug report / integration
|
||||
issue / feature request. We are looking forward to knowing your experience of
|
||||
using this flow and how we can make it better together.
|
||||
|
||||
## External contributions
|
||||
|
||||
We definitely welcome external contributions. We hope it could be a
|
||||
collaborative effort to build a strong open source RISC-V processor
|
||||
verification platform. Free feel to submit your pull request for review.
|
||||
Please refer to CONTRIBUTING.md for license related questions.
|
||||
|
||||
## Future release plan
|
||||
|
||||
We have some work in progress which will be part of future releases:
|
||||
|
||||
- Privileged CSR test suite.
|
||||
- Coverage model.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This is not an officially supported Google product.
|
||||
|
|
20
vendor/google_riscv-dv/iss_cmp
vendored
20
vendor/google_riscv-dv/iss_cmp
vendored
|
@ -20,26 +20,14 @@ report_file="$3"
|
|||
# -----------------------------------------------------------------------------
|
||||
# Convert spike log to standard instruction trace csv
|
||||
# -----------------------------------------------------------------------------
|
||||
# Remove all the init spike boot instructions
|
||||
# 0xffffffff80000000 is the first user instruction
|
||||
if [[ "$XLEN" == "32" ]]; then
|
||||
sed -i '/0xffffffff80000000/,$!d' "$spike_log"
|
||||
else
|
||||
sed -i '/core.*0x0000000080000000/,$!d' "$spike_log"
|
||||
fi
|
||||
# Remove all instructions after ecall (end of program excecution)
|
||||
sed -i '/ecall/q' "$spike_log"
|
||||
# Convert the spike log to riscv_instr_trace.proto format
|
||||
spike_csv=$(echo "$spike_log" | sed 's/\.log/.csv/g')
|
||||
python scripts/spike_log_to_trace_csv.py --log $spike_log --csv $spike_csv
|
||||
python scripts/spike_log_to_trace_csv.py --log $spike_log \
|
||||
--csv $spike_csv --xlen 64
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Convert ovpsim log to standard instruction trace csv
|
||||
# -----------------------------------------------------------------------------
|
||||
# Remove the header part of ovpsim log
|
||||
sed -i '/Info 1:/,$!d' "$ovpsim_log"
|
||||
# Remove all instructions after ecall (end of program excecution)
|
||||
sed -i '/ecall/q' "$ovpsim_log"
|
||||
# Convert the spike log to riscv_instr_trace.proto format
|
||||
ovpsim_csv=$(echo "$ovpsim_log" | sed 's/\.log/.csv/g')
|
||||
python scripts/ovpsim_log_to_trace_csv.py --log $ovpsim_log --csv $ovpsim_csv
|
||||
|
@ -47,4 +35,6 @@ python scripts/ovpsim_log_to_trace_csv.py --log $ovpsim_log --csv $ovpsim_csv
|
|||
# -----------------------------------------------------------------------------
|
||||
# Compare the trace log
|
||||
# -----------------------------------------------------------------------------
|
||||
python scripts/instr_trace_compare.py $spike_csv $ovpsim_csv "spike" "ovpsim" >> $report_file
|
||||
python scripts/instr_trace_compare.py $spike_csv $ovpsim_csv \
|
||||
spike ovpsim >> $report_file
|
||||
echo >> $report_file
|
||||
|
|
2
vendor/google_riscv-dv/iss_sim
vendored
2
vendor/google_riscv-dv/iss_sim
vendored
|
@ -31,7 +31,7 @@ OVPSIM_VARIANT="RV64GC"
|
|||
|
||||
# Binary of RISC-V ovpsim ISS
|
||||
# https://github.com/riscv/riscv-ovpsim
|
||||
RISCV_OVPSIM="${OVPSIM_PATH}/riscv-ovpsim/bin/Linux64/riscvOVPsim.exe"
|
||||
RISCV_OVPSIM="${OVPSIM_PATH}/riscvOVPsim.exe"
|
||||
|
||||
# Directory of assemble tests
|
||||
SRC_DIR="./out_${DATE}/asm_tests"
|
||||
|
|
1
vendor/google_riscv-dv/questa_sim.tcl
vendored
Normal file
1
vendor/google_riscv-dv/questa_sim.tcl
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
run -all ; quit
|
62
vendor/google_riscv-dv/run
vendored
62
vendor/google_riscv-dv/run
vendored
|
@ -28,7 +28,7 @@
|
|||
|
||||
DATE=`date +%Y-%m-%d`
|
||||
|
||||
# RTL simulator, support vcs and irun
|
||||
# RTL simulator, supports vcs, irun, and questa
|
||||
SIMULATOR="vcs"
|
||||
|
||||
# random seed
|
||||
|
@ -141,25 +141,53 @@ OUT=`realpath ${OUT}`
|
|||
# Generate compile and simulation commands
|
||||
if [[ "$SIMULATOR" == "vcs" ]]; then
|
||||
|
||||
COMPILE_CMD="vcs -file ./vcs.compile.option.f \
|
||||
-f ./files.f -full64 \
|
||||
-l $OUT/compile.log \
|
||||
-Mdir=$OUT/vcs_simv.csrc \
|
||||
-o $OUT/vcs_simv ${CMP_OPTS}"
|
||||
function run_compile {
|
||||
vcs -file ./vcs.compile.option.f \
|
||||
-f ./files.f -full64 \
|
||||
-l $OUT/compile.log \
|
||||
-Mdir=$OUT/vcs_simv.csrc \
|
||||
-o $OUT/vcs_simv ${CMP_OPTS}
|
||||
}
|
||||
|
||||
SIM_CMD="$OUT/vcs_simv +vcs+lic+wait +UVM_TESTNAME="
|
||||
SIM_SEED="+ntb_random_seed="
|
||||
|
||||
elif [[ "$SIMULATOR" == "irun" ]]; then
|
||||
|
||||
COMPILE_CMD="irun -64bit \
|
||||
-access +rwc \
|
||||
-f ./files.f \
|
||||
-q -sv -uvm \
|
||||
-vlog_ext +.vh -I. \
|
||||
-uvmhome CDNS-1.2 \
|
||||
-l ${OUT}/compile.log ${CMP_OPTS}"
|
||||
function run_compile {
|
||||
irun -64bit \
|
||||
-access +rwc \
|
||||
-f ./files.f \
|
||||
-q -sv -uvm \
|
||||
-vlog_ext +.vh -I. \
|
||||
-uvmhome CDNS-1.2 \
|
||||
-elaborate \
|
||||
-l ${OUT}/compile.log ${CMP_OPTS}
|
||||
}
|
||||
|
||||
SIM_CMD="irun -R +UVM_TESTNAME="
|
||||
SIM_SEED="-svseed "
|
||||
|
||||
elif [[ "$SIMULATOR" == "questa" ]]; then
|
||||
#Questa requires mapping libraries to compile correctly
|
||||
function run_compile {
|
||||
vmap mtiUvm $QUESTA_HOME/questasim/uvm-1.2
|
||||
vlog -64 \
|
||||
-access=rwc \
|
||||
-f ./files.f \
|
||||
-sv \
|
||||
-mfcu -cuname design_cuname \
|
||||
+define+UVM_REGEX_NO_DPI \
|
||||
-writetoplevels ${OUT}/top.list \
|
||||
-l ${OUT}/compile.log ${CMP_OPTS}
|
||||
vopt -64 -debug \
|
||||
+designfile -f ${OUT}/top.list \
|
||||
-l ${OUT}/optimize.log ${CMP_OPTS} \
|
||||
-o design_opt
|
||||
}
|
||||
|
||||
SIM_CMD="vsim -64 -c -do questa_sim.tcl design_opt +UVM_TESTNAME="
|
||||
SIM_SEED="-sv_seed "
|
||||
|
||||
else
|
||||
echo "unsupported simulator $SIMULATOR"
|
||||
|
@ -180,9 +208,9 @@ mkdir -p ${OUT}/asm_tests
|
|||
if [[ $SIM_ONLY == 0 ]]; then
|
||||
echo "Building RISC-V instruction generator..."
|
||||
if [[ $VERBOSE == 1 ]]; then
|
||||
${COMPILE_CMD}
|
||||
run_compile
|
||||
else
|
||||
${COMPILE_CMD} > /dev/null
|
||||
run_compile > /dev/null
|
||||
fi
|
||||
echo "Building RISC-V instruction generator...done"
|
||||
fi
|
||||
|
@ -209,7 +237,7 @@ if [[ ${TEST} == "all" ]]; then
|
|||
if [[ ${ITERATION} != "0" ]]; then
|
||||
echo "Running ${TEST} to generate ${ITERATION} tests"
|
||||
CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
|
||||
+ntb_random_seed=${SEED} ${TEST_OPTS} ${SIM_OPTS} \
|
||||
${SIM_SEED}${SEED} ${TEST_OPTS} ${SIM_OPTS} \
|
||||
-l ${OUT}/sim_${TEST}.log +num_of_tests=${ITERATION}"
|
||||
((PROGRAM_CNT+=$ITERATION))
|
||||
echo "${OUT}/sim_${TEST}.log" >> ${LOG_LIST}
|
||||
|
@ -262,7 +290,7 @@ if [[ ${TEST} == "all" ]]; then
|
|||
else
|
||||
echo "Running test ${TEST} to generate ${NUM_TESTS} tests"
|
||||
CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
|
||||
+ntb_random_seed=${SEED} \
|
||||
${SIM_SEED}${SEED} \
|
||||
-l ${OUT}/sim_${TEST}.log \
|
||||
+num_of_tests=${NUM_TESTS} ${SIM_OPTS}"
|
||||
if [[ $VERBOSE == 1 ]]; then
|
||||
|
|
350
vendor/google_riscv-dv/run.py
vendored
Normal file
350
vendor/google_riscv-dv/run.py
vendored
Normal file
|
@ -0,0 +1,350 @@
|
|||
"""
|
||||
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.
|
||||
|
||||
Regression script for RISC-V random instruction generator
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import re
|
||||
import sys
|
||||
|
||||
from scripts.lib import *
|
||||
from scripts.spike_log_to_trace_csv import *
|
||||
from scripts.ovpsim_log_to_trace_csv import *
|
||||
from scripts.instr_trace_compare import *
|
||||
|
||||
def get_generator_cmd(simulator, simulator_yaml):
|
||||
""" Setup the compile and simulation command for the generator
|
||||
|
||||
Args:
|
||||
simulator : RTL simulator used to run instruction generator
|
||||
simulator_yaml : RTL simulator configuration file in YAML format
|
||||
|
||||
Returns:
|
||||
compile_cmd : RTL simulator command to compile the instruction generator
|
||||
sim_cmd : RTL simulator command to run the instruction generator
|
||||
"""
|
||||
print("Processing simulator setup file : %s" % simulator_yaml)
|
||||
yaml_data = read_yaml(simulator_yaml)
|
||||
# Search for matched simulator
|
||||
for entry in yaml_data:
|
||||
if entry['tool'] == simulator:
|
||||
print ("Found matching simulator: %s" % entry['tool'])
|
||||
compile_cmd = entry['compile_cmd']
|
||||
sim_cmd = entry['sim_cmd']
|
||||
return compile_cmd, sim_cmd
|
||||
print ("Cannot find RTL simulator %0s" % simulator)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def parse_iss_yaml(iss, iss_yaml, isa):
|
||||
"""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
|
||||
|
||||
Returns:
|
||||
cmd : ISS run command
|
||||
"""
|
||||
print("Processing ISS setup file : %s" % iss_yaml)
|
||||
yaml_data = read_yaml(iss_yaml)
|
||||
# Search for matched ISS
|
||||
for entry in yaml_data:
|
||||
if entry['iss'] == iss:
|
||||
print ("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.upper(), cmd)
|
||||
else:
|
||||
cmd = re.sub("\<variant\>", isa, cmd)
|
||||
return cmd
|
||||
print ("Cannot find ISS %0s" % iss)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def get_iss_cmd(base_cmd, elf, log):
|
||||
"""Get the ISS simulation command
|
||||
|
||||
Args:
|
||||
base_cmd : Original command template
|
||||
elf : ELF file to run ISS simualtion
|
||||
log : ISS simulation log name
|
||||
|
||||
Returns:
|
||||
cmd : Command for ISS simulation
|
||||
"""
|
||||
cmd = re.sub("\<elf\>", elf, base_cmd)
|
||||
cmd += (" &> %s" % log)
|
||||
return cmd
|
||||
|
||||
|
||||
def gen(test_list, simulator, simulator_yaml, output_dir, sim_only,
|
||||
compile_only, lsf_cmd, seed, cwd, cmp_opts, sim_opts, timeout_s, verbose):
|
||||
"""Run the instruction generator
|
||||
|
||||
Args:
|
||||
test_list : List of assembly programs to be compiled
|
||||
simulator : RTL simulator used to run instruction generator
|
||||
simulator_yaml : RTL simulator configuration file in YAML format
|
||||
output_dir : Output directory of the ELF files
|
||||
sim_only : Simulation only
|
||||
compile_only : Compile the generator only
|
||||
lsf_cmd : LSF command used to run the instruction generator
|
||||
seed : Seed to the instruction generator
|
||||
cmp_opts : Compile options for the generator
|
||||
sim_opts : Simulation options for the generator
|
||||
timeout_s : Timeout limit in seconds
|
||||
verbose : Verbose logging
|
||||
"""
|
||||
# Setup the compile and simulation command for the generator
|
||||
compile_cmd = []
|
||||
sim_cmd = ""
|
||||
compile_cmd, sim_cmd = get_generator_cmd(simulator, simulator_yaml);
|
||||
# Compile the instruction generator
|
||||
if not sim_only:
|
||||
print ("Building RISC-V instruction generator")
|
||||
for cmd in compile_cmd:
|
||||
cmd = re.sub("<out>", os.path.abspath(output_dir), cmd)
|
||||
cmd = re.sub("<cwd>", cwd, cmd)
|
||||
cmd = re.sub("<cmp_opts>", cmp_opts, cmd)
|
||||
if verbose:
|
||||
print("Compile command: %s" % cmd)
|
||||
output = run_cmd(cmd)
|
||||
if verbose:
|
||||
print(output)
|
||||
# Run the instruction generator
|
||||
if not compile_only:
|
||||
cmd_list = []
|
||||
sim_cmd = re.sub("<out>", os.path.abspath(output_dir), sim_cmd)
|
||||
sim_cmd = re.sub("<cwd>", cwd, sim_cmd)
|
||||
sim_cmd = re.sub("<sim_opts>", sim_opts, sim_cmd)
|
||||
print ("Running RISC-V instruction generator")
|
||||
for test in test_list:
|
||||
if test['iterations'] > 0:
|
||||
rand_seed = get_seed(seed)
|
||||
cmd = lsf_cmd + " " + sim_cmd.rstrip() + \
|
||||
(" +UVM_TESTNAME=%s " % test['gen_test']) + \
|
||||
(" +num_of_tests=%d " % test['iterations']) + \
|
||||
(" +asm_file_name=%s/asm_tests/%s " % (output_dir, test['test'])) + \
|
||||
(" -l %s/sim_%s.log " % (output_dir, test['test']))
|
||||
cmd = re.sub("<seed>", str(rand_seed), cmd)
|
||||
if "gen_opts" in test:
|
||||
cmd += test['gen_opts']
|
||||
print("Generating %d %s" % (test['iterations'], test['test']))
|
||||
if lsf_cmd:
|
||||
cmd_list.append(cmd)
|
||||
else:
|
||||
run_cmd(cmd, verbose, timeout_s)
|
||||
if lsf_cmd:
|
||||
run_parallel_cmd(cmd_list, verbose, timeout_s)
|
||||
|
||||
|
||||
def gcc_compile(test_list, output_dir, isa, mabi, verbose):
|
||||
"""Use riscv gcc toolchain to compile the assembly program
|
||||
|
||||
Args:
|
||||
test_list : List of assembly programs to be compiled
|
||||
output_dir : Output directory of the ELF files
|
||||
isa : ISA variant passed to GCC
|
||||
mabi : MABI variant passed to GCC
|
||||
verbose : Verbose logging
|
||||
"""
|
||||
for test in test_list:
|
||||
for i in range(0, test['iterations']):
|
||||
prefix = ("%s/asm_tests/%s.%d" % (output_dir, test['test'], i))
|
||||
asm = prefix + ".S"
|
||||
elf = prefix + ".o"
|
||||
binary = prefix + ".bin"
|
||||
# gcc comilation
|
||||
cmd = ("%s -march=%s -mabi=%s -static -mcmodel=medany \
|
||||
-fvisibility=hidden -nostdlib \
|
||||
-nostartfiles \
|
||||
-Tscripts/link.ld %s -o %s" % \
|
||||
(get_env_var("RISCV_GCC") ,isa, mabi, asm, elf))
|
||||
print("Compiling %s" % asm)
|
||||
if verbose:
|
||||
print(cmd)
|
||||
output = subprocess.check_output(cmd.split())
|
||||
if verbose:
|
||||
print(output)
|
||||
# Convert the ELF to plain binary, used in RTL sim
|
||||
print ("Converting to %s" % binary)
|
||||
cmd = ("%s -O binary %s %s" % (get_env_var("RISCV_OBJCOPY"), elf, binary))
|
||||
output = subprocess.check_output(cmd.split())
|
||||
if verbose:
|
||||
print(output)
|
||||
|
||||
|
||||
def iss_sim(test_list, output_dir, iss_list, iss_yaml, isa, timeout_s, verbose):
|
||||
"""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
|
||||
verbose : Verbose logging
|
||||
"""
|
||||
for iss in iss_list.split(","):
|
||||
log_dir = ("%s/%s_sim" % (output_dir, iss))
|
||||
base_cmd = parse_iss_yaml(iss, iss_yaml, isa)
|
||||
print ("%s sim log dir: %s" % (iss, log_dir))
|
||||
subprocess.run(["mkdir", "-p", log_dir])
|
||||
for test in test_list:
|
||||
for i in range(0, test['iterations']):
|
||||
prefix = ("%s/asm_tests/%s.%d" % (output_dir, test['test'], i))
|
||||
elf = prefix + ".o"
|
||||
log = ("%s/%s.%d.log" % (log_dir, test['test'], i))
|
||||
cmd = get_iss_cmd(base_cmd, elf, log)
|
||||
print ("Running ISS simulation: %s" % elf)
|
||||
run_cmd(cmd, 0, timeout_s)
|
||||
if verbose:
|
||||
print (cmd)
|
||||
|
||||
|
||||
def iss_cmp(test_list, iss, output_dir, isa, verbose):
|
||||
"""Compare ISS simulation reult
|
||||
|
||||
Args:
|
||||
test_list : List of assembly programs to be compiled
|
||||
iss : List of instruction set simulators
|
||||
output_dir : Output directory of the ELF files
|
||||
isa : ISA
|
||||
verbose : Verbose logging
|
||||
"""
|
||||
iss_list = iss.split(",")
|
||||
if len(iss_list) != 2:
|
||||
return
|
||||
report = ("%s/iss_regr.log" % output_dir).rstrip()
|
||||
run_cmd("rm -rf %s" % report)
|
||||
for test in test_list:
|
||||
for i in range(0, test['iterations']):
|
||||
elf = ("%s/asm_tests/%s.%d.o" % (output_dir, test['test'], i))
|
||||
print("Comparing ISS sim result %s/%s : %s" %
|
||||
(iss_list[0], iss_list[1], elf))
|
||||
csv_list = []
|
||||
run_cmd(("echo 'Test binary: %s' >> %s" % (elf, report)))
|
||||
for iss in iss_list:
|
||||
log = ("%s/%s_sim/%s.%d.log" % (output_dir, iss, test['test'], i))
|
||||
csv = ("%s/%s_sim/%s.%d.csv" % (output_dir, iss, test['test'], i))
|
||||
csv_list.append(csv)
|
||||
if iss == "spike":
|
||||
process_spike_sim_log(log, csv)
|
||||
elif iss == "ovpsim":
|
||||
process_ovpsim_sim_log(log, csv)
|
||||
else:
|
||||
print("Unsupported ISS" % iss)
|
||||
sys.exit(1)
|
||||
compare_trace_csv(csv_list[0], csv_list[1], iss_list[0], iss_list[1], report)
|
||||
passed_cnt = run_cmd("grep PASSED %s | wc -l" % report).strip()
|
||||
failed_cnt = run_cmd("grep FAILED %s | wc -l" % report).strip()
|
||||
summary = ("%s PASSED, %s FAILED" % (passed_cnt, failed_cnt))
|
||||
print(summary)
|
||||
run_cmd(("echo %s >> %s" % (summary, report)))
|
||||
print("ISS regression report is saved to %s" % report)
|
||||
|
||||
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument("--o", type=str, default="./out",
|
||||
help="Output directory name")
|
||||
parser.add_argument("--testlist", type=str, default="",
|
||||
help="Regression testlist")
|
||||
parser.add_argument("--isa", type=str, default="rv64imc",
|
||||
help="RISC-V ISA subset")
|
||||
parser.add_argument("--mabi", type=str, default="lp64",
|
||||
help="mabi used for compilation, lp32 or lp64")
|
||||
parser.add_argument("--test", type=str, default="all",
|
||||
help="Test name, 'all' means all tests in the list")
|
||||
parser.add_argument("--seed", type=int, default=-1,
|
||||
help="Randomization seed, default -1 means random seed")
|
||||
parser.add_argument("--iterations", type=int, default=0,
|
||||
help="Override the iteration count in the test list")
|
||||
parser.add_argument("--simulator", type=str, default="vcs",
|
||||
help="Simulator used to run the generator, default VCS")
|
||||
parser.add_argument("--simulator_yaml", type=str, default="",
|
||||
help="RTL simulator setting YAML")
|
||||
parser.add_argument("--iss", type=str, default="spike",
|
||||
help="RISC-V instruction set simulator: spike, ovpsim")
|
||||
parser.add_argument("--iss_yaml", type=str, default="",
|
||||
help="ISS setting YAML")
|
||||
parser.add_argument("--verbose", type=int, default=0,
|
||||
help="Verbose logging")
|
||||
parser.add_argument("--co", type=int, default=0,
|
||||
help="Compile the generator only")
|
||||
parser.add_argument("--so", type=int, default=0,
|
||||
help="Simulate the generator only")
|
||||
parser.add_argument("--cmp_opts", type=str, default="",
|
||||
help="Compile options for the generator")
|
||||
parser.add_argument("--sim_opts", type=str, default="",
|
||||
help="Simulation options for the generator")
|
||||
parser.add_argument("--steps", type=str, default="all",
|
||||
help="Run steps: gen,gcc_compile,iss_sim,iss_cmp")
|
||||
parser.add_argument("--lsf_cmd", type=str, default="",
|
||||
help="LSF command. Run in local sequentially if lsf \
|
||||
command is not specified")
|
||||
parser.add_argument("--gen_timeout", type=int, default=360,
|
||||
help="Generator timeout limit in seconds")
|
||||
parser.add_argument("--iss_timeout", type=int, default=50,
|
||||
help="ISS sim timeout limit in seconds")
|
||||
|
||||
args = parser.parse_args()
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
if not args.iss_yaml:
|
||||
args.iss_yaml = cwd + "/yaml/iss.yaml"
|
||||
|
||||
if not args.simulator_yaml:
|
||||
args.simulator_yaml = cwd + "/yaml/simulator.yaml"
|
||||
|
||||
if not args.testlist:
|
||||
args.testlist = cwd + "/yaml/testlist.yaml"
|
||||
|
||||
# Create output directory
|
||||
subprocess.run(["mkdir", "-p", args.o])
|
||||
subprocess.run(["mkdir", "-p", ("%s/asm_tests" % args.o)])
|
||||
|
||||
# Process regression test list
|
||||
matched_list = []
|
||||
process_regression_list(args.testlist, args.test, args.iterations, matched_list)
|
||||
if len(matched_list) == 0:
|
||||
sys.exit("Cannot find %s in %s" % (args.test, args.testlist))
|
||||
|
||||
# Run instruction generator
|
||||
if args.steps == "all" or re.match("gen", args.steps):
|
||||
gen(matched_list, args.simulator, args.simulator_yaml, args.o,
|
||||
args.so, args.co, args.lsf_cmd, args.seed, cwd,
|
||||
args.cmp_opts, args.sim_opts, args.gen_timeout, args.verbose)
|
||||
|
||||
# Compile the assembly program to ELF, convert to plain binary
|
||||
if args.steps == "all" or re.match("gcc_compile", args.steps):
|
||||
gcc_compile(matched_list, args.o, args.isa, args.mabi, args.verbose)
|
||||
|
||||
# Run ISS simulation
|
||||
if args.steps == "all" or re.match("iss_sim", args.steps):
|
||||
iss_sim(matched_list, args.o, args.iss, args.iss_yaml,
|
||||
args.isa, args.iss_timeout, args.verbose)
|
||||
|
||||
# Compare ISS simulation result
|
||||
if args.steps == "all" or re.match("iss_cmp", args.steps):
|
||||
iss_cmp(matched_list, args.iss, args.o, args.isa, args.verbose)
|
280
vendor/google_riscv-dv/scripts/gen_csr_test.py
vendored
Normal file
280
vendor/google_riscv-dv/scripts/gen_csr_test.py
vendored
Normal file
|
@ -0,0 +1,280 @@
|
|||
"""
|
||||
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.
|
||||
|
||||
Parse processor-specific CSR description YAML file and generate a CSR test file.
|
||||
This test code will utilize every CSR instruction, writing values to the CSR
|
||||
and then using a prediction function to calculate a reference value that will
|
||||
be written into another register and compared against the value actually stored
|
||||
in the CSR at this point, allowing for the test to self-check in order to
|
||||
determine success or failure.
|
||||
"""
|
||||
|
||||
|
||||
"""
|
||||
To install the bitstring library:
|
||||
1) sudo apt-get install python3-bitstring OR
|
||||
2) pip install bitstring
|
||||
"""
|
||||
import sys
|
||||
import yaml
|
||||
import argparse
|
||||
import random
|
||||
from bitstring import BitArray as bitarray
|
||||
|
||||
|
||||
def get_csr_map(csr_file, xlen):
|
||||
"""
|
||||
Parses the YAML file containing CSR descriptions.
|
||||
|
||||
Args:
|
||||
csr_file: The CSR YAML file.
|
||||
xlen: The current RISC-V ISA bit length.
|
||||
|
||||
Returns:
|
||||
A dictionary contining mappings for each CSR, of the form:
|
||||
{ csr_name : [csr_val_bitarray, csr_mask_bitarray] }
|
||||
"""
|
||||
rv_string = "rv{}".format(str(xlen))
|
||||
csrs = {}
|
||||
with open(csr_file, "r") as c:
|
||||
csr_description = yaml.safe_load(c)
|
||||
for csr_dict in csr_description:
|
||||
csr_name = csr_dict.get("csr")
|
||||
assert(rv_string in csr_dict), "The {} CSR must be configured for rv{}".format(csr_name, str(rv))
|
||||
csr_value = bitarray(uintbe=0, length=xlen)
|
||||
csr_mask = bitarray(uintbe=0, length=xlen)
|
||||
csr_field_list = csr_dict.get(rv_string)
|
||||
for csr_field_detail_dict in csr_field_list:
|
||||
field_type = csr_field_detail_dict.get("type")
|
||||
field_val = csr_field_detail_dict.get("reset_val")
|
||||
field_msb = csr_field_detail_dict.get("msb")
|
||||
field_lsb = csr_field_detail_dict.get("lsb")
|
||||
field_size = field_msb - field_lsb
|
||||
if field_type != "WPRI":
|
||||
val_size = field_msb - field_lsb + 1
|
||||
val_bitarray = bitarray(uint=field_val, length=val_size)
|
||||
mask_bitarray = bitarray(uint=1, length=1) * val_size
|
||||
csr_value.overwrite(val_bitarray, xlen - 1 - field_msb)
|
||||
csr_mask.overwrite(mask_bitarray, xlen - 1 - field_msb)
|
||||
csrs.update({csr_name : [csr_value, csr_mask]})
|
||||
return csrs
|
||||
|
||||
|
||||
def get_rs1_val(iteration, xlen):
|
||||
"""
|
||||
Calculates and returns the 3 test RS1 values that will be used
|
||||
to exercise the CSR.
|
||||
|
||||
Args:
|
||||
iteration: Integer between 0 and 2 inclusive, indicates which
|
||||
test value to return.
|
||||
xlen: The currnet RISC-V ISA bit length.
|
||||
|
||||
Returns:
|
||||
A bitarray encoding the value that will be written to the CSR to test it.
|
||||
Will be one of 3 values:
|
||||
1) 0xa5a5...
|
||||
2) 0x5a5a...
|
||||
3) A randomly generated number
|
||||
"""
|
||||
if iteration == 0:
|
||||
return bitarray(hex=f"0x{'a5'*int(xlen/8)}")
|
||||
elif iteration == 1:
|
||||
return bitarray(hex=f"0x{'5a'*int(xlen/8)}")
|
||||
elif iteration == 2:
|
||||
val = bitarray(uint=0, length=xlen)
|
||||
# Must randomize all 32 bits, due to randomization library limitations
|
||||
for i in range(32):
|
||||
bit = random.randint(0, 1)
|
||||
val.set(bit, i)
|
||||
return val
|
||||
|
||||
|
||||
def csr_write(val, csr_val, csr_mask):
|
||||
"""
|
||||
Performs a CSR write.
|
||||
|
||||
Args:
|
||||
val: A bitarray containing the value to be written.
|
||||
csr_val: A bitarray containing the current CSR value.
|
||||
csr_mask: A bitarray containing the CSR's mask.
|
||||
"""
|
||||
if val.len != csr_mask.len:
|
||||
csr_val.overwrite(val & csr_mask, 0)
|
||||
|
||||
|
||||
"""
|
||||
CSR Read:
|
||||
Reads the given CSR, after applying the bitmask
|
||||
"""
|
||||
def csr_read(csr_val, csr_mask):
|
||||
"""
|
||||
Performs a CSR read.
|
||||
|
||||
Args:
|
||||
csr_val: A bitarray containing the current CSR value.
|
||||
csr_mask: A bitarray containing the CSR's mask.
|
||||
|
||||
Returns:
|
||||
A bitarray of the logical AND of csr_val and csr_mask.
|
||||
"""
|
||||
return csr_val & csr_mask
|
||||
|
||||
|
||||
def predict_csr_val(csr_op, rs1_val, csr_val, csr_mask):
|
||||
"""
|
||||
Predicts the CSR reference value, based on the current CSR operation.
|
||||
|
||||
Args:
|
||||
csr_op: A string of the CSR operation being performed.
|
||||
rs1_val: A bitarray containing the value to be written to the CSR.
|
||||
csr_val: A bitarray containing the current value of the CSR.
|
||||
csr_mask: A bitarray containing the CSR's mask.
|
||||
|
||||
Returns:
|
||||
A hexadecimal string of the predicted CSR value.
|
||||
"""
|
||||
prediction = None
|
||||
# create a zero bitarray to zero extend immediates
|
||||
zero = bitarray(uint=0, length=csr_val.len - 5)
|
||||
if csr_op == 'csrrw':
|
||||
prediction = csr_read(csr_val, csr_mask)
|
||||
csr_write(rs1_val, csr_val, csr_mask)
|
||||
elif csr_op == 'csrrs':
|
||||
prediction = csr_read(csr_val, csr_mask)
|
||||
csr_write(rs1_val | prediction, csr_val, csr_mask)
|
||||
elif csr_op == 'csrrc':
|
||||
prediction = csr_read(csr_val, csr_mask)
|
||||
csr_write((~rs1_val) & prediction, csr_val, csr_mask)
|
||||
elif csr_op == 'csrrwi':
|
||||
prediction = csr_read(csr_val, csr_mask)
|
||||
zero.append(rs1_val[-5:])
|
||||
csr_write(zero, csr_val, csr_mask)
|
||||
elif csr_op == 'csrrsi':
|
||||
prediction = csr_read(csr_val, csr_mask)
|
||||
zero.append(rs1_val[-5:])
|
||||
csr_write(zero | prediction, csr_val, csr_mask)
|
||||
elif csr_op == 'csrrci':
|
||||
prediction = csr_read(csr_val, csr_mask)
|
||||
zero.append(rs1_val[-5:])
|
||||
csr_write((~zero) & prediction, csr_val, csr_mask)
|
||||
return f"0x{prediction.hex}"
|
||||
|
||||
|
||||
def gen_csr_test_fail(test_file):
|
||||
"""
|
||||
Generates code to handle a test failure.
|
||||
This code consists of writing 1 to the GP register in an infinite loop.
|
||||
The testbench will poll this register at the end of the test to detect failure.
|
||||
|
||||
Args:
|
||||
The file containing the generated assembly test code.
|
||||
"""
|
||||
test_file.write(f"csr_fail:\n")
|
||||
test_file.write(f"\tli gp, 1\n")
|
||||
test_file.write(f"\tj csr_fail\n")
|
||||
|
||||
|
||||
def gen_csr_test_pass(test_file):
|
||||
"""
|
||||
Generates code to handle test success.
|
||||
This code consists of writing 2 to the GP register in an infinite loop.
|
||||
The testbench will poll this register at the end of the test to detect success.
|
||||
|
||||
Args:
|
||||
The file containing the generated assembly test code.
|
||||
"""
|
||||
test_file.write(f"csr_pass:\n")
|
||||
test_file.write(f"\tli gp, 1\n")
|
||||
test_file.write(f"\tj csr_pass\n")
|
||||
|
||||
|
||||
def gen_csr_instr(csr_map, csr_instructions, xlen, iterations, out):
|
||||
"""
|
||||
Uses the information in the map produced by get_csr_map() to generate
|
||||
test CSR instructions operating on the generated random values.
|
||||
|
||||
Args:
|
||||
csr_map: The dictionary containing CSR mappings generated by get_csr_map()
|
||||
csr_instructions: A list of all supported CSR instructions in string form.
|
||||
xlen: The RISC-V ISA bit length.
|
||||
iterations: Indicates how many randomized test files will be generated.
|
||||
out: A string containing the directory path that the tests will be generated in.
|
||||
|
||||
Returns:
|
||||
No explicit return value, but will write the randomized assembly test code
|
||||
to the specified number of files.
|
||||
"""
|
||||
for i in range(iterations):
|
||||
# pick two GPRs at random to act as source and destination registers
|
||||
# for CSR operations
|
||||
source_reg, dest_reg = [f"x{i}" for i in random.sample(range(5, 15), 2)]
|
||||
csr_list = list(csr_map.keys())
|
||||
with open(f"{out}/riscv_csr_test.{i}.S", "w") as csr_test_file:
|
||||
csr_test_file.write(f"csr_test:\n")
|
||||
for csr in csr_list:
|
||||
last_csr = csr
|
||||
csr_val, csr_mask = csr_map.get(csr)
|
||||
for op in csr_instructions:
|
||||
for i in range(3):
|
||||
# hex string
|
||||
rand_rs1_val = get_rs1_val(i, xlen)
|
||||
# I type CSR instruction
|
||||
first_li = ""
|
||||
if op[-1] == "i":
|
||||
imm = rand_rs1_val[-5:]
|
||||
csr_inst = f"\t{op} {dest_reg}, {csr}, 0b{imm.bin}\n"
|
||||
else:
|
||||
first_li = f"\tli {source_reg}, 0x{rand_rs1_val.hex}\n"
|
||||
csr_inst = f"\t{op} {dest_reg}, {csr}, {source_reg}\n"
|
||||
predict_li = f"\tli {source_reg}, {predict_csr_val(op, rand_rs1_val, csr_val, csr_mask)}\n"
|
||||
branch_check = f"\tbne {source_reg}, {dest_reg}, csr_fail\n"
|
||||
csr_test_file.write(first_li)
|
||||
csr_test_file.write(csr_inst)
|
||||
csr_test_file.write(predict_li)
|
||||
csr_test_file.write(branch_check)
|
||||
"""
|
||||
We must hardcode in one final CSR check, as the value that has last
|
||||
been written to the CSR has not been tested.
|
||||
"""
|
||||
if csr == csr_list[-1] and op == csr_instructions[-1] and i == 2:
|
||||
final_csr_read = f"\tcsrr {dest_reg}, {csr_list[-1]}\n"
|
||||
csrrs_read_mask = bitarray(uint=0, length=xlen)
|
||||
final_li = f"\tli {source_reg}, {predict_csr_val('csrrs', csrrs_read_mask, csr_val, csr_mask)}\n"
|
||||
final_branch_check = f"\tbne {source_reg}, {dest_reg}, csr_fail\n"
|
||||
csr_test_file.write(final_csr_read)
|
||||
csr_test_file.write(final_li)
|
||||
csr_test_file.write(final_branch_check)
|
||||
gen_csr_test_pass(csr_test_file)
|
||||
gen_csr_test_fail(csr_test_file)
|
||||
|
||||
|
||||
"""
|
||||
Define command line arguments.
|
||||
"""
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--csr_file", type=str, help="The YAML file contating descriptions of all processor supported CSRs")
|
||||
parser.add_argument("--xlen", type=int, default=32, help="Specify the ISA width, e.g. 32 or 64 or 128")
|
||||
parser.add_argument("--num_test", type=int, default=1, help="Specify how many tests to be generated")
|
||||
parser.add_argument("--out", type=str, default="./", help="Specify output directory")
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
"""
|
||||
A list containing all supported CSR instructions.
|
||||
"""
|
||||
csr_ops = ['csrrw', 'csrrs', 'csrrc', 'csrrwi', 'csrrsi', 'csrrci']
|
||||
|
||||
gen_csr_instr(get_csr_map(args.csr_file, args.xlen), csr_ops, args.xlen, args.num_test, args.out)
|
|
@ -15,18 +15,31 @@ limitations under the License.
|
|||
|
||||
Compare the instruction trace CSV
|
||||
"""
|
||||
import re
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sys
|
||||
|
||||
from riscv_trace_csv import *
|
||||
|
||||
def compare_trace_csv(csv1, csv2, name1, name2,
|
||||
in_order_mode, coalescing_limit, verbose,
|
||||
mismatch_print_limit, compare_final_value_only):
|
||||
def compare_trace_csv(csv1, csv2, name1, name2, log,
|
||||
in_order_mode = 1,
|
||||
coalescing_limit = 0,
|
||||
verbose = 0,
|
||||
mismatch_print_limit = 5,
|
||||
compare_final_value_only = 0):
|
||||
"""Compare two trace CSV file"""
|
||||
matched_cnt = 0
|
||||
mismatch_cnt = 0
|
||||
|
||||
if log:
|
||||
fd = open(log, 'a+')
|
||||
else:
|
||||
fd = sys.stdout
|
||||
|
||||
fd.write("%s : %s\n" % (name1, csv1))
|
||||
fd.write("%s : %s\n" % (name2, csv2))
|
||||
|
||||
with open(csv1, "r") as fd1, open(csv2, "r") as fd2:
|
||||
instr_trace_1 = []
|
||||
instr_trace_2 = []
|
||||
|
@ -58,21 +71,21 @@ def compare_trace_csv(csv1, csv2, name1, name2,
|
|||
# Check if the GPR update is the same between trace 1 and 2
|
||||
if gpr_state_change_2 == 0:
|
||||
mismatch_cnt += 1
|
||||
print("Mismatch[%d]:\n[%d] %s : %s" %
|
||||
(mismatch_cnt, trace_1_index, name1, trace.get_trace_string()))
|
||||
print ("%0d instructions left in trace %0s" %
|
||||
(len(instr_trace_1) - trace_1_index + 1, name1))
|
||||
fd.write("Mismatch[%d]:\n[%d] %s : %s\n" %
|
||||
(mismatch_cnt, trace_1_index, name1, trace.get_trace_string()))
|
||||
fd.write("%0d instructions left in trace %0s\n" %
|
||||
(len(instr_trace_1) - trace_1_index + 1, name1))
|
||||
elif (trace.rd != instr_trace_2[trace_2_index-1].rd or
|
||||
trace.rd_val != instr_trace_2[trace_2_index-1].rd_val):
|
||||
mismatch_cnt += 1
|
||||
# print first few mismatches
|
||||
if mismatch_cnt <= mismatch_print_limit:
|
||||
print("Mismatch[%d]:\n%s[%d] : %s" %
|
||||
(mismatch_cnt, name1, trace_2_index - 1,
|
||||
trace.get_trace_string()))
|
||||
print("%s[%d] : %s" %
|
||||
(name2, trace_2_index - 1,
|
||||
instr_trace_2[trace_2_index-1].get_trace_string()))
|
||||
fd.write("Mismatch[%d]:\n%s[%d] : %s\n" %
|
||||
(mismatch_cnt, name1, trace_2_index - 1,
|
||||
trace.get_trace_string()))
|
||||
fd.write("%s[%d] : %s\n" %
|
||||
(name2, trace_2_index - 1,
|
||||
instr_trace_2[trace_2_index-1].get_trace_string()))
|
||||
else:
|
||||
matched_cnt += 1
|
||||
# Break the loop if it reaches the end of trace 2
|
||||
|
@ -86,8 +99,8 @@ def compare_trace_csv(csv1, csv2, name1, name2,
|
|||
instr_trace_2[trace_2_index].rd_val,
|
||||
gpr_val_2)
|
||||
if gpr_state_change_2 == 1:
|
||||
print ("%0d instructions left in trace %0s" %
|
||||
(len(instr_trace_2) - trace_2_index, name2))
|
||||
fd.write("%0d instructions left in trace %0s\n" %
|
||||
(len(instr_trace_2) - trace_2_index, name2))
|
||||
mismatch_cnt += len(instr_trace_2) - trace_2_index
|
||||
break
|
||||
trace_2_index += 1
|
||||
|
@ -101,17 +114,17 @@ def compare_trace_csv(csv1, csv2, name1, name2,
|
|||
parse_gpr_update_from_trace(instr_trace_1, gpr_trace_1)
|
||||
parse_gpr_update_from_trace(instr_trace_2, gpr_trace_2)
|
||||
if len(gpr_trace_1) != len(gpr_trace_2):
|
||||
print("Mismatch: affected GPR count mismtach %s:%d VS %s:%d" %
|
||||
(name1, len(gpr_trace_1), name2, len(gpr_trace_2)))
|
||||
fd.write("Mismatch: affected GPR count mismtach %s:%d VS %s:%d\n" %
|
||||
(name1, len(gpr_trace_1), name2, len(gpr_trace_2)))
|
||||
mismatch_cnt += 1
|
||||
if not compare_final_value_only:
|
||||
for gpr in gpr_trace_1:
|
||||
coalesced_updates = 0
|
||||
if (len(gpr_trace_1[gpr]) != len(gpr_trace_2[gpr]) and
|
||||
coalescing_limit == 0):
|
||||
print("Mismatch: GPR[%s] trace count mismtach %s:%d VS %s:%d" %
|
||||
(gpr, name1, len(gpr_trace_1[gpr]),
|
||||
name2, len(gpr_trace_2[gpr])))
|
||||
fd.write("Mismatch: GPR[%s] trace count mismtach %s:%d VS %s:%d\n" %
|
||||
(gpr, name1, len(gpr_trace_1[gpr]),
|
||||
name2, len(gpr_trace_2[gpr])))
|
||||
mismatch_cnt += 1
|
||||
trace_2_index = 0
|
||||
coalesced_updates = 0
|
||||
|
@ -124,45 +137,47 @@ def compare_trace_csv(csv1, csv2, name1, name2,
|
|||
coalesced_updates = 0
|
||||
mismatch_cnt += 1
|
||||
if mismatch_cnt <= mismatch_print_limit:
|
||||
print("Mismatch:")
|
||||
print("%s[%d] : %s" % (name1, trace_1_index,
|
||||
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
|
||||
print("%s[%d] : %s" % (name2, trace_2_index,
|
||||
gpr_trace_2[gpr][trace_2_index].get_trace_string()))
|
||||
fd.write("Mismatch:\n")
|
||||
fd.write("%s[%d] : %s\n" % (name1, trace_1_index,
|
||||
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
|
||||
fd.write("%s[%d] : %s\n" % (name2, trace_2_index,
|
||||
gpr_trace_2[gpr][trace_2_index].get_trace_string()))
|
||||
trace_2_index += 1
|
||||
else:
|
||||
if verbose:
|
||||
print("Skipping %s[%d] : %s" %
|
||||
(name1, trace_1_index,
|
||||
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
|
||||
fd.write("Skipping %s[%d] : %s\n" %
|
||||
(name1, trace_1_index,
|
||||
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
|
||||
coalesced_updates += 1
|
||||
else:
|
||||
coalesced_updates = 0
|
||||
matched_cnt += 1
|
||||
if verbose:
|
||||
print("Matched [%0d]: %s : %s" %
|
||||
(trace_1_index, name1,
|
||||
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
|
||||
fd.write("Matched [%0d]: %s : %s\n" %
|
||||
(trace_1_index, name1,
|
||||
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
|
||||
trace_2_index += 1
|
||||
# Check the final value match between the two traces
|
||||
for gpr in gpr_trace_1:
|
||||
if (len(gpr_trace_1[gpr]) == 0 or len(gpr_trace_2[gpr]) == 0):
|
||||
mismatch_cnt += 1
|
||||
print("Zero GPR[%s] updates observed: %s:%d, %s:%d" % (gpr,
|
||||
name1, len(gpr_trace_1[gpr]), name2, len(gpr_trace_2[gpr])))
|
||||
fd.write("Zero GPR[%s] updates observed: %s:%d, %s:%d\n" % (gpr,
|
||||
name1, len(gpr_trace_1[gpr]), name2, len(gpr_trace_2[gpr])))
|
||||
elif long(gpr_trace_1[gpr][-1].rd_val, 16) != \
|
||||
long(gpr_trace_2[gpr][-1].rd_val, 16):
|
||||
mismatch_cnt += 1
|
||||
if mismatch_cnt <= mismatch_print_limit:
|
||||
print("Mismatch final value:")
|
||||
print("%s : %s" % (name1, gpr_trace_1[gpr][-1].get_trace_string()))
|
||||
print("%s : %s" % (name2, gpr_trace_2[gpr][-1].get_trace_string()))
|
||||
fd.write("Mismatch final value:\n")
|
||||
fd.write("%s : %s\n" % (name1, gpr_trace_1[gpr][-1].get_trace_string()))
|
||||
fd.write("%s : %s\n" % (name2, gpr_trace_2[gpr][-1].get_trace_string()))
|
||||
if mismatch_cnt == 0:
|
||||
compare_result = "PASSED"
|
||||
else:
|
||||
compare_result = "FAILED"
|
||||
print("Compare result[%s]: %d matched, %d mismatch" %
|
||||
(compare_result, matched_cnt, mismatch_cnt))
|
||||
fd.write("Compare result[%s]: %d matched, %d mismatch\n\n" %
|
||||
(compare_result, matched_cnt, mismatch_cnt))
|
||||
if log:
|
||||
fd.close()
|
||||
|
||||
|
||||
def parse_gpr_update_from_trace(trace_csv, gpr_trace):
|
||||
|
@ -188,34 +203,41 @@ def check_update_gpr(rd, rd_val, gpr):
|
|||
return gpr_state_change
|
||||
|
||||
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("csv_file_1", type=str, help="Instruction trace 1 CSV")
|
||||
parser.add_argument("csv_file_2", type=str, help="Instruction trace 2 CSV")
|
||||
parser.add_argument("csv_name_1", type=str, help="Instruction trace 1 name")
|
||||
parser.add_argument("csv_name_2", type=str, help="Instruction trace 2 name")
|
||||
# optional arguments
|
||||
parser.add_argument("--in_order_mode", type=int, default=1,
|
||||
help="In order comparison mode")
|
||||
parser.add_argument("--gpr_update_coalescing_limit", type=int, default=1,
|
||||
help="Allow the core to merge multiple updates to the \
|
||||
same GPR into one. This option only applies to \
|
||||
trace 2")
|
||||
parser.add_argument("--mismatch_print_limit", type=int, default=5,
|
||||
help="Max number of mismatches printed")
|
||||
parser.add_argument("--verbose", type=int, default=0,
|
||||
help="Verbose logging")
|
||||
parser.add_argument("--compare_final_value_only", type=int, default=0,
|
||||
help="Only compare the final value of the GPR")
|
||||
def main():
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("csv_file_1", type=str, help="Instruction trace 1 CSV")
|
||||
parser.add_argument("csv_file_2", type=str, help="Instruction trace 2 CSV")
|
||||
parser.add_argument("csv_name_1", type=str, help="Instruction trace 1 name")
|
||||
parser.add_argument("csv_name_2", type=str, help="Instruction trace 2 name")
|
||||
# optional arguments
|
||||
parser.add_argument("--log", type=str, default="",
|
||||
help="Log file")
|
||||
parser.add_argument("--in_order_mode", type=int, default=1,
|
||||
help="In order comparison mode")
|
||||
parser.add_argument("--gpr_update_coalescing_limit", type=int, default=1,
|
||||
help="Allow the core to merge multiple updates to the \
|
||||
same GPR into one. This option only applies to \
|
||||
trace 2")
|
||||
parser.add_argument("--mismatch_print_limit", type=int, default=5,
|
||||
help="Max number of mismatches printed")
|
||||
parser.add_argument("--verbose", type=int, default=0,
|
||||
help="Verbose logging")
|
||||
parser.add_argument("--compare_final_value_only", type=int, default=0,
|
||||
help="Only compare the final value of the GPR")
|
||||
|
||||
args = parser.parse_args()
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.compare_final_value_only:
|
||||
args.in_order_mode = 0
|
||||
if args.compare_final_value_only:
|
||||
args.in_order_mode = 0
|
||||
|
||||
# Compare trace CSV
|
||||
compare_trace_csv(args.csv_file_1, args.csv_file_2,
|
||||
args.csv_name_1, args.csv_name_2,
|
||||
args.in_order_mode, args.gpr_update_coalescing_limit,
|
||||
args.verbose, args.mismatch_print_limit,
|
||||
args.compare_final_value_only)
|
||||
# Compare trace CSV
|
||||
compare_trace_csv(args.csv_file_1, args.csv_file_2,
|
||||
args.csv_name_1, args.csv_name_2, args.log,
|
||||
args.in_order_mode, args.gpr_update_coalescing_limit,
|
||||
args.verbose, args.mismatch_print_limit,
|
||||
args.compare_final_value_only)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
157
vendor/google_riscv-dv/scripts/lib.py
vendored
Normal file
157
vendor/google_riscv-dv/scripts/lib.py
vendored
Normal file
|
@ -0,0 +1,157 @@
|
|||
"""
|
||||
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.
|
||||
|
||||
Parse the regression testlist in YAML format
|
||||
"""
|
||||
|
||||
import os
|
||||
import random
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
import yaml
|
||||
|
||||
def read_yaml(yaml_file):
|
||||
""" Read YAML file to a dictionary
|
||||
|
||||
Args:
|
||||
yaml_file : YAML file
|
||||
|
||||
Returns:
|
||||
yaml_data : data read from YAML in dictionary format
|
||||
"""
|
||||
with open(yaml_file, "r") as f:
|
||||
try:
|
||||
yaml_data = yaml.safe_load(f)
|
||||
except yaml.YAMLError as exc:
|
||||
print(exc)
|
||||
sys.exit(1)
|
||||
return yaml_data
|
||||
|
||||
|
||||
def get_env_var(var):
|
||||
"""Get the value of environment variable
|
||||
|
||||
Args:
|
||||
var : Name of the environment variable
|
||||
|
||||
Returns:
|
||||
val : Value of the environment variable
|
||||
"""
|
||||
try:
|
||||
val = os.environ[var]
|
||||
except KeyError:
|
||||
print ("Please set the environment variable %0s" % var)
|
||||
sys.exit(1)
|
||||
return val
|
||||
|
||||
|
||||
def get_seed(seed):
|
||||
"""Get the seed to run the generator
|
||||
|
||||
Args:
|
||||
seed : input seed
|
||||
|
||||
Returns:
|
||||
seed to run instruction generator
|
||||
"""
|
||||
if seed >= 0:
|
||||
return seed
|
||||
else:
|
||||
return random.getrandbits(32)
|
||||
|
||||
|
||||
def run_cmd(cmd, verbose = 0, timeout_s = 999):
|
||||
"""Run a command and return output
|
||||
|
||||
Args:
|
||||
cmd : shell command to run
|
||||
|
||||
Returns:
|
||||
command output
|
||||
"""
|
||||
try:
|
||||
ps = subprocess.Popen(cmd,
|
||||
shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as exc:
|
||||
print(ps.communicate()[0])
|
||||
sys.exit(1)
|
||||
try:
|
||||
output = ps.communicate(timeout = timeout_s)[0]
|
||||
except subprocess.TimeoutExpired:
|
||||
print("Timeout[%ds]: %s" % (timeout_s, cmd))
|
||||
output = ""
|
||||
ps.kill()
|
||||
if verbose:
|
||||
print(output)
|
||||
return output
|
||||
|
||||
|
||||
def run_parallel_cmd(cmd_list, verbose = 0, timeout_s = 999):
|
||||
"""Run a list of commands in parallel
|
||||
|
||||
Args:
|
||||
cmd_list: command list
|
||||
|
||||
Returns:
|
||||
command output
|
||||
"""
|
||||
children = []
|
||||
for cmd in cmd_list:
|
||||
ps = subprocess.Popen(cmd,
|
||||
shell=True,
|
||||
universal_newlines=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT)
|
||||
children.append(ps)
|
||||
for i in range(len(children)):
|
||||
print("Command progress: %d/%d" % (i, len(children)))
|
||||
if verbose:
|
||||
print("Waiting for command: %s" % cmd_list[i])
|
||||
try:
|
||||
output = children[i].communicate(timeout = timeout_s)[0]
|
||||
except subprocess.TimeoutExpired:
|
||||
print("Timeout[%ds]: %s" % (timeout_s, cmd))
|
||||
children[i].kill()
|
||||
# Restore stty setting otherwise the terminal may go crazy
|
||||
os.system("stty sane")
|
||||
if verbose:
|
||||
print(output)
|
||||
|
||||
|
||||
def process_regression_list(testlist, test, iterations, matched_list):
|
||||
""" Get the matched tests from the regression test list
|
||||
|
||||
Args:
|
||||
testlist : Regression test list
|
||||
test : Test to run, "all" means all tests in the list
|
||||
iterations : Number of iterations for each test
|
||||
|
||||
Returns:
|
||||
matched_list : A list of matched tests
|
||||
"""
|
||||
print("Processing regression test list : %s, test: %s" % (testlist, test))
|
||||
yaml_data = read_yaml(testlist)
|
||||
for entry in yaml_data:
|
||||
if (entry['test'] == test) or (test == "all"):
|
||||
if iterations > 0:
|
||||
entry['iterations'] = iterations
|
||||
if entry['iterations'] > 0:
|
||||
print ("Found matched tests: %s, iterations:%0d" %
|
||||
(entry['test'], entry['iterations']))
|
||||
matched_list.append(entry)
|
|
@ -16,6 +16,7 @@ limitations under the License.
|
|||
Convert ovpsim sim log to standard riscv instruction trace format
|
||||
"""
|
||||
import re
|
||||
import os
|
||||
import argparse
|
||||
|
||||
from riscv_trace_csv import *
|
||||
|
@ -32,6 +33,13 @@ def process_ovpsim_sim_log(ovpsim_log, csv):
|
|||
trace_bin = ""
|
||||
trace_addr = ""
|
||||
|
||||
# Remove the header part of ovpsim log
|
||||
cmd = ("sed -i '/Info 1:/,$!d' %s" % ovpsim_log)
|
||||
os.system(cmd)
|
||||
# Remove all instructions after ecall (end of program excecution)
|
||||
cmd = ("sed -i '/ecall/q' %s" % ovpsim_log)
|
||||
os.system(cmd)
|
||||
|
||||
with open(ovpsim_log, "r") as f, open(csv, "w") as csv_fd:
|
||||
trace_csv = RiscvInstructiontTraceCsv(csv_fd)
|
||||
trace_csv.start_new_trace()
|
||||
|
@ -60,11 +68,18 @@ def process_ovpsim_sim_log(ovpsim_log, csv):
|
|||
trace_csv.write_trace_entry(rv_instr_trace)
|
||||
print("Processed instruction count : %d" % instr_cnt)
|
||||
|
||||
instr_trace = []
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--log", type=str, help="Input ovpsim simulation log")
|
||||
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
|
||||
args = parser.parse_args()
|
||||
# Process ovpsim log
|
||||
process_ovpsim_sim_log(args.log, args.csv)
|
||||
|
||||
def main():
|
||||
instr_trace = []
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--log", type=str, help="Input ovpsim simulation log")
|
||||
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
|
||||
args = parser.parse_args()
|
||||
# Process ovpsim log
|
||||
process_ovpsim_sim_log(args.log, args.csv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
|
|
@ -15,8 +15,13 @@ limitations under the License.
|
|||
|
||||
Convert spike sim log to standard riscv instruction trace format
|
||||
"""
|
||||
import re
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
from riscv_trace_csv import *
|
||||
|
||||
|
@ -30,6 +35,13 @@ def process_spike_sim_log(spike_log, csv):
|
|||
instr_cnt = 0
|
||||
spike_instr = ""
|
||||
|
||||
# Remove all the init spike boot instructions
|
||||
cmd = ("sed -i '/core.*0x0000000000001010/,$!d' %s" % spike_log)
|
||||
os.system(cmd)
|
||||
# Remove all instructions after ecall (end of program excecution)
|
||||
cmd = ("sed -i '/ecall/q' %s" % spike_log)
|
||||
os.system(cmd)
|
||||
|
||||
with open(spike_log, "r") as f, open(csv, "w") as csv_fd:
|
||||
trace_csv = RiscvInstructiontTraceCsv(csv_fd)
|
||||
trace_csv.start_new_trace()
|
||||
|
@ -55,11 +67,16 @@ def process_spike_sim_log(spike_log, csv):
|
|||
trace_csv.write_trace_entry(rv_instr_trace)
|
||||
print("Processed instruction count : %d" % instr_cnt)
|
||||
|
||||
instr_trace = []
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--log", type=str, help="Input spike simulation log")
|
||||
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
|
||||
args = parser.parse_args()
|
||||
# Process spike log
|
||||
process_spike_sim_log(args.log, args.csv)
|
||||
|
||||
def main():
|
||||
instr_trace = []
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--log", type=str, help="Input spike simulation log")
|
||||
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
|
||||
args = parser.parse_args()
|
||||
# Process spike log
|
||||
process_spike_sim_log(args.log, args.csv)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
12
vendor/google_riscv-dv/src/dv_defines.svh
vendored
12
vendor/google_riscv-dv/src/dv_defines.svh
vendored
|
@ -33,15 +33,15 @@
|
|||
`endif
|
||||
|
||||
`ifndef DV_CHECK
|
||||
`define DV_CHECK(T_, MSG_="", SEV_=error, ID_=`gfn) \
|
||||
if (!(T_)) begin \
|
||||
`define DV_CHECK(T_, MSG_="", SEV_=error, ID_=`gfn, WITH_C_=) \
|
||||
if (!(T_ WITH_C_)) begin \
|
||||
`uvm_``SEV_(ID_, $sformatf("Check failed (%s) %s ", `"T_`", MSG_)); \
|
||||
end
|
||||
`endif
|
||||
|
||||
`ifndef DV_CHECK_FATAL
|
||||
`define DV_CHECK_FATAL(T_, MSG_="", ID_=`gfn) \
|
||||
`DV_CHECK(T_, MSG_, fatal, ID_)
|
||||
`define DV_CHECK_FATAL(T_, MSG_="", ID_=`gfn, WITH_C_=) \
|
||||
`DV_CHECK(T_, MSG_, fatal, ID_, WITH_C_)
|
||||
`endif
|
||||
|
||||
// Shorthand for common foo.randomize() + fatal check
|
||||
|
@ -59,11 +59,11 @@
|
|||
// Shorthand for common foo.randomize() with { } + fatal check
|
||||
`ifndef DV_CHECK_RANDOMIZE_WITH_FATAL
|
||||
`define DV_CHECK_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_, MSG_="Randomization failed!", ID_=`gfn) \
|
||||
`DV_CHECK_FATAL(VAR_.randomize() with {WITH_C_}, MSG_, ID_)
|
||||
`DV_CHECK_FATAL(VAR_.randomize(), MSG_, ID_, with { WITH_C_ })
|
||||
`endif
|
||||
|
||||
// Shorthand for common std::randomize(foo) with { } + fatal check
|
||||
`ifndef DV_CHECK_STD_RANDOMIZE_WITH_FATAL
|
||||
`define DV_CHECK_STD_RANDOMIZE_WITH_FATAL(VAR_, WITH_C_,MSG_="Randomization failed!",ID_=`gfn) \
|
||||
`DV_CHECK_FATAL(std::randomize(VAR_) with {WITH_C_}, MSG_, ID_)
|
||||
`DV_CHECK_FATAL(std::randomize(VAR_), MSG_, ID_, with { WITH_C_ })
|
||||
`endif
|
||||
|
|
|
@ -330,7 +330,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
endfunction
|
||||
|
||||
// Setup MISA based on supported extensions
|
||||
virtual function setup_misa();
|
||||
virtual function void setup_misa();
|
||||
bit [XLEN-1:0] misa;
|
||||
misa[XLEN-1:XLEN-3] = (XLEN == 32) ? 1 :
|
||||
(XLEN == 64) ? 2 : 3;
|
||||
|
@ -829,6 +829,23 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
directed_instr_stream_ratio[name] = ratio;
|
||||
endfunction
|
||||
|
||||
virtual function void get_directed_instr_stream();
|
||||
string args, val;
|
||||
string opts[$];
|
||||
for (int i=0; i<cfg.max_directed_instr_stream_seq; i++) begin
|
||||
args = $sformatf("directed_instr_%0d=", i);
|
||||
if ($value$plusargs({args,"%0s"}, val)) begin
|
||||
uvm_split_string(val, ",", opts);
|
||||
if (opts.size() != 2) begin
|
||||
`uvm_fatal(`gfn, $sformatf(
|
||||
"Incorrect directed instruction format : %0s, expect: name,ratio", val))
|
||||
end else begin
|
||||
add_directed_instr_stream(opts[0], opts[1].atoi());
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
// Generate directed instruction stream based on the ratio setting
|
||||
virtual function void generate_directed_instr_stream(input string label,
|
||||
input int unsigned original_instr_cnt,
|
||||
|
@ -896,7 +913,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
|
||||
// Generate the program in the debug ROM
|
||||
// Processor will fetch instruction from here upon receiving debug request from debug module
|
||||
virtual function gen_debug_mode_section();
|
||||
virtual function void gen_debug_mode_section();
|
||||
string instr[];
|
||||
if (riscv_instr_pkg::support_debug_mode) begin
|
||||
instr = {"dret"};
|
||||
|
|
|
@ -137,6 +137,8 @@ class riscv_illegal_instr extends uvm_object;
|
|||
(opcode == 7'b1110011) -> (func3 == 3'b100);
|
||||
(opcode == 7'b0011011) -> (!(func3 inside {3'b000, 3'b001, 3'b101}));
|
||||
(opcode == 7'b0111011) -> (func3 inside {3'b010, 3'b011});
|
||||
opcode inside {7'b1100111, 7'b1100011, 7'b0000011, 7'b0100011,
|
||||
7'b0001111, 7'b1110011, 7'b0011011, 7'b0111011};
|
||||
} else {
|
||||
(opcode == 7'b1100111) -> (func3 == 3'b000);
|
||||
(opcode == 7'b1100011) -> (!(func3 inside {3'b010, 3'b011}));
|
||||
|
@ -182,7 +184,7 @@ class riscv_illegal_instr extends uvm_object;
|
|||
`uvm_object_utils(riscv_illegal_instr)
|
||||
`uvm_object_new
|
||||
|
||||
function init(riscv_instr_gen_config cfg);
|
||||
function void init(riscv_instr_gen_config cfg);
|
||||
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
|
||||
|
|
|
@ -395,7 +395,7 @@ class riscv_instr_base extends uvm_object;
|
|||
super.new(name);
|
||||
endfunction
|
||||
|
||||
// Convert the instrunction to one-liner print message
|
||||
// Convert the instruction to one-liner print message
|
||||
virtual function string convert2string();
|
||||
return convert2asm();
|
||||
endfunction
|
||||
|
|
|
@ -107,6 +107,8 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
int max_stack_len_per_program = 16 * (XLEN/8);
|
||||
// Maximum branch distance, avoid skipping large portion of the code
|
||||
int max_branch_step = 20;
|
||||
// Maximum directed instruction stream sequence count
|
||||
int max_directed_instr_stream_seq = 20;
|
||||
// Reserved registers
|
||||
// Default reserved registers, only used by special instructions
|
||||
riscv_reg_t default_reserved_regs[];
|
||||
|
|
|
@ -131,7 +131,7 @@ class riscv_instr_sequence extends uvm_sequence;
|
|||
virtual function void post_process_instr();
|
||||
int i;
|
||||
int label_idx;
|
||||
int branch_target[string];
|
||||
int branch_target[string] = '{default: 0};
|
||||
// Insert directed instructions, it's randomly mixed with the random instruction stream.
|
||||
foreach (directed_instr[i]) begin
|
||||
instr_stream.insert_instr_stream(directed_instr[i].instr_list);
|
||||
|
|
|
@ -104,7 +104,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object;
|
|||
// Take SV39 for example: (PTE_SIZE = 8B)
|
||||
// Table size is 4KB, PTE_SIZE=8B, entry count = 4K/8 = 512
|
||||
// Level 2: Root table, 2 entries, PTE[0] and PTE[1] is non-leaf PTE, PTE[2] is leaf PTE, all
|
||||
// other PTEs are invalid, totally 1 page table with 3 PTEs at this level.
|
||||
// other PTEs are invalid, totalling 1 page table with 3 PTEs at this level.
|
||||
// Level 1: Two page tables, map to PTE[0] and PTE[1] of the root table.
|
||||
// Each table has 512 entries, PTE[0], PTE[1] are non-leaf PTE, cover 4MB memory
|
||||
// space. PTE[2:511] are leaf PTE, cover 510 * 2MB memory space.
|
||||
|
@ -113,7 +113,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object;
|
|||
// In summary, 7(1+2+4) tables are needed for SV39.
|
||||
// Similarly, 3 (1+2) page tables for SV32, 15 (1 + 2 + 4 + 8) page tables for SV48.
|
||||
// Note:
|
||||
// - The number of randomization call is optmized to improve performance
|
||||
// - The number of randomization call is optimized to improve performance
|
||||
// - PPN assignment is done at program run time
|
||||
virtual function void randomize_page_table();
|
||||
int pte_index;
|
||||
|
@ -196,7 +196,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object;
|
|||
`DV_CHECK_RANDOMIZE_FATAL(exception_cfg)
|
||||
`DV_CHECK_RANDOMIZE_WITH_FATAL(illegal_pte,
|
||||
!(xwr inside {NEXT_LEVEL_PAGE, R_W_EXECUTE_PAGE});)
|
||||
// Wrong privielge mode setting
|
||||
// Wrong privilege mode setting
|
||||
if(exception_cfg.allow_privileged_mode_exception) begin
|
||||
pte.u = ~pte.u;
|
||||
end
|
||||
|
|
|
@ -91,7 +91,8 @@ class riscv_rand_instr extends riscv_instr_base;
|
|||
}
|
||||
|
||||
constraint csr_instr_c {
|
||||
if(cfg.no_csr_instr == 1) {
|
||||
// TODO: support CSR instruction in other modes
|
||||
if(cfg.no_csr_instr || (cfg.init_privileged_mode != MACHINE_MODE)) {
|
||||
category != CSR;
|
||||
} else {
|
||||
if (cfg.enable_illegal_csr_instruction) {
|
||||
|
|
86
vendor/google_riscv-dv/yaml/csr_template.yaml
vendored
Normal file
86
vendor/google_riscv-dv/yaml/csr_template.yaml
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
# 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.
|
||||
#
|
||||
#
|
||||
# Base CSR template that should be followed when describing all processor supported CSRs to enable correct generation of directed test sequences
|
||||
#- csr: CSR_NAME
|
||||
# description: >
|
||||
# BRIEF_DESCRIPTION
|
||||
# privilege_mode: MODE (D/M/S/H/U)
|
||||
# rv32:
|
||||
# - MSB_FIELD_NAME:
|
||||
# - description: >
|
||||
# BRIEF_DESCRIPTION
|
||||
# - type: TYPE (WPRI/WLRL/WARL)
|
||||
# - reset_val: RESET_VAL
|
||||
# - msb: MSB_POS
|
||||
# - lsb: LSB_POS
|
||||
# - ...
|
||||
# - ...
|
||||
# - LSB_FIELD_NAME:
|
||||
# - description: ...
|
||||
# - type: ...
|
||||
# - ...
|
||||
# rv64:
|
||||
# - MSB_FIELD_NAME:
|
||||
# - description: >
|
||||
# BRIEF_DESCRIPTION
|
||||
# - type: TYPE (WPRI/WLRL/WARL)
|
||||
# - reset_val: RESET_VAL
|
||||
# - msb: MSB_POS
|
||||
# - lsb: LSB_POS
|
||||
# - ...
|
||||
# - ...
|
||||
# - LSB_FIELD_NAME:
|
||||
# - description: ...
|
||||
# - type: ...
|
||||
# - ...
|
||||
|
||||
|
||||
# Example template, using the CSR misa
|
||||
# Note: assume the processor supports only the RISC-V I/C extensions
|
||||
- csr: misa
|
||||
description: >
|
||||
Machine ISA Register
|
||||
privilege_mode: M
|
||||
rv32:
|
||||
- field_name: MXL
|
||||
description: >
|
||||
Encodes native base ISA width
|
||||
type: WARL
|
||||
reset_val: 1
|
||||
msb: 31
|
||||
lsb: 30
|
||||
- field_name: Extensions
|
||||
description: >
|
||||
Encodes all supported ISA extensions
|
||||
type: WARL
|
||||
reset_val: 0x104
|
||||
msb: 25
|
||||
lsb: 0
|
||||
rv64:
|
||||
- field_name: MXL
|
||||
description: >
|
||||
Encodes native base ISA width
|
||||
type: WARL
|
||||
reset_val: 2
|
||||
msb: 63
|
||||
lsb: 62
|
||||
- field_name: Extensions
|
||||
description: >
|
||||
Encodes all supported ISA extensions
|
||||
type: WARL
|
||||
reset_val: 0x104
|
||||
msb: 25
|
||||
lsb: 0
|
28
vendor/google_riscv-dv/yaml/iss.yaml
vendored
Normal file
28
vendor/google_riscv-dv/yaml/iss.yaml
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
# 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.
|
||||
|
||||
- iss: spike
|
||||
path_var: SPIKE_PATH
|
||||
cmd: >
|
||||
<path_var>/spike --isa=<variant> -l <elf>
|
||||
|
||||
- iss: ovpsim
|
||||
path_var: OVPSIM_PATH
|
||||
cmd: >
|
||||
<path_var>/riscvOVPsim.exe
|
||||
--variant <variant>
|
||||
--override riscvOVPsim/cpu/PMP_registers=0
|
||||
--override riscvOVPsim/cpu/simulateexceptions=T
|
||||
--trace --tracechange --traceshowicount --program <elf>
|
||||
--finishafter 500000
|
50
vendor/google_riscv-dv/yaml/simulator.yaml
vendored
Normal file
50
vendor/google_riscv-dv/yaml/simulator.yaml
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
# 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.
|
||||
|
||||
- tool: vcs
|
||||
compile_cmd:
|
||||
- "vcs -file <cwd>/vcs.compile.option.f
|
||||
-f <cwd>/files.f -full64
|
||||
-l <out>/compile.log
|
||||
-Mdir=<out>/vcs_simv.csrc
|
||||
-o <out>/vcs_simv <cmp_opts>"
|
||||
sim_cmd: >
|
||||
<out>/vcs_simv +vcs+lic+wait <sim_opts> +ntb_random_seed=<seed>
|
||||
|
||||
- tool: ius
|
||||
compile_cmd:
|
||||
- "irun -64bit -access +rwc -f <cwd>/files.f
|
||||
-q -sv -uvm -vlog_ext +.vh -I.
|
||||
-uvmhome CDNS-1.2
|
||||
-elaborate
|
||||
-l <out>/compile.log <cmp_opts>"
|
||||
sim_cmd: >
|
||||
irun -R <sim_opts> -svseed <seed>
|
||||
|
||||
- tool: questa
|
||||
compile_cmd:
|
||||
- "vmap mtiUvm $QUESTA_HOME/questasim/uvm-1.2"
|
||||
- "vlog -64
|
||||
 -access=rwc
|
||||
 -f <cwd>/files.f
|
||||
 -sv
|
||||
 -mfcu -cuname design_cuname
|
||||
 +define+UVM_REGEX_NO_DPI
|
||||
 -writetoplevels <out>/top.list
|
||||
 -l <out>/compile.log <cmp_opts>"
|
||||
- "vopt -64 -debug
|
||||
 +designfile -f <out>/top.list
|
||||
 -o design_opt"
|
||||
sim_cmd: >
|
||||
vsim -64 -c -do <cwd>/questa_sim.tcl design_opt <sim_opts> -svseed <seed>
|
207
vendor/google_riscv-dv/yaml/testlist.yaml
vendored
Normal file
207
vendor/google_riscv-dv/yaml/testlist.yaml
vendored
Normal file
|
@ -0,0 +1,207 @@
|
|||
# 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
|
||||
# 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
|
||||
# compare_opts : Options for the RTL & ISS trace comparison
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
- test: riscv_arithmetic_basic_test
|
||||
description: >
|
||||
Arithmetic instruction test, no load/store/branch instructions
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=0
|
||||
+no_fence=1
|
||||
+no_data_page=1'b1
|
||||
+no_branch_jump=1'b1
|
||||
+boot_mode=m
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_machine_mode_rand_test
|
||||
description: >
|
||||
Machine mode random instruction test
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=5
|
||||
+boot_mode=m
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_privileged_mode_rand_test
|
||||
description: >
|
||||
Random previliged mode test
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=5
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_rand_instr_test
|
||||
description: >
|
||||
Random instruction stress test
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=5
|
||||
+directed_instr_0=riscv_load_store_rand_instr_stream,4
|
||||
+directed_instr_1=riscv_loop_instr,4
|
||||
+directed_instr_2=riscv_hazard_instr_stream,4
|
||||
+directed_instr_3=riscv_load_store_hazard_instr_stream,4
|
||||
+directed_instr_4=riscv_cache_line_stress_instr_stream,4
|
||||
+directed_instr_5=riscv_multi_page_load_store_instr_stream,4
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_rand_jump_test
|
||||
description: >
|
||||
Jump among large number of sub-programs, stress testing iTLB operations.
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
gen_opts: >
|
||||
+instr_cnt=15000
|
||||
+num_of_sub_program=20
|
||||
+directed_instr_0=riscv_load_store_rand_instr_stream,8
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_mmu_stress_test
|
||||
description: >
|
||||
Test with different patterns of load/store instructions, stress test MMU
|
||||
operations.
|
||||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+num_of_sub_program=5
|
||||
+directed_instr_0=riscv_load_store_rand_instr_stream,40
|
||||
+directed_instr_1=riscv_load_store_hazard_instr_stream,40
|
||||
+directed_instr_2=riscv_cache_line_stress_instr_stream,40
|
||||
+directed_instr_3=riscv_multi_page_load_store_instr_stream,40
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_page_table_exception_test
|
||||
description: >
|
||||
Test random page table exception handling. An exception handling routine is
|
||||
designed to fix the page table error and resume execution.
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+enable_page_table_exception=1
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_no_fence_test
|
||||
description: >
|
||||
Random instruction with FENCE disabled, used to test processor pipeline with
|
||||
less stall/flush operations caused by FENCE instruction.
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+no_fence=1
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_sfence_exception_test
|
||||
description: >
|
||||
Random instruction test with S.FENCE exceptions
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+allow_sfence_exception=1
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_illegal_instr_test
|
||||
description: >
|
||||
Illegal instruction test, verify the processor can detect illegal
|
||||
instruction and handle corresponding exception properly. An exception
|
||||
handling routine is designed to resume execution after illegal
|
||||
instruction exception.
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+enable_illegal_instruction=1
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_hint_instr_test
|
||||
description: >
|
||||
HINT instruction test, verify the processor can detect HINT instruction
|
||||
treat it as NOP. No illegal instruction exception is expected
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+enable_hint_instruction=1
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_ebreak_test
|
||||
description: >
|
||||
Random instruction test with ebreak instruction enabled. Debug mode is not
|
||||
enabled for this test, processor should raise ebreak exception.
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+instr_cnt=6000
|
||||
+no_ebreak=0
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_ebreak_debug_mode_test
|
||||
description: >
|
||||
Ebreak instruction test with debug mode enabled.
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+instr_cnt=6000
|
||||
+no_ebreak=0
|
||||
rtl_test: core_base_test
|
||||
sim_opts: >
|
||||
+enable_debug_seq=1
|
||||
compare_opts: >
|
||||
+compare_final_value_only=1
|
||||
|
||||
- test: riscv_fast_interrupt_test
|
||||
description: >
|
||||
WFI(wait for interrupt) instruction test. If WFI is supported, processor
|
||||
should halt execution upon decoding WFI instruction and resume execution
|
||||
by interrupt. Otherwise WFI should be executed as NOP instruction.
|
||||
Interrupt handling routine is skipped to allow instruction strace comparison
|
||||
with ISS which is not interrupted during execution.
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+skip_trap_handling=1
|
||||
+no_wfi=0
|
||||
rtl_test: core_base_test
|
||||
sim_opts: >
|
||||
+enable_irq_seq=1
|
||||
|
||||
- test: riscv_full_interrupt_test
|
||||
description: >
|
||||
Random instruction test with complete interrupt handling
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
rtl_test: core_base_test
|
||||
sim_opts: >
|
||||
+enable_irq_seq=1
|
||||
compare_opts: >
|
||||
+compare_final_value_only=1
|
Loading…
Add table
Add a link
Reference in a new issue