A timing optimisation for the direction predictor.
Add a "nextPc" interface so that lookup can begin in the previous cycle. Remove the "pc" operands in the vector of lookup interfaces, but rather derive the PC from lookup from the first PC being looked up in that cycle. That is, by adding 4*(interface number) to the beginning lookup PC. As this might not actually be the PC of the instruction, pass the index you used with the training info so that you are certain to train with the same index you looked up. This has less than 1% overhead in CoreMark. This is a general improvement for reasonable timing which should be upstreamed.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user