diff --git a/wally-pipelined/lint-wally b/wally-pipelined/lint-wally index 18851119..59d6bf15 100755 --- a/wally-pipelined/lint-wally +++ b/wally-pipelined/lint-wally @@ -1,11 +1,14 @@ # check for warnings in Verilog code # The verilator lint tool is faster and better than Modelsim so it is best to run this first. -echo "rv64ic linting..." -verilator --lint-only "$@" --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv -echo "rv32ic linting..." -verilator --lint-only "$@" --top-module wallypipelinedsoc -Iconfig/rv32ic src/*/*.sv -#verilator --lint-only --top-module wallypipelinedsoc -Iconfig/rv64ic src/*/*.sv src/*/div/*.sv +for config in rv64ic rv32ic; do + echo "$config linting..." + if !(verilator --lint-only "$@" --top-module wallypipelinedsoc "-Iconfig/$config" src/*/*.sv); then + echo "Exiting after $config lint due to errors or warnings" + exit 1 + fi +done +echo "All lints run with no errors or warnings" # --lint-only just runs lint rather than trying to compile and simulate # -I points to the include directory where files such as `include wally-config.vh are found diff --git a/wally-pipelined/regression/wally-privileged.do b/wally-pipelined/regression/wally-privileged.do index d969e672..9e1447a1 100644 --- a/wally-pipelined/regression/wally-privileged.do +++ b/wally-pipelined/regression/wally-privileged.do @@ -30,34 +30,43 @@ vlib work # default to config/rv64ic, but allow this to be overridden at the command line. For example: # do wally-pipelined.do ../config/rv32ic switch $argc { - 0 {vlog +incdir+../config/rv64ic ../testbench/testbench-privileged.sv ../src/*/*.sv -suppress 2583} - 1 {vlog +incdir+$1 ../testbench/testbench-privileged.sv ../testbench/function_radix.sv ../src/*/*.sv -suppress 2583} + 0 {vlog +incdir+../config/rv64ic ../testbench/testbench-imperas.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 # remove +acc flag for faster sim during regressions if there is no need to access internal signals vopt +acc work.testbench -o workopt vsim workopt - view wave - -- display input and output signals as hexidecimal values -do ./wave-dos/default-waves.do - --- Set Wave Output Items +onerror {resume} +add wave -noupdate /testbench/clk +add wave -noupdate /testbench/reset +add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE +quietly WaveActivateNextPane {} 0 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 -valuecolwidth 140 +configure wave -valuecolwidth 513 configure wave -justifyvalue left -configure wave -signalnamewidth 0 +configure wave -signalnamewidth 1 configure wave -snapdistance 10 configure wave -datasetprefix 0 configure wave -rowmargin 4 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 4100 +#run 5000 run -all #quit +noview ../testbench/testbench-imperas.sv +view wave diff --git a/wally-pipelined/regression/wave-dos/default-waves.do b/wally-pipelined/regression/wave-dos/default-waves.do index 065893e5..85ded931 100644 --- a/wally-pipelined/regression/wave-dos/default-waves.do +++ b/wally-pipelined/regression/wave-dos/default-waves.do @@ -63,4 +63,4 @@ configure wave -snapdistance 10 configure wave -datasetprefix 0 configure wave -rowmargin 4 configure wave -childrowmargin 2 -set DefaultRadix hexadecimal \ No newline at end of file +set DefaultRadix hexadecimal diff --git a/wally-pipelined/src/ifu/globalHistoryPredictor.sv b/wally-pipelined/src/ifu/globalHistoryPredictor.sv index 1fd0720f..087458df 100644 --- a/wally-pipelined/src/ifu/globalHistoryPredictor.sv +++ b/wally-pipelined/src/ifu/globalHistoryPredictor.sv @@ -41,13 +41,13 @@ module globalHistoryPredictor input logic [1:0] UpdatePrediction ); - logic [k-1:0] GHRF, GHRD, GHRE, GHRENext; - assign GHRENext = {PCSrcE, GHRE[k-1:1]}; + logic [k-1:0] GHRF, GHRFNext; + assign GHRFNext = {PCSrcE, GHRF[k-1:1]}; flopenr #(k) GlobalHistoryRegister(.clk(clk), .reset(reset), .en(UpdateEN), - .d(GHRENext), + .d(GHRFNext), .q(GHRF)); @@ -65,7 +65,7 @@ module globalHistoryPredictor .RA1(GHRF), .RD1(PredictionMemory), .REN1(~StallF), - .WA1(GHRENext), + .WA1(GHRFNext), .WD1(UpdatePrediction), .WEN1(UpdateEN), .BitWEN1(2'b11)); @@ -73,7 +73,7 @@ module globalHistoryPredictor // need to forward when updating to the same address as reading. // first we compare to see if the update and lookup addreses are the same - assign DoForwarding = GHRF == GHRE; + assign DoForwarding = GHRF == GHRFNext; // register the update value and the forwarding signal into the Fetch stage // TODO: add stall logic *** @@ -90,7 +90,7 @@ module globalHistoryPredictor assign Prediction = DoForwardingF ? UpdatePredictionF : PredictionMemory; //pipeline for GHR - flopenrc #(k) GHRDReg(.clk(clk), + /*flopenrc #(k) GHRDReg(.clk(clk), .reset(reset), .en(~StallD), .clear(FlushD), @@ -103,5 +103,5 @@ module globalHistoryPredictor .clear(FlushE), .d(GHRD), .q(GHRE)); - +*/ endmodule diff --git a/wally-pipelined/src/ifu/gshare.sv b/wally-pipelined/src/ifu/gshare.sv index 8af54145..4d31e519 100644 --- a/wally-pipelined/src/ifu/gshare.sv +++ b/wally-pipelined/src/ifu/gshare.sv @@ -42,24 +42,24 @@ module gsharePredictor ); - logic [k-1:0] GHRF, GHRD, GHRE, GHRENext; + logic [k-1:0] GHRF, GHRFNext; //logic [k-1:0] LookUpPCIndexD, LookUpPCIndexE; logic [k-1:0] LookUpPCIndex, UpdatePCIndex; logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF; logic [1:0] UpdatePredictionF; - assign GHRENext = {PCSrcE, GHRE[k-1:1]}; + assign GHRFNext = {PCSrcE, GHRF[k-1:1]}; flopenr #(k) GlobalHistoryRegister(.clk(clk), .reset(reset), .en(UpdateEN), - .d(GHRENext), + .d(GHRFNext), .q(GHRF)); // for gshare xor the PC with the GHR - assign UpdatePCIndex = GHRENext ^ UpdatePC[k:1]; + assign UpdatePCIndex = GHRFNext ^ UpdatePC[k:1]; assign LookUpPCIndex = GHRF ^ LookUpPC[k:1]; // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT // GHR referes to the address that the past k branches points to in the prediction stage @@ -110,7 +110,7 @@ module gsharePredictor .q(LookUpPCIndexE)); -----/\----- EXCLUDED -----/\----- */ - flopenrc #(k) GHRRegD(.clk(clk), +/* flopenrc #(k) GHRRegD(.clk(clk), .reset(reset), .en(~StallD), .clear(FlushD), @@ -124,5 +124,5 @@ module gsharePredictor .d(GHRD), .q(GHRE)); - +*/ endmodule diff --git a/wally-pipelined/src/ifu/localHistoryPredictor.sv b/wally-pipelined/src/ifu/localHistoryPredictor.sv index ef33bbc8..70e85562 100644 --- a/wally-pipelined/src/ifu/localHistoryPredictor.sv +++ b/wally-pipelined/src/ifu/localHistoryPredictor.sv @@ -44,13 +44,13 @@ module localHistoryPredictor ); logic [2**m-1:0][k-1:0] LHRNextF; - logic [k-1:0] LHRF, LHRD, LHRE, LHRENext, ForwardLHRNext; + logic [k-1:0] LHRF, ForwardLHRNext; logic [m-1:0] LookUpPCIndex, UpdatePCIndex; logic [1:0] PredictionMemory; logic DoForwarding, DoForwardingF, DoForwardingPHT, DoForwardingPHTF; logic [1:0] UpdatePredictionF; - assign LHRENext = {PCSrcE, LHRE[k-1:1]}; + assign LHRFNext = {PCSrcE, LHRF[k-1:1]}; assign UpdatePCIndex = {UpdatePC[m+1] ^ UpdatePC[1], UpdatePC[m:2]}; assign LookUpPCIndex = {LookUpPC[m+1] ^ LookUpPC[1], LookUpPC[m:2]}; @@ -72,7 +72,7 @@ generate flopenr #(k) LocalHistoryRegister(.clk(clk), .reset(reset), .en(UpdateEN && (index == UpdatePCIndex)), - .d(LHRENext), + .d(LHRFNext), .q(LHRNextF[index])); end endgenerate @@ -80,7 +80,7 @@ endgenerate // need to forward when updating to the same address as reading. // first we compare to see if the update and lookup addreses are the same assign DoForwarding = LookUpPCIndex == UpdatePCIndex; -assign ForwardLHRNext = DoForwarding ? LHRENext :LHRNextF[LookUpPCIndex]; +assign ForwardLHRNext = DoForwarding ? LHRFNext :LHRNextF[LookUpPCIndex]; // Make Prediction by reading the correct address in the PHT and also update the new address in the PHT // LHR referes to the address that the past k branches points to in the prediction stage @@ -90,14 +90,14 @@ assign ForwardLHRNext = DoForwarding ? LHRENext :LHRNextF[LookUpPCIndex]; .RA1(ForwardLHRNext), .RD1(PredictionMemory), .REN1(~StallF), - .WA1(LHRENext), + .WA1(LHRFNext), .WD1(UpdatePrediction), .WEN1(UpdateEN), .BitWEN1(2'b11)); -assign DoForwardingPHT = LHRENext == ForwardLHRNext; +assign DoForwardingPHT = LHRFNext == ForwardLHRNext; // register the update value and the forwarding signal into the Fetch stage // TODO: add stall logic *** @@ -120,7 +120,7 @@ assign DoForwardingPHT = LHRENext == ForwardLHRNext; .clear(FlushF), .d(ForwardLHRNext), .q(LHRF)); - +/* flopenrc #(k) LHRDReg(.clk(clk), .reset(reset), .en(~StallD), @@ -134,5 +134,5 @@ assign DoForwardingPHT = LHRENext == ForwardLHRNext; .clear(FlushE), .d(LHRD), .q(LHRE)); - +*/ endmodule diff --git a/wally-pipelined/src/privileged/csr.sv b/wally-pipelined/src/privileged/csr.sv index 36074415..3c0a193e 100644 --- a/wally-pipelined/src/privileged/csr.sv +++ b/wally-pipelined/src/privileged/csr.sv @@ -36,6 +36,7 @@ module csr #(parameter input logic FlushW, StallD, StallE, StallM, StallW, input logic [31:0] InstrM, input logic [`XLEN-1:0] PCM, SrcAM, + input logic InterruptM, input logic CSRReadM, CSRWriteM, TrapM, MTrapM, STrapM, UTrapM, mretM, sretM, uretM, input logic TimerIntM, ExtIntM, SwIntM, input logic InstrValidW, FloatRegWriteW, LoadStallD, @@ -71,7 +72,14 @@ module csr #(parameter logic WriteMSTATUSM, WriteSSTATUSM, WriteUSTATUSM; logic CSRMWriteM, CSRSWriteM, CSRUWriteM; - logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM; + logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, preservedPCM, readPCM, NextCauseM, NextMtvalM; + + always_ff @(posedge clk) begin + preservedPCM <= PCM; + end + + mux2 #(`XLEN) pcmux(PCM, preservedPCM, InterruptM, readPCM); + //flop #(`XLEN) CSRReadPCMreg(clk, reset, PCM, readPCM); logic [11:0] CSRAdrM; logic [11:0] SIP_REGW, SIE_REGW; @@ -100,7 +108,7 @@ module csr #(parameter // write CSRs assign CSRAdrM = InstrM[31:20]; - assign UnalignedNextEPCM = TrapM ? PCM : CSRWriteValM; + assign UnalignedNextEPCM = TrapM ? readPCM : CSRWriteValM; assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment assign NextCauseM = TrapM ? CauseM : CSRWriteValM; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; diff --git a/wally-pipelined/src/privileged/privileged.sv b/wally-pipelined/src/privileged/privileged.sv index 493f8c89..1ccab204 100644 --- a/wally-pipelined/src/privileged/privileged.sv +++ b/wally-pipelined/src/privileged/privileged.sv @@ -85,7 +85,8 @@ module privileged ( logic IllegalInstrFaultM; logic BreakpointFaultM, EcallFaultM; - logic MTrapM, STrapM, UTrapM; + logic MTrapM, STrapM, UTrapM; + logic InterruptM; logic [1:0] STATUS_MPP; logic STATUS_SPP, STATUS_TSR; diff --git a/wally-pipelined/src/privileged/trap.sv b/wally-pipelined/src/privileged/trap.sv index 2c0506e1..552ce9a4 100644 --- a/wally-pipelined/src/privileged/trap.sv +++ b/wally-pipelined/src/privileged/trap.sv @@ -41,13 +41,14 @@ module trap ( input logic [`XLEN-1:0] InstrMisalignedAdrM, MemAdrM, input logic [31:0] InstrM, output logic TrapM, MTrapM, STrapM, UTrapM, RetM, + output logic InterruptM, output logic [`XLEN-1:0] PrivilegedNextPCM, CauseM, NextFaultMtvalM // output logic [11:0] MIP_REGW, SIP_REGW, UIP_REGW, MIE_REGW, SIE_REGW, UIE_REGW, // input logic WriteMIPM, WriteSIPM, WriteUIPM, WriteMIEM, WriteSIEM, WriteUIEM ); logic [11:0] MIntGlobalEnM, SIntGlobalEnM, PendingIntsM; - logic InterruptM; + //logic InterruptM; logic [`XLEN-1:0] PrivilegedTrapVector, PrivilegedVectoredTrapVector; // Determine pending enabled interrupts diff --git a/wally-pipelined/testbench/testbench-imperas.sv b/wally-pipelined/testbench/testbench-imperas.sv index f7a77b6b..9b448126 100644 --- a/wally-pipelined/testbench/testbench-imperas.sv +++ b/wally-pipelined/testbench/testbench-imperas.sv @@ -354,7 +354,9 @@ module testbench(); "rv64p/WALLY-MARCHID", "4000", "rv64p/WALLY-MIMPID", "4000", "rv64p/WALLY-MHARTID", "4000", - "rv64p/WALLY-MVENDORID", "4000" + "rv64p/WALLY-MVENDORID", "4000", + "rv64p/WALLY-MIE", "3000", + "rv64p/WALLY-MEDELEG", "4000" }; string tests32p[] = '{ @@ -368,6 +370,7 @@ module testbench(); "rv32p/WALLY-MIMPID", "4000", "rv32p/WALLY-MHARTID", "4000", "rv32p/WALLY-MVENDORID", "4000" + //"rv32p/WALLY-MEDELEG", "4000" // all 32 bit tests are currently failing, so haven't been able to confirm this test works yet. It should, though. }; string tests64periph[] = '{ diff --git a/wally-pipelined/testgen/privileged/testgen-CAUSE.py b/wally-pipelined/testgen/privileged/testgen-CAUSE.py index c1841db7..e0af8a57 100644 --- a/wally-pipelined/testgen/privileged/testgen-CAUSE.py +++ b/wally-pipelined/testgen/privileged/testgen-CAUSE.py @@ -58,8 +58,44 @@ def writeVectors(storecmd, returningInstruction): # """) # User Timer Interrupt: True, 4 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # Supervior timer interrupt: True, 5 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # Machine timer interrupt: True, 7 + # TODO: THIS NEEDS TO BE IMPLEMENTED + + # 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""" # li x10, MASK_XLEN(0x8) @@ -121,10 +157,17 @@ def writeVectors(storecmd, returningInstruction): # """) # User external input: True, 8 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # Supervisor external input: True, 9 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # Machine externa input: True, 11 + # TODO: THIS NEEDS TO BE IMPLEMENTED # Instruction address misaligned: False, 0 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # looks like this is giving us an infinite loop for wally # 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 @@ -135,6 +178,7 @@ def writeVectors(storecmd, returningInstruction): # """, False, 0) # Instruction access fault: False, 1 + # TODO: THIS NEEDS TO BE IMPLEMENTED # Illegal Instruction writeTest(storecmd, f, r, f""" @@ -153,16 +197,14 @@ def writeVectors(storecmd, returningInstruction): """, False, 4) # Load Access fault: False, 5 + # TODO: THIS NEEDS TO BE IMPLEMENTED # Store/AMO address misaligned writeTest(storecmd, f, r, f""" sw x0, 11(x0) """, 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") + # Environment call if returningInstruction != "ecall": if fromMode == "u": writeTest(storecmd, f, r, f""" @@ -182,8 +224,13 @@ def writeVectors(storecmd, returningInstruction): """, False, 11, "m") # Instruction page fault: 12 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # Load page fault: 13 + # TODO: THIS NEEDS TO BE IMPLEMENTED + # Store/AMO page fault: 15 + # TODO: THIS NEEDS TO BE IMPLEMENTED @@ -194,7 +241,7 @@ def writeTest(storecmd, f, r, test, interrupt, code, mode = "m", resetHander = " expected = code if(interrupt): - expected+=(1 << (wordsize - 1)) + expected+=(1 << (xlen - 1)) trapEnd = "" @@ -316,6 +363,8 @@ for xlen in xlens: csrs sedeleg, x9 """ + clintAddr = "0x2004000" + lines += f""" li x30, 0 @@ -328,6 +377,32 @@ for xlen in xlens: j _j_t_begin_{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 {"csrr x25, mcause" if testMode == "m" else "li x25, 0xBAD00003"} diff --git a/wally-pipelined/testgen/privileged/testgen-DELEG.py b/wally-pipelined/testgen/privileged/testgen-DELEG.py new file mode 100644 index 00000000..79534df8 --- /dev/null +++ b/wally-pipelined/testgen/privileged/testgen-DELEG.py @@ -0,0 +1,291 @@ +#!/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) + + writeTest(storecmd, f, r, f""" + .fill 1, 4, 0 + """, False, 2) + + # 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 + # TODO: THIS NEEDS TO BE IMPLEMENTED + + # # Store/AMO address misaligned + writeTest(storecmd, f, r, f""" + sw x0, 11(x0) + """, False, 6) + + # Breakpoint: codes 8, 9, 11 + writeTest(storecmd, f, r, "ecall", False, -1) # code determined inside of writeTest + + # Instruction page fault: 12 + # TODO: THIS NEEDS TO BE IMPLEMENTED + + # Load page fault: 13 + # TODO: THIS NEEDS TO BE IMPLEMENTED + + # Store/AMO page fault: 15 + # TODO: THIS NEEDS TO BE IMPLEMENTED + + + #writeTest(storecmd, f, r, "ecall", False, 11, "m") + +def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): + global testnum + global testMode + global isInterrupts + + if interrupt != isInterrupts: + return + + delegateType = "i" if interrupt else "e" + for mode in (["m", "s", "u"] if testMode == "m" else ["s", "u"]): + + if test == "ecall": + if mode == "m": + code = 11 + elif mode == "s": + code = 9 + else: + code = 8 + + mask = 1 << code + 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 + """) + + testnum = 0 + for i in range(0, 2): + writeVectors(storecmd) + + 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() + + + diff --git a/wally-pipelined/testgen/privileged/testgen-IE.py b/wally-pipelined/testgen/privileged/testgen-IE.py index b0b77b0c..bb1ecd2c 100644 --- a/wally-pipelined/testgen/privileged/testgen-IE.py +++ b/wally-pipelined/testgen/privileged/testgen-IE.py @@ -20,84 +20,91 @@ from random import getrandbits # functions ################################## -def writeTrapHandlers(storecmd): +def writeTrapHandlers(storecmd, mode): global testnum [reg1, reg2, reg3] = [30, 29, 28] [reg4, reg5] = [27, 26] - lines = "\n# Trap Handler: Machine Timer Interupt\n" - lines += "_timerM_trap_handler:\n" - lines += "li x" + str(reg1) + ", MASK_XLEN(0x2A)\n" - lines += "la x" + str(reg2) + ", 0x2004000\n" - lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - lines += "csrrw x" + str(reg3) + ", mepc, x0\n" - lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" + if mode == "M": + lines = "\n# Trap Handler: Machine Timer Interupt\n" + lines += "_timerM_trap_handler:\n" + lines += "li x" + str(reg1) + ", MASK_XLEN(0xFFFF)\n" + lines += "la x" + str(reg2) + ", 0x2004000\n" + lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" + lines += "csrrc x" + str(reg3) + ", mepc, x0\n" + lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" + lines += "csrrw x0, mepc, x" + str(reg3) + "\n" + # clear machine timer interupt enable bit in mie + lines += "li x" + str(reg4) + ", MASK_XLEN(" + str(0x80) + ")\n" + lines += "csrrc x0, mie, x" + str(reg4) + "\n" + lines += "mret\n" + elif mode == "S": + lines = "\n# Trap Handler: Supervisor Timer Interupt\n" + lines += "_timerS_trap_handler:\n" + lines += "li x" + str(reg4) + ", MASK_XLEN(0x20)\n" + lines += "csrrc x0, mip, x" + str(reg4) + "\n" + lines += "csrrw x" + str(reg5) + ", mepc, x0\n" + lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" + lines += "mret\n" - lines += "\n# Trap Handler: Supervisor Timer Interupt\n" - lines += "_timerS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x20)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" + #lines += "\n# Trap Handler: User Timer Interupt\n" + #lines += "_timerU_trap_handler:\n" + #lines += "li x" + str(reg4) + ", MASK_XLEN(0x10)\n" + #lines += "csrrc x0, mip, x" + str(reg4) + "\n" + #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" + #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" + #lines += "mret\n" - lines += "\n# Trap Handler: User Timer Interupt\n" - lines += "_timerU_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x10)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" - - lines += "\n# Trap Handler: Machine Software Interupt\n" - lines += "_softwareM_trap_handler:\n" - lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT - lines += "la x" + str(reg2) + ", 0x2000000\n" - lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - lines += "csrrw x" + str(reg3) + ", mepc, x0\n" - lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" - - lines += "\n# Trap Handler: Supervisor Software Interupt\n" - lines += "_softwareS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x2)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" - - lines += "\n# Trap Handler: User Software Interupt\n" - lines += "_softwareU_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x1)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" - - lines += "\n# Trap Handler: Machine External Interupt\n" - lines += "_externalM_trap_handler:\n" + #lines += "\n# Trap Handler: Machine Software Interupt\n" + #lines += "_softwareM_trap_handler:\n" #lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT #lines += "la x" + str(reg2) + ", 0x2000000\n" #lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" - lines += "csrrw x" + str(reg3) + ", mepc, x0\n" - lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" + ##lines += "csrrs x" + str(reg3) + ", mepc, x0\n" + #lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" + #lines += "csrrw x0, mepc, x" + str(reg3) + "\n" + #lines += "mret\n" - lines += "\n# Trap Handler: Supervisor External Interupt\n" - lines += "_externalS_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x200)\n" + """lines += "\n# Trap Handler: Supervisor Software Interupt\n" + lines += "_softwareS_trap_handler:\n" + lines += "li x" + str(reg4) + ", MASK_XLEN(0x2)\n" lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" + lines += "csrrs x" + str(reg5) + ", mepc, x0\n" lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" + lines += "csrrw x0, mepc, x" + str(reg5) + "\n" lines += "mret\n" +""" + #lines += "\n# Trap Handler: User Software Interupt\n" + #lines += "_softwareU_trap_handler:\n" + #lines += "li x" + str(reg4) + ", MASK_XLEN(0x1)\n" + #lines += "csrrc x0, mip, x" + str(reg4) + "\n" + #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" + #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" + #lines += "mret\n" - lines += "\n# Trap Handler: User External Interupt\n" - lines += "_externalU_trap_handler:\n" - lines += "li x" + str(reg4) + ", MASK_XLEN(0x100)\n" - lines += "csrrc x0, mip, x" + str(reg4) + "\n" - lines += "csrrw x" + str(reg5) + ", mepc, x0\n" - lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" - lines += "mret\n" + #lines += "\n# Trap Handler: Machine External Interupt\n" + #lines += "_externalM_trap_handler:\n" + #lines += "li x" + str(reg1) + ", MASK_XLEN(0x0)\n" # clear MSIP bit in CLINT + #lines += "la x" + str(reg2) + ", 0x2000000\n" + #lines += str(storecmd) + " x" + str(reg1) + ", 0(x" + str(reg2) + ")\n" + #lines += "csrrw x" + str(reg3) + ", mepc, x0\n" + #lines += "addi x"+ str(reg3) + ", x" + str(reg3) + ", MASK_XLEN(0x4)\n" + #lines += "mret\n" + + #lines += "\n# Trap Handler: Supervisor External Interupt\n" + #lines += "_externalS_trap_handler:\n" + #lines += "li x" + str(reg4) + ", MASK_XLEN(0x200)\n" + #lines += "csrrc x0, mip, x" + str(reg4) + "\n" + #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" + #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" + #lines += "mret\n" + + #lines += "\n# Trap Handler: User External Interupt\n" + #lines += "_externalU_trap_handler:\n" + #lines += "li x" + str(reg4) + ", MASK_XLEN(0x100)\n" + #lines += "csrrc x0, mip, x" + str(reg4) + "\n" + #lines += "csrrw x" + str(reg5) + ", mepc, x0\n" + #lines += "addi x"+ str(reg5) + ", x" + str(reg5) + ", MASK_XLEN(0x4)\n" + #lines += "mret\n" f.write(lines) @@ -156,26 +163,32 @@ def getMcause(): def writeVectors(a, xlen, storecmd): global testnum - [reg1, reg2, reg3] = [1, 2, 3] + # Registers used: + # x13 ---> read mcause value + # x12 ---> save old value of mtvec + # x8 ---> holds mieE + # x5 ---> holds value of trap handler + # x3 ---> holds mstatusE + # remaining registers (not used by mode management) are free to be used by tests + + [reg2, reg3] = [2, 3] [reg5, reg8] = [5, 8] - [reg9, reg10, reg11, reg12] = [9, 10, 11, 12] + [reg10, reg11, reg12] = [10, 11, 12] + [reg13, reg14, reg15] = [13, 14, 15] lines = f"\n# Testcase {testnum}: {test} Interupt\n" # mcause code expected = getMcause() - lines = lines + "li x" + str(reg1) + ", MASK_XLEN(" + formatstr.format(expected) + ")\n" - - if (testnum == 0): expected = 0 [mstatusE, mieE] = getInteruptEnableValues() - # set interupt enable bit in mstatus - lines += "li x" + str(reg3) + ", MASK_XLEN(" + str(mstatusE) + ")\n" - lines += "csrrs x0, mstatus, x" + str(reg3) + "\n" + # ensure interupt enable bit in mie is low + lines += "li x" + str(reg8) + ", MASK_XLEN(" + formatstr.format(mieE) + ")\n" + lines += "csrrc x0, mie, x" + str(reg8) + "\n" - # set timer interupt enable bit in mie - lines += "li x" + str(reg9) + ", MASK_XLEN(" + str(mieE) + ")\n" - lines += "csrrs x0, mie, x" + str(reg3) + "\n" + # set interupt enable bit in mstatus + lines += "li x" + str(reg3) + ", MASK_XLEN(" + formatstr.format(mstatusE) + ")\n" + lines += "csrrs x0, mstatus, x" + str(reg3) + "\n" # Save and set trap handler address for interrupt lines += "la x" + str(reg5) + ", _" + test + "_trap_handler\n" @@ -185,59 +198,50 @@ def writeVectors(a, xlen, storecmd): # cause timer interupt if test == "timerM": - lines += "li x" + str(reg8) + ", MASK_XLEN(0)\n" - lines += str(storecmd) + " x" + str(reg8) + ", " + str(wordsize*testnum)+ "(x6)\n" - lines += "la x" + str(reg8) + ", 0x2004000\n" + # load MTIMECMP register address + lines += "la x" + str(reg2) + ", 0x2004000\n" - lines += "li x" + str(reg3) + ", MASK_XLEN(0)\n" + # to be stored in MTIMECMP + lines += "li x" + str(reg10) + ", MASK_XLEN(0)\n" # save old value of mtimecmp and then set mtimecmp to zero - lines += "lw x" + str(reg11) + ", 0(x" + str(reg8) + ")\n" - lines += str(storecmd) + " x" + str(reg3) + ", 0(x" + str(reg8) + ")\n" + if xlens == 64: + lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" + lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" + + elif xlen == 32: + lines += "lw x" + str(reg11) + ", 0(x" + str(reg2) + ")\n" + lines += str(storecmd) + " x" + str(reg10) + ", 0(x" + str(reg2) + ")\n" + lines += str(storecmd) + " x" + str(reg10) + ", 4(x" + str(reg2) + ")\n" + elif test == "timerS": lines += "li x" + str(reg3) + ", MASK_XLEN(0x20)\n" lines += "csrrs x0, mip, x" + str(reg3) + "\n" - elif test == "timerU": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x10)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" # cause software interupt if test == "softwareM": lines += "la x" + str(reg8) + ", 0x2000000\n" # Write to the MSIP bit in CLINT - lines += "li x" + str(reg3) + ", MASK_XLEN(0x1)\n" - lines += str(storecmd) + " x" + str(reg3) + ", 0(x" + str(reg8) + ")\n" + lines += "li x" + str(reg11) + ", MASK_XLEN(0x1)\n" + lines += str(storecmd) + " x" + str(reg11) + ", 0(x" + str(reg8) + ")\n" elif test == "softwareS": lines += "li x" + str(reg3) + ", MASK_XLEN(0x2)\n" lines += "csrrs x0, mip, x" + str(reg3) + "\n" - elif test == "softwareU": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x1)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - # cause external interupt - # Not sure how to cause an external machine interupt yet - # will writing to PLIC just cause it? (where is the ExtIntM located in PLIC) - #if test == "externalM": - #lines += "la x" + str(reg8) + ", 0x2000000\n" # Write to the MSIP bit in CLINT - #lines += "li x" + str(reg3) + ", MASK_XLEN(0x1)\n" - #lines += str(storecmd) + " x" + str(reg3) + ", 0(x" + str(reg8) + ")\n" - if test == "externalS": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x200)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - elif test == "externalU": - lines += "li x" + str(reg3) + ", MASK_XLEN(0x100)\n" - lines += "csrrs x0, mip, x" + str(reg3) + "\n" - #lines += "wfi\n" # wait for interupt to be taken + # set timer interupt enable bit in mie + lines += "csrrs x0, mie, x" + str(reg8) + "\n" + + # wait for interupt to be taken lines += "nop\nnop\n" - lines += "csrrw " + " x" + str(reg2) + ", mcause, x" + str(reg1) + "\n" - + lines += "csrrs " + " x" + str(reg13) + ", mcause, x0\n" + # reset mtvec lines += "csrrw x0, mtvec, x" + str(reg12) + "\n" - lines += storecmd + " x" + str(reg2) + ", " + str(wordsize*testnum) + "(x6)\n" - lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg2) +", "+formatstr.format(expected)+")\n" + lines += storecmd + " x" + str(reg13) + ", " + str(wordsize*testnum) + "(x6)\n" + lines += "RVTEST_IO_ASSERT_GPR_EQ(x7, x" + str(reg13) +", "+formatstr.format(expected)+")\n" f.write(lines) if (xlen == 32): line = formatrefstr.format(expected)+"\n" @@ -251,9 +255,10 @@ def writeVectors(a, xlen, storecmd): ################################## # change these to suite your tests -tests = ["timerM"] #, "timerS", "timerU", "softwareM", "softwareS", "softwareU"] +tests = ["timerM"] #, "timerM", "timerS", "softwareM", "softwareS"] author = "ushakya@hmc.edu" -xlens = [64, 32] +xlens = [64] #, 32] +modes = ["M"]#, "S"] numrand = 100; # setup @@ -270,9 +275,9 @@ for xlen in xlens: else: storecmd = "sd" wordsize = 8 - for test in tests: + for mode in modes: imperaspath = "../../../imperas-riscv-tests/riscv-test-suite/rv" + str(xlen) + "p/" - basename = "WALLY-IE" + basename = "WALLY-" + mode + "IE" fname = imperaspath + "src/" + basename + ".S" refname = imperaspath + "references/" + basename + ".reference_output" testnum = 0 @@ -291,13 +296,99 @@ for xlen in xlens: h = open("../testgen_header.S", "r") for line in h: f.write(line) + + line = "\n" + # Registers used for dropping down to supervisor mode: + # x30 ---> set to 1 if we should return to & stay in machine mode after trap, 0 otherwise + # x20 ---> hold address of _j_all_end_{returningInstruction} + # x19 ---> save old value of mtvec + # x18 ---> save old value of medeleg + # x16 ---> save old value of mideleg + # x9 ---> bit mask for mideleg and medeleg + # x1 ---> used to go down to supervisor mode - # print directed and random test vectors - for i in range(0,numrand): - a = getrandbits(xlen) - writeVectors(a, xlen, storecmd) + # We need to leave at least one bit in medeleg unset so that we have a way to get + # back to machine mode when the tests are complete (otherwise we'll only ever be able + # to get up to supervisor mode). + # + # So, we define a returning instruction which will be used to cause the exception that + # brings us into machine mode. The bit for this returning instruction is NOT set in + # medeleg. However, this also means that we can't test that instruction. So, we have + # two different returning instructions. + # + # Current code is written to only support ebreak and ecall. + # + # For testgen-IE, we don't need to test ebreak, so we can use that as the sole + # returning instruction. + returningInstruction = "ebreak" + if mode == "S": + # need to move down to supervisor mode (based on code in testgen-TVAL) + lines += f""" + # Reset x30 to 0 so we can run the tests. We'll set this to 1 when tests are completed so we stay in machine mode + li x30, 0 + """ - writeTrapHandlers(storecmd) + # We don't want to delegate our returning instruction. Otherwise, we'll have no way of getting + # back to machine mode at the end! (and we need to be in machine mode to complete the tests) + medelegMask = "0b1111111111110111" if returningInstruction == "ebreak" else "0b1111000011111111" + + # Set medeleg and mideleg + lines += f""" + csrr x18, medeleg + li x9, {medelegMask if testMode == "s" or testMode == "u" else "0"} + csrw medeleg, x9 + + csrr x16, mideleg + li x9, {"0xffffffff" if testMode == "s" or testMode == "u" else "0"} + csrw mideleg, x9 + """ + + # bring down to supervisor mode + lines += f""" + li x1, 0b110000000000 + csrrc x28, mstatus, x1 + li x1, 0b0100000000000 + 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 supervisor mode... + """ + + for test in tests: + # print directed and random test vectors + for i in range(0,numrand): + a = getrandbits(xlen) + writeVectors(a, xlen, storecmd) + + if mode == "S": + # Bring us back up to machine mode! + # Creates a new trap handler that just jumps to _j_all_end_{returningInstruction} + # + # Get into the trap handler by running returningInstruction (in this case its ebreak) + f.write(f""" + li x30, 1 #may not need this + csrr x19, mtvec # save old value of mtvec + la x20 _j_all_end_{returningInstruction} + csrw mtvec, x20 + {returningInstruction} + + _returnMachineMode_handler: + j _j_all_end_{returningInstruction} + mret + + _j_all_end_{returningInstruction}: + + # Reset trap handling csrs to old values + csrw mtvec, x19 + csrw medeleg, x18 + csrw mideleg, x16 + """) + + f.write(lines) # print footer h = open("../testgen_footer.S", "r") @@ -308,5 +399,8 @@ for xlen in xlens: lines = ".fill " + str(testnum) + ", " + str(wordsize) + ", -1\n" lines = lines + "\nRV_COMPLIANCE_DATA_END\n" f.write(lines) + + writeTrapHandlers(storecmd, mode) + f.close() r.close() diff --git a/wally-pipelined/testgen/privileged/testgen-TVEC.py b/wally-pipelined/testgen/privileged/testgen-TVEC.py index 2e4bb8b9..a6eef5d2 100644 --- a/wally-pipelined/testgen/privileged/testgen-TVEC.py +++ b/wally-pipelined/testgen/privileged/testgen-TVEC.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 ################################## -# testgen-CAUSE.py (new) +# testgen-TVEC.py (new) # # dottolia@hmc.edu 1 Mar 2021 # @@ -25,6 +25,12 @@ from random import randint from random import seed from random import getrandbits +################################## +# setup +################################## + +areVectoredTrapsSupported = True + ################################## # functions ################################## @@ -43,29 +49,6 @@ def randRegs(): def writeVectors(storecmd, returningInstruction): 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 writeTest(storecmd, f, r, f""" @@ -112,6 +95,35 @@ def writeVectors(storecmd, returningInstruction): ecall """, 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 # Load page fault: 13 # Store/AMO page fault: 15 @@ -144,14 +156,13 @@ def writeTest(storecmd, f, r, test, interrupt, code, resetHander = ""): {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""" {storecmd} x25, {testnum * wordsize}(x6) """ + if not areVectoredTrapsSupported: + expected = 0 + f.write(lines) if (xlen == 32): line = formatrefstr.format(expected)+"\n" @@ -291,7 +302,7 @@ for xlen in xlens: # Set up la x1, _j_m_trap_{returningInstruction} - addi x1, 1 + #addi x1, 1 csrw mtvec, x1 la x1, _j_s_trap_{returningInstruction} csrw stvec, x1