From 05c0d5237020a6d07cf49c0c32513f69cc548597 Mon Sep 17 00:00:00 2001 From: "Daniel R. Carvalho" Date: Sun, 27 Dec 2020 14:22:40 -0300 Subject: [PATCH] sim: Remove SimObject dependency from serialize.hh Previously Serializable::serializeAll called SimObject:: serializeAll. This created an unnecessary dependency. This change makes Serializable responsible for the generation of the checkpoint file, and then the SimObjects will perform the serialization of the object using that file. With this change serialize.hh contains only functions related to the (un)serialization of basic types or objects that inherit from Serializable. As a general rule, functions related to the (un)serialization of specific/other types must be defined in the file that introduces that type. Change-Id: I9438b799d7e9d4c992a62c7f9d1f15f3f3250a5a Signed-off-by: Daniel R. Carvalho Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/38740 Tested-by: kokoro Reviewed-by: Jason Lowe-Power Reviewed-by: Giacomo Travaglini Maintainer: Jason Lowe-Power --- src/python/pybind11/core.cc | 2 +- src/sim/serialize.cc | 37 +++++-------------------------------- src/sim/serialize.hh | 28 ++++++++++++++-------------- src/sim/sim_object.cc | 22 +++++++++++++++++++++- src/sim/sim_object.hh | 23 +++++++++++++++++++++-- 5 files changed, 62 insertions(+), 50 deletions(-) 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__