SimObject.py revision 8927:bc3a389d1e37
13101Sstever@eecs.umich.edu# Copyright (c) 2012 ARM Limited 27534Ssteve.reinhardt@amd.com# All rights reserved. 33101Sstever@eecs.umich.edu# 43101Sstever@eecs.umich.edu# The license below extends only to copyright in the software and shall 53101Sstever@eecs.umich.edu# not be construed as granting a license to any other intellectual 63101Sstever@eecs.umich.edu# property including but not limited to intellectual property relating 73101Sstever@eecs.umich.edu# to a hardware implementation of the functionality of the software 83101Sstever@eecs.umich.edu# licensed hereunder. You may use the software subject to the license 93101Sstever@eecs.umich.edu# terms below provided that you ensure that this notice is replicated 103101Sstever@eecs.umich.edu# unmodified and in its entirety in all distributions of the software, 113101Sstever@eecs.umich.edu# modified or unmodified, in source code or in binary form. 123101Sstever@eecs.umich.edu# 133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan 143101Sstever@eecs.umich.edu# Copyright (c) 2010 Advanced Micro Devices, Inc. 153101Sstever@eecs.umich.edu# All rights reserved. 163101Sstever@eecs.umich.edu# 173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without 183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are 193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright 203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer; 213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright 223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the 233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution; 243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its 253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from 263101Sstever@eecs.umich.edu# this software without specific prior written permission. 273101Sstever@eecs.umich.edu# 283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 393101Sstever@eecs.umich.edu# 403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 413101Sstever@eecs.umich.edu# Nathan Binkert 423101Sstever@eecs.umich.edu# Andreas Hansson 433101Sstever@eecs.umich.edu 443101Sstever@eecs.umich.eduimport sys 453101Sstever@eecs.umich.edufrom types import FunctionType, MethodType, ModuleType 463101Sstever@eecs.umich.edu 473101Sstever@eecs.umich.edutry: 483885Sbinkertn@umich.edu import pydot 493885Sbinkertn@umich.eduexcept: 504762Snate@binkert.org pydot = False 513885Sbinkertn@umich.edu 523885Sbinkertn@umich.eduimport m5 537528Ssteve.reinhardt@amd.comfrom m5.util import * 543885Sbinkertn@umich.edu 554380Sbinkertn@umich.edu# Have to import params up top since Param is referenced on initial 564167Sbinkertn@umich.edu# load (when SimObject class references Param to create a class 573102Sstever@eecs.umich.edu# variable, the 'name' param)... 583101Sstever@eecs.umich.edufrom m5.params import * 594762Snate@binkert.org# There are a few things we need that aren't in params.__all__ since 604762Snate@binkert.org# normal users don't need them 614762Snate@binkert.orgfrom m5.params import ParamDesc, VectorParamDesc, \ 624762Snate@binkert.org isNullPointer, SimObjectVector, Port 634762Snate@binkert.org 644762Snate@binkert.orgfrom m5.proxy import * 654762Snate@binkert.orgfrom m5.proxy import isproxy 664762Snate@binkert.org 674762Snate@binkert.org##################################################################### 685033Smilesck@eecs.umich.edu# 695033Smilesck@eecs.umich.edu# M5 Python Configuration Utility 705033Smilesck@eecs.umich.edu# 715033Smilesck@eecs.umich.edu# The basic idea is to write simple Python programs that build Python 725033Smilesck@eecs.umich.edu# objects corresponding to M5 SimObjects for the desired simulation 735033Smilesck@eecs.umich.edu# configuration. For now, the Python emits a .ini file that can be 745033Smilesck@eecs.umich.edu# parsed by M5. In the future, some tighter integration between M5 755033Smilesck@eecs.umich.edu# and the Python interpreter may allow bypassing the .ini file. 765033Smilesck@eecs.umich.edu# 775033Smilesck@eecs.umich.edu# Each SimObject class in M5 is represented by a Python class with the 783101Sstever@eecs.umich.edu# same name. The Python inheritance tree mirrors the M5 C++ tree 793101Sstever@eecs.umich.edu# (e.g., SimpleCPU derives from BaseCPU in both cases, and all 803101Sstever@eecs.umich.edu# SimObjects inherit from a single SimObject base class). To specify 815033Smilesck@eecs.umich.edu# an instance of an M5 SimObject in a configuration, the user simply 823101Sstever@eecs.umich.edu# instantiates the corresponding Python object. The parameters for 837673Snate@binkert.org# that SimObject are given by assigning to attributes of the Python 847673Snate@binkert.org# object, either using keyword assignment in the constructor or in 857673Snate@binkert.org# separate assignment statements. For example: 867673Snate@binkert.org# 877673Snate@binkert.org# cache = BaseCache(size='64KB') 887673Snate@binkert.org# cache.hit_latency = 3 897673Snate@binkert.org# cache.assoc = 8 903101Sstever@eecs.umich.edu# 913101Sstever@eecs.umich.edu# The magic lies in the mapping of the Python attributes for SimObject 923101Sstever@eecs.umich.edu# classes to the actual SimObject parameter specifications. This 933101Sstever@eecs.umich.edu# allows parameter validity checking in the Python code. Continuing 943101Sstever@eecs.umich.edu# the example above, the statements "cache.blurfl=3" or 953101Sstever@eecs.umich.edu# "cache.assoc='hello'" would both result in runtime errors in Python, 963101Sstever@eecs.umich.edu# since the BaseCache object has no 'blurfl' parameter and the 'assoc' 973101Sstever@eecs.umich.edu# parameter requires an integer, respectively. This magic is done 983101Sstever@eecs.umich.edu# primarily by overriding the special __setattr__ method that controls 993101Sstever@eecs.umich.edu# assignment to object attributes. 1003101Sstever@eecs.umich.edu# 1013101Sstever@eecs.umich.edu# Once a set of Python objects have been instantiated in a hierarchy, 1023101Sstever@eecs.umich.edu# calling 'instantiate(obj)' (where obj is the root of the hierarchy) 1036656Snate@binkert.org# will generate a .ini file. 1046656Snate@binkert.org# 1053101Sstever@eecs.umich.edu##################################################################### 1063101Sstever@eecs.umich.edu 1073101Sstever@eecs.umich.edu# list of all SimObject classes 1083101Sstever@eecs.umich.eduallClasses = {} 1093101Sstever@eecs.umich.edu 1103101Sstever@eecs.umich.edu# dict to look up SimObjects based on path 1113101Sstever@eecs.umich.eduinstanceDict = {} 1123101Sstever@eecs.umich.edu 1133101Sstever@eecs.umich.edudef public_value(key, value): 1143101Sstever@eecs.umich.edu return key.startswith('_') or \ 1153101Sstever@eecs.umich.edu isinstance(value, (FunctionType, MethodType, ModuleType, 1163101Sstever@eecs.umich.edu classmethod, type)) 1173101Sstever@eecs.umich.edu 1183101Sstever@eecs.umich.edu# The metaclass for SimObject. This class controls how new classes 1193101Sstever@eecs.umich.edu# that derive from SimObject are instantiated, and provides inherited 1203101Sstever@eecs.umich.edu# class behavior (just like a class controls how instances of that 1213101Sstever@eecs.umich.edu# class are instantiated, and provides inherited instance behavior). 1223101Sstever@eecs.umich.educlass MetaSimObject(type): 1233101Sstever@eecs.umich.edu # Attributes that can be set only at initialization time 1243101Sstever@eecs.umich.edu init_keywords = { 'abstract' : bool, 1253101Sstever@eecs.umich.edu 'cxx_class' : str, 1263101Sstever@eecs.umich.edu 'cxx_type' : str, 1273101Sstever@eecs.umich.edu 'type' : str } 1283101Sstever@eecs.umich.edu # Attributes that can be set any time 1293101Sstever@eecs.umich.edu keywords = { 'check' : FunctionType } 1303101Sstever@eecs.umich.edu 1313101Sstever@eecs.umich.edu # __new__ is called before __init__, and is where the statements 1323101Sstever@eecs.umich.edu # in the body of the class definition get loaded into the class's 1333101Sstever@eecs.umich.edu # __dict__. We intercept this to filter out parameter & port assignments 1343101Sstever@eecs.umich.edu # and only allow "private" attributes to be passed to the base 1353101Sstever@eecs.umich.edu # __new__ (starting with underscore). 1363101Sstever@eecs.umich.edu def __new__(mcls, name, bases, dict): 1373101Sstever@eecs.umich.edu assert name not in allClasses, "SimObject %s already present" % name 1385033Smilesck@eecs.umich.edu 1396656Snate@binkert.org # Copy "private" attributes, functions, and classes to the 1405033Smilesck@eecs.umich.edu # official dict. Everything else goes in _init_dict to be 1415033Smilesck@eecs.umich.edu # filtered in __init__. 1425033Smilesck@eecs.umich.edu cls_dict = {} 1433101Sstever@eecs.umich.edu value_dict = {} 1443101Sstever@eecs.umich.edu for key,val in dict.items(): 1453101Sstever@eecs.umich.edu if public_value(key, val): 1463101Sstever@eecs.umich.edu cls_dict[key] = val 1473101Sstever@eecs.umich.edu else: 1483101Sstever@eecs.umich.edu # must be a param/port setting 1493101Sstever@eecs.umich.edu value_dict[key] = val 1503101Sstever@eecs.umich.edu if 'abstract' not in value_dict: 1513101Sstever@eecs.umich.edu value_dict['abstract'] = False 1523101Sstever@eecs.umich.edu cls_dict['_value_dict'] = value_dict 1533101Sstever@eecs.umich.edu cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 1543101Sstever@eecs.umich.edu if 'type' in value_dict: 1553101Sstever@eecs.umich.edu allClasses[name] = cls 1563102Sstever@eecs.umich.edu return cls 1573101Sstever@eecs.umich.edu 1583101Sstever@eecs.umich.edu # subclass initialization 1593101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 1607673Snate@binkert.org # calls type.__init__()... I think that's a no-op, but leave 1617673Snate@binkert.org # it here just in case it's not. 1623101Sstever@eecs.umich.edu super(MetaSimObject, cls).__init__(name, bases, dict) 1637673Snate@binkert.org 1647673Snate@binkert.org # initialize required attributes 1653101Sstever@eecs.umich.edu 1667673Snate@binkert.org # class-only attributes 1677673Snate@binkert.org cls._params = multidict() # param descriptions 1683101Sstever@eecs.umich.edu cls._ports = multidict() # port descriptions 1693101Sstever@eecs.umich.edu 1703101Sstever@eecs.umich.edu # class or instance attributes 1713101Sstever@eecs.umich.edu cls._values = multidict() # param values 1723101Sstever@eecs.umich.edu cls._children = multidict() # SimObject children 1733101Sstever@eecs.umich.edu cls._port_refs = multidict() # port ref objects 1745033Smilesck@eecs.umich.edu cls._instantiated = False # really instantiated, cloned, or subclassed 1755475Snate@binkert.org 1765475Snate@binkert.org # We don't support multiple inheritance. If you want to, you 1775475Snate@binkert.org # must fix multidict to deal with it properly. 1785475Snate@binkert.org if len(bases) > 1: 1793101Sstever@eecs.umich.edu raise TypeError, "SimObjects do not support multiple inheritance" 1803101Sstever@eecs.umich.edu 1813101Sstever@eecs.umich.edu base = bases[0] 1824762Snate@binkert.org 1834762Snate@binkert.org # Set up general inheritance via multidicts. A subclass will 1844762Snate@binkert.org # inherit all its settings from the base class. The only time 1853101Sstever@eecs.umich.edu # the following is not true is when we define the SimObject 1863101Sstever@eecs.umich.edu # class itself (in which case the multidicts have no parent). 1873101Sstever@eecs.umich.edu if isinstance(base, MetaSimObject): 1887528Ssteve.reinhardt@amd.com cls._base = base 1897528Ssteve.reinhardt@amd.com cls._params.parent = base._params 1907528Ssteve.reinhardt@amd.com cls._ports.parent = base._ports 1917528Ssteve.reinhardt@amd.com cls._values.parent = base._values 1927528Ssteve.reinhardt@amd.com cls._children.parent = base._children 1937528Ssteve.reinhardt@amd.com cls._port_refs.parent = base._port_refs 1943101Sstever@eecs.umich.edu # mark base as having been subclassed 1957528Ssteve.reinhardt@amd.com base._instantiated = True 1967528Ssteve.reinhardt@amd.com else: 1977528Ssteve.reinhardt@amd.com cls._base = None 1987528Ssteve.reinhardt@amd.com 1997528Ssteve.reinhardt@amd.com # default keyword values 2007528Ssteve.reinhardt@amd.com if 'type' in cls._value_dict: 2017528Ssteve.reinhardt@amd.com if 'cxx_class' not in cls._value_dict: 2027528Ssteve.reinhardt@amd.com cls._value_dict['cxx_class'] = cls._value_dict['type'] 2037528Ssteve.reinhardt@amd.com 2047528Ssteve.reinhardt@amd.com cls._value_dict['cxx_type'] = '%s *' % cls._value_dict['cxx_class'] 2057528Ssteve.reinhardt@amd.com 2067528Ssteve.reinhardt@amd.com # Export methods are automatically inherited via C++, so we 2077528Ssteve.reinhardt@amd.com # don't want the method declarations to get inherited on the 2087528Ssteve.reinhardt@amd.com # python side (and thus end up getting repeated in the wrapped 2097528Ssteve.reinhardt@amd.com # versions of derived classes). The code below basicallly 2107528Ssteve.reinhardt@amd.com # suppresses inheritance by substituting in the base (null) 2117528Ssteve.reinhardt@amd.com # versions of these methods unless a different version is 2127528Ssteve.reinhardt@amd.com # explicitly supplied. 2137528Ssteve.reinhardt@amd.com for method_name in ('export_methods', 'export_method_cxx_predecls', 2147528Ssteve.reinhardt@amd.com 'export_method_swig_predecls'): 2157528Ssteve.reinhardt@amd.com if method_name not in cls.__dict__: 2167528Ssteve.reinhardt@amd.com base_method = getattr(MetaSimObject, method_name) 2177528Ssteve.reinhardt@amd.com m = MethodType(base_method, cls, MetaSimObject) 2187528Ssteve.reinhardt@amd.com setattr(cls, method_name, m) 2197528Ssteve.reinhardt@amd.com 2207528Ssteve.reinhardt@amd.com # Now process the _value_dict items. They could be defining 2217528Ssteve.reinhardt@amd.com # new (or overriding existing) parameters or ports, setting 2227528Ssteve.reinhardt@amd.com # class keywords (e.g., 'abstract'), or setting parameter 2237528Ssteve.reinhardt@amd.com # values or port bindings. The first 3 can only be set when 2243101Sstever@eecs.umich.edu # the class is defined, so we handle them here. The others 2253101Sstever@eecs.umich.edu # can be set later too, so just emulate that by calling 2266656Snate@binkert.org # setattr(). 2276656Snate@binkert.org for key,val in cls._value_dict.items(): 2283101Sstever@eecs.umich.edu # param descriptions 2293101Sstever@eecs.umich.edu if isinstance(val, ParamDesc): 2303101Sstever@eecs.umich.edu cls._new_param(key, val) 2313101Sstever@eecs.umich.edu 2323101Sstever@eecs.umich.edu # port objects 2333101Sstever@eecs.umich.edu elif isinstance(val, Port): 2343101Sstever@eecs.umich.edu cls._new_port(key, val) 2354762Snate@binkert.org 2364762Snate@binkert.org # init-time-only keywords 2374762Snate@binkert.org elif cls.init_keywords.has_key(key): 2384762Snate@binkert.org cls._set_keyword(key, val, cls.init_keywords[key]) 2397528Ssteve.reinhardt@amd.com 2404762Snate@binkert.org # default: use normal path (ends up in __setattr__) 2414762Snate@binkert.org else: 2424762Snate@binkert.org setattr(cls, key, val) 2437673Snate@binkert.org 2447675Snate@binkert.org def _set_keyword(cls, keyword, val, kwtype): 2454762Snate@binkert.org if not isinstance(val, kwtype): 2467673Snate@binkert.org raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 2477675Snate@binkert.org (keyword, type(val), kwtype) 2487675Snate@binkert.org if isinstance(val, FunctionType): 2497675Snate@binkert.org val = classmethod(val) 2507675Snate@binkert.org type.__setattr__(cls, keyword, val) 2517675Snate@binkert.org 2527675Snate@binkert.org def _new_param(cls, name, pdesc): 2537673Snate@binkert.org # each param desc should be uniquely assigned to one variable 2547675Snate@binkert.org assert(not hasattr(pdesc, 'name')) 2557675Snate@binkert.org pdesc.name = name 2567675Snate@binkert.org cls._params[name] = pdesc 2577675Snate@binkert.org if hasattr(pdesc, 'default'): 2587675Snate@binkert.org cls._set_param(name, pdesc.default, pdesc) 2597673Snate@binkert.org 2607675Snate@binkert.org def _set_param(cls, name, value, param): 2617675Snate@binkert.org assert(param.name == name) 2627675Snate@binkert.org try: 2637675Snate@binkert.org value = param.convert(value) 2647675Snate@binkert.org except Exception, e: 2657675Snate@binkert.org msg = "%s\nError setting param %s.%s to %s\n" % \ 2667675Snate@binkert.org (e, cls.__name__, name, value) 2677675Snate@binkert.org e.args = (msg, ) 2687675Snate@binkert.org raise 2697675Snate@binkert.org cls._values[name] = value 2707675Snate@binkert.org # if param value is a SimObject, make it a child too, so that 2717675Snate@binkert.org # it gets cloned properly when the class is instantiated 2727675Snate@binkert.org if isSimObjectOrVector(value) and not value.has_parent(): 2737675Snate@binkert.org cls._add_cls_child(name, value) 2747675Snate@binkert.org 2757675Snate@binkert.org def _add_cls_child(cls, name, child): 2767673Snate@binkert.org # It's a little funky to have a class as a parent, but these 2777673Snate@binkert.org # objects should never be instantiated (only cloned, which 2783101Sstever@eecs.umich.edu # clears the parent pointer), and this makes it clear that the 2797675Snate@binkert.org # object is not an orphan and can provide better error 2807675Snate@binkert.org # messages. 2817673Snate@binkert.org child.set_parent(cls, name) 2827673Snate@binkert.org cls._children[name] = child 2837673Snate@binkert.org 2843101Sstever@eecs.umich.edu def _new_port(cls, name, port): 2857673Snate@binkert.org # each port should be uniquely assigned to one variable 2867673Snate@binkert.org assert(not hasattr(port, 'name')) 2873101Sstever@eecs.umich.edu port.name = name 2883101Sstever@eecs.umich.edu cls._ports[name] = port 2893101Sstever@eecs.umich.edu 2903101Sstever@eecs.umich.edu # same as _get_port_ref, effectively, but for classes 2913101Sstever@eecs.umich.edu def _cls_get_port_ref(cls, attr): 2923101Sstever@eecs.umich.edu # Return reference that can be assigned to another port 2933101Sstever@eecs.umich.edu # via __setattr__. There is only ever one reference 2943101Sstever@eecs.umich.edu # object per port, but we create them lazily here. 2953101Sstever@eecs.umich.edu ref = cls._port_refs.get(attr) 2963101Sstever@eecs.umich.edu if not ref: 2973101Sstever@eecs.umich.edu ref = cls._ports[attr].makeRef(cls) 2983101Sstever@eecs.umich.edu cls._port_refs[attr] = ref 2993101Sstever@eecs.umich.edu return ref 3003101Sstever@eecs.umich.edu 3013101Sstever@eecs.umich.edu # Set attribute (called on foo.attr = value when foo is an 3025033Smilesck@eecs.umich.edu # instance of class cls). 3035033Smilesck@eecs.umich.edu def __setattr__(cls, attr, value): 3043101Sstever@eecs.umich.edu # normal processing for private attributes 3053101Sstever@eecs.umich.edu if public_value(attr, value): 3063101Sstever@eecs.umich.edu type.__setattr__(cls, attr, value) 3073101Sstever@eecs.umich.edu return 3083101Sstever@eecs.umich.edu 3093101Sstever@eecs.umich.edu if cls.keywords.has_key(attr): 3103101Sstever@eecs.umich.edu cls._set_keyword(attr, value, cls.keywords[attr]) 3113101Sstever@eecs.umich.edu return 3123101Sstever@eecs.umich.edu 3133101Sstever@eecs.umich.edu if cls._ports.has_key(attr): 3143101Sstever@eecs.umich.edu cls._cls_get_port_ref(attr).connect(value) 3153101Sstever@eecs.umich.edu return 3163101Sstever@eecs.umich.edu 3173101Sstever@eecs.umich.edu if isSimObjectOrSequence(value) and cls._instantiated: 3183101Sstever@eecs.umich.edu raise RuntimeError, \ 3193101Sstever@eecs.umich.edu "cannot set SimObject parameter '%s' after\n" \ 3203101Sstever@eecs.umich.edu " class %s has been instantiated or subclassed" \ 3213101Sstever@eecs.umich.edu % (attr, cls.__name__) 3223101Sstever@eecs.umich.edu 3233101Sstever@eecs.umich.edu # check for param 3243101Sstever@eecs.umich.edu param = cls._params.get(attr) 3253101Sstever@eecs.umich.edu if param: 3263101Sstever@eecs.umich.edu cls._set_param(attr, value, param) 3273101Sstever@eecs.umich.edu return 3283101Sstever@eecs.umich.edu 3297673Snate@binkert.org if isSimObjectOrSequence(value): 3307673Snate@binkert.org # If RHS is a SimObject, it's an implicit child assignment. 3317673Snate@binkert.org cls._add_cls_child(attr, coerceSimObjectOrVector(value)) 3327673Snate@binkert.org return 3337673Snate@binkert.org 3347673Snate@binkert.org # no valid assignment... raise exception 3357673Snate@binkert.org raise AttributeError, \ 3367673Snate@binkert.org "Class %s has no parameter \'%s\'" % (cls.__name__, attr) 3374762Snate@binkert.org 3384762Snate@binkert.org def __getattr__(cls, attr): 3394762Snate@binkert.org if attr == 'cxx_class_path': 3403101Sstever@eecs.umich.edu return cls.cxx_class.split('::') 3413101Sstever@eecs.umich.edu 3423101Sstever@eecs.umich.edu if attr == 'cxx_class_name': 3433101Sstever@eecs.umich.edu return cls.cxx_class_path[-1] 3443101Sstever@eecs.umich.edu 3453101Sstever@eecs.umich.edu if attr == 'cxx_namespaces': 3463101Sstever@eecs.umich.edu return cls.cxx_class_path[:-1] 3473101Sstever@eecs.umich.edu 3483101Sstever@eecs.umich.edu if cls._values.has_key(attr): 3493101Sstever@eecs.umich.edu return cls._values[attr] 3503101Sstever@eecs.umich.edu 3513714Sstever@eecs.umich.edu if cls._children.has_key(attr): 3523714Sstever@eecs.umich.edu return cls._children[attr] 3533714Sstever@eecs.umich.edu 3543714Sstever@eecs.umich.edu raise AttributeError, \ 3553714Sstever@eecs.umich.edu "object '%s' has no attribute '%s'" % (cls.__name__, attr) 3563714Sstever@eecs.umich.edu 3573101Sstever@eecs.umich.edu def __str__(cls): 3583101Sstever@eecs.umich.edu return cls.__name__ 3593101Sstever@eecs.umich.edu 3603101Sstever@eecs.umich.edu # See ParamValue.cxx_predecls for description. 3613101Sstever@eecs.umich.edu def cxx_predecls(cls, code): 3623101Sstever@eecs.umich.edu code('#include "params/$cls.hh"') 3633101Sstever@eecs.umich.edu 3643101Sstever@eecs.umich.edu # See ParamValue.swig_predecls for description. 3653101Sstever@eecs.umich.edu def swig_predecls(cls, code): 3663101Sstever@eecs.umich.edu code('%import "python/m5/internal/param_$cls.i"') 3673101Sstever@eecs.umich.edu 3683101Sstever@eecs.umich.edu # Hook for exporting additional C++ methods to Python via SWIG. 3693101Sstever@eecs.umich.edu # Default is none, override using @classmethod in class definition. 3703101Sstever@eecs.umich.edu def export_methods(cls, code): 3713101Sstever@eecs.umich.edu pass 3723101Sstever@eecs.umich.edu 3733101Sstever@eecs.umich.edu # Generate the code needed as a prerequisite for the C++ methods 3743101Sstever@eecs.umich.edu # exported via export_methods() to be compiled in the _wrap.cc 3753101Sstever@eecs.umich.edu # file. Typically generates one or more #include statements. If 3763101Sstever@eecs.umich.edu # any methods are exported, typically at least the C++ header 3773101Sstever@eecs.umich.edu # declaring the relevant SimObject class must be included. 3783101Sstever@eecs.umich.edu def export_method_cxx_predecls(cls, code): 3793101Sstever@eecs.umich.edu pass 3803101Sstever@eecs.umich.edu 3813101Sstever@eecs.umich.edu # Generate the code needed as a prerequisite for the C++ methods 3825033Smilesck@eecs.umich.edu # exported via export_methods() to be processed by SWIG. 3833101Sstever@eecs.umich.edu # Typically generates one or more %include or %import statements. 3843101Sstever@eecs.umich.edu # If any methods are exported, typically at least the C++ header 3853101Sstever@eecs.umich.edu # declaring the relevant SimObject class must be included. 3863101Sstever@eecs.umich.edu def export_method_swig_predecls(cls, code): 3873101Sstever@eecs.umich.edu pass 3883101Sstever@eecs.umich.edu 3893101Sstever@eecs.umich.edu # Generate the declaration for this object for wrapping with SWIG. 3903101Sstever@eecs.umich.edu # Generates code that goes into a SWIG .i file. Called from 3913101Sstever@eecs.umich.edu # src/SConscript. 3923101Sstever@eecs.umich.edu def swig_decl(cls, code): 3933101Sstever@eecs.umich.edu class_path = cls.cxx_class.split('::') 3943101Sstever@eecs.umich.edu classname = class_path[-1] 3955822Ssaidi@eecs.umich.edu namespaces = class_path[:-1] 3965822Ssaidi@eecs.umich.edu 3973101Sstever@eecs.umich.edu # The 'local' attribute restricts us to the params declared in 3983101Sstever@eecs.umich.edu # the object itself, not including inherited params (which 3993101Sstever@eecs.umich.edu # will also be inherited from the base class's param struct 4003101Sstever@eecs.umich.edu # here). 4013101Sstever@eecs.umich.edu params = cls._params.local.values() 4023101Sstever@eecs.umich.edu ports = cls._ports.local 4033101Sstever@eecs.umich.edu 4043101Sstever@eecs.umich.edu code('%module(package="m5.internal") param_$cls') 4053101Sstever@eecs.umich.edu code() 4063101Sstever@eecs.umich.edu code('%{') 4073101Sstever@eecs.umich.edu code('#include "params/$cls.hh"') 4083101Sstever@eecs.umich.edu for param in params: 4093101Sstever@eecs.umich.edu param.cxx_predecls(code) 4103101Sstever@eecs.umich.edu cls.export_method_cxx_predecls(code) 4113101Sstever@eecs.umich.edu code('''\ 4123101Sstever@eecs.umich.edu/** 4133101Sstever@eecs.umich.edu * This is a workaround for bug in swig. Prior to gcc 4.6.1 the STL 4143101Sstever@eecs.umich.edu * headers like vector, string, etc. used to automatically pull in 4153101Sstever@eecs.umich.edu * the cstddef header but starting with gcc 4.6.1 they no longer do. 4163101Sstever@eecs.umich.edu * This leads to swig generated a file that does not compile so we 4173101Sstever@eecs.umich.edu * explicitly include cstddef. Additionally, including version 2.0.4, 4183102Sstever@eecs.umich.edu * swig uses ptrdiff_t without the std:: namespace prefix which is 4193714Sstever@eecs.umich.edu * required with gcc 4.6.1. We explicitly provide access to it. 4203101Sstever@eecs.umich.edu */ 4213714Sstever@eecs.umich.edu#include <cstddef> 4223714Sstever@eecs.umich.eduusing std::ptrdiff_t; 4233714Sstever@eecs.umich.edu''') 4243101Sstever@eecs.umich.edu code('%}') 4253101Sstever@eecs.umich.edu code() 4267673Snate@binkert.org 4277673Snate@binkert.org for param in params: 4287673Snate@binkert.org param.swig_predecls(code) 4297673Snate@binkert.org cls.export_method_swig_predecls(code) 4307673Snate@binkert.org 4317673Snate@binkert.org code() 4327673Snate@binkert.org if cls._base: 4337673Snate@binkert.org code('%import "python/m5/internal/param_${{cls._base}}.i"') 4347673Snate@binkert.org code() 4357673Snate@binkert.org 4367673Snate@binkert.org for ns in namespaces: 4374762Snate@binkert.org code('namespace $ns {') 4384762Snate@binkert.org 4394762Snate@binkert.org if namespaces: 4403101Sstever@eecs.umich.edu code('// avoid name conflicts') 4413101Sstever@eecs.umich.edu sep_string = '_COLONS_' 4423101Sstever@eecs.umich.edu flat_name = sep_string.join(class_path) 4433101Sstever@eecs.umich.edu code('%rename($flat_name) $classname;') 4443101Sstever@eecs.umich.edu 4453101Sstever@eecs.umich.edu code() 4463101Sstever@eecs.umich.edu code('// stop swig from creating/wrapping default ctor/dtor') 4473101Sstever@eecs.umich.edu code('%nodefault $classname;') 4483101Sstever@eecs.umich.edu code('class $classname') 4493101Sstever@eecs.umich.edu if cls._base: 4503101Sstever@eecs.umich.edu code(' : public ${{cls._base.cxx_class}}') 4513101Sstever@eecs.umich.edu code('{') 4523101Sstever@eecs.umich.edu code(' public:') 4533101Sstever@eecs.umich.edu cls.export_methods(code) 4543101Sstever@eecs.umich.edu code('};') 4553101Sstever@eecs.umich.edu 4563101Sstever@eecs.umich.edu for ns in reversed(namespaces): 4573101Sstever@eecs.umich.edu code('} // namespace $ns') 4583101Sstever@eecs.umich.edu 4593101Sstever@eecs.umich.edu code() 4604446Sbinkertn@umich.edu code('%include "params/$cls.hh"') 4613101Sstever@eecs.umich.edu 4625468Snate@binkert.org 4635468Snate@binkert.org # Generate the C++ declaration (.hh file) for this SimObject's 4645468Snate@binkert.org # param struct. Called from src/SConscript. 4655468Snate@binkert.org def cxx_param_decl(cls, code): 4665468Snate@binkert.org # The 'local' attribute restricts us to the params declared in 4675468Snate@binkert.org # the object itself, not including inherited params (which 4685468Snate@binkert.org # will also be inherited from the base class's param struct 4694762Snate@binkert.org # here). 4704762Snate@binkert.org params = cls._params.local.values() 4714762Snate@binkert.org ports = cls._ports.local 4723101Sstever@eecs.umich.edu try: 4733101Sstever@eecs.umich.edu ptypes = [p.ptype for p in params] 4743101Sstever@eecs.umich.edu except: 4753101Sstever@eecs.umich.edu print cls, p, p.ptype_str 4763101Sstever@eecs.umich.edu print params 4773101Sstever@eecs.umich.edu raise 4783101Sstever@eecs.umich.edu 4793101Sstever@eecs.umich.edu class_path = cls._value_dict['cxx_class'].split('::') 4803102Sstever@eecs.umich.edu 4813101Sstever@eecs.umich.edu code('''\ 4823101Sstever@eecs.umich.edu#ifndef __PARAMS__${cls}__ 4833101Sstever@eecs.umich.edu#define __PARAMS__${cls}__ 4844168Sbinkertn@umich.edu 4853101Sstever@eecs.umich.edu''') 4863101Sstever@eecs.umich.edu 4873101Sstever@eecs.umich.edu # A forward class declaration is sufficient since we are just 4883101Sstever@eecs.umich.edu # declaring a pointer. 4893101Sstever@eecs.umich.edu for ns in class_path[:-1]: 4903101Sstever@eecs.umich.edu code('namespace $ns {') 4913102Sstever@eecs.umich.edu code('class $0;', class_path[-1]) 4923101Sstever@eecs.umich.edu for ns in reversed(class_path[:-1]): 4933101Sstever@eecs.umich.edu code('} // namespace $ns') 4943101Sstever@eecs.umich.edu code() 4953101Sstever@eecs.umich.edu 4963101Sstever@eecs.umich.edu # The base SimObject has a couple of params that get 4973101Sstever@eecs.umich.edu # automatically set from Python without being declared through 4983101Sstever@eecs.umich.edu # the normal Param mechanism; we slip them in here (needed 4993101Sstever@eecs.umich.edu # predecls now, actual declarations below) 5003101Sstever@eecs.umich.edu if cls == SimObject: 5013101Sstever@eecs.umich.edu code(''' 5023101Sstever@eecs.umich.edu#ifndef PY_VERSION 5033102Sstever@eecs.umich.edustruct PyObject; 5043101Sstever@eecs.umich.edu#endif 5053101Sstever@eecs.umich.edu 5063101Sstever@eecs.umich.edu#include <string> 5073584Ssaidi@eecs.umich.edu 5083584Ssaidi@eecs.umich.educlass EventQueue; 5093584Ssaidi@eecs.umich.edu''') 5103584Ssaidi@eecs.umich.edu for param in params: 5113584Ssaidi@eecs.umich.edu param.cxx_predecls(code) 5123101Sstever@eecs.umich.edu for port in ports.itervalues(): 5133101Sstever@eecs.umich.edu port.cxx_predecls(code) 5145033Smilesck@eecs.umich.edu code() 5153101Sstever@eecs.umich.edu 5163101Sstever@eecs.umich.edu if cls._base: 5173101Sstever@eecs.umich.edu code('#include "params/${{cls._base.type}}.hh"') 5183101Sstever@eecs.umich.edu code() 5193101Sstever@eecs.umich.edu 5203101Sstever@eecs.umich.edu for ptype in ptypes: 5213101Sstever@eecs.umich.edu if issubclass(ptype, Enum): 5223101Sstever@eecs.umich.edu code('#include "enums/${{ptype.__name__}}.hh"') 5233101Sstever@eecs.umich.edu code() 5243101Sstever@eecs.umich.edu 5253101Sstever@eecs.umich.edu # now generate the actual param struct 5263101Sstever@eecs.umich.edu code("struct ${cls}Params") 5273101Sstever@eecs.umich.edu if cls._base: 5283101Sstever@eecs.umich.edu code(" : public ${{cls._base.type}}Params") 5293101Sstever@eecs.umich.edu code("{") 5303101Sstever@eecs.umich.edu if not hasattr(cls, 'abstract') or not cls.abstract: 5313101Sstever@eecs.umich.edu if 'type' in cls.__dict__: 5323101Sstever@eecs.umich.edu code(" ${{cls.cxx_type}} create();") 5333101Sstever@eecs.umich.edu 5343101Sstever@eecs.umich.edu code.indent() 5353101Sstever@eecs.umich.edu if cls == SimObject: 5363101Sstever@eecs.umich.edu code(''' 5373101Sstever@eecs.umich.edu SimObjectParams() 5383101Sstever@eecs.umich.edu { 5393101Sstever@eecs.umich.edu extern EventQueue mainEventQueue; 5403101Sstever@eecs.umich.edu eventq = &mainEventQueue; 5413101Sstever@eecs.umich.edu } 5423101Sstever@eecs.umich.edu virtual ~SimObjectParams() {} 5433101Sstever@eecs.umich.edu 5445219Ssaidi@eecs.umich.edu std::string name; 5455219Ssaidi@eecs.umich.edu PyObject *pyobj; 5465219Ssaidi@eecs.umich.edu EventQueue *eventq; 5473101Sstever@eecs.umich.edu ''') 5483101Sstever@eecs.umich.edu for param in params: 5493101Sstever@eecs.umich.edu param.cxx_decl(code) 5503101Sstever@eecs.umich.edu for port in ports.itervalues(): 5513101Sstever@eecs.umich.edu port.cxx_decl(code) 5523101Sstever@eecs.umich.edu 5533101Sstever@eecs.umich.edu code.dedent() 5543101Sstever@eecs.umich.edu code('};') 5553101Sstever@eecs.umich.edu 5563101Sstever@eecs.umich.edu code() 5573101Sstever@eecs.umich.edu code('#endif // __PARAMS__${cls}__') 5583101Sstever@eecs.umich.edu return code 5593101Sstever@eecs.umich.edu 5603101Sstever@eecs.umich.edu 5613101Sstever@eecs.umich.edu 5623101Sstever@eecs.umich.edu# The SimObject class is the root of the special hierarchy. Most of 5637673Snate@binkert.org# the code in this class deals with the configuration hierarchy itself 5647673Snate@binkert.org# (parent/child node relationships). 5657675Snate@binkert.orgclass SimObject(object): 5667673Snate@binkert.org # Specify metaclass. Any class inheriting from SimObject will 5677675Snate@binkert.org # get this metaclass. 5687675Snate@binkert.org __metaclass__ = MetaSimObject 5697675Snate@binkert.org type = 'SimObject' 5707675Snate@binkert.org abstract = True 5717675Snate@binkert.org 5727673Snate@binkert.org @classmethod 5733101Sstever@eecs.umich.edu def export_method_cxx_predecls(cls, code): 5743101Sstever@eecs.umich.edu code(''' 5757673Snate@binkert.org#include <Python.h> 5764762Snate@binkert.org 5777675Snate@binkert.org#include "sim/serialize.hh" 5784762Snate@binkert.org#include "sim/sim_object.hh" 5794762Snate@binkert.org''') 5804762Snate@binkert.org 5814762Snate@binkert.org @classmethod 5824762Snate@binkert.org def export_method_swig_predecls(cls, code): 5833101Sstever@eecs.umich.edu code(''' 5843101Sstever@eecs.umich.edu%include <std_string.i> 5853101Sstever@eecs.umich.edu''') 5867673Snate@binkert.org 5874762Snate@binkert.org @classmethod 5887675Snate@binkert.org def export_methods(cls, code): 5894762Snate@binkert.org code(''' 5904762Snate@binkert.org enum State { 5914762Snate@binkert.org Running, 5924762Snate@binkert.org Draining, 5934762Snate@binkert.org Drained 5943101Sstever@eecs.umich.edu }; 5953101Sstever@eecs.umich.edu 5963101Sstever@eecs.umich.edu void init(); 5973101Sstever@eecs.umich.edu void loadState(Checkpoint *cp); 5983101Sstever@eecs.umich.edu void initState(); 5993101Sstever@eecs.umich.edu void regStats(); 6003101Sstever@eecs.umich.edu void regFormulas(); 6013101Sstever@eecs.umich.edu void resetStats(); 6023102Sstever@eecs.umich.edu void startup(); 6033101Sstever@eecs.umich.edu 6043101Sstever@eecs.umich.edu unsigned int drain(Event *drain_event); 6053101Sstever@eecs.umich.edu void resume(); 6064762Snate@binkert.org void switchOut(); 6074762Snate@binkert.org void takeOverFrom(BaseCPU *cpu); 6084762Snate@binkert.org''') 6093101Sstever@eecs.umich.edu 6103101Sstever@eecs.umich.edu # Initialize new instance. For objects with SimObject-valued 6113101Sstever@eecs.umich.edu # children, we need to recursively clone the classes represented 6123101Sstever@eecs.umich.edu # by those param values as well in a consistent "deep copy"-style 6133101Sstever@eecs.umich.edu # fashion. That is, we want to make sure that each instance is 6143101Sstever@eecs.umich.edu # cloned only once, and that if there are multiple references to 6153101Sstever@eecs.umich.edu # the same original object, we end up with the corresponding 6163101Sstever@eecs.umich.edu # cloned references all pointing to the same cloned instance. 6173101Sstever@eecs.umich.edu def __init__(self, **kwargs): 6183101Sstever@eecs.umich.edu ancestor = kwargs.get('_ancestor') 6193101Sstever@eecs.umich.edu memo_dict = kwargs.get('_memo') 6203101Sstever@eecs.umich.edu if memo_dict is None: 6213101Sstever@eecs.umich.edu # prepare to memoize any recursively instantiated objects 6223101Sstever@eecs.umich.edu memo_dict = {} 6233101Sstever@eecs.umich.edu elif ancestor: 6243101Sstever@eecs.umich.edu # memoize me now to avoid problems with recursive calls 6253101Sstever@eecs.umich.edu memo_dict[ancestor] = self 6263101Sstever@eecs.umich.edu 6273101Sstever@eecs.umich.edu if not ancestor: 6283101Sstever@eecs.umich.edu ancestor = self.__class__ 6294380Sbinkertn@umich.edu ancestor._instantiated = True 6304380Sbinkertn@umich.edu 6314380Sbinkertn@umich.edu # initialize required attributes 6323101Sstever@eecs.umich.edu self._parent = None 6334380Sbinkertn@umich.edu self._name = None 6344380Sbinkertn@umich.edu self._ccObject = None # pointer to C++ object 6354380Sbinkertn@umich.edu self._ccParams = None 6363101Sstever@eecs.umich.edu self._instantiated = False # really "cloned" 6373101Sstever@eecs.umich.edu 6383101Sstever@eecs.umich.edu # Clone children specified at class level. No need for a 6397673Snate@binkert.org # multidict here since we will be cloning everything. 6407673Snate@binkert.org # Do children before parameter values so that children that 6417673Snate@binkert.org # are also param values get cloned properly. 6427673Snate@binkert.org self._children = {} 6437673Snate@binkert.org for key,val in ancestor._children.iteritems(): 6447673Snate@binkert.org self.add_child(key, val(_memo=memo_dict)) 6457673Snate@binkert.org 6467673Snate@binkert.org # Inherit parameter values from class using multidict so 6477673Snate@binkert.org # individual value settings can be overridden but we still 6483101Sstever@eecs.umich.edu # inherit late changes to non-overridden class values. 6493101Sstever@eecs.umich.edu self._values = multidict(ancestor._values) 6503101Sstever@eecs.umich.edu # clone SimObject-valued parameters 6513101Sstever@eecs.umich.edu for key,val in ancestor._values.iteritems(): 6523101Sstever@eecs.umich.edu val = tryAsSimObjectOrVector(val) 6533101Sstever@eecs.umich.edu if val is not None: 6543101Sstever@eecs.umich.edu self._values[key] = val(_memo=memo_dict) 6553101Sstever@eecs.umich.edu 6563101Sstever@eecs.umich.edu # clone port references. no need to use a multidict here 6573101Sstever@eecs.umich.edu # since we will be creating new references for all ports. 6583101Sstever@eecs.umich.edu self._port_refs = {} 6593101Sstever@eecs.umich.edu for key,val in ancestor._port_refs.iteritems(): 6603101Sstever@eecs.umich.edu self._port_refs[key] = val.clone(self, memo_dict) 6613101Sstever@eecs.umich.edu # apply attribute assignments from keyword args, if any 6623101Sstever@eecs.umich.edu for key,val in kwargs.iteritems(): 6633101Sstever@eecs.umich.edu setattr(self, key, val) 6643101Sstever@eecs.umich.edu 6653101Sstever@eecs.umich.edu # "Clone" the current instance by creating another instance of 6663101Sstever@eecs.umich.edu # this instance's class, but that inherits its parameter values 6673101Sstever@eecs.umich.edu # and port mappings from the current instance. If we're in a 6684380Sbinkertn@umich.edu # "deep copy" recursive clone, check the _memo dict to see if 6693101Sstever@eecs.umich.edu # we've already cloned this instance. 6703101Sstever@eecs.umich.edu def __call__(self, **kwargs): 6714762Snate@binkert.org memo_dict = kwargs.get('_memo') 6724762Snate@binkert.org if memo_dict is None: 6734762Snate@binkert.org # no memo_dict: must be top-level clone operation. 6744762Snate@binkert.org # this is only allowed at the root of a hierarchy 6754380Sbinkertn@umich.edu if self._parent: 6764380Sbinkertn@umich.edu raise RuntimeError, "attempt to clone object %s " \ 6773101Sstever@eecs.umich.edu "not at the root of a tree (parent = %s)" \ 6783932Sbinkertn@umich.edu % (self, self._parent) 6793932Sbinkertn@umich.edu # create a new dict and use that. 6803932Sbinkertn@umich.edu memo_dict = {} 6813932Sbinkertn@umich.edu kwargs['_memo'] = memo_dict 6823932Sbinkertn@umich.edu elif memo_dict.has_key(self): 6833932Sbinkertn@umich.edu # clone already done & memoized 6843932Sbinkertn@umich.edu return memo_dict[self] 6853932Sbinkertn@umich.edu return self.__class__(_ancestor = self, **kwargs) 6863932Sbinkertn@umich.edu 6873932Sbinkertn@umich.edu def _get_port_ref(self, attr): 6883932Sbinkertn@umich.edu # Return reference that can be assigned to another port 6893932Sbinkertn@umich.edu # via __setattr__. There is only ever one reference 6903932Sbinkertn@umich.edu # object per port, but we create them lazily here. 6913885Sbinkertn@umich.edu ref = self._port_refs.get(attr) 6923932Sbinkertn@umich.edu if not ref: 6933932Sbinkertn@umich.edu ref = self._ports[attr].makeRef(self) 6943885Sbinkertn@umich.edu self._port_refs[attr] = ref 6953932Sbinkertn@umich.edu return ref 6963932Sbinkertn@umich.edu 6973932Sbinkertn@umich.edu def __getattr__(self, attr): 6983932Sbinkertn@umich.edu if self._ports.has_key(attr): 6993932Sbinkertn@umich.edu return self._get_port_ref(attr) 7003932Sbinkertn@umich.edu 7013932Sbinkertn@umich.edu if self._values.has_key(attr): 7023932Sbinkertn@umich.edu return self._values[attr] 7033932Sbinkertn@umich.edu 7043932Sbinkertn@umich.edu if self._children.has_key(attr): 7053932Sbinkertn@umich.edu return self._children[attr] 7063932Sbinkertn@umich.edu 7073932Sbinkertn@umich.edu # If the attribute exists on the C++ object, transparently 7083932Sbinkertn@umich.edu # forward the reference there. This is typically used for 7093932Sbinkertn@umich.edu # SWIG-wrapped methods such as init(), regStats(), 7103932Sbinkertn@umich.edu # regFormulas(), resetStats(), startup(), drain(), and 7113932Sbinkertn@umich.edu # resume(). 7123932Sbinkertn@umich.edu if self._ccObject and hasattr(self._ccObject, attr): 7133885Sbinkertn@umich.edu return getattr(self._ccObject, attr) 7143885Sbinkertn@umich.edu 7153885Sbinkertn@umich.edu raise AttributeError, "object '%s' has no attribute '%s'" \ 7163885Sbinkertn@umich.edu % (self.__class__.__name__, attr) 7174762Snate@binkert.org 7187673Snate@binkert.org # Set attribute (called on foo.attr = value when foo is an 7197673Snate@binkert.org # instance of class cls). 7207673Snate@binkert.org def __setattr__(self, attr, value): 7217673Snate@binkert.org # normal processing for private attributes 7227673Snate@binkert.org if attr.startswith('_'): 7237673Snate@binkert.org object.__setattr__(self, attr, value) 7247673Snate@binkert.org return 7257673Snate@binkert.org 7267673Snate@binkert.org if self._ports.has_key(attr): 7273885Sbinkertn@umich.edu # set up port connection 7283932Sbinkertn@umich.edu self._get_port_ref(attr).connect(value) 7293885Sbinkertn@umich.edu return 7304762Snate@binkert.org 7314762Snate@binkert.org if isSimObjectOrSequence(value) and self._instantiated: 7324762Snate@binkert.org raise RuntimeError, \ 7334762Snate@binkert.org "cannot set SimObject parameter '%s' after\n" \ 7344762Snate@binkert.org " instance been cloned %s" % (attr, `self`) 7354762Snate@binkert.org 7364762Snate@binkert.org param = self._params.get(attr) 7374762Snate@binkert.org if param: 7384762Snate@binkert.org try: 7394762Snate@binkert.org value = param.convert(value) 7404762Snate@binkert.org except Exception, e: 7414762Snate@binkert.org msg = "%s\nError setting param %s.%s to %s\n" % \ 7424762Snate@binkert.org (e, self.__class__.__name__, attr, value) 7434762Snate@binkert.org e.args = (msg, ) 7444762Snate@binkert.org raise 7454762Snate@binkert.org self._values[attr] = value 7464762Snate@binkert.org # implicitly parent unparented objects assigned as params 7474762Snate@binkert.org if isSimObjectOrVector(value) and not value.has_parent(): 7484762Snate@binkert.org self.add_child(attr, value) 7494762Snate@binkert.org return 7504762Snate@binkert.org 7514762Snate@binkert.org # if RHS is a SimObject, it's an implicit child assignment 7524762Snate@binkert.org if isSimObjectOrSequence(value): 7534762Snate@binkert.org self.add_child(attr, value) 7544762Snate@binkert.org return 7554762Snate@binkert.org 7563885Sbinkertn@umich.edu # no valid assignment... raise exception 7574762Snate@binkert.org raise AttributeError, "Class %s has no parameter %s" \ 7583885Sbinkertn@umich.edu % (self.__class__.__name__, attr) 7593885Sbinkertn@umich.edu 7603932Sbinkertn@umich.edu 7613885Sbinkertn@umich.edu # this hack allows tacking a '[0]' onto parameters that may or may 7623101Sstever@eecs.umich.edu # not be vectors, and always getting the first element (e.g. cpus) 7633101Sstever@eecs.umich.edu def __getitem__(self, key): 7643101Sstever@eecs.umich.edu if key == 0: 7653101Sstever@eecs.umich.edu return self 7663101Sstever@eecs.umich.edu raise TypeError, "Non-zero index '%s' to SimObject" % key 7673101Sstever@eecs.umich.edu 7683101Sstever@eecs.umich.edu # Also implemented by SimObjectVector 7693101Sstever@eecs.umich.edu def clear_parent(self, old_parent): 7703101Sstever@eecs.umich.edu assert self._parent is old_parent 7713101Sstever@eecs.umich.edu self._parent = None 7723101Sstever@eecs.umich.edu 7733101Sstever@eecs.umich.edu # Also implemented by SimObjectVector 7743101Sstever@eecs.umich.edu def set_parent(self, parent, name): 7753101Sstever@eecs.umich.edu self._parent = parent 7764762Snate@binkert.org self._name = name 7773101Sstever@eecs.umich.edu 7785033Smilesck@eecs.umich.edu # Also implemented by SimObjectVector 7794762Snate@binkert.org def get_name(self): 7804762Snate@binkert.org return self._name 7814762Snate@binkert.org 7824762Snate@binkert.org # Also implemented by SimObjectVector 7834762Snate@binkert.org def has_parent(self): 7844762Snate@binkert.org return self._parent is not None 7854762Snate@binkert.org 7863101Sstever@eecs.umich.edu # clear out child with given name. This code is not likely to be exercised. 7873101Sstever@eecs.umich.edu # See comment in add_child. 7883101Sstever@eecs.umich.edu def clear_child(self, name): 7893101Sstever@eecs.umich.edu child = self._children[name] 7903101Sstever@eecs.umich.edu child.clear_parent(self) 7913101Sstever@eecs.umich.edu del self._children[name] 7923101Sstever@eecs.umich.edu 7933101Sstever@eecs.umich.edu # Add a new child to this object. 7943101Sstever@eecs.umich.edu def add_child(self, name, child): 7953101Sstever@eecs.umich.edu child = coerceSimObjectOrVector(child) 7963101Sstever@eecs.umich.edu if child.has_parent(): 7973101Sstever@eecs.umich.edu print "warning: add_child('%s'): child '%s' already has parent" % \ 7983101Sstever@eecs.umich.edu (name, child.get_name()) 7993101Sstever@eecs.umich.edu if self._children.has_key(name): 8003101Sstever@eecs.umich.edu # This code path had an undiscovered bug that would make it fail 8013101Sstever@eecs.umich.edu # at runtime. It had been here for a long time and was only 8023101Sstever@eecs.umich.edu # exposed by a buggy script. Changes here will probably not be 8033101Sstever@eecs.umich.edu # exercised without specialized testing. 8043101Sstever@eecs.umich.edu self.clear_child(name) 8053101Sstever@eecs.umich.edu child.set_parent(self, name) 8064762Snate@binkert.org self._children[name] = child 8073101Sstever@eecs.umich.edu 8083101Sstever@eecs.umich.edu # Take SimObject-valued parameters that haven't been explicitly 8093101Sstever@eecs.umich.edu # assigned as children and make them children of the object that 8103101Sstever@eecs.umich.edu # they were assigned to as a parameter value. This guarantees 8113101Sstever@eecs.umich.edu # that when we instantiate all the parameter objects we're still 8123101Sstever@eecs.umich.edu # inside the configuration hierarchy. 8137673Snate@binkert.org def adoptOrphanParams(self): 8146654Snate@binkert.org for key,val in self._values.iteritems(): 8157673Snate@binkert.org if not isSimObjectVector(val) and isSimObjectSequence(val): 8167673Snate@binkert.org # need to convert raw SimObject sequences to 8177673Snate@binkert.org # SimObjectVector class so we can call has_parent() 8187673Snate@binkert.org val = SimObjectVector(val) 8197673Snate@binkert.org self._values[key] = val 8207673Snate@binkert.org if isSimObjectOrVector(val) and not val.has_parent(): 8217673Snate@binkert.org print "warning: %s adopting orphan SimObject param '%s'" \ 8227673Snate@binkert.org % (self, key) 8234762Snate@binkert.org self.add_child(key, val) 8247673Snate@binkert.org 8257673Snate@binkert.org def path(self): 8267673Snate@binkert.org if not self._parent: 8277673Snate@binkert.org return '<orphan %s>' % self.__class__ 8287673Snate@binkert.org ppath = self._parent.path() 8297673Snate@binkert.org if ppath == 'root': 8307673Snate@binkert.org return self._name 8314762Snate@binkert.org return ppath + "." + self._name 8327673Snate@binkert.org 8337673Snate@binkert.org def __str__(self): 8347673Snate@binkert.org return self.path() 8357673Snate@binkert.org 8366654Snate@binkert.org def ini_str(self): 8377673Snate@binkert.org return self.path() 8387673Snate@binkert.org 8397673Snate@binkert.org def find_any(self, ptype): 8407673Snate@binkert.org if isinstance(self, ptype): 8417673Snate@binkert.org return self, True 8427673Snate@binkert.org 8437673Snate@binkert.org found_obj = None 8444762Snate@binkert.org for child in self._children.itervalues(): 8457673Snate@binkert.org if isinstance(child, ptype): 8467673Snate@binkert.org if found_obj != None and child != found_obj: 8477673Snate@binkert.org raise AttributeError, \ 8487673Snate@binkert.org 'parent.any matched more than one: %s %s' % \ 8497673Snate@binkert.org (found_obj.path, child.path) 8507673Snate@binkert.org found_obj = child 8513101Sstever@eecs.umich.edu # search param space 8523101Sstever@eecs.umich.edu for pname,pdesc in self._params.iteritems(): 8533101Sstever@eecs.umich.edu if issubclass(pdesc.ptype, ptype): 8543101Sstever@eecs.umich.edu match_obj = self._values[pname] 8553101Sstever@eecs.umich.edu if found_obj != None and found_obj != match_obj: 8563101Sstever@eecs.umich.edu raise AttributeError, \ 8573101Sstever@eecs.umich.edu 'parent.any matched more than one: %s and %s' % (found_obj.path, match_obj.path) 8583101Sstever@eecs.umich.edu found_obj = match_obj 8593101Sstever@eecs.umich.edu return found_obj, found_obj != None 8603101Sstever@eecs.umich.edu 8613101Sstever@eecs.umich.edu def find_all(self, ptype): 8623101Sstever@eecs.umich.edu all = {} 8637675Snate@binkert.org # search children 8647675Snate@binkert.org for child in self._children.itervalues(): 8657675Snate@binkert.org if isinstance(child, ptype) and not isproxy(child) and \ 8667675Snate@binkert.org not isNullPointer(child): 8677675Snate@binkert.org all[child] = True 8687675Snate@binkert.org if isSimObject(child): 8697675Snate@binkert.org # also add results from the child itself 8707675Snate@binkert.org child_all, done = child.find_all(ptype) 8714762Snate@binkert.org all.update(dict(zip(child_all, [done] * len(child_all)))) 8724762Snate@binkert.org # search param space 8734762Snate@binkert.org for pname,pdesc in self._params.iteritems(): 8743101Sstever@eecs.umich.edu if issubclass(pdesc.ptype, ptype): 8753101Sstever@eecs.umich.edu match_obj = self._values[pname] 8763101Sstever@eecs.umich.edu if not isproxy(match_obj) and not isNullPointer(match_obj): 8773101Sstever@eecs.umich.edu all[match_obj] = True 8783101Sstever@eecs.umich.edu return all.keys(), True 8793101Sstever@eecs.umich.edu 8804167Sbinkertn@umich.edu def unproxy(self, base): 8813101Sstever@eecs.umich.edu return self 8827673Snate@binkert.org 8837673Snate@binkert.org def unproxyParams(self): 8847673Snate@binkert.org for param in self._params.iterkeys(): 8857673Snate@binkert.org value = self._values.get(param) 8867673Snate@binkert.org if value != None and isproxy(value): 8877673Snate@binkert.org try: 8887673Snate@binkert.org value = value.unproxy(self) 8897673Snate@binkert.org except: 8907673Snate@binkert.org print "Error in unproxying param '%s' of %s" % \ 8914167Sbinkertn@umich.edu (param, self.path()) 8924762Snate@binkert.org raise 8934762Snate@binkert.org setattr(self, param, value) 8944762Snate@binkert.org 8954167Sbinkertn@umich.edu # Unproxy ports in sorted order so that 'append' operations on 8963101Sstever@eecs.umich.edu # vector ports are done in a deterministic fashion. 8974167Sbinkertn@umich.edu port_names = self._ports.keys() 8984167Sbinkertn@umich.edu port_names.sort() 8994167Sbinkertn@umich.edu for port_name in port_names: 9004167Sbinkertn@umich.edu port = self._port_refs.get(port_name) 9014167Sbinkertn@umich.edu if port != None: 9024167Sbinkertn@umich.edu port.unproxy(self) 9034167Sbinkertn@umich.edu 9044167Sbinkertn@umich.edu def print_ini(self, ini_file): 9054167Sbinkertn@umich.edu print >>ini_file, '[' + self.path() + ']' # .ini section header 9064167Sbinkertn@umich.edu 9074167Sbinkertn@umich.edu instanceDict[self.path()] = self 9084167Sbinkertn@umich.edu 9093101Sstever@eecs.umich.edu if hasattr(self, 'type'): 9103101Sstever@eecs.umich.edu print >>ini_file, 'type=%s' % self.type 9113101Sstever@eecs.umich.edu 9123101Sstever@eecs.umich.edu if len(self._children.keys()): 9133101Sstever@eecs.umich.edu print >>ini_file, 'children=%s' % \ 9143101Sstever@eecs.umich.edu ' '.join(self._children[n].get_name() \ 9153101Sstever@eecs.umich.edu for n in sorted(self._children.keys())) 9163101Sstever@eecs.umich.edu 9174762Snate@binkert.org for param in sorted(self._params.keys()): 9184762Snate@binkert.org value = self._values.get(param) 9194762Snate@binkert.org if value != None: 9204762Snate@binkert.org print >>ini_file, '%s=%s' % (param, 9214762Snate@binkert.org self._values[param].ini_str()) 9224762Snate@binkert.org 9234762Snate@binkert.org for port_name in sorted(self._ports.keys()): 9243101Sstever@eecs.umich.edu port = self._port_refs.get(port_name, None) 9253101Sstever@eecs.umich.edu if port != None: 9264762Snate@binkert.org print >>ini_file, '%s=%s' % (port_name, port.ini_str()) 9273101Sstever@eecs.umich.edu 9284167Sbinkertn@umich.edu print >>ini_file # blank line between objects 9293101Sstever@eecs.umich.edu 9304167Sbinkertn@umich.edu # generate a tree of dictionaries expressing all the parameters in the 9314167Sbinkertn@umich.edu # instantiated system for use by scripts that want to do power, thermal 9324167Sbinkertn@umich.edu # visualization, and other similar tasks 9334167Sbinkertn@umich.edu def get_config_as_dict(self): 9344167Sbinkertn@umich.edu d = attrdict() 9354167Sbinkertn@umich.edu if hasattr(self, 'type'): 9364167Sbinkertn@umich.edu d.type = self.type 9374167Sbinkertn@umich.edu if hasattr(self, 'cxx_class'): 9384167Sbinkertn@umich.edu d.cxx_class = self.cxx_class 9394167Sbinkertn@umich.edu 9404167Sbinkertn@umich.edu for param in sorted(self._params.keys()): 9414167Sbinkertn@umich.edu value = self._values.get(param) 9423101Sstever@eecs.umich.edu if value != None: 9433101Sstever@eecs.umich.edu try: 9443101Sstever@eecs.umich.edu # Use native type for those supported by JSON and 9453101Sstever@eecs.umich.edu # strings for everything else. skipkeys=True seems 9463101Sstever@eecs.umich.edu # to not work as well as one would hope 9473101Sstever@eecs.umich.edu if type(self._values[param].value) in \ 9483101Sstever@eecs.umich.edu [str, unicode, int, long, float, bool, None]: 9493101Sstever@eecs.umich.edu d[param] = self._values[param].value 9504167Sbinkertn@umich.edu else: 9514762Snate@binkert.org d[param] = str(self._values[param]) 9524762Snate@binkert.org 9534762Snate@binkert.org except AttributeError: 9544762Snate@binkert.org pass 9554762Snate@binkert.org 9564762Snate@binkert.org for n in sorted(self._children.keys()): 9574762Snate@binkert.org d[self._children[n].get_name()] = self._children[n].get_config_as_dict() 9583101Sstever@eecs.umich.edu 9594762Snate@binkert.org for port_name in sorted(self._ports.keys()): 9603101Sstever@eecs.umich.edu port = self._port_refs.get(port_name, None) 9613101Sstever@eecs.umich.edu if port != None: 9623101Sstever@eecs.umich.edu # Might want to actually make this reference the object 9633101Sstever@eecs.umich.edu # in the future, although execing the string problem would 9643101Sstever@eecs.umich.edu # get some of the way there 9653101Sstever@eecs.umich.edu d[port_name] = port.ini_str() 9667673Snate@binkert.org 9677673Snate@binkert.org return d 9687673Snate@binkert.org 9697673Snate@binkert.org def getCCParams(self): 9707673Snate@binkert.org if self._ccParams: 9717673Snate@binkert.org return self._ccParams 9727673Snate@binkert.org 9737673Snate@binkert.org cc_params_struct = getattr(m5.internal.params, '%sParams' % self.type) 9747673Snate@binkert.org cc_params = cc_params_struct() 9757673Snate@binkert.org cc_params.pyobj = self 9763101Sstever@eecs.umich.edu cc_params.name = str(self) 9774167Sbinkertn@umich.edu 9784167Sbinkertn@umich.edu param_names = self._params.keys() 9794167Sbinkertn@umich.edu param_names.sort() 9804167Sbinkertn@umich.edu for param in param_names: 9814167Sbinkertn@umich.edu value = self._values.get(param) 9824167Sbinkertn@umich.edu if value is None: 9834167Sbinkertn@umich.edu fatal("%s.%s without default or user set value", 9844167Sbinkertn@umich.edu self.path(), param) 9854167Sbinkertn@umich.edu 9864167Sbinkertn@umich.edu value = value.getValue() 9874167Sbinkertn@umich.edu if isinstance(self._params[param], VectorParamDesc): 9884167Sbinkertn@umich.edu assert isinstance(value, list) 9893101Sstever@eecs.umich.edu vec = getattr(cc_params, param) 9903101Sstever@eecs.umich.edu assert not len(vec) 9913101Sstever@eecs.umich.edu for v in value: 9923101Sstever@eecs.umich.edu vec.append(v) 9933101Sstever@eecs.umich.edu else: 9943101Sstever@eecs.umich.edu setattr(cc_params, param, value) 9953101Sstever@eecs.umich.edu 9963101Sstever@eecs.umich.edu port_names = self._ports.keys() 9974762Snate@binkert.org port_names.sort() 9984762Snate@binkert.org for port_name in port_names: 9994762Snate@binkert.org port = self._port_refs.get(port_name, None) 10003101Sstever@eecs.umich.edu if port != None: 10013101Sstever@eecs.umich.edu port_count = len(port) 10023101Sstever@eecs.umich.edu else: 10033101Sstever@eecs.umich.edu port_count = 0 10043101Sstever@eecs.umich.edu setattr(cc_params, 'port_' + port_name + '_connection_count', 10053101Sstever@eecs.umich.edu port_count) 10064167Sbinkertn@umich.edu self._ccParams = cc_params 10074167Sbinkertn@umich.edu return self._ccParams 10083101Sstever@eecs.umich.edu 10093101Sstever@eecs.umich.edu # Get C++ object corresponding to this object, calling C++ if 10103101Sstever@eecs.umich.edu # necessary to construct it. Does *not* recursively create 10113101Sstever@eecs.umich.edu # children. 10123101Sstever@eecs.umich.edu def getCCObject(self): 10134762Snate@binkert.org if not self._ccObject: 10144167Sbinkertn@umich.edu # Make sure this object is in the configuration hierarchy 10154167Sbinkertn@umich.edu if not self._parent and not isRoot(self): 10164167Sbinkertn@umich.edu raise RuntimeError, "Attempt to instantiate orphan node" 10174762Snate@binkert.org # Cycles in the configuration hierarchy are not supported. This 10184762Snate@binkert.org # will catch the resulting recursion and stop. 10194762Snate@binkert.org self._ccObject = -1 10204762Snate@binkert.org params = self.getCCParams() 10214762Snate@binkert.org self._ccObject = params.create() 10223101Sstever@eecs.umich.edu elif self._ccObject == -1: 10233101Sstever@eecs.umich.edu raise RuntimeError, "%s: Cycle found in configuration hierarchy." \ 10243101Sstever@eecs.umich.edu % self.path() 10255469Snate@binkert.org return self._ccObject 10264167Sbinkertn@umich.edu 10273102Sstever@eecs.umich.edu def descendants(self): 10283101Sstever@eecs.umich.edu yield self 10293101Sstever@eecs.umich.edu for child in self._children.itervalues(): 10303101Sstever@eecs.umich.edu for obj in child.descendants(): 10313101Sstever@eecs.umich.edu yield obj 10323101Sstever@eecs.umich.edu 10334762Snate@binkert.org # Call C++ to create C++ object corresponding to this object 10344167Sbinkertn@umich.edu def createCCObject(self): 10355468Snate@binkert.org self.getCCParams() 10365468Snate@binkert.org self.getCCObject() # force creation 10375468Snate@binkert.org 10384167Sbinkertn@umich.edu def getValue(self): 10394762Snate@binkert.org return self.getCCObject() 10404762Snate@binkert.org 10414762Snate@binkert.org # Create C++ port connections corresponding to the connections in 10424762Snate@binkert.org # _port_refs 10434762Snate@binkert.org def connectPorts(self): 10443101Sstever@eecs.umich.edu for portRef in self._port_refs.itervalues(): 10453101Sstever@eecs.umich.edu portRef.ccConnect() 10463101Sstever@eecs.umich.edu 10473101Sstever@eecs.umich.edu def getMemoryMode(self): 10483101Sstever@eecs.umich.edu if not isinstance(self, m5.objects.System): 10493102Sstever@eecs.umich.edu return None 10503102Sstever@eecs.umich.edu 10513102Sstever@eecs.umich.edu return self._ccObject.getMemoryMode() 10523102Sstever@eecs.umich.edu 10533102Sstever@eecs.umich.edu def changeTiming(self, mode): 10543102Sstever@eecs.umich.edu if isinstance(self, m5.objects.System): 10553102Sstever@eecs.umich.edu # i don't know if there's a better way to do this - calling 10563102Sstever@eecs.umich.edu # setMemoryMode directly from self._ccObject results in calling 10573102Sstever@eecs.umich.edu # SimObject::setMemoryMode, not the System::setMemoryMode 10583102Sstever@eecs.umich.edu self._ccObject.setMemoryMode(mode) 10593102Sstever@eecs.umich.edu 10603102Sstever@eecs.umich.edu def takeOverFrom(self, old_cpu): 10613102Sstever@eecs.umich.edu self._ccObject.takeOverFrom(old_cpu._ccObject) 10623102Sstever@eecs.umich.edu 10633102Sstever@eecs.umich.edu # generate output file for 'dot' to display as a pretty graph. 10643102Sstever@eecs.umich.edu # this code is currently broken. 10653102Sstever@eecs.umich.edu def outputDot(self, dot): 10663102Sstever@eecs.umich.edu label = "{%s|" % self.path 10673102Sstever@eecs.umich.edu if isSimObject(self.realtype): 10683102Sstever@eecs.umich.edu label += '%s|' % self.type 10693102Sstever@eecs.umich.edu 10704762Snate@binkert.org if self.children: 10713102Sstever@eecs.umich.edu # instantiate children in same order they were added for 10723102Sstever@eecs.umich.edu # backward compatibility (else we can end up with cpu1 10733102Sstever@eecs.umich.edu # before cpu0). 10744762Snate@binkert.org for c in self.children: 10754762Snate@binkert.org dot.add_edge(pydot.Edge(self.path,c.path, style="bold")) 10764762Snate@binkert.org 10773102Sstever@eecs.umich.edu simobjs = [] 10783102Sstever@eecs.umich.edu for param in self.params: 10793102Sstever@eecs.umich.edu try: 10803102Sstever@eecs.umich.edu if param.value is None: 10813102Sstever@eecs.umich.edu raise AttributeError, 'Parameter with no value' 10823102Sstever@eecs.umich.edu 10833101Sstever@eecs.umich.edu value = param.value 10843101Sstever@eecs.umich.edu string = param.string(value) 10853101Sstever@eecs.umich.edu except Exception, e: 10863101Sstever@eecs.umich.edu msg = 'exception in %s:%s\n%s' % (self.name, param.name, e) 10873101Sstever@eecs.umich.edu e.args = (msg, ) 10883101Sstever@eecs.umich.edu raise 10893101Sstever@eecs.umich.edu 10903101Sstever@eecs.umich.edu if isSimObject(param.ptype) and string != "Null": 10913101Sstever@eecs.umich.edu simobjs.append(string) 10923101Sstever@eecs.umich.edu else: 10933101Sstever@eecs.umich.edu label += '%s = %s\\n' % (param.name, string) 10943101Sstever@eecs.umich.edu 10953101Sstever@eecs.umich.edu for so in simobjs: 10963101Sstever@eecs.umich.edu label += "|<%s> %s" % (so, so) 10973101Sstever@eecs.umich.edu dot.add_edge(pydot.Edge("%s:%s" % (self.path, so), so, 10983101Sstever@eecs.umich.edu tailport="w")) 10993101Sstever@eecs.umich.edu label += '}' 11003105Sstever@eecs.umich.edu dot.add_node(pydot.Node(self.path,shape="Mrecord",label=label)) 11013105Sstever@eecs.umich.edu 11023101Sstever@eecs.umich.edu # recursively dump out children 11033101Sstever@eecs.umich.edu for c in self.children: 11043101Sstever@eecs.umich.edu c.outputDot(dot) 11053101Sstever@eecs.umich.edu 11063105Sstever@eecs.umich.edu# Function to provide to C++ so it can look up instances based on paths 11073101Sstever@eecs.umich.edudef resolveSimObject(name): 11083103Sstever@eecs.umich.edu obj = instanceDict[name] 11093105Sstever@eecs.umich.edu return obj.getCCObject() 11103103Sstever@eecs.umich.edu 11113105Sstever@eecs.umich.edudef isSimObject(value): 11123105Sstever@eecs.umich.edu return isinstance(value, SimObject) 11133105Sstever@eecs.umich.edu 11143105Sstever@eecs.umich.edudef isSimObjectClass(value): 11153105Sstever@eecs.umich.edu return issubclass(value, SimObject) 11163105Sstever@eecs.umich.edu 11173105Sstever@eecs.umich.edudef isSimObjectVector(value): 11183105Sstever@eecs.umich.edu return isinstance(value, SimObjectVector) 11193105Sstever@eecs.umich.edu 11203105Sstever@eecs.umich.edudef isSimObjectSequence(value): 11213105Sstever@eecs.umich.edu if not isinstance(value, (list, tuple)) or len(value) == 0: 11223105Sstever@eecs.umich.edu return False 11233105Sstever@eecs.umich.edu 11243109Sstever@eecs.umich.edu for val in value: 11253105Sstever@eecs.umich.edu if not isNullPointer(val) and not isSimObject(val): 11263105Sstever@eecs.umich.edu return False 11273105Sstever@eecs.umich.edu 11283105Sstever@eecs.umich.edu return True 11293105Sstever@eecs.umich.edu 11303105Sstever@eecs.umich.edudef isSimObjectOrSequence(value): 11313105Sstever@eecs.umich.edu return isSimObject(value) or isSimObjectSequence(value) 11323105Sstever@eecs.umich.edu 11335578SSteve.Reinhardt@amd.comdef isRoot(obj): 11343101Sstever@eecs.umich.edu from m5.objects import Root 11353109Sstever@eecs.umich.edu return obj and obj is Root.getInstance() 11363109Sstever@eecs.umich.edu 11373109Sstever@eecs.umich.edudef isSimObjectOrVector(value): 11383109Sstever@eecs.umich.edu return isSimObject(value) or isSimObjectVector(value) 11393109Sstever@eecs.umich.edu 11403109Sstever@eecs.umich.edudef tryAsSimObjectOrVector(value): 11413109Sstever@eecs.umich.edu if isSimObjectOrVector(value): 11423109Sstever@eecs.umich.edu return value 11433109Sstever@eecs.umich.edu if isSimObjectSequence(value): 11443101Sstever@eecs.umich.edu return SimObjectVector(value) 11453105Sstever@eecs.umich.edu return None 11463105Sstever@eecs.umich.edu 11473105Sstever@eecs.umich.edudef coerceSimObjectOrVector(value): 11483101Sstever@eecs.umich.edu value = tryAsSimObjectOrVector(value) 11493105Sstever@eecs.umich.edu if value is None: 11503105Sstever@eecs.umich.edu raise TypeError, "SimObject or SimObjectVector expected" 11513101Sstever@eecs.umich.edu return value 11523105Sstever@eecs.umich.edu 11533179Sstever@eecs.umich.edubaseClasses = allClasses.copy() 11543105Sstever@eecs.umich.edubaseInstances = instanceDict.copy() 11553105Sstever@eecs.umich.edu 11563101Sstever@eecs.umich.edudef clear(): 11573101Sstever@eecs.umich.edu global allClasses, instanceDict 11583105Sstever@eecs.umich.edu 11593105Sstever@eecs.umich.edu allClasses = baseClasses.copy() 11603105Sstever@eecs.umich.edu instanceDict = baseInstances.copy() 11613105Sstever@eecs.umich.edu 11623105Sstever@eecs.umich.edu# __all__ defines the list of symbols that get exported when 11633105Sstever@eecs.umich.edu# 'from config import *' is invoked. Try to keep this reasonably 11643105Sstever@eecs.umich.edu# short to avoid polluting other namespaces. 11653105Sstever@eecs.umich.edu__all__ = [ 'SimObject' ] 11663105Sstever@eecs.umich.edu