/** Initializes stage by sending back the number of free entries. */
void initStage();
- /** Initializes the switching out of commit. */
- void switchOut();
+ /** Initializes the draining of commit. */
+ void drain();
+
+ /** Resumes execution after draining. */
+ void resume();
/** Completes the switch out of commit. */
- void doSwitchOut();
+ void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
/** Number of Active Threads */
unsigned numThreads;
- /** Is a switch out pending. */
- bool switchPending;
+ /** Is a drain pending. */
+ bool drainPending;
/** Is commit switched out. */
bool switchedOut;
renameWidth(params->renameWidth),
commitWidth(params->commitWidth),
numThreads(params->numberOfThreads),
- switchPending(false),
+ drainPending(false),
switchedOut(false),
trapLatency(params->trapLatency),
fetchTrapLatency(params->fetchTrapLatency)
template <class Impl>
void
-DefaultCommit<Impl>::switchOut()
+DefaultCommit<Impl>::drain()
{
- switchPending = true;
+ drainPending = true;
}
template <class Impl>
void
-DefaultCommit<Impl>::doSwitchOut()
+DefaultCommit<Impl>::switchOut()
{
switchedOut = true;
- switchPending = false;
+ drainPending = false;
rob->switchOut();
}
+template <class Impl>
+void
+DefaultCommit<Impl>::resume()
+{
+}
+
template <class Impl>
void
DefaultCommit<Impl>::takeOverFrom()
wroteToTimeBuffer = false;
_nextStatus = Inactive;
- if (switchPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
- cpu->signalSwitched();
+ if (drainPending && rob->isEmpty() && !iewStage->hasStoresToWB()) {
+ cpu->signalDrained();
+ drainPending = false;
return;
}
physmem(system->physmem),
#endif // FULL_SYSTEM
mem(params->mem),
- switchCount(0),
+ drainCount(0),
deferRegistration(params->deferRegistration),
numThreads(number_of_threads)
{
}
template <class Impl>
-void
-FullO3CPU<Impl>::switchOut()
+bool
+FullO3CPU<Impl>::drain(Event *drain_event)
{
- switchCount = 0;
- fetch.switchOut();
- decode.switchOut();
- rename.switchOut();
- iew.switchOut();
- commit.switchOut();
+ drainCount = 0;
+ drainEvent = drain_event;
+ fetch.drain();
+ decode.drain();
+ rename.drain();
+ iew.drain();
+ commit.drain();
// Wake the CPU and record activity so everything can drain out if
// the CPU is currently idle.
wakeCPU();
activityRec.activity();
+
+ return false;
}
template <class Impl>
void
-FullO3CPU<Impl>::signalSwitched()
-{
- if (++switchCount == NumStages) {
- fetch.doSwitchOut();
- rename.doSwitchOut();
- commit.doSwitchOut();
- instList.clear();
- while (!removeList.empty()) {
- removeList.pop();
- }
+FullO3CPU<Impl>::resume()
+{
+ if (_status == SwitchedOut)
+ return;
+ fetch.resume();
+ decode.resume();
+ rename.resume();
+ iew.resume();
+ commit.resume();
-#if USE_CHECKER
- if (checker)
- checker->switchOut();
-#endif
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick);
+ _status = Running;
+}
+template <class Impl>
+void
+FullO3CPU<Impl>::signalDrained()
+{
+ if (++drainCount == NumStages) {
if (tickEvent.scheduled())
tickEvent.squash();
- _status = SwitchedOut;
+ _status = Drained;
+ drainEvent->process();
}
- assert(switchCount <= 5);
+ assert(drainCount <= 5);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::switchOut()
+{
+ fetch.switchOut();
+ rename.switchOut();
+ commit.switchOut();
+ instList.clear();
+ while (!removeList.empty()) {
+ removeList.pop();
+ }
+
+ _status = SwitchedOut;
+#if USE_CHECKER
+ if (checker)
+ checker->switchOut();
+#endif
}
template <class Impl>
class ThreadContext;
template <class>
class O3ThreadContext;
+
+class Checkpoint;
class MemObject;
class Process;
Idle,
Halted,
Blocked,
+ Drained,
SwitchedOut
};
*/
virtual void syscall(int tid) { panic("Unimplemented!"); }
- /** Switches out this CPU. */
- void switchOut();
+ /** Starts draining the CPU's pipeline of all instructions in
+ * order to stop all memory accesses. */
+ virtual bool drain(Event *drain_event);
+
+ /** Resumes execution after a drain. */
+ virtual void resume();
/** Signals to this CPU that a stage has completed switching out. */
- void signalSwitched();
+ void signalDrained();
+
+ /** Switches out this CPU. */
+ virtual void switchOut();
/** Takes over from another CPU. */
- void takeOverFrom(BaseCPU *oldCPU);
+ virtual void takeOverFrom(BaseCPU *oldCPU);
/** Get the current instruction sequence number, and increment it. */
InstSeqNum getAndIncrementInstSeq()
/** Pointer to memory. */
MemObject *mem;
- /** Counter of how many stages have completed switching out. */
- int switchCount;
+ /** Event to call process() on once draining has completed. */
+ Event *drainEvent;
+
+ /** Counter of how many stages have completed draining. */
+ int drainCount;
/** Pointers to all of the threads in the CPU. */
std::vector<Thread *> thread;
/** Sets pointer to list of active threads. */
void setActiveThreads(std::list<unsigned> *at_ptr);
+ /** Drains the decode stage. */
+ void drain();
+
+ /** Resumes execution after a drain. */
+ void resume() { }
+
/** Switches out the decode stage. */
- void switchOut();
+ void switchOut() { }
/** Takes over from another CPU's thread. */
void takeOverFrom();
template <class Impl>
void
-DefaultDecode<Impl>::switchOut()
+DefaultDecode<Impl>::drain()
{
- // Decode can immediately switch out.
- cpu->signalSwitched();
+ // Decode is done draining at any time.
+ cpu->signalDrained();
}
template <class Impl>
/** Processes cache completion event. */
void processCacheCompletion(PacketPtr pkt);
- /** Begins the switch out of the fetch stage. */
- void switchOut();
+ /** Begins the drain of the fetch stage. */
+ void drain();
+
+ /** Resumes execution after a drain. */
+ void resume();
- /** Completes the switch out of the fetch stage. */
- void doSwitchOut();
+ /** Tells fetch stage to prepare to be switched out. */
+ void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
*/
bool interruptPending;
+ /** Is there a drain pending. */
+ bool drainPending;
+
/** Records if fetch is switched out. */
bool switchedOut;
numThreads(params->numberOfThreads),
numFetchingThreads(params->smtNumFetchingThreads),
interruptPending(false),
+ drainPending(false),
switchedOut(false)
{
if (numThreads > Impl::MaxThreads)
// to return.
if (fetchStatus[tid] != IcacheWaitResponse ||
pkt->req != memReq[tid] ||
- isSwitchedOut()) {
+ isSwitchedOut() ||
+ drainPending) {
++fetchIcacheSquashes;
delete pkt->req;
delete pkt;
template <class Impl>
void
-DefaultFetch<Impl>::switchOut()
+DefaultFetch<Impl>::drain()
{
- // Fetch is ready to switch out at any time.
- switchedOut = true;
- cpu->signalSwitched();
+ // Fetch is ready to drain at any time.
+ cpu->signalDrained();
+ drainPending = true;
}
template <class Impl>
void
-DefaultFetch<Impl>::doSwitchOut()
+DefaultFetch<Impl>::resume()
{
+ drainPending = false;
+}
+
+template <class Impl>
+void
+DefaultFetch<Impl>::switchOut()
+{
+ switchedOut = true;
// Branch predictor needs to have its state cleared.
branchPred.switchOut();
}
unsigned flags = 0;
#endif // FULL_SYSTEM
- if (cacheBlocked || (interruptPending && flags == 0) || switchedOut) {
+ if (cacheBlocked || (interruptPending && flags == 0) || drainPending) {
// Hold off fetch from getting new instructions when:
// Cache is blocked, or
// while an interrupt is pending and we're not in PAL mode, or
/** Sets pointer to the scoreboard. */
void setScoreboard(Scoreboard *sb_ptr);
- /** Starts switch out of IEW stage. */
- void switchOut();
+ /** Drains IEW stage. */
+ void drain();
+
+ /** Resumes execution after a drain. */
+ void resume();
/** Completes switch out of IEW stage. */
- void doSwitchOut();
+ void switchOut();
/** Takes over from another CPU's thread. */
void takeOverFrom();
template <class Impl>
void
-DefaultIEW<Impl>::switchOut()
+DefaultIEW<Impl>::drain()
{
- // IEW is ready to switch out at any time.
- cpu->signalSwitched();
+ // IEW is ready to drain at any time.
+ cpu->signalDrained();
}
template <class Impl>
void
-DefaultIEW<Impl>::doSwitchOut()
+DefaultIEW<Impl>::resume()
+{
+}
+
+template <class Impl>
+void
+DefaultIEW<Impl>::switchOut()
{
// Clear any state.
switchedOut = true;
/** Sets pointer to the scoreboard. */
void setScoreboard(Scoreboard *_scoreboard);
+ /** Drains the rename stage. */
+ void drain();
+
+ /** Resumes execution after a drain. */
+ void resume() { }
+
/** Switches out the rename stage. */
void switchOut();
- /** Completes the switch out. */
- void doSwitchOut();
-
/** Takes over from another CPU's thread. */
void takeOverFrom();
template <class Impl>
void
-DefaultRename<Impl>::switchOut()
+DefaultRename<Impl>::drain()
{
// Rename is ready to switch out at any time.
- cpu->signalSwitched();
+ cpu->signalDrained();
}
template <class Impl>
void
-DefaultRename<Impl>::doSwitchOut()
+DefaultRename<Impl>::switchOut()
{
// Clear any state, fix up the rename map.
for (int i = 0; i < numThreads; i++) {