params.py revision 4446
19544Sandreas.hansson@arm.com# Copyright (c) 2004-2006 The Regents of The University of Michigan 28839Sandreas.hansson@arm.com# All rights reserved. 38839Sandreas.hansson@arm.com# 48839Sandreas.hansson@arm.com# Redistribution and use in source and binary forms, with or without 58839Sandreas.hansson@arm.com# modification, are permitted provided that the following conditions are 68839Sandreas.hansson@arm.com# met: redistributions of source code must retain the above copyright 78839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer; 88839Sandreas.hansson@arm.com# redistributions in binary form must reproduce the above copyright 98839Sandreas.hansson@arm.com# notice, this list of conditions and the following disclaimer in the 108839Sandreas.hansson@arm.com# documentation and/or other materials provided with the distribution; 118839Sandreas.hansson@arm.com# neither the name of the copyright holders nor the names of its 128839Sandreas.hansson@arm.com# contributors may be used to endorse or promote products derived from 133101Sstever@eecs.umich.edu# this software without specific prior written permission. 148579Ssteve.reinhardt@amd.com# 153101Sstever@eecs.umich.edu# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 163101Sstever@eecs.umich.edu# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 173101Sstever@eecs.umich.edu# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 183101Sstever@eecs.umich.edu# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 193101Sstever@eecs.umich.edu# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 203101Sstever@eecs.umich.edu# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 213101Sstever@eecs.umich.edu# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 223101Sstever@eecs.umich.edu# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 233101Sstever@eecs.umich.edu# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 243101Sstever@eecs.umich.edu# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 253101Sstever@eecs.umich.edu# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 263101Sstever@eecs.umich.edu# 273101Sstever@eecs.umich.edu# Authors: Steve Reinhardt 283101Sstever@eecs.umich.edu# Nathan Binkert 293101Sstever@eecs.umich.edu 303101Sstever@eecs.umich.edu##################################################################### 313101Sstever@eecs.umich.edu# 323101Sstever@eecs.umich.edu# Parameter description classes 333101Sstever@eecs.umich.edu# 343101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 353101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 363101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 373101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 383101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 393101Sstever@eecs.umich.edu# type. 403101Sstever@eecs.umich.edu# 413101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 427778Sgblack@eecs.umich.edu# space when the parameter dictionary is initialized (in 438839Sandreas.hansson@arm.com# MetaSimObject._new_param()); after that point they aren't used. 443101Sstever@eecs.umich.edu# 453101Sstever@eecs.umich.edu##################################################################### 463101Sstever@eecs.umich.edu 473101Sstever@eecs.umich.eduimport copy 483101Sstever@eecs.umich.eduimport datetime 493101Sstever@eecs.umich.eduimport inspect 503101Sstever@eecs.umich.eduimport sys 513101Sstever@eecs.umich.eduimport time 523101Sstever@eecs.umich.edu 533101Sstever@eecs.umich.eduimport convert 543101Sstever@eecs.umich.eduimport proxy 553101Sstever@eecs.umich.eduimport ticks 563101Sstever@eecs.umich.edufrom util import * 573101Sstever@eecs.umich.edu 583101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 593101Sstever@eecs.umich.edu# parameters. 603101Sstever@eecs.umich.educlass ParamValue(object): 613101Sstever@eecs.umich.edu 623885Sbinkertn@umich.edu cxx_predecls = [] 633885Sbinkertn@umich.edu swig_predecls = [] 644762Snate@binkert.org 653885Sbinkertn@umich.edu # default for printing to .ini file is regular string conversion. 663885Sbinkertn@umich.edu # will be overridden in some cases 677528Ssteve.reinhardt@amd.com def ini_str(self): 683885Sbinkertn@umich.edu return str(self) 694380Sbinkertn@umich.edu 704167Sbinkertn@umich.edu # allows us to blithely call unproxy() on things without checking 713102Sstever@eecs.umich.edu # if they're really proxies or not 723101Sstever@eecs.umich.edu def unproxy(self, base): 734762Snate@binkert.org return self 744762Snate@binkert.org 754762Snate@binkert.org# Regular parameter description. 764762Snate@binkert.orgclass ParamDesc(object): 774762Snate@binkert.org def __init__(self, ptype_str, ptype, *args, **kwargs): 784762Snate@binkert.org self.ptype_str = ptype_str 794762Snate@binkert.org # remember ptype only if it is provided 804762Snate@binkert.org if ptype != None: 814762Snate@binkert.org self.ptype = ptype 825033Smilesck@eecs.umich.edu 835033Smilesck@eecs.umich.edu if args: 845033Smilesck@eecs.umich.edu if len(args) == 1: 855033Smilesck@eecs.umich.edu self.desc = args[0] 865033Smilesck@eecs.umich.edu elif len(args) == 2: 875033Smilesck@eecs.umich.edu self.default = args[0] 885033Smilesck@eecs.umich.edu self.desc = args[1] 895033Smilesck@eecs.umich.edu else: 905033Smilesck@eecs.umich.edu raise TypeError, 'too many arguments' 915033Smilesck@eecs.umich.edu 923101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 933101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 943101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 955033Smilesck@eecs.umich.edu del kwargs['desc'] 963101Sstever@eecs.umich.edu 978596Ssteve.reinhardt@amd.com if kwargs.has_key('default'): 988596Ssteve.reinhardt@amd.com assert(not hasattr(self, 'default')) 998596Ssteve.reinhardt@amd.com self.default = kwargs['default'] 1008596Ssteve.reinhardt@amd.com del kwargs['default'] 1017673Snate@binkert.org 1027673Snate@binkert.org if kwargs: 1037673Snate@binkert.org raise TypeError, 'extra unknown kwargs %s' % kwargs 1047673Snate@binkert.org 1058596Ssteve.reinhardt@amd.com if not hasattr(self, 'desc'): 1068596Ssteve.reinhardt@amd.com raise TypeError, 'desc attribute missing' 1078596Ssteve.reinhardt@amd.com 1087673Snate@binkert.org def __getattr__(self, attr): 1097673Snate@binkert.org if attr == 'ptype': 1107673Snate@binkert.org try: 1113101Sstever@eecs.umich.edu ptype = eval(self.ptype_str, objects.__dict__) 1123101Sstever@eecs.umich.edu if not isinstance(ptype, type): 1133101Sstever@eecs.umich.edu raise NameError 1143101Sstever@eecs.umich.edu self.ptype = ptype 1153101Sstever@eecs.umich.edu return ptype 1163101Sstever@eecs.umich.edu except NameError: 1173101Sstever@eecs.umich.edu raise TypeError, \ 1183101Sstever@eecs.umich.edu "Param qualifier '%s' is not a type" % self.ptype_str 1193101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1203101Sstever@eecs.umich.edu (type(self).__name__, attr) 1213101Sstever@eecs.umich.edu 1223101Sstever@eecs.umich.edu def convert(self, value): 1233101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1243101Sstever@eecs.umich.edu value.set_param_desc(self) 1253101Sstever@eecs.umich.edu return value 1263101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1273101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 1283101Sstever@eecs.umich.edu # we're just assigning a null pointer 1293101Sstever@eecs.umich.edu return value 1303101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 1313101Sstever@eecs.umich.edu return value 1323101Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1333101Sstever@eecs.umich.edu return value 1343101Sstever@eecs.umich.edu return self.ptype(value) 1353101Sstever@eecs.umich.edu 1363101Sstever@eecs.umich.edu def cxx_predecls(self): 1373101Sstever@eecs.umich.edu return self.ptype.cxx_predecls 1383101Sstever@eecs.umich.edu 1393101Sstever@eecs.umich.edu def swig_predecls(self): 1403101Sstever@eecs.umich.edu return self.ptype.swig_predecls 1413101Sstever@eecs.umich.edu 1423101Sstever@eecs.umich.edu def cxx_decl(self): 1433101Sstever@eecs.umich.edu return '%s %s;' % (self.ptype.cxx_type, self.name) 1443101Sstever@eecs.umich.edu 1453101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1463101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1473101Sstever@eecs.umich.edu# single value. 1483101Sstever@eecs.umich.edu 1493101Sstever@eecs.umich.educlass VectorParamValue(list): 1503101Sstever@eecs.umich.edu def ini_str(self): 1513101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 1523101Sstever@eecs.umich.edu 1533101Sstever@eecs.umich.edu def unproxy(self, base): 1543101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 1553101Sstever@eecs.umich.edu 1563101Sstever@eecs.umich.educlass SimObjVector(VectorParamValue): 1575033Smilesck@eecs.umich.edu def print_ini(self): 1586656Snate@binkert.org for v in self: 1595033Smilesck@eecs.umich.edu v.print_ini() 1605033Smilesck@eecs.umich.edu 1615033Smilesck@eecs.umich.educlass VectorParamDesc(ParamDesc): 1623101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 1633101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 1643101Sstever@eecs.umich.edu def convert(self, value): 1653101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 1663101Sstever@eecs.umich.edu # list: coerce each element into new list 1673101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 1683101Sstever@eecs.umich.edu if isSimObjectSequence(tmp_list): 1693101Sstever@eecs.umich.edu return SimObjVector(tmp_list) 1703101Sstever@eecs.umich.edu else: 1713101Sstever@eecs.umich.edu return VectorParamValue(tmp_list) 1723101Sstever@eecs.umich.edu else: 1733101Sstever@eecs.umich.edu # singleton: leave it be (could coerce to a single-element 1743101Sstever@eecs.umich.edu # list here, but for some historical reason we don't... 1753102Sstever@eecs.umich.edu return ParamDesc.convert(self, value) 1763101Sstever@eecs.umich.edu 1773101Sstever@eecs.umich.edu def cxx_predecls(self): 1783101Sstever@eecs.umich.edu return ['#include <vector>'] + self.ptype.cxx_predecls 1797673Snate@binkert.org 1808607Sgblack@eecs.umich.edu def swig_predecls(self): 1817673Snate@binkert.org return ['%include "std_vector.i"'] + self.ptype.swig_predecls 1823101Sstever@eecs.umich.edu 1837673Snate@binkert.org def cxx_decl(self): 1847673Snate@binkert.org return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name) 1853101Sstever@eecs.umich.edu 1867673Snate@binkert.orgclass ParamFactory(object): 1877673Snate@binkert.org def __init__(self, param_desc_class, ptype_str = None): 1883101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 1893101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1903101Sstever@eecs.umich.edu 1913101Sstever@eecs.umich.edu def __getattr__(self, attr): 1923101Sstever@eecs.umich.edu if self.ptype_str: 1933101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 1945033Smilesck@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 1955475Snate@binkert.org 1965475Snate@binkert.org # E.g., Param.Int(5, "number of widgets") 1975475Snate@binkert.org def __call__(self, *args, **kwargs): 1985475Snate@binkert.org caller_frame = inspect.currentframe().f_back 1993101Sstever@eecs.umich.edu ptype = None 2003101Sstever@eecs.umich.edu try: 2013101Sstever@eecs.umich.edu ptype = eval(self.ptype_str, 2024762Snate@binkert.org caller_frame.f_globals, caller_frame.f_locals) 2034762Snate@binkert.org if not isinstance(ptype, type): 2044762Snate@binkert.org raise TypeError, \ 2053101Sstever@eecs.umich.edu "Param qualifier is not a type: %s" % ptype 2068460SAli.Saidi@ARM.com except NameError: 2078459SAli.Saidi@ARM.com # if name isn't defined yet, assume it's a SimObject, and 2088459SAli.Saidi@ARM.com # try to resolve it later 2098459SAli.Saidi@ARM.com pass 2103101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2117528Ssteve.reinhardt@amd.com 2127528Ssteve.reinhardt@amd.comParam = ParamFactory(ParamDesc) 2137528Ssteve.reinhardt@amd.comVectorParam = ParamFactory(VectorParamDesc) 2147528Ssteve.reinhardt@amd.com 2157528Ssteve.reinhardt@amd.com##################################################################### 2167528Ssteve.reinhardt@amd.com# 2173101Sstever@eecs.umich.edu# Parameter Types 2187528Ssteve.reinhardt@amd.com# 2197528Ssteve.reinhardt@amd.com# Though native Python types could be used to specify parameter types 2207528Ssteve.reinhardt@amd.com# (the 'ptype' field of the Param and VectorParam classes), it's more 2217528Ssteve.reinhardt@amd.com# flexible to define our own set of types. This gives us more control 2227528Ssteve.reinhardt@amd.com# over how Python expressions are converted to values (via the 2237528Ssteve.reinhardt@amd.com# __init__() constructor) and how these values are printed out (via 2247528Ssteve.reinhardt@amd.com# the __str__() conversion method). 2257528Ssteve.reinhardt@amd.com# 2267528Ssteve.reinhardt@amd.com##################################################################### 2277528Ssteve.reinhardt@amd.com 2288321Ssteve.reinhardt@amd.com# String-valued parameter. Just mixin the ParamValue class with the 2298321Ssteve.reinhardt@amd.com# built-in str class. 2307528Ssteve.reinhardt@amd.comclass String(ParamValue,str): 2317528Ssteve.reinhardt@amd.com cxx_type = 'std::string' 2327528Ssteve.reinhardt@amd.com cxx_predecls = ['#include <string>'] 2337528Ssteve.reinhardt@amd.com swig_predecls = ['%include "std_string.i"\n' + 2347528Ssteve.reinhardt@amd.com '%apply const std::string& {std::string *};'] 2357528Ssteve.reinhardt@amd.com pass 2367528Ssteve.reinhardt@amd.com 2377528Ssteve.reinhardt@amd.com# superclass for "numeric" parameter values, to emulate math 2387528Ssteve.reinhardt@amd.com# operations in a type-safe way. e.g., a Latency times an int returns 2397528Ssteve.reinhardt@amd.com# a new Latency object. 2407528Ssteve.reinhardt@amd.comclass NumericParamValue(ParamValue): 2417528Ssteve.reinhardt@amd.com def __str__(self): 2427528Ssteve.reinhardt@amd.com return str(self.value) 2433101Sstever@eecs.umich.edu 2448664SAli.Saidi@ARM.com def __float__(self): 2458664SAli.Saidi@ARM.com return float(self.value) 2468664SAli.Saidi@ARM.com 2478664SAli.Saidi@ARM.com def __long__(self): 2488664SAli.Saidi@ARM.com return long(self.value) 2498664SAli.Saidi@ARM.com 2503101Sstever@eecs.umich.edu def __int__(self): 2513101Sstever@eecs.umich.edu return int(self.value) 2523101Sstever@eecs.umich.edu 2533101Sstever@eecs.umich.edu # hook for bounds checking 2543101Sstever@eecs.umich.edu def _check(self): 2553101Sstever@eecs.umich.edu return 2563101Sstever@eecs.umich.edu 2573101Sstever@eecs.umich.edu def __mul__(self, other): 2584762Snate@binkert.org newobj = self.__class__(self) 2594762Snate@binkert.org newobj.value *= other 2604762Snate@binkert.org newobj._check() 2614762Snate@binkert.org return newobj 2627528Ssteve.reinhardt@amd.com 2634762Snate@binkert.org __rmul__ = __mul__ 2644762Snate@binkert.org 2654762Snate@binkert.org def __div__(self, other): 2668596Ssteve.reinhardt@amd.com newobj = self.__class__(self) 2678596Ssteve.reinhardt@amd.com newobj.value /= other 2688596Ssteve.reinhardt@amd.com newobj._check() 2697673Snate@binkert.org return newobj 2708596Ssteve.reinhardt@amd.com 2714762Snate@binkert.org def __sub__(self, other): 2727673Snate@binkert.org newobj = self.__class__(self) 2738596Ssteve.reinhardt@amd.com newobj.value -= other 2747675Snate@binkert.org newobj._check() 2757675Snate@binkert.org return newobj 2767675Snate@binkert.org 2777675Snate@binkert.org# Metaclass for bounds-checked integer parameters. See CheckedInt. 2788656Sandreas.hansson@arm.comclass CheckedIntType(type): 2798656Sandreas.hansson@arm.com def __init__(cls, name, bases, dict): 2808656Sandreas.hansson@arm.com super(CheckedIntType, cls).__init__(name, bases, dict) 2817675Snate@binkert.org 2827675Snate@binkert.org # CheckedInt is an abstract base class, so we actually don't 2837673Snate@binkert.org # want to do any processing on it... the rest of this code is 2847675Snate@binkert.org # just for classes that derive from CheckedInt. 2857675Snate@binkert.org if name == 'CheckedInt': 2867675Snate@binkert.org return 2877675Snate@binkert.org 2887675Snate@binkert.org if not cls.cxx_predecls: 2897673Snate@binkert.org # most derived types require this, so we just do it here once 2907675Snate@binkert.org cls.cxx_predecls = ['#include "sim/host.hh"'] 2917675Snate@binkert.org 2927675Snate@binkert.org if not cls.swig_predecls: 2937675Snate@binkert.org # most derived types require this, so we just do it here once 2947675Snate@binkert.org cls.swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 2957675Snate@binkert.org '%import "sim/host.hh"'] 2967675Snate@binkert.org 2977675Snate@binkert.org if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 2987675Snate@binkert.org if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 2997675Snate@binkert.org panic("CheckedInt subclass %s must define either\n" \ 3007675Snate@binkert.org " 'min' and 'max' or 'size' and 'unsigned'\n" \ 3017675Snate@binkert.org % name); 3027675Snate@binkert.org if cls.unsigned: 3037675Snate@binkert.org cls.min = 0 3047675Snate@binkert.org cls.max = 2 ** cls.size - 1 3057675Snate@binkert.org else: 3067673Snate@binkert.org cls.min = -(2 ** (cls.size - 1)) 3077673Snate@binkert.org cls.max = (2 ** (cls.size - 1)) - 1 3083101Sstever@eecs.umich.edu 3097675Snate@binkert.org# Abstract superclass for bounds-checked integer parameters. This 3107675Snate@binkert.org# class is subclassed to generate parameter classes with specific 3117673Snate@binkert.org# bounds. Initialization of the min and max bounds is done in the 3127673Snate@binkert.org# metaclass CheckedIntType.__init__. 3137673Snate@binkert.orgclass CheckedInt(NumericParamValue): 3143101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 3157673Snate@binkert.org 3167673Snate@binkert.org def _check(self): 3173101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 3183101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 3193101Sstever@eecs.umich.edu (self.min, self.value, self.max) 3203101Sstever@eecs.umich.edu 3213101Sstever@eecs.umich.edu def __init__(self, value): 3223101Sstever@eecs.umich.edu if isinstance(value, str): 3233101Sstever@eecs.umich.edu self.value = convert.toInteger(value) 3243101Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 3253101Sstever@eecs.umich.edu self.value = long(value) 3263101Sstever@eecs.umich.edu else: 3273101Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 3283101Sstever@eecs.umich.edu % type(value).__name__ 3293101Sstever@eecs.umich.edu self._check() 3303101Sstever@eecs.umich.edu 3313101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 3325033Smilesck@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 3335033Smilesck@eecs.umich.edu 3343101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 3353101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 3363101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 3373101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3383101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 3393101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 3403101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 3413101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 3423101Sstever@eecs.umich.edu 3433101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 3443101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 3453101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3463101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 3473101Sstever@eecs.umich.edu 3483101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 3493101Sstever@eecs.umich.edu 3503101Sstever@eecs.umich.educlass Float(ParamValue, float): 3513101Sstever@eecs.umich.edu cxx_type = 'double' 3523101Sstever@eecs.umich.edu 3533101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 3543101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 3553101Sstever@eecs.umich.edu size = 64 3563101Sstever@eecs.umich.edu unsigned = True 3573101Sstever@eecs.umich.edu def __init__(self, value): 3583101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 3597673Snate@binkert.org self.value = value.value 3607673Snate@binkert.org else: 3617673Snate@binkert.org self.value = convert.toMemorySize(value) 3627673Snate@binkert.org self._check() 3637673Snate@binkert.org 3647673Snate@binkert.orgclass MemorySize32(CheckedInt): 3657673Snate@binkert.org cxx_type = 'uint32_t' 3667673Snate@binkert.org size = 32 3674762Snate@binkert.org unsigned = True 3684762Snate@binkert.org def __init__(self, value): 3694762Snate@binkert.org if isinstance(value, MemorySize): 3703101Sstever@eecs.umich.edu self.value = value.value 3713101Sstever@eecs.umich.edu else: 3723101Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 3733101Sstever@eecs.umich.edu self._check() 3743101Sstever@eecs.umich.edu 3753101Sstever@eecs.umich.educlass Addr(CheckedInt): 3763101Sstever@eecs.umich.edu cxx_type = 'Addr' 3773101Sstever@eecs.umich.edu cxx_predecls = ['#include "targetarch/isa_traits.hh"'] 3783101Sstever@eecs.umich.edu size = 64 3793101Sstever@eecs.umich.edu unsigned = True 3803101Sstever@eecs.umich.edu def __init__(self, value): 3813714Sstever@eecs.umich.edu if isinstance(value, Addr): 3823714Sstever@eecs.umich.edu self.value = value.value 3833714Sstever@eecs.umich.edu else: 3843714Sstever@eecs.umich.edu try: 3853714Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 3863714Sstever@eecs.umich.edu except TypeError: 3873101Sstever@eecs.umich.edu self.value = long(value) 3883101Sstever@eecs.umich.edu self._check() 3893101Sstever@eecs.umich.edu def __add__(self, other): 3903101Sstever@eecs.umich.edu if isinstance(other, Addr): 3913101Sstever@eecs.umich.edu return self.value + other.value 3923101Sstever@eecs.umich.edu else: 3933101Sstever@eecs.umich.edu return self.value + other 3943101Sstever@eecs.umich.edu 3953101Sstever@eecs.umich.edu 3963101Sstever@eecs.umich.educlass MetaRange(type): 3973101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 3983101Sstever@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 3993101Sstever@eecs.umich.edu if name == 'Range': 4003101Sstever@eecs.umich.edu return 4013101Sstever@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 4023101Sstever@eecs.umich.edu cls.cxx_predecls = \ 4033101Sstever@eecs.umich.edu ['#include "base/range.hh"'] + cls.type.cxx_predecls 4043101Sstever@eecs.umich.edu 4053101Sstever@eecs.umich.educlass Range(ParamValue): 4063101Sstever@eecs.umich.edu __metaclass__ = MetaRange 4073101Sstever@eecs.umich.edu type = Int # default; can be overridden in subclasses 4083101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 4093101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 4103101Sstever@eecs.umich.edu if 'end' in kwargs: 4113101Sstever@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 4125033Smilesck@eecs.umich.edu elif 'size' in kwargs: 4133101Sstever@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 4143101Sstever@eecs.umich.edu else: 4153101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 4163101Sstever@eecs.umich.edu 4173101Sstever@eecs.umich.edu if len(args) == 0: 4183101Sstever@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 4193101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4203101Sstever@eecs.umich.edu 4213101Sstever@eecs.umich.edu elif len(args) == 1: 4223101Sstever@eecs.umich.edu if kwargs: 4233101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4243101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 4255822Ssaidi@eecs.umich.edu elif isinstance(args[0], Range): 4265822Ssaidi@eecs.umich.edu self.first = self.type(args[0].first) 4273101Sstever@eecs.umich.edu self.second = self.type(args[0].second) 4283101Sstever@eecs.umich.edu else: 4293101Sstever@eecs.umich.edu self.first = self.type(0) 4303101Sstever@eecs.umich.edu self.second = self.type(args[0]) - 1 4313101Sstever@eecs.umich.edu 4323101Sstever@eecs.umich.edu elif len(args) == 2: 4333101Sstever@eecs.umich.edu self.first = self.type(args[0]) 4343101Sstever@eecs.umich.edu self.second = self.type(args[1]) 4353101Sstever@eecs.umich.edu else: 4363101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 4373101Sstever@eecs.umich.edu 4383101Sstever@eecs.umich.edu if kwargs: 4393101Sstever@eecs.umich.edu raise TypeError, "too many keywords: %s" % kwargs.keys() 4403101Sstever@eecs.umich.edu 4413101Sstever@eecs.umich.edu def __str__(self): 4423101Sstever@eecs.umich.edu return '%s:%s' % (self.first, self.second) 4433101Sstever@eecs.umich.edu 4443101Sstever@eecs.umich.educlass AddrRange(Range): 4453101Sstever@eecs.umich.edu type = Addr 4463101Sstever@eecs.umich.edu 4473101Sstever@eecs.umich.educlass TickRange(Range): 4483102Sstever@eecs.umich.edu type = Tick 4493714Sstever@eecs.umich.edu 4503101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 4513714Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 4523714Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 4533714Sstever@eecs.umich.educlass Bool(ParamValue): 4543101Sstever@eecs.umich.edu cxx_type = 'bool' 4553101Sstever@eecs.umich.edu def __init__(self, value): 4567673Snate@binkert.org try: 4577673Snate@binkert.org self.value = convert.toBool(value) 4587673Snate@binkert.org except TypeError: 4597673Snate@binkert.org self.value = bool(value) 4607673Snate@binkert.org 4617673Snate@binkert.org def __str__(self): 4627673Snate@binkert.org return str(self.value) 4637673Snate@binkert.org 4647673Snate@binkert.org def ini_str(self): 4657673Snate@binkert.org if self.value: 4667673Snate@binkert.org return 'true' 4674762Snate@binkert.org return 'false' 4684762Snate@binkert.org 4694762Snate@binkert.orgdef IncEthernetAddr(addr, val = 1): 4703101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 4713101Sstever@eecs.umich.edu bytes[5] += val 4723101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 4733101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 4743101Sstever@eecs.umich.edu bytes[i] = rem 4753101Sstever@eecs.umich.edu if val == 0: 4763101Sstever@eecs.umich.edu break 4773101Sstever@eecs.umich.edu bytes[i - 1] += val 4783101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 4793101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 4803101Sstever@eecs.umich.edu 4813101Sstever@eecs.umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 4823101Sstever@eecs.umich.edudef NextEthernetAddr(): 4833101Sstever@eecs.umich.edu global _NextEthernetAddr 4843101Sstever@eecs.umich.edu 4853101Sstever@eecs.umich.edu value = _NextEthernetAddr 4863101Sstever@eecs.umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 4873101Sstever@eecs.umich.edu return value 4883101Sstever@eecs.umich.edu 4899184Sandreas.hansson@arm.comclass EthernetAddr(ParamValue): 4909184Sandreas.hansson@arm.com cxx_type = 'Net::EthAddr' 4919184Sandreas.hansson@arm.com cxx_predecls = ['#include "base/inet.hh"'] 4929184Sandreas.hansson@arm.com swig_predecls = ['class Net::EthAddr;'] 4939184Sandreas.hansson@arm.com def __init__(self, value): 4949184Sandreas.hansson@arm.com if value == NextEthernetAddr: 4959184Sandreas.hansson@arm.com self.value = value 4969184Sandreas.hansson@arm.com return 4979184Sandreas.hansson@arm.com 4983101Sstever@eecs.umich.edu if not isinstance(value, str): 4994446Sbinkertn@umich.edu raise TypeError, "expected an ethernet address and didn't get one" 5003101Sstever@eecs.umich.edu 5015468Snate@binkert.org bytes = value.split(':') 5025468Snate@binkert.org if len(bytes) != 6: 5035468Snate@binkert.org raise TypeError, 'invalid ethernet address %s' % value 5045468Snate@binkert.org 5055468Snate@binkert.org for byte in bytes: 5065468Snate@binkert.org if not 0 <= int(byte) <= 256: 5075468Snate@binkert.org raise TypeError, 'invalid ethernet address %s' % value 5084762Snate@binkert.org 5094762Snate@binkert.org self.value = value 5104762Snate@binkert.org 5113101Sstever@eecs.umich.edu def unproxy(self, base): 5123101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 5133101Sstever@eecs.umich.edu return EthernetAddr(self.value()) 5143101Sstever@eecs.umich.edu return self 5153101Sstever@eecs.umich.edu 5163101Sstever@eecs.umich.edu def ini_str(self): 5173101Sstever@eecs.umich.edu return self.value 5183101Sstever@eecs.umich.edu 5193102Sstever@eecs.umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 5203101Sstever@eecs.umich.edu "%a %b %d %H:%M:%S %Z %Y", 5213101Sstever@eecs.umich.edu "%Y/%m/%d %H:%M:%S", 5223101Sstever@eecs.umich.edu "%Y/%m/%d %H:%M", 5234168Sbinkertn@umich.edu "%Y/%m/%d", 5243101Sstever@eecs.umich.edu "%m/%d/%Y %H:%M:%S", 5253101Sstever@eecs.umich.edu "%m/%d/%Y %H:%M", 5263101Sstever@eecs.umich.edu "%m/%d/%Y", 5273101Sstever@eecs.umich.edu "%m/%d/%y %H:%M:%S", 5283101Sstever@eecs.umich.edu "%m/%d/%y %H:%M", 5293101Sstever@eecs.umich.edu "%m/%d/%y"] 5303102Sstever@eecs.umich.edu 5313101Sstever@eecs.umich.edu 5323101Sstever@eecs.umich.edudef parse_time(value): 5333101Sstever@eecs.umich.edu from time import gmtime, strptime, struct_time, time 5343101Sstever@eecs.umich.edu from datetime import datetime, date 5353101Sstever@eecs.umich.edu 5363101Sstever@eecs.umich.edu if isinstance(value, struct_time): 5373101Sstever@eecs.umich.edu return value 5383101Sstever@eecs.umich.edu 5393101Sstever@eecs.umich.edu if isinstance(value, (int, long)): 5403101Sstever@eecs.umich.edu return gmtime(value) 5413101Sstever@eecs.umich.edu 5423102Sstever@eecs.umich.edu if isinstance(value, (datetime, date)): 5433101Sstever@eecs.umich.edu return value.timetuple() 5443101Sstever@eecs.umich.edu 5453101Sstever@eecs.umich.edu if isinstance(value, str): 5463584Ssaidi@eecs.umich.edu if value in ('Now', 'Today'): 5473584Ssaidi@eecs.umich.edu return time.gmtime(time.time()) 5483584Ssaidi@eecs.umich.edu 5493584Ssaidi@eecs.umich.edu for format in time_formats: 5503584Ssaidi@eecs.umich.edu try: 5513101Sstever@eecs.umich.edu return strptime(value, format) 5529232Sandreas.hansson@arm.com except ValueError: 5539235Sandreas.hansson@arm.com pass 5543101Sstever@eecs.umich.edu 5553101Sstever@eecs.umich.edu raise ValueError, "Could not parse '%s' as a time" % value 5569411Sandreas.hansson@arm.com 5579411Sandreas.hansson@arm.comclass Time(ParamValue): 5589411Sandreas.hansson@arm.com cxx_type = 'time_t' 5599411Sandreas.hansson@arm.com def __init__(self, value): 5609411Sandreas.hansson@arm.com self.value = parse_time(value) 5613101Sstever@eecs.umich.edu 5629411Sandreas.hansson@arm.com def __str__(self): 5639411Sandreas.hansson@arm.com tm = self.value 5649411Sandreas.hansson@arm.com return ' '.join([ str(tm[i]) for i in xrange(8)]) 5653101Sstever@eecs.umich.edu 5669232Sandreas.hansson@arm.com def ini_str(self): 5673101Sstever@eecs.umich.edu return str(self) 5689232Sandreas.hansson@arm.com 5693101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 5703101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 5713101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 5729411Sandreas.hansson@arm.com# long run, the integer value of the parameter will be the list index 5739411Sandreas.hansson@arm.com# or the corresponding dictionary value. For now, since we only check 5749411Sandreas.hansson@arm.com# that the alternative is valid and then spit it into a .ini file, 5759411Sandreas.hansson@arm.com# there's not much point in using the dictionary.) 5769411Sandreas.hansson@arm.com 5779411Sandreas.hansson@arm.com# What Enum() must do is generate a new type encapsulating the 5789411Sandreas.hansson@arm.com# provided list/dictionary so that specific values of the parameter 5799411Sandreas.hansson@arm.com# can be instances of that type. We define two hidden internal 5803101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 5819232Sandreas.hansson@arm.com# derive the new type from the appropriate base class on the fly. 5823101Sstever@eecs.umich.edu 5833101Sstever@eecs.umich.edu 5843101Sstever@eecs.umich.edu# Metaclass for Enum types 5853101Sstever@eecs.umich.educlass MetaEnum(type): 5869232Sandreas.hansson@arm.com def __init__(cls, name, bases, init_dict): 5873101Sstever@eecs.umich.edu if init_dict.has_key('map'): 5885219Ssaidi@eecs.umich.edu if not isinstance(cls.map, dict): 5899232Sandreas.hansson@arm.com raise TypeError, "Enum-derived class attribute 'map' " \ 5909232Sandreas.hansson@arm.com "must be of type dict" 5913101Sstever@eecs.umich.edu # build list of value strings from map 5929232Sandreas.hansson@arm.com cls.vals = cls.map.keys() 5939232Sandreas.hansson@arm.com cls.vals.sort() 5943101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 5953101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 5969232Sandreas.hansson@arm.com raise TypeError, "Enum-derived class attribute 'vals' " \ 5979232Sandreas.hansson@arm.com "must be of type list" 5983101Sstever@eecs.umich.edu # build string->value map from vals sequence 5993101Sstever@eecs.umich.edu cls.map = {} 6003101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 6013101Sstever@eecs.umich.edu cls.map[val] = idx 6029232Sandreas.hansson@arm.com else: 6033101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 6043101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 6059232Sandreas.hansson@arm.com 6069232Sandreas.hansson@arm.com cls.cxx_type = name + '::Enum' 6079232Sandreas.hansson@arm.com 6089411Sandreas.hansson@arm.com super(MetaEnum, cls).__init__(name, bases, init_dict) 6099411Sandreas.hansson@arm.com 6103101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 6117673Snate@binkert.org # Note that we wrap the enum in a class/struct to act as a namespace, 6127673Snate@binkert.org # so that the enum strings can be brief w/o worrying about collisions. 6139232Sandreas.hansson@arm.com def cxx_decl(cls): 6149235Sandreas.hansson@arm.com s = 'struct %s {\n enum Enum {\n ' % cls.__name__ 6157675Snate@binkert.org s += ',\n '.join(['%s = %d' % (v,cls.map[v]) for v in cls.vals]) 6167675Snate@binkert.org s += '\n };\n};\n' 6177675Snate@binkert.org return s 6189232Sandreas.hansson@arm.com 6197673Snate@binkert.org# Base class for enum types. 6204762Snate@binkert.orgclass Enum(ParamValue): 6219235Sandreas.hansson@arm.com __metaclass__ = MetaEnum 6229235Sandreas.hansson@arm.com vals = [] 6237675Snate@binkert.org 6244762Snate@binkert.org def __init__(self, value): 6259411Sandreas.hansson@arm.com if value not in self.map: 6269411Sandreas.hansson@arm.com raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 6279411Sandreas.hansson@arm.com % (value, self.vals) 6283101Sstever@eecs.umich.edu self.value = value 6293101Sstever@eecs.umich.edu 6303101Sstever@eecs.umich.edu def __str__(self): 6313101Sstever@eecs.umich.edu return self.value 6323101Sstever@eecs.umich.edu 6333101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 6343101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 6353101Sstever@eecs.umich.edu 6363102Sstever@eecs.umich.educlass TickParamValue(NumericParamValue): 6373101Sstever@eecs.umich.edu cxx_type = 'Tick' 6383101Sstever@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 6393101Sstever@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 6404762Snate@binkert.org '%import "sim/host.hh"'] 6414762Snate@binkert.org 6424762Snate@binkert.orgclass Latency(TickParamValue): 6433101Sstever@eecs.umich.edu def __init__(self, value): 6443101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 6453101Sstever@eecs.umich.edu self.ticks = value.ticks 6468934SBrad.Beckmann@amd.com self.value = value.value 6478934SBrad.Beckmann@amd.com elif isinstance(value, Frequency): 6488934SBrad.Beckmann@amd.com self.ticks = value.ticks 6498934SBrad.Beckmann@amd.com self.value = 1.0 / value.value 6508934SBrad.Beckmann@amd.com elif value.endswith('t'): 6513101Sstever@eecs.umich.edu self.ticks = True 6523101Sstever@eecs.umich.edu self.value = int(value[:-1]) 6533101Sstever@eecs.umich.edu else: 6543101Sstever@eecs.umich.edu self.ticks = False 6553101Sstever@eecs.umich.edu self.value = convert.toLatency(value) 6563101Sstever@eecs.umich.edu 6573101Sstever@eecs.umich.edu def __getattr__(self, attr): 6583101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 6593101Sstever@eecs.umich.edu return self 6603101Sstever@eecs.umich.edu if attr == 'frequency': 6613101Sstever@eecs.umich.edu return Frequency(self) 6623101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 6633101Sstever@eecs.umich.edu 6643101Sstever@eecs.umich.edu # convert latency to ticks 6653101Sstever@eecs.umich.edu def ini_str(self): 6663101Sstever@eecs.umich.edu if self.ticks or self.value == 0: 6673101Sstever@eecs.umich.edu return '%d' % self.value 6684380Sbinkertn@umich.edu else: 6694380Sbinkertn@umich.edu return '%d' % (ticks.fromSeconds(self.value)) 6704380Sbinkertn@umich.edu 6713101Sstever@eecs.umich.educlass Frequency(TickParamValue): 6724380Sbinkertn@umich.edu def __init__(self, value): 6734380Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 6744380Sbinkertn@umich.edu if value.value == 0: 6753101Sstever@eecs.umich.edu self.value = 0 6763101Sstever@eecs.umich.edu else: 6773101Sstever@eecs.umich.edu self.value = 1.0 / value.value 6787673Snate@binkert.org self.ticks = value.ticks 6797673Snate@binkert.org elif isinstance(value, Frequency): 6807673Snate@binkert.org self.value = value.value 6817673Snate@binkert.org self.ticks = value.ticks 6827673Snate@binkert.org else: 6837673Snate@binkert.org self.ticks = False 6847673Snate@binkert.org self.value = convert.toFrequency(value) 6857673Snate@binkert.org 6867673Snate@binkert.org def __getattr__(self, attr): 6873101Sstever@eecs.umich.edu if attr == 'frequency': 6883101Sstever@eecs.umich.edu return self 6893101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 6903101Sstever@eecs.umich.edu return Latency(self) 6913101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 6923101Sstever@eecs.umich.edu 6933101Sstever@eecs.umich.edu # convert latency to ticks 6943101Sstever@eecs.umich.edu def ini_str(self): 6953101Sstever@eecs.umich.edu if self.ticks or self.value == 0: 6963101Sstever@eecs.umich.edu return '%d' % self.value 6973101Sstever@eecs.umich.edu else: 6983101Sstever@eecs.umich.edu return '%d' % (ticks.fromSeconds(1.0 / self.value)) 6993101Sstever@eecs.umich.edu 7007743Sgblack@eecs.umich.edu# A generic frequency and/or Latency value. Value is stored as a latency, 7013101Sstever@eecs.umich.edu# but to avoid ambiguity this object does not support numeric ops (* or /). 7023101Sstever@eecs.umich.edu# An explicit conversion to a Latency or Frequency must be made first. 7033101Sstever@eecs.umich.educlass Clock(ParamValue): 7043101Sstever@eecs.umich.edu cxx_type = 'Tick' 7053101Sstever@eecs.umich.edu cxx_predecls = ['#include "sim/host.hh"'] 7063101Sstever@eecs.umich.edu swig_predecls = ['%import "python/m5/swig/stdint.i"\n' + 7074380Sbinkertn@umich.edu '%import "sim/host.hh"'] 7083101Sstever@eecs.umich.edu def __init__(self, value): 7093101Sstever@eecs.umich.edu if isinstance(value, (Latency, Clock)): 7104762Snate@binkert.org self.ticks = value.ticks 7117677Snate@binkert.org self.value = value.value 7124762Snate@binkert.org elif isinstance(value, Frequency): 7134762Snate@binkert.org self.ticks = value.ticks 7144380Sbinkertn@umich.edu self.value = 1.0 / value.value 7154380Sbinkertn@umich.edu elif value.endswith('t'): 7163101Sstever@eecs.umich.edu self.ticks = True 7177777Sgblack@eecs.umich.edu self.value = int(value[:-1]) 7187777Sgblack@eecs.umich.edu else: 7197777Sgblack@eecs.umich.edu self.ticks = False 7207777Sgblack@eecs.umich.edu self.value = convert.anyToLatency(value) 7217777Sgblack@eecs.umich.edu 7227777Sgblack@eecs.umich.edu def __getattr__(self, attr): 7237777Sgblack@eecs.umich.edu if attr == 'frequency': 7247777Sgblack@eecs.umich.edu return Frequency(self) 7257777Sgblack@eecs.umich.edu if attr in ('latency', 'period'): 7267777Sgblack@eecs.umich.edu return Latency(self) 7277777Sgblack@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 7287777Sgblack@eecs.umich.edu 7297777Sgblack@eecs.umich.edu def ini_str(self): 7307777Sgblack@eecs.umich.edu return self.period.ini_str() 7317777Sgblack@eecs.umich.edu 7327777Sgblack@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 7337777Sgblack@eecs.umich.edu cxx_type = 'float' 7347777Sgblack@eecs.umich.edu def __new__(cls, value): 7357777Sgblack@eecs.umich.edu # convert to bits per second 7367777Sgblack@eecs.umich.edu val = convert.toNetworkBandwidth(value) 7377777Sgblack@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 7387777Sgblack@eecs.umich.edu 7397777Sgblack@eecs.umich.edu def __str__(self): 7408579Ssteve.reinhardt@amd.com return str(self.val) 7418579Ssteve.reinhardt@amd.com 7428579Ssteve.reinhardt@amd.com def ini_str(self): 7438579Ssteve.reinhardt@amd.com # convert to seconds per byte 7448579Ssteve.reinhardt@amd.com value = 8.0 / float(self) 7458579Ssteve.reinhardt@amd.com # convert to ticks per byte 7468579Ssteve.reinhardt@amd.com return '%f' % (ticks.fromSeconds(value)) 7478579Ssteve.reinhardt@amd.com 7488579Ssteve.reinhardt@amd.comclass MemoryBandwidth(float,ParamValue): 7498579Ssteve.reinhardt@amd.com cxx_type = 'float' 7508579Ssteve.reinhardt@amd.com def __new__(self, value): 7518579Ssteve.reinhardt@amd.com # we want the number of ticks per byte of data 7528579Ssteve.reinhardt@amd.com val = convert.toMemoryBandwidth(value) 7538579Ssteve.reinhardt@amd.com return super(cls, MemoryBandwidth).__new__(cls, val) 7548579Ssteve.reinhardt@amd.com 7558579Ssteve.reinhardt@amd.com def __str__(self): 7568579Ssteve.reinhardt@amd.com return str(self.val) 7578579Ssteve.reinhardt@amd.com 7587777Sgblack@eecs.umich.edu def ini_str(self): 7597777Sgblack@eecs.umich.edu # convert to seconds per byte 7607798Sgblack@eecs.umich.edu value = 1.0 / float(self) 7617777Sgblack@eecs.umich.edu # convert to ticks per byte 7627777Sgblack@eecs.umich.edu return '%f' % (ticks.fromSeconds(value)) 7637777Sgblack@eecs.umich.edu 7647777Sgblack@eecs.umich.edu# 7657777Sgblack@eecs.umich.edu# "Constants"... handy aliases for various values. 7667777Sgblack@eecs.umich.edu# 7677777Sgblack@eecs.umich.edu 7687777Sgblack@eecs.umich.edu# Special class for NULL pointers. Note the special check in 7697777Sgblack@eecs.umich.edu# make_param_value() above that lets these be assigned where a 7707777Sgblack@eecs.umich.edu# SimObject is required. 7717777Sgblack@eecs.umich.edu# only one copy of a particular node 7727777Sgblack@eecs.umich.educlass NullSimObject(object): 7737777Sgblack@eecs.umich.edu __metaclass__ = Singleton 7747777Sgblack@eecs.umich.edu 7757777Sgblack@eecs.umich.edu def __call__(cls): 7767777Sgblack@eecs.umich.edu return cls 7777777Sgblack@eecs.umich.edu 7787777Sgblack@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 7797777Sgblack@eecs.umich.edu pass 7807777Sgblack@eecs.umich.edu 7817777Sgblack@eecs.umich.edu def ini_str(self): 7827777Sgblack@eecs.umich.edu return 'Null' 7837777Sgblack@eecs.umich.edu 7847777Sgblack@eecs.umich.edu def unproxy(self, base): 7857777Sgblack@eecs.umich.edu return self 7867777Sgblack@eecs.umich.edu 7877777Sgblack@eecs.umich.edu def set_path(self, parent, name): 7887777Sgblack@eecs.umich.edu pass 7897777Sgblack@eecs.umich.edu def __str__(self): 7907777Sgblack@eecs.umich.edu return 'Null' 7917777Sgblack@eecs.umich.edu 7927777Sgblack@eecs.umich.edu# The only instance you'll ever need... 7937777Sgblack@eecs.umich.eduNULL = NullSimObject() 7947777Sgblack@eecs.umich.edu 7957777Sgblack@eecs.umich.edudef isNullPointer(value): 7967777Sgblack@eecs.umich.edu return isinstance(value, NullSimObject) 7977777Sgblack@eecs.umich.edu 7987777Sgblack@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 7997777Sgblack@eecs.umich.eduMaxAddr = Addr.max 8007777Sgblack@eecs.umich.eduMaxTick = Tick.max 8017777Sgblack@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 8027777Sgblack@eecs.umich.edu 8037777Sgblack@eecs.umich.edu 8047777Sgblack@eecs.umich.edu##################################################################### 8057777Sgblack@eecs.umich.edu# 8067777Sgblack@eecs.umich.edu# Port objects 8077777Sgblack@eecs.umich.edu# 8087777Sgblack@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 8097777Sgblack@eecs.umich.edu# 8107777Sgblack@eecs.umich.edu##################################################################### 8117777Sgblack@eecs.umich.edu 8127777Sgblack@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 8137777Sgblack@eecs.umich.edu# particular SimObject. 8147777Sgblack@eecs.umich.educlass PortRef(object): 8157777Sgblack@eecs.umich.edu def __init__(self, simobj, name): 8168579Ssteve.reinhardt@amd.com assert(isSimObject(simobj) or isSimObjectClass(simobj)) 8178579Ssteve.reinhardt@amd.com self.simobj = simobj 8188579Ssteve.reinhardt@amd.com self.name = name 8198579Ssteve.reinhardt@amd.com self.peer = None # not associated with another port yet 8208579Ssteve.reinhardt@amd.com self.ccConnected = False # C++ port connection done? 8218579Ssteve.reinhardt@amd.com self.index = -1 # always -1 for non-vector ports 8228579Ssteve.reinhardt@amd.com 8238579Ssteve.reinhardt@amd.com def __str__(self): 8248579Ssteve.reinhardt@amd.com return '%s.%s' % (self.simobj, self.name) 8258579Ssteve.reinhardt@amd.com 8268579Ssteve.reinhardt@amd.com # for config.ini, print peer's name (not ours) 8278579Ssteve.reinhardt@amd.com def ini_str(self): 8288579Ssteve.reinhardt@amd.com return str(self.peer) 8298579Ssteve.reinhardt@amd.com 8307777Sgblack@eecs.umich.edu def __getattr__(self, attr): 8317777Sgblack@eecs.umich.edu if attr == 'peerObj': 8327777Sgblack@eecs.umich.edu # shorthand for proxies 8337777Sgblack@eecs.umich.edu return self.peer.simobj 8347777Sgblack@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 8357777Sgblack@eecs.umich.edu (self.__class__.__name__, attr) 8367777Sgblack@eecs.umich.edu 8377777Sgblack@eecs.umich.edu # Full connection is symmetric (both ways). Called via 8387777Sgblack@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 8397777Sgblack@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 8407777Sgblack@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 8417777Sgblack@eecs.umich.edu def connect(self, other): 8427777Sgblack@eecs.umich.edu if isinstance(other, VectorPortRef): 8437777Sgblack@eecs.umich.edu # reference to plain VectorPort is implicit append 8447777Sgblack@eecs.umich.edu other = other._get_next() 8457777Sgblack@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 8467777Sgblack@eecs.umich.edu print "warning: overwriting port", self, \ 8477777Sgblack@eecs.umich.edu "value", self.peer, "with", other 8487777Sgblack@eecs.umich.edu self.peer = other 8497777Sgblack@eecs.umich.edu if proxy.isproxy(other): 8507777Sgblack@eecs.umich.edu other.set_param_desc(PortParamDesc()) 8517777Sgblack@eecs.umich.edu elif isinstance(other, PortRef): 8527777Sgblack@eecs.umich.edu if other.peer is not self: 8537777Sgblack@eecs.umich.edu other.connect(self) 8547777Sgblack@eecs.umich.edu else: 8557777Sgblack@eecs.umich.edu raise TypeError, \ 8567777Sgblack@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 8577777Sgblack@eecs.umich.edu % (other, self) 8587777Sgblack@eecs.umich.edu 8597777Sgblack@eecs.umich.edu def clone(self, simobj, memo): 8607777Sgblack@eecs.umich.edu if memo.has_key(self): 8617777Sgblack@eecs.umich.edu return memo[self] 8627777Sgblack@eecs.umich.edu newRef = copy.copy(self) 8637777Sgblack@eecs.umich.edu memo[self] = newRef 8647777Sgblack@eecs.umich.edu newRef.simobj = simobj 8657777Sgblack@eecs.umich.edu assert(isSimObject(newRef.simobj)) 8667777Sgblack@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 8677777Sgblack@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 8687777Sgblack@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 8697777Sgblack@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 8707777Sgblack@eecs.umich.edu return newRef 8717777Sgblack@eecs.umich.edu 8727777Sgblack@eecs.umich.edu def unproxy(self, simobj): 8737777Sgblack@eecs.umich.edu assert(simobj is self.simobj) 8747777Sgblack@eecs.umich.edu if proxy.isproxy(self.peer): 8757777Sgblack@eecs.umich.edu try: 8767777Sgblack@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 8777777Sgblack@eecs.umich.edu except: 8787777Sgblack@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 8797777Sgblack@eecs.umich.edu (self.name, self.simobj.path()) 8807777Sgblack@eecs.umich.edu raise 8817777Sgblack@eecs.umich.edu self.connect(realPeer) 8827777Sgblack@eecs.umich.edu 8837777Sgblack@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 8847777Sgblack@eecs.umich.edu def ccConnect(self): 8857777Sgblack@eecs.umich.edu if self.ccConnected: # already done this 8867777Sgblack@eecs.umich.edu return 8877777Sgblack@eecs.umich.edu peer = self.peer 8888579Ssteve.reinhardt@amd.com internal.sim_object.connectPorts(self.simobj.getCCObject(), self.name, 8898579Ssteve.reinhardt@amd.com self.index, peer.simobj.getCCObject(), peer.name, peer.index) 8908579Ssteve.reinhardt@amd.com self.ccConnected = True 8918579Ssteve.reinhardt@amd.com peer.ccConnected = True 8928579Ssteve.reinhardt@amd.com 8938579Ssteve.reinhardt@amd.com# A reference to an individual element of a VectorPort... much like a 8948579Ssteve.reinhardt@amd.com# PortRef, but has an index. 8958579Ssteve.reinhardt@amd.comclass VectorPortElementRef(PortRef): 8968579Ssteve.reinhardt@amd.com def __init__(self, simobj, name, index): 8978579Ssteve.reinhardt@amd.com PortRef.__init__(self, simobj, name) 8988579Ssteve.reinhardt@amd.com self.index = index 8998579Ssteve.reinhardt@amd.com 9008579Ssteve.reinhardt@amd.com def __str__(self): 9018579Ssteve.reinhardt@amd.com return '%s.%s[%d]' % (self.simobj, self.name, self.index) 9027777Sgblack@eecs.umich.edu 9037777Sgblack@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 9047777Sgblack@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 9057777Sgblack@eecs.umich.educlass VectorPortRef(object): 9067777Sgblack@eecs.umich.edu def __init__(self, simobj, name): 9077777Sgblack@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 9087777Sgblack@eecs.umich.edu self.simobj = simobj 9097777Sgblack@eecs.umich.edu self.name = name 9107777Sgblack@eecs.umich.edu self.elements = [] 9113932Sbinkertn@umich.edu 9123932Sbinkertn@umich.edu def __str__(self): 9133932Sbinkertn@umich.edu return '%s.%s[:]' % (self.simobj, self.name) 9143932Sbinkertn@umich.edu 9153932Sbinkertn@umich.edu # for config.ini, print peer's name (not ours) 9163932Sbinkertn@umich.edu def ini_str(self): 9173932Sbinkertn@umich.edu return ' '.join([el.ini_str() for el in self.elements]) 9183932Sbinkertn@umich.edu 9193932Sbinkertn@umich.edu def __getitem__(self, key): 9203932Sbinkertn@umich.edu if not isinstance(key, int): 9213932Sbinkertn@umich.edu raise TypeError, "VectorPort index must be integer" 9223932Sbinkertn@umich.edu if key >= len(self.elements): 9233932Sbinkertn@umich.edu # need to extend list 9243885Sbinkertn@umich.edu ext = [VectorPortElementRef(self.simobj, self.name, i) 9253932Sbinkertn@umich.edu for i in range(len(self.elements), key+1)] 9263932Sbinkertn@umich.edu self.elements.extend(ext) 9273885Sbinkertn@umich.edu return self.elements[key] 9283932Sbinkertn@umich.edu 9293932Sbinkertn@umich.edu def _get_next(self): 9303932Sbinkertn@umich.edu return self[len(self.elements)] 9313932Sbinkertn@umich.edu 9323932Sbinkertn@umich.edu def __setitem__(self, key, value): 9333932Sbinkertn@umich.edu if not isinstance(key, int): 9343932Sbinkertn@umich.edu raise TypeError, "VectorPort index must be integer" 9353932Sbinkertn@umich.edu self[key].connect(value) 9363932Sbinkertn@umich.edu 9373932Sbinkertn@umich.edu def connect(self, other): 9383932Sbinkertn@umich.edu if isinstance(other, (list, tuple)): 9393932Sbinkertn@umich.edu # Assign list of port refs to vector port. 9403932Sbinkertn@umich.edu # For now, append them... not sure if that's the right semantics 9413932Sbinkertn@umich.edu # or if it should replace the current vector. 9423932Sbinkertn@umich.edu for ref in other: 9433932Sbinkertn@umich.edu self._get_next().connect(ref) 9443932Sbinkertn@umich.edu else: 9453932Sbinkertn@umich.edu # scalar assignment to plain VectorPort is implicit append 9463885Sbinkertn@umich.edu self._get_next().connect(other) 9473885Sbinkertn@umich.edu 9483885Sbinkertn@umich.edu def clone(self, simobj, memo): 9493885Sbinkertn@umich.edu if memo.has_key(self): 9504762Snate@binkert.org return memo[self] 9517673Snate@binkert.org newRef = copy.copy(self) 9527673Snate@binkert.org memo[self] = newRef 9537673Snate@binkert.org newRef.simobj = simobj 9547673Snate@binkert.org assert(isSimObject(newRef.simobj)) 9557673Snate@binkert.org newRef.elements = [el.clone(simobj, memo) for el in self.elements] 9567673Snate@binkert.org return newRef 9577673Snate@binkert.org 9587673Snate@binkert.org def unproxy(self, simobj): 9597673Snate@binkert.org [el.unproxy(simobj) for el in self.elements] 9603885Sbinkertn@umich.edu 9613932Sbinkertn@umich.edu def ccConnect(self): 9623885Sbinkertn@umich.edu [el.ccConnect() for el in self.elements] 9634762Snate@binkert.org 9647677Snate@binkert.org# Port description object. Like a ParamDesc object, this represents a 9654762Snate@binkert.org# logical port in the SimObject class, not a particular port on a 9664762Snate@binkert.org# SimObject instance. The latter are represented by PortRef objects. 9674762Snate@binkert.orgclass Port(object): 9684762Snate@binkert.org # Port("description") or Port(default, "description") 9694762Snate@binkert.org def __init__(self, *args): 9704762Snate@binkert.org if len(args) == 1: 9714762Snate@binkert.org self.desc = args[0] 9724762Snate@binkert.org elif len(args) == 2: 9734762Snate@binkert.org self.default = args[0] 9744762Snate@binkert.org self.desc = args[1] 9754762Snate@binkert.org else: 9764762Snate@binkert.org raise TypeError, 'wrong number of arguments' 9774762Snate@binkert.org # self.name is set by SimObject class on assignment 9784762Snate@binkert.org # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 9794762Snate@binkert.org 9804762Snate@binkert.org # Generate a PortRef for this port on the given SimObject with the 9814762Snate@binkert.org # given name 9824762Snate@binkert.org def makeRef(self, simobj): 9834762Snate@binkert.org return PortRef(simobj, self.name) 9844762Snate@binkert.org 9854762Snate@binkert.org # Connect an instance of this port (on the given SimObject with 9864762Snate@binkert.org # the given name) with the port described by the supplied PortRef 9874762Snate@binkert.org def connect(self, simobj, ref): 9884762Snate@binkert.org self.makeRef(simobj).connect(ref) 9893885Sbinkertn@umich.edu 9904762Snate@binkert.org# VectorPort description object. Like Port, but represents a vector 9913885Sbinkertn@umich.edu# of connections (e.g., as on a Bus). 9923885Sbinkertn@umich.educlass VectorPort(Port): 9933932Sbinkertn@umich.edu def __init__(self, *args): 9943885Sbinkertn@umich.edu Port.__init__(self, *args) 9958664SAli.Saidi@ARM.com self.isVec = True 9968664SAli.Saidi@ARM.com 9978664SAli.Saidi@ARM.com def makeRef(self, simobj): 9983101Sstever@eecs.umich.edu return VectorPortRef(simobj, self.name) 9993101Sstever@eecs.umich.edu 10003101Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 10013101Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 10023101Sstever@eecs.umich.edu# make sense. 10033101Sstever@eecs.umich.educlass PortParamDesc(object): 10043101Sstever@eecs.umich.edu __metaclass__ = Singleton 10053101Sstever@eecs.umich.edu 10063101Sstever@eecs.umich.edu ptype_str = 'Port' 10073101Sstever@eecs.umich.edu ptype = Port 10083101Sstever@eecs.umich.edu 10093101Sstever@eecs.umich.edu 10103101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 10113101Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 10124762Snate@binkert.org 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 10133101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 10145033Smilesck@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 10154762Snate@binkert.org 'TcpPort', 'UdpPort', 'EthernetAddr', 10164762Snate@binkert.org 'MemorySize', 'MemorySize32', 10174762Snate@binkert.org 'Latency', 'Frequency', 'Clock', 10184762Snate@binkert.org 'NetworkBandwidth', 'MemoryBandwidth', 10194762Snate@binkert.org 'Range', 'AddrRange', 'TickRange', 10204762Snate@binkert.org 'MaxAddr', 'MaxTick', 'AllMemory', 10214762Snate@binkert.org 'Time', 10223101Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 10233101Sstever@eecs.umich.edu 'Port', 'VectorPort'] 10243101Sstever@eecs.umich.edu 10253101Sstever@eecs.umich.edu# see comment on imports at end of __init__.py. 10263101Sstever@eecs.umich.edufrom SimObject import isSimObject, isSimObjectSequence, isSimObjectClass 10273101Sstever@eecs.umich.eduimport objects 10283101Sstever@eecs.umich.eduimport internal 10293101Sstever@eecs.umich.edu