Revamp serialization to make it easier.

--HG--
extra : convert_revision : c57a538d7cf606dbdf5fa244f92da46bd830e335
This commit is contained in:
Steve Reinhardt 2003-10-28 12:55:12 -08:00
parent cec7f73abf
commit b90f810575
15 changed files with 262 additions and 177 deletions

View file

@ -192,13 +192,13 @@ AlphaTlb::flushAddr(Addr vaddr, uint8_t asn)
void void
AlphaTlb::serialize() AlphaTlb::serialize(ostream &os)
{ {
nameOut(); SERIALIZE_MEMBER(size);
SERIALIZE_MEMBER(nlu);
paramOut("size", size);
paramOut("nlu", nlu);
// should just add serialize/unserialize methods to AlphaPTE
#if 0
stringstream buf; stringstream buf;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
buf.str(""); buf.str("");
@ -237,19 +237,18 @@ AlphaTlb::serialize()
ccprintf(buf, "pte%02d.asn", i); ccprintf(buf, "pte%02d.asn", i);
paramOut(buf.str(), table[i].asn); paramOut(buf.str(), table[i].asn);
} }
#endif
} }
void void
AlphaTlb::unserialize(IniFile &db, const string &category, ConfigNode *node) AlphaTlb::unserialize(IniFile &db, const string &section)
{ {
UNSERIALIZE_MEMBER(size);
UNSERIALIZE_MEMBER(nlu);
#if 0
string data; string data;
stringstream buf; 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++) { for (int i = 0; i < size; i++) {
buf.str(""); buf.str("");
ccprintf(buf, "pte%02d.valid", i); 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); db.findDefault(category, buf.str(), data);
to_number(data, table[i].asn); to_number(data, table[i].asn);
} }
#endif
} }

View file

@ -73,9 +73,8 @@ class AlphaTlb : public SimObject
static void checkCacheability(MemReqPtr req); static void checkCacheability(MemReqPtr req);
// Checkpointing // Checkpointing
virtual void serialize(); virtual void serialize(std::ostream &os);
virtual void unserialize(IniFile &db, const std::string &category, virtual void unserialize(IniFile &db, const std::string &section);
ConfigNode *node);
}; };

View file

@ -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 &section)
{
UNSERIALIZE_ARRAY(regs.intRegFile, NumIntRegs);
UNSERIALIZE_ARRAY(regs.floatRegFile.q, NumFloatRegs);
}
void void
ExecContext::setStatus(Status new_status) ExecContext::setStatus(Status new_status)
{ {

View file

@ -31,6 +31,7 @@
#include "sim/host.hh" #include "sim/host.hh"
#include "mem/mem_req.hh" #include "mem/mem_req.hh"
#include "sim/serialize.hh"
// forward declaration: see functional_memory.hh // forward declaration: see functional_memory.hh
class FunctionalMemory; class FunctionalMemory;
@ -140,6 +141,9 @@ class ExecContext
void regStats(const std::string &name); void regStats(const std::string &name);
void serialize(std::ostream &os);
void unserialize(IniFile &db, const std::string &section);
#ifdef FULL_SYSTEM #ifdef FULL_SYSTEM
bool validInstAddr(Addr addr) { return true; } bool validInstAddr(Addr addr) { return true; }
bool validDataAddr(Addr addr) { return true; } bool validDataAddr(Addr addr) { return true; }

View file

@ -240,34 +240,13 @@ SimpleCPU::regStats()
} }
void void
SimpleCPU::serialize() SimpleCPU::serialize(ostream &os)
{ {
nameOut(); xc->serialize(os);
#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);
} }
void void
SimpleCPU::unserialize(IniFile &db, const string &category, ConfigNode *node) SimpleCPU::unserialize(IniFile &db, const string &category)
{ {
string data; string data;

View file

@ -259,9 +259,8 @@ class SimpleCPU : public BaseCPU
void processCacheCompletion(); void processCacheCompletion();
virtual void serialize(); virtual void serialize(std::ostream &os);
virtual void unserialize(IniFile &db, const std::string &category, virtual void unserialize(IniFile &db, const std::string &section);
ConfigNode *node);
template <class T> template <class T>
Fault read(Addr addr, T& data, unsigned flags); Fault read(Addr addr, T& data, unsigned flags);

View file

@ -41,6 +41,11 @@ typedef uint64 UINT64;
#else #else
typedef uint32_t UINT32; typedef uint32_t UINT32;
typedef uint64_t UINT64; typedef uint64_t UINT64;
#include <ostream>
#include <string>
class IniFile;
#endif #endif
// This structure hacked up from simos // This structure hacked up from simos
@ -74,6 +79,11 @@ struct AlphaAccess
UINT64 bootStrapImpure; // 70: UINT64 bootStrapImpure; // 70:
UINT32 bootStrapCPU; // 78: UINT32 bootStrapCPU; // 78:
UINT32 align2; // 7C: Dummy placeholder for alignment UINT32 align2; // 7C: Dummy placeholder for alignment
#ifndef CONSOLE
void serialize(std::ostream &os);
void unserialize(IniFile &db, const std::string &section);
#endif
}; };
#endif // __ALPHA_ACCESS_H__ #endif // __ALPHA_ACCESS_H__

View file

@ -166,70 +166,59 @@ AlphaConsole::write(MemReqPtr req, const uint8_t *data)
} }
void void
AlphaConsole::serialize() AlphaAccess::serialize(ostream &os)
{ {
nameOut(); SERIALIZE_MEMBER(last_offset);
// assumes full AlphaAccess size SERIALIZE_MEMBER(version);
// might have unnecessary fields here SERIALIZE_MEMBER(numCPUs);
paramOut("last_offset",alphaAccess->last_offset); SERIALIZE_MEMBER(mem_size);
paramOut("version",alphaAccess->version); SERIALIZE_MEMBER(cpuClock);
paramOut("numCPUs",alphaAccess->numCPUs); SERIALIZE_MEMBER(intrClockFrequency);
paramOut("mem_size",alphaAccess->mem_size); SERIALIZE_MEMBER(kernStart);
paramOut("cpuClock",alphaAccess->cpuClock); SERIALIZE_MEMBER(kernEnd);
paramOut("intrClockFrequency",alphaAccess->intrClockFrequency); SERIALIZE_MEMBER(entryPoint);
paramOut("kernStart",alphaAccess->kernStart); SERIALIZE_MEMBER(diskUnit);
paramOut("kernEnd",alphaAccess->kernEnd); SERIALIZE_MEMBER(diskCount);
paramOut("entryPoint",alphaAccess->entryPoint); SERIALIZE_MEMBER(diskPAddr);
paramOut("diskUnit",alphaAccess->diskUnit); SERIALIZE_MEMBER(diskBlock);
paramOut("diskCount",alphaAccess->diskCount); SERIALIZE_MEMBER(diskOperation);
paramOut("diskPAddr",alphaAccess->diskPAddr); SERIALIZE_MEMBER(outputChar);
paramOut("diskBlock",alphaAccess->diskBlock); SERIALIZE_MEMBER(bootStrapImpure);
paramOut("diskOperation",alphaAccess->diskOperation); SERIALIZE_MEMBER(bootStrapCPU);
paramOut("outputChar",alphaAccess->outputChar);
paramOut("bootStrapImpure",alphaAccess->bootStrapImpure);
paramOut("bootStrapCPU",alphaAccess->bootStrapCPU);
} }
void void
AlphaConsole::unserialize(IniFile &db, const std::string &category, AlphaAccess::unserialize(IniFile &db, const std::string &section)
ConfigNode *node)
{ {
string data; UNSERIALIZE_MEMBER(last_offset);
db.findDefault(category,"last_offset",data); UNSERIALIZE_MEMBER(version);
to_number(data,alphaAccess->last_offset); UNSERIALIZE_MEMBER(numCPUs);
db.findDefault(category,"version",data); UNSERIALIZE_MEMBER(mem_size);
to_number(data,alphaAccess->version); UNSERIALIZE_MEMBER(cpuClock);
db.findDefault(category,"numCPUs",data); UNSERIALIZE_MEMBER(intrClockFrequency);
to_number(data,alphaAccess->numCPUs); UNSERIALIZE_MEMBER(kernStart);
db.findDefault(category,"mem_size",data); UNSERIALIZE_MEMBER(kernEnd);
to_number(data,alphaAccess->mem_size); UNSERIALIZE_MEMBER(entryPoint);
db.findDefault(category,"cpuClock",data); UNSERIALIZE_MEMBER(diskUnit);
to_number(data,alphaAccess->cpuClock); UNSERIALIZE_MEMBER(diskCount);
db.findDefault(category,"intrClockFrequency",data); UNSERIALIZE_MEMBER(diskPAddr);
to_number(data,alphaAccess->intrClockFrequency); UNSERIALIZE_MEMBER(diskBlock);
db.findDefault(category,"kernStart",data); UNSERIALIZE_MEMBER(diskOperation);
to_number(data,alphaAccess->kernStart); UNSERIALIZE_MEMBER(outputChar);
db.findDefault(category,"kernEnd",data); UNSERIALIZE_MEMBER(bootStrapImpure);
to_number(data,alphaAccess->kernEnd); UNSERIALIZE_MEMBER(bootStrapCPU);
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);
void
AlphaConsole::serialize(ostream &os)
{
alphaAccess->serialize(os);
}
void
AlphaConsole::unserialize(IniFile &db, const std::string &section)
{
alphaAccess->unserialize(db, section);
} }
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole) BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)

View file

@ -100,9 +100,8 @@ class AlphaConsole : public MmapDevice
/** /**
* standard serialization routines for checkpointing * standard serialization routines for checkpointing
*/ */
virtual void serialize(); virtual void serialize(std::ostream &os);
virtual void unserialize(IniFile &db, const std::string &category, virtual void unserialize(IniFile &db, const std::string &section);
ConfigNode *node);
}; };
#endif // __ALPHA_CONSOLE_HH__ #endif // __ALPHA_CONSOLE_HH__

View file

@ -314,14 +314,13 @@ SimConsole::setInt(int bits)
void void
SimConsole::serialize() SimConsole::serialize(ostream &os)
{ {
panic("Unimplemented"); panic("Unimplemented");
} }
void void
SimConsole::unserialize(IniFile &db, const std::string &category, SimConsole::unserialize(IniFile &db, const std::string &section)
ConfigNode *node)
{ {
panic("Unimplemented"); panic("Unimplemented");
} }

View file

@ -128,9 +128,8 @@ class SimConsole : public SimObject
void initInt(IntrControl *i); void initInt(IntrControl *i);
void setInt(int bits); void setInt(int bits);
virtual void serialize(); virtual void serialize(std::ostream &os);
virtual void unserialize(IniFile &db, const std::string &category, virtual void unserialize(IniFile &db, const std::string &section);
ConfigNode *node);
}; };
class ConsoleListener : public SimObject class ConsoleListener : public SimObject

View file

@ -134,7 +134,7 @@ EventQueue::nameChildren()
} }
void void
EventQueue::serialize() EventQueue::serialize(ostream &os)
{ {
string objects = ""; string objects = "";
@ -142,12 +142,12 @@ EventQueue::serialize()
while (event) { while (event) {
objects += event->name(); objects += event->name();
objects += " "; objects += " ";
event->serialize(); event->serialize(os);
event = event->next; event = event->next;
} }
nameOut("Serialized"); nameOut(os, "Serialized");
paramOut("objects",objects); SERIALIZE_MEMBER(objects);
} }
void void

View file

@ -246,7 +246,7 @@ class EventQueue : public Serializeable
Tick nextEventTime() { return empty() ? curTick : head->when(); } Tick nextEventTime() { return empty() ? curTick : head->when(); }
virtual void nameChildren(); virtual void nameChildren();
virtual void serialize(); virtual void serialize(std::ostream &os);
}; };

View file

@ -34,6 +34,7 @@
#include <vector> #include <vector>
#include "base/misc.hh" #include "base/misc.hh"
#include "base/str.hh"
#include "sim/eventq.hh" #include "sim/eventq.hh"
#include "sim/param.hh" #include "sim/param.hh"
@ -48,7 +49,7 @@ using namespace std;
Serializer *Serializeable::serializer = NULL; Serializer *Serializeable::serializer = NULL;
Serializeable::Serializeable(const string &n) Serializeable::Serializeable(const string &n)
: proxy(this), objName(n), serialized(false) : objName(n), serialized(false)
{ } { }
Serializeable::~Serializeable() Serializeable::~Serializeable()
@ -63,30 +64,131 @@ Serializeable::mark()
serialized = true; serialized = true;
} }
ostream & void
Serializeable::out() const Serializeable::nameOut(ostream &os)
{ {
return serializer->out(); os << "\n[" << name() << "]\n";
} }
void void
Serializeable::nameOut() Serializeable::nameOut(ostream &os, const string &_name)
{ {
out() << "\n[" << name() << "]\n"; os << "\n[" << _name << "]\n";
} }
template <class T> bool parseParam(const std::string &str, T &data);
template <class T> void showParam(const std::ostream &os, T &data);
template <class T>
void 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 <class T>
void
paramIn(IniFile &db, const std::string &section,
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 <class T>
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 <class T>
void
arrayParamIn(IniFile &db, const std::string &section,
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<T>::parse().
// it would be nice to unify these somehow...
vector<string> 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<bool>,
// 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 &param); \
template void \
paramIn(IniFile &db, const std::string &section, \
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 &section, \
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 void
Serializeable::childOut(const string &name, Serializeable *child) Serializeable::childOut(const string &name, Serializeable *child)
{ {
@ -96,6 +198,7 @@ Serializeable::childOut(const string &name, Serializeable *child)
out() << name << "=" << child->name() << "\n"; out() << name << "=" << child->name() << "\n";
} }
#endif
void void
Serializeable::setName(const string &name) Serializeable::setName(const string &name)
@ -174,11 +277,12 @@ Serializer::serialize(const string &f)
add_objects(); add_objects();
while (!objects.empty()) { while (!objects.empty()) {
Serializeable *serial = objects.front(); Serializeable *obj = objects.front();
DPRINTF(Serialize, "Serializing %s\n", serial->name()); DPRINTF(Serialize, "Serializing %s\n", obj->name());
serial->serialize(); obj->nameOut(out());
obj->serialize(out());
objects.pop_front(); objects.pop_front();
list.push_back(serial); list.push_back(obj);
} }
while (!list.empty()) { while (!list.empty()) {
@ -203,7 +307,7 @@ class SerializeEvent : public Event
~SerializeEvent(); ~SerializeEvent();
virtual void process(); virtual void process();
virtual void serialize(); virtual void serialize(std::ostream &os);
}; };
SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f) SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f)
@ -226,7 +330,7 @@ SerializeEvent::process()
} }
void void
SerializeEvent::serialize() SerializeEvent::serialize(ostream &os)
{ {
panic("Cannot serialize the SerializeEvent"); panic("Cannot serialize the SerializeEvent");
} }

View file

@ -36,44 +36,52 @@
#include <list> #include <list>
#include <iostream> #include <iostream>
#include <map>
#include "sim/host.hh" #include "sim/host.hh"
#include "sim/configfile.hh" #include "sim/configfile.hh"
class IniFile; class IniFile;
template <class T>
void paramOut(std::ostream &os, const std::string &name, const T& param);
template <class T>
void paramIn(IniFile &db, const std::string &section,
const std::string &name, T& param);
template <class T>
void arrayParamOut(std::ostream &os, const std::string &name,
const T *param, int size);
template <class T>
void arrayParamIn(IniFile &db, const std::string &section,
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. * Basic support for object serialization.
*/ */
class Serializeable class Serializeable
{ {
public: 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 <class T>
void paramOut(const std::string &name, const T& param) const {
obj->paramOut(name, param);
};
};
friend class Serializer; friend class Serializer;
friend class Proxy;
private:
Proxy proxy;
protected: protected:
const Proxy &getProxy() { return(proxy); };
// object name: should be unique // object name: should be unique
std::string objName; std::string objName;
@ -81,13 +89,8 @@ class Serializeable
static Serializer *serializer; static Serializer *serializer;
void mark(); void mark();
void nameOut(); void nameOut(std::ostream& os);
void nameOut(const std::string &_name); void nameOut(std::ostream& os, const std::string &_name);
void childOut(const std::string &name, Serializeable *child);
template <class T>
void paramOut(const std::string &name, const T& param);
std::ostream &out() const;
public: public:
Serializeable(const std::string &n); Serializeable(const std::string &n);
@ -99,12 +102,8 @@ class Serializeable
const std::string &name() const { return objName; } const std::string &name() const { return objName; }
virtual void nameChildren() {} virtual void nameChildren() {}
virtual void serialize() {} virtual void serialize(std::ostream& os) {}
virtual void unserialize(IniFile &db, const std::string &category, virtual void unserialize(IniFile &db, const std::string &section) {}
ConfigNode *node = NULL)
{
std::cout << name() << " is being unserialized" << std::endl;
}
}; };
class Serializer class Serializer
@ -131,17 +130,6 @@ class Serializer
const std::string &filename() const { return file; } const std::string &filename() const { return file; }
}; };
template <class T>
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 // A SerializeableBuilder serves as an evaluation context for a set of
// parameters that describe a specific instance of a Serializeable. This // parameters that describe a specific instance of a Serializeable. This