SimObject.py (7534:c76a14014c27) | SimObject.py (7673:b28bd1fa9a35) |
---|---|
1# Copyright (c) 2004-2006 The Regents of The University of Michigan 2# Copyright (c) 2010 Advanced Micro Devices, Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; --- 15 unchanged lines hidden (view full) --- 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# Authors: Steve Reinhardt 29# Nathan Binkert 30 31import sys | 1# Copyright (c) 2004-2006 The Regents of The University of Michigan 2# Copyright (c) 2010 Advanced Micro Devices, Inc. 3# All rights reserved. 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: redistributions of source code must retain the above copyright 8# notice, this list of conditions and the following disclaimer; --- 15 unchanged lines hidden (view full) --- 24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27# 28# Authors: Steve Reinhardt 29# Nathan Binkert 30 31import sys |
32from types import FunctionType | 32from types import FunctionType, MethodType |
33 34try: 35 import pydot 36except: 37 pydot = False 38 39import m5 40from m5.util import * --- 51 unchanged lines hidden (view full) --- 92##################################################################### 93 94# list of all SimObject classes 95allClasses = {} 96 97# dict to look up SimObjects based on path 98instanceDict = {} 99 | 33 34try: 35 import pydot 36except: 37 pydot = False 38 39import m5 40from m5.util import * --- 51 unchanged lines hidden (view full) --- 92##################################################################### 93 94# list of all SimObject classes 95allClasses = {} 96 97# dict to look up SimObjects based on path 98instanceDict = {} 99 |
100def default_cxx_predecls(cls, code): 101 '''A forward class declaration is sufficient since we are 102 just declaring a pointer.''' 103 104 class_path = cls._value_dict['cxx_class'].split('::') 105 for ns in class_path[:-1]: 106 code('namespace $ns {') 107 code('class $0;', class_path[-1]) 108 for ns in reversed(class_path[:-1]): 109 code('/* namespace $ns */ }') 110 111def default_swig_objdecls(cls, code): 112 class_path = cls.cxx_class.split('::') 113 classname = class_path[-1] 114 namespaces = class_path[:-1] 115 116 for ns in namespaces: 117 code('namespace $ns {') 118 119 if namespaces: 120 code('// avoid name conflicts') 121 sep_string = '_COLONS_' 122 flat_name = sep_string.join(class_path) 123 code('%rename($flat_name) $classname;') 124 125 code() 126 code('// stop swig from creating/wrapping default ctor/dtor') 127 code('%nodefault $classname;') 128 code('class $classname') 129 if cls._base: 130 code(' : public ${{cls._base.cxx_class}}') 131 code('{};') 132 133 for ns in reversed(namespaces): 134 code('/* namespace $ns */ }') 135 136def public_value(key, value): 137 return key.startswith('_') or \ 138 isinstance(value, (FunctionType, MethodType, classmethod, type)) 139 |
|
100# The metaclass for SimObject. This class controls how new classes 101# that derive from SimObject are instantiated, and provides inherited 102# class behavior (just like a class controls how instances of that 103# class are instantiated, and provides inherited instance behavior). 104class MetaSimObject(type): 105 # Attributes that can be set only at initialization time 106 init_keywords = { 'abstract' : bool, 107 'cxx_class' : str, 108 'cxx_type' : str, | 140# The metaclass for SimObject. This class controls how new classes 141# that derive from SimObject are instantiated, and provides inherited 142# class behavior (just like a class controls how instances of that 143# class are instantiated, and provides inherited instance behavior). 144class MetaSimObject(type): 145 # Attributes that can be set only at initialization time 146 init_keywords = { 'abstract' : bool, 147 'cxx_class' : str, 148 'cxx_type' : str, |
109 'cxx_predecls' : list, 110 'swig_objdecls' : list, 111 'swig_predecls' : list, | 149 'cxx_predecls' : MethodType, 150 'swig_objdecls' : MethodType, 151 'swig_predecls' : MethodType, |
112 'type' : str } 113 # Attributes that can be set any time 114 keywords = { 'check' : FunctionType } 115 116 # __new__ is called before __init__, and is where the statements 117 # in the body of the class definition get loaded into the class's 118 # __dict__. We intercept this to filter out parameter & port assignments 119 # and only allow "private" attributes to be passed to the base 120 # __new__ (starting with underscore). 121 def __new__(mcls, name, bases, dict): 122 assert name not in allClasses, "SimObject %s already present" % name 123 124 # Copy "private" attributes, functions, and classes to the 125 # official dict. Everything else goes in _init_dict to be 126 # filtered in __init__. 127 cls_dict = {} 128 value_dict = {} 129 for key,val in dict.items(): | 152 'type' : str } 153 # Attributes that can be set any time 154 keywords = { 'check' : FunctionType } 155 156 # __new__ is called before __init__, and is where the statements 157 # in the body of the class definition get loaded into the class's 158 # __dict__. We intercept this to filter out parameter & port assignments 159 # and only allow "private" attributes to be passed to the base 160 # __new__ (starting with underscore). 161 def __new__(mcls, name, bases, dict): 162 assert name not in allClasses, "SimObject %s already present" % name 163 164 # Copy "private" attributes, functions, and classes to the 165 # official dict. Everything else goes in _init_dict to be 166 # filtered in __init__. 167 cls_dict = {} 168 value_dict = {} 169 for key,val in dict.items(): |
130 if key.startswith('_') or isinstance(val, (FunctionType, 131 classmethod, 132 type)): | 170 if public_value(key, val): |
133 cls_dict[key] = val 134 else: 135 # must be a param/port setting 136 value_dict[key] = val 137 if 'abstract' not in value_dict: 138 value_dict['abstract'] = False 139 cls_dict['_value_dict'] = value_dict 140 cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) --- 44 unchanged lines hidden (view full) --- 185 186 # default keyword values 187 if 'type' in cls._value_dict: 188 if 'cxx_class' not in cls._value_dict: 189 cls._value_dict['cxx_class'] = cls._value_dict['type'] 190 191 cls._value_dict['cxx_type'] = '%s *' % cls._value_dict['cxx_class'] 192 | 171 cls_dict[key] = val 172 else: 173 # must be a param/port setting 174 value_dict[key] = val 175 if 'abstract' not in value_dict: 176 value_dict['abstract'] = False 177 cls_dict['_value_dict'] = value_dict 178 cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) --- 44 unchanged lines hidden (view full) --- 223 224 # default keyword values 225 if 'type' in cls._value_dict: 226 if 'cxx_class' not in cls._value_dict: 227 cls._value_dict['cxx_class'] = cls._value_dict['type'] 228 229 cls._value_dict['cxx_type'] = '%s *' % cls._value_dict['cxx_class'] 230 |
193 if 'cxx_predecls' not in cls._value_dict: 194 # A forward class declaration is sufficient since we are 195 # just declaring a pointer. 196 class_path = cls._value_dict['cxx_class'].split('::') 197 class_path.reverse() 198 decl = 'class %s;' % class_path[0] 199 for ns in class_path[1:]: 200 decl = 'namespace %s { %s }' % (ns, decl) 201 cls._value_dict['cxx_predecls'] = [decl] | 231 if 'cxx_predecls' not in cls.__dict__: 232 m = MethodType(default_cxx_predecls, cls, MetaSimObject) 233 setattr(cls, 'cxx_predecls', m) |
202 | 234 |
203 if 'swig_predecls' not in cls._value_dict: 204 # A forward class declaration is sufficient since we are 205 # just declaring a pointer. 206 cls._value_dict['swig_predecls'] = \ 207 cls._value_dict['cxx_predecls'] | 235 if 'swig_predecls' not in cls.__dict__: 236 setattr(cls, 'swig_predecls', getattr(cls, 'cxx_predecls')) |
208 | 237 |
209 if 'swig_objdecls' not in cls._value_dict: 210 cls._value_dict['swig_objdecls'] = [] | 238 if 'swig_objdecls' not in cls.__dict__: 239 m = MethodType(default_swig_objdecls, cls, MetaSimObject) 240 setattr(cls, 'swig_objdecls', m) |
211 212 # Now process the _value_dict items. They could be defining 213 # new (or overriding existing) parameters or ports, setting 214 # class keywords (e.g., 'abstract'), or setting parameter 215 # values or port bindings. The first 3 can only be set when 216 # the class is defined, so we handle them here. The others 217 # can be set later too, so just emulate that by calling 218 # setattr(). --- 58 unchanged lines hidden (view full) --- 277 ref = cls._ports[attr].makeRef(cls) 278 cls._port_refs[attr] = ref 279 return ref 280 281 # Set attribute (called on foo.attr = value when foo is an 282 # instance of class cls). 283 def __setattr__(cls, attr, value): 284 # normal processing for private attributes | 241 242 # Now process the _value_dict items. They could be defining 243 # new (or overriding existing) parameters or ports, setting 244 # class keywords (e.g., 'abstract'), or setting parameter 245 # values or port bindings. The first 3 can only be set when 246 # the class is defined, so we handle them here. The others 247 # can be set later too, so just emulate that by calling 248 # setattr(). --- 58 unchanged lines hidden (view full) --- 307 ref = cls._ports[attr].makeRef(cls) 308 cls._port_refs[attr] = ref 309 return ref 310 311 # Set attribute (called on foo.attr = value when foo is an 312 # instance of class cls). 313 def __setattr__(cls, attr, value): 314 # normal processing for private attributes |
285 if attr.startswith('_'): | 315 if public_value(attr, value): |
286 type.__setattr__(cls, attr, value) 287 return 288 289 if cls.keywords.has_key(attr): 290 cls._set_keyword(attr, value, cls.keywords[attr]) 291 return 292 293 if cls._ports.has_key(attr): --- 29 unchanged lines hidden (view full) --- 323 return cls._children[attr] 324 325 raise AttributeError, \ 326 "object '%s' has no attribute '%s'" % (cls.__name__, attr) 327 328 def __str__(cls): 329 return cls.__name__ 330 | 316 type.__setattr__(cls, attr, value) 317 return 318 319 if cls.keywords.has_key(attr): 320 cls._set_keyword(attr, value, cls.keywords[attr]) 321 return 322 323 if cls._ports.has_key(attr): --- 29 unchanged lines hidden (view full) --- 353 return cls._children[attr] 354 355 raise AttributeError, \ 356 "object '%s' has no attribute '%s'" % (cls.__name__, attr) 357 358 def __str__(cls): 359 return cls.__name__ 360 |
331 def cxx_decl(cls): 332 code = "#ifndef __PARAMS__%s\n" % cls 333 code += "#define __PARAMS__%s\n\n" % cls | 361 def cxx_decl(cls, code): 362 code('''\ 363#ifndef __PARAMS__${cls}__ 364#define __PARAMS__${cls}__ |
334 | 365 |
366''') 367 |
|
335 # The 'dict' attribute restricts us to the params declared in 336 # the object itself, not including inherited params (which 337 # will also be inherited from the base class's param struct 338 # here). 339 params = cls._params.local.values() 340 try: 341 ptypes = [p.ptype for p in params] 342 except: 343 print cls, p, p.ptype_str 344 print params 345 raise 346 | 368 # The 'dict' attribute restricts us to the params declared in 369 # the object itself, not including inherited params (which 370 # will also be inherited from the base class's param struct 371 # here). 372 params = cls._params.local.values() 373 try: 374 ptypes = [p.ptype for p in params] 375 except: 376 print cls, p, p.ptype_str 377 print params 378 raise 379 |
347 # get a list of lists of predeclaration lines 348 predecls = [] 349 predecls.extend(cls.cxx_predecls) 350 for p in params: 351 predecls.extend(p.cxx_predecls()) 352 # remove redundant lines 353 predecls2 = [] 354 for pd in predecls: 355 if pd not in predecls2: 356 predecls2.append(pd) 357 predecls2.sort() 358 code += "\n".join(predecls2) 359 code += "\n\n"; | 380 # get all predeclarations 381 cls.cxx_predecls(code) 382 for param in params: 383 param.cxx_predecls(code) 384 code() |
360 361 if cls._base: | 385 386 if cls._base: |
362 code += '#include "params/%s.hh"\n\n' % cls._base.type | 387 code('#include "params/${{cls._base.type}}.hh"') 388 code() |
363 364 for ptype in ptypes: 365 if issubclass(ptype, Enum): | 389 390 for ptype in ptypes: 391 if issubclass(ptype, Enum): |
366 code += '#include "enums/%s.hh"\n' % ptype.__name__ 367 code += "\n\n" | 392 code('#include "enums/${{ptype.__name__}}.hh"') 393 code() |
368 | 394 |
369 code += cls.cxx_struct(cls._base, params) | 395 cls.cxx_struct(code, cls._base, params) |
370 371 # close #ifndef __PARAMS__* guard | 396 397 # close #ifndef __PARAMS__* guard |
372 code += "\n#endif\n" | 398 code() 399 code('#endif // __PARAMS__${cls}__') |
373 return code 374 | 400 return code 401 |
375 def cxx_struct(cls, base, params): | 402 def cxx_struct(cls, code, base, params): |
376 if cls == SimObject: | 403 if cls == SimObject: |
377 return '#include "sim/sim_object_params.hh"\n' | 404 code('#include "sim/sim_object_params.hh"') 405 return |
378 379 # now generate the actual param struct | 406 407 # now generate the actual param struct |
380 code = "struct %sParams" % cls | 408 code("struct ${cls}Params") |
381 if base: | 409 if base: |
382 code += " : public %sParams" % base.type 383 code += "\n{\n" | 410 code(" : public ${{base.type}}Params") 411 code("{") |
384 if not hasattr(cls, 'abstract') or not cls.abstract: 385 if 'type' in cls.__dict__: | 412 if not hasattr(cls, 'abstract') or not cls.abstract: 413 if 'type' in cls.__dict__: |
386 code += " %s create();\n" % cls.cxx_type 387 decls = [p.cxx_decl() for p in params] 388 decls.sort() 389 code += "".join([" %s\n" % d for d in decls]) 390 code += "};\n" | 414 code(" ${{cls.cxx_type}} create();") |
391 | 415 |
392 return code | 416 code.indent() 417 for param in params: 418 param.cxx_decl(code) 419 code.dedent() 420 code('};') |
393 | 421 |
394 def swig_decl(cls): 395 code = '%%module %s\n' % cls | 422 def swig_decl(cls, code): 423 code('''\ 424%module $cls |
396 | 425 |
397 code += '%{\n' 398 code += '#include "params/%s.hh"\n' % cls 399 code += '%}\n\n' | 426%{ 427#include "params/$cls.hh" 428%} |
400 | 429 |
430''') 431 |
|
401 # The 'dict' attribute restricts us to the params declared in 402 # the object itself, not including inherited params (which 403 # will also be inherited from the base class's param struct 404 # here). 405 params = cls._params.local.values() 406 ptypes = [p.ptype for p in params] 407 | 432 # The 'dict' attribute restricts us to the params declared in 433 # the object itself, not including inherited params (which 434 # will also be inherited from the base class's param struct 435 # here). 436 params = cls._params.local.values() 437 ptypes = [p.ptype for p in params] 438 |
408 # get a list of lists of predeclaration lines 409 predecls = [] 410 predecls.extend([ p.swig_predecls() for p in params ]) 411 # flatten 412 predecls = reduce(lambda x,y:x+y, predecls, []) 413 # remove redundant lines 414 predecls2 = [] 415 for pd in predecls: 416 if pd not in predecls2: 417 predecls2.append(pd) 418 predecls2.sort() 419 code += "\n".join(predecls2) 420 code += "\n\n"; | 439 # get all predeclarations 440 for param in params: 441 param.swig_predecls(code) 442 code() |
421 422 if cls._base: | 443 444 if cls._base: |
423 code += '%%import "params/%s.i"\n\n' % cls._base.type | 445 code('%import "params/${{cls._base.type}}.i"') 446 code() |
424 425 for ptype in ptypes: 426 if issubclass(ptype, Enum): | 447 448 for ptype in ptypes: 449 if issubclass(ptype, Enum): |
427 code += '%%import "enums/%s.hh"\n' % ptype.__name__ 428 code += "\n\n" | 450 code('%import "enums/${{ptype.__name__}}.hh"') 451 code() |
429 | 452 |
430 code += '%%import "params/%s_type.hh"\n\n' % cls 431 code += '%%include "params/%s.hh"\n\n' % cls | 453 code('%import "params/${cls}_type.hh"') 454 code('%include "params/${cls}.hh"') |
432 | 455 |
433 return code 434 | |
435# The SimObject class is the root of the special hierarchy. Most of 436# the code in this class deals with the configuration hierarchy itself 437# (parent/child node relationships). 438class SimObject(object): 439 # Specify metaclass. Any class inheriting from SimObject will 440 # get this metaclass. 441 __metaclass__ = MetaSimObject 442 type = 'SimObject' 443 abstract = True 444 | 456# The SimObject class is the root of the special hierarchy. Most of 457# the code in this class deals with the configuration hierarchy itself 458# (parent/child node relationships). 459class SimObject(object): 460 # Specify metaclass. Any class inheriting from SimObject will 461 # get this metaclass. 462 __metaclass__ = MetaSimObject 463 type = 'SimObject' 464 abstract = True 465 |
445 swig_objdecls = [ '%include "python/swig/sim_object.i"' ] | 466 @classmethod 467 def swig_objdecls(cls, code): 468 code('%include "python/swig/sim_object.i"') |
446 447 # Initialize new instance. For objects with SimObject-valued 448 # children, we need to recursively clone the classes represented 449 # by those param values as well in a consistent "deep copy"-style 450 # fashion. That is, we want to make sure that each instance is 451 # cloned only once, and that if there are multiple references to 452 # the same original object, we end up with the corresponding 453 # cloned references all pointing to the same cloned instance. --- 482 unchanged lines hidden --- | 469 470 # Initialize new instance. For objects with SimObject-valued 471 # children, we need to recursively clone the classes represented 472 # by those param values as well in a consistent "deep copy"-style 473 # fashion. That is, we want to make sure that each instance is 474 # cloned only once, and that if there are multiple references to 475 # the same original object, we end up with the corresponding 476 # cloned references all pointing to the same cloned instance. --- 482 unchanged lines hidden --- |