Refactor cpuif classes to use Interface abstraction (#14)

* Initial plan

* Refactor cpuif classes to use Interface abstraction

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Fix type annotation consistency in Interface.signal()

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Add runtime validation and documentation for indexer types

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Remove unused variable in SVInterface.signal()

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Fix master port directions in APB3 and APB4 flat interfaces

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* Fix AXI4LiteCpuifFlat and apply code formatting

Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>

* PSELx -> PSEL

* cleanup marker warnings

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>
This commit is contained in:
Copilot
2025-10-26 18:47:11 -07:00
committed by GitHub
parent 1eababe1ab
commit 95fda3abaa
14 changed files with 539 additions and 258 deletions

View File

@@ -1,47 +1,36 @@
from typing import overload
from typing import TYPE_CHECKING, overload
from systemrdl.node import AddressableNode
from ...utils import get_indexed_path
from ..base_cpuif import BaseCpuif
from .apb3_interface import APB3SVInterface
if TYPE_CHECKING:
from ...exporter import BusDecoderExporter
class APB3Cpuif(BaseCpuif):
template_path = "apb3_tmpl.sv"
is_interface = True
def _port_declaration(self, child: AddressableNode) -> str:
base = f"apb3_intf.master m_apb_{child.inst_name}"
def __init__(self, exp: "BusDecoderExporter") -> None:
super().__init__(exp)
self._interface = APB3SVInterface(self)
# When unrolled, current_idx is set - append it to the name
if child.current_idx is not None:
base = f"{base}_{'_'.join(map(str, child.current_idx))}"
# Only add array dimensions if this should be treated as an array
if self.check_is_array(child):
assert child.array_dimensions is not None
return f"{base} {''.join(f'[{dim}]' for dim in child.array_dimensions)}"
return base
@property
def is_interface(self) -> bool:
return self._interface.is_interface
@property
def port_declaration(self) -> str:
slave_ports: list[str] = ["apb3_intf.slave s_apb"]
master_ports: list[str] = list(map(self._port_declaration, self.addressable_children))
return ",\n".join(slave_ports + master_ports)
return self._interface.get_port_declaration("s_apb", "m_apb_")
@overload
def signal(self, signal: str, node: None = None, indexer: None = None) -> str: ...
@overload
def signal(self, signal: str, node: AddressableNode, indexer: str) -> str: ...
def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str:
if node is None or indexer is None:
# Node is none, so this is a slave signal
return f"s_apb.{signal}"
# Master signal
return f"m_apb_{get_indexed_path(node.parent, node, indexer, skip_kw_filter=True)}.{signal}"
return self._interface.signal(signal, node, indexer)
def fanout(self, node: AddressableNode) -> str:
fanout: dict[str, str] = {}