params.py revision 10201
19544Sandreas.hansson@arm.com# Copyright (c) 2012-2013 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
963101Sstever@eecs.umich.edu
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
1173101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
1183101Sstever@eecs.umich.edu    # if they're really proxies or not
1193101Sstever@eecs.umich.edu    def unproxy(self, base):
1203101Sstever@eecs.umich.edu        return self
1213101Sstever@eecs.umich.edu
1223101Sstever@eecs.umich.edu# Regular parameter description.
1233101Sstever@eecs.umich.educlass ParamDesc(object):
1243101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1253101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1263101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1273101Sstever@eecs.umich.edu        if ptype != None:
1283101Sstever@eecs.umich.edu            self.ptype = ptype
1293101Sstever@eecs.umich.edu
1303101Sstever@eecs.umich.edu        if args:
1313101Sstever@eecs.umich.edu            if len(args) == 1:
1323101Sstever@eecs.umich.edu                self.desc = args[0]
1333101Sstever@eecs.umich.edu            elif len(args) == 2:
1343101Sstever@eecs.umich.edu                self.default = args[0]
1353101Sstever@eecs.umich.edu                self.desc = args[1]
1363101Sstever@eecs.umich.edu            else:
1373101Sstever@eecs.umich.edu                raise TypeError, 'too many arguments'
1383101Sstever@eecs.umich.edu
1393101Sstever@eecs.umich.edu        if kwargs.has_key('desc'):
1403101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1413101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1423101Sstever@eecs.umich.edu            del kwargs['desc']
1433101Sstever@eecs.umich.edu
1443101Sstever@eecs.umich.edu        if kwargs.has_key('default'):
1453101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1463101Sstever@eecs.umich.edu            self.default = kwargs['default']
1473101Sstever@eecs.umich.edu            del kwargs['default']
1483101Sstever@eecs.umich.edu
1493101Sstever@eecs.umich.edu        if kwargs:
1503101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1513101Sstever@eecs.umich.edu
1523101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
1533101Sstever@eecs.umich.edu            raise TypeError, 'desc attribute missing'
1543101Sstever@eecs.umich.edu
1553101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1563101Sstever@eecs.umich.edu        if attr == 'ptype':
1575033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1586656Snate@binkert.org            assert isSimObjectClass(ptype)
1595033Smilesck@eecs.umich.edu            self.ptype = ptype
1605033Smilesck@eecs.umich.edu            return ptype
1615033Smilesck@eecs.umich.edu
1623101Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
1633101Sstever@eecs.umich.edu              (type(self).__name__, attr)
1643101Sstever@eecs.umich.edu
1653101Sstever@eecs.umich.edu    def convert(self, value):
1663101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
1673101Sstever@eecs.umich.edu            value.set_param_desc(self)
1683101Sstever@eecs.umich.edu            return value
1693101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
1703101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
1713101Sstever@eecs.umich.edu            # we're just assigning a null pointer
1723101Sstever@eecs.umich.edu            return value
1733101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
1743101Sstever@eecs.umich.edu            return value
1753102Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
1763101Sstever@eecs.umich.edu            return value
1773101Sstever@eecs.umich.edu        return self.ptype(value)
1783101Sstever@eecs.umich.edu
1797673Snate@binkert.org    def cxx_predecls(self, code):
1808607Sgblack@eecs.umich.edu        code('#include <cstddef>')
1817673Snate@binkert.org        self.ptype.cxx_predecls(code)
1823101Sstever@eecs.umich.edu
1837673Snate@binkert.org    def swig_predecls(self, code):
1847673Snate@binkert.org        self.ptype.swig_predecls(code)
1853101Sstever@eecs.umich.edu
1867673Snate@binkert.org    def cxx_decl(self, code):
1877673Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
1883101Sstever@eecs.umich.edu
1893101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
1903101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
1913101Sstever@eecs.umich.edu# single value.
1923101Sstever@eecs.umich.edu
1933101Sstever@eecs.umich.educlass VectorParamValue(list):
1945033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
1955475Snate@binkert.org    def __setattr__(self, attr, value):
1965475Snate@binkert.org        raise AttributeError, \
1975475Snate@binkert.org              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
1985475Snate@binkert.org
1993101Sstever@eecs.umich.edu    def ini_str(self):
2003101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
2013101Sstever@eecs.umich.edu
2024762Snate@binkert.org    def getValue(self):
2034762Snate@binkert.org        return [ v.getValue() for v in self ]
2044762Snate@binkert.org
2053101Sstever@eecs.umich.edu    def unproxy(self, base):
2068460SAli.Saidi@ARM.com        if len(self) == 1 and isinstance(self[0], proxy.AllProxy):
2078459SAli.Saidi@ARM.com            return self[0].unproxy(base)
2088459SAli.Saidi@ARM.com        else:
2098459SAli.Saidi@ARM.com             return [v.unproxy(base) for v in self]
2103101Sstever@eecs.umich.edu
2117528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
2127528Ssteve.reinhardt@amd.com    # support clone operation
2137528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
2147528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
2157528Ssteve.reinhardt@amd.com
2167528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
2173101Sstever@eecs.umich.edu        for v in self:
2187528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
2197528Ssteve.reinhardt@amd.com
2207528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
2217528Ssteve.reinhardt@amd.com        if len(self) == 1:
2227528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2237528Ssteve.reinhardt@amd.com        else:
2247528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2257528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2267528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2277528Ssteve.reinhardt@amd.com
2288321Ssteve.reinhardt@amd.com    def has_parent(self):
2298321Ssteve.reinhardt@amd.com        return reduce(lambda x,y: x and y, [v.has_parent() for v in self])
2307528Ssteve.reinhardt@amd.com
2317528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2327528Ssteve.reinhardt@amd.com    def get_name(self):
2337528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2347528Ssteve.reinhardt@amd.com
2357528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2367528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2377528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2387528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2397528Ssteve.reinhardt@amd.com    def descendants(self):
2407528Ssteve.reinhardt@amd.com        for v in self:
2417528Ssteve.reinhardt@amd.com            for obj in v.descendants():
2427528Ssteve.reinhardt@amd.com                yield obj
2433101Sstever@eecs.umich.edu
2448664SAli.Saidi@ARM.com    def get_config_as_dict(self):
2458664SAli.Saidi@ARM.com        a = []
2468664SAli.Saidi@ARM.com        for v in self:
2478664SAli.Saidi@ARM.com            a.append(v.get_config_as_dict())
2488664SAli.Saidi@ARM.com        return a
2498664SAli.Saidi@ARM.com
2509953Sgeoffrey.blake@arm.com    # If we are replacing an item in the vector, make sure to set the
2519953Sgeoffrey.blake@arm.com    # parent reference of the new SimObject to be the same as the parent
2529953Sgeoffrey.blake@arm.com    # of the SimObject being replaced. Useful to have if we created
2539953Sgeoffrey.blake@arm.com    # a SimObjectVector of temporary objects that will be modified later in
2549953Sgeoffrey.blake@arm.com    # configuration scripts.
2559953Sgeoffrey.blake@arm.com    def __setitem__(self, key, value):
2569953Sgeoffrey.blake@arm.com        val = self[key]
2579953Sgeoffrey.blake@arm.com        if value.has_parent():
2589953Sgeoffrey.blake@arm.com            warn("SimObject %s already has a parent" % value.get_name() +\
2599953Sgeoffrey.blake@arm.com                 " that is being overwritten by a SimObjectVector")
2609953Sgeoffrey.blake@arm.com        value.set_parent(val.get_parent(), val._name)
2619953Sgeoffrey.blake@arm.com        super(SimObjectVector, self).__setitem__(key, value)
2629953Sgeoffrey.blake@arm.com
2633101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
2643101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
2653101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
2663101Sstever@eecs.umich.edu    def convert(self, value):
2673101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
2683101Sstever@eecs.umich.edu            # list: coerce each element into new list
2693101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
2703101Sstever@eecs.umich.edu        else:
2714762Snate@binkert.org            # singleton: coerce to a single-element list
2724762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
2734762Snate@binkert.org
2744762Snate@binkert.org        if isSimObjectSequence(tmp_list):
2757528Ssteve.reinhardt@amd.com            return SimObjectVector(tmp_list)
2764762Snate@binkert.org        else:
2774762Snate@binkert.org            return VectorParamValue(tmp_list)
2784762Snate@binkert.org
2798596Ssteve.reinhardt@amd.com    def swig_module_name(self):
2808596Ssteve.reinhardt@amd.com        return "%s_vector" % self.ptype_str
2818596Ssteve.reinhardt@amd.com
2827673Snate@binkert.org    def swig_predecls(self, code):
2838596Ssteve.reinhardt@amd.com        code('%import "${{self.swig_module_name()}}.i"')
2844762Snate@binkert.org
2857673Snate@binkert.org    def swig_decl(self, code):
2868596Ssteve.reinhardt@amd.com        code('%module(package="m5.internal") ${{self.swig_module_name()}}')
2877675Snate@binkert.org        code('%{')
2887675Snate@binkert.org        self.ptype.cxx_predecls(code)
2897675Snate@binkert.org        code('%}')
2907675Snate@binkert.org        code()
2918656Sandreas.hansson@arm.com        # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
2928656Sandreas.hansson@arm.com        code('%include "std_container.i"')
2938656Sandreas.hansson@arm.com        code()
2947675Snate@binkert.org        self.ptype.swig_predecls(code)
2957675Snate@binkert.org        code()
2967673Snate@binkert.org        code('%include "std_vector.i"')
2977675Snate@binkert.org        code()
2987675Snate@binkert.org
2997675Snate@binkert.org        ptype = self.ptype_str
3007675Snate@binkert.org        cxx_type = self.ptype.cxx_type
3017675Snate@binkert.org
3027675Snate@binkert.org        code('%template(vector_$ptype) std::vector< $cxx_type >;')
3037675Snate@binkert.org
3047673Snate@binkert.org    def cxx_predecls(self, code):
3057673Snate@binkert.org        code('#include <vector>')
3067673Snate@binkert.org        self.ptype.cxx_predecls(code)
3073101Sstever@eecs.umich.edu
3087673Snate@binkert.org    def cxx_decl(self, code):
3097673Snate@binkert.org        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
3103101Sstever@eecs.umich.edu
3113101Sstever@eecs.umich.educlass ParamFactory(object):
3123101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
3133101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
3143101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
3153101Sstever@eecs.umich.edu
3163101Sstever@eecs.umich.edu    def __getattr__(self, attr):
3173101Sstever@eecs.umich.edu        if self.ptype_str:
3183101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
3193101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
3203101Sstever@eecs.umich.edu
3213101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
3223101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
3233101Sstever@eecs.umich.edu        ptype = None
3243101Sstever@eecs.umich.edu        try:
3255033Smilesck@eecs.umich.edu            ptype = allParams[self.ptype_str]
3265033Smilesck@eecs.umich.edu        except KeyError:
3273101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
3283101Sstever@eecs.umich.edu            # try to resolve it later
3293101Sstever@eecs.umich.edu            pass
3303101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
3313101Sstever@eecs.umich.edu
3323101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
3333101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
3343101Sstever@eecs.umich.edu
3353101Sstever@eecs.umich.edu#####################################################################
3363101Sstever@eecs.umich.edu#
3373101Sstever@eecs.umich.edu# Parameter Types
3383101Sstever@eecs.umich.edu#
3393101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
3403101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
3413101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
3423101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
3433101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
3443101Sstever@eecs.umich.edu# the __str__() conversion method).
3453101Sstever@eecs.umich.edu#
3463101Sstever@eecs.umich.edu#####################################################################
3473101Sstever@eecs.umich.edu
3483101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
3493101Sstever@eecs.umich.edu# built-in str class.
3503101Sstever@eecs.umich.educlass String(ParamValue,str):
3513101Sstever@eecs.umich.edu    cxx_type = 'std::string'
3527673Snate@binkert.org
3537673Snate@binkert.org    @classmethod
3547673Snate@binkert.org    def cxx_predecls(self, code):
3557673Snate@binkert.org        code('#include <string>')
3567673Snate@binkert.org
3577673Snate@binkert.org    @classmethod
3587673Snate@binkert.org    def swig_predecls(cls, code):
3597673Snate@binkert.org        code('%include "std_string.i"')
3604762Snate@binkert.org
3614762Snate@binkert.org    def getValue(self):
3624762Snate@binkert.org        return self
3633101Sstever@eecs.umich.edu
3643101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
3653101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
3663101Sstever@eecs.umich.edu# a new Latency object.
3673101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
3683101Sstever@eecs.umich.edu    def __str__(self):
3693101Sstever@eecs.umich.edu        return str(self.value)
3703101Sstever@eecs.umich.edu
3713101Sstever@eecs.umich.edu    def __float__(self):
3723101Sstever@eecs.umich.edu        return float(self.value)
3733101Sstever@eecs.umich.edu
3743714Sstever@eecs.umich.edu    def __long__(self):
3753714Sstever@eecs.umich.edu        return long(self.value)
3763714Sstever@eecs.umich.edu
3773714Sstever@eecs.umich.edu    def __int__(self):
3783714Sstever@eecs.umich.edu        return int(self.value)
3793714Sstever@eecs.umich.edu
3803101Sstever@eecs.umich.edu    # hook for bounds checking
3813101Sstever@eecs.umich.edu    def _check(self):
3823101Sstever@eecs.umich.edu        return
3833101Sstever@eecs.umich.edu
3843101Sstever@eecs.umich.edu    def __mul__(self, other):
3853101Sstever@eecs.umich.edu        newobj = self.__class__(self)
3863101Sstever@eecs.umich.edu        newobj.value *= other
3873101Sstever@eecs.umich.edu        newobj._check()
3883101Sstever@eecs.umich.edu        return newobj
3893101Sstever@eecs.umich.edu
3903101Sstever@eecs.umich.edu    __rmul__ = __mul__
3913101Sstever@eecs.umich.edu
3923101Sstever@eecs.umich.edu    def __div__(self, other):
3933101Sstever@eecs.umich.edu        newobj = self.__class__(self)
3943101Sstever@eecs.umich.edu        newobj.value /= other
3953101Sstever@eecs.umich.edu        newobj._check()
3963101Sstever@eecs.umich.edu        return newobj
3973101Sstever@eecs.umich.edu
3983101Sstever@eecs.umich.edu    def __sub__(self, other):
3993101Sstever@eecs.umich.edu        newobj = self.__class__(self)
4003101Sstever@eecs.umich.edu        newobj.value -= other
4013101Sstever@eecs.umich.edu        newobj._check()
4023101Sstever@eecs.umich.edu        return newobj
4033101Sstever@eecs.umich.edu
4043101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
4055033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue):
4063101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
4073101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
4083101Sstever@eecs.umich.edu
4093101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
4103101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
4113101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
4123101Sstever@eecs.umich.edu        if name == 'CheckedInt':
4133101Sstever@eecs.umich.edu            return
4143101Sstever@eecs.umich.edu
4153101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
4163101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
4173101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
4185822Ssaidi@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
4195822Ssaidi@eecs.umich.edu                      name);
4203101Sstever@eecs.umich.edu            if cls.unsigned:
4213101Sstever@eecs.umich.edu                cls.min = 0
4223101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
4233101Sstever@eecs.umich.edu            else:
4243101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
4253101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
4263101Sstever@eecs.umich.edu
4273101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
4283101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
4293101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
4303101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
4313101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue):
4323101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
4333101Sstever@eecs.umich.edu
4343101Sstever@eecs.umich.edu    def _check(self):
4353101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
4363101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
4373101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
4383101Sstever@eecs.umich.edu
4393101Sstever@eecs.umich.edu    def __init__(self, value):
4403101Sstever@eecs.umich.edu        if isinstance(value, str):
4413102Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
4423714Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
4433101Sstever@eecs.umich.edu            self.value = long(value)
4443714Sstever@eecs.umich.edu        else:
4453714Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to CheckedInt" \
4463714Sstever@eecs.umich.edu                  % type(value).__name__
4473101Sstever@eecs.umich.edu        self._check()
4483101Sstever@eecs.umich.edu
4497673Snate@binkert.org    @classmethod
4507673Snate@binkert.org    def cxx_predecls(cls, code):
4517673Snate@binkert.org        # most derived types require this, so we just do it here once
4527673Snate@binkert.org        code('#include "base/types.hh"')
4537673Snate@binkert.org
4547673Snate@binkert.org    @classmethod
4557673Snate@binkert.org    def swig_predecls(cls, code):
4567673Snate@binkert.org        # most derived types require this, so we just do it here once
4577673Snate@binkert.org        code('%import "stdint.i"')
4587673Snate@binkert.org        code('%import "base/types.hh"')
4597673Snate@binkert.org
4604762Snate@binkert.org    def getValue(self):
4614762Snate@binkert.org        return long(self.value)
4624762Snate@binkert.org
4633101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
4643101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
4653101Sstever@eecs.umich.edu
4663101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
4673101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
4683101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
4693101Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
4703101Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
4713101Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
4723101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
4733101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
4743101Sstever@eecs.umich.edu
4753101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
4763101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
4773101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
4783101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
4793101Sstever@eecs.umich.edu
4803101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
4813101Sstever@eecs.umich.edu
4829184Sandreas.hansson@arm.comclass Cycles(CheckedInt):
4839184Sandreas.hansson@arm.com    cxx_type = 'Cycles'
4849184Sandreas.hansson@arm.com    size = 64
4859184Sandreas.hansson@arm.com    unsigned = True
4869184Sandreas.hansson@arm.com
4879184Sandreas.hansson@arm.com    def getValue(self):
4889184Sandreas.hansson@arm.com        from m5.internal.core import Cycles
4899184Sandreas.hansson@arm.com        return Cycles(self.value)
4909184Sandreas.hansson@arm.com
4913101Sstever@eecs.umich.educlass Float(ParamValue, float):
4924446Sbinkertn@umich.edu    cxx_type = 'double'
4933101Sstever@eecs.umich.edu
4945468Snate@binkert.org    def __init__(self, value):
4955468Snate@binkert.org        if isinstance(value, (int, long, float, NumericParamValue, Float)):
4965468Snate@binkert.org            self.value = float(value)
4975468Snate@binkert.org        else:
4985468Snate@binkert.org            raise TypeError, "Can't convert object of type %s to Float" \
4995468Snate@binkert.org                  % type(value).__name__
5005468Snate@binkert.org
5014762Snate@binkert.org    def getValue(self):
5024762Snate@binkert.org        return float(self.value)
5034762Snate@binkert.org
5043101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
5053101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
5063101Sstever@eecs.umich.edu    size = 64
5073101Sstever@eecs.umich.edu    unsigned = True
5083101Sstever@eecs.umich.edu    def __init__(self, value):
5093101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
5103101Sstever@eecs.umich.edu            self.value = value.value
5113101Sstever@eecs.umich.edu        else:
5123102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
5133101Sstever@eecs.umich.edu        self._check()
5143101Sstever@eecs.umich.edu
5153101Sstever@eecs.umich.educlass MemorySize32(CheckedInt):
5164168Sbinkertn@umich.edu    cxx_type = 'uint32_t'
5173101Sstever@eecs.umich.edu    size = 32
5183101Sstever@eecs.umich.edu    unsigned = True
5193101Sstever@eecs.umich.edu    def __init__(self, value):
5203101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
5213101Sstever@eecs.umich.edu            self.value = value.value
5223101Sstever@eecs.umich.edu        else:
5233102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
5243101Sstever@eecs.umich.edu        self._check()
5253101Sstever@eecs.umich.edu
5263101Sstever@eecs.umich.educlass Addr(CheckedInt):
5273101Sstever@eecs.umich.edu    cxx_type = 'Addr'
5283101Sstever@eecs.umich.edu    size = 64
5293101Sstever@eecs.umich.edu    unsigned = True
5303101Sstever@eecs.umich.edu    def __init__(self, value):
5313101Sstever@eecs.umich.edu        if isinstance(value, Addr):
5323101Sstever@eecs.umich.edu            self.value = value.value
5333101Sstever@eecs.umich.edu        else:
5343101Sstever@eecs.umich.edu            try:
5353102Sstever@eecs.umich.edu                self.value = convert.toMemorySize(value)
5363101Sstever@eecs.umich.edu            except TypeError:
5373101Sstever@eecs.umich.edu                self.value = long(value)
5383101Sstever@eecs.umich.edu        self._check()
5393584Ssaidi@eecs.umich.edu    def __add__(self, other):
5403584Ssaidi@eecs.umich.edu        if isinstance(other, Addr):
5413584Ssaidi@eecs.umich.edu            return self.value + other.value
5423584Ssaidi@eecs.umich.edu        else:
5433584Ssaidi@eecs.umich.edu            return self.value + other
5443101Sstever@eecs.umich.edu
5459232Sandreas.hansson@arm.comclass AddrRange(ParamValue):
5469235Sandreas.hansson@arm.com    cxx_type = 'AddrRange'
5473101Sstever@eecs.umich.edu
5483101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
5499411Sandreas.hansson@arm.com        # Disable interleaving by default
5509411Sandreas.hansson@arm.com        self.intlvHighBit = 0
5519411Sandreas.hansson@arm.com        self.intlvBits = 0
5529411Sandreas.hansson@arm.com        self.intlvMatch = 0
5539411Sandreas.hansson@arm.com
5543101Sstever@eecs.umich.edu        def handle_kwargs(self, kwargs):
5559411Sandreas.hansson@arm.com            # An address range needs to have an upper limit, specified
5569411Sandreas.hansson@arm.com            # either explicitly with an end, or as an offset using the
5579411Sandreas.hansson@arm.com            # size keyword.
5583101Sstever@eecs.umich.edu            if 'end' in kwargs:
5599232Sandreas.hansson@arm.com                self.end = Addr(kwargs.pop('end'))
5603101Sstever@eecs.umich.edu            elif 'size' in kwargs:
5619232Sandreas.hansson@arm.com                self.end = self.start + Addr(kwargs.pop('size')) - 1
5623101Sstever@eecs.umich.edu            else:
5633101Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
5643101Sstever@eecs.umich.edu
5659411Sandreas.hansson@arm.com            # Now on to the optional bit
5669411Sandreas.hansson@arm.com            if 'intlvHighBit' in kwargs:
5679411Sandreas.hansson@arm.com                self.intlvHighBit = int(kwargs.pop('intlvHighBit'))
5689411Sandreas.hansson@arm.com            if 'intlvBits' in kwargs:
5699411Sandreas.hansson@arm.com                self.intlvBits = int(kwargs.pop('intlvBits'))
5709411Sandreas.hansson@arm.com            if 'intlvMatch' in kwargs:
5719411Sandreas.hansson@arm.com                self.intlvMatch = int(kwargs.pop('intlvMatch'))
5729411Sandreas.hansson@arm.com
5733101Sstever@eecs.umich.edu        if len(args) == 0:
5749232Sandreas.hansson@arm.com            self.start = Addr(kwargs.pop('start'))
5753101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
5763101Sstever@eecs.umich.edu
5773101Sstever@eecs.umich.edu        elif len(args) == 1:
5783101Sstever@eecs.umich.edu            if kwargs:
5799232Sandreas.hansson@arm.com                self.start = Addr(args[0])
5803101Sstever@eecs.umich.edu                handle_kwargs(self, kwargs)
5815219Ssaidi@eecs.umich.edu            elif isinstance(args[0], (list, tuple)):
5829232Sandreas.hansson@arm.com                self.start = Addr(args[0][0])
5839232Sandreas.hansson@arm.com                self.end = Addr(args[0][1])
5843101Sstever@eecs.umich.edu            else:
5859232Sandreas.hansson@arm.com                self.start = Addr(0)
5869232Sandreas.hansson@arm.com                self.end = Addr(args[0]) - 1
5873101Sstever@eecs.umich.edu
5883101Sstever@eecs.umich.edu        elif len(args) == 2:
5899232Sandreas.hansson@arm.com            self.start = Addr(args[0])
5909232Sandreas.hansson@arm.com            self.end = Addr(args[1])
5913101Sstever@eecs.umich.edu        else:
5923101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
5933101Sstever@eecs.umich.edu
5943101Sstever@eecs.umich.edu        if kwargs:
5959232Sandreas.hansson@arm.com            raise TypeError, "Too many keywords: %s" % kwargs.keys()
5963101Sstever@eecs.umich.edu
5973101Sstever@eecs.umich.edu    def __str__(self):
5989232Sandreas.hansson@arm.com        return '%s:%s' % (self.start, self.end)
5999232Sandreas.hansson@arm.com
6009232Sandreas.hansson@arm.com    def size(self):
6019411Sandreas.hansson@arm.com        # Divide the size by the size of the interleaving slice
6029411Sandreas.hansson@arm.com        return (long(self.end) - long(self.start) + 1) >> self.intlvBits
6033101Sstever@eecs.umich.edu
6047673Snate@binkert.org    @classmethod
6057673Snate@binkert.org    def cxx_predecls(cls, code):
6069232Sandreas.hansson@arm.com        Addr.cxx_predecls(code)
6079235Sandreas.hansson@arm.com        code('#include "base/addr_range.hh"')
6087675Snate@binkert.org
6097675Snate@binkert.org    @classmethod
6107675Snate@binkert.org    def swig_predecls(cls, code):
6119232Sandreas.hansson@arm.com        Addr.swig_predecls(code)
6127673Snate@binkert.org
6134762Snate@binkert.org    def getValue(self):
6149235Sandreas.hansson@arm.com        # Go from the Python class to the wrapped C++ class generated
6159235Sandreas.hansson@arm.com        # by swig
6167675Snate@binkert.org        from m5.internal.range import AddrRange
6174762Snate@binkert.org
6189411Sandreas.hansson@arm.com        return AddrRange(long(self.start), long(self.end),
6199411Sandreas.hansson@arm.com                         int(self.intlvHighBit), int(self.intlvBits),
6209411Sandreas.hansson@arm.com                         int(self.intlvMatch))
6213101Sstever@eecs.umich.edu
6223101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
6233101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and
6243101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
6253101Sstever@eecs.umich.educlass Bool(ParamValue):
6263101Sstever@eecs.umich.edu    cxx_type = 'bool'
6273101Sstever@eecs.umich.edu    def __init__(self, value):
6283101Sstever@eecs.umich.edu        try:
6293102Sstever@eecs.umich.edu            self.value = convert.toBool(value)
6303101Sstever@eecs.umich.edu        except TypeError:
6313101Sstever@eecs.umich.edu            self.value = bool(value)
6323101Sstever@eecs.umich.edu
6334762Snate@binkert.org    def getValue(self):
6344762Snate@binkert.org        return bool(self.value)
6354762Snate@binkert.org
6363101Sstever@eecs.umich.edu    def __str__(self):
6373101Sstever@eecs.umich.edu        return str(self.value)
6383101Sstever@eecs.umich.edu
6398934SBrad.Beckmann@amd.com    # implement truth value testing for Bool parameters so that these params
6408934SBrad.Beckmann@amd.com    # evaluate correctly during the python configuration phase
6418934SBrad.Beckmann@amd.com    def __nonzero__(self):
6428934SBrad.Beckmann@amd.com        return bool(self.value)
6438934SBrad.Beckmann@amd.com
6443101Sstever@eecs.umich.edu    def ini_str(self):
6453101Sstever@eecs.umich.edu        if self.value:
6463101Sstever@eecs.umich.edu            return 'true'
6473101Sstever@eecs.umich.edu        return 'false'
6483101Sstever@eecs.umich.edu
6493101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
6503101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
6513101Sstever@eecs.umich.edu    bytes[5] += val
6523101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
6533101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
6543101Sstever@eecs.umich.edu        bytes[i] = rem
6553101Sstever@eecs.umich.edu        if val == 0:
6563101Sstever@eecs.umich.edu            break
6573101Sstever@eecs.umich.edu        bytes[i - 1] += val
6583101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
6593101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
6603101Sstever@eecs.umich.edu
6614380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
6624380Sbinkertn@umich.edudef NextEthernetAddr():
6634380Sbinkertn@umich.edu    global _NextEthernetAddr
6643101Sstever@eecs.umich.edu
6654380Sbinkertn@umich.edu    value = _NextEthernetAddr
6664380Sbinkertn@umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
6674380Sbinkertn@umich.edu    return value
6683101Sstever@eecs.umich.edu
6693101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
6703101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
6717673Snate@binkert.org
6727673Snate@binkert.org    @classmethod
6737673Snate@binkert.org    def cxx_predecls(cls, code):
6747673Snate@binkert.org        code('#include "base/inet.hh"')
6757673Snate@binkert.org
6767673Snate@binkert.org    @classmethod
6777673Snate@binkert.org    def swig_predecls(cls, code):
6787673Snate@binkert.org        code('%include "python/swig/inet.i"')
6797673Snate@binkert.org
6803101Sstever@eecs.umich.edu    def __init__(self, value):
6813101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
6823101Sstever@eecs.umich.edu            self.value = value
6833101Sstever@eecs.umich.edu            return
6843101Sstever@eecs.umich.edu
6853101Sstever@eecs.umich.edu        if not isinstance(value, str):
6863101Sstever@eecs.umich.edu            raise TypeError, "expected an ethernet address and didn't get one"
6873101Sstever@eecs.umich.edu
6883101Sstever@eecs.umich.edu        bytes = value.split(':')
6893101Sstever@eecs.umich.edu        if len(bytes) != 6:
6903101Sstever@eecs.umich.edu            raise TypeError, 'invalid ethernet address %s' % value
6913101Sstever@eecs.umich.edu
6923101Sstever@eecs.umich.edu        for byte in bytes:
6939941SGeoffrey.Blake@arm.com            if not 0 <= int(byte, base=16) <= 0xff:
6943101Sstever@eecs.umich.edu                raise TypeError, 'invalid ethernet address %s' % value
6953101Sstever@eecs.umich.edu
6963101Sstever@eecs.umich.edu        self.value = value
6973101Sstever@eecs.umich.edu
6983101Sstever@eecs.umich.edu    def unproxy(self, base):
6993101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
7004380Sbinkertn@umich.edu            return EthernetAddr(self.value())
7013101Sstever@eecs.umich.edu        return self
7023101Sstever@eecs.umich.edu
7034762Snate@binkert.org    def getValue(self):
7047677Snate@binkert.org        from m5.internal.params import EthAddr
7054762Snate@binkert.org        return EthAddr(self.value)
7064762Snate@binkert.org
7074380Sbinkertn@umich.edu    def ini_str(self):
7084380Sbinkertn@umich.edu        return self.value
7093101Sstever@eecs.umich.edu
7107777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
7117777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
7127777Sgblack@eecs.umich.educlass IpAddress(ParamValue):
7137777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpAddress'
7147777Sgblack@eecs.umich.edu
7157777Sgblack@eecs.umich.edu    @classmethod
7167777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
7177777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
7187777Sgblack@eecs.umich.edu
7197777Sgblack@eecs.umich.edu    @classmethod
7207777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
7217777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
7227777Sgblack@eecs.umich.edu
7237777Sgblack@eecs.umich.edu    def __init__(self, value):
7247777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
7257777Sgblack@eecs.umich.edu            self.ip = value.ip
7267777Sgblack@eecs.umich.edu        else:
7277777Sgblack@eecs.umich.edu            try:
7287777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
7297777Sgblack@eecs.umich.edu            except TypeError:
7307777Sgblack@eecs.umich.edu                self.ip = long(value)
7317777Sgblack@eecs.umich.edu        self.verifyIp()
7327777Sgblack@eecs.umich.edu
7338579Ssteve.reinhardt@amd.com    def __str__(self):
7348579Ssteve.reinhardt@amd.com        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
7358579Ssteve.reinhardt@amd.com        return '%d.%d.%d.%d' % tuple(tup)
7368579Ssteve.reinhardt@amd.com
7378579Ssteve.reinhardt@amd.com    def __eq__(self, other):
7388579Ssteve.reinhardt@amd.com        if isinstance(other, IpAddress):
7398579Ssteve.reinhardt@amd.com            return self.ip == other.ip
7408579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
7418579Ssteve.reinhardt@amd.com            try:
7428579Ssteve.reinhardt@amd.com                return self.ip == convert.toIpAddress(other)
7438579Ssteve.reinhardt@amd.com            except:
7448579Ssteve.reinhardt@amd.com                return False
7458579Ssteve.reinhardt@amd.com        else:
7468579Ssteve.reinhardt@amd.com            return self.ip == other
7478579Ssteve.reinhardt@amd.com
7488579Ssteve.reinhardt@amd.com    def __ne__(self, other):
7498579Ssteve.reinhardt@amd.com        return not (self == other)
7508579Ssteve.reinhardt@amd.com
7517777Sgblack@eecs.umich.edu    def verifyIp(self):
7527777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
7537798Sgblack@eecs.umich.edu            raise TypeError, "invalid ip address %#08x" % self.ip
7547777Sgblack@eecs.umich.edu
7557777Sgblack@eecs.umich.edu    def getValue(self):
7567777Sgblack@eecs.umich.edu        from m5.internal.params import IpAddress
7577777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
7587777Sgblack@eecs.umich.edu
7597777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
7607777Sgblack@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
7617777Sgblack@eecs.umich.edu# positional or keyword arguments.
7627777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
7637777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
7647777Sgblack@eecs.umich.edu
7657777Sgblack@eecs.umich.edu    @classmethod
7667777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
7677777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
7687777Sgblack@eecs.umich.edu
7697777Sgblack@eecs.umich.edu    @classmethod
7707777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
7717777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
7727777Sgblack@eecs.umich.edu
7737777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
7747777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
7757777Sgblack@eecs.umich.edu            if key in kwargs:
7767777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
7777777Sgblack@eecs.umich.edu            elif elseVal:
7787777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
7797777Sgblack@eecs.umich.edu            else:
7807777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
7817777Sgblack@eecs.umich.edu
7827777Sgblack@eecs.umich.edu        if len(args) == 0:
7837777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
7847777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
7857777Sgblack@eecs.umich.edu
7867777Sgblack@eecs.umich.edu        elif len(args) == 1:
7877777Sgblack@eecs.umich.edu            if kwargs:
7887777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
7897777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
7907777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
7917777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
7927777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
7937777Sgblack@eecs.umich.edu                self.ip = args[0].ip
7947777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
7957777Sgblack@eecs.umich.edu            else:
7967777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
7977777Sgblack@eecs.umich.edu
7987777Sgblack@eecs.umich.edu        elif len(args) == 2:
7997777Sgblack@eecs.umich.edu            self.ip = args[0]
8007777Sgblack@eecs.umich.edu            self.netmask = args[1]
8017777Sgblack@eecs.umich.edu        else:
8027777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
8037777Sgblack@eecs.umich.edu
8047777Sgblack@eecs.umich.edu        if kwargs:
8057777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
8067777Sgblack@eecs.umich.edu
8077777Sgblack@eecs.umich.edu        self.verify()
8087777Sgblack@eecs.umich.edu
8098579Ssteve.reinhardt@amd.com    def __str__(self):
8108579Ssteve.reinhardt@amd.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
8118579Ssteve.reinhardt@amd.com
8128579Ssteve.reinhardt@amd.com    def __eq__(self, other):
8138579Ssteve.reinhardt@amd.com        if isinstance(other, IpNetmask):
8148579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.netmask == other.netmask
8158579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
8168579Ssteve.reinhardt@amd.com            try:
8178579Ssteve.reinhardt@amd.com                return (self.ip, self.netmask) == convert.toIpNetmask(other)
8188579Ssteve.reinhardt@amd.com            except:
8198579Ssteve.reinhardt@amd.com                return False
8208579Ssteve.reinhardt@amd.com        else:
8218579Ssteve.reinhardt@amd.com            return False
8228579Ssteve.reinhardt@amd.com
8237777Sgblack@eecs.umich.edu    def verify(self):
8247777Sgblack@eecs.umich.edu        self.verifyIp()
8257777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
8267777Sgblack@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
8277777Sgblack@eecs.umich.edu
8287777Sgblack@eecs.umich.edu    def getValue(self):
8297777Sgblack@eecs.umich.edu        from m5.internal.params import IpNetmask
8307777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
8317777Sgblack@eecs.umich.edu
8327777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
8337777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
8347777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
8357777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
8367777Sgblack@eecs.umich.edu
8377777Sgblack@eecs.umich.edu    @classmethod
8387777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
8397777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
8407777Sgblack@eecs.umich.edu
8417777Sgblack@eecs.umich.edu    @classmethod
8427777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
8437777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
8447777Sgblack@eecs.umich.edu
8457777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
8467777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
8477777Sgblack@eecs.umich.edu            if key in kwargs:
8487777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
8497777Sgblack@eecs.umich.edu            elif elseVal:
8507777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
8517777Sgblack@eecs.umich.edu            else:
8527777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
8537777Sgblack@eecs.umich.edu
8547777Sgblack@eecs.umich.edu        if len(args) == 0:
8557777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
8567777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
8577777Sgblack@eecs.umich.edu
8587777Sgblack@eecs.umich.edu        elif len(args) == 1:
8597777Sgblack@eecs.umich.edu            if kwargs:
8607777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
8617777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
8627777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
8637777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
8647777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpWithPort):
8657777Sgblack@eecs.umich.edu                self.ip = args[0].ip
8667777Sgblack@eecs.umich.edu                self.port = args[0].port
8677777Sgblack@eecs.umich.edu            else:
8687777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
8697777Sgblack@eecs.umich.edu
8707777Sgblack@eecs.umich.edu        elif len(args) == 2:
8717777Sgblack@eecs.umich.edu            self.ip = args[0]
8727777Sgblack@eecs.umich.edu            self.port = args[1]
8737777Sgblack@eecs.umich.edu        else:
8747777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
8757777Sgblack@eecs.umich.edu
8767777Sgblack@eecs.umich.edu        if kwargs:
8777777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
8787777Sgblack@eecs.umich.edu
8797777Sgblack@eecs.umich.edu        self.verify()
8807777Sgblack@eecs.umich.edu
8818579Ssteve.reinhardt@amd.com    def __str__(self):
8828579Ssteve.reinhardt@amd.com        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
8838579Ssteve.reinhardt@amd.com
8848579Ssteve.reinhardt@amd.com    def __eq__(self, other):
8858579Ssteve.reinhardt@amd.com        if isinstance(other, IpWithPort):
8868579Ssteve.reinhardt@amd.com            return self.ip == other.ip and self.port == other.port
8878579Ssteve.reinhardt@amd.com        elif isinstance(other, str):
8888579Ssteve.reinhardt@amd.com            try:
8898579Ssteve.reinhardt@amd.com                return (self.ip, self.port) == convert.toIpWithPort(other)
8908579Ssteve.reinhardt@amd.com            except:
8918579Ssteve.reinhardt@amd.com                return False
8928579Ssteve.reinhardt@amd.com        else:
8938579Ssteve.reinhardt@amd.com            return False
8948579Ssteve.reinhardt@amd.com
8957777Sgblack@eecs.umich.edu    def verify(self):
8967777Sgblack@eecs.umich.edu        self.verifyIp()
8977777Sgblack@eecs.umich.edu        if self.port < 0 or self.port > 0xffff:
8987777Sgblack@eecs.umich.edu            raise TypeError, "invalid port %d" % self.port
8997777Sgblack@eecs.umich.edu
9007777Sgblack@eecs.umich.edu    def getValue(self):
9017777Sgblack@eecs.umich.edu        from m5.internal.params import IpWithPort
9027777Sgblack@eecs.umich.edu        return IpWithPort(self.ip, self.port)
9037777Sgblack@eecs.umich.edu
9043932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
9053932Sbinkertn@umich.edu                 "%a %b %d %H:%M:%S %Z %Y",
9063932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
9073932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
9083932Sbinkertn@umich.edu                 "%Y/%m/%d",
9093932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
9103932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
9113932Sbinkertn@umich.edu                 "%m/%d/%Y",
9123932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M:%S",
9133932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M",
9143932Sbinkertn@umich.edu                 "%m/%d/%y"]
9153932Sbinkertn@umich.edu
9163932Sbinkertn@umich.edu
9173885Sbinkertn@umich.edudef parse_time(value):
9183932Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
9193932Sbinkertn@umich.edu    from datetime import datetime, date
9203885Sbinkertn@umich.edu
9213932Sbinkertn@umich.edu    if isinstance(value, struct_time):
9223932Sbinkertn@umich.edu        return value
9233932Sbinkertn@umich.edu
9243932Sbinkertn@umich.edu    if isinstance(value, (int, long)):
9253932Sbinkertn@umich.edu        return gmtime(value)
9263932Sbinkertn@umich.edu
9273932Sbinkertn@umich.edu    if isinstance(value, (datetime, date)):
9283932Sbinkertn@umich.edu        return value.timetuple()
9293932Sbinkertn@umich.edu
9303932Sbinkertn@umich.edu    if isinstance(value, str):
9313932Sbinkertn@umich.edu        if value in ('Now', 'Today'):
9323932Sbinkertn@umich.edu            return time.gmtime(time.time())
9333932Sbinkertn@umich.edu
9343932Sbinkertn@umich.edu        for format in time_formats:
9353932Sbinkertn@umich.edu            try:
9363932Sbinkertn@umich.edu                return strptime(value, format)
9373932Sbinkertn@umich.edu            except ValueError:
9383932Sbinkertn@umich.edu                pass
9393885Sbinkertn@umich.edu
9403885Sbinkertn@umich.edu    raise ValueError, "Could not parse '%s' as a time" % value
9413885Sbinkertn@umich.edu
9423885Sbinkertn@umich.educlass Time(ParamValue):
9434762Snate@binkert.org    cxx_type = 'tm'
9447673Snate@binkert.org
9457673Snate@binkert.org    @classmethod
9467673Snate@binkert.org    def cxx_predecls(cls, code):
9477673Snate@binkert.org        code('#include <time.h>')
9487673Snate@binkert.org
9497673Snate@binkert.org    @classmethod
9507673Snate@binkert.org    def swig_predecls(cls, code):
9517673Snate@binkert.org        code('%include "python/swig/time.i"')
9527673Snate@binkert.org
9533885Sbinkertn@umich.edu    def __init__(self, value):
9543932Sbinkertn@umich.edu        self.value = parse_time(value)
9553885Sbinkertn@umich.edu
9564762Snate@binkert.org    def getValue(self):
9577677Snate@binkert.org        from m5.internal.params import tm
9584762Snate@binkert.org
9594762Snate@binkert.org        c_time = tm()
9604762Snate@binkert.org        py_time = self.value
9614762Snate@binkert.org
9624762Snate@binkert.org        # UNIX is years since 1900
9634762Snate@binkert.org        c_time.tm_year = py_time.tm_year - 1900;
9644762Snate@binkert.org
9654762Snate@binkert.org        # Python starts at 1, UNIX starts at 0
9664762Snate@binkert.org        c_time.tm_mon =  py_time.tm_mon - 1;
9674762Snate@binkert.org        c_time.tm_mday = py_time.tm_mday;
9684762Snate@binkert.org        c_time.tm_hour = py_time.tm_hour;
9694762Snate@binkert.org        c_time.tm_min = py_time.tm_min;
9704762Snate@binkert.org        c_time.tm_sec = py_time.tm_sec;
9714762Snate@binkert.org
9724762Snate@binkert.org        # Python has 0 as Monday, UNIX is 0 as sunday
9734762Snate@binkert.org        c_time.tm_wday = py_time.tm_wday + 1
9744762Snate@binkert.org        if c_time.tm_wday > 6:
9754762Snate@binkert.org            c_time.tm_wday -= 7;
9764762Snate@binkert.org
9774762Snate@binkert.org        # Python starts at 1, Unix starts at 0
9784762Snate@binkert.org        c_time.tm_yday = py_time.tm_yday - 1;
9794762Snate@binkert.org
9804762Snate@binkert.org        return c_time
9814762Snate@binkert.org
9823885Sbinkertn@umich.edu    def __str__(self):
9834762Snate@binkert.org        return time.asctime(self.value)
9843885Sbinkertn@umich.edu
9853885Sbinkertn@umich.edu    def ini_str(self):
9863932Sbinkertn@umich.edu        return str(self)
9873885Sbinkertn@umich.edu
9888664SAli.Saidi@ARM.com    def get_config_as_dict(self):
9898664SAli.Saidi@ARM.com        return str(self)
9908664SAli.Saidi@ARM.com
9913101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
9923101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
9933101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
9943101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
9953101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
9963101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
9973101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
9983101Sstever@eecs.umich.edu
9993101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
10003101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
10013101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
10023101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
10033101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
10043101Sstever@eecs.umich.edu
10054762Snate@binkert.orgallEnums = {}
10063101Sstever@eecs.umich.edu# Metaclass for Enum types
10075033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue):
10084762Snate@binkert.org    def __new__(mcls, name, bases, dict):
10094762Snate@binkert.org        assert name not in allEnums
10104762Snate@binkert.org
10114762Snate@binkert.org        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
10124762Snate@binkert.org        allEnums[name] = cls
10134762Snate@binkert.org        return cls
10144762Snate@binkert.org
10153101Sstever@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
10163101Sstever@eecs.umich.edu        if init_dict.has_key('map'):
10173101Sstever@eecs.umich.edu            if not isinstance(cls.map, dict):
10183101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'map' " \
10193101Sstever@eecs.umich.edu                      "must be of type dict"
10203101Sstever@eecs.umich.edu            # build list of value strings from map
10213101Sstever@eecs.umich.edu            cls.vals = cls.map.keys()
10223101Sstever@eecs.umich.edu            cls.vals.sort()
10233101Sstever@eecs.umich.edu        elif init_dict.has_key('vals'):
10243101Sstever@eecs.umich.edu            if not isinstance(cls.vals, list):
10253101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'vals' " \
10263101Sstever@eecs.umich.edu                      "must be of type list"
10273101Sstever@eecs.umich.edu            # build string->value map from vals sequence
10283101Sstever@eecs.umich.edu            cls.map = {}
10293101Sstever@eecs.umich.edu            for idx,val in enumerate(cls.vals):
10303101Sstever@eecs.umich.edu                cls.map[val] = idx
10313101Sstever@eecs.umich.edu        else:
10323101Sstever@eecs.umich.edu            raise TypeError, "Enum-derived class must define "\
10333101Sstever@eecs.umich.edu                  "attribute 'map' or 'vals'"
10343101Sstever@eecs.umich.edu
10354762Snate@binkert.org        cls.cxx_type = 'Enums::%s' % name
10363101Sstever@eecs.umich.edu
10373101Sstever@eecs.umich.edu        super(MetaEnum, cls).__init__(name, bases, init_dict)
10383101Sstever@eecs.umich.edu
10393101Sstever@eecs.umich.edu    # Generate C++ class declaration for this enum type.
10403101Sstever@eecs.umich.edu    # Note that we wrap the enum in a class/struct to act as a namespace,
10413101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
10427673Snate@binkert.org    def cxx_decl(cls, code):
104310201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
104410201SAndrew.Bardsley@arm.com        wrapper = 'struct' if cls.wrapper_is_struct else 'namespace'
104510201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
104610201SAndrew.Bardsley@arm.com        idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name)
104710201SAndrew.Bardsley@arm.com
10487673Snate@binkert.org        code('''\
104910201SAndrew.Bardsley@arm.com#ifndef $idem_macro
105010201SAndrew.Bardsley@arm.com#define $idem_macro
10517673Snate@binkert.org
105210201SAndrew.Bardsley@arm.com$wrapper $wrapper_name {
10537673Snate@binkert.org    enum $name {
10547673Snate@binkert.org''')
10557673Snate@binkert.org        code.indent(2)
10564762Snate@binkert.org        for val in cls.vals:
10577673Snate@binkert.org            code('$val = ${{cls.map[val]}},')
10588902Sandreas.hansson@arm.com        code('Num_$name = ${{len(cls.vals)}}')
10597673Snate@binkert.org        code.dedent(2)
106010201SAndrew.Bardsley@arm.com        code('    };')
10614762Snate@binkert.org
106210201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
106310201SAndrew.Bardsley@arm.com            code('    static const char *${name}Strings[Num_${name}];')
106410201SAndrew.Bardsley@arm.com            code('};')
106510201SAndrew.Bardsley@arm.com        else:
106610201SAndrew.Bardsley@arm.com            code('extern const char *${name}Strings[Num_${name}];')
106710201SAndrew.Bardsley@arm.com            code('}')
106810201SAndrew.Bardsley@arm.com
106910201SAndrew.Bardsley@arm.com        code()
107010201SAndrew.Bardsley@arm.com        code('#endif // $idem_macro')
10717673Snate@binkert.org
10727673Snate@binkert.org    def cxx_def(cls, code):
107310201SAndrew.Bardsley@arm.com        wrapper_name = cls.wrapper_name
107410201SAndrew.Bardsley@arm.com        file_name = cls.__name__
107510201SAndrew.Bardsley@arm.com        name = cls.__name__ if cls.enum_name is None else cls.enum_name
107610201SAndrew.Bardsley@arm.com
107710201SAndrew.Bardsley@arm.com        code('#include "enums/$file_name.hh"')
107810201SAndrew.Bardsley@arm.com        if cls.wrapper_is_struct:
107910201SAndrew.Bardsley@arm.com            code('const char *${wrapper_name}::${name}Strings'
108010201SAndrew.Bardsley@arm.com                '[Num_${name}] =')
108110201SAndrew.Bardsley@arm.com        else:
108210201SAndrew.Bardsley@arm.com            code('namespace Enums {')
108310201SAndrew.Bardsley@arm.com            code.indent(1)
108410201SAndrew.Bardsley@arm.com            code(' const char *${name}Strings[Num_${name}] =')
108510201SAndrew.Bardsley@arm.com
108610201SAndrew.Bardsley@arm.com        code('{')
108710201SAndrew.Bardsley@arm.com        code.indent(1)
10884762Snate@binkert.org        for val in cls.vals:
10897673Snate@binkert.org            code('"$val",')
109010201SAndrew.Bardsley@arm.com        code.dedent(1)
109110201SAndrew.Bardsley@arm.com        code('};')
109210201SAndrew.Bardsley@arm.com
109310201SAndrew.Bardsley@arm.com        if not cls.wrapper_is_struct:
109410201SAndrew.Bardsley@arm.com            code('} // namespace $wrapper_name')
109510201SAndrew.Bardsley@arm.com            code.dedent(1)
10963101Sstever@eecs.umich.edu
10978596Ssteve.reinhardt@amd.com    def swig_decl(cls, code):
10988596Ssteve.reinhardt@amd.com        name = cls.__name__
10998596Ssteve.reinhardt@amd.com        code('''\
11008596Ssteve.reinhardt@amd.com%module(package="m5.internal") enum_$name
11018596Ssteve.reinhardt@amd.com
11028596Ssteve.reinhardt@amd.com%{
11038596Ssteve.reinhardt@amd.com#include "enums/$name.hh"
11048596Ssteve.reinhardt@amd.com%}
11058596Ssteve.reinhardt@amd.com
11068596Ssteve.reinhardt@amd.com%include "enums/$name.hh"
11078596Ssteve.reinhardt@amd.com''')
11088596Ssteve.reinhardt@amd.com
11098596Ssteve.reinhardt@amd.com
11103101Sstever@eecs.umich.edu# Base class for enum types.
11113101Sstever@eecs.umich.educlass Enum(ParamValue):
11123101Sstever@eecs.umich.edu    __metaclass__ = MetaEnum
11133101Sstever@eecs.umich.edu    vals = []
11143101Sstever@eecs.umich.edu
111510201SAndrew.Bardsley@arm.com    # The name of the wrapping namespace or struct
111610201SAndrew.Bardsley@arm.com    wrapper_name = 'Enums'
111710201SAndrew.Bardsley@arm.com
111810201SAndrew.Bardsley@arm.com    # If true, the enum is wrapped in a struct rather than a namespace
111910201SAndrew.Bardsley@arm.com    wrapper_is_struct = False
112010201SAndrew.Bardsley@arm.com
112110201SAndrew.Bardsley@arm.com    # If not None, use this as the enum name rather than this class name
112210201SAndrew.Bardsley@arm.com    enum_name = None
112310201SAndrew.Bardsley@arm.com
11243101Sstever@eecs.umich.edu    def __init__(self, value):
11253101Sstever@eecs.umich.edu        if value not in self.map:
11263101Sstever@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
11273101Sstever@eecs.umich.edu                  % (value, self.vals)
11283101Sstever@eecs.umich.edu        self.value = value
11293101Sstever@eecs.umich.edu
11307675Snate@binkert.org    @classmethod
11317675Snate@binkert.org    def cxx_predecls(cls, code):
11327675Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
11337675Snate@binkert.org
11347675Snate@binkert.org    @classmethod
11357675Snate@binkert.org    def swig_predecls(cls, code):
11367677Snate@binkert.org        code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
11377675Snate@binkert.org
11384762Snate@binkert.org    def getValue(self):
11394762Snate@binkert.org        return int(self.map[self.value])
11404762Snate@binkert.org
11413101Sstever@eecs.umich.edu    def __str__(self):
11423101Sstever@eecs.umich.edu        return self.value
11433101Sstever@eecs.umich.edu
11443101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it?
11453101Sstever@eecs.umich.edufrequency_tolerance = 0.001  # 0.1%
11463101Sstever@eecs.umich.edu
11474167Sbinkertn@umich.educlass TickParamValue(NumericParamValue):
11483101Sstever@eecs.umich.edu    cxx_type = 'Tick'
11497673Snate@binkert.org
11507673Snate@binkert.org    @classmethod
11517673Snate@binkert.org    def cxx_predecls(cls, code):
11527673Snate@binkert.org        code('#include "base/types.hh"')
11537673Snate@binkert.org
11547673Snate@binkert.org    @classmethod
11557673Snate@binkert.org    def swig_predecls(cls, code):
11567673Snate@binkert.org        code('%import "stdint.i"')
11577673Snate@binkert.org        code('%import "base/types.hh"')
11584167Sbinkertn@umich.edu
11594762Snate@binkert.org    def getValue(self):
11604762Snate@binkert.org        return long(self.value)
11614762Snate@binkert.org
11624167Sbinkertn@umich.educlass Latency(TickParamValue):
11633101Sstever@eecs.umich.edu    def __init__(self, value):
11644167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
11654167Sbinkertn@umich.edu            self.ticks = value.ticks
11664167Sbinkertn@umich.edu            self.value = value.value
11674167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
11684167Sbinkertn@umich.edu            self.ticks = value.ticks
11694167Sbinkertn@umich.edu            self.value = 1.0 / value.value
11704167Sbinkertn@umich.edu        elif value.endswith('t'):
11714167Sbinkertn@umich.edu            self.ticks = True
11724167Sbinkertn@umich.edu            self.value = int(value[:-1])
11734167Sbinkertn@umich.edu        else:
11744167Sbinkertn@umich.edu            self.ticks = False
11754167Sbinkertn@umich.edu            self.value = convert.toLatency(value)
11763101Sstever@eecs.umich.edu
11773101Sstever@eecs.umich.edu    def __getattr__(self, attr):
11783101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
11793101Sstever@eecs.umich.edu            return self
11803101Sstever@eecs.umich.edu        if attr == 'frequency':
11813101Sstever@eecs.umich.edu            return Frequency(self)
11823101Sstever@eecs.umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
11833101Sstever@eecs.umich.edu
11844762Snate@binkert.org    def getValue(self):
11854762Snate@binkert.org        if self.ticks or self.value == 0:
11864762Snate@binkert.org            value = self.value
11874762Snate@binkert.org        else:
11884762Snate@binkert.org            value = ticks.fromSeconds(self.value)
11894762Snate@binkert.org        return long(value)
11904762Snate@binkert.org
11913101Sstever@eecs.umich.edu    # convert latency to ticks
11923101Sstever@eecs.umich.edu    def ini_str(self):
11934762Snate@binkert.org        return '%d' % self.getValue()
11943101Sstever@eecs.umich.edu
11954167Sbinkertn@umich.educlass Frequency(TickParamValue):
11963101Sstever@eecs.umich.edu    def __init__(self, value):
11974167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
11984167Sbinkertn@umich.edu            if value.value == 0:
11994167Sbinkertn@umich.edu                self.value = 0
12004167Sbinkertn@umich.edu            else:
12014167Sbinkertn@umich.edu                self.value = 1.0 / value.value
12024167Sbinkertn@umich.edu            self.ticks = value.ticks
12034167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
12044167Sbinkertn@umich.edu            self.value = value.value
12054167Sbinkertn@umich.edu            self.ticks = value.ticks
12064167Sbinkertn@umich.edu        else:
12074167Sbinkertn@umich.edu            self.ticks = False
12084167Sbinkertn@umich.edu            self.value = convert.toFrequency(value)
12093101Sstever@eecs.umich.edu
12103101Sstever@eecs.umich.edu    def __getattr__(self, attr):
12113101Sstever@eecs.umich.edu        if attr == 'frequency':
12123101Sstever@eecs.umich.edu            return self
12133101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
12143101Sstever@eecs.umich.edu            return Latency(self)
12153101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
12163101Sstever@eecs.umich.edu
12174167Sbinkertn@umich.edu    # convert latency to ticks
12184762Snate@binkert.org    def getValue(self):
12194762Snate@binkert.org        if self.ticks or self.value == 0:
12204762Snate@binkert.org            value = self.value
12214762Snate@binkert.org        else:
12224762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
12234762Snate@binkert.org        return long(value)
12244762Snate@binkert.org
12253101Sstever@eecs.umich.edu    def ini_str(self):
12264762Snate@binkert.org        return '%d' % self.getValue()
12273101Sstever@eecs.umich.edu
122810019Sandreas.hansson@arm.com# A generic Frequency and/or Latency value. Value is stored as a
122910019Sandreas.hansson@arm.com# latency, just like Latency and Frequency.
123010019Sandreas.hansson@arm.comclass Clock(TickParamValue):
12313101Sstever@eecs.umich.edu    def __init__(self, value):
12324167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
12334167Sbinkertn@umich.edu            self.ticks = value.ticks
12344167Sbinkertn@umich.edu            self.value = value.value
12354167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
12364167Sbinkertn@umich.edu            self.ticks = value.ticks
12374167Sbinkertn@umich.edu            self.value = 1.0 / value.value
12384167Sbinkertn@umich.edu        elif value.endswith('t'):
12394167Sbinkertn@umich.edu            self.ticks = True
12404167Sbinkertn@umich.edu            self.value = int(value[:-1])
12414167Sbinkertn@umich.edu        else:
12424167Sbinkertn@umich.edu            self.ticks = False
12434167Sbinkertn@umich.edu            self.value = convert.anyToLatency(value)
12443101Sstever@eecs.umich.edu
12453101Sstever@eecs.umich.edu    def __getattr__(self, attr):
12463101Sstever@eecs.umich.edu        if attr == 'frequency':
12473101Sstever@eecs.umich.edu            return Frequency(self)
12483101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
12493101Sstever@eecs.umich.edu            return Latency(self)
12503101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
12513101Sstever@eecs.umich.edu
12524762Snate@binkert.org    def getValue(self):
12534762Snate@binkert.org        return self.period.getValue()
12544762Snate@binkert.org
12553101Sstever@eecs.umich.edu    def ini_str(self):
12563101Sstever@eecs.umich.edu        return self.period.ini_str()
12573101Sstever@eecs.umich.edu
12589827Sakash.bagdia@arm.comclass Voltage(float,ParamValue):
12599827Sakash.bagdia@arm.com    cxx_type = 'double'
12609827Sakash.bagdia@arm.com    def __new__(cls, value):
12619827Sakash.bagdia@arm.com        # convert to voltage
12629827Sakash.bagdia@arm.com        val = convert.toVoltage(value)
12639827Sakash.bagdia@arm.com        return super(cls, Voltage).__new__(cls, val)
12649827Sakash.bagdia@arm.com
12659827Sakash.bagdia@arm.com    def __str__(self):
12669827Sakash.bagdia@arm.com        return str(self.val)
12679827Sakash.bagdia@arm.com
12689827Sakash.bagdia@arm.com    def getValue(self):
12699827Sakash.bagdia@arm.com        value = float(self)
12709827Sakash.bagdia@arm.com        return value
12719827Sakash.bagdia@arm.com
12729827Sakash.bagdia@arm.com    def ini_str(self):
12739827Sakash.bagdia@arm.com        return '%f' % self.getValue()
12749827Sakash.bagdia@arm.com
12753101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
12763101Sstever@eecs.umich.edu    cxx_type = 'float'
12773101Sstever@eecs.umich.edu    def __new__(cls, value):
12784167Sbinkertn@umich.edu        # convert to bits per second
12794167Sbinkertn@umich.edu        val = convert.toNetworkBandwidth(value)
12803101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
12813101Sstever@eecs.umich.edu
12823101Sstever@eecs.umich.edu    def __str__(self):
12833101Sstever@eecs.umich.edu        return str(self.val)
12843101Sstever@eecs.umich.edu
12854762Snate@binkert.org    def getValue(self):
12864167Sbinkertn@umich.edu        # convert to seconds per byte
12874167Sbinkertn@umich.edu        value = 8.0 / float(self)
12884167Sbinkertn@umich.edu        # convert to ticks per byte
12894762Snate@binkert.org        value = ticks.fromSeconds(value)
12904762Snate@binkert.org        return float(value)
12914762Snate@binkert.org
12924762Snate@binkert.org    def ini_str(self):
12934762Snate@binkert.org        return '%f' % self.getValue()
12943101Sstever@eecs.umich.edu
12953101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
12963101Sstever@eecs.umich.edu    cxx_type = 'float'
12975469Snate@binkert.org    def __new__(cls, value):
12987743Sgblack@eecs.umich.edu        # convert to bytes per second
12993102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
13003101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
13013101Sstever@eecs.umich.edu
13023101Sstever@eecs.umich.edu    def __str__(self):
13033101Sstever@eecs.umich.edu        return str(self.val)
13043101Sstever@eecs.umich.edu
13054762Snate@binkert.org    def getValue(self):
13064167Sbinkertn@umich.edu        # convert to seconds per byte
13075468Snate@binkert.org        value = float(self)
13085468Snate@binkert.org        if value:
13095468Snate@binkert.org            value = 1.0 / float(self)
13104167Sbinkertn@umich.edu        # convert to ticks per byte
13114762Snate@binkert.org        value = ticks.fromSeconds(value)
13124762Snate@binkert.org        return float(value)
13134762Snate@binkert.org
13144762Snate@binkert.org    def ini_str(self):
13154762Snate@binkert.org        return '%f' % self.getValue()
13163101Sstever@eecs.umich.edu
13173101Sstever@eecs.umich.edu#
13183101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
13193101Sstever@eecs.umich.edu#
13203101Sstever@eecs.umich.edu
13213102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
13223102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
13233102Sstever@eecs.umich.edu# SimObject is required.
13243102Sstever@eecs.umich.edu# only one copy of a particular node
13253102Sstever@eecs.umich.educlass NullSimObject(object):
13263102Sstever@eecs.umich.edu    __metaclass__ = Singleton
13273102Sstever@eecs.umich.edu
13283102Sstever@eecs.umich.edu    def __call__(cls):
13293102Sstever@eecs.umich.edu        return cls
13303102Sstever@eecs.umich.edu
13313102Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
13323102Sstever@eecs.umich.edu        pass
13333102Sstever@eecs.umich.edu
13343102Sstever@eecs.umich.edu    def ini_str(self):
13353102Sstever@eecs.umich.edu        return 'Null'
13363102Sstever@eecs.umich.edu
13373102Sstever@eecs.umich.edu    def unproxy(self, base):
13383102Sstever@eecs.umich.edu        return self
13393102Sstever@eecs.umich.edu
13403102Sstever@eecs.umich.edu    def set_path(self, parent, name):
13413102Sstever@eecs.umich.edu        pass
13424762Snate@binkert.org
13433102Sstever@eecs.umich.edu    def __str__(self):
13443102Sstever@eecs.umich.edu        return 'Null'
13453102Sstever@eecs.umich.edu
13464762Snate@binkert.org    def getValue(self):
13474762Snate@binkert.org        return None
13484762Snate@binkert.org
13493102Sstever@eecs.umich.edu# The only instance you'll ever need...
13503102Sstever@eecs.umich.eduNULL = NullSimObject()
13513102Sstever@eecs.umich.edu
13523102Sstever@eecs.umich.edudef isNullPointer(value):
13533102Sstever@eecs.umich.edu    return isinstance(value, NullSimObject)
13543102Sstever@eecs.umich.edu
13553101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
13563101Sstever@eecs.umich.eduMaxAddr = Addr.max
13573101Sstever@eecs.umich.eduMaxTick = Tick.max
13583101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
13593101Sstever@eecs.umich.edu
13603101Sstever@eecs.umich.edu
13613101Sstever@eecs.umich.edu#####################################################################
13623101Sstever@eecs.umich.edu#
13633101Sstever@eecs.umich.edu# Port objects
13643101Sstever@eecs.umich.edu#
13653101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
13663101Sstever@eecs.umich.edu#
13673101Sstever@eecs.umich.edu#####################################################################
13683101Sstever@eecs.umich.edu
13693101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
13703101Sstever@eecs.umich.edu# particular SimObject.
13713101Sstever@eecs.umich.educlass PortRef(object):
13728839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
13733105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
13743101Sstever@eecs.umich.edu        self.simobj = simobj
13753101Sstever@eecs.umich.edu        self.name = name
13768839Sandreas.hansson@arm.com        self.role = role
13773101Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
13783101Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
13793105Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
13803101Sstever@eecs.umich.edu
13813103Sstever@eecs.umich.edu    def __str__(self):
13823105Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
13833103Sstever@eecs.umich.edu
13848840Sandreas.hansson@arm.com    def __len__(self):
13858840Sandreas.hansson@arm.com        # Return the number of connected ports, i.e. 0 is we have no
13868840Sandreas.hansson@arm.com        # peer and 1 if we do.
13878840Sandreas.hansson@arm.com        return int(self.peer != None)
13888840Sandreas.hansson@arm.com
13893105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
13903105Sstever@eecs.umich.edu    def ini_str(self):
13913105Sstever@eecs.umich.edu        return str(self.peer)
13923105Sstever@eecs.umich.edu
13939017Sandreas.hansson@arm.com    # for config.json
13949017Sandreas.hansson@arm.com    def get_config_as_dict(self):
13959017Sandreas.hansson@arm.com        return {'role' : self.role, 'peer' : str(self.peer)}
13969017Sandreas.hansson@arm.com
13973105Sstever@eecs.umich.edu    def __getattr__(self, attr):
13983105Sstever@eecs.umich.edu        if attr == 'peerObj':
13993105Sstever@eecs.umich.edu            # shorthand for proxies
14003105Sstever@eecs.umich.edu            return self.peer.simobj
14013105Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
14023105Sstever@eecs.umich.edu              (self.__class__.__name__, attr)
14033105Sstever@eecs.umich.edu
14043105Sstever@eecs.umich.edu    # Full connection is symmetric (both ways).  Called via
14053105Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
14063109Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
14073105Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
14083105Sstever@eecs.umich.edu    def connect(self, other):
14093105Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
14103105Sstever@eecs.umich.edu            # reference to plain VectorPort is implicit append
14113105Sstever@eecs.umich.edu            other = other._get_next()
14123105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
14139014Sandreas.hansson@arm.com            fatal("Port %s is already connected to %s, cannot connect %s\n",
14149014Sandreas.hansson@arm.com                  self, self.peer, other);
14153101Sstever@eecs.umich.edu        self.peer = other
14163109Sstever@eecs.umich.edu        if proxy.isproxy(other):
14173109Sstever@eecs.umich.edu            other.set_param_desc(PortParamDesc())
14183109Sstever@eecs.umich.edu        elif isinstance(other, PortRef):
14193109Sstever@eecs.umich.edu            if other.peer is not self:
14203109Sstever@eecs.umich.edu                other.connect(self)
14213109Sstever@eecs.umich.edu        else:
14223109Sstever@eecs.umich.edu            raise TypeError, \
14233109Sstever@eecs.umich.edu                  "assigning non-port reference '%s' to port '%s'" \
14243109Sstever@eecs.umich.edu                  % (other, self)
14253101Sstever@eecs.umich.edu
14263105Sstever@eecs.umich.edu    def clone(self, simobj, memo):
14273105Sstever@eecs.umich.edu        if memo.has_key(self):
14283105Sstever@eecs.umich.edu            return memo[self]
14293101Sstever@eecs.umich.edu        newRef = copy.copy(self)
14303105Sstever@eecs.umich.edu        memo[self] = newRef
14313105Sstever@eecs.umich.edu        newRef.simobj = simobj
14323101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
14333105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
14343179Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
14353105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
14363105Sstever@eecs.umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
14373101Sstever@eecs.umich.edu        return newRef
14383101Sstever@eecs.umich.edu
14393105Sstever@eecs.umich.edu    def unproxy(self, simobj):
14403105Sstever@eecs.umich.edu        assert(simobj is self.simobj)
14413105Sstever@eecs.umich.edu        if proxy.isproxy(self.peer):
14423105Sstever@eecs.umich.edu            try:
14433105Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
14443105Sstever@eecs.umich.edu            except:
14453105Sstever@eecs.umich.edu                print "Error in unproxying port '%s' of %s" % \
14463105Sstever@eecs.umich.edu                      (self.name, self.simobj.path())
14473105Sstever@eecs.umich.edu                raise
14483105Sstever@eecs.umich.edu            self.connect(realPeer)
14493105Sstever@eecs.umich.edu
14503101Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
14513101Sstever@eecs.umich.edu    def ccConnect(self):
14528597Ssteve.reinhardt@amd.com        from m5.internal.pyobject import connectPorts
14534762Snate@binkert.org
14548839Sandreas.hansson@arm.com        if self.role == 'SLAVE':
14558839Sandreas.hansson@arm.com            # do nothing and let the master take care of it
14568839Sandreas.hansson@arm.com            return
14578839Sandreas.hansson@arm.com
14583101Sstever@eecs.umich.edu        if self.ccConnected: # already done this
14593101Sstever@eecs.umich.edu            return
14603101Sstever@eecs.umich.edu        peer = self.peer
14615578SSteve.Reinhardt@amd.com        if not self.peer: # nothing to connect to
14625578SSteve.Reinhardt@amd.com            return
14638839Sandreas.hansson@arm.com
14648839Sandreas.hansson@arm.com        # check that we connect a master to a slave
14658839Sandreas.hansson@arm.com        if self.role == peer.role:
14668839Sandreas.hansson@arm.com            raise TypeError, \
14678839Sandreas.hansson@arm.com                "cannot connect '%s' and '%s' due to identical role '%s'" \
14688839Sandreas.hansson@arm.com                % (peer, self, self.role)
14698839Sandreas.hansson@arm.com
14707526Ssteve.reinhardt@amd.com        try:
14718839Sandreas.hansson@arm.com            # self is always the master and peer the slave
14727526Ssteve.reinhardt@amd.com            connectPorts(self.simobj.getCCObject(), self.name, self.index,
14737526Ssteve.reinhardt@amd.com                         peer.simobj.getCCObject(), peer.name, peer.index)
14747526Ssteve.reinhardt@amd.com        except:
14757526Ssteve.reinhardt@amd.com            print "Error connecting port %s.%s to %s.%s" % \
14767526Ssteve.reinhardt@amd.com                  (self.simobj.path(), self.name,
14777526Ssteve.reinhardt@amd.com                   peer.simobj.path(), peer.name)
14787526Ssteve.reinhardt@amd.com            raise
14793101Sstever@eecs.umich.edu        self.ccConnected = True
14803101Sstever@eecs.umich.edu        peer.ccConnected = True
14813101Sstever@eecs.umich.edu
14823105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
14833105Sstever@eecs.umich.edu# PortRef, but has an index.
14843105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
14858839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role, index):
14868839Sandreas.hansson@arm.com        PortRef.__init__(self, simobj, name, role)
14873105Sstever@eecs.umich.edu        self.index = index
14883105Sstever@eecs.umich.edu
14893105Sstever@eecs.umich.edu    def __str__(self):
14903105Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
14913105Sstever@eecs.umich.edu
14923105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
14933105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
14943105Sstever@eecs.umich.educlass VectorPortRef(object):
14958839Sandreas.hansson@arm.com    def __init__(self, simobj, name, role):
14963105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
14973105Sstever@eecs.umich.edu        self.simobj = simobj
14983105Sstever@eecs.umich.edu        self.name = name
14998839Sandreas.hansson@arm.com        self.role = role
15003105Sstever@eecs.umich.edu        self.elements = []
15013105Sstever@eecs.umich.edu
15023109Sstever@eecs.umich.edu    def __str__(self):
15033109Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
15043109Sstever@eecs.umich.edu
15058840Sandreas.hansson@arm.com    def __len__(self):
15068840Sandreas.hansson@arm.com        # Return the number of connected peers, corresponding the the
15078840Sandreas.hansson@arm.com        # length of the elements.
15088840Sandreas.hansson@arm.com        return len(self.elements)
15098840Sandreas.hansson@arm.com
15103105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
15113105Sstever@eecs.umich.edu    def ini_str(self):
15123105Sstever@eecs.umich.edu        return ' '.join([el.ini_str() for el in self.elements])
15133105Sstever@eecs.umich.edu
15149017Sandreas.hansson@arm.com    # for config.json
15159017Sandreas.hansson@arm.com    def get_config_as_dict(self):
15169017Sandreas.hansson@arm.com        return {'role' : self.role,
15179017Sandreas.hansson@arm.com                'peer' : [el.ini_str() for el in self.elements]}
15189017Sandreas.hansson@arm.com
15193105Sstever@eecs.umich.edu    def __getitem__(self, key):
15203105Sstever@eecs.umich.edu        if not isinstance(key, int):
15213105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
15223105Sstever@eecs.umich.edu        if key >= len(self.elements):
15233105Sstever@eecs.umich.edu            # need to extend list
15248839Sandreas.hansson@arm.com            ext = [VectorPortElementRef(self.simobj, self.name, self.role, i)
15253105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
15263105Sstever@eecs.umich.edu            self.elements.extend(ext)
15273105Sstever@eecs.umich.edu        return self.elements[key]
15283105Sstever@eecs.umich.edu
15293105Sstever@eecs.umich.edu    def _get_next(self):
15303105Sstever@eecs.umich.edu        return self[len(self.elements)]
15313105Sstever@eecs.umich.edu
15323105Sstever@eecs.umich.edu    def __setitem__(self, key, value):
15333105Sstever@eecs.umich.edu        if not isinstance(key, int):
15343105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
15353105Sstever@eecs.umich.edu        self[key].connect(value)
15363105Sstever@eecs.umich.edu
15373105Sstever@eecs.umich.edu    def connect(self, other):
15383109Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
15393109Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
15403109Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
15413109Sstever@eecs.umich.edu            # or if it should replace the current vector.
15423109Sstever@eecs.umich.edu            for ref in other:
15433109Sstever@eecs.umich.edu                self._get_next().connect(ref)
15443109Sstever@eecs.umich.edu        else:
15453109Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
15463109Sstever@eecs.umich.edu            self._get_next().connect(other)
15473109Sstever@eecs.umich.edu
15483109Sstever@eecs.umich.edu    def clone(self, simobj, memo):
15493109Sstever@eecs.umich.edu        if memo.has_key(self):
15503109Sstever@eecs.umich.edu            return memo[self]
15513109Sstever@eecs.umich.edu        newRef = copy.copy(self)
15523109Sstever@eecs.umich.edu        memo[self] = newRef
15533109Sstever@eecs.umich.edu        newRef.simobj = simobj
15543109Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
15553109Sstever@eecs.umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
15563109Sstever@eecs.umich.edu        return newRef
15573105Sstever@eecs.umich.edu
15583105Sstever@eecs.umich.edu    def unproxy(self, simobj):
15593105Sstever@eecs.umich.edu        [el.unproxy(simobj) for el in self.elements]
15603105Sstever@eecs.umich.edu
15613105Sstever@eecs.umich.edu    def ccConnect(self):
15623105Sstever@eecs.umich.edu        [el.ccConnect() for el in self.elements]
15633105Sstever@eecs.umich.edu
15643101Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
15653101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a
15663101Sstever@eecs.umich.edu# SimObject instance.  The latter are represented by PortRef objects.
15673101Sstever@eecs.umich.educlass Port(object):
15683101Sstever@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
15693101Sstever@eecs.umich.edu    # given name
15703105Sstever@eecs.umich.edu    def makeRef(self, simobj):
15718839Sandreas.hansson@arm.com        return PortRef(simobj, self.name, self.role)
15723101Sstever@eecs.umich.edu
15733101Sstever@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
15743101Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
15753105Sstever@eecs.umich.edu    def connect(self, simobj, ref):
15763105Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
15773101Sstever@eecs.umich.edu
15788840Sandreas.hansson@arm.com    # No need for any pre-declarations at the moment as we merely rely
15798840Sandreas.hansson@arm.com    # on an unsigned int.
15808840Sandreas.hansson@arm.com    def cxx_predecls(self, code):
15818840Sandreas.hansson@arm.com        pass
15828840Sandreas.hansson@arm.com
15838840Sandreas.hansson@arm.com    # Declare an unsigned int with the same name as the port, that
15848840Sandreas.hansson@arm.com    # will eventually hold the number of connected ports (and thus the
15858840Sandreas.hansson@arm.com    # number of elements for a VectorPort).
15868840Sandreas.hansson@arm.com    def cxx_decl(self, code):
15878840Sandreas.hansson@arm.com        code('unsigned int port_${{self.name}}_connection_count;')
15888840Sandreas.hansson@arm.com
15898839Sandreas.hansson@arm.comclass MasterPort(Port):
15908839Sandreas.hansson@arm.com    # MasterPort("description")
15918839Sandreas.hansson@arm.com    def __init__(self, *args):
15928839Sandreas.hansson@arm.com        if len(args) == 1:
15938839Sandreas.hansson@arm.com            self.desc = args[0]
15948839Sandreas.hansson@arm.com            self.role = 'MASTER'
15958839Sandreas.hansson@arm.com        else:
15968839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
15978839Sandreas.hansson@arm.com
15988839Sandreas.hansson@arm.comclass SlavePort(Port):
15998839Sandreas.hansson@arm.com    # SlavePort("description")
16008839Sandreas.hansson@arm.com    def __init__(self, *args):
16018839Sandreas.hansson@arm.com        if len(args) == 1:
16028839Sandreas.hansson@arm.com            self.desc = args[0]
16038839Sandreas.hansson@arm.com            self.role = 'SLAVE'
16048839Sandreas.hansson@arm.com        else:
16058839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
16068839Sandreas.hansson@arm.com
16073101Sstever@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
16083101Sstever@eecs.umich.edu# of connections (e.g., as on a Bus).
16093101Sstever@eecs.umich.educlass VectorPort(Port):
16103105Sstever@eecs.umich.edu    def __init__(self, *args):
16113101Sstever@eecs.umich.edu        self.isVec = True
16123101Sstever@eecs.umich.edu
16133105Sstever@eecs.umich.edu    def makeRef(self, simobj):
16148839Sandreas.hansson@arm.com        return VectorPortRef(simobj, self.name, self.role)
16158839Sandreas.hansson@arm.com
16168839Sandreas.hansson@arm.comclass VectorMasterPort(VectorPort):
16178839Sandreas.hansson@arm.com    # VectorMasterPort("description")
16188839Sandreas.hansson@arm.com    def __init__(self, *args):
16198839Sandreas.hansson@arm.com        if len(args) == 1:
16208839Sandreas.hansson@arm.com            self.desc = args[0]
16218839Sandreas.hansson@arm.com            self.role = 'MASTER'
16228839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
16238839Sandreas.hansson@arm.com        else:
16248839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
16258839Sandreas.hansson@arm.com
16268839Sandreas.hansson@arm.comclass VectorSlavePort(VectorPort):
16278839Sandreas.hansson@arm.com    # VectorSlavePort("description")
16288839Sandreas.hansson@arm.com    def __init__(self, *args):
16298839Sandreas.hansson@arm.com        if len(args) == 1:
16308839Sandreas.hansson@arm.com            self.desc = args[0]
16318839Sandreas.hansson@arm.com            self.role = 'SLAVE'
16328839Sandreas.hansson@arm.com            VectorPort.__init__(self, *args)
16338839Sandreas.hansson@arm.com        else:
16348839Sandreas.hansson@arm.com            raise TypeError, 'wrong number of arguments'
16353105Sstever@eecs.umich.edu
16363109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
16373109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
16383109Sstever@eecs.umich.edu# make sense.
16393109Sstever@eecs.umich.educlass PortParamDesc(object):
16403109Sstever@eecs.umich.edu    __metaclass__ = Singleton
16413109Sstever@eecs.umich.edu
16423109Sstever@eecs.umich.edu    ptype_str = 'Port'
16433109Sstever@eecs.umich.edu    ptype = Port
16443105Sstever@eecs.umich.edu
16456654Snate@binkert.orgbaseEnums = allEnums.copy()
16466654Snate@binkert.orgbaseParams = allParams.copy()
16476654Snate@binkert.org
16486654Snate@binkert.orgdef clear():
16496654Snate@binkert.org    global allEnums, allParams
16506654Snate@binkert.org
16516654Snate@binkert.org    allEnums = baseEnums.copy()
16526654Snate@binkert.org    allParams = baseParams.copy()
16536654Snate@binkert.org
16543101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam',
16553101Sstever@eecs.umich.edu           'Enum', 'Bool', 'String', 'Float',
16563101Sstever@eecs.umich.edu           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
16573101Sstever@eecs.umich.edu           'Int32', 'UInt32', 'Int64', 'UInt64',
16583101Sstever@eecs.umich.edu           'Counter', 'Addr', 'Tick', 'Percent',
16593101Sstever@eecs.umich.edu           'TcpPort', 'UdpPort', 'EthernetAddr',
16607777Sgblack@eecs.umich.edu           'IpAddress', 'IpNetmask', 'IpWithPort',
16613101Sstever@eecs.umich.edu           'MemorySize', 'MemorySize32',
16629827Sakash.bagdia@arm.com           'Latency', 'Frequency', 'Clock', 'Voltage',
16633101Sstever@eecs.umich.edu           'NetworkBandwidth', 'MemoryBandwidth',
16649232Sandreas.hansson@arm.com           'AddrRange',
16653101Sstever@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
16663885Sbinkertn@umich.edu           'Time',
16673102Sstever@eecs.umich.edu           'NextEthernetAddr', 'NULL',
16688839Sandreas.hansson@arm.com           'MasterPort', 'SlavePort',
16698839Sandreas.hansson@arm.com           'VectorMasterPort', 'VectorSlavePort']
16706654Snate@binkert.org
16716654Snate@binkert.orgimport SimObject
1672