From 0b35c2ea56c72eb03c44b782a497c5c8b8e56629 Mon Sep 17 00:00:00 2001 From: David Harris Date: Fri, 3 Nov 2023 05:24:15 -0700 Subject: [PATCH] Updated testbenches to capture InstrM because it may be optimized out of IFU --- src/ifu/ifu.sv | 6 +++--- testbench/testbench-imperas.sv | 11 ++++++++--- testbench/testbench-linux-imperas.sv | 12 +++++++++--- testbench/testbench-linux.sv | 12 +++++++++--- testbench/testbench-xcelium.sv | 13 +++++++++---- testbench/testbench.sv | 13 +++++++++---- 6 files changed, 47 insertions(+), 20 deletions(-) diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index 4e51fed71..4fdef8c6a 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -388,14 +388,14 @@ module ifu import cvw::*; #(parameter cvw_t P) ( // Instruction and PC pipeline registers flush to NOP, not zero mux2 #(32) FlushInstrEMux(InstrD, nop, FlushE, NextInstrD); - mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE); flopenr #(32) InstrEReg(clk, reset, ~StallE, NextInstrD, InstrE); flopenr #(P.XLEN) PCEReg(clk, reset, ~StallE, PCD, PCE); // InstrM is only needed with CSRs or atomic operations - if (P.ZICSR_SUPPORTED | P.A_SUPPORTED | 1) + if (P.ZICSR_SUPPORTED | P.A_SUPPORTED) begin + mux2 #(32) FlushInstrMMux(InstrE, nop, FlushM, NextInstrE); flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM); - else assign InstrM = 0; + end else assign InstrM = 0; // PCM is only needed with CSRs or branch prediction if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED) flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); diff --git a/testbench/testbench-imperas.sv b/testbench/testbench-imperas.sv index ac7e49a48..4360d4422 100644 --- a/testbench/testbench-imperas.sv +++ b/testbench/testbench-imperas.sv @@ -214,7 +214,7 @@ module testbench; `endif flopenr #(P.XLEN) PCWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.PCM, PCW); - flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); + flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW); // check assertions for a legal configuration riscvassertions #(P) riscvassertions(); @@ -261,7 +261,7 @@ module testbench; instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrD, dut.core.ifu.InstrE, - dut.core.ifu.InstrM, InstrW, + InstrM, InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // initialize tests @@ -298,6 +298,11 @@ module testbench; .ProgramLabelMapFile(ProgramLabelMapFile)); end + // Duplicate copy of pipeline registers that are optimized out of some configurations + logic [31:0] NextInstrE, InstrM; + mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); + flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); + // Termination condition // 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 @@ -311,7 +316,7 @@ module testbench; (dut.core.ieu.dp.regf.we3 & dut.core.ieu.dp.regf.a3 == 3 & dut.core.ieu.dp.regf.wd3 == 1)) | - ((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | + ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), diff --git a/testbench/testbench-linux-imperas.sv b/testbench/testbench-linux-imperas.sv index 52a351d2e..c5443af42 100644 --- a/testbench/testbench-linux-imperas.sv +++ b/testbench/testbench-linux-imperas.sv @@ -229,10 +229,16 @@ module testbench; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Cache Issue /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// + + // Duplicate copy of pipeline registers that are optimized out of some configurations + logic [31:0] NextInstrE, InstrM; + mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); + flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); + logic probe; if (NO_SPOOFING) assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c - & testbench.dut.core.InstrM != 32'h14021273 + & InstrM != 32'h14021273 & testbench.dut.core.InstrValidM; @@ -452,7 +458,7 @@ module testbench; `define FLUSHW dut.core.FlushW `define STALLW dut.core.StallW flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW); - flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW); + flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW); flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW); flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW); flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW); @@ -969,7 +975,7 @@ module testbench; instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrD, dut.core.ifu.InstrE, - dut.core.ifu.InstrM, InstrW, + InstrM, InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // ------------------ diff --git a/testbench/testbench-linux.sv b/testbench/testbench-linux.sv index 683f55952..ef165865f 100644 --- a/testbench/testbench-linux.sv +++ b/testbench/testbench-linux.sv @@ -212,10 +212,16 @@ module testbench; /////////////////////////////////////////////////////////////////////////////// /////////////////////////////// Cache Issue /////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// + + // Duplicate copy of pipeline registers that are optimized out of some configurations + logic [31:0] NextInstrE, InstrM; + mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); + flopenr #(32) InstrMReg(dut.core.clk, dut.core.reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); + logic probe; if (NO_SPOOFING) assign probe = testbench.dut.core.PCM == 64'hffffffff80200c8c - & testbench.dut.core.InstrM != 32'h14021273 + & InstrM != 32'h14021273 & testbench.dut.core.InstrValidM; @@ -280,7 +286,7 @@ module testbench; `define FLUSHW dut.core.FlushW `define STALLW dut.core.StallW flopenrc #(P.XLEN) PCWReg(clk, reset, `FLUSHW, ~`STALLW, `PCM, PCW); - flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : dut.core.ifu.InstrM, InstrW); + flopenr #(32) InstrWReg(clk, reset, ~`STALLW, `FLUSHW ? nop : InstrM, InstrW); flopenrc #(1) controlregW(clk, reset, `FLUSHW, ~`STALLW, dut.core.ieu.c.InstrValidM, InstrValidW); flopenrc #(P.XLEN) IEUAdrWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.IEUAdrM, IEUAdrW); flopenrc #(P.XLEN) WriteDataWReg(clk, reset, `FLUSHW, ~`STALLW, dut.core.lsu.WriteDataM, WriteDataW); @@ -794,7 +800,7 @@ module testbench; instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrD, dut.core.ifu.InstrE, - dut.core.ifu.InstrM, InstrW, + InstrM, InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // ------------------ diff --git a/testbench/testbench-xcelium.sv b/testbench/testbench-xcelium.sv index 89a7cc995..f5dd89290 100644 --- a/testbench/testbench-xcelium.sv +++ b/testbench/testbench-xcelium.sv @@ -440,20 +440,25 @@ module testbench; // Support logic //////////////////////////////////////////////////////////////////////////////// + // Duplicate copy of pipeline registers that are optimized out of some configurations + logic [31:0] NextInstrE, InstrM; + mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); + flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); + // Track names of instructions string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; logic [31:0] InstrW; - flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); + flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW); instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrD, dut.core.ifu.InstrE, - dut.core.ifu.InstrM, InstrW, + InstrM, InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // watch for problems such as lockup, reading unitialized memory, bad configs watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, - dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName); + dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName); 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); @@ -478,7 +483,7 @@ module testbench; (dut.core.ieu.dp.regf.we3 & dut.core.ieu.dp.regf.a3 == 3 & dut.core.ieu.dp.regf.wd3 == 1)) | - ((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | + ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone)); diff --git a/testbench/testbench.sv b/testbench/testbench.sv index 97d91b0ab..063ff5448 100644 --- a/testbench/testbench.sv +++ b/testbench/testbench.sv @@ -408,20 +408,25 @@ module testbench; // Support logic //////////////////////////////////////////////////////////////////////////////// + // Duplicate copy of pipeline registers that are optimized out of some configurations + logic [31:0] NextInstrE, InstrM; + mux2 #(32) FlushInstrMMux(dut.core.ifu.InstrE, dut.core.ifu.nop, dut.core.ifu.FlushM, NextInstrE); + flopenr #(32) InstrMReg(clk, reset, ~dut.core.ifu.StallM, NextInstrE, InstrM); + // Track names of instructions string InstrFName, InstrDName, InstrEName, InstrMName, InstrWName; logic [31:0] InstrW; - flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, dut.core.ifu.InstrM, InstrW); + flopenr #(32) InstrWReg(clk, reset, ~dut.core.ieu.dp.StallW, InstrM, InstrW); instrTrackerTB it(clk, reset, dut.core.ieu.dp.FlushE, dut.core.ifu.InstrRawF[31:0], dut.core.ifu.InstrD, dut.core.ifu.InstrE, - dut.core.ifu.InstrM, InstrW, + InstrM, InstrW, InstrFName, InstrDName, InstrEName, InstrMName, InstrWName); // watch for problems such as lockup, reading unitialized memory, bad configs watchdog #(P.XLEN, 1000000) watchdog(.clk, .reset); // check if PCW is stuck ramxdetector #(P.XLEN, P.LLEN) ramxdetector(clk, dut.core.lsu.MemRWM[1], dut.core.lsu.LSULoadAccessFaultM, dut.core.lsu.ReadDataM, - dut.core.ifu.PCM, dut.core.ifu.InstrM, dut.core.lsu.IEUAdrM, InstrMName); + dut.core.ifu.PCM, InstrM, dut.core.lsu.IEUAdrM, InstrMName); 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); @@ -446,7 +451,7 @@ module testbench; (dut.core.ieu.dp.regf.we3 & dut.core.ieu.dp.regf.a3 == 3 & dut.core.ieu.dp.regf.wd3 == 1)) | - ((dut.core.ifu.InstrM == 32'h6f | dut.core.ifu.InstrM == 32'hfc32a423 | dut.core.ifu.InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | + ((InstrM == 32'h6f | InstrM == 32'hfc32a423 | InstrM == 32'hfc32a823) & dut.core.ieu.c.InstrValidM ) | ((dut.core.lsu.IEUAdrM == ProgramAddrLabelArray["tohost"]) & InstrMName == "SW" ); DCacheFlushFSM #(P) DCacheFlushFSM(.clk(clk), .reset(reset), .start(DCacheFlushStart), .done(DCacheFlushDone));