SimObject.py revision 7493:81328f5e764a
110355SGeoffrey.Blake@arm.com# Copyright (c) 2004-2006 The Regents of The University of Michigan 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without 58839Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are 68839Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright 78839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer; 88839Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright 98839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the 108839Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution; 118839Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its 128839Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from 133101Sstever@eecs.umich.edu# this software without specific prior written permission. 148579Ssteve.reinhardt@amd.com# 153101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 163101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 173101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 183101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 193101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 203101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 213101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 223101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 233101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 243101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 253101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 263101Sstever@eecs.umich.edu# 273101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 283101Sstever@eecs.umich.edu# Nathan Binkert 293101Sstever@eecs.umich.edu 303101Sstever@eecs.umich.eduimport math 313101Sstever@eecs.umich.eduimport sys 323101Sstever@eecs.umich.edufrom types import FunctionType 333101Sstever@eecs.umich.edu 343101Sstever@eecs.umich.edutry: 353101Sstever@eecs.umich.edu import pydot 363101Sstever@eecs.umich.eduexcept: 373101Sstever@eecs.umich.edu pydot = False 383101Sstever@eecs.umich.edu 393101Sstever@eecs.umich.eduimport m5 403101Sstever@eecs.umich.edufrom m5.util import * 413101Sstever@eecs.umich.edu 427778Sgblack@eecs.umich.edu# Have to import params up top since Param is referenced on initial 438839Sandreas.hansson@arm.com# load (when SimObject class references Param to create a class 443101Sstever@eecs.umich.edu# variable, the 'name' param)... 453101Sstever@eecs.umich.edufrom m5.params import * 463101Sstever@eecs.umich.edu# There are a few things we need that aren't in params.__all__ since 473101Sstever@eecs.umich.edu# normal users don't need them 483101Sstever@eecs.umich.edufrom m5.params import ParamDesc, VectorParamDesc, isNullPointer, SimObjVector 493101Sstever@eecs.umich.edu 503101Sstever@eecs.umich.edufrom m5.proxy import * 513101Sstever@eecs.umich.edufrom m5.proxy import isproxy 523101Sstever@eecs.umich.edu 533101Sstever@eecs.umich.edu##################################################################### 543101Sstever@eecs.umich.edu# 553101Sstever@eecs.umich.edu# M5 Python Configuration Utility 563101Sstever@eecs.umich.edu# 573101Sstever@eecs.umich.edu# The basic idea is to write simple Python programs that build Python 583101Sstever@eecs.umich.edu# objects corresponding to M5 SimObjects for the desired simulation 593101Sstever@eecs.umich.edu# configuration. For now, the Python emits a .ini file that can be 603101Sstever@eecs.umich.edu# parsed by M5. In the future, some tighter integration between M5 613101Sstever@eecs.umich.edu# and the Python interpreter may allow bypassing the .ini file. 623885Sbinkertn@umich.edu# 633885Sbinkertn@umich.edu# Each SimObject class in M5 is represented by a Python class with the 644762Snate@binkert.org# same name. The Python inheritance tree mirrors the M5 C++ tree 653885Sbinkertn@umich.edu# (e.g., SimpleCPU derives from BaseCPU in both cases, and all 663885Sbinkertn@umich.edu# SimObjects inherit from a single SimObject base class). To specify 677528Ssteve.reinhardt@amd.com# an instance of an M5 SimObject in a configuration, the user simply 683885Sbinkertn@umich.edu# instantiates the corresponding Python object. The parameters for 694380Sbinkertn@umich.edu# that SimObject are given by assigning to attributes of the Python 704167Sbinkertn@umich.edu# object, either using keyword assignment in the constructor or in 713102Sstever@eecs.umich.edu# separate assignment statements. For example: 723101Sstever@eecs.umich.edu# 734762Snate@binkert.org# cache = BaseCache(size='64KB') 744762Snate@binkert.org# cache.hit_latency = 3 754762Snate@binkert.org# cache.assoc = 8 764762Snate@binkert.org# 774762Snate@binkert.org# The magic lies in the mapping of the Python attributes for SimObject 784762Snate@binkert.org# classes to the actual SimObject parameter specifications. This 794762Snate@binkert.org# allows parameter validity checking in the Python code. Continuing 804762Snate@binkert.org# the example above, the statements "cache.blurfl=3" or 814762Snate@binkert.org# "cache.assoc='hello'" would both result in runtime errors in Python, 825033Smilesck@eecs.umich.edu# since the BaseCache object has no 'blurfl' parameter and the 'assoc' 835033Smilesck@eecs.umich.edu# parameter requires an integer, respectively. This magic is done 845033Smilesck@eecs.umich.edu# primarily by overriding the special __setattr__ method that controls 855033Smilesck@eecs.umich.edu# assignment to object attributes. 865033Smilesck@eecs.umich.edu# 875033Smilesck@eecs.umich.edu# Once a set of Python objects have been instantiated in a hierarchy, 885033Smilesck@eecs.umich.edu# calling 'instantiate(obj)' (where obj is the root of the hierarchy) 895033Smilesck@eecs.umich.edu# will generate a .ini file. 905033Smilesck@eecs.umich.edu# 915033Smilesck@eecs.umich.edu##################################################################### 923101Sstever@eecs.umich.edu 933101Sstever@eecs.umich.edu# list of all SimObject classes 943101Sstever@eecs.umich.eduallClasses = {} 955033Smilesck@eecs.umich.edu 9610267SGeoffrey.Blake@arm.com# dict to look up SimObjects based on path 978596Ssteve.reinhardt@amd.cominstanceDict = {} 988596Ssteve.reinhardt@amd.com 998596Ssteve.reinhardt@amd.com# The metaclass for SimObject. This class controls how new classes 1008596Ssteve.reinhardt@amd.com# that derive from SimObject are instantiated, and provides inherited 1017673Snate@binkert.org# class behavior (just like a class controls how instances of that 1027673Snate@binkert.org# class are instantiated, and provides inherited instance behavior). 1037673Snate@binkert.orgclass MetaSimObject(type): 1047673Snate@binkert.org # Attributes that can be set only at initialization time 1058596Ssteve.reinhardt@amd.com init_keywords = { 'abstract' : bool, 1068596Ssteve.reinhardt@amd.com 'cxx_class' : str, 1078596Ssteve.reinhardt@amd.com 'cxx_type' : str, 1087673Snate@binkert.org 'cxx_predecls' : list, 1097673Snate@binkert.org 'swig_objdecls' : list, 1107673Snate@binkert.org 'swig_predecls' : list, 1113101Sstever@eecs.umich.edu 'type' : str } 1123101Sstever@eecs.umich.edu # Attributes that can be set any time 1133101Sstever@eecs.umich.edu keywords = { 'check' : FunctionType } 1143101Sstever@eecs.umich.edu 1153101Sstever@eecs.umich.edu # __new__ is called before __init__, and is where the statements 1163101Sstever@eecs.umich.edu # in the body of the class definition get loaded into the class's 11710380SAndrew.Bardsley@arm.com # __dict__. We intercept this to filter out parameter & port assignments 11810380SAndrew.Bardsley@arm.com # and only allow "private" attributes to be passed to the base 11910380SAndrew.Bardsley@arm.com # __new__ (starting with underscore). 12010380SAndrew.Bardsley@arm.com def __new__(mcls, name, bases, dict): 12110380SAndrew.Bardsley@arm.com assert name not in allClasses, "SimObject %s already present" % name 12210380SAndrew.Bardsley@arm.com 12310458Sandreas.hansson@arm.com # Copy "private" attributes, functions, and classes to the 12410458Sandreas.hansson@arm.com # official dict. Everything else goes in _init_dict to be 12510458Sandreas.hansson@arm.com # filtered in __init__. 12610458Sandreas.hansson@arm.com cls_dict = {} 12710458Sandreas.hansson@arm.com value_dict = {} 12810458Sandreas.hansson@arm.com for key,val in dict.items(): 12910458Sandreas.hansson@arm.com if key.startswith('_') or isinstance(val, (FunctionType, 13010458Sandreas.hansson@arm.com classmethod, 13110458Sandreas.hansson@arm.com type)): 13210458Sandreas.hansson@arm.com cls_dict[key] = val 13310458Sandreas.hansson@arm.com else: 13410458Sandreas.hansson@arm.com # must be a param/port setting 1353101Sstever@eecs.umich.edu value_dict[key] = val 1363101Sstever@eecs.umich.edu if 'abstract' not in value_dict: 1373101Sstever@eecs.umich.edu value_dict['abstract'] = False 1383101Sstever@eecs.umich.edu cls_dict['_value_dict'] = value_dict 1393101Sstever@eecs.umich.edu cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 14010267SGeoffrey.Blake@arm.com if 'type' in value_dict: 14110267SGeoffrey.Blake@arm.com allClasses[name] = cls 14210267SGeoffrey.Blake@arm.com return cls 14310267SGeoffrey.Blake@arm.com 1443101Sstever@eecs.umich.edu # subclass initialization 1453101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 1463101Sstever@eecs.umich.edu # calls type.__init__()... I think that's a no-op, but leave 1473101Sstever@eecs.umich.edu # it here just in case it's not. 1483101Sstever@eecs.umich.edu super(MetaSimObject, cls).__init__(name, bases, dict) 1493101Sstever@eecs.umich.edu 1503101Sstever@eecs.umich.edu # initialize required attributes 1513101Sstever@eecs.umich.edu 1523101Sstever@eecs.umich.edu # class-only attributes 1533101Sstever@eecs.umich.edu cls._params = multidict() # param descriptions 1543101Sstever@eecs.umich.edu cls._ports = multidict() # port descriptions 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.edu # class or instance attributes 1573101Sstever@eecs.umich.edu cls._values = multidict() # param values 1583101Sstever@eecs.umich.edu cls._port_refs = multidict() # port ref objects 1593101Sstever@eecs.umich.edu cls._instantiated = False # really instantiated, cloned, or subclassed 1603101Sstever@eecs.umich.edu 1613101Sstever@eecs.umich.edu # We don't support multiple inheritance. If you want to, you 1623101Sstever@eecs.umich.edu # must fix multidict to deal with it properly. 1633101Sstever@eecs.umich.edu if len(bases) > 1: 1643101Sstever@eecs.umich.edu raise TypeError, "SimObjects do not support multiple inheritance" 1653101Sstever@eecs.umich.edu 1663101Sstever@eecs.umich.edu base = bases[0] 1673101Sstever@eecs.umich.edu 1683101Sstever@eecs.umich.edu # Set up general inheritance via multidicts. A subclass will 1693101Sstever@eecs.umich.edu # inherit all its settings from the base class. The only time 1703101Sstever@eecs.umich.edu # the following is not true is when we define the SimObject 1713101Sstever@eecs.umich.edu # class itself (in which case the multidicts have no parent). 1723101Sstever@eecs.umich.edu if isinstance(base, MetaSimObject): 1733101Sstever@eecs.umich.edu cls._base = base 1743101Sstever@eecs.umich.edu cls._params.parent = base._params 1753101Sstever@eecs.umich.edu cls._ports.parent = base._ports 1763101Sstever@eecs.umich.edu cls._values.parent = base._values 1773101Sstever@eecs.umich.edu cls._port_refs.parent = base._port_refs 1783101Sstever@eecs.umich.edu # mark base as having been subclassed 1795033Smilesck@eecs.umich.edu base._instantiated = True 1806656Snate@binkert.org else: 1815033Smilesck@eecs.umich.edu cls._base = None 1825033Smilesck@eecs.umich.edu 1835033Smilesck@eecs.umich.edu # default keyword values 1843101Sstever@eecs.umich.edu if 'type' in cls._value_dict: 1853101Sstever@eecs.umich.edu if 'cxx_class' not in cls._value_dict: 1863101Sstever@eecs.umich.edu cls._value_dict['cxx_class'] = cls._value_dict['type'] 18710267SGeoffrey.Blake@arm.com 18810267SGeoffrey.Blake@arm.com cls._value_dict['cxx_type'] = '%s *' % cls._value_dict['cxx_class'] 18910267SGeoffrey.Blake@arm.com 19010267SGeoffrey.Blake@arm.com if 'cxx_predecls' not in cls._value_dict: 19110267SGeoffrey.Blake@arm.com # A forward class declaration is sufficient since we are 19210267SGeoffrey.Blake@arm.com # just declaring a pointer. 19310267SGeoffrey.Blake@arm.com class_path = cls._value_dict['cxx_class'].split('::') 19410267SGeoffrey.Blake@arm.com class_path.reverse() 19510267SGeoffrey.Blake@arm.com decl = 'class %s;' % class_path[0] 19610267SGeoffrey.Blake@arm.com for ns in class_path[1:]: 19710267SGeoffrey.Blake@arm.com decl = 'namespace %s { %s }' % (ns, decl) 19810267SGeoffrey.Blake@arm.com cls._value_dict['cxx_predecls'] = [decl] 19910267SGeoffrey.Blake@arm.com 2003101Sstever@eecs.umich.edu if 'swig_predecls' not in cls._value_dict: 2013101Sstever@eecs.umich.edu # A forward class declaration is sufficient since we are 2023101Sstever@eecs.umich.edu # just declaring a pointer. 2033101Sstever@eecs.umich.edu cls._value_dict['swig_predecls'] = \ 2043101Sstever@eecs.umich.edu cls._value_dict['cxx_predecls'] 2053101Sstever@eecs.umich.edu 2063101Sstever@eecs.umich.edu if 'swig_objdecls' not in cls._value_dict: 2073101Sstever@eecs.umich.edu cls._value_dict['swig_objdecls'] = [] 2083101Sstever@eecs.umich.edu 2093101Sstever@eecs.umich.edu # Now process the _value_dict items. They could be defining 2103102Sstever@eecs.umich.edu # new (or overriding existing) parameters or ports, setting 2113101Sstever@eecs.umich.edu # class keywords (e.g., 'abstract'), or setting parameter 2123101Sstever@eecs.umich.edu # values or port bindings. The first 3 can only be set when 2133101Sstever@eecs.umich.edu # the class is defined, so we handle them here. The others 21410267SGeoffrey.Blake@arm.com # can be set later too, so just emulate that by calling 21510267SGeoffrey.Blake@arm.com # setattr(). 21610267SGeoffrey.Blake@arm.com for key,val in cls._value_dict.items(): 21710267SGeoffrey.Blake@arm.com # param descriptions 21810267SGeoffrey.Blake@arm.com if isinstance(val, ParamDesc): 21910267SGeoffrey.Blake@arm.com cls._new_param(key, val) 22010267SGeoffrey.Blake@arm.com 2217673Snate@binkert.org # port objects 2228607Sgblack@eecs.umich.edu elif isinstance(val, Port): 2237673Snate@binkert.org cls._new_port(key, val) 2243101Sstever@eecs.umich.edu 2257673Snate@binkert.org # init-time-only keywords 2267673Snate@binkert.org elif cls.init_keywords.has_key(key): 2273101Sstever@eecs.umich.edu cls._set_keyword(key, val, cls.init_keywords[key]) 2287673Snate@binkert.org 2297673Snate@binkert.org # default: use normal path (ends up in __setattr__) 2303101Sstever@eecs.umich.edu else: 2313101Sstever@eecs.umich.edu setattr(cls, key, val) 2323101Sstever@eecs.umich.edu 2333101Sstever@eecs.umich.edu def _set_keyword(cls, keyword, val, kwtype): 2343101Sstever@eecs.umich.edu if not isinstance(val, kwtype): 2353101Sstever@eecs.umich.edu raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 2365033Smilesck@eecs.umich.edu (keyword, type(val), kwtype) 2375475Snate@binkert.org if isinstance(val, FunctionType): 2385475Snate@binkert.org val = classmethod(val) 2395475Snate@binkert.org type.__setattr__(cls, keyword, val) 2405475Snate@binkert.org 24110380SAndrew.Bardsley@arm.com def _new_param(cls, name, pdesc): 24210380SAndrew.Bardsley@arm.com # each param desc should be uniquely assigned to one variable 24310380SAndrew.Bardsley@arm.com assert(not hasattr(pdesc, 'name')) 2443101Sstever@eecs.umich.edu pdesc.name = name 2453101Sstever@eecs.umich.edu cls._params[name] = pdesc 2463101Sstever@eecs.umich.edu if hasattr(pdesc, 'default'): 2474762Snate@binkert.org cls._set_param(name, pdesc.default, pdesc) 2484762Snate@binkert.org 2494762Snate@binkert.org def _set_param(cls, name, value, param): 2503101Sstever@eecs.umich.edu assert(param.name == name) 2518460SAli.Saidi@ARM.com try: 2528459SAli.Saidi@ARM.com cls._values[name] = param.convert(value) 2538459SAli.Saidi@ARM.com except Exception, e: 2548459SAli.Saidi@ARM.com msg = "%s\nError setting param %s.%s to %s\n" % \ 2553101Sstever@eecs.umich.edu (e, cls.__name__, name, value) 2567528Ssteve.reinhardt@amd.com e.args = (msg, ) 2577528Ssteve.reinhardt@amd.com raise 2587528Ssteve.reinhardt@amd.com 2597528Ssteve.reinhardt@amd.com def _new_port(cls, name, port): 2607528Ssteve.reinhardt@amd.com # each port should be uniquely assigned to one variable 2617528Ssteve.reinhardt@amd.com assert(not hasattr(port, 'name')) 2623101Sstever@eecs.umich.edu port.name = name 2637528Ssteve.reinhardt@amd.com cls._ports[name] = port 2647528Ssteve.reinhardt@amd.com if hasattr(port, 'default'): 2657528Ssteve.reinhardt@amd.com cls._cls_get_port_ref(name).connect(port.default) 2667528Ssteve.reinhardt@amd.com 2677528Ssteve.reinhardt@amd.com # same as _get_port_ref, effectively, but for classes 2687528Ssteve.reinhardt@amd.com def _cls_get_port_ref(cls, attr): 2697528Ssteve.reinhardt@amd.com # Return reference that can be assigned to another port 2707528Ssteve.reinhardt@amd.com # via __setattr__. There is only ever one reference 2717528Ssteve.reinhardt@amd.com # object per port, but we create them lazily here. 2727528Ssteve.reinhardt@amd.com ref = cls._port_refs.get(attr) 2738321Ssteve.reinhardt@amd.com if not ref: 2748321Ssteve.reinhardt@amd.com ref = cls._ports[attr].makeRef(cls) 2757528Ssteve.reinhardt@amd.com cls._port_refs[attr] = ref 2767528Ssteve.reinhardt@amd.com return ref 2777528Ssteve.reinhardt@amd.com 2787528Ssteve.reinhardt@amd.com # Set attribute (called on foo.attr = value when foo is an 2797528Ssteve.reinhardt@amd.com # instance of class cls). 2807528Ssteve.reinhardt@amd.com def __setattr__(cls, attr, value): 2817528Ssteve.reinhardt@amd.com # normal processing for private attributes 2827528Ssteve.reinhardt@amd.com if attr.startswith('_'): 2837528Ssteve.reinhardt@amd.com type.__setattr__(cls, attr, value) 2847528Ssteve.reinhardt@amd.com return 2857528Ssteve.reinhardt@amd.com 2867528Ssteve.reinhardt@amd.com if cls.keywords.has_key(attr): 2877528Ssteve.reinhardt@amd.com cls._set_keyword(attr, value, cls.keywords[attr]) 2883101Sstever@eecs.umich.edu return 2898664SAli.Saidi@ARM.com 2908664SAli.Saidi@ARM.com if cls._ports.has_key(attr): 2918664SAli.Saidi@ARM.com cls._cls_get_port_ref(attr).connect(value) 2928664SAli.Saidi@ARM.com return 2938664SAli.Saidi@ARM.com 2948664SAli.Saidi@ARM.com if isSimObjectOrSequence(value) and cls._instantiated: 2959953Sgeoffrey.blake@arm.com raise RuntimeError, \ 2969953Sgeoffrey.blake@arm.com "cannot set SimObject parameter '%s' after\n" \ 2979953Sgeoffrey.blake@arm.com " class %s has been instantiated or subclassed" \ 2989953Sgeoffrey.blake@arm.com % (attr, cls.__name__) 2999953Sgeoffrey.blake@arm.com 3009953Sgeoffrey.blake@arm.com # check for param 3019953Sgeoffrey.blake@arm.com param = cls._params.get(attr) 3029953Sgeoffrey.blake@arm.com if param: 3039953Sgeoffrey.blake@arm.com cls._set_param(attr, value, param) 3049953Sgeoffrey.blake@arm.com return 3059953Sgeoffrey.blake@arm.com 3069953Sgeoffrey.blake@arm.com if isSimObjectOrSequence(value): 3079953Sgeoffrey.blake@arm.com # If RHS is a SimObject, it's an implicit child assignment. 30810267SGeoffrey.Blake@arm.com # Classes don't have children, so we just put this object 30910267SGeoffrey.Blake@arm.com # in _values; later, each instance will do a 'setattr(self, 31010267SGeoffrey.Blake@arm.com # attr, _values[attr])' in SimObject.__init__ which will 31110267SGeoffrey.Blake@arm.com # add this object as a child. 31210267SGeoffrey.Blake@arm.com cls._values[attr] = value 31310267SGeoffrey.Blake@arm.com return 31410267SGeoffrey.Blake@arm.com 31510267SGeoffrey.Blake@arm.com # no valid assignment... raise exception 31610267SGeoffrey.Blake@arm.com raise AttributeError, \ 31710267SGeoffrey.Blake@arm.com "Class %s has no parameter \'%s\'" % (cls.__name__, attr) 31810267SGeoffrey.Blake@arm.com 31910267SGeoffrey.Blake@arm.com def __getattr__(cls, attr): 32010267SGeoffrey.Blake@arm.com if cls._values.has_key(attr): 32110267SGeoffrey.Blake@arm.com return cls._values[attr] 32210267SGeoffrey.Blake@arm.com 32310267SGeoffrey.Blake@arm.com raise AttributeError, \ 32410267SGeoffrey.Blake@arm.com "object '%s' has no attribute '%s'" % (cls.__name__, attr) 32510267SGeoffrey.Blake@arm.com 32610267SGeoffrey.Blake@arm.com def __str__(cls): 32710267SGeoffrey.Blake@arm.com return cls.__name__ 3283101Sstever@eecs.umich.edu 3293101Sstever@eecs.umich.edu def cxx_decl(cls): 3303101Sstever@eecs.umich.edu code = "#ifndef __PARAMS__%s\n" % cls 3313101Sstever@eecs.umich.edu code += "#define __PARAMS__%s\n\n" % cls 3323101Sstever@eecs.umich.edu 3333101Sstever@eecs.umich.edu # The 'dict' attribute restricts us to the params declared in 3343101Sstever@eecs.umich.edu # the object itself, not including inherited params (which 33510364SGeoffrey.Blake@arm.com # will also be inherited from the base class's param struct 33610364SGeoffrey.Blake@arm.com # here). 33710364SGeoffrey.Blake@arm.com params = cls._params.local.values() 33810364SGeoffrey.Blake@arm.com try: 3393101Sstever@eecs.umich.edu ptypes = [p.ptype for p in params] 3404762Snate@binkert.org except: 3414762Snate@binkert.org print cls, p, p.ptype_str 3424762Snate@binkert.org print params 3434762Snate@binkert.org raise 3447528Ssteve.reinhardt@amd.com 3454762Snate@binkert.org # get a list of lists of predeclaration lines 3464762Snate@binkert.org predecls = [] 3474762Snate@binkert.org predecls.extend(cls.cxx_predecls) 34810267SGeoffrey.Blake@arm.com for p in params: 34910267SGeoffrey.Blake@arm.com predecls.extend(p.cxx_predecls()) 35010267SGeoffrey.Blake@arm.com # remove redundant lines 35110267SGeoffrey.Blake@arm.com predecls2 = [] 35210267SGeoffrey.Blake@arm.com for pd in predecls: 35310267SGeoffrey.Blake@arm.com if pd not in predecls2: 35410267SGeoffrey.Blake@arm.com predecls2.append(pd) 35510267SGeoffrey.Blake@arm.com predecls2.sort() 35610267SGeoffrey.Blake@arm.com code += "\n".join(predecls2) 35710267SGeoffrey.Blake@arm.com code += "\n\n"; 35810267SGeoffrey.Blake@arm.com 35910267SGeoffrey.Blake@arm.com if cls._base: 36010267SGeoffrey.Blake@arm.com code += '#include "params/%s.hh"\n\n' % cls._base.type 36110267SGeoffrey.Blake@arm.com 36210267SGeoffrey.Blake@arm.com for ptype in ptypes: 36310267SGeoffrey.Blake@arm.com if issubclass(ptype, Enum): 36410267SGeoffrey.Blake@arm.com code += '#include "enums/%s.hh"\n' % ptype.__name__ 36510267SGeoffrey.Blake@arm.com code += "\n\n" 36610267SGeoffrey.Blake@arm.com 36710267SGeoffrey.Blake@arm.com code += cls.cxx_struct(cls._base, params) 36810267SGeoffrey.Blake@arm.com 36910267SGeoffrey.Blake@arm.com # close #ifndef __PARAMS__* guard 37010267SGeoffrey.Blake@arm.com code += "\n#endif\n" 37110267SGeoffrey.Blake@arm.com return code 37210267SGeoffrey.Blake@arm.com 37310267SGeoffrey.Blake@arm.com def cxx_struct(cls, base, params): 37410364SGeoffrey.Blake@arm.com if cls == SimObject: 37510364SGeoffrey.Blake@arm.com return '#include "sim/sim_object_params.hh"\n' 37610267SGeoffrey.Blake@arm.com 37710267SGeoffrey.Blake@arm.com # now generate the actual param struct 37810267SGeoffrey.Blake@arm.com code = "struct %sParams" % cls 37910267SGeoffrey.Blake@arm.com if base: 38010267SGeoffrey.Blake@arm.com code += " : public %sParams" % base.type 38110267SGeoffrey.Blake@arm.com code += "\n{\n" 3828596Ssteve.reinhardt@amd.com if not hasattr(cls, 'abstract') or not cls.abstract: 3838596Ssteve.reinhardt@amd.com if 'type' in cls.__dict__: 3848596Ssteve.reinhardt@amd.com code += " %s create();\n" % cls.cxx_type 3857673Snate@binkert.org decls = [p.cxx_decl() for p in params] 3868596Ssteve.reinhardt@amd.com decls.sort() 3874762Snate@binkert.org code += "".join([" %s\n" % d for d in decls]) 3887673Snate@binkert.org code += "};\n" 3898596Ssteve.reinhardt@amd.com 3907675Snate@binkert.org return code 3917675Snate@binkert.org 3927675Snate@binkert.org def swig_decl(cls): 3937675Snate@binkert.org code = '%%module %s\n' % cls 3948656Sandreas.hansson@arm.com 3958656Sandreas.hansson@arm.com code += '%{\n' 3968656Sandreas.hansson@arm.com code += '#include "params/%s.hh"\n' % cls 3977675Snate@binkert.org code += '%}\n\n' 3987675Snate@binkert.org 3997673Snate@binkert.org # The 'dict' attribute restricts us to the params declared in 4007675Snate@binkert.org # the object itself, not including inherited params (which 4017675Snate@binkert.org # will also be inherited from the base class's param struct 4027675Snate@binkert.org # here). 4037675Snate@binkert.org params = cls._params.local.values() 4047675Snate@binkert.org ptypes = [p.ptype for p in params] 4057675Snate@binkert.org 4067675Snate@binkert.org # get a list of lists of predeclaration lines 4077673Snate@binkert.org predecls = [] 4087673Snate@binkert.org predecls.extend([ p.swig_predecls() for p in params ]) 4097673Snate@binkert.org # flatten 4103101Sstever@eecs.umich.edu predecls = reduce(lambda x,y:x+y, predecls, []) 4117673Snate@binkert.org # remove redundant lines 4127673Snate@binkert.org predecls2 = [] 4133101Sstever@eecs.umich.edu for pd in predecls: 4143101Sstever@eecs.umich.edu if pd not in predecls2: 4153101Sstever@eecs.umich.edu predecls2.append(pd) 4163101Sstever@eecs.umich.edu predecls2.sort() 4173101Sstever@eecs.umich.edu code += "\n".join(predecls2) 4183101Sstever@eecs.umich.edu code += "\n\n"; 4193101Sstever@eecs.umich.edu 4203101Sstever@eecs.umich.edu if cls._base: 4213101Sstever@eecs.umich.edu code += '%%import "params/%s.i"\n\n' % cls._base.type 4223101Sstever@eecs.umich.edu 4233101Sstever@eecs.umich.edu for ptype in ptypes: 4243101Sstever@eecs.umich.edu if issubclass(ptype, Enum): 4253101Sstever@eecs.umich.edu code += '%%import "enums/%s.hh"\n' % ptype.__name__ 4263101Sstever@eecs.umich.edu code += "\n\n" 4273101Sstever@eecs.umich.edu 4285033Smilesck@eecs.umich.edu code += '%%import "params/%s_type.hh"\n\n' % cls 4295033Smilesck@eecs.umich.edu code += '%%include "params/%s.hh"\n\n' % cls 4303101Sstever@eecs.umich.edu 4313101Sstever@eecs.umich.edu return code 4323101Sstever@eecs.umich.edu 4333101Sstever@eecs.umich.edu# The SimObject class is the root of the special hierarchy. Most of 4343101Sstever@eecs.umich.edu# the code in this class deals with the configuration hierarchy itself 4353101Sstever@eecs.umich.edu# (parent/child node relationships). 4363101Sstever@eecs.umich.educlass SimObject(object): 4373101Sstever@eecs.umich.edu # Specify metaclass. Any class inheriting from SimObject will 4383101Sstever@eecs.umich.edu # get this metaclass. 4393101Sstever@eecs.umich.edu __metaclass__ = MetaSimObject 4403101Sstever@eecs.umich.edu type = 'SimObject' 4413101Sstever@eecs.umich.edu abstract = True 4423101Sstever@eecs.umich.edu 4433101Sstever@eecs.umich.edu swig_objdecls = [ '%include "python/swig/sim_object.i"' ] 4443101Sstever@eecs.umich.edu 4453101Sstever@eecs.umich.edu # Initialize new instance. For objects with SimObject-valued 4463101Sstever@eecs.umich.edu # children, we need to recursively clone the classes represented 4473101Sstever@eecs.umich.edu # by those param values as well in a consistent "deep copy"-style 4483101Sstever@eecs.umich.edu # fashion. That is, we want to make sure that each instance is 4493101Sstever@eecs.umich.edu # cloned only once, and that if there are multiple references to 4503101Sstever@eecs.umich.edu # the same original object, we end up with the corresponding 4513101Sstever@eecs.umich.edu # cloned references all pointing to the same cloned instance. 4523101Sstever@eecs.umich.edu def __init__(self, **kwargs): 4533101Sstever@eecs.umich.edu ancestor = kwargs.get('_ancestor') 4543101Sstever@eecs.umich.edu memo_dict = kwargs.get('_memo') 45510267SGeoffrey.Blake@arm.com if memo_dict is None: 4567673Snate@binkert.org # prepare to memoize any recursively instantiated objects 4577673Snate@binkert.org memo_dict = {} 4587673Snate@binkert.org elif ancestor: 4597673Snate@binkert.org # memoize me now to avoid problems with recursive calls 4607673Snate@binkert.org memo_dict[ancestor] = self 4617673Snate@binkert.org 4627673Snate@binkert.org if not ancestor: 4637673Snate@binkert.org ancestor = self.__class__ 4644762Snate@binkert.org ancestor._instantiated = True 46510267SGeoffrey.Blake@arm.com 46610267SGeoffrey.Blake@arm.com # initialize required attributes 46710267SGeoffrey.Blake@arm.com self._parent = None 46810267SGeoffrey.Blake@arm.com self._children = {} 46910458Sandreas.hansson@arm.com self._ccObject = None # pointer to C++ object 47010458Sandreas.hansson@arm.com self._ccParams = None 47110458Sandreas.hansson@arm.com self._instantiated = False # really "cloned" 47210458Sandreas.hansson@arm.com 47310458Sandreas.hansson@arm.com # Inherit parameter values from class using multidict so 4744762Snate@binkert.org # individual value settings can be overridden. 4754762Snate@binkert.org self._values = multidict(ancestor._values) 4763101Sstever@eecs.umich.edu # clone SimObject-valued parameters 4773101Sstever@eecs.umich.edu for key,val in ancestor._values.iteritems(): 4783101Sstever@eecs.umich.edu if isSimObject(val): 4793101Sstever@eecs.umich.edu setattr(self, key, val(_memo=memo_dict)) 4803101Sstever@eecs.umich.edu elif isSimObjectSequence(val) and len(val): 4813101Sstever@eecs.umich.edu setattr(self, key, [ v(_memo=memo_dict) for v in val ]) 4823101Sstever@eecs.umich.edu # clone port references. no need to use a multidict here 4833101Sstever@eecs.umich.edu # since we will be creating new references for all ports. 4843101Sstever@eecs.umich.edu self._port_refs = {} 4853101Sstever@eecs.umich.edu for key,val in ancestor._port_refs.iteritems(): 4863101Sstever@eecs.umich.edu self._port_refs[key] = val.clone(self, memo_dict) 4873714Sstever@eecs.umich.edu # apply attribute assignments from keyword args, if any 4883714Sstever@eecs.umich.edu for key,val in kwargs.iteritems(): 4893714Sstever@eecs.umich.edu setattr(self, key, val) 4903714Sstever@eecs.umich.edu 4913714Sstever@eecs.umich.edu # "Clone" the current instance by creating another instance of 4923714Sstever@eecs.umich.edu # this instance's class, but that inherits its parameter values 4933101Sstever@eecs.umich.edu # and port mappings from the current instance. If we're in a 4943101Sstever@eecs.umich.edu # "deep copy" recursive clone, check the _memo dict to see if 4953101Sstever@eecs.umich.edu # we've already cloned this instance. 4963101Sstever@eecs.umich.edu def __call__(self, **kwargs): 4973101Sstever@eecs.umich.edu memo_dict = kwargs.get('_memo') 4983101Sstever@eecs.umich.edu if memo_dict is None: 4993101Sstever@eecs.umich.edu # no memo_dict: must be top-level clone operation. 5003101Sstever@eecs.umich.edu # this is only allowed at the root of a hierarchy 5013101Sstever@eecs.umich.edu if self._parent: 5023101Sstever@eecs.umich.edu raise RuntimeError, "attempt to clone object %s " \ 5033101Sstever@eecs.umich.edu "not at the root of a tree (parent = %s)" \ 5043101Sstever@eecs.umich.edu % (self, self._parent) 5053101Sstever@eecs.umich.edu # create a new dict and use that. 5063101Sstever@eecs.umich.edu memo_dict = {} 5073101Sstever@eecs.umich.edu kwargs['_memo'] = memo_dict 5083101Sstever@eecs.umich.edu elif memo_dict.has_key(self): 5093101Sstever@eecs.umich.edu # clone already done & memoized 5103101Sstever@eecs.umich.edu return memo_dict[self] 5113101Sstever@eecs.umich.edu return self.__class__(_ancestor = self, **kwargs) 5123101Sstever@eecs.umich.edu 5133101Sstever@eecs.umich.edu def _get_port_ref(self, attr): 5143101Sstever@eecs.umich.edu # Return reference that can be assigned to another port 5153101Sstever@eecs.umich.edu # via __setattr__. There is only ever one reference 5163101Sstever@eecs.umich.edu # object per port, but we create them lazily here. 51710380SAndrew.Bardsley@arm.com ref = self._port_refs.get(attr) 51810380SAndrew.Bardsley@arm.com if not ref: 51910380SAndrew.Bardsley@arm.com ref = self._ports[attr].makeRef(self) 52010458Sandreas.hansson@arm.com self._port_refs[attr] = ref 52110458Sandreas.hansson@arm.com return ref 52210458Sandreas.hansson@arm.com 52310458Sandreas.hansson@arm.com def __getattr__(self, attr): 52410458Sandreas.hansson@arm.com if self._ports.has_key(attr): 52510458Sandreas.hansson@arm.com return self._get_port_ref(attr) 52610458Sandreas.hansson@arm.com 52710458Sandreas.hansson@arm.com if self._values.has_key(attr): 52810458Sandreas.hansson@arm.com return self._values[attr] 52910458Sandreas.hansson@arm.com 53010458Sandreas.hansson@arm.com raise AttributeError, "object '%s' has no attribute '%s'" \ 53110458Sandreas.hansson@arm.com % (self.__class__.__name__, attr) 53210458Sandreas.hansson@arm.com 5333101Sstever@eecs.umich.edu # Set attribute (called on foo.attr = value when foo is an 5345033Smilesck@eecs.umich.edu # instance of class cls). 5353101Sstever@eecs.umich.edu def __setattr__(self, attr, value): 5363101Sstever@eecs.umich.edu # normal processing for private attributes 5373101Sstever@eecs.umich.edu if attr.startswith('_'): 5383101Sstever@eecs.umich.edu object.__setattr__(self, attr, value) 5393101Sstever@eecs.umich.edu return 5403101Sstever@eecs.umich.edu 5413101Sstever@eecs.umich.edu if self._ports.has_key(attr): 5423101Sstever@eecs.umich.edu # set up port connection 5433101Sstever@eecs.umich.edu self._get_port_ref(attr).connect(value) 5443101Sstever@eecs.umich.edu return 5453101Sstever@eecs.umich.edu 5463101Sstever@eecs.umich.edu if isSimObjectOrSequence(value) and self._instantiated: 5475822Ssaidi@eecs.umich.edu raise RuntimeError, \ 5485822Ssaidi@eecs.umich.edu "cannot set SimObject parameter '%s' after\n" \ 5493101Sstever@eecs.umich.edu " instance been cloned %s" % (attr, `self`) 5503101Sstever@eecs.umich.edu 5513101Sstever@eecs.umich.edu # must be SimObject param 5523101Sstever@eecs.umich.edu param = self._params.get(attr) 5533101Sstever@eecs.umich.edu if param: 5543101Sstever@eecs.umich.edu try: 5553101Sstever@eecs.umich.edu value = param.convert(value) 5563101Sstever@eecs.umich.edu except Exception, e: 5573101Sstever@eecs.umich.edu msg = "%s\nError setting param %s.%s to %s\n" % \ 5583101Sstever@eecs.umich.edu (e, self.__class__.__name__, attr, value) 5593101Sstever@eecs.umich.edu e.args = (msg, ) 5603101Sstever@eecs.umich.edu raise 5613101Sstever@eecs.umich.edu self._set_child(attr, value) 56210267SGeoffrey.Blake@arm.com return 5633101Sstever@eecs.umich.edu 5643101Sstever@eecs.umich.edu if isSimObjectOrSequence(value): 5653101Sstever@eecs.umich.edu self._set_child(attr, value) 5663101Sstever@eecs.umich.edu return 5673101Sstever@eecs.umich.edu 5683101Sstever@eecs.umich.edu # no valid assignment... raise exception 5693101Sstever@eecs.umich.edu raise AttributeError, "Class %s has no parameter %s" \ 5703101Sstever@eecs.umich.edu % (self.__class__.__name__, attr) 5713102Sstever@eecs.umich.edu 5723714Sstever@eecs.umich.edu 5733101Sstever@eecs.umich.edu # this hack allows tacking a '[0]' onto parameters that may or may 5743714Sstever@eecs.umich.edu # not be vectors, and always getting the first element (e.g. cpus) 5753714Sstever@eecs.umich.edu def __getitem__(self, key): 5763714Sstever@eecs.umich.edu if key == 0: 5773101Sstever@eecs.umich.edu return self 5783101Sstever@eecs.umich.edu raise TypeError, "Non-zero index '%s' to SimObject" % key 57910267SGeoffrey.Blake@arm.com 58010267SGeoffrey.Blake@arm.com # clear out children with given name, even if it's a vector 58110267SGeoffrey.Blake@arm.com def clear_child(self, name): 58210267SGeoffrey.Blake@arm.com if not self._children.has_key(name): 5837673Snate@binkert.org return 5847673Snate@binkert.org child = self._children[name] 5857673Snate@binkert.org if isinstance(child, SimObjVector): 5867673Snate@binkert.org for i in xrange(len(child)): 5877673Snate@binkert.org del self._children["s%d" % (name, i)] 5887673Snate@binkert.org del self._children[name] 5897673Snate@binkert.org 5907673Snate@binkert.org def add_child(self, name, value): 5917673Snate@binkert.org self._children[name] = value 5927673Snate@binkert.org 5937673Snate@binkert.org def _maybe_set_parent(self, parent, name): 5944762Snate@binkert.org if not self._parent: 5954762Snate@binkert.org self._parent = parent 5964762Snate@binkert.org self._name = name 5973101Sstever@eecs.umich.edu parent.add_child(name, self) 5983101Sstever@eecs.umich.edu 5993101Sstever@eecs.umich.edu def _set_child(self, attr, value): 6003101Sstever@eecs.umich.edu # if RHS is a SimObject, it's an implicit child assignment 6013101Sstever@eecs.umich.edu # clear out old child with this name, if any 6023101Sstever@eecs.umich.edu self.clear_child(attr) 6033101Sstever@eecs.umich.edu 6043101Sstever@eecs.umich.edu if isSimObject(value): 6053101Sstever@eecs.umich.edu value._maybe_set_parent(self, attr) 6063101Sstever@eecs.umich.edu elif isSimObjectSequence(value): 6073101Sstever@eecs.umich.edu value = SimObjVector(value) 6083101Sstever@eecs.umich.edu if len(value) == 1: 6093101Sstever@eecs.umich.edu value[0]._maybe_set_parent(self, attr) 6103101Sstever@eecs.umich.edu else: 6113101Sstever@eecs.umich.edu width = int(math.ceil(math.log(len(value))/math.log(10))) 6123101Sstever@eecs.umich.edu for i,v in enumerate(value): 6133101Sstever@eecs.umich.edu v._maybe_set_parent(self, "%s%0*d" % (attr, width, i)) 6143101Sstever@eecs.umich.edu 6153101Sstever@eecs.umich.edu self._values[attr] = value 6169184Sandreas.hansson@arm.com 6179184Sandreas.hansson@arm.com def path(self): 6189184Sandreas.hansson@arm.com if not self._parent: 6199184Sandreas.hansson@arm.com return 'root' 6209184Sandreas.hansson@arm.com ppath = self._parent.path() 6219184Sandreas.hansson@arm.com if ppath == 'root': 6229184Sandreas.hansson@arm.com return self._name 6239184Sandreas.hansson@arm.com return ppath + "." + self._name 6249184Sandreas.hansson@arm.com 62510458Sandreas.hansson@arm.com def __str__(self): 62610458Sandreas.hansson@arm.com return self.path() 62710458Sandreas.hansson@arm.com 62810458Sandreas.hansson@arm.com def ini_str(self): 62910458Sandreas.hansson@arm.com return self.path() 63010458Sandreas.hansson@arm.com 63110458Sandreas.hansson@arm.com def find_any(self, ptype): 63210458Sandreas.hansson@arm.com if isinstance(self, ptype): 63310458Sandreas.hansson@arm.com return self, True 63410458Sandreas.hansson@arm.com 63510458Sandreas.hansson@arm.com found_obj = None 63610458Sandreas.hansson@arm.com for child in self._children.itervalues(): 63710458Sandreas.hansson@arm.com if isinstance(child, ptype): 63810458Sandreas.hansson@arm.com if found_obj != None and child != found_obj: 6393101Sstever@eecs.umich.edu raise AttributeError, \ 6404446Sbinkertn@umich.edu 'parent.any matched more than one: %s %s' % \ 64110668SGeoffrey.Blake@arm.com (found_obj.path, child.path) 6423101Sstever@eecs.umich.edu found_obj = child 6435468Snate@binkert.org # search param space 64410267SGeoffrey.Blake@arm.com for pname,pdesc in self._params.iteritems(): 6455468Snate@binkert.org if issubclass(pdesc.ptype, ptype): 6465468Snate@binkert.org match_obj = self._values[pname] 6475468Snate@binkert.org if found_obj != None and found_obj != match_obj: 6485468Snate@binkert.org raise AttributeError, \ 6495468Snate@binkert.org 'parent.any matched more than one: %s and %s' % (found_obj.path, match_obj.path) 65010267SGeoffrey.Blake@arm.com found_obj = match_obj 65110267SGeoffrey.Blake@arm.com return found_obj, found_obj != None 65210267SGeoffrey.Blake@arm.com 65310267SGeoffrey.Blake@arm.com def unproxy(self, base): 6544762Snate@binkert.org return self 6554762Snate@binkert.org 6564762Snate@binkert.org def unproxy_all(self): 65710380SAndrew.Bardsley@arm.com for param in self._params.iterkeys(): 65810380SAndrew.Bardsley@arm.com value = self._values.get(param) 65910380SAndrew.Bardsley@arm.com if value != None and isproxy(value): 66010458Sandreas.hansson@arm.com try: 66110458Sandreas.hansson@arm.com value = value.unproxy(self) 66210458Sandreas.hansson@arm.com except: 66310458Sandreas.hansson@arm.com print "Error in unproxying param '%s' of %s" % \ 66410458Sandreas.hansson@arm.com (param, self.path()) 66510458Sandreas.hansson@arm.com raise 66610458Sandreas.hansson@arm.com setattr(self, param, value) 66710458Sandreas.hansson@arm.com 6683101Sstever@eecs.umich.edu # Unproxy ports in sorted order so that 'append' operations on 6693101Sstever@eecs.umich.edu # vector ports are done in a deterministic fashion. 67010267SGeoffrey.Blake@arm.com port_names = self._ports.keys() 6713101Sstever@eecs.umich.edu port_names.sort() 6723101Sstever@eecs.umich.edu for port_name in port_names: 6733101Sstever@eecs.umich.edu port = self._port_refs.get(port_name) 6743101Sstever@eecs.umich.edu if port != None: 6753101Sstever@eecs.umich.edu port.unproxy(self) 6763101Sstever@eecs.umich.edu 6773102Sstever@eecs.umich.edu # Unproxy children in sorted order for determinism also. 6783101Sstever@eecs.umich.edu child_names = self._children.keys() 6793101Sstever@eecs.umich.edu child_names.sort() 6803101Sstever@eecs.umich.edu for child in child_names: 6814168Sbinkertn@umich.edu self._children[child].unproxy_all() 68210267SGeoffrey.Blake@arm.com 6833101Sstever@eecs.umich.edu def print_ini(self, ini_file): 6843101Sstever@eecs.umich.edu print >>ini_file, '[' + self.path() + ']' # .ini section header 6853101Sstever@eecs.umich.edu 6863101Sstever@eecs.umich.edu instanceDict[self.path()] = self 6873101Sstever@eecs.umich.edu 6883101Sstever@eecs.umich.edu if hasattr(self, 'type'): 6893102Sstever@eecs.umich.edu print >>ini_file, 'type=%s' % self.type 6903101Sstever@eecs.umich.edu 6913101Sstever@eecs.umich.edu child_names = self._children.keys() 6923101Sstever@eecs.umich.edu child_names.sort() 6933101Sstever@eecs.umich.edu if len(child_names): 6943101Sstever@eecs.umich.edu print >>ini_file, 'children=%s' % ' '.join(child_names) 6953101Sstever@eecs.umich.edu 6963101Sstever@eecs.umich.edu param_names = self._params.keys() 6973101Sstever@eecs.umich.edu param_names.sort() 6983101Sstever@eecs.umich.edu for param in param_names: 6993101Sstever@eecs.umich.edu value = self._values.get(param) 7003101Sstever@eecs.umich.edu if value != None: 70110317Smitch.hayenga@arm.com print >>ini_file, '%s=%s' % (param, 70210317Smitch.hayenga@arm.com self._values[param].ini_str()) 70310317Smitch.hayenga@arm.com 70410317Smitch.hayenga@arm.com port_names = self._ports.keys() 70510317Smitch.hayenga@arm.com port_names.sort() 7063102Sstever@eecs.umich.edu for port_name in port_names: 70710317Smitch.hayenga@arm.com port = self._port_refs.get(port_name, None) 70810317Smitch.hayenga@arm.com if port != None: 70910317Smitch.hayenga@arm.com print >>ini_file, '%s=%s' % (port_name, port.ini_str()) 71010317Smitch.hayenga@arm.com 71110317Smitch.hayenga@arm.com print >>ini_file # blank line between objects 7123101Sstever@eecs.umich.edu 7133584Ssaidi@eecs.umich.edu for child in child_names: 7143584Ssaidi@eecs.umich.edu self._children[child].print_ini(ini_file) 7153584Ssaidi@eecs.umich.edu 7163584Ssaidi@eecs.umich.edu def getCCParams(self): 7173584Ssaidi@eecs.umich.edu if self._ccParams: 71810267SGeoffrey.Blake@arm.com return self._ccParams 71910267SGeoffrey.Blake@arm.com 72010267SGeoffrey.Blake@arm.com cc_params_struct = getattr(m5.objects.params, '%sParams' % self.type) 72110267SGeoffrey.Blake@arm.com cc_params = cc_params_struct() 72210267SGeoffrey.Blake@arm.com cc_params.pyobj = self 72310267SGeoffrey.Blake@arm.com cc_params.name = str(self) 7243101Sstever@eecs.umich.edu 7259232Sandreas.hansson@arm.com param_names = self._params.keys() 7269235Sandreas.hansson@arm.com param_names.sort() 7273101Sstever@eecs.umich.edu for param in param_names: 7283101Sstever@eecs.umich.edu value = self._values.get(param) 7299411Sandreas.hansson@arm.com if value is None: 7309411Sandreas.hansson@arm.com fatal("%s.%s without default or user set value", 7319411Sandreas.hansson@arm.com self.path(), param) 7329411Sandreas.hansson@arm.com 7339411Sandreas.hansson@arm.com value = value.getValue() 7343101Sstever@eecs.umich.edu if isinstance(self._params[param], VectorParamDesc): 7359411Sandreas.hansson@arm.com assert isinstance(value, list) 7369411Sandreas.hansson@arm.com vec = getattr(cc_params, param) 7379411Sandreas.hansson@arm.com assert not len(vec) 7383101Sstever@eecs.umich.edu for v in value: 7399232Sandreas.hansson@arm.com vec.append(v) 7403101Sstever@eecs.umich.edu else: 7419232Sandreas.hansson@arm.com setattr(cc_params, param, value) 7423101Sstever@eecs.umich.edu 7433101Sstever@eecs.umich.edu port_names = self._ports.keys() 7443101Sstever@eecs.umich.edu port_names.sort() 7459411Sandreas.hansson@arm.com for port_name in port_names: 7469411Sandreas.hansson@arm.com port = self._port_refs.get(port_name, None) 7479411Sandreas.hansson@arm.com if port != None: 7489411Sandreas.hansson@arm.com setattr(cc_params, port_name, port) 7499411Sandreas.hansson@arm.com self._ccParams = cc_params 7509411Sandreas.hansson@arm.com return self._ccParams 7519411Sandreas.hansson@arm.com 7529411Sandreas.hansson@arm.com # Get C++ object corresponding to this object, calling C++ if 7533101Sstever@eecs.umich.edu # necessary to construct it. Does *not* recursively create 7549232Sandreas.hansson@arm.com # children. 7553101Sstever@eecs.umich.edu def getCCObject(self): 7563101Sstever@eecs.umich.edu if not self._ccObject: 7573101Sstever@eecs.umich.edu # Cycles in the configuration heirarchy are not supported. This 7583101Sstever@eecs.umich.edu # will catch the resulting recursion and stop. 7599232Sandreas.hansson@arm.com self._ccObject = -1 7603101Sstever@eecs.umich.edu params = self.getCCParams() 7615219Ssaidi@eecs.umich.edu self._ccObject = params.create() 7629232Sandreas.hansson@arm.com elif self._ccObject == -1: 7639232Sandreas.hansson@arm.com raise RuntimeError, "%s: Cycle found in configuration heirarchy." \ 7643101Sstever@eecs.umich.edu % self.path() 7659232Sandreas.hansson@arm.com return self._ccObject 7669232Sandreas.hansson@arm.com 7673101Sstever@eecs.umich.edu # Call C++ to create C++ object corresponding to this object and 7683101Sstever@eecs.umich.edu # (recursively) all its children 7699232Sandreas.hansson@arm.com def createCCObject(self): 7709232Sandreas.hansson@arm.com self.getCCParams() 7713101Sstever@eecs.umich.edu self.getCCObject() # force creation 7723101Sstever@eecs.umich.edu for child in self._children.itervalues(): 7733101Sstever@eecs.umich.edu child.createCCObject() 7743101Sstever@eecs.umich.edu 7759232Sandreas.hansson@arm.com def getValue(self): 7763101Sstever@eecs.umich.edu return self.getCCObject() 7773101Sstever@eecs.umich.edu 7789232Sandreas.hansson@arm.com # Create C++ port connections corresponding to the connections in 7799232Sandreas.hansson@arm.com # _port_refs (& recursively for all children) 7809232Sandreas.hansson@arm.com def connectPorts(self): 7819411Sandreas.hansson@arm.com for portRef in self._port_refs.itervalues(): 7829411Sandreas.hansson@arm.com portRef.ccConnect() 7833101Sstever@eecs.umich.edu for child in self._children.itervalues(): 7847673Snate@binkert.org child.connectPorts() 7857673Snate@binkert.org 7869232Sandreas.hansson@arm.com def startDrain(self, drain_event, recursive): 7879235Sandreas.hansson@arm.com count = 0 7887675Snate@binkert.org if isinstance(self, SimObject): 7897675Snate@binkert.org count += self._ccObject.drain(drain_event) 7907675Snate@binkert.org if recursive: 7919232Sandreas.hansson@arm.com for child in self._children.itervalues(): 7927673Snate@binkert.org count += child.startDrain(drain_event, True) 79310458Sandreas.hansson@arm.com return count 79410458Sandreas.hansson@arm.com 79510458Sandreas.hansson@arm.com def resume(self): 79610458Sandreas.hansson@arm.com if isinstance(self, SimObject): 79710458Sandreas.hansson@arm.com self._ccObject.resume() 79810458Sandreas.hansson@arm.com for child in self._children.itervalues(): 79910458Sandreas.hansson@arm.com child.resume() 80010458Sandreas.hansson@arm.com 80110458Sandreas.hansson@arm.com def getMemoryMode(self): 80210458Sandreas.hansson@arm.com if not isinstance(self, m5.objects.System): 80310458Sandreas.hansson@arm.com return None 80410458Sandreas.hansson@arm.com 80510458Sandreas.hansson@arm.com return self._ccObject.getMemoryMode() 80610458Sandreas.hansson@arm.com 80710458Sandreas.hansson@arm.com def changeTiming(self, mode): 80810458Sandreas.hansson@arm.com if isinstance(self, m5.objects.System): 80910458Sandreas.hansson@arm.com # i don't know if there's a better way to do this - calling 81010458Sandreas.hansson@arm.com # setMemoryMode directly from self._ccObject results in calling 8114762Snate@binkert.org # SimObject::setMemoryMode, not the System::setMemoryMode 8129235Sandreas.hansson@arm.com self._ccObject.setMemoryMode(mode) 8139235Sandreas.hansson@arm.com for child in self._children.itervalues(): 8147675Snate@binkert.org child.changeTiming(mode) 8154762Snate@binkert.org 8169411Sandreas.hansson@arm.com def takeOverFrom(self, old_cpu): 8179411Sandreas.hansson@arm.com self._ccObject.takeOverFrom(old_cpu._ccObject) 8189411Sandreas.hansson@arm.com 8193101Sstever@eecs.umich.edu # generate output file for 'dot' to display as a pretty graph. 8203101Sstever@eecs.umich.edu # this code is currently broken. 8213101Sstever@eecs.umich.edu def outputDot(self, dot): 8223101Sstever@eecs.umich.edu label = "{%s|" % self.path 8233101Sstever@eecs.umich.edu if isSimObject(self.realtype): 8243101Sstever@eecs.umich.edu label += '%s|' % self.type 82510267SGeoffrey.Blake@arm.com 82610267SGeoffrey.Blake@arm.com if self.children: 8273101Sstever@eecs.umich.edu # instantiate children in same order they were added for 8283101Sstever@eecs.umich.edu # backward compatibility (else we can end up with cpu1 8293102Sstever@eecs.umich.edu # before cpu0). 8303101Sstever@eecs.umich.edu for c in self.children: 8313101Sstever@eecs.umich.edu dot.add_edge(pydot.Edge(self.path,c.path, style="bold")) 8323101Sstever@eecs.umich.edu 83310267SGeoffrey.Blake@arm.com simobjs = [] 83410267SGeoffrey.Blake@arm.com for param in self.params: 83510267SGeoffrey.Blake@arm.com try: 83610267SGeoffrey.Blake@arm.com if param.value is None: 8374762Snate@binkert.org raise AttributeError, 'Parameter with no value' 8384762Snate@binkert.org 8394762Snate@binkert.org value = param.value 8403101Sstever@eecs.umich.edu string = param.string(value) 8413101Sstever@eecs.umich.edu except Exception, e: 8423101Sstever@eecs.umich.edu msg = 'exception in %s:%s\n%s' % (self.name, param.name, e) 8438934SBrad.Beckmann@amd.com e.args = (msg, ) 8448934SBrad.Beckmann@amd.com raise 8458934SBrad.Beckmann@amd.com 8468934SBrad.Beckmann@amd.com if isSimObject(param.ptype) and string != "Null": 8478934SBrad.Beckmann@amd.com simobjs.append(string) 8483101Sstever@eecs.umich.edu else: 8493101Sstever@eecs.umich.edu label += '%s = %s\\n' % (param.name, string) 8503101Sstever@eecs.umich.edu 8513101Sstever@eecs.umich.edu for so in simobjs: 8523101Sstever@eecs.umich.edu label += "|<%s> %s" % (so, so) 85310380SAndrew.Bardsley@arm.com dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, 85410380SAndrew.Bardsley@arm.com tailport="w")) 85510380SAndrew.Bardsley@arm.com label += '}' 85610458Sandreas.hansson@arm.com dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) 85710458Sandreas.hansson@arm.com 85810458Sandreas.hansson@arm.com # recursively dump out children 85910458Sandreas.hansson@arm.com for c in self.children: 86010458Sandreas.hansson@arm.com c.outputDot(dot) 86110458Sandreas.hansson@arm.com 86210458Sandreas.hansson@arm.com# Function to provide to C++ so it can look up instances based on paths 86310458Sandreas.hansson@arm.comdef resolveSimObject(name): 86410458Sandreas.hansson@arm.com obj = instanceDict[name] 86510458Sandreas.hansson@arm.com return obj.getCCObject() 8663101Sstever@eecs.umich.edu 8673101Sstever@eecs.umich.edudef isSimObject(value): 8683101Sstever@eecs.umich.edu return isinstance(value, SimObject) 8693101Sstever@eecs.umich.edu 8703101Sstever@eecs.umich.edudef isSimObjectClass(value): 8713101Sstever@eecs.umich.edu return issubclass(value, SimObject) 8723101Sstever@eecs.umich.edu 8733101Sstever@eecs.umich.edudef isSimObjectSequence(value): 8743101Sstever@eecs.umich.edu if not isinstance(value, (list, tuple)) or len(value) == 0: 8753101Sstever@eecs.umich.edu return False 8763101Sstever@eecs.umich.edu 8773101Sstever@eecs.umich.edu for val in value: 8784380Sbinkertn@umich.edu if not isNullPointer(val) and not isSimObject(val): 8794380Sbinkertn@umich.edu return False 8804380Sbinkertn@umich.edu 8813101Sstever@eecs.umich.edu return True 8824380Sbinkertn@umich.edu 8834380Sbinkertn@umich.edudef isSimObjectOrSequence(value): 8844380Sbinkertn@umich.edu return isSimObject(value) or isSimObjectSequence(value) 8853101Sstever@eecs.umich.edu 8863101Sstever@eecs.umich.edubaseClasses = allClasses.copy() 8873101Sstever@eecs.umich.edubaseInstances = instanceDict.copy() 88810267SGeoffrey.Blake@arm.com 88910267SGeoffrey.Blake@arm.comdef clear(): 8907673Snate@binkert.org global allClasses, instanceDict 8917673Snate@binkert.org 8927673Snate@binkert.org allClasses = baseClasses.copy() 8937673Snate@binkert.org instanceDict = baseInstances.copy() 8947673Snate@binkert.org 8957673Snate@binkert.org# __all__ defines the list of symbols that get exported when 8967673Snate@binkert.org# 'from config import *' is invoked. Try to keep this reasonably 8977673Snate@binkert.org# short to avoid polluting other namespaces. 8987673Snate@binkert.org__all__ = [ 'SimObject' ] 8993101Sstever@eecs.umich.edu