code-morph in StepLoop work towards splitting into iterators
[openpower-isa.git] / src / openpower / decoder / power_fields.py
index 9e4758b4a675e00ddffcd667e15940efc8c42f0c..f39ff38603b096e145076bc2b42684278aa1d564 100644 (file)
@@ -8,6 +8,7 @@ from openpower.decoder.selectable_int import (
     SelectableInt as _SelectableInt,
     BitRange as _BitRange,
     selectconcat as _selectconcat,
+    selectltu as _selectltu,
 )
 
 
@@ -65,11 +66,14 @@ class Reference:
         return op(lhs, rhs)
 
     def __lt__(self, other):
-        return self.__binary_operator(_operator.lt, other)
+        return self.__binary_operator(_selectltu, other)
 
     def __eq__(self, other):
         return self.__binary_operator(_operator.eq, other)
 
+    def __bool__(self):
+        return bool(int(self))
+
     def __int__(self):
         span = dict.fromkeys(self.__class__.span).keys()
         return int(_selectconcat(*(self.storage[bit] for bit in span)))
@@ -162,14 +166,8 @@ class FieldMeta(type):
     def span(cls):
         return cls.__members__
 
-    def traverse(cls, path):
-        yield (path, cls.__members__)
-
 
 class Field(Reference, metaclass=FieldMeta):
-    def __len__(self):
-        return self.__class__.__len__()
-
     def __repr__(self):
         return f"[{len(self.__class__)}]0x{int(self):x}"
 
@@ -181,9 +179,16 @@ class Field(Reference, metaclass=FieldMeta):
         if isinstance(key, int):
             bit = self.storage[self.__class__.__members__[key]]
             return _SelectableInt(value=bit, bits=1)
+        if isinstance(key, slice):
+            assert key.step is None or key.step == 1
+            key = range(key.start, key.stop)
 
         return _selectconcat(*(self[bit] for bit in tuple(key)))
 
+    def traverse(self, path):
+        span = self.__class__.__members__
+        yield (path, self.storage[span], span)
+
 
 class MappingMeta(type):
     def __new__(metacls, clsname, bases, ns):
@@ -227,17 +232,7 @@ class MappingMeta(type):
         return length
 
     def __getitem__(cls, selector):
-        best_min = 0
-        best_max = 0
-        for field in cls.__members__.values():
-            length = len(field)
-            best_min = min(best_min, length)
-            best_max = max(best_max, length)
-
-        items = tuple(range(best_min, best_max))
-        field = FieldMeta(cls.__name__, (Field,), {}, items=items)
-
-        return field[selector]
+        return cls.__members__["_"][selector]
 
     def remap(cls, scheme):
         ns = {}
@@ -255,15 +250,6 @@ class MappingMeta(type):
         for field in cls.__members__.values():
             yield from field.span
 
-    def traverse(cls, path=""):
-        for (name, field) in cls:
-            if name == "_":
-                yield from field.traverse(path=path)
-            elif path == "":
-                yield from field.traverse(path=name)
-            else:
-                yield from field.traverse(path=f"{path}.{name}")
-
 
 class Mapping(Reference, metaclass=MappingMeta):
     def __init__(self, storage, **kwargs):
@@ -284,10 +270,19 @@ class Mapping(Reference, metaclass=MappingMeta):
 
     def __getitem__(self, key):
         if isinstance(key, (int, slice, list, tuple, range)):
-            return self.storage[key]
+            return self["_"][key]
 
         return self.__members[key]
 
+    def traverse(self, path=""):
+        for (name, member) in self.__members.items():
+            if name == "_":
+                yield from member.traverse(path=path)
+            elif path == "":
+                yield from member.traverse(path=name)
+            else:
+                yield from member.traverse(path=f"{path}.{name}")
+
 
 def decode_instructions(form):
     res = {}