Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main

This commit is contained in:
Ross Thompson 2022-04-13 13:39:47 -05:00
commit 65573f07b7
3 changed files with 51 additions and 29 deletions

View File

@ -102,8 +102,8 @@ then
# Priority Levels for sources 1 thru 63
x/63xw 0x0C000004
# Interrupt Enables for sources 1 thru 63 for contexts 0 and 1
x/2xw 0x0C020000
x/2xw 0x0C020080
x/2xw 0x0C002000
x/2xw 0x0C002080
# Global Priority Threshold for contexts 0 and 1
x/1xw 0x0C200000
x/1xw 0x0C201000

View File

@ -26,11 +26,8 @@ def strip0x(num):
return num[2:]
def stripZeroes(num):
num = num.strip('0')
if num=='':
return '0'
else:
return num
num = int(num,16)
return hex(num)[2:]
#############
# Main Code #
@ -84,11 +81,11 @@ with open(rawPlicStateFile, 'r') as rawPlicStateFile:
# 0x0C020000 thru 0x0C020004
plicIntEnable = tokenize(rawPlicStateFile.readline())[1:]
plicIntEnable = map(strip0x,plicIntEnable)
plicIntEnableArray.append(reduce(lambda x,y: x+y,plicIntEnable))
plicIntEnableArray.append(reduce(lambda x,y: y+x,plicIntEnable))
# 0x0C020080 thru 0x0C020084
plicIntEnable = tokenize(rawPlicStateFile.readline())[1:]
plicIntEnable = map(strip0x,plicIntEnable)
plicIntEnableArray.append(reduce(lambda x,y: x+y,plicIntEnable))
plicIntEnableArray.append(reduce(lambda x,y: y+x,plicIntEnable))
plicIntPriorityThresholdArray = [] # iterates over number of different contexts
# 0x0C200000
@ -101,6 +98,7 @@ with open(outDir+'checkpoint-PLIC_INT_PRIORITY', 'w') as outFile:
outFile.write(stripZeroes(word[2:])+'\n')
with open(outDir+'checkpoint-PLIC_INT_ENABLE', 'w') as outFile:
for word in plicIntEnableArray:
word = hex(int(word,16)>>1)[2:] # right shift by 1 because source 0 does not exist
outFile.write(stripZeroes(word)+'\n')
with open(outDir+'checkpoint-PLIC_THRESHOLD', 'w') as outFile:
for word in plicIntPriorityThresholdArray:

View File

@ -182,6 +182,7 @@ module testbench;
`define UART_LCR `UART.LCR
`define UART_MCR `UART.MCR
`define UART_SCR `UART.SCR
`define UART_IP `UART.INTR
`define PLIC dut.uncore.plic.plic
`define PLIC_INT_PRIORITY `PLIC.intPriority
`define PLIC_INT_ENABLE `PLIC.intEn
@ -376,7 +377,7 @@ module testbench;
`INIT_CHECKPOINT_VAL(SATP, [`XLEN-1:0]);
`INIT_CHECKPOINT_VAL(PRIV, [1:0]);
`INIT_CHECKPOINT_PACKED_ARRAY(PLIC_INT_PRIORITY, [2:0],`PLIC_NUM_SRC,1);
`INIT_CHECKPOINT_PACKED_ARRAY(PLIC_INT_ENABLE, [`PLIC_NUM_SRC:1],1,0);
`MAKE_CHECKPOINT_INIT_SIGNAL(PLIC_INT_ENABLE, [`PLIC_NUM_SRC:0],1,0);
`INIT_CHECKPOINT_PACKED_ARRAY(PLIC_THRESHOLD, [2:0],1,0);
// UART checkpointing does not cover entire UART state
// Many UART registers are difficult to initialize because under the hood
@ -399,6 +400,7 @@ module testbench;
if(!NO_IE_MTIME_CHECKPOINT) begin
force `MEIP = 0;
force `SEIP = 0;
force `UART_IP = 0;
force `MTIP = 0;
end
$sformat(testvectorDir,"%s/linux-testvectors/",RISCV_DIR);
@ -446,6 +448,7 @@ module testbench;
force {`STATUS_SPP,`STATUS_MPIE} = initMSTATUS[0][8:7];
force {`STATUS_SPIE,`STATUS_UPIE,`STATUS_MIE} = initMSTATUS[0][5:3];
force {`STATUS_SIE,`STATUS_UIE} = initMSTATUS[0][1:0];
force `PLIC_INT_ENABLE = {initPLIC_INT_ENABLE[1][`PLIC_NUM_SRC:1],initPLIC_INT_ENABLE[0][`PLIC_NUM_SRC:1]}; // would need to expand into a generate loop to cover an arbitrary number of contexts
force `INSTRET = CHECKPOINT;
while (reset!==1) #1;
while (reset!==0) #1;
@ -455,6 +458,7 @@ module testbench;
release {`STATUS_SPP,`STATUS_MPIE};
release {`STATUS_SPIE,`STATUS_UPIE,`STATUS_MIE};
release {`STATUS_SIE,`STATUS_UIE};
release `PLIC_INT_ENABLE;
release `INSTRET;
end
// Get the E-stage trace reader ahead of the M-stage trace reader
@ -481,6 +485,9 @@ module testbench;
if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line``STAGE); \
// extract PC, Instr \
matchCount``STAGE = $sscanf(line``STAGE, "%x %x %s", ExpectedPC``STAGE, ExpectedInstr``STAGE, text``STAGE); \
if (`"STAGE`"=="M") begin \
AttemptedInstructionCount += 1; \
end \
\
// for the life of me I cannot get any build in C or C++ string parsing functions/methods to work. \
// strtok was the best idea but it cannot be used correctly as system verilog does not have null \
@ -493,9 +500,6 @@ module testbench;
for(index``STAGE = 0; index``STAGE < line``STAGE.len(); index``STAGE++) begin \
//$display("char = %s", line``STAGE[index]); \
if (line``STAGE[index``STAGE] == " " | line``STAGE[index``STAGE] == "\n") begin \
if (line``STAGE[index``STAGE] == "\n" & `"STAGE`"=="M") begin \
AttemptedInstructionCount += 1; \
end \
EndIndex``STAGE = index``STAGE; \
ExpectedTokens``STAGE[TokenIndex``STAGE] = line``STAGE.substr(StartIndex``STAGE, EndIndex``STAGE-1); \
//$display("In Tokenizer %s", line``STAGE.substr(StartIndex, EndIndex-1)); \
@ -560,14 +564,14 @@ module testbench;
// ========== VALUE-CHECKING MACROS ==========
`define checkEQ(NAME, VAL, EXPECTED) \
if(VAL != EXPECTED) begin \
$display("%tns, %d instrs: %s %x differs from expected %x", $time, InstrCountW, NAME, VAL, EXPECTED); \
$display("%tns, %d instrs: %s %x differs from expected %x", $time, AttemptedInstructionCount, NAME, VAL, EXPECTED); \
if ((NAME == "PCW") | (`DEBUG_TRACE >= 2)) fault = 1; \
end
`define checkCSR(CSR) \
begin \
if (CSR != ExpectedCSRArrayValueW[NumCSRPostWIndex]) begin \
$display("%tns, %d instrs: CSR %s = %016x, does not equal expected value %016x", $time, InstrCountW, ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \
$display("%tns, %d instrs: CSR %s = %016x, does not equal expected value %016x", $time, AttemptedInstructionCount, ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \
if(`DEBUG_TRACE >= 3) fault = 1; \
end \
end
@ -627,12 +631,12 @@ module testbench;
// override on special conditions
if(~dut.core.StallW) begin
if(textW.substr(0,5) == "rdtime") begin
//$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, InstrCountW);
//$display("%tns, %d instrs: Releasing force of MTIME_CLINT.", $time, AttemptedInstructionCount);
if(!NO_IE_MTIME_CHECKPOINT)
release dut.uncore.clint.clint.MTIME;
end
//if (ExpectedIEUAdrM == 'h10000005) begin
//$display("%tns, %d instrs: releasing force of ReadDataM.", $time, InstrCountW);
//$display("%tns, %d instrs: releasing force of ReadDataM.", $time, AttemptedInstructionCount);
//release dut.core.ieu.dp.ReadDataM;
//end
end
@ -642,15 +646,16 @@ module testbench;
// step2: make all checks in the write back stage.
assign checkInstrW = InstrValidW & ~dut.core.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
always @(negedge clk) begin
#1; // small delay allows interrupt spoofing to happen first
// always check PC, instruction bits
if (checkInstrW) begin
InstrCountW += 1;
// print progress message
if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW);
if (AttemptedInstructionCount % 'd100000 == 0) $display("Reached %d instructions", AttemptedInstructionCount);
// turn on waves
if (InstrCountW == INSTR_WAVEON) $stop;
if (AttemptedInstructionCount == INSTR_WAVEON) $stop;
// end sim
if ((InstrCountW == INSTR_LIMIT) & (INSTR_LIMIT!=0)) $stop;
if ((AttemptedInstructionCount == INSTR_LIMIT) & (INSTR_LIMIT!=0)) $stop;
fault = 0;
if (`DEBUG_TRACE >= 1) begin
`checkEQ("PCW",PCW,ExpectedPCW)
@ -659,8 +664,8 @@ module testbench;
`checkEQ("Instr Count",dut.core.priv.priv.csr.counters.counters.INSTRET_REGW,InstrCountW)
#2; // delay 2 ns.
if(`DEBUG_TRACE >= 5) begin
$display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, InstrCountW, dut.core.ieu.dp.regf.a3, ExpectedRegAdrW);
$display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.core.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
$display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, AttemptedInstructionCount, dut.core.ieu.dp.regf.a3, ExpectedRegAdrW);
$display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, AttemptedInstructionCount, ExpectedRegAdrW, dut.core.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
end
if (RegWriteW == "GPR") begin
`checkEQ("Reg Write Address",dut.core.ieu.dp.regf.a3,ExpectedRegAdrW)
@ -703,6 +708,8 @@ module testbench;
force `MEIP = 0;
if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<09) == 0)
force `SEIP = 0;
if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & ((1<<11) | (1<<09))) == 0)
force `UART_IP = 0;
if ((ExpectedCSRArrayValueW[NumCSRPostWIndex] & 1<<07) == 0)
force `MTIP = 0;
end
@ -711,7 +718,7 @@ module testbench;
end
if (fault == 1) begin
errorCount +=1;
$display("processed %0d instructions with %0d warnings", InstrCountW, warningCount);
$display("processed %0d instructions with %0d warnings", AttemptedInstructionCount, warningCount);
$stop;
end
end // if (`DEBUG_TRACE >= 1)
@ -720,22 +727,39 @@ module testbench;
// New IP spoofing
always @(posedge clk) begin
#1
logic globalIntsBecomeEnabled;
assign globalIntsBecomeEnabled = (`CSR_BASE.csrm.WriteMSTATUSM || `CSR_BASE.csrs.WriteSSTATUSM) && (|(`CSR_BASE.CSRWriteValM & (~`CSR_BASE.csrm.MSTATUS_REGW) & 32'h22));
always @(negedge clk) begin
if(checkInstrM) begin
if((interruptInstrCount+1) == AttemptedInstructionCount) begin
if(!NO_IE_MTIME_CHECKPOINT) begin
case (interruptCauseVal)
11: force `MEIP = 1;
09: force `SEIP = 1;
11: begin
force `MEIP = 1;
force `UART_IP = 1;
end
09: begin
force `SEIP = 1;
force `UART_IP = 1;
end
07: force `MTIP = 1;
default: $display("Unsupported interrupt in interrupts.txt. cause = %0d",interruptCauseVal);
endcase
$display("Forcing interrupt.");
end
`SCAN_NEW_INTERRUPT
garbageInt = $fgets(garbageString,traceFileE);
garbageInt = $fgets(garbageString,traceFileM);
if (globalIntsBecomeEnabled) begin
$display("Enabled global interrupts");
// The idea here is if a CSR instruction causes an interrupt by
// enabling interrupts, that CSR instruction will commit.
end else begin
// Other instructions, however, will get interrupted and not
// commit, so we don't want our W-stage checker to look for them
// and get confused when it doesn't find them.
garbageInt = $fgets(garbageString,traceFileE);
garbageInt = $fgets(garbageString,traceFileM);
AttemptedInstructionCount += 1;
end
end
end
end