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 <bslathi19@gmail.com>
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING, overload
|
from typing import TYPE_CHECKING, overload
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
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:
|
def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str:
|
||||||
return self._interface.signal(signal, node, indexer)
|
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: dict[str, str] = {}
|
||||||
fanout[self.signal("PSEL", node, "gi")] = (
|
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')}"
|
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')}"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
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 ..base_cpuif import BaseCpuif
|
||||||
from .apb3_interface import APB3FlatInterface
|
from .apb3_interface import APB3FlatInterface
|
||||||
|
|
||||||
@@ -33,8 +35,12 @@ class APB3CpuifFlat(BaseCpuif):
|
|||||||
) -> str:
|
) -> str:
|
||||||
return self._interface.signal(signal, node, idx)
|
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] = {}
|
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")] = (
|
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')}"
|
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")] = (
|
fanout[self.signal("PWRITE", node, "gi")] = (
|
||||||
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, 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"
|
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
|
|
||||||
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
return "\n".join(map(lambda kv: f"assign {kv[0]} = {kv[1]};", fanout.items()))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
|
from ...utils import clog2
|
||||||
from ..interface import FlatInterface, SVInterface
|
from ..interface import FlatInterface, SVInterface
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ class APB3FlatInterface(FlatInterface):
|
|||||||
f"output logic {self.signal('PSEL', child)}",
|
f"output logic {self.signal('PSEL', child)}",
|
||||||
f"output logic {self.signal('PENABLE', child)}",
|
f"output logic {self.signal('PENABLE', child)}",
|
||||||
f"output logic {self.signal('PWRITE', 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"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.cpuif.data_width - 1}:0] {self.signal('PRDATA', child)}",
|
||||||
f"input logic {self.signal('PREADY', child)}",
|
f"input logic {self.signal('PREADY', child)}",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING, overload
|
from typing import TYPE_CHECKING, overload
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
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:
|
def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str:
|
||||||
return self._interface.signal(signal, node, indexer)
|
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: dict[str, str] = {}
|
||||||
fanout[self.signal("PSEL", node, "gi")] = (
|
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')}"
|
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')}"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
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 ..base_cpuif import BaseCpuif
|
||||||
from .apb4_interface import APB4FlatInterface
|
from .apb4_interface import APB4FlatInterface
|
||||||
|
|
||||||
@@ -33,8 +35,12 @@ class APB4CpuifFlat(BaseCpuif):
|
|||||||
) -> str:
|
) -> str:
|
||||||
return self._interface.signal(signal, node, idx)
|
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] = {}
|
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")] = (
|
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')}"
|
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")] = (
|
fanout[self.signal("PWRITE", node, "gi")] = (
|
||||||
f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, 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("PPROT", node, "gi")] = self.signal("PPROT")
|
||||||
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
fanout[self.signal("PWDATA", node, "gi")] = "cpuif_wr_data"
|
||||||
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
fanout[self.signal("PSTRB", node, "gi")] = "cpuif_wr_byte_en"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
|
from ...utils import clog2
|
||||||
from ..interface import FlatInterface, SVInterface
|
from ..interface import FlatInterface, SVInterface
|
||||||
|
|
||||||
|
|
||||||
@@ -50,7 +51,7 @@ class APB4FlatInterface(FlatInterface):
|
|||||||
f"output logic {self.signal('PSEL', child)}",
|
f"output logic {self.signal('PSEL', child)}",
|
||||||
f"output logic {self.signal('PENABLE', child)}",
|
f"output logic {self.signal('PENABLE', child)}",
|
||||||
f"output logic {self.signal('PWRITE', 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 [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 - 1}:0] {self.signal('PWDATA', child)}",
|
||||||
f"output logic [{self.cpuif.data_width // 8 - 1}:0] {self.signal('PSTRB', child)}",
|
f"output logic [{self.cpuif.data_width // 8 - 1}:0] {self.signal('PSTRB', child)}",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING, overload
|
from typing import TYPE_CHECKING, overload
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
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:
|
def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str:
|
||||||
return self._interface.signal(signal, node, indexer)
|
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: dict[str, str] = {}
|
||||||
|
|
||||||
wr_sel = f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
|
wr_sel = f"cpuif_wr_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING, overload
|
from typing import TYPE_CHECKING, overload
|
||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
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 ..base_cpuif import BaseCpuif
|
||||||
from .axi4_lite_interface import AXI4LiteFlatInterface
|
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:
|
def signal(self, signal: str, node: AddressableNode | None = None, indexer: str | None = None) -> str:
|
||||||
return self._interface.signal(signal, node, indexer)
|
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: 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')}"
|
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')}"
|
rd_sel = f"cpuif_rd_sel.{get_indexed_path(self.exp.ds.top_node, node, 'gi')}"
|
||||||
|
|
||||||
# Write address channel
|
# Write address channel
|
||||||
fanout[self.signal("AWVALID", node, "gi")] = wr_sel
|
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")
|
fanout[self.signal("AWPROT", node, "gi")] = self.signal("AWPROT")
|
||||||
|
|
||||||
# Write data channel
|
# Write data channel
|
||||||
@@ -56,7 +64,7 @@ class AXI4LiteCpuifFlat(BaseCpuif):
|
|||||||
|
|
||||||
# Read address channel
|
# Read address channel
|
||||||
fanout[self.signal("ARVALID", node, "gi")] = rd_sel
|
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")
|
fanout[self.signal("ARPROT", node, "gi")] = self.signal("ARPROT")
|
||||||
|
|
||||||
# Read data channel (master -> slave)
|
# Read data channel (master -> slave)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from systemrdl.node import AddressableNode
|
from systemrdl.node import AddressableNode
|
||||||
|
|
||||||
|
from ...utils import clog2
|
||||||
from ..interface import FlatInterface, SVInterface
|
from ..interface import FlatInterface, SVInterface
|
||||||
|
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ class AXI4LiteFlatInterface(FlatInterface):
|
|||||||
# Write address channel
|
# Write address channel
|
||||||
f"output logic {self.signal('AWVALID', child)}",
|
f"output logic {self.signal('AWVALID', child)}",
|
||||||
f"input logic {self.signal('AWREADY', 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)}",
|
f"output logic [2:0] {self.signal('AWPROT', child)}",
|
||||||
# Write data channel
|
# Write data channel
|
||||||
f"output logic {self.signal('WVALID', child)}",
|
f"output logic {self.signal('WVALID', child)}",
|
||||||
@@ -74,7 +75,7 @@ class AXI4LiteFlatInterface(FlatInterface):
|
|||||||
# Read address channel
|
# Read address channel
|
||||||
f"output logic {self.signal('ARVALID', child)}",
|
f"output logic {self.signal('ARVALID', child)}",
|
||||||
f"input logic {self.signal('ARREADY', 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)}",
|
f"output logic [2:0] {self.signal('ARPROT', child)}",
|
||||||
# Read data channel
|
# Read data channel
|
||||||
f"input logic {self.signal('RVALID', child)}",
|
f"input logic {self.signal('RVALID', child)}",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
|
from collections import deque
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import jinja2 as jj
|
import jinja2 as jj
|
||||||
@@ -106,7 +107,7 @@ class BaseCpuif:
|
|||||||
|
|
||||||
return f"({cpuif_addr} - 'h{addr:x})[{clog2(size) - 1}:0]"
|
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
|
raise NotImplementedError
|
||||||
|
|
||||||
def fanin(self, node: AddressableNode | None = None) -> str:
|
def fanin(self, node: AddressableNode | None = None) -> str:
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ class FanoutGenerator(BusDecoderListener):
|
|||||||
)
|
)
|
||||||
self._stack.append(fb)
|
self._stack.append(fb)
|
||||||
|
|
||||||
self._stack[-1] += self._cpuif.fanout(node)
|
self._stack[-1] += self._cpuif.fanout(node, self._array_stride_stack)
|
||||||
|
|
||||||
return action
|
return action
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,8 @@ def _build_master_table(dut, masters_cfg: list[dict[str, Any]]) -> dict[str, dic
|
|||||||
"PREADY": SignalHandle(dut, f"{prefix}_PREADY"),
|
"PREADY": SignalHandle(dut, f"{prefix}_PREADY"),
|
||||||
"PSLVERR": SignalHandle(dut, f"{prefix}_PSLVERR"),
|
"PSLVERR": SignalHandle(dut, f"{prefix}_PSLVERR"),
|
||||||
},
|
},
|
||||||
|
"inst_size": master["inst_size"],
|
||||||
|
"inst_address": master["inst_address"],
|
||||||
}
|
}
|
||||||
table[master["inst_name"]] = entry
|
table[master["inst_name"]] = entry
|
||||||
return table
|
return table
|
||||||
@@ -125,11 +127,16 @@ async def test_apb3_address_decoding(dut) -> None:
|
|||||||
slave.PSEL.value = 1
|
slave.PSEL.value = 1
|
||||||
slave.PENABLE.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")
|
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"]["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"]["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"
|
f"{master_name} must receive write address"
|
||||||
)
|
)
|
||||||
assert _get_int(entry["outputs"]["PWDATA"], index) == write_data, (
|
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, (
|
assert _get_int(entry["outputs"]["PWRITE"], index) == 0, (
|
||||||
f"{master_name} should clear write during read"
|
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"
|
f"{master_name} must receive read address"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Any, Iterable
|
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"),
|
"PREADY": SignalHandle(dut, f"{port_prefix}_PREADY"),
|
||||||
"PSLVERR": SignalHandle(dut, f"{port_prefix}_PSLVERR"),
|
"PSLVERR": SignalHandle(dut, f"{port_prefix}_PSLVERR"),
|
||||||
},
|
},
|
||||||
|
"inst_size": master["inst_size"],
|
||||||
|
"inst_address": master["inst_address"],
|
||||||
}
|
}
|
||||||
table[master["inst_name"]] = entry
|
table[master["inst_name"]] = entry
|
||||||
return table
|
return table
|
||||||
@@ -138,11 +141,16 @@ async def test_apb4_address_decoding(dut) -> None:
|
|||||||
slave.PSEL.value = 1
|
slave.PSEL.value = 1
|
||||||
slave.PENABLE.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")
|
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"]["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"]["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"
|
f"{master_name} must receive write address"
|
||||||
)
|
)
|
||||||
assert _get_int(entry["outputs"]["PWDATA"], index) == write_data, (
|
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, (
|
assert _get_int(entry["outputs"]["PWRITE"], index) == 0, (
|
||||||
f"{master_name} should deassert write for reads"
|
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"
|
f"{master_name} must receive read address"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import logging
|
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
|
rdl_path = repo_root / "tests" / "cocotb_lib" / "rdl" / rdl_file
|
||||||
build_root = tmp_path / top_name
|
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(
|
module_path, package_path, config = prepare_cpuif_case(
|
||||||
str(rdl_path),
|
str(rdl_path),
|
||||||
top_name,
|
top_name,
|
||||||
@@ -83,4 +87,4 @@ def test_apb4_smoke(tmp_path: Path, rdl_file: str, top_name: str) -> None:
|
|||||||
=== End Simulation Log ===
|
=== End Simulation Log ===
|
||||||
""")
|
""")
|
||||||
if e.code != 0:
|
if e.code != 0:
|
||||||
raise
|
raise e
|
||||||
|
|||||||
@@ -84,6 +84,8 @@ def _build_master_table(dut, masters_cfg: list[dict[str, Any]]) -> dict[str, dic
|
|||||||
"RDATA": SignalHandle(dut, f"{prefix}_RDATA"),
|
"RDATA": SignalHandle(dut, f"{prefix}_RDATA"),
|
||||||
"RRESP": SignalHandle(dut, f"{prefix}_RRESP"),
|
"RRESP": SignalHandle(dut, f"{prefix}_RRESP"),
|
||||||
},
|
},
|
||||||
|
"inst_size": master["inst_size"],
|
||||||
|
"inst_address": master["inst_address"],
|
||||||
}
|
}
|
||||||
table[master["inst_name"]] = entry
|
table[master["inst_name"]] = entry
|
||||||
return table
|
return table
|
||||||
@@ -156,10 +158,17 @@ async def test_axi4lite_address_decoding(dut) -> None:
|
|||||||
slave.WVALID.value = 1
|
slave.WVALID.value = 1
|
||||||
slave.BREADY.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")
|
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"]["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"]["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"]["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"
|
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")
|
await Timer(1, units="ns")
|
||||||
|
|
||||||
assert _get_int(entry["outputs"]["ARVALID"], index) == 1, f"{master_name} should assert ARVALID"
|
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):
|
for other_name, other_idx in _all_index_pairs(masters):
|
||||||
if other_name == master_name and other_idx == index:
|
if other_name == master_name and other_idx == index:
|
||||||
|
|||||||
@@ -223,6 +223,8 @@ def _build_case_config(
|
|||||||
"is_array": bool(child.is_array),
|
"is_array": bool(child.is_array),
|
||||||
"dimensions": list(child.array_dimensions or []),
|
"dimensions": list(child.array_dimensions or []),
|
||||||
"indices": set(),
|
"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
|
# 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),
|
"is_array": bool(master.is_array),
|
||||||
"dimensions": list(master.array_dimensions or []),
|
"dimensions": list(master.array_dimensions or []),
|
||||||
"indices": set(),
|
"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 [])
|
idx_tuple = tuple(master.current_idx or [])
|
||||||
@@ -279,6 +283,8 @@ def _build_case_config(
|
|||||||
"is_array": entry["is_array"],
|
"is_array": entry["is_array"],
|
||||||
"dimensions": entry["dimensions"],
|
"dimensions": entry["dimensions"],
|
||||||
"indices": entry["indices"],
|
"indices": entry["indices"],
|
||||||
|
"inst_size": entry["inst_size"],
|
||||||
|
"inst_address": entry["inst_address"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user