Automated merge with ssh://repo.gem5.org/gem5
[gem5.git] / src / sim / serialize.cc
index f73fc93a33e8287fe3379d4dd9ab517641e6d8d0..03f900837dc4c9374ece271491823f9ca4e98c34 100644 (file)
  *          Steve Reinhardt
  */
 
+#include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <errno.h>
 
+#include <cerrno>
 #include <fstream>
 #include <list>
 #include <string>
@@ -93,6 +93,14 @@ showParam(ostream &os, const char &value)
 }
 
 
+template <>
+void
+showParam(ostream &os, const signed char &value)
+{
+    os << (int)value;
+}
+
+
 template <>
 void
 showParam(ostream &os, const unsigned char &value)
@@ -182,17 +190,34 @@ template <class T>
 void
 arrayParamOut(ostream &os, const string &name, const vector<T> &param)
 {
-    int size = param.size();
+    typename vector<T>::size_type size = param.size();
     os << name << "=";
     if (size > 0)
         showParam(os, param[0]);
-    for (int i = 1; i < size; ++i) {
+    for (typename vector<T>::size_type i = 1; i < size; ++i) {
         os << " ";
         showParam(os, param[i]);
     }
     os << "\n";
 }
 
+template <class T>
+void
+arrayParamOut(ostream &os, const string &name, const list<T> &param)
+{
+    typename list<T>::const_iterator it = param.begin();
+
+    os << name << "=";
+    if (param.size() > 0)
+        showParam(os, *it);
+    it++;
+    while (it != param.end()) {
+        os << " ";
+        showParam(os, *it);
+        it++;
+    }
+    os << "\n";
+}
 
 template <class T>
 void
@@ -204,15 +229,27 @@ paramIn(Checkpoint *cp, const string &section, const string &name, T &param)
     }
 }
 
+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 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]);
     }
@@ -223,7 +260,7 @@ arrayParamOut(ostream &os, const string &name, const T *param, int size)
 template <class T>
 void
 arrayParamIn(Checkpoint *cp, const string &section, const string &name,
-             T *param, int size)
+             T *param, unsigned size)
 {
     string str;
     if (!cp->find(section, name, str)) {
@@ -244,12 +281,12 @@ arrayParamIn(Checkpoint *cp, const string &section, const string &name,
         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 \"");
 
@@ -286,12 +323,12 @@ arrayParamIn(Checkpoint *cp, const string &section,
 
     param.resize(tokens.size());
 
-    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 \"");
 
@@ -306,6 +343,35 @@ arrayParamIn(Checkpoint *cp, const string &section,
     }
 }
 
+template <class T>
+void
+arrayParamIn(Checkpoint *cp, const string &section,
+             const string &name, list<T> &param)
+{
+    string str;
+    if (!cp->find(section, name, str)) {
+        fatal("Can't unserialize '%s:%s'\n", section, name);
+    }
+    param.clear();
+
+    vector<string> tokens;
+    tokenize(tokens, str, ' ');
+
+    for (vector<string>::size_type i = 0; i < tokens.size(); i++) {
+        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.push_back(scalar_value);
+    }
+}
 
 
 void
@@ -324,19 +390,29 @@ 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, int size);                             \
+              type const *param, unsigned size);                        \
 template void                                                           \
 arrayParamIn(Checkpoint *cp, const string &section,                     \
-             const string &name, type *param, int size);                \
+             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);
+             const string &name, vector<type> &param);                  \
+template void                                                           \
+arrayParamOut(ostream &os, const string &name,                          \
+              const list<type> &param);                                 \
+template void                                                           \
+arrayParamIn(Checkpoint *cp, const string &section,                     \
+             const string &name, list<type> &param);
 
+INSTANTIATE_PARAM_TEMPLATES(char)
 INSTANTIATE_PARAM_TEMPLATES(signed char)
 INSTANTIATE_PARAM_TEMPLATES(unsigned char)
 INSTANTIATE_PARAM_TEMPLATES(signed short)
@@ -378,7 +454,7 @@ void
 Globals::serialize(ostream &os)
 {
     nameOut(os);
-    SERIALIZE_SCALAR(curTick);
+    paramOut(os, "curTick", curTick());
 
     nameOut(os, "MainEventQueue");
     mainEventQueue.serialize(os);
@@ -388,7 +464,9 @@ void
 Globals::unserialize(Checkpoint *cp)
 {
     const string &section = name();
-    UNSERIALIZE_SCALAR(curTick);
+    Tick tick;
+    paramIn(cp, section, "curTick", tick);
+    curTick(tick);
 
     mainEventQueue.unserialize(cp, "MainEventQueue");
 }
@@ -414,8 +492,7 @@ Serializable::unserialize(Checkpoint *cp, const string &section)
 void
 Serializable::serializeAll(const string &cpt_dir)
 {
-    setCheckpointDir(cpt_dir);
-    string dir = Checkpoint::dir();
+    string dir = Checkpoint::setDir(cpt_dir);
     if (mkdir(dir.c_str(), 0775) == -1 && errno != EEXIST)
             fatal("couldn't mkdir %s\n", dir);
 
@@ -424,54 +501,18 @@ Serializable::serializeAll(const string &cpt_dir)
     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);
+    outstream << "## checkpoint generated: " << ctime(&t);
 
     globals.serialize(outstream);
     SimObject::serializeAll(outstream);
 }
 
-void
-Serializable::unserializeAll(const string &cpt_dir)
-{
-    setCheckpointDir(cpt_dir);
-    string dir = Checkpoint::dir();
-    string cpt_file = dir + Checkpoint::baseFilename;
-    string section = "";
-
-    DPRINTFR(Config, "Loading checkpoint dir '%s'\n",
-             dir);
-    Checkpoint *cp = new Checkpoint(dir, section);
-    unserializeGlobals(cp);
-    SimObject::unserializeAll(cp);
-}
-
 void
 Serializable::unserializeGlobals(Checkpoint *cp)
 {
     globals.unserialize(cp);
 }
 
-const char *Checkpoint::baseFilename = "m5.cpt";
-
-static string checkpointDirBase;
-
-void
-setCheckpointDir(const string &name)
-{
-    checkpointDirBase = name;
-    if (checkpointDirBase[checkpointDirBase.size() - 1] != '/')
-        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
 debug_serialize(const string &cpt_dir)
 {
@@ -541,10 +582,33 @@ Serializable::create(Checkpoint *cp, const string &section)
 }
 
 
-Checkpoint::Checkpoint(const string &cpt_dir, const 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);
     }