From dd8d9c8f5f23f1e562be4cf8746e6981a0bfa91c Mon Sep 17 00:00:00 2001 From: FallenSigh Date: Wed, 1 Jul 2026 21:59:57 +0800 Subject: [PATCH] Add CDMA matmul sequencer --- rtl/ip/cdma/snix_axil_cdma_mux.sv | 568 ++++++++++++++++++++++-- sdk/axi_ram.mif | 256 +++-------- sdk/software/examples/asm/dma.h | 17 + sdk/software/examples/asm/user-sample.c | 129 +----- 4 files changed, 625 insertions(+), 345 deletions(-) diff --git a/rtl/ip/cdma/snix_axil_cdma_mux.sv b/rtl/ip/cdma/snix_axil_cdma_mux.sv index 4a4757b..b04e5d4 100644 --- a/rtl/ip/cdma/snix_axil_cdma_mux.sv +++ b/rtl/ip/cdma/snix_axil_cdma_mux.sv @@ -122,6 +122,30 @@ module snix_axil_cdma_mux #( localparam logic [1:0] MODE_MEM2MEM = 2'd0; localparam logic [1:0] MODE_MEM2EP = 2'd1; localparam logic [1:0] MODE_EP2MEM = 2'd2; + + localparam logic [7:0] SEQ_REG_CTRL = 8'h00; + localparam logic [7:0] SEQ_REG_STATUS = 8'h04; + localparam logic [7:0] SEQ_REG_SRC_BASE = 8'h08; + localparam logic [7:0] SEQ_REG_DST_BASE = 8'h0C; + localparam logic [7:0] SEQ_REG_GROUPS = 8'h10; + localparam logic [7:0] SEQ_REG_MAT_BASE = 8'h14; + localparam logic [7:0] SEQ_REG_SRC_STRIDE = 8'h18; + localparam logic [7:0] SEQ_REG_DST_STRIDE = 8'h1C; + + localparam logic [11:0] MAT_CTRL_OFF = 12'h000; + localparam logic [11:0] MAT_STATUS_OFF = 12'h004; + localparam logic [11:0] MAT_CRC_OFF = 12'h010; + localparam logic [11:0] MAT_B0_AB_OFF = 12'h100; + localparam logic [11:0] MAT_B0_C_OFF = 12'h180; + localparam logic [11:0] MAT_B1_AB_OFF = 12'h300; + localparam logic [11:0] MAT_B1_C_OFF = 12'h380; + + localparam logic [31:0] MAT_STATUS_DONE_CLR = 32'h0000_0006; + localparam logic [31:0] MAT_STATUS_DONE_BIT = 32'h0000_0002; + localparam logic [31:0] MAT_CTRL_START_B0 = 32'h0000_0001; + localparam logic [31:0] MAT_CTRL_START_B1 = 32'h0000_0002; + localparam logic [31:0] MAT_AB_BYTES = 32'd128; + localparam logic [31:0] MAT_C_BYTES = 32'd192; // Function to safely apply WSTRB to 32-bit registers function automatic logic [31:0] apply_wstrb( @@ -153,6 +177,17 @@ module snix_axil_cdma_mux #( logic [PORTS-1:0] arb_set_done; // From Arbiter to CSR + logic [31:0] seq_src_base; + logic [31:0] seq_dst_base; + logic [31:0] seq_groups; + logic [31:0] seq_mat_base; + logic [31:0] seq_src_stride; + logic [31:0] seq_dst_stride; + logic seq_busy; + logic seq_done_flag; + wire seq_start_req; + wire seq_done_clear_req; + // ========================================== // Address Decoding (0x40 offset per channel) // ========================================== @@ -160,6 +195,14 @@ module snix_axil_cdma_mux #( wire [5:0] wr_reg = s_axil_awaddr[5:0]; wire [CH_BITS-1:0] rd_ch = s_axil_araddr[6 +: CH_BITS]; wire [5:0] rd_reg = s_axil_araddr[5:0]; + wire wr_seq_reg = (s_axil_awaddr[11:8] == 4'h2); + wire rd_seq_reg = (s_axil_araddr[11:8] == 4'h2); + wire [7:0] wr_seq_off = s_axil_awaddr[7:0]; + wire [7:0] rd_seq_off = s_axil_araddr[7:0]; + assign seq_start_req = do_write && wr_seq_reg && (wr_seq_off == SEQ_REG_CTRL) && + s_axil_wstrb[0] && s_axil_wdata[0]; + assign seq_done_clear_req = do_write && wr_seq_reg && (wr_seq_off == SEQ_REG_STATUS) && + s_axil_wstrb[0] && s_axil_wdata[1]; // ========================================== // AXI-Lite Slave Logic (Robust Backpressure) @@ -219,7 +262,19 @@ module snix_axil_cdma_mux #( end else begin if (do_read) begin s_axil_rvalid <= 1'b1; - if (rd_ch < PORTS) begin + if (rd_seq_reg) begin + case (rd_seq_off) + SEQ_REG_CTRL: s_axil_rdata <= {31'd0, seq_start_req}; + SEQ_REG_STATUS: s_axil_rdata <= {30'd0, seq_done_flag, seq_busy}; + SEQ_REG_SRC_BASE: s_axil_rdata <= seq_src_base; + SEQ_REG_DST_BASE: s_axil_rdata <= seq_dst_base; + SEQ_REG_GROUPS: s_axil_rdata <= seq_groups; + SEQ_REG_MAT_BASE: s_axil_rdata <= seq_mat_base; + SEQ_REG_SRC_STRIDE: s_axil_rdata <= seq_src_stride; + SEQ_REG_DST_STRIDE: s_axil_rdata <= seq_dst_stride; + default: s_axil_rdata <= 32'd0; + endcase + end else if (rd_ch < PORTS) begin case (rd_reg) 6'h00: s_axil_rdata <= ch_src_addr[rd_ch]; 6'h04: s_axil_rdata <= ch_dst_addr[rd_ch]; @@ -249,6 +304,12 @@ module snix_axil_cdma_mux #( if (!rst_n) begin ch_req <= '0; ch_done <= '0; + seq_src_base <= 32'h0; + seq_dst_base <= 32'h0; + seq_groups <= 32'h0; + seq_mat_base <= 32'h1f50_0000; + seq_src_stride <= 32'd128; + seq_dst_stride <= 32'd192; for (int i=0; i 32'd4)) begin + op_src_cur <= op_src_cur + 32'd4; + op_dst_cur <= op_dst_cur + 32'd4; + op_bytes_left <= op_bytes_left - 32'd4; + op_state <= OP_READ_ADDR; + end else begin + op_done <= 1'b1; + op_state <= OP_IDLE; + end + end + end + + OP_REG_READ_ADDR: begin + if (seq_arvalid && seq_arready) + op_state <= OP_REG_READ_DATA; + end + + OP_REG_READ_DATA: begin + if (mm2mm_rvalid && seq_rready) begin + op_read_data <= mm2mm_rdata; + op_done <= 1'b1; + op_state <= OP_IDLE; + end + end + + OP_COPY_START: begin + op_state <= OP_COPY_WAIT; + end + + OP_COPY_WAIT: begin + if (mm2mm_done) begin + op_done <= 1'b1; + op_state <= OP_IDLE; + end + end + + default: op_state <= OP_IDLE; + endcase + end + end + + always_ff @(posedge clk) begin + if (!rst_n) begin + seq_state <= SQ_IDLE; + seq_busy <= 1'b0; + seq_done_flag <= 1'b0; + op_start_copy <= 1'b0; + op_start_write <= 1'b0; + op_start_read <= 1'b0; + op_src_addr <= '0; + op_dst_addr <= '0; + op_bytes <= '0; + op_write_addr <= '0; + op_write_data <= '0; + op_read_addr <= '0; + seq_group_idx <= '0; + seq_load_idx <= '0; + seq_store_idx <= '0; + seq_compute_bank <= 1'b0; + seq_status_data <= '0; + end else begin + op_start_copy <= 1'b0; + op_start_write <= 1'b0; + op_start_read <= 1'b0; + + if (seq_done_clear_req) + seq_done_flag <= 1'b0; + + case (seq_state) + SQ_IDLE: begin + seq_busy <= 1'b0; + if (seq_start_req && (seq_groups != 32'd0)) begin + seq_busy <= 1'b1; + seq_done_flag <= 1'b0; + seq_group_idx <= 32'd0; + seq_load_idx <= 32'd0; + seq_store_idx <= 32'd0; + seq_compute_bank <= 1'b0; + op_write_addr <= seq_mat_base + MAT_CRC_OFF; + op_write_data <= 32'd0; + op_start_write <= 1'b1; + seq_state <= SQ_CLEAR_CRC; + end + end + + SQ_CLEAR_CRC: begin + if (op_done) begin + op_src_addr <= seq_src_base; + op_dst_addr <= seq_mat_base + MAT_B0_AB_OFF; + op_bytes <= MAT_AB_BYTES; + op_start_copy <= 1'b1; + seq_load_idx <= 32'd1; + seq_state <= SQ_LOAD0; + end + end + + SQ_LOAD0: begin + if (op_done) begin + op_write_addr <= seq_mat_base + MAT_CTRL_OFF; + op_write_data <= MAT_CTRL_START_B0; + op_start_write <= 1'b1; + seq_state <= SQ_START0; + end + end + + SQ_START0: begin + if (op_done) begin + if (seq_load_idx < seq_groups) begin + op_src_addr <= seq_src_base + (seq_load_idx * seq_src_stride); + op_dst_addr <= seq_mat_base + MAT_B1_AB_OFF; + op_bytes <= MAT_AB_BYTES; + op_start_copy <= 1'b1; + seq_load_idx <= seq_load_idx + 32'd1; + seq_state <= SQ_LOAD1; + end else begin + op_read_addr <= seq_mat_base + MAT_STATUS_OFF; + op_start_read <= 1'b1; + seq_state <= SQ_WAIT_DONE; + end + end + end + + SQ_LOAD1: begin + if (op_done) begin + op_read_addr <= seq_mat_base + MAT_STATUS_OFF; + op_start_read <= 1'b1; + seq_state <= SQ_WAIT_DONE; + end + end + + SQ_WAIT_DONE: begin + if (op_done) begin + seq_status_data <= op_read_data; + if ((op_read_data & MAT_STATUS_DONE_BIT) != 32'd0) begin + seq_store_idx <= seq_group_idx; + if ((seq_group_idx + 32'd1) >= seq_groups) begin + op_src_addr <= seq_mat_base + (seq_compute_bank ? MAT_B1_C_OFF : MAT_B0_C_OFF); + op_dst_addr <= seq_dst_base + (seq_group_idx * seq_dst_stride); + op_bytes <= MAT_C_BYTES; + op_start_copy <= 1'b1; + seq_state <= SQ_STORE; + end else begin + op_write_addr <= seq_mat_base + MAT_STATUS_OFF; + op_write_data <= MAT_STATUS_DONE_CLR; + op_start_write <= 1'b1; + seq_state <= SQ_CLEAR_DONE; + end + end else begin + op_read_addr <= seq_mat_base + MAT_STATUS_OFF; + op_start_read <= 1'b1; + end + end + end + + SQ_STORE: begin + if (op_done) begin + if ((seq_group_idx + 32'd1) >= seq_groups) begin + seq_state <= SQ_DONE; + end else if (seq_has_more_load) begin + op_src_addr <= seq_src_addr_for_load; + op_dst_addr <= seq_dst_addr_for_load; + op_bytes <= MAT_AB_BYTES; + op_start_copy <= 1'b1; + seq_load_idx <= seq_load_idx + 32'd1; + seq_state <= SQ_LOAD_NEXT; + end else begin + op_read_addr <= seq_mat_base + MAT_STATUS_OFF; + op_start_read <= 1'b1; + seq_state <= SQ_WAIT_DONE; + end + end + end + + SQ_CLEAR_DONE: begin + if (op_done) begin + seq_group_idx <= seq_group_idx + 32'd1; + seq_compute_bank <= ~seq_compute_bank; + op_write_addr <= seq_mat_base + MAT_CTRL_OFF; + op_write_data <= (~seq_compute_bank) ? MAT_CTRL_START_B1 : MAT_CTRL_START_B0; + op_start_write <= 1'b1; + seq_state <= SQ_START_NEXT; + end + end + + SQ_START_NEXT: begin + if (op_done) begin + op_src_addr <= seq_src_addr_for_store; + op_dst_addr <= seq_dst_addr_for_store; + op_bytes <= MAT_C_BYTES; + op_start_copy <= 1'b1; + seq_state <= SQ_STORE; + end + end + + SQ_LOAD_NEXT: begin + if (op_done) begin + op_read_addr <= seq_mat_base + MAT_STATUS_OFF; + op_start_read <= 1'b1; + seq_state <= SQ_WAIT_DONE; + end + end + + SQ_DONE: begin + seq_busy <= 1'b0; + seq_done_flag <= 1'b1; + seq_state <= SQ_IDLE; + end + + default: seq_state <= SQ_IDLE; + endcase + end + end + // ========================================== // Endpoint transfer engine (32-bit only in this SoC integration) // ========================================== diff --git a/sdk/axi_ram.mif b/sdk/axi_ram.mif index bc43ad7..5b103ec 100644 --- a/sdk/axi_ram.mif +++ b/sdk/axi_ram.mif @@ -52,7 +52,7 @@ 00000011100000000110000000001101 00000100000000000000000110101100 00011100000000000000000000101100 -00000010101110101111000110001100 +00000010101100111111000110001100 00011100000000000001000000001101 00000010101111001001000110101101 00011100000000000001000000001110 @@ -94,7 +94,7 @@ 00000000000101010000000000001110 00101001000000000001000110101110 00011100000000000000000000001100 -00000010100100110001000110001100 +00000010100011000001000110001100 00000100000000000011000000101100 00000011100000000000010000001101 00000100000000010001000000101101 @@ -142,17 +142,13 @@ 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 -00000010101111110100000001100011 -00000010100000000000100000001101 -00000010100000000000010000001110 +00000010101111111000000001100011 00010101011111100000000000010000 -00101001100000000110000001101110 -00101001100000000111000001101101 -00101001100000001011000001100001 -00101001100000001010000001110111 +00101001100000000111000001100001 +00101001100000000110000001110111 00000010100000010011010000001100 00011100000000000001000000001111 -00000010101101100111000111101111 +00000010101101101011000111101111 00000011100000000001011000001101 00101001100000000011000001101100 00101010000000000011000001101110 @@ -164,134 +160,36 @@ 00101001000000000000001000001110 00101000000000000000000111101100 01011111111111111101110110000000 -01010100000001111110100000000000 -00010101011111101010000000001100 -00000011100000000001000110001110 -00000010100000000001100000001111 -00101001100000000000000111001111 -00000011100000000100000110001101 -00101001100000000000000110100000 +01010100000001100011100000000000 00010101011111100110000000001100 -00010100001110001000000000010010 -00101001100000000000000110010010 -00101001100000000001000110000000 +00000011100010000000000110001100 +00000010100000000000100000001110 +00101001100000000001000110001110 +00010100001110001000000000001101 +00101001100000000010000110001101 +00000011100101000000000110110011 +00000010100000000010100000010010 +00101001100000000011000110010011 +00101001100000000100000110010010 +00010100001111101010000000010001 00000010100000100000000000010000 -00101001100000000010000110010000 -00000010100000000000010000001111 -00101001100000000110000110001111 -00000011101111110100010000001110 -00101001100000000111000110000000 +00101001100000000101000110010001 +00101001100000000110000110010000 +00000010100000110000000000001111 +00000010100000000000010000001110 +00101001100000000111000110001111 00000000000101010000000010010111 -00010101011111100110000000010001 -00101001100000000100000110001110 -00101000100000000101001000101100 -00000011010000000000100110001100 -01011011111111111111100110000000 -00000010100000000000100000001100 -00101001100000000101001000101100 -00101000100000000110000001100101 -00010100001110001000000000010100 -00010101011111101010000000010010 -00101001100000000000001001000101 -00000011100000100000001010001110 -00101001100000000000001000101110 -00101001100000000001001000100000 -00000010100000100000000000000100 -00101001100000000010001000100100 -00000010100000000000010000001100 -00000011101111110100010000000111 -00010100001110001001001110001001 -00010101011111101010000000001010 -00010101011111100110000000001101 -00010100000000000000000000100110 -00101001100000000110001000101100 -00101001100000000111001000101100 -00101001100000000100001000100111 -00000011100100000000000100101001 -00000011100001000000001010010100 -00000010100000000000010000010000 -00000010100000000000010000010011 -00000011100000000001000101001111 -00000011100011100001110011000110 -00000010100000000000100000010010 -00000010100000000000010000000101 -00000011100000010000000110101110 -00000010100000110000000000001000 -00000011101111110100010000000100 -00000010100000100000000000000111 -00000011110000000000011000010001 -00101000100000000000000111101100 -00000011010000000000100110001100 -01011011111111111111100110000000 -00101001100000000000000111110010 -01011000000000000001101001100101 +00000000000101010000000110001101 +00101001100000000000000110001110 00000011010000000000000000000000 -00101000100000000101000111001100 -00000011010000000000100110001100 -01011011111111111111100110000000 -00101001100000000101000111010010 -00101001100000000000000111000000 -00101001100000000001000111001001 -00101001100000000010000111001000 -00101001100000000110000111010010 -00101001100000000111000111010001 -00101001100000000100000111000100 -00101000100000000101000110101100 -00000011010000000000100110001100 -01011011111111111111100110000000 -00000010100000001000000001101100 -00000000010000001000101000010000 -00101001100000000101000110110010 -00000000000100000100000110010000 -00101000101111111110001000001100 -00101001100000000000000101001100 -01011000000000000011001001100110 -00101001100000000000000110110100 -00101001100000000001000110100000 -00101001100000000010000110100111 -00101001100000000110000110100101 -00101001100000000111000110110001 -00000010100000000000011001110011 -00000010100000100000001010010100 -00000010100000110000000100101001 -00000000000101010000001000110000 -00101001100000000100000110100100 -01010011111111110110111111111111 -00010101011111101010000000001110 -00000011100000000001000111001110 -00101000100000000000000111001100 +00101000100000000001000110101100 00000011010000000000100110001100 01011011111111111111100110000000 00000010100000000000100000001100 -00010101011111100110000000001101 -00101001100000000000000111001100 -00000011100000010000000110101101 -00101000100000000101000110101100 -00000011010000000000100110001100 -01011011111111111111100110000000 -00000010100000000000100000001111 -00101001100000000101000110101111 -00010100001110001011000011001100 -00101001100000000000000110100000 -00000010100000110000000000010010 -00000011101001010000000110001100 00101001100000000001000110101100 -00101001100000000010000110110010 -00000010100000000000010000010001 -00000011101111110100010000010000 -00010101011111100110000000001110 -00101001100000000110000110101111 -00101001100000000111000110110001 -00000011100000010000000111001110 -00101001100000000100000110110000 -00101000100000000101000111001100 -00000011010000000000100110001100 -01011011111111111111100110000000 -00000010100000000000100000001100 -00101001100000000101000111001100 -01010100000001011111010000000000 +01010100000001011100110000000000 00011100000000000001000000001110 -00000010101011110010000111001110 +00000010101101011000000111001110 00101000100000000000000111010010 00010101011111101010000000001101 00010100000000000001111010001100 @@ -299,16 +197,46 @@ 00010101011111100000000000010000 00000011100010010000000110001110 00000000000100010101110010000100 -00000000001000010011101001010001 +00000000001000010011101001010011 01011100000000000000100111000000 00000000001010100000000000000111 -00101000100000000000000110110100 -00000000001000010100010010010010 -01011100000000000000101000100000 +00101000100000000000000110110001 +00000000001000010100110010010010 +01011100000000000000101001100000 00000000001010100000000000000111 00000010100000010011010000001100 00011100000000000001000000001111 -00000010101011001111000111101111 +00000010101100110101000111101111 +00000011100000000001011000001101 +00101001100000000011000001101100 +00101010000000000011000001101110 +00000010100000000000010111101111 +00101010000000000000000110101100 +00000011010000001000000110001100 +01011011111111111111100110000000 +00101001000000000000001000001110 +00101000000000000000000111101100 +01011111111111111110000110000000 +00010101011111100000000000010000 +00000010100000000111000000001110 +00000010100000000010010000010100 +00000010101111111111000000010011 +00000011100000000001011000001101 +00000000000101111011101000101100 +00000011010000000011110110001100 +00000010100000010101110110001111 +01101000000000000000101010001100 +00000010100000001100000110001111 +00101010000000000000000110101100 +00000011010000001000000110001100 +01011011111111111111100110000000 +00101001000000000000001000001111 +00000010101111111111000111001110 +01011111111111111101100111010011 +00010101011111100000000000010000 +00000010100000000011010000001100 +00011100000000000001000000001111 +00000010101100011011000111101111 00000011100000000001011000001101 00101001100000000011000001101100 00101010000000000011000001101110 @@ -320,57 +248,28 @@ 00101001000000000000001000001110 00101000000000000000000111101100 01011111111111111101110110000000 -00010101011111100000000000010000 -00000010100000000111000000001110 -00000010100000000010010000010011 -00000010101111111111000000010001 -00000011100000000001011000001101 -00000000000101111011101010001100 -00000011010000000011110110001100 -00000010100000010101110110001111 -01101000000000000000101001101100 -00000010100000001100000110001111 -00101010000000000000000110101100 -00000011010000001000000110001100 -01011011111111111111100110000000 -00101001000000000000001000001111 -00000010101111111111000111001110 -01011111111111111101100111010001 +01010100000000101001100000000000 00010101011111100000000000010000 00000010100000000011010000001100 00011100000000000001000000001111 -00000010101010110100000111101111 +00000010101100010000000111101111 00000011100000000001011000001101 00101001100000000011000001101100 00101010000000000011000001101110 00000010100000000000010111101111 +00000011010000000000000000000000 00101010000000000000000110101100 00000011010000001000000110001100 01011011111111111111100110000000 00101001000000000000001000001110 00101000000000000000000111101100 -01011111111111111110000110000000 -01010100000000101100000000000000 -00010101011111100000000000010000 -00000010100000000011010000001100 -00011100000000000001000000001111 -00000010101010101010000111101111 -00000011100000000001011000001101 -00101001100000000011000001101100 -00101010000000000011000001101110 -00000010100000000000010111101111 -00101010000000000000000110101100 -00000011010000001000000110001100 -01011011111111111111100110000000 -00101001000000000000001000001110 -00101000000000000000000111101100 -01011111111111111110000110000000 +01011111111111111101110110000000 00000000000101010000001001000100 -01010100000000101000000000000000 +01010100000000100101010000000000 00010101011111100000000000010000 00000010100000000011010000001100 00011100000000000001000000001111 -00000010101010011111000111101111 +00000010101100000100000111101111 00000011100000000001011000001101 00101001100000000011000001101100 00101010000000000011000001101110 @@ -381,23 +280,12 @@ 00101001000000000000001000001110 00101000000000000000000111101100 01011111111111111110000110000000 -00101000100000001011000001100001 -00101000100000001010000001110111 +00101000100000000111000001100001 +00101000100000000110000001110111 00000000000101010000000000000100 -00000010100000001100000001100011 +00000010100000001000000001100011 01001100000000000000000000100000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 -00000000000000000000000000000000 +00000011010000000000000000000000 00000010101111100001000001100011 00101001100000011110000001100001 00101001100000011101000001100010 diff --git a/sdk/software/examples/asm/dma.h b/sdk/software/examples/asm/dma.h index 86dfc34..405f0de 100644 --- a/sdk/software/examples/asm/dma.h +++ b/sdk/software/examples/asm/dma.h @@ -18,6 +18,19 @@ typedef struct { #define CDMA_MUX_BASE 0xbf300000 #define DMA_CH(i) ((volatile dma_ch_regs_t*)(CDMA_MUX_BASE + (i) * 0x40)) +typedef struct { + volatile u32 CTRL; // 0x200: bit0 start + volatile u32 STATUS; // 0x204: bit0 busy, bit1 done (W1C) + volatile u32 SRC_BASE; // 0x208 + volatile u32 DST_BASE; // 0x20C + volatile u32 GROUPS; // 0x210 + volatile u32 MAT_BASE; // 0x214 + volatile u32 SRC_STRIDE; // 0x218 + volatile u32 DST_STRIDE; // 0x21C +} dma_seq_regs_t; + +#define DMA_SEQ ((volatile dma_seq_regs_t*)(CDMA_MUX_BASE + 0x200)) + // CTRL 寄存器位定义 #define CTRL_START_BIT (1 << 0) #define CTRL_BURST_SIZE(x) (((x) & 0x7) << 3) // Bits [5:3]: AXI AxSIZE (0=1B, 1=2B, 2=4B, 3=8B) @@ -33,5 +46,9 @@ typedef struct { #define STATUS_BUSY_BIT (1 << 0) #define STATUS_DONE_BIT (1 << 1) +#define SEQ_START_BIT (1 << 0) +#define SEQ_BUSY_BIT (1 << 0) +#define SEQ_DONE_BIT (1 << 1) + void dma_start_transfer(int ch_id, u32 src, u32 dst, u32 bytes, u32 tag); void dma_wait_polling(int ch_id); diff --git a/sdk/software/examples/asm/user-sample.c b/sdk/software/examples/asm/user-sample.c index d31a9a0..213b6c1 100644 --- a/sdk/software/examples/asm/user-sample.c +++ b/sdk/software/examples/asm/user-sample.c @@ -82,6 +82,7 @@ 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 CTRL_START_B0 0x1 #define CTRL_START_B1 0x2 @@ -100,132 +101,26 @@ int main(void) if (MATMUL_GROUP_NUM <= 0) return 0; /* ── Hot-path local volatile pointers (one-time addr calc) ──────── */ - volatile unsigned int *mat_status = (volatile unsigned int *)MATMUL_STATUS; - volatile unsigned int *mat_ctrl = (volatile unsigned int *)MATMUL_CTRL; volatile unsigned int *mat_crc = (volatile unsigned int *)MATMUL_CRC; - volatile dma_ch_regs_t *ch0 = DMA_CH(0); - volatile dma_ch_regs_t *ch1 = DMA_CH(1); + volatile dma_seq_regs_t *seq = DMA_SEQ; unsigned int crc; unsigned int cycle_start, cycle_end, cycles, time_us; - int g, bank; - - unsigned int ctrl_start[2] = {CTRL_START_B0, CTRL_START_B1}; /* ── Start marker (must be first output) ──────────────────── */ uart_puts("MATMUL_START\r\n"); cycle_start = get_clock_count(); - // Reset IP state - *mat_status = STATUS_DONE | STATUS_ERROR; - *mat_crc = 0; - - /* ═══════════════════════════════════════════════════════════════ - * PROLOGUE: Load group 0 → Bank 0, start IP, pre-fire group 1 - * ═══════════════════════════════════════════════════════════════ */ - - // DMA Ch0: Load group 0 A+B (128 bytes) → IP Bank 0 - ch0->SRC_ADDR = EXTRAM_PHYS_AB(0); - ch0->DST_ADDR = 0; - ch0->LENGTH = 128; - ch0->MODE = DMA_MODE_MEM2EP; - ch0->EP_CFG = DMA_EP_CFG(MATMUL_EP_ID, 0, 0); - ch0->CTRL = DMA_CTRL_VAL; - while (!(ch0->STATUS & STATUS_DONE_BIT)) {} - ch0->STATUS = STATUS_DONE_BIT; - - // Start IP Bank 0 (group 0) - *mat_ctrl = ctrl_start[0]; - - // Pre-fire: DMA Ch0 load group 1 → Bank 1 (overlaps with IP compute) - if (MATMUL_GROUP_NUM > 1) { - ch0->SRC_ADDR = EXTRAM_PHYS_AB(1); - ch0->DST_ADDR = 0; - ch0->LENGTH = 128; - ch0->MODE = DMA_MODE_MEM2EP; - ch0->EP_CFG = DMA_EP_CFG(MATMUL_EP_ID, 1, 0); - ch0->CTRL = DMA_CTRL_VAL; - } - - /* ═══════════════════════════════════════════════════════════════ - * MAIN LOOP: Fully-pipelined — pre-fire DMA load at loop tail - * - * At iteration g: - * IP is computing group (g-1) on prev_bank - * Ch0 loaded group g to cur_bank (pre-fired in iteration g-1) - * - * Pipeline: - * Ch0: | load g+1 | | load g+2 | - * Ch1: | store g-1 | | store g | - * IP : | compute g | | compute g+1 | - * ═══════════════════════════════════════════════════════════════ */ - bank = 1; // cur_bank for iteration g=1; prev_bank = bank ^ 1 - - for (g = 1; g < MATMUL_GROUP_NUM; g++) { - int cur_bank = bank; - int prev_bank = bank ^ 1; - - // 1. Wait for previous IP computation (group g-1 on prev_bank) - while (!(*mat_status & STATUS_DONE)) {} - *mat_status = STATUS_DONE; - - // 2. Ensure previous DMA Ch1 store is done (group g-2) - if (g > 1) { - while (!(ch1->STATUS & STATUS_DONE_BIT)) {} - ch1->STATUS = STATUS_DONE_BIT; - } - - // 3. Start DMA Ch1 store: group (g-1) result → ExtRAM - ch1->SRC_ADDR = 0; - ch1->DST_ADDR = EXTRAM_PHYS_C(g - 1); - ch1->LENGTH = 192; - ch1->MODE = DMA_MODE_EP2MEM; - ch1->EP_CFG = DMA_EP_CFG(MATMUL_EP_ID, prev_bank, 0); - ch1->CTRL = DMA_CTRL_VAL; - - // 4. Wait for current DMA Ch0 load (group g → cur_bank, pre-fired in iteration g-1) - while (!(ch0->STATUS & STATUS_DONE_BIT)) {} - ch0->STATUS = STATUS_DONE_BIT; - - // 5. Start IP computation for current group on cur_bank - *mat_ctrl = ctrl_start[cur_bank]; - - // ★ 6. PRE-FIRE: DMA Ch0 load next group (g+1) → next_bank - // This runs CONCURRENTLY with IP computation started in step 5! - if (g < MATMUL_GROUP_NUM - 1) { - int next_bank = bank ^ 1; - ch0->SRC_ADDR = EXTRAM_PHYS_AB(g + 1); - ch0->DST_ADDR = 0; - ch0->LENGTH = 128; - ch0->MODE = DMA_MODE_MEM2EP; - ch0->EP_CFG = DMA_EP_CFG(MATMUL_EP_ID, next_bank, 0); - ch0->CTRL = DMA_CTRL_VAL; - } - - // Toggle bank for next iteration - bank ^= 1; - } - - /* ═══════════════════════════════════════════════════════════════ - * EPILOGUE: Flush the final group - * ═══════════════════════════════════════════════════════════════ */ - - // Wait for last IP computation - while (!(*mat_status & STATUS_DONE)) {} - *mat_status = STATUS_DONE; - - // Wait for previous DMA store and start/complete final store - while (!(ch1->STATUS & STATUS_DONE_BIT)) {} - ch1->STATUS = STATUS_DONE_BIT; - - ch1->SRC_ADDR = 0; - ch1->DST_ADDR = EXTRAM_PHYS_C(MATMUL_GROUP_NUM - 1); - ch1->LENGTH = 192; - ch1->MODE = DMA_MODE_EP2MEM; - ch1->EP_CFG = DMA_EP_CFG(MATMUL_EP_ID, (MATMUL_GROUP_NUM - 1) % 2, 0); - ch1->CTRL = DMA_CTRL_VAL; - while (!(ch1->STATUS & STATUS_DONE_BIT)) {} - ch1->STATUS = STATUS_DONE_BIT; + 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; cycle_end = get_clock_count(); cycles = cycle_end - cycle_start; time_us = cycles / (CORE_CLOCKS_PER_SEC / 1000000UL);