diff options
Diffstat (limited to 'sim/pyconfig/m5config.py')
-rw-r--r-- | sim/pyconfig/m5config.py | 131 |
1 files changed, 100 insertions, 31 deletions
diff --git a/sim/pyconfig/m5config.py b/sim/pyconfig/m5config.py index 4e2a377b0..4e3a4103c 100644 --- a/sim/pyconfig/m5config.py +++ b/sim/pyconfig/m5config.py @@ -26,14 +26,14 @@ from __future__ import generators import os, re, sys, types +noDot = False +try: + import pydot +except: + noDot = True env = {} env.update(os.environ) -def defined(key): - return env.has_key(key) - -def define(key, value = True): - env[key] = value def panic(*args, **kwargs): sys.exit(*args, **kwargs) @@ -59,9 +59,6 @@ class Singleton(type): cls._instance = super(Singleton, cls).__call__(*args, **kwargs) return cls._instance -if os.environ.has_key('FULL_SYSTEM'): - FULL_SYSTEM = True - ##################################################################### # # M5 Python Configuration Utility @@ -209,6 +206,17 @@ def isSimObjSequence(value): return True +def isParamContext(value): + try: + return issubclass(value, ParamContext) + except: + return False + + +class_decorator = '_M5M5_SIMOBJECT_' +expr_decorator = '_M5M5_EXPRESSION_' +dot_decorator = '_M5M5_DOT_' + # 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 @@ -218,7 +226,6 @@ def isSimObjSequence(value): class MetaConfigNode(type): keywords = { 'abstract' : types.BooleanType, 'check' : types.FunctionType, - '_init' : types.FunctionType, 'type' : (types.NoneType, types.StringType) } # __new__ is called before __init__, and is where the statements @@ -234,6 +241,11 @@ class MetaConfigNode(type): '_disable' : {} } for key,val in dict.items(): + del dict[key] + + if key.startswith(expr_decorator): + key = key[len(expr_decorator):] + if mcls.keywords.has_key(key): if not isinstance(val, mcls.keywords[key]): raise TypeError, \ @@ -243,11 +255,9 @@ class MetaConfigNode(type): if isinstance(val, types.FunctionType): val = classmethod(val) priv[key] = val - del dict[key] elif key.startswith('_'): priv[key] = val - del dict[key] elif not isNullPointer(val) and isConfigNode(val): dict[key] = val() @@ -255,19 +265,22 @@ class MetaConfigNode(type): elif isSimObjSequence(val): dict[key] = [ v() for v in val ] + else: + dict[key] = val + # If your parent has a value in it that's a config node, clone it. for base in bases: if not isConfigNode(base): continue - for name,value in base._values.iteritems(): - if dict.has_key(name): + for key,value in base._values.iteritems(): + if dict.has_key(key): continue if isConfigNode(value): - priv['_values'][name] = value() + priv['_values'][key] = value() elif isSimObjSequence(value): - priv['_values'][name] = [ val() for val in value ] + priv['_values'][key] = [ val() for val in value ] # entries left in dict will get passed to __init__, where we'll # deal with them as params. @@ -281,12 +294,12 @@ class MetaConfigNode(type): cls._bases = [c for c in cls.__mro__ if isConfigNode(c)] # initialize attributes with values from class definition - for pname,value in dict.iteritems(): - setattr(cls, pname, value) - - if hasattr(cls, '_init'): - cls._init() - del cls._init + for key,value in dict.iteritems(): + key = key.split(dot_decorator) + c = cls + for item in key[:-1]: + c = getattr(c, item) + setattr(c, key[-1], value) def _isvalue(cls, name): for c in cls._bases: @@ -378,7 +391,6 @@ class MetaConfigNode(type): raise AttributeError, \ "object '%s' has no attribute '%s'" % (cls.__name__, cls) - # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(cls, attr, value): @@ -435,7 +447,7 @@ class MetaConfigNode(type): # Print instance info to .ini file. def instantiate(cls, name, parent = None): - instance = Node(name, cls, cls.type, parent) + instance = Node(name, cls, cls.type, parent, isParamContext(cls)) if hasattr(cls, 'check'): cls.check() @@ -456,7 +468,11 @@ class MetaConfigNode(type): if cls._getdisable(pname): continue - value = cls._getvalue(pname) + try: + value = cls._getvalue(pname) + except: + print 'Error getting %s' % pname + raise if isConfigNode(value): value = instance.child_objects[value] @@ -533,6 +549,9 @@ class ConfigNode(object): # v = param.convert(value) # object.__setattr__(self, attr, v) +class ParamContext(ConfigNode): + pass + # SimObject is a minimal extension of ConfigNode, implementing a # hierarchy node that corresponds to an M5 SimObject. It prints out a # "type=" line to indicate its SimObject class, prints out the @@ -569,7 +588,7 @@ class NodeParam(object): class Node(object): all = {} - def __init__(self, name, realtype, type, parent): + def __init__(self, name, realtype, type, parent, paramcontext): self.name = name self.realtype = realtype self.type = type @@ -580,6 +599,7 @@ class Node(object): self.top_child_names = {} self.params = [] self.param_names = {} + self.paramcontext = paramcontext path = [ self.name ] node = self.parent @@ -642,7 +662,7 @@ class Node(object): % (self.name, ptype, value._path) found, done = obj.find(ptype, value._path) if isinstance(found, Proxy): - done = false + done = False obj = obj.parent return found @@ -678,7 +698,8 @@ class Node(object): # instantiate children in same order they were added for # backward compatibility (else we can end up with cpu1 # before cpu0). - print 'children =', ' '.join([ c.name for c in self.children]) + children = [ c.name for c in self.children if not c.paramcontext] + print 'children =', ' '.join(children) for param in self.params: try: @@ -699,6 +720,48 @@ class Node(object): for c in self.children: c.display() + # print type and parameter values to .ini file + def outputDot(self, dot): + + + label = "{%s|" % self.path + if isSimObject(self.realtype): + label += '%s|' % self.type + + if self.children: + # instantiate children in same order they were added for + # backward compatibility (else we can end up with cpu1 + # before cpu0). + for c in self.children: + dot.add_edge(pydot.Edge(self.path,c.path, style="bold")) + + simobjs = [] + for param in self.params: + try: + if param.value is None: + raise AttributeError, 'Parameter with no value' + + value = param.convert(param.value) + string = param.string(value) + except: + print 'exception in %s:%s' % (self.name, param.name) + raise + ptype = eval(param.ptype) + if isConfigNode(ptype) and string != "Null": + simobjs.append(string) + else: + label += '%s = %s\\n' % (param.name, string) + + for so in simobjs: + label += "|<%s> %s" % (so, so) + dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w")) + label += '}' + dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) + + # recursively dump out children + for c in self.children: + c.outputDot(dot) + def _string(cls, value): if not isinstance(value, Node): raise AttributeError, 'expecting %s got %s' % (Node, value) @@ -1196,12 +1259,9 @@ class Enum(type): # "Constants"... handy aliases for various values. # -# For compatibility with C++ bool constants. -false = False -true = True - # Some memory range specifications use this as a default upper bound. MAX_ADDR = Addr._max +MaxTick = Tick._max # For power-of-two sizing, e.g. 64*K gives an integer value 65536. K = 1024 @@ -1234,6 +1294,15 @@ def instantiate(root): instance = root.instantiate('root') instance.fixup() instance.display() + if not noDot: + dot = pydot.Dot() + instance.outputDot(dot) + dot.orientation = "portrait" + dot.size = "8.5,11" + dot.ranksep="equally" + dot.rank="samerank" + dot.write("config.dot") + dot.write_ps("config.ps") from objects import * |