summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/alpha/regfile.hh4
-rw-r--r--src/cpu/o3/commit.hh2
-rw-r--r--src/cpu/o3/commit_impl.hh11
-rw-r--r--src/cpu/o3/cpu.cc78
-rw-r--r--src/cpu/o3/cpu.hh8
-rw-r--r--src/cpu/o3/decode.hh2
-rw-r--r--src/cpu/o3/decode_impl.hh3
-rw-r--r--src/cpu/o3/fetch.hh2
-rw-r--r--src/cpu/o3/fetch_impl.hh3
-rw-r--r--src/cpu/o3/iew.hh2
-rw-r--r--src/cpu/o3/iew_impl.hh3
-rw-r--r--src/cpu/o3/lsq_impl.hh3
-rw-r--r--src/cpu/o3/regfile.hh4
-rw-r--r--src/cpu/o3/rename.hh2
-rw-r--r--src/cpu/o3/rename_impl.hh3
-rw-r--r--src/cpu/simple/timing.cc28
-rw-r--r--src/cpu/simple/timing.hh2
-rw-r--r--src/cpu/simple_thread.cc78
-rw-r--r--src/cpu/simple_thread.hh10
-rw-r--r--src/cpu/thread_state.cc43
-rw-r--r--src/cpu/thread_state.hh6
-rw-r--r--src/dev/tsunami_pchip.hh2
-rw-r--r--src/python/m5/__init__.py25
-rw-r--r--src/sim/main.cc8
-rw-r--r--src/sim/pseudo_inst.cc1
-rw-r--r--src/sim/serialize.cc10
-rw-r--r--src/sim/serialize.hh6
27 files changed, 259 insertions, 90 deletions
diff --git a/src/arch/alpha/regfile.hh b/src/arch/alpha/regfile.hh
index 1025412cd..9ecad6f42 100644
--- a/src/arch/alpha/regfile.hh
+++ b/src/arch/alpha/regfile.hh
@@ -112,6 +112,10 @@ namespace AlphaISA
lock_flag = 0;
lock_addr = 0;
}
+
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
#if FULL_SYSTEM
protected:
typedef uint64_t InternalProcReg;
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 &section)
+{
+ 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 &section);
+
+ 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 &section);
-
/** 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>
diff --git a/src/cpu/simple/timing.cc b/src/cpu/simple/timing.cc
index 12a47fb3e..e55301c6b 100644
--- a/src/cpu/simple/timing.cc
+++ b/src/cpu/simple/timing.cc
@@ -90,6 +90,7 @@ TimingSimpleCPU::TimingSimpleCPU(Params *p)
_status = Idle;
ifetch_pkt = dcache_pkt = NULL;
drainEvent = NULL;
+ fetchEvent = NULL;
state = SimObject::Timing;
}
@@ -119,11 +120,11 @@ TimingSimpleCPU::drain(Event *drain_event)
// an access to complete.
if (status() == Idle || status() == Running || status() == SwitchedOut) {
changeState(SimObject::DrainedTiming);
- return false;
+ return true;
} else {
changeState(SimObject::Draining);
drainEvent = drain_event;
- return true;
+ return false;
}
}
@@ -131,9 +132,15 @@ void
TimingSimpleCPU::resume()
{
if (_status != SwitchedOut && _status != Idle) {
- Event *e =
- new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true);
- e->schedule(curTick);
+ // Delete the old event if it existed.
+ if (fetchEvent) {
+ assert(!fetchEvent->scheduled());
+ delete fetchEvent;
+ }
+
+ fetchEvent =
+ new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
+ fetchEvent->schedule(curTick);
}
}
@@ -148,6 +155,11 @@ TimingSimpleCPU::switchOut()
{
assert(status() == Running || status() == Idle);
_status = SwitchedOut;
+
+ // If we've been scheduled to resume but are then told to switch out,
+ // we'll need to cancel it.
+ if (fetchEvent && fetchEvent->scheduled())
+ fetchEvent->deschedule();
}
@@ -179,9 +191,9 @@ TimingSimpleCPU::activateContext(int thread_num, int delay)
notIdleFraction++;
_status = Running;
// kick things off by initiating the fetch of the next instruction
- Event *e =
- new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, true);
- e->schedule(curTick + cycles(delay));
+ fetchEvent =
+ new EventWrapper<TimingSimpleCPU, &TimingSimpleCPU::fetch>(this, false);
+ fetchEvent->schedule(curTick + cycles(delay));
}
diff --git a/src/cpu/simple/timing.hh b/src/cpu/simple/timing.hh
index d5b5d6648..0a3f91e6c 100644
--- a/src/cpu/simple/timing.hh
+++ b/src/cpu/simple/timing.hh
@@ -66,6 +66,8 @@ class TimingSimpleCPU : public BaseSimpleCPU
Event *drainEvent;
+ Event *fetchEvent;
+
private:
class CpuPort : public Port
diff --git a/src/cpu/simple_thread.cc b/src/cpu/simple_thread.cc
index db28b23e8..af1db2ff2 100644
--- a/src/cpu/simple_thread.cc
+++ b/src/cpu/simple_thread.cc
@@ -123,15 +123,19 @@ SimpleThread::SimpleThread(BaseCPU *_cpu, int _thread_num,
tc = new ProxyThreadContext<SimpleThread>(this);
}
-SimpleThread::SimpleThread(RegFile *regFile)
- : ThreadState(-1, -1, NULL, -1, NULL), cpu(NULL)
+#endif
+
+SimpleThread::SimpleThread()
+#if FULL_SYSTEM
+ : ThreadState(-1, -1)
+#else
+ : ThreadState(-1, -1, NULL, -1, NULL)
+#endif
{
- regs = *regFile;
tc = new ProxyThreadContext<SimpleThread>(this);
+ regs.clear();
}
-#endif
-
SimpleThread::~SimpleThread()
{
delete tc;
@@ -147,13 +151,8 @@ SimpleThread::takeOverFrom(ThreadContext *oldContext)
assert(process == oldContext->getProcessPtr());
#endif
- // copy over functional state
- _status = oldContext->status();
- copyArchRegs(oldContext);
- cpuId = oldContext->readCpuId();
-#if !FULL_SYSTEM
- funcExeInst = oldContext->readFuncExeInst();
-#else
+ copyState(oldContext);
+#if FULL_SYSTEM
EndQuiesceEvent *quiesce = oldContext->getQuiesceEvent();
if (quiesce) {
// Point the quiesce event's TC at this TC so that it wakes up
@@ -171,42 +170,49 @@ SimpleThread::takeOverFrom(ThreadContext *oldContext)
}
void
-SimpleThread::serialize(ostream &os)
+SimpleThread::copyTC(ThreadContext *context)
{
- SERIALIZE_ENUM(_status);
- regs.serialize(os);
- // thread_num and cpu_id are deterministic from the config
- SERIALIZE_SCALAR(funcExeInst);
- SERIALIZE_SCALAR(inst);
+ copyState(context);
#if FULL_SYSTEM
- Tick quiesceEndTick = 0;
- if (quiesceEvent->scheduled())
- quiesceEndTick = quiesceEvent->when();
- SERIALIZE_SCALAR(quiesceEndTick);
- if (kernelStats)
- kernelStats->serialize(os);
+ EndQuiesceEvent *quiesce = context->getQuiesceEvent();
+ if (quiesce) {
+ quiesceEvent = quiesce;
+ }
+ Kernel::Statistics *stats = context->getKernelStats();
+ if (stats) {
+ kernelStats = stats;
+ }
#endif
}
+void
+SimpleThread::copyState(ThreadContext *oldContext)
+{
+ // copy over functional state
+ _status = oldContext->status();
+ copyArchRegs(oldContext);
+ cpuId = oldContext->readCpuId();
+#if !FULL_SYSTEM
+ funcExeInst = oldContext->readFuncExeInst();
+#endif
+}
+
+void
+SimpleThread::serialize(ostream &os)
+{
+ ThreadState::serialize(os);
+ regs.serialize(os);
+ // thread_num and cpu_id are deterministic from the config
+}
+
void
SimpleThread::unserialize(Checkpoint *cp, const std::string &section)
{
- UNSERIALIZE_ENUM(_status);
+ ThreadState::unserialize(cp, section);
regs.unserialize(cp, section);
// thread_num and cpu_id are deterministic from the config
- UNSERIALIZE_SCALAR(funcExeInst);
- UNSERIALIZE_SCALAR(inst);
-
-#if FULL_SYSTEM
- Tick quiesceEndTick;
- UNSERIALIZE_SCALAR(quiesceEndTick);
- if (quiesceEndTick)
- quiesceEvent->schedule(quiesceEndTick);
- if (kernelStats)
- kernelStats->unserialize(cp, section);
-#endif
}
#if FULL_SYSTEM
diff --git a/src/cpu/simple_thread.hh b/src/cpu/simple_thread.hh
index de65e9891..d36853db4 100644
--- a/src/cpu/simple_thread.hh
+++ b/src/cpu/simple_thread.hh
@@ -119,16 +119,20 @@ class SimpleThread : public ThreadState
#else
SimpleThread(BaseCPU *_cpu, int _thread_num, Process *_process, int _asid,
MemObject *memobj);
- // Constructor to use SimpleThread to pass reg file around. Not
- // used for anything else.
- SimpleThread(RegFile *regFile);
#endif
+
+ SimpleThread();
+
virtual ~SimpleThread();
virtual void takeOverFrom(ThreadContext *oldContext);
void regStats(const std::string &name);
+ void copyTC(ThreadContext *context);
+
+ void copyState(ThreadContext *oldContext);
+
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
diff --git a/src/cpu/thread_state.cc b/src/cpu/thread_state.cc
index 872678a41..6a96560f1 100644
--- a/src/cpu/thread_state.cc
+++ b/src/cpu/thread_state.cc
@@ -31,6 +31,12 @@
#include "base/output.hh"
#include "cpu/profile.hh"
#include "cpu/thread_state.hh"
+#include "sim/serialize.hh"
+
+#if FULL_SYSTEM
+#include "cpu/quiesce_event.hh"
+#include "kern/kernel_stats.hh"
+#endif
#if FULL_SYSTEM
ThreadState::ThreadState(int _cpuId, int _tid)
@@ -49,6 +55,43 @@ ThreadState::ThreadState(int _cpuId, int _tid, Process *_process,
numLoad = 0;
}
+void
+ThreadState::serialize(std::ostream &os)
+{
+ SERIALIZE_ENUM(_status);
+ // thread_num and cpu_id are deterministic from the config
+ SERIALIZE_SCALAR(funcExeInst);
+ SERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+ Tick quiesceEndTick = 0;
+ if (quiesceEvent->scheduled())
+ quiesceEndTick = quiesceEvent->when();
+ SERIALIZE_SCALAR(quiesceEndTick);
+ if (kernelStats)
+ kernelStats->serialize(os);
+#endif
+}
+
+void
+ThreadState::unserialize(Checkpoint *cp, const std::string &section)
+{
+
+ UNSERIALIZE_ENUM(_status);
+ // thread_num and cpu_id are deterministic from the config
+ UNSERIALIZE_SCALAR(funcExeInst);
+ UNSERIALIZE_SCALAR(inst);
+
+#if FULL_SYSTEM
+ Tick quiesceEndTick;
+ UNSERIALIZE_SCALAR(quiesceEndTick);
+ if (quiesceEndTick)
+ quiesceEvent->schedule(quiesceEndTick);
+ if (kernelStats)
+ kernelStats->unserialize(cp, section);
+#endif
+}
+
#if FULL_SYSTEM
void
diff --git a/src/cpu/thread_state.hh b/src/cpu/thread_state.hh
index cb1449ac5..b03a2e2bb 100644
--- a/src/cpu/thread_state.hh
+++ b/src/cpu/thread_state.hh
@@ -49,6 +49,8 @@ namespace Kernel {
};
#endif
+class Checkpoint;
+
/**
* Struct for holding general thread state that is needed across CPU
* models. This includes things such as pointers to the process,
@@ -65,6 +67,10 @@ struct ThreadState {
short _asid, MemObject *mem);
#endif
+ void serialize(std::ostream &os);
+
+ void unserialize(Checkpoint *cp, const std::string &section);
+
void setCpuId(int id) { cpuId = id; }
int readCpuId() { return cpuId; }
diff --git a/src/dev/tsunami_pchip.hh b/src/dev/tsunami_pchip.hh
index b9e900526..2c97a1fea 100644
--- a/src/dev/tsunami_pchip.hh
+++ b/src/dev/tsunami_pchip.hh
@@ -46,7 +46,7 @@ class TsunamiPChip : public BasicPioDevice
{
protected:
- static const Addr TsunamiPciBus0Config = 0x801fe000000;
+ static const Addr TsunamiPciBus0Config = ULL(0x801fe000000);
/** Pchip control register */
uint64_t pctl;
diff --git a/src/python/m5/__init__.py b/src/python/m5/__init__.py
index 579785a46..f4f5be2d1 100644
--- a/src/python/m5/__init__.py
+++ b/src/python/m5/__init__.py
@@ -34,7 +34,7 @@ import cc_main
# import a few SWIG-wrapped items (those that are likely to be used
# directly by user scripts) completely into this module for
# convenience
-from cc_main import simulate, SimLoopExitEvent, setCheckpointDir
+from cc_main import simulate, SimLoopExitEvent
# import the m5 compile options
import defines
@@ -213,29 +213,44 @@ atexit.register(cc_main.doExitCleanup)
# matter since most scripts will probably 'from m5.objects import *'.
import objects
+# This loops until all objects have been fully drained.
def doDrain(root):
+ all_drained = drain(root)
+ while (not all_drained):
+ all_drained = drain(root)
+
+# Tries to drain all objects. Draining might not be completed unless
+# all objects return that they are drained on the first call. This is
+# because as objects drain they may cause other objects to no longer
+# be drained.
+def drain(root):
+ all_drained = False
drain_event = cc_main.createCountedDrain()
unready_objects = root.startDrain(drain_event, True)
# If we've got some objects that can't drain immediately, then simulate
if unready_objects > 0:
drain_event.setCount(unready_objects)
simulate()
+ else:
+ all_drained = True
cc_main.cleanupCountedDrain(drain_event)
+ return all_drained
def resume(root):
root.resume()
-def checkpoint(root):
+def checkpoint(root, dir):
if not isinstance(root, objects.Root):
raise TypeError, "Object is not a root object. Checkpoint must be called on a root object."
doDrain(root)
print "Writing checkpoint"
- cc_main.serializeAll()
+ cc_main.serializeAll(dir)
resume(root)
-def restoreCheckpoint(root):
+def restoreCheckpoint(root, dir):
print "Restoring from checkpoint"
- cc_main.unserializeAll()
+ cc_main.unserializeAll(dir)
+ resume(root)
def changeToAtomic(system):
if not isinstance(system, objects.Root) and not isinstance(system, System):
diff --git a/src/sim/main.cc b/src/sim/main.cc
index e96a44930..5f34f6520 100644
--- a/src/sim/main.cc
+++ b/src/sim/main.cc
@@ -542,15 +542,15 @@ cleanupCountedDrain(Event *counted_drain)
}
void
-serializeAll()
+serializeAll(const std::string &cpt_dir)
{
- Serializable::serializeAll();
+ Serializable::serializeAll(cpt_dir);
}
void
-unserializeAll()
+unserializeAll(const std::string &cpt_dir)
{
- Serializable::unserializeAll();
+ Serializable::unserializeAll(cpt_dir);
}
/**
diff --git a/src/sim/pseudo_inst.cc b/src/sim/pseudo_inst.cc
index 869805f5c..fcf0b957a 100644
--- a/src/sim/pseudo_inst.cc
+++ b/src/sim/pseudo_inst.cc
@@ -37,7 +37,6 @@
#include "sim/pseudo_inst.hh"
#include "arch/vtophys.hh"
#include "cpu/base.hh"
-#include "cpu/sampler/sampler.hh"
#include "cpu/thread_context.hh"
#include "cpu/quiesce_event.hh"
#include "kern/kernel_stats.hh"
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index 7450d7b7e..6a1d084b7 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -231,8 +231,9 @@ Globals::unserialize(Checkpoint *cp)
}
void
-Serializable::serializeAll()
+Serializable::serializeAll(const std::string &cpt_dir)
{
+ setCheckpointDir(cpt_dir);
string dir = Checkpoint::dir();
if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
fatal("couldn't mkdir %s\n", dir);
@@ -247,8 +248,9 @@ Serializable::serializeAll()
}
void
-Serializable::unserializeAll()
+Serializable::unserializeAll(const std::string &cpt_dir)
{
+ setCheckpointDir(cpt_dir);
string dir = Checkpoint::dir();
string cpt_file = dir + Checkpoint::baseFilename;
string section = "";
@@ -289,9 +291,9 @@ Checkpoint::dir()
}
void
-debug_serialize()
+debug_serialize(const std::string &cpt_dir)
{
- Serializable::serializeAll();
+ Serializable::serializeAll(cpt_dir);
}
diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh
index a80dc99e4..880fb0785 100644
--- a/src/sim/serialize.hh
+++ b/src/sim/serialize.hh
@@ -126,8 +126,8 @@ class Serializable
static int ckptCount;
static int ckptMaxCount;
static int ckptPrevCount;
- static void serializeAll();
- static void unserializeAll();
+ static void serializeAll(const std::string &cpt_dir);
+ static void unserializeAll(const std::string &cpt_dir);
static void unserializeGlobals(Checkpoint *cp);
};
@@ -206,7 +206,7 @@ SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
OBJ_CLASS::createForUnserialize);
void
-setCheckpointName(const std::string &name);
+setCheckpointDir(const std::string &name);
class Checkpoint
{