Merge ktlim@zizzer:/bk/m5
[gem5.git] / src / cpu / o3 / bpred_unit_impl.hh
index 8d16a0cdf0b8d2bc7a061c7dd99922eb7a6dc7dc..c37df606bdfa8a19186b011643876f76e33f4126 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <list>
+#include <vector>
+
 #include "base/trace.hh"
 #include "base/traceflags.hh"
 #include "cpu/o3/bpred_unit.hh"
 
+using namespace std;
+
 template<class Impl>
-TwobitBPredUnit<Impl>::TwobitBPredUnit(Params &params)
-  : BP(params.local_predictor_size,
-       params.local_ctr_bits,
-       params.instShiftAmt),
-    BTB(params.BTBEntries,
-        params.BTBTagSize,
-        params.instShiftAmt),
-    RAS(params.RASSize)
+TwobitBPredUnit<Impl>::TwobitBPredUnit(Params *params)
+  : BP(params->localPredictorSize,
+       params->localCtrBits,
+       params->instShiftAmt),
+    BTB(params->BTBEntries,
+        params->BTBTagSize,
+        params->instShiftAmt)
 {
+    for (int i=0; i < Impl::MaxThreads; i++)
+        RAS[i].init(params->RASSize);
 }
 
 template <class Impl>
@@ -79,7 +85,7 @@ TwobitBPredUnit<Impl>::regStats()
 
     usedRAS
         .name(name() + ".BPredUnit.usedRAS")
-        .desc("Number of times the RAS was used.")
+        .desc("Number of times the RAS was used to get a target.")
         ;
 
     RASIncorrect
@@ -88,9 +94,31 @@ TwobitBPredUnit<Impl>::regStats()
         ;
 }
 
+template <class Impl>
+void
+TwobitBPredUnit<Impl>::switchOut()
+{
+    for (int i = 0; i < Impl::MaxThreads; ++i) {
+        predHist[i].clear();
+    }
+}
+
+template <class Impl>
+void
+TwobitBPredUnit<Impl>::takeOverFrom()
+{
+/*
+    for (int i = 0; i < Impl::MaxThreads; ++i)
+        RAS[i].reset();
+
+    BP.reset();
+    BTB.reset();
+*/
+}
+
 template <class Impl>
 bool
-TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC)
+TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC, unsigned tid)
 {
     // See if branch predictor predicts taken.
     // If so, get its target addr either from the BTB or the RAS.
@@ -106,18 +134,19 @@ TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC)
     ++lookups;
 
     if (inst->isUncondCtrl()) {
-        DPRINTF(Fetch, "BranchPred: Unconditional control.\n");
+        DPRINTF(Fetch, "BranchPred: [tid:%i] Unconditional control.\n", tid);
         pred_taken = true;
     } else {
         ++condPredicted;
 
         pred_taken = BPLookup(PC);
 
-        DPRINTF(Fetch, "BranchPred: Branch predictor predicted %i for PC %#x"
-                "\n", pred_taken, inst->readPC());
+        DPRINTF(Fetch, "BranchPred: [tid:%i]: Branch predictor predicted %i "
+                "for PC %#x\n",
+                tid, pred_taken, inst->readPC());
     }
 
-    PredictorHistory predict_record(inst->seqNum, PC, pred_taken);
+    PredictorHistory predict_record(inst->seqNum, PC, pred_taken, tid);
 
     // Now lookup in the BTB or RAS.
     if (pred_taken) {
@@ -126,45 +155,48 @@ TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC)
 
             // If it's a function return call, then look up the address
             // in the RAS.
-            target = RAS.top();
+            target = RAS[tid].top();
 
             // Record the top entry of the RAS, and its index.
             predict_record.usedRAS = true;
-            predict_record.RASIndex = RAS.topIdx();
+            predict_record.RASIndex = RAS[tid].topIdx();
             predict_record.RASTarget = target;
 
-            RAS.pop();
+            assert(predict_record.RASIndex < 16);
 
-            DPRINTF(Fetch, "BranchPred: Instruction %#x is a return, RAS "
-                    "predicted target: %#x, RAS index: %i.\n",
-                    inst->readPC(), target, predict_record.RASIndex);
+            RAS[tid].pop();
+
+            DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x is a return, "
+                    "RAS predicted target: %#x, RAS index: %i.\n",
+                    tid, inst->readPC(), target, predict_record.RASIndex);
         } else {
             ++BTBLookups;
 
             if (inst->isCall()) {
-                RAS.push(PC+sizeof(MachInst));
+                RAS[tid].push(PC + sizeof(MachInst));
 
                 // 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(Fetch, "BranchPred: Instruction %#x was a call, "
-                        "adding %#x to the RAS.\n",
-                        inst->readPC(), PC+sizeof(MachInst));
+                DPRINTF(Fetch, "BranchPred: [tid:%i] Instruction %#x was a call"
+                        "adding %#x to the RAS.\n",
+                        tid, inst->readPC(), PC + sizeof(MachInst));
             }
 
-            if (BTB.valid(PC)) {
+            if (BTB.valid(PC, tid)) {
                 ++BTBHits;
 
                 //If it's anything else, use the BTB to get the target addr.
-                target = BTB.lookup(PC);
+                target = BTB.lookup(PC, tid);
 
-                DPRINTF(Fetch, "BranchPred: Instruction %#x predicted target "
-                        "is %#x.\n", inst->readPC(), target);
+                DPRINTF(Fetch, "BranchPred: [tid:%i]: Instruction %#x predicted"
+                        " target is %#x.\n",
+                        tid, inst->readPC(), target);
 
             } else {
-                DPRINTF(Fetch, "BranchPred: BTB doesn't have a valid entry."
-                        "\n");
+                DPRINTF(Fetch, "BranchPred: [tid:%i]: BTB doesn't have a "
+                        "valid entry.\n",tid);
                 pred_taken = false;
             }
 
@@ -180,97 +212,113 @@ TwobitBPredUnit<Impl>::predict(DynInstPtr &inst, Addr &PC)
         inst->setPredTarg(PC);
     }
 
-    predHist.push_front(predict_record);
+    predHist[tid].push_front(predict_record);
 
-    assert(!predHist.empty());
+    DPRINTF(Fetch, "[tid:%i] predHist.size(): %i\n", tid, predHist[tid].size());
 
     return pred_taken;
 }
 
 template <class Impl>
 void
-TwobitBPredUnit<Impl>::update(const InstSeqNum &done_sn)
+TwobitBPredUnit<Impl>::update(const InstSeqNum &done_sn, unsigned tid)
 {
-    DPRINTF(Fetch, "BranchPred: Commiting branches until sequence number "
-            "%i.\n", done_sn);
-
-    while (!predHist.empty() && predHist.back().seqNum <= done_sn) {
-        assert(!predHist.empty());
+    DPRINTF(Fetch, "BranchPred: [tid:%i]: Commiting branches until sequence"
+            "number %lli.\n", tid, done_sn);
 
-        // Update the branch predictor with the correct results of branches.
-        BP.update(predHist.back().PC, predHist.back().predTaken);
+    while (!predHist[tid].empty() &&
+           predHist[tid].back().seqNum <= done_sn) {
+        // Update the branch predictor with the correct results.
+        BP.update(predHist[tid].back().PC,
+                  predHist[tid].back().predTaken);
 
-        predHist.pop_back();
+        predHist[tid].pop_back();
     }
 }
 
 template <class Impl>
 void
-TwobitBPredUnit<Impl>::squash(const InstSeqNum &squashed_sn)
+TwobitBPredUnit<Impl>::squash(const InstSeqNum &squashed_sn, unsigned tid)
 {
-    while (!predHist.empty() && predHist.front().seqNum > squashed_sn) {
-        if (predHist.front().usedRAS) {
-            DPRINTF(Fetch, "BranchPred: Restoring top of RAS to: %i, "
-                    "target: %#x.\n",
-                    predHist.front().RASIndex,
-                    predHist.front().RASTarget);
+    History &pred_hist = predHist[tid];
+
+    while (!pred_hist.empty() &&
+           pred_hist.front().seqNum > squashed_sn) {
+       if (pred_hist.front().usedRAS) {
+            DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i,"
+                    " target: %#x.\n",
+                    tid,
+                    pred_hist.front().RASIndex,
+                    pred_hist.front().RASTarget);
+
+            RAS[tid].restore(pred_hist.front().RASIndex,
+                             pred_hist.front().RASTarget);
 
-            RAS.restore(predHist.front().RASIndex,
-                        predHist.front().RASTarget);
-        } else if (predHist.front().wasCall) {
-            DPRINTF(Fetch, "BranchPred: Removing speculative entry added "
-                    "to the RAS.\n");
+        } else if (pred_hist.front().wasCall) {
+            DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing speculative entry added "
+                    "to the RAS.\n",tid);
 
-            RAS.pop();
+            RAS[tid].pop();
         }
 
-        predHist.pop_front();
+        pred_hist.pop_front();
     }
+
 }
 
 template <class Impl>
 void
 TwobitBPredUnit<Impl>::squash(const InstSeqNum &squashed_sn,
                               const Addr &corr_target,
-                              const bool actually_taken)
+                              const bool actually_taken,
+                              unsigned tid)
 {
     // Now that we know that a branch was mispredicted, we need to undo
     // all the branches that have been seen up until this branch and
     // fix up everything.
 
+    History &pred_hist = predHist[tid];
+
     ++condIncorrect;
 
-    DPRINTF(Fetch, "BranchPred: Squashing from sequence number %i, "
+    DPRINTF(Fetch, "BranchPred: [tid:%i]: Squashing from sequence number %i, "
             "setting target to %#x.\n",
-            squashed_sn, corr_target);
-
-    while (!predHist.empty() && predHist.front().seqNum > squashed_sn) {
+            tid, squashed_sn, corr_target);
 
-        if (predHist.front().usedRAS) {
-            DPRINTF(Fetch, "BranchPred: Restoring top of RAS to: %i, "
+    while (!pred_hist.empty() &&
+           pred_hist.front().seqNum > squashed_sn) {
+        if (pred_hist.front().usedRAS) {
+            DPRINTF(Fetch, "BranchPred: [tid:%i]: Restoring top of RAS to: %i, "
                     "target: %#x.\n",
-                    predHist.front().RASIndex,
-                    predHist.front().RASTarget);
+                    tid,
+                    pred_hist.front().RASIndex,
+                    pred_hist.front().RASTarget);
 
-            RAS.restore(predHist.front().RASIndex,
-                        predHist.front().RASTarget);
-        } else if (predHist.front().wasCall) {
-            DPRINTF(Fetch, "BranchPred: Removing speculative entry added "
-                    "to the RAS.\n");
+            RAS[tid].restore(pred_hist.front().RASIndex,
+                             pred_hist.front().RASTarget);
+        } else if (pred_hist.front().wasCall) {
+            DPRINTF(Fetch, "BranchPred: [tid:%i]: Removing speculative entry"
+                    " added to the RAS.\n", tid);
 
-            RAS.pop();
+            RAS[tid].pop();
         }
 
-        predHist.pop_front();
+        pred_hist.pop_front();
     }
 
-    predHist.front().predTaken = actually_taken;
+    // If there's a squash due to a syscall, there may not be an entry
+    // corresponding to the squash.  In that case, don't bother trying to
+    // fix up the entry.
+    if (!pred_hist.empty()) {
+        pred_hist.front().predTaken = actually_taken;
 
-    if (predHist.front().usedRAS) {
-        ++RASIncorrect;
-    }
+        if (pred_hist.front().usedRAS) {
+            ++RASIncorrect;
+        }
 
-    BP.update(predHist.front().PC, actually_taken);
+        BP.update(pred_hist.front().PC, actually_taken);
 
-    BTB.update(predHist.front().PC, corr_target);
+        BTB.update(pred_hist.front().PC, corr_target, tid);
+        pred_hist.pop_front();
+    }
 }