cpu: split LTAGE implementation into a base TAGE and a derived LTAGE
[gem5.git] / src / cpu / pred / bpred_unit.cc
index 04a05eaa48e57d87d1505eb3fbc05503ee1f15d3..05770cba9358ca6cc4e9812c81fa69d89bebf328 100644 (file)
@@ -80,6 +80,8 @@ BPredUnit::BPredUnit(const Params *params)
 void
 BPredUnit::regStats()
 {
+    SimObject::regStats();
+
     lookups
         .name(name() + ".lookups")
         .desc("Number of BP lookups")
@@ -143,7 +145,7 @@ BPredUnit::regStats()
         ;
 
     indirectMispredicted
-        .name(name() + "indirectMispredcited")
+        .name(name() + "indirectMispredicted")
         .desc("Number of mispredicted indirect branches.")
         ;
 
@@ -318,128 +320,6 @@ BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
     return pred_taken;
 }
 
-bool
-BPredUnit::predictInOrder(const StaticInstPtr &inst, const InstSeqNum &seqNum,
-                          int asid, TheISA::PCState &instPC,
-                          TheISA::PCState &predPC, ThreadID tid)
-{
-    // See if branch predictor predicts taken.
-    // If so, get its target addr either from the BTB or the RAS.
-    // Save off record of branch stuff so the RAS can be fixed
-    // up once it's done.
-
-    using TheISA::MachInst;
-
-    bool pred_taken = false;
-    TheISA::PCState target;
-
-    ++lookups;
-    ppBranches->notify(1);
-
-    DPRINTF(Branch, "[tid:%i] [sn:%i] %s ... PC %s doing branch "
-            "prediction\n", tid, seqNum,
-            inst->disassemble(instPC.instAddr()), instPC);
-
-    void *bp_history = NULL;
-
-    if (inst->isUncondCtrl()) {
-        DPRINTF(Branch, "[tid:%i] Unconditional control.\n", tid);
-        pred_taken = true;
-        // Tell the BP there was an unconditional branch.
-        uncondBranch(tid, instPC.instAddr(), bp_history);
-
-        if (inst->isReturn() && RAS[tid].empty()) {
-            DPRINTF(Branch, "[tid:%i] RAS is empty, predicting "
-                    "false.\n", tid);
-            pred_taken = false;
-        }
-    } else {
-        ++condPredicted;
-
-        pred_taken = lookup(tid, predPC.instAddr(), bp_history);
-    }
-
-    PredictorHistory predict_record(seqNum, predPC.instAddr(), pred_taken,
-                                    bp_history, tid);
-
-    // Now lookup in the BTB or RAS.
-    if (pred_taken) {
-        if (inst->isReturn()) {
-            ++usedRAS;
-
-            // If it's a function return call, then look up the address
-            // in the RAS.
-            TheISA::PCState rasTop = RAS[tid].top();
-            target = TheISA::buildRetPC(instPC, rasTop);
-
-            // Record the top entry of the RAS, and its index.
-            predict_record.usedRAS = true;
-            predict_record.RASIndex = RAS[tid].topIdx();
-            predict_record.RASTarget = rasTop;
-
-            assert(predict_record.RASIndex < 16);
-
-            RAS[tid].pop();
-
-            DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, "
-                    "RAS predicted target: %s, RAS index: %i.\n",
-                    tid, instPC, target,
-                    predict_record.RASIndex);
-        } else {
-            ++BTBLookups;
-
-            if (inst->isCall()) {
-
-                RAS[tid].push(instPC);
-                predict_record.pushedRAS = true;
-
-                // Record that it was a call so that the top RAS entry can
-                // be popped off if the speculation is incorrect.
-                predict_record.wasCall = true;
-
-                DPRINTF(Branch, "[tid:%i]: Instruction %s was a call"
-                        ", adding %s to the RAS index: %i.\n",
-                        tid, instPC, predPC,
-                        RAS[tid].topIdx());
-            }
-
-            if (inst->isCall() &&
-                inst->isUncondCtrl() &&
-                inst->isDirectCtrl()) {
-                target = inst->branchTarget(instPC);
-            } else if (BTB.valid(predPC.instAddr(), asid)) {
-                ++BTBHits;
-
-                // If it's not a return, use the BTB to get the target addr.
-                target = BTB.lookup(predPC.instAddr(), asid);
-
-                DPRINTF(Branch, "[tid:%i]: [asid:%i] Instruction %s "
-                        "predicted target is %s.\n",
-                        tid, asid, instPC, target);
-            } else {
-                DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
-                        "valid entry, predicting false.\n",tid);
-                pred_taken = false;
-            }
-        }
-    }
-
-    if (pred_taken) {
-        // Set the PC and the instruction's predicted target.
-        predPC = target;
-    }
-    DPRINTF(Branch, "[tid:%i]: [sn:%i]: Setting Predicted PC to %s.\n",
-            tid, seqNum, predPC);
-
-    predHist[tid].push_front(predict_record);
-
-    DPRINTF(Branch, "[tid:%i] [sn:%i] pushed onto front of predHist "
-            "...predHist.size(): %i\n",
-            tid, seqNum, predHist[tid].size());
-
-    return pred_taken;
-}
-
 void
 BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
 {
@@ -450,13 +330,9 @@ BPredUnit::update(const InstSeqNum &done_sn, ThreadID tid)
     while (!predHist[tid].empty() &&
            predHist[tid].back().seqNum <= done_sn) {
         // Update the branch predictor with the correct results.
-        if (!predHist[tid].back().wasSquashed) {
-            update(tid, predHist[tid].back().pc,
-                        predHist[tid].back().predTaken,
-                        predHist[tid].back().bpHistory, false);
-        } else {
-            retireSquashed(tid, predHist[tid].back().bpHistory);
-        }
+        update(tid, predHist[tid].back().pc,
+                    predHist[tid].back().predTaken,
+                    predHist[tid].back().bpHistory, false);
 
         predHist[tid].pop_back();
     }
@@ -550,12 +426,23 @@ BPredUnit::squash(const InstSeqNum &squashed_sn,
                     tid, hist_it->seqNum);
         }
 
-        // Have to get GHR here because the update deletes bpHistory
+        // Get the underlying Global History Register
         unsigned ghr = getGHR(tid, hist_it->bpHistory);
 
+        // There are separate functions for in-order and out-of-order
+        // branch prediction, but not for update. Therefore, this
+        // call should take into account that the mispredicted branch may
+        // be on the wrong path (i.e., OoO execution), and that the counter
+        // counter table(s) should not be updated. Thus, this call should
+        // restore the state of the underlying predictor, for instance the
+        // local/global histories. The counter tables will be updated when
+        // the branch actually commits.
+
+        // Remember the correct direction for the update at commit.
+        pred_hist.front().predTaken = actually_taken;
+
         update(tid, (*hist_it).pc, actually_taken,
                pred_hist.front().bpHistory, true);
-        hist_it->wasSquashed = true;
 
         if (actually_taken) {
             if (hist_it->wasReturn && !hist_it->usedRAS) {