diff --git a/wally-pipelined/testbench/testbench-linux.sv b/wally-pipelined/testbench/testbench-linux.sv index a09c0838f..76a1841b8 100644 --- a/wally-pipelined/testbench/testbench-linux.sv +++ b/wally-pipelined/testbench/testbench-linux.sv @@ -21,12 +21,20 @@ // 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 // 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" `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(); @@ -74,6 +82,7 @@ module testbench(); // P, Instr Checking logic [`XLEN-1:0] PCW; integer data_file_all; + string name; // Write Back stage signals needed for trace compare, but don't actually // exist in CPU. @@ -129,25 +138,24 @@ module testbench(); integer NumCSRPostWIndex; logic [`XLEN-1:0] InstrCountW; - // ------------ - // Error Macros - // ------------ - `define ERROR \ - errorCount +=1; \ - $display("processed %0d instructions with %0d warnings", InstrCountW, warningCount); \ - $stop; + // ------ + // Macros + // ------ `define CSRwarn(CSR) \ begin \ - if(`DEBUG_TRACE > 0) begin \ - $display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \ - end \ + $display("CSR: %s = %016x, expected = %016x", ExpectedCSRArrayW[NumCSRPostWIndex], CSR, ExpectedCSRArrayValueW[NumCSRPostWIndex]); \ 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]); \ - if(!`DontHaltOnCSRMisMatch) fault = 1; \ + if(`DEBUG_TRACE >= 3) fault = 1; \ 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 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; - // trapW will already be invalid in there was an InstrPageFault in the previous instruction. - assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW; + assign checkInstrW = dut.hart.ieu.InstrValidW & ~dut.hart.StallW; // trapW will already be invalid in there was an InstrPageFault in the previous instruction. // Additonal W stage registers 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 // read 1 line of the trace file 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 matchCount = $sscanf(line, "%x %x %s", ExpectedPCM, ExpectedInstrM, textM); //$display("matchCount %d, PCM %x ExpectedInstrM %x textM %x", matchCount, ExpectedPCM, ExpectedInstrM, textM); @@ -326,90 +333,65 @@ module testbench(); if (InstrCountW == waveOnICount) $stop; // print progress message if (InstrCountW % 'd100000 == 0) $display("Reached %d instructions", InstrCountW); - // check PCW fault = 0; - if(PCW != ExpectedPCW) begin - $display("%tns, %d instrs: PCW %016x does not equal ExpectedPCW: %016x", $time, InstrCountW, PCW, ExpectedPCW); - fault = 1; - end - // 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. - if(`DEBUG_TRACE > 2) 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: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW); - end - if (RegWriteW == "GPR") begin - if (dut.hart.ieu.dp.regf.a3 != ExpectedRegAdrW) begin - $display("%tns, %d instrs: Reg Write Address %02d does not equal expected value: %02d", $time, InstrCountW, dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW); - fault = 1; + if (`DEBUG_TRACE >= 1) begin + `checkEQ("PCW",PCW,ExpectedPCW) + `checkEQ("InstrW",dut.hart.ifu.InstrW,ExpectedInstrW) + `checkEQ("Instr Count",dut.hart.priv.csr.genblk1.counters.genblk1.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.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); 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; + if (RegWriteW == "GPR") begin + `checkEQ("Reg Write Address",dut.hart.ieu.dp.regf.a3,ExpectedRegAdrW) + $sprintf(name,"RF[%02d]",ExpectedRegAdrW); + `checkEQ(name, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW) end - end - - if (MemOpW.substr(0,2) == "Mem") begin - if(`DEBUG_TRACE > 3) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW); - // always check address - 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(`DEBUG_TRACE > 3) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW); - if (dut.hart.ieu.dp.ReadDataW != ExpectedMemReadDataW) begin - $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 - if(`DEBUG_TRACE > 3) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW); - if (WriteDataW != ExpectedMemWriteDataW) begin - $display("%tns, %d instrs: WriteDataW %016x does not equal expected value: %016x", $time, InstrCountW, WriteDataW, ExpectedMemWriteDataW); - fault = 1; + if (MemOpW.substr(0,2) == "Mem") begin + if(`DEBUG_TRACE >= 4) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW); + `checkEQ("MemAdrW",MemAdrW,ExpectedMemAdrW) + if(MemOpW == "MemR" || MemOpW == "MemRW") begin + if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW); + `checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW) + end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin + if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW); + `checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW) end end - end - - // check csr - for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin - case(ExpectedCSRArrayW[NumCSRPostWIndex]) - "mhartid": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW) - "mstatus": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW) - "mtvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW) - "mip": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIP_REGW) - "mie": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIE_REGW) - "mideleg":`CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW) - "medeleg": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW) - "mepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEPC_REGW) - "mtval": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW) - "sepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.SEPC_REGW) - "scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW) - "stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW) - "stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW) - endcase // case (ExpectedCSRArrayW[NumCSRPostWIndex]) - end // for (NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) - if (fault == 1) begin `ERROR end + // check csr + for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin + case(ExpectedCSRArrayW[NumCSRPostWIndex]) + "mhartid": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW) + "mstatus": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW) + "mtvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW) + "mip": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIP_REGW) + "mie": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIE_REGW) + "mideleg":`CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW) + "medeleg": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW) + "mepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEPC_REGW) + "mtval": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW) + "sepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.SEPC_REGW) + "scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW) + "stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW) + "stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW) + endcase + 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 // always @ (negedge clk) // track the current function FunctionName FunctionName(.reset(reset), - .clk(clk), - .ProgramAddrMapFile(ProgramAddrMapFile), - .ProgramLabelMapFile(ProgramLabelMapFile)); + .clk(clk), + .ProgramAddrMapFile(ProgramAddrMapFile), + .ProgramLabelMapFile(ProgramLabelMapFile)); ///////////////////////////////////////////////////////////////////////////////