@@ -9,9 +9,10 @@ if TYPE_CHECKING:
|
||||
from systemrdl.node import AddrmapNode
|
||||
|
||||
class Readback:
|
||||
def __init__(self, exp:'RegblockExporter', do_fanin_stage: bool):
|
||||
def __init__(self, exp:'RegblockExporter', do_fanin_stage: bool, has_external_addressable: bool):
|
||||
self.exp = exp
|
||||
self.do_fanin_stage = do_fanin_stage
|
||||
self.has_external_addressable = has_external_addressable
|
||||
|
||||
@property
|
||||
def top_node(self) -> 'AddrmapNode':
|
||||
@@ -33,6 +34,7 @@ class Readback:
|
||||
"get_always_ff_event": lambda resetsignal : get_always_ff_event(self.exp.dereferencer, resetsignal),
|
||||
"cpuif": self.exp.cpuif,
|
||||
"do_fanin_stage": self.do_fanin_stage,
|
||||
"has_external_addressable": self.has_external_addressable,
|
||||
}
|
||||
|
||||
if self.do_fanin_stage:
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
from typing import TYPE_CHECKING, List
|
||||
|
||||
from systemrdl.node import RegNode
|
||||
from systemrdl.node import RegNode, AddressableNode
|
||||
from systemrdl.walker import WalkerAction
|
||||
|
||||
from ..forloop_generator import RDLForLoopGenerator, LoopBody
|
||||
|
||||
@@ -77,9 +78,26 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator):
|
||||
self.current_offset = start_offset + n_regs * dim
|
||||
|
||||
|
||||
def enter_Reg(self, node: RegNode) -> None:
|
||||
def enter_AddressableComponent(self, node: 'AddressableNode') -> WalkerAction:
|
||||
super().enter_AddressableComponent(node)
|
||||
|
||||
if node.external and not isinstance(node, RegNode):
|
||||
# External block
|
||||
strb = self.exp.hwif.get_external_rd_ack(node)
|
||||
data = self.exp.hwif.get_external_rd_data(node)
|
||||
self.add_content(f"assign readback_array[{self.current_offset_str}] = {strb} ? {data} : '0;")
|
||||
self.current_offset += 1
|
||||
return WalkerAction.SkipDescendants
|
||||
|
||||
return WalkerAction.Continue
|
||||
|
||||
def enter_Reg(self, node: RegNode) -> WalkerAction:
|
||||
if node.external:
|
||||
self.process_external_reg(node)
|
||||
return WalkerAction.SkipDescendants
|
||||
|
||||
if not node.has_sw_readable:
|
||||
return
|
||||
return WalkerAction.SkipDescendants
|
||||
|
||||
accesswidth = node.get_property('accesswidth')
|
||||
regwidth = node.get_property('regwidth')
|
||||
@@ -100,6 +118,19 @@ class ReadbackAssignmentGenerator(RDLForLoopGenerator):
|
||||
else:
|
||||
self.process_reg(node)
|
||||
|
||||
return WalkerAction.SkipDescendants
|
||||
|
||||
def process_external_reg(self, node: RegNode) -> None:
|
||||
strb = self.exp.hwif.get_external_rd_ack(node)
|
||||
data = self.exp.hwif.get_external_rd_data(node)
|
||||
regwidth = node.get_property('regwidth')
|
||||
if regwidth < self.exp.cpuif.data_width:
|
||||
self.add_content(f"assign readback_array[{self.current_offset_str}][{self.exp.cpuif.data_width-1}:{regwidth}] = '0;")
|
||||
self.add_content(f"assign readback_array[{self.current_offset_str}][{regwidth-1}:0] = {strb} ? {data} : '0;")
|
||||
else:
|
||||
self.add_content(f"assign readback_array[{self.current_offset_str}] = {strb} ? {data} : '0;")
|
||||
|
||||
self.current_offset += 1
|
||||
|
||||
def process_reg(self, node: RegNode) -> None:
|
||||
current_bit = 0
|
||||
|
||||
@@ -35,7 +35,11 @@ always_ff @(posedge clk) begin
|
||||
readback_done_r <= '0;
|
||||
end else begin
|
||||
readback_array_r <= readback_array_c;
|
||||
{%- if has_external_addressable %}
|
||||
readback_done_r <= decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
|
||||
{%- else %}
|
||||
readback_done_r <= decoded_req & ~decoded_req_is_wr;
|
||||
{%- endif %}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -54,7 +58,11 @@ end
|
||||
// Reduce the array
|
||||
always_comb begin
|
||||
automatic logic [{{cpuif.data_width-1}}:0] readback_data_var;
|
||||
{%- if has_external_addressable %}
|
||||
readback_done = decoded_req & ~decoded_req_is_wr & ~decoded_strb_is_external;
|
||||
{%- else %}
|
||||
readback_done = decoded_req & ~decoded_req_is_wr;
|
||||
{%- endif %}
|
||||
readback_err = '0;
|
||||
readback_data_var = '0;
|
||||
for(int i=0; i<{{array_size}}; i++) readback_data_var |= readback_array[i];
|
||||
|
||||
Reference in New Issue
Block a user