summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Reinhardt <steve.reinhardt@amd.com>2010-08-17 05:17:06 -0700
committerSteve Reinhardt <steve.reinhardt@amd.com>2010-08-17 05:17:06 -0700
commitf064aa306061ecc468efd8cf148ed08398ca824d (patch)
treed78548dc953bb621d9154249d07022dabf2f6e2c
parent2519d116c9171ed4bf220d5049f244b333aa0842 (diff)
downloadgem5-f064aa306061ecc468efd8cf148ed08398ca824d.tar.xz
sim: revamp unserialization procedure
Replace direct call to unserialize() on each SimObject with a pair of calls for better control over initialization in both ckpt and non-ckpt cases. If restoring from a checkpoint, loadState(ckpt) is called on each SimObject. The default implementation simply calls unserialize() if there is a corresponding checkpoint section, so we get backward compatibility for existing objects. However, objects can override loadState() to get other behaviors, e.g., doing other programmed initializations after unserialize(), or complaining if no checkpoint section is found. (Note that the default warning for a missing checkpoint section is now gone.) If not restoring from a checkpoint, we call the new initState() method on each SimObject instead. This provides a hook for state initializations that are only required when *not* restoring from a checkpoint. Given this new framework, do some cleanup of LiveProcess subclasses and X86System, which were (in some cases) emulating initState() behavior in startup via a local flag or (in other cases) erroneously doing initializations in startup() that clobbered state loaded earlier by unserialize().
-rw-r--r--src/arch/alpha/process.cc26
-rw-r--r--src/arch/alpha/process.hh6
-rw-r--r--src/arch/arm/process.cc4
-rw-r--r--src/arch/mips/process.cc5
-rw-r--r--src/arch/mips/process.hh2
-rw-r--r--src/arch/power/linux/process.cc4
-rw-r--r--src/arch/power/linux/process.hh2
-rw-r--r--src/arch/power/process.cc7
-rw-r--r--src/arch/power/process.hh2
-rw-r--r--src/arch/sparc/process.cc18
-rw-r--r--src/arch/sparc/process.hh6
-rw-r--r--src/arch/x86/linux/system.cc4
-rw-r--r--src/arch/x86/linux/system.hh2
-rw-r--r--src/arch/x86/process.cc14
-rw-r--r--src/arch/x86/process.hh4
-rw-r--r--src/arch/x86/system.cc5
-rw-r--r--src/arch/x86/system.hh2
-rw-r--r--src/python/m5/simulate.py6
-rw-r--r--src/python/swig/core.i5
-rw-r--r--src/python/swig/pyobject.hh10
-rw-r--r--src/python/swig/sim_object.i2
-rw-r--r--src/sim/process.cc9
-rw-r--r--src/sim/process.hh5
-rw-r--r--src/sim/serialize.cc15
-rw-r--r--src/sim/serialize.hh1
-rw-r--r--src/sim/sim_object.cc12
-rw-r--r--src/sim/sim_object.hh39
27 files changed, 131 insertions, 86 deletions
diff --git a/src/arch/alpha/process.cc b/src/arch/alpha/process.cc
index 1c83f64b2..431ef86c0 100644
--- a/src/arch/alpha/process.cc
+++ b/src/arch/alpha/process.cc
@@ -173,19 +173,35 @@ AlphaLiveProcess::argsInit(int intSize, int pageSize)
}
void
-AlphaLiveProcess::startup()
+AlphaLiveProcess::setupASNReg()
{
ThreadContext *tc = system->getThreadContext(contextIds[0]);
tc->setMiscRegNoEffect(IPR_DTB_ASN, M5_pid << 57);
+}
- if (checkpointRestored) {
- return;
- }
- Process::startup();
+void
+AlphaLiveProcess::loadState(Checkpoint *cp)
+{
+ LiveProcess::loadState(cp);
+ // need to set up ASN after unserialization since M5_pid value may
+ // come from checkpoint
+ setupASNReg();
+}
+
+
+void
+AlphaLiveProcess::initState()
+{
+ // need to set up ASN before further initialization since init
+ // will involve writing to virtual memory addresses
+ setupASNReg();
+
+ LiveProcess::initState();
argsInit(MachineBytes, VMPageSize);
+ ThreadContext *tc = system->getThreadContext(contextIds[0]);
tc->setIntReg(GlobalPointerReg, objFile->globalPointer());
//Operate in user mode
tc->setMiscRegNoEffect(IPR_ICM, 0x18);
diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh
index 36b25a48e..40d6bf48a 100644
--- a/src/arch/alpha/process.hh
+++ b/src/arch/alpha/process.hh
@@ -36,10 +36,14 @@
class AlphaLiveProcess : public LiveProcess
{
+ private:
+ void setupASNReg();
+
protected:
AlphaLiveProcess(LiveProcessParams *params, ObjectFile *objFile);
- void startup();
+ void loadState(Checkpoint *cp);
+ void initState();
void argsInit(int intSize, int pageSize);
diff --git a/src/arch/arm/process.cc b/src/arch/arm/process.cc
index 555fdf56e..e7748ad50 100644
--- a/src/arch/arm/process.cc
+++ b/src/arch/arm/process.cc
@@ -76,6 +76,7 @@ ArmLiveProcess::ArmLiveProcess(LiveProcessParams *params, ObjectFile *objFile,
void
ArmLiveProcess::startup()
{
+ LiveProcess::startup();
argsInit(MachineBytes, VMPageSize);
}
@@ -114,9 +115,6 @@ ArmLiveProcess::argsInit(int intSize, int pageSize)
//We want 16 byte alignment
uint64_t align = 16;
- // Overloaded argsInit so that we can fine-tune for ARM architecture
- Process::startup();
-
// load object file into target memory
objFile->loadSections(initVirtMem);
diff --git a/src/arch/mips/process.cc b/src/arch/mips/process.cc
index 2fd9114e9..7f1e94709 100644
--- a/src/arch/mips/process.cc
+++ b/src/arch/mips/process.cc
@@ -67,9 +67,9 @@ MipsLiveProcess::MipsLiveProcess(LiveProcessParams * params,
}
void
-MipsLiveProcess::startup()
+MipsLiveProcess::initState()
{
- Process::startup();
+ LiveProcess::initState();
argsInit<uint32_t>(VMPageSize);
}
@@ -79,7 +79,6 @@ void
MipsLiveProcess::argsInit(int pageSize)
{
int intSize = sizeof(IntType);
- Process::startup();
// load object file into target memory
objFile->loadSections(initVirtMem);
diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh
index f1238b41f..a065feb8f 100644
--- a/src/arch/mips/process.hh
+++ b/src/arch/mips/process.hh
@@ -45,7 +45,7 @@ class MipsLiveProcess : public LiveProcess
protected:
MipsLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
- void startup();
+ void initState();
template<class IntType>
void argsInit(int pageSize);
diff --git a/src/arch/power/linux/process.cc b/src/arch/power/linux/process.cc
index 504d0e334..c2587d5e7 100644
--- a/src/arch/power/linux/process.cc
+++ b/src/arch/power/linux/process.cc
@@ -432,9 +432,9 @@ PowerLinuxProcess::getDesc(int callnum)
}
void
-PowerLinuxProcess::startup()
+PowerLinuxProcess::initState()
{
- PowerLiveProcess::startup();
+ PowerLiveProcess::initState();
}
PowerISA::IntReg
diff --git a/src/arch/power/linux/process.hh b/src/arch/power/linux/process.hh
index db6759a77..bef7e8dae 100644
--- a/src/arch/power/linux/process.hh
+++ b/src/arch/power/linux/process.hh
@@ -44,7 +44,7 @@ class PowerLinuxProcess : public PowerLiveProcess
virtual SyscallDesc* getDesc(int callnum);
- void startup();
+ void initState();
PowerISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
void setSyscallArg(ThreadContext *tc, int i, PowerISA::IntReg val);
diff --git a/src/arch/power/process.cc b/src/arch/power/process.cc
index 12b216e50..9fb69b9f8 100644
--- a/src/arch/power/process.cc
+++ b/src/arch/power/process.cc
@@ -63,8 +63,10 @@ PowerLiveProcess::PowerLiveProcess(LiveProcessParams *params,
}
void
-PowerLiveProcess::startup()
+PowerLiveProcess::initState()
{
+ Process::initState();
+
argsInit(MachineBytes, VMPageSize);
}
@@ -83,9 +85,6 @@ PowerLiveProcess::argsInit(int intSize, int pageSize)
//We want 16 byte alignment
uint64_t align = 16;
- // Overloaded argsInit so that we can fine-tune for POWER architecture
- Process::startup();
-
// load object file into target memory
objFile->loadSections(initVirtMem);
diff --git a/src/arch/power/process.hh b/src/arch/power/process.hh
index ede75f05f..473b7e028 100644
--- a/src/arch/power/process.hh
+++ b/src/arch/power/process.hh
@@ -46,7 +46,7 @@ class PowerLiveProcess : public LiveProcess
protected:
PowerLiveProcess(LiveProcessParams * params, ObjectFile *objFile);
- void startup();
+ void initState();
public:
void argsInit(int intSize, int pageSize);
diff --git a/src/arch/sparc/process.cc b/src/arch/sparc/process.cc
index 7e01f6b07..0cd8889a9 100644
--- a/src/arch/sparc/process.cc
+++ b/src/arch/sparc/process.cc
@@ -111,9 +111,9 @@ void SparcLiveProcess::handleTrap(int trapNum, ThreadContext *tc)
}
void
-SparcLiveProcess::startup()
+SparcLiveProcess::initState()
{
- Process::startup();
+ LiveProcess::initState();
ThreadContext *tc = system->getThreadContext(contextIds[0]);
//From the SPARC ABI
@@ -157,12 +157,9 @@ SparcLiveProcess::startup()
}
void
-Sparc32LiveProcess::startup()
+Sparc32LiveProcess::initState()
{
- if (checkpointRestored)
- return;
-
- SparcLiveProcess::startup();
+ SparcLiveProcess::initState();
ThreadContext *tc = system->getThreadContext(contextIds[0]);
//The process runs in user mode with 32 bit addresses
@@ -172,12 +169,9 @@ Sparc32LiveProcess::startup()
}
void
-Sparc64LiveProcess::startup()
+Sparc64LiveProcess::initState()
{
- if (checkpointRestored)
- return;
-
- SparcLiveProcess::startup();
+ SparcLiveProcess::initState();
ThreadContext *tc = system->getThreadContext(contextIds[0]);
//The process runs in user mode
diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh
index cca312e0a..2d68fb3fc 100644
--- a/src/arch/sparc/process.hh
+++ b/src/arch/sparc/process.hh
@@ -52,7 +52,7 @@ class SparcLiveProcess : public LiveProcess
SparcLiveProcess(LiveProcessParams * params,
ObjectFile *objFile, Addr _StackBias);
- void startup();
+ void initState();
template<class IntType>
void argsInit(int pageSize);
@@ -87,7 +87,7 @@ class Sparc32LiveProcess : public SparcLiveProcess
mmap_start = mmap_end = 0x70000000;
}
- void startup();
+ void initState();
public:
@@ -115,7 +115,7 @@ class Sparc64LiveProcess : public SparcLiveProcess
mmap_start = mmap_end = 0xfffff80000000000ULL;
}
- void startup();
+ void initState();
public:
diff --git a/src/arch/x86/linux/system.cc b/src/arch/x86/linux/system.cc
index 4ae6d0ca4..1a113d365 100644
--- a/src/arch/x86/linux/system.cc
+++ b/src/arch/x86/linux/system.cc
@@ -59,9 +59,9 @@ LinuxX86System::~LinuxX86System()
}
void
-LinuxX86System::startup()
+LinuxX86System::initState()
{
- X86System::startup();
+ X86System::initState();
// The location of the real mode data structure.
const Addr realModeData = 0x90200;
diff --git a/src/arch/x86/linux/system.hh b/src/arch/x86/linux/system.hh
index e3c52ae50..ae7e93f3d 100644
--- a/src/arch/x86/linux/system.hh
+++ b/src/arch/x86/linux/system.hh
@@ -58,7 +58,7 @@ class LinuxX86System : public X86System
LinuxX86System(Params *p);
~LinuxX86System();
- void startup();
+ void initState();
};
#endif
diff --git a/src/arch/x86/process.cc b/src/arch/x86/process.cc
index 2a2d43d3b..02cd45478 100644
--- a/src/arch/x86/process.cc
+++ b/src/arch/x86/process.cc
@@ -157,12 +157,9 @@ X86LiveProcess::getDesc(int callnum)
}
void
-X86_64LiveProcess::startup()
+X86_64LiveProcess::initState()
{
- LiveProcess::startup();
-
- if (checkpointRestored)
- return;
+ X86LiveProcess::initState();
argsInit(sizeof(uint64_t), VMPageSize);
@@ -255,12 +252,9 @@ X86_64LiveProcess::startup()
}
void
-I386LiveProcess::startup()
+I386LiveProcess::initState()
{
- LiveProcess::startup();
-
- if (checkpointRestored)
- return;
+ X86LiveProcess::initState();
argsInit(sizeof(uint32_t), VMPageSize);
diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh
index 8063898d7..34275b2d3 100644
--- a/src/arch/x86/process.hh
+++ b/src/arch/x86/process.hh
@@ -99,7 +99,7 @@ namespace X86ISA
public:
void argsInit(int intSize, int pageSize);
- void startup();
+ void initState();
X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val);
@@ -123,7 +123,7 @@ namespace X86ISA
public:
void argsInit(int intSize, int pageSize);
- void startup();
+ void initState();
void syscall(int64_t callnum, ThreadContext *tc);
X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i);
diff --git a/src/arch/x86/system.cc b/src/arch/x86/system.cc
index 01416e544..46d17cdb3 100644
--- a/src/arch/x86/system.cc
+++ b/src/arch/x86/system.cc
@@ -109,9 +109,10 @@ installSegDesc(ThreadContext *tc, SegmentRegIndex seg,
}
void
-X86System::startup()
+X86System::initState()
{
- System::startup();
+ System::initState();
+
ThreadContext *tc = threadContexts[0];
// This is the boot strap processor (BSP). Initialize it to look like
// the boot loader has just turned control over to the 64 bit OS. We
diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh
index 4a61193e6..0b5da3145 100644
--- a/src/arch/x86/system.hh
+++ b/src/arch/x86/system.hh
@@ -77,7 +77,7 @@ class X86System : public System
void serialize(std::ostream &os);
void unserialize(Checkpoint *cp, const std::string &section);
- void startup();
+ void initState();
protected:
diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py
index 0cf0a254e..cd2f8bb64 100644
--- a/src/python/m5/simulate.py
+++ b/src/python/m5/simulate.py
@@ -88,8 +88,12 @@ def instantiate(ckpt_dir=None):
# Restore checkpoint (if any)
if ckpt_dir:
- internal.core.unserializeAll(ckpt_dir)
+ ckpt = internal.core.getCheckpoint(ckpt_dir)
+ internal.core.unserializeGlobals(ckpt);
+ for obj in root.descendants(): obj.loadState(ckpt)
need_resume.append(root)
+ else:
+ for obj in root.descendants(): obj.initState()
# Reset to put the stats in a consistent state.
stats.reset()
diff --git a/src/python/swig/core.i b/src/python/swig/core.i
index 81085dd06..f48fe9590 100644
--- a/src/python/swig/core.i
+++ b/src/python/swig/core.i
@@ -75,8 +75,11 @@ void setClockFrequency(Tick ticksPerSecond);
%immutable curTick;
Tick curTick;
+class Checkpoint;
+
void serializeAll(const std::string &cpt_dir);
-void unserializeAll(const std::string &cpt_dir);
+Checkpoint *getCheckpoint(const std::string &cpt_dir);
+void unserializeGlobals(Checkpoint *cp);
bool want_warn, warn_verbose;
bool want_info, info_verbose;
diff --git a/src/python/swig/pyobject.hh b/src/python/swig/pyobject.hh
index a27080d08..b18a2a76c 100644
--- a/src/python/swig/pyobject.hh
+++ b/src/python/swig/pyobject.hh
@@ -52,8 +52,14 @@ serializeAll(const std::string &cpt_dir)
Serializable::serializeAll(cpt_dir);
}
+inline Checkpoint *
+getCheckpoint(const std::string &cpt_dir)
+{
+ return new Checkpoint(cpt_dir);
+}
+
inline void
-unserializeAll(const std::string &cpt_dir)
+unserializeGlobals(Checkpoint *cp)
{
- Serializable::unserializeAll(cpt_dir);
+ Serializable::unserializeGlobals(cp);
}
diff --git a/src/python/swig/sim_object.i b/src/python/swig/sim_object.i
index 8cd8e8beb..af9afd057 100644
--- a/src/python/swig/sim_object.i
+++ b/src/python/swig/sim_object.i
@@ -51,6 +51,8 @@ class SimObject {
};
void init();
+ void loadState(Checkpoint *cp);
+ void initState();
void regStats();
void regFormulas();
void resetStats();
diff --git a/src/sim/process.cc b/src/sim/process.cc
index f11fdcac8..d4b1fba90 100644
--- a/src/sim/process.cc
+++ b/src/sim/process.cc
@@ -100,8 +100,8 @@ template class AuxVector<uint32_t>;
template class AuxVector<uint64_t>;
Process::Process(ProcessParams * params)
- : SimObject(params), system(params->system), checkpointRestored(false),
- max_stack_size(params->max_stack_size)
+ : SimObject(params), system(params->system),
+ max_stack_size(params->max_stack_size)
{
string in = params->input;
string out = params->output;
@@ -233,7 +233,7 @@ Process::findFreeContext()
}
void
-Process::startup()
+Process::initState()
{
if (contextIds.empty())
fatal("Process %s is not associated with any HW contexts!\n", name());
@@ -537,9 +537,6 @@ Process::unserialize(Checkpoint *cp, const std::string &section)
// find the param in the checkpoint if you wanted to, like set a default
// but in this case we'll just stick with the instantianted value if not
// found.
-
- checkpointRestored = true;
-
}
diff --git a/src/sim/process.hh b/src/sim/process.hh
index e73f93fa5..3b78cb001 100644
--- a/src/sim/process.hh
+++ b/src/sim/process.hh
@@ -79,8 +79,6 @@ class Process : public SimObject
/// running on.
System *system;
- bool checkpointRestored;
-
// thread contexts associated with this process
std::vector<int> contextIds;
@@ -130,8 +128,7 @@ class Process : public SimObject
// constructor
Process(ProcessParams * params);
- // post initialization startup
- virtual void startup();
+ virtual void initState();
protected:
/// Memory object for initialization (image loading)
diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc
index d95092629..d6d5ac094 100644
--- a/src/sim/serialize.cc
+++ b/src/sim/serialize.cc
@@ -452,17 +452,6 @@ Serializable::serializeAll(const string &cpt_dir)
}
void
-Serializable::unserializeAll(const string &cpt_dir)
-{
- string dir = Checkpoint::setDir(cpt_dir);
-
- DPRINTFR(Config, "Loading checkpoint dir '%s'\n", dir);
- Checkpoint *cp = new Checkpoint(dir);
- unserializeGlobals(cp);
- SimObject::unserializeAll(cp);
-}
-
-void
Serializable::unserializeGlobals(Checkpoint *cp)
{
globals.unserialize(cp);
@@ -561,9 +550,9 @@ Checkpoint::dir()
Checkpoint::Checkpoint(const string &cpt_dir)
- : db(new IniFile), cptDir(cpt_dir)
+ : db(new IniFile), cptDir(setDir(cpt_dir))
{
- string filename = cpt_dir + "/" + Checkpoint::baseFilename;
+ string filename = cptDir + "/" + Checkpoint::baseFilename;
if (!db->load(filename)) {
fatal("Can't load checkpoint file '%s'\n", filename);
}
diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh
index 677a3fd92..d785605f3 100644
--- a/src/sim/serialize.hh
+++ b/src/sim/serialize.hh
@@ -141,7 +141,6 @@ class Serializable
static int ckptMaxCount;
static int ckptPrevCount;
static void serializeAll(const std::string &cpt_dir);
- static void unserializeAll(const std::string &cpt_dir);
static void unserializeGlobals(Checkpoint *cp);
};
diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc
index 157bf1395..503ac5650 100644
--- a/src/sim/sim_object.cc
+++ b/src/sim/sim_object.cc
@@ -74,6 +74,18 @@ SimObject::init()
}
void
+SimObject::loadState(Checkpoint *cp)
+{
+ if (cp->sectionExists(name()))
+ unserialize(cp, name());
+}
+
+void
+SimObject::initState()
+{
+}
+
+void
SimObject::startup()
{
}
diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh
index 1b22c5825..876501be2 100644
--- a/src/sim/sim_object.hh
+++ b/src/sim/sim_object.hh
@@ -91,17 +91,48 @@ class SimObject : public EventManager, public Serializable
virtual const std::string name() const { return params()->name; }
- // initialization pass of all objects.
- // Gets invoked after construction, before unserialize.
+ // The following SimObject initialization methods are called from
+ // the instantiate() method in src/python/m5/simulate.py. See
+ // that function for details on how/when these methods are
+ // invoked.
+
+ /**
+ * init() is called after all C++ SimObjects have been created and
+ * all ports are connected. Initializations that are independent
+ * of unserialization but rely on a fully instantiated and
+ * connected SimObject graph should be done here.
+ */
virtual void init();
+ /**
+ * loadState() is called on each SimObject when restoring from a
+ * checkpoint. The default implementation simply calls
+ * unserialize() if there is a corresponding section in the
+ * checkpoint. However, objects can override loadState() to get
+ * other behaviors, e.g., doing other programmed initializations
+ * after unserialize(), or complaining if no checkpoint section is
+ * found.
+ */
+ virtual void loadState(Checkpoint *cp);
+
+ /**
+ * initState() is called on each SimObject when *not* restoring
+ * from a checkpoint. This provides a hook for state
+ * initializations that are only required for a "cold start".
+ */
+ virtual void initState();
+
// register statistics for this object
virtual void regStats();
virtual void regFormulas();
virtual void resetStats();
- // final initialization before simulation
- // all state is unserialized so
+ /**
+ * startup() is the final initialization call before simulation.
+ * All state is initialized (including unserialized state, if any,
+ * such as the curTick value), so this is the appropriate place to
+ * schedule initial event(s) for objects that need them.
+ */
virtual void startup();
// static: call nameOut() & serialize() on all SimObjects