| /* | |
| * Copyright (c) 2002-2005 The Regents of The University of Michigan | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are | |
| * met: redistributions of source code must retain the above copyright | |
| * notice, this list of conditions and the following disclaimer; | |
| * redistributions in binary form must reproduce the above copyright | |
| * notice, this list of conditions and the following disclaimer in the | |
| * documentation and/or other materials provided with the distribution; | |
| * neither the name of the copyright holders nor the names of its | |
| * contributors may be used to endorse or promote products derived from | |
| * this software without specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * Authors: Nathan Binkert | |
| * Erik Hallnor | |
| * Steve Reinhardt | |
| */ | |
| /* @file | |
| * Serialization Interface Declarations | |
| */ | |
| #ifndef __SERIALIZE_HH__ | |
| #define __SERIALIZE_HH__ | |
| #include <iostream> | |
| #include <list> | |
| #include <map> | |
| #include <vector> | |
| #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 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, 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, 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 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 UNSERIALIZE_ENUM(scalar) \ | |
| do { \ | |
| int tmp; \ | |
| paramIn(cp, section, #scalar, tmp); \ | |
| fromInt(scalar, tmp); \ | |
| } while (0) | |
| #define SERIALIZE_ARRAY(member, size) \ | |
| arrayParamOut(os, #member, member, size) | |
| #define UNSERIALIZE_ARRAY(member, size) \ | |
| arrayParamIn(cp, section, #member, member, size) | |
| #define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name()) | |
| #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 | |
| { | |
| protected: | |
| void nameOut(std::ostream &os); | |
| void nameOut(std::ostream &os, const std::string &_name); | |
| public: | |
| 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); | |
| static Serializable *create(Checkpoint *cp, const std::string §ion); | |
| static int ckptCount; | |
| static int ckptMaxCount; | |
| static int ckptPrevCount; | |
| 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 | |
| // evaluation context corresponds to a section in the .ini file (as | |
| // with the base ParamContext) plus an optional node in the | |
| // configuration hierarchy (the configNode member) for resolving | |
| // Serializable references. SerializableBuilder is an abstract superclass; | |
| // derived classes specialize the class for particular subclasses of | |
| // Serializable (e.g., BaseCache). | |
| // | |
| // For typical usage, see the definition of | |
| // SerializableClass::createObject(). | |
| // | |
| class SerializableBuilder | |
| { | |
| public: | |
| SerializableBuilder() {} | |
| virtual ~SerializableBuilder() {} | |
| // Create the actual Serializable corresponding to the parameter | |
| // values in this context. This function is overridden in derived | |
| // classes to call a specific constructor for a particular | |
| // subclass of Serializable. | |
| virtual Serializable *create() = 0; | |
| }; | |
| // | |
| // An instance of SerializableClass corresponds to a class derived from | |
| // Serializable. The SerializableClass instance serves to bind the string | |
| // name (found in the config file) to a function that creates an | |
| // instance of the appropriate derived class. | |
| // | |
| // This would be much cleaner in Smalltalk or Objective-C, where types | |
| // are first-class objects themselves. | |
| // | |
| class SerializableClass | |
| { | |
| public: | |
| // Type CreateFunc is a pointer to a function that creates a new | |
| // simulation object builder based on a .ini-file parameter | |
| // section (specified by the first string argument), a unique name | |
| // for the object (specified by the second string argument), and | |
| // an optional config hierarchy node (specified by the third | |
| // argument). A pointer to the new SerializableBuilder is returned. | |
| typedef Serializable *(*CreateFunc)(Checkpoint *cp, | |
| const std::string §ion); | |
| static std::map<std::string,CreateFunc> *classMap; | |
| // Constructor. For example: | |
| // | |
| // SerializableClass baseCacheSerializableClass("BaseCacheSerializable", | |
| // newBaseCacheSerializableBuilder); | |
| // | |
| SerializableClass(const std::string &className, CreateFunc createFunc); | |
| // create Serializable given name of class and pointer to | |
| // configuration hierarchy node | |
| static Serializable *createObject(Checkpoint *cp, | |
| const std::string §ion); | |
| }; | |
| // | |
| // Macros to encapsulate the magic of declaring & defining | |
| // SerializableBuilder and SerializableClass objects | |
| // | |
| #define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \ | |
| SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \ | |
| OBJ_CLASS::createForUnserialize); | |
| // 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; | |
| SimObjectResolver &objNameResolver; | |
| public: | |
| Checkpoint(const std::string &cpt_dir, SimObjectResolver &resolver); | |
| ~Checkpoint(); | |
| const std::string cptDir; | |
| bool find(const std::string §ion, const std::string &entry, | |
| std::string &value); | |
| bool findObj(const std::string §ion, const std::string &entry, | |
| 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. 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 | |
| // guaranteed to end in '/' so filenames can be directly appended. | |
| // This function is only valid while a checkpoint is being created. | |
| static std::string dir(); | |
| // Filename for base checkpoint file within directory. | |
| static const char *baseFilename; | |
| }; | |
| #endif // __SERIALIZE_HH__ |