From 76cd4393c08b83fa9006ee7bce1fb62457e053c1 Mon Sep 17 00:00:00 2001 From: Andreas Sandberg Date: Tue, 7 Jul 2015 09:51:03 +0100 Subject: sim: Refactor the serialization base class Objects that are can be serialized are supposed to inherit from the Serializable class. This class is meant to provide a unified API for such objects. However, so far it has mainly been used by SimObjects due to some fundamental design limitations. This changeset redesigns to the serialization interface to make it more generic and hide the underlying checkpoint storage. Specifically: * Add a set of APIs to serialize into a subsection of the current object. Previously, objects that needed this functionality would use ad-hoc solutions using nameOut() and section name generation. In the new world, an object that implements the interface has the methods serializeSection() and unserializeSection() that serialize into a named /subsection/ of the current object. Calling serialize() serializes an object into the current section. * Move the name() method from Serializable to SimObject as it is no longer needed for serialization. The fully qualified section name is generated by the main serialization code on the fly as objects serialize sub-objects. * Add a scoped ScopedCheckpointSection helper class. Some objects need to serialize data structures, that are not deriving from Serializable, into subsections. Previously, this was done using nameOut() and manual section name generation. To simplify this, this changeset introduces a ScopedCheckpointSection() helper class. When this class is instantiated, it adds a new /subsection/ and subsequent serialization calls during the lifetime of this helper class happen inside this section (or a subsection in case of nested sections). * The serialize() call is now const which prevents accidental state manipulation during serialization. Objects that rely on modifying state can use the serializeOld() call instead. The default implementation simply calls serialize(). Note: The old-style calls need to be explicitly called using the serializeOld()/serializeSectionOld() style APIs. These are used by default when serializing SimObjects. * Both the input and output checkpoints now use their own named types. This hides underlying checkpoint implementation from objects that need checkpointing and makes it easier to change the underlying checkpoint storage code. --- src/sim/clock_domain.cc | 8 +- src/sim/clock_domain.hh | 5 +- src/sim/cxx_manager.cc | 2 +- src/sim/cxx_manager.hh | 4 +- src/sim/dvfs_handler.cc | 23 ++-- src/sim/dvfs_handler.hh | 4 +- src/sim/eventq.cc | 21 ++-- src/sim/eventq.hh | 11 +- src/sim/process.cc | 25 +++-- src/sim/process.hh | 12 ++- src/sim/root.cc | 6 +- src/sim/root.hh | 7 +- src/sim/serialize.cc | 270 ++++++++++++++++++++++++++-------------------- src/sim/serialize.hh | 257 ++++++++++++++++++++++++++++++++++--------- src/sim/sim_events.cc | 17 ++- src/sim/sim_events.hh | 10 +- src/sim/sim_object.cc | 15 +-- src/sim/sim_object.hh | 8 +- src/sim/system.cc | 17 ++- src/sim/system.hh | 9 +- src/sim/ticked_object.cc | 20 ++-- src/sim/ticked_object.hh | 10 +- src/sim/voltage_domain.cc | 6 +- src/sim/voltage_domain.hh | 5 +- 24 files changed, 488 insertions(+), 284 deletions(-) (limited to 'src/sim') diff --git a/src/sim/clock_domain.cc b/src/sim/clock_domain.cc index 8f45bba09..60c688b1a 100644 --- a/src/sim/clock_domain.cc +++ b/src/sim/clock_domain.cc @@ -156,16 +156,16 @@ SrcClockDomain::perfLevel(PerfLevel perf_level) } void -SrcClockDomain::serialize(std::ostream &os) +SrcClockDomain::serialize(CheckpointOut &cp) const { SERIALIZE_SCALAR(_perfLevel); - ClockDomain::serialize(os); + ClockDomain::serialize(cp); } void -SrcClockDomain::unserialize(Checkpoint *cp, const std::string §ion) +SrcClockDomain::unserialize(CheckpointIn &cp) { - ClockDomain::unserialize(cp, section); + ClockDomain::unserialize(cp); UNSERIALIZE_SCALAR(_perfLevel); } diff --git a/src/sim/clock_domain.hh b/src/sim/clock_domain.hh index edf2340ad..c4242af55 100644 --- a/src/sim/clock_domain.hh +++ b/src/sim/clock_domain.hh @@ -238,8 +238,9 @@ class SrcClockDomain : public ClockDomain } void startup(); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; private: /** diff --git a/src/sim/cxx_manager.cc b/src/sim/cxx_manager.cc index 7f6a03398..6d4565dbc 100644 --- a/src/sim/cxx_manager.cc +++ b/src/sim/cxx_manager.cc @@ -671,7 +671,7 @@ CxxConfigManager::serialize(std::ostream &os) } void -CxxConfigManager::loadState(Checkpoint *checkpoint) +CxxConfigManager::loadState(CheckpointIn &checkpoint) { for (auto i = objectsInOrder.begin(); i != objectsInOrder.end(); ++ i) (*i)->loadState(checkpoint); diff --git a/src/sim/cxx_manager.hh b/src/sim/cxx_manager.hh index caa115f03..b2ba31214 100644 --- a/src/sim/cxx_manager.hh +++ b/src/sim/cxx_manager.hh @@ -61,7 +61,7 @@ #include "base/cprintf.hh" #include "sim/cxx_config.hh" -class Checkpoint; +class CheckpointIn; /** This class allows a config file to be read into gem5 (generating the * appropriate SimObjects) from C++ */ @@ -292,7 +292,7 @@ class CxxConfigManager void serialize(std::ostream &os); /** Load all objects' state from the given Checkpoint */ - void loadState(Checkpoint *checkpoint); + void loadState(CheckpointIn &checkpoint); /** Delete all objects and clear objectsByName and objectsByOrder */ void deleteObjects(); diff --git a/src/sim/dvfs_handler.cc b/src/sim/dvfs_handler.cc index f4fe760a2..f507897b3 100644 --- a/src/sim/dvfs_handler.cc +++ b/src/sim/dvfs_handler.cc @@ -170,7 +170,7 @@ DVFSHandler::UpdateEvent::updatePerfLevel() } void -DVFSHandler::serialize(std::ostream &os) +DVFSHandler::serialize(CheckpointOut &cp) const { //This is to ensure that the handler status is maintained during the //entire simulation run and not changed from command line during checkpoint @@ -182,23 +182,22 @@ DVFSHandler::serialize(std::ostream &os) std::vector domain_ids; std::vector perf_levels; std::vector whens; - for (auto it = updatePerfLevelEvents.begin(); - it != updatePerfLevelEvents.end(); ++it) { - DomainID id = it->first; - UpdateEvent *event = &it->second; + for (const auto &ev_pair : updatePerfLevelEvents) { + DomainID id = ev_pair.first; + const UpdateEvent *event = &ev_pair.second; assert(id == event->domainIDToSet); domain_ids.push_back(id); perf_levels.push_back(event->perfLevelToSet); whens.push_back(event->scheduled() ? event->when() : 0); } - arrayParamOut(os, "domain_ids", domain_ids); - arrayParamOut(os, "perf_levels", perf_levels); - arrayParamOut(os, "whens", whens); + SERIALIZE_CONTAINER(domain_ids); + SERIALIZE_CONTAINER(perf_levels); + SERIALIZE_CONTAINER(whens); } void -DVFSHandler::unserialize(Checkpoint *cp, const std::string §ion) +DVFSHandler::unserialize(CheckpointIn &cp) { bool temp = enableHandler; @@ -213,9 +212,9 @@ DVFSHandler::unserialize(Checkpoint *cp, const std::string §ion) std::vector domain_ids; std::vector perf_levels; std::vector whens; - arrayParamIn(cp, section, "domain_ids", domain_ids); - arrayParamIn(cp, section, "perf_levels", perf_levels); - arrayParamIn(cp, section, "whens", whens); + UNSERIALIZE_CONTAINER(domain_ids); + UNSERIALIZE_CONTAINER(perf_levels); + UNSERIALIZE_CONTAINER(whens); for (size_t i = 0; i < domain_ids.size(); ++i) {; UpdateEvent *event = &updatePerfLevelEvents[domain_ids[i]]; diff --git a/src/sim/dvfs_handler.hh b/src/sim/dvfs_handler.hh index a8b78d08b..6e495fff5 100644 --- a/src/sim/dvfs_handler.hh +++ b/src/sim/dvfs_handler.hh @@ -198,8 +198,8 @@ class DVFSHandler : public SimObject */ bool isEnabled() const { return enableHandler; } - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; private: typedef std::map Domains; diff --git a/src/sim/eventq.cc b/src/sim/eventq.cc index 4fde79656..f75ada47c 100644 --- a/src/sim/eventq.cc +++ b/src/sim/eventq.cc @@ -242,7 +242,7 @@ EventQueue::serviceOne() } void -Event::serialize(std::ostream &os) +Event::serialize(CheckpointOut &cp) const { SERIALIZE_SCALAR(_when); SERIALIZE_SCALAR(_priority); @@ -251,12 +251,12 @@ Event::serialize(std::ostream &os) } void -Event::unserialize(Checkpoint *cp, const string §ion) +Event::unserialize(CheckpointIn &cp) { } void -Event::unserialize(Checkpoint *cp, const string §ion, EventQueue *eventq) +Event::unserializeEvent(CheckpointIn &cp, EventQueue *eventq) { if (scheduled()) eventq->deschedule(this); @@ -290,7 +290,7 @@ Event::unserialize(Checkpoint *cp, const string §ion, EventQueue *eventq) } void -EventQueue::serialize(ostream &os) +EventQueue::serialize(CheckpointOut &cp) const { std::list eventPtrs; @@ -302,7 +302,7 @@ EventQueue::serialize(ostream &os) while (nextInBin) { if (nextInBin->flags.isSet(Event::AutoSerialize)) { eventPtrs.push_back(nextInBin); - paramOut(os, csprintf("event%d", numEvents++), + paramOut(cp, csprintf("event%d", numEvents++), nextInBin->name()); } nextInBin = nextInBin->nextInBin; @@ -313,15 +313,12 @@ EventQueue::serialize(ostream &os) SERIALIZE_SCALAR(numEvents); - for (std::list::iterator it = eventPtrs.begin(); - it != eventPtrs.end(); ++it) { - (*it)->nameOut(os); - (*it)->serialize(os); - } + for (Event *ev : eventPtrs) + ev->serializeSection(cp, ev->name()); } void -EventQueue::unserialize(Checkpoint *cp, const std::string §ion) +EventQueue::unserialize(CheckpointIn &cp) { int numEvents; UNSERIALIZE_SCALAR(numEvents); @@ -329,7 +326,7 @@ EventQueue::unserialize(Checkpoint *cp, const std::string §ion) std::string eventName; for (int i = 0; i < numEvents; i++) { // get the pointer value associated with the event - paramIn(cp, section, csprintf("event%d", i), eventName); + paramIn(cp, csprintf("event%d", i), eventName); // create the event based on its pointer value Serializable::create(cp, eventName); diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index f726a6dbd..b90e5d382 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -350,15 +350,14 @@ class Event : public EventBase, public Serializable virtual BaseGlobalEvent *globalEvent() { return NULL; } #ifndef SWIG - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; //! This function is required to support restoring from checkpoints //! when running with multiple queues. Since we still have not thrashed //! out all the details on checkpointing, this function is most likely //! to be revisited in future. - virtual void unserialize(Checkpoint *cp, const std::string §ion, - EventQueue *eventq); + virtual void unserializeEvent(CheckpointIn &cp, EventQueue *eventq); #endif }; @@ -647,8 +646,8 @@ class EventQueue : public Serializable /**@}*/ #ifndef SWIG - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; #endif virtual ~EventQueue() { } diff --git a/src/sim/process.cc b/src/sim/process.cc index 35f981d1e..a820b0632 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -259,6 +259,13 @@ Process::initState() pTable->initState(tc); } +unsigned int +Process::drain(DrainManager *dm) +{ + find_file_offsets(); + return 0; +} + // map simulator fd sim_fd to target fd tgt_fd void Process::dup_fd(int sim_fd, int tgt_fd) @@ -488,7 +495,7 @@ Process::setReadPipeSource(int read_pipe_fd, int source_fd) } void -Process::FdMap::serialize(std::ostream &os) +Process::FdMap::serialize(CheckpointOut &cp) const { SERIALIZE_SCALAR(fd); SERIALIZE_SCALAR(isPipe); @@ -499,7 +506,7 @@ Process::FdMap::serialize(std::ostream &os) } void -Process::FdMap::unserialize(Checkpoint *cp, const std::string §ion) +Process::FdMap::unserialize(CheckpointIn &cp) { UNSERIALIZE_SCALAR(fd); UNSERIALIZE_SCALAR(isPipe); @@ -510,7 +517,7 @@ Process::FdMap::unserialize(Checkpoint *cp, const std::string §ion) } void -Process::serialize(std::ostream &os) +Process::serialize(CheckpointOut &cp) const { SERIALIZE_SCALAR(brk_point); SERIALIZE_SCALAR(stack_base); @@ -521,18 +528,16 @@ Process::serialize(std::ostream &os) SERIALIZE_SCALAR(mmap_end); SERIALIZE_SCALAR(nxm_start); SERIALIZE_SCALAR(nxm_end); - find_file_offsets(); - pTable->serialize(os); + pTable->serialize(cp); for (int x = 0; x <= MAX_FD; x++) { - nameOut(os, csprintf("%s.FdMap%d", name(), x)); - fd_map[x].serialize(os); + fd_map[x].serializeSection(cp, csprintf("FdMap%d", x)); } SERIALIZE_SCALAR(M5_pid); } void -Process::unserialize(Checkpoint *cp, const std::string §ion) +Process::unserialize(CheckpointIn &cp) { UNSERIALIZE_SCALAR(brk_point); UNSERIALIZE_SCALAR(stack_base); @@ -543,9 +548,9 @@ Process::unserialize(Checkpoint *cp, const std::string §ion) UNSERIALIZE_SCALAR(mmap_end); UNSERIALIZE_SCALAR(nxm_start); UNSERIALIZE_SCALAR(nxm_end); - pTable->unserialize(cp, section); + pTable->unserialize(cp); for (int x = 0; x <= MAX_FD; x++) { - fd_map[x].unserialize(cp, csprintf("%s.FdMap%d", section, x)); + fd_map[x].unserializeSection(cp, csprintf("FdMap%d", x)); } fix_file_offsets(); UNSERIALIZE_OPT_SCALAR(M5_pid); diff --git a/src/sim/process.hh b/src/sim/process.hh index 04ce00f67..c1499ccf7 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -120,6 +120,8 @@ class Process : public SimObject virtual void initState(); + unsigned int drain(DrainManager *dm) M5_ATTR_OVERRIDE; + public: //This id is assigned by m5 and is used to keep process' tlb entries @@ -133,7 +135,7 @@ class Process : public SimObject PageTableBase* pTable; - class FdMap + class FdMap : public Serializable { public: int fd; @@ -150,8 +152,8 @@ class Process : public SimObject isPipe(false), readPipeSource(0), fileOffset(0), driver(NULL) { } - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; }; protected: @@ -233,8 +235,8 @@ class Process : public SimObject */ bool map(Addr vaddr, Addr paddr, int size, bool cacheable = true); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; }; // diff --git a/src/sim/root.cc b/src/sim/root.cc index 9bb8b4f05..1d58c3bbe 100644 --- a/src/sim/root.cc +++ b/src/sim/root.cc @@ -123,14 +123,14 @@ Root::initState() } void -Root::loadState(Checkpoint *cp) +Root::loadState(CheckpointIn &cp) { SimObject::loadState(cp); timeSyncEnable(params()->time_sync_enable); } void -Root::serialize(std::ostream &os) +Root::serialize(CheckpointOut &cp) const { uint64_t cpt_ver = gem5CheckpointVersion; SERIALIZE_SCALAR(cpt_ver); @@ -140,7 +140,7 @@ Root::serialize(std::ostream &os) } void -Root::unserialize(Checkpoint *cp, const std::string §ion) +Root::unserialize(CheckpointIn &cp) { uint64_t cpt_ver = 0; UNSERIALIZE_OPT_SCALAR(cpt_ver); diff --git a/src/sim/root.hh b/src/sim/root.hh index 6a7b5dc93..1c330e2c4 100644 --- a/src/sim/root.hh +++ b/src/sim/root.hh @@ -106,15 +106,14 @@ class Root : public SimObject /** Schedule the timesync event at loadState() so that curTick is correct */ - void loadState(Checkpoint *cp); + void loadState(CheckpointIn &cp) M5_ATTR_OVERRIDE; /** Schedule the timesync event at initState() when not unserializing */ void initState(); - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; }; #endif // __SIM_ROOT_HH__ diff --git a/src/sim/serialize.cc b/src/sim/serialize.cc index 99426b5a6..a7c1834cf 100644 --- a/src/sim/serialize.cc +++ b/src/sim/serialize.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2015 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * Copyright (c) 2013 Advanced Micro Devices, Inc. * Copyright (c) 2013 Mark D. Hill and David A. Wood @@ -30,6 +42,7 @@ * Authors: Nathan Binkert * Erik Hallnor * Steve Reinhardt + * Andreas Sandberg */ #include @@ -47,6 +60,7 @@ #include "base/output.hh" #include "base/str.hh" #include "base/trace.hh" +#include "debug/Checkpoint.hh" #include "sim/eventq.hh" #include "sim/serialize.hh" #include "sim/sim_events.hh" @@ -71,7 +85,7 @@ parseParam(const string &s, T &value) template void -showParam(ostream &os, const T &value) +showParam(CheckpointOut &os, const T &value) { os << value; } @@ -87,7 +101,7 @@ showParam(ostream &os, const T &value) // Treat 8-bit ints (chars) as ints on output, not as chars template <> void -showParam(ostream &os, const char &value) +showParam(CheckpointOut &os, const char &value) { os << (int)value; } @@ -95,7 +109,7 @@ showParam(ostream &os, const char &value) template <> void -showParam(ostream &os, const signed char &value) +showParam(CheckpointOut &os, const signed char &value) { os << (int)value; } @@ -103,7 +117,7 @@ showParam(ostream &os, const signed char &value) template <> void -showParam(ostream &os, const unsigned char &value) +showParam(CheckpointOut &os, const unsigned char &value) { os << (unsigned int)value; } @@ -133,7 +147,7 @@ parseParam(const string &s, bool &value) // Display bools as strings template <> void -showParam(ostream &os, const bool &value) +showParam(CheckpointOut &os, const bool &value) { os << (value ? "true" : "false"); } @@ -151,22 +165,11 @@ parseParam(const string &s, string &value) int Serializable::ckptMaxCount = 0; int Serializable::ckptCount = 0; int Serializable::ckptPrevCount = -1; - -void -Serializable::nameOut(ostream &os) -{ - os << "\n[" << name() << "]\n"; -} - -void -Serializable::nameOut(ostream &os, const string &_name) -{ - os << "\n[" << _name << "]\n"; -} +std::stack Serializable::path; template void -paramOut(ostream &os, const string &name, const T ¶m) +paramOut(CheckpointOut &os, const string &name, const T ¶m) { os << name << "="; showParam(os, param); @@ -175,7 +178,7 @@ paramOut(ostream &os, const string &name, const T ¶m) template void -arrayParamOut(ostream &os, const string &name, const vector ¶m) +arrayParamOut(CheckpointOut &os, const string &name, const vector ¶m) { typename vector::size_type size = param.size(); os << name << "="; @@ -190,7 +193,7 @@ arrayParamOut(ostream &os, const string &name, const vector ¶m) template void -arrayParamOut(ostream &os, const string &name, const list ¶m) +arrayParamOut(CheckpointOut &os, const string &name, const list ¶m) { typename list::const_iterator it = param.begin(); @@ -208,20 +211,22 @@ arrayParamOut(ostream &os, const string &name, const list ¶m) template void -paramIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) +paramIn(CheckpointIn &cp, const string &name, T ¶m) { + const string §ion(Serializable::currentSection()); string str; - if (!cp->find(section, name, str) || !parseParam(str, param)) { + if (!cp.find(section, name, str) || !parseParam(str, param)) { fatal("Can't unserialize '%s:%s'\n", section, name); } } template bool -optParamIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) +optParamIn(CheckpointIn &cp, const string &name, T ¶m) { + const string §ion(Serializable::currentSection()); string str; - if (!cp->find(section, name, str) || !parseParam(str, param)) { + if (!cp.find(section, name, str) || !parseParam(str, param)) { warn("optional parameter %s:%s not present\n", section, name); return false; } else { @@ -231,7 +236,8 @@ optParamIn(Checkpoint *cp, const string §ion, const string &name, T ¶m) template void -arrayParamOut(ostream &os, const string &name, const T *param, unsigned size) +arrayParamOut(CheckpointOut &os, const string &name, + const T *param, unsigned size) { os << name << "="; if (size > 0) @@ -246,11 +252,11 @@ arrayParamOut(ostream &os, const string &name, const T *param, unsigned size) template void -arrayParamIn(Checkpoint *cp, const string §ion, const string &name, - T *param, unsigned size) +arrayParamIn(CheckpointIn &cp, const string &name, T *param, unsigned size) { + const string §ion(Serializable::currentSection()); string str; - if (!cp->find(section, name, str)) { + if (!cp.find(section, name, str)) { fatal("Can't unserialize '%s:%s'\n", section, name); } @@ -273,7 +279,7 @@ arrayParamIn(Checkpoint *cp, const string §ion, const string &name, // for which operator[] returns a special reference class // that's not the same as 'bool&', (since it's a packed // vector) - T scalar_value = 0; + T scalar_value; if (!parseParam(tokens[i], scalar_value)) { string err("could not parse \""); @@ -290,11 +296,11 @@ arrayParamIn(Checkpoint *cp, const string §ion, const string &name, template void -arrayParamIn(Checkpoint *cp, const string §ion, - const string &name, vector ¶m) +arrayParamIn(CheckpointIn &cp, const string &name, vector ¶m) { + const string §ion(Serializable::currentSection()); string str; - if (!cp->find(section, name, str)) { + if (!cp.find(section, name, str)) { fatal("Can't unserialize '%s:%s'\n", section, name); } @@ -315,7 +321,7 @@ arrayParamIn(Checkpoint *cp, const string §ion, // for which operator[] returns a special reference class // that's not the same as 'bool&', (since it's a packed // vector) - T scalar_value = 0; + T scalar_value; if (!parseParam(tokens[i], scalar_value)) { string err("could not parse \""); @@ -332,11 +338,11 @@ arrayParamIn(Checkpoint *cp, const string §ion, template void -arrayParamIn(Checkpoint *cp, const string §ion, - const string &name, list ¶m) +arrayParamIn(CheckpointIn &cp, const string &name, list ¶m) { + const string §ion(Serializable::currentSection()); string str; - if (!cp->find(section, name, str)) { + if (!cp.find(section, name, str)) { fatal("Can't unserialize '%s:%s'\n", section, name); } param.clear(); @@ -345,7 +351,7 @@ arrayParamIn(Checkpoint *cp, const string §ion, tokenize(tokens, str, ' '); for (vector::size_type i = 0; i < tokens.size(); i++) { - T scalar_value = 0; + T scalar_value; if (!parseParam(tokens[i], scalar_value)) { string err("could not parse \""); @@ -362,42 +368,40 @@ arrayParamIn(Checkpoint *cp, const string §ion, void -objParamIn(Checkpoint *cp, const string §ion, - const string &name, SimObject * ¶m) +objParamIn(CheckpointIn &cp, const string &name, SimObject * ¶m) { - if (!cp->findObj(section, name, param)) { + 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(ostream &os, const string &name, type const ¶m); \ -template void \ -paramIn(Checkpoint *cp, const string §ion, \ - const string &name, type & param); \ -template bool \ -optParamIn(Checkpoint *cp, const string §ion, \ - const string &name, type & param); \ -template void \ -arrayParamOut(ostream &os, const string &name, \ - type const *param, unsigned size); \ -template void \ -arrayParamIn(Checkpoint *cp, const string §ion, \ - const string &name, type *param, unsigned size); \ -template void \ -arrayParamOut(ostream &os, const string &name, \ - const vector ¶m); \ -template void \ -arrayParamIn(Checkpoint *cp, const string §ion, \ - const string &name, vector ¶m); \ -template void \ -arrayParamOut(ostream &os, const string &name, \ - const list ¶m); \ -template void \ -arrayParamIn(Checkpoint *cp, const string §ion, \ - const string &name, list ¶m); + 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); \ + 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) @@ -423,45 +427,31 @@ INSTANTIATE_PARAM_TEMPLATES(string) class Globals : public Serializable { public: - const string name() const; - void serialize(ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + Globals() + : unserializedCurTick(0) {} + + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; + + Tick unserializedCurTick; }; /// The one and only instance of the Globals class. Globals globals; -const string -Globals::name() const -{ - return "Globals"; -} - void -Globals::serialize(ostream &os) +Globals::serialize(CheckpointOut &cp) const { - nameOut(os); - paramOut(os, "curTick", curTick()); + paramOut(cp, "curTick", curTick()); + paramOut(cp, "numMainEventQueues", numMainEventQueues); - paramOut(os, "numMainEventQueues", numMainEventQueues); - - for (uint32_t i = 0; i < numMainEventQueues; ++i) { - nameOut(os, "MainEventQueue"); - mainEventQueue[i]->serialize(os); - } } void -Globals::unserialize(Checkpoint *cp, const std::string §ion) +Globals::unserialize(CheckpointIn &cp) { - Tick tick; - paramIn(cp, section, "curTick", tick); - paramIn(cp, section, "numMainEventQueues", numMainEventQueues); - - for (uint32_t i = 0; i < numMainEventQueues; ++i) { - mainEventQueue[i]->setCurTick(tick); - mainEventQueue[i]->unserialize(cp, "MainEventQueue"); - } + paramIn(cp, "curTick", unserializedCurTick); + paramIn(cp, "numMainEventQueues", numMainEventQueues); } Serializable::Serializable() @@ -473,37 +463,82 @@ Serializable::~Serializable() } void -Serializable::serialize(ostream &os) +Serializable::serializeSection(CheckpointOut &cp, const char *name) const { + Serializable::ScopedCheckpointSection sec(cp, name); + serialize(cp); } void -Serializable::unserialize(Checkpoint *cp, const string §ion) +Serializable::serializeSectionOld(CheckpointOut &cp, const char *name) { + Serializable::ScopedCheckpointSection sec(cp, name); + serializeOld(cp); +} + +void +Serializable::unserializeSection(CheckpointIn &cp, const char *name) +{ + Serializable::ScopedCheckpointSection sec(cp, name); + unserialize(cp); } void Serializable::serializeAll(const string &cpt_dir) { - string dir = Checkpoint::setDir(cpt_dir); + string dir = CheckpointIn::setDir(cpt_dir); if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) fatal("couldn't mkdir %s\n", dir); - string cpt_file = dir + Checkpoint::baseFilename; + string cpt_file = dir + CheckpointIn::baseFilename; ofstream outstream(cpt_file.c_str()); time_t t = time(NULL); if (!outstream.is_open()) fatal("Unable to open file %s for writing\n", cpt_file.c_str()); outstream << "## checkpoint generated: " << ctime(&t); - globals.serialize(outstream); + globals.serializeSection(outstream, "Globals"); + for (uint32_t i = 0; i < numMainEventQueues; ++i) + mainEventQueue[i]->serializeSection(outstream, "MainEventQueue"); + SimObject::serializeAll(outstream); } void -Serializable::unserializeGlobals(Checkpoint *cp) +Serializable::unserializeGlobals(CheckpointIn &cp) +{ + globals.unserializeSection(cp, "Globals"); + + for (uint32_t i = 0; i < numMainEventQueues; ++i) { + mainEventQueue[i]->setCurTick(globals.unserializedCurTick); + mainEventQueue[i]->unserializeSection(cp, "MainEventQueue"); + } +} + +Serializable::ScopedCheckpointSection::~ScopedCheckpointSection() +{ + assert(!path.empty()); + DPRINTF(Checkpoint, "Popping: %s\n", path.top()); + path.pop(); +} + +void +Serializable::ScopedCheckpointSection::pushName(const char *obj_name) { - globals.unserialize(cp, globals.name()); + if (path.empty()) { + path.push(obj_name); + } else { + path.push(csprintf("%s.%s", path.top(), obj_name)); + } + DPRINTF(Checkpoint, "ScopedCheckpointSection::pushName: %s\n", obj_name); +} + +void +Serializable::ScopedCheckpointSection::nameOut(CheckpointOut &cp) +{ + DPRINTF(Checkpoint, "ScopedCheckpointSection::nameOut: %s\n", + Serializable::currentSection()); + cp << "\n[" << Serializable::currentSection() << "]\n"; } void @@ -542,11 +577,11 @@ SerializableClass::SerializableClass(const string &className, // // Serializable * -SerializableClass::createObject(Checkpoint *cp, const string §ion) +SerializableClass::createObject(CheckpointIn &cp, const string §ion) { string className; - if (!cp->find(section, "type", className)) { + if (!cp.find(section, "type", className)) { fatal("Serializable::create: no 'type' entry in section '%s'.\n", section); } @@ -565,22 +600,29 @@ SerializableClass::createObject(Checkpoint *cp, const string §ion) return object; } +const std::string & +Serializable::currentSection() +{ + assert(!path.empty()); + + return path.top(); +} Serializable * -Serializable::create(Checkpoint *cp, const string §ion) +Serializable::create(CheckpointIn &cp, const string §ion) { Serializable *object = SerializableClass::createObject(cp, section); - object->unserialize(cp, section); + object->unserializeSection(cp, section); return object; } -const char *Checkpoint::baseFilename = "m5.cpt"; +const char *CheckpointIn::baseFilename = "m5.cpt"; -string Checkpoint::currentDirectory; +string CheckpointIn::currentDirectory; string -Checkpoint::setDir(const string &name) +CheckpointIn::setDir(const string &name) { // use csprintf to insert curTick() into directory name if it // appears to have a format placeholder in it. @@ -592,35 +634,35 @@ Checkpoint::setDir(const string &name) } string -Checkpoint::dir() +CheckpointIn::dir() { return currentDirectory; } -Checkpoint::Checkpoint(const string &cpt_dir, SimObjectResolver &resolver) +CheckpointIn::CheckpointIn(const string &cpt_dir, SimObjectResolver &resolver) : db(new IniFile), objNameResolver(resolver), cptDir(setDir(cpt_dir)) { - string filename = cptDir + "/" + Checkpoint::baseFilename; + string filename = cptDir + "/" + CheckpointIn::baseFilename; if (!db->load(filename)) { fatal("Can't load checkpoint file '%s'\n", filename); } } -Checkpoint::~Checkpoint() +CheckpointIn::~CheckpointIn() { delete db; } bool -Checkpoint::find(const string §ion, const string &entry, string &value) +CheckpointIn::find(const string §ion, const string &entry, string &value) { return db->find(section, entry, value); } bool -Checkpoint::findObj(const string §ion, const string &entry, +CheckpointIn::findObj(const string §ion, const string &entry, SimObject *&value) { string path; @@ -634,7 +676,7 @@ Checkpoint::findObj(const string §ion, const string &entry, bool -Checkpoint::sectionExists(const string §ion) +CheckpointIn::sectionExists(const string §ion) { return db->sectionExists(section); } diff --git a/src/sim/serialize.hh b/src/sim/serialize.hh index 2fb7cddd0..644ef4005 100644 --- a/src/sim/serialize.hh +++ b/src/sim/serialize.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2015 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2002-2005 The Regents of The University of Michigan * All rights reserved. * @@ -28,6 +40,7 @@ * Authors: Nathan Binkert * Erik Hallnor * Steve Reinhardt + * Andreas Sandberg */ /* @file @@ -41,6 +54,7 @@ #include #include #include +#include #include #include "base/bitunion.hh" @@ -48,10 +62,13 @@ class IniFile; class Serializable; -class Checkpoint; +class CheckpointIn; class SimObject; class EventQueue; +typedef std::ostream CheckpointOut; + + /** 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 @@ -62,66 +79,61 @@ class EventQueue; static const uint64_t gem5CheckpointVersion = 0x000000000000000e; template -void paramOut(std::ostream &os, const std::string &name, const T ¶m); +void paramOut(CheckpointOut &cp, const std::string &name, const T ¶m); template -void paramOut(std::ostream &os, const std::string &name, +void paramOut(CheckpointOut &cp, const std::string &name, const BitfieldBackend::BitUnionOperators &p) { - paramOut(os, name, p.__data); + paramOut(cp, name, p.__data); } template -void paramIn(Checkpoint *cp, const std::string §ion, - const std::string &name, T ¶m); +void paramIn(CheckpointIn &cp, const std::string &name, T ¶m); template -void paramIn(Checkpoint *cp, const std::string §ion, - const std::string &name, +void paramIn(CheckpointIn &cp, const std::string &name, BitfieldBackend::BitUnionOperators &p) { - paramIn(cp, section, name, p.__data); + paramIn(cp, name, p.__data); } template -bool optParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, T ¶m); +bool optParamIn(CheckpointIn &cp, const std::string &name, T ¶m); template -bool optParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, +bool optParamIn(CheckpointIn &cp, const std::string &name, BitfieldBackend::BitUnionOperators &p) { - return optParamIn(cp, section, name, p.__data); + return optParamIn(cp, name, p.__data); } template -void arrayParamOut(std::ostream &os, const std::string &name, +void arrayParamOut(CheckpointOut &cp, const std::string &name, const T *param, unsigned size); template -void arrayParamOut(std::ostream &os, const std::string &name, +void arrayParamOut(CheckpointOut &cp, const std::string &name, const std::vector ¶m); template -void arrayParamOut(std::ostream &os, const std::string &name, +void arrayParamOut(CheckpointOut &cp, const std::string &name, const std::list ¶m); template -void arrayParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, T *param, unsigned size); +void arrayParamIn(CheckpointIn &cp, const std::string &name, + T *param, unsigned size); template -void arrayParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, std::vector ¶m); +void arrayParamIn(CheckpointIn &cp, const std::string &name, + std::vector ¶m); template -void arrayParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, std::list ¶m); +void arrayParamIn(CheckpointIn &cp, const std::string &name, + std::list ¶m); void -objParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, SimObject * ¶m); +objParamIn(CheckpointIn &cp, const std::string &name, SimObject * ¶m); template void fromInt(T &t, int i) @@ -139,45 +151,66 @@ void fromSimObject(T &t, SimObject *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 SERIALIZE_SCALAR(scalar) paramOut(cp, #scalar, scalar) -#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #scalar, scalar) -#define UNSERIALIZE_OPT_SCALAR(scalar) optParamIn(cp, section, #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(os, #scalar, (int)scalar) +#define SERIALIZE_ENUM(scalar) paramOut(cp, #scalar, (int)scalar) #define UNSERIALIZE_ENUM(scalar) \ do { \ int tmp; \ - paramIn(cp, section, #scalar, tmp); \ - fromInt(scalar, tmp); \ + paramIn(cp, #scalar, tmp); \ + fromInt(scalar, tmp); \ } while (0) #define SERIALIZE_ARRAY(member, size) \ - arrayParamOut(os, #member, member, size) + arrayParamOut(cp, #member, member, size) #define UNSERIALIZE_ARRAY(member, size) \ - arrayParamIn(cp, section, #member, member, size) + arrayParamIn(cp, #member, member, size) #define SERIALIZE_CONTAINER(member) \ - arrayParamOut(os, #member, member) + arrayParamOut(cp, #member, member) #define UNSERIALIZE_CONTAINER(member) \ - arrayParamIn(cp, section, #member, member) + arrayParamIn(cp, #member, member) -#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name()) +#define SERIALIZE_OBJPTR(objptr) paramOut(cp, #objptr, (objptr)->name()) #define UNSERIALIZE_OBJPTR(objptr) \ do { \ SimObject *sptr; \ - objParamIn(cp, section, #objptr, sptr); \ + objParamIn(cp, #objptr, sptr); \ fromSimObject(objptr, sptr); \ } while (0) /** * Basic support for object serialization. * + * Objects that support serialization should derive from this + * class. Such objects can largely be divided into two categories: 1) + * True SimObjects (deriving from SimObject), and 2) child objects + * (non-SimObjects). + * + * SimObjects are serialized automatically into their own sections + * automatically by the SimObject base class (see + * SimObject::serializeAll(). + * + * SimObjects can contain other serializable objects that are not + * SimObjects. Much like normal serialized members are not serialized + * automatically, these objects will not be serialized automatically + * and it is expected that the objects owning such serializable + * objects call the required serialization/unserialization methods on + * child objects. The preferred method to serialize a child object is + * to call serializeSection() on the child, which serializes the + * object into a new subsection in the current section. Another option + * is to call serialize() directly, which serializes the object into + * the current section. The latter is not recommended as it can lead + * to naming clashes between objects. + * * @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 @@ -187,26 +220,146 @@ void fromSimObject(T &t, SimObject *s) class Serializable { protected: - void nameOut(std::ostream &os); - void nameOut(std::ostream &os, const std::string &_name); + /** + * Scoped checkpoint section helper class + * + * This helper class creates a section within a checkpoint without + * the need for a separate serializeable object. It is mainly used + * within the Serializable class when serializing or unserializing + * section (see serializeSection() and unserializeSection()). It + * can also be used to maintain backwards compatibility in + * existing code that serializes structs that are not inheriting + * from Serializable into subsections. + * + * When the class is instantiated, it appends a name to the active + * path in a checkpoint. The old path is later restored when the + * instance is destroyed. For example, serializeSection() could be + * implemented by instantiating a ScopedCheckpointSection and then + * calling serialize() on an object. + */ + class ScopedCheckpointSection { + public: + template + ScopedCheckpointSection(CP &cp, const char *name) { + pushName(name); + nameOut(cp); + } + + template + ScopedCheckpointSection(CP &cp, const std::string &name) { + pushName(name.c_str()); + nameOut(cp); + } + + ~ScopedCheckpointSection(); + + ScopedCheckpointSection() = delete; + ScopedCheckpointSection(const ScopedCheckpointSection &) = delete; + ScopedCheckpointSection &operator=( + const ScopedCheckpointSection &) = delete; + ScopedCheckpointSection &operator=( + ScopedCheckpointSection &&) = delete; + + private: + void pushName(const char *name); + void nameOut(CheckpointOut &cp); + void nameOut(CheckpointIn &cp) {}; + }; 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); + /** + * Serialize an object + * + * Output an object's state into the current checkpoint section. + * + * @param cp Checkpoint state + */ + virtual void serialize(CheckpointOut &cp) const = 0; + + /** + * Unserialize an object + * + * Read an object's state from the current checkpoint section. + * + * @param cp Checkpoint state + */ + virtual void unserialize(CheckpointIn &cp) = 0; + + /** + * Serialize an object into a new section + * + * This method creates a new section in a checkpoint and calls + * serialize() to serialize the current object into that + * section. The name of the section is appended to the current + * checkpoint path. + * + * @param cp Checkpoint state + * @param name Name to append to the active path + */ + void serializeSection(CheckpointOut &cp, const char *name) const; + + void serializeSection(CheckpointOut &cp, const std::string &name) const { + serializeSection(cp, name.c_str()); + } + + /** + * Unserialize an a child object + * + * This method loads a child object from a checkpoint. The object + * name is appended to the active path to form a fully qualified + * section name and unserialize() is called. + * + * @param cp Checkpoint state + * @param name Name to append to the active path + */ + void unserializeSection(CheckpointIn &cp, const char *name); + + void unserializeSection(CheckpointIn &cp, const std::string &name) { + unserializeSection(cp, name.c_str()); + } + + /** + * @{ + * @name Legacy interface + * + * Interface for objects that insist on changing their state when + * serializing. Such state change should be done in drain(), + * memWriteback(), or memInvalidate() and not in the serialization + * method. In general, if state changes occur in serialize, it + * complicates testing since it breaks assumptions about draining + * and serialization. It potentially also makes components more + * fragile since they there are no ordering guarantees when + * serializing SimObjects. + * + * @warn This interface is considered deprecated and should never + * be used. + */ + + virtual void serializeOld(CheckpointOut &cp) { + serialize(cp); + } + void serializeSectionOld(CheckpointOut &cp, const char *name); + void serializeSectionOld(CheckpointOut &cp, const std::string &name) { + serializeSectionOld(cp, name.c_str()); + } + /** @} */ + + /** Get the fully-qualified name of the active section */ + static const std::string ¤tSection(); + + static Serializable *create(CheckpointIn &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); + static void unserializeGlobals(CheckpointIn &cp); + + private: + static std::stack path; }; void debug_serialize(const std::string &cpt_dir); @@ -258,7 +411,7 @@ class SerializableClass // 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, + typedef Serializable *(*CreateFunc)(CheckpointIn &cp, const std::string §ion); static std::map *classMap; @@ -272,7 +425,7 @@ class SerializableClass // create Serializable given name of class and pointer to // configuration hierarchy node - static Serializable *createObject(Checkpoint *cp, + static Serializable *createObject(CheckpointIn &cp, const std::string §ion); }; @@ -297,7 +450,7 @@ class SimObjectResolver virtual SimObject *resolveSimObject(const std::string &name) = 0; }; -class Checkpoint +class CheckpointIn { private: @@ -306,8 +459,8 @@ class Checkpoint SimObjectResolver &objNameResolver; public: - Checkpoint(const std::string &cpt_dir, SimObjectResolver &resolver); - ~Checkpoint(); + CheckpointIn(const std::string &cpt_dir, SimObjectResolver &resolver); + ~CheckpointIn(); const std::string cptDir; diff --git a/src/sim/sim_events.cc b/src/sim/sim_events.cc index 5e47adca1..719a732ab 100644 --- a/src/sim/sim_events.cc +++ b/src/sim/sim_events.cc @@ -117,10 +117,10 @@ LocalSimLoopExitEvent::description() const } void -LocalSimLoopExitEvent::serialize(ostream &os) +LocalSimLoopExitEvent::serialize(CheckpointOut &cp) const { - paramOut(os, "type", string("SimLoopExitEvent")); - Event::serialize(os); + paramOut(cp, "type", string("SimLoopExitEvent")); + Event::serialize(cp); SERIALIZE_SCALAR(cause); SERIALIZE_SCALAR(code); @@ -128,9 +128,9 @@ LocalSimLoopExitEvent::serialize(ostream &os) } void -LocalSimLoopExitEvent::unserialize(Checkpoint *cp, const string §ion) +LocalSimLoopExitEvent::unserialize(CheckpointIn &cp) { - Event::unserialize(cp, section); + Event::unserialize(cp); UNSERIALIZE_SCALAR(cause); UNSERIALIZE_SCALAR(code); @@ -138,10 +138,9 @@ LocalSimLoopExitEvent::unserialize(Checkpoint *cp, const string §ion) } void -LocalSimLoopExitEvent::unserialize(Checkpoint *cp, const string §ion, - EventQueue *eventq) +LocalSimLoopExitEvent::unserializeEvent(CheckpointIn &cp, EventQueue *eventq) { - Event::unserialize(cp, section, eventq); + Event::unserializeEvent(cp, eventq); UNSERIALIZE_SCALAR(cause); UNSERIALIZE_SCALAR(code); @@ -149,7 +148,7 @@ LocalSimLoopExitEvent::unserialize(Checkpoint *cp, const string §ion, } Serializable * -LocalSimLoopExitEvent::createForUnserialize(Checkpoint *cp, +LocalSimLoopExitEvent::createForUnserialize(CheckpointIn &cp, const string §ion) { return new LocalSimLoopExitEvent(); diff --git a/src/sim/sim_events.hh b/src/sim/sim_events.hh index 5be2609fd..8d5d5da7b 100644 --- a/src/sim/sim_events.hh +++ b/src/sim/sim_events.hh @@ -93,11 +93,11 @@ class LocalSimLoopExitEvent : public Event virtual const char *description() const; - virtual void serialize(std::ostream &os); - virtual void unserialize(Checkpoint *cp, const std::string §ion); - virtual void unserialize(Checkpoint *cp, const std::string §ion, - EventQueue *eventq); - static Serializable *createForUnserialize(Checkpoint *cp, + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; + void unserializeEvent(CheckpointIn &cp, + EventQueue *eventq) M5_ATTR_OVERRIDE; + static Serializable *createForUnserialize(CheckpointIn &cp, const std::string §ion); }; diff --git a/src/sim/sim_object.cc b/src/sim/sim_object.cc index a7be4ebd2..2c4ba48f6 100644 --- a/src/sim/sim_object.cc +++ b/src/sim/sim_object.cc @@ -81,11 +81,13 @@ SimObject::init() } void -SimObject::loadState(Checkpoint *cp) +SimObject::loadState(CheckpointIn &cp) { - if (cp->sectionExists(name())) { + if (cp.sectionExists(name())) { DPRINTF(Checkpoint, "unserializing\n"); - unserialize(cp, name()); + // This works despite name() returning a fully qualified name + // since we are at the top level. + unserializeSection(cp, name()); } else { DPRINTF(Checkpoint, "no checkpoint section found\n"); } @@ -140,15 +142,16 @@ SimObject::getProbeManager() // static function: serialize all SimObjects. // void -SimObject::serializeAll(std::ostream &os) +SimObject::serializeAll(CheckpointOut &cp) { SimObjectList::reverse_iterator ri = simObjectList.rbegin(); SimObjectList::reverse_iterator rend = simObjectList.rend(); for (; ri != rend; ++ri) { SimObject *obj = *ri; - obj->nameOut(os); - obj->serialize(os); + // This works despite name() returning a fully qualified name + // since we are at the top level. + obj->serializeSectionOld(cp, obj->name()); } } diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index 9bf95d07f..16237d051 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -126,7 +126,7 @@ class SimObject : public EventManager, public Serializable, public Drainable * * @param cp Checkpoint to restore the state from. */ - virtual void loadState(Checkpoint *cp); + virtual void loadState(CheckpointIn &cp); /** * initState() is called on each SimObject when *not* restoring @@ -175,10 +175,14 @@ class SimObject : public EventManager, public Serializable, public Drainable */ unsigned int drain(DrainManager *drainManger); + + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE {}; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE {}; + /** * Serialize all SimObjects in the system. */ - static void serializeAll(std::ostream &os); + static void serializeAll(CheckpointOut &cp); #ifdef DEBUG public: diff --git a/src/sim/system.cc b/src/sim/system.cc index 2f2427769..f781377f7 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -370,31 +370,30 @@ System::drainResume() } void -System::serialize(ostream &os) +System::serialize(CheckpointOut &cp) const { if (FullSystem) - kernelSymtab->serialize("kernel_symtab", os); + kernelSymtab->serialize("kernel_symtab", cp); SERIALIZE_SCALAR(pagePtr); SERIALIZE_SCALAR(nextPID); - serializeSymtab(os); + serializeSymtab(cp); // also serialize the memories in the system - nameOut(os, csprintf("%s.physmem", name())); - physmem.serialize(os); + physmem.serializeSection(cp, "physmem"); } void -System::unserialize(Checkpoint *cp, const string §ion) +System::unserialize(CheckpointIn &cp) { if (FullSystem) - kernelSymtab->unserialize("kernel_symtab", cp, section); + kernelSymtab->unserialize("kernel_symtab", cp); UNSERIALIZE_SCALAR(pagePtr); UNSERIALIZE_SCALAR(nextPID); - unserializeSymtab(cp, section); + unserializeSymtab(cp); // also unserialize the memories in the system - physmem.unserialize(cp, csprintf("%s.physmem", name())); + physmem.unserializeSection(cp, "physmem"); } void diff --git a/src/sim/system.hh b/src/sim/system.hh index 9ec349a47..b8114d0ca 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -517,8 +517,8 @@ class System : public MemObject int registerThreadContext(ThreadContext *tc, int assigned=-1); void replaceThreadContext(ThreadContext *tc, int context_id); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; unsigned int drain(DrainManager *dm); void drainResume(); @@ -552,7 +552,7 @@ class System : public MemObject * * @param os stream to serialize to */ - virtual void serializeSymtab(std::ostream &os) {} + virtual void serializeSymtab(CheckpointOut &os) const {} /** * If needed, unserialize additional symbol table entries for a @@ -561,8 +561,7 @@ class System : public MemObject * @param cp checkpoint to unserialize from * @param section relevant section in the checkpoint */ - virtual void unserializeSymtab(Checkpoint *cp, - const std::string §ion) {} + virtual void unserializeSymtab(CheckpointIn &cp) {} }; diff --git a/src/sim/ticked_object.cc b/src/sim/ticked_object.cc index ef6ee1c20..ecdb87827 100644 --- a/src/sim/ticked_object.cc +++ b/src/sim/ticked_object.cc @@ -72,15 +72,15 @@ Ticked::regStats() } void -Ticked::serialize(std::ostream &os) +Ticked::serialize(CheckpointOut &cp) const { uint64_t lastStoppedUint = lastStopped; - paramOut(os, "lastStopped", lastStoppedUint); + paramOut(cp, "lastStopped", lastStoppedUint); } void -Ticked::unserialize(Checkpoint *cp, const std::string §ion) +Ticked::unserialize(CheckpointIn &cp) { uint64_t lastStoppedUint = 0; @@ -90,7 +90,7 @@ Ticked::unserialize(Checkpoint *cp, const std::string §ion) * checkpointed object but not this one. * An example would be a CPU model using Ticked restores from a * simple CPU without without Ticked */ - optParamIn(cp, section, "lastStopped", lastStoppedUint); + optParamIn(cp, "lastStopped", lastStoppedUint); lastStopped = Cycles(lastStoppedUint); } @@ -109,14 +109,14 @@ TickedObject::regStats() } void -TickedObject::serialize(std::ostream &os) +TickedObject::serialize(CheckpointOut &cp) const { - Ticked::serialize(os); - ClockedObject::serialize(os); + Ticked::serialize(cp); + ClockedObject::serialize(cp); } void -TickedObject::unserialize(Checkpoint *cp, const std::string §ion) +TickedObject::unserialize(CheckpointIn &cp) { - Ticked::unserialize(cp, section); - ClockedObject::unserialize(cp, section); + Ticked::unserialize(cp); + ClockedObject::unserialize(cp); } diff --git a/src/sim/ticked_object.hh b/src/sim/ticked_object.hh index ee143e0df..97750873f 100644 --- a/src/sim/ticked_object.hh +++ b/src/sim/ticked_object.hh @@ -56,7 +56,7 @@ * * Ticked is not a ClockedObject but can be attached to one by * inheritance and by calling regStats, serialize/unserialize */ -class Ticked +class Ticked : public Serializable { protected: /** An event to call process periodically */ @@ -164,8 +164,8 @@ class Ticked } /** Checkpoint lastStopped */ - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; /** Action to call on the clock tick */ virtual void evaluate() = 0; @@ -199,8 +199,8 @@ class TickedObject : public ClockedObject, public Ticked /** Pass on regStats, serialize etc. onto Ticked */ void regStats(); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; }; #endif /* __SIM_TICKED_OBJECT_HH__ */ diff --git a/src/sim/voltage_domain.cc b/src/sim/voltage_domain.cc index 2b16d04b9..b82efda33 100644 --- a/src/sim/voltage_domain.cc +++ b/src/sim/voltage_domain.cc @@ -142,12 +142,14 @@ VoltageDomainParams::create() } void -VoltageDomain::serialize(std::ostream &os) { +VoltageDomain::serialize(CheckpointOut &cp) const +{ SERIALIZE_SCALAR(_perfLevel); } void -VoltageDomain::unserialize(Checkpoint *cp, const std::string §ion) { +VoltageDomain::unserialize(CheckpointIn &cp) +{ UNSERIALIZE_SCALAR(_perfLevel); perfLevel(_perfLevel); } diff --git a/src/sim/voltage_domain.hh b/src/sim/voltage_domain.hh index ab96abad8..596daba40 100644 --- a/src/sim/voltage_domain.hh +++ b/src/sim/voltage_domain.hh @@ -128,8 +128,9 @@ class VoltageDomain : public SimObject void regStats(); - void serialize(std::ostream &os); - void unserialize(Checkpoint *cp, const std::string §ion); + void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE; + void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE; + private: typedef std::vector Voltages; /** -- cgit v1.2.3