Migrated from Pyrefly to ty (#33)
This commit is contained in:
4
.github/workflows/typecheck.yml
vendored
4
.github/workflows/typecheck.yml
vendored
@@ -22,5 +22,5 @@ jobs:
|
|||||||
- name: Install package
|
- name: Install package
|
||||||
run: uv sync --extra cli
|
run: uv sync --extra cli
|
||||||
|
|
||||||
- name: Run pyrefly type check
|
- name: Run ty type check
|
||||||
run: uvx pyrefly check src/
|
run: uvx ty check src/
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "peakrdl-busdecoder"
|
name = "peakrdl-busdecoder"
|
||||||
version = "0.6.4"
|
version = "0.6.5"
|
||||||
requires-python = ">=3.10"
|
requires-python = ">=3.10"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jinja2~=3.1",
|
"jinja2~=3.1",
|
||||||
@@ -65,7 +65,7 @@ test = [
|
|||||||
"cocotb>=1.8.0",
|
"cocotb>=1.8.0",
|
||||||
"cocotb-bus>=0.2.1",
|
"cocotb-bus>=0.2.1",
|
||||||
]
|
]
|
||||||
tools = ["pyrefly>=0.37.0", "ruff>=0.14.0"]
|
tools = ["ty>=0.0.7", "ruff>=0.14.0"]
|
||||||
|
|
||||||
[project.entry-points."peakrdl.exporters"]
|
[project.entry-points."peakrdl.exporters"]
|
||||||
busdecoder = "peakrdl_busdecoder.__peakrdl__:Exporter"
|
busdecoder = "peakrdl_busdecoder.__peakrdl__:Exporter"
|
||||||
@@ -100,15 +100,12 @@ ignore = [
|
|||||||
quote-style = "double"
|
quote-style = "double"
|
||||||
indent-style = "space"
|
indent-style = "space"
|
||||||
|
|
||||||
# ---------------------- PYREFLY ----------------------
|
# ---------------------- TY ----------------------
|
||||||
[tool.pyrefly]
|
[tool.ty.environment]
|
||||||
python-version = "3.10"
|
python-version = "3.10"
|
||||||
|
|
||||||
# Default behavior: check bodies of untyped defs & infer return types.
|
[tool.ty.src]
|
||||||
untyped-def-behavior = "check-and-infer-return-type"
|
include = ["src"]
|
||||||
|
|
||||||
project-includes = ["src/**/*"]
|
|
||||||
project-excludes = ["**/__pycache__", "**/*venv/**/*"]
|
|
||||||
|
|
||||||
# ---------------------- PYTEST ----------------------
|
# ---------------------- PYTEST ----------------------
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
@@ -69,7 +71,7 @@ class Exporter(ExporterSubcommandPlugin):
|
|||||||
def get_cpuifs(self) -> dict[str, type[BaseCpuif]]:
|
def get_cpuifs(self) -> dict[str, type[BaseCpuif]]:
|
||||||
return get_cpuifs(map(tuple, self.cfg["cpuifs"].items()))
|
return get_cpuifs(map(tuple, self.cfg["cpuifs"].items()))
|
||||||
|
|
||||||
def add_exporter_arguments(self, arg_group: "argparse.ArgumentParser") -> None: # type: ignore
|
def add_exporter_arguments(self, arg_group: argparse._ActionsContainer) -> None:
|
||||||
cpuifs = self.get_cpuifs()
|
cpuifs = self.get_cpuifs()
|
||||||
|
|
||||||
arg_group.add_argument(
|
arg_group.add_argument(
|
||||||
@@ -122,7 +124,7 @@ class Exporter(ExporterSubcommandPlugin):
|
|||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
|
||||||
def do_export(self, top_node: "AddrmapNode", options: "argparse.Namespace") -> None:
|
def do_export(self, top_node: AddrmapNode, options: argparse.Namespace) -> None:
|
||||||
cpuifs = self.get_cpuifs()
|
cpuifs = self.get_cpuifs()
|
||||||
|
|
||||||
x = BusDecoderExporter()
|
x = BusDecoderExporter()
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class APB3Cpuif(BaseCpuif):
|
|||||||
fanout[self.signal("PADDR", node, "gi")] = self.signal("PADDR")
|
fanout[self.signal("PADDR", node, "gi")] = self.signal("PADDR")
|
||||||
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
|
||||||
|
|
||||||
def fanin(self, node: AddressableNode | None = None) -> str:
|
def fanin(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -64,7 +64,7 @@ class APB3Cpuif(BaseCpuif):
|
|||||||
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
||||||
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|
||||||
def readback(self, node: AddressableNode | None = None) -> str:
|
def readback(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -80,7 +80,7 @@ class APB3Cpuif(BaseCpuif):
|
|||||||
else:
|
else:
|
||||||
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|
||||||
def fanin_intermediate_assignments(
|
def fanin_intermediate_assignments(
|
||||||
self, node: AddressableNode, inst_name: str, array_idx: str, master_prefix: str, indexed_path: str
|
self, node: AddressableNode, inst_name: str, array_idx: str, master_prefix: str, indexed_path: str
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class APB3CpuifFlat(BaseCpuif):
|
|||||||
fanout[self.signal("PADDR", node, "gi")] = f"{{{'-'.join(addr_comp)}}}[{clog2(node.size) - 1}:0]"
|
fanout[self.signal("PADDR", node, "gi")] = f"{{{'-'.join(addr_comp)}}}[{clog2(node.size) - 1}:0]"
|
||||||
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
|
||||||
|
|
||||||
def fanin(self, node: AddressableNode | None = None) -> str:
|
def fanin(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -62,7 +62,7 @@ class APB3CpuifFlat(BaseCpuif):
|
|||||||
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
||||||
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|
||||||
def readback(self, node: AddressableNode | None = None) -> str:
|
def readback(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -71,4 +71,4 @@ class APB3CpuifFlat(BaseCpuif):
|
|||||||
else:
|
else:
|
||||||
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class APB4Cpuif(BaseCpuif):
|
|||||||
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
|
||||||
|
|
||||||
def fanin(self, node: AddressableNode | None = None) -> str:
|
def fanin(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -67,7 +67,7 @@ class APB4Cpuif(BaseCpuif):
|
|||||||
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
||||||
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|
||||||
def readback(self, node: AddressableNode | None = None) -> str:
|
def readback(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -83,7 +83,7 @@ class APB4Cpuif(BaseCpuif):
|
|||||||
else:
|
else:
|
||||||
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|
||||||
def fanin_intermediate_assignments(
|
def fanin_intermediate_assignments(
|
||||||
self, node: AddressableNode, inst_name: str, array_idx: str, master_prefix: str, indexed_path: str
|
self, node: AddressableNode, inst_name: str, array_idx: str, master_prefix: str, indexed_path: str
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ class APB4CpuifFlat(BaseCpuif):
|
|||||||
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
|
||||||
|
|
||||||
def fanin(self, node: AddressableNode | None = None) -> str:
|
def fanin(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -64,7 +64,7 @@ class APB4CpuifFlat(BaseCpuif):
|
|||||||
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
|
||||||
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|
||||||
def readback(self, node: AddressableNode | None = None) -> str:
|
def readback(self, node: AddressableNode | None = None) -> str:
|
||||||
fanin: dict[str, str] = {}
|
fanin: dict[str, str] = {}
|
||||||
@@ -73,4 +73,4 @@ class APB4CpuifFlat(BaseCpuif):
|
|||||||
else:
|
else:
|
||||||
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"{kv[0]} = {kv[1]};", fanin.items()))
|
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
|
||||||
|
|||||||
@@ -82,15 +82,15 @@ class BaseCpuif:
|
|||||||
loader=loader,
|
loader=loader,
|
||||||
undefined=jj.StrictUndefined,
|
undefined=jj.StrictUndefined,
|
||||||
)
|
)
|
||||||
jj_env.tests["array"] = self.check_is_array # type: ignore
|
jj_env.tests["array"] = self.check_is_array
|
||||||
jj_env.filters["clog2"] = clog2 # type: ignore
|
jj_env.filters["clog2"] = clog2
|
||||||
jj_env.filters["is_pow2"] = is_pow2 # type: ignore
|
jj_env.filters["is_pow2"] = is_pow2
|
||||||
jj_env.filters["roundup_pow2"] = roundup_pow2 # type: ignore
|
jj_env.filters["roundup_pow2"] = roundup_pow2
|
||||||
jj_env.filters["address_slice"] = self.get_address_slice # type: ignore
|
jj_env.filters["address_slice"] = self.get_address_slice
|
||||||
jj_env.filters["get_path"] = lambda x: get_indexed_path(self.exp.ds.top_node, x, "i") # type: ignore
|
jj_env.filters["get_path"] = lambda x: get_indexed_path(self.exp.ds.top_node, x, "i")
|
||||||
jj_env.filters["walk"] = self.exp.walk # type: ignore
|
jj_env.filters["walk"] = self.exp.walk
|
||||||
|
|
||||||
context = { # type: ignore
|
context = {
|
||||||
"cpuif": self,
|
"cpuif": self,
|
||||||
"ds": self.exp.ds,
|
"ds": self.exp.ds,
|
||||||
"fanout": FanoutGenerator,
|
"fanout": FanoutGenerator,
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ class SVInterface(Interface):
|
|||||||
|
|
||||||
# When unrolled, current_idx is set - append it to the name
|
# When unrolled, current_idx is set - append it to the name
|
||||||
if child.current_idx is not None:
|
if child.current_idx is not None:
|
||||||
base = f"{base}_{'_'.join(map(str, child.current_idx))}"
|
base = f"{base}_{'_'.join(map(str, child.current_idx))}" # ty: ignore
|
||||||
|
|
||||||
# Only add array dimensions if this should be treated as an array
|
# Only add array dimensions if this should be treated as an array
|
||||||
if self.cpuif.check_is_array(child):
|
if self.cpuif.check_is_array(child):
|
||||||
|
|||||||
@@ -58,9 +58,9 @@ class BusDecoderExporter:
|
|||||||
loader=c_loader,
|
loader=c_loader,
|
||||||
undefined=jj.StrictUndefined,
|
undefined=jj.StrictUndefined,
|
||||||
)
|
)
|
||||||
self.jj_env.filters["kwf"] = kwf # type: ignore
|
self.jj_env.filters["kwf"] = kwf
|
||||||
self.jj_env.filters["walk"] = self.walk # type: ignore
|
self.jj_env.filters["walk"] = self.walk
|
||||||
self.jj_env.filters["clog2"] = clog2 # type: ignore
|
self.jj_env.filters["clog2"] = clog2
|
||||||
|
|
||||||
def export(self, node: RootNode | AddrmapNode, output_dir: str, **kwargs: Unpack[ExporterKwargs]) -> None:
|
def export(self, node: RootNode | AddrmapNode, output_dir: str, **kwargs: Unpack[ExporterKwargs]) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -98,7 +98,7 @@ class BusDecoderExporter:
|
|||||||
else:
|
else:
|
||||||
top_node = node
|
top_node = node
|
||||||
|
|
||||||
self.ds = DesignState(top_node, kwargs)
|
self.ds = DesignState(top_node, kwargs) # ty: ignore
|
||||||
|
|
||||||
cpuif_cls: type[BaseCpuif] = kwargs.pop("cpuif_cls", None) or APB4Cpuif
|
cpuif_cls: type[BaseCpuif] = kwargs.pop("cpuif_cls", None) or APB4Cpuif
|
||||||
|
|
||||||
@@ -113,7 +113,7 @@ class BusDecoderExporter:
|
|||||||
DesignValidator(self).do_validate()
|
DesignValidator(self).do_validate()
|
||||||
|
|
||||||
# Build Jinja template context
|
# Build Jinja template context
|
||||||
context = { # type: ignore
|
context = {
|
||||||
"version": version("peakrdl-busdecoder"),
|
"version": version("peakrdl-busdecoder"),
|
||||||
"cpuif": self.cpuif,
|
"cpuif": self.cpuif,
|
||||||
"cpuif_decode": DecodeLogicGenerator,
|
"cpuif_decode": DecodeLogicGenerator,
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ def ref_is_internal(top_node: AddrmapNode, ref: Node | PropertyReference) -> boo
|
|||||||
else:
|
else:
|
||||||
current_node = ref
|
current_node = ref
|
||||||
|
|
||||||
# pyrefly: ignore[bad-assignment] - false positive due to circular type checking
|
|
||||||
while current_node is not None:
|
while current_node is not None:
|
||||||
if current_node == top_node:
|
if current_node == top_node:
|
||||||
# reached top node without finding any external components
|
# reached top node without finding any external components
|
||||||
|
|||||||
@@ -74,7 +74,9 @@ class DesignValidator(RDLListener):
|
|||||||
f"instance '{node.inst_name}' must be a multiple of {alignment}",
|
f"instance '{node.inst_name}' must be a multiple of {alignment}",
|
||||||
node.inst.inst_src_ref,
|
node.inst.inst_src_ref,
|
||||||
)
|
)
|
||||||
if node.is_array and (node.array_stride % alignment) != 0: # type: ignore # is_array implies stride is not none
|
if node.is_array and (
|
||||||
|
node.array_stride is not None and (node.array_stride % alignment) != 0
|
||||||
|
): # is_array implies stride is not none
|
||||||
self.msg.error(
|
self.msg.error(
|
||||||
"Unaligned registers are not supported. Address stride of "
|
"Unaligned registers are not supported. Address stride of "
|
||||||
f"instance array '{node.inst_name}' must be a multiple of {alignment}",
|
f"instance array '{node.inst_name}' must be a multiple of {alignment}",
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ def prepare_cpuif_case(
|
|||||||
compiler = RDLCompiler()
|
compiler = RDLCompiler()
|
||||||
compiler.compile_file(rdl_source)
|
compiler.compile_file(rdl_source)
|
||||||
root = compiler.elaborate(top_name)
|
root = compiler.elaborate(top_name)
|
||||||
top_node = root.top # type: ignore[assignment]
|
top_node = root.top
|
||||||
|
|
||||||
export_kwargs: dict[str, Any] = {"cpuif_cls": cpuif_cls}
|
export_kwargs: dict[str, Any] = {"cpuif_cls": cpuif_cls}
|
||||||
if exporter_kwargs:
|
if exporter_kwargs:
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class TestDecodeLogicGenerator:
|
|||||||
|
|
||||||
# Basic sanity check - it should initialize
|
# Basic sanity check - it should initialize
|
||||||
assert gen is not None
|
assert gen is not None
|
||||||
assert gen._flavor == DecodeLogicFlavor.READ # type: ignore
|
assert gen._flavor == DecodeLogicFlavor.READ
|
||||||
|
|
||||||
def test_decode_logic_write(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
def test_decode_logic_write(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
||||||
"""Test decode logic generation for write operations."""
|
"""Test decode logic generation for write operations."""
|
||||||
@@ -48,7 +48,7 @@ class TestDecodeLogicGenerator:
|
|||||||
gen = DecodeLogicGenerator(ds, DecodeLogicFlavor.WRITE)
|
gen = DecodeLogicGenerator(ds, DecodeLogicFlavor.WRITE)
|
||||||
|
|
||||||
assert gen is not None
|
assert gen is not None
|
||||||
assert gen._flavor == DecodeLogicFlavor.WRITE # type: ignore
|
assert gen._flavor == DecodeLogicFlavor.WRITE
|
||||||
|
|
||||||
def test_cpuif_addr_predicate(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
def test_cpuif_addr_predicate(self, compile_rdl: Callable[..., AddrmapNode]) -> None:
|
||||||
"""Test address predicate generation."""
|
"""Test address predicate generation."""
|
||||||
|
|||||||
Reference in New Issue
Block a user