axi_dmac: Limit number of bursts on the source side
Currently the source side of the DMAC can issue requests for up to 2*FIFO_SIZE-1 bursts even though there is only room for FIFO_SIZE bursts in the store and forward memory. This can problematic for memory mapped buses. If the data is not read fast enough from the DMAC back-pressure will propagate through the whole system memory subsystem and can cause significant performance penalty or even a deadlock halting the whole system. To avoid this make sure that not more that than what fits into the store-and-forward memory is requested by throttling the request ID based on how much room is available in the memory. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>main
parent
d80175d895
commit
7d643e216a
|
@ -48,6 +48,8 @@ module axi_dmac_burst_memory #(
|
|||
input [DATA_WIDTH_SRC-1:0] src_data,
|
||||
input src_data_last,
|
||||
|
||||
output [ID_WIDTH-1:0] src_data_request_id,
|
||||
|
||||
input dest_clk,
|
||||
input dest_reset,
|
||||
|
||||
|
@ -159,6 +161,8 @@ assign src_beat = src_mem_data_valid & src_mem_data_ready;
|
|||
assign src_last_beat = src_beat & src_mem_data_last;
|
||||
assign src_waddr = {src_id_reduced,src_beat_counter};
|
||||
|
||||
assign src_data_request_id = src_dest_id;
|
||||
|
||||
always @(*) begin
|
||||
if (src_last_beat == 1'b1) begin
|
||||
src_id_next <= inc_id(src_id);
|
||||
|
|
|
@ -251,6 +251,8 @@ wire [1:0] src_response_resp;
|
|||
*/
|
||||
|
||||
wire [ID_WIDTH-1:0] src_request_id;
|
||||
reg [ID_WIDTH-1:0] src_throttled_request_id;
|
||||
wire [ID_WIDTH-1:0] src_data_request_id;
|
||||
wire [ID_WIDTH-1:0] src_response_id;
|
||||
|
||||
wire src_valid;
|
||||
|
@ -542,7 +544,7 @@ dmac_src_mm_axi #(
|
|||
.response_resp(src_response_resp),
|
||||
*/
|
||||
|
||||
.request_id(src_request_id),
|
||||
.request_id(src_throttled_request_id),
|
||||
.response_id(src_response_id),
|
||||
.address_id(src_address_id),
|
||||
.data_id(src_data_id),
|
||||
|
@ -615,7 +617,7 @@ dmac_src_axi_stream #(
|
|||
.req_sync_transfer_start(src_req_sync_transfer_start),
|
||||
.req_xlast(src_req_xlast),
|
||||
|
||||
.request_id(src_request_id),
|
||||
.request_id(src_throttled_request_id),
|
||||
.response_id(src_response_id),
|
||||
|
||||
.eot(src_eot),
|
||||
|
@ -671,7 +673,7 @@ dmac_src_fifo_inf #(
|
|||
.req_last_burst_length(src_req_last_burst_length),
|
||||
.req_sync_transfer_start(src_req_sync_transfer_start),
|
||||
|
||||
.request_id(src_request_id),
|
||||
.request_id(src_throttled_request_id),
|
||||
.response_id(src_response_id),
|
||||
|
||||
.eot(src_eot),
|
||||
|
@ -705,6 +707,39 @@ sync_bits #(
|
|||
.out(src_request_id)
|
||||
);
|
||||
|
||||
`include "inc_id.h"
|
||||
|
||||
function compare_id;
|
||||
input [ID_WIDTH-1:0] a;
|
||||
input [ID_WIDTH-1:0] b;
|
||||
begin
|
||||
compare_id = a[ID_WIDTH-1] == b[ID_WIDTH-1];
|
||||
if (ID_WIDTH >= 2) begin
|
||||
if (a[ID_WIDTH-2] == b[ID_WIDTH-2]) begin
|
||||
compare_id = 1'b1;
|
||||
end
|
||||
end
|
||||
if (ID_WIDTH >= 3) begin
|
||||
if (a[ID_WIDTH-3:0] != b[ID_WIDTH-3:0]) begin
|
||||
compare_id = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
/*
|
||||
* Make sure that we do not request more data than what fits into the
|
||||
* store-and-forward burst memory.
|
||||
*/
|
||||
always @(posedge src_clk) begin
|
||||
if (src_resetn == 1'b0) begin
|
||||
src_throttled_request_id <= 'h00;
|
||||
end else if (src_throttled_request_id != src_request_id &&
|
||||
compare_id(src_throttled_request_id, src_data_request_id)) begin
|
||||
src_throttled_request_id <= inc_id(src_throttled_request_id);
|
||||
end
|
||||
end
|
||||
|
||||
sync_bits #(
|
||||
.NUM_OF_BITS(ID_WIDTH),
|
||||
.ASYNC_CLK(ASYNC_CLK_DEST_REQ)
|
||||
|
@ -744,6 +779,8 @@ axi_dmac_burst_memory #(
|
|||
.src_data(src_fifo_data),
|
||||
.src_data_last(src_fifo_last),
|
||||
|
||||
.src_data_request_id(src_data_request_id),
|
||||
|
||||
.dest_clk(dest_clk),
|
||||
.dest_reset(~dest_resetn),
|
||||
.dest_data_valid(dest_fifo_valid),
|
||||
|
|
Loading…
Reference in New Issue