Skip to content

Commit efe665f

Browse files
committed
Fix linting errors pointed by ruff
Signed-off-by: Douglas Reis <doreis@lowrisc.org>
1 parent c2ce5d0 commit efe665f

File tree

10 files changed

+117
-91
lines changed

10 files changed

+117
-91
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ select = ["ALL"]
3636
extend-select = ["W391", "E303"]
3737
allowed-confusables = [""]
3838
ignore = [
39-
"D203", "D213", "COM812", "ISC001",
40-
"FIX", "TD",
39+
"D203", "D213", "COM812", "ISC001", "FIX", "TD", "T201", "S101", "C901", "D401",
40+
"PLR0911", "PLR0915", "INP001", "RUF012", "EXE001", "S701"
4141
]
4242

4343
[tool.uv.workspace]

rdl2ot/src/rdl2ot/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# Copyright lowRISC contributors (OpenTitan project).
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
4+
5+
"""Init."""

rdl2ot/src/rdl2ot/__main__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5+
"""Main."""
6+
57
from cli import main
68

79
if __name__ == "__main__":

rdl2ot/src/rdl2ot/cli.py

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,43 +3,50 @@
33
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
44
# SPDX-License-Identifier: Apache-2.0
55

6+
7+
"""Cli."""
8+
69
from pathlib import Path
710

811
import click
12+
import export_rtl as rtl_exporter
13+
from systemrdl import RDLCompiler
914

1015

1116
@click.group()
12-
def main():
13-
pass
17+
def main() -> None:
18+
"""Cli."""
1419

1520

1621
@main.command()
1722
@click.argument(
1823
"input_file",
1924
type=click.Path(writable=True),
20-
# help="The input RDL.",
2125
)
2226
@click.argument(
2327
"out_dir",
2428
default="./result",
2529
type=click.Path(writable=True),
26-
# help="The destination dir to generate the output.",
2730
)
28-
def export_rtl(input_file: str, out_dir: str):
29-
from systemrdl import RDLCompiler
31+
def export_rtl(input_file: str, out_dir: str) -> None:
32+
"""Export opentitan rtl.
3033
34+
INPUT_FILE: The input RDL
35+
HELP: The destination dir to generate the output
36+
37+
"""
3138
rdlc = RDLCompiler()
3239
try:
3340
rdlc.compile_file(input_file)
3441
root = rdlc.elaborate()
3542
except Exception as e:
36-
raise RuntimeError(f"In file {input_file}") from e
37-
38-
import export_rtl
43+
error_msg = f"In file {input_file}"
44+
raise RuntimeError(error_msg) from e
3945

4046
try:
41-
export_rtl.run(rdlc, root, Path(out_dir))
47+
rtl_exporter.run(rdlc, root, Path(out_dir))
4248
except Exception as e:
43-
raise RuntimeError(f"In file {input_file}") from e
49+
error_msg = f"In file {input_file}"
50+
raise RuntimeError(error_msg) from e
4451

4552
print("Successfully finished!\n")

rdl2ot/src/rdl2ot/export_rtl.py

Lines changed: 27 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5+
"""Export RDL to opentitan RTL."""
6+
57
import json
68
from pathlib import Path
79

@@ -14,18 +16,18 @@
1416
DEFAULT_INTERFACE_NAME = "regs"
1517

1618

17-
def run(rdlc: RDLCompiler, obj: node.RootNode, out_dir: Path):
19+
def run(rdlc: RDLCompiler, obj: node.RootNode, out_dir: Path) -> None:
20+
"""Export RDL to opentitan RTL."""
1821
factory = OtInterfaceBuilder(rdlc)
1922
data = factory.parse_root(obj.top)
20-
with open("/tmp/reg.json", "w", encoding="utf-8") as f:
23+
with (out_dir / "rdl.json").open("w", encoding="utf-8") as f:
2124
json.dump(data, f, indent=2)
2225

2326
file_loader = FileSystemLoader(TEMPLATES_DIR)
2427
env = Environment(loader=file_loader)
2528

2629
ip_name = data["ip_name"]
2730
reg_pkg_tpl = env.get_template("reg_pkg.sv.tpl")
28-
# stream = reg_pkg_tpl.stream(data)
2931
stream = reg_pkg_tpl.render(data)
3032
path = out_dir / f"{ip_name}_reg_pkg.sv"
3133
path.open("w").write(stream)
@@ -35,14 +37,15 @@ def run(rdlc: RDLCompiler, obj: node.RootNode, out_dir: Path):
3537
for interface in data["interfaces"]:
3638
name = "_{}".format(interface["name"].lower()) if "name" in interface else ""
3739
data_ = {"ip_name": ip_name, "interface": interface}
38-
# stream = reg_top_tpl.stream(data_)
3940
stream = reg_top_tpl.render(data_).replace(" \n", "\n")
4041
path = out_dir / f"{ip_name}{name}_reg_top.sv"
4142
path.open("w").write(stream)
4243
print(f"Generated {path}.")
4344

4445

4546
class OtInterfaceBuilder:
47+
"""Opentitan Interface Builder."""
48+
4649
num_regs: int = 0 # The number of registers of an interface
4750
num_windows: int = 0 # The number of registers of an interface
4851
any_async_clk: bool = False # Whether is there any register with async clock in the interface
@@ -52,13 +55,13 @@ class OtInterfaceBuilder:
5255
reg_index: int = 0
5356
rdlc: RDLCompiler
5457

55-
def __init__(self, rdlc: RDLCompiler):
58+
def __init__(self, rdlc: RDLCompiler) -> None:
59+
"""Constructor."""
5660
self.rdlc = rdlc
5761

5862
def get_field(self, field: node.FieldNode) -> dict:
59-
"""Parse a field and return a dictionary.
60-
"""
61-
obj = dict()
63+
"""Parse a field and return a dictionary."""
64+
obj = {}
6265
obj["name"] = field.inst_name
6366
obj["type"] = "field"
6467
obj["desc"] = field.get_property("desc", default="")
@@ -91,9 +94,8 @@ def get_field(self, field: node.FieldNode) -> dict:
9194
return obj
9295

9396
def get_mem(self, mem: node.FieldNode) -> dict:
94-
"""Parse a memory and return a dictionary representing a window.
95-
"""
96-
obj = dict()
97+
"""Parse a memory and return a dictionary representing a window."""
98+
obj = {}
9799
obj["name"] = mem.inst_name
98100
obj["entries"] = mem.get_property("mementries")
99101
obj["sw_writable"] = mem.is_sw_writable
@@ -107,9 +109,8 @@ def get_mem(self, mem: node.FieldNode) -> dict:
107109
return obj
108110

109111
def get_reg(self, reg: node.RegNode) -> dict:
110-
"""Parse a register and return a dictionary.
111-
"""
112-
obj = dict()
112+
"""Parse a register and return a dictionary."""
113+
obj = {}
113114
obj["name"] = reg.inst_name
114115
obj["type"] = "reg"
115116
obj["width"] = reg.get_property("regwidth")
@@ -140,8 +141,8 @@ def get_reg(self, reg: node.RegNode) -> dict:
140141
msb = 0
141142
reset_val = 0
142143
bitmask = 0
143-
for field in reg.fields():
144-
field = self.get_field(field)
144+
for f in reg.fields():
145+
field = self.get_field(f)
145146
obj["fields"].append(field)
146147
sw_write_en |= field["sw_write_en"]
147148
msb = max(msb, field["msb"])
@@ -175,17 +176,14 @@ def get_reg(self, reg: node.RegNode) -> dict:
175176
return obj
176177

177178
def get_paramesters(self, obj: node.AddrmapNode | node.RegfileNode) -> [dict]:
178-
"""Parse the custom property localparams and return a list of dictionaries.
179-
"""
180-
res = [
179+
"""Parse the custom property localparams and return a list of dictionaries."""
180+
return [
181181
{"name": param.name, "type": "int", "value": param.get_value()}
182182
for param in obj.inst.parameters
183183
]
184-
return res
185184

186185
def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = None) -> dict:
187-
"""Parse an interface and return a dictionary.
188-
"""
186+
"""Parse an interface and return a dictionary."""
189187
self.num_regs = 0
190188
self.num_windows = 0
191189
self.any_async_clk = False
@@ -196,7 +194,7 @@ def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = Non
196194
if addrmap.is_array:
197195
print(f"WARNING: Unsupported array type: {type(addrmap)}, skiping...")
198196

199-
interface = dict()
197+
interface = {}
200198
if defalt_name:
201199
interface["name"] = addrmap.inst_name or defalt_name
202200

@@ -233,21 +231,20 @@ def get_interface(self, addrmap: node.AddrmapNode, defalt_name: None | str = Non
233231
interface["all_async_clk"] = self.all_async_clk
234232
interface["any_shadowed_reg"] = self.any_shadowed_reg
235233
interface["any_integrity_bypass"] = any(
236-
[win["integrity_bypass"] for win in interface["windows"]]
234+
win["integrity_bypass"] for win in interface["windows"]
237235
)
238236
return interface
239237

240238
def parse_root(self, root: node.AddrmapNode) -> dict:
241-
"""Parse the root node and return a dictionary representing a window.
242-
"""
239+
"""Parse the root node and return a dictionary representing a window."""
243240
if root.is_array:
244241
print("Error: Unsupported array type on the top")
245242
raise RuntimeError
246243
if not isinstance(root, node.AddrmapNode):
247244
print("Error: Top level must be an addrmap")
248-
raise RuntimeError
245+
raise TypeError
249246

250-
obj = dict()
247+
obj = {}
251248
params = self.get_paramesters(root)
252249
if params:
253250
obj["parameters"] = params
@@ -263,10 +260,10 @@ def parse_root(self, root: node.AddrmapNode) -> dict:
263260
continue
264261
else:
265262
print(
266-
f"""Error: Unsupported type: {type(child)}, top level only supports
263+
f"""Error: Unsupported type: {type(child)}, top level only supports
267264
addrmap and reg components."""
268265
)
269-
raise RuntimeError
266+
raise TypeError
270267

271268
# If the root contain imediate registers, use a default interface name
272269
if len(root.registers()) > 0:

rdl2ot/src/rdl2ot/opentitan.py

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,28 @@
22
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
33
# SPDX-License-Identifier: Apache-2.0
44

5+
"""Functions with opentitan specific logic."""
6+
57
import re
68

79
from systemrdl import node
810
from systemrdl.rdltypes import AccessType, OnReadType, OnWriteType
911

1012

1113
def register_permit_mask(reg: dict) -> int:
12-
"""One bit presents one byte in the register, so in total 4 bits are used.
13-
"""
14+
"""One bit presents one byte in the register, so in total 4 bits are used."""
1415
w = reg["msb"] + 1
15-
if w > 24:
16+
if w > 24: # noqa: PLR2004
1617
return 0b1111
17-
if w > 16:
18+
if w > 16: # noqa: PLR2004
1819
return 0b0111
19-
if w > 8:
20+
if w > 8: # noqa: PLR2004
2021
return 0b0011
2122
return 0b0001
2223

2324

24-
def needs_read_en(reg: dict()) -> bool:
25-
"""Return true if at least one field needs a read-enable
25+
def needs_read_en(reg: dict) -> bool:
26+
"""Return true if at least one field needs a read-enable.
2627
2728
This is true if any of the following are true:
2829
@@ -40,44 +41,42 @@ def needs_read_en(reg: dict()) -> bool:
4041
side might need the re signal)
4142
"""
4243
return reg["shadowed"] or any(
43-
[
44-
(field["clear_onread"] or (reg["external"] and field["sw_readable"]))
45-
for field in reg["fields"]
46-
]
44+
(field["clear_onread"] or (reg["external"] and field["sw_readable"]))
45+
for field in reg["fields"]
4746
)
4847

4948

50-
def needs_write_en(reg: dict()) -> bool:
51-
"""Should the register for this field have a write-enable signal?
49+
def needs_write_en(reg: dict) -> bool:
50+
"""Return register for this field should have a write-enable signal.
5251
5352
This is almost the same as allows_write(), but doesn't return true for
5453
RC registers, which should use a read-enable signal (connected to their
5554
prim_subreg's we port).
5655
"""
57-
return any([(not field["clear_onread"] and field["sw_writable"]) for field in reg["fields"]])
56+
return any((not field["clear_onread"] and field["sw_writable"]) for field in reg["fields"])
57+
5858

59+
def needs_qe(reg: dict) -> bool:
60+
"""Return true if the register or at least one field needs a q-enable."""
61+
return any(field["swmod"] for field in reg["fields"])
5962

60-
def needs_qe(reg: dict()) -> bool:
61-
"""Return true if the register or at least one field needs a q-enable"""
62-
return any([field["swmod"] for field in reg["fields"]])
6363

64+
def needs_int_qe(reg: dict) -> bool:
65+
"""Return true if the register or at least one field needs an internal q-enable.
6466
65-
def needs_int_qe(reg: dict()) -> bool:
66-
"""Return true if the register or at least one field needs an
67-
internal q-enable. An internal q-enable means the net
68-
may be consumed by other reg logic but will not be exposed
69-
in the package file.
67+
An internal q-enable means the net may be consumed by other reg logic but will
68+
not be exposed in the package file.
7069
"""
7170
return (bool(reg["async_clk"]) and reg["hw_writable"]) or needs_qe(reg)
7271

7372

7473
def get_bit_width(offset: int) -> int:
75-
"""Calculate the number of bits to address every byte of the block"""
74+
"""Calculate the number of bits to address every byte of the block."""
7675
return (offset - 1).bit_length()
7776

7877

7978
def get_sw_access_enum(field: node.FieldNode) -> str:
80-
"""Map the rdl access permissions to reggen SwAccess enum"""
79+
"""Map the rdl access permissions to reggen SwAccess enum."""
8180
sw = field.get_property("sw")
8281
onwrite = field.get_property("onwrite")
8382
onread = field.get_property("onread")
@@ -99,15 +98,17 @@ def get_sw_access_enum(field: node.FieldNode) -> str:
9998
return "NONE"
10099

101100

102-
def fields_no_write_en(reg: dict()) -> int:
101+
def fields_no_write_en(reg: dict) -> int:
102+
"""Count how many fields has write enable."""
103103
res = 0
104104
for idx, field in enumerate(reg["fields"]):
105105
res |= (not needs_we(field)) << idx
106106
return res
107107

108108

109109
def needs_we(field: dict) -> bool:
110-
"""Should the register for this field have a write-enable signal?
110+
"""True if the register for this field should have a write-enable signal.
111+
111112
This is almost the same as allows_write(), but doesn't return true for
112113
RC registers, which should use a read-enable signal (connected to their
113114
prim_subreg's we port).
@@ -116,8 +117,9 @@ def needs_we(field: dict) -> bool:
116117

117118

118119
def is_homogeneous(reg: dict) -> bool:
119-
"""Return true if all fields of a register are equal. The offset are excluded from
120-
the comparison.
120+
"""Return true if all fields of a register are equal.
121+
122+
The offset are excluded from the comparison.
121123
"""
122124
exclude = ["name", "msb", "lsb", "bitmask", "type"]
123125
unamed_fields = [

0 commit comments

Comments
 (0)