diff --git a/vendor/google_riscv-dv.lock.hjson b/vendor/google_riscv-dv.lock.hjson index e9bc3165..114c777e 100644 --- a/vendor/google_riscv-dv.lock.hjson +++ b/vendor/google_riscv-dv.lock.hjson @@ -9,6 +9,6 @@ upstream: { url: https://github.com/google/riscv-dv - rev: e81acc9ab4f692ff205a207c2dc3d9f2b0284d39 + rev: faddfa49f456f3f8ef8c4231865994b7b13aa96d } } diff --git a/vendor/google_riscv-dv/README.md b/vendor/google_riscv-dv/README.md index 0f29a577..58d642f5 100644 --- a/vendor/google_riscv-dv/README.md +++ b/vendor/google_riscv-dv/README.md @@ -3,7 +3,7 @@ RISCV-DV is a SV/UVM based open-source instruction generator for RISC-V processor verification. It currently supports the following features: -- Supported instruction set: RV32IMC, RV64IMC +- Supported instruction set: RV32IMAC, RV64IMAC - Supported privileged mode: machine mode, supervisor mode, user mode - Page table randomization and exception - Privileged CSR setup randomization @@ -370,73 +370,6 @@ We have some work in progress which will be part of future releases: - 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 -``` -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". - -``` -./run -test all -``` -The script will run each test in the test list sequentially with the iteration -count specified in the "testlist". All the generated RISC-V assembly will be -listed when the regression is done. If it is successful, you should see the -following output: - -``` -=========================================================== - Generated RISC-V assembly tests - ---------------------------------------------------------- -./out_2018-11-20/asm_tests/riscv_arithmetic_basic_test.0.S -./out_2018-11-20/asm_tests/riscv_machine_mode_rand_test.0.S -./out_2018-11-20/asm_tests/riscv_mmu_stress_test.0.S -./out_2018-11-20/asm_tests/riscv_mmu_stress_test.1.S -./out_2018-11-20/asm_tests/riscv_no_fence_test.0.S -./out_2018-11-20/asm_tests/riscv_page_table_exception_test.0.S -./out_2018-11-20/asm_tests/riscv_page_table_exception_test.1.S -./out_2018-11-20/asm_tests/riscv_privileged_mode_rand_test.0.S -./out_2018-11-20/asm_tests/riscv_privileged_mode_rand_test.1.S -./out_2018-11-20/asm_tests/riscv_rand_instr_test.0.S -./out_2018-11-20/asm_tests/riscv_rand_instr_test.1.S -./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 - -// Run a test with a specified seed -./run -test riscv_page_table_exception_test -seed 123 - -// Run a test with addtional runtime options, separated with comma -./run -test riscv_rand_instr_test -runo +instr_cnt=10000,+no_fence=1 - -// Two steps compile and simulation (Avoid multiple compilation) -./run -co # compile only -# Generate multiple tests -./run -so -test riscv_rand_instr_test -n 10 -./run -so -test riscv_mmu_stress_test -n 20 -.... -``` ## Disclaimer This is not an officially supported Google product. diff --git a/vendor/google_riscv-dv/files.f b/vendor/google_riscv-dv/files.f index bfd9b7aa..87224071 100644 --- a/vendor/google_riscv-dv/files.f +++ b/vendor/google_riscv-dv/files.f @@ -17,6 +17,7 @@ +incdir+./test // SOURCES +./src/riscv_signature_pkg.sv ./src/riscv_instr_pkg.sv ./test/riscv_instr_test_pkg.sv ./test/riscv_instr_gen_tb_top.sv diff --git a/vendor/google_riscv-dv/iss_cmp b/vendor/google_riscv-dv/iss_cmp deleted file mode 100755 index 18f915e3..00000000 --- a/vendor/google_riscv-dv/iss_cmp +++ /dev/null @@ -1,40 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - -spike_log="$1" -ovpsim_log="$2" -report_file="$3" - -# ----------------------------------------------------------------------------- -# Convert spike log to standard instruction trace csv -# ----------------------------------------------------------------------------- -# 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 --xlen 64 - -# ----------------------------------------------------------------------------- -# Convert ovpsim log to standard instruction trace csv -# ----------------------------------------------------------------------------- -# 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 - -# ----------------------------------------------------------------------------- -# Compare the trace log -# ----------------------------------------------------------------------------- -python scripts/instr_trace_compare.py $spike_csv $ovpsim_csv \ - spike ovpsim >> $report_file -echo >> $report_file diff --git a/vendor/google_riscv-dv/iss_sim b/vendor/google_riscv-dv/iss_sim deleted file mode 100755 index 22baa05e..00000000 --- a/vendor/google_riscv-dv/iss_sim +++ /dev/null @@ -1,191 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - -# Environment variable for the path of RISC-V GCC toolchain -# You can install the toolchain from https://github.com/riscv/riscv-gcc -# RISCV_TOOLCHAIN="XXX" - -# GCC compile options -ABI="lp64" -ISA="rv64imc" - -DATE=`date +%Y-%m-%d` - -# Instruction set simulator -ISS="spike" # other options: ovpsim, all - -# riscv-ovpsim options -OVPSIM_VARIANT="RV64GC" - -# Binary of RISC-V ovpsim ISS -# https://github.com/riscv/riscv-ovpsim -RISCV_OVPSIM="${OVPSIM_PATH}/riscvOVPsim.exe" - -# Directory of assemble tests -SRC_DIR="./out_${DATE}/asm_tests" - -# Assembly test file name -TEST="" - -# Regression report file name -REPORT="$SRC_DIR/regression_report.log" - -# Clean the result of the previous runs -CLEAN=1 - -if [[ -z $RISCV_TOOLCHAIN ]]; then - echo "ERROR: Please define RISCV_TOOLCHAIN environment variable first" - exit 1 -fi - -# Process command line options -while [[ $# -gt 0 ]] -do -key="$1" - case $key in - -iss) - ISS="$2" - shift - ;; - -dir) - SRC_DIR="$2" - shift - ;; - -toolchain) - RISCV_TOOLCHAIN="$2" - shift - ;; - -isa) - ISA="$2" - shift - ;; - -abi) - ABI="$2" - shift - ;; - -test) - TEST="$2" - shift - ;; - -report) - REPORT="$2" - shift - ;; - -noclean) - CLEAN=0 - shift - ;; - *) - echo "unknown option $1" - return - ;; -esac -shift -done - -RISCV_GCC="$RISCV_TOOLCHAIN/bin/riscv64-unknown-elf-gcc" -RISCV_OBJCOPY="$RISCV_TOOLCHAIN/bin/riscv64-unknown-elf-objcopy" -RISCV_SPIKE="$RISCV_TOOLCHAIN/bin/spike" - -mkdir -p "$SRC_DIR" - -# If the test is specified through "-test" option, run a single test rather -# than all tests under SRC_DIR. -if [[ $TEST == "" ]]; then - find "$SRC_DIR" -name "*.S" > "$SRC_DIR/asm_test_list" -else - echo "$TEST" > "$SRC_DIR/asm_test_list" -fi - -if [[ $ISA =~ 32 ]]; then - OVPSIM_VARIANT="RV32GC" -fi - -# Clean up previous running result -if [[ $CLEAN == 1 ]]; then - rm -rf "$REPORT" - if [[ "$ISS" == "spike" ]] || [[ "$ISS" == "all" ]]; then - rm -rf "$SRC_DIR/spike_sim" - fi - if [[ "$ISS" == "ovpsim" ]] || [[ "$ISS" == "all" ]]; then - rm -rf "$SRC_DIR/riscv_ovpsim" - fi -fi - -# GCC compile -while read asm_test; do - # Generate binary for RTL simulation - SRC="$asm_test" - OBJFILE="$asm_test.o" - BINFILE="$asm_test.bin" - GCC_CMD="$RISCV_GCC -march=$ISA -mabi=$ABI -static -mcmodel=medany \ - -fvisibility=hidden -nostdlib \ - -nostartfiles -I$RISCV_TESTS/env/p \ - -Tscripts/link.ld $SRC -o $OBJFILE" - echo "riscv_gcc compiling : $SRC" - $($GCC_CMD) - echo "Convert $OBJFILE to $BINFILE" - # Convert the ELF to plain binary - # You can load this binary to your RTL simulation - "$RISCV_OBJCOPY" -O binary "$OBJFILE" "$BINFILE" -done <"$SRC_DIR/asm_test_list" - -if [[ "$ISS" == "ovpsim" ]] || [[ "$ISS" == "all" ]]; then - mkdir -p "$SRC_DIR/riscv_ovpsim" -fi -if [[ "$ISS" == "spike" ]] || [[ "$ISS" == "all" ]]; then - mkdir -p "$SRC_DIR/spike_sim" -fi - -# Run ISS simulation -while read asm_test; do - ELF="${asm_test}.o" - TEST_NAME=$(echo "$ELF" | sed 's/^.*\///g') - # Spike sim - if [[ "$ISS" == "spike" ]] || [[ "$ISS" == "all" ]]; then - echo "Running spike: $TEST_NAME" - SPIKE_LOG="$SRC_DIR/spike_sim/$TEST_NAME.log" - SPIKE_CMD="timeout 60s $RISCV_SPIKE --isa=$ISA -l $ELF &> $SPIKE_LOG" - $($SPIKE_CMD &> $SPIKE_LOG) - fi - # riscv_ovpsim sim - if [[ "$ISS" == "ovpsim" ]] || [[ "$ISS" == "all" ]]; then - if [[ -z $OVPSIM_PATH ]]; then - echo "ERROR: Please define OVPSIM_PATH environment variable first" - exit 1 - fi - OVPSIM_LOG="$SRC_DIR/riscv_ovpsim/$TEST_NAME.log" - echo "Running ovpsim: $TEST_NAME" - RISCV_OVPSIM_CMD="$RISCV_OVPSIM --variant $OVPSIM_VARIANT \ - --override riscvOVPsim/cpu/PMP_registers=0 \ - --override riscvOVPsim/cpu/simulateexceptions=T \ - --trace --tracechange --traceshowicount --program $ELF \ - --finishafter 500000" - $($RISCV_OVPSIM_CMD &> $OVPSIM_LOG) - fi - if [[ "$ISS" == "all" ]]; then - echo "Rerun command: ./iss_sim -test $asm_test -iss all" >> "$REPORT" - echo "spike : $SPIKE_LOG" >> "$REPORT" - echo "ovpsim : $OVPSIM_LOG" >> "$REPORT" - ./iss_cmp "$SPIKE_LOG" "$OVPSIM_LOG" "$REPORT" - tail -1 "$REPORT" - echo "" >> "$REPORT" - fi -done <"$SRC_DIR/asm_test_list" - -if [[ "$ISS" == "all" ]]; then - echo "Full regression report is saved to $REPORT" - cat "$REPORT" -fi diff --git a/vendor/google_riscv-dv/run b/vendor/google_riscv-dv/run deleted file mode 100755 index 23980f21..00000000 --- a/vendor/google_riscv-dv/run +++ /dev/null @@ -1,308 +0,0 @@ -#!/bin/bash -# Copyright 2018 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. - - -# This is simple run script to run a dedicated test or a regression -# -# Usage: -# Run a single test with irun -# ./run -tool irun -test riscv_instr_base_test -# -# Run regression with vcs -# ./run -test all -# -# Change output directory -# ./run -out my_output_dir - -DATE=`date +%Y-%m-%d` - -# RTL simulator, supports vcs, irun, and questa -SIMULATOR="vcs" - -# random seed -SEED=`date +%s` - -# Test name, "all" means run all tests in the testlist -TEST="riscv_instr_base_test" - -# Number of assembly programs to be generated for this test -# This option only apply to single test mode. For the regression mode, the number is specified in -# the testlist -NUM_TESTS=1 - -# Simulation output directory -OUT="./out_${DATE}" - -# Simulation only -SIM_ONLY=0 - -# Compile only -CMP_ONLY=0 - -# Compile/run time options -SIM_OPTS="" -CMP_OPTS="" - -# Verbose logging, by default disable detail logging -VERBOSE=0 - -# Submit to LSF -LSF_CMD="bsub" -LSF_OPTS="" -LSF=0 -LSF_TIMEOUT=100 - -# Testlist for regression -TEST_LIST=testlist - -# Process command line options -while [[ $# -gt 0 ]] -do -key="$1" -case $key in - -tool) - SIMULATOR="$2" - shift - ;; - -test) - TEST="$2" - shift - ;; - -n) - NUM_TESTS="$2" - shift - ;; - -seed) - SEED="$2" - shift - ;; - -sim_opts) - SIM_OPTS="$2" - shift - ;; - -cmp_opts) - CMP_OPTS="$2" - shift - ;; - -testlist) - TEST_LIST="$2" - shift - ;; - -timeout) - LSF_TIMEOUT="$2" - shift - ;; - -so) - SIM_ONLY=1 - ;; - -verbose) - VERBOSE=1 - ;; - -co) - CMP_ONLY=1 - ;; - -lsf) - LSF=1 - ;; - -lsf_opts) - LSF_OPTS="$2" - shift - ;; - -o) - OUT="$2" - shift - ;; - *) - echo "unknown option $1" - exit 1 - ;; -esac -shift -done - -if [[ $LSF == 0 ]]; then - LSF_CMD="" -fi - -OUT=`realpath ${OUT}` - -# Generate compile and simulation commands -if [[ "$SIMULATOR" == "vcs" ]]; then - - 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 - - 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" - exit 1 -fi - -# Clean up previous runs -if [[ $SIM_ONLY == 0 ]]; then - rm -rf ${OUT} -else - rm -rf ${OUT}/asm_tests -fi - -mkdir -p ${OUT} -mkdir -p ${OUT}/asm_tests - -# Compilation -if [[ $SIM_ONLY == 0 ]]; then - echo "Building RISC-V instruction generator..." - if [[ $VERBOSE == 1 ]]; then - run_compile - else - run_compile > /dev/null - fi - echo "Building RISC-V instruction generator...done" -fi - -# Skip simulation if compilation only flag is set -if [[ $CMP_ONLY == 1 ]]; then - exit 0 -fi - -# Run sim -if [[ ${TEST} == "all" ]]; then - echo "Running regression with testlist: $TEST_LIST" - LOG_LIST="${OUT}/sim_log.list" - PROGRAM_CNT=0 - cat "$TEST_LIST" - rm -rf "$LOG_LIST" - while read line; do - if ! [[ $line =~ ^\/\/ ]]; then - if [[ $line =~([a-z0-9_-]*)([[:space:]]*)\:([[:space:]]*)([0-9]*)([[:space:]]*)\:(.*$) ]]; then - SEED=`date +%s` - TEST=${BASH_REMATCH[1]} - ITERATION=${BASH_REMATCH[4]} - TEST_OPTS=${BASH_REMATCH[6]} - if [[ ${ITERATION} != "0" ]]; then - echo "Running ${TEST} to generate ${ITERATION} tests" - CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \ - ${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} - if [[ $VERBOSE == 1 ]]; then - ${LSF_CMD} ${LSF_OPTS} ${CMD} - else - ${LSF_CMD} ${LSF_OPTS} ${CMD} > /dev/null - fi - fi - fi - fi - done < $TEST_LIST - # Wait util all tests are generated - if [[ $LSF == 1 ]]; then - TIMEOUT_CNT=0 - TOTAL_CNT=`wc -l < ${LOG_LIST}` - echo "Waiting for ${TOTAL_CNT} tests to complete, ${PROGRAM_CNT} programs to generate." - while [[ 1 ]]; do - COMPLETED_CNT=0 - while read log; do - if [[ -f "$log" ]]; then - if grep -q "TEST GENERATION DONE" $log; then - ((COMPLETED_CNT+=1)) - else - if [[ $VERBOSE == 1 ]]; then - echo "$log is not completed" - fi - fi - else - if [[ $VERBOSE == 1 ]]; then - echo "$log is not completed" - fi - fi - done < ${LOG_LIST} - GENERATED_CNT=`find ${OUT}/asm_tests/ -name "*.S" | wc -l` - echo "[$TIMEOUT_CNT] Progress > Test:${COMPLETED_CNT}/${TOTAL_CNT} Program:${GENERATED_CNT}/${PROGRAM_CNT}" - if [[ "$COMPLETED_CNT" == "$TOTAL_CNT" ]]; then - break - else - if [[ "$TIMEOUT_CNT" == "$LSF_TIMEOUT" ]]; then - echo "Generator timeout after $LSF_TIMEOUT * 10 seconds" - break - else - sleep 10 - fi - fi - ((TIMEOUT_CNT+=1)) - done - fi -else - echo "Running test ${TEST} to generate ${NUM_TESTS} tests" - CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \ - ${SIM_SEED}${SEED} \ - -l ${OUT}/sim_${TEST}.log \ - +num_of_tests=${NUM_TESTS} ${SIM_OPTS}" - if [[ $VERBOSE == 1 ]]; then - ${CMD} - else - ${CMD} > /dev/null - fi -fi - - -# List all generated assembly tests -echo "===========================================================" -echo " Generated RISC-V assembly tests" -echo " ----------------------------------------------------------" -find $OUT/asm_tests -name "*.S" | sort -k11 diff --git a/vendor/google_riscv-dv/run.py b/vendor/google_riscv-dv/run.py index 51e34439..0da97d86 100644 --- a/vendor/google_riscv-dv/run.py +++ b/vendor/google_riscv-dv/run.py @@ -334,7 +334,7 @@ def setup_parser(): parser.add_argument("--lsf_cmd", type=str, default="", help="LSF command. Run in local sequentially if lsf \ command is not specified") - parser.add_argument("--isa", type=str, default="rv64imc", + parser.add_argument("--isa", type=str, default="rv64gc", help="RISC-V ISA subset") parser.add_argument("-m", "--mabi", type=str, default="lp64", help="mabi used for compilation, lp32 or lp64", dest="mabi") diff --git a/vendor/google_riscv-dv/scripts/__init__.py b/vendor/google_riscv-dv/scripts/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/vendor/google_riscv-dv/scripts/gen_csr_test.py b/vendor/google_riscv-dv/scripts/gen_csr_test.py index 803ca149..a1604cf7 100644 --- a/vendor/google_riscv-dv/scripts/gen_csr_test.py +++ b/vendor/google_riscv-dv/scripts/gen_csr_test.py @@ -43,8 +43,9 @@ except ImportError as e: Defines the test's success/failure values, one of which will be written to the chosen signature address to indicate the test's result. """ -PASS_VAL = 1 -FAIL_VAL = 0 +TEST_RESULT = 1 +TEST_PASS = 0 +TEST_FAIL = 1 def get_csr_map(csr_file, xlen): """ @@ -227,7 +228,9 @@ def gen_csr_test_fail(test_file, end_addr): end_addr: address that should be written to at end of test """ test_file.write(f"csr_fail:\n") - test_file.write(f"\tli x1, {FAIL_VAL}\n") + test_file.write(f"\tli x1, {TEST_FAIL}\n") + test_file.write(f"\tslli x1, x1, 8\n") + test_file.write(f"\taddi x1, x1, {TEST_RESULT}\n") test_file.write(f"\tli x2, {end_addr}\n") test_file.write(f"\tsw x1, 0(x2)\n") test_file.write(f"\tj csr_fail\n") @@ -244,7 +247,9 @@ def gen_csr_test_pass(test_file, end_addr): end_addr: address that should be written to at end of test """ test_file.write(f"csr_pass:\n") - test_file.write(f"\tli x1, {PASS_VAL}\n") + test_file.write(f"\tli x1, {TEST_PASS}\n") + test_file.write(f"\tslli x1, x1, 8\n") + test_file.write(f"\taddi x1, x1, {TEST_RESULT}\n") test_file.write(f"\tli x2, {end_addr}\n") test_file.write(f"\tsw x1, 0(x2)\n") test_file.write(f"\tj csr_pass\n") diff --git a/vendor/google_riscv-dv/scripts/lib.py b/vendor/google_riscv-dv/scripts/lib.py index 9842483b..1037680b 100644 --- a/vendor/google_riscv-dv/scripts/lib.py +++ b/vendor/google_riscv-dv/scripts/lib.py @@ -147,7 +147,7 @@ def process_regression_list(testlist, test, iterations, matched_list): yaml_data = read_yaml(testlist) for entry in yaml_data: if (entry['test'] == test) or (test == "all"): - if iterations > 0: + if (iterations > 0 and entry['iterations'] > 0): entry['iterations'] = iterations if entry['iterations'] > 0: logging.info("Found matched tests: %s, iterations:%0d" % diff --git a/vendor/google_riscv-dv/setting/riscv_core_setting.sv b/vendor/google_riscv-dv/setting/riscv_core_setting.sv index 86b91fe5..5ca55e02 100644 --- a/vendor/google_riscv-dv/setting/riscv_core_setting.sv +++ b/vendor/google_riscv-dv/setting/riscv_core_setting.sv @@ -30,7 +30,7 @@ privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MAC riscv_instr_name_t unsupported_instr[]; // ISA supported by the processor -riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C}; +riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C, RV32A, RV64A}; // Interrupt mode support mtvec_mode_t supported_interrupt_mode[$] = {DIRECT, VECTORED}; diff --git a/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv b/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv new file mode 100644 index 00000000..f16fe584 --- /dev/null +++ b/vendor/google_riscv-dv/src/riscv_amo_instr_lib.sv @@ -0,0 +1,170 @@ +/* + * 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 class for AMO instruction stream +class riscv_amo_base_instr_stream extends riscv_directed_instr_stream; + + rand int unsigned num_amo; + rand int unsigned num_mixed_instr; + rand int base; + rand riscv_reg_t rs1_reg; + riscv_reg_t reserved_rd[$]; + rand int unsigned data_page_id; + + // User can specify a small group of available registers to generate various hazard condition + rand riscv_reg_t avail_regs[]; + + `uvm_object_utils(riscv_amo_base_instr_stream) + + constraint rs1_c { + !(rs1_reg inside {cfg.reserved_regs, reserved_rd, ZERO}); + } + + constraint addr_range_c { + data_page_id < max_data_page_id; + base inside {[0 : max_load_store_offset-1]}; + } + + constraint aligned_amo_c { + if (XLEN == 32) { + base % 4 == 0; + } else { + base % 8 == 0; + } + } + + function new(string name = ""); + super.new(name); + instr_list.rand_mode(0); + endfunction + + function void post_randomize(); + gen_amo_instr(); + // rs1 cannot be modified by other instructions + if(!(rs1_reg inside {reserved_rd})) begin + reserved_rd.push_back(rs1_reg); + end + add_mixed_instr(); + add_rs1_init_la_instr(); + super.post_randomize(); + endfunction + + // Use "la" instruction to initialize the base regiseter + virtual function void add_rs1_init_la_instr(); + riscv_pseudo_instr la_instr; + la_instr = riscv_pseudo_instr::type_id::create("la_instr"); + `DV_CHECK_RANDOMIZE_WITH_FATAL(la_instr, + pseudo_instr_name == LA; + rd == rs1_reg;, + "Cannot randomize la_instr") + if(access_u_mode_mem) begin + la_instr.imm_str = $sformatf("data_page_%0d+%0d", data_page_id, base); + end else begin + la_instr.imm_str = $sformatf("kernel_data_page_%0d+%0d", data_page_id, base); + end + instr_list.push_front(la_instr); + endfunction + + // AMO instruction generation + virtual function void gen_amo_instr(); + endfunction + + // Insert some other instructions to mix with load/store instruction + virtual function void add_mixed_instr(); + riscv_rand_instr rand_instr; + for(int i = 0; i < num_mixed_instr; i ++) begin + rand_instr = riscv_rand_instr::type_id::create("rand_instr"); + rand_instr.cfg = cfg; + rand_instr.reserved_rd = reserved_rd; + `DV_CHECK_RANDOMIZE_WITH_FATAL(rand_instr, + if(avail_regs.size() > 0) { + rs1 inside {avail_regs}; + rd inside {avail_regs}; + } + !(category inside {LOAD, STORE, BRANCH, JUMP});, + "Cannot randomize instruction") + insert_instr(rand_instr); + end + endfunction + +endclass + +// A pair of LR/SC instruction +class riscv_lr_sc_instr_stream extends riscv_amo_base_instr_stream; + + riscv_rand_instr lr_instr; + riscv_rand_instr sc_instr; + + constraint legal_c { + num_amo == 1; + num_mixed_instr inside {[0:15]}; + } + + `uvm_object_utils(riscv_lr_sc_instr_stream) + + function new(string name = ""); + super.new(name); + lr_instr = riscv_rand_instr::type_id::create("lr_instr"); + sc_instr = riscv_rand_instr::type_id::create("sc_instr"); + endfunction + + virtual function void gen_amo_instr(); + lr_instr.cfg = cfg; + sc_instr.cfg = cfg; + lr_instr.disable_a_extension_c.constraint_mode(0); + sc_instr.disable_a_extension_c.constraint_mode(0); + `DV_CHECK_RANDOMIZE_WITH_FATAL(lr_instr, + rs1 == rs1_reg; + rd != rs1_reg; + instr_name inside {LR_W, LR_D};) + `DV_CHECK_RANDOMIZE_WITH_FATAL(sc_instr, + rs1 == rs1_reg; + rd != rs1_reg; + instr_name inside {SC_W, SC_D};) + instr_list.push_front(lr_instr); + instr_list.push_front(sc_instr); + endfunction + +endclass + +class riscv_amo_instr_stream extends riscv_amo_base_instr_stream; + + riscv_rand_instr amo_instr[]; + + constraint reasonable_c { + solve num_amo before num_mixed_instr; + num_amo inside {[1:10]}; + num_mixed_instr inside {[0:2*num_amo]}; + } + + `uvm_object_utils(riscv_amo_instr_stream) + `uvm_object_new + + virtual function void gen_amo_instr(); + amo_instr = new[num_amo]; + foreach (amo_instr[i]) begin + amo_instr[i] = riscv_rand_instr::type_id::create($sformatf("amo_instr_%0d", i)); + amo_instr[i].cfg = cfg; + amo_instr[i].disable_a_extension_c.constraint_mode(0); + `DV_CHECK_RANDOMIZE_WITH_FATAL(amo_instr[i], + rs1 == rs1_reg; + rd != rs1_reg; + category == AMO;) + instr_list.push_front(amo_instr[i]); + end + endfunction + +endclass diff --git a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv index eeeaa0fa..7817ae57 100644 --- a/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv +++ b/vendor/google_riscv-dv/src/riscv_asm_program_gen.sv @@ -70,6 +70,7 @@ class riscv_asm_program_gen extends uvm_object; gen_program_header(); // Initialize general purpose registers init_gpr(); + setup_misa(); // Create all page tables create_page_table(); // Setup privileged mode registers and enter target privileged mode @@ -355,7 +356,6 @@ class riscv_asm_program_gen extends uvm_object; instr_stream.push_back(str); // Init stack pointer to point to the end of the user stack str = {indent, "la sp, _user_stack_end"}; - setup_misa(); instr_stream.push_back(str); core_is_initialized(); // Copy the instruction from data section to instruction section @@ -384,6 +384,7 @@ class riscv_asm_program_gen extends uvm_object; RV32C, RV64C, RV128C : misa[MISA_EXT_C] = 1'b1; RV32I, RV64I, RV128I : misa[MISA_EXT_I] = 1'b1; RV32M, RV64M : misa[MISA_EXT_M] = 1'b1; + RV32A, RV64A : misa[MISA_EXT_A] = 1'b1; default : `uvm_fatal(`gfn, $sformatf("%0s is not yet supported", supported_isa[i].name())) endcase end @@ -400,12 +401,7 @@ class riscv_asm_program_gen extends uvm_object; if (cfg.require_signature_addr) begin if (cfg.signature_addr != 32'hdead_beef) begin string str; - str = {indent, $sformatf("li x5, 0x%0h", cfg.signature_addr)}; - instr_stream.push_back(str); - str = {indent, $sformatf("li x6, 0x%0h", riscv_instr_pkg::CORE_INITIALIZATION_DONE)}; - instr_stream.push_back(str); - str = {indent, "sw x6, 0(x5)"}; - instr_stream.push_back(str); + gen_signature_handshake(instr_stream, CORE_STATUS, INITIALIZED); end else begin `uvm_fatal(`gfn, "The signature_addr is not properly configured!") end @@ -627,10 +623,11 @@ class riscv_asm_program_gen extends uvm_object; // Generate page table fault handling routine // Page table fault is always handled in machine mode, as virtual address translation may be // broken when page fault happens. + gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION); if(page_table_list != null) begin page_table_list.gen_page_fault_handling_routine(instr); end else begin - instr = {"nop"}; + instr.push_back("nop"); end gen_section("pt_fault_handler", instr); endfunction @@ -670,7 +667,12 @@ class riscv_asm_program_gen extends uvm_object; tvec_name = tvec.name(); gen_section($sformatf("%0s_handler", tvec_name.tolower()), instr); // Exception handler - instr = {"", + instr = {}; + if (cfg.mtvec_mode == VECTORED) begin + push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, instr); + end + gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION); + instr = {instr, // The trap is caused by an exception, read back xCAUSE, xEPC to see if these // CSR values are set properly. The checking is done by comparing against the log // generated by ISA simulator (spike). @@ -725,12 +727,13 @@ class riscv_asm_program_gen extends uvm_object; $sformatf("j %0smode_exception_handler", mode)}; // Redirect the interrupt to the corresponding interrupt handler for (int i = 1; i < 16; i++) begin - instr.push_back($sformatf("j intr_vector_%0d", i)); + instr.push_back($sformatf("j %0smode_intr_vector_%0d", mode, i)); end instr = {instr, ".option rvc;"}; for (int i = 1; i < 16; i++) begin string intr_handler[$]; push_gpr_to_kernel_stack(status, scratch, cfg.mstatus_mprv, intr_handler); + gen_signature_handshake(intr_handler, CORE_STATUS, HANDLING_IRQ); intr_handler = {intr_handler, $sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()), // Terminate the test if xCause[31] != 0 (indicating exception) @@ -739,7 +742,7 @@ class riscv_asm_program_gen extends uvm_object; // Jump to commmon interrupt handling routine $sformatf("j %0smode_intr_handler", mode), "1: j test_done"}; - gen_section($sformatf("intr_vector_%0d", i), intr_handler); + gen_section($sformatf("%0smode_intr_vector_%0d", mode, i), intr_handler); end endfunction @@ -765,10 +768,12 @@ class riscv_asm_program_gen extends uvm_object; // TODO: Support random operations in debug mode // TODO: Support ebreak exception delegation virtual function void gen_ebreak_handler(); - string instr[$] = { - "csrr x31, mepc", - "addi x31, x31, 4", - "csrw mepc, x31" + string instr[$]; + gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION); + instr = {instr, + "csrr x31, mepc", + "addi x31, x31, 4", + "csrw mepc, x31" }; pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, instr); instr.push_back("mret"); @@ -782,10 +787,12 @@ class riscv_asm_program_gen extends uvm_object; // 4 and resumes execution. The way that the illegal instruction is injected guarantees that // PC + 4 is a valid instruction boundary. virtual function void gen_illegal_instr_handler(); - string instr[$] = { - "csrr x31, mepc", - "addi x31, x31, 4", - "csrw mepc, x31" + string instr[$]; + gen_signature_handshake(instr, CORE_STATUS, HANDLING_EXCEPTION); + instr = {instr, + "csrr x31, mepc", + "addi x31, x31, 4", + "csrw mepc, x31" }; pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, instr); instr.push_back("mret"); @@ -929,6 +936,88 @@ class riscv_asm_program_gen extends uvm_object; `uvm_info(get_full_name(), $sformatf("%0s is generated", test_name), UVM_LOW) endfunction + // Helper function to generate the proper sequence of handshake instructions + // to signal the testbench (see riscv_signature_pkg.sv) + function void gen_signature_handshake(ref string instr[$], + input signature_type_t signature_type, + core_status_t core_status = INITIALIZED, + test_result_t test_result = TEST_FAIL, + privileged_reg_t csr = MSCRATCH); + if (cfg.require_signature_addr) begin + string str; + str = $sformatf("li x%0d, 0x%0h", cfg.signature_addr_reg, cfg.signature_addr); + instr.push_back(str); + case (signature_type) + // A single data word is written to the signature address. + // Bits [7:0] contain the signature_type of CORE_STATUS, and the upper + // XLEN-8 bits contain the core_status_t data. + CORE_STATUS: begin + str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, core_status); + instr.push_back(str); + str = $sformatf("slli x%0d, x%0d, 8", cfg.signature_data_reg, cfg.signature_data_reg); + instr.push_back(str); + str = $sformatf("addi x%0d, x%0d, 0x%0h", cfg.signature_data_reg, + cfg.signature_data_reg, signature_type); + instr.push_back(str); + str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg); + instr.push_back(str); + end + // A single data word is written to the signature address. + // Bits [7:0] contain the signature_type of TEST_RESULT, and the upper + // XLEN-8 bits contain the test_result_t data. + TEST_RESULT: begin + str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, test_result); + instr.push_back(str); + str = $sformatf("slli x%0d, x%0d, 8", cfg.signature_data_reg, cfg.signature_data_reg); + instr.push_back(str); + str = $sformatf("addi x%0d, x%0d, 0x%0h", cfg.signature_data_reg, + cfg.signature_data_reg, signature_type); + instr.push_back(str); + str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg); + instr.push_back(str); + end + // The first write to the signature address contains just the + // signature_type of WRITE_GPR. + // It is followed by 32 consecutive writes to the signature address, + // each writing the data contained in one GPR, starting from x0 as the + // first write, and ending with x31 as the 32nd write. + WRITE_GPR: begin + str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, signature_type); + instr.push_back(str); + str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg); + instr.push_back(str); + for(int i = 0; i < 32; i++) begin + str = $sformatf("sw x%0x, 0(x%0d)", i, cfg.signature_addr_reg); + instr.push_back(str); + end + end + // The first write to the signature address contains the + // signature_type of WRITE_CSR in bits [7:0], and the CSR address in + // the upper XLEN-8 bits. + // It is followed by a second write to the signature address, + // containing the data stored in the specified CSR. + WRITE_CSR: begin + str = $sformatf("li x%0d, 0x%0h", cfg.signature_data_reg, csr); + instr.push_back(str); + str = $sformatf("slli x%0d, x%0d, 8", cfg.signature_data_reg, cfg.signature_data_reg); + instr.push_back(str); + str = $sformatf("addi x%0d, x%0d, 0x%0h", cfg.signature_data_reg, + cfg.signature_data_reg, signature_type); + instr.push_back(str); + str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg); + instr.push_back(str); + str = $sformatf("csrr x%0d, 0x%0h", cfg.signature_data_reg, csr); + instr.push_back(str); + str = $sformatf("sw x%0d, 0(x%0d)", cfg.signature_data_reg, cfg.signature_addr_reg); + instr.push_back(str); + end + default: begin + `uvm_fatal(`gfn, "signature_type is not defined") + end + endcase + end + endfunction + //--------------------------------------------------------------------------------------- // Inject directed instruction stream //--------------------------------------------------------------------------------------- @@ -1028,6 +1117,10 @@ class riscv_asm_program_gen extends uvm_object; string dret; string debug_sub_program_name[$] = {}; if (riscv_instr_pkg::support_debug_mode) begin + // Signal that the core entered the debug rom regardless of whether the + // main debug rom program has been generated + gen_signature_handshake(instr, CORE_STATUS, IN_DEBUG_MODE); + format_section(instr); // The main debug rom if (cfg.gen_debug_section) begin gen_sub_program(debug_sub_program, debug_sub_program_name, @@ -1048,7 +1141,7 @@ class riscv_asm_program_gen extends uvm_object; 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}; + instr = {push_gpr, instr, debug_program.instr_string_list, pop_gpr}; insert_sub_program(debug_sub_program, instr_stream); end dret = {format_string(" ", LABEL_STR_LEN), "dret"}; diff --git a/vendor/google_riscv-dv/src/riscv_instr_base.sv b/vendor/google_riscv-dv/src/riscv_instr_base.sv index d371fcf9..97b47c15 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_base.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_base.sv @@ -30,6 +30,8 @@ class riscv_instr_base extends uvm_object; rand imm_t imm_type; rand bit [4:0] imm_len; rand bit is_pseudo_instr; + rand bit aq; + rand bit rl; bit is_branch_target; bit has_label = 1'b1; bit atomic = 0; @@ -106,6 +108,10 @@ class riscv_instr_base extends uvm_object; } } + constraint aq_rl_c { + aq && rl == 0; + } + // Avoid generating HINT or illegal instruction by default as it's not supported by the compiler constraint no_hint_illegal_instr_c { if (instr_name inside {C_ADDI, C_ADDIW, C_LI, C_LUI, C_SLLI, C_SLLI64, @@ -366,6 +372,32 @@ class riscv_instr_base extends uvm_object; `add_instr(C_FLDSP, CI_FORMAT, LOAD, RV32DC, UIMM) `add_instr(C_FSDSP, CSS_FORMAT, STORE, RV32DC, UIMM) + // RV32A + `add_instr(LR_W, R_FORMAT, LOAD, RV32A) + `add_instr(SC_W, R_FORMAT, STORE, RV32A) + `add_instr(AMOSWAP_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOADD_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOAND_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOOR_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOXOR_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOMIN_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOMAX_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOMINU_W, R_FORMAT, AMO, RV32A) + `add_instr(AMOMAXU_W, R_FORMAT, AMO, RV32A) + + // RV64A + `add_instr(LR_D, R_FORMAT, LOAD, RV32A) + `add_instr(SC_D, R_FORMAT, STORE, RV32A) + `add_instr(AMOSWAP_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOADD_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOAND_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOOR_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOXOR_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOMIN_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOMAX_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOMINU_D, R_FORMAT, AMO, RV32A) + `add_instr(AMOMAXU_D, R_FORMAT, AMO, RV32A) + // Supervisor Instructions `add_instr(SFENCE_VMA, R_FORMAT,SYNCH,RV32I) @@ -408,7 +440,7 @@ class riscv_instr_base extends uvm_object; virtual function string convert2asm(string prefix = ""); string asm_str; asm_str = format_string(get_instr_name(), MAX_INSTR_STR_LEN); - if(category != SYSTEM) begin + if((category != SYSTEM) && !(group inside {RV32A, RV64A})) begin case(format) J_FORMAT, U_FORMAT : // instr rd,imm asm_str = $sformatf("%0s%0s, %0s", asm_str, rd.name(), get_imm()); @@ -431,12 +463,13 @@ class riscv_instr_base extends uvm_object; else asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rs1.name(), rs2.name(), get_imm()); R_FORMAT: // instr rd,rs1,rs2 - if(category == CSR) + if(category == CSR) begin asm_str = $sformatf("%0s%0s, 0x%0x, %0s", asm_str, rd.name(), csr, rs1.name()); - else if(instr_name == SFENCE_VMA) + end else if(instr_name == SFENCE_VMA) begin asm_str = "sfence.vma x0, x0"; // TODO: Support all possible sfence - else + end else begin asm_str = $sformatf("%0s%0s, %0s, %0s", asm_str, rd.name(), rs1.name(), rs2.name()); + end CI_FORMAT, CIW_FORMAT: if(instr_name == C_NOP) asm_str = "c.nop"; @@ -458,6 +491,12 @@ class riscv_instr_base extends uvm_object; CJ_FORMAT: asm_str = $sformatf("%0s%0s", asm_str, get_imm()); endcase + end else if (group inside {RV32A, RV64A}) begin + if (instr_name inside {LR_W, LR_D}) begin + asm_str = $sformatf("%0s %0s, (%0s)", asm_str, rd.name(), rs1.name()); + end else begin + asm_str = $sformatf("%0s %0s, %0s, (%0s)", asm_str, rd.name(), rs2.name(), rs1.name()); + end end else begin // For EBREAK,C.EBREAK, making sure pc+4 is a valid instruction boundary // This is needed to resume execution from epc+4 after ebreak handling @@ -835,6 +874,14 @@ class riscv_instr_base extends uvm_object; get_instr_name = instr_name.name(); if(get_instr_name.substr(0, 1) == "C_") begin get_instr_name = {"c.", get_instr_name.substr(2, get_instr_name.len() - 1)}; + end else if (group == RV32A) begin + get_instr_name = {get_instr_name.substr(0, get_instr_name.len() - 3), ".w"}; + get_instr_name = aq ? {get_instr_name, ".aq"} : + rl ? {get_instr_name, ".rl"} : get_instr_name; + end else if (group == RV64A) begin + get_instr_name = {get_instr_name.substr(0, get_instr_name.len() - 3), ".d"}; + get_instr_name = aq ? {get_instr_name, ".aq"} : + rl ? {get_instr_name, ".rl"} : get_instr_name; end return get_instr_name; endfunction diff --git a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv index 5ff6bcf4..031ef7b0 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_gen_config.sv @@ -113,6 +113,8 @@ class riscv_instr_gen_config extends uvm_object; // the testbench - testbench will take action based on the value written int signature_addr = 32'hdead_beef; bit require_signature_addr = 1'b0; + rand riscv_reg_t signature_addr_reg; + rand riscv_reg_t signature_data_reg; bit gen_debug_section = 1'b0; // Enable a full or empty debug_rom section. // Full debug_rom will contain random instruction streams. @@ -245,6 +247,9 @@ class riscv_instr_gen_config extends uvm_object; foreach(loop_regs[i]) { !(loop_regs[i] inside {default_reserved_regs}); } + !(signature_addr_reg inside {default_reserved_regs, loop_regs}); + !(signature_data_reg inside {default_reserved_regs, loop_regs}); + signature_addr_reg != signature_data_reg; } constraint legal_loop_regs_c { diff --git a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv index 30183d44..5e44ec68 100644 --- a/vendor/google_riscv-dv/src/riscv_instr_pkg.sv +++ b/vendor/google_riscv-dv/src/riscv_instr_pkg.sv @@ -17,6 +17,7 @@ package riscv_instr_pkg; import uvm_pkg::*; + import riscv_signature_pkg::*; `include "uvm_macros.svh" `include "dv_defines.svh" @@ -24,8 +25,6 @@ package riscv_instr_pkg; `define include_file(f) `include `"f`" - parameter CORE_INITIALIZATION_DONE = 2; - typedef enum bit [3:0] { BARE = 4'b0000, SV32 = 4'b0001, @@ -237,6 +236,30 @@ package riscv_instr_pkg; C_FSD, C_FLDSP, C_FSDSP, + // RV32A + LR_W, + SC_W, + AMOSWAP_W, + AMOADD_W, + AMOAND_W, + AMOOR_W, + AMOXOR_W, + AMOMIN_W, + AMOMAX_W, + AMOMINU_W, + AMOMAXU_W, + // RV64A + LR_D, + SC_D, + AMOSWAP_D, + AMOADD_D, + AMOAND_D, + AMOOR_D, + AMOXOR_D, + AMOMIN_D, + AMOMAX_D, + AMOMINU_D, + AMOMAXU_D, // Supervisor instruction MRET, URET, @@ -317,7 +340,8 @@ package riscv_instr_pkg; CSR, CHANGELEVEL, TRAP, - INTERRUPT + INTERRUPT, + AMO } riscv_instr_cateogry_t; typedef bit [11:0] riscv_csr_t; @@ -776,6 +800,7 @@ package riscv_instr_pkg; end endfunction + `include "riscv_instr_gen_config.sv" `include "riscv_illegal_instr.sv" `include "riscv_reg.sv" @@ -793,6 +818,7 @@ package riscv_instr_pkg; `include "riscv_loop_instr.sv" `include "riscv_directed_instr_lib.sv" `include "riscv_load_store_instr_lib.sv" + `include "riscv_amo_instr_lib.sv" `include "riscv_instr_sequence.sv" `include "riscv_asm_program_gen.sv" diff --git a/vendor/google_riscv-dv/src/riscv_page_table_list.sv b/vendor/google_riscv-dv/src/riscv_page_table_list.sv index 1b88b35a..4a7b35de 100644 --- a/vendor/google_riscv-dv/src/riscv_page_table_list.sv +++ b/vendor/google_riscv-dv/src/riscv_page_table_list.sv @@ -244,7 +244,7 @@ class riscv_page_table_list#(satp_mode_t MODE = SV39) extends uvm_object; // 2. For normal test, a page table fault typically means the program is accessing a large // virtual address which currently not mapped a valid physical address. Need to do a // memcpy to move data from lower physical address to the place the virtual address map to. - virtual function void gen_page_fault_handling_routine(output string instr[$]); + virtual function void gen_page_fault_handling_routine(ref string instr[$]); int unsigned level; string load_store_unit; bit[XLEN-1:0] bit_mask = '1; diff --git a/vendor/google_riscv-dv/src/riscv_rand_instr.sv b/vendor/google_riscv-dv/src/riscv_rand_instr.sv index 7a6e7a68..3ec45d3a 100644 --- a/vendor/google_riscv-dv/src/riscv_rand_instr.sv +++ b/vendor/google_riscv-dv/src/riscv_rand_instr.sv @@ -23,12 +23,23 @@ class riscv_rand_instr extends riscv_instr_base; `uvm_object_utils(riscv_rand_instr) + constraint category_c { + soft category inside {LOAD, STORE, SHIFT, ARITHMETIC, LOGICAL, + BRANCH, COMPARE, CSR, SYSTEM, SYNCH}; + } + + // Atomic extension instructions are default disabled + // AMO instruction generation is handled by riscv_amo_instr_lib.sv + constraint disable_a_extension_c { + group != RV32A; + group != RV64A; + } + constraint instr_c { solve instr_name before imm; solve instr_name before rs1; solve instr_name before rs2; !(instr_name inside {riscv_instr_pkg::unsupported_instr}); - category inside {LOAD, STORE, SHIFT, ARITHMETIC, LOGICAL, BRANCH, COMPARE, CSR, SYSTEM, SYNCH}; group inside {riscv_instr_pkg::supported_isa}; // Avoid using any special purpose register as rd, those registers are reserved for // special instructions diff --git a/vendor/google_riscv-dv/src/riscv_signature_pkg.sv b/vendor/google_riscv-dv/src/riscv_signature_pkg.sv new file mode 100644 index 00000000..45194d29 --- /dev/null +++ b/vendor/google_riscv-dv/src/riscv_signature_pkg.sv @@ -0,0 +1,54 @@ +/* + * 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. + */ + +package riscv_signature_pkg; + + // Will be the lowest 8 bits of the data word + typedef enum bit[7:0] { + // Information sent to the core relating its current status. + // Bits [12:8] of the data word will be the core_status_t value + // corresponding to the current core status. + CORE_STATUS, + // Information sent to the core conveying the uvm simulation result. + // Bit [8] of the data word will be the test_result_t value. + TEST_RESULT, + // Sent to the core to indicate a dump of GPRs to testbench. + // Will be followed by 32 writes of registers x0-x32. + WRITE_GPR, + // Sent to the core to indicate a write of a CSR's data. + // Bits [19:8] of the data word will be the CSR address. + // Will be followed by a second write of the actual data from the CSR. + WRITE_CSR + } signature_type_t; + + typedef enum bit[4:0] { + INITIALIZED, + IN_DEBUG_MODE, + IN_MACHINE_MODE, + IN_HYPERVISOR_MODE, + IN_SUPERVISOR_MODE, + IN_USER_MODE, + HANDLING_IRQ, + HANDLING_EXCEPTION + } core_status_t; + + typedef enum bit { + TEST_PASS, + TEST_FAIL + } test_result_t; + + +endpackage diff --git a/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv b/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv index 87614482..e4be2f4b 100644 --- a/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv +++ b/vendor/google_riscv-dv/test/riscv_instr_test_lib.sv @@ -14,120 +14,6 @@ * limitations under the License. */ -//================================================================================================ -// RISC-V Test Library -//------------------------------------------------------------------------------------------------ -// riscv_arithmetic_basic_test : -// - Simple arithmetic instruction test, [machine mode] -// -// riscv_machine_mode_rand_test : -// - Random instruction test, include sub-programs, branch, load/store [machine mode] -// -// riscv_privileged_mode_rand_test : -// - Similar to riscv_machine_mode_rand_test, run in supervisor mode or user mode if supported -// -// riscv_rand_instr_test : -// - A full random test, with a mix of directed instruction stream -// -// riscv_rand_jump_test : -// - Random jump among a large number of sub programs -// -// riscv_mmu_stress_test: -// - A mixed of intense load/store instructions -// -// riscv_page_table_exception_test: -// - Running test in privileged mode with page table exceptions -// -// riscv_no_fence_test -// - Random instruction with fence disabled, allow more intense instruction execution -// -// riscv_sfence_exception_test -// - Random instruction with sfence exception. sfence.vma could be excuted in non-supervisor mode -// or mstatus.tvm is set. -// -// riscv_illegal_instr_test: -// - Random instruction mixed with illegal instructions -// -// riscv_hint_instr_test: -// - Random instruction mixed with HINT instructions -// -// riscv_ebreak_test: -// - Randomly inject ebreak instruction, verify core can be halted and resumed properly -// -// riscv_wfi_test: -// - Randomly inject wfi instruction, verify core can be halted and resumed properly(by interrupt) -// -// riscv_csr_test: -// - Random instructions with CSR intruction enabled -// -// riscv_illegal_csr_test: -// - Accessing non-existence CSR or CSR with the wrong privileged mode -// -//================================================================================================ - -class riscv_arithmetic_basic_test extends riscv_instr_base_test; - - `uvm_component_utils(riscv_arithmetic_basic_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.instr_cnt = 10000; - cfg.num_of_sub_program = 0; - cfg.no_fence = 1; - cfg.no_data_page = 1'b1; - cfg.no_branch_jump = 1'b1; - `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg, - init_privileged_mode == MACHINE_MODE; - max_nested_loop == 0;) - `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", - cfg.sprint()), UVM_LOW) - endfunction - -endclass - -class riscv_machine_mode_rand_test extends riscv_instr_base_test; - - `uvm_component_utils(riscv_machine_mode_rand_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.instr_cnt = 10000; - cfg.num_of_sub_program = 5; - `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg, - init_privileged_mode == MACHINE_MODE; - max_nested_loop == 0;) - `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", - cfg.sprint()), UVM_LOW) - endfunction - - virtual function void apply_directed_instr(); - // Add load/store instruction stream - asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 10); - endfunction - -endclass - -class riscv_privileged_mode_rand_test extends riscv_instr_base_test; - - `uvm_component_utils(riscv_privileged_mode_rand_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.instr_cnt = 10000; - cfg.num_of_sub_program = 5; - `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg, - init_privileged_mode != MACHINE_MODE; - max_nested_loop == 0;) - `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", - cfg.sprint()), UVM_LOW) - endfunction - - virtual function void apply_directed_instr(); - // Add load/store instruction stream - asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 10); - endfunction - -endclass class riscv_rand_instr_test extends riscv_instr_base_test; @@ -154,142 +40,3 @@ class riscv_rand_instr_test extends riscv_instr_base_test; endfunction endclass - -class riscv_rand_jump_test extends riscv_instr_base_test; - - `uvm_component_utils(riscv_rand_jump_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.instr_cnt = 20000; - cfg.num_of_sub_program = 20; - `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg, - max_nested_loop == 1;) - `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", - cfg.sprint()), UVM_LOW) - endfunction - - virtual function void apply_directed_instr(); - asm_gen.add_directed_instr_stream("riscv_load_store_rand_instr_stream", 10); - endfunction - -endclass - -class riscv_mmu_stress_test extends riscv_instr_base_test; - - `uvm_component_utils(riscv_mmu_stress_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.instr_cnt = 500; - cfg.num_of_sub_program = 0; - `DV_CHECK_RANDOMIZE_WITH_FATAL(cfg, - max_nested_loop == 0;) - `uvm_info(`gfn, $sformatf("riscv_instr_gen_config is randomized:\n%0s", - cfg.sprint()), UVM_LOW) - endfunction - - virtual function void apply_directed_instr(); - // Mix below directed instructino streams with the random instructions - asm_gen.add_directed_instr_stream("riscv_cache_line_stress_instr_stream", 80); - asm_gen.add_directed_instr_stream("riscv_load_store_hazard_instr_stream", 80); - asm_gen.add_directed_instr_stream("riscv_multi_page_load_store_instr_stream", 80); - endfunction - -endclass - -class riscv_page_table_exception_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_page_table_exception_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.enable_page_table_exception = 1'b1; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_no_fence_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_no_fence_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.no_fence = 1'b1; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_sfence_exception_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_sfence_exception_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.allow_sfence_exception = 1'b1; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_illegal_instr_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_illegal_instr_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.enable_illegal_instruction = 1'b1; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_hint_instr_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_hint_instr_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.enable_hint_instruction = 1'b1; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_ebreak_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_ebreak_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.no_ebreak = 1'b0; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_wfi_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_wfi_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.no_wfi = 1'b0; - super.randomize_cfg(); - endfunction - -endclass - -class riscv_illegal_csr_test extends riscv_rand_instr_test; - - `uvm_component_utils(riscv_illegal_csr_test) - `uvm_component_new - - virtual function void randomize_cfg(); - cfg.enable_illegal_csr_instruction = 1'b1; - super.randomize_cfg(); - endfunction - -endclass diff --git a/vendor/google_riscv-dv/testlist b/vendor/google_riscv-dv/testlist deleted file mode 100644 index ec6f7079..00000000 --- a/vendor/google_riscv-dv/testlist +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2018 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. - -//==================================================================== -// Test name : iterations : options -//-------------------------------------------------------------------- -riscv_arithmetic_basic_test : 2 : -riscv_machine_mode_rand_test : 2 : -riscv_privileged_mode_rand_test : 2 : -riscv_rand_instr_test : 2 : -riscv_rand_jump_test : 2 : -riscv_mmu_stress_test : 2 : -riscv_page_table_exception_test : 2 : -riscv_no_fence_test : 2 : -riscv_sfence_exception_test : 2 : -riscv_illegal_instr_test : 2 : -riscv_hint_instr_test : 2 : -riscv_ebreak_test : 2 : -riscv_wfi_test : 2 : -//-------------------------------------------------------------------- diff --git a/vendor/google_riscv-dv/yaml/testlist.yaml b/vendor/google_riscv-dv/yaml/testlist.yaml index 7307b8d9..a6bd9f6e 100644 --- a/vendor/google_riscv-dv/yaml/testlist.yaml +++ b/vendor/google_riscv-dv/yaml/testlist.yaml @@ -185,7 +185,6 @@ iterations: 2 gen_test: riscv_rand_instr_test gen_opts: > - +require_signature_addr=1 +instr_cnt=6000 +no_ebreak=0 rtl_test: core_base_test @@ -195,34 +194,14 @@ 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: > - +require_signature_addr=1 - +skip_trap_handling=1 - +no_wfi=0 - rtl_test: core_base_test - sim_opts: > - +require_signature_addr=1 - +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 gen_opts: > - +require_signature_addr=1 rtl_test: core_base_test sim_opts: > - +require_signature_addr=1 +enable_irq_seq=1 compare_opts: > +compare_final_value_only=1 @@ -252,3 +231,15 @@ +directed_instr_3=riscv_multi_page_load_store_instr_stream,20 +enable_unaligned_load_store=1 rtl_test: core_ibex_base_test + +- test: riscv_amo_test + description: > + RISC-V atomic instruction extension test + iterations: 2 + gen_test: riscv_rand_instr_test + gen_opts: > + +instr_cnt=5000 + +num_of_sub_program=5 + +directed_instr_0=riscv_lr_sc_instr_stream,10 + +directed_instr_1=riscv_amo_instr_stream,10 + rtl_test: core_base_test