condense testbench code; debug_level of 0 means don't check at all

This commit is contained in:
bbracker 2021-09-27 03:03:11 -04:00
parent 077f125c13
commit 2ffdbdf6d2

View File

@ -21,12 +21,20 @@
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
// OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// When letting Wally go for it, let wally generate own interrupts
/////////////////////////////////////////// ///////////////////////////////////////////
`include "wally-config.vh" `include "wally-config.vh"
`define DEBUG_TRACE 0 `define DEBUG_TRACE 0
`define DontHaltOnCSRMisMatch 1 // Debug Levels
// 0: don't check against QEMU
// 1: print disagreements with QEMU, but only halt on PCW disagreements
// 2: halt on any disagreement with QEMU except CSRs
// 3: halt on all disagreements with QEMU
// 4: print memory accesses whenever they happen
// 5: print everything
module testbench(); module testbench();
@ -74,6 +82,7 @@ module testbench();
// P, Instr Checking // P, Instr Checking
logic [`XLEN-1:0] PCW; logic [`XLEN-1:0] PCW;
integer data_file_all; integer data_file_all;
string name;
// Write Back stage signals needed for trace compare, but don't actually // Write Back stage signals needed for trace compare, but don't actually
// exist in CPU. // exist in CPU.
@ -129,25 +138,24 @@ module testbench();
integer NumCSRPostWIndex; integer NumCSRPostWIndex;
logic [`XLEN-1:0] InstrCountW; logic [`XLEN-1:0] InstrCountW;
// ------------ // ------
// Error Macros // Macros
// ------------ // ------
`define ERROR \
errorCount +=1; \
$display("processed %0d instructions with %0d warnings", InstrCountW, warningCount); \
$stop;
`define CSRwarn(CSR) \ `define CSRwarn(CSR) \
begin \ begin \
if(`DEBUG_TRACE > 0) begin \
$display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \ $display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \
end \
if (CSR != ExpectedCSRArrayValueW[NumCSRPostWIndex]) 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, InstrCountW, ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \
if(!`DontHaltOnCSRMisMatch) fault = 1; \ if(`DEBUG_TRACE >= 3) fault = 1; \
end \ end \
end end
`define checkEQ(NAME, VAL, EXPECTED) \
if(VAL != EXPECTED) begin \
$display("%tns, %d instrs: %s %x differs from expected %x", $time, InstrCountW, NAME, VAL, EXPECTED); \
if ((NAME == "PCW") || (`DEBUG_TRACE >= 2)) fault = 1; \
end
initial begin initial begin
data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r"); data_file_all = $fopen({`LINUX_TEST_VECTORS,"all.txt"}, "r");
@ -159,8 +167,7 @@ module testbench();
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;
// trapW will already be invalid in there was an InstrPageFault in the previous instruction. assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction.
assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW;
// Additonal W stage registers // Additonal W stage registers
flopenrc #(`XLEN) MemAdrWReg(clk, reset, dut.hart.FlushW, ~dut.hart.StallW, dut.hart.ieu.dp.MemAdrM, MemAdrW); flopenrc #(`XLEN) MemAdrWReg(clk, reset, dut.hart.FlushW, ~dut.hart.StallW, dut.hart.ieu.dp.MemAdrM, MemAdrW);
@ -181,7 +188,7 @@ module testbench();
if (checkInstrM) begin if (checkInstrM) begin
// read 1 line of the trace file // read 1 line of the trace file
matchCount = $fgets(line, data_file_all); matchCount = $fgets(line, data_file_all);
if(`DEBUG_TRACE > 1) $display("Time %t, line %x", $time, line); if(`DEBUG_TRACE >= 5) $display("Time %t, line %x", $time, line);
// extract PC, Instr // extract PC, Instr
matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM); matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM);
//$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM); //$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM);
@ -326,62 +333,32 @@ module testbench();
if (InstrCountW == waveOnICount) $stop; if (InstrCountW == waveOnICount) $stop;
// print progress message // print progress message
if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW); if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW);
// check PCW
fault = 0; fault = 0;
if(PCW != ExpectedPCW) begin if (`DEBUG_TRACE >= 1) begin
$display("%tns, %d instrs: PCW %016x does not equal ExpectedPCW: %016x", $time, InstrCountW, PCW, ExpectedPCW); `checkEQ("PCW",PCW,ExpectedPCW)
fault = 1; `checkEQ("InstrW",dut.hart.ifu.InstrW,ExpectedInstrW)
end `checkEQ("Instr Count",dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW,InstrCountW)
// check instruction value
if(dut.hart.ifu.InstrW != ExpectedInstrW) begin
$display("%tns, %d instrs: InstrW %x does not equal ExpectedInstrW: %x", $time, InstrCountW, dut.hart.ifu.InstrW, ExpectedInstrW);
fault = 1;
end
// check the number of instructions
if(dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW != InstrCountW) begin
$display("%t, Number of instruction Retired = %d does not equal number of instructions in trace = %d", $time, dut.hart.priv.csr.genblk1.counters.genblk1.INSTRET_REGW, InstrCountW);
if(!`DontHaltOnCSRMisMatch) fault = 1;
end
#2; // delay 2 ns. #2; // delay 2 ns.
if(`DEBUG_TRACE > 2) begin if(`DEBUG_TRACE >= 5) begin
$display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, InstrCountW, dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW); $display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, InstrCountW, dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW);
$display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW); $display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
end end
if (RegWriteW == "GPR") begin if (RegWriteW == "GPR") begin
if (dut.hart.ieu.dp.regf.a3 != ExpectedRegAdrW) begin `checkEQ("Reg Write Address",dut.hart.ieu.dp.regf.a3,ExpectedRegAdrW)
$display("%tns, %d instrs: Reg Write Address %02d does not equal expected value: %02d", $time, InstrCountW, dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW); $sprintf(name,"RF[%02d]",ExpectedRegAdrW);
fault = 1; `checkEQ(name, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW)
end end
if (dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW] != ExpectedRegValueW) begin
$display("%tns, %d instrs: RF[%02d] %016x does not equal expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
fault = 1;
end
end
if (MemOpW.substr(0,2) == "Mem") begin if (MemOpW.substr(0,2) == "Mem") begin
if(`DEBUG_TRACE > 3) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW); if(`DEBUG_TRACE >= 4) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW);
// always check address `checkEQ("MemAdrW",MemAdrW,ExpectedMemAdrW)
if (MemAdrW != ExpectedMemAdrW) begin
$display("%tns, %d instrs: MemAdrW %016x does not equal expected value: %016x", $time, InstrCountW, MemAdrW, ExpectedMemAdrW);
fault = 1;
end
// check read data
if(MemOpW == "MemR" || MemOpW == "MemRW") begin if(MemOpW == "MemR" || MemOpW == "MemRW") begin
if(`DEBUG_TRACE > 3) $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);
if (dut.hart.ieu.dp.ReadDataW != ExpectedMemReadDataW) begin `checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
$display("%tns, %d instrs: ReadDataW %016x does not equal expected value: %016x", $time, InstrCountW, dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
fault = 1;
end
// check write data
end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
if(`DEBUG_TRACE > 3) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW); if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
if (WriteDataW != ExpectedMemWriteDataW) begin `checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
$display("%tns, %d instrs: WriteDataW %016x does not equal expected value: %016x", $time, InstrCountW, WriteDataW, ExpectedMemWriteDataW);
fault = 1;
end end
end end
end
// check csr // check csr
for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin
case(ExpectedCSRArrayW[NumCSRPostWIndex]) case(ExpectedCSRArrayW[NumCSRPostWIndex])
@ -398,9 +375,14 @@ module testbench();
"scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW) "scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW)
"stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW) "stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW)
"stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW) "stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW)
endcase // case (ExpectedCSRArrayW[NumCSRPostWIndex]) endcase
end // for (NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) end
if (fault == 1) begin `ERROR end if (fault == 1) begin
errorCount +=1;
$display("processed %0d instructions with %0d warnings", InstrCountW, warningCount);
$stop;
end
end // if (`DEBUG_TRACE >= 1)
end // if (checkInstrW) end // if (checkInstrW)
end // always @ (negedge clk) end // always @ (negedge clk)