params.py revision 7673
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 303101Sstever@eecs.umich.edu 313101Sstever@eecs.umich.edu##################################################################### 323101Sstever@eecs.umich.edu# 333101Sstever@eecs.umich.edu# Parameter description classes 343101Sstever@eecs.umich.edu# 353101Sstever@eecs.umich.edu# The _params dictionary in each class maps parameter names to either 363101Sstever@eecs.umich.edu# a Param or a VectorParam object. These objects contain the 373101Sstever@eecs.umich.edu# parameter description string, the parameter type, and the default 383101Sstever@eecs.umich.edu# value (if any). The convert() method on these objects is used to 393101Sstever@eecs.umich.edu# force whatever value is assigned to the parameter to the appropriate 403101Sstever@eecs.umich.edu# type. 413101Sstever@eecs.umich.edu# 423101Sstever@eecs.umich.edu# Note that the default values are loaded into the class's attribute 433101Sstever@eecs.umich.edu# space when the parameter dictionary is initialized (in 443101Sstever@eecs.umich.edu# MetaSimObject._new_param()); after that point they aren't used. 453101Sstever@eecs.umich.edu# 463101Sstever@eecs.umich.edu##################################################################### 473101Sstever@eecs.umich.edu 483885Sbinkertn@umich.eduimport copy 493885Sbinkertn@umich.eduimport datetime 504762Snate@binkert.orgimport re 513885Sbinkertn@umich.eduimport sys 523885Sbinkertn@umich.eduimport time 537528Ssteve.reinhardt@amd.comimport math 543885Sbinkertn@umich.edu 554380Sbinkertn@umich.eduimport proxy 564167Sbinkertn@umich.eduimport ticks 573102Sstever@eecs.umich.edufrom util import * 583101Sstever@eecs.umich.edu 594762Snate@binkert.orgdef isSimObject(*args, **kwargs): 604762Snate@binkert.org return SimObject.isSimObject(*args, **kwargs) 614762Snate@binkert.org 624762Snate@binkert.orgdef isSimObjectSequence(*args, **kwargs): 634762Snate@binkert.org return SimObject.isSimObjectSequence(*args, **kwargs) 644762Snate@binkert.org 654762Snate@binkert.orgdef isSimObjectClass(*args, **kwargs): 664762Snate@binkert.org return SimObject.isSimObjectClass(*args, **kwargs) 674762Snate@binkert.org 685033Smilesck@eecs.umich.eduallParams = {} 695033Smilesck@eecs.umich.edu 705033Smilesck@eecs.umich.educlass MetaParamValue(type): 715033Smilesck@eecs.umich.edu def __new__(mcls, name, bases, dct): 725033Smilesck@eecs.umich.edu cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 735033Smilesck@eecs.umich.edu assert name not in allParams 745033Smilesck@eecs.umich.edu allParams[name] = cls 755033Smilesck@eecs.umich.edu return cls 765033Smilesck@eecs.umich.edu 775033Smilesck@eecs.umich.edu 783101Sstever@eecs.umich.edu# Dummy base class to identify types that are legitimate for SimObject 793101Sstever@eecs.umich.edu# parameters. 803101Sstever@eecs.umich.educlass ParamValue(object): 815033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 823101Sstever@eecs.umich.edu 837673Snate@binkert.org @classmethod 847673Snate@binkert.org def cxx_predecls(cls, code): 857673Snate@binkert.org pass 867673Snate@binkert.org 877673Snate@binkert.org @classmethod 887673Snate@binkert.org def swig_predecls(cls, code): 897673Snate@binkert.org pass 903101Sstever@eecs.umich.edu 913101Sstever@eecs.umich.edu # default for printing to .ini file is regular string conversion. 923101Sstever@eecs.umich.edu # will be overridden in some cases 933101Sstever@eecs.umich.edu def ini_str(self): 943101Sstever@eecs.umich.edu return str(self) 953101Sstever@eecs.umich.edu 963101Sstever@eecs.umich.edu # allows us to blithely call unproxy() on things without checking 973101Sstever@eecs.umich.edu # if they're really proxies or not 983101Sstever@eecs.umich.edu def unproxy(self, base): 993101Sstever@eecs.umich.edu return self 1003101Sstever@eecs.umich.edu 1013101Sstever@eecs.umich.edu# Regular parameter description. 1023101Sstever@eecs.umich.educlass ParamDesc(object): 1036656Snate@binkert.org file_ext = 'ptype' 1046656Snate@binkert.org 1053101Sstever@eecs.umich.edu def __init__(self, ptype_str, ptype, *args, **kwargs): 1063101Sstever@eecs.umich.edu self.ptype_str = ptype_str 1073101Sstever@eecs.umich.edu # remember ptype only if it is provided 1083101Sstever@eecs.umich.edu if ptype != None: 1093101Sstever@eecs.umich.edu self.ptype = ptype 1103101Sstever@eecs.umich.edu 1113101Sstever@eecs.umich.edu if args: 1123101Sstever@eecs.umich.edu if len(args) == 1: 1133101Sstever@eecs.umich.edu self.desc = args[0] 1143101Sstever@eecs.umich.edu elif len(args) == 2: 1153101Sstever@eecs.umich.edu self.default = args[0] 1163101Sstever@eecs.umich.edu self.desc = args[1] 1173101Sstever@eecs.umich.edu else: 1183101Sstever@eecs.umich.edu raise TypeError, 'too many arguments' 1193101Sstever@eecs.umich.edu 1203101Sstever@eecs.umich.edu if kwargs.has_key('desc'): 1213101Sstever@eecs.umich.edu assert(not hasattr(self, 'desc')) 1223101Sstever@eecs.umich.edu self.desc = kwargs['desc'] 1233101Sstever@eecs.umich.edu del kwargs['desc'] 1243101Sstever@eecs.umich.edu 1253101Sstever@eecs.umich.edu if kwargs.has_key('default'): 1263101Sstever@eecs.umich.edu assert(not hasattr(self, 'default')) 1273101Sstever@eecs.umich.edu self.default = kwargs['default'] 1283101Sstever@eecs.umich.edu del kwargs['default'] 1293101Sstever@eecs.umich.edu 1303101Sstever@eecs.umich.edu if kwargs: 1313101Sstever@eecs.umich.edu raise TypeError, 'extra unknown kwargs %s' % kwargs 1323101Sstever@eecs.umich.edu 1333101Sstever@eecs.umich.edu if not hasattr(self, 'desc'): 1343101Sstever@eecs.umich.edu raise TypeError, 'desc attribute missing' 1353101Sstever@eecs.umich.edu 1363101Sstever@eecs.umich.edu def __getattr__(self, attr): 1373101Sstever@eecs.umich.edu if attr == 'ptype': 1385033Smilesck@eecs.umich.edu ptype = SimObject.allClasses[self.ptype_str] 1396656Snate@binkert.org assert isSimObjectClass(ptype) 1405033Smilesck@eecs.umich.edu self.ptype = ptype 1415033Smilesck@eecs.umich.edu return ptype 1425033Smilesck@eecs.umich.edu 1433101Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 1443101Sstever@eecs.umich.edu (type(self).__name__, attr) 1453101Sstever@eecs.umich.edu 1463101Sstever@eecs.umich.edu def convert(self, value): 1473101Sstever@eecs.umich.edu if isinstance(value, proxy.BaseProxy): 1483101Sstever@eecs.umich.edu value.set_param_desc(self) 1493101Sstever@eecs.umich.edu return value 1503101Sstever@eecs.umich.edu if not hasattr(self, 'ptype') and isNullPointer(value): 1513101Sstever@eecs.umich.edu # deferred evaluation of SimObject; continue to defer if 1523101Sstever@eecs.umich.edu # we're just assigning a null pointer 1533101Sstever@eecs.umich.edu return value 1543101Sstever@eecs.umich.edu if isinstance(value, self.ptype): 1553101Sstever@eecs.umich.edu return value 1563102Sstever@eecs.umich.edu if isNullPointer(value) and isSimObjectClass(self.ptype): 1573101Sstever@eecs.umich.edu return value 1583101Sstever@eecs.umich.edu return self.ptype(value) 1593101Sstever@eecs.umich.edu 1607673Snate@binkert.org def cxx_predecls(self, code): 1617673Snate@binkert.org self.ptype.cxx_predecls(code) 1623101Sstever@eecs.umich.edu 1637673Snate@binkert.org def swig_predecls(self, code): 1647673Snate@binkert.org self.ptype.swig_predecls(code) 1653101Sstever@eecs.umich.edu 1667673Snate@binkert.org def cxx_decl(self, code): 1677673Snate@binkert.org code('${{self.ptype.cxx_type}} ${{self.name}};') 1683101Sstever@eecs.umich.edu 1693101Sstever@eecs.umich.edu# Vector-valued parameter description. Just like ParamDesc, except 1703101Sstever@eecs.umich.edu# that the value is a vector (list) of the specified type instead of a 1713101Sstever@eecs.umich.edu# single value. 1723101Sstever@eecs.umich.edu 1733101Sstever@eecs.umich.educlass VectorParamValue(list): 1745033Smilesck@eecs.umich.edu __metaclass__ = MetaParamValue 1755475Snate@binkert.org def __setattr__(self, attr, value): 1765475Snate@binkert.org raise AttributeError, \ 1775475Snate@binkert.org "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 1785475Snate@binkert.org 1793101Sstever@eecs.umich.edu def ini_str(self): 1803101Sstever@eecs.umich.edu return ' '.join([v.ini_str() for v in self]) 1813101Sstever@eecs.umich.edu 1824762Snate@binkert.org def getValue(self): 1834762Snate@binkert.org return [ v.getValue() for v in self ] 1844762Snate@binkert.org 1853101Sstever@eecs.umich.edu def unproxy(self, base): 1863101Sstever@eecs.umich.edu return [v.unproxy(base) for v in self] 1873101Sstever@eecs.umich.edu 1887528Ssteve.reinhardt@amd.comclass SimObjectVector(VectorParamValue): 1897528Ssteve.reinhardt@amd.com # support clone operation 1907528Ssteve.reinhardt@amd.com def __call__(self, **kwargs): 1917528Ssteve.reinhardt@amd.com return SimObjectVector([v(**kwargs) for v in self]) 1927528Ssteve.reinhardt@amd.com 1937528Ssteve.reinhardt@amd.com def clear_parent(self, old_parent): 1943101Sstever@eecs.umich.edu for v in self: 1957528Ssteve.reinhardt@amd.com v.clear_parent(old_parent) 1967528Ssteve.reinhardt@amd.com 1977528Ssteve.reinhardt@amd.com def set_parent(self, parent, name): 1987528Ssteve.reinhardt@amd.com if len(self) == 1: 1997528Ssteve.reinhardt@amd.com self[0].set_parent(parent, name) 2007528Ssteve.reinhardt@amd.com else: 2017528Ssteve.reinhardt@amd.com width = int(math.ceil(math.log(len(self))/math.log(10))) 2027528Ssteve.reinhardt@amd.com for i,v in enumerate(self): 2037528Ssteve.reinhardt@amd.com v.set_parent(parent, "%s%0*d" % (name, width, i)) 2047528Ssteve.reinhardt@amd.com 2057528Ssteve.reinhardt@amd.com def get_parent(self): 2067528Ssteve.reinhardt@amd.com parent_set = set(v._parent for v in self) 2077528Ssteve.reinhardt@amd.com if len(parent_set) != 1: 2087528Ssteve.reinhardt@amd.com raise RuntimeError, \ 2097528Ssteve.reinhardt@amd.com "SimObjectVector elements have inconsistent parent value." 2107528Ssteve.reinhardt@amd.com return parent_set.pop() 2117528Ssteve.reinhardt@amd.com 2127528Ssteve.reinhardt@amd.com # return 'cpu0 cpu1' etc. for print_ini() 2137528Ssteve.reinhardt@amd.com def get_name(self): 2147528Ssteve.reinhardt@amd.com return ' '.join([v._name for v in self]) 2157528Ssteve.reinhardt@amd.com 2167528Ssteve.reinhardt@amd.com # By iterating through the constituent members of the vector here 2177528Ssteve.reinhardt@amd.com # we can nicely handle iterating over all a SimObject's children 2187528Ssteve.reinhardt@amd.com # without having to provide lots of special functions on 2197528Ssteve.reinhardt@amd.com # SimObjectVector directly. 2207528Ssteve.reinhardt@amd.com def descendants(self): 2217528Ssteve.reinhardt@amd.com for v in self: 2227528Ssteve.reinhardt@amd.com for obj in v.descendants(): 2237528Ssteve.reinhardt@amd.com yield obj 2243101Sstever@eecs.umich.edu 2253101Sstever@eecs.umich.educlass VectorParamDesc(ParamDesc): 2266656Snate@binkert.org file_ext = 'vptype' 2276656Snate@binkert.org 2283101Sstever@eecs.umich.edu # Convert assigned value to appropriate type. If the RHS is not a 2293101Sstever@eecs.umich.edu # list or tuple, it generates a single-element list. 2303101Sstever@eecs.umich.edu def convert(self, value): 2313101Sstever@eecs.umich.edu if isinstance(value, (list, tuple)): 2323101Sstever@eecs.umich.edu # list: coerce each element into new list 2333101Sstever@eecs.umich.edu tmp_list = [ ParamDesc.convert(self, v) for v in value ] 2343101Sstever@eecs.umich.edu else: 2354762Snate@binkert.org # singleton: coerce to a single-element list 2364762Snate@binkert.org tmp_list = [ ParamDesc.convert(self, value) ] 2374762Snate@binkert.org 2384762Snate@binkert.org if isSimObjectSequence(tmp_list): 2397528Ssteve.reinhardt@amd.com return SimObjectVector(tmp_list) 2404762Snate@binkert.org else: 2414762Snate@binkert.org return VectorParamValue(tmp_list) 2424762Snate@binkert.org 2437673Snate@binkert.org def swig_predecls(self, code): 2447673Snate@binkert.org code('%include "${{self.ptype_str}}_vptype.i"') 2454762Snate@binkert.org 2467673Snate@binkert.org def swig_decl(self, code): 2474762Snate@binkert.org cxx_type = re.sub('std::', '', self.ptype.cxx_type) 2487673Snate@binkert.org code('%include "std_vector.i"') 2497673Snate@binkert.org self.ptype.swig_predecls(code) 2507673Snate@binkert.org code('''\ 2517673Snate@binkert.orgnamespace std { 2527673Snate@binkert.org%template(vector_${{self.ptype_str}}) vector< $cxx_type >; 2537673Snate@binkert.org} 2547673Snate@binkert.org''') 2553101Sstever@eecs.umich.edu 2567673Snate@binkert.org def cxx_predecls(self, code): 2577673Snate@binkert.org code('#include <vector>') 2587673Snate@binkert.org self.ptype.cxx_predecls(code) 2593101Sstever@eecs.umich.edu 2607673Snate@binkert.org def cxx_decl(self, code): 2617673Snate@binkert.org code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 2623101Sstever@eecs.umich.edu 2633101Sstever@eecs.umich.educlass ParamFactory(object): 2643101Sstever@eecs.umich.edu def __init__(self, param_desc_class, ptype_str = None): 2653101Sstever@eecs.umich.edu self.param_desc_class = param_desc_class 2663101Sstever@eecs.umich.edu self.ptype_str = ptype_str 2673101Sstever@eecs.umich.edu 2683101Sstever@eecs.umich.edu def __getattr__(self, attr): 2693101Sstever@eecs.umich.edu if self.ptype_str: 2703101Sstever@eecs.umich.edu attr = self.ptype_str + '.' + attr 2713101Sstever@eecs.umich.edu return ParamFactory(self.param_desc_class, attr) 2723101Sstever@eecs.umich.edu 2733101Sstever@eecs.umich.edu # E.g., Param.Int(5, "number of widgets") 2743101Sstever@eecs.umich.edu def __call__(self, *args, **kwargs): 2753101Sstever@eecs.umich.edu ptype = None 2763101Sstever@eecs.umich.edu try: 2775033Smilesck@eecs.umich.edu ptype = allParams[self.ptype_str] 2785033Smilesck@eecs.umich.edu except KeyError: 2793101Sstever@eecs.umich.edu # if name isn't defined yet, assume it's a SimObject, and 2803101Sstever@eecs.umich.edu # try to resolve it later 2813101Sstever@eecs.umich.edu pass 2823101Sstever@eecs.umich.edu return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 2833101Sstever@eecs.umich.edu 2843101Sstever@eecs.umich.eduParam = ParamFactory(ParamDesc) 2853101Sstever@eecs.umich.eduVectorParam = ParamFactory(VectorParamDesc) 2863101Sstever@eecs.umich.edu 2873101Sstever@eecs.umich.edu##################################################################### 2883101Sstever@eecs.umich.edu# 2893101Sstever@eecs.umich.edu# Parameter Types 2903101Sstever@eecs.umich.edu# 2913101Sstever@eecs.umich.edu# Though native Python types could be used to specify parameter types 2923101Sstever@eecs.umich.edu# (the 'ptype' field of the Param and VectorParam classes), it's more 2933101Sstever@eecs.umich.edu# flexible to define our own set of types. This gives us more control 2943101Sstever@eecs.umich.edu# over how Python expressions are converted to values (via the 2953101Sstever@eecs.umich.edu# __init__() constructor) and how these values are printed out (via 2963101Sstever@eecs.umich.edu# the __str__() conversion method). 2973101Sstever@eecs.umich.edu# 2983101Sstever@eecs.umich.edu##################################################################### 2993101Sstever@eecs.umich.edu 3003101Sstever@eecs.umich.edu# String-valued parameter. Just mixin the ParamValue class with the 3013101Sstever@eecs.umich.edu# built-in str class. 3023101Sstever@eecs.umich.educlass String(ParamValue,str): 3033101Sstever@eecs.umich.edu cxx_type = 'std::string' 3047673Snate@binkert.org 3057673Snate@binkert.org @classmethod 3067673Snate@binkert.org def cxx_predecls(self, code): 3077673Snate@binkert.org code('#include <string>') 3087673Snate@binkert.org 3097673Snate@binkert.org @classmethod 3107673Snate@binkert.org def swig_predecls(cls, code): 3117673Snate@binkert.org code('%include "std_string.i"') 3124762Snate@binkert.org 3134762Snate@binkert.org def getValue(self): 3144762Snate@binkert.org return self 3153101Sstever@eecs.umich.edu 3163101Sstever@eecs.umich.edu# superclass for "numeric" parameter values, to emulate math 3173101Sstever@eecs.umich.edu# operations in a type-safe way. e.g., a Latency times an int returns 3183101Sstever@eecs.umich.edu# a new Latency object. 3193101Sstever@eecs.umich.educlass NumericParamValue(ParamValue): 3203101Sstever@eecs.umich.edu def __str__(self): 3213101Sstever@eecs.umich.edu return str(self.value) 3223101Sstever@eecs.umich.edu 3233101Sstever@eecs.umich.edu def __float__(self): 3243101Sstever@eecs.umich.edu return float(self.value) 3253101Sstever@eecs.umich.edu 3263714Sstever@eecs.umich.edu def __long__(self): 3273714Sstever@eecs.umich.edu return long(self.value) 3283714Sstever@eecs.umich.edu 3293714Sstever@eecs.umich.edu def __int__(self): 3303714Sstever@eecs.umich.edu return int(self.value) 3313714Sstever@eecs.umich.edu 3323101Sstever@eecs.umich.edu # hook for bounds checking 3333101Sstever@eecs.umich.edu def _check(self): 3343101Sstever@eecs.umich.edu return 3353101Sstever@eecs.umich.edu 3363101Sstever@eecs.umich.edu def __mul__(self, other): 3373101Sstever@eecs.umich.edu newobj = self.__class__(self) 3383101Sstever@eecs.umich.edu newobj.value *= other 3393101Sstever@eecs.umich.edu newobj._check() 3403101Sstever@eecs.umich.edu return newobj 3413101Sstever@eecs.umich.edu 3423101Sstever@eecs.umich.edu __rmul__ = __mul__ 3433101Sstever@eecs.umich.edu 3443101Sstever@eecs.umich.edu def __div__(self, other): 3453101Sstever@eecs.umich.edu newobj = self.__class__(self) 3463101Sstever@eecs.umich.edu newobj.value /= other 3473101Sstever@eecs.umich.edu newobj._check() 3483101Sstever@eecs.umich.edu return newobj 3493101Sstever@eecs.umich.edu 3503101Sstever@eecs.umich.edu def __sub__(self, other): 3513101Sstever@eecs.umich.edu newobj = self.__class__(self) 3523101Sstever@eecs.umich.edu newobj.value -= other 3533101Sstever@eecs.umich.edu newobj._check() 3543101Sstever@eecs.umich.edu return newobj 3553101Sstever@eecs.umich.edu 3563101Sstever@eecs.umich.edu# Metaclass for bounds-checked integer parameters. See CheckedInt. 3575033Smilesck@eecs.umich.educlass CheckedIntType(MetaParamValue): 3583101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 3593101Sstever@eecs.umich.edu super(CheckedIntType, cls).__init__(name, bases, dict) 3603101Sstever@eecs.umich.edu 3613101Sstever@eecs.umich.edu # CheckedInt is an abstract base class, so we actually don't 3623101Sstever@eecs.umich.edu # want to do any processing on it... the rest of this code is 3633101Sstever@eecs.umich.edu # just for classes that derive from CheckedInt. 3643101Sstever@eecs.umich.edu if name == 'CheckedInt': 3653101Sstever@eecs.umich.edu return 3663101Sstever@eecs.umich.edu 3673101Sstever@eecs.umich.edu if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 3683101Sstever@eecs.umich.edu if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 3693101Sstever@eecs.umich.edu panic("CheckedInt subclass %s must define either\n" \ 3705822Ssaidi@eecs.umich.edu " 'min' and 'max' or 'size' and 'unsigned'\n", 3715822Ssaidi@eecs.umich.edu name); 3723101Sstever@eecs.umich.edu if cls.unsigned: 3733101Sstever@eecs.umich.edu cls.min = 0 3743101Sstever@eecs.umich.edu cls.max = 2 ** cls.size - 1 3753101Sstever@eecs.umich.edu else: 3763101Sstever@eecs.umich.edu cls.min = -(2 ** (cls.size - 1)) 3773101Sstever@eecs.umich.edu cls.max = (2 ** (cls.size - 1)) - 1 3783101Sstever@eecs.umich.edu 3793101Sstever@eecs.umich.edu# Abstract superclass for bounds-checked integer parameters. This 3803101Sstever@eecs.umich.edu# class is subclassed to generate parameter classes with specific 3813101Sstever@eecs.umich.edu# bounds. Initialization of the min and max bounds is done in the 3823101Sstever@eecs.umich.edu# metaclass CheckedIntType.__init__. 3833101Sstever@eecs.umich.educlass CheckedInt(NumericParamValue): 3843101Sstever@eecs.umich.edu __metaclass__ = CheckedIntType 3853101Sstever@eecs.umich.edu 3863101Sstever@eecs.umich.edu def _check(self): 3873101Sstever@eecs.umich.edu if not self.min <= self.value <= self.max: 3883101Sstever@eecs.umich.edu raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 3893101Sstever@eecs.umich.edu (self.min, self.value, self.max) 3903101Sstever@eecs.umich.edu 3913101Sstever@eecs.umich.edu def __init__(self, value): 3923101Sstever@eecs.umich.edu if isinstance(value, str): 3933102Sstever@eecs.umich.edu self.value = convert.toInteger(value) 3943714Sstever@eecs.umich.edu elif isinstance(value, (int, long, float, NumericParamValue)): 3953101Sstever@eecs.umich.edu self.value = long(value) 3963714Sstever@eecs.umich.edu else: 3973714Sstever@eecs.umich.edu raise TypeError, "Can't convert object of type %s to CheckedInt" \ 3983714Sstever@eecs.umich.edu % type(value).__name__ 3993101Sstever@eecs.umich.edu self._check() 4003101Sstever@eecs.umich.edu 4017673Snate@binkert.org @classmethod 4027673Snate@binkert.org def cxx_predecls(cls, code): 4037673Snate@binkert.org # most derived types require this, so we just do it here once 4047673Snate@binkert.org code('#include "base/types.hh"') 4057673Snate@binkert.org 4067673Snate@binkert.org @classmethod 4077673Snate@binkert.org def swig_predecls(cls, code): 4087673Snate@binkert.org # most derived types require this, so we just do it here once 4097673Snate@binkert.org code('%import "stdint.i"') 4107673Snate@binkert.org code('%import "base/types.hh"') 4117673Snate@binkert.org 4124762Snate@binkert.org def getValue(self): 4134762Snate@binkert.org return long(self.value) 4144762Snate@binkert.org 4153101Sstever@eecs.umich.educlass Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 4163101Sstever@eecs.umich.educlass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 4173101Sstever@eecs.umich.edu 4183101Sstever@eecs.umich.educlass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 4193101Sstever@eecs.umich.educlass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 4203101Sstever@eecs.umich.educlass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 4213101Sstever@eecs.umich.educlass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 4223101Sstever@eecs.umich.educlass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 4233101Sstever@eecs.umich.educlass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 4243101Sstever@eecs.umich.educlass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 4253101Sstever@eecs.umich.educlass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 4263101Sstever@eecs.umich.edu 4273101Sstever@eecs.umich.educlass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 4283101Sstever@eecs.umich.educlass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 4293101Sstever@eecs.umich.educlass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 4303101Sstever@eecs.umich.educlass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 4313101Sstever@eecs.umich.edu 4323101Sstever@eecs.umich.educlass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 4333101Sstever@eecs.umich.edu 4343101Sstever@eecs.umich.educlass Float(ParamValue, float): 4354446Sbinkertn@umich.edu cxx_type = 'double' 4363101Sstever@eecs.umich.edu 4375468Snate@binkert.org def __init__(self, value): 4385468Snate@binkert.org if isinstance(value, (int, long, float, NumericParamValue, Float)): 4395468Snate@binkert.org self.value = float(value) 4405468Snate@binkert.org else: 4415468Snate@binkert.org raise TypeError, "Can't convert object of type %s to Float" \ 4425468Snate@binkert.org % type(value).__name__ 4435468Snate@binkert.org 4444762Snate@binkert.org def getValue(self): 4454762Snate@binkert.org return float(self.value) 4464762Snate@binkert.org 4473101Sstever@eecs.umich.educlass MemorySize(CheckedInt): 4483101Sstever@eecs.umich.edu cxx_type = 'uint64_t' 4493101Sstever@eecs.umich.edu size = 64 4503101Sstever@eecs.umich.edu unsigned = True 4513101Sstever@eecs.umich.edu def __init__(self, value): 4523101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 4533101Sstever@eecs.umich.edu self.value = value.value 4543101Sstever@eecs.umich.edu else: 4553102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4563101Sstever@eecs.umich.edu self._check() 4573101Sstever@eecs.umich.edu 4583101Sstever@eecs.umich.educlass MemorySize32(CheckedInt): 4594168Sbinkertn@umich.edu cxx_type = 'uint32_t' 4603101Sstever@eecs.umich.edu size = 32 4613101Sstever@eecs.umich.edu unsigned = True 4623101Sstever@eecs.umich.edu def __init__(self, value): 4633101Sstever@eecs.umich.edu if isinstance(value, MemorySize): 4643101Sstever@eecs.umich.edu self.value = value.value 4653101Sstever@eecs.umich.edu else: 4663102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4673101Sstever@eecs.umich.edu self._check() 4683101Sstever@eecs.umich.edu 4693101Sstever@eecs.umich.educlass Addr(CheckedInt): 4703101Sstever@eecs.umich.edu cxx_type = 'Addr' 4713101Sstever@eecs.umich.edu size = 64 4723101Sstever@eecs.umich.edu unsigned = True 4733101Sstever@eecs.umich.edu def __init__(self, value): 4743101Sstever@eecs.umich.edu if isinstance(value, Addr): 4753101Sstever@eecs.umich.edu self.value = value.value 4763101Sstever@eecs.umich.edu else: 4773101Sstever@eecs.umich.edu try: 4783102Sstever@eecs.umich.edu self.value = convert.toMemorySize(value) 4793101Sstever@eecs.umich.edu except TypeError: 4803101Sstever@eecs.umich.edu self.value = long(value) 4813101Sstever@eecs.umich.edu self._check() 4823584Ssaidi@eecs.umich.edu def __add__(self, other): 4833584Ssaidi@eecs.umich.edu if isinstance(other, Addr): 4843584Ssaidi@eecs.umich.edu return self.value + other.value 4853584Ssaidi@eecs.umich.edu else: 4863584Ssaidi@eecs.umich.edu return self.value + other 4873101Sstever@eecs.umich.edu 4883101Sstever@eecs.umich.edu 4895033Smilesck@eecs.umich.educlass MetaRange(MetaParamValue): 4903101Sstever@eecs.umich.edu def __init__(cls, name, bases, dict): 4913101Sstever@eecs.umich.edu super(MetaRange, cls).__init__(name, bases, dict) 4923101Sstever@eecs.umich.edu if name == 'Range': 4933101Sstever@eecs.umich.edu return 4943101Sstever@eecs.umich.edu cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 4953101Sstever@eecs.umich.edu 4963101Sstever@eecs.umich.educlass Range(ParamValue): 4973101Sstever@eecs.umich.edu __metaclass__ = MetaRange 4983101Sstever@eecs.umich.edu type = Int # default; can be overridden in subclasses 4993101Sstever@eecs.umich.edu def __init__(self, *args, **kwargs): 5003101Sstever@eecs.umich.edu def handle_kwargs(self, kwargs): 5013101Sstever@eecs.umich.edu if 'end' in kwargs: 5023101Sstever@eecs.umich.edu self.second = self.type(kwargs.pop('end')) 5033101Sstever@eecs.umich.edu elif 'size' in kwargs: 5043101Sstever@eecs.umich.edu self.second = self.first + self.type(kwargs.pop('size')) - 1 5053101Sstever@eecs.umich.edu else: 5063101Sstever@eecs.umich.edu raise TypeError, "Either end or size must be specified" 5073101Sstever@eecs.umich.edu 5083101Sstever@eecs.umich.edu if len(args) == 0: 5093101Sstever@eecs.umich.edu self.first = self.type(kwargs.pop('start')) 5103101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 5113101Sstever@eecs.umich.edu 5123101Sstever@eecs.umich.edu elif len(args) == 1: 5133101Sstever@eecs.umich.edu if kwargs: 5143101Sstever@eecs.umich.edu self.first = self.type(args[0]) 5153101Sstever@eecs.umich.edu handle_kwargs(self, kwargs) 5163101Sstever@eecs.umich.edu elif isinstance(args[0], Range): 5173101Sstever@eecs.umich.edu self.first = self.type(args[0].first) 5183101Sstever@eecs.umich.edu self.second = self.type(args[0].second) 5195219Ssaidi@eecs.umich.edu elif isinstance(args[0], (list, tuple)): 5205219Ssaidi@eecs.umich.edu self.first = self.type(args[0][0]) 5215219Ssaidi@eecs.umich.edu self.second = self.type(args[0][1]) 5223101Sstever@eecs.umich.edu else: 5233101Sstever@eecs.umich.edu self.first = self.type(0) 5243101Sstever@eecs.umich.edu self.second = self.type(args[0]) - 1 5253101Sstever@eecs.umich.edu 5263101Sstever@eecs.umich.edu elif len(args) == 2: 5273101Sstever@eecs.umich.edu self.first = self.type(args[0]) 5283101Sstever@eecs.umich.edu self.second = self.type(args[1]) 5293101Sstever@eecs.umich.edu else: 5303101Sstever@eecs.umich.edu raise TypeError, "Too many arguments specified" 5313101Sstever@eecs.umich.edu 5323101Sstever@eecs.umich.edu if kwargs: 5333101Sstever@eecs.umich.edu raise TypeError, "too many keywords: %s" % kwargs.keys() 5343101Sstever@eecs.umich.edu 5353101Sstever@eecs.umich.edu def __str__(self): 5363101Sstever@eecs.umich.edu return '%s:%s' % (self.first, self.second) 5373101Sstever@eecs.umich.edu 5387673Snate@binkert.org @classmethod 5397673Snate@binkert.org def cxx_predecls(cls, code): 5407673Snate@binkert.org code('#include "base/range.hh"') 5417673Snate@binkert.org cls.type.cxx_predecls(code) 5427673Snate@binkert.org 5433101Sstever@eecs.umich.educlass AddrRange(Range): 5443101Sstever@eecs.umich.edu type = Addr 5457673Snate@binkert.org 5467673Snate@binkert.org @classmethod 5477673Snate@binkert.org def swig_predecls(cls, code): 5487673Snate@binkert.org code('%include "python/swig/range.i"') 5494762Snate@binkert.org 5504762Snate@binkert.org def getValue(self): 5514762Snate@binkert.org from m5.objects.params import AddrRange 5524762Snate@binkert.org 5534762Snate@binkert.org value = AddrRange() 5544762Snate@binkert.org value.start = long(self.first) 5554762Snate@binkert.org value.end = long(self.second) 5564762Snate@binkert.org return value 5573101Sstever@eecs.umich.edu 5583101Sstever@eecs.umich.educlass TickRange(Range): 5593101Sstever@eecs.umich.edu type = Tick 5607673Snate@binkert.org 5617673Snate@binkert.org @classmethod 5627673Snate@binkert.org def swig_predecls(cls, code): 5637673Snate@binkert.org code('%include "python/swig/range.i"') 5644762Snate@binkert.org 5654762Snate@binkert.org def getValue(self): 5664762Snate@binkert.org from m5.objects.params import TickRange 5674762Snate@binkert.org 5684762Snate@binkert.org value = TickRange() 5694762Snate@binkert.org value.start = long(self.first) 5704762Snate@binkert.org value.end = long(self.second) 5714762Snate@binkert.org return value 5723101Sstever@eecs.umich.edu 5733101Sstever@eecs.umich.edu# Boolean parameter type. Python doesn't let you subclass bool, since 5743101Sstever@eecs.umich.edu# it doesn't want to let you create multiple instances of True and 5753101Sstever@eecs.umich.edu# False. Thus this is a little more complicated than String. 5763101Sstever@eecs.umich.educlass Bool(ParamValue): 5773101Sstever@eecs.umich.edu cxx_type = 'bool' 5783101Sstever@eecs.umich.edu def __init__(self, value): 5793101Sstever@eecs.umich.edu try: 5803102Sstever@eecs.umich.edu self.value = convert.toBool(value) 5813101Sstever@eecs.umich.edu except TypeError: 5823101Sstever@eecs.umich.edu self.value = bool(value) 5833101Sstever@eecs.umich.edu 5844762Snate@binkert.org def getValue(self): 5854762Snate@binkert.org return bool(self.value) 5864762Snate@binkert.org 5873101Sstever@eecs.umich.edu def __str__(self): 5883101Sstever@eecs.umich.edu return str(self.value) 5893101Sstever@eecs.umich.edu 5903101Sstever@eecs.umich.edu def ini_str(self): 5913101Sstever@eecs.umich.edu if self.value: 5923101Sstever@eecs.umich.edu return 'true' 5933101Sstever@eecs.umich.edu return 'false' 5943101Sstever@eecs.umich.edu 5953101Sstever@eecs.umich.edudef IncEthernetAddr(addr, val = 1): 5963101Sstever@eecs.umich.edu bytes = map(lambda x: int(x, 16), addr.split(':')) 5973101Sstever@eecs.umich.edu bytes[5] += val 5983101Sstever@eecs.umich.edu for i in (5, 4, 3, 2, 1): 5993101Sstever@eecs.umich.edu val,rem = divmod(bytes[i], 256) 6003101Sstever@eecs.umich.edu bytes[i] = rem 6013101Sstever@eecs.umich.edu if val == 0: 6023101Sstever@eecs.umich.edu break 6033101Sstever@eecs.umich.edu bytes[i - 1] += val 6043101Sstever@eecs.umich.edu assert(bytes[0] <= 255) 6053101Sstever@eecs.umich.edu return ':'.join(map(lambda x: '%02x' % x, bytes)) 6063101Sstever@eecs.umich.edu 6074380Sbinkertn@umich.edu_NextEthernetAddr = "00:90:00:00:00:01" 6084380Sbinkertn@umich.edudef NextEthernetAddr(): 6094380Sbinkertn@umich.edu global _NextEthernetAddr 6103101Sstever@eecs.umich.edu 6114380Sbinkertn@umich.edu value = _NextEthernetAddr 6124380Sbinkertn@umich.edu _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 6134380Sbinkertn@umich.edu return value 6143101Sstever@eecs.umich.edu 6153101Sstever@eecs.umich.educlass EthernetAddr(ParamValue): 6163101Sstever@eecs.umich.edu cxx_type = 'Net::EthAddr' 6177673Snate@binkert.org 6187673Snate@binkert.org @classmethod 6197673Snate@binkert.org def cxx_predecls(cls, code): 6207673Snate@binkert.org code('#include "base/inet.hh"') 6217673Snate@binkert.org 6227673Snate@binkert.org @classmethod 6237673Snate@binkert.org def swig_predecls(cls, code): 6247673Snate@binkert.org code('%include "python/swig/inet.i"') 6257673Snate@binkert.org 6263101Sstever@eecs.umich.edu def __init__(self, value): 6273101Sstever@eecs.umich.edu if value == NextEthernetAddr: 6283101Sstever@eecs.umich.edu self.value = value 6293101Sstever@eecs.umich.edu return 6303101Sstever@eecs.umich.edu 6313101Sstever@eecs.umich.edu if not isinstance(value, str): 6323101Sstever@eecs.umich.edu raise TypeError, "expected an ethernet address and didn't get one" 6333101Sstever@eecs.umich.edu 6343101Sstever@eecs.umich.edu bytes = value.split(':') 6353101Sstever@eecs.umich.edu if len(bytes) != 6: 6363101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 6373101Sstever@eecs.umich.edu 6383101Sstever@eecs.umich.edu for byte in bytes: 6393101Sstever@eecs.umich.edu if not 0 <= int(byte) <= 256: 6403101Sstever@eecs.umich.edu raise TypeError, 'invalid ethernet address %s' % value 6413101Sstever@eecs.umich.edu 6423101Sstever@eecs.umich.edu self.value = value 6433101Sstever@eecs.umich.edu 6443101Sstever@eecs.umich.edu def unproxy(self, base): 6453101Sstever@eecs.umich.edu if self.value == NextEthernetAddr: 6464380Sbinkertn@umich.edu return EthernetAddr(self.value()) 6473101Sstever@eecs.umich.edu return self 6483101Sstever@eecs.umich.edu 6494762Snate@binkert.org def getValue(self): 6504762Snate@binkert.org from m5.objects.params import EthAddr 6514762Snate@binkert.org return EthAddr(self.value) 6524762Snate@binkert.org 6534380Sbinkertn@umich.edu def ini_str(self): 6544380Sbinkertn@umich.edu return self.value 6553101Sstever@eecs.umich.edu 6563932Sbinkertn@umich.edutime_formats = [ "%a %b %d %H:%M:%S %Z %Y", 6573932Sbinkertn@umich.edu "%a %b %d %H:%M:%S %Z %Y", 6583932Sbinkertn@umich.edu "%Y/%m/%d %H:%M:%S", 6593932Sbinkertn@umich.edu "%Y/%m/%d %H:%M", 6603932Sbinkertn@umich.edu "%Y/%m/%d", 6613932Sbinkertn@umich.edu "%m/%d/%Y %H:%M:%S", 6623932Sbinkertn@umich.edu "%m/%d/%Y %H:%M", 6633932Sbinkertn@umich.edu "%m/%d/%Y", 6643932Sbinkertn@umich.edu "%m/%d/%y %H:%M:%S", 6653932Sbinkertn@umich.edu "%m/%d/%y %H:%M", 6663932Sbinkertn@umich.edu "%m/%d/%y"] 6673932Sbinkertn@umich.edu 6683932Sbinkertn@umich.edu 6693885Sbinkertn@umich.edudef parse_time(value): 6703932Sbinkertn@umich.edu from time import gmtime, strptime, struct_time, time 6713932Sbinkertn@umich.edu from datetime import datetime, date 6723885Sbinkertn@umich.edu 6733932Sbinkertn@umich.edu if isinstance(value, struct_time): 6743932Sbinkertn@umich.edu return value 6753932Sbinkertn@umich.edu 6763932Sbinkertn@umich.edu if isinstance(value, (int, long)): 6773932Sbinkertn@umich.edu return gmtime(value) 6783932Sbinkertn@umich.edu 6793932Sbinkertn@umich.edu if isinstance(value, (datetime, date)): 6803932Sbinkertn@umich.edu return value.timetuple() 6813932Sbinkertn@umich.edu 6823932Sbinkertn@umich.edu if isinstance(value, str): 6833932Sbinkertn@umich.edu if value in ('Now', 'Today'): 6843932Sbinkertn@umich.edu return time.gmtime(time.time()) 6853932Sbinkertn@umich.edu 6863932Sbinkertn@umich.edu for format in time_formats: 6873932Sbinkertn@umich.edu try: 6883932Sbinkertn@umich.edu return strptime(value, format) 6893932Sbinkertn@umich.edu except ValueError: 6903932Sbinkertn@umich.edu pass 6913885Sbinkertn@umich.edu 6923885Sbinkertn@umich.edu raise ValueError, "Could not parse '%s' as a time" % value 6933885Sbinkertn@umich.edu 6943885Sbinkertn@umich.educlass Time(ParamValue): 6954762Snate@binkert.org cxx_type = 'tm' 6967673Snate@binkert.org 6977673Snate@binkert.org @classmethod 6987673Snate@binkert.org def cxx_predecls(cls, code): 6997673Snate@binkert.org code('#include <time.h>') 7007673Snate@binkert.org 7017673Snate@binkert.org @classmethod 7027673Snate@binkert.org def swig_predecls(cls, code): 7037673Snate@binkert.org code('%include "python/swig/time.i"') 7047673Snate@binkert.org 7053885Sbinkertn@umich.edu def __init__(self, value): 7063932Sbinkertn@umich.edu self.value = parse_time(value) 7073885Sbinkertn@umich.edu 7084762Snate@binkert.org def getValue(self): 7094762Snate@binkert.org from m5.objects.params import tm 7104762Snate@binkert.org 7114762Snate@binkert.org c_time = tm() 7124762Snate@binkert.org py_time = self.value 7134762Snate@binkert.org 7144762Snate@binkert.org # UNIX is years since 1900 7154762Snate@binkert.org c_time.tm_year = py_time.tm_year - 1900; 7164762Snate@binkert.org 7174762Snate@binkert.org # Python starts at 1, UNIX starts at 0 7184762Snate@binkert.org c_time.tm_mon = py_time.tm_mon - 1; 7194762Snate@binkert.org c_time.tm_mday = py_time.tm_mday; 7204762Snate@binkert.org c_time.tm_hour = py_time.tm_hour; 7214762Snate@binkert.org c_time.tm_min = py_time.tm_min; 7224762Snate@binkert.org c_time.tm_sec = py_time.tm_sec; 7234762Snate@binkert.org 7244762Snate@binkert.org # Python has 0 as Monday, UNIX is 0 as sunday 7254762Snate@binkert.org c_time.tm_wday = py_time.tm_wday + 1 7264762Snate@binkert.org if c_time.tm_wday > 6: 7274762Snate@binkert.org c_time.tm_wday -= 7; 7284762Snate@binkert.org 7294762Snate@binkert.org # Python starts at 1, Unix starts at 0 7304762Snate@binkert.org c_time.tm_yday = py_time.tm_yday - 1; 7314762Snate@binkert.org 7324762Snate@binkert.org return c_time 7334762Snate@binkert.org 7343885Sbinkertn@umich.edu def __str__(self): 7354762Snate@binkert.org return time.asctime(self.value) 7363885Sbinkertn@umich.edu 7373885Sbinkertn@umich.edu def ini_str(self): 7383932Sbinkertn@umich.edu return str(self) 7393885Sbinkertn@umich.edu 7403101Sstever@eecs.umich.edu# Enumerated types are a little more complex. The user specifies the 7413101Sstever@eecs.umich.edu# type as Enum(foo) where foo is either a list or dictionary of 7423101Sstever@eecs.umich.edu# alternatives (typically strings, but not necessarily so). (In the 7433101Sstever@eecs.umich.edu# long run, the integer value of the parameter will be the list index 7443101Sstever@eecs.umich.edu# or the corresponding dictionary value. For now, since we only check 7453101Sstever@eecs.umich.edu# that the alternative is valid and then spit it into a .ini file, 7463101Sstever@eecs.umich.edu# there's not much point in using the dictionary.) 7473101Sstever@eecs.umich.edu 7483101Sstever@eecs.umich.edu# What Enum() must do is generate a new type encapsulating the 7493101Sstever@eecs.umich.edu# provided list/dictionary so that specific values of the parameter 7503101Sstever@eecs.umich.edu# can be instances of that type. We define two hidden internal 7513101Sstever@eecs.umich.edu# classes (_ListEnum and _DictEnum) to serve as base classes, then 7523101Sstever@eecs.umich.edu# derive the new type from the appropriate base class on the fly. 7533101Sstever@eecs.umich.edu 7544762Snate@binkert.orgallEnums = {} 7553101Sstever@eecs.umich.edu# Metaclass for Enum types 7565033Smilesck@eecs.umich.educlass MetaEnum(MetaParamValue): 7574762Snate@binkert.org def __new__(mcls, name, bases, dict): 7584762Snate@binkert.org assert name not in allEnums 7594762Snate@binkert.org 7604762Snate@binkert.org cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 7614762Snate@binkert.org allEnums[name] = cls 7624762Snate@binkert.org return cls 7634762Snate@binkert.org 7643101Sstever@eecs.umich.edu def __init__(cls, name, bases, init_dict): 7653101Sstever@eecs.umich.edu if init_dict.has_key('map'): 7663101Sstever@eecs.umich.edu if not isinstance(cls.map, dict): 7673101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'map' " \ 7683101Sstever@eecs.umich.edu "must be of type dict" 7693101Sstever@eecs.umich.edu # build list of value strings from map 7703101Sstever@eecs.umich.edu cls.vals = cls.map.keys() 7713101Sstever@eecs.umich.edu cls.vals.sort() 7723101Sstever@eecs.umich.edu elif init_dict.has_key('vals'): 7733101Sstever@eecs.umich.edu if not isinstance(cls.vals, list): 7743101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class attribute 'vals' " \ 7753101Sstever@eecs.umich.edu "must be of type list" 7763101Sstever@eecs.umich.edu # build string->value map from vals sequence 7773101Sstever@eecs.umich.edu cls.map = {} 7783101Sstever@eecs.umich.edu for idx,val in enumerate(cls.vals): 7793101Sstever@eecs.umich.edu cls.map[val] = idx 7803101Sstever@eecs.umich.edu else: 7813101Sstever@eecs.umich.edu raise TypeError, "Enum-derived class must define "\ 7823101Sstever@eecs.umich.edu "attribute 'map' or 'vals'" 7833101Sstever@eecs.umich.edu 7844762Snate@binkert.org cls.cxx_type = 'Enums::%s' % name 7853101Sstever@eecs.umich.edu 7863101Sstever@eecs.umich.edu super(MetaEnum, cls).__init__(name, bases, init_dict) 7873101Sstever@eecs.umich.edu 7883101Sstever@eecs.umich.edu # Generate C++ class declaration for this enum type. 7893101Sstever@eecs.umich.edu # Note that we wrap the enum in a class/struct to act as a namespace, 7903101Sstever@eecs.umich.edu # so that the enum strings can be brief w/o worrying about collisions. 7917673Snate@binkert.org def cxx_decl(cls, code): 7926654Snate@binkert.org name = cls.__name__ 7937673Snate@binkert.org code('''\ 7947673Snate@binkert.org#ifndef __ENUM__${name}__ 7957673Snate@binkert.org#define __ENUM__${name}__ 7967673Snate@binkert.org 7977673Snate@binkert.orgnamespace Enums { 7987673Snate@binkert.org enum $name { 7997673Snate@binkert.org''') 8007673Snate@binkert.org code.indent(2) 8014762Snate@binkert.org for val in cls.vals: 8027673Snate@binkert.org code('$val = ${{cls.map[val]}},') 8037673Snate@binkert.org code('Num_$name = ${{len(cls.vals)}},') 8047673Snate@binkert.org code.dedent(2) 8057673Snate@binkert.org code('''\ 8067673Snate@binkert.org }; 8077673Snate@binkert.orgextern const char *${name}Strings[Num_${name}]; 8087673Snate@binkert.org} 8094762Snate@binkert.org 8107673Snate@binkert.org#endif // __ENUM__${name}__ 8117673Snate@binkert.org''') 8127673Snate@binkert.org 8137673Snate@binkert.org def cxx_def(cls, code): 8146654Snate@binkert.org name = cls.__name__ 8157673Snate@binkert.org code('''\ 8167673Snate@binkert.org#include "enums/${name}.hh" 8177673Snate@binkert.orgnamespace Enums { 8187673Snate@binkert.org const char *${name}Strings[Num_${name}] = 8197673Snate@binkert.org { 8207673Snate@binkert.org''') 8217673Snate@binkert.org code.indent(2) 8224762Snate@binkert.org for val in cls.vals: 8237673Snate@binkert.org code('"$val",') 8247673Snate@binkert.org code.dedent(2) 8257673Snate@binkert.org code(''' 8267673Snate@binkert.org }; 8277673Snate@binkert.org/* namespace Enums */ } 8287673Snate@binkert.org''') 8293101Sstever@eecs.umich.edu 8303101Sstever@eecs.umich.edu# Base class for enum types. 8313101Sstever@eecs.umich.educlass Enum(ParamValue): 8323101Sstever@eecs.umich.edu __metaclass__ = MetaEnum 8333101Sstever@eecs.umich.edu vals = [] 8343101Sstever@eecs.umich.edu 8353101Sstever@eecs.umich.edu def __init__(self, value): 8363101Sstever@eecs.umich.edu if value not in self.map: 8373101Sstever@eecs.umich.edu raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 8383101Sstever@eecs.umich.edu % (value, self.vals) 8393101Sstever@eecs.umich.edu self.value = value 8403101Sstever@eecs.umich.edu 8414762Snate@binkert.org def getValue(self): 8424762Snate@binkert.org return int(self.map[self.value]) 8434762Snate@binkert.org 8443101Sstever@eecs.umich.edu def __str__(self): 8453101Sstever@eecs.umich.edu return self.value 8463101Sstever@eecs.umich.edu 8473101Sstever@eecs.umich.edu# how big does a rounding error need to be before we warn about it? 8483101Sstever@eecs.umich.edufrequency_tolerance = 0.001 # 0.1% 8493101Sstever@eecs.umich.edu 8504167Sbinkertn@umich.educlass TickParamValue(NumericParamValue): 8513101Sstever@eecs.umich.edu cxx_type = 'Tick' 8527673Snate@binkert.org 8537673Snate@binkert.org @classmethod 8547673Snate@binkert.org def cxx_predecls(cls, code): 8557673Snate@binkert.org code('#include "base/types.hh"') 8567673Snate@binkert.org 8577673Snate@binkert.org @classmethod 8587673Snate@binkert.org def swig_predecls(cls, code): 8597673Snate@binkert.org code('%import "stdint.i"') 8607673Snate@binkert.org code('%import "base/types.hh"') 8614167Sbinkertn@umich.edu 8624762Snate@binkert.org def getValue(self): 8634762Snate@binkert.org return long(self.value) 8644762Snate@binkert.org 8654167Sbinkertn@umich.educlass Latency(TickParamValue): 8663101Sstever@eecs.umich.edu def __init__(self, value): 8674167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 8684167Sbinkertn@umich.edu self.ticks = value.ticks 8694167Sbinkertn@umich.edu self.value = value.value 8704167Sbinkertn@umich.edu elif isinstance(value, Frequency): 8714167Sbinkertn@umich.edu self.ticks = value.ticks 8724167Sbinkertn@umich.edu self.value = 1.0 / value.value 8734167Sbinkertn@umich.edu elif value.endswith('t'): 8744167Sbinkertn@umich.edu self.ticks = True 8754167Sbinkertn@umich.edu self.value = int(value[:-1]) 8764167Sbinkertn@umich.edu else: 8774167Sbinkertn@umich.edu self.ticks = False 8784167Sbinkertn@umich.edu self.value = convert.toLatency(value) 8793101Sstever@eecs.umich.edu 8803101Sstever@eecs.umich.edu def __getattr__(self, attr): 8813101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 8823101Sstever@eecs.umich.edu return self 8833101Sstever@eecs.umich.edu if attr == 'frequency': 8843101Sstever@eecs.umich.edu return Frequency(self) 8853101Sstever@eecs.umich.edu raise AttributeError, "Latency object has no attribute '%s'" % attr 8863101Sstever@eecs.umich.edu 8874762Snate@binkert.org def getValue(self): 8884762Snate@binkert.org if self.ticks or self.value == 0: 8894762Snate@binkert.org value = self.value 8904762Snate@binkert.org else: 8914762Snate@binkert.org value = ticks.fromSeconds(self.value) 8924762Snate@binkert.org return long(value) 8934762Snate@binkert.org 8943101Sstever@eecs.umich.edu # convert latency to ticks 8953101Sstever@eecs.umich.edu def ini_str(self): 8964762Snate@binkert.org return '%d' % self.getValue() 8973101Sstever@eecs.umich.edu 8984167Sbinkertn@umich.educlass Frequency(TickParamValue): 8993101Sstever@eecs.umich.edu def __init__(self, value): 9004167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 9014167Sbinkertn@umich.edu if value.value == 0: 9024167Sbinkertn@umich.edu self.value = 0 9034167Sbinkertn@umich.edu else: 9044167Sbinkertn@umich.edu self.value = 1.0 / value.value 9054167Sbinkertn@umich.edu self.ticks = value.ticks 9064167Sbinkertn@umich.edu elif isinstance(value, Frequency): 9074167Sbinkertn@umich.edu self.value = value.value 9084167Sbinkertn@umich.edu self.ticks = value.ticks 9094167Sbinkertn@umich.edu else: 9104167Sbinkertn@umich.edu self.ticks = False 9114167Sbinkertn@umich.edu self.value = convert.toFrequency(value) 9123101Sstever@eecs.umich.edu 9133101Sstever@eecs.umich.edu def __getattr__(self, attr): 9143101Sstever@eecs.umich.edu if attr == 'frequency': 9153101Sstever@eecs.umich.edu return self 9163101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 9173101Sstever@eecs.umich.edu return Latency(self) 9183101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 9193101Sstever@eecs.umich.edu 9204167Sbinkertn@umich.edu # convert latency to ticks 9214762Snate@binkert.org def getValue(self): 9224762Snate@binkert.org if self.ticks or self.value == 0: 9234762Snate@binkert.org value = self.value 9244762Snate@binkert.org else: 9254762Snate@binkert.org value = ticks.fromSeconds(1.0 / self.value) 9264762Snate@binkert.org return long(value) 9274762Snate@binkert.org 9283101Sstever@eecs.umich.edu def ini_str(self): 9294762Snate@binkert.org return '%d' % self.getValue() 9303101Sstever@eecs.umich.edu 9313101Sstever@eecs.umich.edu# A generic frequency and/or Latency value. Value is stored as a latency, 9323101Sstever@eecs.umich.edu# but to avoid ambiguity this object does not support numeric ops (* or /). 9333101Sstever@eecs.umich.edu# An explicit conversion to a Latency or Frequency must be made first. 9343101Sstever@eecs.umich.educlass Clock(ParamValue): 9353101Sstever@eecs.umich.edu cxx_type = 'Tick' 9367673Snate@binkert.org 9377673Snate@binkert.org @classmethod 9387673Snate@binkert.org def cxx_predecls(cls, code): 9397673Snate@binkert.org code('#include "base/types.hh"') 9407673Snate@binkert.org 9417673Snate@binkert.org @classmethod 9427673Snate@binkert.org def swig_predecls(cls, code): 9437673Snate@binkert.org code('%import "stdint.i"') 9447673Snate@binkert.org code('%import "base/types.hh"') 9457673Snate@binkert.org 9463101Sstever@eecs.umich.edu def __init__(self, value): 9474167Sbinkertn@umich.edu if isinstance(value, (Latency, Clock)): 9484167Sbinkertn@umich.edu self.ticks = value.ticks 9494167Sbinkertn@umich.edu self.value = value.value 9504167Sbinkertn@umich.edu elif isinstance(value, Frequency): 9514167Sbinkertn@umich.edu self.ticks = value.ticks 9524167Sbinkertn@umich.edu self.value = 1.0 / value.value 9534167Sbinkertn@umich.edu elif value.endswith('t'): 9544167Sbinkertn@umich.edu self.ticks = True 9554167Sbinkertn@umich.edu self.value = int(value[:-1]) 9564167Sbinkertn@umich.edu else: 9574167Sbinkertn@umich.edu self.ticks = False 9584167Sbinkertn@umich.edu self.value = convert.anyToLatency(value) 9593101Sstever@eecs.umich.edu 9603101Sstever@eecs.umich.edu def __getattr__(self, attr): 9613101Sstever@eecs.umich.edu if attr == 'frequency': 9623101Sstever@eecs.umich.edu return Frequency(self) 9633101Sstever@eecs.umich.edu if attr in ('latency', 'period'): 9643101Sstever@eecs.umich.edu return Latency(self) 9653101Sstever@eecs.umich.edu raise AttributeError, "Frequency object has no attribute '%s'" % attr 9663101Sstever@eecs.umich.edu 9674762Snate@binkert.org def getValue(self): 9684762Snate@binkert.org return self.period.getValue() 9694762Snate@binkert.org 9703101Sstever@eecs.umich.edu def ini_str(self): 9713101Sstever@eecs.umich.edu return self.period.ini_str() 9723101Sstever@eecs.umich.edu 9733101Sstever@eecs.umich.educlass NetworkBandwidth(float,ParamValue): 9743101Sstever@eecs.umich.edu cxx_type = 'float' 9753101Sstever@eecs.umich.edu def __new__(cls, value): 9764167Sbinkertn@umich.edu # convert to bits per second 9774167Sbinkertn@umich.edu val = convert.toNetworkBandwidth(value) 9783101Sstever@eecs.umich.edu return super(cls, NetworkBandwidth).__new__(cls, val) 9793101Sstever@eecs.umich.edu 9803101Sstever@eecs.umich.edu def __str__(self): 9813101Sstever@eecs.umich.edu return str(self.val) 9823101Sstever@eecs.umich.edu 9834762Snate@binkert.org def getValue(self): 9844167Sbinkertn@umich.edu # convert to seconds per byte 9854167Sbinkertn@umich.edu value = 8.0 / float(self) 9864167Sbinkertn@umich.edu # convert to ticks per byte 9874762Snate@binkert.org value = ticks.fromSeconds(value) 9884762Snate@binkert.org return float(value) 9894762Snate@binkert.org 9904762Snate@binkert.org def ini_str(self): 9914762Snate@binkert.org return '%f' % self.getValue() 9923101Sstever@eecs.umich.edu 9933101Sstever@eecs.umich.educlass MemoryBandwidth(float,ParamValue): 9943101Sstever@eecs.umich.edu cxx_type = 'float' 9955469Snate@binkert.org def __new__(cls, value): 9964167Sbinkertn@umich.edu # we want the number of ticks per byte of data 9973102Sstever@eecs.umich.edu val = convert.toMemoryBandwidth(value) 9983101Sstever@eecs.umich.edu return super(cls, MemoryBandwidth).__new__(cls, val) 9993101Sstever@eecs.umich.edu 10003101Sstever@eecs.umich.edu def __str__(self): 10013101Sstever@eecs.umich.edu return str(self.val) 10023101Sstever@eecs.umich.edu 10034762Snate@binkert.org def getValue(self): 10044167Sbinkertn@umich.edu # convert to seconds per byte 10055468Snate@binkert.org value = float(self) 10065468Snate@binkert.org if value: 10075468Snate@binkert.org value = 1.0 / float(self) 10084167Sbinkertn@umich.edu # convert to ticks per byte 10094762Snate@binkert.org value = ticks.fromSeconds(value) 10104762Snate@binkert.org return float(value) 10114762Snate@binkert.org 10124762Snate@binkert.org def ini_str(self): 10134762Snate@binkert.org return '%f' % self.getValue() 10143101Sstever@eecs.umich.edu 10153101Sstever@eecs.umich.edu# 10163101Sstever@eecs.umich.edu# "Constants"... handy aliases for various values. 10173101Sstever@eecs.umich.edu# 10183101Sstever@eecs.umich.edu 10193102Sstever@eecs.umich.edu# Special class for NULL pointers. Note the special check in 10203102Sstever@eecs.umich.edu# make_param_value() above that lets these be assigned where a 10213102Sstever@eecs.umich.edu# SimObject is required. 10223102Sstever@eecs.umich.edu# only one copy of a particular node 10233102Sstever@eecs.umich.educlass NullSimObject(object): 10243102Sstever@eecs.umich.edu __metaclass__ = Singleton 10253102Sstever@eecs.umich.edu 10263102Sstever@eecs.umich.edu def __call__(cls): 10273102Sstever@eecs.umich.edu return cls 10283102Sstever@eecs.umich.edu 10293102Sstever@eecs.umich.edu def _instantiate(self, parent = None, path = ''): 10303102Sstever@eecs.umich.edu pass 10313102Sstever@eecs.umich.edu 10323102Sstever@eecs.umich.edu def ini_str(self): 10333102Sstever@eecs.umich.edu return 'Null' 10343102Sstever@eecs.umich.edu 10353102Sstever@eecs.umich.edu def unproxy(self, base): 10363102Sstever@eecs.umich.edu return self 10373102Sstever@eecs.umich.edu 10383102Sstever@eecs.umich.edu def set_path(self, parent, name): 10393102Sstever@eecs.umich.edu pass 10404762Snate@binkert.org 10413102Sstever@eecs.umich.edu def __str__(self): 10423102Sstever@eecs.umich.edu return 'Null' 10433102Sstever@eecs.umich.edu 10444762Snate@binkert.org def getValue(self): 10454762Snate@binkert.org return None 10464762Snate@binkert.org 10473102Sstever@eecs.umich.edu# The only instance you'll ever need... 10483102Sstever@eecs.umich.eduNULL = NullSimObject() 10493102Sstever@eecs.umich.edu 10503102Sstever@eecs.umich.edudef isNullPointer(value): 10513102Sstever@eecs.umich.edu return isinstance(value, NullSimObject) 10523102Sstever@eecs.umich.edu 10533101Sstever@eecs.umich.edu# Some memory range specifications use this as a default upper bound. 10543101Sstever@eecs.umich.eduMaxAddr = Addr.max 10553101Sstever@eecs.umich.eduMaxTick = Tick.max 10563101Sstever@eecs.umich.eduAllMemory = AddrRange(0, MaxAddr) 10573101Sstever@eecs.umich.edu 10583101Sstever@eecs.umich.edu 10593101Sstever@eecs.umich.edu##################################################################### 10603101Sstever@eecs.umich.edu# 10613101Sstever@eecs.umich.edu# Port objects 10623101Sstever@eecs.umich.edu# 10633101Sstever@eecs.umich.edu# Ports are used to interconnect objects in the memory system. 10643101Sstever@eecs.umich.edu# 10653101Sstever@eecs.umich.edu##################################################################### 10663101Sstever@eecs.umich.edu 10673101Sstever@eecs.umich.edu# Port reference: encapsulates a reference to a particular port on a 10683101Sstever@eecs.umich.edu# particular SimObject. 10693101Sstever@eecs.umich.educlass PortRef(object): 10703105Sstever@eecs.umich.edu def __init__(self, simobj, name): 10713105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 10723101Sstever@eecs.umich.edu self.simobj = simobj 10733101Sstever@eecs.umich.edu self.name = name 10743101Sstever@eecs.umich.edu self.peer = None # not associated with another port yet 10753101Sstever@eecs.umich.edu self.ccConnected = False # C++ port connection done? 10763105Sstever@eecs.umich.edu self.index = -1 # always -1 for non-vector ports 10773101Sstever@eecs.umich.edu 10783103Sstever@eecs.umich.edu def __str__(self): 10793105Sstever@eecs.umich.edu return '%s.%s' % (self.simobj, self.name) 10803103Sstever@eecs.umich.edu 10813105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 10823105Sstever@eecs.umich.edu def ini_str(self): 10833105Sstever@eecs.umich.edu return str(self.peer) 10843105Sstever@eecs.umich.edu 10853105Sstever@eecs.umich.edu def __getattr__(self, attr): 10863105Sstever@eecs.umich.edu if attr == 'peerObj': 10873105Sstever@eecs.umich.edu # shorthand for proxies 10883105Sstever@eecs.umich.edu return self.peer.simobj 10893105Sstever@eecs.umich.edu raise AttributeError, "'%s' object has no attribute '%s'" % \ 10903105Sstever@eecs.umich.edu (self.__class__.__name__, attr) 10913105Sstever@eecs.umich.edu 10923105Sstever@eecs.umich.edu # Full connection is symmetric (both ways). Called via 10933105Sstever@eecs.umich.edu # SimObject.__setattr__ as a result of a port assignment, e.g., 10943109Sstever@eecs.umich.edu # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 10953105Sstever@eecs.umich.edu # e.g., "obj1.portA[3] = obj2.portB". 10963105Sstever@eecs.umich.edu def connect(self, other): 10973105Sstever@eecs.umich.edu if isinstance(other, VectorPortRef): 10983105Sstever@eecs.umich.edu # reference to plain VectorPort is implicit append 10993105Sstever@eecs.umich.edu other = other._get_next() 11003105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 11013105Sstever@eecs.umich.edu print "warning: overwriting port", self, \ 11023105Sstever@eecs.umich.edu "value", self.peer, "with", other 11035578SSteve.Reinhardt@amd.com self.peer.peer = None 11043101Sstever@eecs.umich.edu self.peer = other 11053109Sstever@eecs.umich.edu if proxy.isproxy(other): 11063109Sstever@eecs.umich.edu other.set_param_desc(PortParamDesc()) 11073109Sstever@eecs.umich.edu elif isinstance(other, PortRef): 11083109Sstever@eecs.umich.edu if other.peer is not self: 11093109Sstever@eecs.umich.edu other.connect(self) 11103109Sstever@eecs.umich.edu else: 11113109Sstever@eecs.umich.edu raise TypeError, \ 11123109Sstever@eecs.umich.edu "assigning non-port reference '%s' to port '%s'" \ 11133109Sstever@eecs.umich.edu % (other, self) 11143101Sstever@eecs.umich.edu 11153105Sstever@eecs.umich.edu def clone(self, simobj, memo): 11163105Sstever@eecs.umich.edu if memo.has_key(self): 11173105Sstever@eecs.umich.edu return memo[self] 11183101Sstever@eecs.umich.edu newRef = copy.copy(self) 11193105Sstever@eecs.umich.edu memo[self] = newRef 11203105Sstever@eecs.umich.edu newRef.simobj = simobj 11213101Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 11223105Sstever@eecs.umich.edu if self.peer and not proxy.isproxy(self.peer): 11233179Sstever@eecs.umich.edu peerObj = self.peer.simobj(_memo=memo) 11243105Sstever@eecs.umich.edu newRef.peer = self.peer.clone(peerObj, memo) 11253105Sstever@eecs.umich.edu assert(not isinstance(newRef.peer, VectorPortRef)) 11263101Sstever@eecs.umich.edu return newRef 11273101Sstever@eecs.umich.edu 11283105Sstever@eecs.umich.edu def unproxy(self, simobj): 11293105Sstever@eecs.umich.edu assert(simobj is self.simobj) 11303105Sstever@eecs.umich.edu if proxy.isproxy(self.peer): 11313105Sstever@eecs.umich.edu try: 11323105Sstever@eecs.umich.edu realPeer = self.peer.unproxy(self.simobj) 11333105Sstever@eecs.umich.edu except: 11343105Sstever@eecs.umich.edu print "Error in unproxying port '%s' of %s" % \ 11353105Sstever@eecs.umich.edu (self.name, self.simobj.path()) 11363105Sstever@eecs.umich.edu raise 11373105Sstever@eecs.umich.edu self.connect(realPeer) 11383105Sstever@eecs.umich.edu 11393101Sstever@eecs.umich.edu # Call C++ to create corresponding port connection between C++ objects 11403101Sstever@eecs.umich.edu def ccConnect(self): 11414859Snate@binkert.org from m5.objects.params import connectPorts 11424762Snate@binkert.org 11433101Sstever@eecs.umich.edu if self.ccConnected: # already done this 11443101Sstever@eecs.umich.edu return 11453101Sstever@eecs.umich.edu peer = self.peer 11465578SSteve.Reinhardt@amd.com if not self.peer: # nothing to connect to 11475578SSteve.Reinhardt@amd.com return 11487526Ssteve.reinhardt@amd.com try: 11497526Ssteve.reinhardt@amd.com connectPorts(self.simobj.getCCObject(), self.name, self.index, 11507526Ssteve.reinhardt@amd.com peer.simobj.getCCObject(), peer.name, peer.index) 11517526Ssteve.reinhardt@amd.com except: 11527526Ssteve.reinhardt@amd.com print "Error connecting port %s.%s to %s.%s" % \ 11537526Ssteve.reinhardt@amd.com (self.simobj.path(), self.name, 11547526Ssteve.reinhardt@amd.com peer.simobj.path(), peer.name) 11557526Ssteve.reinhardt@amd.com raise 11563101Sstever@eecs.umich.edu self.ccConnected = True 11573101Sstever@eecs.umich.edu peer.ccConnected = True 11583101Sstever@eecs.umich.edu 11593105Sstever@eecs.umich.edu# A reference to an individual element of a VectorPort... much like a 11603105Sstever@eecs.umich.edu# PortRef, but has an index. 11613105Sstever@eecs.umich.educlass VectorPortElementRef(PortRef): 11623105Sstever@eecs.umich.edu def __init__(self, simobj, name, index): 11633105Sstever@eecs.umich.edu PortRef.__init__(self, simobj, name) 11643105Sstever@eecs.umich.edu self.index = index 11653105Sstever@eecs.umich.edu 11663105Sstever@eecs.umich.edu def __str__(self): 11673105Sstever@eecs.umich.edu return '%s.%s[%d]' % (self.simobj, self.name, self.index) 11683105Sstever@eecs.umich.edu 11693105Sstever@eecs.umich.edu# A reference to a complete vector-valued port (not just a single element). 11703105Sstever@eecs.umich.edu# Can be indexed to retrieve individual VectorPortElementRef instances. 11713105Sstever@eecs.umich.educlass VectorPortRef(object): 11723105Sstever@eecs.umich.edu def __init__(self, simobj, name): 11733105Sstever@eecs.umich.edu assert(isSimObject(simobj) or isSimObjectClass(simobj)) 11743105Sstever@eecs.umich.edu self.simobj = simobj 11753105Sstever@eecs.umich.edu self.name = name 11763105Sstever@eecs.umich.edu self.elements = [] 11773105Sstever@eecs.umich.edu 11783109Sstever@eecs.umich.edu def __str__(self): 11793109Sstever@eecs.umich.edu return '%s.%s[:]' % (self.simobj, self.name) 11803109Sstever@eecs.umich.edu 11813105Sstever@eecs.umich.edu # for config.ini, print peer's name (not ours) 11823105Sstever@eecs.umich.edu def ini_str(self): 11833105Sstever@eecs.umich.edu return ' '.join([el.ini_str() for el in self.elements]) 11843105Sstever@eecs.umich.edu 11853105Sstever@eecs.umich.edu def __getitem__(self, key): 11863105Sstever@eecs.umich.edu if not isinstance(key, int): 11873105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 11883105Sstever@eecs.umich.edu if key >= len(self.elements): 11893105Sstever@eecs.umich.edu # need to extend list 11903105Sstever@eecs.umich.edu ext = [VectorPortElementRef(self.simobj, self.name, i) 11913105Sstever@eecs.umich.edu for i in range(len(self.elements), key+1)] 11923105Sstever@eecs.umich.edu self.elements.extend(ext) 11933105Sstever@eecs.umich.edu return self.elements[key] 11943105Sstever@eecs.umich.edu 11953105Sstever@eecs.umich.edu def _get_next(self): 11963105Sstever@eecs.umich.edu return self[len(self.elements)] 11973105Sstever@eecs.umich.edu 11983105Sstever@eecs.umich.edu def __setitem__(self, key, value): 11993105Sstever@eecs.umich.edu if not isinstance(key, int): 12003105Sstever@eecs.umich.edu raise TypeError, "VectorPort index must be integer" 12013105Sstever@eecs.umich.edu self[key].connect(value) 12023105Sstever@eecs.umich.edu 12033105Sstever@eecs.umich.edu def connect(self, other): 12043109Sstever@eecs.umich.edu if isinstance(other, (list, tuple)): 12053109Sstever@eecs.umich.edu # Assign list of port refs to vector port. 12063109Sstever@eecs.umich.edu # For now, append them... not sure if that's the right semantics 12073109Sstever@eecs.umich.edu # or if it should replace the current vector. 12083109Sstever@eecs.umich.edu for ref in other: 12093109Sstever@eecs.umich.edu self._get_next().connect(ref) 12103109Sstever@eecs.umich.edu else: 12113109Sstever@eecs.umich.edu # scalar assignment to plain VectorPort is implicit append 12123109Sstever@eecs.umich.edu self._get_next().connect(other) 12133109Sstever@eecs.umich.edu 12143109Sstever@eecs.umich.edu def clone(self, simobj, memo): 12153109Sstever@eecs.umich.edu if memo.has_key(self): 12163109Sstever@eecs.umich.edu return memo[self] 12173109Sstever@eecs.umich.edu newRef = copy.copy(self) 12183109Sstever@eecs.umich.edu memo[self] = newRef 12193109Sstever@eecs.umich.edu newRef.simobj = simobj 12203109Sstever@eecs.umich.edu assert(isSimObject(newRef.simobj)) 12213109Sstever@eecs.umich.edu newRef.elements = [el.clone(simobj, memo) for el in self.elements] 12223109Sstever@eecs.umich.edu return newRef 12233105Sstever@eecs.umich.edu 12243105Sstever@eecs.umich.edu def unproxy(self, simobj): 12253105Sstever@eecs.umich.edu [el.unproxy(simobj) for el in self.elements] 12263105Sstever@eecs.umich.edu 12273105Sstever@eecs.umich.edu def ccConnect(self): 12283105Sstever@eecs.umich.edu [el.ccConnect() for el in self.elements] 12293105Sstever@eecs.umich.edu 12303101Sstever@eecs.umich.edu# Port description object. Like a ParamDesc object, this represents a 12313101Sstever@eecs.umich.edu# logical port in the SimObject class, not a particular port on a 12323101Sstever@eecs.umich.edu# SimObject instance. The latter are represented by PortRef objects. 12333101Sstever@eecs.umich.educlass Port(object): 12343105Sstever@eecs.umich.edu # Port("description") or Port(default, "description") 12353105Sstever@eecs.umich.edu def __init__(self, *args): 12363105Sstever@eecs.umich.edu if len(args) == 1: 12373105Sstever@eecs.umich.edu self.desc = args[0] 12383105Sstever@eecs.umich.edu elif len(args) == 2: 12393105Sstever@eecs.umich.edu self.default = args[0] 12403105Sstever@eecs.umich.edu self.desc = args[1] 12413105Sstever@eecs.umich.edu else: 12423105Sstever@eecs.umich.edu raise TypeError, 'wrong number of arguments' 12433105Sstever@eecs.umich.edu # self.name is set by SimObject class on assignment 12443105Sstever@eecs.umich.edu # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 12453101Sstever@eecs.umich.edu 12463101Sstever@eecs.umich.edu # Generate a PortRef for this port on the given SimObject with the 12473101Sstever@eecs.umich.edu # given name 12483105Sstever@eecs.umich.edu def makeRef(self, simobj): 12493105Sstever@eecs.umich.edu return PortRef(simobj, self.name) 12503101Sstever@eecs.umich.edu 12513101Sstever@eecs.umich.edu # Connect an instance of this port (on the given SimObject with 12523101Sstever@eecs.umich.edu # the given name) with the port described by the supplied PortRef 12533105Sstever@eecs.umich.edu def connect(self, simobj, ref): 12543105Sstever@eecs.umich.edu self.makeRef(simobj).connect(ref) 12553101Sstever@eecs.umich.edu 12563101Sstever@eecs.umich.edu# VectorPort description object. Like Port, but represents a vector 12573101Sstever@eecs.umich.edu# of connections (e.g., as on a Bus). 12583101Sstever@eecs.umich.educlass VectorPort(Port): 12593105Sstever@eecs.umich.edu def __init__(self, *args): 12603105Sstever@eecs.umich.edu Port.__init__(self, *args) 12613101Sstever@eecs.umich.edu self.isVec = True 12623101Sstever@eecs.umich.edu 12633105Sstever@eecs.umich.edu def makeRef(self, simobj): 12643105Sstever@eecs.umich.edu return VectorPortRef(simobj, self.name) 12653105Sstever@eecs.umich.edu 12663109Sstever@eecs.umich.edu# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 12673109Sstever@eecs.umich.edu# proxy objects (via set_param_desc()) so that proxy error messages 12683109Sstever@eecs.umich.edu# make sense. 12693109Sstever@eecs.umich.educlass PortParamDesc(object): 12703109Sstever@eecs.umich.edu __metaclass__ = Singleton 12713109Sstever@eecs.umich.edu 12723109Sstever@eecs.umich.edu ptype_str = 'Port' 12733109Sstever@eecs.umich.edu ptype = Port 12743105Sstever@eecs.umich.edu 12756654Snate@binkert.orgbaseEnums = allEnums.copy() 12766654Snate@binkert.orgbaseParams = allParams.copy() 12776654Snate@binkert.org 12786654Snate@binkert.orgdef clear(): 12796654Snate@binkert.org global allEnums, allParams 12806654Snate@binkert.org 12816654Snate@binkert.org allEnums = baseEnums.copy() 12826654Snate@binkert.org allParams = baseParams.copy() 12836654Snate@binkert.org 12843101Sstever@eecs.umich.edu__all__ = ['Param', 'VectorParam', 12853101Sstever@eecs.umich.edu 'Enum', 'Bool', 'String', 'Float', 12863101Sstever@eecs.umich.edu 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 12873101Sstever@eecs.umich.edu 'Int32', 'UInt32', 'Int64', 'UInt64', 12883101Sstever@eecs.umich.edu 'Counter', 'Addr', 'Tick', 'Percent', 12893101Sstever@eecs.umich.edu 'TcpPort', 'UdpPort', 'EthernetAddr', 12903101Sstever@eecs.umich.edu 'MemorySize', 'MemorySize32', 12914167Sbinkertn@umich.edu 'Latency', 'Frequency', 'Clock', 12923101Sstever@eecs.umich.edu 'NetworkBandwidth', 'MemoryBandwidth', 12933101Sstever@eecs.umich.edu 'Range', 'AddrRange', 'TickRange', 12943101Sstever@eecs.umich.edu 'MaxAddr', 'MaxTick', 'AllMemory', 12953885Sbinkertn@umich.edu 'Time', 12963102Sstever@eecs.umich.edu 'NextEthernetAddr', 'NULL', 12973101Sstever@eecs.umich.edu 'Port', 'VectorPort'] 12986654Snate@binkert.org 12996654Snate@binkert.orgimport SimObject 1300