Skip to content

Commit

Permalink
[reggen] Make reggen library MyPy-clean
Browse files Browse the repository at this point in the history
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
python/mypy#12483. Using a do-nothing cast
with str() silences things.

Signed-off-by: Rupert Swarbrick <rswarbrick@lowrisc.org>
  • Loading branch information
rswarbrick committed Jul 12, 2023
1 parent 2030c80 commit e3ab620
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 28 deletions.
12 changes: 6 additions & 6 deletions util/design/mubi/prim_mubi.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
Expand All @@ -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),
Expand Down
2 changes: 1 addition & 1 deletion util/reggen/access.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
8 changes: 4 additions & 4 deletions util/reggen/gen_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -30,5 +32,3 @@ def gen_json(obj, outfile, format):
use_decimal=True)
else:
raise ValueError('Invalid JSON format ' + format)

return 0
36 changes: 20 additions & 16 deletions util/reggen/gen_selfdoc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down Expand Up @@ -200,16 +202,17 @@ 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:
genout(outfile, "\nKey | Description\n")
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]
Expand All @@ -220,34 +223,35 @@ 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))
else:
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(
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():
Expand All @@ -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():
Expand All @@ -267,37 +271,37 @@ 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():
doc_tbl_line(outfile, k, 'o', v)
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])

genout(outfile, offset_intro)
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():
Expand Down
2 changes: 1 addition & 1 deletion util/reggen/register.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 "
Expand Down

0 comments on commit e3ab620

Please sign in to comment.