#define __SERIALIZE_HH__
-#include <list>
#include <iostream>
+#include <list>
#include <map>
+#include <vector>
-#include "sim/host.hh"
+#include "base/bitunion.hh"
+#include "base/types.hh"
class IniFile;
class Serializable;
class Checkpoint;
+class SimObject;
+class EventQueue;
+
+/** The current version of the checkpoint format.
+ * This should be incremented by 1 and only 1 for every new version, where a new
+ * version is defined as a checkpoint created before this version won't work on
+ * the current version until the checkpoint format is updated. Adding a new
+ * SimObject shouldn't cause the version number to increase, only changes to
+ * existing objects such as serializing/unserializing more state, changing sizes
+ * of serialized arrays, etc. */
+static const uint64_t gem5CheckpointVersion = 0x000000000000000d;
template <class T>
void paramOut(std::ostream &os, const std::string &name, const T ¶m);
+template <typename DataType, typename BitUnion>
+void paramOut(std::ostream &os, const std::string &name,
+ const BitfieldBackend::BitUnionOperators<DataType, BitUnion> &p)
+{
+ paramOut(os, name, p.__data);
+}
+
template <class T>
void paramIn(Checkpoint *cp, const std::string §ion,
const std::string &name, T ¶m);
+template <typename DataType, typename BitUnion>
+void paramIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name,
+ BitfieldBackend::BitUnionOperators<DataType, BitUnion> &p)
+{
+ paramIn(cp, section, name, p.__data);
+}
+
+template <class T>
+bool optParamIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name, T ¶m);
+
+template <typename DataType, typename BitUnion>
+bool optParamIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name,
+ BitfieldBackend::BitUnionOperators<DataType, BitUnion> &p)
+{
+ return optParamIn(cp, section, name, p.__data);
+}
+
+template <class T>
+void arrayParamOut(std::ostream &os, const std::string &name,
+ const T *param, unsigned size);
+
+template <class T>
+void arrayParamOut(std::ostream &os, const std::string &name,
+ const std::vector<T> ¶m);
+
template <class T>
void arrayParamOut(std::ostream &os, const std::string &name,
- const T *param, int size);
+ const std::list<T> ¶m);
+
+template <class T>
+void arrayParamIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name, T *param, unsigned size);
template <class T>
void arrayParamIn(Checkpoint *cp, const std::string §ion,
- const std::string &name, T *param, int size);
+ const std::string &name, std::vector<T> ¶m);
+
+template <class T>
+void arrayParamIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name, std::list<T> ¶m);
void
objParamIn(Checkpoint *cp, const std::string §ion,
- const std::string &name, Serializable * ¶m);
+ const std::string &name, SimObject * ¶m);
+
+template <typename T>
+void fromInt(T &t, int i)
+{
+ t = (T)i;
+}
+template <typename T>
+void fromSimObject(T &t, SimObject *s)
+{
+ t = dynamic_cast<T>(s);
+}
//
// These macros are streamlined to use in serialize/unserialize
// functions. It's assumed that serialize() has a parameter 'os' for
// the ostream, and unserialize() has parameters 'cp' and 'section'.
-#define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar)
+#define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar)
-#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar)
+#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar)
+#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, section, #scalar, scalar)
// ENUMs are like SCALARs, but we cast them to ints on the way out
-#define SERIALIZE_ENUM(scalar) paramOut(os, #scalar, (int)scalar)
+#define SERIALIZE_ENUM(scalar) paramOut(os, #scalar, (int)scalar)
-#define UNSERIALIZE_ENUM(scalar) \
- do { \
- int tmp; \
- paramIn(cp, section, #scalar, tmp); \
- scalar = (typeof(scalar))tmp; \
+#define UNSERIALIZE_ENUM(scalar) \
+ do { \
+ int tmp; \
+ paramIn(cp, section, #scalar, tmp); \
+ fromInt(scalar, tmp); \
} while (0)
-#define SERIALIZE_ARRAY(member, size) \
+#define SERIALIZE_ARRAY(member, size) \
arrayParamOut(os, #member, member, size)
-#define UNSERIALIZE_ARRAY(member, size) \
+#define UNSERIALIZE_ARRAY(member, size) \
arrayParamIn(cp, section, #member, member, size)
-#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name())
+#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name())
-#define UNSERIALIZE_OBJPTR(objptr) \
- do { \
- Serializable *sptr; \
- objParamIn(cp, section, #objptr, sptr); \
- objptr = dynamic_cast<typeof(objptr)>(sptr); \
+#define UNSERIALIZE_OBJPTR(objptr) \
+ do { \
+ SimObject *sptr; \
+ objParamIn(cp, section, #objptr, sptr); \
+ fromSimObject(objptr, sptr); \
} while (0)
-/*
+/**
* Basic support for object serialization.
+ *
+ * @note Many objects that support serialization need to be put in a
+ * consistent state when serialization takes place. We refer to the
+ * action of forcing an object into a consistent state as
+ * 'draining'. Objects that need draining inherit from Drainable. See
+ * Drainable for more information.
*/
class Serializable
{
void nameOut(std::ostream &os, const std::string &_name);
public:
- Serializable() {}
- virtual ~Serializable() {}
+ Serializable();
+ virtual ~Serializable();
// manditory virtual function, so objects must provide names
virtual const std::string name() const = 0;
- virtual void serialize(std::ostream &os) {}
- virtual void unserialize(Checkpoint *cp, const std::string §ion) {}
+ virtual void serialize(std::ostream &os);
+ virtual void unserialize(Checkpoint *cp, const std::string §ion);
- static Serializable *create(Checkpoint *cp,
- const std::string §ion);
+ static Serializable *create(Checkpoint *cp, const std::string §ion);
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 unserializeGlobals(Checkpoint *cp);
};
+void debug_serialize(const std::string &cpt_dir);
+
//
// A SerializableBuilder serves as an evaluation context for a set of
// parameters that describe a specific instance of a Serializable. This
// SerializableBuilder and SerializableClass objects
//
-#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \
-SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
+#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \
+SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \
OBJ_CLASS::createForUnserialize);
-void
-setCheckpointName(const std::string &name);
+// Base class to wrap object resolving functionality. This can be
+// provided to Checkpoint to allow it to map object names onto
+// object C++ objects in which to unserialize
+class SimObjectResolver
+{
+ public:
+ virtual ~SimObjectResolver() { }
+
+ // Find a SimObject given a full path name
+ virtual SimObject *resolveSimObject(const std::string &name) = 0;
+};
class Checkpoint
{
private:
IniFile *db;
- const std::string basePath;
- std::map<std::string, Serializable*> objMap;
+
+ SimObjectResolver &objNameResolver;
public:
- Checkpoint(const std::string &cpt_dir, const std::string &path);
+ Checkpoint(const std::string &cpt_dir, SimObjectResolver &resolver);
+ ~Checkpoint();
const std::string cptDir;
std::string &value);
bool findObj(const std::string §ion, const std::string &entry,
- Serializable *&value);
+ SimObject *&value);
bool sectionExists(const std::string §ion);
// The following static functions have to do with checkpoint
// creation rather than restoration. This class makes a handy
- // namespace for them though.
+ // namespace for them though. Currently no Checkpoint object is
+ // created on serialization (only unserialization) so we track the
+ // directory name as a global. It would be nice to change this
+ // someday
+
+ private:
+ // current directory we're serializing into.
+ static std::string currentDirectory;
+
+ public:
+ // Set the current directory. This function takes care of
+ // inserting curTick() if there's a '%d' in the argument, and
+ // appends a '/' if necessary. The final name is returned.
+ static std::string setDir(const std::string &base_name);
// Export current checkpoint directory name so other objects can
// derive filenames from it (e.g., memory). The return value is
// Filename for base checkpoint file within directory.
static const char *baseFilename;
-
- // Set up a checkpoint creation event or series of events.
- static void setup(Tick when, Tick period = 0);
};
#endif // __SERIALIZE_HH__