Allow math on CheckedInt-derived ParamValue classes w/o
authorSteve Reinhardt <stever@eecs.umich.edu>
Tue, 1 Nov 2005 19:11:54 +0000 (14:11 -0500)
committerSteve Reinhardt <stever@eecs.umich.edu>
Tue, 1 Nov 2005 19:11:54 +0000 (14:11 -0500)
losing type information.

python/m5/config.py:
    Allow math on CheckedInt-derived ParamValue classes w/o
    losing type information.
    - Make CheckedInt derive from NumericParamValue, and *not*
    multiply inherit from long
    - Move CheckedInt bounds check to _check() hook so we can
    call it when value is updated (not just in constructor)
python/m5/convert.py:
    - make toInteger() return a long, making toLong() unnecessary
    - toMemorySize should return long rather than float

--HG--
extra : convert_revision : c1cf5e15b9ff35d9b573dd545e076fe68afef989

python/m5/config.py
python/m5/convert.py

index 3c49421d3de1d3e080b2233cd93a58fe90c7bf09..86acb75f8dc96103ca6c1d1bec1924ab49fd683a 100644 (file)
@@ -825,6 +825,40 @@ VectorParam = ParamFactory(VectorParamDesc)
 #
 #####################################################################
 
+# 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)
+
+    # 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
+
 class Range(ParamValue):
     type = int # default; can be overridden in subclasses
     def __init__(self, *args, **kwargs):
@@ -891,18 +925,20 @@ 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(long,ParamValue):
+class CheckedInt(NumericParamValue):
     __metaclass__ = CheckedIntType
 
-    def __new__(cls, value):
-        if isinstance(value, str):
-            value = toInteger(value)
-
-        self = long.__new__(cls, value)
-
-        if not cls.min <= self <= cls.max:
+    def _check(self):
+        if not self.min <= self.value <= self.max:
             raise TypeError, 'Integer param out of bounds %d < %d < %d' % \
-                  (cls.min, self, cls.max)
+                  (self.min, self.value, self.max)
+
+    def __init__(self, value):
+        if isinstance(value, str):
+            self.value = toInteger(value)
+        elif isinstance(value, (int, long)):
+            self.value = long(value)
+        self._check()
         return self
 
 class Int(CheckedInt):      size = 32; unsigned = False
@@ -930,19 +966,28 @@ class Float(ParamValue, float):
 class MemorySize(CheckedInt):
     size = 64
     unsigned = True
-    def __new__(cls, value):
-        return super(MemorySize, cls).__new__(cls, toMemorySize(value))
+    def __init__(self, value):
+        if isinstance(value, MemorySize):
+            self.value = value.value
+        else:
+            self.value = toMemorySize(value)
+        self._check()
+        return self
 
 
 class Addr(CheckedInt):
     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 __init__(self, value):
+        if isinstance(value, Addr):
+            self.value = value.value
+        else:
+            try:
+                self.value = toMemorySize(value)
+            except TypeError:
+                self.value = long(value)
+        self._check()
+        return self
 
 class AddrRange(Range):
     type = Addr
@@ -1123,29 +1168,6 @@ def tick_check(float_ticks):
         #raise ValueError
     return int_ticks
 
-# 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 __mul__(self, other):
-        newobj = self.__class__(self)
-        newobj.value *= other
-        return newobj
-
-    __rmul__ = __mul__
-
-    def __div__(self, other):
-        newobj = self.__class__(self)
-        newobj.value /= other
-        return newobj
-
-
 def getLatency(value):
     if isinstance(value, Latency) or isinstance(value, Clock):
         return value.value
index 9d9f4efa7fa397c0db9cc5aaba0ee2b177e9dd0e..73181e9850d225a680c3c271495fcd006388f462 100644 (file)
@@ -89,17 +89,9 @@ def toFloat(value):
     else:
         return float(value)
 
-def toLong(value):
-    value = toFloat(value)
-    result = int(value)
-    if value != result:
-        raise ValueError, "cannot convert '%s' to long" % value
-
-    return result
-
 def toInteger(value):
     value = toFloat(value)
-    result = int(value)
+    result = long(value)
     if value != result:
         raise ValueError, "cannot convert '%s' to integer" % value
 
@@ -220,16 +212,16 @@ def toMemorySize(value):
         raise TypeError, "wrong type '%s' should be str" % type(value)
 
     if value.endswith('PB'):
-        return float(value[:-2]) * pebi
+        return long(value[:-2]) * pebi
     elif value.endswith('TB'):
-        return float(value[:-2]) * tebi
+        return long(value[:-2]) * tebi
     elif value.endswith('GB'):
-        return float(value[:-2]) * gibi
+        return long(value[:-2]) * gibi
     elif value.endswith('MB'):
-        return float(value[:-2]) * mebi
+        return long(value[:-2]) * mebi
     elif value.endswith('kB'):
-        return float(value[:-2]) * kibi
+        return long(value[:-2]) * kibi
     elif value.endswith('B'):
-        return float(value[:-1])
+        return long(value[:-1])
 
     raise ValueError, "cannot convert '%s' to memory size" % value