cpu: re-organizes the branch predictor structure.
authorDibakar Gope <gope@wisc.edu>
Mon, 13 Apr 2015 22:33:57 +0000 (17:33 -0500)
committerDibakar Gope <gope@wisc.edu>
Mon, 13 Apr 2015 22:33:57 +0000 (17:33 -0500)
Committed by: Nilay Vaish <nilay@cs.wisc.edu>

16 files changed:
configs/common/O3_ARM_v7a.py
src/cpu/inorder/InOrderCPU.py
src/cpu/minor/MinorCPU.py
src/cpu/o3/O3CPU.py
src/cpu/pred/2bit_local.cc
src/cpu/pred/2bit_local.hh
src/cpu/pred/BranchPredictor.py
src/cpu/pred/SConscript
src/cpu/pred/bi_mode.cc
src/cpu/pred/bi_mode.hh
src/cpu/pred/bpred_unit.cc
src/cpu/pred/bpred_unit.hh
src/cpu/pred/bpred_unit_impl.hh [deleted file]
src/cpu/pred/tournament.cc
src/cpu/pred/tournament.hh
src/cpu/simple/BaseSimpleCPU.py

index b3607c518492b1f2d5b0abc3cece43cac262b02c..7d4987d7f2180392d29ea6931a869f6fb9dcd4ba 100644 (file)
@@ -88,8 +88,7 @@ class O3_ARM_v7a_FUP(FUPool):
               O3_ARM_v7a_Load(), O3_ARM_v7a_Store(), O3_ARM_v7a_FP()]
 
 # Bi-Mode Branch Predictor
-class O3_ARM_v7a_BP(BranchPredictor):
-    predType = "bi-mode"
+class O3_ARM_v7a_BP(BiModeBP):
     globalPredictorSize = 8192
     globalCtrBits = 2
     choicePredictorSize = 8192
index 920b9cdc13bedca9714f9cff2520f40585f74c2c..dddcbbcec6a6a9a4ff0b5dbd4c7a0ada8e46c5f4 100644 (file)
@@ -29,7 +29,7 @@
 from m5.params import *
 from m5.proxy import *
 from BaseCPU import BaseCPU
-from BranchPredictor import BranchPredictor
+from BranchPredictor import *
 
 class ThreadModel(Enum):
     vals = ['Single', 'SMT', 'SwitchOnCacheMiss']
@@ -72,6 +72,6 @@ class InOrderCPU(BaseCPU):
     div32Latency = Param.Cycles(1, "Latency for 32-bit Divide Operations")
     div32RepeatRate = Param.Cycles(1, "Repeat Rate for 32-bit Divide Operations")
 
-    branchPred = Param.BranchPredictor(BranchPredictor(numThreads =
+    branchPred = Param.BranchPredictor(TournamentBP(numThreads =
                                                        Parent.numThreads),
                                        "Branch Predictor")
index 07953cf5a14023399d88c38363f3c360480cdb0e..9ab7b0b39e00a453c4e75521c9f3eae1cc618185 100644 (file)
@@ -46,7 +46,7 @@ from m5.proxy import *
 from m5.SimObject import SimObject
 from BaseCPU import BaseCPU
 from DummyChecker import DummyChecker
-from BranchPredictor import BranchPredictor
+from BranchPredictor import *
 from TimingExpr import TimingExpr
 
 from FuncUnit import OpClass
@@ -266,7 +266,7 @@ class MinorCPU(BaseCPU):
     enableIdling = Param.Bool(True,
         "Enable cycle skipping when the processor is idle\n");
 
-    branchPred = Param.BranchPredictor(BranchPredictor(
+    branchPred = Param.BranchPredictor(TournamentBP(
         numThreads = Parent.numThreads), "Branch Predictor")
 
     def addCheckerCpu(self):
index 1b25b2e7bbba06a470dd01f9e527521d621d5369..92f96a3b634afe0c4f3b1e9d3530cb2a27eb5124 100644 (file)
@@ -32,7 +32,7 @@ from m5.proxy import *
 from BaseCPU import BaseCPU
 from FUPool import *
 from O3Checker import O3Checker
-from BranchPredictor import BranchPredictor
+from BranchPredictor import *
 
 class DerivO3CPU(BaseCPU):
     type = 'DerivO3CPU'
@@ -139,7 +139,7 @@ class DerivO3CPU(BaseCPU):
     smtROBThreshold = Param.Int(100, "SMT ROB Threshold Sharing Parameter")
     smtCommitPolicy = Param.String('RoundRobin', "SMT Commit Policy")
 
-    branchPred = Param.BranchPredictor(BranchPredictor(numThreads =
+    branchPred = Param.BranchPredictor(TournamentBP(numThreads =
                                                        Parent.numThreads),
                                        "Branch Predictor")
     needsTSO = Param.Bool(buildEnv['TARGET_ISA'] == 'x86',
index 0fd0a10d3b53360bd3549d37684d5a193f64799e..36ca1593e57432728eef71292b4d5d19fcc03eb9 100644 (file)
 #include "cpu/pred/2bit_local.hh"
 #include "debug/Fetch.hh"
 
-LocalBP::LocalBP(const Params *params)
+LocalBP::LocalBP(const LocalBPParams *params)
     : BPredUnit(params),
       localPredictorSize(params->localPredictorSize),
-      localCtrBits(params->localCtrBits),
-      instShiftAmt(params->instShiftAmt)
+      localCtrBits(params->localCtrBits)
 {
     if (!isPowerOf2(localPredictorSize)) {
         fatal("Invalid local predictor size!\n");
@@ -153,6 +152,12 @@ LocalBP::getLocalIndex(Addr &branch_addr)
 }
 
 void
-LocalBP::uncondBranch(void *&bp_history)
+LocalBP::uncondBranch(Addr pc, void *&bp_history)
 {
 }
+
+LocalBP*
+LocalBPParams::create()
+{
+    return new LocalBP(this);
+}
index e008c62327431a45e51dcf2ad934e4f5f468355c..61e2dc24e9853fa1d7f2e8086707e9e1b7b0186d 100644 (file)
@@ -49,6 +49,7 @@
 #include "base/types.hh"
 #include "cpu/pred/bpred_unit.hh"
 #include "cpu/pred/sat_counter.hh"
+#include "params/LocalBP.hh"
 
 /**
  * Implements a local predictor that uses the PC to index into a table of
@@ -63,9 +64,9 @@ class LocalBP : public BPredUnit
     /**
      * Default branch predictor constructor.
      */
-    LocalBP(const Params *params);
+    LocalBP(const LocalBPParams *params);
 
-    virtual void uncondBranch(void * &bp_history);
+    virtual void uncondBranch(Addr pc, void * &bp_history);
 
     /**
      * Looks up the given address in the branch predictor and returns
@@ -124,9 +125,6 @@ class LocalBP : public BPredUnit
     /** Number of bits of the local predictor's counters. */
     unsigned localCtrBits;
 
-    /** Number of bits to shift the PC when calculating index. */
-    unsigned instShiftAmt;
-
     /** Mask to get index bits. */
     unsigned indexMask;
 };
index 1bdc71d4d1fbfceafa9f0e9b638e638caf0a3088..5c52fb65e402090110db3f3362a0748ca206e746 100644 (file)
@@ -1,4 +1,5 @@
 # Copyright (c) 2012 Mark D. Hill and David A. Wood
+# Copyright (c) 2015 The University of Wisconsin
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -24,7 +25,7 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
-# Authors: Nilay Vaish
+# Authors: Nilay Vaish and Dibakar Gope
 
 from m5.SimObject import SimObject
 from m5.params import *
@@ -33,20 +34,45 @@ class BranchPredictor(SimObject):
     type = 'BranchPredictor'
     cxx_class = 'BPredUnit'
     cxx_header = "cpu/pred/bpred_unit.hh"
+    abstract = True
 
     numThreads = Param.Unsigned(1, "Number of threads")
-    predType = Param.String("tournament",
-        "Branch predictor type ('local', 'tournament', 'bi-mode')")
+    BTBEntries = Param.Unsigned(4096, "Number of BTB entries")
+    BTBTagSize = Param.Unsigned(16, "Size of the BTB tags, in bits")
+    RASSize = Param.Unsigned(16, "RAS size")
+    instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by")
+
+
+class LocalBP(BranchPredictor):
+    type = 'LocalBP'
+    cxx_class = 'LocalBP'
+    cxx_header = "cpu/pred/2bit_local.hh"
+
+    localPredictorSize = Param.Unsigned(2048, "Size of local predictor")
+    localCtrBits = Param.Unsigned(2, "Bits per counter")
+
+
+class TournamentBP(BranchPredictor):
+    type = 'TournamentBP'
+    cxx_class = 'TournamentBP'
+    cxx_header = "cpu/pred/tournament.hh"
+
     localPredictorSize = Param.Unsigned(2048, "Size of local predictor")
     localCtrBits = Param.Unsigned(2, "Bits per counter")
-    localHistoryTableSize = Param.Unsigned(2048, "Size of local history table")
+    localHistoryTableSize = Param.Unsigned(2048, "size of local history table")
     globalPredictorSize = Param.Unsigned(8192, "Size of global predictor")
     globalCtrBits = Param.Unsigned(2, "Bits per counter")
     choicePredictorSize = Param.Unsigned(8192, "Size of choice predictor")
     choiceCtrBits = Param.Unsigned(2, "Bits of choice counters")
 
-    BTBEntries = Param.Unsigned(4096, "Number of BTB entries")
-    BTBTagSize = Param.Unsigned(16, "Size of the BTB tags, in bits")
 
-    RASSize = Param.Unsigned(16, "RAS size")
-    instShiftAmt = Param.Unsigned(2, "Number of bits to shift instructions by")
+class BiModeBP(BranchPredictor):
+    type = 'BiModeBP'
+    cxx_class = 'BiModeBP'
+    cxx_header = "cpu/pred/bi_mode.hh"
+
+    globalPredictorSize = Param.Unsigned(8192, "Size of global predictor")
+    globalCtrBits = Param.Unsigned(2, "Bits per counter")
+    choicePredictorSize = Param.Unsigned(8192, "Size of choice predictor")
+    choiceCtrBits = Param.Unsigned(2, "Bits of choice counters")
+
index 763f3a9b6412c0f50003b06990b3ff928d5106cb..1bf94712d1fccacc644a49a839785182083ba639 100644 (file)
@@ -43,3 +43,4 @@ Source('tournament.cc')
 Source ('bi_mode.cc')
 DebugFlag('FreeList')
 DebugFlag('Branch')
+DebugFlag('LTage')
index 604afee55dbcee661c77b85ff7615530b05e695f..c2a41cd4da06f2fa50043804624816833b10e6ca 100644 (file)
@@ -36,8 +36,8 @@
 #include "base/intmath.hh"
 #include "cpu/pred/bi_mode.hh"
 
-BiModeBP::BiModeBP(const Params *params)
-    : BPredUnit(params), instShiftAmt(params->instShiftAmt),
+BiModeBP::BiModeBP(const BiModeBPParams *params)
+    : BPredUnit(params),
       globalHistoryReg(0),
       globalHistoryBits(ceilLog2(params->globalPredictorSize)),
       choicePredictorSize(params->choicePredictorSize),
@@ -77,7 +77,7 @@ BiModeBP::BiModeBP(const Params *params)
  * chooses the taken array and the taken array predicts taken.
  */
 void
-BiModeBP::uncondBranch(void * &bpHistory)
+BiModeBP::uncondBranch(Addr pc, void * &bpHistory)
 {
     BPHistory *history = new BPHistory;
     history->globalHistoryReg = globalHistoryReg;
@@ -243,3 +243,9 @@ BiModeBP::updateGlobalHistReg(bool taken)
                                (globalHistoryReg << 1);
     globalHistoryReg &= historyRegisterMask;
 }
+
+BiModeBP*
+BiModeBPParams::create()
+{
+    return new BiModeBP(this);
+}
index a412d63cf59135d1153f46409b27f798ca1529d2..da7c49f46023c2682cceb63446add9fa69cdaf2b 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "cpu/pred/bpred_unit.hh"
 #include "cpu/pred/sat_counter.hh"
+#include "params/BiModeBP.hh"
 
 /**
  * Implements a bi-mode branch predictor. The bi-mode predictor is a two-level
@@ -55,8 +56,8 @@
 class BiModeBP : public BPredUnit
 {
   public:
-    BiModeBP(const Params *params);
-    void uncondBranch(void * &bp_history);
+    BiModeBP(const BiModeBPParams *params);
+    void uncondBranch(Addr pc, void * &bp_history);
     void squash(void *bp_history);
     bool lookup(Addr branch_addr, void * &bp_history);
     void btbUpdate(Addr branch_addr, void * &bp_history);
@@ -93,8 +94,6 @@ class BiModeBP : public BPredUnit
     // not-taken direction predictors
     std::vector<SatCounter> notTakenCounters;
 
-    unsigned instShiftAmt;
-
     unsigned globalHistoryReg;
     unsigned globalHistoryBits;
     unsigned historyRegisterMask;
index 585f7c2d89c73ba328543c34aff5f1398089a35c..a5e1ffd599d2956b8e4a3c48c75040f9c69af5c0 100644 (file)
@@ -1,7 +1,19 @@
 /*
- * Copyright (c) 2004-2006 The Regents of The University of Michigan
+ * Copyright (c) 2011-2012, 2014 ARM Limited
  * Copyright (c) 2010 The University of Edinburgh
  * Copyright (c) 2012 Mark D. Hill and David A. Wood
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder.  You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Kevin Lim
- *          Timothy M. Jones
  */
 
-#include "cpu/pred/2bit_local.hh"
-#include "cpu/pred/bi_mode.hh"
-#include "cpu/pred/bpred_unit_impl.hh"
-#include "cpu/pred/tournament.hh"
-
-BPredUnit *
-BranchPredictorParams::create()
-{
-    // Setup the selected predictor.
-    if (predType == "local") {
-        return new LocalBP(this);
-    } else if (predType == "tournament") {
-        return new TournamentBP(this);
-    } else if (predType == "bi-mode") {
-        return new BiModeBP(this);
+#include "cpu/pred/bpred_unit.hh"
+
+#include <algorithm>
+
+#include "arch/isa_traits.hh"
+#include "arch/types.hh"
+#include "arch/utility.hh"
+#include "base/trace.hh"
+#include "config/the_isa.hh"
+#include "debug/Branch.hh"
+
+BPredUnit::BPredUnit(const Params *params)
+    : SimObject(params),
+      numThreads(params->numThreads),
+      predHist(numThreads),
+      BTB(params->BTBEntries,
+          params->BTBTagSize,
+          params->instShiftAmt),
+      RAS(numThreads),
+      instShiftAmt(params->instShiftAmt)
+{
+    for (auto& r : RAS)
+        r.init(params->RASSize);
+}
+
+void
+BPredUnit::regStats()
+{
+    lookups
+        .name(name() + ".lookups")
+        .desc("Number of BP lookups")
+        ;
+
+    condPredicted
+        .name(name() + ".condPredicted")
+        .desc("Number of conditional branches predicted")
+        ;
+
+    condIncorrect
+        .name(name() + ".condIncorrect")
+        .desc("Number of conditional branches incorrect")
+        ;
+
+    BTBLookups
+        .name(name() + ".BTBLookups")
+        .desc("Number of BTB lookups")
+        ;
+
+    BTBHits
+        .name(name() + ".BTBHits")
+        .desc("Number of BTB hits")
+        ;
+
+    BTBCorrect
+        .name(name() + ".BTBCorrect")
+        .desc("Number of correct BTB predictions (this stat may not "
+              "work properly.")
+        ;
+
+    BTBHitPct
+        .name(name() + ".BTBHitPct")
+        .desc("BTB Hit Percentage")
+        .precision(6);
+    BTBHitPct = (BTBHits / BTBLookups) * 100;
+
+    usedRAS
+        .name(name() + ".usedRAS")
+        .desc("Number of times the RAS was used to get a target.")
+        ;
+
+    RASIncorrect
+        .name(name() + ".RASInCorrect")
+        .desc("Number of incorrect RAS predictions.")
+        ;
+}
+
+ProbePoints::PMUUPtr
+BPredUnit::pmuProbePoint(const char *name)
+{
+    ProbePoints::PMUUPtr ptr;
+    ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
+
+    return ptr;
+}
+
+void
+BPredUnit::regProbePoints()
+{
+    ppBranches = pmuProbePoint("Branches");
+    ppMisses = pmuProbePoint("Misses");
+}
+
+void
+BPredUnit::drainSanityCheck() const
+{
+    // We shouldn't have any outstanding requests when we resume from
+    // a drained system.
+    for (const auto& ph M5_VAR_USED : predHist)
+        assert(ph.empty());
+}
+
+bool
+BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
+                   TheISA::PCState &pc, 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.
+
+    bool pred_taken = false;
+    TheISA::PCState target = pc;
+
+    ++lookups;
+    ppBranches->notify(1);
+
+    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(pc.instAddr(), bp_history);
+    } else {
+        ++condPredicted;
+        pred_taken = lookup(pc.instAddr(), bp_history);
+
+        DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
+                " predicted %i for PC %s\n", tid, seqNum,  pred_taken, pc);
+    }
+
+    DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history "
+            "for PC %s\n", tid, seqNum, pc);
+
+    PredictorHistory predict_record(seqNum, pc.instAddr(),
+                                    pred_taken, bp_history, tid);
+
+    // Now lookup in the BTB or RAS.
+    if (pred_taken) {
+        if (inst->isReturn()) {
+            ++usedRAS;
+            predict_record.wasReturn = true;
+            // If it's a function return call, then look up the address
+            // in the RAS.
+            TheISA::PCState rasTop = RAS[tid].top();
+            target = TheISA::buildRetPC(pc, 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;
+
+            RAS[tid].pop();
+
+            DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, "
+                    "RAS predicted target: %s, RAS index: %i.\n",
+                    tid, pc, target, predict_record.RASIndex);
+        } else {
+            ++BTBLookups;
+
+            if (inst->isCall()) {
+                RAS[tid].push(pc);
+                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, pc, pc, RAS[tid].topIdx());
+            }
+
+            if (BTB.valid(pc.instAddr(), tid)) {
+                ++BTBHits;
+
+                // If it's not a return, use the BTB to get the target addr.
+                target = BTB.lookup(pc.instAddr(), tid);
+
+                DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
+                        " target is %s.\n", tid, pc, target);
+
+            } else {
+                DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
+                        "valid entry.\n",tid);
+                pred_taken = false;
+                // The Direction of the branch predictor is altered because the
+                // BTB did not have an entry
+                // The predictor needs to be updated accordingly
+                if (!inst->isCall() && !inst->isReturn()) {
+                      btbUpdate(pc.instAddr(), bp_history);
+                      DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
+                              " called for %s\n", tid, seqNum, pc);
+                } else if (inst->isCall() && !inst->isUncondCtrl()) {
+                      RAS[tid].pop();
+                      predict_record.pushedRAS = false;
+                }
+                TheISA::advancePC(target, inst);
+            }
+        }
     } else {
-        fatal("Invalid BP selected!");
+        if (inst->isReturn()) {
+           predict_record.wasReturn = true;
+        }
+        TheISA::advancePC(target, inst);
     }
+
+    pc = target;
+
+    predHist[tid].push_front(predict_record);
+
+    DPRINTF(Branch, "[tid:%i]: [sn:%i]: History entry added."
+            "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
+
+    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(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(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)
+{
+    DPRINTF(Branch, "[tid:%i]: Committing branches until "
+            "[sn:%lli].\n", tid, done_sn);
+
+    while (!predHist[tid].empty() &&
+           predHist[tid].back().seqNum <= done_sn) {
+        // Update the branch predictor with the correct results.
+        if (!predHist[tid].back().wasSquashed) {
+            update(predHist[tid].back().pc, predHist[tid].back().predTaken,
+                predHist[tid].back().bpHistory, false);
+        } else {
+            retireSquashed(predHist[tid].back().bpHistory);
+        }
+
+        predHist[tid].pop_back();
+    }
+}
+
+void
+BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
+{
+    History &pred_hist = predHist[tid];
+
+    while (!pred_hist.empty() &&
+           pred_hist.front().seqNum > squashed_sn) {
+        if (pred_hist.front().usedRAS) {
+            DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i,"
+                    " target: %s.\n", tid,
+                    pred_hist.front().RASIndex, pred_hist.front().RASTarget);
+
+            RAS[tid].restore(pred_hist.front().RASIndex,
+                             pred_hist.front().RASTarget);
+        } else if(pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
+             // Was a call but predicated false. Pop RAS here
+             DPRINTF(Branch, "[tid: %i] Squashing"
+                     "  Call [sn:%i] PC: %s Popping RAS\n", tid,
+                     pred_hist.front().seqNum, pred_hist.front().pc);
+             RAS[tid].pop();
+        }
+
+        // This call should delete the bpHistory.
+        squash(pred_hist.front().bpHistory);
+
+        DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
+                "PC %s.\n", tid, pred_hist.front().seqNum,
+                pred_hist.front().pc);
+
+        pred_hist.pop_front();
+
+        DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n",
+                tid, predHist[tid].size());
+    }
+}
+
+void
+BPredUnit::squash(const InstSeqNum &squashed_sn,
+                  const TheISA::PCState &corrTarget,
+                  bool actually_taken, ThreadID 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.
+    // NOTE: This should be call conceivably in 2 scenarios:
+    // (1) After an branch is executed, it updates its status in the ROB
+    //     The commit stage then checks the ROB update and sends a signal to
+    //     the fetch stage to squash history after the mispredict
+    // (2) In the decode stage, you can find out early if a unconditional
+    //     PC-relative, branch was predicted incorrectly. If so, a signal
+    //     to the fetch stage is sent to squash history after the mispredict
+
+    History &pred_hist = predHist[tid];
+
+    ++condIncorrect;
+    ppMisses->notify(1);
+
+    DPRINTF(Branch, "[tid:%i]: Squashing from sequence number %i, "
+            "setting target to %s.\n", tid, squashed_sn, corrTarget);
+
+    // Squash All Branches AFTER this mispredicted branch
+    squash(squashed_sn, tid);
+
+    // 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()) {
+
+        auto hist_it = pred_hist.begin();
+        //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(),
+        //                       squashed_sn);
+
+        //assert(hist_it != pred_hist.end());
+        if (pred_hist.front().seqNum != squashed_sn) {
+            DPRINTF(Branch, "Front sn %i != Squash sn %i\n",
+                    pred_hist.front().seqNum, squashed_sn);
+
+            assert(pred_hist.front().seqNum == squashed_sn);
+        }
+
+
+        if ((*hist_it).usedRAS) {
+            ++RASIncorrect;
+        }
+
+        update((*hist_it).pc, actually_taken,
+               pred_hist.front().bpHistory, true);
+        hist_it->wasSquashed = true;
+
+        if (actually_taken) {
+            if (hist_it->wasReturn && !hist_it->usedRAS) {
+                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
+                         "  return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
+                         hist_it->pc);
+                 RAS[tid].pop();
+                 hist_it->usedRAS = true;
+            }
+
+            DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]"
+                    " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
+
+            BTB.update((*hist_it).pc, corrTarget, tid);
+
+        } else {
+           //Actually not Taken
+           if (hist_it->usedRAS) {
+                DPRINTF(Branch,"[tid: %i] Incorrectly predicted"
+                        "  return [sn:%i] PC: %s Restoring RAS\n", tid,
+                        hist_it->seqNum, hist_it->pc);
+                DPRINTF(Branch, "[tid:%i]: Restoring top of RAS"
+                        " to: %i, target: %s.\n", tid,
+                        hist_it->RASIndex, hist_it->RASTarget);
+                RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
+                hist_it->usedRAS = false;
+           } else if (hist_it->wasCall && hist_it->pushedRAS) {
+                 //Was a Call but predicated false. Pop RAS here
+                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
+                         "  Call [sn:%i] PC: %s Popping RAS\n", tid,
+                         hist_it->seqNum, hist_it->pc);
+                 RAS[tid].pop();
+                 hist_it->pushedRAS = false;
+           }
+        }
+    } else {
+        DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't "
+                "update.\n", tid, squashed_sn);
+    }
+}
+
+void
+BPredUnit::dump()
+{
+    int i = 0;
+    for (const auto& ph : predHist) {
+        if (!ph.empty()) {
+            auto pred_hist_it = ph.begin();
+
+            cprintf("predHist[%i].size(): %i\n", i++, ph.size());
+
+            while (pred_hist_it != ph.end()) {
+                cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
+                        "bpHistory:%#x\n",
+                        pred_hist_it->seqNum, pred_hist_it->pc,
+                        pred_hist_it->tid, pred_hist_it->predTaken,
+                        pred_hist_it->bpHistory);
+                pred_hist_it++;
+            }
+
+            cprintf("\n");
+        }
+    }
+}
+
index 851cdbb78f40a5024a633c06ee27bc7db79a3066..f8b217567f5c3469904948c38033aa057572d72b 100644 (file)
@@ -97,7 +97,7 @@ class BPredUnit : public SimObject
                         TheISA::PCState &predPC, ThreadID tid);
 
     // @todo: Rename this function.
-    virtual void uncondBranch(void * &bp_history) = 0;
+    virtual void uncondBranch(Addr pc, void * &bp_history) = 0;
 
     /**
      * Tells the branch predictor to commit any updates until the given
@@ -260,7 +260,8 @@ class BPredUnit : public SimObject
     typedef std::deque<PredictorHistory> History;
 
     /** Number of the threads for which the branch history is maintained. */
-    uint32_t numThreads;
+    const unsigned numThreads;
+
 
     /**
      * The per-thread predictor history. This is used to update the predictor
@@ -295,6 +296,9 @@ class BPredUnit : public SimObject
     Stats::Scalar RASIncorrect;
 
   protected:
+    /** Number of bits to shift instructions by for predictor addresses. */
+    const unsigned instShiftAmt;
+
     /**
      * @{
      * @name PMU Probe points.
diff --git a/src/cpu/pred/bpred_unit_impl.hh b/src/cpu/pred/bpred_unit_impl.hh
deleted file mode 100644 (file)
index 4d17bfd..0000000
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- * Copyright (c) 2011-2012, 2014 ARM Limited
- * Copyright (c) 2010 The University of Edinburgh
- * Copyright (c) 2012 Mark D. Hill and David A. Wood
- * All rights reserved
- *
- * The license below extends only to copyright in the software and shall
- * not be construed as granting a license to any other intellectual
- * property including but not limited to intellectual property relating
- * to a hardware implementation of the functionality of the software
- * licensed hereunder.  You may use the software subject to the license
- * terms below provided that you ensure that this notice is replicated
- * unmodified and in its entirety in all distributions of the software,
- * modified or unmodified, in source code or in binary form.
- *
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met: redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer;
- * redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution;
- * neither the name of the copyright holders nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Authors: Kevin Lim
- */
-
-#ifndef __CPU_PRED_BPRED_UNIT_IMPL_HH__
-#define __CPU_PRED_BPRED_UNIT_IMPL_HH__
-
-#include <algorithm>
-
-#include "arch/isa_traits.hh"
-#include "arch/types.hh"
-#include "arch/utility.hh"
-#include "base/trace.hh"
-#include "config/the_isa.hh"
-#include "cpu/pred/bpred_unit.hh"
-#include "debug/Branch.hh"
-
-BPredUnit::BPredUnit(const Params *params)
-    : SimObject(params),
-      numThreads(params->numThreads),
-      predHist(numThreads),
-      BTB(params->BTBEntries,
-          params->BTBTagSize,
-          params->instShiftAmt),
-      RAS(numThreads)
-{
-    for (auto& r : RAS)
-        r.init(params->RASSize);
-}
-
-void
-BPredUnit::regStats()
-{
-    lookups
-        .name(name() + ".lookups")
-        .desc("Number of BP lookups")
-        ;
-
-    condPredicted
-        .name(name() + ".condPredicted")
-        .desc("Number of conditional branches predicted")
-        ;
-
-    condIncorrect
-        .name(name() + ".condIncorrect")
-        .desc("Number of conditional branches incorrect")
-        ;
-
-    BTBLookups
-        .name(name() + ".BTBLookups")
-        .desc("Number of BTB lookups")
-        ;
-
-    BTBHits
-        .name(name() + ".BTBHits")
-        .desc("Number of BTB hits")
-        ;
-
-    BTBCorrect
-        .name(name() + ".BTBCorrect")
-        .desc("Number of correct BTB predictions (this stat may not "
-              "work properly.")
-        ;
-
-    BTBHitPct
-        .name(name() + ".BTBHitPct")
-        .desc("BTB Hit Percentage")
-        .precision(6);
-    BTBHitPct = (BTBHits / BTBLookups) * 100;
-
-    usedRAS
-        .name(name() + ".usedRAS")
-        .desc("Number of times the RAS was used to get a target.")
-        ;
-
-    RASIncorrect
-        .name(name() + ".RASInCorrect")
-        .desc("Number of incorrect RAS predictions.")
-        ;
-}
-
-ProbePoints::PMUUPtr
-BPredUnit::pmuProbePoint(const char *name)
-{
-    ProbePoints::PMUUPtr ptr;
-    ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
-
-    return ptr;
-}
-
-void
-BPredUnit::regProbePoints()
-{
-    ppBranches = pmuProbePoint("Branches");
-    ppMisses = pmuProbePoint("Misses");
-}
-
-void
-BPredUnit::drainSanityCheck() const
-{
-    // We shouldn't have any outstanding requests when we resume from
-    // a drained system.
-    for (const auto& ph M5_VAR_USED : predHist)
-        assert(ph.empty());
-}
-
-bool
-BPredUnit::predict(const StaticInstPtr &inst, const InstSeqNum &seqNum,
-                   TheISA::PCState &pc, 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.
-
-    bool pred_taken = false;
-    TheISA::PCState target = pc;
-
-    ++lookups;
-    ppBranches->notify(1);
-
-    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(bp_history);
-    } else {
-        ++condPredicted;
-        pred_taken = lookup(pc.instAddr(), bp_history);
-
-        DPRINTF(Branch, "[tid:%i]: [sn:%i] Branch predictor"
-                " predicted %i for PC %s\n", tid, seqNum,  pred_taken, pc);
-    }
-
-    DPRINTF(Branch, "[tid:%i]: [sn:%i] Creating prediction history "
-            "for PC %s\n", tid, seqNum, pc);
-
-    PredictorHistory predict_record(seqNum, pc.instAddr(),
-                                    pred_taken, bp_history, tid);
-
-    // Now lookup in the BTB or RAS.
-    if (pred_taken) {
-        if (inst->isReturn()) {
-            ++usedRAS;
-            predict_record.wasReturn = true;
-            // If it's a function return call, then look up the address
-            // in the RAS.
-            TheISA::PCState rasTop = RAS[tid].top();
-            target = TheISA::buildRetPC(pc, 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;
-
-            RAS[tid].pop();
-
-            DPRINTF(Branch, "[tid:%i]: Instruction %s is a return, "
-                    "RAS predicted target: %s, RAS index: %i.\n",
-                    tid, pc, target, predict_record.RASIndex);
-        } else {
-            ++BTBLookups;
-
-            if (inst->isCall()) {
-                RAS[tid].push(pc);
-                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, pc, pc, RAS[tid].topIdx());
-            }
-
-            if (BTB.valid(pc.instAddr(), tid)) {
-                ++BTBHits;
-
-                // If it's not a return, use the BTB to get the target addr.
-                target = BTB.lookup(pc.instAddr(), tid);
-
-                DPRINTF(Branch, "[tid:%i]: Instruction %s predicted"
-                        " target is %s.\n", tid, pc, target);
-
-            } else {
-                DPRINTF(Branch, "[tid:%i]: BTB doesn't have a "
-                        "valid entry.\n",tid);
-                pred_taken = false;
-                // The Direction of the branch predictor is altered because the
-                // BTB did not have an entry
-                // The predictor needs to be updated accordingly
-                if (!inst->isCall() && !inst->isReturn()) {
-                      btbUpdate(pc.instAddr(), bp_history);
-                      DPRINTF(Branch, "[tid:%i]:[sn:%i] btbUpdate"
-                              " called for %s\n", tid, seqNum, pc);
-                } else if (inst->isCall() && !inst->isUncondCtrl()) {
-                      RAS[tid].pop();
-                      predict_record.pushedRAS = false;
-                }
-                TheISA::advancePC(target, inst);
-            }
-        }
-    } else {
-        if (inst->isReturn()) {
-           predict_record.wasReturn = true;
-        }
-        TheISA::advancePC(target, inst);
-    }
-
-    pc = target;
-
-    predHist[tid].push_front(predict_record);
-
-    DPRINTF(Branch, "[tid:%i]: [sn:%i]: History entry added."
-            "predHist.size(): %i\n", tid, seqNum, predHist[tid].size());
-
-    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(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(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)
-{
-    DPRINTF(Branch, "[tid:%i]: Committing branches until "
-            "[sn:%lli].\n", tid, done_sn);
-
-    while (!predHist[tid].empty() &&
-           predHist[tid].back().seqNum <= done_sn) {
-        // Update the branch predictor with the correct results.
-        if (!predHist[tid].back().wasSquashed) {
-            update(predHist[tid].back().pc, predHist[tid].back().predTaken,
-                predHist[tid].back().bpHistory, false);
-        } else {
-            retireSquashed(predHist[tid].back().bpHistory);
-        }
-
-        predHist[tid].pop_back();
-    }
-}
-
-void
-BPredUnit::squash(const InstSeqNum &squashed_sn, ThreadID tid)
-{
-    History &pred_hist = predHist[tid];
-
-    while (!pred_hist.empty() &&
-           pred_hist.front().seqNum > squashed_sn) {
-        if (pred_hist.front().usedRAS) {
-            DPRINTF(Branch, "[tid:%i]: Restoring top of RAS to: %i,"
-                    " target: %s.\n", tid,
-                    pred_hist.front().RASIndex, pred_hist.front().RASTarget);
-
-            RAS[tid].restore(pred_hist.front().RASIndex,
-                             pred_hist.front().RASTarget);
-        } else if(pred_hist.front().wasCall && pred_hist.front().pushedRAS) {
-             // Was a call but predicated false. Pop RAS here
-             DPRINTF(Branch, "[tid: %i] Squashing"
-                     "  Call [sn:%i] PC: %s Popping RAS\n", tid,
-                     pred_hist.front().seqNum, pred_hist.front().pc);
-             RAS[tid].pop();
-        }
-
-        // This call should delete the bpHistory.
-        squash(pred_hist.front().bpHistory);
-
-        DPRINTF(Branch, "[tid:%i]: Removing history for [sn:%i] "
-                "PC %s.\n", tid, pred_hist.front().seqNum,
-                pred_hist.front().pc);
-
-        pred_hist.pop_front();
-
-        DPRINTF(Branch, "[tid:%i]: predHist.size(): %i\n",
-                tid, predHist[tid].size());
-    }
-}
-
-void
-BPredUnit::squash(const InstSeqNum &squashed_sn,
-                  const TheISA::PCState &corrTarget,
-                  bool actually_taken, ThreadID 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.
-    // NOTE: This should be call conceivably in 2 scenarios:
-    // (1) After an branch is executed, it updates its status in the ROB
-    //     The commit stage then checks the ROB update and sends a signal to
-    //     the fetch stage to squash history after the mispredict
-    // (2) In the decode stage, you can find out early if a unconditional
-    //     PC-relative, branch was predicted incorrectly. If so, a signal
-    //     to the fetch stage is sent to squash history after the mispredict
-
-    History &pred_hist = predHist[tid];
-
-    ++condIncorrect;
-    ppMisses->notify(1);
-
-    DPRINTF(Branch, "[tid:%i]: Squashing from sequence number %i, "
-            "setting target to %s.\n", tid, squashed_sn, corrTarget);
-
-    // Squash All Branches AFTER this mispredicted branch
-    squash(squashed_sn, tid);
-
-    // 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()) {
-
-        auto hist_it = pred_hist.begin();
-        //HistoryIt hist_it = find(pred_hist.begin(), pred_hist.end(),
-        //                       squashed_sn);
-
-        //assert(hist_it != pred_hist.end());
-        if (pred_hist.front().seqNum != squashed_sn) {
-            DPRINTF(Branch, "Front sn %i != Squash sn %i\n",
-                    pred_hist.front().seqNum, squashed_sn);
-
-            assert(pred_hist.front().seqNum == squashed_sn);
-        }
-
-
-        if ((*hist_it).usedRAS) {
-            ++RASIncorrect;
-        }
-
-        update((*hist_it).pc, actually_taken,
-               pred_hist.front().bpHistory, true);
-        hist_it->wasSquashed = true;
-
-        if (actually_taken) {
-            if (hist_it->wasReturn && !hist_it->usedRAS) {
-                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
-                         "  return [sn:%i] PC: %s\n", tid, hist_it->seqNum,
-                         hist_it->pc);
-                 RAS[tid].pop();
-                 hist_it->usedRAS = true;
-            }
-
-            DPRINTF(Branch,"[tid: %i] BTB Update called for [sn:%i]"
-                    " PC: %s\n", tid,hist_it->seqNum, hist_it->pc);
-
-            BTB.update((*hist_it).pc, corrTarget, tid);
-
-        } else {
-           //Actually not Taken
-           if (hist_it->usedRAS) {
-                DPRINTF(Branch,"[tid: %i] Incorrectly predicted"
-                        "  return [sn:%i] PC: %s Restoring RAS\n", tid,
-                        hist_it->seqNum, hist_it->pc);
-                DPRINTF(Branch, "[tid:%i]: Restoring top of RAS"
-                        " to: %i, target: %s.\n", tid,
-                        hist_it->RASIndex, hist_it->RASTarget);
-                RAS[tid].restore(hist_it->RASIndex, hist_it->RASTarget);
-                hist_it->usedRAS = false;
-           } else if (hist_it->wasCall && hist_it->pushedRAS) {
-                 //Was a Call but predicated false. Pop RAS here
-                 DPRINTF(Branch, "[tid: %i] Incorrectly predicted"
-                         "  Call [sn:%i] PC: %s Popping RAS\n", tid,
-                         hist_it->seqNum, hist_it->pc);
-                 RAS[tid].pop();
-                 hist_it->pushedRAS = false;
-           }
-        }
-    } else {
-        DPRINTF(Branch, "[tid:%i]: [sn:%i] pred_hist empty, can't "
-                "update.\n", tid, squashed_sn);
-    }
-}
-
-void
-BPredUnit::dump()
-{
-    int i = 0;
-    for (const auto& ph : predHist) {
-        if (!ph.empty()) {
-            auto pred_hist_it = ph.begin();
-
-            cprintf("predHist[%i].size(): %i\n", i++, ph.size());
-
-            while (pred_hist_it != ph.end()) {
-                cprintf("[sn:%lli], PC:%#x, tid:%i, predTaken:%i, "
-                        "bpHistory:%#x\n",
-                        pred_hist_it->seqNum, pred_hist_it->pc,
-                        pred_hist_it->tid, pred_hist_it->predTaken,
-                        pred_hist_it->bpHistory);
-                pred_hist_it++;
-            }
-
-            cprintf("\n");
-        }
-    }
-}
-
-#endif//__CPU_PRED_BPRED_UNIT_IMPL_HH__
index c6514b6add0a2e1c49d3695349a62f53f450203b..1d4fe037e77d1dfb545959940aca663742330e7d 100644 (file)
@@ -44,7 +44,7 @@
 #include "base/intmath.hh"
 #include "cpu/pred/tournament.hh"
 
-TournamentBP::TournamentBP(const Params *params)
+TournamentBP::TournamentBP(const TournamentBPParams *params)
     : BPredUnit(params),
       localPredictorSize(params->localPredictorSize),
       localCtrBits(params->localCtrBits),
@@ -58,8 +58,7 @@ TournamentBP::TournamentBP(const Params *params)
           ceilLog2(params->globalPredictorSize) :
           ceilLog2(params->choicePredictorSize)),
       choicePredictorSize(params->choicePredictorSize),
-      choiceCtrBits(params->choiceCtrBits),
-      instShiftAmt(params->instShiftAmt)
+      choiceCtrBits(params->choiceCtrBits)
 {
     if (!isPowerOf2(localPredictorSize)) {
         fatal("Invalid local predictor size!\n");
@@ -249,7 +248,7 @@ TournamentBP::lookup(Addr branch_addr, void * &bp_history)
 }
 
 void
-TournamentBP::uncondBranch(void * &bp_history)
+TournamentBP::uncondBranch(Addr pc, void * &bp_history)
 {
     // Create BPHistory and pass it back to be recorded.
     BPHistory *history = new BPHistory;
@@ -376,6 +375,12 @@ TournamentBP::squash(void *bp_history)
     delete history;
 }
 
+TournamentBP*
+TournamentBPParams::create()
+{
+    return new TournamentBP(this);
+}
+
 #ifdef DEBUG
 int
 TournamentBP::BPHistory::newCount = 0;
index 88334a8c03071758615235ae820b2ffebcb2671b..d461756103eceff7e40b25761a9693234e0a8840 100644 (file)
@@ -50,6 +50,7 @@
 #include "base/types.hh"
 #include "cpu/pred/bpred_unit.hh"
 #include "cpu/pred/sat_counter.hh"
+#include "params/TournamentBP.hh"
 
 /**
  * Implements a tournament branch predictor, hopefully identical to the one
@@ -66,7 +67,7 @@ class TournamentBP : public BPredUnit
     /**
      * Default branch predictor constructor.
      */
-    TournamentBP(const Params *params);
+    TournamentBP(const TournamentBPParams *params);
 
     /**
      * Looks up the given address in the branch predictor and returns
@@ -84,7 +85,7 @@ class TournamentBP : public BPredUnit
      * global history stored in it.
      * @param bp_history Pointer that will be set to the BPHistory object.
      */
-    void uncondBranch(void * &bp_history);
+    void uncondBranch(Addr pc, void * &bp_history);
     /**
      * Updates the branch predictor to Not Taken if a BTB entry is
      * invalid or not found.
@@ -234,11 +235,6 @@ class TournamentBP : public BPredUnit
     /** Number of bits in the choice predictor's counters. */
     unsigned choiceCtrBits;
 
-    /** Number of bits to shift the instruction over to get rid of the word
-     *  offset.
-     */
-    unsigned instShiftAmt;
-
     /** Thresholds for the counter value; above the threshold is taken,
      *  equal to or below the threshold is not taken.
      */
index 243a092696289f1e4b5e7375b79b131126d520b6..7298724ea4f40a6530bfcc7c1bb5c1560968c807 100644 (file)
@@ -30,7 +30,7 @@ from m5.defines import buildEnv
 from m5.params import *
 from BaseCPU import BaseCPU
 from DummyChecker import DummyChecker
-from BranchPredictor import BranchPredictor
+from BranchPredictor import *
 
 class BaseSimpleCPU(BaseCPU):
     type = 'BaseSimpleCPU'