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