"updt"
This commit is contained in:
79
src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py
Normal file
79
src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py
Normal file
@@ -0,0 +1,79 @@
|
||||
from systemrdl.node import AddressableNode
|
||||
from ..base_cpuif import BaseCpuif
|
||||
|
||||
|
||||
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}"
|
||||
if not child.is_array:
|
||||
return base
|
||||
if child.current_idx is not None:
|
||||
return f"{base}_{'_'.join(map(str, child.current_idx))} [N_{child.inst_name.upper()}S]"
|
||||
return f"{base} [N_{child.inst_name.upper()}S]"
|
||||
|
||||
@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)
|
||||
|
||||
def signal(
|
||||
self,
|
||||
signal: str,
|
||||
node: AddressableNode | None = None,
|
||||
idx: str | int | None = None,
|
||||
) -> str:
|
||||
if node is None:
|
||||
# Node is none, so this is a slave signal
|
||||
return f"s_apb.{signal}"
|
||||
|
||||
# Master signal
|
||||
base = f"m_apb_{node.inst_name}"
|
||||
if not node.is_array:
|
||||
return f"{base}.{signal}"
|
||||
if node.current_idx is not None:
|
||||
# This is a specific instance of an array
|
||||
return f"{base}_{'_'.join(map(str, node.current_idx))}.{signal}"
|
||||
if idx is not None:
|
||||
return f"{base}[{idx}].{signal}"
|
||||
|
||||
raise ValueError("Must provide an index for arrayed interface signals")
|
||||
|
||||
def get_address_predicate(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that evaluates to true when the
|
||||
address on the bus matches the address range of the given node.
|
||||
"""
|
||||
|
||||
addr_mask = (1 << self.addr_width) - 1
|
||||
addr = node.absolute_address & addr_mask
|
||||
size = node.size
|
||||
if size == 0:
|
||||
raise ValueError("Node size must be greater than 0")
|
||||
if (addr % size) != 0:
|
||||
raise ValueError("Node address must be aligned to its size")
|
||||
|
||||
# Calculate the address range of the node
|
||||
addr_start = addr
|
||||
addr_end = addr + size - 1
|
||||
if addr_end > addr_mask:
|
||||
raise ValueError("Node address range exceeds address width")
|
||||
|
||||
if addr_start == addr_end:
|
||||
return f"({self.signal('PADDR')} == 'h{addr_start:X})"
|
||||
|
||||
return f"({self.signal('PADDR')} >= 'h{addr_start:X} && {self.signal('PADDR')} <= 'h{addr_end:X})"
|
||||
|
||||
def get_address_decode_condition(self, node: AddressableNode) -> str:
|
||||
"""
|
||||
Returns a SystemVerilog expression that evaluates to true when the
|
||||
address on the bus matches the address range of the given node.
|
||||
"""
|
||||
addr_pred = self.get_address_predicate(node)
|
||||
return addr_pred
|
||||
Reference in New Issue
Block a user