Major changes to how SimObjects are created and initialized. Almost all
creation and initialization now happens in python. Parameter objects are generated and initialized by python. The .ini file is now solely for debugging purposes and is not used in construction of the objects in any way. --HG-- extra : convert_revision : 7e722873e417cb3d696f2e34c35ff488b7bff4ed
This commit is contained in:
@@ -29,6 +29,8 @@
|
||||
|
||||
import sys, types
|
||||
|
||||
import proxy
|
||||
import m5
|
||||
from util import *
|
||||
from multidict import multidict
|
||||
|
||||
@@ -61,7 +63,7 @@ def isSimObjectOrSequence(value):
|
||||
from params import *
|
||||
# There are a few things we need that aren't in params.__all__ since
|
||||
# normal users don't need them
|
||||
from params import ParamDesc, isNullPointer, SimObjVector
|
||||
from params import ParamDesc, VectorParamDesc, isNullPointer, SimObjVector
|
||||
|
||||
noDot = False
|
||||
try:
|
||||
@@ -109,6 +111,9 @@ except:
|
||||
#
|
||||
#####################################################################
|
||||
|
||||
# list of all SimObject classes
|
||||
allClasses = {}
|
||||
|
||||
# dict to look up SimObjects based on path
|
||||
instanceDict = {}
|
||||
|
||||
@@ -119,12 +124,14 @@ instanceDict = {}
|
||||
class MetaSimObject(type):
|
||||
# Attributes that can be set only at initialization time
|
||||
init_keywords = { 'abstract' : types.BooleanType,
|
||||
'cxx_namespace' : types.StringType,
|
||||
'cxx_class' : types.StringType,
|
||||
'cxx_type' : types.StringType,
|
||||
'cxx_predecls' : types.ListType,
|
||||
'swig_predecls' : types.ListType,
|
||||
'type' : types.StringType }
|
||||
# Attributes that can be set any time
|
||||
keywords = { 'check' : types.FunctionType,
|
||||
'cxx_type' : types.StringType,
|
||||
'cxx_predecls' : types.ListType,
|
||||
'swig_predecls' : types.ListType }
|
||||
keywords = { 'check' : types.FunctionType }
|
||||
|
||||
# __new__ is called before __init__, and is where the statements
|
||||
# in the body of the class definition get loaded into the class's
|
||||
@@ -132,6 +139,8 @@ class MetaSimObject(type):
|
||||
# and only allow "private" attributes to be passed to the base
|
||||
# __new__ (starting with underscore).
|
||||
def __new__(mcls, name, bases, dict):
|
||||
assert name not in allClasses
|
||||
|
||||
# Copy "private" attributes, functions, and classes to the
|
||||
# official dict. Everything else goes in _init_dict to be
|
||||
# filtered in __init__.
|
||||
@@ -144,8 +153,13 @@ class MetaSimObject(type):
|
||||
else:
|
||||
# must be a param/port setting
|
||||
value_dict[key] = val
|
||||
if 'abstract' not in value_dict:
|
||||
value_dict['abstract'] = False
|
||||
cls_dict['_value_dict'] = value_dict
|
||||
return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict)
|
||||
cls = super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict)
|
||||
if 'type' in value_dict:
|
||||
allClasses[name] = cls
|
||||
return cls
|
||||
|
||||
# subclass initialization
|
||||
def __init__(cls, name, bases, dict):
|
||||
@@ -183,6 +197,34 @@ class MetaSimObject(type):
|
||||
# mark base as having been subclassed
|
||||
base._instantiated = True
|
||||
|
||||
# default keyword values
|
||||
if 'type' in cls._value_dict:
|
||||
_type = cls._value_dict['type']
|
||||
if 'cxx_class' not in cls._value_dict:
|
||||
cls._value_dict['cxx_class'] = _type
|
||||
|
||||
namespace = cls._value_dict.get('cxx_namespace', None)
|
||||
|
||||
_cxx_class = cls._value_dict['cxx_class']
|
||||
if 'cxx_type' not in cls._value_dict:
|
||||
t = _cxx_class + '*'
|
||||
if namespace:
|
||||
t = '%s::%s' % (namespace, t)
|
||||
cls._value_dict['cxx_type'] = t
|
||||
if 'cxx_predecls' not in cls._value_dict:
|
||||
# A forward class declaration is sufficient since we are
|
||||
# just declaring a pointer.
|
||||
decl = 'class %s;' % _cxx_class
|
||||
if namespace:
|
||||
decl = 'namespace %s { %s }' % (namespace, decl)
|
||||
cls._value_dict['cxx_predecls'] = [decl]
|
||||
|
||||
if 'swig_predecls' not in cls._value_dict:
|
||||
# A forward class declaration is sufficient since we are
|
||||
# just declaring a pointer.
|
||||
cls._value_dict['swig_predecls'] = \
|
||||
cls._value_dict['cxx_predecls']
|
||||
|
||||
# Now process the _value_dict items. They could be defining
|
||||
# new (or overriding existing) parameters or ports, setting
|
||||
# class keywords (e.g., 'abstract'), or setting parameter
|
||||
@@ -207,12 +249,6 @@ class MetaSimObject(type):
|
||||
else:
|
||||
setattr(cls, key, val)
|
||||
|
||||
cls.cxx_type = cls.type + '*'
|
||||
# A forward class declaration is sufficient since we are just
|
||||
# declaring a pointer.
|
||||
cls.cxx_predecls = ['class %s;' % cls.type]
|
||||
cls.swig_predecls = cls.cxx_predecls
|
||||
|
||||
def _set_keyword(cls, keyword, val, kwtype):
|
||||
if not isinstance(val, kwtype):
|
||||
raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \
|
||||
@@ -310,18 +346,19 @@ class MetaSimObject(type):
|
||||
return cls.__name__
|
||||
|
||||
def cxx_decl(cls):
|
||||
code = "#ifndef __PARAMS__%s\n#define __PARAMS__%s\n\n" % (cls, cls)
|
||||
|
||||
if str(cls) != 'SimObject':
|
||||
base = cls.__bases__[0].type
|
||||
else:
|
||||
base = None
|
||||
|
||||
code = "#ifndef __PARAMS__%s\n" % cls
|
||||
code += "#define __PARAMS__%s\n\n" % cls
|
||||
|
||||
# The 'dict' attribute restricts us to the params declared in
|
||||
# the object itself, not including inherited params (which
|
||||
# will also be inherited from the base class's param struct
|
||||
# here).
|
||||
params = cls._params.dict.values()
|
||||
params = cls._params.local.values()
|
||||
try:
|
||||
ptypes = [p.ptype for p in params]
|
||||
except:
|
||||
@@ -330,9 +367,10 @@ class MetaSimObject(type):
|
||||
raise
|
||||
|
||||
# get a list of lists of predeclaration lines
|
||||
predecls = [p.cxx_predecls() for p in params]
|
||||
# flatten
|
||||
predecls = reduce(lambda x,y:x+y, predecls, [])
|
||||
predecls = []
|
||||
predecls.extend(cls.cxx_predecls)
|
||||
for p in params:
|
||||
predecls.extend(p.cxx_predecls())
|
||||
# remove redundant lines
|
||||
predecls2 = []
|
||||
for pd in predecls:
|
||||
@@ -345,17 +383,21 @@ class MetaSimObject(type):
|
||||
if base:
|
||||
code += '#include "params/%s.hh"\n\n' % base
|
||||
|
||||
# Generate declarations for locally defined enumerations.
|
||||
enum_ptypes = [t for t in ptypes if issubclass(t, Enum)]
|
||||
if enum_ptypes:
|
||||
code += "\n".join([t.cxx_decl() for t in enum_ptypes])
|
||||
code += "\n\n"
|
||||
for ptype in ptypes:
|
||||
if issubclass(ptype, Enum):
|
||||
code += '#include "enums/%s.hh"\n' % ptype.__name__
|
||||
code += "\n\n"
|
||||
|
||||
# now generate the actual param struct
|
||||
code += "struct %sParams" % cls
|
||||
if base:
|
||||
code += " : public %sParams" % base
|
||||
code += " {\n"
|
||||
code += "\n{\n"
|
||||
if cls == SimObject:
|
||||
code += " virtual ~%sParams() {}\n" % cls
|
||||
if not hasattr(cls, 'abstract') or not cls.abstract:
|
||||
if 'type' in cls.__dict__:
|
||||
code += " %s create();\n" % cls.cxx_type
|
||||
decls = [p.cxx_decl() for p in params]
|
||||
decls.sort()
|
||||
code += "".join([" %s\n" % d for d in decls])
|
||||
@@ -365,12 +407,34 @@ class MetaSimObject(type):
|
||||
code += "\n#endif\n"
|
||||
return code
|
||||
|
||||
def swig_decl(cls):
|
||||
def cxx_type_decl(cls):
|
||||
if str(cls) != 'SimObject':
|
||||
base = cls.__bases__[0]
|
||||
else:
|
||||
base = None
|
||||
|
||||
code = '%%module %sParams\n' % cls
|
||||
code = ''
|
||||
|
||||
if base:
|
||||
code += '#include "%s_type.h"\n' % base
|
||||
|
||||
# now generate dummy code for inheritance
|
||||
code += "struct %s" % cls.cxx_class
|
||||
if base:
|
||||
code += " : public %s" % base.cxx_class
|
||||
code += "\n{};\n"
|
||||
|
||||
return code
|
||||
|
||||
def swig_decl(cls):
|
||||
code = '%%module %s\n' % cls
|
||||
|
||||
code += '%{\n'
|
||||
code += '#include "params/%s.hh"\n' % cls
|
||||
code += '%}\n\n'
|
||||
|
||||
if str(cls) != 'SimObject':
|
||||
base = cls.__bases__[0].type
|
||||
base = cls.__bases__[0]
|
||||
else:
|
||||
base = None
|
||||
|
||||
@@ -378,11 +442,12 @@ class MetaSimObject(type):
|
||||
# the object itself, not including inherited params (which
|
||||
# will also be inherited from the base class's param struct
|
||||
# here).
|
||||
params = cls._params.dict.values()
|
||||
params = cls._params.local.values()
|
||||
ptypes = [p.ptype for p in params]
|
||||
|
||||
# get a list of lists of predeclaration lines
|
||||
predecls = [p.swig_predecls() for p in params]
|
||||
predecls = []
|
||||
predecls.extend([ p.swig_predecls() for p in params ])
|
||||
# flatten
|
||||
predecls = reduce(lambda x,y:x+y, predecls, [])
|
||||
# remove redundant lines
|
||||
@@ -395,11 +460,14 @@ class MetaSimObject(type):
|
||||
code += "\n\n";
|
||||
|
||||
if base:
|
||||
code += '%%import "python/m5/swig/%sParams.i"\n\n' % base
|
||||
code += '%%import "params/%s.i"\n\n' % base
|
||||
|
||||
code += '%{\n'
|
||||
code += '#include "params/%s.hh"\n' % cls
|
||||
code += '%}\n\n'
|
||||
for ptype in ptypes:
|
||||
if issubclass(ptype, Enum):
|
||||
code += '%%import "enums/%s.hh"\n' % ptype.__name__
|
||||
code += "\n\n"
|
||||
|
||||
code += '%%import "params/%s_type.hh"\n\n' % cls
|
||||
code += '%%include "params/%s.hh"\n\n' % cls
|
||||
|
||||
return code
|
||||
@@ -412,6 +480,7 @@ class SimObject(object):
|
||||
# get this metaclass.
|
||||
__metaclass__ = MetaSimObject
|
||||
type = 'SimObject'
|
||||
abstract = True
|
||||
|
||||
name = Param.String("Object name")
|
||||
|
||||
@@ -440,6 +509,7 @@ class SimObject(object):
|
||||
self._parent = None
|
||||
self._children = {}
|
||||
self._ccObject = None # pointer to C++ object
|
||||
self._ccParams = None
|
||||
self._instantiated = False # really "cloned"
|
||||
|
||||
# Inherit parameter values from class using multidict so
|
||||
@@ -577,8 +647,11 @@ class SimObject(object):
|
||||
value._maybe_set_parent(self, attr)
|
||||
elif isSimObjectSequence(value):
|
||||
value = SimObjVector(value)
|
||||
[v._maybe_set_parent(self, "%s%d" % (attr, i))
|
||||
for i,v in enumerate(value)]
|
||||
if len(value) == 1:
|
||||
value[0]._maybe_set_parent(self, attr)
|
||||
else:
|
||||
for i,v in enumerate(value):
|
||||
v._maybe_set_parent(self, "%s%d" % (attr, i))
|
||||
|
||||
self._values[attr] = value
|
||||
|
||||
@@ -680,25 +753,66 @@ class SimObject(object):
|
||||
for child in child_names:
|
||||
self._children[child].print_ini()
|
||||
|
||||
# Call C++ to create C++ object corresponding to this object and
|
||||
# (recursively) all its children
|
||||
def createCCObject(self):
|
||||
self.getCCObject() # force creation
|
||||
for child in self._children.itervalues():
|
||||
child.createCCObject()
|
||||
def getCCParams(self):
|
||||
if self._ccParams:
|
||||
return self._ccParams
|
||||
|
||||
cc_params_struct = eval('m5.objects.params.%sParams' % self.type)
|
||||
cc_params = cc_params_struct()
|
||||
cc_params.object = self
|
||||
cc_params.name = str(self)
|
||||
|
||||
param_names = self._params.keys()
|
||||
param_names.sort()
|
||||
for param in param_names:
|
||||
value = self._values.get(param)
|
||||
if value is None:
|
||||
continue
|
||||
|
||||
value = value.getValue()
|
||||
if isinstance(self._params[param], VectorParamDesc):
|
||||
assert isinstance(value, list)
|
||||
vec = getattr(cc_params, param)
|
||||
assert not len(vec)
|
||||
for v in value:
|
||||
vec.append(v)
|
||||
else:
|
||||
setattr(cc_params, param, value)
|
||||
|
||||
port_names = self._ports.keys()
|
||||
port_names.sort()
|
||||
for port_name in port_names:
|
||||
port = self._port_refs.get(port_name, None)
|
||||
if port != None:
|
||||
setattr(cc_params, port_name, port)
|
||||
self._ccParams = cc_params
|
||||
return self._ccParams
|
||||
|
||||
# Get C++ object corresponding to this object, calling C++ if
|
||||
# necessary to construct it. Does *not* recursively create
|
||||
# children.
|
||||
def getCCObject(self):
|
||||
import internal
|
||||
params = self.getCCParams()
|
||||
if not self._ccObject:
|
||||
self._ccObject = -1 # flag to catch cycles in recursion
|
||||
self._ccObject = internal.sim_object.createSimObject(self.path())
|
||||
self._ccObject = params.create()
|
||||
elif self._ccObject == -1:
|
||||
raise RuntimeError, "%s: recursive call to getCCObject()" \
|
||||
% self.path()
|
||||
return self._ccObject
|
||||
|
||||
# Call C++ to create C++ object corresponding to this object and
|
||||
# (recursively) all its children
|
||||
def createCCObject(self):
|
||||
self.getCCParams()
|
||||
self.getCCObject() # force creation
|
||||
for child in self._children.itervalues():
|
||||
child.createCCObject()
|
||||
|
||||
def getValue(self):
|
||||
return self.getCCObject()
|
||||
|
||||
# Create C++ port connections corresponding to the connections in
|
||||
# _port_refs (& recursively for all children)
|
||||
def connectPorts(self):
|
||||
@@ -730,6 +844,7 @@ class SimObject(object):
|
||||
return system_ptr.getMemoryMode()
|
||||
|
||||
def changeTiming(self, mode):
|
||||
import internal
|
||||
if isinstance(self, m5.objects.System):
|
||||
# i don't know if there's a better way to do this - calling
|
||||
# setMemoryMode directly from self._ccObject results in calling
|
||||
@@ -740,6 +855,7 @@ class SimObject(object):
|
||||
child.changeTiming(mode)
|
||||
|
||||
def takeOverFrom(self, old_cpu):
|
||||
import internal
|
||||
cpu_ptr = internal.sim_object.convertToBaseCPUPtr(old_cpu._ccObject)
|
||||
self._ccObject.takeOverFrom(cpu_ptr)
|
||||
|
||||
@@ -794,9 +910,4 @@ def resolveSimObject(name):
|
||||
# __all__ defines the list of symbols that get exported when
|
||||
# 'from config import *' is invoked. Try to keep this reasonably
|
||||
# short to avoid polluting other namespaces.
|
||||
__all__ = ['SimObject']
|
||||
|
||||
# see comment on imports at end of __init__.py.
|
||||
import proxy
|
||||
import internal
|
||||
import m5
|
||||
__all__ = [ 'SimObject' ]
|
||||
|
||||
Reference in New Issue
Block a user