diff --git a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv index 536a330..4cb507a 100644 --- a/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv +++ b/src_Core/RISCY_OOO/procs/RV64G_OOO/FetchStage.bsv @@ -358,6 +358,10 @@ module mkFetchStage(FetchStage); Integer pc_fetch3_port = 2; Integer pc_redirect_port = 3; Integer pc_final_port = 4; + // To track the next expected PC in Decode for early lookups for prediction. + Ehr#(TAdd#(SupSize, 2), Addr) decode_pc_reg <- mkEhr(?); + Integer decode_pc_redirect_port = valueOf(SupSize); + Integer decode_pc_final_port = valueOf(SupSize) + 1; // PC compression structure holding an indexed set of PC blocks so that only indexes need be tracked. IndexedMultiset#(PcIdx, PcMSB, SupSizeX2) pcBlocks <- mkIndexedMultisetQueue; @@ -659,7 +663,7 @@ module mkFetchStage(FetchStage); Maybe#(IType) redirectInst = Invalid; `endif // Vector functions to generate all PCs, predicted next PCs, decode all instructions, - // and perform direction prediction for all. Taking these out of the following loop + // and perform direction predictions. Taking these out of the following loop // makes them unconditional, not depending on previous iterations, improving timing. function t valid (Maybe#(t) v) = v.Valid; function CapMem getPc(Integer i) = decompressPc(valid(decodeIn[i]).pc); @@ -675,7 +679,7 @@ module mkFetchStage(FetchStage); Bool fetch_branch_misprediction = False; for (Integer i = 0; i < valueof(SupSize); i=i+1) begin if(dInsts[i].iType == Br && !fetch_branch_misprediction) begin - pred_ress[i] <- dirPred.pred[i].pred(getAddr(pcs[i])); + pred_ress[i] <- dirPred.pred[i].pred; fetch_branch_misprediction = (pred_ress[i].taken != valid(decodeIn[i]).pred_jump); end end @@ -686,14 +690,14 @@ module mkFetchStage(FetchStage); for (Integer i = 0; i < valueof(SupSize); i=i+1) begin if (decodeIn[i] matches tagged Valid .in) begin let cause = in.cause; - CapMem pc = pcs[i];//decompressPc(in.pc); - CapMem ppc = ppcs[i];//decompressPc(in.ppc); + CapMem pc = pcs[i]; + CapMem ppc = ppcs[i]; pcBlocks.rPort[i].remove(in.pc.idx); if (verbose) $display("Decode: %0d in = ", i, fshow (in)); - let decode_result = decode_results[i];//decode(in.inst, getFlags(pc)==1); // Decode 32b inst, or 32b expansion of 16b inst - let dInst = dInsts[i];//decode_result.dInst; + let decode_result = decode_results[i]; // Decode 32b inst, or 32b expansion of 16b inst + let dInst = dInsts[i]; let regs = decode_result.regs; // do decode and branch prediction @@ -792,6 +796,7 @@ module mkFetchStage(FetchStage); `endif end end // if (!isValid(cause)) + decode_pc_reg[i] <= getAddr(ppc); let out = FromFetchStage{pc: pc, `ifdef RVFI_DII dii_pid: in.dii_pid, @@ -823,8 +828,8 @@ module mkFetchStage(FetchStage); end // for (Integer i = 0; i < valueof(SupSize); i=i+1) // update PC and epoch - if(redirectPc matches tagged Valid .nextPc) begin - pc_reg[pc_decode_port] <= nextPc; + if(redirectPc matches tagged Valid .rp) begin + pc_reg[pc_decode_port] <= rp; end `ifdef RVFI_DII doAssert(isValid(redirectPc) == isValid(redirectDiiPid), "PC and DII redirections always happen together"); @@ -850,6 +855,10 @@ module mkFetchStage(FetchStage); `endif endrule + rule reportDecodePc; + dirPred.nextPc(decode_pc_reg[decode_pc_final_port]); + endrule + // train next addr pred: we use a wire to catch outputs of napTrainByDecQ. // This prevents napTrainByDecQ from clogging doDecode rule when // superscalar size is large @@ -917,6 +926,7 @@ module mkFetchStage(FetchStage); dii_pid_reg[pc_redirect_port] <= dii_pid; if (verbose) $display("%t Redirect: dii_pid_reg %d", $time(), dii_pid); `endif + decode_pc_reg[decode_pc_redirect_port] <= getAddr(new_pc); f_main_epoch <= (f_main_epoch == fromInteger(valueOf(NumEpochs)-1)) ? 0 : f_main_epoch + 1; // redirect comes, stop stalling for redirect waitForRedirect[1] <= False; @@ -958,7 +968,7 @@ module mkFetchStage(FetchStage); //end if (iType == Br) begin // Train the direction predictor for all branches - dirPred.update(getAddr(pc), taken, dpTrain, mispred); + dirPred.update(taken, dpTrain, mispred); end // train next addr pred when mispred if(mispred) begin diff --git a/src_Core/RISCY_OOO/procs/lib/Bht.bsv b/src_Core/RISCY_OOO/procs/lib/Bht.bsv index e87cb08..7560fb4 100644 --- a/src_Core/RISCY_OOO/procs/lib/Bht.bsv +++ b/src_Core/RISCY_OOO/procs/lib/Bht.bsv @@ -42,18 +42,21 @@ import BrPred::*; export BhtTrainInfo; export mkBht; - -typedef Bit#(0) BhtTrainInfo; // no training info needs to be remembered +export BhtEntries; +export BhtIndex; // Local BHT Typedefs typedef 128 BhtEntries; typedef Bit#(TLog#(BhtEntries)) BhtIndex; +typedef BhtIndex BhtTrainInfo; + (* synthesize *) module mkBht(DirPredictor#(BhtTrainInfo)); // Read and Write ordering doesn't matter since this is a predictor // mkRegFileWCF is the RegFile version of mkConfigReg RegFile#(BhtIndex, Bit#(2)) hist <- mkRegFileWCF(0,fromInteger(valueOf(BhtEntries)-1)); + Reg#(Addr) pc_reg <- mkRegU; function BhtIndex getIndex(Addr pc); return truncate(pc >> 2); @@ -62,22 +65,24 @@ module mkBht(DirPredictor#(BhtTrainInfo)); Vector#(SupSize, DirPred#(BhtTrainInfo)) predIfc; for(Integer i = 0; i < valueof(SupSize); i = i+1) begin predIfc[i] = (interface DirPred; - method ActionValue#(DirPredResult#(BhtTrainInfo)) pred(Addr pc); - let index = getIndex(pc); + method ActionValue#(DirPredResult#(BhtTrainInfo)) pred; + let index = getIndex(offsetPc(pc_reg, i)); Bit#(2) cnt = hist.sub(index); Bool taken = cnt[1] == 1; return DirPredResult { taken: taken, - train: 0 + train: index }; endmethod endinterface); end + method nextPc = pc_reg._write; + interface pred = predIfc; - method Action update(Addr pc, Bool taken, BhtTrainInfo train, Bool mispred); - let index = getIndex(pc); + method Action update(Bool taken, BhtTrainInfo train, Bool mispred); + let index = train; let current_hist = hist.sub(index); Bit#(2) next_hist; if(taken) begin diff --git a/src_Core/RISCY_OOO/procs/lib/BrPred.bsv b/src_Core/RISCY_OOO/procs/lib/BrPred.bsv index 8d074a4..76f1b8e 100644 --- a/src_Core/RISCY_OOO/procs/lib/BrPred.bsv +++ b/src_Core/RISCY_OOO/procs/lib/BrPred.bsv @@ -67,18 +67,22 @@ endfunction // general types for direction predictor +// Function to offset PC by the probable size of an instruction without a full add delay. +function Addr offsetPc(Addr pc, Integer i) = {truncateLSB(pc), pc[7:0] + (fromInteger(i)*4)}; + typedef struct { Bool taken; trainInfoT train; // info that a branch must keep for future training } DirPredResult#(type trainInfoT) deriving(Bits, Eq, FShow); interface DirPred#(type trainInfoT); - method ActionValue#(DirPredResult#(trainInfoT)) pred(Addr pc); + method ActionValue#(DirPredResult#(trainInfoT)) pred; endinterface interface DirPredictor#(type trainInfoT); + method Action nextPc(Addr nextPc); interface Vector#(SupSize, DirPred#(trainInfoT)) pred; - method Action update(Addr pc, Bool taken, trainInfoT train, Bool mispred); + method Action update(Bool taken, trainInfoT train, Bool mispred); method Action flush; method Bool flush_done; endinterface diff --git a/src_Core/RISCY_OOO/procs/lib/GSelectPred.bsv b/src_Core/RISCY_OOO/procs/lib/GSelectPred.bsv index 41b9f12..adf70ca 100644 --- a/src_Core/RISCY_OOO/procs/lib/GSelectPred.bsv +++ b/src_Core/RISCY_OOO/procs/lib/GSelectPred.bsv @@ -46,6 +46,9 @@ export GSelectGHistSz; export GSelectGHist; export GSelectTrainInfo; export mkGSelectPred; +export PCIndexSz; +export BhtIndexSz; +export BhtIndex; // 1KB gselect predictor @@ -60,6 +63,7 @@ typedef Bit#(BhtIndexSz) BhtIndex; // bookkeeping info a branch should keep for future training typedef struct { GSelectGHist gHist; + BhtIndex index; } GSelectTrainInfo deriving(Bits, Eq, FShow); // global history @@ -83,6 +87,9 @@ module mkGSelectPred(DirPredictor#(GSelectTrainInfo)); Ehr#(TAdd#(1, SupSize), Bit#(TLog#(TAdd#(SupSize, 1)))) predCnt <- mkEhr(0); Ehr#(TAdd#(1, SupSize), Bit#(SupSize)) predRes <- mkEhr(0); + // Lookup PC + Reg#(Addr) pc_reg <- mkRegU; + function BhtIndex getIndex(Addr pc, GSelectGHist gHist); Bit#(PCIndexSz) pcIdx = truncate(pc >> 2); return {gHist, pcIdx}; @@ -106,13 +113,14 @@ module mkGSelectPred(DirPredictor#(GSelectTrainInfo)); Vector#(SupSize, DirPred#(GSelectTrainInfo)) predIfc; for(Integer i = 0; i < valueof(SupSize); i = i+1) begin predIfc[i] = (interface DirPred; - method ActionValue#(DirPredResult#(GSelectTrainInfo)) pred(Addr pc); + method ActionValue#(DirPredResult#(GSelectTrainInfo)) pred; // get the global history // all previous branch in this cycle must be not taken // otherwise this branch should be on wrong path // because all inst in same cycle are fetched consecutively GSelectGHist gHist = curGHist >> predCnt[i]; - Bool taken = isTaken(tab.sub(getIndex(pc, gHist))); + BhtIndex index = getIndex(offsetPc(pc_reg, i), gHist); + Bool taken = isTaken(tab.sub(index)); // record pred result predCnt[i] <= predCnt[i] + 1; @@ -124,7 +132,8 @@ module mkGSelectPred(DirPredictor#(GSelectTrainInfo)); return DirPredResult { taken: taken, train: GSelectTrainInfo { - gHist: gHist + gHist: gHist, + index: index } }; endmethod @@ -138,16 +147,18 @@ module mkGSelectPred(DirPredictor#(GSelectTrainInfo)); predCnt[valueof(SupSize)] <= 0; endrule + method nextPc = pc_reg._write; + interface pred = predIfc; - method Action update(Addr pc, Bool taken, GSelectTrainInfo train, Bool mispred); + method Action update(Bool taken, GSelectTrainInfo train, Bool mispred); // update history if mispred if(mispred) begin GSelectGHist newHist = truncate({pack(taken), train.gHist} >> 1); globalHist.redirect(newHist); end // update sat cnt - let index = getIndex(pc, train.gHist); + let index = train.index; Bit#(2) cnt = tab.sub(index); tab.upd(index, updateCnt(cnt, taken)); endmethod diff --git a/src_Core/RISCY_OOO/procs/lib/GSharePred.bsv b/src_Core/RISCY_OOO/procs/lib/GSharePred.bsv index 395ba46..b95541f 100644 --- a/src_Core/RISCY_OOO/procs/lib/GSharePred.bsv +++ b/src_Core/RISCY_OOO/procs/lib/GSharePred.bsv @@ -46,6 +46,8 @@ export GShareGHistSz; export GShareGHist; export GShareTrainInfo; export mkGSharePred; +export BhtIndexSz; +export BhtIndex; // 16KB gshare predictor (to match BOOM evaluation paper) @@ -60,6 +62,7 @@ typedef Bit#(BhtIndexSz) BhtIndex; // bookkeeping info a branch should keep for future training typedef struct { GShareGHist gHist; + BhtIndex index; } GShareTrainInfo deriving(Bits, Eq, FShow); // global history @@ -83,6 +86,9 @@ module mkGSharePred(DirPredictor#(GShareTrainInfo)); Ehr#(TAdd#(1, SupSize), Bit#(TLog#(TAdd#(SupSize, 1)))) predCnt <- mkEhr(0); Ehr#(TAdd#(1, SupSize), Bit#(SupSize)) predRes <- mkEhr(0); + // Lookup PC + Reg#(Addr) pc_reg <- mkRegU; + function BhtIndex getIndex(Addr pc, GShareGHist gHist); Bit#(PCIndexSz) pcIdx = truncate(pc >> 2); return gHist ^ pcIdx; @@ -106,13 +112,14 @@ module mkGSharePred(DirPredictor#(GShareTrainInfo)); Vector#(SupSize, DirPred#(GShareTrainInfo)) predIfc; for(Integer i = 0; i < valueof(SupSize); i = i+1) begin predIfc[i] = (interface DirPred; - method ActionValue#(DirPredResult#(GShareTrainInfo)) pred(Addr pc); + method ActionValue#(DirPredResult#(GShareTrainInfo)) pred; // get the global history // all previous branch in this cycle must be not taken // otherwise this branch should be on wrong path // because all inst in same cycle are fetched consecutively GShareGHist gHist = curGHist >> predCnt[i]; - Bool taken = isTaken(tab.sub(getIndex(pc, gHist))); + BhtIndex index = getIndex(offsetPc(pc_reg, i), gHist); + Bool taken = isTaken(tab.sub(index)); // record pred result predCnt[i] <= predCnt[i] + 1; @@ -124,7 +131,8 @@ module mkGSharePred(DirPredictor#(GShareTrainInfo)); return DirPredResult { taken: taken, train: GShareTrainInfo { - gHist: gHist + gHist: gHist, + index: index } }; endmethod @@ -138,18 +146,19 @@ module mkGSharePred(DirPredictor#(GShareTrainInfo)); predCnt[valueof(SupSize)] <= 0; endrule + method nextPc = pc_reg._write; + interface pred = predIfc; - method Action update(Addr pc, Bool taken, GShareTrainInfo train, Bool mispred); + method Action update(Bool taken, GShareTrainInfo train, Bool mispred); // update history if mispred if(mispred) begin GShareGHist newHist = truncate({pack(taken), train.gHist} >> 1); globalHist.redirect(newHist); end // update sat cnt - let index = getIndex(pc, train.gHist); - Bit#(2) cnt = tab.sub(index); - tab.upd(index, updateCnt(cnt, taken)); + Bit#(2) cnt = tab.sub(train.index); + tab.upd(train.index, updateCnt(cnt, taken)); endmethod method flush = noAction; diff --git a/src_Core/RISCY_OOO/procs/lib/TourPred.bsv b/src_Core/RISCY_OOO/procs/lib/TourPred.bsv index 7cd680b..ede7bb9 100644 --- a/src_Core/RISCY_OOO/procs/lib/TourPred.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TourPred.bsv @@ -50,6 +50,8 @@ export TourTrainInfo(..); export TourGHistReg(..); export mkTourGHistReg; export mkTourPred; +export PCIndexSz; +export PCIndex; // 4KB tournament predictor @@ -66,6 +68,7 @@ typedef struct { TourLocalHist localHist; Bool globalTaken; Bool localTaken; + PCIndex pcIndex; } TourTrainInfo deriving(Bits, Eq, FShow); // global history reg @@ -90,6 +93,9 @@ module mkTourPred(DirPredictor#(TourTrainInfo)); // choice sat counters: large (taken) -- use local, small (not taken) -- use global RegFile#(TourGlobalHist, Bit#(2)) choiceBht <- mkRegFileWCF(0, maxBound); + // Lookup PC + Reg#(Addr) pc_reg <- mkRegU; + // EHR to record predict results in this cycle Ehr#(TAdd#(1, SupSize), SupCnt) predCnt <- mkEhr(0); Ehr#(TAdd#(1, SupSize), Bit#(SupSize)) predRes <- mkEhr(0); @@ -120,9 +126,10 @@ module mkTourPred(DirPredictor#(TourTrainInfo)); Vector#(SupSize, DirPred#(TourTrainInfo)) predIfc; for(Integer i = 0; i < valueof(SupSize); i = i+1) begin predIfc[i] = (interface DirPred; - method ActionValue#(DirPredResult#(TourTrainInfo)) pred(Addr pc); + method ActionValue#(DirPredResult#(TourTrainInfo)) pred; + PCIndex pcIndex = getPCIndex(offsetPc(pc_reg, i)); // get local history & prediction - TourLocalHist localHist = localHistTab.sub(getPCIndex(pc)); + TourLocalHist localHist = localHistTab.sub(pcIndex); Bool localTaken = isTaken(localBht.sub(localHist)); // get the global history @@ -149,7 +156,8 @@ module mkTourPred(DirPredictor#(TourTrainInfo)); globalHist: curGHist >> predCnt[i], localHist: localHist, globalTaken: globalTaken, - localTaken: localTaken + localTaken: localTaken, + pcIndex: pcIndex } }; endmethod @@ -171,16 +179,18 @@ module mkTourPred(DirPredictor#(TourTrainInfo)); predCnt[valueof(SupSize)] <= 0; endrule + method nextPc = pc_reg._write; + interface pred = predIfc; - method Action update(Addr pc, Bool taken, TourTrainInfo train, Bool mispred); + method Action update(Bool taken, TourTrainInfo train, Bool mispred); // update history if mispred if(mispred) begin TourGlobalHist newHist = truncateLSB({pack(taken), train.globalHist}); gHistReg.redirect(newHist); end // update local history (assume only 1 branch for an PC in flight) - localHistTab.upd(getPCIndex(pc), truncateLSB({pack(taken), train.localHist})); + localHistTab.upd(train.pcIndex, truncateLSB({pack(taken), train.localHist})); // update local sat cnt let localCnt = localBht.sub(train.localHist); localBht.upd(train.localHist, updateCnt(localCnt, taken)); diff --git a/src_Core/RISCY_OOO/procs/lib/TourPredSecure.bsv b/src_Core/RISCY_OOO/procs/lib/TourPredSecure.bsv index 747b531..d97b46f 100644 --- a/src_Core/RISCY_OOO/procs/lib/TourPredSecure.bsv +++ b/src_Core/RISCY_OOO/procs/lib/TourPredSecure.bsv @@ -73,7 +73,6 @@ typedef TExp#(LgGlobalVecSz) GlobalVecSz; typedef Bit#(GlobalVecSz) GlobalVecSelect; typedef struct { - Addr pc; Bool taken; TourTrainInfo train; Bool mispred; @@ -93,6 +92,9 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); // choice sat counters: large (taken) -- use local, small (not taken) -- use global RegFile#(TabIndex, Vector#(GlobalVecSz, Bit#(2))) choiceBht <- mkRegFileWCF(0, maxBound); + // Lookup PC + Reg#(Addr) pc_reg <- mkRegU; + // EHR to record predict results in this cycle Ehr#(TAdd#(1, SupSize), SupCnt) predCnt <- mkEhr(0); Ehr#(TAdd#(1, SupSize), Bit#(SupSize)) predRes <- mkEhr(0); @@ -103,8 +105,9 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); Reg#(Bool) flushDone <- mkReg(True); Reg#(TabIndex) flushIndex <- mkReg(0); - function Tuple2#(TabIndex, LocalHistVecSelect) getPCIndex(Addr pc); - PCIndex pcIdx = truncate(pc >> 2); + function PCIndex getPCIndex(Addr pc) = truncate(pc >> 2); + + function Tuple2#(TabIndex, LocalHistVecSelect) getPCIndices(PCIndex pcIdx); TabIndex tabIdx = truncateLSB(pcIdx); LocalHistVecSelect sel = truncate(pcIdx); return tuple2(tabIdx, sel); @@ -142,9 +145,10 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); Vector#(SupSize, DirPred#(TourTrainInfo)) predIfc; for(Integer i = 0; i < valueof(SupSize); i = i+1) begin predIfc[i] = (interface DirPred; - method ActionValue#(DirPredResult#(TourTrainInfo)) pred(Addr pc); + method ActionValue#(DirPredResult#(TourTrainInfo)) pred; // get local history - let {localHistTabIdx, localHistVecSel} = getPCIndex(pc); + PCIndex pcIndex = getPCIndex(offsetPc(pc_reg, i)); + let {localHistTabIdx, localHistVecSel} = getPCIndices(pcIndex); Vector#(LocalHistVecSz, TourLocalHist) localHistVec = localHistTab.sub(localHistTabIdx); TourLocalHist localHist = localHistVec[localHistVecSel]; // get local prediction @@ -180,7 +184,8 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); globalHist: globalHist, localHist: localHist, globalTaken: globalTaken, - localTaken: localTaken + localTaken: localTaken, + pcIndex: pcIndex } }; endmethod @@ -197,7 +202,6 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); // no flush, accept update (* fire_when_enabled, no_implicit_conditions *) rule canonUpdate(flushDone &&& updateEn.wget matches tagged Valid .upd); - let pc = upd.pc; let taken = upd.taken; let train = upd.train; let mispred = upd.mispred; @@ -209,7 +213,7 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); end // update local history (assume only 1 branch for an PC in flight) - let {localHistTabIdx, localHistVecSel} = getPCIndex(pc); + let {localHistTabIdx, localHistVecSel} = getPCIndices(train.pcIndex); Vector#(LocalHistVecSz, TourLocalHist) localHistVec = localHistTab.sub(localHistTabIdx); localHistVec[localHistVecSel] = truncateLSB({pack(taken), train.localHist}); localHistTab.upd(localHistTabIdx, localHistVec); @@ -251,10 +255,12 @@ module mkTourPredSecure(DirPredictor#(TourTrainInfo)); end endrule + method nextPc = pc_reg._write; + interface pred = predIfc; - method Action update(Addr pc, Bool taken, TourTrainInfo train, Bool mispred); - updateEn.wset(TourUpdate {pc: pc, taken: taken, train: train, mispred: mispred}); + method Action update(Bool taken, TourTrainInfo train, Bool mispred); + updateEn.wset(TourUpdate {taken: taken, train: train, mispred: mispred}); endmethod method Action flush if(flushDone);