params.py revision 11228
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
12310458Sandreas.hansson@arm.com    # Prerequisites for .ini parsing with cxx_ini_parse
12410458Sandreas.hansson@arm.com    @classmethod
12510458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
12610458Sandreas.hansson@arm.com        pass
12710458Sandreas.hansson@arm.com
12810458Sandreas.hansson@arm.com    # parse a .ini file entry for this param from string expression
12910458Sandreas.hansson@arm.com    # src into lvalue dest (of the param's C++ type)
13010458Sandreas.hansson@arm.com    @classmethod
13110458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
13210458Sandreas.hansson@arm.com        code('// Unhandled param type: %s' % cls.__name__)
13310458Sandreas.hansson@arm.com        code('%s false;' % ret)
13410458Sandreas.hansson@arm.com
1353101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
1363101Sstever@eecs.umich.edu    # if they're really proxies or not
1373101Sstever@eecs.umich.edu    def unproxy(self, base):
1383101Sstever@eecs.umich.edu        return self
1393101Sstever@eecs.umich.edu
14010267SGeoffrey.Blake@arm.com    # Produce a human readable version of the stored value
14110267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
14210267SGeoffrey.Blake@arm.com        return str(value)
14310267SGeoffrey.Blake@arm.com
1443101Sstever@eecs.umich.edu# Regular parameter description.
1453101Sstever@eecs.umich.educlass ParamDesc(object):
1463101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1473101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1483101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1493101Sstever@eecs.umich.edu        if ptype != None:
1503101Sstever@eecs.umich.edu            self.ptype = ptype
1513101Sstever@eecs.umich.edu
1523101Sstever@eecs.umich.edu        if args:
1533101Sstever@eecs.umich.edu            if len(args) == 1:
1543101Sstever@eecs.umich.edu                self.desc = args[0]
1553101Sstever@eecs.umich.edu            elif len(args) == 2:
1563101Sstever@eecs.umich.edu                self.default = args[0]
1573101Sstever@eecs.umich.edu                self.desc = args[1]
1583101Sstever@eecs.umich.edu            else:
1593101Sstever@eecs.umich.edu                raise TypeError, 'too many arguments'
1603101Sstever@eecs.umich.edu
1613101Sstever@eecs.umich.edu        if kwargs.has_key('desc'):
1623101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1633101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1643101Sstever@eecs.umich.edu            del kwargs['desc']
1653101Sstever@eecs.umich.edu
1663101Sstever@eecs.umich.edu        if kwargs.has_key('default'):
1673101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1683101Sstever@eecs.umich.edu            self.default = kwargs['default']
1693101Sstever@eecs.umich.edu            del kwargs['default']
1703101Sstever@eecs.umich.edu
1713101Sstever@eecs.umich.edu        if kwargs:
1723101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1733101Sstever@eecs.umich.edu
1743101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
1753101Sstever@eecs.umich.edu            raise TypeError, 'desc attribute missing'
1763101Sstever@eecs.umich.edu
1773101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1783101Sstever@eecs.umich.edu        if attr == 'ptype':
1795033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1806656Snate@binkert.org            assert isSimObjectClass(ptype)
1815033Smilesck@eecs.umich.edu            self.ptype = ptype
1825033Smilesck@eecs.umich.edu            return ptype
1835033Smilesck@eecs.umich.edu
1843101Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
1853101Sstever@eecs.umich.edu              (type(self).__name__, attr)
1863101Sstever@eecs.umich.edu
18710267SGeoffrey.Blake@arm.com    def example_str(self):
18810267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "ex_str"):
18910267SGeoffrey.Blake@arm.com            return self.ptype.ex_str
19010267SGeoffrey.Blake@arm.com        else:
19110267SGeoffrey.Blake@arm.com            return self.ptype_str
19210267SGeoffrey.Blake@arm.com
19310267SGeoffrey.Blake@arm.com    # Is the param available to be exposed on the command line
19410267SGeoffrey.Blake@arm.com    def isCmdLineSettable(self):
19510267SGeoffrey.Blake@arm.com        if hasattr(self.ptype, "cmd_line_settable"):
19610267SGeoffrey.Blake@arm.com            return self.ptype.cmd_line_settable
19710267SGeoffrey.Blake@arm.com        else:
19810267SGeoffrey.Blake@arm.com            return False
19910267SGeoffrey.Blake@arm.com
2003101Sstever@eecs.umich.edu    def convert(self, value):
2013101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
2023101Sstever@eecs.umich.edu            value.set_param_desc(self)
2033101Sstever@eecs.umich.edu            return value
2043101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
2053101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
2063101Sstever@eecs.umich.edu            # we're just assigning a null pointer
2073101Sstever@eecs.umich.edu            return value
2083101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
2093101Sstever@eecs.umich.edu            return value
2103102Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
2113101Sstever@eecs.umich.edu            return value
2123101Sstever@eecs.umich.edu        return self.ptype(value)
2133101Sstever@eecs.umich.edu
21410267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
21510267SGeoffrey.Blake@arm.com        if isinstance(value, proxy.BaseProxy):
21610267SGeoffrey.Blake@arm.com           return str(value)
21710267SGeoffrey.Blake@arm.com        if isNullPointer(value):
21810267SGeoffrey.Blake@arm.com           return NULL
21910267SGeoffrey.Blake@arm.com        return self.ptype(value).pretty_print(value)
22010267SGeoffrey.Blake@arm.com
2217673Snate@binkert.org    def cxx_predecls(self, code):
2228607Sgblack@eecs.umich.edu        code('#include <cstddef>')
2237673Snate@binkert.org        self.ptype.cxx_predecls(code)
2243101Sstever@eecs.umich.edu
2257673Snate@binkert.org    def swig_predecls(self, code):
2267673Snate@binkert.org        self.ptype.swig_predecls(code)
2273101Sstever@eecs.umich.edu
2287673Snate@binkert.org    def cxx_decl(self, code):
2297673Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
2303101Sstever@eecs.umich.edu
2313101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
2323101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
2333101Sstever@eecs.umich.edu# single value.
2343101Sstever@eecs.umich.edu
2353101Sstever@eecs.umich.educlass VectorParamValue(list):
2365033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
2375475Snate@binkert.org    def __setattr__(self, attr, value):
2385475Snate@binkert.org        raise AttributeError, \
2395475Snate@binkert.org              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
2405475Snate@binkert.org
24110380SAndrew.Bardsley@arm.com    def config_value(self):
24210380SAndrew.Bardsley@arm.com        return [v.config_value() for v in self]
24310380SAndrew.Bardsley@arm.com
2443101Sstever@eecs.umich.edu    def ini_str(self):
2453101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
2463101Sstever@eecs.umich.edu
2474762Snate@binkert.org    def getValue(self):
2484762Snate@binkert.org        return [ v.getValue() for v in self ]
2494762Snate@binkert.org
2503101Sstever@eecs.umich.edu    def unproxy(self, base):
2518460SAli.Saidi@ARM.com        if len(self) == 1 and isinstance(self[0], proxy.AllProxy):
2528459SAli.Saidi@ARM.com            return self[0].unproxy(base)
2538459SAli.Saidi@ARM.com        else:
2548459SAli.Saidi@ARM.com             return [v.unproxy(base) for v in self]
2553101Sstever@eecs.umich.edu
2567528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2577528Ssteve.reinhardt@amd.com    # support clone operation
2587528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2597528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2607528Ssteve.reinhardt@amd.com
2617528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
2623101Sstever@eecs.umich.edu        for v in self:
2637528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2647528Ssteve.reinhardt@amd.com
2657528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2667528Ssteve.reinhardt@amd.com        if len(self) == 1:
2677528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2687528Ssteve.reinhardt@amd.com        else:
2697528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2707528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2717528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2727528Ssteve.reinhardt@amd.com
2738321Ssteve.reinhardt@amd.com    def has_parent(self):
2748321Ssteve.reinhardt@amd.com        return reduce(lambda x,y: x and y, [v.has_parent() for v in self])
2757528Ssteve.reinhardt@amd.com
2767528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2777528Ssteve.reinhardt@amd.com    def get_name(self):
2787528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2797528Ssteve.reinhardt@amd.com
2807528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2817528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2827528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2837528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2847528Ssteve.reinhardt@amd.com    def descendants(self):
2857528Ssteve.reinhardt@amd.com        for v in self:
2867528Ssteve.reinhardt@amd.com            for obj in v.descendants():
2877528Ssteve.reinhardt@amd.com                yield obj
2883101Sstever@eecs.umich.edu
2898664SAli.Saidi@ARM.com    def get_config_as_dict(self):
2908664SAli.Saidi@ARM.com        a = []
2918664SAli.Saidi@ARM.com        for v in self:
2928664SAli.Saidi@ARM.com            a.append(v.get_config_as_dict())
2938664SAli.Saidi@ARM.com        return a
2948664SAli.Saidi@ARM.com
2959953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
2969953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
2979953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
2989953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
2999953Sgeoffrey.blake@arm.com    # configuration scripts.
3009953Sgeoffrey.blake@arm.com    def __setitem__(self, key, value):
3019953Sgeoffrey.blake@arm.com        val = self[key]
3029953Sgeoffrey.blake@arm.com        if value.has_parent():
3039953Sgeoffrey.blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
3049953Sgeoffrey.blake@arm.com                 " that is being overwritten by a SimObjectVector")
3059953Sgeoffrey.blake@arm.com        value.set_parent(val.get_parent(), val._name)
3069953Sgeoffrey.blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
3079953Sgeoffrey.blake@arm.com
30810267SGeoffrey.Blake@arm.com    # Enumerate the params of each member of the SimObject vector. Creates
30910267SGeoffrey.Blake@arm.com    # strings that will allow indexing into the vector by the python code and
31010267SGeoffrey.Blake@arm.com    # allow it to be specified on the command line.
31110267SGeoffrey.Blake@arm.com    def enumerateParams(self, flags_dict = {},
31210267SGeoffrey.Blake@arm.com                        cmd_line_str = "",
31310267SGeoffrey.Blake@arm.com                        access_str = ""):
31410267SGeoffrey.Blake@arm.com        if hasattr(self, "_paramEnumed"):
31510267SGeoffrey.Blake@arm.com            print "Cycle detected enumerating params at %s?!" % (cmd_line_str)
31610267SGeoffrey.Blake@arm.com        else:
31710267SGeoffrey.Blake@arm.com            x = 0
31810267SGeoffrey.Blake@arm.com            for vals in self:
31910267SGeoffrey.Blake@arm.com                # Each entry in the SimObjectVector should be an
32010267SGeoffrey.Blake@arm.com                # instance of a SimObject
32110267SGeoffrey.Blake@arm.com                flags_dict = vals.enumerateParams(flags_dict,
32210267SGeoffrey.Blake@arm.com                                                  cmd_line_str + "%d." % x,
32310267SGeoffrey.Blake@arm.com                                                  access_str + "[%d]." % x)
32410267SGeoffrey.Blake@arm.com                x = x + 1
32510267SGeoffrey.Blake@arm.com
32610267SGeoffrey.Blake@arm.com        return flags_dict
32710267SGeoffrey.Blake@arm.com
3283101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
3293101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
3303101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
3313101Sstever@eecs.umich.edu    def convert(self, value):
3323101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
3333101Sstever@eecs.umich.edu            # list: coerce each element into new list
3343101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
33510364SGeoffrey.Blake@arm.com        elif isinstance(value, str):
33610364SGeoffrey.Blake@arm.com            # If input is a csv string
33710364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
33810364SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
3393101Sstever@eecs.umich.edu        else:
3404762Snate@binkert.org            # singleton: coerce to a single-element list
3414762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
3424762Snate@binkert.org
3434762Snate@binkert.org        if isSimObjectSequence(tmp_list):
3447528Ssteve.reinhardt@amd.com            return SimObjectVector(tmp_list)
3454762Snate@binkert.org        else:
3464762Snate@binkert.org            return VectorParamValue(tmp_list)
3474762Snate@binkert.org
34810267SGeoffrey.Blake@arm.com    # Produce a human readable example string that describes
34910267SGeoffrey.Blake@arm.com    # how to set this vector parameter in the absence of a default
35010267SGeoffrey.Blake@arm.com    # value.
35110267SGeoffrey.Blake@arm.com    def example_str(self):
35210267SGeoffrey.Blake@arm.com        s = super(VectorParamDesc, self).example_str()
35310267SGeoffrey.Blake@arm.com        help_str = "[" + s + "," + s + ", ...]"
35410267SGeoffrey.Blake@arm.com        return help_str
35510267SGeoffrey.Blake@arm.com
35610267SGeoffrey.Blake@arm.com    # Produce a human readable representation of the value of this vector param.
35710267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
35810267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
35910267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ]
36010267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
36110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ]
36210267SGeoffrey.Blake@arm.com        else:
36310267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.pretty_print(self, value) ]
36410267SGeoffrey.Blake@arm.com
36510267SGeoffrey.Blake@arm.com        return tmp_list
36610267SGeoffrey.Blake@arm.com
36710267SGeoffrey.Blake@arm.com    # This is a helper function for the new config system
36810267SGeoffrey.Blake@arm.com    def __call__(self, value):
36910267SGeoffrey.Blake@arm.com        if isinstance(value, (list, tuple)):
37010267SGeoffrey.Blake@arm.com            # list: coerce each element into new list
37110267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
37210267SGeoffrey.Blake@arm.com        elif isinstance(value, str):
37310267SGeoffrey.Blake@arm.com            # If input is a csv string
37410364SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, v) \
37510364SGeoffrey.Blake@arm.com                         for v in value.strip('[').strip(']').split(',') ]
37610267SGeoffrey.Blake@arm.com        else:
37710267SGeoffrey.Blake@arm.com            # singleton: coerce to a single-element list
37810267SGeoffrey.Blake@arm.com            tmp_list = [ ParamDesc.convert(self, value) ]
37910267SGeoffrey.Blake@arm.com
38010267SGeoffrey.Blake@arm.com        return VectorParamValue(tmp_list)
38110267SGeoffrey.Blake@arm.com
3828596Ssteve.reinhardt@amd.com    def swig_module_name(self):
3838596Ssteve.reinhardt@amd.com        return "%s_vector" % self.ptype_str
3848596Ssteve.reinhardt@amd.com
3857673Snate@binkert.org    def swig_predecls(self, code):
3868596Ssteve.reinhardt@amd.com        code('%import "${{self.swig_module_name()}}.i"')
3874762Snate@binkert.org
3887673Snate@binkert.org    def swig_decl(self, code):
3898596Ssteve.reinhardt@amd.com        code('%module(package="m5.internal") ${{self.swig_module_name()}}')
3907675Snate@binkert.org        code('%{')
3917675Snate@binkert.org        self.ptype.cxx_predecls(code)
3927675Snate@binkert.org        code('%}')
3937675Snate@binkert.org        code()
3948656Sandreas.hansson@arm.com        # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
3958656Sandreas.hansson@arm.com        code('%include "std_container.i"')
3968656Sandreas.hansson@arm.com        code()
3977675Snate@binkert.org        self.ptype.swig_predecls(code)
3987675Snate@binkert.org        code()
3997673Snate@binkert.org        code('%include "std_vector.i"')
4007675Snate@binkert.org        code()
4017675Snate@binkert.org
4027675Snate@binkert.org        ptype = self.ptype_str
4037675Snate@binkert.org        cxx_type = self.ptype.cxx_type
4047675Snate@binkert.org
4057675Snate@binkert.org        code('%template(vector_$ptype) std::vector< $cxx_type >;')
4067675Snate@binkert.org
4077673Snate@binkert.org    def cxx_predecls(self, code):
4087673Snate@binkert.org        code('#include <vector>')
4097673Snate@binkert.org        self.ptype.cxx_predecls(code)
4103101Sstever@eecs.umich.edu
4117673Snate@binkert.org    def cxx_decl(self, code):
4127673Snate@binkert.org        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
4133101Sstever@eecs.umich.edu
4143101Sstever@eecs.umich.educlass ParamFactory(object):
4153101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
4163101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
4173101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
4183101Sstever@eecs.umich.edu
4193101Sstever@eecs.umich.edu    def __getattr__(self, attr):
4203101Sstever@eecs.umich.edu        if self.ptype_str:
4213101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
4223101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
4233101Sstever@eecs.umich.edu
4243101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
4253101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
4263101Sstever@eecs.umich.edu        ptype = None
4273101Sstever@eecs.umich.edu        try:
4285033Smilesck@eecs.umich.edu            ptype = allParams[self.ptype_str]
4295033Smilesck@eecs.umich.edu        except KeyError:
4303101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
4313101Sstever@eecs.umich.edu            # try to resolve it later
4323101Sstever@eecs.umich.edu            pass
4333101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
4343101Sstever@eecs.umich.edu
4353101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
4363101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
4373101Sstever@eecs.umich.edu
4383101Sstever@eecs.umich.edu#####################################################################
4393101Sstever@eecs.umich.edu#
4403101Sstever@eecs.umich.edu# Parameter Types
4413101Sstever@eecs.umich.edu#
4423101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
4433101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
4443101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
4453101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
4463101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
4473101Sstever@eecs.umich.edu# the __str__() conversion method).
4483101Sstever@eecs.umich.edu#
4493101Sstever@eecs.umich.edu#####################################################################
4503101Sstever@eecs.umich.edu
4513101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
4523101Sstever@eecs.umich.edu# built-in str class.
4533101Sstever@eecs.umich.educlass String(ParamValue,str):
4543101Sstever@eecs.umich.edu    cxx_type = 'std::string'
45510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
4567673Snate@binkert.org
4577673Snate@binkert.org    @classmethod
4587673Snate@binkert.org    def cxx_predecls(self, code):
4597673Snate@binkert.org        code('#include <string>')
4607673Snate@binkert.org
4617673Snate@binkert.org    @classmethod
4627673Snate@binkert.org    def swig_predecls(cls, code):
4637673Snate@binkert.org        code('%include "std_string.i"')
4644762Snate@binkert.org
46510267SGeoffrey.Blake@arm.com    def __call__(self, value):
46610267SGeoffrey.Blake@arm.com        self = value
46710267SGeoffrey.Blake@arm.com        return value
46810267SGeoffrey.Blake@arm.com
46910458Sandreas.hansson@arm.com    @classmethod
47010458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
47110458Sandreas.hansson@arm.com        code('%s = %s;' % (dest, src))
47210458Sandreas.hansson@arm.com        code('%s true;' % ret)
47310458Sandreas.hansson@arm.com
4744762Snate@binkert.org    def getValue(self):
4754762Snate@binkert.org        return self
4763101Sstever@eecs.umich.edu
4773101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
4783101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
4793101Sstever@eecs.umich.edu# a new Latency object.
4803101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
4813101Sstever@eecs.umich.edu    def __str__(self):
4823101Sstever@eecs.umich.edu        return str(self.value)
4833101Sstever@eecs.umich.edu
4843101Sstever@eecs.umich.edu    def __float__(self):
4853101Sstever@eecs.umich.edu        return float(self.value)
4863101Sstever@eecs.umich.edu
4873714Sstever@eecs.umich.edu    def __long__(self):
4883714Sstever@eecs.umich.edu        return long(self.value)
4893714Sstever@eecs.umich.edu
4903714Sstever@eecs.umich.edu    def __int__(self):
4913714Sstever@eecs.umich.edu        return int(self.value)
4923714Sstever@eecs.umich.edu
4933101Sstever@eecs.umich.edu    # hook for bounds checking
4943101Sstever@eecs.umich.edu    def _check(self):
4953101Sstever@eecs.umich.edu        return
4963101Sstever@eecs.umich.edu
4973101Sstever@eecs.umich.edu    def __mul__(self, other):
4983101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4993101Sstever@eecs.umich.edu        newobj.value *= other
5003101Sstever@eecs.umich.edu        newobj._check()
5013101Sstever@eecs.umich.edu        return newobj
5023101Sstever@eecs.umich.edu
5033101Sstever@eecs.umich.edu    __rmul__ = __mul__
5043101Sstever@eecs.umich.edu
5053101Sstever@eecs.umich.edu    def __div__(self, other):
5063101Sstever@eecs.umich.edu        newobj = self.__class__(self)
5073101Sstever@eecs.umich.edu        newobj.value /= other
5083101Sstever@eecs.umich.edu        newobj._check()
5093101Sstever@eecs.umich.edu        return newobj
5103101Sstever@eecs.umich.edu
5113101Sstever@eecs.umich.edu    def __sub__(self, other):
5123101Sstever@eecs.umich.edu        newobj = self.__class__(self)
5133101Sstever@eecs.umich.edu        newobj.value -= other
5143101Sstever@eecs.umich.edu        newobj._check()
5153101Sstever@eecs.umich.edu        return newobj
5163101Sstever@eecs.umich.edu
51710380SAndrew.Bardsley@arm.com    def config_value(self):
51810380SAndrew.Bardsley@arm.com        return self.value
51910380SAndrew.Bardsley@arm.com
52010458Sandreas.hansson@arm.com    @classmethod
52110458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
52210458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
52310458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
52410458Sandreas.hansson@arm.com        pass
52510458Sandreas.hansson@arm.com
52610458Sandreas.hansson@arm.com    # The default for parsing PODs from an .ini entry is to extract from an
52710458Sandreas.hansson@arm.com    # istringstream and let overloading choose the right type according to
52810458Sandreas.hansson@arm.com    # the dest type.
52910458Sandreas.hansson@arm.com    @classmethod
53010458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
53110458Sandreas.hansson@arm.com        code('%s to_number(%s, %s);' % (ret, src, dest))
53210458Sandreas.hansson@arm.com
5333101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
5345033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue):
5353101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5363101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
5373101Sstever@eecs.umich.edu
5383101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
5393101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
5403101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
5413101Sstever@eecs.umich.edu        if name == 'CheckedInt':
5423101Sstever@eecs.umich.edu            return
5433101Sstever@eecs.umich.edu
5443101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
5453101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
5463101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
5475822Ssaidi@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
5485822Ssaidi@eecs.umich.edu                      name);
5493101Sstever@eecs.umich.edu            if cls.unsigned:
5503101Sstever@eecs.umich.edu                cls.min = 0
5513101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
5523101Sstever@eecs.umich.edu            else:
5533101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
5543101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
5553101Sstever@eecs.umich.edu
5563101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
5573101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
5583101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
5593101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
5603101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue):
5613101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
56210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
5633101Sstever@eecs.umich.edu
5643101Sstever@eecs.umich.edu    def _check(self):
5653101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
5663101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
5673101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
5683101Sstever@eecs.umich.edu
5693101Sstever@eecs.umich.edu    def __init__(self, value):
5703101Sstever@eecs.umich.edu        if isinstance(value, str):
5713102Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
5723714Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
5733101Sstever@eecs.umich.edu            self.value = long(value)
5743714Sstever@eecs.umich.edu        else:
5753714Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to CheckedInt" \
5763714Sstever@eecs.umich.edu                  % type(value).__name__
5773101Sstever@eecs.umich.edu        self._check()
5783101Sstever@eecs.umich.edu
57910267SGeoffrey.Blake@arm.com    def __call__(self, value):
58010267SGeoffrey.Blake@arm.com        self.__init__(value)
58110267SGeoffrey.Blake@arm.com        return value
58210267SGeoffrey.Blake@arm.com
5837673Snate@binkert.org    @classmethod
5847673Snate@binkert.org    def cxx_predecls(cls, code):
5857673Snate@binkert.org        # most derived types require this, so we just do it here once
5867673Snate@binkert.org        code('#include "base/types.hh"')
5877673Snate@binkert.org
5887673Snate@binkert.org    @classmethod
5897673Snate@binkert.org    def swig_predecls(cls, code):
5907673Snate@binkert.org        # most derived types require this, so we just do it here once
5917673Snate@binkert.org        code('%import "stdint.i"')
5927673Snate@binkert.org        code('%import "base/types.hh"')
5937673Snate@binkert.org
5944762Snate@binkert.org    def getValue(self):
5954762Snate@binkert.org        return long(self.value)
5964762Snate@binkert.org
5973101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
5983101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
5993101Sstever@eecs.umich.edu
6003101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
6013101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
6023101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
6033101Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
6043101Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
6053101Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
6063101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
6073101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
6083101Sstever@eecs.umich.edu
6093101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
6103101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
6113101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6123101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
6133101Sstever@eecs.umich.edu
6143101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
6153101Sstever@eecs.umich.edu
6169184Sandreas.hansson@arm.comclass Cycles(CheckedInt):
6179184Sandreas.hansson@arm.com    cxx_type = 'Cycles'
6189184Sandreas.hansson@arm.com    size = 64
6199184Sandreas.hansson@arm.com    unsigned = True
6209184Sandreas.hansson@arm.com
6219184Sandreas.hansson@arm.com    def getValue(self):
6229184Sandreas.hansson@arm.com        from m5.internal.core import Cycles
6239184Sandreas.hansson@arm.com        return Cycles(self.value)
6249184Sandreas.hansson@arm.com
62510458Sandreas.hansson@arm.com    @classmethod
62610458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
62710458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
62810458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
62910458Sandreas.hansson@arm.com        pass
63010458Sandreas.hansson@arm.com
63110458Sandreas.hansson@arm.com    @classmethod
63210458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
63310458Sandreas.hansson@arm.com        code('uint64_t _temp;')
63410458Sandreas.hansson@arm.com        code('bool _ret = to_number(%s, _temp);' % src)
63510458Sandreas.hansson@arm.com        code('if (_ret)')
63610458Sandreas.hansson@arm.com        code('    %s = Cycles(_temp);' % dest)
63710458Sandreas.hansson@arm.com        code('%s _ret;' % ret)
63810458Sandreas.hansson@arm.com
6393101Sstever@eecs.umich.educlass Float(ParamValue, float):
6404446Sbinkertn@umich.edu    cxx_type = 'double'
64110668SGeoffrey.Blake@arm.com    cmd_line_settable = True
6423101Sstever@eecs.umich.edu
6435468Snate@binkert.org    def __init__(self, value):
64410267SGeoffrey.Blake@arm.com        if isinstance(value, (int, long, float, NumericParamValue, Float, str)):
6455468Snate@binkert.org            self.value = float(value)
6465468Snate@binkert.org        else:
6475468Snate@binkert.org            raise TypeError, "Can't convert object of type %s to Float" \
6485468Snate@binkert.org                  % type(value).__name__
6495468Snate@binkert.org
65010267SGeoffrey.Blake@arm.com    def __call__(self, value):
65110267SGeoffrey.Blake@arm.com        self.__init__(value)
65210267SGeoffrey.Blake@arm.com        return value
65310267SGeoffrey.Blake@arm.com
6544762Snate@binkert.org    def getValue(self):
6554762Snate@binkert.org        return float(self.value)
6564762Snate@binkert.org
65710380SAndrew.Bardsley@arm.com    def config_value(self):
65810380SAndrew.Bardsley@arm.com        return self
65910380SAndrew.Bardsley@arm.com
66010458Sandreas.hansson@arm.com    @classmethod
66110458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
66210458Sandreas.hansson@arm.com        code('#include <sstream>')
66310458Sandreas.hansson@arm.com
66410458Sandreas.hansson@arm.com    @classmethod
66510458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
66610458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
66710458Sandreas.hansson@arm.com
6683101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
6693101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
67010267SGeoffrey.Blake@arm.com    ex_str = '512MB'
6713101Sstever@eecs.umich.edu    size = 64
6723101Sstever@eecs.umich.edu    unsigned = True
6733101Sstever@eecs.umich.edu    def __init__(self, value):
6743101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
6753101Sstever@eecs.umich.edu            self.value = value.value
6763101Sstever@eecs.umich.edu        else:
6773102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
6783101Sstever@eecs.umich.edu        self._check()
6793101Sstever@eecs.umich.edu
6803101Sstever@eecs.umich.educlass MemorySize32(CheckedInt):
6814168Sbinkertn@umich.edu    cxx_type = 'uint32_t'
68210267SGeoffrey.Blake@arm.com    ex_str = '512MB'
6833101Sstever@eecs.umich.edu    size = 32
6843101Sstever@eecs.umich.edu    unsigned = True
6853101Sstever@eecs.umich.edu    def __init__(self, value):
6863101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
6873101Sstever@eecs.umich.edu            self.value = value.value
6883101Sstever@eecs.umich.edu        else:
6893102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
6903101Sstever@eecs.umich.edu        self._check()
6913101Sstever@eecs.umich.edu
6923101Sstever@eecs.umich.educlass Addr(CheckedInt):
6933101Sstever@eecs.umich.edu    cxx_type = 'Addr'
6943101Sstever@eecs.umich.edu    size = 64
6953101Sstever@eecs.umich.edu    unsigned = True
6963101Sstever@eecs.umich.edu    def __init__(self, value):
6973101Sstever@eecs.umich.edu        if isinstance(value, Addr):
6983101Sstever@eecs.umich.edu            self.value = value.value
6993101Sstever@eecs.umich.edu        else:
7003101Sstever@eecs.umich.edu            try:
70110317Smitch.hayenga@arm.com                # Often addresses are referred to with sizes. Ex: A device
70210317Smitch.hayenga@arm.com                # base address is at "512MB".  Use toMemorySize() to convert
70310317Smitch.hayenga@arm.com                # these into addresses. If the address is not specified with a
70410317Smitch.hayenga@arm.com                # "size", an exception will occur and numeric translation will
70510317Smitch.hayenga@arm.com                # proceed below.
7063102Sstever@eecs.umich.edu                self.value = convert.toMemorySize(value)
70710317Smitch.hayenga@arm.com            except (TypeError, ValueError):
70810317Smitch.hayenga@arm.com                # Convert number to string and use long() to do automatic
70910317Smitch.hayenga@arm.com                # base conversion (requires base=0 for auto-conversion)
71010317Smitch.hayenga@arm.com                self.value = long(str(value), base=0)
71110317Smitch.hayenga@arm.com
7123101Sstever@eecs.umich.edu        self._check()
7133584Ssaidi@eecs.umich.edu    def __add__(self, other):
7143584Ssaidi@eecs.umich.edu        if isinstance(other, Addr):
7153584Ssaidi@eecs.umich.edu            return self.value + other.value
7163584Ssaidi@eecs.umich.edu        else:
7173584Ssaidi@eecs.umich.edu            return self.value + other
71810267SGeoffrey.Blake@arm.com    def pretty_print(self, value):
71910267SGeoffrey.Blake@arm.com        try:
72010267SGeoffrey.Blake@arm.com            val = convert.toMemorySize(value)
72110267SGeoffrey.Blake@arm.com        except TypeError:
72210267SGeoffrey.Blake@arm.com            val = long(value)
72310267SGeoffrey.Blake@arm.com        return "0x%x" % long(val)
7243101Sstever@eecs.umich.edu
7259232Sandreas.hansson@arm.comclass AddrRange(ParamValue):
7269235Sandreas.hansson@arm.com    cxx_type = 'AddrRange'
7273101Sstever@eecs.umich.edu
7283101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
72910676Sandreas.hansson@arm.com        # Disable interleaving and hashing by default
7309411Sandreas.hansson@arm.com        self.intlvHighBit = 0
73110676Sandreas.hansson@arm.com        self.xorHighBit = 0
7329411Sandreas.hansson@arm.com        self.intlvBits = 0
7339411Sandreas.hansson@arm.com        self.intlvMatch = 0
7349411Sandreas.hansson@arm.com
7353101Sstever@eecs.umich.edu        def handle_kwargs(self, kwargs):
7369411Sandreas.hansson@arm.com            # An address range needs to have an upper limit, specified
7379411Sandreas.hansson@arm.com            # either explicitly with an end, or as an offset using the
7389411Sandreas.hansson@arm.com            # size keyword.
7393101Sstever@eecs.umich.edu            if 'end' in kwargs:
7409232Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
7413101Sstever@eecs.umich.edu            elif 'size' in kwargs:
7429232Sandreas.hansson@arm.com                self.end = self.start + Addr(kwargs.pop('size')) - 1
7433101Sstever@eecs.umich.edu            else:
7443101Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
7453101Sstever@eecs.umich.edu
7469411Sandreas.hansson@arm.com            # Now on to the optional bit
7479411Sandreas.hansson@arm.com            if 'intlvHighBit' in kwargs:
7489411Sandreas.hansson@arm.com                self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
74910676Sandreas.hansson@arm.com            if 'xorHighBit' in kwargs:
75010676Sandreas.hansson@arm.com                self.xorHighBit = int(kwargs.pop('xorHighBit'))
7519411Sandreas.hansson@arm.com            if 'intlvBits' in kwargs:
7529411Sandreas.hansson@arm.com                self.intlvBits = int(kwargs.pop('intlvBits'))
7539411Sandreas.hansson@arm.com            if 'intlvMatch' in kwargs:
7549411Sandreas.hansson@arm.com                self.intlvMatch = int(kwargs.pop('intlvMatch'))
7559411Sandreas.hansson@arm.com
7563101Sstever@eecs.umich.edu        if len(args) == 0:
7579232Sandreas.hansson@arm.com            self.start = Addr(kwargs.pop('start'))
7583101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
7593101Sstever@eecs.umich.edu
7603101Sstever@eecs.umich.edu        elif len(args) == 1:
7613101Sstever@eecs.umich.edu            if kwargs:
7629232Sandreas.hansson@arm.com                self.start = Addr(args[0])
7633101Sstever@eecs.umich.edu                handle_kwargs(self, kwargs)
7645219Ssaidi@eecs.umich.edu            elif isinstance(args[0], (list, tuple)):
7659232Sandreas.hansson@arm.com                self.start = Addr(args[0][0])
7669232Sandreas.hansson@arm.com                self.end = Addr(args[0][1])
7673101Sstever@eecs.umich.edu            else:
7689232Sandreas.hansson@arm.com                self.start = Addr(0)
7699232Sandreas.hansson@arm.com                self.end = Addr(args[0]) - 1
7703101Sstever@eecs.umich.edu
7713101Sstever@eecs.umich.edu        elif len(args) == 2:
7729232Sandreas.hansson@arm.com            self.start = Addr(args[0])
7739232Sandreas.hansson@arm.com            self.end = Addr(args[1])
7743101Sstever@eecs.umich.edu        else:
7753101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
7763101Sstever@eecs.umich.edu
7773101Sstever@eecs.umich.edu        if kwargs:
7789232Sandreas.hansson@arm.com            raise TypeError, "Too many keywords: %s" % kwargs.keys()
7793101Sstever@eecs.umich.edu
7803101Sstever@eecs.umich.edu    def __str__(self):
7819232Sandreas.hansson@arm.com        return '%s:%s' % (self.start, self.end)
7829232Sandreas.hansson@arm.com
7839232Sandreas.hansson@arm.com    def size(self):
7849411Sandreas.hansson@arm.com        # Divide the size by the size of the interleaving slice
7859411Sandreas.hansson@arm.com        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
7863101Sstever@eecs.umich.edu
7877673Snate@binkert.org    @classmethod
7887673Snate@binkert.org    def cxx_predecls(cls, code):
7899232Sandreas.hansson@arm.com        Addr.cxx_predecls(code)
7909235Sandreas.hansson@arm.com        code('#include "base/addr_range.hh"')
7917675Snate@binkert.org
7927675Snate@binkert.org    @classmethod
7937675Snate@binkert.org    def swig_predecls(cls, code):
7949232Sandreas.hansson@arm.com        Addr.swig_predecls(code)
7957673Snate@binkert.org
79610458Sandreas.hansson@arm.com    @classmethod
79710458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
79810458Sandreas.hansson@arm.com        code('#include <sstream>')
79910458Sandreas.hansson@arm.com
80010458Sandreas.hansson@arm.com    @classmethod
80110458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
80210458Sandreas.hansson@arm.com        code('uint64_t _start, _end;')
80310458Sandreas.hansson@arm.com        code('char _sep;')
80410458Sandreas.hansson@arm.com        code('std::istringstream _stream(${src});')
80510458Sandreas.hansson@arm.com        code('_stream >> _start;')
80610458Sandreas.hansson@arm.com        code('_stream.get(_sep);')
80710458Sandreas.hansson@arm.com        code('_stream >> _end;')
80810458Sandreas.hansson@arm.com        code('bool _ret = !_stream.fail() &&'
80910458Sandreas.hansson@arm.com            '_stream.eof() && _sep == \':\';')
81010458Sandreas.hansson@arm.com        code('if (_ret)')
81110458Sandreas.hansson@arm.com        code('   ${dest} = AddrRange(_start, _end);')
81210458Sandreas.hansson@arm.com        code('${ret} _ret;')
81310458Sandreas.hansson@arm.com
8144762Snate@binkert.org    def getValue(self):
8159235Sandreas.hansson@arm.com        # Go from the Python class to the wrapped C++ class generated
8169235Sandreas.hansson@arm.com        # by swig
8177675Snate@binkert.org        from m5.internal.range import AddrRange
8184762Snate@binkert.org
8199411Sandreas.hansson@arm.com        return AddrRange(long(self.start), long(self.end),
82010676Sandreas.hansson@arm.com                         int(self.intlvHighBit), int(self.xorHighBit),
82110676Sandreas.hansson@arm.com                         int(self.intlvBits), int(self.intlvMatch))
8223101Sstever@eecs.umich.edu
8233101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
8243101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and
8253101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
8263101Sstever@eecs.umich.educlass Bool(ParamValue):
8273101Sstever@eecs.umich.edu    cxx_type = 'bool'
82810267SGeoffrey.Blake@arm.com    cmd_line_settable = True
82910267SGeoffrey.Blake@arm.com
8303101Sstever@eecs.umich.edu    def __init__(self, value):
8313101Sstever@eecs.umich.edu        try:
8323102Sstever@eecs.umich.edu            self.value = convert.toBool(value)
8333101Sstever@eecs.umich.edu        except TypeError:
8343101Sstever@eecs.umich.edu            self.value = bool(value)
8353101Sstever@eecs.umich.edu
83610267SGeoffrey.Blake@arm.com    def __call__(self, value):
83710267SGeoffrey.Blake@arm.com        self.__init__(value)
83810267SGeoffrey.Blake@arm.com        return value
83910267SGeoffrey.Blake@arm.com
8404762Snate@binkert.org    def getValue(self):
8414762Snate@binkert.org        return bool(self.value)
8424762Snate@binkert.org
8433101Sstever@eecs.umich.edu    def __str__(self):
8443101Sstever@eecs.umich.edu        return str(self.value)
8453101Sstever@eecs.umich.edu
8468934SBrad.Beckmann@amd.com    # implement truth value testing for Bool parameters so that these params
8478934SBrad.Beckmann@amd.com    # evaluate correctly during the python configuration phase
8488934SBrad.Beckmann@amd.com    def __nonzero__(self):
8498934SBrad.Beckmann@amd.com        return bool(self.value)
8508934SBrad.Beckmann@amd.com
8513101Sstever@eecs.umich.edu    def ini_str(self):
8523101Sstever@eecs.umich.edu        if self.value:
8533101Sstever@eecs.umich.edu            return 'true'
8543101Sstever@eecs.umich.edu        return 'false'
8553101Sstever@eecs.umich.edu
85610380SAndrew.Bardsley@arm.com    def config_value(self):
85710380SAndrew.Bardsley@arm.com        return self.value
85810380SAndrew.Bardsley@arm.com
85910458Sandreas.hansson@arm.com    @classmethod
86010458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
86110458Sandreas.hansson@arm.com        # Assume that base/str.hh will be included anyway
86210458Sandreas.hansson@arm.com        # code('#include "base/str.hh"')
86310458Sandreas.hansson@arm.com        pass
86410458Sandreas.hansson@arm.com
86510458Sandreas.hansson@arm.com    @classmethod
86610458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
86710458Sandreas.hansson@arm.com        code('%s to_bool(%s, %s);' % (ret, src, dest))
86810458Sandreas.hansson@arm.com
8693101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
8703101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
8713101Sstever@eecs.umich.edu    bytes[5] += val
8723101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
8733101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
8743101Sstever@eecs.umich.edu        bytes[i] = rem
8753101Sstever@eecs.umich.edu        if val == 0:
8763101Sstever@eecs.umich.edu            break
8773101Sstever@eecs.umich.edu        bytes[i - 1] += val
8783101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
8793101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
8803101Sstever@eecs.umich.edu
8814380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
8824380Sbinkertn@umich.edudef NextEthernetAddr():
8834380Sbinkertn@umich.edu    global _NextEthernetAddr
8843101Sstever@eecs.umich.edu
8854380Sbinkertn@umich.edu    value = _NextEthernetAddr
8864380Sbinkertn@umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
8874380Sbinkertn@umich.edu    return value
8883101Sstever@eecs.umich.edu
8893101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
8903101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
89110267SGeoffrey.Blake@arm.com    ex_str = "00:90:00:00:00:01"
89210267SGeoffrey.Blake@arm.com    cmd_line_settable = True
8937673Snate@binkert.org
8947673Snate@binkert.org    @classmethod
8957673Snate@binkert.org    def cxx_predecls(cls, code):
8967673Snate@binkert.org        code('#include "base/inet.hh"')
8977673Snate@binkert.org
8987673Snate@binkert.org    @classmethod
8997673Snate@binkert.org    def swig_predecls(cls, code):
9007673Snate@binkert.org        code('%include "python/swig/inet.i"')
9017673Snate@binkert.org
9023101Sstever@eecs.umich.edu    def __init__(self, value):
9033101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
9043101Sstever@eecs.umich.edu            self.value = value
9053101Sstever@eecs.umich.edu            return
9063101Sstever@eecs.umich.edu
9073101Sstever@eecs.umich.edu        if not isinstance(value, str):
9083101Sstever@eecs.umich.edu            raise TypeError, "expected an ethernet address and didn't get one"
9093101Sstever@eecs.umich.edu
9103101Sstever@eecs.umich.edu        bytes = value.split(':')
9113101Sstever@eecs.umich.edu        if len(bytes) != 6:
9123101Sstever@eecs.umich.edu            raise TypeError, 'invalid ethernet address %s' % value
9133101Sstever@eecs.umich.edu
9143101Sstever@eecs.umich.edu        for byte in bytes:
9159941SGeoffrey.Blake@arm.com            if not 0 <= int(byte, base=16) <= 0xff:
9163101Sstever@eecs.umich.edu                raise TypeError, 'invalid ethernet address %s' % value
9173101Sstever@eecs.umich.edu
9183101Sstever@eecs.umich.edu        self.value = value
9193101Sstever@eecs.umich.edu
92010267SGeoffrey.Blake@arm.com    def __call__(self, value):
92110267SGeoffrey.Blake@arm.com        self.__init__(value)
92210267SGeoffrey.Blake@arm.com        return value
92310267SGeoffrey.Blake@arm.com
9243101Sstever@eecs.umich.edu    def unproxy(self, base):
9253101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
9264380Sbinkertn@umich.edu            return EthernetAddr(self.value())
9273101Sstever@eecs.umich.edu        return self
9283101Sstever@eecs.umich.edu
9294762Snate@binkert.org    def getValue(self):
9307677Snate@binkert.org        from m5.internal.params import EthAddr
9314762Snate@binkert.org        return EthAddr(self.value)
9324762Snate@binkert.org
93311228SAndrew.Bardsley@arm.com    def __str__(self):
93411228SAndrew.Bardsley@arm.com        return self.value
93511228SAndrew.Bardsley@arm.com
9364380Sbinkertn@umich.edu    def ini_str(self):
9374380Sbinkertn@umich.edu        return self.value
9383101Sstever@eecs.umich.edu
93910458Sandreas.hansson@arm.com    @classmethod
94010458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
94110458Sandreas.hansson@arm.com        code('%s = Net::EthAddr(%s);' % (dest, src))
94210458Sandreas.hansson@arm.com        code('%s true;' % ret)
94310458Sandreas.hansson@arm.com
9447777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
9457777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
9467777Sgblack@eecs.umich.educlass IpAddress(ParamValue):
9477777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpAddress'
94810267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1"
94910267SGeoffrey.Blake@arm.com    cmd_line_settable = True
9507777Sgblack@eecs.umich.edu
9517777Sgblack@eecs.umich.edu    @classmethod
9527777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
9537777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
9547777Sgblack@eecs.umich.edu
9557777Sgblack@eecs.umich.edu    @classmethod
9567777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
9577777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
9587777Sgblack@eecs.umich.edu
9597777Sgblack@eecs.umich.edu    def __init__(self, value):
9607777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
9617777Sgblack@eecs.umich.edu            self.ip = value.ip
9627777Sgblack@eecs.umich.edu        else:
9637777Sgblack@eecs.umich.edu            try:
9647777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
9657777Sgblack@eecs.umich.edu            except TypeError:
9667777Sgblack@eecs.umich.edu                self.ip = long(value)
9677777Sgblack@eecs.umich.edu        self.verifyIp()
9687777Sgblack@eecs.umich.edu
96910267SGeoffrey.Blake@arm.com    def __call__(self, value):
97010267SGeoffrey.Blake@arm.com        self.__init__(value)
97110267SGeoffrey.Blake@arm.com        return value
97210267SGeoffrey.Blake@arm.com
9738579Ssteve.reinhardt@amd.com    def __str__(self):
9748579Ssteve.reinhardt@amd.com        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
9758579Ssteve.reinhardt@amd.com        return '%d.%d.%d.%d' % tuple(tup)
9768579Ssteve.reinhardt@amd.com
9778579Ssteve.reinhardt@amd.com    def __eq__(self, other):
9788579Ssteve.reinhardt@amd.com        if isinstance(other, IpAddress):
9798579Ssteve.reinhardt@amd.com            return self.ip == other.ip
9808579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
9818579Ssteve.reinhardt@amd.com            try:
9828579Ssteve.reinhardt@amd.com                return self.ip == convert.toIpAddress(other)
9838579Ssteve.reinhardt@amd.com            except:
9848579Ssteve.reinhardt@amd.com                return False
9858579Ssteve.reinhardt@amd.com        else:
9868579Ssteve.reinhardt@amd.com            return self.ip == other
9878579Ssteve.reinhardt@amd.com
9888579Ssteve.reinhardt@amd.com    def __ne__(self, other):
9898579Ssteve.reinhardt@amd.com        return not (self == other)
9908579Ssteve.reinhardt@amd.com
9917777Sgblack@eecs.umich.edu    def verifyIp(self):
9927777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
9937798Sgblack@eecs.umich.edu            raise TypeError, "invalid ip address %#08x" % self.ip
9947777Sgblack@eecs.umich.edu
9957777Sgblack@eecs.umich.edu    def getValue(self):
9967777Sgblack@eecs.umich.edu        from m5.internal.params import IpAddress
9977777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
9987777Sgblack@eecs.umich.edu
9997777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
10007777Sgblack@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
10017777Sgblack@eecs.umich.edu# positional or keyword arguments.
10027777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
10037777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
100410267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.0/24"
100510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
10067777Sgblack@eecs.umich.edu
10077777Sgblack@eecs.umich.edu    @classmethod
10087777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10097777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10107777Sgblack@eecs.umich.edu
10117777Sgblack@eecs.umich.edu    @classmethod
10127777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
10137777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
10147777Sgblack@eecs.umich.edu
10157777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10167777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10177777Sgblack@eecs.umich.edu            if key in kwargs:
10187777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10197777Sgblack@eecs.umich.edu            elif elseVal:
10207777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10217777Sgblack@eecs.umich.edu            else:
10227777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
10237777Sgblack@eecs.umich.edu
10247777Sgblack@eecs.umich.edu        if len(args) == 0:
10257777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
10267777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
10277777Sgblack@eecs.umich.edu
10287777Sgblack@eecs.umich.edu        elif len(args) == 1:
10297777Sgblack@eecs.umich.edu            if kwargs:
10307777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
10317777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
10327777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
10337777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
10347777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
10357777Sgblack@eecs.umich.edu                self.ip = args[0].ip
10367777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
10377777Sgblack@eecs.umich.edu            else:
10387777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
10397777Sgblack@eecs.umich.edu
10407777Sgblack@eecs.umich.edu        elif len(args) == 2:
10417777Sgblack@eecs.umich.edu            self.ip = args[0]
10427777Sgblack@eecs.umich.edu            self.netmask = args[1]
10437777Sgblack@eecs.umich.edu        else:
10447777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
10457777Sgblack@eecs.umich.edu
10467777Sgblack@eecs.umich.edu        if kwargs:
10477777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
10487777Sgblack@eecs.umich.edu
10497777Sgblack@eecs.umich.edu        self.verify()
10507777Sgblack@eecs.umich.edu
105110267SGeoffrey.Blake@arm.com    def __call__(self, value):
105210267SGeoffrey.Blake@arm.com        self.__init__(value)
105310267SGeoffrey.Blake@arm.com        return value
105410267SGeoffrey.Blake@arm.com
10558579Ssteve.reinhardt@amd.com    def __str__(self):
10568579Ssteve.reinhardt@amd.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
10578579Ssteve.reinhardt@amd.com
10588579Ssteve.reinhardt@amd.com    def __eq__(self, other):
10598579Ssteve.reinhardt@amd.com        if isinstance(other, IpNetmask):
10608579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.netmask == other.netmask
10618579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
10628579Ssteve.reinhardt@amd.com            try:
10638579Ssteve.reinhardt@amd.com                return (self.ip, self.netmask) == convert.toIpNetmask(other)
10648579Ssteve.reinhardt@amd.com            except:
10658579Ssteve.reinhardt@amd.com                return False
10668579Ssteve.reinhardt@amd.com        else:
10678579Ssteve.reinhardt@amd.com            return False
10688579Ssteve.reinhardt@amd.com
10697777Sgblack@eecs.umich.edu    def verify(self):
10707777Sgblack@eecs.umich.edu        self.verifyIp()
10717777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
10727777Sgblack@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
10737777Sgblack@eecs.umich.edu
10747777Sgblack@eecs.umich.edu    def getValue(self):
10757777Sgblack@eecs.umich.edu        from m5.internal.params import IpNetmask
10767777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
10777777Sgblack@eecs.umich.edu
10787777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
10797777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
10807777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
10817777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
108210267SGeoffrey.Blake@arm.com    ex_str = "127.0.0.1:80"
108310267SGeoffrey.Blake@arm.com    cmd_line_settable = True
10847777Sgblack@eecs.umich.edu
10857777Sgblack@eecs.umich.edu    @classmethod
10867777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10877777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
10887777Sgblack@eecs.umich.edu
10897777Sgblack@eecs.umich.edu    @classmethod
10907777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
10917777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
10927777Sgblack@eecs.umich.edu
10937777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
10947777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
10957777Sgblack@eecs.umich.edu            if key in kwargs:
10967777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
10977777Sgblack@eecs.umich.edu            elif elseVal:
10987777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
10997777Sgblack@eecs.umich.edu            else:
11007777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
11017777Sgblack@eecs.umich.edu
11027777Sgblack@eecs.umich.edu        if len(args) == 0:
11037777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
11047777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
11057777Sgblack@eecs.umich.edu
11067777Sgblack@eecs.umich.edu        elif len(args) == 1:
11077777Sgblack@eecs.umich.edu            if kwargs:
11087777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
11097777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
11107777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
11117777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
11127777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpWithPort):
11137777Sgblack@eecs.umich.edu                self.ip = args[0].ip
11147777Sgblack@eecs.umich.edu                self.port = args[0].port
11157777Sgblack@eecs.umich.edu            else:
11167777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
11177777Sgblack@eecs.umich.edu
11187777Sgblack@eecs.umich.edu        elif len(args) == 2:
11197777Sgblack@eecs.umich.edu            self.ip = args[0]
11207777Sgblack@eecs.umich.edu            self.port = args[1]
11217777Sgblack@eecs.umich.edu        else:
11227777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
11237777Sgblack@eecs.umich.edu
11247777Sgblack@eecs.umich.edu        if kwargs:
11257777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
11267777Sgblack@eecs.umich.edu
11277777Sgblack@eecs.umich.edu        self.verify()
11287777Sgblack@eecs.umich.edu
112910267SGeoffrey.Blake@arm.com    def __call__(self, value):
113010267SGeoffrey.Blake@arm.com        self.__init__(value)
113110267SGeoffrey.Blake@arm.com        return value
113210267SGeoffrey.Blake@arm.com
11338579Ssteve.reinhardt@amd.com    def __str__(self):
11348579Ssteve.reinhardt@amd.com        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
11358579Ssteve.reinhardt@amd.com
11368579Ssteve.reinhardt@amd.com    def __eq__(self, other):
11378579Ssteve.reinhardt@amd.com        if isinstance(other, IpWithPort):
11388579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.port == other.port
11398579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
11408579Ssteve.reinhardt@amd.com            try:
11418579Ssteve.reinhardt@amd.com                return (self.ip, self.port) == convert.toIpWithPort(other)
11428579Ssteve.reinhardt@amd.com            except:
11438579Ssteve.reinhardt@amd.com                return False
11448579Ssteve.reinhardt@amd.com        else:
11458579Ssteve.reinhardt@amd.com            return False
11468579Ssteve.reinhardt@amd.com
11477777Sgblack@eecs.umich.edu    def verify(self):
11487777Sgblack@eecs.umich.edu        self.verifyIp()
11497777Sgblack@eecs.umich.edu        if self.port < 0 or self.port > 0xffff:
11507777Sgblack@eecs.umich.edu            raise TypeError, "invalid port %d" % self.port
11517777Sgblack@eecs.umich.edu
11527777Sgblack@eecs.umich.edu    def getValue(self):
11537777Sgblack@eecs.umich.edu        from m5.internal.params import IpWithPort
11547777Sgblack@eecs.umich.edu        return IpWithPort(self.ip, self.port)
11557777Sgblack@eecs.umich.edu
11563932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
115710380SAndrew.Bardsley@arm.com                 "%a %b %d %H:%M:%S %Y",
11583932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
11593932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
11603932Sbinkertn@umich.edu                 "%Y/%m/%d",
11613932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
11623932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
11633932Sbinkertn@umich.edu                 "%m/%d/%Y",
11643932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M:%S",
11653932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M",
11663932Sbinkertn@umich.edu                 "%m/%d/%y"]
11673932Sbinkertn@umich.edu
11683932Sbinkertn@umich.edu
11693885Sbinkertn@umich.edudef parse_time(value):
11703932Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
11713932Sbinkertn@umich.edu    from datetime import datetime, date
11723885Sbinkertn@umich.edu
11733932Sbinkertn@umich.edu    if isinstance(value, struct_time):
11743932Sbinkertn@umich.edu        return value
11753932Sbinkertn@umich.edu
11763932Sbinkertn@umich.edu    if isinstance(value, (int, long)):
11773932Sbinkertn@umich.edu        return gmtime(value)
11783932Sbinkertn@umich.edu
11793932Sbinkertn@umich.edu    if isinstance(value, (datetime, date)):
11803932Sbinkertn@umich.edu        return value.timetuple()
11813932Sbinkertn@umich.edu
11823932Sbinkertn@umich.edu    if isinstance(value, str):
11833932Sbinkertn@umich.edu        if value in ('Now', 'Today'):
11843932Sbinkertn@umich.edu            return time.gmtime(time.time())
11853932Sbinkertn@umich.edu
11863932Sbinkertn@umich.edu        for format in time_formats:
11873932Sbinkertn@umich.edu            try:
11883932Sbinkertn@umich.edu                return strptime(value, format)
11893932Sbinkertn@umich.edu            except ValueError:
11903932Sbinkertn@umich.edu                pass
11913885Sbinkertn@umich.edu
11923885Sbinkertn@umich.edu    raise ValueError, "Could not parse '%s' as a time" % value
11933885Sbinkertn@umich.edu
11943885Sbinkertn@umich.educlass Time(ParamValue):
11954762Snate@binkert.org    cxx_type = 'tm'
11967673Snate@binkert.org
11977673Snate@binkert.org    @classmethod
11987673Snate@binkert.org    def cxx_predecls(cls, code):
11997673Snate@binkert.org        code('#include <time.h>')
12007673Snate@binkert.org
12017673Snate@binkert.org    @classmethod
12027673Snate@binkert.org    def swig_predecls(cls, code):
12037673Snate@binkert.org        code('%include "python/swig/time.i"')
12047673Snate@binkert.org
12053885Sbinkertn@umich.edu    def __init__(self, value):
12063932Sbinkertn@umich.edu        self.value = parse_time(value)
12073885Sbinkertn@umich.edu
120810267SGeoffrey.Blake@arm.com    def __call__(self, value):
120910267SGeoffrey.Blake@arm.com        self.__init__(value)
121010267SGeoffrey.Blake@arm.com        return value
121110267SGeoffrey.Blake@arm.com
12124762Snate@binkert.org    def getValue(self):
12137677Snate@binkert.org        from m5.internal.params import tm
12144762Snate@binkert.org
12154762Snate@binkert.org        c_time = tm()
12164762Snate@binkert.org        py_time = self.value
12174762Snate@binkert.org
12184762Snate@binkert.org        # UNIX is years since 1900
12194762Snate@binkert.org        c_time.tm_year = py_time.tm_year - 1900;
12204762Snate@binkert.org
12214762Snate@binkert.org        # Python starts at 1, UNIX starts at 0
12224762Snate@binkert.org        c_time.tm_mon =  py_time.tm_mon - 1;
12234762Snate@binkert.org        c_time.tm_mday = py_time.tm_mday;
12244762Snate@binkert.org        c_time.tm_hour = py_time.tm_hour;
12254762Snate@binkert.org        c_time.tm_min = py_time.tm_min;
12264762Snate@binkert.org        c_time.tm_sec = py_time.tm_sec;
12274762Snate@binkert.org
12284762Snate@binkert.org        # Python has 0 as Monday, UNIX is 0 as sunday
12294762Snate@binkert.org        c_time.tm_wday = py_time.tm_wday + 1
12304762Snate@binkert.org        if c_time.tm_wday > 6:
12314762Snate@binkert.org            c_time.tm_wday -= 7;
12324762Snate@binkert.org
12334762Snate@binkert.org        # Python starts at 1, Unix starts at 0
12344762Snate@binkert.org        c_time.tm_yday = py_time.tm_yday - 1;
12354762Snate@binkert.org
12364762Snate@binkert.org        return c_time
12374762Snate@binkert.org
12383885Sbinkertn@umich.edu    def __str__(self):
12394762Snate@binkert.org        return time.asctime(self.value)
12403885Sbinkertn@umich.edu
12413885Sbinkertn@umich.edu    def ini_str(self):
12423932Sbinkertn@umich.edu        return str(self)
12433885Sbinkertn@umich.edu
12448664SAli.Saidi@ARM.com    def get_config_as_dict(self):
124510380SAndrew.Bardsley@arm.com        assert false
12468664SAli.Saidi@ARM.com        return str(self)
12478664SAli.Saidi@ARM.com
124810458Sandreas.hansson@arm.com    @classmethod
124910458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
125010458Sandreas.hansson@arm.com        code('#include <time.h>')
125110458Sandreas.hansson@arm.com
125210458Sandreas.hansson@arm.com    @classmethod
125310458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
125410458Sandreas.hansson@arm.com        code('char *_parse_ret = strptime((${src}).c_str(),')
125510458Sandreas.hansson@arm.com        code('    "%a %b %d %H:%M:%S %Y", &(${dest}));')
125610458Sandreas.hansson@arm.com        code('${ret} _parse_ret && *_parse_ret == \'\\0\';');
125710458Sandreas.hansson@arm.com
12583101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
12593101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
12603101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
12613101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
12623101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
12633101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
12643101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
12653101Sstever@eecs.umich.edu
12663101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
12673101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
12683101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
12693101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
12703101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
12713101Sstever@eecs.umich.edu
12724762Snate@binkert.orgallEnums = {}
12733101Sstever@eecs.umich.edu# Metaclass for Enum types
12745033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue):
12754762Snate@binkert.org    def __new__(mcls, name, bases, dict):
12764762Snate@binkert.org        assert name not in allEnums
12774762Snate@binkert.org
12784762Snate@binkert.org        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
12794762Snate@binkert.org        allEnums[name] = cls
12804762Snate@binkert.org        return cls
12814762Snate@binkert.org
12823101Sstever@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
12833101Sstever@eecs.umich.edu        if init_dict.has_key('map'):
12843101Sstever@eecs.umich.edu            if not isinstance(cls.map, dict):
12853101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'map' " \
12863101Sstever@eecs.umich.edu                      "must be of type dict"
12873101Sstever@eecs.umich.edu            # build list of value strings from map
12883101Sstever@eecs.umich.edu            cls.vals = cls.map.keys()
12893101Sstever@eecs.umich.edu            cls.vals.sort()
12903101Sstever@eecs.umich.edu        elif init_dict.has_key('vals'):
12913101Sstever@eecs.umich.edu            if not isinstance(cls.vals, list):
12923101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'vals' " \
12933101Sstever@eecs.umich.edu                      "must be of type list"
12943101Sstever@eecs.umich.edu            # build string->value map from vals sequence
12953101Sstever@eecs.umich.edu            cls.map = {}
12963101Sstever@eecs.umich.edu            for idx,val in enumerate(cls.vals):
12973101Sstever@eecs.umich.edu                cls.map[val] = idx
12983101Sstever@eecs.umich.edu        else:
12993101Sstever@eecs.umich.edu            raise TypeError, "Enum-derived class must define "\
13003101Sstever@eecs.umich.edu                  "attribute 'map' or 'vals'"
13013101Sstever@eecs.umich.edu
13024762Snate@binkert.org        cls.cxx_type = 'Enums::%s' % name
13033101Sstever@eecs.umich.edu
13043101Sstever@eecs.umich.edu        super(MetaEnum, cls).__init__(name, bases, init_dict)
13053101Sstever@eecs.umich.edu
13063101Sstever@eecs.umich.edu    # Generate C++ class declaration for this enum type.
13073101Sstever@eecs.umich.edu    # Note that we wrap the enum in a class/struct to act as a namespace,
13083101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
13097673Snate@binkert.org    def cxx_decl(cls, code):
131010201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
131110201SAndrew.Bardsley@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
131210201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
131310201SAndrew.Bardsley@arm.com        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
131410201SAndrew.Bardsley@arm.com
13157673Snate@binkert.org        code('''\
131610201SAndrew.Bardsley@arm.com#ifndef $idem_macro
131710201SAndrew.Bardsley@arm.com#define $idem_macro
13187673Snate@binkert.org
131910201SAndrew.Bardsley@arm.com$wrapper $wrapper_name {
13207673Snate@binkert.org    enum $name {
13217673Snate@binkert.org''')
13227673Snate@binkert.org        code.indent(2)
13234762Snate@binkert.org        for val in cls.vals:
13247673Snate@binkert.org            code('$val = ${{cls.map[val]}},')
13258902Sandreas.hansson@arm.com        code('Num_$name = ${{len(cls.vals)}}')
13267673Snate@binkert.org        code.dedent(2)
132710201SAndrew.Bardsley@arm.com        code('    };')
13284762Snate@binkert.org
132910201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
133010201SAndrew.Bardsley@arm.com            code('    static const char *${name}Strings[Num_${name}];')
133110201SAndrew.Bardsley@arm.com            code('};')
133210201SAndrew.Bardsley@arm.com        else:
133310201SAndrew.Bardsley@arm.com            code('extern const char *${name}Strings[Num_${name}];')
133410201SAndrew.Bardsley@arm.com            code('}')
133510201SAndrew.Bardsley@arm.com
133610201SAndrew.Bardsley@arm.com        code()
133710201SAndrew.Bardsley@arm.com        code('#endif // $idem_macro')
13387673Snate@binkert.org
13397673Snate@binkert.org    def cxx_def(cls, code):
134010201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
134110201SAndrew.Bardsley@arm.com        file_name = cls.__name__
134210201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
134310201SAndrew.Bardsley@arm.com
134410201SAndrew.Bardsley@arm.com        code('#include "enums/$file_name.hh"')
134510201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
134610201SAndrew.Bardsley@arm.com            code('const char *${wrapper_name}::${name}Strings'
134710201SAndrew.Bardsley@arm.com                '[Num_${name}] =')
134810201SAndrew.Bardsley@arm.com        else:
134910201SAndrew.Bardsley@arm.com            code('namespace Enums {')
135010201SAndrew.Bardsley@arm.com            code.indent(1)
135110201SAndrew.Bardsley@arm.com            code(' const char *${name}Strings[Num_${name}] =')
135210201SAndrew.Bardsley@arm.com
135310201SAndrew.Bardsley@arm.com        code('{')
135410201SAndrew.Bardsley@arm.com        code.indent(1)
13554762Snate@binkert.org        for val in cls.vals:
13567673Snate@binkert.org            code('"$val",')
135710201SAndrew.Bardsley@arm.com        code.dedent(1)
135810201SAndrew.Bardsley@arm.com        code('};')
135910201SAndrew.Bardsley@arm.com
136010201SAndrew.Bardsley@arm.com        if not cls.wrapper_is_struct:
136110201SAndrew.Bardsley@arm.com            code('} // namespace $wrapper_name')
136210201SAndrew.Bardsley@arm.com            code.dedent(1)
13633101Sstever@eecs.umich.edu
13648596Ssteve.reinhardt@amd.com    def swig_decl(cls, code):
13658596Ssteve.reinhardt@amd.com        name = cls.__name__
13668596Ssteve.reinhardt@amd.com        code('''\
13678596Ssteve.reinhardt@amd.com%module(package="m5.internal") enum_$name
13688596Ssteve.reinhardt@amd.com
13698596Ssteve.reinhardt@amd.com%{
13708596Ssteve.reinhardt@amd.com#include "enums/$name.hh"
13718596Ssteve.reinhardt@amd.com%}
13728596Ssteve.reinhardt@amd.com
13738596Ssteve.reinhardt@amd.com%include "enums/$name.hh"
13748596Ssteve.reinhardt@amd.com''')
13758596Ssteve.reinhardt@amd.com
13768596Ssteve.reinhardt@amd.com
13773101Sstever@eecs.umich.edu# Base class for enum types.
13783101Sstever@eecs.umich.educlass Enum(ParamValue):
13793101Sstever@eecs.umich.edu    __metaclass__ = MetaEnum
13803101Sstever@eecs.umich.edu    vals = []
138110267SGeoffrey.Blake@arm.com    cmd_line_settable = True
13823101Sstever@eecs.umich.edu
138310201SAndrew.Bardsley@arm.com    # The name of the wrapping namespace or struct
138410201SAndrew.Bardsley@arm.com    wrapper_name = 'Enums'
138510201SAndrew.Bardsley@arm.com
138610201SAndrew.Bardsley@arm.com    # If true, the enum is wrapped in a struct rather than a namespace
138710201SAndrew.Bardsley@arm.com    wrapper_is_struct = False
138810201SAndrew.Bardsley@arm.com
138910201SAndrew.Bardsley@arm.com    # If not None, use this as the enum name rather than this class name
139010201SAndrew.Bardsley@arm.com    enum_name = None
139110201SAndrew.Bardsley@arm.com
13923101Sstever@eecs.umich.edu    def __init__(self, value):
13933101Sstever@eecs.umich.edu        if value not in self.map:
13943101Sstever@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
13953101Sstever@eecs.umich.edu                  % (value, self.vals)
13963101Sstever@eecs.umich.edu        self.value = 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
14027675Snate@binkert.org    @classmethod
14037675Snate@binkert.org    def cxx_predecls(cls, code):
14047675Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
14057675Snate@binkert.org
14067675Snate@binkert.org    @classmethod
14077675Snate@binkert.org    def swig_predecls(cls, code):
14087677Snate@binkert.org        code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
14097675Snate@binkert.org
141010458Sandreas.hansson@arm.com    @classmethod
141110458Sandreas.hansson@arm.com    def cxx_ini_parse(cls, code, src, dest, ret):
141210458Sandreas.hansson@arm.com        code('if (false) {')
141310458Sandreas.hansson@arm.com        for elem_name in cls.map.iterkeys():
141410458Sandreas.hansson@arm.com            code('} else if (%s == "%s") {' % (src, elem_name))
141510458Sandreas.hansson@arm.com            code.indent()
141610458Sandreas.hansson@arm.com            code('%s = Enums::%s;' % (dest, elem_name))
141710458Sandreas.hansson@arm.com            code('%s true;' % ret)
141810458Sandreas.hansson@arm.com            code.dedent()
141910458Sandreas.hansson@arm.com        code('} else {')
142010458Sandreas.hansson@arm.com        code('    %s false;' % ret)
142110458Sandreas.hansson@arm.com        code('}')
142210458Sandreas.hansson@arm.com
14234762Snate@binkert.org    def getValue(self):
14244762Snate@binkert.org        return int(self.map[self.value])
14254762Snate@binkert.org
14263101Sstever@eecs.umich.edu    def __str__(self):
14273101Sstever@eecs.umich.edu        return self.value
14283101Sstever@eecs.umich.edu
14293101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it?
14303101Sstever@eecs.umich.edufrequency_tolerance = 0.001  # 0.1%
14313101Sstever@eecs.umich.edu
14324167Sbinkertn@umich.educlass TickParamValue(NumericParamValue):
14333101Sstever@eecs.umich.edu    cxx_type = 'Tick'
143410267SGeoffrey.Blake@arm.com    ex_str = "1MHz"
143510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
14367673Snate@binkert.org
14377673Snate@binkert.org    @classmethod
14387673Snate@binkert.org    def cxx_predecls(cls, code):
14397673Snate@binkert.org        code('#include "base/types.hh"')
14407673Snate@binkert.org
14417673Snate@binkert.org    @classmethod
14427673Snate@binkert.org    def swig_predecls(cls, code):
14437673Snate@binkert.org        code('%import "stdint.i"')
14447673Snate@binkert.org        code('%import "base/types.hh"')
14454167Sbinkertn@umich.edu
144610267SGeoffrey.Blake@arm.com    def __call__(self, value):
144710267SGeoffrey.Blake@arm.com        self.__init__(value)
144810267SGeoffrey.Blake@arm.com        return value
144910267SGeoffrey.Blake@arm.com
14504762Snate@binkert.org    def getValue(self):
14514762Snate@binkert.org        return long(self.value)
14524762Snate@binkert.org
145310458Sandreas.hansson@arm.com    @classmethod
145410458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
145510458Sandreas.hansson@arm.com        code('#include <sstream>')
145610458Sandreas.hansson@arm.com
145710458Sandreas.hansson@arm.com    # Ticks are expressed in seconds in JSON files and in plain
145810458Sandreas.hansson@arm.com    # Ticks in .ini files.  Switch based on a config flag
145910458Sandreas.hansson@arm.com    @classmethod
146010458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
146110458Sandreas.hansson@arm.com        code('${ret} to_number(${src}, ${dest});')
146210458Sandreas.hansson@arm.com
14634167Sbinkertn@umich.educlass Latency(TickParamValue):
146410267SGeoffrey.Blake@arm.com    ex_str = "100ns"
146510267SGeoffrey.Blake@arm.com
14663101Sstever@eecs.umich.edu    def __init__(self, value):
14674167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
14684167Sbinkertn@umich.edu            self.ticks = value.ticks
14694167Sbinkertn@umich.edu            self.value = value.value
14704167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
14714167Sbinkertn@umich.edu            self.ticks = value.ticks
14724167Sbinkertn@umich.edu            self.value = 1.0 / value.value
14734167Sbinkertn@umich.edu        elif value.endswith('t'):
14744167Sbinkertn@umich.edu            self.ticks = True
14754167Sbinkertn@umich.edu            self.value = int(value[:-1])
14764167Sbinkertn@umich.edu        else:
14774167Sbinkertn@umich.edu            self.ticks = False
14784167Sbinkertn@umich.edu            self.value = convert.toLatency(value)
14793101Sstever@eecs.umich.edu
148010267SGeoffrey.Blake@arm.com    def __call__(self, value):
148110267SGeoffrey.Blake@arm.com        self.__init__(value)
148210267SGeoffrey.Blake@arm.com        return value
148310267SGeoffrey.Blake@arm.com
14843101Sstever@eecs.umich.edu    def __getattr__(self, attr):
14853101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
14863101Sstever@eecs.umich.edu            return self
14873101Sstever@eecs.umich.edu        if attr == 'frequency':
14883101Sstever@eecs.umich.edu            return Frequency(self)
14893101Sstever@eecs.umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
14903101Sstever@eecs.umich.edu
14914762Snate@binkert.org    def getValue(self):
14924762Snate@binkert.org        if self.ticks or self.value == 0:
14934762Snate@binkert.org            value = self.value
14944762Snate@binkert.org        else:
14954762Snate@binkert.org            value = ticks.fromSeconds(self.value)
14964762Snate@binkert.org        return long(value)
14974762Snate@binkert.org
149810380SAndrew.Bardsley@arm.com    def config_value(self):
149910380SAndrew.Bardsley@arm.com        return self.getValue()
150010380SAndrew.Bardsley@arm.com
15013101Sstever@eecs.umich.edu    # convert latency to ticks
15023101Sstever@eecs.umich.edu    def ini_str(self):
15034762Snate@binkert.org        return '%d' % self.getValue()
15043101Sstever@eecs.umich.edu
15054167Sbinkertn@umich.educlass Frequency(TickParamValue):
150610267SGeoffrey.Blake@arm.com    ex_str = "1GHz"
150710267SGeoffrey.Blake@arm.com
15083101Sstever@eecs.umich.edu    def __init__(self, value):
15094167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
15104167Sbinkertn@umich.edu            if value.value == 0:
15114167Sbinkertn@umich.edu                self.value = 0
15124167Sbinkertn@umich.edu            else:
15134167Sbinkertn@umich.edu                self.value = 1.0 / value.value
15144167Sbinkertn@umich.edu            self.ticks = value.ticks
15154167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
15164167Sbinkertn@umich.edu            self.value = value.value
15174167Sbinkertn@umich.edu            self.ticks = value.ticks
15184167Sbinkertn@umich.edu        else:
15194167Sbinkertn@umich.edu            self.ticks = False
15204167Sbinkertn@umich.edu            self.value = convert.toFrequency(value)
15213101Sstever@eecs.umich.edu
152210267SGeoffrey.Blake@arm.com    def __call__(self, value):
152310267SGeoffrey.Blake@arm.com        self.__init__(value)
152410267SGeoffrey.Blake@arm.com        return value
152510267SGeoffrey.Blake@arm.com
15263101Sstever@eecs.umich.edu    def __getattr__(self, attr):
15273101Sstever@eecs.umich.edu        if attr == 'frequency':
15283101Sstever@eecs.umich.edu            return self
15293101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
15303101Sstever@eecs.umich.edu            return Latency(self)
15313101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
15323101Sstever@eecs.umich.edu
15334167Sbinkertn@umich.edu    # convert latency to ticks
15344762Snate@binkert.org    def getValue(self):
15354762Snate@binkert.org        if self.ticks or self.value == 0:
15364762Snate@binkert.org            value = self.value
15374762Snate@binkert.org        else:
15384762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
15394762Snate@binkert.org        return long(value)
15404762Snate@binkert.org
154110380SAndrew.Bardsley@arm.com    def config_value(self):
154210380SAndrew.Bardsley@arm.com        return self.getValue()
154310380SAndrew.Bardsley@arm.com
15443101Sstever@eecs.umich.edu    def ini_str(self):
15454762Snate@binkert.org        return '%d' % self.getValue()
15463101Sstever@eecs.umich.edu
154710019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a
154810019Sandreas.hansson@arm.com# latency, just like Latency and Frequency.
154910019Sandreas.hansson@arm.comclass Clock(TickParamValue):
15503101Sstever@eecs.umich.edu    def __init__(self, value):
15514167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
15524167Sbinkertn@umich.edu            self.ticks = value.ticks
15534167Sbinkertn@umich.edu            self.value = value.value
15544167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
15554167Sbinkertn@umich.edu            self.ticks = value.ticks
15564167Sbinkertn@umich.edu            self.value = 1.0 / value.value
15574167Sbinkertn@umich.edu        elif value.endswith('t'):
15584167Sbinkertn@umich.edu            self.ticks = True
15594167Sbinkertn@umich.edu            self.value = int(value[:-1])
15604167Sbinkertn@umich.edu        else:
15614167Sbinkertn@umich.edu            self.ticks = False
15624167Sbinkertn@umich.edu            self.value = convert.anyToLatency(value)
15633101Sstever@eecs.umich.edu
156410267SGeoffrey.Blake@arm.com    def __call__(self, value):
156510267SGeoffrey.Blake@arm.com        self.__init__(value)
156610267SGeoffrey.Blake@arm.com        return value
156710267SGeoffrey.Blake@arm.com
156810267SGeoffrey.Blake@arm.com    def __str__(self):
156910267SGeoffrey.Blake@arm.com        return "%s" % Latency(self)
157010267SGeoffrey.Blake@arm.com
15713101Sstever@eecs.umich.edu    def __getattr__(self, attr):
15723101Sstever@eecs.umich.edu        if attr == 'frequency':
15733101Sstever@eecs.umich.edu            return Frequency(self)
15743101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
15753101Sstever@eecs.umich.edu            return Latency(self)
15763101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
15773101Sstever@eecs.umich.edu
15784762Snate@binkert.org    def getValue(self):
15794762Snate@binkert.org        return self.period.getValue()
15804762Snate@binkert.org
158110380SAndrew.Bardsley@arm.com    def config_value(self):
158210380SAndrew.Bardsley@arm.com        return self.period.config_value()
158310380SAndrew.Bardsley@arm.com
15843101Sstever@eecs.umich.edu    def ini_str(self):
15853101Sstever@eecs.umich.edu        return self.period.ini_str()
15863101Sstever@eecs.umich.edu
15879827Sakash.bagdia@arm.comclass Voltage(float,ParamValue):
15889827Sakash.bagdia@arm.com    cxx_type = 'double'
158910267SGeoffrey.Blake@arm.com    ex_str = "1V"
159010267SGeoffrey.Blake@arm.com    cmd_line_settable = False
159110267SGeoffrey.Blake@arm.com
15929827Sakash.bagdia@arm.com    def __new__(cls, value):
15939827Sakash.bagdia@arm.com        # convert to voltage
15949827Sakash.bagdia@arm.com        val = convert.toVoltage(value)
15959827Sakash.bagdia@arm.com        return super(cls, Voltage).__new__(cls, val)
15969827Sakash.bagdia@arm.com
159710267SGeoffrey.Blake@arm.com    def __call__(self, value):
159810267SGeoffrey.Blake@arm.com        val = convert.toVoltage(value)
159910267SGeoffrey.Blake@arm.com        self.__init__(val)
160010267SGeoffrey.Blake@arm.com        return value
160110267SGeoffrey.Blake@arm.com
16029827Sakash.bagdia@arm.com    def __str__(self):
160310267SGeoffrey.Blake@arm.com        return str(self.getValue())
16049827Sakash.bagdia@arm.com
16059827Sakash.bagdia@arm.com    def getValue(self):
16069827Sakash.bagdia@arm.com        value = float(self)
16079827Sakash.bagdia@arm.com        return value
16089827Sakash.bagdia@arm.com
16099827Sakash.bagdia@arm.com    def ini_str(self):
16109827Sakash.bagdia@arm.com        return '%f' % self.getValue()
16119827Sakash.bagdia@arm.com
161210458Sandreas.hansson@arm.com    @classmethod
161310458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
161410458Sandreas.hansson@arm.com        code('#include <sstream>')
161510458Sandreas.hansson@arm.com
161610458Sandreas.hansson@arm.com    @classmethod
161710458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
161810458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
161910458Sandreas.hansson@arm.com
162010427Sandreas.hansson@arm.comclass Current(float, ParamValue):
162110427Sandreas.hansson@arm.com    cxx_type = 'double'
162210427Sandreas.hansson@arm.com    ex_str = "1mA"
162310427Sandreas.hansson@arm.com    cmd_line_settable = False
162410427Sandreas.hansson@arm.com
162510427Sandreas.hansson@arm.com    def __new__(cls, value):
162610427Sandreas.hansson@arm.com        # convert to current
162710427Sandreas.hansson@arm.com        val = convert.toCurrent(value)
162810427Sandreas.hansson@arm.com        return super(cls, Current).__new__(cls, val)
162910427Sandreas.hansson@arm.com
163010427Sandreas.hansson@arm.com    def __call__(self, value):
163110427Sandreas.hansson@arm.com        val = convert.toCurrent(value)
163210427Sandreas.hansson@arm.com        self.__init__(val)
163310427Sandreas.hansson@arm.com        return value
163410427Sandreas.hansson@arm.com
163510427Sandreas.hansson@arm.com    def __str__(self):
163610427Sandreas.hansson@arm.com        return str(self.getValue())
163710427Sandreas.hansson@arm.com
163810427Sandreas.hansson@arm.com    def getValue(self):
163910427Sandreas.hansson@arm.com        value = float(self)
164010427Sandreas.hansson@arm.com        return value
164110427Sandreas.hansson@arm.com
164210427Sandreas.hansson@arm.com    def ini_str(self):
164310427Sandreas.hansson@arm.com        return '%f' % self.getValue()
164410427Sandreas.hansson@arm.com
164510458Sandreas.hansson@arm.com    @classmethod
164610458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
164710458Sandreas.hansson@arm.com        code('#include <sstream>')
164810458Sandreas.hansson@arm.com
164910458Sandreas.hansson@arm.com    @classmethod
165010458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
165110458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
165210458Sandreas.hansson@arm.com
16533101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
16543101Sstever@eecs.umich.edu    cxx_type = 'float'
165510267SGeoffrey.Blake@arm.com    ex_str = "1Gbps"
165610267SGeoffrey.Blake@arm.com    cmd_line_settable = True
165710267SGeoffrey.Blake@arm.com
16583101Sstever@eecs.umich.edu    def __new__(cls, value):
16594167Sbinkertn@umich.edu        # convert to bits per second
16604167Sbinkertn@umich.edu        val = convert.toNetworkBandwidth(value)
16613101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
16623101Sstever@eecs.umich.edu
16633101Sstever@eecs.umich.edu    def __str__(self):
16643101Sstever@eecs.umich.edu        return str(self.val)
16653101Sstever@eecs.umich.edu
166610267SGeoffrey.Blake@arm.com    def __call__(self, value):
166710267SGeoffrey.Blake@arm.com        val = convert.toNetworkBandwidth(value)
166810267SGeoffrey.Blake@arm.com        self.__init__(val)
166910267SGeoffrey.Blake@arm.com        return value
167010267SGeoffrey.Blake@arm.com
16714762Snate@binkert.org    def getValue(self):
16724167Sbinkertn@umich.edu        # convert to seconds per byte
16734167Sbinkertn@umich.edu        value = 8.0 / float(self)
16744167Sbinkertn@umich.edu        # convert to ticks per byte
16754762Snate@binkert.org        value = ticks.fromSeconds(value)
16764762Snate@binkert.org        return float(value)
16774762Snate@binkert.org
16784762Snate@binkert.org    def ini_str(self):
16794762Snate@binkert.org        return '%f' % self.getValue()
16803101Sstever@eecs.umich.edu
168110380SAndrew.Bardsley@arm.com    def config_value(self):
168210380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
168310380SAndrew.Bardsley@arm.com
168410458Sandreas.hansson@arm.com    @classmethod
168510458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
168610458Sandreas.hansson@arm.com        code('#include <sstream>')
168710458Sandreas.hansson@arm.com
168810458Sandreas.hansson@arm.com    @classmethod
168910458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
169010458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
169110458Sandreas.hansson@arm.com
16923101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
16933101Sstever@eecs.umich.edu    cxx_type = 'float'
169410267SGeoffrey.Blake@arm.com    ex_str = "1GB/s"
169510267SGeoffrey.Blake@arm.com    cmd_line_settable = True
169610267SGeoffrey.Blake@arm.com
16975469Snate@binkert.org    def __new__(cls, value):
16987743Sgblack@eecs.umich.edu        # convert to bytes per second
16993102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
17003101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
17013101Sstever@eecs.umich.edu
170210267SGeoffrey.Blake@arm.com    def __call__(self, value):
170310267SGeoffrey.Blake@arm.com        val = convert.toMemoryBandwidth(value)
170410267SGeoffrey.Blake@arm.com        self.__init__(val)
170510267SGeoffrey.Blake@arm.com        return value
17063101Sstever@eecs.umich.edu
17074762Snate@binkert.org    def getValue(self):
17084167Sbinkertn@umich.edu        # convert to seconds per byte
17095468Snate@binkert.org        value = float(self)
17105468Snate@binkert.org        if value:
17115468Snate@binkert.org            value = 1.0 / float(self)
17124167Sbinkertn@umich.edu        # convert to ticks per byte
17134762Snate@binkert.org        value = ticks.fromSeconds(value)
17144762Snate@binkert.org        return float(value)
17154762Snate@binkert.org
17164762Snate@binkert.org    def ini_str(self):
17174762Snate@binkert.org        return '%f' % self.getValue()
17183101Sstever@eecs.umich.edu
171910380SAndrew.Bardsley@arm.com    def config_value(self):
172010380SAndrew.Bardsley@arm.com        return '%f' % self.getValue()
172110380SAndrew.Bardsley@arm.com
172210458Sandreas.hansson@arm.com    @classmethod
172310458Sandreas.hansson@arm.com    def cxx_ini_predecls(cls, code):
172410458Sandreas.hansson@arm.com        code('#include <sstream>')
172510458Sandreas.hansson@arm.com
172610458Sandreas.hansson@arm.com    @classmethod
172710458Sandreas.hansson@arm.com    def cxx_ini_parse(self, code, src, dest, ret):
172810458Sandreas.hansson@arm.com        code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest))
172910458Sandreas.hansson@arm.com
17303101Sstever@eecs.umich.edu#
17313101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
17323101Sstever@eecs.umich.edu#
17333101Sstever@eecs.umich.edu
17343102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
17353102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
17363102Sstever@eecs.umich.edu# SimObject is required.
17373102Sstever@eecs.umich.edu# only one copy of a particular node
17383102Sstever@eecs.umich.educlass NullSimObject(object):
17393102Sstever@eecs.umich.edu    __metaclass__ = Singleton
17403102Sstever@eecs.umich.edu
17413102Sstever@eecs.umich.edu    def __call__(cls):
17423102Sstever@eecs.umich.edu        return cls
17433102Sstever@eecs.umich.edu
17443102Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
17453102Sstever@eecs.umich.edu        pass
17463102Sstever@eecs.umich.edu
17473102Sstever@eecs.umich.edu    def ini_str(self):
17483102Sstever@eecs.umich.edu        return 'Null'
17493102Sstever@eecs.umich.edu
17503102Sstever@eecs.umich.edu    def unproxy(self, base):
17513102Sstever@eecs.umich.edu        return self
17523102Sstever@eecs.umich.edu
17533102Sstever@eecs.umich.edu    def set_path(self, parent, name):
17543102Sstever@eecs.umich.edu        pass
17554762Snate@binkert.org
17563102Sstever@eecs.umich.edu    def __str__(self):
17573102Sstever@eecs.umich.edu        return 'Null'
17583102Sstever@eecs.umich.edu
175910380SAndrew.Bardsley@arm.com    def config_value(self):
176010380SAndrew.Bardsley@arm.com        return None
176110380SAndrew.Bardsley@arm.com
17624762Snate@binkert.org    def getValue(self):
17634762Snate@binkert.org        return None
17644762Snate@binkert.org
17653102Sstever@eecs.umich.edu# The only instance you'll ever need...
17663102Sstever@eecs.umich.eduNULL = NullSimObject()
17673102Sstever@eecs.umich.edu
17683102Sstever@eecs.umich.edudef isNullPointer(value):
17693102Sstever@eecs.umich.edu    return isinstance(value, NullSimObject)
17703102Sstever@eecs.umich.edu
17713101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
17723101Sstever@eecs.umich.eduMaxAddr = Addr.max
17733101Sstever@eecs.umich.eduMaxTick = Tick.max
17743101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
17753101Sstever@eecs.umich.edu
17763101Sstever@eecs.umich.edu
17773101Sstever@eecs.umich.edu#####################################################################
17783101Sstever@eecs.umich.edu#
17793101Sstever@eecs.umich.edu# Port objects
17803101Sstever@eecs.umich.edu#
17813101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
17823101Sstever@eecs.umich.edu#
17833101Sstever@eecs.umich.edu#####################################################################
17843101Sstever@eecs.umich.edu
17853101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
17863101Sstever@eecs.umich.edu# particular SimObject.
17873101Sstever@eecs.umich.educlass PortRef(object):
17888839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
17893105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
17903101Sstever@eecs.umich.edu        self.simobj = simobj
17913101Sstever@eecs.umich.edu        self.name = name
17928839Sandreas.hansson@arm.com        self.role = role
17933101Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
17943101Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
17953105Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
17963101Sstever@eecs.umich.edu
17973103Sstever@eecs.umich.edu    def __str__(self):
17983105Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
17993103Sstever@eecs.umich.edu
18008840Sandreas.hansson@arm.com    def __len__(self):
18018840Sandreas.hansson@arm.com        # Return the number of connected ports, i.e. 0 is we have no
18028840Sandreas.hansson@arm.com        # peer and 1 if we do.
18038840Sandreas.hansson@arm.com        return int(self.peer != None)
18048840Sandreas.hansson@arm.com
18053105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
18063105Sstever@eecs.umich.edu    def ini_str(self):
18073105Sstever@eecs.umich.edu        return str(self.peer)
18083105Sstever@eecs.umich.edu
18099017Sandreas.hansson@arm.com    # for config.json
18109017Sandreas.hansson@arm.com    def get_config_as_dict(self):
18119017Sandreas.hansson@arm.com        return {'role' : self.role, 'peer' : str(self.peer)}
18129017Sandreas.hansson@arm.com
18133105Sstever@eecs.umich.edu    def __getattr__(self, attr):
18143105Sstever@eecs.umich.edu        if attr == 'peerObj':
18153105Sstever@eecs.umich.edu            # shorthand for proxies
18163105Sstever@eecs.umich.edu            return self.peer.simobj
18173105Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
18183105Sstever@eecs.umich.edu              (self.__class__.__name__, attr)
18193105Sstever@eecs.umich.edu
18203105Sstever@eecs.umich.edu    # Full connection is symmetric (both ways).  Called via
18213105Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
18223109Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
18233105Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
18243105Sstever@eecs.umich.edu    def connect(self, other):
18253105Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
18263105Sstever@eecs.umich.edu            # reference to plain VectorPort is implicit append
18273105Sstever@eecs.umich.edu            other = other._get_next()
18283105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
18299014Sandreas.hansson@arm.com            fatal("Port %s is already connected to %s, cannot connect %s\n",
18309014Sandreas.hansson@arm.com                  self, self.peer, other);
18313101Sstever@eecs.umich.edu        self.peer = other
18323109Sstever@eecs.umich.edu        if proxy.isproxy(other):
18333109Sstever@eecs.umich.edu            other.set_param_desc(PortParamDesc())
18343109Sstever@eecs.umich.edu        elif isinstance(other, PortRef):
18353109Sstever@eecs.umich.edu            if other.peer is not self:
18363109Sstever@eecs.umich.edu                other.connect(self)
18373109Sstever@eecs.umich.edu        else:
18383109Sstever@eecs.umich.edu            raise TypeError, \
18393109Sstever@eecs.umich.edu                  "assigning non-port reference '%s' to port '%s'" \
18403109Sstever@eecs.umich.edu                  % (other, self)
18413101Sstever@eecs.umich.edu
184210355SGeoffrey.Blake@arm.com    # Allow a master/slave port pair to be spliced between
184310355SGeoffrey.Blake@arm.com    # a port and its connected peer. Useful operation for connecting
184410355SGeoffrey.Blake@arm.com    # instrumentation structures into a system when it is necessary
184510355SGeoffrey.Blake@arm.com    # to connect the instrumentation after the full system has been
184610355SGeoffrey.Blake@arm.com    # constructed.
184710355SGeoffrey.Blake@arm.com    def splice(self, new_master_peer, new_slave_peer):
184810355SGeoffrey.Blake@arm.com        if self.peer and not proxy.isproxy(self.peer):
184910355SGeoffrey.Blake@arm.com            if isinstance(new_master_peer, PortRef) and \
185010355SGeoffrey.Blake@arm.com               isinstance(new_slave_peer, PortRef):
185110355SGeoffrey.Blake@arm.com                 old_peer = self.peer
185210355SGeoffrey.Blake@arm.com                 if self.role == 'SLAVE':
185310355SGeoffrey.Blake@arm.com                     self.peer = new_master_peer
185410355SGeoffrey.Blake@arm.com                     old_peer.peer = new_slave_peer
185510355SGeoffrey.Blake@arm.com                     new_master_peer.connect(self)
185610355SGeoffrey.Blake@arm.com                     new_slave_peer.connect(old_peer)
185710355SGeoffrey.Blake@arm.com                 elif self.role == 'MASTER':
185810355SGeoffrey.Blake@arm.com                     self.peer = new_slave_peer
185910355SGeoffrey.Blake@arm.com                     old_peer.peer = new_master_peer
186010355SGeoffrey.Blake@arm.com                     new_slave_peer.connect(self)
186110355SGeoffrey.Blake@arm.com                     new_master_peer.connect(old_peer)
186210355SGeoffrey.Blake@arm.com                 else:
186310355SGeoffrey.Blake@arm.com                     panic("Port %s has unknown role, "+\
186410355SGeoffrey.Blake@arm.com                           "cannot splice in new peers\n", self)
186510355SGeoffrey.Blake@arm.com            else:
186610355SGeoffrey.Blake@arm.com                raise TypeError, \
186710355SGeoffrey.Blake@arm.com                      "Splicing non-port references '%s','%s' to port '%s'"\
186810355SGeoffrey.Blake@arm.com                      % (new_peer, peers_new_peer, self)
186910355SGeoffrey.Blake@arm.com        else:
187010355SGeoffrey.Blake@arm.com            fatal("Port %s not connected, cannot splice in new peers\n", self)
187110355SGeoffrey.Blake@arm.com
18723105Sstever@eecs.umich.edu    def clone(self, simobj, memo):
18733105Sstever@eecs.umich.edu        if memo.has_key(self):
18743105Sstever@eecs.umich.edu            return memo[self]
18753101Sstever@eecs.umich.edu        newRef = copy.copy(self)
18763105Sstever@eecs.umich.edu        memo[self] = newRef
18773105Sstever@eecs.umich.edu        newRef.simobj = simobj
18783101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
18793105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
18803179Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
18813105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
18823105Sstever@eecs.umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
18833101Sstever@eecs.umich.edu        return newRef
18843101Sstever@eecs.umich.edu
18853105Sstever@eecs.umich.edu    def unproxy(self, simobj):
18863105Sstever@eecs.umich.edu        assert(simobj is self.simobj)
18873105Sstever@eecs.umich.edu        if proxy.isproxy(self.peer):
18883105Sstever@eecs.umich.edu            try:
18893105Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
18903105Sstever@eecs.umich.edu            except:
18913105Sstever@eecs.umich.edu                print "Error in unproxying port '%s' of %s" % \
18923105Sstever@eecs.umich.edu                      (self.name, self.simobj.path())
18933105Sstever@eecs.umich.edu                raise
18943105Sstever@eecs.umich.edu            self.connect(realPeer)
18953105Sstever@eecs.umich.edu
18963101Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
18973101Sstever@eecs.umich.edu    def ccConnect(self):
18988597Ssteve.reinhardt@amd.com        from m5.internal.pyobject import connectPorts
18994762Snate@binkert.org
19008839Sandreas.hansson@arm.com        if self.role == 'SLAVE':
19018839Sandreas.hansson@arm.com            # do nothing and let the master take care of it
19028839Sandreas.hansson@arm.com            return
19038839Sandreas.hansson@arm.com
19043101Sstever@eecs.umich.edu        if self.ccConnected: # already done this
19053101Sstever@eecs.umich.edu            return
19063101Sstever@eecs.umich.edu        peer = self.peer
19075578SSteve.Reinhardt@amd.com        if not self.peer: # nothing to connect to
19085578SSteve.Reinhardt@amd.com            return
19098839Sandreas.hansson@arm.com
19108839Sandreas.hansson@arm.com        # check that we connect a master to a slave
19118839Sandreas.hansson@arm.com        if self.role == peer.role:
19128839Sandreas.hansson@arm.com            raise TypeError, \
19138839Sandreas.hansson@arm.com                "cannot connect '%s' and '%s' due to identical role '%s'" \
19148839Sandreas.hansson@arm.com                % (peer, self, self.role)
19158839Sandreas.hansson@arm.com
19167526Ssteve.reinhardt@amd.com        try:
19178839Sandreas.hansson@arm.com            # self is always the master and peer the slave
19187526Ssteve.reinhardt@amd.com            connectPorts(self.simobj.getCCObject(), self.name, self.index,
19197526Ssteve.reinhardt@amd.com                         peer.simobj.getCCObject(), peer.name, peer.index)
19207526Ssteve.reinhardt@amd.com        except:
19217526Ssteve.reinhardt@amd.com            print "Error connecting port %s.%s to %s.%s" % \
19227526Ssteve.reinhardt@amd.com                  (self.simobj.path(), self.name,
19237526Ssteve.reinhardt@amd.com                   peer.simobj.path(), peer.name)
19247526Ssteve.reinhardt@amd.com            raise
19253101Sstever@eecs.umich.edu        self.ccConnected = True
19263101Sstever@eecs.umich.edu        peer.ccConnected = True
19273101Sstever@eecs.umich.edu
19283105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
19293105Sstever@eecs.umich.edu# PortRef, but has an index.
19303105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
19318839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role, index):
19328839Sandreas.hansson@arm.com        PortRef.__init__(self, simobj, name, role)
19333105Sstever@eecs.umich.edu        self.index = index
19343105Sstever@eecs.umich.edu
19353105Sstever@eecs.umich.edu    def __str__(self):
19363105Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
19373105Sstever@eecs.umich.edu
19383105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
19393105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
19403105Sstever@eecs.umich.educlass VectorPortRef(object):
19418839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
19423105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
19433105Sstever@eecs.umich.edu        self.simobj = simobj
19443105Sstever@eecs.umich.edu        self.name = name
19458839Sandreas.hansson@arm.com        self.role = role
19463105Sstever@eecs.umich.edu        self.elements = []
19473105Sstever@eecs.umich.edu
19483109Sstever@eecs.umich.edu    def __str__(self):
19493109Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
19503109Sstever@eecs.umich.edu
19518840Sandreas.hansson@arm.com    def __len__(self):
19528840Sandreas.hansson@arm.com        # Return the number of connected peers, corresponding the the
19538840Sandreas.hansson@arm.com        # length of the elements.
19548840Sandreas.hansson@arm.com        return len(self.elements)
19558840Sandreas.hansson@arm.com
19563105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
19573105Sstever@eecs.umich.edu    def ini_str(self):
19583105Sstever@eecs.umich.edu        return ' '.join([el.ini_str() for el in self.elements])
19593105Sstever@eecs.umich.edu
19609017Sandreas.hansson@arm.com    # for config.json
19619017Sandreas.hansson@arm.com    def get_config_as_dict(self):
19629017Sandreas.hansson@arm.com        return {'role' : self.role,
19639017Sandreas.hansson@arm.com                'peer' : [el.ini_str() for el in self.elements]}
19649017Sandreas.hansson@arm.com
19653105Sstever@eecs.umich.edu    def __getitem__(self, key):
19663105Sstever@eecs.umich.edu        if not isinstance(key, int):
19673105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
19683105Sstever@eecs.umich.edu        if key >= len(self.elements):
19693105Sstever@eecs.umich.edu            # need to extend list
19708839Sandreas.hansson@arm.com            ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
19713105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
19723105Sstever@eecs.umich.edu            self.elements.extend(ext)
19733105Sstever@eecs.umich.edu        return self.elements[key]
19743105Sstever@eecs.umich.edu
19753105Sstever@eecs.umich.edu    def _get_next(self):
19763105Sstever@eecs.umich.edu        return self[len(self.elements)]
19773105Sstever@eecs.umich.edu
19783105Sstever@eecs.umich.edu    def __setitem__(self, key, value):
19793105Sstever@eecs.umich.edu        if not isinstance(key, int):
19803105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
19813105Sstever@eecs.umich.edu        self[key].connect(value)
19823105Sstever@eecs.umich.edu
19833105Sstever@eecs.umich.edu    def connect(self, other):
19843109Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
19853109Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
19863109Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
19873109Sstever@eecs.umich.edu            # or if it should replace the current vector.
19883109Sstever@eecs.umich.edu            for ref in other:
19893109Sstever@eecs.umich.edu                self._get_next().connect(ref)
19903109Sstever@eecs.umich.edu        else:
19913109Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
19923109Sstever@eecs.umich.edu            self._get_next().connect(other)
19933109Sstever@eecs.umich.edu
19943109Sstever@eecs.umich.edu    def clone(self, simobj, memo):
19953109Sstever@eecs.umich.edu        if memo.has_key(self):
19963109Sstever@eecs.umich.edu            return memo[self]
19973109Sstever@eecs.umich.edu        newRef = copy.copy(self)
19983109Sstever@eecs.umich.edu        memo[self] = newRef
19993109Sstever@eecs.umich.edu        newRef.simobj = simobj
20003109Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
20013109Sstever@eecs.umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
20023109Sstever@eecs.umich.edu        return newRef
20033105Sstever@eecs.umich.edu
20043105Sstever@eecs.umich.edu    def unproxy(self, simobj):
20053105Sstever@eecs.umich.edu        [el.unproxy(simobj) for el in self.elements]
20063105Sstever@eecs.umich.edu
20073105Sstever@eecs.umich.edu    def ccConnect(self):
20083105Sstever@eecs.umich.edu        [el.ccConnect() for el in self.elements]
20093105Sstever@eecs.umich.edu
20103101Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
20113101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a
20123101Sstever@eecs.umich.edu# SimObject instance.  The latter are represented by PortRef objects.
20133101Sstever@eecs.umich.educlass Port(object):
20143101Sstever@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
20153101Sstever@eecs.umich.edu    # given name
20163105Sstever@eecs.umich.edu    def makeRef(self, simobj):
20178839Sandreas.hansson@arm.com        return PortRef(simobj, self.name, self.role)
20183101Sstever@eecs.umich.edu
20193101Sstever@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
20203101Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
20213105Sstever@eecs.umich.edu    def connect(self, simobj, ref):
20223105Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
20233101Sstever@eecs.umich.edu
20248840Sandreas.hansson@arm.com    # No need for any pre-declarations at the moment as we merely rely
20258840Sandreas.hansson@arm.com    # on an unsigned int.
20268840Sandreas.hansson@arm.com    def cxx_predecls(self, code):
20278840Sandreas.hansson@arm.com        pass
20288840Sandreas.hansson@arm.com
20298840Sandreas.hansson@arm.com    # Declare an unsigned int with the same name as the port, that
20308840Sandreas.hansson@arm.com    # will eventually hold the number of connected ports (and thus the
20318840Sandreas.hansson@arm.com    # number of elements for a VectorPort).
20328840Sandreas.hansson@arm.com    def cxx_decl(self, code):
20338840Sandreas.hansson@arm.com        code('unsigned int port_${{self.name}}_connection_count;')
20348840Sandreas.hansson@arm.com
20358839Sandreas.hansson@arm.comclass MasterPort(Port):
20368839Sandreas.hansson@arm.com    # MasterPort("description")
20378839Sandreas.hansson@arm.com    def __init__(self, *args):
20388839Sandreas.hansson@arm.com        if len(args) == 1:
20398839Sandreas.hansson@arm.com            self.desc = args[0]
20408839Sandreas.hansson@arm.com            self.role = 'MASTER'
20418839Sandreas.hansson@arm.com        else:
20428839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20438839Sandreas.hansson@arm.com
20448839Sandreas.hansson@arm.comclass SlavePort(Port):
20458839Sandreas.hansson@arm.com    # SlavePort("description")
20468839Sandreas.hansson@arm.com    def __init__(self, *args):
20478839Sandreas.hansson@arm.com        if len(args) == 1:
20488839Sandreas.hansson@arm.com            self.desc = args[0]
20498839Sandreas.hansson@arm.com            self.role = 'SLAVE'
20508839Sandreas.hansson@arm.com        else:
20518839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20528839Sandreas.hansson@arm.com
20533101Sstever@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
205410405Sandreas.hansson@arm.com# of connections (e.g., as on a XBar).
20553101Sstever@eecs.umich.educlass VectorPort(Port):
20563105Sstever@eecs.umich.edu    def __init__(self, *args):
20573101Sstever@eecs.umich.edu        self.isVec = True
20583101Sstever@eecs.umich.edu
20593105Sstever@eecs.umich.edu    def makeRef(self, simobj):
20608839Sandreas.hansson@arm.com        return VectorPortRef(simobj, self.name, self.role)
20618839Sandreas.hansson@arm.com
20628839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort):
20638839Sandreas.hansson@arm.com    # VectorMasterPort("description")
20648839Sandreas.hansson@arm.com    def __init__(self, *args):
20658839Sandreas.hansson@arm.com        if len(args) == 1:
20668839Sandreas.hansson@arm.com            self.desc = args[0]
20678839Sandreas.hansson@arm.com            self.role = 'MASTER'
20688839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
20698839Sandreas.hansson@arm.com        else:
20708839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20718839Sandreas.hansson@arm.com
20728839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort):
20738839Sandreas.hansson@arm.com    # VectorSlavePort("description")
20748839Sandreas.hansson@arm.com    def __init__(self, *args):
20758839Sandreas.hansson@arm.com        if len(args) == 1:
20768839Sandreas.hansson@arm.com            self.desc = args[0]
20778839Sandreas.hansson@arm.com            self.role = 'SLAVE'
20788839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
20798839Sandreas.hansson@arm.com        else:
20808839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
20813105Sstever@eecs.umich.edu
20823109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
20833109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
20843109Sstever@eecs.umich.edu# make sense.
20853109Sstever@eecs.umich.educlass PortParamDesc(object):
20863109Sstever@eecs.umich.edu    __metaclass__ = Singleton
20873109Sstever@eecs.umich.edu
20883109Sstever@eecs.umich.edu    ptype_str = 'Port'
20893109Sstever@eecs.umich.edu    ptype = Port
20903105Sstever@eecs.umich.edu
20916654Snate@binkert.orgbaseEnums = allEnums.copy()
20926654Snate@binkert.orgbaseParams = allParams.copy()
20936654Snate@binkert.org
20946654Snate@binkert.orgdef clear():
20956654Snate@binkert.org    global allEnums, allParams
20966654Snate@binkert.org
20976654Snate@binkert.org    allEnums = baseEnums.copy()
20986654Snate@binkert.org    allParams = baseParams.copy()
20996654Snate@binkert.org
21003101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam',
21013101Sstever@eecs.umich.edu           'Enum', 'Bool', 'String', 'Float',
21023101Sstever@eecs.umich.edu           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
21033101Sstever@eecs.umich.edu           'Int32', 'UInt32', 'Int64', 'UInt64',
21043101Sstever@eecs.umich.edu           'Counter', 'Addr', 'Tick', 'Percent',
21053101Sstever@eecs.umich.edu           'TcpPort', 'UdpPort', 'EthernetAddr',
21067777Sgblack@eecs.umich.edu           'IpAddress', 'IpNetmask', 'IpWithPort',
21073101Sstever@eecs.umich.edu           'MemorySize', 'MemorySize32',
21089827Sakash.bagdia@arm.com           'Latency', 'Frequency', 'Clock', 'Voltage',
21093101Sstever@eecs.umich.edu           'NetworkBandwidth', 'MemoryBandwidth',
21109232Sandreas.hansson@arm.com           'AddrRange',
21113101Sstever@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
21123885Sbinkertn@umich.edu           'Time',
21133102Sstever@eecs.umich.edu           'NextEthernetAddr', 'NULL',
21148839Sandreas.hansson@arm.com           'MasterPort', 'SlavePort',
21158839Sandreas.hansson@arm.com           'VectorMasterPort', 'VectorSlavePort']
21166654Snate@binkert.org
21176654Snate@binkert.orgimport SimObject
2118