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
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 &section)
{
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
}

View file

@ -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 &section);
};

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
ExecContext::setStatus(Status new_status)
{

View file

@ -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 &section);
#ifdef FULL_SYSTEM
bool validInstAddr(Addr addr) { return true; }
bool validDataAddr(Addr addr) { return true; }

View file

@ -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;

View file

@ -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 &section);
template <class T>
Fault read(Addr addr, T& data, unsigned flags);

View file

@ -41,6 +41,11 @@ typedef uint64 UINT64;
#else
typedef uint32_t UINT32;
typedef uint64_t UINT64;
#include <ostream>
#include <string>
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 &section);
#endif
};
#endif // __ALPHA_ACCESS_H__

View file

@ -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 &section)
{
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 &section)
{
alphaAccess->unserialize(db, section);
}
BEGIN_DECLARE_SIM_OBJECT_PARAMS(AlphaConsole)

View file

@ -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 &section);
};
#endif // __ALPHA_CONSOLE_HH__

View file

@ -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 &section)
{
panic("Unimplemented");
}

View file

@ -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 &section);
};
class ConsoleListener : public SimObject

View file

@ -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

View file

@ -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);
};

View file

@ -34,6 +34,7 @@
#include <vector>
#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 <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
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
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");
}

View file

@ -36,44 +36,52 @@
#include <list>
#include <iostream>
#include <map>
#include "sim/host.hh"
#include "sim/configfile.hh"
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.
*/
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 <class T>
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 <class T>
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 &section) {}
};
class Serializer
@ -131,17 +130,6 @@ class Serializer
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
// parameters that describe a specific instance of a Serializeable. This