SimObject.py revision 9017:a20f46ccb9ce
13101Sstever@eecs.umich.edu# Copyright (c) 2012 ARM Limited 23101Sstever@eecs.umich.edu# 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 473885Sbinkertn@umich.eduimport m5 483885Sbinkertn@umich.edufrom m5.util import * 494762Snate@binkert.org 503885Sbinkertn@umich.edu# Have to import params up top since Param is referenced on initial 513885Sbinkertn@umich.edu# load (when SimObject class references Param to create a class 523885Sbinkertn@umich.edu# variable, the 'name' param)... 533101Sstever@eecs.umich.edufrom m5.params import * 544380Sbinkertn@umich.edu# There are a few things we need that aren't in params.__all__ since 554167Sbinkertn@umich.edu# normal users don't need them 563102Sstever@eecs.umich.edufrom m5.params import ParamDesc, VectorParamDesc, \ 573101Sstever@eecs.umich.edu isNullPointer, SimObjectVector, Port 584762Snate@binkert.org 594762Snate@binkert.orgfrom m5.proxy import * 604762Snate@binkert.orgfrom m5.proxy import isproxy 614762Snate@binkert.org 624762Snate@binkert.org##################################################################### 634762Snate@binkert.org# 644762Snate@binkert.org# M5 Python Configuration Utility 654762Snate@binkert.org# 664762Snate@binkert.org# The basic idea is to write simple Python programs that build Python 674762Snate@binkert.org# objects corresponding to M5 SimObjects for the desired simulation 684762Snate@binkert.org# configuration. For now, the Python emits a .ini file that can be 695033Smilesck@eecs.umich.edu# parsed by M5. In the future, some tighter integration between M5 705033Smilesck@eecs.umich.edu# and the Python interpreter may allow bypassing the .ini file. 715033Smilesck@eecs.umich.edu# 725033Smilesck@eecs.umich.edu# Each SimObject class in M5 is represented by a Python class with the 735033Smilesck@eecs.umich.edu# same name. The Python inheritance tree mirrors the M5 C++ tree 745033Smilesck@eecs.umich.edu# (e.g., SimpleCPU derives from BaseCPU in both cases, and all 755033Smilesck@eecs.umich.edu# SimObjects inherit from a single SimObject base class). To specify 765033Smilesck@eecs.umich.edu# an instance of an M5 SimObject in a configuration, the user simply 775033Smilesck@eecs.umich.edu# instantiates the corresponding Python object. The parameters for 785033Smilesck@eecs.umich.edu# that SimObject are given by assigning to attributes of the Python 793101Sstever@eecs.umich.edu# object, either using keyword assignment in the constructor or in 803101Sstever@eecs.umich.edu# separate assignment statements. For example: 813101Sstever@eecs.umich.edu# 825033Smilesck@eecs.umich.edu# cache = BaseCache(size='64KB') 833101Sstever@eecs.umich.edu# cache.hit_latency = 3 843101Sstever@eecs.umich.edu# cache.assoc = 8 853101Sstever@eecs.umich.edu# 863101Sstever@eecs.umich.edu# The magic lies in the mapping of the Python attributes for SimObject 873101Sstever@eecs.umich.edu# classes to the actual SimObject parameter specifications. This 883101Sstever@eecs.umich.edu# allows parameter validity checking in the Python code. Continuing 893101Sstever@eecs.umich.edu# the example above, the statements "cache.blurfl=3" or 903101Sstever@eecs.umich.edu# "cache.assoc='hello'" would both result in runtime errors in Python, 913101Sstever@eecs.umich.edu# since the BaseCache object has no 'blurfl' parameter and the 'assoc' 923101Sstever@eecs.umich.edu# parameter requires an integer, respectively. This magic is done 933101Sstever@eecs.umich.edu# primarily by overriding the special __setattr__ method that controls 943101Sstever@eecs.umich.edu# assignment to object attributes. 953101Sstever@eecs.umich.edu# 963101Sstever@eecs.umich.edu# Once a set of Python objects have been instantiated in a hierarchy, 973101Sstever@eecs.umich.edu# calling 'instantiate(obj)' (where obj is the root of the hierarchy) 983101Sstever@eecs.umich.edu# will generate a .ini file. 993101Sstever@eecs.umich.edu# 1003101Sstever@eecs.umich.edu##################################################################### 1013101Sstever@eecs.umich.edu 1023101Sstever@eecs.umich.edu# list of all SimObject classes 1033101Sstever@eecs.umich.eduallClasses = {} 1043101Sstever@eecs.umich.edu 1053101Sstever@eecs.umich.edu# dict to look up SimObjects based on path 1063101Sstever@eecs.umich.eduinstanceDict = {} 1073101Sstever@eecs.umich.edu 1083101Sstever@eecs.umich.edudef public_value(key, value): 1093101Sstever@eecs.umich.edu return key.startswith('_') or \ 1103101Sstever@eecs.umich.edu isinstance(value, (FunctionType, MethodType, ModuleType, 1113101Sstever@eecs.umich.edu classmethod, type)) 1123101Sstever@eecs.umich.edu 1133101Sstever@eecs.umich.edu# The metaclass for SimObject. This class controls how new classes 1143101Sstever@eecs.umich.edu# that derive from SimObject are instantiated, and provides inherited 1153101Sstever@eecs.umich.edu# class behavior (just like a class controls how instances of that 1163101Sstever@eecs.umich.edu# class are instantiated, and provides inherited instance behavior). 1173101Sstever@eecs.umich.educlass MetaSimObject(type): 1183101Sstever@eecs.umich.edu # Attributes that can be set only at initialization time 1193101Sstever@eecs.umich.edu init_keywords = { 'abstract' : bool, 1203101Sstever@eecs.umich.edu 'cxx_class' : str, 1213101Sstever@eecs.umich.edu 'cxx_type' : str, 1223101Sstever@eecs.umich.edu 'type' : str } 1233101Sstever@eecs.umich.edu # Attributes that can be set any time 1243101Sstever@eecs.umich.edu keywords = { 'check' : FunctionType } 1253101Sstever@eecs.umich.edu 1263101Sstever@eecs.umich.edu # __new__ is called before __init__, and is where the statements 1273101Sstever@eecs.umich.edu # in the body of the class definition get loaded into the class's 1283101Sstever@eecs.umich.edu # __dict__. We intercept this to filter out parameter & port assignments 1293101Sstever@eecs.umich.edu # and only allow "private" attributes to be passed to the base 1303101Sstever@eecs.umich.edu # __new__ (starting with underscore). 1313101Sstever@eecs.umich.edu def __new__(mcls, name, bases, dict): 1325033Smilesck@eecs.umich.edu assert name not in allClasses, "SimObject %s already present" % name 1335033Smilesck@eecs.umich.edu 1345033Smilesck@eecs.umich.edu # Copy "private" attributes, functions, and classes to the 1355033Smilesck@eecs.umich.edu # official dict. Everything else goes in _init_dict to be 1365033Smilesck@eecs.umich.edu # filtered in __init__. 1373101Sstever@eecs.umich.edu cls_dict = {} 1383101Sstever@eecs.umich.edu value_dict = {} 1393101Sstever@eecs.umich.edu for key,val in dict.items(): 1403101Sstever@eecs.umich.edu if public_value(key, val): 1413101Sstever@eecs.umich.edu cls_dict[key] = val 1423101Sstever@eecs.umich.edu else: 1433101Sstever@eecs.umich.edu # must be a param/port setting 1443101Sstever@eecs.umich.edu value_dict[key] = val 1453101Sstever@eecs.umich.edu if 'abstract' not in value_dict: 1463101Sstever@eecs.umich.edu value_dict['abstract'] = False 1473101Sstever@eecs.umich.edu cls_dict['_value_dict'] = value_dict 1483101Sstever@eecs.umich.edu cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) 1493101Sstever@eecs.umich.edu if 'type' in value_dict: 1503102Sstever@eecs.umich.edu allClasses[name] = cls 1513101Sstever@eecs.umich.edu return cls 1523101Sstever@eecs.umich.edu 1533101Sstever@eecs.umich.edu # subclass initialization 1543101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 1553101Sstever@eecs.umich.edu # calls type.__init__()... I think that's a no-op, but leave 1563101Sstever@eecs.umich.edu # it here just in case it's not. 1573101Sstever@eecs.umich.edu super(MetaSimObject, cls).__init__(name, bases, dict) 1583101Sstever@eecs.umich.edu 1593101Sstever@eecs.umich.edu # initialize required attributes 1603101Sstever@eecs.umich.edu 1613101Sstever@eecs.umich.edu # class-only attributes 1623101Sstever@eecs.umich.edu cls._params = multidict() # param descriptions 1633101Sstever@eecs.umich.edu cls._ports = multidict() # port descriptions 1643101Sstever@eecs.umich.edu 1653101Sstever@eecs.umich.edu # class or instance attributes 1663101Sstever@eecs.umich.edu cls._values = multidict() # param values 1673101Sstever@eecs.umich.edu cls._children = multidict() # SimObject children 1685033Smilesck@eecs.umich.edu cls._port_refs = multidict() # port ref objects 1695475Snate@binkert.org cls._instantiated = False # really instantiated, cloned, or subclassed 1705475Snate@binkert.org 1715475Snate@binkert.org # We don't support multiple inheritance. If you want to, you 1725475Snate@binkert.org # must fix multidict to deal with it properly. 1733101Sstever@eecs.umich.edu if len(bases) > 1: 1743101Sstever@eecs.umich.edu raise TypeError, "SimObjects do not support multiple inheritance" 1753101Sstever@eecs.umich.edu 1764762Snate@binkert.org base = bases[0] 1774762Snate@binkert.org 1784762Snate@binkert.org # Set up general inheritance via multidicts. A subclass will 1793101Sstever@eecs.umich.edu # inherit all its settings from the base class. The only time 1803101Sstever@eecs.umich.edu # the following is not true is when we define the SimObject 1813101Sstever@eecs.umich.edu # class itself (in which case the multidicts have no parent). 1823101Sstever@eecs.umich.edu if isinstance(base, MetaSimObject): 1835037Smilesck@eecs.umich.edu cls._base = base 1843101Sstever@eecs.umich.edu cls._params.parent = base._params 1855037Smilesck@eecs.umich.edu cls._ports.parent = base._ports 1863101Sstever@eecs.umich.edu cls._values.parent = base._values 1873101Sstever@eecs.umich.edu cls._children.parent = base._children 1883101Sstever@eecs.umich.edu cls._port_refs.parent = base._port_refs 1893101Sstever@eecs.umich.edu # mark base as having been subclassed 1903101Sstever@eecs.umich.edu base._instantiated = True 1913101Sstever@eecs.umich.edu else: 1923101Sstever@eecs.umich.edu cls._base = None 1933101Sstever@eecs.umich.edu 1943101Sstever@eecs.umich.edu # default keyword values 1954762Snate@binkert.org if 'type' in cls._value_dict: 1964762Snate@binkert.org if 'cxx_class' not in cls._value_dict: 1974762Snate@binkert.org cls._value_dict['cxx_class'] = cls._value_dict['type'] 1984762Snate@binkert.org 1994762Snate@binkert.org cls._value_dict['cxx_type'] = '%s *' % cls._value_dict['cxx_class'] 2004762Snate@binkert.org 2014762Snate@binkert.org # Export methods are automatically inherited via C++, so we 2024762Snate@binkert.org # don't want the method declarations to get inherited on the 2034762Snate@binkert.org # python side (and thus end up getting repeated in the wrapped 2044762Snate@binkert.org # versions of derived classes). The code below basicallly 2054762Snate@binkert.org # suppresses inheritance by substituting in the base (null) 2064762Snate@binkert.org # versions of these methods unless a different version is 2074762Snate@binkert.org # explicitly supplied. 2084762Snate@binkert.org for method_name in ('export_methods', 'export_method_cxx_predecls', 2094762Snate@binkert.org 'export_method_swig_predecls'): 2104762Snate@binkert.org if method_name not in cls.__dict__: 2113101Sstever@eecs.umich.edu base_method = getattr(MetaSimObject, method_name) 2123101Sstever@eecs.umich.edu m = MethodType(base_method, cls, MetaSimObject) 2133101Sstever@eecs.umich.edu setattr(cls, method_name, m) 2143101Sstever@eecs.umich.edu 2153101Sstever@eecs.umich.edu # Now process the _value_dict items. They could be defining 2163101Sstever@eecs.umich.edu # new (or overriding existing) parameters or ports, setting 2173101Sstever@eecs.umich.edu # class keywords (e.g., 'abstract'), or setting parameter 2183101Sstever@eecs.umich.edu # values or port bindings. The first 3 can only be set when 2193101Sstever@eecs.umich.edu # the class is defined, so we handle them here. The others 2203101Sstever@eecs.umich.edu # can be set later too, so just emulate that by calling 2213101Sstever@eecs.umich.edu # setattr(). 2223101Sstever@eecs.umich.edu for key,val in cls._value_dict.items(): 2233101Sstever@eecs.umich.edu # param descriptions 2243101Sstever@eecs.umich.edu if isinstance(val, ParamDesc): 2253101Sstever@eecs.umich.edu cls._new_param(key, val) 2263101Sstever@eecs.umich.edu 2273101Sstever@eecs.umich.edu # port objects 2283101Sstever@eecs.umich.edu elif isinstance(val, Port): 2293101Sstever@eecs.umich.edu cls._new_port(key, val) 2303101Sstever@eecs.umich.edu 2313101Sstever@eecs.umich.edu # init-time-only keywords 2325033Smilesck@eecs.umich.edu elif cls.init_keywords.has_key(key): 2335033Smilesck@eecs.umich.edu cls._set_keyword(key, val, cls.init_keywords[key]) 2343101Sstever@eecs.umich.edu 2353101Sstever@eecs.umich.edu # default: use normal path (ends up in __setattr__) 2363101Sstever@eecs.umich.edu else: 2373101Sstever@eecs.umich.edu setattr(cls, key, val) 2383101Sstever@eecs.umich.edu 2393101Sstever@eecs.umich.edu def _set_keyword(cls, keyword, val, kwtype): 2403101Sstever@eecs.umich.edu if not isinstance(val, kwtype): 2413101Sstever@eecs.umich.edu raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ 2423101Sstever@eecs.umich.edu (keyword, type(val), kwtype) 2433101Sstever@eecs.umich.edu if isinstance(val, FunctionType): 2443101Sstever@eecs.umich.edu val = classmethod(val) 2453101Sstever@eecs.umich.edu type.__setattr__(cls, keyword, val) 2463101Sstever@eecs.umich.edu 2473101Sstever@eecs.umich.edu def _new_param(cls, name, pdesc): 2483101Sstever@eecs.umich.edu # each param desc should be uniquely assigned to one variable 2493101Sstever@eecs.umich.edu assert(not hasattr(pdesc, 'name')) 2503101Sstever@eecs.umich.edu pdesc.name = name 2513101Sstever@eecs.umich.edu cls._params[name] = pdesc 2523101Sstever@eecs.umich.edu if hasattr(pdesc, 'default'): 2533101Sstever@eecs.umich.edu cls._set_param(name, pdesc.default, pdesc) 2543101Sstever@eecs.umich.edu 2553101Sstever@eecs.umich.edu def _set_param(cls, name, value, param): 2563101Sstever@eecs.umich.edu assert(param.name == name) 2573101Sstever@eecs.umich.edu try: 2583101Sstever@eecs.umich.edu value = param.convert(value) 2593101Sstever@eecs.umich.edu except Exception, e: 2603101Sstever@eecs.umich.edu msg = "%s\nError setting param %s.%s to %s\n" % \ 2613101Sstever@eecs.umich.edu (e, cls.__name__, name, value) 2624762Snate@binkert.org e.args = (msg, ) 2634762Snate@binkert.org raise 2644762Snate@binkert.org cls._values[name] = value 2654762Snate@binkert.org # if param value is a SimObject, make it a child too, so that 2663101Sstever@eecs.umich.edu # it gets cloned properly when the class is instantiated 2673101Sstever@eecs.umich.edu if isSimObjectOrVector(value) and not value.has_parent(): 2683101Sstever@eecs.umich.edu cls._add_cls_child(name, value) 2693101Sstever@eecs.umich.edu 2703101Sstever@eecs.umich.edu def _add_cls_child(cls, name, child): 2713101Sstever@eecs.umich.edu # It's a little funky to have a class as a parent, but these 2723101Sstever@eecs.umich.edu # objects should never be instantiated (only cloned, which 2733101Sstever@eecs.umich.edu # clears the parent pointer), and this makes it clear that the 2743101Sstever@eecs.umich.edu # object is not an orphan and can provide better error 2753101Sstever@eecs.umich.edu # messages. 2763101Sstever@eecs.umich.edu child.set_parent(cls, name) 2773714Sstever@eecs.umich.edu cls._children[name] = child 2783714Sstever@eecs.umich.edu 2793714Sstever@eecs.umich.edu def _new_port(cls, name, port): 2803714Sstever@eecs.umich.edu # each port should be uniquely assigned to one variable 2813714Sstever@eecs.umich.edu assert(not hasattr(port, 'name')) 2823714Sstever@eecs.umich.edu port.name = name 2833101Sstever@eecs.umich.edu cls._ports[name] = port 2843101Sstever@eecs.umich.edu 2853101Sstever@eecs.umich.edu # same as _get_port_ref, effectively, but for classes 2863101Sstever@eecs.umich.edu def _cls_get_port_ref(cls, attr): 2873101Sstever@eecs.umich.edu # Return reference that can be assigned to another port 2883101Sstever@eecs.umich.edu # via __setattr__. There is only ever one reference 2893101Sstever@eecs.umich.edu # object per port, but we create them lazily here. 2903101Sstever@eecs.umich.edu ref = cls._port_refs.get(attr) 2913101Sstever@eecs.umich.edu if not ref: 2923101Sstever@eecs.umich.edu ref = cls._ports[attr].makeRef(cls) 2933101Sstever@eecs.umich.edu cls._port_refs[attr] = ref 2943101Sstever@eecs.umich.edu return ref 2953101Sstever@eecs.umich.edu 2963101Sstever@eecs.umich.edu # Set attribute (called on foo.attr = value when foo is an 2973101Sstever@eecs.umich.edu # instance of class cls). 2983101Sstever@eecs.umich.edu def __setattr__(cls, attr, value): 2993101Sstever@eecs.umich.edu # normal processing for private attributes 3003101Sstever@eecs.umich.edu if public_value(attr, value): 3013101Sstever@eecs.umich.edu type.__setattr__(cls, attr, value) 3023101Sstever@eecs.umich.edu return 3033101Sstever@eecs.umich.edu 3043101Sstever@eecs.umich.edu if cls.keywords.has_key(attr): 3053101Sstever@eecs.umich.edu cls._set_keyword(attr, value, cls.keywords[attr]) 3063101Sstever@eecs.umich.edu return 3073101Sstever@eecs.umich.edu 3085033Smilesck@eecs.umich.edu if cls._ports.has_key(attr): 3093101Sstever@eecs.umich.edu cls._cls_get_port_ref(attr).connect(value) 3103101Sstever@eecs.umich.edu return 3113101Sstever@eecs.umich.edu 3123101Sstever@eecs.umich.edu if isSimObjectOrSequence(value) and cls._instantiated: 3133101Sstever@eecs.umich.edu raise RuntimeError, \ 3143101Sstever@eecs.umich.edu "cannot set SimObject parameter '%s' after\n" \ 3153101Sstever@eecs.umich.edu " class %s has been instantiated or subclassed" \ 3163101Sstever@eecs.umich.edu % (attr, cls.__name__) 3173101Sstever@eecs.umich.edu 3183101Sstever@eecs.umich.edu # check for param 3193101Sstever@eecs.umich.edu param = cls._params.get(attr) 3203101Sstever@eecs.umich.edu if param: 3213101Sstever@eecs.umich.edu cls._set_param(attr, value, param) 3223101Sstever@eecs.umich.edu return 3233101Sstever@eecs.umich.edu 3244762Snate@binkert.org if isSimObjectOrSequence(value): 3253101Sstever@eecs.umich.edu # If RHS is a SimObject, it's an implicit child assignment. 3263101Sstever@eecs.umich.edu cls._add_cls_child(attr, coerceSimObjectOrVector(value)) 3273101Sstever@eecs.umich.edu return 3283101Sstever@eecs.umich.edu 3293101Sstever@eecs.umich.edu # no valid assignment... raise exception 3303101Sstever@eecs.umich.edu raise AttributeError, \ 3313101Sstever@eecs.umich.edu "Class %s has no parameter \'%s\'" % (cls.__name__, attr) 3323101Sstever@eecs.umich.edu 3333101Sstever@eecs.umich.edu def __getattr__(cls, attr): 3343101Sstever@eecs.umich.edu if attr == 'cxx_class_path': 3353101Sstever@eecs.umich.edu return cls.cxx_class.split('::') 3363101Sstever@eecs.umich.edu 3373101Sstever@eecs.umich.edu if attr == 'cxx_class_name': 3383101Sstever@eecs.umich.edu return cls.cxx_class_path[-1] 3393101Sstever@eecs.umich.edu 3403101Sstever@eecs.umich.edu if attr == 'cxx_namespaces': 3413101Sstever@eecs.umich.edu return cls.cxx_class_path[:-1] 3423101Sstever@eecs.umich.edu 3433101Sstever@eecs.umich.edu if cls._values.has_key(attr): 3443101Sstever@eecs.umich.edu return cls._values[attr] 3453101Sstever@eecs.umich.edu 3463101Sstever@eecs.umich.edu if cls._children.has_key(attr): 3473101Sstever@eecs.umich.edu return cls._children[attr] 3483101Sstever@eecs.umich.edu 3493101Sstever@eecs.umich.edu raise AttributeError, \ 3503101Sstever@eecs.umich.edu "object '%s' has no attribute '%s'" % (cls.__name__, attr) 3513101Sstever@eecs.umich.edu 3523101Sstever@eecs.umich.edu def __str__(cls): 3533102Sstever@eecs.umich.edu return cls.__name__ 3543714Sstever@eecs.umich.edu 3553101Sstever@eecs.umich.edu # See ParamValue.cxx_predecls for description. 3563714Sstever@eecs.umich.edu def cxx_predecls(cls, code): 3573714Sstever@eecs.umich.edu code('#include "params/$cls.hh"') 3583714Sstever@eecs.umich.edu 3593101Sstever@eecs.umich.edu # See ParamValue.swig_predecls for description. 3603101Sstever@eecs.umich.edu def swig_predecls(cls, code): 3614762Snate@binkert.org code('%import "python/m5/internal/param_$cls.i"') 3624762Snate@binkert.org 3634762Snate@binkert.org # Hook for exporting additional C++ methods to Python via SWIG. 3643101Sstever@eecs.umich.edu # Default is none, override using @classmethod in class definition. 3653101Sstever@eecs.umich.edu def export_methods(cls, code): 3663101Sstever@eecs.umich.edu pass 3673101Sstever@eecs.umich.edu 3683101Sstever@eecs.umich.edu # Generate the code needed as a prerequisite for the C++ methods 3693101Sstever@eecs.umich.edu # exported via export_methods() to be compiled in the _wrap.cc 3703101Sstever@eecs.umich.edu # file. Typically generates one or more #include statements. If 3713101Sstever@eecs.umich.edu # any methods are exported, typically at least the C++ header 3723101Sstever@eecs.umich.edu # declaring the relevant SimObject class must be included. 3733101Sstever@eecs.umich.edu def export_method_cxx_predecls(cls, code): 3743101Sstever@eecs.umich.edu pass 3753101Sstever@eecs.umich.edu 3763101Sstever@eecs.umich.edu # Generate the code needed as a prerequisite for the C++ methods 3773101Sstever@eecs.umich.edu # exported via export_methods() to be processed by SWIG. 3783101Sstever@eecs.umich.edu # Typically generates one or more %include or %import statements. 3793101Sstever@eecs.umich.edu # If any methods are exported, typically at least the C++ header 3803101Sstever@eecs.umich.edu # declaring the relevant SimObject class must be included. 3813101Sstever@eecs.umich.edu def export_method_swig_predecls(cls, code): 3823101Sstever@eecs.umich.edu pass 3833101Sstever@eecs.umich.edu 3844446Sbinkertn@umich.edu # Generate the declaration for this object for wrapping with SWIG. 3853101Sstever@eecs.umich.edu # Generates code that goes into a SWIG .i file. Called from 3865468Snate@binkert.org # src/SConscript. 3875468Snate@binkert.org def swig_decl(cls, code): 3885468Snate@binkert.org class_path = cls.cxx_class.split('::') 3895468Snate@binkert.org classname = class_path[-1] 3905468Snate@binkert.org namespaces = class_path[:-1] 3915468Snate@binkert.org 3925468Snate@binkert.org # The 'local' attribute restricts us to the params declared in 3934762Snate@binkert.org # the object itself, not including inherited params (which 3944762Snate@binkert.org # will also be inherited from the base class's param struct 3954762Snate@binkert.org # here). 3963101Sstever@eecs.umich.edu params = cls._params.local.values() 3973101Sstever@eecs.umich.edu ports = cls._ports.local 3983101Sstever@eecs.umich.edu 3993101Sstever@eecs.umich.edu code('%module(package="m5.internal") param_$cls') 4003101Sstever@eecs.umich.edu code() 4013101Sstever@eecs.umich.edu code('%{') 4023101Sstever@eecs.umich.edu code('#include "params/$cls.hh"') 4033101Sstever@eecs.umich.edu for param in params: 4043102Sstever@eecs.umich.edu param.cxx_predecls(code) 4053101Sstever@eecs.umich.edu cls.export_method_cxx_predecls(code) 4063101Sstever@eecs.umich.edu code('''\ 4073101Sstever@eecs.umich.edu/** 4084168Sbinkertn@umich.edu * This is a workaround for bug in swig. Prior to gcc 4.6.1 the STL 4093101Sstever@eecs.umich.edu * headers like vector, string, etc. used to automatically pull in 4103101Sstever@eecs.umich.edu * the cstddef header but starting with gcc 4.6.1 they no longer do. 4113101Sstever@eecs.umich.edu * This leads to swig generated a file that does not compile so we 4123101Sstever@eecs.umich.edu * explicitly include cstddef. Additionally, including version 2.0.4, 4133101Sstever@eecs.umich.edu * swig uses ptrdiff_t without the std:: namespace prefix which is 4143101Sstever@eecs.umich.edu * required with gcc 4.6.1. We explicitly provide access to it. 4153102Sstever@eecs.umich.edu */ 4163101Sstever@eecs.umich.edu#include <cstddef> 4173101Sstever@eecs.umich.eduusing std::ptrdiff_t; 4183101Sstever@eecs.umich.edu''') 4193101Sstever@eecs.umich.edu code('%}') 4203101Sstever@eecs.umich.edu code() 4213101Sstever@eecs.umich.edu 4223101Sstever@eecs.umich.edu for param in params: 4233101Sstever@eecs.umich.edu param.swig_predecls(code) 4243101Sstever@eecs.umich.edu cls.export_method_swig_predecls(code) 4253101Sstever@eecs.umich.edu 4263101Sstever@eecs.umich.edu code() 4273102Sstever@eecs.umich.edu if cls._base: 4283101Sstever@eecs.umich.edu code('%import "python/m5/internal/param_${{cls._base}}.i"') 4293101Sstever@eecs.umich.edu code() 4303101Sstever@eecs.umich.edu 4313584Ssaidi@eecs.umich.edu for ns in namespaces: 4323584Ssaidi@eecs.umich.edu code('namespace $ns {') 4333584Ssaidi@eecs.umich.edu 4343584Ssaidi@eecs.umich.edu if namespaces: 4353584Ssaidi@eecs.umich.edu code('// avoid name conflicts') 4363101Sstever@eecs.umich.edu sep_string = '_COLONS_' 4373101Sstever@eecs.umich.edu flat_name = sep_string.join(class_path) 4385033Smilesck@eecs.umich.edu code('%rename($flat_name) $classname;') 4393101Sstever@eecs.umich.edu 4403101Sstever@eecs.umich.edu code() 4413101Sstever@eecs.umich.edu code('// stop swig from creating/wrapping default ctor/dtor') 4423101Sstever@eecs.umich.edu code('%nodefault $classname;') 4433101Sstever@eecs.umich.edu code('class $classname') 4443101Sstever@eecs.umich.edu if cls._base: 4453101Sstever@eecs.umich.edu code(' : public ${{cls._base.cxx_class}}') 4463101Sstever@eecs.umich.edu code('{') 4473101Sstever@eecs.umich.edu code(' public:') 4483101Sstever@eecs.umich.edu cls.export_methods(code) 4493101Sstever@eecs.umich.edu code('};') 4503101Sstever@eecs.umich.edu 4513101Sstever@eecs.umich.edu for ns in reversed(namespaces): 4523101Sstever@eecs.umich.edu code('} // namespace $ns') 4533101Sstever@eecs.umich.edu 4543101Sstever@eecs.umich.edu code() 4553101Sstever@eecs.umich.edu code('%include "params/$cls.hh"') 4563101Sstever@eecs.umich.edu 4573101Sstever@eecs.umich.edu 4583101Sstever@eecs.umich.edu # Generate the C++ declaration (.hh file) for this SimObject's 4593101Sstever@eecs.umich.edu # param struct. Called from src/SConscript. 4603101Sstever@eecs.umich.edu def cxx_param_decl(cls, code): 4613101Sstever@eecs.umich.edu # The 'local' attribute restricts us to the params declared in 4623101Sstever@eecs.umich.edu # the object itself, not including inherited params (which 4633101Sstever@eecs.umich.edu # will also be inherited from the base class's param struct 4643101Sstever@eecs.umich.edu # here). 4653101Sstever@eecs.umich.edu params = cls._params.local.values() 4663101Sstever@eecs.umich.edu ports = cls._ports.local 4673101Sstever@eecs.umich.edu try: 4683101Sstever@eecs.umich.edu ptypes = [p.ptype for p in params] 4693101Sstever@eecs.umich.edu except: 4705219Ssaidi@eecs.umich.edu print cls, p, p.ptype_str 4715219Ssaidi@eecs.umich.edu print params 4725219Ssaidi@eecs.umich.edu raise 4733101Sstever@eecs.umich.edu 4743101Sstever@eecs.umich.edu class_path = cls._value_dict['cxx_class'].split('::') 4753101Sstever@eecs.umich.edu 4763101Sstever@eecs.umich.edu code('''\ 4773101Sstever@eecs.umich.edu#ifndef __PARAMS__${cls}__ 4783101Sstever@eecs.umich.edu#define __PARAMS__${cls}__ 4793101Sstever@eecs.umich.edu 4803101Sstever@eecs.umich.edu''') 4813101Sstever@eecs.umich.edu 4823101Sstever@eecs.umich.edu # A forward class declaration is sufficient since we are just 4833101Sstever@eecs.umich.edu # declaring a pointer. 4843101Sstever@eecs.umich.edu for ns in class_path[:-1]: 4853101Sstever@eecs.umich.edu code('namespace $ns {') 4863101Sstever@eecs.umich.edu code('class $0;', class_path[-1]) 4873101Sstever@eecs.umich.edu for ns in reversed(class_path[:-1]): 4883101Sstever@eecs.umich.edu code('} // namespace $ns') 4893101Sstever@eecs.umich.edu code() 4903101Sstever@eecs.umich.edu 4914762Snate@binkert.org # The base SimObject has a couple of params that get 4924762Snate@binkert.org # automatically set from Python without being declared through 4934762Snate@binkert.org # the normal Param mechanism; we slip them in here (needed 4944762Snate@binkert.org # predecls now, actual declarations below) 4954762Snate@binkert.org if cls == SimObject: 4964762Snate@binkert.org code(''' 4974762Snate@binkert.org#ifndef PY_VERSION 4984762Snate@binkert.orgstruct PyObject; 4994762Snate@binkert.org#endif 5003101Sstever@eecs.umich.edu 5013101Sstever@eecs.umich.edu#include <string> 5023101Sstever@eecs.umich.edu 5034762Snate@binkert.orgclass EventQueue; 5044762Snate@binkert.org''') 5054762Snate@binkert.org for param in params: 5064762Snate@binkert.org param.cxx_predecls(code) 5074762Snate@binkert.org for port in ports.itervalues(): 5084762Snate@binkert.org port.cxx_predecls(code) 5094762Snate@binkert.org code() 5104762Snate@binkert.org 5114762Snate@binkert.org if cls._base: 5123101Sstever@eecs.umich.edu code('#include "params/${{cls._base.type}}.hh"') 5133101Sstever@eecs.umich.edu code() 5143101Sstever@eecs.umich.edu 5153101Sstever@eecs.umich.edu for ptype in ptypes: 5163101Sstever@eecs.umich.edu if issubclass(ptype, Enum): 5173101Sstever@eecs.umich.edu code('#include "enums/${{ptype.__name__}}.hh"') 5183101Sstever@eecs.umich.edu code() 5193101Sstever@eecs.umich.edu 5203102Sstever@eecs.umich.edu # now generate the actual param struct 5213101Sstever@eecs.umich.edu code("struct ${cls}Params") 5223101Sstever@eecs.umich.edu if cls._base: 5233101Sstever@eecs.umich.edu code(" : public ${{cls._base.type}}Params") 5244762Snate@binkert.org code("{") 5254762Snate@binkert.org if not hasattr(cls, 'abstract') or not cls.abstract: 5264762Snate@binkert.org if 'type' in cls.__dict__: 5273101Sstever@eecs.umich.edu code(" ${{cls.cxx_type}} create();") 5283101Sstever@eecs.umich.edu 5293101Sstever@eecs.umich.edu code.indent() 5303101Sstever@eecs.umich.edu if cls == SimObject: 5313101Sstever@eecs.umich.edu code(''' 5323101Sstever@eecs.umich.edu SimObjectParams() 5333101Sstever@eecs.umich.edu { 5343101Sstever@eecs.umich.edu extern EventQueue mainEventQueue; 5353101Sstever@eecs.umich.edu eventq = &mainEventQueue; 5363101Sstever@eecs.umich.edu } 5373101Sstever@eecs.umich.edu virtual ~SimObjectParams() {} 5383101Sstever@eecs.umich.edu 5393101Sstever@eecs.umich.edu std::string name; 5403101Sstever@eecs.umich.edu PyObject *pyobj; 5413101Sstever@eecs.umich.edu EventQueue *eventq; 5423101Sstever@eecs.umich.edu ''') 5433101Sstever@eecs.umich.edu for param in params: 5443101Sstever@eecs.umich.edu param.cxx_decl(code) 5453101Sstever@eecs.umich.edu for port in ports.itervalues(): 5463101Sstever@eecs.umich.edu port.cxx_decl(code) 5474380Sbinkertn@umich.edu 5484380Sbinkertn@umich.edu code.dedent() 5494380Sbinkertn@umich.edu code('};') 5503101Sstever@eecs.umich.edu 5514380Sbinkertn@umich.edu code() 5524380Sbinkertn@umich.edu code('#endif // __PARAMS__${cls}__') 5534380Sbinkertn@umich.edu return code 5543101Sstever@eecs.umich.edu 5553101Sstever@eecs.umich.edu 5563101Sstever@eecs.umich.edu 5573101Sstever@eecs.umich.edu# The SimObject class is the root of the special hierarchy. Most of 5584762Snate@binkert.org# the code in this class deals with the configuration hierarchy itself 5593101Sstever@eecs.umich.edu# (parent/child node relationships). 5603101Sstever@eecs.umich.educlass SimObject(object): 5613101Sstever@eecs.umich.edu # Specify metaclass. Any class inheriting from SimObject will 5623101Sstever@eecs.umich.edu # get this metaclass. 5633101Sstever@eecs.umich.edu __metaclass__ = MetaSimObject 5643101Sstever@eecs.umich.edu type = 'SimObject' 5653101Sstever@eecs.umich.edu abstract = True 5663101Sstever@eecs.umich.edu 5673101Sstever@eecs.umich.edu @classmethod 5683101Sstever@eecs.umich.edu def export_method_cxx_predecls(cls, code): 5693101Sstever@eecs.umich.edu code(''' 5703101Sstever@eecs.umich.edu#include <Python.h> 5713101Sstever@eecs.umich.edu 5723101Sstever@eecs.umich.edu#include "sim/serialize.hh" 5733101Sstever@eecs.umich.edu#include "sim/sim_object.hh" 5743101Sstever@eecs.umich.edu''') 5753101Sstever@eecs.umich.edu 5763101Sstever@eecs.umich.edu @classmethod 5773101Sstever@eecs.umich.edu def export_method_swig_predecls(cls, code): 5783101Sstever@eecs.umich.edu code(''' 5794380Sbinkertn@umich.edu%include <std_string.i> 5803101Sstever@eecs.umich.edu''') 5813101Sstever@eecs.umich.edu 5824762Snate@binkert.org @classmethod 5834762Snate@binkert.org def export_methods(cls, code): 5844762Snate@binkert.org code(''' 5854762Snate@binkert.org enum State { 5864380Sbinkertn@umich.edu Running, 5874380Sbinkertn@umich.edu Draining, 5883101Sstever@eecs.umich.edu Drained 5893932Sbinkertn@umich.edu }; 5903932Sbinkertn@umich.edu 5913932Sbinkertn@umich.edu void init(); 5923932Sbinkertn@umich.edu void loadState(Checkpoint *cp); 5933932Sbinkertn@umich.edu void initState(); 5943932Sbinkertn@umich.edu void regStats(); 5953932Sbinkertn@umich.edu void regFormulas(); 5963932Sbinkertn@umich.edu void resetStats(); 5973932Sbinkertn@umich.edu void startup(); 5983932Sbinkertn@umich.edu 5993932Sbinkertn@umich.edu unsigned int drain(Event *drain_event); 6003932Sbinkertn@umich.edu void resume(); 6013932Sbinkertn@umich.edu void switchOut(); 6023885Sbinkertn@umich.edu void takeOverFrom(BaseCPU *cpu); 6033932Sbinkertn@umich.edu''') 6043932Sbinkertn@umich.edu 6053885Sbinkertn@umich.edu # Initialize new instance. For objects with SimObject-valued 6063932Sbinkertn@umich.edu # children, we need to recursively clone the classes represented 6073932Sbinkertn@umich.edu # by those param values as well in a consistent "deep copy"-style 6083932Sbinkertn@umich.edu # fashion. That is, we want to make sure that each instance is 6093932Sbinkertn@umich.edu # cloned only once, and that if there are multiple references to 6103932Sbinkertn@umich.edu # the same original object, we end up with the corresponding 6113932Sbinkertn@umich.edu # cloned references all pointing to the same cloned instance. 6123932Sbinkertn@umich.edu def __init__(self, **kwargs): 6133932Sbinkertn@umich.edu ancestor = kwargs.get('_ancestor') 6143932Sbinkertn@umich.edu memo_dict = kwargs.get('_memo') 6153932Sbinkertn@umich.edu if memo_dict is None: 6163932Sbinkertn@umich.edu # prepare to memoize any recursively instantiated objects 6173932Sbinkertn@umich.edu memo_dict = {} 6183932Sbinkertn@umich.edu elif ancestor: 6193932Sbinkertn@umich.edu # memoize me now to avoid problems with recursive calls 6203932Sbinkertn@umich.edu memo_dict[ancestor] = self 6213932Sbinkertn@umich.edu 6223932Sbinkertn@umich.edu if not ancestor: 6233932Sbinkertn@umich.edu ancestor = self.__class__ 6243885Sbinkertn@umich.edu ancestor._instantiated = True 6253885Sbinkertn@umich.edu 6263885Sbinkertn@umich.edu # initialize required attributes 6273885Sbinkertn@umich.edu self._parent = None 6284762Snate@binkert.org self._name = None 6294762Snate@binkert.org self._ccObject = None # pointer to C++ object 6304762Snate@binkert.org self._ccParams = None 6313885Sbinkertn@umich.edu self._instantiated = False # really "cloned" 6323932Sbinkertn@umich.edu 6333885Sbinkertn@umich.edu # Clone children specified at class level. No need for a 6344762Snate@binkert.org # multidict here since we will be cloning everything. 6354762Snate@binkert.org # Do children before parameter values so that children that 6364762Snate@binkert.org # are also param values get cloned properly. 6374762Snate@binkert.org self._children = {} 6384762Snate@binkert.org for key,val in ancestor._children.iteritems(): 6394762Snate@binkert.org self.add_child(key, val(_memo=memo_dict)) 6404762Snate@binkert.org 6414762Snate@binkert.org # Inherit parameter values from class using multidict so 6424762Snate@binkert.org # individual value settings can be overridden but we still 6434762Snate@binkert.org # inherit late changes to non-overridden class values. 6444762Snate@binkert.org self._values = multidict(ancestor._values) 6454762Snate@binkert.org # clone SimObject-valued parameters 6464762Snate@binkert.org for key,val in ancestor._values.iteritems(): 6474762Snate@binkert.org val = tryAsSimObjectOrVector(val) 6484762Snate@binkert.org if val is not None: 6494762Snate@binkert.org self._values[key] = val(_memo=memo_dict) 6504762Snate@binkert.org 6514762Snate@binkert.org # clone port references. no need to use a multidict here 6524762Snate@binkert.org # since we will be creating new references for all ports. 6534762Snate@binkert.org self._port_refs = {} 6544762Snate@binkert.org for key,val in ancestor._port_refs.iteritems(): 6554762Snate@binkert.org self._port_refs[key] = val.clone(self, memo_dict) 6564762Snate@binkert.org # apply attribute assignments from keyword args, if any 6574762Snate@binkert.org for key,val in kwargs.iteritems(): 6584762Snate@binkert.org setattr(self, key, val) 6594762Snate@binkert.org 6603885Sbinkertn@umich.edu # "Clone" the current instance by creating another instance of 6614762Snate@binkert.org # this instance's class, but that inherits its parameter values 6623885Sbinkertn@umich.edu # and port mappings from the current instance. If we're in a 6633885Sbinkertn@umich.edu # "deep copy" recursive clone, check the _memo dict to see if 6643932Sbinkertn@umich.edu # we've already cloned this instance. 6653885Sbinkertn@umich.edu def __call__(self, **kwargs): 6663101Sstever@eecs.umich.edu memo_dict = kwargs.get('_memo') 6673101Sstever@eecs.umich.edu if memo_dict is None: 6683101Sstever@eecs.umich.edu # no memo_dict: must be top-level clone operation. 6693101Sstever@eecs.umich.edu # this is only allowed at the root of a hierarchy 6703101Sstever@eecs.umich.edu if self._parent: 6713101Sstever@eecs.umich.edu raise RuntimeError, "attempt to clone object %s " \ 6723101Sstever@eecs.umich.edu "not at the root of a tree (parent = %s)" \ 6733101Sstever@eecs.umich.edu % (self, self._parent) 6743101Sstever@eecs.umich.edu # create a new dict and use that. 6753101Sstever@eecs.umich.edu memo_dict = {} 6763101Sstever@eecs.umich.edu kwargs['_memo'] = memo_dict 6773101Sstever@eecs.umich.edu elif memo_dict.has_key(self): 6783101Sstever@eecs.umich.edu # clone already done & memoized 6793101Sstever@eecs.umich.edu return memo_dict[self] 6804762Snate@binkert.org return self.__class__(_ancestor = self, **kwargs) 6813101Sstever@eecs.umich.edu 6825033Smilesck@eecs.umich.edu def _get_port_ref(self, attr): 6834762Snate@binkert.org # Return reference that can be assigned to another port 6844762Snate@binkert.org # via __setattr__. There is only ever one reference 6854762Snate@binkert.org # object per port, but we create them lazily here. 6864762Snate@binkert.org ref = self._port_refs.get(attr) 6874762Snate@binkert.org if not ref: 6884762Snate@binkert.org ref = self._ports[attr].makeRef(self) 6894762Snate@binkert.org self._port_refs[attr] = ref 6903101Sstever@eecs.umich.edu return ref 6913101Sstever@eecs.umich.edu 6923101Sstever@eecs.umich.edu def __getattr__(self, attr): 6933101Sstever@eecs.umich.edu if self._ports.has_key(attr): 6943101Sstever@eecs.umich.edu return self._get_port_ref(attr) 6953101Sstever@eecs.umich.edu 6963101Sstever@eecs.umich.edu if self._values.has_key(attr): 6973101Sstever@eecs.umich.edu return self._values[attr] 6983101Sstever@eecs.umich.edu 6993101Sstever@eecs.umich.edu if self._children.has_key(attr): 7003101Sstever@eecs.umich.edu return self._children[attr] 7013101Sstever@eecs.umich.edu 7023101Sstever@eecs.umich.edu # If the attribute exists on the C++ object, transparently 7033101Sstever@eecs.umich.edu # forward the reference there. This is typically used for 7043101Sstever@eecs.umich.edu # SWIG-wrapped methods such as init(), regStats(), 7053101Sstever@eecs.umich.edu # regFormulas(), resetStats(), startup(), drain(), and 7063101Sstever@eecs.umich.edu # resume(). 7073101Sstever@eecs.umich.edu if self._ccObject and hasattr(self._ccObject, attr): 7083101Sstever@eecs.umich.edu return getattr(self._ccObject, attr) 7093101Sstever@eecs.umich.edu 7104762Snate@binkert.org raise AttributeError, "object '%s' has no attribute '%s'" \ 7113101Sstever@eecs.umich.edu % (self.__class__.__name__, attr) 7123101Sstever@eecs.umich.edu 7133101Sstever@eecs.umich.edu # Set attribute (called on foo.attr = value when foo is an 7144762Snate@binkert.org # instance of class cls). 7154762Snate@binkert.org def __setattr__(self, attr, value): 7164762Snate@binkert.org # normal processing for private attributes 7173101Sstever@eecs.umich.edu if attr.startswith('_'): 7183101Sstever@eecs.umich.edu object.__setattr__(self, attr, value) 7193101Sstever@eecs.umich.edu return 7203101Sstever@eecs.umich.edu 7214762Snate@binkert.org if self._ports.has_key(attr): 7224762Snate@binkert.org # set up port connection 7234762Snate@binkert.org self._get_port_ref(attr).connect(value) 7244762Snate@binkert.org return 7254762Snate@binkert.org 7264762Snate@binkert.org if isSimObjectOrSequence(value) and self._instantiated: 7274762Snate@binkert.org raise RuntimeError, \ 7284762Snate@binkert.org "cannot set SimObject parameter '%s' after\n" \ 7294762Snate@binkert.org " instance been cloned %s" % (attr, `self`) 7304762Snate@binkert.org 7314762Snate@binkert.org param = self._params.get(attr) 7324762Snate@binkert.org if param: 7334762Snate@binkert.org try: 7344762Snate@binkert.org value = param.convert(value) 7354762Snate@binkert.org except Exception, e: 7364762Snate@binkert.org msg = "%s\nError setting param %s.%s to %s\n" % \ 7374762Snate@binkert.org (e, self.__class__.__name__, attr, value) 7384762Snate@binkert.org e.args = (msg, ) 7394762Snate@binkert.org raise 7404762Snate@binkert.org self._values[attr] = value 7414762Snate@binkert.org # implicitly parent unparented objects assigned as params 7424762Snate@binkert.org if isSimObjectOrVector(value) and not value.has_parent(): 7434762Snate@binkert.org self.add_child(attr, value) 7444762Snate@binkert.org return 7454762Snate@binkert.org 7463101Sstever@eecs.umich.edu # if RHS is a SimObject, it's an implicit child assignment 7473101Sstever@eecs.umich.edu if isSimObjectOrSequence(value): 7483101Sstever@eecs.umich.edu self.add_child(attr, value) 7493101Sstever@eecs.umich.edu return 7503101Sstever@eecs.umich.edu 7513101Sstever@eecs.umich.edu # no valid assignment... raise exception 7523101Sstever@eecs.umich.edu raise AttributeError, "Class %s has no parameter %s" \ 7533101Sstever@eecs.umich.edu % (self.__class__.__name__, attr) 7543101Sstever@eecs.umich.edu 7553101Sstever@eecs.umich.edu 7563101Sstever@eecs.umich.edu # this hack allows tacking a '[0]' onto parameters that may or may 7573101Sstever@eecs.umich.edu # not be vectors, and always getting the first element (e.g. cpus) 7584762Snate@binkert.org def __getitem__(self, key): 7594762Snate@binkert.org if key == 0: 7604762Snate@binkert.org return self 7613101Sstever@eecs.umich.edu raise TypeError, "Non-zero index '%s' to SimObject" % key 7623101Sstever@eecs.umich.edu 7633101Sstever@eecs.umich.edu # Also implemented by SimObjectVector 7643101Sstever@eecs.umich.edu def clear_parent(self, old_parent): 7653101Sstever@eecs.umich.edu assert self._parent is old_parent 7663101Sstever@eecs.umich.edu self._parent = None 7674167Sbinkertn@umich.edu 7683101Sstever@eecs.umich.edu # Also implemented by SimObjectVector 7693101Sstever@eecs.umich.edu def set_parent(self, parent, name): 7704762Snate@binkert.org self._parent = parent 7713101Sstever@eecs.umich.edu self._name = name 7724167Sbinkertn@umich.edu 7734762Snate@binkert.org # Also implemented by SimObjectVector 7744762Snate@binkert.org def get_name(self): 7754762Snate@binkert.org return self._name 7764167Sbinkertn@umich.edu 7773101Sstever@eecs.umich.edu # Also implemented by SimObjectVector 7784167Sbinkertn@umich.edu def has_parent(self): 7794167Sbinkertn@umich.edu return self._parent is not None 7804167Sbinkertn@umich.edu 7814167Sbinkertn@umich.edu # clear out child with given name. This code is not likely to be exercised. 7824167Sbinkertn@umich.edu # See comment in add_child. 7834167Sbinkertn@umich.edu def clear_child(self, name): 7844167Sbinkertn@umich.edu child = self._children[name] 7854167Sbinkertn@umich.edu child.clear_parent(self) 7864167Sbinkertn@umich.edu del self._children[name] 7874167Sbinkertn@umich.edu 7884167Sbinkertn@umich.edu # Add a new child to this object. 7894167Sbinkertn@umich.edu def add_child(self, name, child): 7903101Sstever@eecs.umich.edu child = coerceSimObjectOrVector(child) 7913101Sstever@eecs.umich.edu if child.has_parent(): 7923101Sstever@eecs.umich.edu print "warning: add_child('%s'): child '%s' already has parent" % \ 7933101Sstever@eecs.umich.edu (name, child.get_name()) 7943101Sstever@eecs.umich.edu if self._children.has_key(name): 7953101Sstever@eecs.umich.edu # This code path had an undiscovered bug that would make it fail 7963101Sstever@eecs.umich.edu # at runtime. It had been here for a long time and was only 7973101Sstever@eecs.umich.edu # exposed by a buggy script. Changes here will probably not be 7984762Snate@binkert.org # exercised without specialized testing. 7994762Snate@binkert.org self.clear_child(name) 8004762Snate@binkert.org child.set_parent(self, name) 8014762Snate@binkert.org self._children[name] = child 8024762Snate@binkert.org 8034762Snate@binkert.org # Take SimObject-valued parameters that haven't been explicitly 8044762Snate@binkert.org # assigned as children and make them children of the object that 8053101Sstever@eecs.umich.edu # they were assigned to as a parameter value. This guarantees 8063101Sstever@eecs.umich.edu # that when we instantiate all the parameter objects we're still 8074762Snate@binkert.org # inside the configuration hierarchy. 8083101Sstever@eecs.umich.edu def adoptOrphanParams(self): 8094167Sbinkertn@umich.edu for key,val in self._values.iteritems(): 8103101Sstever@eecs.umich.edu if not isSimObjectVector(val) and isSimObjectSequence(val): 8114167Sbinkertn@umich.edu # need to convert raw SimObject sequences to 8124167Sbinkertn@umich.edu # SimObjectVector class so we can call has_parent() 8134167Sbinkertn@umich.edu val = SimObjectVector(val) 8144167Sbinkertn@umich.edu self._values[key] = val 8154167Sbinkertn@umich.edu if isSimObjectOrVector(val) and not val.has_parent(): 8164167Sbinkertn@umich.edu print "warning: %s adopting orphan SimObject param '%s'" \ 8174167Sbinkertn@umich.edu % (self, key) 8184167Sbinkertn@umich.edu self.add_child(key, val) 8194167Sbinkertn@umich.edu 8204167Sbinkertn@umich.edu def path(self): 8214167Sbinkertn@umich.edu if not self._parent: 8224167Sbinkertn@umich.edu return '<orphan %s>' % self.__class__ 8233101Sstever@eecs.umich.edu ppath = self._parent.path() 8243101Sstever@eecs.umich.edu if ppath == 'root': 8253101Sstever@eecs.umich.edu return self._name 8263101Sstever@eecs.umich.edu return ppath + "." + self._name 8273101Sstever@eecs.umich.edu 8283101Sstever@eecs.umich.edu def __str__(self): 8293101Sstever@eecs.umich.edu return self.path() 8303101Sstever@eecs.umich.edu 8314167Sbinkertn@umich.edu def ini_str(self): 8324762Snate@binkert.org return self.path() 8334762Snate@binkert.org 8344762Snate@binkert.org def find_any(self, ptype): 8354762Snate@binkert.org if isinstance(self, ptype): 8364762Snate@binkert.org return self, True 8374762Snate@binkert.org 8384762Snate@binkert.org found_obj = None 8393101Sstever@eecs.umich.edu for child in self._children.itervalues(): 8404762Snate@binkert.org if isinstance(child, ptype): 8413101Sstever@eecs.umich.edu if found_obj != None and child != found_obj: 8423101Sstever@eecs.umich.edu raise AttributeError, \ 8433101Sstever@eecs.umich.edu 'parent.any matched more than one: %s %s' % \ 8443101Sstever@eecs.umich.edu (found_obj.path, child.path) 8453101Sstever@eecs.umich.edu found_obj = child 8463101Sstever@eecs.umich.edu # search param space 8473101Sstever@eecs.umich.edu for pname,pdesc in self._params.iteritems(): 8484762Snate@binkert.org if issubclass(pdesc.ptype, ptype): 8493101Sstever@eecs.umich.edu match_obj = self._values[pname] 8503101Sstever@eecs.umich.edu if found_obj != None and found_obj != match_obj: 8514167Sbinkertn@umich.edu raise AttributeError, \ 8524167Sbinkertn@umich.edu 'parent.any matched more than one: %s and %s' % (found_obj.path, match_obj.path) 8534167Sbinkertn@umich.edu found_obj = match_obj 8544167Sbinkertn@umich.edu return found_obj, found_obj != None 8554167Sbinkertn@umich.edu 8564167Sbinkertn@umich.edu def find_all(self, ptype): 8574167Sbinkertn@umich.edu all = {} 8584167Sbinkertn@umich.edu # search children 8594167Sbinkertn@umich.edu for child in self._children.itervalues(): 8604167Sbinkertn@umich.edu if isinstance(child, ptype) and not isproxy(child) and \ 8614167Sbinkertn@umich.edu not isNullPointer(child): 8624167Sbinkertn@umich.edu all[child] = True 8633101Sstever@eecs.umich.edu if isSimObject(child): 8643101Sstever@eecs.umich.edu # also add results from the child itself 8653101Sstever@eecs.umich.edu child_all, done = child.find_all(ptype) 8663101Sstever@eecs.umich.edu all.update(dict(zip(child_all, [done] * len(child_all)))) 8673101Sstever@eecs.umich.edu # search param space 8683101Sstever@eecs.umich.edu for pname,pdesc in self._params.iteritems(): 8693101Sstever@eecs.umich.edu if issubclass(pdesc.ptype, ptype): 8703101Sstever@eecs.umich.edu match_obj = self._values[pname] 8714762Snate@binkert.org if not isproxy(match_obj) and not isNullPointer(match_obj): 8724762Snate@binkert.org all[match_obj] = True 8734762Snate@binkert.org return all.keys(), True 8743101Sstever@eecs.umich.edu 8753101Sstever@eecs.umich.edu def unproxy(self, base): 8763101Sstever@eecs.umich.edu return self 8773101Sstever@eecs.umich.edu 8783101Sstever@eecs.umich.edu def unproxyParams(self): 8793101Sstever@eecs.umich.edu for param in self._params.iterkeys(): 8804167Sbinkertn@umich.edu value = self._values.get(param) 8814167Sbinkertn@umich.edu if value != None and isproxy(value): 8823101Sstever@eecs.umich.edu try: 8833101Sstever@eecs.umich.edu value = value.unproxy(self) 8843101Sstever@eecs.umich.edu except: 8853101Sstever@eecs.umich.edu print "Error in unproxying param '%s' of %s" % \ 8863101Sstever@eecs.umich.edu (param, self.path()) 8874762Snate@binkert.org raise 8884167Sbinkertn@umich.edu setattr(self, param, value) 8894167Sbinkertn@umich.edu 8904167Sbinkertn@umich.edu # Unproxy ports in sorted order so that 'append' operations on 8914762Snate@binkert.org # vector ports are done in a deterministic fashion. 8924762Snate@binkert.org port_names = self._ports.keys() 8934762Snate@binkert.org port_names.sort() 8944762Snate@binkert.org for port_name in port_names: 8954762Snate@binkert.org port = self._port_refs.get(port_name) 8963101Sstever@eecs.umich.edu if port != None: 8973101Sstever@eecs.umich.edu port.unproxy(self) 8983101Sstever@eecs.umich.edu 8995469Snate@binkert.org def print_ini(self, ini_file): 9004167Sbinkertn@umich.edu print >>ini_file, '[' + self.path() + ']' # .ini section header 9013102Sstever@eecs.umich.edu 9023101Sstever@eecs.umich.edu instanceDict[self.path()] = self 9033101Sstever@eecs.umich.edu 9043101Sstever@eecs.umich.edu if hasattr(self, 'type'): 9053101Sstever@eecs.umich.edu print >>ini_file, 'type=%s' % self.type 9063101Sstever@eecs.umich.edu 9074762Snate@binkert.org if len(self._children.keys()): 9084167Sbinkertn@umich.edu print >>ini_file, 'children=%s' % \ 9095468Snate@binkert.org ' '.join(self._children[n].get_name() \ 9105468Snate@binkert.org for n in sorted(self._children.keys())) 9115468Snate@binkert.org 9124167Sbinkertn@umich.edu for param in sorted(self._params.keys()): 9134762Snate@binkert.org value = self._values.get(param) 9144762Snate@binkert.org if value != None: 9154762Snate@binkert.org print >>ini_file, '%s=%s' % (param, 9164762Snate@binkert.org self._values[param].ini_str()) 9174762Snate@binkert.org 9183101Sstever@eecs.umich.edu for port_name in sorted(self._ports.keys()): 9193101Sstever@eecs.umich.edu port = self._port_refs.get(port_name, None) 9203101Sstever@eecs.umich.edu if port != None: 9213101Sstever@eecs.umich.edu print >>ini_file, '%s=%s' % (port_name, port.ini_str()) 9223101Sstever@eecs.umich.edu 9233102Sstever@eecs.umich.edu print >>ini_file # blank line between objects 9243102Sstever@eecs.umich.edu 9253102Sstever@eecs.umich.edu # generate a tree of dictionaries expressing all the parameters in the 9263102Sstever@eecs.umich.edu # instantiated system for use by scripts that want to do power, thermal 9273102Sstever@eecs.umich.edu # visualization, and other similar tasks 9283102Sstever@eecs.umich.edu def get_config_as_dict(self): 9293102Sstever@eecs.umich.edu d = attrdict() 9303102Sstever@eecs.umich.edu if hasattr(self, 'type'): 9313102Sstever@eecs.umich.edu d.type = self.type 9323102Sstever@eecs.umich.edu if hasattr(self, 'cxx_class'): 9333102Sstever@eecs.umich.edu d.cxx_class = self.cxx_class 9343102Sstever@eecs.umich.edu # Add the name and path of this object to be able to link to 9353102Sstever@eecs.umich.edu # the stats 9363102Sstever@eecs.umich.edu d.name = self.get_name() 9373102Sstever@eecs.umich.edu d.path = self.path() 9383102Sstever@eecs.umich.edu 9393102Sstever@eecs.umich.edu for param in sorted(self._params.keys()): 9403102Sstever@eecs.umich.edu value = self._values.get(param) 9413102Sstever@eecs.umich.edu if value != None: 9423102Sstever@eecs.umich.edu try: 9433102Sstever@eecs.umich.edu # Use native type for those supported by JSON and 9444762Snate@binkert.org # strings for everything else. skipkeys=True seems 9453102Sstever@eecs.umich.edu # to not work as well as one would hope 9463102Sstever@eecs.umich.edu if type(self._values[param].value) in \ 9473102Sstever@eecs.umich.edu [str, unicode, int, long, float, bool, None]: 9484762Snate@binkert.org d[param] = self._values[param].value 9494762Snate@binkert.org else: 9504762Snate@binkert.org d[param] = str(self._values[param]) 9513102Sstever@eecs.umich.edu 9523102Sstever@eecs.umich.edu except AttributeError: 9533102Sstever@eecs.umich.edu pass 9543102Sstever@eecs.umich.edu 9553102Sstever@eecs.umich.edu for n in sorted(self._children.keys()): 9563102Sstever@eecs.umich.edu child = self._children[n] 9573101Sstever@eecs.umich.edu # Use the name of the attribute (and not get_name()) as 9583101Sstever@eecs.umich.edu # the key in the JSON dictionary to capture the hierarchy 9593101Sstever@eecs.umich.edu # in the Python code that assembled this system 9603101Sstever@eecs.umich.edu d[n] = child.get_config_as_dict() 9613101Sstever@eecs.umich.edu 9623101Sstever@eecs.umich.edu for port_name in sorted(self._ports.keys()): 9633101Sstever@eecs.umich.edu port = self._port_refs.get(port_name, None) 9643101Sstever@eecs.umich.edu if port != None: 9653101Sstever@eecs.umich.edu # Represent each port with a dictionary containing the 9663101Sstever@eecs.umich.edu # prominent attributes 9673101Sstever@eecs.umich.edu d[port_name] = port.get_config_as_dict() 9683101Sstever@eecs.umich.edu 9693101Sstever@eecs.umich.edu return d 9703101Sstever@eecs.umich.edu 9713101Sstever@eecs.umich.edu def getCCParams(self): 9723101Sstever@eecs.umich.edu if self._ccParams: 9733101Sstever@eecs.umich.edu return self._ccParams 9743105Sstever@eecs.umich.edu 9753105Sstever@eecs.umich.edu cc_params_struct = getattr(m5.internal.params, '%sParams' % self.type) 9763101Sstever@eecs.umich.edu cc_params = cc_params_struct() 9773101Sstever@eecs.umich.edu cc_params.pyobj = self 9783101Sstever@eecs.umich.edu cc_params.name = str(self) 9793101Sstever@eecs.umich.edu 9803105Sstever@eecs.umich.edu param_names = self._params.keys() 9813101Sstever@eecs.umich.edu param_names.sort() 9823103Sstever@eecs.umich.edu for param in param_names: 9833105Sstever@eecs.umich.edu value = self._values.get(param) 9843103Sstever@eecs.umich.edu if value is None: 9853105Sstever@eecs.umich.edu fatal("%s.%s without default or user set value", 9863105Sstever@eecs.umich.edu self.path(), param) 9873105Sstever@eecs.umich.edu 9883105Sstever@eecs.umich.edu value = value.getValue() 9893105Sstever@eecs.umich.edu if isinstance(self._params[param], VectorParamDesc): 9903105Sstever@eecs.umich.edu assert isinstance(value, list) 9913105Sstever@eecs.umich.edu vec = getattr(cc_params, param) 9923105Sstever@eecs.umich.edu assert not len(vec) 9933105Sstever@eecs.umich.edu for v in value: 9943105Sstever@eecs.umich.edu vec.append(v) 9953105Sstever@eecs.umich.edu else: 9963105Sstever@eecs.umich.edu setattr(cc_params, param, value) 9973105Sstever@eecs.umich.edu 9983109Sstever@eecs.umich.edu port_names = self._ports.keys() 9993105Sstever@eecs.umich.edu port_names.sort() 10003105Sstever@eecs.umich.edu for port_name in port_names: 10013105Sstever@eecs.umich.edu port = self._port_refs.get(port_name, None) 10023105Sstever@eecs.umich.edu if port != None: 10033105Sstever@eecs.umich.edu port_count = len(port) 10043105Sstever@eecs.umich.edu else: 10053105Sstever@eecs.umich.edu port_count = 0 10063105Sstever@eecs.umich.edu setattr(cc_params, 'port_' + port_name + '_connection_count', 10073101Sstever@eecs.umich.edu port_count) 10083109Sstever@eecs.umich.edu self._ccParams = cc_params 10093109Sstever@eecs.umich.edu return self._ccParams 10103109Sstever@eecs.umich.edu 10113109Sstever@eecs.umich.edu # Get C++ object corresponding to this object, calling C++ if 10123109Sstever@eecs.umich.edu # necessary to construct it. Does *not* recursively create 10133109Sstever@eecs.umich.edu # children. 10143109Sstever@eecs.umich.edu def getCCObject(self): 10153109Sstever@eecs.umich.edu if not self._ccObject: 10163109Sstever@eecs.umich.edu # Make sure this object is in the configuration hierarchy 10173101Sstever@eecs.umich.edu if not self._parent and not isRoot(self): 10183105Sstever@eecs.umich.edu raise RuntimeError, "Attempt to instantiate orphan node" 10193105Sstever@eecs.umich.edu # Cycles in the configuration hierarchy are not supported. This 10203105Sstever@eecs.umich.edu # will catch the resulting recursion and stop. 10213101Sstever@eecs.umich.edu self._ccObject = -1 10223105Sstever@eecs.umich.edu params = self.getCCParams() 10233105Sstever@eecs.umich.edu self._ccObject = params.create() 10243101Sstever@eecs.umich.edu elif self._ccObject == -1: 10253105Sstever@eecs.umich.edu raise RuntimeError, "%s: Cycle found in configuration hierarchy." \ 10263179Sstever@eecs.umich.edu % self.path() 10273105Sstever@eecs.umich.edu return self._ccObject 10283105Sstever@eecs.umich.edu 10293101Sstever@eecs.umich.edu def descendants(self): 10303101Sstever@eecs.umich.edu yield self 10313105Sstever@eecs.umich.edu for child in self._children.itervalues(): 10323105Sstever@eecs.umich.edu for obj in child.descendants(): 10333105Sstever@eecs.umich.edu yield obj 10343105Sstever@eecs.umich.edu 10353105Sstever@eecs.umich.edu # Call C++ to create C++ object corresponding to this object 10363105Sstever@eecs.umich.edu def createCCObject(self): 10373105Sstever@eecs.umich.edu self.getCCParams() 10383105Sstever@eecs.umich.edu self.getCCObject() # force creation 10393105Sstever@eecs.umich.edu 10403105Sstever@eecs.umich.edu def getValue(self): 10413105Sstever@eecs.umich.edu return self.getCCObject() 10423101Sstever@eecs.umich.edu 10433101Sstever@eecs.umich.edu # Create C++ port connections corresponding to the connections in 10444859Snate@binkert.org # _port_refs 10454762Snate@binkert.org def connectPorts(self): 10463101Sstever@eecs.umich.edu for portRef in self._port_refs.itervalues(): 10473101Sstever@eecs.umich.edu portRef.ccConnect() 10483101Sstever@eecs.umich.edu 10494859Snate@binkert.org def getMemoryMode(self): 10504859Snate@binkert.org if not isinstance(self, m5.objects.System): 10513101Sstever@eecs.umich.edu return None 10523101Sstever@eecs.umich.edu 10533101Sstever@eecs.umich.edu return self._ccObject.getMemoryMode() 10543105Sstever@eecs.umich.edu 10553105Sstever@eecs.umich.edu def changeTiming(self, mode): 10563105Sstever@eecs.umich.edu if isinstance(self, m5.objects.System): 10573105Sstever@eecs.umich.edu # i don't know if there's a better way to do this - calling 10583105Sstever@eecs.umich.edu # setMemoryMode directly from self._ccObject results in calling 10593105Sstever@eecs.umich.edu # SimObject::setMemoryMode, not the System::setMemoryMode 10603105Sstever@eecs.umich.edu self._ccObject.setMemoryMode(mode) 10613105Sstever@eecs.umich.edu 10623105Sstever@eecs.umich.edu def takeOverFrom(self, old_cpu): 10633105Sstever@eecs.umich.edu self._ccObject.takeOverFrom(old_cpu._ccObject) 10643105Sstever@eecs.umich.edu 10653105Sstever@eecs.umich.edu# Function to provide to C++ so it can look up instances based on paths 10663105Sstever@eecs.umich.edudef resolveSimObject(name): 10673105Sstever@eecs.umich.edu obj = instanceDict[name] 10683105Sstever@eecs.umich.edu return obj.getCCObject() 10693105Sstever@eecs.umich.edu 10703105Sstever@eecs.umich.edudef isSimObject(value): 10713105Sstever@eecs.umich.edu return isinstance(value, SimObject) 10723105Sstever@eecs.umich.edu 10733109Sstever@eecs.umich.edudef isSimObjectClass(value): 10743109Sstever@eecs.umich.edu return issubclass(value, SimObject) 10753109Sstever@eecs.umich.edu 10763105Sstever@eecs.umich.edudef isSimObjectVector(value): 10773105Sstever@eecs.umich.edu return isinstance(value, SimObjectVector) 10783105Sstever@eecs.umich.edu 10793105Sstever@eecs.umich.edudef isSimObjectSequence(value): 10803105Sstever@eecs.umich.edu if not isinstance(value, (list, tuple)) or len(value) == 0: 10813105Sstever@eecs.umich.edu return False 10823105Sstever@eecs.umich.edu 10833105Sstever@eecs.umich.edu for val in value: 10843105Sstever@eecs.umich.edu if not isNullPointer(val) and not isSimObject(val): 10853105Sstever@eecs.umich.edu return False 10863105Sstever@eecs.umich.edu 10873105Sstever@eecs.umich.edu return True 10883105Sstever@eecs.umich.edu 10893105Sstever@eecs.umich.edudef isSimObjectOrSequence(value): 10903105Sstever@eecs.umich.edu return isSimObject(value) or isSimObjectSequence(value) 10913105Sstever@eecs.umich.edu 10923105Sstever@eecs.umich.edudef isRoot(obj): 10933105Sstever@eecs.umich.edu from m5.objects import Root 10943105Sstever@eecs.umich.edu return obj and obj is Root.getInstance() 10953105Sstever@eecs.umich.edu 10963105Sstever@eecs.umich.edudef isSimObjectOrVector(value): 10973105Sstever@eecs.umich.edu return isSimObject(value) or isSimObjectVector(value) 10983105Sstever@eecs.umich.edu 10993109Sstever@eecs.umich.edudef tryAsSimObjectOrVector(value): 11003109Sstever@eecs.umich.edu if isSimObjectOrVector(value): 11013109Sstever@eecs.umich.edu return value 11023109Sstever@eecs.umich.edu if isSimObjectSequence(value): 11033109Sstever@eecs.umich.edu return SimObjectVector(value) 11043109Sstever@eecs.umich.edu return None 11053109Sstever@eecs.umich.edu 11063109Sstever@eecs.umich.edudef coerceSimObjectOrVector(value): 11073109Sstever@eecs.umich.edu value = tryAsSimObjectOrVector(value) 11083109Sstever@eecs.umich.edu if value is None: 11093109Sstever@eecs.umich.edu raise TypeError, "SimObject or SimObjectVector expected" 11103109Sstever@eecs.umich.edu return value 11113109Sstever@eecs.umich.edu 11123109Sstever@eecs.umich.edubaseClasses = allClasses.copy() 11133109Sstever@eecs.umich.edubaseInstances = instanceDict.copy() 11143109Sstever@eecs.umich.edu 11153109Sstever@eecs.umich.edudef clear(): 11163109Sstever@eecs.umich.edu global allClasses, instanceDict 11173109Sstever@eecs.umich.edu 11183105Sstever@eecs.umich.edu allClasses = baseClasses.copy() 11193105Sstever@eecs.umich.edu instanceDict = baseInstances.copy() 11203105Sstever@eecs.umich.edu 11213105Sstever@eecs.umich.edu# __all__ defines the list of symbols that get exported when 11223105Sstever@eecs.umich.edu# 'from config import *' is invoked. Try to keep this reasonably 11233105Sstever@eecs.umich.edu# short to avoid polluting other namespaces. 11243105Sstever@eecs.umich.edu__all__ = [ 'SimObject' ] 11253101Sstever@eecs.umich.edu