cpu: Use PCStateBase in the branch predictors.
Use PCStateBase instead of TheISA::PCState in the branch predictors. Change-Id: I0b0867bc09b6191a54d7658813c0b9656c436811 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/52055 Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Reviewed-by: Earl Ou <shunhsingou@google.com> Maintainer: Gabe Black <gabe.black@gmail.com> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
@@ -156,7 +156,7 @@ Fetch2::updateBranchPrediction(const BranchData &branch)
|
||||
/* Unpredicted branch or barrier */
|
||||
DPRINTF(Branch, "Unpredicted branch seen inst: %s\n", *inst);
|
||||
branchPredictor.squash(inst->id.fetchSeqNum,
|
||||
branch.target->as<TheISA::PCState>(), true, inst->id.threadId);
|
||||
*branch.target, true, inst->id.threadId);
|
||||
// Update after squashing to accomodate O3CPU
|
||||
// using the branch prediction code.
|
||||
branchPredictor.update(inst->id.fetchSeqNum,
|
||||
@@ -172,8 +172,7 @@ Fetch2::updateBranchPrediction(const BranchData &branch)
|
||||
/* Predicted taken, not taken */
|
||||
DPRINTF(Branch, "Branch mis-predicted inst: %s\n", *inst);
|
||||
branchPredictor.squash(inst->id.fetchSeqNum,
|
||||
branch.target->as<TheISA::PCState>() /* Not used */,
|
||||
false, inst->id.threadId);
|
||||
*branch.target /* Not used */, false, inst->id.threadId);
|
||||
// Update after squashing to accomodate O3CPU
|
||||
// using the branch prediction code.
|
||||
branchPredictor.update(inst->id.fetchSeqNum,
|
||||
@@ -184,7 +183,7 @@ Fetch2::updateBranchPrediction(const BranchData &branch)
|
||||
DPRINTF(Branch, "Branch mis-predicted target inst: %s target: %s\n",
|
||||
*inst, *branch.target);
|
||||
branchPredictor.squash(inst->id.fetchSeqNum,
|
||||
branch.target->as<TheISA::PCState>(), true, inst->id.threadId);
|
||||
*branch.target, true, inst->id.threadId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -206,8 +205,7 @@ Fetch2::predictBranch(MinorDynInstPtr inst, BranchData &branch)
|
||||
DPRINTF(Branch, "Trying to predict for inst: %s\n", *inst);
|
||||
|
||||
if (branchPredictor.predict(inst->staticInst,
|
||||
inst->id.fetchSeqNum, inst_pc->as<TheISA::PCState>(),
|
||||
inst->id.threadId)) {
|
||||
inst->id.fetchSeqNum, *inst_pc, inst->id.threadId)) {
|
||||
set(branch.target, *inst_pc);
|
||||
inst->predictedTaken = true;
|
||||
set(inst->predictedTarget, inst_pc);
|
||||
|
||||
@@ -524,7 +524,7 @@ Fetch::lookupAndUpdateNextPC(const DynInstPtr &inst, PCStateBase &next_pc)
|
||||
|
||||
ThreadID tid = inst->threadNumber;
|
||||
predict_taken = branchPred->predict(inst->staticInst, inst->seqNum,
|
||||
next_pc.as<TheISA::PCState>(), tid);
|
||||
next_pc, tid);
|
||||
|
||||
if (predict_taken) {
|
||||
DPRINTF(Fetch, "[tid:%i] [sn:%llu] Branch at PC %#x "
|
||||
@@ -968,7 +968,7 @@ Fetch::checkSignalsAndUpdate(ThreadID tid)
|
||||
if (fromCommit->commitInfo[tid].mispredictInst &&
|
||||
fromCommit->commitInfo[tid].mispredictInst->isControl()) {
|
||||
branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum,
|
||||
fromCommit->commitInfo[tid].pc->as<TheISA::PCState>(),
|
||||
*fromCommit->commitInfo[tid].pc,
|
||||
fromCommit->commitInfo[tid].branchTaken, tid);
|
||||
} else {
|
||||
branchPred->squash(fromCommit->commitInfo[tid].doneSeqNum,
|
||||
@@ -990,7 +990,7 @@ Fetch::checkSignalsAndUpdate(ThreadID tid)
|
||||
// Update the branch predictor.
|
||||
if (fromDecode->decodeInfo[tid].branchMispredict) {
|
||||
branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum,
|
||||
fromDecode->decodeInfo[tid].nextPC->as<TheISA::PCState>(),
|
||||
*fromDecode->decodeInfo[tid].nextPC,
|
||||
fromDecode->decodeInfo[tid].branchTaken, tid);
|
||||
} else {
|
||||
branchPred->squash(fromDecode->decodeInfo[tid].doneSeqNum,
|
||||
|
||||
@@ -129,7 +129,7 @@ BPredUnit::drainSanityCheck() const
|
||||
|
||||
bool
|
||||
BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
TheISA::PCState &pc, ThreadID tid)
|
||||
PCStateBase &pc, ThreadID tid)
|
||||
{
|
||||
// See if branch predictor predicts taken.
|
||||
// If so, get its target addr either from the BTB or the RAS.
|
||||
@@ -137,7 +137,7 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
// up once it's done.
|
||||
|
||||
bool pred_taken = false;
|
||||
TheISA::PCState target = pc;
|
||||
std::unique_ptr<PCStateBase> target(pc.clone());
|
||||
|
||||
++stats.lookups;
|
||||
ppBranches->notify(1);
|
||||
@@ -179,19 +179,20 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
predict_record.wasReturn = true;
|
||||
// If it's a function return call, then look up the address
|
||||
// in the RAS.
|
||||
TheISA::PCState rasTop = RAS[tid].top();
|
||||
target = inst->buildRetPC(pc, rasTop)->as<TheISA::PCState>();
|
||||
const PCStateBase *ras_top = RAS[tid].top();
|
||||
if (ras_top)
|
||||
set(target, inst->buildRetPC(pc, *ras_top));
|
||||
|
||||
// Record the top entry of the RAS, and its index.
|
||||
predict_record.usedRAS = true;
|
||||
predict_record.RASIndex = RAS[tid].topIdx();
|
||||
predict_record.RASTarget = rasTop;
|
||||
set(predict_record.RASTarget, ras_top);
|
||||
|
||||
RAS[tid].pop();
|
||||
|
||||
DPRINTF(Branch, "[tid:%i] [sn:%llu] Instruction %s is a return, "
|
||||
"RAS predicted target: %s, RAS index: %i\n",
|
||||
tid, seqNum, pc, target, predict_record.RASIndex);
|
||||
tid, seqNum, pc, *target, predict_record.RASIndex);
|
||||
} else {
|
||||
|
||||
if (inst->isCall()) {
|
||||
@@ -214,14 +215,14 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
if (BTB.valid(pc.instAddr(), tid)) {
|
||||
++stats.BTBHits;
|
||||
// If it's not a return, use the BTB to get target addr.
|
||||
target = BTB.lookup(pc.instAddr(), tid);
|
||||
set(target, BTB.lookup(pc.instAddr(), tid));
|
||||
DPRINTF(Branch,
|
||||
"[tid:%i] [sn:%llu] Instruction %s predicted "
|
||||
"target is %s\n",
|
||||
tid, seqNum, pc, target);
|
||||
tid, seqNum, pc, *target);
|
||||
} else {
|
||||
DPRINTF(Branch, "[tid:%i] [sn:%llu] BTB doesn't have a "
|
||||
"valid entry\n",tid,seqNum);
|
||||
"valid entry\n", tid, seqNum);
|
||||
pred_taken = false;
|
||||
predict_record.predTaken = pred_taken;
|
||||
// The Direction of the branch predictor is altered
|
||||
@@ -237,27 +238,25 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
RAS[tid].pop();
|
||||
predict_record.pushedRAS = false;
|
||||
}
|
||||
inst->advancePC(target);
|
||||
inst->advancePC(*target);
|
||||
}
|
||||
} else {
|
||||
predict_record.wasIndirect = true;
|
||||
++stats.indirectLookups;
|
||||
//Consult indirect predictor on indirect control
|
||||
if (iPred->lookup(pc.instAddr(), target, tid)) {
|
||||
if (iPred->lookup(pc.instAddr(), *target, tid)) {
|
||||
// Indirect predictor hit
|
||||
++stats.indirectHits;
|
||||
DPRINTF(Branch,
|
||||
"[tid:%i] [sn:%llu] "
|
||||
"Instruction %s predicted "
|
||||
"[tid:%i] [sn:%llu] Instruction %s predicted "
|
||||
"indirect target is %s\n",
|
||||
tid, seqNum, pc, target);
|
||||
tid, seqNum, pc, *target);
|
||||
} else {
|
||||
++stats.indirectMisses;
|
||||
pred_taken = false;
|
||||
predict_record.predTaken = pred_taken;
|
||||
DPRINTF(Branch,
|
||||
"[tid:%i] [sn:%llu] "
|
||||
"Instruction %s no indirect "
|
||||
"[tid:%i] [sn:%llu] Instruction %s no indirect "
|
||||
"target\n",
|
||||
tid, seqNum, pc);
|
||||
if (!inst->isCall() && !inst->isReturn()) {
|
||||
@@ -266,21 +265,21 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
RAS[tid].pop();
|
||||
predict_record.pushedRAS = false;
|
||||
}
|
||||
inst->advancePC(target);
|
||||
inst->advancePC(*target);
|
||||
}
|
||||
iPred->recordIndirect(pc.instAddr(), target.instAddr(), seqNum,
|
||||
tid);
|
||||
iPred->recordIndirect(pc.instAddr(), target->instAddr(),
|
||||
seqNum, tid);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (inst->isReturn()) {
|
||||
predict_record.wasReturn = true;
|
||||
}
|
||||
inst->advancePC(target);
|
||||
inst->advancePC(*target);
|
||||
}
|
||||
predict_record.target = target.instAddr();
|
||||
predict_record.target = target->instAddr();
|
||||
|
||||
pc = target;
|
||||
set(pc, *target);
|
||||
|
||||
if (iPred) {
|
||||
// Update the indirect predictor with the direction prediction
|
||||
@@ -339,10 +338,10 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
|
||||
DPRINTF(Branch, "[tid:%i] [squash sn:%llu]"
|
||||
" Restoring top of RAS to: %i,"
|
||||
" target: %s\n", tid, squashed_sn,
|
||||
pred_hist.front().RASIndex, pred_hist.front().RASTarget);
|
||||
pred_hist.front().RASIndex, *pred_hist.front().RASTarget);
|
||||
|
||||
RAS[tid].restore(pred_hist.front().RASIndex,
|
||||
pred_hist.front().RASTarget);
|
||||
pred_hist.front().RASTarget.get());
|
||||
} else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
|
||||
// Was a call but predicated false. Pop RAS here
|
||||
DPRINTF(Branch, "[tid:%i] [squash sn:%llu] Squashing"
|
||||
@@ -371,7 +370,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
|
||||
|
||||
void
|
||||
BPredUnit::squash(const InstSeqNum &squashed_sn,
|
||||
const TheISA::PCState &corrTarget,
|
||||
const PCStateBase &corr_target,
|
||||
bool actually_taken, ThreadID tid)
|
||||
{
|
||||
// Now that we know that a branch was mispredicted, we need to undo
|
||||
@@ -391,7 +390,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
|
||||
ppMisses->notify(1);
|
||||
|
||||
DPRINTF(Branch, "[tid:%i] Squashing from sequence number %i, "
|
||||
"setting target to %s\n", tid, squashed_sn, corrTarget);
|
||||
"setting target to %s\n", tid, squashed_sn, corr_target);
|
||||
|
||||
// Squash All Branches AFTER this mispredicted branch
|
||||
squash(squashed_sn, tid);
|
||||
@@ -432,11 +431,11 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
|
||||
|
||||
// Remember the correct direction for the update at commit.
|
||||
pred_hist.front().predTaken = actually_taken;
|
||||
pred_hist.front().target = corrTarget.instAddr();
|
||||
pred_hist.front().target = corr_target.instAddr();
|
||||
|
||||
update(tid, (*hist_it).pc, actually_taken,
|
||||
pred_hist.front().bpHistory, true, pred_hist.front().inst,
|
||||
corrTarget.instAddr());
|
||||
corr_target.instAddr());
|
||||
|
||||
if (iPred) {
|
||||
iPred->changeDirectionPrediction(tid,
|
||||
@@ -458,7 +457,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
|
||||
if (iPred) {
|
||||
iPred->recordTarget(
|
||||
hist_it->seqNum, pred_hist.front().indirectHistory,
|
||||
corrTarget, tid);
|
||||
corr_target, tid);
|
||||
}
|
||||
} else {
|
||||
DPRINTF(Branch,"[tid:%i] [squash sn:%llu] "
|
||||
@@ -466,7 +465,7 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
|
||||
"PC %#x\n", tid, squashed_sn,
|
||||
hist_it->seqNum, hist_it->pc);
|
||||
|
||||
BTB.update((*hist_it).pc, corrTarget, tid);
|
||||
BTB.update(hist_it->pc, corr_target, tid);
|
||||
}
|
||||
} else {
|
||||
//Actually not Taken
|
||||
@@ -479,8 +478,8 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
|
||||
DPRINTF(Branch,
|
||||
"[tid:%i] [squash sn:%llu] Restoring top of RAS "
|
||||
"to: %i, target: %s\n", tid, squashed_sn,
|
||||
hist_it->RASIndex, hist_it->RASTarget);
|
||||
RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
|
||||
hist_it->RASIndex, *hist_it->RASTarget);
|
||||
RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get());
|
||||
hist_it->usedRAS = false;
|
||||
} else if (hist_it->wasCall && hist_it->pushedRAS) {
|
||||
//Was a Call but predicated false. Pop RAS here
|
||||
|
||||
@@ -88,7 +88,7 @@ class BPredUnit : public SimObject
|
||||
* @return Returns if the branch is taken or not.
|
||||
*/
|
||||
bool predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
|
||||
TheISA::PCState &pc, ThreadID tid);
|
||||
PCStateBase &pc, ThreadID tid);
|
||||
|
||||
// @todo: Rename this function.
|
||||
virtual void uncondBranch(ThreadID tid, Addr pc, void * &bp_history) = 0;
|
||||
@@ -119,7 +119,7 @@ class BPredUnit : public SimObject
|
||||
* @param tid The thread id.
|
||||
*/
|
||||
void squash(const InstSeqNum &squashed_sn,
|
||||
const TheISA::PCState &corr_target,
|
||||
const PCStateBase &corr_target,
|
||||
bool actually_taken, ThreadID tid);
|
||||
|
||||
/**
|
||||
@@ -155,11 +155,17 @@ class BPredUnit : public SimObject
|
||||
bool BTBValid(Addr instPC) { return BTB.valid(instPC, 0); }
|
||||
|
||||
/**
|
||||
* Looks up a given PC in the BTB to get the predicted target.
|
||||
* Looks up a given PC in the BTB to get the predicted target. The PC may
|
||||
* be changed or deleted in the future, so it needs to be used immediately,
|
||||
* and/or copied for use later.
|
||||
* @param inst_PC The PC to look up.
|
||||
* @return The address of the target of the branch.
|
||||
*/
|
||||
TheISA::PCState BTBLookup(Addr instPC) { return BTB.lookup(instPC, 0); }
|
||||
const PCStateBase *
|
||||
BTBLookup(Addr inst_pc)
|
||||
{
|
||||
return BTB.lookup(inst_pc, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the BP with taken/not taken information.
|
||||
@@ -183,7 +189,7 @@ class BPredUnit : public SimObject
|
||||
* @param target_PC The branch's target that will be added to the BTB.
|
||||
*/
|
||||
void
|
||||
BTBUpdate(Addr instPC, const TheISA::PCState &target)
|
||||
BTBUpdate(Addr instPC, const PCStateBase &target)
|
||||
{
|
||||
BTB.update(instPC, target, 0);
|
||||
}
|
||||
@@ -203,12 +209,21 @@ class BPredUnit : public SimObject
|
||||
void *indirect_history, ThreadID _tid,
|
||||
const StaticInstPtr & inst)
|
||||
: seqNum(seq_num), pc(instPC), bpHistory(bp_history),
|
||||
indirectHistory(indirect_history), RASTarget(0), RASIndex(0),
|
||||
tid(_tid), predTaken(pred_taken), usedRAS(0), pushedRAS(0),
|
||||
wasCall(0), wasReturn(0), wasIndirect(0), target(MaxAddr),
|
||||
inst(inst)
|
||||
indirectHistory(indirect_history), tid(_tid),
|
||||
predTaken(pred_taken), inst(inst)
|
||||
{}
|
||||
|
||||
PredictorHistory(const PredictorHistory &other) :
|
||||
seqNum(other.seqNum), pc(other.pc), bpHistory(other.bpHistory),
|
||||
indirectHistory(other.indirectHistory), RASIndex(other.RASIndex),
|
||||
tid(other.tid), predTaken(other.predTaken), usedRAS(other.usedRAS),
|
||||
pushedRAS(other.pushedRAS), wasCall(other.wasCall),
|
||||
wasReturn(other.wasReturn), wasIndirect(other.wasIndirect),
|
||||
target(other.target), inst(other.inst)
|
||||
{
|
||||
set(RASTarget, other.RASTarget);
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(const PredictorHistory &entry) const
|
||||
{
|
||||
@@ -225,15 +240,15 @@ class BPredUnit : public SimObject
|
||||
* predictor. It is used to update or restore state of the
|
||||
* branch predictor.
|
||||
*/
|
||||
void *bpHistory;
|
||||
void *bpHistory = nullptr;
|
||||
|
||||
void *indirectHistory;
|
||||
void *indirectHistory = nullptr;
|
||||
|
||||
/** The RAS target (only valid if a return). */
|
||||
TheISA::PCState RASTarget;
|
||||
std::unique_ptr<PCStateBase> RASTarget;
|
||||
|
||||
/** The RAS index of the instruction (only valid if a call). */
|
||||
unsigned RASIndex;
|
||||
unsigned RASIndex = 0;
|
||||
|
||||
/** The thread id. */
|
||||
ThreadID tid;
|
||||
@@ -242,24 +257,24 @@ class BPredUnit : public SimObject
|
||||
bool predTaken;
|
||||
|
||||
/** Whether or not the RAS was used. */
|
||||
bool usedRAS;
|
||||
bool usedRAS = false;
|
||||
|
||||
/* Whether or not the RAS was pushed */
|
||||
bool pushedRAS;
|
||||
bool pushedRAS = false;
|
||||
|
||||
/** Whether or not the instruction was a call. */
|
||||
bool wasCall;
|
||||
bool wasCall = false;
|
||||
|
||||
/** Whether or not the instruction was a return. */
|
||||
bool wasReturn;
|
||||
bool wasReturn = false;
|
||||
|
||||
/** Wether this instruction was an indirect branch */
|
||||
bool wasIndirect;
|
||||
bool wasIndirect = false;
|
||||
|
||||
/** Target of the branch. First it is predicted, and fixed later
|
||||
* if necessary
|
||||
*/
|
||||
Addr target;
|
||||
Addr target = MaxAddr;
|
||||
|
||||
/** The branch instrction */
|
||||
const StaticInstPtr inst;
|
||||
|
||||
@@ -112,35 +112,35 @@ DefaultBTB::valid(Addr instPC, ThreadID tid)
|
||||
// @todo Create some sort of return struct that has both whether or not the
|
||||
// address is valid, and also the address. For now will just use addr = 0 to
|
||||
// represent invalid entry.
|
||||
TheISA::PCState
|
||||
DefaultBTB::lookup(Addr instPC, ThreadID tid)
|
||||
const PCStateBase *
|
||||
DefaultBTB::lookup(Addr inst_pc, ThreadID tid)
|
||||
{
|
||||
unsigned btb_idx = getIndex(instPC, tid);
|
||||
unsigned btb_idx = getIndex(inst_pc, tid);
|
||||
|
||||
Addr inst_tag = getTag(instPC);
|
||||
Addr inst_tag = getTag(inst_pc);
|
||||
|
||||
assert(btb_idx < numEntries);
|
||||
|
||||
if (btb[btb_idx].valid
|
||||
&& inst_tag == btb[btb_idx].tag
|
||||
&& btb[btb_idx].tid == tid) {
|
||||
return btb[btb_idx].target;
|
||||
return btb[btb_idx].target.get();
|
||||
} else {
|
||||
return TheISA::PCState(0);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DefaultBTB::update(Addr instPC, const TheISA::PCState &target, ThreadID tid)
|
||||
DefaultBTB::update(Addr inst_pc, const PCStateBase &target, ThreadID tid)
|
||||
{
|
||||
unsigned btb_idx = getIndex(instPC, tid);
|
||||
unsigned btb_idx = getIndex(inst_pc, tid);
|
||||
|
||||
assert(btb_idx < numEntries);
|
||||
|
||||
btb[btb_idx].tid = tid;
|
||||
btb[btb_idx].valid = true;
|
||||
btb[btb_idx].target = target;
|
||||
btb[btb_idx].tag = getTag(instPC);
|
||||
set(btb[btb_idx].target, target);
|
||||
btb[btb_idx].tag = getTag(inst_pc);
|
||||
}
|
||||
|
||||
} // namespace branch_prediction
|
||||
|
||||
@@ -45,21 +45,17 @@ class DefaultBTB
|
||||
private:
|
||||
struct BTBEntry
|
||||
{
|
||||
BTBEntry()
|
||||
: tag(0), target(0), valid(false)
|
||||
{}
|
||||
|
||||
/** The entry's tag. */
|
||||
Addr tag;
|
||||
Addr tag = 0;
|
||||
|
||||
/** The entry's target. */
|
||||
TheISA::PCState target;
|
||||
std::unique_ptr<PCStateBase> target;
|
||||
|
||||
/** The entry's thread id. */
|
||||
ThreadID tid;
|
||||
|
||||
/** Whether or not the entry is valid. */
|
||||
bool valid;
|
||||
bool valid = false;
|
||||
};
|
||||
|
||||
public:
|
||||
@@ -79,7 +75,7 @@ class DefaultBTB
|
||||
* @param tid The thread id.
|
||||
* @return Returns the target of the branch.
|
||||
*/
|
||||
TheISA::PCState lookup(Addr instPC, ThreadID tid);
|
||||
const PCStateBase *lookup(Addr instPC, ThreadID tid);
|
||||
|
||||
/** Checks if a branch is in the BTB.
|
||||
* @param inst_PC The address of the branch to look up.
|
||||
@@ -89,12 +85,11 @@ class DefaultBTB
|
||||
bool valid(Addr instPC, ThreadID tid);
|
||||
|
||||
/** Updates the BTB with the target of a branch.
|
||||
* @param inst_PC The address of the branch being updated.
|
||||
* @param target_PC The target address of the branch.
|
||||
* @param inst_pc The address of the branch being updated.
|
||||
* @param target_pc The target address of the branch.
|
||||
* @param tid The thread id.
|
||||
*/
|
||||
void update(Addr instPC, const TheISA::PCState &targetPC,
|
||||
ThreadID tid);
|
||||
void update(Addr inst_pc, const PCStateBase &target_pc, ThreadID tid);
|
||||
|
||||
private:
|
||||
/** Returns the index into the BTB, based on the branch's PC.
|
||||
|
||||
@@ -52,7 +52,7 @@ class IndirectPredictor : public SimObject
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool lookup(Addr br_addr, TheISA::PCState& br_target,
|
||||
virtual bool lookup(Addr br_addr, PCStateBase& br_target,
|
||||
ThreadID tid) = 0;
|
||||
virtual void recordIndirect(Addr br_addr, Addr tgt_addr,
|
||||
InstSeqNum seq_num, ThreadID tid) = 0;
|
||||
@@ -60,7 +60,7 @@ class IndirectPredictor : public SimObject
|
||||
void * indirect_history) = 0;
|
||||
virtual void squash(InstSeqNum seq_num, ThreadID tid) = 0;
|
||||
virtual void recordTarget(InstSeqNum seq_num, void * indirect_history,
|
||||
const TheISA::PCState& target, ThreadID tid) = 0;
|
||||
const PCStateBase& target, ThreadID tid) = 0;
|
||||
virtual void genIndirectInfo(ThreadID tid, void* & indirect_history) = 0;
|
||||
virtual void updateDirectionInfo(ThreadID tid, bool actually_taken) = 0;
|
||||
virtual void deleteIndirectInfo(ThreadID tid, void * indirect_history) = 0;
|
||||
|
||||
@@ -47,16 +47,14 @@ ReturnAddrStack::reset()
|
||||
{
|
||||
usedEntries = 0;
|
||||
tos = 0;
|
||||
for (unsigned i = 0; i < numEntries; ++i)
|
||||
addrStack[i].set(0);
|
||||
}
|
||||
|
||||
void
|
||||
ReturnAddrStack::push(const TheISA::PCState &return_addr)
|
||||
ReturnAddrStack::push(const PCStateBase &return_addr)
|
||||
{
|
||||
incrTos();
|
||||
|
||||
addrStack[tos] = return_addr;
|
||||
set(addrStack[tos], return_addr);
|
||||
|
||||
if (usedEntries != numEntries) {
|
||||
++usedEntries;
|
||||
@@ -74,12 +72,11 @@ ReturnAddrStack::pop()
|
||||
}
|
||||
|
||||
void
|
||||
ReturnAddrStack::restore(unsigned top_entry_idx,
|
||||
const TheISA::PCState &restored)
|
||||
ReturnAddrStack::restore(unsigned top_entry_idx, const PCStateBase *restored)
|
||||
{
|
||||
tos = top_entry_idx;
|
||||
|
||||
addrStack[tos] = restored;
|
||||
set(addrStack[tos], restored);
|
||||
|
||||
if (usedEntries != numEntries) {
|
||||
++usedEntries;
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "arch/pcstate.hh"
|
||||
#include "arch/generic/pcstate.hh"
|
||||
#include "base/types.hh"
|
||||
#include "config/the_isa.hh"
|
||||
|
||||
namespace gem5
|
||||
{
|
||||
@@ -58,13 +57,13 @@ class ReturnAddrStack
|
||||
void reset();
|
||||
|
||||
/** Returns the top address on the RAS. */
|
||||
TheISA::PCState top() { return addrStack[tos]; }
|
||||
const PCStateBase *top() { return addrStack[tos].get(); }
|
||||
|
||||
/** Returns the index of the top of the RAS. */
|
||||
unsigned topIdx() { return tos; }
|
||||
|
||||
/** Pushes an address onto the RAS. */
|
||||
void push(const TheISA::PCState &return_addr);
|
||||
void push(const PCStateBase &return_addr);
|
||||
|
||||
/** Pops the top address from the RAS. */
|
||||
void pop();
|
||||
@@ -74,7 +73,7 @@ class ReturnAddrStack
|
||||
* @param top_entry_idx The index of the RAS that will now be the top.
|
||||
* @param restored The new target address of the new top of the RAS.
|
||||
*/
|
||||
void restore(unsigned top_entry_idx, const TheISA::PCState &restored);
|
||||
void restore(unsigned top_entry_idx, const PCStateBase *restored);
|
||||
|
||||
bool empty() { return usedEntries == 0; }
|
||||
|
||||
@@ -96,7 +95,7 @@ class ReturnAddrStack
|
||||
}
|
||||
|
||||
/** The RAS itself. */
|
||||
std::vector<TheISA::PCState> addrStack;
|
||||
std::vector<std::unique_ptr<PCStateBase>> addrStack;
|
||||
|
||||
/** The number of entries in the RAS. */
|
||||
unsigned numEntries;
|
||||
|
||||
@@ -93,7 +93,7 @@ SimpleIndirectPredictor::changeDirectionPrediction(ThreadID tid,
|
||||
}
|
||||
|
||||
bool
|
||||
SimpleIndirectPredictor::lookup(Addr br_addr, TheISA::PCState& target,
|
||||
SimpleIndirectPredictor::lookup(Addr br_addr, PCStateBase& target,
|
||||
ThreadID tid)
|
||||
{
|
||||
Addr set_index = getSetIndex(br_addr, threadInfo[tid].ghr, tid);
|
||||
@@ -105,8 +105,8 @@ SimpleIndirectPredictor::lookup(Addr br_addr, TheISA::PCState& target,
|
||||
const auto &iset = targetCache[set_index];
|
||||
for (auto way = iset.begin(); way != iset.end(); ++way) {
|
||||
if (way->tag == tag) {
|
||||
DPRINTF(Indirect, "Hit %x (target:%s)\n", br_addr, way->target);
|
||||
target = way->target;
|
||||
DPRINTF(Indirect, "Hit %x (target:%s)\n", br_addr, *way->target);
|
||||
set(target, *way->target);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ SimpleIndirectPredictor::deleteIndirectInfo(ThreadID tid,
|
||||
|
||||
void
|
||||
SimpleIndirectPredictor::recordTarget(
|
||||
InstSeqNum seq_num, void * indirect_history, const TheISA::PCState& target,
|
||||
InstSeqNum seq_num, void * indirect_history, const PCStateBase& target,
|
||||
ThreadID tid)
|
||||
{
|
||||
ThreadInfo &t_info = threadInfo[tid];
|
||||
@@ -200,7 +200,7 @@ SimpleIndirectPredictor::recordTarget(
|
||||
if (way->tag == tag) {
|
||||
DPRINTF(Indirect, "Updating Target (seq: %d br:%x set:%d target:"
|
||||
"%s)\n", seq_num, hist_entry.pcAddr, set_index, target);
|
||||
way->target = target;
|
||||
set(way->target, target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -210,7 +210,7 @@ SimpleIndirectPredictor::recordTarget(
|
||||
// Did not find entry, random replacement
|
||||
auto &way = iset[rand() % numWays];
|
||||
way.tag = tag;
|
||||
way.target = target;
|
||||
set(way.target, target);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -47,13 +47,13 @@ class SimpleIndirectPredictor : public IndirectPredictor
|
||||
public:
|
||||
SimpleIndirectPredictor(const SimpleIndirectPredictorParams ¶ms);
|
||||
|
||||
bool lookup(Addr br_addr, TheISA::PCState& br_target, ThreadID tid);
|
||||
bool lookup(Addr br_addr, PCStateBase& br_target, ThreadID tid);
|
||||
void recordIndirect(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num,
|
||||
ThreadID tid);
|
||||
void commit(InstSeqNum seq_num, ThreadID tid, void * indirect_history);
|
||||
void squash(InstSeqNum seq_num, ThreadID tid);
|
||||
void recordTarget(InstSeqNum seq_num, void * indirect_history,
|
||||
const TheISA::PCState& target, ThreadID tid);
|
||||
const PCStateBase& target, ThreadID tid);
|
||||
void genIndirectInfo(ThreadID tid, void* & indirect_history);
|
||||
void updateDirectionInfo(ThreadID tid, bool actually_taken);
|
||||
void deleteIndirectInfo(ThreadID tid, void * indirect_history);
|
||||
@@ -73,9 +73,8 @@ class SimpleIndirectPredictor : public IndirectPredictor
|
||||
|
||||
struct IPredEntry
|
||||
{
|
||||
IPredEntry() : tag(0), target(0) { }
|
||||
Addr tag;
|
||||
TheISA::PCState target;
|
||||
Addr tag = 0;
|
||||
std::unique_ptr<PCStateBase> target;
|
||||
};
|
||||
|
||||
std::vector<std::vector<IPredEntry> > targetCache;
|
||||
@@ -95,11 +94,9 @@ class SimpleIndirectPredictor : public IndirectPredictor
|
||||
|
||||
struct ThreadInfo
|
||||
{
|
||||
ThreadInfo() : headHistEntry(0), ghr(0) { }
|
||||
|
||||
std::deque<HistoryEntry> pathHist;
|
||||
unsigned headHistEntry;
|
||||
unsigned ghr;
|
||||
unsigned headHistEntry = 0;
|
||||
unsigned ghr = 0;
|
||||
};
|
||||
|
||||
std::vector<ThreadInfo> threadInfo;
|
||||
|
||||
@@ -371,9 +371,8 @@ BaseSimpleCPU::preExecute()
|
||||
const InstSeqNum cur_sn(0);
|
||||
set(t_info.predPC, thread->pcState());
|
||||
const bool predict_taken(
|
||||
branchPred->predict(curStaticInst, cur_sn,
|
||||
t_info.predPC->as<TheISA::PCState>(),
|
||||
curThread));
|
||||
branchPred->predict(curStaticInst, cur_sn, *t_info.predPC,
|
||||
curThread));
|
||||
|
||||
if (predict_taken)
|
||||
++t_info.execContextStats.numPredictedBranches;
|
||||
@@ -489,7 +488,8 @@ BaseSimpleCPU::advancePC(const Fault &fault)
|
||||
branchPred->update(cur_sn, curThread);
|
||||
} else {
|
||||
// Mis-predicted branch
|
||||
branchPred->squash(cur_sn, thread->pcState(), branching, curThread);
|
||||
branchPred->squash(cur_sn, thread->pcState(), branching,
|
||||
curThread);
|
||||
++t_info.execContextStats.numBranchMispred;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user