From c0d8e0d94b6974a8c9c26d649d32e0f1372353b6 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 11 Mar 2021 22:04:09 -0800 Subject: [PATCH] add RangesField that tracks ranges of bits for instruction fields --- generate_headers.py | 131 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 12 deletions(-) diff --git a/generate_headers.py b/generate_headers.py index 75126c6..e498a21 100755 --- a/generate_headers.py +++ b/generate_headers.py @@ -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 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 -- 2.30.2