radix: reading first page table entry
[soc.git] / src / soc / decoder / selectable_int.py
index 3036b6f6412afd87c8aabc9fe6a58ef1652e57b6..152764ca08758f3922e991da1b400cee6e47c853 100644 (file)
@@ -18,14 +18,15 @@ def check_extsign(a, b):
 class FieldSelectableInt:
     """FieldSelectableInt: allows bit-range selection onto another target
     """
+
     def __init__(self, si, br):
-        self.si = si # target selectable int
+        self.si = si  # target selectable int
         if isinstance(br, list) or isinstance(br, tuple):
             _br = BitRange()
             for i, v in enumerate(br):
                 _br[i] = v
             br = _br
-        self.br = br # map of indices.
+        self.br = br  # map of indices.
 
     def eq(self, b):
         if isinstance(b, SelectableInt):
@@ -46,11 +47,11 @@ class FieldSelectableInt:
         return self.merge(vi)
 
     def __getitem__(self, key):
-        print ("getitem", key, self.br)
+        print("getitem", key, self.br)
         if isinstance(key, SelectableInt):
             key = key.value
         if isinstance(key, int):
-            key = self.br[key] # don't do POWER 1.3.4 bit-inversion
+            key = self.br[key]  # don't do POWER 1.3.4 bit-inversion
             return self.si[key]
         if isinstance(key, slice):
             key = self.br[key]
@@ -59,7 +60,7 @@ class FieldSelectableInt:
     def __setitem__(self, key, value):
         if isinstance(key, SelectableInt):
             key = key.value
-        key = self.br[key] # don't do POWER 1.3.4 bit-inversion
+        key = self.br[key]  # don't do POWER 1.3.4 bit-inversion
         if isinstance(key, int):
             return self.si.__setitem__(key, value)
         else:
@@ -70,22 +71,31 @@ class FieldSelectableInt:
 
     def __negate__(self):
         return self._op1(negate)
+
     def __invert__(self):
         return self._op1(inv)
+
     def __add__(self, b):
         return self._op(add, b)
+
     def __sub__(self, b):
         return self._op(sub, b)
+
     def __mul__(self, b):
         return self._op(mul, b)
+
     def __div__(self, b):
         return self._op(truediv, b)
+
     def __mod__(self, b):
         return self._op(mod, b)
+
     def __and__(self, b):
         return self._op(and_, b)
+
     def __or__(self, b):
         return self._op(or_, b)
+
     def __xor__(self, b):
         return self._op(xor, b)
 
@@ -104,6 +114,15 @@ class FieldSelectableInt:
     def __repr__(self):
         return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
 
+    def asint(self, msb0=False):
+        res = 0
+        brlen = len(self.br)
+        for i, key in self.br.items():
+            bit = self.si[key].value
+            #print("asint", i, key, bit)
+            res |= bit << ((brlen-i-1) if msb0 else i)
+        return res
+
 
 class FieldSelectableIntTestCase(unittest.TestCase):
     def test_arith(self):
@@ -115,7 +134,7 @@ class FieldSelectableIntTestCase(unittest.TestCase):
         br[2] = 3
         fs = FieldSelectableInt(a, br)
         c = fs + b
-        print (c)
+        print(c)
         #self.assertEqual(c.value, a.value + b.value)
 
     def test_select(self):
@@ -143,7 +162,6 @@ class FieldSelectableIntTestCase(unittest.TestCase):
         fs[0:2] = 0b10
         self.assertEqual(fs.get_range(), 0b1011)
 
-
 class SelectableInt:
     """SelectableInt - a class that behaves exactly like python int
 
@@ -155,17 +173,29 @@ class SelectableInt:
     is a bit width associated with SelectableInt, slices operate correctly
     including negative start/end points.
     """
+
     def __init__(self, value, bits):
         if isinstance(value, SelectableInt):
             value = value.value
         mask = (1 << bits) - 1
         self.value = value & mask
         self.bits = bits
+        self.overflow = (value & ~mask) != 0
 
     def eq(self, b):
         self.value = b.value
         self.bits = b.bits
 
+    def to_signed_int(self):
+        print ("to signed?", self.value & (1<<(self.bits-1)), self.value)
+        if self.value & (1<<(self.bits-1)) != 0: # negative
+            res = self.value - (1<<self.bits)
+            print ("    val -ve:", self.bits, res)
+        else:
+            res = self.value
+            print ("    val +ve:", res)
+        return res
+
     def _op(self, op, b):
         if isinstance(b, int):
             b = SelectableInt(b, self.bits)
@@ -175,29 +205,41 @@ class SelectableInt:
 
     def __add__(self, b):
         return self._op(add, b)
+
     def __sub__(self, b):
         return self._op(sub, b)
+
     def __mul__(self, b):
-        # different case: mul result needs to fit the total bitsize 
+        # different case: mul result needs to fit the total bitsize
         if isinstance(b, int):
             b = SelectableInt(b, self.bits)
-        print ("SelectableInt mul", hex(self.value), hex(b.value),
-                                    self.bits, b.bits)
+        print("SelectableInt mul", hex(self.value), hex(b.value),
+              self.bits, b.bits)
         return SelectableInt(self.value * b.value, self.bits + b.bits)
+
     def __floordiv__(self, b):
         return self._op(floordiv, b)
+
     def __truediv__(self, b):
         return self._op(truediv, b)
+
     def __mod__(self, b):
         return self._op(mod, b)
+
     def __and__(self, b):
         return self._op(and_, b)
+
     def __or__(self, b):
         return self._op(or_, b)
+
     def __xor__(self, b):
         return self._op(xor, b)
+
     def __abs__(self):
-        return SelectableInt(0, self.bits) - self
+        print("abs", self.value & (1 << (self.bits-1)))
+        if self.value & (1 << (self.bits-1)) != 0:
+            return -self
+        return self
 
     def __rsub__(self, b):
         if isinstance(b, int):
@@ -222,7 +264,9 @@ class SelectableInt:
         return SelectableInt(~self.value, self.bits)
 
     def __neg__(self):
-        return SelectableInt(~self.value + 1, self.bits)
+        res = SelectableInt((~self.value) + 1, self.bits)
+        print ("neg", hex(self.value), hex(res.value))
+        return res
 
     def __lshift__(self, b):
         b = check_extsign(self, b)
@@ -243,6 +287,7 @@ class SelectableInt:
             key = self.bits - (key + 1)
 
             value = (self.value >> key) & 1
+            print("getitem", key, self.bits, hex(self.value), value)
             return SelectableInt(value, 1)
         elif isinstance(key, slice):
             assert key.step is None or key.step == 1
@@ -254,14 +299,16 @@ class SelectableInt:
             start = self.bits - key.stop
 
             bits = stop - start
-            #print ("__getitem__ slice num bits", bits)
+            #print ("__getitem__ slice num bits", start, stop, bits)
             mask = (1 << bits) - 1
             value = (self.value >> start) & mask
+            print("getitem", stop, start, self.bits, hex(self.value), value)
             return SelectableInt(value, bits)
 
     def __setitem__(self, key, value):
         if isinstance(key, SelectableInt):
             key = key.value
+        print("setitem", key, self.bits, hex(self.value))
         if isinstance(key, int):
             assert key < self.bits
             assert key >= 0
@@ -297,9 +344,9 @@ class SelectableInt:
         if isinstance(other, SelectableInt):
             other = check_extsign(self, other)
             assert other.bits == self.bits
-            other = other.value
+            other = other.to_signed_int()
         if isinstance(other, int):
-            return onebit(self.value >= other.value)
+            return onebit(self.to_signed_int() >= other)
         assert False
 
     def __le__(self, other):
@@ -308,9 +355,9 @@ class SelectableInt:
         if isinstance(other, SelectableInt):
             other = check_extsign(self, other)
             assert other.bits == self.bits
-            other = other.value
+            other = other.to_signed_int()
         if isinstance(other, int):
-            return onebit(self.value <= other)
+            return onebit(self.to_signed_int() <= other)
         assert False
 
     def __gt__(self, other):
@@ -319,30 +366,35 @@ class SelectableInt:
         if isinstance(other, SelectableInt):
             other = check_extsign(self, other)
             assert other.bits == self.bits
-            other = other.value
+            other = other.to_signed_int()
         if isinstance(other, int):
-            return onebit(self.value > other)
+            return onebit(self.to_signed_int() > other)
         assert False
 
     def __lt__(self, other):
+        print ("SelectableInt lt", self, other)
         if isinstance(other, FieldSelectableInt):
             other = other.get_range()
         if isinstance(other, SelectableInt):
             other = check_extsign(self, other)
             assert other.bits == self.bits
-            other = other.value
+            other = other.to_signed_int()
         if isinstance(other, int):
-            return onebit(self.value < other)
+            a = self.to_signed_int()
+            res = onebit(a  < other)
+            print ("    a < b", a, other, res)
+            return res
         assert False
 
     def __eq__(self, other):
-        print ("__eq__", self, other)
+        print("__eq__", self, other)
         if isinstance(other, FieldSelectableInt):
             other = other.get_range()
         if isinstance(other, SelectableInt):
             other = check_extsign(self, other)
             assert other.bits == self.bits
             other = other.value
+        print ("    eq", other, self.value, other == self.value)
         if isinstance(other, int):
             return onebit(other == self.value)
         assert False
@@ -356,7 +408,7 @@ class SelectableInt:
 
     def __repr__(self):
         return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
-                                                           self.bits)
+                                                             self.bits)
 
     def __len__(self):
         return self.bits
@@ -368,6 +420,7 @@ class SelectableInt:
 def onebit(bit):
     return SelectableInt(1 if bit else 0, 1)
 
+
 def selectltu(lhs, rhs):
     """ less-than (unsigned)
     """
@@ -375,6 +428,7 @@ def selectltu(lhs, rhs):
         rhs = rhs.value
     return onebit(lhs.value < rhs)
 
+
 def selectgtu(lhs, rhs):
     """ greater-than (unsigned)
     """
@@ -392,7 +446,7 @@ def selectassign(lhs, idx, rhs):
         else:
             lower, upper, step = idx
         toidx = range(lower, upper, step)
-        fromidx = range(0, upper-lower, step) # XXX eurgh...
+        fromidx = range(0, upper-lower, step)  # XXX eurgh...
     else:
         toidx = [idx]
         fromidx = [0]
@@ -403,7 +457,7 @@ def selectassign(lhs, idx, rhs):
 def selectconcat(*args, repeat=1):
     if repeat != 1 and len(args) == 1 and isinstance(args[0], int):
         args = [SelectableInt(args[0], 1)]
-    if repeat != 1: # multiplies the incoming arguments
+    if repeat != 1:  # multiplies the incoming arguments
         tmp = []
         for i in range(repeat):
             tmp += args
@@ -415,7 +469,7 @@ def selectconcat(*args, repeat=1):
         assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
         res.bits += i.bits
         res.value = (res.value << i.bits) | i.value
-    print ("concat", repeat, res)
+    print("concat", repeat, res)
     return res
 
 
@@ -501,5 +555,6 @@ class SelectableIntTestCase(unittest.TestCase):
         self.assertTrue(a != b)
         self.assertFalse(a == b)
 
+
 if __name__ == "__main__":
     unittest.main()