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 + -
显示快捷键?