Integrate riscv-dv upstream changes (#107)

* Remove all local patches

* Update google_riscv-dv to 00739df

Update code from upstream repository https://github.com/google/riscv-
dv to revision 00739df0ec744986934097bebcde3ebf5a4fdf81

* Merge pull request #30 from google/dev (taoliug)
* Fix LSF options (Tao Liu)
* Refactoring to make extension easier (Tao Liu)
* Merge pull request #29 from google/dev (taoliug)
* Add a sample program (Tao Liu)
* Merge pull request #28 from google/dev (taoliug)
* Move riscv_core_setting to a separate folder (Tao Liu)
* Merge pull request #27 from google/dev (taoliug)
* Add ebreak/wfi test, more regression control (Tao Liu)
* Merge pull request #26 from google/dev (taoliug)
* Add support for GPR based comparison (Tao Liu)

* Add ibex extensions for riscv_dv
This commit is contained in:
taoliug 2019-07-01 08:59:31 -07:00 committed by GitHub
parent 08f535ebb2
commit 2d66834f14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 19812 additions and 421 deletions

View file

@ -49,7 +49,13 @@ clean:
# Generate random instructions
gen:
mkdir -p ${OUT}
cd ${GEN_DIR}; ./run -o ${OUT}/instr_gen ${GEN_OPTS};
cd ${GEN_DIR}; \
./run -o ${OUT}/instr_gen ${GEN_OPTS} \
-cmp_opts "+define+RISCV_CORE_SETTING=${DV_DIR}/riscv_dv_extension/ibex_core_setting.sv \
+define+RISCV_DV_EXT_FILE_LIST=${DV_DIR}/riscv_dv_extension/flist \
+incdir+${DV_DIR}/riscv_dv_extension/ " \
-testlist ${DV_DIR}/riscv_dv_extension/testlist \
-sim_opts "+uvm_set_type_override=riscv_asm_program_gen,ibex_asm_program_gen";
# ISS simulation
iss_sim:

View file

@ -32,7 +32,7 @@ compare_log () {
sed -i '/ecall/q' "$ibex_log"
# Convert the spike log to riscv_instr_trace.proto format
ibex_csv=$(echo "$ibex_log" | sed 's/\.log/.csv/g')
python $script_path/scripts/ibex_log_to_trace_csv.py \
python ./riscv_dv_extension/ibex_log_to_trace_csv.py \
--log $ibex_log --csv $ibex_csv >> $report_file
# -----------------------------------------------------------------------------

View file

@ -0,0 +1 @@
`include "ibex_asm_program_gen.sv"

View file

@ -0,0 +1,45 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//-----------------------------------------------------------------------------------------
// RISC-V assembly program generator for ibex
//-----------------------------------------------------------------------------------------
class ibex_asm_program_gen extends riscv_asm_program_gen;
`uvm_object_utils(ibex_asm_program_gen)
`uvm_object_new
virtual function void gen_program_header();
// Override the cfg value, below field is not supported by ibex
cfg.mstatus_mprv = 0;
cfg.mstatus_mxr = 0;
cfg.mstatus_sum = 0;
cfg.mstatus_tvm = 0;
// The ibex core load the program from 0x80
// Some address is reserved for hardware interrupt handling, need to decide if we need to copy
// the init program from crt0.S later.
instr_stream.push_back(".macro init");
instr_stream.push_back(".endm");
instr_stream.push_back(".section .text.init");
instr_stream.push_back(".globl _start");
instr_stream.push_back("j _start");
// Align the start section to 0x80
instr_stream.push_back(".align 7");
instr_stream.push_back("_start: j _reset_entry");
// ibex reserves 0x84-0x8C for trap handling, redirect everything mtvec_handler
// 0x84 illegal instruction
instr_stream.push_back(".align 2");
instr_stream.push_back("j mtvec_handler");
// 0x88 ECALL instruction handler
instr_stream.push_back(".align 2");
instr_stream.push_back("j mtvec_handler");
// 0x8C LSU error
instr_stream.push_back(".align 2");
instr_stream.push_back("j mtvec_handler");
// Starting point of the reset entry
instr_stream.push_back("_reset_entry:");
endfunction
endclass

View file

@ -0,0 +1,53 @@
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
#
# Convert ibex log to the standard trace CSV format
import argparse
import re
from riscv_trace_csv import *
def process_ibex_sim_log(ibex_log, csv):
"""Process ibex simulation log.
Extract instruction and affected register information from ibex simulation
log and save to a standard CSV format.
"""
print("Processing ibex log : %s" % ibex_log)
instr_cnt = 0
ibex_instr = ""
with open(ibex_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"^\s*(?P<time>\d+)\s+(?P<cycle>\d+) " \
"(?P<pc>[0-9a-f]+) (?P<bin>[0-9a-f]+) (?P<instr>.*)" \
"x(?P<rd>\d+)=(?P<val>[0-9a-f]+)", line)
if m:
# Write the extracted instruction to a csvcol buffer file
rv_instr_trace = RiscvInstructiontTraceEntry()
rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("rd"))
rv_instr_trace.rd_val = m.group("val")
rv_instr_trace.addr = m.group("pc")
rv_instr_trace.binary = m.group("bin")
rv_instr_trace.instr_str = m.group("instr")
trace_csv.write_trace_entry(rv_instr_trace)
#print("Processed instruction[%d] : %0s" % (instr_cnt, m.group("instr")))
instr_cnt += 1
print("Processed instruction count : %d" % instr_cnt)
instr_trace = []
# Parse input arguments
parser = argparse.ArgumentParser()
parser.add_argument("--log", type=str, help="Input ibex simulation log")
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
args = parser.parse_args()
# Process ibex log
process_ibex_sim_log(args.log, args.csv)

View file

@ -0,0 +1,21 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//====================================================================
// Test name : iterations : options
//--------------------------------------------------------------------
riscv_arithmetic_basic_test : 10 :
riscv_machine_mode_rand_test : 10 :
riscv_privileged_mode_rand_test : 0 :
riscv_rand_instr_test : 10 :
riscv_rand_jump_test : 10 :
riscv_mmu_stress_test : 10 :
riscv_page_table_exception_test : 0 :
riscv_no_fence_test : 10 :
riscv_sfence_exception_test : 0 :
riscv_illegal_instr_test : 5 :
riscv_hint_instr_test : 10 :
riscv_ebreak_test : 5 :
riscv_wfi_test : 5 :
//--------------------------------------------------------------------

View file

@ -9,6 +9,6 @@
upstream:
{
url: https://github.com/google/riscv-dv
rev: b4bd0c6cff0456111be966a11c1bd0aeec2d96e4
rev: 00739df0ec744986934097bebcde3ebf5a4fdf81
}
}

View file

@ -4,7 +4,6 @@
{
name: "google_riscv-dv",
target_dir: "google_riscv-dv",
patch_dir: "patches/google_riscv-dv",
upstream: {
url: "https://github.com/google/riscv-dv",

View file

@ -51,6 +51,20 @@ 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=0
# Testlist for regression
TEST_LIST=testlist
# Process command line options
while [[ $# -gt 0 ]]
do
@ -72,12 +86,30 @@ case $key in
SEED="$2"
shift
;;
-sim_opts)
SIM_OPTS="$2"
shift
;;
-cmp_opts)
CMP_OPTS="$2"
shift
;;
-testlist)
TEST_LIST="$2"
shift
;;
-so)
SIM_ONLY=1
;;
-verbose)
VERBOSE=1
;;
-co)
CMP_ONLY=1
;;
-lsf)
LSF=1
;;
-o)
OUT="$2"
shift
@ -90,6 +122,12 @@ esac
shift
done
if [[ $LSF == 0 ]]; then
LSF_CMD=""
fi
OUT=`realpath ${OUT}`
# Generate compile and simulation commands
if [[ "$SIMULATOR" == "vcs" ]]; then
@ -97,7 +135,7 @@ if [[ "$SIMULATOR" == "vcs" ]]; then
-f ./files.f -full64 \
-l $OUT/compile.log \
-Mdir=$OUT/vcs_simv.csrc \
-o $OUT/vcs_simv"
-o $OUT/vcs_simv ${CMP_OPTS}"
SIM_CMD="$OUT/vcs_simv +UVM_TESTNAME="
@ -109,7 +147,7 @@ elif [[ "$SIMULATOR" == "irun" ]]; then
-q -sv -uvm \
-vlog_ext +.vh -I. \
-uvmhome CDNS-1.2 \
-l ${OUT}/compile.log"
-l ${OUT}/compile.log ${CMP_OPTS}"
SIM_CMD="irun -R +UVM_TESTNAME="
@ -121,6 +159,8 @@ fi
# Clean up previous runs
if [[ $SIM_ONLY == 0 ]]; then
rm -rf ${OUT}
else
rm -rf ${OUT}/asm_tests
fi
mkdir -p ${OUT}
@ -128,7 +168,13 @@ mkdir -p ${OUT}/asm_tests
# Compilation
if [[ $SIM_ONLY == 0 ]]; then
${COMPILE_CMD}
echo "Building RISC-V instruction generator..."
if [[ $VERBOSE == 1 ]]; then
${COMPILE_CMD}
else
${COMPILE_CMD} > /dev/null
fi
echo "Building RISC-V instruction generator...done"
fi
# Skip simulation if compilation only flag is set
@ -138,31 +184,70 @@ fi
# Run sim
if [[ ${TEST} == "all" ]]; then
echo "Running regression with testlist:"
cat testlist
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]*) ]]; then
if [[ $line =~([a-z0-9_-]*)([[:space:]]*)\:([[:space:]]*)([0-9]*)([[:space:]]*)\:(.*$) ]]; then
SEED=`date +%s`
TEST=${BASH_REMATCH[1]}
ITERATION=${BASH_REMATCH[4]}
echo "Running ${TEST}, iteration count: ${ITERATION}"
if ! [[ $ITERATION == "0" ]]; then
${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
+ntb_random_seed=${SEED} \
-l ${OUT}/sim_${TEST}.log +num_of_tests=${ITERATION}
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} \
+ntb_random_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} ${CMD}
else
${LSF_CMD} ${CMD} > /dev/null
fi
fi
fi
fi
done < testlist
done < $TEST_LIST
# Wait util all tests are generated
if [[ $LSF == 1 ]]; then
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))
fi
fi
done < ${LOG_LIST}
GENERATED_CNT=`find ${OUT}/asm_tests/ -name "*.S" | wc -l`
echo "Progress > Test:${COMPLETED_CNT}/${TOTAL_CNT} Program:${GENERATED_CNT}/${PROGRAM_CNT}"
if [[ "$COMPLETED_CNT" == "$TOTAL_CNT" ]]; then
break
else
sleep 10
fi
done
fi
else
echo "Running test ${TEST} with $SIMULATOR.."
${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
echo "Running test ${TEST} to generate ${NUM_TESTS} tests"
CMD="${SIM_CMD}${TEST} +asm_file_name=${OUT}/asm_tests/${TEST} \
+ntb_random_seed=${SEED} \
-l ${OUT}/sim_${TEST}.log \
+num_of_tests=${NUM_TESTS}
+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"

19195
vendor/google_riscv-dv/sample/sample.S vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,53 +0,0 @@
"""
Copyright lowRISC contributors.
Licensed under the Apache License, Version 2.0, see LICENSE for details.
SPDX-License-Identifier: Apache-2.0
Convert ibex log to the standard trace CSV format
"""
import re
import argparse
from riscv_trace_csv import *
def process_ibex_sim_log(ibex_log, csv):
"""Process ibex simulation log.
Extract instruction and affected register information from ibex simulation
log and save to a standard CSV format.
"""
print("Processing ibex log : %s" % ibex_log)
instr_cnt = 0
ibex_instr = ""
with open(ibex_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"^\s*(?P<time>\d+)\s+(?P<cycle>\d+) " \
"(?P<pc>[0-9a-f]+) (?P<bin>[0-9a-f]+) (?P<instr>.*)" \
"x(?P<rd>\d+)=(?P<val>[0-9a-f]+)", line)
if m:
# Write the extracted instruction to a csvcol buffer file
rv_instr_trace = RiscvInstructiontTraceEntry()
rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("rd"))
rv_instr_trace.rd_val = m.group("val")
rv_instr_trace.addr = m.group("pc")
rv_instr_trace.binary = m.group("bin")
rv_instr_trace.instr_str = m.group("instr")
trace_csv.write_trace_entry(rv_instr_trace)
#print("Processed instruction[%d] : %0s" % (instr_cnt, m.group("instr")))
instr_cnt += 1
print("Processed instruction count : %d" % instr_cnt)
instr_trace = []
# Parse input arguments
parser = argparse.ArgumentParser()
parser.add_argument("--log", type=str, help="Input ibex simulation log")
parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
args = parser.parse_args()
# Process ibex log
process_ibex_sim_log(args.log, args.csv)

View file

@ -13,19 +13,19 @@ 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 ovpsim sim log to standard riscv instruction trace format
Compare the instruction trace CSV
"""
import re
import argparse
from riscv_trace_csv import *
def compare_trace_csv(csv1, csv2, name1, name2):
def compare_trace_csv(csv1, csv2, name1, name2,
in_order_mode, coalescing_limit, verbose,
mismatch_print_limit, compare_final_value_only):
"""Compare two trace CSV file"""
matched_cnt = 0
mismatch_cnt = 0
gpr_val_1 = {}
gpr_val_2 = {}
with open(csv1, "r") as fd1, open(csv2, "r") as fd2:
instr_trace_1 = []
@ -36,60 +36,127 @@ def compare_trace_csv(csv1, csv2, name1, name2):
trace_csv_2.read_trace(instr_trace_2)
trace_1_index = 0
trace_2_index = 0
for trace in instr_trace_1:
trace_1_index += 1
# 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:
continue
# 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)
trace_2_index += 1
# Check if the GPR update is the same between trace 1 and 2
if gpr_state_change_2 == 0:
mismatch_cnt += 1
print("Mismatch[%d]:\n[%d] %s : %s -> %s(0x%s) addr:0x%s" %
(mismatch_cnt, trace_1_index, name1, trace.instr_str, trace.rd,
trace.rd_val, trace.addr))
print ("%0d instructions left in trace %0s" %
(len(instr_trace_1) - trace_1_index + 1, name1))
elif (trace.rd != instr_trace_2[trace_2_index-1].rd or
trace.rd_val != instr_trace_2[trace_2_index-1].rd_val):
mismatch_cnt += 1
# print first 5 mismatches
if mismatch_cnt <= 5:
print("Mismatch[%d]:\n[%d] %s : %s -> %s(0x%s) addr:0x%s" %
(mismatch_cnt, trace_2_index - 1, name1, trace.instr_str,
trace.rd, trace.rd_val, trace.addr))
print("[%d] %s : %s -> %s(0x%s) addr:0x%s" %
(trace_2_index - 1, name2,
instr_trace_2[trace_2_index-1].instr_str,
instr_trace_2[trace_2_index-1].rd,
instr_trace_2[trace_2_index-1].rd_val,
instr_trace_2[trace_2_index-1].addr))
else:
matched_cnt += 1
# Break the loop if it reaches the end of trace 2
if trace_2_index == len(instr_trace_2):
break
# Check if there's remaining instruction that change architectural state
if trace_2_index != len(instr_trace_2):
while (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 gpr_state_change_2 == 1:
mismatch_cnt = 0
matched_cnt = 0
if in_order_mode:
gpr_val_1 = {}
gpr_val_2 = {}
for trace in instr_trace_1:
trace_1_index += 1
# 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:
continue
# 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)
trace_2_index += 1
# Check if the GPR update is the same between trace 1 and 2
if gpr_state_change_2 == 0:
mismatch_cnt += 1
print("Mismatch[%d]:\n[%d] %s : %s" %
(mismatch_cnt, trace_1_index, name1, trace.get_trace_string()))
print ("%0d instructions left in trace %0s" %
(len(instr_trace_2) - trace_2_index, name2))
mismatch_cnt += len(instr_trace_2) - trace_2_index
(len(instr_trace_1) - trace_1_index + 1, name1))
elif (trace.rd != instr_trace_2[trace_2_index-1].rd or
trace.rd_val != instr_trace_2[trace_2_index-1].rd_val):
mismatch_cnt += 1
# print first few mismatches
if mismatch_cnt <= mismatch_print_limit:
print("Mismatch:\n%s[%d] : %s" %
(mismatch_cnt, name1, trace_2_index - 1,
trace.get_trace_string()))
print("%s[%d] : %s" %
(name2, trace_2_index - 1,
instr_trace_2[trace_2_index-1].get_trace_string()))
else:
matched_cnt += 1
# Break the loop if it reaches the end of trace 2
if trace_2_index == len(instr_trace_2):
break
trace_2_index += 1
# Check if there's remaining instruction that change architectural state
if trace_2_index != len(instr_trace_2):
while (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 gpr_state_change_2 == 1:
print ("%0d instructions left in trace %0s" %
(len(instr_trace_2) - trace_2_index, name2))
mismatch_cnt += len(instr_trace_2) - trace_2_index
break
trace_2_index += 1
else:
# For processors which can commit multiple instructions in one cycle, the
# ordering between different GPR update on that cycle could be
# non-deterministic. If multiple instructions try to update the same GPR on
# the same cycle, these updates could be coalesced to one update.
gpr_trace_1 = {}
gpr_trace_2 = {}
parse_gpr_update_from_trace(instr_trace_1, gpr_trace_1)
parse_gpr_update_from_trace(instr_trace_2, gpr_trace_2)
if len(gpr_trace_1) != len(gpr_trace_2):
print("Mismatch: affected GPR count mismtach %s:%d VS %s:%d" %
(name1, len(gpr_trace_1), name2, len(gpr_trace_2)))
mismatch_cnt += 1
if not compare_final_value_only:
for gpr in gpr_trace_1:
coalesced_updates = 0
if (len(gpr_trace_1[gpr]) != len(gpr_trace_2[gpr]) and
coalescing_limit == 0):
print("Mismatch: GPR[%s] trace count mismtach %s:%d VS %s:%d" %
(gpr, name1, len(gpr_trace_1[gpr]),
name2, len(gpr_trace_2[gpr])))
mismatch_cnt += 1
trace_2_index = 0
coalesced_updates = 0
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 coalesced_updates >= coalescing_limit:
coalesced_updates = 0
mismatch_cnt += 1
if mismatch_cnt <= mismatch_print_limit:
print("Mismatch:")
print("%s[%d] : %s" % (name1, trace_1_index,
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
print("%s[%d] : %s" % (name2, trace_2_index,
gpr_trace_2[gpr][trace_2_index].get_trace_string()))
trace_2_index += 1
else:
if verbose:
print("Skipping %s[%d] : %s" %
(name1, trace_1_index,
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
coalesced_updates += 1
else:
coalesced_updates = 0
matched_cnt += 1
if verbose:
print("Matched [%0d]: %s : %s" %
(trace_1_index, name1,
gpr_trace_1[gpr][trace_1_index].get_trace_string()))
trace_2_index += 1
# Check the final value match between the two traces
for gpr in gpr_trace_1:
if (len(gpr_trace_1[gpr]) == 0 or len(gpr_trace_2[gpr]) == 0):
mismatch_cnt += 1
print("Zero GPR[%s] updates observed: %s:%d, %s:%d" % (gpr,
name1, len(gpr_trace_1[gpr]), name2, len(gpr_trace_2[gpr])))
elif long(gpr_trace_1[gpr][-1].rd_val, 16) != \
long(gpr_trace_2[gpr][-1].rd_val, 16):
mismatch_cnt += 1
if mismatch_cnt <= mismatch_print_limit:
print("Mismatch final value:")
print("%s : %s" % (name1, gpr_trace_1[gpr][-1].get_trace_string()))
print("%s : %s" % (name2, gpr_trace_2[gpr][-1].get_trace_string()))
if mismatch_cnt == 0:
compare_result = "PASSED"
else:
@ -98,6 +165,17 @@ def compare_trace_csv(csv1, csv2, name1, name2):
(compare_result, matched_cnt, mismatch_cnt))
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
def check_update_gpr(rd, rd_val, gpr):
gpr_state_change = 0
if rd in gpr:
@ -116,7 +194,28 @@ parser.add_argument("csv_file_1", type=str, help="Instruction trace 1 CSV")
parser.add_argument("csv_file_2", type=str, help="Instruction trace 2 CSV")
parser.add_argument("csv_name_1", type=str, help="Instruction trace 1 name")
parser.add_argument("csv_name_2", type=str, help="Instruction trace 2 name")
# optional arguments
parser.add_argument("--in_order_mode", type=int, default=0,
help="In order comparison mode")
parser.add_argument("--gpr_update_coalescing_limit", type=int, default=1,
help="Allow the core to merge multiple updates to the \
same GPR into one. This option only applies to \
trace 2")
parser.add_argument("--mismatch_print_limit", type=int, default=5,
help="Max number of mismatches printed")
parser.add_argument("--verbose", type=int, default=0,
help="Verbose logging")
parser.add_argument("--compare_final_value_only", type=int, default=0,
help="Only compare the final value of the GPR")
args = parser.parse_args()
# Process ovpsim csv
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.csv_name_1, args.csv_name_2,
args.in_order_mode, args.gpr_update_coalescing_limit,
args.verbose, args.mismatch_print_limit,
args.compare_final_value_only)

View file

@ -34,6 +34,11 @@ class RiscvInstructiontTraceEntry(object):
self.instr_str = ""
self.privileged_mode = ""
def get_trace_string(self):
"""Return a short string of the trace entry"""
return ("%s -> %s(0x%s) addr:0x%s" %
(self.instr_str, self.rd, self.rd_val, self.addr))
class RiscvInstructiontTraceCsv(object):
"""RISC-V instruction trace CSV class
@ -73,6 +78,7 @@ class RiscvInstructiontTraceCsv(object):
'binary' : entry.binary,
'addr' : entry.addr})
def gpr_to_abi(gpr):
"""Convert a general purpose register to its corresponding abi name"""
switcher = {

View file

@ -0,0 +1,128 @@
/*
* Copyright 2019 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//-----------------------------------------------------------------------------
// Processor feature configuration
//-----------------------------------------------------------------------------
// XLEN
parameter int XLEN = 64;
// Parameter for SATP mode, set to BARE if address translation is not supported
parameter satp_mode_t SATP_MODE = SV39;
// Supported Privileged mode
privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MACHINE_MODE};
// Unsupported instructions
riscv_instr_name_t unsupported_instr[];
// ISA supported by the processor
riscv_instr_group_t supported_isa[$] = {RV32I, RV32M, RV64I, RV64M, RV32C, RV64C};
// Support delegate trap to user mode
bit support_umode_trap = 0;
// Support sfence.vma instruction
bit support_sfence = 1;
// Cache line size (in bytes)
// If processor does not support caches, set to XLEN/8
int dcache_line_size_in_bytes = 128;
// Number of data section
// For processor that doesn't have data TLB, this can be set to 1
// For processor that supports data TLB, this should be set to be larger than the number
// of entries of dTLB to cover dTLB hit/miss scenario
int num_of_data_pages = 40;
// Data section byte size
// For processor with no dTLB and data cache, keep the value below 10K
// For processor with dTLB support, set it to the physical memory size that covers one entry
// of the dTLB
int data_page_size = 4096;
int data_page_alignment = $clog2(data_page_size);
// The maximum data section byte size actually used by load/store instruction
// Set to this value to be smaller than data_page_size. If there's data cache in the system,
// this value should be set large enough to be able to hit cache hit/miss scenario within a data
// section. Don't set this to too big as it will introduce a very large binary.
int max_used_data_page_size = 512;
// Stack section word length
int stack_len = 5000;
//-----------------------------------------------------------------------------
// Kernel section setting, used by supervisor mode programs
//-----------------------------------------------------------------------------
// Number of kernel data pages
int num_of_kernel_data_pages = 5;
// Byte size of kernel data pages
int kernel_data_page_size = 4096;
// Kernel Stack section word length
int kernel_stack_len = 5000;
// Number of instructions for each kernel program
int kernel_program_instr_cnt = 400;
// ----------------------------------------------------------------------------
// Previleged CSR implementation
// ----------------------------------------------------------------------------
// Implemented previlieged CSR list
privileged_reg_t implemented_csr[$] = {
// User mode CSR
USTATUS, // User status
UIE, // User interrupt-enable register
UTVEC, // User trap-handler base address
USCRATCH, // Scratch register for user trap handlers
UEPC, // User exception program counter
UCAUSE, // User trap cause
UTVAL, // User bad address or instruction
UIP, // User interrupt pending
// Supervisor mode CSR
SSTATUS, // Supervisor status
SEDELEG, // Supervisor exception delegation register
SIDELEG, // Supervisor interrupt delegation register
SIE, // Supervisor interrupt-enable register
STVEC, // Supervisor trap-handler base address
SCOUNTEREN, // Supervisor counter enable
SSCRATCH, // Scratch register for supervisor trap handlers
SEPC, // Supervisor exception program counter
SCAUSE, // Supervisor trap cause
STVAL, // Supervisor bad address or instruction
SIP, // Supervisor interrupt pending
SATP, // Supervisor address translation and protection
// Machine mode mode CSR
MVENDORID, // Vendor ID
MARCHID, // Architecture ID
MIMPID, // Implementation ID
MHARTID, // Hardware thread ID
MSTATUS, // Machine status
MISA, // ISA and extensions
MEDELEG, // Machine exception delegation register
MIDELEG, // Machine interrupt delegation register
MIE, // Machine interrupt-enable register
MTVEC, // Machine trap-handler base address
MCOUNTEREN, // Machine counter enable
MSCRATCH, // Scratch register for machine trap handlers
MEPC, // Machine exception program counter
MCAUSE, // Machine trap cause
MTVAL, // Machine bad address or instruction
MIP // Machine interrupt pending
};

View file

@ -244,36 +244,11 @@ class riscv_asm_program_gen extends uvm_object;
//---------------------------------------------------------------------------------------
virtual function void gen_program_header();
// ------------- IBEX modification start --------------------
// Override the cfg value, below field is not supported by ibex
cfg.mstatus_mprv = 0;
cfg.mstatus_mxr = 0;
cfg.mstatus_sum = 0;
cfg.mstatus_tvm = 0;
// The ibex core load the program from 0x80
// Some address is reserved for hardware interrupt handling, need to decide if we need to copy
// the init program from crt0.S later.
instr_stream.push_back(".macro init");
instr_stream.push_back(".endm");
instr_stream.push_back(".section .text.init");
instr_stream.push_back(".globl _start");
instr_stream.push_back("j _start");
// Align the start section to 0x80
instr_stream.push_back(".align 7");
instr_stream.push_back("_start: j _reset_entry");
// ibex reserves 0x84-0x8C for trap handling, redirect everything mtvec_handler
// 0x84 illegal instruction
instr_stream.push_back(".align 2");
instr_stream.push_back("j mtvec_handler");
// 0x88 ECALL instruction handler
instr_stream.push_back(".align 2");
instr_stream.push_back("j mtvec_handler");
// 0x8C LSU error
instr_stream.push_back(".align 2");
instr_stream.push_back("j mtvec_handler");
// Starting point of the reset entry
instr_stream.push_back("_reset_entry:");
// ------------- IBEX modification end --------------------
instr_stream.push_back("_start:");
endfunction
virtual function void gen_program_end();
@ -554,6 +529,8 @@ class riscv_asm_program_gen extends uvm_object;
gen_trap_handler_section("u", UCAUSE, UTVEC, UTVAL, UEPC, USCRATCH, USTATUS);
endcase
end
// Ebreak handler
gen_ebreak_handler();
// Ecall handler
gen_ecall_handler();
// Illegal instruction handler
@ -595,6 +572,9 @@ class riscv_asm_program_gen extends uvm_object;
$sformatf("csrr a1, 0x%0x # %0s", cause, cause.name()),
$sformatf("csrr x31, 0x%0x # %0s", epc, epc.name()),
$sformatf("csrr x29, 0x%0x # %0s", status, status.name()),
// Breakpoint
$sformatf("li a2, 0x%0x # BREAKPOINT", BREAKPOINT),
"beq a1, a2, ebreak_handler",
// Check if it's an ECALL exception. Jump to ECALL exception handler
$sformatf("li a2, 0x%0x # ECALL_UMODE", ECALL_UMODE),
"beq a1, a2, ecall_handler",
@ -645,6 +625,24 @@ class riscv_asm_program_gen extends uvm_object;
instr_stream.push_back(str);
endfunction
// Ebreak trap handler
// When breakpoint exception happens, epc will be written with ebreak instruction
// itself. Add epc by 4 and resume execution.
// Note the breakpoint could be triggered by a C.EBREAK instruction, the generated program
// guarantees that epc + 4 is a valid instruction boundary
// 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"
};
pop_gpr_from_kernel_stack(MSTATUS, MSCRATCH, cfg.mstatus_mprv, instr);
instr.push_back("mret");
gen_section("ebreak_handler", instr);
endfunction
// Illegal instruction handler
// Note: Save the illegal instruction to MTVAL is optional in the spec, and mepc could be
// a virtual address that cannot be used in machine mode handler. As a result, there's no way to
@ -652,7 +650,6 @@ 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 str;
string instr[$] = {
"csrr x31, mepc",
"addi x31, x31, 4",

View file

@ -458,6 +458,14 @@ class riscv_instr_base extends uvm_object;
CJ_FORMAT:
asm_str = $sformatf("%0s%0s", asm_str, get_imm());
endcase
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
if(instr_name == EBREAK) begin
asm_str = ".option norvc;ebreak;.option rvc;";
end else if(instr_name == C_EBREAK) begin
asm_str = "c.ebreak;c.nop;";
end
end
if(comment != "")
asm_str = {asm_str, " #",comment};

View file

@ -72,6 +72,7 @@ class riscv_instr_gen_config extends uvm_object;
bit no_csr_instr = 1; // No csr instruction
bit no_ebreak = 1; // No ebreak instruction
bit no_fence; // No fence instruction
bit no_wfi = 1; // No WFI instruction
bit enable_illegal_instruction;
bit enable_hint_instruction;
int bin_program_instr_cnt = 200;
@ -226,6 +227,7 @@ class riscv_instr_gen_config extends uvm_object;
get_int_arg_value("+num_of_sub_program=", num_of_sub_program);
get_int_arg_value("+instr_cnt=", instr_cnt);
get_bool_arg_value("+no_ebreak=", no_ebreak);
get_bool_arg_value("+no_wfi=", no_wfi);
get_bool_arg_value("+no_branch_jump=", no_branch_jump);
get_bool_arg_value("+no_load_store=", no_load_store);
get_bool_arg_value("+no_csr_instr=", no_csr_instr);

View file

@ -22,6 +22,8 @@ package riscv_instr_pkg;
`include "dv_defines.svh"
`include "riscv_defines.svh"
`define include_file(f) `include "``f``"
typedef enum bit [3:0] {
BARE = 4'b0000,
SV32 = 4'b0001,
@ -613,7 +615,11 @@ package riscv_instr_pkg;
STORE_AMO_PAGE_FAULT = 4'hF
} exception_cause_t;
`include "riscv_core_setting.sv"
`ifndef RISCV_CORE_SETTING
`define RISCV_CORE_SETTING ../setting/riscv_core_setting.sv
`endif
`include_file(`RISCV_CORE_SETTING)
typedef bit [15:0] program_id_t;
@ -754,4 +760,8 @@ package riscv_instr_pkg;
`include "riscv_instr_sequence.sv"
`include "riscv_asm_program_gen.sv"
`ifdef RISCV_DV_EXT_FILE_LIST
`include_file(`RISCV_DV_EXT_FILE_LIST)
`endif
endpackage

View file

@ -79,8 +79,11 @@ class riscv_rand_instr extends riscv_instr_base;
instr_name != EBREAK;
instr_name != C_EBREAK;
}
if(cfg.no_wfi) {
instr_name != WFI;
}
// Below previleged instruction is not generated by default
!(instr_name inside {ECALL, WFI, URET, SRET, MRET});
!(instr_name inside {ECALL, URET, SRET, MRET});
if(cfg.no_load_store) {
category != LOAD;
category != STORE;

View file

@ -59,6 +59,7 @@ class riscv_instr_base_test extends uvm_test;
end else begin
`uvm_info("", "TEST FAILED", UVM_NONE);
end
`uvm_info("", "TEST GENERATION DONE", UVM_NONE);
super.report_phase(phase);
endfunction

View file

@ -51,6 +51,12 @@
// 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_privileged_csr_test:
// - To be released soon
//
@ -248,3 +254,27 @@ class riscv_hint_instr_test extends riscv_rand_instr_test;
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

View file

@ -12,18 +12,20 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//================================================
// Test name : iteration count
//------------------------------------------------
riscv_arithmetic_basic_test : 10
riscv_machine_mode_rand_test : 10
riscv_privileged_mode_rand_test : 0
riscv_rand_instr_test : 10
riscv_rand_jump_test : 10
riscv_mmu_stress_test : 10
riscv_page_table_exception_test : 0
riscv_no_fence_test : 10
riscv_sfence_exception_test : 0
riscv_illegal_instr_test : 1
riscv_hint_instr_test : 10
//------------------------------------------------
//====================================================================
// 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 :
//--------------------------------------------------------------------

View file

@ -1,247 +0,0 @@
diff --git a/scripts/ibex_log_to_trace_csv.py b/scripts/ibex_log_to_trace_csv.py
new file mode 100644
index 0000000..34036bb
--- /dev/null
+++ b/scripts/ibex_log_to_trace_csv.py
@@ -0,0 +1,53 @@
+"""
+Copyright lowRISC contributors.
+Licensed under the Apache License, Version 2.0, see LICENSE for details.
+SPDX-License-Identifier: Apache-2.0
+
+Convert ibex log to the standard trace CSV format
+"""
+
+import re
+import argparse
+
+from riscv_trace_csv import *
+
+def process_ibex_sim_log(ibex_log, csv):
+ """Process ibex simulation log.
+
+ Extract instruction and affected register information from ibex simulation
+ log and save to a standard CSV format.
+ """
+ print("Processing ibex log : %s" % ibex_log)
+ instr_cnt = 0
+ ibex_instr = ""
+
+ with open(ibex_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"^\s*(?P<time>\d+)\s+(?P<cycle>\d+) " \
+ "(?P<pc>[0-9a-f]+) (?P<bin>[0-9a-f]+) (?P<instr>.*)" \
+ "x(?P<rd>\d+)=(?P<val>[0-9a-f]+)", line)
+ if m:
+ # Write the extracted instruction to a csvcol buffer file
+ rv_instr_trace = RiscvInstructiontTraceEntry()
+ rv_instr_trace.rd = gpr_to_abi("x%0s" % m.group("rd"))
+ rv_instr_trace.rd_val = m.group("val")
+ rv_instr_trace.addr = m.group("pc")
+ rv_instr_trace.binary = m.group("bin")
+ rv_instr_trace.instr_str = m.group("instr")
+ trace_csv.write_trace_entry(rv_instr_trace)
+ #print("Processed instruction[%d] : %0s" % (instr_cnt, m.group("instr")))
+ instr_cnt += 1
+
+ print("Processed instruction count : %d" % instr_cnt)
+
+instr_trace = []
+# Parse input arguments
+parser = argparse.ArgumentParser()
+parser.add_argument("--log", type=str, help="Input ibex simulation log")
+parser.add_argument("--csv", type=str, help="Output trace csv_buf file")
+args = parser.parse_args()
+# Process ibex log
+process_ibex_sim_log(args.log, args.csv)
diff --git a/src/riscv_asm_program_gen.sv b/src/riscv_asm_program_gen.sv
index b538b72..2f9f28f 100644
--- a/src/riscv_asm_program_gen.sv
+++ b/src/riscv_asm_program_gen.sv
@@ -244,11 +244,36 @@ class riscv_asm_program_gen extends uvm_object;
//---------------------------------------------------------------------------------------
virtual function void gen_program_header();
+ // ------------- IBEX modification start --------------------
+ // Override the cfg value, below field is not supported by ibex
+ cfg.mstatus_mprv = 0;
+ cfg.mstatus_mxr = 0;
+ cfg.mstatus_sum = 0;
+ cfg.mstatus_tvm = 0;
+ // The ibex core load the program from 0x80
+ // Some address is reserved for hardware interrupt handling, need to decide if we need to copy
+ // the init program from crt0.S later.
instr_stream.push_back(".macro init");
instr_stream.push_back(".endm");
instr_stream.push_back(".section .text.init");
instr_stream.push_back(".globl _start");
- instr_stream.push_back("_start:");
+ instr_stream.push_back("j _start");
+ // Align the start section to 0x80
+ instr_stream.push_back(".align 7");
+ instr_stream.push_back("_start: j _reset_entry");
+ // ibex reserves 0x84-0x8C for trap handling, redirect everything mtvec_handler
+ // 0x84 illegal instruction
+ instr_stream.push_back(".align 2");
+ instr_stream.push_back("j mtvec_handler");
+ // 0x88 ECALL instruction handler
+ instr_stream.push_back(".align 2");
+ instr_stream.push_back("j mtvec_handler");
+ // 0x8C LSU error
+ instr_stream.push_back(".align 2");
+ instr_stream.push_back("j mtvec_handler");
+ // Starting point of the reset entry
+ instr_stream.push_back("_reset_entry:");
+ // ------------- IBEX modification end --------------------
endfunction
virtual function void gen_program_end();
diff --git a/src/riscv_core_setting.sv b/src/riscv_core_setting.sv
index 75c5821..0175d2f 100644
--- a/src/riscv_core_setting.sv
+++ b/src/riscv_core_setting.sv
@@ -18,25 +18,27 @@
// Processor feature configuration
//-----------------------------------------------------------------------------
// XLEN
-parameter int XLEN = 64;
+parameter int XLEN = 32;
// Parameter for SATP mode, set to BARE if address translation is not supported
-parameter satp_mode_t SATP_MODE = SV39;
+parameter satp_mode_t SATP_MODE = BARE;
// Supported Privileged mode
-privileged_mode_t supported_privileged_mode[] = {USER_MODE, SUPERVISOR_MODE, MACHINE_MODE};
+privileged_mode_t supported_privileged_mode[] = {MACHINE_MODE};
// Unsupported instructions
-riscv_instr_name_t unsupported_instr[];
+// Avoid generating these instructions in regular regression
+// FENCE.I is intentionally treated as illegal instruction by ibex core
+riscv_instr_name_t unsupported_instr[] = {FENCEI};
// 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, RV32C};
// Support delegate trap to user mode
bit support_umode_trap = 0;
// Support sfence.vma instruction
-bit support_sfence = 1;
+bit support_sfence = 0;
// Cache line size (in bytes)
// If processor does not support caches, set to XLEN/8
@@ -46,7 +48,7 @@ int dcache_line_size_in_bytes = 128;
// For processor that doesn't have data TLB, this can be set to 1
// For processor that supports data TLB, this should be set to be larger than the number
// of entries of dTLB to cover dTLB hit/miss scenario
-int num_of_data_pages = 40;
+int num_of_data_pages = 4;
// Data section byte size
// For processor with no dTLB and data cache, keep the value below 10K
@@ -55,12 +57,6 @@ int num_of_data_pages = 40;
int data_page_size = 4096;
int data_page_alignment = $clog2(data_page_size);
-// The maximum data section byte size actually used by load/store instruction
-// Set to this value to be smaller than data_page_size. If there's data cache in the system,
-// this value should be set large enough to be able to hit cache hit/miss scenario within a data
-// section. Don't set this to too big as it will introduce a very large binary.
-int max_used_data_page_size = 512;
-
// Stack section word length
int stack_len = 5000;
@@ -69,7 +65,7 @@ int stack_len = 5000;
//-----------------------------------------------------------------------------
// Number of kernel data pages
-int num_of_kernel_data_pages = 5;
+int num_of_kernel_data_pages = 2;
// Byte size of kernel data pages
int kernel_data_page_size = 4096;
@@ -86,43 +82,15 @@ int kernel_program_instr_cnt = 400;
// Implemented previlieged CSR list
privileged_reg_t implemented_csr[$] = {
- // User mode CSR
- USTATUS, // User status
- UIE, // User interrupt-enable register
- UTVEC, // User trap-handler base address
- USCRATCH, // Scratch register for user trap handlers
- UEPC, // User exception program counter
- UCAUSE, // User trap cause
- UTVAL, // User bad address or instruction
- UIP, // User interrupt pending
- // Supervisor mode CSR
- SSTATUS, // Supervisor status
- SEDELEG, // Supervisor exception delegation register
- SIDELEG, // Supervisor interrupt delegation register
- SIE, // Supervisor interrupt-enable register
- STVEC, // Supervisor trap-handler base address
- SCOUNTEREN, // Supervisor counter enable
- SSCRATCH, // Scratch register for supervisor trap handlers
- SEPC, // Supervisor exception program counter
- SCAUSE, // Supervisor trap cause
- STVAL, // Supervisor bad address or instruction
- SIP, // Supervisor interrupt pending
- SATP, // Supervisor address translation and protection
// Machine mode mode CSR
MVENDORID, // Vendor ID
MARCHID, // Architecture ID
- MIMPID, // Implementation ID
MHARTID, // Hardware thread ID
MSTATUS, // Machine status
MISA, // ISA and extensions
- MEDELEG, // Machine exception delegation register
- MIDELEG, // Machine interrupt delegation register
- MIE, // Machine interrupt-enable register
MTVEC, // Machine trap-handler base address
- MCOUNTEREN, // Machine counter enable
- MSCRATCH, // Scratch register for machine trap handlers
MEPC, // Machine exception program counter
MCAUSE, // Machine trap cause
- MTVAL, // Machine bad address or instruction
- MIP // Machine interrupt pending
+ MTVAL // Machine bad address or instruction
+ // TODO: Add performance CSRs and debug mode CSR
};
diff --git a/testlist b/testlist
index 123951e..0fd4e31 100644
--- a/testlist
+++ b/testlist
@@ -15,15 +15,15 @@
//================================================
// Test name : iteration count
//------------------------------------------------
-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 : 1
-riscv_hint_instr_test : 1
+riscv_arithmetic_basic_test : 10
+riscv_machine_mode_rand_test : 10
+riscv_privileged_mode_rand_test : 0
+riscv_rand_instr_test : 10
+riscv_rand_jump_test : 10
+riscv_mmu_stress_test : 10
+riscv_page_table_exception_test : 0
+riscv_no_fence_test : 10
+riscv_sfence_exception_test : 0
+riscv_illegal_instr_test : 1
+riscv_hint_instr_test : 10
//------------------------------------------------