From c63b2cbab256aeb5184fd576373f62863c27e791 Mon Sep 17 00:00:00 2001 From: Arnav Sacheti <36746504+arnavsacheti@users.noreply.github.com> Date: Thu, 4 Dec 2025 21:31:44 -0800 Subject: [PATCH] Dev/downsize apb paddr (#27) * Downsize paddr bits * Updated Test suite to use offset aligned address * fix for apb3 and axi4lite * modified structure to pass hierarchy information --------- Co-authored-by: Byron Lathi --- src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py | 3 ++- .../cpuif/apb3/apb3_cpuif_flat.py | 12 +++++++++--- .../cpuif/apb3/apb3_interface.py | 3 ++- src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py | 3 ++- .../cpuif/apb4/apb4_cpuif_flat.py | 12 +++++++++--- .../cpuif/apb4/apb4_interface.py | 3 ++- .../cpuif/axi4lite/axi4_lite_cpuif.py | 3 ++- .../cpuif/axi4lite/axi4_lite_cpuif_flat.py | 16 ++++++++++++---- .../cpuif/axi4lite/axi4_lite_interface.py | 5 +++-- src/peakrdl_busdecoder/cpuif/base_cpuif.py | 3 ++- src/peakrdl_busdecoder/cpuif/fanout_gen.py | 2 +- tests/cocotb/apb3/smoke/test_register_access.py | 11 +++++++++-- tests/cocotb/apb4/smoke/test_register_access.py | 12 ++++++++++-- tests/cocotb/apb4/smoke/test_runner.py | 6 +++++- .../axi4lite/smoke/test_register_access.py | 15 +++++++++++++-- tests/cocotb_lib/utils.py | 6 ++++++ 16 files changed, 89 insertions(+), 26 deletions(-) diff --git a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py index b074795..fb3c16d 100644 --- a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py @@ -1,3 +1,4 @@ +from collections import deque from typing import TYPE_CHECKING, overload from systemrdl.node import AddressableNode @@ -32,7 +33,7 @@ class APB3Cpuif(BaseCpuif): def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str: return self._interface.signal(signal, node, indexer) - def fanout(self, node: AddressableNode) -> str: + def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str: fanout: dict[str, str] = {} 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')}" diff --git a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py index 944d2ad..01f3518 100644 --- a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py +++ b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py @@ -1,8 +1,10 @@ +from collections import deque from typing import TYPE_CHECKING from systemrdl.node import AddressableNode -from ...utils import get_indexed_path +from ...sv_int import SVInt +from ...utils import clog2, get_indexed_path from ..base_cpuif import BaseCpuif from .apb3_interface import APB3FlatInterface @@ -33,8 +35,12 @@ class APB3CpuifFlat(BaseCpuif): ) -> str: return self._interface.signal(signal, node, idx) - def fanout(self, node: AddressableNode) -> str: + 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')}" ) @@ -42,7 +48,7 @@ class APB3CpuifFlat(BaseCpuif): 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")] = self.signal("PADDR") + fanout[self.signal("PADDR", node, "gi")] = f"{{{'-'.join(addr_comp)}}}[{clog2(node.size) - 1}:0]" fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data" return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items())) diff --git a/src/peakrdl_busdecoder/cpuif/apb3/apb3_interface.py b/src/peakrdl_busdecoder/cpuif/apb3/apb3_interface.py index 04badae..698559f 100644 --- a/src/peakrdl_busdecoder/cpuif/apb3/apb3_interface.py +++ b/src/peakrdl_busdecoder/cpuif/apb3/apb3_interface.py @@ -2,6 +2,7 @@ from systemrdl.node import AddressableNode +from ...utils import clog2 from ..interface import FlatInterface, SVInterface @@ -48,7 +49,7 @@ class APB3FlatInterface(FlatInterface): f"output logic {self.signal('PSEL', child)}", f"output logic {self.signal('PENABLE', child)}", f"output logic {self.signal('PWRITE', child)}", - f"output logic [{self.cpuif.addr_width - 1}:0] {self.signal('PADDR', child)}", + f"output logic [{clog2(child.size) - 1}:0] {self.signal('PADDR', child)}", f"output logic [{self.cpuif.data_width - 1}:0] {self.signal('PWDATA', child)}", f"input logic [{self.cpuif.data_width - 1}:0] {self.signal('PRDATA', child)}", f"input logic {self.signal('PREADY', child)}", diff --git a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py index f2e1c98..5c85db1 100644 --- a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py @@ -1,3 +1,4 @@ +from collections import deque from typing import TYPE_CHECKING, overload from systemrdl.node import AddressableNode @@ -33,7 +34,7 @@ class APB4Cpuif(BaseCpuif): def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str: return self._interface.signal(signal, node, indexer) - def fanout(self, node: AddressableNode) -> str: + def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str: fanout: dict[str, str] = {} 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')}" diff --git a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py index 17ec392..ea9cf18 100644 --- a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py +++ b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py @@ -1,8 +1,10 @@ +from collections import deque from typing import TYPE_CHECKING from systemrdl.node import AddressableNode -from ...utils import get_indexed_path +from ...sv_int import SVInt +from ...utils import clog2, get_indexed_path from ..base_cpuif import BaseCpuif from .apb4_interface import APB4FlatInterface @@ -33,8 +35,12 @@ class APB4CpuifFlat(BaseCpuif): ) -> str: return self._interface.signal(signal, node, idx) - def fanout(self, node: AddressableNode) -> str: + 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')}" ) @@ -42,7 +48,7 @@ class APB4CpuifFlat(BaseCpuif): 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")] = self.signal("PADDR") + 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" diff --git a/src/peakrdl_busdecoder/cpuif/apb4/apb4_interface.py b/src/peakrdl_busdecoder/cpuif/apb4/apb4_interface.py index be87240..3ad19fb 100644 --- a/src/peakrdl_busdecoder/cpuif/apb4/apb4_interface.py +++ b/src/peakrdl_busdecoder/cpuif/apb4/apb4_interface.py @@ -2,6 +2,7 @@ from systemrdl.node import AddressableNode +from ...utils import clog2 from ..interface import FlatInterface, SVInterface @@ -50,7 +51,7 @@ class APB4FlatInterface(FlatInterface): f"output logic {self.signal('PSEL', child)}", f"output logic {self.signal('PENABLE', child)}", f"output logic {self.signal('PWRITE', child)}", - f"output logic [{self.cpuif.addr_width - 1}:0] {self.signal('PADDR', child)}", + f"output logic [{clog2(child.size) - 1}:0] {self.signal('PADDR', child)}", f"output logic [2:0] {self.signal('PPROT', child)}", f"output logic [{self.cpuif.data_width - 1}:0] {self.signal('PWDATA', child)}", f"output logic [{self.cpuif.data_width // 8 - 1}:0] {self.signal('PSTRB', child)}", diff --git a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py index b49677d..12b7205 100644 --- a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py @@ -1,3 +1,4 @@ +from collections import deque from typing import TYPE_CHECKING, overload from systemrdl.node import AddressableNode @@ -33,7 +34,7 @@ class AXI4LiteCpuif(BaseCpuif): def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str: return self._interface.signal(signal, node, indexer) - def fanout(self, node: AddressableNode) -> str: + def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str: fanout: dict[str, str] = {} wr_sel = f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}" diff --git a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py index 2322c3d..be54571 100644 --- a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py +++ b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py @@ -1,8 +1,10 @@ +from collections import deque from typing import TYPE_CHECKING, overload from systemrdl.node import AddressableNode -from ...utils import get_indexed_path +from ...sv_int import SVInt +from ...utils import clog2, get_indexed_path from ..base_cpuif import BaseCpuif from .axi4_lite_interface import AXI4LiteFlatInterface @@ -35,15 +37,21 @@ class AXI4LiteCpuifFlat(BaseCpuif): def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str: return self._interface.signal(signal, node, indexer) - def fanout(self, node: AddressableNode) -> str: + def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str: fanout: dict[str, str] = {} + waddr_comp = [f"{self.signal('AWADDR')}"] + raddr_comp = [f"{self.signal('ARADDR')}"] + for i, stride in enumerate(array_stack): + offset = f"(gi{i}*{SVInt(stride, self.addr_width)})" + waddr_comp.append(offset) + raddr_comp.append(offset) wr_sel = f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}" rd_sel = f"cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}" # Write address channel fanout[self.signal("AWVALID", node, "gi")] = wr_sel - fanout[self.signal("AWADDR", node, "gi")] = self.signal("AWADDR") + fanout[self.signal("AWADDR", node, "gi")] = f"{{{'-'.join(waddr_comp)}}}[{clog2(node.size) - 1}:0]" fanout[self.signal("AWPROT", node, "gi")] = self.signal("AWPROT") # Write data channel @@ -56,7 +64,7 @@ class AXI4LiteCpuifFlat(BaseCpuif): # Read address channel fanout[self.signal("ARVALID", node, "gi")] = rd_sel - fanout[self.signal("ARADDR", node, "gi")] = self.signal("ARADDR") + fanout[self.signal("ARADDR", node, "gi")] = f"{{{'-'.join(raddr_comp)}}}[{clog2(node.size) - 1}:0]" fanout[self.signal("ARPROT", node, "gi")] = self.signal("ARPROT") # Read data channel (master -> slave) diff --git a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_interface.py b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_interface.py index 70a65bb..bf63ccc 100644 --- a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_interface.py +++ b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_interface.py @@ -2,6 +2,7 @@ from systemrdl.node import AddressableNode +from ...utils import clog2 from ..interface import FlatInterface, SVInterface @@ -60,7 +61,7 @@ class AXI4LiteFlatInterface(FlatInterface): # Write address channel f"output logic {self.signal('AWVALID', child)}", f"input logic {self.signal('AWREADY', child)}", - f"output logic [{self.cpuif.addr_width - 1}:0] {self.signal('AWADDR', child)}", + f"output logic [{clog2(child.size) - 1}:0] {self.signal('AWADDR', child)}", f"output logic [2:0] {self.signal('AWPROT', child)}", # Write data channel f"output logic {self.signal('WVALID', child)}", @@ -74,7 +75,7 @@ class AXI4LiteFlatInterface(FlatInterface): # Read address channel f"output logic {self.signal('ARVALID', child)}", f"input logic {self.signal('ARREADY', child)}", - f"output logic [{self.cpuif.addr_width - 1}:0] {self.signal('ARADDR', child)}", + f"output logic [{clog2(child.size) - 1}:0] {self.signal('ARADDR', child)}", f"output logic [2:0] {self.signal('ARPROT', child)}", # Read data channel f"input logic {self.signal('RVALID', child)}", diff --git a/src/peakrdl_busdecoder/cpuif/base_cpuif.py b/src/peakrdl_busdecoder/cpuif/base_cpuif.py index 519d83a..8b28d9a 100644 --- a/src/peakrdl_busdecoder/cpuif/base_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/base_cpuif.py @@ -1,5 +1,6 @@ import inspect import os +from collections import deque from typing import TYPE_CHECKING import jinja2 as jj @@ -106,7 +107,7 @@ class BaseCpuif: return f"({cpuif_addr} - 'h{addr:x})[{clog2(size) - 1}:0]" - def fanout(self, node: AddressableNode) -> str: + def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str: raise NotImplementedError def fanin(self, node: AddressableNode | None = None) -> str: diff --git a/src/peakrdl_busdecoder/cpuif/fanout_gen.py b/src/peakrdl_busdecoder/cpuif/fanout_gen.py index abb513f..bce0753 100644 --- a/src/peakrdl_busdecoder/cpuif/fanout_gen.py +++ b/src/peakrdl_busdecoder/cpuif/fanout_gen.py @@ -43,7 +43,7 @@ class FanoutGenerator(BusDecoderListener): ) self._stack.append(fb) - self._stack[-1] += self._cpuif.fanout(node) + self._stack[-1] += self._cpuif.fanout(node, self._array_stride_stack) return action diff --git a/tests/cocotb/apb3/smoke/test_register_access.py b/tests/cocotb/apb3/smoke/test_register_access.py index 4b2eae1..b821131 100644 --- a/tests/cocotb/apb3/smoke/test_register_access.py +++ b/tests/cocotb/apb3/smoke/test_register_access.py @@ -64,6 +64,8 @@ def _build_master_table(dut, masters_cfg: list[dict[str, Any]]) -> dict[str, dic "PREADY": SignalHandle(dut, f"{prefix}_PREADY"), "PSLVERR": SignalHandle(dut, f"{prefix}_PSLVERR"), }, + "inst_size": master["inst_size"], + "inst_address": master["inst_address"], } table[master["inst_name"]] = entry return table @@ -125,11 +127,16 @@ async def test_apb3_address_decoding(dut) -> None: slave.PSEL.value = 1 slave.PENABLE.value = 1 + dut._log.info( + f"Starting transaction {txn['label']} to {master_name}{index} at address 0x{address:08X}" + ) + master_address = (address - entry["inst_address"]) % entry["inst_size"] + await Timer(1, units="ns") assert _get_int(entry["outputs"]["PSEL"], index) == 1, f"{master_name} should assert PSEL for write" assert _get_int(entry["outputs"]["PWRITE"], index) == 1, f"{master_name} should see write direction" - assert _get_int(entry["outputs"]["PADDR"], index) == address, ( + assert _get_int(entry["outputs"]["PADDR"], index) == master_address, ( f"{master_name} must receive write address" ) assert _get_int(entry["outputs"]["PWDATA"], index) == write_data, ( @@ -172,7 +179,7 @@ async def test_apb3_address_decoding(dut) -> None: assert _get_int(entry["outputs"]["PWRITE"], index) == 0, ( f"{master_name} should clear write during read" ) - assert _get_int(entry["outputs"]["PADDR"], index) == address, ( + assert _get_int(entry["outputs"]["PADDR"], index) == master_address, ( f"{master_name} must receive read address" ) diff --git a/tests/cocotb/apb4/smoke/test_register_access.py b/tests/cocotb/apb4/smoke/test_register_access.py index cbf1b12..bec958e 100644 --- a/tests/cocotb/apb4/smoke/test_register_access.py +++ b/tests/cocotb/apb4/smoke/test_register_access.py @@ -3,6 +3,7 @@ from __future__ import annotations import json +import logging import os from typing import Any, Iterable @@ -71,6 +72,8 @@ def _build_master_table(dut, masters_cfg: list[dict[str, Any]]) -> dict[str, dic "PREADY": SignalHandle(dut, f"{port_prefix}_PREADY"), "PSLVERR": SignalHandle(dut, f"{port_prefix}_PSLVERR"), }, + "inst_size": master["inst_size"], + "inst_address": master["inst_address"], } table[master["inst_name"]] = entry return table @@ -138,11 +141,16 @@ async def test_apb4_address_decoding(dut) -> None: slave.PSEL.value = 1 slave.PENABLE.value = 1 + dut._log.info( + f"Starting transaction {txn['label']} to {master_name}{index} at address 0x{address:08X}" + ) + master_address = (address - entry["inst_address"]) % entry["inst_size"] + await Timer(1, units="ns") assert _get_int(entry["outputs"]["PSEL"], index) == 1, f"{master_name} should assert PSEL for write" assert _get_int(entry["outputs"]["PWRITE"], index) == 1, f"{master_name} should see write intent" - assert _get_int(entry["outputs"]["PADDR"], index) == address, ( + assert _get_int(entry["outputs"]["PADDR"], index) == master_address, ( f"{master_name} must receive write address" ) assert _get_int(entry["outputs"]["PWDATA"], index) == write_data, ( @@ -189,7 +197,7 @@ async def test_apb4_address_decoding(dut) -> None: assert _get_int(entry["outputs"]["PWRITE"], index) == 0, ( f"{master_name} should deassert write for reads" ) - assert _get_int(entry["outputs"]["PADDR"], index) == address, ( + assert _get_int(entry["outputs"]["PADDR"], index) == master_address, ( f"{master_name} must receive read address" ) diff --git a/tests/cocotb/apb4/smoke/test_runner.py b/tests/cocotb/apb4/smoke/test_runner.py index 4aef4cc..1428ac5 100644 --- a/tests/cocotb/apb4/smoke/test_runner.py +++ b/tests/cocotb/apb4/smoke/test_runner.py @@ -3,6 +3,7 @@ from __future__ import annotations import json +import logging from pathlib import Path import logging @@ -28,6 +29,9 @@ def test_apb4_smoke(tmp_path: Path, rdl_file: str, top_name: str) -> None: rdl_path = repo_root / "tests" / "cocotb_lib" / "rdl" / rdl_file build_root = tmp_path / top_name + logging.info(f"Running APB4 smoke test for {rdl_path} with top {top_name}") + logging.info(f"Build root: {build_root}") + module_path, package_path, config = prepare_cpuif_case( str(rdl_path), top_name, @@ -83,4 +87,4 @@ def test_apb4_smoke(tmp_path: Path, rdl_file: str, top_name: str) -> None: === End Simulation Log === """) if e.code != 0: - raise + raise e diff --git a/tests/cocotb/axi4lite/smoke/test_register_access.py b/tests/cocotb/axi4lite/smoke/test_register_access.py index e23ff17..ab09a87 100644 --- a/tests/cocotb/axi4lite/smoke/test_register_access.py +++ b/tests/cocotb/axi4lite/smoke/test_register_access.py @@ -84,6 +84,8 @@ def _build_master_table(dut, masters_cfg: list[dict[str, Any]]) -> dict[str, dic "RDATA": SignalHandle(dut, f"{prefix}_RDATA"), "RRESP": SignalHandle(dut, f"{prefix}_RRESP"), }, + "inst_size": master["inst_size"], + "inst_address": master["inst_address"], } table[master["inst_name"]] = entry return table @@ -156,10 +158,17 @@ async def test_axi4lite_address_decoding(dut) -> None: slave.WVALID.value = 1 slave.BREADY.value = 1 + dut._log.info( + f"Starting transaction {txn['label']} to {master_name}{index} at address 0x{address:08X}" + ) + master_address = (address - entry["inst_address"]) % entry["inst_size"] + await Timer(1, units="ns") assert _get_int(entry["outputs"]["AWVALID"], index) == 1, f"{master_name} should see AWVALID asserted" - assert _get_int(entry["outputs"]["AWADDR"], index) == address, f"{master_name} must receive AWADDR" + assert _get_int(entry["outputs"]["AWADDR"], index) == master_address, ( + f"{master_name} must receive AWADDR" + ) assert _get_int(entry["outputs"]["WVALID"], index) == 1, f"{master_name} should see WVALID asserted" assert _get_int(entry["outputs"]["WDATA"], index) == write_data, f"{master_name} must receive WDATA" assert _get_int(entry["outputs"]["WSTRB"], index) == strobe_mask, f"{master_name} must receive WSTRB" @@ -193,7 +202,9 @@ async def test_axi4lite_address_decoding(dut) -> None: await Timer(1, units="ns") assert _get_int(entry["outputs"]["ARVALID"], index) == 1, f"{master_name} should assert ARVALID" - assert _get_int(entry["outputs"]["ARADDR"], index) == address, f"{master_name} must receive ARADDR" + assert _get_int(entry["outputs"]["ARADDR"], index) == master_address, ( + f"{master_name} must receive ARADDR" + ) for other_name, other_idx in _all_index_pairs(masters): if other_name == master_name and other_idx == index: diff --git a/tests/cocotb_lib/utils.py b/tests/cocotb_lib/utils.py index 14381f4..abf491e 100644 --- a/tests/cocotb_lib/utils.py +++ b/tests/cocotb_lib/utils.py @@ -223,6 +223,8 @@ def _build_case_config( "is_array": bool(child.is_array), "dimensions": list(child.array_dimensions or []), "indices": set(), + "inst_size": child.array_stride if child.is_array else child.size, + "inst_address": child.raw_absolute_address, } # Map each register to its top-level master and collect addresses @@ -252,6 +254,8 @@ def _build_case_config( "is_array": bool(master.is_array), "dimensions": list(master.array_dimensions or []), "indices": set(), + "inst_size": master.array_stride if master.is_array else master.size, + "inst_address": master.raw_absolute_address, } idx_tuple = tuple(master.current_idx or []) @@ -279,6 +283,8 @@ def _build_case_config( "is_array": entry["is_array"], "dimensions": entry["dimensions"], "indices": entry["indices"], + "inst_size": entry["inst_size"], + "inst_address": entry["inst_address"], } )