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, 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 |
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 |
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, |
149 'cxx_predecls' : MethodType, 150 'swig_objdecls' : MethodType, 151 'swig_predecls' : MethodType, |
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(): |
170 if public_value(key, val): |
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 |
231 if 'cxx_predecls' not in cls.__dict__: 232 m = MethodType(default_cxx_predecls, cls, MetaSimObject) 233 setattr(cls, 'cxx_predecls', m) |
234 |
235 if 'swig_predecls' not in cls.__dict__: 236 setattr(cls, 'swig_predecls', getattr(cls, 'cxx_predecls')) |
237 |
238 if 'swig_objdecls' not in cls.__dict__: 239 m = MethodType(default_swig_objdecls, cls, MetaSimObject) 240 setattr(cls, 'swig_objdecls', m) |
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 |
315 if public_value(attr, value): |
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 |
361 def cxx_decl(cls, code): 362 code('''\ 363#ifndef __PARAMS__${cls}__ 364#define __PARAMS__${cls}__ |
365 |
366''') 367 |
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 |
380 # get all predeclarations 381 cls.cxx_predecls(code) 382 for param in params: 383 param.cxx_predecls(code) 384 code() |
385 386 if cls._base: |
387 code('#include "params/${{cls._base.type}}.hh"') 388 code() |
389 390 for ptype in ptypes: 391 if issubclass(ptype, Enum): |
392 code('#include "enums/${{ptype.__name__}}.hh"') 393 code() |
394 |
395 cls.cxx_struct(code, cls._base, params) |
396 397 # close #ifndef __PARAMS__* guard |
398 code() 399 code('#endif // __PARAMS__${cls}__') |
400 return code 401 |
402 def cxx_struct(cls, code, base, params): |
403 if cls == SimObject: |
404 code('#include "sim/sim_object_params.hh"') 405 return |
406 407 # now generate the actual param struct |
408 code("struct ${cls}Params") |
409 if base: |
410 code(" : public ${{base.type}}Params") 411 code("{") |
412 if not hasattr(cls, 'abstract') or not cls.abstract: 413 if 'type' in cls.__dict__: |
414 code(" ${{cls.cxx_type}} create();") |
415 |
416 code.indent() 417 for param in params: 418 param.cxx_decl(code) 419 code.dedent() 420 code('};') |
421 |
422 def swig_decl(cls, code): 423 code('''\ 424%module $cls |
425 |
426%{ 427#include "params/$cls.hh" 428%} |
429 |
430''') 431 |
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 |
439 # get all predeclarations 440 for param in params: 441 param.swig_predecls(code) 442 code() |
443 444 if cls._base: |
445 code('%import "params/${{cls._base.type}}.i"') 446 code() |
447 448 for ptype in ptypes: 449 if issubclass(ptype, Enum): |
450 code('%import "enums/${{ptype.__name__}}.hh"') 451 code() |
452 |
453 code('%import "params/${cls}_type.hh"') 454 code('%include "params/${cls}.hh"') |
455 |
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 |
466 @classmethod 467 def swig_objdecls(cls, code): 468 code('%include "python/swig/sim_object.i"') |
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 --- |