1# Copyright (c) 2004-2006 The Regents of The University of Michigan 2# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# Authors: Steve Reinhardt 29# Nathan Binkert 30# Gabe Black 31 32##################################################################### 33# 34# Parameter description classes 35# 36# The _params dictionary in each class maps parameter names to either 37# a Param or a VectorParam object. These objects contain the 38# parameter description string, the parameter type, and the default 39# value (if any). The convert() method on these objects is used to 40# force whatever value is assigned to the parameter to the appropriate 41# type. 42# 43# Note that the default values are loaded into the class's attribute 44# space when the parameter dictionary is initialized (in 45# MetaSimObject._new_param()); after that point they aren't used. 46# 47##################################################################### 48 49import copy 50import datetime 51import re 52import sys 53import time 54import math 55 56import proxy 57import ticks 58from util import * 59 60def isSimObject(*args, **kwargs): 61 return SimObject.isSimObject(*args, **kwargs) 62 63def isSimObjectSequence(*args, **kwargs): 64 return SimObject.isSimObjectSequence(*args, **kwargs) 65 66def isSimObjectClass(*args, **kwargs): 67 return SimObject.isSimObjectClass(*args, **kwargs) 68 69allParams = {} 70 71class MetaParamValue(type): 72 def __new__(mcls, name, bases, dct): 73 cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 74 assert name not in allParams 75 allParams[name] = cls 76 return cls 77 78 79# Dummy base class to identify types that are legitimate for SimObject 80# parameters. 81class ParamValue(object): 82 __metaclass__ = MetaParamValue 83
| 1# Copyright (c) 2004-2006 The Regents of The University of Michigan 2# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; 9# redistributions in binary form must reproduce the above copyright 10# notice, this list of conditions and the following disclaimer in the 11# documentation and/or other materials provided with the distribution; 12# neither the name of the copyright holders nor the names of its 13# contributors may be used to endorse or promote products derived from 14# this software without specific prior written permission. 15# 16# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# Authors: Steve Reinhardt 29# Nathan Binkert 30# Gabe Black 31 32##################################################################### 33# 34# Parameter description classes 35# 36# The _params dictionary in each class maps parameter names to either 37# a Param or a VectorParam object. These objects contain the 38# parameter description string, the parameter type, and the default 39# value (if any). The convert() method on these objects is used to 40# force whatever value is assigned to the parameter to the appropriate 41# type. 42# 43# Note that the default values are loaded into the class's attribute 44# space when the parameter dictionary is initialized (in 45# MetaSimObject._new_param()); after that point they aren't used. 46# 47##################################################################### 48 49import copy 50import datetime 51import re 52import sys 53import time 54import math 55 56import proxy 57import ticks 58from util import * 59 60def isSimObject(*args, **kwargs): 61 return SimObject.isSimObject(*args, **kwargs) 62 63def isSimObjectSequence(*args, **kwargs): 64 return SimObject.isSimObjectSequence(*args, **kwargs) 65 66def isSimObjectClass(*args, **kwargs): 67 return SimObject.isSimObjectClass(*args, **kwargs) 68 69allParams = {} 70 71class MetaParamValue(type): 72 def __new__(mcls, name, bases, dct): 73 cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 74 assert name not in allParams 75 allParams[name] = cls 76 return cls 77 78 79# Dummy base class to identify types that are legitimate for SimObject 80# parameters. 81class ParamValue(object): 82 __metaclass__ = MetaParamValue 83
|
| 84 85 # Generate the code needed as a prerequisite for declaring a C++ 86 # object of this type. Typically generates one or more #include 87 # statements. Used when declaring parameters of this type.
|
84 @classmethod 85 def cxx_predecls(cls, code): 86 pass 87
| 88 @classmethod 89 def cxx_predecls(cls, code): 90 pass 91
|
| 92 # Generate the code needed as a prerequisite for including a 93 # reference to a C++ object of this type in a SWIG .i file. 94 # Typically generates one or more %import or %include statements.
|
88 @classmethod 89 def swig_predecls(cls, code): 90 pass 91 92 # default for printing to .ini file is regular string conversion. 93 # will be overridden in some cases 94 def ini_str(self): 95 return str(self) 96 97 # allows us to blithely call unproxy() on things without checking 98 # if they're really proxies or not 99 def unproxy(self, base): 100 return self 101 102# Regular parameter description. 103class ParamDesc(object):
| 95 @classmethod 96 def swig_predecls(cls, code): 97 pass 98 99 # default for printing to .ini file is regular string conversion. 100 # will be overridden in some cases 101 def ini_str(self): 102 return str(self) 103 104 # allows us to blithely call unproxy() on things without checking 105 # if they're really proxies or not 106 def unproxy(self, base): 107 return self 108 109# Regular parameter description. 110class ParamDesc(object):
|
104 file_ext = 'ptype' 105
| |
106 def __init__(self, ptype_str, ptype, *args, **kwargs): 107 self.ptype_str = ptype_str 108 # remember ptype only if it is provided 109 if ptype != None: 110 self.ptype = ptype 111 112 if args: 113 if len(args) == 1: 114 self.desc = args[0] 115 elif len(args) == 2: 116 self.default = args[0] 117 self.desc = args[1] 118 else: 119 raise TypeError, 'too many arguments' 120 121 if kwargs.has_key('desc'): 122 assert(not hasattr(self, 'desc')) 123 self.desc = kwargs['desc'] 124 del kwargs['desc'] 125 126 if kwargs.has_key('default'): 127 assert(not hasattr(self, 'default')) 128 self.default = kwargs['default'] 129 del kwargs['default'] 130 131 if kwargs: 132 raise TypeError, 'extra unknown kwargs %s' % kwargs 133 134 if not hasattr(self, 'desc'): 135 raise TypeError, 'desc attribute missing' 136 137 def __getattr__(self, attr): 138 if attr == 'ptype': 139 ptype = SimObject.allClasses[self.ptype_str] 140 assert isSimObjectClass(ptype) 141 self.ptype = ptype 142 return ptype 143 144 raise AttributeError, "'%s' object has no attribute '%s'" % \ 145 (type(self).__name__, attr) 146 147 def convert(self, value): 148 if isinstance(value, proxy.BaseProxy): 149 value.set_param_desc(self) 150 return value 151 if not hasattr(self, 'ptype') and isNullPointer(value): 152 # deferred evaluation of SimObject; continue to defer if 153 # we're just assigning a null pointer 154 return value 155 if isinstance(value, self.ptype): 156 return value 157 if isNullPointer(value) and isSimObjectClass(self.ptype): 158 return value 159 return self.ptype(value) 160 161 def cxx_predecls(self, code): 162 self.ptype.cxx_predecls(code) 163 164 def swig_predecls(self, code): 165 self.ptype.swig_predecls(code) 166 167 def cxx_decl(self, code): 168 code('${{self.ptype.cxx_type}} ${{self.name}};') 169 170# Vector-valued parameter description. Just like ParamDesc, except 171# that the value is a vector (list) of the specified type instead of a 172# single value. 173 174class VectorParamValue(list): 175 __metaclass__ = MetaParamValue 176 def __setattr__(self, attr, value): 177 raise AttributeError, \ 178 "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 179 180 def ini_str(self): 181 return ' '.join([v.ini_str() for v in self]) 182 183 def getValue(self): 184 return [ v.getValue() for v in self ] 185 186 def unproxy(self, base): 187 if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 188 return self[0].unproxy(base) 189 else: 190 return [v.unproxy(base) for v in self] 191 192class SimObjectVector(VectorParamValue): 193 # support clone operation 194 def __call__(self, **kwargs): 195 return SimObjectVector([v(**kwargs) for v in self]) 196 197 def clear_parent(self, old_parent): 198 for v in self: 199 v.clear_parent(old_parent) 200 201 def set_parent(self, parent, name): 202 if len(self) == 1: 203 self[0].set_parent(parent, name) 204 else: 205 width = int(math.ceil(math.log(len(self))/math.log(10))) 206 for i,v in enumerate(self): 207 v.set_parent(parent, "%s%0*d" % (name, width, i)) 208 209 def has_parent(self): 210 return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 211 212 # return 'cpu0 cpu1' etc. for print_ini() 213 def get_name(self): 214 return ' '.join([v._name for v in self]) 215 216 # By iterating through the constituent members of the vector here 217 # we can nicely handle iterating over all a SimObject's children 218 # without having to provide lots of special functions on 219 # SimObjectVector directly. 220 def descendants(self): 221 for v in self: 222 for obj in v.descendants(): 223 yield obj 224 225class VectorParamDesc(ParamDesc):
| 111 def __init__(self, ptype_str, ptype, *args, **kwargs): 112 self.ptype_str = ptype_str 113 # remember ptype only if it is provided 114 if ptype != None: 115 self.ptype = ptype 116 117 if args: 118 if len(args) == 1: 119 self.desc = args[0] 120 elif len(args) == 2: 121 self.default = args[0] 122 self.desc = args[1] 123 else: 124 raise TypeError, 'too many arguments' 125 126 if kwargs.has_key('desc'): 127 assert(not hasattr(self, 'desc')) 128 self.desc = kwargs['desc'] 129 del kwargs['desc'] 130 131 if kwargs.has_key('default'): 132 assert(not hasattr(self, 'default')) 133 self.default = kwargs['default'] 134 del kwargs['default'] 135 136 if kwargs: 137 raise TypeError, 'extra unknown kwargs %s' % kwargs 138 139 if not hasattr(self, 'desc'): 140 raise TypeError, 'desc attribute missing' 141 142 def __getattr__(self, attr): 143 if attr == 'ptype': 144 ptype = SimObject.allClasses[self.ptype_str] 145 assert isSimObjectClass(ptype) 146 self.ptype = ptype 147 return ptype 148 149 raise AttributeError, "'%s' object has no attribute '%s'" % \ 150 (type(self).__name__, attr) 151 152 def convert(self, value): 153 if isinstance(value, proxy.BaseProxy): 154 value.set_param_desc(self) 155 return value 156 if not hasattr(self, 'ptype') and isNullPointer(value): 157 # deferred evaluation of SimObject; continue to defer if 158 # we're just assigning a null pointer 159 return value 160 if isinstance(value, self.ptype): 161 return value 162 if isNullPointer(value) and isSimObjectClass(self.ptype): 163 return value 164 return self.ptype(value) 165 166 def cxx_predecls(self, code): 167 self.ptype.cxx_predecls(code) 168 169 def swig_predecls(self, code): 170 self.ptype.swig_predecls(code) 171 172 def cxx_decl(self, code): 173 code('${{self.ptype.cxx_type}} ${{self.name}};') 174 175# Vector-valued parameter description. Just like ParamDesc, except 176# that the value is a vector (list) of the specified type instead of a 177# single value. 178 179class VectorParamValue(list): 180 __metaclass__ = MetaParamValue 181 def __setattr__(self, attr, value): 182 raise AttributeError, \ 183 "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 184 185 def ini_str(self): 186 return ' '.join([v.ini_str() for v in self]) 187 188 def getValue(self): 189 return [ v.getValue() for v in self ] 190 191 def unproxy(self, base): 192 if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 193 return self[0].unproxy(base) 194 else: 195 return [v.unproxy(base) for v in self] 196 197class SimObjectVector(VectorParamValue): 198 # support clone operation 199 def __call__(self, **kwargs): 200 return SimObjectVector([v(**kwargs) for v in self]) 201 202 def clear_parent(self, old_parent): 203 for v in self: 204 v.clear_parent(old_parent) 205 206 def set_parent(self, parent, name): 207 if len(self) == 1: 208 self[0].set_parent(parent, name) 209 else: 210 width = int(math.ceil(math.log(len(self))/math.log(10))) 211 for i,v in enumerate(self): 212 v.set_parent(parent, "%s%0*d" % (name, width, i)) 213 214 def has_parent(self): 215 return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 216 217 # return 'cpu0 cpu1' etc. for print_ini() 218 def get_name(self): 219 return ' '.join([v._name for v in self]) 220 221 # By iterating through the constituent members of the vector here 222 # we can nicely handle iterating over all a SimObject's children 223 # without having to provide lots of special functions on 224 # SimObjectVector directly. 225 def descendants(self): 226 for v in self: 227 for obj in v.descendants(): 228 yield obj 229 230class VectorParamDesc(ParamDesc):
|
226 file_ext = 'vptype' 227
| |
228 # Convert assigned value to appropriate type. If the RHS is not a 229 # list or tuple, it generates a single-element list. 230 def convert(self, value): 231 if isinstance(value, (list, tuple)): 232 # list: coerce each element into new list 233 tmp_list = [ ParamDesc.convert(self, v) for v in value ] 234 else: 235 # singleton: coerce to a single-element list 236 tmp_list = [ ParamDesc.convert(self, value) ] 237 238 if isSimObjectSequence(tmp_list): 239 return SimObjectVector(tmp_list) 240 else: 241 return VectorParamValue(tmp_list) 242
| 231 # Convert assigned value to appropriate type. If the RHS is not a 232 # list or tuple, it generates a single-element list. 233 def convert(self, value): 234 if isinstance(value, (list, tuple)): 235 # list: coerce each element into new list 236 tmp_list = [ ParamDesc.convert(self, v) for v in value ] 237 else: 238 # singleton: coerce to a single-element list 239 tmp_list = [ ParamDesc.convert(self, value) ] 240 241 if isSimObjectSequence(tmp_list): 242 return SimObjectVector(tmp_list) 243 else: 244 return VectorParamValue(tmp_list) 245
|
| 246 def swig_module_name(self): 247 return "%s_vector" % self.ptype_str 248
|
243 def swig_predecls(self, code):
| 249 def swig_predecls(self, code):
|
244 code('%import "vptype_${{self.ptype_str}}.i"')
| 250 code('%import "${{self.swig_module_name()}}.i"')
|
245 246 def swig_decl(self, code):
| 251 252 def swig_decl(self, code):
|
| 253 code('%module(package="m5.internal") ${{self.swig_module_name()}}')
|
247 code('%{') 248 self.ptype.cxx_predecls(code) 249 code('%}') 250 code() 251 self.ptype.swig_predecls(code) 252 code() 253 code('%include "std_vector.i"') 254 code() 255 256 ptype = self.ptype_str 257 cxx_type = self.ptype.cxx_type 258 259 code('''\ 260%typemap(in) std::vector< $cxx_type >::value_type { 261 if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) { 262 if (SWIG_ConvertPtr($$input, (void **)&$$1, 263 $$descriptor($cxx_type), 0) == -1) { 264 return NULL; 265 } 266 } 267} 268 269%typemap(in) std::vector< $cxx_type >::value_type * { 270 if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) { 271 if (SWIG_ConvertPtr($$input, (void **)&$$1, 272 $$descriptor($cxx_type *), 0) == -1) { 273 return NULL; 274 } 275 } 276} 277''') 278 279 code('%template(vector_$ptype) std::vector< $cxx_type >;') 280 281 def cxx_predecls(self, code): 282 code('#include <vector>') 283 self.ptype.cxx_predecls(code) 284 285 def cxx_decl(self, code): 286 code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 287 288class ParamFactory(object): 289 def __init__(self, param_desc_class, ptype_str = None): 290 self.param_desc_class = param_desc_class 291 self.ptype_str = ptype_str 292 293 def __getattr__(self, attr): 294 if self.ptype_str: 295 attr = self.ptype_str + '.' + attr 296 return ParamFactory(self.param_desc_class, attr) 297 298 # E.g., Param.Int(5, "number of widgets") 299 def __call__(self, *args, **kwargs): 300 ptype = None 301 try: 302 ptype = allParams[self.ptype_str] 303 except KeyError: 304 # if name isn't defined yet, assume it's a SimObject, and 305 # try to resolve it later 306 pass 307 return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 308 309Param = ParamFactory(ParamDesc) 310VectorParam = ParamFactory(VectorParamDesc) 311 312##################################################################### 313# 314# Parameter Types 315# 316# Though native Python types could be used to specify parameter types 317# (the 'ptype' field of the Param and VectorParam classes), it's more 318# flexible to define our own set of types. This gives us more control 319# over how Python expressions are converted to values (via the 320# __init__() constructor) and how these values are printed out (via 321# the __str__() conversion method). 322# 323##################################################################### 324 325# String-valued parameter. Just mixin the ParamValue class with the 326# built-in str class. 327class String(ParamValue,str): 328 cxx_type = 'std::string' 329 330 @classmethod 331 def cxx_predecls(self, code): 332 code('#include <string>') 333 334 @classmethod 335 def swig_predecls(cls, code): 336 code('%include "std_string.i"') 337 338 def getValue(self): 339 return self 340 341# superclass for "numeric" parameter values, to emulate math 342# operations in a type-safe way. e.g., a Latency times an int returns 343# a new Latency object. 344class NumericParamValue(ParamValue): 345 def __str__(self): 346 return str(self.value) 347 348 def __float__(self): 349 return float(self.value) 350 351 def __long__(self): 352 return long(self.value) 353 354 def __int__(self): 355 return int(self.value) 356 357 # hook for bounds checking 358 def _check(self): 359 return 360 361 def __mul__(self, other): 362 newobj = self.__class__(self) 363 newobj.value *= other 364 newobj._check() 365 return newobj 366 367 __rmul__ = __mul__ 368 369 def __div__(self, other): 370 newobj = self.__class__(self) 371 newobj.value /= other 372 newobj._check() 373 return newobj 374 375 def __sub__(self, other): 376 newobj = self.__class__(self) 377 newobj.value -= other 378 newobj._check() 379 return newobj 380 381# Metaclass for bounds-checked integer parameters. See CheckedInt. 382class CheckedIntType(MetaParamValue): 383 def __init__(cls, name, bases, dict): 384 super(CheckedIntType, cls).__init__(name, bases, dict) 385 386 # CheckedInt is an abstract base class, so we actually don't 387 # want to do any processing on it... the rest of this code is 388 # just for classes that derive from CheckedInt. 389 if name == 'CheckedInt': 390 return 391 392 if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 393 if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 394 panic("CheckedInt subclass %s must define either\n" \ 395 " 'min' and 'max' or 'size' and 'unsigned'\n", 396 name); 397 if cls.unsigned: 398 cls.min = 0 399 cls.max = 2 ** cls.size - 1 400 else: 401 cls.min = -(2 ** (cls.size - 1)) 402 cls.max = (2 ** (cls.size - 1)) - 1 403 404# Abstract superclass for bounds-checked integer parameters. This 405# class is subclassed to generate parameter classes with specific 406# bounds. Initialization of the min and max bounds is done in the 407# metaclass CheckedIntType.__init__. 408class CheckedInt(NumericParamValue): 409 __metaclass__ = CheckedIntType 410 411 def _check(self): 412 if not self.min <= self.value <= self.max: 413 raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 414 (self.min, self.value, self.max) 415 416 def __init__(self, value): 417 if isinstance(value, str): 418 self.value = convert.toInteger(value) 419 elif isinstance(value, (int, long, float, NumericParamValue)): 420 self.value = long(value) 421 else: 422 raise TypeError, "Can't convert object of type %s to CheckedInt" \ 423 % type(value).__name__ 424 self._check() 425 426 @classmethod 427 def cxx_predecls(cls, code): 428 # most derived types require this, so we just do it here once 429 code('#include "base/types.hh"') 430 431 @classmethod 432 def swig_predecls(cls, code): 433 # most derived types require this, so we just do it here once 434 code('%import "stdint.i"') 435 code('%import "base/types.hh"') 436 437 def getValue(self): 438 return long(self.value) 439 440class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 441class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 442 443class Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 444class UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 445class Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 446class UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 447class Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 448class UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 449class Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 450class UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 451 452class Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 453class Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 454class TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 455class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 456 457class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 458 459class Float(ParamValue, float): 460 cxx_type = 'double' 461 462 def __init__(self, value): 463 if isinstance(value, (int, long, float, NumericParamValue, Float)): 464 self.value = float(value) 465 else: 466 raise TypeError, "Can't convert object of type %s to Float" \ 467 % type(value).__name__ 468 469 def getValue(self): 470 return float(self.value) 471 472class MemorySize(CheckedInt): 473 cxx_type = 'uint64_t' 474 size = 64 475 unsigned = True 476 def __init__(self, value): 477 if isinstance(value, MemorySize): 478 self.value = value.value 479 else: 480 self.value = convert.toMemorySize(value) 481 self._check() 482 483class MemorySize32(CheckedInt): 484 cxx_type = 'uint32_t' 485 size = 32 486 unsigned = True 487 def __init__(self, value): 488 if isinstance(value, MemorySize): 489 self.value = value.value 490 else: 491 self.value = convert.toMemorySize(value) 492 self._check() 493 494class Addr(CheckedInt): 495 cxx_type = 'Addr' 496 size = 64 497 unsigned = True 498 def __init__(self, value): 499 if isinstance(value, Addr): 500 self.value = value.value 501 else: 502 try: 503 self.value = convert.toMemorySize(value) 504 except TypeError: 505 self.value = long(value) 506 self._check() 507 def __add__(self, other): 508 if isinstance(other, Addr): 509 return self.value + other.value 510 else: 511 return self.value + other 512 513 514class MetaRange(MetaParamValue): 515 def __init__(cls, name, bases, dict): 516 super(MetaRange, cls).__init__(name, bases, dict) 517 if name == 'Range': 518 return 519 cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 520 521class Range(ParamValue): 522 __metaclass__ = MetaRange 523 type = Int # default; can be overridden in subclasses 524 def __init__(self, *args, **kwargs): 525 def handle_kwargs(self, kwargs): 526 if 'end' in kwargs: 527 self.second = self.type(kwargs.pop('end')) 528 elif 'size' in kwargs: 529 self.second = self.first + self.type(kwargs.pop('size')) - 1 530 else: 531 raise TypeError, "Either end or size must be specified" 532 533 if len(args) == 0: 534 self.first = self.type(kwargs.pop('start')) 535 handle_kwargs(self, kwargs) 536 537 elif len(args) == 1: 538 if kwargs: 539 self.first = self.type(args[0]) 540 handle_kwargs(self, kwargs) 541 elif isinstance(args[0], Range): 542 self.first = self.type(args[0].first) 543 self.second = self.type(args[0].second) 544 elif isinstance(args[0], (list, tuple)): 545 self.first = self.type(args[0][0]) 546 self.second = self.type(args[0][1]) 547 else: 548 self.first = self.type(0) 549 self.second = self.type(args[0]) - 1 550 551 elif len(args) == 2: 552 self.first = self.type(args[0]) 553 self.second = self.type(args[1]) 554 else: 555 raise TypeError, "Too many arguments specified" 556 557 if kwargs: 558 raise TypeError, "too many keywords: %s" % kwargs.keys() 559 560 def __str__(self): 561 return '%s:%s' % (self.first, self.second) 562 563 @classmethod 564 def cxx_predecls(cls, code): 565 cls.type.cxx_predecls(code) 566 code('#include "base/range.hh"') 567 568 @classmethod 569 def swig_predecls(cls, code): 570 cls.type.swig_predecls(code) 571 code('%import "python/swig/range.i"') 572 573class AddrRange(Range): 574 type = Addr 575 576 def getValue(self): 577 from m5.internal.range import AddrRange 578 579 value = AddrRange() 580 value.start = long(self.first) 581 value.end = long(self.second) 582 return value 583 584class TickRange(Range): 585 type = Tick 586 587 def getValue(self): 588 from m5.internal.range import TickRange 589 590 value = TickRange() 591 value.start = long(self.first) 592 value.end = long(self.second) 593 return value 594 595# Boolean parameter type. Python doesn't let you subclass bool, since 596# it doesn't want to let you create multiple instances of True and 597# False. Thus this is a little more complicated than String. 598class Bool(ParamValue): 599 cxx_type = 'bool' 600 def __init__(self, value): 601 try: 602 self.value = convert.toBool(value) 603 except TypeError: 604 self.value = bool(value) 605 606 def getValue(self): 607 return bool(self.value) 608 609 def __str__(self): 610 return str(self.value) 611 612 def ini_str(self): 613 if self.value: 614 return 'true' 615 return 'false' 616 617def IncEthernetAddr(addr, val = 1): 618 bytes = map(lambda x: int(x, 16), addr.split(':')) 619 bytes[5] += val 620 for i in (5, 4, 3, 2, 1): 621 val,rem = divmod(bytes[i], 256) 622 bytes[i] = rem 623 if val == 0: 624 break 625 bytes[i - 1] += val 626 assert(bytes[0] <= 255) 627 return ':'.join(map(lambda x: '%02x' % x, bytes)) 628 629_NextEthernetAddr = "00:90:00:00:00:01" 630def NextEthernetAddr(): 631 global _NextEthernetAddr 632 633 value = _NextEthernetAddr 634 _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 635 return value 636 637class EthernetAddr(ParamValue): 638 cxx_type = 'Net::EthAddr' 639 640 @classmethod 641 def cxx_predecls(cls, code): 642 code('#include "base/inet.hh"') 643 644 @classmethod 645 def swig_predecls(cls, code): 646 code('%include "python/swig/inet.i"') 647 648 def __init__(self, value): 649 if value == NextEthernetAddr: 650 self.value = value 651 return 652 653 if not isinstance(value, str): 654 raise TypeError, "expected an ethernet address and didn't get one" 655 656 bytes = value.split(':') 657 if len(bytes) != 6: 658 raise TypeError, 'invalid ethernet address %s' % value 659 660 for byte in bytes: 661 if not 0 <= int(byte) <= 0xff: 662 raise TypeError, 'invalid ethernet address %s' % value 663 664 self.value = value 665 666 def unproxy(self, base): 667 if self.value == NextEthernetAddr: 668 return EthernetAddr(self.value()) 669 return self 670 671 def getValue(self): 672 from m5.internal.params import EthAddr 673 return EthAddr(self.value) 674 675 def ini_str(self): 676 return self.value 677 678# When initializing an IpAddress, pass in an existing IpAddress, a string of 679# the form "a.b.c.d", or an integer representing an IP. 680class IpAddress(ParamValue): 681 cxx_type = 'Net::IpAddress' 682 683 @classmethod 684 def cxx_predecls(cls, code): 685 code('#include "base/inet.hh"') 686 687 @classmethod 688 def swig_predecls(cls, code): 689 code('%include "python/swig/inet.i"') 690 691 def __init__(self, value): 692 if isinstance(value, IpAddress): 693 self.ip = value.ip 694 else: 695 try: 696 self.ip = convert.toIpAddress(value) 697 except TypeError: 698 self.ip = long(value) 699 self.verifyIp() 700 701 def __str__(self): 702 tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 703 return '%d.%d.%d.%d' % tuple(tup) 704 705 def __eq__(self, other): 706 if isinstance(other, IpAddress): 707 return self.ip == other.ip 708 elif isinstance(other, str): 709 try: 710 return self.ip == convert.toIpAddress(other) 711 except: 712 return False 713 else: 714 return self.ip == other 715 716 def __ne__(self, other): 717 return not (self == other) 718 719 def verifyIp(self): 720 if self.ip < 0 or self.ip >= (1 << 32): 721 raise TypeError, "invalid ip address %#08x" % self.ip 722 723 def getValue(self): 724 from m5.internal.params import IpAddress 725 return IpAddress(self.ip) 726 727# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 728# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 729# positional or keyword arguments. 730class IpNetmask(IpAddress): 731 cxx_type = 'Net::IpNetmask' 732 733 @classmethod 734 def cxx_predecls(cls, code): 735 code('#include "base/inet.hh"') 736 737 @classmethod 738 def swig_predecls(cls, code): 739 code('%include "python/swig/inet.i"') 740 741 def __init__(self, *args, **kwargs): 742 def handle_kwarg(self, kwargs, key, elseVal = None): 743 if key in kwargs: 744 setattr(self, key, kwargs.pop(key)) 745 elif elseVal: 746 setattr(self, key, elseVal) 747 else: 748 raise TypeError, "No value set for %s" % key 749 750 if len(args) == 0: 751 handle_kwarg(self, kwargs, 'ip') 752 handle_kwarg(self, kwargs, 'netmask') 753 754 elif len(args) == 1: 755 if kwargs: 756 if not 'ip' in kwargs and not 'netmask' in kwargs: 757 raise TypeError, "Invalid arguments" 758 handle_kwarg(self, kwargs, 'ip', args[0]) 759 handle_kwarg(self, kwargs, 'netmask', args[0]) 760 elif isinstance(args[0], IpNetmask): 761 self.ip = args[0].ip 762 self.netmask = args[0].netmask 763 else: 764 (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 765 766 elif len(args) == 2: 767 self.ip = args[0] 768 self.netmask = args[1] 769 else: 770 raise TypeError, "Too many arguments specified" 771 772 if kwargs: 773 raise TypeError, "Too many keywords: %s" % kwargs.keys() 774 775 self.verify() 776 777 def __str__(self): 778 return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 779 780 def __eq__(self, other): 781 if isinstance(other, IpNetmask): 782 return self.ip == other.ip and self.netmask == other.netmask 783 elif isinstance(other, str): 784 try: 785 return (self.ip, self.netmask) == convert.toIpNetmask(other) 786 except: 787 return False 788 else: 789 return False 790 791 def verify(self): 792 self.verifyIp() 793 if self.netmask < 0 or self.netmask > 32: 794 raise TypeError, "invalid netmask %d" % netmask 795 796 def getValue(self): 797 from m5.internal.params import IpNetmask 798 return IpNetmask(self.ip, self.netmask) 799 800# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 801# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 802class IpWithPort(IpAddress): 803 cxx_type = 'Net::IpWithPort' 804 805 @classmethod 806 def cxx_predecls(cls, code): 807 code('#include "base/inet.hh"') 808 809 @classmethod 810 def swig_predecls(cls, code): 811 code('%include "python/swig/inet.i"') 812 813 def __init__(self, *args, **kwargs): 814 def handle_kwarg(self, kwargs, key, elseVal = None): 815 if key in kwargs: 816 setattr(self, key, kwargs.pop(key)) 817 elif elseVal: 818 setattr(self, key, elseVal) 819 else: 820 raise TypeError, "No value set for %s" % key 821 822 if len(args) == 0: 823 handle_kwarg(self, kwargs, 'ip') 824 handle_kwarg(self, kwargs, 'port') 825 826 elif len(args) == 1: 827 if kwargs: 828 if not 'ip' in kwargs and not 'port' in kwargs: 829 raise TypeError, "Invalid arguments" 830 handle_kwarg(self, kwargs, 'ip', args[0]) 831 handle_kwarg(self, kwargs, 'port', args[0]) 832 elif isinstance(args[0], IpWithPort): 833 self.ip = args[0].ip 834 self.port = args[0].port 835 else: 836 (self.ip, self.port) = convert.toIpWithPort(args[0]) 837 838 elif len(args) == 2: 839 self.ip = args[0] 840 self.port = args[1] 841 else: 842 raise TypeError, "Too many arguments specified" 843 844 if kwargs: 845 raise TypeError, "Too many keywords: %s" % kwargs.keys() 846 847 self.verify() 848 849 def __str__(self): 850 return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 851 852 def __eq__(self, other): 853 if isinstance(other, IpWithPort): 854 return self.ip == other.ip and self.port == other.port 855 elif isinstance(other, str): 856 try: 857 return (self.ip, self.port) == convert.toIpWithPort(other) 858 except: 859 return False 860 else: 861 return False 862 863 def verify(self): 864 self.verifyIp() 865 if self.port < 0 or self.port > 0xffff: 866 raise TypeError, "invalid port %d" % self.port 867 868 def getValue(self): 869 from m5.internal.params import IpWithPort 870 return IpWithPort(self.ip, self.port) 871 872time_formats = [ "%a %b %d %H:%M:%S %Z %Y", 873 "%a %b %d %H:%M:%S %Z %Y", 874 "%Y/%m/%d %H:%M:%S", 875 "%Y/%m/%d %H:%M", 876 "%Y/%m/%d", 877 "%m/%d/%Y %H:%M:%S", 878 "%m/%d/%Y %H:%M", 879 "%m/%d/%Y", 880 "%m/%d/%y %H:%M:%S", 881 "%m/%d/%y %H:%M", 882 "%m/%d/%y"] 883 884 885def parse_time(value): 886 from time import gmtime, strptime, struct_time, time 887 from datetime import datetime, date 888 889 if isinstance(value, struct_time): 890 return value 891 892 if isinstance(value, (int, long)): 893 return gmtime(value) 894 895 if isinstance(value, (datetime, date)): 896 return value.timetuple() 897 898 if isinstance(value, str): 899 if value in ('Now', 'Today'): 900 return time.gmtime(time.time()) 901 902 for format in time_formats: 903 try: 904 return strptime(value, format) 905 except ValueError: 906 pass 907 908 raise ValueError, "Could not parse '%s' as a time" % value 909 910class Time(ParamValue): 911 cxx_type = 'tm' 912 913 @classmethod 914 def cxx_predecls(cls, code): 915 code('#include <time.h>') 916 917 @classmethod 918 def swig_predecls(cls, code): 919 code('%include "python/swig/time.i"') 920 921 def __init__(self, value): 922 self.value = parse_time(value) 923 924 def getValue(self): 925 from m5.internal.params import tm 926 927 c_time = tm() 928 py_time = self.value 929 930 # UNIX is years since 1900 931 c_time.tm_year = py_time.tm_year - 1900; 932 933 # Python starts at 1, UNIX starts at 0 934 c_time.tm_mon = py_time.tm_mon - 1; 935 c_time.tm_mday = py_time.tm_mday; 936 c_time.tm_hour = py_time.tm_hour; 937 c_time.tm_min = py_time.tm_min; 938 c_time.tm_sec = py_time.tm_sec; 939 940 # Python has 0 as Monday, UNIX is 0 as sunday 941 c_time.tm_wday = py_time.tm_wday + 1 942 if c_time.tm_wday > 6: 943 c_time.tm_wday -= 7; 944 945 # Python starts at 1, Unix starts at 0 946 c_time.tm_yday = py_time.tm_yday - 1; 947 948 return c_time 949 950 def __str__(self): 951 return time.asctime(self.value) 952 953 def ini_str(self): 954 return str(self) 955 956# Enumerated types are a little more complex. The user specifies the 957# type as Enum(foo) where foo is either a list or dictionary of 958# alternatives (typically strings, but not necessarily so). (In the 959# long run, the integer value of the parameter will be the list index 960# or the corresponding dictionary value. For now, since we only check 961# that the alternative is valid and then spit it into a .ini file, 962# there's not much point in using the dictionary.) 963 964# What Enum() must do is generate a new type encapsulating the 965# provided list/dictionary so that specific values of the parameter 966# can be instances of that type. We define two hidden internal 967# classes (_ListEnum and _DictEnum) to serve as base classes, then 968# derive the new type from the appropriate base class on the fly. 969 970allEnums = {} 971# Metaclass for Enum types 972class MetaEnum(MetaParamValue): 973 def __new__(mcls, name, bases, dict): 974 assert name not in allEnums 975 976 cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 977 allEnums[name] = cls 978 return cls 979 980 def __init__(cls, name, bases, init_dict): 981 if init_dict.has_key('map'): 982 if not isinstance(cls.map, dict): 983 raise TypeError, "Enum-derived class attribute 'map' " \ 984 "must be of type dict" 985 # build list of value strings from map 986 cls.vals = cls.map.keys() 987 cls.vals.sort() 988 elif init_dict.has_key('vals'): 989 if not isinstance(cls.vals, list): 990 raise TypeError, "Enum-derived class attribute 'vals' " \ 991 "must be of type list" 992 # build string->value map from vals sequence 993 cls.map = {} 994 for idx,val in enumerate(cls.vals): 995 cls.map[val] = idx 996 else: 997 raise TypeError, "Enum-derived class must define "\ 998 "attribute 'map' or 'vals'" 999 1000 cls.cxx_type = 'Enums::%s' % name 1001 1002 super(MetaEnum, cls).__init__(name, bases, init_dict) 1003 1004 # Generate C++ class declaration for this enum type. 1005 # Note that we wrap the enum in a class/struct to act as a namespace, 1006 # so that the enum strings can be brief w/o worrying about collisions. 1007 def cxx_decl(cls, code): 1008 name = cls.__name__ 1009 code('''\ 1010#ifndef __ENUM__${name}__ 1011#define __ENUM__${name}__ 1012 1013namespace Enums { 1014 enum $name { 1015''') 1016 code.indent(2) 1017 for val in cls.vals: 1018 code('$val = ${{cls.map[val]}},') 1019 code('Num_$name = ${{len(cls.vals)}},') 1020 code.dedent(2) 1021 code('''\ 1022 }; 1023extern const char *${name}Strings[Num_${name}]; 1024} 1025 1026#endif // __ENUM__${name}__ 1027''') 1028 1029 def cxx_def(cls, code): 1030 name = cls.__name__ 1031 code('''\ 1032#include "enums/$name.hh" 1033namespace Enums { 1034 const char *${name}Strings[Num_${name}] = 1035 { 1036''') 1037 code.indent(2) 1038 for val in cls.vals: 1039 code('"$val",') 1040 code.dedent(2) 1041 code(''' 1042 }; 1043} // namespace Enums 1044''') 1045
| 254 code('%{') 255 self.ptype.cxx_predecls(code) 256 code('%}') 257 code() 258 self.ptype.swig_predecls(code) 259 code() 260 code('%include "std_vector.i"') 261 code() 262 263 ptype = self.ptype_str 264 cxx_type = self.ptype.cxx_type 265 266 code('''\ 267%typemap(in) std::vector< $cxx_type >::value_type { 268 if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) { 269 if (SWIG_ConvertPtr($$input, (void **)&$$1, 270 $$descriptor($cxx_type), 0) == -1) { 271 return NULL; 272 } 273 } 274} 275 276%typemap(in) std::vector< $cxx_type >::value_type * { 277 if (SWIG_ConvertPtr($$input, (void **)&$$1, $$1_descriptor, 0) == -1) { 278 if (SWIG_ConvertPtr($$input, (void **)&$$1, 279 $$descriptor($cxx_type *), 0) == -1) { 280 return NULL; 281 } 282 } 283} 284''') 285 286 code('%template(vector_$ptype) std::vector< $cxx_type >;') 287 288 def cxx_predecls(self, code): 289 code('#include <vector>') 290 self.ptype.cxx_predecls(code) 291 292 def cxx_decl(self, code): 293 code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 294 295class ParamFactory(object): 296 def __init__(self, param_desc_class, ptype_str = None): 297 self.param_desc_class = param_desc_class 298 self.ptype_str = ptype_str 299 300 def __getattr__(self, attr): 301 if self.ptype_str: 302 attr = self.ptype_str + '.' + attr 303 return ParamFactory(self.param_desc_class, attr) 304 305 # E.g., Param.Int(5, "number of widgets") 306 def __call__(self, *args, **kwargs): 307 ptype = None 308 try: 309 ptype = allParams[self.ptype_str] 310 except KeyError: 311 # if name isn't defined yet, assume it's a SimObject, and 312 # try to resolve it later 313 pass 314 return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 315 316Param = ParamFactory(ParamDesc) 317VectorParam = ParamFactory(VectorParamDesc) 318 319##################################################################### 320# 321# Parameter Types 322# 323# Though native Python types could be used to specify parameter types 324# (the 'ptype' field of the Param and VectorParam classes), it's more 325# flexible to define our own set of types. This gives us more control 326# over how Python expressions are converted to values (via the 327# __init__() constructor) and how these values are printed out (via 328# the __str__() conversion method). 329# 330##################################################################### 331 332# String-valued parameter. Just mixin the ParamValue class with the 333# built-in str class. 334class String(ParamValue,str): 335 cxx_type = 'std::string' 336 337 @classmethod 338 def cxx_predecls(self, code): 339 code('#include <string>') 340 341 @classmethod 342 def swig_predecls(cls, code): 343 code('%include "std_string.i"') 344 345 def getValue(self): 346 return self 347 348# superclass for "numeric" parameter values, to emulate math 349# operations in a type-safe way. e.g., a Latency times an int returns 350# a new Latency object. 351class NumericParamValue(ParamValue): 352 def __str__(self): 353 return str(self.value) 354 355 def __float__(self): 356 return float(self.value) 357 358 def __long__(self): 359 return long(self.value) 360 361 def __int__(self): 362 return int(self.value) 363 364 # hook for bounds checking 365 def _check(self): 366 return 367 368 def __mul__(self, other): 369 newobj = self.__class__(self) 370 newobj.value *= other 371 newobj._check() 372 return newobj 373 374 __rmul__ = __mul__ 375 376 def __div__(self, other): 377 newobj = self.__class__(self) 378 newobj.value /= other 379 newobj._check() 380 return newobj 381 382 def __sub__(self, other): 383 newobj = self.__class__(self) 384 newobj.value -= other 385 newobj._check() 386 return newobj 387 388# Metaclass for bounds-checked integer parameters. See CheckedInt. 389class CheckedIntType(MetaParamValue): 390 def __init__(cls, name, bases, dict): 391 super(CheckedIntType, cls).__init__(name, bases, dict) 392 393 # CheckedInt is an abstract base class, so we actually don't 394 # want to do any processing on it... the rest of this code is 395 # just for classes that derive from CheckedInt. 396 if name == 'CheckedInt': 397 return 398 399 if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 400 if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 401 panic("CheckedInt subclass %s must define either\n" \ 402 " 'min' and 'max' or 'size' and 'unsigned'\n", 403 name); 404 if cls.unsigned: 405 cls.min = 0 406 cls.max = 2 ** cls.size - 1 407 else: 408 cls.min = -(2 ** (cls.size - 1)) 409 cls.max = (2 ** (cls.size - 1)) - 1 410 411# Abstract superclass for bounds-checked integer parameters. This 412# class is subclassed to generate parameter classes with specific 413# bounds. Initialization of the min and max bounds is done in the 414# metaclass CheckedIntType.__init__. 415class CheckedInt(NumericParamValue): 416 __metaclass__ = CheckedIntType 417 418 def _check(self): 419 if not self.min <= self.value <= self.max: 420 raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 421 (self.min, self.value, self.max) 422 423 def __init__(self, value): 424 if isinstance(value, str): 425 self.value = convert.toInteger(value) 426 elif isinstance(value, (int, long, float, NumericParamValue)): 427 self.value = long(value) 428 else: 429 raise TypeError, "Can't convert object of type %s to CheckedInt" \ 430 % type(value).__name__ 431 self._check() 432 433 @classmethod 434 def cxx_predecls(cls, code): 435 # most derived types require this, so we just do it here once 436 code('#include "base/types.hh"') 437 438 @classmethod 439 def swig_predecls(cls, code): 440 # most derived types require this, so we just do it here once 441 code('%import "stdint.i"') 442 code('%import "base/types.hh"') 443 444 def getValue(self): 445 return long(self.value) 446 447class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 448class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 449 450class Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 451class UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 452class Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 453class UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 454class Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 455class UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 456class Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 457class UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 458 459class Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 460class Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 461class TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 462class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 463 464class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 465 466class Float(ParamValue, float): 467 cxx_type = 'double' 468 469 def __init__(self, value): 470 if isinstance(value, (int, long, float, NumericParamValue, Float)): 471 self.value = float(value) 472 else: 473 raise TypeError, "Can't convert object of type %s to Float" \ 474 % type(value).__name__ 475 476 def getValue(self): 477 return float(self.value) 478 479class MemorySize(CheckedInt): 480 cxx_type = 'uint64_t' 481 size = 64 482 unsigned = True 483 def __init__(self, value): 484 if isinstance(value, MemorySize): 485 self.value = value.value 486 else: 487 self.value = convert.toMemorySize(value) 488 self._check() 489 490class MemorySize32(CheckedInt): 491 cxx_type = 'uint32_t' 492 size = 32 493 unsigned = True 494 def __init__(self, value): 495 if isinstance(value, MemorySize): 496 self.value = value.value 497 else: 498 self.value = convert.toMemorySize(value) 499 self._check() 500 501class Addr(CheckedInt): 502 cxx_type = 'Addr' 503 size = 64 504 unsigned = True 505 def __init__(self, value): 506 if isinstance(value, Addr): 507 self.value = value.value 508 else: 509 try: 510 self.value = convert.toMemorySize(value) 511 except TypeError: 512 self.value = long(value) 513 self._check() 514 def __add__(self, other): 515 if isinstance(other, Addr): 516 return self.value + other.value 517 else: 518 return self.value + other 519 520 521class MetaRange(MetaParamValue): 522 def __init__(cls, name, bases, dict): 523 super(MetaRange, cls).__init__(name, bases, dict) 524 if name == 'Range': 525 return 526 cls.cxx_type = 'Range< %s >' % cls.type.cxx_type 527 528class Range(ParamValue): 529 __metaclass__ = MetaRange 530 type = Int # default; can be overridden in subclasses 531 def __init__(self, *args, **kwargs): 532 def handle_kwargs(self, kwargs): 533 if 'end' in kwargs: 534 self.second = self.type(kwargs.pop('end')) 535 elif 'size' in kwargs: 536 self.second = self.first + self.type(kwargs.pop('size')) - 1 537 else: 538 raise TypeError, "Either end or size must be specified" 539 540 if len(args) == 0: 541 self.first = self.type(kwargs.pop('start')) 542 handle_kwargs(self, kwargs) 543 544 elif len(args) == 1: 545 if kwargs: 546 self.first = self.type(args[0]) 547 handle_kwargs(self, kwargs) 548 elif isinstance(args[0], Range): 549 self.first = self.type(args[0].first) 550 self.second = self.type(args[0].second) 551 elif isinstance(args[0], (list, tuple)): 552 self.first = self.type(args[0][0]) 553 self.second = self.type(args[0][1]) 554 else: 555 self.first = self.type(0) 556 self.second = self.type(args[0]) - 1 557 558 elif len(args) == 2: 559 self.first = self.type(args[0]) 560 self.second = self.type(args[1]) 561 else: 562 raise TypeError, "Too many arguments specified" 563 564 if kwargs: 565 raise TypeError, "too many keywords: %s" % kwargs.keys() 566 567 def __str__(self): 568 return '%s:%s' % (self.first, self.second) 569 570 @classmethod 571 def cxx_predecls(cls, code): 572 cls.type.cxx_predecls(code) 573 code('#include "base/range.hh"') 574 575 @classmethod 576 def swig_predecls(cls, code): 577 cls.type.swig_predecls(code) 578 code('%import "python/swig/range.i"') 579 580class AddrRange(Range): 581 type = Addr 582 583 def getValue(self): 584 from m5.internal.range import AddrRange 585 586 value = AddrRange() 587 value.start = long(self.first) 588 value.end = long(self.second) 589 return value 590 591class TickRange(Range): 592 type = Tick 593 594 def getValue(self): 595 from m5.internal.range import TickRange 596 597 value = TickRange() 598 value.start = long(self.first) 599 value.end = long(self.second) 600 return value 601 602# Boolean parameter type. Python doesn't let you subclass bool, since 603# it doesn't want to let you create multiple instances of True and 604# False. Thus this is a little more complicated than String. 605class Bool(ParamValue): 606 cxx_type = 'bool' 607 def __init__(self, value): 608 try: 609 self.value = convert.toBool(value) 610 except TypeError: 611 self.value = bool(value) 612 613 def getValue(self): 614 return bool(self.value) 615 616 def __str__(self): 617 return str(self.value) 618 619 def ini_str(self): 620 if self.value: 621 return 'true' 622 return 'false' 623 624def IncEthernetAddr(addr, val = 1): 625 bytes = map(lambda x: int(x, 16), addr.split(':')) 626 bytes[5] += val 627 for i in (5, 4, 3, 2, 1): 628 val,rem = divmod(bytes[i], 256) 629 bytes[i] = rem 630 if val == 0: 631 break 632 bytes[i - 1] += val 633 assert(bytes[0] <= 255) 634 return ':'.join(map(lambda x: '%02x' % x, bytes)) 635 636_NextEthernetAddr = "00:90:00:00:00:01" 637def NextEthernetAddr(): 638 global _NextEthernetAddr 639 640 value = _NextEthernetAddr 641 _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 642 return value 643 644class EthernetAddr(ParamValue): 645 cxx_type = 'Net::EthAddr' 646 647 @classmethod 648 def cxx_predecls(cls, code): 649 code('#include "base/inet.hh"') 650 651 @classmethod 652 def swig_predecls(cls, code): 653 code('%include "python/swig/inet.i"') 654 655 def __init__(self, value): 656 if value == NextEthernetAddr: 657 self.value = value 658 return 659 660 if not isinstance(value, str): 661 raise TypeError, "expected an ethernet address and didn't get one" 662 663 bytes = value.split(':') 664 if len(bytes) != 6: 665 raise TypeError, 'invalid ethernet address %s' % value 666 667 for byte in bytes: 668 if not 0 <= int(byte) <= 0xff: 669 raise TypeError, 'invalid ethernet address %s' % value 670 671 self.value = value 672 673 def unproxy(self, base): 674 if self.value == NextEthernetAddr: 675 return EthernetAddr(self.value()) 676 return self 677 678 def getValue(self): 679 from m5.internal.params import EthAddr 680 return EthAddr(self.value) 681 682 def ini_str(self): 683 return self.value 684 685# When initializing an IpAddress, pass in an existing IpAddress, a string of 686# the form "a.b.c.d", or an integer representing an IP. 687class IpAddress(ParamValue): 688 cxx_type = 'Net::IpAddress' 689 690 @classmethod 691 def cxx_predecls(cls, code): 692 code('#include "base/inet.hh"') 693 694 @classmethod 695 def swig_predecls(cls, code): 696 code('%include "python/swig/inet.i"') 697 698 def __init__(self, value): 699 if isinstance(value, IpAddress): 700 self.ip = value.ip 701 else: 702 try: 703 self.ip = convert.toIpAddress(value) 704 except TypeError: 705 self.ip = long(value) 706 self.verifyIp() 707 708 def __str__(self): 709 tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 710 return '%d.%d.%d.%d' % tuple(tup) 711 712 def __eq__(self, other): 713 if isinstance(other, IpAddress): 714 return self.ip == other.ip 715 elif isinstance(other, str): 716 try: 717 return self.ip == convert.toIpAddress(other) 718 except: 719 return False 720 else: 721 return self.ip == other 722 723 def __ne__(self, other): 724 return not (self == other) 725 726 def verifyIp(self): 727 if self.ip < 0 or self.ip >= (1 << 32): 728 raise TypeError, "invalid ip address %#08x" % self.ip 729 730 def getValue(self): 731 from m5.internal.params import IpAddress 732 return IpAddress(self.ip) 733 734# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 735# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 736# positional or keyword arguments. 737class IpNetmask(IpAddress): 738 cxx_type = 'Net::IpNetmask' 739 740 @classmethod 741 def cxx_predecls(cls, code): 742 code('#include "base/inet.hh"') 743 744 @classmethod 745 def swig_predecls(cls, code): 746 code('%include "python/swig/inet.i"') 747 748 def __init__(self, *args, **kwargs): 749 def handle_kwarg(self, kwargs, key, elseVal = None): 750 if key in kwargs: 751 setattr(self, key, kwargs.pop(key)) 752 elif elseVal: 753 setattr(self, key, elseVal) 754 else: 755 raise TypeError, "No value set for %s" % key 756 757 if len(args) == 0: 758 handle_kwarg(self, kwargs, 'ip') 759 handle_kwarg(self, kwargs, 'netmask') 760 761 elif len(args) == 1: 762 if kwargs: 763 if not 'ip' in kwargs and not 'netmask' in kwargs: 764 raise TypeError, "Invalid arguments" 765 handle_kwarg(self, kwargs, 'ip', args[0]) 766 handle_kwarg(self, kwargs, 'netmask', args[0]) 767 elif isinstance(args[0], IpNetmask): 768 self.ip = args[0].ip 769 self.netmask = args[0].netmask 770 else: 771 (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 772 773 elif len(args) == 2: 774 self.ip = args[0] 775 self.netmask = args[1] 776 else: 777 raise TypeError, "Too many arguments specified" 778 779 if kwargs: 780 raise TypeError, "Too many keywords: %s" % kwargs.keys() 781 782 self.verify() 783 784 def __str__(self): 785 return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 786 787 def __eq__(self, other): 788 if isinstance(other, IpNetmask): 789 return self.ip == other.ip and self.netmask == other.netmask 790 elif isinstance(other, str): 791 try: 792 return (self.ip, self.netmask) == convert.toIpNetmask(other) 793 except: 794 return False 795 else: 796 return False 797 798 def verify(self): 799 self.verifyIp() 800 if self.netmask < 0 or self.netmask > 32: 801 raise TypeError, "invalid netmask %d" % netmask 802 803 def getValue(self): 804 from m5.internal.params import IpNetmask 805 return IpNetmask(self.ip, self.netmask) 806 807# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 808# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 809class IpWithPort(IpAddress): 810 cxx_type = 'Net::IpWithPort' 811 812 @classmethod 813 def cxx_predecls(cls, code): 814 code('#include "base/inet.hh"') 815 816 @classmethod 817 def swig_predecls(cls, code): 818 code('%include "python/swig/inet.i"') 819 820 def __init__(self, *args, **kwargs): 821 def handle_kwarg(self, kwargs, key, elseVal = None): 822 if key in kwargs: 823 setattr(self, key, kwargs.pop(key)) 824 elif elseVal: 825 setattr(self, key, elseVal) 826 else: 827 raise TypeError, "No value set for %s" % key 828 829 if len(args) == 0: 830 handle_kwarg(self, kwargs, 'ip') 831 handle_kwarg(self, kwargs, 'port') 832 833 elif len(args) == 1: 834 if kwargs: 835 if not 'ip' in kwargs and not 'port' in kwargs: 836 raise TypeError, "Invalid arguments" 837 handle_kwarg(self, kwargs, 'ip', args[0]) 838 handle_kwarg(self, kwargs, 'port', args[0]) 839 elif isinstance(args[0], IpWithPort): 840 self.ip = args[0].ip 841 self.port = args[0].port 842 else: 843 (self.ip, self.port) = convert.toIpWithPort(args[0]) 844 845 elif len(args) == 2: 846 self.ip = args[0] 847 self.port = args[1] 848 else: 849 raise TypeError, "Too many arguments specified" 850 851 if kwargs: 852 raise TypeError, "Too many keywords: %s" % kwargs.keys() 853 854 self.verify() 855 856 def __str__(self): 857 return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 858 859 def __eq__(self, other): 860 if isinstance(other, IpWithPort): 861 return self.ip == other.ip and self.port == other.port 862 elif isinstance(other, str): 863 try: 864 return (self.ip, self.port) == convert.toIpWithPort(other) 865 except: 866 return False 867 else: 868 return False 869 870 def verify(self): 871 self.verifyIp() 872 if self.port < 0 or self.port > 0xffff: 873 raise TypeError, "invalid port %d" % self.port 874 875 def getValue(self): 876 from m5.internal.params import IpWithPort 877 return IpWithPort(self.ip, self.port) 878 879time_formats = [ "%a %b %d %H:%M:%S %Z %Y", 880 "%a %b %d %H:%M:%S %Z %Y", 881 "%Y/%m/%d %H:%M:%S", 882 "%Y/%m/%d %H:%M", 883 "%Y/%m/%d", 884 "%m/%d/%Y %H:%M:%S", 885 "%m/%d/%Y %H:%M", 886 "%m/%d/%Y", 887 "%m/%d/%y %H:%M:%S", 888 "%m/%d/%y %H:%M", 889 "%m/%d/%y"] 890 891 892def parse_time(value): 893 from time import gmtime, strptime, struct_time, time 894 from datetime import datetime, date 895 896 if isinstance(value, struct_time): 897 return value 898 899 if isinstance(value, (int, long)): 900 return gmtime(value) 901 902 if isinstance(value, (datetime, date)): 903 return value.timetuple() 904 905 if isinstance(value, str): 906 if value in ('Now', 'Today'): 907 return time.gmtime(time.time()) 908 909 for format in time_formats: 910 try: 911 return strptime(value, format) 912 except ValueError: 913 pass 914 915 raise ValueError, "Could not parse '%s' as a time" % value 916 917class Time(ParamValue): 918 cxx_type = 'tm' 919 920 @classmethod 921 def cxx_predecls(cls, code): 922 code('#include <time.h>') 923 924 @classmethod 925 def swig_predecls(cls, code): 926 code('%include "python/swig/time.i"') 927 928 def __init__(self, value): 929 self.value = parse_time(value) 930 931 def getValue(self): 932 from m5.internal.params import tm 933 934 c_time = tm() 935 py_time = self.value 936 937 # UNIX is years since 1900 938 c_time.tm_year = py_time.tm_year - 1900; 939 940 # Python starts at 1, UNIX starts at 0 941 c_time.tm_mon = py_time.tm_mon - 1; 942 c_time.tm_mday = py_time.tm_mday; 943 c_time.tm_hour = py_time.tm_hour; 944 c_time.tm_min = py_time.tm_min; 945 c_time.tm_sec = py_time.tm_sec; 946 947 # Python has 0 as Monday, UNIX is 0 as sunday 948 c_time.tm_wday = py_time.tm_wday + 1 949 if c_time.tm_wday > 6: 950 c_time.tm_wday -= 7; 951 952 # Python starts at 1, Unix starts at 0 953 c_time.tm_yday = py_time.tm_yday - 1; 954 955 return c_time 956 957 def __str__(self): 958 return time.asctime(self.value) 959 960 def ini_str(self): 961 return str(self) 962 963# Enumerated types are a little more complex. The user specifies the 964# type as Enum(foo) where foo is either a list or dictionary of 965# alternatives (typically strings, but not necessarily so). (In the 966# long run, the integer value of the parameter will be the list index 967# or the corresponding dictionary value. For now, since we only check 968# that the alternative is valid and then spit it into a .ini file, 969# there's not much point in using the dictionary.) 970 971# What Enum() must do is generate a new type encapsulating the 972# provided list/dictionary so that specific values of the parameter 973# can be instances of that type. We define two hidden internal 974# classes (_ListEnum and _DictEnum) to serve as base classes, then 975# derive the new type from the appropriate base class on the fly. 976 977allEnums = {} 978# Metaclass for Enum types 979class MetaEnum(MetaParamValue): 980 def __new__(mcls, name, bases, dict): 981 assert name not in allEnums 982 983 cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 984 allEnums[name] = cls 985 return cls 986 987 def __init__(cls, name, bases, init_dict): 988 if init_dict.has_key('map'): 989 if not isinstance(cls.map, dict): 990 raise TypeError, "Enum-derived class attribute 'map' " \ 991 "must be of type dict" 992 # build list of value strings from map 993 cls.vals = cls.map.keys() 994 cls.vals.sort() 995 elif init_dict.has_key('vals'): 996 if not isinstance(cls.vals, list): 997 raise TypeError, "Enum-derived class attribute 'vals' " \ 998 "must be of type list" 999 # build string->value map from vals sequence 1000 cls.map = {} 1001 for idx,val in enumerate(cls.vals): 1002 cls.map[val] = idx 1003 else: 1004 raise TypeError, "Enum-derived class must define "\ 1005 "attribute 'map' or 'vals'" 1006 1007 cls.cxx_type = 'Enums::%s' % name 1008 1009 super(MetaEnum, cls).__init__(name, bases, init_dict) 1010 1011 # Generate C++ class declaration for this enum type. 1012 # Note that we wrap the enum in a class/struct to act as a namespace, 1013 # so that the enum strings can be brief w/o worrying about collisions. 1014 def cxx_decl(cls, code): 1015 name = cls.__name__ 1016 code('''\ 1017#ifndef __ENUM__${name}__ 1018#define __ENUM__${name}__ 1019 1020namespace Enums { 1021 enum $name { 1022''') 1023 code.indent(2) 1024 for val in cls.vals: 1025 code('$val = ${{cls.map[val]}},') 1026 code('Num_$name = ${{len(cls.vals)}},') 1027 code.dedent(2) 1028 code('''\ 1029 }; 1030extern const char *${name}Strings[Num_${name}]; 1031} 1032 1033#endif // __ENUM__${name}__ 1034''') 1035 1036 def cxx_def(cls, code): 1037 name = cls.__name__ 1038 code('''\ 1039#include "enums/$name.hh" 1040namespace Enums { 1041 const char *${name}Strings[Num_${name}] = 1042 { 1043''') 1044 code.indent(2) 1045 for val in cls.vals: 1046 code('"$val",') 1047 code.dedent(2) 1048 code(''' 1049 }; 1050} // namespace Enums 1051''') 1052
|
| 1053 def swig_decl(cls, code): 1054 name = cls.__name__ 1055 code('''\ 1056%module(package="m5.internal") enum_$name 1057 1058%{ 1059#include "enums/$name.hh" 1060%} 1061 1062%include "enums/$name.hh" 1063''') 1064 1065
|
1046# Base class for enum types. 1047class Enum(ParamValue): 1048 __metaclass__ = MetaEnum 1049 vals = [] 1050 1051 def __init__(self, value): 1052 if value not in self.map: 1053 raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 1054 % (value, self.vals) 1055 self.value = value 1056 1057 @classmethod 1058 def cxx_predecls(cls, code): 1059 code('#include "enums/$0.hh"', cls.__name__) 1060 1061 @classmethod 1062 def swig_predecls(cls, code): 1063 code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 1064 1065 def getValue(self): 1066 return int(self.map[self.value]) 1067 1068 def __str__(self): 1069 return self.value 1070 1071# how big does a rounding error need to be before we warn about it? 1072frequency_tolerance = 0.001 # 0.1% 1073 1074class TickParamValue(NumericParamValue): 1075 cxx_type = 'Tick' 1076 1077 @classmethod 1078 def cxx_predecls(cls, code): 1079 code('#include "base/types.hh"') 1080 1081 @classmethod 1082 def swig_predecls(cls, code): 1083 code('%import "stdint.i"') 1084 code('%import "base/types.hh"') 1085 1086 def getValue(self): 1087 return long(self.value) 1088 1089class Latency(TickParamValue): 1090 def __init__(self, value): 1091 if isinstance(value, (Latency, Clock)): 1092 self.ticks = value.ticks 1093 self.value = value.value 1094 elif isinstance(value, Frequency): 1095 self.ticks = value.ticks 1096 self.value = 1.0 / value.value 1097 elif value.endswith('t'): 1098 self.ticks = True 1099 self.value = int(value[:-1]) 1100 else: 1101 self.ticks = False 1102 self.value = convert.toLatency(value) 1103 1104 def __getattr__(self, attr): 1105 if attr in ('latency', 'period'): 1106 return self 1107 if attr == 'frequency': 1108 return Frequency(self) 1109 raise AttributeError, "Latency object has no attribute '%s'" % attr 1110 1111 def getValue(self): 1112 if self.ticks or self.value == 0: 1113 value = self.value 1114 else: 1115 value = ticks.fromSeconds(self.value) 1116 return long(value) 1117 1118 # convert latency to ticks 1119 def ini_str(self): 1120 return '%d' % self.getValue() 1121 1122class Frequency(TickParamValue): 1123 def __init__(self, value): 1124 if isinstance(value, (Latency, Clock)): 1125 if value.value == 0: 1126 self.value = 0 1127 else: 1128 self.value = 1.0 / value.value 1129 self.ticks = value.ticks 1130 elif isinstance(value, Frequency): 1131 self.value = value.value 1132 self.ticks = value.ticks 1133 else: 1134 self.ticks = False 1135 self.value = convert.toFrequency(value) 1136 1137 def __getattr__(self, attr): 1138 if attr == 'frequency': 1139 return self 1140 if attr in ('latency', 'period'): 1141 return Latency(self) 1142 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1143 1144 # convert latency to ticks 1145 def getValue(self): 1146 if self.ticks or self.value == 0: 1147 value = self.value 1148 else: 1149 value = ticks.fromSeconds(1.0 / self.value) 1150 return long(value) 1151 1152 def ini_str(self): 1153 return '%d' % self.getValue() 1154 1155# A generic frequency and/or Latency value. Value is stored as a latency, 1156# but to avoid ambiguity this object does not support numeric ops (* or /). 1157# An explicit conversion to a Latency or Frequency must be made first. 1158class Clock(ParamValue): 1159 cxx_type = 'Tick' 1160 1161 @classmethod 1162 def cxx_predecls(cls, code): 1163 code('#include "base/types.hh"') 1164 1165 @classmethod 1166 def swig_predecls(cls, code): 1167 code('%import "stdint.i"') 1168 code('%import "base/types.hh"') 1169 1170 def __init__(self, value): 1171 if isinstance(value, (Latency, Clock)): 1172 self.ticks = value.ticks 1173 self.value = value.value 1174 elif isinstance(value, Frequency): 1175 self.ticks = value.ticks 1176 self.value = 1.0 / value.value 1177 elif value.endswith('t'): 1178 self.ticks = True 1179 self.value = int(value[:-1]) 1180 else: 1181 self.ticks = False 1182 self.value = convert.anyToLatency(value) 1183 1184 def __getattr__(self, attr): 1185 if attr == 'frequency': 1186 return Frequency(self) 1187 if attr in ('latency', 'period'): 1188 return Latency(self) 1189 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1190 1191 def getValue(self): 1192 return self.period.getValue() 1193 1194 def ini_str(self): 1195 return self.period.ini_str() 1196 1197class NetworkBandwidth(float,ParamValue): 1198 cxx_type = 'float' 1199 def __new__(cls, value): 1200 # convert to bits per second 1201 val = convert.toNetworkBandwidth(value) 1202 return super(cls, NetworkBandwidth).__new__(cls, val) 1203 1204 def __str__(self): 1205 return str(self.val) 1206 1207 def getValue(self): 1208 # convert to seconds per byte 1209 value = 8.0 / float(self) 1210 # convert to ticks per byte 1211 value = ticks.fromSeconds(value) 1212 return float(value) 1213 1214 def ini_str(self): 1215 return '%f' % self.getValue() 1216 1217class MemoryBandwidth(float,ParamValue): 1218 cxx_type = 'float' 1219 def __new__(cls, value): 1220 # convert to bytes per second 1221 val = convert.toMemoryBandwidth(value) 1222 return super(cls, MemoryBandwidth).__new__(cls, val) 1223 1224 def __str__(self): 1225 return str(self.val) 1226 1227 def getValue(self): 1228 # convert to seconds per byte 1229 value = float(self) 1230 if value: 1231 value = 1.0 / float(self) 1232 # convert to ticks per byte 1233 value = ticks.fromSeconds(value) 1234 return float(value) 1235 1236 def ini_str(self): 1237 return '%f' % self.getValue() 1238 1239# 1240# "Constants"... handy aliases for various values. 1241# 1242 1243# Special class for NULL pointers. Note the special check in 1244# make_param_value() above that lets these be assigned where a 1245# SimObject is required. 1246# only one copy of a particular node 1247class NullSimObject(object): 1248 __metaclass__ = Singleton 1249 1250 def __call__(cls): 1251 return cls 1252 1253 def _instantiate(self, parent = None, path = ''): 1254 pass 1255 1256 def ini_str(self): 1257 return 'Null' 1258 1259 def unproxy(self, base): 1260 return self 1261 1262 def set_path(self, parent, name): 1263 pass 1264 1265 def __str__(self): 1266 return 'Null' 1267 1268 def getValue(self): 1269 return None 1270 1271# The only instance you'll ever need... 1272NULL = NullSimObject() 1273 1274def isNullPointer(value): 1275 return isinstance(value, NullSimObject) 1276 1277# Some memory range specifications use this as a default upper bound. 1278MaxAddr = Addr.max 1279MaxTick = Tick.max 1280AllMemory = AddrRange(0, MaxAddr) 1281 1282 1283##################################################################### 1284# 1285# Port objects 1286# 1287# Ports are used to interconnect objects in the memory system. 1288# 1289##################################################################### 1290 1291# Port reference: encapsulates a reference to a particular port on a 1292# particular SimObject. 1293class PortRef(object): 1294 def __init__(self, simobj, name): 1295 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1296 self.simobj = simobj 1297 self.name = name 1298 self.peer = None # not associated with another port yet 1299 self.ccConnected = False # C++ port connection done? 1300 self.index = -1 # always -1 for non-vector ports 1301 1302 def __str__(self): 1303 return '%s.%s' % (self.simobj, self.name) 1304 1305 # for config.ini, print peer's name (not ours) 1306 def ini_str(self): 1307 return str(self.peer) 1308 1309 def __getattr__(self, attr): 1310 if attr == 'peerObj': 1311 # shorthand for proxies 1312 return self.peer.simobj 1313 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1314 (self.__class__.__name__, attr) 1315 1316 # Full connection is symmetric (both ways). Called via 1317 # SimObject.__setattr__ as a result of a port assignment, e.g., 1318 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1319 # e.g., "obj1.portA[3] = obj2.portB". 1320 def connect(self, other): 1321 if isinstance(other, VectorPortRef): 1322 # reference to plain VectorPort is implicit append 1323 other = other._get_next() 1324 if self.peer and not proxy.isproxy(self.peer): 1325 print "warning: overwriting port", self, \ 1326 "value", self.peer, "with", other 1327 self.peer.peer = None 1328 self.peer = other 1329 if proxy.isproxy(other): 1330 other.set_param_desc(PortParamDesc()) 1331 elif isinstance(other, PortRef): 1332 if other.peer is not self: 1333 other.connect(self) 1334 else: 1335 raise TypeError, \ 1336 "assigning non-port reference '%s' to port '%s'" \ 1337 % (other, self) 1338 1339 def clone(self, simobj, memo): 1340 if memo.has_key(self): 1341 return memo[self] 1342 newRef = copy.copy(self) 1343 memo[self] = newRef 1344 newRef.simobj = simobj 1345 assert(isSimObject(newRef.simobj)) 1346 if self.peer and not proxy.isproxy(self.peer): 1347 peerObj = self.peer.simobj(_memo=memo) 1348 newRef.peer = self.peer.clone(peerObj, memo) 1349 assert(not isinstance(newRef.peer, VectorPortRef)) 1350 return newRef 1351 1352 def unproxy(self, simobj): 1353 assert(simobj is self.simobj) 1354 if proxy.isproxy(self.peer): 1355 try: 1356 realPeer = self.peer.unproxy(self.simobj) 1357 except: 1358 print "Error in unproxying port '%s' of %s" % \ 1359 (self.name, self.simobj.path()) 1360 raise 1361 self.connect(realPeer) 1362 1363 # Call C++ to create corresponding port connection between C++ objects 1364 def ccConnect(self): 1365 from m5.internal.params import connectPorts 1366 1367 if self.ccConnected: # already done this 1368 return 1369 peer = self.peer 1370 if not self.peer: # nothing to connect to 1371 return 1372 try: 1373 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1374 peer.simobj.getCCObject(), peer.name, peer.index) 1375 except: 1376 print "Error connecting port %s.%s to %s.%s" % \ 1377 (self.simobj.path(), self.name, 1378 peer.simobj.path(), peer.name) 1379 raise 1380 self.ccConnected = True 1381 peer.ccConnected = True 1382 1383# A reference to an individual element of a VectorPort... much like a 1384# PortRef, but has an index. 1385class VectorPortElementRef(PortRef): 1386 def __init__(self, simobj, name, index): 1387 PortRef.__init__(self, simobj, name) 1388 self.index = index 1389 1390 def __str__(self): 1391 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1392 1393# A reference to a complete vector-valued port (not just a single element). 1394# Can be indexed to retrieve individual VectorPortElementRef instances. 1395class VectorPortRef(object): 1396 def __init__(self, simobj, name): 1397 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1398 self.simobj = simobj 1399 self.name = name 1400 self.elements = [] 1401 1402 def __str__(self): 1403 return '%s.%s[:]' % (self.simobj, self.name) 1404 1405 # for config.ini, print peer's name (not ours) 1406 def ini_str(self): 1407 return ' '.join([el.ini_str() for el in self.elements]) 1408 1409 def __getitem__(self, key): 1410 if not isinstance(key, int): 1411 raise TypeError, "VectorPort index must be integer" 1412 if key >= len(self.elements): 1413 # need to extend list 1414 ext = [VectorPortElementRef(self.simobj, self.name, i) 1415 for i in range(len(self.elements), key+1)] 1416 self.elements.extend(ext) 1417 return self.elements[key] 1418 1419 def _get_next(self): 1420 return self[len(self.elements)] 1421 1422 def __setitem__(self, key, value): 1423 if not isinstance(key, int): 1424 raise TypeError, "VectorPort index must be integer" 1425 self[key].connect(value) 1426 1427 def connect(self, other): 1428 if isinstance(other, (list, tuple)): 1429 # Assign list of port refs to vector port. 1430 # For now, append them... not sure if that's the right semantics 1431 # or if it should replace the current vector. 1432 for ref in other: 1433 self._get_next().connect(ref) 1434 else: 1435 # scalar assignment to plain VectorPort is implicit append 1436 self._get_next().connect(other) 1437 1438 def clone(self, simobj, memo): 1439 if memo.has_key(self): 1440 return memo[self] 1441 newRef = copy.copy(self) 1442 memo[self] = newRef 1443 newRef.simobj = simobj 1444 assert(isSimObject(newRef.simobj)) 1445 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 1446 return newRef 1447 1448 def unproxy(self, simobj): 1449 [el.unproxy(simobj) for el in self.elements] 1450 1451 def ccConnect(self): 1452 [el.ccConnect() for el in self.elements] 1453 1454# Port description object. Like a ParamDesc object, this represents a 1455# logical port in the SimObject class, not a particular port on a 1456# SimObject instance. The latter are represented by PortRef objects. 1457class Port(object): 1458 # Port("description") or Port(default, "description") 1459 def __init__(self, *args): 1460 if len(args) == 1: 1461 self.desc = args[0] 1462 elif len(args) == 2: 1463 self.default = args[0] 1464 self.desc = args[1] 1465 else: 1466 raise TypeError, 'wrong number of arguments' 1467 # self.name is set by SimObject class on assignment 1468 # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 1469 1470 # Generate a PortRef for this port on the given SimObject with the 1471 # given name 1472 def makeRef(self, simobj): 1473 return PortRef(simobj, self.name) 1474 1475 # Connect an instance of this port (on the given SimObject with 1476 # the given name) with the port described by the supplied PortRef 1477 def connect(self, simobj, ref): 1478 self.makeRef(simobj).connect(ref) 1479 1480# VectorPort description object. Like Port, but represents a vector 1481# of connections (e.g., as on a Bus). 1482class VectorPort(Port): 1483 def __init__(self, *args): 1484 Port.__init__(self, *args) 1485 self.isVec = True 1486 1487 def makeRef(self, simobj): 1488 return VectorPortRef(simobj, self.name) 1489 1490# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 1491# proxy objects (via set_param_desc()) so that proxy error messages 1492# make sense. 1493class PortParamDesc(object): 1494 __metaclass__ = Singleton 1495 1496 ptype_str = 'Port' 1497 ptype = Port 1498 1499baseEnums = allEnums.copy() 1500baseParams = allParams.copy() 1501 1502def clear(): 1503 global allEnums, allParams 1504 1505 allEnums = baseEnums.copy() 1506 allParams = baseParams.copy() 1507 1508__all__ = ['Param', 'VectorParam', 1509 'Enum', 'Bool', 'String', 'Float', 1510 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 1511 'Int32', 'UInt32', 'Int64', 'UInt64', 1512 'Counter', 'Addr', 'Tick', 'Percent', 1513 'TcpPort', 'UdpPort', 'EthernetAddr', 1514 'IpAddress', 'IpNetmask', 'IpWithPort', 1515 'MemorySize', 'MemorySize32', 1516 'Latency', 'Frequency', 'Clock', 1517 'NetworkBandwidth', 'MemoryBandwidth', 1518 'Range', 'AddrRange', 'TickRange', 1519 'MaxAddr', 'MaxTick', 'AllMemory', 1520 'Time', 1521 'NextEthernetAddr', 'NULL', 1522 'Port', 'VectorPort'] 1523 1524import SimObject
| 1066# Base class for enum types. 1067class Enum(ParamValue): 1068 __metaclass__ = MetaEnum 1069 vals = [] 1070 1071 def __init__(self, value): 1072 if value not in self.map: 1073 raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 1074 % (value, self.vals) 1075 self.value = value 1076 1077 @classmethod 1078 def cxx_predecls(cls, code): 1079 code('#include "enums/$0.hh"', cls.__name__) 1080 1081 @classmethod 1082 def swig_predecls(cls, code): 1083 code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 1084 1085 def getValue(self): 1086 return int(self.map[self.value]) 1087 1088 def __str__(self): 1089 return self.value 1090 1091# how big does a rounding error need to be before we warn about it? 1092frequency_tolerance = 0.001 # 0.1% 1093 1094class TickParamValue(NumericParamValue): 1095 cxx_type = 'Tick' 1096 1097 @classmethod 1098 def cxx_predecls(cls, code): 1099 code('#include "base/types.hh"') 1100 1101 @classmethod 1102 def swig_predecls(cls, code): 1103 code('%import "stdint.i"') 1104 code('%import "base/types.hh"') 1105 1106 def getValue(self): 1107 return long(self.value) 1108 1109class Latency(TickParamValue): 1110 def __init__(self, value): 1111 if isinstance(value, (Latency, Clock)): 1112 self.ticks = value.ticks 1113 self.value = value.value 1114 elif isinstance(value, Frequency): 1115 self.ticks = value.ticks 1116 self.value = 1.0 / value.value 1117 elif value.endswith('t'): 1118 self.ticks = True 1119 self.value = int(value[:-1]) 1120 else: 1121 self.ticks = False 1122 self.value = convert.toLatency(value) 1123 1124 def __getattr__(self, attr): 1125 if attr in ('latency', 'period'): 1126 return self 1127 if attr == 'frequency': 1128 return Frequency(self) 1129 raise AttributeError, "Latency object has no attribute '%s'" % attr 1130 1131 def getValue(self): 1132 if self.ticks or self.value == 0: 1133 value = self.value 1134 else: 1135 value = ticks.fromSeconds(self.value) 1136 return long(value) 1137 1138 # convert latency to ticks 1139 def ini_str(self): 1140 return '%d' % self.getValue() 1141 1142class Frequency(TickParamValue): 1143 def __init__(self, value): 1144 if isinstance(value, (Latency, Clock)): 1145 if value.value == 0: 1146 self.value = 0 1147 else: 1148 self.value = 1.0 / value.value 1149 self.ticks = value.ticks 1150 elif isinstance(value, Frequency): 1151 self.value = value.value 1152 self.ticks = value.ticks 1153 else: 1154 self.ticks = False 1155 self.value = convert.toFrequency(value) 1156 1157 def __getattr__(self, attr): 1158 if attr == 'frequency': 1159 return self 1160 if attr in ('latency', 'period'): 1161 return Latency(self) 1162 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1163 1164 # convert latency to ticks 1165 def getValue(self): 1166 if self.ticks or self.value == 0: 1167 value = self.value 1168 else: 1169 value = ticks.fromSeconds(1.0 / self.value) 1170 return long(value) 1171 1172 def ini_str(self): 1173 return '%d' % self.getValue() 1174 1175# A generic frequency and/or Latency value. Value is stored as a latency, 1176# but to avoid ambiguity this object does not support numeric ops (* or /). 1177# An explicit conversion to a Latency or Frequency must be made first. 1178class Clock(ParamValue): 1179 cxx_type = 'Tick' 1180 1181 @classmethod 1182 def cxx_predecls(cls, code): 1183 code('#include "base/types.hh"') 1184 1185 @classmethod 1186 def swig_predecls(cls, code): 1187 code('%import "stdint.i"') 1188 code('%import "base/types.hh"') 1189 1190 def __init__(self, value): 1191 if isinstance(value, (Latency, Clock)): 1192 self.ticks = value.ticks 1193 self.value = value.value 1194 elif isinstance(value, Frequency): 1195 self.ticks = value.ticks 1196 self.value = 1.0 / value.value 1197 elif value.endswith('t'): 1198 self.ticks = True 1199 self.value = int(value[:-1]) 1200 else: 1201 self.ticks = False 1202 self.value = convert.anyToLatency(value) 1203 1204 def __getattr__(self, attr): 1205 if attr == 'frequency': 1206 return Frequency(self) 1207 if attr in ('latency', 'period'): 1208 return Latency(self) 1209 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1210 1211 def getValue(self): 1212 return self.period.getValue() 1213 1214 def ini_str(self): 1215 return self.period.ini_str() 1216 1217class NetworkBandwidth(float,ParamValue): 1218 cxx_type = 'float' 1219 def __new__(cls, value): 1220 # convert to bits per second 1221 val = convert.toNetworkBandwidth(value) 1222 return super(cls, NetworkBandwidth).__new__(cls, val) 1223 1224 def __str__(self): 1225 return str(self.val) 1226 1227 def getValue(self): 1228 # convert to seconds per byte 1229 value = 8.0 / float(self) 1230 # convert to ticks per byte 1231 value = ticks.fromSeconds(value) 1232 return float(value) 1233 1234 def ini_str(self): 1235 return '%f' % self.getValue() 1236 1237class MemoryBandwidth(float,ParamValue): 1238 cxx_type = 'float' 1239 def __new__(cls, value): 1240 # convert to bytes per second 1241 val = convert.toMemoryBandwidth(value) 1242 return super(cls, MemoryBandwidth).__new__(cls, val) 1243 1244 def __str__(self): 1245 return str(self.val) 1246 1247 def getValue(self): 1248 # convert to seconds per byte 1249 value = float(self) 1250 if value: 1251 value = 1.0 / float(self) 1252 # convert to ticks per byte 1253 value = ticks.fromSeconds(value) 1254 return float(value) 1255 1256 def ini_str(self): 1257 return '%f' % self.getValue() 1258 1259# 1260# "Constants"... handy aliases for various values. 1261# 1262 1263# Special class for NULL pointers. Note the special check in 1264# make_param_value() above that lets these be assigned where a 1265# SimObject is required. 1266# only one copy of a particular node 1267class NullSimObject(object): 1268 __metaclass__ = Singleton 1269 1270 def __call__(cls): 1271 return cls 1272 1273 def _instantiate(self, parent = None, path = ''): 1274 pass 1275 1276 def ini_str(self): 1277 return 'Null' 1278 1279 def unproxy(self, base): 1280 return self 1281 1282 def set_path(self, parent, name): 1283 pass 1284 1285 def __str__(self): 1286 return 'Null' 1287 1288 def getValue(self): 1289 return None 1290 1291# The only instance you'll ever need... 1292NULL = NullSimObject() 1293 1294def isNullPointer(value): 1295 return isinstance(value, NullSimObject) 1296 1297# Some memory range specifications use this as a default upper bound. 1298MaxAddr = Addr.max 1299MaxTick = Tick.max 1300AllMemory = AddrRange(0, MaxAddr) 1301 1302 1303##################################################################### 1304# 1305# Port objects 1306# 1307# Ports are used to interconnect objects in the memory system. 1308# 1309##################################################################### 1310 1311# Port reference: encapsulates a reference to a particular port on a 1312# particular SimObject. 1313class PortRef(object): 1314 def __init__(self, simobj, name): 1315 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1316 self.simobj = simobj 1317 self.name = name 1318 self.peer = None # not associated with another port yet 1319 self.ccConnected = False # C++ port connection done? 1320 self.index = -1 # always -1 for non-vector ports 1321 1322 def __str__(self): 1323 return '%s.%s' % (self.simobj, self.name) 1324 1325 # for config.ini, print peer's name (not ours) 1326 def ini_str(self): 1327 return str(self.peer) 1328 1329 def __getattr__(self, attr): 1330 if attr == 'peerObj': 1331 # shorthand for proxies 1332 return self.peer.simobj 1333 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1334 (self.__class__.__name__, attr) 1335 1336 # Full connection is symmetric (both ways). Called via 1337 # SimObject.__setattr__ as a result of a port assignment, e.g., 1338 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1339 # e.g., "obj1.portA[3] = obj2.portB". 1340 def connect(self, other): 1341 if isinstance(other, VectorPortRef): 1342 # reference to plain VectorPort is implicit append 1343 other = other._get_next() 1344 if self.peer and not proxy.isproxy(self.peer): 1345 print "warning: overwriting port", self, \ 1346 "value", self.peer, "with", other 1347 self.peer.peer = None 1348 self.peer = other 1349 if proxy.isproxy(other): 1350 other.set_param_desc(PortParamDesc()) 1351 elif isinstance(other, PortRef): 1352 if other.peer is not self: 1353 other.connect(self) 1354 else: 1355 raise TypeError, \ 1356 "assigning non-port reference '%s' to port '%s'" \ 1357 % (other, self) 1358 1359 def clone(self, simobj, memo): 1360 if memo.has_key(self): 1361 return memo[self] 1362 newRef = copy.copy(self) 1363 memo[self] = newRef 1364 newRef.simobj = simobj 1365 assert(isSimObject(newRef.simobj)) 1366 if self.peer and not proxy.isproxy(self.peer): 1367 peerObj = self.peer.simobj(_memo=memo) 1368 newRef.peer = self.peer.clone(peerObj, memo) 1369 assert(not isinstance(newRef.peer, VectorPortRef)) 1370 return newRef 1371 1372 def unproxy(self, simobj): 1373 assert(simobj is self.simobj) 1374 if proxy.isproxy(self.peer): 1375 try: 1376 realPeer = self.peer.unproxy(self.simobj) 1377 except: 1378 print "Error in unproxying port '%s' of %s" % \ 1379 (self.name, self.simobj.path()) 1380 raise 1381 self.connect(realPeer) 1382 1383 # Call C++ to create corresponding port connection between C++ objects 1384 def ccConnect(self): 1385 from m5.internal.params import connectPorts 1386 1387 if self.ccConnected: # already done this 1388 return 1389 peer = self.peer 1390 if not self.peer: # nothing to connect to 1391 return 1392 try: 1393 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1394 peer.simobj.getCCObject(), peer.name, peer.index) 1395 except: 1396 print "Error connecting port %s.%s to %s.%s" % \ 1397 (self.simobj.path(), self.name, 1398 peer.simobj.path(), peer.name) 1399 raise 1400 self.ccConnected = True 1401 peer.ccConnected = True 1402 1403# A reference to an individual element of a VectorPort... much like a 1404# PortRef, but has an index. 1405class VectorPortElementRef(PortRef): 1406 def __init__(self, simobj, name, index): 1407 PortRef.__init__(self, simobj, name) 1408 self.index = index 1409 1410 def __str__(self): 1411 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1412 1413# A reference to a complete vector-valued port (not just a single element). 1414# Can be indexed to retrieve individual VectorPortElementRef instances. 1415class VectorPortRef(object): 1416 def __init__(self, simobj, name): 1417 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1418 self.simobj = simobj 1419 self.name = name 1420 self.elements = [] 1421 1422 def __str__(self): 1423 return '%s.%s[:]' % (self.simobj, self.name) 1424 1425 # for config.ini, print peer's name (not ours) 1426 def ini_str(self): 1427 return ' '.join([el.ini_str() for el in self.elements]) 1428 1429 def __getitem__(self, key): 1430 if not isinstance(key, int): 1431 raise TypeError, "VectorPort index must be integer" 1432 if key >= len(self.elements): 1433 # need to extend list 1434 ext = [VectorPortElementRef(self.simobj, self.name, i) 1435 for i in range(len(self.elements), key+1)] 1436 self.elements.extend(ext) 1437 return self.elements[key] 1438 1439 def _get_next(self): 1440 return self[len(self.elements)] 1441 1442 def __setitem__(self, key, value): 1443 if not isinstance(key, int): 1444 raise TypeError, "VectorPort index must be integer" 1445 self[key].connect(value) 1446 1447 def connect(self, other): 1448 if isinstance(other, (list, tuple)): 1449 # Assign list of port refs to vector port. 1450 # For now, append them... not sure if that's the right semantics 1451 # or if it should replace the current vector. 1452 for ref in other: 1453 self._get_next().connect(ref) 1454 else: 1455 # scalar assignment to plain VectorPort is implicit append 1456 self._get_next().connect(other) 1457 1458 def clone(self, simobj, memo): 1459 if memo.has_key(self): 1460 return memo[self] 1461 newRef = copy.copy(self) 1462 memo[self] = newRef 1463 newRef.simobj = simobj 1464 assert(isSimObject(newRef.simobj)) 1465 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 1466 return newRef 1467 1468 def unproxy(self, simobj): 1469 [el.unproxy(simobj) for el in self.elements] 1470 1471 def ccConnect(self): 1472 [el.ccConnect() for el in self.elements] 1473 1474# Port description object. Like a ParamDesc object, this represents a 1475# logical port in the SimObject class, not a particular port on a 1476# SimObject instance. The latter are represented by PortRef objects. 1477class Port(object): 1478 # Port("description") or Port(default, "description") 1479 def __init__(self, *args): 1480 if len(args) == 1: 1481 self.desc = args[0] 1482 elif len(args) == 2: 1483 self.default = args[0] 1484 self.desc = args[1] 1485 else: 1486 raise TypeError, 'wrong number of arguments' 1487 # self.name is set by SimObject class on assignment 1488 # e.g., pio_port = Port("blah") sets self.name to 'pio_port' 1489 1490 # Generate a PortRef for this port on the given SimObject with the 1491 # given name 1492 def makeRef(self, simobj): 1493 return PortRef(simobj, self.name) 1494 1495 # Connect an instance of this port (on the given SimObject with 1496 # the given name) with the port described by the supplied PortRef 1497 def connect(self, simobj, ref): 1498 self.makeRef(simobj).connect(ref) 1499 1500# VectorPort description object. Like Port, but represents a vector 1501# of connections (e.g., as on a Bus). 1502class VectorPort(Port): 1503 def __init__(self, *args): 1504 Port.__init__(self, *args) 1505 self.isVec = True 1506 1507 def makeRef(self, simobj): 1508 return VectorPortRef(simobj, self.name) 1509 1510# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 1511# proxy objects (via set_param_desc()) so that proxy error messages 1512# make sense. 1513class PortParamDesc(object): 1514 __metaclass__ = Singleton 1515 1516 ptype_str = 'Port' 1517 ptype = Port 1518 1519baseEnums = allEnums.copy() 1520baseParams = allParams.copy() 1521 1522def clear(): 1523 global allEnums, allParams 1524 1525 allEnums = baseEnums.copy() 1526 allParams = baseParams.copy() 1527 1528__all__ = ['Param', 'VectorParam', 1529 'Enum', 'Bool', 'String', 'Float', 1530 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 1531 'Int32', 'UInt32', 'Int64', 'UInt64', 1532 'Counter', 'Addr', 'Tick', 'Percent', 1533 'TcpPort', 'UdpPort', 'EthernetAddr', 1534 'IpAddress', 'IpNetmask', 'IpWithPort', 1535 'MemorySize', 'MemorySize32', 1536 'Latency', 'Frequency', 'Clock', 1537 'NetworkBandwidth', 'MemoryBandwidth', 1538 'Range', 'AddrRange', 'TickRange', 1539 'MaxAddr', 'MaxTick', 'AllMemory', 1540 'Time', 1541 'NextEthernetAddr', 'NULL', 1542 'Port', 'VectorPort'] 1543 1544import SimObject
|