114049Snikos.nikoleris@arm.com# Copyright (c) 2012-2014, 2017-2019 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
6212563Sgabeblack@google.comfrom __future__ import print_function
6313719Sandreas.sandberg@arm.comimport six
6413719Sandreas.sandberg@arm.comif six.PY3:
6513719Sandreas.sandberg@arm.com    long = int
6612563Sgabeblack@google.com
673885Sbinkertn@umich.eduimport copy
683885Sbinkertn@umich.eduimport datetime
694762Snate@binkert.orgimport re
703885Sbinkertn@umich.eduimport sys
713885Sbinkertn@umich.eduimport time
727528Ssteve.reinhardt@amd.comimport math
733885Sbinkertn@umich.edu
7413714Sandreas.sandberg@arm.comfrom . import proxy
7513714Sandreas.sandberg@arm.comfrom . import ticks
7613714Sandreas.sandberg@arm.comfrom .util import *
773101Sstever@eecs.umich.edu
784762Snate@binkert.orgdef isSimObject(*args, **kwargs):
7913716Sandreas.sandberg@arm.com    from . import SimObject
804762Snate@binkert.org    return SimObject.isSimObject(*args, **kwargs)
814762Snate@binkert.org
824762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs):
8313716Sandreas.sandberg@arm.com    from . import SimObject
844762Snate@binkert.org    return SimObject.isSimObjectSequence(*args, **kwargs)
854762Snate@binkert.org
864762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs):
8713716Sandreas.sandberg@arm.com    from . import SimObject
884762Snate@binkert.org    return SimObject.isSimObjectClass(*args, **kwargs)
894762Snate@binkert.org
905033Smilesck@eecs.umich.eduallParams = {}
915033Smilesck@eecs.umich.edu
925033Smilesck@eecs.umich.educlass MetaParamValue(type):
935033Smilesck@eecs.umich.edu    def __new__(mcls, name, bases, dct):
945033Smilesck@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
955033Smilesck@eecs.umich.edu        assert name not in allParams
965033Smilesck@eecs.umich.edu        allParams[name] = cls
975033Smilesck@eecs.umich.edu        return cls
985033Smilesck@eecs.umich.edu
995033Smilesck@eecs.umich.edu
1003101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject
1013101Sstever@eecs.umich.edu# parameters.
1023101Sstever@eecs.umich.educlass ParamValue(object):
1035033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
10410267SGeoffrey.Blake@arm.com    cmd_line_settable = False
1058596Ssteve.reinhardt@amd.com
1068596Ssteve.reinhardt@amd.com    # Generate the code needed as a prerequisite for declaring a C++
1078596Ssteve.reinhardt@amd.com    # object of this type.  Typically generates one or more #include
1088596Ssteve.reinhardt@amd.com    # statements.  Used when declaring parameters of this type.
1097673Snate@binkert.org    @classmethod
1107673Snate@binkert.org    def cxx_predecls(cls, code):
1117673Snate@binkert.org        pass
1127673Snate@binkert.org
11311988Sandreas.sandberg@arm.com    @classmethod
11411988Sandreas.sandberg@arm.com    def pybind_predecls(cls, code):
11511988Sandreas.sandberg@arm.com        cls.cxx_predecls(code)
11611988Sandreas.sandberg@arm.com
1173101Sstever@eecs.umich.edu    # default for printing to .ini file is regular string conversion.
1183101Sstever@eecs.umich.edu    # will be overridden in some cases
1193101Sstever@eecs.umich.edu    def ini_str(self):
1203101Sstever@eecs.umich.edu        return str(self)
1213101Sstever@eecs.umich.edu
12210380SAndrew.Bardsley@arm.com    # default for printing to .json file is regular string conversion.
12310380SAndrew.Bardsley@arm.com    # will be overridden in some cases, mostly to use native Python
12410380SAndrew.Bardsley@arm.com    # types where there are similar JSON types
12510380SAndrew.Bardsley@arm.com    def config_value(self):
12610380SAndrew.Bardsley@arm.com        return str(self)
12710380SAndrew.Bardsley@arm.com
12810458Sandreas.hansson@arm.com    # Prerequisites for .ini parsing with cxx_ini_parse
12910458Sandreas.hansson@arm.com    @classmethod
13010458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
13110458Sandreas.hansson@arm.com        pass
13210458Sandreas.hansson@arm.com
13310458Sandreas.hansson@arm.com    # parse a .ini file entry for this param from string expression
13410458Sandreas.hansson@arm.com    # src into lvalue dest (of the param's C++ type)
13510458Sandreas.hansson@arm.com    @classmethod
13610458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
13710458Sandreas.hansson@arm.com        code('// Unhandled param type: %s' % cls.__name__)
13810458Sandreas.hansson@arm.com        code('%s false;' % ret)
13910458Sandreas.hansson@arm.com
1403101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
1413101Sstever@eecs.umich.edu    # if they're really proxies or not
1423101Sstever@eecs.umich.edu    def unproxy(self, base):
1433101Sstever@eecs.umich.edu        return self
1443101Sstever@eecs.umich.edu
14510267SGeoffrey.Blake@arm.com    # Produce a human readable version of the stored value
14610267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
14710267SGeoffrey.Blake@arm.com        return str(value)
14810267SGeoffrey.Blake@arm.com
1493101Sstever@eecs.umich.edu# Regular parameter description.
1503101Sstever@eecs.umich.educlass ParamDesc(object):
1513101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1523101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1533101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1543101Sstever@eecs.umich.edu        if ptype != None:
1553101Sstever@eecs.umich.edu            self.ptype = ptype
1563101Sstever@eecs.umich.edu
1573101Sstever@eecs.umich.edu        if args:
1583101Sstever@eecs.umich.edu            if len(args) == 1:
1593101Sstever@eecs.umich.edu                self.desc = args[0]
1603101Sstever@eecs.umich.edu            elif len(args) == 2:
1613101Sstever@eecs.umich.edu                self.default = args[0]
1623101Sstever@eecs.umich.edu                self.desc = args[1]
1633101Sstever@eecs.umich.edu            else:
16413663Sandreas.sandberg@arm.com                raise TypeError('too many arguments')
1653101Sstever@eecs.umich.edu
16613675Sandreas.sandberg@arm.com        if 'desc' in kwargs:
1673101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1683101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1693101Sstever@eecs.umich.edu            del kwargs['desc']
1703101Sstever@eecs.umich.edu
17113675Sandreas.sandberg@arm.com        if 'default' in kwargs:
1723101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1733101Sstever@eecs.umich.edu            self.default = kwargs['default']
1743101Sstever@eecs.umich.edu            del kwargs['default']
1753101Sstever@eecs.umich.edu
1763101Sstever@eecs.umich.edu        if kwargs:
17713663Sandreas.sandberg@arm.com            raise TypeError('extra unknown kwargs %s' % kwargs)
1783101Sstever@eecs.umich.edu
1793101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
18013663Sandreas.sandberg@arm.com            raise TypeError('desc attribute missing')
1813101Sstever@eecs.umich.edu
1823101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1833101Sstever@eecs.umich.edu        if attr == 'ptype':
18413716Sandreas.sandberg@arm.com            from . import SimObject
1855033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1866656Snate@binkert.org            assert isSimObjectClass(ptype)
1875033Smilesck@eecs.umich.edu            self.ptype = ptype
1885033Smilesck@eecs.umich.edu            return ptype
1895033Smilesck@eecs.umich.edu
19013663Sandreas.sandberg@arm.com        raise AttributeError("'%s' object has no attribute '%s'" % \
19113663Sandreas.sandberg@arm.com              (type(self).__name__, attr))
1923101Sstever@eecs.umich.edu
19310267SGeoffrey.Blake@arm.com    def example_str(self):
19410267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "ex_str"):
19510267SGeoffrey.Blake@arm.com            return self.ptype.ex_str
19610267SGeoffrey.Blake@arm.com        else:
19710267SGeoffrey.Blake@arm.com            return self.ptype_str
19810267SGeoffrey.Blake@arm.com
19910267SGeoffrey.Blake@arm.com    # Is the param available to be exposed on the command line
20010267SGeoffrey.Blake@arm.com    def isCmdLineSettable(self):
20110267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "cmd_line_settable"):
20210267SGeoffrey.Blake@arm.com            return self.ptype.cmd_line_settable
20310267SGeoffrey.Blake@arm.com        else:
20410267SGeoffrey.Blake@arm.com            return False
20510267SGeoffrey.Blake@arm.com
2063101Sstever@eecs.umich.edu    def convert(self, value):
2073101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
2083101Sstever@eecs.umich.edu            value.set_param_desc(self)
2093101Sstever@eecs.umich.edu            return value
21013699Sandreas.sandberg@arm.com        if 'ptype' not in self.__dict__ and isNullPointer(value):
2113101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
2123101Sstever@eecs.umich.edu            # we're just assigning a null pointer
2133101Sstever@eecs.umich.edu            return value
2143101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
2153101Sstever@eecs.umich.edu            return value
2163102Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
2173101Sstever@eecs.umich.edu            return value
2183101Sstever@eecs.umich.edu        return self.ptype(value)
2193101Sstever@eecs.umich.edu
22010267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
22110267SGeoffrey.Blake@arm.com        if isinstance(value, proxy.BaseProxy):
22210267SGeoffrey.Blake@arm.com           return str(value)
22310267SGeoffrey.Blake@arm.com        if isNullPointer(value):
22410267SGeoffrey.Blake@arm.com           return NULL
22510267SGeoffrey.Blake@arm.com        return self.ptype(value).pretty_print(value)
22610267SGeoffrey.Blake@arm.com
2277673Snate@binkert.org    def cxx_predecls(self, code):
2288607Sgblack@eecs.umich.edu        code('#include <cstddef>')
2297673Snate@binkert.org        self.ptype.cxx_predecls(code)
2303101Sstever@eecs.umich.edu
23111988Sandreas.sandberg@arm.com    def pybind_predecls(self, code):
23211988Sandreas.sandberg@arm.com        self.ptype.pybind_predecls(code)
23311988Sandreas.sandberg@arm.com
2347673Snate@binkert.org    def cxx_decl(self, code):
2357673Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
2363101Sstever@eecs.umich.edu
2373101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
2383101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
2393101Sstever@eecs.umich.edu# single value.
2403101Sstever@eecs.umich.edu
2413101Sstever@eecs.umich.educlass VectorParamValue(list):
2425033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
2435475Snate@binkert.org    def __setattr__(self, attr, value):
24413663Sandreas.sandberg@arm.com        raise AttributeError("Not allowed to set %s on '%s'" % \
24513663Sandreas.sandberg@arm.com                             (attr, type(self).__name__))
2465475Snate@binkert.org
24710380SAndrew.Bardsley@arm.com    def config_value(self):
24810380SAndrew.Bardsley@arm.com        return [v.config_value() for v in self]
24910380SAndrew.Bardsley@arm.com
2503101Sstever@eecs.umich.edu    def ini_str(self):
2513101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
2523101Sstever@eecs.umich.edu
2534762Snate@binkert.org    def getValue(self):
2544762Snate@binkert.org        return [ v.getValue() for v in self ]
2554762Snate@binkert.org
2563101Sstever@eecs.umich.edu    def unproxy(self, base):
25712050Snikos.nikoleris@arm.com        if len(self) == 1 and isinstance(self[0], proxy.BaseProxy):
25812050Snikos.nikoleris@arm.com            # The value is a proxy (e.g. Parent.any, Parent.all or
25912050Snikos.nikoleris@arm.com            # Parent.x) therefore try resolve it
2608459SAli.Saidi@ARM.com            return self[0].unproxy(base)
2618459SAli.Saidi@ARM.com        else:
26212050Snikos.nikoleris@arm.com            return [v.unproxy(base) for v in self]
2633101Sstever@eecs.umich.edu
2647528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2657528Ssteve.reinhardt@amd.com    # support clone operation
2667528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2677528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2687528Ssteve.reinhardt@amd.com
2697528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
2703101Sstever@eecs.umich.edu        for v in self:
2717528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2727528Ssteve.reinhardt@amd.com
2737528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2747528Ssteve.reinhardt@amd.com        if len(self) == 1:
2757528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2767528Ssteve.reinhardt@amd.com        else:
2777528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2787528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2797528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2807528Ssteve.reinhardt@amd.com
2818321Ssteve.reinhardt@amd.com    def has_parent(self):
28212194Sgabeblack@google.com        return any([e.has_parent() for e in self if not isNullPointer(e)])
2837528Ssteve.reinhardt@amd.com
2847528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2857528Ssteve.reinhardt@amd.com    def get_name(self):
2867528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2877528Ssteve.reinhardt@amd.com
2887528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2897528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2907528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2917528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2927528Ssteve.reinhardt@amd.com    def descendants(self):
2937528Ssteve.reinhardt@amd.com        for v in self:
2947528Ssteve.reinhardt@amd.com            for obj in v.descendants():
2957528Ssteve.reinhardt@amd.com                yield obj
2963101Sstever@eecs.umich.edu
2978664SAli.Saidi@ARM.com    def get_config_as_dict(self):
2988664SAli.Saidi@ARM.com        a = []
2998664SAli.Saidi@ARM.com        for v in self:
3008664SAli.Saidi@ARM.com            a.append(v.get_config_as_dict())
3018664SAli.Saidi@ARM.com        return a
3028664SAli.Saidi@ARM.com
3039953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
3049953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
3059953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
3069953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
3079953Sgeoffrey.blake@arm.com    # configuration scripts.
3089953Sgeoffrey.blake@arm.com    def __setitem__(self, key, value):
3099953Sgeoffrey.blake@arm.com        val = self[key]
3109953Sgeoffrey.blake@arm.com        if value.has_parent():
3119953Sgeoffrey.blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
3129953Sgeoffrey.blake@arm.com                 " that is being overwritten by a SimObjectVector")
3139953Sgeoffrey.blake@arm.com        value.set_parent(val.get_parent(), val._name)
3149953Sgeoffrey.blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
3159953Sgeoffrey.blake@arm.com
31610267SGeoffrey.Blake@arm.com    # Enumerate the params of each member of the SimObject vector. Creates
31710267SGeoffrey.Blake@arm.com    # strings that will allow indexing into the vector by the python code and
31810267SGeoffrey.Blake@arm.com    # allow it to be specified on the command line.
31910267SGeoffrey.Blake@arm.com    def enumerateParams(self, flags_dict = {},
32010267SGeoffrey.Blake@arm.com                        cmd_line_str = "",
32110267SGeoffrey.Blake@arm.com                        access_str = ""):
32210267SGeoffrey.Blake@arm.com        if hasattr(self, "_paramEnumed"):
32312563Sgabeblack@google.com            print("Cycle detected enumerating params at %s?!" % (cmd_line_str))
32410267SGeoffrey.Blake@arm.com        else:
32510267SGeoffrey.Blake@arm.com            x = 0
32610267SGeoffrey.Blake@arm.com            for vals in self:
32710267SGeoffrey.Blake@arm.com                # Each entry in the SimObjectVector should be an
32810267SGeoffrey.Blake@arm.com                # instance of a SimObject
32910267SGeoffrey.Blake@arm.com                flags_dict = vals.enumerateParams(flags_dict,
33010267SGeoffrey.Blake@arm.com                                                  cmd_line_str + "%d." % x,
33110267SGeoffrey.Blake@arm.com                                                  access_str + "[%d]." % x)
33210267SGeoffrey.Blake@arm.com                x = x + 1
33310267SGeoffrey.Blake@arm.com
33410267SGeoffrey.Blake@arm.com        return flags_dict
33510267SGeoffrey.Blake@arm.com
3363101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
3373101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
3383101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
3393101Sstever@eecs.umich.edu    def convert(self, value):
3403101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
3413101Sstever@eecs.umich.edu            # list: coerce each element into new list
3423101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
34310364SGeoffrey.Blake@arm.com        elif isinstance(value, str):
34410364SGeoffrey.Blake@arm.com            # If input is a csv string
34510364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
34610364SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
3473101Sstever@eecs.umich.edu        else:
3484762Snate@binkert.org            # singleton: coerce to a single-element list
3494762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
3504762Snate@binkert.org
3514762Snate@binkert.org        if isSimObjectSequence(tmp_list):
3527528Ssteve.reinhardt@amd.com            return SimObjectVector(tmp_list)
3534762Snate@binkert.org        else:
3544762Snate@binkert.org            return VectorParamValue(tmp_list)
3554762Snate@binkert.org
35610267SGeoffrey.Blake@arm.com    # Produce a human readable example string that describes
35710267SGeoffrey.Blake@arm.com    # how to set this vector parameter in the absence of a default
35810267SGeoffrey.Blake@arm.com    # value.
35910267SGeoffrey.Blake@arm.com    def example_str(self):
36010267SGeoffrey.Blake@arm.com        s = super(VectorParamDesc, self).example_str()
36110267SGeoffrey.Blake@arm.com        help_str = "[" + s + "," + s + ", ...]"
36210267SGeoffrey.Blake@arm.com        return help_str
36310267SGeoffrey.Blake@arm.com
36410267SGeoffrey.Blake@arm.com    # Produce a human readable representation of the value of this vector param.
36510267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
36610267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
36710267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
36810267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
36910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
37010267SGeoffrey.Blake@arm.com        else:
37110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, value) ]
37210267SGeoffrey.Blake@arm.com
37310267SGeoffrey.Blake@arm.com        return tmp_list
37410267SGeoffrey.Blake@arm.com
37510267SGeoffrey.Blake@arm.com    # This is a helper function for the new config system
37610267SGeoffrey.Blake@arm.com    def __call__(self, value):
37710267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
37810267SGeoffrey.Blake@arm.com            # list: coerce each element into new list
37910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
38010267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
38110267SGeoffrey.Blake@arm.com            # If input is a csv string
38210364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
38310364SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
38410267SGeoffrey.Blake@arm.com        else:
38510267SGeoffrey.Blake@arm.com            # singleton: coerce to a single-element list
38610267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
38710267SGeoffrey.Blake@arm.com
38810267SGeoffrey.Blake@arm.com        return VectorParamValue(tmp_list)
38910267SGeoffrey.Blake@arm.com
3907673Snate@binkert.org    def cxx_predecls(self, code):
3917673Snate@binkert.org        code('#include <vector>')
3927673Snate@binkert.org        self.ptype.cxx_predecls(code)
3933101Sstever@eecs.umich.edu
39411988Sandreas.sandberg@arm.com    def pybind_predecls(self, code):
39511988Sandreas.sandberg@arm.com        code('#include <vector>')
39611988Sandreas.sandberg@arm.com        self.ptype.pybind_predecls(code)
39711988Sandreas.sandberg@arm.com
3987673Snate@binkert.org    def cxx_decl(self, code):
3997673Snate@binkert.org        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
4003101Sstever@eecs.umich.edu
4013101Sstever@eecs.umich.educlass ParamFactory(object):
4023101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
4033101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
4043101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
4053101Sstever@eecs.umich.edu
4063101Sstever@eecs.umich.edu    def __getattr__(self, attr):
4073101Sstever@eecs.umich.edu        if self.ptype_str:
4083101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
4093101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
4103101Sstever@eecs.umich.edu
4113101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
4123101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
4133101Sstever@eecs.umich.edu        ptype = None
4143101Sstever@eecs.umich.edu        try:
4155033Smilesck@eecs.umich.edu            ptype = allParams[self.ptype_str]
4165033Smilesck@eecs.umich.edu        except KeyError:
4173101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
4183101Sstever@eecs.umich.edu            # try to resolve it later
4193101Sstever@eecs.umich.edu            pass
4203101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
4213101Sstever@eecs.umich.edu
4223101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
4233101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
4243101Sstever@eecs.umich.edu
4253101Sstever@eecs.umich.edu#####################################################################
4263101Sstever@eecs.umich.edu#
4273101Sstever@eecs.umich.edu# Parameter Types
4283101Sstever@eecs.umich.edu#
4293101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
4303101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
4313101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
4323101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
4333101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
4343101Sstever@eecs.umich.edu# the __str__() conversion method).
4353101Sstever@eecs.umich.edu#
4363101Sstever@eecs.umich.edu#####################################################################
4373101Sstever@eecs.umich.edu
4383101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
4393101Sstever@eecs.umich.edu# built-in str class.
4403101Sstever@eecs.umich.educlass String(ParamValue,str):
4413101Sstever@eecs.umich.edu    cxx_type = 'std::string'
44210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
4437673Snate@binkert.org
4447673Snate@binkert.org    @classmethod
4457673Snate@binkert.org    def cxx_predecls(self, code):
4467673Snate@binkert.org        code('#include <string>')
4477673Snate@binkert.org
44810267SGeoffrey.Blake@arm.com    def __call__(self, value):
44910267SGeoffrey.Blake@arm.com        self = value
45010267SGeoffrey.Blake@arm.com        return value
45110267SGeoffrey.Blake@arm.com
45210458Sandreas.hansson@arm.com    @classmethod
45310458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
45410458Sandreas.hansson@arm.com        code('%s = %s;' % (dest, src))
45510458Sandreas.hansson@arm.com        code('%s true;' % ret)
45610458Sandreas.hansson@arm.com
4574762Snate@binkert.org    def getValue(self):
4584762Snate@binkert.org        return self
4593101Sstever@eecs.umich.edu
4603101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
4613101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
4623101Sstever@eecs.umich.edu# a new Latency object.
4633101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
46413708Sandreas.sandberg@arm.com    @staticmethod
46513708Sandreas.sandberg@arm.com    def unwrap(v):
46613708Sandreas.sandberg@arm.com        return v.value if isinstance(v, NumericParamValue) else v
46713708Sandreas.sandberg@arm.com
4683101Sstever@eecs.umich.edu    def __str__(self):
4693101Sstever@eecs.umich.edu        return str(self.value)
4703101Sstever@eecs.umich.edu
4713101Sstever@eecs.umich.edu    def __float__(self):
4723101Sstever@eecs.umich.edu        return float(self.value)
4733101Sstever@eecs.umich.edu
4743714Sstever@eecs.umich.edu    def __long__(self):
4753714Sstever@eecs.umich.edu        return long(self.value)
4763714Sstever@eecs.umich.edu
4773714Sstever@eecs.umich.edu    def __int__(self):
4783714Sstever@eecs.umich.edu        return int(self.value)
4793714Sstever@eecs.umich.edu
4803101Sstever@eecs.umich.edu    # hook for bounds checking
4813101Sstever@eecs.umich.edu    def _check(self):
4823101Sstever@eecs.umich.edu        return
4833101Sstever@eecs.umich.edu
4843101Sstever@eecs.umich.edu    def __mul__(self, other):
4853101Sstever@eecs.umich.edu        newobj = self.__class__(self)
48613708Sandreas.sandberg@arm.com        newobj.value *= NumericParamValue.unwrap(other)
4873101Sstever@eecs.umich.edu        newobj._check()
4883101Sstever@eecs.umich.edu        return newobj
4893101Sstever@eecs.umich.edu
4903101Sstever@eecs.umich.edu    __rmul__ = __mul__
4913101Sstever@eecs.umich.edu
49213708Sandreas.sandberg@arm.com    def __truediv__(self, other):
4933101Sstever@eecs.umich.edu        newobj = self.__class__(self)
49413708Sandreas.sandberg@arm.com        newobj.value /= NumericParamValue.unwrap(other)
49513708Sandreas.sandberg@arm.com        newobj._check()
49613708Sandreas.sandberg@arm.com        return newobj
49713708Sandreas.sandberg@arm.com
49813708Sandreas.sandberg@arm.com    def __floordiv__(self, other):
49913708Sandreas.sandberg@arm.com        newobj = self.__class__(self)
50013708Sandreas.sandberg@arm.com        newobj.value //= NumericParamValue.unwrap(other)
50113708Sandreas.sandberg@arm.com        newobj._check()
50213708Sandreas.sandberg@arm.com        return newobj
50313708Sandreas.sandberg@arm.com
50413708Sandreas.sandberg@arm.com
50513708Sandreas.sandberg@arm.com    def __add__(self, other):
50613708Sandreas.sandberg@arm.com        newobj = self.__class__(self)
50713708Sandreas.sandberg@arm.com        newobj.value += NumericParamValue.unwrap(other)
5083101Sstever@eecs.umich.edu        newobj._check()
5093101Sstever@eecs.umich.edu        return newobj
5103101Sstever@eecs.umich.edu
5113101Sstever@eecs.umich.edu    def __sub__(self, other):
5123101Sstever@eecs.umich.edu        newobj = self.__class__(self)
51313708Sandreas.sandberg@arm.com        newobj.value -= NumericParamValue.unwrap(other)
5143101Sstever@eecs.umich.edu        newobj._check()
5153101Sstever@eecs.umich.edu        return newobj
5163101Sstever@eecs.umich.edu
51713708Sandreas.sandberg@arm.com    def __iadd__(self, other):
51813708Sandreas.sandberg@arm.com        self.value += NumericParamValue.unwrap(other)
51913708Sandreas.sandberg@arm.com        self._check()
52013708Sandreas.sandberg@arm.com        return self
52113708Sandreas.sandberg@arm.com
52213708Sandreas.sandberg@arm.com    def __isub__(self, other):
52313708Sandreas.sandberg@arm.com        self.value -= NumericParamValue.unwrap(other)
52413708Sandreas.sandberg@arm.com        self._check()
52513708Sandreas.sandberg@arm.com        return self
52613708Sandreas.sandberg@arm.com
52713708Sandreas.sandberg@arm.com    def __imul__(self, other):
52813708Sandreas.sandberg@arm.com        self.value *= NumericParamValue.unwrap(other)
52913708Sandreas.sandberg@arm.com        self._check()
53013708Sandreas.sandberg@arm.com        return self
53113708Sandreas.sandberg@arm.com
53213708Sandreas.sandberg@arm.com    def __itruediv__(self, other):
53313708Sandreas.sandberg@arm.com        self.value /= NumericParamValue.unwrap(other)
53413708Sandreas.sandberg@arm.com        self._check()
53513708Sandreas.sandberg@arm.com        return self
53613708Sandreas.sandberg@arm.com
53713708Sandreas.sandberg@arm.com    def __ifloordiv__(self, other):
53813708Sandreas.sandberg@arm.com        self.value //= NumericParamValue.unwrap(other)
53913708Sandreas.sandberg@arm.com        self._check()
54013708Sandreas.sandberg@arm.com        return self
54113708Sandreas.sandberg@arm.com
54213708Sandreas.sandberg@arm.com    def __lt__(self, other):
54313708Sandreas.sandberg@arm.com        return self.value < NumericParamValue.unwrap(other)
54413708Sandreas.sandberg@arm.com
54513708Sandreas.sandberg@arm.com    # Python 2.7 pre __future__.division operators
54613708Sandreas.sandberg@arm.com    # TODO: Remove these when after "import division from __future__"
54713708Sandreas.sandberg@arm.com    __div__ =  __truediv__
54813708Sandreas.sandberg@arm.com    __idiv__ = __itruediv__
54913708Sandreas.sandberg@arm.com
55010380SAndrew.Bardsley@arm.com    def config_value(self):
55110380SAndrew.Bardsley@arm.com        return self.value
55210380SAndrew.Bardsley@arm.com
55310458Sandreas.hansson@arm.com    @classmethod
55410458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
55510458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
55610458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
55710458Sandreas.hansson@arm.com        pass
55810458Sandreas.hansson@arm.com
55910458Sandreas.hansson@arm.com    # The default for parsing PODs from an .ini entry is to extract from an
56010458Sandreas.hansson@arm.com    # istringstream and let overloading choose the right type according to
56110458Sandreas.hansson@arm.com    # the dest type.
56210458Sandreas.hansson@arm.com    @classmethod
56310458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
56410458Sandreas.hansson@arm.com        code('%s to_number(%s, %s);' % (ret, src, dest))
56510458Sandreas.hansson@arm.com
5663101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
5675033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue):
5683101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5693101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
5703101Sstever@eecs.umich.edu
5713101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
5723101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
5733101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
5743101Sstever@eecs.umich.edu        if name == 'CheckedInt':
5753101Sstever@eecs.umich.edu            return
5763101Sstever@eecs.umich.edu
5773101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
5783101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
5793101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
5805822Ssaidi@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
5815822Ssaidi@eecs.umich.edu                      name);
5823101Sstever@eecs.umich.edu            if cls.unsigned:
5833101Sstever@eecs.umich.edu                cls.min = 0
5843101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
5853101Sstever@eecs.umich.edu            else:
5863101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
5873101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
5883101Sstever@eecs.umich.edu
5893101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
5903101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
5913101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
5923101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
5933101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue):
5943101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
59510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
5963101Sstever@eecs.umich.edu
5973101Sstever@eecs.umich.edu    def _check(self):
5983101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
59913663Sandreas.sandberg@arm.com            raise TypeError('Integer param out of bounds %d < %d < %d' % \
60013663Sandreas.sandberg@arm.com                  (self.min, self.value, self.max))
6013101Sstever@eecs.umich.edu
6023101Sstever@eecs.umich.edu    def __init__(self, value):
6033101Sstever@eecs.umich.edu        if isinstance(value, str):
6043102Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
6053714Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
6063101Sstever@eecs.umich.edu            self.value = long(value)
6073714Sstever@eecs.umich.edu        else:
60813663Sandreas.sandberg@arm.com            raise TypeError("Can't convert object of type %s to CheckedInt" \
60913663Sandreas.sandberg@arm.com                  % type(value).__name__)
6103101Sstever@eecs.umich.edu        self._check()
6113101Sstever@eecs.umich.edu
61210267SGeoffrey.Blake@arm.com    def __call__(self, value):
61310267SGeoffrey.Blake@arm.com        self.__init__(value)
61410267SGeoffrey.Blake@arm.com        return value
61510267SGeoffrey.Blake@arm.com
61613711Sandreas.sandberg@arm.com    def __index__(self):
61713711Sandreas.sandberg@arm.com        return int(self.value)
61813711Sandreas.sandberg@arm.com
6197673Snate@binkert.org    @classmethod
6207673Snate@binkert.org    def cxx_predecls(cls, code):
6217673Snate@binkert.org        # most derived types require this, so we just do it here once
6227673Snate@binkert.org        code('#include "base/types.hh"')
6237673Snate@binkert.org
6244762Snate@binkert.org    def getValue(self):
6254762Snate@binkert.org        return long(self.value)
6264762Snate@binkert.org
6273101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
6283101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
6293101Sstever@eecs.umich.edu
6303101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
6313101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
6323101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
6333101Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
6343101Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
6353101Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
6363101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
6373101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
6383101Sstever@eecs.umich.edu
6393101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
6403101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
6413101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6423101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6433101Sstever@eecs.umich.edu
6443101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
6453101Sstever@eecs.umich.edu
6469184Sandreas.hansson@arm.comclass Cycles(CheckedInt):
6479184Sandreas.hansson@arm.com    cxx_type = 'Cycles'
6489184Sandreas.hansson@arm.com    size = 64
6499184Sandreas.hansson@arm.com    unsigned = True
6509184Sandreas.hansson@arm.com
6519184Sandreas.hansson@arm.com    def getValue(self):
65211802Sandreas.sandberg@arm.com        from _m5.core import Cycles
6539184Sandreas.hansson@arm.com        return Cycles(self.value)
6549184Sandreas.hansson@arm.com
65510458Sandreas.hansson@arm.com    @classmethod
65610458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
65710458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
65810458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
65910458Sandreas.hansson@arm.com        pass
66010458Sandreas.hansson@arm.com
66110458Sandreas.hansson@arm.com    @classmethod
66210458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
66310458Sandreas.hansson@arm.com        code('uint64_t _temp;')
66410458Sandreas.hansson@arm.com        code('bool _ret = to_number(%s, _temp);' % src)
66510458Sandreas.hansson@arm.com        code('if (_ret)')
66610458Sandreas.hansson@arm.com        code('    %s = Cycles(_temp);' % dest)
66710458Sandreas.hansson@arm.com        code('%s _ret;' % ret)
66810458Sandreas.hansson@arm.com
6693101Sstever@eecs.umich.educlass Float(ParamValue, float):
6704446Sbinkertn@umich.edu    cxx_type = 'double'
67110668SGeoffrey.Blake@arm.com    cmd_line_settable = True
6723101Sstever@eecs.umich.edu
6735468Snate@binkert.org    def __init__(self, value):
67410267SGeoffrey.Blake@arm.com        if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
6755468Snate@binkert.org            self.value = float(value)
6765468Snate@binkert.org        else:
67713663Sandreas.sandberg@arm.com            raise TypeError("Can't convert object of type %s to Float" \
67813663Sandreas.sandberg@arm.com                  % type(value).__name__)
6795468Snate@binkert.org
68010267SGeoffrey.Blake@arm.com    def __call__(self, value):
68110267SGeoffrey.Blake@arm.com        self.__init__(value)
68210267SGeoffrey.Blake@arm.com        return value
68310267SGeoffrey.Blake@arm.com
6844762Snate@binkert.org    def getValue(self):
6854762Snate@binkert.org        return float(self.value)
6864762Snate@binkert.org
68710380SAndrew.Bardsley@arm.com    def config_value(self):
68810380SAndrew.Bardsley@arm.com        return self
68910380SAndrew.Bardsley@arm.com
69010458Sandreas.hansson@arm.com    @classmethod
69110458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
69210458Sandreas.hansson@arm.com        code('#include <sstream>')
69310458Sandreas.hansson@arm.com
69410458Sandreas.hansson@arm.com    @classmethod
69510458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
69610458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
69710458Sandreas.hansson@arm.com
6983101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
6993101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
70010267SGeoffrey.Blake@arm.com    ex_str = '512MB'
7013101Sstever@eecs.umich.edu    size = 64
7023101Sstever@eecs.umich.edu    unsigned = True
7033101Sstever@eecs.umich.edu    def __init__(self, value):
7043101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
7053101Sstever@eecs.umich.edu            self.value = value.value
7063101Sstever@eecs.umich.edu        else:
7073102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
7083101Sstever@eecs.umich.edu        self._check()
7093101Sstever@eecs.umich.edu
7103101Sstever@eecs.umich.educlass MemorySize32(CheckedInt):
7114168Sbinkertn@umich.edu    cxx_type = 'uint32_t'
71210267SGeoffrey.Blake@arm.com    ex_str = '512MB'
7133101Sstever@eecs.umich.edu    size = 32
7143101Sstever@eecs.umich.edu    unsigned = True
7153101Sstever@eecs.umich.edu    def __init__(self, value):
7163101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
7173101Sstever@eecs.umich.edu            self.value = value.value
7183101Sstever@eecs.umich.edu        else:
7193102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
7203101Sstever@eecs.umich.edu        self._check()
7213101Sstever@eecs.umich.edu
7223101Sstever@eecs.umich.educlass Addr(CheckedInt):
7233101Sstever@eecs.umich.edu    cxx_type = 'Addr'
7243101Sstever@eecs.umich.edu    size = 64
7253101Sstever@eecs.umich.edu    unsigned = True
7263101Sstever@eecs.umich.edu    def __init__(self, value):
7273101Sstever@eecs.umich.edu        if isinstance(value, Addr):
7283101Sstever@eecs.umich.edu            self.value = value.value
7293101Sstever@eecs.umich.edu        else:
7303101Sstever@eecs.umich.edu            try:
73110317Smitch.hayenga@arm.com                # Often addresses are referred to with sizes. Ex: A device
73210317Smitch.hayenga@arm.com                # base address is at "512MB".  Use toMemorySize() to convert
73310317Smitch.hayenga@arm.com                # these into addresses. If the address is not specified with a
73410317Smitch.hayenga@arm.com                # "size", an exception will occur and numeric translation will
73510317Smitch.hayenga@arm.com                # proceed below.
7363102Sstever@eecs.umich.edu                self.value = convert.toMemorySize(value)
73710317Smitch.hayenga@arm.com            except (TypeError, ValueError):
73810317Smitch.hayenga@arm.com                # Convert number to string and use long() to do automatic
73910317Smitch.hayenga@arm.com                # base conversion (requires base=0 for auto-conversion)
74010317Smitch.hayenga@arm.com                self.value = long(str(value), base=0)
74110317Smitch.hayenga@arm.com
7423101Sstever@eecs.umich.edu        self._check()
7433584Ssaidi@eecs.umich.edu    def __add__(self, other):
7443584Ssaidi@eecs.umich.edu        if isinstance(other, Addr):
7453584Ssaidi@eecs.umich.edu            return self.value + other.value
7463584Ssaidi@eecs.umich.edu        else:
7473584Ssaidi@eecs.umich.edu            return self.value + other
74810267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
74910267SGeoffrey.Blake@arm.com        try:
75010267SGeoffrey.Blake@arm.com            val = convert.toMemorySize(value)
75110267SGeoffrey.Blake@arm.com        except TypeError:
75210267SGeoffrey.Blake@arm.com            val = long(value)
75310267SGeoffrey.Blake@arm.com        return "0x%x" % long(val)
7543101Sstever@eecs.umich.edu
7559232Sandreas.hansson@arm.comclass AddrRange(ParamValue):
7569235Sandreas.hansson@arm.com    cxx_type = 'AddrRange'
7573101Sstever@eecs.umich.edu
7583101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
75910676Sandreas.hansson@arm.com        # Disable interleaving and hashing by default
7609411Sandreas.hansson@arm.com        self.intlvBits = 0
7619411Sandreas.hansson@arm.com        self.intlvMatch = 0
76214049Snikos.nikoleris@arm.com        self.masks = []
7639411Sandreas.hansson@arm.com
7643101Sstever@eecs.umich.edu        def handle_kwargs(self, kwargs):
7659411Sandreas.hansson@arm.com            # An address range needs to have an upper limit, specified
7669411Sandreas.hansson@arm.com            # either explicitly with an end, or as an offset using the
7679411Sandreas.hansson@arm.com            # size keyword.
7683101Sstever@eecs.umich.edu            if 'end' in kwargs:
7699232Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
7703101Sstever@eecs.umich.edu            elif 'size' in kwargs:
7719232Sandreas.hansson@arm.com                self.end = self.start + Addr(kwargs.pop('size')) - 1
7723101Sstever@eecs.umich.edu            else:
77313663Sandreas.sandberg@arm.com                raise TypeError("Either end or size must be specified")
7743101Sstever@eecs.umich.edu
7759411Sandreas.hansson@arm.com            # Now on to the optional bit
7769411Sandreas.hansson@arm.com            if 'intlvMatch' in kwargs:
7779411Sandreas.hansson@arm.com                self.intlvMatch = int(kwargs.pop('intlvMatch'))
7789411Sandreas.hansson@arm.com
77914049Snikos.nikoleris@arm.com            if 'masks' in kwargs:
78014049Snikos.nikoleris@arm.com                self.masks = [ long(x) for x in list(kwargs.pop('masks')) ]
78114049Snikos.nikoleris@arm.com                self.intlvBits = len(self.masks)
78214049Snikos.nikoleris@arm.com            else:
78314049Snikos.nikoleris@arm.com                if 'intlvBits' in kwargs:
78414049Snikos.nikoleris@arm.com                    self.intlvBits = int(kwargs.pop('intlvBits'))
78514049Snikos.nikoleris@arm.com                    self.masks = [0] * self.intlvBits
78614059Snikos.nikoleris@arm.com                    if 'intlvHighBit' not in kwargs:
78714059Snikos.nikoleris@arm.com                        raise TypeError("No interleave bits specified")
78814059Snikos.nikoleris@arm.com                    intlv_high_bit = int(kwargs.pop('intlvHighBit'))
78914059Snikos.nikoleris@arm.com                    xor_high_bit = 0
79014059Snikos.nikoleris@arm.com                    if 'xorHighBit' in kwargs:
79114059Snikos.nikoleris@arm.com                        xor_high_bit = int(kwargs.pop('xorHighBit'))
79214059Snikos.nikoleris@arm.com                    for i in range(0, self.intlvBits):
79314059Snikos.nikoleris@arm.com                        bit1 = intlv_high_bit - i
79414059Snikos.nikoleris@arm.com                        mask = 1 << bit1
79514059Snikos.nikoleris@arm.com                        if xor_high_bit != 0:
79614059Snikos.nikoleris@arm.com                            bit2 = xor_high_bit - i
79714059Snikos.nikoleris@arm.com                            mask |= 1 << bit2
79814059Snikos.nikoleris@arm.com                        self.masks[self.intlvBits - i - 1] = mask
79914049Snikos.nikoleris@arm.com
8003101Sstever@eecs.umich.edu        if len(args) == 0:
8019232Sandreas.hansson@arm.com            self.start = Addr(kwargs.pop('start'))
8023101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
8033101Sstever@eecs.umich.edu
8043101Sstever@eecs.umich.edu        elif len(args) == 1:
8053101Sstever@eecs.umich.edu            if kwargs:
8069232Sandreas.hansson@arm.com                self.start = Addr(args[0])
8073101Sstever@eecs.umich.edu                handle_kwargs(self, kwargs)
8085219Ssaidi@eecs.umich.edu            elif isinstance(args[0], (list, tuple)):
8099232Sandreas.hansson@arm.com                self.start = Addr(args[0][0])
8109232Sandreas.hansson@arm.com                self.end = Addr(args[0][1])
8113101Sstever@eecs.umich.edu            else:
8129232Sandreas.hansson@arm.com                self.start = Addr(0)
8139232Sandreas.hansson@arm.com                self.end = Addr(args[0]) - 1
8143101Sstever@eecs.umich.edu
8153101Sstever@eecs.umich.edu        elif len(args) == 2:
8169232Sandreas.hansson@arm.com            self.start = Addr(args[0])
8179232Sandreas.hansson@arm.com            self.end = Addr(args[1])
8183101Sstever@eecs.umich.edu        else:
81913663Sandreas.sandberg@arm.com            raise TypeError("Too many arguments specified")
8203101Sstever@eecs.umich.edu
8213101Sstever@eecs.umich.edu        if kwargs:
82213663Sandreas.sandberg@arm.com            raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
8233101Sstever@eecs.umich.edu
8243101Sstever@eecs.umich.edu    def __str__(self):
82514049Snikos.nikoleris@arm.com        if len(self.masks) == 0:
82614049Snikos.nikoleris@arm.com            return '%s:%s' % (self.start, self.end)
82714049Snikos.nikoleris@arm.com        else:
82814049Snikos.nikoleris@arm.com            return '%s:%s:%s:%s' % (self.start, self.end, self.intlvMatch,
82914049Snikos.nikoleris@arm.com                                    ':'.join(str(m) for m in self.masks))
8309232Sandreas.hansson@arm.com
8319232Sandreas.hansson@arm.com    def size(self):
8329411Sandreas.hansson@arm.com        # Divide the size by the size of the interleaving slice
8339411Sandreas.hansson@arm.com        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
8343101Sstever@eecs.umich.edu
8357673Snate@binkert.org    @classmethod
8367673Snate@binkert.org    def cxx_predecls(cls, code):
8379232Sandreas.hansson@arm.com        Addr.cxx_predecls(code)
8389235Sandreas.hansson@arm.com        code('#include "base/addr_range.hh"')
8397675Snate@binkert.org
8407675Snate@binkert.org    @classmethod
84111988Sandreas.sandberg@arm.com    def pybind_predecls(cls, code):
84211988Sandreas.sandberg@arm.com        Addr.pybind_predecls(code)
84311988Sandreas.sandberg@arm.com        code('#include "base/addr_range.hh"')
84411988Sandreas.sandberg@arm.com
84511988Sandreas.sandberg@arm.com    @classmethod
84610458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
84710458Sandreas.hansson@arm.com        code('#include <sstream>')
84814049Snikos.nikoleris@arm.com        code('#include <vector>')
84914049Snikos.nikoleris@arm.com        code('#include "base/types.hh"')
85010458Sandreas.hansson@arm.com
85110458Sandreas.hansson@arm.com    @classmethod
85210458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
85314049Snikos.nikoleris@arm.com        code('bool _ret = true;')
85414049Snikos.nikoleris@arm.com        code('uint64_t _start, _end, _intlvMatch = 0;')
85514049Snikos.nikoleris@arm.com        code('std::vector<Addr> _masks;')
85610458Sandreas.hansson@arm.com        code('char _sep;')
85710458Sandreas.hansson@arm.com        code('std::istringstream _stream(${src});')
85810458Sandreas.hansson@arm.com        code('_stream >> _start;')
85910458Sandreas.hansson@arm.com        code('_stream.get(_sep);')
86014049Snikos.nikoleris@arm.com        code('_ret = _sep == \':\';')
86110458Sandreas.hansson@arm.com        code('_stream >> _end;')
86211620SMatthew.Poremba@amd.com        code('if (!_stream.fail() && !_stream.eof()) {')
86311620SMatthew.Poremba@amd.com        code('    _stream.get(_sep);')
86414049Snikos.nikoleris@arm.com        code('    _ret = ret && _sep == \':\';')
86511620SMatthew.Poremba@amd.com        code('    _stream >> _intlvMatch;')
86614049Snikos.nikoleris@arm.com        code('    while (!_stream.fail() && !_stream.eof()) {')
86714049Snikos.nikoleris@arm.com        code('        _stream.get(_sep);')
86814049Snikos.nikoleris@arm.com        code('        _ret = ret && _sep == \':\';')
86914049Snikos.nikoleris@arm.com        code('        Addr mask;')
87014049Snikos.nikoleris@arm.com        code('        _stream >> mask;')
87114049Snikos.nikoleris@arm.com        code('        _masks.push_back(mask);')
87214049Snikos.nikoleris@arm.com        code('    }')
87311620SMatthew.Poremba@amd.com        code('}')
87414049Snikos.nikoleris@arm.com        code('_ret = _ret && !_stream.fail() && _stream.eof();')
87510458Sandreas.hansson@arm.com        code('if (_ret)')
87614049Snikos.nikoleris@arm.com        code('   ${dest} = AddrRange(_start, _end, _masks, _intlvMatch);')
87710458Sandreas.hansson@arm.com        code('${ret} _ret;')
87810458Sandreas.hansson@arm.com
8794762Snate@binkert.org    def getValue(self):
88011991Sandreas.sandberg@arm.com        # Go from the Python class to the wrapped C++ class
88111802Sandreas.sandberg@arm.com        from _m5.range import AddrRange
8824762Snate@binkert.org
8839411Sandreas.hansson@arm.com        return AddrRange(long(self.start), long(self.end),
88414049Snikos.nikoleris@arm.com                         self.masks, int(self.intlvMatch))
8853101Sstever@eecs.umich.edu
8863101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
8873101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and
8883101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
8893101Sstever@eecs.umich.educlass Bool(ParamValue):
8903101Sstever@eecs.umich.edu    cxx_type = 'bool'
89110267SGeoffrey.Blake@arm.com    cmd_line_settable = True
89210267SGeoffrey.Blake@arm.com
8933101Sstever@eecs.umich.edu    def __init__(self, value):
8943101Sstever@eecs.umich.edu        try:
8953102Sstever@eecs.umich.edu            self.value = convert.toBool(value)
8963101Sstever@eecs.umich.edu        except TypeError:
8973101Sstever@eecs.umich.edu            self.value = bool(value)
8983101Sstever@eecs.umich.edu
89910267SGeoffrey.Blake@arm.com    def __call__(self, value):
90010267SGeoffrey.Blake@arm.com        self.__init__(value)
90110267SGeoffrey.Blake@arm.com        return value
90210267SGeoffrey.Blake@arm.com
9034762Snate@binkert.org    def getValue(self):
9044762Snate@binkert.org        return bool(self.value)
9054762Snate@binkert.org
9063101Sstever@eecs.umich.edu    def __str__(self):
9073101Sstever@eecs.umich.edu        return str(self.value)
9083101Sstever@eecs.umich.edu
9098934SBrad.Beckmann@amd.com    # implement truth value testing for Bool parameters so that these params
9108934SBrad.Beckmann@amd.com    # evaluate correctly during the python configuration phase
91113697Sandreas.sandberg@arm.com    def __bool__(self):
9128934SBrad.Beckmann@amd.com        return bool(self.value)
9138934SBrad.Beckmann@amd.com
91413697Sandreas.sandberg@arm.com    # Python 2.7 uses __nonzero__ instead of __bool__
91513697Sandreas.sandberg@arm.com    __nonzero__ = __bool__
91613697Sandreas.sandberg@arm.com
9173101Sstever@eecs.umich.edu    def ini_str(self):
9183101Sstever@eecs.umich.edu        if self.value:
9193101Sstever@eecs.umich.edu            return 'true'
9203101Sstever@eecs.umich.edu        return 'false'
9213101Sstever@eecs.umich.edu
92210380SAndrew.Bardsley@arm.com    def config_value(self):
92310380SAndrew.Bardsley@arm.com        return self.value
92410380SAndrew.Bardsley@arm.com
92510458Sandreas.hansson@arm.com    @classmethod
92610458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
92710458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
92810458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
92910458Sandreas.hansson@arm.com        pass
93010458Sandreas.hansson@arm.com
93110458Sandreas.hansson@arm.com    @classmethod
93210458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
93310458Sandreas.hansson@arm.com        code('%s to_bool(%s, %s);' % (ret, src, dest))
93410458Sandreas.hansson@arm.com
9353101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
93613709Sandreas.sandberg@arm.com    bytes = [ int(x, 16) for x in addr.split(':') ]
9373101Sstever@eecs.umich.edu    bytes[5] += val
9383101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
9393101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
9403101Sstever@eecs.umich.edu        bytes[i] = rem
9413101Sstever@eecs.umich.edu        if val == 0:
9423101Sstever@eecs.umich.edu            break
9433101Sstever@eecs.umich.edu        bytes[i - 1] += val
9443101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
9453101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
9463101Sstever@eecs.umich.edu
9474380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
9484380Sbinkertn@umich.edudef NextEthernetAddr():
9494380Sbinkertn@umich.edu    global _NextEthernetAddr
9503101Sstever@eecs.umich.edu
9514380Sbinkertn@umich.edu    value = _NextEthernetAddr
9524380Sbinkertn@umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
9534380Sbinkertn@umich.edu    return value
9543101Sstever@eecs.umich.edu
9553101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
9563101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
95710267SGeoffrey.Blake@arm.com    ex_str = "00:90:00:00:00:01"
95810267SGeoffrey.Blake@arm.com    cmd_line_settable = True
9597673Snate@binkert.org
9607673Snate@binkert.org    @classmethod
9617673Snate@binkert.org    def cxx_predecls(cls, code):
9627673Snate@binkert.org        code('#include "base/inet.hh"')
9637673Snate@binkert.org
9643101Sstever@eecs.umich.edu    def __init__(self, value):
9653101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
9663101Sstever@eecs.umich.edu            self.value = value
9673101Sstever@eecs.umich.edu            return
9683101Sstever@eecs.umich.edu
9693101Sstever@eecs.umich.edu        if not isinstance(value, str):
97013663Sandreas.sandberg@arm.com            raise TypeError("expected an ethernet address and didn't get one")
9713101Sstever@eecs.umich.edu
9723101Sstever@eecs.umich.edu        bytes = value.split(':')
9733101Sstever@eecs.umich.edu        if len(bytes) != 6:
97413663Sandreas.sandberg@arm.com            raise TypeError('invalid ethernet address %s' % value)
9753101Sstever@eecs.umich.edu
9763101Sstever@eecs.umich.edu        for byte in bytes:
9779941SGeoffrey.Blake@arm.com            if not 0 <= int(byte, base=16) <= 0xff:
97813663Sandreas.sandberg@arm.com                raise TypeError('invalid ethernet address %s' % value)
9793101Sstever@eecs.umich.edu
9803101Sstever@eecs.umich.edu        self.value = value
9813101Sstever@eecs.umich.edu
98210267SGeoffrey.Blake@arm.com    def __call__(self, value):
98310267SGeoffrey.Blake@arm.com        self.__init__(value)
98410267SGeoffrey.Blake@arm.com        return value
98510267SGeoffrey.Blake@arm.com
9863101Sstever@eecs.umich.edu    def unproxy(self, base):
9873101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
9884380Sbinkertn@umich.edu            return EthernetAddr(self.value())
9893101Sstever@eecs.umich.edu        return self
9903101Sstever@eecs.umich.edu
9914762Snate@binkert.org    def getValue(self):
99211988Sandreas.sandberg@arm.com        from _m5.net import EthAddr
9934762Snate@binkert.org        return EthAddr(self.value)
9944762Snate@binkert.org
99511228SAndrew.Bardsley@arm.com    def __str__(self):
99611228SAndrew.Bardsley@arm.com        return self.value
99711228SAndrew.Bardsley@arm.com
9984380Sbinkertn@umich.edu    def ini_str(self):
9994380Sbinkertn@umich.edu        return self.value
10003101Sstever@eecs.umich.edu
100110458Sandreas.hansson@arm.com    @classmethod
100210458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
100310458Sandreas.hansson@arm.com        code('%s = Net::EthAddr(%s);' % (dest, src))
100410458Sandreas.hansson@arm.com        code('%s true;' % ret)
100510458Sandreas.hansson@arm.com
10067777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
10077777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
10087777Sgblack@eecs.umich.educlass IpAddress(ParamValue):
10097777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpAddress'
101010267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1"
101110267SGeoffrey.Blake@arm.com    cmd_line_settable = True
10127777Sgblack@eecs.umich.edu
10137777Sgblack@eecs.umich.edu    @classmethod
10147777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10157777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10167777Sgblack@eecs.umich.edu
10177777Sgblack@eecs.umich.edu    def __init__(self, value):
10187777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
10197777Sgblack@eecs.umich.edu            self.ip = value.ip
10207777Sgblack@eecs.umich.edu        else:
10217777Sgblack@eecs.umich.edu            try:
10227777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
10237777Sgblack@eecs.umich.edu            except TypeError:
10247777Sgblack@eecs.umich.edu                self.ip = long(value)
10257777Sgblack@eecs.umich.edu        self.verifyIp()
10267777Sgblack@eecs.umich.edu
102710267SGeoffrey.Blake@arm.com    def __call__(self, value):
102810267SGeoffrey.Blake@arm.com        self.__init__(value)
102910267SGeoffrey.Blake@arm.com        return value
103010267SGeoffrey.Blake@arm.com
10318579Ssteve.reinhardt@amd.com    def __str__(self):
10328579Ssteve.reinhardt@amd.com        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
10338579Ssteve.reinhardt@amd.com        return '%d.%d.%d.%d' % tuple(tup)
10348579Ssteve.reinhardt@amd.com
10358579Ssteve.reinhardt@amd.com    def __eq__(self, other):
10368579Ssteve.reinhardt@amd.com        if isinstance(other, IpAddress):
10378579Ssteve.reinhardt@amd.com            return self.ip == other.ip
10388579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
10398579Ssteve.reinhardt@amd.com            try:
10408579Ssteve.reinhardt@amd.com                return self.ip == convert.toIpAddress(other)
10418579Ssteve.reinhardt@amd.com            except:
10428579Ssteve.reinhardt@amd.com                return False
10438579Ssteve.reinhardt@amd.com        else:
10448579Ssteve.reinhardt@amd.com            return self.ip == other
10458579Ssteve.reinhardt@amd.com
10468579Ssteve.reinhardt@amd.com    def __ne__(self, other):
10478579Ssteve.reinhardt@amd.com        return not (self == other)
10488579Ssteve.reinhardt@amd.com
10497777Sgblack@eecs.umich.edu    def verifyIp(self):
10507777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
105113663Sandreas.sandberg@arm.com            raise TypeError("invalid ip address %#08x" % self.ip)
10527777Sgblack@eecs.umich.edu
10537777Sgblack@eecs.umich.edu    def getValue(self):
105411988Sandreas.sandberg@arm.com        from _m5.net import IpAddress
10557777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
10567777Sgblack@eecs.umich.edu
10577777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
10587777Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
10597777Sgblack@eecs.umich.edu# positional or keyword arguments.
10607777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
10617777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
106210267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.0/24"
106310267SGeoffrey.Blake@arm.com    cmd_line_settable = True
10647777Sgblack@eecs.umich.edu
10657777Sgblack@eecs.umich.edu    @classmethod
10667777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10677777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10687777Sgblack@eecs.umich.edu
10697777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10707777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10717777Sgblack@eecs.umich.edu            if key in kwargs:
10727777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10737777Sgblack@eecs.umich.edu            elif elseVal:
10747777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10757777Sgblack@eecs.umich.edu            else:
107613663Sandreas.sandberg@arm.com                raise TypeError("No value set for %s" % key)
10777777Sgblack@eecs.umich.edu
10787777Sgblack@eecs.umich.edu        if len(args) == 0:
10797777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
10807777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
10817777Sgblack@eecs.umich.edu
10827777Sgblack@eecs.umich.edu        elif len(args) == 1:
10837777Sgblack@eecs.umich.edu            if kwargs:
10847777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
108513663Sandreas.sandberg@arm.com                    raise TypeError("Invalid arguments")
10867777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
10877777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
10887777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
10897777Sgblack@eecs.umich.edu                self.ip = args[0].ip
10907777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
10917777Sgblack@eecs.umich.edu            else:
10927777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
10937777Sgblack@eecs.umich.edu
10947777Sgblack@eecs.umich.edu        elif len(args) == 2:
10957777Sgblack@eecs.umich.edu            self.ip = args[0]
10967777Sgblack@eecs.umich.edu            self.netmask = args[1]
10977777Sgblack@eecs.umich.edu        else:
109813663Sandreas.sandberg@arm.com            raise TypeError("Too many arguments specified")
10997777Sgblack@eecs.umich.edu
11007777Sgblack@eecs.umich.edu        if kwargs:
110113663Sandreas.sandberg@arm.com            raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
11027777Sgblack@eecs.umich.edu
11037777Sgblack@eecs.umich.edu        self.verify()
11047777Sgblack@eecs.umich.edu
110510267SGeoffrey.Blake@arm.com    def __call__(self, value):
110610267SGeoffrey.Blake@arm.com        self.__init__(value)
110710267SGeoffrey.Blake@arm.com        return value
110810267SGeoffrey.Blake@arm.com
11098579Ssteve.reinhardt@amd.com    def __str__(self):
11108579Ssteve.reinhardt@amd.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
11118579Ssteve.reinhardt@amd.com
11128579Ssteve.reinhardt@amd.com    def __eq__(self, other):
11138579Ssteve.reinhardt@amd.com        if isinstance(other, IpNetmask):
11148579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.netmask == other.netmask
11158579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
11168579Ssteve.reinhardt@amd.com            try:
11178579Ssteve.reinhardt@amd.com                return (self.ip, self.netmask) == convert.toIpNetmask(other)
11188579Ssteve.reinhardt@amd.com            except:
11198579Ssteve.reinhardt@amd.com                return False
11208579Ssteve.reinhardt@amd.com        else:
11218579Ssteve.reinhardt@amd.com            return False
11228579Ssteve.reinhardt@amd.com
11237777Sgblack@eecs.umich.edu    def verify(self):
11247777Sgblack@eecs.umich.edu        self.verifyIp()
11257777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
112613663Sandreas.sandberg@arm.com            raise TypeError("invalid netmask %d" % netmask)
11277777Sgblack@eecs.umich.edu
11287777Sgblack@eecs.umich.edu    def getValue(self):
112911988Sandreas.sandberg@arm.com        from _m5.net import IpNetmask
11307777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
11317777Sgblack@eecs.umich.edu
11327777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
11337777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
11347777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
11357777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
113610267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1:80"
113710267SGeoffrey.Blake@arm.com    cmd_line_settable = True
11387777Sgblack@eecs.umich.edu
11397777Sgblack@eecs.umich.edu    @classmethod
11407777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
11417777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
11427777Sgblack@eecs.umich.edu
11437777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
11447777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
11457777Sgblack@eecs.umich.edu            if key in kwargs:
11467777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
11477777Sgblack@eecs.umich.edu            elif elseVal:
11487777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
11497777Sgblack@eecs.umich.edu            else:
115013663Sandreas.sandberg@arm.com                raise TypeError("No value set for %s" % key)
11517777Sgblack@eecs.umich.edu
11527777Sgblack@eecs.umich.edu        if len(args) == 0:
11537777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
11547777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
11557777Sgblack@eecs.umich.edu
11567777Sgblack@eecs.umich.edu        elif len(args) == 1:
11577777Sgblack@eecs.umich.edu            if kwargs:
11587777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
115913663Sandreas.sandberg@arm.com                    raise TypeError("Invalid arguments")
11607777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
11617777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
11627777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpWithPort):
11637777Sgblack@eecs.umich.edu                self.ip = args[0].ip
11647777Sgblack@eecs.umich.edu                self.port = args[0].port
11657777Sgblack@eecs.umich.edu            else:
11667777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
11677777Sgblack@eecs.umich.edu
11687777Sgblack@eecs.umich.edu        elif len(args) == 2:
11697777Sgblack@eecs.umich.edu            self.ip = args[0]
11707777Sgblack@eecs.umich.edu            self.port = args[1]
11717777Sgblack@eecs.umich.edu        else:
117213663Sandreas.sandberg@arm.com            raise TypeError("Too many arguments specified")
11737777Sgblack@eecs.umich.edu
11747777Sgblack@eecs.umich.edu        if kwargs:
117513663Sandreas.sandberg@arm.com            raise TypeError("Too many keywords: %s" % list(kwargs.keys()))
11767777Sgblack@eecs.umich.edu
11777777Sgblack@eecs.umich.edu        self.verify()
11787777Sgblack@eecs.umich.edu
117910267SGeoffrey.Blake@arm.com    def __call__(self, value):
118010267SGeoffrey.Blake@arm.com        self.__init__(value)
118110267SGeoffrey.Blake@arm.com        return value
118210267SGeoffrey.Blake@arm.com
11838579Ssteve.reinhardt@amd.com    def __str__(self):
11848579Ssteve.reinhardt@amd.com        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
11858579Ssteve.reinhardt@amd.com
11868579Ssteve.reinhardt@amd.com    def __eq__(self, other):
11878579Ssteve.reinhardt@amd.com        if isinstance(other, IpWithPort):
11888579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.port == other.port
11898579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
11908579Ssteve.reinhardt@amd.com            try:
11918579Ssteve.reinhardt@amd.com                return (self.ip, self.port) == convert.toIpWithPort(other)
11928579Ssteve.reinhardt@amd.com            except:
11938579Ssteve.reinhardt@amd.com                return False
11948579Ssteve.reinhardt@amd.com        else:
11958579Ssteve.reinhardt@amd.com            return False
11968579Ssteve.reinhardt@amd.com
11977777Sgblack@eecs.umich.edu    def verify(self):
11987777Sgblack@eecs.umich.edu        self.verifyIp()
11997777Sgblack@eecs.umich.edu        if self.port < 0 or self.port > 0xffff:
120013663Sandreas.sandberg@arm.com            raise TypeError("invalid port %d" % self.port)
12017777Sgblack@eecs.umich.edu
12027777Sgblack@eecs.umich.edu    def getValue(self):
120311988Sandreas.sandberg@arm.com        from _m5.net import IpWithPort
12047777Sgblack@eecs.umich.edu        return IpWithPort(self.ip, self.port)
12057777Sgblack@eecs.umich.edu
12063932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
120710380SAndrew.Bardsley@arm.com                 "%a %b %d %H:%M:%S %Y",
12083932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
12093932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
12103932Sbinkertn@umich.edu                 "%Y/%m/%d",
12113932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
12123932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
12133932Sbinkertn@umich.edu                 "%m/%d/%Y",
12143932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M:%S",
12153932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M",
12163932Sbinkertn@umich.edu                 "%m/%d/%y"]
12173932Sbinkertn@umich.edu
12183932Sbinkertn@umich.edu
12193885Sbinkertn@umich.edudef parse_time(value):
12203932Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
12213932Sbinkertn@umich.edu    from datetime import datetime, date
12223885Sbinkertn@umich.edu
12233932Sbinkertn@umich.edu    if isinstance(value, struct_time):
12243932Sbinkertn@umich.edu        return value
12253932Sbinkertn@umich.edu
12263932Sbinkertn@umich.edu    if isinstance(value, (int, long)):
12273932Sbinkertn@umich.edu        return gmtime(value)
12283932Sbinkertn@umich.edu
12293932Sbinkertn@umich.edu    if isinstance(value, (datetime, date)):
12303932Sbinkertn@umich.edu        return value.timetuple()
12313932Sbinkertn@umich.edu
12323932Sbinkertn@umich.edu    if isinstance(value, str):
12333932Sbinkertn@umich.edu        if value in ('Now', 'Today'):
12343932Sbinkertn@umich.edu            return time.gmtime(time.time())
12353932Sbinkertn@umich.edu
12363932Sbinkertn@umich.edu        for format in time_formats:
12373932Sbinkertn@umich.edu            try:
12383932Sbinkertn@umich.edu                return strptime(value, format)
12393932Sbinkertn@umich.edu            except ValueError:
12403932Sbinkertn@umich.edu                pass
12413885Sbinkertn@umich.edu
124213663Sandreas.sandberg@arm.com    raise ValueError("Could not parse '%s' as a time" % value)
12433885Sbinkertn@umich.edu
12443885Sbinkertn@umich.educlass Time(ParamValue):
12454762Snate@binkert.org    cxx_type = 'tm'
12467673Snate@binkert.org
12477673Snate@binkert.org    @classmethod
12487673Snate@binkert.org    def cxx_predecls(cls, code):
12497673Snate@binkert.org        code('#include <time.h>')
12507673Snate@binkert.org
12513885Sbinkertn@umich.edu    def __init__(self, value):
12523932Sbinkertn@umich.edu        self.value = parse_time(value)
12533885Sbinkertn@umich.edu
125410267SGeoffrey.Blake@arm.com    def __call__(self, value):
125510267SGeoffrey.Blake@arm.com        self.__init__(value)
125610267SGeoffrey.Blake@arm.com        return value
125710267SGeoffrey.Blake@arm.com
12584762Snate@binkert.org    def getValue(self):
125911988Sandreas.sandberg@arm.com        from _m5.core import tm
126011988Sandreas.sandberg@arm.com        import calendar
12614762Snate@binkert.org
126211988Sandreas.sandberg@arm.com        return tm.gmtime(calendar.timegm(self.value))
12634762Snate@binkert.org
12643885Sbinkertn@umich.edu    def __str__(self):
12654762Snate@binkert.org        return time.asctime(self.value)
12663885Sbinkertn@umich.edu
12673885Sbinkertn@umich.edu    def ini_str(self):
12683932Sbinkertn@umich.edu        return str(self)
12693885Sbinkertn@umich.edu
12708664SAli.Saidi@ARM.com    def get_config_as_dict(self):
127110380SAndrew.Bardsley@arm.com        assert false
12728664SAli.Saidi@ARM.com        return str(self)
12738664SAli.Saidi@ARM.com
127410458Sandreas.hansson@arm.com    @classmethod
127510458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
127610458Sandreas.hansson@arm.com        code('#include <time.h>')
127710458Sandreas.hansson@arm.com
127810458Sandreas.hansson@arm.com    @classmethod
127910458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
128010458Sandreas.hansson@arm.com        code('char *_parse_ret = strptime((${src}).c_str(),')
128110458Sandreas.hansson@arm.com        code('    "%a %b %d %H:%M:%S %Y", &(${dest}));')
128210458Sandreas.hansson@arm.com        code('${ret} _parse_ret && *_parse_ret == \'\\0\';');
128310458Sandreas.hansson@arm.com
12843101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
12853101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
12863101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
12873101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
12883101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
12893101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
12903101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
12913101Sstever@eecs.umich.edu
12923101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
12933101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
12943101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
12953101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
12963101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
12973101Sstever@eecs.umich.edu
12984762Snate@binkert.orgallEnums = {}
12993101Sstever@eecs.umich.edu# Metaclass for Enum types
13005033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue):
13014762Snate@binkert.org    def __new__(mcls, name, bases, dict):
13024762Snate@binkert.org        assert name not in allEnums
13034762Snate@binkert.org
13044762Snate@binkert.org        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
13054762Snate@binkert.org        allEnums[name] = cls
13064762Snate@binkert.org        return cls
13074762Snate@binkert.org
13083101Sstever@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
130913675Sandreas.sandberg@arm.com        if 'map' in init_dict:
13103101Sstever@eecs.umich.edu            if not isinstance(cls.map, dict):
131113663Sandreas.sandberg@arm.com                raise TypeError("Enum-derived class attribute 'map' " \
131213663Sandreas.sandberg@arm.com                      "must be of type dict")
13133101Sstever@eecs.umich.edu            # build list of value strings from map
131413709Sandreas.sandberg@arm.com            cls.vals = list(cls.map.keys())
13153101Sstever@eecs.umich.edu            cls.vals.sort()
131613675Sandreas.sandberg@arm.com        elif 'vals' in init_dict:
13173101Sstever@eecs.umich.edu            if not isinstance(cls.vals, list):
131813663Sandreas.sandberg@arm.com                raise TypeError("Enum-derived class attribute 'vals' " \
131913663Sandreas.sandberg@arm.com                      "must be of type list")
13203101Sstever@eecs.umich.edu            # build string->value map from vals sequence
13213101Sstever@eecs.umich.edu            cls.map = {}
13223101Sstever@eecs.umich.edu            for idx,val in enumerate(cls.vals):
13233101Sstever@eecs.umich.edu                cls.map[val] = idx
13243101Sstever@eecs.umich.edu        else:
132513663Sandreas.sandberg@arm.com            raise TypeError("Enum-derived class must define "\
132613663Sandreas.sandberg@arm.com                  "attribute 'map' or 'vals'")
13273101Sstever@eecs.umich.edu
132813558Snikos.nikoleris@arm.com        if cls.is_class:
132913558Snikos.nikoleris@arm.com            cls.cxx_type = '%s' % name
133013558Snikos.nikoleris@arm.com        else:
133113558Snikos.nikoleris@arm.com            cls.cxx_type = 'Enums::%s' % name
13323101Sstever@eecs.umich.edu
13333101Sstever@eecs.umich.edu        super(MetaEnum, cls).__init__(name, bases, init_dict)
13343101Sstever@eecs.umich.edu
13353101Sstever@eecs.umich.edu    # Generate C++ class declaration for this enum type.
13363101Sstever@eecs.umich.edu    # Note that we wrap the enum in a class/struct to act as a namespace,
13373101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
13387673Snate@binkert.org    def cxx_decl(cls, code):
133910201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
134010201SAndrew.Bardsley@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
134110201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
134210201SAndrew.Bardsley@arm.com        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
134310201SAndrew.Bardsley@arm.com
13447673Snate@binkert.org        code('''\
134510201SAndrew.Bardsley@arm.com#ifndef $idem_macro
134610201SAndrew.Bardsley@arm.com#define $idem_macro
13477673Snate@binkert.org
134813558Snikos.nikoleris@arm.com''')
134913558Snikos.nikoleris@arm.com        if cls.is_class:
135013558Snikos.nikoleris@arm.com            code('''\
135113558Snikos.nikoleris@arm.comenum class $name {
135213558Snikos.nikoleris@arm.com''')
135313558Snikos.nikoleris@arm.com        else:
135413558Snikos.nikoleris@arm.com            code('''\
135510201SAndrew.Bardsley@arm.com$wrapper $wrapper_name {
13567673Snate@binkert.org    enum $name {
13577673Snate@binkert.org''')
135813558Snikos.nikoleris@arm.com            code.indent(1)
135913558Snikos.nikoleris@arm.com        code.indent(1)
13604762Snate@binkert.org        for val in cls.vals:
13617673Snate@binkert.org            code('$val = ${{cls.map[val]}},')
13628902Sandreas.hansson@arm.com        code('Num_$name = ${{len(cls.vals)}}')
136313558Snikos.nikoleris@arm.com        code.dedent(1)
136413558Snikos.nikoleris@arm.com        code('};')
13654762Snate@binkert.org
136613558Snikos.nikoleris@arm.com        if cls.is_class:
136713558Snikos.nikoleris@arm.com            code('''\
136813558Snikos.nikoleris@arm.comextern const char *${name}Strings[static_cast<int>(${name}::Num_${name})];
136913558Snikos.nikoleris@arm.com''')
137013558Snikos.nikoleris@arm.com        elif cls.wrapper_is_struct:
137113558Snikos.nikoleris@arm.com            code('static const char *${name}Strings[Num_${name}];')
137210201SAndrew.Bardsley@arm.com        else:
137310201SAndrew.Bardsley@arm.com            code('extern const char *${name}Strings[Num_${name}];')
137413558Snikos.nikoleris@arm.com
137513558Snikos.nikoleris@arm.com        if not cls.is_class:
137613558Snikos.nikoleris@arm.com            code.dedent(1)
137713558Snikos.nikoleris@arm.com            code('};')
137810201SAndrew.Bardsley@arm.com
137910201SAndrew.Bardsley@arm.com        code()
138010201SAndrew.Bardsley@arm.com        code('#endif // $idem_macro')
13817673Snate@binkert.org
13827673Snate@binkert.org    def cxx_def(cls, code):
138310201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
138410201SAndrew.Bardsley@arm.com        file_name = cls.__name__
138510201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
138610201SAndrew.Bardsley@arm.com
138710201SAndrew.Bardsley@arm.com        code('#include "enums/$file_name.hh"')
138810201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
138910201SAndrew.Bardsley@arm.com            code('const char *${wrapper_name}::${name}Strings'
139010201SAndrew.Bardsley@arm.com                '[Num_${name}] =')
139110201SAndrew.Bardsley@arm.com        else:
139213558Snikos.nikoleris@arm.com            if cls.is_class:
139313558Snikos.nikoleris@arm.com                code('''\
139413558Snikos.nikoleris@arm.comconst char *${name}Strings[static_cast<int>(${name}::Num_${name})] =
139513558Snikos.nikoleris@arm.com''')
139613558Snikos.nikoleris@arm.com            else:
139713558Snikos.nikoleris@arm.com                code('namespace Enums {')
139813558Snikos.nikoleris@arm.com                code.indent(1)
139913558Snikos.nikoleris@arm.com                code('const char *${name}Strings[Num_${name}] =')
140010201SAndrew.Bardsley@arm.com
140110201SAndrew.Bardsley@arm.com        code('{')
140210201SAndrew.Bardsley@arm.com        code.indent(1)
14034762Snate@binkert.org        for val in cls.vals:
14047673Snate@binkert.org            code('"$val",')
140510201SAndrew.Bardsley@arm.com        code.dedent(1)
140610201SAndrew.Bardsley@arm.com        code('};')
140710201SAndrew.Bardsley@arm.com
140813558Snikos.nikoleris@arm.com        if not cls.wrapper_is_struct and not cls.is_class:
140913558Snikos.nikoleris@arm.com            code.dedent(1)
141010201SAndrew.Bardsley@arm.com            code('} // namespace $wrapper_name')
141113558Snikos.nikoleris@arm.com
14123101Sstever@eecs.umich.edu
141311988Sandreas.sandberg@arm.com    def pybind_def(cls, code):
141411988Sandreas.sandberg@arm.com        name = cls.__name__
141511988Sandreas.sandberg@arm.com        enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name
141613558Snikos.nikoleris@arm.com        wrapper_name = enum_name if cls.is_class else cls.wrapper_name
141711988Sandreas.sandberg@arm.com
141811988Sandreas.sandberg@arm.com        code('''#include "pybind11/pybind11.h"
141911988Sandreas.sandberg@arm.com#include "pybind11/stl.h"
142011988Sandreas.sandberg@arm.com
142111988Sandreas.sandberg@arm.com#include <sim/init.hh>
142211988Sandreas.sandberg@arm.com
142311988Sandreas.sandberg@arm.comnamespace py = pybind11;
142411988Sandreas.sandberg@arm.com
142511988Sandreas.sandberg@arm.comstatic void
142611988Sandreas.sandberg@arm.commodule_init(py::module &m_internal)
142711988Sandreas.sandberg@arm.com{
142811988Sandreas.sandberg@arm.com    py::module m = m_internal.def_submodule("enum_${name}");
142911988Sandreas.sandberg@arm.com
143011988Sandreas.sandberg@arm.com''')
143113558Snikos.nikoleris@arm.com        if cls.is_class:
143213558Snikos.nikoleris@arm.com            code('py::enum_<${enum_name}>(m, "enum_${name}")')
143313558Snikos.nikoleris@arm.com        else:
143413558Snikos.nikoleris@arm.com            code('py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")')
143511988Sandreas.sandberg@arm.com
143611988Sandreas.sandberg@arm.com        code.indent()
143711988Sandreas.sandberg@arm.com        code.indent()
143811988Sandreas.sandberg@arm.com        for val in cls.vals:
143911988Sandreas.sandberg@arm.com            code('.value("${val}", ${wrapper_name}::${val})')
144011988Sandreas.sandberg@arm.com        code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})')
144111988Sandreas.sandberg@arm.com        code('.export_values()')
144211988Sandreas.sandberg@arm.com        code(';')
144311988Sandreas.sandberg@arm.com        code.dedent()
144411988Sandreas.sandberg@arm.com
144511988Sandreas.sandberg@arm.com        code('}')
144611988Sandreas.sandberg@arm.com        code.dedent()
144711988Sandreas.sandberg@arm.com        code()
144811988Sandreas.sandberg@arm.com        code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);')
144911988Sandreas.sandberg@arm.com
14508596Ssteve.reinhardt@amd.com
14513101Sstever@eecs.umich.edu# Base class for enum types.
14523101Sstever@eecs.umich.educlass Enum(ParamValue):
14533101Sstever@eecs.umich.edu    __metaclass__ = MetaEnum
14543101Sstever@eecs.umich.edu    vals = []
145510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
14563101Sstever@eecs.umich.edu
145710201SAndrew.Bardsley@arm.com    # The name of the wrapping namespace or struct
145810201SAndrew.Bardsley@arm.com    wrapper_name = 'Enums'
145910201SAndrew.Bardsley@arm.com
146010201SAndrew.Bardsley@arm.com    # If true, the enum is wrapped in a struct rather than a namespace
146110201SAndrew.Bardsley@arm.com    wrapper_is_struct = False
146210201SAndrew.Bardsley@arm.com
146313558Snikos.nikoleris@arm.com    is_class = False
146413558Snikos.nikoleris@arm.com
146510201SAndrew.Bardsley@arm.com    # If not None, use this as the enum name rather than this class name
146610201SAndrew.Bardsley@arm.com    enum_name = None
146710201SAndrew.Bardsley@arm.com
14683101Sstever@eecs.umich.edu    def __init__(self, value):
14693101Sstever@eecs.umich.edu        if value not in self.map:
147013663Sandreas.sandberg@arm.com            raise TypeError("Enum param got bad value '%s' (not in %s)" \
147113663Sandreas.sandberg@arm.com                  % (value, self.vals))
14723101Sstever@eecs.umich.edu        self.value = value
14733101Sstever@eecs.umich.edu
147410267SGeoffrey.Blake@arm.com    def __call__(self, value):
147510267SGeoffrey.Blake@arm.com        self.__init__(value)
147610267SGeoffrey.Blake@arm.com        return value
147710267SGeoffrey.Blake@arm.com
14787675Snate@binkert.org    @classmethod
14797675Snate@binkert.org    def cxx_predecls(cls, code):
14807675Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
14817675Snate@binkert.org
14827675Snate@binkert.org    @classmethod
148310458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
148410458Sandreas.hansson@arm.com        code('if (false) {')
148513709Sandreas.sandberg@arm.com        for elem_name in cls.map.keys():
148610458Sandreas.hansson@arm.com            code('} else if (%s == "%s") {' % (src, elem_name))
148710458Sandreas.hansson@arm.com            code.indent()
148814052Snikos.nikoleris@arm.com            name = cls.__name__ if cls.enum_name is None else cls.enum_name
148914052Snikos.nikoleris@arm.com            code('%s = %s::%s;' % (dest, name if cls.is_class else 'Enums',
149014052Snikos.nikoleris@arm.com                                   elem_name))
149110458Sandreas.hansson@arm.com            code('%s true;' % ret)
149210458Sandreas.hansson@arm.com            code.dedent()
149310458Sandreas.hansson@arm.com        code('} else {')
149410458Sandreas.hansson@arm.com        code('    %s false;' % ret)
149510458Sandreas.hansson@arm.com        code('}')
149610458Sandreas.hansson@arm.com
14974762Snate@binkert.org    def getValue(self):
149811988Sandreas.sandberg@arm.com        import m5.internal.params
149911988Sandreas.sandberg@arm.com        e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__)
150011988Sandreas.sandberg@arm.com        return e(self.map[self.value])
15014762Snate@binkert.org
15023101Sstever@eecs.umich.edu    def __str__(self):
15033101Sstever@eecs.umich.edu        return self.value
15043101Sstever@eecs.umich.edu
150513558Snikos.nikoleris@arm.com# This param will generate a scoped c++ enum and its python bindings.
150613558Snikos.nikoleris@arm.comclass ScopedEnum(Enum):
150713558Snikos.nikoleris@arm.com    __metaclass__ = MetaEnum
150813558Snikos.nikoleris@arm.com    vals = []
150913558Snikos.nikoleris@arm.com    cmd_line_settable = True
151013558Snikos.nikoleris@arm.com
151113558Snikos.nikoleris@arm.com    # The name of the wrapping namespace or struct
151213558Snikos.nikoleris@arm.com    wrapper_name = None
151313558Snikos.nikoleris@arm.com
151413558Snikos.nikoleris@arm.com    # If true, the enum is wrapped in a struct rather than a namespace
151513558Snikos.nikoleris@arm.com    wrapper_is_struct = False
151613558Snikos.nikoleris@arm.com
151713558Snikos.nikoleris@arm.com    # If true, the generated enum is a scoped enum
151813558Snikos.nikoleris@arm.com    is_class = True
151913558Snikos.nikoleris@arm.com
152013558Snikos.nikoleris@arm.com    # If not None, use this as the enum name rather than this class name
152113558Snikos.nikoleris@arm.com    enum_name = None
152213558Snikos.nikoleris@arm.com
15233101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it?
15243101Sstever@eecs.umich.edufrequency_tolerance = 0.001  # 0.1%
15253101Sstever@eecs.umich.edu
15264167Sbinkertn@umich.educlass TickParamValue(NumericParamValue):
15273101Sstever@eecs.umich.edu    cxx_type = 'Tick'
152810267SGeoffrey.Blake@arm.com    ex_str = "1MHz"
152910267SGeoffrey.Blake@arm.com    cmd_line_settable = True
15307673Snate@binkert.org
15317673Snate@binkert.org    @classmethod
15327673Snate@binkert.org    def cxx_predecls(cls, code):
15337673Snate@binkert.org        code('#include "base/types.hh"')
15347673Snate@binkert.org
153510267SGeoffrey.Blake@arm.com    def __call__(self, value):
153610267SGeoffrey.Blake@arm.com        self.__init__(value)
153710267SGeoffrey.Blake@arm.com        return value
153810267SGeoffrey.Blake@arm.com
15394762Snate@binkert.org    def getValue(self):
15404762Snate@binkert.org        return long(self.value)
15414762Snate@binkert.org
154210458Sandreas.hansson@arm.com    @classmethod
154310458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
154410458Sandreas.hansson@arm.com        code('#include <sstream>')
154510458Sandreas.hansson@arm.com
154610458Sandreas.hansson@arm.com    # Ticks are expressed in seconds in JSON files and in plain
154710458Sandreas.hansson@arm.com    # Ticks in .ini files.  Switch based on a config flag
154810458Sandreas.hansson@arm.com    @classmethod
154910458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
155010458Sandreas.hansson@arm.com        code('${ret} to_number(${src}, ${dest});')
155110458Sandreas.hansson@arm.com
15524167Sbinkertn@umich.educlass Latency(TickParamValue):
155310267SGeoffrey.Blake@arm.com    ex_str = "100ns"
155410267SGeoffrey.Blake@arm.com
15553101Sstever@eecs.umich.edu    def __init__(self, value):
15564167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
15574167Sbinkertn@umich.edu            self.ticks = value.ticks
15584167Sbinkertn@umich.edu            self.value = value.value
15594167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
15604167Sbinkertn@umich.edu            self.ticks = value.ticks
15614167Sbinkertn@umich.edu            self.value = 1.0 / value.value
15624167Sbinkertn@umich.edu        elif value.endswith('t'):
15634167Sbinkertn@umich.edu            self.ticks = True
15644167Sbinkertn@umich.edu            self.value = int(value[:-1])
15654167Sbinkertn@umich.edu        else:
15664167Sbinkertn@umich.edu            self.ticks = False
15674167Sbinkertn@umich.edu            self.value = convert.toLatency(value)
15683101Sstever@eecs.umich.edu
156910267SGeoffrey.Blake@arm.com    def __call__(self, value):
157010267SGeoffrey.Blake@arm.com        self.__init__(value)
157110267SGeoffrey.Blake@arm.com        return value
157210267SGeoffrey.Blake@arm.com
15733101Sstever@eecs.umich.edu    def __getattr__(self, attr):
15743101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
15753101Sstever@eecs.umich.edu            return self
15763101Sstever@eecs.umich.edu        if attr == 'frequency':
15773101Sstever@eecs.umich.edu            return Frequency(self)
157813663Sandreas.sandberg@arm.com        raise AttributeError("Latency object has no attribute '%s'" % attr)
15793101Sstever@eecs.umich.edu
15804762Snate@binkert.org    def getValue(self):
15814762Snate@binkert.org        if self.ticks or self.value == 0:
15824762Snate@binkert.org            value = self.value
15834762Snate@binkert.org        else:
15844762Snate@binkert.org            value = ticks.fromSeconds(self.value)
15854762Snate@binkert.org        return long(value)
15864762Snate@binkert.org
158710380SAndrew.Bardsley@arm.com    def config_value(self):
158810380SAndrew.Bardsley@arm.com        return self.getValue()
158910380SAndrew.Bardsley@arm.com
15903101Sstever@eecs.umich.edu    # convert latency to ticks
15913101Sstever@eecs.umich.edu    def ini_str(self):
15924762Snate@binkert.org        return '%d' % self.getValue()
15933101Sstever@eecs.umich.edu
15944167Sbinkertn@umich.educlass Frequency(TickParamValue):
159510267SGeoffrey.Blake@arm.com    ex_str = "1GHz"
159610267SGeoffrey.Blake@arm.com
15973101Sstever@eecs.umich.edu    def __init__(self, value):
15984167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
15994167Sbinkertn@umich.edu            if value.value == 0:
16004167Sbinkertn@umich.edu                self.value = 0
16014167Sbinkertn@umich.edu            else:
16024167Sbinkertn@umich.edu                self.value = 1.0 / value.value
16034167Sbinkertn@umich.edu            self.ticks = value.ticks
16044167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
16054167Sbinkertn@umich.edu            self.value = value.value
16064167Sbinkertn@umich.edu            self.ticks = value.ticks
16074167Sbinkertn@umich.edu        else:
16084167Sbinkertn@umich.edu            self.ticks = False
16094167Sbinkertn@umich.edu            self.value = convert.toFrequency(value)
16103101Sstever@eecs.umich.edu
161110267SGeoffrey.Blake@arm.com    def __call__(self, value):
161210267SGeoffrey.Blake@arm.com        self.__init__(value)
161310267SGeoffrey.Blake@arm.com        return value
161410267SGeoffrey.Blake@arm.com
16153101Sstever@eecs.umich.edu    def __getattr__(self, attr):
16163101Sstever@eecs.umich.edu        if attr == 'frequency':
16173101Sstever@eecs.umich.edu            return self
16183101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
16193101Sstever@eecs.umich.edu            return Latency(self)
162013663Sandreas.sandberg@arm.com        raise AttributeError("Frequency object has no attribute '%s'" % attr)
16213101Sstever@eecs.umich.edu
16224167Sbinkertn@umich.edu    # convert latency to ticks
16234762Snate@binkert.org    def getValue(self):
16244762Snate@binkert.org        if self.ticks or self.value == 0:
16254762Snate@binkert.org            value = self.value
16264762Snate@binkert.org        else:
16274762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
16284762Snate@binkert.org        return long(value)
16294762Snate@binkert.org
163010380SAndrew.Bardsley@arm.com    def config_value(self):
163110380SAndrew.Bardsley@arm.com        return self.getValue()
163210380SAndrew.Bardsley@arm.com
16333101Sstever@eecs.umich.edu    def ini_str(self):
16344762Snate@binkert.org        return '%d' % self.getValue()
16353101Sstever@eecs.umich.edu
163610019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a
163710019Sandreas.hansson@arm.com# latency, just like Latency and Frequency.
163810019Sandreas.hansson@arm.comclass Clock(TickParamValue):
16393101Sstever@eecs.umich.edu    def __init__(self, value):
16404167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
16414167Sbinkertn@umich.edu            self.ticks = value.ticks
16424167Sbinkertn@umich.edu            self.value = value.value
16434167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
16444167Sbinkertn@umich.edu            self.ticks = value.ticks
16454167Sbinkertn@umich.edu            self.value = 1.0 / value.value
16464167Sbinkertn@umich.edu        elif value.endswith('t'):
16474167Sbinkertn@umich.edu            self.ticks = True
16484167Sbinkertn@umich.edu            self.value = int(value[:-1])
16494167Sbinkertn@umich.edu        else:
16504167Sbinkertn@umich.edu            self.ticks = False
16514167Sbinkertn@umich.edu            self.value = convert.anyToLatency(value)
16523101Sstever@eecs.umich.edu
165310267SGeoffrey.Blake@arm.com    def __call__(self, value):
165410267SGeoffrey.Blake@arm.com        self.__init__(value)
165510267SGeoffrey.Blake@arm.com        return value
165610267SGeoffrey.Blake@arm.com
165710267SGeoffrey.Blake@arm.com    def __str__(self):
165810267SGeoffrey.Blake@arm.com        return "%s" % Latency(self)
165910267SGeoffrey.Blake@arm.com
16603101Sstever@eecs.umich.edu    def __getattr__(self, attr):
16613101Sstever@eecs.umich.edu        if attr == 'frequency':
16623101Sstever@eecs.umich.edu            return Frequency(self)
16633101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
16643101Sstever@eecs.umich.edu            return Latency(self)
166513663Sandreas.sandberg@arm.com        raise AttributeError("Frequency object has no attribute '%s'" % attr)
16663101Sstever@eecs.umich.edu
16674762Snate@binkert.org    def getValue(self):
16684762Snate@binkert.org        return self.period.getValue()
16694762Snate@binkert.org
167010380SAndrew.Bardsley@arm.com    def config_value(self):
167110380SAndrew.Bardsley@arm.com        return self.period.config_value()
167210380SAndrew.Bardsley@arm.com
16733101Sstever@eecs.umich.edu    def ini_str(self):
16743101Sstever@eecs.umich.edu        return self.period.ini_str()
16753101Sstever@eecs.umich.edu
167612250Sgabeblack@google.comclass Voltage(Float):
167710267SGeoffrey.Blake@arm.com    ex_str = "1V"
167810267SGeoffrey.Blake@arm.com
16799827Sakash.bagdia@arm.com    def __new__(cls, value):
168012250Sgabeblack@google.com        value = convert.toVoltage(value)
168112250Sgabeblack@google.com        return super(cls, Voltage).__new__(cls, value)
16829827Sakash.bagdia@arm.com
168312250Sgabeblack@google.com    def __init__(self, value):
168412250Sgabeblack@google.com        value = convert.toVoltage(value)
168512250Sgabeblack@google.com        super(Voltage, self).__init__(value)
168610267SGeoffrey.Blake@arm.com
168712250Sgabeblack@google.comclass Current(Float):
168810427Sandreas.hansson@arm.com    ex_str = "1mA"
168910427Sandreas.hansson@arm.com
169010427Sandreas.hansson@arm.com    def __new__(cls, value):
169112250Sgabeblack@google.com        value = convert.toCurrent(value)
169212250Sgabeblack@google.com        return super(cls, Current).__new__(cls, value)
169310427Sandreas.hansson@arm.com
169412250Sgabeblack@google.com    def __init__(self, value):
169512250Sgabeblack@google.com        value = convert.toCurrent(value)
169612250Sgabeblack@google.com        super(Current, self).__init__(value)
169710458Sandreas.hansson@arm.com
169812253Sgabeblack@google.comclass Energy(Float):
169912253Sgabeblack@google.com    ex_str = "1pJ"
170012253Sgabeblack@google.com
170112253Sgabeblack@google.com    def __new__(cls, value):
170212253Sgabeblack@google.com        value = convert.toEnergy(value)
170312253Sgabeblack@google.com        return super(cls, Energy).__new__(cls, value)
170412253Sgabeblack@google.com
170512253Sgabeblack@google.com    def __init__(self, value):
170612253Sgabeblack@google.com        value = convert.toEnergy(value)
170712253Sgabeblack@google.com        super(Energy, self).__init__(value)
170812253Sgabeblack@google.com
17093101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
17103101Sstever@eecs.umich.edu    cxx_type = 'float'
171110267SGeoffrey.Blake@arm.com    ex_str = "1Gbps"
171210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
171310267SGeoffrey.Blake@arm.com
17143101Sstever@eecs.umich.edu    def __new__(cls, value):
17154167Sbinkertn@umich.edu        # convert to bits per second
17164167Sbinkertn@umich.edu        val = convert.toNetworkBandwidth(value)
17173101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
17183101Sstever@eecs.umich.edu
17193101Sstever@eecs.umich.edu    def __str__(self):
17203101Sstever@eecs.umich.edu        return str(self.val)
17213101Sstever@eecs.umich.edu
172210267SGeoffrey.Blake@arm.com    def __call__(self, value):
172310267SGeoffrey.Blake@arm.com        val = convert.toNetworkBandwidth(value)
172410267SGeoffrey.Blake@arm.com        self.__init__(val)
172510267SGeoffrey.Blake@arm.com        return value
172610267SGeoffrey.Blake@arm.com
17274762Snate@binkert.org    def getValue(self):
17284167Sbinkertn@umich.edu        # convert to seconds per byte
17294167Sbinkertn@umich.edu        value = 8.0 / float(self)
17304167Sbinkertn@umich.edu        # convert to ticks per byte
17314762Snate@binkert.org        value = ticks.fromSeconds(value)
17324762Snate@binkert.org        return float(value)
17334762Snate@binkert.org
17344762Snate@binkert.org    def ini_str(self):
17354762Snate@binkert.org        return '%f' % self.getValue()
17363101Sstever@eecs.umich.edu
173710380SAndrew.Bardsley@arm.com    def config_value(self):
173810380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
173910380SAndrew.Bardsley@arm.com
174010458Sandreas.hansson@arm.com    @classmethod
174110458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
174210458Sandreas.hansson@arm.com        code('#include <sstream>')
174310458Sandreas.hansson@arm.com
174410458Sandreas.hansson@arm.com    @classmethod
174510458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
174610458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
174710458Sandreas.hansson@arm.com
17483101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
17493101Sstever@eecs.umich.edu    cxx_type = 'float'
175010267SGeoffrey.Blake@arm.com    ex_str = "1GB/s"
175110267SGeoffrey.Blake@arm.com    cmd_line_settable = True
175210267SGeoffrey.Blake@arm.com
17535469Snate@binkert.org    def __new__(cls, value):
17547743Sgblack@eecs.umich.edu        # convert to bytes per second
17553102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
17563101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
17573101Sstever@eecs.umich.edu
175810267SGeoffrey.Blake@arm.com    def __call__(self, value):
175910267SGeoffrey.Blake@arm.com        val = convert.toMemoryBandwidth(value)
176010267SGeoffrey.Blake@arm.com        self.__init__(val)
176110267SGeoffrey.Blake@arm.com        return value
17623101Sstever@eecs.umich.edu
17634762Snate@binkert.org    def getValue(self):
17644167Sbinkertn@umich.edu        # convert to seconds per byte
17655468Snate@binkert.org        value = float(self)
17665468Snate@binkert.org        if value:
17675468Snate@binkert.org            value = 1.0 / float(self)
17684167Sbinkertn@umich.edu        # convert to ticks per byte
17694762Snate@binkert.org        value = ticks.fromSeconds(value)
17704762Snate@binkert.org        return float(value)
17714762Snate@binkert.org
17724762Snate@binkert.org    def ini_str(self):
17734762Snate@binkert.org        return '%f' % self.getValue()
17743101Sstever@eecs.umich.edu
177510380SAndrew.Bardsley@arm.com    def config_value(self):
177610380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
177710380SAndrew.Bardsley@arm.com
177810458Sandreas.hansson@arm.com    @classmethod
177910458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
178010458Sandreas.hansson@arm.com        code('#include <sstream>')
178110458Sandreas.hansson@arm.com
178210458Sandreas.hansson@arm.com    @classmethod
178310458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
178410458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
178510458Sandreas.hansson@arm.com
17863101Sstever@eecs.umich.edu#
17873101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
17883101Sstever@eecs.umich.edu#
17893101Sstever@eecs.umich.edu
17903102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
17913102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
17923102Sstever@eecs.umich.edu# SimObject is required.
17933102Sstever@eecs.umich.edu# only one copy of a particular node
17943102Sstever@eecs.umich.educlass NullSimObject(object):
17953102Sstever@eecs.umich.edu    __metaclass__ = Singleton
179612197Sgabeblack@google.com    _name = 'Null'
17973102Sstever@eecs.umich.edu
17983102Sstever@eecs.umich.edu    def __call__(cls):
17993102Sstever@eecs.umich.edu        return cls
18003102Sstever@eecs.umich.edu
18013102Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
18023102Sstever@eecs.umich.edu        pass
18033102Sstever@eecs.umich.edu
18043102Sstever@eecs.umich.edu    def ini_str(self):
18053102Sstever@eecs.umich.edu        return 'Null'
18063102Sstever@eecs.umich.edu
18073102Sstever@eecs.umich.edu    def unproxy(self, base):
18083102Sstever@eecs.umich.edu        return self
18093102Sstever@eecs.umich.edu
18103102Sstever@eecs.umich.edu    def set_path(self, parent, name):
18113102Sstever@eecs.umich.edu        pass
18124762Snate@binkert.org
181312192Sgabeblack@google.com    def set_parent(self, parent, name):
181412192Sgabeblack@google.com        pass
181512192Sgabeblack@google.com
181612195Sgabeblack@google.com    def clear_parent(self, old_parent):
181712195Sgabeblack@google.com        pass
181812195Sgabeblack@google.com
181912196Sgabeblack@google.com    def descendants(self):
182012196Sgabeblack@google.com        return
182112196Sgabeblack@google.com        yield None
182212196Sgabeblack@google.com
182312200Sgabeblack@google.com    def get_config_as_dict(self):
182412200Sgabeblack@google.com        return {}
182512200Sgabeblack@google.com
18263102Sstever@eecs.umich.edu    def __str__(self):
182712197Sgabeblack@google.com        return self._name
18283102Sstever@eecs.umich.edu
182910380SAndrew.Bardsley@arm.com    def config_value(self):
183010380SAndrew.Bardsley@arm.com        return None
183110380SAndrew.Bardsley@arm.com
18324762Snate@binkert.org    def getValue(self):
18334762Snate@binkert.org        return None
18344762Snate@binkert.org
18353102Sstever@eecs.umich.edu# The only instance you'll ever need...
18363102Sstever@eecs.umich.eduNULL = NullSimObject()
18373102Sstever@eecs.umich.edu
18383102Sstever@eecs.umich.edudef isNullPointer(value):
18393102Sstever@eecs.umich.edu    return isinstance(value, NullSimObject)
18403102Sstever@eecs.umich.edu
18413101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
18423101Sstever@eecs.umich.eduMaxAddr = Addr.max
18433101Sstever@eecs.umich.eduMaxTick = Tick.max
18443101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
18453101Sstever@eecs.umich.edu
18463101Sstever@eecs.umich.edu
18473101Sstever@eecs.umich.edu#####################################################################
18483101Sstever@eecs.umich.edu#
18493101Sstever@eecs.umich.edu# Port objects
18503101Sstever@eecs.umich.edu#
18513101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
18523101Sstever@eecs.umich.edu#
18533101Sstever@eecs.umich.edu#####################################################################
18543101Sstever@eecs.umich.edu
18553101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
18563101Sstever@eecs.umich.edu# particular SimObject.
18573101Sstever@eecs.umich.educlass PortRef(object):
185813869Sgabeblack@google.com    def __init__(self, simobj, name, role, is_source):
18593105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
18603101Sstever@eecs.umich.edu        self.simobj = simobj
18613101Sstever@eecs.umich.edu        self.name = name
18628839Sandreas.hansson@arm.com        self.role = role
186313869Sgabeblack@google.com        self.is_source = is_source
18643101Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
18653101Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
18663105Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
18673101Sstever@eecs.umich.edu
18683103Sstever@eecs.umich.edu    def __str__(self):
18693105Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
18703103Sstever@eecs.umich.edu
18718840Sandreas.hansson@arm.com    def __len__(self):
18728840Sandreas.hansson@arm.com        # Return the number of connected ports, i.e. 0 is we have no
18738840Sandreas.hansson@arm.com        # peer and 1 if we do.
18748840Sandreas.hansson@arm.com        return int(self.peer != None)
18758840Sandreas.hansson@arm.com
18763105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
18773105Sstever@eecs.umich.edu    def ini_str(self):
18783105Sstever@eecs.umich.edu        return str(self.peer)
18793105Sstever@eecs.umich.edu
18809017Sandreas.hansson@arm.com    # for config.json
18819017Sandreas.hansson@arm.com    def get_config_as_dict(self):
188213869Sgabeblack@google.com        return {'role' : self.role, 'peer' : str(self.peer),
188313869Sgabeblack@google.com                'is_source' : str(self.is_source)}
18849017Sandreas.hansson@arm.com
18853105Sstever@eecs.umich.edu    def __getattr__(self, attr):
18863105Sstever@eecs.umich.edu        if attr == 'peerObj':
18873105Sstever@eecs.umich.edu            # shorthand for proxies
18883105Sstever@eecs.umich.edu            return self.peer.simobj
188913663Sandreas.sandberg@arm.com        raise AttributeError("'%s' object has no attribute '%s'" % \
189013663Sandreas.sandberg@arm.com              (self.__class__.__name__, attr))
18913105Sstever@eecs.umich.edu
18923105Sstever@eecs.umich.edu    # Full connection is symmetric (both ways).  Called via
18933105Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
18943109Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
18953105Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
18963105Sstever@eecs.umich.edu    def connect(self, other):
18973105Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
18983105Sstever@eecs.umich.edu            # reference to plain VectorPort is implicit append
18993105Sstever@eecs.umich.edu            other = other._get_next()
19003105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
19019014Sandreas.hansson@arm.com            fatal("Port %s is already connected to %s, cannot connect %s\n",
19029014Sandreas.hansson@arm.com                  self, self.peer, other);
19033101Sstever@eecs.umich.edu        self.peer = other
190413869Sgabeblack@google.com
19053109Sstever@eecs.umich.edu        if proxy.isproxy(other):
19063109Sstever@eecs.umich.edu            other.set_param_desc(PortParamDesc())
190713869Sgabeblack@google.com            return
190813869Sgabeblack@google.com        elif not isinstance(other, PortRef):
190913663Sandreas.sandberg@arm.com            raise TypeError("assigning non-port reference '%s' to port '%s'" \
191013663Sandreas.sandberg@arm.com                  % (other, self))
19113101Sstever@eecs.umich.edu
191213869Sgabeblack@google.com        if not Port.is_compat(self, other):
191313869Sgabeblack@google.com            fatal("Ports %s and %s with roles '%s' and '%s' "
191413869Sgabeblack@google.com                    "are not compatible", self, other, self.role, other.role)
191513869Sgabeblack@google.com
191613869Sgabeblack@google.com        if other.peer is not self:
191713869Sgabeblack@google.com            other.connect(self)
191813869Sgabeblack@google.com
191913871Sgabeblack@google.com    # Allow a compatible port pair to be spliced between a port and its
192013871Sgabeblack@google.com    # connected peer. Useful operation for connecting instrumentation
192113871Sgabeblack@google.com    # structures into a system when it is necessary to connect the
192213871Sgabeblack@google.com    # instrumentation after the full system has been constructed.
192313871Sgabeblack@google.com    def splice(self, new_1, new_2):
192413543Sgabeblack@google.com        if not self.peer or proxy.isproxy(self.peer):
192513543Sgabeblack@google.com            fatal("Port %s not connected, cannot splice in new peers\n", self)
192613543Sgabeblack@google.com
192713871Sgabeblack@google.com        if not isinstance(new_1, PortRef) or not isinstance(new_2, PortRef):
192813663Sandreas.sandberg@arm.com            raise TypeError(
192913543Sgabeblack@google.com                  "Splicing non-port references '%s','%s' to port '%s'" % \
193013871Sgabeblack@google.com                  (new_1, new_2, self))
193113543Sgabeblack@google.com
193213543Sgabeblack@google.com        old_peer = self.peer
193313871Sgabeblack@google.com
193413871Sgabeblack@google.com        if Port.is_compat(old_peer, new_1) and Port.is_compat(self, new_2):
193513871Sgabeblack@google.com            old_peer.peer = new_1
193613871Sgabeblack@google.com            new_1.peer = old_peer
193713871Sgabeblack@google.com            self.peer = new_2
193813871Sgabeblack@google.com            new_2.peer = self
193913871Sgabeblack@google.com        elif Port.is_compat(old_peer, new_2) and Port.is_compat(self, new_1):
194013871Sgabeblack@google.com            old_peer.peer = new_2
194113871Sgabeblack@google.com            new_2.peer = old_peer
194213871Sgabeblack@google.com            self.peer = new_1
194313871Sgabeblack@google.com            new_1.peer = self
194410355SGeoffrey.Blake@arm.com        else:
194513871Sgabeblack@google.com            fatal("Ports %s(%s) and %s(%s) can't be compatibly spliced with "
194613871Sgabeblack@google.com                    "%s(%s) and %s(%s)", self, self.role,
194713871Sgabeblack@google.com                    old_peer, old_peer.role, new_1, new_1.role,
194813871Sgabeblack@google.com                    new_2, new_2.role)
194910355SGeoffrey.Blake@arm.com
19503105Sstever@eecs.umich.edu    def clone(self, simobj, memo):
195113675Sandreas.sandberg@arm.com        if self in memo:
19523105Sstever@eecs.umich.edu            return memo[self]
19533101Sstever@eecs.umich.edu        newRef = copy.copy(self)
19543105Sstever@eecs.umich.edu        memo[self] = newRef
19553105Sstever@eecs.umich.edu        newRef.simobj = simobj
19563101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
19573105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
19583179Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
19593105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
19603105Sstever@eecs.umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
19613101Sstever@eecs.umich.edu        return newRef
19623101Sstever@eecs.umich.edu
19633105Sstever@eecs.umich.edu    def unproxy(self, simobj):
19643105Sstever@eecs.umich.edu        assert(simobj is self.simobj)
19653105Sstever@eecs.umich.edu        if proxy.isproxy(self.peer):
19663105Sstever@eecs.umich.edu            try:
19673105Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
19683105Sstever@eecs.umich.edu            except:
196912563Sgabeblack@google.com                print("Error in unproxying port '%s' of %s" %
197012563Sgabeblack@google.com                      (self.name, self.simobj.path()))
19713105Sstever@eecs.umich.edu                raise
19723105Sstever@eecs.umich.edu            self.connect(realPeer)
19733105Sstever@eecs.umich.edu
19743101Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
19753101Sstever@eecs.umich.edu    def ccConnect(self):
197613594Snicholas.lindsay@arm.com        if self.ccConnected: # already done this
19778839Sandreas.hansson@arm.com            return
19788839Sandreas.hansson@arm.com
19793101Sstever@eecs.umich.edu        peer = self.peer
19805578SSteve.Reinhardt@amd.com        if not self.peer: # nothing to connect to
19815578SSteve.Reinhardt@amd.com            return
19828839Sandreas.hansson@arm.com
198313783Sgabeblack@google.com        port = self.simobj.getPort(self.name, self.index)
198413783Sgabeblack@google.com        peer_port = peer.simobj.getPort(peer.name, peer.index)
198513783Sgabeblack@google.com        port.bind(peer_port)
19868839Sandreas.hansson@arm.com
19873101Sstever@eecs.umich.edu        self.ccConnected = True
19883101Sstever@eecs.umich.edu
19893105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
19903105Sstever@eecs.umich.edu# PortRef, but has an index.
19913105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
199213869Sgabeblack@google.com    def __init__(self, simobj, name, role, is_source, index):
199313869Sgabeblack@google.com        PortRef.__init__(self, simobj, name, role, is_source)
19943105Sstever@eecs.umich.edu        self.index = index
19953105Sstever@eecs.umich.edu
19963105Sstever@eecs.umich.edu    def __str__(self):
19973105Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
19983105Sstever@eecs.umich.edu
19993105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
20003105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
20013105Sstever@eecs.umich.educlass VectorPortRef(object):
200213869Sgabeblack@google.com    def __init__(self, simobj, name, role, is_source):
20033105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
20043105Sstever@eecs.umich.edu        self.simobj = simobj
20053105Sstever@eecs.umich.edu        self.name = name
20068839Sandreas.hansson@arm.com        self.role = role
200713869Sgabeblack@google.com        self.is_source = is_source
20083105Sstever@eecs.umich.edu        self.elements = []
20093105Sstever@eecs.umich.edu
20103109Sstever@eecs.umich.edu    def __str__(self):
20113109Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
20123109Sstever@eecs.umich.edu
20138840Sandreas.hansson@arm.com    def __len__(self):
20148840Sandreas.hansson@arm.com        # Return the number of connected peers, corresponding the the
20158840Sandreas.hansson@arm.com        # length of the elements.
20168840Sandreas.hansson@arm.com        return len(self.elements)
20178840Sandreas.hansson@arm.com
20183105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
20193105Sstever@eecs.umich.edu    def ini_str(self):
20203105Sstever@eecs.umich.edu        return ' '.join([el.ini_str() for el in self.elements])
20213105Sstever@eecs.umich.edu
20229017Sandreas.hansson@arm.com    # for config.json
20239017Sandreas.hansson@arm.com    def get_config_as_dict(self):
20249017Sandreas.hansson@arm.com        return {'role' : self.role,
202513869Sgabeblack@google.com                'peer' : [el.ini_str() for el in self.elements],
202613869Sgabeblack@google.com                'is_source' : str(self.is_source)}
20279017Sandreas.hansson@arm.com
20283105Sstever@eecs.umich.edu    def __getitem__(self, key):
20293105Sstever@eecs.umich.edu        if not isinstance(key, int):
203013663Sandreas.sandberg@arm.com            raise TypeError("VectorPort index must be integer")
20313105Sstever@eecs.umich.edu        if key >= len(self.elements):
20323105Sstever@eecs.umich.edu            # need to extend list
203313869Sgabeblack@google.com            ext = [VectorPortElementRef(
203413869Sgabeblack@google.com                    self.simobj, self.name, self.role, self.is_source, i)
20353105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
20363105Sstever@eecs.umich.edu            self.elements.extend(ext)
20373105Sstever@eecs.umich.edu        return self.elements[key]
20383105Sstever@eecs.umich.edu
20393105Sstever@eecs.umich.edu    def _get_next(self):
20403105Sstever@eecs.umich.edu        return self[len(self.elements)]
20413105Sstever@eecs.umich.edu
20423105Sstever@eecs.umich.edu    def __setitem__(self, key, value):
20433105Sstever@eecs.umich.edu        if not isinstance(key, int):
204413663Sandreas.sandberg@arm.com            raise TypeError("VectorPort index must be integer")
20453105Sstever@eecs.umich.edu        self[key].connect(value)
20463105Sstever@eecs.umich.edu
20473105Sstever@eecs.umich.edu    def connect(self, other):
20483109Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
20493109Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
20503109Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
20513109Sstever@eecs.umich.edu            # or if it should replace the current vector.
20523109Sstever@eecs.umich.edu            for ref in other:
20533109Sstever@eecs.umich.edu                self._get_next().connect(ref)
20543109Sstever@eecs.umich.edu        else:
20553109Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
20563109Sstever@eecs.umich.edu            self._get_next().connect(other)
20573109Sstever@eecs.umich.edu
20583109Sstever@eecs.umich.edu    def clone(self, simobj, memo):
205913675Sandreas.sandberg@arm.com        if self in memo:
20603109Sstever@eecs.umich.edu            return memo[self]
20613109Sstever@eecs.umich.edu        newRef = copy.copy(self)
20623109Sstever@eecs.umich.edu        memo[self] = newRef
20633109Sstever@eecs.umich.edu        newRef.simobj = simobj
20643109Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
20653109Sstever@eecs.umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
20663109Sstever@eecs.umich.edu        return newRef
20673105Sstever@eecs.umich.edu
20683105Sstever@eecs.umich.edu    def unproxy(self, simobj):
20693105Sstever@eecs.umich.edu        [el.unproxy(simobj) for el in self.elements]
20703105Sstever@eecs.umich.edu
20713105Sstever@eecs.umich.edu    def ccConnect(self):
20723105Sstever@eecs.umich.edu        [el.ccConnect() for el in self.elements]
20733105Sstever@eecs.umich.edu
20743101Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
20753101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a
20763101Sstever@eecs.umich.edu# SimObject instance.  The latter are represented by PortRef objects.
20773101Sstever@eecs.umich.educlass Port(object):
207813869Sgabeblack@google.com    # Port("role", "description")
207913869Sgabeblack@google.com
208013869Sgabeblack@google.com    _compat_dict = { }
208113869Sgabeblack@google.com
208213869Sgabeblack@google.com    @classmethod
208313869Sgabeblack@google.com    def compat(cls, role, peer):
208413869Sgabeblack@google.com        cls._compat_dict.setdefault(role, set()).add(peer)
208513869Sgabeblack@google.com        cls._compat_dict.setdefault(peer, set()).add(role)
208613869Sgabeblack@google.com
208713869Sgabeblack@google.com    @classmethod
208813869Sgabeblack@google.com    def is_compat(cls, one, two):
208913869Sgabeblack@google.com        for port in one, two:
209013869Sgabeblack@google.com            if not port.role in Port._compat_dict:
209113869Sgabeblack@google.com                fatal("Unrecognized role '%s' for port %s\n", port.role, port)
209213869Sgabeblack@google.com        return one.role in Port._compat_dict[two.role]
209313869Sgabeblack@google.com
209413869Sgabeblack@google.com    def __init__(self, role, desc, is_source=False):
209513869Sgabeblack@google.com        self.desc = desc
209613869Sgabeblack@google.com        self.role = role
209713869Sgabeblack@google.com        self.is_source = is_source
209813869Sgabeblack@google.com
20993101Sstever@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
21003101Sstever@eecs.umich.edu    # given name
21013105Sstever@eecs.umich.edu    def makeRef(self, simobj):
210213869Sgabeblack@google.com        return PortRef(simobj, self.name, self.role, self.is_source)
21033101Sstever@eecs.umich.edu
21043101Sstever@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
21053101Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
21063105Sstever@eecs.umich.edu    def connect(self, simobj, ref):
21073105Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
21083101Sstever@eecs.umich.edu
21098840Sandreas.hansson@arm.com    # No need for any pre-declarations at the moment as we merely rely
21108840Sandreas.hansson@arm.com    # on an unsigned int.
21118840Sandreas.hansson@arm.com    def cxx_predecls(self, code):
21128840Sandreas.hansson@arm.com        pass
21138840Sandreas.hansson@arm.com
211411988Sandreas.sandberg@arm.com    def pybind_predecls(self, code):
211511988Sandreas.sandberg@arm.com        cls.cxx_predecls(self, code)
211611988Sandreas.sandberg@arm.com
21178840Sandreas.hansson@arm.com    # Declare an unsigned int with the same name as the port, that
21188840Sandreas.hansson@arm.com    # will eventually hold the number of connected ports (and thus the
21198840Sandreas.hansson@arm.com    # number of elements for a VectorPort).
21208840Sandreas.hansson@arm.com    def cxx_decl(self, code):
21218840Sandreas.hansson@arm.com        code('unsigned int port_${{self.name}}_connection_count;')
21228840Sandreas.hansson@arm.com
212313890Sgabeblack@google.comPort.compat('GEM5 REQUESTER', 'GEM5 RESPONDER')
212413869Sgabeblack@google.com
212513890Sgabeblack@google.comclass RequestPort(Port):
212613890Sgabeblack@google.com    # RequestPort("description")
212713869Sgabeblack@google.com    def __init__(self, desc):
212813890Sgabeblack@google.com        super(RequestPort, self).__init__(
212913890Sgabeblack@google.com                'GEM5 REQUESTER', desc, is_source=True)
21308839Sandreas.hansson@arm.com
213113890Sgabeblack@google.comclass ResponsePort(Port):
213213890Sgabeblack@google.com    # ResponsePort("description")
213313869Sgabeblack@google.com    def __init__(self, desc):
213413890Sgabeblack@google.com        super(ResponsePort, self).__init__('GEM5 RESPONDER', desc)
21358839Sandreas.hansson@arm.com
21363101Sstever@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
213710405Sandreas.hansson@arm.com# of connections (e.g., as on a XBar).
21383101Sstever@eecs.umich.educlass VectorPort(Port):
21393105Sstever@eecs.umich.edu    def makeRef(self, simobj):
214013869Sgabeblack@google.com        return VectorPortRef(simobj, self.name, self.role, self.is_source)
21418839Sandreas.hansson@arm.com
214213890Sgabeblack@google.comclass VectorRequestPort(VectorPort):
214313890Sgabeblack@google.com    # VectorRequestPort("description")
214413869Sgabeblack@google.com    def __init__(self, desc):
214513890Sgabeblack@google.com        super(VectorRequestPort, self).__init__(
214613890Sgabeblack@google.com                'GEM5 REQUESTER', desc, is_source=True)
21478839Sandreas.hansson@arm.com
214813890Sgabeblack@google.comclass VectorResponsePort(VectorPort):
214913890Sgabeblack@google.com    # VectorResponsePort("description")
215013869Sgabeblack@google.com    def __init__(self, desc):
215113890Sgabeblack@google.com        super(VectorResponsePort, self).__init__('GEM5 RESPONDER', desc)
215213890Sgabeblack@google.com
215313890Sgabeblack@google.com# Old names, maintained for compatibility.
215413890Sgabeblack@google.comMasterPort = RequestPort
215513890Sgabeblack@google.comSlavePort = ResponsePort
215613890Sgabeblack@google.comVectorMasterPort = VectorRequestPort
215713890Sgabeblack@google.comVectorSlavePort = VectorResponsePort
21583105Sstever@eecs.umich.edu
21593109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
21603109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
21613109Sstever@eecs.umich.edu# make sense.
21623109Sstever@eecs.umich.educlass PortParamDesc(object):
21633109Sstever@eecs.umich.edu    __metaclass__ = Singleton
21643109Sstever@eecs.umich.edu
21653109Sstever@eecs.umich.edu    ptype_str = 'Port'
21663109Sstever@eecs.umich.edu    ptype = Port
21673105Sstever@eecs.umich.edu
21686654Snate@binkert.orgbaseEnums = allEnums.copy()
21696654Snate@binkert.orgbaseParams = allParams.copy()
21706654Snate@binkert.org
21716654Snate@binkert.orgdef clear():
21726654Snate@binkert.org    global allEnums, allParams
21736654Snate@binkert.org
21746654Snate@binkert.org    allEnums = baseEnums.copy()
21756654Snate@binkert.org    allParams = baseParams.copy()
21766654Snate@binkert.org
21773101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam',
217813558Snikos.nikoleris@arm.com           'Enum', 'ScopedEnum', 'Bool', 'String', 'Float',
21793101Sstever@eecs.umich.edu           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
21803101Sstever@eecs.umich.edu           'Int32', 'UInt32', 'Int64', 'UInt64',
21813101Sstever@eecs.umich.edu           'Counter', 'Addr', 'Tick', 'Percent',
21823101Sstever@eecs.umich.edu           'TcpPort', 'UdpPort', 'EthernetAddr',
21837777Sgblack@eecs.umich.edu           'IpAddress', 'IpNetmask', 'IpWithPort',
21843101Sstever@eecs.umich.edu           'MemorySize', 'MemorySize32',
218512253Sgabeblack@google.com           'Latency', 'Frequency', 'Clock', 'Voltage', 'Current', 'Energy',
21863101Sstever@eecs.umich.edu           'NetworkBandwidth', 'MemoryBandwidth',
21879232Sandreas.hansson@arm.com           'AddrRange',
21883101Sstever@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
21893885Sbinkertn@umich.edu           'Time',
21903102Sstever@eecs.umich.edu           'NextEthernetAddr', 'NULL',
219113890Sgabeblack@google.com           'Port', 'RequestPort', 'ResponsePort', 'MasterPort', 'SlavePort',
219213890Sgabeblack@google.com           'VectorPort', 'VectorRequestPort', 'VectorResponsePort',
219313890Sgabeblack@google.com           'VectorMasterPort', 'VectorSlavePort']
2194