}
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
// a BTB entry is invalid or not found.
bool
-LocalBP::lookup(Addr branch_addr, void * &bp_history)
+LocalBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history)
{
bool taken;
uint8_t counter_val;
}
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);
unsigned local_predictor_idx;
}
void
-LocalBP::uncondBranch(Addr pc, void *&bp_history)
+LocalBP::uncondBranch(ThreadID tid, Addr pc, void *&bp_history)
{
}
*/
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
* @param bp_history Pointer to any bp history state.
* @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
* @param bp_history Pointer to any bp history state.
* @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.
* @param branch_addr The address of the branch to update.
* @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); }
- void squash(void *bp_history)
+ void squash(ThreadID tid, void *bp_history)
{ assert(bp_history == NULL); }
void reset();
BiModeBP::BiModeBP(const BiModeBPParams *params)
: BPredUnit(params),
- globalHistoryReg(0),
+ globalHistoryReg(params->numThreads, 0),
globalHistoryBits(ceilLog2(params->globalPredictorSize)),
choicePredictorSize(params->choicePredictorSize),
choiceCtrBits(params->choiceCtrBits),
* chooses the taken array and the taken array predicts taken.
*/
void
-BiModeBP::uncondBranch(Addr pc, void * &bpHistory)
+BiModeBP::uncondBranch(ThreadID tid, Addr pc, void * &bpHistory)
{
BPHistory *history = new BPHistory;
- history->globalHistoryReg = globalHistoryReg;
+ history->globalHistoryReg = globalHistoryReg[tid];
history->takenUsed = true;
history->takenPred = true;
history->notTakenPred = true;
history->finalPred = true;
bpHistory = static_cast<void*>(history);
- updateGlobalHistReg(true);
+ updateGlobalHistReg(tid, true);
}
void
-BiModeBP::squash(void *bpHistory)
+BiModeBP::squash(ThreadID tid, void *bpHistory)
{
BPHistory *history = static_cast<BPHistory*>(bpHistory);
- globalHistoryReg = history->globalHistoryReg;
+ globalHistoryReg[tid] = history->globalHistoryReg;
delete history;
}
* direction predictors for the final branch prediction.
*/
bool
-BiModeBP::lookup(Addr branchAddr, void * &bpHistory)
+BiModeBP::lookup(ThreadID tid, Addr branchAddr, void * &bpHistory)
{
unsigned choiceHistoryIdx = ((branchAddr >> instShiftAmt)
& choiceHistoryMask);
unsigned globalHistoryIdx = (((branchAddr >> instShiftAmt)
- ^ globalHistoryReg)
+ ^ globalHistoryReg[tid])
& globalHistoryMask);
assert(choiceHistoryIdx < choicePredictorSize);
bool finalPrediction;
BPHistory *history = new BPHistory;
- history->globalHistoryReg = globalHistoryReg;
+ history->globalHistoryReg = globalHistoryReg[tid];
history->takenUsed = choicePrediction;
history->takenPred = takenGHBPrediction;
history->notTakenPred = notTakenGHBPrediction;
history->finalPred = finalPrediction;
bpHistory = static_cast<void*>(history);
- updateGlobalHistReg(finalPrediction);
+ updateGlobalHistReg(tid, finalPrediction);
return finalPrediction;
}
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
* the direction predictors makes a correct final prediction.
*/
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) {
BPHistory *history = static_cast<BPHistory*>(bpHistory);
if (squashed) {
if (taken) {
- globalHistoryReg = (history->globalHistoryReg << 1) | 1;
+ globalHistoryReg[tid] = (history->globalHistoryReg << 1) | 1;
} else {
- globalHistoryReg = (history->globalHistoryReg << 1);
+ globalHistoryReg[tid] = (history->globalHistoryReg << 1);
}
- globalHistoryReg &= historyRegisterMask;
+ globalHistoryReg[tid] &= historyRegisterMask;
} else {
delete history;
}
}
void
-BiModeBP::retireSquashed(void *bp_history)
+BiModeBP::retireSquashed(ThreadID tid, void *bp_history)
{
BPHistory *history = static_cast<BPHistory*>(bp_history);
delete history;
}
unsigned
-BiModeBP::getGHR(void *bp_history) const
+BiModeBP::getGHR(ThreadID tid, void *bp_history) const
{
return static_cast<BPHistory*>(bp_history)->globalHistoryReg;
}
void
-BiModeBP::updateGlobalHistReg(bool taken)
+BiModeBP::updateGlobalHistReg(ThreadID tid, bool taken)
{
- globalHistoryReg = taken ? (globalHistoryReg << 1) | 1 :
- (globalHistoryReg << 1);
- globalHistoryReg &= historyRegisterMask;
+ globalHistoryReg[tid] = taken ? (globalHistoryReg[tid] << 1) | 1 :
+ (globalHistoryReg[tid] << 1);
+ globalHistoryReg[tid] &= historyRegisterMask;
}
BiModeBP*
{
public:
BiModeBP(const BiModeBPParams *params);
- void uncondBranch(Addr pc, void * &bp_history);
- void squash(void *bp_history);
- bool lookup(Addr branch_addr, void * &bp_history);
- void btbUpdate(Addr branch_addr, void * &bp_history);
- void update(Addr branch_addr, bool taken, void *bp_history, bool squashed);
- void retireSquashed(void *bp_history);
- unsigned getGHR(void *bp_history) const;
+ void uncondBranch(ThreadID tid, Addr pc, void * &bp_history);
+ void squash(ThreadID tid, void *bp_history);
+ bool lookup(ThreadID tid, Addr branch_addr, void * &bp_history);
+ void btbUpdate(ThreadID tid, Addr branch_addr, void * &bp_history);
+ void update(ThreadID tid, Addr branch_addr, bool taken, void *bp_history,
+ bool squashed);
+ void retireSquashed(ThreadID tid, void *bp_history);
+ unsigned getGHR(ThreadID tid, void *bp_history) const;
private:
- void updateGlobalHistReg(bool taken);
+ void updateGlobalHistReg(ThreadID tid, bool taken);
struct BPHistory {
unsigned globalHistoryReg;
// not-taken direction predictors
std::vector<SatCounter> notTakenCounters;
- unsigned globalHistoryReg;
+ std::vector<unsigned> globalHistoryReg;
unsigned globalHistoryBits;
unsigned historyRegisterMask;
DPRINTF(Branch, "[tid:%i]: Unconditional control.\n", tid);
pred_taken = true;
// Tell the BP there was an unconditional branch.
- uncondBranch(pc.instAddr(), bp_history);
+ uncondBranch(tid, pc.instAddr(), bp_history);
} else {
++condPredicted;
- pred_taken = lookup(pc.instAddr(), bp_history);
+ pred_taken = lookup(tid, pc.instAddr(), bp_history);
DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
" predicted %i for PC %s\n", tid, seqNum, pred_taken, pc);
// because the BTB did not have an entry
// The predictor needs to be updated accordingly
if (!inst->isCall() && !inst->isReturn()) {
- btbUpdate(pc.instAddr(), bp_history);
+ btbUpdate(tid, pc.instAddr(), bp_history);
DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
" called for %s\n", tid, seqNum, pc);
} else if (inst->isCall() && !inst->isUncondCtrl()) {
predict_record.wasIndirect = true;
++indirectLookups;
//Consult indirect predictor on indirect control
- if (iPred.lookup(pc.instAddr(), getGHR(bp_history), target,
- tid)) {
+ if (iPred.lookup(pc.instAddr(), getGHR(tid, bp_history),
+ target, tid)) {
// Indirect predictor hit
++indirectHits;
DPRINTF(Branch, "[tid:%i]: Instruction %s predicted "
DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid);
pred_taken = true;
// 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()) {
DPRINTF(Branch, "[tid:%i] RAS is empty, predicting "
} else {
++condPredicted;
- pred_taken = lookup(predPC.instAddr(), bp_history);
+ pred_taken = lookup(tid, predPC.instAddr(), bp_history);
}
PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken,
predHist[tid].back().seqNum <= done_sn) {
// Update the branch predictor with the correct results.
if (!predHist[tid].back().wasSquashed) {
- update(predHist[tid].back().pc, predHist[tid].back().predTaken,
- predHist[tid].back().bpHistory, false);
+ update(tid, predHist[tid].back().pc,
+ predHist[tid].back().predTaken,
+ predHist[tid].back().bpHistory, false);
} else {
- retireSquashed(predHist[tid].back().bpHistory);
+ retireSquashed(tid, predHist[tid].back().bpHistory);
}
predHist[tid].pop_back();
}
// 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] "
"PC %s.\n", tid, pred_hist.front().seqNum,
}
// 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);
hist_it->wasSquashed = true;
TheISA::PCState &predPC, ThreadID tid);
// @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
* @param bp_history Pointer to the history object. The predictor
* 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.
* has the branch predictor state associated with the lookup.
* @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,
* @param bp_history Pointer that will be set to an object that
* 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.
* squash operation.
* @todo Make this update flexible enough to handle a global predictor.
*/
- virtual void update(Addr instPC, bool taken, void *bp_history,
- bool squashed) = 0;
+ virtual void update(ThreadID tid, Addr instPC, bool taken,
+ void *bp_history, bool squashed) = 0;
/**
* Deletes the associated history with a branch, performs no predictor
* updates. Used for branches that mispredict and update tables but
* are still speculative and later retire.
* @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.
{ 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();
localHistoryBits(ceilLog2(params->localPredictorSize)),
globalPredictorSize(params->globalPredictorSize),
globalCtrBits(params->globalCtrBits),
+ globalHistory(params->numThreads, 0),
globalHistoryBits(
ceilLog2(params->globalPredictorSize) >
ceilLog2(params->choicePredictorSize) ?
for (int i = 0; i < globalPredictorSize; ++i)
globalCtrs[i].setBits(globalCtrBits);
- //Clear the global history
- globalHistory = 0;
// Set up the global history mask
// this is equivalent to mask(log2(globalPredictorSize)
globalHistoryMask = globalPredictorSize - 1;
inline
void
-TournamentBP::updateGlobalHistTaken()
+TournamentBP::updateGlobalHistTaken(ThreadID tid)
{
- globalHistory = (globalHistory << 1) | 1;
- globalHistory = globalHistory & historyRegisterMask;
+ globalHistory[tid] = (globalHistory[tid] << 1) | 1;
+ globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
}
inline
void
-TournamentBP::updateGlobalHistNotTaken()
+TournamentBP::updateGlobalHistNotTaken(ThreadID tid)
{
- globalHistory = (globalHistory << 1);
- globalHistory = globalHistory & historyRegisterMask;
+ globalHistory[tid] = (globalHistory[tid] << 1);
+ globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
}
inline
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);
//Update Global History to Not Taken (clear LSB)
- globalHistory &= (historyRegisterMask & ~ULL(1));
+ globalHistory[tid] &= (historyRegisterMask & ~ULL(1));
//Update Local History to Not Taken
localHistoryTable[local_history_idx] =
localHistoryTable[local_history_idx] & (localPredictorMask & ~ULL(1));
}
bool
-TournamentBP::lookup(Addr branch_addr, void * &bp_history)
+TournamentBP::lookup(ThreadID tid, Addr branch_addr, void * &bp_history)
{
bool local_prediction;
unsigned local_history_idx;
local_prediction = localCtrs[local_predictor_idx].read() > localThreshold;
//Lookup in the global predictor to get its branch prediction
- global_prediction =
- globalCtrs[globalHistory & globalHistoryMask].read() > globalThreshold;
+ global_prediction = globalThreshold <
+ globalCtrs[globalHistory[tid] & globalHistoryMask].read();
//Lookup in the choice predictor to see which one to use
- choice_prediction =
- choiceCtrs[globalHistory & choiceHistoryMask].read() > choiceThreshold;
+ choice_prediction = choiceThreshold <
+ choiceCtrs[globalHistory[tid] & choiceHistoryMask].read();
// Create BPHistory and pass it back to be recorded.
BPHistory *history = new BPHistory;
- history->globalHistory = globalHistory;
+ history->globalHistory = globalHistory[tid];
history->localPredTaken = local_prediction;
history->globalPredTaken = global_prediction;
history->globalUsed = choice_prediction;
// all histories.
if (choice_prediction) {
if (global_prediction) {
- updateGlobalHistTaken();
+ updateGlobalHistTaken(tid);
updateLocalHistTaken(local_history_idx);
return true;
} else {
- updateGlobalHistNotTaken();
+ updateGlobalHistNotTaken(tid);
updateLocalHistNotTaken(local_history_idx);
return false;
}
} else {
if (local_prediction) {
- updateGlobalHistTaken();
+ updateGlobalHistTaken(tid);
updateLocalHistTaken(local_history_idx);
return true;
} else {
- updateGlobalHistNotTaken();
+ updateGlobalHistNotTaken(tid);
updateLocalHistNotTaken(local_history_idx);
return false;
}
}
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.
BPHistory *history = new BPHistory;
- history->globalHistory = globalHistory;
+ history->globalHistory = globalHistory[tid];
history->localPredTaken = true;
history->globalPredTaken = true;
history->globalUsed = true;
history->localHistory = invalidPredictorIndex;
bp_history = static_cast<void *>(history);
- updateGlobalHistTaken();
+ updateGlobalHistTaken(tid);
}
void
-TournamentBP::update(Addr branch_addr, bool taken, void *bp_history,
- bool squashed)
+TournamentBP::update(ThreadID tid, Addr branch_addr, bool taken,
+ void *bp_history, bool squashed)
{
unsigned local_history_idx;
unsigned local_predictor_idx M5_VAR_USED;
}
if (squashed) {
if (taken) {
- globalHistory = (history->globalHistory << 1) | 1;
- globalHistory = globalHistory & historyRegisterMask;
+ globalHistory[tid] = (history->globalHistory << 1) | 1;
+ globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
if (old_local_pred_valid) {
localHistoryTable[local_history_idx] =
(history->localHistory << 1) | 1;
}
} else {
- globalHistory = (history->globalHistory << 1);
- globalHistory = globalHistory & historyRegisterMask;
+ globalHistory[tid] = (history->globalHistory << 1);
+ globalHistory[tid] = globalHistory[tid] & historyRegisterMask;
if (old_local_pred_valid) {
localHistoryTable[local_history_idx] =
history->localHistory << 1;
}
void
-TournamentBP::retireSquashed(void *bp_history)
+TournamentBP::retireSquashed(ThreadID tid, void *bp_history)
{
BPHistory *history = static_cast<BPHistory *>(bp_history);
delete history;
}
void
-TournamentBP::squash(void *bp_history)
+TournamentBP::squash(ThreadID tid, void *bp_history)
{
BPHistory *history = static_cast<BPHistory *>(bp_history);
// Restore global history to state prior to this branch.
- globalHistory = history->globalHistory;
+ globalHistory[tid] = history->globalHistory;
// Restore local history
if (history->localHistoryIdx != invalidPredictorIndex) {
}
unsigned
-TournamentBP::getGHR(void *bp_history) const
+TournamentBP::getGHR(ThreadID tid, void *bp_history) const
{
return static_cast<BPHistory *>(bp_history)->globalHistory;
}
* @param bp_history Pointer that will be set to the BPHistory object.
* @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
* global history stored in it.
* @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
* invalid or not found.
* @param bp_history Pointer to any bp history state.
* @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.
* @param branch_addr The address of the branch to update.
* @param squashed is set when this function is called during a squash
* 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.
* @param bp_history Pointer to the BPHistory object that has the
* previous global branch history in it.
*/
- void squash(void *bp_history);
+ void squash(ThreadID tid, void *bp_history);
- unsigned getGHR(void *bp_history) const;
-
- /** Returns the global history. */
- inline unsigned readGlobalHist() { return globalHistory; }
+ unsigned getGHR(ThreadID tid, void *bp_history) const;
private:
/**
inline unsigned calcLocHistIdx(Addr &branch_addr);
/** Updates global history as taken. */
- inline void updateGlobalHistTaken();
+ inline void updateGlobalHistTaken(ThreadID tid);
/** Updates global history as not taken. */
- inline void updateGlobalHistNotTaken();
+ inline void updateGlobalHistNotTaken(ThreadID tid);
/**
* Updates local histories as taken.
/** Global history register. Contains as much history as specified by
* globalHistoryBits. Actual number of bits used is determined by
* globalHistoryMask and choiceHistoryMask. */
- unsigned globalHistory;
+ std::vector<unsigned> globalHistory;
/** Number of bits for the global history. Determines maximum number of
entries in global and choice predictor tables. */