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:
parent
0fd4bb7f12
commit
d99deff8ea
8 changed files with 110 additions and 108 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
Loading…
Reference in a new issue