params.py revision 8664
113558Snikos.nikoleris@arm.com# Copyright (c) 2004-2006 The Regents of The University of Michigan
28839Sandreas.hansson@arm.com# Copyright (c) 2010-2011 Advanced Micro Devices, Inc.
38839Sandreas.hansson@arm.com# All rights reserved.
48839Sandreas.hansson@arm.com#
58839Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without
68839Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are
78839Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright
88839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer;
98839Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright
108839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the
118839Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution;
128839Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its
133101Sstever@eecs.umich.edu# contributors may be used to endorse or promote products derived from
148579Ssteve.reinhardt@amd.com# this software without specific prior written permission.
153101Sstever@eecs.umich.edu#
163101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
173101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
183101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
193101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
203101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
213101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
223101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
233101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
243101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
253101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
263101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273101Sstever@eecs.umich.edu#
283101Sstever@eecs.umich.edu# Authors: Steve Reinhardt
293101Sstever@eecs.umich.edu#          Nathan Binkert
303101Sstever@eecs.umich.edu#          Gabe Black
313101Sstever@eecs.umich.edu
323101Sstever@eecs.umich.edu#####################################################################
333101Sstever@eecs.umich.edu#
343101Sstever@eecs.umich.edu# Parameter description classes
353101Sstever@eecs.umich.edu#
363101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either
373101Sstever@eecs.umich.edu# a Param or a VectorParam object.  These objects contain the
383101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default
393101Sstever@eecs.umich.edu# value (if any).  The convert() method on these objects is used to
403101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate
413101Sstever@eecs.umich.edu# type.
427778Sgblack@eecs.umich.edu#
438839Sandreas.hansson@arm.com# Note that the default values are loaded into the class's attribute
443101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in
453101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used.
463101Sstever@eecs.umich.edu#
473101Sstever@eecs.umich.edu#####################################################################
483101Sstever@eecs.umich.edu
493101Sstever@eecs.umich.eduimport copy
503101Sstever@eecs.umich.eduimport datetime
513101Sstever@eecs.umich.eduimport re
523101Sstever@eecs.umich.eduimport sys
533101Sstever@eecs.umich.eduimport time
543101Sstever@eecs.umich.eduimport math
553101Sstever@eecs.umich.edu
563101Sstever@eecs.umich.eduimport proxy
573101Sstever@eecs.umich.eduimport ticks
583101Sstever@eecs.umich.edufrom util import *
593101Sstever@eecs.umich.edu
603101Sstever@eecs.umich.edudef isSimObject(*args, **kwargs):
613101Sstever@eecs.umich.edu    return SimObject.isSimObject(*args, **kwargs)
6212563Sgabeblack@google.com
6312563Sgabeblack@google.comdef isSimObjectSequence(*args, **kwargs):
643885Sbinkertn@umich.edu    return SimObject.isSimObjectSequence(*args, **kwargs)
653885Sbinkertn@umich.edu
664762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs):
673885Sbinkertn@umich.edu    return SimObject.isSimObjectClass(*args, **kwargs)
683885Sbinkertn@umich.edu
697528Ssteve.reinhardt@amd.comallParams = {}
703885Sbinkertn@umich.edu
714380Sbinkertn@umich.educlass MetaParamValue(type):
724167Sbinkertn@umich.edu    def __new__(mcls, name, bases, dct):
733102Sstever@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
743101Sstever@eecs.umich.edu        assert name not in allParams
754762Snate@binkert.org        allParams[name] = cls
764762Snate@binkert.org        return cls
774762Snate@binkert.org
784762Snate@binkert.org
794762Snate@binkert.org# Dummy base class to identify types that are legitimate for SimObject
804762Snate@binkert.org# parameters.
814762Snate@binkert.orgclass ParamValue(object):
824762Snate@binkert.org    __metaclass__ = MetaParamValue
834762Snate@binkert.org
845033Smilesck@eecs.umich.edu
855033Smilesck@eecs.umich.edu    # Generate the code needed as a prerequisite for declaring a C++
865033Smilesck@eecs.umich.edu    # object of this type.  Typically generates one or more #include
875033Smilesck@eecs.umich.edu    # statements.  Used when declaring parameters of this type.
885033Smilesck@eecs.umich.edu    @classmethod
895033Smilesck@eecs.umich.edu    def cxx_predecls(cls, code):
905033Smilesck@eecs.umich.edu        pass
915033Smilesck@eecs.umich.edu
925033Smilesck@eecs.umich.edu    # Generate the code needed as a prerequisite for including a
935033Smilesck@eecs.umich.edu    # reference to a C++ object of this type in a SWIG .i file.
943101Sstever@eecs.umich.edu    # Typically generates one or more %import or %include statements.
953101Sstever@eecs.umich.edu    @classmethod
963101Sstever@eecs.umich.edu    def swig_predecls(cls, code):
975033Smilesck@eecs.umich.edu        pass
9810267SGeoffrey.Blake@arm.com
998596Ssteve.reinhardt@amd.com    # default for printing to .ini file is regular string conversion.
1008596Ssteve.reinhardt@amd.com    # will be overridden in some cases
1018596Ssteve.reinhardt@amd.com    def ini_str(self):
1028596Ssteve.reinhardt@amd.com        return str(self)
1037673Snate@binkert.org
1047673Snate@binkert.org    # allows us to blithely call unproxy() on things without checking
1057673Snate@binkert.org    # if they're really proxies or not
1067673Snate@binkert.org    def unproxy(self, base):
10711988Sandreas.sandberg@arm.com        return self
10811988Sandreas.sandberg@arm.com
10911988Sandreas.sandberg@arm.com# Regular parameter description.
11011988Sandreas.sandberg@arm.comclass ParamDesc(object):
1113101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1123101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1133101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1143101Sstever@eecs.umich.edu        if ptype != None:
1153101Sstever@eecs.umich.edu            self.ptype = ptype
11610380SAndrew.Bardsley@arm.com
11710380SAndrew.Bardsley@arm.com        if args:
11810380SAndrew.Bardsley@arm.com            if len(args) == 1:
11910380SAndrew.Bardsley@arm.com                self.desc = args[0]
12010380SAndrew.Bardsley@arm.com            elif len(args) == 2:
12110380SAndrew.Bardsley@arm.com                self.default = args[0]
12210458Sandreas.hansson@arm.com                self.desc = args[1]
12310458Sandreas.hansson@arm.com            else:
12410458Sandreas.hansson@arm.com                raise TypeError, 'too many arguments'
12510458Sandreas.hansson@arm.com
12610458Sandreas.hansson@arm.com        if kwargs.has_key('desc'):
12710458Sandreas.hansson@arm.com            assert(not hasattr(self, 'desc'))
12810458Sandreas.hansson@arm.com            self.desc = kwargs['desc']
12910458Sandreas.hansson@arm.com            del kwargs['desc']
13010458Sandreas.hansson@arm.com
13110458Sandreas.hansson@arm.com        if kwargs.has_key('default'):
13210458Sandreas.hansson@arm.com            assert(not hasattr(self, 'default'))
13310458Sandreas.hansson@arm.com            self.default = kwargs['default']
1343101Sstever@eecs.umich.edu            del kwargs['default']
1353101Sstever@eecs.umich.edu
1363101Sstever@eecs.umich.edu        if kwargs:
1373101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1383101Sstever@eecs.umich.edu
13910267SGeoffrey.Blake@arm.com        if not hasattr(self, 'desc'):
14010267SGeoffrey.Blake@arm.com            raise TypeError, 'desc attribute missing'
14110267SGeoffrey.Blake@arm.com
14210267SGeoffrey.Blake@arm.com    def __getattr__(self, attr):
1433101Sstever@eecs.umich.edu        if attr == 'ptype':
1443101Sstever@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1453101Sstever@eecs.umich.edu            assert isSimObjectClass(ptype)
1463101Sstever@eecs.umich.edu            self.ptype = ptype
1473101Sstever@eecs.umich.edu            return ptype
1483101Sstever@eecs.umich.edu
1493101Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
1503101Sstever@eecs.umich.edu              (type(self).__name__, attr)
1513101Sstever@eecs.umich.edu
1523101Sstever@eecs.umich.edu    def convert(self, value):
1533101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
1543101Sstever@eecs.umich.edu            value.set_param_desc(self)
1553101Sstever@eecs.umich.edu            return value
1563101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
1573101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
15813663Sandreas.sandberg@arm.com            # we're just assigning a null pointer
1593101Sstever@eecs.umich.edu            return value
16013675Sandreas.sandberg@arm.com        if isinstance(value, self.ptype):
1613101Sstever@eecs.umich.edu            return value
1623101Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
1633101Sstever@eecs.umich.edu            return value
1643101Sstever@eecs.umich.edu        return self.ptype(value)
16513675Sandreas.sandberg@arm.com
1663101Sstever@eecs.umich.edu    def cxx_predecls(self, code):
1673101Sstever@eecs.umich.edu        code('#include <cstddef>')
1683101Sstever@eecs.umich.edu        self.ptype.cxx_predecls(code)
1693101Sstever@eecs.umich.edu
1703101Sstever@eecs.umich.edu    def swig_predecls(self, code):
17113663Sandreas.sandberg@arm.com        self.ptype.swig_predecls(code)
1723101Sstever@eecs.umich.edu
1733101Sstever@eecs.umich.edu    def cxx_decl(self, code):
17413663Sandreas.sandberg@arm.com        code('${{self.ptype.cxx_type}} ${{self.name}};')
1753101Sstever@eecs.umich.edu
1763101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
1773101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
1785033Smilesck@eecs.umich.edu# single value.
1796656Snate@binkert.org
1805033Smilesck@eecs.umich.educlass VectorParamValue(list):
1815033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
1825033Smilesck@eecs.umich.edu    def __setattr__(self, attr, value):
18313663Sandreas.sandberg@arm.com        raise AttributeError, \
18413663Sandreas.sandberg@arm.com              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
1853101Sstever@eecs.umich.edu
18610267SGeoffrey.Blake@arm.com    def ini_str(self):
18710267SGeoffrey.Blake@arm.com        return ' '.join([v.ini_str() for v in self])
18810267SGeoffrey.Blake@arm.com
18910267SGeoffrey.Blake@arm.com    def getValue(self):
19010267SGeoffrey.Blake@arm.com        return [ v.getValue() for v in self ]
19110267SGeoffrey.Blake@arm.com
19210267SGeoffrey.Blake@arm.com    def unproxy(self, base):
19310267SGeoffrey.Blake@arm.com        if len(self) == 1 and isinstance(self[0], proxy.AllProxy):
19410267SGeoffrey.Blake@arm.com            return self[0].unproxy(base)
19510267SGeoffrey.Blake@arm.com        else:
19610267SGeoffrey.Blake@arm.com             return [v.unproxy(base) for v in self]
19710267SGeoffrey.Blake@arm.com
19810267SGeoffrey.Blake@arm.comclass SimObjectVector(VectorParamValue):
1993101Sstever@eecs.umich.edu    # support clone operation
2003101Sstever@eecs.umich.edu    def __call__(self, **kwargs):
2013101Sstever@eecs.umich.edu        return SimObjectVector([v(**kwargs) for v in self])
2023101Sstever@eecs.umich.edu
2033101Sstever@eecs.umich.edu    def clear_parent(self, old_parent):
2043101Sstever@eecs.umich.edu        for v in self:
2053101Sstever@eecs.umich.edu            v.clear_parent(old_parent)
2063101Sstever@eecs.umich.edu
2073101Sstever@eecs.umich.edu    def set_parent(self, parent, name):
2083101Sstever@eecs.umich.edu        if len(self) == 1:
2093102Sstever@eecs.umich.edu            self[0].set_parent(parent, name)
2103101Sstever@eecs.umich.edu        else:
2113101Sstever@eecs.umich.edu            width = int(math.ceil(math.log(len(self))/math.log(10)))
2123101Sstever@eecs.umich.edu            for i,v in enumerate(self):
21310267SGeoffrey.Blake@arm.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
21410267SGeoffrey.Blake@arm.com
21510267SGeoffrey.Blake@arm.com    def has_parent(self):
21610267SGeoffrey.Blake@arm.com        return reduce(lambda x,y: x and y, [v.has_parent() for v in self])
21710267SGeoffrey.Blake@arm.com
21810267SGeoffrey.Blake@arm.com    # return 'cpu0 cpu1' etc. for print_ini()
21910267SGeoffrey.Blake@arm.com    def get_name(self):
2207673Snate@binkert.org        return ' '.join([v._name for v in self])
2218607Sgblack@eecs.umich.edu
2227673Snate@binkert.org    # By iterating through the constituent members of the vector here
2233101Sstever@eecs.umich.edu    # we can nicely handle iterating over all a SimObject's children
22411988Sandreas.sandberg@arm.com    # without having to provide lots of special functions on
22511988Sandreas.sandberg@arm.com    # SimObjectVector directly.
22611988Sandreas.sandberg@arm.com    def descendants(self):
2277673Snate@binkert.org        for v in self:
2287673Snate@binkert.org            for obj in v.descendants():
2293101Sstever@eecs.umich.edu                yield obj
2303101Sstever@eecs.umich.edu
2313101Sstever@eecs.umich.edu    def get_config_as_dict(self):
2323101Sstever@eecs.umich.edu        a = []
2333101Sstever@eecs.umich.edu        for v in self:
2343101Sstever@eecs.umich.edu            a.append(v.get_config_as_dict())
2355033Smilesck@eecs.umich.edu        return a
2365475Snate@binkert.org
23713663Sandreas.sandberg@arm.comclass VectorParamDesc(ParamDesc):
23813663Sandreas.sandberg@arm.com    # Convert assigned value to appropriate type.  If the RHS is not a
2395475Snate@binkert.org    # list or tuple, it generates a single-element list.
24010380SAndrew.Bardsley@arm.com    def convert(self, value):
24110380SAndrew.Bardsley@arm.com        if isinstance(value, (list, tuple)):
24210380SAndrew.Bardsley@arm.com            # list: coerce each element into new list
2433101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
2443101Sstever@eecs.umich.edu        else:
2453101Sstever@eecs.umich.edu            # singleton: coerce to a single-element list
2464762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
2474762Snate@binkert.org
2484762Snate@binkert.org        if isSimObjectSequence(tmp_list):
2493101Sstever@eecs.umich.edu            return SimObjectVector(tmp_list)
25012050Snikos.nikoleris@arm.com        else:
25112050Snikos.nikoleris@arm.com            return VectorParamValue(tmp_list)
25212050Snikos.nikoleris@arm.com
2538459SAli.Saidi@ARM.com    def swig_module_name(self):
2548459SAli.Saidi@ARM.com        return "%s_vector" % self.ptype_str
25512050Snikos.nikoleris@arm.com
2563101Sstever@eecs.umich.edu    def swig_predecls(self, code):
2577528Ssteve.reinhardt@amd.com        code('%import "${{self.swig_module_name()}}.i"')
2587528Ssteve.reinhardt@amd.com
2597528Ssteve.reinhardt@amd.com    def swig_decl(self, code):
2607528Ssteve.reinhardt@amd.com        code('%module(package="m5.internal") ${{self.swig_module_name()}}')
2617528Ssteve.reinhardt@amd.com        code('%{')
2627528Ssteve.reinhardt@amd.com        self.ptype.cxx_predecls(code)
2633101Sstever@eecs.umich.edu        code('%}')
2647528Ssteve.reinhardt@amd.com        code()
2657528Ssteve.reinhardt@amd.com        # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion
2667528Ssteve.reinhardt@amd.com        code('%include "std_container.i"')
2677528Ssteve.reinhardt@amd.com        code()
2687528Ssteve.reinhardt@amd.com        self.ptype.swig_predecls(code)
2697528Ssteve.reinhardt@amd.com        code()
2707528Ssteve.reinhardt@amd.com        code('%include "std_vector.i"')
2717528Ssteve.reinhardt@amd.com        code()
2727528Ssteve.reinhardt@amd.com
2737528Ssteve.reinhardt@amd.com        ptype = self.ptype_str
2748321Ssteve.reinhardt@amd.com        cxx_type = self.ptype.cxx_type
27512194Sgabeblack@google.com
2767528Ssteve.reinhardt@amd.com        code('''\
2777528Ssteve.reinhardt@amd.com%typemap(in) std::vector< $cxx_type >::value_type {
2787528Ssteve.reinhardt@amd.com    if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) {
2797528Ssteve.reinhardt@amd.com        if (SWIG_ConvertPtr($$input, (void **)&$$1,
2807528Ssteve.reinhardt@amd.com                            $$descriptor($cxx_type), 0) == -1) {
2817528Ssteve.reinhardt@amd.com            return NULL;
2827528Ssteve.reinhardt@amd.com        }
2837528Ssteve.reinhardt@amd.com    }
2847528Ssteve.reinhardt@amd.com}
2857528Ssteve.reinhardt@amd.com
2867528Ssteve.reinhardt@amd.com%typemap(in) std::vector< $cxx_type >::value_type * {
2877528Ssteve.reinhardt@amd.com    if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) {
2887528Ssteve.reinhardt@amd.com        if (SWIG_ConvertPtr($$input, (void **)&$$1,
2893101Sstever@eecs.umich.edu                            $$descriptor($cxx_type *), 0) == -1) {
2908664SAli.Saidi@ARM.com            return NULL;
2918664SAli.Saidi@ARM.com        }
2928664SAli.Saidi@ARM.com    }
2938664SAli.Saidi@ARM.com}
2948664SAli.Saidi@ARM.com''')
2958664SAli.Saidi@ARM.com
2969953Sgeoffrey.blake@arm.com        code('%template(vector_$ptype) std::vector< $cxx_type >;')
2979953Sgeoffrey.blake@arm.com
2989953Sgeoffrey.blake@arm.com    def cxx_predecls(self, code):
2999953Sgeoffrey.blake@arm.com        code('#include <vector>')
3009953Sgeoffrey.blake@arm.com        self.ptype.cxx_predecls(code)
3019953Sgeoffrey.blake@arm.com
3029953Sgeoffrey.blake@arm.com    def cxx_decl(self, code):
3039953Sgeoffrey.blake@arm.com        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
3049953Sgeoffrey.blake@arm.com
3059953Sgeoffrey.blake@arm.comclass ParamFactory(object):
3069953Sgeoffrey.blake@arm.com    def __init__(self, param_desc_class, ptype_str = None):
3079953Sgeoffrey.blake@arm.com        self.param_desc_class = param_desc_class
3089953Sgeoffrey.blake@arm.com        self.ptype_str = ptype_str
30910267SGeoffrey.Blake@arm.com
31010267SGeoffrey.Blake@arm.com    def __getattr__(self, attr):
31110267SGeoffrey.Blake@arm.com        if self.ptype_str:
31210267SGeoffrey.Blake@arm.com            attr = self.ptype_str + '.' + attr
31310267SGeoffrey.Blake@arm.com        return ParamFactory(self.param_desc_class, attr)
31410267SGeoffrey.Blake@arm.com
31510267SGeoffrey.Blake@arm.com    # E.g., Param.Int(5, "number of widgets")
31612563Sgabeblack@google.com    def __call__(self, *args, **kwargs):
31710267SGeoffrey.Blake@arm.com        ptype = None
31810267SGeoffrey.Blake@arm.com        try:
31910267SGeoffrey.Blake@arm.com            ptype = allParams[self.ptype_str]
32010267SGeoffrey.Blake@arm.com        except KeyError:
32110267SGeoffrey.Blake@arm.com            # if name isn't defined yet, assume it's a SimObject, and
32210267SGeoffrey.Blake@arm.com            # try to resolve it later
32310267SGeoffrey.Blake@arm.com            pass
32410267SGeoffrey.Blake@arm.com        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
32510267SGeoffrey.Blake@arm.com
32610267SGeoffrey.Blake@arm.comParam = ParamFactory(ParamDesc)
32710267SGeoffrey.Blake@arm.comVectorParam = ParamFactory(VectorParamDesc)
32810267SGeoffrey.Blake@arm.com
3293101Sstever@eecs.umich.edu#####################################################################
3303101Sstever@eecs.umich.edu#
3313101Sstever@eecs.umich.edu# Parameter Types
3323101Sstever@eecs.umich.edu#
3333101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
3343101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
3353101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
33610364SGeoffrey.Blake@arm.com# over how Python expressions are converted to values (via the
33710364SGeoffrey.Blake@arm.com# __init__() constructor) and how these values are printed out (via
33810364SGeoffrey.Blake@arm.com# the __str__() conversion method).
33910364SGeoffrey.Blake@arm.com#
3403101Sstever@eecs.umich.edu#####################################################################
3414762Snate@binkert.org
3424762Snate@binkert.org# String-valued parameter.  Just mixin the ParamValue class with the
3434762Snate@binkert.org# built-in str class.
3444762Snate@binkert.orgclass String(ParamValue,str):
3457528Ssteve.reinhardt@amd.com    cxx_type = 'std::string'
3464762Snate@binkert.org
3474762Snate@binkert.org    @classmethod
3484762Snate@binkert.org    def cxx_predecls(self, code):
34910267SGeoffrey.Blake@arm.com        code('#include <string>')
35010267SGeoffrey.Blake@arm.com
35110267SGeoffrey.Blake@arm.com    @classmethod
35210267SGeoffrey.Blake@arm.com    def swig_predecls(cls, code):
35310267SGeoffrey.Blake@arm.com        code('%include "std_string.i"')
35410267SGeoffrey.Blake@arm.com
35510267SGeoffrey.Blake@arm.com    def getValue(self):
35610267SGeoffrey.Blake@arm.com        return self
35710267SGeoffrey.Blake@arm.com
35810267SGeoffrey.Blake@arm.com# superclass for "numeric" parameter values, to emulate math
35910267SGeoffrey.Blake@arm.com# operations in a type-safe way.  e.g., a Latency times an int returns
36010267SGeoffrey.Blake@arm.com# a new Latency object.
36110267SGeoffrey.Blake@arm.comclass NumericParamValue(ParamValue):
36210267SGeoffrey.Blake@arm.com    def __str__(self):
36310267SGeoffrey.Blake@arm.com        return str(self.value)
36410267SGeoffrey.Blake@arm.com
36510267SGeoffrey.Blake@arm.com    def __float__(self):
36610267SGeoffrey.Blake@arm.com        return float(self.value)
36710267SGeoffrey.Blake@arm.com
36810267SGeoffrey.Blake@arm.com    def __long__(self):
36910267SGeoffrey.Blake@arm.com        return long(self.value)
37010267SGeoffrey.Blake@arm.com
37110267SGeoffrey.Blake@arm.com    def __int__(self):
37210267SGeoffrey.Blake@arm.com        return int(self.value)
37310267SGeoffrey.Blake@arm.com
37410267SGeoffrey.Blake@arm.com    # hook for bounds checking
37510364SGeoffrey.Blake@arm.com    def _check(self):
37610364SGeoffrey.Blake@arm.com        return
37710267SGeoffrey.Blake@arm.com
37810267SGeoffrey.Blake@arm.com    def __mul__(self, other):
37910267SGeoffrey.Blake@arm.com        newobj = self.__class__(self)
38010267SGeoffrey.Blake@arm.com        newobj.value *= other
38110267SGeoffrey.Blake@arm.com        newobj._check()
38210267SGeoffrey.Blake@arm.com        return newobj
3837673Snate@binkert.org
3847673Snate@binkert.org    __rmul__ = __mul__
3857673Snate@binkert.org
3863101Sstever@eecs.umich.edu    def __div__(self, other):
38711988Sandreas.sandberg@arm.com        newobj = self.__class__(self)
38811988Sandreas.sandberg@arm.com        newobj.value /= other
38911988Sandreas.sandberg@arm.com        newobj._check()
39011988Sandreas.sandberg@arm.com        return newobj
3917673Snate@binkert.org
3927673Snate@binkert.org    def __sub__(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# Metaclass for bounds-checked integer parameters.  See CheckedInt.
3993101Sstever@eecs.umich.educlass CheckedIntType(MetaParamValue):
4003101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
4013101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
4023101Sstever@eecs.umich.edu
4033101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
4043101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
4053101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
4063101Sstever@eecs.umich.edu        if name == 'CheckedInt':
4073101Sstever@eecs.umich.edu            return
4085033Smilesck@eecs.umich.edu
4095033Smilesck@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
4103101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
4113101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
4123101Sstever@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
4133101Sstever@eecs.umich.edu                      name);
4143101Sstever@eecs.umich.edu            if cls.unsigned:
4153101Sstever@eecs.umich.edu                cls.min = 0
4163101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
4173101Sstever@eecs.umich.edu            else:
4183101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
4193101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
4203101Sstever@eecs.umich.edu
4213101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
4223101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
4233101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
4243101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
4253101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue):
4263101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
4273101Sstever@eecs.umich.edu
4283101Sstever@eecs.umich.edu    def _check(self):
4293101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
4303101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
4313101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
4323101Sstever@eecs.umich.edu
4333101Sstever@eecs.umich.edu    def __init__(self, value):
4343101Sstever@eecs.umich.edu        if isinstance(value, str):
43510267SGeoffrey.Blake@arm.com            self.value = convert.toInteger(value)
4367673Snate@binkert.org        elif isinstance(value, (int, long, float, NumericParamValue)):
4377673Snate@binkert.org            self.value = long(value)
4387673Snate@binkert.org        else:
4397673Snate@binkert.org            raise TypeError, "Can't convert object of type %s to CheckedInt" \
4407673Snate@binkert.org                  % type(value).__name__
44110267SGeoffrey.Blake@arm.com        self._check()
44210267SGeoffrey.Blake@arm.com
44310267SGeoffrey.Blake@arm.com    @classmethod
44410267SGeoffrey.Blake@arm.com    def cxx_predecls(cls, code):
44510458Sandreas.hansson@arm.com        # most derived types require this, so we just do it here once
44610458Sandreas.hansson@arm.com        code('#include "base/types.hh"')
44710458Sandreas.hansson@arm.com
44810458Sandreas.hansson@arm.com    @classmethod
44910458Sandreas.hansson@arm.com    def swig_predecls(cls, code):
4504762Snate@binkert.org        # most derived types require this, so we just do it here once
4514762Snate@binkert.org        code('%import "stdint.i"')
4523101Sstever@eecs.umich.edu        code('%import "base/types.hh"')
4533101Sstever@eecs.umich.edu
4543101Sstever@eecs.umich.edu    def getValue(self):
4553101Sstever@eecs.umich.edu        return long(self.value)
4563101Sstever@eecs.umich.edu
4573101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
4583101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
4593101Sstever@eecs.umich.edu
4603101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
4613101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
4623101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
4633714Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
4643714Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
4653714Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
4663714Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
4673714Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
4683714Sstever@eecs.umich.edu
4693101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
4703101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
4713101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
4723101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
4733101Sstever@eecs.umich.edu
4743101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
4753101Sstever@eecs.umich.edu
4763101Sstever@eecs.umich.educlass Float(ParamValue, float):
4773101Sstever@eecs.umich.edu    cxx_type = 'double'
4783101Sstever@eecs.umich.edu
4793101Sstever@eecs.umich.edu    def __init__(self, value):
4803101Sstever@eecs.umich.edu        if isinstance(value, (int, long, float, NumericParamValue, Float)):
4813101Sstever@eecs.umich.edu            self.value = float(value)
4823101Sstever@eecs.umich.edu        else:
4833101Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to Float" \
4843101Sstever@eecs.umich.edu                  % type(value).__name__
4853101Sstever@eecs.umich.edu
4863101Sstever@eecs.umich.edu    def getValue(self):
4873101Sstever@eecs.umich.edu        return float(self.value)
4883101Sstever@eecs.umich.edu
4893101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
4903101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
4913101Sstever@eecs.umich.edu    size = 64
4923101Sstever@eecs.umich.edu    unsigned = True
49310380SAndrew.Bardsley@arm.com    def __init__(self, value):
49410380SAndrew.Bardsley@arm.com        if isinstance(value, MemorySize):
49510380SAndrew.Bardsley@arm.com            self.value = value.value
49610458Sandreas.hansson@arm.com        else:
49710458Sandreas.hansson@arm.com            self.value = convert.toMemorySize(value)
49810458Sandreas.hansson@arm.com        self._check()
49910458Sandreas.hansson@arm.com
50010458Sandreas.hansson@arm.comclass MemorySize32(CheckedInt):
50110458Sandreas.hansson@arm.com    cxx_type = 'uint32_t'
50210458Sandreas.hansson@arm.com    size = 32
50310458Sandreas.hansson@arm.com    unsigned = True
50410458Sandreas.hansson@arm.com    def __init__(self, value):
50510458Sandreas.hansson@arm.com        if isinstance(value, MemorySize):
50610458Sandreas.hansson@arm.com            self.value = value.value
50710458Sandreas.hansson@arm.com        else:
50810458Sandreas.hansson@arm.com            self.value = convert.toMemorySize(value)
5093101Sstever@eecs.umich.edu        self._check()
5105033Smilesck@eecs.umich.edu
5113101Sstever@eecs.umich.educlass Addr(CheckedInt):
5123101Sstever@eecs.umich.edu    cxx_type = 'Addr'
5133101Sstever@eecs.umich.edu    size = 64
5143101Sstever@eecs.umich.edu    unsigned = True
5153101Sstever@eecs.umich.edu    def __init__(self, value):
5163101Sstever@eecs.umich.edu        if isinstance(value, Addr):
5173101Sstever@eecs.umich.edu            self.value = value.value
5183101Sstever@eecs.umich.edu        else:
5193101Sstever@eecs.umich.edu            try:
5203101Sstever@eecs.umich.edu                self.value = convert.toMemorySize(value)
5213101Sstever@eecs.umich.edu            except TypeError:
5223101Sstever@eecs.umich.edu                self.value = long(value)
5235822Ssaidi@eecs.umich.edu        self._check()
5245822Ssaidi@eecs.umich.edu    def __add__(self, other):
5253101Sstever@eecs.umich.edu        if isinstance(other, Addr):
5263101Sstever@eecs.umich.edu            return self.value + other.value
5273101Sstever@eecs.umich.edu        else:
5283101Sstever@eecs.umich.edu            return self.value + other
5293101Sstever@eecs.umich.edu
5303101Sstever@eecs.umich.edu
5313101Sstever@eecs.umich.educlass MetaRange(MetaParamValue):
5323101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5333101Sstever@eecs.umich.edu        super(MetaRange, cls).__init__(name, bases, dict)
5343101Sstever@eecs.umich.edu        if name == 'Range':
5353101Sstever@eecs.umich.edu            return
5363101Sstever@eecs.umich.edu        cls.cxx_type = 'Range< %s >' % cls.type.cxx_type
5373101Sstever@eecs.umich.edu
53810267SGeoffrey.Blake@arm.comclass Range(ParamValue):
5393101Sstever@eecs.umich.edu    __metaclass__ = MetaRange
5403101Sstever@eecs.umich.edu    type = Int # default; can be overridden in subclasses
5413101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
54213663Sandreas.sandberg@arm.com        def handle_kwargs(self, kwargs):
54313663Sandreas.sandberg@arm.com            if 'end' in kwargs:
5443101Sstever@eecs.umich.edu                self.second = self.type(kwargs.pop('end'))
5453101Sstever@eecs.umich.edu            elif 'size' in kwargs:
5463101Sstever@eecs.umich.edu                self.second = self.first + self.type(kwargs.pop('size')) - 1
5473102Sstever@eecs.umich.edu            else:
5483714Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
5493101Sstever@eecs.umich.edu
5503714Sstever@eecs.umich.edu        if len(args) == 0:
55113663Sandreas.sandberg@arm.com            self.first = self.type(kwargs.pop('start'))
55213663Sandreas.sandberg@arm.com            handle_kwargs(self, kwargs)
5533101Sstever@eecs.umich.edu
5543101Sstever@eecs.umich.edu        elif len(args) == 1:
55510267SGeoffrey.Blake@arm.com            if kwargs:
55610267SGeoffrey.Blake@arm.com                self.first = self.type(args[0])
55710267SGeoffrey.Blake@arm.com                handle_kwargs(self, kwargs)
55810267SGeoffrey.Blake@arm.com            elif isinstance(args[0], Range):
5597673Snate@binkert.org                self.first = self.type(args[0].first)
5607673Snate@binkert.org                self.second = self.type(args[0].second)
5617673Snate@binkert.org            elif isinstance(args[0], (list, tuple)):
5627673Snate@binkert.org                self.first = self.type(args[0][0])
5637673Snate@binkert.org                self.second = self.type(args[0][1])
5644762Snate@binkert.org            else:
5654762Snate@binkert.org                self.first = self.type(0)
5664762Snate@binkert.org                self.second = self.type(args[0]) - 1
5673101Sstever@eecs.umich.edu
5683101Sstever@eecs.umich.edu        elif len(args) == 2:
5693101Sstever@eecs.umich.edu            self.first = self.type(args[0])
5703101Sstever@eecs.umich.edu            self.second = self.type(args[1])
5713101Sstever@eecs.umich.edu        else:
5723101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
5733101Sstever@eecs.umich.edu
5743101Sstever@eecs.umich.edu        if kwargs:
5753101Sstever@eecs.umich.edu            raise TypeError, "too many keywords: %s" % kwargs.keys()
5763101Sstever@eecs.umich.edu
5773101Sstever@eecs.umich.edu    def __str__(self):
5783101Sstever@eecs.umich.edu        return '%s:%s' % (self.first, self.second)
5793101Sstever@eecs.umich.edu
5803101Sstever@eecs.umich.edu    @classmethod
5813101Sstever@eecs.umich.edu    def cxx_predecls(cls, code):
5823101Sstever@eecs.umich.edu        cls.type.cxx_predecls(code)
5833101Sstever@eecs.umich.edu        code('#include "base/range.hh"')
5843101Sstever@eecs.umich.edu
5853101Sstever@eecs.umich.edu    @classmethod
5869184Sandreas.hansson@arm.com    def swig_predecls(cls, code):
5879184Sandreas.hansson@arm.com        cls.type.swig_predecls(code)
5889184Sandreas.hansson@arm.com        code('%import "python/swig/range.i"')
5899184Sandreas.hansson@arm.com
5909184Sandreas.hansson@arm.comclass AddrRange(Range):
5919184Sandreas.hansson@arm.com    type = Addr
59211802Sandreas.sandberg@arm.com
5939184Sandreas.hansson@arm.com    def getValue(self):
5949184Sandreas.hansson@arm.com        from m5.internal.range import AddrRange
59510458Sandreas.hansson@arm.com
59610458Sandreas.hansson@arm.com        value = AddrRange()
59710458Sandreas.hansson@arm.com        value.start = long(self.first)
59810458Sandreas.hansson@arm.com        value.end = long(self.second)
59910458Sandreas.hansson@arm.com        return value
60010458Sandreas.hansson@arm.com
60110458Sandreas.hansson@arm.comclass TickRange(Range):
60210458Sandreas.hansson@arm.com    type = Tick
60310458Sandreas.hansson@arm.com
60410458Sandreas.hansson@arm.com    def getValue(self):
60510458Sandreas.hansson@arm.com        from m5.internal.range import TickRange
60610458Sandreas.hansson@arm.com
60710458Sandreas.hansson@arm.com        value = TickRange()
60810458Sandreas.hansson@arm.com        value.start = long(self.first)
6093101Sstever@eecs.umich.edu        value.end = long(self.second)
6104446Sbinkertn@umich.edu        return value
61110668SGeoffrey.Blake@arm.com
6123101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
6135468Snate@binkert.org# it doesn't want to let you create multiple instances of True and
61410267SGeoffrey.Blake@arm.com# False.  Thus this is a little more complicated than String.
6155468Snate@binkert.orgclass Bool(ParamValue):
6165468Snate@binkert.org    cxx_type = 'bool'
61713663Sandreas.sandberg@arm.com    def __init__(self, value):
61813663Sandreas.sandberg@arm.com        try:
6195468Snate@binkert.org            self.value = convert.toBool(value)
62010267SGeoffrey.Blake@arm.com        except TypeError:
62110267SGeoffrey.Blake@arm.com            self.value = bool(value)
62210267SGeoffrey.Blake@arm.com
62310267SGeoffrey.Blake@arm.com    def getValue(self):
6244762Snate@binkert.org        return bool(self.value)
6254762Snate@binkert.org
6264762Snate@binkert.org    def __str__(self):
62710380SAndrew.Bardsley@arm.com        return str(self.value)
62810380SAndrew.Bardsley@arm.com
62910380SAndrew.Bardsley@arm.com    def ini_str(self):
63010458Sandreas.hansson@arm.com        if self.value:
63110458Sandreas.hansson@arm.com            return 'true'
63210458Sandreas.hansson@arm.com        return 'false'
63310458Sandreas.hansson@arm.com
63410458Sandreas.hansson@arm.comdef IncEthernetAddr(addr, val = 1):
63510458Sandreas.hansson@arm.com    bytes = map(lambda x: int(x, 16), addr.split(':'))
63610458Sandreas.hansson@arm.com    bytes[5] += val
63710458Sandreas.hansson@arm.com    for i in (5, 4, 3, 2, 1):
6383101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
6393101Sstever@eecs.umich.edu        bytes[i] = rem
64010267SGeoffrey.Blake@arm.com        if val == 0:
6413101Sstever@eecs.umich.edu            break
6423101Sstever@eecs.umich.edu        bytes[i - 1] += val
6433101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
6443101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
6453101Sstever@eecs.umich.edu
6463101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
6473102Sstever@eecs.umich.edudef NextEthernetAddr():
6483101Sstever@eecs.umich.edu    global _NextEthernetAddr
6493101Sstever@eecs.umich.edu
6503101Sstever@eecs.umich.edu    value = _NextEthernetAddr
6514168Sbinkertn@umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
65210267SGeoffrey.Blake@arm.com    return value
6533101Sstever@eecs.umich.edu
6543101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
6553101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
6563101Sstever@eecs.umich.edu
6573101Sstever@eecs.umich.edu    @classmethod
6583101Sstever@eecs.umich.edu    def cxx_predecls(cls, code):
6593102Sstever@eecs.umich.edu        code('#include "base/inet.hh"')
6603101Sstever@eecs.umich.edu
6613101Sstever@eecs.umich.edu    @classmethod
6623101Sstever@eecs.umich.edu    def swig_predecls(cls, code):
6633101Sstever@eecs.umich.edu        code('%include "python/swig/inet.i"')
6643101Sstever@eecs.umich.edu
6653101Sstever@eecs.umich.edu    def __init__(self, value):
6663101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
6673101Sstever@eecs.umich.edu            self.value = value
6683101Sstever@eecs.umich.edu            return
6693101Sstever@eecs.umich.edu
6703101Sstever@eecs.umich.edu        if not isinstance(value, str):
67110317Smitch.hayenga@arm.com            raise TypeError, "expected an ethernet address and didn't get one"
67210317Smitch.hayenga@arm.com
67310317Smitch.hayenga@arm.com        bytes = value.split(':')
67410317Smitch.hayenga@arm.com        if len(bytes) != 6:
67510317Smitch.hayenga@arm.com            raise TypeError, 'invalid ethernet address %s' % value
6763102Sstever@eecs.umich.edu
67710317Smitch.hayenga@arm.com        for byte in bytes:
67810317Smitch.hayenga@arm.com            if not 0 <= int(byte) <= 0xff:
67910317Smitch.hayenga@arm.com                raise TypeError, 'invalid ethernet address %s' % value
68010317Smitch.hayenga@arm.com
68110317Smitch.hayenga@arm.com        self.value = value
6823101Sstever@eecs.umich.edu
6833584Ssaidi@eecs.umich.edu    def unproxy(self, base):
6843584Ssaidi@eecs.umich.edu        if self.value == NextEthernetAddr:
6853584Ssaidi@eecs.umich.edu            return EthernetAddr(self.value())
6863584Ssaidi@eecs.umich.edu        return self
6873584Ssaidi@eecs.umich.edu
68810267SGeoffrey.Blake@arm.com    def getValue(self):
68910267SGeoffrey.Blake@arm.com        from m5.internal.params import EthAddr
69010267SGeoffrey.Blake@arm.com        return EthAddr(self.value)
69110267SGeoffrey.Blake@arm.com
69210267SGeoffrey.Blake@arm.com    def ini_str(self):
69310267SGeoffrey.Blake@arm.com        return self.value
6943101Sstever@eecs.umich.edu
6959232Sandreas.hansson@arm.com# When initializing an IpAddress, pass in an existing IpAddress, a string of
6969235Sandreas.hansson@arm.com# the form "a.b.c.d", or an integer representing an IP.
6973101Sstever@eecs.umich.educlass IpAddress(ParamValue):
6983101Sstever@eecs.umich.edu    cxx_type = 'Net::IpAddress'
69910676Sandreas.hansson@arm.com
7009411Sandreas.hansson@arm.com    @classmethod
70110676Sandreas.hansson@arm.com    def cxx_predecls(cls, code):
7029411Sandreas.hansson@arm.com        code('#include "base/inet.hh"')
7039411Sandreas.hansson@arm.com
7049411Sandreas.hansson@arm.com    @classmethod
7053101Sstever@eecs.umich.edu    def swig_predecls(cls, code):
7069411Sandreas.hansson@arm.com        code('%include "python/swig/inet.i"')
7079411Sandreas.hansson@arm.com
7089411Sandreas.hansson@arm.com    def __init__(self, value):
7093101Sstever@eecs.umich.edu        if isinstance(value, IpAddress):
7109232Sandreas.hansson@arm.com            self.ip = value.ip
7113101Sstever@eecs.umich.edu        else:
7129232Sandreas.hansson@arm.com            try:
7133101Sstever@eecs.umich.edu                self.ip = convert.toIpAddress(value)
71413663Sandreas.sandberg@arm.com            except TypeError:
7153101Sstever@eecs.umich.edu                self.ip = long(value)
7169411Sandreas.hansson@arm.com        self.verifyIp()
7179411Sandreas.hansson@arm.com
7189411Sandreas.hansson@arm.com    def __str__(self):
71910676Sandreas.hansson@arm.com        tup = [(self.ip >> i)  & 0xff for i in (24, 16, 8, 0)]
72010676Sandreas.hansson@arm.com        return '%d.%d.%d.%d' % tuple(tup)
7219411Sandreas.hansson@arm.com
7229411Sandreas.hansson@arm.com    def __eq__(self, other):
7239411Sandreas.hansson@arm.com        if isinstance(other, IpAddress):
7249411Sandreas.hansson@arm.com            return self.ip == other.ip
7259411Sandreas.hansson@arm.com        elif isinstance(other, str):
7263101Sstever@eecs.umich.edu            try:
7279232Sandreas.hansson@arm.com                return self.ip == convert.toIpAddress(other)
7283101Sstever@eecs.umich.edu            except:
7293101Sstever@eecs.umich.edu                return False
7303101Sstever@eecs.umich.edu        else:
7313101Sstever@eecs.umich.edu            return self.ip == other
7329232Sandreas.hansson@arm.com
7333101Sstever@eecs.umich.edu    def __ne__(self, other):
7345219Ssaidi@eecs.umich.edu        return not (self == other)
7359232Sandreas.hansson@arm.com
7369232Sandreas.hansson@arm.com    def verifyIp(self):
7373101Sstever@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
7389232Sandreas.hansson@arm.com            raise TypeError, "invalid ip address %#08x" % self.ip
7399232Sandreas.hansson@arm.com
7403101Sstever@eecs.umich.edu    def getValue(self):
7413101Sstever@eecs.umich.edu        from m5.internal.params import IpAddress
7429232Sandreas.hansson@arm.com        return IpAddress(self.ip)
7439232Sandreas.hansson@arm.com
7443101Sstever@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
74513663Sandreas.sandberg@arm.com# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
7463101Sstever@eecs.umich.edu# positional or keyword arguments.
7473101Sstever@eecs.umich.educlass IpNetmask(IpAddress):
74813663Sandreas.sandberg@arm.com    cxx_type = 'Net::IpNetmask'
7493101Sstever@eecs.umich.edu
7503101Sstever@eecs.umich.edu    @classmethod
75111620SMatthew.Poremba@amd.com    def cxx_predecls(cls, code):
75211620SMatthew.Poremba@amd.com        code('#include "base/inet.hh"')
75311620SMatthew.Poremba@amd.com
7549232Sandreas.hansson@arm.com    @classmethod
7559232Sandreas.hansson@arm.com    def swig_predecls(cls, code):
7569411Sandreas.hansson@arm.com        code('%include "python/swig/inet.i"')
7579411Sandreas.hansson@arm.com
7583101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
7597673Snate@binkert.org        def handle_kwarg(self, kwargs, key, elseVal = None):
7607673Snate@binkert.org            if key in kwargs:
7619232Sandreas.hansson@arm.com                setattr(self, key, kwargs.pop(key))
7629235Sandreas.hansson@arm.com            elif elseVal:
7637675Snate@binkert.org                setattr(self, key, elseVal)
7647675Snate@binkert.org            else:
76511988Sandreas.sandberg@arm.com                raise TypeError, "No value set for %s" % key
76611988Sandreas.sandberg@arm.com
76711988Sandreas.sandberg@arm.com        if len(args) == 0:
76811988Sandreas.sandberg@arm.com            handle_kwarg(self, kwargs, 'ip')
76911988Sandreas.sandberg@arm.com            handle_kwarg(self, kwargs, 'netmask')
77010458Sandreas.hansson@arm.com
77110458Sandreas.hansson@arm.com        elif len(args) == 1:
77210458Sandreas.hansson@arm.com            if kwargs:
77310458Sandreas.hansson@arm.com                if not 'ip' in kwargs and not 'netmask' in kwargs:
77410458Sandreas.hansson@arm.com                    raise TypeError, "Invalid arguments"
77511620SMatthew.Poremba@amd.com                handle_kwarg(self, kwargs, 'ip', args[0])
77611620SMatthew.Poremba@amd.com                handle_kwarg(self, kwargs, 'netmask', args[0])
77710458Sandreas.hansson@arm.com            elif isinstance(args[0], IpNetmask):
77810458Sandreas.hansson@arm.com                self.ip = args[0].ip
77910458Sandreas.hansson@arm.com                self.netmask = args[0].netmask
78010458Sandreas.hansson@arm.com            else:
78110458Sandreas.hansson@arm.com                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
78211620SMatthew.Poremba@amd.com
78311620SMatthew.Poremba@amd.com        elif len(args) == 2:
78411620SMatthew.Poremba@amd.com            self.ip = args[0]
78511620SMatthew.Poremba@amd.com            self.netmask = args[1]
78611620SMatthew.Poremba@amd.com        else:
78711620SMatthew.Poremba@amd.com            raise TypeError, "Too many arguments specified"
78811620SMatthew.Poremba@amd.com
78911620SMatthew.Poremba@amd.com        if kwargs:
79011620SMatthew.Poremba@amd.com            raise TypeError, "Too many keywords: %s" % kwargs.keys()
79111620SMatthew.Poremba@amd.com
79210458Sandreas.hansson@arm.com        self.verify()
79310458Sandreas.hansson@arm.com
79410458Sandreas.hansson@arm.com    def __str__(self):
79511620SMatthew.Poremba@amd.com        return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask)
79611620SMatthew.Poremba@amd.com
79710458Sandreas.hansson@arm.com    def __eq__(self, other):
79810458Sandreas.hansson@arm.com        if isinstance(other, IpNetmask):
7994762Snate@binkert.org            return self.ip == other.ip and self.netmask == other.netmask
80011991Sandreas.sandberg@arm.com        elif isinstance(other, str):
80111802Sandreas.sandberg@arm.com            try:
8024762Snate@binkert.org                return (self.ip, self.netmask) == convert.toIpNetmask(other)
8039411Sandreas.hansson@arm.com            except:
80410676Sandreas.hansson@arm.com                return False
80510676Sandreas.hansson@arm.com        else:
8063101Sstever@eecs.umich.edu            return False
8073101Sstever@eecs.umich.edu
8083101Sstever@eecs.umich.edu    def verify(self):
8093101Sstever@eecs.umich.edu        self.verifyIp()
8103101Sstever@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
8113101Sstever@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
81210267SGeoffrey.Blake@arm.com
81310267SGeoffrey.Blake@arm.com    def getValue(self):
8143101Sstever@eecs.umich.edu        from m5.internal.params import IpNetmask
8153101Sstever@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
8163102Sstever@eecs.umich.edu
8173101Sstever@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
8183101Sstever@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
8193101Sstever@eecs.umich.educlass IpWithPort(IpAddress):
82010267SGeoffrey.Blake@arm.com    cxx_type = 'Net::IpWithPort'
82110267SGeoffrey.Blake@arm.com
82210267SGeoffrey.Blake@arm.com    @classmethod
82310267SGeoffrey.Blake@arm.com    def cxx_predecls(cls, code):
8244762Snate@binkert.org        code('#include "base/inet.hh"')
8254762Snate@binkert.org
8264762Snate@binkert.org    @classmethod
8273101Sstever@eecs.umich.edu    def swig_predecls(cls, code):
8283101Sstever@eecs.umich.edu        code('%include "python/swig/inet.i"')
8293101Sstever@eecs.umich.edu
8308934SBrad.Beckmann@amd.com    def __init__(self, *args, **kwargs):
8318934SBrad.Beckmann@amd.com        def handle_kwarg(self, kwargs, key, elseVal = None):
83213697Sandreas.sandberg@arm.com            if key in kwargs:
8338934SBrad.Beckmann@amd.com                setattr(self, key, kwargs.pop(key))
8348934SBrad.Beckmann@amd.com            elif elseVal:
83513697Sandreas.sandberg@arm.com                setattr(self, key, elseVal)
83613697Sandreas.sandberg@arm.com            else:
83713697Sandreas.sandberg@arm.com                raise TypeError, "No value set for %s" % key
8383101Sstever@eecs.umich.edu
8393101Sstever@eecs.umich.edu        if len(args) == 0:
8403101Sstever@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
8413101Sstever@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
8423101Sstever@eecs.umich.edu
84310380SAndrew.Bardsley@arm.com        elif len(args) == 1:
84410380SAndrew.Bardsley@arm.com            if kwargs:
84510380SAndrew.Bardsley@arm.com                if not 'ip' in kwargs and not 'port' in kwargs:
84610458Sandreas.hansson@arm.com                    raise TypeError, "Invalid arguments"
84710458Sandreas.hansson@arm.com                handle_kwarg(self, kwargs, 'ip', args[0])
84810458Sandreas.hansson@arm.com                handle_kwarg(self, kwargs, 'port', args[0])
84910458Sandreas.hansson@arm.com            elif isinstance(args[0], IpWithPort):
85010458Sandreas.hansson@arm.com                self.ip = args[0].ip
85110458Sandreas.hansson@arm.com                self.port = args[0].port
85210458Sandreas.hansson@arm.com            else:
85310458Sandreas.hansson@arm.com                (self.ip, self.port) = convert.toIpWithPort(args[0])
85410458Sandreas.hansson@arm.com
85510458Sandreas.hansson@arm.com        elif len(args) == 2:
8563101Sstever@eecs.umich.edu            self.ip = args[0]
8573101Sstever@eecs.umich.edu            self.port = args[1]
8583101Sstever@eecs.umich.edu        else:
8593101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
8603101Sstever@eecs.umich.edu
8613101Sstever@eecs.umich.edu        if kwargs:
8623101Sstever@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
8633101Sstever@eecs.umich.edu
8643101Sstever@eecs.umich.edu        self.verify()
8653101Sstever@eecs.umich.edu
8663101Sstever@eecs.umich.edu    def __str__(self):
8673101Sstever@eecs.umich.edu        return "%s:%d" % (super(IpWithPort, self).__str__(), self.port)
8684380Sbinkertn@umich.edu
8694380Sbinkertn@umich.edu    def __eq__(self, other):
8704380Sbinkertn@umich.edu        if isinstance(other, IpWithPort):
8713101Sstever@eecs.umich.edu            return self.ip == other.ip and self.port == other.port
8724380Sbinkertn@umich.edu        elif isinstance(other, str):
8734380Sbinkertn@umich.edu            try:
8744380Sbinkertn@umich.edu                return (self.ip, self.port) == convert.toIpWithPort(other)
8753101Sstever@eecs.umich.edu            except:
8763101Sstever@eecs.umich.edu                return False
8773101Sstever@eecs.umich.edu        else:
87810267SGeoffrey.Blake@arm.com            return False
87910267SGeoffrey.Blake@arm.com
8807673Snate@binkert.org    def verify(self):
8817673Snate@binkert.org        self.verifyIp()
8827673Snate@binkert.org        if self.port < 0 or self.port > 0xffff:
8837673Snate@binkert.org            raise TypeError, "invalid port %d" % self.port
8847673Snate@binkert.org
8853101Sstever@eecs.umich.edu    def getValue(self):
8863101Sstever@eecs.umich.edu        from m5.internal.params import IpWithPort
8873101Sstever@eecs.umich.edu        return IpWithPort(self.ip, self.port)
8883101Sstever@eecs.umich.edu
8893101Sstever@eecs.umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
8903101Sstever@eecs.umich.edu                 "%a %b %d %H:%M:%S %Z %Y",
89113663Sandreas.sandberg@arm.com                 "%Y/%m/%d %H:%M:%S",
8923101Sstever@eecs.umich.edu                 "%Y/%m/%d %H:%M",
8933101Sstever@eecs.umich.edu                 "%Y/%m/%d",
8943101Sstever@eecs.umich.edu                 "%m/%d/%Y %H:%M:%S",
89513663Sandreas.sandberg@arm.com                 "%m/%d/%Y %H:%M",
8963101Sstever@eecs.umich.edu                 "%m/%d/%Y",
8973101Sstever@eecs.umich.edu                 "%m/%d/%y %H:%M:%S",
8989941SGeoffrey.Blake@arm.com                 "%m/%d/%y %H:%M",
89913663Sandreas.sandberg@arm.com                 "%m/%d/%y"]
9003101Sstever@eecs.umich.edu
9013101Sstever@eecs.umich.edu
9023101Sstever@eecs.umich.edudef parse_time(value):
90310267SGeoffrey.Blake@arm.com    from time import gmtime, strptime, struct_time, time
90410267SGeoffrey.Blake@arm.com    from datetime import datetime, date
90510267SGeoffrey.Blake@arm.com
90610267SGeoffrey.Blake@arm.com    if isinstance(value, struct_time):
9073101Sstever@eecs.umich.edu        return value
9083101Sstever@eecs.umich.edu
9094380Sbinkertn@umich.edu    if isinstance(value, (int, long)):
9103101Sstever@eecs.umich.edu        return gmtime(value)
9113101Sstever@eecs.umich.edu
9124762Snate@binkert.org    if isinstance(value, (datetime, date)):
91311988Sandreas.sandberg@arm.com        return value.timetuple()
9144762Snate@binkert.org
9154762Snate@binkert.org    if isinstance(value, str):
91611228SAndrew.Bardsley@arm.com        if value in ('Now', 'Today'):
91711228SAndrew.Bardsley@arm.com            return time.gmtime(time.time())
91811228SAndrew.Bardsley@arm.com
9194380Sbinkertn@umich.edu        for format in time_formats:
9204380Sbinkertn@umich.edu            try:
9213101Sstever@eecs.umich.edu                return strptime(value, format)
92210458Sandreas.hansson@arm.com            except ValueError:
92310458Sandreas.hansson@arm.com                pass
92410458Sandreas.hansson@arm.com
92510458Sandreas.hansson@arm.com    raise ValueError, "Could not parse '%s' as a time" % value
92610458Sandreas.hansson@arm.com
9277777Sgblack@eecs.umich.educlass Time(ParamValue):
9287777Sgblack@eecs.umich.edu    cxx_type = 'tm'
9297777Sgblack@eecs.umich.edu
9307777Sgblack@eecs.umich.edu    @classmethod
93110267SGeoffrey.Blake@arm.com    def cxx_predecls(cls, code):
93210267SGeoffrey.Blake@arm.com        code('#include <time.h>')
9337777Sgblack@eecs.umich.edu
9347777Sgblack@eecs.umich.edu    @classmethod
9357777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
9367777Sgblack@eecs.umich.edu        code('%include "python/swig/time.i"')
9377777Sgblack@eecs.umich.edu
9387777Sgblack@eecs.umich.edu    def __init__(self, value):
9397777Sgblack@eecs.umich.edu        self.value = parse_time(value)
9407777Sgblack@eecs.umich.edu
9417777Sgblack@eecs.umich.edu    def getValue(self):
9427777Sgblack@eecs.umich.edu        from m5.internal.params import tm
9437777Sgblack@eecs.umich.edu
9447777Sgblack@eecs.umich.edu        c_time = tm()
9457777Sgblack@eecs.umich.edu        py_time = self.value
9467777Sgblack@eecs.umich.edu
9477777Sgblack@eecs.umich.edu        # UNIX is years since 1900
94810267SGeoffrey.Blake@arm.com        c_time.tm_year = py_time.tm_year - 1900;
94910267SGeoffrey.Blake@arm.com
95010267SGeoffrey.Blake@arm.com        # Python starts at 1, UNIX starts at 0
95110267SGeoffrey.Blake@arm.com        c_time.tm_mon =  py_time.tm_mon - 1;
9528579Ssteve.reinhardt@amd.com        c_time.tm_mday = py_time.tm_mday;
9538579Ssteve.reinhardt@amd.com        c_time.tm_hour = py_time.tm_hour;
9548579Ssteve.reinhardt@amd.com        c_time.tm_min = py_time.tm_min;
9558579Ssteve.reinhardt@amd.com        c_time.tm_sec = py_time.tm_sec;
9568579Ssteve.reinhardt@amd.com
9578579Ssteve.reinhardt@amd.com        # Python has 0 as Monday, UNIX is 0 as sunday
9588579Ssteve.reinhardt@amd.com        c_time.tm_wday = py_time.tm_wday + 1
9598579Ssteve.reinhardt@amd.com        if c_time.tm_wday > 6:
9608579Ssteve.reinhardt@amd.com            c_time.tm_wday -= 7;
9618579Ssteve.reinhardt@amd.com
9628579Ssteve.reinhardt@amd.com        # Python starts at 1, Unix starts at 0
9638579Ssteve.reinhardt@amd.com        c_time.tm_yday = py_time.tm_yday - 1;
9648579Ssteve.reinhardt@amd.com
9658579Ssteve.reinhardt@amd.com        return c_time
9668579Ssteve.reinhardt@amd.com
9678579Ssteve.reinhardt@amd.com    def __str__(self):
9688579Ssteve.reinhardt@amd.com        return time.asctime(self.value)
9698579Ssteve.reinhardt@amd.com
9707777Sgblack@eecs.umich.edu    def ini_str(self):
9717777Sgblack@eecs.umich.edu        return str(self)
97213663Sandreas.sandberg@arm.com
9737777Sgblack@eecs.umich.edu    def get_config_as_dict(self):
9747777Sgblack@eecs.umich.edu        return str(self)
97511988Sandreas.sandberg@arm.com
9767777Sgblack@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
9777777Sgblack@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
9787777Sgblack@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
9797777Sgblack@eecs.umich.edu# long run, the integer value of the parameter will be the list index
9807777Sgblack@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
9817777Sgblack@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
9827777Sgblack@eecs.umich.edu# there's not much point in using the dictionary.)
98310267SGeoffrey.Blake@arm.com
98410267SGeoffrey.Blake@arm.com# What Enum() must do is generate a new type encapsulating the
9857777Sgblack@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
9867777Sgblack@eecs.umich.edu# can be instances of that type.  We define two hidden internal
9877777Sgblack@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
9887777Sgblack@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
9897777Sgblack@eecs.umich.edu
9907777Sgblack@eecs.umich.eduallEnums = {}
9917777Sgblack@eecs.umich.edu# Metaclass for Enum types
9927777Sgblack@eecs.umich.educlass MetaEnum(MetaParamValue):
9937777Sgblack@eecs.umich.edu    def __new__(mcls, name, bases, dict):
9947777Sgblack@eecs.umich.edu        assert name not in allEnums
9957777Sgblack@eecs.umich.edu
9967777Sgblack@eecs.umich.edu        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
99713663Sandreas.sandberg@arm.com        allEnums[name] = cls
9987777Sgblack@eecs.umich.edu        return cls
9997777Sgblack@eecs.umich.edu
10007777Sgblack@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
10017777Sgblack@eecs.umich.edu        if init_dict.has_key('map'):
10027777Sgblack@eecs.umich.edu            if not isinstance(cls.map, dict):
10037777Sgblack@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'map' " \
10047777Sgblack@eecs.umich.edu                      "must be of type dict"
10057777Sgblack@eecs.umich.edu            # build list of value strings from map
100613663Sandreas.sandberg@arm.com            cls.vals = cls.map.keys()
10077777Sgblack@eecs.umich.edu            cls.vals.sort()
10087777Sgblack@eecs.umich.edu        elif init_dict.has_key('vals'):
10097777Sgblack@eecs.umich.edu            if not isinstance(cls.vals, list):
10107777Sgblack@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'vals' " \
10117777Sgblack@eecs.umich.edu                      "must be of type list"
10127777Sgblack@eecs.umich.edu            # build string->value map from vals sequence
10137777Sgblack@eecs.umich.edu            cls.map = {}
10147777Sgblack@eecs.umich.edu            for idx,val in enumerate(cls.vals):
10157777Sgblack@eecs.umich.edu                cls.map[val] = idx
10167777Sgblack@eecs.umich.edu        else:
10177777Sgblack@eecs.umich.edu            raise TypeError, "Enum-derived class must define "\
10187777Sgblack@eecs.umich.edu                  "attribute 'map' or 'vals'"
101913663Sandreas.sandberg@arm.com
10207777Sgblack@eecs.umich.edu        cls.cxx_type = 'Enums::%s' % name
10217777Sgblack@eecs.umich.edu
102213663Sandreas.sandberg@arm.com        super(MetaEnum, cls).__init__(name, bases, init_dict)
10237777Sgblack@eecs.umich.edu
10247777Sgblack@eecs.umich.edu    # Generate C++ class declaration for this enum type.
10257777Sgblack@eecs.umich.edu    # Note that we wrap the enum in a class/struct to act as a namespace,
102610267SGeoffrey.Blake@arm.com    # so that the enum strings can be brief w/o worrying about collisions.
102710267SGeoffrey.Blake@arm.com    def cxx_decl(cls, code):
102810267SGeoffrey.Blake@arm.com        name = cls.__name__
102910267SGeoffrey.Blake@arm.com        code('''\
10308579Ssteve.reinhardt@amd.com#ifndef __ENUM__${name}__
10318579Ssteve.reinhardt@amd.com#define __ENUM__${name}__
10328579Ssteve.reinhardt@amd.com
10338579Ssteve.reinhardt@amd.comnamespace Enums {
10348579Ssteve.reinhardt@amd.com    enum $name {
10358579Ssteve.reinhardt@amd.com''')
10368579Ssteve.reinhardt@amd.com        code.indent(2)
10378579Ssteve.reinhardt@amd.com        for val in cls.vals:
10388579Ssteve.reinhardt@amd.com            code('$val = ${{cls.map[val]}},')
10398579Ssteve.reinhardt@amd.com        code('Num_$name = ${{len(cls.vals)}},')
10408579Ssteve.reinhardt@amd.com        code.dedent(2)
10418579Ssteve.reinhardt@amd.com        code('''\
10428579Ssteve.reinhardt@amd.com    };
10438579Ssteve.reinhardt@amd.comextern const char *${name}Strings[Num_${name}];
10447777Sgblack@eecs.umich.edu}
10457777Sgblack@eecs.umich.edu
10467777Sgblack@eecs.umich.edu#endif // __ENUM__${name}__
104713663Sandreas.sandberg@arm.com''')
10487777Sgblack@eecs.umich.edu
10497777Sgblack@eecs.umich.edu    def cxx_def(cls, code):
105011988Sandreas.sandberg@arm.com        name = cls.__name__
10517777Sgblack@eecs.umich.edu        code('''\
10527777Sgblack@eecs.umich.edu#include "enums/$name.hh"
10537777Sgblack@eecs.umich.edunamespace Enums {
10547777Sgblack@eecs.umich.edu    const char *${name}Strings[Num_${name}] =
10557777Sgblack@eecs.umich.edu    {
10567777Sgblack@eecs.umich.edu''')
105710267SGeoffrey.Blake@arm.com        code.indent(2)
105810267SGeoffrey.Blake@arm.com        for val in cls.vals:
10597777Sgblack@eecs.umich.edu            code('"$val",')
10607777Sgblack@eecs.umich.edu        code.dedent(2)
10617777Sgblack@eecs.umich.edu        code('''
10627777Sgblack@eecs.umich.edu    };
10637777Sgblack@eecs.umich.edu} // namespace Enums
10647777Sgblack@eecs.umich.edu''')
10657777Sgblack@eecs.umich.edu
10667777Sgblack@eecs.umich.edu    def swig_decl(cls, code):
10677777Sgblack@eecs.umich.edu        name = cls.__name__
10687777Sgblack@eecs.umich.edu        code('''\
10697777Sgblack@eecs.umich.edu%module(package="m5.internal") enum_$name
10707777Sgblack@eecs.umich.edu
107113663Sandreas.sandberg@arm.com%{
10727777Sgblack@eecs.umich.edu#include "enums/$name.hh"
10737777Sgblack@eecs.umich.edu%}
10747777Sgblack@eecs.umich.edu
10757777Sgblack@eecs.umich.edu%include "enums/$name.hh"
10767777Sgblack@eecs.umich.edu''')
10777777Sgblack@eecs.umich.edu
10787777Sgblack@eecs.umich.edu
10797777Sgblack@eecs.umich.edu# Base class for enum types.
108013663Sandreas.sandberg@arm.comclass Enum(ParamValue):
10817777Sgblack@eecs.umich.edu    __metaclass__ = MetaEnum
10827777Sgblack@eecs.umich.edu    vals = []
10837777Sgblack@eecs.umich.edu
10847777Sgblack@eecs.umich.edu    def __init__(self, value):
10857777Sgblack@eecs.umich.edu        if value not in self.map:
10867777Sgblack@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
10877777Sgblack@eecs.umich.edu                  % (value, self.vals)
10887777Sgblack@eecs.umich.edu        self.value = value
10897777Sgblack@eecs.umich.edu
10907777Sgblack@eecs.umich.edu    @classmethod
10917777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
10927777Sgblack@eecs.umich.edu        code('#include "enums/$0.hh"', cls.__name__)
109313663Sandreas.sandberg@arm.com
10947777Sgblack@eecs.umich.edu    @classmethod
10957777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
109613663Sandreas.sandberg@arm.com        code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
10977777Sgblack@eecs.umich.edu
10987777Sgblack@eecs.umich.edu    def getValue(self):
10997777Sgblack@eecs.umich.edu        return int(self.map[self.value])
110010267SGeoffrey.Blake@arm.com
110110267SGeoffrey.Blake@arm.com    def __str__(self):
110210267SGeoffrey.Blake@arm.com        return self.value
110310267SGeoffrey.Blake@arm.com
11048579Ssteve.reinhardt@amd.com# how big does a rounding error need to be before we warn about it?
11058579Ssteve.reinhardt@amd.comfrequency_tolerance = 0.001  # 0.1%
11068579Ssteve.reinhardt@amd.com
11078579Ssteve.reinhardt@amd.comclass TickParamValue(NumericParamValue):
11088579Ssteve.reinhardt@amd.com    cxx_type = 'Tick'
11098579Ssteve.reinhardt@amd.com
11108579Ssteve.reinhardt@amd.com    @classmethod
11118579Ssteve.reinhardt@amd.com    def cxx_predecls(cls, code):
11128579Ssteve.reinhardt@amd.com        code('#include "base/types.hh"')
11138579Ssteve.reinhardt@amd.com
11148579Ssteve.reinhardt@amd.com    @classmethod
11158579Ssteve.reinhardt@amd.com    def swig_predecls(cls, code):
11168579Ssteve.reinhardt@amd.com        code('%import "stdint.i"')
11178579Ssteve.reinhardt@amd.com        code('%import "base/types.hh"')
11187777Sgblack@eecs.umich.edu
11197777Sgblack@eecs.umich.edu    def getValue(self):
11207777Sgblack@eecs.umich.edu        return long(self.value)
112113663Sandreas.sandberg@arm.com
11227777Sgblack@eecs.umich.educlass Latency(TickParamValue):
11237777Sgblack@eecs.umich.edu    def __init__(self, value):
112411988Sandreas.sandberg@arm.com        if isinstance(value, (Latency, Clock)):
11257777Sgblack@eecs.umich.edu            self.ticks = value.ticks
11267777Sgblack@eecs.umich.edu            self.value = value.value
11273932Sbinkertn@umich.edu        elif isinstance(value, Frequency):
112810380SAndrew.Bardsley@arm.com            self.ticks = value.ticks
11293932Sbinkertn@umich.edu            self.value = 1.0 / value.value
11303932Sbinkertn@umich.edu        elif value.endswith('t'):
11313932Sbinkertn@umich.edu            self.ticks = True
11323932Sbinkertn@umich.edu            self.value = int(value[:-1])
11333932Sbinkertn@umich.edu        else:
11343932Sbinkertn@umich.edu            self.ticks = False
11353932Sbinkertn@umich.edu            self.value = convert.toLatency(value)
11363932Sbinkertn@umich.edu
11373932Sbinkertn@umich.edu    def __getattr__(self, attr):
11383932Sbinkertn@umich.edu        if attr in ('latency', 'period'):
11393932Sbinkertn@umich.edu            return self
11403885Sbinkertn@umich.edu        if attr == 'frequency':
11413932Sbinkertn@umich.edu            return Frequency(self)
11423932Sbinkertn@umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
11433885Sbinkertn@umich.edu
11443932Sbinkertn@umich.edu    def getValue(self):
11453932Sbinkertn@umich.edu        if self.ticks or self.value == 0:
11463932Sbinkertn@umich.edu            value = self.value
11473932Sbinkertn@umich.edu        else:
11483932Sbinkertn@umich.edu            value = ticks.fromSeconds(self.value)
11493932Sbinkertn@umich.edu        return long(value)
11503932Sbinkertn@umich.edu
11513932Sbinkertn@umich.edu    # convert latency to ticks
11523932Sbinkertn@umich.edu    def ini_str(self):
11533932Sbinkertn@umich.edu        return '%d' % self.getValue()
11543932Sbinkertn@umich.edu
11553932Sbinkertn@umich.educlass Frequency(TickParamValue):
11563932Sbinkertn@umich.edu    def __init__(self, value):
11573932Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
11583932Sbinkertn@umich.edu            if value.value == 0:
11593932Sbinkertn@umich.edu                self.value = 0
11603932Sbinkertn@umich.edu            else:
11613932Sbinkertn@umich.edu                self.value = 1.0 / value.value
11623885Sbinkertn@umich.edu            self.ticks = value.ticks
116313663Sandreas.sandberg@arm.com        elif isinstance(value, Frequency):
11643885Sbinkertn@umich.edu            self.value = value.value
11653885Sbinkertn@umich.edu            self.ticks = value.ticks
11664762Snate@binkert.org        else:
11677673Snate@binkert.org            self.ticks = False
11687673Snate@binkert.org            self.value = convert.toFrequency(value)
11697673Snate@binkert.org
11707673Snate@binkert.org    def __getattr__(self, attr):
11717673Snate@binkert.org        if attr == 'frequency':
11723885Sbinkertn@umich.edu            return self
11733932Sbinkertn@umich.edu        if attr in ('latency', 'period'):
11743885Sbinkertn@umich.edu            return Latency(self)
117510267SGeoffrey.Blake@arm.com        raise AttributeError, "Frequency object has no attribute '%s'" % attr
117610267SGeoffrey.Blake@arm.com
117710267SGeoffrey.Blake@arm.com    # convert latency to ticks
117810267SGeoffrey.Blake@arm.com    def getValue(self):
11794762Snate@binkert.org        if self.ticks or self.value == 0:
118011988Sandreas.sandberg@arm.com            value = self.value
118111988Sandreas.sandberg@arm.com        else:
11824762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
118311988Sandreas.sandberg@arm.com        return long(value)
11844762Snate@binkert.org
11853885Sbinkertn@umich.edu    def ini_str(self):
11864762Snate@binkert.org        return '%d' % self.getValue()
11873885Sbinkertn@umich.edu
11883885Sbinkertn@umich.edu# A generic frequency and/or Latency value.  Value is stored as a latency,
11893932Sbinkertn@umich.edu# but to avoid ambiguity this object does not support numeric ops (* or /).
11903885Sbinkertn@umich.edu# An explicit conversion to a Latency or Frequency must be made first.
11918664SAli.Saidi@ARM.comclass Clock(ParamValue):
119210380SAndrew.Bardsley@arm.com    cxx_type = 'Tick'
11938664SAli.Saidi@ARM.com
11948664SAli.Saidi@ARM.com    @classmethod
119510458Sandreas.hansson@arm.com    def cxx_predecls(cls, code):
119610458Sandreas.hansson@arm.com        code('#include "base/types.hh"')
119710458Sandreas.hansson@arm.com
119810458Sandreas.hansson@arm.com    @classmethod
119910458Sandreas.hansson@arm.com    def swig_predecls(cls, code):
120010458Sandreas.hansson@arm.com        code('%import "stdint.i"')
120110458Sandreas.hansson@arm.com        code('%import "base/types.hh"')
120210458Sandreas.hansson@arm.com
120310458Sandreas.hansson@arm.com    def __init__(self, value):
120410458Sandreas.hansson@arm.com        if isinstance(value, (Latency, Clock)):
12053101Sstever@eecs.umich.edu            self.ticks = value.ticks
12063101Sstever@eecs.umich.edu            self.value = value.value
12073101Sstever@eecs.umich.edu        elif isinstance(value, Frequency):
12083101Sstever@eecs.umich.edu            self.ticks = value.ticks
12093101Sstever@eecs.umich.edu            self.value = 1.0 / value.value
12103101Sstever@eecs.umich.edu        elif value.endswith('t'):
12113101Sstever@eecs.umich.edu            self.ticks = True
12123101Sstever@eecs.umich.edu            self.value = int(value[:-1])
12133101Sstever@eecs.umich.edu        else:
12143101Sstever@eecs.umich.edu            self.ticks = False
12153101Sstever@eecs.umich.edu            self.value = convert.anyToLatency(value)
12163101Sstever@eecs.umich.edu
12173101Sstever@eecs.umich.edu    def __getattr__(self, attr):
12183101Sstever@eecs.umich.edu        if attr == 'frequency':
12194762Snate@binkert.org            return Frequency(self)
12203101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
12215033Smilesck@eecs.umich.edu            return Latency(self)
12224762Snate@binkert.org        raise AttributeError, "Frequency object has no attribute '%s'" % attr
12234762Snate@binkert.org
12244762Snate@binkert.org    def getValue(self):
12254762Snate@binkert.org        return self.period.getValue()
12264762Snate@binkert.org
12274762Snate@binkert.org    def ini_str(self):
12284762Snate@binkert.org        return self.period.ini_str()
12293101Sstever@eecs.umich.edu
123013675Sandreas.sandberg@arm.comclass NetworkBandwidth(float,ParamValue):
12313101Sstever@eecs.umich.edu    cxx_type = 'float'
123213663Sandreas.sandberg@arm.com    def __new__(cls, value):
123313663Sandreas.sandberg@arm.com        # convert to bits per second
12343101Sstever@eecs.umich.edu        val = convert.toNetworkBandwidth(value)
12353101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
12363101Sstever@eecs.umich.edu
123713675Sandreas.sandberg@arm.com    def __str__(self):
12383101Sstever@eecs.umich.edu        return str(self.val)
123913663Sandreas.sandberg@arm.com
124013663Sandreas.sandberg@arm.com    def getValue(self):
12413101Sstever@eecs.umich.edu        # convert to seconds per byte
12423101Sstever@eecs.umich.edu        value = 8.0 / float(self)
12433101Sstever@eecs.umich.edu        # convert to ticks per byte
12443101Sstever@eecs.umich.edu        value = ticks.fromSeconds(value)
12453101Sstever@eecs.umich.edu        return float(value)
124613663Sandreas.sandberg@arm.com
124713663Sandreas.sandberg@arm.com    def ini_str(self):
12483101Sstever@eecs.umich.edu        return '%f' % self.getValue()
124913558Snikos.nikoleris@arm.com
125013558Snikos.nikoleris@arm.comclass MemoryBandwidth(float,ParamValue):
125113558Snikos.nikoleris@arm.com    cxx_type = 'float'
125213558Snikos.nikoleris@arm.com    def __new__(cls, value):
12533101Sstever@eecs.umich.edu        # convert to bytes per second
12543101Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
12553101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
12563101Sstever@eecs.umich.edu
12573101Sstever@eecs.umich.edu    def __str__(self):
12583101Sstever@eecs.umich.edu        return str(self.val)
12597673Snate@binkert.org
126010201SAndrew.Bardsley@arm.com    def getValue(self):
126110201SAndrew.Bardsley@arm.com        # convert to seconds per byte
126210201SAndrew.Bardsley@arm.com        value = float(self)
126310201SAndrew.Bardsley@arm.com        if value:
126410201SAndrew.Bardsley@arm.com            value = 1.0 / float(self)
12657673Snate@binkert.org        # convert to ticks per byte
126610201SAndrew.Bardsley@arm.com        value = ticks.fromSeconds(value)
126710201SAndrew.Bardsley@arm.com        return float(value)
12687673Snate@binkert.org
126913558Snikos.nikoleris@arm.com    def ini_str(self):
127013558Snikos.nikoleris@arm.com        return '%f' % self.getValue()
127113558Snikos.nikoleris@arm.com
127213558Snikos.nikoleris@arm.com#
127313558Snikos.nikoleris@arm.com# "Constants"... handy aliases for various values.
127413558Snikos.nikoleris@arm.com#
127513558Snikos.nikoleris@arm.com
127610201SAndrew.Bardsley@arm.com# Special class for NULL pointers.  Note the special check in
12777673Snate@binkert.org# make_param_value() above that lets these be assigned where a
12787673Snate@binkert.org# SimObject is required.
127913558Snikos.nikoleris@arm.com# only one copy of a particular node
128013558Snikos.nikoleris@arm.comclass NullSimObject(object):
12814762Snate@binkert.org    __metaclass__ = Singleton
12827673Snate@binkert.org
12838902Sandreas.hansson@arm.com    def __call__(cls):
128413558Snikos.nikoleris@arm.com        return cls
128513558Snikos.nikoleris@arm.com
12864762Snate@binkert.org    def _instantiate(self, parent = None, path = ''):
128713558Snikos.nikoleris@arm.com        pass
128813558Snikos.nikoleris@arm.com
128913558Snikos.nikoleris@arm.com    def ini_str(self):
129013558Snikos.nikoleris@arm.com        return 'Null'
129113558Snikos.nikoleris@arm.com
129213558Snikos.nikoleris@arm.com    def unproxy(self, base):
129310201SAndrew.Bardsley@arm.com        return self
129410201SAndrew.Bardsley@arm.com
129513558Snikos.nikoleris@arm.com    def set_path(self, parent, name):
129613558Snikos.nikoleris@arm.com        pass
129713558Snikos.nikoleris@arm.com
129813558Snikos.nikoleris@arm.com    def __str__(self):
129910201SAndrew.Bardsley@arm.com        return 'Null'
130010201SAndrew.Bardsley@arm.com
130110201SAndrew.Bardsley@arm.com    def getValue(self):
13027673Snate@binkert.org        return None
13037673Snate@binkert.org
130410201SAndrew.Bardsley@arm.com# The only instance you'll ever need...
130510201SAndrew.Bardsley@arm.comNULL = NullSimObject()
130610201SAndrew.Bardsley@arm.com
130710201SAndrew.Bardsley@arm.comdef isNullPointer(value):
130810201SAndrew.Bardsley@arm.com    return isinstance(value, NullSimObject)
130910201SAndrew.Bardsley@arm.com
131010201SAndrew.Bardsley@arm.com# Some memory range specifications use this as a default upper bound.
131110201SAndrew.Bardsley@arm.comMaxAddr = Addr.max
131210201SAndrew.Bardsley@arm.comMaxTick = Tick.max
131313558Snikos.nikoleris@arm.comAllMemory = AddrRange(0, MaxAddr)
131413558Snikos.nikoleris@arm.com
131513558Snikos.nikoleris@arm.com
131613558Snikos.nikoleris@arm.com#####################################################################
131713558Snikos.nikoleris@arm.com#
131813558Snikos.nikoleris@arm.com# Port objects
131913558Snikos.nikoleris@arm.com#
132013558Snikos.nikoleris@arm.com# Ports are used to interconnect objects in the memory system.
132110201SAndrew.Bardsley@arm.com#
132210201SAndrew.Bardsley@arm.com#####################################################################
132310201SAndrew.Bardsley@arm.com
13244762Snate@binkert.org# Port reference: encapsulates a reference to a particular port on a
13257673Snate@binkert.org# particular SimObject.
132610201SAndrew.Bardsley@arm.comclass PortRef(object):
132710201SAndrew.Bardsley@arm.com    def __init__(self, simobj, name):
132810201SAndrew.Bardsley@arm.com        assert(isSimObject(simobj) or isSimObjectClass(simobj))
132913558Snikos.nikoleris@arm.com        self.simobj = simobj
133013558Snikos.nikoleris@arm.com        self.name = name
133110201SAndrew.Bardsley@arm.com        self.peer = None   # not associated with another port yet
133213558Snikos.nikoleris@arm.com        self.ccConnected = False # C++ port connection done?
13333101Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
133411988Sandreas.sandberg@arm.com
133511988Sandreas.sandberg@arm.com    def __str__(self):
133611988Sandreas.sandberg@arm.com        return '%s.%s' % (self.simobj, self.name)
133713558Snikos.nikoleris@arm.com
133811988Sandreas.sandberg@arm.com    # for config.ini, print peer's name (not ours)
133911988Sandreas.sandberg@arm.com    def ini_str(self):
134011988Sandreas.sandberg@arm.com        return str(self.peer)
134111988Sandreas.sandberg@arm.com
134211988Sandreas.sandberg@arm.com    def __getattr__(self, attr):
134311988Sandreas.sandberg@arm.com        if attr == 'peerObj':
134411988Sandreas.sandberg@arm.com            # shorthand for proxies
134511988Sandreas.sandberg@arm.com            return self.peer.simobj
134611988Sandreas.sandberg@arm.com        raise AttributeError, "'%s' object has no attribute '%s'" % \
134711988Sandreas.sandberg@arm.com              (self.__class__.__name__, attr)
134811988Sandreas.sandberg@arm.com
134911988Sandreas.sandberg@arm.com    # Full connection is symmetric (both ways).  Called via
135011988Sandreas.sandberg@arm.com    # SimObject.__setattr__ as a result of a port assignment, e.g.,
135111988Sandreas.sandberg@arm.com    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
135213558Snikos.nikoleris@arm.com    # e.g., "obj1.portA[3] = obj2.portB".
135313558Snikos.nikoleris@arm.com    def connect(self, other):
135413558Snikos.nikoleris@arm.com        if isinstance(other, VectorPortRef):
135513558Snikos.nikoleris@arm.com            # reference to plain VectorPort is implicit append
135611988Sandreas.sandberg@arm.com            other = other._get_next()
135711988Sandreas.sandberg@arm.com        if self.peer and not proxy.isproxy(self.peer):
135811988Sandreas.sandberg@arm.com            print "warning: overwriting port", self, \
135911988Sandreas.sandberg@arm.com                  "value", self.peer, "with", other
136011988Sandreas.sandberg@arm.com            self.peer.peer = None
136111988Sandreas.sandberg@arm.com        self.peer = other
136211988Sandreas.sandberg@arm.com        if proxy.isproxy(other):
136311988Sandreas.sandberg@arm.com            other.set_param_desc(PortParamDesc())
136411988Sandreas.sandberg@arm.com        elif isinstance(other, PortRef):
136511988Sandreas.sandberg@arm.com            if other.peer is not self:
136611988Sandreas.sandberg@arm.com                other.connect(self)
136711988Sandreas.sandberg@arm.com        else:
136811988Sandreas.sandberg@arm.com            raise TypeError, \
136911988Sandreas.sandberg@arm.com                  "assigning non-port reference '%s' to port '%s'" \
137011988Sandreas.sandberg@arm.com                  % (other, self)
13718596Ssteve.reinhardt@amd.com
13723101Sstever@eecs.umich.edu    def clone(self, simobj, memo):
13733101Sstever@eecs.umich.edu        if memo.has_key(self):
13743101Sstever@eecs.umich.edu            return memo[self]
13753101Sstever@eecs.umich.edu        newRef = copy.copy(self)
137610267SGeoffrey.Blake@arm.com        memo[self] = newRef
13773101Sstever@eecs.umich.edu        newRef.simobj = simobj
137810201SAndrew.Bardsley@arm.com        assert(isSimObject(newRef.simobj))
137910201SAndrew.Bardsley@arm.com        if self.peer and not proxy.isproxy(self.peer):
138010201SAndrew.Bardsley@arm.com            peerObj = self.peer.simobj(_memo=memo)
138110201SAndrew.Bardsley@arm.com            newRef.peer = self.peer.clone(peerObj, memo)
138210201SAndrew.Bardsley@arm.com            assert(not isinstance(newRef.peer, VectorPortRef))
138310201SAndrew.Bardsley@arm.com        return newRef
138413558Snikos.nikoleris@arm.com
138513558Snikos.nikoleris@arm.com    def unproxy(self, simobj):
138610201SAndrew.Bardsley@arm.com        assert(simobj is self.simobj)
138710201SAndrew.Bardsley@arm.com        if proxy.isproxy(self.peer):
138810201SAndrew.Bardsley@arm.com            try:
13893101Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
13903101Sstever@eecs.umich.edu            except:
139113663Sandreas.sandberg@arm.com                print "Error in unproxying port '%s' of %s" % \
139213663Sandreas.sandberg@arm.com                      (self.name, self.simobj.path())
13933101Sstever@eecs.umich.edu                raise
13943101Sstever@eecs.umich.edu            self.connect(realPeer)
139510267SGeoffrey.Blake@arm.com
139610267SGeoffrey.Blake@arm.com    # Call C++ to create corresponding port connection between C++ objects
139710267SGeoffrey.Blake@arm.com    def ccConnect(self):
139810267SGeoffrey.Blake@arm.com        from m5.internal.pyobject import connectPorts
13997675Snate@binkert.org
14007675Snate@binkert.org        if self.ccConnected: # already done this
14017675Snate@binkert.org            return
14027675Snate@binkert.org        peer = self.peer
14037675Snate@binkert.org        if not self.peer: # nothing to connect to
140410458Sandreas.hansson@arm.com            return
140510458Sandreas.hansson@arm.com        try:
140610458Sandreas.hansson@arm.com            connectPorts(self.simobj.getCCObject(), self.name, self.index,
140710458Sandreas.hansson@arm.com                         peer.simobj.getCCObject(), peer.name, peer.index)
140810458Sandreas.hansson@arm.com        except:
140910458Sandreas.hansson@arm.com            print "Error connecting port %s.%s to %s.%s" % \
141010458Sandreas.hansson@arm.com                  (self.simobj.path(), self.name,
141110458Sandreas.hansson@arm.com                   peer.simobj.path(), peer.name)
141210458Sandreas.hansson@arm.com            raise
141310458Sandreas.hansson@arm.com        self.ccConnected = True
141410458Sandreas.hansson@arm.com        peer.ccConnected = True
141510458Sandreas.hansson@arm.com
14164762Snate@binkert.org# A reference to an individual element of a VectorPort... much like a
141711988Sandreas.sandberg@arm.com# PortRef, but has an index.
141811988Sandreas.sandberg@arm.comclass VectorPortElementRef(PortRef):
141911988Sandreas.sandberg@arm.com    def __init__(self, simobj, name, index):
14204762Snate@binkert.org        PortRef.__init__(self, simobj, name)
14213101Sstever@eecs.umich.edu        self.index = index
14223101Sstever@eecs.umich.edu
14233101Sstever@eecs.umich.edu    def __str__(self):
142413558Snikos.nikoleris@arm.com        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
142513558Snikos.nikoleris@arm.com
142613558Snikos.nikoleris@arm.com# A reference to a complete vector-valued port (not just a single element).
142713558Snikos.nikoleris@arm.com# Can be indexed to retrieve individual VectorPortElementRef instances.
142813558Snikos.nikoleris@arm.comclass VectorPortRef(object):
142913558Snikos.nikoleris@arm.com    def __init__(self, simobj, name):
143013558Snikos.nikoleris@arm.com        assert(isSimObject(simobj) or isSimObjectClass(simobj))
143113558Snikos.nikoleris@arm.com        self.simobj = simobj
143213558Snikos.nikoleris@arm.com        self.name = name
143313558Snikos.nikoleris@arm.com        self.elements = []
143413558Snikos.nikoleris@arm.com
143513558Snikos.nikoleris@arm.com    def __str__(self):
143613558Snikos.nikoleris@arm.com        return '%s.%s[:]' % (self.simobj, self.name)
143713558Snikos.nikoleris@arm.com
143813558Snikos.nikoleris@arm.com    # for config.ini, print peer's name (not ours)
143913558Snikos.nikoleris@arm.com    def ini_str(self):
144013558Snikos.nikoleris@arm.com        return ' '.join([el.ini_str() for el in self.elements])
144113558Snikos.nikoleris@arm.com
14423101Sstever@eecs.umich.edu    def __getitem__(self, key):
14433101Sstever@eecs.umich.edu        if not isinstance(key, int):
14443101Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
14454167Sbinkertn@umich.edu        if key >= len(self.elements):
14463101Sstever@eecs.umich.edu            # need to extend list
144710267SGeoffrey.Blake@arm.com            ext = [VectorPortElementRef(self.simobj, self.name, i)
144810267SGeoffrey.Blake@arm.com                   for i in range(len(self.elements), key+1)]
14497673Snate@binkert.org            self.elements.extend(ext)
14507673Snate@binkert.org        return self.elements[key]
14517673Snate@binkert.org
14527673Snate@binkert.org    def _get_next(self):
14537673Snate@binkert.org        return self[len(self.elements)]
145410267SGeoffrey.Blake@arm.com
145510267SGeoffrey.Blake@arm.com    def __setitem__(self, key, value):
145610267SGeoffrey.Blake@arm.com        if not isinstance(key, int):
145710267SGeoffrey.Blake@arm.com            raise TypeError, "VectorPort index must be integer"
14584762Snate@binkert.org        self[key].connect(value)
14594762Snate@binkert.org
14604762Snate@binkert.org    def connect(self, other):
146110458Sandreas.hansson@arm.com        if isinstance(other, (list, tuple)):
146210458Sandreas.hansson@arm.com            # Assign list of port refs to vector port.
146310458Sandreas.hansson@arm.com            # For now, append them... not sure if that's the right semantics
146410458Sandreas.hansson@arm.com            # or if it should replace the current vector.
146510458Sandreas.hansson@arm.com            for ref in other:
146610458Sandreas.hansson@arm.com                self._get_next().connect(ref)
146710458Sandreas.hansson@arm.com        else:
146810458Sandreas.hansson@arm.com            # scalar assignment to plain VectorPort is implicit append
146910458Sandreas.hansson@arm.com            self._get_next().connect(other)
147010458Sandreas.hansson@arm.com
14714167Sbinkertn@umich.edu    def clone(self, simobj, memo):
147210267SGeoffrey.Blake@arm.com        if memo.has_key(self):
147310267SGeoffrey.Blake@arm.com            return memo[self]
14743101Sstever@eecs.umich.edu        newRef = copy.copy(self)
14754167Sbinkertn@umich.edu        memo[self] = newRef
14764167Sbinkertn@umich.edu        newRef.simobj = simobj
14774167Sbinkertn@umich.edu        assert(isSimObject(newRef.simobj))
14784167Sbinkertn@umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
14794167Sbinkertn@umich.edu        return newRef
14804167Sbinkertn@umich.edu
14814167Sbinkertn@umich.edu    def unproxy(self, simobj):
14824167Sbinkertn@umich.edu        [el.unproxy(simobj) for el in self.elements]
14834167Sbinkertn@umich.edu
14844167Sbinkertn@umich.edu    def ccConnect(self):
14854167Sbinkertn@umich.edu        [el.ccConnect() for el in self.elements]
14864167Sbinkertn@umich.edu
14873101Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
148810267SGeoffrey.Blake@arm.com# logical port in the SimObject class, not a particular port on a
148910267SGeoffrey.Blake@arm.com# SimObject instance.  The latter are represented by PortRef objects.
149010267SGeoffrey.Blake@arm.comclass Port(object):
149110267SGeoffrey.Blake@arm.com    # Port("description") or Port(default, "description")
14923101Sstever@eecs.umich.edu    def __init__(self, *args):
14933101Sstever@eecs.umich.edu        if len(args) == 1:
14943101Sstever@eecs.umich.edu            self.desc = args[0]
14953101Sstever@eecs.umich.edu        elif len(args) == 2:
14963101Sstever@eecs.umich.edu            self.default = args[0]
149713663Sandreas.sandberg@arm.com            self.desc = args[1]
14983101Sstever@eecs.umich.edu        else:
14994762Snate@binkert.org            raise TypeError, 'wrong number of arguments'
15004762Snate@binkert.org        # self.name is set by SimObject class on assignment
15014762Snate@binkert.org        # e.g., pio_port = Port("blah") sets self.name to 'pio_port'
15024762Snate@binkert.org
15034762Snate@binkert.org    # Generate a PortRef for this port on the given SimObject with the
15044762Snate@binkert.org    # given name
15054762Snate@binkert.org    def makeRef(self, simobj):
150610380SAndrew.Bardsley@arm.com        return PortRef(simobj, self.name)
150710380SAndrew.Bardsley@arm.com
150810380SAndrew.Bardsley@arm.com    # Connect an instance of this port (on the given SimObject with
15093101Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
15103101Sstever@eecs.umich.edu    def connect(self, simobj, ref):
15114762Snate@binkert.org        self.makeRef(simobj).connect(ref)
15123101Sstever@eecs.umich.edu
15134167Sbinkertn@umich.edu# VectorPort description object.  Like Port, but represents a vector
151410267SGeoffrey.Blake@arm.com# of connections (e.g., as on a Bus).
151510267SGeoffrey.Blake@arm.comclass VectorPort(Port):
15163101Sstever@eecs.umich.edu    def __init__(self, *args):
15174167Sbinkertn@umich.edu        Port.__init__(self, *args)
15184167Sbinkertn@umich.edu        self.isVec = True
15194167Sbinkertn@umich.edu
15204167Sbinkertn@umich.edu    def makeRef(self, simobj):
15214167Sbinkertn@umich.edu        return VectorPortRef(simobj, self.name)
15224167Sbinkertn@umich.edu
15234167Sbinkertn@umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
15244167Sbinkertn@umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
15254167Sbinkertn@umich.edu# make sense.
15264167Sbinkertn@umich.educlass PortParamDesc(object):
15274167Sbinkertn@umich.edu    __metaclass__ = Singleton
15284167Sbinkertn@umich.edu
15293101Sstever@eecs.umich.edu    ptype_str = 'Port'
153010267SGeoffrey.Blake@arm.com    ptype = Port
153110267SGeoffrey.Blake@arm.com
153210267SGeoffrey.Blake@arm.combaseEnums = allEnums.copy()
153310267SGeoffrey.Blake@arm.combaseParams = allParams.copy()
15343101Sstever@eecs.umich.edu
15353101Sstever@eecs.umich.edudef clear():
15363101Sstever@eecs.umich.edu    global allEnums, allParams
15373101Sstever@eecs.umich.edu
15383101Sstever@eecs.umich.edu    allEnums = baseEnums.copy()
153913663Sandreas.sandberg@arm.com    allParams = baseParams.copy()
15403101Sstever@eecs.umich.edu
15414167Sbinkertn@umich.edu__all__ = ['Param', 'VectorParam',
15424762Snate@binkert.org           'Enum', 'Bool', 'String', 'Float',
15434762Snate@binkert.org           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
15444762Snate@binkert.org           'Int32', 'UInt32', 'Int64', 'UInt64',
15454762Snate@binkert.org           'Counter', 'Addr', 'Tick', 'Percent',
15464762Snate@binkert.org           'TcpPort', 'UdpPort', 'EthernetAddr',
15474762Snate@binkert.org           'IpAddress', 'IpNetmask', 'IpWithPort',
15484762Snate@binkert.org           'MemorySize', 'MemorySize32',
154910380SAndrew.Bardsley@arm.com           'Latency', 'Frequency', 'Clock',
155010380SAndrew.Bardsley@arm.com           'NetworkBandwidth', 'MemoryBandwidth',
155110380SAndrew.Bardsley@arm.com           'Range', 'AddrRange', 'TickRange',
15523101Sstever@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
15534762Snate@binkert.org           'Time',
15543101Sstever@eecs.umich.edu           'NextEthernetAddr', 'NULL',
155510019Sandreas.hansson@arm.com           'Port', 'VectorPort']
155610019Sandreas.hansson@arm.com
155710019Sandreas.hansson@arm.comimport SimObject
15583101Sstever@eecs.umich.edu