Major cleanup of testbench.

This commit is contained in:
Ross Thompson 2023-06-15 14:57:05 -05:00
parent 87fb9a3e16
commit af046d4772

View File

@ -87,8 +87,6 @@ module testbench;
logic Validate; logic Validate;
logic SelectTest; logic SelectTest;
// check assertions for a legal configuration
riscvassertions #(P) riscvassertions();
// pick tests based on modes supported // pick tests based on modes supported
initial begin initial begin
@ -204,89 +202,52 @@ module testbench;
if (TestBenchReset) CurrState <= #1 STATE_TESTBENCH_RESET; if (TestBenchReset) CurrState <= #1 STATE_TESTBENCH_RESET;
else CurrState <= #1 NextState; else CurrState <= #1 NextState;
// fsm next state logic
always_comb begin always_comb begin
reset_ext = 0;
ResetMem = 0;
LoadMem = 0;
ResetCntEn = 0;
ResetCntRst = 0;
Validate = 0;
SelectTest = 0;
// riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests // riscof tests have a different signature, tests[0] == "1" refers to RiscvArchTests
// and tests[0] == "2" refers to WallyRiscvArchTests // and tests[0] == "2" refers to WallyRiscvArchTests
riscofTest = tests[0] == "1" | tests[0] == "2"; riscofTest = tests[0] == "1" | tests[0] == "2";
pathname = tvpaths[tests[0].atoi()]; pathname = tvpaths[tests[0].atoi()];
case(CurrState) case(CurrState)
STATE_TESTBENCH_RESET: begin STATE_TESTBENCH_RESET: NextState = STATE_INIT_TEST;
NextState = STATE_INIT_TEST; STATE_INIT_TEST: NextState = STATE_RESET_MEMORIES;
reset_ext = 1; STATE_RESET_MEMORIES: NextState = STATE_RESET_MEMORIES2;
end STATE_RESET_MEMORIES2: NextState = STATE_LOAD_MEMORIES; // Give the reset enough time to ensure the bus is reset before loading the memories.
STATE_INIT_TEST: begin STATE_LOAD_MEMORIES: NextState = STATE_RESET_TEST;
NextState = STATE_RESET_MEMORIES; STATE_RESET_TEST: if(ResetCount < ResetThreshold) NextState = STATE_RESET_TEST;
ResetCntRst = 1; else NextState = STATE_RUN_TEST;
SelectTest = 1; STATE_RUN_TEST: if(DCacheFlushStart) NextState = STATE_CHECK_TEST;
reset_ext = 1; else NextState = STATE_RUN_TEST;
end STATE_CHECK_TEST: if (DCacheFlushDone) NextState = STATE_VALIDATE;
STATE_RESET_MEMORIES: begin else NextState = STATE_CHECK_TEST_WAIT;
NextState = STATE_RESET_MEMORIES2; STATE_CHECK_TEST_WAIT: if(DCacheFlushDone) NextState = STATE_VALIDATE;
reset_ext = 1; else NextState = STATE_CHECK_TEST_WAIT;
if (TEST == "coremark") ResetMem = 1; // this initialization is very expensive, only do it for coremark. STATE_VALIDATE: NextState = STATE_INIT_TEST;
end STATE_INCR_TEST: NextState = STATE_INIT_TEST;
STATE_RESET_MEMORIES2: begin // Give the reset enough time to ensure the bus is reset before loading the memories.
NextState = STATE_LOAD_MEMORIES;
reset_ext = 1;
// this initialization is very expensive, only do it for coremark.
if (TEST == "coremark") ResetMem = 1;
end
STATE_LOAD_MEMORIES: begin
NextState = STATE_RESET_TEST;
reset_ext = 1;
LoadMem = 1;
end
STATE_RESET_TEST: begin
reset_ext = 1;
ResetCntEn = 1;
if(ResetCount < ResetThreshold) begin
NextState = STATE_RESET_TEST;
end else begin
NextState = STATE_RUN_TEST;
end
end
STATE_RUN_TEST:
if(DCacheFlushStart) begin
NextState = STATE_CHECK_TEST;
end else begin
NextState = STATE_RUN_TEST;
end
STATE_CHECK_TEST: begin
if (DCacheFlushDone) begin
NextState = STATE_VALIDATE;
end else begin
NextState = STATE_CHECK_TEST_WAIT;
end
end
STATE_CHECK_TEST_WAIT: begin
if(DCacheFlushDone) begin
NextState = STATE_VALIDATE;
end else begin
NextState = STATE_CHECK_TEST_WAIT;
end
end
STATE_VALIDATE: begin
NextState = STATE_INIT_TEST;
Validate = '1;
end
STATE_INCR_TEST: begin
NextState = STATE_INIT_TEST;
end
default: NextState = STATE_TESTBENCH_RESET; default: NextState = STATE_TESTBENCH_RESET;
endcase endcase
end // always_comb end // always_comb
// fsm output control logic
assign reset_ext = CurrState == STATE_TESTBENCH_RESET | CurrState == STATE_INIT_TEST |
CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2 |
CurrState == STATE_LOAD_MEMORIES | CurrState ==STATE_RESET_TEST;
// this initialization is very expensive, only do it for coremark.
assign ResetMem = (CurrState == STATE_RESET_MEMORIES | CurrState == STATE_RESET_MEMORIES2) & TEST == "coremark";
assign LoadMem = CurrState == STATE_LOAD_MEMORIES;
assign ResetCntRst = CurrState == STATE_INIT_TEST;
assign ResetCntEn = CurrState == STATE_RESET_TEST;
assign Validate = CurrState == STATE_VALIDATE;
assign SelectTest = CurrState == STATE_INIT_TEST;
// fsm reset counter
counter #(3) RstCounter(clk, ResetCntRst, ResetCntEn, ResetCount);
////////////////////////////////////////////////////////////////////////////////
// Find the test vector files and populate the PC to function label converter
////////////////////////////////////////////////////////////////////////////////
assign begin_signature_addr = ProgramAddrLabelArray["begin_signature"];
always @(posedge clk) begin always @(posedge clk) begin
if(SelectTest) begin if(SelectTest) begin
if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"}; if (riscofTest) memfilename = {pathname, tests[test], "/ref/ref.elf.memfile"};
else memfilename = {pathname, tests[test], ".elf.memfile"}; else memfilename = {pathname, tests[test], ".elf.memfile"};
@ -305,14 +266,17 @@ module testbench;
end end
end end
////////////////////////////////////////////////////////////////////////////////
// Verify the test ran correctly by checking the memory against a known signature.
////////////////////////////////////////////////////////////////////////////////
if(TestBenchReset) test = 1; if(TestBenchReset) test = 1;
if(Validate) begin
if (TEST == "coremark") if (TEST == "coremark")
if (dut.core.EcallFaultM) begin if (dut.core.EcallFaultM) begin
$display("Benchmark: coremark is done."); $display("Benchmark: coremark is done.");
$stop; $stop;
end end
else if (TEST == "embench") begin if(Validate) begin
if (TEST == "embench") begin
// Writes contents of begin_signature to .sim.output file // Writes contents of begin_signature to .sim.output file
// this contains instret and cycles for start and end of test run, used by embench // this contains instret and cycles for start and end of test run, used by embench
// python speed script to calculate embench speed score. // python speed script to calculate embench speed score.
@ -347,13 +311,10 @@ module testbench;
end end
end end
counter #(3) RstCounter(clk, ResetCntRst, ResetCntEn, ResetCount);
assign begin_signature_addr = ProgramAddrLabelArray["begin_signature"];
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Some memories are not reset, but should be zeros or set to some initial value for simulation // Some memories are not reset, but should be zeros or set to some initial value for simulation
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
integer adrindex; integer adrindex;
always @(posedge clk) begin always @(posedge clk) begin
if (ResetMem) // program memory is sometimes reset if (ResetMem) // program memory is sometimes reset
@ -395,6 +356,9 @@ module testbench;
end end
end end
////////////////////////////////////////////////////////////////////////////////
// Actual hardware
////////////////////////////////////////////////////////////////////////////////
// instantiate device to be tested // instantiate device to be tested
assign GPIOIN = 0; assign GPIOIN = 0;
@ -403,12 +367,10 @@ module testbench;
if(P.EXT_MEM_SUPPORTED) begin if(P.EXT_MEM_SUPPORTED) begin
ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE)) ram_ahb #(.BASE(P.EXT_MEM_BASE), .RANGE(P.EXT_MEM_RANGE))
ram (.HCLK, .HRESETn, .HADDR, .HWRITE, .HTRANS, .HWDATA, .HSELRam(HSELEXT), ram (.HCLK, .HRESETn, .HADDR, .HWRITE, .HTRANS, .HWDATA, .HSELRam(HSELEXT),
.HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HREADRam(HRDATAEXT), .HREADYRam(HREADYEXT), .HRESPRam(HRESPEXT), .HREADY, .HWSTRB);
.HWSTRB);
end else begin end else begin
assign HREADYEXT = 1; assign HREADYEXT = 1;
assign HRESPEXT = 0; assign {HRESPEXT, HRDATAEXT} = '0;
assign HRDATAEXT = 0;
end end
if(P.FPGA) begin : sdcard if(P.FPGA) begin : sdcard
@ -430,6 +392,26 @@ module testbench;
.HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN, .HTRANS, .HMASTLOCK, .HREADY, .TIMECLK(1'b0), .GPIOIN, .GPIOOUT, .GPIOEN,
.UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK); .UARTSin, .UARTSout, .SDCCmdIn, .SDCCmdOut, .SDCCmdOE, .SDCDatIn, .SDCCLK);
// generate clock to sequence tests
always begin
clk = 1; # 5; clk = 0; # 5;
end
////////////////////////////////////////////////////////////////////////////////
// Support logic
////////////////////////////////////////////////////////////////////////////////
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck
riscvassertions #(P) riscvassertions(); // check assertions for a legal configuration
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
// track the current function or global label
if (DEBUG == 1 | (PrintHPMCounters & P.ZICOUNTERS_SUPPORTED)) begin : FunctionName
FunctionName #(P) FunctionName(.reset(reset_ext | TestBenchReset),
.clk(clk), .ProgramAddrMapFile(ProgramAddrMapFile), .ProgramLabelMapFile(ProgramLabelMapFile));
end
// Track names of instructions // Track names of instructions
string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName;
logic [31:0] InstrW; logic [31:0] InstrW;
@ -440,22 +422,6 @@ module testbench;
dut.core.ifu.InstrM, InstrW, dut.core.ifu.InstrM, InstrW,
InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); InstrFName, InstrDName, InstrEName, InstrMName, InstrWName);
// generate clock to sequence tests
always
begin
clk = 1; # 5; clk = 0; # 5;
// if ($time % 100000 == 0) $display("Time is %0t", $time);
end
// track the current function or global label
if (DEBUG == 1 | (PrintHPMCounters & P.ZICOUNTERS_SUPPORTED)) begin : FunctionName
FunctionName #(P) FunctionName(.reset(reset_ext | TestBenchReset),
.clk(clk),
.ProgramAddrMapFile(ProgramAddrMapFile),
.ProgramLabelMapFile(ProgramLabelMapFile));
end
// Termination condition // Termination condition
// terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed // terminate on a specific ECALL after li x3,1 for old Imperas tests, *** remove this when old imperas tests are removed
// or sw gp,-56(t0) for new Imperas tests // or sw gp,-56(t0) for new Imperas tests
@ -472,14 +438,7 @@ module testbench;
((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) |
((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" );
DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));
.reset(reset),
.start(DCacheFlushStart),
.done(DCacheFlushDone));
watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset);
loggers #(P, TEST, PrintHPMCounters, I_CACHE_ADDR_LOGGER, D_CACHE_ADDR_LOGGER, BPRED_LOGGER)
loggers (clk, reset, DCacheFlushStart, DCacheFlushDone, memfilename);
task automatic CheckSignature; task automatic CheckSignature;
// This task must be declared inside this module as it needs access to parameter P. There is // This task must be declared inside this module as it needs access to parameter P. There is