47 #include "arch/isa_traits.hh" 48 #include "arch/types.hh" 49 #include "arch/utility.hh" 51 #include "config/the_isa.hh" 52 #include "debug/Branch.hh" 56 numThreads(params->numThreads),
58 BTB(params->BTBEntries,
63 iPred(params->indirectBranchPred),
64 instShiftAmt(params->instShiftAmt)
67 r.init(params->RASSize);
77 .
desc(
"Number of BP lookups")
82 .
desc(
"Number of conditional branches predicted")
87 .
desc(
"Number of conditional branches incorrect")
92 .
desc(
"Number of BTB lookups")
97 .
desc(
"Number of BTB hits")
102 .
desc(
"Number of correct BTB predictions (this stat may not " 108 .
desc(
"BTB Hit Percentage")
114 .
desc(
"Number of times the RAS was used to get a target.")
119 .
desc(
"Number of incorrect RAS predictions.")
124 .
desc(
"Number of indirect predictor lookups.")
129 .
desc(
"Number of indirect target hits.")
134 .
desc(
"Number of indirect misses.")
138 .
name(
name() +
"indirectMispredicted")
139 .
desc(
"Number of mispredicted indirect branches.")
165 for (
const auto& ph M5_VAR_USED :
predHist)
178 bool pred_taken =
false;
184 void *bp_history = NULL;
185 void *indirect_history = NULL;
188 DPRINTF(Branch,
"[tid:%i] [sn:%llu] " 189 "Unconditional control\n",
196 pred_taken =
lookup(tid, pc.instAddr(), bp_history);
198 DPRINTF(Branch,
"[tid:%i] [sn:%llu] " 199 "Branch predictor predicted %i for PC %s\n",
200 tid, seqNum, pred_taken, pc);
203 const bool orig_pred_taken = pred_taken;
208 DPRINTF(Branch,
"[tid:%i] [sn:%llu] " 209 "Creating prediction history " 210 "for PC %s\n", tid, seqNum, pc);
213 bp_history, indirect_history, tid, inst);
219 predict_record.wasReturn =
true;
226 predict_record.usedRAS =
true;
227 predict_record.RASIndex =
RAS[tid].topIdx();
228 predict_record.RASTarget = rasTop;
232 DPRINTF(Branch,
"[tid:%i] [sn:%llu] Instruction %s is a return, " 233 "RAS predicted target: %s, RAS index: %i\n",
234 tid, seqNum, pc, target, predict_record.RASIndex);
239 predict_record.pushedRAS =
true;
243 predict_record.wasCall =
true;
246 "[tid:%i] [sn:%llu] Instruction %s was a call, adding " 247 "%s to the RAS index: %i\n",
248 tid, seqNum, pc, pc,
RAS[tid].topIdx());
254 if (
BTB.
valid(pc.instAddr(), tid)) {
259 "[tid:%i] [sn:%llu] Instruction %s predicted " 261 tid, seqNum, pc, target);
263 DPRINTF(Branch,
"[tid:%i] [sn:%llu] BTB doesn't have a " 264 "valid entry\n",tid,seqNum);
266 predict_record.predTaken = pred_taken;
271 btbUpdate(tid, pc.instAddr(), bp_history);
273 "[tid:%i] [sn:%llu] btbUpdate " 278 predict_record.pushedRAS =
false;
283 predict_record.wasIndirect =
true;
290 "[tid:%i] [sn:%llu] " 291 "Instruction %s predicted " 292 "indirect target is %s\n",
293 tid, seqNum, pc, target);
297 predict_record.predTaken = pred_taken;
299 "[tid:%i] [sn:%llu] " 300 "Instruction %s no indirect " 307 predict_record.pushedRAS =
false;
317 predict_record.wasReturn =
true;
321 predict_record.target = target.instAddr();
334 predHist[tid].push_front(predict_record);
337 "[tid:%i] [sn:%llu] History entry added. " 338 "predHist.size(): %i\n",
347 DPRINTF(Branch,
"[tid:%i] Committing branches until " 348 "sn:%llu]\n", tid, done_sn);
351 predHist[tid].back().seqNum <= done_sn) {
355 predHist[tid].back().bpHistory,
false,
376 while (!pred_hist.empty() &&
377 pred_hist.front().seqNum > squashed_sn) {
378 if (pred_hist.front().usedRAS) {
379 DPRINTF(Branch,
"[tid:%i] [squash sn:%llu]" 380 " Restoring top of RAS to: %i," 381 " target: %s\n", tid, squashed_sn,
382 pred_hist.front().RASIndex, pred_hist.front().RASTarget);
384 RAS[tid].restore(pred_hist.front().RASIndex,
385 pred_hist.front().RASTarget);
386 }
else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
388 DPRINTF(Branch,
"[tid:%i] [squash sn:%llu] Squashing" 389 " Call [sn:%llu] PC: %s Popping RAS\n", tid, squashed_sn,
390 pred_hist.front().seqNum, pred_hist.front().pc);
395 squash(tid, pred_hist.front().bpHistory);
400 DPRINTF(Branch,
"[tid:%i] [squash sn:%llu] " 401 "Removing history for [sn:%llu] " 402 "PC %#x\n", tid, squashed_sn, pred_hist.front().seqNum,
403 pred_hist.front().pc);
405 pred_hist.pop_front();
407 DPRINTF(Branch,
"[tid:%i] [squash sn:%llu] predHist.size(): %i\n",
408 tid, squashed_sn,
predHist[tid].size());
433 DPRINTF(Branch,
"[tid:%i] Squashing from sequence number %i, " 434 "setting target to %s\n", tid, squashed_sn, corrTarget);
442 if (!pred_hist.empty()) {
444 auto hist_it = pred_hist.begin();
449 if (pred_hist.front().seqNum != squashed_sn) {
450 DPRINTF(Branch,
"Front sn %i != Squash sn %i\n",
451 pred_hist.front().seqNum, squashed_sn);
453 assert(pred_hist.front().seqNum == squashed_sn);
457 if ((*hist_it).usedRAS) {
460 "[tid:%i] [squash sn:%llu] Incorrect RAS [sn:%llu]\n",
461 tid, squashed_sn, hist_it->seqNum);
474 pred_hist.front().predTaken = actually_taken;
475 pred_hist.front().target = corrTarget.instAddr();
477 update(tid, (*hist_it).pc, actually_taken,
478 pred_hist.front().bpHistory,
true, pred_hist.front().inst,
479 corrTarget.instAddr());
483 pred_hist.front().indirectHistory, actually_taken);
486 if (actually_taken) {
487 if (hist_it->wasReturn && !hist_it->usedRAS) {
488 DPRINTF(Branch,
"[tid:%i] [squash sn:%llu] " 489 "Incorrectly predicted " 490 "return [sn:%llu] PC: %#x\n", tid, squashed_sn,
494 hist_it->usedRAS =
true;
496 if (hist_it->wasIndirect) {
500 hist_it->seqNum, pred_hist.front().indirectHistory,
504 DPRINTF(Branch,
"[tid:%i] [squash sn:%llu] " 505 "BTB Update called for [sn:%llu] " 506 "PC %#x\n", tid, squashed_sn,
507 hist_it->seqNum, hist_it->pc);
509 BTB.
update((*hist_it).pc, corrTarget, tid);
513 if (hist_it->usedRAS) {
515 "[tid:%i] [squash sn:%llu] Incorrectly predicted " 516 "return [sn:%llu] PC: %#x Restoring RAS\n", tid,
518 hist_it->seqNum, hist_it->pc);
520 "[tid:%i] [squash sn:%llu] Restoring top of RAS " 521 "to: %i, target: %s\n", tid, squashed_sn,
522 hist_it->RASIndex, hist_it->RASTarget);
523 RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
524 hist_it->usedRAS =
false;
525 }
else if (hist_it->wasCall && hist_it->pushedRAS) {
528 "[tid:%i] [squash sn:%llu] " 529 "Incorrectly predicted " 530 "Call [sn:%llu] PC: %s Popping RAS\n",
532 hist_it->seqNum, hist_it->pc);
534 hist_it->pushedRAS =
false;
538 DPRINTF(Branch,
"[tid:%i] [sn:%llu] pred_hist empty, can't " 539 "update\n", tid, squashed_sn);
549 auto pred_hist_it = ph.begin();
551 cprintf(
"predHist[%i].size(): %i\n", i++, ph.size());
553 while (pred_hist_it != ph.end()) {
554 cprintf(
"sn:%llu], PC:%#x, tid:%i, predTaken:%i, " 556 pred_hist_it->seqNum, pred_hist_it->pc,
557 pred_hist_it->tid, pred_hist_it->predTaken,
558 pred_hist_it->bpHistory);
virtual void deleteIndirectInfo(ThreadID tid, void *indirect_history)=0
Stats::Scalar indirectHits
Stat for the number of indirect target hits.
virtual void recordIndirect(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num, ThreadID tid)=0
Stats::Scalar BTBHits
Stat for number of BTB hits.
virtual void genIndirectInfo(ThreadID tid, void *&indirect_history)=0
PCState buildRetPC(const PCState &curPC, const PCState &callPC)
Stats::Scalar usedRAS
Stat for number of times the RAS is used to get a target.
virtual void updateDirectionInfo(ThreadID tid, bool actually_taken)=0
BranchPredictorParams Params
std::vector< History > predHist
The per-thread predictor history.
void update(const InstSeqNum &done_sn, ThreadID tid)
Tells the branch predictor to commit any updates until the given sequence number. ...
IndirectPredictor * iPred
The indirect target predictor.
Stats::Scalar condIncorrect
Stat for number of conditional branches predicted incorrectly.
Stats::Scalar BTBCorrect
Stat for number of times the BTB is correct.
bool isDirectCtrl() const
bool isUncondCtrl() const
virtual void commit(InstSeqNum seq_num, ThreadID tid, void *indirect_history)=0
void regProbePoints() override
Register probe points for this object.
virtual void changeDirectionPrediction(ThreadID tid, void *indirect_history, bool actually_taken)=0
Stats::Formula BTBHitPct
Stat for percent times an entry in BTB found.
Stats::Scalar indirectMisses
Stat for the number of indirect target misses.
std::unique_ptr< PMU > PMUUPtr
virtual void uncondBranch(ThreadID tid, Addr pc, void *&bp_history)=0
Stats::Scalar condPredicted
Stat for number of conditional branches predicted.
virtual bool lookup(Addr br_addr, TheISA::PCState &br_target, ThreadID tid)=0
virtual void squash(InstSeqNum seq_num, ThreadID tid)=0
virtual void btbUpdate(ThreadID tid, Addr instPC, void *&bp_history)=0
If a branch is not taken, because the BTB address is invalid or missing, this function sets the appro...
Stats::Scalar BTBLookups
Stat for number of BTB lookups.
bool predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, TheISA::PCState &pc, ThreadID tid)
Predicts whether or not the instruction is a taken branch, and the target of the branch if it is take...
ProbePoints::PMUUPtr pmuProbePoint(const char *name)
Helper method to instantiate probe points belonging to this object.
void advancePC(PCState &pc, const StaticInstPtr &inst)
void update(Addr instPC, const TheISA::PCState &targetPC, ThreadID tid)
Updates the BTB with the target of a branch.
TheISA::PCState lookup(Addr instPC, ThreadID tid)
Looks up an address in the BTB.
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
ProbePoints::PMUUPtr ppMisses
Miss-predicted branches.
void regStats() override
Registers statistics.
virtual bool lookup(ThreadID tid, Addr instPC, void *&bp_history)=0
Looks up a given PC in the BP to see if it is taken or not taken.
std::vector< ReturnAddrStack > RAS
The per-thread return address stack.
Stats::Scalar RASIncorrect
Stat for number of times the RAS is incorrect.
ProbeManager * getProbeManager()
Get the probe manager for this object.
Derived & name(const std::string &name)
Set the name and marks this stat to print at the end of simulation.
int16_t ThreadID
Thread index/ID type.
virtual const std::string name() const
ProbePointArg generates a point for the class of Arg.
bool valid(Addr instPC, ThreadID tid)
Checks if a branch is in the BTB.
void drainSanityCheck() const
Perform sanity checks after a drain.
Stats::Scalar indirectMispredicted
Stat for the number of indirect target mispredictions.
BPredUnit(const Params *p)
void squash(const InstSeqNum &squashed_sn, ThreadID tid)
Squashes all outstanding updates until a given sequence number.
Derived & desc(const std::string &_desc)
Set the description and marks this stat to print at the end of simulation.
virtual void regStats()
Callback to set stat parameters.
GenericISA::DelaySlotPCState< MachInst > PCState
Stats::Scalar indirectLookups
Stat for the number of indirect target lookups.
ProbePoints::PMUUPtr ppBranches
Branches seen by the branch predictor.
Abstract superclass for simulation objects.
Stats::Scalar lookups
Stat for number of BP lookups.
virtual void recordTarget(InstSeqNum seq_num, void *indirect_history, const TheISA::PCState &target, ThreadID tid)=0
void cprintf(const char *format, const Args &...args)