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