Move activity tracking code into its own class. Now the CPU no longer has to keep track of the activity tracking internals; it just calls advance() on the class and uses it to tell if it should deschedule itself.
SConscript: Split off activity/idling code into its own class to do the processing separately. cpu/o3/alpha_cpu_builder.cc: cpu/o3/alpha_params.hh: Activity stuff. This is mostly for debugging and may be removed later on (or changed to enable/disable activity idling). cpu/o3/cpu.cc: Move activity idling stuff mostly into its own class, so it no longer clutters this file. cpu/o3/cpu.hh: Move activity idling stuff into its own class. python/m5/objects/AlphaFullCPU.py: Add parameter for initial activity value. --HG-- extra : convert_revision : f32f7cc03895dc07ab57ddba78c5402a1a8b0f1a
This commit is contained in:
parent
c7e7d07ec3
commit
c4a87f874a
8 changed files with 273 additions and 175 deletions
|
@ -80,6 +80,7 @@ base_sources = Split('''
|
||||||
base/stats/visit.cc
|
base/stats/visit.cc
|
||||||
base/stats/text.cc
|
base/stats/text.cc
|
||||||
|
|
||||||
|
cpu/activity.cc
|
||||||
cpu/base.cc
|
cpu/base.cc
|
||||||
cpu/base_dyn_inst.cc
|
cpu/base_dyn_inst.cc
|
||||||
cpu/cpu_exec_context.cc
|
cpu/cpu_exec_context.cc
|
||||||
|
|
122
cpu/activity.cc
Normal file
122
cpu/activity.cc
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
67
cpu/activity.hh
Normal file
67
cpu/activity.hh
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
|
||||||
|
#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__
|
|
@ -48,6 +48,7 @@ BEGIN_DECLARE_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
|
||||||
|
|
||||||
Param<int> clock;
|
Param<int> clock;
|
||||||
Param<int> numThreads;
|
Param<int> numThreads;
|
||||||
|
Param<int> activity;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
SimObjectParam<System *> system;
|
SimObjectParam<System *> system;
|
||||||
|
@ -156,6 +157,7 @@ BEGIN_INIT_SIM_OBJECT_PARAMS(DerivAlphaFullCPU)
|
||||||
|
|
||||||
INIT_PARAM(clock, "clock speed"),
|
INIT_PARAM(clock, "clock speed"),
|
||||||
INIT_PARAM(numThreads, "number of HW thread contexts"),
|
INIT_PARAM(numThreads, "number of HW thread contexts"),
|
||||||
|
INIT_PARAM_DFLT(activity, "Initial activity count", 0),
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
INIT_PARAM(system, "System object"),
|
INIT_PARAM(system, "System object"),
|
||||||
|
@ -301,6 +303,7 @@ CREATE_SIM_OBJECT(DerivAlphaFullCPU)
|
||||||
|
|
||||||
params->name = getInstanceName();
|
params->name = getInstanceName();
|
||||||
params->numberOfThreads = actual_num_threads;
|
params->numberOfThreads = actual_num_threads;
|
||||||
|
params->activity = activity;
|
||||||
|
|
||||||
#if FULL_SYSTEM
|
#if FULL_SYSTEM
|
||||||
params->system = system;
|
params->system = system;
|
||||||
|
|
|
@ -64,6 +64,8 @@ class AlphaSimpleParams : public BaseFullCPU::Params
|
||||||
|
|
||||||
BaseCPU *checker;
|
BaseCPU *checker;
|
||||||
|
|
||||||
|
unsigned activity;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Caches
|
// Caches
|
||||||
//
|
//
|
||||||
|
|
167
cpu/o3/cpu.cc
167
cpu/o3/cpu.cc
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* 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.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -33,8 +33,8 @@
|
||||||
#else
|
#else
|
||||||
#include "sim/process.hh"
|
#include "sim/process.hh"
|
||||||
#endif
|
#endif
|
||||||
#include "sim/root.hh"
|
|
||||||
|
|
||||||
|
#include "cpu/activity.hh"
|
||||||
#include "cpu/checker/cpu.hh"
|
#include "cpu/checker/cpu.hh"
|
||||||
#include "cpu/cpu_exec_context.hh"
|
#include "cpu/cpu_exec_context.hh"
|
||||||
#include "cpu/exec_context.hh"
|
#include "cpu/exec_context.hh"
|
||||||
|
@ -42,6 +42,7 @@
|
||||||
#include "cpu/o3/alpha_impl.hh"
|
#include "cpu/o3/alpha_impl.hh"
|
||||||
#include "cpu/o3/cpu.hh"
|
#include "cpu/o3/cpu.hh"
|
||||||
|
|
||||||
|
#include "sim/root.hh"
|
||||||
#include "sim/stat_control.hh"
|
#include "sim/stat_control.hh"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -104,16 +105,15 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
|
||||||
TheISA::NumMiscRegs * number_of_threads,
|
TheISA::NumMiscRegs * number_of_threads,
|
||||||
TheISA::ZeroReg),
|
TheISA::ZeroReg),
|
||||||
|
|
||||||
// What to pass to these time buffers?
|
|
||||||
// For now just have these time buffers be pretty big.
|
// 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),
|
timeBuffer(5, 5),
|
||||||
fetchQueue(5, 5),
|
fetchQueue(5, 5),
|
||||||
decodeQueue(5, 5),
|
decodeQueue(5, 5),
|
||||||
renameQueue(5, 5),
|
renameQueue(5, 5),
|
||||||
iewQueue(5, 5),
|
iewQueue(5, 5),
|
||||||
activityBuffer(5, 0),
|
activityRec(NumStages, 10, params->activity),
|
||||||
activityCount(0),
|
|
||||||
|
|
||||||
globalSeqNum(1),
|
globalSeqNum(1),
|
||||||
|
|
||||||
|
@ -150,9 +150,9 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
|
||||||
tids.resize(number_of_threads);
|
tids.resize(number_of_threads);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The stages also need their CPU pointer setup. However this must be
|
// The stages also need their CPU pointer setup. However this
|
||||||
// done at the upper level CPU because they have pointers to the upper
|
// must be done at the upper level CPU because they have pointers
|
||||||
// level CPU, and not this FullO3CPU.
|
// to the upper level CPU, and not this FullO3CPU.
|
||||||
|
|
||||||
// Set up Pointers to the activeThreads list for each stage
|
// Set up Pointers to the activeThreads list for each stage
|
||||||
fetch.setActiveThreads(&activeThreads);
|
fetch.setActiveThreads(&activeThreads);
|
||||||
|
@ -207,11 +207,11 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
|
||||||
|
|
||||||
commitRenameMap[tid].init(TheISA::NumIntRegs,
|
commitRenameMap[tid].init(TheISA::NumIntRegs,
|
||||||
params->numPhysIntRegs,
|
params->numPhysIntRegs,
|
||||||
lreg_idx, //Index for Logical. Regs
|
lreg_idx, //Index for Logical. Regs
|
||||||
|
|
||||||
TheISA::NumFloatRegs,
|
TheISA::NumFloatRegs,
|
||||||
params->numPhysFloatRegs,
|
params->numPhysFloatRegs,
|
||||||
freg_idx, //Index for Float Regs
|
freg_idx, //Index for Float Regs
|
||||||
|
|
||||||
TheISA::NumMiscRegs,
|
TheISA::NumMiscRegs,
|
||||||
|
|
||||||
|
@ -223,11 +223,11 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
|
||||||
|
|
||||||
renameMap[tid].init(TheISA::NumIntRegs,
|
renameMap[tid].init(TheISA::NumIntRegs,
|
||||||
params->numPhysIntRegs,
|
params->numPhysIntRegs,
|
||||||
lreg_idx, //Index for Logical. Regs
|
lreg_idx, //Index for Logical. Regs
|
||||||
|
|
||||||
TheISA::NumFloatRegs,
|
TheISA::NumFloatRegs,
|
||||||
params->numPhysFloatRegs,
|
params->numPhysFloatRegs,
|
||||||
freg_idx, //Index for Float Regs
|
freg_idx, //Index for Float Regs
|
||||||
|
|
||||||
TheISA::NumMiscRegs,
|
TheISA::NumMiscRegs,
|
||||||
|
|
||||||
|
@ -258,10 +258,6 @@ FullO3CPU<Impl>::FullO3CPU(Params *params)
|
||||||
|
|
||||||
lastRunningCycle = curTick;
|
lastRunningCycle = curTick;
|
||||||
|
|
||||||
for (int i = 0; i < NumStages; ++i) {
|
|
||||||
stageActive[i] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
contextSwitch = false;
|
contextSwitch = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +332,7 @@ FullO3CPU<Impl>::tick()
|
||||||
|
|
||||||
++numCycles;
|
++numCycles;
|
||||||
|
|
||||||
activity = false;
|
// activity = false;
|
||||||
|
|
||||||
//Tick each of the stages
|
//Tick each of the stages
|
||||||
fetch.tick();
|
fetch.tick();
|
||||||
|
@ -361,14 +357,22 @@ FullO3CPU<Impl>::tick()
|
||||||
renameQueue.advance();
|
renameQueue.advance();
|
||||||
iewQueue.advance();
|
iewQueue.advance();
|
||||||
|
|
||||||
advanceActivityBuffer();
|
activityRec.advance();
|
||||||
|
|
||||||
if (removeInstsThisCycle) {
|
if (removeInstsThisCycle) {
|
||||||
cleanUpRemovedInsts();
|
cleanUpRemovedInsts();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_status != SwitchedOut && activityCount && !tickEvent.scheduled()) {
|
if (!tickEvent.scheduled()) {
|
||||||
tickEvent.schedule(curTick + cycles(1));
|
if (_status == SwitchedOut) {
|
||||||
|
// increment stat
|
||||||
|
lastRunningCycle = curTick;
|
||||||
|
} else if (!activityRec.active()) {
|
||||||
|
lastRunningCycle = curTick;
|
||||||
|
timesIdled++;
|
||||||
|
} else {
|
||||||
|
tickEvent.schedule(curTick + cycles(1));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !FULL_SYSTEM
|
#if !FULL_SYSTEM
|
||||||
|
@ -592,7 +596,7 @@ FullO3CPU<Impl>::activateContext(int tid, int delay)
|
||||||
|
|
||||||
// Be sure to signal that there's some activity so the CPU doesn't
|
// Be sure to signal that there's some activity so the CPU doesn't
|
||||||
// deschedule itself.
|
// deschedule itself.
|
||||||
activityThisCycle();
|
activityRec.activity();
|
||||||
fetch.wakeFromQuiesce();
|
fetch.wakeFromQuiesce();
|
||||||
|
|
||||||
_status = Running;
|
_status = Running;
|
||||||
|
@ -669,13 +673,18 @@ FullO3CPU<Impl>::switchOut(Sampler *_sampler)
|
||||||
rename.switchOut();
|
rename.switchOut();
|
||||||
iew.switchOut();
|
iew.switchOut();
|
||||||
commit.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>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::signalSwitched()
|
FullO3CPU<Impl>::signalSwitched()
|
||||||
{
|
{
|
||||||
if (++switchCount == 5) {
|
if (++switchCount == NumStages) {
|
||||||
fetch.doSwitchOut();
|
fetch.doSwitchOut();
|
||||||
rename.doSwitchOut();
|
rename.doSwitchOut();
|
||||||
commit.doSwitchOut();
|
commit.doSwitchOut();
|
||||||
|
@ -699,18 +708,16 @@ template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||||
{
|
{
|
||||||
// Flush out any old data from the activity buffers.
|
// Flush out any old data from the time buffers.
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
timeBuffer.advance();
|
timeBuffer.advance();
|
||||||
fetchQueue.advance();
|
fetchQueue.advance();
|
||||||
decodeQueue.advance();
|
decodeQueue.advance();
|
||||||
renameQueue.advance();
|
renameQueue.advance();
|
||||||
iewQueue.advance();
|
iewQueue.advance();
|
||||||
activityBuffer.advance();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activityCount = 0;
|
activityRec.reset();
|
||||||
bzero(&stageActive, sizeof(stageActive));
|
|
||||||
|
|
||||||
BaseCPU::takeOverFrom(oldCPU);
|
BaseCPU::takeOverFrom(oldCPU);
|
||||||
|
|
||||||
|
@ -722,23 +729,23 @@ FullO3CPU<Impl>::takeOverFrom(BaseCPU *oldCPU)
|
||||||
|
|
||||||
assert(!tickEvent.scheduled());
|
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;
|
int tid = 0;
|
||||||
|
|
||||||
list<unsigned>::iterator isActive = find(
|
list<unsigned>::iterator isActive = find(
|
||||||
activeThreads.begin(), activeThreads.end(), tid);
|
activeThreads.begin(), activeThreads.end(), tid);
|
||||||
|
|
||||||
if (isActive == activeThreads.end()) {
|
if (isActive == activeThreads.end()) {
|
||||||
//May Need to Re-code this if the delay variable is the
|
//May Need to Re-code this if the delay variable is the delay
|
||||||
//delay needed for thread to activate
|
//needed for thread to activate
|
||||||
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
|
DPRINTF(FullCPU, "Adding Thread %i to active threads list\n",
|
||||||
tid);
|
tid);
|
||||||
|
|
||||||
activeThreads.push_back(tid);
|
activeThreads.push_back(tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set all status's to active, schedule the
|
// Set all statuses to active, schedule the CPU's tick event.
|
||||||
// CPU's tick event.
|
|
||||||
// @todo: Fix up statuses so this is handled properly
|
// @todo: Fix up statuses so this is handled properly
|
||||||
for (int i = 0; i < execContexts.size(); ++i) {
|
for (int i = 0; i < execContexts.size(); ++i) {
|
||||||
ExecContext *xc = execContexts[i];
|
ExecContext *xc = execContexts[i];
|
||||||
|
@ -850,10 +857,6 @@ template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::setArchIntReg(int reg_idx, uint64_t val, unsigned tid)
|
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);
|
PhysRegIndex phys_reg = commitRenameMap[tid].lookup(reg_idx);
|
||||||
|
|
||||||
regFile.setIntReg(phys_reg, val);
|
regFile.setIntReg(phys_reg, val);
|
||||||
|
@ -1049,8 +1052,8 @@ FullO3CPU<Impl>::squashInstIt(const ListIt &instIt, const unsigned &tid)
|
||||||
// Mark it as squashed.
|
// Mark it as squashed.
|
||||||
(*instIt)->setSquashed();
|
(*instIt)->setSquashed();
|
||||||
|
|
||||||
//@todo: Formulate a consistent method for deleting
|
// @todo: Formulate a consistent method for deleting
|
||||||
//instructions from the instruction list
|
// instructions from the instruction list
|
||||||
// Remove the instruction from the list.
|
// Remove the instruction from the list.
|
||||||
removeList.push(instIt);
|
removeList.push(instIt);
|
||||||
}
|
}
|
||||||
|
@ -1074,14 +1077,14 @@ FullO3CPU<Impl>::cleanUpRemovedInsts()
|
||||||
|
|
||||||
removeInstsThisCycle = false;
|
removeInstsThisCycle = false;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::removeAllInsts()
|
FullO3CPU<Impl>::removeAllInsts()
|
||||||
{
|
{
|
||||||
instList.clear();
|
instList.clear();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::dumpInsts()
|
FullO3CPU<Impl>::dumpInsts()
|
||||||
|
@ -1102,98 +1105,30 @@ FullO3CPU<Impl>::dumpInsts()
|
||||||
++num;
|
++num;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
|
FullO3CPU<Impl>::wakeDependents(DynInstPtr &inst)
|
||||||
{
|
{
|
||||||
iew.wakeDependents(inst);
|
iew.wakeDependents(inst);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
void
|
void
|
||||||
FullO3CPU<Impl>::wakeCPU()
|
FullO3CPU<Impl>::wakeCPU()
|
||||||
{
|
{
|
||||||
if (activityCount || tickEvent.scheduled()) {
|
if (activityRec.active() || tickEvent.scheduled()) {
|
||||||
|
DPRINTF(Activity, "CPU already running.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
idleCycles += curTick - lastRunningCycle;
|
DPRINTF(Activity, "Waking up CPU\n");
|
||||||
|
|
||||||
|
idleCycles += (curTick - 1) - lastRunningCycle;
|
||||||
|
|
||||||
tickEvent.schedule(curTick);
|
tickEvent.schedule(curTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Impl>
|
|
||||||
void
|
|
||||||
FullO3CPU<Impl>::activityThisCycle()
|
|
||||||
{
|
|
||||||
if (activityBuffer[0]) {
|
|
||||||
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, "Activity: %i\n", activityCount);
|
|
||||||
} else {
|
|
||||||
DPRINTF(Activity, "Stage %i already inactive.\n", idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(activityCount >= 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class Impl>
|
template <class Impl>
|
||||||
int
|
int
|
||||||
FullO3CPU<Impl>::getFreeTid()
|
FullO3CPU<Impl>::getFreeTid()
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __CPU_O3_FULL_CPU_HH__
|
#ifndef __CPU_O3_CPU_HH__
|
||||||
#define __CPU_O3_FULL_CPU_HH__
|
#define __CPU_O3_CPU_HH__
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
#include "base/statistics.hh"
|
#include "base/statistics.hh"
|
||||||
#include "base/timebuf.hh"
|
#include "base/timebuf.hh"
|
||||||
#include "config/full_system.hh"
|
#include "config/full_system.hh"
|
||||||
|
#include "cpu/activity.hh"
|
||||||
#include "cpu/base.hh"
|
#include "cpu/base.hh"
|
||||||
#include "cpu/cpu_exec_context.hh"
|
#include "cpu/cpu_exec_context.hh"
|
||||||
#include "cpu/o3/comm.hh"
|
#include "cpu/o3/comm.hh"
|
||||||
|
@ -70,7 +71,7 @@ template <class Impl>
|
||||||
class FullO3CPU : public BaseFullCPU
|
class FullO3CPU : public BaseFullCPU
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//Put typedefs from the Impl here.
|
// Typedefs from the Impl here.
|
||||||
typedef typename Impl::CPUPol CPUPolicy;
|
typedef typename Impl::CPUPol CPUPolicy;
|
||||||
typedef typename Impl::Params Params;
|
typedef typename Impl::Params Params;
|
||||||
typedef typename Impl::DynInstPtr DynInstPtr;
|
typedef typename Impl::DynInstPtr DynInstPtr;
|
||||||
|
@ -191,20 +192,18 @@ class FullO3CPU : public BaseFullCPU
|
||||||
* Note: this is a virtual function. CPU-Specific
|
* Note: this is a virtual function. CPU-Specific
|
||||||
* functionality defined in derived classes
|
* 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. */
|
/** Check if there are any system calls pending. */
|
||||||
void checkSyscalls();
|
void checkSyscalls();
|
||||||
|
|
||||||
/** Switches out this CPU.
|
/** Switches out this CPU.
|
||||||
* @todo: Implement this.
|
|
||||||
*/
|
*/
|
||||||
void switchOut(Sampler *sampler);
|
void switchOut(Sampler *sampler);
|
||||||
|
|
||||||
void signalSwitched();
|
void signalSwitched();
|
||||||
|
|
||||||
/** Takes over from another CPU.
|
/** Takes over from another CPU.
|
||||||
* @todo: Implement this.
|
|
||||||
*/
|
*/
|
||||||
void takeOverFrom(BaseCPU *oldCPU);
|
void takeOverFrom(BaseCPU *oldCPU);
|
||||||
|
|
||||||
|
@ -299,12 +298,8 @@ class FullO3CPU : public BaseFullCPU
|
||||||
/** Add Instructions to the CPU Remove List*/
|
/** Add Instructions to the CPU Remove List*/
|
||||||
void addToRemoveList(DynInstPtr &inst);
|
void addToRemoveList(DynInstPtr &inst);
|
||||||
|
|
||||||
/** Remove an instruction from the front of the list. It is expected
|
/** Remove an instruction from the front end of the list. There's
|
||||||
* that there are no instructions in front of it (that is, none are older
|
* no restriction on location of the instruction.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
void removeFrontInst(DynInstPtr &inst);
|
void removeFrontInst(DynInstPtr &inst);
|
||||||
|
|
||||||
|
@ -319,15 +314,15 @@ class FullO3CPU : public BaseFullCPU
|
||||||
void cleanUpRemovedInsts();
|
void cleanUpRemovedInsts();
|
||||||
|
|
||||||
/** Remove all instructions from the list. */
|
/** Remove all instructions from the list. */
|
||||||
void removeAllInsts();
|
// void removeAllInsts();
|
||||||
|
|
||||||
void dumpInsts();
|
void dumpInsts();
|
||||||
|
|
||||||
/** Basically a wrapper function so that instructions executed at
|
/** Basically a wrapper function so that instructions executed at
|
||||||
* commit can tell the instruction queue that they have completed.
|
* commit can tell the instruction queue that they have
|
||||||
* Eventually this hack should be removed.
|
* completed. Eventually this hack should be removed.
|
||||||
*/
|
*/
|
||||||
void wakeDependents(DynInstPtr &inst);
|
// void wakeDependents(DynInstPtr &inst);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** List of all the instructions in flight. */
|
/** List of all the instructions in flight. */
|
||||||
|
@ -338,12 +333,12 @@ class FullO3CPU : public BaseFullCPU
|
||||||
*/
|
*/
|
||||||
std::queue<ListIt> removeList;
|
std::queue<ListIt> removeList;
|
||||||
|
|
||||||
//#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
std::set<InstSeqNum> snList;
|
std::set<InstSeqNum> snList;
|
||||||
//#endif
|
#endif
|
||||||
|
|
||||||
/** Records if instructions need to be removed this cycle due to being
|
/** Records if instructions need to be removed this cycle due to
|
||||||
* retired or squashed.
|
* being retired or squashed.
|
||||||
*/
|
*/
|
||||||
bool removeInstsThisCycle;
|
bool removeInstsThisCycle;
|
||||||
|
|
||||||
|
@ -425,46 +420,19 @@ class FullO3CPU : public BaseFullCPU
|
||||||
/** The IEW stage's instruction queue. */
|
/** The IEW stage's instruction queue. */
|
||||||
TimeBuffer<IEWStruct> iewQueue;
|
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;
|
|
||||||
|
|
||||||
/** Records if there has been activity this cycle. */
|
|
||||||
bool activity;
|
|
||||||
|
|
||||||
/** Records which stages are active/inactive. */
|
|
||||||
bool stageActive[NumStages];
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
ActivityRecorder activityRec;
|
||||||
|
|
||||||
|
void activityThisCycle() { activityRec.activity(); }
|
||||||
|
|
||||||
|
void activateStage(const StageIdx idx)
|
||||||
|
{ activityRec.activateStage(idx); }
|
||||||
|
|
||||||
|
void deactivateStage(const StageIdx idx)
|
||||||
|
{ activityRec.deactivateStage(idx); }
|
||||||
|
|
||||||
/** Wakes the CPU, rescheduling the CPU if it's not already active. */
|
/** Wakes the CPU, rescheduling the CPU if it's not already active. */
|
||||||
void wakeCPU();
|
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. */
|
/** Gets a free thread id. Use if thread ids change across system. */
|
||||||
int getFreeTid();
|
int getFreeTid();
|
||||||
|
@ -550,4 +518,4 @@ class FullO3CPU : public BaseFullCPU
|
||||||
Stats::Formula totalIpc;
|
Stats::Formula totalIpc;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif // __CPU_O3_CPU_HH__
|
||||||
|
|
|
@ -3,7 +3,7 @@ from BaseCPU import BaseCPU
|
||||||
|
|
||||||
class DerivAlphaFullCPU(BaseCPU):
|
class DerivAlphaFullCPU(BaseCPU):
|
||||||
type = 'DerivAlphaFullCPU'
|
type = 'DerivAlphaFullCPU'
|
||||||
|
activity = Param.Unsigned("Initial count")
|
||||||
numThreads = Param.Unsigned("number of HW thread contexts")
|
numThreads = Param.Unsigned("number of HW thread contexts")
|
||||||
|
|
||||||
if not build_env['FULL_SYSTEM']:
|
if not build_env['FULL_SYSTEM']:
|
||||||
|
|
Loading…
Reference in a new issue