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