diff options
Diffstat (limited to 'python/m5/config.py')
-rw-r--r-- | python/m5/config.py | 339 |
1 files changed, 259 insertions, 80 deletions
diff --git a/python/m5/config.py b/python/m5/config.py index f696adc79..a791bbebf 100644 --- a/python/m5/config.py +++ b/python/m5/config.py @@ -27,7 +27,7 @@ from __future__ import generators import os, re, sys, types, inspect -from m5 import panic +from m5 import panic, env from convert import * from multidict import multidict @@ -65,7 +65,7 @@ class Singleton(type): # object, either using keyword assignment in the constructor or in # separate assignment statements. For example: # -# cache = BaseCache('my_cache', root, size=64*K) +# cache = BaseCache('my_cache', root, size='64KB') # cache.hit_latency = 3 # cache.assoc = 8 # @@ -373,7 +373,7 @@ classes. You're trying to derive from: # now process remaining _init_dict items for key,val in cls._init_dict.items(): # param descriptions - if isinstance(val, _Param): + if isinstance(val, ParamBase): cls._new_param(key, val) # init-time-only keywords @@ -433,8 +433,10 @@ classes. You're trying to derive from: try: param.valid(value) except Exception, e: - panic("Exception: %s\nError setting param %s.%s to %s\n" % \ - (e, cls.__name__, attr, value)) + msg = "%s\nError setting param %s.%s to %s\n" % \ + (e, cls.__name__, attr, value) + e.args = (msg, ) + raise cls._values[attr] = value elif isConfigNode(value) or isSimObjSequence(value): cls._values[attr] = value @@ -510,8 +512,10 @@ classes. You're trying to derive from: instance.params.append(p) instance.param_names[pname] = p except Exception, e: - raise e.__class__, 'Exception while evaluating %s.%s\n%s' % \ + msg = 'Exception while evaluating %s.%s\n%s' % \ (instance.path, pname, e) + e.args = (msg, ) + raise return instance @@ -693,8 +697,10 @@ class Node(object): else: param.value = self.unproxy(pval, ptype) except Exception, e: - raise e.__class__, 'Error while fixing up %s:%s\n%s' % \ + msg = 'Error while fixing up %s:%s\n%s' % \ (self.path, param.name, e) + e.args = (msg, ) + raise for child in self.children: assert(child != self) @@ -727,8 +733,9 @@ class Node(object): value = param.convert(param.value) string = param.string(value) except Exception, e: - raise e.__class__, 'exception in %s:%s\n%s' % \ - (self.path, param.name, e) + msg = 'exception in %s:%s\n%s' % (self.path, param.name, e) + e.args = (msg, ) + raise print '%s = %s' % (param.name, string) @@ -740,8 +747,6 @@ class Node(object): # print type and parameter values to .ini file def outputDot(self, dot): - - label = "{%s|" % self.path if isSimObject(self.realtype): label += '%s|' % self.type @@ -762,9 +767,10 @@ class Node(object): value = param.convert(param.value) string = param.string(value) except Exception, e: - raise e.__class__, 'exception in %s:%s\n%s' % \ - (self.name, param.name, e) + msg = 'exception in %s:%s\n%s' % (self.name, param.name, e) + e.args = (msg, ) raise + if isConfigNode(param.ptype) and string != "Null": simobjs.append(string) else: @@ -837,7 +843,7 @@ class Value(object): return len(self._getattr()) # Regular parameter. -class _Param(object): +class ParamBase(object): def __init__(self, ptype, *args, **kwargs): if isinstance(ptype, types.StringType): self.ptype_string = ptype @@ -909,13 +915,13 @@ class _Param(object): def cpp_decl(self, name): return '%s %s;' % (self.ptype._cpp_param_decl, name) -class _ParamProxy(object): +class ParamFactory(object): def __init__(self, type): self.ptype = type # E.g., Param.Int(5, "number of widgets") def __call__(self, *args, **kwargs): - return _Param(self.ptype, *args, **kwargs) + return ParamBase(self.ptype, *args, **kwargs) # Strange magic to theoretically allow dotted names as Param classes, # e.g., Param.Foo.Bar(...) to have a param of type Foo.Bar @@ -929,17 +935,16 @@ class _ParamProxy(object): if attr != 'ptype': raise AttributeError, \ 'Attribute %s not available in %s' % (attr, self.__class__) - super(_ParamProxy, self).__setattr__(attr, value) - + super(ParamFactory, self).__setattr__(attr, value) -Param = _ParamProxy(None) +Param = ParamFactory(None) # Vector-valued parameter description. Just like Param, except that # the value is a vector (list) of the specified type instead of a # single value. -class _VectorParam(_Param): +class VectorParamBase(ParamBase): def __init__(self, type, *args, **kwargs): - _Param.__init__(self, type, *args, **kwargs) + ParamBase.__init__(self, type, *args, **kwargs) def valid(self, value): if value == None: @@ -974,12 +979,12 @@ class _VectorParam(_Param): def cpp_decl(self, name): return 'std::vector<%s> %s;' % (self.ptype._cpp_param_decl, name) -class _VectorParamProxy(_ParamProxy): +class VectorParamFactory(ParamFactory): # E.g., VectorParam.Int(5, "number of widgets") def __call__(self, *args, **kwargs): - return _VectorParam(self.ptype, *args, **kwargs) + return VectorParamBase(self.ptype, *args, **kwargs) -VectorParam = _VectorParamProxy(None) +VectorParam = VectorParamFactory(None) ##################################################################### # @@ -995,6 +1000,80 @@ VectorParam = _VectorParamProxy(None) # ##################################################################### +class MetaRange(type): + def __init__(cls, name, bases, dict): + super(MetaRange, cls).__init__(name, bases, dict) + if name == 'Range': + return + cls._cpp_param_decl = 'Range<%s>' % cls.type._cpp_param_decl + + def _convert(cls, value): + if not isinstance(value, Range): + raise TypeError, 'value %s is not a Pair' % value + value = cls(value) + value.first = cls.type._convert(value.first) + value.second = cls.type._convert(value.second) + return value + + def _string(cls, value): + first = int(value.first) + second = int(value.second) + if value.extend: + second += first + if not value.inclusive: + second -= 1 + return '%s:%s' % (cls.type._string(first), cls.type._string(second)) + +class Range(ParamType): + __metaclass__ = MetaRange + def __init__(self, *args, **kwargs): + if len(args) == 0: + self.first = kwargs.pop('start') + + if 'end' in kwargs: + self.second = kwargs.pop('end') + self.inclusive = True + self.extend = False + elif 'size' in kwargs: + self.second = kwargs.pop('size') + self.inclusive = False + self.extend = True + else: + raise TypeError, "Either end or size must be specified" + + elif len(args) == 1: + if kwargs: + self.first = args[0] + if 'end' in kwargs: + self.second = kwargs.pop('end') + self.inclusive = True + self.extend = False + elif 'size' in kwargs: + self.second = kwargs.pop('size') + self.inclusive = False + self.extend = True + else: + raise TypeError, "Either end or size must be specified" + elif isinstance(args[0], Range): + self.first = args[0].first + self.second = args[0].second + self.inclusive = args[0].inclusive + self.extend = args[0].extend + else: + self.first = 0 + self.second = args[0] + self.inclusive = False + self.extend = True + + elif len(args) == 2: + self.first, self.second = args + self.inclusive = True + self.extend = False + else: + raise TypeError, "Too many arguments specified" + + if kwargs: + raise TypeError, "too many keywords: %s" % kwargs.keys() # Metaclass for bounds-checked integer parameters. See CheckedInt. class CheckedIntType(type): @@ -1028,8 +1107,10 @@ class CheckedIntType(type): if not isinstance(value, (int, long, float, str)): raise TypeError, 'Integer param of invalid type %s' % type(value) - if isinstance(value, (str, float)): - value = long(float(value)) + if isinstance(value, float): + value = long(value) + elif isinstance(value, str): + value = toInteger(value) if not cls.min <= value <= cls.max: raise TypeError, 'Integer param out of bounds %d < %d < %d' % \ @@ -1044,7 +1125,7 @@ class CheckedIntType(type): # 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(ParamType): +class CheckedInt(long,ParamType): __metaclass__ = CheckedIntType class Int(CheckedInt): cppname = 'int'; size = 32; unsigned = False @@ -1060,68 +1141,66 @@ class Int64(CheckedInt): cppname = 'int64_t'; size = 64; unsigned = False class UInt64(CheckedInt): cppname = 'uint64_t'; size = 64; unsigned = True class Counter(CheckedInt): cppname = 'Counter'; size = 64; unsigned = True -class Addr(CheckedInt): cppname = 'Addr'; size = 64; unsigned = True class Tick(CheckedInt): cppname = 'Tick'; size = 64; unsigned = True class Percent(CheckedInt): cppname = 'int'; min = 0; max = 100 -class Pair(object): - def __init__(self, first, second): - self.first = first - self.second = second - -class MetaRange(type): - def __init__(cls, name, bases, dict): - super(MetaRange, cls).__init__(name, bases, dict) - if name == 'Range': - return - cls._cpp_param_decl = 'Range<%s>' % cls.type._cpp_param_decl +class MemorySize(CheckedInt): + cppname = 'uint64_t' + size = 64 + unsigned = True + def __new__(cls, value): + return super(MemorySize, cls).__new__(cls, toMemorySize(value)) def _convert(cls, value): - if not isinstance(value, Pair): - raise TypeError, 'value %s is not a Pair' % value - return Pair(cls.type._convert(value.first), - cls.type._convert(value.second)) + return cls(value) + _convert = classmethod(_convert) def _string(cls, value): - return '%s:%s' % (cls.type._string(value.first), - cls.type._string(value.second)) + return '%d' % value + _string = classmethod(_string) -class Range(ParamType): - __metaclass__ = MetaRange +class Addr(CheckedInt): + cppname = 'Addr' + size = 64 + unsigned = True + def __new__(cls, value): + try: + value = long(toMemorySize(value)) + except TypeError: + value = long(value) + return super(Addr, cls).__new__(cls, value) -def RangeSize(start, size): - return Pair(start, start + size - 1) + def _convert(cls, value): + return cls(value) + _convert = classmethod(_convert) -class AddrRange(Range): type = Addr + def _string(cls, value): + return '%d' % value + _string = classmethod(_string) + +class AddrRange(Range): + type = Addr # Boolean parameter type. class Bool(ParamType): _cpp_param_decl = 'bool' - def _convert(value): - t = type(value) - if t == bool: - return value - - if t == int or t == long: - return bool(value) - - if t == str: - v = value.lower() - if v == "true" or v == "t" or v == "yes" or v == "y": - return True - elif v == "false" or v == "f" or v == "no" or v == "n": - return False + def __init__(self, value): + try: + self.value = toBool(value) + except TypeError: + self.value = bool(value) - raise TypeError, 'Bool parameter (%s) of invalid type %s' % (v, t) - _convert = staticmethod(_convert) + def _convert(cls, value): + return cls(value) + _convert = classmethod(_convert) - def _string(value): - if value: + def _string(cls, value): + if value.value: return "true" else: return "false" - _string = staticmethod(_string) + _string = classmethod(_string) # String-valued parameter. class String(ParamType): @@ -1143,7 +1222,6 @@ class String(ParamType): return value _string = classmethod(_string) - def IncEthernetAddr(addr, val = 1): bytes = map(lambda x: int(x, 16), addr.split(':')) bytes[5] += val @@ -1239,7 +1317,6 @@ Null = NULL = NullSimObject() # Metaclass for Enum types class MetaEnum(type): - def __init__(cls, name, bases, init_dict): if init_dict.has_key('map'): if not isinstance(cls.map, dict): @@ -1286,25 +1363,126 @@ class Enum(ParamType): def _string(self, value): return str(value) _string = classmethod(_string) + +root_frequency = None + # # "Constants"... handy aliases for various values. # +class RootFrequency(float,ParamType): + _cpp_param_decl = 'Tick' + + def __new__(cls, value): + return super(cls, RootFrequency).__new__(cls, toFrequency(value)) + + def _convert(cls, value): + return cls(value) + _convert = classmethod(_convert) + + def _string(cls, value): + return '%d' % int(value) + _string = classmethod(_string) + +class ClockPeriod(float,ParamType): + _cpp_param_decl = 'Tick' + def __new__(cls, value): + relative = False + try: + val = toClockPeriod(value) + except ValueError, e: + relative = True + if value.endswith('f'): + val = float(value[:-1]) + if val: + val = 1 / val + elif value.endswith('c'): + val = float(value[:-1]) + else: + raise e + + self = super(cls, ClockPeriod).__new__(cls, val) + self.relative = relative + return self + + def _convert(cls, value): + return cls(value) + _convert = classmethod(_convert) + + def _string(cls, value): + if not value.relative: + value *= root_frequency + + return '%d' % int(value) + _string = classmethod(_string) + +class Frequency(float,ParamType): + _cpp_param_decl = 'Tick' + + def __new__(cls, value): + relative = False + try: + val = toFrequency(value) + except ValueError, e: + if value.endswith('f'): + val = float(value[:-1]) + relative = True + else: + raise e + self = super(cls, Frequency).__new__(cls, val) + self.relative = relative + return self + + def _convert(cls, value): + return cls(value) + _convert = classmethod(_convert) + + def _string(cls, value): + if not value.relative: + value = root_frequency / value + + return '%d' % int(value) + _string = classmethod(_string) + +class Latency(float,ParamType): + _cpp_param_decl = 'Tick' + def __new__(cls, value): + relative = False + try: + val = toLatency(value) + except ValueError, e: + if value.endswith('c'): + val = float(value[:-1]) + relative = True + else: + raise e + self = super(cls, Latency).__new__(cls, val) + self.relative = relative + return self + + def _convert(cls, value): + return cls(value) + _convert = classmethod(_convert) + + def _string(cls, value): + if not value.relative: + value *= root_frequency + return '%d' % value + _string = classmethod(_string) + # Some memory range specifications use this as a default upper bound. -MAX_ADDR = Addr.max +MaxAddr = Addr.max MaxTick = Tick.max - -# For power-of-two sizing, e.g. 64*K gives an integer value 65536. -K = 1024 -M = K*K -G = K*M +AllMemory = AddrRange(0, MaxAddr) ##################################################################### # The final hook to generate .ini files. Called from configuration # script once config is built. def instantiate(root): + global root_frequency instance = root.instantiate('root') + root_frequency = RootFrequency._convert(root.frequency._getattr()) instance.fixup() instance.display() if not noDot: @@ -1337,6 +1515,7 @@ __all__ = ['ConfigNode', 'SimObject', 'ParamContext', 'Param', 'VectorParam', 'Int', 'Unsigned', 'Int8', 'UInt8', 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64', 'Counter', 'Addr', 'Tick', 'Percent', - 'Pair', 'RangeSize', 'AddrRange', 'MAX_ADDR', 'NULL', 'K', 'M', - 'NextEthernetAddr', - 'instantiate'] + 'MemorySize', 'RootFrequency', 'Frequency', 'Latency', + 'ClockPeriod', + 'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'NULL', + 'NextEthernetAddr', 'instantiate'] |