SimObject.py revision 1438
113481Sgiacomo.travaglini@arm.com# Copyright (c) 2004 The Regents of The University of Michigan 213481Sgiacomo.travaglini@arm.com# All rights reserved. 313481Sgiacomo.travaglini@arm.com# 413481Sgiacomo.travaglini@arm.com# Redistribution and use in source and binary forms, with or without 513481Sgiacomo.travaglini@arm.com# modification, are permitted provided that the following conditions are 613481Sgiacomo.travaglini@arm.com# met: redistributions of source code must retain the above copyright 713481Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer; 813481Sgiacomo.travaglini@arm.com# redistributions in binary form must reproduce the above copyright 913481Sgiacomo.travaglini@arm.com# notice, this list of conditions and the following disclaimer in the 1013481Sgiacomo.travaglini@arm.com# documentation and/or other materials provided with the distribution; 1113481Sgiacomo.travaglini@arm.com# neither the name of the copyright holders nor the names of its 1213481Sgiacomo.travaglini@arm.com# contributors may be used to endorse or promote products derived from 1313481Sgiacomo.travaglini@arm.com# this software without specific prior written permission. 1413481Sgiacomo.travaglini@arm.com# 1513481Sgiacomo.travaglini@arm.com# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1613481Sgiacomo.travaglini@arm.com# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1713481Sgiacomo.travaglini@arm.com# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1813481Sgiacomo.travaglini@arm.com# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1913481Sgiacomo.travaglini@arm.com# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2013481Sgiacomo.travaglini@arm.com# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2113481Sgiacomo.travaglini@arm.com# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2213481Sgiacomo.travaglini@arm.com# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2313481Sgiacomo.travaglini@arm.com# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2413481Sgiacomo.travaglini@arm.com# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2513481Sgiacomo.travaglini@arm.com# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2613481Sgiacomo.travaglini@arm.com 2713481Sgiacomo.travaglini@arm.comfrom __future__ import generators 2813481Sgiacomo.travaglini@arm.comimport os, re, sys, types, inspect 2913481Sgiacomo.travaglini@arm.com 3013481Sgiacomo.travaglini@arm.comfrom importer import AddToPath, LoadMpyFile 3113481Sgiacomo.travaglini@arm.com 3213481Sgiacomo.travaglini@arm.comnoDot = False 3313481Sgiacomo.travaglini@arm.comtry: 3413481Sgiacomo.travaglini@arm.com import pydot 3513481Sgiacomo.travaglini@arm.comexcept: 3613481Sgiacomo.travaglini@arm.com noDot = True 3713481Sgiacomo.travaglini@arm.com 3813481Sgiacomo.travaglini@arm.comenv = {} 3913481Sgiacomo.travaglini@arm.comenv.update(os.environ) 4013481Sgiacomo.travaglini@arm.com 4113481Sgiacomo.travaglini@arm.comdef panic(string): 4213481Sgiacomo.travaglini@arm.com print >>sys.stderr, 'panic:', string 4313481Sgiacomo.travaglini@arm.com sys.exit(1) 4413481Sgiacomo.travaglini@arm.com 4513481Sgiacomo.travaglini@arm.comdef issequence(value): 4613481Sgiacomo.travaglini@arm.com return isinstance(value, tuple) or isinstance(value, list) 4713481Sgiacomo.travaglini@arm.com 4813481Sgiacomo.travaglini@arm.comclass Singleton(type): 4913481Sgiacomo.travaglini@arm.com def __call__(cls, *args, **kwargs): 5013481Sgiacomo.travaglini@arm.com if hasattr(cls, '_instance'): 5113481Sgiacomo.travaglini@arm.com return cls._instance 5213481Sgiacomo.travaglini@arm.com 5313481Sgiacomo.travaglini@arm.com cls._instance = super(Singleton, cls).__call__(*args, **kwargs) 5413481Sgiacomo.travaglini@arm.com return cls._instance 5513481Sgiacomo.travaglini@arm.com 5613481Sgiacomo.travaglini@arm.com##################################################################### 5713481Sgiacomo.travaglini@arm.com# 5813481Sgiacomo.travaglini@arm.com# M5 Python Configuration Utility 5913481Sgiacomo.travaglini@arm.com# 6013481Sgiacomo.travaglini@arm.com# The basic idea is to write simple Python programs that build Python 6113481Sgiacomo.travaglini@arm.com# objects corresponding to M5 SimObjects for the deisred simulation 6213481Sgiacomo.travaglini@arm.com# configuration. For now, the Python emits a .ini file that can be 6313481Sgiacomo.travaglini@arm.com# parsed by M5. In the future, some tighter integration between M5 6413481Sgiacomo.travaglini@arm.com# and the Python interpreter may allow bypassing the .ini file. 6513481Sgiacomo.travaglini@arm.com# 6613481Sgiacomo.travaglini@arm.com# Each SimObject class in M5 is represented by a Python class with the 6713481Sgiacomo.travaglini@arm.com# same name. The Python inheritance tree mirrors the M5 C++ tree 6813481Sgiacomo.travaglini@arm.com# (e.g., SimpleCPU derives from BaseCPU in both cases, and all 6913481Sgiacomo.travaglini@arm.com# SimObjects inherit from a single SimObject base class). To specify 7013481Sgiacomo.travaglini@arm.com# an instance of an M5 SimObject in a configuration, the user simply 7113481Sgiacomo.travaglini@arm.com# instantiates the corresponding Python object. The parameters for 7213481Sgiacomo.travaglini@arm.com# that SimObject are given by assigning to attributes of the Python 7313481Sgiacomo.travaglini@arm.com# object, either using keyword assignment in the constructor or in 7413481Sgiacomo.travaglini@arm.com# separate assignment statements. For example: 7513481Sgiacomo.travaglini@arm.com# 7613481Sgiacomo.travaglini@arm.com# cache = BaseCache('my_cache', root, size=64*K) 7713481Sgiacomo.travaglini@arm.com# cache.hit_latency = 3 7813481Sgiacomo.travaglini@arm.com# cache.assoc = 8 7913481Sgiacomo.travaglini@arm.com# 8013481Sgiacomo.travaglini@arm.com# (The first two constructor arguments specify the name of the created 8113481Sgiacomo.travaglini@arm.com# cache and its parent node in the hierarchy.) 8213481Sgiacomo.travaglini@arm.com# 8313481Sgiacomo.travaglini@arm.com# The magic lies in the mapping of the Python attributes for SimObject 8413481Sgiacomo.travaglini@arm.com# classes to the actual SimObject parameter specifications. This 8513481Sgiacomo.travaglini@arm.com# allows parameter validity checking in the Python code. Continuing 8613481Sgiacomo.travaglini@arm.com# the example above, the statements "cache.blurfl=3" or 8713481Sgiacomo.travaglini@arm.com# "cache.assoc='hello'" would both result in runtime errors in Python, 8813481Sgiacomo.travaglini@arm.com# since the BaseCache object has no 'blurfl' parameter and the 'assoc' 8913481Sgiacomo.travaglini@arm.com# parameter requires an integer, respectively. This magic is done 9013481Sgiacomo.travaglini@arm.com# primarily by overriding the special __setattr__ method that controls 9113481Sgiacomo.travaglini@arm.com# assignment to object attributes. 9213481Sgiacomo.travaglini@arm.com# 9313481Sgiacomo.travaglini@arm.com# The Python module provides another class, ConfigNode, which is a 9413481Sgiacomo.travaglini@arm.com# superclass of SimObject. ConfigNode implements the parent/child 9513481Sgiacomo.travaglini@arm.com# relationship for building the configuration hierarchy tree. 9613481Sgiacomo.travaglini@arm.com# Concrete instances of ConfigNode can be used to group objects in the 9713481Sgiacomo.travaglini@arm.com# hierarchy, but do not correspond to SimObjects themselves (like a 9813481Sgiacomo.travaglini@arm.com# .ini section with "children=" but no "type=". 9913481Sgiacomo.travaglini@arm.com# 10013481Sgiacomo.travaglini@arm.com# Once a set of Python objects have been instantiated in a hierarchy, 10113481Sgiacomo.travaglini@arm.com# calling 'instantiate(obj)' (where obj is the root of the hierarchy) 10213481Sgiacomo.travaglini@arm.com# will generate a .ini file. See simple-4cpu.py for an example 10313481Sgiacomo.travaglini@arm.com# (corresponding to m5-test/simple-4cpu.ini). 10413481Sgiacomo.travaglini@arm.com# 10513481Sgiacomo.travaglini@arm.com##################################################################### 10613481Sgiacomo.travaglini@arm.com 10713481Sgiacomo.travaglini@arm.com##################################################################### 10813481Sgiacomo.travaglini@arm.com# 10913481Sgiacomo.travaglini@arm.com# ConfigNode/SimObject classes 11013481Sgiacomo.travaglini@arm.com# 11113481Sgiacomo.travaglini@arm.com# The Python class hierarchy rooted by ConfigNode (which is the base 11213481Sgiacomo.travaglini@arm.com# class of SimObject, which in turn is the base class of all other M5 11313481Sgiacomo.travaglini@arm.com# SimObject classes) has special attribute behavior. In general, an 11413481Sgiacomo.travaglini@arm.com# object in this hierarchy has three categories of attribute-like 11513481Sgiacomo.travaglini@arm.com# things: 11613481Sgiacomo.travaglini@arm.com# 11713481Sgiacomo.travaglini@arm.com# 1. Regular Python methods and variables. These must start with an 11813481Sgiacomo.travaglini@arm.com# underscore to be treated normally. 11913481Sgiacomo.travaglini@arm.com# 12013481Sgiacomo.travaglini@arm.com# 2. SimObject parameters. These values are stored as normal Python 12113481Sgiacomo.travaglini@arm.com# attributes, but all assignments to these attributes are checked 12213481Sgiacomo.travaglini@arm.com# against the pre-defined set of parameters stored in the class's 12313481Sgiacomo.travaglini@arm.com# _params dictionary. Assignments to attributes that do not 12413481Sgiacomo.travaglini@arm.com# correspond to predefined parameters, or that are not of the correct 12513481Sgiacomo.travaglini@arm.com# type, incur runtime errors. 12613481Sgiacomo.travaglini@arm.com# 12713481Sgiacomo.travaglini@arm.com# 3. Hierarchy children. The child nodes of a ConfigNode are stored 12813481Sgiacomo.travaglini@arm.com# in the node's _children dictionary, but can be accessed using the 12913481Sgiacomo.travaglini@arm.com# Python attribute dot-notation (just as they are printed out by the 13013481Sgiacomo.travaglini@arm.com# simulator). Children cannot be created using attribute assigment; 13113481Sgiacomo.travaglini@arm.com# they must be added by specifying the parent node in the child's 13213481Sgiacomo.travaglini@arm.com# constructor or using the '+=' operator. 13313481Sgiacomo.travaglini@arm.com 13413481Sgiacomo.travaglini@arm.com# The SimObject parameters are the most complex, for a few reasons. 13513481Sgiacomo.travaglini@arm.com# First, both parameter descriptions and parameter values are 13613481Sgiacomo.travaglini@arm.com# inherited. Thus parameter description lookup must go up the 13713481Sgiacomo.travaglini@arm.com# inheritance chain like normal attribute lookup, but this behavior 13813481Sgiacomo.travaglini@arm.com# must be explicitly coded since the lookup occurs in each class's 13913481Sgiacomo.travaglini@arm.com# _params attribute. Second, because parameter values can be set 14013481Sgiacomo.travaglini@arm.com# on SimObject classes (to implement default values), the parameter 14113481Sgiacomo.travaglini@arm.com# checking behavior must be enforced on class attribute assignments as 14213481Sgiacomo.travaglini@arm.com# well as instance attribute assignments. Finally, because we allow 14313481Sgiacomo.travaglini@arm.com# class specialization via inheritance (e.g., see the L1Cache class in 14413481Sgiacomo.travaglini@arm.com# the simple-4cpu.py example), we must do parameter checking even on 14513481Sgiacomo.travaglini@arm.com# class instantiation. To provide all these features, we use a 14613481Sgiacomo.travaglini@arm.com# metaclass to define most of the SimObject parameter behavior for 14713481Sgiacomo.travaglini@arm.com# this class hierarchy. 14813481Sgiacomo.travaglini@arm.com# 14913481Sgiacomo.travaglini@arm.com##################################################################### 15013481Sgiacomo.travaglini@arm.com 15113481Sgiacomo.travaglini@arm.comclass Proxy(object): 15213481Sgiacomo.travaglini@arm.com def __init__(self, path = ()): 15313481Sgiacomo.travaglini@arm.com self._object = None 15413481Sgiacomo.travaglini@arm.com self._path = path 15513481Sgiacomo.travaglini@arm.com 15613481Sgiacomo.travaglini@arm.com def __getattr__(self, attr): 15713481Sgiacomo.travaglini@arm.com return Proxy(self._path + (attr, )) 15813481Sgiacomo.travaglini@arm.com 15913481Sgiacomo.travaglini@arm.com def __setattr__(self, attr, value): 16013481Sgiacomo.travaglini@arm.com if not attr.startswith('_'): 16113481Sgiacomo.travaglini@arm.com raise AttributeError, 'cannot set attribute %s' % attr 16213481Sgiacomo.travaglini@arm.com super(Proxy, self).__setattr__(attr, value) 16313481Sgiacomo.travaglini@arm.com 16413481Sgiacomo.travaglini@arm.com def _convert(self): 16513481Sgiacomo.travaglini@arm.com obj = self._object 16613481Sgiacomo.travaglini@arm.com for attr in self._path: 16713481Sgiacomo.travaglini@arm.com obj = obj.__getattribute__(attr) 16813481Sgiacomo.travaglini@arm.com return obj 16913481Sgiacomo.travaglini@arm.com 17013481Sgiacomo.travaglini@arm.comSuper = Proxy() 17113481Sgiacomo.travaglini@arm.com 17213481Sgiacomo.travaglini@arm.comdef isSubClass(value, cls): 17313481Sgiacomo.travaglini@arm.com try: 17413481Sgiacomo.travaglini@arm.com return issubclass(value, cls) 17513481Sgiacomo.travaglini@arm.com except: 17613481Sgiacomo.travaglini@arm.com return False 17713481Sgiacomo.travaglini@arm.com 17813481Sgiacomo.travaglini@arm.comdef isConfigNode(value): 17913481Sgiacomo.travaglini@arm.com try: 18013481Sgiacomo.travaglini@arm.com return issubclass(value, ConfigNode) 18113481Sgiacomo.travaglini@arm.com except: 18213481Sgiacomo.travaglini@arm.com return False 18313481Sgiacomo.travaglini@arm.com 18413481Sgiacomo.travaglini@arm.comdef isSimObject(value): 18513481Sgiacomo.travaglini@arm.com try: 18613481Sgiacomo.travaglini@arm.com return issubclass(value, SimObject) 18713481Sgiacomo.travaglini@arm.com except: 18813481Sgiacomo.travaglini@arm.com return False 18913481Sgiacomo.travaglini@arm.com 19013481Sgiacomo.travaglini@arm.comdef isSimObjSequence(value): 19113481Sgiacomo.travaglini@arm.com if not issequence(value): 19213481Sgiacomo.travaglini@arm.com return False 19313481Sgiacomo.travaglini@arm.com 19413481Sgiacomo.travaglini@arm.com for val in value: 19513481Sgiacomo.travaglini@arm.com if not isNullPointer(val) and not isConfigNode(val): 19613481Sgiacomo.travaglini@arm.com return False 19713481Sgiacomo.travaglini@arm.com 19813481Sgiacomo.travaglini@arm.com return True 19913481Sgiacomo.travaglini@arm.com 20013481Sgiacomo.travaglini@arm.comdef isParamContext(value): 20113481Sgiacomo.travaglini@arm.com try: 20213481Sgiacomo.travaglini@arm.com return issubclass(value, ParamContext) 20313481Sgiacomo.travaglini@arm.com except: 20413481Sgiacomo.travaglini@arm.com return False 20513481Sgiacomo.travaglini@arm.com 20613481Sgiacomo.travaglini@arm.com 20713481Sgiacomo.travaglini@arm.comclass_decorator = 'M5M5_SIMOBJECT_' 20813481Sgiacomo.travaglini@arm.comexpr_decorator = 'M5M5_EXPRESSION_' 20913481Sgiacomo.travaglini@arm.comdot_decorator = '_M5M5_DOT_' 21013481Sgiacomo.travaglini@arm.com 21113481Sgiacomo.travaglini@arm.com# The metaclass for ConfigNode (and thus for everything that derives 21213481Sgiacomo.travaglini@arm.com# from ConfigNode, including SimObject). This class controls how new 21313481Sgiacomo.travaglini@arm.com# classes that derive from ConfigNode are instantiated, and provides 21413481Sgiacomo.travaglini@arm.com# inherited class behavior (just like a class controls how instances 21513481Sgiacomo.travaglini@arm.com# of that class are instantiated, and provides inherited instance 21613481Sgiacomo.travaglini@arm.com# behavior). 21713481Sgiacomo.travaglini@arm.comclass MetaConfigNode(type): 21813481Sgiacomo.travaglini@arm.com # Attributes that can be set only at initialization time 21913481Sgiacomo.travaglini@arm.com init_keywords = {} 22013481Sgiacomo.travaglini@arm.com # Attributes that can be set any time 22113481Sgiacomo.travaglini@arm.com keywords = { 'check' : types.FunctionType, 22213481Sgiacomo.travaglini@arm.com 'children' : types.ListType } 22313481Sgiacomo.travaglini@arm.com 22413481Sgiacomo.travaglini@arm.com # __new__ is called before __init__, and is where the statements 22513481Sgiacomo.travaglini@arm.com # in the body of the class definition get loaded into the class's 22613481Sgiacomo.travaglini@arm.com # __dict__. We intercept this to filter out parameter assignments 22713481Sgiacomo.travaglini@arm.com # and only allow "private" attributes to be passed to the base 22813481Sgiacomo.travaglini@arm.com # __new__ (starting with underscore). 22913481Sgiacomo.travaglini@arm.com def __new__(mcls, name, bases, dict): 23013481Sgiacomo.travaglini@arm.com # Copy "private" attributes (including special methods such as __new__) 23113481Sgiacomo.travaglini@arm.com # to the official dict. Everything else goes in _init_dict to be 23213481Sgiacomo.travaglini@arm.com # filtered in __init__. 23313481Sgiacomo.travaglini@arm.com cls_dict = {} 23413481Sgiacomo.travaglini@arm.com for key,val in dict.items(): 23513481Sgiacomo.travaglini@arm.com if key.startswith('_'): 23613481Sgiacomo.travaglini@arm.com cls_dict[key] = val 23713481Sgiacomo.travaglini@arm.com del dict[key] 23813481Sgiacomo.travaglini@arm.com cls_dict['_init_dict'] = dict 23913481Sgiacomo.travaglini@arm.com return super(MetaConfigNode, mcls).__new__(mcls, name, bases, cls_dict) 24013481Sgiacomo.travaglini@arm.com 24113481Sgiacomo.travaglini@arm.com # initialization 24213481Sgiacomo.travaglini@arm.com def __init__(cls, name, bases, dict): 24313481Sgiacomo.travaglini@arm.com super(MetaConfigNode, cls).__init__(name, bases, dict) 24413481Sgiacomo.travaglini@arm.com 24513481Sgiacomo.travaglini@arm.com # initialize required attributes 24613481Sgiacomo.travaglini@arm.com cls._params = {} 24713481Sgiacomo.travaglini@arm.com cls._values = {} 24813481Sgiacomo.travaglini@arm.com cls._enums = {} 24913481Sgiacomo.travaglini@arm.com cls._disable = {} 25013481Sgiacomo.travaglini@arm.com cls._bases = [c for c in cls.__mro__ if isConfigNode(c)] 25113481Sgiacomo.travaglini@arm.com cls._anon_subclass_counter = 0 25213481Sgiacomo.travaglini@arm.com 25313481Sgiacomo.travaglini@arm.com # If your parent has a value in it that's a config node, clone 25413481Sgiacomo.travaglini@arm.com # it. Do this now so if we update any of the values' 25513481Sgiacomo.travaglini@arm.com # attributes we are updating the clone and not the original. 25613481Sgiacomo.travaglini@arm.com for base in cls._bases: 25713481Sgiacomo.travaglini@arm.com for key,val in base._values.iteritems(): 25813481Sgiacomo.travaglini@arm.com 25913481Sgiacomo.travaglini@arm.com # don't clone if (1) we're about to overwrite it with 26013481Sgiacomo.travaglini@arm.com # a local setting or (2) we've already cloned a copy 26113481Sgiacomo.travaglini@arm.com # from an earlier (more derived) base 26213481Sgiacomo.travaglini@arm.com if cls._init_dict.has_key(key) or cls._values.has_key(key): 26313481Sgiacomo.travaglini@arm.com continue 26413481Sgiacomo.travaglini@arm.com 26513481Sgiacomo.travaglini@arm.com if isConfigNode(val): 26613481Sgiacomo.travaglini@arm.com cls._values[key] = val() 26713481Sgiacomo.travaglini@arm.com elif isSimObjSequence(val): 26813481Sgiacomo.travaglini@arm.com cls._values[key] = [ v() for v in val ] 26913481Sgiacomo.travaglini@arm.com elif isNullPointer(val): 27013481Sgiacomo.travaglini@arm.com cls._values[key] = val 27113481Sgiacomo.travaglini@arm.com 27213481Sgiacomo.travaglini@arm.com # now process _init_dict items 27313481Sgiacomo.travaglini@arm.com for key,val in cls._init_dict.items(): 27413481Sgiacomo.travaglini@arm.com if isinstance(val, _Param): 27513481Sgiacomo.travaglini@arm.com cls._params[key] = val 27613481Sgiacomo.travaglini@arm.com 27713481Sgiacomo.travaglini@arm.com # init-time-only keywords 27813481Sgiacomo.travaglini@arm.com elif cls.init_keywords.has_key(key): 27913481Sgiacomo.travaglini@arm.com cls._set_keyword(key, val, cls.init_keywords[key]) 28013481Sgiacomo.travaglini@arm.com 28113481Sgiacomo.travaglini@arm.com # enums 28213481Sgiacomo.travaglini@arm.com elif isinstance(val, type) and issubclass(val, Enum): 28313481Sgiacomo.travaglini@arm.com cls._enums[key] = val 28413481Sgiacomo.travaglini@arm.com 28513481Sgiacomo.travaglini@arm.com # See description of decorators in the importer.py file. 28613481Sgiacomo.travaglini@arm.com # We just strip off the expr_decorator now since we don't 28713481Sgiacomo.travaglini@arm.com # need from this point on. 28813481Sgiacomo.travaglini@arm.com elif key.startswith(expr_decorator): 28913481Sgiacomo.travaglini@arm.com key = key[len(expr_decorator):] 29013481Sgiacomo.travaglini@arm.com # because it had dots into a list so that we can find the 29113481Sgiacomo.travaglini@arm.com # proper variable to modify. 29213481Sgiacomo.travaglini@arm.com key = key.split(dot_decorator) 29313481Sgiacomo.travaglini@arm.com c = cls 29413481Sgiacomo.travaglini@arm.com for item in key[:-1]: 29513481Sgiacomo.travaglini@arm.com c = getattr(c, item) 29613481Sgiacomo.travaglini@arm.com setattr(c, key[-1], val) 29713481Sgiacomo.travaglini@arm.com 29813481Sgiacomo.travaglini@arm.com # default: use normal path (ends up in __setattr__) 29913481Sgiacomo.travaglini@arm.com else: 30013481Sgiacomo.travaglini@arm.com setattr(cls, key, val) 30113481Sgiacomo.travaglini@arm.com 30213481Sgiacomo.travaglini@arm.com 30313481Sgiacomo.travaglini@arm.com def _isvalue(cls, name): 30413481Sgiacomo.travaglini@arm.com for c in cls._bases: 30513481Sgiacomo.travaglini@arm.com if c._params.has_key(name): 30613481Sgiacomo.travaglini@arm.com return True 30713481Sgiacomo.travaglini@arm.com 30813481Sgiacomo.travaglini@arm.com for c in cls._bases: 30913481Sgiacomo.travaglini@arm.com if c._values.has_key(name): 31013481Sgiacomo.travaglini@arm.com return True 31113481Sgiacomo.travaglini@arm.com 31213481Sgiacomo.travaglini@arm.com return False 31313481Sgiacomo.travaglini@arm.com 31413481Sgiacomo.travaglini@arm.com # generator that iterates across all parameters for this class and 31513481Sgiacomo.travaglini@arm.com # all classes it inherits from 31613481Sgiacomo.travaglini@arm.com def _getparams(cls): 31713481Sgiacomo.travaglini@arm.com params = {} 31813481Sgiacomo.travaglini@arm.com for c in cls._bases: 31913481Sgiacomo.travaglini@arm.com for p,v in c._params.iteritems(): 32013481Sgiacomo.travaglini@arm.com if not params.has_key(p): 32113481Sgiacomo.travaglini@arm.com params[p] = v 32213481Sgiacomo.travaglini@arm.com return params 32313481Sgiacomo.travaglini@arm.com 32413481Sgiacomo.travaglini@arm.com # Lookup a parameter description by name in the given class. 32513481Sgiacomo.travaglini@arm.com def _getparam(cls, name, default = AttributeError): 32613481Sgiacomo.travaglini@arm.com for c in cls._bases: 32713481Sgiacomo.travaglini@arm.com if c._params.has_key(name): 32813481Sgiacomo.travaglini@arm.com return c._params[name] 32913481Sgiacomo.travaglini@arm.com if isSubClass(default, Exception): 33013481Sgiacomo.travaglini@arm.com raise default, \ 33113481Sgiacomo.travaglini@arm.com "object '%s' has no attribute '%s'" % (cls.__name__, name) 33213481Sgiacomo.travaglini@arm.com else: 33313481Sgiacomo.travaglini@arm.com return default 33413481Sgiacomo.travaglini@arm.com 33513481Sgiacomo.travaglini@arm.com def _hasvalue(cls, name): 33613481Sgiacomo.travaglini@arm.com for c in cls._bases: 33713481Sgiacomo.travaglini@arm.com if c._values.has_key(name): 33813481Sgiacomo.travaglini@arm.com return True 33913481Sgiacomo.travaglini@arm.com 34013481Sgiacomo.travaglini@arm.com return False 34113481Sgiacomo.travaglini@arm.com 34213481Sgiacomo.travaglini@arm.com def _getvalues(cls): 34313481Sgiacomo.travaglini@arm.com values = {} 34413481Sgiacomo.travaglini@arm.com for i,c in enumerate(cls._bases): 34513481Sgiacomo.travaglini@arm.com for p,v in c._values.iteritems(): 34613481Sgiacomo.travaglini@arm.com if not values.has_key(p): 34713481Sgiacomo.travaglini@arm.com values[p] = v 34813481Sgiacomo.travaglini@arm.com for p,v in c._params.iteritems(): 34913481Sgiacomo.travaglini@arm.com if not values.has_key(p) and hasattr(v, 'default'): 35013481Sgiacomo.travaglini@arm.com try: 35113481Sgiacomo.travaglini@arm.com v.valid(v.default) 35213481Sgiacomo.travaglini@arm.com except TypeError: 35313481Sgiacomo.travaglini@arm.com panic("Invalid default %s for param %s in node %s" 35413481Sgiacomo.travaglini@arm.com % (v.default,p,cls.__name__)) 35513481Sgiacomo.travaglini@arm.com v = v.default 35613481Sgiacomo.travaglini@arm.com cls._setvalue(p, v) 35713481Sgiacomo.travaglini@arm.com values[p] = v 35813481Sgiacomo.travaglini@arm.com 35913481Sgiacomo.travaglini@arm.com return values 36013481Sgiacomo.travaglini@arm.com 36113481Sgiacomo.travaglini@arm.com def _getvalue(cls, name, default = AttributeError): 36213481Sgiacomo.travaglini@arm.com value = None 36313481Sgiacomo.travaglini@arm.com for c in cls._bases: 36413481Sgiacomo.travaglini@arm.com if c._values.has_key(name): 36513481Sgiacomo.travaglini@arm.com value = c._values[name] 36613481Sgiacomo.travaglini@arm.com break 36713481Sgiacomo.travaglini@arm.com if value is not None: 36813481Sgiacomo.travaglini@arm.com return value 36913481Sgiacomo.travaglini@arm.com 37013481Sgiacomo.travaglini@arm.com param = cls._getparam(name, None) 37113481Sgiacomo.travaglini@arm.com if param is not None and hasattr(param, 'default'): 37213481Sgiacomo.travaglini@arm.com param.valid(param.default) 37313481Sgiacomo.travaglini@arm.com value = param.default 37413481Sgiacomo.travaglini@arm.com cls._setvalue(name, value) 37513481Sgiacomo.travaglini@arm.com return value 37613481Sgiacomo.travaglini@arm.com 37713481Sgiacomo.travaglini@arm.com if isSubClass(default, Exception): 37813481Sgiacomo.travaglini@arm.com raise default, 'value for %s not found' % name 37913481Sgiacomo.travaglini@arm.com else: 38013481Sgiacomo.travaglini@arm.com return default 38113481Sgiacomo.travaglini@arm.com 38213481Sgiacomo.travaglini@arm.com def _setvalue(cls, name, value): 38313481Sgiacomo.travaglini@arm.com cls._values[name] = value 38413481Sgiacomo.travaglini@arm.com 38513481Sgiacomo.travaglini@arm.com def _getdisable(cls, name): 38613481Sgiacomo.travaglini@arm.com for c in cls._bases: 38713481Sgiacomo.travaglini@arm.com if c._disable.has_key(name): 38813481Sgiacomo.travaglini@arm.com return c._disable[name] 38913481Sgiacomo.travaglini@arm.com return False 39013481Sgiacomo.travaglini@arm.com 39113481Sgiacomo.travaglini@arm.com def _setdisable(cls, name, value): 39213481Sgiacomo.travaglini@arm.com cls._disable[name] = value 39313481Sgiacomo.travaglini@arm.com 39413481Sgiacomo.travaglini@arm.com def __getattr__(cls, attr): 39513481Sgiacomo.travaglini@arm.com if cls._isvalue(attr): 39613481Sgiacomo.travaglini@arm.com return Value(cls, attr) 39713481Sgiacomo.travaglini@arm.com 39813481Sgiacomo.travaglini@arm.com if attr == '_cpp_param_decl' and hasattr(cls, 'type'): 39913481Sgiacomo.travaglini@arm.com return cls.type + '*' 40013481Sgiacomo.travaglini@arm.com 40113481Sgiacomo.travaglini@arm.com raise AttributeError, \ 40213481Sgiacomo.travaglini@arm.com "object '%s' has no attribute '%s'" % (cls.__name__, attr) 40313481Sgiacomo.travaglini@arm.com 40413481Sgiacomo.travaglini@arm.com def _set_keyword(cls, keyword, val, kwtype): 40513481Sgiacomo.travaglini@arm.com if not isinstance(val, kwtype): 40613481Sgiacomo.travaglini@arm.com raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 40713481Sgiacomo.travaglini@arm.com (keyword, type(val), kwtype) 40813481Sgiacomo.travaglini@arm.com if isinstance(val, types.FunctionType): 40913481Sgiacomo.travaglini@arm.com val = classmethod(val) 41013481Sgiacomo.travaglini@arm.com type.__setattr__(cls, keyword, val) 41113481Sgiacomo.travaglini@arm.com 41213481Sgiacomo.travaglini@arm.com # Set attribute (called on foo.attr = value when foo is an 41313481Sgiacomo.travaglini@arm.com # instance of class cls). 41413481Sgiacomo.travaglini@arm.com def __setattr__(cls, attr, value): 41513481Sgiacomo.travaglini@arm.com # normal processing for private attributes 41613481Sgiacomo.travaglini@arm.com if attr.startswith('_'): 41713481Sgiacomo.travaglini@arm.com type.__setattr__(cls, attr, value) 41813481Sgiacomo.travaglini@arm.com return 41913481Sgiacomo.travaglini@arm.com 42013481Sgiacomo.travaglini@arm.com if cls.keywords.has_key(attr): 42113481Sgiacomo.travaglini@arm.com cls._set_keyword(attr, value, cls.keywords[attr]) 42213481Sgiacomo.travaglini@arm.com return 42313481Sgiacomo.travaglini@arm.com 42413481Sgiacomo.travaglini@arm.com # must be SimObject param 42513481Sgiacomo.travaglini@arm.com param = cls._getparam(attr, None) 42613481Sgiacomo.travaglini@arm.com if param: 42713481Sgiacomo.travaglini@arm.com # It's ok: set attribute by delegating to 'object' class. 42813481Sgiacomo.travaglini@arm.com # Note the use of param.make_value() to verify/canonicalize 42913481Sgiacomo.travaglini@arm.com # the assigned value 43013481Sgiacomo.travaglini@arm.com param.valid(value) 43113481Sgiacomo.travaglini@arm.com cls._setvalue(attr, value) 43213481Sgiacomo.travaglini@arm.com elif isConfigNode(value) or isSimObjSequence(value): 43313481Sgiacomo.travaglini@arm.com cls._setvalue(attr, value) 43413481Sgiacomo.travaglini@arm.com else: 43513481Sgiacomo.travaglini@arm.com raise AttributeError, \ 43613481Sgiacomo.travaglini@arm.com "Class %s has no parameter %s" % (cls.__name__, attr) 43713481Sgiacomo.travaglini@arm.com 43813481Sgiacomo.travaglini@arm.com def add_child(cls, instance, name, child): 43913481Sgiacomo.travaglini@arm.com if isNullPointer(child) or instance.top_child_names.has_key(name): 44013481Sgiacomo.travaglini@arm.com return 44113481Sgiacomo.travaglini@arm.com 44213481Sgiacomo.travaglini@arm.com if issequence(child): 44313481Sgiacomo.travaglini@arm.com kid = [] 44413481Sgiacomo.travaglini@arm.com for i,c in enumerate(child): 44513481Sgiacomo.travaglini@arm.com n = '%s%d' % (name, i) 44613481Sgiacomo.travaglini@arm.com k = c.instantiate(n, instance) 44713481Sgiacomo.travaglini@arm.com 44813481Sgiacomo.travaglini@arm.com instance.children.append(k) 44913481Sgiacomo.travaglini@arm.com instance.child_names[n] = k 45013481Sgiacomo.travaglini@arm.com instance.child_objects[c] = k 45113481Sgiacomo.travaglini@arm.com kid.append(k) 45213481Sgiacomo.travaglini@arm.com else: 45313481Sgiacomo.travaglini@arm.com kid = child.instantiate(name, instance) 45413481Sgiacomo.travaglini@arm.com instance.children.append(kid) 45513481Sgiacomo.travaglini@arm.com instance.child_names[name] = kid 45613481Sgiacomo.travaglini@arm.com instance.child_objects[child] = kid 45713481Sgiacomo.travaglini@arm.com 45813481Sgiacomo.travaglini@arm.com instance.top_child_names[name] = kid 45913481Sgiacomo.travaglini@arm.com 46013481Sgiacomo.travaglini@arm.com # Print instance info to .ini file. 46113481Sgiacomo.travaglini@arm.com def instantiate(cls, name, parent = None): 46213481Sgiacomo.travaglini@arm.com instance = Node(name, cls, cls.type, parent, isParamContext(cls)) 46313481Sgiacomo.travaglini@arm.com 46413481Sgiacomo.travaglini@arm.com if hasattr(cls, 'check'): 46513481Sgiacomo.travaglini@arm.com cls.check() 46613481Sgiacomo.travaglini@arm.com 46713481Sgiacomo.travaglini@arm.com for key,value in cls._getvalues().iteritems(): 46813481Sgiacomo.travaglini@arm.com if cls._getdisable(key): 46913481Sgiacomo.travaglini@arm.com continue 47013481Sgiacomo.travaglini@arm.com 47113481Sgiacomo.travaglini@arm.com if isConfigNode(value): 47213481Sgiacomo.travaglini@arm.com cls.add_child(instance, key, value) 47313481Sgiacomo.travaglini@arm.com if issequence(value): 47413481Sgiacomo.travaglini@arm.com list = [ v for v in value if isConfigNode(v) ] 47513481Sgiacomo.travaglini@arm.com if len(list): 47613481Sgiacomo.travaglini@arm.com cls.add_child(instance, key, list) 47713481Sgiacomo.travaglini@arm.com 47813481Sgiacomo.travaglini@arm.com for pname,param in cls._getparams().iteritems(): 47913481Sgiacomo.travaglini@arm.com try: 48013481Sgiacomo.travaglini@arm.com if cls._getdisable(pname): 48113481Sgiacomo.travaglini@arm.com continue 48213481Sgiacomo.travaglini@arm.com 48313481Sgiacomo.travaglini@arm.com try: 48413481Sgiacomo.travaglini@arm.com value = cls._getvalue(pname) 48513481Sgiacomo.travaglini@arm.com except: 48613481Sgiacomo.travaglini@arm.com print 'Error getting %s' % pname 48713481Sgiacomo.travaglini@arm.com raise 48813481Sgiacomo.travaglini@arm.com 48913481Sgiacomo.travaglini@arm.com if isConfigNode(value): 49013481Sgiacomo.travaglini@arm.com value = instance.child_objects[value] 49113481Sgiacomo.travaglini@arm.com elif issequence(value): 49213481Sgiacomo.travaglini@arm.com v = [] 49313481Sgiacomo.travaglini@arm.com for val in value: 49413481Sgiacomo.travaglini@arm.com if isConfigNode(val): 49513481Sgiacomo.travaglini@arm.com v.append(instance.child_objects[val]) 49613481Sgiacomo.travaglini@arm.com else: 49713481Sgiacomo.travaglini@arm.com v.append(val) 49813481Sgiacomo.travaglini@arm.com value = v 49913481Sgiacomo.travaglini@arm.com 50013481Sgiacomo.travaglini@arm.com p = NodeParam(pname, param, value) 50113481Sgiacomo.travaglini@arm.com instance.params.append(p) 50213481Sgiacomo.travaglini@arm.com instance.param_names[pname] = p 50313481Sgiacomo.travaglini@arm.com except: 50413481Sgiacomo.travaglini@arm.com print 'Exception while evaluating %s.%s' % \ 50513481Sgiacomo.travaglini@arm.com (instance.path, pname) 50613481Sgiacomo.travaglini@arm.com raise 50713481Sgiacomo.travaglini@arm.com 50813481Sgiacomo.travaglini@arm.com return instance 50913481Sgiacomo.travaglini@arm.com 51013481Sgiacomo.travaglini@arm.com def _convert(cls, value): 51113481Sgiacomo.travaglini@arm.com realvalue = value 51213481Sgiacomo.travaglini@arm.com if isinstance(value, Node): 51313481Sgiacomo.travaglini@arm.com realvalue = value.realtype 51413481Sgiacomo.travaglini@arm.com 51513481Sgiacomo.travaglini@arm.com if isinstance(realvalue, Proxy): 51613481Sgiacomo.travaglini@arm.com return value 51713481Sgiacomo.travaglini@arm.com 51813481Sgiacomo.travaglini@arm.com if realvalue == None or isNullPointer(realvalue): 51913481Sgiacomo.travaglini@arm.com return value 52013481Sgiacomo.travaglini@arm.com 52113481Sgiacomo.travaglini@arm.com if isSubClass(realvalue, cls): 52213481Sgiacomo.travaglini@arm.com return value 52313481Sgiacomo.travaglini@arm.com 52413481Sgiacomo.travaglini@arm.com raise TypeError, 'object %s type %s wrong type, should be %s' % \ 52513481Sgiacomo.travaglini@arm.com (repr(realvalue), realvalue, cls) 52613481Sgiacomo.travaglini@arm.com 52713481Sgiacomo.travaglini@arm.com def _string(cls, value): 52813481Sgiacomo.travaglini@arm.com if isNullPointer(value): 52913481Sgiacomo.travaglini@arm.com return 'Null' 53013481Sgiacomo.travaglini@arm.com return Node._string(value) 53113481Sgiacomo.travaglini@arm.com 53213481Sgiacomo.travaglini@arm.com# The ConfigNode class is the root of the special hierarchy. Most of 53313481Sgiacomo.travaglini@arm.com# the code in this class deals with the configuration hierarchy itself 53413481Sgiacomo.travaglini@arm.com# (parent/child node relationships). 53513481Sgiacomo.travaglini@arm.comclass ConfigNode(object): 53613481Sgiacomo.travaglini@arm.com # Specify metaclass. Any class inheriting from ConfigNode will 53713481Sgiacomo.travaglini@arm.com # get this metaclass. 53813481Sgiacomo.travaglini@arm.com __metaclass__ = MetaConfigNode 53913481Sgiacomo.travaglini@arm.com 54013481Sgiacomo.travaglini@arm.com def __new__(cls, **kwargs): 54113481Sgiacomo.travaglini@arm.com name = cls.__name__ + ("_%d" % cls._anon_subclass_counter) 54213481Sgiacomo.travaglini@arm.com cls._anon_subclass_counter += 1 54313481Sgiacomo.travaglini@arm.com return cls.__metaclass__(name, (cls, ), kwargs) 54413481Sgiacomo.travaglini@arm.com 54513481Sgiacomo.travaglini@arm.comclass ParamContext(ConfigNode): 54613481Sgiacomo.travaglini@arm.com pass 54713481Sgiacomo.travaglini@arm.com 54813481Sgiacomo.travaglini@arm.comclass MetaSimObject(MetaConfigNode): 54913481Sgiacomo.travaglini@arm.com # init_keywords and keywords are inherited from MetaConfigNode, 55013481Sgiacomo.travaglini@arm.com # with overrides/additions 55113481Sgiacomo.travaglini@arm.com init_keywords = MetaConfigNode.init_keywords 55213481Sgiacomo.travaglini@arm.com init_keywords.update({ 'abstract' : types.BooleanType, 55313481Sgiacomo.travaglini@arm.com 'type' : types.StringType }) 55413481Sgiacomo.travaglini@arm.com 55513481Sgiacomo.travaglini@arm.com keywords = MetaConfigNode.keywords 55613481Sgiacomo.travaglini@arm.com # no additional keywords 55713481Sgiacomo.travaglini@arm.com 55813481Sgiacomo.travaglini@arm.com cpp_classes = [] 55913481Sgiacomo.travaglini@arm.com 56013481Sgiacomo.travaglini@arm.com # initialization 56113481Sgiacomo.travaglini@arm.com def __init__(cls, name, bases, dict): 56213481Sgiacomo.travaglini@arm.com super(MetaSimObject, cls).__init__(name, bases, dict) 56313481Sgiacomo.travaglini@arm.com 56413481Sgiacomo.travaglini@arm.com if hasattr(cls, 'type'): 56513481Sgiacomo.travaglini@arm.com if name == 'SimObject': 56613481Sgiacomo.travaglini@arm.com cls._cpp_base = None 56713481Sgiacomo.travaglini@arm.com elif hasattr(cls._bases[1], 'type'): 56813481Sgiacomo.travaglini@arm.com cls._cpp_base = cls._bases[1].type 56913481Sgiacomo.travaglini@arm.com else: 57013481Sgiacomo.travaglini@arm.com panic("SimObject %s derives from a non-C++ SimObject %s "\ 57113481Sgiacomo.travaglini@arm.com "(no 'type')" % (cls, cls_bases[1].__name__)) 57213481Sgiacomo.travaglini@arm.com 57313481Sgiacomo.travaglini@arm.com # This class corresponds to a C++ class: put it on the global 57413481Sgiacomo.travaglini@arm.com # list of C++ objects to generate param structs, etc. 57513481Sgiacomo.travaglini@arm.com MetaSimObject.cpp_classes.append(cls) 57613481Sgiacomo.travaglini@arm.com 57713481Sgiacomo.travaglini@arm.com def _cpp_decl(cls): 57813481Sgiacomo.travaglini@arm.com name = cls.__name__ 57913481Sgiacomo.travaglini@arm.com code = "" 58013481Sgiacomo.travaglini@arm.com code += "\n".join([e.cpp_declare() for e in cls._enums.values()]) 58113481Sgiacomo.travaglini@arm.com code += "\n" 58213481Sgiacomo.travaglini@arm.com param_names = cls._params.keys() 58313481Sgiacomo.travaglini@arm.com param_names.sort() 58413481Sgiacomo.travaglini@arm.com code += "struct Params" 58513481Sgiacomo.travaglini@arm.com if cls._cpp_base: 58613481Sgiacomo.travaglini@arm.com code += " : public %s::Params" % cls._cpp_base 58713481Sgiacomo.travaglini@arm.com code += " {\n " 58813481Sgiacomo.travaglini@arm.com code += "\n ".join([cls._params[pname].cpp_decl(pname) \ 58913481Sgiacomo.travaglini@arm.com for pname in param_names]) 59013481Sgiacomo.travaglini@arm.com code += "\n};\n" 59113481Sgiacomo.travaglini@arm.com return code 59213481Sgiacomo.travaglini@arm.com 59313481Sgiacomo.travaglini@arm.comclass NodeParam(object): 59413481Sgiacomo.travaglini@arm.com def __init__(self, name, param, value): 59513481Sgiacomo.travaglini@arm.com self.name = name 59613481Sgiacomo.travaglini@arm.com self.param = param 59713481Sgiacomo.travaglini@arm.com self.ptype = param.ptype 59813481Sgiacomo.travaglini@arm.com self.convert = param.convert 59913481Sgiacomo.travaglini@arm.com self.string = param.string 60013481Sgiacomo.travaglini@arm.com self.value = value 60113481Sgiacomo.travaglini@arm.com 60213481Sgiacomo.travaglini@arm.comclass Node(object): 60313481Sgiacomo.travaglini@arm.com all = {} 60413481Sgiacomo.travaglini@arm.com def __init__(self, name, realtype, type, parent, paramcontext): 60513481Sgiacomo.travaglini@arm.com self.name = name 60613481Sgiacomo.travaglini@arm.com self.realtype = realtype 60713481Sgiacomo.travaglini@arm.com self.type = type 60813481Sgiacomo.travaglini@arm.com self.parent = parent 60913481Sgiacomo.travaglini@arm.com self.children = [] 61013481Sgiacomo.travaglini@arm.com self.child_names = {} 61113481Sgiacomo.travaglini@arm.com self.child_objects = {} 61213481Sgiacomo.travaglini@arm.com self.top_child_names = {} 61313481Sgiacomo.travaglini@arm.com self.params = [] 61413481Sgiacomo.travaglini@arm.com self.param_names = {} 61513481Sgiacomo.travaglini@arm.com self.paramcontext = paramcontext 61613481Sgiacomo.travaglini@arm.com 61713481Sgiacomo.travaglini@arm.com path = [ self.name ] 61813481Sgiacomo.travaglini@arm.com node = self.parent 61913481Sgiacomo.travaglini@arm.com while node is not None: 62013481Sgiacomo.travaglini@arm.com if node.name != 'root': 62113481Sgiacomo.travaglini@arm.com path.insert(0, node.name) 62213481Sgiacomo.travaglini@arm.com else: 62313481Sgiacomo.travaglini@arm.com assert(node.parent is None) 62413481Sgiacomo.travaglini@arm.com node = node.parent 62513481Sgiacomo.travaglini@arm.com self.path = '.'.join(path) 62613481Sgiacomo.travaglini@arm.com 62713481Sgiacomo.travaglini@arm.com def find(self, realtype, path): 62813481Sgiacomo.travaglini@arm.com if not path: 62913481Sgiacomo.travaglini@arm.com if issubclass(self.realtype, realtype): 63013481Sgiacomo.travaglini@arm.com return self, True 63113481Sgiacomo.travaglini@arm.com 63213481Sgiacomo.travaglini@arm.com obj = None 63313481Sgiacomo.travaglini@arm.com for child in self.children: 63413481Sgiacomo.travaglini@arm.com if issubclass(child.realtype, realtype): 63513481Sgiacomo.travaglini@arm.com if obj is not None: 63613481Sgiacomo.travaglini@arm.com raise AttributeError, \ 63713481Sgiacomo.travaglini@arm.com 'Super matched more than one: %s %s' % \ 63813481Sgiacomo.travaglini@arm.com (obj.path, child.path) 63913481Sgiacomo.travaglini@arm.com obj = child 64013481Sgiacomo.travaglini@arm.com return obj, obj is not None 64113481Sgiacomo.travaglini@arm.com 64213481Sgiacomo.travaglini@arm.com try: 64313481Sgiacomo.travaglini@arm.com obj = self 64413481Sgiacomo.travaglini@arm.com for node in path[:-1]: 64513481Sgiacomo.travaglini@arm.com obj = obj.child_names[node] 64613481Sgiacomo.travaglini@arm.com 64713481Sgiacomo.travaglini@arm.com last = path[-1] 64813481Sgiacomo.travaglini@arm.com if obj.child_names.has_key(last): 64913481Sgiacomo.travaglini@arm.com value = obj.child_names[last] 65013481Sgiacomo.travaglini@arm.com if issubclass(value.realtype, realtype): 65113481Sgiacomo.travaglini@arm.com return value, True 65213481Sgiacomo.travaglini@arm.com elif obj.param_names.has_key(last): 65313481Sgiacomo.travaglini@arm.com value = obj.param_names[last] 65413481Sgiacomo.travaglini@arm.com realtype._convert(value.value) 65513481Sgiacomo.travaglini@arm.com return value.value, True 65613481Sgiacomo.travaglini@arm.com except KeyError: 65713481Sgiacomo.travaglini@arm.com pass 65813481Sgiacomo.travaglini@arm.com 65913481Sgiacomo.travaglini@arm.com return None, False 66013481Sgiacomo.travaglini@arm.com 66113481Sgiacomo.travaglini@arm.com def unproxy(self, ptype, value): 66213481Sgiacomo.travaglini@arm.com if not isinstance(value, Proxy): 66313481Sgiacomo.travaglini@arm.com return value 66413481Sgiacomo.travaglini@arm.com 66513481Sgiacomo.travaglini@arm.com if value is None: 66613481Sgiacomo.travaglini@arm.com raise AttributeError, 'Error while fixing up %s' % self.path 66713481Sgiacomo.travaglini@arm.com 66813481Sgiacomo.travaglini@arm.com obj = self 66913481Sgiacomo.travaglini@arm.com done = False 67013481Sgiacomo.travaglini@arm.com while not done: 67113481Sgiacomo.travaglini@arm.com if obj is None: 67213481Sgiacomo.travaglini@arm.com raise AttributeError, \ 67313481Sgiacomo.travaglini@arm.com 'Parent of %s type %s not found at path %s' \ 67413481Sgiacomo.travaglini@arm.com % (self.name, ptype, value._path) 67513481Sgiacomo.travaglini@arm.com found, done = obj.find(ptype, value._path) 67613481Sgiacomo.travaglini@arm.com if isinstance(found, Proxy): 67713481Sgiacomo.travaglini@arm.com done = False 67813481Sgiacomo.travaglini@arm.com obj = obj.parent 67913481Sgiacomo.travaglini@arm.com 68013481Sgiacomo.travaglini@arm.com return found 68113481Sgiacomo.travaglini@arm.com 68213481Sgiacomo.travaglini@arm.com def fixup(self): 68313481Sgiacomo.travaglini@arm.com self.all[self.path] = self 68413481Sgiacomo.travaglini@arm.com 68513481Sgiacomo.travaglini@arm.com for param in self.params: 68613481Sgiacomo.travaglini@arm.com ptype = param.ptype 68713481Sgiacomo.travaglini@arm.com pval = param.value 68813481Sgiacomo.travaglini@arm.com 68913481Sgiacomo.travaglini@arm.com try: 69013481Sgiacomo.travaglini@arm.com if issequence(pval): 69113481Sgiacomo.travaglini@arm.com param.value = [ self.unproxy(ptype, pv) for pv in pval ] 69213481Sgiacomo.travaglini@arm.com else: 69313481Sgiacomo.travaglini@arm.com param.value = self.unproxy(ptype, pval) 69413481Sgiacomo.travaglini@arm.com except: 69513481Sgiacomo.travaglini@arm.com print 'Error while fixing up %s:%s' % (self.path, param.name) 69613481Sgiacomo.travaglini@arm.com raise 69713481Sgiacomo.travaglini@arm.com 69813481Sgiacomo.travaglini@arm.com for child in self.children: 69913481Sgiacomo.travaglini@arm.com assert(child != self) 70013481Sgiacomo.travaglini@arm.com child.fixup() 70113481Sgiacomo.travaglini@arm.com 70213481Sgiacomo.travaglini@arm.com # print type and parameter values to .ini file 70313481Sgiacomo.travaglini@arm.com def display(self): 70413481Sgiacomo.travaglini@arm.com print '[' + self.path + ']' # .ini section header 70513481Sgiacomo.travaglini@arm.com 70613481Sgiacomo.travaglini@arm.com if isSimObject(self.realtype): 70713481Sgiacomo.travaglini@arm.com print 'type = %s' % self.type 70813481Sgiacomo.travaglini@arm.com 70913481Sgiacomo.travaglini@arm.com if self.children: 71013481Sgiacomo.travaglini@arm.com # instantiate children in same order they were added for 71113481Sgiacomo.travaglini@arm.com # backward compatibility (else we can end up with cpu1 71213481Sgiacomo.travaglini@arm.com # before cpu0). 71313481Sgiacomo.travaglini@arm.com self.children.sort(lambda x,y: cmp(x.name, y.name)) 71413481Sgiacomo.travaglini@arm.com children = [ c.name for c in self.children if not c.paramcontext] 71513481Sgiacomo.travaglini@arm.com print 'children =', ' '.join(children) 71613481Sgiacomo.travaglini@arm.com 71713481Sgiacomo.travaglini@arm.com self.params.sort(lambda x,y: cmp(x.name, y.name)) 71813481Sgiacomo.travaglini@arm.com for param in self.params: 71913481Sgiacomo.travaglini@arm.com try: 72013481Sgiacomo.travaglini@arm.com if param.value is None: 72113481Sgiacomo.travaglini@arm.com raise AttributeError, 'Parameter with no value' 72213481Sgiacomo.travaglini@arm.com 72313481Sgiacomo.travaglini@arm.com value = param.convert(param.value) 72413481Sgiacomo.travaglini@arm.com string = param.string(value) 72513481Sgiacomo.travaglini@arm.com except: 72613481Sgiacomo.travaglini@arm.com print 'exception in %s:%s' % (self.path, param.name) 72713481Sgiacomo.travaglini@arm.com raise 72813481Sgiacomo.travaglini@arm.com 72913481Sgiacomo.travaglini@arm.com print '%s = %s' % (param.name, string) 73013481Sgiacomo.travaglini@arm.com 73113481Sgiacomo.travaglini@arm.com print 73213481Sgiacomo.travaglini@arm.com 73313481Sgiacomo.travaglini@arm.com # recursively dump out children 73413481Sgiacomo.travaglini@arm.com for c in self.children: 73513481Sgiacomo.travaglini@arm.com c.display() 73613481Sgiacomo.travaglini@arm.com 73713481Sgiacomo.travaglini@arm.com # print type and parameter values to .ini file 73813481Sgiacomo.travaglini@arm.com def outputDot(self, dot): 73913481Sgiacomo.travaglini@arm.com 74013481Sgiacomo.travaglini@arm.com 74113481Sgiacomo.travaglini@arm.com label = "{%s|" % self.path 74213481Sgiacomo.travaglini@arm.com if isSimObject(self.realtype): 74313481Sgiacomo.travaglini@arm.com label += '%s|' % self.type 74413481Sgiacomo.travaglini@arm.com 74513481Sgiacomo.travaglini@arm.com if self.children: 74613481Sgiacomo.travaglini@arm.com # instantiate children in same order they were added for 74713481Sgiacomo.travaglini@arm.com # backward compatibility (else we can end up with cpu1 74813481Sgiacomo.travaglini@arm.com # before cpu0). 74913481Sgiacomo.travaglini@arm.com for c in self.children: 75013481Sgiacomo.travaglini@arm.com dot.add_edge(pydot.Edge(self.path,c.path, style="bold")) 75113481Sgiacomo.travaglini@arm.com 75213481Sgiacomo.travaglini@arm.com simobjs = [] 75313481Sgiacomo.travaglini@arm.com for param in self.params: 75413481Sgiacomo.travaglini@arm.com try: 75513481Sgiacomo.travaglini@arm.com if param.value is None: 75613481Sgiacomo.travaglini@arm.com raise AttributeError, 'Parameter with no value' 75713481Sgiacomo.travaglini@arm.com 75813481Sgiacomo.travaglini@arm.com value = param.convert(param.value) 75913481Sgiacomo.travaglini@arm.com string = param.string(value) 76013481Sgiacomo.travaglini@arm.com except: 76113481Sgiacomo.travaglini@arm.com print 'exception in %s:%s' % (self.name, param.name) 76213481Sgiacomo.travaglini@arm.com raise 76313481Sgiacomo.travaglini@arm.com if isConfigNode(param.ptype) and string != "Null": 76413481Sgiacomo.travaglini@arm.com simobjs.append(string) 76513481Sgiacomo.travaglini@arm.com else: 76613481Sgiacomo.travaglini@arm.com label += '%s = %s\\n' % (param.name, string) 76713481Sgiacomo.travaglini@arm.com 76813481Sgiacomo.travaglini@arm.com for so in simobjs: 76913481Sgiacomo.travaglini@arm.com label += "|<%s> %s" % (so, so) 77013481Sgiacomo.travaglini@arm.com dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, tailport="w")) 77113481Sgiacomo.travaglini@arm.com label += '}' 77213481Sgiacomo.travaglini@arm.com dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) 77313481Sgiacomo.travaglini@arm.com 77413481Sgiacomo.travaglini@arm.com # recursively dump out children 77513481Sgiacomo.travaglini@arm.com for c in self.children: 77613481Sgiacomo.travaglini@arm.com c.outputDot(dot) 77713481Sgiacomo.travaglini@arm.com 77813481Sgiacomo.travaglini@arm.com def _string(cls, value): 77913481Sgiacomo.travaglini@arm.com if not isinstance(value, Node): 78013481Sgiacomo.travaglini@arm.com raise AttributeError, 'expecting %s got %s' % (Node, value) 78113481Sgiacomo.travaglini@arm.com return value.path 78213481Sgiacomo.travaglini@arm.com _string = classmethod(_string) 78313481Sgiacomo.travaglini@arm.com 78413481Sgiacomo.travaglini@arm.com##################################################################### 78513481Sgiacomo.travaglini@arm.com# 78613481Sgiacomo.travaglini@arm.com# Parameter description classes 78713481Sgiacomo.travaglini@arm.com# 78813481Sgiacomo.travaglini@arm.com# The _params dictionary in each class maps parameter names to 78913481Sgiacomo.travaglini@arm.com# either a Param or a VectorParam object. These objects contain the 79013481Sgiacomo.travaglini@arm.com# parameter description string, the parameter type, and the default 79113481Sgiacomo.travaglini@arm.com# value (loaded from the PARAM section of the .odesc files). The 79213481Sgiacomo.travaglini@arm.com# _convert() method on these objects is used to force whatever value 79313481Sgiacomo.travaglini@arm.com# is assigned to the parameter to the appropriate type. 79413481Sgiacomo.travaglini@arm.com# 79513481Sgiacomo.travaglini@arm.com# Note that the default values are loaded into the class's attribute 79613481Sgiacomo.travaglini@arm.com# space when the parameter dictionary is initialized (in 79713481Sgiacomo.travaglini@arm.com# MetaConfigNode._setparams()); after that point they aren't used. 79813481Sgiacomo.travaglini@arm.com# 79913481Sgiacomo.travaglini@arm.com##################################################################### 80013481Sgiacomo.travaglini@arm.com 80113481Sgiacomo.travaglini@arm.comdef isNullPointer(value): 80213481Sgiacomo.travaglini@arm.com return isinstance(value, NullSimObject) 80313481Sgiacomo.travaglini@arm.com 80413481Sgiacomo.travaglini@arm.comclass Value(object): 80513481Sgiacomo.travaglini@arm.com def __init__(self, obj, attr): 80613481Sgiacomo.travaglini@arm.com super(Value, self).__setattr__('attr', attr) 80713481Sgiacomo.travaglini@arm.com super(Value, self).__setattr__('obj', obj) 80813481Sgiacomo.travaglini@arm.com 80913481Sgiacomo.travaglini@arm.com def _getattr(self): 81013481Sgiacomo.travaglini@arm.com return self.obj._getvalue(self.attr) 81113481Sgiacomo.travaglini@arm.com 81213481Sgiacomo.travaglini@arm.com def __setattr__(self, attr, value): 81313481Sgiacomo.travaglini@arm.com if attr == 'disable': 81413481Sgiacomo.travaglini@arm.com self.obj._setdisable(self.attr, value) 81513481Sgiacomo.travaglini@arm.com else: 81613481Sgiacomo.travaglini@arm.com setattr(self._getattr(), attr, value) 81713481Sgiacomo.travaglini@arm.com 81813481Sgiacomo.travaglini@arm.com def __getattr__(self, attr): 81913481Sgiacomo.travaglini@arm.com if attr == 'disable': 82013481Sgiacomo.travaglini@arm.com return self.obj._getdisable(self.attr) 82113481Sgiacomo.travaglini@arm.com else: 82213481Sgiacomo.travaglini@arm.com return getattr(self._getattr(), attr) 82313481Sgiacomo.travaglini@arm.com 82413481Sgiacomo.travaglini@arm.com def __getitem__(self, index): 82513481Sgiacomo.travaglini@arm.com return self._getattr().__getitem__(index) 82613481Sgiacomo.travaglini@arm.com 82713481Sgiacomo.travaglini@arm.com def __call__(self, *args, **kwargs): 82813481Sgiacomo.travaglini@arm.com return self._getattr().__call__(*args, **kwargs) 82913481Sgiacomo.travaglini@arm.com 83013481Sgiacomo.travaglini@arm.com def __nonzero__(self): 83113481Sgiacomo.travaglini@arm.com return bool(self._getattr()) 83213481Sgiacomo.travaglini@arm.com 83313481Sgiacomo.travaglini@arm.com def __str__(self): 83413481Sgiacomo.travaglini@arm.com return str(self._getattr()) 83513481Sgiacomo.travaglini@arm.com 83613481Sgiacomo.travaglini@arm.com# Regular parameter. 83713481Sgiacomo.travaglini@arm.comclass _Param(object): 83813481Sgiacomo.travaglini@arm.com def __init__(self, ptype, *args, **kwargs): 83913481Sgiacomo.travaglini@arm.com if isinstance(ptype, types.StringType): 84013481Sgiacomo.travaglini@arm.com self.ptype_string = ptype 84113481Sgiacomo.travaglini@arm.com elif isinstance(ptype, type): 84213481Sgiacomo.travaglini@arm.com self.ptype = ptype 84313481Sgiacomo.travaglini@arm.com else: 84413481Sgiacomo.travaglini@arm.com raise TypeError, "Param type is not a type (%s)" % ptype 84513481Sgiacomo.travaglini@arm.com 84613481Sgiacomo.travaglini@arm.com if args: 84713481Sgiacomo.travaglini@arm.com if len(args) == 1: 84813481Sgiacomo.travaglini@arm.com self.desc = args[0] 84913481Sgiacomo.travaglini@arm.com elif len(args) == 2: 85013481Sgiacomo.travaglini@arm.com self.default = args[0] 85113481Sgiacomo.travaglini@arm.com self.desc = args[1] 85213481Sgiacomo.travaglini@arm.com else: 85313481Sgiacomo.travaglini@arm.com raise TypeError, 'too many arguments' 85413481Sgiacomo.travaglini@arm.com 85513481Sgiacomo.travaglini@arm.com if kwargs.has_key('desc'): 85613481Sgiacomo.travaglini@arm.com assert(not hasattr(self, 'desc')) 85713481Sgiacomo.travaglini@arm.com self.desc = kwargs['desc'] 85813481Sgiacomo.travaglini@arm.com del kwargs['desc'] 85913481Sgiacomo.travaglini@arm.com 86013481Sgiacomo.travaglini@arm.com if kwargs.has_key('default'): 86113481Sgiacomo.travaglini@arm.com assert(not hasattr(self, 'default')) 86213481Sgiacomo.travaglini@arm.com self.default = kwargs['default'] 86313481Sgiacomo.travaglini@arm.com del kwargs['default'] 86413481Sgiacomo.travaglini@arm.com 86513481Sgiacomo.travaglini@arm.com if kwargs: 86613481Sgiacomo.travaglini@arm.com raise TypeError, 'extra unknown kwargs %s' % kwargs 86713481Sgiacomo.travaglini@arm.com 86813481Sgiacomo.travaglini@arm.com if not hasattr(self, 'desc'): 86913481Sgiacomo.travaglini@arm.com raise TypeError, 'desc attribute missing' 87013481Sgiacomo.travaglini@arm.com 87113481Sgiacomo.travaglini@arm.com def __getattr__(self, attr): 87213481Sgiacomo.travaglini@arm.com if attr == 'ptype': 87313481Sgiacomo.travaglini@arm.com try: 87413481Sgiacomo.travaglini@arm.com self.ptype = eval(self.ptype_string) 87513481Sgiacomo.travaglini@arm.com return self.ptype 87613481Sgiacomo.travaglini@arm.com except: 87713481Sgiacomo.travaglini@arm.com raise TypeError, 'Param.%s: undefined type' % self.ptype_string 87813481Sgiacomo.travaglini@arm.com else: 87913481Sgiacomo.travaglini@arm.com raise AttributeError, "'%s' object has no attribute '%s'" % \ 88013481Sgiacomo.travaglini@arm.com (type(self).__name__, attr) 88113481Sgiacomo.travaglini@arm.com 88213481Sgiacomo.travaglini@arm.com def valid(self, value): 88313481Sgiacomo.travaglini@arm.com if not isinstance(value, Proxy): 88413481Sgiacomo.travaglini@arm.com self.ptype._convert(value) 88513481Sgiacomo.travaglini@arm.com 88613481Sgiacomo.travaglini@arm.com def convert(self, value): 88713481Sgiacomo.travaglini@arm.com return self.ptype._convert(value) 88813481Sgiacomo.travaglini@arm.com 88913481Sgiacomo.travaglini@arm.com def string(self, value): 89013481Sgiacomo.travaglini@arm.com return self.ptype._string(value) 89113481Sgiacomo.travaglini@arm.com 89213481Sgiacomo.travaglini@arm.com def set(self, name, instance, value): 89313481Sgiacomo.travaglini@arm.com instance.__dict__[name] = value 89413481Sgiacomo.travaglini@arm.com 89513481Sgiacomo.travaglini@arm.com def cpp_decl(self, name): 89613481Sgiacomo.travaglini@arm.com return '%s %s;' % (self.ptype._cpp_param_decl, name) 89713481Sgiacomo.travaglini@arm.com 89813481Sgiacomo.travaglini@arm.comclass _ParamProxy(object): 89913481Sgiacomo.travaglini@arm.com def __init__(self, type): 90013481Sgiacomo.travaglini@arm.com self.ptype = type 90113481Sgiacomo.travaglini@arm.com 90213481Sgiacomo.travaglini@arm.com # E.g., Param.Int(5, "number of widgets") 90313481Sgiacomo.travaglini@arm.com def __call__(self, *args, **kwargs): 90413481Sgiacomo.travaglini@arm.com # Param type could be defined only in context of caller (e.g., 90513481Sgiacomo.travaglini@arm.com # for locally defined Enum subclass). Need to go look up the 90613481Sgiacomo.travaglini@arm.com # type in that enclosing scope. 90713481Sgiacomo.travaglini@arm.com caller_frame = inspect.stack()[1][0] 90813481Sgiacomo.travaglini@arm.com ptype = caller_frame.f_locals.get(self.ptype, None) 90913481Sgiacomo.travaglini@arm.com if not ptype: ptype = caller_frame.f_globals.get(self.ptype, None) 91013481Sgiacomo.travaglini@arm.com if not ptype: ptype = globals().get(self.ptype, None) 91113481Sgiacomo.travaglini@arm.com # ptype could still be None due to circular references... we'll 91213481Sgiacomo.travaglini@arm.com # try one more time to evaluate lazily when ptype is first needed. 91313481Sgiacomo.travaglini@arm.com # In the meantime we'll save the type name as a string. 91413481Sgiacomo.travaglini@arm.com if not ptype: ptype = self.ptype 91513481Sgiacomo.travaglini@arm.com return _Param(ptype, *args, **kwargs) 91613481Sgiacomo.travaglini@arm.com 91713481Sgiacomo.travaglini@arm.com def __getattr__(self, attr): 91813481Sgiacomo.travaglini@arm.com if attr == '__bases__': 91913481Sgiacomo.travaglini@arm.com raise AttributeError, '' 92013481Sgiacomo.travaglini@arm.com cls = type(self) 92113481Sgiacomo.travaglini@arm.com return cls(attr) 92213481Sgiacomo.travaglini@arm.com 92313481Sgiacomo.travaglini@arm.com def __setattr__(self, attr, value): 92413481Sgiacomo.travaglini@arm.com if attr != 'ptype': 92513481Sgiacomo.travaglini@arm.com raise AttributeError, \ 92613481Sgiacomo.travaglini@arm.com 'Attribute %s not available in %s' % (attr, self.__class__) 92713481Sgiacomo.travaglini@arm.com super(_ParamProxy, self).__setattr__(attr, value) 92813481Sgiacomo.travaglini@arm.com 92913481Sgiacomo.travaglini@arm.com 93013481Sgiacomo.travaglini@arm.comParam = _ParamProxy(None) 93113481Sgiacomo.travaglini@arm.com 93213481Sgiacomo.travaglini@arm.com# Vector-valued parameter description. Just like Param, except that 93313481Sgiacomo.travaglini@arm.com# the value is a vector (list) of the specified type instead of a 93413481Sgiacomo.travaglini@arm.com# single value. 93513481Sgiacomo.travaglini@arm.comclass _VectorParam(_Param): 93613481Sgiacomo.travaglini@arm.com def __init__(self, type, *args, **kwargs): 93713481Sgiacomo.travaglini@arm.com _Param.__init__(self, type, *args, **kwargs) 93813481Sgiacomo.travaglini@arm.com 93913481Sgiacomo.travaglini@arm.com def valid(self, value): 94013481Sgiacomo.travaglini@arm.com if value == None: 94113481Sgiacomo.travaglini@arm.com return True 94213481Sgiacomo.travaglini@arm.com 94313481Sgiacomo.travaglini@arm.com if issequence(value): 94413481Sgiacomo.travaglini@arm.com for val in value: 94513481Sgiacomo.travaglini@arm.com if not isinstance(val, Proxy): 94613481Sgiacomo.travaglini@arm.com self.ptype._convert(val) 94713481Sgiacomo.travaglini@arm.com elif not isinstance(value, Proxy): 94813481Sgiacomo.travaglini@arm.com self.ptype._convert(value) 94913481Sgiacomo.travaglini@arm.com 95013481Sgiacomo.travaglini@arm.com # Convert assigned value to appropriate type. If the RHS is not a 95113481Sgiacomo.travaglini@arm.com # list or tuple, it generates a single-element list. 95213481Sgiacomo.travaglini@arm.com def convert(self, value): 95313481Sgiacomo.travaglini@arm.com if value == None: 95413481Sgiacomo.travaglini@arm.com return [] 95513481Sgiacomo.travaglini@arm.com 95613481Sgiacomo.travaglini@arm.com if issequence(value): 95713481Sgiacomo.travaglini@arm.com # list: coerce each element into new list 95813481Sgiacomo.travaglini@arm.com return [ self.ptype._convert(v) for v in value ] 95913481Sgiacomo.travaglini@arm.com else: 96013481Sgiacomo.travaglini@arm.com # singleton: coerce & wrap in a list 96113481Sgiacomo.travaglini@arm.com return self.ptype._convert(value) 96213481Sgiacomo.travaglini@arm.com 96313481Sgiacomo.travaglini@arm.com def string(self, value): 96413481Sgiacomo.travaglini@arm.com if issequence(value): 96513481Sgiacomo.travaglini@arm.com return ' '.join([ self.ptype._string(v) for v in value]) 96613481Sgiacomo.travaglini@arm.com else: 96713481Sgiacomo.travaglini@arm.com return self.ptype._string(value) 96813481Sgiacomo.travaglini@arm.com 96913481Sgiacomo.travaglini@arm.com def cpp_decl(self, name): 97013481Sgiacomo.travaglini@arm.com return 'std::vector<%s> %s;' % (self.ptype._cpp_param_decl, name) 97113481Sgiacomo.travaglini@arm.com 97213481Sgiacomo.travaglini@arm.comclass _VectorParamProxy(_ParamProxy): 97313481Sgiacomo.travaglini@arm.com # E.g., VectorParam.Int(5, "number of widgets") 97413481Sgiacomo.travaglini@arm.com def __call__(self, *args, **kwargs): 97513481Sgiacomo.travaglini@arm.com return _VectorParam(self.ptype, *args, **kwargs) 97613481Sgiacomo.travaglini@arm.com 97713481Sgiacomo.travaglini@arm.comVectorParam = _VectorParamProxy(None) 97813481Sgiacomo.travaglini@arm.com 97913481Sgiacomo.travaglini@arm.com##################################################################### 98013481Sgiacomo.travaglini@arm.com# 98113481Sgiacomo.travaglini@arm.com# Parameter Types 98213481Sgiacomo.travaglini@arm.com# 98313481Sgiacomo.travaglini@arm.com# Though native Python types could be used to specify parameter types 98413481Sgiacomo.travaglini@arm.com# (the 'ptype' field of the Param and VectorParam classes), it's more 98513481Sgiacomo.travaglini@arm.com# flexible to define our own set of types. This gives us more control 98613481Sgiacomo.travaglini@arm.com# over how Python expressions are converted to values (via the 98713481Sgiacomo.travaglini@arm.com# __init__() constructor) and how these values are printed out (via 98813481Sgiacomo.travaglini@arm.com# the __str__() conversion method). Eventually we'll need these types 98913481Sgiacomo.travaglini@arm.com# to correspond to distinct C++ types as well. 99013481Sgiacomo.travaglini@arm.com# 99113481Sgiacomo.travaglini@arm.com##################################################################### 99213481Sgiacomo.travaglini@arm.com# Integer parameter type. 99313481Sgiacomo.travaglini@arm.comclass _CheckedInt(object): 99413481Sgiacomo.travaglini@arm.com def _convert(cls, value): 99513481Sgiacomo.travaglini@arm.com t = type(value) 99613481Sgiacomo.travaglini@arm.com if t == bool: 99713481Sgiacomo.travaglini@arm.com return int(value) 99813481Sgiacomo.travaglini@arm.com 99913481Sgiacomo.travaglini@arm.com if t != int and t != long and t != float and t != str: 100013481Sgiacomo.travaglini@arm.com raise TypeError, 'Integer parameter of invalid type %s' % t 100113481Sgiacomo.travaglini@arm.com 100213481Sgiacomo.travaglini@arm.com if t == str or t == float: 100313481Sgiacomo.travaglini@arm.com value = long(value) 100413481Sgiacomo.travaglini@arm.com 100513481Sgiacomo.travaglini@arm.com if not cls._min <= value <= cls._max: 100613481Sgiacomo.travaglini@arm.com raise TypeError, 'Integer parameter out of bounds %d < %d < %d' % \ 100713481Sgiacomo.travaglini@arm.com (cls._min, value, cls._max) 100813481Sgiacomo.travaglini@arm.com 100913481Sgiacomo.travaglini@arm.com return value 101013481Sgiacomo.travaglini@arm.com _convert = classmethod(_convert) 101113481Sgiacomo.travaglini@arm.com 101213481Sgiacomo.travaglini@arm.com def _string(cls, value): 101313481Sgiacomo.travaglini@arm.com return str(value) 101413481Sgiacomo.travaglini@arm.com _string = classmethod(_string) 101513481Sgiacomo.travaglini@arm.com 101613481Sgiacomo.travaglini@arm.comclass CheckedInt(type): 101713481Sgiacomo.travaglini@arm.com def __new__(cls, cppname, min, max): 101813481Sgiacomo.travaglini@arm.com # New class derives from _CheckedInt base with proper bounding 101913481Sgiacomo.travaglini@arm.com # parameters 102013481Sgiacomo.travaglini@arm.com dict = { '_cpp_param_decl' : cppname, '_min' : min, '_max' : max } 102113481Sgiacomo.travaglini@arm.com return type.__new__(cls, cppname, (_CheckedInt, ), dict) 102213481Sgiacomo.travaglini@arm.com 102313481Sgiacomo.travaglini@arm.comclass CheckedIntType(CheckedInt): 102413481Sgiacomo.travaglini@arm.com def __new__(cls, cppname, size, unsigned): 102513481Sgiacomo.travaglini@arm.com dict = {} 102613481Sgiacomo.travaglini@arm.com if unsigned: 102713481Sgiacomo.travaglini@arm.com min = 0 102813481Sgiacomo.travaglini@arm.com max = 2 ** size - 1 102913481Sgiacomo.travaglini@arm.com else: 103013481Sgiacomo.travaglini@arm.com min = -(2 ** (size - 1)) 103113481Sgiacomo.travaglini@arm.com max = (2 ** (size - 1)) - 1 103213481Sgiacomo.travaglini@arm.com 103313481Sgiacomo.travaglini@arm.com return super(cls, CheckedIntType).__new__(cls, cppname, min, max) 103413481Sgiacomo.travaglini@arm.com 103513481Sgiacomo.travaglini@arm.comInt = CheckedIntType('int', 32, False) 103613481Sgiacomo.travaglini@arm.comUnsigned = CheckedIntType('unsigned', 32, True) 103713481Sgiacomo.travaglini@arm.com 103813481Sgiacomo.travaglini@arm.comInt8 = CheckedIntType('int8_t', 8, False) 103913481Sgiacomo.travaglini@arm.comUInt8 = CheckedIntType('uint8_t', 8, True) 104013481Sgiacomo.travaglini@arm.comInt16 = CheckedIntType('int16_t', 16, False) 104113481Sgiacomo.travaglini@arm.comUInt16 = CheckedIntType('uint16_t', 16, True) 104213481Sgiacomo.travaglini@arm.comInt32 = CheckedIntType('int32_t', 32, False) 104313481Sgiacomo.travaglini@arm.comUInt32 = CheckedIntType('uint32_t', 32, True) 104413481Sgiacomo.travaglini@arm.comInt64 = CheckedIntType('int64_t', 64, False) 104513481Sgiacomo.travaglini@arm.comUInt64 = CheckedIntType('uint64_t', 64, True) 104613481Sgiacomo.travaglini@arm.com 104713481Sgiacomo.travaglini@arm.comCounter = CheckedIntType('Counter', 64, True) 104813481Sgiacomo.travaglini@arm.comAddr = CheckedIntType('Addr', 64, True) 104913481Sgiacomo.travaglini@arm.comTick = CheckedIntType('Tick', 64, True) 105013481Sgiacomo.travaglini@arm.com 105113481Sgiacomo.travaglini@arm.comPercent = CheckedInt('int', 0, 100) 105213481Sgiacomo.travaglini@arm.com 105313481Sgiacomo.travaglini@arm.comclass Pair(object): 105413481Sgiacomo.travaglini@arm.com def __init__(self, first, second): 105513481Sgiacomo.travaglini@arm.com self.first = first 105613481Sgiacomo.travaglini@arm.com self.second = second 105713481Sgiacomo.travaglini@arm.com 105813481Sgiacomo.travaglini@arm.comclass _Range(object): 105913481Sgiacomo.travaglini@arm.com def _convert(cls, value): 106013481Sgiacomo.travaglini@arm.com if not isinstance(value, Pair): 106113481Sgiacomo.travaglini@arm.com raise TypeError, 'value %s is not a Pair' % value 106213481Sgiacomo.travaglini@arm.com return Pair(cls._type._convert(value.first), 106313481Sgiacomo.travaglini@arm.com cls._type._convert(value.second)) 106413481Sgiacomo.travaglini@arm.com _convert = classmethod(_convert) 106513481Sgiacomo.travaglini@arm.com 106613481Sgiacomo.travaglini@arm.com def _string(cls, value): 106713481Sgiacomo.travaglini@arm.com return '%s:%s' % (cls._type._string(value.first), 106813481Sgiacomo.travaglini@arm.com cls._type._string(value.second)) 106913481Sgiacomo.travaglini@arm.com _string = classmethod(_string) 107013481Sgiacomo.travaglini@arm.com 107113481Sgiacomo.travaglini@arm.comdef RangeSize(start, size): 107213481Sgiacomo.travaglini@arm.com return Pair(start, start + size - 1) 107313481Sgiacomo.travaglini@arm.com 107413481Sgiacomo.travaglini@arm.comclass Range(type): 107513481Sgiacomo.travaglini@arm.com def __new__(cls, type): 107613481Sgiacomo.travaglini@arm.com dict = { '_cpp_param_decl' : 'Range<%s>' % type._cpp_param_decl, 107713481Sgiacomo.travaglini@arm.com '_type' : type } 107813481Sgiacomo.travaglini@arm.com clsname = 'Range_' + type.__name__ 107913481Sgiacomo.travaglini@arm.com return super(cls, Range).__new__(cls, clsname, (_Range, ), dict) 108013481Sgiacomo.travaglini@arm.com 108113481Sgiacomo.travaglini@arm.comAddrRange = Range(Addr) 108213481Sgiacomo.travaglini@arm.com 108313481Sgiacomo.travaglini@arm.com# Boolean parameter type. 108413481Sgiacomo.travaglini@arm.comclass Bool(object): 108513481Sgiacomo.travaglini@arm.com _cpp_param_decl = 'bool' 108613481Sgiacomo.travaglini@arm.com def _convert(value): 108713481Sgiacomo.travaglini@arm.com t = type(value) 108813481Sgiacomo.travaglini@arm.com if t == bool: 108913481Sgiacomo.travaglini@arm.com return value 109013481Sgiacomo.travaglini@arm.com 109113481Sgiacomo.travaglini@arm.com if t == int or t == long: 109213481Sgiacomo.travaglini@arm.com return bool(value) 109313481Sgiacomo.travaglini@arm.com 109413481Sgiacomo.travaglini@arm.com if t == str: 109513481Sgiacomo.travaglini@arm.com v = value.lower() 109613481Sgiacomo.travaglini@arm.com if v == "true" or v == "t" or v == "yes" or v == "y": 109713481Sgiacomo.travaglini@arm.com return True 109813481Sgiacomo.travaglini@arm.com elif v == "false" or v == "f" or v == "no" or v == "n": 109913481Sgiacomo.travaglini@arm.com return False 110013481Sgiacomo.travaglini@arm.com 110113481Sgiacomo.travaglini@arm.com raise TypeError, 'Bool parameter (%s) of invalid type %s' % (v, t) 110213481Sgiacomo.travaglini@arm.com _convert = staticmethod(_convert) 110313481Sgiacomo.travaglini@arm.com 110413481Sgiacomo.travaglini@arm.com def _string(value): 110513481Sgiacomo.travaglini@arm.com if value: 110613481Sgiacomo.travaglini@arm.com return "true" 110713481Sgiacomo.travaglini@arm.com else: 110813481Sgiacomo.travaglini@arm.com return "false" 110913481Sgiacomo.travaglini@arm.com _string = staticmethod(_string) 111013481Sgiacomo.travaglini@arm.com 111113481Sgiacomo.travaglini@arm.com# String-valued parameter. 111213481Sgiacomo.travaglini@arm.comclass String(object): 111313481Sgiacomo.travaglini@arm.com _cpp_param_decl = 'string' 111413481Sgiacomo.travaglini@arm.com 111513481Sgiacomo.travaglini@arm.com # Constructor. Value must be Python string. 111613481Sgiacomo.travaglini@arm.com def _convert(cls,value): 111713481Sgiacomo.travaglini@arm.com if value is None: 111813481Sgiacomo.travaglini@arm.com return '' 111913481Sgiacomo.travaglini@arm.com if isinstance(value, str): 112013481Sgiacomo.travaglini@arm.com return value 112113481Sgiacomo.travaglini@arm.com 112213481Sgiacomo.travaglini@arm.com raise TypeError, \ 112313481Sgiacomo.travaglini@arm.com "String param got value %s %s" % (repr(value), type(value)) 112413481Sgiacomo.travaglini@arm.com _convert = classmethod(_convert) 112513481Sgiacomo.travaglini@arm.com 112613481Sgiacomo.travaglini@arm.com # Generate printable string version. Not too tricky. 112713481Sgiacomo.travaglini@arm.com def _string(cls, value): 112813481Sgiacomo.travaglini@arm.com return value 112913481Sgiacomo.travaglini@arm.com _string = classmethod(_string) 113013481Sgiacomo.travaglini@arm.com 113113481Sgiacomo.travaglini@arm.com 113213481Sgiacomo.travaglini@arm.comdef IncEthernetAddr(addr, val = 1): 113313481Sgiacomo.travaglini@arm.com bytes = map(lambda x: int(x, 16), addr.split(':')) 113413481Sgiacomo.travaglini@arm.com bytes[5] += val 113513481Sgiacomo.travaglini@arm.com for i in (5, 4, 3, 2, 1): 113613481Sgiacomo.travaglini@arm.com val,rem = divmod(bytes[i], 256) 113713481Sgiacomo.travaglini@arm.com bytes[i] = rem 113813481Sgiacomo.travaglini@arm.com if val == 0: 113913481Sgiacomo.travaglini@arm.com break 114013481Sgiacomo.travaglini@arm.com bytes[i - 1] += val 114113481Sgiacomo.travaglini@arm.com assert(bytes[0] <= 255) 114213481Sgiacomo.travaglini@arm.com return ':'.join(map(lambda x: '%02x' % x, bytes)) 114313481Sgiacomo.travaglini@arm.com 114413481Sgiacomo.travaglini@arm.comclass NextEthernetAddr(object): 114513481Sgiacomo.travaglini@arm.com __metaclass__ = Singleton 114613481Sgiacomo.travaglini@arm.com addr = "00:90:00:00:00:01" 114713481Sgiacomo.travaglini@arm.com 114813481Sgiacomo.travaglini@arm.com def __init__(self, inc = 1): 114913481Sgiacomo.travaglini@arm.com self.value = self.addr 115013481Sgiacomo.travaglini@arm.com self.addr = IncEthernetAddr(self.addr, inc) 115113481Sgiacomo.travaglini@arm.com 115213481Sgiacomo.travaglini@arm.comclass EthernetAddr(object): 115313481Sgiacomo.travaglini@arm.com _cpp_param_decl = 'EthAddr' 115413481Sgiacomo.travaglini@arm.com 115513481Sgiacomo.travaglini@arm.com def _convert(cls, value): 115613481Sgiacomo.travaglini@arm.com if value == NextEthernetAddr: 115713481Sgiacomo.travaglini@arm.com return value 115813481Sgiacomo.travaglini@arm.com 115913481Sgiacomo.travaglini@arm.com if not isinstance(value, str): 116013481Sgiacomo.travaglini@arm.com raise TypeError, "expected an ethernet address and didn't get one" 116113481Sgiacomo.travaglini@arm.com 116213481Sgiacomo.travaglini@arm.com bytes = value.split(':') 116313481Sgiacomo.travaglini@arm.com if len(bytes) != 6: 116413481Sgiacomo.travaglini@arm.com raise TypeError, 'invalid ethernet address %s' % value 116513481Sgiacomo.travaglini@arm.com 116613481Sgiacomo.travaglini@arm.com for byte in bytes: 116713481Sgiacomo.travaglini@arm.com if not 0 <= int(byte) <= 256: 116813481Sgiacomo.travaglini@arm.com raise TypeError, 'invalid ethernet address %s' % value 116913481Sgiacomo.travaglini@arm.com 117013481Sgiacomo.travaglini@arm.com return value 117113481Sgiacomo.travaglini@arm.com _convert = classmethod(_convert) 117213481Sgiacomo.travaglini@arm.com 117313481Sgiacomo.travaglini@arm.com def _string(cls, value): 117413481Sgiacomo.travaglini@arm.com if value == NextEthernetAddr: 117513481Sgiacomo.travaglini@arm.com value = value().value 117613481Sgiacomo.travaglini@arm.com return value 117713481Sgiacomo.travaglini@arm.com _string = classmethod(_string) 117813481Sgiacomo.travaglini@arm.com 117913481Sgiacomo.travaglini@arm.com# Special class for NULL pointers. Note the special check in 118013481Sgiacomo.travaglini@arm.com# make_param_value() above that lets these be assigned where a 118113481Sgiacomo.travaglini@arm.com# SimObject is required. 118213481Sgiacomo.travaglini@arm.com# only one copy of a particular node 118313481Sgiacomo.travaglini@arm.comclass NullSimObject(object): 118413481Sgiacomo.travaglini@arm.com __metaclass__ = Singleton 118513481Sgiacomo.travaglini@arm.com 118613481Sgiacomo.travaglini@arm.com def __call__(cls): 118713481Sgiacomo.travaglini@arm.com return cls 118813481Sgiacomo.travaglini@arm.com 118913481Sgiacomo.travaglini@arm.com def _instantiate(self, parent = None, path = ''): 119013481Sgiacomo.travaglini@arm.com pass 119113481Sgiacomo.travaglini@arm.com 119213481Sgiacomo.travaglini@arm.com def _convert(cls, value): 119313481Sgiacomo.travaglini@arm.com if value == Nxone: 119413481Sgiacomo.travaglini@arm.com return 119513481Sgiacomo.travaglini@arm.com 119613481Sgiacomo.travaglini@arm.com if isinstance(value, cls): 119713481Sgiacomo.travaglini@arm.com return value 119813481Sgiacomo.travaglini@arm.com 119913481Sgiacomo.travaglini@arm.com raise TypeError, 'object %s %s of the wrong type, should be %s' % \ 120013481Sgiacomo.travaglini@arm.com (repr(value), type(value), cls) 120113481Sgiacomo.travaglini@arm.com _convert = classmethod(_convert) 120213481Sgiacomo.travaglini@arm.com 120313481Sgiacomo.travaglini@arm.com def _string(): 120413481Sgiacomo.travaglini@arm.com return 'NULL' 120513481Sgiacomo.travaglini@arm.com _string = staticmethod(_string) 120613481Sgiacomo.travaglini@arm.com 120713481Sgiacomo.travaglini@arm.com# The only instance you'll ever need... 120813481Sgiacomo.travaglini@arm.comNull = NULL = NullSimObject() 120913481Sgiacomo.travaglini@arm.com 121013481Sgiacomo.travaglini@arm.com# Enumerated types are a little more complex. The user specifies the 121113481Sgiacomo.travaglini@arm.com# type as Enum(foo) where foo is either a list or dictionary of 121213481Sgiacomo.travaglini@arm.com# alternatives (typically strings, but not necessarily so). (In the 121313481Sgiacomo.travaglini@arm.com# long run, the integer value of the parameter will be the list index 121413481Sgiacomo.travaglini@arm.com# or the corresponding dictionary value. For now, since we only check 121513481Sgiacomo.travaglini@arm.com# that the alternative is valid and then spit it into a .ini file, 121613481Sgiacomo.travaglini@arm.com# there's not much point in using the dictionary.) 121713481Sgiacomo.travaglini@arm.com 121813481Sgiacomo.travaglini@arm.com# What Enum() must do is generate a new type encapsulating the 121913481Sgiacomo.travaglini@arm.com# provided list/dictionary so that specific values of the parameter 122013481Sgiacomo.travaglini@arm.com# can be instances of that type. We define two hidden internal 122113481Sgiacomo.travaglini@arm.com# classes (_ListEnum and _DictEnum) to serve as base classes, then 122213481Sgiacomo.travaglini@arm.com# derive the new type from the appropriate base class on the fly. 122313481Sgiacomo.travaglini@arm.com 122413481Sgiacomo.travaglini@arm.com 122513481Sgiacomo.travaglini@arm.com# Metaclass for Enum types 122613481Sgiacomo.travaglini@arm.comclass MetaEnum(type): 122713481Sgiacomo.travaglini@arm.com 122813481Sgiacomo.travaglini@arm.com def __init__(cls, name, bases, init_dict): 122913481Sgiacomo.travaglini@arm.com if init_dict.has_key('map'): 123013481Sgiacomo.travaglini@arm.com if not isinstance(cls.map, dict): 123113481Sgiacomo.travaglini@arm.com raise TypeError, "Enum-derived class attribute 'map' " \ 123213481Sgiacomo.travaglini@arm.com "must be of type dict" 123313481Sgiacomo.travaglini@arm.com # build list of value strings from map 123413481Sgiacomo.travaglini@arm.com cls.vals = cls.map.keys() 123513481Sgiacomo.travaglini@arm.com cls.vals.sort() 123613481Sgiacomo.travaglini@arm.com elif init_dict.has_key('vals'): 123713481Sgiacomo.travaglini@arm.com if not isinstance(cls.vals, list): 123813481Sgiacomo.travaglini@arm.com raise TypeError, "Enum-derived class attribute 'vals' " \ 123913481Sgiacomo.travaglini@arm.com "must be of type list" 124013481Sgiacomo.travaglini@arm.com # build string->value map from vals sequence 124113481Sgiacomo.travaglini@arm.com cls.map = {} 124213481Sgiacomo.travaglini@arm.com for idx,val in enumerate(cls.vals): 124313481Sgiacomo.travaglini@arm.com cls.map[val] = idx 124413481Sgiacomo.travaglini@arm.com else: 124513481Sgiacomo.travaglini@arm.com raise TypeError, "Enum-derived class must define "\ 124613481Sgiacomo.travaglini@arm.com "attribute 'map' or 'vals'" 124713481Sgiacomo.travaglini@arm.com 124813481Sgiacomo.travaglini@arm.com cls._cpp_param_decl = name 124913481Sgiacomo.travaglini@arm.com 125013481Sgiacomo.travaglini@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 125113481Sgiacomo.travaglini@arm.com 125213481Sgiacomo.travaglini@arm.com def cpp_declare(cls): 125313481Sgiacomo.travaglini@arm.com s = 'enum %s {\n ' % cls.__name__ 125413481Sgiacomo.travaglini@arm.com s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals]) 125513481Sgiacomo.travaglini@arm.com s += '\n};\n' 125613481Sgiacomo.travaglini@arm.com return s 125713481Sgiacomo.travaglini@arm.com 125813481Sgiacomo.travaglini@arm.com# Base class for enum types. 125913481Sgiacomo.travaglini@arm.comclass Enum(object): 126013481Sgiacomo.travaglini@arm.com __metaclass__ = MetaEnum 126113481Sgiacomo.travaglini@arm.com vals = [] 126213481Sgiacomo.travaglini@arm.com 126313481Sgiacomo.travaglini@arm.com def _convert(self, value): 126413481Sgiacomo.travaglini@arm.com if value not in self.map: 126513481Sgiacomo.travaglini@arm.com raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 126613481Sgiacomo.travaglini@arm.com % (value, self.vals) 126713481Sgiacomo.travaglini@arm.com return value 126813481Sgiacomo.travaglini@arm.com _convert = classmethod(_convert) 126913481Sgiacomo.travaglini@arm.com 127013481Sgiacomo.travaglini@arm.com # Generate printable string version of value. 127113481Sgiacomo.travaglini@arm.com def _string(self, value): 127213481Sgiacomo.travaglini@arm.com return str(value) 127313481Sgiacomo.travaglini@arm.com _string = classmethod(_string) 127413481Sgiacomo.travaglini@arm.com# 127513481Sgiacomo.travaglini@arm.com# "Constants"... handy aliases for various values. 127613481Sgiacomo.travaglini@arm.com# 127713481Sgiacomo.travaglini@arm.com 127813481Sgiacomo.travaglini@arm.com# Some memory range specifications use this as a default upper bound. 127913481Sgiacomo.travaglini@arm.comMAX_ADDR = Addr._max 128013481Sgiacomo.travaglini@arm.comMaxTick = Tick._max 128113481Sgiacomo.travaglini@arm.com 128213481Sgiacomo.travaglini@arm.com# For power-of-two sizing, e.g. 64*K gives an integer value 65536. 128313481Sgiacomo.travaglini@arm.comK = 1024 128413481Sgiacomo.travaglini@arm.comM = K*K 128513481Sgiacomo.travaglini@arm.comG = K*M 128613481Sgiacomo.travaglini@arm.com 128713481Sgiacomo.travaglini@arm.com##################################################################### 128813481Sgiacomo.travaglini@arm.com 128913481Sgiacomo.travaglini@arm.com# The final hook to generate .ini files. Called from configuration 129013481Sgiacomo.travaglini@arm.com# script once config is built. 129113481Sgiacomo.travaglini@arm.comdef instantiate(root): 129213481Sgiacomo.travaglini@arm.com if not issubclass(root, Root): 129313481Sgiacomo.travaglini@arm.com raise AttributeError, 'Can only instantiate the Root of the tree' 129413481Sgiacomo.travaglini@arm.com 129513481Sgiacomo.travaglini@arm.com instance = root.instantiate('root') 129613481Sgiacomo.travaglini@arm.com instance.fixup() 129713481Sgiacomo.travaglini@arm.com instance.display() 129813481Sgiacomo.travaglini@arm.com if not noDot: 129913481Sgiacomo.travaglini@arm.com dot = pydot.Dot() 130013481Sgiacomo.travaglini@arm.com instance.outputDot(dot) 130113481Sgiacomo.travaglini@arm.com dot.orientation = "portrait" 130213481Sgiacomo.travaglini@arm.com dot.size = "8.5,11" 130313481Sgiacomo.travaglini@arm.com dot.ranksep="equally" 130413481Sgiacomo.travaglini@arm.com dot.rank="samerank" 130513481Sgiacomo.travaglini@arm.com dot.write("config.dot") 130613481Sgiacomo.travaglini@arm.com dot.write_ps("config.ps") 130713481Sgiacomo.travaglini@arm.com 130813481Sgiacomo.travaglini@arm.com# SimObject is a minimal extension of ConfigNode, implementing a 130913481Sgiacomo.travaglini@arm.com# hierarchy node that corresponds to an M5 SimObject. It prints out a 131013481Sgiacomo.travaglini@arm.com# "type=" line to indicate its SimObject class, prints out the 131113481Sgiacomo.travaglini@arm.com# assigned parameters corresponding to its class, and allows 131213481Sgiacomo.travaglini@arm.com# parameters to be set by keyword in the constructor. Note that most 131313481Sgiacomo.travaglini@arm.com# of the heavy lifting for the SimObject param handling is done in the 131413481Sgiacomo.travaglini@arm.com# MetaConfigNode metaclass. 131513481Sgiacomo.travaglini@arm.comclass SimObject(ConfigNode): 131613481Sgiacomo.travaglini@arm.com __metaclass__ = MetaSimObject 131713481Sgiacomo.travaglini@arm.com type = 'SimObject' 131813481Sgiacomo.travaglini@arm.com 131913481Sgiacomo.travaglini@arm.comfrom objects import * 132013481Sgiacomo.travaglini@arm.com 132113481Sgiacomo.travaglini@arm.comcpp_classes = MetaSimObject.cpp_classes 132213481Sgiacomo.travaglini@arm.comcpp_classes.sort() 132313481Sgiacomo.travaglini@arm.com