First step in fixing up parameter handling. Clean up the
authorNathan Binkert <binkertn@umich.edu>
Wed, 23 Mar 2005 18:25:48 +0000 (13:25 -0500)
committerNathan Binkert <binkertn@umich.edu>
Wed, 23 Mar 2005 18:25:48 +0000 (13:25 -0500)
way ranges work, more fully support metric prefixes for all
integer types, and convert memory sized parameters to the
MemorySize type.

python/m5/config.py:
    - no more _Param and _ParamProxy stuff.  Use the names
    ParamBase and ParamFactory to hopefully make it clearer
    what we intend.
    - Get rid of RangeSize and the old Range class and more fully flesh
    out the Range class to deal with types of parameters and different
    kinds of ranges.
    - Call toInteger on the CheckedInt types so we can use metric prefixes
    in strings for all integers.
    - Get rid of the K, M, and G constants.  Use the proper type or call
    one of the functions in the convert package.
python/m5/convert.py:
    Simple way to deal with both floating point and integer strings.
python/m5/objects/BaseCache.mpy:
python/m5/objects/Ethernet.mpy:
    This is a MemorySize typed parameter

--HG--
extra : convert_revision : 92b4ea662d723abdd6c0a49065b79c25400fac9b

python/m5/config.py
python/m5/convert.py
python/m5/objects/BaseCache.mpy
python/m5/objects/Ethernet.mpy

index f696adc7929c99c2c40cc3596de6af1c53bfcbd2..3fc90f6bc0ee7bd68a6141892096ba69529ffbf5 100644 (file)
@@ -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,8 @@ 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))
+                raise e.__class__,  "%s\nError setting param %s.%s to %s\n" % \
+                      (e, cls.__name__, attr, value)
             cls._values[attr] = value
         elif isConfigNode(value) or isSimObjSequence(value):
             cls._values[attr] = value
@@ -837,7 +837,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 +909,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 +929,17 @@ 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 +974,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 +995,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 +1102,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 +1120,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 +1136,47 @@ 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))
-
-class Range(ParamType):
-    __metaclass__ = MetaRange
+        return '%d' % value
+    _string = classmethod(_string)
 
-def RangeSize(start, size):
-    return Pair(start, start + size - 1)
+class Addr(MemorySize):
+    pass
 
-class AddrRange(Range): type = Addr
+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
+    #def __new__(cls, value):
+    #    return super(MemorySize, cls).__new__(cls, toBool(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
-
-        raise TypeError, 'Bool parameter (%s) of invalid type %s' % (v, t)
-    _convert = staticmethod(_convert)
+    def _convert(cls, value):
+        return toBool(value)
+    _convert = classmethod(_convert)
 
-    def _string(value):
+    def _string(cls, value):
         if value:
             return "true"
         else:
             return "false"
-    _string = staticmethod(_string)
+    _string = classmethod(_string)
 
 # String-valued parameter.
 class String(ParamType):
@@ -1291,13 +1346,9 @@ class Enum(ParamType):
 #
 
 # 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)
 
 #####################################################################
 
@@ -1337,6 +1388,6 @@ __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',
+           'Range', 'AddrRange', 'MaxAddr', 'MaxTick', 'AllMemory', 'NULL',
+           'NextEthernetAddr', 'instantiate']
index 2ebe9388944f233db8e852dfe9cfde2f2515c2e6..2f69645b947f9783a93dcc89ba9acb0b0f359537 100644 (file)
@@ -60,7 +60,7 @@ def toInteger(value):
     elif value.endswith('f'):
         result = int(value[:-1]) * femto
     else:
-        result = int(value)
+        result = int(float(value))
 
     return result
 
index 98a422e30acc4406931ae1b4c12268827b3fce2e..b9986917f70362b43f979b65f71165c6914e9687 100644 (file)
@@ -23,7 +23,7 @@ simobj BaseCache(BaseMem):
         "always service demand misses first")
     protocol = Param.CoherenceProtocol(NULL, "coherence protocol to use")
     repl = Param.Repl(NULL, "replacement policy")
-    size = Param.Int("capacity in bytes")
+    size = Param.MemorySize("capacity in bytes")
     split = Param.Bool(False, "whether or not this cache is split")
     split_size = Param.Int(0,
         "How many ways of the cache belong to CPU/LRU partition")
index cd251f36da09903c0b59758446df4224804e1dcc..3acd8d04df556daa2f65aeb321400b59d6b0b92e 100644 (file)
@@ -68,8 +68,8 @@ simobj NSGigE(PciDevice):
     rx_delay = Param.Tick(1000, "Receive Delay")
     tx_delay = Param.Tick(1000, "Transmit Delay")
 
-    rx_fifo_size = Param.Int(131072, "max size in bytes of rxFifo")
-    tx_fifo_size = Param.Int(131072, "max size in bytes of txFifo")
+    rx_fifo_size = Param.MemorySize('128kB', "max size in bytes of rxFifo")
+    tx_fifo_size = Param.MemorySize('128kB', "max size in bytes of txFifo")
 
     intr_delay = Param.Tick(0, "Interrupt Delay in microseconds")
     payload_bus = Param.Bus(NULL, "The IO Bus to attach to for payload")