/*
- * Copyright (c) 2003 The Regents of The University of Michigan
+ * Copyright (c) 2002-2004 The Regents of The University of Michigan
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
*/
#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include <fstream>
#include <list>
#include <string>
#include <vector>
+#include "base/inifile.hh"
#include "base/misc.hh"
-
+#include "base/str.hh"
+#include "base/trace.hh"
+#include "sim/config_node.hh"
#include "sim/eventq.hh"
#include "sim/param.hh"
#include "sim/serialize.hh"
-#include "base/inifile.hh"
#include "sim/sim_events.hh"
#include "sim/sim_object.hh"
-#include "base/trace.hh"
using namespace std;
-Serializer *Serializeable::serializer = NULL;
-
-Serializeable::Serializeable(const string &n)
- : proxy(this), objName(n), serialized(false)
-{ }
-
-Serializeable::~Serializeable()
-{ }
-
void
-Serializeable::mark()
+Serializable::nameOut(ostream &os)
{
- if (!serialized)
- serializer->add_object(this);
-
- serialized = true;
+ os << "\n[" << name() << "]\n";
}
-ostream &
-Serializeable::out() const
+void
+Serializable::nameOut(ostream &os, const string &_name)
{
- return serializer->out();
+ os << "\n[" << _name << "]\n";
}
+template <class T>
void
-Serializeable::nameOut()
+paramOut(ostream &os, const std::string &name, const T ¶m)
{
- out() << "\n[" << name() << "]\n";
+ os << name << "=";
+ showParam(os, param);
+ os << "\n";
}
+
+template <class T>
void
-Serializeable::nameOut(const string &_name)
+paramIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name, T ¶m)
{
- out() << "\n[" << _name << "]\n";
+ std::string str;
+ if (!cp->find(section, name, str) || !parseParam(str, param)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
+ }
}
-template<> void
-Serializeable::paramOut(const string &name, const uint64_t& param)
-{
- out() << name << "=0x" << hex << param << dec << "\n";
-}
+template <class T>
void
-Serializeable::childOut(const string &name, Serializeable *child)
+arrayParamOut(ostream &os, const std::string &name,
+ const T *param, int size)
{
- child->mark();
- if (child->name() == "")
- panic("child is unnamed");
-
- out() << name << "=" << child->name() << "\n";
+ 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
-Serializeable::setName(const string &name)
+arrayParamIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name, T *param, int size)
{
- if (objName != "") {
- cprintf("Renaming object '%s' to '%s'.\n", objName, name);
+ std::string str;
+ if (!cp->find(section, name, str)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
}
- objName = name;
-}
+ // code below stolen from VectorParam<T>::parse().
+ // it would be nice to unify these somehow...
-Serializer::Serializer()
-{ }
+ vector<string> tokens;
-Serializer::~Serializer()
-{ }
+ tokenize(tokens, str, ' ');
-ostream &
-Serializer::out() const
-{
- if (!output)
- panic("must set output before serializing");
+ // 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 \"");
- return *output;
+ err += str;
+ err += "\"";
+
+ fatal(err);
+ }
+
+ // assign parsed value to vector
+ param[i] = scalar_value;
+ }
}
+
void
-Serializer::add_object(Serializeable *obj)
+objParamIn(Checkpoint *cp, const std::string §ion,
+ const std::string &name, Serializable * ¶m)
{
- objects.push_back(obj);
+ if (!cp->findObj(section, name, param)) {
+ fatal("Can't unserialize '%s:%s'\n", section, name);
+ }
}
-void
-Serializer::add_objects()
+
+#define INSTANTIATE_PARAM_TEMPLATES(type) \
+template void \
+paramOut(ostream &os, const std::string &name, type const ¶m); \
+template void \
+paramIn(Checkpoint *cp, const std::string §ion, \
+ const std::string &name, type & param); \
+template void \
+arrayParamOut(ostream &os, const std::string &name, \
+ type const *param, int size); \
+template void \
+arrayParamIn(Checkpoint *cp, 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(bool)
+INSTANTIATE_PARAM_TEMPLATES(string)
+
+
+/////////////////////////////
+
+/// Container for serializing global variables (not associated with
+/// any serialized object).
+class Globals : public Serializable
{
- mainEventQueue.mark();
+ public:
+ const string name() const;
+ void serialize(ostream &os);
+ void unserialize(Checkpoint *cp);
+};
- SimObject::SimObjectList::iterator i = SimObject::simObjectList.begin();
- SimObject::SimObjectList::iterator end = SimObject::simObjectList.end();
+/// The one and only instance of the Globals class.
+Globals globals;
- while (i != end) {
- (*i)->mark();
- ++i;
- }
+const string
+Globals::name() const
+{
+ return "Globals";
}
void
-Serializer::serialize(const string &f)
+Globals::serialize(ostream &os)
{
- if (Serializeable::serializer != NULL)
- panic("in process of serializing!");
-
- Serializeable::serializer = this;
+ nameOut(os);
+ SERIALIZE_SCALAR(curTick);
- file = f;
- string cpt_file = file + ".cpt";
- output = new ofstream(cpt_file.c_str());
- time_t t = time(NULL);
- *output << "// checkpoint generated: " << ctime(&t);
+ nameOut(os, "MainEventQueue");
+ mainEventQueue.serialize(os);
+}
- serlist_t list;
+void
+Globals::unserialize(Checkpoint *cp)
+{
+ const string §ion = name();
+ UNSERIALIZE_SCALAR(curTick);
- add_objects();
- while (!objects.empty()) {
- Serializeable *serial = objects.front();
- DPRINTF(Serialize, "Naming children of %s\n", serial->name());
- serial->nameChildren();
- objects.pop_front();
- list.push_back(serial);
- }
+ mainEventQueue.unserialize(cp, "MainEventQueue");
+}
- while (!list.empty()) {
- list.front()->serialized = false;
- list.pop_front();
- }
+void
+Serializable::serializeAll()
+{
+ string dir = Checkpoint::dir();
+ if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
+ fatal("couldn't mkdir %s\n", dir);
- add_objects();
- while (!objects.empty()) {
- Serializeable *serial = objects.front();
- DPRINTF(Serialize, "Serializing %s\n", serial->name());
- serial->serialize();
- objects.pop_front();
- list.push_back(serial);
- }
+ string cpt_file = dir + Checkpoint::baseFilename;
+ ofstream outstream(cpt_file.c_str());
+ time_t t = time(NULL);
+ 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;
- file = "";
+void
+Serializable::unserializeGlobals(Checkpoint *cp)
+{
+ globals.unserialize(cp);
}
+
class SerializeEvent : public Event
{
protected:
- string file;
+ Tick repeat;
public:
- SerializeEvent(EventQueue *q, Tick when, const string &file);
- ~SerializeEvent();
-
+ SerializeEvent(Tick _when, Tick _repeat);
virtual void process();
- virtual void serialize();
+ virtual void serialize(std::ostream &os)
+ {
+ panic("Cannot serialize the SerializeEvent");
+ }
+
};
-SerializeEvent::SerializeEvent(EventQueue *q, Tick when, const string &f)
- : Event(q), file(f)
+SerializeEvent::SerializeEvent(Tick _when, Tick _repeat)
+ : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat)
{
setFlags(AutoDelete);
- schedule(when);
+ schedule(_when);
}
-SerializeEvent::~SerializeEvent()
+void
+SerializeEvent::process()
{
+ Serializable::serializeAll();
+ if (repeat)
+ schedule(curTick + repeat);
}
-void
-SerializeEvent::process()
+const char *Checkpoint::baseFilename = "m5.cpt";
+
+static string checkpointDirBase;
+
+string
+Checkpoint::dir()
{
- Serializer serial;
- serial.serialize(file);
- new SimExitEvent("Serialization caused exit");
+ // use csprintf to insert curTick into directory name if it
+ // appears to have a format placeholder in it.
+ return (checkpointDirBase.find("%") != string::npos) ?
+ csprintf(checkpointDirBase, curTick) : checkpointDirBase;
}
void
-SerializeEvent::serialize()
+Checkpoint::setup(Tick when, Tick period)
{
- panic("Cannot serialize the SerializeEvent");
+ new SerializeEvent(when, period);
}
class SerializeParamContext : public ParamContext
SerializeParamContext serialParams("serialize");
+Param<string> serialize_dir(&serialParams, "dir",
+ "dir to stick checkpoint in "
+ "(sprintf format with cycle #)");
+
Param<Counter> serialize_cycle(&serialParams,
"cycle",
"cycle to serialize",
0);
-Param<string> serialize_file(&serialParams,
- "file",
- "file to write to", "");
+Param<Counter> serialize_period(&serialParams,
+ "period",
+ "period to repeat serializations",
+ 0);
+
+
SerializeParamContext::SerializeParamContext(const string §ion)
: ParamContext(section), event(NULL)
void
SerializeParamContext::checkParams()
{
- if (!((string)serialize_file).empty() && serialize_cycle > 0)
- event = new SerializeEvent(&mainEventQueue, serialize_cycle,
- serialize_file);
+ if (serialize_dir.isValid()) {
+ checkpointDirBase = serialize_dir;
+ } else {
+ checkpointDirBase = outputDirectory + "cpt.%012d";
+ }
+
+ // guarantee that directory ends with a '/'
+ if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
+ checkpointDirBase += "/";
+
+ if (serialize_cycle > 0)
+ Checkpoint::setup(serialize_cycle, serialize_period);
}
void
-debug_serialize(const char *file)
+debug_serialize()
{
- Serializer serial;
- serial.serialize(file);
- new SimExitEvent("Serialization caused exit");
+ Serializable::serializeAll();
}
-
-
+void
+debug_serialize(Tick when)
+{
+ new SerializeEvent(when, 0);
+}
////////////////////////////////////////////////////////////////////////
//
-// 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<string,SerializeableClass::CreateFunc> *SerializeableClass::classMap = 0;
+map<string,SerializableClass::CreateFunc> *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<string,SerializeableClass::CreateFunc>();
+ classMap = new map<string,SerializableClass::CreateFunc>();
if ((*classMap)[className])
{
//
//
-Serializeable *
-SerializeableClass::createObject(IniFile &configDB,
- const string &configClassName)
+Serializable *
+SerializableClass::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("Serializable::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("Serializable::create: no create function for class '%s'.\n",
+ className);
}
- CreateFunc createFunc = (*classMap)[simObjClassName];
+ Serializable *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);
+Serializable *
+Serializable::create(Checkpoint *cp, const std::string §ion)
+{
+ Serializable *object = SerializableClass::createObject(cp, section);
+ object->unserialize(cp, section);
+ return object;
+}
- // done with the SerializeableBuilder now
- delete objectBuilder;
- return object;
+Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path,
+ const ConfigNode *_configNode)
+ : db(new IniFile), basePath(path), configNode(_configNode), cptDir(cpt_dir)
+{
+ string filename = cpt_dir + "/" + Checkpoint::baseFilename;
+ if (!db->load(filename)) {
+ fatal("Can't load checkpoint file '%s'\n", filename);
+ }
+}
+
+
+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,
+ Serializable *&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;
+}
+
+
+bool
+Checkpoint::sectionExists(const std::string §ion)
+{
+ return db->sectionExists(section);
+}