params.py revision 4380
113558Snikos.nikoleris@arm.com# Copyright (c) 2004-2006 The Regents of The University of Michigan
28839Sandreas.hansson@arm.com# All rights reserved.
38839Sandreas.hansson@arm.com#
48839Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without
58839Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are
68839Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright
78839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer;
88839Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright
98839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the
108839Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution;
118839Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its
128839Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from
133101Sstever@eecs.umich.edu# this software without specific prior written permission.
148579Ssteve.reinhardt@amd.com#
153101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
163101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
173101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
183101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
193101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
203101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
213101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
223101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
233101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
243101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
253101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
263101Sstever@eecs.umich.edu#
273101Sstever@eecs.umich.edu# Authors: Steve Reinhardt
283101Sstever@eecs.umich.edu#          Nathan Binkert
293101Sstever@eecs.umich.edu
303101Sstever@eecs.umich.edu#####################################################################
313101Sstever@eecs.umich.edu#
323101Sstever@eecs.umich.edu# Parameter description classes
333101Sstever@eecs.umich.edu#
343101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either
353101Sstever@eecs.umich.edu# a Param or a VectorParam object.  These objects contain the
363101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default
373101Sstever@eecs.umich.edu# value (if any).  The convert() method on these objects is used to
383101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate
393101Sstever@eecs.umich.edu# type.
403101Sstever@eecs.umich.edu#
413101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute
427778Sgblack@eecs.umich.edu# space when the parameter dictionary is initialized (in
438839Sandreas.hansson@arm.com# MetaSimObject._new_param()); after that point they aren't used.
443101Sstever@eecs.umich.edu#
453101Sstever@eecs.umich.edu#####################################################################
463101Sstever@eecs.umich.edu
473101Sstever@eecs.umich.eduimport copy
483101Sstever@eecs.umich.eduimport datetime
493101Sstever@eecs.umich.eduimport inspect
503101Sstever@eecs.umich.eduimport sys
513101Sstever@eecs.umich.eduimport time
523101Sstever@eecs.umich.edu
533101Sstever@eecs.umich.eduimport convert
543101Sstever@eecs.umich.eduimport proxy
553101Sstever@eecs.umich.eduimport ticks
563101Sstever@eecs.umich.edufrom util import *
573101Sstever@eecs.umich.edu
583101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject
593101Sstever@eecs.umich.edu# parameters.
603101Sstever@eecs.umich.educlass ParamValue(object):
613101Sstever@eecs.umich.edu
6212563Sgabeblack@google.com    cxx_predecls = []
6312563Sgabeblack@google.com    swig_predecls = []
643885Sbinkertn@umich.edu
653885Sbinkertn@umich.edu    # default for printing to .ini file is regular string conversion.
664762Snate@binkert.org    # will be overridden in some cases
673885Sbinkertn@umich.edu    def ini_str(self):
683885Sbinkertn@umich.edu        return str(self)
697528Ssteve.reinhardt@amd.com
703885Sbinkertn@umich.edu    # allows us to blithely call unproxy() on things without checking
714380Sbinkertn@umich.edu    # if they're really proxies or not
724167Sbinkertn@umich.edu    def unproxy(self, base):
733102Sstever@eecs.umich.edu        return self
743101Sstever@eecs.umich.edu
754762Snate@binkert.org# Regular parameter description.
764762Snate@binkert.orgclass ParamDesc(object):
774762Snate@binkert.org    def __init__(self, ptype_str, ptype, *args, **kwargs):
784762Snate@binkert.org        self.ptype_str = ptype_str
794762Snate@binkert.org        # remember ptype only if it is provided
804762Snate@binkert.org        if ptype != None:
814762Snate@binkert.org            self.ptype = ptype
824762Snate@binkert.org
834762Snate@binkert.org        if args:
845033Smilesck@eecs.umich.edu            if len(args) == 1:
855033Smilesck@eecs.umich.edu                self.desc = args[0]
865033Smilesck@eecs.umich.edu            elif len(args) == 2:
875033Smilesck@eecs.umich.edu                self.default = args[0]
885033Smilesck@eecs.umich.edu                self.desc = args[1]
895033Smilesck@eecs.umich.edu            else:
905033Smilesck@eecs.umich.edu                raise TypeError, 'too many arguments'
915033Smilesck@eecs.umich.edu
925033Smilesck@eecs.umich.edu        if kwargs.has_key('desc'):
935033Smilesck@eecs.umich.edu            assert(not hasattr(self, 'desc'))
943101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
953101Sstever@eecs.umich.edu            del kwargs['desc']
963101Sstever@eecs.umich.edu
975033Smilesck@eecs.umich.edu        if kwargs.has_key('default'):
9810267SGeoffrey.Blake@arm.com            assert(not hasattr(self, 'default'))
998596Ssteve.reinhardt@amd.com            self.default = kwargs['default']
1008596Ssteve.reinhardt@amd.com            del kwargs['default']
1018596Ssteve.reinhardt@amd.com
1028596Ssteve.reinhardt@amd.com        if kwargs:
1037673Snate@binkert.org            raise TypeError, 'extra unknown kwargs %s' % kwargs
1047673Snate@binkert.org
1057673Snate@binkert.org        if not hasattr(self, 'desc'):
1067673Snate@binkert.org            raise TypeError, 'desc attribute missing'
10711988Sandreas.sandberg@arm.com
10811988Sandreas.sandberg@arm.com    def __getattr__(self, attr):
10911988Sandreas.sandberg@arm.com        if attr == 'ptype':
11011988Sandreas.sandberg@arm.com            try:
1113101Sstever@eecs.umich.edu                ptype = eval(self.ptype_str, objects.__dict__)
1123101Sstever@eecs.umich.edu                if not isinstance(ptype, type):
1133101Sstever@eecs.umich.edu                    raise NameError
1143101Sstever@eecs.umich.edu                self.ptype = ptype
1153101Sstever@eecs.umich.edu                return ptype
11610380SAndrew.Bardsley@arm.com            except NameError:
11710380SAndrew.Bardsley@arm.com                raise TypeError, \
11810380SAndrew.Bardsley@arm.com                      "Param qualifier '%s' is not a type" % self.ptype_str
11910380SAndrew.Bardsley@arm.com        raise AttributeError, "'%s' object has no attribute '%s'" % \
12010380SAndrew.Bardsley@arm.com              (type(self).__name__, attr)
12110380SAndrew.Bardsley@arm.com
12210458Sandreas.hansson@arm.com    def convert(self, value):
12310458Sandreas.hansson@arm.com        if isinstance(value, proxy.BaseProxy):
12410458Sandreas.hansson@arm.com            value.set_param_desc(self)
12510458Sandreas.hansson@arm.com            return value
12610458Sandreas.hansson@arm.com        if not hasattr(self, 'ptype') and isNullPointer(value):
12710458Sandreas.hansson@arm.com            # deferred evaluation of SimObject; continue to defer if
12810458Sandreas.hansson@arm.com            # we're just assigning a null pointer
12910458Sandreas.hansson@arm.com            return value
13010458Sandreas.hansson@arm.com        if isinstance(value, self.ptype):
13110458Sandreas.hansson@arm.com            return value
13210458Sandreas.hansson@arm.com        if isNullPointer(value) and isSimObjectClass(self.ptype):
13310458Sandreas.hansson@arm.com            return value
1343101Sstever@eecs.umich.edu        return self.ptype(value)
1353101Sstever@eecs.umich.edu
1363101Sstever@eecs.umich.edu    def cxx_predecls(self):
1373101Sstever@eecs.umich.edu        return self.ptype.cxx_predecls
1383101Sstever@eecs.umich.edu
13910267SGeoffrey.Blake@arm.com    def swig_predecls(self):
14010267SGeoffrey.Blake@arm.com        return self.ptype.swig_predecls
14110267SGeoffrey.Blake@arm.com
14210267SGeoffrey.Blake@arm.com    def cxx_decl(self):
1433101Sstever@eecs.umich.edu        return '%s %s;' % (self.ptype.cxx_type, self.name)
1443101Sstever@eecs.umich.edu
1453101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
1463101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
1473101Sstever@eecs.umich.edu# single value.
1483101Sstever@eecs.umich.edu
1493101Sstever@eecs.umich.educlass VectorParamValue(list):
1503101Sstever@eecs.umich.edu    def ini_str(self):
1513101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
1523101Sstever@eecs.umich.edu
1533101Sstever@eecs.umich.edu    def unproxy(self, base):
1543101Sstever@eecs.umich.edu        return [v.unproxy(base) for v in self]
1553101Sstever@eecs.umich.edu
1563101Sstever@eecs.umich.educlass SimObjVector(VectorParamValue):
1573101Sstever@eecs.umich.edu    def print_ini(self):
15813663Sandreas.sandberg@arm.com        for v in self:
1593101Sstever@eecs.umich.edu            v.print_ini()
16013675Sandreas.sandberg@arm.com
1613101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
1623101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
1633101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
1643101Sstever@eecs.umich.edu    def convert(self, value):
16513675Sandreas.sandberg@arm.com        if isinstance(value, (list, tuple)):
1663101Sstever@eecs.umich.edu            # list: coerce each element into new list
1673101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
1683101Sstever@eecs.umich.edu            if isSimObjectSequence(tmp_list):
1693101Sstever@eecs.umich.edu                return SimObjVector(tmp_list)
1703101Sstever@eecs.umich.edu            else:
17113663Sandreas.sandberg@arm.com                return VectorParamValue(tmp_list)
1723101Sstever@eecs.umich.edu        else:
1733101Sstever@eecs.umich.edu            # singleton: leave it be (could coerce to a single-element
17413663Sandreas.sandberg@arm.com            # list here, but for some historical reason we don't...
1753101Sstever@eecs.umich.edu            return ParamDesc.convert(self, value)
1763101Sstever@eecs.umich.edu
1773101Sstever@eecs.umich.edu    def cxx_predecls(self):
1785033Smilesck@eecs.umich.edu        return ['#include <vector>'] + self.ptype.cxx_predecls
1796656Snate@binkert.org
1805033Smilesck@eecs.umich.edu    def swig_predecls(self):
1815033Smilesck@eecs.umich.edu        return ['%include "std_vector.i"'] + self.ptype.swig_predecls
1825033Smilesck@eecs.umich.edu
18313663Sandreas.sandberg@arm.com    def cxx_decl(self):
18413663Sandreas.sandberg@arm.com        return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name)
1853101Sstever@eecs.umich.edu
18610267SGeoffrey.Blake@arm.comclass ParamFactory(object):
18710267SGeoffrey.Blake@arm.com    def __init__(self, param_desc_class, ptype_str = None):
18810267SGeoffrey.Blake@arm.com        self.param_desc_class = param_desc_class
18910267SGeoffrey.Blake@arm.com        self.ptype_str = ptype_str
19010267SGeoffrey.Blake@arm.com
19110267SGeoffrey.Blake@arm.com    def __getattr__(self, attr):
19210267SGeoffrey.Blake@arm.com        if self.ptype_str:
19310267SGeoffrey.Blake@arm.com            attr = self.ptype_str + '.' + attr
19410267SGeoffrey.Blake@arm.com        return ParamFactory(self.param_desc_class, attr)
19510267SGeoffrey.Blake@arm.com
19610267SGeoffrey.Blake@arm.com    # E.g., Param.Int(5, "number of widgets")
19710267SGeoffrey.Blake@arm.com    def __call__(self, *args, **kwargs):
19810267SGeoffrey.Blake@arm.com        caller_frame = inspect.currentframe().f_back
1993101Sstever@eecs.umich.edu        ptype = None
2003101Sstever@eecs.umich.edu        try:
2013101Sstever@eecs.umich.edu            ptype = eval(self.ptype_str,
2023101Sstever@eecs.umich.edu                         caller_frame.f_globals, caller_frame.f_locals)
20313699Sandreas.sandberg@arm.com            if not isinstance(ptype, type):
2043101Sstever@eecs.umich.edu                raise TypeError, \
2053101Sstever@eecs.umich.edu                      "Param qualifier is not a type: %s" % ptype
2063101Sstever@eecs.umich.edu        except NameError:
2073101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
2083101Sstever@eecs.umich.edu            # try to resolve it later
2093102Sstever@eecs.umich.edu            pass
2103101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
2113101Sstever@eecs.umich.edu
2123101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
21310267SGeoffrey.Blake@arm.comVectorParam = ParamFactory(VectorParamDesc)
21410267SGeoffrey.Blake@arm.com
21510267SGeoffrey.Blake@arm.com#####################################################################
21610267SGeoffrey.Blake@arm.com#
21710267SGeoffrey.Blake@arm.com# Parameter Types
21810267SGeoffrey.Blake@arm.com#
21910267SGeoffrey.Blake@arm.com# Though native Python types could be used to specify parameter types
2207673Snate@binkert.org# (the 'ptype' field of the Param and VectorParam classes), it's more
2218607Sgblack@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
2227673Snate@binkert.org# over how Python expressions are converted to values (via the
2233101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
22411988Sandreas.sandberg@arm.com# the __str__() conversion method).
22511988Sandreas.sandberg@arm.com#
22611988Sandreas.sandberg@arm.com#####################################################################
2277673Snate@binkert.org
2287673Snate@binkert.org# String-valued parameter.  Just mixin the ParamValue class with the
2293101Sstever@eecs.umich.edu# built-in str class.
2303101Sstever@eecs.umich.educlass String(ParamValue,str):
2313101Sstever@eecs.umich.edu    cxx_type = 'std::string'
2323101Sstever@eecs.umich.edu    cxx_predecls = ['#include <string>']
2333101Sstever@eecs.umich.edu    swig_predecls = ['%include "std_string.i"\n' +
2343101Sstever@eecs.umich.edu                     '%apply const std::string& {std::string *};']
2355033Smilesck@eecs.umich.edu    pass
2365475Snate@binkert.org
23713663Sandreas.sandberg@arm.com# superclass for "numeric" parameter values, to emulate math
23813663Sandreas.sandberg@arm.com# operations in a type-safe way.  e.g., a Latency times an int returns
2395475Snate@binkert.org# a new Latency object.
24010380SAndrew.Bardsley@arm.comclass NumericParamValue(ParamValue):
24110380SAndrew.Bardsley@arm.com    def __str__(self):
24210380SAndrew.Bardsley@arm.com        return str(self.value)
2433101Sstever@eecs.umich.edu
2443101Sstever@eecs.umich.edu    def __float__(self):
2453101Sstever@eecs.umich.edu        return float(self.value)
2464762Snate@binkert.org
2474762Snate@binkert.org    def __long__(self):
2484762Snate@binkert.org        return long(self.value)
2493101Sstever@eecs.umich.edu
25012050Snikos.nikoleris@arm.com    def __int__(self):
25112050Snikos.nikoleris@arm.com        return int(self.value)
25212050Snikos.nikoleris@arm.com
2538459SAli.Saidi@ARM.com    # hook for bounds checking
2548459SAli.Saidi@ARM.com    def _check(self):
25512050Snikos.nikoleris@arm.com        return
2563101Sstever@eecs.umich.edu
2577528Ssteve.reinhardt@amd.com    def __mul__(self, other):
2587528Ssteve.reinhardt@amd.com        newobj = self.__class__(self)
2597528Ssteve.reinhardt@amd.com        newobj.value *= other
2607528Ssteve.reinhardt@amd.com        newobj._check()
2617528Ssteve.reinhardt@amd.com        return newobj
2627528Ssteve.reinhardt@amd.com
2633101Sstever@eecs.umich.edu    __rmul__ = __mul__
2647528Ssteve.reinhardt@amd.com
2657528Ssteve.reinhardt@amd.com    def __div__(self, other):
2667528Ssteve.reinhardt@amd.com        newobj = self.__class__(self)
2677528Ssteve.reinhardt@amd.com        newobj.value /= other
2687528Ssteve.reinhardt@amd.com        newobj._check()
2697528Ssteve.reinhardt@amd.com        return newobj
2707528Ssteve.reinhardt@amd.com
2717528Ssteve.reinhardt@amd.com    def __sub__(self, other):
2727528Ssteve.reinhardt@amd.com        newobj = self.__class__(self)
2737528Ssteve.reinhardt@amd.com        newobj.value -= other
2748321Ssteve.reinhardt@amd.com        newobj._check()
27512194Sgabeblack@google.com        return newobj
2767528Ssteve.reinhardt@amd.com
2777528Ssteve.reinhardt@amd.com# Metaclass for bounds-checked integer parameters.  See CheckedInt.
2787528Ssteve.reinhardt@amd.comclass CheckedIntType(type):
2797528Ssteve.reinhardt@amd.com    def __init__(cls, name, bases, dict):
2807528Ssteve.reinhardt@amd.com        super(CheckedIntType, cls).__init__(name, bases, dict)
2817528Ssteve.reinhardt@amd.com
2827528Ssteve.reinhardt@amd.com        # CheckedInt is an abstract base class, so we actually don't
2837528Ssteve.reinhardt@amd.com        # want to do any processing on it... the rest of this code is
2847528Ssteve.reinhardt@amd.com        # just for classes that derive from CheckedInt.
2857528Ssteve.reinhardt@amd.com        if name == 'CheckedInt':
2867528Ssteve.reinhardt@amd.com            return
2877528Ssteve.reinhardt@amd.com
2887528Ssteve.reinhardt@amd.com        if not cls.cxx_predecls:
2893101Sstever@eecs.umich.edu            # most derived types require this, so we just do it here once
2908664SAli.Saidi@ARM.com            cls.cxx_predecls = ['#include "sim/host.hh"']
2918664SAli.Saidi@ARM.com
2928664SAli.Saidi@ARM.com        if not cls.swig_predecls:
2938664SAli.Saidi@ARM.com            # most derived types require this, so we just do it here once
2948664SAli.Saidi@ARM.com            cls.swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
2958664SAli.Saidi@ARM.com                                 '%import "sim/host.hh"']
2969953Sgeoffrey.blake@arm.com
2979953Sgeoffrey.blake@arm.com        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
2989953Sgeoffrey.blake@arm.com            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
2999953Sgeoffrey.blake@arm.com                panic("CheckedInt subclass %s must define either\n" \
3009953Sgeoffrey.blake@arm.com                      "    'min' and 'max' or 'size' and 'unsigned'\n" \
3019953Sgeoffrey.blake@arm.com                      % name);
3029953Sgeoffrey.blake@arm.com            if cls.unsigned:
3039953Sgeoffrey.blake@arm.com                cls.min = 0
3049953Sgeoffrey.blake@arm.com                cls.max = 2 ** cls.size - 1
3059953Sgeoffrey.blake@arm.com            else:
3069953Sgeoffrey.blake@arm.com                cls.min = -(2 ** (cls.size - 1))
3079953Sgeoffrey.blake@arm.com                cls.max = (2 ** (cls.size - 1)) - 1
3089953Sgeoffrey.blake@arm.com
30910267SGeoffrey.Blake@arm.com# Abstract superclass for bounds-checked integer parameters.  This
31010267SGeoffrey.Blake@arm.com# class is subclassed to generate parameter classes with specific
31110267SGeoffrey.Blake@arm.com# bounds.  Initialization of the min and max bounds is done in the
31210267SGeoffrey.Blake@arm.com# metaclass CheckedIntType.__init__.
31310267SGeoffrey.Blake@arm.comclass CheckedInt(NumericParamValue):
31410267SGeoffrey.Blake@arm.com    __metaclass__ = CheckedIntType
31510267SGeoffrey.Blake@arm.com
31612563Sgabeblack@google.com    def _check(self):
31710267SGeoffrey.Blake@arm.com        if not self.min <= self.value <= self.max:
31810267SGeoffrey.Blake@arm.com            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
31910267SGeoffrey.Blake@arm.com                  (self.min, self.value, self.max)
32010267SGeoffrey.Blake@arm.com
32110267SGeoffrey.Blake@arm.com    def __init__(self, value):
32210267SGeoffrey.Blake@arm.com        if isinstance(value, str):
32310267SGeoffrey.Blake@arm.com            self.value = convert.toInteger(value)
32410267SGeoffrey.Blake@arm.com        elif isinstance(value, (int, long, float, NumericParamValue)):
32510267SGeoffrey.Blake@arm.com            self.value = long(value)
32610267SGeoffrey.Blake@arm.com        else:
32710267SGeoffrey.Blake@arm.com            raise TypeError, "Can't convert object of type %s to CheckedInt" \
32810267SGeoffrey.Blake@arm.com                  % type(value).__name__
3293101Sstever@eecs.umich.edu        self._check()
3303101Sstever@eecs.umich.edu
3313101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
3323101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
3333101Sstever@eecs.umich.edu
3343101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
3353101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
33610364SGeoffrey.Blake@arm.comclass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
33710364SGeoffrey.Blake@arm.comclass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
33810364SGeoffrey.Blake@arm.comclass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
33910364SGeoffrey.Blake@arm.comclass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
3403101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
3414762Snate@binkert.orgclass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
3424762Snate@binkert.org
3434762Snate@binkert.orgclass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
3444762Snate@binkert.orgclass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
3457528Ssteve.reinhardt@amd.comclass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
3464762Snate@binkert.orgclass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
3474762Snate@binkert.org
3484762Snate@binkert.orgclass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
34910267SGeoffrey.Blake@arm.com
35010267SGeoffrey.Blake@arm.comclass Float(ParamValue, float):
35110267SGeoffrey.Blake@arm.com    pass
35210267SGeoffrey.Blake@arm.com
35310267SGeoffrey.Blake@arm.comclass MemorySize(CheckedInt):
35410267SGeoffrey.Blake@arm.com    cxx_type = 'uint64_t'
35510267SGeoffrey.Blake@arm.com    size = 64
35610267SGeoffrey.Blake@arm.com    unsigned = True
35710267SGeoffrey.Blake@arm.com    def __init__(self, value):
35810267SGeoffrey.Blake@arm.com        if isinstance(value, MemorySize):
35910267SGeoffrey.Blake@arm.com            self.value = value.value
36010267SGeoffrey.Blake@arm.com        else:
36110267SGeoffrey.Blake@arm.com            self.value = convert.toMemorySize(value)
36210267SGeoffrey.Blake@arm.com        self._check()
36310267SGeoffrey.Blake@arm.com
36410267SGeoffrey.Blake@arm.comclass MemorySize32(CheckedInt):
36510267SGeoffrey.Blake@arm.com    cxx_type = 'uint32_t'
36610267SGeoffrey.Blake@arm.com    size = 32
36710267SGeoffrey.Blake@arm.com    unsigned = True
36810267SGeoffrey.Blake@arm.com    def __init__(self, value):
36910267SGeoffrey.Blake@arm.com        if isinstance(value, MemorySize):
37010267SGeoffrey.Blake@arm.com            self.value = value.value
37110267SGeoffrey.Blake@arm.com        else:
37210267SGeoffrey.Blake@arm.com            self.value = convert.toMemorySize(value)
37310267SGeoffrey.Blake@arm.com        self._check()
37410267SGeoffrey.Blake@arm.com
37510364SGeoffrey.Blake@arm.comclass Addr(CheckedInt):
37610364SGeoffrey.Blake@arm.com    cxx_type = 'Addr'
37710267SGeoffrey.Blake@arm.com    cxx_predecls = ['#include "targetarch/isa_traits.hh"']
37810267SGeoffrey.Blake@arm.com    size = 64
37910267SGeoffrey.Blake@arm.com    unsigned = True
38010267SGeoffrey.Blake@arm.com    def __init__(self, value):
38110267SGeoffrey.Blake@arm.com        if isinstance(value, Addr):
38210267SGeoffrey.Blake@arm.com            self.value = value.value
3837673Snate@binkert.org        else:
3847673Snate@binkert.org            try:
3857673Snate@binkert.org                self.value = convert.toMemorySize(value)
3863101Sstever@eecs.umich.edu            except TypeError:
38711988Sandreas.sandberg@arm.com                self.value = long(value)
38811988Sandreas.sandberg@arm.com        self._check()
38911988Sandreas.sandberg@arm.com    def __add__(self, other):
39011988Sandreas.sandberg@arm.com        if isinstance(other, Addr):
3917673Snate@binkert.org            return self.value + other.value
3927673Snate@binkert.org        else:
3933101Sstever@eecs.umich.edu            return self.value + other
3943101Sstever@eecs.umich.edu
3953101Sstever@eecs.umich.edu
3963101Sstever@eecs.umich.educlass MetaRange(type):
3973101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
3983101Sstever@eecs.umich.edu        super(MetaRange, cls).__init__(name, bases, dict)
3993101Sstever@eecs.umich.edu        if name == 'Range':
4003101Sstever@eecs.umich.edu            return
4013101Sstever@eecs.umich.edu        cls.cxx_type = 'Range< %s >' % cls.type.cxx_type
4023101Sstever@eecs.umich.edu        cls.cxx_predecls = \
4033101Sstever@eecs.umich.edu                       ['#include "base/range.hh"'] + cls.type.cxx_predecls
4043101Sstever@eecs.umich.edu
4053101Sstever@eecs.umich.educlass Range(ParamValue):
4063101Sstever@eecs.umich.edu    __metaclass__ = MetaRange
4073101Sstever@eecs.umich.edu    type = Int # default; can be overridden in subclasses
4085033Smilesck@eecs.umich.edu    def __init__(self, *args, **kwargs):
4095033Smilesck@eecs.umich.edu        def handle_kwargs(self, kwargs):
4103101Sstever@eecs.umich.edu            if 'end' in kwargs:
4113101Sstever@eecs.umich.edu                self.second = self.type(kwargs.pop('end'))
4123101Sstever@eecs.umich.edu            elif 'size' in kwargs:
4133101Sstever@eecs.umich.edu                self.second = self.first + self.type(kwargs.pop('size')) - 1
4143101Sstever@eecs.umich.edu            else:
4153101Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
4163101Sstever@eecs.umich.edu
4173101Sstever@eecs.umich.edu        if len(args) == 0:
4183101Sstever@eecs.umich.edu            self.first = self.type(kwargs.pop('start'))
4193101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
4203101Sstever@eecs.umich.edu
4213101Sstever@eecs.umich.edu        elif len(args) == 1:
4223101Sstever@eecs.umich.edu            if kwargs:
4233101Sstever@eecs.umich.edu                self.first = self.type(args[0])
4243101Sstever@eecs.umich.edu                handle_kwargs(self, kwargs)
4253101Sstever@eecs.umich.edu            elif isinstance(args[0], Range):
4263101Sstever@eecs.umich.edu                self.first = self.type(args[0].first)
4273101Sstever@eecs.umich.edu                self.second = self.type(args[0].second)
4283101Sstever@eecs.umich.edu            else:
4293101Sstever@eecs.umich.edu                self.first = self.type(0)
4303101Sstever@eecs.umich.edu                self.second = self.type(args[0]) - 1
4313101Sstever@eecs.umich.edu
4323101Sstever@eecs.umich.edu        elif len(args) == 2:
4333101Sstever@eecs.umich.edu            self.first = self.type(args[0])
4343101Sstever@eecs.umich.edu            self.second = self.type(args[1])
43510267SGeoffrey.Blake@arm.com        else:
4367673Snate@binkert.org            raise TypeError, "Too many arguments specified"
4377673Snate@binkert.org
4387673Snate@binkert.org        if kwargs:
4397673Snate@binkert.org            raise TypeError, "too many keywords: %s" % kwargs.keys()
4407673Snate@binkert.org
44110267SGeoffrey.Blake@arm.com    def __str__(self):
44210267SGeoffrey.Blake@arm.com        return '%s:%s' % (self.first, self.second)
44310267SGeoffrey.Blake@arm.com
44410267SGeoffrey.Blake@arm.comclass AddrRange(Range):
44510458Sandreas.hansson@arm.com    type = Addr
44610458Sandreas.hansson@arm.com
44710458Sandreas.hansson@arm.comclass TickRange(Range):
44810458Sandreas.hansson@arm.com    type = Tick
44910458Sandreas.hansson@arm.com
4504762Snate@binkert.org# Boolean parameter type.  Python doesn't let you subclass bool, since
4514762Snate@binkert.org# it doesn't want to let you create multiple instances of True and
4523101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
4533101Sstever@eecs.umich.educlass Bool(ParamValue):
4543101Sstever@eecs.umich.edu    cxx_type = 'bool'
4553101Sstever@eecs.umich.edu    def __init__(self, value):
4563101Sstever@eecs.umich.edu        try:
4573101Sstever@eecs.umich.edu            self.value = convert.toBool(value)
4583101Sstever@eecs.umich.edu        except TypeError:
4593101Sstever@eecs.umich.edu            self.value = bool(value)
4603101Sstever@eecs.umich.edu
4613101Sstever@eecs.umich.edu    def __str__(self):
4623101Sstever@eecs.umich.edu        return str(self.value)
4633714Sstever@eecs.umich.edu
4643714Sstever@eecs.umich.edu    def ini_str(self):
4653714Sstever@eecs.umich.edu        if self.value:
4663714Sstever@eecs.umich.edu            return 'true'
4673714Sstever@eecs.umich.edu        return 'false'
4683714Sstever@eecs.umich.edu
4693101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
4703101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
4713101Sstever@eecs.umich.edu    bytes[5] += val
4723101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
4733101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
4743101Sstever@eecs.umich.edu        bytes[i] = rem
4753101Sstever@eecs.umich.edu        if val == 0:
4763101Sstever@eecs.umich.edu            break
4773101Sstever@eecs.umich.edu        bytes[i - 1] += val
4783101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
4793101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
4803101Sstever@eecs.umich.edu
4813101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
4823101Sstever@eecs.umich.edudef NextEthernetAddr():
4833101Sstever@eecs.umich.edu    global _NextEthernetAddr
4843101Sstever@eecs.umich.edu
4853101Sstever@eecs.umich.edu    value = _NextEthernetAddr
4863101Sstever@eecs.umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
4873101Sstever@eecs.umich.edu    return value
4883101Sstever@eecs.umich.edu
4893101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
4903101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
4913101Sstever@eecs.umich.edu    cxx_predecls = ['#include "base/inet.hh"']
4923101Sstever@eecs.umich.edu    swig_predecls = ['class Net::EthAddr;']
49310380SAndrew.Bardsley@arm.com    def __init__(self, value):
49410380SAndrew.Bardsley@arm.com        if value == NextEthernetAddr:
49510380SAndrew.Bardsley@arm.com            self.value = value
49610458Sandreas.hansson@arm.com            return
49710458Sandreas.hansson@arm.com
49810458Sandreas.hansson@arm.com        if not isinstance(value, str):
49910458Sandreas.hansson@arm.com            raise TypeError, "expected an ethernet address and didn't get one"
50010458Sandreas.hansson@arm.com
50110458Sandreas.hansson@arm.com        bytes = value.split(':')
50210458Sandreas.hansson@arm.com        if len(bytes) != 6:
50310458Sandreas.hansson@arm.com            raise TypeError, 'invalid ethernet address %s' % value
50410458Sandreas.hansson@arm.com
50510458Sandreas.hansson@arm.com        for byte in bytes:
50610458Sandreas.hansson@arm.com            if not 0 <= int(byte) <= 256:
50710458Sandreas.hansson@arm.com                raise TypeError, 'invalid ethernet address %s' % value
50810458Sandreas.hansson@arm.com
5093101Sstever@eecs.umich.edu        self.value = value
5105033Smilesck@eecs.umich.edu
5113101Sstever@eecs.umich.edu    def unproxy(self, base):
5123101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
5133101Sstever@eecs.umich.edu            return EthernetAddr(self.value())
5143101Sstever@eecs.umich.edu        return self
5153101Sstever@eecs.umich.edu
5163101Sstever@eecs.umich.edu    def ini_str(self):
5173101Sstever@eecs.umich.edu        return self.value
5183101Sstever@eecs.umich.edu
5193101Sstever@eecs.umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
5203101Sstever@eecs.umich.edu                 "%a %b %d %H:%M:%S %Z %Y",
5213101Sstever@eecs.umich.edu                 "%Y/%m/%d %H:%M:%S",
5223101Sstever@eecs.umich.edu                 "%Y/%m/%d %H:%M",
5235822Ssaidi@eecs.umich.edu                 "%Y/%m/%d",
5245822Ssaidi@eecs.umich.edu                 "%m/%d/%Y %H:%M:%S",
5253101Sstever@eecs.umich.edu                 "%m/%d/%Y %H:%M",
5263101Sstever@eecs.umich.edu                 "%m/%d/%Y",
5273101Sstever@eecs.umich.edu                 "%m/%d/%y %H:%M:%S",
5283101Sstever@eecs.umich.edu                 "%m/%d/%y %H:%M",
5293101Sstever@eecs.umich.edu                 "%m/%d/%y"]
5303101Sstever@eecs.umich.edu
5313101Sstever@eecs.umich.edu
5323101Sstever@eecs.umich.edudef parse_time(value):
5333101Sstever@eecs.umich.edu    from time import gmtime, strptime, struct_time, time
5343101Sstever@eecs.umich.edu    from datetime import datetime, date
5353101Sstever@eecs.umich.edu
5363101Sstever@eecs.umich.edu    if isinstance(value, struct_time):
5373101Sstever@eecs.umich.edu        return value
53810267SGeoffrey.Blake@arm.com
5393101Sstever@eecs.umich.edu    if isinstance(value, (int, long)):
5403101Sstever@eecs.umich.edu        return gmtime(value)
5413101Sstever@eecs.umich.edu
54213663Sandreas.sandberg@arm.com    if isinstance(value, (datetime, date)):
54313663Sandreas.sandberg@arm.com        return value.timetuple()
5443101Sstever@eecs.umich.edu
5453101Sstever@eecs.umich.edu    if isinstance(value, str):
5463101Sstever@eecs.umich.edu        if value in ('Now', 'Today'):
5473102Sstever@eecs.umich.edu            return time.gmtime(time.time())
5483714Sstever@eecs.umich.edu
5493101Sstever@eecs.umich.edu        for format in time_formats:
5503714Sstever@eecs.umich.edu            try:
55113663Sandreas.sandberg@arm.com                return strptime(value, format)
55213663Sandreas.sandberg@arm.com            except ValueError:
5533101Sstever@eecs.umich.edu                pass
5543101Sstever@eecs.umich.edu
55510267SGeoffrey.Blake@arm.com    raise ValueError, "Could not parse '%s' as a time" % value
55610267SGeoffrey.Blake@arm.com
55710267SGeoffrey.Blake@arm.comclass Time(ParamValue):
55810267SGeoffrey.Blake@arm.com    cxx_type = 'time_t'
5597673Snate@binkert.org    def __init__(self, value):
5607673Snate@binkert.org        self.value = parse_time(value)
5617673Snate@binkert.org
5627673Snate@binkert.org    def __str__(self):
5637673Snate@binkert.org        tm = self.value
5644762Snate@binkert.org        return ' '.join([ str(tm[i]) for i in xrange(8)])
5654762Snate@binkert.org
5664762Snate@binkert.org    def ini_str(self):
5673101Sstever@eecs.umich.edu        return str(self)
5683101Sstever@eecs.umich.edu
5693101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
5703101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
5713101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
5723101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
5733101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
5743101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
5753101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
5763101Sstever@eecs.umich.edu
5773101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
5783101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
5793101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
5803101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
5813101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
5823101Sstever@eecs.umich.edu
5833101Sstever@eecs.umich.edu
5843101Sstever@eecs.umich.edu# Metaclass for Enum types
5853101Sstever@eecs.umich.educlass MetaEnum(type):
5869184Sandreas.hansson@arm.com    def __init__(cls, name, bases, init_dict):
5879184Sandreas.hansson@arm.com        if init_dict.has_key('map'):
5889184Sandreas.hansson@arm.com            if not isinstance(cls.map, dict):
5899184Sandreas.hansson@arm.com                raise TypeError, "Enum-derived class attribute 'map' " \
5909184Sandreas.hansson@arm.com                      "must be of type dict"
5919184Sandreas.hansson@arm.com            # build list of value strings from map
59211802Sandreas.sandberg@arm.com            cls.vals = cls.map.keys()
5939184Sandreas.hansson@arm.com            cls.vals.sort()
5949184Sandreas.hansson@arm.com        elif init_dict.has_key('vals'):
59510458Sandreas.hansson@arm.com            if not isinstance(cls.vals, list):
59610458Sandreas.hansson@arm.com                raise TypeError, "Enum-derived class attribute 'vals' " \
59710458Sandreas.hansson@arm.com                      "must be of type list"
59810458Sandreas.hansson@arm.com            # build string->value map from vals sequence
59910458Sandreas.hansson@arm.com            cls.map = {}
60010458Sandreas.hansson@arm.com            for idx,val in enumerate(cls.vals):
60110458Sandreas.hansson@arm.com                cls.map[val] = idx
60210458Sandreas.hansson@arm.com        else:
60310458Sandreas.hansson@arm.com            raise TypeError, "Enum-derived class must define "\
60410458Sandreas.hansson@arm.com                  "attribute 'map' or 'vals'"
60510458Sandreas.hansson@arm.com
60610458Sandreas.hansson@arm.com        cls.cxx_type = name + '::Enum'
60710458Sandreas.hansson@arm.com
60810458Sandreas.hansson@arm.com        super(MetaEnum, cls).__init__(name, bases, init_dict)
6093101Sstever@eecs.umich.edu
6104446Sbinkertn@umich.edu    # Generate C++ class declaration for this enum type.
61110668SGeoffrey.Blake@arm.com    # Note that we wrap the enum in a class/struct to act as a namespace,
6123101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
6135468Snate@binkert.org    def cxx_decl(cls):
61410267SGeoffrey.Blake@arm.com        s = 'struct %s {\n  enum Enum {\n    ' % cls.__name__
6155468Snate@binkert.org        s += ',\n    '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals])
6165468Snate@binkert.org        s += '\n  };\n};\n'
61713663Sandreas.sandberg@arm.com        return s
61813663Sandreas.sandberg@arm.com
6195468Snate@binkert.org# Base class for enum types.
62010267SGeoffrey.Blake@arm.comclass Enum(ParamValue):
62110267SGeoffrey.Blake@arm.com    __metaclass__ = MetaEnum
62210267SGeoffrey.Blake@arm.com    vals = []
62310267SGeoffrey.Blake@arm.com
6244762Snate@binkert.org    def __init__(self, value):
6254762Snate@binkert.org        if value not in self.map:
6264762Snate@binkert.org            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
62710380SAndrew.Bardsley@arm.com                  % (value, self.vals)
62810380SAndrew.Bardsley@arm.com        self.value = value
62910380SAndrew.Bardsley@arm.com
63010458Sandreas.hansson@arm.com    def __str__(self):
63110458Sandreas.hansson@arm.com        return self.value
63210458Sandreas.hansson@arm.com
63310458Sandreas.hansson@arm.com# how big does a rounding error need to be before we warn about it?
63410458Sandreas.hansson@arm.comfrequency_tolerance = 0.001  # 0.1%
63510458Sandreas.hansson@arm.com
63610458Sandreas.hansson@arm.comclass TickParamValue(NumericParamValue):
63710458Sandreas.hansson@arm.com    cxx_type = 'Tick'
6383101Sstever@eecs.umich.edu    cxx_predecls = ['#include "sim/host.hh"']
6393101Sstever@eecs.umich.edu    swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
64010267SGeoffrey.Blake@arm.com                     '%import "sim/host.hh"']
6413101Sstever@eecs.umich.edu
6423101Sstever@eecs.umich.educlass Latency(TickParamValue):
6433101Sstever@eecs.umich.edu    def __init__(self, value):
6443101Sstever@eecs.umich.edu        if isinstance(value, (Latency, Clock)):
6453101Sstever@eecs.umich.edu            self.ticks = value.ticks
6463101Sstever@eecs.umich.edu            self.value = value.value
6473102Sstever@eecs.umich.edu        elif isinstance(value, Frequency):
6483101Sstever@eecs.umich.edu            self.ticks = value.ticks
6493101Sstever@eecs.umich.edu            self.value = 1.0 / value.value
6503101Sstever@eecs.umich.edu        elif value.endswith('t'):
6514168Sbinkertn@umich.edu            self.ticks = True
65210267SGeoffrey.Blake@arm.com            self.value = int(value[:-1])
6533101Sstever@eecs.umich.edu        else:
6543101Sstever@eecs.umich.edu            self.ticks = False
6553101Sstever@eecs.umich.edu            self.value = convert.toLatency(value)
6563101Sstever@eecs.umich.edu
6573101Sstever@eecs.umich.edu    def __getattr__(self, attr):
6583101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
6593102Sstever@eecs.umich.edu            return self
6603101Sstever@eecs.umich.edu        if attr == 'frequency':
6613101Sstever@eecs.umich.edu            return Frequency(self)
6623101Sstever@eecs.umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
6633101Sstever@eecs.umich.edu
6643101Sstever@eecs.umich.edu    # convert latency to ticks
6653101Sstever@eecs.umich.edu    def ini_str(self):
6663101Sstever@eecs.umich.edu        if self.ticks or self.value == 0:
6673101Sstever@eecs.umich.edu            return '%d' % self.value
6683101Sstever@eecs.umich.edu        else:
6693101Sstever@eecs.umich.edu            return '%d' % (ticks.fromSeconds(self.value))
6703101Sstever@eecs.umich.edu
67110317Smitch.hayenga@arm.comclass Frequency(TickParamValue):
67210317Smitch.hayenga@arm.com    def __init__(self, value):
67310317Smitch.hayenga@arm.com        if isinstance(value, (Latency, Clock)):
67410317Smitch.hayenga@arm.com            if value.value == 0:
67510317Smitch.hayenga@arm.com                self.value = 0
6763102Sstever@eecs.umich.edu            else:
67710317Smitch.hayenga@arm.com                self.value = 1.0 / value.value
67810317Smitch.hayenga@arm.com            self.ticks = value.ticks
67910317Smitch.hayenga@arm.com        elif isinstance(value, Frequency):
68010317Smitch.hayenga@arm.com            self.value = value.value
68110317Smitch.hayenga@arm.com            self.ticks = value.ticks
6823101Sstever@eecs.umich.edu        else:
6833584Ssaidi@eecs.umich.edu            self.ticks = False
6843584Ssaidi@eecs.umich.edu            self.value = convert.toFrequency(value)
6853584Ssaidi@eecs.umich.edu
6863584Ssaidi@eecs.umich.edu    def __getattr__(self, attr):
6873584Ssaidi@eecs.umich.edu        if attr == 'frequency':
68810267SGeoffrey.Blake@arm.com            return self
68910267SGeoffrey.Blake@arm.com        if attr in ('latency', 'period'):
69010267SGeoffrey.Blake@arm.com            return Latency(self)
69110267SGeoffrey.Blake@arm.com        raise AttributeError, "Frequency object has no attribute '%s'" % attr
69210267SGeoffrey.Blake@arm.com
69310267SGeoffrey.Blake@arm.com    # convert latency to ticks
6943101Sstever@eecs.umich.edu    def ini_str(self):
6959232Sandreas.hansson@arm.com        if self.ticks or self.value == 0:
6969235Sandreas.hansson@arm.com            return '%d' % self.value
6973101Sstever@eecs.umich.edu        else:
6983101Sstever@eecs.umich.edu            return '%d' % (ticks.fromSeconds(1.0 / self.value))
69910676Sandreas.hansson@arm.com
7009411Sandreas.hansson@arm.com# A generic frequency and/or Latency value.  Value is stored as a latency,
70110676Sandreas.hansson@arm.com# but to avoid ambiguity this object does not support numeric ops (* or /).
7029411Sandreas.hansson@arm.com# An explicit conversion to a Latency or Frequency must be made first.
7039411Sandreas.hansson@arm.comclass Clock(ParamValue):
7049411Sandreas.hansson@arm.com    cxx_type = 'Tick'
7053101Sstever@eecs.umich.edu    cxx_predecls = ['#include "sim/host.hh"']
7069411Sandreas.hansson@arm.com    swig_predecls = ['%import "python/m5/swig/stdint.i"\n' +
7079411Sandreas.hansson@arm.com                     '%import "sim/host.hh"']
7089411Sandreas.hansson@arm.com    def __init__(self, value):
7093101Sstever@eecs.umich.edu        if isinstance(value, (Latency, Clock)):
7109232Sandreas.hansson@arm.com            self.ticks = value.ticks
7113101Sstever@eecs.umich.edu            self.value = value.value
7129232Sandreas.hansson@arm.com        elif isinstance(value, Frequency):
7133101Sstever@eecs.umich.edu            self.ticks = value.ticks
71413663Sandreas.sandberg@arm.com            self.value = 1.0 / value.value
7153101Sstever@eecs.umich.edu        elif value.endswith('t'):
7169411Sandreas.hansson@arm.com            self.ticks = True
7179411Sandreas.hansson@arm.com            self.value = int(value[:-1])
7189411Sandreas.hansson@arm.com        else:
71910676Sandreas.hansson@arm.com            self.ticks = False
72010676Sandreas.hansson@arm.com            self.value = convert.anyToLatency(value)
7219411Sandreas.hansson@arm.com
7229411Sandreas.hansson@arm.com    def __getattr__(self, attr):
7239411Sandreas.hansson@arm.com        if attr == 'frequency':
7249411Sandreas.hansson@arm.com            return Frequency(self)
7259411Sandreas.hansson@arm.com        if attr in ('latency', 'period'):
7263101Sstever@eecs.umich.edu            return Latency(self)
7279232Sandreas.hansson@arm.com        raise AttributeError, "Frequency object has no attribute '%s'" % attr
7283101Sstever@eecs.umich.edu
7293101Sstever@eecs.umich.edu    def ini_str(self):
7303101Sstever@eecs.umich.edu        return self.period.ini_str()
7313101Sstever@eecs.umich.edu
7329232Sandreas.hansson@arm.comclass NetworkBandwidth(float,ParamValue):
7333101Sstever@eecs.umich.edu    cxx_type = 'float'
7345219Ssaidi@eecs.umich.edu    def __new__(cls, value):
7359232Sandreas.hansson@arm.com        # convert to bits per second
7369232Sandreas.hansson@arm.com        val = convert.toNetworkBandwidth(value)
7373101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
7389232Sandreas.hansson@arm.com
7399232Sandreas.hansson@arm.com    def __str__(self):
7403101Sstever@eecs.umich.edu        return str(self.val)
7413101Sstever@eecs.umich.edu
7429232Sandreas.hansson@arm.com    def ini_str(self):
7439232Sandreas.hansson@arm.com        # convert to seconds per byte
7443101Sstever@eecs.umich.edu        value = 8.0 / float(self)
74513663Sandreas.sandberg@arm.com        # convert to ticks per byte
7463101Sstever@eecs.umich.edu        return '%f' % (ticks.fromSeconds(value))
7473101Sstever@eecs.umich.edu
74813663Sandreas.sandberg@arm.comclass MemoryBandwidth(float,ParamValue):
7493101Sstever@eecs.umich.edu    cxx_type = 'float'
7503101Sstever@eecs.umich.edu    def __new__(self, value):
75111620SMatthew.Poremba@amd.com        # we want the number of ticks per byte of data
75211620SMatthew.Poremba@amd.com        val = convert.toMemoryBandwidth(value)
75311620SMatthew.Poremba@amd.com        return super(cls, MemoryBandwidth).__new__(cls, val)
7549232Sandreas.hansson@arm.com
7559232Sandreas.hansson@arm.com    def __str__(self):
7569411Sandreas.hansson@arm.com        return str(self.val)
7579411Sandreas.hansson@arm.com
7583101Sstever@eecs.umich.edu    def ini_str(self):
7597673Snate@binkert.org        # convert to seconds per byte
7607673Snate@binkert.org        value = 1.0 / float(self)
7619232Sandreas.hansson@arm.com        # convert to ticks per byte
7629235Sandreas.hansson@arm.com        return '%f' % (ticks.fromSeconds(value))
7637675Snate@binkert.org
7647675Snate@binkert.org#
76511988Sandreas.sandberg@arm.com# "Constants"... handy aliases for various values.
76611988Sandreas.sandberg@arm.com#
76711988Sandreas.sandberg@arm.com
76811988Sandreas.sandberg@arm.com# Special class for NULL pointers.  Note the special check in
76911988Sandreas.sandberg@arm.com# make_param_value() above that lets these be assigned where a
77010458Sandreas.hansson@arm.com# SimObject is required.
77110458Sandreas.hansson@arm.com# only one copy of a particular node
77210458Sandreas.hansson@arm.comclass NullSimObject(object):
77310458Sandreas.hansson@arm.com    __metaclass__ = Singleton
77410458Sandreas.hansson@arm.com
77511620SMatthew.Poremba@amd.com    def __call__(cls):
77611620SMatthew.Poremba@amd.com        return cls
77710458Sandreas.hansson@arm.com
77810458Sandreas.hansson@arm.com    def _instantiate(self, parent = None, path = ''):
77910458Sandreas.hansson@arm.com        pass
78010458Sandreas.hansson@arm.com
78110458Sandreas.hansson@arm.com    def ini_str(self):
78211620SMatthew.Poremba@amd.com        return 'Null'
78311620SMatthew.Poremba@amd.com
78411620SMatthew.Poremba@amd.com    def unproxy(self, base):
78511620SMatthew.Poremba@amd.com        return self
78611620SMatthew.Poremba@amd.com
78711620SMatthew.Poremba@amd.com    def set_path(self, parent, name):
78811620SMatthew.Poremba@amd.com        pass
78911620SMatthew.Poremba@amd.com    def __str__(self):
79011620SMatthew.Poremba@amd.com        return 'Null'
79111620SMatthew.Poremba@amd.com
79210458Sandreas.hansson@arm.com# The only instance you'll ever need...
79310458Sandreas.hansson@arm.comNULL = NullSimObject()
79410458Sandreas.hansson@arm.com
79511620SMatthew.Poremba@amd.comdef isNullPointer(value):
79611620SMatthew.Poremba@amd.com    return isinstance(value, NullSimObject)
79710458Sandreas.hansson@arm.com
79810458Sandreas.hansson@arm.com# Some memory range specifications use this as a default upper bound.
7994762Snate@binkert.orgMaxAddr = Addr.max
80011991Sandreas.sandberg@arm.comMaxTick = Tick.max
80111802Sandreas.sandberg@arm.comAllMemory = AddrRange(0, MaxAddr)
8024762Snate@binkert.org
8039411Sandreas.hansson@arm.com
80410676Sandreas.hansson@arm.com#####################################################################
80510676Sandreas.hansson@arm.com#
8063101Sstever@eecs.umich.edu# Port objects
8073101Sstever@eecs.umich.edu#
8083101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
8093101Sstever@eecs.umich.edu#
8103101Sstever@eecs.umich.edu#####################################################################
8113101Sstever@eecs.umich.edu
81210267SGeoffrey.Blake@arm.com# Port reference: encapsulates a reference to a particular port on a
81310267SGeoffrey.Blake@arm.com# particular SimObject.
8143101Sstever@eecs.umich.educlass PortRef(object):
8153101Sstever@eecs.umich.edu    def __init__(self, simobj, name):
8163102Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
8173101Sstever@eecs.umich.edu        self.simobj = simobj
8183101Sstever@eecs.umich.edu        self.name = name
8193101Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
82010267SGeoffrey.Blake@arm.com        self.ccConnected = False # C++ port connection done?
82110267SGeoffrey.Blake@arm.com        self.index = -1  # always -1 for non-vector ports
82210267SGeoffrey.Blake@arm.com
82310267SGeoffrey.Blake@arm.com    def __str__(self):
8244762Snate@binkert.org        return '%s.%s' % (self.simobj, self.name)
8254762Snate@binkert.org
8264762Snate@binkert.org    # for config.ini, print peer's name (not ours)
8273101Sstever@eecs.umich.edu    def ini_str(self):
8283101Sstever@eecs.umich.edu        return str(self.peer)
8293101Sstever@eecs.umich.edu
8308934SBrad.Beckmann@amd.com    def __getattr__(self, attr):
8318934SBrad.Beckmann@amd.com        if attr == 'peerObj':
83213697Sandreas.sandberg@arm.com            # shorthand for proxies
8338934SBrad.Beckmann@amd.com            return self.peer.simobj
8348934SBrad.Beckmann@amd.com        raise AttributeError, "'%s' object has no attribute '%s'" % \
83513697Sandreas.sandberg@arm.com              (self.__class__.__name__, attr)
83613697Sandreas.sandberg@arm.com
83713697Sandreas.sandberg@arm.com    # Full connection is symmetric (both ways).  Called via
8383101Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
8393101Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
8403101Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
8413101Sstever@eecs.umich.edu    def connect(self, other):
8423101Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
84310380SAndrew.Bardsley@arm.com            # reference to plain VectorPort is implicit append
84410380SAndrew.Bardsley@arm.com            other = other._get_next()
84510380SAndrew.Bardsley@arm.com        if self.peer and not proxy.isproxy(self.peer):
84610458Sandreas.hansson@arm.com            print "warning: overwriting port", self, \
84710458Sandreas.hansson@arm.com                  "value", self.peer, "with", other
84810458Sandreas.hansson@arm.com        self.peer = other
84910458Sandreas.hansson@arm.com        if proxy.isproxy(other):
85010458Sandreas.hansson@arm.com            other.set_param_desc(PortParamDesc())
85110458Sandreas.hansson@arm.com        elif isinstance(other, PortRef):
85210458Sandreas.hansson@arm.com            if other.peer is not self:
85310458Sandreas.hansson@arm.com                other.connect(self)
85410458Sandreas.hansson@arm.com        else:
85510458Sandreas.hansson@arm.com            raise TypeError, \
8563101Sstever@eecs.umich.edu                  "assigning non-port reference '%s' to port '%s'" \
8573101Sstever@eecs.umich.edu                  % (other, self)
8583101Sstever@eecs.umich.edu
8593101Sstever@eecs.umich.edu    def clone(self, simobj, memo):
8603101Sstever@eecs.umich.edu        if memo.has_key(self):
8613101Sstever@eecs.umich.edu            return memo[self]
8623101Sstever@eecs.umich.edu        newRef = copy.copy(self)
8633101Sstever@eecs.umich.edu        memo[self] = newRef
8643101Sstever@eecs.umich.edu        newRef.simobj = simobj
8653101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
8663101Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
8673101Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
8684380Sbinkertn@umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
8694380Sbinkertn@umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
8704380Sbinkertn@umich.edu        return newRef
8713101Sstever@eecs.umich.edu
8724380Sbinkertn@umich.edu    def unproxy(self, simobj):
8734380Sbinkertn@umich.edu        assert(simobj is self.simobj)
8744380Sbinkertn@umich.edu        if proxy.isproxy(self.peer):
8753101Sstever@eecs.umich.edu            try:
8763101Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
8773101Sstever@eecs.umich.edu            except:
87810267SGeoffrey.Blake@arm.com                print "Error in unproxying port '%s' of %s" % \
87910267SGeoffrey.Blake@arm.com                      (self.name, self.simobj.path())
8807673Snate@binkert.org                raise
8817673Snate@binkert.org            self.connect(realPeer)
8827673Snate@binkert.org
8837673Snate@binkert.org    # Call C++ to create corresponding port connection between C++ objects
8847673Snate@binkert.org    def ccConnect(self):
8853101Sstever@eecs.umich.edu        if self.ccConnected: # already done this
8863101Sstever@eecs.umich.edu            return
8873101Sstever@eecs.umich.edu        peer = self.peer
8883101Sstever@eecs.umich.edu        internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name,
8893101Sstever@eecs.umich.edu            self.index, peer.simobj.getCCObject(), peer.name, peer.index)
8903101Sstever@eecs.umich.edu        self.ccConnected = True
89113663Sandreas.sandberg@arm.com        peer.ccConnected = True
8923101Sstever@eecs.umich.edu
8933101Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
8943101Sstever@eecs.umich.edu# PortRef, but has an index.
89513663Sandreas.sandberg@arm.comclass VectorPortElementRef(PortRef):
8963101Sstever@eecs.umich.edu    def __init__(self, simobj, name, index):
8973101Sstever@eecs.umich.edu        PortRef.__init__(self, simobj, name)
8989941SGeoffrey.Blake@arm.com        self.index = index
89913663Sandreas.sandberg@arm.com
9003101Sstever@eecs.umich.edu    def __str__(self):
9013101Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
9023101Sstever@eecs.umich.edu
90310267SGeoffrey.Blake@arm.com# A reference to a complete vector-valued port (not just a single element).
90410267SGeoffrey.Blake@arm.com# Can be indexed to retrieve individual VectorPortElementRef instances.
90510267SGeoffrey.Blake@arm.comclass VectorPortRef(object):
90610267SGeoffrey.Blake@arm.com    def __init__(self, simobj, name):
9073101Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
9083101Sstever@eecs.umich.edu        self.simobj = simobj
9094380Sbinkertn@umich.edu        self.name = name
9103101Sstever@eecs.umich.edu        self.elements = []
9113101Sstever@eecs.umich.edu
9124762Snate@binkert.org    def __str__(self):
91311988Sandreas.sandberg@arm.com        return '%s.%s[:]' % (self.simobj, self.name)
9144762Snate@binkert.org
9154762Snate@binkert.org    # for config.ini, print peer's name (not ours)
91611228SAndrew.Bardsley@arm.com    def ini_str(self):
91711228SAndrew.Bardsley@arm.com        return ' '.join([el.ini_str() for el in self.elements])
91811228SAndrew.Bardsley@arm.com
9194380Sbinkertn@umich.edu    def __getitem__(self, key):
9204380Sbinkertn@umich.edu        if not isinstance(key, int):
9213101Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
92210458Sandreas.hansson@arm.com        if key >= len(self.elements):
92310458Sandreas.hansson@arm.com            # need to extend list
92410458Sandreas.hansson@arm.com            ext = [VectorPortElementRef(self.simobj, self.name, i)
92510458Sandreas.hansson@arm.com                   for i in range(len(self.elements), key+1)]
92610458Sandreas.hansson@arm.com            self.elements.extend(ext)
9277777Sgblack@eecs.umich.edu        return self.elements[key]
9287777Sgblack@eecs.umich.edu
9297777Sgblack@eecs.umich.edu    def _get_next(self):
9307777Sgblack@eecs.umich.edu        return self[len(self.elements)]
93110267SGeoffrey.Blake@arm.com
93210267SGeoffrey.Blake@arm.com    def __setitem__(self, key, value):
9337777Sgblack@eecs.umich.edu        if not isinstance(key, int):
9347777Sgblack@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
9357777Sgblack@eecs.umich.edu        self[key].connect(value)
9367777Sgblack@eecs.umich.edu
9377777Sgblack@eecs.umich.edu    def connect(self, other):
9387777Sgblack@eecs.umich.edu        if isinstance(other, (list, tuple)):
9397777Sgblack@eecs.umich.edu            # Assign list of port refs to vector port.
9407777Sgblack@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
9417777Sgblack@eecs.umich.edu            # or if it should replace the current vector.
9427777Sgblack@eecs.umich.edu            for ref in other:
9437777Sgblack@eecs.umich.edu                self._get_next().connect(ref)
9447777Sgblack@eecs.umich.edu        else:
9457777Sgblack@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
9467777Sgblack@eecs.umich.edu            self._get_next().connect(other)
9477777Sgblack@eecs.umich.edu
94810267SGeoffrey.Blake@arm.com    def clone(self, simobj, memo):
94910267SGeoffrey.Blake@arm.com        if memo.has_key(self):
95010267SGeoffrey.Blake@arm.com            return memo[self]
95110267SGeoffrey.Blake@arm.com        newRef = copy.copy(self)
9528579Ssteve.reinhardt@amd.com        memo[self] = newRef
9538579Ssteve.reinhardt@amd.com        newRef.simobj = simobj
9548579Ssteve.reinhardt@amd.com        assert(isSimObject(newRef.simobj))
9558579Ssteve.reinhardt@amd.com        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
9568579Ssteve.reinhardt@amd.com        return newRef
9578579Ssteve.reinhardt@amd.com
9588579Ssteve.reinhardt@amd.com    def unproxy(self, simobj):
9598579Ssteve.reinhardt@amd.com        [el.unproxy(simobj) for el in self.elements]
9608579Ssteve.reinhardt@amd.com
9618579Ssteve.reinhardt@amd.com    def ccConnect(self):
9628579Ssteve.reinhardt@amd.com        [el.ccConnect() for el in self.elements]
9638579Ssteve.reinhardt@amd.com
9648579Ssteve.reinhardt@amd.com# Port description object.  Like a ParamDesc object, this represents a
9658579Ssteve.reinhardt@amd.com# logical port in the SimObject class, not a particular port on a
9668579Ssteve.reinhardt@amd.com# SimObject instance.  The latter are represented by PortRef objects.
9678579Ssteve.reinhardt@amd.comclass Port(object):
9688579Ssteve.reinhardt@amd.com    # Port("description") or Port(default, "description")
9698579Ssteve.reinhardt@amd.com    def __init__(self, *args):
9707777Sgblack@eecs.umich.edu        if len(args) == 1:
9717777Sgblack@eecs.umich.edu            self.desc = args[0]
97213663Sandreas.sandberg@arm.com        elif len(args) == 2:
9737777Sgblack@eecs.umich.edu            self.default = args[0]
9747777Sgblack@eecs.umich.edu            self.desc = args[1]
97511988Sandreas.sandberg@arm.com        else:
9767777Sgblack@eecs.umich.edu            raise TypeError, 'wrong number of arguments'
9777777Sgblack@eecs.umich.edu        # self.name is set by SimObject class on assignment
9787777Sgblack@eecs.umich.edu        # e.g., pio_port = Port("blah") sets self.name to 'pio_port'
9797777Sgblack@eecs.umich.edu
9807777Sgblack@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
9817777Sgblack@eecs.umich.edu    # given name
9827777Sgblack@eecs.umich.edu    def makeRef(self, simobj):
98310267SGeoffrey.Blake@arm.com        return PortRef(simobj, self.name)
98410267SGeoffrey.Blake@arm.com
9857777Sgblack@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
9867777Sgblack@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
9877777Sgblack@eecs.umich.edu    def connect(self, simobj, ref):
9887777Sgblack@eecs.umich.edu        self.makeRef(simobj).connect(ref)
9897777Sgblack@eecs.umich.edu
9907777Sgblack@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
9917777Sgblack@eecs.umich.edu# of connections (e.g., as on a Bus).
9927777Sgblack@eecs.umich.educlass VectorPort(Port):
9937777Sgblack@eecs.umich.edu    def __init__(self, *args):
9947777Sgblack@eecs.umich.edu        Port.__init__(self, *args)
9957777Sgblack@eecs.umich.edu        self.isVec = True
9967777Sgblack@eecs.umich.edu
99713663Sandreas.sandberg@arm.com    def makeRef(self, simobj):
9987777Sgblack@eecs.umich.edu        return VectorPortRef(simobj, self.name)
9997777Sgblack@eecs.umich.edu
10007777Sgblack@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
10017777Sgblack@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
10027777Sgblack@eecs.umich.edu# make sense.
10037777Sgblack@eecs.umich.educlass PortParamDesc(object):
10047777Sgblack@eecs.umich.edu    __metaclass__ = Singleton
10057777Sgblack@eecs.umich.edu
100613663Sandreas.sandberg@arm.com    ptype_str = 'Port'
10077777Sgblack@eecs.umich.edu    ptype = Port
10087777Sgblack@eecs.umich.edu
10097777Sgblack@eecs.umich.edu
10107777Sgblack@eecs.umich.edu__all__ = ['Param', 'VectorParam',
10117777Sgblack@eecs.umich.edu           'Enum', 'Bool', 'String', 'Float',
10127777Sgblack@eecs.umich.edu           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
10137777Sgblack@eecs.umich.edu           'Int32', 'UInt32', 'Int64', 'UInt64',
10147777Sgblack@eecs.umich.edu           'Counter', 'Addr', 'Tick', 'Percent',
10157777Sgblack@eecs.umich.edu           'TcpPort', 'UdpPort', 'EthernetAddr',
10167777Sgblack@eecs.umich.edu           'MemorySize', 'MemorySize32',
10177777Sgblack@eecs.umich.edu           'Latency', 'Frequency', 'Clock',
10187777Sgblack@eecs.umich.edu           'NetworkBandwidth', 'MemoryBandwidth',
101913663Sandreas.sandberg@arm.com           'Range', 'AddrRange', 'TickRange',
10207777Sgblack@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
10217777Sgblack@eecs.umich.edu           'Time',
102213663Sandreas.sandberg@arm.com           'NextEthernetAddr', 'NULL',
10237777Sgblack@eecs.umich.edu           'Port', 'VectorPort']
10247777Sgblack@eecs.umich.edu
10257777Sgblack@eecs.umich.edu# see comment on imports at end of __init__.py.
102610267SGeoffrey.Blake@arm.comfrom SimObject import isSimObject, isSimObjectSequence, isSimObjectClass
102710267SGeoffrey.Blake@arm.comimport objects
102810267SGeoffrey.Blake@arm.comimport internal
102910267SGeoffrey.Blake@arm.com