params.py revision 13783:e9a2fef479e7
111988Sandreas.sandberg@arm.com# Copyright (c) 2012-2014, 2017, 2018 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.edufrom __future__ import print_function
633885Sbinkertn@umich.eduimport six
644762Snate@binkert.orgif six.PY3:
653885Sbinkertn@umich.edu    long = int
663885Sbinkertn@umich.edu
677528Ssteve.reinhardt@amd.comimport copy
683885Sbinkertn@umich.eduimport datetime
694380Sbinkertn@umich.eduimport re
704167Sbinkertn@umich.eduimport sys
713102Sstever@eecs.umich.eduimport time
723101Sstever@eecs.umich.eduimport math
734762Snate@binkert.org
744762Snate@binkert.orgfrom . import proxy
754762Snate@binkert.orgfrom . import ticks
764762Snate@binkert.orgfrom .util import *
774762Snate@binkert.org
784762Snate@binkert.orgdef isSimObject(*args, **kwargs):
794762Snate@binkert.org    from . import SimObject
804762Snate@binkert.org    return SimObject.isSimObject(*args, **kwargs)
814762Snate@binkert.org
825033Smilesck@eecs.umich.edudef isSimObjectSequence(*args, **kwargs):
835033Smilesck@eecs.umich.edu    from . import SimObject
845033Smilesck@eecs.umich.edu    return SimObject.isSimObjectSequence(*args, **kwargs)
855033Smilesck@eecs.umich.edu
865033Smilesck@eecs.umich.edudef isSimObjectClass(*args, **kwargs):
875033Smilesck@eecs.umich.edu    from . import SimObject
885033Smilesck@eecs.umich.edu    return SimObject.isSimObjectClass(*args, **kwargs)
895033Smilesck@eecs.umich.edu
905033Smilesck@eecs.umich.eduallParams = {}
915033Smilesck@eecs.umich.edu
923101Sstever@eecs.umich.educlass MetaParamValue(type):
933101Sstever@eecs.umich.edu    def __new__(mcls, name, bases, dct):
943101Sstever@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
955033Smilesck@eecs.umich.edu        assert name not in allParams
9610267SGeoffrey.Blake@arm.com        allParams[name] = cls
978596Ssteve.reinhardt@amd.com        return cls
988596Ssteve.reinhardt@amd.com
998596Ssteve.reinhardt@amd.com
1008596Ssteve.reinhardt@amd.com# Dummy base class to identify types that are legitimate for SimObject
1017673Snate@binkert.org# parameters.
1027673Snate@binkert.orgclass ParamValue(object):
1037673Snate@binkert.org    __metaclass__ = MetaParamValue
1047673Snate@binkert.org    cmd_line_settable = False
10511988Sandreas.sandberg@arm.com
10611988Sandreas.sandberg@arm.com    # Generate the code needed as a prerequisite for declaring a C++
10711988Sandreas.sandberg@arm.com    # object of this type.  Typically generates one or more #include
10811988Sandreas.sandberg@arm.com    # statements.  Used when declaring parameters of this type.
1093101Sstever@eecs.umich.edu    @classmethod
1103101Sstever@eecs.umich.edu    def cxx_predecls(cls, code):
1113101Sstever@eecs.umich.edu        pass
1123101Sstever@eecs.umich.edu
1133101Sstever@eecs.umich.edu    @classmethod
11410380SAndrew.Bardsley@arm.com    def pybind_predecls(cls, code):
11510380SAndrew.Bardsley@arm.com        cls.cxx_predecls(code)
11610380SAndrew.Bardsley@arm.com
11710380SAndrew.Bardsley@arm.com    # default for printing to .ini file is regular string conversion.
11810380SAndrew.Bardsley@arm.com    # will be overridden in some cases
11910380SAndrew.Bardsley@arm.com    def ini_str(self):
12010458Sandreas.hansson@arm.com        return str(self)
12110458Sandreas.hansson@arm.com
12210458Sandreas.hansson@arm.com    # default for printing to .json file is regular string conversion.
12310458Sandreas.hansson@arm.com    # will be overridden in some cases, mostly to use native Python
12410458Sandreas.hansson@arm.com    # types where there are similar JSON types
12510458Sandreas.hansson@arm.com    def config_value(self):
12610458Sandreas.hansson@arm.com        return str(self)
12710458Sandreas.hansson@arm.com
12810458Sandreas.hansson@arm.com    # Prerequisites for .ini parsing with cxx_ini_parse
12910458Sandreas.hansson@arm.com    @classmethod
13010458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
13110458Sandreas.hansson@arm.com        pass
1323101Sstever@eecs.umich.edu
1333101Sstever@eecs.umich.edu    # parse a .ini file entry for this param from string expression
1343101Sstever@eecs.umich.edu    # src into lvalue dest (of the param's C++ type)
1353101Sstever@eecs.umich.edu    @classmethod
1363101Sstever@eecs.umich.edu    def cxx_ini_parse(cls, code, src, dest, ret):
13710267SGeoffrey.Blake@arm.com        code('// Unhandled param type: %s' % cls.__name__)
13810267SGeoffrey.Blake@arm.com        code('%s false;' % ret)
13910267SGeoffrey.Blake@arm.com
14010267SGeoffrey.Blake@arm.com    # allows us to blithely call unproxy() on things without checking
1413101Sstever@eecs.umich.edu    # if they're really proxies or not
1423101Sstever@eecs.umich.edu    def unproxy(self, base):
1433101Sstever@eecs.umich.edu        return self
1443101Sstever@eecs.umich.edu
1453101Sstever@eecs.umich.edu    # Produce a human readable version of the stored value
1463101Sstever@eecs.umich.edu    def pretty_print(self, value):
1473101Sstever@eecs.umich.edu        return str(value)
1483101Sstever@eecs.umich.edu
1493101Sstever@eecs.umich.edu# Regular parameter description.
1503101Sstever@eecs.umich.educlass ParamDesc(object):
1513101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1523101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1533101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1543101Sstever@eecs.umich.edu        if ptype != None:
1553101Sstever@eecs.umich.edu            self.ptype = ptype
1563101Sstever@eecs.umich.edu
1573101Sstever@eecs.umich.edu        if args:
1583101Sstever@eecs.umich.edu            if len(args) == 1:
1593101Sstever@eecs.umich.edu                self.desc = args[0]
1603101Sstever@eecs.umich.edu            elif len(args) == 2:
1613101Sstever@eecs.umich.edu                self.default = args[0]
1623101Sstever@eecs.umich.edu                self.desc = args[1]
1633101Sstever@eecs.umich.edu            else:
1643101Sstever@eecs.umich.edu                raise TypeError('too many arguments')
1653101Sstever@eecs.umich.edu
1663101Sstever@eecs.umich.edu        if 'desc' in kwargs:
1673101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1683101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1693101Sstever@eecs.umich.edu            del kwargs['desc']
1703101Sstever@eecs.umich.edu
1713101Sstever@eecs.umich.edu        if 'default' in kwargs:
1723101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1733101Sstever@eecs.umich.edu            self.default = kwargs['default']
1743101Sstever@eecs.umich.edu            del kwargs['default']
1753101Sstever@eecs.umich.edu
1765033Smilesck@eecs.umich.edu        if kwargs:
1776656Snate@binkert.org            raise TypeError('extra unknown kwargs %s' % kwargs)
1785033Smilesck@eecs.umich.edu
1795033Smilesck@eecs.umich.edu        if not hasattr(self, 'desc'):
1805033Smilesck@eecs.umich.edu            raise TypeError('desc attribute missing')
1813101Sstever@eecs.umich.edu
1823101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1833101Sstever@eecs.umich.edu        if attr == 'ptype':
18410267SGeoffrey.Blake@arm.com            from . import SimObject
18510267SGeoffrey.Blake@arm.com            ptype = SimObject.allClasses[self.ptype_str]
18610267SGeoffrey.Blake@arm.com            assert isSimObjectClass(ptype)
18710267SGeoffrey.Blake@arm.com            self.ptype = ptype
18810267SGeoffrey.Blake@arm.com            return ptype
18910267SGeoffrey.Blake@arm.com
19010267SGeoffrey.Blake@arm.com        raise AttributeError("'%s' object has no attribute '%s'" % \
19110267SGeoffrey.Blake@arm.com              (type(self).__name__, attr))
19210267SGeoffrey.Blake@arm.com
19310267SGeoffrey.Blake@arm.com    def example_str(self):
19410267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "ex_str"):
19510267SGeoffrey.Blake@arm.com            return self.ptype.ex_str
19610267SGeoffrey.Blake@arm.com        else:
1973101Sstever@eecs.umich.edu            return self.ptype_str
1983101Sstever@eecs.umich.edu
1993101Sstever@eecs.umich.edu    # Is the param available to be exposed on the command line
2003101Sstever@eecs.umich.edu    def isCmdLineSettable(self):
2013101Sstever@eecs.umich.edu        if hasattr(self.ptype, "cmd_line_settable"):
2023101Sstever@eecs.umich.edu            return self.ptype.cmd_line_settable
2033101Sstever@eecs.umich.edu        else:
2043101Sstever@eecs.umich.edu            return False
2053101Sstever@eecs.umich.edu
2063101Sstever@eecs.umich.edu    def convert(self, value):
2073102Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
2083101Sstever@eecs.umich.edu            value.set_param_desc(self)
2093101Sstever@eecs.umich.edu            return value
2103101Sstever@eecs.umich.edu        if 'ptype' not in self.__dict__ and isNullPointer(value):
21110267SGeoffrey.Blake@arm.com            # deferred evaluation of SimObject; continue to defer if
21210267SGeoffrey.Blake@arm.com            # we're just assigning a null pointer
21310267SGeoffrey.Blake@arm.com            return value
21410267SGeoffrey.Blake@arm.com        if isinstance(value, self.ptype):
21510267SGeoffrey.Blake@arm.com            return value
21610267SGeoffrey.Blake@arm.com        if isNullPointer(value) and isSimObjectClass(self.ptype):
21710267SGeoffrey.Blake@arm.com            return value
2187673Snate@binkert.org        return self.ptype(value)
2198607Sgblack@eecs.umich.edu
2207673Snate@binkert.org    def pretty_print(self, value):
2213101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
22211988Sandreas.sandberg@arm.com           return str(value)
22311988Sandreas.sandberg@arm.com        if isNullPointer(value):
22411988Sandreas.sandberg@arm.com           return NULL
2257673Snate@binkert.org        return self.ptype(value).pretty_print(value)
2267673Snate@binkert.org
2273101Sstever@eecs.umich.edu    def cxx_predecls(self, code):
2283101Sstever@eecs.umich.edu        code('#include <cstddef>')
2293101Sstever@eecs.umich.edu        self.ptype.cxx_predecls(code)
2303101Sstever@eecs.umich.edu
2313101Sstever@eecs.umich.edu    def pybind_predecls(self, code):
2323101Sstever@eecs.umich.edu        self.ptype.pybind_predecls(code)
2335033Smilesck@eecs.umich.edu
2345475Snate@binkert.org    def cxx_decl(self, code):
2355475Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
2365475Snate@binkert.org
2375475Snate@binkert.org# Vector-valued parameter description.  Just like ParamDesc, except
23810380SAndrew.Bardsley@arm.com# that the value is a vector (list) of the specified type instead of a
23910380SAndrew.Bardsley@arm.com# single value.
24010380SAndrew.Bardsley@arm.com
2413101Sstever@eecs.umich.educlass VectorParamValue(list):
2423101Sstever@eecs.umich.edu    __metaclass__ = MetaParamValue
2433101Sstever@eecs.umich.edu    def __setattr__(self, attr, value):
2444762Snate@binkert.org        raise AttributeError("Not allowed to set %s on '%s'" % \
2454762Snate@binkert.org                             (attr, type(self).__name__))
2464762Snate@binkert.org
2473101Sstever@eecs.umich.edu    def config_value(self):
24812050Snikos.nikoleris@arm.com        return [v.config_value() for v in self]
24912050Snikos.nikoleris@arm.com
25012050Snikos.nikoleris@arm.com    def ini_str(self):
2518459SAli.Saidi@ARM.com        return ' '.join([v.ini_str() for v in self])
2528459SAli.Saidi@ARM.com
25312050Snikos.nikoleris@arm.com    def getValue(self):
2543101Sstever@eecs.umich.edu        return [ v.getValue() for v in self ]
2557528Ssteve.reinhardt@amd.com
2567528Ssteve.reinhardt@amd.com    def unproxy(self, base):
2577528Ssteve.reinhardt@amd.com        if len(self) == 1 and isinstance(self[0], proxy.BaseProxy):
2587528Ssteve.reinhardt@amd.com            # The value is a proxy (e.g. Parent.any, Parent.all or
2597528Ssteve.reinhardt@amd.com            # Parent.x) therefore try resolve it
2607528Ssteve.reinhardt@amd.com            return self[0].unproxy(base)
2613101Sstever@eecs.umich.edu        else:
2627528Ssteve.reinhardt@amd.com            return [v.unproxy(base) for v in self]
2637528Ssteve.reinhardt@amd.com
2647528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2657528Ssteve.reinhardt@amd.com    # support clone operation
2667528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2677528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2687528Ssteve.reinhardt@amd.com
2697528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
2707528Ssteve.reinhardt@amd.com        for v in self:
2717528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2728321Ssteve.reinhardt@amd.com
2738321Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2747528Ssteve.reinhardt@amd.com        if len(self) == 1:
2757528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2767528Ssteve.reinhardt@amd.com        else:
2777528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2787528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2797528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2807528Ssteve.reinhardt@amd.com
2817528Ssteve.reinhardt@amd.com    def has_parent(self):
2827528Ssteve.reinhardt@amd.com        return any([e.has_parent() for e in self if not isNullPointer(e)])
2837528Ssteve.reinhardt@amd.com
2847528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2857528Ssteve.reinhardt@amd.com    def get_name(self):
2867528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2873101Sstever@eecs.umich.edu
2888664SAli.Saidi@ARM.com    # By iterating through the constituent members of the vector here
2898664SAli.Saidi@ARM.com    # we can nicely handle iterating over all a SimObject's children
2908664SAli.Saidi@ARM.com    # without having to provide lots of special functions on
2918664SAli.Saidi@ARM.com    # SimObjectVector directly.
2928664SAli.Saidi@ARM.com    def descendants(self):
2938664SAli.Saidi@ARM.com        for v in self:
2949953Sgeoffrey.blake@arm.com            for obj in v.descendants():
2959953Sgeoffrey.blake@arm.com                yield obj
2969953Sgeoffrey.blake@arm.com
2979953Sgeoffrey.blake@arm.com    def get_config_as_dict(self):
2989953Sgeoffrey.blake@arm.com        a = []
2999953Sgeoffrey.blake@arm.com        for v in self:
3009953Sgeoffrey.blake@arm.com            a.append(v.get_config_as_dict())
3019953Sgeoffrey.blake@arm.com        return a
3029953Sgeoffrey.blake@arm.com
3039953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
3049953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
3059953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
3069953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
30710267SGeoffrey.Blake@arm.com    # configuration scripts.
30810267SGeoffrey.Blake@arm.com    def __setitem__(self, key, value):
30910267SGeoffrey.Blake@arm.com        val = self[key]
31010267SGeoffrey.Blake@arm.com        if value.has_parent():
31110267SGeoffrey.Blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
31210267SGeoffrey.Blake@arm.com                 " that is being overwritten by a SimObjectVector")
31310267SGeoffrey.Blake@arm.com        value.set_parent(val.get_parent(), val._name)
31410267SGeoffrey.Blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
31510267SGeoffrey.Blake@arm.com
31610267SGeoffrey.Blake@arm.com    # Enumerate the params of each member of the SimObject vector. Creates
31710267SGeoffrey.Blake@arm.com    # strings that will allow indexing into the vector by the python code and
31810267SGeoffrey.Blake@arm.com    # allow it to be specified on the command line.
31910267SGeoffrey.Blake@arm.com    def enumerateParams(self, flags_dict = {},
32010267SGeoffrey.Blake@arm.com                        cmd_line_str = "",
32110267SGeoffrey.Blake@arm.com                        access_str = ""):
32210267SGeoffrey.Blake@arm.com        if hasattr(self, "_paramEnumed"):
32310267SGeoffrey.Blake@arm.com            print("Cycle detected enumerating params at %s?!" % (cmd_line_str))
32410267SGeoffrey.Blake@arm.com        else:
32510267SGeoffrey.Blake@arm.com            x = 0
32610267SGeoffrey.Blake@arm.com            for vals in self:
3273101Sstever@eecs.umich.edu                # Each entry in the SimObjectVector should be an
3283101Sstever@eecs.umich.edu                # instance of a SimObject
3293101Sstever@eecs.umich.edu                flags_dict = vals.enumerateParams(flags_dict,
3303101Sstever@eecs.umich.edu                                                  cmd_line_str + "%d." % x,
3313101Sstever@eecs.umich.edu                                                  access_str + "[%d]." % x)
3323101Sstever@eecs.umich.edu                x = x + 1
3333101Sstever@eecs.umich.edu
33410364SGeoffrey.Blake@arm.com        return flags_dict
33510364SGeoffrey.Blake@arm.com
33610364SGeoffrey.Blake@arm.comclass VectorParamDesc(ParamDesc):
33710364SGeoffrey.Blake@arm.com    # Convert assigned value to appropriate type.  If the RHS is not a
3383101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
3394762Snate@binkert.org    def convert(self, value):
3404762Snate@binkert.org        if isinstance(value, (list, tuple)):
3414762Snate@binkert.org            # list: coerce each element into new list
3424762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
3437528Ssteve.reinhardt@amd.com        elif isinstance(value, str):
3444762Snate@binkert.org            # If input is a csv string
3454762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, v) \
3464762Snate@binkert.org                         for v in value.strip('[').strip(']').split(',') ]
34710267SGeoffrey.Blake@arm.com        else:
34810267SGeoffrey.Blake@arm.com            # singleton: coerce to a single-element list
34910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
35010267SGeoffrey.Blake@arm.com
35110267SGeoffrey.Blake@arm.com        if isSimObjectSequence(tmp_list):
35210267SGeoffrey.Blake@arm.com            return SimObjectVector(tmp_list)
35310267SGeoffrey.Blake@arm.com        else:
35410267SGeoffrey.Blake@arm.com            return VectorParamValue(tmp_list)
35510267SGeoffrey.Blake@arm.com
35610267SGeoffrey.Blake@arm.com    # Produce a human readable example string that describes
35710267SGeoffrey.Blake@arm.com    # how to set this vector parameter in the absence of a default
35810267SGeoffrey.Blake@arm.com    # value.
35910267SGeoffrey.Blake@arm.com    def example_str(self):
36010267SGeoffrey.Blake@arm.com        s = super(VectorParamDesc, self).example_str()
36110267SGeoffrey.Blake@arm.com        help_str = "[" + s + "," + s + ", ...]"
36210267SGeoffrey.Blake@arm.com        return help_str
36310267SGeoffrey.Blake@arm.com
36410267SGeoffrey.Blake@arm.com    # Produce a human readable representation of the value of this vector param.
36510267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
36610267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
36710267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
36810267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
36910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
37010267SGeoffrey.Blake@arm.com        else:
37110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, value) ]
37210267SGeoffrey.Blake@arm.com
37310364SGeoffrey.Blake@arm.com        return tmp_list
37410364SGeoffrey.Blake@arm.com
37510267SGeoffrey.Blake@arm.com    # This is a helper function for the new config system
37610267SGeoffrey.Blake@arm.com    def __call__(self, value):
37710267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
37810267SGeoffrey.Blake@arm.com            # list: coerce each element into new list
37910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
38010267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
3817673Snate@binkert.org            # If input is a csv string
3827673Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, v) \
3837673Snate@binkert.org                         for v in value.strip('[').strip(']').split(',') ]
3843101Sstever@eecs.umich.edu        else:
38511988Sandreas.sandberg@arm.com            # singleton: coerce to a single-element list
38611988Sandreas.sandberg@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
38711988Sandreas.sandberg@arm.com
38811988Sandreas.sandberg@arm.com        return VectorParamValue(tmp_list)
3897673Snate@binkert.org
3907673Snate@binkert.org    def cxx_predecls(self, code):
3913101Sstever@eecs.umich.edu        code('#include <vector>')
3923101Sstever@eecs.umich.edu        self.ptype.cxx_predecls(code)
3933101Sstever@eecs.umich.edu
3943101Sstever@eecs.umich.edu    def pybind_predecls(self, code):
3953101Sstever@eecs.umich.edu        code('#include <vector>')
3963101Sstever@eecs.umich.edu        self.ptype.pybind_predecls(code)
3973101Sstever@eecs.umich.edu
3983101Sstever@eecs.umich.edu    def cxx_decl(self, code):
3993101Sstever@eecs.umich.edu        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
4003101Sstever@eecs.umich.edu
4013101Sstever@eecs.umich.educlass ParamFactory(object):
4023101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
4033101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
4043101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
4053101Sstever@eecs.umich.edu
4065033Smilesck@eecs.umich.edu    def __getattr__(self, attr):
4075033Smilesck@eecs.umich.edu        if self.ptype_str:
4083101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
4093101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
4103101Sstever@eecs.umich.edu
4113101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
4123101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
4133101Sstever@eecs.umich.edu        ptype = None
4143101Sstever@eecs.umich.edu        try:
4153101Sstever@eecs.umich.edu            ptype = allParams[self.ptype_str]
4163101Sstever@eecs.umich.edu        except KeyError:
4173101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
4183101Sstever@eecs.umich.edu            # try to resolve it later
4193101Sstever@eecs.umich.edu            pass
4203101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
4213101Sstever@eecs.umich.edu
4223101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
4233101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
4243101Sstever@eecs.umich.edu
4253101Sstever@eecs.umich.edu#####################################################################
4263101Sstever@eecs.umich.edu#
4273101Sstever@eecs.umich.edu# Parameter Types
4283101Sstever@eecs.umich.edu#
4293101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
4303101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
4313101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
4323101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
43310267SGeoffrey.Blake@arm.com# __init__() constructor) and how these values are printed out (via
4347673Snate@binkert.org# the __str__() conversion method).
4357673Snate@binkert.org#
4367673Snate@binkert.org#####################################################################
4377673Snate@binkert.org
4387673Snate@binkert.org# String-valued parameter.  Just mixin the ParamValue class with the
43910267SGeoffrey.Blake@arm.com# built-in str class.
44010267SGeoffrey.Blake@arm.comclass String(ParamValue,str):
44110267SGeoffrey.Blake@arm.com    cxx_type = 'std::string'
44210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
44310458Sandreas.hansson@arm.com
44410458Sandreas.hansson@arm.com    @classmethod
44510458Sandreas.hansson@arm.com    def cxx_predecls(self, code):
44610458Sandreas.hansson@arm.com        code('#include <string>')
44710458Sandreas.hansson@arm.com
4484762Snate@binkert.org    def __call__(self, value):
4494762Snate@binkert.org        self = value
4503101Sstever@eecs.umich.edu        return value
4513101Sstever@eecs.umich.edu
4523101Sstever@eecs.umich.edu    @classmethod
4533101Sstever@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
4543101Sstever@eecs.umich.edu        code('%s = %s;' % (dest, src))
4553101Sstever@eecs.umich.edu        code('%s true;' % ret)
4563101Sstever@eecs.umich.edu
4573101Sstever@eecs.umich.edu    def getValue(self):
4583101Sstever@eecs.umich.edu        return self
4593101Sstever@eecs.umich.edu
4603101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
4613714Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
4623714Sstever@eecs.umich.edu# a new Latency object.
4633714Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
4643714Sstever@eecs.umich.edu    @staticmethod
4653714Sstever@eecs.umich.edu    def unwrap(v):
4663714Sstever@eecs.umich.edu        return v.value if isinstance(v, NumericParamValue) else v
4673101Sstever@eecs.umich.edu
4683101Sstever@eecs.umich.edu    def __str__(self):
4693101Sstever@eecs.umich.edu        return str(self.value)
4703101Sstever@eecs.umich.edu
4713101Sstever@eecs.umich.edu    def __float__(self):
4723101Sstever@eecs.umich.edu        return float(self.value)
4733101Sstever@eecs.umich.edu
4743101Sstever@eecs.umich.edu    def __long__(self):
4753101Sstever@eecs.umich.edu        return long(self.value)
4763101Sstever@eecs.umich.edu
4773101Sstever@eecs.umich.edu    def __int__(self):
4783101Sstever@eecs.umich.edu        return int(self.value)
4793101Sstever@eecs.umich.edu
4803101Sstever@eecs.umich.edu    # hook for bounds checking
4813101Sstever@eecs.umich.edu    def _check(self):
4823101Sstever@eecs.umich.edu        return
4833101Sstever@eecs.umich.edu
4843101Sstever@eecs.umich.edu    def __mul__(self, other):
4853101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4863101Sstever@eecs.umich.edu        newobj.value *= NumericParamValue.unwrap(other)
4873101Sstever@eecs.umich.edu        newobj._check()
4883101Sstever@eecs.umich.edu        return newobj
4893101Sstever@eecs.umich.edu
4903101Sstever@eecs.umich.edu    __rmul__ = __mul__
49110380SAndrew.Bardsley@arm.com
49210380SAndrew.Bardsley@arm.com    def __truediv__(self, other):
49310380SAndrew.Bardsley@arm.com        newobj = self.__class__(self)
49410458Sandreas.hansson@arm.com        newobj.value /= NumericParamValue.unwrap(other)
49510458Sandreas.hansson@arm.com        newobj._check()
49610458Sandreas.hansson@arm.com        return newobj
49710458Sandreas.hansson@arm.com
49810458Sandreas.hansson@arm.com    def __floordiv__(self, other):
49910458Sandreas.hansson@arm.com        newobj = self.__class__(self)
50010458Sandreas.hansson@arm.com        newobj.value //= NumericParamValue.unwrap(other)
50110458Sandreas.hansson@arm.com        newobj._check()
50210458Sandreas.hansson@arm.com        return newobj
50310458Sandreas.hansson@arm.com
50410458Sandreas.hansson@arm.com
50510458Sandreas.hansson@arm.com    def __add__(self, other):
50610458Sandreas.hansson@arm.com        newobj = self.__class__(self)
5073101Sstever@eecs.umich.edu        newobj.value += NumericParamValue.unwrap(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 -= NumericParamValue.unwrap(other)
5143101Sstever@eecs.umich.edu        newobj._check()
5153101Sstever@eecs.umich.edu        return newobj
5163101Sstever@eecs.umich.edu
5173101Sstever@eecs.umich.edu    def __iadd__(self, other):
5183101Sstever@eecs.umich.edu        self.value += NumericParamValue.unwrap(other)
5193101Sstever@eecs.umich.edu        self._check()
5203101Sstever@eecs.umich.edu        return self
5215822Ssaidi@eecs.umich.edu
5225822Ssaidi@eecs.umich.edu    def __isub__(self, other):
5233101Sstever@eecs.umich.edu        self.value -= NumericParamValue.unwrap(other)
5243101Sstever@eecs.umich.edu        self._check()
5253101Sstever@eecs.umich.edu        return self
5263101Sstever@eecs.umich.edu
5273101Sstever@eecs.umich.edu    def __imul__(self, other):
5283101Sstever@eecs.umich.edu        self.value *= NumericParamValue.unwrap(other)
5293101Sstever@eecs.umich.edu        self._check()
5303101Sstever@eecs.umich.edu        return self
5313101Sstever@eecs.umich.edu
5323101Sstever@eecs.umich.edu    def __itruediv__(self, other):
5333101Sstever@eecs.umich.edu        self.value /= NumericParamValue.unwrap(other)
5343101Sstever@eecs.umich.edu        self._check()
5353101Sstever@eecs.umich.edu        return self
53610267SGeoffrey.Blake@arm.com
5373101Sstever@eecs.umich.edu    def __ifloordiv__(self, other):
5383101Sstever@eecs.umich.edu        self.value //= NumericParamValue.unwrap(other)
5393101Sstever@eecs.umich.edu        self._check()
5403101Sstever@eecs.umich.edu        return self
5413101Sstever@eecs.umich.edu
5423101Sstever@eecs.umich.edu    def __lt__(self, other):
5433101Sstever@eecs.umich.edu        return self.value < NumericParamValue.unwrap(other)
5443101Sstever@eecs.umich.edu
5453102Sstever@eecs.umich.edu    # Python 2.7 pre __future__.division operators
5463714Sstever@eecs.umich.edu    # TODO: Remove these when after "import division from __future__"
5473101Sstever@eecs.umich.edu    __div__ =  __truediv__
5483714Sstever@eecs.umich.edu    __idiv__ = __itruediv__
5493714Sstever@eecs.umich.edu
5503714Sstever@eecs.umich.edu    def config_value(self):
5513101Sstever@eecs.umich.edu        return self.value
5523101Sstever@eecs.umich.edu
55310267SGeoffrey.Blake@arm.com    @classmethod
55410267SGeoffrey.Blake@arm.com    def cxx_ini_predecls(cls, code):
55510267SGeoffrey.Blake@arm.com        # Assume that base/str.hh will be included anyway
55610267SGeoffrey.Blake@arm.com        # code('#include "base/str.hh"')
5577673Snate@binkert.org        pass
5587673Snate@binkert.org
5597673Snate@binkert.org    # The default for parsing PODs from an .ini entry is to extract from an
5607673Snate@binkert.org    # istringstream and let overloading choose the right type according to
5617673Snate@binkert.org    # the dest type.
5624762Snate@binkert.org    @classmethod
5634762Snate@binkert.org    def cxx_ini_parse(self, code, src, dest, ret):
5644762Snate@binkert.org        code('%s to_number(%s, %s);' % (ret, src, dest))
5653101Sstever@eecs.umich.edu
5663101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
5673101Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue):
5683101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5693101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
5703101Sstever@eecs.umich.edu
5713101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
5723101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
5733101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
5743101Sstever@eecs.umich.edu        if name == 'CheckedInt':
5753101Sstever@eecs.umich.edu            return
5763101Sstever@eecs.umich.edu
5773101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
5783101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
5793101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
5803101Sstever@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
5813101Sstever@eecs.umich.edu                      name);
5823101Sstever@eecs.umich.edu            if cls.unsigned:
5833101Sstever@eecs.umich.edu                cls.min = 0
5849184Sandreas.hansson@arm.com                cls.max = 2 ** cls.size - 1
5859184Sandreas.hansson@arm.com            else:
5869184Sandreas.hansson@arm.com                cls.min = -(2 ** (cls.size - 1))
5879184Sandreas.hansson@arm.com                cls.max = (2 ** (cls.size - 1)) - 1
5889184Sandreas.hansson@arm.com
5899184Sandreas.hansson@arm.com# Abstract superclass for bounds-checked integer parameters.  This
59011802Sandreas.sandberg@arm.com# class is subclassed to generate parameter classes with specific
5919184Sandreas.hansson@arm.com# bounds.  Initialization of the min and max bounds is done in the
5929184Sandreas.hansson@arm.com# metaclass CheckedIntType.__init__.
59310458Sandreas.hansson@arm.comclass CheckedInt(NumericParamValue):
59410458Sandreas.hansson@arm.com    __metaclass__ = CheckedIntType
59510458Sandreas.hansson@arm.com    cmd_line_settable = True
59610458Sandreas.hansson@arm.com
59710458Sandreas.hansson@arm.com    def _check(self):
59810458Sandreas.hansson@arm.com        if not self.min <= self.value <= self.max:
59910458Sandreas.hansson@arm.com            raise TypeError('Integer param out of bounds %d < %d < %d' % \
60010458Sandreas.hansson@arm.com                  (self.min, self.value, self.max))
60110458Sandreas.hansson@arm.com
60210458Sandreas.hansson@arm.com    def __init__(self, value):
60310458Sandreas.hansson@arm.com        if isinstance(value, str):
60410458Sandreas.hansson@arm.com            self.value = convert.toInteger(value)
60510458Sandreas.hansson@arm.com        elif isinstance(value, (int, long, float, NumericParamValue)):
60610458Sandreas.hansson@arm.com            self.value = long(value)
6073101Sstever@eecs.umich.edu        else:
6084446Sbinkertn@umich.edu            raise TypeError("Can't convert object of type %s to CheckedInt" \
60910668SGeoffrey.Blake@arm.com                  % type(value).__name__)
6103101Sstever@eecs.umich.edu        self._check()
6115468Snate@binkert.org
61210267SGeoffrey.Blake@arm.com    def __call__(self, value):
6135468Snate@binkert.org        self.__init__(value)
6145468Snate@binkert.org        return value
6155468Snate@binkert.org
6165468Snate@binkert.org    def __index__(self):
6175468Snate@binkert.org        return int(self.value)
61810267SGeoffrey.Blake@arm.com
61910267SGeoffrey.Blake@arm.com    @classmethod
62010267SGeoffrey.Blake@arm.com    def cxx_predecls(cls, code):
62110267SGeoffrey.Blake@arm.com        # most derived types require this, so we just do it here once
6224762Snate@binkert.org        code('#include "base/types.hh"')
6234762Snate@binkert.org
6244762Snate@binkert.org    def getValue(self):
62510380SAndrew.Bardsley@arm.com        return long(self.value)
62610380SAndrew.Bardsley@arm.com
62710380SAndrew.Bardsley@arm.comclass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
62810458Sandreas.hansson@arm.comclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
62910458Sandreas.hansson@arm.com
63010458Sandreas.hansson@arm.comclass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
63110458Sandreas.hansson@arm.comclass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
63210458Sandreas.hansson@arm.comclass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
63310458Sandreas.hansson@arm.comclass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
63410458Sandreas.hansson@arm.comclass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
63510458Sandreas.hansson@arm.comclass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
6363101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
6373101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
63810267SGeoffrey.Blake@arm.com
6393101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
6403101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
6413101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6423101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6433101Sstever@eecs.umich.edu
6443101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
6453102Sstever@eecs.umich.edu
6463101Sstever@eecs.umich.educlass Cycles(CheckedInt):
6473101Sstever@eecs.umich.edu    cxx_type = 'Cycles'
6483101Sstever@eecs.umich.edu    size = 64
6494168Sbinkertn@umich.edu    unsigned = True
65010267SGeoffrey.Blake@arm.com
6513101Sstever@eecs.umich.edu    def getValue(self):
6523101Sstever@eecs.umich.edu        from _m5.core import Cycles
6533101Sstever@eecs.umich.edu        return Cycles(self.value)
6543101Sstever@eecs.umich.edu
6553101Sstever@eecs.umich.edu    @classmethod
6563101Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
6573102Sstever@eecs.umich.edu        # Assume that base/str.hh will be included anyway
6583101Sstever@eecs.umich.edu        # code('#include "base/str.hh"')
6593101Sstever@eecs.umich.edu        pass
6603101Sstever@eecs.umich.edu
6613101Sstever@eecs.umich.edu    @classmethod
6623101Sstever@eecs.umich.edu    def cxx_ini_parse(cls, code, src, dest, ret):
6633101Sstever@eecs.umich.edu        code('uint64_t _temp;')
6643101Sstever@eecs.umich.edu        code('bool _ret = to_number(%s, _temp);' % src)
6653101Sstever@eecs.umich.edu        code('if (_ret)')
6663101Sstever@eecs.umich.edu        code('    %s = Cycles(_temp);' % dest)
6673101Sstever@eecs.umich.edu        code('%s _ret;' % ret)
6683101Sstever@eecs.umich.edu
66910317Smitch.hayenga@arm.comclass Float(ParamValue, float):
67010317Smitch.hayenga@arm.com    cxx_type = 'double'
67110317Smitch.hayenga@arm.com    cmd_line_settable = True
67210317Smitch.hayenga@arm.com
67310317Smitch.hayenga@arm.com    def __init__(self, value):
6743102Sstever@eecs.umich.edu        if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
67510317Smitch.hayenga@arm.com            self.value = float(value)
67610317Smitch.hayenga@arm.com        else:
67710317Smitch.hayenga@arm.com            raise TypeError("Can't convert object of type %s to Float" \
67810317Smitch.hayenga@arm.com                  % type(value).__name__)
67910317Smitch.hayenga@arm.com
6803101Sstever@eecs.umich.edu    def __call__(self, value):
6813584Ssaidi@eecs.umich.edu        self.__init__(value)
6823584Ssaidi@eecs.umich.edu        return value
6833584Ssaidi@eecs.umich.edu
6843584Ssaidi@eecs.umich.edu    def getValue(self):
6853584Ssaidi@eecs.umich.edu        return float(self.value)
68610267SGeoffrey.Blake@arm.com
68710267SGeoffrey.Blake@arm.com    def config_value(self):
68810267SGeoffrey.Blake@arm.com        return self
68910267SGeoffrey.Blake@arm.com
69010267SGeoffrey.Blake@arm.com    @classmethod
69110267SGeoffrey.Blake@arm.com    def cxx_ini_predecls(cls, code):
6923101Sstever@eecs.umich.edu        code('#include <sstream>')
6939232Sandreas.hansson@arm.com
6949235Sandreas.hansson@arm.com    @classmethod
6953101Sstever@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
6963101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
69710676Sandreas.hansson@arm.com
6989411Sandreas.hansson@arm.comclass MemorySize(CheckedInt):
69910676Sandreas.hansson@arm.com    cxx_type = 'uint64_t'
7009411Sandreas.hansson@arm.com    ex_str = '512MB'
7019411Sandreas.hansson@arm.com    size = 64
7029411Sandreas.hansson@arm.com    unsigned = True
7033101Sstever@eecs.umich.edu    def __init__(self, value):
7049411Sandreas.hansson@arm.com        if isinstance(value, MemorySize):
7059411Sandreas.hansson@arm.com            self.value = value.value
7069411Sandreas.hansson@arm.com        else:
7073101Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
7089232Sandreas.hansson@arm.com        self._check()
7093101Sstever@eecs.umich.edu
7109232Sandreas.hansson@arm.comclass MemorySize32(CheckedInt):
7113101Sstever@eecs.umich.edu    cxx_type = 'uint32_t'
7123101Sstever@eecs.umich.edu    ex_str = '512MB'
7133101Sstever@eecs.umich.edu    size = 32
7149411Sandreas.hansson@arm.com    unsigned = True
7159411Sandreas.hansson@arm.com    def __init__(self, value):
7169411Sandreas.hansson@arm.com        if isinstance(value, MemorySize):
71710676Sandreas.hansson@arm.com            self.value = value.value
71810676Sandreas.hansson@arm.com        else:
7199411Sandreas.hansson@arm.com            self.value = convert.toMemorySize(value)
7209411Sandreas.hansson@arm.com        self._check()
7219411Sandreas.hansson@arm.com
7229411Sandreas.hansson@arm.comclass Addr(CheckedInt):
7239411Sandreas.hansson@arm.com    cxx_type = 'Addr'
7243101Sstever@eecs.umich.edu    size = 64
7259232Sandreas.hansson@arm.com    unsigned = True
7263101Sstever@eecs.umich.edu    def __init__(self, value):
7273101Sstever@eecs.umich.edu        if isinstance(value, Addr):
7283101Sstever@eecs.umich.edu            self.value = value.value
7293101Sstever@eecs.umich.edu        else:
7309232Sandreas.hansson@arm.com            try:
7313101Sstever@eecs.umich.edu                # Often addresses are referred to with sizes. Ex: A device
7325219Ssaidi@eecs.umich.edu                # base address is at "512MB".  Use toMemorySize() to convert
7339232Sandreas.hansson@arm.com                # these into addresses. If the address is not specified with a
7349232Sandreas.hansson@arm.com                # "size", an exception will occur and numeric translation will
7353101Sstever@eecs.umich.edu                # proceed below.
7369232Sandreas.hansson@arm.com                self.value = convert.toMemorySize(value)
7379232Sandreas.hansson@arm.com            except (TypeError, ValueError):
7383101Sstever@eecs.umich.edu                # Convert number to string and use long() to do automatic
7393101Sstever@eecs.umich.edu                # base conversion (requires base=0 for auto-conversion)
7409232Sandreas.hansson@arm.com                self.value = long(str(value), base=0)
7419232Sandreas.hansson@arm.com
7423101Sstever@eecs.umich.edu        self._check()
7433101Sstever@eecs.umich.edu    def __add__(self, other):
7443101Sstever@eecs.umich.edu        if isinstance(other, Addr):
7453101Sstever@eecs.umich.edu            return self.value + other.value
7469232Sandreas.hansson@arm.com        else:
7473101Sstever@eecs.umich.edu            return self.value + other
7483101Sstever@eecs.umich.edu    def pretty_print(self, value):
74911620SMatthew.Poremba@amd.com        try:
75011620SMatthew.Poremba@amd.com            val = convert.toMemorySize(value)
75111620SMatthew.Poremba@amd.com        except TypeError:
7529232Sandreas.hansson@arm.com            val = long(value)
7539232Sandreas.hansson@arm.com        return "0x%x" % long(val)
7549411Sandreas.hansson@arm.com
7559411Sandreas.hansson@arm.comclass AddrRange(ParamValue):
7563101Sstever@eecs.umich.edu    cxx_type = 'AddrRange'
7577673Snate@binkert.org
7587673Snate@binkert.org    def __init__(self, *args, **kwargs):
7599232Sandreas.hansson@arm.com        # Disable interleaving and hashing by default
7609235Sandreas.hansson@arm.com        self.intlvHighBit = 0
7617675Snate@binkert.org        self.xorHighBit = 0
7627675Snate@binkert.org        self.intlvBits = 0
76311988Sandreas.sandberg@arm.com        self.intlvMatch = 0
76411988Sandreas.sandberg@arm.com
76511988Sandreas.sandberg@arm.com        def handle_kwargs(self, kwargs):
76611988Sandreas.sandberg@arm.com            # An address range needs to have an upper limit, specified
76711988Sandreas.sandberg@arm.com            # either explicitly with an end, or as an offset using the
76810458Sandreas.hansson@arm.com            # size keyword.
76910458Sandreas.hansson@arm.com            if 'end' in kwargs:
77010458Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
77110458Sandreas.hansson@arm.com            elif 'size' in kwargs:
77210458Sandreas.hansson@arm.com                self.end = self.start + Addr(kwargs.pop('size')) - 1
77311620SMatthew.Poremba@amd.com            else:
77411620SMatthew.Poremba@amd.com                raise TypeError("Either end or size must be specified")
77510458Sandreas.hansson@arm.com
77610458Sandreas.hansson@arm.com            # Now on to the optional bit
77710458Sandreas.hansson@arm.com            if 'intlvHighBit' in kwargs:
77810458Sandreas.hansson@arm.com                self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
77910458Sandreas.hansson@arm.com            if 'xorHighBit' in kwargs:
78011620SMatthew.Poremba@amd.com                self.xorHighBit = int(kwargs.pop('xorHighBit'))
78111620SMatthew.Poremba@amd.com            if 'intlvBits' in kwargs:
78211620SMatthew.Poremba@amd.com                self.intlvBits = int(kwargs.pop('intlvBits'))
78311620SMatthew.Poremba@amd.com            if 'intlvMatch' in kwargs:
78411620SMatthew.Poremba@amd.com                self.intlvMatch = int(kwargs.pop('intlvMatch'))
78511620SMatthew.Poremba@amd.com
78611620SMatthew.Poremba@amd.com        if len(args) == 0:
78711620SMatthew.Poremba@amd.com            self.start = Addr(kwargs.pop('start'))
78811620SMatthew.Poremba@amd.com            handle_kwargs(self, kwargs)
78911620SMatthew.Poremba@amd.com
79010458Sandreas.hansson@arm.com        elif len(args) == 1:
79110458Sandreas.hansson@arm.com            if kwargs:
79210458Sandreas.hansson@arm.com                self.start = Addr(args[0])
79311620SMatthew.Poremba@amd.com                handle_kwargs(self, kwargs)
79411620SMatthew.Poremba@amd.com            elif isinstance(args[0], (list, tuple)):
79510458Sandreas.hansson@arm.com                self.start = Addr(args[0][0])
79610458Sandreas.hansson@arm.com                self.end = Addr(args[0][1])
7974762Snate@binkert.org            else:
79811991Sandreas.sandberg@arm.com                self.start = Addr(0)
79911802Sandreas.sandberg@arm.com                self.end = Addr(args[0]) - 1
8004762Snate@binkert.org
8019411Sandreas.hansson@arm.com        elif len(args) == 2:
80210676Sandreas.hansson@arm.com            self.start = Addr(args[0])
80310676Sandreas.hansson@arm.com            self.end = Addr(args[1])
8043101Sstever@eecs.umich.edu        else:
8053101Sstever@eecs.umich.edu            raise TypeError("Too many arguments specified")
8063101Sstever@eecs.umich.edu
8073101Sstever@eecs.umich.edu        if kwargs:
8083101Sstever@eecs.umich.edu            raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
8093101Sstever@eecs.umich.edu
81010267SGeoffrey.Blake@arm.com    def __str__(self):
81110267SGeoffrey.Blake@arm.com        return '%s:%s:%s:%s:%s:%s' \
8123101Sstever@eecs.umich.edu            % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\
8133101Sstever@eecs.umich.edu               self.intlvBits, self.intlvMatch)
8143102Sstever@eecs.umich.edu
8153101Sstever@eecs.umich.edu    def size(self):
8163101Sstever@eecs.umich.edu        # Divide the size by the size of the interleaving slice
8173101Sstever@eecs.umich.edu        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
81810267SGeoffrey.Blake@arm.com
81910267SGeoffrey.Blake@arm.com    @classmethod
82010267SGeoffrey.Blake@arm.com    def cxx_predecls(cls, code):
82110267SGeoffrey.Blake@arm.com        Addr.cxx_predecls(code)
8224762Snate@binkert.org        code('#include "base/addr_range.hh"')
8234762Snate@binkert.org
8244762Snate@binkert.org    @classmethod
8253101Sstever@eecs.umich.edu    def pybind_predecls(cls, code):
8263101Sstever@eecs.umich.edu        Addr.pybind_predecls(code)
8273101Sstever@eecs.umich.edu        code('#include "base/addr_range.hh"')
8288934SBrad.Beckmann@amd.com
8298934SBrad.Beckmann@amd.com    @classmethod
8308934SBrad.Beckmann@amd.com    def cxx_ini_predecls(cls, code):
8318934SBrad.Beckmann@amd.com        code('#include <sstream>')
8328934SBrad.Beckmann@amd.com
8333101Sstever@eecs.umich.edu    @classmethod
8343101Sstever@eecs.umich.edu    def cxx_ini_parse(cls, code, src, dest, ret):
8353101Sstever@eecs.umich.edu        code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;')
8363101Sstever@eecs.umich.edu        code('uint64_t _intlvBits = 0, _intlvMatch = 0;')
8373101Sstever@eecs.umich.edu        code('char _sep;')
83810380SAndrew.Bardsley@arm.com        code('std::istringstream _stream(${src});')
83910380SAndrew.Bardsley@arm.com        code('_stream >> _start;')
84010380SAndrew.Bardsley@arm.com        code('_stream.get(_sep);')
84110458Sandreas.hansson@arm.com        code('_stream >> _end;')
84210458Sandreas.hansson@arm.com        code('if (!_stream.fail() && !_stream.eof()) {')
84310458Sandreas.hansson@arm.com        code('    _stream.get(_sep);')
84410458Sandreas.hansson@arm.com        code('    _stream >> _intlvHighBit;')
84510458Sandreas.hansson@arm.com        code('    _stream.get(_sep);')
84610458Sandreas.hansson@arm.com        code('    _stream >> _xorHighBit;')
84710458Sandreas.hansson@arm.com        code('    _stream.get(_sep);')
84810458Sandreas.hansson@arm.com        code('    _stream >> _intlvBits;')
84910458Sandreas.hansson@arm.com        code('    _stream.get(_sep);')
85010458Sandreas.hansson@arm.com        code('    _stream >> _intlvMatch;')
8513101Sstever@eecs.umich.edu        code('}')
8523101Sstever@eecs.umich.edu        code('bool _ret = !_stream.fail() &&'
8533101Sstever@eecs.umich.edu            '_stream.eof() && _sep == \':\';')
8543101Sstever@eecs.umich.edu        code('if (_ret)')
8553101Sstever@eecs.umich.edu        code('   ${dest} = AddrRange(_start, _end, _intlvHighBit, \
8563101Sstever@eecs.umich.edu                _xorHighBit, _intlvBits, _intlvMatch);')
8573101Sstever@eecs.umich.edu        code('${ret} _ret;')
8583101Sstever@eecs.umich.edu
8593101Sstever@eecs.umich.edu    def getValue(self):
8603101Sstever@eecs.umich.edu        # Go from the Python class to the wrapped C++ class
8613101Sstever@eecs.umich.edu        from _m5.range import AddrRange
8623101Sstever@eecs.umich.edu
8634380Sbinkertn@umich.edu        return AddrRange(long(self.start), long(self.end),
8644380Sbinkertn@umich.edu                         int(self.intlvHighBit), int(self.xorHighBit),
8654380Sbinkertn@umich.edu                         int(self.intlvBits), int(self.intlvMatch))
8663101Sstever@eecs.umich.edu
8674380Sbinkertn@umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
8684380Sbinkertn@umich.edu# it doesn't want to let you create multiple instances of True and
8694380Sbinkertn@umich.edu# False.  Thus this is a little more complicated than String.
8703101Sstever@eecs.umich.educlass Bool(ParamValue):
8713101Sstever@eecs.umich.edu    cxx_type = 'bool'
8723101Sstever@eecs.umich.edu    cmd_line_settable = True
87310267SGeoffrey.Blake@arm.com
87410267SGeoffrey.Blake@arm.com    def __init__(self, value):
8757673Snate@binkert.org        try:
8767673Snate@binkert.org            self.value = convert.toBool(value)
8777673Snate@binkert.org        except TypeError:
8787673Snate@binkert.org            self.value = bool(value)
8797673Snate@binkert.org
8803101Sstever@eecs.umich.edu    def __call__(self, value):
8813101Sstever@eecs.umich.edu        self.__init__(value)
8823101Sstever@eecs.umich.edu        return value
8833101Sstever@eecs.umich.edu
8843101Sstever@eecs.umich.edu    def getValue(self):
8853101Sstever@eecs.umich.edu        return bool(self.value)
8863101Sstever@eecs.umich.edu
8873101Sstever@eecs.umich.edu    def __str__(self):
8883101Sstever@eecs.umich.edu        return str(self.value)
8893101Sstever@eecs.umich.edu
8903101Sstever@eecs.umich.edu    # implement truth value testing for Bool parameters so that these params
8913101Sstever@eecs.umich.edu    # evaluate correctly during the python configuration phase
8923101Sstever@eecs.umich.edu    def __bool__(self):
8939941SGeoffrey.Blake@arm.com        return bool(self.value)
8943101Sstever@eecs.umich.edu
8953101Sstever@eecs.umich.edu    # Python 2.7 uses __nonzero__ instead of __bool__
8963101Sstever@eecs.umich.edu    __nonzero__ = __bool__
8973101Sstever@eecs.umich.edu
89810267SGeoffrey.Blake@arm.com    def ini_str(self):
89910267SGeoffrey.Blake@arm.com        if self.value:
90010267SGeoffrey.Blake@arm.com            return 'true'
90110267SGeoffrey.Blake@arm.com        return 'false'
9023101Sstever@eecs.umich.edu
9033101Sstever@eecs.umich.edu    def config_value(self):
9044380Sbinkertn@umich.edu        return self.value
9053101Sstever@eecs.umich.edu
9063101Sstever@eecs.umich.edu    @classmethod
9074762Snate@binkert.org    def cxx_ini_predecls(cls, code):
90811988Sandreas.sandberg@arm.com        # Assume that base/str.hh will be included anyway
9094762Snate@binkert.org        # code('#include "base/str.hh"')
9104762Snate@binkert.org        pass
91111228SAndrew.Bardsley@arm.com
91211228SAndrew.Bardsley@arm.com    @classmethod
91311228SAndrew.Bardsley@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
9144380Sbinkertn@umich.edu        code('%s to_bool(%s, %s);' % (ret, src, dest))
9154380Sbinkertn@umich.edu
9163101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
91710458Sandreas.hansson@arm.com    bytes = [ int(x, 16) for x in addr.split(':') ]
91810458Sandreas.hansson@arm.com    bytes[5] += val
91910458Sandreas.hansson@arm.com    for i in (5, 4, 3, 2, 1):
92010458Sandreas.hansson@arm.com        val,rem = divmod(bytes[i], 256)
92110458Sandreas.hansson@arm.com        bytes[i] = rem
9227777Sgblack@eecs.umich.edu        if val == 0:
9237777Sgblack@eecs.umich.edu            break
9247777Sgblack@eecs.umich.edu        bytes[i - 1] += val
9257777Sgblack@eecs.umich.edu    assert(bytes[0] <= 255)
92610267SGeoffrey.Blake@arm.com    return ':'.join(map(lambda x: '%02x' % x, bytes))
92710267SGeoffrey.Blake@arm.com
9287777Sgblack@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
9297777Sgblack@eecs.umich.edudef NextEthernetAddr():
9307777Sgblack@eecs.umich.edu    global _NextEthernetAddr
9317777Sgblack@eecs.umich.edu
9327777Sgblack@eecs.umich.edu    value = _NextEthernetAddr
9337777Sgblack@eecs.umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
9347777Sgblack@eecs.umich.edu    return value
9357777Sgblack@eecs.umich.edu
9367777Sgblack@eecs.umich.educlass EthernetAddr(ParamValue):
9377777Sgblack@eecs.umich.edu    cxx_type = 'Net::EthAddr'
9387777Sgblack@eecs.umich.edu    ex_str = "00:90:00:00:00:01"
9397777Sgblack@eecs.umich.edu    cmd_line_settable = True
9407777Sgblack@eecs.umich.edu
9417777Sgblack@eecs.umich.edu    @classmethod
9427777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
94310267SGeoffrey.Blake@arm.com        code('#include "base/inet.hh"')
94410267SGeoffrey.Blake@arm.com
94510267SGeoffrey.Blake@arm.com    def __init__(self, value):
94610267SGeoffrey.Blake@arm.com        if value == NextEthernetAddr:
9478579Ssteve.reinhardt@amd.com            self.value = value
9488579Ssteve.reinhardt@amd.com            return
9498579Ssteve.reinhardt@amd.com
9508579Ssteve.reinhardt@amd.com        if not isinstance(value, str):
9518579Ssteve.reinhardt@amd.com            raise TypeError("expected an ethernet address and didn't get one")
9528579Ssteve.reinhardt@amd.com
9538579Ssteve.reinhardt@amd.com        bytes = value.split(':')
9548579Ssteve.reinhardt@amd.com        if len(bytes) != 6:
9558579Ssteve.reinhardt@amd.com            raise TypeError('invalid ethernet address %s' % value)
9568579Ssteve.reinhardt@amd.com
9578579Ssteve.reinhardt@amd.com        for byte in bytes:
9588579Ssteve.reinhardt@amd.com            if not 0 <= int(byte, base=16) <= 0xff:
9598579Ssteve.reinhardt@amd.com                raise TypeError('invalid ethernet address %s' % value)
9608579Ssteve.reinhardt@amd.com
9618579Ssteve.reinhardt@amd.com        self.value = value
9628579Ssteve.reinhardt@amd.com
9638579Ssteve.reinhardt@amd.com    def __call__(self, value):
9648579Ssteve.reinhardt@amd.com        self.__init__(value)
9657777Sgblack@eecs.umich.edu        return value
9667777Sgblack@eecs.umich.edu
9677798Sgblack@eecs.umich.edu    def unproxy(self, base):
9687777Sgblack@eecs.umich.edu        if self.value == NextEthernetAddr:
9697777Sgblack@eecs.umich.edu            return EthernetAddr(self.value())
97011988Sandreas.sandberg@arm.com        return self
9717777Sgblack@eecs.umich.edu
9727777Sgblack@eecs.umich.edu    def getValue(self):
9737777Sgblack@eecs.umich.edu        from _m5.net import EthAddr
9747777Sgblack@eecs.umich.edu        return EthAddr(self.value)
9757777Sgblack@eecs.umich.edu
9767777Sgblack@eecs.umich.edu    def __str__(self):
9777777Sgblack@eecs.umich.edu        return self.value
97810267SGeoffrey.Blake@arm.com
97910267SGeoffrey.Blake@arm.com    def ini_str(self):
9807777Sgblack@eecs.umich.edu        return self.value
9817777Sgblack@eecs.umich.edu
9827777Sgblack@eecs.umich.edu    @classmethod
9837777Sgblack@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
9847777Sgblack@eecs.umich.edu        code('%s = Net::EthAddr(%s);' % (dest, src))
9857777Sgblack@eecs.umich.edu        code('%s true;' % ret)
9867777Sgblack@eecs.umich.edu
9877777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
9887777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
9897777Sgblack@eecs.umich.educlass IpAddress(ParamValue):
9907777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpAddress'
9917777Sgblack@eecs.umich.edu    ex_str = "127.0.0.1"
9927777Sgblack@eecs.umich.edu    cmd_line_settable = True
9937777Sgblack@eecs.umich.edu
9947777Sgblack@eecs.umich.edu    @classmethod
9957777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
9967777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
9977777Sgblack@eecs.umich.edu
9987777Sgblack@eecs.umich.edu    def __init__(self, value):
9997777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
10007777Sgblack@eecs.umich.edu            self.ip = value.ip
10017777Sgblack@eecs.umich.edu        else:
10027777Sgblack@eecs.umich.edu            try:
10037777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
10047777Sgblack@eecs.umich.edu            except TypeError:
10057777Sgblack@eecs.umich.edu                self.ip = long(value)
10067777Sgblack@eecs.umich.edu        self.verifyIp()
10077777Sgblack@eecs.umich.edu
10087777Sgblack@eecs.umich.edu    def __call__(self, value):
10097777Sgblack@eecs.umich.edu        self.__init__(value)
10107777Sgblack@eecs.umich.edu        return value
10117777Sgblack@eecs.umich.edu
10127777Sgblack@eecs.umich.edu    def __str__(self):
10137777Sgblack@eecs.umich.edu        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
10147777Sgblack@eecs.umich.edu        return '%d.%d.%d.%d' % tuple(tup)
10157777Sgblack@eecs.umich.edu
10167777Sgblack@eecs.umich.edu    def __eq__(self, other):
10177777Sgblack@eecs.umich.edu        if isinstance(other, IpAddress):
10187777Sgblack@eecs.umich.edu            return self.ip == other.ip
10197777Sgblack@eecs.umich.edu        elif isinstance(other, str):
10207777Sgblack@eecs.umich.edu            try:
102110267SGeoffrey.Blake@arm.com                return self.ip == convert.toIpAddress(other)
102210267SGeoffrey.Blake@arm.com            except:
102310267SGeoffrey.Blake@arm.com                return False
102410267SGeoffrey.Blake@arm.com        else:
10258579Ssteve.reinhardt@amd.com            return self.ip == other
10268579Ssteve.reinhardt@amd.com
10278579Ssteve.reinhardt@amd.com    def __ne__(self, other):
10288579Ssteve.reinhardt@amd.com        return not (self == other)
10298579Ssteve.reinhardt@amd.com
10308579Ssteve.reinhardt@amd.com    def verifyIp(self):
10318579Ssteve.reinhardt@amd.com        if self.ip < 0 or self.ip >= (1 << 32):
10328579Ssteve.reinhardt@amd.com            raise TypeError("invalid ip address %#08x" % self.ip)
10338579Ssteve.reinhardt@amd.com
10348579Ssteve.reinhardt@amd.com    def getValue(self):
10358579Ssteve.reinhardt@amd.com        from _m5.net import IpAddress
10368579Ssteve.reinhardt@amd.com        return IpAddress(self.ip)
10378579Ssteve.reinhardt@amd.com
10388579Ssteve.reinhardt@amd.com# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
10397777Sgblack@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
10407777Sgblack@eecs.umich.edu# positional or keyword arguments.
10417777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
10427777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
10437777Sgblack@eecs.umich.edu    ex_str = "127.0.0.0/24"
10447777Sgblack@eecs.umich.edu    cmd_line_settable = True
104511988Sandreas.sandberg@arm.com
10467777Sgblack@eecs.umich.edu    @classmethod
10477777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10487777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10497777Sgblack@eecs.umich.edu
10507777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10517777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
105210267SGeoffrey.Blake@arm.com            if key in kwargs:
105310267SGeoffrey.Blake@arm.com                setattr(self, key, kwargs.pop(key))
10547777Sgblack@eecs.umich.edu            elif elseVal:
10557777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10567777Sgblack@eecs.umich.edu            else:
10577777Sgblack@eecs.umich.edu                raise TypeError("No value set for %s" % key)
10587777Sgblack@eecs.umich.edu
10597777Sgblack@eecs.umich.edu        if len(args) == 0:
10607777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
10617777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
10627777Sgblack@eecs.umich.edu
10637777Sgblack@eecs.umich.edu        elif len(args) == 1:
10647777Sgblack@eecs.umich.edu            if kwargs:
10657777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
10667777Sgblack@eecs.umich.edu                    raise TypeError("Invalid arguments")
10677777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
10687777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
10697777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
10707777Sgblack@eecs.umich.edu                self.ip = args[0].ip
10717777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
10727777Sgblack@eecs.umich.edu            else:
10737777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
10747777Sgblack@eecs.umich.edu
10757777Sgblack@eecs.umich.edu        elif len(args) == 2:
10767777Sgblack@eecs.umich.edu            self.ip = args[0]
10777777Sgblack@eecs.umich.edu            self.netmask = args[1]
10787777Sgblack@eecs.umich.edu        else:
10797777Sgblack@eecs.umich.edu            raise TypeError("Too many arguments specified")
10807777Sgblack@eecs.umich.edu
10817777Sgblack@eecs.umich.edu        if kwargs:
10827777Sgblack@eecs.umich.edu            raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
10837777Sgblack@eecs.umich.edu
10847777Sgblack@eecs.umich.edu        self.verify()
10857777Sgblack@eecs.umich.edu
10867777Sgblack@eecs.umich.edu    def __call__(self, value):
10877777Sgblack@eecs.umich.edu        self.__init__(value)
10887777Sgblack@eecs.umich.edu        return value
10897777Sgblack@eecs.umich.edu
10907777Sgblack@eecs.umich.edu    def __str__(self):
10917777Sgblack@eecs.umich.edu        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
10927777Sgblack@eecs.umich.edu
10937777Sgblack@eecs.umich.edu    def __eq__(self, other):
10947777Sgblack@eecs.umich.edu        if isinstance(other, IpNetmask):
109510267SGeoffrey.Blake@arm.com            return self.ip == other.ip and self.netmask == other.netmask
109610267SGeoffrey.Blake@arm.com        elif isinstance(other, str):
109710267SGeoffrey.Blake@arm.com            try:
109810267SGeoffrey.Blake@arm.com                return (self.ip, self.netmask) == convert.toIpNetmask(other)
10998579Ssteve.reinhardt@amd.com            except:
11008579Ssteve.reinhardt@amd.com                return False
11018579Ssteve.reinhardt@amd.com        else:
11028579Ssteve.reinhardt@amd.com            return False
11038579Ssteve.reinhardt@amd.com
11048579Ssteve.reinhardt@amd.com    def verify(self):
11058579Ssteve.reinhardt@amd.com        self.verifyIp()
11068579Ssteve.reinhardt@amd.com        if self.netmask < 0 or self.netmask > 32:
11078579Ssteve.reinhardt@amd.com            raise TypeError("invalid netmask %d" % netmask)
11088579Ssteve.reinhardt@amd.com
11098579Ssteve.reinhardt@amd.com    def getValue(self):
11108579Ssteve.reinhardt@amd.com        from _m5.net import IpNetmask
11118579Ssteve.reinhardt@amd.com        return IpNetmask(self.ip, self.netmask)
11128579Ssteve.reinhardt@amd.com
11137777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
11147777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
11157777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
11167777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
11177777Sgblack@eecs.umich.edu    ex_str = "127.0.0.1:80"
11187777Sgblack@eecs.umich.edu    cmd_line_settable = True
111911988Sandreas.sandberg@arm.com
11207777Sgblack@eecs.umich.edu    @classmethod
11217777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
11223932Sbinkertn@umich.edu        code('#include "base/inet.hh"')
112310380SAndrew.Bardsley@arm.com
11243932Sbinkertn@umich.edu    def __init__(self, *args, **kwargs):
11253932Sbinkertn@umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
11263932Sbinkertn@umich.edu            if key in kwargs:
11273932Sbinkertn@umich.edu                setattr(self, key, kwargs.pop(key))
11283932Sbinkertn@umich.edu            elif elseVal:
11293932Sbinkertn@umich.edu                setattr(self, key, elseVal)
11303932Sbinkertn@umich.edu            else:
11313932Sbinkertn@umich.edu                raise TypeError("No value set for %s" % key)
11323932Sbinkertn@umich.edu
11333932Sbinkertn@umich.edu        if len(args) == 0:
11343932Sbinkertn@umich.edu            handle_kwarg(self, kwargs, 'ip')
11353885Sbinkertn@umich.edu            handle_kwarg(self, kwargs, 'port')
11363932Sbinkertn@umich.edu
11373932Sbinkertn@umich.edu        elif len(args) == 1:
11383885Sbinkertn@umich.edu            if kwargs:
11393932Sbinkertn@umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
11403932Sbinkertn@umich.edu                    raise TypeError("Invalid arguments")
11413932Sbinkertn@umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
11423932Sbinkertn@umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
11433932Sbinkertn@umich.edu            elif isinstance(args[0], IpWithPort):
11443932Sbinkertn@umich.edu                self.ip = args[0].ip
11453932Sbinkertn@umich.edu                self.port = args[0].port
11463932Sbinkertn@umich.edu            else:
11473932Sbinkertn@umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
11483932Sbinkertn@umich.edu
11493932Sbinkertn@umich.edu        elif len(args) == 2:
11503932Sbinkertn@umich.edu            self.ip = args[0]
11513932Sbinkertn@umich.edu            self.port = args[1]
11523932Sbinkertn@umich.edu        else:
11533932Sbinkertn@umich.edu            raise TypeError("Too many arguments specified")
11543932Sbinkertn@umich.edu
11553932Sbinkertn@umich.edu        if kwargs:
11563932Sbinkertn@umich.edu            raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
11573885Sbinkertn@umich.edu
11583885Sbinkertn@umich.edu        self.verify()
11593885Sbinkertn@umich.edu
11603885Sbinkertn@umich.edu    def __call__(self, value):
11614762Snate@binkert.org        self.__init__(value)
11627673Snate@binkert.org        return value
11637673Snate@binkert.org
11647673Snate@binkert.org    def __str__(self):
11657673Snate@binkert.org        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
11667673Snate@binkert.org
11673885Sbinkertn@umich.edu    def __eq__(self, other):
11683932Sbinkertn@umich.edu        if isinstance(other, IpWithPort):
11693885Sbinkertn@umich.edu            return self.ip == other.ip and self.port == other.port
117010267SGeoffrey.Blake@arm.com        elif isinstance(other, str):
117110267SGeoffrey.Blake@arm.com            try:
117210267SGeoffrey.Blake@arm.com                return (self.ip, self.port) == convert.toIpWithPort(other)
117310267SGeoffrey.Blake@arm.com            except:
11744762Snate@binkert.org                return False
117511988Sandreas.sandberg@arm.com        else:
117611988Sandreas.sandberg@arm.com            return False
11774762Snate@binkert.org
117811988Sandreas.sandberg@arm.com    def verify(self):
11794762Snate@binkert.org        self.verifyIp()
11803885Sbinkertn@umich.edu        if self.port < 0 or self.port > 0xffff:
11814762Snate@binkert.org            raise TypeError("invalid port %d" % self.port)
11823885Sbinkertn@umich.edu
11833885Sbinkertn@umich.edu    def getValue(self):
11843932Sbinkertn@umich.edu        from _m5.net import IpWithPort
11853885Sbinkertn@umich.edu        return IpWithPort(self.ip, self.port)
11868664SAli.Saidi@ARM.com
118710380SAndrew.Bardsley@arm.comtime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
11888664SAli.Saidi@ARM.com                 "%a %b %d %H:%M:%S %Y",
11898664SAli.Saidi@ARM.com                 "%Y/%m/%d %H:%M:%S",
119010458Sandreas.hansson@arm.com                 "%Y/%m/%d %H:%M",
119110458Sandreas.hansson@arm.com                 "%Y/%m/%d",
119210458Sandreas.hansson@arm.com                 "%m/%d/%Y %H:%M:%S",
119310458Sandreas.hansson@arm.com                 "%m/%d/%Y %H:%M",
119410458Sandreas.hansson@arm.com                 "%m/%d/%Y",
119510458Sandreas.hansson@arm.com                 "%m/%d/%y %H:%M:%S",
119610458Sandreas.hansson@arm.com                 "%m/%d/%y %H:%M",
119710458Sandreas.hansson@arm.com                 "%m/%d/%y"]
119810458Sandreas.hansson@arm.com
119910458Sandreas.hansson@arm.com
12003101Sstever@eecs.umich.edudef parse_time(value):
12013101Sstever@eecs.umich.edu    from time import gmtime, strptime, struct_time, time
12023101Sstever@eecs.umich.edu    from datetime import datetime, date
12033101Sstever@eecs.umich.edu
12043101Sstever@eecs.umich.edu    if isinstance(value, struct_time):
12053101Sstever@eecs.umich.edu        return value
12063101Sstever@eecs.umich.edu
12073101Sstever@eecs.umich.edu    if isinstance(value, (int, long)):
12083101Sstever@eecs.umich.edu        return gmtime(value)
12093101Sstever@eecs.umich.edu
12103101Sstever@eecs.umich.edu    if isinstance(value, (datetime, date)):
12113101Sstever@eecs.umich.edu        return value.timetuple()
12123101Sstever@eecs.umich.edu
12133101Sstever@eecs.umich.edu    if isinstance(value, str):
12144762Snate@binkert.org        if value in ('Now', 'Today'):
12153101Sstever@eecs.umich.edu            return time.gmtime(time.time())
12165033Smilesck@eecs.umich.edu
12174762Snate@binkert.org        for format in time_formats:
12184762Snate@binkert.org            try:
12194762Snate@binkert.org                return strptime(value, format)
12204762Snate@binkert.org            except ValueError:
12214762Snate@binkert.org                pass
12224762Snate@binkert.org
12234762Snate@binkert.org    raise ValueError("Could not parse '%s' as a time" % value)
12243101Sstever@eecs.umich.edu
12253101Sstever@eecs.umich.educlass Time(ParamValue):
12263101Sstever@eecs.umich.edu    cxx_type = 'tm'
12273101Sstever@eecs.umich.edu
12283101Sstever@eecs.umich.edu    @classmethod
12293101Sstever@eecs.umich.edu    def cxx_predecls(cls, code):
12303101Sstever@eecs.umich.edu        code('#include <time.h>')
12313101Sstever@eecs.umich.edu
12323101Sstever@eecs.umich.edu    def __init__(self, value):
12333101Sstever@eecs.umich.edu        self.value = parse_time(value)
12343101Sstever@eecs.umich.edu
12353101Sstever@eecs.umich.edu    def __call__(self, value):
12363101Sstever@eecs.umich.edu        self.__init__(value)
12373101Sstever@eecs.umich.edu        return value
12383101Sstever@eecs.umich.edu
12393101Sstever@eecs.umich.edu    def getValue(self):
12403101Sstever@eecs.umich.edu        from _m5.core import tm
12413101Sstever@eecs.umich.edu        import calendar
12423101Sstever@eecs.umich.edu
12433101Sstever@eecs.umich.edu        return tm.gmtime(calendar.timegm(self.value))
12444762Snate@binkert.org
12453101Sstever@eecs.umich.edu    def __str__(self):
12463101Sstever@eecs.umich.edu        return time.asctime(self.value)
12473101Sstever@eecs.umich.edu
12483101Sstever@eecs.umich.edu    def ini_str(self):
12493101Sstever@eecs.umich.edu        return str(self)
12503101Sstever@eecs.umich.edu
12517673Snate@binkert.org    def get_config_as_dict(self):
125210201SAndrew.Bardsley@arm.com        assert false
125310201SAndrew.Bardsley@arm.com        return str(self)
125410201SAndrew.Bardsley@arm.com
125510201SAndrew.Bardsley@arm.com    @classmethod
125610201SAndrew.Bardsley@arm.com    def cxx_ini_predecls(cls, code):
12577673Snate@binkert.org        code('#include <time.h>')
125810201SAndrew.Bardsley@arm.com
125910201SAndrew.Bardsley@arm.com    @classmethod
12607673Snate@binkert.org    def cxx_ini_parse(cls, code, src, dest, ret):
126110201SAndrew.Bardsley@arm.com        code('char *_parse_ret = strptime((${src}).c_str(),')
12627673Snate@binkert.org        code('    "%a %b %d %H:%M:%S %Y", &(${dest}));')
12637673Snate@binkert.org        code('${ret} _parse_ret && *_parse_ret == \'\\0\';');
12647673Snate@binkert.org
12654762Snate@binkert.org# Enumerated types are a little more complex.  The user specifies the
12667673Snate@binkert.org# type as Enum(foo) where foo is either a list or dictionary of
12678902Sandreas.hansson@arm.com# alternatives (typically strings, but not necessarily so).  (In the
12687673Snate@binkert.org# long run, the integer value of the parameter will be the list index
126910201SAndrew.Bardsley@arm.com# or the corresponding dictionary value.  For now, since we only check
12704762Snate@binkert.org# that the alternative is valid and then spit it into a .ini file,
127110201SAndrew.Bardsley@arm.com# there's not much point in using the dictionary.)
127210201SAndrew.Bardsley@arm.com
127310201SAndrew.Bardsley@arm.com# What Enum() must do is generate a new type encapsulating the
127410201SAndrew.Bardsley@arm.com# provided list/dictionary so that specific values of the parameter
127510201SAndrew.Bardsley@arm.com# can be instances of that type.  We define two hidden internal
127610201SAndrew.Bardsley@arm.com# classes (_ListEnum and _DictEnum) to serve as base classes, then
127710201SAndrew.Bardsley@arm.com# derive the new type from the appropriate base class on the fly.
127810201SAndrew.Bardsley@arm.com
127910201SAndrew.Bardsley@arm.comallEnums = {}
12807673Snate@binkert.org# Metaclass for Enum types
12817673Snate@binkert.orgclass MetaEnum(MetaParamValue):
128210201SAndrew.Bardsley@arm.com    def __new__(mcls, name, bases, dict):
128310201SAndrew.Bardsley@arm.com        assert name not in allEnums
128410201SAndrew.Bardsley@arm.com
128510201SAndrew.Bardsley@arm.com        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
128610201SAndrew.Bardsley@arm.com        allEnums[name] = cls
128710201SAndrew.Bardsley@arm.com        return cls
128810201SAndrew.Bardsley@arm.com
128910201SAndrew.Bardsley@arm.com    def __init__(cls, name, bases, init_dict):
129010201SAndrew.Bardsley@arm.com        if 'map' in init_dict:
129110201SAndrew.Bardsley@arm.com            if not isinstance(cls.map, dict):
129210201SAndrew.Bardsley@arm.com                raise TypeError("Enum-derived class attribute 'map' " \
129310201SAndrew.Bardsley@arm.com                      "must be of type dict")
129410201SAndrew.Bardsley@arm.com            # build list of value strings from map
129510201SAndrew.Bardsley@arm.com            cls.vals = list(cls.map.keys())
129610201SAndrew.Bardsley@arm.com            cls.vals.sort()
12974762Snate@binkert.org        elif 'vals' in init_dict:
12987673Snate@binkert.org            if not isinstance(cls.vals, list):
129910201SAndrew.Bardsley@arm.com                raise TypeError("Enum-derived class attribute 'vals' " \
130010201SAndrew.Bardsley@arm.com                      "must be of type list")
130110201SAndrew.Bardsley@arm.com            # build string->value map from vals sequence
130210201SAndrew.Bardsley@arm.com            cls.map = {}
130310201SAndrew.Bardsley@arm.com            for idx,val in enumerate(cls.vals):
130410201SAndrew.Bardsley@arm.com                cls.map[val] = idx
13053101Sstever@eecs.umich.edu        else:
130611988Sandreas.sandberg@arm.com            raise TypeError("Enum-derived class must define "\
130711988Sandreas.sandberg@arm.com                  "attribute 'map' or 'vals'")
130811988Sandreas.sandberg@arm.com
130911988Sandreas.sandberg@arm.com        if cls.is_class:
131011988Sandreas.sandberg@arm.com            cls.cxx_type = '%s' % name
131111988Sandreas.sandberg@arm.com        else:
131211988Sandreas.sandberg@arm.com            cls.cxx_type = 'Enums::%s' % name
131311988Sandreas.sandberg@arm.com
131411988Sandreas.sandberg@arm.com        super(MetaEnum, cls).__init__(name, bases, init_dict)
131511988Sandreas.sandberg@arm.com
131611988Sandreas.sandberg@arm.com    # Generate C++ class declaration for this enum type.
131711988Sandreas.sandberg@arm.com    # Note that we wrap the enum in a class/struct to act as a namespace,
131811988Sandreas.sandberg@arm.com    # so that the enum strings can be brief w/o worrying about collisions.
131911988Sandreas.sandberg@arm.com    def cxx_decl(cls, code):
132011988Sandreas.sandberg@arm.com        wrapper_name = cls.wrapper_name
132111988Sandreas.sandberg@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
132211988Sandreas.sandberg@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
132311988Sandreas.sandberg@arm.com        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
132411988Sandreas.sandberg@arm.com
132511988Sandreas.sandberg@arm.com        code('''\
132611988Sandreas.sandberg@arm.com#ifndef $idem_macro
132711988Sandreas.sandberg@arm.com#define $idem_macro
132811988Sandreas.sandberg@arm.com
132911988Sandreas.sandberg@arm.com''')
133011988Sandreas.sandberg@arm.com        if cls.is_class:
133111988Sandreas.sandberg@arm.com            code('''\
133211988Sandreas.sandberg@arm.comenum class $name {
133311988Sandreas.sandberg@arm.com''')
133411988Sandreas.sandberg@arm.com        else:
133511988Sandreas.sandberg@arm.com            code('''\
133611988Sandreas.sandberg@arm.com$wrapper $wrapper_name {
133711988Sandreas.sandberg@arm.com    enum $name {
133811988Sandreas.sandberg@arm.com''')
133911988Sandreas.sandberg@arm.com            code.indent(1)
13408596Ssteve.reinhardt@amd.com        code.indent(1)
13413101Sstever@eecs.umich.edu        for val in cls.vals:
13423101Sstever@eecs.umich.edu            code('$val = ${{cls.map[val]}},')
13433101Sstever@eecs.umich.edu        code('Num_$name = ${{len(cls.vals)}}')
13443101Sstever@eecs.umich.edu        code.dedent(1)
134510267SGeoffrey.Blake@arm.com        code('};')
13463101Sstever@eecs.umich.edu
134710201SAndrew.Bardsley@arm.com        if cls.is_class:
134810201SAndrew.Bardsley@arm.com            code('''\
134910201SAndrew.Bardsley@arm.comextern const char *${name}Strings[static_cast<int>(${name}::Num_${name})];
135010201SAndrew.Bardsley@arm.com''')
135110201SAndrew.Bardsley@arm.com        elif cls.wrapper_is_struct:
135210201SAndrew.Bardsley@arm.com            code('static const char *${name}Strings[Num_${name}];')
135310201SAndrew.Bardsley@arm.com        else:
135410201SAndrew.Bardsley@arm.com            code('extern const char *${name}Strings[Num_${name}];')
135510201SAndrew.Bardsley@arm.com
13563101Sstever@eecs.umich.edu        if not cls.is_class:
13573101Sstever@eecs.umich.edu            code.dedent(1)
13583101Sstever@eecs.umich.edu            code('};')
13593101Sstever@eecs.umich.edu
13603101Sstever@eecs.umich.edu        code()
13613101Sstever@eecs.umich.edu        code('#endif // $idem_macro')
136210267SGeoffrey.Blake@arm.com
136310267SGeoffrey.Blake@arm.com    def cxx_def(cls, code):
136410267SGeoffrey.Blake@arm.com        wrapper_name = cls.wrapper_name
136510267SGeoffrey.Blake@arm.com        file_name = cls.__name__
13667675Snate@binkert.org        name = cls.__name__ if cls.enum_name is None else cls.enum_name
13677675Snate@binkert.org
13687675Snate@binkert.org        code('#include "enums/$file_name.hh"')
13697675Snate@binkert.org        if cls.wrapper_is_struct:
13707675Snate@binkert.org            code('const char *${wrapper_name}::${name}Strings'
137110458Sandreas.hansson@arm.com                '[Num_${name}] =')
137210458Sandreas.hansson@arm.com        else:
137310458Sandreas.hansson@arm.com            if cls.is_class:
137410458Sandreas.hansson@arm.com                code('''\
137510458Sandreas.hansson@arm.comconst char *${name}Strings[static_cast<int>(${name}::Num_${name})] =
137610458Sandreas.hansson@arm.com''')
137710458Sandreas.hansson@arm.com            else:
137810458Sandreas.hansson@arm.com                code('namespace Enums {')
137910458Sandreas.hansson@arm.com                code.indent(1)
138010458Sandreas.hansson@arm.com                code('const char *${name}Strings[Num_${name}] =')
138110458Sandreas.hansson@arm.com
138210458Sandreas.hansson@arm.com        code('{')
13834762Snate@binkert.org        code.indent(1)
138411988Sandreas.sandberg@arm.com        for val in cls.vals:
138511988Sandreas.sandberg@arm.com            code('"$val",')
138611988Sandreas.sandberg@arm.com        code.dedent(1)
13874762Snate@binkert.org        code('};')
13883101Sstever@eecs.umich.edu
13893101Sstever@eecs.umich.edu        if not cls.wrapper_is_struct and not cls.is_class:
13903101Sstever@eecs.umich.edu            code.dedent(1)
13913101Sstever@eecs.umich.edu            code('} // namespace $wrapper_name')
13923101Sstever@eecs.umich.edu
13933101Sstever@eecs.umich.edu
13944167Sbinkertn@umich.edu    def pybind_def(cls, code):
13953101Sstever@eecs.umich.edu        name = cls.__name__
139610267SGeoffrey.Blake@arm.com        enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name
139710267SGeoffrey.Blake@arm.com        wrapper_name = enum_name if cls.is_class else cls.wrapper_name
13987673Snate@binkert.org
13997673Snate@binkert.org        code('''#include "pybind11/pybind11.h"
14007673Snate@binkert.org#include "pybind11/stl.h"
14017673Snate@binkert.org
14027673Snate@binkert.org#include <sim/init.hh>
140310267SGeoffrey.Blake@arm.com
140410267SGeoffrey.Blake@arm.comnamespace py = pybind11;
140510267SGeoffrey.Blake@arm.com
140610267SGeoffrey.Blake@arm.comstatic void
14074762Snate@binkert.orgmodule_init(py::module &m_internal)
14084762Snate@binkert.org{
14094762Snate@binkert.org    py::module m = m_internal.def_submodule("enum_${name}");
141010458Sandreas.hansson@arm.com
141110458Sandreas.hansson@arm.com''')
141210458Sandreas.hansson@arm.com        if cls.is_class:
141310458Sandreas.hansson@arm.com            code('py::enum_<${enum_name}>(m, "enum_${name}")')
141410458Sandreas.hansson@arm.com        else:
141510458Sandreas.hansson@arm.com            code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")')
141610458Sandreas.hansson@arm.com
141710458Sandreas.hansson@arm.com        code.indent()
141810458Sandreas.hansson@arm.com        code.indent()
141910458Sandreas.hansson@arm.com        for val in cls.vals:
14204167Sbinkertn@umich.edu            code('.value("${val}", ${wrapper_name}::${val})')
142110267SGeoffrey.Blake@arm.com        code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})')
142210267SGeoffrey.Blake@arm.com        code('.export_values()')
14233101Sstever@eecs.umich.edu        code(';')
14244167Sbinkertn@umich.edu        code.dedent()
14254167Sbinkertn@umich.edu
14264167Sbinkertn@umich.edu        code('}')
14274167Sbinkertn@umich.edu        code.dedent()
14284167Sbinkertn@umich.edu        code()
14294167Sbinkertn@umich.edu        code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);')
14304167Sbinkertn@umich.edu
14314167Sbinkertn@umich.edu
14324167Sbinkertn@umich.edu# Base class for enum types.
14334167Sbinkertn@umich.educlass Enum(ParamValue):
14344167Sbinkertn@umich.edu    __metaclass__ = MetaEnum
14354167Sbinkertn@umich.edu    vals = []
14363101Sstever@eecs.umich.edu    cmd_line_settable = True
143710267SGeoffrey.Blake@arm.com
143810267SGeoffrey.Blake@arm.com    # The name of the wrapping namespace or struct
143910267SGeoffrey.Blake@arm.com    wrapper_name = 'Enums'
144010267SGeoffrey.Blake@arm.com
14413101Sstever@eecs.umich.edu    # If true, the enum is wrapped in a struct rather than a namespace
14423101Sstever@eecs.umich.edu    wrapper_is_struct = False
14433101Sstever@eecs.umich.edu
14443101Sstever@eecs.umich.edu    is_class = False
14453101Sstever@eecs.umich.edu
14463101Sstever@eecs.umich.edu    # If not None, use this as the enum name rather than this class name
14473101Sstever@eecs.umich.edu    enum_name = None
14484762Snate@binkert.org
14494762Snate@binkert.org    def __init__(self, value):
14504762Snate@binkert.org        if value not in self.map:
14514762Snate@binkert.org            raise TypeError("Enum param got bad value '%s' (not in %s)" \
14524762Snate@binkert.org                  % (value, self.vals))
14534762Snate@binkert.org        self.value = value
14544762Snate@binkert.org
145510380SAndrew.Bardsley@arm.com    def __call__(self, value):
145610380SAndrew.Bardsley@arm.com        self.__init__(value)
145710380SAndrew.Bardsley@arm.com        return value
14583101Sstever@eecs.umich.edu
14593101Sstever@eecs.umich.edu    @classmethod
14604762Snate@binkert.org    def cxx_predecls(cls, code):
14613101Sstever@eecs.umich.edu        code('#include "enums/$0.hh"', cls.__name__)
14624167Sbinkertn@umich.edu
146310267SGeoffrey.Blake@arm.com    @classmethod
146410267SGeoffrey.Blake@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
14653101Sstever@eecs.umich.edu        code('if (false) {')
14664167Sbinkertn@umich.edu        for elem_name in cls.map.keys():
14674167Sbinkertn@umich.edu            code('} else if (%s == "%s") {' % (src, elem_name))
14684167Sbinkertn@umich.edu            code.indent()
14694167Sbinkertn@umich.edu            code('%s = Enums::%s;' % (dest, elem_name))
14704167Sbinkertn@umich.edu            code('%s true;' % ret)
14714167Sbinkertn@umich.edu            code.dedent()
14724167Sbinkertn@umich.edu        code('} else {')
14734167Sbinkertn@umich.edu        code('    %s false;' % ret)
14744167Sbinkertn@umich.edu        code('}')
14754167Sbinkertn@umich.edu
14764167Sbinkertn@umich.edu    def getValue(self):
14774167Sbinkertn@umich.edu        import m5.internal.params
14783101Sstever@eecs.umich.edu        e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__)
147910267SGeoffrey.Blake@arm.com        return e(self.map[self.value])
148010267SGeoffrey.Blake@arm.com
148110267SGeoffrey.Blake@arm.com    def __str__(self):
148210267SGeoffrey.Blake@arm.com        return self.value
14833101Sstever@eecs.umich.edu
14843101Sstever@eecs.umich.edu# This param will generate a scoped c++ enum and its python bindings.
14853101Sstever@eecs.umich.educlass ScopedEnum(Enum):
14863101Sstever@eecs.umich.edu    __metaclass__ = MetaEnum
14873101Sstever@eecs.umich.edu    vals = []
14883101Sstever@eecs.umich.edu    cmd_line_settable = True
14893101Sstever@eecs.umich.edu
14904167Sbinkertn@umich.edu    # The name of the wrapping namespace or struct
14914762Snate@binkert.org    wrapper_name = None
14924762Snate@binkert.org
14934762Snate@binkert.org    # If true, the enum is wrapped in a struct rather than a namespace
14944762Snate@binkert.org    wrapper_is_struct = False
14954762Snate@binkert.org
14964762Snate@binkert.org    # If true, the generated enum is a scoped enum
14974762Snate@binkert.org    is_class = True
149810380SAndrew.Bardsley@arm.com
149910380SAndrew.Bardsley@arm.com    # If not None, use this as the enum name rather than this class name
150010380SAndrew.Bardsley@arm.com    enum_name = None
15013101Sstever@eecs.umich.edu
15024762Snate@binkert.org# how big does a rounding error need to be before we warn about it?
15033101Sstever@eecs.umich.edufrequency_tolerance = 0.001  # 0.1%
150410019Sandreas.hansson@arm.com
150510019Sandreas.hansson@arm.comclass TickParamValue(NumericParamValue):
150610019Sandreas.hansson@arm.com    cxx_type = 'Tick'
15073101Sstever@eecs.umich.edu    ex_str = "1MHz"
15084167Sbinkertn@umich.edu    cmd_line_settable = True
15094167Sbinkertn@umich.edu
15104167Sbinkertn@umich.edu    @classmethod
15114167Sbinkertn@umich.edu    def cxx_predecls(cls, code):
15124167Sbinkertn@umich.edu        code('#include "base/types.hh"')
15134167Sbinkertn@umich.edu
15144167Sbinkertn@umich.edu    def __call__(self, value):
15154167Sbinkertn@umich.edu        self.__init__(value)
15164167Sbinkertn@umich.edu        return value
15174167Sbinkertn@umich.edu
15184167Sbinkertn@umich.edu    def getValue(self):
15194167Sbinkertn@umich.edu        return long(self.value)
15203101Sstever@eecs.umich.edu
152110267SGeoffrey.Blake@arm.com    @classmethod
152210267SGeoffrey.Blake@arm.com    def cxx_ini_predecls(cls, code):
152310267SGeoffrey.Blake@arm.com        code('#include <sstream>')
152410267SGeoffrey.Blake@arm.com
152510267SGeoffrey.Blake@arm.com    # Ticks are expressed in seconds in JSON files and in plain
152610267SGeoffrey.Blake@arm.com    # Ticks in .ini files.  Switch based on a config flag
152710267SGeoffrey.Blake@arm.com    @classmethod
15283101Sstever@eecs.umich.edu    def cxx_ini_parse(self, code, src, dest, ret):
15293101Sstever@eecs.umich.edu        code('${ret} to_number(${src}, ${dest});')
15303101Sstever@eecs.umich.edu
15313101Sstever@eecs.umich.educlass Latency(TickParamValue):
15323101Sstever@eecs.umich.edu    ex_str = "100ns"
15333101Sstever@eecs.umich.edu
15343101Sstever@eecs.umich.edu    def __init__(self, value):
15354762Snate@binkert.org        if isinstance(value, (Latency, Clock)):
15364762Snate@binkert.org            self.ticks = value.ticks
15374762Snate@binkert.org            self.value = value.value
153810380SAndrew.Bardsley@arm.com        elif isinstance(value, Frequency):
153910380SAndrew.Bardsley@arm.com            self.ticks = value.ticks
154010380SAndrew.Bardsley@arm.com            self.value = 1.0 / value.value
15413101Sstever@eecs.umich.edu        elif value.endswith('t'):
15423101Sstever@eecs.umich.edu            self.ticks = True
15433101Sstever@eecs.umich.edu            self.value = int(value[:-1])
15449827Sakash.bagdia@arm.com        else:
15459827Sakash.bagdia@arm.com            self.ticks = False
154610267SGeoffrey.Blake@arm.com            self.value = convert.toLatency(value)
154711498Sakash.bagdia@ARM.com
154810267SGeoffrey.Blake@arm.com    def __call__(self, value):
15499827Sakash.bagdia@arm.com        self.__init__(value)
15509827Sakash.bagdia@arm.com        return value
15519827Sakash.bagdia@arm.com
15529827Sakash.bagdia@arm.com    def __getattr__(self, attr):
15539827Sakash.bagdia@arm.com        if attr in ('latency', 'period'):
155410267SGeoffrey.Blake@arm.com            return self
155510267SGeoffrey.Blake@arm.com        if attr == 'frequency':
155610267SGeoffrey.Blake@arm.com            return Frequency(self)
155710267SGeoffrey.Blake@arm.com        raise AttributeError("Latency object has no attribute '%s'" % attr)
155810267SGeoffrey.Blake@arm.com
15599827Sakash.bagdia@arm.com    def getValue(self):
156010267SGeoffrey.Blake@arm.com        if self.ticks or self.value == 0:
15619827Sakash.bagdia@arm.com            value = self.value
15629827Sakash.bagdia@arm.com        else:
15639827Sakash.bagdia@arm.com            value = ticks.fromSeconds(self.value)
15649827Sakash.bagdia@arm.com        return long(value)
15659827Sakash.bagdia@arm.com
15669827Sakash.bagdia@arm.com    def config_value(self):
15679827Sakash.bagdia@arm.com        return self.getValue()
15689827Sakash.bagdia@arm.com
156910458Sandreas.hansson@arm.com    # convert latency to ticks
157010458Sandreas.hansson@arm.com    def ini_str(self):
157110458Sandreas.hansson@arm.com        return '%d' % self.getValue()
157210458Sandreas.hansson@arm.com
157310458Sandreas.hansson@arm.comclass Frequency(TickParamValue):
157410458Sandreas.hansson@arm.com    ex_str = "1GHz"
157510458Sandreas.hansson@arm.com
157610458Sandreas.hansson@arm.com    def __init__(self, value):
157710427Sandreas.hansson@arm.com        if isinstance(value, (Latency, Clock)):
157810427Sandreas.hansson@arm.com            if value.value == 0:
157910427Sandreas.hansson@arm.com                self.value = 0
158010427Sandreas.hansson@arm.com            else:
158110427Sandreas.hansson@arm.com                self.value = 1.0 / value.value
158210427Sandreas.hansson@arm.com            self.ticks = value.ticks
158310427Sandreas.hansson@arm.com        elif isinstance(value, Frequency):
158410427Sandreas.hansson@arm.com            self.value = value.value
158510427Sandreas.hansson@arm.com            self.ticks = value.ticks
158610427Sandreas.hansson@arm.com        else:
158710427Sandreas.hansson@arm.com            self.ticks = False
158810427Sandreas.hansson@arm.com            self.value = convert.toFrequency(value)
158910427Sandreas.hansson@arm.com
159010427Sandreas.hansson@arm.com    def __call__(self, value):
159110427Sandreas.hansson@arm.com        self.__init__(value)
159210427Sandreas.hansson@arm.com        return value
159310427Sandreas.hansson@arm.com
159410427Sandreas.hansson@arm.com    def __getattr__(self, attr):
159510427Sandreas.hansson@arm.com        if attr == 'frequency':
159610427Sandreas.hansson@arm.com            return self
159710427Sandreas.hansson@arm.com        if attr in ('latency', 'period'):
159810427Sandreas.hansson@arm.com            return Latency(self)
159910427Sandreas.hansson@arm.com        raise AttributeError("Frequency object has no attribute '%s'" % attr)
160010427Sandreas.hansson@arm.com
160110427Sandreas.hansson@arm.com    # convert latency to ticks
160210458Sandreas.hansson@arm.com    def getValue(self):
160310458Sandreas.hansson@arm.com        if self.ticks or self.value == 0:
160410458Sandreas.hansson@arm.com            value = self.value
160510458Sandreas.hansson@arm.com        else:
160610458Sandreas.hansson@arm.com            value = ticks.fromSeconds(1.0 / self.value)
160710458Sandreas.hansson@arm.com        return long(value)
160810458Sandreas.hansson@arm.com
160910458Sandreas.hansson@arm.com    def config_value(self):
16103101Sstever@eecs.umich.edu        return self.getValue()
16113101Sstever@eecs.umich.edu
161210267SGeoffrey.Blake@arm.com    def ini_str(self):
161310267SGeoffrey.Blake@arm.com        return '%d' % self.getValue()
161410267SGeoffrey.Blake@arm.com
16153101Sstever@eecs.umich.edu# A generic Frequency and/or Latency value. Value is stored as a
16164167Sbinkertn@umich.edu# latency, just like Latency and Frequency.
16174167Sbinkertn@umich.educlass Clock(TickParamValue):
16183101Sstever@eecs.umich.edu    def __init__(self, value):
16193101Sstever@eecs.umich.edu        if isinstance(value, (Latency, Clock)):
16203101Sstever@eecs.umich.edu            self.ticks = value.ticks
16213101Sstever@eecs.umich.edu            self.value = value.value
16223101Sstever@eecs.umich.edu        elif isinstance(value, Frequency):
162310267SGeoffrey.Blake@arm.com            self.ticks = value.ticks
162410267SGeoffrey.Blake@arm.com            self.value = 1.0 / value.value
162510267SGeoffrey.Blake@arm.com        elif value.endswith('t'):
162610267SGeoffrey.Blake@arm.com            self.ticks = True
162710267SGeoffrey.Blake@arm.com            self.value = int(value[:-1])
16284762Snate@binkert.org        else:
16294167Sbinkertn@umich.edu            self.ticks = False
16304167Sbinkertn@umich.edu            self.value = convert.anyToLatency(value)
16314167Sbinkertn@umich.edu
16324762Snate@binkert.org    def __call__(self, value):
16334762Snate@binkert.org        self.__init__(value)
16344762Snate@binkert.org        return value
16354762Snate@binkert.org
16364762Snate@binkert.org    def __str__(self):
16373101Sstever@eecs.umich.edu        return "%s" % Latency(self)
163810380SAndrew.Bardsley@arm.com
163910380SAndrew.Bardsley@arm.com    def __getattr__(self, attr):
164010380SAndrew.Bardsley@arm.com        if attr == 'frequency':
164110458Sandreas.hansson@arm.com            return Frequency(self)
164210458Sandreas.hansson@arm.com        if attr in ('latency', 'period'):
164310458Sandreas.hansson@arm.com            return Latency(self)
164410458Sandreas.hansson@arm.com        raise AttributeError("Frequency object has no attribute '%s'" % attr)
164510458Sandreas.hansson@arm.com
164610458Sandreas.hansson@arm.com    def getValue(self):
164710458Sandreas.hansson@arm.com        return self.period.getValue()
164810458Sandreas.hansson@arm.com
16493101Sstever@eecs.umich.edu    def config_value(self):
16503101Sstever@eecs.umich.edu        return self.period.config_value()
165110267SGeoffrey.Blake@arm.com
165210267SGeoffrey.Blake@arm.com    def ini_str(self):
165310267SGeoffrey.Blake@arm.com        return self.period.ini_str()
16545469Snate@binkert.org
16557743Sgblack@eecs.umich.educlass Voltage(Float):
16563102Sstever@eecs.umich.edu    ex_str = "1V"
16573101Sstever@eecs.umich.edu
16583101Sstever@eecs.umich.edu    def __new__(cls, value):
165910267SGeoffrey.Blake@arm.com        value = convert.toVoltage(value)
166010267SGeoffrey.Blake@arm.com        return super(cls, Voltage).__new__(cls, value)
166110267SGeoffrey.Blake@arm.com
166210267SGeoffrey.Blake@arm.com    def __init__(self, value):
16633101Sstever@eecs.umich.edu        value = convert.toVoltage(value)
16644762Snate@binkert.org        super(Voltage, self).__init__(value)
16654167Sbinkertn@umich.edu
16665468Snate@binkert.orgclass Current(Float):
16675468Snate@binkert.org    ex_str = "1mA"
16685468Snate@binkert.org
16694167Sbinkertn@umich.edu    def __new__(cls, value):
16704762Snate@binkert.org        value = convert.toCurrent(value)
16714762Snate@binkert.org        return super(cls, Current).__new__(cls, value)
16724762Snate@binkert.org
16734762Snate@binkert.org    def __init__(self, value):
16744762Snate@binkert.org        value = convert.toCurrent(value)
16753101Sstever@eecs.umich.edu        super(Current, self).__init__(value)
167610380SAndrew.Bardsley@arm.com
167710380SAndrew.Bardsley@arm.comclass Energy(Float):
167810380SAndrew.Bardsley@arm.com    ex_str = "1pJ"
167910458Sandreas.hansson@arm.com
168010458Sandreas.hansson@arm.com    def __new__(cls, value):
168110458Sandreas.hansson@arm.com        value = convert.toEnergy(value)
168210458Sandreas.hansson@arm.com        return super(cls, Energy).__new__(cls, value)
168310458Sandreas.hansson@arm.com
168410458Sandreas.hansson@arm.com    def __init__(self, value):
168510458Sandreas.hansson@arm.com        value = convert.toEnergy(value)
168610458Sandreas.hansson@arm.com        super(Energy, self).__init__(value)
16873101Sstever@eecs.umich.edu
16883101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
16893101Sstever@eecs.umich.edu    cxx_type = 'float'
16903101Sstever@eecs.umich.edu    ex_str = "1Gbps"
16913102Sstever@eecs.umich.edu    cmd_line_settable = True
16923102Sstever@eecs.umich.edu
16933102Sstever@eecs.umich.edu    def __new__(cls, value):
16943102Sstever@eecs.umich.edu        # convert to bits per second
16953102Sstever@eecs.umich.edu        val = convert.toNetworkBandwidth(value)
16963102Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
16973102Sstever@eecs.umich.edu
16983102Sstever@eecs.umich.edu    def __str__(self):
16993102Sstever@eecs.umich.edu        return str(self.val)
17003102Sstever@eecs.umich.edu
17013102Sstever@eecs.umich.edu    def __call__(self, value):
17023102Sstever@eecs.umich.edu        val = convert.toNetworkBandwidth(value)
17033102Sstever@eecs.umich.edu        self.__init__(val)
17043102Sstever@eecs.umich.edu        return value
17053102Sstever@eecs.umich.edu
17063102Sstever@eecs.umich.edu    def getValue(self):
17073102Sstever@eecs.umich.edu        # convert to seconds per byte
17083102Sstever@eecs.umich.edu        value = 8.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
17163102Sstever@eecs.umich.edu    def config_value(self):
17173102Sstever@eecs.umich.edu        return '%f' % self.getValue()
17183102Sstever@eecs.umich.edu
171910380SAndrew.Bardsley@arm.com    @classmethod
172010380SAndrew.Bardsley@arm.com    def cxx_ini_predecls(cls, code):
172110380SAndrew.Bardsley@arm.com        code('#include <sstream>')
17224762Snate@binkert.org
17234762Snate@binkert.org    @classmethod
17244762Snate@binkert.org    def cxx_ini_parse(self, code, src, dest, ret):
17253102Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
17263102Sstever@eecs.umich.edu
17273102Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
17283102Sstever@eecs.umich.edu    cxx_type = 'float'
17293102Sstever@eecs.umich.edu    ex_str = "1GB/s"
17303102Sstever@eecs.umich.edu    cmd_line_settable = True
17313101Sstever@eecs.umich.edu
17323101Sstever@eecs.umich.edu    def __new__(cls, value):
17333101Sstever@eecs.umich.edu        # convert to bytes per second
17343101Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
17353101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
17363101Sstever@eecs.umich.edu
17373101Sstever@eecs.umich.edu    def __call__(self, value):
17383101Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
17393101Sstever@eecs.umich.edu        self.__init__(val)
17403101Sstever@eecs.umich.edu        return value
17413101Sstever@eecs.umich.edu
17423101Sstever@eecs.umich.edu    def getValue(self):
17433101Sstever@eecs.umich.edu        # convert to seconds per byte
17443101Sstever@eecs.umich.edu        value = float(self)
17453101Sstever@eecs.umich.edu        if value:
17463101Sstever@eecs.umich.edu            value = 1.0 / float(self)
17473101Sstever@eecs.umich.edu        # convert to ticks per byte
17488839Sandreas.hansson@arm.com        value = ticks.fromSeconds(value)
17493105Sstever@eecs.umich.edu        return float(value)
17503101Sstever@eecs.umich.edu
17513101Sstever@eecs.umich.edu    def ini_str(self):
17528839Sandreas.hansson@arm.com        return '%f' % self.getValue()
17533101Sstever@eecs.umich.edu
17543101Sstever@eecs.umich.edu    def config_value(self):
17553105Sstever@eecs.umich.edu        return '%f' % self.getValue()
17563101Sstever@eecs.umich.edu
17573103Sstever@eecs.umich.edu    @classmethod
17583105Sstever@eecs.umich.edu    def cxx_ini_predecls(cls, code):
17593103Sstever@eecs.umich.edu        code('#include <sstream>')
17608840Sandreas.hansson@arm.com
17618840Sandreas.hansson@arm.com    @classmethod
17628840Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
17638840Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
17648840Sandreas.hansson@arm.com
17653105Sstever@eecs.umich.edu#
17663105Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
17673105Sstever@eecs.umich.edu#
17683105Sstever@eecs.umich.edu
17699017Sandreas.hansson@arm.com# Special class for NULL pointers.  Note the special check in
17709017Sandreas.hansson@arm.com# make_param_value() above that lets these be assigned where a
17719017Sandreas.hansson@arm.com# SimObject is required.
17729017Sandreas.hansson@arm.com# only one copy of a particular node
17733105Sstever@eecs.umich.educlass NullSimObject(object):
17743105Sstever@eecs.umich.edu    __metaclass__ = Singleton
17753105Sstever@eecs.umich.edu    _name = 'Null'
17763105Sstever@eecs.umich.edu
17773105Sstever@eecs.umich.edu    def __call__(cls):
17783105Sstever@eecs.umich.edu        return cls
17793105Sstever@eecs.umich.edu
17803105Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
17813105Sstever@eecs.umich.edu        pass
17823109Sstever@eecs.umich.edu
17833105Sstever@eecs.umich.edu    def ini_str(self):
17843105Sstever@eecs.umich.edu        return 'Null'
17853105Sstever@eecs.umich.edu
17863105Sstever@eecs.umich.edu    def unproxy(self, base):
17873105Sstever@eecs.umich.edu        return self
17883105Sstever@eecs.umich.edu
17899014Sandreas.hansson@arm.com    def set_path(self, parent, name):
17909014Sandreas.hansson@arm.com        pass
17913101Sstever@eecs.umich.edu
17923109Sstever@eecs.umich.edu    def set_parent(self, parent, name):
17933109Sstever@eecs.umich.edu        pass
17943109Sstever@eecs.umich.edu
17953109Sstever@eecs.umich.edu    def clear_parent(self, old_parent):
17963109Sstever@eecs.umich.edu        pass
17973109Sstever@eecs.umich.edu
17983109Sstever@eecs.umich.edu    def descendants(self):
17993109Sstever@eecs.umich.edu        return
18003109Sstever@eecs.umich.edu        yield None
18013101Sstever@eecs.umich.edu
180210355SGeoffrey.Blake@arm.com    def get_config_as_dict(self):
180310355SGeoffrey.Blake@arm.com        return {}
180410355SGeoffrey.Blake@arm.com
180510355SGeoffrey.Blake@arm.com    def __str__(self):
180610355SGeoffrey.Blake@arm.com        return self._name
180710355SGeoffrey.Blake@arm.com
180810355SGeoffrey.Blake@arm.com    def config_value(self):
180910355SGeoffrey.Blake@arm.com        return None
181010355SGeoffrey.Blake@arm.com
181110355SGeoffrey.Blake@arm.com    def getValue(self):
181210355SGeoffrey.Blake@arm.com        return None
181310355SGeoffrey.Blake@arm.com
181410355SGeoffrey.Blake@arm.com# The only instance you'll ever need...
181510355SGeoffrey.Blake@arm.comNULL = NullSimObject()
181610355SGeoffrey.Blake@arm.com
181710355SGeoffrey.Blake@arm.comdef isNullPointer(value):
181810355SGeoffrey.Blake@arm.com    return isinstance(value, NullSimObject)
181910355SGeoffrey.Blake@arm.com
182010355SGeoffrey.Blake@arm.com# Some memory range specifications use this as a default upper bound.
182110355SGeoffrey.Blake@arm.comMaxAddr = Addr.max
182210355SGeoffrey.Blake@arm.comMaxTick = Tick.max
182310355SGeoffrey.Blake@arm.comAllMemory = AddrRange(0, MaxAddr)
182410355SGeoffrey.Blake@arm.com
182510355SGeoffrey.Blake@arm.com
182610355SGeoffrey.Blake@arm.com#####################################################################
182710355SGeoffrey.Blake@arm.com#
182810355SGeoffrey.Blake@arm.com# Port objects
182910355SGeoffrey.Blake@arm.com#
183010355SGeoffrey.Blake@arm.com# Ports are used to interconnect objects in the memory system.
183110355SGeoffrey.Blake@arm.com#
18323105Sstever@eecs.umich.edu#####################################################################
18333105Sstever@eecs.umich.edu
18343105Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
18353101Sstever@eecs.umich.edu# particular SimObject.
18363105Sstever@eecs.umich.educlass PortRef(object):
18373105Sstever@eecs.umich.edu    def __init__(self, simobj, name, role):
18383101Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
18393105Sstever@eecs.umich.edu        self.simobj = simobj
18403179Sstever@eecs.umich.edu        self.name = name
18413105Sstever@eecs.umich.edu        self.role = role
18423105Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
18433101Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
18443101Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
18453105Sstever@eecs.umich.edu
18463105Sstever@eecs.umich.edu    def __str__(self):
18473105Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
18483105Sstever@eecs.umich.edu
18493105Sstever@eecs.umich.edu    def __len__(self):
18503105Sstever@eecs.umich.edu        # Return the number of connected ports, i.e. 0 is we have no
18513105Sstever@eecs.umich.edu        # peer and 1 if we do.
18523105Sstever@eecs.umich.edu        return int(self.peer != None)
18533105Sstever@eecs.umich.edu
18543105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
18553105Sstever@eecs.umich.edu    def ini_str(self):
18563101Sstever@eecs.umich.edu        return str(self.peer)
18573101Sstever@eecs.umich.edu
185811802Sandreas.sandberg@arm.com    # for config.json
18594762Snate@binkert.org    def get_config_as_dict(self):
18608839Sandreas.hansson@arm.com        return {'role' : self.role, 'peer' : str(self.peer)}
18618839Sandreas.hansson@arm.com
18628839Sandreas.hansson@arm.com    def __getattr__(self, attr):
18638839Sandreas.hansson@arm.com        if attr == 'peerObj':
18643101Sstever@eecs.umich.edu            # shorthand for proxies
18653101Sstever@eecs.umich.edu            return self.peer.simobj
18663101Sstever@eecs.umich.edu        raise AttributeError("'%s' object has no attribute '%s'" % \
18675578SSteve.Reinhardt@amd.com              (self.__class__.__name__, attr))
18685578SSteve.Reinhardt@amd.com
18698839Sandreas.hansson@arm.com    # Full connection is symmetric (both ways).  Called via
18708839Sandreas.hansson@arm.com    # SimObject.__setattr__ as a result of a port assignment, e.g.,
18718839Sandreas.hansson@arm.com    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
18728839Sandreas.hansson@arm.com    # e.g., "obj1.portA[3] = obj2.portB".
18738839Sandreas.hansson@arm.com    def connect(self, other):
18748839Sandreas.hansson@arm.com        if isinstance(other, VectorPortRef):
18758839Sandreas.hansson@arm.com            # reference to plain VectorPort is implicit append
18767526Ssteve.reinhardt@amd.com            other = other._get_next()
18778839Sandreas.hansson@arm.com        if self.peer and not proxy.isproxy(self.peer):
18787526Ssteve.reinhardt@amd.com            fatal("Port %s is already connected to %s, cannot connect %s\n",
18797526Ssteve.reinhardt@amd.com                  self, self.peer, other);
18807526Ssteve.reinhardt@amd.com        self.peer = other
18817526Ssteve.reinhardt@amd.com        if proxy.isproxy(other):
18827526Ssteve.reinhardt@amd.com            other.set_param_desc(PortParamDesc())
18837526Ssteve.reinhardt@amd.com        elif isinstance(other, PortRef):
18847526Ssteve.reinhardt@amd.com            if other.peer is not self:
18853101Sstever@eecs.umich.edu                other.connect(self)
18863101Sstever@eecs.umich.edu        else:
18873101Sstever@eecs.umich.edu            raise TypeError("assigning non-port reference '%s' to port '%s'" \
18883105Sstever@eecs.umich.edu                  % (other, self))
18893105Sstever@eecs.umich.edu
18903105Sstever@eecs.umich.edu    # Allow a master/slave port pair to be spliced between
18918839Sandreas.hansson@arm.com    # a port and its connected peer. Useful operation for connecting
18928839Sandreas.hansson@arm.com    # instrumentation structures into a system when it is necessary
18933105Sstever@eecs.umich.edu    # to connect the instrumentation after the full system has been
18943105Sstever@eecs.umich.edu    # constructed.
18953105Sstever@eecs.umich.edu    def splice(self, new_master_peer, new_slave_peer):
18963105Sstever@eecs.umich.edu        if not self.peer or proxy.isproxy(self.peer):
18973105Sstever@eecs.umich.edu            fatal("Port %s not connected, cannot splice in new peers\n", self)
18983105Sstever@eecs.umich.edu
18993105Sstever@eecs.umich.edu        if not isinstance(new_master_peer, PortRef) or \
19003105Sstever@eecs.umich.edu           not isinstance(new_slave_peer, PortRef):
19018839Sandreas.hansson@arm.com            raise TypeError(
19023105Sstever@eecs.umich.edu                  "Splicing non-port references '%s','%s' to port '%s'" % \
19033105Sstever@eecs.umich.edu                  (new_master_peer, new_slave_peer, self))
19043105Sstever@eecs.umich.edu
19058839Sandreas.hansson@arm.com        old_peer = self.peer
19063105Sstever@eecs.umich.edu        if self.role == 'SLAVE':
19073105Sstever@eecs.umich.edu            self.peer = new_master_peer
19083109Sstever@eecs.umich.edu            old_peer.peer = new_slave_peer
19093109Sstever@eecs.umich.edu            new_master_peer.connect(self)
19103109Sstever@eecs.umich.edu            new_slave_peer.connect(old_peer)
19118840Sandreas.hansson@arm.com        elif self.role == 'MASTER':
19128840Sandreas.hansson@arm.com            self.peer = new_slave_peer
19138840Sandreas.hansson@arm.com            old_peer.peer = new_master_peer
19148840Sandreas.hansson@arm.com            new_slave_peer.connect(self)
19158840Sandreas.hansson@arm.com            new_master_peer.connect(old_peer)
19163105Sstever@eecs.umich.edu        else:
19173105Sstever@eecs.umich.edu            panic("Port %s has unknown role, "+\
19183105Sstever@eecs.umich.edu                  "cannot splice in new peers\n", self)
19193105Sstever@eecs.umich.edu
19209017Sandreas.hansson@arm.com    def clone(self, simobj, memo):
19219017Sandreas.hansson@arm.com        if self in memo:
19229017Sandreas.hansson@arm.com            return memo[self]
19239017Sandreas.hansson@arm.com        newRef = copy.copy(self)
19249017Sandreas.hansson@arm.com        memo[self] = newRef
19253105Sstever@eecs.umich.edu        newRef.simobj = simobj
19263105Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
19273105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
19283105Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
19293105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
19308839Sandreas.hansson@arm.com            assert(not isinstance(newRef.peer, VectorPortRef))
19313105Sstever@eecs.umich.edu        return newRef
19323105Sstever@eecs.umich.edu
19333105Sstever@eecs.umich.edu    def unproxy(self, simobj):
19343105Sstever@eecs.umich.edu        assert(simobj is self.simobj)
19353105Sstever@eecs.umich.edu        if proxy.isproxy(self.peer):
19363105Sstever@eecs.umich.edu            try:
19373105Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
19383105Sstever@eecs.umich.edu            except:
19393105Sstever@eecs.umich.edu                print("Error in unproxying port '%s' of %s" %
19403105Sstever@eecs.umich.edu                      (self.name, self.simobj.path()))
19413105Sstever@eecs.umich.edu                raise
19423105Sstever@eecs.umich.edu            self.connect(realPeer)
19433105Sstever@eecs.umich.edu
19443109Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
19453109Sstever@eecs.umich.edu    def ccConnect(self):
19463109Sstever@eecs.umich.edu        if self.ccConnected: # already done this
19473109Sstever@eecs.umich.edu            return
19483109Sstever@eecs.umich.edu
19493109Sstever@eecs.umich.edu        peer = self.peer
19503109Sstever@eecs.umich.edu        if not self.peer: # nothing to connect to
19513109Sstever@eecs.umich.edu            return
19523109Sstever@eecs.umich.edu
19533109Sstever@eecs.umich.edu        port = self.simobj.getPort(self.name, self.index)
19543109Sstever@eecs.umich.edu        peer_port = peer.simobj.getPort(peer.name, peer.index)
19553109Sstever@eecs.umich.edu        port.bind(peer_port)
19563109Sstever@eecs.umich.edu
19573109Sstever@eecs.umich.edu        self.ccConnected = True
19583109Sstever@eecs.umich.edu
19593109Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
19603109Sstever@eecs.umich.edu# PortRef, but has an index.
19613109Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
19623109Sstever@eecs.umich.edu    def __init__(self, simobj, name, role, index):
19633105Sstever@eecs.umich.edu        PortRef.__init__(self, simobj, name, role)
19643105Sstever@eecs.umich.edu        self.index = index
19653105Sstever@eecs.umich.edu
19663105Sstever@eecs.umich.edu    def __str__(self):
19673105Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
19683105Sstever@eecs.umich.edu
19693105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
19703101Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
19713101Sstever@eecs.umich.educlass VectorPortRef(object):
19723101Sstever@eecs.umich.edu    def __init__(self, simobj, name, role):
19733101Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
19743101Sstever@eecs.umich.edu        self.simobj = simobj
19753101Sstever@eecs.umich.edu        self.name = name
19763105Sstever@eecs.umich.edu        self.role = role
19778839Sandreas.hansson@arm.com        self.elements = []
19783101Sstever@eecs.umich.edu
19793101Sstever@eecs.umich.edu    def __str__(self):
19803101Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
19813105Sstever@eecs.umich.edu
19823105Sstever@eecs.umich.edu    def __len__(self):
19833101Sstever@eecs.umich.edu        # Return the number of connected peers, corresponding the the
19848840Sandreas.hansson@arm.com        # length of the elements.
19858840Sandreas.hansson@arm.com        return len(self.elements)
19868840Sandreas.hansson@arm.com
19878840Sandreas.hansson@arm.com    # for config.ini, print peer's name (not ours)
19888840Sandreas.hansson@arm.com    def ini_str(self):
198911988Sandreas.sandberg@arm.com        return ' '.join([el.ini_str() for el in self.elements])
199011988Sandreas.sandberg@arm.com
199111988Sandreas.sandberg@arm.com    # for config.json
19928840Sandreas.hansson@arm.com    def get_config_as_dict(self):
19938840Sandreas.hansson@arm.com        return {'role' : self.role,
19948840Sandreas.hansson@arm.com                'peer' : [el.ini_str() for el in self.elements]}
19958840Sandreas.hansson@arm.com
19968840Sandreas.hansson@arm.com    def __getitem__(self, key):
19978840Sandreas.hansson@arm.com        if not isinstance(key, int):
19988839Sandreas.hansson@arm.com            raise TypeError("VectorPort index must be integer")
19998839Sandreas.hansson@arm.com        if key >= len(self.elements):
20008839Sandreas.hansson@arm.com            # need to extend list
20018839Sandreas.hansson@arm.com            ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
20028839Sandreas.hansson@arm.com                   for i in range(len(self.elements), key+1)]
20038839Sandreas.hansson@arm.com            self.elements.extend(ext)
20048839Sandreas.hansson@arm.com        return self.elements[key]
20058839Sandreas.hansson@arm.com
20068839Sandreas.hansson@arm.com    def _get_next(self):
20078839Sandreas.hansson@arm.com        return self[len(self.elements)]
20088839Sandreas.hansson@arm.com
20098839Sandreas.hansson@arm.com    def __setitem__(self, key, value):
20108839Sandreas.hansson@arm.com        if not isinstance(key, int):
20118839Sandreas.hansson@arm.com            raise TypeError("VectorPort index must be integer")
20128839Sandreas.hansson@arm.com        self[key].connect(value)
20138839Sandreas.hansson@arm.com
20148839Sandreas.hansson@arm.com    def connect(self, other):
20158839Sandreas.hansson@arm.com        if isinstance(other, (list, tuple)):
20163101Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
201710405Sandreas.hansson@arm.com            # For now, append them... not sure if that's the right semantics
20183101Sstever@eecs.umich.edu            # or if it should replace the current vector.
20193105Sstever@eecs.umich.edu            for ref in other:
20203101Sstever@eecs.umich.edu                self._get_next().connect(ref)
20213101Sstever@eecs.umich.edu        else:
20223105Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
20238839Sandreas.hansson@arm.com            self._get_next().connect(other)
20248839Sandreas.hansson@arm.com
20258839Sandreas.hansson@arm.com    def clone(self, simobj, memo):
20268839Sandreas.hansson@arm.com        if self in memo:
20278839Sandreas.hansson@arm.com            return memo[self]
20288839Sandreas.hansson@arm.com        newRef = copy.copy(self)
20298839Sandreas.hansson@arm.com        memo[self] = newRef
20308839Sandreas.hansson@arm.com        newRef.simobj = simobj
20318839Sandreas.hansson@arm.com        assert(isSimObject(newRef.simobj))
20328839Sandreas.hansson@arm.com        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
20338839Sandreas.hansson@arm.com        return newRef
20348839Sandreas.hansson@arm.com
20358839Sandreas.hansson@arm.com    def unproxy(self, simobj):
20368839Sandreas.hansson@arm.com        [el.unproxy(simobj) for el in self.elements]
20378839Sandreas.hansson@arm.com
20388839Sandreas.hansson@arm.com    def ccConnect(self):
20398839Sandreas.hansson@arm.com        [el.ccConnect() for el in self.elements]
20408839Sandreas.hansson@arm.com
20418839Sandreas.hansson@arm.com# Port description object.  Like a ParamDesc object, this represents a
20428839Sandreas.hansson@arm.com# logical port in the SimObject class, not a particular port on a
20438839Sandreas.hansson@arm.com# SimObject instance.  The latter are represented by PortRef objects.
20443105Sstever@eecs.umich.educlass Port(object):
20453109Sstever@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
20463109Sstever@eecs.umich.edu    # given name
20473109Sstever@eecs.umich.edu    def makeRef(self, simobj):
20483109Sstever@eecs.umich.edu        return PortRef(simobj, self.name, self.role)
20493109Sstever@eecs.umich.edu
20503109Sstever@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
20513109Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
20523109Sstever@eecs.umich.edu    def connect(self, simobj, ref):
20533105Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
20546654Snate@binkert.org
20556654Snate@binkert.org    # No need for any pre-declarations at the moment as we merely rely
20566654Snate@binkert.org    # on an unsigned int.
20576654Snate@binkert.org    def cxx_predecls(self, code):
20586654Snate@binkert.org        pass
20596654Snate@binkert.org
20606654Snate@binkert.org    def pybind_predecls(self, code):
20616654Snate@binkert.org        cls.cxx_predecls(self, code)
20626654Snate@binkert.org
20633101Sstever@eecs.umich.edu    # Declare an unsigned int with the same name as the port, that
20643101Sstever@eecs.umich.edu    # will eventually hold the number of connected ports (and thus the
20653101Sstever@eecs.umich.edu    # number of elements for a VectorPort).
20663101Sstever@eecs.umich.edu    def cxx_decl(self, code):
20673101Sstever@eecs.umich.edu        code('unsigned int port_${{self.name}}_connection_count;')
20683101Sstever@eecs.umich.edu
20697777Sgblack@eecs.umich.educlass MasterPort(Port):
20703101Sstever@eecs.umich.edu    # MasterPort("description")
20719827Sakash.bagdia@arm.com    def __init__(self, *args):
20723101Sstever@eecs.umich.edu        if len(args) == 1:
20739232Sandreas.hansson@arm.com            self.desc = args[0]
20743101Sstever@eecs.umich.edu            self.role = 'MASTER'
20753885Sbinkertn@umich.edu        else:
20763102Sstever@eecs.umich.edu            raise TypeError('wrong number of arguments')
20778839Sandreas.hansson@arm.com
20788839Sandreas.hansson@arm.comclass SlavePort(Port):
20796654Snate@binkert.org    # SlavePort("description")
20806654Snate@binkert.org    def __init__(self, *args):
2081        if len(args) == 1:
2082            self.desc = args[0]
2083            self.role = 'SLAVE'
2084        else:
2085            raise TypeError('wrong number of arguments')
2086
2087# VectorPort description object.  Like Port, but represents a vector
2088# of connections (e.g., as on a XBar).
2089class VectorPort(Port):
2090    def __init__(self, *args):
2091        self.isVec = True
2092
2093    def makeRef(self, simobj):
2094        return VectorPortRef(simobj, self.name, self.role)
2095
2096class VectorMasterPort(VectorPort):
2097    # VectorMasterPort("description")
2098    def __init__(self, *args):
2099        if len(args) == 1:
2100            self.desc = args[0]
2101            self.role = 'MASTER'
2102            VectorPort.__init__(self, *args)
2103        else:
2104            raise TypeError('wrong number of arguments')
2105
2106class VectorSlavePort(VectorPort):
2107    # VectorSlavePort("description")
2108    def __init__(self, *args):
2109        if len(args) == 1:
2110            self.desc = args[0]
2111            self.role = 'SLAVE'
2112            VectorPort.__init__(self, *args)
2113        else:
2114            raise TypeError('wrong number of arguments')
2115
2116# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
2117# proxy objects (via set_param_desc()) so that proxy error messages
2118# make sense.
2119class PortParamDesc(object):
2120    __metaclass__ = Singleton
2121
2122    ptype_str = 'Port'
2123    ptype = Port
2124
2125baseEnums = allEnums.copy()
2126baseParams = allParams.copy()
2127
2128def clear():
2129    global allEnums, allParams
2130
2131    allEnums = baseEnums.copy()
2132    allParams = baseParams.copy()
2133
2134__all__ = ['Param', 'VectorParam',
2135           'Enum', 'ScopedEnum', 'Bool', 'String', 'Float',
2136           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
2137           'Int32', 'UInt32', 'Int64', 'UInt64',
2138           'Counter', 'Addr', 'Tick', 'Percent',
2139           'TcpPort', 'UdpPort', 'EthernetAddr',
2140           'IpAddress', 'IpNetmask', 'IpWithPort',
2141           'MemorySize', 'MemorySize32',
2142           'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy',
2143           'NetworkBandwidth', 'MemoryBandwidth',
2144           'AddrRange',
2145           'MaxAddr', 'MaxTick', 'AllMemory',
2146           'Time',
2147           'NextEthernetAddr', 'NULL',
2148           'MasterPort', 'SlavePort',
2149           'VectorMasterPort', 'VectorSlavePort']
2150