From 777c1ebfab0318d4b98834b0f2ef48a2de16b8dd Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Thu, 11 Dec 2003 00:16:46 -0800 Subject: [PATCH] Stats & serialization tweaks & cleanup. Unserializing from a checkpoint now gives identical results to running from scratch and doing at switchover at the same cycle! - CPUs start at cycle 0 again, not cycle 1. - curTick is now serialized & unserialized. - Stats get reset in main (before event loop). Since this is done after curTick is unserialized, simTicks gets set correctly for running from a checkpoint. - Simplify serialization to happen in a single pass. - s/Serializeable/Serializable/ arch/alpha/isa_traits.hh: dev/etherlink.hh: sim/eventq.cc: sim/eventq.hh: s/Serializeable/Serializable/ kern/tru64/tru64_system.cc: sim/process.cc: Make initial CPU activation on cycle 0 again (not 1). sim/main.cc: Reset stats before getting started. Make error message on falling out of event loop more meaningful. sim/serialize.cc: sim/serialize.hh: Get rid of now-useless initial pass; serialization is done in a single pass now. Serialize & unserialize curTick. Wrap curTick and mainEventQueue in a "globals" Serializable object. s/Serializeable/Serializable/ sim/sim_object.cc: Add static function to serialize all SimObjects. sim/sim_object.hh: Add static function to serialize all SimObjects. s/Serializeable/Serializable/ --HG-- extra : convert_revision : 9dcc411d0009b54b8eb61c3a509680b81b9f6f68 --- arch/alpha/isa_traits.hh | 2 +- dev/etherlink.hh | 2 +- kern/tru64/tru64_system.cc | 4 +- sim/eventq.cc | 2 +- sim/eventq.hh | 4 +- sim/main.cc | 5 +- sim/process.cc | 6 +- sim/serialize.cc | 153 ++++++++++++++----------------------- sim/serialize.hh | 95 +++++++++-------------- sim/sim_object.cc | 16 ++++ sim/sim_object.hh | 5 +- 11 files changed, 127 insertions(+), 167 deletions(-) diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index 406ffb6f3..ecca91d43 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -225,7 +225,7 @@ class AlphaISA int regnum); #if 0 - static void serializeSpecialRegs(const Serializeable::Proxy &proxy, + static void serializeSpecialRegs(const Serializable::Proxy &proxy, const RegFile ®s); static void unserializeSpecialRegs(const IniFile *db, diff --git a/dev/etherlink.hh b/dev/etherlink.hh index ea7bdcbcc..ef587faf7 100644 --- a/dev/etherlink.hh +++ b/dev/etherlink.hh @@ -52,7 +52,7 @@ class EtherLink : public SimObject /* * Model for a single uni-directional link */ - class Link : public Serializeable { + class Link : public Serializable { protected: std::string objName; diff --git a/kern/tru64/tru64_system.cc b/kern/tru64/tru64_system.cc index 6fe5fb81b..99d99afd4 100644 --- a/kern/tru64/tru64_system.cc +++ b/kern/tru64/tru64_system.cc @@ -566,7 +566,9 @@ Tru64System::registerExecContext(ExecContext *xc) int xcIndex = System::registerExecContext(xc); if (xcIndex == 0) { - xc->activate(); + // activate with zero delay so that we start ticking right + // away on cycle 0 + xc->activate(0); } RemoteGDB *rgdb = new RemoteGDB(this, xc); diff --git a/sim/eventq.cc b/sim/eventq.cc index 52f7dfaff..a0aac4fee 100644 --- a/sim/eventq.cc +++ b/sim/eventq.cc @@ -184,7 +184,7 @@ EventQueue::unserialize(Checkpoint *cp, const std::string §ion) paramIn(cp, section, csprintf("event%d", i), eventName); // create the event based on its pointer value - Serializeable::create(cp, eventName); + Serializable::create(cp, eventName); } } diff --git a/sim/eventq.hh b/sim/eventq.hh index 475c4face..dc1b2d9af 100644 --- a/sim/eventq.hh +++ b/sim/eventq.hh @@ -53,7 +53,7 @@ class EventQueue; // forward declaration * event is specified by deriving a subclass and overriding the * process() member function. */ -class Event : public Serializeable, public FastAlloc +class Event : public Serializable, public FastAlloc { friend class EventQueue; @@ -204,7 +204,7 @@ DelayFunction(Tick when, T *object) /* * Queue of events sorted in time order */ -class EventQueue : public Serializeable +class EventQueue : public Serializable { protected: std::string objName; diff --git a/sim/main.cc b/sim/main.cc index f697aebce..287b3d6e6 100644 --- a/sim/main.cc +++ b/sim/main.cc @@ -389,6 +389,9 @@ main(int argc, char **argv) // Check to make sure that the stats package is properly initialized Statistics::check(); + // Reset to put the stats in a consistent state. + Statistics::reset(); + // Nothing to simulate if we don't have at least one CPU somewhere. if (BaseCPU::numSimulatedCPUs() == 0) { cerr << "Fatal: no CPUs to simulate." << endl; @@ -437,7 +440,7 @@ main(int argc, char **argv) // simulation to terminate (hit max cycles/insts, signal, // simulated system halts/exits) generates an exit event, so we // should never run out of events on the queue. - exitNow("improperly exited event loop!", 1); + exitNow("no events on event loop! All CPUs must be idle.", 1); return 0; } diff --git a/sim/process.cc b/sim/process.cc index 0d7c3403d..c5eee4527 100644 --- a/sim/process.cc +++ b/sim/process.cc @@ -148,8 +148,10 @@ Process::registerExecContext(ExecContext *xc) // copy process's initial regs struct xc->regs = *init_regs; - // mark this context as active - xc->activate(); + // mark this context as active. + // activate with zero delay so that we start ticking right + // away on cycle 0 + xc->activate(0); } // return CPU number to caller and increment available CPU count diff --git a/sim/serialize.cc b/sim/serialize.cc index 9738029c2..82d295384 100644 --- a/sim/serialize.cc +++ b/sim/serialize.cc @@ -48,25 +48,14 @@ using namespace std; -Serializer *Serializeable::serializer = NULL; - -void -Serializeable::mark() -{ - if (!serialized) - serializer->add_object(this); - - serialized = true; -} - void -Serializeable::nameOut(ostream &os) +Serializable::nameOut(ostream &os) { os << "\n[" << name() << "]\n"; } void -Serializeable::nameOut(ostream &os, const string &_name) +Serializable::nameOut(ostream &os, const string &_name) { os << "\n[" << _name << "]\n"; } @@ -156,7 +145,7 @@ arrayParamIn(Checkpoint *cp, const std::string §ion, void objParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, Serializeable * ¶m) + const std::string &name, Serializable * ¶m) { if (!cp->findObj(section, name, param)) { fatal("Can't unserialize '%s:%s'\n", section, name); @@ -190,94 +179,70 @@ INSTANTIATE_PARAM_TEMPLATES(bool) INSTANTIATE_PARAM_TEMPLATES(string) -#if 0 -// unneeded? -void -Serializeable::childOut(const string &name, Serializeable *child) -{ - child->mark(); - if (child->name() == "") - panic("child is unnamed"); +///////////////////////////// - out() << name << "=" << child->name() << "\n"; -} -#endif - -Serializer::Serializer() -{ } +/// Container for serializing global variables (not associated with +/// any serialized object). +class Globals : public Serializable +{ + public: + string name() const; + void serialize(ostream& os); + void unserialize(Checkpoint *cp); +}; -Serializer::~Serializer() -{ } +/// The one and only instance of the Globals class. +Globals globals; -ostream & -Serializer::out() const +string +Globals::name() const { - if (!output) - panic("must set output before serializing"); - - return *output; + return "Globals"; } void -Serializer::add_object(Serializeable *obj) +Globals::serialize(ostream& os) { - objects.push_back(obj); + nameOut(os); + SERIALIZE_SCALAR(curTick); + + nameOut(os, "MainEventQueue"); + mainEventQueue.serialize(os); } void -Serializer::add_objects() +Globals::unserialize(Checkpoint *cp) { - mainEventQueue.mark(); - - SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin(); - SimObject::SimObjectList::iterator end = SimObject::simObjectList.end(); + const string §ion = name(); + UNSERIALIZE_SCALAR(curTick); - while (i != end) { - (*i)->mark(); - ++i; - } + mainEventQueue.unserialize(cp, "MainEventQueue"); } void -Serializer::serialize() +Serializable::serializeAll() { - if (Serializeable::serializer != NULL) - panic("in process of serializing!"); - - Serializeable::serializer = this; - string dir = CheckpointDir(); if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST) warn("could mkdir %s\n", dir); string cpt_file = dir + "m5.cpt"; - output = new ofstream(cpt_file.c_str()); + ofstream outstream(cpt_file.c_str()); time_t t = time(NULL); - *output << "// checkpoint generated: " << ctime(&t); - - serlist_t list; - - add_objects(); - while (!objects.empty()) { - Serializeable *obj = objects.front(); - DPRINTF(Serialize, "Serializing %s\n", obj->name()); - obj->nameOut(out()); - obj->serialize(out()); - objects.pop_front(); - list.push_back(obj); - } + outstream << "// checkpoint generated: " << ctime(&t); - while (!list.empty()) { - list.front()->serialized = false; - list.pop_front(); - } + globals.serialize(outstream); + SimObject::serializeAll(outstream); +} - Serializeable::serializer = NULL; - delete output; - output = NULL; +void +Serializable::unserializeGlobals(Checkpoint *cp) +{ + globals.unserialize(cp); } + class SerializeEvent : public Event { protected: @@ -303,8 +268,7 @@ SerializeEvent::SerializeEvent(Tick _when, Tick _repeat) void SerializeEvent::process() { - Serializer serial; - serial.serialize(); + Serializable::serializeAll(); if (repeat) schedule(curTick + repeat); } @@ -374,8 +338,7 @@ SerializeParamContext::checkParams() void debug_serialize() { - Serializer serial; - serial.serialize(); + Serializable::serializeAll(); } void @@ -386,22 +349,22 @@ debug_serialize(Tick when) //////////////////////////////////////////////////////////////////////// // -// SerializeableClass member definitions +// SerializableClass member definitions // //////////////////////////////////////////////////////////////////////// -// Map of class names to SerializeableBuilder creation functions. +// Map of class names to SerializableBuilder creation functions. // Need to make this a pointer so we can force initialization on the -// first reference; otherwise, some SerializeableClass constructors +// first reference; otherwise, some SerializableClass constructors // may be invoked before the classMap constructor. -map *SerializeableClass::classMap = 0; +map *SerializableClass::classMap = 0; -// SerializeableClass constructor: add mapping to classMap -SerializeableClass::SerializeableClass(const string &className, +// SerializableClass constructor: add mapping to classMap +SerializableClass::SerializableClass(const string &className, CreateFunc createFunc) { if (classMap == NULL) - classMap = new map(); + classMap = new map(); if ((*classMap)[className]) { @@ -417,25 +380,25 @@ SerializeableClass::SerializeableClass(const string &className, // // -Serializeable * -SerializeableClass::createObject(Checkpoint *cp, +Serializable * +SerializableClass::createObject(Checkpoint *cp, const std::string §ion) { string className; if (!cp->find(section, "type", className)) { - fatal("Serializeable::create: no 'type' entry in section '%s'.\n", + fatal("Serializable::create: no 'type' entry in section '%s'.\n", section); } CreateFunc createFunc = (*classMap)[className]; if (createFunc == NULL) { - fatal("Serializeable::create: no create function for class '%s'.\n", + fatal("Serializable::create: no create function for class '%s'.\n", className); } - Serializeable *object = createFunc(cp, section); + Serializable *object = createFunc(cp, section); assert(object != NULL); @@ -443,10 +406,10 @@ SerializeableClass::createObject(Checkpoint *cp, } -Serializeable * -Serializeable::create(Checkpoint *cp, const std::string §ion) +Serializable * +Serializable::create(Checkpoint *cp, const std::string §ion) { - Serializeable *object = SerializeableClass::createObject(cp, section); + Serializable *object = SerializableClass::createObject(cp, section); object->unserialize(cp, section); return object; } @@ -459,8 +422,6 @@ Checkpoint::Checkpoint(const std::string &filename, const std::string &path, if (!db->load(filename)) { fatal("Can't load checkpoint file '%s'\n", filename); } - - mainEventQueue.unserialize(this, "MainEventQueue"); } @@ -474,7 +435,7 @@ Checkpoint::find(const std::string §ion, const std::string &entry, bool Checkpoint::findObj(const std::string §ion, const std::string &entry, - Serializeable *&value) + Serializable *&value) { string path; diff --git a/sim/serialize.hh b/sim/serialize.hh index 077931d8c..60e06f94b 100644 --- a/sim/serialize.hh +++ b/sim/serialize.hh @@ -41,7 +41,7 @@ #include "sim/host.hh" #include "sim/configfile.hh" -class Serializeable; +class Serializable; class Checkpoint; template @@ -61,7 +61,7 @@ void arrayParamIn(Checkpoint *cp, const std::string §ion, void objParamIn(Checkpoint *cp, const std::string §ion, - const std::string &name, Serializeable * ¶m); + const std::string &name, Serializable * ¶m); // @@ -92,7 +92,7 @@ objParamIn(Checkpoint *cp, const std::string §ion, #define UNSERIALIZE_OBJPTR(objptr) \ do { \ - Serializeable *sptr; \ + Serializable *sptr; \ objParamIn(cp, section, #objptr, sptr); \ objptr = dynamic_cast(sptr); \ } while (0) @@ -100,23 +100,15 @@ objParamIn(Checkpoint *cp, const std::string §ion, /* * Basic support for object serialization. */ -class Serializeable +class Serializable { - public: - - friend class Serializer; - protected: - bool serialized; - static Serializer *serializer; - - void mark(); void nameOut(std::ostream& os); void nameOut(std::ostream& os, const std::string &_name); public: - Serializeable() : serialized(false) {} - virtual ~Serializeable() {} + Serializable() {} + virtual ~Serializable() {} // manditory virtual function, so objects must provide names virtual std::string name() const = 0; @@ -124,70 +116,51 @@ class Serializeable virtual void serialize(std::ostream& os) {} virtual void unserialize(Checkpoint *cp, const std::string §ion) {} - static Serializeable *create(Checkpoint *cp, + static Serializable *create(Checkpoint *cp, const std::string §ion); -}; - -class Serializer -{ - friend class Serializeable; - protected: - typedef std::list serlist_t; - serlist_t objects; - std::ostream *output; - std::ostream &out() const; - - public: - Serializer(); - virtual ~Serializer(); - - private: - void add_object(Serializeable *obj); - void add_objects(); - - public: - void serialize(); + static void serializeAll(); + static void unserializeGlobals(Checkpoint *cp); }; // -// A SerializeableBuilder serves as an evaluation context for a set of -// parameters that describe a specific instance of a Serializeable. This +// A SerializableBuilder serves as an evaluation context for a set of +// parameters that describe a specific instance of a Serializable. This // evaluation context corresponds to a section in the .ini file (as // with the base ParamContext) plus an optional node in the // configuration hierarchy (the configNode member) for resolving -// Serializeable references. SerializeableBuilder is an abstract superclass; +// Serializable references. SerializableBuilder is an abstract superclass; // derived classes specialize the class for particular subclasses of -// Serializeable (e.g., BaseCache). +// Serializable (e.g., BaseCache). // // For typical usage, see the definition of -// SerializeableClass::createObject(). +// SerializableClass::createObject(). // -class SerializeableBuilder +class SerializableBuilder { public: - SerializeableBuilder() {} + SerializableBuilder() {} - virtual ~SerializeableBuilder() {} + virtual ~SerializableBuilder() {} - // Create the actual Serializeable corresponding to the parameter + // Create the actual Serializable corresponding to the parameter // values in this context. This function is overridden in derived // classes to call a specific constructor for a particular - // subclass of Serializeable. - virtual Serializeable *create() = 0; + // subclass of Serializable. + virtual Serializable *create() = 0; }; // -// An instance of SerializeableClass corresponds to a class derived from -// Serializeable. The SerializeableClass instance serves to bind the string +// An instance of SerializableClass corresponds to a class derived from +// Serializable. The SerializableClass instance serves to bind the string // name (found in the config file) to a function that creates an // instance of the appropriate derived class. // // This would be much cleaner in Smalltalk or Objective-C, where types // are first-class objects themselves. // -class SerializeableClass +class SerializableClass { public: @@ -196,32 +169,32 @@ class SerializeableClass // section (specified by the first string argument), a unique name // 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 SerializeableBuilder is returned. - typedef Serializeable *(*CreateFunc)(Checkpoint *cp, + // argument). A pointer to the new SerializableBuilder is returned. + typedef Serializable *(*CreateFunc)(Checkpoint *cp, const std::string §ion); static std::map *classMap; // Constructor. For example: // - // SerializeableClass baseCacheSerializeableClass("BaseCacheSerializeable", - // newBaseCacheSerializeableBuilder); + // SerializableClass baseCacheSerializableClass("BaseCacheSerializable", + // newBaseCacheSerializableBuilder); // - SerializeableClass(const std::string &className, CreateFunc createFunc); + SerializableClass(const std::string &className, CreateFunc createFunc); - // create Serializeable given name of class and pointer to + // create Serializable given name of class and pointer to // configuration hierarchy node - static Serializeable *createObject(Checkpoint *cp, + static Serializable *createObject(Checkpoint *cp, const std::string §ion); }; // // Macros to encapsulate the magic of declaring & defining -// SerializeableBuilder and SerializeableClass objects +// SerializableBuilder and SerializableClass objects // #define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \ -SerializeableClass the##OBJ_CLASS##Class(CLASS_NAME, \ +SerializableClass the##OBJ_CLASS##Class(CLASS_NAME, \ OBJ_CLASS::createForUnserialize); class Checkpoint @@ -231,7 +204,7 @@ class Checkpoint IniFile *db; const std::string basePath; const ConfigNode *configNode; - std::map objMap; + std::map objMap; public: Checkpoint(const std::string &filename, const std::string &path, @@ -241,7 +214,7 @@ class Checkpoint std::string &value); bool findObj(const std::string §ion, const std::string &entry, - Serializeable *&value); + Serializable *&value); bool sectionExists(const std::string §ion); }; diff --git a/sim/sim_object.cc b/sim/sim_object.cc index 90ad78648..364dbe035 100644 --- a/sim/sim_object.cc +++ b/sim/sim_object.cc @@ -155,3 +155,19 @@ SimObject::printAllExtraOutput(ostream &os) obj->printExtraOutput(os); } } + +// +// static function: serialize all SimObjects. +// +void +SimObject::serializeAll(ostream &os) +{ + SimObjectList::iterator i = simObjectList.begin(); + SimObjectList::iterator end = simObjectList.end(); + + for (; i != end; ++i) { + SimObject *obj = *i; + obj->nameOut(os); + obj->serialize(os); + } +} diff --git a/sim/sim_object.hh b/sim/sim_object.hh index 6b26a1cb0..937ff9427 100644 --- a/sim/sim_object.hh +++ b/sim/sim_object.hh @@ -45,7 +45,7 @@ * correspond to physical components and can be specified via the * config file (CPUs, caches, etc.). */ -class SimObject : public Serializeable +class SimObject : public Serializable { protected: std::string objName; @@ -82,6 +82,9 @@ class SimObject : public Serializeable // static: call printExtraOutput on all SimObjects static void printAllExtraOutput(std::ostream&); + + // static: call nameOut() & serialize() on all SimObjects + static void serializeAll(std::ostream &); }; #endif // __SIM_OBJECT_HH__ -- 2.30.2