simobject.py
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· Python 代码 · 共 911 行 · 第 1/3 页
PY
911 行
if attr.startswith('_'): type.__setattr__(cls, attr, value) return if cls.keywords.has_key(attr): cls._set_keyword(attr, value, cls.keywords[attr]) return if cls._ports.has_key(attr): cls._cls_get_port_ref(attr).connect(value) return if isSimObjectOrSequence(value) and cls._instantiated: raise RuntimeError, \ "cannot set SimObject parameter '%s' after\n" \ " class %s has been instantiated or subclassed" \ % (attr, cls.__name__) # check for param param = cls._params.get(attr) if param: cls._set_param(attr, value, param) return if isSimObjectOrSequence(value): # If RHS is a SimObject, it's an implicit child assignment. # Classes don't have children, so we just put this object # in _values; later, each instance will do a 'setattr(self, # attr, _values[attr])' in SimObject.__init__ which will # add this object as a child. cls._values[attr] = value return # no valid assignment... raise exception raise AttributeError, \ "Class %s has no parameter \'%s\'" % (cls.__name__, attr) def __getattr__(cls, attr): if cls._values.has_key(attr): return cls._values[attr] raise AttributeError, \ "object '%s' has no attribute '%s'" % (cls.__name__, attr) def __str__(cls): return cls.__name__ def get_base(cls): if str(cls) == 'SimObject': return None return cls.__bases__[0].type def cxx_decl(cls): 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.local.values() try: ptypes = [p.ptype for p in params] except: print cls, p, p.ptype_str print params raise # get a list of lists of predeclaration lines predecls = [] predecls.extend(cls.cxx_predecls) for p in params: predecls.extend(p.cxx_predecls()) # remove redundant lines predecls2 = [] for pd in predecls: if pd not in predecls2: predecls2.append(pd) predecls2.sort() code += "\n".join(predecls2) code += "\n\n"; base = cls.get_base() if base: code += '#include "params/%s.hh"\n\n' % base 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{\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]) code += "};\n" # close #ifndef __PARAMS__* guard code += "\n#endif\n" return code def cxx_type_decl(cls): base = cls.get_base() 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): base = cls.get_base() code = '%%module %s\n' % cls code += '%{\n' code += '#include "params/%s.hh"\n' % cls code += '%}\n\n' # 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.local.values() ptypes = [p.ptype for p in params] # get a list of lists of predeclaration lines predecls = [] predecls.extend([ p.swig_predecls() for p in params ]) # flatten predecls = reduce(lambda x,y:x+y, predecls, []) # remove redundant lines predecls2 = [] for pd in predecls: if pd not in predecls2: predecls2.append(pd) predecls2.sort() code += "\n".join(predecls2) code += "\n\n"; if base: code += '%%import "params/%s.i"\n\n' % base 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# The SimObject class is the root of the special hierarchy. Most of# the code in this class deals with the configuration hierarchy itself# (parent/child node relationships).class SimObject(object): # Specify metaclass. Any class inheriting from SimObject will # get this metaclass. __metaclass__ = MetaSimObject type = 'SimObject' abstract = True name = Param.String("Object name") swig_objdecls = [ '%include "python/swig/sim_object.i"' ] # Initialize new instance. For objects with SimObject-valued # children, we need to recursively clone the classes represented # by those param values as well in a consistent "deep copy"-style # fashion. That is, we want to make sure that each instance is # cloned only once, and that if there are multiple references to # the same original object, we end up with the corresponding # cloned references all pointing to the same cloned instance. def __init__(self, **kwargs): ancestor = kwargs.get('_ancestor') memo_dict = kwargs.get('_memo') if memo_dict is None: # prepare to memoize any recursively instantiated objects memo_dict = {} elif ancestor: # memoize me now to avoid problems with recursive calls memo_dict[ancestor] = self if not ancestor: ancestor = self.__class__ ancestor._instantiated = True # initialize required attributes 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 # individual value settings can be overridden. self._values = multidict(ancestor._values) # clone SimObject-valued parameters for key,val in ancestor._values.iteritems(): if isSimObject(val): setattr(self, key, val(_memo=memo_dict)) elif isSimObjectSequence(val) and len(val): setattr(self, key, [ v(_memo=memo_dict) for v in val ]) # clone port references. no need to use a multidict here # since we will be creating new references for all ports. self._port_refs = {} for key,val in ancestor._port_refs.iteritems(): self._port_refs[key] = val.clone(self, memo_dict) # apply attribute assignments from keyword args, if any for key,val in kwargs.iteritems(): setattr(self, key, val) # "Clone" the current instance by creating another instance of # this instance's class, but that inherits its parameter values # and port mappings from the current instance. If we're in a # "deep copy" recursive clone, check the _memo dict to see if # we've already cloned this instance. def __call__(self, **kwargs): memo_dict = kwargs.get('_memo') if memo_dict is None: # no memo_dict: must be top-level clone operation. # this is only allowed at the root of a hierarchy if self._parent: raise RuntimeError, "attempt to clone object %s " \ "not at the root of a tree (parent = %s)" \ % (self, self._parent) # create a new dict and use that. memo_dict = {} kwargs['_memo'] = memo_dict elif memo_dict.has_key(self): # clone already done & memoized return memo_dict[self] return self.__class__(_ancestor = self, **kwargs) def _get_port_ref(self, attr): # Return reference that can be assigned to another port # via __setattr__. There is only ever one reference # object per port, but we create them lazily here. ref = self._port_refs.get(attr) if not ref: ref = self._ports[attr].makeRef(self) self._port_refs[attr] = ref return ref def __getattr__(self, attr): if self._ports.has_key(attr): return self._get_port_ref(attr) if self._values.has_key(attr): return self._values[attr] raise AttributeError, "object '%s' has no attribute '%s'" \ % (self.__class__.__name__, attr) # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(self, attr, value): # normal processing for private attributes if attr.startswith('_'): object.__setattr__(self, attr, value) return if self._ports.has_key(attr): # set up port connection self._get_port_ref(attr).connect(value) return if isSimObjectOrSequence(value) and self._instantiated: raise RuntimeError, \ "cannot set SimObject parameter '%s' after\n" \ " instance been cloned %s" % (attr, `self`) # must be SimObject param param = self._params.get(attr) if param: try: value = param.convert(value) except Exception, e: msg = "%s\nError setting param %s.%s to %s\n" % \ (e, self.__class__.__name__, attr, value) e.args = (msg, ) raise self._set_child(attr, value) return if isSimObjectOrSequence(value): self._set_child(attr, value) return
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?