sim: Generalize the arrayParamOut and arrayParamIn functions.
authorGabe Black <gabe.black@gmail.com>
Wed, 21 Oct 2020 04:11:53 +0000 (21:11 -0700)
committerGabe Black <gabe.black@gmail.com>
Thu, 22 Oct 2020 22:00:38 +0000 (22:00 +0000)
These had been written specifically for the vector, list, set, and C
style array types. This change reworks them to share an implementation,
and to work with more general types. The arrayParamOut method requires
std::begin() and std::end() to accept that type, and the arrayParamIn
method requires either insert or push_back, or the type to be an array.

Also fix up a couple of files which accidentally depended on includes in
the serialize headers which are no longer necessary.

Change-Id: I6ec4fe3bb900603bbb4e35c4efa620c249942452
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/36277
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/sim/fd_array.hh
src/sim/serialize.cc
src/sim/serialize.hh
src/sim/system.hh

index 5b9265d37057774c93a46caf3e021e8ae65fc622..5295566471e788bba25e37d21b48d3956daeb375 100644 (file)
@@ -35,6 +35,7 @@
 #define __FD_ARRAY_HH__
 
 #include <array>
+#include <map>
 #include <memory>
 #include <string>
 
index 5aa933d2e38e583ed327aa3e0de095c796b8bb32..e502d9aa77d0b90ec96720949fa9a38eaffc819c 100644 (file)
@@ -49,6 +49,7 @@
 #include <cerrno>
 #include <fstream>
 #include <list>
+#include <set>
 #include <string>
 #include <vector>
 
index 6c06eeb25c918a790349a568071a9e4d38d5b469..22c40aac0331d2349ba83d8b3b09c105ea03e499 100644 (file)
 
 #include <algorithm>
 #include <iostream>
-#include <list>
-#include <map>
+#include <iterator>
 #include <stack>
-#include <set>
+#include <type_traits>
 #include <vector>
 
 #include "base/bitunion.hh"
@@ -524,18 +523,18 @@ paramIn(CheckpointIn &cp, const std::string &name, T &param)
 /**
  * @ingroup api_serialize
  */
-template <class T>
+template <class InputIterator>
 void
 arrayParamOut(CheckpointOut &os, const std::string &name,
-              const std::vector<T> &param)
+              InputIterator start, InputIterator end)
 {
-    typename std::vector<T>::size_type size = param.size();
     os << name << "=";
-    if (size > 0)
-        showParam(os, param[0]);
-    for (typename std::vector<T>::size_type i = 1; i < size; ++i) {
+    auto it = start;
+    if (it != end)
+        showParam(os, *it++);
+    while (it != end) {
         os << " ";
-        showParam(os, param[i]);
+        showParam(os, *it++);
     }
     os << "\n";
 }
@@ -544,45 +543,14 @@ arrayParamOut(CheckpointOut &os, const std::string &name,
  * @ingroup api_serialize
  */
 template <class T>
-void
+decltype(std::begin(std::declval<const T&>()),
+         std::end(std::declval<const T&>()), void())
 arrayParamOut(CheckpointOut &os, const std::string &name,
-              const std::list<T> &param)
+              const T &param)
 {
-    typename std::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";
+    arrayParamOut(os, name, std::begin(param), std::end(param));
 }
 
-/**
- * @ingroup api_serialize
- */
-template <class T>
-void
-arrayParamOut(CheckpointOut &os, const std::string &name,
-              const std::set<T> &param)
-{
-    typename std::set<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";
-}
 
 /**
  * @ingroup api_serialize
@@ -592,14 +560,7 @@ void
 arrayParamOut(CheckpointOut &os, const std::string &name,
               const T *param, unsigned size)
 {
-    os << name << "=";
-    if (size > 0)
-        showParam(os, param[0]);
-    for (unsigned i = 1; i < size; ++i) {
-        os << " ";
-        showParam(os, param[i]);
-    }
-    os << "\n";
+    arrayParamOut(os, name, param, param + size);
 }
 
 /**
@@ -613,48 +574,28 @@ arrayParamOut(CheckpointOut &os, const std::string &name,
  *
  * @ingroup api_serialize
  */
-template <class T>
+
+template <class T, class InsertIterator>
 void
 arrayParamIn(CheckpointIn &cp, const std::string &name,
-             T *param, unsigned size)
+             InsertIterator inserter, ssize_t fixed_size=-1)
 {
-    const std::string &section(Serializable::currentSection());
+    const std::string &section = Serializable::currentSection();
     std::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...
+    fatal_if(!cp.find(section, name, str),
+        "Can't unserialize '%s:%s'.", section, name);
 
     std::vector<std::string> tokens;
-
     tokenize(tokens, str, ' ');
 
-    // Need this if we were doing a vector
-    // value.resize(tokens.size());
-
-    fatal_if(tokens.size() != size,
+    fatal_if(fixed_size >= 0 && tokens.size() != fixed_size,
              "Array size mismatch on %s:%s (Got %u, expected %u)'\n",
-             section, name, tokens.size(), size);
-
-    for (std::vector<std::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;
-        if (!parseParam(tokens[i], scalar_value)) {
-            std::string err("could not parse \"");
-
-            err += str;
-            err += "\"";
-
-            fatal(err);
-        }
+             section, name, tokens.size(), fixed_size);
 
-        // assign parsed value to vector
-        param[i] = scalar_value;
+    for (const auto &token: tokens) {
+        T value;
+        fatal_if(!parseParam(token, value), "Could not parse \"%s\".", str);
+        *inserter = value;
     }
 }
 
@@ -662,78 +603,25 @@ arrayParamIn(CheckpointIn &cp, const std::string &name,
  * @ingroup api_serialize
  */
 template <class T>
-void
-arrayParamIn(CheckpointIn &cp, const std::string &name, std::vector<T> &param)
+decltype(std::declval<T>().insert(std::declval<typename T::value_type>()),
+         void())
+arrayParamIn(CheckpointIn &cp, const std::string &name, T &param)
 {
-    const std::string &section(Serializable::currentSection());
-    std::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...
-
-    std::vector<std::string> tokens;
-
-    tokenize(tokens, str, ' ');
-
-    // Need this if we were doing a vector
-    // value.resize(tokens.size());
-
-    param.resize(tokens.size());
-
-    for (std::vector<std::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;
-        if (!parseParam(tokens[i], scalar_value)) {
-            std::string err("could not parse \"");
-
-            err += str;
-            err += "\"";
-
-            fatal(err);
-        }
-
-        // assign parsed value to vector
-        param[i] = scalar_value;
-    }
+    param.clear();
+    arrayParamIn<typename T::value_type>(
+            cp, name, std::inserter(param, param.begin()));
 }
 
 /**
  * @ingroup api_serialize
  */
 template <class T>
-void
-arrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> &param)
+decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()),
+         void())
+arrayParamIn(CheckpointIn &cp, const std::string &name, T &param)
 {
-    const std::string &section(Serializable::currentSection());
-    std::string str;
-    if (!cp.find(section, name, str)) {
-        fatal("Can't unserialize '%s:%s'\n", section, name);
-    }
     param.clear();
-
-    std::vector<std::string> tokens;
-    tokenize(tokens, str, ' ');
-
-    for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
-        T scalar_value;
-        if (!parseParam(tokens[i], scalar_value)) {
-            std::string err("could not parse \"");
-
-            err += str;
-            err += "\"";
-
-            fatal(err);
-        }
-
-        // assign parsed value to vector
-        param.push_back(scalar_value);
-    }
+    arrayParamIn<typename T::value_type>(cp, name, std::back_inserter(param));
 }
 
 /**
@@ -741,32 +629,16 @@ arrayParamIn(CheckpointIn &cp, const std::string &name, std::list<T> &param)
  */
 template <class T>
 void
-arrayParamIn(CheckpointIn &cp, const std::string &name, std::set<T> &param)
+arrayParamIn(CheckpointIn &cp, const std::string &name,
+             T *param, unsigned size)
 {
-    const std::string &section(Serializable::currentSection());
-    std::string str;
-    if (!cp.find(section, name, str)) {
-        fatal("Can't unserialize '%s:%s'\n", section, name);
-    }
-    param.clear();
-
-    std::vector<std::string> tokens;
-    tokenize(tokens, str, ' ');
+    struct ArrayInserter
+    {
+        T *data;
+        T &operator *() { return *data++; }
+    } insert_it{param};
 
-    for (std::vector<std::string>::size_type i = 0; i < tokens.size(); i++) {
-        T scalar_value;
-        if (!parseParam(tokens[i], scalar_value)) {
-            std::string err("could not parse \"");
-
-            err += str;
-            err += "\"";
-
-            fatal(err);
-        }
-
-        // assign parsed value to vector
-        param.insert(scalar_value);
-    }
+    arrayParamIn<T>(cp, name, insert_it, size);
 }
 
 void
index 4b446168664bb960fe6a3705a6b4b40a074ed461..4954af68f44e0664d6894a0d8bfb6e96a719db8e 100644 (file)
@@ -42,6 +42,7 @@
 #ifndef __SYSTEM_HH__
 #define __SYSTEM_HH__
 
+#include <set>
 #include <string>
 #include <unordered_map>
 #include <utility>