params.py
来自「M5,一个功能强大的多处理器系统模拟器.很多针对处理器架构,性能的研究都使用它作」· Python 代码 · 共 1,172 行 · 第 1/3 页
PY
1,172 行
# Copyright (c) 2004, 2005, 2006# The Regents of The University of Michigan# All Rights Reserved## This code is part of the M5 simulator.## 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.## Authors: Steven K. Reinhardt# Nathan L. Binkert####################################################################### Parameter description classes## The _params dictionary in each class maps parameter names to either# a Param or a VectorParam object. These objects contain the# parameter description string, the parameter type, and the default# value (if any). The convert() method on these objects is used to# force whatever value is assigned to the parameter to the appropriate# type.## Note that the default values are loaded into the class's attribute# space when the parameter dictionary is initialized (in# MetaSimObject._new_param()); after that point they aren't used.######################################################################import copyimport datetimeimport reimport sysimport timeimport convertimport proxyimport ticksfrom util import *import SimObjectdef isSimObject(*args, **kwargs): return SimObject.isSimObject(*args, **kwargs)def isSimObjectSequence(*args, **kwargs): return SimObject.isSimObjectSequence(*args, **kwargs)def isSimObjectClass(*args, **kwargs): return SimObject.isSimObjectClass(*args, **kwargs)allParams = {}class MetaParamValue(type): def __new__(mcls, name, bases, dct): cls = super(MetaParamValue, mcls).__new__(mcls, name, bases, dct) assert name not in allParams allParams[name] = cls return cls# Dummy base class to identify types that are legitimate for SimObject# parameters.class ParamValue(object): __metaclass__ = MetaParamValue cxx_predecls = [] swig_predecls = [] # default for printing to .ini file is regular string conversion. # will be overridden in some cases def ini_str(self): return str(self) # allows us to blithely call unproxy() on things without checking # if they're really proxies or not def unproxy(self, base): return self# Regular parameter description.class ParamDesc(object): def __init__(self, ptype_str, ptype, *args, **kwargs): self.ptype_str = ptype_str # remember ptype only if it is provided if ptype != None: self.ptype = ptype if args: if len(args) == 1: self.desc = args[0] elif len(args) == 2: self.default = args[0] self.desc = args[1] else: raise TypeError, 'too many arguments' if kwargs.has_key('desc'): assert(not hasattr(self, 'desc')) self.desc = kwargs['desc'] del kwargs['desc'] if kwargs.has_key('default'): assert(not hasattr(self, 'default')) self.default = kwargs['default'] del kwargs['default'] if kwargs: raise TypeError, 'extra unknown kwargs %s' % kwargs if not hasattr(self, 'desc'): raise TypeError, 'desc attribute missing' def __getattr__(self, attr): if attr == 'ptype': ptype = SimObject.allClasses[self.ptype_str] assert issubclass(ptype, SimObject.SimObject) self.ptype = ptype return ptype raise AttributeError, "'%s' object has no attribute '%s'" % \ (type(self).__name__, attr) def convert(self, value): if isinstance(value, proxy.BaseProxy): value.set_param_desc(self) return value if not hasattr(self, 'ptype') and isNullPointer(value): # deferred evaluation of SimObject; continue to defer if # we're just assigning a null pointer return value if isinstance(value, self.ptype): return value if isNullPointer(value) and isSimObjectClass(self.ptype): return value return self.ptype(value) def cxx_predecls(self): return self.ptype.cxx_predecls def swig_predecls(self): return self.ptype.swig_predecls def cxx_decl(self): return '%s %s;' % (self.ptype.cxx_type, self.name)# Vector-valued parameter description. Just like ParamDesc, except# that the value is a vector (list) of the specified type instead of a# single value.class VectorParamValue(list): __metaclass__ = MetaParamValue def ini_str(self): return ' '.join([v.ini_str() for v in self]) def getValue(self): return [ v.getValue() for v in self ] def unproxy(self, base): return [v.unproxy(base) for v in self]class SimObjVector(VectorParamValue): def print_ini(self, ini_file): for v in self: v.print_ini(ini_file)class VectorParamDesc(ParamDesc): # Convert assigned value to appropriate type. If the RHS is not a # list or tuple, it generates a single-element list. def convert(self, value): if isinstance(value, (list, tuple)): # list: coerce each element into new list tmp_list = [ ParamDesc.convert(self, v) for v in value ] else: # singleton: coerce to a single-element list tmp_list = [ ParamDesc.convert(self, value) ] if isSimObjectSequence(tmp_list): return SimObjVector(tmp_list) else: return VectorParamValue(tmp_list) def swig_predecls(self): return ['%%include "%s_vptype.i"' % self.ptype_str] def swig_decl(self): cxx_type = re.sub('std::', '', self.ptype.cxx_type) vdecl = 'namespace std { %%template(vector_%s) vector< %s >; }' % \ (self.ptype_str, cxx_type) return ['%include "std_vector.i"'] + self.ptype.swig_predecls + [vdecl] def cxx_predecls(self): return ['#include <vector>'] + self.ptype.cxx_predecls def cxx_decl(self): return 'std::vector< %s > %s;' % (self.ptype.cxx_type, self.name)class ParamFactory(object): def __init__(self, param_desc_class, ptype_str = None): self.param_desc_class = param_desc_class self.ptype_str = ptype_str def __getattr__(self, attr): if self.ptype_str: attr = self.ptype_str + '.' + attr return ParamFactory(self.param_desc_class, attr) # E.g., Param.Int(5, "number of widgets") def __call__(self, *args, **kwargs): ptype = None try: ptype = allParams[self.ptype_str] except KeyError: # if name isn't defined yet, assume it's a SimObject, and # try to resolve it later pass return self.param_desc_class(self.ptype_str, ptype, *args, **kwargs)Param = ParamFactory(ParamDesc)VectorParam = ParamFactory(VectorParamDesc)####################################################################### Parameter Types## Though native Python types could be used to specify parameter types# (the 'ptype' field of the Param and VectorParam classes), it's more# flexible to define our own set of types. This gives us more control# over how Python expressions are converted to values (via the# __init__() constructor) and how these values are printed out (via# the __str__() conversion method).####################################################################### String-valued parameter. Just mixin the ParamValue class with the# built-in str class.class String(ParamValue,str): cxx_type = 'std::string' cxx_predecls = ['#include <string>'] swig_predecls = ['%include "std_string.i"\n' + '%apply const std::string& {std::string *};'] swig_predecls = ['%include "std_string.i"' ] def getValue(self): return self# superclass for "numeric" parameter values, to emulate math# operations in a type-safe way. e.g., a Latency times an int returns# a new Latency object.class NumericParamValue(ParamValue): def __str__(self): return str(self.value) def __float__(self): return float(self.value) def __long__(self): return long(self.value) def __int__(self): return int(self.value) # hook for bounds checking def _check(self): return def __mul__(self, other): newobj = self.__class__(self) newobj.value *= other newobj._check() return newobj __rmul__ = __mul__ def __div__(self, other): newobj = self.__class__(self) newobj.value /= other newobj._check() return newobj def __sub__(self, other): newobj = self.__class__(self) newobj.value -= other newobj._check() return newobj# Metaclass for bounds-checked integer parameters. See CheckedInt.class CheckedIntType(MetaParamValue): def __init__(cls, name, bases, dict): super(CheckedIntType, cls).__init__(name, bases, dict) # CheckedInt is an abstract base class, so we actually don't # want to do any processing on it... the rest of this code is # just for classes that derive from CheckedInt. if name == 'CheckedInt': return if not cls.cxx_predecls: # most derived types require this, so we just do it here once cls.cxx_predecls = ['#include "sim/host.hh"'] if not cls.swig_predecls: # most derived types require this, so we just do it here once cls.swig_predecls = ['%import "stdint.i"\n' + '%import "sim/host.hh"'] if not (hasattr(cls, 'min') and hasattr(cls, 'max')): if not (hasattr(cls, 'size') and hasattr(cls, 'unsigned')): panic("CheckedInt subclass %s must define either\n" \ " 'min' and 'max' or 'size' and 'unsigned'\n" \ % name); if cls.unsigned: cls.min = 0 cls.max = 2 ** cls.size - 1 else: cls.min = -(2 ** (cls.size - 1)) cls.max = (2 ** (cls.size - 1)) - 1# Abstract superclass for bounds-checked integer parameters. This# class is subclassed to generate parameter classes with specific# bounds. Initialization of the min and max bounds is done in the# metaclass CheckedIntType.__init__.class CheckedInt(NumericParamValue): __metaclass__ = CheckedIntType def _check(self): if not self.min <= self.value <= self.max: raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ (self.min, self.value, self.max) def __init__(self, value): if isinstance(value, str): self.value = convert.toInteger(value) elif isinstance(value, (int, long, float, NumericParamValue)): self.value = long(value) else: raise TypeError, "Can't convert object of type %s to CheckedInt" \ % type(value).__name__ self._check() def getValue(self): return long(self.value)class Int(CheckedInt): cxx_type = 'int'; size = 32; unsigned = Falseclass Unsigned(CheckedInt): cxx_type = 'unsigned'; size = 32; unsigned = Trueclass Int8(CheckedInt): cxx_type = 'int8_t'; size = 8; unsigned = Falseclass UInt8(CheckedInt): cxx_type = 'uint8_t'; size = 8; unsigned = Trueclass Int16(CheckedInt): cxx_type = 'int16_t'; size = 16; unsigned = Falseclass UInt16(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = Trueclass Int32(CheckedInt): cxx_type = 'int32_t'; size = 32; unsigned = Falseclass UInt32(CheckedInt): cxx_type = 'uint32_t'; size = 32; unsigned = Trueclass Int64(CheckedInt): cxx_type = 'int64_t'; size = 64; unsigned = Falseclass UInt64(CheckedInt): cxx_type = 'uint64_t'; size = 64; unsigned = Trueclass Counter(CheckedInt): cxx_type = 'Counter'; size = 64; unsigned = Trueclass Tick(CheckedInt): cxx_type = 'Tick'; size = 64; unsigned = Trueclass TcpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = Trueclass UdpPort(CheckedInt): cxx_type = 'uint16_t'; size = 16; unsigned = Trueclass Percent(CheckedInt): cxx_type = 'int'; min = 0; max = 100class Float(ParamValue, float): cxx_type = 'double' def getValue(self): return float(self.value)class MemorySize(CheckedInt): cxx_type = 'uint64_t' size = 64 unsigned = True def __init__(self, value): if isinstance(value, MemorySize): self.value = value.value
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?