Add medeleg tests

This commit is contained in:
Domenico Ottolia 2021-04-29 15:02:36 -04:00
parent 246b41e604
commit 99a927be47
5 changed files with 390 additions and 43 deletions

View File

@ -30,34 +30,43 @@ vlib work
# default to config/rv64ic, but allow this to be overridden at the command line. For example: # default to config/rv64ic, but allow this to be overridden at the command line. For example:
# do wally-pipelined.do ../config/rv32ic # do wally-pipelined.do ../config/rv32ic
switch $argc { switch $argc {
0 {vlog +incdir+../config/rv64ic ../testbench/testbench-privileged.sv ../src/*/*.sv -suppress 2583} 0 {vlog +incdir+../config/rv64ic ../testbench/testbench-imperas.sv ../src/*/*.sv -suppress 2583}
1 {vlog +incdir+$1 ../testbench/testbench-privileged.sv ../testbench/function_radix.sv ../src/*/*.sv -suppress 2583} 1 {vlog +incdir+$1 ../testbench/testbench-imperas.sv ../testbench/function_radix.sv ../src/*/*.sv -suppress 2583}
} }
# start and run simulation # start and run simulation
# remove +acc flag for faster sim during regressions if there is no need to access internal signals # remove +acc flag for faster sim during regressions if there is no need to access internal signals
vopt +acc work.testbench -o workopt vopt +acc work.testbench -o workopt
vsim workopt vsim workopt
view wave view wave
-- display input and output signals as hexidecimal values -- display input and output signals as hexidecimal values
do ./wave-dos/default-waves.do onerror {resume}
add wave -noupdate /testbench/clk
-- Set Wave Output Items add wave -noupdate /testbench/reset
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE
quietly WaveActivateNextPane {} 0
TreeUpdate [SetDefaultTree] TreeUpdate [SetDefaultTree]
WaveRestoreZoom {0 ps} {100 ps} WaveRestoreCursors {{Cursor 2} {12215488 ns} 0} {{Cursor 4} {22127 ns} 0}
quietly wave cursor active 2
configure wave -namecolwidth 250 configure wave -namecolwidth 250
configure wave -valuecolwidth 140 configure wave -valuecolwidth 513
configure wave -justifyvalue left configure wave -justifyvalue left
configure wave -signalnamewidth 0 configure wave -signalnamewidth 1
configure wave -snapdistance 10 configure wave -snapdistance 10
configure wave -datasetprefix 0 configure wave -datasetprefix 0
configure wave -rowmargin 4 configure wave -rowmargin 4
configure wave -childrowmargin 2 configure wave -childrowmargin 2
set DefaultRadix hexadecimal configure wave -gridoffset 0
configure wave -gridperiod 1
configure wave -griddelta 40
configure wave -timeline 0
configure wave -timelineunits ns
update
WaveRestoreZoom {21993 ns} {22181 ns}
-- Run the Simulation -- Run the Simulation
#run 4100 #run 5000
run -all run -all
#quit #quit
noview ../testbench/testbench-imperas.sv
view wave

View File

@ -354,7 +354,8 @@ module testbench();
"rv64p/WALLY-MARCHID", "4000", "rv64p/WALLY-MARCHID", "4000",
"rv64p/WALLY-MIMPID", "4000", "rv64p/WALLY-MIMPID", "4000",
"rv64p/WALLY-MHARTID", "4000", "rv64p/WALLY-MHARTID", "4000",
"rv64p/WALLY-MVENDORID", "4000" "rv64p/WALLY-MVENDORID", "4000",
"rv64p/WALLY-MEDELEG", "2000"
}; };
string tests32p[] = '{ string tests32p[] = '{
@ -368,6 +369,7 @@ module testbench();
"rv32p/WALLY-MIMPID", "4000", "rv32p/WALLY-MIMPID", "4000",
"rv32p/WALLY-MHARTID", "4000", "rv32p/WALLY-MHARTID", "4000",
"rv32p/WALLY-MVENDORID", "4000" "rv32p/WALLY-MVENDORID", "4000"
//"rv32p/WALLY-MEDELEG", "2000" // all 32 bit tests are currently failing, so haven't been able to confirm this test works yet. It should, though.
}; };
string tests64periph[] = '{ string tests64periph[] = '{

View File

@ -61,6 +61,37 @@ def writeVectors(storecmd, returningInstruction):
# Supervior timer interrupt: True, 5 # Supervior timer interrupt: True, 5
# Machine timer interrupt: True, 7 # Machine timer interrupt: True, 7
# if fromMode == "m":
# clintAddr = "0x2004000"
# writeTest(storecmd, f, r, f"""
# li x1, 0x8
# csrrs x0, {fromMode}status, x1
# la x18, {clintAddr}
# lw x11, 0(x18)
# li x1, 1
# # {storecmd} x1, 0(x18)
# li x1, 0x80
# csrrs x0, {fromMode}ie, x1
# nop
# nop
# nop
# nop
# nop
# nop
# nop
# """, True, 4, f"""
# li x1, 0x80
# # csrrc x0, {fromMode}ie, x1
# li x1, 0x8
# # csrrc x0, {fromMode}status, x1
# la x18, {clintAddr}
# {storecmd} x11, 0(x18)
# """)
# writeTest(storecmd, f, r, f""" # writeTest(storecmd, f, r, f"""
# li x10, MASK_XLEN(0x8) # li x10, MASK_XLEN(0x8)
# csrrs x0, mstatus, x10 # csrrs x0, mstatus, x10
@ -194,7 +225,7 @@ def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = "
expected = code expected = code
if(interrupt): if(interrupt):
expected+=(1 << (wordsize - 1)) expected+=(1 << (xlen - 1))
trapEnd = "" trapEnd = ""
@ -316,6 +347,8 @@ for xlen in xlens:
csrs sedeleg, x9 csrs sedeleg, x9
""" """
clintAddr = "0x2004000"
lines += f""" lines += f"""
li x30, 0 li x30, 0
@ -328,6 +361,32 @@ for xlen in xlens:
j _j_t_begin_{returningInstruction} j _j_t_begin_{returningInstruction}
_j_m_trap_{returningInstruction}: _j_m_trap_{returningInstruction}:
#li x1, 0x20
#csrrw x0, mie, x1
li x11, 0x3fffffffffffffff
la x18, {clintAddr}
{storecmd} x11, 0(x18)
li x1, 0x8
csrrc x0, mstatus, x1
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
sub x1, x2, x3
csrrs x1, mepc, x0 csrrs x1, mepc, x0
{"csrr x25, mcause" if testMode == "m" else "li x25, 0xBAD00003"} {"csrr x25, mcause" if testMode == "m" else "li x25, 0xBAD00003"}

View File

@ -0,0 +1,266 @@
#!/usr/bin/python3
##################################
# testgen-CAUSE.py
#
# dottolia@hmc.edu 27 Apr 2021
#
# Generate directed and random test vectors for RISC-V Design Validation.
#
#
##################################
# DOCUMENTATION:
# Most of the comments explaining what everything
# does can be found in testgen-TVAL.py
###################################
##################################
# libraries
##################################
from datetime import datetime
from random import randint
from random import seed
from random import getrandbits
##################################
# functions
##################################
#For instruction-fetch access or page-fault exceptions on systems with variable-length instructions, mtval will contain the virtual address of the portion of the instruction that caused the fault while mepc will point to the beginning of the instruction.
def randRegs():
reg1 = randint(1,20)
reg2 = randint(1,20)
reg3 = randint(1,20)
if (reg1 == 6 or reg2 == 6 or reg3 == 6 or reg1 == reg2):
return randRegs()
else:
return str(reg1), str(reg2), str(reg3)
def writeVectors(storecmd):
global testnum
# User Software Interrupt: True, 0
# Supervisor Software Interrupt: True, 1
# Machine Software Interrupt: True, 2
# User external input: True, 8
# Supervisor external input: True, 9
# Machine externa input: True, 11
# Instruction address misaligned: False, 0
# Instruction access fault: False, 1
# Illegal Instruction
#writeTest(storecmd, f, r, "ecall", False, 11, "m")
# Breakpoint
writeTest(storecmd, f, r, "ebreak", False, 3)
# Load Address Misaligned
# writeTest(storecmd, f, r, f"""
# lw x0, 11(x0)
# """, False, 4)
# # Load Access fault: False, 5
# # Store/AMO address misaligned
# writeTest(storecmd, f, r, f"""
# sw x0, 11(x0)
# """, False, 6)
#writeTest(storecmd, f, r, "ecall", False, 11, "m")
def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = ""):
global testnum
global testMode
global isInterrupts
if interrupt != isInterrupts:
return
mask = 1 << code
delegateType = "i" if interrupt else "e"
for mode in (["m", "s", "u"] if testMode == "m" else ["s", "u"]):
for delegated in [True, False]:
labelSuffix = testnum
f.write(f"""
_start_{labelSuffix}:
la x1, _j_m_trap_{labelSuffix}
csrw mtvec, x1
la x1, _j_s_trap_{labelSuffix}
csrw stvec, x1
j _j_test_{labelSuffix}
_j_m_trap_{labelSuffix}:
li x25, 3
csrr x1, mepc
addi x1, x1, 4
csrrw x0, mepc, x1
bnez x30, _j_finished_{labelSuffix}
mret
_j_s_trap_{labelSuffix}:
li x25, 1
csrr x1, sepc
addi x1, x1, 4
csrrw x0, sepc, x1
bnez x30, _j_goto_machine_mode_{labelSuffix}
sret
_j_goto_machine_mode_{labelSuffix}:
li x30, 1
{"ebreak" if test is not "ebreak" else "ecall"}
_j_test_{labelSuffix}:
""")
original = f"""
li x1, {mask if delegated else 0}
csrw m{delegateType}deleg, x1
"""
lines = original + "\n" + test
if mode != "m":
lines = f"""
{original}
li x1, 0b110000000000
csrrc x28, {testMode}status, x1
li x1, 0b{"01" if mode == "s" else "00"}00000000000
csrrs x28, {testMode}status, x1
auipc x1, 0
addi x1, x1, 16 # x1 is now right after the ret instruction
csrrw x27, {testMode}epc, x1
{testMode}ret
# From {testMode}, we're now in {mode} mode...
{test}
"""
writeTestInner(storecmd, f, r, lines, 1 if delegated else 3)
f.write(f"""
j _j_goto_machine_mode_{labelSuffix}
""")
else:
writeTestInner(storecmd, f, r, lines, 3)
f.write(f"""
_j_finished_{labelSuffix}:
li x30, 0
""")
def writeTestInner(storecmd, f, r, lines, expected):
global testnum
lines = f"""
li x25, 0xDEADBEA7
{lines}
"""
lines += storecmd + " x25, " + str(testnum * wordsize) + "(x6)\n"
f.write(lines)
if (xlen == 32):
line = formatrefstr.format(expected)+"\n"
else:
line = formatrefstr.format(expected % 2**32)+"\n" + formatrefstr.format(expected >> 32) + "\n"
r.write(line)
testnum = testnum+1
##################################
# main body
##################################
# change these to suite your tests
author = "dottolia@hmc.edu"
xlens = [32, 64]
numrand = 1;
# setup
seed(0xD0C0_D0C0_D0C0_D0C0) # make tests reproducible
# generate files for each test
for xlen in xlens:
formatstrlen = str(int(xlen/4))
formatstr = "0x{:0" + formatstrlen + "x}" # format as xlen-bit hexadecimal number
formatrefstr = "{:08x}" # format as xlen-bit hexadecimal number with no leading 0x
if (xlen == 32):
storecmd = "sw"
wordsize = 4
else:
storecmd = "sd"
wordsize = 8
for testMode in ["m"]:
for isInterrupts in [True, False]:
imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/"
basename = "WALLY-" + testMode.upper() + ("I" if isInterrupts else "E") + "DELEG"
fname = imperaspath + "src/" + basename + ".S"
refname = imperaspath + "references/" + basename + ".reference_output"
# print custom header part
f = open(fname, "w")
r = open(refname, "w")
line = "///////////////////////////////////////////\n"
f.write(line)
lines="// "+fname+ "\n// " + author + "\n"
f.write(lines)
line ="// Created " + str(datetime.now())
f.write(line)
# insert generic header
h = open("../testgen_header.S", "r")
for line in h:
f.write(line)
# All registers used:
# x19: mtvec old value
# x18: medeleg old value
# x17: mideleg old value
f.write(f"""
add x7, x6, x0
csrr x19, mtvec
csrr x18, medeleg
csrr x17, medeleg
""")
print("\n\n" + basename)
testnum = 0
for i in range(0, 2):
writeVectors(storecmd)
print(testnum)
f.write(f"""
csrw mtvec, x19
csrw medeleg, x18
csrw mideleg, x17
""")
# if we're in supervisor mode, this leaves the ebreak instruction untested (we need a way to)
# get back to machine mode.
# print footer
h = open("../testgen_footer.S", "r")
for line in h:
f.write(line)
# Finish
lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n"
lines = lines + "\nRV_COMPLIANCE_DATA_END\n"
f.write(lines)
f.close()
r.close()

View File

@ -1,6 +1,6 @@
#!/usr/bin/python3 #!/usr/bin/python3
################################## ##################################
# testgen-CAUSE.py (new) # testgen-TVEC.py (new)
# #
# dottolia@hmc.edu 1 Mar 2021 # dottolia@hmc.edu 1 Mar 2021
# #
@ -25,6 +25,12 @@ from random import randint
from random import seed from random import seed
from random import getrandbits from random import getrandbits
##################################
# setup
##################################
areVectoredTrapsSupported = True
################################## ##################################
# functions # functions
################################## ##################################
@ -43,29 +49,6 @@ def randRegs():
def writeVectors(storecmd, returningInstruction): def writeVectors(storecmd, returningInstruction):
global testnum global testnum
if fromMode == "m":
expectedCode = 7 if fromMode == "m" else 5
clintAddr = "0x2004000"
writeTest(storecmd, f, r, f"""
li x1, 0x8
csrrs x0, {fromMode}status, x1
la x18, {clintAddr}
lw x11, 0(x18)
li x1, 1
{storecmd} x1, 0(x18)
li x1, 0x80
csrrs x0, {fromMode}ie, x1
""", True, expectedCode, f"""
la x18, {clintAddr}
{storecmd} x11, 0(x18)
li x1, 0x80
csrrc x0, {fromMode}ie, x1
""")
# Illegal Instruction # Illegal Instruction
writeTest(storecmd, f, r, f""" writeTest(storecmd, f, r, f"""
@ -112,6 +95,35 @@ def writeVectors(storecmd, returningInstruction):
ecall ecall
""", False, 0) """, False, 0)
if fromMode == "m":
expectedCode = 7 if fromMode == "m" else 5
clintAddr = "0x2004000"
writeTest(storecmd, f, r, f"""
li x1, 0x8
csrrs x0, {fromMode}status, x1
la x18, {clintAddr}
lw x11, 0(x18)
li x1, 0x3fffffffffffffff
{storecmd} x1, 0(x18)
li x1, 0x80
csrrs x0, {fromMode}ie, x1
{storecmd} x0, 0(x18)
""", True, expectedCode, f"""
li x1, 0x80
csrrc x0, {fromMode}ie, x1
li x1, 0x8
csrrc x0, {fromMode}status, x1
la x18, {clintAddr}
{storecmd} x0, 0(x18)
""")
# Instruction page fault: 12 # Instruction page fault: 12
# Load page fault: 13 # Load page fault: 13
# Store/AMO page fault: 15 # Store/AMO page fault: 15
@ -144,14 +156,13 @@ def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""):
{test} {test}
""" """
# We expect x25 to be 0 always. This is because of the code we wrote at the begining
# of this function
# Store the expected value of x25 to memory and in the .reference_output file
lines += f""" lines += f"""
{storecmd} x25, {testnum * wordsize}(x6) {storecmd} x25, {testnum * wordsize}(x6)
""" """
if not areVectoredTrapsSupported:
expected = 0
f.write(lines) f.write(lines)
if (xlen == 32): if (xlen == 32):
line = formatrefstr.format(expected)+"\n" line = formatrefstr.format(expected)+"\n"
@ -291,7 +302,7 @@ for xlen in xlens:
# Set up # Set up
la x1, _j_m_trap_{returningInstruction} la x1, _j_m_trap_{returningInstruction}
addi x1, 1 #addi x1, 1
csrw mtvec, x1 csrw mtvec, x1
la x1, _j_s_trap_{returningInstruction} la x1, _j_s_trap_{returningInstruction}
csrw stvec, x1 csrw stvec, x1