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.
This commit is contained in:
parent
eb73a14fe2
commit
c52190a695
3 changed files with 73 additions and 3 deletions
|
@ -30,6 +30,7 @@ from m5.defines import buildEnv
|
||||||
from m5.params import *
|
from m5.params import *
|
||||||
from BaseCPU import BaseCPU
|
from BaseCPU import BaseCPU
|
||||||
from DummyChecker import DummyChecker
|
from DummyChecker import DummyChecker
|
||||||
|
from BranchPredictor import BranchPredictor
|
||||||
|
|
||||||
class BaseSimpleCPU(BaseCPU):
|
class BaseSimpleCPU(BaseCPU):
|
||||||
type = 'BaseSimpleCPU'
|
type = 'BaseSimpleCPU'
|
||||||
|
@ -46,3 +47,5 @@ class BaseSimpleCPU(BaseCPU):
|
||||||
else:
|
else:
|
||||||
print "ERROR: Checker only supported under ARM ISA!"
|
print "ERROR: Checker only supported under ARM ISA!"
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
branchPred = Param.BranchPredictor(NULL, "Branch Predictor")
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
#include "cpu/checker/thread_context.hh"
|
#include "cpu/checker/thread_context.hh"
|
||||||
#include "cpu/exetrace.hh"
|
#include "cpu/exetrace.hh"
|
||||||
|
#include "cpu/pred/bpred_unit.hh"
|
||||||
#include "cpu/profile.hh"
|
#include "cpu/profile.hh"
|
||||||
#include "cpu/simple_thread.hh"
|
#include "cpu/simple_thread.hh"
|
||||||
#include "cpu/smt.hh"
|
#include "cpu/smt.hh"
|
||||||
|
@ -85,7 +86,9 @@ using namespace std;
|
||||||
using namespace TheISA;
|
using namespace TheISA;
|
||||||
|
|
||||||
BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
|
BaseSimpleCPU::BaseSimpleCPU(BaseSimpleCPUParams *p)
|
||||||
: BaseCPU(p), traceData(NULL), thread(NULL)
|
: BaseCPU(p),
|
||||||
|
branchPred(p->branchPred),
|
||||||
|
traceData(NULL), thread(NULL)
|
||||||
{
|
{
|
||||||
if (FullSystem)
|
if (FullSystem)
|
||||||
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb,
|
thread = new SimpleThread(this, 0, p->system, p->itb, p->dtb,
|
||||||
|
@ -286,6 +289,21 @@ BaseSimpleCPU::regStats()
|
||||||
idleFraction = constant(1.0) - notIdleFraction;
|
idleFraction = constant(1.0) - notIdleFraction;
|
||||||
numIdleCycles = idleFraction * numCycles;
|
numIdleCycles = idleFraction * numCycles;
|
||||||
numBusyCycles = (notIdleFraction)*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
|
void
|
||||||
|
@ -434,6 +452,19 @@ BaseSimpleCPU::preExecute()
|
||||||
curStaticInst->getName(), curStaticInst->machInst);
|
curStaticInst->getName(), curStaticInst->machInst);
|
||||||
#endif // TRACING_ON
|
#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
|
void
|
||||||
|
@ -464,6 +495,10 @@ BaseSimpleCPU::postExecute()
|
||||||
CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr());
|
CPA::cpa()->swAutoBegin(tc, pc.nextInstAddr());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (curStaticInst->isControl()) {
|
||||||
|
++numBranches;
|
||||||
|
}
|
||||||
|
|
||||||
/* Power model statistics */
|
/* Power model statistics */
|
||||||
//integer alu accesses
|
//integer alu accesses
|
||||||
if (curStaticInst->isInteger()){
|
if (curStaticInst->isInteger()){
|
||||||
|
@ -507,10 +542,11 @@ BaseSimpleCPU::postExecute()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BaseSimpleCPU::advancePC(Fault fault)
|
BaseSimpleCPU::advancePC(Fault fault)
|
||||||
{
|
{
|
||||||
|
const bool branching(thread->pcState().branching());
|
||||||
|
|
||||||
//Since we're moving to a new pc, zero out the offset
|
//Since we're moving to a new pc, zero out the offset
|
||||||
fetchOffset = 0;
|
fetchOffset = 0;
|
||||||
if (fault != NoFault) {
|
if (fault != NoFault) {
|
||||||
|
@ -526,6 +562,23 @@ BaseSimpleCPU::advancePC(Fault fault)
|
||||||
thread->pcState(pcState);
|
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
|
void
|
||||||
|
|
|
@ -77,7 +77,7 @@ namespace Trace {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BaseSimpleCPUParams;
|
struct BaseSimpleCPUParams;
|
||||||
|
class BPredUnit;
|
||||||
|
|
||||||
class BaseSimpleCPU : public BaseCPU
|
class BaseSimpleCPU : public BaseCPU
|
||||||
{
|
{
|
||||||
|
@ -87,6 +87,8 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
typedef TheISA::FloatRegBits FloatRegBits;
|
typedef TheISA::FloatRegBits FloatRegBits;
|
||||||
typedef TheISA::CCReg CCReg;
|
typedef TheISA::CCReg CCReg;
|
||||||
|
|
||||||
|
BPredUnit *branchPred;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Trace::InstRecord *traceData;
|
Trace::InstRecord *traceData;
|
||||||
|
|
||||||
|
@ -272,6 +274,15 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
Stats::Scalar dcacheRetryCycles;
|
Stats::Scalar dcacheRetryCycles;
|
||||||
Counter lastDcacheRetry;
|
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 serializeThread(std::ostream &os, ThreadID tid);
|
||||||
void unserializeThread(Checkpoint *cp, const std::string §ion,
|
void unserializeThread(Checkpoint *cp, const std::string §ion,
|
||||||
ThreadID tid);
|
ThreadID tid);
|
||||||
|
@ -446,6 +457,9 @@ class BaseSimpleCPU : public BaseCPU
|
||||||
|
|
||||||
bool misspeculating() { return thread->misspeculating(); }
|
bool misspeculating() { return thread->misspeculating(); }
|
||||||
ThreadContext *tcBase() { return tc; }
|
ThreadContext *tcBase() { return tc; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TheISA::PCState pred_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __CPU_SIMPLE_BASE_HH__
|
#endif // __CPU_SIMPLE_BASE_HH__
|
||||||
|
|
Loading…
Reference in a new issue