params.py revision 10676:f6c168692b20
111988Sandreas.sandberg@arm.com# Copyright (c) 2012-2014 ARM Limited
28839Sandreas.hansson@arm.com# All rights reserved.
38839Sandreas.hansson@arm.com#
48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall
58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual
68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating
78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software
88839Sandreas.hansson@arm.com# licensed hereunder.  You may use the software subject to the license
98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated
108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software,
118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form.
128839Sandreas.hansson@arm.com#
133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan
148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
153101Sstever@eecs.umich.edu# All rights reserved.
163101Sstever@eecs.umich.edu#
173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are
193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright
203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution;
243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its
253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from
263101Sstever@eecs.umich.edu# this software without specific prior written permission.
273101Sstever@eecs.umich.edu#
283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
393101Sstever@eecs.umich.edu#
403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt
413101Sstever@eecs.umich.edu#          Nathan Binkert
427778Sgblack@eecs.umich.edu#          Gabe Black
438839Sandreas.hansson@arm.com#          Andreas Hansson
443101Sstever@eecs.umich.edu
453101Sstever@eecs.umich.edu#####################################################################
463101Sstever@eecs.umich.edu#
473101Sstever@eecs.umich.edu# Parameter description classes
483101Sstever@eecs.umich.edu#
493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either
503101Sstever@eecs.umich.edu# a Param or a VectorParam object.  These objects contain the
513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default
523101Sstever@eecs.umich.edu# value (if any).  The convert() method on these objects is used to
533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate
543101Sstever@eecs.umich.edu# type.
553101Sstever@eecs.umich.edu#
563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute
573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in
583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used.
593101Sstever@eecs.umich.edu#
603101Sstever@eecs.umich.edu#####################################################################
613101Sstever@eecs.umich.edu
623885Sbinkertn@umich.eduimport copy
633885Sbinkertn@umich.eduimport datetime
644762Snate@binkert.orgimport re
653885Sbinkertn@umich.eduimport sys
663885Sbinkertn@umich.eduimport time
677528Ssteve.reinhardt@amd.comimport math
683885Sbinkertn@umich.edu
694380Sbinkertn@umich.eduimport proxy
704167Sbinkertn@umich.eduimport ticks
713102Sstever@eecs.umich.edufrom util import *
723101Sstever@eecs.umich.edu
734762Snate@binkert.orgdef isSimObject(*args, **kwargs):
744762Snate@binkert.org    return SimObject.isSimObject(*args, **kwargs)
754762Snate@binkert.org
764762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs):
774762Snate@binkert.org    return SimObject.isSimObjectSequence(*args, **kwargs)
784762Snate@binkert.org
794762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs):
804762Snate@binkert.org    return SimObject.isSimObjectClass(*args, **kwargs)
814762Snate@binkert.org
825033Smilesck@eecs.umich.eduallParams = {}
835033Smilesck@eecs.umich.edu
845033Smilesck@eecs.umich.educlass MetaParamValue(type):
855033Smilesck@eecs.umich.edu    def __new__(mcls, name, bases, dct):
865033Smilesck@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
875033Smilesck@eecs.umich.edu        assert name not in allParams
885033Smilesck@eecs.umich.edu        allParams[name] = cls
895033Smilesck@eecs.umich.edu        return cls
905033Smilesck@eecs.umich.edu
915033Smilesck@eecs.umich.edu
923101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject
933101Sstever@eecs.umich.edu# parameters.
943101Sstever@eecs.umich.educlass ParamValue(object):
955033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
9610267SGeoffrey.Blake@arm.com    cmd_line_settable = False
978596Ssteve.reinhardt@amd.com
988596Ssteve.reinhardt@amd.com    # Generate the code needed as a prerequisite for declaring a C++
998596Ssteve.reinhardt@amd.com    # object of this type.  Typically generates one or more #include
1008596Ssteve.reinhardt@amd.com    # statements.  Used when declaring parameters of this type.
1017673Snate@binkert.org    @classmethod
1027673Snate@binkert.org    def cxx_predecls(cls, code):
1037673Snate@binkert.org        pass
1047673Snate@binkert.org
10511988Sandreas.sandberg@arm.com    # Generate the code needed as a prerequisite for including a
10611988Sandreas.sandberg@arm.com    # reference to a C++ object of this type in a SWIG .i file.
10711988Sandreas.sandberg@arm.com    # Typically generates one or more %import or %include statements.
10811988Sandreas.sandberg@arm.com    @classmethod
1093101Sstever@eecs.umich.edu    def swig_predecls(cls, code):
1103101Sstever@eecs.umich.edu        pass
1113101Sstever@eecs.umich.edu
1123101Sstever@eecs.umich.edu    # default for printing to .ini file is regular string conversion.
1133101Sstever@eecs.umich.edu    # will be overridden in some cases
11410380SAndrew.Bardsley@arm.com    def ini_str(self):
11510380SAndrew.Bardsley@arm.com        return str(self)
11610380SAndrew.Bardsley@arm.com
11710380SAndrew.Bardsley@arm.com    # default for printing to .json file is regular string conversion.
11810380SAndrew.Bardsley@arm.com    # will be overridden in some cases, mostly to use native Python
11910380SAndrew.Bardsley@arm.com    # types where there are similar JSON types
12010458Sandreas.hansson@arm.com    def config_value(self):
12110458Sandreas.hansson@arm.com        return str(self)
12210458Sandreas.hansson@arm.com
12310458Sandreas.hansson@arm.com    # Prerequisites for .ini parsing with cxx_ini_parse
12410458Sandreas.hansson@arm.com    @classmethod
12510458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
12610458Sandreas.hansson@arm.com        pass
12710458Sandreas.hansson@arm.com
12810458Sandreas.hansson@arm.com    # parse a .ini file entry for this param from string expression
12910458Sandreas.hansson@arm.com    # src into lvalue dest (of the param's C++ type)
13010458Sandreas.hansson@arm.com    @classmethod
13110458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
1323101Sstever@eecs.umich.edu        code('// Unhandled param type: %s' % cls.__name__)
1333101Sstever@eecs.umich.edu        code('%s false;' % ret)
1343101Sstever@eecs.umich.edu
1353101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
1363101Sstever@eecs.umich.edu    # if they're really proxies or not
13710267SGeoffrey.Blake@arm.com    def unproxy(self, base):
13810267SGeoffrey.Blake@arm.com        return self
13910267SGeoffrey.Blake@arm.com
14010267SGeoffrey.Blake@arm.com    # Produce a human readable version of the stored value
1413101Sstever@eecs.umich.edu    def pretty_print(self, value):
1423101Sstever@eecs.umich.edu        return str(value)
1433101Sstever@eecs.umich.edu
1443101Sstever@eecs.umich.edu# Regular parameter description.
1453101Sstever@eecs.umich.educlass ParamDesc(object):
1463101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1473101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1483101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1493101Sstever@eecs.umich.edu        if ptype != None:
1503101Sstever@eecs.umich.edu            self.ptype = ptype
1513101Sstever@eecs.umich.edu
1523101Sstever@eecs.umich.edu        if args:
1533101Sstever@eecs.umich.edu            if len(args) == 1:
1543101Sstever@eecs.umich.edu                self.desc = args[0]
1553101Sstever@eecs.umich.edu            elif len(args) == 2:
1563101Sstever@eecs.umich.edu                self.default = args[0]
1573101Sstever@eecs.umich.edu                self.desc = args[1]
1583101Sstever@eecs.umich.edu            else:
1593101Sstever@eecs.umich.edu                raise TypeError, 'too many arguments'
1603101Sstever@eecs.umich.edu
1613101Sstever@eecs.umich.edu        if kwargs.has_key('desc'):
1623101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1633101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1643101Sstever@eecs.umich.edu            del kwargs['desc']
1653101Sstever@eecs.umich.edu
1663101Sstever@eecs.umich.edu        if kwargs.has_key('default'):
1673101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1683101Sstever@eecs.umich.edu            self.default = kwargs['default']
1693101Sstever@eecs.umich.edu            del kwargs['default']
1703101Sstever@eecs.umich.edu
1713101Sstever@eecs.umich.edu        if kwargs:
1723101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1733101Sstever@eecs.umich.edu
1743101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
1753101Sstever@eecs.umich.edu            raise TypeError, 'desc attribute missing'
1765033Smilesck@eecs.umich.edu
1776656Snate@binkert.org    def __getattr__(self, attr):
1785033Smilesck@eecs.umich.edu        if attr == 'ptype':
1795033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1805033Smilesck@eecs.umich.edu            assert isSimObjectClass(ptype)
1813101Sstever@eecs.umich.edu            self.ptype = ptype
1823101Sstever@eecs.umich.edu            return ptype
1833101Sstever@eecs.umich.edu
18410267SGeoffrey.Blake@arm.com        raise AttributeError, "'%s' object has no attribute '%s'" % \
18510267SGeoffrey.Blake@arm.com              (type(self).__name__, attr)
18610267SGeoffrey.Blake@arm.com
18710267SGeoffrey.Blake@arm.com    def example_str(self):
18810267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "ex_str"):
18910267SGeoffrey.Blake@arm.com            return self.ptype.ex_str
19010267SGeoffrey.Blake@arm.com        else:
19110267SGeoffrey.Blake@arm.com            return self.ptype_str
19210267SGeoffrey.Blake@arm.com
19310267SGeoffrey.Blake@arm.com    # Is the param available to be exposed on the command line
19410267SGeoffrey.Blake@arm.com    def isCmdLineSettable(self):
19510267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "cmd_line_settable"):
19610267SGeoffrey.Blake@arm.com            return self.ptype.cmd_line_settable
1973101Sstever@eecs.umich.edu        else:
1983101Sstever@eecs.umich.edu            return False
1993101Sstever@eecs.umich.edu
2003101Sstever@eecs.umich.edu    def convert(self, value):
2013101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
2023101Sstever@eecs.umich.edu            value.set_param_desc(self)
2033101Sstever@eecs.umich.edu            return value
2043101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
2053101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
2063101Sstever@eecs.umich.edu            # we're just assigning a null pointer
2073102Sstever@eecs.umich.edu            return value
2083101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
2093101Sstever@eecs.umich.edu            return value
2103101Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
21110267SGeoffrey.Blake@arm.com            return value
21210267SGeoffrey.Blake@arm.com        return self.ptype(value)
21310267SGeoffrey.Blake@arm.com
21410267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
21510267SGeoffrey.Blake@arm.com        if isinstance(value, proxy.BaseProxy):
21610267SGeoffrey.Blake@arm.com           return str(value)
21710267SGeoffrey.Blake@arm.com        if isNullPointer(value):
2187673Snate@binkert.org           return NULL
2198607Sgblack@eecs.umich.edu        return self.ptype(value).pretty_print(value)
2207673Snate@binkert.org
2213101Sstever@eecs.umich.edu    def cxx_predecls(self, code):
22211988Sandreas.sandberg@arm.com        code('#include <cstddef>')
22311988Sandreas.sandberg@arm.com        self.ptype.cxx_predecls(code)
22411988Sandreas.sandberg@arm.com
2257673Snate@binkert.org    def swig_predecls(self, code):
2267673Snate@binkert.org        self.ptype.swig_predecls(code)
2273101Sstever@eecs.umich.edu
2283101Sstever@eecs.umich.edu    def cxx_decl(self, code):
2293101Sstever@eecs.umich.edu        code('${{self.ptype.cxx_type}} ${{self.name}};')
2303101Sstever@eecs.umich.edu
2313101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
2323101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
2335033Smilesck@eecs.umich.edu# single value.
2345475Snate@binkert.org
2355475Snate@binkert.orgclass VectorParamValue(list):
2365475Snate@binkert.org    __metaclass__ = MetaParamValue
2375475Snate@binkert.org    def __setattr__(self, attr, value):
23810380SAndrew.Bardsley@arm.com        raise AttributeError, \
23910380SAndrew.Bardsley@arm.com              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
24010380SAndrew.Bardsley@arm.com
2413101Sstever@eecs.umich.edu    def config_value(self):
2423101Sstever@eecs.umich.edu        return [v.config_value() for v in self]
2433101Sstever@eecs.umich.edu
2444762Snate@binkert.org    def ini_str(self):
2454762Snate@binkert.org        return ' '.join([v.ini_str() for v in self])
2464762Snate@binkert.org
2473101Sstever@eecs.umich.edu    def getValue(self):
24812050Snikos.nikoleris@arm.com        return [ v.getValue() for v in self ]
24912050Snikos.nikoleris@arm.com
25012050Snikos.nikoleris@arm.com    def unproxy(self, base):
2518459SAli.Saidi@ARM.com        if len(self) == 1 and isinstance(self[0], proxy.AllProxy):
2528459SAli.Saidi@ARM.com            return self[0].unproxy(base)
25312050Snikos.nikoleris@arm.com        else:
2543101Sstever@eecs.umich.edu             return [v.unproxy(base) for v in self]
2557528Ssteve.reinhardt@amd.com
2567528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2577528Ssteve.reinhardt@amd.com    # support clone operation
2587528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2597528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2607528Ssteve.reinhardt@amd.com
2613101Sstever@eecs.umich.edu    def clear_parent(self, old_parent):
2627528Ssteve.reinhardt@amd.com        for v in self:
2637528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2647528Ssteve.reinhardt@amd.com
2657528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2667528Ssteve.reinhardt@amd.com        if len(self) == 1:
2677528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2687528Ssteve.reinhardt@amd.com        else:
2697528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2707528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2717528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2728321Ssteve.reinhardt@amd.com
27312194Sgabeblack@google.com    def has_parent(self):
2747528Ssteve.reinhardt@amd.com        return reduce(lambda x,y: x and y, [v.has_parent() for v in self])
2757528Ssteve.reinhardt@amd.com
2767528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2777528Ssteve.reinhardt@amd.com    def get_name(self):
2787528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2797528Ssteve.reinhardt@amd.com
2807528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2817528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2827528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2837528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2847528Ssteve.reinhardt@amd.com    def descendants(self):
2857528Ssteve.reinhardt@amd.com        for v in self:
2867528Ssteve.reinhardt@amd.com            for obj in v.descendants():
2873101Sstever@eecs.umich.edu                yield obj
2888664SAli.Saidi@ARM.com
2898664SAli.Saidi@ARM.com    def get_config_as_dict(self):
2908664SAli.Saidi@ARM.com        a = []
2918664SAli.Saidi@ARM.com        for v in self:
2928664SAli.Saidi@ARM.com            a.append(v.get_config_as_dict())
2938664SAli.Saidi@ARM.com        return a
2949953Sgeoffrey.blake@arm.com
2959953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
2969953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
2979953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
2989953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
2999953Sgeoffrey.blake@arm.com    # configuration scripts.
3009953Sgeoffrey.blake@arm.com    def __setitem__(self, key, value):
3019953Sgeoffrey.blake@arm.com        val = self[key]
3029953Sgeoffrey.blake@arm.com        if value.has_parent():
3039953Sgeoffrey.blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
3049953Sgeoffrey.blake@arm.com                 " that is being overwritten by a SimObjectVector")
3059953Sgeoffrey.blake@arm.com        value.set_parent(val.get_parent(), val._name)
3069953Sgeoffrey.blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
30710267SGeoffrey.Blake@arm.com
30810267SGeoffrey.Blake@arm.com    # Enumerate the params of each member of the SimObject vector. Creates
30910267SGeoffrey.Blake@arm.com    # strings that will allow indexing into the vector by the python code and
31010267SGeoffrey.Blake@arm.com    # allow it to be specified on the command line.
31110267SGeoffrey.Blake@arm.com    def enumerateParams(self, flags_dict = {},
31210267SGeoffrey.Blake@arm.com                        cmd_line_str = "",
31310267SGeoffrey.Blake@arm.com                        access_str = ""):
31410267SGeoffrey.Blake@arm.com        if hasattr(self, "_paramEnumed"):
31510267SGeoffrey.Blake@arm.com            print "Cycle detected enumerating params at %s?!" % (cmd_line_str)
31610267SGeoffrey.Blake@arm.com        else:
31710267SGeoffrey.Blake@arm.com            x = 0
31810267SGeoffrey.Blake@arm.com            for vals in self:
31910267SGeoffrey.Blake@arm.com                # Each entry in the SimObjectVector should be an
32010267SGeoffrey.Blake@arm.com                # instance of a SimObject
32110267SGeoffrey.Blake@arm.com                flags_dict = vals.enumerateParams(flags_dict,
32210267SGeoffrey.Blake@arm.com                                                  cmd_line_str + "%d." % x,
32310267SGeoffrey.Blake@arm.com                                                  access_str + "[%d]." % x)
32410267SGeoffrey.Blake@arm.com                x = x + 1
32510267SGeoffrey.Blake@arm.com
32610267SGeoffrey.Blake@arm.com        return flags_dict
3273101Sstever@eecs.umich.edu
3283101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
3293101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
3303101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
3313101Sstever@eecs.umich.edu    def convert(self, value):
3323101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
3333101Sstever@eecs.umich.edu            # list: coerce each element into new list
33410364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
33510364SGeoffrey.Blake@arm.com        elif isinstance(value, str):
33610364SGeoffrey.Blake@arm.com            # If input is a csv string
33710364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
3383101Sstever@eecs.umich.edu                         for v in value.strip('[').strip(']').split(',') ]
3394762Snate@binkert.org        else:
3404762Snate@binkert.org            # singleton: coerce to a single-element list
3414762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
3424762Snate@binkert.org
3437528Ssteve.reinhardt@amd.com        if isSimObjectSequence(tmp_list):
3444762Snate@binkert.org            return SimObjectVector(tmp_list)
3454762Snate@binkert.org        else:
3464762Snate@binkert.org            return VectorParamValue(tmp_list)
34710267SGeoffrey.Blake@arm.com
34810267SGeoffrey.Blake@arm.com    # Produce a human readable example string that describes
34910267SGeoffrey.Blake@arm.com    # how to set this vector parameter in the absence of a default
35010267SGeoffrey.Blake@arm.com    # value.
35110267SGeoffrey.Blake@arm.com    def example_str(self):
35210267SGeoffrey.Blake@arm.com        s = super(VectorParamDesc, self).example_str()
35310267SGeoffrey.Blake@arm.com        help_str = "[" + s + "," + s + ", ...]"
35410267SGeoffrey.Blake@arm.com        return help_str
35510267SGeoffrey.Blake@arm.com
35610267SGeoffrey.Blake@arm.com    # Produce a human readable representation of the value of this vector param.
35710267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
35810267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
35910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
36010267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
36110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
36210267SGeoffrey.Blake@arm.com        else:
36310267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, value) ]
36410267SGeoffrey.Blake@arm.com
36510267SGeoffrey.Blake@arm.com        return tmp_list
36610267SGeoffrey.Blake@arm.com
36710267SGeoffrey.Blake@arm.com    # This is a helper function for the new config system
36810267SGeoffrey.Blake@arm.com    def __call__(self, value):
36910267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
37010267SGeoffrey.Blake@arm.com            # list: coerce each element into new list
37110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
37210267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
37310364SGeoffrey.Blake@arm.com            # If input is a csv string
37410364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
37510267SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
37610267SGeoffrey.Blake@arm.com        else:
37710267SGeoffrey.Blake@arm.com            # singleton: coerce to a single-element list
37810267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
37910267SGeoffrey.Blake@arm.com
38010267SGeoffrey.Blake@arm.com        return VectorParamValue(tmp_list)
3817673Snate@binkert.org
3827673Snate@binkert.org    def swig_module_name(self):
3837673Snate@binkert.org        return "%s_vector" % self.ptype_str
3843101Sstever@eecs.umich.edu
38511988Sandreas.sandberg@arm.com    def swig_predecls(self, code):
38611988Sandreas.sandberg@arm.com        code('%import "${{self.swig_module_name()}}.i"')
38711988Sandreas.sandberg@arm.com
38811988Sandreas.sandberg@arm.com    def swig_decl(self, code):
3897673Snate@binkert.org        code('%module(package="m5.internal") ${{self.swig_module_name()}}')
3907673Snate@binkert.org        code('%{')
3913101Sstever@eecs.umich.edu        self.ptype.cxx_predecls(code)
3923101Sstever@eecs.umich.edu        code('%}')
3933101Sstever@eecs.umich.edu        code()
3943101Sstever@eecs.umich.edu        # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
3953101Sstever@eecs.umich.edu        code('%include "std_container.i"')
3963101Sstever@eecs.umich.edu        code()
3973101Sstever@eecs.umich.edu        self.ptype.swig_predecls(code)
3983101Sstever@eecs.umich.edu        code()
3993101Sstever@eecs.umich.edu        code('%include "std_vector.i"')
4003101Sstever@eecs.umich.edu        code()
4013101Sstever@eecs.umich.edu
4023101Sstever@eecs.umich.edu        ptype = self.ptype_str
4033101Sstever@eecs.umich.edu        cxx_type = self.ptype.cxx_type
4043101Sstever@eecs.umich.edu
4053101Sstever@eecs.umich.edu        code('%template(vector_$ptype) std::vector< $cxx_type >;')
4065033Smilesck@eecs.umich.edu
4075033Smilesck@eecs.umich.edu    def cxx_predecls(self, code):
4083101Sstever@eecs.umich.edu        code('#include <vector>')
4093101Sstever@eecs.umich.edu        self.ptype.cxx_predecls(code)
4103101Sstever@eecs.umich.edu
4113101Sstever@eecs.umich.edu    def cxx_decl(self, code):
4123101Sstever@eecs.umich.edu        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
4133101Sstever@eecs.umich.edu
4143101Sstever@eecs.umich.educlass ParamFactory(object):
4153101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
4163101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
4173101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
4183101Sstever@eecs.umich.edu
4193101Sstever@eecs.umich.edu    def __getattr__(self, attr):
4203101Sstever@eecs.umich.edu        if self.ptype_str:
4213101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
4223101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
4233101Sstever@eecs.umich.edu
4243101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
4253101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
4263101Sstever@eecs.umich.edu        ptype = None
4273101Sstever@eecs.umich.edu        try:
4283101Sstever@eecs.umich.edu            ptype = allParams[self.ptype_str]
4293101Sstever@eecs.umich.edu        except KeyError:
4303101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
4313101Sstever@eecs.umich.edu            # try to resolve it later
4323101Sstever@eecs.umich.edu            pass
43310267SGeoffrey.Blake@arm.com        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
4347673Snate@binkert.org
4357673Snate@binkert.orgParam = ParamFactory(ParamDesc)
4367673Snate@binkert.orgVectorParam = ParamFactory(VectorParamDesc)
4377673Snate@binkert.org
4387673Snate@binkert.org#####################################################################
43910267SGeoffrey.Blake@arm.com#
44010267SGeoffrey.Blake@arm.com# Parameter Types
44110267SGeoffrey.Blake@arm.com#
44210267SGeoffrey.Blake@arm.com# Though native Python types could be used to specify parameter types
44310458Sandreas.hansson@arm.com# (the 'ptype' field of the Param and VectorParam classes), it's more
44410458Sandreas.hansson@arm.com# flexible to define our own set of types.  This gives us more control
44510458Sandreas.hansson@arm.com# over how Python expressions are converted to values (via the
44610458Sandreas.hansson@arm.com# __init__() constructor) and how these values are printed out (via
44710458Sandreas.hansson@arm.com# the __str__() conversion method).
4484762Snate@binkert.org#
4494762Snate@binkert.org#####################################################################
4503101Sstever@eecs.umich.edu
4513101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
4523101Sstever@eecs.umich.edu# built-in str class.
4533101Sstever@eecs.umich.educlass String(ParamValue,str):
4543101Sstever@eecs.umich.edu    cxx_type = 'std::string'
4553101Sstever@eecs.umich.edu    cmd_line_settable = True
4563101Sstever@eecs.umich.edu
4573101Sstever@eecs.umich.edu    @classmethod
4583101Sstever@eecs.umich.edu    def cxx_predecls(self, code):
4593101Sstever@eecs.umich.edu        code('#include <string>')
4603101Sstever@eecs.umich.edu
4613714Sstever@eecs.umich.edu    @classmethod
4623714Sstever@eecs.umich.edu    def swig_predecls(cls, code):
4633714Sstever@eecs.umich.edu        code('%include "std_string.i"')
4643714Sstever@eecs.umich.edu
4653714Sstever@eecs.umich.edu    def __call__(self, value):
4663714Sstever@eecs.umich.edu        self = value
4673101Sstever@eecs.umich.edu        return value
4683101Sstever@eecs.umich.edu
4693101Sstever@eecs.umich.edu    @classmethod
4703101Sstever@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
4713101Sstever@eecs.umich.edu        code('%s = %s;' % (dest, src))
4723101Sstever@eecs.umich.edu        code('%s true;' % ret)
4733101Sstever@eecs.umich.edu
4743101Sstever@eecs.umich.edu    def getValue(self):
4753101Sstever@eecs.umich.edu        return self
4763101Sstever@eecs.umich.edu
4773101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
4783101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
4793101Sstever@eecs.umich.edu# a new Latency object.
4803101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
4813101Sstever@eecs.umich.edu    def __str__(self):
4823101Sstever@eecs.umich.edu        return str(self.value)
4833101Sstever@eecs.umich.edu
4843101Sstever@eecs.umich.edu    def __float__(self):
4853101Sstever@eecs.umich.edu        return float(self.value)
4863101Sstever@eecs.umich.edu
4873101Sstever@eecs.umich.edu    def __long__(self):
4883101Sstever@eecs.umich.edu        return long(self.value)
4893101Sstever@eecs.umich.edu
4903101Sstever@eecs.umich.edu    def __int__(self):
49110380SAndrew.Bardsley@arm.com        return int(self.value)
49210380SAndrew.Bardsley@arm.com
49310380SAndrew.Bardsley@arm.com    # hook for bounds checking
49410458Sandreas.hansson@arm.com    def _check(self):
49510458Sandreas.hansson@arm.com        return
49610458Sandreas.hansson@arm.com
49710458Sandreas.hansson@arm.com    def __mul__(self, other):
49810458Sandreas.hansson@arm.com        newobj = self.__class__(self)
49910458Sandreas.hansson@arm.com        newobj.value *= other
50010458Sandreas.hansson@arm.com        newobj._check()
50110458Sandreas.hansson@arm.com        return newobj
50210458Sandreas.hansson@arm.com
50310458Sandreas.hansson@arm.com    __rmul__ = __mul__
50410458Sandreas.hansson@arm.com
50510458Sandreas.hansson@arm.com    def __div__(self, other):
50610458Sandreas.hansson@arm.com        newobj = self.__class__(self)
5073101Sstever@eecs.umich.edu        newobj.value /= other
5085033Smilesck@eecs.umich.edu        newobj._check()
5093101Sstever@eecs.umich.edu        return newobj
5103101Sstever@eecs.umich.edu
5113101Sstever@eecs.umich.edu    def __sub__(self, other):
5123101Sstever@eecs.umich.edu        newobj = self.__class__(self)
5133101Sstever@eecs.umich.edu        newobj.value -= other
5143101Sstever@eecs.umich.edu        newobj._check()
5153101Sstever@eecs.umich.edu        return newobj
5163101Sstever@eecs.umich.edu
5173101Sstever@eecs.umich.edu    def config_value(self):
5183101Sstever@eecs.umich.edu        return self.value
5193101Sstever@eecs.umich.edu
5203101Sstever@eecs.umich.edu    @classmethod
5215822Ssaidi@eecs.umich.edu    def cxx_ini_predecls(cls, code):
5225822Ssaidi@eecs.umich.edu        # Assume that base/str.hh will be included anyway
5233101Sstever@eecs.umich.edu        # code('#include "base/str.hh"')
5243101Sstever@eecs.umich.edu        pass
5253101Sstever@eecs.umich.edu
5263101Sstever@eecs.umich.edu    # The default for parsing PODs from an .ini entry is to extract from an
5273101Sstever@eecs.umich.edu    # istringstream and let overloading choose the right type according to
5283101Sstever@eecs.umich.edu    # the dest type.
5293101Sstever@eecs.umich.edu    @classmethod
5303101Sstever@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
5313101Sstever@eecs.umich.edu        code('%s to_number(%s, %s);' % (ret, src, dest))
5323101Sstever@eecs.umich.edu
5333101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
5343101Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue):
5353101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
53610267SGeoffrey.Blake@arm.com        super(CheckedIntType, cls).__init__(name, bases, dict)
5373101Sstever@eecs.umich.edu
5383101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
5393101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
5403101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
5413101Sstever@eecs.umich.edu        if name == 'CheckedInt':
5423101Sstever@eecs.umich.edu            return
5433101Sstever@eecs.umich.edu
5443101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
5453102Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
5463714Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
5473101Sstever@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
5483714Sstever@eecs.umich.edu                      name);
5493714Sstever@eecs.umich.edu            if cls.unsigned:
5503714Sstever@eecs.umich.edu                cls.min = 0
5513101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
5523101Sstever@eecs.umich.edu            else:
55310267SGeoffrey.Blake@arm.com                cls.min = -(2 ** (cls.size - 1))
55410267SGeoffrey.Blake@arm.com                cls.max = (2 ** (cls.size - 1)) - 1
55510267SGeoffrey.Blake@arm.com
55610267SGeoffrey.Blake@arm.com# Abstract superclass for bounds-checked integer parameters.  This
5577673Snate@binkert.org# class is subclassed to generate parameter classes with specific
5587673Snate@binkert.org# bounds.  Initialization of the min and max bounds is done in the
5597673Snate@binkert.org# metaclass CheckedIntType.__init__.
5607673Snate@binkert.orgclass CheckedInt(NumericParamValue):
5617673Snate@binkert.org    __metaclass__ = CheckedIntType
5624762Snate@binkert.org    cmd_line_settable = True
5634762Snate@binkert.org
5644762Snate@binkert.org    def _check(self):
5653101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
5663101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
5673101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
5683101Sstever@eecs.umich.edu
5693101Sstever@eecs.umich.edu    def __init__(self, value):
5703101Sstever@eecs.umich.edu        if isinstance(value, str):
5713101Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
5723101Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
5733101Sstever@eecs.umich.edu            self.value = long(value)
5743101Sstever@eecs.umich.edu        else:
5753101Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to CheckedInt" \
5763101Sstever@eecs.umich.edu                  % type(value).__name__
5773101Sstever@eecs.umich.edu        self._check()
5783101Sstever@eecs.umich.edu
5793101Sstever@eecs.umich.edu    def __call__(self, value):
5803101Sstever@eecs.umich.edu        self.__init__(value)
5813101Sstever@eecs.umich.edu        return value
5823101Sstever@eecs.umich.edu
5833101Sstever@eecs.umich.edu    @classmethod
5849184Sandreas.hansson@arm.com    def cxx_predecls(cls, code):
5859184Sandreas.hansson@arm.com        # most derived types require this, so we just do it here once
5869184Sandreas.hansson@arm.com        code('#include "base/types.hh"')
5879184Sandreas.hansson@arm.com
5889184Sandreas.hansson@arm.com    @classmethod
5899184Sandreas.hansson@arm.com    def swig_predecls(cls, code):
59011802Sandreas.sandberg@arm.com        # most derived types require this, so we just do it here once
5919184Sandreas.hansson@arm.com        code('%import "stdint.i"')
5929184Sandreas.hansson@arm.com        code('%import "base/types.hh"')
59310458Sandreas.hansson@arm.com
59410458Sandreas.hansson@arm.com    def getValue(self):
59510458Sandreas.hansson@arm.com        return long(self.value)
59610458Sandreas.hansson@arm.com
59710458Sandreas.hansson@arm.comclass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
59810458Sandreas.hansson@arm.comclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
59910458Sandreas.hansson@arm.com
60010458Sandreas.hansson@arm.comclass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
60110458Sandreas.hansson@arm.comclass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
60210458Sandreas.hansson@arm.comclass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
60310458Sandreas.hansson@arm.comclass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
60410458Sandreas.hansson@arm.comclass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
60510458Sandreas.hansson@arm.comclass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
60610458Sandreas.hansson@arm.comclass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
6073101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
6084446Sbinkertn@umich.edu
60910668SGeoffrey.Blake@arm.comclass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
6103101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
6115468Snate@binkert.orgclass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
61210267SGeoffrey.Blake@arm.comclass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6135468Snate@binkert.org
6145468Snate@binkert.orgclass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
6155468Snate@binkert.org
6165468Snate@binkert.orgclass Cycles(CheckedInt):
6175468Snate@binkert.org    cxx_type = 'Cycles'
61810267SGeoffrey.Blake@arm.com    size = 64
61910267SGeoffrey.Blake@arm.com    unsigned = True
62010267SGeoffrey.Blake@arm.com
62110267SGeoffrey.Blake@arm.com    def getValue(self):
6224762Snate@binkert.org        from m5.internal.core import Cycles
6234762Snate@binkert.org        return Cycles(self.value)
6244762Snate@binkert.org
62510380SAndrew.Bardsley@arm.com    @classmethod
62610380SAndrew.Bardsley@arm.com    def cxx_ini_predecls(cls, code):
62710380SAndrew.Bardsley@arm.com        # Assume that base/str.hh will be included anyway
62810458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
62910458Sandreas.hansson@arm.com        pass
63010458Sandreas.hansson@arm.com
63110458Sandreas.hansson@arm.com    @classmethod
63210458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
63310458Sandreas.hansson@arm.com        code('uint64_t _temp;')
63410458Sandreas.hansson@arm.com        code('bool _ret = to_number(%s, _temp);' % src)
63510458Sandreas.hansson@arm.com        code('if (_ret)')
6363101Sstever@eecs.umich.edu        code('    %s = Cycles(_temp);' % dest)
6373101Sstever@eecs.umich.edu        code('%s _ret;' % ret)
63810267SGeoffrey.Blake@arm.com
6393101Sstever@eecs.umich.educlass Float(ParamValue, float):
6403101Sstever@eecs.umich.edu    cxx_type = 'double'
6413101Sstever@eecs.umich.edu    cmd_line_settable = True
6423101Sstever@eecs.umich.edu
6433101Sstever@eecs.umich.edu    def __init__(self, value):
6443101Sstever@eecs.umich.edu        if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
6453102Sstever@eecs.umich.edu            self.value = float(value)
6463101Sstever@eecs.umich.edu        else:
6473101Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to Float" \
6483101Sstever@eecs.umich.edu                  % type(value).__name__
6494168Sbinkertn@umich.edu
65010267SGeoffrey.Blake@arm.com    def __call__(self, value):
6513101Sstever@eecs.umich.edu        self.__init__(value)
6523101Sstever@eecs.umich.edu        return value
6533101Sstever@eecs.umich.edu
6543101Sstever@eecs.umich.edu    def getValue(self):
6553101Sstever@eecs.umich.edu        return float(self.value)
6563101Sstever@eecs.umich.edu
6573102Sstever@eecs.umich.edu    def config_value(self):
6583101Sstever@eecs.umich.edu        return self
6593101Sstever@eecs.umich.edu
6603101Sstever@eecs.umich.edu    @classmethod
6613101Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
6623101Sstever@eecs.umich.edu        code('#include <sstream>')
6633101Sstever@eecs.umich.edu
6643101Sstever@eecs.umich.edu    @classmethod
6653101Sstever@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
6663101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
6673101Sstever@eecs.umich.edu
6683101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
66910317Smitch.hayenga@arm.com    cxx_type = 'uint64_t'
67010317Smitch.hayenga@arm.com    ex_str = '512MB'
67110317Smitch.hayenga@arm.com    size = 64
67210317Smitch.hayenga@arm.com    unsigned = True
67310317Smitch.hayenga@arm.com    def __init__(self, value):
6743102Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
67510317Smitch.hayenga@arm.com            self.value = value.value
67610317Smitch.hayenga@arm.com        else:
67710317Smitch.hayenga@arm.com            self.value = convert.toMemorySize(value)
67810317Smitch.hayenga@arm.com        self._check()
67910317Smitch.hayenga@arm.com
6803101Sstever@eecs.umich.educlass MemorySize32(CheckedInt):
6813584Ssaidi@eecs.umich.edu    cxx_type = 'uint32_t'
6823584Ssaidi@eecs.umich.edu    ex_str = '512MB'
6833584Ssaidi@eecs.umich.edu    size = 32
6843584Ssaidi@eecs.umich.edu    unsigned = True
6853584Ssaidi@eecs.umich.edu    def __init__(self, value):
68610267SGeoffrey.Blake@arm.com        if isinstance(value, MemorySize):
68710267SGeoffrey.Blake@arm.com            self.value = value.value
68810267SGeoffrey.Blake@arm.com        else:
68910267SGeoffrey.Blake@arm.com            self.value = convert.toMemorySize(value)
69010267SGeoffrey.Blake@arm.com        self._check()
69110267SGeoffrey.Blake@arm.com
6923101Sstever@eecs.umich.educlass Addr(CheckedInt):
6939232Sandreas.hansson@arm.com    cxx_type = 'Addr'
6949235Sandreas.hansson@arm.com    size = 64
6953101Sstever@eecs.umich.edu    unsigned = True
6963101Sstever@eecs.umich.edu    def __init__(self, value):
69710676Sandreas.hansson@arm.com        if isinstance(value, Addr):
6989411Sandreas.hansson@arm.com            self.value = value.value
69910676Sandreas.hansson@arm.com        else:
7009411Sandreas.hansson@arm.com            try:
7019411Sandreas.hansson@arm.com                # Often addresses are referred to with sizes. Ex: A device
7029411Sandreas.hansson@arm.com                # base address is at "512MB".  Use toMemorySize() to convert
7033101Sstever@eecs.umich.edu                # these into addresses. If the address is not specified with a
7049411Sandreas.hansson@arm.com                # "size", an exception will occur and numeric translation will
7059411Sandreas.hansson@arm.com                # proceed below.
7069411Sandreas.hansson@arm.com                self.value = convert.toMemorySize(value)
7073101Sstever@eecs.umich.edu            except (TypeError, ValueError):
7089232Sandreas.hansson@arm.com                # Convert number to string and use long() to do automatic
7093101Sstever@eecs.umich.edu                # base conversion (requires base=0 for auto-conversion)
7109232Sandreas.hansson@arm.com                self.value = long(str(value), base=0)
7113101Sstever@eecs.umich.edu
7123101Sstever@eecs.umich.edu        self._check()
7133101Sstever@eecs.umich.edu    def __add__(self, other):
7149411Sandreas.hansson@arm.com        if isinstance(other, Addr):
7159411Sandreas.hansson@arm.com            return self.value + other.value
7169411Sandreas.hansson@arm.com        else:
71710676Sandreas.hansson@arm.com            return self.value + other
71810676Sandreas.hansson@arm.com    def pretty_print(self, value):
7199411Sandreas.hansson@arm.com        try:
7209411Sandreas.hansson@arm.com            val = convert.toMemorySize(value)
7219411Sandreas.hansson@arm.com        except TypeError:
7229411Sandreas.hansson@arm.com            val = long(value)
7239411Sandreas.hansson@arm.com        return "0x%x" % long(val)
7243101Sstever@eecs.umich.edu
7259232Sandreas.hansson@arm.comclass AddrRange(ParamValue):
7263101Sstever@eecs.umich.edu    cxx_type = 'AddrRange'
7273101Sstever@eecs.umich.edu
7283101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
7293101Sstever@eecs.umich.edu        # Disable interleaving and hashing by default
7309232Sandreas.hansson@arm.com        self.intlvHighBit = 0
7313101Sstever@eecs.umich.edu        self.xorHighBit = 0
7325219Ssaidi@eecs.umich.edu        self.intlvBits = 0
7339232Sandreas.hansson@arm.com        self.intlvMatch = 0
7349232Sandreas.hansson@arm.com
7353101Sstever@eecs.umich.edu        def handle_kwargs(self, kwargs):
7369232Sandreas.hansson@arm.com            # An address range needs to have an upper limit, specified
7379232Sandreas.hansson@arm.com            # either explicitly with an end, or as an offset using the
7383101Sstever@eecs.umich.edu            # size keyword.
7393101Sstever@eecs.umich.edu            if 'end' in kwargs:
7409232Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
7419232Sandreas.hansson@arm.com            elif 'size' in kwargs:
7423101Sstever@eecs.umich.edu                self.end = self.start + Addr(kwargs.pop('size')) - 1
7433101Sstever@eecs.umich.edu            else:
7443101Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
7453101Sstever@eecs.umich.edu
7469232Sandreas.hansson@arm.com            # Now on to the optional bit
7473101Sstever@eecs.umich.edu            if 'intlvHighBit' in kwargs:
7483101Sstever@eecs.umich.edu                self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
74911620SMatthew.Poremba@amd.com            if 'xorHighBit' in kwargs:
75011620SMatthew.Poremba@amd.com                self.xorHighBit = int(kwargs.pop('xorHighBit'))
75111620SMatthew.Poremba@amd.com            if 'intlvBits' in kwargs:
7529232Sandreas.hansson@arm.com                self.intlvBits = int(kwargs.pop('intlvBits'))
7539232Sandreas.hansson@arm.com            if 'intlvMatch' in kwargs:
7549411Sandreas.hansson@arm.com                self.intlvMatch = int(kwargs.pop('intlvMatch'))
7559411Sandreas.hansson@arm.com
7563101Sstever@eecs.umich.edu        if len(args) == 0:
7577673Snate@binkert.org            self.start = Addr(kwargs.pop('start'))
7587673Snate@binkert.org            handle_kwargs(self, kwargs)
7599232Sandreas.hansson@arm.com
7609235Sandreas.hansson@arm.com        elif len(args) == 1:
7617675Snate@binkert.org            if kwargs:
7627675Snate@binkert.org                self.start = Addr(args[0])
76311988Sandreas.sandberg@arm.com                handle_kwargs(self, kwargs)
76411988Sandreas.sandberg@arm.com            elif isinstance(args[0], (list, tuple)):
76511988Sandreas.sandberg@arm.com                self.start = Addr(args[0][0])
76611988Sandreas.sandberg@arm.com                self.end = Addr(args[0][1])
76711988Sandreas.sandberg@arm.com            else:
76810458Sandreas.hansson@arm.com                self.start = Addr(0)
76910458Sandreas.hansson@arm.com                self.end = Addr(args[0]) - 1
77010458Sandreas.hansson@arm.com
77110458Sandreas.hansson@arm.com        elif len(args) == 2:
77210458Sandreas.hansson@arm.com            self.start = Addr(args[0])
77311620SMatthew.Poremba@amd.com            self.end = Addr(args[1])
77411620SMatthew.Poremba@amd.com        else:
77510458Sandreas.hansson@arm.com            raise TypeError, "Too many arguments specified"
77610458Sandreas.hansson@arm.com
77710458Sandreas.hansson@arm.com        if kwargs:
77810458Sandreas.hansson@arm.com            raise TypeError, "Too many keywords: %s" % kwargs.keys()
77910458Sandreas.hansson@arm.com
78011620SMatthew.Poremba@amd.com    def __str__(self):
78111620SMatthew.Poremba@amd.com        return '%s:%s' % (self.start, self.end)
78211620SMatthew.Poremba@amd.com
78311620SMatthew.Poremba@amd.com    def size(self):
78411620SMatthew.Poremba@amd.com        # Divide the size by the size of the interleaving slice
78511620SMatthew.Poremba@amd.com        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
78611620SMatthew.Poremba@amd.com
78711620SMatthew.Poremba@amd.com    @classmethod
78811620SMatthew.Poremba@amd.com    def cxx_predecls(cls, code):
78911620SMatthew.Poremba@amd.com        Addr.cxx_predecls(code)
79010458Sandreas.hansson@arm.com        code('#include "base/addr_range.hh"')
79110458Sandreas.hansson@arm.com
79210458Sandreas.hansson@arm.com    @classmethod
79311620SMatthew.Poremba@amd.com    def swig_predecls(cls, code):
79411620SMatthew.Poremba@amd.com        Addr.swig_predecls(code)
79510458Sandreas.hansson@arm.com
79610458Sandreas.hansson@arm.com    @classmethod
7974762Snate@binkert.org    def cxx_ini_predecls(cls, code):
79811991Sandreas.sandberg@arm.com        code('#include <sstream>')
79911802Sandreas.sandberg@arm.com
8004762Snate@binkert.org    @classmethod
8019411Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
80210676Sandreas.hansson@arm.com        code('uint64_t _start, _end;')
80310676Sandreas.hansson@arm.com        code('char _sep;')
8043101Sstever@eecs.umich.edu        code('std::istringstream _stream(${src});')
8053101Sstever@eecs.umich.edu        code('_stream >> _start;')
8063101Sstever@eecs.umich.edu        code('_stream.get(_sep);')
8073101Sstever@eecs.umich.edu        code('_stream >> _end;')
8083101Sstever@eecs.umich.edu        code('bool _ret = !_stream.fail() &&'
8093101Sstever@eecs.umich.edu            '_stream.eof() && _sep == \':\';')
81010267SGeoffrey.Blake@arm.com        code('if (_ret)')
81110267SGeoffrey.Blake@arm.com        code('   ${dest} = AddrRange(_start, _end);')
8123101Sstever@eecs.umich.edu        code('${ret} _ret;')
8133101Sstever@eecs.umich.edu
8143102Sstever@eecs.umich.edu    def getValue(self):
8153101Sstever@eecs.umich.edu        # Go from the Python class to the wrapped C++ class generated
8163101Sstever@eecs.umich.edu        # by swig
8173101Sstever@eecs.umich.edu        from m5.internal.range import AddrRange
81810267SGeoffrey.Blake@arm.com
81910267SGeoffrey.Blake@arm.com        return AddrRange(long(self.start), long(self.end),
82010267SGeoffrey.Blake@arm.com                         int(self.intlvHighBit), int(self.xorHighBit),
82110267SGeoffrey.Blake@arm.com                         int(self.intlvBits), int(self.intlvMatch))
8224762Snate@binkert.org
8234762Snate@binkert.org# Boolean parameter type.  Python doesn't let you subclass bool, since
8244762Snate@binkert.org# it doesn't want to let you create multiple instances of True and
8253101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
8263101Sstever@eecs.umich.educlass Bool(ParamValue):
8273101Sstever@eecs.umich.edu    cxx_type = 'bool'
8288934SBrad.Beckmann@amd.com    cmd_line_settable = True
8298934SBrad.Beckmann@amd.com
8308934SBrad.Beckmann@amd.com    def __init__(self, value):
8318934SBrad.Beckmann@amd.com        try:
8328934SBrad.Beckmann@amd.com            self.value = convert.toBool(value)
8333101Sstever@eecs.umich.edu        except TypeError:
8343101Sstever@eecs.umich.edu            self.value = bool(value)
8353101Sstever@eecs.umich.edu
8363101Sstever@eecs.umich.edu    def __call__(self, value):
8373101Sstever@eecs.umich.edu        self.__init__(value)
83810380SAndrew.Bardsley@arm.com        return value
83910380SAndrew.Bardsley@arm.com
84010380SAndrew.Bardsley@arm.com    def getValue(self):
84110458Sandreas.hansson@arm.com        return bool(self.value)
84210458Sandreas.hansson@arm.com
84310458Sandreas.hansson@arm.com    def __str__(self):
84410458Sandreas.hansson@arm.com        return str(self.value)
84510458Sandreas.hansson@arm.com
84610458Sandreas.hansson@arm.com    # implement truth value testing for Bool parameters so that these params
84710458Sandreas.hansson@arm.com    # evaluate correctly during the python configuration phase
84810458Sandreas.hansson@arm.com    def __nonzero__(self):
84910458Sandreas.hansson@arm.com        return bool(self.value)
85010458Sandreas.hansson@arm.com
8513101Sstever@eecs.umich.edu    def ini_str(self):
8523101Sstever@eecs.umich.edu        if self.value:
8533101Sstever@eecs.umich.edu            return 'true'
8543101Sstever@eecs.umich.edu        return 'false'
8553101Sstever@eecs.umich.edu
8563101Sstever@eecs.umich.edu    def config_value(self):
8573101Sstever@eecs.umich.edu        return self.value
8583101Sstever@eecs.umich.edu
8593101Sstever@eecs.umich.edu    @classmethod
8603101Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
8613101Sstever@eecs.umich.edu        # Assume that base/str.hh will be included anyway
8623101Sstever@eecs.umich.edu        # code('#include "base/str.hh"')
8634380Sbinkertn@umich.edu        pass
8644380Sbinkertn@umich.edu
8654380Sbinkertn@umich.edu    @classmethod
8663101Sstever@eecs.umich.edu    def cxx_ini_parse(cls, code, src, dest, ret):
8674380Sbinkertn@umich.edu        code('%s to_bool(%s, %s);' % (ret, src, dest))
8684380Sbinkertn@umich.edu
8694380Sbinkertn@umich.edudef IncEthernetAddr(addr, val = 1):
8703101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
8713101Sstever@eecs.umich.edu    bytes[5] += val
8723101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
87310267SGeoffrey.Blake@arm.com        val,rem = divmod(bytes[i], 256)
87410267SGeoffrey.Blake@arm.com        bytes[i] = rem
8757673Snate@binkert.org        if val == 0:
8767673Snate@binkert.org            break
8777673Snate@binkert.org        bytes[i - 1] += val
8787673Snate@binkert.org    assert(bytes[0] <= 255)
8797673Snate@binkert.org    return ':'.join(map(lambda x: '%02x' % x, bytes))
8803101Sstever@eecs.umich.edu
8813101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
8823101Sstever@eecs.umich.edudef NextEthernetAddr():
8833101Sstever@eecs.umich.edu    global _NextEthernetAddr
8843101Sstever@eecs.umich.edu
8853101Sstever@eecs.umich.edu    value = _NextEthernetAddr
8863101Sstever@eecs.umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
8873101Sstever@eecs.umich.edu    return value
8883101Sstever@eecs.umich.edu
8893101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
8903101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
8913101Sstever@eecs.umich.edu    ex_str = "00:90:00:00:00:01"
8923101Sstever@eecs.umich.edu    cmd_line_settable = True
8939941SGeoffrey.Blake@arm.com
8943101Sstever@eecs.umich.edu    @classmethod
8953101Sstever@eecs.umich.edu    def cxx_predecls(cls, code):
8963101Sstever@eecs.umich.edu        code('#include "base/inet.hh"')
8973101Sstever@eecs.umich.edu
89810267SGeoffrey.Blake@arm.com    @classmethod
89910267SGeoffrey.Blake@arm.com    def swig_predecls(cls, code):
90010267SGeoffrey.Blake@arm.com        code('%include "python/swig/inet.i"')
90110267SGeoffrey.Blake@arm.com
9023101Sstever@eecs.umich.edu    def __init__(self, value):
9033101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
9044380Sbinkertn@umich.edu            self.value = value
9053101Sstever@eecs.umich.edu            return
9063101Sstever@eecs.umich.edu
9074762Snate@binkert.org        if not isinstance(value, str):
90811988Sandreas.sandberg@arm.com            raise TypeError, "expected an ethernet address and didn't get one"
9094762Snate@binkert.org
9104762Snate@binkert.org        bytes = value.split(':')
91111228SAndrew.Bardsley@arm.com        if len(bytes) != 6:
91211228SAndrew.Bardsley@arm.com            raise TypeError, 'invalid ethernet address %s' % value
91311228SAndrew.Bardsley@arm.com
9144380Sbinkertn@umich.edu        for byte in bytes:
9154380Sbinkertn@umich.edu            if not 0 <= int(byte, base=16) <= 0xff:
9163101Sstever@eecs.umich.edu                raise TypeError, 'invalid ethernet address %s' % value
91710458Sandreas.hansson@arm.com
91810458Sandreas.hansson@arm.com        self.value = value
91910458Sandreas.hansson@arm.com
92010458Sandreas.hansson@arm.com    def __call__(self, value):
92110458Sandreas.hansson@arm.com        self.__init__(value)
9227777Sgblack@eecs.umich.edu        return value
9237777Sgblack@eecs.umich.edu
9247777Sgblack@eecs.umich.edu    def unproxy(self, base):
9257777Sgblack@eecs.umich.edu        if self.value == NextEthernetAddr:
92610267SGeoffrey.Blake@arm.com            return EthernetAddr(self.value())
92710267SGeoffrey.Blake@arm.com        return self
9287777Sgblack@eecs.umich.edu
9297777Sgblack@eecs.umich.edu    def getValue(self):
9307777Sgblack@eecs.umich.edu        from m5.internal.params import EthAddr
9317777Sgblack@eecs.umich.edu        return EthAddr(self.value)
9327777Sgblack@eecs.umich.edu
9337777Sgblack@eecs.umich.edu    def ini_str(self):
9347777Sgblack@eecs.umich.edu        return self.value
9357777Sgblack@eecs.umich.edu
9367777Sgblack@eecs.umich.edu    @classmethod
9377777Sgblack@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
9387777Sgblack@eecs.umich.edu        code('%s = Net::EthAddr(%s);' % (dest, src))
9397777Sgblack@eecs.umich.edu        code('%s true;' % ret)
9407777Sgblack@eecs.umich.edu
9417777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
9427777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
94310267SGeoffrey.Blake@arm.comclass IpAddress(ParamValue):
94410267SGeoffrey.Blake@arm.com    cxx_type = 'Net::IpAddress'
94510267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1"
94610267SGeoffrey.Blake@arm.com    cmd_line_settable = True
9478579Ssteve.reinhardt@amd.com
9488579Ssteve.reinhardt@amd.com    @classmethod
9498579Ssteve.reinhardt@amd.com    def cxx_predecls(cls, code):
9508579Ssteve.reinhardt@amd.com        code('#include "base/inet.hh"')
9518579Ssteve.reinhardt@amd.com
9528579Ssteve.reinhardt@amd.com    @classmethod
9538579Ssteve.reinhardt@amd.com    def swig_predecls(cls, code):
9548579Ssteve.reinhardt@amd.com        code('%include "python/swig/inet.i"')
9558579Ssteve.reinhardt@amd.com
9568579Ssteve.reinhardt@amd.com    def __init__(self, value):
9578579Ssteve.reinhardt@amd.com        if isinstance(value, IpAddress):
9588579Ssteve.reinhardt@amd.com            self.ip = value.ip
9598579Ssteve.reinhardt@amd.com        else:
9608579Ssteve.reinhardt@amd.com            try:
9618579Ssteve.reinhardt@amd.com                self.ip = convert.toIpAddress(value)
9628579Ssteve.reinhardt@amd.com            except TypeError:
9638579Ssteve.reinhardt@amd.com                self.ip = long(value)
9648579Ssteve.reinhardt@amd.com        self.verifyIp()
9657777Sgblack@eecs.umich.edu
9667777Sgblack@eecs.umich.edu    def __call__(self, value):
9677798Sgblack@eecs.umich.edu        self.__init__(value)
9687777Sgblack@eecs.umich.edu        return value
9697777Sgblack@eecs.umich.edu
97011988Sandreas.sandberg@arm.com    def __str__(self):
9717777Sgblack@eecs.umich.edu        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
9727777Sgblack@eecs.umich.edu        return '%d.%d.%d.%d' % tuple(tup)
9737777Sgblack@eecs.umich.edu
9747777Sgblack@eecs.umich.edu    def __eq__(self, other):
9757777Sgblack@eecs.umich.edu        if isinstance(other, IpAddress):
9767777Sgblack@eecs.umich.edu            return self.ip == other.ip
9777777Sgblack@eecs.umich.edu        elif isinstance(other, str):
97810267SGeoffrey.Blake@arm.com            try:
97910267SGeoffrey.Blake@arm.com                return self.ip == convert.toIpAddress(other)
9807777Sgblack@eecs.umich.edu            except:
9817777Sgblack@eecs.umich.edu                return False
9827777Sgblack@eecs.umich.edu        else:
9837777Sgblack@eecs.umich.edu            return self.ip == other
9847777Sgblack@eecs.umich.edu
9857777Sgblack@eecs.umich.edu    def __ne__(self, other):
9867777Sgblack@eecs.umich.edu        return not (self == other)
9877777Sgblack@eecs.umich.edu
9887777Sgblack@eecs.umich.edu    def verifyIp(self):
9897777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
9907777Sgblack@eecs.umich.edu            raise TypeError, "invalid ip address %#08x" % self.ip
9917777Sgblack@eecs.umich.edu
9927777Sgblack@eecs.umich.edu    def getValue(self):
9937777Sgblack@eecs.umich.edu        from m5.internal.params import IpAddress
9947777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
9957777Sgblack@eecs.umich.edu
9967777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
9977777Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
9987777Sgblack@eecs.umich.edu# positional or keyword arguments.
9997777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
10007777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
10017777Sgblack@eecs.umich.edu    ex_str = "127.0.0.0/24"
10027777Sgblack@eecs.umich.edu    cmd_line_settable = True
10037777Sgblack@eecs.umich.edu
10047777Sgblack@eecs.umich.edu    @classmethod
10057777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10067777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10077777Sgblack@eecs.umich.edu
10087777Sgblack@eecs.umich.edu    @classmethod
10097777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
10107777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
10117777Sgblack@eecs.umich.edu
10127777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10137777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10147777Sgblack@eecs.umich.edu            if key in kwargs:
10157777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10167777Sgblack@eecs.umich.edu            elif elseVal:
10177777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10187777Sgblack@eecs.umich.edu            else:
10197777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
10207777Sgblack@eecs.umich.edu
102110267SGeoffrey.Blake@arm.com        if len(args) == 0:
102210267SGeoffrey.Blake@arm.com            handle_kwarg(self, kwargs, 'ip')
102310267SGeoffrey.Blake@arm.com            handle_kwarg(self, kwargs, 'netmask')
102410267SGeoffrey.Blake@arm.com
10258579Ssteve.reinhardt@amd.com        elif len(args) == 1:
10268579Ssteve.reinhardt@amd.com            if kwargs:
10278579Ssteve.reinhardt@amd.com                if not 'ip' in kwargs and not 'netmask' in kwargs:
10288579Ssteve.reinhardt@amd.com                    raise TypeError, "Invalid arguments"
10298579Ssteve.reinhardt@amd.com                handle_kwarg(self, kwargs, 'ip', args[0])
10308579Ssteve.reinhardt@amd.com                handle_kwarg(self, kwargs, 'netmask', args[0])
10318579Ssteve.reinhardt@amd.com            elif isinstance(args[0], IpNetmask):
10328579Ssteve.reinhardt@amd.com                self.ip = args[0].ip
10338579Ssteve.reinhardt@amd.com                self.netmask = args[0].netmask
10348579Ssteve.reinhardt@amd.com            else:
10358579Ssteve.reinhardt@amd.com                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
10368579Ssteve.reinhardt@amd.com
10378579Ssteve.reinhardt@amd.com        elif len(args) == 2:
10388579Ssteve.reinhardt@amd.com            self.ip = args[0]
10397777Sgblack@eecs.umich.edu            self.netmask = args[1]
10407777Sgblack@eecs.umich.edu        else:
10417777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
10427777Sgblack@eecs.umich.edu
10437777Sgblack@eecs.umich.edu        if kwargs:
10447777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
104511988Sandreas.sandberg@arm.com
10467777Sgblack@eecs.umich.edu        self.verify()
10477777Sgblack@eecs.umich.edu
10487777Sgblack@eecs.umich.edu    def __call__(self, value):
10497777Sgblack@eecs.umich.edu        self.__init__(value)
10507777Sgblack@eecs.umich.edu        return value
10517777Sgblack@eecs.umich.edu
105210267SGeoffrey.Blake@arm.com    def __str__(self):
105310267SGeoffrey.Blake@arm.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
10547777Sgblack@eecs.umich.edu
10557777Sgblack@eecs.umich.edu    def __eq__(self, other):
10567777Sgblack@eecs.umich.edu        if isinstance(other, IpNetmask):
10577777Sgblack@eecs.umich.edu            return self.ip == other.ip and self.netmask == other.netmask
10587777Sgblack@eecs.umich.edu        elif isinstance(other, str):
10597777Sgblack@eecs.umich.edu            try:
10607777Sgblack@eecs.umich.edu                return (self.ip, self.netmask) == convert.toIpNetmask(other)
10617777Sgblack@eecs.umich.edu            except:
10627777Sgblack@eecs.umich.edu                return False
10637777Sgblack@eecs.umich.edu        else:
10647777Sgblack@eecs.umich.edu            return False
10657777Sgblack@eecs.umich.edu
10667777Sgblack@eecs.umich.edu    def verify(self):
10677777Sgblack@eecs.umich.edu        self.verifyIp()
10687777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
10697777Sgblack@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
10707777Sgblack@eecs.umich.edu
10717777Sgblack@eecs.umich.edu    def getValue(self):
10727777Sgblack@eecs.umich.edu        from m5.internal.params import IpNetmask
10737777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
10747777Sgblack@eecs.umich.edu
10757777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
10767777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
10777777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
10787777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
10797777Sgblack@eecs.umich.edu    ex_str = "127.0.0.1:80"
10807777Sgblack@eecs.umich.edu    cmd_line_settable = True
10817777Sgblack@eecs.umich.edu
10827777Sgblack@eecs.umich.edu    @classmethod
10837777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10847777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10857777Sgblack@eecs.umich.edu
10867777Sgblack@eecs.umich.edu    @classmethod
10877777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
10887777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
10897777Sgblack@eecs.umich.edu
10907777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10917777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10927777Sgblack@eecs.umich.edu            if key in kwargs:
10937777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10947777Sgblack@eecs.umich.edu            elif elseVal:
109510267SGeoffrey.Blake@arm.com                setattr(self, key, elseVal)
109610267SGeoffrey.Blake@arm.com            else:
109710267SGeoffrey.Blake@arm.com                raise TypeError, "No value set for %s" % key
109810267SGeoffrey.Blake@arm.com
10998579Ssteve.reinhardt@amd.com        if len(args) == 0:
11008579Ssteve.reinhardt@amd.com            handle_kwarg(self, kwargs, 'ip')
11018579Ssteve.reinhardt@amd.com            handle_kwarg(self, kwargs, 'port')
11028579Ssteve.reinhardt@amd.com
11038579Ssteve.reinhardt@amd.com        elif len(args) == 1:
11048579Ssteve.reinhardt@amd.com            if kwargs:
11058579Ssteve.reinhardt@amd.com                if not 'ip' in kwargs and not 'port' in kwargs:
11068579Ssteve.reinhardt@amd.com                    raise TypeError, "Invalid arguments"
11078579Ssteve.reinhardt@amd.com                handle_kwarg(self, kwargs, 'ip', args[0])
11088579Ssteve.reinhardt@amd.com                handle_kwarg(self, kwargs, 'port', args[0])
11098579Ssteve.reinhardt@amd.com            elif isinstance(args[0], IpWithPort):
11108579Ssteve.reinhardt@amd.com                self.ip = args[0].ip
11118579Ssteve.reinhardt@amd.com                self.port = args[0].port
11128579Ssteve.reinhardt@amd.com            else:
11137777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
11147777Sgblack@eecs.umich.edu
11157777Sgblack@eecs.umich.edu        elif len(args) == 2:
11167777Sgblack@eecs.umich.edu            self.ip = args[0]
11177777Sgblack@eecs.umich.edu            self.port = args[1]
11187777Sgblack@eecs.umich.edu        else:
111911988Sandreas.sandberg@arm.com            raise TypeError, "Too many arguments specified"
11207777Sgblack@eecs.umich.edu
11217777Sgblack@eecs.umich.edu        if kwargs:
11223932Sbinkertn@umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
112310380SAndrew.Bardsley@arm.com
11243932Sbinkertn@umich.edu        self.verify()
11253932Sbinkertn@umich.edu
11263932Sbinkertn@umich.edu    def __call__(self, value):
11273932Sbinkertn@umich.edu        self.__init__(value)
11283932Sbinkertn@umich.edu        return value
11293932Sbinkertn@umich.edu
11303932Sbinkertn@umich.edu    def __str__(self):
11313932Sbinkertn@umich.edu        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
11323932Sbinkertn@umich.edu
11333932Sbinkertn@umich.edu    def __eq__(self, other):
11343932Sbinkertn@umich.edu        if isinstance(other, IpWithPort):
11353885Sbinkertn@umich.edu            return self.ip == other.ip and self.port == other.port
11363932Sbinkertn@umich.edu        elif isinstance(other, str):
11373932Sbinkertn@umich.edu            try:
11383885Sbinkertn@umich.edu                return (self.ip, self.port) == convert.toIpWithPort(other)
11393932Sbinkertn@umich.edu            except:
11403932Sbinkertn@umich.edu                return False
11413932Sbinkertn@umich.edu        else:
11423932Sbinkertn@umich.edu            return False
11433932Sbinkertn@umich.edu
11443932Sbinkertn@umich.edu    def verify(self):
11453932Sbinkertn@umich.edu        self.verifyIp()
11463932Sbinkertn@umich.edu        if self.port < 0 or self.port > 0xffff:
11473932Sbinkertn@umich.edu            raise TypeError, "invalid port %d" % self.port
11483932Sbinkertn@umich.edu
11493932Sbinkertn@umich.edu    def getValue(self):
11503932Sbinkertn@umich.edu        from m5.internal.params import IpWithPort
11513932Sbinkertn@umich.edu        return IpWithPort(self.ip, self.port)
11523932Sbinkertn@umich.edu
11533932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
11543932Sbinkertn@umich.edu                 "%a %b %d %H:%M:%S %Y",
11553932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
11563932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
11573885Sbinkertn@umich.edu                 "%Y/%m/%d",
11583885Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
11593885Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
11603885Sbinkertn@umich.edu                 "%m/%d/%Y",
11614762Snate@binkert.org                 "%m/%d/%y %H:%M:%S",
11627673Snate@binkert.org                 "%m/%d/%y %H:%M",
11637673Snate@binkert.org                 "%m/%d/%y"]
11647673Snate@binkert.org
11657673Snate@binkert.org
11667673Snate@binkert.orgdef parse_time(value):
11673885Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
11683932Sbinkertn@umich.edu    from datetime import datetime, date
11693885Sbinkertn@umich.edu
117010267SGeoffrey.Blake@arm.com    if isinstance(value, struct_time):
117110267SGeoffrey.Blake@arm.com        return value
117210267SGeoffrey.Blake@arm.com
117310267SGeoffrey.Blake@arm.com    if isinstance(value, (int, long)):
11744762Snate@binkert.org        return gmtime(value)
117511988Sandreas.sandberg@arm.com
117611988Sandreas.sandberg@arm.com    if isinstance(value, (datetime, date)):
11774762Snate@binkert.org        return value.timetuple()
117811988Sandreas.sandberg@arm.com
11794762Snate@binkert.org    if isinstance(value, str):
11803885Sbinkertn@umich.edu        if value in ('Now', 'Today'):
11814762Snate@binkert.org            return time.gmtime(time.time())
11823885Sbinkertn@umich.edu
11833885Sbinkertn@umich.edu        for format in time_formats:
11843932Sbinkertn@umich.edu            try:
11853885Sbinkertn@umich.edu                return strptime(value, format)
11868664SAli.Saidi@ARM.com            except ValueError:
118710380SAndrew.Bardsley@arm.com                pass
11888664SAli.Saidi@ARM.com
11898664SAli.Saidi@ARM.com    raise ValueError, "Could not parse '%s' as a time" % value
119010458Sandreas.hansson@arm.com
119110458Sandreas.hansson@arm.comclass Time(ParamValue):
119210458Sandreas.hansson@arm.com    cxx_type = 'tm'
119310458Sandreas.hansson@arm.com
119410458Sandreas.hansson@arm.com    @classmethod
119510458Sandreas.hansson@arm.com    def cxx_predecls(cls, code):
119610458Sandreas.hansson@arm.com        code('#include <time.h>')
119710458Sandreas.hansson@arm.com
119810458Sandreas.hansson@arm.com    @classmethod
119910458Sandreas.hansson@arm.com    def swig_predecls(cls, code):
12003101Sstever@eecs.umich.edu        code('%include "python/swig/time.i"')
12013101Sstever@eecs.umich.edu
12023101Sstever@eecs.umich.edu    def __init__(self, value):
12033101Sstever@eecs.umich.edu        self.value = parse_time(value)
12043101Sstever@eecs.umich.edu
12053101Sstever@eecs.umich.edu    def __call__(self, value):
12063101Sstever@eecs.umich.edu        self.__init__(value)
12073101Sstever@eecs.umich.edu        return value
12083101Sstever@eecs.umich.edu
12093101Sstever@eecs.umich.edu    def getValue(self):
12103101Sstever@eecs.umich.edu        from m5.internal.params import tm
12113101Sstever@eecs.umich.edu
12123101Sstever@eecs.umich.edu        c_time = tm()
12133101Sstever@eecs.umich.edu        py_time = self.value
12144762Snate@binkert.org
12153101Sstever@eecs.umich.edu        # UNIX is years since 1900
12165033Smilesck@eecs.umich.edu        c_time.tm_year = py_time.tm_year - 1900;
12174762Snate@binkert.org
12184762Snate@binkert.org        # Python starts at 1, UNIX starts at 0
12194762Snate@binkert.org        c_time.tm_mon =  py_time.tm_mon - 1;
12204762Snate@binkert.org        c_time.tm_mday = py_time.tm_mday;
12214762Snate@binkert.org        c_time.tm_hour = py_time.tm_hour;
12224762Snate@binkert.org        c_time.tm_min = py_time.tm_min;
12234762Snate@binkert.org        c_time.tm_sec = py_time.tm_sec;
12243101Sstever@eecs.umich.edu
12253101Sstever@eecs.umich.edu        # Python has 0 as Monday, UNIX is 0 as sunday
12263101Sstever@eecs.umich.edu        c_time.tm_wday = py_time.tm_wday + 1
12273101Sstever@eecs.umich.edu        if c_time.tm_wday > 6:
12283101Sstever@eecs.umich.edu            c_time.tm_wday -= 7;
12293101Sstever@eecs.umich.edu
12303101Sstever@eecs.umich.edu        # Python starts at 1, Unix starts at 0
12313101Sstever@eecs.umich.edu        c_time.tm_yday = py_time.tm_yday - 1;
12323101Sstever@eecs.umich.edu
12333101Sstever@eecs.umich.edu        return c_time
12343101Sstever@eecs.umich.edu
12353101Sstever@eecs.umich.edu    def __str__(self):
12363101Sstever@eecs.umich.edu        return time.asctime(self.value)
12373101Sstever@eecs.umich.edu
12383101Sstever@eecs.umich.edu    def ini_str(self):
12393101Sstever@eecs.umich.edu        return str(self)
12403101Sstever@eecs.umich.edu
12413101Sstever@eecs.umich.edu    def get_config_as_dict(self):
12423101Sstever@eecs.umich.edu        assert false
12433101Sstever@eecs.umich.edu        return str(self)
12444762Snate@binkert.org
12453101Sstever@eecs.umich.edu    @classmethod
12463101Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
12473101Sstever@eecs.umich.edu        code('#include <time.h>')
12483101Sstever@eecs.umich.edu
12493101Sstever@eecs.umich.edu    @classmethod
12503101Sstever@eecs.umich.edu    def cxx_ini_parse(cls, code, src, dest, ret):
12517673Snate@binkert.org        code('char *_parse_ret = strptime((${src}).c_str(),')
125210201SAndrew.Bardsley@arm.com        code('    "%a %b %d %H:%M:%S %Y", &(${dest}));')
125310201SAndrew.Bardsley@arm.com        code('${ret} _parse_ret && *_parse_ret == \'\\0\';');
125410201SAndrew.Bardsley@arm.com
125510201SAndrew.Bardsley@arm.com# Enumerated types are a little more complex.  The user specifies the
125610201SAndrew.Bardsley@arm.com# type as Enum(foo) where foo is either a list or dictionary of
12577673Snate@binkert.org# alternatives (typically strings, but not necessarily so).  (In the
125810201SAndrew.Bardsley@arm.com# long run, the integer value of the parameter will be the list index
125910201SAndrew.Bardsley@arm.com# or the corresponding dictionary value.  For now, since we only check
12607673Snate@binkert.org# that the alternative is valid and then spit it into a .ini file,
126110201SAndrew.Bardsley@arm.com# there's not much point in using the dictionary.)
12627673Snate@binkert.org
12637673Snate@binkert.org# What Enum() must do is generate a new type encapsulating the
12647673Snate@binkert.org# provided list/dictionary so that specific values of the parameter
12654762Snate@binkert.org# can be instances of that type.  We define two hidden internal
12667673Snate@binkert.org# classes (_ListEnum and _DictEnum) to serve as base classes, then
12678902Sandreas.hansson@arm.com# derive the new type from the appropriate base class on the fly.
12687673Snate@binkert.org
126910201SAndrew.Bardsley@arm.comallEnums = {}
12704762Snate@binkert.org# Metaclass for Enum types
127110201SAndrew.Bardsley@arm.comclass MetaEnum(MetaParamValue):
127210201SAndrew.Bardsley@arm.com    def __new__(mcls, name, bases, dict):
127310201SAndrew.Bardsley@arm.com        assert name not in allEnums
127410201SAndrew.Bardsley@arm.com
127510201SAndrew.Bardsley@arm.com        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
127610201SAndrew.Bardsley@arm.com        allEnums[name] = cls
127710201SAndrew.Bardsley@arm.com        return cls
127810201SAndrew.Bardsley@arm.com
127910201SAndrew.Bardsley@arm.com    def __init__(cls, name, bases, init_dict):
12807673Snate@binkert.org        if init_dict.has_key('map'):
12817673Snate@binkert.org            if not isinstance(cls.map, dict):
128210201SAndrew.Bardsley@arm.com                raise TypeError, "Enum-derived class attribute 'map' " \
128310201SAndrew.Bardsley@arm.com                      "must be of type dict"
128410201SAndrew.Bardsley@arm.com            # build list of value strings from map
128510201SAndrew.Bardsley@arm.com            cls.vals = cls.map.keys()
128610201SAndrew.Bardsley@arm.com            cls.vals.sort()
128710201SAndrew.Bardsley@arm.com        elif init_dict.has_key('vals'):
128810201SAndrew.Bardsley@arm.com            if not isinstance(cls.vals, list):
128910201SAndrew.Bardsley@arm.com                raise TypeError, "Enum-derived class attribute 'vals' " \
129010201SAndrew.Bardsley@arm.com                      "must be of type list"
129110201SAndrew.Bardsley@arm.com            # build string->value map from vals sequence
129210201SAndrew.Bardsley@arm.com            cls.map = {}
129310201SAndrew.Bardsley@arm.com            for idx,val in enumerate(cls.vals):
129410201SAndrew.Bardsley@arm.com                cls.map[val] = idx
129510201SAndrew.Bardsley@arm.com        else:
129610201SAndrew.Bardsley@arm.com            raise TypeError, "Enum-derived class must define "\
12974762Snate@binkert.org                  "attribute 'map' or 'vals'"
12987673Snate@binkert.org
129910201SAndrew.Bardsley@arm.com        cls.cxx_type = 'Enums::%s' % name
130010201SAndrew.Bardsley@arm.com
130110201SAndrew.Bardsley@arm.com        super(MetaEnum, cls).__init__(name, bases, init_dict)
130210201SAndrew.Bardsley@arm.com
130310201SAndrew.Bardsley@arm.com    # Generate C++ class declaration for this enum type.
130410201SAndrew.Bardsley@arm.com    # Note that we wrap the enum in a class/struct to act as a namespace,
13053101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
130611988Sandreas.sandberg@arm.com    def cxx_decl(cls, code):
130711988Sandreas.sandberg@arm.com        wrapper_name = cls.wrapper_name
130811988Sandreas.sandberg@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
130911988Sandreas.sandberg@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
131011988Sandreas.sandberg@arm.com        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
131111988Sandreas.sandberg@arm.com
131211988Sandreas.sandberg@arm.com        code('''\
131311988Sandreas.sandberg@arm.com#ifndef $idem_macro
131411988Sandreas.sandberg@arm.com#define $idem_macro
131511988Sandreas.sandberg@arm.com
131611988Sandreas.sandberg@arm.com$wrapper $wrapper_name {
131711988Sandreas.sandberg@arm.com    enum $name {
131811988Sandreas.sandberg@arm.com''')
131911988Sandreas.sandberg@arm.com        code.indent(2)
132011988Sandreas.sandberg@arm.com        for val in cls.vals:
132111988Sandreas.sandberg@arm.com            code('$val = ${{cls.map[val]}},')
132211988Sandreas.sandberg@arm.com        code('Num_$name = ${{len(cls.vals)}}')
132311988Sandreas.sandberg@arm.com        code.dedent(2)
132411988Sandreas.sandberg@arm.com        code('    };')
132511988Sandreas.sandberg@arm.com
132611988Sandreas.sandberg@arm.com        if cls.wrapper_is_struct:
132711988Sandreas.sandberg@arm.com            code('    static const char *${name}Strings[Num_${name}];')
132811988Sandreas.sandberg@arm.com            code('};')
132911988Sandreas.sandberg@arm.com        else:
133011988Sandreas.sandberg@arm.com            code('extern const char *${name}Strings[Num_${name}];')
133111988Sandreas.sandberg@arm.com            code('}')
133211988Sandreas.sandberg@arm.com
133311988Sandreas.sandberg@arm.com        code()
133411988Sandreas.sandberg@arm.com        code('#endif // $idem_macro')
133511988Sandreas.sandberg@arm.com
133611988Sandreas.sandberg@arm.com    def cxx_def(cls, code):
133711988Sandreas.sandberg@arm.com        wrapper_name = cls.wrapper_name
133811988Sandreas.sandberg@arm.com        file_name = cls.__name__
133911988Sandreas.sandberg@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
13408596Ssteve.reinhardt@amd.com
13413101Sstever@eecs.umich.edu        code('#include "enums/$file_name.hh"')
13423101Sstever@eecs.umich.edu        if cls.wrapper_is_struct:
13433101Sstever@eecs.umich.edu            code('const char *${wrapper_name}::${name}Strings'
13443101Sstever@eecs.umich.edu                '[Num_${name}] =')
134510267SGeoffrey.Blake@arm.com        else:
13463101Sstever@eecs.umich.edu            code('namespace Enums {')
134710201SAndrew.Bardsley@arm.com            code.indent(1)
134810201SAndrew.Bardsley@arm.com            code(' const char *${name}Strings[Num_${name}] =')
134910201SAndrew.Bardsley@arm.com
135010201SAndrew.Bardsley@arm.com        code('{')
135110201SAndrew.Bardsley@arm.com        code.indent(1)
135210201SAndrew.Bardsley@arm.com        for val in cls.vals:
135310201SAndrew.Bardsley@arm.com            code('"$val",')
135410201SAndrew.Bardsley@arm.com        code.dedent(1)
135510201SAndrew.Bardsley@arm.com        code('};')
13563101Sstever@eecs.umich.edu
13573101Sstever@eecs.umich.edu        if not cls.wrapper_is_struct:
13583101Sstever@eecs.umich.edu            code('} // namespace $wrapper_name')
13593101Sstever@eecs.umich.edu            code.dedent(1)
13603101Sstever@eecs.umich.edu
13613101Sstever@eecs.umich.edu    def swig_decl(cls, code):
136210267SGeoffrey.Blake@arm.com        name = cls.__name__
136310267SGeoffrey.Blake@arm.com        code('''\
136410267SGeoffrey.Blake@arm.com%module(package="m5.internal") enum_$name
136510267SGeoffrey.Blake@arm.com
13667675Snate@binkert.org%{
13677675Snate@binkert.org#include "enums/$name.hh"
13687675Snate@binkert.org%}
13697675Snate@binkert.org
13707675Snate@binkert.org%include "enums/$name.hh"
137110458Sandreas.hansson@arm.com''')
137210458Sandreas.hansson@arm.com
137310458Sandreas.hansson@arm.com
137410458Sandreas.hansson@arm.com# Base class for enum types.
137510458Sandreas.hansson@arm.comclass Enum(ParamValue):
137610458Sandreas.hansson@arm.com    __metaclass__ = MetaEnum
137710458Sandreas.hansson@arm.com    vals = []
137810458Sandreas.hansson@arm.com    cmd_line_settable = True
137910458Sandreas.hansson@arm.com
138010458Sandreas.hansson@arm.com    # The name of the wrapping namespace or struct
138110458Sandreas.hansson@arm.com    wrapper_name = 'Enums'
138210458Sandreas.hansson@arm.com
13834762Snate@binkert.org    # If true, the enum is wrapped in a struct rather than a namespace
138411988Sandreas.sandberg@arm.com    wrapper_is_struct = False
138511988Sandreas.sandberg@arm.com
138611988Sandreas.sandberg@arm.com    # If not None, use this as the enum name rather than this class name
13874762Snate@binkert.org    enum_name = None
13883101Sstever@eecs.umich.edu
13893101Sstever@eecs.umich.edu    def __init__(self, value):
13903101Sstever@eecs.umich.edu        if value not in self.map:
13913101Sstever@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
13923101Sstever@eecs.umich.edu                  % (value, self.vals)
13933101Sstever@eecs.umich.edu        self.value = value
13944167Sbinkertn@umich.edu
13953101Sstever@eecs.umich.edu    def __call__(self, value):
139610267SGeoffrey.Blake@arm.com        self.__init__(value)
139710267SGeoffrey.Blake@arm.com        return value
13987673Snate@binkert.org
13997673Snate@binkert.org    @classmethod
14007673Snate@binkert.org    def cxx_predecls(cls, code):
14017673Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
14027673Snate@binkert.org
140310267SGeoffrey.Blake@arm.com    @classmethod
140410267SGeoffrey.Blake@arm.com    def swig_predecls(cls, code):
140510267SGeoffrey.Blake@arm.com        code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
140610267SGeoffrey.Blake@arm.com
14074762Snate@binkert.org    @classmethod
14084762Snate@binkert.org    def cxx_ini_parse(cls, code, src, dest, ret):
14094762Snate@binkert.org        code('if (false) {')
141010458Sandreas.hansson@arm.com        for elem_name in cls.map.iterkeys():
141110458Sandreas.hansson@arm.com            code('} else if (%s == "%s") {' % (src, elem_name))
141210458Sandreas.hansson@arm.com            code.indent()
141310458Sandreas.hansson@arm.com            code('%s = Enums::%s;' % (dest, elem_name))
141410458Sandreas.hansson@arm.com            code('%s true;' % ret)
141510458Sandreas.hansson@arm.com            code.dedent()
141610458Sandreas.hansson@arm.com        code('} else {')
141710458Sandreas.hansson@arm.com        code('    %s false;' % ret)
141810458Sandreas.hansson@arm.com        code('}')
141910458Sandreas.hansson@arm.com
14204167Sbinkertn@umich.edu    def getValue(self):
142110267SGeoffrey.Blake@arm.com        return int(self.map[self.value])
142210267SGeoffrey.Blake@arm.com
14233101Sstever@eecs.umich.edu    def __str__(self):
14244167Sbinkertn@umich.edu        return self.value
14254167Sbinkertn@umich.edu
14264167Sbinkertn@umich.edu# how big does a rounding error need to be before we warn about it?
14274167Sbinkertn@umich.edufrequency_tolerance = 0.001  # 0.1%
14284167Sbinkertn@umich.edu
14294167Sbinkertn@umich.educlass TickParamValue(NumericParamValue):
14304167Sbinkertn@umich.edu    cxx_type = 'Tick'
14314167Sbinkertn@umich.edu    ex_str = "1MHz"
14324167Sbinkertn@umich.edu    cmd_line_settable = True
14334167Sbinkertn@umich.edu
14344167Sbinkertn@umich.edu    @classmethod
14354167Sbinkertn@umich.edu    def cxx_predecls(cls, code):
14363101Sstever@eecs.umich.edu        code('#include "base/types.hh"')
143710267SGeoffrey.Blake@arm.com
143810267SGeoffrey.Blake@arm.com    @classmethod
143910267SGeoffrey.Blake@arm.com    def swig_predecls(cls, code):
144010267SGeoffrey.Blake@arm.com        code('%import "stdint.i"')
14413101Sstever@eecs.umich.edu        code('%import "base/types.hh"')
14423101Sstever@eecs.umich.edu
14433101Sstever@eecs.umich.edu    def __call__(self, value):
14443101Sstever@eecs.umich.edu        self.__init__(value)
14453101Sstever@eecs.umich.edu        return value
14463101Sstever@eecs.umich.edu
14473101Sstever@eecs.umich.edu    def getValue(self):
14484762Snate@binkert.org        return long(self.value)
14494762Snate@binkert.org
14504762Snate@binkert.org    @classmethod
14514762Snate@binkert.org    def cxx_ini_predecls(cls, code):
14524762Snate@binkert.org        code('#include <sstream>')
14534762Snate@binkert.org
14544762Snate@binkert.org    # Ticks are expressed in seconds in JSON files and in plain
145510380SAndrew.Bardsley@arm.com    # Ticks in .ini files.  Switch based on a config flag
145610380SAndrew.Bardsley@arm.com    @classmethod
145710380SAndrew.Bardsley@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
14583101Sstever@eecs.umich.edu        code('${ret} to_number(${src}, ${dest});')
14593101Sstever@eecs.umich.edu
14604762Snate@binkert.orgclass Latency(TickParamValue):
14613101Sstever@eecs.umich.edu    ex_str = "100ns"
14624167Sbinkertn@umich.edu
146310267SGeoffrey.Blake@arm.com    def __init__(self, value):
146410267SGeoffrey.Blake@arm.com        if isinstance(value, (Latency, Clock)):
14653101Sstever@eecs.umich.edu            self.ticks = value.ticks
14664167Sbinkertn@umich.edu            self.value = value.value
14674167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
14684167Sbinkertn@umich.edu            self.ticks = value.ticks
14694167Sbinkertn@umich.edu            self.value = 1.0 / value.value
14704167Sbinkertn@umich.edu        elif value.endswith('t'):
14714167Sbinkertn@umich.edu            self.ticks = True
14724167Sbinkertn@umich.edu            self.value = int(value[:-1])
14734167Sbinkertn@umich.edu        else:
14744167Sbinkertn@umich.edu            self.ticks = False
14754167Sbinkertn@umich.edu            self.value = convert.toLatency(value)
14764167Sbinkertn@umich.edu
14774167Sbinkertn@umich.edu    def __call__(self, value):
14783101Sstever@eecs.umich.edu        self.__init__(value)
147910267SGeoffrey.Blake@arm.com        return value
148010267SGeoffrey.Blake@arm.com
148110267SGeoffrey.Blake@arm.com    def __getattr__(self, attr):
148210267SGeoffrey.Blake@arm.com        if attr in ('latency', 'period'):
14833101Sstever@eecs.umich.edu            return self
14843101Sstever@eecs.umich.edu        if attr == 'frequency':
14853101Sstever@eecs.umich.edu            return Frequency(self)
14863101Sstever@eecs.umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
14873101Sstever@eecs.umich.edu
14883101Sstever@eecs.umich.edu    def getValue(self):
14893101Sstever@eecs.umich.edu        if self.ticks or self.value == 0:
14904167Sbinkertn@umich.edu            value = self.value
14914762Snate@binkert.org        else:
14924762Snate@binkert.org            value = ticks.fromSeconds(self.value)
14934762Snate@binkert.org        return long(value)
14944762Snate@binkert.org
14954762Snate@binkert.org    def config_value(self):
14964762Snate@binkert.org        return self.getValue()
14974762Snate@binkert.org
149810380SAndrew.Bardsley@arm.com    # convert latency to ticks
149910380SAndrew.Bardsley@arm.com    def ini_str(self):
150010380SAndrew.Bardsley@arm.com        return '%d' % self.getValue()
15013101Sstever@eecs.umich.edu
15024762Snate@binkert.orgclass Frequency(TickParamValue):
15033101Sstever@eecs.umich.edu    ex_str = "1GHz"
150410019Sandreas.hansson@arm.com
150510019Sandreas.hansson@arm.com    def __init__(self, value):
150610019Sandreas.hansson@arm.com        if isinstance(value, (Latency, Clock)):
15073101Sstever@eecs.umich.edu            if value.value == 0:
15084167Sbinkertn@umich.edu                self.value = 0
15094167Sbinkertn@umich.edu            else:
15104167Sbinkertn@umich.edu                self.value = 1.0 / value.value
15114167Sbinkertn@umich.edu            self.ticks = value.ticks
15124167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
15134167Sbinkertn@umich.edu            self.value = value.value
15144167Sbinkertn@umich.edu            self.ticks = value.ticks
15154167Sbinkertn@umich.edu        else:
15164167Sbinkertn@umich.edu            self.ticks = False
15174167Sbinkertn@umich.edu            self.value = convert.toFrequency(value)
15184167Sbinkertn@umich.edu
15194167Sbinkertn@umich.edu    def __call__(self, value):
15203101Sstever@eecs.umich.edu        self.__init__(value)
152110267SGeoffrey.Blake@arm.com        return value
152210267SGeoffrey.Blake@arm.com
152310267SGeoffrey.Blake@arm.com    def __getattr__(self, attr):
152410267SGeoffrey.Blake@arm.com        if attr == 'frequency':
152510267SGeoffrey.Blake@arm.com            return self
152610267SGeoffrey.Blake@arm.com        if attr in ('latency', 'period'):
152710267SGeoffrey.Blake@arm.com            return Latency(self)
15283101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
15293101Sstever@eecs.umich.edu
15303101Sstever@eecs.umich.edu    # convert latency to ticks
15313101Sstever@eecs.umich.edu    def getValue(self):
15323101Sstever@eecs.umich.edu        if self.ticks or self.value == 0:
15333101Sstever@eecs.umich.edu            value = self.value
15343101Sstever@eecs.umich.edu        else:
15354762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
15364762Snate@binkert.org        return long(value)
15374762Snate@binkert.org
153810380SAndrew.Bardsley@arm.com    def config_value(self):
153910380SAndrew.Bardsley@arm.com        return self.getValue()
154010380SAndrew.Bardsley@arm.com
15413101Sstever@eecs.umich.edu    def ini_str(self):
15423101Sstever@eecs.umich.edu        return '%d' % self.getValue()
15433101Sstever@eecs.umich.edu
15449827Sakash.bagdia@arm.com# A generic Frequency and/or Latency value. Value is stored as a
15459827Sakash.bagdia@arm.com# latency, just like Latency and Frequency.
154610267SGeoffrey.Blake@arm.comclass Clock(TickParamValue):
154711498Sakash.bagdia@ARM.com    def __init__(self, value):
154810267SGeoffrey.Blake@arm.com        if isinstance(value, (Latency, Clock)):
15499827Sakash.bagdia@arm.com            self.ticks = value.ticks
15509827Sakash.bagdia@arm.com            self.value = value.value
15519827Sakash.bagdia@arm.com        elif isinstance(value, Frequency):
15529827Sakash.bagdia@arm.com            self.ticks = value.ticks
15539827Sakash.bagdia@arm.com            self.value = 1.0 / value.value
155410267SGeoffrey.Blake@arm.com        elif value.endswith('t'):
155510267SGeoffrey.Blake@arm.com            self.ticks = True
155610267SGeoffrey.Blake@arm.com            self.value = int(value[:-1])
155710267SGeoffrey.Blake@arm.com        else:
155810267SGeoffrey.Blake@arm.com            self.ticks = False
15599827Sakash.bagdia@arm.com            self.value = convert.anyToLatency(value)
156010267SGeoffrey.Blake@arm.com
15619827Sakash.bagdia@arm.com    def __call__(self, value):
15629827Sakash.bagdia@arm.com        self.__init__(value)
15639827Sakash.bagdia@arm.com        return value
15649827Sakash.bagdia@arm.com
15659827Sakash.bagdia@arm.com    def __str__(self):
15669827Sakash.bagdia@arm.com        return "%s" % Latency(self)
15679827Sakash.bagdia@arm.com
15689827Sakash.bagdia@arm.com    def __getattr__(self, attr):
156910458Sandreas.hansson@arm.com        if attr == 'frequency':
157010458Sandreas.hansson@arm.com            return Frequency(self)
157110458Sandreas.hansson@arm.com        if attr in ('latency', 'period'):
157210458Sandreas.hansson@arm.com            return Latency(self)
157310458Sandreas.hansson@arm.com        raise AttributeError, "Frequency object has no attribute '%s'" % attr
157410458Sandreas.hansson@arm.com
157510458Sandreas.hansson@arm.com    def getValue(self):
157610458Sandreas.hansson@arm.com        return self.period.getValue()
157710427Sandreas.hansson@arm.com
157810427Sandreas.hansson@arm.com    def config_value(self):
157910427Sandreas.hansson@arm.com        return self.period.config_value()
158010427Sandreas.hansson@arm.com
158110427Sandreas.hansson@arm.com    def ini_str(self):
158210427Sandreas.hansson@arm.com        return self.period.ini_str()
158310427Sandreas.hansson@arm.com
158410427Sandreas.hansson@arm.comclass Voltage(float,ParamValue):
158510427Sandreas.hansson@arm.com    cxx_type = 'double'
158610427Sandreas.hansson@arm.com    ex_str = "1V"
158710427Sandreas.hansson@arm.com    cmd_line_settable = False
158810427Sandreas.hansson@arm.com
158910427Sandreas.hansson@arm.com    def __new__(cls, value):
159010427Sandreas.hansson@arm.com        # convert to voltage
159110427Sandreas.hansson@arm.com        val = convert.toVoltage(value)
159210427Sandreas.hansson@arm.com        return super(cls, Voltage).__new__(cls, val)
159310427Sandreas.hansson@arm.com
159410427Sandreas.hansson@arm.com    def __call__(self, value):
159510427Sandreas.hansson@arm.com        val = convert.toVoltage(value)
159610427Sandreas.hansson@arm.com        self.__init__(val)
159710427Sandreas.hansson@arm.com        return value
159810427Sandreas.hansson@arm.com
159910427Sandreas.hansson@arm.com    def __str__(self):
160010427Sandreas.hansson@arm.com        return str(self.getValue())
160110427Sandreas.hansson@arm.com
160210458Sandreas.hansson@arm.com    def getValue(self):
160310458Sandreas.hansson@arm.com        value = float(self)
160410458Sandreas.hansson@arm.com        return value
160510458Sandreas.hansson@arm.com
160610458Sandreas.hansson@arm.com    def ini_str(self):
160710458Sandreas.hansson@arm.com        return '%f' % self.getValue()
160810458Sandreas.hansson@arm.com
160910458Sandreas.hansson@arm.com    @classmethod
16103101Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
16113101Sstever@eecs.umich.edu        code('#include <sstream>')
161210267SGeoffrey.Blake@arm.com
161310267SGeoffrey.Blake@arm.com    @classmethod
161410267SGeoffrey.Blake@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
16153101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
16164167Sbinkertn@umich.edu
16174167Sbinkertn@umich.educlass Current(float, ParamValue):
16183101Sstever@eecs.umich.edu    cxx_type = 'double'
16193101Sstever@eecs.umich.edu    ex_str = "1mA"
16203101Sstever@eecs.umich.edu    cmd_line_settable = False
16213101Sstever@eecs.umich.edu
16223101Sstever@eecs.umich.edu    def __new__(cls, value):
162310267SGeoffrey.Blake@arm.com        # convert to current
162410267SGeoffrey.Blake@arm.com        val = convert.toCurrent(value)
162510267SGeoffrey.Blake@arm.com        return super(cls, Current).__new__(cls, val)
162610267SGeoffrey.Blake@arm.com
162710267SGeoffrey.Blake@arm.com    def __call__(self, value):
16284762Snate@binkert.org        val = convert.toCurrent(value)
16294167Sbinkertn@umich.edu        self.__init__(val)
16304167Sbinkertn@umich.edu        return value
16314167Sbinkertn@umich.edu
16324762Snate@binkert.org    def __str__(self):
16334762Snate@binkert.org        return str(self.getValue())
16344762Snate@binkert.org
16354762Snate@binkert.org    def getValue(self):
16364762Snate@binkert.org        value = float(self)
16373101Sstever@eecs.umich.edu        return value
163810380SAndrew.Bardsley@arm.com
163910380SAndrew.Bardsley@arm.com    def ini_str(self):
164010380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
164110458Sandreas.hansson@arm.com
164210458Sandreas.hansson@arm.com    @classmethod
164310458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
164410458Sandreas.hansson@arm.com        code('#include <sstream>')
164510458Sandreas.hansson@arm.com
164610458Sandreas.hansson@arm.com    @classmethod
164710458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
164810458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
16493101Sstever@eecs.umich.edu
16503101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
165110267SGeoffrey.Blake@arm.com    cxx_type = 'float'
165210267SGeoffrey.Blake@arm.com    ex_str = "1Gbps"
165310267SGeoffrey.Blake@arm.com    cmd_line_settable = True
16545469Snate@binkert.org
16557743Sgblack@eecs.umich.edu    def __new__(cls, value):
16563102Sstever@eecs.umich.edu        # convert to bits per second
16573101Sstever@eecs.umich.edu        val = convert.toNetworkBandwidth(value)
16583101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
165910267SGeoffrey.Blake@arm.com
166010267SGeoffrey.Blake@arm.com    def __str__(self):
166110267SGeoffrey.Blake@arm.com        return str(self.val)
166210267SGeoffrey.Blake@arm.com
16633101Sstever@eecs.umich.edu    def __call__(self, value):
16644762Snate@binkert.org        val = convert.toNetworkBandwidth(value)
16654167Sbinkertn@umich.edu        self.__init__(val)
16665468Snate@binkert.org        return value
16675468Snate@binkert.org
16685468Snate@binkert.org    def getValue(self):
16694167Sbinkertn@umich.edu        # convert to seconds per byte
16704762Snate@binkert.org        value = 8.0 / float(self)
16714762Snate@binkert.org        # convert to ticks per byte
16724762Snate@binkert.org        value = ticks.fromSeconds(value)
16734762Snate@binkert.org        return float(value)
16744762Snate@binkert.org
16753101Sstever@eecs.umich.edu    def ini_str(self):
167610380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
167710380SAndrew.Bardsley@arm.com
167810380SAndrew.Bardsley@arm.com    def config_value(self):
167910458Sandreas.hansson@arm.com        return '%f' % self.getValue()
168010458Sandreas.hansson@arm.com
168110458Sandreas.hansson@arm.com    @classmethod
168210458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
168310458Sandreas.hansson@arm.com        code('#include <sstream>')
168410458Sandreas.hansson@arm.com
168510458Sandreas.hansson@arm.com    @classmethod
168610458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
16873101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
16883101Sstever@eecs.umich.edu
16893101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
16903101Sstever@eecs.umich.edu    cxx_type = 'float'
16913102Sstever@eecs.umich.edu    ex_str = "1GB/s"
16923102Sstever@eecs.umich.edu    cmd_line_settable = True
16933102Sstever@eecs.umich.edu
16943102Sstever@eecs.umich.edu    def __new__(cls, value):
16953102Sstever@eecs.umich.edu        # convert to bytes per second
16963102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
16973102Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
16983102Sstever@eecs.umich.edu
16993102Sstever@eecs.umich.edu    def __call__(self, value):
17003102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
17013102Sstever@eecs.umich.edu        self.__init__(val)
17023102Sstever@eecs.umich.edu        return value
17033102Sstever@eecs.umich.edu
17043102Sstever@eecs.umich.edu    def getValue(self):
17053102Sstever@eecs.umich.edu        # convert to seconds per byte
17063102Sstever@eecs.umich.edu        value = float(self)
17073102Sstever@eecs.umich.edu        if value:
17083102Sstever@eecs.umich.edu            value = 1.0 / float(self)
17093102Sstever@eecs.umich.edu        # convert to ticks per byte
17103102Sstever@eecs.umich.edu        value = ticks.fromSeconds(value)
17113102Sstever@eecs.umich.edu        return float(value)
17124762Snate@binkert.org
171312192Sgabeblack@google.com    def ini_str(self):
171412192Sgabeblack@google.com        return '%f' % self.getValue()
171512192Sgabeblack@google.com
171612195Sgabeblack@google.com    def config_value(self):
171712195Sgabeblack@google.com        return '%f' % self.getValue()
171812195Sgabeblack@google.com
17193102Sstever@eecs.umich.edu    @classmethod
17203102Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
17213102Sstever@eecs.umich.edu        code('#include <sstream>')
172210380SAndrew.Bardsley@arm.com
172310380SAndrew.Bardsley@arm.com    @classmethod
172410380SAndrew.Bardsley@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
17254762Snate@binkert.org        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
17264762Snate@binkert.org
17274762Snate@binkert.org#
17283102Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
17293102Sstever@eecs.umich.edu#
17303102Sstever@eecs.umich.edu
17313102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
17323102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
17333102Sstever@eecs.umich.edu# SimObject is required.
17343101Sstever@eecs.umich.edu# only one copy of a particular node
17353101Sstever@eecs.umich.educlass NullSimObject(object):
17363101Sstever@eecs.umich.edu    __metaclass__ = Singleton
17373101Sstever@eecs.umich.edu
17383101Sstever@eecs.umich.edu    def __call__(cls):
17393101Sstever@eecs.umich.edu        return cls
17403101Sstever@eecs.umich.edu
17413101Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
17423101Sstever@eecs.umich.edu        pass
17433101Sstever@eecs.umich.edu
17443101Sstever@eecs.umich.edu    def ini_str(self):
17453101Sstever@eecs.umich.edu        return 'Null'
17463101Sstever@eecs.umich.edu
17473101Sstever@eecs.umich.edu    def unproxy(self, base):
17483101Sstever@eecs.umich.edu        return self
17493101Sstever@eecs.umich.edu
17503101Sstever@eecs.umich.edu    def set_path(self, parent, name):
17518839Sandreas.hansson@arm.com        pass
17523105Sstever@eecs.umich.edu
17533101Sstever@eecs.umich.edu    def __str__(self):
17543101Sstever@eecs.umich.edu        return 'Null'
17558839Sandreas.hansson@arm.com
17563101Sstever@eecs.umich.edu    def config_value(self):
17573101Sstever@eecs.umich.edu        return None
17583105Sstever@eecs.umich.edu
17593101Sstever@eecs.umich.edu    def getValue(self):
17603103Sstever@eecs.umich.edu        return None
17613105Sstever@eecs.umich.edu
17623103Sstever@eecs.umich.edu# The only instance you'll ever need...
17638840Sandreas.hansson@arm.comNULL = NullSimObject()
17648840Sandreas.hansson@arm.com
17658840Sandreas.hansson@arm.comdef isNullPointer(value):
17668840Sandreas.hansson@arm.com    return isinstance(value, NullSimObject)
17678840Sandreas.hansson@arm.com
17683105Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
17693105Sstever@eecs.umich.eduMaxAddr = Addr.max
17703105Sstever@eecs.umich.eduMaxTick = Tick.max
17713105Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
17729017Sandreas.hansson@arm.com
17739017Sandreas.hansson@arm.com
17749017Sandreas.hansson@arm.com#####################################################################
17759017Sandreas.hansson@arm.com#
17763105Sstever@eecs.umich.edu# Port objects
17773105Sstever@eecs.umich.edu#
17783105Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
17793105Sstever@eecs.umich.edu#
17803105Sstever@eecs.umich.edu#####################################################################
17813105Sstever@eecs.umich.edu
17823105Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
17833105Sstever@eecs.umich.edu# particular SimObject.
17843105Sstever@eecs.umich.educlass PortRef(object):
17853109Sstever@eecs.umich.edu    def __init__(self, simobj, name, role):
17863105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
17873105Sstever@eecs.umich.edu        self.simobj = simobj
17883105Sstever@eecs.umich.edu        self.name = name
17893105Sstever@eecs.umich.edu        self.role = role
17903105Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
17913105Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
17929014Sandreas.hansson@arm.com        self.index = -1  # always -1 for non-vector ports
17939014Sandreas.hansson@arm.com
17943101Sstever@eecs.umich.edu    def __str__(self):
17953109Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
17963109Sstever@eecs.umich.edu
17973109Sstever@eecs.umich.edu    def __len__(self):
17983109Sstever@eecs.umich.edu        # Return the number of connected ports, i.e. 0 is we have no
17993109Sstever@eecs.umich.edu        # peer and 1 if we do.
18003109Sstever@eecs.umich.edu        return int(self.peer != None)
18013109Sstever@eecs.umich.edu
18023109Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
18033109Sstever@eecs.umich.edu    def ini_str(self):
18043101Sstever@eecs.umich.edu        return str(self.peer)
180510355SGeoffrey.Blake@arm.com
180610355SGeoffrey.Blake@arm.com    # for config.json
180710355SGeoffrey.Blake@arm.com    def get_config_as_dict(self):
180810355SGeoffrey.Blake@arm.com        return {'role' : self.role, 'peer' : str(self.peer)}
180910355SGeoffrey.Blake@arm.com
181010355SGeoffrey.Blake@arm.com    def __getattr__(self, attr):
181110355SGeoffrey.Blake@arm.com        if attr == 'peerObj':
181210355SGeoffrey.Blake@arm.com            # shorthand for proxies
181310355SGeoffrey.Blake@arm.com            return self.peer.simobj
181410355SGeoffrey.Blake@arm.com        raise AttributeError, "'%s' object has no attribute '%s'" % \
181510355SGeoffrey.Blake@arm.com              (self.__class__.__name__, attr)
181610355SGeoffrey.Blake@arm.com
181710355SGeoffrey.Blake@arm.com    # Full connection is symmetric (both ways).  Called via
181810355SGeoffrey.Blake@arm.com    # SimObject.__setattr__ as a result of a port assignment, e.g.,
181910355SGeoffrey.Blake@arm.com    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
182010355SGeoffrey.Blake@arm.com    # e.g., "obj1.portA[3] = obj2.portB".
182110355SGeoffrey.Blake@arm.com    def connect(self, other):
182210355SGeoffrey.Blake@arm.com        if isinstance(other, VectorPortRef):
182310355SGeoffrey.Blake@arm.com            # reference to plain VectorPort is implicit append
182410355SGeoffrey.Blake@arm.com            other = other._get_next()
182510355SGeoffrey.Blake@arm.com        if self.peer and not proxy.isproxy(self.peer):
182610355SGeoffrey.Blake@arm.com            fatal("Port %s is already connected to %s, cannot connect %s\n",
182710355SGeoffrey.Blake@arm.com                  self, self.peer, other);
182810355SGeoffrey.Blake@arm.com        self.peer = other
182910355SGeoffrey.Blake@arm.com        if proxy.isproxy(other):
183010355SGeoffrey.Blake@arm.com            other.set_param_desc(PortParamDesc())
183110355SGeoffrey.Blake@arm.com        elif isinstance(other, PortRef):
183210355SGeoffrey.Blake@arm.com            if other.peer is not self:
183310355SGeoffrey.Blake@arm.com                other.connect(self)
183410355SGeoffrey.Blake@arm.com        else:
18353105Sstever@eecs.umich.edu            raise TypeError, \
18363105Sstever@eecs.umich.edu                  "assigning non-port reference '%s' to port '%s'" \
18373105Sstever@eecs.umich.edu                  % (other, self)
18383101Sstever@eecs.umich.edu
18393105Sstever@eecs.umich.edu    # Allow a master/slave port pair to be spliced between
18403105Sstever@eecs.umich.edu    # a port and its connected peer. Useful operation for connecting
18413101Sstever@eecs.umich.edu    # instrumentation structures into a system when it is necessary
18423105Sstever@eecs.umich.edu    # to connect the instrumentation after the full system has been
18433179Sstever@eecs.umich.edu    # constructed.
18443105Sstever@eecs.umich.edu    def splice(self, new_master_peer, new_slave_peer):
18453105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
18463101Sstever@eecs.umich.edu            if isinstance(new_master_peer, PortRef) and \
18473101Sstever@eecs.umich.edu               isinstance(new_slave_peer, PortRef):
18483105Sstever@eecs.umich.edu                 old_peer = self.peer
18493105Sstever@eecs.umich.edu                 if self.role == 'SLAVE':
18503105Sstever@eecs.umich.edu                     self.peer = new_master_peer
18513105Sstever@eecs.umich.edu                     old_peer.peer = new_slave_peer
18523105Sstever@eecs.umich.edu                     new_master_peer.connect(self)
18533105Sstever@eecs.umich.edu                     new_slave_peer.connect(old_peer)
18543105Sstever@eecs.umich.edu                 elif self.role == 'MASTER':
18553105Sstever@eecs.umich.edu                     self.peer = new_slave_peer
18563105Sstever@eecs.umich.edu                     old_peer.peer = new_master_peer
18573105Sstever@eecs.umich.edu                     new_slave_peer.connect(self)
18583105Sstever@eecs.umich.edu                     new_master_peer.connect(old_peer)
18593101Sstever@eecs.umich.edu                 else:
18603101Sstever@eecs.umich.edu                     panic("Port %s has unknown role, "+\
186111802Sandreas.sandberg@arm.com                           "cannot splice in new peers\n", self)
18624762Snate@binkert.org            else:
18638839Sandreas.hansson@arm.com                raise TypeError, \
18648839Sandreas.hansson@arm.com                      "Splicing non-port references '%s','%s' to port '%s'"\
18658839Sandreas.hansson@arm.com                      % (new_peer, peers_new_peer, self)
18668839Sandreas.hansson@arm.com        else:
18673101Sstever@eecs.umich.edu            fatal("Port %s not connected, cannot splice in new peers\n", self)
18683101Sstever@eecs.umich.edu
18693101Sstever@eecs.umich.edu    def clone(self, simobj, memo):
18705578SSteve.Reinhardt@amd.com        if memo.has_key(self):
18715578SSteve.Reinhardt@amd.com            return memo[self]
18728839Sandreas.hansson@arm.com        newRef = copy.copy(self)
18738839Sandreas.hansson@arm.com        memo[self] = newRef
18748839Sandreas.hansson@arm.com        newRef.simobj = simobj
18758839Sandreas.hansson@arm.com        assert(isSimObject(newRef.simobj))
18768839Sandreas.hansson@arm.com        if self.peer and not proxy.isproxy(self.peer):
18778839Sandreas.hansson@arm.com            peerObj = self.peer.simobj(_memo=memo)
18788839Sandreas.hansson@arm.com            newRef.peer = self.peer.clone(peerObj, memo)
18797526Ssteve.reinhardt@amd.com            assert(not isinstance(newRef.peer, VectorPortRef))
18808839Sandreas.hansson@arm.com        return newRef
18817526Ssteve.reinhardt@amd.com
18827526Ssteve.reinhardt@amd.com    def unproxy(self, simobj):
18837526Ssteve.reinhardt@amd.com        assert(simobj is self.simobj)
18847526Ssteve.reinhardt@amd.com        if proxy.isproxy(self.peer):
18857526Ssteve.reinhardt@amd.com            try:
18867526Ssteve.reinhardt@amd.com                realPeer = self.peer.unproxy(self.simobj)
18877526Ssteve.reinhardt@amd.com            except:
18883101Sstever@eecs.umich.edu                print "Error in unproxying port '%s' of %s" % \
18893101Sstever@eecs.umich.edu                      (self.name, self.simobj.path())
18903101Sstever@eecs.umich.edu                raise
18913105Sstever@eecs.umich.edu            self.connect(realPeer)
18923105Sstever@eecs.umich.edu
18933105Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
18948839Sandreas.hansson@arm.com    def ccConnect(self):
18958839Sandreas.hansson@arm.com        from m5.internal.pyobject import connectPorts
18963105Sstever@eecs.umich.edu
18973105Sstever@eecs.umich.edu        if self.role == 'SLAVE':
18983105Sstever@eecs.umich.edu            # do nothing and let the master take care of it
18993105Sstever@eecs.umich.edu            return
19003105Sstever@eecs.umich.edu
19013105Sstever@eecs.umich.edu        if self.ccConnected: # already done this
19023105Sstever@eecs.umich.edu            return
19033105Sstever@eecs.umich.edu        peer = self.peer
19048839Sandreas.hansson@arm.com        if not self.peer: # nothing to connect to
19053105Sstever@eecs.umich.edu            return
19063105Sstever@eecs.umich.edu
19073105Sstever@eecs.umich.edu        # check that we connect a master to a slave
19088839Sandreas.hansson@arm.com        if self.role == peer.role:
19093105Sstever@eecs.umich.edu            raise TypeError, \
19103105Sstever@eecs.umich.edu                "cannot connect '%s' and '%s' due to identical role '%s'" \
19113109Sstever@eecs.umich.edu                % (peer, self, self.role)
19123109Sstever@eecs.umich.edu
19133109Sstever@eecs.umich.edu        try:
19148840Sandreas.hansson@arm.com            # self is always the master and peer the slave
19158840Sandreas.hansson@arm.com            connectPorts(self.simobj.getCCObject(), self.name, self.index,
19168840Sandreas.hansson@arm.com                         peer.simobj.getCCObject(), peer.name, peer.index)
19178840Sandreas.hansson@arm.com        except:
19188840Sandreas.hansson@arm.com            print "Error connecting port %s.%s to %s.%s" % \
19193105Sstever@eecs.umich.edu                  (self.simobj.path(), self.name,
19203105Sstever@eecs.umich.edu                   peer.simobj.path(), peer.name)
19213105Sstever@eecs.umich.edu            raise
19223105Sstever@eecs.umich.edu        self.ccConnected = True
19239017Sandreas.hansson@arm.com        peer.ccConnected = True
19249017Sandreas.hansson@arm.com
19259017Sandreas.hansson@arm.com# A reference to an individual element of a VectorPort... much like a
19269017Sandreas.hansson@arm.com# PortRef, but has an index.
19279017Sandreas.hansson@arm.comclass VectorPortElementRef(PortRef):
19283105Sstever@eecs.umich.edu    def __init__(self, simobj, name, role, index):
19293105Sstever@eecs.umich.edu        PortRef.__init__(self, simobj, name, role)
19303105Sstever@eecs.umich.edu        self.index = index
19313105Sstever@eecs.umich.edu
19323105Sstever@eecs.umich.edu    def __str__(self):
19338839Sandreas.hansson@arm.com        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
19343105Sstever@eecs.umich.edu
19353105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
19363105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
19373105Sstever@eecs.umich.educlass VectorPortRef(object):
19383105Sstever@eecs.umich.edu    def __init__(self, simobj, name, role):
19393105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
19403105Sstever@eecs.umich.edu        self.simobj = simobj
19413105Sstever@eecs.umich.edu        self.name = name
19423105Sstever@eecs.umich.edu        self.role = role
19433105Sstever@eecs.umich.edu        self.elements = []
19443105Sstever@eecs.umich.edu
19453105Sstever@eecs.umich.edu    def __str__(self):
19463105Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
19473109Sstever@eecs.umich.edu
19483109Sstever@eecs.umich.edu    def __len__(self):
19493109Sstever@eecs.umich.edu        # Return the number of connected peers, corresponding the the
19503109Sstever@eecs.umich.edu        # length of the elements.
19513109Sstever@eecs.umich.edu        return len(self.elements)
19523109Sstever@eecs.umich.edu
19533109Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
19543109Sstever@eecs.umich.edu    def ini_str(self):
19553109Sstever@eecs.umich.edu        return ' '.join([el.ini_str() for el in self.elements])
19563109Sstever@eecs.umich.edu
19573109Sstever@eecs.umich.edu    # for config.json
19583109Sstever@eecs.umich.edu    def get_config_as_dict(self):
19593109Sstever@eecs.umich.edu        return {'role' : self.role,
19603109Sstever@eecs.umich.edu                'peer' : [el.ini_str() for el in self.elements]}
19613109Sstever@eecs.umich.edu
19623109Sstever@eecs.umich.edu    def __getitem__(self, key):
19633109Sstever@eecs.umich.edu        if not isinstance(key, int):
19643109Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
19653109Sstever@eecs.umich.edu        if key >= len(self.elements):
19663105Sstever@eecs.umich.edu            # need to extend list
19673105Sstever@eecs.umich.edu            ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
19683105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
19693105Sstever@eecs.umich.edu            self.elements.extend(ext)
19703105Sstever@eecs.umich.edu        return self.elements[key]
19713105Sstever@eecs.umich.edu
19723105Sstever@eecs.umich.edu    def _get_next(self):
19733101Sstever@eecs.umich.edu        return self[len(self.elements)]
19743101Sstever@eecs.umich.edu
19753101Sstever@eecs.umich.edu    def __setitem__(self, key, value):
19763101Sstever@eecs.umich.edu        if not isinstance(key, int):
19773101Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
19783101Sstever@eecs.umich.edu        self[key].connect(value)
19793105Sstever@eecs.umich.edu
19808839Sandreas.hansson@arm.com    def connect(self, other):
19813101Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
19823101Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
19833101Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
19843105Sstever@eecs.umich.edu            # or if it should replace the current vector.
19853105Sstever@eecs.umich.edu            for ref in other:
19863101Sstever@eecs.umich.edu                self._get_next().connect(ref)
19878840Sandreas.hansson@arm.com        else:
19888840Sandreas.hansson@arm.com            # scalar assignment to plain VectorPort is implicit append
19898840Sandreas.hansson@arm.com            self._get_next().connect(other)
19908840Sandreas.hansson@arm.com
19918840Sandreas.hansson@arm.com    def clone(self, simobj, memo):
199211988Sandreas.sandberg@arm.com        if memo.has_key(self):
199311988Sandreas.sandberg@arm.com            return memo[self]
199411988Sandreas.sandberg@arm.com        newRef = copy.copy(self)
19958840Sandreas.hansson@arm.com        memo[self] = newRef
19968840Sandreas.hansson@arm.com        newRef.simobj = simobj
19978840Sandreas.hansson@arm.com        assert(isSimObject(newRef.simobj))
19988840Sandreas.hansson@arm.com        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
19998840Sandreas.hansson@arm.com        return newRef
20008840Sandreas.hansson@arm.com
20018839Sandreas.hansson@arm.com    def unproxy(self, simobj):
20028839Sandreas.hansson@arm.com        [el.unproxy(simobj) for el in self.elements]
20038839Sandreas.hansson@arm.com
20048839Sandreas.hansson@arm.com    def ccConnect(self):
20058839Sandreas.hansson@arm.com        [el.ccConnect() for el in self.elements]
20068839Sandreas.hansson@arm.com
20078839Sandreas.hansson@arm.com# Port description object.  Like a ParamDesc object, this represents a
20088839Sandreas.hansson@arm.com# logical port in the SimObject class, not a particular port on a
20098839Sandreas.hansson@arm.com# SimObject instance.  The latter are represented by PortRef objects.
20108839Sandreas.hansson@arm.comclass Port(object):
20118839Sandreas.hansson@arm.com    # Generate a PortRef for this port on the given SimObject with the
20128839Sandreas.hansson@arm.com    # given name
20138839Sandreas.hansson@arm.com    def makeRef(self, simobj):
20148839Sandreas.hansson@arm.com        return PortRef(simobj, self.name, self.role)
20158839Sandreas.hansson@arm.com
20168839Sandreas.hansson@arm.com    # Connect an instance of this port (on the given SimObject with
20178839Sandreas.hansson@arm.com    # the given name) with the port described by the supplied PortRef
20188839Sandreas.hansson@arm.com    def connect(self, simobj, ref):
20193101Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
202010405Sandreas.hansson@arm.com
20213101Sstever@eecs.umich.edu    # No need for any pre-declarations at the moment as we merely rely
20223105Sstever@eecs.umich.edu    # on an unsigned int.
20233101Sstever@eecs.umich.edu    def cxx_predecls(self, code):
20243101Sstever@eecs.umich.edu        pass
20253105Sstever@eecs.umich.edu
20268839Sandreas.hansson@arm.com    # Declare an unsigned int with the same name as the port, that
20278839Sandreas.hansson@arm.com    # will eventually hold the number of connected ports (and thus the
20288839Sandreas.hansson@arm.com    # number of elements for a VectorPort).
20298839Sandreas.hansson@arm.com    def cxx_decl(self, code):
20308839Sandreas.hansson@arm.com        code('unsigned int port_${{self.name}}_connection_count;')
20318839Sandreas.hansson@arm.com
20328839Sandreas.hansson@arm.comclass MasterPort(Port):
20338839Sandreas.hansson@arm.com    # MasterPort("description")
20348839Sandreas.hansson@arm.com    def __init__(self, *args):
20358839Sandreas.hansson@arm.com        if len(args) == 1:
20368839Sandreas.hansson@arm.com            self.desc = args[0]
20378839Sandreas.hansson@arm.com            self.role = 'MASTER'
20388839Sandreas.hansson@arm.com        else:
20398839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20408839Sandreas.hansson@arm.com
20418839Sandreas.hansson@arm.comclass SlavePort(Port):
20428839Sandreas.hansson@arm.com    # SlavePort("description")
20438839Sandreas.hansson@arm.com    def __init__(self, *args):
20448839Sandreas.hansson@arm.com        if len(args) == 1:
20458839Sandreas.hansson@arm.com            self.desc = args[0]
20468839Sandreas.hansson@arm.com            self.role = 'SLAVE'
20473105Sstever@eecs.umich.edu        else:
20483109Sstever@eecs.umich.edu            raise TypeError, 'wrong number of arguments'
20493109Sstever@eecs.umich.edu
20503109Sstever@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
20513109Sstever@eecs.umich.edu# of connections (e.g., as on a XBar).
20523109Sstever@eecs.umich.educlass VectorPort(Port):
20533109Sstever@eecs.umich.edu    def __init__(self, *args):
20543109Sstever@eecs.umich.edu        self.isVec = True
20553109Sstever@eecs.umich.edu
20563105Sstever@eecs.umich.edu    def makeRef(self, simobj):
20576654Snate@binkert.org        return VectorPortRef(simobj, self.name, self.role)
20586654Snate@binkert.org
20596654Snate@binkert.orgclass VectorMasterPort(VectorPort):
20606654Snate@binkert.org    # VectorMasterPort("description")
20616654Snate@binkert.org    def __init__(self, *args):
20626654Snate@binkert.org        if len(args) == 1:
20636654Snate@binkert.org            self.desc = args[0]
20646654Snate@binkert.org            self.role = 'MASTER'
20656654Snate@binkert.org            VectorPort.__init__(self, *args)
20663101Sstever@eecs.umich.edu        else:
20673101Sstever@eecs.umich.edu            raise TypeError, 'wrong number of arguments'
20683101Sstever@eecs.umich.edu
20693101Sstever@eecs.umich.educlass VectorSlavePort(VectorPort):
20703101Sstever@eecs.umich.edu    # VectorSlavePort("description")
20713101Sstever@eecs.umich.edu    def __init__(self, *args):
20727777Sgblack@eecs.umich.edu        if len(args) == 1:
20733101Sstever@eecs.umich.edu            self.desc = args[0]
20749827Sakash.bagdia@arm.com            self.role = 'SLAVE'
20753101Sstever@eecs.umich.edu            VectorPort.__init__(self, *args)
20769232Sandreas.hansson@arm.com        else:
20773101Sstever@eecs.umich.edu            raise TypeError, 'wrong number of arguments'
20783885Sbinkertn@umich.edu
20793102Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
20808839Sandreas.hansson@arm.com# proxy objects (via set_param_desc()) so that proxy error messages
20818839Sandreas.hansson@arm.com# make sense.
20826654Snate@binkert.orgclass PortParamDesc(object):
20836654Snate@binkert.org    __metaclass__ = Singleton
2084
2085    ptype_str = 'Port'
2086    ptype = Port
2087
2088baseEnums = allEnums.copy()
2089baseParams = allParams.copy()
2090
2091def clear():
2092    global allEnums, allParams
2093
2094    allEnums = baseEnums.copy()
2095    allParams = baseParams.copy()
2096
2097__all__ = ['Param', 'VectorParam',
2098           'Enum', 'Bool', 'String', 'Float',
2099           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
2100           'Int32', 'UInt32', 'Int64', 'UInt64',
2101           'Counter', 'Addr', 'Tick', 'Percent',
2102           'TcpPort', 'UdpPort', 'EthernetAddr',
2103           'IpAddress', 'IpNetmask', 'IpWithPort',
2104           'MemorySize', 'MemorySize32',
2105           'Latency', 'Frequency', 'Clock', 'Voltage',
2106           'NetworkBandwidth', 'MemoryBandwidth',
2107           'AddrRange',
2108           'MaxAddr', 'MaxTick', 'AllMemory',
2109           'Time',
2110           'NextEthernetAddr', 'NULL',
2111           'MasterPort', 'SlavePort',
2112           'VectorMasterPort', 'VectorSlavePort']
2113
2114import SimObject
2115