Files
PeakRDL-BusDecoder/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py
Copilot 1e09da6dbf Fix APB PREADY not asserted on invalid address decode errors (#40)
Fix APB PREADY signal to assert during error conditions

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: arnavsacheti <36746504+arnavsacheti@users.noreply.github.com>
2026-02-02 23:34:09 -08:00

86 lines
3.3 KiB
Python

from collections import deque
from typing import TYPE_CHECKING
from systemrdl.node import AddressableNode
from ...sv_int import SVInt
from ...utils import clog2, get_indexed_path
from ..base_cpuif import BaseCpuif
from .apb4_interface import APB4FlatInterface
if TYPE_CHECKING:
from ...exporter import BusDecoderExporter
class APB4CpuifFlat(BaseCpuif):
template_path = "apb4_tmpl.sv"
def __init__(self, exp: "BusDecoderExporter") -> None:
super().__init__(exp)
self._interface = APB4FlatInterface(self)
@property
def is_interface(self) -> bool:
return self._interface.is_interface
@property
def port_declaration(self) -> str:
return self._interface.get_port_declaration("s_apb_", "m_apb_")
def signal(
self,
signal: str,
node: AddressableNode | None = None,
idx: str | int | None = None,
) -> str:
return self._interface.signal(signal, node, idx)
def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str:
fanout: dict[str, str] = {}
addr_comp = [f"{self.signal('PADDR')}"]
for i, stride in enumerate(array_stack):
addr_comp.append(f"(gi{i}*{SVInt(stride, self.addr_width)})")
fanout[self.signal("PSEL", node, "gi")] = (
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}|cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
)
fanout[self.signal("PENABLE", node, "gi")] = self.signal("PENABLE")
fanout[self.signal("PWRITE", node, "gi")] = (
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
)
fanout[self.signal("PADDR", node, "gi")] = f"{{{'-'.join(addr_comp)}}}[{clog2(node.size) - 1}:0]"
fanout[self.signal("PPROT", node, "gi")] = self.signal("PPROT")
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
fanin: dict[str, str] = {}
if node is None:
fanin["cpuif_wr_ack"] = "'0"
fanin["cpuif_wr_err"] = "'0"
if error:
fanin["cpuif_wr_ack"] = "'1"
fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
else:
fanin["cpuif_wr_ack"] = self.signal("PREADY", node, "i")
fanin["cpuif_wr_err"] = self.signal("PSLVERR", node, "i")
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
fanin: dict[str, str] = {}
if node is None:
fanin["cpuif_rd_ack"] = "'0"
fanin["cpuif_rd_err"] = "'0"
fanin["cpuif_rd_data"] = "'0"
if error:
fanin["cpuif_rd_ack"] = "'1"
fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
else:
fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())