From: Jacob Lifshay Date: Wed, 17 Mar 2021 20:45:00 +0000 (-0700) Subject: add function to generate table of instruction properties for unimplemented instructions X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=48b74372374bd2f1d4d966d23c254fdd08fb8b9d;p=simplev-cpp.git add function to generate table of instruction properties for unimplemented instructions --- diff --git a/generate_headers.py b/generate_headers.py index 0163c2f..9e33e93 100755 --- a/generate_headers.py +++ b/generate_headers.py @@ -3,15 +3,133 @@ # See Notices.txt for copyright information import sys -from pprint import pprint from io import StringIO -from typing import List +from typing import Any, Dict, List from soc.decoder.pseudo.pagereader import ISA from soc.decoder.power_svp64 import SVP64RM from soc.decoder.power_fields import DecodeFields from soc.decoder.power_decoder import create_pdecode +# generated text should wrap at 80 columns +OUTPUT_WIDTH = 80 + + +def wcwidth(text: str) -> int: + """ return the number of columns that `text` takes up if printed to a terminal. + returns -1 if any characters are not printable. + """ + # TODO: replace with wcwidth from wcwidth + # package when we add pip packaging files + if text.isprintable(): + return len(text) + return -1 + + +class TableEntry: + def __init__(self, key: str, value: Any): + self.key = repr(key) + self.key_lines = self.key.splitlines() + for i in range(len(self.key_lines)): + self.key_lines[i] = self.key_lines[i].rstrip() + self.value = repr(value) + self.value_lines = self.value.splitlines() + for i in range(len(self.value_lines)): + self.value_lines[i] = self.value_lines[i].rstrip() + self.width = max(max(map(wcwidth, self.key_lines)), + max(map(wcwidth, self.value_lines))) + + +def format_dict_as_tables(d: Dict[str, Any], column_width: int) -> List[str]: + entries = [TableEntry(k, v) for k, v in d.items()] + entries.sort(key=lambda entry: entry.key) + entries.reverse() + col_sep_start = '| ' + col_sep_start_top_line = '+-' + col_sep_start_mid_line = '+=' + col_sep_start_bottom_line = '+-' + col_sep_start_width = wcwidth(col_sep_start) + col_sep_mid = ' | ' + col_sep_mid_top_line = '-+-' + col_sep_mid_mid_line = '=+=' + col_sep_mid_bottom_line = '-+-' + col_sep_mid_width = wcwidth(col_sep_mid) + col_sep_end = ' |' + col_sep_end_top_line = '-+' + col_sep_end_mid_line = '=+' + col_sep_end_bottom_line = '-+' + col_sep_end_width = wcwidth(col_sep_end) + col_top_line_char = '-' + col_mid_line_char = '=' + col_bottom_line_char = '-' + retval: List[str] = [] + while len(entries) != 0: + total_width = col_sep_start_width - col_sep_mid_width + column_entries: List[TableEntry] = [] + key_line_count = 0 + value_line_count = 0 + while len(entries) != 0: + entry = entries.pop() + next_total_width = total_width + col_sep_mid_width + next_total_width += entry.width + if len(column_entries) != 0 and \ + next_total_width + col_sep_end_width >= column_width: + entries.append(entry) + break + total_width = next_total_width + column_entries.append(entry) + key_line_count = max(key_line_count, len(entry.key_lines)) + value_line_count = max(value_line_count, len(entry.value_lines)) + top_line = col_sep_start_top_line + mid_line = col_sep_start_mid_line + bottom_line = col_sep_start_bottom_line + key_lines = [col_sep_start] * key_line_count + value_lines = [col_sep_start] * value_line_count + for i in range(len(column_entries)): + last = (i == len(column_entries) - 1) + entry = column_entries[i] + + def extend_line(line, entry_text, fill_char, + col_sep_mid, col_sep_end): + line += entry_text + line += fill_char * (entry.width - wcwidth(entry_text)) + line += col_sep_end if last else col_sep_mid + return line + + top_line = extend_line(line=top_line, entry_text='', + fill_char=col_top_line_char, + col_sep_mid=col_sep_mid_top_line, + col_sep_end=col_sep_end_top_line) + mid_line = extend_line(line=mid_line, entry_text='', + fill_char=col_mid_line_char, + col_sep_mid=col_sep_mid_mid_line, + col_sep_end=col_sep_end_mid_line) + bottom_line = extend_line(line=bottom_line, entry_text='', + fill_char=col_bottom_line_char, + col_sep_mid=col_sep_mid_bottom_line, + col_sep_end=col_sep_end_bottom_line) + + def extend_lines(lines, entry_lines): + for j in range(len(lines)): + entry_text = '' + if j < len(entry_lines): + entry_text = entry_lines[j] + lines[j] = extend_line(line=lines[j], + entry_text=entry_text, + fill_char=' ', + col_sep_mid=col_sep_mid, + col_sep_end=col_sep_end) + + extend_lines(key_lines, entry.key_lines) + extend_lines(value_lines, entry.value_lines) + retval.append(top_line) + retval.extend(key_lines) + retval.append(mid_line) + retval.extend(value_lines) + retval.append(bottom_line) + return retval + + class InclusiveRange: __slots__ = "start", "stop" @@ -149,7 +267,7 @@ def subdecoders(): yield from visit_subdecoders(decoder.dec) -def make_opcodes_dict(): +def make_opcodes_dict() -> Dict[str, Dict[str, Any]]: retval = {} for subdecoder in subdecoders(): for opcode in subdecoder.opcodes: @@ -325,8 +443,14 @@ inline __attribute__((always_inline)) VL setvl(std::size_t vl) else: assert SV_Ptype == 'P1' # TODO - o.write(f"""/// (not yet implemented) -template + o.write("/// (not yet implemented)\n") + instr_without_subdecoder = instr.copy() + del instr_without_subdecoder['subdecoder'] + comment = "/// " + for line in format_dict_as_tables(instr_without_subdecoder, + OUTPUT_WIDTH - wcwidth(comment)): + o.write((comment + line).rstrip() + '\n') + o.write(f"""template void {function_name}(Args &&...) = delete; """) o.write(f"""}} // namespace sv