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,46 +1,29 @@
from typing import TYPE_CHECKING
from systemrdl.node import AddressableNode
from ...utils import get_indexed_path
from ..base_cpuif import BaseCpuif
from .apb3_interface import APB3FlatInterface
if TYPE_CHECKING:
from ...exporter import BusDecoderExporter
class APB3CpuifFlat(BaseCpuif):
template_path = "apb3_tmpl.sv"
is_interface = False
def _port_declaration(self, child: AddressableNode) -> list[str]:
return [
f"input logic {self.signal('PCLK', child)}",
f"input logic {self.signal('PRESETn', child)}",
f"output logic {self.signal('PSELx', child)}",
f"output logic {self.signal('PENABLE', child)}",
f"output logic {self.signal('PWRITE', child)}",
f"output logic [{self.addr_width - 1}:0] {self.signal('PADDR', child)}",
f"output logic [{self.data_width - 1}:0] {self.signal('PWDATA', child)}",
f"input logic [{self.data_width - 1}:0] {self.signal('PRDATA', child)}",
f"input logic {self.signal('PREADY', child)}",
f"input logic {self.signal('PSLVERR', child)}",
]
def __init__(self, exp: "BusDecoderExporter") -> None:
super().__init__(exp)
self._interface = APB3FlatInterface(self)
@property
def is_interface(self) -> bool:
return self._interface.is_interface
@property
def port_declaration(self) -> str:
slave_ports: list[str] = [
f"input logic {self.signal('PCLK')}",
f"input logic {self.signal('PRESETn')}",
f"input logic {self.signal('PSELx')}",
f"input logic {self.signal('PENABLE')}",
f"input logic {self.signal('PWRITE')}",
f"input logic [{self.addr_width - 1}:0] {self.signal('PADDR')}",
f"input logic [{self.data_width - 1}:0] {self.signal('PWDATA')}",
f"output logic [{self.data_width - 1}:0] {self.signal('PRDATA')}",
f"output logic {self.signal('PREADY')}",
f"output logic {self.signal('PSLVERR')}",
]
master_ports: list[str] = []
for child in self.addressable_children:
master_ports.extend(self._port_declaration(child))
return ",\n".join(slave_ports + master_ports)
return self._interface.get_port_declaration("s_apb_", "m_apb_")
def signal(
self,
@@ -48,27 +31,11 @@ class APB3CpuifFlat(BaseCpuif):
node: AddressableNode | None = None,
idx: str | int | None = None,
) -> str:
mapped_signal = "PSELx" if signal == "PSEL" else signal
if node is None:
# Node is none, so this is a slave signal
return f"s_apb_{mapped_signal}"
# Master signal
base = f"m_apb_{node.inst_name}"
if not self.check_is_array(node):
# Not an array or an unrolled element
if node.current_idx is not None:
# This is a specific instance of an unrolled array
return f"{base}_{mapped_signal}_{'_'.join(map(str, node.current_idx))}"
return f"{base}_{mapped_signal}"
# Is an array
if idx is not None:
return f"{base}_{mapped_signal}[{idx}]"
return f"{base}_{mapped_signal}[N_{node.inst_name.upper()}S]"
return self._interface.signal(signal, node, idx)
def fanout(self, node: AddressableNode) -> str:
fanout: dict[str, str] = {}
fanout[self.signal("PSELx", node)] = (
fanout[self.signal("PSEL", node)] = (
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'i')}|cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node, 'i')}"
)
fanout[self.signal("PENABLE", node)] = self.signal("PENABLE")