From 1e09da6dbf5dd44fd865c7c68cfbfc6ffd2dee91 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Mon, 2 Feb 2026 23:34:09 -0800 Subject: [PATCH] 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> --- pyproject.toml | 2 +- .../cpuif/apb3/apb3_cpuif.py | 43 ++++++++++------- .../cpuif/apb3/apb3_cpuif_flat.py | 28 +++++++---- .../cpuif/apb3/apb3_tmpl.sv | 4 +- .../cpuif/apb4/apb4_cpuif.py | 44 ++++++++++------- .../cpuif/apb4/apb4_cpuif_flat.py | 27 +++++++---- .../cpuif/apb4/apb4_tmpl.sv | 4 +- .../cpuif/axi4lite/axi4_lite_cpuif.py | 48 ++++++++++++------- .../cpuif/axi4lite/axi4_lite_cpuif_flat.py | 30 ++++++++---- src/peakrdl_busdecoder/cpuif/base_cpuif.py | 4 +- src/peakrdl_busdecoder/cpuif/fanin_gen.py | 22 ++++++--- uv.lock | 5 +- 12 files changed, 168 insertions(+), 93 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0cdccf2..9211dcf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "peakrdl-busdecoder" -version = "0.6.5" +version = "0.6.6" requires-python = ">=3.10" dependencies = [ "jinja2~=3.1", diff --git a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py index a0c5bcc..07f3f81 100644 --- a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py @@ -47,11 +47,36 @@ class APB3Cpuif(BaseCpuif): return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items()) - def fanin(self, node: AddressableNode | None = None) -> str: + 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: + # Use intermediate signals for interface arrays to avoid + # non-constant indexing of interface arrays in procedural blocks + if self.is_interface and node.is_array and node.array_dimensions: + # Generate array index string [i0][i1]... for the intermediate signal + array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) + fanin["cpuif_wr_ack"] = f"{node.inst_name}_fanin_ready{array_idx}" + fanin["cpuif_wr_err"] = f"{node.inst_name}_fanin_err{array_idx}" + 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: # Use intermediate signals for interface arrays to avoid # non-constant indexing of interface arrays in procedural blocks @@ -60,24 +85,10 @@ class APB3Cpuif(BaseCpuif): array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}" fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}" + fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}" else: fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i") fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i") - - return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) - - def readback(self, node: AddressableNode | None = None) -> str: - fanin: dict[str, str] = {} - if node is None: - fanin["cpuif_rd_data"] = "'0" - else: - # Use intermediate signals for interface arrays to avoid - # non-constant indexing of interface arrays in procedural blocks - if self.is_interface and node.is_array and node.array_dimensions: - # Generate array index string [i0][i1]... for the intermediate signal - array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) - fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}" - else: fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i") return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) diff --git a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py index 0abd376..e8c2079 100644 --- a/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py +++ b/src/peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py @@ -53,22 +53,32 @@ class APB3CpuifFlat(BaseCpuif): return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items()) - def fanin(self, node: AddressableNode | None = None) -> str: + 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") - - return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) - - def readback(self, node: AddressableNode | None = None) -> str: - fanin: dict[str, str] = {} - if node is None: - fanin["cpuif_rd_data"] = "'0" - else: fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i") return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) diff --git a/src/peakrdl_busdecoder/cpuif/apb3/apb3_tmpl.sv b/src/peakrdl_busdecoder/cpuif/apb3/apb3_tmpl.sv index fb0b726..2688072 100644 --- a/src/peakrdl_busdecoder/cpuif/apb3/apb3_tmpl.sv +++ b/src/peakrdl_busdecoder/cpuif/apb3/apb3_tmpl.sv @@ -19,8 +19,8 @@ assign cpuif_rd_addr = {{cpuif.signal("PADDR")}}; assign cpuif_wr_data = {{cpuif.signal("PWDATA")}}; assign {{cpuif.signal("PRDATA")}} = cpuif_rd_data; -assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack; -assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpuif_wr_sel.cpuif_err; +assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack | cpuif_wr_ack; +assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_wr_err; //-------------------------------------------------------------------------- // Fanout CPU Bus interface signals diff --git a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py index 88a9626..3114432 100644 --- a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py @@ -50,11 +50,37 @@ class APB4Cpuif(BaseCpuif): return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items()) - def fanin(self, node: AddressableNode | None = None) -> str: + 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: + # Use intermediate signals for interface arrays to avoid + # non-constant indexing of interface arrays in procedural blocks + if self.is_interface and node.is_array and node.array_dimensions: + # Generate array index string [i0][i1]... for the intermediate signal + array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) + fanin["cpuif_wr_ack"] = f"{node.inst_name}_fanin_ready{array_idx}" + fanin["cpuif_wr_err"] = f"{node.inst_name}_fanin_err{array_idx}" + 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: # Use intermediate signals for interface arrays to avoid # non-constant indexing of interface arrays in procedural blocks @@ -63,24 +89,10 @@ class APB4Cpuif(BaseCpuif): array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}" fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}" + fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}" else: fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i") fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i") - - return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) - - def readback(self, node: AddressableNode | None = None) -> str: - fanin: dict[str, str] = {} - if node is None: - fanin["cpuif_rd_data"] = "'0" - else: - # Use intermediate signals for interface arrays to avoid - # non-constant indexing of interface arrays in procedural blocks - if self.is_interface and node.is_array and node.array_dimensions: - # Generate array index string [i0][i1]... for the intermediate signal - array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) - fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}" - else: fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i") return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) diff --git a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py index 2d43216..33bc589 100644 --- a/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py +++ b/src/peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py @@ -55,22 +55,31 @@ class APB4CpuifFlat(BaseCpuif): return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items()) - def fanin(self, node: AddressableNode | None = None) -> str: + 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") - - return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) - - def readback(self, node: AddressableNode | None = None) -> str: - fanin: dict[str, str] = {} - if node is None: - fanin["cpuif_rd_data"] = "'0" - else: fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i") return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items()) diff --git a/src/peakrdl_busdecoder/cpuif/apb4/apb4_tmpl.sv b/src/peakrdl_busdecoder/cpuif/apb4/apb4_tmpl.sv index 410e878..e44ef30 100644 --- a/src/peakrdl_busdecoder/cpuif/apb4/apb4_tmpl.sv +++ b/src/peakrdl_busdecoder/cpuif/apb4/apb4_tmpl.sv @@ -20,8 +20,8 @@ assign cpuif_wr_data = {{cpuif.signal("PWDATA")}}; assign cpuif_wr_byte_en = {{cpuif.signal("PSTRB")}}; assign {{cpuif.signal("PRDATA")}} = cpuif_rd_data; -assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack; -assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpuif_wr_sel.cpuif_err; +assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack | cpuif_wr_ack; +assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_wr_err; //-------------------------------------------------------------------------- // Fanout CPU Bus interface signals diff --git a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py index 12b7205..bc9aa0f 100644 --- a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py @@ -63,11 +63,38 @@ class AXI4LiteCpuif(BaseCpuif): return "\n".join(f"assign {lhs} = {rhs};" for lhs, rhs in fanout.items()) - def fanin(self, node: AddressableNode | None = None) -> str: + 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: + # Use intermediate signals for interface arrays to avoid + # non-constant indexing of interface arrays in procedural blocks + if self.is_interface and node.is_array and node.array_dimensions: + # Generate array index string [i0][i1]... for the intermediate signal + array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) + fanin["cpuif_wr_ack"] = f"{node.inst_name}_fanin_ready{array_idx}" + fanin["cpuif_wr_err"] = f"{node.inst_name}_fanin_err{array_idx}" + else: + # Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR) + fanin["cpuif_wr_ack"] = self.signal("BVALID", node, "i") + fanin["cpuif_wr_err"] = f"{self.signal('BRESP', node, 'i')}[1]" + + return "\n".join(f"{lhs} = {rhs};" for lhs, rhs 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: # Use intermediate signals for interface arrays to avoid # non-constant indexing of interface arrays in procedural blocks @@ -76,25 +103,10 @@ class AXI4LiteCpuif(BaseCpuif): array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}" fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}" - else: - # Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR) - fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i") - fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]" - - return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items()) - - def readback(self, node: AddressableNode | None = None) -> str: - fanin: dict[str, str] = {} - if node is None: - fanin["cpuif_rd_data"] = "'0" - else: - # Use intermediate signals for interface arrays to avoid - # non-constant indexing of interface arrays in procedural blocks - if self.is_interface and node.is_array and node.array_dimensions: - # Generate array index string [i0][i1]... for the intermediate signal - array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions))) fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}" else: + fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i") + fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]" fanin["cpuif_rd_data"] = self.signal("RDATA", node, "i") return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items()) 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 be54571..b4761cc 100644 --- a/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py +++ b/src/peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py @@ -72,23 +72,33 @@ class AXI4LiteCpuifFlat(BaseCpuif): return "\n".join(f"assign {lhs} = {rhs};" for lhs, rhs in fanout.items()) - def fanin(self, node: AddressableNode | None = None) -> str: + 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: + # Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR) + fanin["cpuif_wr_ack"] = self.signal("BVALID", node, "i") + fanin["cpuif_wr_err"] = f"{self.signal('BRESP', node, 'i')}[1]" + + return "\n".join(f"{lhs} = {rhs};" for lhs, rhs 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: - # Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR) fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i") fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]" - - return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items()) - - def readback(self, node: AddressableNode | None = None) -> str: - fanin: dict[str, str] = {} - if node is None: - fanin["cpuif_rd_data"] = "'0" - else: fanin["cpuif_rd_data"] = self.signal("RDATA", node, "i") return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items()) diff --git a/src/peakrdl_busdecoder/cpuif/base_cpuif.py b/src/peakrdl_busdecoder/cpuif/base_cpuif.py index 741267a..185b4c9 100644 --- a/src/peakrdl_busdecoder/cpuif/base_cpuif.py +++ b/src/peakrdl_busdecoder/cpuif/base_cpuif.py @@ -110,10 +110,10 @@ class BaseCpuif: def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str: raise NotImplementedError - def fanin(self, node: AddressableNode | None = None) -> str: + def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str: raise NotImplementedError - def readback(self, node: AddressableNode | None = None) -> str: + def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str: raise NotImplementedError def fanin_intermediate_assignments( diff --git a/src/peakrdl_busdecoder/cpuif/fanin_gen.py b/src/peakrdl_busdecoder/cpuif/fanin_gen.py index d5fc598..282bd2b 100644 --- a/src/peakrdl_busdecoder/cpuif/fanin_gen.py +++ b/src/peakrdl_busdecoder/cpuif/fanin_gen.py @@ -20,8 +20,8 @@ class FaninGenerator(BusDecoderListener): self._stack: deque[Body] = deque() cb = CombinationalBody() - cb += cpuif.fanin() - cb += cpuif.readback() + cb += cpuif.fanin_wr() + cb += cpuif.fanin_rd() self._stack.append(cb) def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None: @@ -48,15 +48,13 @@ class FaninGenerator(BusDecoderListener): self._stack.append(fb) ifb = IfBody() - with ifb.cm( - f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)} || cpuif_wr_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}" - ) as b: - b += self._cpuif.fanin(node) + with ifb.cm(f"cpuif_wr_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}") as b: + b += self._cpuif.fanin_wr(node) self._stack[-1] += ifb ifb = IfBody() with ifb.cm(f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}") as b: - b += self._cpuif.readback(node) + b += self._cpuif.fanin_rd(node) self._stack[-1] += ifb return action @@ -72,4 +70,14 @@ class FaninGenerator(BusDecoderListener): super().exit_AddressableComponent(node) def __str__(self) -> str: + wr_ifb = IfBody() + with wr_ifb.cm("cpuif_wr_sel.cpuif_err") as b: + self._cpuif.fanin_wr(error=True) + self._stack[-1] += wr_ifb + + rd_ifb = IfBody() + with rd_ifb.cm("cpuif_rd_sel.cpuif_err") as b: + self._cpuif.fanin_rd(error=True) + self._stack[-1] += rd_ifb + return "\n".join(map(str, self._stack)) diff --git a/uv.lock b/uv.lock index 57480a0..d35ba2b 100644 --- a/uv.lock +++ b/uv.lock @@ -311,6 +311,9 @@ dependencies = [ { name = "scapy" }, ] sdist = { url = "https://files.pythonhosted.org/packages/4e/f9/1474d5503af6f8c979a33e3489c0e6886b6ffb1af3d00419d2e0da1dd274/cocotb_bus-0.3.0.tar.gz", hash = "sha256:9762b29273ff062f52160e57274e3cb106d14e7e776515de1372c1d73546b005", size = 29991, upload-time = "2025-11-22T00:19:31.734Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ea/43/8b3f96cf401c2a7f6e907ccc86d3b73433eeaf5525df90b630d8c112474b/cocotb_bus-0.3.0-py3-none-any.whl", hash = "sha256:b4f06cce2462a8f9487b42c46b0ff3afd253f0fa4f67a0c382ebe0ba614229eb", size = 36206, upload-time = "2026-01-15T04:51:43.009Z" }, +] [[package]] name = "colorama" @@ -655,7 +658,7 @@ wheels = [ [[package]] name = "peakrdl-busdecoder" -version = "0.6.5" +version = "0.6.6" source = { editable = "." } dependencies = [ { name = "jinja2" },