changeset 3b0d0c988ed6 in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=3b0d0c988ed6
description:
cpu: simple: Add support for using branch predictors
This changesets adds branch predictor support to the
BaseSimpleCPU. The simple CPUs normally don't need a branch predictor,
however, there are at least two cases where it can be desirable:
1) A simple CPU can be used to warm the branch predictor of an O3
CPU before switching to the slower O3 model.
2) The simple CPU can be used as a quick way of evaluating/debugging
new branch predictors since it exposes branch predictor
statistics.
Limitations:
* Since the simple CPU doesn't speculate, only one instruction will
be active in the branch predictor at a time (i.e., the branch
predictor will never see speculative branches).
* The outcome of a branch prediction does not affect the performance
of the simple CPU.
diffstat:
src/cpu/simple/BaseSimpleCPU.py | 3 ++
src/cpu/simple/base.cc | 57 +++++++++++++++++++++++++++++++++++++++-
src/cpu/simple/base.hh | 16 ++++++++++-
3 files changed, 73 insertions(+), 3 deletions(-)
diffs (176 lines):
diff -r f60cd60445b7 -r 3b0d0c988ed6 src/cpu/simple/BaseSimpleCPU.py
--- a/src/cpu/simple/BaseSimpleCPU.py Thu Feb 06 16:30:13 2014 -0600
+++ b/src/cpu/simple/BaseSimpleCPU.py Sun Feb 09 20:49:28 2014 +0100
@@ -30,6 +30,7 @@
from m5.params import *
from BaseCPU import BaseCPU
from DummyChecker import DummyChecker
+from BranchPredictor import BranchPredictor
class BaseSimpleCPU(BaseCPU):
type = 'BaseSimpleCPU'
@@ -46,3 +47,5 @@
else:
print "ERROR: Checker only supported under ARM ISA!"
exit(1)
+
+ branchPred = Param.BranchPredictor(NULL, "Branch Predictor")
diff -r f60cd60445b7 -r 3b0d0c988ed6 src/cpu/simple/base.cc
--- a/src/cpu/simple/base.cc Thu Feb 06 16:30:13 2014 -0600
+++ b/src/cpu/simple/base.cc Sun Feb 09 20:49:28 2014 +0100
@@ -60,6 +60,7 @@
#include "cpu/checker/cpu.hh"
#include "cpu/checker/thread_context.hh"
#include "cpu/exetrace.hh"
+#include "cpu/pred/bpred_unit.hh"
#include "cpu/profile.hh"
#include "cpu/simple_thread.hh"
#include "cpu/smt.hh"
@@ -85,7 +86,9 @@
using namespace TheISA;
BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
- : BaseCPU(p), traceData(NULL), thread(NULL)
+ : BaseCPU(p),
+ branchPred(p->branchPred),
+ traceData(NULL), thread(NULL)
{
if (FullSystem)
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb,
@@ -286,6 +289,21 @@
idleFraction = constant(1.0) - notIdleFraction;
numIdleCycles = idleFraction * numCycles;
numBusyCycles = (notIdleFraction)*numCycles;
+
+ numBranches
+ .name(name() + ".Branches")
+ .desc("Number of branches fetched")
+ .prereq(numBranches);
+
+ numPredictedBranches
+ .name(name() + ".predictedBranches")
+ .desc("Number of branches predicted as taken")
+ .prereq(numPredictedBranches);
+
+ numBranchMispred
+ .name(name() + ".BranchMispred")
+ .desc("Number of branch mispredictions")
+ .prereq(numBranchMispred);
}
void
@@ -434,6 +452,19 @@
curStaticInst->getName(), curStaticInst->machInst);
#endif // TRACING_ON
}
+
+ if (branchPred && curStaticInst && curStaticInst->isControl()) {
+ // Use a fake sequence number since we only have one
+ // instruction in flight at the same time.
+ const InstSeqNum cur_sn(0);
+ const ThreadID tid(0);
+ pred_pc = thread->pcState();
+ const bool predict_taken(
+ branchPred->predict(curStaticInst, cur_sn, pred_pc, tid));
+
+ if (predict_taken)
+ ++numPredictedBranches;
+ }
}
void
@@ -464,6 +495,10 @@
CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr());
}
+ if (curStaticInst->isControl()) {
+ ++numBranches;
+ }
+
/* Power model statistics */
//integer alu accesses
if (curStaticInst->isInteger()){
@@ -507,10 +542,11 @@
}
}
-
void
BaseSimpleCPU::advancePC(Fault fault)
{
+ const bool branching(thread->pcState().branching());
+
//Since we're moving to a new pc, zero out the offset
fetchOffset = 0;
if (fault != NoFault) {
@@ -526,6 +562,23 @@
thread->pcState(pcState);
}
}
+
+ if (branchPred && curStaticInst && curStaticInst->isControl()) {
+ // Use a fake sequence number since we only have one
+ // instruction in flight at the same time.
+ const InstSeqNum cur_sn(0);
+ const ThreadID tid(0);
+
+ if (pred_pc == thread->pcState()) {
+ // Correctly predicted branch
+ branchPred->update(cur_sn, tid);
+ } else {
+ // Mis-predicted branch
+ branchPred->squash(cur_sn, pcState(),
+ branching, tid);
+ ++numBranchMispred;
+ }
+ }
}
void
diff -r f60cd60445b7 -r 3b0d0c988ed6 src/cpu/simple/base.hh
--- a/src/cpu/simple/base.hh Thu Feb 06 16:30:13 2014 -0600
+++ b/src/cpu/simple/base.hh Sun Feb 09 20:49:28 2014 +0100
@@ -77,7 +77,7 @@
}
struct BaseSimpleCPUParams;
-
+class BPredUnit;
class BaseSimpleCPU : public BaseCPU
{
@@ -87,6 +87,8 @@
typedef TheISA::FloatRegBits FloatRegBits;
typedef TheISA::CCReg CCReg;
+ BPredUnit *branchPred;
+
protected:
Trace::InstRecord *traceData;
@@ -272,6 +274,15 @@
Stats::Scalar dcacheRetryCycles;
Counter lastDcacheRetry;
+ /// @{
+ /// Total number of branches fetched
+ Stats::Scalar numBranches;
+ /// Number of branches predicted as taken
+ Stats::Scalar numPredictedBranches;
+ /// Number of misprediced branches
+ Stats::Scalar numBranchMispred;
+ /// @}
+
void serializeThread(std::ostream &os, ThreadID tid);
void unserializeThread(Checkpoint *cp, const std::string §ion,
ThreadID tid);
@@ -446,6 +457,9 @@
bool misspeculating() { return thread->misspeculating(); }
ThreadContext *tcBase() { return tc; }
+
+ private:
+ TheISA::PCState pred_pc;
};
#endif // __CPU_SIMPLE_BASE_HH__
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev