diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index ded8e22b..416f1c41 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -334,7 +334,9 @@ string tests32i[] = { }; string tests64p[] = '{ - "rv64p/WALLY-CAUSE", "3000" + "rv64p/WALLY-CAUSE", "3000", + "rv64p/WALLY-EPC", "3000", + "rv64p/WALLY-TVAL", "3000" }; string tests[]; @@ -370,7 +372,7 @@ string tests32i[] = { //if (`MEM_VIRTMEM) tests = {tests, tests64mmu}; end // tests = {tests64a, tests}; - // tests = {tests, tests64p}; + tests = {tests, tests64p}; end else begin // RV32 // *** add the 32 bit bp tests tests = {tests32i}; @@ -382,7 +384,7 @@ string tests32i[] = { if (`MEM_VIRTMEM) tests = {tests32mmu, tests}; end - // tests = tests64p; + //tests = tests64p; end diff --git a/wally-pipelined/testgen/privileged/testgen-CAUSE.py b/wally-pipelined/testgen/privileged/testgen-CAUSE.py index 00b1deca..8d2bc137 100644 --- a/wally-pipelined/testgen/privileged/testgen-CAUSE.py +++ b/wally-pipelined/testgen/privileged/testgen-CAUSE.py @@ -19,6 +19,8 @@ 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) @@ -74,11 +76,10 @@ def writeVectors(storecmd): # BUG: jumping to a misaligned instruction address doesn't cause an exception: we actually jump... # Either that, or somehow at the end we always end up at 0x80004002 # This is fine in OVPsim - writeTest(storecmd, f, r, f""" - li x1, 11 - li x25, 0 # Force this test to pass, for now - # jr x1 # Something about this instruction is funky on wally, but fine with ovpsim - """, False, 0) + # writeTest(storecmd, f, r, f""" + # li x1, 11 + # jr x1 # Something about this instruction is funky on wally, but fine with ovpsim + # """, False, 0) # Instruction access fault: False, 1 @@ -112,9 +113,10 @@ def writeVectors(storecmd): # # Environment call from s-mode # ??? BUG ??? Code should be 9, but ends up being 8 - # writeTest(storecmd, f, r, f""" - # ecall - # """, False, 8, "s") + # It's 8 for both OVPSim and Wally + writeTest(storecmd, f, r, f""" + ecall + """, False, 8, "s") # Environment call from m-mode writeTest(storecmd, f, r, f""" diff --git a/wally-pipelined/testgen/privileged/testgen-EPC.py b/wally-pipelined/testgen/privileged/testgen-EPC.py new file mode 100644 index 00000000..5d6e42f4 --- /dev/null +++ b/wally-pipelined/testgen/privileged/testgen-EPC.py @@ -0,0 +1,184 @@ +#!/usr/bin/python3 +################################## +# testgen-CAUSE.py +# +# dottolia@hmc.edu 1 Mar 2021 +# +# Generate directed and random test vectors for RISC-V Design Validation. +################################## + +################################## +# libraries +################################## +from datetime import datetime +from random import randint +from random import seed +from random import getrandbits + +################################## +# functions +################################## + +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 + + # Breakpoint + writeTest(storecmd, f, r, f""" + ebreak + """) + + + +def writeTest(storecmd, f, r, test, mode = "m", resetHander = ""): + global testnum + + noprand = "" + for i in range(0, randint(0, 32)): + noprand+="nop\n" + + # Setup + # TODO: Adding 8 to x30 won't work for 32 bit? + # x31: Old mtvec value + # x30: trap handler address + # x29: Old mtvec value for user/supervisor mode + # x28: Old mstatus value + # x27: Old mepc value + # x26: 0 if we should execute mret normally. 1 otherwise. This allows us to stay in machine + # x25: x24 - x23 should = 0 + # x24: expected mepc value + # x23: actual mepc value + lines = f""" + # Testcase {testnum} + csrrs x31, mtvec, x0 + + auipc x30, 0 + addi x30, x30, 12 + j _jtest{testnum} + + # Machine trap vector + csrrs x23, mepc, x0 + addi x1, x23, 4 + csrrw x0, mepc, x1 + mret + + # Actual test + _jtest{testnum}: + csrrw x0, mtvec, x30 + + # Start test code + li x25, 0x7BAD + li x23, 0x7BAD + auipc x24, 0 + {test} + {noprand} + + # Finished test. Reset to old mtvec + _jend{testnum}: + addi x24, x24, 4 # x24 should be the address of the test + sub x25, x24, x23 + csrrw x0, mtvec, x31 + """ + + expected = 0 + + #expected = 42 + + lines += storecmd + " x25, " + str(wordsize*testnum) + "(x6)\n" + #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\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 + + # lines += storecmd + " x0" + ", " + str(wordsize*testnum) + "(x6)\n" + # #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\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 +# csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci +author = "dottolia@hmc.edu" +xlens = [32, 64] +numrand = 40; # Doesn't work when numrand = 10 + +# setup +seed(0xC365DDEB9173AB42) # 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 + + corners = [ + 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, + 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 + ] + imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" + basename = "WALLY-EPC" + fname = imperaspath + "src/" + basename + ".S" + refname = imperaspath + "references/" + basename + ".reference_output" + testnum = 0 + + # 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) + + # print directed and random test vectors + for i in range(0,numrand): + writeVectors(storecmd) + + + # 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() + + + + diff --git a/wally-pipelined/testgen/privileged/testgen-TVAL.py b/wally-pipelined/testgen/privileged/testgen-TVAL.py new file mode 100644 index 00000000..e25105da --- /dev/null +++ b/wally-pipelined/testgen/privileged/testgen-TVAL.py @@ -0,0 +1,227 @@ +#!/usr/bin/python3 +################################## +# testgen-CAUSE.py +# +# dottolia@hmc.edu 1 Mar 2021 +# +# Generate directed and random test vectors for RISC-V Design Validation. +################################## + +################################## +# libraries +################################## +from datetime import datetime +from random import randint +from random import seed +from random import getrandbits + +################################## +# functions +################################## + +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 + + # x23 holds the expected value + + # Illegal Instruction + writeTest(storecmd, f, r, f""" + .fill 1, 4, 0 + """, f""" + li x23, 0 + """) + + val = (randint(0, 200) * 4) + 1 + + # Load Address Misaligned + writeTest(storecmd, f, r, f""" + lw x0, {val}(x0) + """, f""" + li x23, {val} + """) + + val = (randint(0, 200) * 4) + 1 + + # Load Address Misaligned + writeTest(storecmd, f, r, f""" + sw x0, {val}(x0) + """, f""" + li x23, {val} + """) + + + + +def writeTest(storecmd, f, r, test, expected, mode = "m", resetHander = ""): + global testnum + + + trapEnd = "" + before = "" + if mode != "m": + before = f""" + li x1, 0b110000000000 + csrrc x28, mstatus, x1 + li x1, 0b{"01" if mode == "s" else "00"}0000000000 + csrrs x28, mstatus, x1 + + auipc x1, 0 + addi x1, x1, 16 # x1 is now right after the mret instruction + csrrw x27, mepc, x1 + mret + + # We're now in {mode} mode... + """ + + trapEnd = f"""j _jend{testnum}""" + + + # Setup + # TODO: Adding 8 to x30 won't work for 32 bit? + # x31: Old mtvec value + # x30: trap handler address + # x29: Old mtvec value for user/supervisor mode + # x28: Old mstatus value + # x27: Old mepc value + # x26: 0 if we should execute mret normally. 1 otherwise. This allows us to stay in machine + # x25: mcause + # x24: mtval + # x23: mtval expected + # mode for the next tests + lines = f""" + # Testcase {testnum} + csrrs x31, mtvec, x0 + + auipc x30, 0 + addi x30, x30, 12 + j _jtest{testnum} + + # Machine trap vector + {resetHander} + csrrs x25, mcause, x0 + csrrs x24, mtval, x0 + csrrs x1, mepc, x0 + addi x1, x1, 4 + csrrw x0, mepc, x1 + {trapEnd} + mret + + # Actual test + _jtest{testnum}: + csrrw x0, mtvec, x30 + + # Start test code + li x25, 0x7BAD + li x24, 0x7BAD + {before} + {test} + + # Finished test. Reset to old mtvec + _jend{testnum}: + + {expected} + sub x25, x24, x23 + csrrw x0, mtvec, x31 + """ + + expected = 0 + + lines += storecmd + " x25, " + str(wordsize*testnum) + "(x6)\n" + #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\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 + + # lines += storecmd + " x0" + ", " + str(wordsize*testnum) + "(x6)\n" + # #lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, " + str(reg2) +", "+formatstr.format(expected)+")\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 +# csrrw, csrrs, csrrc, csrrwi, csrrsi, csrrci +author = "dottolia@hmc.edu" +xlens = [32, 64] +numrand = 30; + +# setup +seed(0xC363DDEB9173AB42) # 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 + + corners = [ + 0x624B3E976C52DD14 % 2**xlen, 2**(xlen-1)-2, 2**(xlen-1)-1, + 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 + ] + imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" + basename = "WALLY-TVAL" + fname = imperaspath + "src/" + basename + ".S" + refname = imperaspath + "references/" + basename + ".reference_output" + testnum = 0 + + # 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) + + # print directed and random test vectors + for i in range(0,numrand): + writeVectors(storecmd) + + + # 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() + + + +