mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of github.com:davidharrishmc/riscv-wally into main
This commit is contained in:
commit
65573f07b7
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user