cpu: Probe points for basic PMU stats

This changeset adds probe points that can be used to implement PMU
counters for CPU stats. The following probes are supported:

  * BaseCPU::ppCycles / Cycles
  * BaseCPU::ppRetiredInsts / RetiredInsts
  * BaseCPU::ppRetiredLoads / RetiredLoads
  * BaseCPU::ppRetiredStores / RetiredStores
  * BaseCPU::ppRetiredBranches RetiredBranches
This commit is contained in:
Andreas Sandberg 2014-10-16 05:49:41 -04:00
parent 9d35d48e84
commit e0074324ba
10 changed files with 150 additions and 16 deletions

View file

@ -283,6 +283,42 @@ BaseCPU::startup()
}
}
ProbePoints::PMUUPtr
BaseCPU::pmuProbePoint(const char *name)
{
ProbePoints::PMUUPtr ptr;
ptr.reset(new ProbePoints::PMU(getProbeManager(), name));
return ptr;
}
void
BaseCPU::regProbePoints()
{
ppCycles = pmuProbePoint("Cycles");
ppRetiredInsts = pmuProbePoint("RetiredInsts");
ppRetiredLoads = pmuProbePoint("RetiredLoads");
ppRetiredStores = pmuProbePoint("RetiredStores");
ppRetiredBranches = pmuProbePoint("RetiredBranches");
}
void
BaseCPU::probeInstCommit(const StaticInstPtr &inst)
{
if (!inst->isMicroop() || inst->isLastMicroop())
ppRetiredInsts->notify(1);
if (inst->isLoad())
ppRetiredLoads->notify(1);
if (inst->isStore())
ppRetiredLoads->notify(1);
if (inst->isControl())
ppRetiredBranches->notify(1);
}
void
BaseCPU::regStats()

View file

@ -62,6 +62,7 @@
#include "sim/eventq.hh"
#include "sim/full_system.hh"
#include "sim/insttracer.hh"
#include "sim/probe/pmu.hh"
#include "sim/system.hh"
struct BaseCPUParams;
@ -280,6 +281,8 @@ class BaseCPU : public MemObject
virtual void startup();
virtual void regStats();
void regProbePoints() M5_ATTR_OVERRIDE;
void registerThreadContexts();
/**
@ -437,6 +440,54 @@ class BaseCPU : public MemObject
*/
void scheduleLoadStop(ThreadID tid, Counter loads, const char *cause);
public:
/**
* @{
* @name PMU Probe points.
*/
/**
* Helper method to trigger PMU probes for a committed
* instruction.
*
* @param inst Instruction that just committed
*/
virtual void probeInstCommit(const StaticInstPtr &inst);
/**
* Helper method to instantiate probe points belonging to this
* object.
*
* @param name Name of the probe point.
* @return A unique_ptr to the new probe point.
*/
ProbePoints::PMUUPtr pmuProbePoint(const char *name);
/** CPU cycle counter */
ProbePoints::PMUUPtr ppCycles;
/**
* Instruction commit probe point.
*
* This probe point is triggered whenever one or more instructions
* are committed. It is normally triggered once for every
* instruction. However, CPU models committing bundles of
* instructions may call notify once for the entire bundle.
*/
ProbePoints::PMUUPtr ppRetiredInsts;
/** Retired load instructions */
ProbePoints::PMUUPtr ppRetiredLoads;
/** Retired store instructions */
ProbePoints::PMUUPtr ppRetiredStores;
/** Retired branches (any type) */
ProbePoints::PMUUPtr ppRetiredBranches;
/** @} */
// Function tracing
private:
bool functionTracingEnabled;

View file

@ -853,6 +853,8 @@ Execute::doInstCommitAccounting(MinorDynInstPtr inst)
/* Set the CP SeqNum to the numOps commit number */
if (inst->traceData)
inst->traceData->setCPSeq(thread->numOp);
cpu.probeInstCommit(inst->staticInst);
}
bool

View file

@ -126,6 +126,11 @@ class Pipeline : public Ticked
* stages and pipeline advance) */
void evaluate();
void countCycles(Cycles delta) M5_ATTR_OVERRIDE
{
cpu.ppCycles->notify(delta);
}
void minorTrace() const;
/** Functions below here are BaseCPU operations passed on to pipeline

View file

@ -405,8 +405,11 @@ template <class Impl>
void
FullO3CPU<Impl>::regProbePoints()
{
BaseCPU::regProbePoints();
ppInstAccessComplete = new ProbePointArg<PacketPtr>(getProbeManager(), "InstAccessComplete");
ppDataAccessComplete = new ProbePointArg<std::pair<DynInstPtr, PacketPtr> >(getProbeManager(), "DataAccessComplete");
fetch.regProbePoints();
iew.regProbePoints();
commit.regProbePoints();
@ -534,6 +537,7 @@ FullO3CPU<Impl>::tick()
assert(getDrainState() != Drainable::Drained);
++numCycles;
ppCycles->notify(1);
// activity = false;
@ -1444,6 +1448,8 @@ FullO3CPU<Impl>::instDone(ThreadID tid, DynInstPtr &inst)
// Check for instruction-count-based events.
comInstEventQueue[tid]->serviceEvents(thread[tid]->numInst);
system->instEventQueue.serviceEvents(system->totalNumInsts);
probeInstCommit(inst->staticInst);
}
template <class Impl>
@ -1622,10 +1628,12 @@ FullO3CPU<Impl>::wakeCPU()
Cycles cycles(curCycle() - lastRunningCycle);
// @todo: This is an oddity that is only here to match the stats
if (cycles != 0)
if (cycles > 1) {
--cycles;
idleCycles += cycles;
numCycles += cycles;
idleCycles += cycles;
numCycles += cycles;
ppCycles->notify(cycles);
}
schedule(tickEvent, clockEdge());
}

View file

@ -233,7 +233,9 @@ AtomicSimpleCPU::activateContext(ThreadID thread_num)
assert(!tickEvent.scheduled());
notIdleFraction = 1;
numCycles += ticksToCycles(thread->lastActivate - thread->lastSuspend);
Cycles delta = ticksToCycles(thread->lastActivate - thread->lastSuspend);
numCycles += delta;
ppCycles->notify(delta);
//Make sure ticks are still on multiples of cycles
schedule(tickEvent, clockEdge(Cycles(0)));
@ -501,6 +503,7 @@ AtomicSimpleCPU::tick()
for (int i = 0; i < width || locked; ++i) {
numCycles++;
ppCycles->notify(1);
if (!curStaticInst || !curStaticInst->isDelayedCommit())
checkForInterrupts();
@ -614,6 +617,8 @@ AtomicSimpleCPU::tick()
void
AtomicSimpleCPU::regProbePoints()
{
BaseCPU::regProbePoints();
ppCommit = new ProbePointArg<pair<SimpleThread*, const StaticInstPtr>>
(getProbeManager(), "Commit");
}

View file

@ -544,6 +544,9 @@ BaseSimpleCPU::postExecute()
delete traceData;
traceData = NULL;
}
// Call CPU instruction commit probes
probeInstCommit(curStaticInst);
}
void

View file

@ -178,7 +178,7 @@ TimingSimpleCPU::switchOut()
assert(!stayAtPC);
assert(microPC() == 0);
numCycles += curCycle() - previousCycle;
updateCycleCounts();
}
@ -332,8 +332,7 @@ TimingSimpleCPU::translationFault(const Fault &fault)
{
// fault may be NoFault in cases where a fault is suppressed,
// for instance prefetches.
numCycles += curCycle() - previousCycle;
previousCycle = curCycle();
updateCycleCounts();
if (traceData) {
// Since there was a fault, we shouldn't trace this instruction.
@ -569,8 +568,7 @@ TimingSimpleCPU::fetch()
_status = IcacheWaitResponse;
completeIfetch(NULL);
numCycles += curCycle() - previousCycle;
previousCycle = curCycle();
updateCycleCounts();
}
}
@ -603,8 +601,7 @@ TimingSimpleCPU::sendFetch(const Fault &fault, RequestPtr req,
advanceInst(fault);
}
numCycles += curCycle() - previousCycle;
previousCycle = curCycle();
updateCycleCounts();
}
@ -651,8 +648,7 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt)
_status = BaseSimpleCPU::Running;
numCycles += curCycle() - previousCycle;
previousCycle = curCycle();
updateCycleCounts();
if (pkt)
pkt->req->setAccessLatency();
@ -753,8 +749,8 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt)
pkt->req->getFlags().isSet(Request::NO_ACCESS));
pkt->req->setAccessLatency();
numCycles += curCycle() - previousCycle;
previousCycle = curCycle();
updateCycleCounts();
if (pkt->senderState) {
SplitFragmentSenderState * send_state =
@ -808,6 +804,17 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt)
advanceInst(fault);
}
void
TimingSimpleCPU::updateCycleCounts()
{
const Cycles delta(curCycle() - previousCycle);
numCycles += delta;
ppCycles->notify(delta);
previousCycle = curCycle();
}
void
TimingSimpleCPU::DcachePort::recvTimingSnoopReq(PacketPtr pkt)
{

View file

@ -245,13 +245,15 @@ class TimingSimpleCPU : public BaseSimpleCPU
};
void updateCycleCounts();
IcachePort icachePort;
DcachePort dcachePort;
PacketPtr ifetch_pkt;
PacketPtr dcache_pkt;
Tick previousCycle;
Cycles previousCycle;
protected:

View file

@ -76,6 +76,7 @@ class Ticked
{
++owner.tickCycles;
++owner.numCycles;
owner.countCycles(Cycles(1));
owner.evaluate();
if (owner.running) {
owner.object.schedule(this,
@ -132,6 +133,7 @@ class Ticked
object.schedule(event, object.clockEdge(Cycles(1)));
running = true;
numCycles += cyclesSinceLastStopped();
countCycles(cyclesSinceLastStopped());
}
}
@ -167,6 +169,19 @@ class Ticked
/** Action to call on the clock tick */
virtual void evaluate() = 0;
/**
* Callback to handle cycle statistics and probes.
*
* This callback is called at the beginning of a new cycle active
* cycle and when restarting the ticked object. The delta
* parameter indicates the number of cycles elapsed since the
* previous call is normally '1' unless the object has been
* stopped and restarted.
*
* @param delta Number of cycles since the previous call.
*/
virtual void countCycles(Cycles delta) {}
};
/** TickedObject attaches Ticked to ClockedObject and can be used as