diff options
author | Andreas Sandberg <Andreas.Sandberg@arm.com> | 2012-11-02 11:32:01 -0500 |
---|---|---|
committer | Andreas Sandberg <Andreas.Sandberg@arm.com> | 2012-11-02 11:32:01 -0500 |
commit | b81a977e6ab7dbfd122cb778cfe3d40ca7451198 (patch) | |
tree | 09804c27367de8cf93623ec4644bf47abf316bf9 /src/cpu | |
parent | eb703a4b4e167e4d45f92203a1e0849f19cdba6d (diff) | |
download | gem5-b81a977e6ab7dbfd122cb778cfe3d40ca7451198.tar.xz |
sim: Move the draining interface into a separate base class
This patch moves the draining interface from SimObject to a separate
class that can be used by any object needing draining. However,
objects not visible to the Python code (i.e., objects not deriving
from SimObject) still depend on their parents informing them when to
drain. This patch also gets rid of the CountedDrainEvent (which isn't
really an event) and replaces it with a DrainManager.
Diffstat (limited to 'src/cpu')
-rw-r--r-- | src/cpu/o3/cpu.cc | 26 | ||||
-rw-r--r-- | src/cpu/o3/cpu.hh | 8 | ||||
-rw-r--r-- | src/cpu/simple/atomic.cc | 28 | ||||
-rw-r--r-- | src/cpu/simple/atomic.hh | 4 | ||||
-rw-r--r-- | src/cpu/simple/timing.cc | 59 | ||||
-rw-r--r-- | src/cpu/simple/timing.hh | 8 | ||||
-rw-r--r-- | src/cpu/testers/traffic_gen/traffic_gen.cc | 4 | ||||
-rw-r--r-- | src/cpu/testers/traffic_gen/traffic_gen.hh | 2 |
8 files changed, 76 insertions, 63 deletions
diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index fdd45fdda..bc5f096e6 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -619,7 +619,7 @@ FullO3CPU<Impl>::tick() if (!tickEvent.scheduled()) { if (_status == SwitchedOut || - getState() == SimObject::Drained) { + getDrainState() == Drainable::Drained) { DPRINTF(O3CPU, "Switched out!\n"); // increment stat lastRunningCycle = curCycle(); @@ -1077,7 +1077,7 @@ template <class Impl> void FullO3CPU<Impl>::serialize(std::ostream &os) { - SimObject::State so_state = SimObject::getState(); + Drainable::State so_state(getDrainState()); SERIALIZE_ENUM(so_state); BaseCPU::serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); @@ -1100,7 +1100,7 @@ template <class Impl> void FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) { - SimObject::State so_state; + Drainable::State so_state; UNSERIALIZE_ENUM(so_state); BaseCPU::unserialize(cp, section); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); @@ -1120,7 +1120,7 @@ FullO3CPU<Impl>::unserialize(Checkpoint *cp, const std::string §ion) template <class Impl> unsigned int -FullO3CPU<Impl>::drain(Event *drain_event) +FullO3CPU<Impl>::drain(DrainManager *drain_manager) { DPRINTF(O3CPU, "Switching out\n"); @@ -1137,12 +1137,12 @@ FullO3CPU<Impl>::drain(Event *drain_event) // Wake the CPU and record activity so everything can drain out if // the CPU was not able to immediately drain. - if (getState() != SimObject::Drained) { - // A bit of a hack...set the drainEvent after all the drain() + if (getDrainState() != Drainable::Drained) { + // A bit of a hack...set the drainManager 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; + drainManager = drain_manager; wakeCPU(); activityRec.activity(); @@ -1157,7 +1157,7 @@ FullO3CPU<Impl>::drain(Event *drain_event) template <class Impl> void -FullO3CPU<Impl>::resume() +FullO3CPU<Impl>::drainResume() { fetch.resume(); decode.resume(); @@ -1165,7 +1165,7 @@ FullO3CPU<Impl>::resume() iew.resume(); commit.resume(); - changeState(SimObject::Running); + setDrainState(Drainable::Running); if (_status == SwitchedOut) return; @@ -1185,14 +1185,14 @@ FullO3CPU<Impl>::signalDrained() if (tickEvent.scheduled()) tickEvent.squash(); - changeState(SimObject::Drained); + setDrainState(Drainable::Drained); BaseCPU::switchOut(); - if (drainEvent) { + if (drainManager) { DPRINTF(Drain, "CPU done draining, processing drain event\n"); - drainEvent->process(); - drainEvent = NULL; + drainManager->signalDrainDone(); + drainManager = NULL; } } assert(drainCount <= 5); diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index 076cce0fb..1f9a8da6c 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -431,10 +431,10 @@ class FullO3CPU : public BaseO3CPU /** Starts draining the CPU's pipeline of all instructions in * order to stop all memory accesses. */ - virtual unsigned int drain(Event *drain_event); + unsigned int drain(DrainManager *drain_manager); /** Resumes execution after a drain. */ - virtual void resume(); + void drainResume(); /** Signals to this CPU that a stage has completed switching out. */ void signalDrained(); @@ -730,8 +730,8 @@ class FullO3CPU : public BaseO3CPU /** Pointer to the system. */ System *system; - /** Event to call process() on once draining has completed. */ - Event *drainEvent; + /** DrainManager to notify when draining has completed. */ + DrainManager *drainManager; /** Counter of how many stages have completed draining. */ int drainCount; diff --git a/src/cpu/simple/atomic.cc b/src/cpu/simple/atomic.cc index 2d7afd221..e63d998a7 100644 --- a/src/cpu/simple/atomic.cc +++ b/src/cpu/simple/atomic.cc @@ -123,7 +123,7 @@ AtomicSimpleCPU::~AtomicSimpleCPU() void AtomicSimpleCPU::serialize(ostream &os) { - SimObject::State so_state = SimObject::getState(); + Drainable::State so_state(getDrainState()); SERIALIZE_ENUM(so_state); SERIALIZE_SCALAR(locked); BaseSimpleCPU::serialize(os); @@ -134,15 +134,22 @@ AtomicSimpleCPU::serialize(ostream &os) void AtomicSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { - SimObject::State so_state; + Drainable::State so_state; UNSERIALIZE_ENUM(so_state); UNSERIALIZE_SCALAR(locked); BaseSimpleCPU::unserialize(cp, section); tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); } +unsigned int +AtomicSimpleCPU::drain(DrainManager *drain_manager) +{ + setDrainState(Drainable::Drained); + return 0; +} + void -AtomicSimpleCPU::resume() +AtomicSimpleCPU::drainResume() { if (_status == Idle || _status == SwitchedOut) return; @@ -150,7 +157,7 @@ AtomicSimpleCPU::resume() DPRINTF(SimpleCPU, "Resume\n"); assert(system->getMemoryMode() == Enums::atomic); - changeState(SimObject::Running); + setDrainState(Drainable::Running); if (thread->status() == ThreadContext::Active) { if (!tickEvent.scheduled()) schedule(tickEvent, nextCycle()); @@ -161,7 +168,7 @@ AtomicSimpleCPU::resume() void AtomicSimpleCPU::switchOut() { - assert(_status == Running || _status == Idle); + assert(_status == BaseSimpleCPU::Running || _status == Idle); _status = SwitchedOut; tickEvent.squash(); @@ -180,13 +187,14 @@ AtomicSimpleCPU::takeOverFrom(BaseCPU *oldCPU) ThreadID size = threadContexts.size(); for (ThreadID i = 0; i < size; ++i) { ThreadContext *tc = threadContexts[i]; - if (tc->status() == ThreadContext::Active && _status != Running) { - _status = Running; + if (tc->status() == ThreadContext::Active && + _status != BaseSimpleCPU::Running) { + _status = BaseSimpleCPU::Running; schedule(tickEvent, nextCycle()); break; } } - if (_status != Running) { + if (_status != BaseSimpleCPU::Running) { _status = Idle; } assert(threadContexts.size() == 1); @@ -212,7 +220,7 @@ AtomicSimpleCPU::activateContext(ThreadID thread_num, Cycles delay) //Make sure ticks are still on multiples of cycles schedule(tickEvent, clockEdge(delay)); - _status = Running; + _status = BaseSimpleCPU::Running; } @@ -227,7 +235,7 @@ AtomicSimpleCPU::suspendContext(ThreadID thread_num) if (_status == Idle) return; - assert(_status == Running); + assert(_status == BaseSimpleCPU::Running); // tick event may not be scheduled if this gets called from inside // an instruction's execution, e.g. "quiesce" diff --git a/src/cpu/simple/atomic.hh b/src/cpu/simple/atomic.hh index d67ab67a5..94d2de081 100644 --- a/src/cpu/simple/atomic.hh +++ b/src/cpu/simple/atomic.hh @@ -122,7 +122,9 @@ class AtomicSimpleCPU : public BaseSimpleCPU virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); - virtual void resume(); + + unsigned int drain(DrainManager *drain_manager); + void drainResume(); void switchOut(); void takeOverFrom(BaseCPU *oldCPU); diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc index 15b277d53..41764302d 100644 --- a/src/cpu/simple/timing.cc +++ b/src/cpu/simple/timing.cc @@ -92,7 +92,7 @@ TimingSimpleCPU::TimingSimpleCPU(TimingSimpleCPUParams *p) { _status = Idle; - changeState(SimObject::Running); + setDrainState(Drainable::Running); system->totalNumInsts = 0; } @@ -104,7 +104,7 @@ TimingSimpleCPU::~TimingSimpleCPU() void TimingSimpleCPU::serialize(ostream &os) { - SimObject::State so_state = SimObject::getState(); + Drainable::State so_state(getDrainState()); SERIALIZE_ENUM(so_state); BaseSimpleCPU::serialize(os); } @@ -112,29 +112,31 @@ TimingSimpleCPU::serialize(ostream &os) void TimingSimpleCPU::unserialize(Checkpoint *cp, const string §ion) { - SimObject::State so_state; + Drainable::State so_state; UNSERIALIZE_ENUM(so_state); BaseSimpleCPU::unserialize(cp, section); } unsigned int -TimingSimpleCPU::drain(Event *drain_event) +TimingSimpleCPU::drain(DrainManager *drain_manager) { // TimingSimpleCPU is ready to drain if it's not waiting for // an access to complete. - if (_status == Idle || _status == Running || _status == SwitchedOut) { - changeState(SimObject::Drained); + if (_status == Idle || + _status == BaseSimpleCPU::Running || + _status == SwitchedOut) { + setDrainState(Drainable::Drained); return 0; } else { - changeState(SimObject::Draining); - drainEvent = drain_event; + setDrainState(Drainable::Draining); + drainManager = drain_manager; DPRINTF(Drain, "CPU not drained\n"); return 1; } } void -TimingSimpleCPU::resume() +TimingSimpleCPU::drainResume() { DPRINTF(SimpleCPU, "Resume\n"); if (_status != SwitchedOut && _status != Idle) { @@ -146,13 +148,13 @@ TimingSimpleCPU::resume() schedule(fetchEvent, nextCycle()); } - changeState(SimObject::Running); + setDrainState(Drainable::Running); } void TimingSimpleCPU::switchOut() { - assert(_status == Running || _status == Idle); + assert(_status == BaseSimpleCPU::Running || _status == Idle); _status = SwitchedOut; numCycles += curCycle() - previousCycle; @@ -172,13 +174,14 @@ TimingSimpleCPU::takeOverFrom(BaseCPU *oldCPU) // running and schedule its tick event. for (int i = 0; i < threadContexts.size(); ++i) { ThreadContext *tc = threadContexts[i]; - if (tc->status() == ThreadContext::Active && _status != Running) { - _status = Running; + if (tc->status() == ThreadContext::Active && + _status != BaseSimpleCPU::Running) { + _status = BaseSimpleCPU::Running; break; } } - if (_status != Running) { + if (_status != BaseSimpleCPU::Running) { _status = Idle; } assert(threadContexts.size() == 1); @@ -197,7 +200,7 @@ TimingSimpleCPU::activateContext(ThreadID thread_num, Cycles delay) assert(_status == Idle); notIdleFraction++; - _status = Running; + _status = BaseSimpleCPU::Running; // kick things off by initiating the fetch of the next instruction schedule(fetchEvent, clockEdge(delay)); @@ -215,7 +218,7 @@ TimingSimpleCPU::suspendContext(ThreadID thread_num) if (_status == Idle) return; - assert(_status == Running); + assert(_status == BaseSimpleCPU::Running); // just change status to Idle... if status != Running, // completeInst() will not initiate fetch of next instruction. @@ -330,7 +333,7 @@ TimingSimpleCPU::translationFault(Fault fault) postExecute(); - if (getState() == SimObject::Draining) { + if (getDrainState() == Drainable::Draining) { advancePC(fault); completeDrain(); } else { @@ -511,7 +514,7 @@ TimingSimpleCPU::writeMem(uint8_t *data, unsigned size, void TimingSimpleCPU::finishTranslation(WholeTranslationState *state) { - _status = Running; + _status = BaseSimpleCPU::Running; if (state->getFault() != NoFault) { if (state->isPrefetch()) { @@ -552,7 +555,7 @@ TimingSimpleCPU::fetch() bool needToFetch = !isRomMicroPC(pcState.microPC()) && !curMacroStaticInst; if (needToFetch) { - _status = Running; + _status = BaseSimpleCPU::Running; Request *ifetch_req = new Request(); ifetch_req->setThreadContext(_cpuId, /* thread ID */ 0); setupFetchRequest(ifetch_req); @@ -592,7 +595,7 @@ TimingSimpleCPU::sendFetch(Fault fault, RequestPtr req, ThreadContext *tc) DPRINTF(SimpleCPU, "Translation of addr %#x faulted\n", req->getVaddr()); delete req; // fetch fault: advance directly to next instruction (fault handler) - _status = Running; + _status = BaseSimpleCPU::Running; advanceInst(fault); } @@ -620,7 +623,7 @@ TimingSimpleCPU::advanceInst(Fault fault) if (!stayAtPC) advancePC(fault); - if (_status == Running) { + if (_status == BaseSimpleCPU::Running) { // kick off fetch of next instruction... callback from icache // response will cause that instruction to be executed, // keeping the CPU running. @@ -641,12 +644,12 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) assert(!pkt || !pkt->isError()); assert(_status == IcacheWaitResponse); - _status = Running; + _status = BaseSimpleCPU::Running; numCycles += curCycle() - previousCycle; previousCycle = curCycle(); - if (getState() == SimObject::Draining) { + if (getDrainState() == Drainable::Draining) { if (pkt) { delete pkt->req; delete pkt; @@ -664,7 +667,7 @@ TimingSimpleCPU::completeIfetch(PacketPtr pkt) // If we're not running now the instruction will complete in a dcache // response callback or the instruction faulted and has started an // ifetch - if (_status == Running) { + if (_status == BaseSimpleCPU::Running) { if (fault != NoFault && traceData) { // If there was a fault, we shouldn't trace this instruction. delete traceData; @@ -778,7 +781,7 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt) } } - _status = Running; + _status = BaseSimpleCPU::Running; Fault fault = curStaticInst->completeAcc(pkt, this, traceData); @@ -802,7 +805,7 @@ TimingSimpleCPU::completeDataAccess(PacketPtr pkt) postExecute(); - if (getState() == SimObject::Draining) { + if (getDrainState() == Drainable::Draining) { advancePC(fault); completeDrain(); @@ -817,8 +820,8 @@ void TimingSimpleCPU::completeDrain() { DPRINTF(Drain, "CPU done draining, processing drain event\n"); - changeState(SimObject::Drained); - drainEvent->process(); + setDrainState(Drainable::Drained); + drainManager->signalDrainDone(); } bool diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh index a2570abe6..e7f5122d0 100644 --- a/src/cpu/simple/timing.hh +++ b/src/cpu/simple/timing.hh @@ -45,7 +45,7 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void init(); public: - Event *drainEvent; + DrainManager *drainManager; private: @@ -109,7 +109,7 @@ class TimingSimpleCPU : public BaseSimpleCPU void markDelayed() { - assert(cpu->_status == Running); + assert(cpu->_status == BaseSimpleCPU::Running); cpu->_status = ITBWaitResponse; } @@ -249,8 +249,8 @@ class TimingSimpleCPU : public BaseSimpleCPU virtual void serialize(std::ostream &os); virtual void unserialize(Checkpoint *cp, const std::string §ion); - virtual unsigned int drain(Event *drain_event); - virtual void resume(); + unsigned int drain(DrainManager *drain_manager); + void drainResume(); void switchOut(); void takeOverFrom(BaseCPU *oldCPU); diff --git a/src/cpu/testers/traffic_gen/traffic_gen.cc b/src/cpu/testers/traffic_gen/traffic_gen.cc index af7ff89f4..e0657822c 100644 --- a/src/cpu/testers/traffic_gen/traffic_gen.cc +++ b/src/cpu/testers/traffic_gen/traffic_gen.cc @@ -110,11 +110,11 @@ TrafficGen::initState() } unsigned int -TrafficGen::drain(Event* drain_event) +TrafficGen::drain(DrainManager *dm) { // @todo we should also stop putting new requests in the queue and // either interrupt the current state or wait for a transition - return port.drain(drain_event); + return port.drain(dm); } void diff --git a/src/cpu/testers/traffic_gen/traffic_gen.hh b/src/cpu/testers/traffic_gen/traffic_gen.hh index 5f59be82c..4e94df548 100644 --- a/src/cpu/testers/traffic_gen/traffic_gen.hh +++ b/src/cpu/testers/traffic_gen/traffic_gen.hh @@ -604,7 +604,7 @@ class TrafficGen : public MemObject void initState(); - unsigned int drain(Event *drain_event); + unsigned int drain(DrainManager *dm); void serialize(std::ostream &os); |