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