Add matmul AXI master path

This commit is contained in:
2026-07-01 23:13:28 +08:00
parent 2b6e29f761
commit fd03aaaaa1
4 changed files with 2198 additions and 1748 deletions

View File

@@ -95,6 +95,47 @@ module matmul_axi_slave (
output reg [31:0] ep_rd_data,
output ep_rd_ready,
// AXI master port for autonomous matrix stream load/store
output reg [3:0] m_axi_awid,
output reg [31:0] m_axi_awaddr,
output reg [7:0] m_axi_awlen,
output reg [2:0] m_axi_awsize,
output reg [1:0] m_axi_awburst,
output reg m_axi_awlock,
output reg [3:0] m_axi_awcache,
output reg [2:0] m_axi_awprot,
output reg m_axi_awvalid,
input m_axi_awready,
output reg [31:0] m_axi_wdata,
output reg [3:0] m_axi_wstrb,
output reg m_axi_wlast,
output reg m_axi_wvalid,
input m_axi_wready,
input [3:0] m_axi_bid,
input [1:0] m_axi_bresp,
input m_axi_bvalid,
output reg m_axi_bready,
output reg [3:0] m_axi_arid,
output reg [31:0] m_axi_araddr,
output reg [7:0] m_axi_arlen,
output reg [2:0] m_axi_arsize,
output reg [1:0] m_axi_arburst,
output reg m_axi_arlock,
output reg [3:0] m_axi_arcache,
output reg [2:0] m_axi_arprot,
output reg m_axi_arvalid,
input m_axi_arready,
input [3:0] m_axi_rid,
input [31:0] m_axi_rdata,
input [1:0] m_axi_rresp,
input m_axi_rlast,
input m_axi_rvalid,
output reg m_axi_rready,
// Interrupt output (active high level, pulsed by calc_done)
output intr
);
@@ -105,6 +146,11 @@ module matmul_axi_slave (
localparam ADDR_CTRL = 12'h000;
localparam ADDR_STATUS = 12'h004;
localparam ADDR_CRC = 12'h010;
localparam ADDR_DMA_SRC_BASE = 12'h020;
localparam ADDR_DMA_DST_BASE = 12'h024;
localparam ADDR_DMA_GROUPS = 12'h028;
localparam ADDR_DMA_SRC_STRIDE = 12'h02C;
localparam ADDR_DMA_DST_STRIDE = 12'h030;
localparam ADDR_B0_A = 12'h100;
localparam ADDR_B0_B = 12'h140;
@@ -131,6 +177,28 @@ module matmul_axi_slave (
reg [31:0] b1_b [0:15];
reg [65:0] b1_c [0:15];
reg [31:0] dma_src_base;
reg [31:0] dma_dst_base;
reg [31:0] dma_groups;
reg [31:0] dma_src_stride;
reg [31:0] dma_dst_stride;
reg dma_busy;
reg dma_done;
reg [31:0] load_group;
reg [31:0] store_group;
reg [31:0] completed_groups;
reg [1:0] bank_loaded;
reg [1:0] bank_store_pending;
reg [1:0] bank_storing;
reg [1:0] bank_compute_pending;
reg dma_compute_bank;
reg dma_load_bank;
reg dma_store_bank;
reg dma_start_pulse;
reg dma_done_clear_pulse;
reg dma_req0_pulse;
reg dma_req1_pulse;
assign ep_wr_ready = 1'b1;
assign ep_rd_ready = 1'b1;
@@ -177,12 +245,15 @@ module matmul_axi_slave (
reg [31:0] crc32_table [0:255];
reg [31:0] crc_reg;
wire [31:0] crc_stream_data = ep_rd_valid ? ep_rd_data : s_axi_rdata;
wire crc_dma_valid;
wire [31:0] crc_dma_data;
wire [31:0] crc_stream_data = crc_dma_valid ? crc_dma_data :
(ep_rd_valid ? ep_rd_data : s_axi_rdata);
wire crc_axi_valid = (r_state == R_DATA) && s_axi_rvalid && s_axi_rready &&
((r_offset >= ADDR_B0_C && r_offset < (ADDR_B0_C + 12'h0C0)) ||
(r_offset >= ADDR_B1_C && r_offset < (ADDR_B1_C + 12'h0C0)));
wire crc_ep_valid = ep_rd_valid && ep_rd_ready && (ep_rd_word_addr < 8'd48);
wire crc_stream_valid = crc_axi_valid || crc_ep_valid;
wire crc_stream_valid = crc_axi_valid || crc_ep_valid || crc_dma_valid;
wire [31:0] crc_t0, crc_c0, crc_t1, crc_c1, crc_t2, crc_c2, crc_t3, crc_next;
assign crc_t0 = crc32_table[(crc_reg[7:0] ^ crc_stream_data[7:0])];
@@ -348,6 +419,46 @@ module matmul_axi_slave (
reg [1:0] state;
reg cur_bank;
reg calc_done_pulse;
localparam DMA_RD_IDLE = 2'd0;
localparam DMA_RD_ADDR = 2'd1;
localparam DMA_RD_DATA = 2'd2;
reg [1:0] dma_rd_state;
reg [4:0] dma_rd_count;
reg dma_rd_bank;
wire [3:0] dma_rd_word_idx = dma_rd_count[3:0];
wire dma_rd_commit = (dma_rd_state == DMA_RD_DATA) && m_axi_rvalid && m_axi_rready;
localparam DMA_WR_IDLE = 2'd0;
localparam DMA_WR_ADDR = 2'd1;
localparam DMA_WR_DATA = 2'd2;
localparam DMA_WR_RESP = 2'd3;
reg [1:0] dma_wr_state;
reg [5:0] dma_wr_count;
wire [7:0] dma_wr_elem_raw = dma_wr_count / 6'd3;
wire [7:0] dma_wr_part_raw = dma_wr_count % 6'd3;
wire [3:0] dma_wr_elem = dma_wr_elem_raw[3:0];
wire [1:0] dma_wr_part = dma_wr_part_raw[1:0];
wire [65:0] dma_wr_c0 = b0_c[dma_wr_elem];
wire [65:0] dma_wr_c1 = b1_c[dma_wr_elem];
wire [65:0] dma_wr_c = dma_store_bank ? dma_wr_c1 : dma_wr_c0;
wire [31:0] dma_wr_word =
(dma_wr_part == 2'd0) ? dma_wr_c[31:0] :
(dma_wr_part == 2'd1) ? dma_wr_c[63:32] :
{30'b0, dma_wr_c[65:64]};
wire [5:0] dma_wr_next_count = dma_wr_count + 6'd1;
wire [7:0] dma_wr_next_elem_raw = dma_wr_next_count / 6'd3;
wire [7:0] dma_wr_next_part_raw = dma_wr_next_count % 6'd3;
wire [3:0] dma_wr_next_elem = dma_wr_next_elem_raw[3:0];
wire [1:0] dma_wr_next_part = dma_wr_next_part_raw[1:0];
wire [65:0] dma_wr_next_c0 = b0_c[dma_wr_next_elem];
wire [65:0] dma_wr_next_c1 = b1_c[dma_wr_next_elem];
wire [65:0] dma_wr_next_c = dma_store_bank ? dma_wr_next_c1 : dma_wr_next_c0;
wire [31:0] dma_wr_word_next =
(dma_wr_next_part == 2'd0) ? dma_wr_next_c[31:0] :
(dma_wr_next_part == 2'd1) ? dma_wr_next_c[63:32] :
{30'b0, dma_wr_next_c[65:64]};
// 【修改点 1】单独引出一个写脉冲信号给 CRC 清零用
wire crc_clear_pulse = (w_state == W_DATA) && s_axi_wvalid && s_axi_wready && (w_offset == ADDR_CRC);
@@ -364,7 +475,17 @@ module matmul_axi_slave (
req_1 <= 1'b0;
done_count <= 2'd0;
error <= 1'b0;
dma_src_base <= 32'd0;
dma_dst_base <= 32'd0;
dma_groups <= 32'd0;
dma_src_stride <= 32'd128;
dma_dst_stride <= 32'd192;
dma_start_pulse <= 1'b0;
dma_done_clear_pulse <= 1'b0;
end else begin
dma_start_pulse <= 1'b0;
dma_done_clear_pulse <= 1'b0;
if (ep_wr_valid && ep_wr_ready) begin
if (ep_wr_bank[0] == 1'b0) begin
if (ep_wr_word_addr < 8'd16)
@@ -383,8 +504,24 @@ module matmul_axi_slave (
end
end
if (dma_rd_commit) begin
if (dma_rd_bank == 1'b0) begin
if (dma_rd_count < 5'd16)
b0_a[dma_rd_word_idx] <= m_axi_rdata;
else
b0_b[dma_rd_word_idx] <= m_axi_rdata;
end else begin
if (dma_rd_count < 5'd16)
b1_a[dma_rd_word_idx] <= m_axi_rdata;
else
b1_b[dma_rd_word_idx] <= m_axi_rdata;
end
end
if (req_0 && state == C_RUN && cur_bank == 1'b0) req_0 <= 1'b0;
if (req_1 && state == C_RUN && cur_bank == 1'b1) req_1 <= 1'b0;
if (dma_req0_pulse) req_0 <= 1'b1;
if (dma_req1_pulse) req_1 <= 1'b1;
case (w_state)
W_IDLE: begin
@@ -403,10 +540,22 @@ module matmul_axi_slave (
if (w_offset == ADDR_CTRL) begin
if (s_axi_wdata[0]) req_0 <= 1'b1;
if (s_axi_wdata[1]) req_1 <= 1'b1;
if (s_axi_wdata[8]) dma_start_pulse <= 1'b1;
end
else if (w_offset == ADDR_STATUS) begin
if (s_axi_wdata[2]) error <= 1'b0;
if (s_axi_wdata[4]) dma_done_clear_pulse <= 1'b1;
end
else if (w_offset == ADDR_DMA_SRC_BASE)
dma_src_base <= apply_wstrb(dma_src_base, s_axi_wdata, s_axi_wstrb);
else if (w_offset == ADDR_DMA_DST_BASE)
dma_dst_base <= apply_wstrb(dma_dst_base, s_axi_wdata, s_axi_wstrb);
else if (w_offset == ADDR_DMA_GROUPS)
dma_groups <= apply_wstrb(dma_groups, s_axi_wdata, s_axi_wstrb);
else if (w_offset == ADDR_DMA_SRC_STRIDE)
dma_src_stride <= apply_wstrb(dma_src_stride, s_axi_wdata, s_axi_wstrb);
else if (w_offset == ADDR_DMA_DST_STRIDE)
dma_dst_stride <= apply_wstrb(dma_dst_stride, s_axi_wdata, s_axi_wstrb);
// 【修改点 2】删除 else if (w_offset == ADDR_CRC) { crc_reg <= ... } 防止多重驱动
else if (w_offset >= ADDR_B0_A && w_offset < ADDR_B0_B)
b0_a[(w_offset - ADDR_B0_A) >> 2] <= apply_wstrb(b0_a[(w_offset - ADDR_B0_A) >> 2], s_axi_wdata, s_axi_wstrb);
@@ -528,7 +677,17 @@ module matmul_axi_slave (
else if (current_r_offset == ADDR_CRC)
s_axi_rdata = crc_reg ^ 32'hFFFFFFFF;
else if (current_r_offset == ADDR_STATUS)
s_axi_rdata = {29'b0, error, done, busy};
s_axi_rdata = {27'b0, dma_done, dma_busy, error, done, busy};
else if (current_r_offset == ADDR_DMA_SRC_BASE)
s_axi_rdata = dma_src_base;
else if (current_r_offset == ADDR_DMA_DST_BASE)
s_axi_rdata = dma_dst_base;
else if (current_r_offset == ADDR_DMA_GROUPS)
s_axi_rdata = dma_groups;
else if (current_r_offset == ADDR_DMA_SRC_STRIDE)
s_axi_rdata = dma_src_stride;
else if (current_r_offset == ADDR_DMA_DST_STRIDE)
s_axi_rdata = dma_dst_stride;
else if (current_r_offset >= ADDR_B0_A && current_r_offset < ADDR_B0_B)
s_axi_rdata = b0_a[(current_r_offset - ADDR_B0_A) >> 2];
else if (current_r_offset >= ADDR_B0_B && current_r_offset < ADDR_B0_C)
@@ -709,6 +868,206 @@ module matmul_axi_slave (
end
end
// ==========================================
// Autonomous AXI master loader/storer
// ==========================================
assign crc_dma_valid = (dma_wr_state == DMA_WR_DATA) && m_axi_wvalid && m_axi_wready;
assign crc_dma_data = m_axi_wdata;
always @(posedge clk) begin
if (!resetn) begin
dma_busy <= 1'b0;
dma_done <= 1'b0;
load_group <= 32'd0;
store_group <= 32'd0;
completed_groups <= 32'd0;
bank_loaded <= 2'b00;
bank_store_pending <= 2'b00;
bank_storing <= 2'b00;
bank_compute_pending <= 2'b00;
dma_compute_bank <= 1'b0;
dma_load_bank <= 1'b0;
dma_store_bank <= 1'b0;
dma_rd_state <= DMA_RD_IDLE;
dma_rd_count <= 5'd0;
dma_rd_bank <= 1'b0;
dma_wr_state <= DMA_WR_IDLE;
dma_wr_count <= 6'd0;
m_axi_arid <= 4'd0;
m_axi_araddr <= 32'd0;
m_axi_arlen <= 8'd31;
m_axi_arsize <= 3'd2;
m_axi_arburst <= 2'b01;
m_axi_arlock <= 1'b0;
m_axi_arcache <= 4'b0;
m_axi_arprot <= 3'b0;
m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b0;
m_axi_awid <= 4'd0;
m_axi_awaddr <= 32'd0;
m_axi_awlen <= 8'd47;
m_axi_awsize <= 3'd2;
m_axi_awburst <= 2'b01;
m_axi_awlock <= 1'b0;
m_axi_awcache <= 4'b0;
m_axi_awprot <= 3'b0;
m_axi_awvalid <= 1'b0;
m_axi_wdata <= 32'd0;
m_axi_wstrb <= 4'hF;
m_axi_wlast <= 1'b0;
m_axi_wvalid <= 1'b0;
m_axi_bready <= 1'b0;
dma_req0_pulse <= 1'b0;
dma_req1_pulse <= 1'b0;
end else begin
dma_req0_pulse <= 1'b0;
dma_req1_pulse <= 1'b0;
if (dma_done_clear_pulse)
dma_done <= 1'b0;
if (dma_start_pulse && !dma_busy && dma_groups != 32'd0) begin
dma_busy <= 1'b1;
dma_done <= 1'b0;
load_group <= 32'd0;
store_group <= 32'd0;
completed_groups <= 32'd0;
bank_loaded <= 2'b00;
bank_store_pending <= 2'b00;
bank_storing <= 2'b00;
bank_compute_pending <= 2'b00;
dma_compute_bank <= 1'b0;
dma_load_bank <= 1'b0;
dma_store_bank <= 1'b0;
dma_rd_state <= DMA_RD_IDLE;
dma_wr_state <= DMA_WR_IDLE;
end
if (dma_busy) begin
if (state == C_RUN)
bank_compute_pending[cur_bank] <= 1'b0;
if (bank_loaded[0] && !req_0 && !bank_store_pending[0] && !bank_storing[0] &&
!bank_compute_pending[0] && !(state == C_RUN && cur_bank == 1'b0)) begin
dma_req0_pulse <= 1'b1;
bank_loaded[0] <= 1'b0;
bank_compute_pending[0] <= 1'b1;
dma_compute_bank <= 1'b0;
end else if (bank_loaded[1] && !req_1 && !bank_store_pending[1] && !bank_storing[1] &&
!bank_compute_pending[1] && !(state == C_RUN && cur_bank == 1'b1)) begin
dma_req1_pulse <= 1'b1;
bank_loaded[1] <= 1'b0;
bank_compute_pending[1] <= 1'b1;
dma_compute_bank <= 1'b1;
end
end
if (calc_done_pulse && dma_busy) begin
bank_store_pending[cur_bank] <= 1'b1;
end
case (dma_rd_state)
DMA_RD_IDLE: begin
m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b0;
if (dma_busy && load_group < dma_groups && !bank_loaded[dma_load_bank] &&
!bank_compute_pending[dma_load_bank] &&
!((dma_load_bank == 1'b0) ? req_0 : req_1) &&
!(state == C_RUN && cur_bank == dma_load_bank)) begin
dma_rd_bank <= dma_load_bank;
dma_rd_count <= 5'd0;
m_axi_araddr <= dma_src_base + (load_group * dma_src_stride);
m_axi_arlen <= 8'd31;
m_axi_arsize <= 3'd2;
m_axi_arburst <= 2'b01;
m_axi_arvalid <= 1'b1;
dma_rd_state <= DMA_RD_ADDR;
end
end
DMA_RD_ADDR: begin
if (m_axi_arvalid && m_axi_arready) begin
m_axi_arvalid <= 1'b0;
m_axi_rready <= 1'b1;
dma_rd_state <= DMA_RD_DATA;
end
end
DMA_RD_DATA: begin
if (m_axi_rvalid && m_axi_rready) begin
if (m_axi_rlast) begin
m_axi_rready <= 1'b0;
bank_loaded[dma_rd_bank] <= 1'b1;
load_group <= load_group + 32'd1;
dma_load_bank <= ~dma_load_bank;
dma_rd_state <= DMA_RD_IDLE;
end else begin
dma_rd_count <= dma_rd_count + 5'd1;
end
end
end
default: dma_rd_state <= DMA_RD_IDLE;
endcase
case (dma_wr_state)
DMA_WR_IDLE: begin
m_axi_awvalid <= 1'b0;
m_axi_wvalid <= 1'b0;
m_axi_bready <= 1'b0;
if (dma_busy && bank_store_pending[dma_store_bank]) begin
dma_wr_count <= 6'd0;
bank_store_pending[dma_store_bank] <= 1'b0;
bank_storing[dma_store_bank] <= 1'b1;
m_axi_awaddr <= dma_dst_base + (store_group * dma_dst_stride);
m_axi_awlen <= 8'd47;
m_axi_awsize <= 3'd2;
m_axi_awburst <= 2'b01;
m_axi_awvalid <= 1'b1;
dma_wr_state <= DMA_WR_ADDR;
end
end
DMA_WR_ADDR: begin
if (m_axi_awvalid && m_axi_awready) begin
m_axi_awvalid <= 1'b0;
m_axi_wvalid <= 1'b1;
m_axi_wdata <= dma_wr_word;
m_axi_wlast <= 1'b0;
dma_wr_state <= DMA_WR_DATA;
end
end
DMA_WR_DATA: begin
if (m_axi_wvalid && m_axi_wready) begin
if (dma_wr_count == 6'd47) begin
m_axi_wvalid <= 1'b0;
m_axi_wlast <= 1'b0;
m_axi_bready <= 1'b1;
dma_wr_state <= DMA_WR_RESP;
end else begin
dma_wr_count <= dma_wr_count + 6'd1;
m_axi_wdata <= dma_wr_word_next;
m_axi_wlast <= (dma_wr_count == 6'd46);
end
end
end
DMA_WR_RESP: begin
if (m_axi_bvalid && m_axi_bready) begin
m_axi_bready <= 1'b0;
bank_storing[dma_store_bank] <= 1'b0;
dma_store_bank <= ~dma_store_bank;
store_group <= store_group + 32'd1;
completed_groups <= completed_groups + 32'd1;
if ((completed_groups + 32'd1) >= dma_groups) begin
dma_busy <= 1'b0;
dma_done <= 1'b1;
end
dma_wr_state <= DMA_WR_IDLE;
end
end
default: dma_wr_state <= DMA_WR_IDLE;
endcase
end
end
assign intr = done;
endmodule

File diff suppressed because it is too large Load Diff

View File

@@ -52,7 +52,7 @@
00000011100000000110000000001101
00000100000000000000000110101100
00011100000000000000000000101100
00000010101100111111000110001100
00000010101101001111000110001100
00011100000000000001000000001101
00000010101111001001000110101101
00011100000000000001000000001110
@@ -94,7 +94,7 @@
00000000000101010000000000001110
00101001000000000001000110101110
00011100000000000000000000001100
00000010100011000001000110001100
00000010100011010001000110001100
00000100000000000011000000101100
00000011100000000000010000001101
00000100000000010001000000101101
@@ -146,67 +146,70 @@
00010101011111100000000000010000
00101001100000000111000001100001
00101001100000000110000001110111
00101001100000000101000001111000
00000010100000010011010000001100
00011100000000000001000000001111
00000010101101101011000111101111
00000010101101101010000111101111
00000011100000000001011000001101
00101001100000000011000001101100
00101010000000000011000001101110
00000010100000000000010111101111
00000011010000000000000000000000
00101010000000000000000110101100
00000011010000001000000110001100
01011011111111111111100110000000
00101001000000000000001000001110
00101000000000000000000111101100
01011111111111111101110110000000
01010100000001100011100000000000
00010101011111100110000000001100
00000011100010000000000110001100
00000010100000000000100000001110
00101001100000000001000110001110
00010100001110001000000000001101
00101001100000000010000110001101
00000011100101000000000110110011
00000010100000000010100000010010
00101001100000000011000110010011
00101001100000000100000110010010
00010100001111101010000000010001
00000010100000100000000000010000
00101001100000000101000110010001
00101001100000000110000110010000
00000010100000110000000000001111
00000010100000000000010000001110
00101001100000000111000110001111
00000000000101010000000010010111
00000000000101010000000110001101
01011111111111111110000110000000
01010100000001100111100000000000
00010101011111101010000000001100
00000011100000000100000110010001
00101001100000000000001000100000
00000010100000000101100000010000
00000011100000000001000110001101
00101001100000000000000110110000
00010100001110001000000000001110
00000011100000001000000110001111
00101001100000000000000111101110
00000011100101000000000111000101
00000000000101010000000010011000
00000011100000001001000110000100
00101001100000000000000010000101
00000011100000001010000110010011
00000010100000000010100000010100
00101001100000000000001001110100
00000011100000001011000110010001
00000010100000100000000000010010
00101001100000000000001000110010
00000011100000001100000110001111
00000010100000110000000000010000
00000010100001000000000000001110
00101001100000000000000111110000
00010101011111101010000000010111
00101001100000000000000110001110
00000011010000000000000000000000
00101000100000000001000110101100
00000011010000000000100110001100
00101000100000000000000110101100
00000011010000000100000110001100
01011011111111111111100110000000
00000010100000000000100000001100
00101001100000000001000110101100
01010100000001011100110000000000
00011100000000000001000000001110
00000010101101011000000111001110
00101000100000000000000111010010
00010101011111101010000000001101
00000010100000000100000000001100
00101001100000000000000110101100
01010100000001011111110000000000
00011100000000000001000000001101
00000010101101010100000110101101
00000011100000000100001011110111
00101000100000000000000110110010
00101000100000000000001011110001
00010100000000000001111010001100
00000011100000000100000110101101
00010101011111100000000000010000
00000011100010010000000110001110
00000000000100010101110010000100
00000000000100010110000010000100
00000000001000010011101001010011
01011100000000000000100111000000
00000000001010100000000000000111
00101000100000000000000110110001
00000010100000010011010000001100
00000000001000010100110010010010
01011100000000000000101001100000
00000000001010100000000000000111
00000010100000010011010000001100
00011100000000000001000000001111
00000010101100110101000111101111
00000010101100110010000111101111
00000011100000000001011000001101
00101001100000000011000001101100
00101010000000000011000001101110
@@ -222,6 +225,7 @@
00000010100000000010010000010100
00000010101111111111000000010011
00000011100000000001011000001101
00000011010000000000000000000000
00000000000101111011101000101100
00000011010000000011110110001100
00000010100000010101110110001111
@@ -236,7 +240,7 @@
00010101011111100000000000010000
00000010100000000011010000001100
00011100000000000001000000001111
00000010101100011011000111101111
00000010101100010111000111101111
00000011100000000001011000001101
00101001100000000011000001101100
00101010000000000011000001101110
@@ -248,11 +252,11 @@
00101001000000000000001000001110
00101000000000000000000111101100
01011111111111111101110110000000
01010100000000101001100000000000
01010100000000101100100000000000
00010101011111100000000000010000
00000010100000000011010000001100
00011100000000000001000000001111
00000010101100010000000111101111
00000010101100001100000111101111
00000011100000000001011000001101
00101001100000000011000001101100
00101010000000000011000001101110
@@ -265,11 +269,11 @@
00101000000000000000000111101100
01011111111111111101110110000000
00000000000101010000001001000100
01010100000000100101010000000000
01010100000000101000010000000000
00010101011111100000000000010000
00000010100000000011010000001100
00011100000000000001000000001111
00000010101100000100000111101111
00000010101100000000000111101111
00000011100000000001011000001101
00101001100000000011000001101100
00101010000000000011000001101110
@@ -282,10 +286,22 @@
01011111111111111110000110000000
00101000100000000111000001100001
00101000100000000110000001110111
00101000100000000101000001111000
00000000000101010000000000000100
00000010100000001000000001100011
01001100000000000000000000100000
00000011010000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000000000000000000000000000000
00000010101111100001000001100011
00101001100000011110000001100001
00101001100000011101000001100010

View File

@@ -1,13 +1,7 @@
/**
* user-sample - CIC-IEC 2026 Stage 3 Evaluation Program
*
* (ULTIMATE PERFORMANCE DMA + PING-PONG BUFFER ARCHITECTURE v2)
*
* Optimizations over v1:
* 1. Pre-fire DMA Ch0 load at loop tail → fully overlaps with IP compute
* 2. Inlined wait loops → zero function-call overhead in hot path
* 3. Inlined DMA start → skips redundant STATUS_BUSY_BIT check
* 4. XOR bank toggle → avoids g%2 recomputation per iteration
* Matmul AXI-master path.
*/
#include <dma.h>
@@ -82,12 +76,19 @@ unsigned long CORE_CLOCKS_PER_SEC = 33000000L;
#define MATMUL_CTRL (MATMUL_BASE_UNCACHED + 0x000)
#define MATMUL_STATUS (MATMUL_BASE_UNCACHED + 0x004)
#define MATMUL_BASE_PHYS_FOR_DMA MATMUL_BASE_PHYS
#define MATMUL_DMA_SRC_BASE (MATMUL_BASE_UNCACHED + 0x020)
#define MATMUL_DMA_DST_BASE (MATMUL_BASE_UNCACHED + 0x024)
#define MATMUL_DMA_GROUPS (MATMUL_BASE_UNCACHED + 0x028)
#define MATMUL_DMA_SRC_STRIDE (MATMUL_BASE_UNCACHED + 0x02C)
#define MATMUL_DMA_DST_STRIDE (MATMUL_BASE_UNCACHED + 0x030)
#define CTRL_START_B0 0x1
#define CTRL_START_B1 0x2
#define CTRL_DMA_START (1 << 8)
#define STATUS_DONE 0x2
#define STATUS_ERROR 0x4
#define STATUS_DMA_BUSY (1 << 3)
#define STATUS_DMA_DONE (1 << 4)
#define MATMUL_CRC (MATMUL_BASE_UNCACHED + 0x010)
@@ -101,8 +102,9 @@ int main(void)
if (MATMUL_GROUP_NUM <= 0) return 0;
/* ── Hot-path local volatile pointers (one-time addr calc) ──────── */
volatile unsigned int *mat_crc = (volatile unsigned int *)MATMUL_CRC;
volatile dma_seq_regs_t *seq = DMA_SEQ;
volatile unsigned int *mat_ctrl = (volatile unsigned int *)MATMUL_CTRL;
volatile unsigned int *mat_status = (volatile unsigned int *)MATMUL_STATUS;
volatile unsigned int *mat_crc = (volatile unsigned int *)MATMUL_CRC;
unsigned int crc;
unsigned int cycle_start, cycle_end, cycles, time_us;
@@ -111,16 +113,16 @@ int main(void)
uart_puts("MATMUL_START\r\n");
cycle_start = get_clock_count();
seq->STATUS = SEQ_DONE_BIT;
seq->SRC_BASE = EXTRAM_PHYS_AB(0);
seq->DST_BASE = EXTRAM_PHYS_C(0);
seq->GROUPS = MATMUL_GROUP_NUM;
seq->MAT_BASE = MATMUL_BASE_PHYS_FOR_DMA;
seq->SRC_STRIDE = 128;
seq->DST_STRIDE = 192;
seq->CTRL = SEQ_START_BIT;
while (!(seq->STATUS & SEQ_DONE_BIT)) {}
seq->STATUS = SEQ_DONE_BIT;
*(volatile unsigned int *)MATMUL_CRC = 0;
*mat_status = STATUS_DMA_DONE | STATUS_DONE | STATUS_ERROR;
*(volatile unsigned int *)MATMUL_DMA_SRC_BASE = EXTRAM_PHYS_AB(0);
*(volatile unsigned int *)MATMUL_DMA_DST_BASE = EXTRAM_PHYS_C(0);
*(volatile unsigned int *)MATMUL_DMA_GROUPS = MATMUL_GROUP_NUM;
*(volatile unsigned int *)MATMUL_DMA_SRC_STRIDE = 128;
*(volatile unsigned int *)MATMUL_DMA_DST_STRIDE = 192;
*mat_ctrl = CTRL_DMA_START;
while (!(*mat_status & STATUS_DMA_DONE)) {}
*mat_status = STATUS_DMA_DONE;
cycle_end = get_clock_count();
cycles = cycle_end - cycle_start;
time_us = cycles / (CORE_CLOCKS_PER_SEC / 1000000UL);