SimObject.py revision 1605
112027Sjungma@eit.uni-kl.de# Copyright (c) 2004 The Regents of The University of Michigan 212027Sjungma@eit.uni-kl.de# All rights reserved. 312027Sjungma@eit.uni-kl.de# 412027Sjungma@eit.uni-kl.de# Redistribution and use in source and binary forms, with or without 512027Sjungma@eit.uni-kl.de# modification, are permitted provided that the following conditions are 612027Sjungma@eit.uni-kl.de# met: redistributions of source code must retain the above copyright 712027Sjungma@eit.uni-kl.de# notice, this list of conditions and the following disclaimer; 812027Sjungma@eit.uni-kl.de# redistributions in binary form must reproduce the above copyright 912027Sjungma@eit.uni-kl.de# notice, this list of conditions and the following disclaimer in the 1012027Sjungma@eit.uni-kl.de# documentation and/or other materials provided with the distribution; 1112027Sjungma@eit.uni-kl.de# neither the name of the copyright holders nor the names of its 1212027Sjungma@eit.uni-kl.de# contributors may be used to endorse or promote products derived from 1312027Sjungma@eit.uni-kl.de# this software without specific prior written permission. 1412027Sjungma@eit.uni-kl.de# 1512027Sjungma@eit.uni-kl.de# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1612027Sjungma@eit.uni-kl.de# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1712027Sjungma@eit.uni-kl.de# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1812027Sjungma@eit.uni-kl.de# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1912027Sjungma@eit.uni-kl.de# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2012027Sjungma@eit.uni-kl.de# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2112027Sjungma@eit.uni-kl.de# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2212027Sjungma@eit.uni-kl.de# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2312027Sjungma@eit.uni-kl.de# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2412027Sjungma@eit.uni-kl.de# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2512027Sjungma@eit.uni-kl.de# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2612027Sjungma@eit.uni-kl.de 2712027Sjungma@eit.uni-kl.defrom __future__ import generators 2812027Sjungma@eit.uni-kl.deimport os, re, sys, types, inspect 2912027Sjungma@eit.uni-kl.de 3012027Sjungma@eit.uni-kl.defrom m5 import panic, env 3112027Sjungma@eit.uni-kl.defrom convert import * 3212027Sjungma@eit.uni-kl.defrom multidict import multidict 3312027Sjungma@eit.uni-kl.de 3412027Sjungma@eit.uni-kl.denoDot = False 3512027Sjungma@eit.uni-kl.detry: 3612027Sjungma@eit.uni-kl.de import pydot 3712027Sjungma@eit.uni-kl.deexcept: 3812027Sjungma@eit.uni-kl.de noDot = True 3912027Sjungma@eit.uni-kl.de 4012027Sjungma@eit.uni-kl.declass Singleton(type): 4112027Sjungma@eit.uni-kl.de def __call__(cls, *args, **kwargs): 4212027Sjungma@eit.uni-kl.de if hasattr(cls, '_instance'): 4312027Sjungma@eit.uni-kl.de return cls._instance 4412027Sjungma@eit.uni-kl.de 4512027Sjungma@eit.uni-kl.de cls._instance = super(Singleton, cls).__call__(*args, **kwargs) 4612027Sjungma@eit.uni-kl.de return cls._instance 4712027Sjungma@eit.uni-kl.de 4812027Sjungma@eit.uni-kl.de##################################################################### 4912027Sjungma@eit.uni-kl.de# 5012027Sjungma@eit.uni-kl.de# M5 Python Configuration Utility 5112027Sjungma@eit.uni-kl.de# 5212027Sjungma@eit.uni-kl.de# The basic idea is to write simple Python programs that build Python 5312027Sjungma@eit.uni-kl.de# objects corresponding to M5 SimObjects for the deisred simulation 5412027Sjungma@eit.uni-kl.de# configuration. For now, the Python emits a .ini file that can be 5512027Sjungma@eit.uni-kl.de# parsed by M5. In the future, some tighter integration between M5 5612027Sjungma@eit.uni-kl.de# and the Python interpreter may allow bypassing the .ini file. 5712027Sjungma@eit.uni-kl.de# 5812027Sjungma@eit.uni-kl.de# Each SimObject class in M5 is represented by a Python class with the 5912027Sjungma@eit.uni-kl.de# same name. The Python inheritance tree mirrors the M5 C++ tree 6012027Sjungma@eit.uni-kl.de# (e.g., SimpleCPU derives from BaseCPU in both cases, and all 6112027Sjungma@eit.uni-kl.de# SimObjects inherit from a single SimObject base class). To specify 6212027Sjungma@eit.uni-kl.de# an instance of an M5 SimObject in a configuration, the user simply 6312027Sjungma@eit.uni-kl.de# instantiates the corresponding Python object. The parameters for 6412027Sjungma@eit.uni-kl.de# that SimObject are given by assigning to attributes of the Python 6512027Sjungma@eit.uni-kl.de# object, either using keyword assignment in the constructor or in 6612027Sjungma@eit.uni-kl.de# separate assignment statements. For example: 6712027Sjungma@eit.uni-kl.de# 6812027Sjungma@eit.uni-kl.de# cache = BaseCache('my_cache', root, size='64KB') 6912027Sjungma@eit.uni-kl.de# cache.hit_latency = 3 7012027Sjungma@eit.uni-kl.de# cache.assoc = 8 7112027Sjungma@eit.uni-kl.de# 7212027Sjungma@eit.uni-kl.de# (The first two constructor arguments specify the name of the created 7312027Sjungma@eit.uni-kl.de# cache and its parent node in the hierarchy.) 7412027Sjungma@eit.uni-kl.de# 7512027Sjungma@eit.uni-kl.de# The magic lies in the mapping of the Python attributes for SimObject 7612027Sjungma@eit.uni-kl.de# classes to the actual SimObject parameter specifications. This 7712027Sjungma@eit.uni-kl.de# allows parameter validity checking in the Python code. Continuing 7812027Sjungma@eit.uni-kl.de# the example above, the statements "cache.blurfl=3" or 7912027Sjungma@eit.uni-kl.de# "cache.assoc='hello'" would both result in runtime errors in Python, 8012027Sjungma@eit.uni-kl.de# since the BaseCache object has no 'blurfl' parameter and the 'assoc' 8112027Sjungma@eit.uni-kl.de# parameter requires an integer, respectively. This magic is done 8212027Sjungma@eit.uni-kl.de# primarily by overriding the special __setattr__ method that controls 8312027Sjungma@eit.uni-kl.de# assignment to object attributes. 8412027Sjungma@eit.uni-kl.de# 8512027Sjungma@eit.uni-kl.de# The Python module provides another class, ConfigNode, which is a 8612027Sjungma@eit.uni-kl.de# superclass of SimObject. ConfigNode implements the parent/child 8712027Sjungma@eit.uni-kl.de# relationship for building the configuration hierarchy tree. 8812027Sjungma@eit.uni-kl.de# Concrete instances of ConfigNode can be used to group objects in the 8912027Sjungma@eit.uni-kl.de# hierarchy, but do not correspond to SimObjects themselves (like a 9012027Sjungma@eit.uni-kl.de# .ini section with "children=" but no "type=". 9112027Sjungma@eit.uni-kl.de# 9212027Sjungma@eit.uni-kl.de# Once a set of Python objects have been instantiated in a hierarchy, 9312027Sjungma@eit.uni-kl.de# calling 'instantiate(obj)' (where obj is the root of the hierarchy) 9412027Sjungma@eit.uni-kl.de# will generate a .ini file. See simple-4cpu.py for an example 9512027Sjungma@eit.uni-kl.de# (corresponding to m5-test/simple-4cpu.ini). 9612027Sjungma@eit.uni-kl.de# 9712027Sjungma@eit.uni-kl.de##################################################################### 9812027Sjungma@eit.uni-kl.de 9912027Sjungma@eit.uni-kl.de##################################################################### 10012027Sjungma@eit.uni-kl.de# 10112027Sjungma@eit.uni-kl.de# ConfigNode/SimObject classes 10212027Sjungma@eit.uni-kl.de# 10312027Sjungma@eit.uni-kl.de# The Python class hierarchy rooted by ConfigNode (which is the base 10412027Sjungma@eit.uni-kl.de# class of SimObject, which in turn is the base class of all other M5 10512027Sjungma@eit.uni-kl.de# SimObject classes) has special attribute behavior. In general, an 10612027Sjungma@eit.uni-kl.de# object in this hierarchy has three categories of attribute-like 10712027Sjungma@eit.uni-kl.de# things: 10812027Sjungma@eit.uni-kl.de# 10912027Sjungma@eit.uni-kl.de# 1. Regular Python methods and variables. These must start with an 11012027Sjungma@eit.uni-kl.de# underscore to be treated normally. 11112027Sjungma@eit.uni-kl.de# 11212027Sjungma@eit.uni-kl.de# 2. SimObject parameters. These values are stored as normal Python 11312027Sjungma@eit.uni-kl.de# attributes, but all assignments to these attributes are checked 11412027Sjungma@eit.uni-kl.de# against the pre-defined set of parameters stored in the class's 11512027Sjungma@eit.uni-kl.de# _params dictionary. Assignments to attributes that do not 11612027Sjungma@eit.uni-kl.de# correspond to predefined parameters, or that are not of the correct 11712027Sjungma@eit.uni-kl.de# type, incur runtime errors. 11812027Sjungma@eit.uni-kl.de# 11912027Sjungma@eit.uni-kl.de# 3. Hierarchy children. The child nodes of a ConfigNode are stored 12012027Sjungma@eit.uni-kl.de# in the node's _children dictionary, but can be accessed using the 12112027Sjungma@eit.uni-kl.de# Python attribute dot-notation (just as they are printed out by the 12212027Sjungma@eit.uni-kl.de# simulator). Children cannot be created using attribute assigment; 12312027Sjungma@eit.uni-kl.de# they must be added by specifying the parent node in the child's 12412027Sjungma@eit.uni-kl.de# constructor or using the '+=' operator. 12512027Sjungma@eit.uni-kl.de 12612027Sjungma@eit.uni-kl.de# The SimObject parameters are the most complex, for a few reasons. 12712027Sjungma@eit.uni-kl.de# First, both parameter descriptions and parameter values are 12812027Sjungma@eit.uni-kl.de# inherited. Thus parameter description lookup must go up the 12912027Sjungma@eit.uni-kl.de# inheritance chain like normal attribute lookup, but this behavior 13012027Sjungma@eit.uni-kl.de# must be explicitly coded since the lookup occurs in each class's 13112027Sjungma@eit.uni-kl.de# _params attribute. Second, because parameter values can be set 13212027Sjungma@eit.uni-kl.de# on SimObject classes (to implement default values), the parameter 13312027Sjungma@eit.uni-kl.de# checking behavior must be enforced on class attribute assignments as 13412027Sjungma@eit.uni-kl.de# well as instance attribute assignments. Finally, because we allow 13512027Sjungma@eit.uni-kl.de# class specialization via inheritance (e.g., see the L1Cache class in 13612027Sjungma@eit.uni-kl.de# the simple-4cpu.py example), we must do parameter checking even on 13712027Sjungma@eit.uni-kl.de# class instantiation. To provide all these features, we use a 13812027Sjungma@eit.uni-kl.de# metaclass to define most of the SimObject parameter behavior for 13912027Sjungma@eit.uni-kl.de# this class hierarchy. 14012027Sjungma@eit.uni-kl.de# 14112027Sjungma@eit.uni-kl.de##################################################################### 14212027Sjungma@eit.uni-kl.de 14312027Sjungma@eit.uni-kl.declass Proxy(object): 14412027Sjungma@eit.uni-kl.de def __init__(self, path): 14512027Sjungma@eit.uni-kl.de self._object = None 14612027Sjungma@eit.uni-kl.de if path == 'any': 14712027Sjungma@eit.uni-kl.de self._path = None 14812027Sjungma@eit.uni-kl.de else: 14912027Sjungma@eit.uni-kl.de # path is a list of (attr,index) tuples 15012027Sjungma@eit.uni-kl.de self._path = [(path,None)] 15112027Sjungma@eit.uni-kl.de self._index = None 15212027Sjungma@eit.uni-kl.de self._multiplier = None 15312027Sjungma@eit.uni-kl.de 15412027Sjungma@eit.uni-kl.de def __getattr__(self, attr): 15512027Sjungma@eit.uni-kl.de # python uses __bases__ internally for inheritance 15612027Sjungma@eit.uni-kl.de if attr == '__bases__': 15712027Sjungma@eit.uni-kl.de return super(Proxy, self).__getattr__(self, attr) 15812027Sjungma@eit.uni-kl.de if (self._path == None): 15912027Sjungma@eit.uni-kl.de panic("Can't add attributes to 'any' proxy") 16012027Sjungma@eit.uni-kl.de self._path.append((attr,None)) 16112027Sjungma@eit.uni-kl.de return self 16212027Sjungma@eit.uni-kl.de 16312027Sjungma@eit.uni-kl.de def __setattr__(self, attr, value): 16412027Sjungma@eit.uni-kl.de if not attr.startswith('_'): 16512027Sjungma@eit.uni-kl.de raise AttributeError, 'cannot set attribute %s' % attr 16612027Sjungma@eit.uni-kl.de super(Proxy, self).__setattr__(attr, value) 16712027Sjungma@eit.uni-kl.de 16812027Sjungma@eit.uni-kl.de # support indexing on proxies (e.g., parent.cpu[0]) 16912027Sjungma@eit.uni-kl.de def __getitem__(self, key): 17012027Sjungma@eit.uni-kl.de if not isinstance(key, int): 17112027Sjungma@eit.uni-kl.de raise TypeError, "Proxy object requires integer index" 17212027Sjungma@eit.uni-kl.de if self._path == None: 17312027Sjungma@eit.uni-kl.de raise IndexError, "Index applied to 'any' proxy" 17412027Sjungma@eit.uni-kl.de # replace index portion of last path element with new index 17512027Sjungma@eit.uni-kl.de self._path[-1] = (self._path[-1][0], key) 17612027Sjungma@eit.uni-kl.de return self 17712027Sjungma@eit.uni-kl.de 17812027Sjungma@eit.uni-kl.de # support multiplying proxies by constants 17912027Sjungma@eit.uni-kl.de def __mul__(self, other): 18012027Sjungma@eit.uni-kl.de if not isinstance(other, int): 18112027Sjungma@eit.uni-kl.de raise TypeError, "Proxy multiplier must be integer" 18212027Sjungma@eit.uni-kl.de if self._multiplier == None: 18312027Sjungma@eit.uni-kl.de self._multiplier = other 18412027Sjungma@eit.uni-kl.de else: 18512027Sjungma@eit.uni-kl.de # support chained multipliers 18612027Sjungma@eit.uni-kl.de self._multiplier *= other 18712027Sjungma@eit.uni-kl.de return self 18812027Sjungma@eit.uni-kl.de 18912027Sjungma@eit.uni-kl.de def _mulcheck(self, result): 19012027Sjungma@eit.uni-kl.de if self._multiplier == None: 19112027Sjungma@eit.uni-kl.de return result 19212027Sjungma@eit.uni-kl.de if not isinstance(result, int): 19312027Sjungma@eit.uni-kl.de raise TypeError, "Proxy with multiplier resolves to " \ 19412027Sjungma@eit.uni-kl.de "non-integer value" 19512027Sjungma@eit.uni-kl.de return result * self._multiplier 19612027Sjungma@eit.uni-kl.de 19712027Sjungma@eit.uni-kl.de def unproxy(self, base, ptype): 19812027Sjungma@eit.uni-kl.de obj = base 19912027Sjungma@eit.uni-kl.de done = False 20012027Sjungma@eit.uni-kl.de while not done: 20112027Sjungma@eit.uni-kl.de if obj is None: 20212027Sjungma@eit.uni-kl.de raise AttributeError, \ 20312027Sjungma@eit.uni-kl.de 'Parent of %s type %s not found at path %s' \ 20412027Sjungma@eit.uni-kl.de % (base.name, ptype, self._path) 20512027Sjungma@eit.uni-kl.de 20612027Sjungma@eit.uni-kl.de result, done = obj.find(ptype, self._path) 20712027Sjungma@eit.uni-kl.de obj = obj.parent 20812027Sjungma@eit.uni-kl.de 20912027Sjungma@eit.uni-kl.de if isinstance(result, Proxy): 21012027Sjungma@eit.uni-kl.de result = result.unproxy(obj, ptype) 21112027Sjungma@eit.uni-kl.de 21212027Sjungma@eit.uni-kl.de return self._mulcheck(result) 21312027Sjungma@eit.uni-kl.de 21412027Sjungma@eit.uni-kl.de def getindex(obj, index): 21512027Sjungma@eit.uni-kl.de if index == None: 21612027Sjungma@eit.uni-kl.de return obj 21712027Sjungma@eit.uni-kl.de try: 21812027Sjungma@eit.uni-kl.de obj = obj[index] 21912027Sjungma@eit.uni-kl.de except TypeError: 22012027Sjungma@eit.uni-kl.de if index != 0: 22112027Sjungma@eit.uni-kl.de raise 22212027Sjungma@eit.uni-kl.de # if index is 0 and item is not subscriptable, just 22312027Sjungma@eit.uni-kl.de # use item itself (so cpu[0] works on uniprocessors) 22412027Sjungma@eit.uni-kl.de return obj 22512027Sjungma@eit.uni-kl.de getindex = staticmethod(getindex) 22612027Sjungma@eit.uni-kl.de 22712027Sjungma@eit.uni-kl.declass ProxyFactory(object): 22812027Sjungma@eit.uni-kl.de def __getattr__(self, attr): 22912027Sjungma@eit.uni-kl.de return Proxy(attr) 23012027Sjungma@eit.uni-kl.de 23112027Sjungma@eit.uni-kl.de# global object for handling parent.foo proxies 23212027Sjungma@eit.uni-kl.deparent = ProxyFactory() 23312027Sjungma@eit.uni-kl.de 23412027Sjungma@eit.uni-kl.dedef isSubClass(value, cls): 23512027Sjungma@eit.uni-kl.de try: 23612027Sjungma@eit.uni-kl.de return issubclass(value, cls) 23712027Sjungma@eit.uni-kl.de except: 23812027Sjungma@eit.uni-kl.de return False 23912027Sjungma@eit.uni-kl.de 24012027Sjungma@eit.uni-kl.dedef isConfigNode(value): 24112027Sjungma@eit.uni-kl.de try: 24212027Sjungma@eit.uni-kl.de return issubclass(value, ConfigNode) 24312027Sjungma@eit.uni-kl.de except: 24412027Sjungma@eit.uni-kl.de return False 24512027Sjungma@eit.uni-kl.de 24612027Sjungma@eit.uni-kl.dedef isSimObject(value): 24712027Sjungma@eit.uni-kl.de try: 24812027Sjungma@eit.uni-kl.de return issubclass(value, SimObject) 24912027Sjungma@eit.uni-kl.de except: 25012027Sjungma@eit.uni-kl.de return False 25112027Sjungma@eit.uni-kl.de 25212027Sjungma@eit.uni-kl.dedef isSimObjSequence(value): 25312027Sjungma@eit.uni-kl.de if not isinstance(value, (list, tuple)): 25412027Sjungma@eit.uni-kl.de return False 25512027Sjungma@eit.uni-kl.de 25612027Sjungma@eit.uni-kl.de for val in value: 25712027Sjungma@eit.uni-kl.de if not isNullPointer(val) and not isConfigNode(val): 25812027Sjungma@eit.uni-kl.de return False 25912027Sjungma@eit.uni-kl.de 26012027Sjungma@eit.uni-kl.de return True 26112027Sjungma@eit.uni-kl.de 26212027Sjungma@eit.uni-kl.dedef isParamContext(value): 26312027Sjungma@eit.uni-kl.de try: 26412027Sjungma@eit.uni-kl.de return issubclass(value, ParamContext) 26512027Sjungma@eit.uni-kl.de except: 26612027Sjungma@eit.uni-kl.de return False 26712027Sjungma@eit.uni-kl.de 26812027Sjungma@eit.uni-kl.de 26912027Sjungma@eit.uni-kl.declass_decorator = 'M5M5_SIMOBJECT_' 27012027Sjungma@eit.uni-kl.deexpr_decorator = 'M5M5_EXPRESSION_' 27112027Sjungma@eit.uni-kl.dedot_decorator = '_M5M5_DOT_' 27212027Sjungma@eit.uni-kl.de 27312027Sjungma@eit.uni-kl.de# 'Global' map of legitimate types for SimObject parameters. 27412027Sjungma@eit.uni-kl.deparam_types = {} 27512027Sjungma@eit.uni-kl.de 27612027Sjungma@eit.uni-kl.de# Dummy base class to identify types that are legitimate for SimObject 27712027Sjungma@eit.uni-kl.de# parameters. 27812027Sjungma@eit.uni-kl.declass ParamType(object): 27912027Sjungma@eit.uni-kl.de pass 28012027Sjungma@eit.uni-kl.de 28112027Sjungma@eit.uni-kl.de# Add types defined in given context (dict or module) that are derived 28212027Sjungma@eit.uni-kl.de# from ParamType to param_types map. 28312027Sjungma@eit.uni-kl.dedef add_param_types(ctx): 28412027Sjungma@eit.uni-kl.de if isinstance(ctx, types.DictType): 28512027Sjungma@eit.uni-kl.de source_dict = ctx 28612027Sjungma@eit.uni-kl.de elif isinstance(ctx, types.ModuleType): 28712027Sjungma@eit.uni-kl.de source_dict = ctx.__dict__ 28812027Sjungma@eit.uni-kl.de else: 28912027Sjungma@eit.uni-kl.de raise TypeError, \ 29012027Sjungma@eit.uni-kl.de "m5.config.add_param_types requires dict or module as arg" 29112027Sjungma@eit.uni-kl.de for key,val in source_dict.iteritems(): 29212027Sjungma@eit.uni-kl.de if isinstance(val, type) and issubclass(val, ParamType): 29312027Sjungma@eit.uni-kl.de param_types[key] = val 29412027Sjungma@eit.uni-kl.de 29512027Sjungma@eit.uni-kl.de# The metaclass for ConfigNode (and thus for everything that derives 29612027Sjungma@eit.uni-kl.de# from ConfigNode, including SimObject). This class controls how new 29712027Sjungma@eit.uni-kl.de# classes that derive from ConfigNode are instantiated, and provides 29812027Sjungma@eit.uni-kl.de# inherited class behavior (just like a class controls how instances 29912027Sjungma@eit.uni-kl.de# of that class are instantiated, and provides inherited instance 30012027Sjungma@eit.uni-kl.de# behavior). 30112027Sjungma@eit.uni-kl.declass MetaConfigNode(type): 30212027Sjungma@eit.uni-kl.de # Attributes that can be set only at initialization time 30312027Sjungma@eit.uni-kl.de init_keywords = {} 30412027Sjungma@eit.uni-kl.de # Attributes that can be set any time 30512027Sjungma@eit.uni-kl.de keywords = { 'check' : types.FunctionType, 30612027Sjungma@eit.uni-kl.de 'children' : types.ListType } 30712027Sjungma@eit.uni-kl.de 30812027Sjungma@eit.uni-kl.de # __new__ is called before __init__, and is where the statements 30912027Sjungma@eit.uni-kl.de # in the body of the class definition get loaded into the class's 31012027Sjungma@eit.uni-kl.de # __dict__. We intercept this to filter out parameter assignments 31112027Sjungma@eit.uni-kl.de # and only allow "private" attributes to be passed to the base 31212027Sjungma@eit.uni-kl.de # __new__ (starting with underscore). 31312027Sjungma@eit.uni-kl.de def __new__(mcls, name, bases, dict): 31412027Sjungma@eit.uni-kl.de # Copy "private" attributes (including special methods such as __new__) 31512027Sjungma@eit.uni-kl.de # to the official dict. Everything else goes in _init_dict to be 31612027Sjungma@eit.uni-kl.de # filtered in __init__. 31712027Sjungma@eit.uni-kl.de cls_dict = {} 31812027Sjungma@eit.uni-kl.de for key,val in dict.items(): 31912027Sjungma@eit.uni-kl.de if key.startswith('_'): 32012027Sjungma@eit.uni-kl.de cls_dict[key] = val 32112027Sjungma@eit.uni-kl.de del dict[key] 32212027Sjungma@eit.uni-kl.de cls_dict['_init_dict'] = dict 32312027Sjungma@eit.uni-kl.de return super(MetaConfigNode, mcls).__new__(mcls, name, bases, cls_dict) 32412027Sjungma@eit.uni-kl.de 32512027Sjungma@eit.uni-kl.de # initialization 32612027Sjungma@eit.uni-kl.de def __init__(cls, name, bases, dict): 32712027Sjungma@eit.uni-kl.de super(MetaConfigNode, cls).__init__(name, bases, dict) 32812027Sjungma@eit.uni-kl.de 32912027Sjungma@eit.uni-kl.de # initialize required attributes 33012027Sjungma@eit.uni-kl.de cls._params = multidict() 33112027Sjungma@eit.uni-kl.de cls._values = multidict() 33212027Sjungma@eit.uni-kl.de cls._param_types = {} 33312027Sjungma@eit.uni-kl.de cls._bases = [c for c in cls.__mro__ if isConfigNode(c)] 33412027Sjungma@eit.uni-kl.de cls._anon_subclass_counter = 0 33512027Sjungma@eit.uni-kl.de 33612027Sjungma@eit.uni-kl.de # We don't support multiple inheritence. If you want to, you 33712027Sjungma@eit.uni-kl.de # must fix multidict to deal with it properly. 33812027Sjungma@eit.uni-kl.de cnbase = [ base for base in bases if isConfigNode(base) ] 33912027Sjungma@eit.uni-kl.de if len(cnbase) == 1: 34012027Sjungma@eit.uni-kl.de # If your parent has a value in it that's a config node, clone 34112027Sjungma@eit.uni-kl.de # it. Do this now so if we update any of the values' 34212027Sjungma@eit.uni-kl.de # attributes we are updating the clone and not the original. 34312027Sjungma@eit.uni-kl.de for key,val in cnbase[0]._values.iteritems(): 34412027Sjungma@eit.uni-kl.de 34512027Sjungma@eit.uni-kl.de # don't clone if (1) we're about to overwrite it with 34612027Sjungma@eit.uni-kl.de # a local setting or (2) we've already cloned a copy 34712027Sjungma@eit.uni-kl.de # from an earlier (more derived) base 34812027Sjungma@eit.uni-kl.de if cls._init_dict.has_key(key) or cls._values.has_key(key): 34912027Sjungma@eit.uni-kl.de continue 35012027Sjungma@eit.uni-kl.de 35112027Sjungma@eit.uni-kl.de if isConfigNode(val): 35212027Sjungma@eit.uni-kl.de cls._values[key] = val() 35312027Sjungma@eit.uni-kl.de elif isSimObjSequence(val) and len(val): 35412027Sjungma@eit.uni-kl.de cls._values[key] = [ v() for v in val ] 35512027Sjungma@eit.uni-kl.de 35612027Sjungma@eit.uni-kl.de cls._params.parent = cnbase[0]._params 35712027Sjungma@eit.uni-kl.de cls._values.parent = cnbase[0]._values 35812027Sjungma@eit.uni-kl.de 35912027Sjungma@eit.uni-kl.de elif len(cnbase) > 1: 36012027Sjungma@eit.uni-kl.de panic("""\ 36112027Sjungma@eit.uni-kl.deThe config hierarchy only supports single inheritence of SimObject 36212027Sjungma@eit.uni-kl.declasses. You're trying to derive from: 36312027Sjungma@eit.uni-kl.de%s""" % str(cnbase)) 36412027Sjungma@eit.uni-kl.de 36512027Sjungma@eit.uni-kl.de # process param types from _init_dict, as these may be needed 36612027Sjungma@eit.uni-kl.de # by param descriptions also in _init_dict 36712027Sjungma@eit.uni-kl.de for key,val in cls._init_dict.items(): 36812027Sjungma@eit.uni-kl.de if isinstance(val, type) and issubclass(val, ParamType): 36912027Sjungma@eit.uni-kl.de cls._param_types[key] = val 37012027Sjungma@eit.uni-kl.de if not issubclass(val, ConfigNode): 37112027Sjungma@eit.uni-kl.de del cls._init_dict[key] 37212027Sjungma@eit.uni-kl.de 37312027Sjungma@eit.uni-kl.de # now process remaining _init_dict items 37412027Sjungma@eit.uni-kl.de for key,val in cls._init_dict.items(): 37512027Sjungma@eit.uni-kl.de # param descriptions 37612027Sjungma@eit.uni-kl.de if isinstance(val, ParamBase): 37712027Sjungma@eit.uni-kl.de cls._new_param(key, val) 37812027Sjungma@eit.uni-kl.de 37912027Sjungma@eit.uni-kl.de # init-time-only keywords 38012027Sjungma@eit.uni-kl.de elif cls.init_keywords.has_key(key): 38112027Sjungma@eit.uni-kl.de cls._set_keyword(key, val, cls.init_keywords[key]) 38212027Sjungma@eit.uni-kl.de 38312027Sjungma@eit.uni-kl.de # See description of decorators in the importer.py file. 38412027Sjungma@eit.uni-kl.de # We just strip off the expr_decorator now since we don't 38512027Sjungma@eit.uni-kl.de # need from this point on. 38612027Sjungma@eit.uni-kl.de elif key.startswith(expr_decorator): 38712027Sjungma@eit.uni-kl.de key = key[len(expr_decorator):] 38812027Sjungma@eit.uni-kl.de # because it had dots into a list so that we can find the 38912027Sjungma@eit.uni-kl.de # proper variable to modify. 39012027Sjungma@eit.uni-kl.de key = key.split(dot_decorator) 39112027Sjungma@eit.uni-kl.de c = cls 39212027Sjungma@eit.uni-kl.de for item in key[:-1]: 39312027Sjungma@eit.uni-kl.de c = getattr(c, item) 39412027Sjungma@eit.uni-kl.de setattr(c, key[-1], val) 39512027Sjungma@eit.uni-kl.de 39612027Sjungma@eit.uni-kl.de # default: use normal path (ends up in __setattr__) 39712027Sjungma@eit.uni-kl.de else: 39812027Sjungma@eit.uni-kl.de setattr(cls, key, val) 39912027Sjungma@eit.uni-kl.de 40012027Sjungma@eit.uni-kl.de def _set_keyword(cls, keyword, val, kwtype): 40112027Sjungma@eit.uni-kl.de if not isinstance(val, kwtype): 40212027Sjungma@eit.uni-kl.de raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 40312027Sjungma@eit.uni-kl.de (keyword, type(val), kwtype) 40412027Sjungma@eit.uni-kl.de if isinstance(val, types.FunctionType): 40512027Sjungma@eit.uni-kl.de val = classmethod(val) 40612027Sjungma@eit.uni-kl.de type.__setattr__(cls, keyword, val) 40712027Sjungma@eit.uni-kl.de 40812027Sjungma@eit.uni-kl.de def _new_param(cls, name, value): 40912027Sjungma@eit.uni-kl.de cls._params[name] = value 41012027Sjungma@eit.uni-kl.de if hasattr(value, 'default'): 41112027Sjungma@eit.uni-kl.de cls._values[name] = value.default 41212027Sjungma@eit.uni-kl.de # try to resolve local param types in local param_types scope 41312027Sjungma@eit.uni-kl.de value.maybe_resolve_type(cls._param_types) 41412027Sjungma@eit.uni-kl.de 41512027Sjungma@eit.uni-kl.de # Set attribute (called on foo.attr = value when foo is an 41612027Sjungma@eit.uni-kl.de # instance of class cls). 41712027Sjungma@eit.uni-kl.de def __setattr__(cls, attr, value): 41812027Sjungma@eit.uni-kl.de # normal processing for private attributes 41912027Sjungma@eit.uni-kl.de if attr.startswith('_'): 42012027Sjungma@eit.uni-kl.de type.__setattr__(cls, attr, value) 42112027Sjungma@eit.uni-kl.de return 42212027Sjungma@eit.uni-kl.de 42312027Sjungma@eit.uni-kl.de if cls.keywords.has_key(attr): 42412027Sjungma@eit.uni-kl.de cls._set_keyword(attr, value, cls.keywords[attr]) 42512027Sjungma@eit.uni-kl.de return 42612027Sjungma@eit.uni-kl.de 42712027Sjungma@eit.uni-kl.de # must be SimObject param 42812027Sjungma@eit.uni-kl.de param = cls._params.get(attr, None) 42912027Sjungma@eit.uni-kl.de if param: 43012027Sjungma@eit.uni-kl.de # It's ok: set attribute by delegating to 'object' class. 43112027Sjungma@eit.uni-kl.de # Note the use of param.make_value() to verify/canonicalize 43212027Sjungma@eit.uni-kl.de # the assigned value 43312027Sjungma@eit.uni-kl.de try: 43412027Sjungma@eit.uni-kl.de param.valid(value) 43512027Sjungma@eit.uni-kl.de except Exception, e: 43612027Sjungma@eit.uni-kl.de msg = "%s\nError setting param %s.%s to %s\n" % \ 43712027Sjungma@eit.uni-kl.de (e, cls.__name__, attr, value) 43812027Sjungma@eit.uni-kl.de e.args = (msg, ) 43912027Sjungma@eit.uni-kl.de raise 44012027Sjungma@eit.uni-kl.de cls._values[attr] = value 44112027Sjungma@eit.uni-kl.de elif isConfigNode(value) or isSimObjSequence(value): 44212027Sjungma@eit.uni-kl.de cls._values[attr] = value 44312027Sjungma@eit.uni-kl.de else: 44412027Sjungma@eit.uni-kl.de raise AttributeError, \ 44512027Sjungma@eit.uni-kl.de "Class %s has no parameter %s" % (cls.__name__, attr) 44612027Sjungma@eit.uni-kl.de 44712027Sjungma@eit.uni-kl.de def __getattr__(cls, attr): 44812027Sjungma@eit.uni-kl.de if cls._params.has_key(attr) or cls._values.has_key(attr): 44912027Sjungma@eit.uni-kl.de return Value(cls, attr) 45012027Sjungma@eit.uni-kl.de 45112027Sjungma@eit.uni-kl.de if attr == '_cpp_param_decl' and hasattr(cls, 'type'): 45212027Sjungma@eit.uni-kl.de return cls.type + '*' 45312027Sjungma@eit.uni-kl.de 45412027Sjungma@eit.uni-kl.de raise AttributeError, \ 45512027Sjungma@eit.uni-kl.de "object '%s' has no attribute '%s'" % (cls.__name__, attr) 45612027Sjungma@eit.uni-kl.de 45712027Sjungma@eit.uni-kl.de def add_child(cls, instance, name, child): 45812027Sjungma@eit.uni-kl.de if isNullPointer(child) or instance.top_child_names.has_key(name): 45912027Sjungma@eit.uni-kl.de return 46012027Sjungma@eit.uni-kl.de 46112027Sjungma@eit.uni-kl.de if isinstance(child, (list, tuple)): 46212027Sjungma@eit.uni-kl.de kid = [] 46312027Sjungma@eit.uni-kl.de for i,c in enumerate(child): 46412027Sjungma@eit.uni-kl.de n = '%s%d' % (name, i) 46512027Sjungma@eit.uni-kl.de k = c.instantiate(n, instance) 46612027Sjungma@eit.uni-kl.de 46712027Sjungma@eit.uni-kl.de instance.children.append(k) 46812027Sjungma@eit.uni-kl.de instance.child_names[n] = k 46912027Sjungma@eit.uni-kl.de instance.child_objects[c] = k 47012027Sjungma@eit.uni-kl.de kid.append(k) 47112027Sjungma@eit.uni-kl.de else: 47212027Sjungma@eit.uni-kl.de kid = child.instantiate(name, instance) 47312027Sjungma@eit.uni-kl.de instance.children.append(kid) 47412027Sjungma@eit.uni-kl.de instance.child_names[name] = kid 47512027Sjungma@eit.uni-kl.de instance.child_objects[child] = kid 47612027Sjungma@eit.uni-kl.de 47712027Sjungma@eit.uni-kl.de instance.top_child_names[name] = kid 47812027Sjungma@eit.uni-kl.de 47912027Sjungma@eit.uni-kl.de # Print instance info to .ini file. 48012027Sjungma@eit.uni-kl.de def instantiate(cls, name, parent = None): 48112027Sjungma@eit.uni-kl.de instance = Node(name, cls, parent, isParamContext(cls)) 48212027Sjungma@eit.uni-kl.de 48312027Sjungma@eit.uni-kl.de if hasattr(cls, 'check'): 48412027Sjungma@eit.uni-kl.de cls.check() 48512027Sjungma@eit.uni-kl.de 48612027Sjungma@eit.uni-kl.de for key,value in cls._values.iteritems(): 48712027Sjungma@eit.uni-kl.de if isConfigNode(value): 48812027Sjungma@eit.uni-kl.de cls.add_child(instance, key, value) 48912027Sjungma@eit.uni-kl.de if isinstance(value, (list, tuple)): 49012027Sjungma@eit.uni-kl.de vals = [ v for v in value if isConfigNode(v) ] 49112027Sjungma@eit.uni-kl.de if len(vals): 49212027Sjungma@eit.uni-kl.de cls.add_child(instance, key, vals) 49312027Sjungma@eit.uni-kl.de 49412027Sjungma@eit.uni-kl.de for pname,param in cls._params.iteritems(): 49512027Sjungma@eit.uni-kl.de value = cls._values.get(pname, None) 49612027Sjungma@eit.uni-kl.de if value is None: 49712027Sjungma@eit.uni-kl.de panic('Error getting %s from %s' % (pname, name)) 49812027Sjungma@eit.uni-kl.de 49912027Sjungma@eit.uni-kl.de try: 50012027Sjungma@eit.uni-kl.de if isConfigNode(value): 50112027Sjungma@eit.uni-kl.de value = instance.child_objects[value] 50212027Sjungma@eit.uni-kl.de elif isinstance(value, (list, tuple)): 50312027Sjungma@eit.uni-kl.de v = [] 50412027Sjungma@eit.uni-kl.de for val in value: 50512027Sjungma@eit.uni-kl.de if isConfigNode(val): 50612027Sjungma@eit.uni-kl.de v.append(instance.child_objects[val]) 50712027Sjungma@eit.uni-kl.de else: 50812027Sjungma@eit.uni-kl.de v.append(val) 50912027Sjungma@eit.uni-kl.de value = v 51012027Sjungma@eit.uni-kl.de 51112027Sjungma@eit.uni-kl.de p = NodeParam(pname, param, value) 51212027Sjungma@eit.uni-kl.de instance.params.append(p) 51312027Sjungma@eit.uni-kl.de instance.param_names[pname] = p 51412027Sjungma@eit.uni-kl.de except Exception, e: 51512027Sjungma@eit.uni-kl.de msg = 'Exception while evaluating %s.%s\n%s' % \ 51612027Sjungma@eit.uni-kl.de (instance.path, pname, e) 51712027Sjungma@eit.uni-kl.de e.args = (msg, ) 51812027Sjungma@eit.uni-kl.de raise 51912027Sjungma@eit.uni-kl.de 52012027Sjungma@eit.uni-kl.de return instance 52112027Sjungma@eit.uni-kl.de 52212027Sjungma@eit.uni-kl.de def _convert(cls, value): 52312027Sjungma@eit.uni-kl.de realvalue = value 52412027Sjungma@eit.uni-kl.de if isinstance(value, Node): 52512027Sjungma@eit.uni-kl.de realvalue = value.realtype 52612027Sjungma@eit.uni-kl.de 52712027Sjungma@eit.uni-kl.de if isinstance(realvalue, Proxy): 52812027Sjungma@eit.uni-kl.de return value 52912027Sjungma@eit.uni-kl.de 53012027Sjungma@eit.uni-kl.de if realvalue == None or isNullPointer(realvalue): 53112027Sjungma@eit.uni-kl.de return value 53212027Sjungma@eit.uni-kl.de 53312027Sjungma@eit.uni-kl.de if isSubClass(realvalue, cls): 53412027Sjungma@eit.uni-kl.de return value 53512027Sjungma@eit.uni-kl.de 53612027Sjungma@eit.uni-kl.de raise TypeError, 'object %s type %s wrong type, should be %s' % \ 53712027Sjungma@eit.uni-kl.de (repr(realvalue), realvalue, cls) 53812027Sjungma@eit.uni-kl.de 53912027Sjungma@eit.uni-kl.de def _string(cls, value): 54012027Sjungma@eit.uni-kl.de if isNullPointer(value): 54112027Sjungma@eit.uni-kl.de return 'Null' 54212027Sjungma@eit.uni-kl.de return Node._string(value) 54312027Sjungma@eit.uni-kl.de 54412027Sjungma@eit.uni-kl.de# The ConfigNode class is the root of the special hierarchy. Most of 54512027Sjungma@eit.uni-kl.de# the code in this class deals with the configuration hierarchy itself 54612027Sjungma@eit.uni-kl.de# (parent/child node relationships). 54712027Sjungma@eit.uni-kl.declass ConfigNode(object): 54812027Sjungma@eit.uni-kl.de # Specify metaclass. Any class inheriting from ConfigNode will 54912027Sjungma@eit.uni-kl.de # get this metaclass. 55012027Sjungma@eit.uni-kl.de __metaclass__ = MetaConfigNode 55112027Sjungma@eit.uni-kl.de 55212027Sjungma@eit.uni-kl.de def __new__(cls, **kwargs): 55312027Sjungma@eit.uni-kl.de name = cls.__name__ + ("_%d" % cls._anon_subclass_counter) 55412027Sjungma@eit.uni-kl.de cls._anon_subclass_counter += 1 55512027Sjungma@eit.uni-kl.de return cls.__metaclass__(name, (cls, ), kwargs) 55612027Sjungma@eit.uni-kl.de 55712027Sjungma@eit.uni-kl.declass ParamContext(ConfigNode,ParamType): 55812027Sjungma@eit.uni-kl.de pass 55912027Sjungma@eit.uni-kl.de 56012027Sjungma@eit.uni-kl.declass MetaSimObject(MetaConfigNode): 56112027Sjungma@eit.uni-kl.de # init_keywords and keywords are inherited from MetaConfigNode, 56212027Sjungma@eit.uni-kl.de # with overrides/additions 56312027Sjungma@eit.uni-kl.de init_keywords = MetaConfigNode.init_keywords 56412027Sjungma@eit.uni-kl.de init_keywords.update({ 'abstract' : types.BooleanType, 56512027Sjungma@eit.uni-kl.de 'type' : types.StringType }) 56612027Sjungma@eit.uni-kl.de 56712027Sjungma@eit.uni-kl.de keywords = MetaConfigNode.keywords 56812027Sjungma@eit.uni-kl.de # no additional keywords 56912027Sjungma@eit.uni-kl.de 57012027Sjungma@eit.uni-kl.de cpp_classes = [] 57112027Sjungma@eit.uni-kl.de 57212027Sjungma@eit.uni-kl.de # initialization 57312027Sjungma@eit.uni-kl.de def __init__(cls, name, bases, dict): 57412027Sjungma@eit.uni-kl.de super(MetaSimObject, cls).__init__(name, bases, dict) 57512027Sjungma@eit.uni-kl.de 57612027Sjungma@eit.uni-kl.de if hasattr(cls, 'type'): 57712027Sjungma@eit.uni-kl.de if name == 'SimObject': 57812027Sjungma@eit.uni-kl.de cls._cpp_base = None 57912027Sjungma@eit.uni-kl.de elif hasattr(cls._bases[1], 'type'): 58012027Sjungma@eit.uni-kl.de cls._cpp_base = cls._bases[1].type 58112027Sjungma@eit.uni-kl.de else: 58212027Sjungma@eit.uni-kl.de panic("SimObject %s derives from a non-C++ SimObject %s "\ 58312027Sjungma@eit.uni-kl.de "(no 'type')" % (cls, cls_bases[1].__name__)) 58412027Sjungma@eit.uni-kl.de 58512027Sjungma@eit.uni-kl.de # This class corresponds to a C++ class: put it on the global 58612027Sjungma@eit.uni-kl.de # list of C++ objects to generate param structs, etc. 58712027Sjungma@eit.uni-kl.de MetaSimObject.cpp_classes.append(cls) 58812027Sjungma@eit.uni-kl.de 58912027Sjungma@eit.uni-kl.de def _cpp_decl(cls): 59012027Sjungma@eit.uni-kl.de name = cls.__name__ 59112027Sjungma@eit.uni-kl.de code = "" 59212027Sjungma@eit.uni-kl.de code += "\n".join([e.cpp_declare() for e in cls._param_types.values()]) 59312027Sjungma@eit.uni-kl.de code += "\n" 59412027Sjungma@eit.uni-kl.de param_names = cls._params.keys() 59512027Sjungma@eit.uni-kl.de param_names.sort() 59612027Sjungma@eit.uni-kl.de code += "struct Params" 59712027Sjungma@eit.uni-kl.de if cls._cpp_base: 59812027Sjungma@eit.uni-kl.de code += " : public %s::Params" % cls._cpp_base 59912027Sjungma@eit.uni-kl.de code += " {\n " 60012027Sjungma@eit.uni-kl.de code += "\n ".join([cls._params[pname].cpp_decl(pname) \ 60112027Sjungma@eit.uni-kl.de for pname in param_names]) 60212027Sjungma@eit.uni-kl.de code += "\n};\n" 60312027Sjungma@eit.uni-kl.de return code 60412027Sjungma@eit.uni-kl.de 60512027Sjungma@eit.uni-kl.declass NodeParam(object): 60612027Sjungma@eit.uni-kl.de def __init__(self, name, param, value): 60712027Sjungma@eit.uni-kl.de self.name = name 60812027Sjungma@eit.uni-kl.de self.param = param 60912027Sjungma@eit.uni-kl.de self.ptype = param.ptype 61012027Sjungma@eit.uni-kl.de self.convert = param.convert 61112027Sjungma@eit.uni-kl.de self.string = param.string 61212027Sjungma@eit.uni-kl.de self.value = value 61312027Sjungma@eit.uni-kl.de 61412027Sjungma@eit.uni-kl.declass Node(object): 61512027Sjungma@eit.uni-kl.de all = {} 61612027Sjungma@eit.uni-kl.de def __init__(self, name, realtype, parent, paramcontext): 61712027Sjungma@eit.uni-kl.de self.name = name 61812027Sjungma@eit.uni-kl.de self.realtype = realtype 61912027Sjungma@eit.uni-kl.de if isSimObject(realtype): 62012027Sjungma@eit.uni-kl.de self.type = realtype.type 62112027Sjungma@eit.uni-kl.de else: 62212027Sjungma@eit.uni-kl.de self.type = None 62312027Sjungma@eit.uni-kl.de self.parent = parent 62412027Sjungma@eit.uni-kl.de self.children = [] 62512027Sjungma@eit.uni-kl.de self.child_names = {} 62612027Sjungma@eit.uni-kl.de self.child_objects = {} 62712027Sjungma@eit.uni-kl.de self.top_child_names = {} 62812027Sjungma@eit.uni-kl.de self.params = [] 62912027Sjungma@eit.uni-kl.de self.param_names = {} 63012027Sjungma@eit.uni-kl.de self.paramcontext = paramcontext 63112027Sjungma@eit.uni-kl.de 63212027Sjungma@eit.uni-kl.de path = [ self.name ] 63312027Sjungma@eit.uni-kl.de node = self.parent 63412027Sjungma@eit.uni-kl.de while node is not None: 63512027Sjungma@eit.uni-kl.de if node.name != 'root': 63612027Sjungma@eit.uni-kl.de path.insert(0, node.name) 63712027Sjungma@eit.uni-kl.de else: 63812027Sjungma@eit.uni-kl.de assert(node.parent is None) 63912027Sjungma@eit.uni-kl.de node = node.parent 64012027Sjungma@eit.uni-kl.de self.path = '.'.join(path) 64112027Sjungma@eit.uni-kl.de 64212027Sjungma@eit.uni-kl.de def find(self, realtype, path): 64312027Sjungma@eit.uni-kl.de if not path: 64412027Sjungma@eit.uni-kl.de if issubclass(self.realtype, realtype): 64512027Sjungma@eit.uni-kl.de return self, True 64612027Sjungma@eit.uni-kl.de 64712027Sjungma@eit.uni-kl.de obj = None 64812027Sjungma@eit.uni-kl.de for child in self.children: 64912027Sjungma@eit.uni-kl.de if issubclass(child.realtype, realtype): 65012027Sjungma@eit.uni-kl.de if obj is not None: 65112027Sjungma@eit.uni-kl.de raise AttributeError, \ 65212027Sjungma@eit.uni-kl.de 'parent.any matched more than one: %s %s' % \ 65312027Sjungma@eit.uni-kl.de (obj.path, child.path) 65412027Sjungma@eit.uni-kl.de obj = child 65512027Sjungma@eit.uni-kl.de return obj, obj is not None 65612027Sjungma@eit.uni-kl.de 65712027Sjungma@eit.uni-kl.de try: 65812027Sjungma@eit.uni-kl.de obj = self 65912027Sjungma@eit.uni-kl.de for (node,index) in path[:-1]: 66012027Sjungma@eit.uni-kl.de if obj.child_names.has_key(node): 66112027Sjungma@eit.uni-kl.de obj = obj.child_names[node] 66212027Sjungma@eit.uni-kl.de else: 66312027Sjungma@eit.uni-kl.de obj = obj.top_child_names[node] 66412027Sjungma@eit.uni-kl.de obj = Proxy.getindex(obj, index) 66512027Sjungma@eit.uni-kl.de 66612027Sjungma@eit.uni-kl.de (last,index) = path[-1] 66712027Sjungma@eit.uni-kl.de if obj.child_names.has_key(last): 66812027Sjungma@eit.uni-kl.de value = obj.child_names[last] 66912027Sjungma@eit.uni-kl.de return Proxy.getindex(value, index), True 67012027Sjungma@eit.uni-kl.de elif obj.top_child_names.has_key(last): 67112027Sjungma@eit.uni-kl.de value = obj.top_child_names[last] 67212027Sjungma@eit.uni-kl.de return Proxy.getindex(value, index), True 67312027Sjungma@eit.uni-kl.de elif obj.param_names.has_key(last): 67412027Sjungma@eit.uni-kl.de value = obj.param_names[last] 67512027Sjungma@eit.uni-kl.de realtype._convert(value.value) 67612027Sjungma@eit.uni-kl.de return Proxy.getindex(value.value, index), True 67712027Sjungma@eit.uni-kl.de except KeyError: 67812027Sjungma@eit.uni-kl.de pass 67912027Sjungma@eit.uni-kl.de 68012027Sjungma@eit.uni-kl.de return None, False 68112027Sjungma@eit.uni-kl.de 68212027Sjungma@eit.uni-kl.de def unproxy(self, param, ptype): 68312027Sjungma@eit.uni-kl.de if not isinstance(param, Proxy): 68412027Sjungma@eit.uni-kl.de return param 68512027Sjungma@eit.uni-kl.de return param.unproxy(self, ptype) 68612027Sjungma@eit.uni-kl.de 68712027Sjungma@eit.uni-kl.de def fixup(self): 68812027Sjungma@eit.uni-kl.de self.all[self.path] = self 68912027Sjungma@eit.uni-kl.de 69012027Sjungma@eit.uni-kl.de for param in self.params: 69112027Sjungma@eit.uni-kl.de ptype = param.ptype 69212027Sjungma@eit.uni-kl.de pval = param.value 69312027Sjungma@eit.uni-kl.de 69412027Sjungma@eit.uni-kl.de try: 69512027Sjungma@eit.uni-kl.de if isinstance(pval, (list, tuple)): 69612027Sjungma@eit.uni-kl.de param.value = [ self.unproxy(pv, ptype) for pv in pval ] 69712027Sjungma@eit.uni-kl.de else: 69812027Sjungma@eit.uni-kl.de param.value = self.unproxy(pval, ptype) 69912027Sjungma@eit.uni-kl.de except Exception, e: 70012027Sjungma@eit.uni-kl.de msg = 'Error while fixing up %s:%s\n%s' % \ 70112027Sjungma@eit.uni-kl.de (self.path, param.name, e) 70212027Sjungma@eit.uni-kl.de e.args = (msg, ) 70312027Sjungma@eit.uni-kl.de raise 70412027Sjungma@eit.uni-kl.de 70512027Sjungma@eit.uni-kl.de for child in self.children: 70612027Sjungma@eit.uni-kl.de assert(child != self) 70712027Sjungma@eit.uni-kl.de child.fixup() 70812027Sjungma@eit.uni-kl.de 70912027Sjungma@eit.uni-kl.de # print type and parameter values to .ini file 71012027Sjungma@eit.uni-kl.de def display(self): 71112027Sjungma@eit.uni-kl.de print '[' + self.path + ']' # .ini section header 71212027Sjungma@eit.uni-kl.de 71312027Sjungma@eit.uni-kl.de if isSimObject(self.realtype): 71412027Sjungma@eit.uni-kl.de print 'type = %s' % self.type 71512027Sjungma@eit.uni-kl.de 71612027Sjungma@eit.uni-kl.de if self.children: 71712027Sjungma@eit.uni-kl.de # instantiate children in same order they were added for 71812027Sjungma@eit.uni-kl.de # backward compatibility (else we can end up with cpu1 71912027Sjungma@eit.uni-kl.de # before cpu0). Changing ordering can also influence timing 72012027Sjungma@eit.uni-kl.de # in the current memory system, as caches get added to a bus 72112027Sjungma@eit.uni-kl.de # in different orders which affects their priority in the 72212027Sjungma@eit.uni-kl.de # case of simulataneous requests. 72312027Sjungma@eit.uni-kl.de self.children.sort(lambda x,y: cmp(x.name, y.name)) 72412027Sjungma@eit.uni-kl.de children = [ c.name for c in self.children if not c.paramcontext] 72512027Sjungma@eit.uni-kl.de print 'children =', ' '.join(children) 72612027Sjungma@eit.uni-kl.de 72712027Sjungma@eit.uni-kl.de self.params.sort(lambda x,y: cmp(x.name, y.name)) 72812027Sjungma@eit.uni-kl.de for param in self.params: 72912027Sjungma@eit.uni-kl.de try: 73012027Sjungma@eit.uni-kl.de if param.value is None: 73112027Sjungma@eit.uni-kl.de raise AttributeError, 'Parameter with no value' 73212027Sjungma@eit.uni-kl.de 73312027Sjungma@eit.uni-kl.de value = param.convert(param.value) 73412027Sjungma@eit.uni-kl.de string = param.string(value) 73512027Sjungma@eit.uni-kl.de except Exception, e: 73612027Sjungma@eit.uni-kl.de msg = 'exception in %s:%s\n%s' % (self.path, param.name, e) 73712027Sjungma@eit.uni-kl.de e.args = (msg, ) 73812027Sjungma@eit.uni-kl.de raise 73912027Sjungma@eit.uni-kl.de 74012027Sjungma@eit.uni-kl.de print '%s = %s' % (param.name, string) 74112027Sjungma@eit.uni-kl.de 74212027Sjungma@eit.uni-kl.de print 74312027Sjungma@eit.uni-kl.de 74412027Sjungma@eit.uni-kl.de # recursively dump out children 74512027Sjungma@eit.uni-kl.de for c in self.children: 74612027Sjungma@eit.uni-kl.de c.display() 74712027Sjungma@eit.uni-kl.de 74812027Sjungma@eit.uni-kl.de # print type and parameter values to .ini file 74912027Sjungma@eit.uni-kl.de def outputDot(self, dot): 75012027Sjungma@eit.uni-kl.de label = "{%s|" % self.path 75112027Sjungma@eit.uni-kl.de if isSimObject(self.realtype): 75212027Sjungma@eit.uni-kl.de label += '%s|' % self.type 75312027Sjungma@eit.uni-kl.de 75412027Sjungma@eit.uni-kl.de if self.children: 75512027Sjungma@eit.uni-kl.de # instantiate children in same order they were added for 75612027Sjungma@eit.uni-kl.de # backward compatibility (else we can end up with cpu1 75712027Sjungma@eit.uni-kl.de # before cpu0). 75812027Sjungma@eit.uni-kl.de for c in self.children: 75912027Sjungma@eit.uni-kl.de dot.add_edge(pydot.Edge(self.path,c.path, style="bold")) 76012027Sjungma@eit.uni-kl.de 76112027Sjungma@eit.uni-kl.de simobjs = [] 76212027Sjungma@eit.uni-kl.de for param in self.params: 76312027Sjungma@eit.uni-kl.de try: 76412027Sjungma@eit.uni-kl.de if param.value is None: 76512027Sjungma@eit.uni-kl.de raise AttributeError, 'Parameter with no value' 76612027Sjungma@eit.uni-kl.de 76712027Sjungma@eit.uni-kl.de value = param.convert(param.value) 76812027Sjungma@eit.uni-kl.de string = param.string(value) 76912027Sjungma@eit.uni-kl.de except Exception, e: 77012027Sjungma@eit.uni-kl.de msg = 'exception in %s:%s\n%s' % (self.name, param.name, e) 77112027Sjungma@eit.uni-kl.de e.args = (msg, ) 77212027Sjungma@eit.uni-kl.de raise 77312027Sjungma@eit.uni-kl.de 77412027Sjungma@eit.uni-kl.de if isConfigNode(param.ptype) and string != "Null": 77512027Sjungma@eit.uni-kl.de simobjs.append(string) 77612027Sjungma@eit.uni-kl.de else: 77712027Sjungma@eit.uni-kl.de label += '%s = %s\\n' % (param.name, string) 77812027Sjungma@eit.uni-kl.de 77912027Sjungma@eit.uni-kl.de for so in simobjs: 78012027Sjungma@eit.uni-kl.de label += "|<%s> %s" % (so, so) 78112027Sjungma@eit.uni-kl.de dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, 78212027Sjungma@eit.uni-kl.de tailport="w")) 78312027Sjungma@eit.uni-kl.de label += '}' 78412027Sjungma@eit.uni-kl.de dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) 78512027Sjungma@eit.uni-kl.de 78612027Sjungma@eit.uni-kl.de # recursively dump out children 78712027Sjungma@eit.uni-kl.de for c in self.children: 78812027Sjungma@eit.uni-kl.de c.outputDot(dot) 78912027Sjungma@eit.uni-kl.de 79012027Sjungma@eit.uni-kl.de def _string(cls, value): 79112027Sjungma@eit.uni-kl.de if not isinstance(value, Node): 79212027Sjungma@eit.uni-kl.de raise AttributeError, 'expecting %s got %s' % (Node, value) 79312027Sjungma@eit.uni-kl.de return value.path 79412027Sjungma@eit.uni-kl.de _string = classmethod(_string) 79512027Sjungma@eit.uni-kl.de 79612027Sjungma@eit.uni-kl.de##################################################################### 79712027Sjungma@eit.uni-kl.de# 79812027Sjungma@eit.uni-kl.de# Parameter description classes 79912027Sjungma@eit.uni-kl.de# 80012027Sjungma@eit.uni-kl.de# The _params dictionary in each class maps parameter names to 80112027Sjungma@eit.uni-kl.de# either a Param or a VectorParam object. These objects contain the 80212027Sjungma@eit.uni-kl.de# parameter description string, the parameter type, and the default 80312027Sjungma@eit.uni-kl.de# value (loaded from the PARAM section of the .odesc files). The 80412027Sjungma@eit.uni-kl.de# _convert() method on these objects is used to force whatever value 80512027Sjungma@eit.uni-kl.de# is assigned to the parameter to the appropriate type. 80612027Sjungma@eit.uni-kl.de# 80712027Sjungma@eit.uni-kl.de# Note that the default values are loaded into the class's attribute 80812027Sjungma@eit.uni-kl.de# space when the parameter dictionary is initialized (in 80912027Sjungma@eit.uni-kl.de# MetaConfigNode._setparams()); after that point they aren't used. 81012027Sjungma@eit.uni-kl.de# 81112027Sjungma@eit.uni-kl.de##################################################################### 81212027Sjungma@eit.uni-kl.de 81312027Sjungma@eit.uni-kl.dedef isNullPointer(value): 81412027Sjungma@eit.uni-kl.de return isinstance(value, NullSimObject) 81512027Sjungma@eit.uni-kl.de 81612027Sjungma@eit.uni-kl.declass Value(object): 81712027Sjungma@eit.uni-kl.de def __init__(self, obj, attr): 81812027Sjungma@eit.uni-kl.de super(Value, self).__setattr__('attr', attr) 81912027Sjungma@eit.uni-kl.de super(Value, self).__setattr__('obj', obj) 82012027Sjungma@eit.uni-kl.de 82112027Sjungma@eit.uni-kl.de def _getattr(self): 82212027Sjungma@eit.uni-kl.de return self.obj._values.get(self.attr) 82312027Sjungma@eit.uni-kl.de 82412027Sjungma@eit.uni-kl.de def __setattr__(self, attr, value): 82512027Sjungma@eit.uni-kl.de setattr(self._getattr(), attr, value) 82612027Sjungma@eit.uni-kl.de 82712027Sjungma@eit.uni-kl.de def __getattr__(self, attr): 82812027Sjungma@eit.uni-kl.de return getattr(self._getattr(), attr) 82912027Sjungma@eit.uni-kl.de 83012027Sjungma@eit.uni-kl.de def __getitem__(self, index): 83112027Sjungma@eit.uni-kl.de return self._getattr().__getitem__(index) 83212027Sjungma@eit.uni-kl.de 83312027Sjungma@eit.uni-kl.de def __call__(self, *args, **kwargs): 83412027Sjungma@eit.uni-kl.de return self._getattr().__call__(*args, **kwargs) 83512027Sjungma@eit.uni-kl.de 83612027Sjungma@eit.uni-kl.de def __nonzero__(self): 83712027Sjungma@eit.uni-kl.de return bool(self._getattr()) 83812027Sjungma@eit.uni-kl.de 83912027Sjungma@eit.uni-kl.de def __str__(self): 84012027Sjungma@eit.uni-kl.de return str(self._getattr()) 84112027Sjungma@eit.uni-kl.de 84212027Sjungma@eit.uni-kl.de def __len__(self): 84312027Sjungma@eit.uni-kl.de return len(self._getattr()) 84412027Sjungma@eit.uni-kl.de 84512027Sjungma@eit.uni-kl.de# Regular parameter. 84612027Sjungma@eit.uni-kl.declass ParamBase(object): 84712027Sjungma@eit.uni-kl.de def __init__(self, ptype, *args, **kwargs): 84812027Sjungma@eit.uni-kl.de if isinstance(ptype, types.StringType): 84912027Sjungma@eit.uni-kl.de self.ptype_string = ptype 85012027Sjungma@eit.uni-kl.de elif isinstance(ptype, type): 85112027Sjungma@eit.uni-kl.de self.ptype = ptype 85212027Sjungma@eit.uni-kl.de else: 85312027Sjungma@eit.uni-kl.de raise TypeError, "Param type is not a type (%s)" % ptype 85412027Sjungma@eit.uni-kl.de 85512027Sjungma@eit.uni-kl.de if args: 85612027Sjungma@eit.uni-kl.de if len(args) == 1: 85712027Sjungma@eit.uni-kl.de self.desc = args[0] 85812027Sjungma@eit.uni-kl.de elif len(args) == 2: 85912027Sjungma@eit.uni-kl.de self.default = args[0] 86012027Sjungma@eit.uni-kl.de self.desc = args[1] 86112027Sjungma@eit.uni-kl.de else: 86212027Sjungma@eit.uni-kl.de raise TypeError, 'too many arguments' 86312027Sjungma@eit.uni-kl.de 86412027Sjungma@eit.uni-kl.de if kwargs.has_key('desc'): 86512027Sjungma@eit.uni-kl.de assert(not hasattr(self, 'desc')) 86612027Sjungma@eit.uni-kl.de self.desc = kwargs['desc'] 86712027Sjungma@eit.uni-kl.de del kwargs['desc'] 86812027Sjungma@eit.uni-kl.de 86912027Sjungma@eit.uni-kl.de if kwargs.has_key('default'): 87012027Sjungma@eit.uni-kl.de assert(not hasattr(self, 'default')) 87112027Sjungma@eit.uni-kl.de self.default = kwargs['default'] 87212027Sjungma@eit.uni-kl.de del kwargs['default'] 87312027Sjungma@eit.uni-kl.de 87412027Sjungma@eit.uni-kl.de if kwargs: 87512027Sjungma@eit.uni-kl.de raise TypeError, 'extra unknown kwargs %s' % kwargs 87612027Sjungma@eit.uni-kl.de 87712027Sjungma@eit.uni-kl.de if not hasattr(self, 'desc'): 87812027Sjungma@eit.uni-kl.de raise TypeError, 'desc attribute missing' 87912027Sjungma@eit.uni-kl.de 88012027Sjungma@eit.uni-kl.de def maybe_resolve_type(self, context): 88112027Sjungma@eit.uni-kl.de # check if already resolved... don't use hasattr(), 88212027Sjungma@eit.uni-kl.de # as that calls __getattr__() 88312027Sjungma@eit.uni-kl.de if self.__dict__.has_key('ptype'): 88412027Sjungma@eit.uni-kl.de return 88512027Sjungma@eit.uni-kl.de try: 88612027Sjungma@eit.uni-kl.de self.ptype = context[self.ptype_string] 88712027Sjungma@eit.uni-kl.de except KeyError: 88812027Sjungma@eit.uni-kl.de # no harm in trying... we'll try again later using global scope 88912027Sjungma@eit.uni-kl.de pass 89012027Sjungma@eit.uni-kl.de 89112027Sjungma@eit.uni-kl.de def __getattr__(self, attr): 89212027Sjungma@eit.uni-kl.de if attr == 'ptype': 89312027Sjungma@eit.uni-kl.de try: 89412027Sjungma@eit.uni-kl.de self.ptype = param_types[self.ptype_string] 89512027Sjungma@eit.uni-kl.de return self.ptype 89612027Sjungma@eit.uni-kl.de except: 89712027Sjungma@eit.uni-kl.de panic("undefined Param type %s" % self.ptype_string) 89812027Sjungma@eit.uni-kl.de else: 89912027Sjungma@eit.uni-kl.de raise AttributeError, "'%s' object has no attribute '%s'" % \ 90012027Sjungma@eit.uni-kl.de (type(self).__name__, attr) 90112027Sjungma@eit.uni-kl.de 90212027Sjungma@eit.uni-kl.de def valid(self, value): 90312027Sjungma@eit.uni-kl.de if not isinstance(value, Proxy): 90412027Sjungma@eit.uni-kl.de self.ptype._convert(value) 90512027Sjungma@eit.uni-kl.de 90612027Sjungma@eit.uni-kl.de def convert(self, value): 90712027Sjungma@eit.uni-kl.de return self.ptype._convert(value) 90812027Sjungma@eit.uni-kl.de 90912027Sjungma@eit.uni-kl.de def string(self, value): 91012027Sjungma@eit.uni-kl.de return self.ptype._string(value) 91112027Sjungma@eit.uni-kl.de 91212027Sjungma@eit.uni-kl.de def set(self, name, instance, value): 91312027Sjungma@eit.uni-kl.de instance.__dict__[name] = value 91412027Sjungma@eit.uni-kl.de 91512027Sjungma@eit.uni-kl.de def cpp_decl(self, name): 91612027Sjungma@eit.uni-kl.de return '%s %s;' % (self.ptype._cpp_param_decl, name) 91712027Sjungma@eit.uni-kl.de 91812027Sjungma@eit.uni-kl.declass ParamFactory(object): 91912027Sjungma@eit.uni-kl.de def __init__(self, type): 92012027Sjungma@eit.uni-kl.de self.ptype = type 92112027Sjungma@eit.uni-kl.de 92212027Sjungma@eit.uni-kl.de # E.g., Param.Int(5, "number of widgets") 92312027Sjungma@eit.uni-kl.de def __call__(self, *args, **kwargs): 92412027Sjungma@eit.uni-kl.de return ParamBase(self.ptype, *args, **kwargs) 92512027Sjungma@eit.uni-kl.de 92612027Sjungma@eit.uni-kl.de # Strange magic to theoretically allow dotted names as Param classes, 92712027Sjungma@eit.uni-kl.de # e.g., Param.Foo.Bar(...) to have a param of type Foo.Bar 92812027Sjungma@eit.uni-kl.de def __getattr__(self, attr): 92912027Sjungma@eit.uni-kl.de if attr == '__bases__': 93012027Sjungma@eit.uni-kl.de raise AttributeError, '' 93112027Sjungma@eit.uni-kl.de cls = type(self) 93212027Sjungma@eit.uni-kl.de return cls(attr) 93312027Sjungma@eit.uni-kl.de 93412027Sjungma@eit.uni-kl.de def __setattr__(self, attr, value): 93512027Sjungma@eit.uni-kl.de if attr != 'ptype': 93612027Sjungma@eit.uni-kl.de raise AttributeError, \ 93712027Sjungma@eit.uni-kl.de 'Attribute %s not available in %s' % (attr, self.__class__) 93812027Sjungma@eit.uni-kl.de super(ParamFactory, self).__setattr__(attr, value) 93912027Sjungma@eit.uni-kl.de 94012027Sjungma@eit.uni-kl.deParam = ParamFactory(None) 94112027Sjungma@eit.uni-kl.de 94212027Sjungma@eit.uni-kl.de# Vector-valued parameter description. Just like Param, except that 94312027Sjungma@eit.uni-kl.de# the value is a vector (list) of the specified type instead of a 94412027Sjungma@eit.uni-kl.de# single value. 94512027Sjungma@eit.uni-kl.declass VectorParamBase(ParamBase): 94612027Sjungma@eit.uni-kl.de def __init__(self, type, *args, **kwargs): 94712027Sjungma@eit.uni-kl.de ParamBase.__init__(self, type, *args, **kwargs) 94812027Sjungma@eit.uni-kl.de 94912027Sjungma@eit.uni-kl.de def valid(self, value): 95012027Sjungma@eit.uni-kl.de if value == None: 95112027Sjungma@eit.uni-kl.de return True 95212027Sjungma@eit.uni-kl.de 95312027Sjungma@eit.uni-kl.de if isinstance(value, (list, tuple)): 95412027Sjungma@eit.uni-kl.de for val in value: 95512027Sjungma@eit.uni-kl.de if not isinstance(val, Proxy): 95612027Sjungma@eit.uni-kl.de self.ptype._convert(val) 95712027Sjungma@eit.uni-kl.de elif not isinstance(value, Proxy): 95812027Sjungma@eit.uni-kl.de self.ptype._convert(value) 95912027Sjungma@eit.uni-kl.de 96012027Sjungma@eit.uni-kl.de # Convert assigned value to appropriate type. If the RHS is not a 96112027Sjungma@eit.uni-kl.de # list or tuple, it generates a single-element list. 96212027Sjungma@eit.uni-kl.de def convert(self, value): 96312027Sjungma@eit.uni-kl.de if value == None: 96412027Sjungma@eit.uni-kl.de return [] 96512027Sjungma@eit.uni-kl.de 96612027Sjungma@eit.uni-kl.de if isinstance(value, (list, tuple)): 96712027Sjungma@eit.uni-kl.de # list: coerce each element into new list 96812027Sjungma@eit.uni-kl.de return [ self.ptype._convert(v) for v in value ] 96912027Sjungma@eit.uni-kl.de else: 97012027Sjungma@eit.uni-kl.de # singleton: coerce & wrap in a list 97112027Sjungma@eit.uni-kl.de return self.ptype._convert(value) 97212027Sjungma@eit.uni-kl.de 97312027Sjungma@eit.uni-kl.de def string(self, value): 97412027Sjungma@eit.uni-kl.de if isinstance(value, (list, tuple)): 97512027Sjungma@eit.uni-kl.de return ' '.join([ self.ptype._string(v) for v in value]) 97612027Sjungma@eit.uni-kl.de else: 97712027Sjungma@eit.uni-kl.de return self.ptype._string(value) 97812027Sjungma@eit.uni-kl.de 97912027Sjungma@eit.uni-kl.de def cpp_decl(self, name): 98012027Sjungma@eit.uni-kl.de return 'std::vector<%s> %s;' % (self.ptype._cpp_param_decl, name) 98112027Sjungma@eit.uni-kl.de 98212027Sjungma@eit.uni-kl.declass VectorParamFactory(ParamFactory): 98312027Sjungma@eit.uni-kl.de # E.g., VectorParam.Int(5, "number of widgets") 98412027Sjungma@eit.uni-kl.de def __call__(self, *args, **kwargs): 98512027Sjungma@eit.uni-kl.de return VectorParamBase(self.ptype, *args, **kwargs) 98612027Sjungma@eit.uni-kl.de 98712027Sjungma@eit.uni-kl.deVectorParam = VectorParamFactory(None) 98812027Sjungma@eit.uni-kl.de 98912027Sjungma@eit.uni-kl.de##################################################################### 99012027Sjungma@eit.uni-kl.de# 99112027Sjungma@eit.uni-kl.de# Parameter Types 99212027Sjungma@eit.uni-kl.de# 99312027Sjungma@eit.uni-kl.de# Though native Python types could be used to specify parameter types 99412027Sjungma@eit.uni-kl.de# (the 'ptype' field of the Param and VectorParam classes), it's more 99512027Sjungma@eit.uni-kl.de# flexible to define our own set of types. This gives us more control 99612027Sjungma@eit.uni-kl.de# over how Python expressions are converted to values (via the 99712027Sjungma@eit.uni-kl.de# __init__() constructor) and how these values are printed out (via 99812027Sjungma@eit.uni-kl.de# the __str__() conversion method). Eventually we'll need these types 99912027Sjungma@eit.uni-kl.de# to correspond to distinct C++ types as well. 100012027Sjungma@eit.uni-kl.de# 100112027Sjungma@eit.uni-kl.de##################################################################### 100212027Sjungma@eit.uni-kl.de 100312027Sjungma@eit.uni-kl.declass MetaRange(type): 100412027Sjungma@eit.uni-kl.de def __init__(cls, name, bases, dict): 100512027Sjungma@eit.uni-kl.de super(MetaRange, cls).__init__(name, bases, dict) 100612027Sjungma@eit.uni-kl.de if name == 'Range': 100712027Sjungma@eit.uni-kl.de return 100812027Sjungma@eit.uni-kl.de cls._cpp_param_decl = 'Range<%s>' % cls.type._cpp_param_decl 100912027Sjungma@eit.uni-kl.de 101012027Sjungma@eit.uni-kl.de def _convert(cls, value): 101112027Sjungma@eit.uni-kl.de if not isinstance(value, Range): 101212027Sjungma@eit.uni-kl.de raise TypeError, 'value %s is not a Pair' % value 101312027Sjungma@eit.uni-kl.de value = cls(value) 101412027Sjungma@eit.uni-kl.de value.first = cls.type._convert(value.first) 101512027Sjungma@eit.uni-kl.de value.second = cls.type._convert(value.second) 101612027Sjungma@eit.uni-kl.de return value 101712027Sjungma@eit.uni-kl.de 101812027Sjungma@eit.uni-kl.de def _string(cls, value): 101912027Sjungma@eit.uni-kl.de first = int(value.first) 102012027Sjungma@eit.uni-kl.de second = int(value.second) 102112027Sjungma@eit.uni-kl.de if value.extend: 102212027Sjungma@eit.uni-kl.de second += first 102312027Sjungma@eit.uni-kl.de if not value.inclusive: 102412027Sjungma@eit.uni-kl.de second -= 1 102512027Sjungma@eit.uni-kl.de return '%s:%s' % (cls.type._string(first), cls.type._string(second)) 102612027Sjungma@eit.uni-kl.de 102712027Sjungma@eit.uni-kl.declass Range(ParamType): 102812027Sjungma@eit.uni-kl.de __metaclass__ = MetaRange 102912027Sjungma@eit.uni-kl.de def __init__(self, *args, **kwargs): 103012027Sjungma@eit.uni-kl.de if len(args) == 0: 103112027Sjungma@eit.uni-kl.de self.first = kwargs.pop('start') 103212027Sjungma@eit.uni-kl.de 103312027Sjungma@eit.uni-kl.de if 'end' in kwargs: 103412027Sjungma@eit.uni-kl.de self.second = kwargs.pop('end') 103512027Sjungma@eit.uni-kl.de self.inclusive = True 103612027Sjungma@eit.uni-kl.de self.extend = False 103712027Sjungma@eit.uni-kl.de elif 'size' in kwargs: 103812027Sjungma@eit.uni-kl.de self.second = kwargs.pop('size') 103912027Sjungma@eit.uni-kl.de self.inclusive = False 104012027Sjungma@eit.uni-kl.de self.extend = True 104112027Sjungma@eit.uni-kl.de else: 104212027Sjungma@eit.uni-kl.de raise TypeError, "Either end or size must be specified" 104312027Sjungma@eit.uni-kl.de 104412027Sjungma@eit.uni-kl.de elif len(args) == 1: 104512027Sjungma@eit.uni-kl.de if kwargs: 104612027Sjungma@eit.uni-kl.de self.first = args[0] 104712027Sjungma@eit.uni-kl.de if 'end' in kwargs: 104812027Sjungma@eit.uni-kl.de self.second = kwargs.pop('end') 104912027Sjungma@eit.uni-kl.de self.inclusive = True 105012027Sjungma@eit.uni-kl.de self.extend = False 105112027Sjungma@eit.uni-kl.de elif 'size' in kwargs: 105212027Sjungma@eit.uni-kl.de self.second = kwargs.pop('size') 105312027Sjungma@eit.uni-kl.de self.inclusive = False 105412027Sjungma@eit.uni-kl.de self.extend = True 105512027Sjungma@eit.uni-kl.de else: 105612027Sjungma@eit.uni-kl.de raise TypeError, "Either end or size must be specified" 105712027Sjungma@eit.uni-kl.de elif isinstance(args[0], Range): 105812027Sjungma@eit.uni-kl.de self.first = args[0].first 105912027Sjungma@eit.uni-kl.de self.second = args[0].second 106012027Sjungma@eit.uni-kl.de self.inclusive = args[0].inclusive 106112027Sjungma@eit.uni-kl.de self.extend = args[0].extend 106212027Sjungma@eit.uni-kl.de else: 106312027Sjungma@eit.uni-kl.de self.first = 0 106412027Sjungma@eit.uni-kl.de self.second = args[0] 106512027Sjungma@eit.uni-kl.de self.inclusive = False 106612027Sjungma@eit.uni-kl.de self.extend = True 106712027Sjungma@eit.uni-kl.de 106812027Sjungma@eit.uni-kl.de elif len(args) == 2: 106912027Sjungma@eit.uni-kl.de self.first, self.second = args 107012027Sjungma@eit.uni-kl.de self.inclusive = True 107112027Sjungma@eit.uni-kl.de self.extend = False 107212027Sjungma@eit.uni-kl.de else: 107312027Sjungma@eit.uni-kl.de raise TypeError, "Too many arguments specified" 107412027Sjungma@eit.uni-kl.de 107512027Sjungma@eit.uni-kl.de if kwargs: 107612027Sjungma@eit.uni-kl.de raise TypeError, "too many keywords: %s" % kwargs.keys() 107712027Sjungma@eit.uni-kl.de 107812027Sjungma@eit.uni-kl.de# Metaclass for bounds-checked integer parameters. See CheckedInt. 107912027Sjungma@eit.uni-kl.declass CheckedIntType(type): 108012027Sjungma@eit.uni-kl.de def __init__(cls, name, bases, dict): 108112027Sjungma@eit.uni-kl.de super(CheckedIntType, cls).__init__(name, bases, dict) 108212027Sjungma@eit.uni-kl.de 108312027Sjungma@eit.uni-kl.de # CheckedInt is an abstract base class, so we actually don't 108412027Sjungma@eit.uni-kl.de # want to do any processing on it... the rest of this code is 108512027Sjungma@eit.uni-kl.de # just for classes that derive from CheckedInt. 108612027Sjungma@eit.uni-kl.de if name == 'CheckedInt': 108712027Sjungma@eit.uni-kl.de return 108812027Sjungma@eit.uni-kl.de 108912027Sjungma@eit.uni-kl.de if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 109012027Sjungma@eit.uni-kl.de if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 109112027Sjungma@eit.uni-kl.de panic("CheckedInt subclass %s must define either\n" \ 109212027Sjungma@eit.uni-kl.de " 'min' and 'max' or 'size' and 'unsigned'\n" \ 109312027Sjungma@eit.uni-kl.de % name); 109412027Sjungma@eit.uni-kl.de if cls.unsigned: 109512027Sjungma@eit.uni-kl.de cls.min = 0 109612027Sjungma@eit.uni-kl.de cls.max = 2 ** cls.size - 1 109712027Sjungma@eit.uni-kl.de else: 109812027Sjungma@eit.uni-kl.de cls.min = -(2 ** (cls.size - 1)) 109912027Sjungma@eit.uni-kl.de cls.max = (2 ** (cls.size - 1)) - 1 110012027Sjungma@eit.uni-kl.de 110112027Sjungma@eit.uni-kl.de cls._cpp_param_decl = cls.cppname 110212027Sjungma@eit.uni-kl.de 110312027Sjungma@eit.uni-kl.de def _convert(cls, value): 110412027Sjungma@eit.uni-kl.de if isinstance(value, bool): 110512027Sjungma@eit.uni-kl.de return int(value) 110612027Sjungma@eit.uni-kl.de 110712027Sjungma@eit.uni-kl.de if not isinstance(value, (int, long, float, str)): 110812027Sjungma@eit.uni-kl.de raise TypeError, 'Integer param of invalid type %s' % type(value) 110912027Sjungma@eit.uni-kl.de 111012027Sjungma@eit.uni-kl.de if isinstance(value, float): 111112027Sjungma@eit.uni-kl.de value = long(value) 111212027Sjungma@eit.uni-kl.de elif isinstance(value, str): 111312027Sjungma@eit.uni-kl.de value = toInteger(value) 111412027Sjungma@eit.uni-kl.de 111512027Sjungma@eit.uni-kl.de if not cls.min <= value <= cls.max: 111612027Sjungma@eit.uni-kl.de raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 111712027Sjungma@eit.uni-kl.de (cls.min, value, cls.max) 111812027Sjungma@eit.uni-kl.de 111912027Sjungma@eit.uni-kl.de return value 112012027Sjungma@eit.uni-kl.de 112112027Sjungma@eit.uni-kl.de def _string(cls, value): 112212027Sjungma@eit.uni-kl.de return str(value) 112312027Sjungma@eit.uni-kl.de 112412027Sjungma@eit.uni-kl.de# Abstract superclass for bounds-checked integer parameters. This 112512027Sjungma@eit.uni-kl.de# class is subclassed to generate parameter classes with specific 112612027Sjungma@eit.uni-kl.de# bounds. Initialization of the min and max bounds is done in the 112712027Sjungma@eit.uni-kl.de# metaclass CheckedIntType.__init__. 112812027Sjungma@eit.uni-kl.declass CheckedInt(long,ParamType): 112912027Sjungma@eit.uni-kl.de __metaclass__ = CheckedIntType 113012027Sjungma@eit.uni-kl.de 113112027Sjungma@eit.uni-kl.declass Int(CheckedInt): cppname = 'int'; size = 32; unsigned = False 113212027Sjungma@eit.uni-kl.declass Unsigned(CheckedInt): cppname = 'unsigned'; size = 32; unsigned = True 113312027Sjungma@eit.uni-kl.de 113412027Sjungma@eit.uni-kl.declass Int8(CheckedInt): cppname = 'int8_t'; size = 8; unsigned = False 113512027Sjungma@eit.uni-kl.declass UInt8(CheckedInt): cppname = 'uint8_t'; size = 8; unsigned = True 113612027Sjungma@eit.uni-kl.declass Int16(CheckedInt): cppname = 'int16_t'; size = 16; unsigned = False 113712027Sjungma@eit.uni-kl.declass UInt16(CheckedInt): cppname = 'uint16_t'; size = 16; unsigned = True 113812027Sjungma@eit.uni-kl.declass Int32(CheckedInt): cppname = 'int32_t'; size = 32; unsigned = False 113912027Sjungma@eit.uni-kl.declass UInt32(CheckedInt): cppname = 'uint32_t'; size = 32; unsigned = True 114012027Sjungma@eit.uni-kl.declass Int64(CheckedInt): cppname = 'int64_t'; size = 64; unsigned = False 114112027Sjungma@eit.uni-kl.declass UInt64(CheckedInt): cppname = 'uint64_t'; size = 64; unsigned = True 114212027Sjungma@eit.uni-kl.de 114312027Sjungma@eit.uni-kl.declass Counter(CheckedInt): cppname = 'Counter'; size = 64; unsigned = True 114412027Sjungma@eit.uni-kl.declass Tick(CheckedInt): cppname = 'Tick'; size = 64; unsigned = True 114512027Sjungma@eit.uni-kl.de 114612027Sjungma@eit.uni-kl.declass Percent(CheckedInt): cppname = 'int'; min = 0; max = 100 114712027Sjungma@eit.uni-kl.de 114812027Sjungma@eit.uni-kl.declass MemorySize(CheckedInt): 114912027Sjungma@eit.uni-kl.de cppname = 'uint64_t' 115012027Sjungma@eit.uni-kl.de size = 64 115112027Sjungma@eit.uni-kl.de unsigned = True 115212027Sjungma@eit.uni-kl.de def __new__(cls, value): 115312027Sjungma@eit.uni-kl.de return super(MemorySize, cls).__new__(cls, toMemorySize(value)) 115412027Sjungma@eit.uni-kl.de 115512027Sjungma@eit.uni-kl.de def _convert(cls, value): 115612027Sjungma@eit.uni-kl.de return cls(value) 115712027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 115812027Sjungma@eit.uni-kl.de 115912027Sjungma@eit.uni-kl.de def _string(cls, value): 116012027Sjungma@eit.uni-kl.de return '%d' % value 116112027Sjungma@eit.uni-kl.de _string = classmethod(_string) 116212027Sjungma@eit.uni-kl.de 116312027Sjungma@eit.uni-kl.declass Addr(MemorySize): 116412027Sjungma@eit.uni-kl.de pass 116512027Sjungma@eit.uni-kl.de 116612027Sjungma@eit.uni-kl.declass AddrRange(Range): 116712027Sjungma@eit.uni-kl.de type = Addr 116812027Sjungma@eit.uni-kl.de 116912027Sjungma@eit.uni-kl.de# Boolean parameter type. 117012027Sjungma@eit.uni-kl.declass Bool(ParamType): 117112027Sjungma@eit.uni-kl.de _cpp_param_decl = 'bool' 117212027Sjungma@eit.uni-kl.de #def __new__(cls, value): 117312027Sjungma@eit.uni-kl.de # return super(MemorySize, cls).__new__(cls, toBool(value)) 117412027Sjungma@eit.uni-kl.de 117512027Sjungma@eit.uni-kl.de def _convert(cls, value): 117612027Sjungma@eit.uni-kl.de return toBool(value) 117712027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 117812027Sjungma@eit.uni-kl.de 117912027Sjungma@eit.uni-kl.de def _string(cls, value): 118012027Sjungma@eit.uni-kl.de if value: 118112027Sjungma@eit.uni-kl.de return "true" 118212027Sjungma@eit.uni-kl.de else: 118312027Sjungma@eit.uni-kl.de return "false" 118412027Sjungma@eit.uni-kl.de _string = classmethod(_string) 118512027Sjungma@eit.uni-kl.de 118612027Sjungma@eit.uni-kl.de# String-valued parameter. 118712027Sjungma@eit.uni-kl.declass String(ParamType): 118812027Sjungma@eit.uni-kl.de _cpp_param_decl = 'string' 118912027Sjungma@eit.uni-kl.de 119012027Sjungma@eit.uni-kl.de # Constructor. Value must be Python string. 119112027Sjungma@eit.uni-kl.de def _convert(cls,value): 119212027Sjungma@eit.uni-kl.de if value is None: 119312027Sjungma@eit.uni-kl.de return '' 119412027Sjungma@eit.uni-kl.de if isinstance(value, str): 119512027Sjungma@eit.uni-kl.de return value 119612027Sjungma@eit.uni-kl.de 119712027Sjungma@eit.uni-kl.de raise TypeError, \ 119812027Sjungma@eit.uni-kl.de "String param got value %s %s" % (repr(value), type(value)) 119912027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 120012027Sjungma@eit.uni-kl.de 120112027Sjungma@eit.uni-kl.de # Generate printable string version. Not too tricky. 120212027Sjungma@eit.uni-kl.de def _string(cls, value): 120312027Sjungma@eit.uni-kl.de return value 120412027Sjungma@eit.uni-kl.de _string = classmethod(_string) 120512027Sjungma@eit.uni-kl.de 120612027Sjungma@eit.uni-kl.dedef IncEthernetAddr(addr, val = 1): 120712027Sjungma@eit.uni-kl.de bytes = map(lambda x: int(x, 16), addr.split(':')) 120812027Sjungma@eit.uni-kl.de bytes[5] += val 120912027Sjungma@eit.uni-kl.de for i in (5, 4, 3, 2, 1): 121012027Sjungma@eit.uni-kl.de val,rem = divmod(bytes[i], 256) 121112027Sjungma@eit.uni-kl.de bytes[i] = rem 121212027Sjungma@eit.uni-kl.de if val == 0: 121312027Sjungma@eit.uni-kl.de break 121412027Sjungma@eit.uni-kl.de bytes[i - 1] += val 121512027Sjungma@eit.uni-kl.de assert(bytes[0] <= 255) 121612027Sjungma@eit.uni-kl.de return ':'.join(map(lambda x: '%02x' % x, bytes)) 121712027Sjungma@eit.uni-kl.de 121812027Sjungma@eit.uni-kl.declass NextEthernetAddr(object): 121912027Sjungma@eit.uni-kl.de __metaclass__ = Singleton 122012027Sjungma@eit.uni-kl.de addr = "00:90:00:00:00:01" 122112027Sjungma@eit.uni-kl.de 122212027Sjungma@eit.uni-kl.de def __init__(self, inc = 1): 122312027Sjungma@eit.uni-kl.de self.value = self.addr 122412027Sjungma@eit.uni-kl.de self.addr = IncEthernetAddr(self.addr, inc) 122512027Sjungma@eit.uni-kl.de 122612027Sjungma@eit.uni-kl.declass EthernetAddr(ParamType): 122712027Sjungma@eit.uni-kl.de _cpp_param_decl = 'EthAddr' 122812027Sjungma@eit.uni-kl.de 122912027Sjungma@eit.uni-kl.de def _convert(cls, value): 123012027Sjungma@eit.uni-kl.de if value == NextEthernetAddr: 123112027Sjungma@eit.uni-kl.de return value 123212027Sjungma@eit.uni-kl.de 123312027Sjungma@eit.uni-kl.de if not isinstance(value, str): 123412027Sjungma@eit.uni-kl.de raise TypeError, "expected an ethernet address and didn't get one" 123512027Sjungma@eit.uni-kl.de 123612027Sjungma@eit.uni-kl.de bytes = value.split(':') 123712027Sjungma@eit.uni-kl.de if len(bytes) != 6: 123812027Sjungma@eit.uni-kl.de raise TypeError, 'invalid ethernet address %s' % value 123912027Sjungma@eit.uni-kl.de 124012027Sjungma@eit.uni-kl.de for byte in bytes: 124112027Sjungma@eit.uni-kl.de if not 0 <= int(byte) <= 256: 124212027Sjungma@eit.uni-kl.de raise TypeError, 'invalid ethernet address %s' % value 124312027Sjungma@eit.uni-kl.de 124412027Sjungma@eit.uni-kl.de return value 124512027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 124612027Sjungma@eit.uni-kl.de 124712027Sjungma@eit.uni-kl.de def _string(cls, value): 124812027Sjungma@eit.uni-kl.de if value == NextEthernetAddr: 124912027Sjungma@eit.uni-kl.de value = value().value 125012027Sjungma@eit.uni-kl.de return value 125112027Sjungma@eit.uni-kl.de _string = classmethod(_string) 125212027Sjungma@eit.uni-kl.de 125312027Sjungma@eit.uni-kl.de# Special class for NULL pointers. Note the special check in 125412027Sjungma@eit.uni-kl.de# make_param_value() above that lets these be assigned where a 125512027Sjungma@eit.uni-kl.de# SimObject is required. 125612027Sjungma@eit.uni-kl.de# only one copy of a particular node 125712027Sjungma@eit.uni-kl.declass NullSimObject(object): 125812027Sjungma@eit.uni-kl.de __metaclass__ = Singleton 125912027Sjungma@eit.uni-kl.de 126012027Sjungma@eit.uni-kl.de def __call__(cls): 126112027Sjungma@eit.uni-kl.de return cls 126212027Sjungma@eit.uni-kl.de 126312027Sjungma@eit.uni-kl.de def _instantiate(self, parent = None, path = ''): 126412027Sjungma@eit.uni-kl.de pass 126512027Sjungma@eit.uni-kl.de 126612027Sjungma@eit.uni-kl.de def _convert(cls, value): 126712027Sjungma@eit.uni-kl.de if value == Nxone: 126812027Sjungma@eit.uni-kl.de return 126912027Sjungma@eit.uni-kl.de 127012027Sjungma@eit.uni-kl.de if isinstance(value, cls): 127112027Sjungma@eit.uni-kl.de return value 127212027Sjungma@eit.uni-kl.de 127312027Sjungma@eit.uni-kl.de raise TypeError, 'object %s %s of the wrong type, should be %s' % \ 127412027Sjungma@eit.uni-kl.de (repr(value), type(value), cls) 127512027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 127612027Sjungma@eit.uni-kl.de 127712027Sjungma@eit.uni-kl.de def _string(): 127812027Sjungma@eit.uni-kl.de return 'NULL' 127912027Sjungma@eit.uni-kl.de _string = staticmethod(_string) 128012027Sjungma@eit.uni-kl.de 128112027Sjungma@eit.uni-kl.de# The only instance you'll ever need... 128212027Sjungma@eit.uni-kl.deNull = NULL = NullSimObject() 128312027Sjungma@eit.uni-kl.de 128412027Sjungma@eit.uni-kl.de# Enumerated types are a little more complex. The user specifies the 128512027Sjungma@eit.uni-kl.de# type as Enum(foo) where foo is either a list or dictionary of 128612027Sjungma@eit.uni-kl.de# alternatives (typically strings, but not necessarily so). (In the 128712027Sjungma@eit.uni-kl.de# long run, the integer value of the parameter will be the list index 128812027Sjungma@eit.uni-kl.de# or the corresponding dictionary value. For now, since we only check 128912027Sjungma@eit.uni-kl.de# that the alternative is valid and then spit it into a .ini file, 129012027Sjungma@eit.uni-kl.de# there's not much point in using the dictionary.) 129112027Sjungma@eit.uni-kl.de 129212027Sjungma@eit.uni-kl.de# What Enum() must do is generate a new type encapsulating the 129312027Sjungma@eit.uni-kl.de# provided list/dictionary so that specific values of the parameter 129412027Sjungma@eit.uni-kl.de# can be instances of that type. We define two hidden internal 129512027Sjungma@eit.uni-kl.de# classes (_ListEnum and _DictEnum) to serve as base classes, then 129612027Sjungma@eit.uni-kl.de# derive the new type from the appropriate base class on the fly. 129712027Sjungma@eit.uni-kl.de 129812027Sjungma@eit.uni-kl.de 129912027Sjungma@eit.uni-kl.de# Metaclass for Enum types 130012027Sjungma@eit.uni-kl.declass MetaEnum(type): 130112027Sjungma@eit.uni-kl.de def __init__(cls, name, bases, init_dict): 130212027Sjungma@eit.uni-kl.de if init_dict.has_key('map'): 130312027Sjungma@eit.uni-kl.de if not isinstance(cls.map, dict): 130412027Sjungma@eit.uni-kl.de raise TypeError, "Enum-derived class attribute 'map' " \ 130512027Sjungma@eit.uni-kl.de "must be of type dict" 130612027Sjungma@eit.uni-kl.de # build list of value strings from map 130712027Sjungma@eit.uni-kl.de cls.vals = cls.map.keys() 130812027Sjungma@eit.uni-kl.de cls.vals.sort() 130912027Sjungma@eit.uni-kl.de elif init_dict.has_key('vals'): 131012027Sjungma@eit.uni-kl.de if not isinstance(cls.vals, list): 131112027Sjungma@eit.uni-kl.de raise TypeError, "Enum-derived class attribute 'vals' " \ 131212027Sjungma@eit.uni-kl.de "must be of type list" 131312027Sjungma@eit.uni-kl.de # build string->value map from vals sequence 131412027Sjungma@eit.uni-kl.de cls.map = {} 131512027Sjungma@eit.uni-kl.de for idx,val in enumerate(cls.vals): 131612027Sjungma@eit.uni-kl.de cls.map[val] = idx 131712027Sjungma@eit.uni-kl.de else: 131812027Sjungma@eit.uni-kl.de raise TypeError, "Enum-derived class must define "\ 131912027Sjungma@eit.uni-kl.de "attribute 'map' or 'vals'" 132012027Sjungma@eit.uni-kl.de 132112027Sjungma@eit.uni-kl.de cls._cpp_param_decl = name 132212027Sjungma@eit.uni-kl.de 132312027Sjungma@eit.uni-kl.de super(MetaEnum, cls).__init__(name, bases, init_dict) 132412027Sjungma@eit.uni-kl.de 132512027Sjungma@eit.uni-kl.de def cpp_declare(cls): 132612027Sjungma@eit.uni-kl.de s = 'enum %s {\n ' % cls.__name__ 132712027Sjungma@eit.uni-kl.de s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals]) 132812027Sjungma@eit.uni-kl.de s += '\n};\n' 132912027Sjungma@eit.uni-kl.de return s 133012027Sjungma@eit.uni-kl.de 133112027Sjungma@eit.uni-kl.de# Base class for enum types. 133212027Sjungma@eit.uni-kl.declass Enum(ParamType): 133312027Sjungma@eit.uni-kl.de __metaclass__ = MetaEnum 133412027Sjungma@eit.uni-kl.de vals = [] 133512027Sjungma@eit.uni-kl.de 133612027Sjungma@eit.uni-kl.de def _convert(self, value): 133712027Sjungma@eit.uni-kl.de if value not in self.map: 133812027Sjungma@eit.uni-kl.de raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 133912027Sjungma@eit.uni-kl.de % (value, self.vals) 134012027Sjungma@eit.uni-kl.de return value 134112027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 134212027Sjungma@eit.uni-kl.de 134312027Sjungma@eit.uni-kl.de # Generate printable string version of value. 134412027Sjungma@eit.uni-kl.de def _string(self, value): 134512027Sjungma@eit.uni-kl.de return str(value) 134612027Sjungma@eit.uni-kl.de _string = classmethod(_string) 134712027Sjungma@eit.uni-kl.de# 134812027Sjungma@eit.uni-kl.de# "Constants"... handy aliases for various values. 134912027Sjungma@eit.uni-kl.de# 135012027Sjungma@eit.uni-kl.de 135112027Sjungma@eit.uni-kl.declass Frequency(int,ParamType): 135212027Sjungma@eit.uni-kl.de _cpp_param_decl = 'Tick' 135312027Sjungma@eit.uni-kl.de 135412027Sjungma@eit.uni-kl.de def __new__(cls, value): 135512027Sjungma@eit.uni-kl.de if isinstance(value, basestring): 135612027Sjungma@eit.uni-kl.de val = int(env['FREQUENCY'] / toFrequency(value)) 135712027Sjungma@eit.uni-kl.de else: 135812027Sjungma@eit.uni-kl.de val = toFrequency(value) 135912027Sjungma@eit.uni-kl.de return super(cls, Frequency).__new__(cls, val) 136012027Sjungma@eit.uni-kl.de 136112027Sjungma@eit.uni-kl.de def _convert(cls, value): 136212027Sjungma@eit.uni-kl.de return cls(value) 136312027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 136412027Sjungma@eit.uni-kl.de 136512027Sjungma@eit.uni-kl.de def _string(cls, value): 136612027Sjungma@eit.uni-kl.de return '%d' % value 136712027Sjungma@eit.uni-kl.de _string = classmethod(_string) 136812027Sjungma@eit.uni-kl.de 136912027Sjungma@eit.uni-kl.declass Latency(int,ParamType): 137012027Sjungma@eit.uni-kl.de _cpp_param_decl = 'Tick' 137112027Sjungma@eit.uni-kl.de def __new__(cls, value): 137212027Sjungma@eit.uni-kl.de if isinstance(value, basestring): 137312027Sjungma@eit.uni-kl.de val = int(env['FREQUENCY'] * toLatency(value)) 137412027Sjungma@eit.uni-kl.de else: 137512027Sjungma@eit.uni-kl.de val = toLatency(value) 137612027Sjungma@eit.uni-kl.de return super(cls, Latency).__new__(cls, val) 137712027Sjungma@eit.uni-kl.de 137812027Sjungma@eit.uni-kl.de def _convert(cls, value): 137912027Sjungma@eit.uni-kl.de return cls(value) 138012027Sjungma@eit.uni-kl.de _convert = classmethod(_convert) 138112027Sjungma@eit.uni-kl.de 138212027Sjungma@eit.uni-kl.de def _string(cls, value): 138312027Sjungma@eit.uni-kl.de return '%d' % value 138412027Sjungma@eit.uni-kl.de _string = classmethod(_string) 138512027Sjungma@eit.uni-kl.de 138612027Sjungma@eit.uni-kl.de 138712027Sjungma@eit.uni-kl.de# Some memory range specifications use this as a default upper bound. 138812027Sjungma@eit.uni-kl.deMaxAddr = Addr.max 138912027Sjungma@eit.uni-kl.deMaxTick = Tick.max 139012027Sjungma@eit.uni-kl.deAllMemory = AddrRange(0, MaxAddr) 139112027Sjungma@eit.uni-kl.de 139212027Sjungma@eit.uni-kl.de##################################################################### 139312027Sjungma@eit.uni-kl.de 139412027Sjungma@eit.uni-kl.de# The final hook to generate .ini files. Called from configuration 139512027Sjungma@eit.uni-kl.de# script once config is built. 139612027Sjungma@eit.uni-kl.dedef instantiate(root): 139712027Sjungma@eit.uni-kl.de instance = root.instantiate('root') 139812027Sjungma@eit.uni-kl.de instance.fixup() 139912027Sjungma@eit.uni-kl.de instance.display() 140012027Sjungma@eit.uni-kl.de if not noDot: 140112027Sjungma@eit.uni-kl.de dot = pydot.Dot() 140212027Sjungma@eit.uni-kl.de instance.outputDot(dot) 140312027Sjungma@eit.uni-kl.de dot.orientation = "portrait" 140412027Sjungma@eit.uni-kl.de dot.size = "8.5,11" 140512027Sjungma@eit.uni-kl.de dot.ranksep="equally" 140612027Sjungma@eit.uni-kl.de dot.rank="samerank" 140712027Sjungma@eit.uni-kl.de dot.write("config.dot") 140812027Sjungma@eit.uni-kl.de dot.write_ps("config.ps") 140912027Sjungma@eit.uni-kl.de 141012027Sjungma@eit.uni-kl.de# SimObject is a minimal extension of ConfigNode, implementing a 141112027Sjungma@eit.uni-kl.de# hierarchy node that corresponds to an M5 SimObject. It prints out a 141212027Sjungma@eit.uni-kl.de# "type=" line to indicate its SimObject class, prints out the 141312027Sjungma@eit.uni-kl.de# assigned parameters corresponding to its class, and allows 141412027Sjungma@eit.uni-kl.de# parameters to be set by keyword in the constructor. Note that most 141512027Sjungma@eit.uni-kl.de# of the heavy lifting for the SimObject param handling is done in the 141612027Sjungma@eit.uni-kl.de# MetaConfigNode metaclass. 141712027Sjungma@eit.uni-kl.declass SimObject(ConfigNode, ParamType): 141812027Sjungma@eit.uni-kl.de __metaclass__ = MetaSimObject 141912027Sjungma@eit.uni-kl.de type = 'SimObject' 142012027Sjungma@eit.uni-kl.de 142112027Sjungma@eit.uni-kl.de 142212027Sjungma@eit.uni-kl.de# __all__ defines the list of symbols that get exported when 142312027Sjungma@eit.uni-kl.de# 'from config import *' is invoked. Try to keep this reasonably 142412027Sjungma@eit.uni-kl.de# short to avoid polluting other namespaces. 142512027Sjungma@eit.uni-kl.de__all__ = ['ConfigNode', 'SimObject', 'ParamContext', 'Param', 'VectorParam', 142612027Sjungma@eit.uni-kl.de 'parent', 'Enum', 142712027Sjungma@eit.uni-kl.de 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 142812027Sjungma@eit.uni-kl.de 'Int32', 'UInt32', 'Int64', 'UInt64', 142912027Sjungma@eit.uni-kl.de 'Counter', 'Addr', 'Tick', 'Percent', 143012027Sjungma@eit.uni-kl.de 'MemorySize', 'Frequency', 'Latency', 143112027Sjungma@eit.uni-kl.de 'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'NULL', 143212027Sjungma@eit.uni-kl.de 'NextEthernetAddr', 'instantiate'] 143312027Sjungma@eit.uni-kl.de