params.py revision 7811
13101Sstever@eecs.umich.edu# Copyright (c) 2004-2006 The Regents of The University of Michigan
27534Ssteve.reinhardt@amd.com# Copyright (c) 2010 Advanced Micro Devices, Inc.
33101Sstever@eecs.umich.edu# All rights reserved.
43101Sstever@eecs.umich.edu#
53101Sstever@eecs.umich.edu# Redistribution and use in source and binary forms, with or without
63101Sstever@eecs.umich.edu# modification, are permitted provided that the following conditions are
73101Sstever@eecs.umich.edu# met: redistributions of source code must retain the above copyright
83101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer;
93101Sstever@eecs.umich.edu# redistributions in binary form must reproduce the above copyright
103101Sstever@eecs.umich.edu# notice, this list of conditions and the following disclaimer in the
113101Sstever@eecs.umich.edu# documentation and/or other materials provided with the distribution;
123101Sstever@eecs.umich.edu# 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
143101Sstever@eecs.umich.edu# 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
307778Sgblack@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.
423101Sstever@eecs.umich.edu#
433101Sstever@eecs.umich.edu# 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
493885Sbinkertn@umich.eduimport copy
503885Sbinkertn@umich.eduimport datetime
514762Snate@binkert.orgimport re
523885Sbinkertn@umich.eduimport sys
533885Sbinkertn@umich.eduimport time
547528Ssteve.reinhardt@amd.comimport math
553885Sbinkertn@umich.edu
564380Sbinkertn@umich.eduimport proxy
574167Sbinkertn@umich.eduimport ticks
583102Sstever@eecs.umich.edufrom util import *
593101Sstever@eecs.umich.edu
604762Snate@binkert.orgdef isSimObject(*args, **kwargs):
614762Snate@binkert.org    return SimObject.isSimObject(*args, **kwargs)
624762Snate@binkert.org
634762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs):
644762Snate@binkert.org    return SimObject.isSimObjectSequence(*args, **kwargs)
654762Snate@binkert.org
664762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs):
674762Snate@binkert.org    return SimObject.isSimObjectClass(*args, **kwargs)
684762Snate@binkert.org
695033Smilesck@eecs.umich.eduallParams = {}
705033Smilesck@eecs.umich.edu
715033Smilesck@eecs.umich.educlass MetaParamValue(type):
725033Smilesck@eecs.umich.edu    def __new__(mcls, name, bases, dct):
735033Smilesck@eecs.umich.edu        cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct)
745033Smilesck@eecs.umich.edu        assert name not in allParams
755033Smilesck@eecs.umich.edu        allParams[name] = cls
765033Smilesck@eecs.umich.edu        return cls
775033Smilesck@eecs.umich.edu
785033Smilesck@eecs.umich.edu
793101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject
803101Sstever@eecs.umich.edu# parameters.
813101Sstever@eecs.umich.educlass ParamValue(object):
825033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
833101Sstever@eecs.umich.edu
847673Snate@binkert.org    @classmethod
857673Snate@binkert.org    def cxx_predecls(cls, code):
867673Snate@binkert.org        pass
877673Snate@binkert.org
887673Snate@binkert.org    @classmethod
897673Snate@binkert.org    def swig_predecls(cls, code):
907673Snate@binkert.org        pass
913101Sstever@eecs.umich.edu
923101Sstever@eecs.umich.edu    # default for printing to .ini file is regular string conversion.
933101Sstever@eecs.umich.edu    # will be overridden in some cases
943101Sstever@eecs.umich.edu    def ini_str(self):
953101Sstever@eecs.umich.edu        return str(self)
963101Sstever@eecs.umich.edu
973101Sstever@eecs.umich.edu    # allows us to blithely call unproxy() on things without checking
983101Sstever@eecs.umich.edu    # if they're really proxies or not
993101Sstever@eecs.umich.edu    def unproxy(self, base):
1003101Sstever@eecs.umich.edu        return self
1013101Sstever@eecs.umich.edu
1023101Sstever@eecs.umich.edu# Regular parameter description.
1033101Sstever@eecs.umich.educlass ParamDesc(object):
1046656Snate@binkert.org    file_ext = 'ptype'
1056656Snate@binkert.org
1063101Sstever@eecs.umich.edu    def __init__(self, ptype_str, ptype, *args, **kwargs):
1073101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
1083101Sstever@eecs.umich.edu        # remember ptype only if it is provided
1093101Sstever@eecs.umich.edu        if ptype != None:
1103101Sstever@eecs.umich.edu            self.ptype = ptype
1113101Sstever@eecs.umich.edu
1123101Sstever@eecs.umich.edu        if args:
1133101Sstever@eecs.umich.edu            if len(args) == 1:
1143101Sstever@eecs.umich.edu                self.desc = args[0]
1153101Sstever@eecs.umich.edu            elif len(args) == 2:
1163101Sstever@eecs.umich.edu                self.default = args[0]
1173101Sstever@eecs.umich.edu                self.desc = args[1]
1183101Sstever@eecs.umich.edu            else:
1193101Sstever@eecs.umich.edu                raise TypeError, 'too many arguments'
1203101Sstever@eecs.umich.edu
1213101Sstever@eecs.umich.edu        if kwargs.has_key('desc'):
1223101Sstever@eecs.umich.edu            assert(not hasattr(self, 'desc'))
1233101Sstever@eecs.umich.edu            self.desc = kwargs['desc']
1243101Sstever@eecs.umich.edu            del kwargs['desc']
1253101Sstever@eecs.umich.edu
1263101Sstever@eecs.umich.edu        if kwargs.has_key('default'):
1273101Sstever@eecs.umich.edu            assert(not hasattr(self, 'default'))
1283101Sstever@eecs.umich.edu            self.default = kwargs['default']
1293101Sstever@eecs.umich.edu            del kwargs['default']
1303101Sstever@eecs.umich.edu
1313101Sstever@eecs.umich.edu        if kwargs:
1323101Sstever@eecs.umich.edu            raise TypeError, 'extra unknown kwargs %s' % kwargs
1333101Sstever@eecs.umich.edu
1343101Sstever@eecs.umich.edu        if not hasattr(self, 'desc'):
1353101Sstever@eecs.umich.edu            raise TypeError, 'desc attribute missing'
1363101Sstever@eecs.umich.edu
1373101Sstever@eecs.umich.edu    def __getattr__(self, attr):
1383101Sstever@eecs.umich.edu        if attr == 'ptype':
1395033Smilesck@eecs.umich.edu            ptype = SimObject.allClasses[self.ptype_str]
1406656Snate@binkert.org            assert isSimObjectClass(ptype)
1415033Smilesck@eecs.umich.edu            self.ptype = ptype
1425033Smilesck@eecs.umich.edu            return ptype
1435033Smilesck@eecs.umich.edu
1443101Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
1453101Sstever@eecs.umich.edu              (type(self).__name__, attr)
1463101Sstever@eecs.umich.edu
1473101Sstever@eecs.umich.edu    def convert(self, value):
1483101Sstever@eecs.umich.edu        if isinstance(value, proxy.BaseProxy):
1493101Sstever@eecs.umich.edu            value.set_param_desc(self)
1503101Sstever@eecs.umich.edu            return value
1513101Sstever@eecs.umich.edu        if not hasattr(self, 'ptype') and isNullPointer(value):
1523101Sstever@eecs.umich.edu            # deferred evaluation of SimObject; continue to defer if
1533101Sstever@eecs.umich.edu            # we're just assigning a null pointer
1543101Sstever@eecs.umich.edu            return value
1553101Sstever@eecs.umich.edu        if isinstance(value, self.ptype):
1563101Sstever@eecs.umich.edu            return value
1573102Sstever@eecs.umich.edu        if isNullPointer(value) and isSimObjectClass(self.ptype):
1583101Sstever@eecs.umich.edu            return value
1593101Sstever@eecs.umich.edu        return self.ptype(value)
1603101Sstever@eecs.umich.edu
1617673Snate@binkert.org    def cxx_predecls(self, code):
1627673Snate@binkert.org        self.ptype.cxx_predecls(code)
1633101Sstever@eecs.umich.edu
1647673Snate@binkert.org    def swig_predecls(self, code):
1657673Snate@binkert.org        self.ptype.swig_predecls(code)
1663101Sstever@eecs.umich.edu
1677673Snate@binkert.org    def cxx_decl(self, code):
1687673Snate@binkert.org        code('${{self.ptype.cxx_type}} ${{self.name}};')
1693101Sstever@eecs.umich.edu
1703101Sstever@eecs.umich.edu# Vector-valued parameter description.  Just like ParamDesc, except
1713101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a
1723101Sstever@eecs.umich.edu# single value.
1733101Sstever@eecs.umich.edu
1743101Sstever@eecs.umich.educlass VectorParamValue(list):
1755033Smilesck@eecs.umich.edu    __metaclass__ = MetaParamValue
1765475Snate@binkert.org    def __setattr__(self, attr, value):
1775475Snate@binkert.org        raise AttributeError, \
1785475Snate@binkert.org              "Not allowed to set %s on '%s'" % (attr, type(self).__name__)
1795475Snate@binkert.org
1803101Sstever@eecs.umich.edu    def ini_str(self):
1813101Sstever@eecs.umich.edu        return ' '.join([v.ini_str() for v in self])
1823101Sstever@eecs.umich.edu
1834762Snate@binkert.org    def getValue(self):
1844762Snate@binkert.org        return [ v.getValue() for v in self ]
1854762Snate@binkert.org
1863101Sstever@eecs.umich.edu    def unproxy(self, base):
1873101Sstever@eecs.umich.edu        return [v.unproxy(base) for v in self]
1883101Sstever@eecs.umich.edu
1897528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue):
1907528Ssteve.reinhardt@amd.com    # support clone operation
1917528Ssteve.reinhardt@amd.com    def __call__(self, **kwargs):
1927528Ssteve.reinhardt@amd.com        return SimObjectVector([v(**kwargs) for v in self])
1937528Ssteve.reinhardt@amd.com
1947528Ssteve.reinhardt@amd.com    def clear_parent(self, old_parent):
1953101Sstever@eecs.umich.edu        for v in self:
1967528Ssteve.reinhardt@amd.com            v.clear_parent(old_parent)
1977528Ssteve.reinhardt@amd.com
1987528Ssteve.reinhardt@amd.com    def set_parent(self, parent, name):
1997528Ssteve.reinhardt@amd.com        if len(self) == 1:
2007528Ssteve.reinhardt@amd.com            self[0].set_parent(parent, name)
2017528Ssteve.reinhardt@amd.com        else:
2027528Ssteve.reinhardt@amd.com            width = int(math.ceil(math.log(len(self))/math.log(10)))
2037528Ssteve.reinhardt@amd.com            for i,v in enumerate(self):
2047528Ssteve.reinhardt@amd.com                v.set_parent(parent, "%s%0*d" % (name, width, i))
2057528Ssteve.reinhardt@amd.com
2067528Ssteve.reinhardt@amd.com    def get_parent(self):
2077528Ssteve.reinhardt@amd.com        parent_set = set(v._parent for v in self)
2087528Ssteve.reinhardt@amd.com        if len(parent_set) != 1:
2097528Ssteve.reinhardt@amd.com            raise RuntimeError, \
2107528Ssteve.reinhardt@amd.com                  "SimObjectVector elements have inconsistent parent value."
2117528Ssteve.reinhardt@amd.com        return parent_set.pop()
2127528Ssteve.reinhardt@amd.com
2137528Ssteve.reinhardt@amd.com    # return 'cpu0 cpu1' etc. for print_ini()
2147528Ssteve.reinhardt@amd.com    def get_name(self):
2157528Ssteve.reinhardt@amd.com        return ' '.join([v._name for v in self])
2167528Ssteve.reinhardt@amd.com
2177528Ssteve.reinhardt@amd.com    # By iterating through the constituent members of the vector here
2187528Ssteve.reinhardt@amd.com    # we can nicely handle iterating over all a SimObject's children
2197528Ssteve.reinhardt@amd.com    # without having to provide lots of special functions on
2207528Ssteve.reinhardt@amd.com    # SimObjectVector directly.
2217528Ssteve.reinhardt@amd.com    def descendants(self):
2227528Ssteve.reinhardt@amd.com        for v in self:
2237528Ssteve.reinhardt@amd.com            for obj in v.descendants():
2247528Ssteve.reinhardt@amd.com                yield obj
2253101Sstever@eecs.umich.edu
2263101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc):
2276656Snate@binkert.org    file_ext = 'vptype'
2286656Snate@binkert.org
2293101Sstever@eecs.umich.edu    # Convert assigned value to appropriate type.  If the RHS is not a
2303101Sstever@eecs.umich.edu    # list or tuple, it generates a single-element list.
2313101Sstever@eecs.umich.edu    def convert(self, value):
2323101Sstever@eecs.umich.edu        if isinstance(value, (list, tuple)):
2333101Sstever@eecs.umich.edu            # list: coerce each element into new list
2343101Sstever@eecs.umich.edu            tmp_list = [ ParamDesc.convert(self, v) for v in value ]
2353101Sstever@eecs.umich.edu        else:
2364762Snate@binkert.org            # singleton: coerce to a single-element list
2374762Snate@binkert.org            tmp_list = [ ParamDesc.convert(self, value) ]
2384762Snate@binkert.org
2394762Snate@binkert.org        if isSimObjectSequence(tmp_list):
2407528Ssteve.reinhardt@amd.com            return SimObjectVector(tmp_list)
2414762Snate@binkert.org        else:
2424762Snate@binkert.org            return VectorParamValue(tmp_list)
2434762Snate@binkert.org
2447673Snate@binkert.org    def swig_predecls(self, code):
2457677Snate@binkert.org        code('%import "vptype_${{self.ptype_str}}.i"')
2464762Snate@binkert.org
2477673Snate@binkert.org    def swig_decl(self, code):
2487675Snate@binkert.org        code('%{')
2497675Snate@binkert.org        self.ptype.cxx_predecls(code)
2507675Snate@binkert.org        code('%}')
2517675Snate@binkert.org        code()
2527675Snate@binkert.org        self.ptype.swig_predecls(code)
2537675Snate@binkert.org        code()
2547673Snate@binkert.org        code('%include "std_vector.i"')
2557675Snate@binkert.org        code()
2567675Snate@binkert.org
2577675Snate@binkert.org        ptype = self.ptype_str
2587675Snate@binkert.org        cxx_type = self.ptype.cxx_type
2597675Snate@binkert.org
2607673Snate@binkert.org        code('''\
2617675Snate@binkert.org%typemap(in) std::vector< $cxx_type >::value_type {
2627675Snate@binkert.org    if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) {
2637675Snate@binkert.org        if (SWIG_ConvertPtr($$input, (void **)&$$1,
2647675Snate@binkert.org                            $$descriptor($cxx_type), 0) == -1) {
2657675Snate@binkert.org            return NULL;
2667675Snate@binkert.org        }
2677675Snate@binkert.org    }
2687675Snate@binkert.org}
2697675Snate@binkert.org
2707675Snate@binkert.org%typemap(in) std::vector< $cxx_type >::value_type * {
2717675Snate@binkert.org    if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) {
2727675Snate@binkert.org        if (SWIG_ConvertPtr($$input, (void **)&$$1,
2737675Snate@binkert.org                            $$descriptor($cxx_type *), 0) == -1) {
2747675Snate@binkert.org            return NULL;
2757675Snate@binkert.org        }
2767675Snate@binkert.org    }
2777673Snate@binkert.org}
2787673Snate@binkert.org''')
2793101Sstever@eecs.umich.edu
2807675Snate@binkert.org        code('%template(vector_$ptype) std::vector< $cxx_type >;')
2817675Snate@binkert.org
2827673Snate@binkert.org    def cxx_predecls(self, code):
2837673Snate@binkert.org        code('#include <vector>')
2847673Snate@binkert.org        self.ptype.cxx_predecls(code)
2853101Sstever@eecs.umich.edu
2867673Snate@binkert.org    def cxx_decl(self, code):
2877673Snate@binkert.org        code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};')
2883101Sstever@eecs.umich.edu
2893101Sstever@eecs.umich.educlass ParamFactory(object):
2903101Sstever@eecs.umich.edu    def __init__(self, param_desc_class, ptype_str = None):
2913101Sstever@eecs.umich.edu        self.param_desc_class = param_desc_class
2923101Sstever@eecs.umich.edu        self.ptype_str = ptype_str
2933101Sstever@eecs.umich.edu
2943101Sstever@eecs.umich.edu    def __getattr__(self, attr):
2953101Sstever@eecs.umich.edu        if self.ptype_str:
2963101Sstever@eecs.umich.edu            attr = self.ptype_str + '.' + attr
2973101Sstever@eecs.umich.edu        return ParamFactory(self.param_desc_class, attr)
2983101Sstever@eecs.umich.edu
2993101Sstever@eecs.umich.edu    # E.g., Param.Int(5, "number of widgets")
3003101Sstever@eecs.umich.edu    def __call__(self, *args, **kwargs):
3013101Sstever@eecs.umich.edu        ptype = None
3023101Sstever@eecs.umich.edu        try:
3035033Smilesck@eecs.umich.edu            ptype = allParams[self.ptype_str]
3045033Smilesck@eecs.umich.edu        except KeyError:
3053101Sstever@eecs.umich.edu            # if name isn't defined yet, assume it's a SimObject, and
3063101Sstever@eecs.umich.edu            # try to resolve it later
3073101Sstever@eecs.umich.edu            pass
3083101Sstever@eecs.umich.edu        return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)
3093101Sstever@eecs.umich.edu
3103101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc)
3113101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc)
3123101Sstever@eecs.umich.edu
3133101Sstever@eecs.umich.edu#####################################################################
3143101Sstever@eecs.umich.edu#
3153101Sstever@eecs.umich.edu# Parameter Types
3163101Sstever@eecs.umich.edu#
3173101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types
3183101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more
3193101Sstever@eecs.umich.edu# flexible to define our own set of types.  This gives us more control
3203101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the
3213101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via
3223101Sstever@eecs.umich.edu# the __str__() conversion method).
3233101Sstever@eecs.umich.edu#
3243101Sstever@eecs.umich.edu#####################################################################
3253101Sstever@eecs.umich.edu
3263101Sstever@eecs.umich.edu# String-valued parameter.  Just mixin the ParamValue class with the
3273101Sstever@eecs.umich.edu# built-in str class.
3283101Sstever@eecs.umich.educlass String(ParamValue,str):
3293101Sstever@eecs.umich.edu    cxx_type = 'std::string'
3307673Snate@binkert.org
3317673Snate@binkert.org    @classmethod
3327673Snate@binkert.org    def cxx_predecls(self, code):
3337673Snate@binkert.org        code('#include <string>')
3347673Snate@binkert.org
3357673Snate@binkert.org    @classmethod
3367673Snate@binkert.org    def swig_predecls(cls, code):
3377673Snate@binkert.org        code('%include "std_string.i"')
3384762Snate@binkert.org
3394762Snate@binkert.org    def getValue(self):
3404762Snate@binkert.org        return self
3413101Sstever@eecs.umich.edu
3423101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math
3433101Sstever@eecs.umich.edu# operations in a type-safe way.  e.g., a Latency times an int returns
3443101Sstever@eecs.umich.edu# a new Latency object.
3453101Sstever@eecs.umich.educlass NumericParamValue(ParamValue):
3463101Sstever@eecs.umich.edu    def __str__(self):
3473101Sstever@eecs.umich.edu        return str(self.value)
3483101Sstever@eecs.umich.edu
3493101Sstever@eecs.umich.edu    def __float__(self):
3503101Sstever@eecs.umich.edu        return float(self.value)
3513101Sstever@eecs.umich.edu
3523714Sstever@eecs.umich.edu    def __long__(self):
3533714Sstever@eecs.umich.edu        return long(self.value)
3543714Sstever@eecs.umich.edu
3553714Sstever@eecs.umich.edu    def __int__(self):
3563714Sstever@eecs.umich.edu        return int(self.value)
3573714Sstever@eecs.umich.edu
3583101Sstever@eecs.umich.edu    # hook for bounds checking
3593101Sstever@eecs.umich.edu    def _check(self):
3603101Sstever@eecs.umich.edu        return
3613101Sstever@eecs.umich.edu
3623101Sstever@eecs.umich.edu    def __mul__(self, other):
3633101Sstever@eecs.umich.edu        newobj = self.__class__(self)
3643101Sstever@eecs.umich.edu        newobj.value *= other
3653101Sstever@eecs.umich.edu        newobj._check()
3663101Sstever@eecs.umich.edu        return newobj
3673101Sstever@eecs.umich.edu
3683101Sstever@eecs.umich.edu    __rmul__ = __mul__
3693101Sstever@eecs.umich.edu
3703101Sstever@eecs.umich.edu    def __div__(self, other):
3713101Sstever@eecs.umich.edu        newobj = self.__class__(self)
3723101Sstever@eecs.umich.edu        newobj.value /= other
3733101Sstever@eecs.umich.edu        newobj._check()
3743101Sstever@eecs.umich.edu        return newobj
3753101Sstever@eecs.umich.edu
3763101Sstever@eecs.umich.edu    def __sub__(self, other):
3773101Sstever@eecs.umich.edu        newobj = self.__class__(self)
3783101Sstever@eecs.umich.edu        newobj.value -= other
3793101Sstever@eecs.umich.edu        newobj._check()
3803101Sstever@eecs.umich.edu        return newobj
3813101Sstever@eecs.umich.edu
3823101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters.  See CheckedInt.
3835033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue):
3843101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
3853101Sstever@eecs.umich.edu        super(CheckedIntType, cls).__init__(name, bases, dict)
3863101Sstever@eecs.umich.edu
3873101Sstever@eecs.umich.edu        # CheckedInt is an abstract base class, so we actually don't
3883101Sstever@eecs.umich.edu        # want to do any processing on it... the rest of this code is
3893101Sstever@eecs.umich.edu        # just for classes that derive from CheckedInt.
3903101Sstever@eecs.umich.edu        if name == 'CheckedInt':
3913101Sstever@eecs.umich.edu            return
3923101Sstever@eecs.umich.edu
3933101Sstever@eecs.umich.edu        if not (hasattr(cls, 'min') and hasattr(cls, 'max')):
3943101Sstever@eecs.umich.edu            if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')):
3953101Sstever@eecs.umich.edu                panic("CheckedInt subclass %s must define either\n" \
3965822Ssaidi@eecs.umich.edu                      "    'min' and 'max' or 'size' and 'unsigned'\n",
3975822Ssaidi@eecs.umich.edu                      name);
3983101Sstever@eecs.umich.edu            if cls.unsigned:
3993101Sstever@eecs.umich.edu                cls.min = 0
4003101Sstever@eecs.umich.edu                cls.max = 2 ** cls.size - 1
4013101Sstever@eecs.umich.edu            else:
4023101Sstever@eecs.umich.edu                cls.min = -(2 ** (cls.size - 1))
4033101Sstever@eecs.umich.edu                cls.max = (2 ** (cls.size - 1)) - 1
4043101Sstever@eecs.umich.edu
4053101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters.  This
4063101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific
4073101Sstever@eecs.umich.edu# bounds.  Initialization of the min and max bounds is done in the
4083101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__.
4093101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue):
4103101Sstever@eecs.umich.edu    __metaclass__ = CheckedIntType
4113101Sstever@eecs.umich.edu
4123101Sstever@eecs.umich.edu    def _check(self):
4133101Sstever@eecs.umich.edu        if not self.min <= self.value <= self.max:
4143101Sstever@eecs.umich.edu            raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
4153101Sstever@eecs.umich.edu                  (self.min, self.value, self.max)
4163101Sstever@eecs.umich.edu
4173101Sstever@eecs.umich.edu    def __init__(self, value):
4183101Sstever@eecs.umich.edu        if isinstance(value, str):
4193102Sstever@eecs.umich.edu            self.value = convert.toInteger(value)
4203714Sstever@eecs.umich.edu        elif isinstance(value, (int, long, float, NumericParamValue)):
4213101Sstever@eecs.umich.edu            self.value = long(value)
4223714Sstever@eecs.umich.edu        else:
4233714Sstever@eecs.umich.edu            raise TypeError, "Can't convert object of type %s to CheckedInt" \
4243714Sstever@eecs.umich.edu                  % type(value).__name__
4253101Sstever@eecs.umich.edu        self._check()
4263101Sstever@eecs.umich.edu
4277673Snate@binkert.org    @classmethod
4287673Snate@binkert.org    def cxx_predecls(cls, code):
4297673Snate@binkert.org        # most derived types require this, so we just do it here once
4307673Snate@binkert.org        code('#include "base/types.hh"')
4317673Snate@binkert.org
4327673Snate@binkert.org    @classmethod
4337673Snate@binkert.org    def swig_predecls(cls, code):
4347673Snate@binkert.org        # most derived types require this, so we just do it here once
4357673Snate@binkert.org        code('%import "stdint.i"')
4367673Snate@binkert.org        code('%import "base/types.hh"')
4377673Snate@binkert.org
4384762Snate@binkert.org    def getValue(self):
4394762Snate@binkert.org        return long(self.value)
4404762Snate@binkert.org
4413101Sstever@eecs.umich.educlass Int(CheckedInt):      cxx_type = 'int';      size = 32; unsigned = False
4423101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True
4433101Sstever@eecs.umich.edu
4443101Sstever@eecs.umich.educlass Int8(CheckedInt):     cxx_type =   'int8_t'; size =  8; unsigned = False
4453101Sstever@eecs.umich.educlass UInt8(CheckedInt):    cxx_type =  'uint8_t'; size =  8; unsigned = True
4463101Sstever@eecs.umich.educlass Int16(CheckedInt):    cxx_type =  'int16_t'; size = 16; unsigned = False
4473101Sstever@eecs.umich.educlass UInt16(CheckedInt):   cxx_type = 'uint16_t'; size = 16; unsigned = True
4483101Sstever@eecs.umich.educlass Int32(CheckedInt):    cxx_type =  'int32_t'; size = 32; unsigned = False
4493101Sstever@eecs.umich.educlass UInt32(CheckedInt):   cxx_type = 'uint32_t'; size = 32; unsigned = True
4503101Sstever@eecs.umich.educlass Int64(CheckedInt):    cxx_type =  'int64_t'; size = 64; unsigned = False
4513101Sstever@eecs.umich.educlass UInt64(CheckedInt):   cxx_type = 'uint64_t'; size = 64; unsigned = True
4523101Sstever@eecs.umich.edu
4533101Sstever@eecs.umich.educlass Counter(CheckedInt):  cxx_type = 'Counter';  size = 64; unsigned = True
4543101Sstever@eecs.umich.educlass Tick(CheckedInt):     cxx_type = 'Tick';     size = 64; unsigned = True
4553101Sstever@eecs.umich.educlass TcpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
4563101Sstever@eecs.umich.educlass UdpPort(CheckedInt):  cxx_type = 'uint16_t'; size = 16; unsigned = True
4573101Sstever@eecs.umich.edu
4583101Sstever@eecs.umich.educlass Percent(CheckedInt):  cxx_type = 'int'; min = 0; max = 100
4593101Sstever@eecs.umich.edu
4603101Sstever@eecs.umich.educlass Float(ParamValue, float):
4614446Sbinkertn@umich.edu    cxx_type = 'double'
4623101Sstever@eecs.umich.edu
4635468Snate@binkert.org    def __init__(self, value):
4645468Snate@binkert.org        if isinstance(value, (int, long, float, NumericParamValue, Float)):
4655468Snate@binkert.org            self.value = float(value)
4665468Snate@binkert.org        else:
4675468Snate@binkert.org            raise TypeError, "Can't convert object of type %s to Float" \
4685468Snate@binkert.org                  % type(value).__name__
4695468Snate@binkert.org
4704762Snate@binkert.org    def getValue(self):
4714762Snate@binkert.org        return float(self.value)
4724762Snate@binkert.org
4733101Sstever@eecs.umich.educlass MemorySize(CheckedInt):
4743101Sstever@eecs.umich.edu    cxx_type = 'uint64_t'
4753101Sstever@eecs.umich.edu    size = 64
4763101Sstever@eecs.umich.edu    unsigned = True
4773101Sstever@eecs.umich.edu    def __init__(self, value):
4783101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
4793101Sstever@eecs.umich.edu            self.value = value.value
4803101Sstever@eecs.umich.edu        else:
4813102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
4823101Sstever@eecs.umich.edu        self._check()
4833101Sstever@eecs.umich.edu
4843101Sstever@eecs.umich.educlass MemorySize32(CheckedInt):
4854168Sbinkertn@umich.edu    cxx_type = 'uint32_t'
4863101Sstever@eecs.umich.edu    size = 32
4873101Sstever@eecs.umich.edu    unsigned = True
4883101Sstever@eecs.umich.edu    def __init__(self, value):
4893101Sstever@eecs.umich.edu        if isinstance(value, MemorySize):
4903101Sstever@eecs.umich.edu            self.value = value.value
4913101Sstever@eecs.umich.edu        else:
4923102Sstever@eecs.umich.edu            self.value = convert.toMemorySize(value)
4933101Sstever@eecs.umich.edu        self._check()
4943101Sstever@eecs.umich.edu
4953101Sstever@eecs.umich.educlass Addr(CheckedInt):
4963101Sstever@eecs.umich.edu    cxx_type = 'Addr'
4973101Sstever@eecs.umich.edu    size = 64
4983101Sstever@eecs.umich.edu    unsigned = True
4993101Sstever@eecs.umich.edu    def __init__(self, value):
5003101Sstever@eecs.umich.edu        if isinstance(value, Addr):
5013101Sstever@eecs.umich.edu            self.value = value.value
5023101Sstever@eecs.umich.edu        else:
5033101Sstever@eecs.umich.edu            try:
5043102Sstever@eecs.umich.edu                self.value = convert.toMemorySize(value)
5053101Sstever@eecs.umich.edu            except TypeError:
5063101Sstever@eecs.umich.edu                self.value = long(value)
5073101Sstever@eecs.umich.edu        self._check()
5083584Ssaidi@eecs.umich.edu    def __add__(self, other):
5093584Ssaidi@eecs.umich.edu        if isinstance(other, Addr):
5103584Ssaidi@eecs.umich.edu            return self.value + other.value
5113584Ssaidi@eecs.umich.edu        else:
5123584Ssaidi@eecs.umich.edu            return self.value + other
5133101Sstever@eecs.umich.edu
5143101Sstever@eecs.umich.edu
5155033Smilesck@eecs.umich.educlass MetaRange(MetaParamValue):
5163101Sstever@eecs.umich.edu    def __init__(cls, name, bases, dict):
5173101Sstever@eecs.umich.edu        super(MetaRange, cls).__init__(name, bases, dict)
5183101Sstever@eecs.umich.edu        if name == 'Range':
5193101Sstever@eecs.umich.edu            return
5203101Sstever@eecs.umich.edu        cls.cxx_type = 'Range< %s >' % cls.type.cxx_type
5213101Sstever@eecs.umich.edu
5223101Sstever@eecs.umich.educlass Range(ParamValue):
5233101Sstever@eecs.umich.edu    __metaclass__ = MetaRange
5243101Sstever@eecs.umich.edu    type = Int # default; can be overridden in subclasses
5253101Sstever@eecs.umich.edu    def __init__(self, *args, **kwargs):
5263101Sstever@eecs.umich.edu        def handle_kwargs(self, kwargs):
5273101Sstever@eecs.umich.edu            if 'end' in kwargs:
5283101Sstever@eecs.umich.edu                self.second = self.type(kwargs.pop('end'))
5293101Sstever@eecs.umich.edu            elif 'size' in kwargs:
5303101Sstever@eecs.umich.edu                self.second = self.first + self.type(kwargs.pop('size')) - 1
5313101Sstever@eecs.umich.edu            else:
5323101Sstever@eecs.umich.edu                raise TypeError, "Either end or size must be specified"
5333101Sstever@eecs.umich.edu
5343101Sstever@eecs.umich.edu        if len(args) == 0:
5353101Sstever@eecs.umich.edu            self.first = self.type(kwargs.pop('start'))
5363101Sstever@eecs.umich.edu            handle_kwargs(self, kwargs)
5373101Sstever@eecs.umich.edu
5383101Sstever@eecs.umich.edu        elif len(args) == 1:
5393101Sstever@eecs.umich.edu            if kwargs:
5403101Sstever@eecs.umich.edu                self.first = self.type(args[0])
5413101Sstever@eecs.umich.edu                handle_kwargs(self, kwargs)
5423101Sstever@eecs.umich.edu            elif isinstance(args[0], Range):
5433101Sstever@eecs.umich.edu                self.first = self.type(args[0].first)
5443101Sstever@eecs.umich.edu                self.second = self.type(args[0].second)
5455219Ssaidi@eecs.umich.edu            elif isinstance(args[0], (list, tuple)):
5465219Ssaidi@eecs.umich.edu                self.first = self.type(args[0][0])
5475219Ssaidi@eecs.umich.edu                self.second = self.type(args[0][1])
5483101Sstever@eecs.umich.edu            else:
5493101Sstever@eecs.umich.edu                self.first = self.type(0)
5503101Sstever@eecs.umich.edu                self.second = self.type(args[0]) - 1
5513101Sstever@eecs.umich.edu
5523101Sstever@eecs.umich.edu        elif len(args) == 2:
5533101Sstever@eecs.umich.edu            self.first = self.type(args[0])
5543101Sstever@eecs.umich.edu            self.second = self.type(args[1])
5553101Sstever@eecs.umich.edu        else:
5563101Sstever@eecs.umich.edu            raise TypeError, "Too many arguments specified"
5573101Sstever@eecs.umich.edu
5583101Sstever@eecs.umich.edu        if kwargs:
5593101Sstever@eecs.umich.edu            raise TypeError, "too many keywords: %s" % kwargs.keys()
5603101Sstever@eecs.umich.edu
5613101Sstever@eecs.umich.edu    def __str__(self):
5623101Sstever@eecs.umich.edu        return '%s:%s' % (self.first, self.second)
5633101Sstever@eecs.umich.edu
5647673Snate@binkert.org    @classmethod
5657673Snate@binkert.org    def cxx_predecls(cls, code):
5667675Snate@binkert.org        cls.type.cxx_predecls(code)
5677673Snate@binkert.org        code('#include "base/range.hh"')
5687675Snate@binkert.org
5697675Snate@binkert.org    @classmethod
5707675Snate@binkert.org    def swig_predecls(cls, code):
5717675Snate@binkert.org        cls.type.swig_predecls(code)
5727675Snate@binkert.org        code('%import "python/swig/range.i"')
5737673Snate@binkert.org
5743101Sstever@eecs.umich.educlass AddrRange(Range):
5753101Sstever@eecs.umich.edu    type = Addr
5767673Snate@binkert.org
5774762Snate@binkert.org    def getValue(self):
5787675Snate@binkert.org        from m5.internal.range import AddrRange
5794762Snate@binkert.org
5804762Snate@binkert.org        value = AddrRange()
5814762Snate@binkert.org        value.start = long(self.first)
5824762Snate@binkert.org        value.end = long(self.second)
5834762Snate@binkert.org        return value
5843101Sstever@eecs.umich.edu
5853101Sstever@eecs.umich.educlass TickRange(Range):
5863101Sstever@eecs.umich.edu    type = Tick
5877673Snate@binkert.org
5884762Snate@binkert.org    def getValue(self):
5897675Snate@binkert.org        from m5.internal.range import TickRange
5904762Snate@binkert.org
5914762Snate@binkert.org        value = TickRange()
5924762Snate@binkert.org        value.start = long(self.first)
5934762Snate@binkert.org        value.end = long(self.second)
5944762Snate@binkert.org        return value
5953101Sstever@eecs.umich.edu
5963101Sstever@eecs.umich.edu# Boolean parameter type.  Python doesn't let you subclass bool, since
5973101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and
5983101Sstever@eecs.umich.edu# False.  Thus this is a little more complicated than String.
5993101Sstever@eecs.umich.educlass Bool(ParamValue):
6003101Sstever@eecs.umich.edu    cxx_type = 'bool'
6013101Sstever@eecs.umich.edu    def __init__(self, value):
6023101Sstever@eecs.umich.edu        try:
6033102Sstever@eecs.umich.edu            self.value = convert.toBool(value)
6043101Sstever@eecs.umich.edu        except TypeError:
6053101Sstever@eecs.umich.edu            self.value = bool(value)
6063101Sstever@eecs.umich.edu
6074762Snate@binkert.org    def getValue(self):
6084762Snate@binkert.org        return bool(self.value)
6094762Snate@binkert.org
6103101Sstever@eecs.umich.edu    def __str__(self):
6113101Sstever@eecs.umich.edu        return str(self.value)
6123101Sstever@eecs.umich.edu
6133101Sstever@eecs.umich.edu    def ini_str(self):
6143101Sstever@eecs.umich.edu        if self.value:
6153101Sstever@eecs.umich.edu            return 'true'
6163101Sstever@eecs.umich.edu        return 'false'
6173101Sstever@eecs.umich.edu
6183101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1):
6193101Sstever@eecs.umich.edu    bytes = map(lambda x: int(x, 16), addr.split(':'))
6203101Sstever@eecs.umich.edu    bytes[5] += val
6213101Sstever@eecs.umich.edu    for i in (5, 4, 3, 2, 1):
6223101Sstever@eecs.umich.edu        val,rem = divmod(bytes[i], 256)
6233101Sstever@eecs.umich.edu        bytes[i] = rem
6243101Sstever@eecs.umich.edu        if val == 0:
6253101Sstever@eecs.umich.edu            break
6263101Sstever@eecs.umich.edu        bytes[i - 1] += val
6273101Sstever@eecs.umich.edu    assert(bytes[0] <= 255)
6283101Sstever@eecs.umich.edu    return ':'.join(map(lambda x: '%02x' % x, bytes))
6293101Sstever@eecs.umich.edu
6304380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01"
6314380Sbinkertn@umich.edudef NextEthernetAddr():
6324380Sbinkertn@umich.edu    global _NextEthernetAddr
6333101Sstever@eecs.umich.edu
6344380Sbinkertn@umich.edu    value = _NextEthernetAddr
6354380Sbinkertn@umich.edu    _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1)
6364380Sbinkertn@umich.edu    return value
6373101Sstever@eecs.umich.edu
6383101Sstever@eecs.umich.educlass EthernetAddr(ParamValue):
6393101Sstever@eecs.umich.edu    cxx_type = 'Net::EthAddr'
6407673Snate@binkert.org
6417673Snate@binkert.org    @classmethod
6427673Snate@binkert.org    def cxx_predecls(cls, code):
6437673Snate@binkert.org        code('#include "base/inet.hh"')
6447673Snate@binkert.org
6457673Snate@binkert.org    @classmethod
6467673Snate@binkert.org    def swig_predecls(cls, code):
6477673Snate@binkert.org        code('%include "python/swig/inet.i"')
6487673Snate@binkert.org
6493101Sstever@eecs.umich.edu    def __init__(self, value):
6503101Sstever@eecs.umich.edu        if value == NextEthernetAddr:
6513101Sstever@eecs.umich.edu            self.value = value
6523101Sstever@eecs.umich.edu            return
6533101Sstever@eecs.umich.edu
6543101Sstever@eecs.umich.edu        if not isinstance(value, str):
6553101Sstever@eecs.umich.edu            raise TypeError, "expected an ethernet address and didn't get one"
6563101Sstever@eecs.umich.edu
6573101Sstever@eecs.umich.edu        bytes = value.split(':')
6583101Sstever@eecs.umich.edu        if len(bytes) != 6:
6593101Sstever@eecs.umich.edu            raise TypeError, 'invalid ethernet address %s' % value
6603101Sstever@eecs.umich.edu
6613101Sstever@eecs.umich.edu        for byte in bytes:
6627743Sgblack@eecs.umich.edu            if not 0 <= int(byte) <= 0xff:
6633101Sstever@eecs.umich.edu                raise TypeError, 'invalid ethernet address %s' % value
6643101Sstever@eecs.umich.edu
6653101Sstever@eecs.umich.edu        self.value = value
6663101Sstever@eecs.umich.edu
6673101Sstever@eecs.umich.edu    def unproxy(self, base):
6683101Sstever@eecs.umich.edu        if self.value == NextEthernetAddr:
6694380Sbinkertn@umich.edu            return EthernetAddr(self.value())
6703101Sstever@eecs.umich.edu        return self
6713101Sstever@eecs.umich.edu
6724762Snate@binkert.org    def getValue(self):
6737677Snate@binkert.org        from m5.internal.params import EthAddr
6744762Snate@binkert.org        return EthAddr(self.value)
6754762Snate@binkert.org
6764380Sbinkertn@umich.edu    def ini_str(self):
6774380Sbinkertn@umich.edu        return self.value
6783101Sstever@eecs.umich.edu
6797777Sgblack@eecs.umich.edu# When initializing an IpAddress, pass in an existing IpAddress, a string of
6807777Sgblack@eecs.umich.edu# the form "a.b.c.d", or an integer representing an IP.
6817777Sgblack@eecs.umich.educlass IpAddress(ParamValue):
6827777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpAddress'
6837777Sgblack@eecs.umich.edu
6847777Sgblack@eecs.umich.edu    @classmethod
6857777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
6867777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
6877777Sgblack@eecs.umich.edu
6887777Sgblack@eecs.umich.edu    @classmethod
6897777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
6907777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
6917777Sgblack@eecs.umich.edu
6927777Sgblack@eecs.umich.edu    def __init__(self, value):
6937777Sgblack@eecs.umich.edu        if isinstance(value, IpAddress):
6947777Sgblack@eecs.umich.edu            self.ip = value.ip
6957777Sgblack@eecs.umich.edu        else:
6967777Sgblack@eecs.umich.edu            try:
6977777Sgblack@eecs.umich.edu                self.ip = convert.toIpAddress(value)
6987777Sgblack@eecs.umich.edu            except TypeError:
6997777Sgblack@eecs.umich.edu                self.ip = long(value)
7007777Sgblack@eecs.umich.edu        self.verifyIp()
7017777Sgblack@eecs.umich.edu
7027777Sgblack@eecs.umich.edu    def verifyIp(self):
7037777Sgblack@eecs.umich.edu        if self.ip < 0 or self.ip >= (1 << 32):
7047798Sgblack@eecs.umich.edu            raise TypeError, "invalid ip address %#08x" % self.ip
7057777Sgblack@eecs.umich.edu
7067777Sgblack@eecs.umich.edu    def getValue(self):
7077777Sgblack@eecs.umich.edu        from m5.internal.params import IpAddress
7087777Sgblack@eecs.umich.edu        return IpAddress(self.ip)
7097777Sgblack@eecs.umich.edu
7107777Sgblack@eecs.umich.edu    def ini_str(self):
7117777Sgblack@eecs.umich.edu        return self.ip
7127777Sgblack@eecs.umich.edu
7137777Sgblack@eecs.umich.edu# When initializing an IpNetmask, pass in an existing IpNetmask, a string of
7147777Sgblack@eecs.umich.edu# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as
7157777Sgblack@eecs.umich.edu# positional or keyword arguments.
7167777Sgblack@eecs.umich.educlass IpNetmask(IpAddress):
7177777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpNetmask'
7187777Sgblack@eecs.umich.edu
7197777Sgblack@eecs.umich.edu    @classmethod
7207777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
7217777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
7227777Sgblack@eecs.umich.edu
7237777Sgblack@eecs.umich.edu    @classmethod
7247777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
7257777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
7267777Sgblack@eecs.umich.edu
7277777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
7287777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
7297777Sgblack@eecs.umich.edu            if key in kwargs:
7307777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
7317777Sgblack@eecs.umich.edu            elif elseVal:
7327777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
7337777Sgblack@eecs.umich.edu            else:
7347777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
7357777Sgblack@eecs.umich.edu
7367777Sgblack@eecs.umich.edu        if len(args) == 0:
7377777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
7387777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'netmask')
7397777Sgblack@eecs.umich.edu
7407777Sgblack@eecs.umich.edu        elif len(args) == 1:
7417777Sgblack@eecs.umich.edu            if kwargs:
7427777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'netmask' in kwargs:
7437777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
7447777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
7457777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'netmask', args[0])
7467777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpNetmask):
7477777Sgblack@eecs.umich.edu                self.ip = args[0].ip
7487777Sgblack@eecs.umich.edu                self.netmask = args[0].netmask
7497777Sgblack@eecs.umich.edu            else:
7507777Sgblack@eecs.umich.edu                (self.ip, self.netmask) = convert.toIpNetmask(args[0])
7517777Sgblack@eecs.umich.edu
7527777Sgblack@eecs.umich.edu        elif len(args) == 2:
7537777Sgblack@eecs.umich.edu            self.ip = args[0]
7547777Sgblack@eecs.umich.edu            self.netmask = args[1]
7557777Sgblack@eecs.umich.edu        else:
7567777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
7577777Sgblack@eecs.umich.edu
7587777Sgblack@eecs.umich.edu        if kwargs:
7597777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
7607777Sgblack@eecs.umich.edu
7617777Sgblack@eecs.umich.edu        self.verify()
7627777Sgblack@eecs.umich.edu
7637777Sgblack@eecs.umich.edu    def verify(self):
7647777Sgblack@eecs.umich.edu        self.verifyIp()
7657777Sgblack@eecs.umich.edu        if self.netmask < 0 or self.netmask > 32:
7667777Sgblack@eecs.umich.edu            raise TypeError, "invalid netmask %d" % netmask
7677777Sgblack@eecs.umich.edu
7687777Sgblack@eecs.umich.edu    def getValue(self):
7697777Sgblack@eecs.umich.edu        from m5.internal.params import IpNetmask
7707777Sgblack@eecs.umich.edu        return IpNetmask(self.ip, self.netmask)
7717777Sgblack@eecs.umich.edu
7727777Sgblack@eecs.umich.edu    def ini_str(self):
7737777Sgblack@eecs.umich.edu        return "%08x/%d" % (self.ip, self.netmask)
7747777Sgblack@eecs.umich.edu
7757777Sgblack@eecs.umich.edu# When initializing an IpWithPort, pass in an existing IpWithPort, a string of
7767777Sgblack@eecs.umich.edu# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments.
7777777Sgblack@eecs.umich.educlass IpWithPort(IpAddress):
7787777Sgblack@eecs.umich.edu    cxx_type = 'Net::IpWithPort'
7797777Sgblack@eecs.umich.edu
7807777Sgblack@eecs.umich.edu    @classmethod
7817777Sgblack@eecs.umich.edu    def cxx_predecls(cls, code):
7827777Sgblack@eecs.umich.edu        code('#include "base/inet.hh"')
7837777Sgblack@eecs.umich.edu
7847777Sgblack@eecs.umich.edu    @classmethod
7857777Sgblack@eecs.umich.edu    def swig_predecls(cls, code):
7867777Sgblack@eecs.umich.edu        code('%include "python/swig/inet.i"')
7877777Sgblack@eecs.umich.edu
7887777Sgblack@eecs.umich.edu    def __init__(self, *args, **kwargs):
7897777Sgblack@eecs.umich.edu        def handle_kwarg(self, kwargs, key, elseVal = None):
7907777Sgblack@eecs.umich.edu            if key in kwargs:
7917777Sgblack@eecs.umich.edu                setattr(self, key, kwargs.pop(key))
7927777Sgblack@eecs.umich.edu            elif elseVal:
7937777Sgblack@eecs.umich.edu                setattr(self, key, elseVal)
7947777Sgblack@eecs.umich.edu            else:
7957777Sgblack@eecs.umich.edu                raise TypeError, "No value set for %s" % key
7967777Sgblack@eecs.umich.edu
7977777Sgblack@eecs.umich.edu        if len(args) == 0:
7987777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'ip')
7997777Sgblack@eecs.umich.edu            handle_kwarg(self, kwargs, 'port')
8007777Sgblack@eecs.umich.edu
8017777Sgblack@eecs.umich.edu        elif len(args) == 1:
8027777Sgblack@eecs.umich.edu            if kwargs:
8037777Sgblack@eecs.umich.edu                if not 'ip' in kwargs and not 'port' in kwargs:
8047777Sgblack@eecs.umich.edu                    raise TypeError, "Invalid arguments"
8057777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'ip', args[0])
8067777Sgblack@eecs.umich.edu                handle_kwarg(self, kwargs, 'port', args[0])
8077777Sgblack@eecs.umich.edu            elif isinstance(args[0], IpWithPort):
8087777Sgblack@eecs.umich.edu                self.ip = args[0].ip
8097777Sgblack@eecs.umich.edu                self.port = args[0].port
8107777Sgblack@eecs.umich.edu            else:
8117777Sgblack@eecs.umich.edu                (self.ip, self.port) = convert.toIpWithPort(args[0])
8127777Sgblack@eecs.umich.edu
8137777Sgblack@eecs.umich.edu        elif len(args) == 2:
8147777Sgblack@eecs.umich.edu            self.ip = args[0]
8157777Sgblack@eecs.umich.edu            self.port = args[1]
8167777Sgblack@eecs.umich.edu        else:
8177777Sgblack@eecs.umich.edu            raise TypeError, "Too many arguments specified"
8187777Sgblack@eecs.umich.edu
8197777Sgblack@eecs.umich.edu        if kwargs:
8207777Sgblack@eecs.umich.edu            raise TypeError, "Too many keywords: %s" % kwargs.keys()
8217777Sgblack@eecs.umich.edu
8227777Sgblack@eecs.umich.edu        self.verify()
8237777Sgblack@eecs.umich.edu
8247777Sgblack@eecs.umich.edu    def verify(self):
8257777Sgblack@eecs.umich.edu        self.verifyIp()
8267777Sgblack@eecs.umich.edu        if self.port < 0 or self.port > 0xffff:
8277777Sgblack@eecs.umich.edu            raise TypeError, "invalid port %d" % self.port
8287777Sgblack@eecs.umich.edu
8297777Sgblack@eecs.umich.edu    def getValue(self):
8307777Sgblack@eecs.umich.edu        from m5.internal.params import IpWithPort
8317777Sgblack@eecs.umich.edu        return IpWithPort(self.ip, self.port)
8327777Sgblack@eecs.umich.edu
8337777Sgblack@eecs.umich.edu    def ini_str(self):
8347777Sgblack@eecs.umich.edu        return "%08x:%d" % (self.ip, self.port)
8357777Sgblack@eecs.umich.edu
8363932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y",
8373932Sbinkertn@umich.edu                 "%a %b %d %H:%M:%S %Z %Y",
8383932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M:%S",
8393932Sbinkertn@umich.edu                 "%Y/%m/%d %H:%M",
8403932Sbinkertn@umich.edu                 "%Y/%m/%d",
8413932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M:%S",
8423932Sbinkertn@umich.edu                 "%m/%d/%Y %H:%M",
8433932Sbinkertn@umich.edu                 "%m/%d/%Y",
8443932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M:%S",
8453932Sbinkertn@umich.edu                 "%m/%d/%y %H:%M",
8463932Sbinkertn@umich.edu                 "%m/%d/%y"]
8473932Sbinkertn@umich.edu
8483932Sbinkertn@umich.edu
8493885Sbinkertn@umich.edudef parse_time(value):
8503932Sbinkertn@umich.edu    from time import gmtime, strptime, struct_time, time
8513932Sbinkertn@umich.edu    from datetime import datetime, date
8523885Sbinkertn@umich.edu
8533932Sbinkertn@umich.edu    if isinstance(value, struct_time):
8543932Sbinkertn@umich.edu        return value
8553932Sbinkertn@umich.edu
8563932Sbinkertn@umich.edu    if isinstance(value, (int, long)):
8573932Sbinkertn@umich.edu        return gmtime(value)
8583932Sbinkertn@umich.edu
8593932Sbinkertn@umich.edu    if isinstance(value, (datetime, date)):
8603932Sbinkertn@umich.edu        return value.timetuple()
8613932Sbinkertn@umich.edu
8623932Sbinkertn@umich.edu    if isinstance(value, str):
8633932Sbinkertn@umich.edu        if value in ('Now', 'Today'):
8643932Sbinkertn@umich.edu            return time.gmtime(time.time())
8653932Sbinkertn@umich.edu
8663932Sbinkertn@umich.edu        for format in time_formats:
8673932Sbinkertn@umich.edu            try:
8683932Sbinkertn@umich.edu                return strptime(value, format)
8693932Sbinkertn@umich.edu            except ValueError:
8703932Sbinkertn@umich.edu                pass
8713885Sbinkertn@umich.edu
8723885Sbinkertn@umich.edu    raise ValueError, "Could not parse '%s' as a time" % value
8733885Sbinkertn@umich.edu
8743885Sbinkertn@umich.educlass Time(ParamValue):
8754762Snate@binkert.org    cxx_type = 'tm'
8767673Snate@binkert.org
8777673Snate@binkert.org    @classmethod
8787673Snate@binkert.org    def cxx_predecls(cls, code):
8797673Snate@binkert.org        code('#include <time.h>')
8807673Snate@binkert.org
8817673Snate@binkert.org    @classmethod
8827673Snate@binkert.org    def swig_predecls(cls, code):
8837673Snate@binkert.org        code('%include "python/swig/time.i"')
8847673Snate@binkert.org
8853885Sbinkertn@umich.edu    def __init__(self, value):
8863932Sbinkertn@umich.edu        self.value = parse_time(value)
8873885Sbinkertn@umich.edu
8884762Snate@binkert.org    def getValue(self):
8897677Snate@binkert.org        from m5.internal.params import tm
8904762Snate@binkert.org
8914762Snate@binkert.org        c_time = tm()
8924762Snate@binkert.org        py_time = self.value
8934762Snate@binkert.org
8944762Snate@binkert.org        # UNIX is years since 1900
8954762Snate@binkert.org        c_time.tm_year = py_time.tm_year - 1900;
8964762Snate@binkert.org
8974762Snate@binkert.org        # Python starts at 1, UNIX starts at 0
8984762Snate@binkert.org        c_time.tm_mon =  py_time.tm_mon - 1;
8994762Snate@binkert.org        c_time.tm_mday = py_time.tm_mday;
9004762Snate@binkert.org        c_time.tm_hour = py_time.tm_hour;
9014762Snate@binkert.org        c_time.tm_min = py_time.tm_min;
9024762Snate@binkert.org        c_time.tm_sec = py_time.tm_sec;
9034762Snate@binkert.org
9044762Snate@binkert.org        # Python has 0 as Monday, UNIX is 0 as sunday
9054762Snate@binkert.org        c_time.tm_wday = py_time.tm_wday + 1
9064762Snate@binkert.org        if c_time.tm_wday > 6:
9074762Snate@binkert.org            c_time.tm_wday -= 7;
9084762Snate@binkert.org
9094762Snate@binkert.org        # Python starts at 1, Unix starts at 0
9104762Snate@binkert.org        c_time.tm_yday = py_time.tm_yday - 1;
9114762Snate@binkert.org
9124762Snate@binkert.org        return c_time
9134762Snate@binkert.org
9143885Sbinkertn@umich.edu    def __str__(self):
9154762Snate@binkert.org        return time.asctime(self.value)
9163885Sbinkertn@umich.edu
9173885Sbinkertn@umich.edu    def ini_str(self):
9183932Sbinkertn@umich.edu        return str(self)
9193885Sbinkertn@umich.edu
9203101Sstever@eecs.umich.edu# Enumerated types are a little more complex.  The user specifies the
9213101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of
9223101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so).  (In the
9233101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index
9243101Sstever@eecs.umich.edu# or the corresponding dictionary value.  For now, since we only check
9253101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file,
9263101Sstever@eecs.umich.edu# there's not much point in using the dictionary.)
9273101Sstever@eecs.umich.edu
9283101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the
9293101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter
9303101Sstever@eecs.umich.edu# can be instances of that type.  We define two hidden internal
9313101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then
9323101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly.
9333101Sstever@eecs.umich.edu
9344762Snate@binkert.orgallEnums = {}
9353101Sstever@eecs.umich.edu# Metaclass for Enum types
9365033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue):
9374762Snate@binkert.org    def __new__(mcls, name, bases, dict):
9384762Snate@binkert.org        assert name not in allEnums
9394762Snate@binkert.org
9404762Snate@binkert.org        cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict)
9414762Snate@binkert.org        allEnums[name] = cls
9424762Snate@binkert.org        return cls
9434762Snate@binkert.org
9443101Sstever@eecs.umich.edu    def __init__(cls, name, bases, init_dict):
9453101Sstever@eecs.umich.edu        if init_dict.has_key('map'):
9463101Sstever@eecs.umich.edu            if not isinstance(cls.map, dict):
9473101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'map' " \
9483101Sstever@eecs.umich.edu                      "must be of type dict"
9493101Sstever@eecs.umich.edu            # build list of value strings from map
9503101Sstever@eecs.umich.edu            cls.vals = cls.map.keys()
9513101Sstever@eecs.umich.edu            cls.vals.sort()
9523101Sstever@eecs.umich.edu        elif init_dict.has_key('vals'):
9533101Sstever@eecs.umich.edu            if not isinstance(cls.vals, list):
9543101Sstever@eecs.umich.edu                raise TypeError, "Enum-derived class attribute 'vals' " \
9553101Sstever@eecs.umich.edu                      "must be of type list"
9563101Sstever@eecs.umich.edu            # build string->value map from vals sequence
9573101Sstever@eecs.umich.edu            cls.map = {}
9583101Sstever@eecs.umich.edu            for idx,val in enumerate(cls.vals):
9593101Sstever@eecs.umich.edu                cls.map[val] = idx
9603101Sstever@eecs.umich.edu        else:
9613101Sstever@eecs.umich.edu            raise TypeError, "Enum-derived class must define "\
9623101Sstever@eecs.umich.edu                  "attribute 'map' or 'vals'"
9633101Sstever@eecs.umich.edu
9644762Snate@binkert.org        cls.cxx_type = 'Enums::%s' % name
9653101Sstever@eecs.umich.edu
9663101Sstever@eecs.umich.edu        super(MetaEnum, cls).__init__(name, bases, init_dict)
9673101Sstever@eecs.umich.edu
9683101Sstever@eecs.umich.edu    # Generate C++ class declaration for this enum type.
9693101Sstever@eecs.umich.edu    # Note that we wrap the enum in a class/struct to act as a namespace,
9703101Sstever@eecs.umich.edu    # so that the enum strings can be brief w/o worrying about collisions.
9717673Snate@binkert.org    def cxx_decl(cls, code):
9726654Snate@binkert.org        name = cls.__name__
9737673Snate@binkert.org        code('''\
9747673Snate@binkert.org#ifndef __ENUM__${name}__
9757673Snate@binkert.org#define __ENUM__${name}__
9767673Snate@binkert.org
9777673Snate@binkert.orgnamespace Enums {
9787673Snate@binkert.org    enum $name {
9797673Snate@binkert.org''')
9807673Snate@binkert.org        code.indent(2)
9814762Snate@binkert.org        for val in cls.vals:
9827673Snate@binkert.org            code('$val = ${{cls.map[val]}},')
9837673Snate@binkert.org        code('Num_$name = ${{len(cls.vals)}},')
9847673Snate@binkert.org        code.dedent(2)
9857673Snate@binkert.org        code('''\
9867673Snate@binkert.org    };
9877673Snate@binkert.orgextern const char *${name}Strings[Num_${name}];
9887673Snate@binkert.org}
9894762Snate@binkert.org
9907673Snate@binkert.org#endif // __ENUM__${name}__
9917673Snate@binkert.org''')
9927673Snate@binkert.org
9937673Snate@binkert.org    def cxx_def(cls, code):
9946654Snate@binkert.org        name = cls.__name__
9957673Snate@binkert.org        code('''\
9967677Snate@binkert.org#include "enums/$name.hh"
9977673Snate@binkert.orgnamespace Enums {
9987673Snate@binkert.org    const char *${name}Strings[Num_${name}] =
9997673Snate@binkert.org    {
10007673Snate@binkert.org''')
10017673Snate@binkert.org        code.indent(2)
10024762Snate@binkert.org        for val in cls.vals:
10037673Snate@binkert.org            code('"$val",')
10047673Snate@binkert.org        code.dedent(2)
10057673Snate@binkert.org        code('''
10067673Snate@binkert.org    };
10077811Ssteve.reinhardt@amd.com} // namespace Enums
10087673Snate@binkert.org''')
10093101Sstever@eecs.umich.edu
10103101Sstever@eecs.umich.edu# Base class for enum types.
10113101Sstever@eecs.umich.educlass Enum(ParamValue):
10123101Sstever@eecs.umich.edu    __metaclass__ = MetaEnum
10133101Sstever@eecs.umich.edu    vals = []
10143101Sstever@eecs.umich.edu
10153101Sstever@eecs.umich.edu    def __init__(self, value):
10163101Sstever@eecs.umich.edu        if value not in self.map:
10173101Sstever@eecs.umich.edu            raise TypeError, "Enum param got bad value '%s' (not in %s)" \
10183101Sstever@eecs.umich.edu                  % (value, self.vals)
10193101Sstever@eecs.umich.edu        self.value = value
10203101Sstever@eecs.umich.edu
10217675Snate@binkert.org    @classmethod
10227675Snate@binkert.org    def cxx_predecls(cls, code):
10237675Snate@binkert.org        code('#include "enums/$0.hh"', cls.__name__)
10247675Snate@binkert.org
10257675Snate@binkert.org    @classmethod
10267675Snate@binkert.org    def swig_predecls(cls, code):
10277677Snate@binkert.org        code('%import "python/m5/internal/enum_$0.i"', cls.__name__)
10287675Snate@binkert.org
10294762Snate@binkert.org    def getValue(self):
10304762Snate@binkert.org        return int(self.map[self.value])
10314762Snate@binkert.org
10323101Sstever@eecs.umich.edu    def __str__(self):
10333101Sstever@eecs.umich.edu        return self.value
10343101Sstever@eecs.umich.edu
10353101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it?
10363101Sstever@eecs.umich.edufrequency_tolerance = 0.001  # 0.1%
10373101Sstever@eecs.umich.edu
10384167Sbinkertn@umich.educlass TickParamValue(NumericParamValue):
10393101Sstever@eecs.umich.edu    cxx_type = 'Tick'
10407673Snate@binkert.org
10417673Snate@binkert.org    @classmethod
10427673Snate@binkert.org    def cxx_predecls(cls, code):
10437673Snate@binkert.org        code('#include "base/types.hh"')
10447673Snate@binkert.org
10457673Snate@binkert.org    @classmethod
10467673Snate@binkert.org    def swig_predecls(cls, code):
10477673Snate@binkert.org        code('%import "stdint.i"')
10487673Snate@binkert.org        code('%import "base/types.hh"')
10494167Sbinkertn@umich.edu
10504762Snate@binkert.org    def getValue(self):
10514762Snate@binkert.org        return long(self.value)
10524762Snate@binkert.org
10534167Sbinkertn@umich.educlass Latency(TickParamValue):
10543101Sstever@eecs.umich.edu    def __init__(self, value):
10554167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
10564167Sbinkertn@umich.edu            self.ticks = value.ticks
10574167Sbinkertn@umich.edu            self.value = value.value
10584167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
10594167Sbinkertn@umich.edu            self.ticks = value.ticks
10604167Sbinkertn@umich.edu            self.value = 1.0 / value.value
10614167Sbinkertn@umich.edu        elif value.endswith('t'):
10624167Sbinkertn@umich.edu            self.ticks = True
10634167Sbinkertn@umich.edu            self.value = int(value[:-1])
10644167Sbinkertn@umich.edu        else:
10654167Sbinkertn@umich.edu            self.ticks = False
10664167Sbinkertn@umich.edu            self.value = convert.toLatency(value)
10673101Sstever@eecs.umich.edu
10683101Sstever@eecs.umich.edu    def __getattr__(self, attr):
10693101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
10703101Sstever@eecs.umich.edu            return self
10713101Sstever@eecs.umich.edu        if attr == 'frequency':
10723101Sstever@eecs.umich.edu            return Frequency(self)
10733101Sstever@eecs.umich.edu        raise AttributeError, "Latency object has no attribute '%s'" % attr
10743101Sstever@eecs.umich.edu
10754762Snate@binkert.org    def getValue(self):
10764762Snate@binkert.org        if self.ticks or self.value == 0:
10774762Snate@binkert.org            value = self.value
10784762Snate@binkert.org        else:
10794762Snate@binkert.org            value = ticks.fromSeconds(self.value)
10804762Snate@binkert.org        return long(value)
10814762Snate@binkert.org
10823101Sstever@eecs.umich.edu    # convert latency to ticks
10833101Sstever@eecs.umich.edu    def ini_str(self):
10844762Snate@binkert.org        return '%d' % self.getValue()
10853101Sstever@eecs.umich.edu
10864167Sbinkertn@umich.educlass Frequency(TickParamValue):
10873101Sstever@eecs.umich.edu    def __init__(self, value):
10884167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
10894167Sbinkertn@umich.edu            if value.value == 0:
10904167Sbinkertn@umich.edu                self.value = 0
10914167Sbinkertn@umich.edu            else:
10924167Sbinkertn@umich.edu                self.value = 1.0 / value.value
10934167Sbinkertn@umich.edu            self.ticks = value.ticks
10944167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
10954167Sbinkertn@umich.edu            self.value = value.value
10964167Sbinkertn@umich.edu            self.ticks = value.ticks
10974167Sbinkertn@umich.edu        else:
10984167Sbinkertn@umich.edu            self.ticks = False
10994167Sbinkertn@umich.edu            self.value = convert.toFrequency(value)
11003101Sstever@eecs.umich.edu
11013101Sstever@eecs.umich.edu    def __getattr__(self, attr):
11023101Sstever@eecs.umich.edu        if attr == 'frequency':
11033101Sstever@eecs.umich.edu            return self
11043101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
11053101Sstever@eecs.umich.edu            return Latency(self)
11063101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
11073101Sstever@eecs.umich.edu
11084167Sbinkertn@umich.edu    # convert latency to ticks
11094762Snate@binkert.org    def getValue(self):
11104762Snate@binkert.org        if self.ticks or self.value == 0:
11114762Snate@binkert.org            value = self.value
11124762Snate@binkert.org        else:
11134762Snate@binkert.org            value = ticks.fromSeconds(1.0 / self.value)
11144762Snate@binkert.org        return long(value)
11154762Snate@binkert.org
11163101Sstever@eecs.umich.edu    def ini_str(self):
11174762Snate@binkert.org        return '%d' % self.getValue()
11183101Sstever@eecs.umich.edu
11193101Sstever@eecs.umich.edu# A generic frequency and/or Latency value.  Value is stored as a latency,
11203101Sstever@eecs.umich.edu# but to avoid ambiguity this object does not support numeric ops (* or /).
11213101Sstever@eecs.umich.edu# An explicit conversion to a Latency or Frequency must be made first.
11223101Sstever@eecs.umich.educlass Clock(ParamValue):
11233101Sstever@eecs.umich.edu    cxx_type = 'Tick'
11247673Snate@binkert.org
11257673Snate@binkert.org    @classmethod
11267673Snate@binkert.org    def cxx_predecls(cls, code):
11277673Snate@binkert.org        code('#include "base/types.hh"')
11287673Snate@binkert.org
11297673Snate@binkert.org    @classmethod
11307673Snate@binkert.org    def swig_predecls(cls, code):
11317673Snate@binkert.org        code('%import "stdint.i"')
11327673Snate@binkert.org        code('%import "base/types.hh"')
11337673Snate@binkert.org
11343101Sstever@eecs.umich.edu    def __init__(self, value):
11354167Sbinkertn@umich.edu        if isinstance(value, (Latency, Clock)):
11364167Sbinkertn@umich.edu            self.ticks = value.ticks
11374167Sbinkertn@umich.edu            self.value = value.value
11384167Sbinkertn@umich.edu        elif isinstance(value, Frequency):
11394167Sbinkertn@umich.edu            self.ticks = value.ticks
11404167Sbinkertn@umich.edu            self.value = 1.0 / value.value
11414167Sbinkertn@umich.edu        elif value.endswith('t'):
11424167Sbinkertn@umich.edu            self.ticks = True
11434167Sbinkertn@umich.edu            self.value = int(value[:-1])
11444167Sbinkertn@umich.edu        else:
11454167Sbinkertn@umich.edu            self.ticks = False
11464167Sbinkertn@umich.edu            self.value = convert.anyToLatency(value)
11473101Sstever@eecs.umich.edu
11483101Sstever@eecs.umich.edu    def __getattr__(self, attr):
11493101Sstever@eecs.umich.edu        if attr == 'frequency':
11503101Sstever@eecs.umich.edu            return Frequency(self)
11513101Sstever@eecs.umich.edu        if attr in ('latency', 'period'):
11523101Sstever@eecs.umich.edu            return Latency(self)
11533101Sstever@eecs.umich.edu        raise AttributeError, "Frequency object has no attribute '%s'" % attr
11543101Sstever@eecs.umich.edu
11554762Snate@binkert.org    def getValue(self):
11564762Snate@binkert.org        return self.period.getValue()
11574762Snate@binkert.org
11583101Sstever@eecs.umich.edu    def ini_str(self):
11593101Sstever@eecs.umich.edu        return self.period.ini_str()
11603101Sstever@eecs.umich.edu
11613101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue):
11623101Sstever@eecs.umich.edu    cxx_type = 'float'
11633101Sstever@eecs.umich.edu    def __new__(cls, value):
11644167Sbinkertn@umich.edu        # convert to bits per second
11654167Sbinkertn@umich.edu        val = convert.toNetworkBandwidth(value)
11663101Sstever@eecs.umich.edu        return super(cls, NetworkBandwidth).__new__(cls, val)
11673101Sstever@eecs.umich.edu
11683101Sstever@eecs.umich.edu    def __str__(self):
11693101Sstever@eecs.umich.edu        return str(self.val)
11703101Sstever@eecs.umich.edu
11714762Snate@binkert.org    def getValue(self):
11724167Sbinkertn@umich.edu        # convert to seconds per byte
11734167Sbinkertn@umich.edu        value = 8.0 / float(self)
11744167Sbinkertn@umich.edu        # convert to ticks per byte
11754762Snate@binkert.org        value = ticks.fromSeconds(value)
11764762Snate@binkert.org        return float(value)
11774762Snate@binkert.org
11784762Snate@binkert.org    def ini_str(self):
11794762Snate@binkert.org        return '%f' % self.getValue()
11803101Sstever@eecs.umich.edu
11813101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue):
11823101Sstever@eecs.umich.edu    cxx_type = 'float'
11835469Snate@binkert.org    def __new__(cls, value):
11847743Sgblack@eecs.umich.edu        # convert to bytes per second
11853102Sstever@eecs.umich.edu        val = convert.toMemoryBandwidth(value)
11863101Sstever@eecs.umich.edu        return super(cls, MemoryBandwidth).__new__(cls, val)
11873101Sstever@eecs.umich.edu
11883101Sstever@eecs.umich.edu    def __str__(self):
11893101Sstever@eecs.umich.edu        return str(self.val)
11903101Sstever@eecs.umich.edu
11914762Snate@binkert.org    def getValue(self):
11924167Sbinkertn@umich.edu        # convert to seconds per byte
11935468Snate@binkert.org        value = float(self)
11945468Snate@binkert.org        if value:
11955468Snate@binkert.org            value = 1.0 / float(self)
11964167Sbinkertn@umich.edu        # convert to ticks per byte
11974762Snate@binkert.org        value = ticks.fromSeconds(value)
11984762Snate@binkert.org        return float(value)
11994762Snate@binkert.org
12004762Snate@binkert.org    def ini_str(self):
12014762Snate@binkert.org        return '%f' % self.getValue()
12023101Sstever@eecs.umich.edu
12033101Sstever@eecs.umich.edu#
12043101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values.
12053101Sstever@eecs.umich.edu#
12063101Sstever@eecs.umich.edu
12073102Sstever@eecs.umich.edu# Special class for NULL pointers.  Note the special check in
12083102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a
12093102Sstever@eecs.umich.edu# SimObject is required.
12103102Sstever@eecs.umich.edu# only one copy of a particular node
12113102Sstever@eecs.umich.educlass NullSimObject(object):
12123102Sstever@eecs.umich.edu    __metaclass__ = Singleton
12133102Sstever@eecs.umich.edu
12143102Sstever@eecs.umich.edu    def __call__(cls):
12153102Sstever@eecs.umich.edu        return cls
12163102Sstever@eecs.umich.edu
12173102Sstever@eecs.umich.edu    def _instantiate(self, parent = None, path = ''):
12183102Sstever@eecs.umich.edu        pass
12193102Sstever@eecs.umich.edu
12203102Sstever@eecs.umich.edu    def ini_str(self):
12213102Sstever@eecs.umich.edu        return 'Null'
12223102Sstever@eecs.umich.edu
12233102Sstever@eecs.umich.edu    def unproxy(self, base):
12243102Sstever@eecs.umich.edu        return self
12253102Sstever@eecs.umich.edu
12263102Sstever@eecs.umich.edu    def set_path(self, parent, name):
12273102Sstever@eecs.umich.edu        pass
12284762Snate@binkert.org
12293102Sstever@eecs.umich.edu    def __str__(self):
12303102Sstever@eecs.umich.edu        return 'Null'
12313102Sstever@eecs.umich.edu
12324762Snate@binkert.org    def getValue(self):
12334762Snate@binkert.org        return None
12344762Snate@binkert.org
12353102Sstever@eecs.umich.edu# The only instance you'll ever need...
12363102Sstever@eecs.umich.eduNULL = NullSimObject()
12373102Sstever@eecs.umich.edu
12383102Sstever@eecs.umich.edudef isNullPointer(value):
12393102Sstever@eecs.umich.edu    return isinstance(value, NullSimObject)
12403102Sstever@eecs.umich.edu
12413101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound.
12423101Sstever@eecs.umich.eduMaxAddr = Addr.max
12433101Sstever@eecs.umich.eduMaxTick = Tick.max
12443101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr)
12453101Sstever@eecs.umich.edu
12463101Sstever@eecs.umich.edu
12473101Sstever@eecs.umich.edu#####################################################################
12483101Sstever@eecs.umich.edu#
12493101Sstever@eecs.umich.edu# Port objects
12503101Sstever@eecs.umich.edu#
12513101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system.
12523101Sstever@eecs.umich.edu#
12533101Sstever@eecs.umich.edu#####################################################################
12543101Sstever@eecs.umich.edu
12553101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a
12563101Sstever@eecs.umich.edu# particular SimObject.
12573101Sstever@eecs.umich.educlass PortRef(object):
12583105Sstever@eecs.umich.edu    def __init__(self, simobj, name):
12593105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
12603101Sstever@eecs.umich.edu        self.simobj = simobj
12613101Sstever@eecs.umich.edu        self.name = name
12623101Sstever@eecs.umich.edu        self.peer = None   # not associated with another port yet
12633101Sstever@eecs.umich.edu        self.ccConnected = False # C++ port connection done?
12643105Sstever@eecs.umich.edu        self.index = -1  # always -1 for non-vector ports
12653101Sstever@eecs.umich.edu
12663103Sstever@eecs.umich.edu    def __str__(self):
12673105Sstever@eecs.umich.edu        return '%s.%s' % (self.simobj, self.name)
12683103Sstever@eecs.umich.edu
12693105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
12703105Sstever@eecs.umich.edu    def ini_str(self):
12713105Sstever@eecs.umich.edu        return str(self.peer)
12723105Sstever@eecs.umich.edu
12733105Sstever@eecs.umich.edu    def __getattr__(self, attr):
12743105Sstever@eecs.umich.edu        if attr == 'peerObj':
12753105Sstever@eecs.umich.edu            # shorthand for proxies
12763105Sstever@eecs.umich.edu            return self.peer.simobj
12773105Sstever@eecs.umich.edu        raise AttributeError, "'%s' object has no attribute '%s'" % \
12783105Sstever@eecs.umich.edu              (self.__class__.__name__, attr)
12793105Sstever@eecs.umich.edu
12803105Sstever@eecs.umich.edu    # Full connection is symmetric (both ways).  Called via
12813105Sstever@eecs.umich.edu    # SimObject.__setattr__ as a result of a port assignment, e.g.,
12823109Sstever@eecs.umich.edu    # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__,
12833105Sstever@eecs.umich.edu    # e.g., "obj1.portA[3] = obj2.portB".
12843105Sstever@eecs.umich.edu    def connect(self, other):
12853105Sstever@eecs.umich.edu        if isinstance(other, VectorPortRef):
12863105Sstever@eecs.umich.edu            # reference to plain VectorPort is implicit append
12873105Sstever@eecs.umich.edu            other = other._get_next()
12883105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
12893105Sstever@eecs.umich.edu            print "warning: overwriting port", self, \
12903105Sstever@eecs.umich.edu                  "value", self.peer, "with", other
12915578SSteve.Reinhardt@amd.com            self.peer.peer = None
12923101Sstever@eecs.umich.edu        self.peer = other
12933109Sstever@eecs.umich.edu        if proxy.isproxy(other):
12943109Sstever@eecs.umich.edu            other.set_param_desc(PortParamDesc())
12953109Sstever@eecs.umich.edu        elif isinstance(other, PortRef):
12963109Sstever@eecs.umich.edu            if other.peer is not self:
12973109Sstever@eecs.umich.edu                other.connect(self)
12983109Sstever@eecs.umich.edu        else:
12993109Sstever@eecs.umich.edu            raise TypeError, \
13003109Sstever@eecs.umich.edu                  "assigning non-port reference '%s' to port '%s'" \
13013109Sstever@eecs.umich.edu                  % (other, self)
13023101Sstever@eecs.umich.edu
13033105Sstever@eecs.umich.edu    def clone(self, simobj, memo):
13043105Sstever@eecs.umich.edu        if memo.has_key(self):
13053105Sstever@eecs.umich.edu            return memo[self]
13063101Sstever@eecs.umich.edu        newRef = copy.copy(self)
13073105Sstever@eecs.umich.edu        memo[self] = newRef
13083105Sstever@eecs.umich.edu        newRef.simobj = simobj
13093101Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
13103105Sstever@eecs.umich.edu        if self.peer and not proxy.isproxy(self.peer):
13113179Sstever@eecs.umich.edu            peerObj = self.peer.simobj(_memo=memo)
13123105Sstever@eecs.umich.edu            newRef.peer = self.peer.clone(peerObj, memo)
13133105Sstever@eecs.umich.edu            assert(not isinstance(newRef.peer, VectorPortRef))
13143101Sstever@eecs.umich.edu        return newRef
13153101Sstever@eecs.umich.edu
13163105Sstever@eecs.umich.edu    def unproxy(self, simobj):
13173105Sstever@eecs.umich.edu        assert(simobj is self.simobj)
13183105Sstever@eecs.umich.edu        if proxy.isproxy(self.peer):
13193105Sstever@eecs.umich.edu            try:
13203105Sstever@eecs.umich.edu                realPeer = self.peer.unproxy(self.simobj)
13213105Sstever@eecs.umich.edu            except:
13223105Sstever@eecs.umich.edu                print "Error in unproxying port '%s' of %s" % \
13233105Sstever@eecs.umich.edu                      (self.name, self.simobj.path())
13243105Sstever@eecs.umich.edu                raise
13253105Sstever@eecs.umich.edu            self.connect(realPeer)
13263105Sstever@eecs.umich.edu
13273101Sstever@eecs.umich.edu    # Call C++ to create corresponding port connection between C++ objects
13283101Sstever@eecs.umich.edu    def ccConnect(self):
13297677Snate@binkert.org        from m5.internal.params import connectPorts
13304762Snate@binkert.org
13313101Sstever@eecs.umich.edu        if self.ccConnected: # already done this
13323101Sstever@eecs.umich.edu            return
13333101Sstever@eecs.umich.edu        peer = self.peer
13345578SSteve.Reinhardt@amd.com        if not self.peer: # nothing to connect to
13355578SSteve.Reinhardt@amd.com            return
13367526Ssteve.reinhardt@amd.com        try:
13377526Ssteve.reinhardt@amd.com            connectPorts(self.simobj.getCCObject(), self.name, self.index,
13387526Ssteve.reinhardt@amd.com                         peer.simobj.getCCObject(), peer.name, peer.index)
13397526Ssteve.reinhardt@amd.com        except:
13407526Ssteve.reinhardt@amd.com            print "Error connecting port %s.%s to %s.%s" % \
13417526Ssteve.reinhardt@amd.com                  (self.simobj.path(), self.name,
13427526Ssteve.reinhardt@amd.com                   peer.simobj.path(), peer.name)
13437526Ssteve.reinhardt@amd.com            raise
13443101Sstever@eecs.umich.edu        self.ccConnected = True
13453101Sstever@eecs.umich.edu        peer.ccConnected = True
13463101Sstever@eecs.umich.edu
13473105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a
13483105Sstever@eecs.umich.edu# PortRef, but has an index.
13493105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef):
13503105Sstever@eecs.umich.edu    def __init__(self, simobj, name, index):
13513105Sstever@eecs.umich.edu        PortRef.__init__(self, simobj, name)
13523105Sstever@eecs.umich.edu        self.index = index
13533105Sstever@eecs.umich.edu
13543105Sstever@eecs.umich.edu    def __str__(self):
13553105Sstever@eecs.umich.edu        return '%s.%s[%d]' % (self.simobj, self.name, self.index)
13563105Sstever@eecs.umich.edu
13573105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element).
13583105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances.
13593105Sstever@eecs.umich.educlass VectorPortRef(object):
13603105Sstever@eecs.umich.edu    def __init__(self, simobj, name):
13613105Sstever@eecs.umich.edu        assert(isSimObject(simobj) or isSimObjectClass(simobj))
13623105Sstever@eecs.umich.edu        self.simobj = simobj
13633105Sstever@eecs.umich.edu        self.name = name
13643105Sstever@eecs.umich.edu        self.elements = []
13653105Sstever@eecs.umich.edu
13663109Sstever@eecs.umich.edu    def __str__(self):
13673109Sstever@eecs.umich.edu        return '%s.%s[:]' % (self.simobj, self.name)
13683109Sstever@eecs.umich.edu
13693105Sstever@eecs.umich.edu    # for config.ini, print peer's name (not ours)
13703105Sstever@eecs.umich.edu    def ini_str(self):
13713105Sstever@eecs.umich.edu        return ' '.join([el.ini_str() for el in self.elements])
13723105Sstever@eecs.umich.edu
13733105Sstever@eecs.umich.edu    def __getitem__(self, key):
13743105Sstever@eecs.umich.edu        if not isinstance(key, int):
13753105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
13763105Sstever@eecs.umich.edu        if key >= len(self.elements):
13773105Sstever@eecs.umich.edu            # need to extend list
13783105Sstever@eecs.umich.edu            ext = [VectorPortElementRef(self.simobj, self.name, i)
13793105Sstever@eecs.umich.edu                   for i in range(len(self.elements), key+1)]
13803105Sstever@eecs.umich.edu            self.elements.extend(ext)
13813105Sstever@eecs.umich.edu        return self.elements[key]
13823105Sstever@eecs.umich.edu
13833105Sstever@eecs.umich.edu    def _get_next(self):
13843105Sstever@eecs.umich.edu        return self[len(self.elements)]
13853105Sstever@eecs.umich.edu
13863105Sstever@eecs.umich.edu    def __setitem__(self, key, value):
13873105Sstever@eecs.umich.edu        if not isinstance(key, int):
13883105Sstever@eecs.umich.edu            raise TypeError, "VectorPort index must be integer"
13893105Sstever@eecs.umich.edu        self[key].connect(value)
13903105Sstever@eecs.umich.edu
13913105Sstever@eecs.umich.edu    def connect(self, other):
13923109Sstever@eecs.umich.edu        if isinstance(other, (list, tuple)):
13933109Sstever@eecs.umich.edu            # Assign list of port refs to vector port.
13943109Sstever@eecs.umich.edu            # For now, append them... not sure if that's the right semantics
13953109Sstever@eecs.umich.edu            # or if it should replace the current vector.
13963109Sstever@eecs.umich.edu            for ref in other:
13973109Sstever@eecs.umich.edu                self._get_next().connect(ref)
13983109Sstever@eecs.umich.edu        else:
13993109Sstever@eecs.umich.edu            # scalar assignment to plain VectorPort is implicit append
14003109Sstever@eecs.umich.edu            self._get_next().connect(other)
14013109Sstever@eecs.umich.edu
14023109Sstever@eecs.umich.edu    def clone(self, simobj, memo):
14033109Sstever@eecs.umich.edu        if memo.has_key(self):
14043109Sstever@eecs.umich.edu            return memo[self]
14053109Sstever@eecs.umich.edu        newRef = copy.copy(self)
14063109Sstever@eecs.umich.edu        memo[self] = newRef
14073109Sstever@eecs.umich.edu        newRef.simobj = simobj
14083109Sstever@eecs.umich.edu        assert(isSimObject(newRef.simobj))
14093109Sstever@eecs.umich.edu        newRef.elements = [el.clone(simobj, memo) for el in self.elements]
14103109Sstever@eecs.umich.edu        return newRef
14113105Sstever@eecs.umich.edu
14123105Sstever@eecs.umich.edu    def unproxy(self, simobj):
14133105Sstever@eecs.umich.edu        [el.unproxy(simobj) for el in self.elements]
14143105Sstever@eecs.umich.edu
14153105Sstever@eecs.umich.edu    def ccConnect(self):
14163105Sstever@eecs.umich.edu        [el.ccConnect() for el in self.elements]
14173105Sstever@eecs.umich.edu
14183101Sstever@eecs.umich.edu# Port description object.  Like a ParamDesc object, this represents a
14193101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a
14203101Sstever@eecs.umich.edu# SimObject instance.  The latter are represented by PortRef objects.
14213101Sstever@eecs.umich.educlass Port(object):
14223105Sstever@eecs.umich.edu    # Port("description") or Port(default, "description")
14233105Sstever@eecs.umich.edu    def __init__(self, *args):
14243105Sstever@eecs.umich.edu        if len(args) == 1:
14253105Sstever@eecs.umich.edu            self.desc = args[0]
14263105Sstever@eecs.umich.edu        elif len(args) == 2:
14273105Sstever@eecs.umich.edu            self.default = args[0]
14283105Sstever@eecs.umich.edu            self.desc = args[1]
14293105Sstever@eecs.umich.edu        else:
14303105Sstever@eecs.umich.edu            raise TypeError, 'wrong number of arguments'
14313105Sstever@eecs.umich.edu        # self.name is set by SimObject class on assignment
14323105Sstever@eecs.umich.edu        # e.g., pio_port = Port("blah") sets self.name to 'pio_port'
14333101Sstever@eecs.umich.edu
14343101Sstever@eecs.umich.edu    # Generate a PortRef for this port on the given SimObject with the
14353101Sstever@eecs.umich.edu    # given name
14363105Sstever@eecs.umich.edu    def makeRef(self, simobj):
14373105Sstever@eecs.umich.edu        return PortRef(simobj, self.name)
14383101Sstever@eecs.umich.edu
14393101Sstever@eecs.umich.edu    # Connect an instance of this port (on the given SimObject with
14403101Sstever@eecs.umich.edu    # the given name) with the port described by the supplied PortRef
14413105Sstever@eecs.umich.edu    def connect(self, simobj, ref):
14423105Sstever@eecs.umich.edu        self.makeRef(simobj).connect(ref)
14433101Sstever@eecs.umich.edu
14443101Sstever@eecs.umich.edu# VectorPort description object.  Like Port, but represents a vector
14453101Sstever@eecs.umich.edu# of connections (e.g., as on a Bus).
14463101Sstever@eecs.umich.educlass VectorPort(Port):
14473105Sstever@eecs.umich.edu    def __init__(self, *args):
14483105Sstever@eecs.umich.edu        Port.__init__(self, *args)
14493101Sstever@eecs.umich.edu        self.isVec = True
14503101Sstever@eecs.umich.edu
14513105Sstever@eecs.umich.edu    def makeRef(self, simobj):
14523105Sstever@eecs.umich.edu        return VectorPortRef(simobj, self.name)
14533105Sstever@eecs.umich.edu
14543109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of
14553109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages
14563109Sstever@eecs.umich.edu# make sense.
14573109Sstever@eecs.umich.educlass PortParamDesc(object):
14583109Sstever@eecs.umich.edu    __metaclass__ = Singleton
14593109Sstever@eecs.umich.edu
14603109Sstever@eecs.umich.edu    ptype_str = 'Port'
14613109Sstever@eecs.umich.edu    ptype = Port
14623105Sstever@eecs.umich.edu
14636654Snate@binkert.orgbaseEnums = allEnums.copy()
14646654Snate@binkert.orgbaseParams = allParams.copy()
14656654Snate@binkert.org
14666654Snate@binkert.orgdef clear():
14676654Snate@binkert.org    global allEnums, allParams
14686654Snate@binkert.org
14696654Snate@binkert.org    allEnums = baseEnums.copy()
14706654Snate@binkert.org    allParams = baseParams.copy()
14716654Snate@binkert.org
14723101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam',
14733101Sstever@eecs.umich.edu           'Enum', 'Bool', 'String', 'Float',
14743101Sstever@eecs.umich.edu           'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16',
14753101Sstever@eecs.umich.edu           'Int32', 'UInt32', 'Int64', 'UInt64',
14763101Sstever@eecs.umich.edu           'Counter', 'Addr', 'Tick', 'Percent',
14773101Sstever@eecs.umich.edu           'TcpPort', 'UdpPort', 'EthernetAddr',
14787777Sgblack@eecs.umich.edu           'IpAddress', 'IpNetmask', 'IpWithPort',
14793101Sstever@eecs.umich.edu           'MemorySize', 'MemorySize32',
14804167Sbinkertn@umich.edu           'Latency', 'Frequency', 'Clock',
14813101Sstever@eecs.umich.edu           'NetworkBandwidth', 'MemoryBandwidth',
14823101Sstever@eecs.umich.edu           'Range', 'AddrRange', 'TickRange',
14833101Sstever@eecs.umich.edu           'MaxAddr', 'MaxTick', 'AllMemory',
14843885Sbinkertn@umich.edu           'Time',
14853102Sstever@eecs.umich.edu           'NextEthernetAddr', 'NULL',
14863101Sstever@eecs.umich.edu           'Port', 'VectorPort']
14876654Snate@binkert.org
14886654Snate@binkert.orgimport SimObject
1489