Added mmap start and end so detailed CPU can know if an access is
[gem5.git] / sim / param.cc
index 8284983a8b528a30fcd0e55333e9c1c152be35b8..ff023ce85f03985ccacf584ff922d490f4b554c4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * 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 <algorithm>
+#include <cassert>
+#include <cstdio>
 #include <list>
 #include <string>
 #include <vector>
-#include <stdio.h>     // for sscanf()
 
-#include <assert.h>
-
-#include "sim/param.hh"
-#include "sim/sim_object.hh"
 #include "base/inifile.hh"
-#include "sim/configfile.hh"
-#include "sim/config_node.hh"
 #include "base/misc.hh"
+#include "base/range.hh"
 #include "base/str.hh"
 #include "base/trace.hh"
+#include "sim/config_node.hh"
+#include "sim/configfile.hh"
+#include "sim/param.hh"
+#include "sim/sim_object.hh"
 
 using namespace std;
 
@@ -85,67 +85,76 @@ BaseParam::die(const string &err) const
 ////////////////////////////////////////////////////////////////////////
 
 //
-// Integer types all use to_number for parsing and '<<' for
-// displaying
+// The base implementations use to_number for parsing and '<<' for
+// displaying, suitable for integer types.
 //
-#define INT_PARAM(type)                                \
-bool                                           \
-parseParam(const string &s, type &value)       \
-{                                              \
-    return to_number(s, value);                        \
-}                                              \
-                                                \
-void                                           \
-showParam(ostream &os, type value)             \
-{                                              \
-    os << value;                               \
+template <class T>
+bool
+parseParam(const string &s, T &value)
+{
+    return to_number(s, value);
 }
 
-INT_PARAM(unsigned long long)
-INT_PARAM(signed long long)
-INT_PARAM(unsigned long)
-INT_PARAM(signed long)
-INT_PARAM(unsigned int)
-INT_PARAM(signed int)
-INT_PARAM(unsigned short)
-INT_PARAM(signed short)
-INT_PARAM(unsigned char)
-INT_PARAM(signed char)
-
-#undef INT_PARAM
+template <class T>
+void
+showParam(ostream &os, T const &value)
+{
+    os << value;
+}
 
 //
-// Floating-point types
+// 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 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);
 }
 
-void showParam(ostream &os, float value)  { os << value; }
-void showParam(ostream &os, double value) { os << value; }
-
-//
-// bool
-//
+// Be flexible about what we take for bool
+template <>
 bool
 parseParam(const string &s, bool &value)
 {
-    const string &lower = to_lower(s);
+    const string &ls = to_lower(s);
 
-    if (lower == "true" || lower == "t" || lower == "yes" || lower == "y") {
+    if (ls == "true" || ls == "t" || ls == "yes" || ls == "y" || ls == "1") {
         value = true;
         return true;
     }
 
-    if (lower == "false" || lower == "f" || lower == "no" || lower == "n") {
+    if (ls == "false" || ls == "f" || ls == "no" || ls == "n" || ls == "0") {
         value = false;
         return true;
     }
@@ -153,17 +162,17 @@ parseParam(const string &s, bool &value)
     return false;
 }
 
-
+// Display bools as strings
+template <>
 void
-showParam(ostream &os, bool value)
+showParam(ostream &os, const bool &value)
 {
     os << (value ? "true" : "false");
 }
 
 
-//
-// string
-//
+// String requires no processing to speak of
+template <>
 bool
 parseParam(const string &s, string &value)
 {
@@ -171,11 +180,20 @@ parseParam(const string &s, string &value)
     return true;
 }
 
+template <>
+bool
+parseParam(const string &s, Range<uint32_t> &value)
+{
+    value = s;
+    return value.valid();
+}
 
-void
-showParam(ostream &os, const string &value)
+template <>
+bool
+parseParam(const string &s, Range<uint64_t> &value)
 {
-    os << value;
+    value = s;
+    return value.valid();
 }
 
 //
@@ -209,6 +227,11 @@ template <class T>
 void
 VectorParam<T>::parse(const string &s)
 {
+    if (s.empty()) {
+        wasSet = true;
+        return;
+    }
+
     vector<string> tokens;
 
     tokenize(tokens, s, ' ');
@@ -274,6 +297,8 @@ template VectorParam<type>;
 // instantiate all four methods (parse/show, scalar/vector) for basic
 // types that can use the above templates
 #define INSTANTIATE_PARAM_TEMPLATES(type, typestr)                     \
+template bool parseParam<type>(const string &s, type &value);          \
+template void showParam<type>(ostream &os, type const &value);         \
 template void Param<type>::parse(const string &);                      \
 template void VectorParam<type>::parse(const string &);                        \
 template void Param<type>::showValue(ostream &) const;                 \
@@ -301,6 +326,9 @@ INSTANTIATE_PARAM_TEMPLATES(double, "double")
 INSTANTIATE_PARAM_TEMPLATES(bool, "bool")
 INSTANTIATE_PARAM_TEMPLATES(string, "string")
 
+INSTANTIATE_PARAM_TEMPLATES(Range<uint64_t>, "uint64 range")
+INSTANTIATE_PARAM_TEMPLATES(Range<uint32_t>, "uint32 range")
+
 #undef INSTANTIATE_PARAM_TEMPLATES
 
 //
@@ -413,6 +441,11 @@ EnumVectorParam<Map>::parse(const string &s)
 {
     vector<string> tokens;
 
+    if (s.empty()) {
+        wasSet = true;
+        return;
+    }
+
     tokenize(tokens, s, ' ');
 
     value.resize(tokens.size());
@@ -465,11 +498,11 @@ EnumVectorParam<Map>::showType(ostream &os) const
     showEnumType(os, map, num_values);
 }
 
-template EnumParam<const char *>;
-template EnumVectorParam<const char *>;
+template class EnumParam<const char *>;
+template class EnumVectorParam<const char *>;
 
-template EnumParam<EnumParamMap>;
-template EnumVectorParam<EnumParamMap>;
+template class EnumParam<EnumParamMap>;
+template class EnumVectorParam<EnumParamMap>;
 
 ////////////////////////////////////////////////////////////////////////
 //
@@ -551,15 +584,27 @@ SimObjectBaseParam::parse(const string &s, vector<SimObject *>&value)
 
 list<ParamContext *> *ParamContext::ctxList = NULL;
 
-ParamContext::ParamContext(const string &_iniSection, bool noAutoParse)
+ParamContext::ParamContext(const string &_iniSection, InitPhase _initPhase)
     : iniFilePtr(NULL),        // initialized on call to parseParams()
-      iniSection(_iniSection), paramList(NULL)
+      iniSection(_iniSection), paramList(NULL),
+      initPhase(_initPhase)
 {
-    if (!noAutoParse) {
+    // Put this context on global list for initialization
+    if (initPhase != NoAutoInit) {
         if (ctxList == NULL)
             ctxList = new list<ParamContext *>();
 
-        (*ctxList).push_back(this);
+        // keep list sorted by ascending initPhase values
+        list<ParamContext *>::iterator i = ctxList->begin();
+        list<ParamContext *>::iterator end = ctxList->end();
+        for (; i != end; ++i) {
+            if (initPhase <= (*i)->initPhase) {
+                // found where we want to insert
+                break;
+            }
+        }
+        // (fall through case: insert at end)
+        ctxList->insert(i, this);
     }
 }
 
@@ -581,9 +626,8 @@ ParamContext::parseParams(IniFile &iniFile)
     for (i = getParamList()->begin(); i != getParamList()->end(); ++i) {
         string string_value;
 
-        if (iniFile.findDefault(iniSection, (*i)->name, string_value)) {
+        if (iniFile.find(iniSection, (*i)->name, string_value))
             (*i)->parse(string_value);
-        }
     }
 }
 
@@ -659,18 +703,8 @@ ParamContext::printErrorProlog(ostream &os)
 // SimObjectBuilder objects, which return non-NULL for configNode()).
 //
 SimObject *
-ParamContext::resolveSimObject(const string &_name)
-{
-    // look for a colon
-    string::size_type i = _name.find(':');
-    string name = _name;
-    if (i != string::npos) {
-        // colon found: local object
-        // add as child to current node and create it
-        name = _name.substr(0, i);
-        string objConfigClassName = _name.substr(i + 1);
-        getConfigNode()->addChild(name, objConfigClassName);
-    }
+ParamContext::resolveSimObject(const string &name)
+{
     ConfigNode *n = getConfigNode();
     return n ? n->resolveSimObject(name) : NULL;
 }