changeset ed97f6f2ed7a in /z/repo/gem5
details: http://repo.gem5.org/gem5?cmd=changeset;node=ed97f6f2ed7a
description:
        config: Add hooks to enable new config sys

        This patch adds helper functions to SimObject.py, params.py and
        simulate.py to enable the new configuration system.  Functions like
        enumerateParams() in SimObject lets the config system auto-generate
        command line options for simobjects to be modified on the command
        line.

        Params in params.py have __call__() added
        to their definition to allow the argparse module to use them
        as a type to check command input is in the proper format.

diffstat:

 src/python/m5/SimObject.py |  110 ++++++++++++++++++++++++-
 src/python/m5/params.py    |  195 +++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 297 insertions(+), 8 deletions(-)

diffs (truncated from 666 to 300 lines):

diff -r d4090f0cab30 -r ed97f6f2ed7a src/python/m5/SimObject.py
--- a/src/python/m5/SimObject.py        Sun Aug 10 05:39:04 2014 -0400
+++ b/src/python/m5/SimObject.py        Sun Aug 10 05:39:13 2014 -0400
@@ -172,6 +172,7 @@
 
         # class or instance attributes
         cls._values = multidict()   # param values
+        cls._hr_values = multidict() # human readable param values
         cls._children = multidict() # SimObject children
         cls._port_refs = multidict() # port ref objects
         cls._instantiated = False # really instantiated, cloned, or subclassed
@@ -197,6 +198,7 @@
             cls._params.parent = base._params
             cls._ports.parent = base._ports
             cls._values.parent = base._values
+            cls._hr_values.parent = base._hr_values
             cls._children.parent = base._children
             cls._port_refs.parent = base._port_refs
             # mark base as having been subclassed
@@ -273,6 +275,7 @@
     def _set_param(cls, name, value, param):
         assert(param.name == name)
         try:
+            hr_value = value
             value = param.convert(value)
         except Exception, e:
             msg = "%s\nError setting param %s.%s to %s\n" % \
@@ -284,6 +287,11 @@
         # it gets cloned properly when the class is instantiated
         if isSimObjectOrVector(value) and not value.has_parent():
             cls._add_cls_child(name, value)
+        # update human-readable values of the param if it has a literal
+        # value and is not an object or proxy.
+        if not (isSimObjectOrVector(value) or\
+                isinstance(value, m5.proxy.BaseProxy)):
+            cls._hr_values[name] = hr_value
 
     def _add_cls_child(cls, name, child):
         # It's a little funky to have a class as a parent, but these
@@ -585,6 +593,28 @@
 def isSimObjectOrVector(value):
     return False
 
+# This class holds information about each simobject parameter
+# that should be displayed on the command line for use in the
+# configuration system.
+class ParamInfo(object):
+  def __init__(self, type, desc, type_str, example, default_val, access_str):
+    self.type = type
+    self.desc = desc
+    self.type_str = type_str
+    self.example_str = example
+    self.default_val = default_val
+    # The string representation used to access this param through python.
+    # The method to access this parameter presented on the command line may
+    # be different, so this needs to be stored for later use.
+    self.access_str = access_str
+    self.created = True
+
+  # Make it so we can only set attributes at initialization time
+  # and effectively make this a const object.
+  def __setattr__(self, name, value):
+    if not "created" in self.__dict__:
+      self.__dict__[name] = value
+
 # The SimObject class is the root of the special hierarchy.  Most of
 # the code in this class deals with the configuration hierarchy itself
 # (parent/child node relationships).
@@ -621,6 +651,64 @@
     void startup();
 ''')
 
+    # Returns a dict of all the option strings that can be
+    # generated as command line options for this simobject instance
+    # by tracing all reachable params in the top level instance and
+    # any children it contains.
+    def enumerateParams(self, flags_dict = {},
+                        cmd_line_str = "", access_str = ""):
+        if hasattr(self, "_paramEnumed"):
+            print "Cycle detected enumerating params"
+        else:
+            self._paramEnumed = True
+            # Scan the children first to pick up all the objects in this SimObj
+            for keys in self._children:
+                child = self._children[keys]
+                next_cmdline_str = cmd_line_str + keys
+                next_access_str = access_str + keys
+                if not isSimObjectVector(child):
+                    next_cmdline_str = next_cmdline_str + "."
+                    next_access_str = next_access_str + "."
+                flags_dict = child.enumerateParams(flags_dict,
+                                                   next_cmdline_str,
+                                                   next_access_str)
+
+            # Go through the simple params in the simobject in this level
+            # of the simobject hierarchy and save information about the
+            # parameter to be used for generating and processing command line
+            # options to the simulator to set these parameters.
+            for keys,values in self._params.items():
+                if values.isCmdLineSettable():
+                    type_str = ''
+                    ex_str = values.example_str()
+                    ptype = None
+                    if isinstance(values, VectorParamDesc):
+                        type_str = 'Vector_%s' % values.ptype_str
+                        ptype = values
+                    else:
+                        type_str = '%s' % values.ptype_str
+                        ptype = values.ptype
+
+                    if keys in self._hr_values\
+                       and keys in self._values\
+                       and not isinstance(self._values[keys], 
m5.proxy.BaseProxy):
+                        cmd_str = cmd_line_str + keys
+                        acc_str = access_str + keys
+                        flags_dict[cmd_str] = ParamInfo(ptype,
+                                    self._params[keys].desc, type_str, ex_str,
+                                    values.pretty_print(self._hr_values[keys]),
+                                    acc_str)
+                    elif not keys in self._hr_values\
+                         and not keys in self._values:
+                        # Empty param
+                        cmd_str = cmd_line_str + keys
+                        acc_str = access_str + keys
+                        flags_dict[cmd_str] = ParamInfo(ptype,
+                                    self._params[keys].desc,
+                                    type_str, ex_str, '', acc_str)
+
+        return flags_dict
+
     # Initialize new instance.  For objects with SimObject-valued
     # children, we need to recursively clone the classes represented
     # by those param values as well in a consistent "deep copy"-style
@@ -661,6 +749,7 @@
         # individual value settings can be overridden but we still
         # inherit late changes to non-overridden class values.
         self._values = multidict(ancestor._values)
+        self._hr_values = multidict(ancestor._hr_values)
         # clone SimObject-valued parameters
         for key,val in ancestor._values.iteritems():
             val = tryAsSimObjectOrVector(val)
@@ -751,6 +840,7 @@
         param = self._params.get(attr)
         if param:
             try:
+                hr_value = value
                 value = param.convert(value)
             except Exception, e:
                 msg = "%s\nError setting param %s.%s to %s\n" % \
@@ -761,6 +851,13 @@
             # implicitly parent unparented objects assigned as params
             if isSimObjectOrVector(value) and not value.has_parent():
                 self.add_child(attr, value)
+            # set the human-readable value dict if this is a param
+            # with a literal value and is not being set as an object
+            # or proxy.
+            if not (isSimObjectOrVector(value) or\
+                    isinstance(value, m5.proxy.BaseProxy)):
+                self._hr_values[attr] = hr_value
+
             return
 
         # if RHS is a SimObject, it's an implicit child assignment
@@ -778,7 +875,13 @@
     def __getitem__(self, key):
         if key == 0:
             return self
-        raise TypeError, "Non-zero index '%s' to SimObject" % key
+        raise IndexError, "Non-zero index '%s' to SimObject" % key
+
+    # this hack allows us to iterate over a SimObject that may
+    # not be a vector, so we can call a loop over it and get just one
+    # element.
+    def __len__(self):
+        return 1
 
     # Also implemented by SimObjectVector
     def clear_parent(self, old_parent):
@@ -1054,8 +1157,9 @@
             # Cycles in the configuration hierarchy are not supported. This
             # will catch the resulting recursion and stop.
             self._ccObject = -1
-            params = self.getCCParams()
-            self._ccObject = params.create()
+            if not self.abstract:
+                params = self.getCCParams()
+                self._ccObject = params.create()
         elif self._ccObject == -1:
             raise RuntimeError, "%s: Cycle found in configuration hierarchy." \
                   % self.path()
diff -r d4090f0cab30 -r ed97f6f2ed7a src/python/m5/params.py
--- a/src/python/m5/params.py   Sun Aug 10 05:39:04 2014 -0400
+++ b/src/python/m5/params.py   Sun Aug 10 05:39:13 2014 -0400
@@ -93,7 +93,7 @@
 # parameters.
 class ParamValue(object):
     __metaclass__ = MetaParamValue
-
+    cmd_line_settable = False
 
     # Generate the code needed as a prerequisite for declaring a C++
     # object of this type.  Typically generates one or more #include
@@ -119,6 +119,10 @@
     def unproxy(self, base):
         return self
 
+    # Produce a human readable version of the stored value
+    def pretty_print(self, value):
+        return str(value)
+
 # Regular parameter description.
 class ParamDesc(object):
     def __init__(self, ptype_str, ptype, *args, **kwargs):
@@ -162,6 +166,19 @@
         raise AttributeError, "'%s' object has no attribute '%s'" % \
               (type(self).__name__, attr)
 
+    def example_str(self):
+        if hasattr(self.ptype, "ex_str"):
+            return self.ptype.ex_str
+        else:
+            return self.ptype_str
+
+    # Is the param available to be exposed on the command line
+    def isCmdLineSettable(self):
+        if hasattr(self.ptype, "cmd_line_settable"):
+            return self.ptype.cmd_line_settable
+        else:
+            return False
+
     def convert(self, value):
         if isinstance(value, proxy.BaseProxy):
             value.set_param_desc(self)
@@ -176,6 +193,13 @@
             return value
         return self.ptype(value)
 
+    def pretty_print(self, value):
+        if isinstance(value, proxy.BaseProxy):
+           return str(value)
+        if isNullPointer(value):
+           return NULL
+        return self.ptype(value).pretty_print(value)
+
     def cxx_predecls(self, code):
         code('#include <cstddef>')
         self.ptype.cxx_predecls(code)
@@ -260,6 +284,26 @@
         value.set_parent(val.get_parent(), val._name)
         super(SimObjectVector, self).__setitem__(key, value)
 
+    # Enumerate the params of each member of the SimObject vector. Creates
+    # strings that will allow indexing into the vector by the python code and
+    # allow it to be specified on the command line.
+    def enumerateParams(self, flags_dict = {},
+                        cmd_line_str = "",
+                        access_str = ""):
+        if hasattr(self, "_paramEnumed"):
+            print "Cycle detected enumerating params at %s?!" % (cmd_line_str)
+        else:
+            x = 0
+            for vals in self:
+                # Each entry in the SimObjectVector should be an
+                # instance of a SimObject
+                flags_dict = vals.enumerateParams(flags_dict,
+                                                  cmd_line_str + "%d." % x,
+                                                  access_str + "[%d]." % x)
+                x = x + 1
+
+        return flags_dict
+
 class VectorParamDesc(ParamDesc):
     # Convert assigned value to appropriate type.  If the RHS is not a
     # list or tuple, it generates a single-element list.
@@ -276,6 +320,39 @@
         else:
             return VectorParamValue(tmp_list)
 
+    # Produce a human readable example string that describes
+    # how to set this vector parameter in the absence of a default
+    # value.
+    def example_str(self):
+        s = super(VectorParamDesc, self).example_str()
+        help_str = "[" + s + "," + s + ", ...]"
+        return help_str
+
+    # Produce a human readable representation of the value of this vector 
param.
+    def pretty_print(self, value):
+        if isinstance(value, (list, tuple)):
+            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
+        elif isinstance(value, str):
+            tmp_list = [ ParamDesc.pretty_print(self, v) for v in 
value.split(',') ]
+        else:
+            tmp_list = [ ParamDesc.pretty_print(self, value) ]
+
+        return tmp_list
+
+    # This is a helper function for the new config system
+    def __call__(self, value):
+        if isinstance(value, (list, tuple)):
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to