temporarily revert opcode changes
[openpower-isa.git] / src / openpower / decoder / selectable_int.py
index 34ea01550174df96a7cd13896d0775e33575c7b8..1e7458ee9f8e0de4c68ebbe7bd0580b80c92f3c9 100644 (file)
@@ -1,6 +1,7 @@
 import unittest
 import struct
 from copy import copy
+import functools
 from openpower.decoder.power_fields import BitRange
 from operator import (add, sub, mul, floordiv, truediv, mod, or_, and_, xor,
                       neg, inv, lshift, rshift)
@@ -23,7 +24,7 @@ class FieldSelectableInt:
 
     def __init__(self, si, br):
         self.si = si  # target selectable int
-        if isinstance(br, list) or isinstance(br, tuple):
+        if isinstance(br, (list, tuple, range)):
             _br = BitRange()
             for i, v in enumerate(br):
                 _br[i] = v
@@ -120,7 +121,7 @@ class FieldSelectableInt:
         return fi
 
     def __repr__(self):
-        return "FieldSelectableInt(si=%s, br=%s)" % (self.si, self.br)
+        return f"{self.__class__.__name__}(si={self.si}, br={self.br})"
 
     def asint(self, msb0=False):
         res = 0
@@ -420,8 +421,8 @@ class SelectableInt:
         return self.value != 0
 
     def __repr__(self):
-        return "SelectableInt(value=0x{:x}, bits={})".format(self.value,
-                                                             self.bits)
+        value = f"value=0x{self.value:x}, bits={self.bits}"
+        return f"{self.__class__.__name__}({value})"
 
     def __len__(self):
         return self.bits
@@ -438,6 +439,56 @@ class SelectableInt:
         return struct.unpack('<d', data)[0]
 
 
+class SelectableIntMappingMeta(type):
+    def __new__(metacls, name, bases, attrs, bits=0, fields=None):
+        if fields is None:
+            fields = {}
+
+        def field(item):
+            (key, value) = item
+            if isinstance(value, dict):
+                value = dict(map(field, value.items()))
+            else:
+                value = tuple(value)
+            return (key, value)
+
+        cls = super().__new__(metacls, name, bases, attrs)
+        cls.__bits = bits
+        cls.__fields = dict(map(field, fields.items()))
+
+        return cls
+
+    def __iter__(cls):
+        for (key, value) in cls.__fields.items():
+            yield (key, value)
+
+    def __getattr__(cls, attr):
+        try:
+            return cls.__fields[attr]
+        except KeyError as error:
+            raise AttributeError from error
+
+    @property
+    def bits(cls):
+        return cls.__bits
+
+
+class SelectableIntMapping(SelectableInt, metaclass=SelectableIntMappingMeta):
+    def __init__(self, value=0):
+        return super().__init__(value, self.__class__.bits)
+
+    def __getattr__(self, attr):
+        def field(value):
+            if isinstance(value, dict):
+                return {key:field(value) for (key, value) in tuple(value.items())}
+            return FieldSelectableInt(si=self, br=value)
+
+        try:
+            return field(getattr(self.__class__, attr))
+        except KeyError as error:
+            raise AttributeError from error
+
+
 def onebit(bit):
     return SelectableInt(1 if bit else 0, 1)