From: Steve Reinhardt Date: Thu, 30 Oct 2003 05:45:39 +0000 (-0800) Subject: Support for Serializable non-SimObject things like events. X-Git-Tag: m5_1.0_beta2~324^2 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5a1eb9049d16d37448282362529d462d73558181;p=gem5.git Support for Serializable non-SimObject things like events. Can now serialize & unserialize DmaRequestEvents and DmaTransferEvents. Also support serialize/unserialize of pointers to SimObjects and other Serializable objects. arch/alpha/alpha_memory.cc: arch/alpha/alpha_memory.hh: arch/alpha/isa_traits.hh: cpu/exec_context.cc: cpu/exec_context.hh: cpu/simple_cpu/simple_cpu.hh: dev/alpha_access.h: dev/alpha_console.cc: dev/alpha_console.hh: dev/console.cc: dev/console.hh: unserialize() now takes a Checkpoint* instead of an IniFile*. cpu/simple_cpu/simple_cpu.cc: unserialize() now takes a Checkpoint* instead of an IniFile*. Put ExecContext in its own section so its _status fields doesn't conflict. sim/eventq.cc: sim/eventq.hh: unserialize() now takes a Checkpoint* instead of an IniFile*. Events get serialized by the event queue only if they're marked as AutoSerialize... others are assumed to be serialized by something else (e.g. an owning SimObject) or to not matter. sim/param.cc: Shift 'const' in case T is a ptr type. sim/serialize.cc: sim/serialize.hh: Define Checkpoint object to encapsulate everything you need to know about a checkpoint. Use it to allow lookups of named Serializable objects (and SimObjects) during unserialization. unserialize() now takes a Checkpoint* instead of an IniFile*. --HG-- extra : convert_revision : 8e6baab32405f8f548bb67a097b2f713296537a5 --- diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index 7c0b1120f..c79b821d0 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -204,13 +204,13 @@ AlphaTlb::serialize(ostream &os) } void -AlphaTlb::unserialize(const IniFile *db, const string §ion) +AlphaTlb::unserialize(Checkpoint *cp, const string §ion) { UNSERIALIZE_SCALAR(size); UNSERIALIZE_SCALAR(nlu); for (int i = 0; i < size; i++) { - table[i].unserialize(db, csprintf("%s.PTE%d", section, i)); + table[i].unserialize(cp, csprintf("%s.PTE%d", section, i)); if (table[i].valid) { lookupTable.insert(make_pair(table[i].tag, i)); } diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh index fc4d46191..bfcd313e2 100644 --- a/arch/alpha/alpha_memory.hh +++ b/arch/alpha/alpha_memory.hh @@ -74,7 +74,7 @@ class AlphaTlb : public SimObject // Checkpointing virtual void serialize(std::ostream &os); - virtual void unserialize(const IniFile *db, const std::string §ion); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; class AlphaItb : public AlphaTlb diff --git a/arch/alpha/isa_traits.hh b/arch/alpha/isa_traits.hh index fbdcffbcf..406ffb6f3 100644 --- a/arch/alpha/isa_traits.hh +++ b/arch/alpha/isa_traits.hh @@ -34,7 +34,7 @@ #include "base/misc.hh" class FullCPU; -class IniFile; +class Checkpoint; #define TARGET_ALPHA @@ -160,7 +160,7 @@ class AlphaISA uint8_t opcode, ra; // current instruction details (for intr's) void serialize(std::ostream &os); - void unserialize(const IniFile *db, const std::string §ion); + void unserialize(Checkpoint *cp, const std::string §ion); }; static StaticInstPtr decodeInst(MachInst); diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc index b869a8c4d..195c9daad 100644 --- a/cpu/exec_context.cc +++ b/cpu/exec_context.cc @@ -108,10 +108,10 @@ ExecContext::serialize(ostream &os) void -ExecContext::unserialize(const IniFile *db, const std::string §ion) +ExecContext::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_ENUM(_status); - regs.unserialize(db, section); + regs.unserialize(cp, section); // thread_num and cpu_id are deterministic from the config UNSERIALIZE_SCALAR(func_exe_insn); } diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index 6938b369f..cb826a15e 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -142,7 +142,7 @@ class ExecContext void regStats(const std::string &name); void serialize(std::ostream &os); - void unserialize(const IniFile *db, const std::string §ion); + void unserialize(Checkpoint *cp, const std::string §ion); #ifdef FULL_SYSTEM bool validInstAddr(Addr addr) { return true; } diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 3179b7b1f..519a8cd4d 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -262,6 +262,7 @@ SimpleCPU::serialize(ostream &os) { SERIALIZE_ENUM(_status); SERIALIZE_SCALAR(inst); + nameOut(os, csprintf("%s.xc", name())); xc->serialize(os); nameOut(os, csprintf("%s.tickEvent", name())); tickEvent.serialize(os); @@ -270,14 +271,14 @@ SimpleCPU::serialize(ostream &os) } void -SimpleCPU::unserialize(const IniFile *db, const string §ion) +SimpleCPU::unserialize(Checkpoint *cp, const string §ion) { UNSERIALIZE_ENUM(_status); UNSERIALIZE_SCALAR(inst); - xc->unserialize(db, section); - tickEvent.unserialize(db, csprintf("%s.tickEvent", name())); + xc->unserialize(cp, csprintf("%s.xc", section)); + tickEvent.unserialize(cp, csprintf("%s.tickEvent", section)); cacheCompletionEvent - .unserialize(db, csprintf("%s.cacheCompletionEvent", name())); + .unserialize(cp, csprintf("%s.cacheCompletionEvent", section)); } void diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 61831cb3c..61c9143ba 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -49,7 +49,7 @@ class GDBListener; #endif // FULL_SYSTEM class MemInterface; -class IniFile; +class Checkpoint; namespace Trace { class InstRecord; @@ -259,7 +259,7 @@ class SimpleCPU : public BaseCPU void processCacheCompletion(); virtual void serialize(std::ostream &os); - virtual void unserialize(const IniFile *db, const std::string §ion); + virtual void unserialize(Checkpoint *cp, const std::string §ion); template Fault read(Addr addr, T& data, unsigned flags); diff --git a/dev/alpha_access.h b/dev/alpha_access.h index c145fa2a3..eb551a359 100644 --- a/dev/alpha_access.h +++ b/dev/alpha_access.h @@ -44,7 +44,7 @@ typedef uint64_t UINT64; #include #include -class IniFile; +class Checkpoint; #endif @@ -82,7 +82,7 @@ struct AlphaAccess #ifndef CONSOLE void serialize(std::ostream &os); - void unserialize(const IniFile *db, const std::string §ion); + void unserialize(Checkpoint *cp, const std::string §ion); #endif }; diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index 969b1e4c3..6fe57edb5 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -188,7 +188,7 @@ AlphaAccess::serialize(ostream &os) } void -AlphaAccess::unserialize(const IniFile *db, const std::string §ion) +AlphaAccess::unserialize(Checkpoint *cp, const std::string §ion) { UNSERIALIZE_SCALAR(last_offset); UNSERIALIZE_SCALAR(version); @@ -216,9 +216,9 @@ AlphaConsole::serialize(ostream &os) } void -AlphaConsole::unserialize(const IniFile *db, const std::string §ion) +AlphaConsole::unserialize(Checkpoint *cp, const std::string §ion) { - alphaAccess->unserialize(db, section); + alphaAccess->unserialize(cp, section); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh index e4aeb2417..9e774773e 100644 --- a/dev/alpha_console.hh +++ b/dev/alpha_console.hh @@ -101,7 +101,7 @@ class AlphaConsole : public MmapDevice * standard serialization routines for checkpointing */ virtual void serialize(std::ostream &os); - virtual void unserialize(const IniFile *db, const std::string §ion); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; #endif // __ALPHA_CONSOLE_HH__ diff --git a/dev/console.cc b/dev/console.cc index 749add532..2378f8c75 100644 --- a/dev/console.cc +++ b/dev/console.cc @@ -319,7 +319,7 @@ SimConsole::serialize(ostream &os) } void -SimConsole::unserialize(const IniFile *db, const std::string §ion) +SimConsole::unserialize(Checkpoint *cp, const std::string §ion) { } diff --git a/dev/console.hh b/dev/console.hh index 6746f90b6..fd02e7a9a 100644 --- a/dev/console.hh +++ b/dev/console.hh @@ -129,7 +129,7 @@ class SimConsole : public SimObject void setInt(int bits); virtual void serialize(std::ostream &os); - virtual void unserialize(const IniFile *db, const std::string §ion); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; class ConsoleListener : public SimObject diff --git a/sim/eventq.cc b/sim/eventq.cc index 77eb490c7..ef813eb13 100644 --- a/sim/eventq.cc +++ b/sim/eventq.cc @@ -129,7 +129,7 @@ Event::serialize(std::ostream &os) void -Event::unserialize(const IniFile *db, const string §ion) +Event::unserialize(Checkpoint *cp, const string §ion) { if (scheduled()) deschedule(); @@ -154,39 +154,51 @@ Event::unserialize(const IniFile *db, const string §ion) void EventQueue::nameChildren() { -#if 0 - int j = 0; - + int numEvents = 0; Event *event = head; while (event) { - stringstream stream; - ccprintf(stream, "%s.event%d", name(), j++); - event->setName(stream.str()); - + if (event->getFlags(Event::AutoSerialize)) { + event->setName(csprintf("%s.event%d", name(), numEvents++)); + } event = event->next; } -#endif + + numAutoSerializeEvents = numEvents; } void EventQueue::serialize(ostream &os) { -#if 0 - string objects = ""; + // should have been set by a preceding call to nameChildren() + assert(numAutoSerializeEvents >= 0); + SERIALIZE_SCALAR(numAutoSerializeEvents); + + int numEvents = 0; Event *event = head; while (event) { - objects += event->name(); - objects += " "; - event->serialize(os); - + if (event->getFlags(Event::AutoSerialize)) { + event->nameOut(os); + event->serialize(os); + numEvents++; + } event = event->next; } - nameOut(os, "Serialized"); - SERIALIZE_SCALAR(objects); -#endif + + assert(numEvents == numAutoSerializeEvents); +} + + +void +EventQueue::unserialize(Checkpoint *cp, const std::string §ion) +{ + UNSERIALIZE_SCALAR(numAutoSerializeEvents); + for (int eventNum = 0; eventNum < numAutoSerializeEvents; ++eventNum) { + Serializeable::create(cp, csprintf("%s.event%d", section, eventNum)); + } } + void EventQueue::dump() { diff --git a/sim/eventq.hh b/sim/eventq.hh index a8eae1248..11bfe3a4e 100644 --- a/sim/eventq.hh +++ b/sim/eventq.hh @@ -73,7 +73,8 @@ class Event : public Serializeable, public FastAlloc None = 0x0, Squashed = 0x1, Scheduled = 0x2, - AutoDelete = 0x4 + AutoDelete = 0x4, + AutoSerialize = 0x8 }; bool getFlags(Flags f) const { return (_flags & f) == f; } @@ -190,7 +191,7 @@ class Event : public Serializeable, public FastAlloc }; virtual void serialize(std::ostream &os); - virtual void unserialize(const IniFile *db, const std::string §ion); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; template @@ -221,6 +222,9 @@ class EventQueue : public Serializeable private: Event *head; + // only used to hold value between nameChildren() and serialize() + int numAutoSerializeEvents; + void insert(Event *event); void remove(Event *event); @@ -228,7 +232,7 @@ class EventQueue : public Serializeable // constructor EventQueue(const std::string &n) - : Serializeable(n), head(NULL) + : Serializeable(n), head(NULL), numAutoSerializeEvents(-1) {} // schedule the given event on this queue @@ -264,6 +268,7 @@ class EventQueue : public Serializeable virtual void nameChildren(); virtual void serialize(std::ostream &os); + virtual void unserialize(Checkpoint *cp, const std::string §ion); }; diff --git a/sim/param.cc b/sim/param.cc index 5f3f604c1..7affe4786 100644 --- a/sim/param.cc +++ b/sim/param.cc @@ -97,7 +97,7 @@ parseParam(const string &s, T &value) template void -showParam(ostream &os, const T &value) +showParam(ostream &os, T const &value) { os << value; } @@ -277,7 +277,7 @@ template VectorParam; // types that can use the above templates #define INSTANTIATE_PARAM_TEMPLATES(type, typestr) \ template bool parseParam(const string &s, type &value); \ -template void showParam(ostream &os, const type &value); \ +template void showParam(ostream &os, type const &value); \ template void Param::parse(const string &); \ template void VectorParam::parse(const string &); \ template void Param::showValue(ostream &) const; \ diff --git a/sim/serialize.cc b/sim/serialize.cc index f838acc8d..dfd495a32 100644 --- a/sim/serialize.cc +++ b/sim/serialize.cc @@ -43,6 +43,7 @@ #include "sim/sim_events.hh" #include "sim/sim_object.hh" #include "base/trace.hh" +#include "sim/config_node.hh" using namespace std; @@ -88,11 +89,11 @@ paramOut(ostream &os, const std::string &name, const T& param) template void -paramIn(const IniFile *db, const std::string §ion, +paramIn(Checkpoint *cp, const std::string §ion, const std::string &name, T& param) { std::string str; - if (!db->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); } } @@ -116,11 +117,11 @@ arrayParamOut(ostream &os, const std::string &name, template void -arrayParamIn(const IniFile *db, const std::string §ion, +arrayParamIn(Checkpoint *cp, const std::string §ion, const std::string &name, T *param, int size) { std::string str; - if (!db->find(section, name, str)) { + if (!cp->find(section, name, str)) { fatal("Can't unserialize '%s:%s'\n", section, name); } @@ -159,17 +160,27 @@ arrayParamIn(const IniFile *db, const std::string §ion, } +void +objParamIn(Checkpoint *cp, const std::string §ion, + const std::string &name, Serializeable * ¶m) +{ + 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 std::string &name, const type ¶m); \ +paramOut(ostream &os, const std::string &name, type const ¶m); \ template void \ -paramIn(const IniFile *db, const std::string §ion, \ +paramIn(Checkpoint *cp, const std::string §ion, \ const std::string &name, type & param); \ template void \ arrayParamOut(ostream &os, const std::string &name, \ - const type *param, int size); \ + type const *param, int size); \ template void \ -arrayParamIn(const IniFile *db, const std::string §ion, \ +arrayParamIn(Checkpoint *cp, const std::string §ion, \ const std::string &name, type *param, int size); @@ -421,41 +432,74 @@ SerializeableClass::SerializeableClass(const string &className, // // Serializeable * -SerializeableClass::createObject(IniFile &configDB, - const string &configClassName) +SerializeableClass::createObject(Checkpoint *cp, + const std::string §ion) { - // find simulation object class name from configuration class - // (specified by 'type=' parameter) - string simObjClassName; + string className; - if (!configDB.findDefault(configClassName, "type", simObjClassName)) { - cerr << "Configuration class '" << configClassName << "' not found." - << endl; - abort(); + if (!cp->find(section, "type", className)) { + fatal("Serializeable::create: no 'type' entry in section '%s'.\n", + section); } - // look up className to get appropriate createFunc - if (classMap->find(simObjClassName) == classMap->end()) { - cerr << "Simulator object class '" << simObjClassName << "' not found." - << endl; - abort(); + CreateFunc createFunc = (*classMap)[className]; + + if (createFunc == NULL) { + fatal("Serializeable::create: no create function for class '%s'.\n", + className); } - CreateFunc createFunc = (*classMap)[simObjClassName]; + Serializeable *object = createFunc(cp, section); - // builder instance - SerializeableBuilder *objectBuilder = (*createFunc)(); + assert(object != NULL); - assert(objectBuilder != NULL); + return object; +} - // now create the actual simulation object - Serializeable *object = objectBuilder->create(); - assert(object != NULL); +Serializeable * +Serializeable::create(Checkpoint *cp, const std::string §ion) +{ + Serializeable *object = SerializeableClass::createObject(cp, section); + object->unserialize(cp, section); + return object; +} - // done with the SerializeableBuilder now - delete objectBuilder; - return object; +Checkpoint::Checkpoint(const std::string &filename, const std::string &path, + const ConfigNode *_configNode) + : db(new IniFile), basePath(path), configNode(_configNode) +{ + if (!db->load(filename)) { + fatal("Can't load checkpoint file '%s'\n", filename); + } + + mainEventQueue.unserialize(this, "MainEventQueue"); +} + + +bool +Checkpoint::find(const std::string §ion, const std::string &entry, + std::string &value) +{ + return db->find(section, entry, value); } + +bool +Checkpoint::findObj(const std::string §ion, const std::string &entry, + Serializeable *&value) +{ + string path; + + if (!db->find(section, entry, path)) + return false; + + if ((value = configNode->resolveSimObject(path)) != NULL) + return true; + + if ((value = objMap[path]) != NULL) + return true; + + return false; +} diff --git a/sim/serialize.hh b/sim/serialize.hh index 4e0dbd1bd..b615e6527 100644 --- a/sim/serialize.hh +++ b/sim/serialize.hh @@ -41,13 +41,14 @@ #include "sim/host.hh" #include "sim/configfile.hh" -class IniFile; +class Serializeable; +class Checkpoint; template void paramOut(std::ostream &os, const std::string &name, const T& param); template -void paramIn(const IniFile *db, const std::string §ion, +void paramIn(Checkpoint *cp, const std::string §ion, const std::string &name, T& param); template @@ -55,16 +56,21 @@ void arrayParamOut(std::ostream &os, const std::string &name, const T *param, int size); template -void arrayParamIn(const IniFile *db, const std::string §ion, +void arrayParamIn(Checkpoint *cp, const std::string §ion, const std::string &name, T *param, int size); +void +objParamIn(Checkpoint *cp, const std::string §ion, + const std::string &name, Serializeable * ¶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 'db' and 'section'. +// the ostream, and unserialize() has parameters 'cp' and 'section'. #define SERIALIZE_SCALAR(scalar) paramOut(os, #scalar, scalar) -#define UNSERIALIZE_SCALAR(scalar) paramIn(db, section, #scalar, scalar) +#define UNSERIALIZE_SCALAR(scalar) paramIn(cp, section, #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) @@ -72,7 +78,7 @@ void arrayParamIn(const IniFile *db, const std::string §ion, #define UNSERIALIZE_ENUM(scalar) \ do { \ int tmp; \ - paramIn(db, section, #scalar, tmp); \ + paramIn(cp, section, #scalar, tmp); \ scalar = (typeof(scalar))tmp; \ } while (0) @@ -80,7 +86,16 @@ void arrayParamIn(const IniFile *db, const std::string §ion, arrayParamOut(os, #member, member, size) #define UNSERIALIZE_ARRAY(member, size) \ - arrayParamIn(db, section, #member, member, size) + arrayParamIn(cp, section, #member, member, size) + +#define SERIALIZE_OBJPTR(objptr) paramOut(os, #objptr, (objptr)->name()) + +#define UNSERIALIZE_OBJPTR(objptr) \ + do { \ + Serializeable *sptr; \ + objParamIn(cp, section, #objptr, sptr); \ + objptr = dynamic_cast(sptr); \ + } while (0) /* * Basic support for object serialization. @@ -113,7 +128,10 @@ class Serializeable virtual void nameChildren() {} virtual void serialize(std::ostream& os) {} - virtual void unserialize(const IniFile *db, const std::string §ion) {} + virtual void unserialize(Checkpoint *cp, const std::string §ion) {} + + static Serializeable *create(Checkpoint *cp, + const std::string §ion); }; class Serializer @@ -187,7 +205,8 @@ class SerializeableClass // 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 SerializeableBuilder *(*CreateFunc)(); + typedef Serializeable *(*CreateFunc)(Checkpoint *cp, + const std::string §ion); static std::map *classMap; @@ -200,9 +219,8 @@ class SerializeableClass // create Serializeable given name of class and pointer to // configuration hierarchy node - static Serializeable *createObject(IniFile &configDB, - const std::string &configClassName); - + static Serializeable *createObject(Checkpoint *cp, + const std::string §ion); }; // @@ -210,29 +228,29 @@ class SerializeableClass // SerializeableBuilder and SerializeableClass objects // -#define CREATE_SERIALIZEABLE(OBJ_CLASS) \ -OBJ_CLASS *OBJ_CLASS##Builder::create() - -#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \ -class OBJ_CLASS##Builder : public SerializeableBuilder \ -{ \ - public: \ - \ - OBJ_CLASS##Builder() {} \ - virtual ~OBJ_CLASS##Builder() {} \ - \ - OBJ_CLASS *create(); \ -}; \ - \ - \ -SerializeableBuilder * \ -new##OBJ_CLASS##Builder() \ -{ \ - return new OBJ_CLASS##Builder(); \ -} \ - \ -SerializeableClass the##OBJ_CLASS##Class(CLASS_NAME, \ - new##OBJ_CLASS##Builder); +#define REGISTER_SERIALIZEABLE(CLASS_NAME, OBJ_CLASS) \ +SerializeableClass the##OBJ_CLASS##Class(CLASS_NAME, \ + OBJ_CLASS::createForUnserialize); + +class Checkpoint +{ + private: + + IniFile *db; + const std::string basePath; + const ConfigNode *configNode; + std::map objMap; + + public: + Checkpoint(const std::string &filename, const std::string &path, + const ConfigNode *_configNode); + + bool find(const std::string §ion, const std::string &entry, + std::string &value); + + bool findObj(const std::string §ion, const std::string &entry, + Serializeable *&value); +}; //