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