From b1cd107a0001d8b43c046d6634ed8236b6004144 Mon Sep 17 00:00:00 2001 From: Domenico Ottolia Date: Thu, 15 Apr 2021 19:41:25 -0400 Subject: [PATCH] Add tests for scause and ucause --- wally-pipelined/src/privileged/trap.sv | 15 +- .../testbench/testbench-imperas.sv | 14 +- .../testgen/privileged/testgen-CAUSE.py | 144 ++++++++++-------- .../testgen/privileged/testgen-READONLY.py | 2 - 4 files changed, 99 insertions(+), 76 deletions(-) diff --git a/wally-pipelined/src/privileged/trap.sv b/wally-pipelined/src/privileged/trap.sv index 8452fd28b..71677dd29 100644 --- a/wally-pipelined/src/privileged/trap.sv +++ b/wally-pipelined/src/privileged/trap.sv @@ -72,14 +72,23 @@ module trap ( // Handle vectored traps (when mtvec/stvec/utvec csr value has bits [1:0] == 01) // For vectored traps, set program counter to _tvec value + 4 times the cause code - assign PrivilegedVectoredTrapVector = PrivilegedTrapVector + {CauseM[`XLEN-3:0], 2'b00}; + generate + if(`VECTORED_INTERRUPTS_SUPPORTED) begin + always_comb + if (PrivilegedTrapVector[1:0] == 2'b01 && CauseM[`XLEN-1] == 1) + PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2] + CauseM[`XLEN-3:0], 2'b00}; + else + PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; + end + else begin + assign PrivilegedVectoredTrapVector = {PrivilegedTrapVector[`XLEN-1:2], 2'b00}; + end + endgenerate always_comb if (mretM) PrivilegedNextPCM = MEPC_REGW; else if (sretM) PrivilegedNextPCM = SEPC_REGW; else if (uretM) PrivilegedNextPCM = UEPC_REGW; - else if (PrivilegedTrapVector[1:0] == 2'b01 && CauseM[`XLEN-1] == 1) - PrivilegedNextPCM = PrivilegedVectoredTrapVector; else PrivilegedNextPCM = PrivilegedTrapVector; // Cause priority defined in table 3.7 of 20190608 privileged spec diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index 109938495..70d620a4f 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -342,7 +342,9 @@ module testbench(); }; string tests64p[] = '{ - "rv64p/WALLY-MCAUSE", "3000", + "rv64p/WALLY-MCAUSE", "2000", + "rv64p/WALLY-SCAUSE", "2000", + "rv64p/WALLY-UCAUSE", "2000", "rv64p/WALLY-EPC", "3000", "rv64p/WALLY-TVAL", "3000", "rv64p/WALLY-MARCHID", "4000", @@ -352,7 +354,9 @@ module testbench(); }; string tests32p[] = '{ - "rv32p/WALLY-MCAUSE", "3000", + "rv32p/WALLY-MCAUSE", "2000", + "rv32p/WALLY-SCAUSE", "2000", + "rv32p/WALLY-UCAUSE", "2000", "rv32p/WALLY-EPC", "3000", "rv32p/WALLY-TVAL", "3000", "rv32p/WALLY-MARCHID", "4000", @@ -406,8 +410,8 @@ module testbench(); if (`MEM_VIRTMEM) tests = {tests64mmu, tests}; end //tests = {tests64a, tests}; - // tests = {tests, tests64p}; - tests = tests64p; + + //tests = tests64p; end else begin // RV32 // *** add the 32 bit bp tests if (TESTSPERIPH) begin @@ -422,7 +426,7 @@ module testbench(); if (`MEM_VIRTMEM) tests = {tests32mmu, tests}; end - tests = tests32p; + //tests = tests32p; end end diff --git a/wally-pipelined/testgen/privileged/testgen-CAUSE.py b/wally-pipelined/testgen/privileged/testgen-CAUSE.py index 9bd72422a..5c9220125 100644 --- a/wally-pipelined/testgen/privileged/testgen-CAUSE.py +++ b/wally-pipelined/testgen/privileged/testgen-CAUSE.py @@ -153,19 +153,25 @@ def writeVectors(storecmd): """, False, 6) # Environment call from u-mode: only for when only M and U mode enabled? - writeTest(storecmd, f, r, f""" - ecall - """, False, 8, "u") + # writeTest(storecmd, f, r, f""" + # ecall + # """, False, 8, "u") + if testMode == "u": + writeTest(storecmd, f, r, f""" + ecall + """, False, 8, "u") - # # Environment call from s-mode - writeTest(storecmd, f, r, f""" - ecall - """, False, 9, "s") + # Environment call from s-mode + if testMode == "s": + writeTest(storecmd, f, r, f""" + ecall + """, False, 9, "s") # Environment call from m-mode - writeTest(storecmd, f, r, f""" - ecall - """, False, 11, "m") + if testMode == "m": + writeTest(storecmd, f, r, f""" + ecall + """, False, 11, "m") # Instruction page fault: 12 # Load page fault: 13 @@ -176,6 +182,7 @@ def writeVectors(storecmd): def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = ""): global testnum + global testMode expected = code if(interrupt): @@ -187,67 +194,29 @@ def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = " if mode != "m": before = f""" li x1, 0b110000000000 - csrrc x28, mstatus, x1 + csrrc x28, {testMode}status, x1 li x1, 0b{"01" if mode == "s" else "00"}00000000000 - csrrs x28, mstatus, x1 + csrrs x28, {testMode}status, x1 auipc x1, 0 addi x1, x1, 16 # x1 is now right after the mret instruction - csrrw x27, mepc, x1 - mret + csrrw x27, {testMode}epc, x1 + {testMode}ret - # We're now in {mode} mode... + # From {testMode}, 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 - # 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 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 - {before} {test} - # Finished test. Reset to old mtvec _jend{testnum}: - csrrw x0, mtvec, x31 """ - #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" @@ -256,22 +225,11 @@ def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = " 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 = 8; @@ -296,9 +254,9 @@ for xlen in xlens: 2**(xlen-1), 2**(xlen-1)+1, 0xC365DDEB9173AB42 % 2**xlen, 2**(xlen)-2, 2**(xlen)-1 ] - for mode in ["m", "s", "u"]: + for testMode in ["m", "s", "u"]: imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-" + mode.upper() + "CAUSE" + basename = "WALLY-" + testMode.upper() + "CAUSE" fname = imperaspath + "src/" + basename + ".S" refname = imperaspath + "references/" + basename + ".reference_output" testnum = 0 @@ -318,11 +276,65 @@ for xlen in xlens: for line in h: f.write(line) + lines = f""" + csrr x31, mtvec + li x30, 0 + + la x1, _j_m_trap + csrw mtvec, x1 + la x1, _j_s_trap + csrw stvec, x1 + j _j_t_begin + + _j_m_trap: + csrrs x25, mcause, x0 + csrrs x1, mepc, x0 + addi x1, x1, 4 + csrrw x0, mepc, x1 + bnez x30, _j_all_end + mret + + _j_s_trap: + csrrs x25, scause, x0 + csrrs x1, sepc, x0 + addi x1, x1, 4 + csrrw x0, sepc, x1 + sret + + _j_t_begin: + """ + + if testMode == "s" or testMode == "u": + lines += f""" + li x1, 0b110000000000 + csrrc x28, mstatus, x1 + li x1, 0b{"01" if testMode == "s" else "00"}00000000000 + csrrs x28, mstatus, x1 + + auipc x1, 0 + addi x1, x1, 16 # x1 is now right after the mret instruction + csrw mepc, x1 + mret + + # We're now in {testMode} mode... + """ + + f.write(lines) + + # print directed and random test vectors for i in range(0,numrand): writeVectors(storecmd) + f.write(f""" + li x30, 1 + ecall + _j_all_end: + + csrw mtvec, x31 + """) + # print footer h = open("../testgen_footer.S", "r") for line in h: diff --git a/wally-pipelined/testgen/privileged/testgen-READONLY.py b/wally-pipelined/testgen/privileged/testgen-READONLY.py index 1dae13f76..ad94b60cd 100644 --- a/wally-pipelined/testgen/privileged/testgen-READONLY.py +++ b/wally-pipelined/testgen/privileged/testgen-READONLY.py @@ -30,8 +30,6 @@ def randRegs(): else: return str(reg1), str(reg2), str(reg3) -# WALLY BUG: doesn't cause an illegal instruction on csr writes to readonly places. Last paragraph of page 5 of privileged spec - def writeVectors(a, storecmd): writeSingleVector(a, storecmd, f"""csrrw x0, {test}, x13""") writeSingleVector(a, storecmd, f"""csrrwi x0, {test}, {a % 32}""")