diff --git a/arch/alpha/alpha_memory.cc b/arch/alpha/alpha_memory.cc index 83dd5accf..82dd2afa5 100644 --- a/arch/alpha/alpha_memory.cc +++ b/arch/alpha/alpha_memory.cc @@ -192,13 +192,13 @@ AlphaTlb::flushAddr(Addr vaddr, uint8_t asn) void -AlphaTlb::serialize() +AlphaTlb::serialize(ostream &os) { - nameOut(); - - paramOut("size", size); - paramOut("nlu", nlu); + SERIALIZE_MEMBER(size); + SERIALIZE_MEMBER(nlu); + // should just add serialize/unserialize methods to AlphaPTE +#if 0 stringstream buf; for (int i = 0; i < size; i++) { buf.str(""); @@ -237,19 +237,18 @@ AlphaTlb::serialize() ccprintf(buf, "pte%02d.asn", i); paramOut(buf.str(), table[i].asn); } +#endif } void -AlphaTlb::unserialize(IniFile &db, const string &category, ConfigNode *node) +AlphaTlb::unserialize(IniFile &db, const string §ion) { + UNSERIALIZE_MEMBER(size); + UNSERIALIZE_MEMBER(nlu); + +#if 0 string data; stringstream buf; - - db.findDefault(category,"size",data); - to_number(data,size); - db.findDefault(category,"nlu",data); - to_number(data,nlu); - for (int i = 0; i < size; i++) { buf.str(""); ccprintf(buf, "pte%02d.valid", i); @@ -296,6 +295,7 @@ AlphaTlb::unserialize(IniFile &db, const string &category, ConfigNode *node) db.findDefault(category, buf.str(), data); to_number(data, table[i].asn); } +#endif } diff --git a/arch/alpha/alpha_memory.hh b/arch/alpha/alpha_memory.hh index 9b7306bfd..c94ee26c3 100644 --- a/arch/alpha/alpha_memory.hh +++ b/arch/alpha/alpha_memory.hh @@ -73,9 +73,8 @@ class AlphaTlb : public SimObject static void checkCacheability(MemReqPtr req); // Checkpointing - virtual void serialize(); - virtual void unserialize(IniFile &db, const std::string &category, - ConfigNode *node); + virtual void serialize(std::ostream &os); + virtual void unserialize(IniFile &db, const std::string §ion); }; diff --git a/cpu/exec_context.cc b/cpu/exec_context.cc index a4670f291..8cfd0a0ea 100644 --- a/cpu/exec_context.cc +++ b/cpu/exec_context.cc @@ -97,6 +97,22 @@ ExecContext::takeOverFrom(ExecContext *oldContext) } +void +ExecContext::serialize(ostream &os) +{ + SERIALIZE_ARRAY(regs.intRegFile, NumIntRegs); + SERIALIZE_ARRAY(regs.floatRegFile.q, NumFloatRegs); +} + + +void +ExecContext::unserialize(IniFile &db, const std::string §ion) +{ + UNSERIALIZE_ARRAY(regs.intRegFile, NumIntRegs); + UNSERIALIZE_ARRAY(regs.floatRegFile.q, NumFloatRegs); +} + + void ExecContext::setStatus(Status new_status) { diff --git a/cpu/exec_context.hh b/cpu/exec_context.hh index f2afaa334..285154ed0 100644 --- a/cpu/exec_context.hh +++ b/cpu/exec_context.hh @@ -31,6 +31,7 @@ #include "sim/host.hh" #include "mem/mem_req.hh" +#include "sim/serialize.hh" // forward declaration: see functional_memory.hh class FunctionalMemory; @@ -140,6 +141,9 @@ class ExecContext void regStats(const std::string &name); + void serialize(std::ostream &os); + void unserialize(IniFile &db, const std::string §ion); + #ifdef FULL_SYSTEM bool validInstAddr(Addr addr) { return true; } bool validDataAddr(Addr addr) { return true; } diff --git a/cpu/simple_cpu/simple_cpu.cc b/cpu/simple_cpu/simple_cpu.cc index 3d0818672..83e9e1fa2 100644 --- a/cpu/simple_cpu/simple_cpu.cc +++ b/cpu/simple_cpu/simple_cpu.cc @@ -240,34 +240,13 @@ SimpleCPU::regStats() } void -SimpleCPU::serialize() +SimpleCPU::serialize(ostream &os) { - nameOut(); - -#ifdef FULL_SYSTEM -#if 0 - // do we need this anymore?? egh - childOut("itb", xc->itb); - childOut("dtb", xc->dtb); - childOut("physmem", physmem); -#endif -#endif - - for (int i = 0; i < NumIntRegs; i++) { - stringstream buf; - ccprintf(buf, "R%02d", i); - paramOut(buf.str(), xc->regs.intRegFile[i]); - } - for (int i = 0; i < NumFloatRegs; i++) { - stringstream buf; - ccprintf(buf, "F%02d", i); - paramOut(buf.str(), xc->regs.floatRegFile.q[i]); - } - // CPUTraitsType::serializeSpecialRegs(getProxy(), xc->regs); + xc->serialize(os); } void -SimpleCPU::unserialize(IniFile &db, const string &category, ConfigNode *node) +SimpleCPU::unserialize(IniFile &db, const string &category) { string data; diff --git a/cpu/simple_cpu/simple_cpu.hh b/cpu/simple_cpu/simple_cpu.hh index 9e2c7fd06..fa7386106 100644 --- a/cpu/simple_cpu/simple_cpu.hh +++ b/cpu/simple_cpu/simple_cpu.hh @@ -259,9 +259,8 @@ class SimpleCPU : public BaseCPU void processCacheCompletion(); - virtual void serialize(); - virtual void unserialize(IniFile &db, const std::string &category, - ConfigNode *node); + virtual void serialize(std::ostream &os); + virtual void unserialize(IniFile &db, 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 ef33633e5..4bba39c4f 100644 --- a/dev/alpha_access.h +++ b/dev/alpha_access.h @@ -41,6 +41,11 @@ typedef uint64 UINT64; #else typedef uint32_t UINT32; typedef uint64_t UINT64; + +#include +#include +class IniFile; + #endif // This structure hacked up from simos @@ -74,6 +79,11 @@ struct AlphaAccess UINT64 bootStrapImpure; // 70: UINT32 bootStrapCPU; // 78: UINT32 align2; // 7C: Dummy placeholder for alignment + +#ifndef CONSOLE + void serialize(std::ostream &os); + void unserialize(IniFile &db, const std::string §ion); +#endif }; #endif // __ALPHA_ACCESS_H__ diff --git a/dev/alpha_console.cc b/dev/alpha_console.cc index cd03b3656..00dab4bad 100644 --- a/dev/alpha_console.cc +++ b/dev/alpha_console.cc @@ -166,70 +166,59 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data) } void -AlphaConsole::serialize() +AlphaAccess::serialize(ostream &os) { - nameOut(); - // assumes full AlphaAccess size - // might have unnecessary fields here - paramOut("last_offset",alphaAccess->last_offset); - paramOut("version",alphaAccess->version); - paramOut("numCPUs",alphaAccess->numCPUs); - paramOut("mem_size",alphaAccess->mem_size); - paramOut("cpuClock",alphaAccess->cpuClock); - paramOut("intrClockFrequency",alphaAccess->intrClockFrequency); - paramOut("kernStart",alphaAccess->kernStart); - paramOut("kernEnd",alphaAccess->kernEnd); - paramOut("entryPoint",alphaAccess->entryPoint); - paramOut("diskUnit",alphaAccess->diskUnit); - paramOut("diskCount",alphaAccess->diskCount); - paramOut("diskPAddr",alphaAccess->diskPAddr); - paramOut("diskBlock",alphaAccess->diskBlock); - paramOut("diskOperation",alphaAccess->diskOperation); - paramOut("outputChar",alphaAccess->outputChar); - paramOut("bootStrapImpure",alphaAccess->bootStrapImpure); - paramOut("bootStrapCPU",alphaAccess->bootStrapCPU); + SERIALIZE_MEMBER(last_offset); + SERIALIZE_MEMBER(version); + SERIALIZE_MEMBER(numCPUs); + SERIALIZE_MEMBER(mem_size); + SERIALIZE_MEMBER(cpuClock); + SERIALIZE_MEMBER(intrClockFrequency); + SERIALIZE_MEMBER(kernStart); + SERIALIZE_MEMBER(kernEnd); + SERIALIZE_MEMBER(entryPoint); + SERIALIZE_MEMBER(diskUnit); + SERIALIZE_MEMBER(diskCount); + SERIALIZE_MEMBER(diskPAddr); + SERIALIZE_MEMBER(diskBlock); + SERIALIZE_MEMBER(diskOperation); + SERIALIZE_MEMBER(outputChar); + SERIALIZE_MEMBER(bootStrapImpure); + SERIALIZE_MEMBER(bootStrapCPU); } void -AlphaConsole::unserialize(IniFile &db, const std::string &category, - ConfigNode *node) +AlphaAccess::unserialize(IniFile &db, const std::string §ion) { - string data; - db.findDefault(category,"last_offset",data); - to_number(data,alphaAccess->last_offset); - db.findDefault(category,"version",data); - to_number(data,alphaAccess->version); - db.findDefault(category,"numCPUs",data); - to_number(data,alphaAccess->numCPUs); - db.findDefault(category,"mem_size",data); - to_number(data,alphaAccess->mem_size); - db.findDefault(category,"cpuClock",data); - to_number(data,alphaAccess->cpuClock); - db.findDefault(category,"intrClockFrequency",data); - to_number(data,alphaAccess->intrClockFrequency); - db.findDefault(category,"kernStart",data); - to_number(data,alphaAccess->kernStart); - db.findDefault(category,"kernEnd",data); - to_number(data,alphaAccess->kernEnd); - db.findDefault(category,"entryPoint",data); - to_number(data,alphaAccess->entryPoint); - db.findDefault(category,"diskUnit",data); - to_number(data,alphaAccess->diskUnit); - db.findDefault(category,"diskCount",data); - to_number(data,alphaAccess->diskCount); - db.findDefault(category,"diskPAddr",data); - to_number(data,alphaAccess->diskPAddr); - db.findDefault(category,"diskBlock",data); - to_number(data,alphaAccess->diskBlock); - db.findDefault(category,"diskOperation",data); - to_number(data,alphaAccess->diskOperation); - db.findDefault(category,"outputChar",data); - to_number(data,alphaAccess->outputChar); - db.findDefault(category,"bootStrapImpure",data); - to_number(data,alphaAccess->bootStrapImpure); - db.findDefault(category,"bootStrapCPU",data); - to_number(data,alphaAccess->bootStrapCPU); + UNSERIALIZE_MEMBER(last_offset); + UNSERIALIZE_MEMBER(version); + UNSERIALIZE_MEMBER(numCPUs); + UNSERIALIZE_MEMBER(mem_size); + UNSERIALIZE_MEMBER(cpuClock); + UNSERIALIZE_MEMBER(intrClockFrequency); + UNSERIALIZE_MEMBER(kernStart); + UNSERIALIZE_MEMBER(kernEnd); + UNSERIALIZE_MEMBER(entryPoint); + UNSERIALIZE_MEMBER(diskUnit); + UNSERIALIZE_MEMBER(diskCount); + UNSERIALIZE_MEMBER(diskPAddr); + UNSERIALIZE_MEMBER(diskBlock); + UNSERIALIZE_MEMBER(diskOperation); + UNSERIALIZE_MEMBER(outputChar); + UNSERIALIZE_MEMBER(bootStrapImpure); + UNSERIALIZE_MEMBER(bootStrapCPU); +} +void +AlphaConsole::serialize(ostream &os) +{ + alphaAccess->serialize(os); +} + +void +AlphaConsole::unserialize(IniFile &db, const std::string §ion) +{ + alphaAccess->unserialize(db, section); } BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) diff --git a/dev/alpha_console.hh b/dev/alpha_console.hh index 608e6ac00..caa571cec 100644 --- a/dev/alpha_console.hh +++ b/dev/alpha_console.hh @@ -100,9 +100,8 @@ class AlphaConsole : public MmapDevice /** * standard serialization routines for checkpointing */ - virtual void serialize(); - virtual void unserialize(IniFile &db, const std::string &category, - ConfigNode *node); + virtual void serialize(std::ostream &os); + virtual void unserialize(IniFile &db, const std::string §ion); }; #endif // __ALPHA_CONSOLE_HH__ diff --git a/dev/console.cc b/dev/console.cc index 168907417..a84f4a666 100644 --- a/dev/console.cc +++ b/dev/console.cc @@ -314,14 +314,13 @@ SimConsole::setInt(int bits) void -SimConsole::serialize() +SimConsole::serialize(ostream &os) { panic("Unimplemented"); } void -SimConsole::unserialize(IniFile &db, const std::string &category, - ConfigNode *node) +SimConsole::unserialize(IniFile &db, const std::string §ion) { panic("Unimplemented"); } diff --git a/dev/console.hh b/dev/console.hh index b88cab3ef..5d9ea5302 100644 --- a/dev/console.hh +++ b/dev/console.hh @@ -128,9 +128,8 @@ class SimConsole : public SimObject void initInt(IntrControl *i); void setInt(int bits); - virtual void serialize(); - virtual void unserialize(IniFile &db, const std::string &category, - ConfigNode *node); + virtual void serialize(std::ostream &os); + virtual void unserialize(IniFile &db, const std::string §ion); }; class ConsoleListener : public SimObject diff --git a/sim/eventq.cc b/sim/eventq.cc index 6ffce4c0e..da9e85eeb 100644 --- a/sim/eventq.cc +++ b/sim/eventq.cc @@ -134,7 +134,7 @@ EventQueue::nameChildren() } void -EventQueue::serialize() +EventQueue::serialize(ostream &os) { string objects = ""; @@ -142,12 +142,12 @@ EventQueue::serialize() while (event) { objects += event->name(); objects += " "; - event->serialize(); + event->serialize(os); event = event->next; } - nameOut("Serialized"); - paramOut("objects",objects); + nameOut(os, "Serialized"); + SERIALIZE_MEMBER(objects); } void diff --git a/sim/eventq.hh b/sim/eventq.hh index df8e00bd8..cd86512e4 100644 --- a/sim/eventq.hh +++ b/sim/eventq.hh @@ -246,7 +246,7 @@ class EventQueue : public Serializeable Tick nextEventTime() { return empty() ? curTick : head->when(); } virtual void nameChildren(); - virtual void serialize(); + virtual void serialize(std::ostream &os); }; diff --git a/sim/serialize.cc b/sim/serialize.cc index c90f1694e..936812795 100644 --- a/sim/serialize.cc +++ b/sim/serialize.cc @@ -34,6 +34,7 @@ #include #include "base/misc.hh" +#include "base/str.hh" #include "sim/eventq.hh" #include "sim/param.hh" @@ -48,7 +49,7 @@ using namespace std; Serializer *Serializeable::serializer = NULL; Serializeable::Serializeable(const string &n) - : proxy(this), objName(n), serialized(false) + : objName(n), serialized(false) { } Serializeable::~Serializeable() @@ -63,30 +64,131 @@ Serializeable::mark() serialized = true; } -ostream & -Serializeable::out() const +void +Serializeable::nameOut(ostream &os) { - return serializer->out(); + os << "\n[" << name() << "]\n"; } void -Serializeable::nameOut() +Serializeable::nameOut(ostream &os, const string &_name) { - out() << "\n[" << name() << "]\n"; + os << "\n[" << _name << "]\n"; } +template bool parseParam(const std::string &str, T &data); +template void showParam(const std::ostream &os, T &data); + +template void -Serializeable::nameOut(const string &_name) +paramOut(ostream &os, const std::string &name, const T& param) { - out() << "\n[" << _name << "]\n"; + os << name << "="; + showParam(os, param); + os << "\n"; } -template<> void -Serializeable::paramOut(const string &name, const uint64_t& param) + +template +void +paramIn(IniFile &db, const std::string §ion, + const std::string &name, T& param) { - out() << name << "=0x" << hex << param << dec << "\n"; + std::string str; + if (!db.find(section, name, str) || !parseParam(str, param)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } } + +template +void +arrayParamOut(ostream &os, const std::string &name, + const T *param, int size) +{ + os << name << "="; + if (size > 0) + showParam(os, param[0]); + for (int i = 1; i < size; ++i) { + os << " "; + showParam(os, param[i]); + } + os << "\n"; +} + + +template +void +arrayParamIn(IniFile &db, const std::string §ion, + const std::string &name, T *param, int size) +{ + std::string str; + if (!db.find(section, name, str)) { + fatal("Can't unserialize '%s:%s'\n", section, name); + } + + // code below stolen from VectorParam::parse(). + // it would be nice to unify these somehow... + + vector tokens; + + tokenize(tokens, str, ' '); + + // Need this if we were doing a vector + // value.resize(tokens.size()); + + if (tokens.size() != size) { + fatal("Array size mismatch on %s:%s'\n", section, name); + } + + for (int i = 0; i < tokens.size(); i++) { + // need to parse into local variable to handle vector, + // for which operator[] returns a special reference class + // that's not the same as 'bool&', (since it's a packed + // vector) + T scalar_value; + if (!parseParam(tokens[i], scalar_value)) { + string err("could not parse \""); + + err += str; + err += "\""; + + fatal(err); + } + + // assign parsed value to vector + param[i] = scalar_value; + } +} + + +#define INSTANTIATE_PARAM_TEMPLATES(type) \ +template void \ +paramOut(ostream &os, const std::string &name, const type ¶m); \ +template void \ +paramIn(IniFile &db, const std::string §ion, \ + const std::string &name, type & param); \ +template void \ +arrayParamOut(ostream &os, const std::string &name, \ + const type *param, int size); \ +template void \ +arrayParamIn(IniFile &db, const std::string §ion, \ + const std::string &name, type *param, int size); + + +INSTANTIATE_PARAM_TEMPLATES(int8_t) +INSTANTIATE_PARAM_TEMPLATES(uint8_t) +INSTANTIATE_PARAM_TEMPLATES(int16_t) +INSTANTIATE_PARAM_TEMPLATES(uint16_t) +INSTANTIATE_PARAM_TEMPLATES(int32_t) +INSTANTIATE_PARAM_TEMPLATES(uint32_t) +INSTANTIATE_PARAM_TEMPLATES(int64_t) +INSTANTIATE_PARAM_TEMPLATES(uint64_t) +INSTANTIATE_PARAM_TEMPLATES(string) + + +#if 0 +// unneeded? void Serializeable::childOut(const string &name, Serializeable *child) { @@ -96,6 +198,7 @@ Serializeable::childOut(const string &name, Serializeable *child) out() << name << "=" << child->name() << "\n"; } +#endif void Serializeable::setName(const string &name) @@ -174,11 +277,12 @@ Serializer::serialize(const string &f) add_objects(); while (!objects.empty()) { - Serializeable *serial = objects.front(); - DPRINTF(Serialize, "Serializing %s\n", serial->name()); - serial->serialize(); + Serializeable *obj = objects.front(); + DPRINTF(Serialize, "Serializing %s\n", obj->name()); + obj->nameOut(out()); + obj->serialize(out()); objects.pop_front(); - list.push_back(serial); + list.push_back(obj); } while (!list.empty()) { @@ -203,7 +307,7 @@ class SerializeEvent : public Event ~SerializeEvent(); virtual void process(); - virtual void serialize(); + virtual void serialize(std::ostream &os); }; SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f) @@ -226,7 +330,7 @@ SerializeEvent::process() } void -SerializeEvent::serialize() +SerializeEvent::serialize(ostream &os) { panic("Cannot serialize the SerializeEvent"); } diff --git a/sim/serialize.hh b/sim/serialize.hh index ffcbbcdc2..5ebbfaba5 100644 --- a/sim/serialize.hh +++ b/sim/serialize.hh @@ -36,44 +36,52 @@ #include #include +#include #include "sim/host.hh" #include "sim/configfile.hh" class IniFile; +template +void paramOut(std::ostream &os, const std::string &name, const T& param); + +template +void paramIn(IniFile &db, const std::string §ion, + const std::string &name, T& param); + +template +void arrayParamOut(std::ostream &os, const std::string &name, + const T *param, int size); + +template +void arrayParamIn(IniFile &db, const std::string §ion, + const std::string &name, T *param, int size); + +// +// 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'. +#define SERIALIZE_MEMBER(member) paramOut(os, #member, member) + +#define UNSERIALIZE_MEMBER(member) paramIn(db, section, #member, member) + +#define SERIALIZE_ARRAY(member, size) \ + arrayParamOut(os, #member, member, size) + +#define UNSERIALIZE_ARRAY(member, size) \ + arrayParamIn(db, section, #member, member, size) + /* * Basic support for object serialization. */ class Serializeable { public: - // To allow other classes to do some of the serialization work. - class Proxy { - private: - Serializeable *obj; - - // Make it so only Serializables can construct one of these. - Proxy(Serializeable *o) : obj(o) {}; - - friend class Serializeable; - - public: - template - void paramOut(const std::string &name, const T& param) const { - obj->paramOut(name, param); - }; - }; friend class Serializer; - friend class Proxy; - - private: - Proxy proxy; protected: - const Proxy &getProxy() { return(proxy); }; - // object name: should be unique std::string objName; @@ -81,13 +89,8 @@ class Serializeable static Serializer *serializer; void mark(); - void nameOut(); - void nameOut(const std::string &_name); - void childOut(const std::string &name, Serializeable *child); - template - void paramOut(const std::string &name, const T& param); - - std::ostream &out() const; + void nameOut(std::ostream& os); + void nameOut(std::ostream& os, const std::string &_name); public: Serializeable(const std::string &n); @@ -99,12 +102,8 @@ class Serializeable const std::string &name() const { return objName; } virtual void nameChildren() {} - virtual void serialize() {} - virtual void unserialize(IniFile &db, const std::string &category, - ConfigNode *node = NULL) - { - std::cout << name() << " is being unserialized" << std::endl; - } + virtual void serialize(std::ostream& os) {} + virtual void unserialize(IniFile &db, const std::string §ion) {} }; class Serializer @@ -131,17 +130,6 @@ class Serializer const std::string &filename() const { return file; } }; -template -inline void -Serializeable::paramOut(const std::string &name, const T& param) -{ - out() << name << "=" << param << "\n"; -} - -template <> void -Serializeable::paramOut(const std::string &name, const uint64_t& param); - - // // A SerializeableBuilder serves as an evaluation context for a set of // parameters that describe a specific instance of a Serializeable. This