params.py revision 10405
110355SGeoffrey.Blake@arm.com# Copyright (c) 2012-2014 ARM Limited
28839Sandreas.hansson@arm.com# All rights reserved.
38839Sandreas.hansson@arm.com#
48839Sandreas.hansson@arm.com# The license below extends only to copyright in the software and shall
58839Sandreas.hansson@arm.com# not be construed as granting a license to any other intellectual
68839Sandreas.hansson@arm.com# property including but not limited to intellectual property relating
78839Sandreas.hansson@arm.com# to a hardware implementation of the functionality of the software
88839Sandreas.hansson@arm.com# licensed hereunder.  You may use the software subject to the license
98839Sandreas.hansson@arm.com# terms below provided that you ensure that this notice is replicated
108839Sandreas.hansson@arm.com# unmodified and in its entirety in all distributions of the software,
118839Sandreas.hansson@arm.com# modified or unmodified, in source code or in binary form.
128839Sandreas.hansson@arm.com#
133101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan
148579Ssteve.reinhardt@amd.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
153101Sstever@eecs.umich.edu# All rights reserved.
163101Sstever@eecs.umich.edu#
173101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
183101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are
193101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright
203101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
213101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
223101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
233101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution;
243101Sstever@eecs.umich.edu# neither the name of the copyright holders nor the names of its
253101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from
263101Sstever@eecs.umich.edu# this software without specific prior written permission.
273101Sstever@eecs.umich.edu#
283101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
293101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
303101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
313101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
323101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
333101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
343101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
353101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
363101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
373101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
383101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
393101Sstever@eecs.umich.edu#
403101Sstever@eecs.umich.edu# Authors: Steve Reinhardt
413101Sstever@eecs.umich.edu#          Nathan Binkert
427778Sgblack@eecs.umich.edu#          Gabe Black
438839Sandreas.hansson@arm.com#          Andreas Hansson
443101Sstever@eecs.umich.edu
453101Sstever@eecs.umich.edu#####################################################################
463101Sstever@eecs.umich.edu#
473101Sstever@eecs.umich.edu# Parameter description classes
483101Sstever@eecs.umich.edu#
493101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either
503101Sstever@eecs.umich.edu# a Param or a VectorParam object.  These objects contain the
513101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default
523101Sstever@eecs.umich.edu# value (if any).  The convert() method on these objects is used to
533101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate
543101Sstever@eecs.umich.edu# type.
553101Sstever@eecs.umich.edu#
563101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute
573101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in
583101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used.
593101Sstever@eecs.umich.edu#
603101Sstever@eecs.umich.edu#####################################################################
613101Sstever@eecs.umich.edu
623885Sbinkertn@umich.eduimport copy
633885Sbinkertn@umich.eduimport datetime
644762Snate@binkert.orgimport re
653885Sbinkertn@umich.eduimport sys
663885Sbinkertn@umich.eduimport time
677528Ssteve.reinhardt@amd.comimport math
683885Sbinkertn@umich.edu
694380Sbinkertn@umich.eduimport proxy
704167Sbinkertn@umich.eduimport ticks
713102Sstever@eecs.umich.edufrom util import *
723101Sstever@eecs.umich.edu
734762Snate@binkert.orgdef isSimObject(*args, **kwargs):
744762Snate@binkert.org    return SimObject.isSimObject(*args, **kwargs)
754762Snate@binkert.org
764762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs):
774762Snate@binkert.org    return SimObject.isSimObjectSequence(*args, **kwargs)
784762Snate@binkert.org
794762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs):
804762Snate@binkert.org    return SimObject.isSimObjectClass(*args, **kwargs)
814762Snate@binkert.org
825033Smilesck@eecs.umich.eduallParams = {}
835033Smilesck@eecs.umich.edu
845033Smilesck@eecs.umich.educlass MetaParamValue(type):
855033Smilesck@eecs.umich.edu    def __new__(mcls, name, bases, dct):
865033Smilesck@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
875033Smilesck@eecs.umich.edu        assert name not in allParams
885033Smilesck@eecs.umich.edu        allParams[name] = cls
895033Smilesck@eecs.umich.edu        return cls
905033Smilesck@eecs.umich.edu
915033Smilesck@eecs.umich.edu
923101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject
933101Sstever@eecs.umich.edu# parameters.
943101Sstever@eecs.umich.educlass ParamValue(object):
955033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
9610267SGeoffrey.Blake@arm.com    cmd_line_settable = False
978596Ssteve.reinhardt@amd.com
988596Ssteve.reinhardt@amd.com    # Generate the code needed as a prerequisite for declaring a C++
998596Ssteve.reinhardt@amd.com    # object of this type.  Typically generates one or more #include
1008596Ssteve.reinhardt@amd.com    # statements.  Used when declaring parameters of this type.
1017673Snate@binkert.org    @classmethod
1027673Snate@binkert.org    def cxx_predecls(cls, code):
1037673Snate@binkert.org        pass
1047673Snate@binkert.org
1058596Ssteve.reinhardt@amd.com    # Generate the code needed as a prerequisite for including a
1068596Ssteve.reinhardt@amd.com    # reference to a C++ object of this type in a SWIG .i file.
1078596Ssteve.reinhardt@amd.com    # Typically generates one or more %import or %include statements.
1087673Snate@binkert.org    @classmethod
1097673Snate@binkert.org    def swig_predecls(cls, code):
1107673Snate@binkert.org        pass
1113101Sstever@eecs.umich.edu
1123101Sstever@eecs.umich.edu    # default for printing to .ini file is regular string conversion.
1133101Sstever@eecs.umich.edu    # will be overridden in some cases
1143101Sstever@eecs.umich.edu    def ini_str(self):
1153101Sstever@eecs.umich.edu        return str(self)
1163101Sstever@eecs.umich.edu
11710380SAndrew.Bardsley@arm.com    # default for printing to .json file is regular string conversion.
11810380SAndrew.Bardsley@arm.com    # will be overridden in some cases, mostly to use native Python
11910380SAndrew.Bardsley@arm.com    # types where there are similar JSON types
12010380SAndrew.Bardsley@arm.com    def config_value(self):
12110380SAndrew.Bardsley@arm.com        return str(self)
12210380SAndrew.Bardsley@arm.com
1233101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
1243101Sstever@eecs.umich.edu    # if they're really proxies or not
1253101Sstever@eecs.umich.edu    def unproxy(self, base):
1263101Sstever@eecs.umich.edu        return self
1273101Sstever@eecs.umich.edu
12810267SGeoffrey.Blake@arm.com    # Produce a human readable version of the stored value
12910267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
13010267SGeoffrey.Blake@arm.com        return str(value)
13110267SGeoffrey.Blake@arm.com
1323101Sstever@eecs.umich.edu# Regular parameter description.
1333101Sstever@eecs.umich.educlass ParamDesc(object):
1343101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1353101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1363101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1373101Sstever@eecs.umich.edu        if ptype != None:
1383101Sstever@eecs.umich.edu            self.ptype = ptype
1393101Sstever@eecs.umich.edu
1403101Sstever@eecs.umich.edu        if args:
1413101Sstever@eecs.umich.edu            if len(args) == 1:
1423101Sstever@eecs.umich.edu                self.desc = args[0]
1433101Sstever@eecs.umich.edu            elif len(args) == 2:
1443101Sstever@eecs.umich.edu                self.default = args[0]
1453101Sstever@eecs.umich.edu                self.desc = args[1]
1463101Sstever@eecs.umich.edu            else:
1473101Sstever@eecs.umich.edu                raise TypeError, 'too many arguments'
1483101Sstever@eecs.umich.edu
1493101Sstever@eecs.umich.edu        if kwargs.has_key('desc'):
1503101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1513101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1523101Sstever@eecs.umich.edu            del kwargs['desc']
1533101Sstever@eecs.umich.edu
1543101Sstever@eecs.umich.edu        if kwargs.has_key('default'):
1553101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1563101Sstever@eecs.umich.edu            self.default = kwargs['default']
1573101Sstever@eecs.umich.edu            del kwargs['default']
1583101Sstever@eecs.umich.edu
1593101Sstever@eecs.umich.edu        if kwargs:
1603101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1613101Sstever@eecs.umich.edu
1623101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
1633101Sstever@eecs.umich.edu            raise TypeError, 'desc attribute missing'
1643101Sstever@eecs.umich.edu
1653101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1663101Sstever@eecs.umich.edu        if attr == 'ptype':
1675033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1686656Snate@binkert.org            assert isSimObjectClass(ptype)
1695033Smilesck@eecs.umich.edu            self.ptype = ptype
1705033Smilesck@eecs.umich.edu            return ptype
1715033Smilesck@eecs.umich.edu
1723101Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
1733101Sstever@eecs.umich.edu              (type(self).__name__, attr)
1743101Sstever@eecs.umich.edu
17510267SGeoffrey.Blake@arm.com    def example_str(self):
17610267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "ex_str"):
17710267SGeoffrey.Blake@arm.com            return self.ptype.ex_str
17810267SGeoffrey.Blake@arm.com        else:
17910267SGeoffrey.Blake@arm.com            return self.ptype_str
18010267SGeoffrey.Blake@arm.com
18110267SGeoffrey.Blake@arm.com    # Is the param available to be exposed on the command line
18210267SGeoffrey.Blake@arm.com    def isCmdLineSettable(self):
18310267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "cmd_line_settable"):
18410267SGeoffrey.Blake@arm.com            return self.ptype.cmd_line_settable
18510267SGeoffrey.Blake@arm.com        else:
18610267SGeoffrey.Blake@arm.com            return False
18710267SGeoffrey.Blake@arm.com
1883101Sstever@eecs.umich.edu    def convert(self, value):
1893101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
1903101Sstever@eecs.umich.edu            value.set_param_desc(self)
1913101Sstever@eecs.umich.edu            return value
1923101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
1933101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
1943101Sstever@eecs.umich.edu            # we're just assigning a null pointer
1953101Sstever@eecs.umich.edu            return value
1963101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
1973101Sstever@eecs.umich.edu            return value
1983102Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
1993101Sstever@eecs.umich.edu            return value
2003101Sstever@eecs.umich.edu        return self.ptype(value)
2013101Sstever@eecs.umich.edu
20210267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
20310267SGeoffrey.Blake@arm.com        if isinstance(value, proxy.BaseProxy):
20410267SGeoffrey.Blake@arm.com           return str(value)
20510267SGeoffrey.Blake@arm.com        if isNullPointer(value):
20610267SGeoffrey.Blake@arm.com           return NULL
20710267SGeoffrey.Blake@arm.com        return self.ptype(value).pretty_print(value)
20810267SGeoffrey.Blake@arm.com
2097673Snate@binkert.org    def cxx_predecls(self, code):
2108607Sgblack@eecs.umich.edu        code('#include <cstddef>')
2117673Snate@binkert.org        self.ptype.cxx_predecls(code)
2123101Sstever@eecs.umich.edu
2137673Snate@binkert.org    def swig_predecls(self, code):
2147673Snate@binkert.org        self.ptype.swig_predecls(code)
2153101Sstever@eecs.umich.edu
2167673Snate@binkert.org    def cxx_decl(self, code):
2177673Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
2183101Sstever@eecs.umich.edu
2193101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
2203101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
2213101Sstever@eecs.umich.edu# single value.
2223101Sstever@eecs.umich.edu
2233101Sstever@eecs.umich.educlass VectorParamValue(list):
2245033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
2255475Snate@binkert.org    def __setattr__(self, attr, value):
2265475Snate@binkert.org        raise AttributeError, \
2275475Snate@binkert.org              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
2285475Snate@binkert.org
22910380SAndrew.Bardsley@arm.com    def config_value(self):
23010380SAndrew.Bardsley@arm.com        return [v.config_value() for v in self]
23110380SAndrew.Bardsley@arm.com
2323101Sstever@eecs.umich.edu    def ini_str(self):
2333101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
2343101Sstever@eecs.umich.edu
2354762Snate@binkert.org    def getValue(self):
2364762Snate@binkert.org        return [ v.getValue() for v in self ]
2374762Snate@binkert.org
2383101Sstever@eecs.umich.edu    def unproxy(self, base):
2398460SAli.Saidi@ARM.com        if len(self) == 1 and isinstance(self[0], proxy.AllProxy):
2408459SAli.Saidi@ARM.com            return self[0].unproxy(base)
2418459SAli.Saidi@ARM.com        else:
2428459SAli.Saidi@ARM.com             return [v.unproxy(base) for v in self]
2433101Sstever@eecs.umich.edu
2447528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2457528Ssteve.reinhardt@amd.com    # support clone operation
2467528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2477528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2487528Ssteve.reinhardt@amd.com
2497528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
2503101Sstever@eecs.umich.edu        for v in self:
2517528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2527528Ssteve.reinhardt@amd.com
2537528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2547528Ssteve.reinhardt@amd.com        if len(self) == 1:
2557528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2567528Ssteve.reinhardt@amd.com        else:
2577528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2587528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2597528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2607528Ssteve.reinhardt@amd.com
2618321Ssteve.reinhardt@amd.com    def has_parent(self):
2628321Ssteve.reinhardt@amd.com        return reduce(lambda x,y: x and y, [v.has_parent() for v in self])
2637528Ssteve.reinhardt@amd.com
2647528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2657528Ssteve.reinhardt@amd.com    def get_name(self):
2667528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2677528Ssteve.reinhardt@amd.com
2687528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2697528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2707528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2717528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2727528Ssteve.reinhardt@amd.com    def descendants(self):
2737528Ssteve.reinhardt@amd.com        for v in self:
2747528Ssteve.reinhardt@amd.com            for obj in v.descendants():
2757528Ssteve.reinhardt@amd.com                yield obj
2763101Sstever@eecs.umich.edu
2778664SAli.Saidi@ARM.com    def get_config_as_dict(self):
2788664SAli.Saidi@ARM.com        a = []
2798664SAli.Saidi@ARM.com        for v in self:
2808664SAli.Saidi@ARM.com            a.append(v.get_config_as_dict())
2818664SAli.Saidi@ARM.com        return a
2828664SAli.Saidi@ARM.com
2839953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
2849953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
2859953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
2869953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
2879953Sgeoffrey.blake@arm.com    # configuration scripts.
2889953Sgeoffrey.blake@arm.com    def __setitem__(self, key, value):
2899953Sgeoffrey.blake@arm.com        val = self[key]
2909953Sgeoffrey.blake@arm.com        if value.has_parent():
2919953Sgeoffrey.blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
2929953Sgeoffrey.blake@arm.com                 " that is being overwritten by a SimObjectVector")
2939953Sgeoffrey.blake@arm.com        value.set_parent(val.get_parent(), val._name)
2949953Sgeoffrey.blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
2959953Sgeoffrey.blake@arm.com
29610267SGeoffrey.Blake@arm.com    # Enumerate the params of each member of the SimObject vector. Creates
29710267SGeoffrey.Blake@arm.com    # strings that will allow indexing into the vector by the python code and
29810267SGeoffrey.Blake@arm.com    # allow it to be specified on the command line.
29910267SGeoffrey.Blake@arm.com    def enumerateParams(self, flags_dict = {},
30010267SGeoffrey.Blake@arm.com                        cmd_line_str = "",
30110267SGeoffrey.Blake@arm.com                        access_str = ""):
30210267SGeoffrey.Blake@arm.com        if hasattr(self, "_paramEnumed"):
30310267SGeoffrey.Blake@arm.com            print "Cycle detected enumerating params at %s?!" % (cmd_line_str)
30410267SGeoffrey.Blake@arm.com        else:
30510267SGeoffrey.Blake@arm.com            x = 0
30610267SGeoffrey.Blake@arm.com            for vals in self:
30710267SGeoffrey.Blake@arm.com                # Each entry in the SimObjectVector should be an
30810267SGeoffrey.Blake@arm.com                # instance of a SimObject
30910267SGeoffrey.Blake@arm.com                flags_dict = vals.enumerateParams(flags_dict,
31010267SGeoffrey.Blake@arm.com                                                  cmd_line_str + "%d." % x,
31110267SGeoffrey.Blake@arm.com                                                  access_str + "[%d]." % x)
31210267SGeoffrey.Blake@arm.com                x = x + 1
31310267SGeoffrey.Blake@arm.com
31410267SGeoffrey.Blake@arm.com        return flags_dict
31510267SGeoffrey.Blake@arm.com
3163101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
3173101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
3183101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
3193101Sstever@eecs.umich.edu    def convert(self, value):
3203101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
3213101Sstever@eecs.umich.edu            # list: coerce each element into new list
3223101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
32310364SGeoffrey.Blake@arm.com        elif isinstance(value, str):
32410364SGeoffrey.Blake@arm.com            # If input is a csv string
32510364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
32610364SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
3273101Sstever@eecs.umich.edu        else:
3284762Snate@binkert.org            # singleton: coerce to a single-element list
3294762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
3304762Snate@binkert.org
3314762Snate@binkert.org        if isSimObjectSequence(tmp_list):
3327528Ssteve.reinhardt@amd.com            return SimObjectVector(tmp_list)
3334762Snate@binkert.org        else:
3344762Snate@binkert.org            return VectorParamValue(tmp_list)
3354762Snate@binkert.org
33610267SGeoffrey.Blake@arm.com    # Produce a human readable example string that describes
33710267SGeoffrey.Blake@arm.com    # how to set this vector parameter in the absence of a default
33810267SGeoffrey.Blake@arm.com    # value.
33910267SGeoffrey.Blake@arm.com    def example_str(self):
34010267SGeoffrey.Blake@arm.com        s = super(VectorParamDesc, self).example_str()
34110267SGeoffrey.Blake@arm.com        help_str = "[" + s + "," + s + ", ...]"
34210267SGeoffrey.Blake@arm.com        return help_str
34310267SGeoffrey.Blake@arm.com
34410267SGeoffrey.Blake@arm.com    # Produce a human readable representation of the value of this vector param.
34510267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
34610267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
34710267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
34810267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
34910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
35010267SGeoffrey.Blake@arm.com        else:
35110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, value) ]
35210267SGeoffrey.Blake@arm.com
35310267SGeoffrey.Blake@arm.com        return tmp_list
35410267SGeoffrey.Blake@arm.com
35510267SGeoffrey.Blake@arm.com    # This is a helper function for the new config system
35610267SGeoffrey.Blake@arm.com    def __call__(self, value):
35710267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
35810267SGeoffrey.Blake@arm.com            # list: coerce each element into new list
35910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
36010267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
36110267SGeoffrey.Blake@arm.com            # If input is a csv string
36210364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
36310364SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
36410267SGeoffrey.Blake@arm.com        else:
36510267SGeoffrey.Blake@arm.com            # singleton: coerce to a single-element list
36610267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
36710267SGeoffrey.Blake@arm.com
36810267SGeoffrey.Blake@arm.com        return VectorParamValue(tmp_list)
36910267SGeoffrey.Blake@arm.com
3708596Ssteve.reinhardt@amd.com    def swig_module_name(self):
3718596Ssteve.reinhardt@amd.com        return "%s_vector" % self.ptype_str
3728596Ssteve.reinhardt@amd.com
3737673Snate@binkert.org    def swig_predecls(self, code):
3748596Ssteve.reinhardt@amd.com        code('%import "${{self.swig_module_name()}}.i"')
3754762Snate@binkert.org
3767673Snate@binkert.org    def swig_decl(self, code):
3778596Ssteve.reinhardt@amd.com        code('%module(package="m5.internal") ${{self.swig_module_name()}}')
3787675Snate@binkert.org        code('%{')
3797675Snate@binkert.org        self.ptype.cxx_predecls(code)
3807675Snate@binkert.org        code('%}')
3817675Snate@binkert.org        code()
3828656Sandreas.hansson@arm.com        # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
3838656Sandreas.hansson@arm.com        code('%include "std_container.i"')
3848656Sandreas.hansson@arm.com        code()
3857675Snate@binkert.org        self.ptype.swig_predecls(code)
3867675Snate@binkert.org        code()
3877673Snate@binkert.org        code('%include "std_vector.i"')
3887675Snate@binkert.org        code()
3897675Snate@binkert.org
3907675Snate@binkert.org        ptype = self.ptype_str
3917675Snate@binkert.org        cxx_type = self.ptype.cxx_type
3927675Snate@binkert.org
3937675Snate@binkert.org        code('%template(vector_$ptype) std::vector< $cxx_type >;')
3947675Snate@binkert.org
3957673Snate@binkert.org    def cxx_predecls(self, code):
3967673Snate@binkert.org        code('#include <vector>')
3977673Snate@binkert.org        self.ptype.cxx_predecls(code)
3983101Sstever@eecs.umich.edu
3997673Snate@binkert.org    def cxx_decl(self, code):
4007673Snate@binkert.org        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
4013101Sstever@eecs.umich.edu
4023101Sstever@eecs.umich.educlass ParamFactory(object):
4033101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
4043101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
4053101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
4063101Sstever@eecs.umich.edu
4073101Sstever@eecs.umich.edu    def __getattr__(self, attr):
4083101Sstever@eecs.umich.edu        if self.ptype_str:
4093101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
4103101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
4113101Sstever@eecs.umich.edu
4123101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
4133101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
4143101Sstever@eecs.umich.edu        ptype = None
4153101Sstever@eecs.umich.edu        try:
4165033Smilesck@eecs.umich.edu            ptype = allParams[self.ptype_str]
4175033Smilesck@eecs.umich.edu        except KeyError:
4183101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
4193101Sstever@eecs.umich.edu            # try to resolve it later
4203101Sstever@eecs.umich.edu            pass
4213101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
4223101Sstever@eecs.umich.edu
4233101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
4243101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
4253101Sstever@eecs.umich.edu
4263101Sstever@eecs.umich.edu#####################################################################
4273101Sstever@eecs.umich.edu#
4283101Sstever@eecs.umich.edu# Parameter Types
4293101Sstever@eecs.umich.edu#
4303101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
4313101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
4323101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
4333101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
4343101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
4353101Sstever@eecs.umich.edu# the __str__() conversion method).
4363101Sstever@eecs.umich.edu#
4373101Sstever@eecs.umich.edu#####################################################################
4383101Sstever@eecs.umich.edu
4393101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
4403101Sstever@eecs.umich.edu# built-in str class.
4413101Sstever@eecs.umich.educlass String(ParamValue,str):
4423101Sstever@eecs.umich.edu    cxx_type = 'std::string'
44310267SGeoffrey.Blake@arm.com    cmd_line_settable = True
4447673Snate@binkert.org
4457673Snate@binkert.org    @classmethod
4467673Snate@binkert.org    def cxx_predecls(self, code):
4477673Snate@binkert.org        code('#include <string>')
4487673Snate@binkert.org
4497673Snate@binkert.org    @classmethod
4507673Snate@binkert.org    def swig_predecls(cls, code):
4517673Snate@binkert.org        code('%include "std_string.i"')
4524762Snate@binkert.org
45310267SGeoffrey.Blake@arm.com    def __call__(self, value):
45410267SGeoffrey.Blake@arm.com        self = value
45510267SGeoffrey.Blake@arm.com        return value
45610267SGeoffrey.Blake@arm.com
4574762Snate@binkert.org    def getValue(self):
4584762Snate@binkert.org        return self
4593101Sstever@eecs.umich.edu
4603101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
4613101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
4623101Sstever@eecs.umich.edu# a new Latency object.
4633101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
4643101Sstever@eecs.umich.edu    def __str__(self):
4653101Sstever@eecs.umich.edu        return str(self.value)
4663101Sstever@eecs.umich.edu
4673101Sstever@eecs.umich.edu    def __float__(self):
4683101Sstever@eecs.umich.edu        return float(self.value)
4693101Sstever@eecs.umich.edu
4703714Sstever@eecs.umich.edu    def __long__(self):
4713714Sstever@eecs.umich.edu        return long(self.value)
4723714Sstever@eecs.umich.edu
4733714Sstever@eecs.umich.edu    def __int__(self):
4743714Sstever@eecs.umich.edu        return int(self.value)
4753714Sstever@eecs.umich.edu
4763101Sstever@eecs.umich.edu    # hook for bounds checking
4773101Sstever@eecs.umich.edu    def _check(self):
4783101Sstever@eecs.umich.edu        return
4793101Sstever@eecs.umich.edu
4803101Sstever@eecs.umich.edu    def __mul__(self, other):
4813101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4823101Sstever@eecs.umich.edu        newobj.value *= other
4833101Sstever@eecs.umich.edu        newobj._check()
4843101Sstever@eecs.umich.edu        return newobj
4853101Sstever@eecs.umich.edu
4863101Sstever@eecs.umich.edu    __rmul__ = __mul__
4873101Sstever@eecs.umich.edu
4883101Sstever@eecs.umich.edu    def __div__(self, other):
4893101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4903101Sstever@eecs.umich.edu        newobj.value /= other
4913101Sstever@eecs.umich.edu        newobj._check()
4923101Sstever@eecs.umich.edu        return newobj
4933101Sstever@eecs.umich.edu
4943101Sstever@eecs.umich.edu    def __sub__(self, other):
4953101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4963101Sstever@eecs.umich.edu        newobj.value -= other
4973101Sstever@eecs.umich.edu        newobj._check()
4983101Sstever@eecs.umich.edu        return newobj
4993101Sstever@eecs.umich.edu
50010380SAndrew.Bardsley@arm.com    def config_value(self):
50110380SAndrew.Bardsley@arm.com        return self.value
50210380SAndrew.Bardsley@arm.com
5033101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
5045033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue):
5053101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5063101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
5073101Sstever@eecs.umich.edu
5083101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
5093101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
5103101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
5113101Sstever@eecs.umich.edu        if name == 'CheckedInt':
5123101Sstever@eecs.umich.edu            return
5133101Sstever@eecs.umich.edu
5143101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
5153101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
5163101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
5175822Ssaidi@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
5185822Ssaidi@eecs.umich.edu                      name);
5193101Sstever@eecs.umich.edu            if cls.unsigned:
5203101Sstever@eecs.umich.edu                cls.min = 0
5213101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
5223101Sstever@eecs.umich.edu            else:
5233101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
5243101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
5253101Sstever@eecs.umich.edu
5263101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
5273101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
5283101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
5293101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
5303101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue):
5313101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
53210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
5333101Sstever@eecs.umich.edu
5343101Sstever@eecs.umich.edu    def _check(self):
5353101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
5363101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
5373101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
5383101Sstever@eecs.umich.edu
5393101Sstever@eecs.umich.edu    def __init__(self, value):
5403101Sstever@eecs.umich.edu        if isinstance(value, str):
5413102Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
5423714Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
5433101Sstever@eecs.umich.edu            self.value = long(value)
5443714Sstever@eecs.umich.edu        else:
5453714Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to CheckedInt" \
5463714Sstever@eecs.umich.edu                  % type(value).__name__
5473101Sstever@eecs.umich.edu        self._check()
5483101Sstever@eecs.umich.edu
54910267SGeoffrey.Blake@arm.com    def __call__(self, value):
55010267SGeoffrey.Blake@arm.com        self.__init__(value)
55110267SGeoffrey.Blake@arm.com        return value
55210267SGeoffrey.Blake@arm.com
5537673Snate@binkert.org    @classmethod
5547673Snate@binkert.org    def cxx_predecls(cls, code):
5557673Snate@binkert.org        # most derived types require this, so we just do it here once
5567673Snate@binkert.org        code('#include "base/types.hh"')
5577673Snate@binkert.org
5587673Snate@binkert.org    @classmethod
5597673Snate@binkert.org    def swig_predecls(cls, code):
5607673Snate@binkert.org        # most derived types require this, so we just do it here once
5617673Snate@binkert.org        code('%import "stdint.i"')
5627673Snate@binkert.org        code('%import "base/types.hh"')
5637673Snate@binkert.org
5644762Snate@binkert.org    def getValue(self):
5654762Snate@binkert.org        return long(self.value)
5664762Snate@binkert.org
5673101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
5683101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
5693101Sstever@eecs.umich.edu
5703101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
5713101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
5723101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
5733101Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
5743101Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
5753101Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
5763101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
5773101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
5783101Sstever@eecs.umich.edu
5793101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
5803101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
5813101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
5823101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
5833101Sstever@eecs.umich.edu
5843101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
5853101Sstever@eecs.umich.edu
5869184Sandreas.hansson@arm.comclass Cycles(CheckedInt):
5879184Sandreas.hansson@arm.com    cxx_type = 'Cycles'
5889184Sandreas.hansson@arm.com    size = 64
5899184Sandreas.hansson@arm.com    unsigned = True
5909184Sandreas.hansson@arm.com
5919184Sandreas.hansson@arm.com    def getValue(self):
5929184Sandreas.hansson@arm.com        from m5.internal.core import Cycles
5939184Sandreas.hansson@arm.com        return Cycles(self.value)
5949184Sandreas.hansson@arm.com
5953101Sstever@eecs.umich.educlass Float(ParamValue, float):
5964446Sbinkertn@umich.edu    cxx_type = 'double'
59710267SGeoffrey.Blake@arm.com    cmdLineSettable = True
5983101Sstever@eecs.umich.edu
5995468Snate@binkert.org    def __init__(self, value):
60010267SGeoffrey.Blake@arm.com        if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
6015468Snate@binkert.org            self.value = float(value)
6025468Snate@binkert.org        else:
6035468Snate@binkert.org            raise TypeError, "Can't convert object of type %s to Float" \
6045468Snate@binkert.org                  % type(value).__name__
6055468Snate@binkert.org
60610267SGeoffrey.Blake@arm.com    def __call__(self, value):
60710267SGeoffrey.Blake@arm.com        self.__init__(value)
60810267SGeoffrey.Blake@arm.com        return value
60910267SGeoffrey.Blake@arm.com
6104762Snate@binkert.org    def getValue(self):
6114762Snate@binkert.org        return float(self.value)
6124762Snate@binkert.org
61310380SAndrew.Bardsley@arm.com    def config_value(self):
61410380SAndrew.Bardsley@arm.com        return self
61510380SAndrew.Bardsley@arm.com
6163101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
6173101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
61810267SGeoffrey.Blake@arm.com    ex_str = '512MB'
6193101Sstever@eecs.umich.edu    size = 64
6203101Sstever@eecs.umich.edu    unsigned = True
6213101Sstever@eecs.umich.edu    def __init__(self, value):
6223101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
6233101Sstever@eecs.umich.edu            self.value = value.value
6243101Sstever@eecs.umich.edu        else:
6253102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
6263101Sstever@eecs.umich.edu        self._check()
6273101Sstever@eecs.umich.edu
6283101Sstever@eecs.umich.educlass MemorySize32(CheckedInt):
6294168Sbinkertn@umich.edu    cxx_type = 'uint32_t'
63010267SGeoffrey.Blake@arm.com    ex_str = '512MB'
6313101Sstever@eecs.umich.edu    size = 32
6323101Sstever@eecs.umich.edu    unsigned = True
6333101Sstever@eecs.umich.edu    def __init__(self, value):
6343101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
6353101Sstever@eecs.umich.edu            self.value = value.value
6363101Sstever@eecs.umich.edu        else:
6373102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
6383101Sstever@eecs.umich.edu        self._check()
6393101Sstever@eecs.umich.edu
6403101Sstever@eecs.umich.educlass Addr(CheckedInt):
6413101Sstever@eecs.umich.edu    cxx_type = 'Addr'
6423101Sstever@eecs.umich.edu    size = 64
6433101Sstever@eecs.umich.edu    unsigned = True
6443101Sstever@eecs.umich.edu    def __init__(self, value):
6453101Sstever@eecs.umich.edu        if isinstance(value, Addr):
6463101Sstever@eecs.umich.edu            self.value = value.value
6473101Sstever@eecs.umich.edu        else:
6483101Sstever@eecs.umich.edu            try:
64910317Smitch.hayenga@arm.com                # Often addresses are referred to with sizes. Ex: A device
65010317Smitch.hayenga@arm.com                # base address is at "512MB".  Use toMemorySize() to convert
65110317Smitch.hayenga@arm.com                # these into addresses. If the address is not specified with a
65210317Smitch.hayenga@arm.com                # "size", an exception will occur and numeric translation will
65310317Smitch.hayenga@arm.com                # proceed below.
6543102Sstever@eecs.umich.edu                self.value = convert.toMemorySize(value)
65510317Smitch.hayenga@arm.com            except (TypeError, ValueError):
65610317Smitch.hayenga@arm.com                # Convert number to string and use long() to do automatic
65710317Smitch.hayenga@arm.com                # base conversion (requires base=0 for auto-conversion)
65810317Smitch.hayenga@arm.com                self.value = long(str(value), base=0)
65910317Smitch.hayenga@arm.com
6603101Sstever@eecs.umich.edu        self._check()
6613584Ssaidi@eecs.umich.edu    def __add__(self, other):
6623584Ssaidi@eecs.umich.edu        if isinstance(other, Addr):
6633584Ssaidi@eecs.umich.edu            return self.value + other.value
6643584Ssaidi@eecs.umich.edu        else:
6653584Ssaidi@eecs.umich.edu            return self.value + other
66610267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
66710267SGeoffrey.Blake@arm.com        try:
66810267SGeoffrey.Blake@arm.com            val = convert.toMemorySize(value)
66910267SGeoffrey.Blake@arm.com        except TypeError:
67010267SGeoffrey.Blake@arm.com            val = long(value)
67110267SGeoffrey.Blake@arm.com        return "0x%x" % long(val)
6723101Sstever@eecs.umich.edu
6739232Sandreas.hansson@arm.comclass AddrRange(ParamValue):
6749235Sandreas.hansson@arm.com    cxx_type = 'AddrRange'
6753101Sstever@eecs.umich.edu
6763101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
6779411Sandreas.hansson@arm.com        # Disable interleaving by default
6789411Sandreas.hansson@arm.com        self.intlvHighBit = 0
6799411Sandreas.hansson@arm.com        self.intlvBits = 0
6809411Sandreas.hansson@arm.com        self.intlvMatch = 0
6819411Sandreas.hansson@arm.com
6823101Sstever@eecs.umich.edu        def handle_kwargs(self, kwargs):
6839411Sandreas.hansson@arm.com            # An address range needs to have an upper limit, specified
6849411Sandreas.hansson@arm.com            # either explicitly with an end, or as an offset using the
6859411Sandreas.hansson@arm.com            # size keyword.
6863101Sstever@eecs.umich.edu            if 'end' in kwargs:
6879232Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
6883101Sstever@eecs.umich.edu            elif 'size' in kwargs:
6899232Sandreas.hansson@arm.com                self.end = self.start + Addr(kwargs.pop('size')) - 1
6903101Sstever@eecs.umich.edu            else:
6913101Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
6923101Sstever@eecs.umich.edu
6939411Sandreas.hansson@arm.com            # Now on to the optional bit
6949411Sandreas.hansson@arm.com            if 'intlvHighBit' in kwargs:
6959411Sandreas.hansson@arm.com                self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
6969411Sandreas.hansson@arm.com            if 'intlvBits' in kwargs:
6979411Sandreas.hansson@arm.com                self.intlvBits = int(kwargs.pop('intlvBits'))
6989411Sandreas.hansson@arm.com            if 'intlvMatch' in kwargs:
6999411Sandreas.hansson@arm.com                self.intlvMatch = int(kwargs.pop('intlvMatch'))
7009411Sandreas.hansson@arm.com
7013101Sstever@eecs.umich.edu        if len(args) == 0:
7029232Sandreas.hansson@arm.com            self.start = Addr(kwargs.pop('start'))
7033101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
7043101Sstever@eecs.umich.edu
7053101Sstever@eecs.umich.edu        elif len(args) == 1:
7063101Sstever@eecs.umich.edu            if kwargs:
7079232Sandreas.hansson@arm.com                self.start = Addr(args[0])
7083101Sstever@eecs.umich.edu                handle_kwargs(self, kwargs)
7095219Ssaidi@eecs.umich.edu            elif isinstance(args[0], (list, tuple)):
7109232Sandreas.hansson@arm.com                self.start = Addr(args[0][0])
7119232Sandreas.hansson@arm.com                self.end = Addr(args[0][1])
7123101Sstever@eecs.umich.edu            else:
7139232Sandreas.hansson@arm.com                self.start = Addr(0)
7149232Sandreas.hansson@arm.com                self.end = Addr(args[0]) - 1
7153101Sstever@eecs.umich.edu
7163101Sstever@eecs.umich.edu        elif len(args) == 2:
7179232Sandreas.hansson@arm.com            self.start = Addr(args[0])
7189232Sandreas.hansson@arm.com            self.end = Addr(args[1])
7193101Sstever@eecs.umich.edu        else:
7203101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
7213101Sstever@eecs.umich.edu
7223101Sstever@eecs.umich.edu        if kwargs:
7239232Sandreas.hansson@arm.com            raise TypeError, "Too many keywords: %s" % kwargs.keys()
7243101Sstever@eecs.umich.edu
7253101Sstever@eecs.umich.edu    def __str__(self):
7269232Sandreas.hansson@arm.com        return '%s:%s' % (self.start, self.end)
7279232Sandreas.hansson@arm.com
7289232Sandreas.hansson@arm.com    def size(self):
7299411Sandreas.hansson@arm.com        # Divide the size by the size of the interleaving slice
7309411Sandreas.hansson@arm.com        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
7313101Sstever@eecs.umich.edu
7327673Snate@binkert.org    @classmethod
7337673Snate@binkert.org    def cxx_predecls(cls, code):
7349232Sandreas.hansson@arm.com        Addr.cxx_predecls(code)
7359235Sandreas.hansson@arm.com        code('#include "base/addr_range.hh"')
7367675Snate@binkert.org
7377675Snate@binkert.org    @classmethod
7387675Snate@binkert.org    def swig_predecls(cls, code):
7399232Sandreas.hansson@arm.com        Addr.swig_predecls(code)
7407673Snate@binkert.org
7414762Snate@binkert.org    def getValue(self):
7429235Sandreas.hansson@arm.com        # Go from the Python class to the wrapped C++ class generated
7439235Sandreas.hansson@arm.com        # by swig
7447675Snate@binkert.org        from m5.internal.range import AddrRange
7454762Snate@binkert.org
7469411Sandreas.hansson@arm.com        return AddrRange(long(self.start), long(self.end),
7479411Sandreas.hansson@arm.com                         int(self.intlvHighBit), int(self.intlvBits),
7489411Sandreas.hansson@arm.com                         int(self.intlvMatch))
7493101Sstever@eecs.umich.edu
7503101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
7513101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and
7523101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
7533101Sstever@eecs.umich.educlass Bool(ParamValue):
7543101Sstever@eecs.umich.edu    cxx_type = 'bool'
75510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
75610267SGeoffrey.Blake@arm.com
7573101Sstever@eecs.umich.edu    def __init__(self, value):
7583101Sstever@eecs.umich.edu        try:
7593102Sstever@eecs.umich.edu            self.value = convert.toBool(value)
7603101Sstever@eecs.umich.edu        except TypeError:
7613101Sstever@eecs.umich.edu            self.value = bool(value)
7623101Sstever@eecs.umich.edu
76310267SGeoffrey.Blake@arm.com    def __call__(self, value):
76410267SGeoffrey.Blake@arm.com        self.__init__(value)
76510267SGeoffrey.Blake@arm.com        return value
76610267SGeoffrey.Blake@arm.com
7674762Snate@binkert.org    def getValue(self):
7684762Snate@binkert.org        return bool(self.value)
7694762Snate@binkert.org
7703101Sstever@eecs.umich.edu    def __str__(self):
7713101Sstever@eecs.umich.edu        return str(self.value)
7723101Sstever@eecs.umich.edu
7738934SBrad.Beckmann@amd.com    # implement truth value testing for Bool parameters so that these params
7748934SBrad.Beckmann@amd.com    # evaluate correctly during the python configuration phase
7758934SBrad.Beckmann@amd.com    def __nonzero__(self):
7768934SBrad.Beckmann@amd.com        return bool(self.value)
7778934SBrad.Beckmann@amd.com
7783101Sstever@eecs.umich.edu    def ini_str(self):
7793101Sstever@eecs.umich.edu        if self.value:
7803101Sstever@eecs.umich.edu            return 'true'
7813101Sstever@eecs.umich.edu        return 'false'
7823101Sstever@eecs.umich.edu
78310380SAndrew.Bardsley@arm.com    def config_value(self):
78410380SAndrew.Bardsley@arm.com        return self.value
78510380SAndrew.Bardsley@arm.com
7863101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
7873101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
7883101Sstever@eecs.umich.edu    bytes[5] += val
7893101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
7903101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
7913101Sstever@eecs.umich.edu        bytes[i] = rem
7923101Sstever@eecs.umich.edu        if val == 0:
7933101Sstever@eecs.umich.edu            break
7943101Sstever@eecs.umich.edu        bytes[i - 1] += val
7953101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
7963101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
7973101Sstever@eecs.umich.edu
7984380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
7994380Sbinkertn@umich.edudef NextEthernetAddr():
8004380Sbinkertn@umich.edu    global _NextEthernetAddr
8013101Sstever@eecs.umich.edu
8024380Sbinkertn@umich.edu    value = _NextEthernetAddr
8034380Sbinkertn@umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
8044380Sbinkertn@umich.edu    return value
8053101Sstever@eecs.umich.edu
8063101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
8073101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
80810267SGeoffrey.Blake@arm.com    ex_str = "00:90:00:00:00:01"
80910267SGeoffrey.Blake@arm.com    cmd_line_settable = True
8107673Snate@binkert.org
8117673Snate@binkert.org    @classmethod
8127673Snate@binkert.org    def cxx_predecls(cls, code):
8137673Snate@binkert.org        code('#include "base/inet.hh"')
8147673Snate@binkert.org
8157673Snate@binkert.org    @classmethod
8167673Snate@binkert.org    def swig_predecls(cls, code):
8177673Snate@binkert.org        code('%include "python/swig/inet.i"')
8187673Snate@binkert.org
8193101Sstever@eecs.umich.edu    def __init__(self, value):
8203101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
8213101Sstever@eecs.umich.edu            self.value = value
8223101Sstever@eecs.umich.edu            return
8233101Sstever@eecs.umich.edu
8243101Sstever@eecs.umich.edu        if not isinstance(value, str):
8253101Sstever@eecs.umich.edu            raise TypeError, "expected an ethernet address and didn't get one"
8263101Sstever@eecs.umich.edu
8273101Sstever@eecs.umich.edu        bytes = value.split(':')
8283101Sstever@eecs.umich.edu        if len(bytes) != 6:
8293101Sstever@eecs.umich.edu            raise TypeError, 'invalid ethernet address %s' % value
8303101Sstever@eecs.umich.edu
8313101Sstever@eecs.umich.edu        for byte in bytes:
8329941SGeoffrey.Blake@arm.com            if not 0 <= int(byte, base=16) <= 0xff:
8333101Sstever@eecs.umich.edu                raise TypeError, 'invalid ethernet address %s' % value
8343101Sstever@eecs.umich.edu
8353101Sstever@eecs.umich.edu        self.value = value
8363101Sstever@eecs.umich.edu
83710267SGeoffrey.Blake@arm.com    def __call__(self, value):
83810267SGeoffrey.Blake@arm.com        self.__init__(value)
83910267SGeoffrey.Blake@arm.com        return value
84010267SGeoffrey.Blake@arm.com
8413101Sstever@eecs.umich.edu    def unproxy(self, base):
8423101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
8434380Sbinkertn@umich.edu            return EthernetAddr(self.value())
8443101Sstever@eecs.umich.edu        return self
8453101Sstever@eecs.umich.edu
8464762Snate@binkert.org    def getValue(self):
8477677Snate@binkert.org        from m5.internal.params import EthAddr
8484762Snate@binkert.org        return EthAddr(self.value)
8494762Snate@binkert.org
8504380Sbinkertn@umich.edu    def ini_str(self):
8514380Sbinkertn@umich.edu        return self.value
8523101Sstever@eecs.umich.edu
8537777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
8547777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
8557777Sgblack@eecs.umich.educlass IpAddress(ParamValue):
8567777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpAddress'
85710267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1"
85810267SGeoffrey.Blake@arm.com    cmd_line_settable = True
8597777Sgblack@eecs.umich.edu
8607777Sgblack@eecs.umich.edu    @classmethod
8617777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
8627777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
8637777Sgblack@eecs.umich.edu
8647777Sgblack@eecs.umich.edu    @classmethod
8657777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
8667777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
8677777Sgblack@eecs.umich.edu
8687777Sgblack@eecs.umich.edu    def __init__(self, value):
8697777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
8707777Sgblack@eecs.umich.edu            self.ip = value.ip
8717777Sgblack@eecs.umich.edu        else:
8727777Sgblack@eecs.umich.edu            try:
8737777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
8747777Sgblack@eecs.umich.edu            except TypeError:
8757777Sgblack@eecs.umich.edu                self.ip = long(value)
8767777Sgblack@eecs.umich.edu        self.verifyIp()
8777777Sgblack@eecs.umich.edu
87810267SGeoffrey.Blake@arm.com    def __call__(self, value):
87910267SGeoffrey.Blake@arm.com        self.__init__(value)
88010267SGeoffrey.Blake@arm.com        return value
88110267SGeoffrey.Blake@arm.com
8828579Ssteve.reinhardt@amd.com    def __str__(self):
8838579Ssteve.reinhardt@amd.com        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
8848579Ssteve.reinhardt@amd.com        return '%d.%d.%d.%d' % tuple(tup)
8858579Ssteve.reinhardt@amd.com
8868579Ssteve.reinhardt@amd.com    def __eq__(self, other):
8878579Ssteve.reinhardt@amd.com        if isinstance(other, IpAddress):
8888579Ssteve.reinhardt@amd.com            return self.ip == other.ip
8898579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
8908579Ssteve.reinhardt@amd.com            try:
8918579Ssteve.reinhardt@amd.com                return self.ip == convert.toIpAddress(other)
8928579Ssteve.reinhardt@amd.com            except:
8938579Ssteve.reinhardt@amd.com                return False
8948579Ssteve.reinhardt@amd.com        else:
8958579Ssteve.reinhardt@amd.com            return self.ip == other
8968579Ssteve.reinhardt@amd.com
8978579Ssteve.reinhardt@amd.com    def __ne__(self, other):
8988579Ssteve.reinhardt@amd.com        return not (self == other)
8998579Ssteve.reinhardt@amd.com
9007777Sgblack@eecs.umich.edu    def verifyIp(self):
9017777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
9027798Sgblack@eecs.umich.edu            raise TypeError, "invalid ip address %#08x" % self.ip
9037777Sgblack@eecs.umich.edu
9047777Sgblack@eecs.umich.edu    def getValue(self):
9057777Sgblack@eecs.umich.edu        from m5.internal.params import IpAddress
9067777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
9077777Sgblack@eecs.umich.edu
9087777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
9097777Sgblack@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
9107777Sgblack@eecs.umich.edu# positional or keyword arguments.
9117777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
9127777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
91310267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.0/24"
91410267SGeoffrey.Blake@arm.com    cmd_line_settable = True
9157777Sgblack@eecs.umich.edu
9167777Sgblack@eecs.umich.edu    @classmethod
9177777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
9187777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
9197777Sgblack@eecs.umich.edu
9207777Sgblack@eecs.umich.edu    @classmethod
9217777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
9227777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
9237777Sgblack@eecs.umich.edu
9247777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
9257777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
9267777Sgblack@eecs.umich.edu            if key in kwargs:
9277777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
9287777Sgblack@eecs.umich.edu            elif elseVal:
9297777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
9307777Sgblack@eecs.umich.edu            else:
9317777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
9327777Sgblack@eecs.umich.edu
9337777Sgblack@eecs.umich.edu        if len(args) == 0:
9347777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
9357777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
9367777Sgblack@eecs.umich.edu
9377777Sgblack@eecs.umich.edu        elif len(args) == 1:
9387777Sgblack@eecs.umich.edu            if kwargs:
9397777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
9407777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
9417777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
9427777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
9437777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
9447777Sgblack@eecs.umich.edu                self.ip = args[0].ip
9457777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
9467777Sgblack@eecs.umich.edu            else:
9477777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
9487777Sgblack@eecs.umich.edu
9497777Sgblack@eecs.umich.edu        elif len(args) == 2:
9507777Sgblack@eecs.umich.edu            self.ip = args[0]
9517777Sgblack@eecs.umich.edu            self.netmask = args[1]
9527777Sgblack@eecs.umich.edu        else:
9537777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
9547777Sgblack@eecs.umich.edu
9557777Sgblack@eecs.umich.edu        if kwargs:
9567777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
9577777Sgblack@eecs.umich.edu
9587777Sgblack@eecs.umich.edu        self.verify()
9597777Sgblack@eecs.umich.edu
96010267SGeoffrey.Blake@arm.com    def __call__(self, value):
96110267SGeoffrey.Blake@arm.com        self.__init__(value)
96210267SGeoffrey.Blake@arm.com        return value
96310267SGeoffrey.Blake@arm.com
9648579Ssteve.reinhardt@amd.com    def __str__(self):
9658579Ssteve.reinhardt@amd.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
9668579Ssteve.reinhardt@amd.com
9678579Ssteve.reinhardt@amd.com    def __eq__(self, other):
9688579Ssteve.reinhardt@amd.com        if isinstance(other, IpNetmask):
9698579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.netmask == other.netmask
9708579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
9718579Ssteve.reinhardt@amd.com            try:
9728579Ssteve.reinhardt@amd.com                return (self.ip, self.netmask) == convert.toIpNetmask(other)
9738579Ssteve.reinhardt@amd.com            except:
9748579Ssteve.reinhardt@amd.com                return False
9758579Ssteve.reinhardt@amd.com        else:
9768579Ssteve.reinhardt@amd.com            return False
9778579Ssteve.reinhardt@amd.com
9787777Sgblack@eecs.umich.edu    def verify(self):
9797777Sgblack@eecs.umich.edu        self.verifyIp()
9807777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
9817777Sgblack@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
9827777Sgblack@eecs.umich.edu
9837777Sgblack@eecs.umich.edu    def getValue(self):
9847777Sgblack@eecs.umich.edu        from m5.internal.params import IpNetmask
9857777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
9867777Sgblack@eecs.umich.edu
9877777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
9887777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
9897777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
9907777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
99110267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1:80"
99210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
9937777Sgblack@eecs.umich.edu
9947777Sgblack@eecs.umich.edu    @classmethod
9957777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
9967777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
9977777Sgblack@eecs.umich.edu
9987777Sgblack@eecs.umich.edu    @classmethod
9997777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
10007777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
10017777Sgblack@eecs.umich.edu
10027777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10037777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10047777Sgblack@eecs.umich.edu            if key in kwargs:
10057777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10067777Sgblack@eecs.umich.edu            elif elseVal:
10077777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10087777Sgblack@eecs.umich.edu            else:
10097777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
10107777Sgblack@eecs.umich.edu
10117777Sgblack@eecs.umich.edu        if len(args) == 0:
10127777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
10137777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
10147777Sgblack@eecs.umich.edu
10157777Sgblack@eecs.umich.edu        elif len(args) == 1:
10167777Sgblack@eecs.umich.edu            if kwargs:
10177777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
10187777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
10197777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
10207777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
10217777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpWithPort):
10227777Sgblack@eecs.umich.edu                self.ip = args[0].ip
10237777Sgblack@eecs.umich.edu                self.port = args[0].port
10247777Sgblack@eecs.umich.edu            else:
10257777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
10267777Sgblack@eecs.umich.edu
10277777Sgblack@eecs.umich.edu        elif len(args) == 2:
10287777Sgblack@eecs.umich.edu            self.ip = args[0]
10297777Sgblack@eecs.umich.edu            self.port = args[1]
10307777Sgblack@eecs.umich.edu        else:
10317777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
10327777Sgblack@eecs.umich.edu
10337777Sgblack@eecs.umich.edu        if kwargs:
10347777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
10357777Sgblack@eecs.umich.edu
10367777Sgblack@eecs.umich.edu        self.verify()
10377777Sgblack@eecs.umich.edu
103810267SGeoffrey.Blake@arm.com    def __call__(self, value):
103910267SGeoffrey.Blake@arm.com        self.__init__(value)
104010267SGeoffrey.Blake@arm.com        return value
104110267SGeoffrey.Blake@arm.com
10428579Ssteve.reinhardt@amd.com    def __str__(self):
10438579Ssteve.reinhardt@amd.com        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
10448579Ssteve.reinhardt@amd.com
10458579Ssteve.reinhardt@amd.com    def __eq__(self, other):
10468579Ssteve.reinhardt@amd.com        if isinstance(other, IpWithPort):
10478579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.port == other.port
10488579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
10498579Ssteve.reinhardt@amd.com            try:
10508579Ssteve.reinhardt@amd.com                return (self.ip, self.port) == convert.toIpWithPort(other)
10518579Ssteve.reinhardt@amd.com            except:
10528579Ssteve.reinhardt@amd.com                return False
10538579Ssteve.reinhardt@amd.com        else:
10548579Ssteve.reinhardt@amd.com            return False
10558579Ssteve.reinhardt@amd.com
10567777Sgblack@eecs.umich.edu    def verify(self):
10577777Sgblack@eecs.umich.edu        self.verifyIp()
10587777Sgblack@eecs.umich.edu        if self.port < 0 or self.port > 0xffff:
10597777Sgblack@eecs.umich.edu            raise TypeError, "invalid port %d" % self.port
10607777Sgblack@eecs.umich.edu
10617777Sgblack@eecs.umich.edu    def getValue(self):
10627777Sgblack@eecs.umich.edu        from m5.internal.params import IpWithPort
10637777Sgblack@eecs.umich.edu        return IpWithPort(self.ip, self.port)
10647777Sgblack@eecs.umich.edu
10653932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
106610380SAndrew.Bardsley@arm.com                 "%a %b %d %H:%M:%S %Y",
10673932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
10683932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
10693932Sbinkertn@umich.edu                 "%Y/%m/%d",
10703932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
10713932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
10723932Sbinkertn@umich.edu                 "%m/%d/%Y",
10733932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M:%S",
10743932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M",
10753932Sbinkertn@umich.edu                 "%m/%d/%y"]
10763932Sbinkertn@umich.edu
10773932Sbinkertn@umich.edu
10783885Sbinkertn@umich.edudef parse_time(value):
10793932Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
10803932Sbinkertn@umich.edu    from datetime import datetime, date
10813885Sbinkertn@umich.edu
10823932Sbinkertn@umich.edu    if isinstance(value, struct_time):
10833932Sbinkertn@umich.edu        return value
10843932Sbinkertn@umich.edu
10853932Sbinkertn@umich.edu    if isinstance(value, (int, long)):
10863932Sbinkertn@umich.edu        return gmtime(value)
10873932Sbinkertn@umich.edu
10883932Sbinkertn@umich.edu    if isinstance(value, (datetime, date)):
10893932Sbinkertn@umich.edu        return value.timetuple()
10903932Sbinkertn@umich.edu
10913932Sbinkertn@umich.edu    if isinstance(value, str):
10923932Sbinkertn@umich.edu        if value in ('Now', 'Today'):
10933932Sbinkertn@umich.edu            return time.gmtime(time.time())
10943932Sbinkertn@umich.edu
10953932Sbinkertn@umich.edu        for format in time_formats:
10963932Sbinkertn@umich.edu            try:
10973932Sbinkertn@umich.edu                return strptime(value, format)
10983932Sbinkertn@umich.edu            except ValueError:
10993932Sbinkertn@umich.edu                pass
11003885Sbinkertn@umich.edu
11013885Sbinkertn@umich.edu    raise ValueError, "Could not parse '%s' as a time" % value
11023885Sbinkertn@umich.edu
11033885Sbinkertn@umich.educlass Time(ParamValue):
11044762Snate@binkert.org    cxx_type = 'tm'
11057673Snate@binkert.org
11067673Snate@binkert.org    @classmethod
11077673Snate@binkert.org    def cxx_predecls(cls, code):
11087673Snate@binkert.org        code('#include <time.h>')
11097673Snate@binkert.org
11107673Snate@binkert.org    @classmethod
11117673Snate@binkert.org    def swig_predecls(cls, code):
11127673Snate@binkert.org        code('%include "python/swig/time.i"')
11137673Snate@binkert.org
11143885Sbinkertn@umich.edu    def __init__(self, value):
11153932Sbinkertn@umich.edu        self.value = parse_time(value)
11163885Sbinkertn@umich.edu
111710267SGeoffrey.Blake@arm.com    def __call__(self, value):
111810267SGeoffrey.Blake@arm.com        self.__init__(value)
111910267SGeoffrey.Blake@arm.com        return value
112010267SGeoffrey.Blake@arm.com
11214762Snate@binkert.org    def getValue(self):
11227677Snate@binkert.org        from m5.internal.params import tm
11234762Snate@binkert.org
11244762Snate@binkert.org        c_time = tm()
11254762Snate@binkert.org        py_time = self.value
11264762Snate@binkert.org
11274762Snate@binkert.org        # UNIX is years since 1900
11284762Snate@binkert.org        c_time.tm_year = py_time.tm_year - 1900;
11294762Snate@binkert.org
11304762Snate@binkert.org        # Python starts at 1, UNIX starts at 0
11314762Snate@binkert.org        c_time.tm_mon =  py_time.tm_mon - 1;
11324762Snate@binkert.org        c_time.tm_mday = py_time.tm_mday;
11334762Snate@binkert.org        c_time.tm_hour = py_time.tm_hour;
11344762Snate@binkert.org        c_time.tm_min = py_time.tm_min;
11354762Snate@binkert.org        c_time.tm_sec = py_time.tm_sec;
11364762Snate@binkert.org
11374762Snate@binkert.org        # Python has 0 as Monday, UNIX is 0 as sunday
11384762Snate@binkert.org        c_time.tm_wday = py_time.tm_wday + 1
11394762Snate@binkert.org        if c_time.tm_wday > 6:
11404762Snate@binkert.org            c_time.tm_wday -= 7;
11414762Snate@binkert.org
11424762Snate@binkert.org        # Python starts at 1, Unix starts at 0
11434762Snate@binkert.org        c_time.tm_yday = py_time.tm_yday - 1;
11444762Snate@binkert.org
11454762Snate@binkert.org        return c_time
11464762Snate@binkert.org
11473885Sbinkertn@umich.edu    def __str__(self):
11484762Snate@binkert.org        return time.asctime(self.value)
11493885Sbinkertn@umich.edu
11503885Sbinkertn@umich.edu    def ini_str(self):
11513932Sbinkertn@umich.edu        return str(self)
11523885Sbinkertn@umich.edu
11538664SAli.Saidi@ARM.com    def get_config_as_dict(self):
115410380SAndrew.Bardsley@arm.com        assert false
11558664SAli.Saidi@ARM.com        return str(self)
11568664SAli.Saidi@ARM.com
11573101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
11583101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
11593101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
11603101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
11613101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
11623101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
11633101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
11643101Sstever@eecs.umich.edu
11653101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
11663101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
11673101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
11683101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
11693101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
11703101Sstever@eecs.umich.edu
11714762Snate@binkert.orgallEnums = {}
11723101Sstever@eecs.umich.edu# Metaclass for Enum types
11735033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue):
11744762Snate@binkert.org    def __new__(mcls, name, bases, dict):
11754762Snate@binkert.org        assert name not in allEnums
11764762Snate@binkert.org
11774762Snate@binkert.org        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
11784762Snate@binkert.org        allEnums[name] = cls
11794762Snate@binkert.org        return cls
11804762Snate@binkert.org
11813101Sstever@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
11823101Sstever@eecs.umich.edu        if init_dict.has_key('map'):
11833101Sstever@eecs.umich.edu            if not isinstance(cls.map, dict):
11843101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'map' " \
11853101Sstever@eecs.umich.edu                      "must be of type dict"
11863101Sstever@eecs.umich.edu            # build list of value strings from map
11873101Sstever@eecs.umich.edu            cls.vals = cls.map.keys()
11883101Sstever@eecs.umich.edu            cls.vals.sort()
11893101Sstever@eecs.umich.edu        elif init_dict.has_key('vals'):
11903101Sstever@eecs.umich.edu            if not isinstance(cls.vals, list):
11913101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'vals' " \
11923101Sstever@eecs.umich.edu                      "must be of type list"
11933101Sstever@eecs.umich.edu            # build string->value map from vals sequence
11943101Sstever@eecs.umich.edu            cls.map = {}
11953101Sstever@eecs.umich.edu            for idx,val in enumerate(cls.vals):
11963101Sstever@eecs.umich.edu                cls.map[val] = idx
11973101Sstever@eecs.umich.edu        else:
11983101Sstever@eecs.umich.edu            raise TypeError, "Enum-derived class must define "\
11993101Sstever@eecs.umich.edu                  "attribute 'map' or 'vals'"
12003101Sstever@eecs.umich.edu
12014762Snate@binkert.org        cls.cxx_type = 'Enums::%s' % name
12023101Sstever@eecs.umich.edu
12033101Sstever@eecs.umich.edu        super(MetaEnum, cls).__init__(name, bases, init_dict)
12043101Sstever@eecs.umich.edu
12053101Sstever@eecs.umich.edu    # Generate C++ class declaration for this enum type.
12063101Sstever@eecs.umich.edu    # Note that we wrap the enum in a class/struct to act as a namespace,
12073101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
12087673Snate@binkert.org    def cxx_decl(cls, code):
120910201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
121010201SAndrew.Bardsley@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
121110201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
121210201SAndrew.Bardsley@arm.com        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
121310201SAndrew.Bardsley@arm.com
12147673Snate@binkert.org        code('''\
121510201SAndrew.Bardsley@arm.com#ifndef $idem_macro
121610201SAndrew.Bardsley@arm.com#define $idem_macro
12177673Snate@binkert.org
121810201SAndrew.Bardsley@arm.com$wrapper $wrapper_name {
12197673Snate@binkert.org    enum $name {
12207673Snate@binkert.org''')
12217673Snate@binkert.org        code.indent(2)
12224762Snate@binkert.org        for val in cls.vals:
12237673Snate@binkert.org            code('$val = ${{cls.map[val]}},')
12248902Sandreas.hansson@arm.com        code('Num_$name = ${{len(cls.vals)}}')
12257673Snate@binkert.org        code.dedent(2)
122610201SAndrew.Bardsley@arm.com        code('    };')
12274762Snate@binkert.org
122810201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
122910201SAndrew.Bardsley@arm.com            code('    static const char *${name}Strings[Num_${name}];')
123010201SAndrew.Bardsley@arm.com            code('};')
123110201SAndrew.Bardsley@arm.com        else:
123210201SAndrew.Bardsley@arm.com            code('extern const char *${name}Strings[Num_${name}];')
123310201SAndrew.Bardsley@arm.com            code('}')
123410201SAndrew.Bardsley@arm.com
123510201SAndrew.Bardsley@arm.com        code()
123610201SAndrew.Bardsley@arm.com        code('#endif // $idem_macro')
12377673Snate@binkert.org
12387673Snate@binkert.org    def cxx_def(cls, code):
123910201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
124010201SAndrew.Bardsley@arm.com        file_name = cls.__name__
124110201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
124210201SAndrew.Bardsley@arm.com
124310201SAndrew.Bardsley@arm.com        code('#include "enums/$file_name.hh"')
124410201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
124510201SAndrew.Bardsley@arm.com            code('const char *${wrapper_name}::${name}Strings'
124610201SAndrew.Bardsley@arm.com                '[Num_${name}] =')
124710201SAndrew.Bardsley@arm.com        else:
124810201SAndrew.Bardsley@arm.com            code('namespace Enums {')
124910201SAndrew.Bardsley@arm.com            code.indent(1)
125010201SAndrew.Bardsley@arm.com            code(' const char *${name}Strings[Num_${name}] =')
125110201SAndrew.Bardsley@arm.com
125210201SAndrew.Bardsley@arm.com        code('{')
125310201SAndrew.Bardsley@arm.com        code.indent(1)
12544762Snate@binkert.org        for val in cls.vals:
12557673Snate@binkert.org            code('"$val",')
125610201SAndrew.Bardsley@arm.com        code.dedent(1)
125710201SAndrew.Bardsley@arm.com        code('};')
125810201SAndrew.Bardsley@arm.com
125910201SAndrew.Bardsley@arm.com        if not cls.wrapper_is_struct:
126010201SAndrew.Bardsley@arm.com            code('} // namespace $wrapper_name')
126110201SAndrew.Bardsley@arm.com            code.dedent(1)
12623101Sstever@eecs.umich.edu
12638596Ssteve.reinhardt@amd.com    def swig_decl(cls, code):
12648596Ssteve.reinhardt@amd.com        name = cls.__name__
12658596Ssteve.reinhardt@amd.com        code('''\
12668596Ssteve.reinhardt@amd.com%module(package="m5.internal") enum_$name
12678596Ssteve.reinhardt@amd.com
12688596Ssteve.reinhardt@amd.com%{
12698596Ssteve.reinhardt@amd.com#include "enums/$name.hh"
12708596Ssteve.reinhardt@amd.com%}
12718596Ssteve.reinhardt@amd.com
12728596Ssteve.reinhardt@amd.com%include "enums/$name.hh"
12738596Ssteve.reinhardt@amd.com''')
12748596Ssteve.reinhardt@amd.com
12758596Ssteve.reinhardt@amd.com
12763101Sstever@eecs.umich.edu# Base class for enum types.
12773101Sstever@eecs.umich.educlass Enum(ParamValue):
12783101Sstever@eecs.umich.edu    __metaclass__ = MetaEnum
12793101Sstever@eecs.umich.edu    vals = []
128010267SGeoffrey.Blake@arm.com    cmd_line_settable = True
12813101Sstever@eecs.umich.edu
128210201SAndrew.Bardsley@arm.com    # The name of the wrapping namespace or struct
128310201SAndrew.Bardsley@arm.com    wrapper_name = 'Enums'
128410201SAndrew.Bardsley@arm.com
128510201SAndrew.Bardsley@arm.com    # If true, the enum is wrapped in a struct rather than a namespace
128610201SAndrew.Bardsley@arm.com    wrapper_is_struct = False
128710201SAndrew.Bardsley@arm.com
128810201SAndrew.Bardsley@arm.com    # If not None, use this as the enum name rather than this class name
128910201SAndrew.Bardsley@arm.com    enum_name = None
129010201SAndrew.Bardsley@arm.com
12913101Sstever@eecs.umich.edu    def __init__(self, value):
12923101Sstever@eecs.umich.edu        if value not in self.map:
12933101Sstever@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
12943101Sstever@eecs.umich.edu                  % (value, self.vals)
12953101Sstever@eecs.umich.edu        self.value = value
12963101Sstever@eecs.umich.edu
129710267SGeoffrey.Blake@arm.com    def __call__(self, value):
129810267SGeoffrey.Blake@arm.com        self.__init__(value)
129910267SGeoffrey.Blake@arm.com        return value
130010267SGeoffrey.Blake@arm.com
13017675Snate@binkert.org    @classmethod
13027675Snate@binkert.org    def cxx_predecls(cls, code):
13037675Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
13047675Snate@binkert.org
13057675Snate@binkert.org    @classmethod
13067675Snate@binkert.org    def swig_predecls(cls, code):
13077677Snate@binkert.org        code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
13087675Snate@binkert.org
13094762Snate@binkert.org    def getValue(self):
13104762Snate@binkert.org        return int(self.map[self.value])
13114762Snate@binkert.org
13123101Sstever@eecs.umich.edu    def __str__(self):
13133101Sstever@eecs.umich.edu        return self.value
13143101Sstever@eecs.umich.edu
13153101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it?
13163101Sstever@eecs.umich.edufrequency_tolerance = 0.001  # 0.1%
13173101Sstever@eecs.umich.edu
13184167Sbinkertn@umich.educlass TickParamValue(NumericParamValue):
13193101Sstever@eecs.umich.edu    cxx_type = 'Tick'
132010267SGeoffrey.Blake@arm.com    ex_str = "1MHz"
132110267SGeoffrey.Blake@arm.com    cmd_line_settable = True
13227673Snate@binkert.org
13237673Snate@binkert.org    @classmethod
13247673Snate@binkert.org    def cxx_predecls(cls, code):
13257673Snate@binkert.org        code('#include "base/types.hh"')
13267673Snate@binkert.org
13277673Snate@binkert.org    @classmethod
13287673Snate@binkert.org    def swig_predecls(cls, code):
13297673Snate@binkert.org        code('%import "stdint.i"')
13307673Snate@binkert.org        code('%import "base/types.hh"')
13314167Sbinkertn@umich.edu
133210267SGeoffrey.Blake@arm.com    def __call__(self, value):
133310267SGeoffrey.Blake@arm.com        self.__init__(value)
133410267SGeoffrey.Blake@arm.com        return value
133510267SGeoffrey.Blake@arm.com
13364762Snate@binkert.org    def getValue(self):
13374762Snate@binkert.org        return long(self.value)
13384762Snate@binkert.org
13394167Sbinkertn@umich.educlass Latency(TickParamValue):
134010267SGeoffrey.Blake@arm.com    ex_str = "100ns"
134110267SGeoffrey.Blake@arm.com
13423101Sstever@eecs.umich.edu    def __init__(self, value):
13434167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
13444167Sbinkertn@umich.edu            self.ticks = value.ticks
13454167Sbinkertn@umich.edu            self.value = value.value
13464167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
13474167Sbinkertn@umich.edu            self.ticks = value.ticks
13484167Sbinkertn@umich.edu            self.value = 1.0 / value.value
13494167Sbinkertn@umich.edu        elif value.endswith('t'):
13504167Sbinkertn@umich.edu            self.ticks = True
13514167Sbinkertn@umich.edu            self.value = int(value[:-1])
13524167Sbinkertn@umich.edu        else:
13534167Sbinkertn@umich.edu            self.ticks = False
13544167Sbinkertn@umich.edu            self.value = convert.toLatency(value)
13553101Sstever@eecs.umich.edu
135610267SGeoffrey.Blake@arm.com    def __call__(self, value):
135710267SGeoffrey.Blake@arm.com        self.__init__(value)
135810267SGeoffrey.Blake@arm.com        return value
135910267SGeoffrey.Blake@arm.com
13603101Sstever@eecs.umich.edu    def __getattr__(self, attr):
13613101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
13623101Sstever@eecs.umich.edu            return self
13633101Sstever@eecs.umich.edu        if attr == 'frequency':
13643101Sstever@eecs.umich.edu            return Frequency(self)
13653101Sstever@eecs.umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
13663101Sstever@eecs.umich.edu
13674762Snate@binkert.org    def getValue(self):
13684762Snate@binkert.org        if self.ticks or self.value == 0:
13694762Snate@binkert.org            value = self.value
13704762Snate@binkert.org        else:
13714762Snate@binkert.org            value = ticks.fromSeconds(self.value)
13724762Snate@binkert.org        return long(value)
13734762Snate@binkert.org
137410380SAndrew.Bardsley@arm.com    def config_value(self):
137510380SAndrew.Bardsley@arm.com        return self.getValue()
137610380SAndrew.Bardsley@arm.com
13773101Sstever@eecs.umich.edu    # convert latency to ticks
13783101Sstever@eecs.umich.edu    def ini_str(self):
13794762Snate@binkert.org        return '%d' % self.getValue()
13803101Sstever@eecs.umich.edu
13814167Sbinkertn@umich.educlass Frequency(TickParamValue):
138210267SGeoffrey.Blake@arm.com    ex_str = "1GHz"
138310267SGeoffrey.Blake@arm.com
13843101Sstever@eecs.umich.edu    def __init__(self, value):
13854167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
13864167Sbinkertn@umich.edu            if value.value == 0:
13874167Sbinkertn@umich.edu                self.value = 0
13884167Sbinkertn@umich.edu            else:
13894167Sbinkertn@umich.edu                self.value = 1.0 / value.value
13904167Sbinkertn@umich.edu            self.ticks = value.ticks
13914167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
13924167Sbinkertn@umich.edu            self.value = value.value
13934167Sbinkertn@umich.edu            self.ticks = value.ticks
13944167Sbinkertn@umich.edu        else:
13954167Sbinkertn@umich.edu            self.ticks = False
13964167Sbinkertn@umich.edu            self.value = convert.toFrequency(value)
13973101Sstever@eecs.umich.edu
139810267SGeoffrey.Blake@arm.com    def __call__(self, value):
139910267SGeoffrey.Blake@arm.com        self.__init__(value)
140010267SGeoffrey.Blake@arm.com        return value
140110267SGeoffrey.Blake@arm.com
14023101Sstever@eecs.umich.edu    def __getattr__(self, attr):
14033101Sstever@eecs.umich.edu        if attr == 'frequency':
14043101Sstever@eecs.umich.edu            return self
14053101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
14063101Sstever@eecs.umich.edu            return Latency(self)
14073101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
14083101Sstever@eecs.umich.edu
14094167Sbinkertn@umich.edu    # convert latency to ticks
14104762Snate@binkert.org    def getValue(self):
14114762Snate@binkert.org        if self.ticks or self.value == 0:
14124762Snate@binkert.org            value = self.value
14134762Snate@binkert.org        else:
14144762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
14154762Snate@binkert.org        return long(value)
14164762Snate@binkert.org
141710380SAndrew.Bardsley@arm.com    def config_value(self):
141810380SAndrew.Bardsley@arm.com        return self.getValue()
141910380SAndrew.Bardsley@arm.com
14203101Sstever@eecs.umich.edu    def ini_str(self):
14214762Snate@binkert.org        return '%d' % self.getValue()
14223101Sstever@eecs.umich.edu
142310019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a
142410019Sandreas.hansson@arm.com# latency, just like Latency and Frequency.
142510019Sandreas.hansson@arm.comclass Clock(TickParamValue):
14263101Sstever@eecs.umich.edu    def __init__(self, value):
14274167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
14284167Sbinkertn@umich.edu            self.ticks = value.ticks
14294167Sbinkertn@umich.edu            self.value = value.value
14304167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
14314167Sbinkertn@umich.edu            self.ticks = value.ticks
14324167Sbinkertn@umich.edu            self.value = 1.0 / value.value
14334167Sbinkertn@umich.edu        elif value.endswith('t'):
14344167Sbinkertn@umich.edu            self.ticks = True
14354167Sbinkertn@umich.edu            self.value = int(value[:-1])
14364167Sbinkertn@umich.edu        else:
14374167Sbinkertn@umich.edu            self.ticks = False
14384167Sbinkertn@umich.edu            self.value = convert.anyToLatency(value)
14393101Sstever@eecs.umich.edu
144010267SGeoffrey.Blake@arm.com    def __call__(self, value):
144110267SGeoffrey.Blake@arm.com        self.__init__(value)
144210267SGeoffrey.Blake@arm.com        return value
144310267SGeoffrey.Blake@arm.com
144410267SGeoffrey.Blake@arm.com    def __str__(self):
144510267SGeoffrey.Blake@arm.com        return "%s" % Latency(self)
144610267SGeoffrey.Blake@arm.com
14473101Sstever@eecs.umich.edu    def __getattr__(self, attr):
14483101Sstever@eecs.umich.edu        if attr == 'frequency':
14493101Sstever@eecs.umich.edu            return Frequency(self)
14503101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
14513101Sstever@eecs.umich.edu            return Latency(self)
14523101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
14533101Sstever@eecs.umich.edu
14544762Snate@binkert.org    def getValue(self):
14554762Snate@binkert.org        return self.period.getValue()
14564762Snate@binkert.org
145710380SAndrew.Bardsley@arm.com    def config_value(self):
145810380SAndrew.Bardsley@arm.com        return self.period.config_value()
145910380SAndrew.Bardsley@arm.com
14603101Sstever@eecs.umich.edu    def ini_str(self):
14613101Sstever@eecs.umich.edu        return self.period.ini_str()
14623101Sstever@eecs.umich.edu
14639827Sakash.bagdia@arm.comclass Voltage(float,ParamValue):
14649827Sakash.bagdia@arm.com    cxx_type = 'double'
146510267SGeoffrey.Blake@arm.com    ex_str = "1V"
146610267SGeoffrey.Blake@arm.com    cmd_line_settable = False
146710267SGeoffrey.Blake@arm.com
14689827Sakash.bagdia@arm.com    def __new__(cls, value):
14699827Sakash.bagdia@arm.com        # convert to voltage
14709827Sakash.bagdia@arm.com        val = convert.toVoltage(value)
14719827Sakash.bagdia@arm.com        return super(cls, Voltage).__new__(cls, val)
14729827Sakash.bagdia@arm.com
147310267SGeoffrey.Blake@arm.com    def __call__(self, value):
147410267SGeoffrey.Blake@arm.com        val = convert.toVoltage(value)
147510267SGeoffrey.Blake@arm.com        self.__init__(val)
147610267SGeoffrey.Blake@arm.com        return value
147710267SGeoffrey.Blake@arm.com
14789827Sakash.bagdia@arm.com    def __str__(self):
147910267SGeoffrey.Blake@arm.com        return str(self.getValue())
14809827Sakash.bagdia@arm.com
14819827Sakash.bagdia@arm.com    def getValue(self):
14829827Sakash.bagdia@arm.com        value = float(self)
14839827Sakash.bagdia@arm.com        return value
14849827Sakash.bagdia@arm.com
14859827Sakash.bagdia@arm.com    def ini_str(self):
14869827Sakash.bagdia@arm.com        return '%f' % self.getValue()
14879827Sakash.bagdia@arm.com
14883101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
14893101Sstever@eecs.umich.edu    cxx_type = 'float'
149010267SGeoffrey.Blake@arm.com    ex_str = "1Gbps"
149110267SGeoffrey.Blake@arm.com    cmd_line_settable = True
149210267SGeoffrey.Blake@arm.com
14933101Sstever@eecs.umich.edu    def __new__(cls, value):
14944167Sbinkertn@umich.edu        # convert to bits per second
14954167Sbinkertn@umich.edu        val = convert.toNetworkBandwidth(value)
14963101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
14973101Sstever@eecs.umich.edu
14983101Sstever@eecs.umich.edu    def __str__(self):
14993101Sstever@eecs.umich.edu        return str(self.val)
15003101Sstever@eecs.umich.edu
150110267SGeoffrey.Blake@arm.com    def __call__(self, value):
150210267SGeoffrey.Blake@arm.com        val = convert.toNetworkBandwidth(value)
150310267SGeoffrey.Blake@arm.com        self.__init__(val)
150410267SGeoffrey.Blake@arm.com        return value
150510267SGeoffrey.Blake@arm.com
15064762Snate@binkert.org    def getValue(self):
15074167Sbinkertn@umich.edu        # convert to seconds per byte
15084167Sbinkertn@umich.edu        value = 8.0 / float(self)
15094167Sbinkertn@umich.edu        # convert to ticks per byte
15104762Snate@binkert.org        value = ticks.fromSeconds(value)
15114762Snate@binkert.org        return float(value)
15124762Snate@binkert.org
15134762Snate@binkert.org    def ini_str(self):
15144762Snate@binkert.org        return '%f' % self.getValue()
15153101Sstever@eecs.umich.edu
151610380SAndrew.Bardsley@arm.com    def config_value(self):
151710380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
151810380SAndrew.Bardsley@arm.com
15193101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
15203101Sstever@eecs.umich.edu    cxx_type = 'float'
152110267SGeoffrey.Blake@arm.com    ex_str = "1GB/s"
152210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
152310267SGeoffrey.Blake@arm.com
15245469Snate@binkert.org    def __new__(cls, value):
15257743Sgblack@eecs.umich.edu        # convert to bytes per second
15263102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
15273101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
15283101Sstever@eecs.umich.edu
152910267SGeoffrey.Blake@arm.com    def __call__(self, value):
153010267SGeoffrey.Blake@arm.com        val = convert.toMemoryBandwidth(value)
153110267SGeoffrey.Blake@arm.com        self.__init__(val)
153210267SGeoffrey.Blake@arm.com        return value
15333101Sstever@eecs.umich.edu
15344762Snate@binkert.org    def getValue(self):
15354167Sbinkertn@umich.edu        # convert to seconds per byte
15365468Snate@binkert.org        value = float(self)
15375468Snate@binkert.org        if value:
15385468Snate@binkert.org            value = 1.0 / float(self)
15394167Sbinkertn@umich.edu        # convert to ticks per byte
15404762Snate@binkert.org        value = ticks.fromSeconds(value)
15414762Snate@binkert.org        return float(value)
15424762Snate@binkert.org
15434762Snate@binkert.org    def ini_str(self):
15444762Snate@binkert.org        return '%f' % self.getValue()
15453101Sstever@eecs.umich.edu
154610380SAndrew.Bardsley@arm.com    def config_value(self):
154710380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
154810380SAndrew.Bardsley@arm.com
15493101Sstever@eecs.umich.edu#
15503101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
15513101Sstever@eecs.umich.edu#
15523101Sstever@eecs.umich.edu
15533102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
15543102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
15553102Sstever@eecs.umich.edu# SimObject is required.
15563102Sstever@eecs.umich.edu# only one copy of a particular node
15573102Sstever@eecs.umich.educlass NullSimObject(object):
15583102Sstever@eecs.umich.edu    __metaclass__ = Singleton
15593102Sstever@eecs.umich.edu
15603102Sstever@eecs.umich.edu    def __call__(cls):
15613102Sstever@eecs.umich.edu        return cls
15623102Sstever@eecs.umich.edu
15633102Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
15643102Sstever@eecs.umich.edu        pass
15653102Sstever@eecs.umich.edu
15663102Sstever@eecs.umich.edu    def ini_str(self):
15673102Sstever@eecs.umich.edu        return 'Null'
15683102Sstever@eecs.umich.edu
15693102Sstever@eecs.umich.edu    def unproxy(self, base):
15703102Sstever@eecs.umich.edu        return self
15713102Sstever@eecs.umich.edu
15723102Sstever@eecs.umich.edu    def set_path(self, parent, name):
15733102Sstever@eecs.umich.edu        pass
15744762Snate@binkert.org
15753102Sstever@eecs.umich.edu    def __str__(self):
15763102Sstever@eecs.umich.edu        return 'Null'
15773102Sstever@eecs.umich.edu
157810380SAndrew.Bardsley@arm.com    def config_value(self):
157910380SAndrew.Bardsley@arm.com        return None
158010380SAndrew.Bardsley@arm.com
15814762Snate@binkert.org    def getValue(self):
15824762Snate@binkert.org        return None
15834762Snate@binkert.org
15843102Sstever@eecs.umich.edu# The only instance you'll ever need...
15853102Sstever@eecs.umich.eduNULL = NullSimObject()
15863102Sstever@eecs.umich.edu
15873102Sstever@eecs.umich.edudef isNullPointer(value):
15883102Sstever@eecs.umich.edu    return isinstance(value, NullSimObject)
15893102Sstever@eecs.umich.edu
15903101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
15913101Sstever@eecs.umich.eduMaxAddr = Addr.max
15923101Sstever@eecs.umich.eduMaxTick = Tick.max
15933101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
15943101Sstever@eecs.umich.edu
15953101Sstever@eecs.umich.edu
15963101Sstever@eecs.umich.edu#####################################################################
15973101Sstever@eecs.umich.edu#
15983101Sstever@eecs.umich.edu# Port objects
15993101Sstever@eecs.umich.edu#
16003101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
16013101Sstever@eecs.umich.edu#
16023101Sstever@eecs.umich.edu#####################################################################
16033101Sstever@eecs.umich.edu
16043101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
16053101Sstever@eecs.umich.edu# particular SimObject.
16063101Sstever@eecs.umich.educlass PortRef(object):
16078839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
16083105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
16093101Sstever@eecs.umich.edu        self.simobj = simobj
16103101Sstever@eecs.umich.edu        self.name = name
16118839Sandreas.hansson@arm.com        self.role = role
16123101Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
16133101Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
16143105Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
16153101Sstever@eecs.umich.edu
16163103Sstever@eecs.umich.edu    def __str__(self):
16173105Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
16183103Sstever@eecs.umich.edu
16198840Sandreas.hansson@arm.com    def __len__(self):
16208840Sandreas.hansson@arm.com        # Return the number of connected ports, i.e. 0 is we have no
16218840Sandreas.hansson@arm.com        # peer and 1 if we do.
16228840Sandreas.hansson@arm.com        return int(self.peer != None)
16238840Sandreas.hansson@arm.com
16243105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
16253105Sstever@eecs.umich.edu    def ini_str(self):
16263105Sstever@eecs.umich.edu        return str(self.peer)
16273105Sstever@eecs.umich.edu
16289017Sandreas.hansson@arm.com    # for config.json
16299017Sandreas.hansson@arm.com    def get_config_as_dict(self):
16309017Sandreas.hansson@arm.com        return {'role' : self.role, 'peer' : str(self.peer)}
16319017Sandreas.hansson@arm.com
16323105Sstever@eecs.umich.edu    def __getattr__(self, attr):
16333105Sstever@eecs.umich.edu        if attr == 'peerObj':
16343105Sstever@eecs.umich.edu            # shorthand for proxies
16353105Sstever@eecs.umich.edu            return self.peer.simobj
16363105Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
16373105Sstever@eecs.umich.edu              (self.__class__.__name__, attr)
16383105Sstever@eecs.umich.edu
16393105Sstever@eecs.umich.edu    # Full connection is symmetric (both ways).  Called via
16403105Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
16413109Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
16423105Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
16433105Sstever@eecs.umich.edu    def connect(self, other):
16443105Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
16453105Sstever@eecs.umich.edu            # reference to plain VectorPort is implicit append
16463105Sstever@eecs.umich.edu            other = other._get_next()
16473105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
16489014Sandreas.hansson@arm.com            fatal("Port %s is already connected to %s, cannot connect %s\n",
16499014Sandreas.hansson@arm.com                  self, self.peer, other);
16503101Sstever@eecs.umich.edu        self.peer = other
16513109Sstever@eecs.umich.edu        if proxy.isproxy(other):
16523109Sstever@eecs.umich.edu            other.set_param_desc(PortParamDesc())
16533109Sstever@eecs.umich.edu        elif isinstance(other, PortRef):
16543109Sstever@eecs.umich.edu            if other.peer is not self:
16553109Sstever@eecs.umich.edu                other.connect(self)
16563109Sstever@eecs.umich.edu        else:
16573109Sstever@eecs.umich.edu            raise TypeError, \
16583109Sstever@eecs.umich.edu                  "assigning non-port reference '%s' to port '%s'" \
16593109Sstever@eecs.umich.edu                  % (other, self)
16603101Sstever@eecs.umich.edu
166110355SGeoffrey.Blake@arm.com    # Allow a master/slave port pair to be spliced between
166210355SGeoffrey.Blake@arm.com    # a port and its connected peer. Useful operation for connecting
166310355SGeoffrey.Blake@arm.com    # instrumentation structures into a system when it is necessary
166410355SGeoffrey.Blake@arm.com    # to connect the instrumentation after the full system has been
166510355SGeoffrey.Blake@arm.com    # constructed.
166610355SGeoffrey.Blake@arm.com    def splice(self, new_master_peer, new_slave_peer):
166710355SGeoffrey.Blake@arm.com        if self.peer and not proxy.isproxy(self.peer):
166810355SGeoffrey.Blake@arm.com            if isinstance(new_master_peer, PortRef) and \
166910355SGeoffrey.Blake@arm.com               isinstance(new_slave_peer, PortRef):
167010355SGeoffrey.Blake@arm.com                 old_peer = self.peer
167110355SGeoffrey.Blake@arm.com                 if self.role == 'SLAVE':
167210355SGeoffrey.Blake@arm.com                     self.peer = new_master_peer
167310355SGeoffrey.Blake@arm.com                     old_peer.peer = new_slave_peer
167410355SGeoffrey.Blake@arm.com                     new_master_peer.connect(self)
167510355SGeoffrey.Blake@arm.com                     new_slave_peer.connect(old_peer)
167610355SGeoffrey.Blake@arm.com                 elif self.role == 'MASTER':
167710355SGeoffrey.Blake@arm.com                     self.peer = new_slave_peer
167810355SGeoffrey.Blake@arm.com                     old_peer.peer = new_master_peer
167910355SGeoffrey.Blake@arm.com                     new_slave_peer.connect(self)
168010355SGeoffrey.Blake@arm.com                     new_master_peer.connect(old_peer)
168110355SGeoffrey.Blake@arm.com                 else:
168210355SGeoffrey.Blake@arm.com                     panic("Port %s has unknown role, "+\
168310355SGeoffrey.Blake@arm.com                           "cannot splice in new peers\n", self)
168410355SGeoffrey.Blake@arm.com            else:
168510355SGeoffrey.Blake@arm.com                raise TypeError, \
168610355SGeoffrey.Blake@arm.com                      "Splicing non-port references '%s','%s' to port '%s'"\
168710355SGeoffrey.Blake@arm.com                      % (new_peer, peers_new_peer, self)
168810355SGeoffrey.Blake@arm.com        else:
168910355SGeoffrey.Blake@arm.com            fatal("Port %s not connected, cannot splice in new peers\n", self)
169010355SGeoffrey.Blake@arm.com
16913105Sstever@eecs.umich.edu    def clone(self, simobj, memo):
16923105Sstever@eecs.umich.edu        if memo.has_key(self):
16933105Sstever@eecs.umich.edu            return memo[self]
16943101Sstever@eecs.umich.edu        newRef = copy.copy(self)
16953105Sstever@eecs.umich.edu        memo[self] = newRef
16963105Sstever@eecs.umich.edu        newRef.simobj = simobj
16973101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
16983105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
16993179Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
17003105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
17013105Sstever@eecs.umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
17023101Sstever@eecs.umich.edu        return newRef
17033101Sstever@eecs.umich.edu
17043105Sstever@eecs.umich.edu    def unproxy(self, simobj):
17053105Sstever@eecs.umich.edu        assert(simobj is self.simobj)
17063105Sstever@eecs.umich.edu        if proxy.isproxy(self.peer):
17073105Sstever@eecs.umich.edu            try:
17083105Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
17093105Sstever@eecs.umich.edu            except:
17103105Sstever@eecs.umich.edu                print "Error in unproxying port '%s' of %s" % \
17113105Sstever@eecs.umich.edu                      (self.name, self.simobj.path())
17123105Sstever@eecs.umich.edu                raise
17133105Sstever@eecs.umich.edu            self.connect(realPeer)
17143105Sstever@eecs.umich.edu
17153101Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
17163101Sstever@eecs.umich.edu    def ccConnect(self):
17178597Ssteve.reinhardt@amd.com        from m5.internal.pyobject import connectPorts
17184762Snate@binkert.org
17198839Sandreas.hansson@arm.com        if self.role == 'SLAVE':
17208839Sandreas.hansson@arm.com            # do nothing and let the master take care of it
17218839Sandreas.hansson@arm.com            return
17228839Sandreas.hansson@arm.com
17233101Sstever@eecs.umich.edu        if self.ccConnected: # already done this
17243101Sstever@eecs.umich.edu            return
17253101Sstever@eecs.umich.edu        peer = self.peer
17265578SSteve.Reinhardt@amd.com        if not self.peer: # nothing to connect to
17275578SSteve.Reinhardt@amd.com            return
17288839Sandreas.hansson@arm.com
17298839Sandreas.hansson@arm.com        # check that we connect a master to a slave
17308839Sandreas.hansson@arm.com        if self.role == peer.role:
17318839Sandreas.hansson@arm.com            raise TypeError, \
17328839Sandreas.hansson@arm.com                "cannot connect '%s' and '%s' due to identical role '%s'" \
17338839Sandreas.hansson@arm.com                % (peer, self, self.role)
17348839Sandreas.hansson@arm.com
17357526Ssteve.reinhardt@amd.com        try:
17368839Sandreas.hansson@arm.com            # self is always the master and peer the slave
17377526Ssteve.reinhardt@amd.com            connectPorts(self.simobj.getCCObject(), self.name, self.index,
17387526Ssteve.reinhardt@amd.com                         peer.simobj.getCCObject(), peer.name, peer.index)
17397526Ssteve.reinhardt@amd.com        except:
17407526Ssteve.reinhardt@amd.com            print "Error connecting port %s.%s to %s.%s" % \
17417526Ssteve.reinhardt@amd.com                  (self.simobj.path(), self.name,
17427526Ssteve.reinhardt@amd.com                   peer.simobj.path(), peer.name)
17437526Ssteve.reinhardt@amd.com            raise
17443101Sstever@eecs.umich.edu        self.ccConnected = True
17453101Sstever@eecs.umich.edu        peer.ccConnected = True
17463101Sstever@eecs.umich.edu
17473105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
17483105Sstever@eecs.umich.edu# PortRef, but has an index.
17493105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
17508839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role, index):
17518839Sandreas.hansson@arm.com        PortRef.__init__(self, simobj, name, role)
17523105Sstever@eecs.umich.edu        self.index = index
17533105Sstever@eecs.umich.edu
17543105Sstever@eecs.umich.edu    def __str__(self):
17553105Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
17563105Sstever@eecs.umich.edu
17573105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
17583105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
17593105Sstever@eecs.umich.educlass VectorPortRef(object):
17608839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
17613105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
17623105Sstever@eecs.umich.edu        self.simobj = simobj
17633105Sstever@eecs.umich.edu        self.name = name
17648839Sandreas.hansson@arm.com        self.role = role
17653105Sstever@eecs.umich.edu        self.elements = []
17663105Sstever@eecs.umich.edu
17673109Sstever@eecs.umich.edu    def __str__(self):
17683109Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
17693109Sstever@eecs.umich.edu
17708840Sandreas.hansson@arm.com    def __len__(self):
17718840Sandreas.hansson@arm.com        # Return the number of connected peers, corresponding the the
17728840Sandreas.hansson@arm.com        # length of the elements.
17738840Sandreas.hansson@arm.com        return len(self.elements)
17748840Sandreas.hansson@arm.com
17753105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
17763105Sstever@eecs.umich.edu    def ini_str(self):
17773105Sstever@eecs.umich.edu        return ' '.join([el.ini_str() for el in self.elements])
17783105Sstever@eecs.umich.edu
17799017Sandreas.hansson@arm.com    # for config.json
17809017Sandreas.hansson@arm.com    def get_config_as_dict(self):
17819017Sandreas.hansson@arm.com        return {'role' : self.role,
17829017Sandreas.hansson@arm.com                'peer' : [el.ini_str() for el in self.elements]}
17839017Sandreas.hansson@arm.com
17843105Sstever@eecs.umich.edu    def __getitem__(self, key):
17853105Sstever@eecs.umich.edu        if not isinstance(key, int):
17863105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
17873105Sstever@eecs.umich.edu        if key >= len(self.elements):
17883105Sstever@eecs.umich.edu            # need to extend list
17898839Sandreas.hansson@arm.com            ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
17903105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
17913105Sstever@eecs.umich.edu            self.elements.extend(ext)
17923105Sstever@eecs.umich.edu        return self.elements[key]
17933105Sstever@eecs.umich.edu
17943105Sstever@eecs.umich.edu    def _get_next(self):
17953105Sstever@eecs.umich.edu        return self[len(self.elements)]
17963105Sstever@eecs.umich.edu
17973105Sstever@eecs.umich.edu    def __setitem__(self, key, value):
17983105Sstever@eecs.umich.edu        if not isinstance(key, int):
17993105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
18003105Sstever@eecs.umich.edu        self[key].connect(value)
18013105Sstever@eecs.umich.edu
18023105Sstever@eecs.umich.edu    def connect(self, other):
18033109Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
18043109Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
18053109Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
18063109Sstever@eecs.umich.edu            # or if it should replace the current vector.
18073109Sstever@eecs.umich.edu            for ref in other:
18083109Sstever@eecs.umich.edu                self._get_next().connect(ref)
18093109Sstever@eecs.umich.edu        else:
18103109Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
18113109Sstever@eecs.umich.edu            self._get_next().connect(other)
18123109Sstever@eecs.umich.edu
18133109Sstever@eecs.umich.edu    def clone(self, simobj, memo):
18143109Sstever@eecs.umich.edu        if memo.has_key(self):
18153109Sstever@eecs.umich.edu            return memo[self]
18163109Sstever@eecs.umich.edu        newRef = copy.copy(self)
18173109Sstever@eecs.umich.edu        memo[self] = newRef
18183109Sstever@eecs.umich.edu        newRef.simobj = simobj
18193109Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
18203109Sstever@eecs.umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
18213109Sstever@eecs.umich.edu        return newRef
18223105Sstever@eecs.umich.edu
18233105Sstever@eecs.umich.edu    def unproxy(self, simobj):
18243105Sstever@eecs.umich.edu        [el.unproxy(simobj) for el in self.elements]
18253105Sstever@eecs.umich.edu
18263105Sstever@eecs.umich.edu    def ccConnect(self):
18273105Sstever@eecs.umich.edu        [el.ccConnect() for el in self.elements]
18283105Sstever@eecs.umich.edu
18293101Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
18303101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a
18313101Sstever@eecs.umich.edu# SimObject instance.  The latter are represented by PortRef objects.
18323101Sstever@eecs.umich.educlass Port(object):
18333101Sstever@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
18343101Sstever@eecs.umich.edu    # given name
18353105Sstever@eecs.umich.edu    def makeRef(self, simobj):
18368839Sandreas.hansson@arm.com        return PortRef(simobj, self.name, self.role)
18373101Sstever@eecs.umich.edu
18383101Sstever@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
18393101Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
18403105Sstever@eecs.umich.edu    def connect(self, simobj, ref):
18413105Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
18423101Sstever@eecs.umich.edu
18438840Sandreas.hansson@arm.com    # No need for any pre-declarations at the moment as we merely rely
18448840Sandreas.hansson@arm.com    # on an unsigned int.
18458840Sandreas.hansson@arm.com    def cxx_predecls(self, code):
18468840Sandreas.hansson@arm.com        pass
18478840Sandreas.hansson@arm.com
18488840Sandreas.hansson@arm.com    # Declare an unsigned int with the same name as the port, that
18498840Sandreas.hansson@arm.com    # will eventually hold the number of connected ports (and thus the
18508840Sandreas.hansson@arm.com    # number of elements for a VectorPort).
18518840Sandreas.hansson@arm.com    def cxx_decl(self, code):
18528840Sandreas.hansson@arm.com        code('unsigned int port_${{self.name}}_connection_count;')
18538840Sandreas.hansson@arm.com
18548839Sandreas.hansson@arm.comclass MasterPort(Port):
18558839Sandreas.hansson@arm.com    # MasterPort("description")
18568839Sandreas.hansson@arm.com    def __init__(self, *args):
18578839Sandreas.hansson@arm.com        if len(args) == 1:
18588839Sandreas.hansson@arm.com            self.desc = args[0]
18598839Sandreas.hansson@arm.com            self.role = 'MASTER'
18608839Sandreas.hansson@arm.com        else:
18618839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
18628839Sandreas.hansson@arm.com
18638839Sandreas.hansson@arm.comclass SlavePort(Port):
18648839Sandreas.hansson@arm.com    # SlavePort("description")
18658839Sandreas.hansson@arm.com    def __init__(self, *args):
18668839Sandreas.hansson@arm.com        if len(args) == 1:
18678839Sandreas.hansson@arm.com            self.desc = args[0]
18688839Sandreas.hansson@arm.com            self.role = 'SLAVE'
18698839Sandreas.hansson@arm.com        else:
18708839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
18718839Sandreas.hansson@arm.com
18723101Sstever@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
187310405Sandreas.hansson@arm.com# of connections (e.g., as on a XBar).
18743101Sstever@eecs.umich.educlass VectorPort(Port):
18753105Sstever@eecs.umich.edu    def __init__(self, *args):
18763101Sstever@eecs.umich.edu        self.isVec = True
18773101Sstever@eecs.umich.edu
18783105Sstever@eecs.umich.edu    def makeRef(self, simobj):
18798839Sandreas.hansson@arm.com        return VectorPortRef(simobj, self.name, self.role)
18808839Sandreas.hansson@arm.com
18818839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort):
18828839Sandreas.hansson@arm.com    # VectorMasterPort("description")
18838839Sandreas.hansson@arm.com    def __init__(self, *args):
18848839Sandreas.hansson@arm.com        if len(args) == 1:
18858839Sandreas.hansson@arm.com            self.desc = args[0]
18868839Sandreas.hansson@arm.com            self.role = 'MASTER'
18878839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
18888839Sandreas.hansson@arm.com        else:
18898839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
18908839Sandreas.hansson@arm.com
18918839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort):
18928839Sandreas.hansson@arm.com    # VectorSlavePort("description")
18938839Sandreas.hansson@arm.com    def __init__(self, *args):
18948839Sandreas.hansson@arm.com        if len(args) == 1:
18958839Sandreas.hansson@arm.com            self.desc = args[0]
18968839Sandreas.hansson@arm.com            self.role = 'SLAVE'
18978839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
18988839Sandreas.hansson@arm.com        else:
18998839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
19003105Sstever@eecs.umich.edu
19013109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
19023109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
19033109Sstever@eecs.umich.edu# make sense.
19043109Sstever@eecs.umich.educlass PortParamDesc(object):
19053109Sstever@eecs.umich.edu    __metaclass__ = Singleton
19063109Sstever@eecs.umich.edu
19073109Sstever@eecs.umich.edu    ptype_str = 'Port'
19083109Sstever@eecs.umich.edu    ptype = Port
19093105Sstever@eecs.umich.edu
19106654Snate@binkert.orgbaseEnums = allEnums.copy()
19116654Snate@binkert.orgbaseParams = allParams.copy()
19126654Snate@binkert.org
19136654Snate@binkert.orgdef clear():
19146654Snate@binkert.org    global allEnums, allParams
19156654Snate@binkert.org
19166654Snate@binkert.org    allEnums = baseEnums.copy()
19176654Snate@binkert.org    allParams = baseParams.copy()
19186654Snate@binkert.org
19193101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam',
19203101Sstever@eecs.umich.edu           'Enum', 'Bool', 'String', 'Float',
19213101Sstever@eecs.umich.edu           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
19223101Sstever@eecs.umich.edu           'Int32', 'UInt32', 'Int64', 'UInt64',
19233101Sstever@eecs.umich.edu           'Counter', 'Addr', 'Tick', 'Percent',
19243101Sstever@eecs.umich.edu           'TcpPort', 'UdpPort', 'EthernetAddr',
19257777Sgblack@eecs.umich.edu           'IpAddress', 'IpNetmask', 'IpWithPort',
19263101Sstever@eecs.umich.edu           'MemorySize', 'MemorySize32',
19279827Sakash.bagdia@arm.com           'Latency', 'Frequency', 'Clock', 'Voltage',
19283101Sstever@eecs.umich.edu           'NetworkBandwidth', 'MemoryBandwidth',
19299232Sandreas.hansson@arm.com           'AddrRange',
19303101Sstever@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
19313885Sbinkertn@umich.edu           'Time',
19323102Sstever@eecs.umich.edu           'NextEthernetAddr', 'NULL',
19338839Sandreas.hansson@arm.com           'MasterPort', 'SlavePort',
19348839Sandreas.hansson@arm.com           'VectorMasterPort', 'VectorSlavePort']
19356654Snate@binkert.org
19366654Snate@binkert.orgimport SimObject
1937