mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
fix testbench interrupt timing
This commit is contained in:
parent
0cc71f1dec
commit
0c7681b942
@ -60,20 +60,26 @@ add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/c/RegWriteD
|
|||||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD
|
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/RdD
|
||||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D
|
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs1D
|
||||||
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D
|
add wave -noupdate -group {Decode Stage} /testbench/dut/hart/ieu/dp/Rs2D
|
||||||
add wave -noupdate -group {Execution Stage} /testbench/dut/hart/ifu/PCE
|
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/PCE
|
||||||
add wave -noupdate -group {Execution Stage} /testbench/InstrEName
|
add wave -noupdate -expand -group {Execution Stage} /testbench/dut/hart/ifu/InstrE
|
||||||
add wave -noupdate -group {Execution Stage} /testbench/dut/hart/ifu/InstrE
|
add wave -noupdate -expand -group {Execution Stage} /testbench/InstrEName
|
||||||
add wave -noupdate -group {Execution Stage} -color {Cornflower Blue} /testbench/FunctionName/FunctionName
|
add wave -noupdate -expand -group {Execution Stage} /testbench/textE
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/priv/trap/InstrValidM
|
add wave -noupdate -expand -group {Execution Stage} -color {Cornflower Blue} /testbench/FunctionName/FunctionName
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/PCM
|
add wave -noupdate -expand -group {Memory Stage} /testbench/checkInstrM
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/InstrMName
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/priv/trap/InstrValidM
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/InstrM
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/PCM
|
||||||
add wave -noupdate -group {Memory Stage} /testbench/dut/hart/lsu/MemAdrM
|
add wave -noupdate -expand -group {Memory Stage} /testbench/ExpectedPCM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/PCW
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/InstrM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/InstrW
|
add wave -noupdate -expand -group {Memory Stage} /testbench/InstrMName
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/InstrWName
|
add wave -noupdate -expand -group {Memory Stage} /testbench/textM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/InstrValidW
|
add wave -noupdate -expand -group {Memory Stage} /testbench/dut/hart/lsu/MemAdrM
|
||||||
add wave -noupdate -group {WriteBack stage} /testbench/checkInstrW
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/checkInstrW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/InstrValidW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/PCW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/ExpectedPCW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/InstrW
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/InstrWName
|
||||||
|
add wave -noupdate -expand -group {WriteBack stage} /testbench/textW
|
||||||
add wave -noupdate -group Bpred -color Orange /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/GHR
|
add wave -noupdate -group Bpred -color Orange /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/GHR
|
||||||
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/BPPredF
|
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} /testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/BPPredF
|
||||||
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} {/testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/InstrClassE[0]}
|
add wave -noupdate -group Bpred -expand -group {branch update selection inputs} {/testbench/dut/hart/ifu/bpred/bpred/Predictor/DirPredictor/InstrClassE[0]}
|
||||||
@ -484,7 +490,6 @@ add wave -noupdate -group {debug trace} -expand -group mem /testbench/dut/hart/p
|
|||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/checkInstrM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/checkInstrM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/dut/hart/PCM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/dut/hart/PCM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/ExpectedPCM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/ExpectedPCM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/line
|
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem /testbench/textM
|
add wave -noupdate -group {debug trace} -expand -group mem /testbench/textM
|
||||||
add wave -noupdate -group {debug trace} -expand -group mem -color Brown /testbench/dut/hart/hzu/TrapM
|
add wave -noupdate -group {debug trace} -expand -group mem -color Brown /testbench/dut/hart/hzu/TrapM
|
||||||
add wave -noupdate -group {debug trace} -expand -group wb /testbench/checkInstrW
|
add wave -noupdate -group {debug trace} -expand -group wb /testbench/checkInstrW
|
||||||
@ -510,7 +515,7 @@ add wave -noupdate /testbench/dut/uncore/dtim/memwrite
|
|||||||
add wave -noupdate /testbench/dut/uncore/dtim/HWDATA
|
add wave -noupdate /testbench/dut/uncore/dtim/HWDATA
|
||||||
add wave -noupdate /testbench/dut/uncore/dtim/risingHREADYTim
|
add wave -noupdate /testbench/dut/uncore/dtim/risingHREADYTim
|
||||||
TreeUpdate [SetDefaultTree]
|
TreeUpdate [SetDefaultTree]
|
||||||
WaveRestoreCursors {{Cursor 23} {209183247 ns} 0} {{Cursor 5} {229 ns} 0}
|
WaveRestoreCursors {{Cursor 23} {209183247 ns} 0} {{Cursor 5} {5672440 ns} 0}
|
||||||
quietly wave cursor active 2
|
quietly wave cursor active 2
|
||||||
configure wave -namecolwidth 250
|
configure wave -namecolwidth 250
|
||||||
configure wave -valuecolwidth 314
|
configure wave -valuecolwidth 314
|
||||||
@ -526,4 +531,4 @@ configure wave -griddelta 40
|
|||||||
configure wave -timeline 0
|
configure wave -timeline 0
|
||||||
configure wave -timelineunits ns
|
configure wave -timelineunits ns
|
||||||
update
|
update
|
||||||
WaveRestoreZoom {182 ns} {330 ns}
|
WaveRestoreZoom {5672937 ns} {5673085 ns}
|
||||||
|
@ -103,30 +103,35 @@ module testbench();
|
|||||||
string checkpointDir;
|
string checkpointDir;
|
||||||
logic [1:0] initPriv;
|
logic [1:0] initPriv;
|
||||||
// Signals used to parse the trace file
|
// Signals used to parse the trace file
|
||||||
integer data_file_all;
|
`define DECLARE_TRACE_SCANNER_SIGNALS(STAGE) \
|
||||||
string name;
|
integer traceFile``STAGE; \
|
||||||
integer matchCount;
|
integer matchCount``STAGE; \
|
||||||
string line;
|
string line``STAGE; \
|
||||||
logic [`XLEN-1:0] ExpectedPCM;
|
string token``STAGE; \
|
||||||
logic [31:0] ExpectedInstrM;
|
string ExpectedTokens``STAGE [31:0]; \
|
||||||
string textM;
|
integer index``STAGE; \
|
||||||
string token;
|
integer StartIndex``STAGE, EndIndex``STAGE; \
|
||||||
string ExpectedTokens [31:0];
|
integer TokenIndex``STAGE; \
|
||||||
integer index;
|
integer MarkerIndex``STAGE; \
|
||||||
integer StartIndex, EndIndex;
|
integer NumCSR``STAGE; \
|
||||||
integer TokenIndex;
|
logic [`XLEN-1:0] ExpectedPC``STAGE; \
|
||||||
integer MarkerIndex;
|
logic [31:0] ExpectedInstr``STAGE; \
|
||||||
integer NumCSRM;
|
string text``STAGE; \
|
||||||
|
string MemOp``STAGE; \
|
||||||
|
string RegWrite``STAGE; \
|
||||||
|
integer ExpectedRegAdr``STAGE; \
|
||||||
|
logic [`XLEN-1:0] ExpectedRegValue``STAGE; \
|
||||||
|
logic [`XLEN-1:0] ExpectedMemAdr``STAGE, ExpectedMemReadData``STAGE, ExpectedMemWriteData``STAGE; \
|
||||||
|
string ExpectedCSRArray``STAGE[10:0]; \
|
||||||
|
logic [`XLEN-1:0] ExpectedCSRArrayValue``STAGE[10:0];
|
||||||
|
`DECLARE_TRACE_SCANNER_SIGNALS(E)
|
||||||
|
`DECLARE_TRACE_SCANNER_SIGNALS(M)
|
||||||
|
integer NextMIPexpected;
|
||||||
|
integer NextMepcExpected;
|
||||||
// Memory stage expected values from trace
|
// Memory stage expected values from trace
|
||||||
logic checkInstrM;
|
logic checkInstrM;
|
||||||
integer MIPexpected;
|
integer MIPexpected;
|
||||||
string RegWriteM;
|
string name;
|
||||||
integer ExpectedRegAdrM;
|
|
||||||
logic [`XLEN-1:0] ExpectedRegValueM;
|
|
||||||
string MemOpM;
|
|
||||||
logic [`XLEN-1:0] ExpectedMemAdrM, ExpectedMemReadDataM, ExpectedMemWriteDataM;
|
|
||||||
string ExpectedCSRArrayM[10:0];
|
|
||||||
logic [`XLEN-1:0] ExpectedCSRArrayValueM[10:0];
|
|
||||||
logic [`AHBW-1:0] readDataExpected;
|
logic [`AHBW-1:0] readDataExpected;
|
||||||
// Write back stage expected values from trace
|
// Write back stage expected values from trace
|
||||||
logic checkInstrW;
|
logic checkInstrW;
|
||||||
@ -148,6 +153,11 @@ module testbench();
|
|||||||
integer NumCSRPostWIndex;
|
integer NumCSRPostWIndex;
|
||||||
logic [`XLEN-1:0] InstrCountW;
|
logic [`XLEN-1:0] InstrCountW;
|
||||||
integer RequestDelayedMIP;
|
integer RequestDelayedMIP;
|
||||||
|
integer ForceMIPFuture;
|
||||||
|
integer CSRIndex;
|
||||||
|
longint MepcExpected;
|
||||||
|
integer CheckMIPFutureE;
|
||||||
|
integer CheckMIPFutureM;
|
||||||
// Useful Aliases
|
// Useful Aliases
|
||||||
`define RF dut.hart.ieu.dp.regf.rf
|
`define RF dut.hart.ieu.dp.regf.rf
|
||||||
`define PC dut.hart.ifu.pcreg.q
|
`define PC dut.hart.ifu.pcreg.q
|
||||||
@ -292,13 +302,15 @@ module testbench();
|
|||||||
ProgramLabelMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.lab"};
|
ProgramLabelMapFile = {`LINUX_TEST_VECTORS,"vmlinux.objdump.lab"};
|
||||||
if (CHECKPOINT==0) begin // normal
|
if (CHECKPOINT==0) begin // normal
|
||||||
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
$readmemh({`LINUX_TEST_VECTORS,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||||
data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
traceFileM = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
||||||
|
traceFileE = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
|
||||||
InstrCountW = '0;
|
InstrCountW = '0;
|
||||||
end else begin // checkpoint
|
end else begin // checkpoint
|
||||||
$sformat(checkpointDir,"checkpoint%0d/",CHECKPOINT);
|
$sformat(checkpointDir,"checkpoint%0d/",CHECKPOINT);
|
||||||
checkpointDir = {`LINUX_TEST_VECTORS,checkpointDir};
|
checkpointDir = {`LINUX_TEST_VECTORS,checkpointDir};
|
||||||
$readmemh({checkpointDir,"ram.txt"}, dut.uncore.dtim.RAM);
|
$readmemh({checkpointDir,"ram.txt"}, dut.uncore.dtim.RAM);
|
||||||
data_file_all = $fopen({checkpointDir,"all.txt"}, "r");
|
traceFileE = $fopen({checkpointDir,"all.txt"}, "r");
|
||||||
|
traceFileM = $fopen({checkpointDir,"all.txt"}, "r");
|
||||||
InstrCountW = CHECKPOINT;
|
InstrCountW = CHECKPOINT;
|
||||||
// manual checkpoint initializations that don't neatly fit into MACRO
|
// manual checkpoint initializations that don't neatly fit into MACRO
|
||||||
force {`STATUS_TSR,`STATUS_TW,`STATUS_TVM,`STATUS_MXR,`STATUS_SUM,`STATUS_MPRV} = initMSTATUS[0][22:17];
|
force {`STATUS_TSR,`STATUS_TW,`STATUS_TVM,`STATUS_MXR,`STATUS_SUM,`STATUS_MPRV} = initMSTATUS[0][22:17];
|
||||||
@ -319,8 +331,12 @@ module testbench();
|
|||||||
release `INSTRET;
|
release `INSTRET;
|
||||||
release `CURR_PRIV;
|
release `CURR_PRIV;
|
||||||
end
|
end
|
||||||
|
// Get the E-stage trace reader ahead of the M-stage trace reader
|
||||||
|
matchCountE = $fgets(lineE,traceFileE);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////// CORE /////////////////////////////////////
|
//////////////////////////////////// CORE /////////////////////////////////////
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -332,94 +348,158 @@ module testbench();
|
|||||||
// on the next falling edge the expected state is compared to the wally state.
|
// on the next falling edge the expected state is compared to the wally state.
|
||||||
|
|
||||||
// step 0: read the expected state
|
// step 0: read the expected state
|
||||||
assign checkInstrM = dut.hart.ieu.InstrValidM & ~dut.hart.priv.trap.InstrPageFaultM & ~dut.hart.priv.trap.InterruptM & ~dut.hart.StallM;
|
assign checkInstrM = dut.hart.ieu.InstrValidM & ~dut.hart.priv.trap.InstrPageFaultM & ~dut.hart.priv.trap.InterruptM & ~dut.hart.StallM;
|
||||||
|
`define SCAN_NEW_INSTR_FROM_TRACE(STAGE) \
|
||||||
|
// always check PC, instruction bits \
|
||||||
|
if (checkInstrM) begin \
|
||||||
|
// read 1 line of the trace file \
|
||||||
|
matchCount``STAGE = $fgets(line``STAGE, traceFile``STAGE); \
|
||||||
|
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); \
|
||||||
|
\
|
||||||
|
// 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 \
|
||||||
|
// terminated strings. \
|
||||||
|
\
|
||||||
|
// Just going to do this char by char. \
|
||||||
|
StartIndex``STAGE = 0; \
|
||||||
|
TokenIndex``STAGE = 0; \
|
||||||
|
//$display("len = %d", line``STAGE.len()); \
|
||||||
|
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 \
|
||||||
|
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)); \
|
||||||
|
StartIndex``STAGE = EndIndex``STAGE + 1; \
|
||||||
|
TokenIndex``STAGE++; \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
\
|
||||||
|
MarkerIndex``STAGE = 3; \
|
||||||
|
NumCSR``STAGE = 0; \
|
||||||
|
MemOp``STAGE = ""; \
|
||||||
|
RegWrite``STAGE = ""; \
|
||||||
|
\
|
||||||
|
#2; \
|
||||||
|
\
|
||||||
|
while(TokenIndex``STAGE > MarkerIndex``STAGE) begin \
|
||||||
|
// parse the GPR \
|
||||||
|
if (ExpectedTokens``STAGE[MarkerIndex``STAGE] == "GPR") begin \
|
||||||
|
RegWrite``STAGE = ExpectedTokens``STAGE[MarkerIndex``STAGE]; \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+1], "%d", ExpectedRegAdr``STAGE); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+2], "%x", ExpectedRegValue``STAGE); \
|
||||||
|
MarkerIndex``STAGE += 3; \
|
||||||
|
// parse memory address, read data, and/or write data \
|
||||||
|
end else if(ExpectedTokens``STAGE[MarkerIndex``STAGE].substr(0, 2) == "Mem") begin \
|
||||||
|
MemOp``STAGE = ExpectedTokens``STAGE[MarkerIndex``STAGE]; \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+1], "%x", ExpectedMemAdr``STAGE); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+2], "%x", ExpectedMemWriteData``STAGE); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+3], "%x", ExpectedMemReadData``STAGE); \
|
||||||
|
MarkerIndex``STAGE += 4; \
|
||||||
|
// parse CSRs, because there are 1 or more CSRs after the CSR token \
|
||||||
|
// we check if the CSR token or the number of CSRs is greater than 0. \
|
||||||
|
// if so then we want to parse for a CSR. \
|
||||||
|
end else if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR" || NumCSR``STAGE > 0) begin \
|
||||||
|
if(ExpectedTokens``STAGE[MarkerIndex``STAGE] == "CSR") begin \
|
||||||
|
// all additional CSR's won't have this token. \
|
||||||
|
MarkerIndex``STAGE++; \
|
||||||
|
end \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE], "%s", ExpectedCSRArray``STAGE[NumCSR``STAGE]); \
|
||||||
|
matchCount``STAGE = $sscanf(ExpectedTokens``STAGE[MarkerIndex``STAGE+1], "%x", ExpectedCSRArrayValue``STAGE[NumCSR``STAGE]); \
|
||||||
|
MarkerIndex``STAGE += 2; \
|
||||||
|
if(`"STAGE`"=="E") begin \
|
||||||
|
// match MIP to QEMU's because interrupts are imprecise \
|
||||||
|
if(ExpectedCSRArrayE[NumCSRE].substr(0, 2) == "mip") begin \
|
||||||
|
CheckMIPFutureE = 1; \
|
||||||
|
NextMIPexpected = ExpectedCSRArrayValueE[NumCSRE]; \
|
||||||
|
end \
|
||||||
|
// $display("%tn: ExpectedCSRArrayM[7] (MEPC) = %x",$time,ExpectedCSRArrayM[7]); \
|
||||||
|
// $display("%tn: ExpectedPCM = %x",$time,ExpectedPCM); \
|
||||||
|
// // if PC does not equal MEPC, request delayed MIP is True \
|
||||||
|
// if(ExpectedPCM != ExpectedCSRArrayM[7]) begin \
|
||||||
|
// RequestDelayedMIP = 1; \
|
||||||
|
// end else begin \
|
||||||
|
// $display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueM[NumCSRM]); \
|
||||||
|
// MIPexpected = ExpectedCSRArrayValueM[NumCSRM]; \
|
||||||
|
// force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected; \
|
||||||
|
// end \
|
||||||
|
// end \
|
||||||
|
// $display("%tns: ExpectedCSRArrayM::: %p",$time,ExpectedCSRArrayM); \
|
||||||
|
if(ExpectedCSRArrayE[NumCSRE].substr(0,3) == "mepc") begin \
|
||||||
|
$display("hello! we are here."); \
|
||||||
|
MepcExpected = ExpectedCSRArrayValueE[NumCSRE]; \
|
||||||
|
$display("%tns: MepcExpected: %x",$time,MepcExpected); \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
\
|
||||||
|
NumCSR``STAGE++; \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
if(`"STAGE`"=="M") begin \
|
||||||
|
// override on special conditions \
|
||||||
|
if (ExpectedMemAdrM == 'h10000005) begin \
|
||||||
|
//$display("%tns, %d instrs: Overwriting read data from CLINT.", $time, InstrCountW); \
|
||||||
|
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM; \
|
||||||
|
end \
|
||||||
|
if(textM.substr(0,5) == "rdtime") begin \
|
||||||
|
//$display("%tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage.", $time, InstrCountW); \
|
||||||
|
force dut.uncore.clint.clint.MTIME = ExpectedRegValueM; \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
end \
|
||||||
|
|
||||||
always @(negedge clk) begin
|
always @(negedge clk) begin
|
||||||
// always check PC, instruction bits
|
`SCAN_NEW_INSTR_FROM_TRACE(E)
|
||||||
if (checkInstrM) begin
|
end
|
||||||
// read 1 line of the trace file
|
|
||||||
matchCount = $fgets(line, data_file_all);
|
|
||||||
if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line);
|
|
||||||
// extract PC, Instr
|
|
||||||
matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM);
|
|
||||||
//$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM);
|
|
||||||
|
|
||||||
// for the life of me I cannot get any build in C or C++ string parsing functions/methods to work.
|
always @(negedge clk) begin
|
||||||
// strtok was the best idea but it cannot be used correctly as system verilog does not have null
|
`SCAN_NEW_INSTR_FROM_TRACE(M)
|
||||||
// terminated strings.
|
end
|
||||||
|
|
||||||
// Just going to do this char by char.
|
// MIP spoofing
|
||||||
StartIndex = 0;
|
always @(posedge clk) begin
|
||||||
TokenIndex = 0;
|
#1;
|
||||||
//$display("len = %d", line.len());
|
if(CheckMIPFutureE) CheckMIPFutureE <= 0;
|
||||||
for(index = 0; index < line.len(); index++) begin
|
CheckMIPFutureM <= CheckMIPFutureE;
|
||||||
//$display("char = %s", line[index]);
|
if(CheckMIPFutureM) begin
|
||||||
if (line[index] == " " || line[index] == "\n") begin
|
if((ExpectedPCM != MepcExpected) & ((MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM) <= 16)) begin
|
||||||
EndIndex = index;
|
RequestDelayedMIP = 1;
|
||||||
ExpectedTokens[TokenIndex] = line.substr(StartIndex, EndIndex-1);
|
$display("%tns: Requesting Delayed MIP. Current MEPC value is %x",$time,MepcExpected);
|
||||||
//$display("In Tokenizer %s", line.substr(StartIndex, EndIndex-1));
|
end else begin // update MIP immediately
|
||||||
StartIndex = EndIndex + 1;
|
$display("%tns: Updating MIP to %x",$time,NextMIPexpected);
|
||||||
TokenIndex++;
|
MIPexpected = NextMIPexpected;
|
||||||
end
|
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||||
end
|
end
|
||||||
|
$display("%tn: ExpectedCSRArrayM = %p",$time,ExpectedCSRArrayM);
|
||||||
MarkerIndex = 3;
|
$display("%tn: ExpectedCSRArrayValueM = %p",$time,ExpectedCSRArrayValueM);
|
||||||
NumCSRM = 0;
|
$display("%tn: ExpectedTokens = %p",$time,ExpectedTokensM);
|
||||||
MemOpM = "";
|
$display("%tn: MepcExpected = %x",$time,MepcExpected);
|
||||||
RegWriteM = "";
|
$display("%tn: ExpectedPCM = %x",$time,ExpectedPCM);
|
||||||
|
// if PC does not equal MEPC, request delayed MIP is True
|
||||||
#2;
|
$display("%tns: Difference/multiplication thing: %x",$time,(MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM));
|
||||||
|
$display("%tn: ExpectedCSRArrayM[NumCSRM] %x",$time,ExpectedCSRArrayM[NumCSRM]);
|
||||||
while(TokenIndex > MarkerIndex) begin
|
$display("%tn: ExpectedCSRArrayValueM[NumCSRM] %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
|
||||||
// parse the GPR
|
|
||||||
if (ExpectedTokens[MarkerIndex] == "GPR") begin
|
if((ExpectedPCM != MepcExpected) & ((MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM) <= 16)) begin
|
||||||
RegWriteM = ExpectedTokens[MarkerIndex];
|
RequestDelayedMIP = 1;
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%d", ExpectedRegAdrM);
|
$display("%tns: Requesting Delayed MIP. Current MEPC value is %x",$time,MepcExpected);
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedRegValueM);
|
end else begin
|
||||||
MarkerIndex += 3;
|
$display("%tns: Updating MIP to %x",$time,NextMIPexpected);
|
||||||
// parse memory address, read data, and/or write data
|
MIPexpected = NextMIPexpected;
|
||||||
end else if(ExpectedTokens[MarkerIndex].substr(0, 2) == "Mem") begin
|
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||||
MemOpM = ExpectedTokens[MarkerIndex];
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedMemAdrM);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedMemWriteDataM);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+3], "%x", ExpectedMemReadDataM);
|
|
||||||
MarkerIndex += 4;
|
|
||||||
// parse CSRs, because there are 1 or more CSRs after the CSR token
|
|
||||||
// we check if the CSR token or the number of CSRs is greater than 0.
|
|
||||||
// if so then we want to parse for a CSR.
|
|
||||||
end else if(ExpectedTokens[MarkerIndex] == "CSR" || NumCSRM > 0) begin
|
|
||||||
if(ExpectedTokens[MarkerIndex] == "CSR") begin
|
|
||||||
// all additional CSR's won't have this token.
|
|
||||||
MarkerIndex++;
|
|
||||||
end
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex], "%s", ExpectedCSRArrayM[NumCSRM]);
|
|
||||||
matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%x", ExpectedCSRArrayValueM[NumCSRM]);
|
|
||||||
MarkerIndex += 2;
|
|
||||||
// match MIP to QEMU's because interrupts are imprecise
|
|
||||||
if(ExpectedCSRArrayM[NumCSRM].substr(0, 2) == "mip") begin
|
|
||||||
$display("%tn: ExpectedCSRArrayM[7] (MEPC) = %x",$time,ExpectedCSRArrayM[7]);
|
|
||||||
$display("%tn: ExpectedPCM = %x",$time,ExpectedPCM);
|
|
||||||
// if PC does not equal MEPC, request delayed MIP is True
|
|
||||||
if(ExpectedPCM != ExpectedCSRArrayM[7]) begin
|
|
||||||
RequestDelayedMIP = 1;
|
|
||||||
end else begin
|
|
||||||
$display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
|
|
||||||
MIPexpected = ExpectedCSRArrayValueM[NumCSRM];
|
|
||||||
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
NumCSRM++;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
// override on special conditions
|
|
||||||
if (ExpectedMemAdrM == 'h10000005) begin
|
|
||||||
//$display("%tns, %d instrs: Overwriting read data from CLINT.", $time, InstrCountW);
|
|
||||||
force dut.hart.ieu.dp.ReadDataM = ExpectedMemReadDataM;
|
|
||||||
end
|
|
||||||
if(textM.substr(0,5) == "rdtime") begin
|
|
||||||
//$display("%tns, %d instrs: Overwrite MTIME_CLINT on read of MTIME in memory stage.", $time, InstrCountW);
|
|
||||||
force dut.uncore.clint.clint.MTIME = ExpectedRegValueM;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if(RequestDelayedMIP) begin
|
||||||
|
$display("%tns: Executing Delayed MIP. Current MEPC value is %x",$time,dut.hart.priv.csr.genblk1.csrm.MEPC_REGW);
|
||||||
|
$display("%tns: Updating MIP to %x",$time,NextMIPexpected);
|
||||||
|
$display("%tns: MepcExpected %x",$time,MepcExpected);
|
||||||
|
MIPexpected = NextMIPexpected;
|
||||||
|
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
||||||
|
$display("%tns: Finished Executing Delayed MIP. Current MEPC value is %x",$time,dut.hart.priv.csr.genblk1.csrm.MEPC_REGW);
|
||||||
|
RequestDelayedMIP = 0;
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
// step 1: register expected state into the write back stage.
|
// step 1: register expected state into the write back stage.
|
||||||
@ -449,7 +529,7 @@ module testbench();
|
|||||||
ExpectedMemWriteDataW <= '0;
|
ExpectedMemWriteDataW <= '0;
|
||||||
ExpectedMemReadDataW <= '0;
|
ExpectedMemReadDataW <= '0;
|
||||||
NumCSRW <= '0;
|
NumCSRW <= '0;
|
||||||
end else begin
|
end else if (dut.hart.ieu.c.InstrValidM) begin
|
||||||
ExpectedPCW <= ExpectedPCM;
|
ExpectedPCW <= ExpectedPCM;
|
||||||
ExpectedInstrW <= ExpectedInstrM;
|
ExpectedInstrW <= ExpectedInstrM;
|
||||||
textW <= textM;
|
textW <= textM;
|
||||||
@ -484,12 +564,6 @@ module testbench();
|
|||||||
// step2: make all checks in the write back stage.
|
// step2: make all checks in the write back stage.
|
||||||
assign checkInstrW = InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
|
assign checkInstrW = InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
|
||||||
always @(negedge clk) begin
|
always @(negedge clk) begin
|
||||||
if(RequestDelayedMIP) begin
|
|
||||||
$display("%tns: Updating MIP to %x",$time,ExpectedCSRArrayValueW[NumCSRM]);
|
|
||||||
MIPexpected = ExpectedCSRArrayValueW[NumCSRM];
|
|
||||||
force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
|
|
||||||
RequestDelayedMIP = 0;
|
|
||||||
end
|
|
||||||
// always check PC, instruction bits
|
// always check PC, instruction bits
|
||||||
if (checkInstrW) begin
|
if (checkInstrW) begin
|
||||||
InstrCountW += 1;
|
InstrCountW += 1;
|
||||||
@ -521,7 +595,7 @@ module testbench();
|
|||||||
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
||||||
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||||
`checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
`checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
||||||
end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
|
end else if(MemOpW == "MemW" || MemOpW == "MemRW") begin
|
||||||
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||||
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user