cpu: Implement per-thread GHRs

Branch predictors that use GHRs should index them on a
per-thread basis.  This makes that so.

This is a re-spin of fb51231 after the revert (bd1c6789).
This commit is contained in:
Mitch Hayenga 2016-04-05 12:20:19 -05:00
parent 0fd4bb7f12
commit d99deff8ea
8 changed files with 110 additions and 108 deletions

View file

@ -78,7 +78,7 @@ LocalBP::reset()
} }
void void
LocalBP::btbUpdate(Addr branch_addr, void * &bp_history) LocalBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history)
{ {
// Place holder for a function that is called to update predictor history when // Place holder for a function that is called to update predictor history when
// a BTB entry is invalid or not found. // a BTB entry is invalid or not found.
@ -86,7 +86,7 @@ LocalBP::btbUpdate(Addr branch_addr, void * &bp_history)
bool bool
LocalBP::lookup(Addr branch_addr, void * &bp_history) LocalBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history)
{ {
bool taken; bool taken;
uint8_t counter_val; uint8_t counter_val;
@ -117,7 +117,8 @@ LocalBP::lookup(Addr branch_addr, void * &bp_history)
} }
void void
LocalBP::update(Addr branch_addr, bool taken, void *bp_history, bool squashed) LocalBP::update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
bool squashed)
{ {
assert(bp_history == NULL); assert(bp_history == NULL);
unsigned local_predictor_idx; unsigned local_predictor_idx;
@ -152,7 +153,7 @@ LocalBP::getLocalIndex(Addr &branch_addr)
} }
void void
LocalBP::uncondBranch(Addr pc, void *&bp_history) LocalBP::uncondBranch(ThreadID tid, Addr pc, void *&bp_history)
{ {
} }

View file

@ -66,7 +66,7 @@ class LocalBP : public BPredUnit
*/ */
LocalBP(const LocalBPParams *params); LocalBP(const LocalBPParams *params);
virtual void uncondBranch(Addr pc, void * &bp_history); virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history);
/** /**
* Looks up the given address in the branch predictor and returns * Looks up the given address in the branch predictor and returns
@ -75,7 +75,7 @@ class LocalBP : public BPredUnit
* @param bp_history Pointer to any bp history state. * @param bp_history Pointer to any bp history state.
* @return Whether or not the branch is taken. * @return Whether or not the branch is taken.
*/ */
bool lookup(Addr branch_addr, void * &bp_history); bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history);
/** /**
* Updates the branch predictor to Not Taken if a BTB entry is * Updates the branch predictor to Not Taken if a BTB entry is
@ -84,19 +84,20 @@ class LocalBP : public BPredUnit
* @param bp_history Pointer to any bp history state. * @param bp_history Pointer to any bp history state.
* @return Whether or not the branch is taken. * @return Whether or not the branch is taken.
*/ */
void btbUpdate(Addr branch_addr, void * &bp_history); void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history);
/** /**
* Updates the branch predictor with the actual result of a branch. * Updates the branch predictor with the actual result of a branch.
* @param branch_addr The address of the branch to update. * @param branch_addr The address of the branch to update.
* @param taken Whether or not the branch was taken. * @param taken Whether or not the branch was taken.
*/ */
void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
bool squashed);
void retireSquashed(void *bp_history) void retireSquashed(ThreadID tid, void *bp_history)
{ assert(bp_history == NULL); } { assert(bp_history == NULL); }
void squash(void *bp_history) void squash(ThreadID tid, void *bp_history)
{ assert(bp_history == NULL); } { assert(bp_history == NULL); }
void reset(); void reset();

View file

@ -38,7 +38,7 @@
BiModeBP::BiModeBP(const BiModeBPParams *params) BiModeBP::BiModeBP(const BiModeBPParams *params)
: BPredUnit(params), : BPredUnit(params),
globalHistoryReg(0), globalHistoryReg(params->numThreads, 0),
globalHistoryBits(ceilLog2(params->globalPredictorSize)), globalHistoryBits(ceilLog2(params->globalPredictorSize)),
choicePredictorSize(params->choicePredictorSize), choicePredictorSize(params->choicePredictorSize),
choiceCtrBits(params->choiceCtrBits), choiceCtrBits(params->choiceCtrBits),
@ -77,23 +77,23 @@ BiModeBP::BiModeBP(const BiModeBPParams *params)
* chooses the taken array and the taken array predicts taken. * chooses the taken array and the taken array predicts taken.
*/ */
void void
BiModeBP::uncondBranch(Addr pc, void * &bpHistory) BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory)
{ {
BPHistory *history = new BPHistory; BPHistory *history = new BPHistory;
history->globalHistoryReg = globalHistoryReg; history->globalHistoryReg = globalHistoryReg[tid];
history->takenUsed = true; history->takenUsed = true;
history->takenPred = true; history->takenPred = true;
history->notTakenPred = true; history->notTakenPred = true;
history->finalPred = true; history->finalPred = true;
bpHistory = static_cast<void*>(history); bpHistory = static_cast<void*>(history);
updateGlobalHistReg(true); updateGlobalHistReg(tid, true);
} }
void void
BiModeBP::squash(void *bpHistory) BiModeBP::squash(ThreadID tid, void *bpHistory)
{ {
BPHistory *history = static_cast<BPHistory*>(bpHistory); BPHistory *history = static_cast<BPHistory*>(bpHistory);
globalHistoryReg = history->globalHistoryReg; globalHistoryReg[tid] = history->globalHistoryReg;
delete history; delete history;
} }
@ -108,12 +108,12 @@ BiModeBP::squash(void *bpHistory)
* direction predictors for the final branch prediction. * direction predictors for the final branch prediction.
*/ */
bool bool
BiModeBP::lookup(Addr branchAddr, void * &bpHistory) BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory)
{ {
unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt) unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
& choiceHistoryMask); & choiceHistoryMask);
unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt) unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
^ globalHistoryReg) ^ globalHistoryReg[tid])
& globalHistoryMask); & globalHistoryMask);
assert(choiceHistoryIdx < choicePredictorSize); assert(choiceHistoryIdx < choicePredictorSize);
@ -128,7 +128,7 @@ BiModeBP::lookup(Addr branchAddr, void * &bpHistory)
bool finalPrediction; bool finalPrediction;
BPHistory *history = new BPHistory; BPHistory *history = new BPHistory;
history->globalHistoryReg = globalHistoryReg; history->globalHistoryReg = globalHistoryReg[tid];
history->takenUsed = choicePrediction; history->takenUsed = choicePrediction;
history->takenPred = takenGHBPrediction; history->takenPred = takenGHBPrediction;
history->notTakenPred = notTakenGHBPrediction; history->notTakenPred = notTakenGHBPrediction;
@ -141,15 +141,15 @@ BiModeBP::lookup(Addr branchAddr, void * &bpHistory)
history->finalPred = finalPrediction; history->finalPred = finalPrediction;
bpHistory = static_cast<void*>(history); bpHistory = static_cast<void*>(history);
updateGlobalHistReg(finalPrediction); updateGlobalHistReg(tid, finalPrediction);
return finalPrediction; return finalPrediction;
} }
void void
BiModeBP::btbUpdate(Addr branchAddr, void * &bpHistory) BiModeBP::btbUpdate(ThreadID tid, Addr branchAddr, void * &bpHistory)
{ {
globalHistoryReg &= (historyRegisterMask & ~ULL(1)); globalHistoryReg[tid] &= (historyRegisterMask & ~ULL(1));
} }
/* Only the selected direction predictor will be updated with the final /* Only the selected direction predictor will be updated with the final
@ -159,7 +159,8 @@ BiModeBP::btbUpdate(Addr branchAddr, void * &bpHistory)
* the direction predictors makes a correct final prediction. * the direction predictors makes a correct final prediction.
*/ */
void void
BiModeBP::update(Addr branchAddr, bool taken, void *bpHistory, bool squashed) BiModeBP::update(ThreadID tid, Addr branchAddr, bool taken, void *bpHistory,
bool squashed)
{ {
if (bpHistory) { if (bpHistory) {
BPHistory *history = static_cast<BPHistory*>(bpHistory); BPHistory *history = static_cast<BPHistory*>(bpHistory);
@ -218,11 +219,11 @@ BiModeBP::update(Addr branchAddr, bool taken, void *bpHistory, bool squashed)
if (squashed) { if (squashed) {
if (taken) { if (taken) {
globalHistoryReg = (history->globalHistoryReg << 1) | 1; globalHistoryReg[tid] = (history->globalHistoryReg << 1) | 1;
} else { } else {
globalHistoryReg = (history->globalHistoryReg << 1); globalHistoryReg[tid] = (history->globalHistoryReg << 1);
} }
globalHistoryReg &= historyRegisterMask; globalHistoryReg[tid] &= historyRegisterMask;
} else { } else {
delete history; delete history;
} }
@ -230,24 +231,24 @@ BiModeBP::update(Addr branchAddr, bool taken, void *bpHistory, bool squashed)
} }
void void
BiModeBP::retireSquashed(void *bp_history) BiModeBP::retireSquashed(ThreadID tid, void *bp_history)
{ {
BPHistory *history = static_cast<BPHistory*>(bp_history); BPHistory *history = static_cast<BPHistory*>(bp_history);
delete history; delete history;
} }
unsigned unsigned
BiModeBP::getGHR(void *bp_history) const BiModeBP::getGHR(ThreadID tid, void *bp_history) const
{ {
return static_cast<BPHistory*>(bp_history)->globalHistoryReg; return static_cast<BPHistory*>(bp_history)->globalHistoryReg;
} }
void void
BiModeBP::updateGlobalHistReg(bool taken) BiModeBP::updateGlobalHistReg(ThreadID tid, bool taken)
{ {
globalHistoryReg = taken ? (globalHistoryReg << 1) | 1 : globalHistoryReg[tid] = taken ? (globalHistoryReg[tid] << 1) | 1 :
(globalHistoryReg << 1); (globalHistoryReg[tid] << 1);
globalHistoryReg &= historyRegisterMask; globalHistoryReg[tid] &= historyRegisterMask;
} }
BiModeBP* BiModeBP*

View file

@ -57,16 +57,17 @@ class BiModeBP : public BPredUnit
{ {
public: public:
BiModeBP(const BiModeBPParams *params); BiModeBP(const BiModeBPParams *params);
void uncondBranch(Addr pc, void * &bp_history); void uncondBranch(ThreadID tid, Addr pc, void * &bp_history);
void squash(void *bp_history); void squash(ThreadID tid, void *bp_history);
bool lookup(Addr branch_addr, void * &bp_history); bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history);
void btbUpdate(Addr branch_addr, void * &bp_history); void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history);
void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
void retireSquashed(void *bp_history); bool squashed);
unsigned getGHR(void *bp_history) const; void retireSquashed(ThreadID tid, void *bp_history);
unsigned getGHR(ThreadID tid, void *bp_history) const;
private: private:
void updateGlobalHistReg(bool taken); void updateGlobalHistReg(ThreadID tid, bool taken);
struct BPHistory { struct BPHistory {
unsigned globalHistoryReg; unsigned globalHistoryReg;
@ -95,7 +96,7 @@ class BiModeBP : public BPredUnit
// not-taken direction predictors // not-taken direction predictors
std::vector<SatCounter> notTakenCounters; std::vector<SatCounter> notTakenCounters;
unsigned globalHistoryReg; std::vector<unsigned> globalHistoryReg;
unsigned globalHistoryBits; unsigned globalHistoryBits;
unsigned historyRegisterMask; unsigned historyRegisterMask;

View file

@ -195,10 +195,10 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid); DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid);
pred_taken = true; pred_taken = true;
// Tell the BP there was an unconditional branch. // Tell the BP there was an unconditional branch.
uncondBranch(pc.instAddr(), bp_history); uncondBranch(tid, pc.instAddr(), bp_history);
} else { } else {
++condPredicted; ++condPredicted;
pred_taken = lookup(pc.instAddr(), bp_history); pred_taken = lookup(tid, pc.instAddr(), bp_history);
DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor" DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
" predicted %i for PC %s\n", tid, seqNum, pred_taken, pc); " predicted %i for PC %s\n", tid, seqNum, pred_taken, pc);
@ -265,7 +265,7 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
// because the BTB did not have an entry // because the BTB did not have an entry
// The predictor needs to be updated accordingly // The predictor needs to be updated accordingly
if (!inst->isCall() && !inst->isReturn()) { if (!inst->isCall() && !inst->isReturn()) {
btbUpdate(pc.instAddr(), bp_history); btbUpdate(tid, pc.instAddr(), bp_history);
DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate" DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
" called for %s\n", tid, seqNum, pc); " called for %s\n", tid, seqNum, pc);
} else if (inst->isCall() && !inst->isUncondCtrl()) { } else if (inst->isCall() && !inst->isUncondCtrl()) {
@ -278,8 +278,8 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
predict_record.wasIndirect = true; predict_record.wasIndirect = true;
++indirectLookups; ++indirectLookups;
//Consult indirect predictor on indirect control //Consult indirect predictor on indirect control
if (iPred.lookup(pc.instAddr(), getGHR(bp_history), target, if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history),
tid)) { target, tid)) {
// Indirect predictor hit // Indirect predictor hit
++indirectHits; ++indirectHits;
DPRINTF(Branch, "[tid:%i]: Instruction %s predicted " DPRINTF(Branch, "[tid:%i]: Instruction %s predicted "
@ -346,7 +346,7 @@ BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum,
DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid); DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid);
pred_taken = true; pred_taken = true;
// Tell the BP there was an unconditional branch. // Tell the BP there was an unconditional branch.
uncondBranch(instPC.instAddr(), bp_history); uncondBranch(tid, instPC.instAddr(), bp_history);
if (inst->isReturn() && RAS[tid].empty()) { if (inst->isReturn() && RAS[tid].empty()) {
DPRINTF(Branch, "[tid:%i] RAS is empty, predicting " DPRINTF(Branch, "[tid:%i] RAS is empty, predicting "
@ -356,7 +356,7 @@ BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum,
} else { } else {
++condPredicted; ++condPredicted;
pred_taken = lookup(predPC.instAddr(), bp_history); pred_taken = lookup(tid, predPC.instAddr(), bp_history);
} }
PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken, PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken,
@ -451,10 +451,11 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
predHist[tid].back().seqNum <= done_sn) { predHist[tid].back().seqNum <= done_sn) {
// Update the branch predictor with the correct results. // Update the branch predictor with the correct results.
if (!predHist[tid].back().wasSquashed) { if (!predHist[tid].back().wasSquashed) {
update(predHist[tid].back().pc, predHist[tid].back().predTaken, update(tid, predHist[tid].back().pc,
predHist[tid].back().bpHistory, false); predHist[tid].back().predTaken,
predHist[tid].back().bpHistory, false);
} else { } else {
retireSquashed(predHist[tid].back().bpHistory); retireSquashed(tid, predHist[tid].back().bpHistory);
} }
predHist[tid].pop_back(); predHist[tid].pop_back();
@ -485,7 +486,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
} }
// This call should delete the bpHistory. // This call should delete the bpHistory.
squash(pred_hist.front().bpHistory); squash(tid, pred_hist.front().bpHistory);
DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] " DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
"PC %s.\n", tid, pred_hist.front().seqNum, "PC %s.\n", tid, pred_hist.front().seqNum,
@ -550,9 +551,9 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
} }
// Have to get GHR here because the update deletes bpHistory // Have to get GHR here because the update deletes bpHistory
unsigned ghr = getGHR(hist_it->bpHistory); unsigned ghr = getGHR(tid, hist_it->bpHistory);
update((*hist_it).pc, actually_taken, update(tid, (*hist_it).pc, actually_taken,
pred_hist.front().bpHistory, true); pred_hist.front().bpHistory, true);
hist_it->wasSquashed = true; hist_it->wasSquashed = true;

View file

@ -98,7 +98,7 @@ class BPredUnit : public SimObject
TheISA::PCState &predPC, ThreadID tid); TheISA::PCState &predPC, ThreadID tid);
// @todo: Rename this function. // @todo: Rename this function.
virtual void uncondBranch(Addr pc, void * &bp_history) = 0; virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) = 0;
/** /**
* Tells the branch predictor to commit any updates until the given * Tells the branch predictor to commit any updates until the given
@ -133,7 +133,7 @@ class BPredUnit : public SimObject
* @param bp_history Pointer to the history object. The predictor * @param bp_history Pointer to the history object. The predictor
* will need to update any state and delete the object. * will need to update any state and delete the object.
*/ */
virtual void squash(void *bp_history) = 0; virtual void squash(ThreadID tid, void *bp_history) = 0;
/** /**
* Looks up a given PC in the BP to see if it is taken or not taken. * Looks up a given PC in the BP to see if it is taken or not taken.
@ -142,7 +142,7 @@ class BPredUnit : public SimObject
* has the branch predictor state associated with the lookup. * has the branch predictor state associated with the lookup.
* @return Whether the branch is taken or not taken. * @return Whether the branch is taken or not taken.
*/ */
virtual bool lookup(Addr instPC, void * &bp_history) = 0; virtual bool lookup(ThreadID tid, Addr instPC, void * &bp_history) = 0;
/** /**
* If a branch is not taken, because the BTB address is invalid or missing, * If a branch is not taken, because the BTB address is invalid or missing,
@ -152,7 +152,7 @@ class BPredUnit : public SimObject
* @param bp_history Pointer that will be set to an object that * @param bp_history Pointer that will be set to an object that
* has the branch predictor state associated with the lookup. * has the branch predictor state associated with the lookup.
*/ */
virtual void btbUpdate(Addr instPC, void * &bp_history) = 0; virtual void btbUpdate(ThreadID tid, Addr instPC, void * &bp_history) = 0;
/** /**
* Looks up a given PC in the BTB to see if a matching entry exists. * Looks up a given PC in the BTB to see if a matching entry exists.
@ -180,15 +180,15 @@ class BPredUnit : public SimObject
* squash operation. * squash operation.
* @todo Make this update flexible enough to handle a global predictor. * @todo Make this update flexible enough to handle a global predictor.
*/ */
virtual void update(Addr instPC, bool taken, void *bp_history, virtual void update(ThreadID tid, Addr instPC, bool taken,
bool squashed) = 0; void *bp_history, bool squashed) = 0;
/** /**
* Deletes the associated history with a branch, performs no predictor * Deletes the associated history with a branch, performs no predictor
* updates. Used for branches that mispredict and update tables but * updates. Used for branches that mispredict and update tables but
* are still speculative and later retire. * are still speculative and later retire.
* @param bp_history History to delete associated with this predictor * @param bp_history History to delete associated with this predictor
*/ */
virtual void retireSquashed(void *bp_history) = 0; virtual void retireSquashed(ThreadID tid, void *bp_history) = 0;
/** /**
* Updates the BTB with the target of a branch. * Updates the BTB with the target of a branch.
@ -199,7 +199,7 @@ class BPredUnit : public SimObject
{ BTB.update(instPC, target, 0); } { BTB.update(instPC, target, 0); }
virtual unsigned getGHR(void* bp_history) const { return 0; } virtual unsigned getGHR(ThreadID tid, void* bp_history) const { return 0; }
void dump(); void dump();

View file

@ -52,6 +52,7 @@ TournamentBP::TournamentBP(const TournamentBPParams *params)
localHistoryBits(ceilLog2(params->localPredictorSize)), localHistoryBits(ceilLog2(params->localPredictorSize)),
globalPredictorSize(params->globalPredictorSize), globalPredictorSize(params->globalPredictorSize),
globalCtrBits(params->globalCtrBits), globalCtrBits(params->globalCtrBits),
globalHistory(params->numThreads, 0),
globalHistoryBits( globalHistoryBits(
ceilLog2(params->globalPredictorSize) > ceilLog2(params->globalPredictorSize) >
ceilLog2(params->choicePredictorSize) ? ceilLog2(params->choicePredictorSize) ?
@ -92,8 +93,6 @@ TournamentBP::TournamentBP(const TournamentBPParams *params)
for (int i = 0; i < globalPredictorSize; ++i) for (int i = 0; i < globalPredictorSize; ++i)
globalCtrs[i].setBits(globalCtrBits); globalCtrs[i].setBits(globalCtrBits);
//Clear the global history
globalHistory = 0;
// Set up the global history mask // Set up the global history mask
// this is equivalent to mask(log2(globalPredictorSize) // this is equivalent to mask(log2(globalPredictorSize)
globalHistoryMask = globalPredictorSize - 1; globalHistoryMask = globalPredictorSize - 1;
@ -145,18 +144,18 @@ TournamentBP::calcLocHistIdx(Addr &branch_addr)
inline inline
void void
TournamentBP::updateGlobalHistTaken() TournamentBP::updateGlobalHistTaken(ThreadID tid)
{ {
globalHistory = (globalHistory << 1) | 1; globalHistory[tid] = (globalHistory[tid] << 1) | 1;
globalHistory = globalHistory & historyRegisterMask; globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
} }
inline inline
void void
TournamentBP::updateGlobalHistNotTaken() TournamentBP::updateGlobalHistNotTaken(ThreadID tid)
{ {
globalHistory = (globalHistory << 1); globalHistory[tid] = (globalHistory[tid] << 1);
globalHistory = globalHistory & historyRegisterMask; globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
} }
inline inline
@ -177,18 +176,18 @@ TournamentBP::updateLocalHistNotTaken(unsigned local_history_idx)
void void
TournamentBP::btbUpdate(Addr branch_addr, void * &bp_history) TournamentBP::btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history)
{ {
unsigned local_history_idx = calcLocHistIdx(branch_addr); unsigned local_history_idx = calcLocHistIdx(branch_addr);
//Update Global History to Not Taken (clear LSB) //Update Global History to Not Taken (clear LSB)
globalHistory &= (historyRegisterMask & ~ULL(1)); globalHistory[tid] &= (historyRegisterMask & ~ULL(1));
//Update Local History to Not Taken //Update Local History to Not Taken
localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] =
localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1)); localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1));
} }
bool bool
TournamentBP::lookup(Addr branch_addr, void * &bp_history) TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history)
{ {
bool local_prediction; bool local_prediction;
unsigned local_history_idx; unsigned local_history_idx;
@ -204,16 +203,16 @@ TournamentBP::lookup(Addr branch_addr, void * &bp_history)
local_prediction = localCtrs[local_predictor_idx].read() > localThreshold; local_prediction = localCtrs[local_predictor_idx].read() > localThreshold;
//Lookup in the global predictor to get its branch prediction //Lookup in the global predictor to get its branch prediction
global_prediction = global_prediction = globalThreshold <
globalCtrs[globalHistory & globalHistoryMask].read() > globalThreshold; globalCtrs[globalHistory[tid] & globalHistoryMask].read();
//Lookup in the choice predictor to see which one to use //Lookup in the choice predictor to see which one to use
choice_prediction = choice_prediction = choiceThreshold <
choiceCtrs[globalHistory & choiceHistoryMask].read() > choiceThreshold; choiceCtrs[globalHistory[tid] & choiceHistoryMask].read();
// Create BPHistory and pass it back to be recorded. // Create BPHistory and pass it back to be recorded.
BPHistory *history = new BPHistory; BPHistory *history = new BPHistory;
history->globalHistory = globalHistory; history->globalHistory = globalHistory[tid];
history->localPredTaken = local_prediction; history->localPredTaken = local_prediction;
history->globalPredTaken = global_prediction; history->globalPredTaken = global_prediction;
history->globalUsed = choice_prediction; history->globalUsed = choice_prediction;
@ -227,21 +226,21 @@ TournamentBP::lookup(Addr branch_addr, void * &bp_history)
// all histories. // all histories.
if (choice_prediction) { if (choice_prediction) {
if (global_prediction) { if (global_prediction) {
updateGlobalHistTaken(); updateGlobalHistTaken(tid);
updateLocalHistTaken(local_history_idx); updateLocalHistTaken(local_history_idx);
return true; return true;
} else { } else {
updateGlobalHistNotTaken(); updateGlobalHistNotTaken(tid);
updateLocalHistNotTaken(local_history_idx); updateLocalHistNotTaken(local_history_idx);
return false; return false;
} }
} else { } else {
if (local_prediction) { if (local_prediction) {
updateGlobalHistTaken(); updateGlobalHistTaken(tid);
updateLocalHistTaken(local_history_idx); updateLocalHistTaken(local_history_idx);
return true; return true;
} else { } else {
updateGlobalHistNotTaken(); updateGlobalHistNotTaken(tid);
updateLocalHistNotTaken(local_history_idx); updateLocalHistNotTaken(local_history_idx);
return false; return false;
} }
@ -249,11 +248,11 @@ TournamentBP::lookup(Addr branch_addr, void * &bp_history)
} }
void void
TournamentBP::uncondBranch(Addr pc, void * &bp_history) TournamentBP::uncondBranch(ThreadID tid, Addr pc, void * &bp_history)
{ {
// Create BPHistory and pass it back to be recorded. // Create BPHistory and pass it back to be recorded.
BPHistory *history = new BPHistory; BPHistory *history = new BPHistory;
history->globalHistory = globalHistory; history->globalHistory = globalHistory[tid];
history->localPredTaken = true; history->localPredTaken = true;
history->globalPredTaken = true; history->globalPredTaken = true;
history->globalUsed = true; history->globalUsed = true;
@ -261,12 +260,12 @@ TournamentBP::uncondBranch(Addr pc, void * &bp_history)
history->localHistory = invalidPredictorIndex; history->localHistory = invalidPredictorIndex;
bp_history = static_cast<void *>(history); bp_history = static_cast<void *>(history);
updateGlobalHistTaken(); updateGlobalHistTaken(tid);
} }
void void
TournamentBP::update(Addr branch_addr, bool taken, void *bp_history, TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken,
bool squashed) void *bp_history, bool squashed)
{ {
unsigned local_history_idx; unsigned local_history_idx;
unsigned local_predictor_idx M5_VAR_USED; unsigned local_predictor_idx M5_VAR_USED;
@ -332,15 +331,15 @@ TournamentBP::update(Addr branch_addr, bool taken, void *bp_history,
} }
if (squashed) { if (squashed) {
if (taken) { if (taken) {
globalHistory = (history->globalHistory << 1) | 1; globalHistory[tid] = (history->globalHistory << 1) | 1;
globalHistory = globalHistory & historyRegisterMask; globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
if (old_local_pred_valid) { if (old_local_pred_valid) {
localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] =
(history->localHistory << 1) | 1; (history->localHistory << 1) | 1;
} }
} else { } else {
globalHistory = (history->globalHistory << 1); globalHistory[tid] = (history->globalHistory << 1);
globalHistory = globalHistory & historyRegisterMask; globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
if (old_local_pred_valid) { if (old_local_pred_valid) {
localHistoryTable[local_history_idx] = localHistoryTable[local_history_idx] =
history->localHistory << 1; history->localHistory << 1;
@ -359,19 +358,19 @@ TournamentBP::update(Addr branch_addr, bool taken, void *bp_history,
} }
void void
TournamentBP::retireSquashed(void *bp_history) TournamentBP::retireSquashed(ThreadID tid, void *bp_history)
{ {
BPHistory *history = static_cast<BPHistory *>(bp_history); BPHistory *history = static_cast<BPHistory *>(bp_history);
delete history; delete history;
} }
void void
TournamentBP::squash(void *bp_history) TournamentBP::squash(ThreadID tid, void *bp_history)
{ {
BPHistory *history = static_cast<BPHistory *>(bp_history); BPHistory *history = static_cast<BPHistory *>(bp_history);
// Restore global history to state prior to this branch. // Restore global history to state prior to this branch.
globalHistory = history->globalHistory; globalHistory[tid] = history->globalHistory;
// Restore local history // Restore local history
if (history->localHistoryIdx != invalidPredictorIndex) { if (history->localHistoryIdx != invalidPredictorIndex) {
@ -389,7 +388,7 @@ TournamentBPParams::create()
} }
unsigned unsigned
TournamentBP::getGHR(void *bp_history) const TournamentBP::getGHR(ThreadID tid, void *bp_history) const
{ {
return static_cast<BPHistory *>(bp_history)->globalHistory; return static_cast<BPHistory *>(bp_history)->globalHistory;
} }

View file

@ -77,7 +77,7 @@ class TournamentBP : public BPredUnit
* @param bp_history Pointer that will be set to the BPHistory object. * @param bp_history Pointer that will be set to the BPHistory object.
* @return Whether or not the branch is taken. * @return Whether or not the branch is taken.
*/ */
bool lookup(Addr branch_addr, void * &bp_history); bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history);
/** /**
* Records that there was an unconditional branch, and modifies * Records that there was an unconditional branch, and modifies
@ -85,7 +85,7 @@ class TournamentBP : public BPredUnit
* global history stored in it. * global history stored in it.
* @param bp_history Pointer that will be set to the BPHistory object. * @param bp_history Pointer that will be set to the BPHistory object.
*/ */
void uncondBranch(Addr pc, void * &bp_history); void uncondBranch(ThreadID tid, Addr pc, void * &bp_history);
/** /**
* Updates the branch predictor to Not Taken if a BTB entry is * Updates the branch predictor to Not Taken if a BTB entry is
* invalid or not found. * invalid or not found.
@ -93,7 +93,7 @@ class TournamentBP : public BPredUnit
* @param bp_history Pointer to any bp history state. * @param bp_history Pointer to any bp history state.
* @return Whether or not the branch is taken. * @return Whether or not the branch is taken.
*/ */
void btbUpdate(Addr branch_addr, void * &bp_history); void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history);
/** /**
* Updates the branch predictor with the actual result of a branch. * Updates the branch predictor with the actual result of a branch.
* @param branch_addr The address of the branch to update. * @param branch_addr The address of the branch to update.
@ -103,21 +103,19 @@ class TournamentBP : public BPredUnit
* @param squashed is set when this function is called during a squash * @param squashed is set when this function is called during a squash
* operation. * operation.
*/ */
void update(Addr branch_addr, bool taken, void *bp_history, bool squashed); void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
bool squashed);
void retireSquashed(void *bp_history); void retireSquashed(ThreadID tid, void *bp_history);
/** /**
* Restores the global branch history on a squash. * Restores the global branch history on a squash.
* @param bp_history Pointer to the BPHistory object that has the * @param bp_history Pointer to the BPHistory object that has the
* previous global branch history in it. * previous global branch history in it.
*/ */
void squash(void *bp_history); void squash(ThreadID tid, void *bp_history);
unsigned getGHR(void *bp_history) const; unsigned getGHR(ThreadID tid, void *bp_history) const;
/** Returns the global history. */
inline unsigned readGlobalHist() { return globalHistory; }
private: private:
/** /**
@ -134,10 +132,10 @@ class TournamentBP : public BPredUnit
inline unsigned calcLocHistIdx(Addr &branch_addr); inline unsigned calcLocHistIdx(Addr &branch_addr);
/** Updates global history as taken. */ /** Updates global history as taken. */
inline void updateGlobalHistTaken(); inline void updateGlobalHistTaken(ThreadID tid);
/** Updates global history as not taken. */ /** Updates global history as not taken. */
inline void updateGlobalHistNotTaken(); inline void updateGlobalHistNotTaken(ThreadID tid);
/** /**
* Updates local histories as taken. * Updates local histories as taken.
@ -211,7 +209,7 @@ class TournamentBP : public BPredUnit
/** Global history register. Contains as much history as specified by /** Global history register. Contains as much history as specified by
* globalHistoryBits. Actual number of bits used is determined by * globalHistoryBits. Actual number of bits used is determined by
* globalHistoryMask and choiceHistoryMask. */ * globalHistoryMask and choiceHistoryMask. */
unsigned globalHistory; std::vector<unsigned> globalHistory;
/** Number of bits for the global history. Determines maximum number of /** Number of bits for the global history. Determines maximum number of
entries in global and choice predictor tables. */ entries in global and choice predictor tables. */