config.py
来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· Python 代码 · 共 1,298 行 · 第 1/4 页
PY
1,298 行
# Copyright (c) 2004, 2005# The Regents of The University of Michigan# All Rights Reserved## This code is part of the M5 simulator, developed by Nathan Binkert,# Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions# from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi,# and Andrew Schultz.## Permission is granted to use, copy, create derivative works and# redistribute this software and such derivative works for any# purpose, so long as the copyright notice above, this grant of# permission, and the disclaimer below appear in all copies made; and# so long as the name of The University of Michigan is not used in any# advertising or publicity pertaining to the use or distribution of# this software without specific, written prior authorization.## THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE# UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND# WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER# EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR# PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE# LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT,# INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM# ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN# IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH# DAMAGES.from __future__ import generatorsimport os, re, sys, types, inspectimport m5panic = m5.panicfrom convert import *from multidict import multidictnoDot = Falsetry: import pydotexcept: noDot = Trueclass Singleton(type): def __call__(cls, *args, **kwargs): if hasattr(cls, '_instance'): return cls._instance cls._instance = super(Singleton, cls).__call__(*args, **kwargs) return cls._instance####################################################################### M5 Python Configuration Utility## The basic idea is to write simple Python programs that build Python# objects corresponding to M5 SimObjects for the desired simulation# configuration. For now, the Python emits a .ini file that can be# parsed by M5. In the future, some tighter integration between M5# and the Python interpreter may allow bypassing the .ini file.## Each SimObject class in M5 is represented by a Python class with the# same name. The Python inheritance tree mirrors the M5 C++ tree# (e.g., SimpleCPU derives from BaseCPU in both cases, and all# SimObjects inherit from a single SimObject base class). To specify# an instance of an M5 SimObject in a configuration, the user simply# instantiates the corresponding Python object. The parameters for# that SimObject are given by assigning to attributes of the Python# object, either using keyword assignment in the constructor or in# separate assignment statements. For example:## cache = BaseCache(size='64KB')# cache.hit_latency = 3# cache.assoc = 8## The magic lies in the mapping of the Python attributes for SimObject# classes to the actual SimObject parameter specifications. This# allows parameter validity checking in the Python code. Continuing# the example above, the statements "cache.blurfl=3" or# "cache.assoc='hello'" would both result in runtime errors in Python,# since the BaseCache object has no 'blurfl' parameter and the 'assoc'# parameter requires an integer, respectively. This magic is done# primarily by overriding the special __setattr__ method that controls# assignment to object attributes.## Once a set of Python objects have been instantiated in a hierarchy,# calling 'instantiate(obj)' (where obj is the root of the hierarchy)# will generate a .ini file. See simple-4cpu.py for an example# (corresponding to m5-test/simple-4cpu.ini).############################################################################################################################################# ConfigNode/SimObject classes## The Python class hierarchy rooted by ConfigNode (which is the base# class of SimObject, which in turn is the base class of all other M5# SimObject classes) has special attribute behavior. In general, an# object in this hierarchy has three categories of attribute-like# things:## 1. Regular Python methods and variables. These must start with an# underscore to be treated normally.## 2. SimObject parameters. These values are stored as normal Python# attributes, but all assignments to these attributes are checked# against the pre-defined set of parameters stored in the class's# _params dictionary. Assignments to attributes that do not# correspond to predefined parameters, or that are not of the correct# type, incur runtime errors.## 3. Hierarchy children. The child nodes of a ConfigNode are stored# in the node's _children dictionary, but can be accessed using the# Python attribute dot-notation (just as they are printed out by the# simulator). Children cannot be created using attribute assigment;# they must be added by specifying the parent node in the child's# constructor or using the '+=' operator.# The SimObject parameters are the most complex, for a few reasons.# First, both parameter descriptions and parameter values are# inherited. Thus parameter description lookup must go up the# inheritance chain like normal attribute lookup, but this behavior# must be explicitly coded since the lookup occurs in each class's# _params attribute. Second, because parameter values can be set# on SimObject classes (to implement default values), the parameter# checking behavior must be enforced on class attribute assignments as# well as instance attribute assignments. Finally, because we allow# class specialization via inheritance (e.g., see the L1Cache class in# the simple-4cpu.py example), we must do parameter checking even on# class instantiation. To provide all these features, we use a# metaclass to define most of the SimObject parameter behavior for# this class hierarchy.######################################################################def isSimObject(value): return isinstance(value, SimObject) def isSimObjSequence(value): if not isinstance(value, (list, tuple)): return False for val in value: if not isNullPointer(val) and not isSimObject(val): return False return Truedef isNullPointer(value): return isinstance(value, NullSimObject)# The metaclass for ConfigNode (and thus for everything that derives# from ConfigNode, including SimObject). This class controls how new# classes that derive from ConfigNode are instantiated, and provides# inherited class behavior (just like a class controls how instances# of that class are instantiated, and provides inherited instance# behavior).class MetaSimObject(type): # Attributes that can be set only at initialization time init_keywords = { 'abstract' : types.BooleanType, 'type' : types.StringType } # Attributes that can be set any time keywords = { 'check' : types.FunctionType, 'children' : types.ListType } # __new__ is called before __init__, and is where the statements # in the body of the class definition get loaded into the class's # __dict__. We intercept this to filter out parameter assignments # and only allow "private" attributes to be passed to the base # __new__ (starting with underscore). def __new__(mcls, name, bases, dict): # Copy "private" attributes (including special methods such as __new__) # to the official dict. Everything else goes in _init_dict to be # filtered in __init__. cls_dict = {} for key,val in dict.items(): if key.startswith('_'): cls_dict[key] = val del dict[key] cls_dict['_init_dict'] = dict return super(MetaSimObject, mcls).__new__(mcls, name, bases, cls_dict) # initialization def __init__(cls, name, bases, dict): super(MetaSimObject, cls).__init__(name, bases, dict) # initialize required attributes cls._params = multidict() cls._values = multidict() cls._anon_subclass_counter = 0 # We don't support multiple inheritance. If you want to, you # must fix multidict to deal with it properly. if len(bases) > 1: raise TypeError, "SimObjects do not support multiple inheritance" base = bases[0] if isinstance(base, MetaSimObject): cls._params.parent = base._params cls._values.parent = base._values # If your parent has a value in it that's a config node, clone # it. Do this now so if we update any of the values' # attributes we are updating the clone and not the original. for key,val in base._values.iteritems(): # don't clone if (1) we're about to overwrite it with # a local setting or (2) we've already cloned a copy # from an earlier (more derived) base if cls._init_dict.has_key(key) or cls._values.has_key(key): continue if isSimObject(val): cls._values[key] = val() elif isSimObjSequence(val) and len(val): cls._values[key] = [ v() for v in val ] # now process remaining _init_dict items for key,val in cls._init_dict.items(): if isinstance(val, (types.FunctionType, types.TypeType)): type.__setattr__(cls, key, val) # param descriptions elif isinstance(val, ParamDesc): cls._new_param(key, val) # init-time-only keywords elif cls.init_keywords.has_key(key): cls._set_keyword(key, val, cls.init_keywords[key]) # default: use normal path (ends up in __setattr__) else: setattr(cls, key, val) def _set_keyword(cls, keyword, val, kwtype): if not isinstance(val, kwtype): raise TypeError, 'keyword %s has bad type %s (expecting %s)' % \ (keyword, type(val), kwtype) if isinstance(val, types.FunctionType): val = classmethod(val) type.__setattr__(cls, keyword, val) def _new_param(cls, name, value): cls._params[name] = value if hasattr(value, 'default'): setattr(cls, name, value.default) # Set attribute (called on foo.attr = value when foo is an # instance of class cls). def __setattr__(cls, attr, value): # normal processing for private attributes if attr.startswith('_'): type.__setattr__(cls, attr, value) return if cls.keywords.has_key(attr): cls._set_keyword(attr, value, cls.keywords[attr]) return # must be SimObject param param = cls._params.get(attr, None) if param: # It's ok: set attribute by delegating to 'object' class. try: cls._values[attr] = param.convert(value) except Exception, e: msg = "%s\nError setting param %s.%s to %s\n" % \ (e, cls.__name__, attr, value) e.args = (msg, ) raise # I would love to get rid of this elif isSimObject(value) or isSimObjSequence(value): cls._values[attr] = value else: 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)# The ConfigNode 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 def __init__(self, _value_parent = None, **kwargs): self._children = {} if _value_parent and type(_value_parent) != type(self): # this was called as a type conversion rather than a clone raise TypeError, "Cannot convert %s to %s" % \ (_value_parent.__class__.__name__, self.__class__.__name__) if not _value_parent: _value_parent = self.__class__ # clone values self._values = multidict(_value_parent._values) for key,val in _value_parent._values.iteritems(): if isSimObject(val): setattr(self, key, val()) elif isSimObjSequence(val) and len(val): setattr(self, key, [ v() for v in val ]) # apply attribute assignments from keyword args, if any for key,val in kwargs.iteritems(): setattr(self, key, val) def __call__(self, **kwargs): return self.__class__(_value_parent = self, **kwargs) def __getattr__(self, 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).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?