diff --git a/src/python/pybind11/core.cc b/src/python/pybind11/core.cc index 3b99ede752..a000cccf73 100644 --- a/src/python/pybind11/core.cc +++ b/src/python/pybind11/core.cc @@ -307,7 +307,7 @@ pybind_init_core(py::module_ &m_native) * Serialization helpers */ m_core - .def("serializeAll", &Serializable::serializeAll) + .def("serializeAll", &SimObject::serializeAll) .def("getCheckpoint", [](const std::string &cpt_dir) { SimObject::setSimObjectResolver(&pybindSimObjectResolver); return new CheckpointIn(cpt_dir); diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 86aaecbb24..93eaf2c1fb 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -46,21 +46,12 @@ #include #include +#include #include -#include -#include -#include -#include -#include #include "base/inifile.hh" -#include "base/output.hh" #include "base/trace.hh" #include "debug/Checkpoint.hh" -#include "sim/sim_object.hh" - -// For stat reset hack -#include "sim/stat_control.hh" int ckptMaxCount = 0; int ckptCount = 0; @@ -92,20 +83,19 @@ Serializable::unserializeSection(CheckpointIn &cp, const char *name) } void -Serializable::serializeAll(const std::string &cpt_dir) +Serializable::generateCheckpointOut(const std::string &cpt_dir, + std::ofstream &outstream) { std::string dir = CheckpointIn::setDir(cpt_dir); if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) fatal("couldn't mkdir %s\n", dir); std::string cpt_file = dir + CheckpointIn::baseFilename; - std::ofstream outstream(cpt_file.c_str()); + outstream = std::ofstream(cpt_file.c_str()); time_t t = time(NULL); - if (!outstream.is_open()) + if (!outstream) fatal("Unable to open file %s for writing\n", cpt_file.c_str()); outstream << "## checkpoint generated: " << ctime(&t); - - SimObject::serializeAll(outstream); } Serializable::ScopedCheckpointSection::~ScopedCheckpointSection() @@ -220,20 +210,3 @@ CheckpointIn::visitSection(const std::string §ion, { db->visitSection(section, cb); } - -void -objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m) -{ - const std::string §ion(Serializable::currentSection()); - std::string path; - if (!cp.find(section, name, path)) { - fatal("Can't unserialize '%s:%s'\n", section, name); - } - param = SimObject::getSimObjectResolver()->resolveSimObject(path); -} - -void -debug_serialize(const std::string &cpt_dir) -{ - Serializable::serializeAll(cpt_dir); -} diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index d20d9cf943..5bd59a467d 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -47,10 +47,11 @@ #include +#include #include #include #include -#include +#include #include #include #include @@ -60,7 +61,6 @@ #include "sim/serialize_handlers.hh" class IniFile; -class SimObject; typedef std::ostream CheckpointOut; @@ -301,11 +301,15 @@ class Serializable static const std::string ¤tSection(); /** - * Serializes all the SimObjects. + * Generate a checkpoint file so that the serialization can be routed to + * it. * + * @param cpt_dir The dir at which the cpt file will be created. + * @param outstream The cpt file. * @ingroup api_serialize */ - static void serializeAll(const std::string &cpt_dir); + static void generateCheckpointOut(const std::string &cpt_dir, + std::ofstream &outstream); private: static std::stack path; @@ -499,16 +503,6 @@ arrayParamIn(CheckpointIn &cp, const std::string &name, arrayParamIn(cp, name, insert_it, size); } -void -debug_serialize(const std::string &cpt_dir); - - -/** - * @ingroup api_serialize - */ -void -objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m); - /** * Serialize a mapping represented as two arrays: one containing names * and the other containing values. @@ -643,6 +637,12 @@ mappingParamIn(CheckpointIn &cp, const char* sectionName, /** * \def SERIALIZE_OBJ(obj) * + * This macro serializes an object into its own section. The object must + * inherit from Serializable, but NOT from SimObject (i.e, it is an object + * in the strict sense of "object oriented programing"). Objects that + * derive from SimObject are automatically serialized elsewhere + * (@see Serializable, SimObject::serializeAll()). + * * @ingroup api_serialize */ #define SERIALIZE_OBJ(obj) obj.serializeSection(cp, #obj) diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index 4c8d87b0ca..949a990a16 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -129,8 +129,11 @@ SimObject::getPort(const std::string &if_name, PortID idx) // static function: serialize all SimObjects. // void -SimObject::serializeAll(CheckpointOut &cp) +SimObject::serializeAll(const std::string &cpt_dir) { + std::ofstream cp; + Serializable::generateCheckpointOut(cpt_dir, cp); + SimObjectList::reverse_iterator ri = simObjectList.rbegin(); SimObjectList::reverse_iterator rend = simObjectList.rend(); @@ -194,3 +197,20 @@ SimObject::getSimObjectResolver() assert(_objNameResolver); return _objNameResolver; } + +void +objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m) +{ + const std::string §ion(Serializable::currentSection()); + std::string path; + if (!cp.find(section, name, path)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } + param = SimObject::getSimObjectResolver()->resolveSimObject(path); +} + +void +debug_serialize(const std::string &cpt_dir) +{ + SimObject::serializeAll(cpt_dir); +} diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index dad2217835..a47b0a31a4 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -318,9 +318,18 @@ class SimObject : public EventManager, public Serializable, public Drainable, void unserialize(CheckpointIn &cp) override {}; /** - * Serialize all SimObjects in the system. + * Create a checkpoint by serializing all SimObjects in the system. + * + * This is the entry point in the process of checkpoint creation, + * so it will create the checkpoint file and then unfold into + * the serialization of all the sim objects declared. + * + * Each SimObject instance is explicitly and individually serialized + * in its own section. As such, the serialization functions should not + * be called on sim objects anywhere else; otherwise, these objects + * would be needlessly serialized more than once. */ - static void serializeAll(CheckpointOut &cp); + static void serializeAll(const std::string &cpt_dir); #ifdef DEBUG public: @@ -392,4 +401,14 @@ class SimObjectResolver void debugObjectBreak(const char *objs); #endif +/** + * To avoid circular dependencies the unserialization of SimObjects must be + * implemented here. + * + * @ingroup api_serialize + */ +void objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m); + +void debug_serialize(const std::string &cpt_dir); + #endif // __SIM_OBJECT_HH__