diff options
Diffstat (limited to 'src/cpu/o3')
-rw-r--r-- | src/cpu/o3/commit.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/commit_impl.hh | 11 | ||||
-rw-r--r-- | src/cpu/o3/cpu.cc | 78 | ||||
-rw-r--r-- | src/cpu/o3/cpu.hh | 8 | ||||
-rw-r--r-- | src/cpu/o3/decode.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/decode_impl.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/fetch.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/fetch_impl.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/iew.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/iew_impl.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/lsq_impl.hh | 3 | ||||
-rw-r--r-- | src/cpu/o3/regfile.hh | 4 | ||||
-rw-r--r-- | src/cpu/o3/rename.hh | 2 | ||||
-rw-r--r-- | src/cpu/o3/rename_impl.hh | 3 |
14 files changed, 101 insertions, 25 deletions
diff --git a/src/cpu/o3/commit.hh b/src/cpu/o3/commit.hh index 49ff5cdad..c39bc10f9 100644 --- a/src/cpu/o3/commit.hh +++ b/src/cpu/o3/commit.hh @@ -188,7 +188,7 @@ class DefaultCommit void initStage(); /** Initializes the draining of commit. */ - void drain(); + bool drain(); /** Resumes execution after draining. */ void resume(); diff --git a/src/cpu/o3/commit_impl.hh b/src/cpu/o3/commit_impl.hh index 2eb05afac..39e1cf3fe 100644 --- a/src/cpu/o3/commit_impl.hh +++ b/src/cpu/o3/commit_impl.hh @@ -350,10 +350,18 @@ DefaultCommit<Impl>::initStage() } template <class Impl> -void +bool DefaultCommit<Impl>::drain() { drainPending = true; + + // If it's already drained, return true. + if (rob->isEmpty() && !iewStage->hasStoresToWB()) { + cpu->signalDrained(); + return true; + } + + return false; } template <class Impl> @@ -369,6 +377,7 @@ template <class Impl> void DefaultCommit<Impl>::resume() { + drainPending = false; } template <class Impl> diff --git a/src/cpu/o3/cpu.cc b/src/cpu/o3/cpu.cc index b182d5ca7..ceba74ef3 100644 --- a/src/cpu/o3/cpu.cc +++ b/src/cpu/o3/cpu.cc @@ -400,7 +400,8 @@ FullO3CPU<Impl>::tick() } if (!tickEvent.scheduled()) { - if (_status == SwitchedOut) { + if (_status == SwitchedOut || + getState() == SimObject::DrainedTiming) { // increment stat lastRunningCycle = curTick; } else if (!activityRec.active()) { @@ -708,11 +709,51 @@ FullO3CPU<Impl>::haltContext(int tid) } template <class Impl> +void +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) +{ + 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; - drainEvent = drain_event; fetch.drain(); decode.drain(); rename.drain(); @@ -720,28 +761,40 @@ FullO3CPU<Impl>::drain(Event *drain_event) 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; + return false; + } else { + return true; + } } template <class Impl> void FullO3CPU<Impl>::resume() { - if (_status == SwitchedOut) - return; fetch.resume(); decode.resume(); rename.resume(); iew.resume(); commit.resume(); + if (_status == SwitchedOut || _status == Idle) + return; + if (!tickEvent.scheduled()) tickEvent.schedule(curTick); _status = Running; + changeState(SimObject::Timing); } template <class Impl> @@ -751,8 +804,13 @@ FullO3CPU<Impl>::signalDrained() if (++drainCount == NumStages) { if (tickEvent.scheduled()) tickEvent.squash(); - _status = Drained; - drainEvent->process(); + + changeState(SimObject::DrainedTiming); + + if (drainEvent) { + drainEvent->process(); + drainEvent = NULL; + } } assert(drainCount <= 5); } diff --git a/src/cpu/o3/cpu.hh b/src/cpu/o3/cpu.hh index cf3747601..5b881e558 100644 --- a/src/cpu/o3/cpu.hh +++ b/src/cpu/o3/cpu.hh @@ -111,7 +111,6 @@ class FullO3CPU : public BaseO3CPU Idle, Halted, Blocked, - Drained, SwitchedOut }; @@ -266,6 +265,13 @@ class FullO3CPU : public BaseO3CPU /** Update The Order In Which We Process Threads. */ void updateThreadPriority(); + /** Serialize state. */ + virtual void serialize(std::ostream &os); + + /** Unserialize from a checkpoint. */ + virtual void unserialize(Checkpoint *cp, const std::string §ion); + + public: /** Executes a syscall on this cycle. * --------------------------------------- * Note: this is a virtual function. CPU-Specific diff --git a/src/cpu/o3/decode.hh b/src/cpu/o3/decode.hh index 1e96f1884..7f5ecbc26 100644 --- a/src/cpu/o3/decode.hh +++ b/src/cpu/o3/decode.hh @@ -110,7 +110,7 @@ class DefaultDecode void setActiveThreads(std::list<unsigned> *at_ptr); /** Drains the decode stage. */ - void drain(); + bool drain(); /** Resumes execution after a drain. */ void resume() { } diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 71637883b..8b851c032 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -165,11 +165,12 @@ DefaultDecode<Impl>::setActiveThreads(list<unsigned> *at_ptr) } template <class Impl> -void +bool DefaultDecode<Impl>::drain() { // Decode is done draining at any time. cpu->signalDrained(); + return true; } template <class Impl> diff --git a/src/cpu/o3/fetch.hh b/src/cpu/o3/fetch.hh index 9611f0455..a793c7361 100644 --- a/src/cpu/o3/fetch.hh +++ b/src/cpu/o3/fetch.hh @@ -181,7 +181,7 @@ class DefaultFetch void processCacheCompletion(PacketPtr pkt); /** Begins the drain of the fetch stage. */ - void drain(); + bool drain(); /** Resumes execution after a drain. */ void resume(); diff --git a/src/cpu/o3/fetch_impl.hh b/src/cpu/o3/fetch_impl.hh index 500b5304e..c0cc189f2 100644 --- a/src/cpu/o3/fetch_impl.hh +++ b/src/cpu/o3/fetch_impl.hh @@ -385,12 +385,13 @@ DefaultFetch<Impl>::processCacheCompletion(PacketPtr pkt) } template <class Impl> -void +bool DefaultFetch<Impl>::drain() { // Fetch is ready to drain at any time. cpu->signalDrained(); drainPending = true; + return true; } template <class Impl> diff --git a/src/cpu/o3/iew.hh b/src/cpu/o3/iew.hh index 774b6dcbd..4908a6649 100644 --- a/src/cpu/o3/iew.hh +++ b/src/cpu/o3/iew.hh @@ -144,7 +144,7 @@ class DefaultIEW void setScoreboard(Scoreboard *sb_ptr); /** Drains IEW stage. */ - void drain(); + bool drain(); /** Resumes execution after a drain. */ void resume(); diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index c3aa748ae..0d82645e3 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -354,11 +354,12 @@ DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) } template <class Impl> -void +bool DefaultIEW<Impl>::drain() { // IEW is ready to drain at any time. cpu->signalDrained(); + return true; } template <class Impl> diff --git a/src/cpu/o3/lsq_impl.hh b/src/cpu/o3/lsq_impl.hh index 5173f8be1..89fd1a71d 100644 --- a/src/cpu/o3/lsq_impl.hh +++ b/src/cpu/o3/lsq_impl.hh @@ -502,6 +502,9 @@ LSQ<Impl>::hasStoresToWB() { list<unsigned>::iterator active_threads = (*activeThreads).begin(); + if ((*activeThreads).empty()) + return false; + while (active_threads != (*activeThreads).end()) { unsigned tid = *active_threads++; if (!hasStoresToWB(tid)) diff --git a/src/cpu/o3/regfile.hh b/src/cpu/o3/regfile.hh index 6972f055f..b6677b4b1 100644 --- a/src/cpu/o3/regfile.hh +++ b/src/cpu/o3/regfile.hh @@ -86,10 +86,6 @@ class PhysRegFile //The duplication is unfortunate but it's better than having //different ways to access certain registers. - //Add these in later when everything else is in place -// void serialize(std::ostream &os); -// void unserialize(Checkpoint *cp, const std::string §ion); - /** Reads an integer register. */ uint64_t readIntReg(PhysRegIndex reg_idx) { diff --git a/src/cpu/o3/rename.hh b/src/cpu/o3/rename.hh index 538dd9bb4..034087feb 100644 --- a/src/cpu/o3/rename.hh +++ b/src/cpu/o3/rename.hh @@ -158,7 +158,7 @@ class DefaultRename void setScoreboard(Scoreboard *_scoreboard); /** Drains the rename stage. */ - void drain(); + bool drain(); /** Resumes execution after a drain. */ void resume() { } diff --git a/src/cpu/o3/rename_impl.hh b/src/cpu/o3/rename_impl.hh index fddbae3db..805a72808 100644 --- a/src/cpu/o3/rename_impl.hh +++ b/src/cpu/o3/rename_impl.hh @@ -257,11 +257,12 @@ DefaultRename<Impl>::setScoreboard(Scoreboard *_scoreboard) } template <class Impl> -void +bool DefaultRename<Impl>::drain() { // Rename is ready to switch out at any time. cpu->signalDrained(); + return true; } template <class Impl> |