1# Copyright (c) 2012-2014 ARM Limited 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Copyright (c) 2004-2006 The Regents of The University of Michigan 14# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 15# All rights reserved. 16# 17# Redistribution and use in source and binary forms, with or without 18# modification, are permitted provided that the following conditions are 19# met: redistributions of source code must retain the above copyright 20# notice, this list of conditions and the following disclaimer; 21# redistributions in binary form must reproduce the above copyright 22# notice, this list of conditions and the following disclaimer in the 23# documentation and/or other materials provided with the distribution; 24# neither the name of the copyright holders nor the names of its 25# contributors may be used to endorse or promote products derived from 26# this software without specific prior written permission. 27# 28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39# 40# Authors: Steve Reinhardt 41# Nathan Binkert 42# Gabe Black 43# Andreas Hansson 44 45##################################################################### 46# 47# Parameter description classes 48# 49# The _params dictionary in each class maps parameter names to either 50# a Param or a VectorParam object. These objects contain the 51# parameter description string, the parameter type, and the default 52# value (if any). The convert() method on these objects is used to 53# force whatever value is assigned to the parameter to the appropriate 54# type. 55# 56# Note that the default values are loaded into the class's attribute 57# space when the parameter dictionary is initialized (in 58# MetaSimObject._new_param()); after that point they aren't used. 59# 60##################################################################### 61 62import copy 63import datetime 64import re 65import sys 66import time 67import math 68 69import proxy 70import ticks 71from util import * 72 73def isSimObject(*args, **kwargs): 74 return SimObject.isSimObject(*args, **kwargs) 75 76def isSimObjectSequence(*args, **kwargs): 77 return SimObject.isSimObjectSequence(*args, **kwargs) 78 79def isSimObjectClass(*args, **kwargs): 80 return SimObject.isSimObjectClass(*args, **kwargs) 81 82allParams = {} 83 84class MetaParamValue(type): 85 def __new__(mcls, name, bases, dct): 86 cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 87 assert name not in allParams 88 allParams[name] = cls 89 return cls 90 91 92# Dummy base class to identify types that are legitimate for SimObject 93# parameters. 94class ParamValue(object): 95 __metaclass__ = MetaParamValue 96 cmd_line_settable = False 97 98 # Generate the code needed as a prerequisite for declaring a C++ 99 # object of this type. Typically generates one or more #include 100 # statements. Used when declaring parameters of this type. 101 @classmethod 102 def cxx_predecls(cls, code): 103 pass 104 105 # Generate the code needed as a prerequisite for including a 106 # reference to a C++ object of this type in a SWIG .i file. 107 # Typically generates one or more %import or %include statements. 108 @classmethod 109 def swig_predecls(cls, code): 110 pass 111 112 # default for printing to .ini file is regular string conversion. 113 # will be overridden in some cases 114 def ini_str(self): 115 return str(self) 116 117 # default for printing to .json file is regular string conversion. 118 # will be overridden in some cases, mostly to use native Python 119 # types where there are similar JSON types 120 def config_value(self): 121 return str(self) 122
| 1# Copyright (c) 2012-2014 ARM Limited 2# All rights reserved. 3# 4# The license below extends only to copyright in the software and shall 5# not be construed as granting a license to any other intellectual 6# property including but not limited to intellectual property relating 7# to a hardware implementation of the functionality of the software 8# licensed hereunder. You may use the software subject to the license 9# terms below provided that you ensure that this notice is replicated 10# unmodified and in its entirety in all distributions of the software, 11# modified or unmodified, in source code or in binary form. 12# 13# Copyright (c) 2004-2006 The Regents of The University of Michigan 14# Copyright (c) 2010-2011 Advanced Micro Devices, Inc. 15# All rights reserved. 16# 17# Redistribution and use in source and binary forms, with or without 18# modification, are permitted provided that the following conditions are 19# met: redistributions of source code must retain the above copyright 20# notice, this list of conditions and the following disclaimer; 21# redistributions in binary form must reproduce the above copyright 22# notice, this list of conditions and the following disclaimer in the 23# documentation and/or other materials provided with the distribution; 24# neither the name of the copyright holders nor the names of its 25# contributors may be used to endorse or promote products derived from 26# this software without specific prior written permission. 27# 28# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39# 40# Authors: Steve Reinhardt 41# Nathan Binkert 42# Gabe Black 43# Andreas Hansson 44 45##################################################################### 46# 47# Parameter description classes 48# 49# The _params dictionary in each class maps parameter names to either 50# a Param or a VectorParam object. These objects contain the 51# parameter description string, the parameter type, and the default 52# value (if any). The convert() method on these objects is used to 53# force whatever value is assigned to the parameter to the appropriate 54# type. 55# 56# Note that the default values are loaded into the class's attribute 57# space when the parameter dictionary is initialized (in 58# MetaSimObject._new_param()); after that point they aren't used. 59# 60##################################################################### 61 62import copy 63import datetime 64import re 65import sys 66import time 67import math 68 69import proxy 70import ticks 71from util import * 72 73def isSimObject(*args, **kwargs): 74 return SimObject.isSimObject(*args, **kwargs) 75 76def isSimObjectSequence(*args, **kwargs): 77 return SimObject.isSimObjectSequence(*args, **kwargs) 78 79def isSimObjectClass(*args, **kwargs): 80 return SimObject.isSimObjectClass(*args, **kwargs) 81 82allParams = {} 83 84class MetaParamValue(type): 85 def __new__(mcls, name, bases, dct): 86 cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) 87 assert name not in allParams 88 allParams[name] = cls 89 return cls 90 91 92# Dummy base class to identify types that are legitimate for SimObject 93# parameters. 94class ParamValue(object): 95 __metaclass__ = MetaParamValue 96 cmd_line_settable = False 97 98 # Generate the code needed as a prerequisite for declaring a C++ 99 # object of this type. Typically generates one or more #include 100 # statements. Used when declaring parameters of this type. 101 @classmethod 102 def cxx_predecls(cls, code): 103 pass 104 105 # Generate the code needed as a prerequisite for including a 106 # reference to a C++ object of this type in a SWIG .i file. 107 # Typically generates one or more %import or %include statements. 108 @classmethod 109 def swig_predecls(cls, code): 110 pass 111 112 # default for printing to .ini file is regular string conversion. 113 # will be overridden in some cases 114 def ini_str(self): 115 return str(self) 116 117 # default for printing to .json file is regular string conversion. 118 # will be overridden in some cases, mostly to use native Python 119 # types where there are similar JSON types 120 def config_value(self): 121 return str(self) 122
|
| 123 # Prerequisites for .ini parsing with cxx_ini_parse 124 @classmethod 125 def cxx_ini_predecls(cls, code): 126 pass 127 128 # parse a .ini file entry for this param from string expression 129 # src into lvalue dest (of the param's C++ type) 130 @classmethod 131 def cxx_ini_parse(cls, code, src, dest, ret): 132 code('// Unhandled param type: %s' % cls.__name__) 133 code('%s false;' % ret) 134
|
123 # allows us to blithely call unproxy() on things without checking 124 # if they're really proxies or not 125 def unproxy(self, base): 126 return self 127 128 # Produce a human readable version of the stored value 129 def pretty_print(self, value): 130 return str(value) 131 132# Regular parameter description. 133class ParamDesc(object): 134 def __init__(self, ptype_str, ptype, *args, **kwargs): 135 self.ptype_str = ptype_str 136 # remember ptype only if it is provided 137 if ptype != None: 138 self.ptype = ptype 139 140 if args: 141 if len(args) == 1: 142 self.desc = args[0] 143 elif len(args) == 2: 144 self.default = args[0] 145 self.desc = args[1] 146 else: 147 raise TypeError, 'too many arguments' 148 149 if kwargs.has_key('desc'): 150 assert(not hasattr(self, 'desc')) 151 self.desc = kwargs['desc'] 152 del kwargs['desc'] 153 154 if kwargs.has_key('default'): 155 assert(not hasattr(self, 'default')) 156 self.default = kwargs['default'] 157 del kwargs['default'] 158 159 if kwargs: 160 raise TypeError, 'extra unknown kwargs %s' % kwargs 161 162 if not hasattr(self, 'desc'): 163 raise TypeError, 'desc attribute missing' 164 165 def __getattr__(self, attr): 166 if attr == 'ptype': 167 ptype = SimObject.allClasses[self.ptype_str] 168 assert isSimObjectClass(ptype) 169 self.ptype = ptype 170 return ptype 171 172 raise AttributeError, "'%s' object has no attribute '%s'" % \ 173 (type(self).__name__, attr) 174 175 def example_str(self): 176 if hasattr(self.ptype, "ex_str"): 177 return self.ptype.ex_str 178 else: 179 return self.ptype_str 180 181 # Is the param available to be exposed on the command line 182 def isCmdLineSettable(self): 183 if hasattr(self.ptype, "cmd_line_settable"): 184 return self.ptype.cmd_line_settable 185 else: 186 return False 187 188 def convert(self, value): 189 if isinstance(value, proxy.BaseProxy): 190 value.set_param_desc(self) 191 return value 192 if not hasattr(self, 'ptype') and isNullPointer(value): 193 # deferred evaluation of SimObject; continue to defer if 194 # we're just assigning a null pointer 195 return value 196 if isinstance(value, self.ptype): 197 return value 198 if isNullPointer(value) and isSimObjectClass(self.ptype): 199 return value 200 return self.ptype(value) 201 202 def pretty_print(self, value): 203 if isinstance(value, proxy.BaseProxy): 204 return str(value) 205 if isNullPointer(value): 206 return NULL 207 return self.ptype(value).pretty_print(value) 208 209 def cxx_predecls(self, code): 210 code('#include <cstddef>') 211 self.ptype.cxx_predecls(code) 212 213 def swig_predecls(self, code): 214 self.ptype.swig_predecls(code) 215 216 def cxx_decl(self, code): 217 code('${{self.ptype.cxx_type}} ${{self.name}};') 218 219# Vector-valued parameter description. Just like ParamDesc, except 220# that the value is a vector (list) of the specified type instead of a 221# single value. 222 223class VectorParamValue(list): 224 __metaclass__ = MetaParamValue 225 def __setattr__(self, attr, value): 226 raise AttributeError, \ 227 "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 228 229 def config_value(self): 230 return [v.config_value() for v in self] 231 232 def ini_str(self): 233 return ' '.join([v.ini_str() for v in self]) 234 235 def getValue(self): 236 return [ v.getValue() for v in self ] 237 238 def unproxy(self, base): 239 if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 240 return self[0].unproxy(base) 241 else: 242 return [v.unproxy(base) for v in self] 243 244class SimObjectVector(VectorParamValue): 245 # support clone operation 246 def __call__(self, **kwargs): 247 return SimObjectVector([v(**kwargs) for v in self]) 248 249 def clear_parent(self, old_parent): 250 for v in self: 251 v.clear_parent(old_parent) 252 253 def set_parent(self, parent, name): 254 if len(self) == 1: 255 self[0].set_parent(parent, name) 256 else: 257 width = int(math.ceil(math.log(len(self))/math.log(10))) 258 for i,v in enumerate(self): 259 v.set_parent(parent, "%s%0*d" % (name, width, i)) 260 261 def has_parent(self): 262 return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 263 264 # return 'cpu0 cpu1' etc. for print_ini() 265 def get_name(self): 266 return ' '.join([v._name for v in self]) 267 268 # By iterating through the constituent members of the vector here 269 # we can nicely handle iterating over all a SimObject's children 270 # without having to provide lots of special functions on 271 # SimObjectVector directly. 272 def descendants(self): 273 for v in self: 274 for obj in v.descendants(): 275 yield obj 276 277 def get_config_as_dict(self): 278 a = [] 279 for v in self: 280 a.append(v.get_config_as_dict()) 281 return a 282 283 # If we are replacing an item in the vector, make sure to set the 284 # parent reference of the new SimObject to be the same as the parent 285 # of the SimObject being replaced. Useful to have if we created 286 # a SimObjectVector of temporary objects that will be modified later in 287 # configuration scripts. 288 def __setitem__(self, key, value): 289 val = self[key] 290 if value.has_parent(): 291 warn("SimObject %s already has a parent" % value.get_name() +\ 292 " that is being overwritten by a SimObjectVector") 293 value.set_parent(val.get_parent(), val._name) 294 super(SimObjectVector, self).__setitem__(key, value) 295 296 # Enumerate the params of each member of the SimObject vector. Creates 297 # strings that will allow indexing into the vector by the python code and 298 # allow it to be specified on the command line. 299 def enumerateParams(self, flags_dict = {}, 300 cmd_line_str = "", 301 access_str = ""): 302 if hasattr(self, "_paramEnumed"): 303 print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 304 else: 305 x = 0 306 for vals in self: 307 # Each entry in the SimObjectVector should be an 308 # instance of a SimObject 309 flags_dict = vals.enumerateParams(flags_dict, 310 cmd_line_str + "%d." % x, 311 access_str + "[%d]." % x) 312 x = x + 1 313 314 return flags_dict 315 316class VectorParamDesc(ParamDesc): 317 # Convert assigned value to appropriate type. If the RHS is not a 318 # list or tuple, it generates a single-element list. 319 def convert(self, value): 320 if isinstance(value, (list, tuple)): 321 # list: coerce each element into new list 322 tmp_list = [ ParamDesc.convert(self, v) for v in value ] 323 elif isinstance(value, str): 324 # If input is a csv string 325 tmp_list = [ ParamDesc.convert(self, v) \ 326 for v in value.strip('[').strip(']').split(',') ] 327 else: 328 # singleton: coerce to a single-element list 329 tmp_list = [ ParamDesc.convert(self, value) ] 330 331 if isSimObjectSequence(tmp_list): 332 return SimObjectVector(tmp_list) 333 else: 334 return VectorParamValue(tmp_list) 335 336 # Produce a human readable example string that describes 337 # how to set this vector parameter in the absence of a default 338 # value. 339 def example_str(self): 340 s = super(VectorParamDesc, self).example_str() 341 help_str = "[" + s + "," + s + ", ...]" 342 return help_str 343 344 # Produce a human readable representation of the value of this vector param. 345 def pretty_print(self, value): 346 if isinstance(value, (list, tuple)): 347 tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 348 elif isinstance(value, str): 349 tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 350 else: 351 tmp_list = [ ParamDesc.pretty_print(self, value) ] 352 353 return tmp_list 354 355 # This is a helper function for the new config system 356 def __call__(self, value): 357 if isinstance(value, (list, tuple)): 358 # list: coerce each element into new list 359 tmp_list = [ ParamDesc.convert(self, v) for v in value ] 360 elif isinstance(value, str): 361 # If input is a csv string 362 tmp_list = [ ParamDesc.convert(self, v) \ 363 for v in value.strip('[').strip(']').split(',') ] 364 else: 365 # singleton: coerce to a single-element list 366 tmp_list = [ ParamDesc.convert(self, value) ] 367 368 return VectorParamValue(tmp_list) 369 370 def swig_module_name(self): 371 return "%s_vector" % self.ptype_str 372 373 def swig_predecls(self, code): 374 code('%import "${{self.swig_module_name()}}.i"') 375 376 def swig_decl(self, code): 377 code('%module(package="m5.internal") ${{self.swig_module_name()}}') 378 code('%{') 379 self.ptype.cxx_predecls(code) 380 code('%}') 381 code() 382 # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 383 code('%include "std_container.i"') 384 code() 385 self.ptype.swig_predecls(code) 386 code() 387 code('%include "std_vector.i"') 388 code() 389 390 ptype = self.ptype_str 391 cxx_type = self.ptype.cxx_type 392 393 code('%template(vector_$ptype) std::vector< $cxx_type >;') 394 395 def cxx_predecls(self, code): 396 code('#include <vector>') 397 self.ptype.cxx_predecls(code) 398 399 def cxx_decl(self, code): 400 code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 401 402class ParamFactory(object): 403 def __init__(self, param_desc_class, ptype_str = None): 404 self.param_desc_class = param_desc_class 405 self.ptype_str = ptype_str 406 407 def __getattr__(self, attr): 408 if self.ptype_str: 409 attr = self.ptype_str + '.' + attr 410 return ParamFactory(self.param_desc_class, attr) 411 412 # E.g., Param.Int(5, "number of widgets") 413 def __call__(self, *args, **kwargs): 414 ptype = None 415 try: 416 ptype = allParams[self.ptype_str] 417 except KeyError: 418 # if name isn't defined yet, assume it's a SimObject, and 419 # try to resolve it later 420 pass 421 return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 422 423Param = ParamFactory(ParamDesc) 424VectorParam = ParamFactory(VectorParamDesc) 425 426##################################################################### 427# 428# Parameter Types 429# 430# Though native Python types could be used to specify parameter types 431# (the 'ptype' field of the Param and VectorParam classes), it's more 432# flexible to define our own set of types. This gives us more control 433# over how Python expressions are converted to values (via the 434# __init__() constructor) and how these values are printed out (via 435# the __str__() conversion method). 436# 437##################################################################### 438 439# String-valued parameter. Just mixin the ParamValue class with the 440# built-in str class. 441class String(ParamValue,str): 442 cxx_type = 'std::string' 443 cmd_line_settable = True 444 445 @classmethod 446 def cxx_predecls(self, code): 447 code('#include <string>') 448 449 @classmethod 450 def swig_predecls(cls, code): 451 code('%include "std_string.i"') 452 453 def __call__(self, value): 454 self = value 455 return value 456
| 135 # allows us to blithely call unproxy() on things without checking 136 # if they're really proxies or not 137 def unproxy(self, base): 138 return self 139 140 # Produce a human readable version of the stored value 141 def pretty_print(self, value): 142 return str(value) 143 144# Regular parameter description. 145class ParamDesc(object): 146 def __init__(self, ptype_str, ptype, *args, **kwargs): 147 self.ptype_str = ptype_str 148 # remember ptype only if it is provided 149 if ptype != None: 150 self.ptype = ptype 151 152 if args: 153 if len(args) == 1: 154 self.desc = args[0] 155 elif len(args) == 2: 156 self.default = args[0] 157 self.desc = args[1] 158 else: 159 raise TypeError, 'too many arguments' 160 161 if kwargs.has_key('desc'): 162 assert(not hasattr(self, 'desc')) 163 self.desc = kwargs['desc'] 164 del kwargs['desc'] 165 166 if kwargs.has_key('default'): 167 assert(not hasattr(self, 'default')) 168 self.default = kwargs['default'] 169 del kwargs['default'] 170 171 if kwargs: 172 raise TypeError, 'extra unknown kwargs %s' % kwargs 173 174 if not hasattr(self, 'desc'): 175 raise TypeError, 'desc attribute missing' 176 177 def __getattr__(self, attr): 178 if attr == 'ptype': 179 ptype = SimObject.allClasses[self.ptype_str] 180 assert isSimObjectClass(ptype) 181 self.ptype = ptype 182 return ptype 183 184 raise AttributeError, "'%s' object has no attribute '%s'" % \ 185 (type(self).__name__, attr) 186 187 def example_str(self): 188 if hasattr(self.ptype, "ex_str"): 189 return self.ptype.ex_str 190 else: 191 return self.ptype_str 192 193 # Is the param available to be exposed on the command line 194 def isCmdLineSettable(self): 195 if hasattr(self.ptype, "cmd_line_settable"): 196 return self.ptype.cmd_line_settable 197 else: 198 return False 199 200 def convert(self, value): 201 if isinstance(value, proxy.BaseProxy): 202 value.set_param_desc(self) 203 return value 204 if not hasattr(self, 'ptype') and isNullPointer(value): 205 # deferred evaluation of SimObject; continue to defer if 206 # we're just assigning a null pointer 207 return value 208 if isinstance(value, self.ptype): 209 return value 210 if isNullPointer(value) and isSimObjectClass(self.ptype): 211 return value 212 return self.ptype(value) 213 214 def pretty_print(self, value): 215 if isinstance(value, proxy.BaseProxy): 216 return str(value) 217 if isNullPointer(value): 218 return NULL 219 return self.ptype(value).pretty_print(value) 220 221 def cxx_predecls(self, code): 222 code('#include <cstddef>') 223 self.ptype.cxx_predecls(code) 224 225 def swig_predecls(self, code): 226 self.ptype.swig_predecls(code) 227 228 def cxx_decl(self, code): 229 code('${{self.ptype.cxx_type}} ${{self.name}};') 230 231# Vector-valued parameter description. Just like ParamDesc, except 232# that the value is a vector (list) of the specified type instead of a 233# single value. 234 235class VectorParamValue(list): 236 __metaclass__ = MetaParamValue 237 def __setattr__(self, attr, value): 238 raise AttributeError, \ 239 "Not allowed to set %s on '%s'" % (attr, type(self).__name__) 240 241 def config_value(self): 242 return [v.config_value() for v in self] 243 244 def ini_str(self): 245 return ' '.join([v.ini_str() for v in self]) 246 247 def getValue(self): 248 return [ v.getValue() for v in self ] 249 250 def unproxy(self, base): 251 if len(self) == 1 and isinstance(self[0], proxy.AllProxy): 252 return self[0].unproxy(base) 253 else: 254 return [v.unproxy(base) for v in self] 255 256class SimObjectVector(VectorParamValue): 257 # support clone operation 258 def __call__(self, **kwargs): 259 return SimObjectVector([v(**kwargs) for v in self]) 260 261 def clear_parent(self, old_parent): 262 for v in self: 263 v.clear_parent(old_parent) 264 265 def set_parent(self, parent, name): 266 if len(self) == 1: 267 self[0].set_parent(parent, name) 268 else: 269 width = int(math.ceil(math.log(len(self))/math.log(10))) 270 for i,v in enumerate(self): 271 v.set_parent(parent, "%s%0*d" % (name, width, i)) 272 273 def has_parent(self): 274 return reduce(lambda x,y: x and y, [v.has_parent() for v in self]) 275 276 # return 'cpu0 cpu1' etc. for print_ini() 277 def get_name(self): 278 return ' '.join([v._name for v in self]) 279 280 # By iterating through the constituent members of the vector here 281 # we can nicely handle iterating over all a SimObject's children 282 # without having to provide lots of special functions on 283 # SimObjectVector directly. 284 def descendants(self): 285 for v in self: 286 for obj in v.descendants(): 287 yield obj 288 289 def get_config_as_dict(self): 290 a = [] 291 for v in self: 292 a.append(v.get_config_as_dict()) 293 return a 294 295 # If we are replacing an item in the vector, make sure to set the 296 # parent reference of the new SimObject to be the same as the parent 297 # of the SimObject being replaced. Useful to have if we created 298 # a SimObjectVector of temporary objects that will be modified later in 299 # configuration scripts. 300 def __setitem__(self, key, value): 301 val = self[key] 302 if value.has_parent(): 303 warn("SimObject %s already has a parent" % value.get_name() +\ 304 " that is being overwritten by a SimObjectVector") 305 value.set_parent(val.get_parent(), val._name) 306 super(SimObjectVector, self).__setitem__(key, value) 307 308 # Enumerate the params of each member of the SimObject vector. Creates 309 # strings that will allow indexing into the vector by the python code and 310 # allow it to be specified on the command line. 311 def enumerateParams(self, flags_dict = {}, 312 cmd_line_str = "", 313 access_str = ""): 314 if hasattr(self, "_paramEnumed"): 315 print "Cycle detected enumerating params at %s?!" % (cmd_line_str) 316 else: 317 x = 0 318 for vals in self: 319 # Each entry in the SimObjectVector should be an 320 # instance of a SimObject 321 flags_dict = vals.enumerateParams(flags_dict, 322 cmd_line_str + "%d." % x, 323 access_str + "[%d]." % x) 324 x = x + 1 325 326 return flags_dict 327 328class VectorParamDesc(ParamDesc): 329 # Convert assigned value to appropriate type. If the RHS is not a 330 # list or tuple, it generates a single-element list. 331 def convert(self, value): 332 if isinstance(value, (list, tuple)): 333 # list: coerce each element into new list 334 tmp_list = [ ParamDesc.convert(self, v) for v in value ] 335 elif isinstance(value, str): 336 # If input is a csv string 337 tmp_list = [ ParamDesc.convert(self, v) \ 338 for v in value.strip('[').strip(']').split(',') ] 339 else: 340 # singleton: coerce to a single-element list 341 tmp_list = [ ParamDesc.convert(self, value) ] 342 343 if isSimObjectSequence(tmp_list): 344 return SimObjectVector(tmp_list) 345 else: 346 return VectorParamValue(tmp_list) 347 348 # Produce a human readable example string that describes 349 # how to set this vector parameter in the absence of a default 350 # value. 351 def example_str(self): 352 s = super(VectorParamDesc, self).example_str() 353 help_str = "[" + s + "," + s + ", ...]" 354 return help_str 355 356 # Produce a human readable representation of the value of this vector param. 357 def pretty_print(self, value): 358 if isinstance(value, (list, tuple)): 359 tmp_list = [ ParamDesc.pretty_print(self, v) for v in value ] 360 elif isinstance(value, str): 361 tmp_list = [ ParamDesc.pretty_print(self, v) for v in value.split(',') ] 362 else: 363 tmp_list = [ ParamDesc.pretty_print(self, value) ] 364 365 return tmp_list 366 367 # This is a helper function for the new config system 368 def __call__(self, value): 369 if isinstance(value, (list, tuple)): 370 # list: coerce each element into new list 371 tmp_list = [ ParamDesc.convert(self, v) for v in value ] 372 elif isinstance(value, str): 373 # If input is a csv string 374 tmp_list = [ ParamDesc.convert(self, v) \ 375 for v in value.strip('[').strip(']').split(',') ] 376 else: 377 # singleton: coerce to a single-element list 378 tmp_list = [ ParamDesc.convert(self, value) ] 379 380 return VectorParamValue(tmp_list) 381 382 def swig_module_name(self): 383 return "%s_vector" % self.ptype_str 384 385 def swig_predecls(self, code): 386 code('%import "${{self.swig_module_name()}}.i"') 387 388 def swig_decl(self, code): 389 code('%module(package="m5.internal") ${{self.swig_module_name()}}') 390 code('%{') 391 self.ptype.cxx_predecls(code) 392 code('%}') 393 code() 394 # Make sure the SWIGPY_SLICE_ARG is defined through this inclusion 395 code('%include "std_container.i"') 396 code() 397 self.ptype.swig_predecls(code) 398 code() 399 code('%include "std_vector.i"') 400 code() 401 402 ptype = self.ptype_str 403 cxx_type = self.ptype.cxx_type 404 405 code('%template(vector_$ptype) std::vector< $cxx_type >;') 406 407 def cxx_predecls(self, code): 408 code('#include <vector>') 409 self.ptype.cxx_predecls(code) 410 411 def cxx_decl(self, code): 412 code('std::vector< ${{self.ptype.cxx_type}} > ${{self.name}};') 413 414class ParamFactory(object): 415 def __init__(self, param_desc_class, ptype_str = None): 416 self.param_desc_class = param_desc_class 417 self.ptype_str = ptype_str 418 419 def __getattr__(self, attr): 420 if self.ptype_str: 421 attr = self.ptype_str + '.' + attr 422 return ParamFactory(self.param_desc_class, attr) 423 424 # E.g., Param.Int(5, "number of widgets") 425 def __call__(self, *args, **kwargs): 426 ptype = None 427 try: 428 ptype = allParams[self.ptype_str] 429 except KeyError: 430 # if name isn't defined yet, assume it's a SimObject, and 431 # try to resolve it later 432 pass 433 return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs) 434 435Param = ParamFactory(ParamDesc) 436VectorParam = ParamFactory(VectorParamDesc) 437 438##################################################################### 439# 440# Parameter Types 441# 442# Though native Python types could be used to specify parameter types 443# (the 'ptype' field of the Param and VectorParam classes), it's more 444# flexible to define our own set of types. This gives us more control 445# over how Python expressions are converted to values (via the 446# __init__() constructor) and how these values are printed out (via 447# the __str__() conversion method). 448# 449##################################################################### 450 451# String-valued parameter. Just mixin the ParamValue class with the 452# built-in str class. 453class String(ParamValue,str): 454 cxx_type = 'std::string' 455 cmd_line_settable = True 456 457 @classmethod 458 def cxx_predecls(self, code): 459 code('#include <string>') 460 461 @classmethod 462 def swig_predecls(cls, code): 463 code('%include "std_string.i"') 464 465 def __call__(self, value): 466 self = value 467 return value 468
|
| 469 @classmethod 470 def cxx_ini_parse(self, code, src, dest, ret): 471 code('%s = %s;' % (dest, src)) 472 code('%s true;' % ret) 473
|
457 def getValue(self): 458 return self 459 460# superclass for "numeric" parameter values, to emulate math 461# operations in a type-safe way. e.g., a Latency times an int returns 462# a new Latency object. 463class NumericParamValue(ParamValue): 464 def __str__(self): 465 return str(self.value) 466 467 def __float__(self): 468 return float(self.value) 469 470 def __long__(self): 471 return long(self.value) 472 473 def __int__(self): 474 return int(self.value) 475 476 # hook for bounds checking 477 def _check(self): 478 return 479 480 def __mul__(self, other): 481 newobj = self.__class__(self) 482 newobj.value *= other 483 newobj._check() 484 return newobj 485 486 __rmul__ = __mul__ 487 488 def __div__(self, other): 489 newobj = self.__class__(self) 490 newobj.value /= other 491 newobj._check() 492 return newobj 493 494 def __sub__(self, other): 495 newobj = self.__class__(self) 496 newobj.value -= other 497 newobj._check() 498 return newobj 499 500 def config_value(self): 501 return self.value 502
| 474 def getValue(self): 475 return self 476 477# superclass for "numeric" parameter values, to emulate math 478# operations in a type-safe way. e.g., a Latency times an int returns 479# a new Latency object. 480class NumericParamValue(ParamValue): 481 def __str__(self): 482 return str(self.value) 483 484 def __float__(self): 485 return float(self.value) 486 487 def __long__(self): 488 return long(self.value) 489 490 def __int__(self): 491 return int(self.value) 492 493 # hook for bounds checking 494 def _check(self): 495 return 496 497 def __mul__(self, other): 498 newobj = self.__class__(self) 499 newobj.value *= other 500 newobj._check() 501 return newobj 502 503 __rmul__ = __mul__ 504 505 def __div__(self, other): 506 newobj = self.__class__(self) 507 newobj.value /= other 508 newobj._check() 509 return newobj 510 511 def __sub__(self, other): 512 newobj = self.__class__(self) 513 newobj.value -= other 514 newobj._check() 515 return newobj 516 517 def config_value(self): 518 return self.value 519
|
| 520 @classmethod 521 def cxx_ini_predecls(cls, code): 522 # Assume that base/str.hh will be included anyway 523 # code('#include "base/str.hh"') 524 pass 525 526 # The default for parsing PODs from an .ini entry is to extract from an 527 # istringstream and let overloading choose the right type according to 528 # the dest type. 529 @classmethod 530 def cxx_ini_parse(self, code, src, dest, ret): 531 code('%s to_number(%s, %s);' % (ret, src, dest)) 532
|
503# Metaclass for bounds-checked integer parameters. See CheckedInt. 504class CheckedIntType(MetaParamValue): 505 def __init__(cls, name, bases, dict): 506 super(CheckedIntType, cls).__init__(name, bases, dict) 507 508 # CheckedInt is an abstract base class, so we actually don't 509 # want to do any processing on it... the rest of this code is 510 # just for classes that derive from CheckedInt. 511 if name == 'CheckedInt': 512 return 513 514 if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 515 if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 516 panic("CheckedInt subclass %s must define either\n" \ 517 " 'min' and 'max' or 'size' and 'unsigned'\n", 518 name); 519 if cls.unsigned: 520 cls.min = 0 521 cls.max = 2 ** cls.size - 1 522 else: 523 cls.min = -(2 ** (cls.size - 1)) 524 cls.max = (2 ** (cls.size - 1)) - 1 525 526# Abstract superclass for bounds-checked integer parameters. This 527# class is subclassed to generate parameter classes with specific 528# bounds. Initialization of the min and max bounds is done in the 529# metaclass CheckedIntType.__init__. 530class CheckedInt(NumericParamValue): 531 __metaclass__ = CheckedIntType 532 cmd_line_settable = True 533 534 def _check(self): 535 if not self.min <= self.value <= self.max: 536 raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 537 (self.min, self.value, self.max) 538 539 def __init__(self, value): 540 if isinstance(value, str): 541 self.value = convert.toInteger(value) 542 elif isinstance(value, (int, long, float, NumericParamValue)): 543 self.value = long(value) 544 else: 545 raise TypeError, "Can't convert object of type %s to CheckedInt" \ 546 % type(value).__name__ 547 self._check() 548 549 def __call__(self, value): 550 self.__init__(value) 551 return value 552 553 @classmethod 554 def cxx_predecls(cls, code): 555 # most derived types require this, so we just do it here once 556 code('#include "base/types.hh"') 557 558 @classmethod 559 def swig_predecls(cls, code): 560 # most derived types require this, so we just do it here once 561 code('%import "stdint.i"') 562 code('%import "base/types.hh"') 563 564 def getValue(self): 565 return long(self.value) 566 567class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 568class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 569 570class Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 571class UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 572class Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 573class UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 574class Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 575class UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 576class Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 577class UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 578 579class Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 580class Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 581class TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 582class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 583 584class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 585 586class Cycles(CheckedInt): 587 cxx_type = 'Cycles' 588 size = 64 589 unsigned = True 590 591 def getValue(self): 592 from m5.internal.core import Cycles 593 return Cycles(self.value) 594
| 533# Metaclass for bounds-checked integer parameters. See CheckedInt. 534class CheckedIntType(MetaParamValue): 535 def __init__(cls, name, bases, dict): 536 super(CheckedIntType, cls).__init__(name, bases, dict) 537 538 # CheckedInt is an abstract base class, so we actually don't 539 # want to do any processing on it... the rest of this code is 540 # just for classes that derive from CheckedInt. 541 if name == 'CheckedInt': 542 return 543 544 if not (hasattr(cls, 'min') and hasattr(cls, 'max')): 545 if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): 546 panic("CheckedInt subclass %s must define either\n" \ 547 " 'min' and 'max' or 'size' and 'unsigned'\n", 548 name); 549 if cls.unsigned: 550 cls.min = 0 551 cls.max = 2 ** cls.size - 1 552 else: 553 cls.min = -(2 ** (cls.size - 1)) 554 cls.max = (2 ** (cls.size - 1)) - 1 555 556# Abstract superclass for bounds-checked integer parameters. This 557# class is subclassed to generate parameter classes with specific 558# bounds. Initialization of the min and max bounds is done in the 559# metaclass CheckedIntType.__init__. 560class CheckedInt(NumericParamValue): 561 __metaclass__ = CheckedIntType 562 cmd_line_settable = True 563 564 def _check(self): 565 if not self.min <= self.value <= self.max: 566 raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ 567 (self.min, self.value, self.max) 568 569 def __init__(self, value): 570 if isinstance(value, str): 571 self.value = convert.toInteger(value) 572 elif isinstance(value, (int, long, float, NumericParamValue)): 573 self.value = long(value) 574 else: 575 raise TypeError, "Can't convert object of type %s to CheckedInt" \ 576 % type(value).__name__ 577 self._check() 578 579 def __call__(self, value): 580 self.__init__(value) 581 return value 582 583 @classmethod 584 def cxx_predecls(cls, code): 585 # most derived types require this, so we just do it here once 586 code('#include "base/types.hh"') 587 588 @classmethod 589 def swig_predecls(cls, code): 590 # most derived types require this, so we just do it here once 591 code('%import "stdint.i"') 592 code('%import "base/types.hh"') 593 594 def getValue(self): 595 return long(self.value) 596 597class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = False 598class Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = True 599 600class Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = False 601class UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = True 602class Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = False 603class UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 604class Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = False 605class UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = True 606class Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = False 607class UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = True 608 609class Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = True 610class Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = True 611class TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 612class UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = True 613 614class Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100 615 616class Cycles(CheckedInt): 617 cxx_type = 'Cycles' 618 size = 64 619 unsigned = True 620 621 def getValue(self): 622 from m5.internal.core import Cycles 623 return Cycles(self.value) 624
|
| 625 @classmethod 626 def cxx_ini_predecls(cls, code): 627 # Assume that base/str.hh will be included anyway 628 # code('#include "base/str.hh"') 629 pass 630 631 @classmethod 632 def cxx_ini_parse(cls, code, src, dest, ret): 633 code('uint64_t _temp;') 634 code('bool _ret = to_number(%s, _temp);' % src) 635 code('if (_ret)') 636 code(' %s = Cycles(_temp);' % dest) 637 code('%s _ret;' % ret) 638
|
595class Float(ParamValue, float): 596 cxx_type = 'double' 597 cmdLineSettable = True 598 599 def __init__(self, value): 600 if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 601 self.value = float(value) 602 else: 603 raise TypeError, "Can't convert object of type %s to Float" \ 604 % type(value).__name__ 605 606 def __call__(self, value): 607 self.__init__(value) 608 return value 609 610 def getValue(self): 611 return float(self.value) 612 613 def config_value(self): 614 return self 615
| 639class Float(ParamValue, float): 640 cxx_type = 'double' 641 cmdLineSettable = True 642 643 def __init__(self, value): 644 if isinstance(value, (int, long, float, NumericParamValue, Float, str)): 645 self.value = float(value) 646 else: 647 raise TypeError, "Can't convert object of type %s to Float" \ 648 % type(value).__name__ 649 650 def __call__(self, value): 651 self.__init__(value) 652 return value 653 654 def getValue(self): 655 return float(self.value) 656 657 def config_value(self): 658 return self 659
|
| 660 @classmethod 661 def cxx_ini_predecls(cls, code): 662 code('#include <sstream>') 663 664 @classmethod 665 def cxx_ini_parse(self, code, src, dest, ret): 666 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 667
|
616class MemorySize(CheckedInt): 617 cxx_type = 'uint64_t' 618 ex_str = '512MB' 619 size = 64 620 unsigned = True 621 def __init__(self, value): 622 if isinstance(value, MemorySize): 623 self.value = value.value 624 else: 625 self.value = convert.toMemorySize(value) 626 self._check() 627 628class MemorySize32(CheckedInt): 629 cxx_type = 'uint32_t' 630 ex_str = '512MB' 631 size = 32 632 unsigned = True 633 def __init__(self, value): 634 if isinstance(value, MemorySize): 635 self.value = value.value 636 else: 637 self.value = convert.toMemorySize(value) 638 self._check() 639 640class Addr(CheckedInt): 641 cxx_type = 'Addr' 642 size = 64 643 unsigned = True 644 def __init__(self, value): 645 if isinstance(value, Addr): 646 self.value = value.value 647 else: 648 try: 649 # Often addresses are referred to with sizes. Ex: A device 650 # base address is at "512MB". Use toMemorySize() to convert 651 # these into addresses. If the address is not specified with a 652 # "size", an exception will occur and numeric translation will 653 # proceed below. 654 self.value = convert.toMemorySize(value) 655 except (TypeError, ValueError): 656 # Convert number to string and use long() to do automatic 657 # base conversion (requires base=0 for auto-conversion) 658 self.value = long(str(value), base=0) 659 660 self._check() 661 def __add__(self, other): 662 if isinstance(other, Addr): 663 return self.value + other.value 664 else: 665 return self.value + other 666 def pretty_print(self, value): 667 try: 668 val = convert.toMemorySize(value) 669 except TypeError: 670 val = long(value) 671 return "0x%x" % long(val) 672 673class AddrRange(ParamValue): 674 cxx_type = 'AddrRange' 675 676 def __init__(self, *args, **kwargs): 677 # Disable interleaving by default 678 self.intlvHighBit = 0 679 self.intlvBits = 0 680 self.intlvMatch = 0 681 682 def handle_kwargs(self, kwargs): 683 # An address range needs to have an upper limit, specified 684 # either explicitly with an end, or as an offset using the 685 # size keyword. 686 if 'end' in kwargs: 687 self.end = Addr(kwargs.pop('end')) 688 elif 'size' in kwargs: 689 self.end = self.start + Addr(kwargs.pop('size')) - 1 690 else: 691 raise TypeError, "Either end or size must be specified" 692 693 # Now on to the optional bit 694 if 'intlvHighBit' in kwargs: 695 self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 696 if 'intlvBits' in kwargs: 697 self.intlvBits = int(kwargs.pop('intlvBits')) 698 if 'intlvMatch' in kwargs: 699 self.intlvMatch = int(kwargs.pop('intlvMatch')) 700 701 if len(args) == 0: 702 self.start = Addr(kwargs.pop('start')) 703 handle_kwargs(self, kwargs) 704 705 elif len(args) == 1: 706 if kwargs: 707 self.start = Addr(args[0]) 708 handle_kwargs(self, kwargs) 709 elif isinstance(args[0], (list, tuple)): 710 self.start = Addr(args[0][0]) 711 self.end = Addr(args[0][1]) 712 else: 713 self.start = Addr(0) 714 self.end = Addr(args[0]) - 1 715 716 elif len(args) == 2: 717 self.start = Addr(args[0]) 718 self.end = Addr(args[1]) 719 else: 720 raise TypeError, "Too many arguments specified" 721 722 if kwargs: 723 raise TypeError, "Too many keywords: %s" % kwargs.keys() 724 725 def __str__(self): 726 return '%s:%s' % (self.start, self.end) 727 728 def size(self): 729 # Divide the size by the size of the interleaving slice 730 return (long(self.end) - long(self.start) + 1) >> self.intlvBits 731 732 @classmethod 733 def cxx_predecls(cls, code): 734 Addr.cxx_predecls(code) 735 code('#include "base/addr_range.hh"') 736 737 @classmethod 738 def swig_predecls(cls, code): 739 Addr.swig_predecls(code) 740
| 668class MemorySize(CheckedInt): 669 cxx_type = 'uint64_t' 670 ex_str = '512MB' 671 size = 64 672 unsigned = True 673 def __init__(self, value): 674 if isinstance(value, MemorySize): 675 self.value = value.value 676 else: 677 self.value = convert.toMemorySize(value) 678 self._check() 679 680class MemorySize32(CheckedInt): 681 cxx_type = 'uint32_t' 682 ex_str = '512MB' 683 size = 32 684 unsigned = True 685 def __init__(self, value): 686 if isinstance(value, MemorySize): 687 self.value = value.value 688 else: 689 self.value = convert.toMemorySize(value) 690 self._check() 691 692class Addr(CheckedInt): 693 cxx_type = 'Addr' 694 size = 64 695 unsigned = True 696 def __init__(self, value): 697 if isinstance(value, Addr): 698 self.value = value.value 699 else: 700 try: 701 # Often addresses are referred to with sizes. Ex: A device 702 # base address is at "512MB". Use toMemorySize() to convert 703 # these into addresses. If the address is not specified with a 704 # "size", an exception will occur and numeric translation will 705 # proceed below. 706 self.value = convert.toMemorySize(value) 707 except (TypeError, ValueError): 708 # Convert number to string and use long() to do automatic 709 # base conversion (requires base=0 for auto-conversion) 710 self.value = long(str(value), base=0) 711 712 self._check() 713 def __add__(self, other): 714 if isinstance(other, Addr): 715 return self.value + other.value 716 else: 717 return self.value + other 718 def pretty_print(self, value): 719 try: 720 val = convert.toMemorySize(value) 721 except TypeError: 722 val = long(value) 723 return "0x%x" % long(val) 724 725class AddrRange(ParamValue): 726 cxx_type = 'AddrRange' 727 728 def __init__(self, *args, **kwargs): 729 # Disable interleaving by default 730 self.intlvHighBit = 0 731 self.intlvBits = 0 732 self.intlvMatch = 0 733 734 def handle_kwargs(self, kwargs): 735 # An address range needs to have an upper limit, specified 736 # either explicitly with an end, or as an offset using the 737 # size keyword. 738 if 'end' in kwargs: 739 self.end = Addr(kwargs.pop('end')) 740 elif 'size' in kwargs: 741 self.end = self.start + Addr(kwargs.pop('size')) - 1 742 else: 743 raise TypeError, "Either end or size must be specified" 744 745 # Now on to the optional bit 746 if 'intlvHighBit' in kwargs: 747 self.intlvHighBit = int(kwargs.pop('intlvHighBit')) 748 if 'intlvBits' in kwargs: 749 self.intlvBits = int(kwargs.pop('intlvBits')) 750 if 'intlvMatch' in kwargs: 751 self.intlvMatch = int(kwargs.pop('intlvMatch')) 752 753 if len(args) == 0: 754 self.start = Addr(kwargs.pop('start')) 755 handle_kwargs(self, kwargs) 756 757 elif len(args) == 1: 758 if kwargs: 759 self.start = Addr(args[0]) 760 handle_kwargs(self, kwargs) 761 elif isinstance(args[0], (list, tuple)): 762 self.start = Addr(args[0][0]) 763 self.end = Addr(args[0][1]) 764 else: 765 self.start = Addr(0) 766 self.end = Addr(args[0]) - 1 767 768 elif len(args) == 2: 769 self.start = Addr(args[0]) 770 self.end = Addr(args[1]) 771 else: 772 raise TypeError, "Too many arguments specified" 773 774 if kwargs: 775 raise TypeError, "Too many keywords: %s" % kwargs.keys() 776 777 def __str__(self): 778 return '%s:%s' % (self.start, self.end) 779 780 def size(self): 781 # Divide the size by the size of the interleaving slice 782 return (long(self.end) - long(self.start) + 1) >> self.intlvBits 783 784 @classmethod 785 def cxx_predecls(cls, code): 786 Addr.cxx_predecls(code) 787 code('#include "base/addr_range.hh"') 788 789 @classmethod 790 def swig_predecls(cls, code): 791 Addr.swig_predecls(code) 792
|
| 793 @classmethod 794 def cxx_ini_predecls(cls, code): 795 code('#include <sstream>') 796 797 @classmethod 798 def cxx_ini_parse(cls, code, src, dest, ret): 799 code('uint64_t _start, _end;') 800 code('char _sep;') 801 code('std::istringstream _stream(${src});') 802 code('_stream >> _start;') 803 code('_stream.get(_sep);') 804 code('_stream >> _end;') 805 code('bool _ret = !_stream.fail() &&' 806 '_stream.eof() && _sep == \':\';') 807 code('if (_ret)') 808 code(' ${dest} = AddrRange(_start, _end);') 809 code('${ret} _ret;') 810
|
741 def getValue(self): 742 # Go from the Python class to the wrapped C++ class generated 743 # by swig 744 from m5.internal.range import AddrRange 745 746 return AddrRange(long(self.start), long(self.end), 747 int(self.intlvHighBit), int(self.intlvBits), 748 int(self.intlvMatch)) 749 750# Boolean parameter type. Python doesn't let you subclass bool, since 751# it doesn't want to let you create multiple instances of True and 752# False. Thus this is a little more complicated than String. 753class Bool(ParamValue): 754 cxx_type = 'bool' 755 cmd_line_settable = True 756 757 def __init__(self, value): 758 try: 759 self.value = convert.toBool(value) 760 except TypeError: 761 self.value = bool(value) 762 763 def __call__(self, value): 764 self.__init__(value) 765 return value 766 767 def getValue(self): 768 return bool(self.value) 769 770 def __str__(self): 771 return str(self.value) 772 773 # implement truth value testing for Bool parameters so that these params 774 # evaluate correctly during the python configuration phase 775 def __nonzero__(self): 776 return bool(self.value) 777 778 def ini_str(self): 779 if self.value: 780 return 'true' 781 return 'false' 782 783 def config_value(self): 784 return self.value 785
| 811 def getValue(self): 812 # Go from the Python class to the wrapped C++ class generated 813 # by swig 814 from m5.internal.range import AddrRange 815 816 return AddrRange(long(self.start), long(self.end), 817 int(self.intlvHighBit), int(self.intlvBits), 818 int(self.intlvMatch)) 819 820# Boolean parameter type. Python doesn't let you subclass bool, since 821# it doesn't want to let you create multiple instances of True and 822# False. Thus this is a little more complicated than String. 823class Bool(ParamValue): 824 cxx_type = 'bool' 825 cmd_line_settable = True 826 827 def __init__(self, value): 828 try: 829 self.value = convert.toBool(value) 830 except TypeError: 831 self.value = bool(value) 832 833 def __call__(self, value): 834 self.__init__(value) 835 return value 836 837 def getValue(self): 838 return bool(self.value) 839 840 def __str__(self): 841 return str(self.value) 842 843 # implement truth value testing for Bool parameters so that these params 844 # evaluate correctly during the python configuration phase 845 def __nonzero__(self): 846 return bool(self.value) 847 848 def ini_str(self): 849 if self.value: 850 return 'true' 851 return 'false' 852 853 def config_value(self): 854 return self.value 855
|
| 856 @classmethod 857 def cxx_ini_predecls(cls, code): 858 # Assume that base/str.hh will be included anyway 859 # code('#include "base/str.hh"') 860 pass 861 862 @classmethod 863 def cxx_ini_parse(cls, code, src, dest, ret): 864 code('%s to_bool(%s, %s);' % (ret, src, dest)) 865
|
786def IncEthernetAddr(addr, val = 1): 787 bytes = map(lambda x: int(x, 16), addr.split(':')) 788 bytes[5] += val 789 for i in (5, 4, 3, 2, 1): 790 val,rem = divmod(bytes[i], 256) 791 bytes[i] = rem 792 if val == 0: 793 break 794 bytes[i - 1] += val 795 assert(bytes[0] <= 255) 796 return ':'.join(map(lambda x: '%02x' % x, bytes)) 797 798_NextEthernetAddr = "00:90:00:00:00:01" 799def NextEthernetAddr(): 800 global _NextEthernetAddr 801 802 value = _NextEthernetAddr 803 _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 804 return value 805 806class EthernetAddr(ParamValue): 807 cxx_type = 'Net::EthAddr' 808 ex_str = "00:90:00:00:00:01" 809 cmd_line_settable = True 810 811 @classmethod 812 def cxx_predecls(cls, code): 813 code('#include "base/inet.hh"') 814 815 @classmethod 816 def swig_predecls(cls, code): 817 code('%include "python/swig/inet.i"') 818 819 def __init__(self, value): 820 if value == NextEthernetAddr: 821 self.value = value 822 return 823 824 if not isinstance(value, str): 825 raise TypeError, "expected an ethernet address and didn't get one" 826 827 bytes = value.split(':') 828 if len(bytes) != 6: 829 raise TypeError, 'invalid ethernet address %s' % value 830 831 for byte in bytes: 832 if not 0 <= int(byte, base=16) <= 0xff: 833 raise TypeError, 'invalid ethernet address %s' % value 834 835 self.value = value 836 837 def __call__(self, value): 838 self.__init__(value) 839 return value 840 841 def unproxy(self, base): 842 if self.value == NextEthernetAddr: 843 return EthernetAddr(self.value()) 844 return self 845 846 def getValue(self): 847 from m5.internal.params import EthAddr 848 return EthAddr(self.value) 849 850 def ini_str(self): 851 return self.value 852
| 866def IncEthernetAddr(addr, val = 1): 867 bytes = map(lambda x: int(x, 16), addr.split(':')) 868 bytes[5] += val 869 for i in (5, 4, 3, 2, 1): 870 val,rem = divmod(bytes[i], 256) 871 bytes[i] = rem 872 if val == 0: 873 break 874 bytes[i - 1] += val 875 assert(bytes[0] <= 255) 876 return ':'.join(map(lambda x: '%02x' % x, bytes)) 877 878_NextEthernetAddr = "00:90:00:00:00:01" 879def NextEthernetAddr(): 880 global _NextEthernetAddr 881 882 value = _NextEthernetAddr 883 _NextEthernetAddr = IncEthernetAddr(_NextEthernetAddr, 1) 884 return value 885 886class EthernetAddr(ParamValue): 887 cxx_type = 'Net::EthAddr' 888 ex_str = "00:90:00:00:00:01" 889 cmd_line_settable = True 890 891 @classmethod 892 def cxx_predecls(cls, code): 893 code('#include "base/inet.hh"') 894 895 @classmethod 896 def swig_predecls(cls, code): 897 code('%include "python/swig/inet.i"') 898 899 def __init__(self, value): 900 if value == NextEthernetAddr: 901 self.value = value 902 return 903 904 if not isinstance(value, str): 905 raise TypeError, "expected an ethernet address and didn't get one" 906 907 bytes = value.split(':') 908 if len(bytes) != 6: 909 raise TypeError, 'invalid ethernet address %s' % value 910 911 for byte in bytes: 912 if not 0 <= int(byte, base=16) <= 0xff: 913 raise TypeError, 'invalid ethernet address %s' % value 914 915 self.value = value 916 917 def __call__(self, value): 918 self.__init__(value) 919 return value 920 921 def unproxy(self, base): 922 if self.value == NextEthernetAddr: 923 return EthernetAddr(self.value()) 924 return self 925 926 def getValue(self): 927 from m5.internal.params import EthAddr 928 return EthAddr(self.value) 929 930 def ini_str(self): 931 return self.value 932
|
| 933 @classmethod 934 def cxx_ini_parse(self, code, src, dest, ret): 935 code('%s = Net::EthAddr(%s);' % (dest, src)) 936 code('%s true;' % ret) 937
|
853# When initializing an IpAddress, pass in an existing IpAddress, a string of 854# the form "a.b.c.d", or an integer representing an IP. 855class IpAddress(ParamValue): 856 cxx_type = 'Net::IpAddress' 857 ex_str = "127.0.0.1" 858 cmd_line_settable = True 859 860 @classmethod 861 def cxx_predecls(cls, code): 862 code('#include "base/inet.hh"') 863 864 @classmethod 865 def swig_predecls(cls, code): 866 code('%include "python/swig/inet.i"') 867 868 def __init__(self, value): 869 if isinstance(value, IpAddress): 870 self.ip = value.ip 871 else: 872 try: 873 self.ip = convert.toIpAddress(value) 874 except TypeError: 875 self.ip = long(value) 876 self.verifyIp() 877 878 def __call__(self, value): 879 self.__init__(value) 880 return value 881 882 def __str__(self): 883 tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 884 return '%d.%d.%d.%d' % tuple(tup) 885 886 def __eq__(self, other): 887 if isinstance(other, IpAddress): 888 return self.ip == other.ip 889 elif isinstance(other, str): 890 try: 891 return self.ip == convert.toIpAddress(other) 892 except: 893 return False 894 else: 895 return self.ip == other 896 897 def __ne__(self, other): 898 return not (self == other) 899 900 def verifyIp(self): 901 if self.ip < 0 or self.ip >= (1 << 32): 902 raise TypeError, "invalid ip address %#08x" % self.ip 903 904 def getValue(self): 905 from m5.internal.params import IpAddress 906 return IpAddress(self.ip) 907 908# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 909# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 910# positional or keyword arguments. 911class IpNetmask(IpAddress): 912 cxx_type = 'Net::IpNetmask' 913 ex_str = "127.0.0.0/24" 914 cmd_line_settable = True 915 916 @classmethod 917 def cxx_predecls(cls, code): 918 code('#include "base/inet.hh"') 919 920 @classmethod 921 def swig_predecls(cls, code): 922 code('%include "python/swig/inet.i"') 923 924 def __init__(self, *args, **kwargs): 925 def handle_kwarg(self, kwargs, key, elseVal = None): 926 if key in kwargs: 927 setattr(self, key, kwargs.pop(key)) 928 elif elseVal: 929 setattr(self, key, elseVal) 930 else: 931 raise TypeError, "No value set for %s" % key 932 933 if len(args) == 0: 934 handle_kwarg(self, kwargs, 'ip') 935 handle_kwarg(self, kwargs, 'netmask') 936 937 elif len(args) == 1: 938 if kwargs: 939 if not 'ip' in kwargs and not 'netmask' in kwargs: 940 raise TypeError, "Invalid arguments" 941 handle_kwarg(self, kwargs, 'ip', args[0]) 942 handle_kwarg(self, kwargs, 'netmask', args[0]) 943 elif isinstance(args[0], IpNetmask): 944 self.ip = args[0].ip 945 self.netmask = args[0].netmask 946 else: 947 (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 948 949 elif len(args) == 2: 950 self.ip = args[0] 951 self.netmask = args[1] 952 else: 953 raise TypeError, "Too many arguments specified" 954 955 if kwargs: 956 raise TypeError, "Too many keywords: %s" % kwargs.keys() 957 958 self.verify() 959 960 def __call__(self, value): 961 self.__init__(value) 962 return value 963 964 def __str__(self): 965 return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 966 967 def __eq__(self, other): 968 if isinstance(other, IpNetmask): 969 return self.ip == other.ip and self.netmask == other.netmask 970 elif isinstance(other, str): 971 try: 972 return (self.ip, self.netmask) == convert.toIpNetmask(other) 973 except: 974 return False 975 else: 976 return False 977 978 def verify(self): 979 self.verifyIp() 980 if self.netmask < 0 or self.netmask > 32: 981 raise TypeError, "invalid netmask %d" % netmask 982 983 def getValue(self): 984 from m5.internal.params import IpNetmask 985 return IpNetmask(self.ip, self.netmask) 986 987# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 988# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 989class IpWithPort(IpAddress): 990 cxx_type = 'Net::IpWithPort' 991 ex_str = "127.0.0.1:80" 992 cmd_line_settable = True 993 994 @classmethod 995 def cxx_predecls(cls, code): 996 code('#include "base/inet.hh"') 997 998 @classmethod 999 def swig_predecls(cls, code): 1000 code('%include "python/swig/inet.i"') 1001 1002 def __init__(self, *args, **kwargs): 1003 def handle_kwarg(self, kwargs, key, elseVal = None): 1004 if key in kwargs: 1005 setattr(self, key, kwargs.pop(key)) 1006 elif elseVal: 1007 setattr(self, key, elseVal) 1008 else: 1009 raise TypeError, "No value set for %s" % key 1010 1011 if len(args) == 0: 1012 handle_kwarg(self, kwargs, 'ip') 1013 handle_kwarg(self, kwargs, 'port') 1014 1015 elif len(args) == 1: 1016 if kwargs: 1017 if not 'ip' in kwargs and not 'port' in kwargs: 1018 raise TypeError, "Invalid arguments" 1019 handle_kwarg(self, kwargs, 'ip', args[0]) 1020 handle_kwarg(self, kwargs, 'port', args[0]) 1021 elif isinstance(args[0], IpWithPort): 1022 self.ip = args[0].ip 1023 self.port = args[0].port 1024 else: 1025 (self.ip, self.port) = convert.toIpWithPort(args[0]) 1026 1027 elif len(args) == 2: 1028 self.ip = args[0] 1029 self.port = args[1] 1030 else: 1031 raise TypeError, "Too many arguments specified" 1032 1033 if kwargs: 1034 raise TypeError, "Too many keywords: %s" % kwargs.keys() 1035 1036 self.verify() 1037 1038 def __call__(self, value): 1039 self.__init__(value) 1040 return value 1041 1042 def __str__(self): 1043 return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 1044 1045 def __eq__(self, other): 1046 if isinstance(other, IpWithPort): 1047 return self.ip == other.ip and self.port == other.port 1048 elif isinstance(other, str): 1049 try: 1050 return (self.ip, self.port) == convert.toIpWithPort(other) 1051 except: 1052 return False 1053 else: 1054 return False 1055 1056 def verify(self): 1057 self.verifyIp() 1058 if self.port < 0 or self.port > 0xffff: 1059 raise TypeError, "invalid port %d" % self.port 1060 1061 def getValue(self): 1062 from m5.internal.params import IpWithPort 1063 return IpWithPort(self.ip, self.port) 1064 1065time_formats = [ "%a %b %d %H:%M:%S %Z %Y", 1066 "%a %b %d %H:%M:%S %Y", 1067 "%Y/%m/%d %H:%M:%S", 1068 "%Y/%m/%d %H:%M", 1069 "%Y/%m/%d", 1070 "%m/%d/%Y %H:%M:%S", 1071 "%m/%d/%Y %H:%M", 1072 "%m/%d/%Y", 1073 "%m/%d/%y %H:%M:%S", 1074 "%m/%d/%y %H:%M", 1075 "%m/%d/%y"] 1076 1077 1078def parse_time(value): 1079 from time import gmtime, strptime, struct_time, time 1080 from datetime import datetime, date 1081 1082 if isinstance(value, struct_time): 1083 return value 1084 1085 if isinstance(value, (int, long)): 1086 return gmtime(value) 1087 1088 if isinstance(value, (datetime, date)): 1089 return value.timetuple() 1090 1091 if isinstance(value, str): 1092 if value in ('Now', 'Today'): 1093 return time.gmtime(time.time()) 1094 1095 for format in time_formats: 1096 try: 1097 return strptime(value, format) 1098 except ValueError: 1099 pass 1100 1101 raise ValueError, "Could not parse '%s' as a time" % value 1102 1103class Time(ParamValue): 1104 cxx_type = 'tm' 1105 1106 @classmethod 1107 def cxx_predecls(cls, code): 1108 code('#include <time.h>') 1109 1110 @classmethod 1111 def swig_predecls(cls, code): 1112 code('%include "python/swig/time.i"') 1113 1114 def __init__(self, value): 1115 self.value = parse_time(value) 1116 1117 def __call__(self, value): 1118 self.__init__(value) 1119 return value 1120 1121 def getValue(self): 1122 from m5.internal.params import tm 1123 1124 c_time = tm() 1125 py_time = self.value 1126 1127 # UNIX is years since 1900 1128 c_time.tm_year = py_time.tm_year - 1900; 1129 1130 # Python starts at 1, UNIX starts at 0 1131 c_time.tm_mon = py_time.tm_mon - 1; 1132 c_time.tm_mday = py_time.tm_mday; 1133 c_time.tm_hour = py_time.tm_hour; 1134 c_time.tm_min = py_time.tm_min; 1135 c_time.tm_sec = py_time.tm_sec; 1136 1137 # Python has 0 as Monday, UNIX is 0 as sunday 1138 c_time.tm_wday = py_time.tm_wday + 1 1139 if c_time.tm_wday > 6: 1140 c_time.tm_wday -= 7; 1141 1142 # Python starts at 1, Unix starts at 0 1143 c_time.tm_yday = py_time.tm_yday - 1; 1144 1145 return c_time 1146 1147 def __str__(self): 1148 return time.asctime(self.value) 1149 1150 def ini_str(self): 1151 return str(self) 1152 1153 def get_config_as_dict(self): 1154 assert false 1155 return str(self) 1156
| 938# When initializing an IpAddress, pass in an existing IpAddress, a string of 939# the form "a.b.c.d", or an integer representing an IP. 940class IpAddress(ParamValue): 941 cxx_type = 'Net::IpAddress' 942 ex_str = "127.0.0.1" 943 cmd_line_settable = True 944 945 @classmethod 946 def cxx_predecls(cls, code): 947 code('#include "base/inet.hh"') 948 949 @classmethod 950 def swig_predecls(cls, code): 951 code('%include "python/swig/inet.i"') 952 953 def __init__(self, value): 954 if isinstance(value, IpAddress): 955 self.ip = value.ip 956 else: 957 try: 958 self.ip = convert.toIpAddress(value) 959 except TypeError: 960 self.ip = long(value) 961 self.verifyIp() 962 963 def __call__(self, value): 964 self.__init__(value) 965 return value 966 967 def __str__(self): 968 tup = [(self.ip >> i) & 0xff for i in (24, 16, 8, 0)] 969 return '%d.%d.%d.%d' % tuple(tup) 970 971 def __eq__(self, other): 972 if isinstance(other, IpAddress): 973 return self.ip == other.ip 974 elif isinstance(other, str): 975 try: 976 return self.ip == convert.toIpAddress(other) 977 except: 978 return False 979 else: 980 return self.ip == other 981 982 def __ne__(self, other): 983 return not (self == other) 984 985 def verifyIp(self): 986 if self.ip < 0 or self.ip >= (1 << 32): 987 raise TypeError, "invalid ip address %#08x" % self.ip 988 989 def getValue(self): 990 from m5.internal.params import IpAddress 991 return IpAddress(self.ip) 992 993# When initializing an IpNetmask, pass in an existing IpNetmask, a string of 994# the form "a.b.c.d/n" or "a.b.c.d/e.f.g.h", or an ip and netmask as 995# positional or keyword arguments. 996class IpNetmask(IpAddress): 997 cxx_type = 'Net::IpNetmask' 998 ex_str = "127.0.0.0/24" 999 cmd_line_settable = True 1000 1001 @classmethod 1002 def cxx_predecls(cls, code): 1003 code('#include "base/inet.hh"') 1004 1005 @classmethod 1006 def swig_predecls(cls, code): 1007 code('%include "python/swig/inet.i"') 1008 1009 def __init__(self, *args, **kwargs): 1010 def handle_kwarg(self, kwargs, key, elseVal = None): 1011 if key in kwargs: 1012 setattr(self, key, kwargs.pop(key)) 1013 elif elseVal: 1014 setattr(self, key, elseVal) 1015 else: 1016 raise TypeError, "No value set for %s" % key 1017 1018 if len(args) == 0: 1019 handle_kwarg(self, kwargs, 'ip') 1020 handle_kwarg(self, kwargs, 'netmask') 1021 1022 elif len(args) == 1: 1023 if kwargs: 1024 if not 'ip' in kwargs and not 'netmask' in kwargs: 1025 raise TypeError, "Invalid arguments" 1026 handle_kwarg(self, kwargs, 'ip', args[0]) 1027 handle_kwarg(self, kwargs, 'netmask', args[0]) 1028 elif isinstance(args[0], IpNetmask): 1029 self.ip = args[0].ip 1030 self.netmask = args[0].netmask 1031 else: 1032 (self.ip, self.netmask) = convert.toIpNetmask(args[0]) 1033 1034 elif len(args) == 2: 1035 self.ip = args[0] 1036 self.netmask = args[1] 1037 else: 1038 raise TypeError, "Too many arguments specified" 1039 1040 if kwargs: 1041 raise TypeError, "Too many keywords: %s" % kwargs.keys() 1042 1043 self.verify() 1044 1045 def __call__(self, value): 1046 self.__init__(value) 1047 return value 1048 1049 def __str__(self): 1050 return "%s/%d" % (super(IpNetmask, self).__str__(), self.netmask) 1051 1052 def __eq__(self, other): 1053 if isinstance(other, IpNetmask): 1054 return self.ip == other.ip and self.netmask == other.netmask 1055 elif isinstance(other, str): 1056 try: 1057 return (self.ip, self.netmask) == convert.toIpNetmask(other) 1058 except: 1059 return False 1060 else: 1061 return False 1062 1063 def verify(self): 1064 self.verifyIp() 1065 if self.netmask < 0 or self.netmask > 32: 1066 raise TypeError, "invalid netmask %d" % netmask 1067 1068 def getValue(self): 1069 from m5.internal.params import IpNetmask 1070 return IpNetmask(self.ip, self.netmask) 1071 1072# When initializing an IpWithPort, pass in an existing IpWithPort, a string of 1073# the form "a.b.c.d:p", or an ip and port as positional or keyword arguments. 1074class IpWithPort(IpAddress): 1075 cxx_type = 'Net::IpWithPort' 1076 ex_str = "127.0.0.1:80" 1077 cmd_line_settable = True 1078 1079 @classmethod 1080 def cxx_predecls(cls, code): 1081 code('#include "base/inet.hh"') 1082 1083 @classmethod 1084 def swig_predecls(cls, code): 1085 code('%include "python/swig/inet.i"') 1086 1087 def __init__(self, *args, **kwargs): 1088 def handle_kwarg(self, kwargs, key, elseVal = None): 1089 if key in kwargs: 1090 setattr(self, key, kwargs.pop(key)) 1091 elif elseVal: 1092 setattr(self, key, elseVal) 1093 else: 1094 raise TypeError, "No value set for %s" % key 1095 1096 if len(args) == 0: 1097 handle_kwarg(self, kwargs, 'ip') 1098 handle_kwarg(self, kwargs, 'port') 1099 1100 elif len(args) == 1: 1101 if kwargs: 1102 if not 'ip' in kwargs and not 'port' in kwargs: 1103 raise TypeError, "Invalid arguments" 1104 handle_kwarg(self, kwargs, 'ip', args[0]) 1105 handle_kwarg(self, kwargs, 'port', args[0]) 1106 elif isinstance(args[0], IpWithPort): 1107 self.ip = args[0].ip 1108 self.port = args[0].port 1109 else: 1110 (self.ip, self.port) = convert.toIpWithPort(args[0]) 1111 1112 elif len(args) == 2: 1113 self.ip = args[0] 1114 self.port = args[1] 1115 else: 1116 raise TypeError, "Too many arguments specified" 1117 1118 if kwargs: 1119 raise TypeError, "Too many keywords: %s" % kwargs.keys() 1120 1121 self.verify() 1122 1123 def __call__(self, value): 1124 self.__init__(value) 1125 return value 1126 1127 def __str__(self): 1128 return "%s:%d" % (super(IpWithPort, self).__str__(), self.port) 1129 1130 def __eq__(self, other): 1131 if isinstance(other, IpWithPort): 1132 return self.ip == other.ip and self.port == other.port 1133 elif isinstance(other, str): 1134 try: 1135 return (self.ip, self.port) == convert.toIpWithPort(other) 1136 except: 1137 return False 1138 else: 1139 return False 1140 1141 def verify(self): 1142 self.verifyIp() 1143 if self.port < 0 or self.port > 0xffff: 1144 raise TypeError, "invalid port %d" % self.port 1145 1146 def getValue(self): 1147 from m5.internal.params import IpWithPort 1148 return IpWithPort(self.ip, self.port) 1149 1150time_formats = [ "%a %b %d %H:%M:%S %Z %Y", 1151 "%a %b %d %H:%M:%S %Y", 1152 "%Y/%m/%d %H:%M:%S", 1153 "%Y/%m/%d %H:%M", 1154 "%Y/%m/%d", 1155 "%m/%d/%Y %H:%M:%S", 1156 "%m/%d/%Y %H:%M", 1157 "%m/%d/%Y", 1158 "%m/%d/%y %H:%M:%S", 1159 "%m/%d/%y %H:%M", 1160 "%m/%d/%y"] 1161 1162 1163def parse_time(value): 1164 from time import gmtime, strptime, struct_time, time 1165 from datetime import datetime, date 1166 1167 if isinstance(value, struct_time): 1168 return value 1169 1170 if isinstance(value, (int, long)): 1171 return gmtime(value) 1172 1173 if isinstance(value, (datetime, date)): 1174 return value.timetuple() 1175 1176 if isinstance(value, str): 1177 if value in ('Now', 'Today'): 1178 return time.gmtime(time.time()) 1179 1180 for format in time_formats: 1181 try: 1182 return strptime(value, format) 1183 except ValueError: 1184 pass 1185 1186 raise ValueError, "Could not parse '%s' as a time" % value 1187 1188class Time(ParamValue): 1189 cxx_type = 'tm' 1190 1191 @classmethod 1192 def cxx_predecls(cls, code): 1193 code('#include <time.h>') 1194 1195 @classmethod 1196 def swig_predecls(cls, code): 1197 code('%include "python/swig/time.i"') 1198 1199 def __init__(self, value): 1200 self.value = parse_time(value) 1201 1202 def __call__(self, value): 1203 self.__init__(value) 1204 return value 1205 1206 def getValue(self): 1207 from m5.internal.params import tm 1208 1209 c_time = tm() 1210 py_time = self.value 1211 1212 # UNIX is years since 1900 1213 c_time.tm_year = py_time.tm_year - 1900; 1214 1215 # Python starts at 1, UNIX starts at 0 1216 c_time.tm_mon = py_time.tm_mon - 1; 1217 c_time.tm_mday = py_time.tm_mday; 1218 c_time.tm_hour = py_time.tm_hour; 1219 c_time.tm_min = py_time.tm_min; 1220 c_time.tm_sec = py_time.tm_sec; 1221 1222 # Python has 0 as Monday, UNIX is 0 as sunday 1223 c_time.tm_wday = py_time.tm_wday + 1 1224 if c_time.tm_wday > 6: 1225 c_time.tm_wday -= 7; 1226 1227 # Python starts at 1, Unix starts at 0 1228 c_time.tm_yday = py_time.tm_yday - 1; 1229 1230 return c_time 1231 1232 def __str__(self): 1233 return time.asctime(self.value) 1234 1235 def ini_str(self): 1236 return str(self) 1237 1238 def get_config_as_dict(self): 1239 assert false 1240 return str(self) 1241
|
| 1242 @classmethod 1243 def cxx_ini_predecls(cls, code): 1244 code('#include <time.h>') 1245 1246 @classmethod 1247 def cxx_ini_parse(cls, code, src, dest, ret): 1248 code('char *_parse_ret = strptime((${src}).c_str(),') 1249 code(' "%a %b %d %H:%M:%S %Y", &(${dest}));') 1250 code('${ret} _parse_ret && *_parse_ret == \'\\0\';'); 1251
|
1157# Enumerated types are a little more complex. The user specifies the 1158# type as Enum(foo) where foo is either a list or dictionary of 1159# alternatives (typically strings, but not necessarily so). (In the 1160# long run, the integer value of the parameter will be the list index 1161# or the corresponding dictionary value. For now, since we only check 1162# that the alternative is valid and then spit it into a .ini file, 1163# there's not much point in using the dictionary.) 1164 1165# What Enum() must do is generate a new type encapsulating the 1166# provided list/dictionary so that specific values of the parameter 1167# can be instances of that type. We define two hidden internal 1168# classes (_ListEnum and _DictEnum) to serve as base classes, then 1169# derive the new type from the appropriate base class on the fly. 1170 1171allEnums = {} 1172# Metaclass for Enum types 1173class MetaEnum(MetaParamValue): 1174 def __new__(mcls, name, bases, dict): 1175 assert name not in allEnums 1176 1177 cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 1178 allEnums[name] = cls 1179 return cls 1180 1181 def __init__(cls, name, bases, init_dict): 1182 if init_dict.has_key('map'): 1183 if not isinstance(cls.map, dict): 1184 raise TypeError, "Enum-derived class attribute 'map' " \ 1185 "must be of type dict" 1186 # build list of value strings from map 1187 cls.vals = cls.map.keys() 1188 cls.vals.sort() 1189 elif init_dict.has_key('vals'): 1190 if not isinstance(cls.vals, list): 1191 raise TypeError, "Enum-derived class attribute 'vals' " \ 1192 "must be of type list" 1193 # build string->value map from vals sequence 1194 cls.map = {} 1195 for idx,val in enumerate(cls.vals): 1196 cls.map[val] = idx 1197 else: 1198 raise TypeError, "Enum-derived class must define "\ 1199 "attribute 'map' or 'vals'" 1200 1201 cls.cxx_type = 'Enums::%s' % name 1202 1203 super(MetaEnum, cls).__init__(name, bases, init_dict) 1204 1205 # Generate C++ class declaration for this enum type. 1206 # Note that we wrap the enum in a class/struct to act as a namespace, 1207 # so that the enum strings can be brief w/o worrying about collisions. 1208 def cxx_decl(cls, code): 1209 wrapper_name = cls.wrapper_name 1210 wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 1211 name = cls.__name__ if cls.enum_name is None else cls.enum_name 1212 idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 1213 1214 code('''\ 1215#ifndef $idem_macro 1216#define $idem_macro 1217 1218$wrapper $wrapper_name { 1219 enum $name { 1220''') 1221 code.indent(2) 1222 for val in cls.vals: 1223 code('$val = ${{cls.map[val]}},') 1224 code('Num_$name = ${{len(cls.vals)}}') 1225 code.dedent(2) 1226 code(' };') 1227 1228 if cls.wrapper_is_struct: 1229 code(' static const char *${name}Strings[Num_${name}];') 1230 code('};') 1231 else: 1232 code('extern const char *${name}Strings[Num_${name}];') 1233 code('}') 1234 1235 code() 1236 code('#endif // $idem_macro') 1237 1238 def cxx_def(cls, code): 1239 wrapper_name = cls.wrapper_name 1240 file_name = cls.__name__ 1241 name = cls.__name__ if cls.enum_name is None else cls.enum_name 1242 1243 code('#include "enums/$file_name.hh"') 1244 if cls.wrapper_is_struct: 1245 code('const char *${wrapper_name}::${name}Strings' 1246 '[Num_${name}] =') 1247 else: 1248 code('namespace Enums {') 1249 code.indent(1) 1250 code(' const char *${name}Strings[Num_${name}] =') 1251 1252 code('{') 1253 code.indent(1) 1254 for val in cls.vals: 1255 code('"$val",') 1256 code.dedent(1) 1257 code('};') 1258 1259 if not cls.wrapper_is_struct: 1260 code('} // namespace $wrapper_name') 1261 code.dedent(1) 1262 1263 def swig_decl(cls, code): 1264 name = cls.__name__ 1265 code('''\ 1266%module(package="m5.internal") enum_$name 1267 1268%{ 1269#include "enums/$name.hh" 1270%} 1271 1272%include "enums/$name.hh" 1273''') 1274 1275 1276# Base class for enum types. 1277class Enum(ParamValue): 1278 __metaclass__ = MetaEnum 1279 vals = [] 1280 cmd_line_settable = True 1281 1282 # The name of the wrapping namespace or struct 1283 wrapper_name = 'Enums' 1284 1285 # If true, the enum is wrapped in a struct rather than a namespace 1286 wrapper_is_struct = False 1287 1288 # If not None, use this as the enum name rather than this class name 1289 enum_name = None 1290 1291 def __init__(self, value): 1292 if value not in self.map: 1293 raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 1294 % (value, self.vals) 1295 self.value = value 1296 1297 def __call__(self, value): 1298 self.__init__(value) 1299 return value 1300 1301 @classmethod 1302 def cxx_predecls(cls, code): 1303 code('#include "enums/$0.hh"', cls.__name__) 1304 1305 @classmethod 1306 def swig_predecls(cls, code): 1307 code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 1308
| 1252# Enumerated types are a little more complex. The user specifies the 1253# type as Enum(foo) where foo is either a list or dictionary of 1254# alternatives (typically strings, but not necessarily so). (In the 1255# long run, the integer value of the parameter will be the list index 1256# or the corresponding dictionary value. For now, since we only check 1257# that the alternative is valid and then spit it into a .ini file, 1258# there's not much point in using the dictionary.) 1259 1260# What Enum() must do is generate a new type encapsulating the 1261# provided list/dictionary so that specific values of the parameter 1262# can be instances of that type. We define two hidden internal 1263# classes (_ListEnum and _DictEnum) to serve as base classes, then 1264# derive the new type from the appropriate base class on the fly. 1265 1266allEnums = {} 1267# Metaclass for Enum types 1268class MetaEnum(MetaParamValue): 1269 def __new__(mcls, name, bases, dict): 1270 assert name not in allEnums 1271 1272 cls = super(MetaEnum, mcls).__new__(mcls, name, bases, dict) 1273 allEnums[name] = cls 1274 return cls 1275 1276 def __init__(cls, name, bases, init_dict): 1277 if init_dict.has_key('map'): 1278 if not isinstance(cls.map, dict): 1279 raise TypeError, "Enum-derived class attribute 'map' " \ 1280 "must be of type dict" 1281 # build list of value strings from map 1282 cls.vals = cls.map.keys() 1283 cls.vals.sort() 1284 elif init_dict.has_key('vals'): 1285 if not isinstance(cls.vals, list): 1286 raise TypeError, "Enum-derived class attribute 'vals' " \ 1287 "must be of type list" 1288 # build string->value map from vals sequence 1289 cls.map = {} 1290 for idx,val in enumerate(cls.vals): 1291 cls.map[val] = idx 1292 else: 1293 raise TypeError, "Enum-derived class must define "\ 1294 "attribute 'map' or 'vals'" 1295 1296 cls.cxx_type = 'Enums::%s' % name 1297 1298 super(MetaEnum, cls).__init__(name, bases, init_dict) 1299 1300 # Generate C++ class declaration for this enum type. 1301 # Note that we wrap the enum in a class/struct to act as a namespace, 1302 # so that the enum strings can be brief w/o worrying about collisions. 1303 def cxx_decl(cls, code): 1304 wrapper_name = cls.wrapper_name 1305 wrapper = 'struct' if cls.wrapper_is_struct else 'namespace' 1306 name = cls.__name__ if cls.enum_name is None else cls.enum_name 1307 idem_macro = '__ENUM__%s__%s__' % (wrapper_name, name) 1308 1309 code('''\ 1310#ifndef $idem_macro 1311#define $idem_macro 1312 1313$wrapper $wrapper_name { 1314 enum $name { 1315''') 1316 code.indent(2) 1317 for val in cls.vals: 1318 code('$val = ${{cls.map[val]}},') 1319 code('Num_$name = ${{len(cls.vals)}}') 1320 code.dedent(2) 1321 code(' };') 1322 1323 if cls.wrapper_is_struct: 1324 code(' static const char *${name}Strings[Num_${name}];') 1325 code('};') 1326 else: 1327 code('extern const char *${name}Strings[Num_${name}];') 1328 code('}') 1329 1330 code() 1331 code('#endif // $idem_macro') 1332 1333 def cxx_def(cls, code): 1334 wrapper_name = cls.wrapper_name 1335 file_name = cls.__name__ 1336 name = cls.__name__ if cls.enum_name is None else cls.enum_name 1337 1338 code('#include "enums/$file_name.hh"') 1339 if cls.wrapper_is_struct: 1340 code('const char *${wrapper_name}::${name}Strings' 1341 '[Num_${name}] =') 1342 else: 1343 code('namespace Enums {') 1344 code.indent(1) 1345 code(' const char *${name}Strings[Num_${name}] =') 1346 1347 code('{') 1348 code.indent(1) 1349 for val in cls.vals: 1350 code('"$val",') 1351 code.dedent(1) 1352 code('};') 1353 1354 if not cls.wrapper_is_struct: 1355 code('} // namespace $wrapper_name') 1356 code.dedent(1) 1357 1358 def swig_decl(cls, code): 1359 name = cls.__name__ 1360 code('''\ 1361%module(package="m5.internal") enum_$name 1362 1363%{ 1364#include "enums/$name.hh" 1365%} 1366 1367%include "enums/$name.hh" 1368''') 1369 1370 1371# Base class for enum types. 1372class Enum(ParamValue): 1373 __metaclass__ = MetaEnum 1374 vals = [] 1375 cmd_line_settable = True 1376 1377 # The name of the wrapping namespace or struct 1378 wrapper_name = 'Enums' 1379 1380 # If true, the enum is wrapped in a struct rather than a namespace 1381 wrapper_is_struct = False 1382 1383 # If not None, use this as the enum name rather than this class name 1384 enum_name = None 1385 1386 def __init__(self, value): 1387 if value not in self.map: 1388 raise TypeError, "Enum param got bad value '%s' (not in %s)" \ 1389 % (value, self.vals) 1390 self.value = value 1391 1392 def __call__(self, value): 1393 self.__init__(value) 1394 return value 1395 1396 @classmethod 1397 def cxx_predecls(cls, code): 1398 code('#include "enums/$0.hh"', cls.__name__) 1399 1400 @classmethod 1401 def swig_predecls(cls, code): 1402 code('%import "python/m5/internal/enum_$0.i"', cls.__name__) 1403
|
| 1404 @classmethod 1405 def cxx_ini_parse(cls, code, src, dest, ret): 1406 code('if (false) {') 1407 for elem_name in cls.map.iterkeys(): 1408 code('} else if (%s == "%s") {' % (src, elem_name)) 1409 code.indent() 1410 code('%s = Enums::%s;' % (dest, elem_name)) 1411 code('%s true;' % ret) 1412 code.dedent() 1413 code('} else {') 1414 code(' %s false;' % ret) 1415 code('}') 1416
|
1309 def getValue(self): 1310 return int(self.map[self.value]) 1311 1312 def __str__(self): 1313 return self.value 1314 1315# how big does a rounding error need to be before we warn about it? 1316frequency_tolerance = 0.001 # 0.1% 1317 1318class TickParamValue(NumericParamValue): 1319 cxx_type = 'Tick' 1320 ex_str = "1MHz" 1321 cmd_line_settable = True 1322 1323 @classmethod 1324 def cxx_predecls(cls, code): 1325 code('#include "base/types.hh"') 1326 1327 @classmethod 1328 def swig_predecls(cls, code): 1329 code('%import "stdint.i"') 1330 code('%import "base/types.hh"') 1331 1332 def __call__(self, value): 1333 self.__init__(value) 1334 return value 1335 1336 def getValue(self): 1337 return long(self.value) 1338
| 1417 def getValue(self): 1418 return int(self.map[self.value]) 1419 1420 def __str__(self): 1421 return self.value 1422 1423# how big does a rounding error need to be before we warn about it? 1424frequency_tolerance = 0.001 # 0.1% 1425 1426class TickParamValue(NumericParamValue): 1427 cxx_type = 'Tick' 1428 ex_str = "1MHz" 1429 cmd_line_settable = True 1430 1431 @classmethod 1432 def cxx_predecls(cls, code): 1433 code('#include "base/types.hh"') 1434 1435 @classmethod 1436 def swig_predecls(cls, code): 1437 code('%import "stdint.i"') 1438 code('%import "base/types.hh"') 1439 1440 def __call__(self, value): 1441 self.__init__(value) 1442 return value 1443 1444 def getValue(self): 1445 return long(self.value) 1446
|
| 1447 @classmethod 1448 def cxx_ini_predecls(cls, code): 1449 code('#include <sstream>') 1450 1451 # Ticks are expressed in seconds in JSON files and in plain 1452 # Ticks in .ini files. Switch based on a config flag 1453 @classmethod 1454 def cxx_ini_parse(self, code, src, dest, ret): 1455 code('${ret} to_number(${src}, ${dest});') 1456
|
1339class Latency(TickParamValue): 1340 ex_str = "100ns" 1341 1342 def __init__(self, value): 1343 if isinstance(value, (Latency, Clock)): 1344 self.ticks = value.ticks 1345 self.value = value.value 1346 elif isinstance(value, Frequency): 1347 self.ticks = value.ticks 1348 self.value = 1.0 / value.value 1349 elif value.endswith('t'): 1350 self.ticks = True 1351 self.value = int(value[:-1]) 1352 else: 1353 self.ticks = False 1354 self.value = convert.toLatency(value) 1355 1356 def __call__(self, value): 1357 self.__init__(value) 1358 return value 1359 1360 def __getattr__(self, attr): 1361 if attr in ('latency', 'period'): 1362 return self 1363 if attr == 'frequency': 1364 return Frequency(self) 1365 raise AttributeError, "Latency object has no attribute '%s'" % attr 1366 1367 def getValue(self): 1368 if self.ticks or self.value == 0: 1369 value = self.value 1370 else: 1371 value = ticks.fromSeconds(self.value) 1372 return long(value) 1373 1374 def config_value(self): 1375 return self.getValue() 1376 1377 # convert latency to ticks 1378 def ini_str(self): 1379 return '%d' % self.getValue() 1380 1381class Frequency(TickParamValue): 1382 ex_str = "1GHz" 1383 1384 def __init__(self, value): 1385 if isinstance(value, (Latency, Clock)): 1386 if value.value == 0: 1387 self.value = 0 1388 else: 1389 self.value = 1.0 / value.value 1390 self.ticks = value.ticks 1391 elif isinstance(value, Frequency): 1392 self.value = value.value 1393 self.ticks = value.ticks 1394 else: 1395 self.ticks = False 1396 self.value = convert.toFrequency(value) 1397 1398 def __call__(self, value): 1399 self.__init__(value) 1400 return value 1401 1402 def __getattr__(self, attr): 1403 if attr == 'frequency': 1404 return self 1405 if attr in ('latency', 'period'): 1406 return Latency(self) 1407 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1408 1409 # convert latency to ticks 1410 def getValue(self): 1411 if self.ticks or self.value == 0: 1412 value = self.value 1413 else: 1414 value = ticks.fromSeconds(1.0 / self.value) 1415 return long(value) 1416 1417 def config_value(self): 1418 return self.getValue() 1419 1420 def ini_str(self): 1421 return '%d' % self.getValue() 1422 1423# A generic Frequency and/or Latency value. Value is stored as a 1424# latency, just like Latency and Frequency. 1425class Clock(TickParamValue): 1426 def __init__(self, value): 1427 if isinstance(value, (Latency, Clock)): 1428 self.ticks = value.ticks 1429 self.value = value.value 1430 elif isinstance(value, Frequency): 1431 self.ticks = value.ticks 1432 self.value = 1.0 / value.value 1433 elif value.endswith('t'): 1434 self.ticks = True 1435 self.value = int(value[:-1]) 1436 else: 1437 self.ticks = False 1438 self.value = convert.anyToLatency(value) 1439 1440 def __call__(self, value): 1441 self.__init__(value) 1442 return value 1443 1444 def __str__(self): 1445 return "%s" % Latency(self) 1446 1447 def __getattr__(self, attr): 1448 if attr == 'frequency': 1449 return Frequency(self) 1450 if attr in ('latency', 'period'): 1451 return Latency(self) 1452 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1453 1454 def getValue(self): 1455 return self.period.getValue() 1456 1457 def config_value(self): 1458 return self.period.config_value() 1459 1460 def ini_str(self): 1461 return self.period.ini_str() 1462 1463class Voltage(float,ParamValue): 1464 cxx_type = 'double' 1465 ex_str = "1V" 1466 cmd_line_settable = False 1467 1468 def __new__(cls, value): 1469 # convert to voltage 1470 val = convert.toVoltage(value) 1471 return super(cls, Voltage).__new__(cls, val) 1472 1473 def __call__(self, value): 1474 val = convert.toVoltage(value) 1475 self.__init__(val) 1476 return value 1477 1478 def __str__(self): 1479 return str(self.getValue()) 1480 1481 def getValue(self): 1482 value = float(self) 1483 return value 1484 1485 def ini_str(self): 1486 return '%f' % self.getValue() 1487
| 1457class Latency(TickParamValue): 1458 ex_str = "100ns" 1459 1460 def __init__(self, value): 1461 if isinstance(value, (Latency, Clock)): 1462 self.ticks = value.ticks 1463 self.value = value.value 1464 elif isinstance(value, Frequency): 1465 self.ticks = value.ticks 1466 self.value = 1.0 / value.value 1467 elif value.endswith('t'): 1468 self.ticks = True 1469 self.value = int(value[:-1]) 1470 else: 1471 self.ticks = False 1472 self.value = convert.toLatency(value) 1473 1474 def __call__(self, value): 1475 self.__init__(value) 1476 return value 1477 1478 def __getattr__(self, attr): 1479 if attr in ('latency', 'period'): 1480 return self 1481 if attr == 'frequency': 1482 return Frequency(self) 1483 raise AttributeError, "Latency object has no attribute '%s'" % attr 1484 1485 def getValue(self): 1486 if self.ticks or self.value == 0: 1487 value = self.value 1488 else: 1489 value = ticks.fromSeconds(self.value) 1490 return long(value) 1491 1492 def config_value(self): 1493 return self.getValue() 1494 1495 # convert latency to ticks 1496 def ini_str(self): 1497 return '%d' % self.getValue() 1498 1499class Frequency(TickParamValue): 1500 ex_str = "1GHz" 1501 1502 def __init__(self, value): 1503 if isinstance(value, (Latency, Clock)): 1504 if value.value == 0: 1505 self.value = 0 1506 else: 1507 self.value = 1.0 / value.value 1508 self.ticks = value.ticks 1509 elif isinstance(value, Frequency): 1510 self.value = value.value 1511 self.ticks = value.ticks 1512 else: 1513 self.ticks = False 1514 self.value = convert.toFrequency(value) 1515 1516 def __call__(self, value): 1517 self.__init__(value) 1518 return value 1519 1520 def __getattr__(self, attr): 1521 if attr == 'frequency': 1522 return self 1523 if attr in ('latency', 'period'): 1524 return Latency(self) 1525 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1526 1527 # convert latency to ticks 1528 def getValue(self): 1529 if self.ticks or self.value == 0: 1530 value = self.value 1531 else: 1532 value = ticks.fromSeconds(1.0 / self.value) 1533 return long(value) 1534 1535 def config_value(self): 1536 return self.getValue() 1537 1538 def ini_str(self): 1539 return '%d' % self.getValue() 1540 1541# A generic Frequency and/or Latency value. Value is stored as a 1542# latency, just like Latency and Frequency. 1543class Clock(TickParamValue): 1544 def __init__(self, value): 1545 if isinstance(value, (Latency, Clock)): 1546 self.ticks = value.ticks 1547 self.value = value.value 1548 elif isinstance(value, Frequency): 1549 self.ticks = value.ticks 1550 self.value = 1.0 / value.value 1551 elif value.endswith('t'): 1552 self.ticks = True 1553 self.value = int(value[:-1]) 1554 else: 1555 self.ticks = False 1556 self.value = convert.anyToLatency(value) 1557 1558 def __call__(self, value): 1559 self.__init__(value) 1560 return value 1561 1562 def __str__(self): 1563 return "%s" % Latency(self) 1564 1565 def __getattr__(self, attr): 1566 if attr == 'frequency': 1567 return Frequency(self) 1568 if attr in ('latency', 'period'): 1569 return Latency(self) 1570 raise AttributeError, "Frequency object has no attribute '%s'" % attr 1571 1572 def getValue(self): 1573 return self.period.getValue() 1574 1575 def config_value(self): 1576 return self.period.config_value() 1577 1578 def ini_str(self): 1579 return self.period.ini_str() 1580 1581class Voltage(float,ParamValue): 1582 cxx_type = 'double' 1583 ex_str = "1V" 1584 cmd_line_settable = False 1585 1586 def __new__(cls, value): 1587 # convert to voltage 1588 val = convert.toVoltage(value) 1589 return super(cls, Voltage).__new__(cls, val) 1590 1591 def __call__(self, value): 1592 val = convert.toVoltage(value) 1593 self.__init__(val) 1594 return value 1595 1596 def __str__(self): 1597 return str(self.getValue()) 1598 1599 def getValue(self): 1600 value = float(self) 1601 return value 1602 1603 def ini_str(self): 1604 return '%f' % self.getValue() 1605
|
| 1606 @classmethod 1607 def cxx_ini_predecls(cls, code): 1608 code('#include <sstream>') 1609 1610 @classmethod 1611 def cxx_ini_parse(self, code, src, dest, ret): 1612 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1613
|
1488class Current(float, ParamValue): 1489 cxx_type = 'double' 1490 ex_str = "1mA" 1491 cmd_line_settable = False 1492 1493 def __new__(cls, value): 1494 # convert to current 1495 val = convert.toCurrent(value) 1496 return super(cls, Current).__new__(cls, val) 1497 1498 def __call__(self, value): 1499 val = convert.toCurrent(value) 1500 self.__init__(val) 1501 return value 1502 1503 def __str__(self): 1504 return str(self.getValue()) 1505 1506 def getValue(self): 1507 value = float(self) 1508 return value 1509 1510 def ini_str(self): 1511 return '%f' % self.getValue() 1512
| 1614class Current(float, ParamValue): 1615 cxx_type = 'double' 1616 ex_str = "1mA" 1617 cmd_line_settable = False 1618 1619 def __new__(cls, value): 1620 # convert to current 1621 val = convert.toCurrent(value) 1622 return super(cls, Current).__new__(cls, val) 1623 1624 def __call__(self, value): 1625 val = convert.toCurrent(value) 1626 self.__init__(val) 1627 return value 1628 1629 def __str__(self): 1630 return str(self.getValue()) 1631 1632 def getValue(self): 1633 value = float(self) 1634 return value 1635 1636 def ini_str(self): 1637 return '%f' % self.getValue() 1638
|
| 1639 @classmethod 1640 def cxx_ini_predecls(cls, code): 1641 code('#include <sstream>') 1642 1643 @classmethod 1644 def cxx_ini_parse(self, code, src, dest, ret): 1645 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1646
|
1513class NetworkBandwidth(float,ParamValue): 1514 cxx_type = 'float' 1515 ex_str = "1Gbps" 1516 cmd_line_settable = True 1517 1518 def __new__(cls, value): 1519 # convert to bits per second 1520 val = convert.toNetworkBandwidth(value) 1521 return super(cls, NetworkBandwidth).__new__(cls, val) 1522 1523 def __str__(self): 1524 return str(self.val) 1525 1526 def __call__(self, value): 1527 val = convert.toNetworkBandwidth(value) 1528 self.__init__(val) 1529 return value 1530 1531 def getValue(self): 1532 # convert to seconds per byte 1533 value = 8.0 / float(self) 1534 # convert to ticks per byte 1535 value = ticks.fromSeconds(value) 1536 return float(value) 1537 1538 def ini_str(self): 1539 return '%f' % self.getValue() 1540 1541 def config_value(self): 1542 return '%f' % self.getValue() 1543
| 1647class NetworkBandwidth(float,ParamValue): 1648 cxx_type = 'float' 1649 ex_str = "1Gbps" 1650 cmd_line_settable = True 1651 1652 def __new__(cls, value): 1653 # convert to bits per second 1654 val = convert.toNetworkBandwidth(value) 1655 return super(cls, NetworkBandwidth).__new__(cls, val) 1656 1657 def __str__(self): 1658 return str(self.val) 1659 1660 def __call__(self, value): 1661 val = convert.toNetworkBandwidth(value) 1662 self.__init__(val) 1663 return value 1664 1665 def getValue(self): 1666 # convert to seconds per byte 1667 value = 8.0 / float(self) 1668 # convert to ticks per byte 1669 value = ticks.fromSeconds(value) 1670 return float(value) 1671 1672 def ini_str(self): 1673 return '%f' % self.getValue() 1674 1675 def config_value(self): 1676 return '%f' % self.getValue() 1677
|
| 1678 @classmethod 1679 def cxx_ini_predecls(cls, code): 1680 code('#include <sstream>') 1681 1682 @classmethod 1683 def cxx_ini_parse(self, code, src, dest, ret): 1684 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1685
|
1544class MemoryBandwidth(float,ParamValue): 1545 cxx_type = 'float' 1546 ex_str = "1GB/s" 1547 cmd_line_settable = True 1548 1549 def __new__(cls, value): 1550 # convert to bytes per second 1551 val = convert.toMemoryBandwidth(value) 1552 return super(cls, MemoryBandwidth).__new__(cls, val) 1553 1554 def __call__(self, value): 1555 val = convert.toMemoryBandwidth(value) 1556 self.__init__(val) 1557 return value 1558 1559 def getValue(self): 1560 # convert to seconds per byte 1561 value = float(self) 1562 if value: 1563 value = 1.0 / float(self) 1564 # convert to ticks per byte 1565 value = ticks.fromSeconds(value) 1566 return float(value) 1567 1568 def ini_str(self): 1569 return '%f' % self.getValue() 1570 1571 def config_value(self): 1572 return '%f' % self.getValue() 1573
| 1686class MemoryBandwidth(float,ParamValue): 1687 cxx_type = 'float' 1688 ex_str = "1GB/s" 1689 cmd_line_settable = True 1690 1691 def __new__(cls, value): 1692 # convert to bytes per second 1693 val = convert.toMemoryBandwidth(value) 1694 return super(cls, MemoryBandwidth).__new__(cls, val) 1695 1696 def __call__(self, value): 1697 val = convert.toMemoryBandwidth(value) 1698 self.__init__(val) 1699 return value 1700 1701 def getValue(self): 1702 # convert to seconds per byte 1703 value = float(self) 1704 if value: 1705 value = 1.0 / float(self) 1706 # convert to ticks per byte 1707 value = ticks.fromSeconds(value) 1708 return float(value) 1709 1710 def ini_str(self): 1711 return '%f' % self.getValue() 1712 1713 def config_value(self): 1714 return '%f' % self.getValue() 1715
|
| 1716 @classmethod 1717 def cxx_ini_predecls(cls, code): 1718 code('#include <sstream>') 1719 1720 @classmethod 1721 def cxx_ini_parse(self, code, src, dest, ret): 1722 code('%s (std::istringstream(%s) >> %s).eof();' % (ret, src, dest)) 1723
|
1574# 1575# "Constants"... handy aliases for various values. 1576# 1577 1578# Special class for NULL pointers. Note the special check in 1579# make_param_value() above that lets these be assigned where a 1580# SimObject is required. 1581# only one copy of a particular node 1582class NullSimObject(object): 1583 __metaclass__ = Singleton 1584 1585 def __call__(cls): 1586 return cls 1587 1588 def _instantiate(self, parent = None, path = ''): 1589 pass 1590 1591 def ini_str(self): 1592 return 'Null' 1593 1594 def unproxy(self, base): 1595 return self 1596 1597 def set_path(self, parent, name): 1598 pass 1599 1600 def __str__(self): 1601 return 'Null' 1602 1603 def config_value(self): 1604 return None 1605 1606 def getValue(self): 1607 return None 1608 1609# The only instance you'll ever need... 1610NULL = NullSimObject() 1611 1612def isNullPointer(value): 1613 return isinstance(value, NullSimObject) 1614 1615# Some memory range specifications use this as a default upper bound. 1616MaxAddr = Addr.max 1617MaxTick = Tick.max 1618AllMemory = AddrRange(0, MaxAddr) 1619 1620 1621##################################################################### 1622# 1623# Port objects 1624# 1625# Ports are used to interconnect objects in the memory system. 1626# 1627##################################################################### 1628 1629# Port reference: encapsulates a reference to a particular port on a 1630# particular SimObject. 1631class PortRef(object): 1632 def __init__(self, simobj, name, role): 1633 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1634 self.simobj = simobj 1635 self.name = name 1636 self.role = role 1637 self.peer = None # not associated with another port yet 1638 self.ccConnected = False # C++ port connection done? 1639 self.index = -1 # always -1 for non-vector ports 1640 1641 def __str__(self): 1642 return '%s.%s' % (self.simobj, self.name) 1643 1644 def __len__(self): 1645 # Return the number of connected ports, i.e. 0 is we have no 1646 # peer and 1 if we do. 1647 return int(self.peer != None) 1648 1649 # for config.ini, print peer's name (not ours) 1650 def ini_str(self): 1651 return str(self.peer) 1652 1653 # for config.json 1654 def get_config_as_dict(self): 1655 return {'role' : self.role, 'peer' : str(self.peer)} 1656 1657 def __getattr__(self, attr): 1658 if attr == 'peerObj': 1659 # shorthand for proxies 1660 return self.peer.simobj 1661 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1662 (self.__class__.__name__, attr) 1663 1664 # Full connection is symmetric (both ways). Called via 1665 # SimObject.__setattr__ as a result of a port assignment, e.g., 1666 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1667 # e.g., "obj1.portA[3] = obj2.portB". 1668 def connect(self, other): 1669 if isinstance(other, VectorPortRef): 1670 # reference to plain VectorPort is implicit append 1671 other = other._get_next() 1672 if self.peer and not proxy.isproxy(self.peer): 1673 fatal("Port %s is already connected to %s, cannot connect %s\n", 1674 self, self.peer, other); 1675 self.peer = other 1676 if proxy.isproxy(other): 1677 other.set_param_desc(PortParamDesc()) 1678 elif isinstance(other, PortRef): 1679 if other.peer is not self: 1680 other.connect(self) 1681 else: 1682 raise TypeError, \ 1683 "assigning non-port reference '%s' to port '%s'" \ 1684 % (other, self) 1685 1686 # Allow a master/slave port pair to be spliced between 1687 # a port and its connected peer. Useful operation for connecting 1688 # instrumentation structures into a system when it is necessary 1689 # to connect the instrumentation after the full system has been 1690 # constructed. 1691 def splice(self, new_master_peer, new_slave_peer): 1692 if self.peer and not proxy.isproxy(self.peer): 1693 if isinstance(new_master_peer, PortRef) and \ 1694 isinstance(new_slave_peer, PortRef): 1695 old_peer = self.peer 1696 if self.role == 'SLAVE': 1697 self.peer = new_master_peer 1698 old_peer.peer = new_slave_peer 1699 new_master_peer.connect(self) 1700 new_slave_peer.connect(old_peer) 1701 elif self.role == 'MASTER': 1702 self.peer = new_slave_peer 1703 old_peer.peer = new_master_peer 1704 new_slave_peer.connect(self) 1705 new_master_peer.connect(old_peer) 1706 else: 1707 panic("Port %s has unknown role, "+\ 1708 "cannot splice in new peers\n", self) 1709 else: 1710 raise TypeError, \ 1711 "Splicing non-port references '%s','%s' to port '%s'"\ 1712 % (new_peer, peers_new_peer, self) 1713 else: 1714 fatal("Port %s not connected, cannot splice in new peers\n", self) 1715 1716 def clone(self, simobj, memo): 1717 if memo.has_key(self): 1718 return memo[self] 1719 newRef = copy.copy(self) 1720 memo[self] = newRef 1721 newRef.simobj = simobj 1722 assert(isSimObject(newRef.simobj)) 1723 if self.peer and not proxy.isproxy(self.peer): 1724 peerObj = self.peer.simobj(_memo=memo) 1725 newRef.peer = self.peer.clone(peerObj, memo) 1726 assert(not isinstance(newRef.peer, VectorPortRef)) 1727 return newRef 1728 1729 def unproxy(self, simobj): 1730 assert(simobj is self.simobj) 1731 if proxy.isproxy(self.peer): 1732 try: 1733 realPeer = self.peer.unproxy(self.simobj) 1734 except: 1735 print "Error in unproxying port '%s' of %s" % \ 1736 (self.name, self.simobj.path()) 1737 raise 1738 self.connect(realPeer) 1739 1740 # Call C++ to create corresponding port connection between C++ objects 1741 def ccConnect(self): 1742 from m5.internal.pyobject import connectPorts 1743 1744 if self.role == 'SLAVE': 1745 # do nothing and let the master take care of it 1746 return 1747 1748 if self.ccConnected: # already done this 1749 return 1750 peer = self.peer 1751 if not self.peer: # nothing to connect to 1752 return 1753 1754 # check that we connect a master to a slave 1755 if self.role == peer.role: 1756 raise TypeError, \ 1757 "cannot connect '%s' and '%s' due to identical role '%s'" \ 1758 % (peer, self, self.role) 1759 1760 try: 1761 # self is always the master and peer the slave 1762 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1763 peer.simobj.getCCObject(), peer.name, peer.index) 1764 except: 1765 print "Error connecting port %s.%s to %s.%s" % \ 1766 (self.simobj.path(), self.name, 1767 peer.simobj.path(), peer.name) 1768 raise 1769 self.ccConnected = True 1770 peer.ccConnected = True 1771 1772# A reference to an individual element of a VectorPort... much like a 1773# PortRef, but has an index. 1774class VectorPortElementRef(PortRef): 1775 def __init__(self, simobj, name, role, index): 1776 PortRef.__init__(self, simobj, name, role) 1777 self.index = index 1778 1779 def __str__(self): 1780 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1781 1782# A reference to a complete vector-valued port (not just a single element). 1783# Can be indexed to retrieve individual VectorPortElementRef instances. 1784class VectorPortRef(object): 1785 def __init__(self, simobj, name, role): 1786 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1787 self.simobj = simobj 1788 self.name = name 1789 self.role = role 1790 self.elements = [] 1791 1792 def __str__(self): 1793 return '%s.%s[:]' % (self.simobj, self.name) 1794 1795 def __len__(self): 1796 # Return the number of connected peers, corresponding the the 1797 # length of the elements. 1798 return len(self.elements) 1799 1800 # for config.ini, print peer's name (not ours) 1801 def ini_str(self): 1802 return ' '.join([el.ini_str() for el in self.elements]) 1803 1804 # for config.json 1805 def get_config_as_dict(self): 1806 return {'role' : self.role, 1807 'peer' : [el.ini_str() for el in self.elements]} 1808 1809 def __getitem__(self, key): 1810 if not isinstance(key, int): 1811 raise TypeError, "VectorPort index must be integer" 1812 if key >= len(self.elements): 1813 # need to extend list 1814 ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 1815 for i in range(len(self.elements), key+1)] 1816 self.elements.extend(ext) 1817 return self.elements[key] 1818 1819 def _get_next(self): 1820 return self[len(self.elements)] 1821 1822 def __setitem__(self, key, value): 1823 if not isinstance(key, int): 1824 raise TypeError, "VectorPort index must be integer" 1825 self[key].connect(value) 1826 1827 def connect(self, other): 1828 if isinstance(other, (list, tuple)): 1829 # Assign list of port refs to vector port. 1830 # For now, append them... not sure if that's the right semantics 1831 # or if it should replace the current vector. 1832 for ref in other: 1833 self._get_next().connect(ref) 1834 else: 1835 # scalar assignment to plain VectorPort is implicit append 1836 self._get_next().connect(other) 1837 1838 def clone(self, simobj, memo): 1839 if memo.has_key(self): 1840 return memo[self] 1841 newRef = copy.copy(self) 1842 memo[self] = newRef 1843 newRef.simobj = simobj 1844 assert(isSimObject(newRef.simobj)) 1845 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 1846 return newRef 1847 1848 def unproxy(self, simobj): 1849 [el.unproxy(simobj) for el in self.elements] 1850 1851 def ccConnect(self): 1852 [el.ccConnect() for el in self.elements] 1853 1854# Port description object. Like a ParamDesc object, this represents a 1855# logical port in the SimObject class, not a particular port on a 1856# SimObject instance. The latter are represented by PortRef objects. 1857class Port(object): 1858 # Generate a PortRef for this port on the given SimObject with the 1859 # given name 1860 def makeRef(self, simobj): 1861 return PortRef(simobj, self.name, self.role) 1862 1863 # Connect an instance of this port (on the given SimObject with 1864 # the given name) with the port described by the supplied PortRef 1865 def connect(self, simobj, ref): 1866 self.makeRef(simobj).connect(ref) 1867 1868 # No need for any pre-declarations at the moment as we merely rely 1869 # on an unsigned int. 1870 def cxx_predecls(self, code): 1871 pass 1872 1873 # Declare an unsigned int with the same name as the port, that 1874 # will eventually hold the number of connected ports (and thus the 1875 # number of elements for a VectorPort). 1876 def cxx_decl(self, code): 1877 code('unsigned int port_${{self.name}}_connection_count;') 1878 1879class MasterPort(Port): 1880 # MasterPort("description") 1881 def __init__(self, *args): 1882 if len(args) == 1: 1883 self.desc = args[0] 1884 self.role = 'MASTER' 1885 else: 1886 raise TypeError, 'wrong number of arguments' 1887 1888class SlavePort(Port): 1889 # SlavePort("description") 1890 def __init__(self, *args): 1891 if len(args) == 1: 1892 self.desc = args[0] 1893 self.role = 'SLAVE' 1894 else: 1895 raise TypeError, 'wrong number of arguments' 1896 1897# VectorPort description object. Like Port, but represents a vector 1898# of connections (e.g., as on a XBar). 1899class VectorPort(Port): 1900 def __init__(self, *args): 1901 self.isVec = True 1902 1903 def makeRef(self, simobj): 1904 return VectorPortRef(simobj, self.name, self.role) 1905 1906class VectorMasterPort(VectorPort): 1907 # VectorMasterPort("description") 1908 def __init__(self, *args): 1909 if len(args) == 1: 1910 self.desc = args[0] 1911 self.role = 'MASTER' 1912 VectorPort.__init__(self, *args) 1913 else: 1914 raise TypeError, 'wrong number of arguments' 1915 1916class VectorSlavePort(VectorPort): 1917 # VectorSlavePort("description") 1918 def __init__(self, *args): 1919 if len(args) == 1: 1920 self.desc = args[0] 1921 self.role = 'SLAVE' 1922 VectorPort.__init__(self, *args) 1923 else: 1924 raise TypeError, 'wrong number of arguments' 1925 1926# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 1927# proxy objects (via set_param_desc()) so that proxy error messages 1928# make sense. 1929class PortParamDesc(object): 1930 __metaclass__ = Singleton 1931 1932 ptype_str = 'Port' 1933 ptype = Port 1934 1935baseEnums = allEnums.copy() 1936baseParams = allParams.copy() 1937 1938def clear(): 1939 global allEnums, allParams 1940 1941 allEnums = baseEnums.copy() 1942 allParams = baseParams.copy() 1943 1944__all__ = ['Param', 'VectorParam', 1945 'Enum', 'Bool', 'String', 'Float', 1946 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 1947 'Int32', 'UInt32', 'Int64', 'UInt64', 1948 'Counter', 'Addr', 'Tick', 'Percent', 1949 'TcpPort', 'UdpPort', 'EthernetAddr', 1950 'IpAddress', 'IpNetmask', 'IpWithPort', 1951 'MemorySize', 'MemorySize32', 1952 'Latency', 'Frequency', 'Clock', 'Voltage', 1953 'NetworkBandwidth', 'MemoryBandwidth', 1954 'AddrRange', 1955 'MaxAddr', 'MaxTick', 'AllMemory', 1956 'Time', 1957 'NextEthernetAddr', 'NULL', 1958 'MasterPort', 'SlavePort', 1959 'VectorMasterPort', 'VectorSlavePort'] 1960 1961import SimObject
| 1724# 1725# "Constants"... handy aliases for various values. 1726# 1727 1728# Special class for NULL pointers. Note the special check in 1729# make_param_value() above that lets these be assigned where a 1730# SimObject is required. 1731# only one copy of a particular node 1732class NullSimObject(object): 1733 __metaclass__ = Singleton 1734 1735 def __call__(cls): 1736 return cls 1737 1738 def _instantiate(self, parent = None, path = ''): 1739 pass 1740 1741 def ini_str(self): 1742 return 'Null' 1743 1744 def unproxy(self, base): 1745 return self 1746 1747 def set_path(self, parent, name): 1748 pass 1749 1750 def __str__(self): 1751 return 'Null' 1752 1753 def config_value(self): 1754 return None 1755 1756 def getValue(self): 1757 return None 1758 1759# The only instance you'll ever need... 1760NULL = NullSimObject() 1761 1762def isNullPointer(value): 1763 return isinstance(value, NullSimObject) 1764 1765# Some memory range specifications use this as a default upper bound. 1766MaxAddr = Addr.max 1767MaxTick = Tick.max 1768AllMemory = AddrRange(0, MaxAddr) 1769 1770 1771##################################################################### 1772# 1773# Port objects 1774# 1775# Ports are used to interconnect objects in the memory system. 1776# 1777##################################################################### 1778 1779# Port reference: encapsulates a reference to a particular port on a 1780# particular SimObject. 1781class PortRef(object): 1782 def __init__(self, simobj, name, role): 1783 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1784 self.simobj = simobj 1785 self.name = name 1786 self.role = role 1787 self.peer = None # not associated with another port yet 1788 self.ccConnected = False # C++ port connection done? 1789 self.index = -1 # always -1 for non-vector ports 1790 1791 def __str__(self): 1792 return '%s.%s' % (self.simobj, self.name) 1793 1794 def __len__(self): 1795 # Return the number of connected ports, i.e. 0 is we have no 1796 # peer and 1 if we do. 1797 return int(self.peer != None) 1798 1799 # for config.ini, print peer's name (not ours) 1800 def ini_str(self): 1801 return str(self.peer) 1802 1803 # for config.json 1804 def get_config_as_dict(self): 1805 return {'role' : self.role, 'peer' : str(self.peer)} 1806 1807 def __getattr__(self, attr): 1808 if attr == 'peerObj': 1809 # shorthand for proxies 1810 return self.peer.simobj 1811 raise AttributeError, "'%s' object has no attribute '%s'" % \ 1812 (self.__class__.__name__, attr) 1813 1814 # Full connection is symmetric (both ways). Called via 1815 # SimObject.__setattr__ as a result of a port assignment, e.g., 1816 # "obj1.portA = obj2.portB", or via VectorPortElementRef.__setitem__, 1817 # e.g., "obj1.portA[3] = obj2.portB". 1818 def connect(self, other): 1819 if isinstance(other, VectorPortRef): 1820 # reference to plain VectorPort is implicit append 1821 other = other._get_next() 1822 if self.peer and not proxy.isproxy(self.peer): 1823 fatal("Port %s is already connected to %s, cannot connect %s\n", 1824 self, self.peer, other); 1825 self.peer = other 1826 if proxy.isproxy(other): 1827 other.set_param_desc(PortParamDesc()) 1828 elif isinstance(other, PortRef): 1829 if other.peer is not self: 1830 other.connect(self) 1831 else: 1832 raise TypeError, \ 1833 "assigning non-port reference '%s' to port '%s'" \ 1834 % (other, self) 1835 1836 # Allow a master/slave port pair to be spliced between 1837 # a port and its connected peer. Useful operation for connecting 1838 # instrumentation structures into a system when it is necessary 1839 # to connect the instrumentation after the full system has been 1840 # constructed. 1841 def splice(self, new_master_peer, new_slave_peer): 1842 if self.peer and not proxy.isproxy(self.peer): 1843 if isinstance(new_master_peer, PortRef) and \ 1844 isinstance(new_slave_peer, PortRef): 1845 old_peer = self.peer 1846 if self.role == 'SLAVE': 1847 self.peer = new_master_peer 1848 old_peer.peer = new_slave_peer 1849 new_master_peer.connect(self) 1850 new_slave_peer.connect(old_peer) 1851 elif self.role == 'MASTER': 1852 self.peer = new_slave_peer 1853 old_peer.peer = new_master_peer 1854 new_slave_peer.connect(self) 1855 new_master_peer.connect(old_peer) 1856 else: 1857 panic("Port %s has unknown role, "+\ 1858 "cannot splice in new peers\n", self) 1859 else: 1860 raise TypeError, \ 1861 "Splicing non-port references '%s','%s' to port '%s'"\ 1862 % (new_peer, peers_new_peer, self) 1863 else: 1864 fatal("Port %s not connected, cannot splice in new peers\n", self) 1865 1866 def clone(self, simobj, memo): 1867 if memo.has_key(self): 1868 return memo[self] 1869 newRef = copy.copy(self) 1870 memo[self] = newRef 1871 newRef.simobj = simobj 1872 assert(isSimObject(newRef.simobj)) 1873 if self.peer and not proxy.isproxy(self.peer): 1874 peerObj = self.peer.simobj(_memo=memo) 1875 newRef.peer = self.peer.clone(peerObj, memo) 1876 assert(not isinstance(newRef.peer, VectorPortRef)) 1877 return newRef 1878 1879 def unproxy(self, simobj): 1880 assert(simobj is self.simobj) 1881 if proxy.isproxy(self.peer): 1882 try: 1883 realPeer = self.peer.unproxy(self.simobj) 1884 except: 1885 print "Error in unproxying port '%s' of %s" % \ 1886 (self.name, self.simobj.path()) 1887 raise 1888 self.connect(realPeer) 1889 1890 # Call C++ to create corresponding port connection between C++ objects 1891 def ccConnect(self): 1892 from m5.internal.pyobject import connectPorts 1893 1894 if self.role == 'SLAVE': 1895 # do nothing and let the master take care of it 1896 return 1897 1898 if self.ccConnected: # already done this 1899 return 1900 peer = self.peer 1901 if not self.peer: # nothing to connect to 1902 return 1903 1904 # check that we connect a master to a slave 1905 if self.role == peer.role: 1906 raise TypeError, \ 1907 "cannot connect '%s' and '%s' due to identical role '%s'" \ 1908 % (peer, self, self.role) 1909 1910 try: 1911 # self is always the master and peer the slave 1912 connectPorts(self.simobj.getCCObject(), self.name, self.index, 1913 peer.simobj.getCCObject(), peer.name, peer.index) 1914 except: 1915 print "Error connecting port %s.%s to %s.%s" % \ 1916 (self.simobj.path(), self.name, 1917 peer.simobj.path(), peer.name) 1918 raise 1919 self.ccConnected = True 1920 peer.ccConnected = True 1921 1922# A reference to an individual element of a VectorPort... much like a 1923# PortRef, but has an index. 1924class VectorPortElementRef(PortRef): 1925 def __init__(self, simobj, name, role, index): 1926 PortRef.__init__(self, simobj, name, role) 1927 self.index = index 1928 1929 def __str__(self): 1930 return '%s.%s[%d]' % (self.simobj, self.name, self.index) 1931 1932# A reference to a complete vector-valued port (not just a single element). 1933# Can be indexed to retrieve individual VectorPortElementRef instances. 1934class VectorPortRef(object): 1935 def __init__(self, simobj, name, role): 1936 assert(isSimObject(simobj) or isSimObjectClass(simobj)) 1937 self.simobj = simobj 1938 self.name = name 1939 self.role = role 1940 self.elements = [] 1941 1942 def __str__(self): 1943 return '%s.%s[:]' % (self.simobj, self.name) 1944 1945 def __len__(self): 1946 # Return the number of connected peers, corresponding the the 1947 # length of the elements. 1948 return len(self.elements) 1949 1950 # for config.ini, print peer's name (not ours) 1951 def ini_str(self): 1952 return ' '.join([el.ini_str() for el in self.elements]) 1953 1954 # for config.json 1955 def get_config_as_dict(self): 1956 return {'role' : self.role, 1957 'peer' : [el.ini_str() for el in self.elements]} 1958 1959 def __getitem__(self, key): 1960 if not isinstance(key, int): 1961 raise TypeError, "VectorPort index must be integer" 1962 if key >= len(self.elements): 1963 # need to extend list 1964 ext = [VectorPortElementRef(self.simobj, self.name, self.role, i) 1965 for i in range(len(self.elements), key+1)] 1966 self.elements.extend(ext) 1967 return self.elements[key] 1968 1969 def _get_next(self): 1970 return self[len(self.elements)] 1971 1972 def __setitem__(self, key, value): 1973 if not isinstance(key, int): 1974 raise TypeError, "VectorPort index must be integer" 1975 self[key].connect(value) 1976 1977 def connect(self, other): 1978 if isinstance(other, (list, tuple)): 1979 # Assign list of port refs to vector port. 1980 # For now, append them... not sure if that's the right semantics 1981 # or if it should replace the current vector. 1982 for ref in other: 1983 self._get_next().connect(ref) 1984 else: 1985 # scalar assignment to plain VectorPort is implicit append 1986 self._get_next().connect(other) 1987 1988 def clone(self, simobj, memo): 1989 if memo.has_key(self): 1990 return memo[self] 1991 newRef = copy.copy(self) 1992 memo[self] = newRef 1993 newRef.simobj = simobj 1994 assert(isSimObject(newRef.simobj)) 1995 newRef.elements = [el.clone(simobj, memo) for el in self.elements] 1996 return newRef 1997 1998 def unproxy(self, simobj): 1999 [el.unproxy(simobj) for el in self.elements] 2000 2001 def ccConnect(self): 2002 [el.ccConnect() for el in self.elements] 2003 2004# Port description object. Like a ParamDesc object, this represents a 2005# logical port in the SimObject class, not a particular port on a 2006# SimObject instance. The latter are represented by PortRef objects. 2007class Port(object): 2008 # Generate a PortRef for this port on the given SimObject with the 2009 # given name 2010 def makeRef(self, simobj): 2011 return PortRef(simobj, self.name, self.role) 2012 2013 # Connect an instance of this port (on the given SimObject with 2014 # the given name) with the port described by the supplied PortRef 2015 def connect(self, simobj, ref): 2016 self.makeRef(simobj).connect(ref) 2017 2018 # No need for any pre-declarations at the moment as we merely rely 2019 # on an unsigned int. 2020 def cxx_predecls(self, code): 2021 pass 2022 2023 # Declare an unsigned int with the same name as the port, that 2024 # will eventually hold the number of connected ports (and thus the 2025 # number of elements for a VectorPort). 2026 def cxx_decl(self, code): 2027 code('unsigned int port_${{self.name}}_connection_count;') 2028 2029class MasterPort(Port): 2030 # MasterPort("description") 2031 def __init__(self, *args): 2032 if len(args) == 1: 2033 self.desc = args[0] 2034 self.role = 'MASTER' 2035 else: 2036 raise TypeError, 'wrong number of arguments' 2037 2038class SlavePort(Port): 2039 # SlavePort("description") 2040 def __init__(self, *args): 2041 if len(args) == 1: 2042 self.desc = args[0] 2043 self.role = 'SLAVE' 2044 else: 2045 raise TypeError, 'wrong number of arguments' 2046 2047# VectorPort description object. Like Port, but represents a vector 2048# of connections (e.g., as on a XBar). 2049class VectorPort(Port): 2050 def __init__(self, *args): 2051 self.isVec = True 2052 2053 def makeRef(self, simobj): 2054 return VectorPortRef(simobj, self.name, self.role) 2055 2056class VectorMasterPort(VectorPort): 2057 # VectorMasterPort("description") 2058 def __init__(self, *args): 2059 if len(args) == 1: 2060 self.desc = args[0] 2061 self.role = 'MASTER' 2062 VectorPort.__init__(self, *args) 2063 else: 2064 raise TypeError, 'wrong number of arguments' 2065 2066class VectorSlavePort(VectorPort): 2067 # VectorSlavePort("description") 2068 def __init__(self, *args): 2069 if len(args) == 1: 2070 self.desc = args[0] 2071 self.role = 'SLAVE' 2072 VectorPort.__init__(self, *args) 2073 else: 2074 raise TypeError, 'wrong number of arguments' 2075 2076# 'Fake' ParamDesc for Port references to assign to the _pdesc slot of 2077# proxy objects (via set_param_desc()) so that proxy error messages 2078# make sense. 2079class PortParamDesc(object): 2080 __metaclass__ = Singleton 2081 2082 ptype_str = 'Port' 2083 ptype = Port 2084 2085baseEnums = allEnums.copy() 2086baseParams = allParams.copy() 2087 2088def clear(): 2089 global allEnums, allParams 2090 2091 allEnums = baseEnums.copy() 2092 allParams = baseParams.copy() 2093 2094__all__ = ['Param', 'VectorParam', 2095 'Enum', 'Bool', 'String', 'Float', 2096 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 2097 'Int32', 'UInt32', 'Int64', 'UInt64', 2098 'Counter', 'Addr', 'Tick', 'Percent', 2099 'TcpPort', 'UdpPort', 'EthernetAddr', 2100 'IpAddress', 'IpNetmask', 'IpWithPort', 2101 'MemorySize', 'MemorySize32', 2102 'Latency', 'Frequency', 'Clock', 'Voltage', 2103 'NetworkBandwidth', 'MemoryBandwidth', 2104 'AddrRange', 2105 'MaxAddr', 'MaxTick', 'AllMemory', 2106 'Time', 2107 'NextEthernetAddr', 'NULL', 2108 'MasterPort', 'SlavePort', 2109 'VectorMasterPort', 'VectorSlavePort'] 2110 2111import SimObject
|