add utilities for testing ELF files
[openpower-isa.git] / src / openpower / decoder / selectable_int.py
index 37592fd0d2804725a81b3b3fb0c3fa06654955be..1eb0d2a7bd22c53be962853731607a0ec680a80e 100644 (file)
@@ -7,13 +7,14 @@ from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
                       neg, inv, lshift, rshift, lt, eq)
 from openpower.util import log
 
+EFFECTIVELY_UNLIMITED = 1024
 
 def check_extsign(a, b):
     if isinstance(b, FieldSelectableInt):
         b = b.get_range()
     if isinstance(b, int):
         return SelectableInt(b, a.bits)
-    if b.bits != 256:
+    if b.bits != EFFECTIVELY_UNLIMITED:
         return b
     return SelectableInt(b.value, a.bits)
 
@@ -58,18 +59,10 @@ class FieldSelectableInt:
         self.br = br  # map of indices
 
     def eq(self, b):
-        if isinstance(b, int):
-            # convert integer to same SelectableInt of same bitlength as range
-            blen = len(self.br)
-            b = SelectableInt(b, blen)
-            for i in range(b.bits):
-                self[i] = b[i]
-        elif isinstance(b, SelectableInt):
-            for i in range(b.bits):
-                self[i] = b[i]
-        else:
-            self.si = copy(b.si)
-            self.br = copy(b.br)
+        if not isinstance(b, SelectableInt):
+            b = SelectableInt(b, len(self.br))
+        for i in range(b.bits):
+            self[i] = b[i]
 
     def _op(self, op, b):
         vi = self.get_range()
@@ -85,7 +78,7 @@ class FieldSelectableInt:
         return len(self.br)
 
     def __getitem__(self, key):
-        log("getitem", key, self.br)
+        #log("getitem", key, self.br)
         if isinstance(key, SelectableInt):
             key = key.value
 
@@ -236,9 +229,21 @@ class SelectableInt:
     FieldSelectableInt can then operate on partial bits, and because there
     is a bit width associated with SelectableInt, slices operate correctly
     including negative start/end points.
+
+    value: int
+        the bits contained by `self`
+    bits: int
+        the number of bits contained by `self`.
+    ok: bool
+        a flag to detect if outputs have been written by pseudo-code
+
+        instruction inputs have `ok` set to `False`, all changed or new
+        SelectableInt instances set `ok` to `True`.
     """
 
-    def __init__(self, value, bits=None):
+    def __init__(self, value, bits=None, *, ok=True):
+        if isinstance(value, FieldSelectableInt):
+            value = value.get_range()
         if isinstance(value, SelectableInt):
             if bits is not None:
                 # check if the bitlength is different. TODO, allow override?
@@ -246,11 +251,7 @@ class SelectableInt:
                     raise ValueError(value)
             bits = value.bits
             value = value.value
-        elif isinstance(value, FieldSelectableInt):
-            if bits is not None:
-                raise ValueError(value)
-            bits = len(value.br)
-            value = value.si.value
+            # intentionally don't copy ok
         else:
             if not isinstance(value, int):
                 raise ValueError(value)
@@ -260,10 +261,12 @@ class SelectableInt:
         self.value = value & mask
         self.bits = bits
         self.overflow = (value & ~mask) != 0
+        self.ok = ok
 
     def eq(self, b):
         self.value = b.value
         self.bits = b.bits
+        self.ok = True
 
     def to_signed_int(self):
         log ("to signed?", self.value & (1<<(self.bits-1)), self.value)
@@ -323,7 +326,7 @@ class SelectableInt:
     def __rsub__(self, b):
         log("rsub", b, self.value)
         if isinstance(b, int):
-            b = SelectableInt(b, 256) # max extent
+            b = SelectableInt(b, EFFECTIVELY_UNLIMITED) # max extent
         #b = check_extsign(self, b)
         #assert b.bits == self.bits
         return SelectableInt(b.value - self.value, b.bits)
@@ -405,6 +408,7 @@ class SelectableInt:
             return selectconcat(*bits)
 
     def __setitem__(self, key, value):
+        self.ok = True
         if isinstance(key, SelectableInt):
             key = key.value
         if isinstance(key, int):
@@ -497,8 +501,10 @@ class SelectableInt:
         return self.value != 0
 
     def __repr__(self):
-        value = f"value={hex(self.value)}, bits={self.bits}"
-        return f"{self.__class__.__name__}({value})"
+        value = "value=%#x, bits=%d" % (self.value, self.bits)
+        if not self.ok:
+            value += ", ok=False"
+        return "%s(%s)" % (self.__class__.__name__, value)
 
     def __len__(self):
         return self.bits
@@ -572,10 +578,14 @@ def selectconcat(*args, repeat=1):
         for i in range(repeat):
             tmp += args
         args = tmp
-    res = copy(args[0])
+    if isinstance(args[0], FieldSelectableInt):
+        res = args[0].get_range()
+    else:
+        assert isinstance(args[0], SelectableInt), "can only concat SIs, sorry"
+        res = SelectableInt(args[0])
     for i in args[1:]:
         if isinstance(i, FieldSelectableInt):
-            i = i.si
+            i = i.get_range()
         assert isinstance(i, SelectableInt), "can only concat SIs, sorry"
         res.bits += i.bits
         res.value = (res.value << i.bits) | i.value