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 ---