peakrdl-busdecoder 0.6.5__py3-none-any.whl → 0.6.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,37 +47,48 @@ class APB3Cpuif(BaseCpuif):
47
47
 
48
48
  return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
49
49
 
50
- def fanin(self, node: AddressableNode | None = None) -> str:
50
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
51
51
  fanin: dict[str, str] = {}
52
52
  if node is None:
53
- fanin["cpuif_rd_ack"] = "'0"
54
- fanin["cpuif_rd_err"] = "'0"
53
+ fanin["cpuif_wr_ack"] = "'0"
54
+ fanin["cpuif_wr_err"] = "'0"
55
+ if error:
56
+ fanin["cpuif_wr_ack"] = "'1"
57
+ fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
55
58
  else:
56
59
  # Use intermediate signals for interface arrays to avoid
57
60
  # non-constant indexing of interface arrays in procedural blocks
58
61
  if self.is_interface and node.is_array and node.array_dimensions:
59
62
  # Generate array index string [i0][i1]... for the intermediate signal
60
63
  array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions)))
61
- fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
62
- fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}"
64
+ fanin["cpuif_wr_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
65
+ fanin["cpuif_wr_err"] = f"{node.inst_name}_fanin_err{array_idx}"
63
66
  else:
64
- fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
65
- fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
66
-
67
+ fanin["cpuif_wr_ack"] = self.signal("PREADY", node, "i")
68
+ fanin["cpuif_wr_err"] = self.signal("PSLVERR", node, "i")
67
69
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
68
70
 
69
- def readback(self, node: AddressableNode | None = None) -> str:
71
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
70
72
  fanin: dict[str, str] = {}
71
73
  if node is None:
74
+ fanin["cpuif_rd_ack"] = "'0"
75
+ fanin["cpuif_rd_err"] = "'0"
72
76
  fanin["cpuif_rd_data"] = "'0"
77
+ if error:
78
+ fanin["cpuif_rd_ack"] = "'1"
79
+ fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
73
80
  else:
74
81
  # Use intermediate signals for interface arrays to avoid
75
82
  # non-constant indexing of interface arrays in procedural blocks
76
83
  if self.is_interface and node.is_array and node.array_dimensions:
77
84
  # Generate array index string [i0][i1]... for the intermediate signal
78
85
  array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions)))
86
+ fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
87
+ fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}"
79
88
  fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}"
80
89
  else:
90
+ fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
91
+ fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
81
92
  fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
82
93
 
83
94
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
@@ -53,22 +53,32 @@ class APB3CpuifFlat(BaseCpuif):
53
53
 
54
54
  return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
55
55
 
56
- def fanin(self, node: AddressableNode | None = None) -> str:
56
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
57
57
  fanin: dict[str, str] = {}
58
58
  if node is None:
59
- fanin["cpuif_rd_ack"] = "'0"
60
- fanin["cpuif_rd_err"] = "'0"
59
+ fanin["cpuif_wr_ack"] = "'0"
60
+ fanin["cpuif_wr_err"] = "'0"
61
+ if error:
62
+ fanin["cpuif_wr_ack"] = "'1"
63
+ fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
61
64
  else:
62
- fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
63
- fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
65
+ fanin["cpuif_wr_ack"] = self.signal("PREADY", node, "i")
66
+ fanin["cpuif_wr_err"] = self.signal("PSLVERR", node, "i")
64
67
 
65
68
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
66
69
 
67
- def readback(self, node: AddressableNode | None = None) -> str:
70
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
68
71
  fanin: dict[str, str] = {}
69
72
  if node is None:
73
+ fanin["cpuif_rd_ack"] = "'0"
74
+ fanin["cpuif_rd_err"] = "'0"
70
75
  fanin["cpuif_rd_data"] = "'0"
76
+ if error:
77
+ fanin["cpuif_rd_ack"] = "'1"
78
+ fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
71
79
  else:
80
+ fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
81
+ fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
72
82
  fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
73
83
 
74
84
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
@@ -19,8 +19,8 @@ assign cpuif_rd_addr = {{cpuif.signal("PADDR")}};
19
19
  assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
20
20
 
21
21
  assign {{cpuif.signal("PRDATA")}} = cpuif_rd_data;
22
- assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack;
23
- assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpuif_wr_sel.cpuif_err;
22
+ assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack | cpuif_wr_ack;
23
+ assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_wr_err;
24
24
 
25
25
  //--------------------------------------------------------------------------
26
26
  // Fanout CPU Bus interface signals
@@ -37,4 +37,4 @@ assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpu
37
37
  //--------------------------------------------------------------------------
38
38
  // Fanin CPU Bus interface signals
39
39
  //--------------------------------------------------------------------------
40
- {{fanin|walk(cpuif=cpuif)}}
40
+ {{fanin|walk(cpuif=cpuif)}}
@@ -50,37 +50,49 @@ class APB4Cpuif(BaseCpuif):
50
50
 
51
51
  return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
52
52
 
53
- def fanin(self, node: AddressableNode | None = None) -> str:
53
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
54
54
  fanin: dict[str, str] = {}
55
55
  if node is None:
56
- fanin["cpuif_rd_ack"] = "'0"
57
- fanin["cpuif_rd_err"] = "'0"
56
+ fanin["cpuif_wr_ack"] = "'0"
57
+ fanin["cpuif_wr_err"] = "'0"
58
+ if error:
59
+ fanin["cpuif_wr_ack"] = "'1"
60
+ fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
58
61
  else:
59
62
  # Use intermediate signals for interface arrays to avoid
60
63
  # non-constant indexing of interface arrays in procedural blocks
61
64
  if self.is_interface and node.is_array and node.array_dimensions:
62
65
  # Generate array index string [i0][i1]... for the intermediate signal
63
66
  array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions)))
64
- fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
65
- fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}"
67
+ fanin["cpuif_wr_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
68
+ fanin["cpuif_wr_err"] = f"{node.inst_name}_fanin_err{array_idx}"
66
69
  else:
67
- fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
68
- fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
70
+ fanin["cpuif_wr_ack"] = self.signal("PREADY", node, "i")
71
+ fanin["cpuif_wr_err"] = self.signal("PSLVERR", node, "i")
69
72
 
70
73
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
71
74
 
72
- def readback(self, node: AddressableNode | None = None) -> str:
75
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
73
76
  fanin: dict[str, str] = {}
74
77
  if node is None:
78
+ fanin["cpuif_rd_ack"] = "'0"
79
+ fanin["cpuif_rd_err"] = "'0"
75
80
  fanin["cpuif_rd_data"] = "'0"
81
+ if error:
82
+ fanin["cpuif_rd_ack"] = "'1"
83
+ fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
76
84
  else:
77
85
  # Use intermediate signals for interface arrays to avoid
78
86
  # non-constant indexing of interface arrays in procedural blocks
79
87
  if self.is_interface and node.is_array and node.array_dimensions:
80
88
  # Generate array index string [i0][i1]... for the intermediate signal
81
89
  array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions)))
90
+ fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
91
+ fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}"
82
92
  fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}"
83
93
  else:
94
+ fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
95
+ fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
84
96
  fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
85
97
 
86
98
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
@@ -55,22 +55,31 @@ class APB4CpuifFlat(BaseCpuif):
55
55
 
56
56
  return "\n".join(f"assign {kv[0]} = {kv[1]};" for kv in fanout.items())
57
57
 
58
- def fanin(self, node: AddressableNode | None = None) -> str:
58
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
59
59
  fanin: dict[str, str] = {}
60
60
  if node is None:
61
- fanin["cpuif_rd_ack"] = "'0"
62
- fanin["cpuif_rd_err"] = "'0"
61
+ fanin["cpuif_wr_ack"] = "'0"
62
+ fanin["cpuif_wr_err"] = "'0"
63
+ if error:
64
+ fanin["cpuif_wr_ack"] = "'1"
65
+ fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
63
66
  else:
64
- fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
65
- fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
66
-
67
+ fanin["cpuif_wr_ack"] = self.signal("PREADY", node, "i")
68
+ fanin["cpuif_wr_err"] = self.signal("PSLVERR", node, "i")
67
69
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
68
70
 
69
- def readback(self, node: AddressableNode | None = None) -> str:
71
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
70
72
  fanin: dict[str, str] = {}
71
73
  if node is None:
74
+ fanin["cpuif_rd_ack"] = "'0"
75
+ fanin["cpuif_rd_err"] = "'0"
72
76
  fanin["cpuif_rd_data"] = "'0"
77
+ if error:
78
+ fanin["cpuif_rd_ack"] = "'1"
79
+ fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
73
80
  else:
81
+ fanin["cpuif_rd_ack"] = self.signal("PREADY", node, "i")
82
+ fanin["cpuif_rd_err"] = self.signal("PSLVERR", node, "i")
74
83
  fanin["cpuif_rd_data"] = self.signal("PRDATA", node, "i")
75
84
 
76
85
  return "\n".join(f"{kv[0]} = {kv[1]};" for kv in fanin.items())
@@ -20,8 +20,8 @@ assign cpuif_wr_data = {{cpuif.signal("PWDATA")}};
20
20
  assign cpuif_wr_byte_en = {{cpuif.signal("PSTRB")}};
21
21
 
22
22
  assign {{cpuif.signal("PRDATA")}} = cpuif_rd_data;
23
- assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack;
24
- assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpuif_wr_sel.cpuif_err;
23
+ assign {{cpuif.signal("PREADY")}} = cpuif_rd_ack | cpuif_wr_ack;
24
+ assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_wr_err;
25
25
 
26
26
  //--------------------------------------------------------------------------
27
27
  // Fanout CPU Bus interface signals
@@ -38,4 +38,4 @@ assign {{cpuif.signal("PSLVERR")}} = cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpu
38
38
  //--------------------------------------------------------------------------
39
39
  // Fanin CPU Bus interface signals
40
40
  //--------------------------------------------------------------------------
41
- {{fanin|walk(cpuif=cpuif)}}
41
+ {{fanin|walk(cpuif=cpuif)}}
@@ -63,38 +63,50 @@ class AXI4LiteCpuif(BaseCpuif):
63
63
 
64
64
  return "\n".join(f"assign {lhs} = {rhs};" for lhs, rhs in fanout.items())
65
65
 
66
- def fanin(self, node: AddressableNode | None = None) -> str:
66
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
67
67
  fanin: dict[str, str] = {}
68
68
  if node is None:
69
- fanin["cpuif_rd_ack"] = "'0"
70
- fanin["cpuif_rd_err"] = "'0"
69
+ fanin["cpuif_wr_ack"] = "'0"
70
+ fanin["cpuif_wr_err"] = "'0"
71
+ if error:
72
+ fanin["cpuif_wr_ack"] = "'1"
73
+ fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
71
74
  else:
72
75
  # Use intermediate signals for interface arrays to avoid
73
76
  # non-constant indexing of interface arrays in procedural blocks
74
77
  if self.is_interface and node.is_array and node.array_dimensions:
75
78
  # Generate array index string [i0][i1]... for the intermediate signal
76
79
  array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions)))
77
- fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
78
- fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}"
80
+ fanin["cpuif_wr_ack"] = f"{node.inst_name}_fanin_wr_valid{array_idx}"
81
+ fanin["cpuif_wr_err"] = f"{node.inst_name}_fanin_wr_err{array_idx}"
79
82
  else:
80
83
  # Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR)
81
- fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i")
82
- fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]"
84
+ fanin["cpuif_wr_ack"] = self.signal("BVALID", node, "i")
85
+ fanin["cpuif_wr_err"] = f"{self.signal('BRESP', node, 'i')}[1]"
83
86
 
84
87
  return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items())
85
88
 
86
- def readback(self, node: AddressableNode | None = None) -> str:
89
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
87
90
  fanin: dict[str, str] = {}
88
91
  if node is None:
92
+ fanin["cpuif_rd_ack"] = "'0"
93
+ fanin["cpuif_rd_err"] = "'0"
89
94
  fanin["cpuif_rd_data"] = "'0"
95
+ if error:
96
+ fanin["cpuif_rd_ack"] = "'1"
97
+ fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
90
98
  else:
91
99
  # Use intermediate signals for interface arrays to avoid
92
100
  # non-constant indexing of interface arrays in procedural blocks
93
101
  if self.is_interface and node.is_array and node.array_dimensions:
94
102
  # Generate array index string [i0][i1]... for the intermediate signal
95
103
  array_idx = "".join(f"[i{i}]" for i in range(len(node.array_dimensions)))
104
+ fanin["cpuif_rd_ack"] = f"{node.inst_name}_fanin_ready{array_idx}"
105
+ fanin["cpuif_rd_err"] = f"{node.inst_name}_fanin_err{array_idx}"
96
106
  fanin["cpuif_rd_data"] = f"{node.inst_name}_fanin_data{array_idx}"
97
107
  else:
108
+ fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i")
109
+ fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]"
98
110
  fanin["cpuif_rd_data"] = self.signal("RDATA", node, "i")
99
111
 
100
112
  return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items())
@@ -107,4 +119,16 @@ class AXI4LiteCpuif(BaseCpuif):
107
119
  f"assign {inst_name}_fanin_ready{array_idx} = {master_prefix}{indexed_path}.RVALID;",
108
120
  f"assign {inst_name}_fanin_err{array_idx} = {master_prefix}{indexed_path}.RRESP[1];",
109
121
  f"assign {inst_name}_fanin_data{array_idx} = {master_prefix}{indexed_path}.RDATA;",
122
+ f"assign {inst_name}_fanin_wr_valid{array_idx} = {master_prefix}{indexed_path}.BVALID;",
123
+ f"assign {inst_name}_fanin_wr_err{array_idx} = {master_prefix}{indexed_path}.BRESP[1];",
124
+ ]
125
+
126
+ def fanin_intermediate_declarations(self, node: AddressableNode) -> list[str]:
127
+ if not node.array_dimensions:
128
+ return []
129
+
130
+ array_str = "".join(f"[{dim}]" for dim in node.array_dimensions)
131
+ return [
132
+ f"logic {node.inst_name}_fanin_wr_valid{array_str};",
133
+ f"logic {node.inst_name}_fanin_wr_err{array_str};",
110
134
  ]
@@ -72,23 +72,33 @@ class AXI4LiteCpuifFlat(BaseCpuif):
72
72
 
73
73
  return "\n".join(f"assign {lhs} = {rhs};" for lhs, rhs in fanout.items())
74
74
 
75
- def fanin(self, node: AddressableNode | None = None) -> str:
75
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
76
76
  fanin: dict[str, str] = {}
77
77
  if node is None:
78
- fanin["cpuif_rd_ack"] = "'0"
79
- fanin["cpuif_rd_err"] = "'0"
78
+ fanin["cpuif_wr_ack"] = "'0"
79
+ fanin["cpuif_wr_err"] = "'0"
80
+ if error:
81
+ fanin["cpuif_wr_ack"] = "'1"
82
+ fanin["cpuif_wr_err"] = "cpuif_wr_sel.cpuif_err"
80
83
  else:
81
84
  # Read side: ack comes from RVALID; err if RRESP[1] is set (SLVERR/DECERR)
82
- fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i")
83
- fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]"
85
+ fanin["cpuif_wr_ack"] = self.signal("BVALID", node, "i")
86
+ fanin["cpuif_wr_err"] = f"{self.signal('BRESP', node, 'i')}[1]"
84
87
 
85
88
  return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items())
86
89
 
87
- def readback(self, node: AddressableNode | None = None) -> str:
90
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
88
91
  fanin: dict[str, str] = {}
89
92
  if node is None:
93
+ fanin["cpuif_rd_ack"] = "'0"
94
+ fanin["cpuif_rd_err"] = "'0"
90
95
  fanin["cpuif_rd_data"] = "'0"
96
+ if error:
97
+ fanin["cpuif_rd_ack"] = "'1"
98
+ fanin["cpuif_rd_err"] = "cpuif_rd_sel.cpuif_err"
91
99
  else:
100
+ fanin["cpuif_rd_ack"] = self.signal("RVALID", node, "i")
101
+ fanin["cpuif_rd_err"] = f"{self.signal('RRESP', node, 'i')}[1]"
92
102
  fanin["cpuif_rd_data"] = self.signal("RDATA", node, "i")
93
103
 
94
104
  return "\n".join(f"{lhs} = {rhs};" for lhs, rhs in fanin.items())
@@ -26,9 +26,21 @@
26
26
  `endif
27
27
  {% endif -%}
28
28
 
29
+ logic axi_wr_valid;
30
+ logic axi_wr_invalid;
31
+ logic cpuif_wr_ack_int;
32
+ logic cpuif_rd_ack_int;
33
+
34
+ assign axi_wr_valid = {{cpuif.signal("AWVALID")}} & {{cpuif.signal("WVALID")}};
35
+ assign axi_wr_invalid = {{cpuif.signal("AWVALID")}} ^ {{cpuif.signal("WVALID")}};
36
+
37
+ // Ready/acceptance follows the simplified single-beat requirement
38
+ assign {{cpuif.signal("AWREADY")}} = axi_wr_valid;
39
+ assign {{cpuif.signal("WREADY")}} = axi_wr_valid;
40
+ assign {{cpuif.signal("ARREADY")}} = {{cpuif.signal("ARVALID")}};
29
41
 
30
42
  assign cpuif_req = {{cpuif.signal("AWVALID")}} | {{cpuif.signal("ARVALID")}};
31
- assign cpuif_wr_en = {{cpuif.signal("AWVALID")}} & {{cpuif.signal("WVALID")}};
43
+ assign cpuif_wr_en = axi_wr_valid;
32
44
  assign cpuif_rd_en = {{cpuif.signal("ARVALID")}};
33
45
 
34
46
  assign cpuif_wr_addr = {{cpuif.signal("AWADDR")}};
@@ -42,12 +54,14 @@ assign cpuif_wr_byte_en = {{cpuif.signal("WSTRB")}};
42
54
  // Read: ack=RVALID, err=RRESP[1] (SLVERR/DECERR), data=RDATA
43
55
  //
44
56
  assign {{cpuif.signal("RDATA")}} = cpuif_rd_data;
45
- assign {{cpuif.signal("RVALID")}} = cpuif_rd_ack;
57
+ assign cpuif_rd_ack_int = cpuif_rd_ack | cpuif_rd_sel.cpuif_err;
58
+ assign {{cpuif.signal("RVALID")}} = cpuif_rd_ack_int;
46
59
  assign {{cpuif.signal("RRESP")}} = (cpuif_rd_err | cpuif_rd_sel.cpuif_err | cpuif_wr_sel.cpuif_err) ? 2'b10 : 2'b00;
47
60
 
48
61
  // Write: ack=BVALID, err=BRESP[1]
49
- assign {{cpuif.signal("BVALID")}} = cpuif_wr_ack;
50
- assign {{cpuif.signal("BRESP")}} = (cpuif_wr_err | cpuif_wr_sel.cpuif_err | cpuif_rd_sel.cpuif_err) ? 2'b10 : 2'b00;
62
+ assign cpuif_wr_ack_int = cpuif_wr_ack | cpuif_wr_sel.cpuif_err | axi_wr_invalid;
63
+ assign {{cpuif.signal("BVALID")}} = cpuif_wr_ack_int;
64
+ assign {{cpuif.signal("BRESP")}} = (cpuif_wr_err | cpuif_wr_sel.cpuif_err | cpuif_rd_sel.cpuif_err | axi_wr_invalid) ? 2'b10 : 2'b00;
51
65
 
52
66
  //--------------------------------------------------------------------------
53
67
  // Fanout CPU Bus interface signals
@@ -64,4 +78,4 @@ assign {{cpuif.signal("BRESP")}} = (cpuif_wr_err | cpuif_wr_sel.cpuif_err | cpu
64
78
  //--------------------------------------------------------------------------
65
79
  // Fanin CPU Bus interface signals
66
80
  //--------------------------------------------------------------------------
67
- {{fanin|walk(cpuif=cpuif)}}
81
+ {{fanin|walk(cpuif=cpuif)}}
@@ -110,10 +110,10 @@ class BaseCpuif:
110
110
  def fanout(self, node: AddressableNode, array_stack: deque[int]) -> str:
111
111
  raise NotImplementedError
112
112
 
113
- def fanin(self, node: AddressableNode | None = None) -> str:
113
+ def fanin_wr(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
114
114
  raise NotImplementedError
115
115
 
116
- def readback(self, node: AddressableNode | None = None) -> str:
116
+ def fanin_rd(self, node: AddressableNode | None = None, *, error: bool = False) -> str:
117
117
  raise NotImplementedError
118
118
 
119
119
  def fanin_intermediate_assignments(
@@ -136,3 +136,7 @@ class BaseCpuif:
136
136
  List of assignment strings
137
137
  """
138
138
  return [] # Default: no intermediate assignments needed
139
+
140
+ def fanin_intermediate_declarations(self, node: AddressableNode) -> list[str]:
141
+ """Optional extra intermediate signal declarations for interface arrays."""
142
+ return []
@@ -20,8 +20,8 @@ class FaninGenerator(BusDecoderListener):
20
20
 
21
21
  self._stack: deque[Body] = deque()
22
22
  cb = CombinationalBody()
23
- cb += cpuif.fanin()
24
- cb += cpuif.readback()
23
+ cb += cpuif.fanin_wr()
24
+ cb += cpuif.fanin_rd()
25
25
  self._stack.append(cb)
26
26
 
27
27
  def enter_AddressableComponent(self, node: AddressableNode) -> WalkerAction | None:
@@ -48,15 +48,13 @@ class FaninGenerator(BusDecoderListener):
48
48
  self._stack.append(fb)
49
49
 
50
50
  ifb = IfBody()
51
- with ifb.cm(
52
- 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)}"
53
- ) as b:
54
- b += self._cpuif.fanin(node)
51
+ with ifb.cm(f"cpuif_wr_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}") as b:
52
+ b += self._cpuif.fanin_wr(node)
55
53
  self._stack[-1] += ifb
56
54
 
57
55
  ifb = IfBody()
58
56
  with ifb.cm(f"cpuif_rd_sel.{get_indexed_path(self._cpuif.exp.ds.top_node, node)}") as b:
59
- b += self._cpuif.readback(node)
57
+ b += self._cpuif.fanin_rd(node)
60
58
  self._stack[-1] += ifb
61
59
 
62
60
  return action
@@ -72,4 +70,14 @@ class FaninGenerator(BusDecoderListener):
72
70
  super().exit_AddressableComponent(node)
73
71
 
74
72
  def __str__(self) -> str:
73
+ wr_ifb = IfBody()
74
+ with wr_ifb.cm("cpuif_wr_sel.cpuif_err") as b:
75
+ b += self._cpuif.fanin_wr(error=True)
76
+ self._stack[-1] += wr_ifb
77
+
78
+ rd_ifb = IfBody()
79
+ with rd_ifb.cm("cpuif_rd_sel.cpuif_err") as b:
80
+ b += self._cpuif.fanin_rd(error=True)
81
+ self._stack[-1] += rd_ifb
82
+
75
83
  return "\n".join(map(str, self._stack))
@@ -94,6 +94,9 @@ class FaninIntermediateGenerator(BusDecoderListener):
94
94
  f"logic [{self._cpuif.data_width - 1}:0] {inst_name}_fanin_data{array_str};"
95
95
  )
96
96
 
97
+ # Allow CPU interface to add extra intermediate declarations (e.g., write responses)
98
+ self._declarations.extend(self._cpuif.fanin_intermediate_declarations(node))
99
+
97
100
  def _generate_intermediate_assignments(self, node: AddressableNode) -> str:
98
101
  """Generate assignments from interface array to intermediate signals."""
99
102
  inst_name = node.inst_name
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: peakrdl-busdecoder
3
- Version: 0.6.5
3
+ Version: 0.6.7
4
4
  Summary: Generate a SystemVerilog bus decoder from SystemRDL for splitting CPU interfaces to multiple sub-address spaces
5
5
  Author: Arnav Sacheti
6
6
  License: LGPLv3
@@ -20,30 +20,30 @@ peakrdl_busdecoder/body/for_loop_body.py,sha256=lJYfDiB7MF9_mfbGEApoVHRViBCqpGRs
20
20
  peakrdl_busdecoder/body/if_body.py,sha256=S4oVS7yz04R1i-23W-aWpVcVZa5dW-H0FL_KnMy-Wsc,3261
21
21
  peakrdl_busdecoder/body/struct_body.py,sha256=74ItYoYD-GqEidxc-ncV5y8fzGoM47NI4GnnweclmS8,624
22
22
  peakrdl_busdecoder/cpuif/__init__.py,sha256=T8YrELGuOBIPgj1e86tNJ5tSCf7fXpPadqa71v5MEx8,59
23
- peakrdl_busdecoder/cpuif/base_cpuif.py,sha256=-5bI43pbcPVYhvS0AEYgMkCBxkhnqmx9jLMazzT0z5k,4985
24
- peakrdl_busdecoder/cpuif/fanin_gen.py,sha256=ioCxjj3V3X8rHssqwuI4p_U-LKpBalATW_Qshtt8j9U,2425
25
- peakrdl_busdecoder/cpuif/fanin_intermediate_gen.py,sha256=hfvMyyx5ajEzvop3dzV37dT6Jn9yjORFnUkMAT1034A,5271
23
+ peakrdl_busdecoder/cpuif/base_cpuif.py,sha256=abc7WB5fI5NMwX5MMZfOOEA18f9bAVECoadC2XzW-gY,5222
24
+ peakrdl_busdecoder/cpuif/fanin_gen.py,sha256=Z5OrN3GaPU6yaVJTDOhQ7fNsUTXJMSai9v7jwSng8bc,2671
25
+ peakrdl_busdecoder/cpuif/fanin_intermediate_gen.py,sha256=r-Ffp6wvgZg3DclpuNfKeL-Jp1NSEs3uCfJiJobvlzs,5450
26
26
  peakrdl_busdecoder/cpuif/fanout_gen.py,sha256=-kopGBHC07D9VreygfN0VubHGVVO51og4lAFq6B1oV8,1876
27
27
  peakrdl_busdecoder/cpuif/interface.py,sha256=0xp_4K6DZMGOePbFgLEOIaVemjMS5pnQp7izKmzgu4s,6462
28
28
  peakrdl_busdecoder/cpuif/apb3/__init__.py,sha256=Uq82IJHzlITUvjTuETvPpSzvLEYoairzzPKfPz7kuC4,119
29
- peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py,sha256=71hIN2RtoyaR6ehqH9vTPh_e_XnO1azBknmTvC3hAeE,4282
30
- peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py,sha256=kdq6My7fjq233DUmwn_7VVFgqqnbZ-QMS4HEoI702MQ,2697
29
+ peakrdl_busdecoder/cpuif/apb3/apb3_cpuif.py,sha256=1NVcgUY-fT5A9OhHDXkSqtdqCWz5ITdoNgZ4b9Qz0iU,4989
30
+ peakrdl_busdecoder/cpuif/apb3/apb3_cpuif_flat.py,sha256=VIdHu5bijNnNN7uCCfCFSE2kGp7f3Ouyv5_l1BFVUq8,3233
31
31
  peakrdl_busdecoder/cpuif/apb3/apb3_interface.py,sha256=PQwMtjETR9-c9S1BzjdWieCis2qoOfUyRQAWcD3ScyE,2170
32
- peakrdl_busdecoder/cpuif/apb3/apb3_tmpl.sv,sha256=6et25KbiNkZBD1hxjSx0XZFUP9NnvVpixMSGtwJuwdA,1967
32
+ peakrdl_busdecoder/cpuif/apb3/apb3_tmpl.sv,sha256=8ej-_HO9k2MMkKvlXk5i57Zczb8adMko6i8JBL7mDH0,1948
33
33
  peakrdl_busdecoder/cpuif/apb4/__init__.py,sha256=k4JCbIrKGT8hiRvWJDcqc5xx7j9i_xYgpXU70sNaLsc,119
34
- peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py,sha256=Fg1CL4tfu0IyQLf1pDRPNP__5ZwZKEZN9es7VecAc5k,4491
35
- peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py,sha256=4nXU_Fgw2Bro9yxJhXjf5OEHf4kQjLzL05SrCbEVM1g,2839
34
+ peakrdl_busdecoder/cpuif/apb4/apb4_cpuif.py,sha256=JS8-wSmcSXfkyHGzmiyN-G-_5qdvdMwmYxpKn7uQgU4,5199
35
+ peakrdl_busdecoder/cpuif/apb4/apb4_cpuif_flat.py,sha256=yk80xCLoF9OQE51kkb1CmqVW_eirMoy_KyZ4tkurAh0,3374
36
36
  peakrdl_busdecoder/cpuif/apb4/apb4_interface.py,sha256=dnVWHi1NZScIR7sLYVfxbJDrU-Fm221O1XvHMdpSyi4,2472
37
- peakrdl_busdecoder/cpuif/apb4/apb4_tmpl.sv,sha256=woX7UBWvg_mtnrBKSel60p269d1sFgGelzgA5kISxew,2020
37
+ peakrdl_busdecoder/cpuif/apb4/apb4_tmpl.sv,sha256=mWxiuW3CWfxxbSLk5AKoogqGZvltKLce_j9swnOiQng,2002
38
38
  peakrdl_busdecoder/cpuif/axi4lite/__init__.py,sha256=5XuWfPK2jDzr6egKUDJFr8l3k3lW-feLIh-lN7Mo8Ks,145
39
- peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py,sha256=bSHP_xYczv30-F62wZYe3rqma458qi6sqSzLAKApiGE,5056
40
- peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py,sha256=47yz1o6yoGFyoIswdka946n_kkwsApUhqYO_xNKekR4,3868
39
+ peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif.py,sha256=gMByBQ4rWUhOorLSdEjUIdp_f27Ty-H9SJ5QLz12JT0,6353
40
+ peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_cpuif_flat.py,sha256=gzXmQX15e0OZcYaXDvXNqQhGLqSHM3qkGCs7qk_lNf8,4410
41
41
  peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_interface.py,sha256=EXW-nPJwMF_oCPdJ4XmreiLwhnpqSca9iViosh2rEXM,3721
42
- peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_tmpl.sv,sha256=ketPrq715LSEs8Ar9ecXgnSe2AUAdQ70oNVmDbXc2Tc,3351
42
+ peakrdl_busdecoder/cpuif/axi4lite/axi4_lite_tmpl.sv,sha256=Ybn4eN4YDiecRWbK2oGn45uPbVsXFgpIHVjJN1ZDpkc,3969
43
43
  peakrdl_busdecoder/udps/__init__.py,sha256=gPc74OMVWTIr5vgtFArzbhEyi1OYjllR3ZFwHJ8APaY,106
44
- peakrdl_busdecoder-0.6.5.dist-info/licenses/LICENSE,sha256=eAMIGRcnsTDZVr4qelHkJ49Rd_IiDY4_MVHU7N0UWSw,7646
45
- peakrdl_busdecoder-0.6.5.dist-info/METADATA,sha256=OVIXfBAAbfNLR-3lgk6QSMWaV-KecglM3m7KPPMUq7c,2797
46
- peakrdl_busdecoder-0.6.5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
- peakrdl_busdecoder-0.6.5.dist-info/entry_points.txt,sha256=7Xzgt-C2F4cQu1kRLpZa0MbXSFFMC1SWEDnZkY0GH7s,73
48
- peakrdl_busdecoder-0.6.5.dist-info/top_level.txt,sha256=ZIYuTsl8cYby4g8tNR_JGzbYYTrG9mqYLSBqnY1Gpmk,19
49
- peakrdl_busdecoder-0.6.5.dist-info/RECORD,,
44
+ peakrdl_busdecoder-0.6.7.dist-info/licenses/LICENSE,sha256=eAMIGRcnsTDZVr4qelHkJ49Rd_IiDY4_MVHU7N0UWSw,7646
45
+ peakrdl_busdecoder-0.6.7.dist-info/METADATA,sha256=kvs6x9WKSfxv8oBspcedzbNYkQt61vxe8VNRl0YrYkc,2797
46
+ peakrdl_busdecoder-0.6.7.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
47
+ peakrdl_busdecoder-0.6.7.dist-info/entry_points.txt,sha256=7Xzgt-C2F4cQu1kRLpZa0MbXSFFMC1SWEDnZkY0GH7s,73
48
+ peakrdl_busdecoder-0.6.7.dist-info/top_level.txt,sha256=ZIYuTsl8cYby4g8tNR_JGzbYYTrG9mqYLSBqnY1Gpmk,19
49
+ peakrdl_busdecoder-0.6.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5