diff options
Diffstat (limited to 'src/sim/serialize.hh')
-rw-r--r-- | src/sim/serialize.hh | 640 |
1 files changed, 464 insertions, 176 deletions
diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index b3081ad5a..adaefdd84 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -60,166 +60,65 @@ #include <vector> #include "base/bitunion.hh" +#include "base/logging.hh" +#include "base/str.hh" -class CheckpointIn; class IniFile; -class Serializable; class SimObject; class SimObjectResolver; typedef std::ostream CheckpointOut; - -template <class T> -void paramOut(CheckpointOut &cp, const std::string &name, const T ¶m); - -template <typename T> -void -paramOut(CheckpointOut &cp, const std::string &name, const BitUnionType<T> &p) -{ - paramOut(cp, name, static_cast<BitUnionBaseType<T> >(p)); -} - -template <class T> -void paramIn(CheckpointIn &cp, const std::string &name, T ¶m); - -template <typename T> -void -paramIn(CheckpointIn &cp, const std::string &name, BitUnionType<T> &p) -{ - BitUnionBaseType<T> b; - paramIn(cp, name, b); - p = b; -} - -template <class T> -bool optParamIn(CheckpointIn &cp, const std::string &name, T ¶m, - bool warn = true); - -template <typename T> -bool -optParamIn(CheckpointIn &cp, const std::string &name, - BitUnionType<T> &p, bool warn = true) -{ - BitUnionBaseType<T> b; - if (optParamIn(cp, name, b, warn)) { - p = b; - return true; - } else { - return false; - } -} - -template <class T> -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const T *param, unsigned size); - -template <class T> -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const std::vector<T> ¶m); - -template <class T> -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const std::list<T> ¶m); - -template <class T> -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const std::set<T> ¶m); - -template <class T> -void arrayParamIn(CheckpointIn &cp, const std::string &name, - T *param, unsigned size); - -template <class T> -void arrayParamIn(CheckpointIn &cp, const std::string &name, - std::vector<T> ¶m); - -template <class T> -void arrayParamIn(CheckpointIn &cp, const std::string &name, - std::list<T> ¶m); - -template <class T> -void arrayParamIn(CheckpointIn &cp, const std::string &name, - std::set<T> ¶m); - -void -objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m); - -template <class T> -static void -arrayParamOut(CheckpointOut &cp, const std::string &name, - const BitUnionType<T> *param, unsigned size) -{ - // We copy the array into a vector. This is needed since we cannot - // directly typecast a pointer to BitUnionType<T> into a pointer - // of BitUnionBaseType<T> but we can typecast BitUnionType<T> - // to BitUnionBaseType<T> since we overloaded the typecast operator - std::vector<BitUnionBaseType<T>> bitunion_vec(param, param + size); - - arrayParamOut(cp, name, bitunion_vec); -} - -template <class T> -static void -arrayParamIn(CheckpointIn &cp, const std::string &name, - BitUnionType<T> *param, unsigned size) +class CheckpointIn { - std::vector<BitUnionBaseType<T>> bitunion_vec(size); - - arrayParamIn(cp, name, bitunion_vec); - std::copy(bitunion_vec.begin(), bitunion_vec.end(), param); -} + private: -// -// 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(cp, #scalar, scalar) + IniFile *db; -#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, #scalar, scalar) -#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, #scalar, scalar) + SimObjectResolver &objNameResolver; -// ENUMs are like SCALARs, but we cast them to ints on the way out -#define SERIALIZE_ENUM(scalar) paramOut(cp, #scalar, (int)scalar) + public: + CheckpointIn(const std::string &cpt_dir, SimObjectResolver &resolver); + ~CheckpointIn(); -#define UNSERIALIZE_ENUM(scalar) \ - do { \ - int tmp; \ - paramIn(cp, #scalar, tmp); \ - scalar = static_cast<decltype(scalar)>(tmp); \ - } while (0) + const std::string cptDir; -#define SERIALIZE_ARRAY(member, size) \ - arrayParamOut(cp, #member, member, size) + bool find(const std::string §ion, const std::string &entry, + std::string &value); -#define UNSERIALIZE_ARRAY(member, size) \ - arrayParamIn(cp, #member, member, size) + bool findObj(const std::string §ion, const std::string &entry, + SimObject *&value); -#define SERIALIZE_CONTAINER(member) \ - arrayParamOut(cp, #member, member) -#define UNSERIALIZE_CONTAINER(member) \ - arrayParamIn(cp, #member, member) + bool entryExists(const std::string §ion, const std::string &entry); + bool sectionExists(const std::string §ion); -#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event); + // 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 -#define UNSERIALIZE_EVENT(event) \ - do { \ - event.unserializeSection(cp, #event); \ - eventQueue()->checkpointReschedule(&event); \ - } while (0) + private: + // current directory we're serializing into. + static std::string currentDirectory; -#define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj) -#define UNSERIALIZE_OBJ(obj) obj.unserializeSection(cp, #obj) + 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); -#define SERIALIZE_OBJPTR(objptr) paramOut(cp, #objptr, (objptr)->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(); -#define UNSERIALIZE_OBJPTR(objptr) \ - do { \ - SimObject *sptr; \ - objParamIn(cp, #objptr, sptr); \ - objptr = dynamic_cast<decltype(objptr)>(sptr); \ - } while (0) + // Filename for base checkpoint file within directory. + static const char *baseFilename; +}; /** * Basic support for object serialization. @@ -368,58 +267,447 @@ class Serializable static std::stack<std::string> path; }; -void debug_serialize(const std::string &cpt_dir); +// +// The base implementations use to_number for parsing and '<<' for +// displaying, suitable for integer types. +// +template <class T> +bool +parseParam(const std::string &s, T &value) +{ + return to_number(s, value); +} +template <class T> +void +showParam(CheckpointOut &os, const T &value) +{ + os << value; +} -class CheckpointIn +// Treat 8-bit ints (chars) as ints on output, not as chars +template <> +inline void +showParam(CheckpointOut &os, const char &value) { - private: + os << (int)value; +} - IniFile *db; +template <> +inline void +showParam(CheckpointOut &os, const signed char &value) +{ + os << (int)value; +} - SimObjectResolver &objNameResolver; +template <> +inline void +showParam(CheckpointOut &os, const unsigned char &value) +{ + os << (unsigned int)value; +} - public: - CheckpointIn(const std::string &cpt_dir, SimObjectResolver &resolver); - ~CheckpointIn(); +template <> +inline bool +parseParam(const std::string &s, float &value) +{ + return to_number(s, value); +} - const std::string cptDir; +template <> +inline bool +parseParam(const std::string &s, double &value) +{ + return to_number(s, value); +} - bool find(const std::string §ion, const std::string &entry, - std::string &value); +template <> +inline bool +parseParam(const std::string &s, bool &value) +{ + return to_bool(s, value); +} - bool findObj(const std::string §ion, const std::string &entry, - SimObject *&value); +// Display bools as strings +template <> +inline void +showParam(CheckpointOut &os, const bool &value) +{ + os << (value ? "true" : "false"); +} +// String requires no processing to speak of +template <> +inline bool +parseParam(const std::string &s, std::string &value) +{ + value = s; + return true; +} - bool entryExists(const std::string §ion, const std::string &entry); - bool sectionExists(const std::string §ion); +template <class T> +void +paramOut(CheckpointOut &os, const std::string &name, const T ¶m) +{ + os << name << "="; + showParam(os, param); + os << "\n"; +} - // 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 +template <typename T> +void +paramOut(CheckpointOut &cp, const std::string &name, const BitUnionType<T> &p) +{ + paramOut(cp, name, static_cast<BitUnionBaseType<T> >(p)); +} - private: - // current directory we're serializing into. - static std::string currentDirectory; +template <class T> +void +paramIn(CheckpointIn &cp, const std::string &name, T ¶m) +{ + const std::string §ion(Serializable::currentSection()); + std::string str; + if (!cp.find(section, name, str) || !parseParam(str, param)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } +} - 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); +template <typename T> +void +paramIn(CheckpointIn &cp, const std::string &name, BitUnionType<T> &p) +{ + BitUnionBaseType<T> b; + paramIn(cp, name, b); + p = b; +} - // 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(); +template <class T> +bool +optParamIn(CheckpointIn &cp, const std::string &name, + T ¶m, bool warn = true) +{ + const std::string §ion(Serializable::currentSection()); + std::string str; + if (!cp.find(section, name, str) || !parseParam(str, param)) { + if (warn) + warn("optional parameter %s:%s not present\n", section, name); + return false; + } else { + return true; + } +} - // Filename for base checkpoint file within directory. - static const char *baseFilename; -}; +template <typename T> +bool +optParamIn(CheckpointIn &cp, const std::string &name, + BitUnionType<T> &p, bool warn = true) +{ + BitUnionBaseType<T> b; + if (optParamIn(cp, name, b, warn)) { + p = b; + return true; + } else { + return false; + } +} + +template <class T> +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const std::vector<T> ¶m) +{ + typename std::vector<T>::size_type size = param.size(); + os << name << "="; + if (size > 0) + showParam(os, param[0]); + for (typename std::vector<T>::size_type i = 1; i < size; ++i) { + os << " "; + showParam(os, param[i]); + } + os << "\n"; +} + +template <class T> +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const std::list<T> ¶m) +{ + typename std::list<T>::const_iterator it = param.begin(); + + os << name << "="; + if (param.size() > 0) + showParam(os, *it); + it++; + while (it != param.end()) { + os << " "; + showParam(os, *it); + it++; + } + os << "\n"; +} + +template <class T> +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const std::set<T> ¶m) +{ + typename std::set<T>::const_iterator it = param.begin(); + + os << name << "="; + if (param.size() > 0) + showParam(os, *it); + it++; + while (it != param.end()) { + os << " "; + showParam(os, *it); + it++; + } + os << "\n"; +} + +template <class T> +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const T *param, unsigned size) +{ + os << name << "="; + if (size > 0) + showParam(os, param[0]); + for (unsigned i = 1; i < size; ++i) { + os << " "; + showParam(os, param[i]); + } + os << "\n"; +} + + +template <class T> +void +arrayParamIn(CheckpointIn &cp, const std::string &name, + T *param, unsigned size) +{ + const std::string §ion(Serializable::currentSection()); + std::string str; + if (!cp.find(section, name, str)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } + + // code below stolen from VectorParam<T>::parse(). + // it would be nice to unify these somehow... + + std::vector<std::string> tokens; + + tokenize(tokens, str, ' '); + + // Need this if we were doing a vector + // value.resize(tokens.size()); + + if (tokens.size() != size) { + fatal("Array size mismatch on %s:%s'\n", section, name); + } + + for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) { + // need to parse into local variable to handle vector<bool>, + // for which operator[] returns a special reference class + // that's not the same as 'bool&', (since it's a packed + // vector) + T scalar_value; + if (!parseParam(tokens[i], scalar_value)) { + std::string err("could not parse \""); + + err += str; + err += "\""; + + fatal(err); + } + + // assign parsed value to vector + param[i] = scalar_value; + } +} + +template <class T> +void +arrayParamIn(CheckpointIn &cp, const std::string &name, std::vector<T> ¶m) +{ + const std::string §ion(Serializable::currentSection()); + std::string str; + if (!cp.find(section, name, str)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } + + // code below stolen from VectorParam<T>::parse(). + // it would be nice to unify these somehow... + + std::vector<std::string> tokens; + + tokenize(tokens, str, ' '); + + // Need this if we were doing a vector + // value.resize(tokens.size()); + + param.resize(tokens.size()); + + for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) { + // need to parse into local variable to handle vector<bool>, + // for which operator[] returns a special reference class + // that's not the same as 'bool&', (since it's a packed + // vector) + T scalar_value; + if (!parseParam(tokens[i], scalar_value)) { + std::string err("could not parse \""); + + err += str; + err += "\""; + + fatal(err); + } + + // assign parsed value to vector + param[i] = scalar_value; + } +} + +template <class T> +void +arrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> ¶m) +{ + const std::string §ion(Serializable::currentSection()); + std::string str; + if (!cp.find(section, name, str)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } + param.clear(); + + std::vector<std::string> tokens; + tokenize(tokens, str, ' '); + + for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) { + T scalar_value; + if (!parseParam(tokens[i], scalar_value)) { + std::string err("could not parse \""); + + err += str; + err += "\""; + + fatal(err); + } + + // assign parsed value to vector + param.push_back(scalar_value); + } +} + +template <class T> +void +arrayParamIn(CheckpointIn &cp, const std::string &name, std::set<T> ¶m) +{ + const std::string §ion(Serializable::currentSection()); + std::string str; + if (!cp.find(section, name, str)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } + param.clear(); + + std::vector<std::string> tokens; + tokenize(tokens, str, ' '); + + for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) { + T scalar_value; + if (!parseParam(tokens[i], scalar_value)) { + std::string err("could not parse \""); + + err += str; + err += "\""; + + fatal(err); + } + + // assign parsed value to vector + param.insert(scalar_value); + } +} + +template <class T> +static void +arrayParamOut(CheckpointOut &cp, const std::string &name, + const BitUnionType<T> *param, unsigned size) +{ + // We copy the array into a vector. This is needed since we cannot + // directly typecast a pointer to BitUnionType<T> into a pointer + // of BitUnionBaseType<T> but we can typecast BitUnionType<T> + // to BitUnionBaseType<T> since we overloaded the typecast operator + std::vector<BitUnionBaseType<T>> bitunion_vec(param, param + size); + + arrayParamOut(cp, name, bitunion_vec); +} + +template <class T> +static void +arrayParamIn(CheckpointIn &cp, const std::string &name, + BitUnionType<T> *param, unsigned size) +{ + std::vector<BitUnionBaseType<T>> bitunion_vec(size); + + arrayParamIn(cp, name, bitunion_vec); + std::copy(bitunion_vec.begin(), bitunion_vec.end(), param); +} + +void +debug_serialize(const std::string &cpt_dir); + +void +objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m); + +// +// 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(cp, #scalar, scalar) + +#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, #scalar, scalar) +#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, #scalar, scalar) + +// ENUMs are like SCALARs, but we cast them to ints on the way out +#define SERIALIZE_ENUM(scalar) paramOut(cp, #scalar, (int)scalar) + +#define UNSERIALIZE_ENUM(scalar) \ + do { \ + int tmp; \ + paramIn(cp, #scalar, tmp); \ + scalar = static_cast<decltype(scalar)>(tmp); \ + } while (0) + +#define SERIALIZE_ARRAY(member, size) \ + arrayParamOut(cp, #member, member, size) + +#define UNSERIALIZE_ARRAY(member, size) \ + arrayParamIn(cp, #member, member, size) + +#define SERIALIZE_CONTAINER(member) \ + arrayParamOut(cp, #member, member) + +#define UNSERIALIZE_CONTAINER(member) \ + arrayParamIn(cp, #member, member) + +#define SERIALIZE_EVENT(event) event.serializeSection(cp, #event); + +#define UNSERIALIZE_EVENT(event) \ + do { \ + event.unserializeSection(cp, #event); \ + eventQueue()->checkpointReschedule(&event); \ + } while (0) + +#define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj) +#define UNSERIALIZE_OBJ(obj) obj.unserializeSection(cp, #obj) + +#define SERIALIZE_OBJPTR(objptr) paramOut(cp, #objptr, (objptr)->name()) + +#define UNSERIALIZE_OBJPTR(objptr) \ + do { \ + SimObject *sptr; \ + objParamIn(cp, #objptr, sptr); \ + objptr = dynamic_cast<decltype(objptr)>(sptr); \ + } while (0) #endif // __SERIALIZE_HH__ |