base/stats/visit.cc
base/stats/text.cc
+ cpu/activity.cc
cpu/base.cc
cpu/base_dyn_inst.cc
cpu/cpu_exec_context.cc
--- /dev/null
+
+#include "base/timebuf.hh"
+#include "cpu/activity.hh"
+
+ActivityRecorder::ActivityRecorder(int num_stages, int longest_latency,
+ int activity)
+ : activityBuffer(longest_latency, 0), longestLatency(longest_latency),
+ activityCount(activity), numStages(num_stages)
+{
+ stageActive = new bool[numStages];
+ memset(stageActive, 0, numStages);
+}
+
+void
+ActivityRecorder::activity()
+{
+ if (activityBuffer[0]) {
+ return;
+ }
+
+ activityBuffer[0] = true;
+
+ ++activityCount;
+
+ DPRINTF(Activity, "Activity: %i\n", activityCount);
+}
+
+void
+ActivityRecorder::advance()
+{
+ if (activityBuffer[-longestLatency]) {
+ --activityCount;
+
+ assert(activityCount >= 0);
+
+ DPRINTF(Activity, "Activity: %i\n", activityCount);
+
+ if (activityCount == 0) {
+ DPRINTF(Activity, "No activity left!\n");
+ }
+ }
+
+ activityBuffer.advance();
+}
+
+void
+ActivityRecorder::activateStage(const int idx)
+{
+ if (!stageActive[idx]) {
+ ++activityCount;
+
+ stageActive[idx] = true;
+
+ DPRINTF(Activity, "Activity: %i\n", activityCount);
+ } else {
+ DPRINTF(Activity, "Stage %i already active.\n", idx);
+ }
+
+// assert(activityCount < longestLatency + numStages + 1);
+}
+
+void
+ActivityRecorder::deactivateStage(const int idx)
+{
+ if (stageActive[idx]) {
+ --activityCount;
+
+ stageActive[idx] = false;
+
+ DPRINTF(Activity, "Activity: %i\n", activityCount);
+ } else {
+ DPRINTF(Activity, "Stage %i already inactive.\n", idx);
+ }
+
+ assert(activityCount >= 0);
+}
+
+void
+ActivityRecorder::reset()
+{
+ activityCount = 0;
+ memset(stageActive, 0, numStages);
+ for (int i = 0; i < longestLatency + 1; ++i)
+ activityBuffer.advance();
+}
+
+void
+ActivityRecorder::dump()
+{
+ for (int i = 0; i <= longestLatency; ++i) {
+ cprintf("[Idx:%i %i] ", i, activityBuffer[-i]);
+ }
+
+ cprintf("\n");
+
+ for (int i = 0; i < numStages; ++i) {
+ cprintf("[Stage:%i %i]\n", i, stageActive[i]);
+ }
+
+ cprintf("\n");
+
+ cprintf("Activity count: %i\n", activityCount);
+}
+
+void
+ActivityRecorder::validate()
+{
+ int count = 0;
+ for (int i = 0; i <= longestLatency; ++i) {
+ if (activityBuffer[-i]) {
+ count++;
+ }
+ }
+
+ for (int i = 0; i < numStages; ++i) {
+ if (stageActive[i]) {
+ count++;
+ }
+ }
+
+ assert(count == activityCount);
+}
--- /dev/null
+
+#ifndef __CPU_ACTIVITY_HH__
+#define __CPU_ACTIVITY_HH__
+
+#include "base/timebuf.hh"
+#include "base/trace.hh"
+
+class ActivityRecorder {
+ public:
+ ActivityRecorder(int num_stages, int longest_latency, int count);
+
+ /** Records that there is activity this cycle. */
+ void activity();
+ /** Advances the activity buffer, decrementing the activityCount if active
+ * communication just left the time buffer, and descheduling the CPU if
+ * there is no activity.
+ */
+ void advance();
+ /** Marks a stage as active. */
+ void activateStage(const int idx);
+ /** Deactivates a stage. */
+ void deactivateStage(const int idx);
+
+ int getActivityCount() { return activityCount; }
+
+ void setActivityCount(int count)
+ { activityCount = count; }
+
+ bool active() { return activityCount; }
+
+ void reset();
+
+ void dump();
+
+ void validate();
+
+ private:
+ /** Time buffer that tracks if any cycles has active communication
+ * in them. It should be as long as the longest communication
+ * latency in the system. Each time any time buffer is written,
+ * the activity buffer should also be written to. The
+ * activityBuffer is advanced along with all the other time
+ * buffers, so it should have a 1 somewhere in it only if there
+ * is active communication in a time buffer.
+ */
+ TimeBuffer<bool> activityBuffer;
+
+ int longestLatency;
+
+ /** Tracks how many stages and cycles of time buffer have
+ * activity. Stages increment this count when they switch to
+ * active, and decrement it when they switch to
+ * inactive. Whenever a cycle that previously had no information
+ * is written in the time buffer, this is incremented. When a
+ * cycle that had information exits the time buffer due to age,
+ * this count is decremented. When the count is 0, there is no
+ * activity in the CPU, and it can be descheduled.
+ */
+ int activityCount;
+
+ int numStages;
+
+ /** Records which stages are active/inactive. */
+ bool *stageActive;
+};
+
+#endif // __CPU_ACTIVITY_HH__
Param<int> clock;
Param<int> numThreads;
+Param<int> activity;
#if FULL_SYSTEM
SimObjectParam<System *> system;
INIT_PARAM(clock, "clock speed"),
INIT_PARAM(numThreads, "number of HW thread contexts"),
+ INIT_PARAM_DFLT(activity, "Initial activity count", 0),
#if FULL_SYSTEM
INIT_PARAM(system, "System object"),
params->name = getInstanceName();
params->numberOfThreads = actual_num_threads;
+ params->activity = activity;
#if FULL_SYSTEM
params->system = system;
BaseCPU *checker;
+ unsigned activity;
+
//
// Caches
//
/*
- * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * Copyright (c) 2004-2006 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#else
#include "sim/process.hh"
#endif
-#include "sim/root.hh"
+#include "cpu/activity.hh"
#include "cpu/checker/cpu.hh"
#include "cpu/cpu_exec_context.hh"
#include "cpu/exec_context.hh"
#include "cpu/o3/alpha_impl.hh"
#include "cpu/o3/cpu.hh"
+#include "sim/root.hh"
#include "sim/stat_control.hh"
using namespace std;
TheISA::NumMiscRegs * number_of_threads,
TheISA::ZeroReg),
- // What to pass to these time buffers?
// For now just have these time buffers be pretty big.
- // @todo: Make these time buffer sizes parameters.
+ // @todo: Make these time buffer sizes parameters or derived
+ // from latencies
timeBuffer(5, 5),
fetchQueue(5, 5),
decodeQueue(5, 5),
renameQueue(5, 5),
iewQueue(5, 5),
- activityBuffer(5, 0),
- activityCount(0),
+ activityRec(NumStages, 10, params->activity),
globalSeqNum(1),
tids.resize(number_of_threads);
#endif
- // The stages also need their CPU pointer setup. However this must be
- // done at the upper level CPU because they have pointers to the upper
- // level CPU, and not this FullO3CPU.
+ // The stages also need their CPU pointer setup. However this
+ // must be done at the upper level CPU because they have pointers
+ // to the upper level CPU, and not this FullO3CPU.
// Set up Pointers to the activeThreads list for each stage
fetch.setActiveThreads(&activeThreads);
commitRenameMap[tid].init(TheISA::NumIntRegs,
params->numPhysIntRegs,
- lreg_idx, //Index for Logical. Regs
+ lreg_idx, //Index for Logical. Regs
TheISA::NumFloatRegs,
params->numPhysFloatRegs,
- freg_idx, //Index for Float Regs
+ freg_idx, //Index for Float Regs
TheISA::NumMiscRegs,
renameMap[tid].init(TheISA::NumIntRegs,
params->numPhysIntRegs,
- lreg_idx, //Index for Logical. Regs
+ lreg_idx, //Index for Logical. Regs
TheISA::NumFloatRegs,
params->numPhysFloatRegs,
- freg_idx, //Index for Float Regs
+ freg_idx, //Index for Float Regs
TheISA::NumMiscRegs,
lastRunningCycle = curTick;
- for (int i = 0; i < NumStages; ++i) {
- stageActive[i] = false;
- }
-
contextSwitch = false;
}
++numCycles;
- activity = false;
+// activity = false;
//Tick each of the stages
fetch.tick();
renameQueue.advance();
iewQueue.advance();
- advanceActivityBuffer();
+ activityRec.advance();
if (removeInstsThisCycle) {
cleanUpRemovedInsts();
}
- if (_status != SwitchedOut && activityCount && !tickEvent.scheduled()) {
- tickEvent.schedule(curTick + cycles(1));
+ if (!tickEvent.scheduled()) {
+ if (_status == SwitchedOut) {
+ // increment stat
+ lastRunningCycle = curTick;
+ } else if (!activityRec.active()) {
+ lastRunningCycle = curTick;
+ timesIdled++;
+ } else {
+ tickEvent.schedule(curTick + cycles(1));
+ }
}
#if !FULL_SYSTEM
// Be sure to signal that there's some activity so the CPU doesn't
// deschedule itself.
- activityThisCycle();
+ activityRec.activity();
fetch.wakeFromQuiesce();
_status = Running;
rename.switchOut();
iew.switchOut();
commit.switchOut();
+
+ // Wake the CPU and record activity so everything can drain out if
+ // the CPU is currently idle.
+ wakeCPU();
+ activityRec.activity();
}
template <class Impl>
void
FullO3CPU<Impl>::signalSwitched()
{
- if (++switchCount == 5) {
+ if (++switchCount == NumStages) {
fetch.doSwitchOut();
rename.doSwitchOut();
commit.doSwitchOut();
void
FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
{
- // Flush out any old data from the activity buffers.
- for (int i = 0; i < 6; ++i) {
+ // Flush out any old data from the time buffers.
+ for (int i = 0; i < 10; ++i) {
timeBuffer.advance();
fetchQueue.advance();
decodeQueue.advance();
renameQueue.advance();
iewQueue.advance();
- activityBuffer.advance();
}
- activityCount = 0;
- bzero(&stageActive, sizeof(stageActive));
+ activityRec.reset();
BaseCPU::takeOverFrom(oldCPU);
assert(!tickEvent.scheduled());
- // @todo: Figure out how to properly select the tid to put onto the active threads list.
+ // @todo: Figure out how to properly select the tid to put onto
+ // the active threads list.
int tid = 0;
list<unsigned>::iterator isActive = find(
activeThreads.begin(), activeThreads.end(), tid);
if (isActive == activeThreads.end()) {
- //May Need to Re-code this if the delay variable is the
- //delay needed for thread to activate
+ //May Need to Re-code this if the delay variable is the delay
+ //needed for thread to activate
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
tid);
activeThreads.push_back(tid);
}
- // Set all status's to active, schedule the
- // CPU's tick event.
+ // Set all statuses to active, schedule the CPU's tick event.
// @todo: Fix up statuses so this is handled properly
for (int i = 0; i < execContexts.size(); ++i) {
ExecContext *xc = execContexts[i];
void
FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
{
- if (reg_idx == TheISA::ZeroReg) {
- warn("Setting r31 through ArchIntReg in CPU, cycle %i\n", curTick);
- }
-
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
regFile.setIntReg(phys_reg, val);
// Mark it as squashed.
(*instIt)->setSquashed();
- //@todo: Formulate a consistent method for deleting
- //instructions from the instruction list
+ // @todo: Formulate a consistent method for deleting
+ // instructions from the instruction list
// Remove the instruction from the list.
removeList.push(instIt);
}
removeInstsThisCycle = false;
}
-
+/*
template <class Impl>
void
FullO3CPU<Impl>::removeAllInsts()
{
instList.clear();
}
-
+*/
template <class Impl>
void
FullO3CPU<Impl>::dumpInsts()
++num;
}
}
-
+/*
template <class Impl>
void
FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
{
iew.wakeDependents(inst);
}
-
+*/
template <class Impl>
void
FullO3CPU<Impl>::wakeCPU()
{
- if (activityCount || tickEvent.scheduled()) {
- return;
- }
-
- idleCycles += curTick - lastRunningCycle;
-
- tickEvent.schedule(curTick);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::activityThisCycle()
-{
- if (activityBuffer[0]) {
+ if (activityRec.active() || tickEvent.scheduled()) {
+ DPRINTF(Activity, "CPU already running.\n");
return;
}
- activityBuffer[0] = true;
- activity = true;
- ++activityCount;
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::advanceActivityBuffer()
-{
- if (activityBuffer[-5]) {
- --activityCount;
-
- assert(activityCount >= 0);
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
-
- if (activityCount == 0) {
- DPRINTF(FullCPU, "No activity left, going to idle!\n");
- lastRunningCycle = curTick;
- timesIdled++;
- }
- }
-
- activityBuffer.advance();
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::activateStage(const StageIdx idx)
-{
- if (!stageActive[idx]) {
- ++activityCount;
-
- stageActive[idx] = true;
-
- DPRINTF(Activity, "Activity: %i\n", activityCount);
- } else {
- DPRINTF(Activity, "Stage %i already active.\n", idx);
- }
-
- // @todo: Number is hardcoded for now. Replace with parameter.
- assert(activityCount < 15);
-}
-
-template <class Impl>
-void
-FullO3CPU<Impl>::deactivateStage(const StageIdx idx)
-{
- if (stageActive[idx]) {
- --activityCount;
-
- stageActive[idx] = false;
+ DPRINTF(Activity, "Waking up CPU\n");
- DPRINTF(Activity, "Activity: %i\n", activityCount);
- } else {
- DPRINTF(Activity, "Stage %i already inactive.\n", idx);
- }
+ idleCycles += (curTick - 1) - lastRunningCycle;
- assert(activityCount >= 0);
+ tickEvent.schedule(curTick);
}
template <class Impl>
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef __CPU_O3_FULL_CPU_HH__
-#define __CPU_O3_FULL_CPU_HH__
+#ifndef __CPU_O3_CPU_HH__
+#define __CPU_O3_CPU_HH__
#include <iostream>
#include <list>
#include "base/statistics.hh"
#include "base/timebuf.hh"
#include "config/full_system.hh"
+#include "cpu/activity.hh"
#include "cpu/base.hh"
#include "cpu/cpu_exec_context.hh"
#include "cpu/o3/comm.hh"
class FullO3CPU : public BaseFullCPU
{
public:
- //Put typedefs from the Impl here.
+ // Typedefs from the Impl here.
typedef typename Impl::CPUPol CPUPolicy;
typedef typename Impl::Params Params;
typedef typename Impl::DynInstPtr DynInstPtr;
* Note: this is a virtual function. CPU-Specific
* functionality defined in derived classes
*/
- virtual void syscall(int tid) {}
+ virtual void syscall(int tid) { panic("Unimplemented!"); }
/** Check if there are any system calls pending. */
void checkSyscalls();
/** Switches out this CPU.
- * @todo: Implement this.
*/
void switchOut(Sampler *sampler);
void signalSwitched();
/** Takes over from another CPU.
- * @todo: Implement this.
*/
void takeOverFrom(BaseCPU *oldCPU);
/** Add Instructions to the CPU Remove List*/
void addToRemoveList(DynInstPtr &inst);
- /** Remove an instruction from the front of the list. It is expected
- * that there are no instructions in front of it (that is, none are older
- * than the instruction being removed). Used when retiring instructions.
- * @todo: Remove the argument to this function, and just have it remove
- * last instruction once it's verified that commit has the same ordering
- * as the instruction list.
+ /** Remove an instruction from the front end of the list. There's
+ * no restriction on location of the instruction.
*/
void removeFrontInst(DynInstPtr &inst);
void cleanUpRemovedInsts();
/** Remove all instructions from the list. */
- void removeAllInsts();
+// void removeAllInsts();
void dumpInsts();
/** Basically a wrapper function so that instructions executed at
- * commit can tell the instruction queue that they have completed.
- * Eventually this hack should be removed.
+ * commit can tell the instruction queue that they have
+ * completed. Eventually this hack should be removed.
*/
- void wakeDependents(DynInstPtr &inst);
+// void wakeDependents(DynInstPtr &inst);
public:
/** List of all the instructions in flight. */
*/
std::queue<ListIt> removeList;
-//#ifdef DEBUG
+#ifdef DEBUG
std::set<InstSeqNum> snList;
-//#endif
+#endif
- /** Records if instructions need to be removed this cycle due to being
- * retired or squashed.
+ /** Records if instructions need to be removed this cycle due to
+ * being retired or squashed.
*/
bool removeInstsThisCycle;
/** The IEW stage's instruction queue. */
TimeBuffer<IEWStruct> iewQueue;
- private:
- /** Time buffer that tracks if any cycles has active communication in them.
- * It should be as long as the longest communication latency in the system.
- * Each time any time buffer is written, the activity buffer should also
- * be written to. The activityBuffer is advanced along with all the other
- * time buffers, so it should always have a 1 somewhere in it only if there
- * is active communication in a time buffer.
- */
- TimeBuffer<bool> activityBuffer;
-
- /** Tracks how many stages and cycles of time buffer have activity. Stages
- * increment this count when they switch to active, and decrement it when
- * they switch to inactive. Whenever a cycle that previously had no
- * information is written in the time buffer, this is incremented. When
- * a cycle that had information exits the time buffer due to age, this
- * count is decremented. When the count is 0, there is no activity in the
- * CPU, and it can be descheduled.
- */
- int activityCount;
+ public:
+ ActivityRecorder activityRec;
- /** Records if there has been activity this cycle. */
- bool activity;
+ void activityThisCycle() { activityRec.activity(); }
- /** Records which stages are active/inactive. */
- bool stageActive[NumStages];
+ void activateStage(const StageIdx idx)
+ { activityRec.activateStage(idx); }
+
+ void deactivateStage(const StageIdx idx)
+ { activityRec.deactivateStage(idx); }
- public:
/** Wakes the CPU, rescheduling the CPU if it's not already active. */
void wakeCPU();
- /** Records that there is activity this cycle. */
- void activityThisCycle();
- /** Advances the activity buffer, decrementing the activityCount if active
- * communication just left the time buffer, and descheduling the CPU if
- * there is no activity.
- */
- void advanceActivityBuffer();
- /** Marks a stage as active. */
- void activateStage(const StageIdx idx);
- /** Deactivates a stage. */
- void deactivateStage(const StageIdx idx);
/** Gets a free thread id. Use if thread ids change across system. */
int getFreeTid();
Stats::Formula totalIpc;
};
-#endif
+#endif // __CPU_O3_CPU_HH__
class DerivAlphaFullCPU(BaseCPU):
type = 'DerivAlphaFullCPU'
-
+ activity = Param.Unsigned("Initial count")
numThreads = Param.Unsigned("number of HW thread contexts")
if not build_env['FULL_SYSTEM']: