From 16bf103ad8e2bfbdf200a0ade11cff17dd33e81d Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Wed, 17 Oct 2018 17:17:48 +0100 Subject: sim: Move paramIn/Out definition to header file This patch is moving the definitions of paramIn/Out templates to the header file. In this way we gain: 1) We don't have to do explicit instantiation anymore for user defined types. This spares us from including data type header files into serialize.cc 2) We can overload show/parseParam for BitUnions or any other type that requires special handling when serializing. Just by overloading the two templates we get all the containers' (list, vector, array..) serialization for free 2) gtest: With the idea of adding unit tests for Serializable objects, we can avoid importing serialize.cc and just redefine Serializable methods in the test source, implementing a Serializable stub Change-Id: I45a9bb87d5ef886a3668fd477005cd105f612e36 Signed-off-by: Giacomo Travaglini Reviewed-on: https://gem5-review.googlesource.com/c/13635 Reviewed-by: Gabe Black Maintainer: Andreas Sandberg --- src/sim/serialize.cc | 429 ++-------------------------------- src/sim/serialize.hh | 640 +++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 479 insertions(+), 590 deletions(-) (limited to 'src') diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index a03a396b3..095a44c34 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -57,12 +57,8 @@ #include #include -#include "arch/generic/vec_reg.hh" -#include "base/framebuffer.hh" #include "base/inifile.hh" -#include "base/logging.hh" #include "base/output.hh" -#include "base/str.hh" #include "base/trace.hh" #include "debug/Checkpoint.hh" #include "sim/eventq.hh" @@ -75,412 +71,11 @@ using namespace std; -// -// The base implementations use to_number for parsing and '<<' for -// displaying, suitable for integer types. -// -template -bool -parseParam(const string &s, T &value) -{ - return to_number(s, value); -} - -template -void -showParam(CheckpointOut &os, const T &value) -{ - os << value; -} - -// -// Template specializations: -// - char (8-bit integer) -// - floating-point types -// - bool -// - string -// - -// Treat 8-bit ints (chars) as ints on output, not as chars -template <> -void -showParam(CheckpointOut &os, const char &value) -{ - os << (int)value; -} - - -template <> -void -showParam(CheckpointOut &os, const signed char &value) -{ - os << (int)value; -} - - -template <> -void -showParam(CheckpointOut &os, const unsigned char &value) -{ - os << (unsigned int)value; -} - - -template <> -bool -parseParam(const string &s, float &value) -{ - return to_number(s, value); -} - -template <> -bool -parseParam(const string &s, double &value) -{ - return to_number(s, value); -} - -template <> -bool -parseParam(const string &s, bool &value) -{ - return to_bool(s, value); -} - -// Display bools as strings -template <> -void -showParam(CheckpointOut &os, const bool &value) -{ - os << (value ? "true" : "false"); -} - - -// String requires no processing to speak of -template <> -bool -parseParam(const string &s, string &value) -{ - value = s; - return true; -} - int Serializable::ckptMaxCount = 0; int Serializable::ckptCount = 0; int Serializable::ckptPrevCount = -1; std::stack Serializable::path; -template -void -paramOut(CheckpointOut &os, const string &name, const T ¶m) -{ - os << name << "="; - showParam(os, param); - os << "\n"; -} - -template -void -arrayParamOut(CheckpointOut &os, const string &name, const vector ¶m) -{ - typename vector::size_type size = param.size(); - os << name << "="; - if (size > 0) - showParam(os, param[0]); - for (typename vector::size_type i = 1; i < size; ++i) { - os << " "; - showParam(os, param[i]); - } - os << "\n"; -} - -template -void -arrayParamOut(CheckpointOut &os, const string &name, const list ¶m) -{ - typename list::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 -void -arrayParamOut(CheckpointOut &os, const string &name, const set ¶m) -{ - typename set::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 -void -paramIn(CheckpointIn &cp, const string &name, T ¶m) -{ - const string §ion(Serializable::currentSection()); - string str; - if (!cp.find(section, name, str) || !parseParam(str, param)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } -} - -template -bool -optParamIn(CheckpointIn &cp, const string &name, T ¶m, bool warn) -{ - const string §ion(Serializable::currentSection()); - 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; - } -} - -template -void -arrayParamOut(CheckpointOut &os, const 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 -void -arrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size) -{ - const string §ion(Serializable::currentSection()); - string str; - if (!cp.find(section, name, str)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } - - // code below stolen from VectorParam::parse(). - // it would be nice to unify these somehow... - - vector 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 (vector::size_type i = 0; i < tokens.size(); i++) { - // need to parse into local variable to handle vector, - // 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)) { - string err("could not parse \""); - - err += str; - err += "\""; - - fatal(err); - } - - // assign parsed value to vector - param[i] = scalar_value; - } -} - -template -void -arrayParamIn(CheckpointIn &cp, const string &name, vector ¶m) -{ - const string §ion(Serializable::currentSection()); - string str; - if (!cp.find(section, name, str)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } - - // code below stolen from VectorParam::parse(). - // it would be nice to unify these somehow... - - vector tokens; - - tokenize(tokens, str, ' '); - - // Need this if we were doing a vector - // value.resize(tokens.size()); - - param.resize(tokens.size()); - - for (vector::size_type i = 0; i < tokens.size(); i++) { - // need to parse into local variable to handle vector, - // 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)) { - string err("could not parse \""); - - err += str; - err += "\""; - - fatal(err); - } - - // assign parsed value to vector - param[i] = scalar_value; - } -} - -template -void -arrayParamIn(CheckpointIn &cp, const string &name, list ¶m) -{ - const string §ion(Serializable::currentSection()); - string str; - if (!cp.find(section, name, str)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } - param.clear(); - - vector tokens; - tokenize(tokens, str, ' '); - - for (vector::size_type i = 0; i < tokens.size(); i++) { - T scalar_value; - if (!parseParam(tokens[i], scalar_value)) { - string err("could not parse \""); - - err += str; - err += "\""; - - fatal(err); - } - - // assign parsed value to vector - param.push_back(scalar_value); - } -} - -template -void -arrayParamIn(CheckpointIn &cp, const string &name, set ¶m) -{ - const string §ion(Serializable::currentSection()); - string str; - if (!cp.find(section, name, str)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } - param.clear(); - - vector tokens; - tokenize(tokens, str, ' '); - - for (vector::size_type i = 0; i < tokens.size(); i++) { - T scalar_value; - if (!parseParam(tokens[i], scalar_value)) { - string err("could not parse \""); - - err += str; - err += "\""; - - fatal(err); - } - - // assign parsed value to vector - param.insert(scalar_value); - } -} - - -void -objParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) -{ - const string §ion(Serializable::currentSection()); - if (!cp.findObj(section, name, param)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } -} - - -#define INSTANTIATE_PARAM_TEMPLATES(type) \ - template void \ - paramOut(CheckpointOut &os, const string &name, type const ¶m); \ - template void \ - paramIn(CheckpointIn &cp, const string &name, type & param); \ - template bool \ - optParamIn(CheckpointIn &cp, const string &name, type & param, \ - bool warn); \ - template void \ - arrayParamOut(CheckpointOut &os, const string &name, \ - type const *param, unsigned size); \ - template void \ - arrayParamIn(CheckpointIn &cp, const string &name, \ - type *param, unsigned size); \ - template void \ - arrayParamOut(CheckpointOut &os, const string &name, \ - const vector ¶m); \ - template void \ - arrayParamIn(CheckpointIn &cp, const string &name, \ - vector ¶m); \ - template void \ - arrayParamOut(CheckpointOut &os, const string &name, \ - const list ¶m); \ - template void \ - arrayParamIn(CheckpointIn &cp, const string &name, \ - list ¶m); - -INSTANTIATE_PARAM_TEMPLATES(char) -INSTANTIATE_PARAM_TEMPLATES(signed char) -INSTANTIATE_PARAM_TEMPLATES(unsigned char) -INSTANTIATE_PARAM_TEMPLATES(signed short) -INSTANTIATE_PARAM_TEMPLATES(unsigned short) -INSTANTIATE_PARAM_TEMPLATES(signed int) -INSTANTIATE_PARAM_TEMPLATES(unsigned int) -INSTANTIATE_PARAM_TEMPLATES(signed long) -INSTANTIATE_PARAM_TEMPLATES(unsigned long) -INSTANTIATE_PARAM_TEMPLATES(signed long long) -INSTANTIATE_PARAM_TEMPLATES(unsigned long long) -INSTANTIATE_PARAM_TEMPLATES(bool) -INSTANTIATE_PARAM_TEMPLATES(float) -INSTANTIATE_PARAM_TEMPLATES(double) -INSTANTIATE_PARAM_TEMPLATES(string) -INSTANTIATE_PARAM_TEMPLATES(Pixel) -INSTANTIATE_PARAM_TEMPLATES(VecRegContainer<8>) -INSTANTIATE_PARAM_TEMPLATES(VecRegContainer<16>) - -// set is only used with strings and furthermore doesn't agree with Pixel -template void -arrayParamOut(CheckpointOut &, const string &, const set &); -template void -arrayParamIn(CheckpointIn &, const string &, set &); - ///////////////////////////// /// Container for serializing global variables (not associated with @@ -645,12 +240,6 @@ Serializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp) cp << "\n[" << Serializable::currentSection() << "]\n"; } -void -debug_serialize(const string &cpt_dir) -{ - Serializable::serializeAll(cpt_dir); -} - const std::string & Serializable::currentSection() { @@ -681,7 +270,6 @@ CheckpointIn::dir() return currentDirectory; } - CheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver) : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir)) { @@ -708,7 +296,6 @@ CheckpointIn::find(const string §ion, const string &entry, string &value) return db->find(section, entry, value); } - bool CheckpointIn::findObj(const string §ion, const string &entry, SimObject *&value) @@ -722,9 +309,23 @@ CheckpointIn::findObj(const string §ion, const string &entry, return true; } - bool CheckpointIn::sectionExists(const string §ion) { return db->sectionExists(section); } + +void +objParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) +{ + const string §ion(Serializable::currentSection()); + if (!cp.findObj(section, name, param)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } +} + +void +debug_serialize(const string &cpt_dir) +{ + Serializable::serializeAll(cpt_dir); +} 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 #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 -void paramOut(CheckpointOut &cp, const std::string &name, const T ¶m); - -template -void -paramOut(CheckpointOut &cp, const std::string &name, const BitUnionType &p) -{ - paramOut(cp, name, static_cast >(p)); -} - -template -void paramIn(CheckpointIn &cp, const std::string &name, T ¶m); - -template -void -paramIn(CheckpointIn &cp, const std::string &name, BitUnionType &p) -{ - BitUnionBaseType b; - paramIn(cp, name, b); - p = b; -} - -template -bool optParamIn(CheckpointIn &cp, const std::string &name, T ¶m, - bool warn = true); - -template -bool -optParamIn(CheckpointIn &cp, const std::string &name, - BitUnionType &p, bool warn = true) -{ - BitUnionBaseType b; - if (optParamIn(cp, name, b, warn)) { - p = b; - return true; - } else { - return false; - } -} - -template -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const T *param, unsigned size); - -template -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const std::vector ¶m); - -template -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const std::list ¶m); - -template -void arrayParamOut(CheckpointOut &cp, const std::string &name, - const std::set ¶m); - -template -void arrayParamIn(CheckpointIn &cp, const std::string &name, - T *param, unsigned size); - -template -void arrayParamIn(CheckpointIn &cp, const std::string &name, - std::vector ¶m); - -template -void arrayParamIn(CheckpointIn &cp, const std::string &name, - std::list ¶m); - -template -void arrayParamIn(CheckpointIn &cp, const std::string &name, - std::set ¶m); - -void -objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m); - -template -static void -arrayParamOut(CheckpointOut &cp, const std::string &name, - const BitUnionType *param, unsigned size) -{ - // We copy the array into a vector. This is needed since we cannot - // directly typecast a pointer to BitUnionType into a pointer - // of BitUnionBaseType but we can typecast BitUnionType - // to BitUnionBaseType since we overloaded the typecast operator - std::vector> bitunion_vec(param, param + size); - - arrayParamOut(cp, name, bitunion_vec); -} - -template -static void -arrayParamIn(CheckpointIn &cp, const std::string &name, - BitUnionType *param, unsigned size) +class CheckpointIn { - std::vector> 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(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(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 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 +bool +parseParam(const std::string &s, T &value) +{ + return to_number(s, value); +} +template +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 +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 +void +paramOut(CheckpointOut &cp, const std::string &name, const BitUnionType &p) +{ + paramOut(cp, name, static_cast >(p)); +} - private: - // current directory we're serializing into. - static std::string currentDirectory; +template +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 +void +paramIn(CheckpointIn &cp, const std::string &name, BitUnionType &p) +{ + BitUnionBaseType 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 +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 +bool +optParamIn(CheckpointIn &cp, const std::string &name, + BitUnionType &p, bool warn = true) +{ + BitUnionBaseType b; + if (optParamIn(cp, name, b, warn)) { + p = b; + return true; + } else { + return false; + } +} + +template +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const std::vector ¶m) +{ + typename std::vector::size_type size = param.size(); + os << name << "="; + if (size > 0) + showParam(os, param[0]); + for (typename std::vector::size_type i = 1; i < size; ++i) { + os << " "; + showParam(os, param[i]); + } + os << "\n"; +} + +template +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const std::list ¶m) +{ + typename std::list::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 +void +arrayParamOut(CheckpointOut &os, const std::string &name, + const std::set ¶m) +{ + typename std::set::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 +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 +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::parse(). + // it would be nice to unify these somehow... + + std::vector 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::size_type i = 0; i < tokens.size(); i++) { + // need to parse into local variable to handle vector, + // 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 +void +arrayParamIn(CheckpointIn &cp, const std::string &name, std::vector ¶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::parse(). + // it would be nice to unify these somehow... + + std::vector tokens; + + tokenize(tokens, str, ' '); + + // Need this if we were doing a vector + // value.resize(tokens.size()); + + param.resize(tokens.size()); + + for (std::vector::size_type i = 0; i < tokens.size(); i++) { + // need to parse into local variable to handle vector, + // 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 +void +arrayParamIn(CheckpointIn &cp, const std::string &name, std::list ¶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 tokens; + tokenize(tokens, str, ' '); + + for (std::vector::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 +void +arrayParamIn(CheckpointIn &cp, const std::string &name, std::set ¶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 tokens; + tokenize(tokens, str, ' '); + + for (std::vector::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 +static void +arrayParamOut(CheckpointOut &cp, const std::string &name, + const BitUnionType *param, unsigned size) +{ + // We copy the array into a vector. This is needed since we cannot + // directly typecast a pointer to BitUnionType into a pointer + // of BitUnionBaseType but we can typecast BitUnionType + // to BitUnionBaseType since we overloaded the typecast operator + std::vector> bitunion_vec(param, param + size); + + arrayParamOut(cp, name, bitunion_vec); +} + +template +static void +arrayParamIn(CheckpointIn &cp, const std::string &name, + BitUnionType *param, unsigned size) +{ + std::vector> 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(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(sptr); \ + } while (0) #endif // __SERIALIZE_HH__ -- cgit v1.2.3