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
							
								
									db268471b6
								
							
						
					
					
						commit
						e4cf044932
					
				@ -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);
 | 
				
			||||||
 | 
					      $display("%tn: ExpectedCSRArrayValueM = %p",$time,ExpectedCSRArrayValueM);
 | 
				
			||||||
 | 
					      $display("%tn: ExpectedTokens = %p",$time,ExpectedTokensM);
 | 
				
			||||||
 | 
					      $display("%tn: MepcExpected = %x",$time,MepcExpected);
 | 
				
			||||||
 | 
					      $display("%tn: ExpectedPCM = %x",$time,ExpectedPCM);
 | 
				
			||||||
 | 
					      // if PC does not equal MEPC, request delayed MIP is True
 | 
				
			||||||
 | 
					      $display("%tns: Difference/multiplication thing: %x",$time,(MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM));
 | 
				
			||||||
 | 
					      $display("%tn: ExpectedCSRArrayM[NumCSRM] %x",$time,ExpectedCSRArrayM[NumCSRM]);
 | 
				
			||||||
 | 
					      $display("%tn: ExpectedCSRArrayValueM[NumCSRM] %x",$time,ExpectedCSRArrayValueM[NumCSRM]);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
      MarkerIndex = 3;
 | 
					      if((ExpectedPCM != MepcExpected) & ((MepcExpected - ExpectedPCM) * (MepcExpected - ExpectedPCM) <= 16)) begin
 | 
				
			||||||
      NumCSRM = 0;
 | 
					        RequestDelayedMIP = 1;
 | 
				
			||||||
      MemOpM = "";
 | 
					        $display("%tns: Requesting Delayed MIP. Current MEPC value is %x",$time,MepcExpected);
 | 
				
			||||||
      RegWriteM = "";
 | 
					      end else begin
 | 
				
			||||||
 | 
					        $display("%tns: Updating MIP to %x",$time,NextMIPexpected);
 | 
				
			||||||
      #2;
 | 
					        MIPexpected = NextMIPexpected;
 | 
				
			||||||
 | 
					        force dut.hart.priv.csr.genblk1.csri.MIP_REGW = MIPexpected;
 | 
				
			||||||
      while(TokenIndex > MarkerIndex) begin
 | 
					 | 
				
			||||||
        // parse the GPR
 | 
					 | 
				
			||||||
        if (ExpectedTokens[MarkerIndex] == "GPR") begin
 | 
					 | 
				
			||||||
          RegWriteM = ExpectedTokens[MarkerIndex];
 | 
					 | 
				
			||||||
          matchCount = $sscanf(ExpectedTokens[MarkerIndex+1], "%d", ExpectedRegAdrM);
 | 
					 | 
				
			||||||
          matchCount = $sscanf(ExpectedTokens[MarkerIndex+2], "%x", ExpectedRegValueM);
 | 
					 | 
				
			||||||
          MarkerIndex += 3;
 | 
					 | 
				
			||||||
        // parse memory address, read data, and/or write data
 | 
					 | 
				
			||||||
        end else if(ExpectedTokens[MarkerIndex].substr(0, 2) == "Mem") begin
 | 
					 | 
				
			||||||
          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