From 54d1a204f0fa0a7c2253802bd0bc4f65f7cfc543 Mon Sep 17 00:00:00 2001 From: Jonathan Woodruff Date: Fri, 17 Dec 2021 16:29:14 +0000 Subject: [PATCH] Don't decode redirected streams until they are non-speculative. --- builds/Resources/Include_Common.mk | 2 +- src_Core/CPU/Core.bsv | 12 +++-- .../procs/RV64G_OOO/AluExePipeline.bsv | 4 +- .../RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv | 49 ++++++++++++----- .../RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv | 52 ++++++++++++++----- src_Core/RISCY_OOO/procs/lib/Bht.bsv | 4 +- 6 files changed, 85 insertions(+), 38 deletions(-) diff --git a/builds/Resources/Include_Common.mk b/builds/Resources/Include_Common.mk index 9bc23e0..d7f1131 100644 --- a/builds/Resources/Include_Common.mk +++ b/builds/Resources/Include_Common.mk @@ -89,7 +89,7 @@ BSC_COMPILATION_FLAGS += \ -D RISCV \ -D PERFORMANCE_MONITORING \ -D RAS_HIT_TRACING \ - -D TSO_MM \ + -D TSO_MM -D NO_SPEC_TRAINING -D NO_SPEC_REDIRECT \ -keep-fires -aggressive-conditions -no-warn-action-shadowing -check-assert \ -suppress-warnings G0020 -steps-max-intervals 10000000 \ -steps-warn-interval 1000000 \ diff --git a/src_Core/CPU/Core.bsv b/src_Core/CPU/Core.bsv index 70f0e23..fdd760f 100644 --- a/src_Core/CPU/Core.bsv +++ b/src_Core/CPU/Core.bsv @@ -353,7 +353,8 @@ module mkCore#(CoreId coreId)(Core); end GlobalSpecUpdate#(CorrectSpecPortNum, ConflictWrongSpecPortNum) globalSpecUpdate <- mkGlobalSpecUpdate( joinSpeculationUpdate( - append(append(append(vec(regRenamingTable.specUpdate, + append(append(append(vec(fetchStage.specUpdate, + regRenamingTable.specUpdate, specTagManager.specUpdate, fix.memExeIfc.specUpdate), aluSpecUpdate), fpuMulDivSpecUpdate), btqSpecUpdate) ), @@ -417,15 +418,16 @@ module mkCore#(CoreId coreId)(Core); method setRegReadyAggr = writeAggr(aluWrAggrPort(i)); interface sendBypass = sendBypassIfc; method writeRegFile = writeCons(aluWrConsPort(i)); - method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag); + method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits); if (verbose) begin $display("[ALU redirect - %d] ", i, fshow(new_pc), "; ", fshow(spec_tag), "; ", fshow(inst_tag)); end epochManager.incrementEpoch; - fetchStage.redirect(new_pc + fetchStage.redirect(new_pc, + spec_bits `ifdef RVFI_DII - , inst_tag.dii_next_pid + , inst_tag.dii_next_pid `endif ); globalSpecUpdate.incorrectSpec(False, spec_tag, inst_tag); @@ -1447,7 +1449,7 @@ module mkCore#(CoreId coreId)(Core); l2Tlb.updateVMInfo(vmI, vmD); let startpc = csrf.dpc_read; - fetchStage.redirect (cast(startpc)); + fetchStage.redirect (cast(startpc), 0); renameStage.debug_resume; commitStage.debug_resume; diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv index 0bd1678..b108761 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/AluExePipeline.bsv @@ -194,7 +194,7 @@ interface AluExeInput; // write reg file & set conservative sb method Action writeRegFile(PhyRIndx dst, CapPipe data); // redirect - method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag); + method Action redirect(CapMem new_pc, SpecTag spec_tag, InstTag inst_tag, SpecBits spec_bits); // spec update method Action correctSpec(SpecTag t); @@ -484,7 +484,7 @@ module mkAluExePipeline#(AluExeInput inIfc)(AluExePipeline); if (x.controlFlow.mispredict) (* nosplit *) begin // wrong branch predictin, we must have spec tag doAssert(isValid(x.spec_tag), "mispredicted branch must have spec tag"); - inIfc.redirect(cast(x.controlFlow.nextPc), validValue(x.spec_tag), x.tag); + inIfc.redirect(cast(x.controlFlow.nextPc), validValue(x.spec_tag), x.tag, exeToFin.spec_bits); // must be a branch, train branch predictor doAssert(x.iType == Jr || x.iType == CJALR || x.iType == CCall || x.iType == Br, "only jr, br, cjalr, and ccall can mispredict"); inIfc.fetch_train_predictors(ToSpecFifo { diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv index 168b20b..8d5d19a 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/CommitStage.bsv @@ -118,7 +118,9 @@ interface CommitInput; method Action setReconcileD; // recocile D$ // redirect method Action killAll; - method Action redirectPc(CapMem trap_pc + method Action redirectPc( + CapMem trap_pc, + SpecBits specBits `ifdef RVFI_DII , Dii_Parcel_Id dii_pid `endif @@ -157,6 +159,13 @@ typedef struct { SpecBits specBits; } RenameErrInfo deriving(Bits, Eq, FShow); +typedef struct { + CapMem trap_pc; +`ifdef RVFI_DII + Dii_Parcel_Id dii_pid; +`endif +} RedirectInfo deriving(Bits, Eq, FShow); + interface CommitStage; // performance method Data getPerf(ComStagePerfType t); @@ -519,6 +528,8 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // cycle handles trap, redirect and handles system consistency Reg#(Maybe#(CommitTrap)) commitTrap <- mkReg(Invalid); // saves new pc here + FIFO#(RedirectInfo) redirectQ <- mkFIFO; + // maintain system consistency when system state (CSR) changes or for security function Action makeSystemConsistent(Bool flushTlb, Bool flushSecurity, @@ -780,11 +791,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // trap handling & redirect let trap_updates <- csrf.trap(trap.trap, cast(trap.pc), trap.addr, trap.orig_inst); CapPipe new_pc = cast(trap_updates.new_pcc); - inIfc.redirectPc(cast(new_pc) + redirectQ.enq(RedirectInfo{trap_pc: cast(new_pc) `ifdef RVFI_DII - , trap.x.dii_pid + (is_16b_inst(trap.orig_inst) ? 1 : 2) + , dii_pid: trap.x.dii_pid + (is_16b_inst(trap.orig_inst) ? 1 : 2) `endif - ); + }); `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); rvfis[0] = genRVFI(trap.x, traceCnt, getTSB(), getAddr(new_pc)); @@ -825,11 +836,11 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); // kill everything, redirect, and increment epoch inIfc.killAll; - inIfc.redirectPc(x.pc -`ifdef RVFI_DII - , x.dii_pid -`endif - ); + redirectQ.enq(RedirectInfo{trap_pc: x.pc + `ifdef RVFI_DII + , dii_pid: x.dii_pid + `endif + }); inIfc.incrementEpoch; // the killed Ld should have claimed phy reg, we should not commit it; @@ -945,11 +956,12 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); m_ret_updates = tagged Valid ret_updates; `endif end - inIfc.redirectPc(next_pc -`ifdef RVFI_DII - , x.dii_pid + (is_16b_inst(x.orig_inst) ? 1 : 2) -`endif - ); + redirectQ.enq(RedirectInfo{trap_pc: next_pc + `ifdef RVFI_DII + , x.dii_pid + (is_16b_inst(x.orig_inst) ? 1 : 2) + `endif + }); + `ifdef RVFI Rvfi_Traces rvfis = replicate(tagged Invalid); @@ -1343,6 +1355,15 @@ module mkCommitStage#(CommitInput inIfc)(CommitStage); `endif endrule + rule pass_redirect; + RedirectInfo ri <- toGet(redirectQ).get; + inIfc.redirectPc(ri.trap_pc, 0 +`ifdef RVFI_DII + , ri.rii_pid +`endif + ); + endrule + // ================================================================ // INTERFACE diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 788fc1c..a78dbe4 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -62,6 +62,8 @@ import Vector::*; import Assert::*; import Cntrs::*; import ConfigReg::*; +import HasSpecBits::*; +import SpecFifo::*; import TlbTypes::*; import ITlb::*; import CCTypes::*; @@ -131,7 +133,9 @@ interface FetchStage; // redirection methods method Action setWaitRedirect; - method Action redirect(CapMem pc + method Action redirect( + CapMem pc, + SpecBits specBits `ifdef RVFI_DII , Dii_Parcel_Id parcel_id `endif @@ -144,6 +148,7 @@ interface FetchStage; CapMem pc, CapMem next_pc, IType iType, Bool taken, PredTrainInfo trainInfo, Bool mispred, Bool isCompressed ); + interface SpeculationUpdate specUpdate; // security method Bool emptyForFlush; @@ -336,7 +341,7 @@ module mkFetchStage(FetchStage); Integer verbosity = 0; // Basic State Elements - Reg#(Bool) started <- mkReg(False); + Reg#(Bool) started <- mkConfigReg(False); // Stall fetch when trap happens or system inst is renamed // All inst younger than the trap/system inst will be killed @@ -364,7 +369,14 @@ module mkFetchStage(FetchStage); function CapMem decompressPc(PcCompressed p) = {pcBlocks.lookup(p.idx),p.lsb}; // Epochs Ehr#(2, Bool) decode_epoch <- mkEhr(False); - Reg#(Epoch) f_main_epoch <- mkReg(0); // fetch estimate of main epoch + // fetch estimate of main epoch + Reg#(Epoch) f_main_epoch <- mkConfigReg(0); + SpecFifo#(2, Bit#(0), 1, 1) main_epoch_spec <- mkSpecFifoUG(True); + function Action set_main_epoch(Epoch e, SpecBits sb) = (action + f_main_epoch <= e; + if (main_epoch_spec.notEmpty) main_epoch_spec.deq; + main_epoch_spec.enq(ToSpecFifo{data: ?, spec_bits: sb}); + endaction); // Pipeline Stage FIFOs Fifo#(2, Fetch1ToFetch2) f12f2 <- mkCFFifo; @@ -549,12 +561,6 @@ module mkFetchStage(FetchStage); $display("Fetch3: Nothing else from Fetch2"); end - let drop_f22f3 = f22f3.notEmpty - && ( fetch3In.main_epoch != f_main_epoch - || fetch3In.decode_epoch != decode_epoch[1]); - - let parse_f22f3 = !drop_f22f3; - // Get ICache/MMIO response if no exception // In case of exception, we still need to process at least inst_data[0] // (it will be turned to an exception later), so inst_data[0] must be @@ -593,7 +599,15 @@ module mkFetchStage(FetchStage); end endrule: doFetch3 - function Bool isCurrent(Fetch3ToDecode in) = (in.main_epoch == f_main_epoch && in.decode_epoch == decode_epoch[0]); + Bool delay_epoch = False; +`ifdef NO_SPEC_REDIRECT + // Delay decode if the head of this buffer matches the current epoch; + // this means the source of this epoch is still speculative. + delay_epoch = (main_epoch_spec.first.spec_bits != 0); +`endif + function Bool isCurrent(Fetch3ToDecode in) = (main_epoch_spec.notEmpty && + in.main_epoch == f_main_epoch && + in.decode_epoch == decode_epoch[0]); rule doDecodeFlush(f32d.deqS[0].canDeq && !isCurrent(f32d.deqS[0].first)); for (Integer i = 0; i < valueOf(SupSizeX2); i = i + 1) @@ -603,7 +617,12 @@ module mkFetchStage(FetchStage); end endrule: doDecodeFlush - rule doDecode(f32d.deqS[0].canDeq && isCurrent(f32d.deqS[0].first)); + rule printStuff; + $display("main_epoch_spec.first.spec_bits: %x, main_epoch_spec.notEmpty: %x, isCurrent: %x, f_main_epoch: %x, next_epoch: %x", + main_epoch_spec.first.spec_bits, main_epoch_spec.notEmpty, isCurrent(f32d.deqS[0].first), f_main_epoch, f32d.deqS[0].first.main_epoch); + endrule + + rule doDecode(f32d.deqS[0].canDeq && isCurrent(f32d.deqS[0].first) && !delay_epoch); Vector#(SupSize, Maybe#(InstrFromFetch3)) decodeIn = replicate(Invalid); // Express the incoming fragments as a vector of maybes. Vector#(SupSizeX2, Maybe#(Fetch3ToDecode)) frags; @@ -886,6 +905,7 @@ module mkFetchStage(FetchStage); started <= True; waitForRedirect[0] <= False; waitForFlush[0] <= False; + set_main_epoch(0,0); endmethod method Action stop(); started <= False; @@ -895,18 +915,20 @@ module mkFetchStage(FetchStage); waitForRedirect[0] <= True; endmethod method Action redirect( - CapMem new_pc + CapMem new_pc, + SpecBits specBits `ifdef RVFI_DII , Dii_Parcel_Id dii_pid `endif ); - if (verbose) $display("Redirect: newpc %h, old f_main_epoch %d, new f_main_epoch %d",new_pc,f_main_epoch,f_main_epoch+1); + //if (verbose) + $display("Redirect: newpc %h, old f_main_epoch %d, new f_main_epoch %d, specBits %x",new_pc,f_main_epoch,f_main_epoch+1, specBits); pc_reg[pc_redirect_port] <= new_pc; `ifdef RVFI_DII dii_pid_reg[pc_redirect_port] <= dii_pid; if (verbose) $display("%t Redirect: dii_pid_reg %d", $time(), dii_pid); `endif - f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1; + set_main_epoch((f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1, specBits); // redirect comes, stop stalling for redirect waitForRedirect[1] <= False; // this redirect may be caused by a trap/system inst in commit stage @@ -958,6 +980,8 @@ module mkFetchStage(FetchStage); end endmethod + interface SpeculationUpdate specUpdate = main_epoch_spec.specUpdate; + // security method Bool emptyForFlush; return empty_for_flush; diff --git a/src_Core/RISCY_OOO/procs/lib/Bht.bsv b/src_Core/RISCY_OOO/procs/lib/Bht.bsv index bd66177..e87cb08 100644 --- a/src_Core/RISCY_OOO/procs/lib/Bht.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Bht.bsv @@ -46,10 +46,10 @@ export mkBht; typedef Bit#(0) BhtTrainInfo; // no training info needs to be remembered // Local BHT Typedefs -typedef 2048 BhtEntries; +typedef 128 BhtEntries; typedef Bit#(TLog#(BhtEntries)) BhtIndex; -//(* synthesize *) +(* synthesize *) module mkBht(DirPredictor#(BhtTrainInfo)); // Read and Write ordering doesn't matter since this is a predictor // mkRegFileWCF is the RegFile version of mkConfigReg