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