97c97
< fetchEvent(this)
---
> fetchEvent(this), drainManager(NULL)
101d100
< setDrainState(Drainable::Running);
110,125d108
< void
< TimingSimpleCPU::serialize(ostream &os)
< {
< Drainable::State so_state(getDrainState());
< SERIALIZE_ENUM(so_state);
< BaseSimpleCPU::serialize(os);
< }
<
< void
< TimingSimpleCPU::unserialize(Checkpoint *cp, const string &section)
< {
< Drainable::State so_state;
< UNSERIALIZE_ENUM(so_state);
< BaseSimpleCPU::unserialize(cp, section);
< }
<
129,130d111
< // TimingSimpleCPU is ready to drain if it's not waiting for
< // an access to complete.
132c113
< _status == BaseSimpleCPU::Running ||
---
> (_status == BaseSimpleCPU::Running && isDrained()) ||
134c115,116
< setDrainState(Drainable::Drained);
---
> assert(!fetchEvent.scheduled());
> DPRINTF(Drain, "No need to drain.\n");
137d118
< setDrainState(Drainable::Draining);
139c120,129
< DPRINTF(Drain, "CPU not drained\n");
---
> DPRINTF(Drain, "Requesting drain: %s\n", pcState());
>
> // The fetch event can become descheduled if a drain didn't
> // succeed on the first attempt. We need to reschedule it if
> // the CPU is waiting for a microcode routine to complete.
> if (_status == BaseSimpleCPU::Running && !isDrained() &&
> !fetchEvent.scheduled()) {
> schedule(fetchEvent, nextCycle());
> }
>
146a137,138
> assert(!fetchEvent.scheduled());
>
154,156d145
< if (fetchEvent.scheduled())
< deschedule(fetchEvent);
<
158a148
> }
160c150,164
< setDrainState(Drainable::Running);
---
> bool
> TimingSimpleCPU::tryCompleteDrain()
> {
> if (!drainManager)
> return false;
>
> DPRINTF(Drain, "tryCompleteDrain: %s\n", pcState());
> if (!isDrained())
> return false;
>
> DPRINTF(Drain, "CPU done draining, processing drain event\n");
> drainManager->signalDrainDone();
> drainManager = NULL;
>
> return true;
167a172
> assert(!fetchEvent.scheduled());
168a174,176
> assert(!stayAtPC);
> assert(microPC() == 0);
>
171,175d178
<
< // If we've been scheduled to resume but are then told to switch out,
< // we'll need to cancel it.
< if (fetchEvent.scheduled())
< deschedule(fetchEvent);
347,352c350
< if (getDrainState() == Drainable::Draining) {
< advancePC(fault);
< completeDrain();
< } else {
< advanceInst(fault);
< }
---
> advanceInst(fault);
621d618
<
636a634,636
> if (tryCompleteDrain())
> return;
>
663,672d662
< if (getDrainState() == Drainable::Draining) {
< if (pkt) {
< delete pkt->req;
< delete pkt;
< }
<
< completeDrain();
< return;
< }
<
819,825d808
< if (getDrainState() == Drainable::Draining) {
< advancePC(fault);
< completeDrain();
<
< return;
< }
<
829,837d811
<
< void
< TimingSimpleCPU::completeDrain()
< {
< DPRINTF(Drain, "CPU done draining, processing drain event\n");
< setDrainState(Drainable::Drained);
< drainManager->signalDrainDone();
< }
<