From d85b26d65a345b8158ba9b5e95e30797bd8ad47e Mon Sep 17 00:00:00 2001 From: Steve Reinhardt Date: Wed, 28 Apr 2004 16:28:37 -0700 Subject: Minor enhancements to Python config stuff: - Add support for assigning NULL to SimObject pointers. In Python, this is a special value, distinct from None. - Initial, incomplete pass at regenerating C++ parameter code (declarations and INIT_PARAM macros) from .odesc files. util/config/m5config.py: - Add support for assigning NULL to SimObject pointers. In Python, this is a special value, distinct from None. - Initial, incomplete pass at regenerating C++ parameter code (declarations and INIT_PARAM macros) from .odesc files. --HG-- extra : convert_revision : d7ae8f32e30b3c0829fd1a60589dd998e2e0d0d7 --- util/config/m5config.py | 105 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 83 insertions(+), 22 deletions(-) (limited to 'util') diff --git a/util/config/m5config.py b/util/config/m5config.py index ea5d68504..9aa3e0387 100644 --- a/util/config/m5config.py +++ b/util/config/m5config.py @@ -99,7 +99,7 @@ import sys # ##################################################################### -# The metaclass for ConfigNode (and thus for everything that dervies +# The metaclass for ConfigNode (and thus for everything that derives # from ConfigNode, including SimObject). This class controls how new # classes that derive from ConfigNode are instantiated, and provides # inherited class behavior (just like a class controls how instances @@ -278,8 +278,8 @@ class ConfigNode(object): self._children[new_child._name] = new_child # operator overload for '+='. You can say "node += child" to add - # # a child that was created with parent=None. An early attempt - # at # playing with syntax; turns out not to be that useful. + # a child that was created with parent=None. An early attempt + # at playing with syntax; turns out not to be that useful. def __iadd__(self, new_child): if new_child._parent != None: raise AttributeError, \ @@ -335,6 +335,23 @@ class SimObject(ConfigNode): if value != None: print pname, '=', value + def _sim_code(cls): + name = cls.__name__ + param_names = cls._param_dict.keys() + param_names.sort() + code = "BEGIN_DECLARE_SIM_OBJECT_PARAMS(%s)\n" % name + decls = [" " + cls._param_dict[pname].sim_decl(pname) \ + for pname in param_names] + code += "\n".join(decls) + "\n" + code += "END_DECLARE_SIM_OBJECT_PARAMS(%s)\n\n" % name + code += "BEGIN_INIT_SIM_OBJECT_PARAMS(%s)\n" % name + inits = [" " + cls._param_dict[pname].sim_init(pname) \ + for pname in param_names] + code += ",\n".join(inits) + "\n" + code += "END_INIT_SIM_OBJECT_PARAMS(%s)\n\n" % name + return code + _sim_code = classmethod(_sim_code) + ##################################################################### # # Parameter description classes @@ -353,26 +370,41 @@ class SimObject(ConfigNode): # ##################################################################### -# Force parameter value (rhs of '=') to ptype (or None, which means -# not set). -def make_param_value(ptype, value): - # nothing to do if None or already correct type - if value == None or isinstance(value, ptype): - return value - # this type conversion will raise an exception if it's illegal - return ptype(value) +def isNullPointer(value): + return isinstance(value, NullSimObject) + +def isSimObjectType(ptype): + return issubclass(ptype, SimObject) # Regular parameter. class Param(object): # Constructor. E.g., Param(Int, "number of widgets", 5) def __init__(self, ptype, desc, default=None): self.ptype = ptype + self.ptype_name = self.ptype.__name__ self.desc = desc self.default = default - # Convert assigned value to appropriate type. + # Convert assigned value to appropriate type. Force parameter + # value (rhs of '=') to ptype (or None, which means not set). def make_value(self, value): - return make_param_value(self.ptype, value) + # nothing to do if None or already correct type. Also allow NULL + # pointer to be assigned where a SimObject is expected. + if value == None or isinstance(value, self.ptype) or \ + isNullPointer(value) and isSimObjectType(self.ptype): + return value + # this type conversion will raise an exception if it's illegal + return self.ptype(value) + + def sim_decl(self, name): + return 'Param<%s> %s;' % (self.ptype_name, name) + + def sim_init(self, name): + if self.default == None: + return 'INIT_PARAM(%s, "%s")' % (name, self.desc) + else: + return 'INIT_PARAM_DFLT(%s, "%s", %s)' % \ + (name, self.desc, str(self.default)) # The _VectorParamValue class is a wrapper for vector-valued # parameters. The leading underscore indicates that users shouldn't @@ -391,12 +423,12 @@ class _VectorParamValue(object): # Vector-valued parameter description. Just like Param, except that # the value is a vector (list) of the specified type instead of a # single value. -class VectorParam(object): - # Constructor. The resulting parameter will be a list of ptype. +class VectorParam(Param): + + # Inherit Param constructor. However, the resulting parameter + # will be a list of ptype rather than a single element of ptype. def __init__(self, ptype, desc, default=None): - self.ptype = ptype - self.desc = desc - self.default = default + Param.__init__(self, ptype, desc, default) # Convert assigned value to appropriate type. If the RHS is not a # list or tuple, it generates a single-element list. @@ -404,14 +436,18 @@ class VectorParam(object): if value == None: return value if isinstance(value, list) or isinstance(value, tuple): # list: coerce each element into new list - val_list = [make_param_value(self.ptype, v) for v in - iter(value)] + val_list = [Param.make_value(self, v) for v in iter(value)] else: # singleton: coerce & wrap in a list - val_list = [ make_param_value(self.ptype, value) ] + val_list = [Param.make_value(self, value)] # wrap list in _VectorParamValue (see above) return _VectorParamValue(val_list) + def sim_decl(self, name): + return 'VectorParam<%s> %s;' % (self.ptype_name, name) + + # sim_init inherited from Param + ##################################################################### # # Parameter Types @@ -498,6 +534,19 @@ class String(object): def __str__(self): return self.value +# Special class for NULL pointers. Note the special check in +# make_param_value() above that lets these be assigned where a +# SimObject is required. +class NullSimObject(object): + # Constructor. No parameters, nothing to do. + def __init__(self): + pass + + def __str__(self): + return "NULL" + +# The only instance you'll ever need... +NULL = NullSimObject() # Enumerated types are a little more complex. The user specifies the # type as Enum(foo) where foo is either a list or dictionary of @@ -673,7 +722,9 @@ def def_class(path): sys.exit(1) if not odesc_loaded[parent]: def_class(odesc_file[parent]) - # define the class. + # define the class. The _name attribute of the class lets us + # track the actual SimObject class name even when we derive new + # subclasses in scripts (to provide new parameter value settings). s = "class %s(%s): _name = '%s'" % (obj, parent, obj) try: # execute in global namespace, so new class will be globally @@ -730,14 +781,24 @@ for objname, path in odesc_file.iteritems(): if not odesc_loaded[objname]: def_class(path) +sim_object_list = odesc_loaded.keys() +sim_object_list.sort() + # Iterate through files again and load parameters. for path in odesc_file.itervalues(): def_params(path) ##################################################################### +# Hook to generate C++ parameter code. +def gen_sim_code(file): + for objname in sim_object_list: + print >> file, eval("%s._sim_code()" % objname) + # The final hook to generate .ini files. Called from configuration # script once config is built. def instantiate(*objs): for obj in objs: obj._instantiate() + + -- cgit v1.2.3