From e3ab620805c7b929a7a14f31afe3ac6521d6eef8 Mon Sep 17 00:00:00 2001 From: Rupert Swarbrick Date: Wed, 12 Jul 2023 15:43:16 +0100 Subject: [PATCH] [reggen] Make reggen library MyPy-clean Fix some mypy errors in the reggen library. It looks like the version of MyPy that we're using in CI at the moment isn't new enough to notice the problems, so we won't really see much change from this commit. However, these changes fix things with 1.0.1 (the latest release), which spat out lots of messages without them. Getting things happy again is mostly a case of adding some types to guide the tool so that it knows what's going on. There's also a small re-write in gen_selfdoc.py: there, the doc_tbl_head() function used an optional int as a way of encoding a bool. This seemed a bit silly (and hard to encode!), so I've switched it to use True/False instead. Finally, we fix a type error in register.py, where the code was missing some parentheses and testing a function (rather than its return value) against None. One slightly odd thing is the change to access.py. There, the problem was that self.value[1].name wasn't known to be a string. It turns out that this depends on the Python version(!) and is tracked in https://github.com/python/mypy/issues/12483. Using a do-nothing cast with str() silences things. Signed-off-by: Rupert Swarbrick --- util/design/mubi/prim_mubi.py | 12 ++++++------ util/reggen/access.py | 2 +- util/reggen/gen_json.py | 8 ++++---- util/reggen/gen_selfdoc.py | 36 +++++++++++++++++++---------------- util/reggen/register.py | 2 +- 5 files changed, 32 insertions(+), 28 deletions(-) diff --git a/util/design/mubi/prim_mubi.py b/util/design/mubi/prim_mubi.py index 4a44b55e5511a..074691c98bb29 100755 --- a/util/design/mubi/prim_mubi.py +++ b/util/design/mubi/prim_mubi.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 r"""Converts mubi mako templates """ -from mako.template import Template +from mako.template import Template # type: ignore MUBI_PKG_TPL_PATH = "util/design/data/prim_mubi_pkg.sv.tpl" MUBI_CORE_TPL_PATH = "util/design/data/prim_mubi.core.tpl" @@ -25,11 +25,11 @@ N_MAX_NIBBLES = 4 -def is_width_valid(width): +def is_width_valid(width: int) -> bool: return (width % 4 == 0) and (width // 4 <= N_MAX_NIBBLES) and (width > 0) -def mubi_value_as_hexstr(sel: bool, width: int): +def mubi_value_as_hexstr(sel: bool, width: int) -> str: if is_width_valid(width): nibble = int(width / 4) @@ -48,15 +48,15 @@ def mubi_value_as_hexstr(sel: bool, width: int): return true_val if sel else false_val -def mubi_value_as_int(sel: bool, width: int): +def mubi_value_as_int(sel: bool, width: int) -> int: return int(mubi_value_as_hexstr(sel, width), 16) -def get_c_path(): +def get_c_path() -> str: return MUBI_SW_OUT_PATH -def gen(): +def gen() -> None: tpls = [ (MUBI_PKG_TPL_PATH, MUBI_PKG_OUT_PATH), diff --git a/util/reggen/access.py b/util/reggen/access.py index 23de055dd2b44..699dcfb5052de 100644 --- a/util/reggen/access.py +++ b/util/reggen/access.py @@ -90,7 +90,7 @@ def dv_rights(self) -> str: '''Return a UVM access string as used by uvm_field::set_access().''' if self.key == 'r0w1c': return 'W1C' - return self.value[1].name + return str(self.value[1].name) def swrd(self) -> SwRdAccess: return self.value[3] diff --git a/util/reggen/gen_json.py b/util/reggen/gen_json.py index c593cc1ca15eb..8d6786aa3b6c7 100644 --- a/util/reggen/gen_json.py +++ b/util/reggen/gen_json.py @@ -4,10 +4,12 @@ """Generate JSON/compact JSON/Hjson from register JSON tree """ -import hjson +from typing import Any, TextIO +import hjson # type: ignore -def gen_json(obj, outfile, format): + +def gen_json(obj: Any, outfile: TextIO, format: str) -> None: if format == 'json': hjson.dumpJSON(obj, outfile, @@ -30,5 +32,3 @@ def gen_json(obj, outfile, format): use_decimal=True) else: raise ValueError('Invalid JSON format ' + format) - - return 0 diff --git a/util/reggen/gen_selfdoc.py b/util/reggen/gen_selfdoc.py index adbef66795254..a1345cb9fcb83 100644 --- a/util/reggen/gen_selfdoc.py +++ b/util/reggen/gen_selfdoc.py @@ -10,8 +10,10 @@ ip_block, enum_entry, field, register, multi_register, window) +from typing import Any, Optional, TextIO -def genout(outfile, msg): + +def genout(outfile: TextIO, msg: str) -> None: outfile.write(msg) @@ -200,8 +202,8 @@ def genout(outfile, msg): """ -def doc_tbl_head(outfile, use): - if use is not None: +def doc_tbl_head(outfile: TextIO, use: bool) -> None: + if use: genout(outfile, "\nKey | Kind | Type | Description of Value\n") genout(outfile, "--- | ---- | ---- | --------------------\n") else: @@ -209,7 +211,8 @@ def doc_tbl_head(outfile, use): genout(outfile, "--- | -----------\n") -def doc_tbl_line(outfile, key, use, desc): +def doc_tbl_line(outfile: TextIO, key: str, + use: Optional[str], desc: Any) -> None: if use is not None: desc_key, desc_txt = desc val_type = (validate.val_types[desc_key][0] @@ -220,6 +223,7 @@ def doc_tbl_line(outfile, key, use, desc): desc_txt = desc if val_type is not None: + assert use is not None genout( outfile, '{} | {} | {} | {}\n'.format(key, validate.key_use[use], val_type, desc_txt)) @@ -227,7 +231,7 @@ def doc_tbl_line(outfile, key, use, desc): genout(outfile, key + " | " + desc_txt + "\n") -def document(outfile): +def document(outfile: TextIO) -> None: genout(outfile, doc_intro) for x in validate.val_types: genout( @@ -235,19 +239,19 @@ def document(outfile): validate.val_types[x][0] + " | " + validate.val_types[x][1] + "\n") genout(outfile, swaccess_intro) - doc_tbl_head(outfile, None) + doc_tbl_head(outfile, False) for key, value in SWACCESS_PERMITTED.items(): doc_tbl_line(outfile, key, None, value[0]) genout(outfile, hwaccess_intro) - doc_tbl_head(outfile, None) - for key, value in HWACCESS_PERMITTED.items(): - doc_tbl_line(outfile, key, None, value[0]) + doc_tbl_head(outfile, False) + for key, hw_value in HWACCESS_PERMITTED.items(): + doc_tbl_line(outfile, key, None, hw_value[0]) genout( outfile, "\n\nThe top level of the JSON is a group containing " "the following keys:\n") - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for k, v in ip_block.REQUIRED_FIELDS.items(): doc_tbl_line(outfile, k, 'r', v) for k, v in ip_block.OPTIONAL_FIELDS.items(): @@ -257,7 +261,7 @@ def document(outfile): genout( outfile, "\n\nThe list of registers includes register definition " "groups containing the following keys:\n") - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for k, v in register.REQUIRED_FIELDS.items(): doc_tbl_line(outfile, k, 'r', v) for k, v in register.OPTIONAL_FIELDS.items(): @@ -267,7 +271,7 @@ def document(outfile): genout( outfile, "\n\nIn the fields list each field definition is a group " "itself containing the following keys:\n") - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for k, v in field.REQUIRED_FIELDS.items(): doc_tbl_line(outfile, k, 'r', v) for k, v in field.OPTIONAL_FIELDS.items(): @@ -275,14 +279,14 @@ def document(outfile): genout(outfile, field_example) genout(outfile, "\n\nDefinitions in an enumeration group contain:\n") - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for k, v in enum_entry.REQUIRED_FIELDS.items(): doc_tbl_line(outfile, k, 'r', v) genout( outfile, "\n\nThe list of registers may include single entry groups " "to control the offset, open a window or generate registers:\n") - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for x in validate.list_optone: doc_tbl_line(outfile, x, 'o', validate.list_optone[x]) @@ -290,14 +294,14 @@ def document(outfile): genout(outfile, regwen_intro) genout(outfile, window_intro) - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for k, v in window.REQUIRED_FIELDS.items(): doc_tbl_line(outfile, k, 'r', v) for k, v in window.OPTIONAL_FIELDS.items(): doc_tbl_line(outfile, k, 'o', v) genout(outfile, multi_intro) - doc_tbl_head(outfile, 1) + doc_tbl_head(outfile, True) for k, v in multi_register.REQUIRED_FIELDS.items(): doc_tbl_line(outfile, k, 'r', v) for k, v in multi_register.OPTIONAL_FIELDS.items(): diff --git a/util/reggen/register.py b/util/reggen/register.py index cfc5c39f24e0a..b2def748166c7 100644 --- a/util/reggen/register.py +++ b/util/reggen/register.py @@ -200,7 +200,7 @@ def __init__(self, for field in self.fields: if field.swaccess.key == 'rc': rc_fields.append(field.name) - elif field.swaccess.allows_write: + elif field.swaccess.allows_write(): we_fields.append(field.name) if rc_fields and we_fields: raise ValueError("Register {} has both software writable fields "