mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
condense testbench code; debug_level of 0 means don't check at all
This commit is contained in:
parent
077f125c13
commit
2ffdbdf6d2
@ -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,90 +333,65 @@ 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
|
#2; // delay 2 ns.
|
||||||
if(dut.hart.ifu.InstrW != ExpectedInstrW) begin
|
if(`DEBUG_TRACE >= 5) begin
|
||||||
$display("%tns, %d instrs: InstrW %x does not equal ExpectedInstrW: %x", $time, InstrCountW, dut.hart.ifu.InstrW, ExpectedInstrW);
|
$display("%tns, %d instrs: Reg Write Address %02d ? expected value: %02d", $time, InstrCountW, dut.hart.ieu.dp.regf.a3, ExpectedRegAdrW);
|
||||||
fault = 1;
|
$display("%tns, %d instrs: RF[%02d] %016x ? expected value: %016x", $time, InstrCountW, ExpectedRegAdrW, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW);
|
||||||
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;
|
|
||||||
end
|
end
|
||||||
if (dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW] != ExpectedRegValueW) begin
|
if (RegWriteW == "GPR") 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);
|
`checkEQ("Reg Write Address",dut.hart.ieu.dp.regf.a3,ExpectedRegAdrW)
|
||||||
fault = 1;
|
$sprintf(name,"RF[%02d]",ExpectedRegAdrW);
|
||||||
|
`checkEQ(name, dut.hart.ieu.dp.regf.rf[ExpectedRegAdrW], ExpectedRegValueW)
|
||||||
end
|
end
|
||||||
end
|
if (MemOpW.substr(0,2) == "Mem") begin
|
||||||
|
if(`DEBUG_TRACE >= 4) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW);
|
||||||
if (MemOpW.substr(0,2) == "Mem") begin
|
`checkEQ("MemAdrW",MemAdrW,ExpectedMemAdrW)
|
||||||
if(`DEBUG_TRACE > 3) $display("\tMemAdrW: %016x ? expected: %016x", MemAdrW, ExpectedMemAdrW);
|
if(MemOpW == "MemR" || MemOpW == "MemRW") begin
|
||||||
// always check address
|
if(`DEBUG_TRACE >= 4) $display("\tReadDataW: %016x ? expected: %016x", dut.hart.ieu.dp.ReadDataW, ExpectedMemReadDataW);
|
||||||
if (MemAdrW != ExpectedMemAdrW) begin
|
`checkEQ("ReadDataW",dut.hart.ieu.dp.ReadDataW,ExpectedMemReadDataW)
|
||||||
$display("%tns, %d instrs: MemAdrW %016x does not equal expected value: %016x", $time, InstrCountW, MemAdrW, ExpectedMemAdrW);
|
end else if(ExpectedTokens[MarkerIndex] == "MemW" || ExpectedTokens[MarkerIndex] == "MemRW") begin
|
||||||
fault = 1;
|
if(`DEBUG_TRACE >= 4) $display("\tWriteDataW: %016x ? expected: %016x", WriteDataW, ExpectedMemWriteDataW);
|
||||||
end
|
`checkEQ("WriteDataW",ExpectedMemWriteDataW,ExpectedMemWriteDataW)
|
||||||
// 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;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
// check csr
|
||||||
|
for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin
|
||||||
// check csr
|
case(ExpectedCSRArrayW[NumCSRPostWIndex])
|
||||||
for(NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++) begin
|
"mhartid": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW)
|
||||||
case(ExpectedCSRArrayW[NumCSRPostWIndex])
|
"mstatus": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW)
|
||||||
"mhartid": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MHARTID_REGW)
|
"mtvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW)
|
||||||
"mstatus": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MSTATUS_REGW)
|
"mip": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIP_REGW)
|
||||||
"mtvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVEC_REGW)
|
"mie": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIE_REGW)
|
||||||
"mip": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIP_REGW)
|
"mideleg":`CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW)
|
||||||
"mie": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIE_REGW)
|
"medeleg": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW)
|
||||||
"mideleg":`CSRwarn(dut.hart.priv.csr.genblk1.csrm.MIDELEG_REGW)
|
"mepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEPC_REGW)
|
||||||
"medeleg": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEDELEG_REGW)
|
"mtval": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW)
|
||||||
"mepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MEPC_REGW)
|
"sepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.SEPC_REGW)
|
||||||
"mtval": `CSRwarn(dut.hart.priv.csr.genblk1.csrm.MTVAL_REGW)
|
"scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW)
|
||||||
"sepc": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.SEPC_REGW)
|
"stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW)
|
||||||
"scause": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.SCAUSE_REGW)
|
"stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW)
|
||||||
"stvec": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.STVEC_REGW)
|
endcase
|
||||||
"stval": `CSRwarn(dut.hart.priv.csr.genblk1.csrs.genblk1.STVAL_REGW)
|
end
|
||||||
endcase // case (ExpectedCSRArrayW[NumCSRPostWIndex])
|
if (fault == 1) begin
|
||||||
end // for (NumCSRPostWIndex = 0; NumCSRPostWIndex < NumCSRW; NumCSRPostWIndex++)
|
errorCount +=1;
|
||||||
if (fault == 1) begin `ERROR end
|
$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)
|
||||||
|
|
||||||
|
|
||||||
// track the current function
|
// track the current function
|
||||||
FunctionName FunctionName(.reset(reset),
|
FunctionName FunctionName(.reset(reset),
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.ProgramAddrMapFile(ProgramAddrMapFile),
|
.ProgramAddrMapFile(ProgramAddrMapFile),
|
||||||
.ProgramLabelMapFile(ProgramLabelMapFile));
|
.ProgramLabelMapFile(ProgramLabelMapFile));
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
Loading…
Reference in New Issue
Block a user