49 #include "arch/isa_traits.hh" 
   50 #include "arch/types.hh" 
   51 #include "arch/utility.hh" 
   53 #include "config/the_isa.hh" 
   54 #include "debug/Branch.hh" 
   58       numThreads(params->numThreads),
 
   60       BTB(params->BTBEntries,
 
   65       useIndirect(params->useIndirect),
 
   66       iPred(params->indirectHashGHR,
 
   67             params->indirectHashTargets,
 
   70             params->indirectTagSize,
 
   71             params->indirectPathLength,
 
   74       instShiftAmt(params->instShiftAmt)
 
   77         r.init(params->RASSize);
 
   87         .
desc(
"Number of BP lookups")
 
   92         .
desc(
"Number of conditional branches predicted")
 
   97         .
desc(
"Number of conditional branches incorrect")
 
  102         .
desc(
"Number of BTB lookups")
 
  107         .
desc(
"Number of BTB hits")
 
  112         .
desc(
"Number of correct BTB predictions (this stat may not " 
  118         .
desc(
"BTB Hit Percentage")
 
  124         .
desc(
"Number of times the RAS was used to get a target.")
 
  129         .
desc(
"Number of incorrect RAS predictions.")
 
  134         .
desc(
"Number of indirect predictor lookups.")
 
  139         .
desc(
"Number of indirect target hits.")
 
  144         .
desc(
"Number of indirect misses.")
 
  148         .
name(
name() + 
"indirectMispredicted")
 
  149         .
desc(
"Number of mispredicted indirect branches.")
 
  188     bool pred_taken = 
false;
 
  194     void *bp_history = NULL;
 
  197         DPRINTF(Branch, 
"[tid:%i]: Unconditional control.\n", tid);
 
  203         pred_taken = 
lookup(tid, pc.instAddr(), bp_history);
 
  205         DPRINTF(Branch, 
"[tid:%i]: [sn:%i] Branch predictor" 
  206                 " predicted %i for PC %s\n", tid, seqNum,  pred_taken, pc);
 
  209     DPRINTF(Branch, 
"[tid:%i]: [sn:%i] Creating prediction history " 
  210             "for PC %s\n", tid, seqNum, pc);
 
  213                                     pred_taken, bp_history, tid);
 
  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]: Instruction %s is a return, " 
  233                     "RAS predicted target: %s, RAS index: %i.\n",
 
  234                     tid, pc, target, predict_record.RASIndex);
 
  240                 predict_record.pushedRAS = 
true;
 
  244                 predict_record.wasCall = 
true;
 
  246                 DPRINTF(Branch, 
"[tid:%i]: Instruction %s was a " 
  247                         "call, adding %s to the RAS index: %i.\n",
 
  248                         tid, pc, pc, 
RAS[tid].topIdx());
 
  253                 if (
BTB.
valid(pc.instAddr(), tid)) {
 
  259                     DPRINTF(Branch, 
"[tid:%i]: Instruction %s predicted" 
  260                             " target is %s.\n", tid, pc, target);
 
  263                     DPRINTF(Branch, 
"[tid:%i]: BTB doesn't have a " 
  264                             "valid entry.\n",tid);
 
  270                         btbUpdate(tid, pc.instAddr(), bp_history);
 
  271                         DPRINTF(Branch, 
"[tid:%i]:[sn:%i] btbUpdate" 
  272                                 " called for %s\n", tid, seqNum, pc);
 
  275                         predict_record.pushedRAS = 
false;
 
  280                 predict_record.wasIndirect = 
true;
 
  287                     DPRINTF(Branch, 
"[tid:%i]: Instruction %s predicted " 
  288                             "indirect target is %s.\n", tid, pc, target);
 
  292                     DPRINTF(Branch, 
"[tid:%i]: Instruction %s no indirect " 
  293                             "target.\n", tid, pc);
 
  298                         predict_record.pushedRAS = 
false;
 
  308            predict_record.wasReturn = 
true;
 
  315     predHist[tid].push_front(predict_record);
 
  317     DPRINTF(Branch, 
"[tid:%i]: [sn:%i]: History entry added." 
  318             "predHist.size(): %i\n", tid, seqNum, 
predHist[tid].
size());
 
  326     DPRINTF(Branch, 
"[tid:%i]: Committing branches until " 
  327             "[sn:%lli].\n", tid, done_sn);
 
  331            predHist[tid].back().seqNum <= done_sn) {
 
  335                     predHist[tid].back().bpHistory, 
false);
 
  347     while (!pred_hist.empty() &&
 
  348            pred_hist.front().seqNum > squashed_sn) {
 
  349         if (pred_hist.front().usedRAS) {
 
  350             DPRINTF(Branch, 
"[tid:%i]: Restoring top of RAS to: %i," 
  351                     " target: %s.\n", tid,
 
  352                     pred_hist.front().RASIndex, pred_hist.front().RASTarget);
 
  354             RAS[tid].restore(pred_hist.front().RASIndex,
 
  355                              pred_hist.front().RASTarget);
 
  356         } 
else if (pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
 
  358              DPRINTF(Branch, 
"[tid: %i] Squashing" 
  359                      "  Call [sn:%i] PC: %s Popping RAS\n", tid,
 
  360                      pred_hist.front().seqNum, pred_hist.front().pc);
 
  365         squash(tid, pred_hist.front().bpHistory);
 
  367         DPRINTF(Branch, 
"[tid:%i]: Removing history for [sn:%i] " 
  368                 "PC %s.\n", tid, pred_hist.front().seqNum,
 
  369                 pred_hist.front().pc);
 
  371         pred_hist.pop_front();
 
  373         DPRINTF(Branch, 
"[tid:%i]: predHist.size(): %i\n",
 
  399     DPRINTF(Branch, 
"[tid:%i]: Squashing from sequence number %i, " 
  400             "setting target to %s.\n", tid, squashed_sn, corrTarget);
 
  408     if (!pred_hist.empty()) {
 
  410         auto hist_it = pred_hist.begin();
 
  415         if (pred_hist.front().seqNum != squashed_sn) {
 
  416             DPRINTF(Branch, 
"Front sn %i != Squash sn %i\n",
 
  417                     pred_hist.front().seqNum, squashed_sn);
 
  419             assert(pred_hist.front().seqNum == squashed_sn);
 
  423         if ((*hist_it).usedRAS) {
 
  425             DPRINTF(Branch, 
"[tid:%i]: Incorrect RAS [sn:%i]\n",
 
  426                     tid, hist_it->seqNum);
 
  430         unsigned ghr = 
getGHR(tid, hist_it->bpHistory);
 
  442         pred_hist.front().predTaken = actually_taken;
 
  444         update(tid, (*hist_it).pc, actually_taken,
 
  445                pred_hist.front().bpHistory, 
true);
 
  447         if (actually_taken) {
 
  448             if (hist_it->wasReturn && !hist_it->usedRAS) {
 
  449                  DPRINTF(Branch, 
"[tid: %i] Incorrectly predicted" 
  450                          "  return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
 
  453                  hist_it->usedRAS = 
true;
 
  455             if (hist_it->wasIndirect) {
 
  459                 DPRINTF(Branch,
"[tid: %i] BTB Update called for [sn:%i]" 
  460                         " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
 
  462                 BTB.
update((*hist_it).pc, corrTarget, tid);
 
  466            if (hist_it->usedRAS) {
 
  467                 DPRINTF(Branch,
"[tid: %i] Incorrectly predicted" 
  468                         "  return [sn:%i] PC: %s Restoring RAS\n", tid,
 
  469                         hist_it->seqNum, hist_it->pc);
 
  470                 DPRINTF(Branch, 
"[tid:%i]: Restoring top of RAS" 
  471                         " to: %i, target: %s.\n", tid,
 
  472                         hist_it->RASIndex, hist_it->RASTarget);
 
  473                 RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
 
  474                 hist_it->usedRAS = 
false;
 
  475            } 
else if (hist_it->wasCall && hist_it->pushedRAS) {
 
  477                  DPRINTF(Branch, 
"[tid: %i] Incorrectly predicted" 
  478                          "  Call [sn:%i] PC: %s Popping RAS\n", tid,
 
  479                          hist_it->seqNum, hist_it->pc);
 
  481                  hist_it->pushedRAS = 
false;
 
  485         DPRINTF(Branch, 
"[tid:%i]: [sn:%i] pred_hist empty, can't " 
  486                 "update.\n", tid, squashed_sn);
 
  496             auto pred_hist_it = ph.begin();
 
  498             cprintf(
"predHist[%i].size(): %i\n", i++, ph.size());
 
  500             while (pred_hist_it != ph.end()) {
 
  501                 cprintf(
"[sn:%lli], PC:%#x, tid:%i, predTaken:%i, " 
  503                         pred_hist_it->seqNum, pred_hist_it->pc,
 
  504                         pred_hist_it->tid, pred_hist_it->predTaken,
 
  505                         pred_hist_it->bpHistory);
 
IndirectPredictor iPred
The indirect target predictor. 
 
Stats::Scalar indirectHits
Stat for the number of indirect target hits. 
 
const std::string & name()
 
Stats::Scalar BTBHits
Stat for number of BTB hits. 
 
Stats::Scalar usedRAS
Stat for number of times the RAS is used to get a target. 
 
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. ...
 
bool isUncondCtrl() const 
 
virtual void regStats()
Register statistics for this object. 
 
Stats::Scalar condIncorrect
Stat for number of conditional branches predicted incorrectly. 
 
Stats::Scalar BTBCorrect
Stat for number of times the BTB is correct. 
 
const bool useIndirect
Option to disable indirect predictor. 
 
void regProbePoints() override
Register probe points for this object. 
 
void drainSanityCheck() const 
Perform sanity checks after a drain. 
 
void commit(InstSeqNum seq_num, ThreadID tid)
 
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 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 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 advancePC(PCState &pc, const StaticInstPtr &inst)
 
void regStats() override
Registers statistics. 
 
PCState buildRetPC(const PCState &curPC, const PCState &callPC)
 
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. 
 
static const int NumArgumentRegs M5_VAR_USED
 
bool isDirectCtrl() const 
 
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. 
 
ProbePointArg generates a point for the class of Arg. 
 
virtual const std::string name() const 
 
void recordIndirect(Addr br_addr, Addr tgt_addr, InstSeqNum seq_num, ThreadID tid)
 
bool valid(Addr instPC, ThreadID tid)
Checks if a branch is in the BTB. 
 
GenericISA::SimplePCState< MachInst > PCState
 
ProbeManager * getProbeManager()
Get the probe manager for this object. 
 
void recordTarget(InstSeqNum seq_num, unsigned ghr, const TheISA::PCState &target, ThreadID tid)
 
Stats::Scalar indirectMispredicted
Stat for the number of indirect target mispredictions. 
 
BPredUnit(const Params *p)
 
bool lookup(Addr br_addr, unsigned ghr, TheISA::PCState &br_target, ThreadID tid)
 
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. 
 
void squash(InstSeqNum seq_num, ThreadID tid)
 
Stats::Scalar indirectLookups
Stat for the number of indirect target lookups. 
 
virtual unsigned getGHR(ThreadID tid, void *bp_history) const 
 
ProbePoints::PMUUPtr ppBranches
Branches seen by the branch predictor. 
 
Abstract superclass for simulation objects. 
 
Stats::Scalar lookups
Stat for number of BP lookups. 
 
void cprintf(const char *format, const Args &...args)