add RangesField that tracks ranges of bits for instruction fields
authorJacob Lifshay <programmerjake@gmail.com>
Fri, 12 Mar 2021 06:04:09 +0000 (22:04 -0800)
committerJacob Lifshay <programmerjake@gmail.com>
Fri, 12 Mar 2021 06:04:09 +0000 (22:04 -0800)
generate_headers.py

index 75126c6387577dbf469159b51fa8fb376e880052..e498a213289bff2275d24898b1898fb0c3da8a8a 100755 (executable)
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 # See Notices.txt for copyright information
 
+from typing import List
 from soc.decoder.isa.caller import (SVP64PrefixFields, SV64P_MAJOR_SIZE,
                                     SV64P_PID_SIZE, SVP64RMFields,
                                     SVP64RM_EXTRA2_SPEC_SIZE,
@@ -15,27 +16,133 @@ from soc.decoder.power_svp64 import SVP64RM, get_regtype, decode_extra
 from soc.decoder.power_fields import DecodeFields
 
 
-class RangeField:
-    def __init__(self):
-        self.start = None
-        self.last = None
-    # TODO: finish
+class InclusiveRange:
+    __slots__ = "start", "stop"
+
+    def __init__(self, start, stop=None):
+        if stop is None:
+            stop = start
+        self.start = start
+        self.stop = stop
+
+    def __len__(self) -> int:
+        return self.width
+
+    @property
+    def width(self) -> int:
+        return self.stop - self.start + 1
+
+    def __repr__(self):
+        if self.start == self.stop:
+            return f"InclusiveRange({self.start})"
+        return f"InclusiveRange({self.start}, {self.stop})"
+
+    def __str__(self):
+        if self.start == self.stop:
+            return f"{self.start}"
+        return f"{self.start}:{self.stop}"
+
+    def append(self, v):
+        if v == self.stop + 1:
+            self.stop = v
+        else:
+            raise ValueError()
+
+    def endian_reversed(self, word_length) -> "InclusiveRange":
+        # note reversed stop/start
+        return InclusiveRange(word_length - 1 - self.stop,
+                              word_length - 1 - self.start)
+
+
+class RangesField:
+    __slots__ = "ranges",
+    ranges: List[InclusiveRange]
+
+    def __init__(self, ranges=None):
+        if ranges is None:
+            ranges = []
+        if isinstance(ranges, InclusiveRange):
+            ranges = [ranges]
+        self.ranges = ranges
+
+    def __len__(self):
+        retval = 0
+        for i in self.ranges:
+            retval += len(i)
+        return retval
+
+    def __repr__(self):
+        if len(self.ranges) == 0:
+            return "RangesField()"
+        if len(self.ranges) == 1:
+            return f"RangesField({self.ranges[0]})"
+        return f"RangesField({self.ranges})"
+
+    def __str__(self):
+        if len(self.ranges) == 0:
+            return "none"
+        return ",".join(map(str, self.ranges))
+
+    def __setitem__(self, key, value):
+        assert isinstance(key, int)
+        assert isinstance(value, int)
+        assert key == len(self)
+        try:
+            self.ranges[-1].append(value)
+            return
+        except IndexError:
+            pass
+        except ValueError:
+            pass
+        self.ranges.append(InclusiveRange(value))
+
+    def endian_reversed(self, word_length) -> "RangesField":
+        return RangesField([i.endian_reversed(word_length) for i in reversed(self.ranges)])
+
+    @property
+    def contiguous(self) -> bool:
+        return len(self.ranges) == 1
+
+    @property
+    def start(self) -> int:
+        assert self.contiguous
+        return self.ranges[0].start
+
+    @property
+    def stop(self) -> int:
+        assert self.contiguous
+        return self.ranges[0].stop
+
+    @property
+    def width(self) -> int:
+        assert self.contiguous
+        return self.ranges[0].width
 
 
 isa = ISA()
 svp64rm = SVP64RM()
-decode_fields = DecodeFields()
+decode_fields = DecodeFields(bitkls=RangesField)
 decode_fields.create_specs()
-
-decode_fields.forms
-PRIMARY_OPCODE_SHIFT = 32 - 6
+PO_FIELD: RangesField = decode_fields.PO
+RT_FIELD: RangesField = decode_fields.RT
+RA_FIELD: RangesField = decode_fields.RA
+print(f"PO_FIELD={PO_FIELD}")
+print(f"RT_FIELD={RT_FIELD}")
+print(f"RA_FIELD={RA_FIELD}")
+
+WORD_LENGTH = 32
+PRIMARY_OPCODE_SHIFT = PO_FIELD.endian_reversed(WORD_LENGTH).start
 # unofficial value. see https://libre-soc.org/openpower/sv/setvl/
 # FIXME: incorrect extended opcode value
 SETVL_OPCODE = (19 << PRIMARY_OPCODE_SHIFT) | (0 << 1)
 SETVL_IMMEDIATE_SHIFT = 32 - 7 - 16
 REG_FIELD_WIDTH = 5
-XL_FORM_RT_SHIFT = 32 - REG_FIELD_WIDTH - 6
-XL_FORM_RA_SHIFT = 32 - REG_FIELD_WIDTH - 11
+RT_SHIFT = RT_FIELD.endian_reversed(WORD_LENGTH).start
+RA_SHIFT = RA_FIELD.endian_reversed(WORD_LENGTH).start
+
+print(f"RT_SHIFT={RT_SHIFT}")
+print(f"RA_SHIFT={RA_SHIFT}")
+print(f"PRIMARY_OPCODE_SHIFT={PRIMARY_OPCODE_SHIFT}")
 
 
 def is_power_of_2(i):
@@ -107,7 +214,7 @@ inline __attribute__((always_inline)) VL<MAX_VL> setvl(std::size_t vl)
         "# setvl %[retval], %[vl], MVL=%[max_vl]\\n\\t"
         ".long %[instr] | (%[retval] << %[rt_shift]) | (%[vl] << %[ra_shift])"
         : [retval] "=b"(retval.value)
-        : [vl] "b"(vl), [max_vl] "n"(MAX_VL), [instr] "n"({FIXME@@@FINISH}));
+        : [vl] "b"(vl), [max_vl] "n"(MAX_VL), [instr] "n"({FIXME___FINISH}));
     return retval;
 }}
 }} // namespace sv