50#include "debug/Branch.hh"
55namespace branch_prediction
60 numThreads(params.numThreads),
62 BTB(params.BTBEntries,
67 iPred(params.indirectBranchPred),
69 instShiftAmt(params.instShiftAmt)
76 : statistics::
Group(parent),
77 ADD_STAT(lookups, statistics::units::Count::get(),
78 "Number of BP lookups"),
79 ADD_STAT(condPredicted, statistics::units::Count::get(),
80 "Number of conditional branches predicted"),
81 ADD_STAT(condIncorrect, statistics::units::Count::get(),
82 "Number of conditional branches incorrect"),
83 ADD_STAT(BTBLookups, statistics::units::Count::get(),
84 "Number of BTB lookups"),
85 ADD_STAT(BTBUpdates, statistics::units::Count::get(),
86 "Number of BTB updates"),
87 ADD_STAT(BTBHits, statistics::units::Count::get(),
"Number of BTB hits"),
88 ADD_STAT(BTBHitRatio, statistics::units::Ratio::get(),
"BTB Hit Ratio",
89 BTBHits / BTBLookups),
90 ADD_STAT(RASUsed, statistics::units::Count::get(),
91 "Number of times the RAS was used to get a target."),
92 ADD_STAT(RASIncorrect, statistics::units::Count::get(),
93 "Number of incorrect RAS predictions."),
94 ADD_STAT(indirectLookups, statistics::units::Count::get(),
95 "Number of indirect predictor lookups."),
96 ADD_STAT(indirectHits, statistics::units::Count::get(),
97 "Number of indirect target hits."),
98 ADD_STAT(indirectMisses, statistics::units::Count::get(),
99 "Number of indirect misses."),
100 ADD_STAT(indirectMispredicted, statistics::units::Count::get(),
101 "Number of mispredicted indirect branches.")
127 for ([[maybe_unused]]
const auto& ph :
predHist)
140 bool pred_taken =
false;
141 std::unique_ptr<PCStateBase> target(
pc.clone());
146 void *bp_history = NULL;
147 void *indirect_history = NULL;
150 DPRINTF(
Branch,
"[tid:%i] [sn:%llu] Unconditional control\n",
157 pred_taken =
lookup(tid,
pc.instAddr(), bp_history);
160 "Branch predictor predicted %i for PC %s\n",
161 tid, seqNum, pred_taken,
pc);
164 const bool orig_pred_taken = pred_taken;
170 "[tid:%i] [sn:%llu] Creating prediction history for PC %s\n",
174 bp_history, indirect_history, tid, inst);
196 DPRINTF(
Branch,
"[tid:%i] [sn:%llu] Instruction %s is a return, "
197 "RAS predicted target: %s, RAS index: %i\n",
198 tid, seqNum,
pc, *target, predict_record.
RASIndex);
210 "[tid:%i] [sn:%llu] Instruction %s was a call, adding "
211 "%s to the RAS index: %i\n",
212 tid, seqNum,
pc,
pc,
RAS[tid].topIdx());
226 "[tid:%i] [sn:%llu] Instruction %s predicted "
228 tid, seqNum,
pc, *target);
231 "valid entry\n", tid, seqNum);
240 "[tid:%i] [sn:%llu] btbUpdate "
257 "[tid:%i] [sn:%llu] Instruction %s predicted "
258 "indirect target is %s\n",
259 tid, seqNum,
pc, *target);
265 "[tid:%i] [sn:%llu] Instruction %s no indirect "
286 predict_record.
target = target->instAddr();
299 predHist[tid].push_front(predict_record);
302 "[tid:%i] [sn:%llu] History entry added. "
303 "predHist.size(): %i\n",
313 "sn:%llu]\n", tid, done_sn);
316 predHist[tid].back().seqNum <= done_sn) {
320 predHist[tid].back().bpHistory,
false,
341 while (!pred_hist.empty() &&
342 pred_hist.front().seqNum > squashed_sn) {
343 if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
346 " Call [sn:%llu] PC: %s Popping RAS\n", tid, squashed_sn,
347 pred_hist.front().seqNum, pred_hist.front().pc);
350 if (pred_hist.front().usedRAS) {
351 if (pred_hist.front().RASTarget !=
nullptr) {
353 " Restoring top of RAS to: %i,"
354 " target: %s\n", tid, squashed_sn,
355 pred_hist.front().RASIndex,
356 *pred_hist.front().RASTarget);
360 " Restoring top of RAS to: %i,"
361 " target: INVALID_TARGET\n", tid, squashed_sn,
362 pred_hist.front().RASIndex);
365 RAS[tid].restore(pred_hist.front().RASIndex,
366 pred_hist.front().RASTarget.get());
370 squash(tid, pred_hist.front().bpHistory);
376 "Removing history for [sn:%llu] "
377 "PC %#x\n", tid, squashed_sn, pred_hist.front().seqNum,
378 pred_hist.front().pc);
380 pred_hist.pop_front();
382 DPRINTF(
Branch,
"[tid:%i] [squash sn:%llu] predHist.size(): %i\n",
383 tid, squashed_sn,
predHist[tid].size());
408 DPRINTF(
Branch,
"[tid:%i] Squashing from sequence number %i, "
409 "setting target to %s\n", tid, squashed_sn, corr_target);
417 if (!pred_hist.empty()) {
419 auto hist_it = pred_hist.begin();
424 if (pred_hist.front().seqNum != squashed_sn) {
426 pred_hist.front().seqNum, squashed_sn);
428 assert(pred_hist.front().seqNum == squashed_sn);
432 if ((*hist_it).usedRAS) {
435 "[tid:%i] [squash sn:%llu] Incorrect RAS [sn:%llu]\n",
436 tid, squashed_sn, hist_it->seqNum);
449 pred_hist.front().predTaken = actually_taken;
450 pred_hist.front().target = corr_target.
instAddr();
452 update(tid, (*hist_it).pc, actually_taken,
453 pred_hist.front().bpHistory,
true, pred_hist.front().inst,
458 pred_hist.front().indirectHistory, actually_taken);
461 if (actually_taken) {
462 if (hist_it->wasReturn && !hist_it->usedRAS) {
464 "Incorrectly predicted "
465 "return [sn:%llu] PC: %#x\n", tid, squashed_sn,
469 hist_it->usedRAS =
true;
471 if (hist_it->wasIndirect) {
475 hist_it->seqNum, pred_hist.front().indirectHistory,
480 "BTB Update called for [sn:%llu] "
481 "PC %#x\n", tid, squashed_sn,
482 hist_it->seqNum, hist_it->pc);
485 BTB.
update(hist_it->pc, corr_target, tid);
489 if (hist_it->wasCall && hist_it->pushedRAS) {
492 "[tid:%i] [squash sn:%llu] "
493 "Incorrectly predicted "
494 "Call [sn:%llu] PC: %s Popping RAS\n",
496 hist_it->seqNum, hist_it->pc);
498 hist_it->pushedRAS =
false;
500 if (hist_it->usedRAS) {
502 "[tid:%i] [squash sn:%llu] Incorrectly predicted "
503 "return [sn:%llu] PC: %#x Restoring RAS\n", tid,
505 hist_it->seqNum, hist_it->pc);
507 "[tid:%i] [squash sn:%llu] Restoring top of RAS "
508 "to: %i, target: %s\n", tid, squashed_sn,
509 hist_it->RASIndex, *hist_it->RASTarget);
510 RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget.get());
511 hist_it->usedRAS =
false;
516 "update\n", tid, squashed_sn);
526 auto pred_hist_it = ph.begin();
528 cprintf(
"predHist[%i].size(): %i\n",
i++, ph.size());
530 while (pred_hist_it != ph.end()) {
531 cprintf(
"sn:%llu], PC:%#x, tid:%i, predTaken:%i, "
533 pred_hist_it->seqNum, pred_hist_it->pc,
534 pred_hist_it->tid, pred_hist_it->predTaken,
535 pred_hist_it->bpHistory);
virtual std::string name() const
Addr instAddr() const
Returns the memory address of the instruction this PC points to.
ProbePointArg generates a point for the class of Arg.
Abstract superclass for simulation objects.
Base class for branch operations.
virtual std::unique_ptr< PCStateBase > buildRetPC(const PCStateBase &cur_pc, const PCStateBase &call_pc) const
bool isDirectCtrl() const
bool isUncondCtrl() const
virtual void advancePC(PCStateBase &pc_state) const =0
std::vector< History > predHist
The per-thread predictor history.
virtual void uncondBranch(ThreadID tid, Addr pc, void *&bp_history)=0
probing::PMUUPtr pmuProbePoint(const char *name)
Helper method to instantiate probe points belonging to this object.
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...
void update(const InstSeqNum &done_sn, ThreadID tid)
Tells the branch predictor to commit any updates until the given sequence number.
BPredUnit(const Params &p)
bool predict(const StaticInstPtr &inst, const InstSeqNum &seqNum, PCStateBase &pc, ThreadID tid)
Predicts whether or not the instruction is a taken branch, and the target of the branch if it is take...
probing::PMUUPtr ppMisses
Miss-predicted branches.
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.
void drainSanityCheck() const
Perform sanity checks after a drain.
IndirectPredictor * iPred
The indirect target predictor.
probing::PMUUPtr ppBranches
Branches seen by the branch predictor.
void regProbePoints() override
Register probe points for this object.
std::vector< ReturnAddrStack > RAS
The per-thread return address stack.
BranchPredictorParams Params
void squash(const InstSeqNum &squashed_sn, ThreadID tid)
Squashes all outstanding updates until a given sequence number.
gem5::branch_prediction::BPredUnit::BPredUnitStats stats
bool valid(Addr instPC, ThreadID tid)
Checks if a branch is in the BTB.
void update(Addr inst_pc, const PCStateBase &target_pc, ThreadID tid)
Updates the BTB with the target of a branch.
const PCStateBase * lookup(Addr instPC, ThreadID tid)
Looks up an address in the BTB.
virtual void commit(InstSeqNum seq_num, ThreadID tid, void *indirect_history)=0
virtual void squash(InstSeqNum seq_num, ThreadID tid)=0
virtual void deleteIndirectInfo(ThreadID tid, void *indirect_history)=0
virtual void updateDirectionInfo(ThreadID tid, bool actually_taken)=0
virtual void changeDirectionPrediction(ThreadID tid, void *indirect_history, bool actually_taken)=0
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
virtual void recordTarget(InstSeqNum seq_num, void *indirect_history, const PCStateBase &target, ThreadID tid)=0
virtual void genIndirectInfo(ThreadID tid, void *&indirect_history)=0
Derived & precision(int _precision)
Set the precision and marks this stat to print at the end of simulation.
#define ADD_STAT(n,...)
Convenience macro to add a stat to a statistics group.
const Params & params() const
ProbeManager * getProbeManager()
Get the probe manager for this object.
std::unique_ptr< PMU > PMUUPtr
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
int16_t ThreadID
Thread index/ID type.
void cprintf(const char *format, const Args &...args)
statistics::Scalar BTBUpdates
Stat for number of BTB updates.
statistics::Scalar indirectMispredicted
Stat for the number of indirect target mispredictions.
statistics::Scalar BTBLookups
Stat for number of BTB lookups.
statistics::Scalar condIncorrect
Stat for number of conditional branches predicted incorrectly.
statistics::Scalar indirectLookups
Stat for the number of indirect target lookups.
statistics::Scalar indirectHits
Stat for the number of indirect target hits.
statistics::Scalar RASUsed
Stat for number of times the RAS is used to get a target.
BPredUnitStats(statistics::Group *parent)
statistics::Scalar condPredicted
Stat for number of conditional branches predicted.
statistics::Formula BTBHitRatio
Stat for the ratio between BTB hits and BTB lookups.
statistics::Scalar indirectMisses
Stat for the number of indirect target misses.
statistics::Scalar RASIncorrect
Stat for number of times the RAS is incorrect.
statistics::Scalar lookups
Stat for number of BP lookups.
statistics::Scalar BTBHits
Stat for number of BTB hits.
bool predTaken
Whether or not it was predicted taken.
Addr target
Target of the branch.
unsigned RASIndex
The RAS index of the instruction (only valid if a call).
bool wasReturn
Whether or not the instruction was a return.
bool wasIndirect
Wether this instruction was an indirect branch.
bool wasCall
Whether or not the instruction was a call.
std::unique_ptr< PCStateBase > RASTarget
The RAS target (only valid if a return).
bool usedRAS
Whether or not the RAS was used.