physmem(system->physmem),
#endif // FULL_SYSTEM
mem(params->mem),
- switchCount(0),
+ drainCount(0),
deferRegistration(params->deferRegistration),
numThreads(number_of_threads)
{
}
if (!tickEvent.scheduled()) {
- if (_status == SwitchedOut) {
+ if (_status == SwitchedOut ||
+ getState() == SimObject::DrainedTiming) {
// increment stat
lastRunningCycle = curTick;
} else if (!activityRec.active()) {
template <class Impl>
void
-FullO3CPU<Impl>::switchOut(Sampler *_sampler)
+FullO3CPU<Impl>::serialize(std::ostream &os)
+{
+ SERIALIZE_ENUM(_status);
+ BaseCPU::serialize(os);
+ nameOut(os, csprintf("%s.tickEvent", name()));
+ tickEvent.serialize(os);
+
+ // Use SimpleThread's ability to checkpoint to make it easier to
+ // write out the registers. Also make this static so it doesn't
+ // get instantiated multiple times (causes a panic in statistics).
+ static SimpleThread temp;
+
+ for (int i = 0; i < thread.size(); i++) {
+ nameOut(os, csprintf("%s.xc.%i", name(), i));
+ temp.copyTC(thread[i]->getTC());
+ temp.serialize(os);
+ }
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion)
{
- sampler = _sampler;
- switchCount = 0;
- fetch.switchOut();
- decode.switchOut();
- rename.switchOut();
- iew.switchOut();
- commit.switchOut();
+ UNSERIALIZE_ENUM(_status);
+ BaseCPU::unserialize(cp, section);
+ tickEvent.unserialize(cp, csprintf("%s.tickEvent", section));
+
+ // Use SimpleThread's ability to checkpoint to make it easier to
+ // read in the registers. Also make this static so it doesn't
+ // get instantiated multiple times (causes a panic in statistics).
+ static SimpleThread temp;
+
+ for (int i = 0; i < thread.size(); i++) {
+ temp.copyTC(thread[i]->getTC());
+ temp.unserialize(cp, csprintf("%s.xc.%i", section, i));
+ thread[i]->getTC()->copyArchRegs(temp.getTC());
+ }
+}
+
+template <class Impl>
+bool
+FullO3CPU<Impl>::drain(Event *drain_event)
+{
+ drainCount = 0;
+ 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();
+ // the CPU was not able to immediately drain.
+ if (getState() != SimObject::DrainedTiming) {
+ // A bit of a hack...set the drainEvent after all the drain()
+ // calls have been made, that way if all of the stages drain
+ // immediately, the signalDrained() function knows not to call
+ // process on the drain event.
+ drainEvent = drain_event;
+
+ wakeCPU();
+ activityRec.activity();
+
+ return false;
+ } else {
+ return true;
+ }
}
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()
+{
+ fetch.resume();
+ decode.resume();
+ rename.resume();
+ iew.resume();
+ commit.resume();
-#if USE_CHECKER
- if (checker)
- checker->switchOut(sampler);
-#endif
+ if (_status == SwitchedOut || _status == Idle)
+ return;
+ if (!tickEvent.scheduled())
+ tickEvent.schedule(curTick);
+ _status = Running;
+ changeState(SimObject::Timing);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::signalDrained()
+{
+ if (++drainCount == NumStages) {
if (tickEvent.scheduled())
tickEvent.squash();
- sampler->signalSwitched();
- _status = SwitchedOut;
+
+ changeState(SimObject::DrainedTiming);
+
+ if (drainEvent) {
+ drainEvent->process();
+ drainEvent = NULL;
+ }
+ }
+ assert(drainCount <= 5);
+}
+
+template <class Impl>
+void
+FullO3CPU<Impl>::switchOut()
+{
+ fetch.switchOut();
+ rename.switchOut();
+ commit.switchOut();
+ instList.clear();
+ while (!removeList.empty()) {
+ removeList.pop();
}
- assert(switchCount <= 5);
+
+ _status = SwitchedOut;
+#if USE_CHECKER
+ if (checker)
+ checker->switchOut();
+#endif
}
template <class Impl>