params.py revision 12196:4c1449b32810
111988Sandreas.sandberg@arm.com# Copyright (c) 2012-2014, 2017 ARM Limited
28839Sandreas.hansson@arm.com# All rights reserved.
38839Sandreas.hansson@arm.com#
48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall
58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual
68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating
78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software
88839Sandreas.hansson@arm.com# licensed hereunder.  You may use the software subject to the license
98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated
108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software,
118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form.
128839Sandreas.hansson@arm.com#
133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan
148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
153101Sstever@eecs.umich.edu# All rights reserved.
163101Sstever@eecs.umich.edu#
173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are
193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright
203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution;
243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its
253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from
263101Sstever@eecs.umich.edu# this software without specific prior written permission.
273101Sstever@eecs.umich.edu#
283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
393101Sstever@eecs.umich.edu#
403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt
413101Sstever@eecs.umich.edu#          Nathan Binkert
427778Sgblack@eecs.umich.edu#          Gabe Black
438839Sandreas.hansson@arm.com#          Andreas Hansson
443101Sstever@eecs.umich.edu
453101Sstever@eecs.umich.edu#####################################################################
463101Sstever@eecs.umich.edu#
473101Sstever@eecs.umich.edu# Parameter description classes
483101Sstever@eecs.umich.edu#
493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either
503101Sstever@eecs.umich.edu# a Param or a VectorParam object.  These objects contain the
513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default
523101Sstever@eecs.umich.edu# value (if any).  The convert() method on these objects is used to
533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate
543101Sstever@eecs.umich.edu# type.
553101Sstever@eecs.umich.edu#
563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute
573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in
583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used.
593101Sstever@eecs.umich.edu#
603101Sstever@eecs.umich.edu#####################################################################
613101Sstever@eecs.umich.edu
623885Sbinkertn@umich.eduimport copy
633885Sbinkertn@umich.eduimport datetime
644762Snate@binkert.orgimport re
653885Sbinkertn@umich.eduimport sys
663885Sbinkertn@umich.eduimport time
677528Ssteve.reinhardt@amd.comimport math
683885Sbinkertn@umich.edu
694380Sbinkertn@umich.eduimport proxy
704167Sbinkertn@umich.eduimport ticks
713102Sstever@eecs.umich.edufrom util import *
723101Sstever@eecs.umich.edu
734762Snate@binkert.orgdef isSimObject(*args, **kwargs):
744762Snate@binkert.org    return SimObject.isSimObject(*args, **kwargs)
754762Snate@binkert.org
764762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs):
774762Snate@binkert.org    return SimObject.isSimObjectSequence(*args, **kwargs)
784762Snate@binkert.org
794762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs):
804762Snate@binkert.org    return SimObject.isSimObjectClass(*args, **kwargs)
814762Snate@binkert.org
825033Smilesck@eecs.umich.eduallParams = {}
835033Smilesck@eecs.umich.edu
845033Smilesck@eecs.umich.educlass MetaParamValue(type):
855033Smilesck@eecs.umich.edu    def __new__(mcls, name, bases, dct):
865033Smilesck@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
875033Smilesck@eecs.umich.edu        assert name not in allParams
885033Smilesck@eecs.umich.edu        allParams[name] = cls
895033Smilesck@eecs.umich.edu        return cls
905033Smilesck@eecs.umich.edu
915033Smilesck@eecs.umich.edu
923101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject
933101Sstever@eecs.umich.edu# parameters.
943101Sstever@eecs.umich.educlass ParamValue(object):
955033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
9610267SGeoffrey.Blake@arm.com    cmd_line_settable = False
978596Ssteve.reinhardt@amd.com
988596Ssteve.reinhardt@amd.com    # Generate the code needed as a prerequisite for declaring a C++
998596Ssteve.reinhardt@amd.com    # object of this type.  Typically generates one or more #include
1008596Ssteve.reinhardt@amd.com    # statements.  Used when declaring parameters of this type.
1017673Snate@binkert.org    @classmethod
1027673Snate@binkert.org    def cxx_predecls(cls, code):
1037673Snate@binkert.org        pass
1047673Snate@binkert.org
10511988Sandreas.sandberg@arm.com    @classmethod
10611988Sandreas.sandberg@arm.com    def pybind_predecls(cls, code):
10711988Sandreas.sandberg@arm.com        cls.cxx_predecls(code)
10811988Sandreas.sandberg@arm.com
1093101Sstever@eecs.umich.edu    # default for printing to .ini file is regular string conversion.
1103101Sstever@eecs.umich.edu    # will be overridden in some cases
1113101Sstever@eecs.umich.edu    def ini_str(self):
1123101Sstever@eecs.umich.edu        return str(self)
1133101Sstever@eecs.umich.edu
11410380SAndrew.Bardsley@arm.com    # default for printing to .json file is regular string conversion.
11510380SAndrew.Bardsley@arm.com    # will be overridden in some cases, mostly to use native Python
11610380SAndrew.Bardsley@arm.com    # types where there are similar JSON types
11710380SAndrew.Bardsley@arm.com    def config_value(self):
11810380SAndrew.Bardsley@arm.com        return str(self)
11910380SAndrew.Bardsley@arm.com
12010458Sandreas.hansson@arm.com    # Prerequisites for .ini parsing with cxx_ini_parse
12110458Sandreas.hansson@arm.com    @classmethod
12210458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
12310458Sandreas.hansson@arm.com        pass
12410458Sandreas.hansson@arm.com
12510458Sandreas.hansson@arm.com    # parse a .ini file entry for this param from string expression
12610458Sandreas.hansson@arm.com    # src into lvalue dest (of the param's C++ type)
12710458Sandreas.hansson@arm.com    @classmethod
12810458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
12910458Sandreas.hansson@arm.com        code('// Unhandled param type: %s' % cls.__name__)
13010458Sandreas.hansson@arm.com        code('%s false;' % ret)
13110458Sandreas.hansson@arm.com
1323101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
1333101Sstever@eecs.umich.edu    # if they're really proxies or not
1343101Sstever@eecs.umich.edu    def unproxy(self, base):
1353101Sstever@eecs.umich.edu        return self
1363101Sstever@eecs.umich.edu
13710267SGeoffrey.Blake@arm.com    # Produce a human readable version of the stored value
13810267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
13910267SGeoffrey.Blake@arm.com        return str(value)
14010267SGeoffrey.Blake@arm.com
1413101Sstever@eecs.umich.edu# Regular parameter description.
1423101Sstever@eecs.umich.educlass ParamDesc(object):
1433101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1443101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1453101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1463101Sstever@eecs.umich.edu        if ptype != None:
1473101Sstever@eecs.umich.edu            self.ptype = ptype
1483101Sstever@eecs.umich.edu
1493101Sstever@eecs.umich.edu        if args:
1503101Sstever@eecs.umich.edu            if len(args) == 1:
1513101Sstever@eecs.umich.edu                self.desc = args[0]
1523101Sstever@eecs.umich.edu            elif len(args) == 2:
1533101Sstever@eecs.umich.edu                self.default = args[0]
1543101Sstever@eecs.umich.edu                self.desc = args[1]
1553101Sstever@eecs.umich.edu            else:
1563101Sstever@eecs.umich.edu                raise TypeError, 'too many arguments'
1573101Sstever@eecs.umich.edu
1583101Sstever@eecs.umich.edu        if kwargs.has_key('desc'):
1593101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1603101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1613101Sstever@eecs.umich.edu            del kwargs['desc']
1623101Sstever@eecs.umich.edu
1633101Sstever@eecs.umich.edu        if kwargs.has_key('default'):
1643101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1653101Sstever@eecs.umich.edu            self.default = kwargs['default']
1663101Sstever@eecs.umich.edu            del kwargs['default']
1673101Sstever@eecs.umich.edu
1683101Sstever@eecs.umich.edu        if kwargs:
1693101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1703101Sstever@eecs.umich.edu
1713101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
1723101Sstever@eecs.umich.edu            raise TypeError, 'desc attribute missing'
1733101Sstever@eecs.umich.edu
1743101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1753101Sstever@eecs.umich.edu        if attr == 'ptype':
1765033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1776656Snate@binkert.org            assert isSimObjectClass(ptype)
1785033Smilesck@eecs.umich.edu            self.ptype = ptype
1795033Smilesck@eecs.umich.edu            return ptype
1805033Smilesck@eecs.umich.edu
1813101Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
1823101Sstever@eecs.umich.edu              (type(self).__name__, attr)
1833101Sstever@eecs.umich.edu
18410267SGeoffrey.Blake@arm.com    def example_str(self):
18510267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "ex_str"):
18610267SGeoffrey.Blake@arm.com            return self.ptype.ex_str
18710267SGeoffrey.Blake@arm.com        else:
18810267SGeoffrey.Blake@arm.com            return self.ptype_str
18910267SGeoffrey.Blake@arm.com
19010267SGeoffrey.Blake@arm.com    # Is the param available to be exposed on the command line
19110267SGeoffrey.Blake@arm.com    def isCmdLineSettable(self):
19210267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "cmd_line_settable"):
19310267SGeoffrey.Blake@arm.com            return self.ptype.cmd_line_settable
19410267SGeoffrey.Blake@arm.com        else:
19510267SGeoffrey.Blake@arm.com            return False
19610267SGeoffrey.Blake@arm.com
1973101Sstever@eecs.umich.edu    def convert(self, value):
1983101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
1993101Sstever@eecs.umich.edu            value.set_param_desc(self)
2003101Sstever@eecs.umich.edu            return value
2013101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
2023101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
2033101Sstever@eecs.umich.edu            # we're just assigning a null pointer
2043101Sstever@eecs.umich.edu            return value
2053101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
2063101Sstever@eecs.umich.edu            return value
2073102Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
2083101Sstever@eecs.umich.edu            return value
2093101Sstever@eecs.umich.edu        return self.ptype(value)
2103101Sstever@eecs.umich.edu
21110267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
21210267SGeoffrey.Blake@arm.com        if isinstance(value, proxy.BaseProxy):
21310267SGeoffrey.Blake@arm.com           return str(value)
21410267SGeoffrey.Blake@arm.com        if isNullPointer(value):
21510267SGeoffrey.Blake@arm.com           return NULL
21610267SGeoffrey.Blake@arm.com        return self.ptype(value).pretty_print(value)
21710267SGeoffrey.Blake@arm.com
2187673Snate@binkert.org    def cxx_predecls(self, code):
2198607Sgblack@eecs.umich.edu        code('#include <cstddef>')
2207673Snate@binkert.org        self.ptype.cxx_predecls(code)
2213101Sstever@eecs.umich.edu
22211988Sandreas.sandberg@arm.com    def pybind_predecls(self, code):
22311988Sandreas.sandberg@arm.com        self.ptype.pybind_predecls(code)
22411988Sandreas.sandberg@arm.com
2257673Snate@binkert.org    def cxx_decl(self, code):
2267673Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
2273101Sstever@eecs.umich.edu
2283101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
2293101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
2303101Sstever@eecs.umich.edu# single value.
2313101Sstever@eecs.umich.edu
2323101Sstever@eecs.umich.educlass VectorParamValue(list):
2335033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
2345475Snate@binkert.org    def __setattr__(self, attr, value):
2355475Snate@binkert.org        raise AttributeError, \
2365475Snate@binkert.org              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
2375475Snate@binkert.org
23810380SAndrew.Bardsley@arm.com    def config_value(self):
23910380SAndrew.Bardsley@arm.com        return [v.config_value() for v in self]
24010380SAndrew.Bardsley@arm.com
2413101Sstever@eecs.umich.edu    def ini_str(self):
2423101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
2433101Sstever@eecs.umich.edu
2444762Snate@binkert.org    def getValue(self):
2454762Snate@binkert.org        return [ v.getValue() for v in self ]
2464762Snate@binkert.org
2473101Sstever@eecs.umich.edu    def unproxy(self, base):
2488460SAli.Saidi@ARM.com        if len(self) == 1 and isinstance(self[0], proxy.BaseProxy):
2498459SAli.Saidi@ARM.com            # The value is a proxy (e.g. Parent.any, Parent.all or
2508459SAli.Saidi@ARM.com            # Parent.x) therefore try resolve it
2518459SAli.Saidi@ARM.com            return self[0].unproxy(base)
2523101Sstever@eecs.umich.edu        else:
2537528Ssteve.reinhardt@amd.com            return [v.unproxy(base) for v in self]
2547528Ssteve.reinhardt@amd.com
2557528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2567528Ssteve.reinhardt@amd.com    # support clone operation
2577528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2587528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2593101Sstever@eecs.umich.edu
2607528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
2617528Ssteve.reinhardt@amd.com        for v in self:
2627528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2637528Ssteve.reinhardt@amd.com
2647528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2657528Ssteve.reinhardt@amd.com        if len(self) == 1:
2667528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2677528Ssteve.reinhardt@amd.com        else:
2687528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2697528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2708321Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2718321Ssteve.reinhardt@amd.com
2727528Ssteve.reinhardt@amd.com    def has_parent(self):
2737528Ssteve.reinhardt@amd.com        return any([e.has_parent() for e in self if not isNullPointer(e)])
2747528Ssteve.reinhardt@amd.com
2757528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2767528Ssteve.reinhardt@amd.com    def get_name(self):
2777528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2787528Ssteve.reinhardt@amd.com
2797528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2807528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2817528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2827528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2837528Ssteve.reinhardt@amd.com    def descendants(self):
2847528Ssteve.reinhardt@amd.com        for v in self:
2853101Sstever@eecs.umich.edu            for obj in v.descendants():
2868664SAli.Saidi@ARM.com                yield obj
2878664SAli.Saidi@ARM.com
2888664SAli.Saidi@ARM.com    def get_config_as_dict(self):
2898664SAli.Saidi@ARM.com        a = []
2908664SAli.Saidi@ARM.com        for v in self:
2918664SAli.Saidi@ARM.com            a.append(v.get_config_as_dict())
2929953Sgeoffrey.blake@arm.com        return a
2939953Sgeoffrey.blake@arm.com
2949953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
2959953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
2969953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
2979953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
2989953Sgeoffrey.blake@arm.com    # configuration scripts.
2999953Sgeoffrey.blake@arm.com    def __setitem__(self, key, value):
3009953Sgeoffrey.blake@arm.com        val = self[key]
3019953Sgeoffrey.blake@arm.com        if value.has_parent():
3029953Sgeoffrey.blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
3039953Sgeoffrey.blake@arm.com                 " that is being overwritten by a SimObjectVector")
3049953Sgeoffrey.blake@arm.com        value.set_parent(val.get_parent(), val._name)
30510267SGeoffrey.Blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
30610267SGeoffrey.Blake@arm.com
30710267SGeoffrey.Blake@arm.com    # Enumerate the params of each member of the SimObject vector. Creates
30810267SGeoffrey.Blake@arm.com    # strings that will allow indexing into the vector by the python code and
30910267SGeoffrey.Blake@arm.com    # allow it to be specified on the command line.
31010267SGeoffrey.Blake@arm.com    def enumerateParams(self, flags_dict = {},
31110267SGeoffrey.Blake@arm.com                        cmd_line_str = "",
31210267SGeoffrey.Blake@arm.com                        access_str = ""):
31310267SGeoffrey.Blake@arm.com        if hasattr(self, "_paramEnumed"):
31410267SGeoffrey.Blake@arm.com            print "Cycle detected enumerating params at %s?!" % (cmd_line_str)
31510267SGeoffrey.Blake@arm.com        else:
31610267SGeoffrey.Blake@arm.com            x = 0
31710267SGeoffrey.Blake@arm.com            for vals in self:
31810267SGeoffrey.Blake@arm.com                # Each entry in the SimObjectVector should be an
31910267SGeoffrey.Blake@arm.com                # instance of a SimObject
32010267SGeoffrey.Blake@arm.com                flags_dict = vals.enumerateParams(flags_dict,
32110267SGeoffrey.Blake@arm.com                                                  cmd_line_str + "%d." % x,
32210267SGeoffrey.Blake@arm.com                                                  access_str + "[%d]." % x)
32310267SGeoffrey.Blake@arm.com                x = x + 1
32410267SGeoffrey.Blake@arm.com
3253101Sstever@eecs.umich.edu        return flags_dict
3263101Sstever@eecs.umich.edu
3273101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
3283101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
3293101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
3303101Sstever@eecs.umich.edu    def convert(self, value):
3313101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
33210364SGeoffrey.Blake@arm.com            # list: coerce each element into new list
33310364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
33410364SGeoffrey.Blake@arm.com        elif isinstance(value, str):
33510364SGeoffrey.Blake@arm.com            # If input is a csv string
3363101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) \
3374762Snate@binkert.org                         for v in value.strip('[').strip(']').split(',') ]
3384762Snate@binkert.org        else:
3394762Snate@binkert.org            # singleton: coerce to a single-element list
3404762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
3417528Ssteve.reinhardt@amd.com
3424762Snate@binkert.org        if isSimObjectSequence(tmp_list):
3434762Snate@binkert.org            return SimObjectVector(tmp_list)
3444762Snate@binkert.org        else:
34510267SGeoffrey.Blake@arm.com            return VectorParamValue(tmp_list)
34610267SGeoffrey.Blake@arm.com
34710267SGeoffrey.Blake@arm.com    # Produce a human readable example string that describes
34810267SGeoffrey.Blake@arm.com    # how to set this vector parameter in the absence of a default
34910267SGeoffrey.Blake@arm.com    # value.
35010267SGeoffrey.Blake@arm.com    def example_str(self):
35110267SGeoffrey.Blake@arm.com        s = super(VectorParamDesc, self).example_str()
35210267SGeoffrey.Blake@arm.com        help_str = "[" + s + "," + s + ", ...]"
35310267SGeoffrey.Blake@arm.com        return help_str
35410267SGeoffrey.Blake@arm.com
35510267SGeoffrey.Blake@arm.com    # Produce a human readable representation of the value of this vector param.
35610267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
35710267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
35810267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
35910267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
36010267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
36110267SGeoffrey.Blake@arm.com        else:
36210267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, value) ]
36310267SGeoffrey.Blake@arm.com
36410267SGeoffrey.Blake@arm.com        return tmp_list
36510267SGeoffrey.Blake@arm.com
36610267SGeoffrey.Blake@arm.com    # This is a helper function for the new config system
36710267SGeoffrey.Blake@arm.com    def __call__(self, value):
36810267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
36910267SGeoffrey.Blake@arm.com            # list: coerce each element into new list
37010267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
37110364SGeoffrey.Blake@arm.com        elif isinstance(value, str):
37210364SGeoffrey.Blake@arm.com            # If input is a csv string
37310267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
37410267SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
37510267SGeoffrey.Blake@arm.com        else:
37610267SGeoffrey.Blake@arm.com            # singleton: coerce to a single-element list
37710267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
37810267SGeoffrey.Blake@arm.com
3797673Snate@binkert.org        return VectorParamValue(tmp_list)
3807673Snate@binkert.org
3817673Snate@binkert.org    def cxx_predecls(self, code):
3823101Sstever@eecs.umich.edu        code('#include <vector>')
38311988Sandreas.sandberg@arm.com        self.ptype.cxx_predecls(code)
38411988Sandreas.sandberg@arm.com
38511988Sandreas.sandberg@arm.com    def pybind_predecls(self, code):
38611988Sandreas.sandberg@arm.com        code('#include <vector>')
3877673Snate@binkert.org        self.ptype.pybind_predecls(code)
3887673Snate@binkert.org
3893101Sstever@eecs.umich.edu    def cxx_decl(self, code):
3903101Sstever@eecs.umich.edu        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
3913101Sstever@eecs.umich.edu
3923101Sstever@eecs.umich.educlass ParamFactory(object):
3933101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
3943101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
3953101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
3963101Sstever@eecs.umich.edu
3973101Sstever@eecs.umich.edu    def __getattr__(self, attr):
3983101Sstever@eecs.umich.edu        if self.ptype_str:
3993101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
4003101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
4013101Sstever@eecs.umich.edu
4023101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
4033101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
4045033Smilesck@eecs.umich.edu        ptype = None
4055033Smilesck@eecs.umich.edu        try:
4063101Sstever@eecs.umich.edu            ptype = allParams[self.ptype_str]
4073101Sstever@eecs.umich.edu        except KeyError:
4083101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
4093101Sstever@eecs.umich.edu            # try to resolve it later
4103101Sstever@eecs.umich.edu            pass
4113101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
4123101Sstever@eecs.umich.edu
4133101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
4143101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
4153101Sstever@eecs.umich.edu
4163101Sstever@eecs.umich.edu#####################################################################
4173101Sstever@eecs.umich.edu#
4183101Sstever@eecs.umich.edu# Parameter Types
4193101Sstever@eecs.umich.edu#
4203101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
4213101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
4223101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
4233101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
4243101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
4253101Sstever@eecs.umich.edu# the __str__() conversion method).
4263101Sstever@eecs.umich.edu#
4273101Sstever@eecs.umich.edu#####################################################################
4283101Sstever@eecs.umich.edu
4293101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
4303101Sstever@eecs.umich.edu# built-in str class.
43110267SGeoffrey.Blake@arm.comclass String(ParamValue,str):
4327673Snate@binkert.org    cxx_type = 'std::string'
4337673Snate@binkert.org    cmd_line_settable = True
4347673Snate@binkert.org
4357673Snate@binkert.org    @classmethod
4367673Snate@binkert.org    def cxx_predecls(self, code):
43710267SGeoffrey.Blake@arm.com        code('#include <string>')
43810267SGeoffrey.Blake@arm.com
43910267SGeoffrey.Blake@arm.com    def __call__(self, value):
44010267SGeoffrey.Blake@arm.com        self = value
44110458Sandreas.hansson@arm.com        return value
44210458Sandreas.hansson@arm.com
44310458Sandreas.hansson@arm.com    @classmethod
44410458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
44510458Sandreas.hansson@arm.com        code('%s = %s;' % (dest, src))
4464762Snate@binkert.org        code('%s true;' % ret)
4474762Snate@binkert.org
4483101Sstever@eecs.umich.edu    def getValue(self):
4493101Sstever@eecs.umich.edu        return self
4503101Sstever@eecs.umich.edu
4513101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
4523101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
4533101Sstever@eecs.umich.edu# a new Latency object.
4543101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
4553101Sstever@eecs.umich.edu    def __str__(self):
4563101Sstever@eecs.umich.edu        return str(self.value)
4573101Sstever@eecs.umich.edu
4583101Sstever@eecs.umich.edu    def __float__(self):
4593714Sstever@eecs.umich.edu        return float(self.value)
4603714Sstever@eecs.umich.edu
4613714Sstever@eecs.umich.edu    def __long__(self):
4623714Sstever@eecs.umich.edu        return long(self.value)
4633714Sstever@eecs.umich.edu
4643714Sstever@eecs.umich.edu    def __int__(self):
4653101Sstever@eecs.umich.edu        return int(self.value)
4663101Sstever@eecs.umich.edu
4673101Sstever@eecs.umich.edu    # hook for bounds checking
4683101Sstever@eecs.umich.edu    def _check(self):
4693101Sstever@eecs.umich.edu        return
4703101Sstever@eecs.umich.edu
4713101Sstever@eecs.umich.edu    def __mul__(self, other):
4723101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4733101Sstever@eecs.umich.edu        newobj.value *= other
4743101Sstever@eecs.umich.edu        newobj._check()
4753101Sstever@eecs.umich.edu        return newobj
4763101Sstever@eecs.umich.edu
4773101Sstever@eecs.umich.edu    __rmul__ = __mul__
4783101Sstever@eecs.umich.edu
4793101Sstever@eecs.umich.edu    def __div__(self, other):
4803101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4813101Sstever@eecs.umich.edu        newobj.value /= other
4823101Sstever@eecs.umich.edu        newobj._check()
4833101Sstever@eecs.umich.edu        return newobj
4843101Sstever@eecs.umich.edu
4853101Sstever@eecs.umich.edu    def __sub__(self, other):
4863101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4873101Sstever@eecs.umich.edu        newobj.value -= other
4883101Sstever@eecs.umich.edu        newobj._check()
48910380SAndrew.Bardsley@arm.com        return newobj
49010380SAndrew.Bardsley@arm.com
49110380SAndrew.Bardsley@arm.com    def config_value(self):
49210458Sandreas.hansson@arm.com        return self.value
49310458Sandreas.hansson@arm.com
49410458Sandreas.hansson@arm.com    @classmethod
49510458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
49610458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
49710458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
49810458Sandreas.hansson@arm.com        pass
49910458Sandreas.hansson@arm.com
50010458Sandreas.hansson@arm.com    # The default for parsing PODs from an .ini entry is to extract from an
50110458Sandreas.hansson@arm.com    # istringstream and let overloading choose the right type according to
50210458Sandreas.hansson@arm.com    # the dest type.
50310458Sandreas.hansson@arm.com    @classmethod
50410458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
5053101Sstever@eecs.umich.edu        code('%s to_number(%s, %s);' % (ret, src, dest))
5065033Smilesck@eecs.umich.edu
5073101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
5083101Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue):
5093101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5103101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
5113101Sstever@eecs.umich.edu
5123101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
5133101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
5143101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
5153101Sstever@eecs.umich.edu        if name == 'CheckedInt':
5163101Sstever@eecs.umich.edu            return
5173101Sstever@eecs.umich.edu
5183101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
5195822Ssaidi@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
5205822Ssaidi@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
5213101Sstever@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
5223101Sstever@eecs.umich.edu                      name);
5233101Sstever@eecs.umich.edu            if cls.unsigned:
5243101Sstever@eecs.umich.edu                cls.min = 0
5253101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
5263101Sstever@eecs.umich.edu            else:
5273101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
5283101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
5293101Sstever@eecs.umich.edu
5303101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
5313101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
5323101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
5333101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
53410267SGeoffrey.Blake@arm.comclass CheckedInt(NumericParamValue):
5353101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
5363101Sstever@eecs.umich.edu    cmd_line_settable = True
5373101Sstever@eecs.umich.edu
5383101Sstever@eecs.umich.edu    def _check(self):
5393101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
5403101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
5413101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
5423101Sstever@eecs.umich.edu
5433102Sstever@eecs.umich.edu    def __init__(self, value):
5443714Sstever@eecs.umich.edu        if isinstance(value, str):
5453101Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
5463714Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
5473714Sstever@eecs.umich.edu            self.value = long(value)
5483714Sstever@eecs.umich.edu        else:
5493101Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to CheckedInt" \
5503101Sstever@eecs.umich.edu                  % type(value).__name__
55110267SGeoffrey.Blake@arm.com        self._check()
55210267SGeoffrey.Blake@arm.com
55310267SGeoffrey.Blake@arm.com    def __call__(self, value):
55410267SGeoffrey.Blake@arm.com        self.__init__(value)
5557673Snate@binkert.org        return value
5567673Snate@binkert.org
5577673Snate@binkert.org    @classmethod
5587673Snate@binkert.org    def cxx_predecls(cls, code):
5597673Snate@binkert.org        # most derived types require this, so we just do it here once
5604762Snate@binkert.org        code('#include "base/types.hh"')
5614762Snate@binkert.org
5624762Snate@binkert.org    def getValue(self):
5633101Sstever@eecs.umich.edu        return long(self.value)
5643101Sstever@eecs.umich.edu
5653101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
5663101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
5673101Sstever@eecs.umich.edu
5683101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
5693101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
5703101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
5713101Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
5723101Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
5733101Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
5743101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
5753101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
5763101Sstever@eecs.umich.edu
5773101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
5783101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
5793101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
5803101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
5813101Sstever@eecs.umich.edu
5829184Sandreas.hansson@arm.comclass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
5839184Sandreas.hansson@arm.com
5849184Sandreas.hansson@arm.comclass Cycles(CheckedInt):
5859184Sandreas.hansson@arm.com    cxx_type = 'Cycles'
5869184Sandreas.hansson@arm.com    size = 64
5879184Sandreas.hansson@arm.com    unsigned = True
58811802Sandreas.sandberg@arm.com
5899184Sandreas.hansson@arm.com    def getValue(self):
5909184Sandreas.hansson@arm.com        from _m5.core import Cycles
59110458Sandreas.hansson@arm.com        return Cycles(self.value)
59210458Sandreas.hansson@arm.com
59310458Sandreas.hansson@arm.com    @classmethod
59410458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
59510458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
59610458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
59710458Sandreas.hansson@arm.com        pass
59810458Sandreas.hansson@arm.com
59910458Sandreas.hansson@arm.com    @classmethod
60010458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
60110458Sandreas.hansson@arm.com        code('uint64_t _temp;')
60210458Sandreas.hansson@arm.com        code('bool _ret = to_number(%s, _temp);' % src)
60310458Sandreas.hansson@arm.com        code('if (_ret)')
60410458Sandreas.hansson@arm.com        code('    %s = Cycles(_temp);' % dest)
6053101Sstever@eecs.umich.edu        code('%s _ret;' % ret)
6064446Sbinkertn@umich.edu
60710668SGeoffrey.Blake@arm.comclass Float(ParamValue, float):
6083101Sstever@eecs.umich.edu    cxx_type = 'double'
6095468Snate@binkert.org    cmd_line_settable = True
61010267SGeoffrey.Blake@arm.com
6115468Snate@binkert.org    def __init__(self, value):
6125468Snate@binkert.org        if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
6135468Snate@binkert.org            self.value = float(value)
6145468Snate@binkert.org        else:
6155468Snate@binkert.org            raise TypeError, "Can't convert object of type %s to Float" \
61610267SGeoffrey.Blake@arm.com                  % type(value).__name__
61710267SGeoffrey.Blake@arm.com
61810267SGeoffrey.Blake@arm.com    def __call__(self, value):
61910267SGeoffrey.Blake@arm.com        self.__init__(value)
6204762Snate@binkert.org        return value
6214762Snate@binkert.org
6224762Snate@binkert.org    def getValue(self):
62310380SAndrew.Bardsley@arm.com        return float(self.value)
62410380SAndrew.Bardsley@arm.com
62510380SAndrew.Bardsley@arm.com    def config_value(self):
62610458Sandreas.hansson@arm.com        return self
62710458Sandreas.hansson@arm.com
62810458Sandreas.hansson@arm.com    @classmethod
62910458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
63010458Sandreas.hansson@arm.com        code('#include <sstream>')
63110458Sandreas.hansson@arm.com
63210458Sandreas.hansson@arm.com    @classmethod
63310458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
6343101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
6353101Sstever@eecs.umich.edu
63610267SGeoffrey.Blake@arm.comclass MemorySize(CheckedInt):
6373101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
6383101Sstever@eecs.umich.edu    ex_str = '512MB'
6393101Sstever@eecs.umich.edu    size = 64
6403101Sstever@eecs.umich.edu    unsigned = True
6413101Sstever@eecs.umich.edu    def __init__(self, value):
6423101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
6433102Sstever@eecs.umich.edu            self.value = value.value
6443101Sstever@eecs.umich.edu        else:
6453101Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
6463101Sstever@eecs.umich.edu        self._check()
6474168Sbinkertn@umich.edu
64810267SGeoffrey.Blake@arm.comclass MemorySize32(CheckedInt):
6493101Sstever@eecs.umich.edu    cxx_type = 'uint32_t'
6503101Sstever@eecs.umich.edu    ex_str = '512MB'
6513101Sstever@eecs.umich.edu    size = 32
6523101Sstever@eecs.umich.edu    unsigned = True
6533101Sstever@eecs.umich.edu    def __init__(self, value):
6543101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
6553102Sstever@eecs.umich.edu            self.value = value.value
6563101Sstever@eecs.umich.edu        else:
6573101Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
6583101Sstever@eecs.umich.edu        self._check()
6593101Sstever@eecs.umich.edu
6603101Sstever@eecs.umich.educlass Addr(CheckedInt):
6613101Sstever@eecs.umich.edu    cxx_type = 'Addr'
6623101Sstever@eecs.umich.edu    size = 64
6633101Sstever@eecs.umich.edu    unsigned = True
6643101Sstever@eecs.umich.edu    def __init__(self, value):
6653101Sstever@eecs.umich.edu        if isinstance(value, Addr):
6663101Sstever@eecs.umich.edu            self.value = value.value
66710317Smitch.hayenga@arm.com        else:
66810317Smitch.hayenga@arm.com            try:
66910317Smitch.hayenga@arm.com                # Often addresses are referred to with sizes. Ex: A device
67010317Smitch.hayenga@arm.com                # base address is at "512MB".  Use toMemorySize() to convert
67110317Smitch.hayenga@arm.com                # these into addresses. If the address is not specified with a
6723102Sstever@eecs.umich.edu                # "size", an exception will occur and numeric translation will
67310317Smitch.hayenga@arm.com                # proceed below.
67410317Smitch.hayenga@arm.com                self.value = convert.toMemorySize(value)
67510317Smitch.hayenga@arm.com            except (TypeError, ValueError):
67610317Smitch.hayenga@arm.com                # Convert number to string and use long() to do automatic
67710317Smitch.hayenga@arm.com                # base conversion (requires base=0 for auto-conversion)
6783101Sstever@eecs.umich.edu                self.value = long(str(value), base=0)
6793584Ssaidi@eecs.umich.edu
6803584Ssaidi@eecs.umich.edu        self._check()
6813584Ssaidi@eecs.umich.edu    def __add__(self, other):
6823584Ssaidi@eecs.umich.edu        if isinstance(other, Addr):
6833584Ssaidi@eecs.umich.edu            return self.value + other.value
68410267SGeoffrey.Blake@arm.com        else:
68510267SGeoffrey.Blake@arm.com            return self.value + other
68610267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
68710267SGeoffrey.Blake@arm.com        try:
68810267SGeoffrey.Blake@arm.com            val = convert.toMemorySize(value)
68910267SGeoffrey.Blake@arm.com        except TypeError:
6903101Sstever@eecs.umich.edu            val = long(value)
6919232Sandreas.hansson@arm.com        return "0x%x" % long(val)
6929235Sandreas.hansson@arm.com
6933101Sstever@eecs.umich.educlass AddrRange(ParamValue):
6943101Sstever@eecs.umich.edu    cxx_type = 'AddrRange'
69510676Sandreas.hansson@arm.com
6969411Sandreas.hansson@arm.com    def __init__(self, *args, **kwargs):
69710676Sandreas.hansson@arm.com        # Disable interleaving and hashing by default
6989411Sandreas.hansson@arm.com        self.intlvHighBit = 0
6999411Sandreas.hansson@arm.com        self.xorHighBit = 0
7009411Sandreas.hansson@arm.com        self.intlvBits = 0
7013101Sstever@eecs.umich.edu        self.intlvMatch = 0
7029411Sandreas.hansson@arm.com
7039411Sandreas.hansson@arm.com        def handle_kwargs(self, kwargs):
7049411Sandreas.hansson@arm.com            # An address range needs to have an upper limit, specified
7053101Sstever@eecs.umich.edu            # either explicitly with an end, or as an offset using the
7069232Sandreas.hansson@arm.com            # size keyword.
7073101Sstever@eecs.umich.edu            if 'end' in kwargs:
7089232Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
7093101Sstever@eecs.umich.edu            elif 'size' in kwargs:
7103101Sstever@eecs.umich.edu                self.end = self.start + Addr(kwargs.pop('size')) - 1
7113101Sstever@eecs.umich.edu            else:
7129411Sandreas.hansson@arm.com                raise TypeError, "Either end or size must be specified"
7139411Sandreas.hansson@arm.com
7149411Sandreas.hansson@arm.com            # Now on to the optional bit
71510676Sandreas.hansson@arm.com            if 'intlvHighBit' in kwargs:
71610676Sandreas.hansson@arm.com                self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
7179411Sandreas.hansson@arm.com            if 'xorHighBit' in kwargs:
7189411Sandreas.hansson@arm.com                self.xorHighBit = int(kwargs.pop('xorHighBit'))
7199411Sandreas.hansson@arm.com            if 'intlvBits' in kwargs:
7209411Sandreas.hansson@arm.com                self.intlvBits = int(kwargs.pop('intlvBits'))
7219411Sandreas.hansson@arm.com            if 'intlvMatch' in kwargs:
7223101Sstever@eecs.umich.edu                self.intlvMatch = int(kwargs.pop('intlvMatch'))
7239232Sandreas.hansson@arm.com
7243101Sstever@eecs.umich.edu        if len(args) == 0:
7253101Sstever@eecs.umich.edu            self.start = Addr(kwargs.pop('start'))
7263101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
7273101Sstever@eecs.umich.edu
7289232Sandreas.hansson@arm.com        elif len(args) == 1:
7293101Sstever@eecs.umich.edu            if kwargs:
7305219Ssaidi@eecs.umich.edu                self.start = Addr(args[0])
7319232Sandreas.hansson@arm.com                handle_kwargs(self, kwargs)
7329232Sandreas.hansson@arm.com            elif isinstance(args[0], (list, tuple)):
7333101Sstever@eecs.umich.edu                self.start = Addr(args[0][0])
7349232Sandreas.hansson@arm.com                self.end = Addr(args[0][1])
7359232Sandreas.hansson@arm.com            else:
7363101Sstever@eecs.umich.edu                self.start = Addr(0)
7373101Sstever@eecs.umich.edu                self.end = Addr(args[0]) - 1
7389232Sandreas.hansson@arm.com
7399232Sandreas.hansson@arm.com        elif len(args) == 2:
7403101Sstever@eecs.umich.edu            self.start = Addr(args[0])
7413101Sstever@eecs.umich.edu            self.end = Addr(args[1])
7423101Sstever@eecs.umich.edu        else:
7433101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
7449232Sandreas.hansson@arm.com
7453101Sstever@eecs.umich.edu        if kwargs:
7463101Sstever@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
74711620SMatthew.Poremba@amd.com
74811620SMatthew.Poremba@amd.com    def __str__(self):
74911620SMatthew.Poremba@amd.com        return '%s:%s:%s:%s:%s:%s' \
7509232Sandreas.hansson@arm.com            % (self.start, self.end, self.intlvHighBit, self.xorHighBit,\
7519232Sandreas.hansson@arm.com               self.intlvBits, self.intlvMatch)
7529411Sandreas.hansson@arm.com
7539411Sandreas.hansson@arm.com    def size(self):
7543101Sstever@eecs.umich.edu        # Divide the size by the size of the interleaving slice
7557673Snate@binkert.org        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
7567673Snate@binkert.org
7579232Sandreas.hansson@arm.com    @classmethod
7589235Sandreas.hansson@arm.com    def cxx_predecls(cls, code):
7597675Snate@binkert.org        Addr.cxx_predecls(code)
7607675Snate@binkert.org        code('#include "base/addr_range.hh"')
76111988Sandreas.sandberg@arm.com
76211988Sandreas.sandberg@arm.com    @classmethod
76311988Sandreas.sandberg@arm.com    def pybind_predecls(cls, code):
76411988Sandreas.sandberg@arm.com        Addr.pybind_predecls(code)
76511988Sandreas.sandberg@arm.com        code('#include "base/addr_range.hh"')
76610458Sandreas.hansson@arm.com
76710458Sandreas.hansson@arm.com    @classmethod
76810458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
76910458Sandreas.hansson@arm.com        code('#include <sstream>')
77010458Sandreas.hansson@arm.com
77111620SMatthew.Poremba@amd.com    @classmethod
77211620SMatthew.Poremba@amd.com    def cxx_ini_parse(cls, code, src, dest, ret):
77310458Sandreas.hansson@arm.com        code('uint64_t _start, _end, _intlvHighBit = 0, _xorHighBit = 0;')
77410458Sandreas.hansson@arm.com        code('uint64_t _intlvBits = 0, _intlvMatch = 0;')
77510458Sandreas.hansson@arm.com        code('char _sep;')
77610458Sandreas.hansson@arm.com        code('std::istringstream _stream(${src});')
77710458Sandreas.hansson@arm.com        code('_stream >> _start;')
77811620SMatthew.Poremba@amd.com        code('_stream.get(_sep);')
77911620SMatthew.Poremba@amd.com        code('_stream >> _end;')
78011620SMatthew.Poremba@amd.com        code('if (!_stream.fail() && !_stream.eof()) {')
78111620SMatthew.Poremba@amd.com        code('    _stream.get(_sep);')
78211620SMatthew.Poremba@amd.com        code('    _stream >> _intlvHighBit;')
78311620SMatthew.Poremba@amd.com        code('    _stream.get(_sep);')
78411620SMatthew.Poremba@amd.com        code('    _stream >> _xorHighBit;')
78511620SMatthew.Poremba@amd.com        code('    _stream.get(_sep);')
78611620SMatthew.Poremba@amd.com        code('    _stream >> _intlvBits;')
78711620SMatthew.Poremba@amd.com        code('    _stream.get(_sep);')
78810458Sandreas.hansson@arm.com        code('    _stream >> _intlvMatch;')
78910458Sandreas.hansson@arm.com        code('}')
79010458Sandreas.hansson@arm.com        code('bool _ret = !_stream.fail() &&'
79111620SMatthew.Poremba@amd.com            '_stream.eof() && _sep == \':\';')
79211620SMatthew.Poremba@amd.com        code('if (_ret)')
79310458Sandreas.hansson@arm.com        code('   ${dest} = AddrRange(_start, _end, _intlvHighBit, \
79410458Sandreas.hansson@arm.com                _xorHighBit, _intlvBits, _intlvMatch);')
7954762Snate@binkert.org        code('${ret} _ret;')
79611991Sandreas.sandberg@arm.com
79711802Sandreas.sandberg@arm.com    def getValue(self):
7984762Snate@binkert.org        # Go from the Python class to the wrapped C++ class
7999411Sandreas.hansson@arm.com        from _m5.range import AddrRange
80010676Sandreas.hansson@arm.com
80110676Sandreas.hansson@arm.com        return AddrRange(long(self.start), long(self.end),
8023101Sstever@eecs.umich.edu                         int(self.intlvHighBit), int(self.xorHighBit),
8033101Sstever@eecs.umich.edu                         int(self.intlvBits), int(self.intlvMatch))
8043101Sstever@eecs.umich.edu
8053101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
8063101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and
8073101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
80810267SGeoffrey.Blake@arm.comclass Bool(ParamValue):
80910267SGeoffrey.Blake@arm.com    cxx_type = 'bool'
8103101Sstever@eecs.umich.edu    cmd_line_settable = True
8113101Sstever@eecs.umich.edu
8123102Sstever@eecs.umich.edu    def __init__(self, value):
8133101Sstever@eecs.umich.edu        try:
8143101Sstever@eecs.umich.edu            self.value = convert.toBool(value)
8153101Sstever@eecs.umich.edu        except TypeError:
81610267SGeoffrey.Blake@arm.com            self.value = bool(value)
81710267SGeoffrey.Blake@arm.com
81810267SGeoffrey.Blake@arm.com    def __call__(self, value):
81910267SGeoffrey.Blake@arm.com        self.__init__(value)
8204762Snate@binkert.org        return value
8214762Snate@binkert.org
8224762Snate@binkert.org    def getValue(self):
8233101Sstever@eecs.umich.edu        return bool(self.value)
8243101Sstever@eecs.umich.edu
8253101Sstever@eecs.umich.edu    def __str__(self):
8268934SBrad.Beckmann@amd.com        return str(self.value)
8278934SBrad.Beckmann@amd.com
8288934SBrad.Beckmann@amd.com    # implement truth value testing for Bool parameters so that these params
8298934SBrad.Beckmann@amd.com    # evaluate correctly during the python configuration phase
8308934SBrad.Beckmann@amd.com    def __nonzero__(self):
8313101Sstever@eecs.umich.edu        return bool(self.value)
8323101Sstever@eecs.umich.edu
8333101Sstever@eecs.umich.edu    def ini_str(self):
8343101Sstever@eecs.umich.edu        if self.value:
8353101Sstever@eecs.umich.edu            return 'true'
83610380SAndrew.Bardsley@arm.com        return 'false'
83710380SAndrew.Bardsley@arm.com
83810380SAndrew.Bardsley@arm.com    def config_value(self):
83910458Sandreas.hansson@arm.com        return self.value
84010458Sandreas.hansson@arm.com
84110458Sandreas.hansson@arm.com    @classmethod
84210458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
84310458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
84410458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
84510458Sandreas.hansson@arm.com        pass
84610458Sandreas.hansson@arm.com
84710458Sandreas.hansson@arm.com    @classmethod
84810458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
8493101Sstever@eecs.umich.edu        code('%s to_bool(%s, %s);' % (ret, src, dest))
8503101Sstever@eecs.umich.edu
8513101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
8523101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
8533101Sstever@eecs.umich.edu    bytes[5] += val
8543101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
8553101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
8563101Sstever@eecs.umich.edu        bytes[i] = rem
8573101Sstever@eecs.umich.edu        if val == 0:
8583101Sstever@eecs.umich.edu            break
8593101Sstever@eecs.umich.edu        bytes[i - 1] += val
8603101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
8614380Sbinkertn@umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
8624380Sbinkertn@umich.edu
8634380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
8643101Sstever@eecs.umich.edudef NextEthernetAddr():
8654380Sbinkertn@umich.edu    global _NextEthernetAddr
8664380Sbinkertn@umich.edu
8674380Sbinkertn@umich.edu    value = _NextEthernetAddr
8683101Sstever@eecs.umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
8693101Sstever@eecs.umich.edu    return value
8703101Sstever@eecs.umich.edu
87110267SGeoffrey.Blake@arm.comclass EthernetAddr(ParamValue):
87210267SGeoffrey.Blake@arm.com    cxx_type = 'Net::EthAddr'
8737673Snate@binkert.org    ex_str = "00:90:00:00:00:01"
8747673Snate@binkert.org    cmd_line_settable = True
8757673Snate@binkert.org
8767673Snate@binkert.org    @classmethod
8777673Snate@binkert.org    def cxx_predecls(cls, code):
8783101Sstever@eecs.umich.edu        code('#include "base/inet.hh"')
8793101Sstever@eecs.umich.edu
8803101Sstever@eecs.umich.edu    def __init__(self, value):
8813101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
8823101Sstever@eecs.umich.edu            self.value = value
8833101Sstever@eecs.umich.edu            return
8843101Sstever@eecs.umich.edu
8853101Sstever@eecs.umich.edu        if not isinstance(value, str):
8863101Sstever@eecs.umich.edu            raise TypeError, "expected an ethernet address and didn't get one"
8873101Sstever@eecs.umich.edu
8883101Sstever@eecs.umich.edu        bytes = value.split(':')
8893101Sstever@eecs.umich.edu        if len(bytes) != 6:
8903101Sstever@eecs.umich.edu            raise TypeError, 'invalid ethernet address %s' % value
8919941SGeoffrey.Blake@arm.com
8923101Sstever@eecs.umich.edu        for byte in bytes:
8933101Sstever@eecs.umich.edu            if not 0 <= int(byte, base=16) <= 0xff:
8943101Sstever@eecs.umich.edu                raise TypeError, 'invalid ethernet address %s' % value
8953101Sstever@eecs.umich.edu
89610267SGeoffrey.Blake@arm.com        self.value = value
89710267SGeoffrey.Blake@arm.com
89810267SGeoffrey.Blake@arm.com    def __call__(self, value):
89910267SGeoffrey.Blake@arm.com        self.__init__(value)
9003101Sstever@eecs.umich.edu        return value
9013101Sstever@eecs.umich.edu
9024380Sbinkertn@umich.edu    def unproxy(self, base):
9033101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
9043101Sstever@eecs.umich.edu            return EthernetAddr(self.value())
9054762Snate@binkert.org        return self
90611988Sandreas.sandberg@arm.com
9074762Snate@binkert.org    def getValue(self):
9084762Snate@binkert.org        from _m5.net import EthAddr
90911228SAndrew.Bardsley@arm.com        return EthAddr(self.value)
91011228SAndrew.Bardsley@arm.com
91111228SAndrew.Bardsley@arm.com    def __str__(self):
9124380Sbinkertn@umich.edu        return self.value
9134380Sbinkertn@umich.edu
9143101Sstever@eecs.umich.edu    def ini_str(self):
91510458Sandreas.hansson@arm.com        return self.value
91610458Sandreas.hansson@arm.com
91710458Sandreas.hansson@arm.com    @classmethod
91810458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
91910458Sandreas.hansson@arm.com        code('%s = Net::EthAddr(%s);' % (dest, src))
9207777Sgblack@eecs.umich.edu        code('%s true;' % ret)
9217777Sgblack@eecs.umich.edu
9227777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
9237777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
92410267SGeoffrey.Blake@arm.comclass IpAddress(ParamValue):
92510267SGeoffrey.Blake@arm.com    cxx_type = 'Net::IpAddress'
9267777Sgblack@eecs.umich.edu    ex_str = "127.0.0.1"
9277777Sgblack@eecs.umich.edu    cmd_line_settable = True
9287777Sgblack@eecs.umich.edu
9297777Sgblack@eecs.umich.edu    @classmethod
9307777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
9317777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
9327777Sgblack@eecs.umich.edu
9337777Sgblack@eecs.umich.edu    def __init__(self, value):
9347777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
9357777Sgblack@eecs.umich.edu            self.ip = value.ip
9367777Sgblack@eecs.umich.edu        else:
9377777Sgblack@eecs.umich.edu            try:
9387777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
9397777Sgblack@eecs.umich.edu            except TypeError:
9407777Sgblack@eecs.umich.edu                self.ip = long(value)
94110267SGeoffrey.Blake@arm.com        self.verifyIp()
94210267SGeoffrey.Blake@arm.com
94310267SGeoffrey.Blake@arm.com    def __call__(self, value):
94410267SGeoffrey.Blake@arm.com        self.__init__(value)
9458579Ssteve.reinhardt@amd.com        return value
9468579Ssteve.reinhardt@amd.com
9478579Ssteve.reinhardt@amd.com    def __str__(self):
9488579Ssteve.reinhardt@amd.com        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
9498579Ssteve.reinhardt@amd.com        return '%d.%d.%d.%d' % tuple(tup)
9508579Ssteve.reinhardt@amd.com
9518579Ssteve.reinhardt@amd.com    def __eq__(self, other):
9528579Ssteve.reinhardt@amd.com        if isinstance(other, IpAddress):
9538579Ssteve.reinhardt@amd.com            return self.ip == other.ip
9548579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
9558579Ssteve.reinhardt@amd.com            try:
9568579Ssteve.reinhardt@amd.com                return self.ip == convert.toIpAddress(other)
9578579Ssteve.reinhardt@amd.com            except:
9588579Ssteve.reinhardt@amd.com                return False
9598579Ssteve.reinhardt@amd.com        else:
9608579Ssteve.reinhardt@amd.com            return self.ip == other
9618579Ssteve.reinhardt@amd.com
9628579Ssteve.reinhardt@amd.com    def __ne__(self, other):
9637777Sgblack@eecs.umich.edu        return not (self == other)
9647777Sgblack@eecs.umich.edu
9657798Sgblack@eecs.umich.edu    def verifyIp(self):
9667777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
9677777Sgblack@eecs.umich.edu            raise TypeError, "invalid ip address %#08x" % self.ip
96811988Sandreas.sandberg@arm.com
9697777Sgblack@eecs.umich.edu    def getValue(self):
9707777Sgblack@eecs.umich.edu        from _m5.net import IpAddress
9717777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
9727777Sgblack@eecs.umich.edu
9737777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
9747777Sgblack@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
9757777Sgblack@eecs.umich.edu# positional or keyword arguments.
97610267SGeoffrey.Blake@arm.comclass IpNetmask(IpAddress):
97710267SGeoffrey.Blake@arm.com    cxx_type = 'Net::IpNetmask'
9787777Sgblack@eecs.umich.edu    ex_str = "127.0.0.0/24"
9797777Sgblack@eecs.umich.edu    cmd_line_settable = True
9807777Sgblack@eecs.umich.edu
9817777Sgblack@eecs.umich.edu    @classmethod
9827777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
9837777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
9847777Sgblack@eecs.umich.edu
9857777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
9867777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
9877777Sgblack@eecs.umich.edu            if key in kwargs:
9887777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
9897777Sgblack@eecs.umich.edu            elif elseVal:
9907777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
9917777Sgblack@eecs.umich.edu            else:
9927777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
9937777Sgblack@eecs.umich.edu
9947777Sgblack@eecs.umich.edu        if len(args) == 0:
9957777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
9967777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
9977777Sgblack@eecs.umich.edu
9987777Sgblack@eecs.umich.edu        elif len(args) == 1:
9997777Sgblack@eecs.umich.edu            if kwargs:
10007777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
10017777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
10027777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
10037777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
10047777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
10057777Sgblack@eecs.umich.edu                self.ip = args[0].ip
10067777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
10077777Sgblack@eecs.umich.edu            else:
10087777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
10097777Sgblack@eecs.umich.edu
10107777Sgblack@eecs.umich.edu        elif len(args) == 2:
10117777Sgblack@eecs.umich.edu            self.ip = args[0]
10127777Sgblack@eecs.umich.edu            self.netmask = args[1]
10137777Sgblack@eecs.umich.edu        else:
10147777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
10157777Sgblack@eecs.umich.edu
10167777Sgblack@eecs.umich.edu        if kwargs:
10177777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
10187777Sgblack@eecs.umich.edu
101910267SGeoffrey.Blake@arm.com        self.verify()
102010267SGeoffrey.Blake@arm.com
102110267SGeoffrey.Blake@arm.com    def __call__(self, value):
102210267SGeoffrey.Blake@arm.com        self.__init__(value)
10238579Ssteve.reinhardt@amd.com        return value
10248579Ssteve.reinhardt@amd.com
10258579Ssteve.reinhardt@amd.com    def __str__(self):
10268579Ssteve.reinhardt@amd.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
10278579Ssteve.reinhardt@amd.com
10288579Ssteve.reinhardt@amd.com    def __eq__(self, other):
10298579Ssteve.reinhardt@amd.com        if isinstance(other, IpNetmask):
10308579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.netmask == other.netmask
10318579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
10328579Ssteve.reinhardt@amd.com            try:
10338579Ssteve.reinhardt@amd.com                return (self.ip, self.netmask) == convert.toIpNetmask(other)
10348579Ssteve.reinhardt@amd.com            except:
10358579Ssteve.reinhardt@amd.com                return False
10368579Ssteve.reinhardt@amd.com        else:
10377777Sgblack@eecs.umich.edu            return False
10387777Sgblack@eecs.umich.edu
10397777Sgblack@eecs.umich.edu    def verify(self):
10407777Sgblack@eecs.umich.edu        self.verifyIp()
10417777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
10427777Sgblack@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
104311988Sandreas.sandberg@arm.com
10447777Sgblack@eecs.umich.edu    def getValue(self):
10457777Sgblack@eecs.umich.edu        from _m5.net import IpNetmask
10467777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
10477777Sgblack@eecs.umich.edu
10487777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
10497777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
105010267SGeoffrey.Blake@arm.comclass IpWithPort(IpAddress):
105110267SGeoffrey.Blake@arm.com    cxx_type = 'Net::IpWithPort'
10527777Sgblack@eecs.umich.edu    ex_str = "127.0.0.1:80"
10537777Sgblack@eecs.umich.edu    cmd_line_settable = True
10547777Sgblack@eecs.umich.edu
10557777Sgblack@eecs.umich.edu    @classmethod
10567777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10577777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10587777Sgblack@eecs.umich.edu
10597777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10607777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10617777Sgblack@eecs.umich.edu            if key in kwargs:
10627777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10637777Sgblack@eecs.umich.edu            elif elseVal:
10647777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10657777Sgblack@eecs.umich.edu            else:
10667777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
10677777Sgblack@eecs.umich.edu
10687777Sgblack@eecs.umich.edu        if len(args) == 0:
10697777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
10707777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
10717777Sgblack@eecs.umich.edu
10727777Sgblack@eecs.umich.edu        elif len(args) == 1:
10737777Sgblack@eecs.umich.edu            if kwargs:
10747777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
10757777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
10767777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
10777777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
10787777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpWithPort):
10797777Sgblack@eecs.umich.edu                self.ip = args[0].ip
10807777Sgblack@eecs.umich.edu                self.port = args[0].port
10817777Sgblack@eecs.umich.edu            else:
10827777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
10837777Sgblack@eecs.umich.edu
10847777Sgblack@eecs.umich.edu        elif len(args) == 2:
10857777Sgblack@eecs.umich.edu            self.ip = args[0]
10867777Sgblack@eecs.umich.edu            self.port = args[1]
10877777Sgblack@eecs.umich.edu        else:
10887777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
10897777Sgblack@eecs.umich.edu
10907777Sgblack@eecs.umich.edu        if kwargs:
10917777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
10927777Sgblack@eecs.umich.edu
109310267SGeoffrey.Blake@arm.com        self.verify()
109410267SGeoffrey.Blake@arm.com
109510267SGeoffrey.Blake@arm.com    def __call__(self, value):
109610267SGeoffrey.Blake@arm.com        self.__init__(value)
10978579Ssteve.reinhardt@amd.com        return value
10988579Ssteve.reinhardt@amd.com
10998579Ssteve.reinhardt@amd.com    def __str__(self):
11008579Ssteve.reinhardt@amd.com        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
11018579Ssteve.reinhardt@amd.com
11028579Ssteve.reinhardt@amd.com    def __eq__(self, other):
11038579Ssteve.reinhardt@amd.com        if isinstance(other, IpWithPort):
11048579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.port == other.port
11058579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
11068579Ssteve.reinhardt@amd.com            try:
11078579Ssteve.reinhardt@amd.com                return (self.ip, self.port) == convert.toIpWithPort(other)
11088579Ssteve.reinhardt@amd.com            except:
11098579Ssteve.reinhardt@amd.com                return False
11108579Ssteve.reinhardt@amd.com        else:
11117777Sgblack@eecs.umich.edu            return False
11127777Sgblack@eecs.umich.edu
11137777Sgblack@eecs.umich.edu    def verify(self):
11147777Sgblack@eecs.umich.edu        self.verifyIp()
11157777Sgblack@eecs.umich.edu        if self.port < 0 or self.port > 0xffff:
11167777Sgblack@eecs.umich.edu            raise TypeError, "invalid port %d" % self.port
111711988Sandreas.sandberg@arm.com
11187777Sgblack@eecs.umich.edu    def getValue(self):
11197777Sgblack@eecs.umich.edu        from _m5.net import IpWithPort
11203932Sbinkertn@umich.edu        return IpWithPort(self.ip, self.port)
112110380SAndrew.Bardsley@arm.com
11223932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
11233932Sbinkertn@umich.edu                 "%a %b %d %H:%M:%S %Y",
11243932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
11253932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
11263932Sbinkertn@umich.edu                 "%Y/%m/%d",
11273932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
11283932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
11293932Sbinkertn@umich.edu                 "%m/%d/%Y",
11303932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M:%S",
11313932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M",
11323932Sbinkertn@umich.edu                 "%m/%d/%y"]
11333885Sbinkertn@umich.edu
11343932Sbinkertn@umich.edu
11353932Sbinkertn@umich.edudef parse_time(value):
11363885Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
11373932Sbinkertn@umich.edu    from datetime import datetime, date
11383932Sbinkertn@umich.edu
11393932Sbinkertn@umich.edu    if isinstance(value, struct_time):
11403932Sbinkertn@umich.edu        return value
11413932Sbinkertn@umich.edu
11423932Sbinkertn@umich.edu    if isinstance(value, (int, long)):
11433932Sbinkertn@umich.edu        return gmtime(value)
11443932Sbinkertn@umich.edu
11453932Sbinkertn@umich.edu    if isinstance(value, (datetime, date)):
11463932Sbinkertn@umich.edu        return value.timetuple()
11473932Sbinkertn@umich.edu
11483932Sbinkertn@umich.edu    if isinstance(value, str):
11493932Sbinkertn@umich.edu        if value in ('Now', 'Today'):
11503932Sbinkertn@umich.edu            return time.gmtime(time.time())
11513932Sbinkertn@umich.edu
11523932Sbinkertn@umich.edu        for format in time_formats:
11533932Sbinkertn@umich.edu            try:
11543932Sbinkertn@umich.edu                return strptime(value, format)
11553885Sbinkertn@umich.edu            except ValueError:
11563885Sbinkertn@umich.edu                pass
11573885Sbinkertn@umich.edu
11583885Sbinkertn@umich.edu    raise ValueError, "Could not parse '%s' as a time" % value
11594762Snate@binkert.org
11607673Snate@binkert.orgclass Time(ParamValue):
11617673Snate@binkert.org    cxx_type = 'tm'
11627673Snate@binkert.org
11637673Snate@binkert.org    @classmethod
11647673Snate@binkert.org    def cxx_predecls(cls, code):
11653885Sbinkertn@umich.edu        code('#include <time.h>')
11663932Sbinkertn@umich.edu
11673885Sbinkertn@umich.edu    def __init__(self, value):
116810267SGeoffrey.Blake@arm.com        self.value = parse_time(value)
116910267SGeoffrey.Blake@arm.com
117010267SGeoffrey.Blake@arm.com    def __call__(self, value):
117110267SGeoffrey.Blake@arm.com        self.__init__(value)
11724762Snate@binkert.org        return value
117311988Sandreas.sandberg@arm.com
117411988Sandreas.sandberg@arm.com    def getValue(self):
11754762Snate@binkert.org        from _m5.core import tm
117611988Sandreas.sandberg@arm.com        import calendar
11774762Snate@binkert.org
11783885Sbinkertn@umich.edu        return tm.gmtime(calendar.timegm(self.value))
11794762Snate@binkert.org
11803885Sbinkertn@umich.edu    def __str__(self):
11813885Sbinkertn@umich.edu        return time.asctime(self.value)
11823932Sbinkertn@umich.edu
11833885Sbinkertn@umich.edu    def ini_str(self):
11848664SAli.Saidi@ARM.com        return str(self)
118510380SAndrew.Bardsley@arm.com
11868664SAli.Saidi@ARM.com    def get_config_as_dict(self):
11878664SAli.Saidi@ARM.com        assert false
118810458Sandreas.hansson@arm.com        return str(self)
118910458Sandreas.hansson@arm.com
119010458Sandreas.hansson@arm.com    @classmethod
119110458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
119210458Sandreas.hansson@arm.com        code('#include <time.h>')
119310458Sandreas.hansson@arm.com
119410458Sandreas.hansson@arm.com    @classmethod
119510458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
119610458Sandreas.hansson@arm.com        code('char *_parse_ret = strptime((${src}).c_str(),')
119710458Sandreas.hansson@arm.com        code('    "%a %b %d %H:%M:%S %Y", &(${dest}));')
11983101Sstever@eecs.umich.edu        code('${ret} _parse_ret && *_parse_ret == \'\\0\';');
11993101Sstever@eecs.umich.edu
12003101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
12013101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
12023101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
12033101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
12043101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
12053101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
12063101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
12073101Sstever@eecs.umich.edu
12083101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
12093101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
12103101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
12113101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
12124762Snate@binkert.org# derive the new type from the appropriate base class on the fly.
12133101Sstever@eecs.umich.edu
12145033Smilesck@eecs.umich.eduallEnums = {}
12154762Snate@binkert.org# Metaclass for Enum types
12164762Snate@binkert.orgclass MetaEnum(MetaParamValue):
12174762Snate@binkert.org    def __new__(mcls, name, bases, dict):
12184762Snate@binkert.org        assert name not in allEnums
12194762Snate@binkert.org
12204762Snate@binkert.org        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
12214762Snate@binkert.org        allEnums[name] = cls
12223101Sstever@eecs.umich.edu        return cls
12233101Sstever@eecs.umich.edu
12243101Sstever@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
12253101Sstever@eecs.umich.edu        if init_dict.has_key('map'):
12263101Sstever@eecs.umich.edu            if not isinstance(cls.map, dict):
12273101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'map' " \
12283101Sstever@eecs.umich.edu                      "must be of type dict"
12293101Sstever@eecs.umich.edu            # build list of value strings from map
12303101Sstever@eecs.umich.edu            cls.vals = cls.map.keys()
12313101Sstever@eecs.umich.edu            cls.vals.sort()
12323101Sstever@eecs.umich.edu        elif init_dict.has_key('vals'):
12333101Sstever@eecs.umich.edu            if not isinstance(cls.vals, list):
12343101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'vals' " \
12353101Sstever@eecs.umich.edu                      "must be of type list"
12363101Sstever@eecs.umich.edu            # build string->value map from vals sequence
12373101Sstever@eecs.umich.edu            cls.map = {}
12383101Sstever@eecs.umich.edu            for idx,val in enumerate(cls.vals):
12393101Sstever@eecs.umich.edu                cls.map[val] = idx
12403101Sstever@eecs.umich.edu        else:
12413101Sstever@eecs.umich.edu            raise TypeError, "Enum-derived class must define "\
12424762Snate@binkert.org                  "attribute 'map' or 'vals'"
12433101Sstever@eecs.umich.edu
12443101Sstever@eecs.umich.edu        cls.cxx_type = 'Enums::%s' % name
12453101Sstever@eecs.umich.edu
12463101Sstever@eecs.umich.edu        super(MetaEnum, cls).__init__(name, bases, init_dict)
12473101Sstever@eecs.umich.edu
12483101Sstever@eecs.umich.edu    # Generate C++ class declaration for this enum type.
12497673Snate@binkert.org    # Note that we wrap the enum in a class/struct to act as a namespace,
125010201SAndrew.Bardsley@arm.com    # so that the enum strings can be brief w/o worrying about collisions.
125110201SAndrew.Bardsley@arm.com    def cxx_decl(cls, code):
125210201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
125310201SAndrew.Bardsley@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
125410201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
12557673Snate@binkert.org        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
125610201SAndrew.Bardsley@arm.com
125710201SAndrew.Bardsley@arm.com        code('''\
12587673Snate@binkert.org#ifndef $idem_macro
125910201SAndrew.Bardsley@arm.com#define $idem_macro
12607673Snate@binkert.org
12617673Snate@binkert.org$wrapper $wrapper_name {
12627673Snate@binkert.org    enum $name {
12634762Snate@binkert.org''')
12647673Snate@binkert.org        code.indent(2)
12658902Sandreas.hansson@arm.com        for val in cls.vals:
12667673Snate@binkert.org            code('$val = ${{cls.map[val]}},')
126710201SAndrew.Bardsley@arm.com        code('Num_$name = ${{len(cls.vals)}}')
12684762Snate@binkert.org        code.dedent(2)
126910201SAndrew.Bardsley@arm.com        code('    };')
127010201SAndrew.Bardsley@arm.com
127110201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
127210201SAndrew.Bardsley@arm.com            code('    static const char *${name}Strings[Num_${name}];')
127310201SAndrew.Bardsley@arm.com            code('};')
127410201SAndrew.Bardsley@arm.com        else:
127510201SAndrew.Bardsley@arm.com            code('extern const char *${name}Strings[Num_${name}];')
127610201SAndrew.Bardsley@arm.com            code('}')
127710201SAndrew.Bardsley@arm.com
12787673Snate@binkert.org        code()
12797673Snate@binkert.org        code('#endif // $idem_macro')
128010201SAndrew.Bardsley@arm.com
128110201SAndrew.Bardsley@arm.com    def cxx_def(cls, code):
128210201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
128310201SAndrew.Bardsley@arm.com        file_name = cls.__name__
128410201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
128510201SAndrew.Bardsley@arm.com
128610201SAndrew.Bardsley@arm.com        code('#include "enums/$file_name.hh"')
128710201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
128810201SAndrew.Bardsley@arm.com            code('const char *${wrapper_name}::${name}Strings'
128910201SAndrew.Bardsley@arm.com                '[Num_${name}] =')
129010201SAndrew.Bardsley@arm.com        else:
129110201SAndrew.Bardsley@arm.com            code('namespace Enums {')
129210201SAndrew.Bardsley@arm.com            code.indent(1)
129310201SAndrew.Bardsley@arm.com            code(' const char *${name}Strings[Num_${name}] =')
129410201SAndrew.Bardsley@arm.com
12954762Snate@binkert.org        code('{')
12967673Snate@binkert.org        code.indent(1)
129710201SAndrew.Bardsley@arm.com        for val in cls.vals:
129810201SAndrew.Bardsley@arm.com            code('"$val",')
129910201SAndrew.Bardsley@arm.com        code.dedent(1)
130010201SAndrew.Bardsley@arm.com        code('};')
130110201SAndrew.Bardsley@arm.com
130210201SAndrew.Bardsley@arm.com        if not cls.wrapper_is_struct:
13033101Sstever@eecs.umich.edu            code('} // namespace $wrapper_name')
130411988Sandreas.sandberg@arm.com            code.dedent(1)
130511988Sandreas.sandberg@arm.com
130611988Sandreas.sandberg@arm.com    def pybind_def(cls, code):
130711988Sandreas.sandberg@arm.com        name = cls.__name__
130811988Sandreas.sandberg@arm.com        wrapper_name = cls.wrapper_name
130911988Sandreas.sandberg@arm.com        enum_name = cls.__name__ if cls.enum_name is None else cls.enum_name
131011988Sandreas.sandberg@arm.com
131111988Sandreas.sandberg@arm.com        code('''#include "pybind11/pybind11.h"
131211988Sandreas.sandberg@arm.com#include "pybind11/stl.h"
131311988Sandreas.sandberg@arm.com
131411988Sandreas.sandberg@arm.com#include <sim/init.hh>
131511988Sandreas.sandberg@arm.com
131611988Sandreas.sandberg@arm.comnamespace py = pybind11;
131711988Sandreas.sandberg@arm.com
131811988Sandreas.sandberg@arm.comstatic void
131911988Sandreas.sandberg@arm.commodule_init(py::module &m_internal)
132011988Sandreas.sandberg@arm.com{
132111988Sandreas.sandberg@arm.com    py::module m = m_internal.def_submodule("enum_${name}");
132211988Sandreas.sandberg@arm.com
132311988Sandreas.sandberg@arm.com    py::enum_<${wrapper_name}::${enum_name}>(m, "enum_${name}")
132411988Sandreas.sandberg@arm.com''')
132511988Sandreas.sandberg@arm.com
132611988Sandreas.sandberg@arm.com        code.indent()
132711988Sandreas.sandberg@arm.com        code.indent()
132811988Sandreas.sandberg@arm.com        for val in cls.vals:
132911988Sandreas.sandberg@arm.com            code('.value("${val}", ${wrapper_name}::${val})')
133011988Sandreas.sandberg@arm.com        code('.value("Num_${name}", ${wrapper_name}::Num_${enum_name})')
133111988Sandreas.sandberg@arm.com        code('.export_values()')
133211988Sandreas.sandberg@arm.com        code(';')
133311988Sandreas.sandberg@arm.com        code.dedent()
133411988Sandreas.sandberg@arm.com
133511988Sandreas.sandberg@arm.com        code('}')
133611988Sandreas.sandberg@arm.com        code.dedent()
133711988Sandreas.sandberg@arm.com        code()
13388596Ssteve.reinhardt@amd.com        code('static EmbeddedPyBind embed_enum("enum_${name}", module_init);')
13393101Sstever@eecs.umich.edu
13403101Sstever@eecs.umich.edu
13413101Sstever@eecs.umich.edu# Base class for enum types.
13423101Sstever@eecs.umich.educlass Enum(ParamValue):
134310267SGeoffrey.Blake@arm.com    __metaclass__ = MetaEnum
13443101Sstever@eecs.umich.edu    vals = []
134510201SAndrew.Bardsley@arm.com    cmd_line_settable = True
134610201SAndrew.Bardsley@arm.com
134710201SAndrew.Bardsley@arm.com    # The name of the wrapping namespace or struct
134810201SAndrew.Bardsley@arm.com    wrapper_name = 'Enums'
134910201SAndrew.Bardsley@arm.com
135010201SAndrew.Bardsley@arm.com    # If true, the enum is wrapped in a struct rather than a namespace
135110201SAndrew.Bardsley@arm.com    wrapper_is_struct = False
135210201SAndrew.Bardsley@arm.com
135310201SAndrew.Bardsley@arm.com    # If not None, use this as the enum name rather than this class name
13543101Sstever@eecs.umich.edu    enum_name = None
13553101Sstever@eecs.umich.edu
13563101Sstever@eecs.umich.edu    def __init__(self, value):
13573101Sstever@eecs.umich.edu        if value not in self.map:
13583101Sstever@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
13593101Sstever@eecs.umich.edu                  % (value, self.vals)
136010267SGeoffrey.Blake@arm.com        self.value = value
136110267SGeoffrey.Blake@arm.com
136210267SGeoffrey.Blake@arm.com    def __call__(self, value):
136310267SGeoffrey.Blake@arm.com        self.__init__(value)
13647675Snate@binkert.org        return value
13657675Snate@binkert.org
13667675Snate@binkert.org    @classmethod
13677675Snate@binkert.org    def cxx_predecls(cls, code):
13687675Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
136910458Sandreas.hansson@arm.com
137010458Sandreas.hansson@arm.com    @classmethod
137110458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
137210458Sandreas.hansson@arm.com        code('if (false) {')
137310458Sandreas.hansson@arm.com        for elem_name in cls.map.iterkeys():
137410458Sandreas.hansson@arm.com            code('} else if (%s == "%s") {' % (src, elem_name))
137510458Sandreas.hansson@arm.com            code.indent()
137610458Sandreas.hansson@arm.com            code('%s = Enums::%s;' % (dest, elem_name))
137710458Sandreas.hansson@arm.com            code('%s true;' % ret)
137810458Sandreas.hansson@arm.com            code.dedent()
137910458Sandreas.hansson@arm.com        code('} else {')
138010458Sandreas.hansson@arm.com        code('    %s false;' % ret)
13814762Snate@binkert.org        code('}')
138211988Sandreas.sandberg@arm.com
138311988Sandreas.sandberg@arm.com    def getValue(self):
138411988Sandreas.sandberg@arm.com        import m5.internal.params
13854762Snate@binkert.org        e = getattr(m5.internal.params, "enum_%s" % self.__class__.__name__)
13863101Sstever@eecs.umich.edu        return e(self.map[self.value])
13873101Sstever@eecs.umich.edu
13883101Sstever@eecs.umich.edu    def __str__(self):
13893101Sstever@eecs.umich.edu        return self.value
13903101Sstever@eecs.umich.edu
13913101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it?
13924167Sbinkertn@umich.edufrequency_tolerance = 0.001  # 0.1%
13933101Sstever@eecs.umich.edu
139410267SGeoffrey.Blake@arm.comclass TickParamValue(NumericParamValue):
139510267SGeoffrey.Blake@arm.com    cxx_type = 'Tick'
13967673Snate@binkert.org    ex_str = "1MHz"
13977673Snate@binkert.org    cmd_line_settable = True
13987673Snate@binkert.org
13997673Snate@binkert.org    @classmethod
14007673Snate@binkert.org    def cxx_predecls(cls, code):
140110267SGeoffrey.Blake@arm.com        code('#include "base/types.hh"')
140210267SGeoffrey.Blake@arm.com
140310267SGeoffrey.Blake@arm.com    def __call__(self, value):
140410267SGeoffrey.Blake@arm.com        self.__init__(value)
14054762Snate@binkert.org        return value
14064762Snate@binkert.org
14074762Snate@binkert.org    def getValue(self):
140810458Sandreas.hansson@arm.com        return long(self.value)
140910458Sandreas.hansson@arm.com
141010458Sandreas.hansson@arm.com    @classmethod
141110458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
141210458Sandreas.hansson@arm.com        code('#include <sstream>')
141310458Sandreas.hansson@arm.com
141410458Sandreas.hansson@arm.com    # Ticks are expressed in seconds in JSON files and in plain
141510458Sandreas.hansson@arm.com    # Ticks in .ini files.  Switch based on a config flag
141610458Sandreas.hansson@arm.com    @classmethod
141710458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
14184167Sbinkertn@umich.edu        code('${ret} to_number(${src}, ${dest});')
141910267SGeoffrey.Blake@arm.com
142010267SGeoffrey.Blake@arm.comclass Latency(TickParamValue):
14213101Sstever@eecs.umich.edu    ex_str = "100ns"
14224167Sbinkertn@umich.edu
14234167Sbinkertn@umich.edu    def __init__(self, value):
14244167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
14254167Sbinkertn@umich.edu            self.ticks = value.ticks
14264167Sbinkertn@umich.edu            self.value = value.value
14274167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
14284167Sbinkertn@umich.edu            self.ticks = value.ticks
14294167Sbinkertn@umich.edu            self.value = 1.0 / value.value
14304167Sbinkertn@umich.edu        elif value.endswith('t'):
14314167Sbinkertn@umich.edu            self.ticks = True
14324167Sbinkertn@umich.edu            self.value = int(value[:-1])
14334167Sbinkertn@umich.edu        else:
14343101Sstever@eecs.umich.edu            self.ticks = False
143510267SGeoffrey.Blake@arm.com            self.value = convert.toLatency(value)
143610267SGeoffrey.Blake@arm.com
143710267SGeoffrey.Blake@arm.com    def __call__(self, value):
143810267SGeoffrey.Blake@arm.com        self.__init__(value)
14393101Sstever@eecs.umich.edu        return value
14403101Sstever@eecs.umich.edu
14413101Sstever@eecs.umich.edu    def __getattr__(self, attr):
14423101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
14433101Sstever@eecs.umich.edu            return self
14443101Sstever@eecs.umich.edu        if attr == 'frequency':
14453101Sstever@eecs.umich.edu            return Frequency(self)
14464762Snate@binkert.org        raise AttributeError, "Latency object has no attribute '%s'" % attr
14474762Snate@binkert.org
14484762Snate@binkert.org    def getValue(self):
14494762Snate@binkert.org        if self.ticks or self.value == 0:
14504762Snate@binkert.org            value = self.value
14514762Snate@binkert.org        else:
14524762Snate@binkert.org            value = ticks.fromSeconds(self.value)
145310380SAndrew.Bardsley@arm.com        return long(value)
145410380SAndrew.Bardsley@arm.com
145510380SAndrew.Bardsley@arm.com    def config_value(self):
14563101Sstever@eecs.umich.edu        return self.getValue()
14573101Sstever@eecs.umich.edu
14584762Snate@binkert.org    # convert latency to ticks
14593101Sstever@eecs.umich.edu    def ini_str(self):
14604167Sbinkertn@umich.edu        return '%d' % self.getValue()
146110267SGeoffrey.Blake@arm.com
146210267SGeoffrey.Blake@arm.comclass Frequency(TickParamValue):
14633101Sstever@eecs.umich.edu    ex_str = "1GHz"
14644167Sbinkertn@umich.edu
14654167Sbinkertn@umich.edu    def __init__(self, value):
14664167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
14674167Sbinkertn@umich.edu            if value.value == 0:
14684167Sbinkertn@umich.edu                self.value = 0
14694167Sbinkertn@umich.edu            else:
14704167Sbinkertn@umich.edu                self.value = 1.0 / value.value
14714167Sbinkertn@umich.edu            self.ticks = value.ticks
14724167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
14734167Sbinkertn@umich.edu            self.value = value.value
14744167Sbinkertn@umich.edu            self.ticks = value.ticks
14754167Sbinkertn@umich.edu        else:
14763101Sstever@eecs.umich.edu            self.ticks = False
147710267SGeoffrey.Blake@arm.com            self.value = convert.toFrequency(value)
147810267SGeoffrey.Blake@arm.com
147910267SGeoffrey.Blake@arm.com    def __call__(self, value):
148010267SGeoffrey.Blake@arm.com        self.__init__(value)
14813101Sstever@eecs.umich.edu        return value
14823101Sstever@eecs.umich.edu
14833101Sstever@eecs.umich.edu    def __getattr__(self, attr):
14843101Sstever@eecs.umich.edu        if attr == 'frequency':
14853101Sstever@eecs.umich.edu            return self
14863101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
14873101Sstever@eecs.umich.edu            return Latency(self)
14884167Sbinkertn@umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
14894762Snate@binkert.org
14904762Snate@binkert.org    # convert latency to ticks
14914762Snate@binkert.org    def getValue(self):
14924762Snate@binkert.org        if self.ticks or self.value == 0:
14934762Snate@binkert.org            value = self.value
14944762Snate@binkert.org        else:
14954762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
149610380SAndrew.Bardsley@arm.com        return long(value)
149710380SAndrew.Bardsley@arm.com
149810380SAndrew.Bardsley@arm.com    def config_value(self):
14993101Sstever@eecs.umich.edu        return self.getValue()
15004762Snate@binkert.org
15013101Sstever@eecs.umich.edu    def ini_str(self):
150210019Sandreas.hansson@arm.com        return '%d' % self.getValue()
150310019Sandreas.hansson@arm.com
150410019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a
15053101Sstever@eecs.umich.edu# latency, just like Latency and Frequency.
15064167Sbinkertn@umich.educlass Clock(TickParamValue):
15074167Sbinkertn@umich.edu    def __init__(self, value):
15084167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
15094167Sbinkertn@umich.edu            self.ticks = value.ticks
15104167Sbinkertn@umich.edu            self.value = value.value
15114167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
15124167Sbinkertn@umich.edu            self.ticks = value.ticks
15134167Sbinkertn@umich.edu            self.value = 1.0 / value.value
15144167Sbinkertn@umich.edu        elif value.endswith('t'):
15154167Sbinkertn@umich.edu            self.ticks = True
15164167Sbinkertn@umich.edu            self.value = int(value[:-1])
15174167Sbinkertn@umich.edu        else:
15183101Sstever@eecs.umich.edu            self.ticks = False
151910267SGeoffrey.Blake@arm.com            self.value = convert.anyToLatency(value)
152010267SGeoffrey.Blake@arm.com
152110267SGeoffrey.Blake@arm.com    def __call__(self, value):
152210267SGeoffrey.Blake@arm.com        self.__init__(value)
152310267SGeoffrey.Blake@arm.com        return value
152410267SGeoffrey.Blake@arm.com
152510267SGeoffrey.Blake@arm.com    def __str__(self):
15263101Sstever@eecs.umich.edu        return "%s" % Latency(self)
15273101Sstever@eecs.umich.edu
15283101Sstever@eecs.umich.edu    def __getattr__(self, attr):
15293101Sstever@eecs.umich.edu        if attr == 'frequency':
15303101Sstever@eecs.umich.edu            return Frequency(self)
15313101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
15323101Sstever@eecs.umich.edu            return Latency(self)
15334762Snate@binkert.org        raise AttributeError, "Frequency object has no attribute '%s'" % attr
15344762Snate@binkert.org
15354762Snate@binkert.org    def getValue(self):
153610380SAndrew.Bardsley@arm.com        return self.period.getValue()
153710380SAndrew.Bardsley@arm.com
153810380SAndrew.Bardsley@arm.com    def config_value(self):
15393101Sstever@eecs.umich.edu        return self.period.config_value()
15403101Sstever@eecs.umich.edu
15413101Sstever@eecs.umich.edu    def ini_str(self):
15429827Sakash.bagdia@arm.com        return self.period.ini_str()
15439827Sakash.bagdia@arm.com
154410267SGeoffrey.Blake@arm.comclass Voltage(float,ParamValue):
154511498Sakash.bagdia@ARM.com    cxx_type = 'double'
154610267SGeoffrey.Blake@arm.com    ex_str = "1V"
15479827Sakash.bagdia@arm.com    cmd_line_settable = True
15489827Sakash.bagdia@arm.com
15499827Sakash.bagdia@arm.com    def __new__(cls, value):
15509827Sakash.bagdia@arm.com        # convert to voltage
15519827Sakash.bagdia@arm.com        val = convert.toVoltage(value)
155210267SGeoffrey.Blake@arm.com        return super(cls, Voltage).__new__(cls, val)
155310267SGeoffrey.Blake@arm.com
155410267SGeoffrey.Blake@arm.com    def __call__(self, value):
155510267SGeoffrey.Blake@arm.com        val = convert.toVoltage(value)
155610267SGeoffrey.Blake@arm.com        self.__init__(val)
15579827Sakash.bagdia@arm.com        return value
155810267SGeoffrey.Blake@arm.com
15599827Sakash.bagdia@arm.com    def __str__(self):
15609827Sakash.bagdia@arm.com        return str(self.getValue())
15619827Sakash.bagdia@arm.com
15629827Sakash.bagdia@arm.com    def getValue(self):
15639827Sakash.bagdia@arm.com        value = float(self)
15649827Sakash.bagdia@arm.com        return value
15659827Sakash.bagdia@arm.com
15669827Sakash.bagdia@arm.com    def ini_str(self):
156710458Sandreas.hansson@arm.com        return '%f' % self.getValue()
156810458Sandreas.hansson@arm.com
156910458Sandreas.hansson@arm.com    @classmethod
157010458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
157110458Sandreas.hansson@arm.com        code('#include <sstream>')
157210458Sandreas.hansson@arm.com
157310458Sandreas.hansson@arm.com    @classmethod
157410458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
157510427Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
157610427Sandreas.hansson@arm.com
157710427Sandreas.hansson@arm.comclass Current(float, ParamValue):
157810427Sandreas.hansson@arm.com    cxx_type = 'double'
157910427Sandreas.hansson@arm.com    ex_str = "1mA"
158010427Sandreas.hansson@arm.com    cmd_line_settable = False
158110427Sandreas.hansson@arm.com
158210427Sandreas.hansson@arm.com    def __new__(cls, value):
158310427Sandreas.hansson@arm.com        # convert to current
158410427Sandreas.hansson@arm.com        val = convert.toCurrent(value)
158510427Sandreas.hansson@arm.com        return super(cls, Current).__new__(cls, val)
158610427Sandreas.hansson@arm.com
158710427Sandreas.hansson@arm.com    def __call__(self, value):
158810427Sandreas.hansson@arm.com        val = convert.toCurrent(value)
158910427Sandreas.hansson@arm.com        self.__init__(val)
159010427Sandreas.hansson@arm.com        return value
159110427Sandreas.hansson@arm.com
159210427Sandreas.hansson@arm.com    def __str__(self):
159310427Sandreas.hansson@arm.com        return str(self.getValue())
159410427Sandreas.hansson@arm.com
159510427Sandreas.hansson@arm.com    def getValue(self):
159610427Sandreas.hansson@arm.com        value = float(self)
159710427Sandreas.hansson@arm.com        return value
159810427Sandreas.hansson@arm.com
159910427Sandreas.hansson@arm.com    def ini_str(self):
160010458Sandreas.hansson@arm.com        return '%f' % self.getValue()
160110458Sandreas.hansson@arm.com
160210458Sandreas.hansson@arm.com    @classmethod
160310458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
160410458Sandreas.hansson@arm.com        code('#include <sstream>')
160510458Sandreas.hansson@arm.com
160610458Sandreas.hansson@arm.com    @classmethod
160710458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
16083101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
16093101Sstever@eecs.umich.edu
161010267SGeoffrey.Blake@arm.comclass NetworkBandwidth(float,ParamValue):
161110267SGeoffrey.Blake@arm.com    cxx_type = 'float'
161210267SGeoffrey.Blake@arm.com    ex_str = "1Gbps"
16133101Sstever@eecs.umich.edu    cmd_line_settable = True
16144167Sbinkertn@umich.edu
16154167Sbinkertn@umich.edu    def __new__(cls, value):
16163101Sstever@eecs.umich.edu        # convert to bits per second
16173101Sstever@eecs.umich.edu        val = convert.toNetworkBandwidth(value)
16183101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
16193101Sstever@eecs.umich.edu
16203101Sstever@eecs.umich.edu    def __str__(self):
162110267SGeoffrey.Blake@arm.com        return str(self.val)
162210267SGeoffrey.Blake@arm.com
162310267SGeoffrey.Blake@arm.com    def __call__(self, value):
162410267SGeoffrey.Blake@arm.com        val = convert.toNetworkBandwidth(value)
162510267SGeoffrey.Blake@arm.com        self.__init__(val)
16264762Snate@binkert.org        return value
16274167Sbinkertn@umich.edu
16284167Sbinkertn@umich.edu    def getValue(self):
16294167Sbinkertn@umich.edu        # convert to seconds per byte
16304762Snate@binkert.org        value = 8.0 / float(self)
16314762Snate@binkert.org        # convert to ticks per byte
16324762Snate@binkert.org        value = ticks.fromSeconds(value)
16334762Snate@binkert.org        return float(value)
16344762Snate@binkert.org
16353101Sstever@eecs.umich.edu    def ini_str(self):
163610380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
163710380SAndrew.Bardsley@arm.com
163810380SAndrew.Bardsley@arm.com    def config_value(self):
163910458Sandreas.hansson@arm.com        return '%f' % self.getValue()
164010458Sandreas.hansson@arm.com
164110458Sandreas.hansson@arm.com    @classmethod
164210458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
164310458Sandreas.hansson@arm.com        code('#include <sstream>')
164410458Sandreas.hansson@arm.com
164510458Sandreas.hansson@arm.com    @classmethod
164610458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
16473101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
16483101Sstever@eecs.umich.edu
164910267SGeoffrey.Blake@arm.comclass MemoryBandwidth(float,ParamValue):
165010267SGeoffrey.Blake@arm.com    cxx_type = 'float'
165110267SGeoffrey.Blake@arm.com    ex_str = "1GB/s"
16525469Snate@binkert.org    cmd_line_settable = True
16537743Sgblack@eecs.umich.edu
16543102Sstever@eecs.umich.edu    def __new__(cls, value):
16553101Sstever@eecs.umich.edu        # convert to bytes per second
16563101Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
165710267SGeoffrey.Blake@arm.com        return super(cls, MemoryBandwidth).__new__(cls, val)
165810267SGeoffrey.Blake@arm.com
165910267SGeoffrey.Blake@arm.com    def __call__(self, value):
166010267SGeoffrey.Blake@arm.com        val = convert.toMemoryBandwidth(value)
16613101Sstever@eecs.umich.edu        self.__init__(val)
16624762Snate@binkert.org        return value
16634167Sbinkertn@umich.edu
16645468Snate@binkert.org    def getValue(self):
16655468Snate@binkert.org        # convert to seconds per byte
16665468Snate@binkert.org        value = float(self)
16674167Sbinkertn@umich.edu        if value:
16684762Snate@binkert.org            value = 1.0 / float(self)
16694762Snate@binkert.org        # convert to ticks per byte
16704762Snate@binkert.org        value = ticks.fromSeconds(value)
16714762Snate@binkert.org        return float(value)
16724762Snate@binkert.org
16733101Sstever@eecs.umich.edu    def ini_str(self):
167410380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
167510380SAndrew.Bardsley@arm.com
167610380SAndrew.Bardsley@arm.com    def config_value(self):
167710458Sandreas.hansson@arm.com        return '%f' % self.getValue()
167810458Sandreas.hansson@arm.com
167910458Sandreas.hansson@arm.com    @classmethod
168010458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
168110458Sandreas.hansson@arm.com        code('#include <sstream>')
168210458Sandreas.hansson@arm.com
168310458Sandreas.hansson@arm.com    @classmethod
168410458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
16853101Sstever@eecs.umich.edu        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
16863101Sstever@eecs.umich.edu
16873101Sstever@eecs.umich.edu#
16883101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
16893102Sstever@eecs.umich.edu#
16903102Sstever@eecs.umich.edu
16913102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
16923102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
16933102Sstever@eecs.umich.edu# SimObject is required.
16943102Sstever@eecs.umich.edu# only one copy of a particular node
16953102Sstever@eecs.umich.educlass NullSimObject(object):
16963102Sstever@eecs.umich.edu    __metaclass__ = Singleton
16973102Sstever@eecs.umich.edu
16983102Sstever@eecs.umich.edu    def __call__(cls):
16993102Sstever@eecs.umich.edu        return cls
17003102Sstever@eecs.umich.edu
17013102Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
17023102Sstever@eecs.umich.edu        pass
17033102Sstever@eecs.umich.edu
17043102Sstever@eecs.umich.edu    def ini_str(self):
17053102Sstever@eecs.umich.edu        return 'Null'
17063102Sstever@eecs.umich.edu
17073102Sstever@eecs.umich.edu    def unproxy(self, base):
17083102Sstever@eecs.umich.edu        return self
17093102Sstever@eecs.umich.edu
17104762Snate@binkert.org    def set_path(self, parent, name):
17113102Sstever@eecs.umich.edu        pass
17123102Sstever@eecs.umich.edu
17133102Sstever@eecs.umich.edu    def set_parent(self, parent, name):
171410380SAndrew.Bardsley@arm.com        pass
171510380SAndrew.Bardsley@arm.com
171610380SAndrew.Bardsley@arm.com    def clear_parent(self, old_parent):
17174762Snate@binkert.org        pass
17184762Snate@binkert.org
17194762Snate@binkert.org    def descendants(self):
17203102Sstever@eecs.umich.edu        return
17213102Sstever@eecs.umich.edu        yield None
17223102Sstever@eecs.umich.edu
17233102Sstever@eecs.umich.edu    def __str__(self):
17243102Sstever@eecs.umich.edu        return 'Null'
17253102Sstever@eecs.umich.edu
17263101Sstever@eecs.umich.edu    def config_value(self):
17273101Sstever@eecs.umich.edu        return None
17283101Sstever@eecs.umich.edu
17293101Sstever@eecs.umich.edu    def getValue(self):
17303101Sstever@eecs.umich.edu        return None
17313101Sstever@eecs.umich.edu
17323101Sstever@eecs.umich.edu# The only instance you'll ever need...
17333101Sstever@eecs.umich.eduNULL = NullSimObject()
17343101Sstever@eecs.umich.edu
17353101Sstever@eecs.umich.edudef isNullPointer(value):
17363101Sstever@eecs.umich.edu    return isinstance(value, NullSimObject)
17373101Sstever@eecs.umich.edu
17383101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
17393101Sstever@eecs.umich.eduMaxAddr = Addr.max
17403101Sstever@eecs.umich.eduMaxTick = Tick.max
17413101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
17423101Sstever@eecs.umich.edu
17438839Sandreas.hansson@arm.com
17443105Sstever@eecs.umich.edu#####################################################################
17453101Sstever@eecs.umich.edu#
17463101Sstever@eecs.umich.edu# Port objects
17478839Sandreas.hansson@arm.com#
17483101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
17493101Sstever@eecs.umich.edu#
17503105Sstever@eecs.umich.edu#####################################################################
17513101Sstever@eecs.umich.edu
17523103Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
17533105Sstever@eecs.umich.edu# particular SimObject.
17543103Sstever@eecs.umich.educlass PortRef(object):
17558840Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
17568840Sandreas.hansson@arm.com        assert(isSimObject(simobj) or isSimObjectClass(simobj))
17578840Sandreas.hansson@arm.com        self.simobj = simobj
17588840Sandreas.hansson@arm.com        self.name = name
17598840Sandreas.hansson@arm.com        self.role = role
17603105Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
17613105Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
17623105Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
17633105Sstever@eecs.umich.edu
17649017Sandreas.hansson@arm.com    def __str__(self):
17659017Sandreas.hansson@arm.com        return '%s.%s' % (self.simobj, self.name)
17669017Sandreas.hansson@arm.com
17679017Sandreas.hansson@arm.com    def __len__(self):
17683105Sstever@eecs.umich.edu        # Return the number of connected ports, i.e. 0 is we have no
17693105Sstever@eecs.umich.edu        # peer and 1 if we do.
17703105Sstever@eecs.umich.edu        return int(self.peer != None)
17713105Sstever@eecs.umich.edu
17723105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
17733105Sstever@eecs.umich.edu    def ini_str(self):
17743105Sstever@eecs.umich.edu        return str(self.peer)
17753105Sstever@eecs.umich.edu
17763105Sstever@eecs.umich.edu    # for config.json
17773109Sstever@eecs.umich.edu    def get_config_as_dict(self):
17783105Sstever@eecs.umich.edu        return {'role' : self.role, 'peer' : str(self.peer)}
17793105Sstever@eecs.umich.edu
17803105Sstever@eecs.umich.edu    def __getattr__(self, attr):
17813105Sstever@eecs.umich.edu        if attr == 'peerObj':
17823105Sstever@eecs.umich.edu            # shorthand for proxies
17833105Sstever@eecs.umich.edu            return self.peer.simobj
17849014Sandreas.hansson@arm.com        raise AttributeError, "'%s' object has no attribute '%s'" % \
17859014Sandreas.hansson@arm.com              (self.__class__.__name__, attr)
17863101Sstever@eecs.umich.edu
17873109Sstever@eecs.umich.edu    # Full connection is symmetric (both ways).  Called via
17883109Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
17893109Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
17903109Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
17913109Sstever@eecs.umich.edu    def connect(self, other):
17923109Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
17933109Sstever@eecs.umich.edu            # reference to plain VectorPort is implicit append
17943109Sstever@eecs.umich.edu            other = other._get_next()
17953109Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
17963101Sstever@eecs.umich.edu            fatal("Port %s is already connected to %s, cannot connect %s\n",
179710355SGeoffrey.Blake@arm.com                  self, self.peer, other);
179810355SGeoffrey.Blake@arm.com        self.peer = other
179910355SGeoffrey.Blake@arm.com        if proxy.isproxy(other):
180010355SGeoffrey.Blake@arm.com            other.set_param_desc(PortParamDesc())
180110355SGeoffrey.Blake@arm.com        elif isinstance(other, PortRef):
180210355SGeoffrey.Blake@arm.com            if other.peer is not self:
180310355SGeoffrey.Blake@arm.com                other.connect(self)
180410355SGeoffrey.Blake@arm.com        else:
180510355SGeoffrey.Blake@arm.com            raise TypeError, \
180610355SGeoffrey.Blake@arm.com                  "assigning non-port reference '%s' to port '%s'" \
180710355SGeoffrey.Blake@arm.com                  % (other, self)
180810355SGeoffrey.Blake@arm.com
180910355SGeoffrey.Blake@arm.com    # Allow a master/slave port pair to be spliced between
181010355SGeoffrey.Blake@arm.com    # a port and its connected peer. Useful operation for connecting
181110355SGeoffrey.Blake@arm.com    # instrumentation structures into a system when it is necessary
181210355SGeoffrey.Blake@arm.com    # to connect the instrumentation after the full system has been
181310355SGeoffrey.Blake@arm.com    # constructed.
181410355SGeoffrey.Blake@arm.com    def splice(self, new_master_peer, new_slave_peer):
181510355SGeoffrey.Blake@arm.com        if self.peer and not proxy.isproxy(self.peer):
181610355SGeoffrey.Blake@arm.com            if isinstance(new_master_peer, PortRef) and \
181710355SGeoffrey.Blake@arm.com               isinstance(new_slave_peer, PortRef):
181810355SGeoffrey.Blake@arm.com                 old_peer = self.peer
181910355SGeoffrey.Blake@arm.com                 if self.role == 'SLAVE':
182010355SGeoffrey.Blake@arm.com                     self.peer = new_master_peer
182110355SGeoffrey.Blake@arm.com                     old_peer.peer = new_slave_peer
182210355SGeoffrey.Blake@arm.com                     new_master_peer.connect(self)
182310355SGeoffrey.Blake@arm.com                     new_slave_peer.connect(old_peer)
182410355SGeoffrey.Blake@arm.com                 elif self.role == 'MASTER':
182510355SGeoffrey.Blake@arm.com                     self.peer = new_slave_peer
182610355SGeoffrey.Blake@arm.com                     old_peer.peer = new_master_peer
18273105Sstever@eecs.umich.edu                     new_slave_peer.connect(self)
18283105Sstever@eecs.umich.edu                     new_master_peer.connect(old_peer)
18293105Sstever@eecs.umich.edu                 else:
18303101Sstever@eecs.umich.edu                     panic("Port %s has unknown role, "+\
18313105Sstever@eecs.umich.edu                           "cannot splice in new peers\n", self)
18323105Sstever@eecs.umich.edu            else:
18333101Sstever@eecs.umich.edu                raise TypeError, \
18343105Sstever@eecs.umich.edu                      "Splicing non-port references '%s','%s' to port '%s'"\
18353179Sstever@eecs.umich.edu                      % (new_peer, peers_new_peer, self)
18363105Sstever@eecs.umich.edu        else:
18373105Sstever@eecs.umich.edu            fatal("Port %s not connected, cannot splice in new peers\n", self)
18383101Sstever@eecs.umich.edu
18393101Sstever@eecs.umich.edu    def clone(self, simobj, memo):
18403105Sstever@eecs.umich.edu        if memo.has_key(self):
18413105Sstever@eecs.umich.edu            return memo[self]
18423105Sstever@eecs.umich.edu        newRef = copy.copy(self)
18433105Sstever@eecs.umich.edu        memo[self] = newRef
18443105Sstever@eecs.umich.edu        newRef.simobj = simobj
18453105Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
18463105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
18473105Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
18483105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
18493105Sstever@eecs.umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
18503105Sstever@eecs.umich.edu        return newRef
18513101Sstever@eecs.umich.edu
18523101Sstever@eecs.umich.edu    def unproxy(self, simobj):
185311802Sandreas.sandberg@arm.com        assert(simobj is self.simobj)
18544762Snate@binkert.org        if proxy.isproxy(self.peer):
18558839Sandreas.hansson@arm.com            try:
18568839Sandreas.hansson@arm.com                realPeer = self.peer.unproxy(self.simobj)
18578839Sandreas.hansson@arm.com            except:
18588839Sandreas.hansson@arm.com                print "Error in unproxying port '%s' of %s" % \
18593101Sstever@eecs.umich.edu                      (self.name, self.simobj.path())
18603101Sstever@eecs.umich.edu                raise
18613101Sstever@eecs.umich.edu            self.connect(realPeer)
18625578SSteve.Reinhardt@amd.com
18635578SSteve.Reinhardt@amd.com    # Call C++ to create corresponding port connection between C++ objects
18648839Sandreas.hansson@arm.com    def ccConnect(self):
18658839Sandreas.hansson@arm.com        from _m5.pyobject import connectPorts
18668839Sandreas.hansson@arm.com
18678839Sandreas.hansson@arm.com        if self.role == 'SLAVE':
18688839Sandreas.hansson@arm.com            # do nothing and let the master take care of it
18698839Sandreas.hansson@arm.com            return
18708839Sandreas.hansson@arm.com
18717526Ssteve.reinhardt@amd.com        if self.ccConnected: # already done this
18728839Sandreas.hansson@arm.com            return
18737526Ssteve.reinhardt@amd.com        peer = self.peer
18747526Ssteve.reinhardt@amd.com        if not self.peer: # nothing to connect to
18757526Ssteve.reinhardt@amd.com            return
18767526Ssteve.reinhardt@amd.com
18777526Ssteve.reinhardt@amd.com        # check that we connect a master to a slave
18787526Ssteve.reinhardt@amd.com        if self.role == peer.role:
18797526Ssteve.reinhardt@amd.com            raise TypeError, \
18803101Sstever@eecs.umich.edu                "cannot connect '%s' and '%s' due to identical role '%s'" \
18813101Sstever@eecs.umich.edu                % (peer, self, self.role)
18823101Sstever@eecs.umich.edu
18833105Sstever@eecs.umich.edu        try:
18843105Sstever@eecs.umich.edu            # self is always the master and peer the slave
18853105Sstever@eecs.umich.edu            connectPorts(self.simobj.getCCObject(), self.name, self.index,
18868839Sandreas.hansson@arm.com                         peer.simobj.getCCObject(), peer.name, peer.index)
18878839Sandreas.hansson@arm.com        except:
18883105Sstever@eecs.umich.edu            print "Error connecting port %s.%s to %s.%s" % \
18893105Sstever@eecs.umich.edu                  (self.simobj.path(), self.name,
18903105Sstever@eecs.umich.edu                   peer.simobj.path(), peer.name)
18913105Sstever@eecs.umich.edu            raise
18923105Sstever@eecs.umich.edu        self.ccConnected = True
18933105Sstever@eecs.umich.edu        peer.ccConnected = True
18943105Sstever@eecs.umich.edu
18953105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
18968839Sandreas.hansson@arm.com# PortRef, but has an index.
18973105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
18983105Sstever@eecs.umich.edu    def __init__(self, simobj, name, role, index):
18993105Sstever@eecs.umich.edu        PortRef.__init__(self, simobj, name, role)
19008839Sandreas.hansson@arm.com        self.index = index
19013105Sstever@eecs.umich.edu
19023105Sstever@eecs.umich.edu    def __str__(self):
19033109Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
19043109Sstever@eecs.umich.edu
19053109Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
19068840Sandreas.hansson@arm.com# Can be indexed to retrieve individual VectorPortElementRef instances.
19078840Sandreas.hansson@arm.comclass VectorPortRef(object):
19088840Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
19098840Sandreas.hansson@arm.com        assert(isSimObject(simobj) or isSimObjectClass(simobj))
19108840Sandreas.hansson@arm.com        self.simobj = simobj
19113105Sstever@eecs.umich.edu        self.name = name
19123105Sstever@eecs.umich.edu        self.role = role
19133105Sstever@eecs.umich.edu        self.elements = []
19143105Sstever@eecs.umich.edu
19159017Sandreas.hansson@arm.com    def __str__(self):
19169017Sandreas.hansson@arm.com        return '%s.%s[:]' % (self.simobj, self.name)
19179017Sandreas.hansson@arm.com
19189017Sandreas.hansson@arm.com    def __len__(self):
19199017Sandreas.hansson@arm.com        # Return the number of connected peers, corresponding the the
19203105Sstever@eecs.umich.edu        # length of the elements.
19213105Sstever@eecs.umich.edu        return len(self.elements)
19223105Sstever@eecs.umich.edu
19233105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
19243105Sstever@eecs.umich.edu    def ini_str(self):
19258839Sandreas.hansson@arm.com        return ' '.join([el.ini_str() for el in self.elements])
19263105Sstever@eecs.umich.edu
19273105Sstever@eecs.umich.edu    # for config.json
19283105Sstever@eecs.umich.edu    def get_config_as_dict(self):
19293105Sstever@eecs.umich.edu        return {'role' : self.role,
19303105Sstever@eecs.umich.edu                'peer' : [el.ini_str() for el in self.elements]}
19313105Sstever@eecs.umich.edu
19323105Sstever@eecs.umich.edu    def __getitem__(self, key):
19333105Sstever@eecs.umich.edu        if not isinstance(key, int):
19343105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
19353105Sstever@eecs.umich.edu        if key >= len(self.elements):
19363105Sstever@eecs.umich.edu            # need to extend list
19373105Sstever@eecs.umich.edu            ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
19383105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
19393109Sstever@eecs.umich.edu            self.elements.extend(ext)
19403109Sstever@eecs.umich.edu        return self.elements[key]
19413109Sstever@eecs.umich.edu
19423109Sstever@eecs.umich.edu    def _get_next(self):
19433109Sstever@eecs.umich.edu        return self[len(self.elements)]
19443109Sstever@eecs.umich.edu
19453109Sstever@eecs.umich.edu    def __setitem__(self, key, value):
19463109Sstever@eecs.umich.edu        if not isinstance(key, int):
19473109Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
19483109Sstever@eecs.umich.edu        self[key].connect(value)
19493109Sstever@eecs.umich.edu
19503109Sstever@eecs.umich.edu    def connect(self, other):
19513109Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
19523109Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
19533109Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
19543109Sstever@eecs.umich.edu            # or if it should replace the current vector.
19553109Sstever@eecs.umich.edu            for ref in other:
19563109Sstever@eecs.umich.edu                self._get_next().connect(ref)
19573109Sstever@eecs.umich.edu        else:
19583105Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
19593105Sstever@eecs.umich.edu            self._get_next().connect(other)
19603105Sstever@eecs.umich.edu
19613105Sstever@eecs.umich.edu    def clone(self, simobj, memo):
19623105Sstever@eecs.umich.edu        if memo.has_key(self):
19633105Sstever@eecs.umich.edu            return memo[self]
19643105Sstever@eecs.umich.edu        newRef = copy.copy(self)
19653101Sstever@eecs.umich.edu        memo[self] = newRef
19663101Sstever@eecs.umich.edu        newRef.simobj = simobj
19673101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
19683101Sstever@eecs.umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
19693101Sstever@eecs.umich.edu        return newRef
19703101Sstever@eecs.umich.edu
19713105Sstever@eecs.umich.edu    def unproxy(self, simobj):
19728839Sandreas.hansson@arm.com        [el.unproxy(simobj) for el in self.elements]
19733101Sstever@eecs.umich.edu
19743101Sstever@eecs.umich.edu    def ccConnect(self):
19753101Sstever@eecs.umich.edu        [el.ccConnect() for el in self.elements]
19763105Sstever@eecs.umich.edu
19773105Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
19783101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a
19798840Sandreas.hansson@arm.com# SimObject instance.  The latter are represented by PortRef objects.
19808840Sandreas.hansson@arm.comclass Port(object):
19818840Sandreas.hansson@arm.com    # Generate a PortRef for this port on the given SimObject with the
19828840Sandreas.hansson@arm.com    # given name
19838840Sandreas.hansson@arm.com    def makeRef(self, simobj):
198411988Sandreas.sandberg@arm.com        return PortRef(simobj, self.name, self.role)
198511988Sandreas.sandberg@arm.com
198611988Sandreas.sandberg@arm.com    # Connect an instance of this port (on the given SimObject with
19878840Sandreas.hansson@arm.com    # the given name) with the port described by the supplied PortRef
19888840Sandreas.hansson@arm.com    def connect(self, simobj, ref):
19898840Sandreas.hansson@arm.com        self.makeRef(simobj).connect(ref)
19908840Sandreas.hansson@arm.com
19918840Sandreas.hansson@arm.com    # No need for any pre-declarations at the moment as we merely rely
19928840Sandreas.hansson@arm.com    # on an unsigned int.
19938839Sandreas.hansson@arm.com    def cxx_predecls(self, code):
19948839Sandreas.hansson@arm.com        pass
19958839Sandreas.hansson@arm.com
19968839Sandreas.hansson@arm.com    def pybind_predecls(self, code):
19978839Sandreas.hansson@arm.com        cls.cxx_predecls(self, code)
19988839Sandreas.hansson@arm.com
19998839Sandreas.hansson@arm.com    # Declare an unsigned int with the same name as the port, that
20008839Sandreas.hansson@arm.com    # will eventually hold the number of connected ports (and thus the
20018839Sandreas.hansson@arm.com    # number of elements for a VectorPort).
20028839Sandreas.hansson@arm.com    def cxx_decl(self, code):
20038839Sandreas.hansson@arm.com        code('unsigned int port_${{self.name}}_connection_count;')
20048839Sandreas.hansson@arm.com
20058839Sandreas.hansson@arm.comclass MasterPort(Port):
20068839Sandreas.hansson@arm.com    # MasterPort("description")
20078839Sandreas.hansson@arm.com    def __init__(self, *args):
20088839Sandreas.hansson@arm.com        if len(args) == 1:
20098839Sandreas.hansson@arm.com            self.desc = args[0]
20108839Sandreas.hansson@arm.com            self.role = 'MASTER'
20113101Sstever@eecs.umich.edu        else:
201210405Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20133101Sstever@eecs.umich.edu
20143105Sstever@eecs.umich.educlass SlavePort(Port):
20153101Sstever@eecs.umich.edu    # SlavePort("description")
20163101Sstever@eecs.umich.edu    def __init__(self, *args):
20173105Sstever@eecs.umich.edu        if len(args) == 1:
20188839Sandreas.hansson@arm.com            self.desc = args[0]
20198839Sandreas.hansson@arm.com            self.role = 'SLAVE'
20208839Sandreas.hansson@arm.com        else:
20218839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20228839Sandreas.hansson@arm.com
20238839Sandreas.hansson@arm.com# VectorPort description object.  Like Port, but represents a vector
20248839Sandreas.hansson@arm.com# of connections (e.g., as on a XBar).
20258839Sandreas.hansson@arm.comclass VectorPort(Port):
20268839Sandreas.hansson@arm.com    def __init__(self, *args):
20278839Sandreas.hansson@arm.com        self.isVec = True
20288839Sandreas.hansson@arm.com
20298839Sandreas.hansson@arm.com    def makeRef(self, simobj):
20308839Sandreas.hansson@arm.com        return VectorPortRef(simobj, self.name, self.role)
20318839Sandreas.hansson@arm.com
20328839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort):
20338839Sandreas.hansson@arm.com    # VectorMasterPort("description")
20348839Sandreas.hansson@arm.com    def __init__(self, *args):
20358839Sandreas.hansson@arm.com        if len(args) == 1:
20368839Sandreas.hansson@arm.com            self.desc = args[0]
20378839Sandreas.hansson@arm.com            self.role = 'MASTER'
20388839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
20393105Sstever@eecs.umich.edu        else:
20403109Sstever@eecs.umich.edu            raise TypeError, 'wrong number of arguments'
20413109Sstever@eecs.umich.edu
20423109Sstever@eecs.umich.educlass VectorSlavePort(VectorPort):
20433109Sstever@eecs.umich.edu    # VectorSlavePort("description")
20443109Sstever@eecs.umich.edu    def __init__(self, *args):
20453109Sstever@eecs.umich.edu        if len(args) == 1:
20463109Sstever@eecs.umich.edu            self.desc = args[0]
20473109Sstever@eecs.umich.edu            self.role = 'SLAVE'
20483105Sstever@eecs.umich.edu            VectorPort.__init__(self, *args)
20496654Snate@binkert.org        else:
20506654Snate@binkert.org            raise TypeError, 'wrong number of arguments'
20516654Snate@binkert.org
20526654Snate@binkert.org# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
20536654Snate@binkert.org# proxy objects (via set_param_desc()) so that proxy error messages
20546654Snate@binkert.org# make sense.
20556654Snate@binkert.orgclass PortParamDesc(object):
20566654Snate@binkert.org    __metaclass__ = Singleton
20576654Snate@binkert.org
20583101Sstever@eecs.umich.edu    ptype_str = 'Port'
20593101Sstever@eecs.umich.edu    ptype = Port
20603101Sstever@eecs.umich.edu
20613101Sstever@eecs.umich.edubaseEnums = allEnums.copy()
20623101Sstever@eecs.umich.edubaseParams = allParams.copy()
20633101Sstever@eecs.umich.edu
20647777Sgblack@eecs.umich.edudef clear():
20653101Sstever@eecs.umich.edu    global allEnums, allParams
20669827Sakash.bagdia@arm.com
20673101Sstever@eecs.umich.edu    allEnums = baseEnums.copy()
20689232Sandreas.hansson@arm.com    allParams = baseParams.copy()
20693101Sstever@eecs.umich.edu
20703885Sbinkertn@umich.edu__all__ = ['Param', 'VectorParam',
20713102Sstever@eecs.umich.edu           'Enum', 'Bool', 'String', 'Float',
20728839Sandreas.hansson@arm.com           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
20738839Sandreas.hansson@arm.com           'Int32', 'UInt32', 'Int64', 'UInt64',
20746654Snate@binkert.org           'Counter', 'Addr', 'Tick', 'Percent',
20756654Snate@binkert.org           'TcpPort', 'UdpPort', 'EthernetAddr',
2076           'IpAddress', 'IpNetmask', 'IpWithPort',
2077           'MemorySize', 'MemorySize32',
2078           'Latency', 'Frequency', 'Clock', 'Voltage',
2079           'NetworkBandwidth', 'MemoryBandwidth',
2080           'AddrRange',
2081           'MaxAddr', 'MaxTick', 'AllMemory',
2082           'Time',
2083           'NextEthernetAddr', 'NULL',
2084           'MasterPort', 'SlavePort',
2085           'VectorMasterPort', 'VectorSlavePort']
2086
2087import SimObject
2088