pseudoinst: get rid of mainEventQueue references.
[gem5.git] / src / sim / serialize.cc
index 0e31391166579f92647354cce7ba98bcaae760b7..aa343d0e9c2ed7569574ad866f0fbef44d414754 100644 (file)
 #include "base/str.hh"
 #include "base/trace.hh"
 #include "sim/eventq.hh"
-#include "sim/param.hh"
 #include "sim/serialize.hh"
 #include "sim/sim_events.hh"
 #include "sim/sim_exit.hh"
 #include "sim/sim_object.hh"
 
+// For stat reset hack
+#include "sim/stat_control.hh"
+
 using namespace std;
 
+extern SimObject *resolveSimObject(const string &);
+
+//
+// The base implementations use to_number for parsing and '<<' for
+// displaying, suitable for integer types.
+//
+template <class T>
+bool
+parseParam(const string &s, T &value)
+{
+    return to_number(s, value);
+}
+
+template <class T>
+void
+showParam(ostream &os, const T &value)
+{
+    os << value;
+}
+
+//
+// Template specializations:
+// - char (8-bit integer)
+// - floating-point types
+// - bool
+// - string
+//
+
+// Treat 8-bit ints (chars) as ints on output, not as chars
+template <>
+void
+showParam(ostream &os, const char &value)
+{
+    os << (int)value;
+}
+
+
+template <>
+void
+showParam(ostream &os, const signed char &value)
+{
+    os << (int)value;
+}
+
+
+template <>
+void
+showParam(ostream &os, const unsigned char &value)
+{
+    os << (unsigned int)value;
+}
+
+
+// Use sscanf() for FP types as to_number() only handles integers
+template <>
+bool
+parseParam(const string &s, float &value)
+{
+    return (sscanf(s.c_str(), "%f", &value) == 1);
+}
+
+template <>
+bool
+parseParam(const string &s, double &value)
+{
+    return (sscanf(s.c_str(), "%lf", &value) == 1);
+}
+
+template <>
+bool
+parseParam(const string &s, bool &value)
+{
+    const string &ls = to_lower(s);
+
+    if (ls == "true") {
+        value = true;
+        return true;
+    }
+
+    if (ls == "false") {
+        value = false;
+        return true;
+    }
+
+    return false;
+}
+
+// Display bools as strings
+template <>
+void
+showParam(ostream &os, const bool &value)
+{
+    os << (value ? "true" : "false");
+}
+
+
+// String requires no processing to speak of
+template <>
+bool
+parseParam(const string &s, string &value)
+{
+    value = s;
+    return true;
+}
+
 int Serializable::ckptMaxCount = 0;
 int Serializable::ckptCount = 0;
 int Serializable::ckptPrevCount = -1;
@@ -72,35 +179,60 @@ Serializable::nameOut(ostream &os, const string &_name)
 
 template <class T>
 void
-paramOut(ostream &os, const std::string &name, const T &param)
+paramOut(ostream &os, const string &name, const T &param)
 {
     os << name << "=";
     showParam(os, param);
     os << "\n";
 }
 
+template <class T>
+void
+arrayParamOut(ostream &os, const string &name, const vector<T> &param)
+{
+    typename vector<T>::size_type size = param.size();
+    os << name << "=";
+    if (size > 0)
+        showParam(os, param[0]);
+    for (typename vector<T>::size_type i = 1; i < size; ++i) {
+        os << " ";
+        showParam(os, param[i]);
+    }
+    os << "\n";
+}
+
 
 template <class T>
 void
-paramIn(Checkpoint *cp, const std::string &section,
-        const std::string &name, T &param)
+paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
 {
-    std::string str;
+    string str;
     if (!cp->find(section, name, str) || !parseParam(str, param)) {
         fatal("Can't unserialize '%s:%s'\n", section, name);
     }
 }
 
+template <class T>
+bool
+optParamIn(Checkpoint *cp, const string &section, const string &name, T &param)
+{
+    string str;
+    if (!cp->find(section, name, str) || !parseParam(str, param)) {
+        warn("optional parameter %s:%s not present\n", section, name);
+        return false;
+    } else {
+        return true;
+    }
+}
 
 template <class T>
 void
-arrayParamOut(ostream &os, const std::string &name,
-              const T *param, int size)
+arrayParamOut(ostream &os, const string &name, const T *param, unsigned size)
 {
     os << name << "=";
     if (size > 0)
         showParam(os, param[0]);
-    for (int i = 1; i < size; ++i) {
+    for (unsigned i = 1; i < size; ++i) {
         os << " ";
         showParam(os, param[i]);
     }
@@ -110,10 +242,10 @@ arrayParamOut(ostream &os, const std::string &name,
 
 template <class T>
 void
-arrayParamIn(Checkpoint *cp, const std::string &section,
-             const std::string &name, T *param, int size)
+arrayParamIn(Checkpoint *cp, const string &section, const string &name,
+             T *param, unsigned size)
 {
-    std::string str;
+    string str;
     if (!cp->find(section, name, str)) {
         fatal("Can't unserialize '%s:%s'\n", section, name);
     }
@@ -132,12 +264,12 @@ arrayParamIn(Checkpoint *cp, const std::string &section,
         fatal("Array size mismatch on %s:%s'\n", section, name);
     }
 
-    for (int i = 0; i < tokens.size(); i++) {
+    for (vector<string>::size_type 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;
+        T scalar_value = 0;
         if (!parseParam(tokens[i], scalar_value)) {
             string err("could not parse \"");
 
@@ -152,10 +284,51 @@ arrayParamIn(Checkpoint *cp, const std::string &section,
     }
 }
 
+template <class T>
+void
+arrayParamIn(Checkpoint *cp, const string &section,
+             const string &name, vector<T> &param)
+{
+    string str;
+    if (!cp->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());
+
+    param.resize(tokens.size());
+
+    for (vector<string>::size_type 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 = 0;
+        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;
+    }
+}
 
 void
-objParamIn(Checkpoint *cp, const std::string &section,
-           const std::string &name, Serializable * &param)
+objParamIn(Checkpoint *cp, const string &section,
+           const string &name, SimObject * &param)
 {
     if (!cp->findObj(section, name, param)) {
         fatal("Can't unserialize '%s:%s'\n", section, name);
@@ -163,19 +336,29 @@ objParamIn(Checkpoint *cp, const std::string &section,
 }
 
 
-#define INSTANTIATE_PARAM_TEMPLATES(type)                              \
-template void                                                          \
-paramOut(ostream &os, const std::string &name, type const &param);     \
-template void                                                          \
-paramIn(Checkpoint *cp, const std::string &section,                    \
-        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 &section,               \
-             const std::string &name, type *param, int size);
-
+#define INSTANTIATE_PARAM_TEMPLATES(type)                               \
+template void                                                           \
+paramOut(ostream &os, const string &name, type const &param);           \
+template void                                                           \
+paramIn(Checkpoint *cp, const string &section,                          \
+        const string &name, type & param);                              \
+template bool                                                           \
+optParamIn(Checkpoint *cp, const string &section,                       \
+        const string &name, type & param);                              \
+template void                                                           \
+arrayParamOut(ostream &os, const string &name,                          \
+              type const *param, unsigned size);                        \
+template void                                                           \
+arrayParamIn(Checkpoint *cp, const string &section,                     \
+             const string &name, type *param, unsigned size);           \
+template void                                                           \
+arrayParamOut(ostream &os, const string &name,                          \
+              const vector<type> &param);                               \
+template void                                                           \
+arrayParamIn(Checkpoint *cp, const string &section,                     \
+             const string &name, vector<type> &param);
+
+INSTANTIATE_PARAM_TEMPLATES(char)
 INSTANTIATE_PARAM_TEMPLATES(signed char)
 INSTANTIATE_PARAM_TEMPLATES(unsigned char)
 INSTANTIATE_PARAM_TEMPLATES(signed short)
@@ -187,6 +370,8 @@ INSTANTIATE_PARAM_TEMPLATES(unsigned long)
 INSTANTIATE_PARAM_TEMPLATES(signed long long)
 INSTANTIATE_PARAM_TEMPLATES(unsigned long long)
 INSTANTIATE_PARAM_TEMPLATES(bool)
+INSTANTIATE_PARAM_TEMPLATES(float)
+INSTANTIATE_PARAM_TEMPLATES(double)
 INSTANTIATE_PARAM_TEMPLATES(string)
 
 
@@ -230,150 +415,55 @@ Globals::unserialize(Checkpoint *cp)
     mainEventQueue.unserialize(cp, "MainEventQueue");
 }
 
-void
-Serializable::serializeAll()
-{
-    string dir = Checkpoint::dir();
-    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
-            fatal("couldn't mkdir %s\n", dir);
-
-    string cpt_file = dir + Checkpoint::baseFilename;
-    ofstream outstream(cpt_file.c_str());
-    time_t t = time(NULL);
-    outstream << "// checkpoint generated: " << ctime(&t);
-
-    globals.serialize(outstream);
-    SimObject::serializeAll(outstream);
-
-    assert(Serializable::ckptPrevCount + 1 == Serializable::ckptCount);
-    Serializable::ckptPrevCount++;
-    if (ckptMaxCount && ++ckptCount >= ckptMaxCount)
-        exitSimLoop(curTick + 1, "Maximum number of checkpoints dropped");
-
-}
-
-
-void
-Serializable::unserializeGlobals(Checkpoint *cp)
+Serializable::Serializable()
 {
-    globals.unserialize(cp);
 }
 
-
-class SerializeEvent : public Event
+Serializable::~Serializable()
 {
-  protected:
-    Tick repeat;
-
-  public:
-    SerializeEvent(Tick _when, Tick _repeat);
-    virtual void process();
-    virtual void serialize(std::ostream &os)
-    {
-        panic("Cannot serialize the SerializeEvent");
-    }
-
-};
-
-SerializeEvent::SerializeEvent(Tick _when, Tick _repeat)
-    : Event(&mainEventQueue, Serialize_Pri), repeat(_repeat)
-{
-    setFlags(AutoDelete);
-    schedule(_when);
 }
 
 void
-SerializeEvent::process()
+Serializable::serialize(ostream &os)
 {
-    Serializable::serializeAll();
-    if (repeat)
-        schedule(curTick + repeat);
-}
-
-const char *Checkpoint::baseFilename = "m5.cpt";
-
-static string checkpointDirBase;
-
-string
-Checkpoint::dir()
-{
-    // 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
-Checkpoint::setup(Tick when, Tick period)
-{
-    new SerializeEvent(when, period);
-}
-
-class SerializeParamContext : public ParamContext
-{
-  private:
-    SerializeEvent *event;
-
-  public:
-    SerializeParamContext(const string &section);
-    ~SerializeParamContext();
-    void checkParams();
-};
-
-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<Counter> serialize_period(&serialParams,
-                                "period",
-                                "period to repeat serializations",
-                                0);
-
-Param<int> serialize_count(&serialParams, "count",
-                           "maximum number of checkpoints to drop");
-
-SerializeParamContext::SerializeParamContext(const string &section)
-    : ParamContext(section), event(NULL)
-{ }
-
-SerializeParamContext::~SerializeParamContext()
+Serializable::unserialize(Checkpoint *cp, const string &section)
 {
 }
 
 void
-SerializeParamContext::checkParams()
+Serializable::serializeAll(const string &cpt_dir)
 {
-    checkpointDirBase = simout.resolve(serialize_dir);
-
-    // guarantee that directory ends with a '/'
-    if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
-        checkpointDirBase += "/";
+    string dir = Checkpoint::setDir(cpt_dir);
+    if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
+            fatal("couldn't mkdir %s\n", dir);
 
-    if (serialize_cycle > 0)
-        Checkpoint::setup(serialize_cycle, serialize_period);
+    string cpt_file = dir + Checkpoint::baseFilename;
+    ofstream outstream(cpt_file.c_str());
+    time_t t = time(NULL);
+    if (!outstream.is_open())
+        fatal("Unable to open file %s for writing\n", cpt_file.c_str());
+    outstream << "## checkpoint generated: " << ctime(&t);
 
-    Serializable::ckptMaxCount = serialize_count;
+    globals.serialize(outstream);
+    SimObject::serializeAll(outstream);
 }
 
 void
-debug_serialize()
+Serializable::unserializeGlobals(Checkpoint *cp)
 {
-    Serializable::serializeAll();
+    globals.unserialize(cp);
 }
 
 void
-debug_serialize(Tick when)
+debug_serialize(const string &cpt_dir)
 {
-    new SerializeEvent(when, 0);
+    Serializable::serializeAll(cpt_dir);
 }
 
+
 ////////////////////////////////////////////////////////////////////////
 //
 // SerializableClass member definitions
@@ -384,32 +474,26 @@ debug_serialize(Tick when)
 // Need to make this a pointer so we can force initialization on the
 // first reference; otherwise, some SerializableClass constructors
 // may be invoked before the classMap constructor.
-map<string,SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
+map<string, SerializableClass::CreateFunc> *SerializableClass::classMap = 0;
 
 // SerializableClass constructor: add mapping to classMap
 SerializableClass::SerializableClass(const string &className,
-                                       CreateFunc createFunc)
+                                     CreateFunc createFunc)
 {
     if (classMap == NULL)
-        classMap = new map<string,SerializableClass::CreateFunc>();
+        classMap = new map<string, SerializableClass::CreateFunc>();
 
     if ((*classMap)[className])
-    {
-        cerr << "Error: simulation object class " << className << " redefined"
-             << endl;
-        fatal("");
-    }
+        fatal("Error: simulation object class %s redefined\n", className);
 
     // add className --> createFunc to class map
     (*classMap)[className] = createFunc;
 }
 
-
 //
 //
 Serializable *
-SerializableClass::createObject(Checkpoint *cp,
-                                 const std::string &section)
+SerializableClass::createObject(Checkpoint *cp, const string &section)
 {
     string className;
 
@@ -434,7 +518,7 @@ SerializableClass::createObject(Checkpoint *cp,
 
 
 Serializable *
-Serializable::create(Checkpoint *cp, const std::string &section)
+Serializable::create(Checkpoint *cp, const string &section)
 {
     Serializable *object = SerializableClass::createObject(cp, section);
     object->unserialize(cp, section);
@@ -442,10 +526,33 @@ Serializable::create(Checkpoint *cp, const std::string &section)
 }
 
 
-Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
-    : db(new IniFile), basePath(path), cptDir(cpt_dir)
+const char *Checkpoint::baseFilename = "m5.cpt";
+
+string Checkpoint::currentDirectory;
+
+string
+Checkpoint::setDir(const string &name)
+{
+    // use csprintf to insert curTick into directory name if it
+    // appears to have a format placeholder in it.
+    currentDirectory = (name.find("%") != string::npos) ?
+        csprintf(name, curTick) : name;
+    if (currentDirectory[currentDirectory.size() - 1] != '/')
+        currentDirectory += "/";
+    return currentDirectory;
+}
+
+string
+Checkpoint::dir()
+{
+    return currentDirectory;
+}
+
+
+Checkpoint::Checkpoint(const string &cpt_dir)
+    : db(new IniFile), cptDir(setDir(cpt_dir))
 {
-    string filename = cpt_dir + "/" + Checkpoint::baseFilename;
+    string filename = cptDir + "/" + Checkpoint::baseFilename;
     if (!db->load(filename)) {
         fatal("Can't load checkpoint file '%s'\n", filename);
     }
@@ -453,31 +560,28 @@ Checkpoint::Checkpoint(const std::string &cpt_dir, const std::string &path)
 
 
 bool
-Checkpoint::find(const std::string &section, const std::string &entry,
-                 std::string &value)
+Checkpoint::find(const string &section, const string &entry, string &value)
 {
     return db->find(section, entry, value);
 }
 
 
 bool
-Checkpoint::findObj(const std::string &section, const std::string &entry,
-                    Serializable *&value)
+Checkpoint::findObj(const string &section, const string &entry,
+                    SimObject *&value)
 {
     string path;
 
     if (!db->find(section, entry, path))
         return false;
 
-    if ((value = objMap[path]) != NULL)
-        return true;
-
-    return false;
+    value = resolveSimObject(path);
+    return true;
 }
 
 
 bool
-Checkpoint::sectionExists(const std::string &section)
+Checkpoint::sectionExists(const string &section)
 {
     return db->sectionExists(section);
 }