mirror of
https://github.com/lowRISC/ibex.git
synced 2025-04-20 03:47:15 -04:00
Update google_riscv-dv to google/riscv-dv@7cce16c (#246)
Update code from upstream repository https://github.com/google/riscv- dv to revision 7cce16c0a212c8713a82516fbf8f2570d3dc4505 * Update spike log processing script to include full trace information (Tao Liu) * Add new tests (Tao Liu) * Add basic debug test functionality (Udi) * fix spelling error, fix output directory arg (Udi) * Add shorten option (dang hai) * Support SAIL-RISCV ISSi, update README (Tao Liu) * Fix CSR map copy issue (Tao Liu)
This commit is contained in:
parent
e1a7dcf37f
commit
6ccd2b698d
15 changed files with 434 additions and 170 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: 63fa0ca922ecf10f3cd733d15a0a79a7937a591e
|
||||
rev: 7cce16c0a212c8713a82516fbf8f2570d3dc4505
|
||||
}
|
||||
}
|
||||
|
|
152
vendor/google_riscv-dv/README.md
vendored
152
vendor/google_riscv-dv/README.md
vendored
|
@ -100,89 +100,23 @@ python3 run.py --test riscv_page_table_exception_test --co
|
|||
### Privileged CSR Test Generation
|
||||
|
||||
|
||||
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). The CSR test code that this script generates will execute every CSR instruction on every processor implemented CSR, writing values to the CSR and then using a prediction function to calculate a reference value that will be written into another GPR. The reference value will then be compared to the value actually stored in the CSR to determine whether to jump to the failure condition or continue executing, allowing it to be completely self checking.
|
||||
To quickly generate a basic CSR test, run the below command:
|
||||
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).
|
||||
The CSR test code that this script generates will execute every CSR instruction
|
||||
on every processor implemented CSR, writing values to the CSR and then using a
|
||||
prediction function to calculate a reference value that will be written into
|
||||
another GPR. The reference value will then be compared to the value actually
|
||||
stored in the CSR to determine whether to jump to the failure condition or
|
||||
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:
|
||||
|
||||
```
|
||||
python3 scripts/gen_csr_test.py
|
||||
python3 scripts/gen_csr_test.py --help
|
||||
```
|
||||
|
||||
To create a new processor-specific CSR description YAML file, format it as
|
||||
detailed below, and then run:
|
||||
```
|
||||
python3 scripts/gen_csr_test.py --csr_file PATH_TO_NEW_CSR_DESCRIPTION_FILE
|
||||
```
|
||||
|
||||
If the CSRs are a different XLEN, such as 64-bit or 128-bit, use the `--xlen`
|
||||
option to change the ISA length used to generate the test.
|
||||
```
|
||||
python3 scripts/gen_csr_test.py --xlen 64
|
||||
```
|
||||
|
||||
To input the number of CSR test files that should be generated, use the
|
||||
`--iterations` option. Say 10 tests should be generated:
|
||||
```
|
||||
python3 scripts/gen_csr_test.py --iterations 10
|
||||
```
|
||||
|
||||
To change the output directory that the tests are generated into, use the
|
||||
`--out` option. Say the tests should be generated into the home directory:
|
||||
```
|
||||
python3 scripts/gen_csr_test.py --out ~
|
||||
```
|
||||
|
||||
Any number of the above options can be combined together, and all of them have
|
||||
default values should they not be specified at runtime.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Setup CSR description list
|
||||
|
||||
This YAML description file of all CSRs is only required for the privileged CSR
|
||||
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)
|
||||
|
||||
```
|
||||
- csr: CSR_NAME
|
||||
description: >
|
||||
BRIEF_DESCRIPTION
|
||||
address: 0x###
|
||||
privilege_mode: MODE (D/M/S/H/U)
|
||||
rv32:
|
||||
- MSB_FIELD_NAME:
|
||||
- description: >
|
||||
BRIEF_DESCRIPTION
|
||||
- type: TYPE (WPRI/WLRL/WARL/R)
|
||||
- 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/R)
|
||||
- reset_val: RESET_VAL
|
||||
- msb: MSB_POS
|
||||
- lsb: LSB_POS
|
||||
- ...
|
||||
- ...
|
||||
- LSB_FIELD_NAME:
|
||||
- description: ...
|
||||
- type: ...
|
||||
- ...
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
### Setup regression test list
|
||||
|
||||
[Test list in YAML format](https://github.com/google/riscv-dv/blob/master/yaml/testlist.yaml)
|
||||
|
@ -269,6 +203,56 @@ riscv_instr_group_t supported_isa[] = {RV32I, RV32M, RV64I, RV64M};
|
|||
| 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 |
|
||||
| empty_debug_section | Disables randomized debug_rom section | 0 |
|
||||
|
||||
|
||||
### Setup Privileged CSR description
|
||||
|
||||
This YAML description file of all CSRs is only required for the privileged CSR
|
||||
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)
|
||||
|
||||
```
|
||||
- csr: CSR_NAME
|
||||
description: >
|
||||
BRIEF_DESCRIPTION
|
||||
address: 0x###
|
||||
privilege_mode: MODE (D/M/S/H/U)
|
||||
rv32:
|
||||
- MSB_FIELD_NAME:
|
||||
- description: >
|
||||
BRIEF_DESCRIPTION
|
||||
- type: TYPE (WPRI/WLRL/WARL/R)
|
||||
- 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/R)
|
||||
- reset_val: RESET_VAL
|
||||
- msb: MSB_POS
|
||||
- lsb: LSB_POS
|
||||
- ...
|
||||
- ...
|
||||
- LSB_FIELD_NAME:
|
||||
- description: ...
|
||||
- type: ...
|
||||
- ...
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
|
||||
### Adding new instruction stream and test
|
||||
|
||||
|
@ -290,17 +274,19 @@ it with random instructions
|
|||
|
||||
## 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).
|
||||
Currently three ISS are supported, the default ISS is spike. You can install any
|
||||
one of below to run ISS simulation.
|
||||
|
||||
- spike setup
|
||||
- [spike](https://github.com/riscv/riscv-isa-sim#) 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
|
||||
|
||||
- [sail-riscv](https://github.com/rems-project/sail-riscv) setup
|
||||
- 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
|
||||
|
||||
You can use -iss to run with different ISS.
|
||||
|
||||
|
@ -310,6 +296,9 @@ 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
|
||||
|
||||
// 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
|
||||
|
@ -327,6 +316,7 @@ real RISC-V processor.
|
|||
|
||||
```
|
||||
python3 run.py --test=riscv_rand_instr_test --iss=spike,ovpsim
|
||||
python3 run.py --test=riscv_rand_instr_test --iss=spike,sail
|
||||
```
|
||||
|
||||
### Integrate a new ISS
|
||||
|
|
72
vendor/google_riscv-dv/run.py
vendored
72
vendor/google_riscv-dv/run.py
vendored
|
@ -27,6 +27,7 @@ from datetime import date
|
|||
from scripts.lib import *
|
||||
from scripts.spike_log_to_trace_csv import *
|
||||
from scripts.ovpsim_log_to_trace_csv import *
|
||||
from scripts.sail_log_to_trace_csv import *
|
||||
from scripts.instr_trace_compare import *
|
||||
|
||||
LOGGER = logging.getLogger()
|
||||
|
@ -170,6 +171,8 @@ def gen(test_list, csr_file, end_signature_addr, isa, simulator,
|
|||
cmd = re.sub("<seed>", str(rand_seed), cmd)
|
||||
if "gen_opts" in test:
|
||||
cmd += test['gen_opts']
|
||||
if not re.search("c", isa):
|
||||
cmd += "+disable_comparessed_instr=1";
|
||||
logging.info("Generating %d %s" % (iterations, test['test']))
|
||||
if lsf_cmd:
|
||||
cmd_list.append(cmd)
|
||||
|
@ -195,11 +198,19 @@ def gcc_compile(test_list, output_dir, isa, mabi, opts):
|
|||
elf = prefix + ".o"
|
||||
binary = prefix + ".bin"
|
||||
# gcc comilation
|
||||
cmd = ("%s -march=%s -mabi=%s -static -mcmodel=medany \
|
||||
cmd = ("%s -static -mcmodel=medany \
|
||||
-fvisibility=hidden -nostdlib \
|
||||
-nostartfiles %s \
|
||||
-Tscripts/link.ld %s -o %s" % \
|
||||
(get_env_var("RISCV_GCC") ,isa, mabi, asm, opts, elf))
|
||||
-Tscripts/link.ld %s -o %s " % \
|
||||
(get_env_var("RISCV_GCC"), asm, opts, elf))
|
||||
if 'gcc_opts' in test:
|
||||
cmd += test['gcc_opts']
|
||||
# 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)
|
||||
if not re.search('mabi', cmd):
|
||||
cmd += (" -mabi=%s" % mabi)
|
||||
logging.info("Compiling %s" % asm)
|
||||
logging.debug(cmd)
|
||||
output = subprocess.check_output(cmd.split())
|
||||
|
@ -270,6 +281,8 @@ def iss_cmp(test_list, iss, output_dir, isa):
|
|||
process_spike_sim_log(log, csv)
|
||||
elif iss == "ovpsim":
|
||||
process_ovpsim_sim_log(log, csv)
|
||||
elif iss == "sail":
|
||||
process_sail_sim_log(log, csv)
|
||||
else:
|
||||
logging.error("Unsupported ISS" % iss)
|
||||
sys.exit(1)
|
||||
|
@ -290,32 +303,20 @@ def setup_parser():
|
|||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument("--o", type=str,
|
||||
help="Output directory name")
|
||||
parser.add_argument("--testlist", type=str, default="",
|
||||
help="Regression testlist")
|
||||
parser.add_argument("--csr_yaml", type=str, default="",
|
||||
help="CSR description file")
|
||||
parser.add_argument("--end_signature_addr", type=str, default="0",
|
||||
help="Address that privileged CSR test writes to at EOT")
|
||||
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("-o", "--output", type=str,
|
||||
help="Output directory name", dest="o")
|
||||
parser.add_argument("-tl", "--testlist", type=str, default="",
|
||||
help="Regression testlist", dest="testlist")
|
||||
parser.add_argument("-tn", "--test", type=str, default="all",
|
||||
help="Test name, 'all' means all tests in the list", dest="test")
|
||||
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("-i", "--iterations", type=int, default=0,
|
||||
help="Override the iteration count in the test list", dest="iterations")
|
||||
parser.add_argument("-si", "--simulator", type=str, default="vcs",
|
||||
help="Simulator used to run the generator, default VCS", dest="simulator")
|
||||
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")
|
||||
help="RISC-V instruction set simulator: spike,ovpsim,sail")
|
||||
parser.add_argument("-v", "--verbose", dest="verbose", action="store_true",
|
||||
help="Verbose logging")
|
||||
parser.add_argument("--co", dest="co", action="store_true",
|
||||
|
@ -328,15 +329,27 @@ def setup_parser():
|
|||
help="Simulation options for the generator")
|
||||
parser.add_argument("--gcc_opts", type=str, default="",
|
||||
help="GCC compile options")
|
||||
parser.add_argument("--steps", type=str, default="all",
|
||||
help="Run steps: gen,gcc_compile,iss_sim,iss_cmp")
|
||||
parser.add_argument("-s", "--steps", type=str, default="all",
|
||||
help="Run steps: gen,gcc_compile,iss_sim,iss_cmp", dest="steps")
|
||||
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="rv64imc",
|
||||
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("--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=50,
|
||||
help="ISS sim timeout limit in seconds")
|
||||
parser.add_argument("--iss_yaml", type=str, default="",
|
||||
help="ISS setting YAML")
|
||||
parser.add_argument("--simulator_yaml", type=str, default="",
|
||||
help="RTL simulator setting YAML")
|
||||
parser.add_argument("--csr_yaml", type=str, default="",
|
||||
help="CSR description file")
|
||||
|
||||
parser.set_defaults(co=False)
|
||||
parser.set_defaults(so=False)
|
||||
|
@ -369,6 +382,9 @@ def main():
|
|||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
setup_logging(args.verbose)
|
||||
|
||||
if not args.csr_yaml:
|
||||
args.csr_yaml = cwd + "/yaml/csr_template.yaml"
|
||||
|
||||
if not args.iss_yaml:
|
||||
args.iss_yaml = cwd + "/yaml/iss.yaml"
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import sys
|
|||
import yaml
|
||||
import argparse
|
||||
import random
|
||||
import copy
|
||||
|
||||
try:
|
||||
from bitstring import BitArray as bitarray
|
||||
|
@ -249,14 +250,14 @@ def gen_csr_test_pass(test_file, end_addr):
|
|||
test_file.write(f"\tj csr_pass\n")
|
||||
|
||||
|
||||
def gen_csr_instr(csr_map, csr_instructions, xlen,
|
||||
def gen_csr_instr(original_csr_map, csr_instructions, xlen,
|
||||
iterations, out, end_signature_addr):
|
||||
"""
|
||||
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()
|
||||
original_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.
|
||||
|
@ -270,6 +271,7 @@ def gen_csr_instr(csr_map, csr_instructions, xlen,
|
|||
for i in range(iterations):
|
||||
# pick two GPRs at random to act as source and destination registers
|
||||
# for CSR operations
|
||||
csr_map = copy.deepcopy(original_csr_map)
|
||||
source_reg, dest_reg = [f"x{i}" for i in random.sample(range(1, 16), 2)]
|
||||
csr_list = list(csr_map.keys())
|
||||
with open(f"{out}/riscv_csr_test.{i}.S", "w") as csr_test_file:
|
||||
|
|
|
@ -32,6 +32,10 @@ def compare_trace_csv(csv1, csv2, name1, name2, log,
|
|||
matched_cnt = 0
|
||||
mismatch_cnt = 0
|
||||
|
||||
# ensure that in order mode is disabled if necessary
|
||||
if compare_final_value_only:
|
||||
in_order_mode = 0
|
||||
|
||||
if log:
|
||||
fd = open(log, 'a+')
|
||||
else:
|
||||
|
@ -56,6 +60,8 @@ def compare_trace_csv(csv1, csv2, name1, name2, log,
|
|||
gpr_val_2 = {}
|
||||
for trace in instr_trace_1:
|
||||
trace_1_index += 1
|
||||
if trace.rd == "":
|
||||
continue
|
||||
# Check if there's a GPR change caused by this instruction
|
||||
gpr_state_change_1 = check_update_gpr(trace.rd, trace.rd_val, gpr_val_1)
|
||||
if gpr_state_change_1 == 0:
|
||||
|
@ -63,10 +69,11 @@ def compare_trace_csv(csv1, csv2, name1, name2, log,
|
|||
# Move forward the other trace until a GPR update happens
|
||||
gpr_state_change_2 = 0
|
||||
while (gpr_state_change_2 == 0 and trace_2_index < len(instr_trace_2)):
|
||||
gpr_state_change_2 = check_update_gpr(
|
||||
instr_trace_2[trace_2_index].rd,
|
||||
instr_trace_2[trace_2_index].rd_val,
|
||||
gpr_val_2)
|
||||
if instr_trace_2[trace_2_index].rd != "":
|
||||
gpr_state_change_2 = check_update_gpr(
|
||||
instr_trace_2[trace_2_index].rd,
|
||||
instr_trace_2[trace_2_index].rd_val,
|
||||
gpr_val_2)
|
||||
trace_2_index += 1
|
||||
# Check if the GPR update is the same between trace 1 and 2
|
||||
if gpr_state_change_2 == 0:
|
||||
|
@ -131,8 +138,8 @@ def compare_trace_csv(csv1, csv2, name1, name2, log,
|
|||
for trace_1_index in range(0, len(gpr_trace_1[gpr])-1):
|
||||
if (trace_2_index == len(gpr_trace_2[gpr])):
|
||||
break
|
||||
if long(gpr_trace_1[gpr][trace_1_index].rd_val, 16) != \
|
||||
long(gpr_trace_2[gpr][trace_2_index].rd_val, 16):
|
||||
if int(gpr_trace_1[gpr][trace_1_index].rd_val, 16) != \
|
||||
int(gpr_trace_2[gpr][trace_2_index].rd_val, 16):
|
||||
if coalesced_updates >= coalescing_limit:
|
||||
coalesced_updates = 0
|
||||
mismatch_cnt += 1
|
||||
|
@ -163,8 +170,8 @@ def compare_trace_csv(csv1, csv2, name1, name2, log,
|
|||
mismatch_cnt += 1
|
||||
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):
|
||||
elif int(gpr_trace_1[gpr][-1].rd_val, 16) != \
|
||||
int(gpr_trace_2[gpr][-1].rd_val, 16):
|
||||
mismatch_cnt += 1
|
||||
if mismatch_cnt <= mismatch_print_limit:
|
||||
fd.write("Mismatch final value:\n")
|
||||
|
@ -183,12 +190,13 @@ def compare_trace_csv(csv1, csv2, name1, name2, log,
|
|||
def parse_gpr_update_from_trace(trace_csv, gpr_trace):
|
||||
prev_val = {}
|
||||
for trace in trace_csv:
|
||||
if not (trace.rd in prev_val):
|
||||
gpr_trace[trace.rd] = []
|
||||
gpr_trace[trace.rd].append(trace)
|
||||
elif prev_val[trace.rd] != trace.rd_val:
|
||||
gpr_trace[trace.rd].append(trace)
|
||||
prev_val[trace.rd] = trace.rd_val
|
||||
if trace.rd != "":
|
||||
if not (trace.rd in prev_val):
|
||||
gpr_trace[trace.rd] = []
|
||||
gpr_trace[trace.rd].append(trace)
|
||||
elif prev_val[trace.rd] != trace.rd_val:
|
||||
gpr_trace[trace.rd].append(trace)
|
||||
prev_val[trace.rd] = trace.rd_val
|
||||
|
||||
|
||||
def check_update_gpr(rd, rd_val, gpr):
|
||||
|
@ -206,10 +214,10 @@ def check_update_gpr(rd, rd_val, 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")
|
||||
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")
|
||||
|
@ -228,9 +236,6 @@ def main():
|
|||
|
||||
args = parser.parse_args()
|
||||
|
||||
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.log,
|
||||
|
|
|
@ -32,6 +32,7 @@ class RiscvInstructiontTraceEntry(object):
|
|||
self.addr = ""
|
||||
self.binary = ""
|
||||
self.instr_str = ""
|
||||
self.instr = ""
|
||||
self.privileged_mode = ""
|
||||
|
||||
def get_trace_string(self):
|
||||
|
@ -47,6 +48,7 @@ class RiscvInstructiontTraceCsv(object):
|
|||
|
||||
def __init__(self, csv_fd):
|
||||
self.csv_fd = csv_fd
|
||||
self.gpr = {}
|
||||
|
||||
|
||||
def start_new_trace(self):
|
||||
|
@ -72,11 +74,19 @@ class RiscvInstructiontTraceCsv(object):
|
|||
|
||||
def write_trace_entry(self, entry):
|
||||
"""Write a new trace entry to CSV"""
|
||||
self.csv_writer.writerow({'str' : entry.instr_str,
|
||||
'rd' : entry.rd,
|
||||
'rd_val' : entry.rd_val,
|
||||
'binary' : entry.binary,
|
||||
'addr' : entry.addr})
|
||||
self.gpr[entry.rd] = entry.rd_val
|
||||
self.csv_writer.writerow({'str' : entry.instr_str,
|
||||
'rd' : entry.rd,
|
||||
'rd_val' : entry.rd_val,
|
||||
'rs1' : entry.rs1,
|
||||
'rs1_val' : entry.rs1_val,
|
||||
'rs2' : entry.rs2,
|
||||
'rs2_val' : entry.rs2_val,
|
||||
'addr' : entry.addr,
|
||||
'instr' : entry.instr,
|
||||
'imm' : entry.imm,
|
||||
'binary' : entry.binary,
|
||||
'addr' : entry.addr})
|
||||
|
||||
|
||||
def gpr_to_abi(gpr):
|
||||
|
|
97
vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py
vendored
Normal file
97
vendor/google_riscv-dv/scripts/sail_log_to_trace_csv.py
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
"""
|
||||
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.
|
||||
|
||||
Convert sail sim log to standard riscv instruction trace format
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import logging
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
from riscv_trace_csv import *
|
||||
|
||||
START_RE = re.compile(r"\[4\] \[M\]: 0x.*00001010")
|
||||
END_RE = re.compile(r"ecall")
|
||||
INSTR_RE = re.compile(r"\[[0-9].*\] \[(?P<pri>.)\]: 0x(?P<addr>[A-F0-9]+?)"
|
||||
" \(0x(?P<bin>[A-F0-9]+?)\) (?P<instr>.+?$)")
|
||||
RD_RE = re.compile(r"x(?P<reg>[0-9]+?) <- 0x(?P<val>[A-F0-9]*)")
|
||||
|
||||
def process_sail_sim_log(sail_log, csv):
|
||||
"""Process SAIL RISCV simulation log.
|
||||
|
||||
Extract instruction and affected register information from sail simulation
|
||||
log and save to a list.
|
||||
"""
|
||||
logging.info("Processing sail log : %s" % sail_log)
|
||||
instr_cnt = 0
|
||||
sail_instr = ""
|
||||
|
||||
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.start_new_trace()
|
||||
instr = None
|
||||
for line in f:
|
||||
# Extract instruction infromation
|
||||
m = START_RE.search(line)
|
||||
if m:
|
||||
search_start = 1
|
||||
continue
|
||||
m = END_RE.search(line)
|
||||
if m:
|
||||
break
|
||||
if search_start:
|
||||
instr = INSTR_RE.search(line)
|
||||
if instr:
|
||||
instr_start = 1
|
||||
pri = instr.group("pri")
|
||||
addr = instr.group("addr").lower()
|
||||
binary = instr.group("bin").lower()
|
||||
instr_str = instr.group("instr")
|
||||
continue
|
||||
if instr_start:
|
||||
m = RD_RE.search(line)
|
||||
if m:
|
||||
# Write the extracted instruction to a csvcol buffer file
|
||||
instr_cnt += 1
|
||||
rv_instr_trace = RiscvInstructiontTraceEntry()
|
||||
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
|
||||
rv_instr_trace.addr = addr
|
||||
rv_instr_trace.binary = binary
|
||||
rv_instr_trace.instr_str = instr_str
|
||||
trace_csv.write_trace_entry(rv_instr_trace)
|
||||
instr_start = 0
|
||||
logging.info("Processed instruction count : %d" % instr_cnt)
|
||||
|
||||
|
||||
def main():
|
||||
instr_trace = []
|
||||
# Parse input arguments
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--log", type=str, help="Input sail simulation log")
|
||||
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
|
||||
args = parser.parse_args()
|
||||
# Process sail log
|
||||
process_sail_sim_log(args.log, args.csv)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -36,6 +36,13 @@ def process_spike_sim_log(spike_log, csv):
|
|||
instr_cnt = 0
|
||||
spike_instr = ""
|
||||
|
||||
RD_RE = re.compile(r"(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
|
||||
"\((?P<bin>.*?)\) x\s*(?P<reg>\d*?) 0x(?P<val>.*)")
|
||||
CORE_RE = re.compile(r"core.*0x(?P<addr>[a-f0-9]+?) \(0x(?P<bin>.*?)\) (?P<instr>.*?)$")
|
||||
INSTR_RE = re.compile(r"(?P<instr>[a-z\.]+?)(\s+?)(?P<operand>.*)")
|
||||
GPR_RE = re.compile(r"^[a-z][0-9a-z]$")
|
||||
CSR_RE = re.compile(r"csr")
|
||||
|
||||
# Remove all the init spike boot instructions
|
||||
cmd = ("sed -i '/core.*0x0000000000001010/,$!d' %s" % spike_log)
|
||||
os.system(cmd)
|
||||
|
@ -43,28 +50,58 @@ def process_spike_sim_log(spike_log, csv):
|
|||
cmd = ("sed -i '/ecall/q' %s" % spike_log)
|
||||
os.system(cmd)
|
||||
|
||||
gpr = {}
|
||||
gpr["zero"] = 0
|
||||
|
||||
with open(spike_log, "r") as f, open(csv, "w") as csv_fd:
|
||||
trace_csv = RiscvInstructiontTraceCsv(csv_fd)
|
||||
trace_csv.start_new_trace()
|
||||
for line in f:
|
||||
# Extract instruction infromation
|
||||
m = re.search(r"core(.*)\) (.*)", line)
|
||||
m = CORE_RE.search(line)
|
||||
if m:
|
||||
spike_instr = m.group(2)
|
||||
else:
|
||||
# Extract register value information
|
||||
m = re.search(r"(?P<pri>\d) 0x(?P<addr>[a-f0-9]+?) " \
|
||||
"\((?P<bin>.*?)\) x\s*(?P<reg>\d*?) 0x(?P<val>.*)", line)
|
||||
if m:
|
||||
# Write the extracted instruction to a csvcol buffer file
|
||||
instr_cnt += 1
|
||||
rv_instr_trace = RiscvInstructiontTraceEntry()
|
||||
rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("reg"))
|
||||
rv_instr_trace.rd_val = m.group("val")
|
||||
rv_instr_trace.privileged_mode = m.group("pri")
|
||||
rv_instr_trace.addr = m.group("addr")
|
||||
rv_instr_trace.binary = m.group("bin")
|
||||
rv_instr_trace.instr_str = spike_instr
|
||||
spike_instr = m.group("instr")
|
||||
rv_instr_trace = RiscvInstructiontTraceEntry()
|
||||
rv_instr_trace.instr_str = spike_instr
|
||||
rv_instr_trace.addr = m.group("addr")
|
||||
rv_instr_trace.binary = m.group("bin")
|
||||
nextline = f.readline()
|
||||
if nextline != "":
|
||||
m = RD_RE.search(nextline)
|
||||
if m:
|
||||
# Extract RD information
|
||||
instr_cnt += 1
|
||||
rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("reg"))
|
||||
rv_instr_trace.rd_val = m.group("val")
|
||||
rv_instr_trace.privileged_mode = m.group("pri")
|
||||
gpr[rv_instr_trace.rd] = rv_instr_trace.rd_val
|
||||
s = INSTR_RE.search(spike_instr)
|
||||
if s:
|
||||
rv_instr_trace.instr = s.group("instr")
|
||||
operand_str = s.group("operand").replace(" ", "")
|
||||
if operand_str != "" :
|
||||
operands = operand_str.split(",")
|
||||
if CSR_RE.search(s.group("instr")):
|
||||
# CSR instruction
|
||||
operand = operands[-1]
|
||||
if GPR_RE.search(operand) or operand == "zero":
|
||||
rv_instr_trace.rs1 = operand
|
||||
rv_instr_trace.rs1_val = gpr[operand]
|
||||
else:
|
||||
rv_instr_trace.imm = operand
|
||||
else:
|
||||
# Non CSR instruction
|
||||
for i in range(1, len(operands)):
|
||||
operand = operands[i]
|
||||
if GPR_RE.search(operand) or operand == "zero":
|
||||
if i == 1:
|
||||
rv_instr_trace.rs1 = operand
|
||||
rv_instr_trace.rs1_val = gpr[operand]
|
||||
else:
|
||||
rv_instr_trace.rs2 = operands[i]
|
||||
rv_instr_trace.rs2_val = gpr[operand]
|
||||
else:
|
||||
rv_instr_trace.imm = operand
|
||||
trace_csv.write_trace_entry(rv_instr_trace)
|
||||
logging.info("Processed instruction count : %d" % instr_cnt)
|
||||
|
||||
|
@ -79,5 +116,6 @@ def main():
|
|||
# Process spike log
|
||||
process_spike_sim_log(args.log, args.csv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
|
@ -31,6 +31,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
riscv_instr_sequence sub_program[];
|
||||
// Program in binary format, stored in the data section, used to inject illegal/HINT instruction
|
||||
riscv_instr_sequence bin_program;
|
||||
riscv_instr_sequence debug_program;
|
||||
string instr_binary[$];
|
||||
// Kernel programs
|
||||
// These programs are called in the interrupt/exception handling routine based on the privileged
|
||||
|
@ -78,6 +79,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
if(cfg.enable_illegal_instruction || cfg.enable_hint_instruction) begin
|
||||
bin_program = riscv_instr_sequence::type_id::create("bin_program");
|
||||
bin_program.instr_cnt = cfg.bin_program_instr_cnt;
|
||||
bin_program.is_debug_program = 0;
|
||||
bin_program.label_name = bin_program.get_name();
|
||||
bin_program.cfg = cfg;
|
||||
if (cfg.enable_illegal_instruction) begin
|
||||
|
@ -99,6 +101,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
foreach(sub_program[i]) begin
|
||||
sub_program[i] = riscv_instr_sequence::type_id::create($sformatf("sub_%0d",i+1));
|
||||
sub_program[i].instr_cnt = cfg.sub_program_instr_cnt[i];
|
||||
sub_program[i].is_debug_program = 0;
|
||||
generate_directed_instr_stream(.label(sub_program[i].get_name()),
|
||||
.original_instr_cnt(sub_program[i].instr_cnt),
|
||||
.min_insert_cnt(0),
|
||||
|
@ -113,6 +116,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
// Generate main program
|
||||
main_program = riscv_instr_sequence::type_id::create("main_program");
|
||||
main_program.instr_cnt = cfg.main_program_instr_cnt;
|
||||
main_program.is_debug_program = 0;
|
||||
main_program.label_name = "_main";
|
||||
generate_directed_instr_stream(.label("main"),
|
||||
.original_instr_cnt(main_program.instr_cnt),
|
||||
|
@ -174,8 +178,10 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
gen_privileged_mode_switch_routine();
|
||||
// Program end
|
||||
gen_program_end();
|
||||
// Generate debug mode section
|
||||
// Generate debug rom section
|
||||
gen_debug_mode_section();
|
||||
// Generate debug mode exception handler
|
||||
gen_debug_exception_section();
|
||||
// Starting point of data section
|
||||
gen_data_page_begin();
|
||||
// Generate the sub program in binary format
|
||||
|
@ -238,6 +244,7 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
.instr_stream(seq.directed_instr),
|
||||
.access_u_mode_mem(1'b0));
|
||||
seq.label_name = seq.get_name();
|
||||
seq.is_debug_program = 0;
|
||||
seq.cfg = cfg;
|
||||
`DV_CHECK_RANDOMIZE_FATAL(seq)
|
||||
seq.gen_instr(0);
|
||||
|
@ -796,6 +803,14 @@ class riscv_asm_program_gen extends uvm_object;
|
|||
// Helper functions
|
||||
//---------------------------------------------------------------------------------------
|
||||
|
||||
// Format a code section, without generating it
|
||||
virtual function void format_section(ref string instr[$]);
|
||||
string prefix = format_string(" ", LABEL_STR_LEN);
|
||||
foreach(instr[i]) begin
|
||||
instr[i] = {prefix, instr[i]};
|
||||
end
|
||||
endfunction
|
||||
|
||||
// Generate a code section
|
||||
virtual function void gen_section(string label, string instr[$]);
|
||||
string str;
|
||||
|
@ -918,10 +933,39 @@ 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 void gen_debug_mode_section();
|
||||
string instr[];
|
||||
string push_gpr[$];
|
||||
string pop_gpr[$];
|
||||
string instr[$];
|
||||
string dret;
|
||||
if (riscv_instr_pkg::support_debug_mode) begin
|
||||
instr = {"dret"};
|
||||
// The main debug rom
|
||||
if (!cfg.empty_debug_section) begin
|
||||
debug_program = riscv_instr_sequence::type_id::create("debug_program");
|
||||
debug_program.instr_cnt = cfg.debug_program_instr_cnt;
|
||||
debug_program.is_debug_program = 1;
|
||||
debug_program.cfg = cfg;
|
||||
`DV_CHECK_RANDOMIZE_FATAL(debug_program)
|
||||
debug_program.gen_instr(.is_main_program(1'b1), .enable_hint_instr(1'b0),
|
||||
.no_branch(1'b1));
|
||||
debug_program.post_process_instr();
|
||||
debug_program.generate_instr_stream(.no_label(1'b1));
|
||||
// Need to save off GPRs to avoid modifying program flow
|
||||
push_gpr_to_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, push_gpr);
|
||||
format_section(push_gpr);
|
||||
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, pop_gpr);
|
||||
format_section(pop_gpr);
|
||||
instr = {push_gpr, debug_program.instr_string_list, pop_gpr};
|
||||
end
|
||||
dret = {format_string(" ", LABEL_STR_LEN), "dret"};
|
||||
instr = {instr, dret};
|
||||
gen_section("debug_rom", instr);
|
||||
end
|
||||
endfunction
|
||||
|
||||
// Generate exception handling routine for debug ROM
|
||||
virtual function void gen_debug_exception_section();
|
||||
if (riscv_instr_pkg::support_debug_mode) begin
|
||||
string instr[];
|
||||
instr = {"dret"};
|
||||
gen_section("debug_exception", instr);
|
||||
end
|
||||
|
|
|
@ -93,7 +93,7 @@ class riscv_jump_instr extends riscv_rand_instr_stream;
|
|||
rand riscv_instr_base jump;
|
||||
rand riscv_instr_base addi;
|
||||
rand riscv_pseudo_instr la;
|
||||
rand riscv_instr_base branch;
|
||||
rand riscv_rand_instr branch;
|
||||
rand bit enable_branch;
|
||||
rand int mixed_instr_cnt;
|
||||
riscv_instr_base stack_exit_instr[];
|
||||
|
@ -125,10 +125,14 @@ class riscv_jump_instr extends riscv_rand_instr_stream;
|
|||
jump = riscv_instr_base::type_id::create("jump");
|
||||
la = riscv_pseudo_instr::type_id::create("la");
|
||||
addi = riscv_instr_base::type_id::create("addi");
|
||||
branch = riscv_instr_base::type_id::create("branch");
|
||||
branch = riscv_rand_instr::type_id::create("branch");
|
||||
instr_list.rand_mode(0);
|
||||
endfunction
|
||||
|
||||
function void pre_randomize();
|
||||
branch.cfg = cfg;
|
||||
endfunction
|
||||
|
||||
function void post_randomize();
|
||||
riscv_instr_base instr[];
|
||||
// Generate some random instructions to mix with jump instructions
|
||||
|
@ -171,7 +175,7 @@ class riscv_push_stack_instr extends riscv_rand_instr_stream;
|
|||
int num_of_redudant_instr;
|
||||
riscv_instr_base push_stack_instr[];
|
||||
riscv_reg_t saved_regs[];
|
||||
rand riscv_instr_base branch_instr;
|
||||
rand riscv_rand_instr branch_instr;
|
||||
rand bit enable_branch;
|
||||
string push_start_label;
|
||||
|
||||
|
@ -179,7 +183,6 @@ class riscv_push_stack_instr extends riscv_rand_instr_stream;
|
|||
|
||||
function new(string name = "");
|
||||
super.new(name);
|
||||
branch_instr = riscv_instr_base::type_id::create("branch_instr");
|
||||
endfunction
|
||||
|
||||
function void init();
|
||||
|
@ -225,6 +228,8 @@ class riscv_push_stack_instr extends riscv_rand_instr_stream;
|
|||
end
|
||||
if(enable_branch) begin
|
||||
// Cover jal -> branch scenario, the branch is added before push stack operation
|
||||
branch_instr = riscv_rand_instr::type_id::create("branch_instr");
|
||||
branch_instr.cfg = cfg;
|
||||
`DV_CHECK_RANDOMIZE_WITH_FATAL(branch_instr,
|
||||
category == BRANCH;)
|
||||
branch_instr.imm_str = push_start_label;
|
||||
|
|
|
@ -30,6 +30,9 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
// Instruction count of each sub-program
|
||||
rand int sub_program_instr_cnt[];
|
||||
|
||||
// Instruction count of the debug rom
|
||||
rand int debug_program_instr_cnt;
|
||||
|
||||
// Pattern of data section: RAND_DATA, ALL_ZERO, INCR_VAL
|
||||
rand data_pattern_t data_page_pattern;
|
||||
|
||||
|
@ -62,6 +65,12 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
bit check_misa_init_val = 1'b0;
|
||||
bit check_xstatus = 1'b1;
|
||||
|
||||
// Enable a full or empty debug_rom section.
|
||||
// Full debug_rom will contain random instruction streams.
|
||||
// Empty debug_rom will contain just dret instruction and will return immediately.
|
||||
// Will be empty by default.
|
||||
bit empty_debug_section = 1'b0;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Command line options or control knobs
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -123,8 +132,13 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
|
||||
constraint default_c {
|
||||
sub_program_instr_cnt.size() == num_of_sub_program;
|
||||
main_program_instr_cnt + sub_program_instr_cnt.sum() == instr_cnt;
|
||||
if (riscv_instr_pkg::support_debug_mode) {
|
||||
main_program_instr_cnt + sub_program_instr_cnt.sum() + debug_program_instr_cnt == instr_cnt;
|
||||
} else {
|
||||
main_program_instr_cnt + sub_program_instr_cnt.sum() == instr_cnt;
|
||||
}
|
||||
main_program_instr_cnt inside {[1 : instr_cnt]};
|
||||
debug_program_instr_cnt inside {[1 : instr_cnt]};
|
||||
foreach(sub_program_instr_cnt[i]) {
|
||||
sub_program_instr_cnt[i] inside {[1 : instr_cnt]};
|
||||
}
|
||||
|
@ -255,6 +269,7 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
get_bool_arg_value("+enable_hint_instruction=", enable_hint_instruction);
|
||||
get_bool_arg_value("+force_m_delegation=", force_m_delegation);
|
||||
get_bool_arg_value("+force_s_delegation=", force_s_delegation);
|
||||
get_bool_arg_value("+empty_debug_section=", empty_debug_section);
|
||||
if(inst.get_arg_value("+boot_mode=", boot_mode_opts)) begin
|
||||
`uvm_info(get_full_name(), $sformatf(
|
||||
"Got boot mode option - %0s", boot_mode_opts), UVM_LOW)
|
||||
|
@ -278,7 +293,8 @@ class riscv_instr_gen_config extends uvm_object;
|
|||
uvm_split_string(s, ",", cmdline_march_list);
|
||||
riscv_instr_pkg::supported_isa.delete();
|
||||
foreach(cmdline_march_list[i]) begin
|
||||
if(uvm_enum_wrapper#(riscv_instr_group_t)::from_name(cmdline_march_list[i], march)) begin
|
||||
if(uvm_enum_wrapper#(riscv_instr_group_t)::from_name(
|
||||
cmdline_march_list[i].toupper(), march)) begin
|
||||
riscv_instr_pkg::supported_isa.push_back(march);
|
||||
end else begin
|
||||
`uvm_fatal(get_full_name(), $sformatf(
|
||||
|
|
|
@ -40,6 +40,7 @@ class riscv_instr_sequence extends uvm_sequence;
|
|||
riscv_pop_stack_instr instr_stack_exit; // Stack pop instructions for sub-programs
|
||||
riscv_rand_instr_stream instr_stream; // Main instruction streams
|
||||
bit is_main_program; // Type of this sequence (main or sub program)
|
||||
bit is_debug_program; // Indicates whether sequence is debug program
|
||||
string label_name; // Label of the sequence (program name)
|
||||
riscv_instr_gen_config cfg; // Configuration class handle
|
||||
string instr_string_list[$]; // Save the instruction list in string format
|
||||
|
@ -70,7 +71,8 @@ class riscv_instr_sequence extends uvm_sequence;
|
|||
// considerably as the instruction stream becomes longer. The downside is we cannot specify
|
||||
// constraints between instructions. The way to solve it is to have a dedicated directed
|
||||
// instruction stream for such scenarios, like hazard sequence.
|
||||
virtual function void gen_instr(bit is_main_program, bit enable_hint_instr = 1'b0);
|
||||
virtual function void gen_instr(bit is_main_program, bit enable_hint_instr = 1'b0,
|
||||
bit no_branch = 1'b0);
|
||||
this.is_main_program = is_main_program;
|
||||
instr_stream.cfg = cfg;
|
||||
instr_stream.initialize_instr_list(instr_cnt);
|
||||
|
@ -78,7 +80,8 @@ class riscv_instr_sequence extends uvm_sequence;
|
|||
instr_stream.instr_list.size()), UVM_LOW)
|
||||
// Do not generate load/store instruction here
|
||||
// The load/store instruction will be inserted as directed instruction stream
|
||||
instr_stream.gen_instr(.no_load_store(1'b1), .enable_hint_instr(enable_hint_instr));
|
||||
instr_stream.gen_instr(.no_branch(no_branch), .no_load_store(1'b1),
|
||||
.enable_hint_instr(enable_hint_instr));
|
||||
if(!is_main_program) begin
|
||||
gen_stack_enter_instr();
|
||||
gen_stack_exit_instr();
|
||||
|
@ -243,13 +246,17 @@ class riscv_instr_sequence extends uvm_sequence;
|
|||
// Convert the instruction stream to the string format.
|
||||
// Label is attached to the instruction if available, otherwise attach proper space to make
|
||||
// the code indent consistent.
|
||||
function void generate_instr_stream();
|
||||
function void generate_instr_stream(bit no_label = 1'b0);
|
||||
string prefix, str;
|
||||
int i;
|
||||
instr_string_list = {};
|
||||
for(i = 0; i < instr_stream.instr_list.size(); i++) begin
|
||||
if(i == 0) begin
|
||||
prefix = format_string($sformatf("%0s:", label_name), LABEL_STR_LEN);
|
||||
if (no_label) begin
|
||||
prefix = format_string(" ", LABEL_STR_LEN);
|
||||
end else begin
|
||||
prefix = format_string($sformatf("%0s:", label_name), LABEL_STR_LEN);
|
||||
end
|
||||
instr_stream.instr_list[i].has_label = 1'b1;
|
||||
end else begin
|
||||
if(instr_stream.instr_list[i].has_label) begin
|
||||
|
|
|
@ -85,7 +85,6 @@ class riscv_instr_base_test extends uvm_test;
|
|||
endfunction
|
||||
|
||||
virtual function void apply_directed_instr();
|
||||
|
||||
endfunction
|
||||
|
||||
task run_phase(uvm_phase phase);
|
||||
|
|
5
vendor/google_riscv-dv/yaml/iss.yaml
vendored
5
vendor/google_riscv-dv/yaml/iss.yaml
vendored
|
@ -26,3 +26,8 @@
|
|||
--override riscvOVPsim/cpu/simulateexceptions=T
|
||||
--trace --tracechange --traceshowicount --program <elf>
|
||||
--finishafter 500000
|
||||
|
||||
- iss: sail
|
||||
path_var: SAIL_RISCV
|
||||
cmd: >
|
||||
<path_var> <elf>
|
||||
|
|
34
vendor/google_riscv-dv/yaml/testlist.yaml
vendored
34
vendor/google_riscv-dv/yaml/testlist.yaml
vendored
|
@ -26,6 +26,7 @@
|
|||
# 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_arithmetic_basic_test
|
||||
|
@ -79,6 +80,17 @@
|
|||
+directed_instr_5=riscv_multi_page_load_store_instr_stream,4
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_non_compressed_instr_test
|
||||
description: >
|
||||
Random instruction test without compressed instructions
|
||||
iterations: 2
|
||||
gen_test: riscv_rand_instr_test
|
||||
gen_opts: >
|
||||
+march=RV32I,RV32M,RV64I,RV64M
|
||||
gcc_opts: >
|
||||
-march=rv64im
|
||||
rtl_test: core_base_test
|
||||
|
||||
- test: riscv_rand_jump_test
|
||||
description: >
|
||||
Jump among large number of sub-programs, stress testing iTLB operations.
|
||||
|
@ -97,7 +109,7 @@
|
|||
iterations: 2
|
||||
gen_test: riscv_instr_base_test
|
||||
gen_opts: >
|
||||
+instr_cnt=10000
|
||||
+instr_cnt=5000
|
||||
+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
|
||||
|
@ -208,10 +220,28 @@
|
|||
compare_opts: >
|
||||
+compare_final_value_only=1
|
||||
|
||||
# Please enable this test for your RTL simulation
|
||||
- test: riscv_csr_test
|
||||
description: >
|
||||
Test all CSR instructions on all implemented CSR registers
|
||||
iterations: 1
|
||||
iterations: 0
|
||||
no_iss: 1
|
||||
rtl_test: core_ibex_csr_test
|
||||
no_post_compare: 1
|
||||
|
||||
- test: riscv_unaligned_load_store_test
|
||||
description: >
|
||||
Unaligned load/store test, ibex should handle it correctly without raising any exception
|
||||
iterations: 1
|
||||
gen_test: riscv_instr_base_test
|
||||
gcc_opts: >
|
||||
-mno-strict-align
|
||||
gen_opts: >
|
||||
+instr_cnt=6000
|
||||
+num_of_sub_program=5
|
||||
+directed_instr_0=riscv_load_store_rand_instr_stream,20
|
||||
+directed_instr_1=riscv_load_store_hazard_instr_stream,20
|
||||
+directed_instr_2=riscv_cache_line_stress_instr_stream,20
|
||||
+directed_instr_3=riscv_multi_page_load_store_instr_stream,20
|
||||
+enable_unaligned_load_store=1
|
||||
rtl_test: core_ibex_base_test
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue