2c2
< * Copyright (c) 2010-2011 ARM Limited
---
> * Copyright (c) 2010-2012 ARM Limited
60a61
> #include "debug/Drain.hh"
76d76
< numInst(0),
82d81
< cacheBlocked(false),
87,89d85
< interruptPending(false),
< drainPending(false),
< switchedOut(false),
101,103d96
< // Set fetch stage's status to inactive.
< _status = Inactive;
<
306a300,317
> assert(priorityList.empty());
> resetStage();
>
> // Fetch needs to start fetching instructions at the very beginning,
> // so it must start up in active state.
> switchToActive();
> }
>
> template<class Impl>
> void
> DefaultFetch<Impl>::resetStage()
> {
> numInst = 0;
> interruptPending = false;
> cacheBlocked = false;
>
> priorityList.clear();
>
308a320
> fetchStatus[tid] = Running;
312,313d323
< delayedCommit[tid] = false;
< }
315,320c325
< for (ThreadID tid = 0; tid < numThreads; tid++) {
<
< fetchStatus[tid] = Running;
<
< priorityList.push_back(tid);
<
---
> delayedCommit[tid] = false;
326a332,334
> stalls[tid].drain = false;
>
> priorityList.push_back(tid);
329,330c337,338
< // Schedule fetch to get the correct PC from the CPU
< // scheduleFetchStartupEvent(1);
---
> wroteToTimeBuffer = false;
> _status = Inactive;
332,334c340,345
< // Fetch needs to start fetching instructions at the very beginning,
< // so it must start up in active state.
< switchToActive();
---
> // this CPU could still be unconnected if we are restoring from a
> // checkpoint and this CPU is to be switched in, thus we can only
> // do this here if the instruction port is actually connected, if
> // not we have to do it as part of takeOverFrom.
> if (cpu->getInstPort().isConnected())
> setIcache();
364a376
> assert(!cpu->switchedOut());
369,370c381
< pkt->req != memReq[tid] ||
< isSwitchedOut()) {
---
> pkt->req != memReq[tid]) {
380,383c391,393
< if (!drainPending) {
< // Wake up the CPU (if it went to sleep and was waiting on
< // this completion event).
< cpu->wakeCPU();
---
> // Wake up the CPU (if it went to sleep and was waiting on
> // this completion event).
> cpu->wakeCPU();
385,386c395,396
< DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
< tid);
---
> DPRINTF(Activity, "[tid:%u] Activating fetch due to cache completion\n",
> tid);
388,389c398
< switchToActive();
< }
---
> switchToActive();
405,406c414,415
< bool
< DefaultFetch<Impl>::drain()
---
> void
> DefaultFetch<Impl>::drainResume()
408,411c417,418
< // Fetch is ready to drain at any time.
< cpu->signalDrained();
< drainPending = true;
< return true;
---
> for (ThreadID i = 0; i < Impl::MaxThreads; ++i)
> stalls[i].drain = false;
416c423
< DefaultFetch<Impl>::resume()
---
> DefaultFetch<Impl>::drainSanityCheck() const
418c425,440
< drainPending = false;
---
> assert(isDrained());
> assert(retryPkt == NULL);
> assert(retryTid == InvalidThreadID);
> assert(cacheBlocked == false);
> assert(interruptPending == false);
>
> for (ThreadID i = 0; i < numThreads; ++i) {
> assert(!memReq[i]);
> assert(!stalls[i].decode);
> assert(!stalls[i].rename);
> assert(!stalls[i].iew);
> assert(!stalls[i].commit);
> assert(fetchStatus[i] == Idle || stalls[i].drain);
> }
>
> branchPred.drainSanityCheck();
422,423c444,445
< void
< DefaultFetch<Impl>::switchOut()
---
> bool
> DefaultFetch<Impl>::isDrained() const
425,427c447,463
< switchedOut = true;
< // Branch predictor needs to have its state cleared.
< branchPred.switchOut();
---
> /* Make sure that threads are either idle of that the commit stage
> * has signaled that draining has completed by setting the drain
> * stall flag. This effectively forces the pipeline to be disabled
> * until the whole system is drained (simulation may continue to
> * drain other components).
> */
> for (ThreadID i = 0; i < numThreads; ++i) {
> if (!(fetchStatus[i] == Idle ||
> (fetchStatus[i] == Blocked && stalls[i].drain)))
> return false;
> }
>
> /* The pipeline might start up again in the middle of the drain
> * cycle if the finish translation event is scheduled, so make
> * sure that's not the case.
> */
> return !finishTranslationEvent.scheduled();
434,436c470,471
< // the instruction port is now connected so we can get the block
< // size
< setIcache();
---
> assert(cpu->getInstPort().isConnected());
> resetStage();
438,451d472
< // Reset all state
< for (ThreadID i = 0; i < Impl::MaxThreads; ++i) {
< stalls[i].decode = 0;
< stalls[i].rename = 0;
< stalls[i].iew = 0;
< stalls[i].commit = 0;
< pc[i] = cpu->pcState(i);
< fetchStatus[i] = Running;
< }
< numInst = 0;
< wroteToTimeBuffer = false;
< _status = Inactive;
< switchedOut = false;
< interruptPending = false;
456a478,487
> DefaultFetch<Impl>::drainStall(ThreadID tid)
> {
> assert(cpu->isDraining());
> assert(!stalls[tid].drain);
> DPRINTF(Drain, "%i: Thread drained.\n", tid);
> stalls[tid].drain = true;
> }
>
> template <class Impl>
> void
538a570,571
> assert(!cpu->switchedOut());
>
545,548d577
< } else if (isSwitchedOut()) {
< DPRINTF(Fetch, "[tid:%i] Can't fetch cache line, switched out\n",
< tid);
< return false;
588a618,619
> assert(!cpu->switchedOut());
>
593c624
< mem_req->getVaddr() != memReq[tid]->getVaddr() || isSwitchedOut()) {
---
> mem_req->getVaddr() != memReq[tid]->getVaddr()) {
759a791,794
> } else if (stalls[tid].drain) {
> assert(cpu->isDraining());
> DPRINTF(Fetch,"[tid:%i]: Drain stall detected.\n",tid);
> ret_val = true;
1100c1135,1137
< if (tid == InvalidThreadID || drainPending) {
---
> assert(!cpu->switchedOut());
>
> if (tid == InvalidThreadID) {
1150,1151c1187
< } else if ((checkInterrupt(thisPC.instAddr()) && !delayedCommit[tid])
< || isSwitchedOut()) {
---
> } else if ((checkInterrupt(thisPC.instAddr()) && !delayedCommit[tid])) {
1569c1605
< if (drainPending) {
---
> if (stalls[tid].drain) {