diff --git a/fpga/app/template/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py b/fpga/app/template/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py index 65e5f626f..b6bfd55dc 100644 --- a/fpga/app/template/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py +++ b/fpga/app/template/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py @@ -379,7 +379,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") for interface in tb.driver.interfaces: - await interface.ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await interface.ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(interface.tx_queue_count): await interface.ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -513,7 +513,7 @@ async def run_test_nic(dut): tb.log.info("All interface 0 ports") for port in tb.driver.interfaces[0].ports: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(port.interface.tx_queue_count): if k % len(tb.driver.interfaces[0].ports) == port.index: await port.schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -539,7 +539,7 @@ async def run_test_nic(dut): tb.loopback_enable = False for port in tb.driver.interfaces[0].ports[1:]: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000000) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000000) tb.log.info("Read statistics counters") diff --git a/fpga/common/rtl/mqnic_core.v b/fpga/common/rtl/mqnic_core.v index 0e268aa20..9450ac4fb 100644 --- a/fpga/common/rtl/mqnic_core.v +++ b/fpga/common/rtl/mqnic_core.v @@ -43,10 +43,14 @@ either expressed or implied, of The Regents of the University of California. module mqnic_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1234, 16'h0000}, - parameter BOARD_VER = {16'd0, 16'd1}, + parameter FPGA_ID = 32'hDEADBEEF, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 16'h1234_0000, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -140,6 +144,7 @@ module mqnic_core # parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT), parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8), parameter AXIL_CSR_PASSTHROUGH_ENABLE = 0, + parameter RB_NEXT_PTR = 0, // AXI lite interface configuration (application control) parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, @@ -378,6 +383,16 @@ parameter AXIS_IF_KEEP_WIDTH = AXIS_SYNC_KEEP_WIDTH; parameter AXIS_IF_TX_USER_WIDTH = AXIS_TX_USER_WIDTH; parameter AXIS_IF_RX_USER_WIDTH = AXIS_RX_USER_WIDTH; +localparam PHC_RB_BASE_ADDR = 32'h100; + +// check configuration +initial begin + if (RB_NEXT_PTR > 0 && RB_NEXT_PTR < 16'h200) begin + $error("Error: RB_NEXT_PTR overlaps block (instance %m)"); + $finish; + end +end + // parameter sizing helpers function [31:0] w_32(input [31:0] val); w_32 = val; @@ -533,16 +548,34 @@ always @(posedge clk) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 8'h00: ctrl_reg_rd_data_reg <= FW_ID; // fw_id - 8'h04: ctrl_reg_rd_data_reg <= FW_VER; // fw_ver - 8'h08: ctrl_reg_rd_data_reg <= BOARD_ID; // board_id - 8'h0C: ctrl_reg_rd_data_reg <= BOARD_VER; // board_ver - 8'h10: ctrl_reg_rd_data_reg <= 1; // phc_count - 8'h14: ctrl_reg_rd_data_reg <= 16'h0200; // phc_offset - 8'h18: ctrl_reg_rd_data_reg <= 16'h0080; // phc_stride - 8'h20: ctrl_reg_rd_data_reg <= IF_COUNT; // if_count - 8'h24: ctrl_reg_rd_data_reg <= 2**AXIL_IF_CTRL_ADDR_WIDTH; // if_stride - 8'h2C: ctrl_reg_rd_data_reg <= 2**AXIL_CSR_ADDR_WIDTH; // if_csr_offset + // FW ID + 8'h00: ctrl_reg_rd_data_reg <= 32'hffffffff; // FW ID: Type + 8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // FW ID: Version + 8'h08: ctrl_reg_rd_data_reg <= 32'h40; // FW ID: Next header + 8'h0C: ctrl_reg_rd_data_reg <= FPGA_ID; // FW ID: FPGA JTAG ID + 8'h10: ctrl_reg_rd_data_reg <= FW_ID; // FW ID: Firmware ID + 8'h14: ctrl_reg_rd_data_reg <= FW_VER; // FW ID: Firmware version + 8'h18: ctrl_reg_rd_data_reg <= BOARD_ID; // FW ID: Board ID + 8'h1C: ctrl_reg_rd_data_reg <= BOARD_VER; // FW ID: Board version + 8'h20: ctrl_reg_rd_data_reg <= BUILD_DATE; // FW ID: Build date + 8'h24: ctrl_reg_rd_data_reg <= GIT_HASH; // FW ID: Git commit hash + 8'h28: ctrl_reg_rd_data_reg <= RELEASE_INFO; // FW ID: Release info + // Interface + 8'h40: ctrl_reg_rd_data_reg <= 32'h0000C000; // Interface: Type + 8'h44: ctrl_reg_rd_data_reg <= 32'h00000100; // Interface: Version + 8'h48: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 32'h60 : PHC_RB_BASE_ADDR; // Interface: Next header + 8'h4C: ctrl_reg_rd_data_reg <= 32'h0; // Interface: Offset + 8'h50: ctrl_reg_rd_data_reg <= IF_COUNT; // Interface: Count + 8'h54: ctrl_reg_rd_data_reg <= 2**AXIL_IF_CTRL_ADDR_WIDTH; // Interface: Stride + 8'h58: ctrl_reg_rd_data_reg <= 2**AXIL_CSR_ADDR_WIDTH; // Interface: CSR offset + // Stats + 8'h60: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 32'h0000C004 : 0; // Stats: Type + 8'h64: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 32'h00000100 : 0; // Stats: Version + 8'h68: ctrl_reg_rd_data_reg <= STAT_ENABLE ? PHC_RB_BASE_ADDR : 0; // Stats: Next header + 8'h6C: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 2**16 : 0; // Stats: Offset + 8'h70: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 2**STAT_ID_WIDTH : 0; // Stats: Count + 8'h74: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 8 : 0; // Stats: Stride + 8'h78: ctrl_reg_rd_data_reg <= STAT_ENABLE ? 32'h00000000 : 0; // Stats: Flags default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -561,9 +594,11 @@ mqnic_ptp #( .PTP_PERIOD_FNS(PTP_PERIOD_FNS), .PTP_PEROUT_ENABLE(PTP_PEROUT_ENABLE), .PTP_PEROUT_COUNT(PTP_PEROUT_COUNT), - .REG_ADDR_WIDTH(8), + .REG_ADDR_WIDTH(AXIL_CTRL_ADDR_WIDTH), .REG_DATA_WIDTH(AXIL_CTRL_DATA_WIDTH), - .REG_STRB_WIDTH(AXIL_CTRL_STRB_WIDTH) + .REG_STRB_WIDTH(AXIL_CTRL_STRB_WIDTH), + .RB_BASE_ADDR(PHC_RB_BASE_ADDR), + .RB_NEXT_PTR(RB_NEXT_PTR) ) mqnic_ptp_inst ( .clk(clk), @@ -575,11 +610,11 @@ mqnic_ptp_inst ( .reg_wr_addr(ctrl_reg_wr_addr), .reg_wr_data(ctrl_reg_wr_data), .reg_wr_strb(ctrl_reg_wr_strb), - .reg_wr_en(ctrl_reg_wr_en && (ctrl_reg_wr_addr >> 8 == 2)), + .reg_wr_en(ctrl_reg_wr_en), .reg_wr_wait(ptp_ctrl_reg_wr_wait), .reg_wr_ack(ptp_ctrl_reg_wr_ack), .reg_rd_addr(ctrl_reg_rd_addr), - .reg_rd_en(ctrl_reg_rd_en && (ctrl_reg_rd_addr >> 8 == 2)), + .reg_rd_en(ctrl_reg_rd_en), .reg_rd_data(ptp_ctrl_reg_rd_data), .reg_rd_wait(ptp_ctrl_reg_rd_wait), .reg_rd_ack(ptp_ctrl_reg_rd_ack), diff --git a/fpga/common/rtl/mqnic_core_axi.v b/fpga/common/rtl/mqnic_core_axi.v index aa0678197..0c82d95e7 100644 --- a/fpga/common/rtl/mqnic_core_axi.v +++ b/fpga/common/rtl/mqnic_core_axi.v @@ -43,10 +43,14 @@ either expressed or implied, of The Regents of the University of California. module mqnic_core_axi # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1234, 16'h0000}, - parameter BOARD_VER = {16'd0, 16'd1}, + parameter FPGA_ID = 32'hDEADBEEF, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 16'h1234_0000, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -143,6 +147,7 @@ module mqnic_core_axi # parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT), parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8), parameter AXIL_CSR_PASSTHROUGH_ENABLE = 0, + parameter RB_NEXT_PTR = 0, // AXI lite interface configuration (application control) parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, @@ -534,10 +539,14 @@ dma_if_axi_inst ( mqnic_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -631,6 +640,7 @@ mqnic_core #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(AXIL_CSR_PASSTHROUGH_ENABLE), + .RB_NEXT_PTR(RB_NEXT_PTR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/common/rtl/mqnic_core_pcie.v b/fpga/common/rtl/mqnic_core_pcie.v index 022484de2..23acb0900 100644 --- a/fpga/common/rtl/mqnic_core_pcie.v +++ b/fpga/common/rtl/mqnic_core_pcie.v @@ -43,10 +43,14 @@ either expressed or implied, of The Regents of the University of California. module mqnic_core_pcie # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1234, 16'h0000}, - parameter BOARD_VER = {16'd0, 16'd1}, + parameter FPGA_ID = 32'hDEADBEEF, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 16'h1234_0000, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -152,6 +156,7 @@ module mqnic_core_pcie # parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT), parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8), parameter AXIL_CSR_PASSTHROUGH_ENABLE = 0, + parameter RB_NEXT_PTR = 0, // AXI lite interface configuration (application control) parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, @@ -1290,10 +1295,14 @@ endgenerate mqnic_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1387,6 +1396,7 @@ mqnic_core #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(AXIL_CSR_PASSTHROUGH_ENABLE), + .RB_NEXT_PTR(RB_NEXT_PTR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/common/rtl/mqnic_core_pcie_s10.v b/fpga/common/rtl/mqnic_core_pcie_s10.v index dbc1be318..0d5450c90 100644 --- a/fpga/common/rtl/mqnic_core_pcie_s10.v +++ b/fpga/common/rtl/mqnic_core_pcie_s10.v @@ -43,10 +43,14 @@ either expressed or implied, of The Regents of the University of California. module mqnic_core_pcie_s10 # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1234, 16'h0000}, - parameter BOARD_VER = {16'd0, 16'd1}, + parameter FPGA_ID = 32'hDEADBEEF, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 16'h1234_0000, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -149,6 +153,7 @@ module mqnic_core_pcie_s10 # parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT), parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8), parameter AXIL_CSR_PASSTHROUGH_ENABLE = 0, + parameter RB_NEXT_PTR = 0, // AXI lite interface configuration (application control) parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, @@ -559,10 +564,14 @@ pcie_s10_if_inst ( mqnic_core_pcie #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -668,6 +677,7 @@ mqnic_core_pcie #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(AXIL_CSR_PASSTHROUGH_ENABLE), + .RB_NEXT_PTR(RB_NEXT_PTR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/common/rtl/mqnic_core_pcie_us.v b/fpga/common/rtl/mqnic_core_pcie_us.v index c9a4e3ad0..b48c77d8b 100644 --- a/fpga/common/rtl/mqnic_core_pcie_us.v +++ b/fpga/common/rtl/mqnic_core_pcie_us.v @@ -43,10 +43,14 @@ either expressed or implied, of The Regents of the University of California. module mqnic_core_pcie_us # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1234, 16'h0000}, - parameter BOARD_VER = {16'd0, 16'd1}, + parameter FPGA_ID = 32'hDEADBEEF, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 16'h1234_0000, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -150,6 +154,7 @@ module mqnic_core_pcie_us # parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT), parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8), parameter AXIL_CSR_PASSTHROUGH_ENABLE = 0, + parameter RB_NEXT_PTR = 0, // AXI lite interface configuration (application control) parameter AXIL_APP_CTRL_DATA_WIDTH = AXIL_CTRL_DATA_WIDTH, @@ -649,10 +654,14 @@ pcie_if_inst ( mqnic_core_pcie #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -758,6 +767,7 @@ mqnic_core_pcie #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(AXIL_CSR_PASSTHROUGH_ENABLE), + .RB_NEXT_PTR(RB_NEXT_PTR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/common/rtl/mqnic_interface.v b/fpga/common/rtl/mqnic_interface.v index a25053d5b..6281dae96 100644 --- a/fpga/common/rtl/mqnic_interface.v +++ b/fpga/common/rtl/mqnic_interface.v @@ -370,6 +370,7 @@ parameter QUEUE_REQ_TAG_WIDTH = $clog2(MAX_DESC_TABLE_SIZE) + 1 + $clog2(PORTS+1 parameter QUEUE_OP_TAG_WIDTH = 6; parameter DMA_TAG_WIDTH_INT = DMA_TAG_WIDTH - $clog2(PORTS); +parameter DMA_CLIENT_LEN_WIDTH = DMA_LEN_WIDTH; parameter QUEUE_INDEX_WIDTH = TX_QUEUE_INDEX_WIDTH > RX_QUEUE_INDEX_WIDTH ? TX_QUEUE_INDEX_WIDTH : RX_QUEUE_INDEX_WIDTH; parameter CPL_QUEUE_INDEX_WIDTH = TX_CPL_QUEUE_INDEX_WIDTH > RX_CPL_QUEUE_INDEX_WIDTH ? TX_CPL_QUEUE_INDEX_WIDTH : RX_CPL_QUEUE_INDEX_WIDTH; @@ -394,7 +395,11 @@ parameter AXIL_RX_QM_BASE_ADDR = AXIL_TX_CQM_BASE_ADDR + 2**AXIL_TX_CQM_ADDR_WID parameter AXIL_RX_CQM_BASE_ADDR = AXIL_RX_QM_BASE_ADDR + 2**AXIL_RX_QM_ADDR_WIDTH; parameter AXIL_PORT_BASE_ADDR = AXIL_RX_CQM_BASE_ADDR + 2**AXIL_RX_CQM_ADDR_WIDTH; -parameter PORT_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(PORTS+1); +localparam RB_BASE_ADDR = AXIL_CTRL_BASE_ADDR; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + +localparam PORT_RB_BASE_ADDR = RB_BASE_ADDR + 16'h1000; +localparam PORT_RB_STRIDE = 16'h1000; // parameter sizing helpers function [31:0] w_32(input [31:0] val); @@ -903,6 +908,11 @@ always @* begin end end +reg [DMA_CLIENT_LEN_WIDTH-1:0] tx_mtu_reg = MAX_TX_SIZE; +reg [DMA_CLIENT_LEN_WIDTH-1:0] rx_mtu_reg = MAX_RX_SIZE; + +reg [RX_QUEUE_INDEX_WIDTH-1:0] rss_mask_reg = 0; + always @(posedge clk) begin ctrl_reg_wr_ack_reg <= 1'b0; ctrl_reg_rd_data_reg <= {AXIL_DATA_WIDTH{1'b0}}; @@ -910,38 +920,81 @@ always @(posedge clk) begin if (ctrl_reg_wr_en && !ctrl_reg_wr_ack_reg) begin // write operation - ctrl_reg_wr_ack_reg <= 1'b0; - // case ({ctrl_reg_wr_addr >> 2, 2'b00}) - // default: ctrl_reg_wr_ack_reg <= 1'b0; - // endcase + ctrl_reg_wr_ack_reg <= 1'b1; + case ({ctrl_reg_wr_addr >> 2, 2'b00}) + // Interface control (TX) + RBB+8'h14: tx_mtu_reg <= ctrl_reg_wr_data; // IF TX ctrl: TX MTU + // Interface control (RX) + RBB+8'h34: rx_mtu_reg <= ctrl_reg_wr_data; // IF RX ctrl: RX MTU + RBB+8'h38: rss_mask_reg <= ctrl_reg_wr_data; // IF RX ctrl: RSS mask + default: ctrl_reg_wr_ack_reg <= 1'b0; + endcase end if (ctrl_reg_rd_en && !ctrl_reg_rd_ack_reg) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0000: ctrl_reg_rd_data_reg <= 32'd0; // if_id - 16'h0004: begin - // if_features - ctrl_reg_rd_data_reg[0] <= RX_RSS_ENABLE && RX_HASH_ENABLE; + // Interface control (TX) + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C001; // IF TX ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // IF TX ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // IF TX ctrl: Next header + RBB+8'h0C: begin + // IF TX ctrl: features ctrl_reg_rd_data_reg[4] <= PTP_TS_ENABLE; ctrl_reg_rd_data_reg[8] <= TX_CHECKSUM_ENABLE; - ctrl_reg_rd_data_reg[9] <= RX_CHECKSUM_ENABLE; - ctrl_reg_rd_data_reg[10] <= RX_HASH_ENABLE; end - 16'h0010: ctrl_reg_rd_data_reg <= 2**EVENT_QUEUE_INDEX_WIDTH; // event_queue_count - 16'h0014: ctrl_reg_rd_data_reg <= AXIL_EQM_BASE_ADDR; // event_queue_offset - 16'h0020: ctrl_reg_rd_data_reg <= 2**TX_QUEUE_INDEX_WIDTH; // tx_queue_count - 16'h0024: ctrl_reg_rd_data_reg <= AXIL_TX_QM_BASE_ADDR; // tx_queue_offset - 16'h0028: ctrl_reg_rd_data_reg <= 2**TX_CPL_QUEUE_INDEX_WIDTH; // tx_cpl_queue_count - 16'h002C: ctrl_reg_rd_data_reg <= AXIL_TX_CQM_BASE_ADDR; // tx_cpl_queue_offset - 16'h0030: ctrl_reg_rd_data_reg <= 2**RX_QUEUE_INDEX_WIDTH; // rx_queue_count - 16'h0034: ctrl_reg_rd_data_reg <= AXIL_RX_QM_BASE_ADDR; // rx_queue_offset - 16'h0038: ctrl_reg_rd_data_reg <= 2**RX_CPL_QUEUE_INDEX_WIDTH; // rx_cpl_queue_count - 16'h003C: ctrl_reg_rd_data_reg <= AXIL_RX_CQM_BASE_ADDR; // rx_cpl_queue_offset - 16'h0040: ctrl_reg_rd_data_reg <= PORTS; // port_count - 16'h0044: ctrl_reg_rd_data_reg <= AXIL_CTRL_BASE_ADDR + 2**PORT_CTRL_ADDR_WIDTH; // port_offset - 16'h0048: ctrl_reg_rd_data_reg <= 2**PORT_CTRL_ADDR_WIDTH; // port_stride + RBB+8'h10: ctrl_reg_rd_data_reg <= MAX_TX_SIZE; // IF TX ctrl: Max TX MTU + RBB+8'h14: ctrl_reg_rd_data_reg <= tx_mtu_reg; // IF TX ctrl: TX MTU + // Interface control (RX) + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C002; // IF RX ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // IF RX ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h40; // IF RX ctrl: Next header + RBB+8'h2C: begin + // IF RX ctrl: features + ctrl_reg_rd_data_reg[0] <= RX_RSS_ENABLE && RX_HASH_ENABLE; + ctrl_reg_rd_data_reg[4] <= PTP_TS_ENABLE; + ctrl_reg_rd_data_reg[8] <= RX_CHECKSUM_ENABLE; + ctrl_reg_rd_data_reg[9] <= RX_HASH_ENABLE; + end + RBB+8'h30: ctrl_reg_rd_data_reg <= MAX_RX_SIZE; // IF RX ctrl: Max RX MTU + RBB+8'h34: ctrl_reg_rd_data_reg <= rx_mtu_reg; // IF RX ctrl: RX MTU + RBB+8'h38: ctrl_reg_rd_data_reg <= rss_mask_reg; // IF RX ctrl: RSS mask + // Queue manager (Event) + RBB+8'h40: ctrl_reg_rd_data_reg <= 32'h0000C010; // Event QM: Type + RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000100; // Event QM: Version + RBB+8'h48: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h60; // Event QM: Next header + RBB+8'h4C: ctrl_reg_rd_data_reg <= AXIL_EQM_BASE_ADDR; // Event QM: Offset + RBB+8'h50: ctrl_reg_rd_data_reg <= 2**EVENT_QUEUE_INDEX_WIDTH; // Event QM: Count + RBB+8'h54: ctrl_reg_rd_data_reg <= 32; // Event QM: Stride + // Queue manager (TX) + RBB+8'h60: ctrl_reg_rd_data_reg <= 32'h0000C020; // TX QM: Type + RBB+8'h64: ctrl_reg_rd_data_reg <= 32'h00000100; // TX QM: Version + RBB+8'h68: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h80; // TX QM: Next header + RBB+8'h6C: ctrl_reg_rd_data_reg <= AXIL_TX_QM_BASE_ADDR; // TX QM: Offset + RBB+8'h70: ctrl_reg_rd_data_reg <= 2**TX_QUEUE_INDEX_WIDTH; // TX QM: Count + RBB+8'h74: ctrl_reg_rd_data_reg <= 32; // TX QM: Stride + // Queue manager (TX CPL) + RBB+8'h80: ctrl_reg_rd_data_reg <= 32'h0000C030; // TX CPL QM: Type + RBB+8'h84: ctrl_reg_rd_data_reg <= 32'h00000100; // TX CPL QM: Version + RBB+8'h88: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'hA0; // TX CPL QM: Next header + RBB+8'h8C: ctrl_reg_rd_data_reg <= AXIL_TX_CQM_BASE_ADDR; // TX CPL QM: Offset + RBB+8'h90: ctrl_reg_rd_data_reg <= 2**TX_CPL_QUEUE_INDEX_WIDTH; // TX CPL QM: Count + RBB+8'h94: ctrl_reg_rd_data_reg <= 32; // TX CPL QM: Stride + // Queue manager (RX) + RBB+8'hA0: ctrl_reg_rd_data_reg <= 32'h0000C021; // RX QM: Type + RBB+8'hA4: ctrl_reg_rd_data_reg <= 32'h00000100; // RX QM: Version + RBB+8'hA8: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'hC0; // RX QM: Next header + RBB+8'hAC: ctrl_reg_rd_data_reg <= AXIL_RX_QM_BASE_ADDR; // RX QM: Offset + RBB+8'hB0: ctrl_reg_rd_data_reg <= 2**RX_QUEUE_INDEX_WIDTH; // RX QM: Count + RBB+8'hB4: ctrl_reg_rd_data_reg <= 32; // RX QM: Stride + // Queue manager (RX CPL) + RBB+8'hC0: ctrl_reg_rd_data_reg <= 32'h0000C031; // RX CPL QM: Type + RBB+8'hC4: ctrl_reg_rd_data_reg <= 32'h00000100; // RX CPL QM: Version + RBB+8'hC8: ctrl_reg_rd_data_reg <= PORT_RB_BASE_ADDR; // RX CPL QM: Next header + RBB+8'hCC: ctrl_reg_rd_data_reg <= AXIL_RX_CQM_BASE_ADDR; // RX CPL QM: Offset + RBB+8'hD0: ctrl_reg_rd_data_reg <= 2**RX_CPL_QUEUE_INDEX_WIDTH; // RX CPL QM: Count + RBB+8'hD4: ctrl_reg_rd_data_reg <= 32; // RX CPL QM: Stride default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -949,6 +1002,11 @@ always @(posedge clk) begin if (rst) begin ctrl_reg_wr_ack_reg <= 1'b0; ctrl_reg_rd_ack_reg <= 1'b0; + + tx_mtu_reg <= MAX_TX_SIZE; + rx_mtu_reg <= MAX_RX_SIZE; + + rss_mask_reg <= 0; end end @@ -2120,6 +2178,7 @@ generate mqnic_port #( .DMA_ADDR_WIDTH(DMA_ADDR_WIDTH), .DMA_LEN_WIDTH(DMA_LEN_WIDTH), + .DMA_CLIENT_LEN_WIDTH(DMA_CLIENT_LEN_WIDTH), .DMA_TAG_WIDTH(DMA_TAG_WIDTH_INT), .REQ_TAG_WIDTH(REQ_TAG_WIDTH), .DESC_REQ_TAG_WIDTH(PORT_DESC_REQ_TAG_WIDTH), @@ -2149,12 +2208,14 @@ generate .RX_HASH_ENABLE(RX_HASH_ENABLE), .RX_CHECKSUM_ENABLE(RX_CHECKSUM_ENABLE), .REG_DATA_WIDTH(AXIL_DATA_WIDTH), - .REG_ADDR_WIDTH(PORT_CTRL_ADDR_WIDTH), + .REG_ADDR_WIDTH(AXIL_CTRL_ADDR_WIDTH), .REG_STRB_WIDTH(AXIL_STRB_WIDTH), + .RB_BASE_ADDR(PORT_RB_BASE_ADDR + PORT_RB_STRIDE*n), + .RB_NEXT_PTR(n < PORTS-1 ? PORT_RB_BASE_ADDR + PORT_RB_STRIDE*(n+1) : 0), .AXIL_DATA_WIDTH(AXIL_DATA_WIDTH), .AXIL_ADDR_WIDTH(AXIL_PORT_ADDR_WIDTH), .AXIL_STRB_WIDTH(AXIL_STRB_WIDTH), - .AXIL_OFFSET(AXIL_PORT_BASE_ADDR + (2**AXIL_PORT_ADDR_WIDTH)*n - (AXIL_CTRL_BASE_ADDR + (2**PORT_CTRL_ADDR_WIDTH)*(n+1))), + .AXIL_OFFSET(AXIL_PORT_BASE_ADDR + (2**AXIL_PORT_ADDR_WIDTH)*n), .SEG_COUNT(SEG_COUNT), .SEG_DATA_WIDTH(SEG_DATA_WIDTH), .SEG_ADDR_WIDTH(SEG_ADDR_WIDTH), @@ -2271,11 +2332,11 @@ generate .ctrl_reg_wr_addr(ctrl_reg_wr_addr), .ctrl_reg_wr_data(ctrl_reg_wr_data), .ctrl_reg_wr_strb(ctrl_reg_wr_strb), - .ctrl_reg_wr_en(ctrl_reg_wr_en && ((ctrl_reg_wr_addr >> PORT_CTRL_ADDR_WIDTH) == n+1)), + .ctrl_reg_wr_en(ctrl_reg_wr_en), .ctrl_reg_wr_wait(port_ctrl_reg_wr_wait[n]), .ctrl_reg_wr_ack(port_ctrl_reg_wr_ack[n]), .ctrl_reg_rd_addr(ctrl_reg_rd_addr), - .ctrl_reg_rd_en(ctrl_reg_rd_en && ((ctrl_reg_rd_addr >> PORT_CTRL_ADDR_WIDTH) == n+1)), + .ctrl_reg_rd_en(ctrl_reg_rd_en), .ctrl_reg_rd_data(port_ctrl_reg_rd_data[n]), .ctrl_reg_rd_wait(port_ctrl_reg_rd_wait[n]), .ctrl_reg_rd_ack(port_ctrl_reg_rd_ack[n]), @@ -2357,7 +2418,14 @@ generate * PTP clock */ .ptp_ts_96(ptp_ts_96), - .ptp_ts_step(ptp_ts_step) + .ptp_ts_step(ptp_ts_step), + + /* + * Configuration + */ + .tx_mtu(tx_mtu_reg), + .rx_mtu(rx_mtu_reg), + .rss_mask(rss_mask_reg) ); end diff --git a/fpga/common/rtl/mqnic_port.v b/fpga/common/rtl/mqnic_port.v index 1fcd437f9..b26591a10 100644 --- a/fpga/common/rtl/mqnic_port.v +++ b/fpga/common/rtl/mqnic_port.v @@ -46,6 +46,8 @@ module mqnic_port # parameter DMA_ADDR_WIDTH = 64, // DMA length field width parameter DMA_LEN_WIDTH = 16, + // DMA client length field width + parameter DMA_CLIENT_LEN_WIDTH = DMA_LEN_WIDTH, // DMA tag field width parameter DMA_TAG_WIDTH = 8, // Request tag field width @@ -108,6 +110,10 @@ module mqnic_port # parameter REG_DATA_WIDTH = 32, // Width of control register interface strb parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8), + // Register block base address + parameter RB_BASE_ADDR = 0, + // Register block next pointer + parameter RB_NEXT_PTR = 0, // Width of AXI lite data bus in bits parameter AXIL_DATA_WIDTH = 32, // Width of AXI lite address bus in bits @@ -334,11 +340,17 @@ module mqnic_port # * PTP clock */ input wire [PTP_TS_WIDTH-1:0] ptp_ts_96, - input wire ptp_ts_step + input wire ptp_ts_step, + + /* + * Configuration + */ + input wire [DMA_CLIENT_LEN_WIDTH-1:0] tx_mtu, + input wire [DMA_CLIENT_LEN_WIDTH-1:0] rx_mtu, + input wire [RX_QUEUE_INDEX_WIDTH-1:0] rss_mask ); parameter DMA_CLIENT_TAG_WIDTH = $clog2(TX_DESC_TABLE_SIZE > RX_DESC_TABLE_SIZE ? TX_DESC_TABLE_SIZE : RX_DESC_TABLE_SIZE); -parameter DMA_CLIENT_LEN_WIDTH = DMA_LEN_WIDTH; parameter DESC_REQ_TAG_WIDTH_INT = DESC_REQ_TAG_WIDTH - $clog2(2); @@ -530,74 +542,6 @@ wire dma_rx_desc_status_user; wire [3:0] dma_rx_desc_status_error; wire dma_rx_desc_status_valid; -wire sched_ctrl_reg_wr_wait; -wire sched_ctrl_reg_wr_ack; -wire [AXIL_DATA_WIDTH-1:0] sched_ctrl_reg_rd_data; -wire sched_ctrl_reg_rd_wait; -wire sched_ctrl_reg_rd_ack; - -reg ctrl_reg_wr_ack_reg = 1'b0; -reg [AXIL_DATA_WIDTH-1:0] ctrl_reg_rd_data_reg = {AXIL_DATA_WIDTH{1'b0}}; -reg ctrl_reg_rd_ack_reg = 1'b0; - -reg [RX_QUEUE_INDEX_WIDTH-1:0] rss_mask_reg = 0; - -reg [DMA_CLIENT_LEN_WIDTH-1:0] tx_mtu_reg = MAX_TX_SIZE; -reg [DMA_CLIENT_LEN_WIDTH-1:0] rx_mtu_reg = MAX_RX_SIZE; - -assign ctrl_reg_wr_wait = sched_ctrl_reg_wr_wait; -assign ctrl_reg_wr_ack = ctrl_reg_wr_ack_reg | sched_ctrl_reg_wr_ack; -assign ctrl_reg_rd_data = ctrl_reg_rd_data_reg | sched_ctrl_reg_rd_data; -assign ctrl_reg_rd_wait = sched_ctrl_reg_rd_wait; -assign ctrl_reg_rd_ack = ctrl_reg_rd_ack_reg | sched_ctrl_reg_rd_ack; - -always @(posedge clk) begin - ctrl_reg_wr_ack_reg <= 1'b0; - ctrl_reg_rd_data_reg <= {AXIL_DATA_WIDTH{1'b0}}; - ctrl_reg_rd_ack_reg <= 1'b0; - - if (ctrl_reg_wr_en && !ctrl_reg_wr_ack_reg) begin - // write operation - ctrl_reg_wr_ack_reg <= 1'b1; - case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0080: rss_mask_reg <= ctrl_reg_wr_data; // RSS mask - 16'h0100: tx_mtu_reg <= ctrl_reg_wr_data; // TX MTU - 16'h0200: rx_mtu_reg <= ctrl_reg_wr_data; // RX MTU - default: ctrl_reg_wr_ack_reg <= 1'b0; - endcase - end - - if (ctrl_reg_rd_en && !ctrl_reg_rd_ack_reg) begin - // read operation - ctrl_reg_rd_ack_reg <= 1'b1; - case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0000: ctrl_reg_rd_data_reg <= 32'd0; // port_id - 16'h0004: begin - // port_features - ctrl_reg_rd_data_reg[0] <= RX_RSS_ENABLE && RX_HASH_ENABLE; - ctrl_reg_rd_data_reg[4] <= PTP_TS_ENABLE; - ctrl_reg_rd_data_reg[8] <= TX_CHECKSUM_ENABLE; - ctrl_reg_rd_data_reg[9] <= RX_CHECKSUM_ENABLE; - ctrl_reg_rd_data_reg[10] <= RX_HASH_ENABLE; - end - 16'h0008: ctrl_reg_rd_data_reg <= MAX_TX_SIZE; // port_mtu - 16'h0080: ctrl_reg_rd_data_reg <= rss_mask_reg; // RSS mask - 16'h0100: ctrl_reg_rd_data_reg <= tx_mtu_reg; // TX MTU - 16'h0200: ctrl_reg_rd_data_reg <= rx_mtu_reg; // RX MTU - default: ctrl_reg_rd_ack_reg <= 1'b0; - endcase - end - - if (rst) begin - ctrl_reg_wr_ack_reg <= 1'b0; - ctrl_reg_rd_ack_reg <= 1'b0; - - rss_mask_reg <= 0; - tx_mtu_reg <= MAX_TX_SIZE; - rx_mtu_reg <= MAX_RX_SIZE; - end -end - desc_op_mux #( .PORTS(2), .SELECT_WIDTH(1), @@ -733,6 +677,8 @@ mqnic_tx_scheduler_block #( .REG_DATA_WIDTH(REG_DATA_WIDTH), .REG_ADDR_WIDTH(REG_ADDR_WIDTH), .REG_STRB_WIDTH(REG_STRB_WIDTH), + .RB_BASE_ADDR(RB_BASE_ADDR), + .RB_NEXT_PTR(RB_NEXT_PTR), .AXIL_DATA_WIDTH(AXIL_DATA_WIDTH), .AXIL_ADDR_WIDTH(AXIL_ADDR_WIDTH), .AXIL_STRB_WIDTH(AXIL_STRB_WIDTH), @@ -757,13 +703,13 @@ scheduler_block ( .ctrl_reg_wr_data(ctrl_reg_wr_data), .ctrl_reg_wr_strb(ctrl_reg_wr_strb), .ctrl_reg_wr_en(ctrl_reg_wr_en), - .ctrl_reg_wr_wait(sched_ctrl_reg_wr_wait), - .ctrl_reg_wr_ack(sched_ctrl_reg_wr_ack), + .ctrl_reg_wr_wait(ctrl_reg_wr_wait), + .ctrl_reg_wr_ack(ctrl_reg_wr_ack), .ctrl_reg_rd_addr(ctrl_reg_rd_addr), .ctrl_reg_rd_en(ctrl_reg_rd_en), - .ctrl_reg_rd_data(sched_ctrl_reg_rd_data), - .ctrl_reg_rd_wait(sched_ctrl_reg_rd_wait), - .ctrl_reg_rd_ack(sched_ctrl_reg_rd_ack), + .ctrl_reg_rd_data(ctrl_reg_rd_data), + .ctrl_reg_rd_wait(ctrl_reg_rd_wait), + .ctrl_reg_rd_ack(ctrl_reg_rd_ack), /* * AXI-Lite slave interface @@ -1204,7 +1150,7 @@ rx_engine_inst ( /* * Configuration */ - .mtu(rx_mtu_reg), + .mtu(rx_mtu), .enable(1'b1) ); @@ -1338,7 +1284,7 @@ if (RX_RSS_ENABLE && RX_HASH_ENABLE) begin .rst(rst), // AXI input - .s_axis_tdata(rx_hash & rss_mask_reg), + .s_axis_tdata(rx_hash & rss_mask), .s_axis_tkeep(0), .s_axis_tvalid(rx_hash_valid), .s_axis_tready(), diff --git a/fpga/common/rtl/mqnic_ptp.v b/fpga/common/rtl/mqnic_ptp.v index dc5b64267..af4442a46 100644 --- a/fpga/common/rtl/mqnic_ptp.v +++ b/fpga/common/rtl/mqnic_ptp.v @@ -51,7 +51,9 @@ module mqnic_ptp # parameter PTP_PEROUT_COUNT = 1, parameter REG_ADDR_WIDTH = 7+(PTP_PEROUT_ENABLE ? $clog2((PTP_PEROUT_COUNT+1)/2) + 1 : 0), parameter REG_DATA_WIDTH = 32, - parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8) + parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8), + parameter RB_BASE_ADDR = 0, + parameter RB_NEXT_PTR = 0 ) ( input wire clk, @@ -103,19 +105,19 @@ end wire clock_reg_wr_wait; wire clock_reg_wr_ack; -wire [31:0] clock_reg_rd_data; +wire [REG_DATA_WIDTH-1:0] clock_reg_rd_data; wire clock_reg_rd_wait; wire clock_reg_rd_ack; wire perout_reg_wr_wait[PTP_PEROUT_COUNT-1:0]; wire perout_reg_wr_ack[PTP_PEROUT_COUNT-1:0]; -wire [31:0] perout_reg_rd_data[PTP_PEROUT_COUNT-1:0]; +wire [REG_DATA_WIDTH-1:0] perout_reg_rd_data[PTP_PEROUT_COUNT-1:0]; wire perout_reg_rd_wait[PTP_PEROUT_COUNT-1:0]; wire perout_reg_rd_ack[PTP_PEROUT_COUNT-1:0]; reg reg_wr_wait_cmb; reg reg_wr_ack_cmb; -reg [31:0] reg_rd_data_cmb; +reg [REG_DATA_WIDTH-1:0] reg_rd_data_cmb; reg reg_rd_wait_cmb; reg reg_rd_ack_cmb; @@ -152,7 +154,12 @@ mqnic_ptp_clock #( .PTP_PERIOD_NS(PTP_PERIOD_NS), .PTP_PERIOD_FNS(PTP_PERIOD_FNS), .PTP_PEROUT_ENABLE(PTP_PEROUT_ENABLE), - .PTP_PEROUT_COUNT(PTP_PEROUT_COUNT) + .PTP_PEROUT_COUNT(PTP_PEROUT_COUNT), + .REG_ADDR_WIDTH(REG_ADDR_WIDTH), + .REG_DATA_WIDTH(REG_DATA_WIDTH), + .REG_STRB_WIDTH(REG_STRB_WIDTH), + .RB_BASE_ADDR(RB_BASE_ADDR), + .RB_NEXT_PTR(PTP_PEROUT_ENABLE ? RB_BASE_ADDR + 32'h80 : RB_NEXT_PTR) ) ptp_clock_inst ( .clk(clk), @@ -164,11 +171,11 @@ ptp_clock_inst ( .reg_wr_addr(reg_wr_addr), .reg_wr_data(reg_wr_data), .reg_wr_strb(reg_wr_strb), - .reg_wr_en(reg_wr_en && (reg_wr_addr >> 7 == 0)), + .reg_wr_en(reg_wr_en), .reg_wr_wait(clock_reg_wr_wait), .reg_wr_ack(clock_reg_wr_ack), .reg_rd_addr(reg_rd_addr), - .reg_rd_en(reg_rd_en && (reg_rd_addr >> 7 == 0)), + .reg_rd_en(reg_rd_en), .reg_rd_data(clock_reg_rd_data), .reg_rd_wait(clock_reg_rd_wait), .reg_rd_ack(clock_reg_rd_ack), @@ -188,8 +195,15 @@ genvar n; if (PTP_PEROUT_ENABLE) begin for (n = 0; n < PTP_PEROUT_COUNT; n = n + 1) begin : perout - - mqnic_ptp_perout ptp_perout_inst ( + + mqnic_ptp_perout #( + .REG_ADDR_WIDTH(REG_ADDR_WIDTH), + .REG_DATA_WIDTH(REG_DATA_WIDTH), + .REG_STRB_WIDTH(REG_STRB_WIDTH), + .RB_BASE_ADDR(RB_BASE_ADDR + 32'h80 + 32'h40*n), + .RB_NEXT_PTR(n < PTP_PEROUT_COUNT-1 ? RB_BASE_ADDR + 32'h80 + 32'h40*(n+1) : RB_NEXT_PTR) + ) + ptp_perout_inst ( .clk(clk), .rst(rst), @@ -199,11 +213,11 @@ if (PTP_PEROUT_ENABLE) begin .reg_wr_addr(reg_wr_addr), .reg_wr_data(reg_wr_data), .reg_wr_strb(reg_wr_strb), - .reg_wr_en(reg_wr_en && ((reg_wr_addr >> 6) == n+2)), + .reg_wr_en(reg_wr_en), .reg_wr_wait(perout_reg_wr_wait[n]), .reg_wr_ack(perout_reg_wr_ack[n]), .reg_rd_addr(reg_rd_addr), - .reg_rd_en(reg_rd_en && ((reg_rd_addr >> 6) == n+2)), + .reg_rd_en(reg_rd_en), .reg_rd_data(perout_reg_rd_data[n]), .reg_rd_wait(perout_reg_rd_wait[n]), .reg_rd_ack(perout_reg_rd_ack[n]), diff --git a/fpga/common/rtl/mqnic_ptp_clock.v b/fpga/common/rtl/mqnic_ptp_clock.v index 3ca29340a..2f0ef42db 100644 --- a/fpga/common/rtl/mqnic_ptp_clock.v +++ b/fpga/common/rtl/mqnic_ptp_clock.v @@ -48,38 +48,68 @@ module mqnic_ptp_clock # parameter PTP_PERIOD_NS = 4'd4, parameter PTP_PERIOD_FNS = 32'd0, parameter PTP_PEROUT_ENABLE = 0, - parameter PTP_PEROUT_COUNT = 1 + parameter PTP_PEROUT_COUNT = 1, + parameter REG_ADDR_WIDTH = 7, + parameter REG_DATA_WIDTH = 32, + parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8), + parameter RB_BASE_ADDR = 0, + parameter RB_NEXT_PTR = 0 ) ( - input wire clk, - input wire rst, + input wire clk, + input wire rst, /* * Register interface */ - input wire [6:0] reg_wr_addr, - input wire [31:0] reg_wr_data, - input wire [3:0] reg_wr_strb, - input wire reg_wr_en, - output wire reg_wr_wait, - output wire reg_wr_ack, - input wire [6:0] reg_rd_addr, - input wire reg_rd_en, - output wire [31:0] reg_rd_data, - output wire reg_rd_wait, - output wire reg_rd_ack, + input wire [REG_ADDR_WIDTH-1:0] reg_wr_addr, + input wire [REG_DATA_WIDTH-1:0] reg_wr_data, + input wire [REG_STRB_WIDTH-1:0] reg_wr_strb, + input wire reg_wr_en, + output wire reg_wr_wait, + output wire reg_wr_ack, + input wire [REG_ADDR_WIDTH-1:0] reg_rd_addr, + input wire reg_rd_en, + output wire [REG_DATA_WIDTH-1:0] reg_rd_data, + output wire reg_rd_wait, + output wire reg_rd_ack, /* * PTP clock */ - output wire ptp_pps, - output wire [95:0] ptp_ts_96, - output wire ptp_ts_step + output wire ptp_pps, + output wire [95:0] ptp_ts_96, + output wire ptp_ts_step ); +localparam RBB = RB_BASE_ADDR & {REG_ADDR_WIDTH{1'b1}}; + +// check configuration +initial begin + if (REG_DATA_WIDTH != 32) begin + $error("Error: Register interface width must be 32 (instance %m)"); + $finish; + end + + if (REG_STRB_WIDTH * 8 != REG_DATA_WIDTH) begin + $error("Error: Register interface requires byte (8-bit) granularity (instance %m)"); + $finish; + end + + if (REG_ADDR_WIDTH < 7) begin + $error("Error: Register address width too narrow (instance %m)"); + $finish; + end + + if (RB_NEXT_PTR >= RB_BASE_ADDR && RB_NEXT_PTR < RB_BASE_ADDR + 7'h60) begin + $error("Error: RB_NEXT_PTR overlaps block (instance %m)"); + $finish; + end +end + // control registers reg reg_wr_ack_reg = 1'b0; -reg [31:0] reg_rd_data_reg = 0; +reg [REG_DATA_WIDTH-1:0] reg_rd_data_reg = 0; reg reg_rd_ack_reg = 1'b0; reg [95:0] get_ptp_ts_96_reg = 0; @@ -114,23 +144,23 @@ always @(posedge clk) begin reg_wr_ack_reg <= 1'b1; case ({reg_wr_addr >> 2, 2'b00}) // PHC - 7'h30: set_ptp_ts_96_reg[15:0] <= reg_wr_data; // PTP set fns - 7'h34: set_ptp_ts_96_reg[45:16] <= reg_wr_data; // PTP set ns - 7'h38: set_ptp_ts_96_reg[79:48] <= reg_wr_data; // PTP set sec l - 7'h3C: begin + RBB+7'h30: set_ptp_ts_96_reg[15:0] <= reg_wr_data; // PTP set fns + RBB+7'h34: set_ptp_ts_96_reg[45:16] <= reg_wr_data; // PTP set ns + RBB+7'h38: set_ptp_ts_96_reg[79:48] <= reg_wr_data; // PTP set sec l + RBB+7'h3C: begin // PTP set sec h set_ptp_ts_96_reg[95:80] <= reg_wr_data; set_ptp_ts_96_valid_reg <= 1'b1; end - 7'h40: set_ptp_period_fns_reg <= reg_wr_data; // PTP period fns - 7'h44: begin + RBB+7'h40: set_ptp_period_fns_reg <= reg_wr_data; // PTP period fns + RBB+7'h44: begin // PTP period ns set_ptp_period_ns_reg <= reg_wr_data; set_ptp_period_valid_reg <= 1'b1; end - 7'h50: set_ptp_offset_fns_reg <= reg_wr_data; // PTP offset fns - 7'h54: set_ptp_offset_ns_reg <= reg_wr_data; // PTP offset ns - 7'h58: begin + RBB+7'h50: set_ptp_offset_fns_reg <= reg_wr_data; // PTP offset fns + RBB+7'h54: set_ptp_offset_ns_reg <= reg_wr_data; // PTP offset ns + RBB+7'h58: begin // PTP offset count set_ptp_offset_count_reg <= reg_wr_data; set_ptp_offset_valid_reg <= 1'b1; @@ -144,37 +174,40 @@ always @(posedge clk) begin reg_rd_ack_reg <= 1'b1; case ({reg_rd_addr >> 2, 2'b00}) // PHC - 7'h00: begin + RBB+7'h00: reg_rd_data_reg <= 32'h0000C080; // PHC: Type + RBB+7'h04: reg_rd_data_reg <= 32'h00000100; // PHC: Version + RBB+7'h08: reg_rd_data_reg <= RB_NEXT_PTR; // PHC: Next header + RBB+7'h0C: begin // PHC features reg_rd_data_reg[7:0] <= PTP_PEROUT_ENABLE ? PTP_PEROUT_COUNT : 0; reg_rd_data_reg[15:8] <= 0; reg_rd_data_reg[23:16] <= 0; reg_rd_data_reg[31:24] <= 0; end - 7'h10: reg_rd_data_reg <= ptp_ts_96[15:0]; // PTP cur fns - 7'h14: reg_rd_data_reg <= ptp_ts_96[45:16]; // PTP cur ns - 7'h18: reg_rd_data_reg <= ptp_ts_96[79:48]; // PTP cur sec l - 7'h1C: reg_rd_data_reg <= ptp_ts_96[95:80]; // PTP cur sec h - 7'h20: begin + RBB+7'h10: reg_rd_data_reg <= ptp_ts_96[15:0]; // PTP cur fns + RBB+7'h14: reg_rd_data_reg <= ptp_ts_96[45:16]; // PTP cur ns + RBB+7'h18: reg_rd_data_reg <= ptp_ts_96[79:48]; // PTP cur sec l + RBB+7'h1C: reg_rd_data_reg <= ptp_ts_96[95:80]; // PTP cur sec h + RBB+7'h20: begin // PTP get fns get_ptp_ts_96_reg <= ptp_ts_96; reg_rd_data_reg <= ptp_ts_96[15:0]; end - 7'h24: reg_rd_data_reg <= get_ptp_ts_96_reg[45:16]; // PTP get ns - 7'h28: reg_rd_data_reg <= get_ptp_ts_96_reg[79:48]; // PTP get sec l - 7'h2C: reg_rd_data_reg <= get_ptp_ts_96_reg[95:80]; // PTP get sec h - 7'h30: reg_rd_data_reg <= set_ptp_ts_96_reg[15:0]; // PTP set fns - 7'h34: reg_rd_data_reg <= set_ptp_ts_96_reg[45:16]; // PTP set ns - 7'h38: reg_rd_data_reg <= set_ptp_ts_96_reg[79:48]; // PTP set sec l - 7'h3C: reg_rd_data_reg <= set_ptp_ts_96_reg[95:80]; // PTP set sec h - 7'h40: reg_rd_data_reg <= set_ptp_period_fns_reg; // PTP period fns - 7'h44: reg_rd_data_reg <= set_ptp_period_ns_reg; // PTP period ns - 7'h48: reg_rd_data_reg <= PTP_PERIOD_FNS; // PTP nom period fns - 7'h4C: reg_rd_data_reg <= PTP_PERIOD_NS; // PTP nom period ns - 7'h50: reg_rd_data_reg <= set_ptp_offset_fns_reg; // PTP offset fns - 7'h54: reg_rd_data_reg <= set_ptp_offset_ns_reg; // PTP offset ns - 7'h58: reg_rd_data_reg <= set_ptp_offset_count_reg; // PTP offset count - 7'h5C: reg_rd_data_reg <= set_ptp_offset_active; // PTP offset status + RBB+7'h24: reg_rd_data_reg <= get_ptp_ts_96_reg[45:16]; // PTP get ns + RBB+7'h28: reg_rd_data_reg <= get_ptp_ts_96_reg[79:48]; // PTP get sec l + RBB+7'h2C: reg_rd_data_reg <= get_ptp_ts_96_reg[95:80]; // PTP get sec h + RBB+7'h30: reg_rd_data_reg <= set_ptp_ts_96_reg[15:0]; // PTP set fns + RBB+7'h34: reg_rd_data_reg <= set_ptp_ts_96_reg[45:16]; // PTP set ns + RBB+7'h38: reg_rd_data_reg <= set_ptp_ts_96_reg[79:48]; // PTP set sec l + RBB+7'h3C: reg_rd_data_reg <= set_ptp_ts_96_reg[95:80]; // PTP set sec h + RBB+7'h40: reg_rd_data_reg <= set_ptp_period_fns_reg; // PTP period fns + RBB+7'h44: reg_rd_data_reg <= set_ptp_period_ns_reg; // PTP period ns + RBB+7'h48: reg_rd_data_reg <= PTP_PERIOD_FNS; // PTP nom period fns + RBB+7'h4C: reg_rd_data_reg <= PTP_PERIOD_NS; // PTP nom period ns + RBB+7'h50: reg_rd_data_reg <= set_ptp_offset_fns_reg; // PTP offset fns + RBB+7'h54: reg_rd_data_reg <= set_ptp_offset_ns_reg; // PTP offset ns + RBB+7'h58: reg_rd_data_reg <= set_ptp_offset_count_reg; // PTP offset count + RBB+7'h5C: reg_rd_data_reg <= set_ptp_offset_active; // PTP offset status default: reg_rd_ack_reg <= 1'b0; endcase end diff --git a/fpga/common/rtl/mqnic_ptp_perout.v b/fpga/common/rtl/mqnic_ptp_perout.v index b4ba3830e..690392d73 100644 --- a/fpga/common/rtl/mqnic_ptp_perout.v +++ b/fpga/common/rtl/mqnic_ptp_perout.v @@ -40,41 +40,73 @@ either expressed or implied, of The Regents of the University of California. /* * PTP period output */ -module mqnic_ptp_perout +module mqnic_ptp_perout # ( - input wire clk, - input wire rst, + parameter REG_ADDR_WIDTH = 6, + parameter REG_DATA_WIDTH = 32, + parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8), + parameter RB_BASE_ADDR = 0, + parameter RB_NEXT_PTR = 0 +) +( + input wire clk, + input wire rst, /* * Register interface */ - input wire [6:0] reg_wr_addr, - input wire [31:0] reg_wr_data, - input wire [3:0] reg_wr_strb, - input wire reg_wr_en, - output wire reg_wr_wait, - output wire reg_wr_ack, - input wire [6:0] reg_rd_addr, - input wire reg_rd_en, - output wire [31:0] reg_rd_data, - output wire reg_rd_wait, - output wire reg_rd_ack, + input wire [REG_ADDR_WIDTH-1:0] reg_wr_addr, + input wire [REG_DATA_WIDTH-1:0] reg_wr_data, + input wire [REG_STRB_WIDTH-1:0] reg_wr_strb, + input wire reg_wr_en, + output wire reg_wr_wait, + output wire reg_wr_ack, + input wire [REG_ADDR_WIDTH-1:0] reg_rd_addr, + input wire reg_rd_en, + output wire [REG_DATA_WIDTH-1:0] reg_rd_data, + output wire reg_rd_wait, + output wire reg_rd_ack, /* * PTP clock */ - input wire [95:0] ptp_ts_96, - input wire ptp_ts_step, - output wire ptp_perout_locked, - output wire ptp_perout_error, - output wire ptp_perout_pulse + input wire [95:0] ptp_ts_96, + input wire ptp_ts_step, + output wire ptp_perout_locked, + output wire ptp_perout_error, + output wire ptp_perout_pulse ); +localparam RBB = RB_BASE_ADDR & {REG_ADDR_WIDTH{1'b1}}; + +// check configuration +initial begin + if (REG_DATA_WIDTH != 32) begin + $error("Error: Register interface width must be 32 (instance %m)"); + $finish; + end + + if (REG_STRB_WIDTH * 8 != REG_DATA_WIDTH) begin + $error("Error: Register interface requires byte (8-bit) granularity (instance %m)"); + $finish; + end + + if (REG_ADDR_WIDTH < 6) begin + $error("Error: Register address width too narrow (instance %m)"); + $finish; + end + + if (RB_NEXT_PTR >= RB_BASE_ADDR && RB_NEXT_PTR < RB_BASE_ADDR + 7'h40) begin + $error("Error: RB_NEXT_PTR overlaps block (instance %m)"); + $finish; + end +end + reg ptp_perout_enable_reg = 1'b0; // control registers reg reg_wr_ack_reg = 1'b0; -reg [31:0] reg_rd_data_reg = 0; +reg [REG_DATA_WIDTH-1:0] reg_rd_data_reg = 0; reg reg_rd_ack_reg = 1'b0; reg [95:0] set_ptp_perout_start_reg = 0; @@ -103,30 +135,30 @@ always @(posedge clk) begin // write operation reg_wr_ack_reg <= 1'b1; case ({reg_wr_addr >> 2, 2'b00}) - 6'h00: begin - // PTP perout control + RBB+6'h0C: begin + // PTP perout control and status ptp_perout_enable_reg <= reg_wr_data[0]; end - 6'h10: set_ptp_perout_start_reg[15:0] <= reg_wr_data; // PTP perout start fns - 6'h14: set_ptp_perout_start_reg[45:16] <= reg_wr_data; // PTP perout start ns - 6'h18: set_ptp_perout_start_reg[79:48] <= reg_wr_data; // PTP perout start sec l - 6'h1C: begin + RBB+6'h10: set_ptp_perout_start_reg[15:0] <= reg_wr_data; // PTP perout start fns + RBB+6'h14: set_ptp_perout_start_reg[45:16] <= reg_wr_data; // PTP perout start ns + RBB+6'h18: set_ptp_perout_start_reg[79:48] <= reg_wr_data; // PTP perout start sec l + RBB+6'h1C: begin // PTP perout start sec h set_ptp_perout_start_reg[95:80] <= reg_wr_data; set_ptp_perout_start_valid_reg <= 1'b1; end - 6'h20: set_ptp_perout_period_reg[15:0] <= reg_wr_data; // PTP perout period fns - 6'h24: set_ptp_perout_period_reg[45:16] <= reg_wr_data; // PTP perout period ns - 6'h28: set_ptp_perout_period_reg[79:48] <= reg_wr_data; // PTP perout period sec l - 6'h2C: begin + RBB+6'h20: set_ptp_perout_period_reg[15:0] <= reg_wr_data; // PTP perout period fns + RBB+6'h24: set_ptp_perout_period_reg[45:16] <= reg_wr_data; // PTP perout period ns + RBB+6'h28: set_ptp_perout_period_reg[79:48] <= reg_wr_data; // PTP perout period sec l + RBB+6'h2C: begin // PTP perout period sec h set_ptp_perout_period_reg[95:80] <= reg_wr_data; set_ptp_perout_period_valid_reg <= 1'b1; end - 6'h30: set_ptp_perout_width_reg[15:0] <= reg_wr_data; // PTP perout width fns - 6'h34: set_ptp_perout_width_reg[45:16] <= reg_wr_data; // PTP perout width ns - 6'h38: set_ptp_perout_width_reg[79:48] <= reg_wr_data; // PTP perout width sec l - 6'h3C: begin + RBB+6'h30: set_ptp_perout_width_reg[15:0] <= reg_wr_data; // PTP perout width fns + RBB+6'h34: set_ptp_perout_width_reg[45:16] <= reg_wr_data; // PTP perout width ns + RBB+6'h38: set_ptp_perout_width_reg[79:48] <= reg_wr_data; // PTP perout width sec l + RBB+6'h3C: begin // PTP perout width sec h set_ptp_perout_width_reg[95:80] <= reg_wr_data; set_ptp_perout_width_valid_reg <= 1'b1; @@ -139,28 +171,28 @@ always @(posedge clk) begin // read operation reg_rd_ack_reg <= 1'b1; case ({reg_rd_addr >> 2, 2'b00}) - 6'h00: begin - // PTP perout control + RBB+6'h00: reg_rd_data_reg <= 32'h0000C081; // PHC: Type + RBB+6'h04: reg_rd_data_reg <= 32'h00000100; // PHC: Version + RBB+6'h08: reg_rd_data_reg <= RB_NEXT_PTR; // PHC: Next header + RBB+6'h0C: begin + // PTP perout control and status reg_rd_data_reg[0] <= ptp_perout_enable_reg; + reg_rd_data_reg[8] <= ptp_perout_pulse; + reg_rd_data_reg[16] <= ptp_perout_locked; + reg_rd_data_reg[24] <= ptp_perout_error; end - 6'h04: begin - // PTP perout status - reg_rd_data_reg[0] <= ptp_perout_pulse; - reg_rd_data_reg[8] <= ptp_perout_locked; - reg_rd_data_reg[16] <= ptp_perout_error; - end - 6'h10: reg_rd_data_reg <= set_ptp_perout_start_reg[15:0]; // PTP perout start fns - 6'h14: reg_rd_data_reg <= set_ptp_perout_start_reg[45:16]; // PTP perout start ns - 6'h18: reg_rd_data_reg <= set_ptp_perout_start_reg[79:48]; // PTP perout start sec l - 6'h1C: reg_rd_data_reg <= set_ptp_perout_start_reg[95:80]; // PTP perout start sec h - 6'h20: reg_rd_data_reg <= set_ptp_perout_period_reg[15:0]; // PTP perout period fns - 6'h24: reg_rd_data_reg <= set_ptp_perout_period_reg[45:16]; // PTP perout period ns - 6'h28: reg_rd_data_reg <= set_ptp_perout_period_reg[79:48]; // PTP perout period sec l - 6'h2C: reg_rd_data_reg <= set_ptp_perout_period_reg[95:80]; // PTP perout period sec h - 6'h30: reg_rd_data_reg <= set_ptp_perout_width_reg[15:0]; // PTP perout width fns - 6'h34: reg_rd_data_reg <= set_ptp_perout_width_reg[45:16]; // PTP perout width ns - 6'h38: reg_rd_data_reg <= set_ptp_perout_width_reg[79:48]; // PTP perout width sec l - 6'h3C: reg_rd_data_reg <= set_ptp_perout_width_reg[95:80]; // PTP perout width sec h + RBB+6'h10: reg_rd_data_reg <= set_ptp_perout_start_reg[15:0]; // PTP perout start fns + RBB+6'h14: reg_rd_data_reg <= set_ptp_perout_start_reg[45:16]; // PTP perout start ns + RBB+6'h18: reg_rd_data_reg <= set_ptp_perout_start_reg[79:48]; // PTP perout start sec l + RBB+6'h1C: reg_rd_data_reg <= set_ptp_perout_start_reg[95:80]; // PTP perout start sec h + RBB+6'h20: reg_rd_data_reg <= set_ptp_perout_period_reg[15:0]; // PTP perout period fns + RBB+6'h24: reg_rd_data_reg <= set_ptp_perout_period_reg[45:16]; // PTP perout period ns + RBB+6'h28: reg_rd_data_reg <= set_ptp_perout_period_reg[79:48]; // PTP perout period sec l + RBB+6'h2C: reg_rd_data_reg <= set_ptp_perout_period_reg[95:80]; // PTP perout period sec h + RBB+6'h30: reg_rd_data_reg <= set_ptp_perout_width_reg[15:0]; // PTP perout width fns + RBB+6'h34: reg_rd_data_reg <= set_ptp_perout_width_reg[45:16]; // PTP perout width ns + RBB+6'h38: reg_rd_data_reg <= set_ptp_perout_width_reg[79:48]; // PTP perout width sec l + RBB+6'h3C: reg_rd_data_reg <= set_ptp_perout_width_reg[95:80]; // PTP perout width sec h default: reg_rd_ack_reg <= 1'b0; endcase end diff --git a/fpga/common/rtl/mqnic_tx_scheduler_block_rr.v b/fpga/common/rtl/mqnic_tx_scheduler_block_rr.v index 8b75d0239..67fcd1b22 100644 --- a/fpga/common/rtl/mqnic_tx_scheduler_block_rr.v +++ b/fpga/common/rtl/mqnic_tx_scheduler_block_rr.v @@ -48,6 +48,10 @@ module mqnic_tx_scheduler_block # parameter REG_DATA_WIDTH = 32, // Width of control register interface strb parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8), + // Register block base address + parameter RB_BASE_ADDR = 0, + // Register block next pointer + parameter RB_NEXT_PTR = 0, // Width of AXI lite data bus in bits parameter AXIL_DATA_WIDTH = 32, // Width of AXI lite address bus in bits @@ -146,6 +150,8 @@ module mqnic_tx_scheduler_block # parameter SCHED_COUNT = 1; parameter AXIL_SCHED_ADDR_WIDTH = AXIL_ADDR_WIDTH-$clog2(SCHED_COUNT); +localparam RBB = RB_BASE_ADDR & {REG_ADDR_WIDTH{1'b1}}; + // control registers reg ctrl_reg_wr_ack_reg = 1'b0; reg [REG_DATA_WIDTH-1:0] ctrl_reg_rd_data_reg = 0; @@ -168,8 +174,9 @@ always @(posedge clk) begin // write operation ctrl_reg_wr_ack_reg <= 1'b1; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // Scheduler enable + // Scheduler + RBB+8'h28: begin + // Sched: Control if (ctrl_reg_wr_strb[0]) begin sched_enable_reg <= ctrl_reg_wr_data[0]; end @@ -182,14 +189,23 @@ always @(posedge clk) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0010: ctrl_reg_rd_data_reg <= SCHED_COUNT; // scheduler_count - 16'h0014: ctrl_reg_rd_data_reg <= AXIL_OFFSET; // scheduler_offset - 16'h0018: ctrl_reg_rd_data_reg <= 2**AXIL_SCHED_ADDR_WIDTH; // scheduler_stride - 16'h001C: ctrl_reg_rd_data_reg <= 32'd0; // scheduler_type - 16'h0040: begin - // Scheduler enable + // Scheduler block + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C003; // Sched block: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // Sched block: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_NEXT_PTR; // Sched block: Next header + RBB+8'h0C: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // Sched block: Offset + // Round-robin scheduler + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C040; // Sched: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // Sched: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= 0; // Sched: Next header + RBB+8'h1C: ctrl_reg_rd_data_reg <= AXIL_OFFSET; // Sched: Offset + RBB+8'h20: ctrl_reg_rd_data_reg <= 2**QUEUE_INDEX_WIDTH; // Sched: Channel count + RBB+8'h24: ctrl_reg_rd_data_reg <= 4; // Sched: Channel stride + RBB+8'h28: begin + // Sched: Control ctrl_reg_rd_data_reg[0] <= sched_enable_reg; end + RBB+8'h2C: ctrl_reg_rd_data_reg <= 0; // Sched: dest default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end diff --git a/fpga/common/rtl/mqnic_tx_scheduler_block_rr_tdma.v b/fpga/common/rtl/mqnic_tx_scheduler_block_rr_tdma.v index bf399991e..0e693bc58 100644 --- a/fpga/common/rtl/mqnic_tx_scheduler_block_rr_tdma.v +++ b/fpga/common/rtl/mqnic_tx_scheduler_block_rr_tdma.v @@ -48,6 +48,10 @@ module mqnic_tx_scheduler_block # parameter REG_DATA_WIDTH = 32, // Width of control register interface strb parameter REG_STRB_WIDTH = (REG_DATA_WIDTH/8), + // Register block base address + parameter RB_BASE_ADDR = 0, + // Register block next pointer + parameter RB_NEXT_PTR = 0, // Width of AXI lite data bus in bits parameter AXIL_DATA_WIDTH = 32, // Width of AXI lite address bus in bits @@ -146,6 +150,8 @@ module mqnic_tx_scheduler_block # parameter SCHED_COUNT = 2; parameter AXIL_SCHED_ADDR_WIDTH = AXIL_ADDR_WIDTH-$clog2(SCHED_COUNT); +localparam RBB = RB_BASE_ADDR & {REG_ADDR_WIDTH{1'b1}}; + // parameter sizing helpers function [31:0] w_32(input [31:0] val); w_32 = val; @@ -224,43 +230,52 @@ always @(posedge clk) begin // write operation ctrl_reg_wr_ack_reg <= 1'b1; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // Scheduler enable + // Scheduler + RBB+8'h28: begin + // Sched: Control if (ctrl_reg_wr_strb[0]) begin sched_enable_reg <= ctrl_reg_wr_data[0]; end end - 16'h1000: begin - // TDMA control + // TDMA scheduler controller + RBB+8'h48: begin + // Sched ctrl: Control + if (ctrl_reg_wr_strb[0]) begin + // sched_enable_reg <= ctrl_reg_wr_data[0]; + end + end + // TDMA scheduler + RBB+8'h60: begin + // TDMA: control if (ctrl_reg_wr_strb[0]) begin tdma_enable_reg <= ctrl_reg_wr_data[0]; end end - 16'h1014: set_tdma_schedule_start_reg[29:0] <= ctrl_reg_wr_data; // TDMA schedule start ns - 16'h1018: set_tdma_schedule_start_reg[63:32] <= ctrl_reg_wr_data; // TDMA schedule start sec l - 16'h101C: begin - // TDMA schedule start sec h + RBB+8'h74: set_tdma_schedule_start_reg[29:0] <= ctrl_reg_wr_data; // TDMA: schedule start ns + RBB+8'h78: set_tdma_schedule_start_reg[63:32] <= ctrl_reg_wr_data; // TDMA: schedule start sec l + RBB+8'h7C: begin + // TDMA: schedule start sec h set_tdma_schedule_start_reg[79:64] <= ctrl_reg_wr_data; set_tdma_schedule_start_valid_reg <= 1'b1; end - 16'h1024: set_tdma_schedule_period_reg[29:0] <= ctrl_reg_wr_data; // TDMA schedule period ns - 16'h1028: set_tdma_schedule_period_reg[63:32] <= ctrl_reg_wr_data; // TDMA schedule period sec l - 16'h102C: begin - // TDMA schedule period sec h + RBB+8'h84: set_tdma_schedule_period_reg[29:0] <= ctrl_reg_wr_data; // TDMA: schedule period ns + RBB+8'h88: set_tdma_schedule_period_reg[63:32] <= ctrl_reg_wr_data; // TDMA: schedule period sec l + RBB+8'h8C: begin + // TDMA: schedule period sec h set_tdma_schedule_period_reg[79:64] <= ctrl_reg_wr_data; set_tdma_schedule_period_valid_reg <= 1'b1; end - 16'h1034: set_tdma_timeslot_period_reg[29:0] <= ctrl_reg_wr_data; // TDMA timeslot period ns - 16'h1038: set_tdma_timeslot_period_reg[63:32] <= ctrl_reg_wr_data; // TDMA timeslot period sec l - 16'h103C: begin - // TDMA timeslot period sec h + RBB+8'h94: set_tdma_timeslot_period_reg[29:0] <= ctrl_reg_wr_data; // TDMA: timeslot period ns + RBB+8'h98: set_tdma_timeslot_period_reg[63:32] <= ctrl_reg_wr_data; // TDMA: timeslot period sec l + RBB+8'h9C: begin + // TDMA: timeslot period sec h set_tdma_timeslot_period_reg[79:64] <= ctrl_reg_wr_data; set_tdma_timeslot_period_valid_reg <= 1'b1; end - 16'h1044: set_tdma_active_period_reg[29:0] <= ctrl_reg_wr_data; // TDMA active period ns - 16'h1048: set_tdma_active_period_reg[63:32] <= ctrl_reg_wr_data; // TDMA active period sec l - 16'h104C: begin - // TDMA active period sec h + RBB+8'hA4: set_tdma_active_period_reg[29:0] <= ctrl_reg_wr_data; // TDMA: active period ns + RBB+8'hA8: set_tdma_active_period_reg[63:32] <= ctrl_reg_wr_data; // TDMA: active period sec l + RBB+8'hAC: begin + // TDMA: active period sec h set_tdma_active_period_reg[79:64] <= ctrl_reg_wr_data; set_tdma_active_period_valid_reg <= 1'b1; end @@ -272,36 +287,61 @@ always @(posedge clk) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0010: ctrl_reg_rd_data_reg <= SCHED_COUNT; // scheduler_count - 16'h0014: ctrl_reg_rd_data_reg <= AXIL_OFFSET; // scheduler_offset - 16'h0018: ctrl_reg_rd_data_reg <= 2**AXIL_SCHED_ADDR_WIDTH; // scheduler_stride - 16'h001C: ctrl_reg_rd_data_reg <= 32'd0; // scheduler_type - 16'h0040: begin - // Scheduler enable + // Scheduler block + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C003; // Sched block: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // Sched block: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_NEXT_PTR; // Sched block: Next header + RBB+8'h0C: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // Sched block: Offset + // Scheduler + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C040; // Sched: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // Sched: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // Sched: Next header + RBB+8'h1C: ctrl_reg_rd_data_reg <= AXIL_OFFSET; // Sched: Offset + RBB+8'h20: ctrl_reg_rd_data_reg <= 2**QUEUE_INDEX_WIDTH; // Sched: Channel count + RBB+8'h24: ctrl_reg_rd_data_reg <= 4; // Sched: Channel stride + RBB+8'h28: begin + // Sched: Control ctrl_reg_rd_data_reg[0] <= sched_enable_reg; end - 16'h1000: begin - // TDMA control + RBB+8'h2C: ctrl_reg_rd_data_reg <= 0; // Sched: dest + // TDMA scheduler controller + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C050; // Sched ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // Sched ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // Sched ctrl: Next header + RBB+8'h3C: ctrl_reg_rd_data_reg <= AXIL_OFFSET+2**(AXIL_ADDR_WIDTH-1); // Sched ctrl: Offset + RBB+8'h40: ctrl_reg_rd_data_reg <= 2**QUEUE_INDEX_WIDTH; // Sched ctrl: Channel count + RBB+8'h44: ctrl_reg_rd_data_reg <= 4*((2**TDMA_INDEX_WIDTH+31)/32); // Sched ctrl: Channel stride + RBB+8'h48: begin + // Sched ctrl: Control + ctrl_reg_rd_data_reg[0] <= 1'b1; + end + RBB+8'h4C: ctrl_reg_rd_data_reg <= 2**TDMA_INDEX_WIDTH; // Sched ctrl: Timeslot count + // TDMA scheduler + RBB+8'h50: ctrl_reg_rd_data_reg <= 32'h0000C060; // TDMA: Type + RBB+8'h54: ctrl_reg_rd_data_reg <= 32'h00000100; // TDMA: Version + RBB+8'h58: ctrl_reg_rd_data_reg <= 0; // TDMA: Next header + RBB+8'h5C: ctrl_reg_rd_data_reg <= 2**TDMA_INDEX_WIDTH; // TDMA: Timeslot count + RBB+8'h60: begin + // TDMA: control ctrl_reg_rd_data_reg[0] <= tdma_enable_reg; end - 16'h1004: begin - // TDMA status + RBB+8'h64: begin + // TDMA: status ctrl_reg_rd_data_reg[0] <= tdma_locked; ctrl_reg_rd_data_reg[1] <= tdma_error; end - 16'h1008: ctrl_reg_rd_data_reg <= 2**TDMA_INDEX_WIDTH; // TDMA timeslot count - 16'h1014: ctrl_reg_rd_data_reg <= set_tdma_schedule_start_reg[29:0]; // TDMA schedule start ns - 16'h1018: ctrl_reg_rd_data_reg <= set_tdma_schedule_start_reg[63:32]; // TDMA schedule start sec l - 16'h101C: ctrl_reg_rd_data_reg <= set_tdma_schedule_start_reg[79:64]; // TDMA schedule start sec h - 16'h1024: ctrl_reg_rd_data_reg <= set_tdma_schedule_period_reg[29:0]; // TDMA schedule period ns - 16'h1028: ctrl_reg_rd_data_reg <= set_tdma_schedule_period_reg[63:32]; // TDMA schedule period sec l - 16'h102C: ctrl_reg_rd_data_reg <= set_tdma_schedule_period_reg[79:64]; // TDMA schedule period sec h - 16'h1034: ctrl_reg_rd_data_reg <= set_tdma_timeslot_period_reg[29:0]; // TDMA timeslot period ns - 16'h1038: ctrl_reg_rd_data_reg <= set_tdma_timeslot_period_reg[63:32]; // TDMA timeslot period sec l - 16'h103C: ctrl_reg_rd_data_reg <= set_tdma_timeslot_period_reg[79:64]; // TDMA timeslot period sec h - 16'h1044: ctrl_reg_rd_data_reg <= set_tdma_active_period_reg[29:0]; // TDMA active period ns - 16'h1048: ctrl_reg_rd_data_reg <= set_tdma_active_period_reg[63:32]; // TDMA active period sec l - 16'h104C: ctrl_reg_rd_data_reg <= set_tdma_active_period_reg[79:64]; // TDMA active period sec h + RBB+8'h74: ctrl_reg_rd_data_reg <= set_tdma_schedule_start_reg[29:0]; // TDMA: schedule start ns + RBB+8'h78: ctrl_reg_rd_data_reg <= set_tdma_schedule_start_reg[63:32]; // TDMA: schedule start sec l + RBB+8'h7C: ctrl_reg_rd_data_reg <= set_tdma_schedule_start_reg[79:64]; // TDMA: schedule start sec h + RBB+8'h84: ctrl_reg_rd_data_reg <= set_tdma_schedule_period_reg[29:0]; // TDMA: schedule period ns + RBB+8'h88: ctrl_reg_rd_data_reg <= set_tdma_schedule_period_reg[63:32]; // TDMA: schedule period sec l + RBB+8'h8C: ctrl_reg_rd_data_reg <= set_tdma_schedule_period_reg[79:64]; // TDMA: schedule period sec h + RBB+8'h94: ctrl_reg_rd_data_reg <= set_tdma_timeslot_period_reg[29:0]; // TDMA: timeslot period ns + RBB+8'h98: ctrl_reg_rd_data_reg <= set_tdma_timeslot_period_reg[63:32]; // TDMA: timeslot period sec l + RBB+8'h9C: ctrl_reg_rd_data_reg <= set_tdma_timeslot_period_reg[79:64]; // TDMA: timeslot period sec h + RBB+8'hA4: ctrl_reg_rd_data_reg <= set_tdma_active_period_reg[29:0]; // TDMA: active period ns + RBB+8'hA8: ctrl_reg_rd_data_reg <= set_tdma_active_period_reg[63:32]; // TDMA: active period sec l + RBB+8'hAC: ctrl_reg_rd_data_reg <= set_tdma_active_period_reg[79:64]; // TDMA: active period sec h default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end diff --git a/fpga/common/tb/mqnic.py b/fpga/common/tb/mqnic.py index 6584d24fc..d69fef808 100644 --- a/fpga/common/tb/mqnic.py +++ b/fpga/common/tb/mqnic.py @@ -31,6 +31,7 @@ either expressed or implied, of The Regents of the University of California. """ +import datetime from collections import deque import cocotb @@ -38,6 +39,8 @@ from cocotb.log import SimLog from cocotb.queue import Queue from cocotb.triggers import Event, Edge, RisingEdge +from cocotbext.axi import Window + import struct MQNIC_MAX_EVENT_RINGS = 1 @@ -46,147 +49,201 @@ MQNIC_MAX_TX_CPL_RINGS = 32 MQNIC_MAX_RX_RINGS = 8 MQNIC_MAX_RX_CPL_RINGS = 8 -MQNIC_QUEUE_STRIDE = 0x00000020 -MQNIC_CPL_QUEUE_STRIDE = 0x00000020 -MQNIC_EVENT_QUEUE_STRIDE = 0x00000020 +# Register blocks +MQNIC_RB_REG_TYPE = 0x00 +MQNIC_RB_REG_VER = 0x04 +MQNIC_RB_REG_NEXT_PTR = 0x08 -# NIC CSRs -MQNIC_REG_FW_ID = 0x0000 -MQNIC_REG_FW_VER = 0x0004 -MQNIC_REG_BOARD_ID = 0x0008 -MQNIC_REG_BOARD_VER = 0x000C +MQNIC_RB_FW_ID_TYPE = 0xFFFFFFFF +MQNIC_RB_FW_ID_VER = 0x00000100 +MQNIC_RB_FW_ID_REG_FPGA_ID = 0x0C +MQNIC_RB_FW_ID_REG_FW_ID = 0x10 +MQNIC_RB_FW_ID_REG_FW_VER = 0x14 +MQNIC_RB_FW_ID_REG_BOARD_ID = 0x18 +MQNIC_RB_FW_ID_REG_BOARD_VER = 0x1C +MQNIC_RB_FW_ID_REG_BUILD_DATE = 0x20 +MQNIC_RB_FW_ID_REG_GIT_HASH = 0x24 +MQNIC_RB_FW_ID_REG_REL_INFO = 0x28 -MQNIC_REG_PHC_COUNT = 0x0010 -MQNIC_REG_PHC_OFFSET = 0x0014 +MQNIC_RB_GPIO_TYPE = 0x0000C100 +MQNIC_RB_GPIO_VER = 0x00000100 +MQNIC_RB_GPIO_REG_GPIO_IN = 0x0C +MQNIC_RB_GPIO_REG_GPIO_OUT = 0x10 -MQNIC_REG_IF_COUNT = 0x0020 -MQNIC_REG_IF_STRIDE = 0x0024 -MQNIC_REG_IF_CSR_OFFSET = 0x002C +MQNIC_RB_I2C_TYPE = 0x0000C110 +MQNIC_RB_I2C_VER = 0x00000100 +MQNIC_RB_I2C_REG_CTRL = 0x0C -MQNIC_REG_FPGA_ID = 0x0040 +MQNIC_RB_SPI_FLASH_TYPE = 0x0000C120 +MQNIC_RB_SPI_FLASH_VER = 0x00000100 +MQNIC_RB_SPI_FLASH_REG_FORMAT = 0x0C +MQNIC_RB_SPI_FLASH_REG_CTRL_0 = 0x10 +MQNIC_RB_SPI_FLASH_REG_CTRL_1 = 0x14 -MQNIC_REG_GPIO_OUT = 0x0100 -MQNIC_REG_GPIO_IN = 0x0104 +MQNIC_RB_BPI_FLASH_TYPE = 0x0000C121 +MQNIC_RB_BPI_FLASH_VER = 0x00000100 +MQNIC_RB_BPI_FLASH_REG_FORMAT = 0x0C +MQNIC_RB_BPI_FLASH_REG_ADDR = 0x10 +MQNIC_RB_BPI_FLASH_REG_DATA = 0x14 +MQNIC_RB_BPI_FLASH_REG_CTRL = 0x18 -MQNIC_REG_GPIO_I2C_0 = 0x0110 -MQNIC_REG_GPIO_I2C_1 = 0x0114 -MQNIC_REG_GPIO_I2C_2 = 0x0118 -MQNIC_REG_GPIO_I2C_3 = 0x011C +MQNIC_RB_ALVEO_BMC_TYPE = 0x0000C140 +MQNIC_RB_ALVEO_BMC_VER = 0x00000100 +MQNIC_RB_ALVEO_BMC_REG_ADDR = 0x0C +MQNIC_RB_ALVEO_BMC_REG_DATA = 0x10 -MQNIC_REG_GPIO_I2C_SCL_IN = 0x00000001 -MQNIC_REG_GPIO_I2C_SCL_OUT = 0x00000002 -MQNIC_REG_GPIO_I2C_SDA_IN = 0x00000100 -MQNIC_REG_GPIO_I2C_SDA_OUT = 0x00000200 +MQNIC_RB_GECKO_BMC_TYPE = 0x0000C141 +MQNIC_RB_GECKO_BMC_VER = 0x00000100 +MQNIC_RB_GECKO_BMC_REG_STATUS = 0x0C +MQNIC_RB_GECKO_BMC_REG_DATA = 0x10 +MQNIC_RB_GECKO_BMC_REG_CMD = 0x14 -MQNIC_REG_GPIO_XCVR_0123 = 0x0120 -MQNIC_REG_GPIO_XCVR_4567 = 0x0124 +MQNIC_RB_STATS_TYPE = 0x0000C004 +MQNIC_RB_STATS_VER = 0x00000100 +MQNIC_RB_STATS_REG_OFFSET = 0x0C +MQNIC_RB_STATS_REG_COUNT = 0x10 +MQNIC_RB_STATS_REG_STRIDE = 0x14 +MQNIC_RB_STATS_REG_FLAGS = 0x18 -MQNIC_REG_GPIO_XCVR_PRSNT_IN = 0x01 -MQNIC_REG_GPIO_XCVR_TX_FAULT_INT_IN = 0x02 -MQNIC_REG_GPIO_XCVR_RX_LOS_IN = 0x03 -MQNIC_REG_GPIO_XCVR_RST_OUT = 0x10 -MQNIC_REG_GPIO_XCVR_TX_DIS_LPMODE_OUT = 0x20 -MQNIC_REG_GPIO_XCVR_RS0_OUT = 0x40 -MQNIC_REG_GPIO_XCVR_RS1_OUT = 0x80 +MQNIC_RB_PHC_TYPE = 0x0000C080 +MQNIC_RB_PHC_VER = 0x00000100 +MQNIC_RB_PHC_REG_CTRL = 0x0C +MQNIC_RB_PHC_REG_CUR_FNS = 0x10 +MQNIC_RB_PHC_REG_CUR_NS = 0x14 +MQNIC_RB_PHC_REG_CUR_SEC_L = 0x18 +MQNIC_RB_PHC_REG_CUR_SEC_H = 0x1C +MQNIC_RB_PHC_REG_GET_FNS = 0x20 +MQNIC_RB_PHC_REG_GET_NS = 0x24 +MQNIC_RB_PHC_REG_GET_SEC_L = 0x28 +MQNIC_RB_PHC_REG_GET_SEC_H = 0x2C +MQNIC_RB_PHC_REG_SET_FNS = 0x30 +MQNIC_RB_PHC_REG_SET_NS = 0x34 +MQNIC_RB_PHC_REG_SET_SEC_L = 0x38 +MQNIC_RB_PHC_REG_SET_SEC_H = 0x3C +MQNIC_RB_PHC_REG_PERIOD_FNS = 0x40 +MQNIC_RB_PHC_REG_PERIOD_NS = 0x44 +MQNIC_RB_PHC_REG_NOM_PERIOD_FNS = 0x48 +MQNIC_RB_PHC_REG_NOM_PERIOD_NS = 0x4C +MQNIC_RB_PHC_REG_ADJ_FNS = 0x50 +MQNIC_RB_PHC_REG_ADJ_NS = 0x54 +MQNIC_RB_PHC_REG_ADJ_COUNT = 0x58 +MQNIC_RB_PHC_REG_ADJ_ACTIVE = 0x5C -MQNIC_PHC_REG_FEATURES = 0x0000 -MQNIC_PHC_REG_PTP_CUR_FNS = 0x0010 -MQNIC_PHC_REG_PTP_CUR_NS = 0x0014 -MQNIC_PHC_REG_PTP_CUR_SEC_L = 0x0018 -MQNIC_PHC_REG_PTP_CUR_SEC_H = 0x001C -MQNIC_PHC_REG_PTP_GET_FNS = 0x0020 -MQNIC_PHC_REG_PTP_GET_NS = 0x0024 -MQNIC_PHC_REG_PTP_GET_SEC_L = 0x0028 -MQNIC_PHC_REG_PTP_GET_SEC_H = 0x002C -MQNIC_PHC_REG_PTP_SET_FNS = 0x0030 -MQNIC_PHC_REG_PTP_SET_NS = 0x0034 -MQNIC_PHC_REG_PTP_SET_SEC_L = 0x0038 -MQNIC_PHC_REG_PTP_SET_SEC_H = 0x003C -MQNIC_PHC_REG_PTP_PERIOD_FNS = 0x0040 -MQNIC_PHC_REG_PTP_PERIOD_NS = 0x0044 -MQNIC_PHC_REG_PTP_NOM_PERIOD_FNS = 0x0048 -MQNIC_PHC_REG_PTP_NOM_PERIOD_NS = 0x004C -MQNIC_PHC_REG_PTP_ADJ_FNS = 0x0050 -MQNIC_PHC_REG_PTP_ADJ_NS = 0x0054 -MQNIC_PHC_REG_PTP_ADJ_COUNT = 0x0058 -MQNIC_PHC_REG_PTP_ADJ_ACTIVE = 0x005C +MQNIC_RB_PHC_PEROUT_TYPE = 0x0000C081 +MQNIC_RB_PHC_PEROUT_VER = 0x00000100 +MQNIC_RB_PHC_PEROUT_REG_CTRL = 0x0C +MQNIC_RB_PHC_PEROUT_REG_START_FNS = 0x10 +MQNIC_RB_PHC_PEROUT_REG_START_NS = 0x14 +MQNIC_RB_PHC_PEROUT_REG_START_SEC_L = 0x18 +MQNIC_RB_PHC_PEROUT_REG_START_SEC_H = 0x1C +MQNIC_RB_PHC_PEROUT_REG_PERIOD_FNS = 0x20 +MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS = 0x24 +MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L = 0x28 +MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H = 0x2C +MQNIC_RB_PHC_PEROUT_REG_WIDTH_FNS = 0x30 +MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS = 0x34 +MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L = 0x38 +MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H = 0x3C -MQNIC_PHC_REG_PEROUT_CTRL = 0x0000 -MQNIC_PHC_REG_PEROUT_STATUS = 0x0004 -MQNIC_PHC_REG_PEROUT_START_FNS = 0x0010 -MQNIC_PHC_REG_PEROUT_START_NS = 0x0014 -MQNIC_PHC_REG_PEROUT_START_SEC_L = 0x0018 -MQNIC_PHC_REG_PEROUT_START_SEC_H = 0x001C -MQNIC_PHC_REG_PEROUT_PERIOD_FNS = 0x0020 -MQNIC_PHC_REG_PEROUT_PERIOD_NS = 0x0024 -MQNIC_PHC_REG_PEROUT_PERIOD_SEC_L = 0x0028 -MQNIC_PHC_REG_PEROUT_PERIOD_SEC_H = 0x002C -MQNIC_PHC_REG_PEROUT_WIDTH_FNS = 0x0030 -MQNIC_PHC_REG_PEROUT_WIDTH_NS = 0x0034 -MQNIC_PHC_REG_PEROUT_WIDTH_SEC_L = 0x0038 -MQNIC_PHC_REG_PEROUT_WIDTH_SEC_H = 0x003C +MQNIC_RB_IF_TYPE = 0x0000C000 +MQNIC_RB_IF_VER = 0x00000100 +MQNIC_RB_IF_REG_OFFSET = 0x0C +MQNIC_RB_IF_REG_COUNT = 0x10 +MQNIC_RB_IF_REG_STRIDE = 0x14 +MQNIC_RB_IF_REG_CSR_OFFSET = 0x18 -# Interface CSRs -MQNIC_IF_REG_IF_ID = 0x0000 -MQNIC_IF_REG_IF_FEATURES = 0x0004 +MQNIC_RB_IF_CTRL_TX_TYPE = 0x0000C001 +MQNIC_RB_IF_CTRL_TX_VER = 0x00000100 +MQNIC_RB_IF_CTRL_TX_REG_FEATURES = 0x0C +MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU = 0x10 +MQNIC_RB_IF_CTRL_TX_REG_MTU = 0x14 -MQNIC_IF_REG_EVENT_QUEUE_COUNT = 0x0010 -MQNIC_IF_REG_EVENT_QUEUE_OFFSET = 0x0014 -MQNIC_IF_REG_TX_QUEUE_COUNT = 0x0020 -MQNIC_IF_REG_TX_QUEUE_OFFSET = 0x0024 -MQNIC_IF_REG_TX_CPL_QUEUE_COUNT = 0x0028 -MQNIC_IF_REG_TX_CPL_QUEUE_OFFSET = 0x002C -MQNIC_IF_REG_RX_QUEUE_COUNT = 0x0030 -MQNIC_IF_REG_RX_QUEUE_OFFSET = 0x0034 -MQNIC_IF_REG_RX_CPL_QUEUE_COUNT = 0x0038 -MQNIC_IF_REG_RX_CPL_QUEUE_OFFSET = 0x003C -MQNIC_IF_REG_PORT_COUNT = 0x0040 -MQNIC_IF_REG_PORT_OFFSET = 0x0044 -MQNIC_IF_REG_PORT_STRIDE = 0x0048 +MQNIC_IF_TX_FEATURE_PTP_TS = (1 << 4) +MQNIC_IF_TX_FEATURE_CSUM = (1 << 8) -MQNIC_IF_FEATURE_RSS = (1 << 0) -MQNIC_IF_FEATURE_PTP_TS = (1 << 4) -MQNIC_IF_FEATURE_TX_CSUM = (1 << 8) -MQNIC_IF_FEATURE_RX_CSUM = (1 << 9) +MQNIC_RB_IF_CTRL_RX_TYPE = 0x0000C002 +MQNIC_RB_IF_CTRL_RX_VER = 0x00000100 +MQNIC_RB_IF_CTRL_RX_REG_FEATURES = 0x0C +MQNIC_RB_IF_CTRL_RX_REG_MAX_MTU = 0x10 +MQNIC_RB_IF_CTRL_RX_REG_MTU = 0x14 +MQNIC_RB_IF_CTRL_RX_REG_RSS_MASK = 0x18 -# Port CSRs -MQNIC_PORT_REG_PORT_ID = 0x0000 -MQNIC_PORT_REG_PORT_FEATURES = 0x0004 -MQNIC_PORT_REG_PORT_MTU = 0x0008 +MQNIC_IF_RX_FEATURE_RSS = (1 << 0) +MQNIC_IF_RX_FEATURE_PTP_TS = (1 << 4) +MQNIC_IF_RX_FEATURE_CSUM = (1 << 8) +MQNIC_IF_RX_FEATURE_HASH = (1 << 9) -MQNIC_PORT_REG_SCHED_COUNT = 0x0010 -MQNIC_PORT_REG_SCHED_OFFSET = 0x0014 -MQNIC_PORT_REG_SCHED_STRIDE = 0x0018 -MQNIC_PORT_REG_SCHED_TYPE = 0x001C -MQNIC_PORT_REG_SCHED_ENABLE = 0x0040 +MQNIC_RB_EVENT_QM_TYPE = 0x0000C010 +MQNIC_RB_EVENT_QM_VER = 0x00000100 +MQNIC_RB_EVENT_QM_REG_OFFSET = 0x0C +MQNIC_RB_EVENT_QM_REG_COUNT = 0x10 +MQNIC_RB_EVENT_QM_REG_STRIDE = 0x14 -MQNIC_PORT_REG_TX_MTU = 0x0100 -MQNIC_PORT_REG_RX_MTU = 0x0200 +MQNIC_RB_TX_QM_TYPE = 0x0000C020 +MQNIC_RB_TX_QM_VER = 0x00000100 +MQNIC_RB_TX_QM_REG_OFFSET = 0x0C +MQNIC_RB_TX_QM_REG_COUNT = 0x10 +MQNIC_RB_TX_QM_REG_STRIDE = 0x14 -MQNIC_PORT_REG_TDMA_CTRL = 0x1000 -MQNIC_PORT_REG_TDMA_STATUS = 0x1004 -MQNIC_PORT_REG_TDMA_TIMESLOT_COUNT = 0x1008 -MQNIC_PORT_REG_TDMA_SCHED_START_FNS = 0x1010 -MQNIC_PORT_REG_TDMA_SCHED_START_NS = 0x1014 -MQNIC_PORT_REG_TDMA_SCHED_START_SEC_L = 0x1018 -MQNIC_PORT_REG_TDMA_SCHED_START_SEC_H = 0x101C -MQNIC_PORT_REG_TDMA_SCHED_PERIOD_FNS = 0x1020 -MQNIC_PORT_REG_TDMA_SCHED_PERIOD_NS = 0x1024 -MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_L = 0x1028 -MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_H = 0x102C -MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_FNS = 0x1030 -MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_NS = 0x1034 -MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_L = 0x1038 -MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_H = 0x103C -MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_FNS = 0x1040 -MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_NS = 0x1044 -MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_L = 0x1048 -MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_H = 0x104C +MQNIC_RB_TX_CQM_TYPE = 0x0000C030 +MQNIC_RB_TX_CQM_VER = 0x00000100 +MQNIC_RB_TX_CQM_REG_OFFSET = 0x0C +MQNIC_RB_TX_CQM_REG_COUNT = 0x10 +MQNIC_RB_TX_CQM_REG_STRIDE = 0x14 -MQNIC_PORT_FEATURE_RSS = (1 << 0) -MQNIC_PORT_FEATURE_PTP_TS = (1 << 4) -MQNIC_PORT_FEATURE_TX_CSUM = (1 << 8) -MQNIC_PORT_FEATURE_RX_CSUM = (1 << 9) +MQNIC_RB_RX_QM_TYPE = 0x0000C021 +MQNIC_RB_RX_QM_VER = 0x00000100 +MQNIC_RB_RX_QM_REG_OFFSET = 0x0C +MQNIC_RB_RX_QM_REG_COUNT = 0x10 +MQNIC_RB_RX_QM_REG_STRIDE = 0x14 + +MQNIC_RB_RX_CQM_TYPE = 0x0000C031 +MQNIC_RB_RX_CQM_VER = 0x00000100 +MQNIC_RB_RX_CQM_REG_OFFSET = 0x0C +MQNIC_RB_RX_CQM_REG_COUNT = 0x10 +MQNIC_RB_RX_CQM_REG_STRIDE = 0x14 + +MQNIC_RB_SCHED_BLOCK_TYPE = 0x0000C003 +MQNIC_RB_SCHED_BLOCK_VER = 0x00000100 +MQNIC_RB_SCHED_BLOCK_REG_OFFSET = 0x0C + +MQNIC_RB_SCHED_RR_TYPE = 0x0000C040 +MQNIC_RB_SCHED_RR_VER = 0x00000100 +MQNIC_RB_SCHED_RR_REG_OFFSET = 0x0C +MQNIC_RB_SCHED_RR_REG_CH_COUNT = 0x10 +MQNIC_RB_SCHED_RR_REG_CH_STRIDE = 0x14 +MQNIC_RB_SCHED_RR_REG_CTRL = 0x18 +MQNIC_RB_SCHED_RR_REG_DEST = 0x1C + +MQNIC_RB_SCHED_CTRL_TDMA_TYPE = 0x0000C050 +MQNIC_RB_SCHED_CTRL_TDMA_VER = 0x00000100 +MQNIC_RB_SCHED_CTRL_TDMA_REG_OFFSET = 0x0C +MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_COUNT = 0x10 +MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_STRIDE = 0x14 +MQNIC_RB_SCHED_CTRL_TDMA_REG_CTRL = 0x18 +MQNIC_RB_SCHED_CTRL_TDMA_REG_TS_COUNT = 0x1C + +MQNIC_RB_TDMA_SCH_TYPE = 0x0000C060 +MQNIC_RB_TDMA_SCH_VER = 0x00000100 +MQNIC_RB_TDMA_SCH_REG_TS_COUNT = 0x0C +MQNIC_RB_TDMA_SCH_REG_CTRL = 0x10 +MQNIC_RB_TDMA_SCH_REG_STATUS = 0x14 +MQNIC_RB_TDMA_SCH_REG_SCH_START_FNS = 0x20 +MQNIC_RB_TDMA_SCH_REG_SCH_START_NS = 0x24 +MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L = 0x28 +MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H = 0x2C +MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_FNS = 0x30 +MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS = 0x34 +MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L = 0x38 +MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H = 0x3C +MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_FNS = 0x40 +MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS = 0x44 +MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L = 0x48 +MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H = 0x4C +MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_FNS = 0x50 +MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS = 0x54 +MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L = 0x58 +MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H = 0x5C MQNIC_QUEUE_BASE_ADDR_REG = 0x00 MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG = 0x08 @@ -226,6 +283,50 @@ MQNIC_CPL_SIZE = 32 MQNIC_EVENT_SIZE = 32 +class RegBlock(Window): + def __init__(self, parent, offset, size, base=0, **kwargs): + super().__init__(parent, offset, size, base, **kwargs) + self._offset = offset + self.type = 0 + self.version = 0 + + +class RegBlockList: + def __init__(self): + self.blocks = [] + + async def enumerate_reg_blocks(self, window, offset=0): + while True: + rb_type = await window.read_dword(offset+MQNIC_RB_REG_TYPE) + rb_version = await window.read_dword(offset+MQNIC_RB_REG_VER) + rb = window.create_window(offset, window_type=RegBlock) + rb.type = rb_type + rb.version = rb_version + print(f"Block ID {rb_type:#010x} version {rb_version:#010x} at offset {offset:#010x}") + self.blocks.append(rb) + offset = await window.read_dword(offset+MQNIC_RB_REG_NEXT_PTR) + if offset == 0: + return + assert offset & 0x3 == 0, "Register block not aligned" + for block in self.blocks: + assert block.offset != offset, "Register blocks form a loop" + + def find(self, rb_type, version=None, index=0): + for block in self.blocks: + if block.type == rb_type and (not version or block.version == version): + if index <= 0: + return block + else: + index -= 1 + return None + + def __getitem__(self, key): + return self.blocks[key] + + def __len__(self): + return len(self.blocks) + + class Packet: def __init__(self, data=b''): self.data = data @@ -615,63 +716,76 @@ class RxRing: await self.write_head_ptr() -class Scheduler: - def __init__(self, port, index, hw_regs): +class BaseScheduler: + def __init__(self, port, index, rb): self.port = port self.log = port.log self.interface = port.interface self.driver = port.interface.driver - self.rc = port.interface.driver.rc self.index = index - self.hw_regs = hw_regs + self.rb = rb + self.hw_regs = None + + async def init(self): + pass + + +class SchedulerRoundRobin(BaseScheduler): + def __init__(self, port, index, rb): + super().__init__(port, index, rb) + + async def init(self): + offset = await self.rb.read_dword(MQNIC_RB_SCHED_RR_REG_OFFSET) + self.hw_regs = self.rb.parent.create_window(offset) + + +class SchedulerControlTdma(BaseScheduler): + def __init__(self, port, index, rb): + super().__init__(port, index, rb) + + async def init(self): + offset = await self.rb.read_dword(MQNIC_RB_SCHED_CTRL_TDMA_REG_OFFSET) + self.hw_regs = self.rb.parent.create_window(offset) class Port: - def __init__(self, interface, index, hw_regs): + def __init__(self, interface, index, rb): self.interface = interface self.log = interface.log self.driver = interface.driver - self.rc = interface.driver.rc self.index = index - self.hw_regs = hw_regs - self.port_id = None - self.port_features = None - self.port_mtu = 0 + self.block_rb = rb + self.reg_blocks = RegBlockList() + self.sched_count = None - self.sched_offset = None - self.sched_stride = None - self.sched_type = None - - async def init(self): - # Read ID registers - self.port_id = await self.hw_regs.read_dword(MQNIC_PORT_REG_PORT_ID) - self.log.info("Port ID: 0x%08x", self.port_id) - self.port_features = await self.hw_regs.read_dword(MQNIC_PORT_REG_PORT_FEATURES) - self.log.info("Port features: 0x%08x", self.port_features) - self.port_mtu = await self.hw_regs.read_dword(MQNIC_PORT_REG_PORT_MTU) - self.log.info("Port MTU: %d", self.port_mtu) - - self.sched_count = await self.hw_regs.read_dword(MQNIC_PORT_REG_SCHED_COUNT) - self.log.info("Scheduler count: %d", self.sched_count) - self.sched_offset = await self.hw_regs.read_dword(MQNIC_PORT_REG_SCHED_OFFSET) - self.log.info("Scheduler offset: 0x%08x", self.sched_offset) - self.sched_stride = await self.hw_regs.read_dword(MQNIC_PORT_REG_SCHED_STRIDE) - self.log.info("Scheduler stride: 0x%08x", self.sched_stride) - self.sched_type = await self.hw_regs.read_dword(MQNIC_PORT_REG_SCHED_TYPE) - self.log.info("Scheduler type: 0x%08x", self.sched_type) self.schedulers = [] - await self.set_mtu(min(self.port_mtu, 9214)) + async def init(self): + # Read ID registers - for k in range(self.sched_count): - p = Scheduler(self, k, self.hw_regs.parent.create_window(self.hw_regs.get_parent_address(0) + self.sched_offset + k*self.sched_stride, self.sched_stride)) - self.schedulers.append(p) + offset = await self.block_rb.read_dword(MQNIC_RB_SCHED_BLOCK_REG_OFFSET) + await self.reg_blocks.enumerate_reg_blocks(self.block_rb.parent, offset) - async def set_mtu(self, mtu): - await self.hw_regs.write_dword(MQNIC_PORT_REG_TX_MTU, mtu) - await self.hw_regs.write_dword(MQNIC_PORT_REG_RX_MTU, mtu) + self.schedulers = [] + + self.sched_count = 0 + for rb in self.reg_blocks: + if rb.type == MQNIC_RB_SCHED_RR_TYPE and rb.version == MQNIC_RB_SCHED_RR_VER: + s = SchedulerRoundRobin(self, self.sched_count, rb) + await s.init() + self.schedulers.append(s) + + self.sched_count += 1 + elif rb.type == MQNIC_RB_SCHED_CTRL_TDMA_TYPE and rb.version == MQNIC_RB_SCHED_CTRL_TDMA_VER: + s = SchedulerControlTdma(self, self.sched_count, rb) + await s.init() + self.schedulers.append(s) + + self.sched_count += 1 + + self.log.info("Scheduler count: %d", self.sched_count) class Interface: @@ -680,23 +794,49 @@ class Interface: self.log = driver.log self.index = index self.hw_regs = hw_regs - self.csr_hw_regs = hw_regs.create_window(driver.if_csr_offset, self.hw_regs.size-driver.if_csr_offset) + self.csr_hw_regs = hw_regs.create_window(driver.if_csr_offset) self.port_up = False - self.if_id = None - self.event_queue_count = None + self.reg_blocks = RegBlockList() + self.if_ctrl_tx_rb = None + self.if_ctrl_rx_rb = None + self.event_queue_rb = None + self.tx_queue_rb = None + self.tx_cpl_queue_rb = None + self.rx_queue_rb = None + self.rx_cpl_queue_rb = None + + self.if_tx_features = None + self.if_rx_features = None + + self.max_tx_mtu = 0 + self.max_rx_mtu = 0 + self.event_queue_offset = None - self.tx_queue_count = None + self.event_queue_count = None + self.event_queue_stride = None self.tx_queue_offset = None - self.tx_cpl_queue_count = None + self.tx_queue_count = None + self.tx_queue_stride = None self.tx_cpl_queue_offset = None - self.rx_queue_count = None + self.tx_cpl_queue_count = None + self.tx_cpl_queue_stride = None self.rx_queue_offset = None - self.rx_cpl_queue_count = None + self.rx_queue_count = None + self.rx_queue_stride = None self.rx_cpl_queue_offset = None + self.rx_cpl_queue_count = None + self.rx_cpl_queue_stride = None + self.port_count = None - self.port_offset = None - self.port_stride = None + + self.event_queues = [] + + self.tx_queues = [] + self.tx_cpl_queues = [] + self.rx_queues = [] + self.rx_cpl_queues = [] + self.ports = [] self.interrupt_running = False self.interrupt_pending = 0 @@ -706,45 +846,90 @@ class Interface: async def init(self): # Read ID registers - self.if_id = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_IF_ID) - self.log.info("IF ID: 0x%08x", self.if_id) - self.if_features = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_IF_FEATURES) - self.log.info("IF features: 0x%08x", self.if_features) - self.event_queue_count = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_EVENT_QUEUE_COUNT) - self.log.info("Event queue count: %d", self.event_queue_count) - self.event_queue_offset = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_EVENT_QUEUE_OFFSET) + # Enumerate registers + await self.reg_blocks.enumerate_reg_blocks(self.hw_regs, self.driver.if_csr_offset) + + self.if_ctrl_tx_rb = self.reg_blocks.find(MQNIC_RB_IF_CTRL_TX_TYPE, MQNIC_RB_IF_CTRL_TX_VER) + + self.if_tx_features = await self.if_ctrl_tx_rb.read_dword(MQNIC_RB_IF_CTRL_TX_REG_FEATURES) + self.max_tx_mtu = await self.if_ctrl_tx_rb.read_dword(MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU) + + self.log.info("IF TX features: 0x%08x", self.if_tx_features) + self.log.info("Max TX MTU: %d", self.max_tx_mtu) + + self.if_ctrl_rx_rb = self.reg_blocks.find(MQNIC_RB_IF_CTRL_RX_TYPE, MQNIC_RB_IF_CTRL_RX_VER) + + self.if_rx_features = await self.if_ctrl_rx_rb.read_dword(MQNIC_RB_IF_CTRL_RX_REG_FEATURES) + self.max_rx_mtu = await self.if_ctrl_rx_rb.read_dword(MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU) + + self.log.info("IF RX features: 0x%08x", self.if_rx_features) + self.log.info("Max RX MTU: %d", self.max_rx_mtu) + + await self.set_mtu(min(self.max_tx_mtu, self.max_rx_mtu, 9214)) + + self.event_queue_rb = self.reg_blocks.find(MQNIC_RB_EVENT_QM_TYPE, MQNIC_RB_EVENT_QM_VER) + + self.event_queue_offset = await self.event_queue_rb.read_dword(MQNIC_RB_EVENT_QM_REG_OFFSET) + self.event_queue_count = await self.event_queue_rb.read_dword(MQNIC_RB_EVENT_QM_REG_COUNT) + self.event_queue_stride = await self.event_queue_rb.read_dword(MQNIC_RB_EVENT_QM_REG_STRIDE) + self.log.info("Event queue offset: 0x%08x", self.event_queue_offset) - self.tx_queue_count = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_TX_QUEUE_COUNT) - self.log.info("TX queue count: %d", self.tx_queue_count) - self.tx_queue_offset = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_TX_QUEUE_OFFSET) - self.log.info("TX queue offset: 0x%08x", self.tx_queue_offset) - self.tx_cpl_queue_count = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_TX_CPL_QUEUE_COUNT) - self.log.info("TX completion queue count: %d", self.tx_cpl_queue_count) - self.tx_cpl_queue_offset = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_TX_CPL_QUEUE_OFFSET) - self.log.info("TX completion queue offset: 0x%08x", self.tx_cpl_queue_offset) - self.rx_queue_count = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_RX_QUEUE_COUNT) - self.log.info("RX queue count: %d", self.rx_queue_count) - self.rx_queue_offset = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_RX_QUEUE_OFFSET) - self.log.info("RX queue offset: 0x%08x", self.rx_queue_offset) - self.rx_cpl_queue_count = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_RX_CPL_QUEUE_COUNT) - self.log.info("RX completion queue count: %d", self.rx_cpl_queue_count) - self.rx_cpl_queue_offset = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_RX_CPL_QUEUE_OFFSET) - self.log.info("RX completion queue offset: 0x%08x", self.rx_cpl_queue_offset) - self.port_count = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_PORT_COUNT) - self.log.info("Port count: %d", self.port_count) - self.port_offset = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_PORT_OFFSET) - self.log.info("Port offset: 0x%08x", self.port_offset) - self.port_stride = await self.csr_hw_regs.read_dword(MQNIC_IF_REG_PORT_STRIDE) - self.log.info("Port stride: 0x%08x", self.port_stride) + self.log.info("Event queue count: %d", self.event_queue_count) + self.log.info("Event queue stride: 0x%08x", self.event_queue_stride) self.event_queue_count = min(self.event_queue_count, MQNIC_MAX_EVENT_RINGS) + + self.tx_queue_rb = self.reg_blocks.find(MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER) + + self.tx_queue_offset = await self.tx_queue_rb.read_dword(MQNIC_RB_TX_QM_REG_OFFSET) + self.tx_queue_count = await self.tx_queue_rb.read_dword(MQNIC_RB_TX_QM_REG_COUNT) + self.tx_queue_stride = await self.tx_queue_rb.read_dword(MQNIC_RB_TX_QM_REG_STRIDE) + + self.log.info("TX queue offset: 0x%08x", self.tx_queue_offset) + self.log.info("TX queue count: %d", self.tx_queue_count) + self.log.info("TX queue stride: 0x%08x", self.tx_queue_stride) + self.tx_queue_count = min(self.tx_queue_count, MQNIC_MAX_TX_RINGS) + + self.tx_cpl_queue_rb = self.reg_blocks.find(MQNIC_RB_TX_CQM_TYPE, MQNIC_RB_TX_CQM_VER) + + self.tx_cpl_queue_offset = await self.tx_cpl_queue_rb.read_dword(MQNIC_RB_TX_CQM_REG_OFFSET) + self.tx_cpl_queue_count = await self.tx_cpl_queue_rb.read_dword(MQNIC_RB_TX_CQM_REG_COUNT) + self.tx_cpl_queue_stride = await self.tx_cpl_queue_rb.read_dword(MQNIC_RB_TX_CQM_REG_STRIDE) + + self.log.info("TX completion queue offset: 0x%08x", self.tx_cpl_queue_offset) + self.log.info("TX completion queue count: %d", self.tx_cpl_queue_count) + self.log.info("TX completion queue stride: 0x%08x", self.tx_cpl_queue_stride) + self.tx_cpl_queue_count = min(self.tx_cpl_queue_count, MQNIC_MAX_TX_CPL_RINGS) + + self.rx_queue_rb = self.reg_blocks.find(MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER) + + self.rx_queue_offset = await self.rx_queue_rb.read_dword(MQNIC_RB_RX_QM_REG_OFFSET) + self.rx_queue_count = await self.rx_queue_rb.read_dword(MQNIC_RB_RX_QM_REG_COUNT) + self.rx_queue_stride = await self.rx_queue_rb.read_dword(MQNIC_RB_RX_QM_REG_STRIDE) + + self.log.info("RX queue offset: 0x%08x", self.rx_queue_offset) + self.log.info("RX queue count: %d", self.rx_queue_count) + self.log.info("RX queue stride: 0x%08x", self.rx_queue_stride) + self.rx_queue_count = min(self.rx_queue_count, MQNIC_MAX_RX_RINGS) + + self.rx_cpl_queue_rb = self.reg_blocks.find(MQNIC_RB_RX_CQM_TYPE, MQNIC_RB_RX_CQM_VER) + + self.rx_cpl_queue_offset = await self.rx_cpl_queue_rb.read_dword(MQNIC_RB_RX_CQM_REG_OFFSET) + self.rx_cpl_queue_count = await self.rx_cpl_queue_rb.read_dword(MQNIC_RB_RX_CQM_REG_COUNT) + self.rx_cpl_queue_stride = await self.rx_cpl_queue_rb.read_dword(MQNIC_RB_RX_CQM_REG_STRIDE) + + self.log.info("RX completion queue offset: 0x%08x", self.rx_cpl_queue_offset) + self.log.info("RX completion queue count: %d", self.rx_cpl_queue_count) + self.log.info("RX completion queue stride: 0x%08x", self.rx_cpl_queue_stride) + self.rx_cpl_queue_count = min(self.rx_cpl_queue_count, MQNIC_MAX_RX_CPL_RINGS) self.event_queues = [] + self.tx_queues = [] self.tx_cpl_queues = [] self.rx_queues = [] @@ -753,39 +938,48 @@ class Interface: for k in range(self.event_queue_count): q = EqRing(self, 1024, MQNIC_EVENT_SIZE, self.index, - self.hw_regs.create_window(self.event_queue_offset + k*MQNIC_EVENT_QUEUE_STRIDE, MQNIC_EVENT_QUEUE_STRIDE)) + self.hw_regs.create_window(self.event_queue_offset + k*self.event_queue_stride, self.event_queue_stride)) await q.init() self.event_queues.append(q) for k in range(self.tx_queue_count): q = TxRing(self, 1024, MQNIC_DESC_SIZE*4, k, - self.hw_regs.create_window(self.tx_queue_offset + k*MQNIC_QUEUE_STRIDE, MQNIC_QUEUE_STRIDE)) + self.hw_regs.create_window(self.tx_queue_offset + k*self.tx_queue_stride, self.tx_queue_stride)) await q.init() self.tx_queues.append(q) for k in range(self.tx_cpl_queue_count): q = CqRing(self, 1024, MQNIC_CPL_SIZE, k, - self.hw_regs.create_window(self.tx_cpl_queue_offset + k*MQNIC_CPL_QUEUE_STRIDE, MQNIC_CPL_QUEUE_STRIDE)) + self.hw_regs.create_window(self.tx_cpl_queue_offset + k*self.tx_cpl_queue_stride, self.tx_cpl_queue_stride)) await q.init() self.tx_cpl_queues.append(q) for k in range(self.rx_queue_count): q = RxRing(self, 1024, MQNIC_DESC_SIZE*4, k, - self.hw_regs.create_window(self.rx_queue_offset + k*MQNIC_QUEUE_STRIDE, MQNIC_QUEUE_STRIDE)) + self.hw_regs.create_window(self.rx_queue_offset + k*self.rx_queue_stride, self.rx_queue_stride)) await q.init() self.rx_queues.append(q) for k in range(self.rx_cpl_queue_count): q = CqRing(self, 1024, MQNIC_CPL_SIZE, k, - self.hw_regs.create_window(self.rx_cpl_queue_offset + k*MQNIC_CPL_QUEUE_STRIDE, MQNIC_CPL_QUEUE_STRIDE)) + self.hw_regs.create_window(self.rx_cpl_queue_offset + k*self.rx_cpl_queue_stride, self.rx_cpl_queue_stride)) await q.init() self.rx_cpl_queues.append(q) - for k in range(self.port_count): - p = Port(self, k, self.hw_regs.create_window(self.port_offset + k*self.port_stride, self.port_stride)) + self.port_count = 0 + while True: + rb = self.reg_blocks.find(MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, index=self.port_count) + if not rb: + break + + p = Port(self, self.port_count, rb) await p.init() self.ports.append(p) + self.port_count += 1 + + self.log.info("Port count: %d", self.port_count) + # wait for all writes to complete await self.hw_regs.read_dword(0) @@ -1020,8 +1214,11 @@ class Interface: await ring.write_head_ptr() async def set_mtu(self, mtu): - for p in self.ports: - await p.set_mtu(mtu) + await self.if_ctrl_tx_rb.write_dword(MQNIC_RB_IF_CTRL_TX_REG_MTU, mtu) + await self.if_ctrl_rx_rb.write_dword(MQNIC_RB_IF_CTRL_RX_REG_MTU, mtu) + + async def set_rss_mask(self, mask): + await self.if_ctrl_rx_rb.write_dword(MQNIC_RB_IF_CTRL_RX_REG_RSS_MASK, mask) async def recv(self): if not self.pkt_rx_queue: @@ -1087,13 +1284,22 @@ class Driver: self.irq_sig = None self.irq_list = [] + self.reg_blocks = RegBlockList() + self.fw_id_rb = None + self.if_rb = None + self.phc_rb = None + + self.fpga_id = None self.fw_id = None self.fw_ver = None self.board_id = None self.board_ver = None - self.phc_count = None - self.phc_offset = None - self.phc_hw_addr = None + self.build_date = None + self.build_time = None + self.git_hash = None + self.rel_info = None + + self.if_offset = None self.if_count = None self.if_stride = None self.if_csr_offset = None @@ -1154,34 +1360,52 @@ class Driver: if self.ram_hw_regs: self.log.info("RAM BAR size: %d", self.ram_hw_regs.size) + # Enumerate registers + await self.reg_blocks.enumerate_reg_blocks(self.hw_regs) + # Read ID registers - self.fw_id = await self.hw_regs.read_dword(MQNIC_REG_FW_ID) + self.fw_id_rb = self.reg_blocks.find(MQNIC_RB_FW_ID_TYPE, MQNIC_RB_FW_ID_VER) + + self.fpga_id = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_FPGA_ID) + self.log.info("FPGA JTAG ID: 0x%08x", self.fpga_id) + self.fw_id = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_FW_ID) self.log.info("FW ID: 0x%08x", self.fw_id) - self.fw_ver = await self.hw_regs.read_dword(MQNIC_REG_FW_VER) - self.log.info("FW version: %d.%d", self.fw_ver >> 16, self.fw_ver & 0xffff) - self.board_id = await self.hw_regs.read_dword(MQNIC_REG_BOARD_ID) + self.fw_ver = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_FW_VER) + self.log.info("FW version: %d.%d.%d.%d", *self.fw_ver.to_bytes(4, 'big')) + self.board_id = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_BOARD_ID) self.log.info("Board ID: 0x%08x", self.board_id) - self.board_ver = await self.hw_regs.read_dword(MQNIC_REG_BOARD_VER) - self.log.info("Board version: %d.%d", self.board_ver >> 16, self.board_ver & 0xffff) + self.board_ver = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_BOARD_VER) + self.log.info("Board version: %d.%d.%d.%d", *self.board_ver.to_bytes(4, 'big')) + self.build_date = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_BUILD_DATE) + self.log.info("Build date: %s UTC (raw: 0x%08x)", datetime.datetime.utcfromtimestamp(self.build_date).isoformat(' '), self.build_date) + self.git_hash = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_GIT_HASH) + self.log.info("Git hash: %08x", self.git_hash) + self.rel_info = await self.fw_id_rb.read_dword(MQNIC_RB_FW_ID_REG_REL_INFO) + self.log.info("Release info: %d", self.rel_info) - self.phc_count = await self.hw_regs.read_dword(MQNIC_REG_PHC_COUNT) - self.log.info("PHC count: %d", self.phc_count) - self.phc_offset = await self.hw_regs.read_dword(MQNIC_REG_PHC_OFFSET) - self.log.info("PHC offset: 0x%08x", self.phc_offset) - - self.if_count = await self.hw_regs.read_dword(MQNIC_REG_IF_COUNT) - self.log.info("IF count: %d", self.if_count) - self.if_stride = await self.hw_regs.read_dword(MQNIC_REG_IF_STRIDE) - self.log.info("IF stride: 0x%08x", self.if_stride) - self.if_csr_offset = await self.hw_regs.read_dword(MQNIC_REG_IF_CSR_OFFSET) - self.log.info("IF CSR offset: 0x%08x", self.if_csr_offset) + self.phc_rb = self.reg_blocks.find(MQNIC_RB_PHC_TYPE, MQNIC_RB_PHC_VER) + # Enumerate interfaces + self.if_rb = self.reg_blocks.find(MQNIC_RB_IF_TYPE, MQNIC_RB_IF_VER) self.interfaces = [] - for k in range(self.if_count): - i = Interface(self, k, self.hw_regs.create_window(k*self.if_stride, self.if_stride)) - await i.init() - self.interfaces.append(i) + if self.if_rb: + self.if_offset = await self.if_rb.read_dword(MQNIC_RB_IF_REG_OFFSET) + self.log.info("IF offset: %d", self.if_offset) + self.if_count = await self.if_rb.read_dword(MQNIC_RB_IF_REG_COUNT) + self.log.info("IF count: %d", self.if_count) + self.if_stride = await self.if_rb.read_dword(MQNIC_RB_IF_REG_STRIDE) + self.log.info("IF stride: 0x%08x", self.if_stride) + self.if_csr_offset = await self.if_rb.read_dword(MQNIC_RB_IF_REG_CSR_OFFSET) + self.log.info("IF CSR offset: 0x%08x", self.if_csr_offset) + + for k in range(self.if_count): + i = Interface(self, k, self.hw_regs.create_window(self.if_offset + k*self.if_stride, self.if_stride)) + await i.init() + self.interfaces.append(i) + + else: + self.log.warning("No interface block found") async def _run_edge_interrupts(self, signal): last_val = 0 diff --git a/fpga/common/tb/mqnic_core_axi/test_mqnic_core_axi.py b/fpga/common/tb/mqnic_core_axi/test_mqnic_core_axi.py index 0e9925bb4..ebb7fe8da 100644 --- a/fpga/common/tb/mqnic_core_axi/test_mqnic_core_axi.py +++ b/fpga/common/tb/mqnic_core_axi/test_mqnic_core_axi.py @@ -193,7 +193,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") for interface in tb.driver.interfaces: - await interface.ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await interface.ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(interface.tx_queue_count): await interface.ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -327,7 +327,7 @@ async def run_test_nic(dut): tb.log.info("All interface 0 ports") for port in tb.driver.interfaces[0].ports: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(port.interface.tx_queue_count): if k % len(tb.driver.interfaces[0].ports) == port.index: await port.schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -353,7 +353,7 @@ async def run_test_nic(dut): tb.loopback_enable = False for port in tb.driver.interfaces[0].ports[1:]: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000000) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000000) tb.log.info("Read statistics counters") diff --git a/fpga/common/tb/mqnic_core_pcie_s10/test_mqnic_core_pcie_s10.py b/fpga/common/tb/mqnic_core_pcie_s10/test_mqnic_core_pcie_s10.py index f5617aa52..3896d9023 100644 --- a/fpga/common/tb/mqnic_core_pcie_s10/test_mqnic_core_pcie_s10.py +++ b/fpga/common/tb/mqnic_core_pcie_s10/test_mqnic_core_pcie_s10.py @@ -304,7 +304,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") for interface in tb.driver.interfaces: - await interface.ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await interface.ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(interface.tx_queue_count): await interface.ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -438,7 +438,7 @@ async def run_test_nic(dut): tb.log.info("All interface 0 ports") for port in tb.driver.interfaces[0].ports: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(port.interface.tx_queue_count): if k % len(tb.driver.interfaces[0].ports) == port.index: await port.schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -464,7 +464,7 @@ async def run_test_nic(dut): tb.loopback_enable = False for port in tb.driver.interfaces[0].ports[1:]: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000000) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000000) tb.log.info("Read statistics counters") diff --git a/fpga/common/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py b/fpga/common/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py index e91be227d..7036fa2ef 100644 --- a/fpga/common/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py +++ b/fpga/common/tb/mqnic_core_pcie_us/test_mqnic_core_pcie_us.py @@ -379,7 +379,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") for interface in tb.driver.interfaces: - await interface.ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await interface.ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(interface.tx_queue_count): await interface.ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -513,7 +513,7 @@ async def run_test_nic(dut): tb.log.info("All interface 0 ports") for port in tb.driver.interfaces[0].ports: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(port.interface.tx_queue_count): if k % len(tb.driver.interfaces[0].ports) == port.index: await port.schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -539,7 +539,7 @@ async def run_test_nic(dut): tb.loopback_enable = False for port in tb.driver.interfaces[0].ports[1:]: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000000) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000000) tb.log.info("Read statistics counters") diff --git a/fpga/common/tb/mqnic_core_pcie_us_tdma/test_mqnic_core_pcie_us.py b/fpga/common/tb/mqnic_core_pcie_us_tdma/test_mqnic_core_pcie_us.py index db4f38270..687d68cb3 100644 --- a/fpga/common/tb/mqnic_core_pcie_us_tdma/test_mqnic_core_pcie_us.py +++ b/fpga/common/tb/mqnic_core_pcie_us_tdma/test_mqnic_core_pcie_us.py @@ -379,7 +379,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") for interface in tb.driver.interfaces: - await interface.ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await interface.ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(interface.tx_queue_count): await interface.ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -513,7 +513,7 @@ async def run_test_nic(dut): tb.log.info("All interface 0 ports") for port in tb.driver.interfaces[0].ports: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(port.interface.tx_queue_count): if k % len(tb.driver.interfaces[0].ports) == port.index: await port.schedulers[0].hw_regs.write_dword(4*k, 0x00000003) @@ -539,7 +539,7 @@ async def run_test_nic(dut): tb.loopback_enable = False for port in tb.driver.interfaces[0].ports[1:]: - await port.hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000000) + await port.schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000000) await Timer(1000, 'ns') @@ -552,22 +552,23 @@ async def run_test_nic(dut): tb.loopback_enable = True # configure TDMA scheduler - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_SCHED_PERIOD_FNS, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_SCHED_PERIOD_NS, 40000) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_L, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_H, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_FNS, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_NS, 10000) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_L, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_H, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_FNS, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_NS, 5000) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_L, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_H, 0) - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_TDMA_CTRL, 0x00000001) + tdma_sch_rb = tb.driver.interfaces[0].ports[0].reg_blocks.find(mqnic.MQNIC_RB_TDMA_SCH_TYPE, mqnic.MQNIC_RB_TDMA_SCH_VER, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_FNS, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS, 40000) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_FNS, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS, 10000) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_FNS, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS, 5000) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H, 0) + await tdma_sch_rb.write_dword(mqnic.MQNIC_RB_TDMA_SCH_REG_CTRL, 0x00000001) # enable queues with global enable off - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000001) diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga/config.tcl b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga/config.tcl index a18205106..aee457e0f 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h41449003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B39093" +set fpga_id [expr 0x4B39093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x4144] +set board_device_id [expr 0x9003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga_tdma/config.tcl b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga_tdma/config.tcl index 63949ebca..917a517bf 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga_tdma/config.tcl +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/fpga_tdma/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h41449003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B39093" +set fpga_id [expr 0x4B39093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x4144] +set board_device_id [expr 0x9003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga.v b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga.v index ac8aaaf4b..4eb017c94 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h4144, 16'h9003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B39093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h4144_9003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1655,11 +1658,14 @@ assign front_led[1] = qsfp_1_rx_status; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga_core.v index f69adee32..e41995e1d 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h4144, 16'h9003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B39093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h4144_9003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -369,6 +372,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -464,13 +470,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -482,8 +489,9 @@ always @(posedge clk_250mhz) begin qsfp_1_sel_reg <= ctrl_reg_wr_data[17]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin eeprom_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -491,8 +499,9 @@ always @(posedge clk_250mhz) begin eeprom_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_reset_reg <= ctrl_reg_wr_data[4]; end @@ -500,9 +509,13 @@ always @(posedge clk_250mhz) begin qsfp_reset_reg <= ctrl_reg_wr_data[12]; end end - // Flash - 16'h0144: begin - // QSPI 0 control + // QSPI flash + RBB+8'h3C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_0_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -514,8 +527,8 @@ always @(posedge clk_250mhz) begin qspi_0_cs_reg <= ctrl_reg_wr_data[17]; end end - 16'h0148: begin - // QSPI 1 control + RBB+8'h44: begin + // SPI flash ctrl: control 1 if (ctrl_reg_wr_strb[0]) begin qspi_1_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -535,10 +548,12 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_i2c_sda_i; @@ -546,15 +561,23 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[16] <= qsfp_0_sel_reg; ctrl_reg_rd_data_reg[17] <= qsfp_1_sel_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= eeprom_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= eeprom_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= eeprom_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= eeprom_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_0_modprs_l; ctrl_reg_rd_data_reg[1] <= !qsfp_int_l; ctrl_reg_rd_data_reg[4] <= qsfp_reset_reg; @@ -562,23 +585,26 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[9] <= !qsfp_int_l; ctrl_reg_rd_data_reg[12] <= qsfp_reset_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 8; // data width (dual QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI 0 control + RBB+8'h40: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_0_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_0_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_0_cs; end - 16'h0148: begin - // QSPI 1 control + RBB+8'h44: begin + // SPI flash ctrl: control 1 ctrl_reg_rd_data_reg[3:0] <= qspi_1_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_1_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -759,10 +785,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -866,6 +896,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/tb/fpga_core/test_fpga_core.py index 09a3f5a1f..0426cb343 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -376,7 +376,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga/config.tcl b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga/config.tcl index 3526c4e1f..f0735a039 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h41449003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B39093" +set fpga_id [expr 0x4B39093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x4144] +set board_device_id [expr 0x9003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga_tdma/config.tcl b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga_tdma/config.tcl index f39809253..1847ea460 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga_tdma/config.tcl +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/fpga_tdma/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h41449003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B39093" +set fpga_id [expr 0x4B39093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x4144] +set board_device_id [expr 0x9003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga.v b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga.v index 5c2b9a89c..514b43a32 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h4144, 16'h9003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B39093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h4144_9003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1429,11 +1432,14 @@ qsfp_1_phy_3_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga_core.v index ebe6d0532..c03b244dc 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h4144, 16'h9003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B39093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h4144_9003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -409,6 +412,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -525,13 +531,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -543,8 +550,9 @@ always @(posedge clk_250mhz) begin qsfp_1_sel_reg <= ctrl_reg_wr_data[17]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin eeprom_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -552,8 +560,9 @@ always @(posedge clk_250mhz) begin eeprom_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_reset_reg <= ctrl_reg_wr_data[4]; end @@ -561,9 +570,13 @@ always @(posedge clk_250mhz) begin qsfp_reset_reg <= ctrl_reg_wr_data[12]; end end - // Flash - 16'h0144: begin - // QSPI 0 control + // QSPI flash + RBB+8'h3C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_0_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -575,8 +588,8 @@ always @(posedge clk_250mhz) begin qspi_0_cs_reg <= ctrl_reg_wr_data[17]; end end - 16'h0148: begin - // QSPI 1 control + RBB+8'h44: begin + // SPI flash ctrl: control 1 if (ctrl_reg_wr_strb[0]) begin qspi_1_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -596,10 +609,12 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_i2c_sda_i; @@ -607,15 +622,23 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[16] <= qsfp_0_sel_reg; ctrl_reg_rd_data_reg[17] <= qsfp_1_sel_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= eeprom_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= eeprom_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= eeprom_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= eeprom_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_0_modprs_l; ctrl_reg_rd_data_reg[1] <= !qsfp_int_l; ctrl_reg_rd_data_reg[4] <= qsfp_reset_reg; @@ -623,23 +646,26 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[9] <= !qsfp_int_l; ctrl_reg_rd_data_reg[12] <= qsfp_reset_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 8; // data width (dual QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI 0 control + RBB+8'h40: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_0_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_0_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_0_cs; end - 16'h0148: begin - // QSPI 1 control + RBB+8'h44: begin + // SPI flash ctrl: control 1 ctrl_reg_rd_data_reg[3:0] <= qspi_1_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_1_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -1006,10 +1032,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1113,6 +1143,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py index 9b2c120e7..0ed277d6f 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -438,7 +438,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga/config.tcl b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga/config.tcl index 3526c4e1f..f0735a039 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga/config.tcl +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h41449003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B39093" +set fpga_id [expr 0x4B39093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x4144] +set board_device_id [expr 0x9003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga_tdma/config.tcl b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga_tdma/config.tcl index f39809253..1847ea460 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga_tdma/config.tcl +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/fpga_tdma/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h41449003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B39093" +set fpga_id [expr 0x4B39093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x4144] +set board_device_id [expr 0x9003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {4144} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v index 08ac54b74..bf53ab193 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h4144, 16'h9003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B39093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h4144_9003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1453,11 +1456,14 @@ qsfp_1_phy_3_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v index 0745e79e5..5107a77c6 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h4144, 16'h9003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B39093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h4144_9003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -409,6 +412,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -525,13 +531,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -543,8 +550,9 @@ always @(posedge clk_250mhz) begin qsfp_1_sel_reg <= ctrl_reg_wr_data[17]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin eeprom_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -552,8 +560,9 @@ always @(posedge clk_250mhz) begin eeprom_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_reset_reg <= ctrl_reg_wr_data[4]; end @@ -561,9 +570,13 @@ always @(posedge clk_250mhz) begin qsfp_reset_reg <= ctrl_reg_wr_data[12]; end end - // Flash - 16'h0144: begin - // QSPI 0 control + // QSPI flash + RBB+8'h3C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_0_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -575,8 +588,8 @@ always @(posedge clk_250mhz) begin qspi_0_cs_reg <= ctrl_reg_wr_data[17]; end end - 16'h0148: begin - // QSPI 1 control + RBB+8'h44: begin + // SPI flash ctrl: control 1 if (ctrl_reg_wr_strb[0]) begin qspi_1_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -596,10 +609,12 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_i2c_sda_i; @@ -607,15 +622,23 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[16] <= qsfp_0_sel_reg; ctrl_reg_rd_data_reg[17] <= qsfp_1_sel_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= eeprom_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= eeprom_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= eeprom_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= eeprom_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_0_modprs_l; ctrl_reg_rd_data_reg[1] <= !qsfp_int_l; ctrl_reg_rd_data_reg[4] <= qsfp_reset_reg; @@ -623,23 +646,26 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[9] <= !qsfp_int_l; ctrl_reg_rd_data_reg[12] <= qsfp_reset_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 8; // data width (dual QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI 0 control + RBB+8'h40: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_0_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_0_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_0_cs; end - 16'h0148: begin - // QSPI 1 control + RBB+8'h44: begin + // SPI flash ctrl: control 1 ctrl_reg_rd_data_reg[3:0] <= qspi_1_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_1_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -1006,10 +1032,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1113,6 +1143,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py index e93972ad8..4ba5f3ef1 100644 --- a/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ADM_PCIE_9V3/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -438,7 +438,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU200/fpga_100g/fpga/config.tcl b/fpga/mqnic/AU200/fpga_100g/fpga/config.tcl index 501497cdb..e8d632c74 100644 --- a/fpga/mqnic/AU200/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/AU200/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee90c8" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B37093" +set fpga_id [expr 0x4B37093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x90c8] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {90c8} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU200/fpga_100g/rtl/fpga.v b/fpga/mqnic/AU200/fpga_100g/rtl/fpga.v index 6f5f8d386..243b18be5 100644 --- a/fpga/mqnic/AU200/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/AU200/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90c8}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B37093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90c8, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1789,11 +1792,14 @@ assign led[2] = qsfp0_rx_status; // green fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU200/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/AU200/fpga_100g/rtl/fpga_core.v index cd0d2cc94..90ddbe8a9 100644 --- a/fpga/mqnic/AU200/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/AU200/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90c8}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B37093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90c8, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -386,6 +389,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -496,13 +502,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -510,8 +517,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp0_reset_reg <= ctrl_reg_wr_data[4]; qsfp0_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -521,9 +529,13 @@ always @(posedge clk_250mhz) begin qsfp1_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -535,14 +547,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h4C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h50: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -558,17 +572,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp0_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp0_intl; ctrl_reg_rd_data_reg[4] <= qsfp0_reset_reg; @@ -578,24 +598,30 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp1_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h40; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h40: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h48: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h4C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h50: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -767,10 +793,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -874,6 +904,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU200/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU200/fpga_100g/tb/fpga_core/test_fpga_core.py index 955cb8363..5e76acaa0 100644 --- a/fpga/mqnic/AU200/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU200/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -376,7 +376,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU200/fpga_10g/fpga/config.tcl b/fpga/mqnic/AU200/fpga_10g/fpga/config.tcl index 98c20bb4f..c4fa2fe74 100644 --- a/fpga/mqnic/AU200/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/AU200/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee90c8" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B37093" +set fpga_id [expr 0x4B37093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x90c8] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {90c8} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU200/fpga_10g/rtl/fpga.v b/fpga/mqnic/AU200/fpga_10g/rtl/fpga.v index 871234a6a..f6b2e7fef 100644 --- a/fpga/mqnic/AU200/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/AU200/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90c8}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B37093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90c8, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1576,11 +1579,14 @@ qsfp1_phy_4_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU200/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/AU200/fpga_10g/rtl/fpga_core.v index b5c154ec7..5a65f89e0 100644 --- a/fpga/mqnic/AU200/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/AU200/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90c8}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B37093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90c8, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -426,6 +429,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -557,13 +563,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -571,8 +578,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp0_reset_reg <= ctrl_reg_wr_data[4]; qsfp0_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -582,9 +590,13 @@ always @(posedge clk_250mhz) begin qsfp1_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -596,14 +608,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h4C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h50: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -619,17 +633,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp0_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp0_intl; ctrl_reg_rd_data_reg[4] <= qsfp0_reset_reg; @@ -639,24 +659,30 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp1_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h40; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h40: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h48: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h4C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h50: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -1014,10 +1040,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1121,6 +1151,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py index 948a77483..9abaf344e 100644 --- a/fpga/mqnic/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU200/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -438,7 +438,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU250/fpga_100g/fpga/config.tcl b/fpga/mqnic/AU250/fpga_100g/fpga/config.tcl index d15ab5c6e..d0a79c54c 100644 --- a/fpga/mqnic/AU250/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/AU250/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee90fa" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B57093" +set fpga_id [expr 0x4B57093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x90fa] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {90fa} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU250/fpga_100g/rtl/fpga.v b/fpga/mqnic/AU250/fpga_100g/rtl/fpga.v index 8e60b3168..3ff199b5c 100644 --- a/fpga/mqnic/AU250/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/AU250/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90fa}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B57093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90fa, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1789,11 +1792,14 @@ assign led[2] = qsfp0_rx_status; // green fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU250/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/AU250/fpga_100g/rtl/fpga_core.v index 7b10116c0..20ea9312c 100644 --- a/fpga/mqnic/AU250/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/AU250/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90fa}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B57093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90fa, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -386,6 +389,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -496,13 +502,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -510,8 +517,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp0_reset_reg <= ctrl_reg_wr_data[4]; qsfp0_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -521,9 +529,13 @@ always @(posedge clk_250mhz) begin qsfp1_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -535,14 +547,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h4C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h50: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -558,17 +572,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp0_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp0_intl; ctrl_reg_rd_data_reg[4] <= qsfp0_reset_reg; @@ -578,24 +598,30 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp1_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h40; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h40: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h48: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h4C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h50: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -767,10 +793,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -874,6 +904,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU250/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU250/fpga_100g/tb/fpga_core/test_fpga_core.py index 955cb8363..5e76acaa0 100644 --- a/fpga/mqnic/AU250/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU250/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -376,7 +376,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU250/fpga_10g/fpga/config.tcl b/fpga/mqnic/AU250/fpga_10g/fpga/config.tcl index d0678d36d..f5000ab53 100644 --- a/fpga/mqnic/AU250/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/AU250/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee90fa" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B57093" +set fpga_id [expr 0x4B57093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x90fa] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {90fa} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU250/fpga_10g/rtl/fpga.v b/fpga/mqnic/AU250/fpga_10g/rtl/fpga.v index 90dc88906..c94b7bfe1 100644 --- a/fpga/mqnic/AU250/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/AU250/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90fa}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B57093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90fa, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1576,11 +1579,14 @@ qsfp1_phy_4_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU250/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/AU250/fpga_10g/rtl/fpga_core.v index 2c348add3..80491867e 100644 --- a/fpga/mqnic/AU250/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/AU250/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h90fa}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B57093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_90fa, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -426,6 +429,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -557,13 +563,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -571,8 +578,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp0_reset_reg <= ctrl_reg_wr_data[4]; qsfp0_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -582,9 +590,13 @@ always @(posedge clk_250mhz) begin qsfp1_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -596,14 +608,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h4C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h50: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -619,17 +633,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp0_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp0_intl; ctrl_reg_rd_data_reg[4] <= qsfp0_reset_reg; @@ -639,24 +659,30 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp1_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h40; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h40: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h44: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h48: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h4C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h50: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -1014,10 +1040,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1121,6 +1151,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py index 948a77483..9abaf344e 100644 --- a/fpga/mqnic/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU250/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -438,7 +438,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU280/fpga_100g/fpga/config.tcl b/fpga/mqnic/AU280/fpga_100g/fpga/config.tcl index 9144de063..91d591adb 100644 --- a/fpga/mqnic/AU280/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/AU280/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee9118" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B7D093" +set fpga_id [expr 0x4B7D093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9118] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4c_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9118} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU280/fpga_100g/rtl/fpga.v b/fpga/mqnic/AU280/fpga_100g/rtl/fpga.v index 8f57843a0..c52e98f7f 100644 --- a/fpga/mqnic/AU280/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/AU280/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9118}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B7D093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9118, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1686,11 +1689,14 @@ qsfp1_cmac_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU280/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/AU280/fpga_100g/rtl/fpga_core.v index 7f759b46e..de63a33d9 100644 --- a/fpga/mqnic/AU280/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/AU280/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9118}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B7D093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9118, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -358,6 +361,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -445,13 +451,18 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h0C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h10: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -463,14 +474,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h2C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h30: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -486,25 +499,30 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // SPI flash ctrl: Next header + RBB+8'h0C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h10: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h2C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h30: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -651,10 +669,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -758,6 +780,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU280/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU280/fpga_100g/tb/fpga_core/test_fpga_core.py index 605f780bb..2ef45cf78 100644 --- a/fpga/mqnic/AU280/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU280/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -365,7 +365,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU280/fpga_10g/fpga/config.tcl b/fpga/mqnic/AU280/fpga_10g/fpga/config.tcl index 8cef7733b..e2fb76d4a 100644 --- a/fpga/mqnic/AU280/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/AU280/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee9118" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B7D093" +set fpga_id [expr 0x4B7D093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9118] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4c_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9118} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU280/fpga_10g/rtl/fpga.v b/fpga/mqnic/AU280/fpga_10g/rtl/fpga.v index 0b36da04a..f8bbd918e 100644 --- a/fpga/mqnic/AU280/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/AU280/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9118}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B7D093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9118, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1479,11 +1482,14 @@ qsfp1_phy_4_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU280/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/AU280/fpga_10g/rtl/fpga_core.v index db68957cc..48daafd62 100644 --- a/fpga/mqnic/AU280/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/AU280/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9118}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B7D093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9118, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -398,6 +401,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -506,13 +512,18 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h0C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h10: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -524,14 +535,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h2C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h30: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -547,25 +560,30 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // SPI flash ctrl: Next header + RBB+8'h0C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h10: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h2C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h30: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -898,10 +916,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1005,6 +1027,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py index 14e0a6328..1cb5d46ca 100644 --- a/fpga/mqnic/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU280/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -427,7 +427,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU50/fpga_100g/fpga/config.tcl b/fpga/mqnic/AU50/fpga_100g/fpga/config.tcl index 3291699eb..cd17a2f8c 100644 --- a/fpga/mqnic/AU50/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/AU50/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee9032" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B77093" +set fpga_id [expr 0x4B77093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9032] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -140,12 +183,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4c_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9032} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU50/fpga_100g/rtl/fpga.v b/fpga/mqnic/AU50/fpga_100g/rtl/fpga.v index 5fd77adcc..e24823724 100644 --- a/fpga/mqnic/AU50/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/AU50/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9032}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B77093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9032, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -1288,11 +1291,14 @@ assign qsfp_led_stat_g = qsfp_rx_status; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU50/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/AU50/fpga_100g/rtl/fpga_core.v index 88689df8c..b43e3b10c 100644 --- a/fpga/mqnic/AU50/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/AU50/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9032}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B77093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9032, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -337,6 +340,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 1) begin $error("Error: Max port count exceeded (instance %m)"); @@ -424,13 +430,18 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h0C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h10: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -442,14 +453,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h2C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h30: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -465,25 +478,30 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // SPI flash ctrl: Next header + RBB+8'h0C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h10: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h2C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h30: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -606,10 +624,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -713,6 +735,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU50/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU50/fpga_100g/tb/fpga_core/test_fpga_core.py index 215aa5c94..5f4118777 100644 --- a/fpga/mqnic/AU50/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU50/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -338,7 +338,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/AU50/fpga_10g/fpga/config.tcl b/fpga/mqnic/AU50/fpga_10g/fpga/config.tcl index 5c265a9c3..7524cb531 100644 --- a/fpga/mqnic/AU50/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/AU50/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee9032" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B77093" +set fpga_id [expr 0x4B77093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9032] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -147,12 +190,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4c_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9032} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/AU50/fpga_10g/rtl/fpga.v b/fpga/mqnic/AU50/fpga_10g/rtl/fpga.v index 6006d98e7..5146b4836 100644 --- a/fpga/mqnic/AU50/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/AU50/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9032}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B77093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9032, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -1195,11 +1198,14 @@ qsfp_phy_4_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/AU50/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/AU50/fpga_10g/rtl/fpga_core.v index af58eada8..4d7a1607d 100644 --- a/fpga/mqnic/AU50/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/AU50/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9032}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B77093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9032, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -360,6 +363,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 4) begin $error("Error: Max port count exceeded (instance %m)"); @@ -468,13 +474,18 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h0C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h10: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -486,14 +497,16 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: begin + // Alveo BMC + RBB+8'h2C: begin + // BMC ctrl: Addr if (!m_axil_cms_arvalid && !m_axil_cms_awvalid) begin m_axil_cms_addr_reg <= ctrl_reg_wr_data; m_axil_cms_arvalid_reg <= 1'b1; end end - 16'h0184: begin + RBB+8'h30: begin + // BMC ctrl: Data if (!m_axil_cms_wvalid) begin m_axil_cms_awvalid_reg <= 1'b1; m_axil_cms_wdata_reg <= ctrl_reg_wr_data; @@ -509,25 +522,30 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // SPI flash ctrl: Next header + RBB+8'h0C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 8'h81; // configuration (Alveo) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h10: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; - 16'h0184: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; + // Alveo BMC + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C140; // BMC ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h2C: ctrl_reg_rd_data_reg <= m_axil_cms_addr_reg; // BMC ctrl: Addr + RBB+8'h30: ctrl_reg_rd_data_reg <= m_axil_cms_rdata; // BMC ctrl: Data default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -801,10 +819,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -908,6 +930,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py index 3e6b8f42d..e0e569915 100644 --- a/fpga/mqnic/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/AU50/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -369,7 +369,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/ExaNIC_X10/fpga/fpga/config.tcl b/fpga/mqnic/ExaNIC_X10/fpga/fpga/config.tcl index 7de413c68..737a2574c 100644 --- a/fpga/mqnic/ExaNIC_X10/fpga/fpga/config.tcl +++ b/fpga/mqnic/ExaNIC_X10/fpga/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1ce40003" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h3823093" +set fpga_id [expr 0x3823093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1ce4] +set board_device_id [expr 0x0003] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "10" set pcie [get_ips pcie3_ultrascale_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1ce4} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {0003} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga.v b/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga.v index ec838008a..89fe81850 100644 --- a/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga.v +++ b/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1ce4, 16'h0003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h3823093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1ce4_0003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -992,11 +995,14 @@ assign sfp_2_led[1] = 1'b0; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga_core.v b/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga_core.v index 8a29778e6..b930053b4 100644 --- a/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga_core.v +++ b/fpga/mqnic/ExaNIC_X10/fpga/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1ce4, 16'h0003}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h3823093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1ce4_0003, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -342,6 +345,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -446,13 +452,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin sfp_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -464,8 +471,9 @@ always @(posedge clk_250mhz) begin sfp_2_sel_reg <= ctrl_reg_wr_data[17]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin eeprom_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -473,8 +481,9 @@ always @(posedge clk_250mhz) begin eeprom_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin sfp_1_tx_disable_reg <= ctrl_reg_wr_data[5]; sfp_1_rs_reg <= ctrl_reg_wr_data[6]; @@ -484,15 +493,19 @@ always @(posedge clk_250mhz) begin sfp_2_rs_reg <= ctrl_reg_wr_data[14]; end end - // Flash - 16'h0144: begin - // Flash address + // BPI flash + RBB+8'h3C: begin + // BPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // BPI flash ctrl: address flash_addr_reg <= ctrl_reg_wr_data[22:0]; flash_region_reg <= ctrl_reg_wr_data[23]; end - 16'h0148: flash_dq_o_reg <= ctrl_reg_wr_data; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h44: flash_dq_o_reg <= ctrl_reg_wr_data; // BPI flash ctrl: data + RBB+8'h48: begin + // BPI flash ctrl: control if (ctrl_reg_wr_strb[0]) begin flash_ce_n_reg <= ctrl_reg_wr_data[0]; flash_oe_n_reg <= ctrl_reg_wr_data[1]; @@ -514,10 +527,12 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= sfp_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= sfp_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= (sfp_1_i2c_sda_i || !sfp_1_sel_reg) && (sfp_2_i2c_sda_i || !sfp_2_sel_reg); @@ -525,15 +540,23 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[16] <= sfp_1_sel_reg; ctrl_reg_rd_data_reg[17] <= sfp_2_sel_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= eeprom_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= eeprom_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= eeprom_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= eeprom_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !sfp_1_npres; ctrl_reg_rd_data_reg[2] <= sfp_1_los; ctrl_reg_rd_data_reg[5] <= sfp_1_tx_disable_reg; @@ -543,22 +566,25 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[13] <= sfp_2_tx_disable_reg; ctrl_reg_rd_data_reg[14] <= sfp_2_rs_reg; end - // Flash - 16'h0140: begin - // Flash ID + // BPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C121; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // BPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 1; // type (BPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 16; // data width ctrl_reg_rd_data_reg[31:24] <= 24; // address width end - 16'h0144: begin - // Flash address + RBB+8'h40: begin + // BPI flash ctrl: address ctrl_reg_rd_data_reg[22:0] <= flash_addr_reg; ctrl_reg_rd_data_reg[23] <= flash_region_reg; end - 16'h0148: ctrl_reg_rd_data_reg <= flash_dq_i; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h44: ctrl_reg_rd_data_reg <= flash_dq_i; // BPI flash ctrl: data + RBB+8'h48: begin + // BPI flash ctrl: control ctrl_reg_rd_data_reg[0] <= flash_ce_n_reg; // chip enable (inverted) ctrl_reg_rd_data_reg[1] <= flash_oe_n_reg; // output enable (inverted) ctrl_reg_rd_data_reg[2] <= flash_we_n_reg; // write enable (inverted) @@ -774,10 +800,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -881,6 +911,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py index b36b0a58d..f29c4f577 100644 --- a/fpga/mqnic/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ExaNIC_X10/fpga/tb/fpga_core/test_fpga_core.py @@ -345,7 +345,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/config.tcl b/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/config.tcl index 212646068..6965a544f 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1ce40009" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A63093" +set fpga_id [expr 0x4A63093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1ce4] +set board_device_id [expr 0x0009] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1ce4} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {0009} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v index 8ead8d9ce..58adacca2 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1ce4, 16'h0009}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A63093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1ce4_0009, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1029,11 +1032,14 @@ assign sfp_2_led[1] = 1'b0; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v index 274cd6abd..ab7f87d12 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1ce4, 16'h0009}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A63093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1ce4_0009, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -350,6 +353,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -475,13 +481,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin sfp_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -493,8 +500,9 @@ always @(posedge clk_250mhz) begin sfp_2_sel_reg <= ctrl_reg_wr_data[17]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin eeprom_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -502,8 +510,9 @@ always @(posedge clk_250mhz) begin eeprom_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin sfp_1_tx_disable_reg <= ctrl_reg_wr_data[5]; sfp_1_rs_reg <= ctrl_reg_wr_data[6]; @@ -513,15 +522,19 @@ always @(posedge clk_250mhz) begin sfp_2_rs_reg <= ctrl_reg_wr_data[14]; end end - // Flash - 16'h0144: begin - // Flash address + // BPI flash + RBB+8'h3C: begin + // BPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // BPI flash ctrl: address flash_addr_reg <= ctrl_reg_wr_data[22:0]; flash_region_reg <= ctrl_reg_wr_data[23]; end - 16'h0148: flash_dq_o_reg <= ctrl_reg_wr_data; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h44: flash_dq_o_reg <= ctrl_reg_wr_data; // BPI flash ctrl: data + RBB+8'h48: begin + // BPI flash ctrl: control if (ctrl_reg_wr_strb[0]) begin flash_ce_n_reg <= ctrl_reg_wr_data[0]; flash_oe_n_reg <= ctrl_reg_wr_data[1]; @@ -543,10 +556,12 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= sfp_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= sfp_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= (sfp_1_i2c_sda_i || !sfp_1_sel_reg) && (sfp_2_i2c_sda_i || !sfp_2_sel_reg); @@ -554,15 +569,23 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[16] <= sfp_1_sel_reg; ctrl_reg_rd_data_reg[17] <= sfp_2_sel_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= eeprom_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= eeprom_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= eeprom_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= eeprom_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !sfp_1_npres; ctrl_reg_rd_data_reg[2] <= sfp_1_los; ctrl_reg_rd_data_reg[5] <= sfp_1_tx_disable_reg; @@ -572,22 +595,25 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[13] <= sfp_2_tx_disable_reg; ctrl_reg_rd_data_reg[14] <= sfp_2_rs_reg; end - // Flash - 16'h0140: begin - // Flash ID + // BPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C121; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // BPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 1; // type (BPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 16; // data width ctrl_reg_rd_data_reg[31:24] <= 24; // address width end - 16'h0144: begin - // Flash address + RBB+8'h40: begin + // BPI flash ctrl: address ctrl_reg_rd_data_reg[22:0] <= flash_addr_reg; ctrl_reg_rd_data_reg[23] <= flash_region_reg; end - 16'h0148: ctrl_reg_rd_data_reg <= flash_dq_i; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h44: ctrl_reg_rd_data_reg <= flash_dq_i; // BPI flash ctrl: data + RBB+8'h48: begin + // BPI flash ctrl: control ctrl_reg_rd_data_reg[0] <= flash_ce_n_reg; // chip enable (inverted) ctrl_reg_rd_data_reg[1] <= flash_oe_n_reg; // output enable (inverted) ctrl_reg_rd_data_reg[2] <= flash_we_n_reg; // write enable (inverted) @@ -851,10 +877,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -958,6 +988,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py index 9058dba7b..b26199ede 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ExaNIC_X25/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -354,7 +354,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/ExaNIC_X25/fpga_25g/fpga/config.tcl b/fpga/mqnic/ExaNIC_X25/fpga_25g/fpga/config.tcl index 212646068..6965a544f 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_25g/fpga/config.tcl +++ b/fpga/mqnic/ExaNIC_X25/fpga_25g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1ce40009" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A63093" +set fpga_id [expr 0x4A63093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1ce4] +set board_device_id [expr 0x0009] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1ce4} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {0009} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga.v b/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga.v index 2093ad938..0f9fd0471 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1ce4, 16'h0009}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A63093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1ce4_0009, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1039,11 +1042,14 @@ assign sfp_2_led[1] = 1'b0; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga_core.v b/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga_core.v index be6d01b03..a2b766743 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga_core.v +++ b/fpga/mqnic/ExaNIC_X25/fpga_25g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1ce4, 16'h0009}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A63093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1ce4_0009, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -350,6 +353,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -475,13 +481,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin sfp_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -493,8 +500,9 @@ always @(posedge clk_250mhz) begin sfp_2_sel_reg <= ctrl_reg_wr_data[17]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin eeprom_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -502,8 +510,9 @@ always @(posedge clk_250mhz) begin eeprom_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin sfp_1_tx_disable_reg <= ctrl_reg_wr_data[5]; sfp_1_rs_reg <= ctrl_reg_wr_data[6]; @@ -513,15 +522,19 @@ always @(posedge clk_250mhz) begin sfp_2_rs_reg <= ctrl_reg_wr_data[14]; end end - // Flash - 16'h0144: begin - // Flash address + // BPI flash + RBB+8'h3C: begin + // BPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // BPI flash ctrl: address flash_addr_reg <= ctrl_reg_wr_data[22:0]; flash_region_reg <= ctrl_reg_wr_data[23]; end - 16'h0148: flash_dq_o_reg <= ctrl_reg_wr_data; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h44: flash_dq_o_reg <= ctrl_reg_wr_data; // BPI flash ctrl: data + RBB+8'h48: begin + // BPI flash ctrl: control if (ctrl_reg_wr_strb[0]) begin flash_ce_n_reg <= ctrl_reg_wr_data[0]; flash_oe_n_reg <= ctrl_reg_wr_data[1]; @@ -543,10 +556,12 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= sfp_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= sfp_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= (sfp_1_i2c_sda_i || !sfp_1_sel_reg) && (sfp_2_i2c_sda_i || !sfp_2_sel_reg); @@ -554,15 +569,23 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[16] <= sfp_1_sel_reg; ctrl_reg_rd_data_reg[17] <= sfp_2_sel_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= eeprom_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= eeprom_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= eeprom_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= eeprom_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !sfp_1_npres; ctrl_reg_rd_data_reg[2] <= sfp_1_los; ctrl_reg_rd_data_reg[5] <= sfp_1_tx_disable_reg; @@ -572,22 +595,25 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[13] <= sfp_2_tx_disable_reg; ctrl_reg_rd_data_reg[14] <= sfp_2_rs_reg; end - // Flash - 16'h0140: begin - // Flash ID + // BPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C121; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // BPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 1; // type (BPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 16; // data width ctrl_reg_rd_data_reg[31:24] <= 24; // address width end - 16'h0144: begin - // Flash address + RBB+8'h40: begin + // BPI flash ctrl: address ctrl_reg_rd_data_reg[22:0] <= flash_addr_reg; ctrl_reg_rd_data_reg[23] <= flash_region_reg; end - 16'h0148: ctrl_reg_rd_data_reg <= flash_dq_i; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h44: ctrl_reg_rd_data_reg <= flash_dq_i; // BPI flash ctrl: data + RBB+8'h48: begin + // BPI flash ctrl: control ctrl_reg_rd_data_reg[0] <= flash_ce_n_reg; // chip enable (inverted) ctrl_reg_rd_data_reg[1] <= flash_oe_n_reg; // output enable (inverted) ctrl_reg_rd_data_reg[2] <= flash_we_n_reg; // write enable (inverted) @@ -851,10 +877,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -958,6 +988,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ExaNIC_X25/fpga_25g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ExaNIC_X25/fpga_25g/tb/fpga_core/test_fpga_core.py index 6285a5e7b..227177f1a 100644 --- a/fpga/mqnic/ExaNIC_X25/fpga_25g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ExaNIC_X25/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -354,7 +354,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/NetFPGA_SUME/fpga/fpga/config.tcl b/fpga/mqnic/NetFPGA_SUME/fpga/fpga/config.tcl index a9699278e..44214fdb3 100644 --- a/fpga/mqnic/NetFPGA_SUME/fpga/fpga/config.tcl +++ b/fpga/mqnic/NetFPGA_SUME/fpga/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee7028" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h3691093" +set fpga_id [expr 0x3691093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x7028] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -147,12 +190,12 @@ dict set params STAT_ID_WIDTH "10" set pcie [get_ips pcie3_7x_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {7028} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga.v b/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga.v index e97e121c1..aa70b30df 100644 --- a/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga.v +++ b/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h7028}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h3691093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_7028, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1283,11 +1286,14 @@ assign led = led_int; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga_core.v b/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga_core.v index 8815a0c24..aa91ee95a 100644 --- a/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga_core.v +++ b/fpga/mqnic/NetFPGA_SUME/fpga/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h7028}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h3691093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_7028, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -346,6 +349,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 4) begin $error("Error: Max port count exceeded (instance %m)"); @@ -422,9 +428,9 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -432,8 +438,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin sfp_1_tx_disable_reg <= ctrl_reg_wr_data[5]; sfp_1_rs_reg <= ctrl_reg_wr_data[7:6]; @@ -459,17 +466,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= 0; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= sfp_1_mod_detect; ctrl_reg_rd_data_reg[1] <= sfp_1_tx_fault; ctrl_reg_rd_data_reg[2] <= sfp_1_los; @@ -724,10 +737,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -831,6 +848,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py index 230a4e358..b3f8622b8 100644 --- a/fpga/mqnic/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/NetFPGA_SUME/fpga/tb/fpga_core/test_fpga_core.py @@ -360,7 +360,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/S10MX_DK/fpga_10g/common/quartus_pro.mk b/fpga/mqnic/S10MX_DK/fpga_10g/common/quartus_pro.mk index c8d3d8396..f9a9fdccd 100644 --- a/fpga/mqnic/S10MX_DK/fpga_10g/common/quartus_pro.mk +++ b/fpga/mqnic/S10MX_DK/fpga_10g/common/quartus_pro.mk @@ -170,7 +170,7 @@ create_project.tcl: Makefile $(QSF_FILES_REL) | $(IP_FILES_INT) $(IP_TCL_FILES_I for x in $(SDC_FILES_REL); do echo set_global_assignment -name SDC_FILE "$$x" >> $@; done for x in $(QSF_FILES_REL); do echo source "$$x" >> $@; done -update_config.tcl: $(CONFIG_TCL_FILES_REL) +update_config.tcl: $(CONFIG_TCL_FILES_REL) $(SYN_FILES_REL) echo "project_open $(FPGA_TOP)" > $@ for x in $(CONFIG_TCL_FILES_REL); do echo source "$$x" >> $@; done diff --git a/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21b/config.tcl b/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21b/config.tcl index 6f4de83f8..c42437c67 100644 --- a/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21b/config.tcl +++ b/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21b/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h11720001" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h632ac0dd" +set fpga_id [expr 0x632AC0DD] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1172] +set board_device_id [expr 0x0001] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -167,12 +210,12 @@ set fp [open "update_ip_${pcie_ip}.tcl" "w"] puts $fp "package require qsys" puts $fp "load_system ip/${pcie_ip}.ip" -puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_device_id_hwtcl} {4097}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_vendor_id_hwtcl} {4660}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_class_code_hwtcl} {131072}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_revision_id_hwtcl} {0}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_dev_id_hwtcl} {1}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_vendor_id_hwtcl} {4466}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_device_id_hwtcl} {$pcie_device_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_vendor_id_hwtcl} {$pcie_vendor_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_class_code_hwtcl} {$pcie_class_code}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_revision_id_hwtcl} {$pcie_revision_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_dev_id_hwtcl} {$pcie_subsystem_device_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_vendor_id_hwtcl} {$pcie_subsystem_vendor_id}" # configure BAR settings proc configure_bar {fp pcie pf bar aperture} { diff --git a/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21c/config.tcl b/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21c/config.tcl index cfdab4a97..d02189c26 100644 --- a/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21c/config.tcl +++ b/fpga/mqnic/S10MX_DK/fpga_10g/fpga_1sm21c/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h11720001" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h432AC0DD" +set fpga_id [expr 0x432AC0DD] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1172] +set board_device_id [expr 0x0001] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -167,12 +210,12 @@ set fp [open "update_ip_${pcie_ip}.tcl" "w"] puts $fp "package require qsys" puts $fp "load_system ip/${pcie_ip}.ip" -puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_device_id_hwtcl} {4097}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_vendor_id_hwtcl} {4660}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_class_code_hwtcl} {131072}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_revision_id_hwtcl} {0}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_dev_id_hwtcl} {1}" -puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_vendor_id_hwtcl} {4466}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_device_id_hwtcl} {$pcie_device_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_pci_type0_vendor_id_hwtcl} {$pcie_vendor_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_class_code_hwtcl} {$pcie_class_code}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_revision_id_hwtcl} {$pcie_revision_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_dev_id_hwtcl} {$pcie_subsystem_device_id}" +puts $fp "set_instance_parameter_value ${pcie} {pf0_subsys_vendor_id_hwtcl} {$pcie_subsystem_vendor_id}" # configure BAR settings proc configure_bar {fp pcie pf bar aperture} { diff --git a/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga.v b/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga.v index 4e24a7939..c34dd3eab 100644 --- a/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1172, 16'h0001}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h432AC0DD, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1172_0001, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd1563227611, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -821,11 +824,14 @@ eth_xcvr_phy_quad_wrapper qsfp1_eth_xcvr_phy_quad ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga_core.v index b449bd554..924a250c1 100644 --- a/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/S10MX_DK/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h432AC0DD, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1172_0001, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd1563227611, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -327,6 +330,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -490,7 +496,7 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID + // 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID // GPIO // 16'h0110: begin // // GPIO I2C 0 @@ -886,10 +892,14 @@ endgenerate mqnic_core_pcie_s10 #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -990,6 +1000,7 @@ mqnic_core_pcie_s10 #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/S10MX_DK/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/S10MX_DK/fpga_10g/tb/fpga_core/test_fpga_core.py index 59713117b..8966ba439 100644 --- a/fpga/mqnic/S10MX_DK/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/S10MX_DK/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -357,7 +357,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/VCU108/fpga_10g/fpga/config.tcl b/fpga/mqnic/VCU108/fpga_10g/fpga/config.tcl index ed9064367..0aecc491e 100644 --- a/fpga/mqnic/VCU108/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/VCU108/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee806c" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h3842093" +set fpga_id [expr 0x3842093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x806c] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -147,12 +190,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie3_ultrascale_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {806c} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/VCU108/fpga_10g/rtl/fpga.v b/fpga/mqnic/VCU108/fpga_10g/rtl/fpga.v index 8cd655935..24bef4782 100644 --- a/fpga/mqnic/VCU108/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/VCU108/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h806c}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h3842093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_806c, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -1151,11 +1154,14 @@ assign led[7:4] = led_int[7:4]; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/VCU108/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/VCU108/fpga_10g/rtl/fpga_core.v index c41a6be74..b0df4cc1f 100644 --- a/fpga/mqnic/VCU108/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/VCU108/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h806c}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h3842093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_806c, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 1, @@ -360,6 +363,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 4) begin $error("Error: Max port count exceeded (instance %m)"); @@ -468,13 +474,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -482,22 +489,27 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_reset_reg <= ctrl_reg_wr_data[4]; qsfp_lpmode_reg <= ctrl_reg_wr_data[5]; end end - // Flash - 16'h0144: begin - // Flash address + // BPI flash + RBB+8'h2C: begin + // BPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // BPI flash ctrl: address flash_addr_reg <= ctrl_reg_wr_data[23:0]; flash_region_reg <= ctrl_reg_wr_data[25:24]; end - 16'h0148: flash_dq_o_reg <= ctrl_reg_wr_data; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h34: flash_dq_o_reg <= ctrl_reg_wr_data; // BPI flash ctrl: data + RBB+8'h38: begin + // BPI flash ctrl: control if (ctrl_reg_wr_strb[0]) begin flash_ce_n_reg <= ctrl_reg_wr_data[0]; flash_oe_n_reg <= ctrl_reg_wr_data[1]; @@ -519,39 +531,47 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp_intl; ctrl_reg_rd_data_reg[4] <= qsfp_reset_reg; ctrl_reg_rd_data_reg[5] <= qsfp_lpmode_reg; end - // Flash - 16'h0140: ctrl_reg_rd_data_reg <= {8'd26, 8'd16, 8'd4, 8'd1}; // Flash ID - 16'h0140: begin - // Flash ID + // BPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C121; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // BPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 1; // type (BPI) ctrl_reg_rd_data_reg[15:8] <= 4; // configuration (four segments) ctrl_reg_rd_data_reg[23:16] <= 16; // data width ctrl_reg_rd_data_reg[31:24] <= 26; // address width end - 16'h0144: begin - // Flash address + RBB+8'h30: begin + // BPI flash ctrl: address ctrl_reg_rd_data_reg[23:0] <= flash_addr_reg; ctrl_reg_rd_data_reg[25:24] <= flash_region_reg; end - 16'h0148: ctrl_reg_rd_data_reg <= flash_dq_i; // Flash data - 16'h014C: begin - // Flash control + RBB+8'h34: ctrl_reg_rd_data_reg <= flash_dq_i; // BPI flash ctrl: data + RBB+8'h38: begin + // BPI flash ctrl: control ctrl_reg_rd_data_reg[0] <= flash_ce_n_reg; // chip enable (inverted) ctrl_reg_rd_data_reg[1] <= flash_oe_n_reg; // output enable (inverted) ctrl_reg_rd_data_reg[2] <= flash_we_n_reg; // write enable (inverted) @@ -843,10 +863,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -950,6 +974,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py index 1a2b0aa8e..9d7158f3b 100644 --- a/fpga/mqnic/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/VCU108/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -376,7 +376,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/VCU118/fpga_100g/fpga/config.tcl b/fpga/mqnic/VCU118/fpga_100g/fpga/config.tcl index fc997ae9b..51c41417b 100644 --- a/fpga/mqnic/VCU118/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/VCU118/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee9076" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B31093" +set fpga_id [expr 0x4B31093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9076] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9076} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/VCU118/fpga_100g/rtl/fpga.v b/fpga/mqnic/VCU118/fpga_100g/rtl/fpga.v index f7abcc11c..beb3bd029 100644 --- a/fpga/mqnic/VCU118/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/VCU118/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9076}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9076, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1649,11 +1652,14 @@ assign led[7:2] = led_int[7:2]; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/VCU118/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/VCU118/fpga_100g/rtl/fpga_core.v index 274b6940d..ee95466bd 100644 --- a/fpga/mqnic/VCU118/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/VCU118/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9076}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9076, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -372,6 +375,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -463,13 +469,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -477,8 +484,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp1_reset_reg <= ctrl_reg_wr_data[4]; qsfp1_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -488,9 +496,13 @@ always @(posedge clk_250mhz) begin qsfp2_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI 0 control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_0_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -502,8 +514,8 @@ always @(posedge clk_250mhz) begin qspi_0_cs_reg <= ctrl_reg_wr_data[17]; end end - 16'h0148: begin - // QSPI 1 control + RBB+8'h34: begin + // SPI flash ctrl: control 1 if (ctrl_reg_wr_strb[0]) begin qspi_1_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -523,17 +535,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp1_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp1_intl; ctrl_reg_rd_data_reg[4] <= qsfp1_reset_reg; @@ -543,23 +561,26 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp2_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp2_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 8; // data width (dual QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI 0 control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_0_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_0_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_0_cs; end - 16'h0148: begin - // QSPI 1 control + RBB+8'h34: begin + // SPI flash ctrl: control 1 ctrl_reg_rd_data_reg[3:0] <= qspi_1_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_1_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -740,10 +761,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -847,6 +872,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/VCU118/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/VCU118/fpga_100g/tb/fpga_core/test_fpga_core.py index 0d3429d25..90779472a 100644 --- a/fpga/mqnic/VCU118/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/VCU118/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -380,7 +380,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/VCU118/fpga_10g/fpga/config.tcl b/fpga/mqnic/VCU118/fpga_10g/fpga/config.tcl index 0872a4717..5328feab2 100644 --- a/fpga/mqnic/VCU118/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/VCU118/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee9076" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B31093" +set fpga_id [expr 0x4B31093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x9076] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {9076} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/VCU118/fpga_10g/rtl/fpga.v b/fpga/mqnic/VCU118/fpga_10g/rtl/fpga.v index b9e1c9935..4c2321eb9 100644 --- a/fpga/mqnic/VCU118/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/VCU118/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9076}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9076, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1415,11 +1418,14 @@ qsfp2_phy_4_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/VCU118/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/VCU118/fpga_10g/rtl/fpga_core.v index 0b63b459e..939ee0413 100644 --- a/fpga/mqnic/VCU118/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/VCU118/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h9076}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_9076, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -412,6 +415,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -524,13 +530,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -538,8 +545,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp1_reset_reg <= ctrl_reg_wr_data[4]; qsfp1_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -549,9 +557,13 @@ always @(posedge clk_250mhz) begin qsfp2_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI 0 control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_0_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -563,8 +575,8 @@ always @(posedge clk_250mhz) begin qspi_0_cs_reg <= ctrl_reg_wr_data[17]; end end - 16'h0148: begin - // QSPI 1 control + RBB+8'h34: begin + // SPI flash ctrl: control 1 if (ctrl_reg_wr_strb[0]) begin qspi_1_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -584,17 +596,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp1_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp1_intl; ctrl_reg_rd_data_reg[4] <= qsfp1_reset_reg; @@ -604,23 +622,26 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp2_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp2_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 8; // data width (dual QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI 0 control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_0_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_0_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_0_cs; end - 16'h0148: begin - // QSPI 1 control + RBB+8'h34: begin + // SPI flash ctrl: control 1 ctrl_reg_rd_data_reg[3:0] <= qspi_1_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_1_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -987,10 +1008,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1094,6 +1119,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py index e56343161..64132e501 100644 --- a/fpga/mqnic/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/VCU118/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -442,7 +442,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/VCU1525/fpga_100g/fpga/config.tcl b/fpga/mqnic/VCU1525/fpga_100g/fpga/config.tcl index 9c3c9eaff..e93b21573 100644 --- a/fpga/mqnic/VCU1525/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/VCU1525/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee95f5" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B31093" +set fpga_id [expr 0x4B31093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x95f5] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {95f5} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga.v b/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga.v index 94fca3701..dda4d0117 100644 --- a/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h95f5}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_95f5, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1638,11 +1641,14 @@ assign led[2] = qsfp0_rx_status; // green fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga_core.v index ee7728858..63205ebc6 100644 --- a/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/VCU1525/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h95f5}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_95f5, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -361,6 +364,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -446,13 +452,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -460,8 +467,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp0_reset_reg <= ctrl_reg_wr_data[4]; qsfp0_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -471,9 +479,13 @@ always @(posedge clk_250mhz) begin qsfp1_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -493,17 +505,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp0_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp0_intl; ctrl_reg_rd_data_reg[4] <= qsfp0_reset_reg; @@ -513,16 +531,19 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp1_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -695,10 +716,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -802,6 +827,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/VCU1525/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/VCU1525/fpga_100g/tb/fpga_core/test_fpga_core.py index 34679417f..166fe804d 100644 --- a/fpga/mqnic/VCU1525/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/VCU1525/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -374,7 +374,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/VCU1525/fpga_10g/fpga/config.tcl b/fpga/mqnic/VCU1525/fpga_10g/fpga/config.tcl index ab2e968f7..652ba5264 100644 --- a/fpga/mqnic/VCU1525/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/VCU1525/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee95f5" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4B31093" +set fpga_id [expr 0x4B31093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x95f5] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {95f5} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga.v b/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga.v index d6aabec93..9c426ac9b 100644 --- a/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h95f5}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_95f5, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1421,11 +1424,14 @@ qsfp1_phy_4_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga_core.v index ab0db4a30..45a6e301d 100644 --- a/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/VCU1525/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h95f5}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4B31093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_95f5, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -401,6 +404,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -507,13 +513,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -521,8 +528,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp0_reset_reg <= ctrl_reg_wr_data[4]; qsfp0_lpmode_reg <= ctrl_reg_wr_data[5]; @@ -532,9 +540,13 @@ always @(posedge clk_250mhz) begin qsfp1_lpmode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h2C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h30: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -554,17 +566,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp0_modprsl; ctrl_reg_rd_data_reg[1] <= !qsfp0_intl; ctrl_reg_rd_data_reg[4] <= qsfp0_reset_reg; @@ -574,16 +592,19 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp1_lpmode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= 0; // SPI flash ctrl: Next header + RBB+8'h2C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 2; // configuration (two segments) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h30: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; @@ -942,10 +963,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1049,6 +1074,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py index 740d4d345..98f1b01e5 100644 --- a/fpga/mqnic/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/VCU1525/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -436,7 +436,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/ZCU106/fpga_pcie/fpga/config.tcl b/fpga/mqnic/ZCU106/fpga_pcie/fpga/config.tcl index cd69e8607..d6f174f6e 100644 --- a/fpga/mqnic/ZCU106/fpga_pcie/fpga/config.tcl +++ b/fpga/mqnic/ZCU106/fpga_pcie/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h10ee906a" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4730093" +set fpga_id [expr 0x4730093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x10ee] +set board_device_id [expr 0x906a] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10ee} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {906a} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga.v b/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga.v index 8dc41e6fd..0ec0b2565 100644 --- a/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga.v +++ b/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h906a}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4730093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_906a, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -804,11 +807,14 @@ sfp1_phy_inst ( fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga_core.v b/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga_core.v index c00597175..561ccbc17 100644 --- a/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga_core.v +++ b/fpga/mqnic/ZCU106/fpga_pcie/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h10ee, 16'h906a}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4730093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h10ee_906a, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -320,6 +323,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -403,9 +409,9 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -413,8 +419,9 @@ always @(posedge clk_250mhz) begin i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h1C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin sfp0_tx_disable_reg <= ctrl_reg_wr_data[5]; end @@ -430,17 +437,23 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= i2c_scl_i; ctrl_reg_rd_data_reg[1] <= i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= i2c_sda_i; ctrl_reg_rd_data_reg[9] <= i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= 0; // XCVR GPIO: Next header + RBB+8'h1C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[5] <= sfp0_tx_disable_reg; ctrl_reg_rd_data_reg[13] <= sfp1_tx_disable_reg; end @@ -674,10 +687,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -781,6 +798,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/ZCU106/fpga_pcie/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/ZCU106/fpga_pcie/tb/fpga_core/test_fpga_core.py index 4ed925447..e380b68d9 100644 --- a/fpga/mqnic/ZCU106/fpga_pcie/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/ZCU106/fpga_pcie/tb/fpga_core/test_fpga_core.py @@ -348,7 +348,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/fb2CG/fpga_100g/fpga/config.tcl b/fpga/mqnic/fb2CG/fpga_100g/fpga/config.tcl index 71920dfa1..2506c80ad 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/fpga/config.tcl +++ b/fpga/mqnic/fb2CG/fpga_100g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1c2ca00e" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A56093" +set fpga_id [expr 0x4A56093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1c2c] +set board_device_id [expr 0xa00e] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1c2c} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {a00e} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/fb2CG/fpga_100g/fpga_tdma/config.tcl b/fpga/mqnic/fb2CG/fpga_100g/fpga_tdma/config.tcl index a0ed4f41e..05c66bc82 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/fpga_tdma/config.tcl +++ b/fpga/mqnic/fb2CG/fpga_100g/fpga_tdma/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1c2ca00e" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A56093" +set fpga_id [expr 0x4A56093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1c2c] +set board_device_id [expr 0xa00e] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -142,12 +185,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1c2c} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {a00e} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v index 7ff17c5fc..924b60fd4 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v +++ b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A56093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1c2c_a00e, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1678,11 +1681,14 @@ assign led_green[7:5] = 0; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v index 5bf9169f0..0a6c9fc26 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_100g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A56093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1c2c_a00e, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -376,6 +379,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 2) begin $error("Error: Max port count exceeded (instance %m)"); @@ -473,13 +479,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_0_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -487,8 +494,9 @@ always @(posedge clk_250mhz) begin qsfp_0_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_1_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -496,8 +504,9 @@ always @(posedge clk_250mhz) begin qsfp_1_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_0_reset_reg <= ctrl_reg_wr_data[4]; qsfp_0_lp_mode_reg <= ctrl_reg_wr_data[5]; @@ -507,9 +516,13 @@ always @(posedge clk_250mhz) begin qsfp_1_lp_mode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h3C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -521,9 +534,10 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: bmc_ctrl_data_reg <= ctrl_reg_wr_data; - 16'h0184: begin + // Gecko BMC + RBB+8'h60: bmc_ctrl_data_reg <= ctrl_reg_wr_data; // BMC ctrl: data + RBB+8'h64: begin + // BMC ctrl: cmd bmc_ctrl_cmd_reg <= ctrl_reg_wr_data[31:16]; bmc_ctrl_valid_reg <= 1'b1; end @@ -535,24 +549,34 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_0_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_0_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_0_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= qsfp_0_i2c_sda_o_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_1_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_1_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_1_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= qsfp_1_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_0_mod_prsnt_n; ctrl_reg_rd_data_reg[1] <= !qsfp_0_intr_n; ctrl_reg_rd_data_reg[4] <= qsfp_0_reset_reg; @@ -562,30 +586,37 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp_1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp_1_lp_mode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 1; // configuration (one segment) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h40: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= bmc_ctrl_data_reg; - 16'h0184: ctrl_reg_rd_data_reg[31:16] <= bmc_ctrl_cmd_reg; - 16'h0188: begin + // Gecko BMC + RBB+8'h50: ctrl_reg_rd_data_reg <= 32'h0000C141; // BMC ctrl: Type + RBB+8'h54: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h58: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h5C: begin + // BMC ctrl: status ctrl_reg_rd_data_reg[15:0] <= bmc_read_data; ctrl_reg_rd_data_reg[16] <= bmc_status_done; ctrl_reg_rd_data_reg[18] <= bmc_status_timeout; ctrl_reg_rd_data_reg[19] <= bmc_status_idle; end + RBB+8'h60: ctrl_reg_rd_data_reg <= bmc_ctrl_data_reg; // BMC ctrl: data + RBB+8'h64: ctrl_reg_rd_data_reg[31:16] <= bmc_ctrl_cmd_reg; // BMC ctrl: cmd default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -787,10 +818,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -894,6 +929,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(0), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/fb2CG/fpga_100g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/fb2CG/fpga_100g/tb/fpga_core/test_fpga_core.py index e2a2dbda3..e6ff3877b 100644 --- a/fpga/mqnic/fb2CG/fpga_100g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/fb2CG/fpga_100g/tb/fpga_core/test_fpga_core.py @@ -378,7 +378,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/fb2CG/fpga_10g/fpga/config.tcl b/fpga/mqnic/fb2CG/fpga_10g/fpga/config.tcl index a7b992ae8..5d2ce35b3 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/fpga/config.tcl +++ b/fpga/mqnic/fb2CG/fpga_10g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1c2ca00e" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A56093" +set fpga_id [expr 0x4A56093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1c2c] +set board_device_id [expr 0xa00e] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1c2c} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {a00e} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/fb2CG/fpga_10g/fpga_tdma/config.tcl b/fpga/mqnic/fb2CG/fpga_10g/fpga_tdma/config.tcl index 63271a7c2..80adc6fed 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/fpga_tdma/config.tcl +++ b/fpga/mqnic/fb2CG/fpga_10g/fpga_tdma/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1c2ca00e" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A56093" +set fpga_id [expr 0x4A56093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1c2c] +set board_device_id [expr 0xa00e] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1c2c} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {a00e} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v index 557d971b7..6b72985cd 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v +++ b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A56093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1c2c_a00e, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1501,11 +1504,14 @@ assign led_green[7] = qsfp_1_rx_block_lock_3; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v index cd50ac090..914246613 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_10g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A56093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1c2c_a00e, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -416,6 +419,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -534,13 +540,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_0_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -548,8 +555,9 @@ always @(posedge clk_250mhz) begin qsfp_0_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_1_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -557,8 +565,9 @@ always @(posedge clk_250mhz) begin qsfp_1_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_0_reset_reg <= ctrl_reg_wr_data[4]; qsfp_0_lp_mode_reg <= ctrl_reg_wr_data[5]; @@ -568,9 +577,13 @@ always @(posedge clk_250mhz) begin qsfp_1_lp_mode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h3C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -582,9 +595,10 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: bmc_ctrl_data_reg <= ctrl_reg_wr_data; - 16'h0184: begin + // Gecko BMC + RBB+8'h60: bmc_ctrl_data_reg <= ctrl_reg_wr_data; // BMC ctrl: data + RBB+8'h64: begin + // BMC ctrl: cmd bmc_ctrl_cmd_reg <= ctrl_reg_wr_data[31:16]; bmc_ctrl_valid_reg <= 1'b1; end @@ -596,24 +610,34 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_0_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_0_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_0_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= qsfp_0_i2c_sda_o_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_1_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_1_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_1_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= qsfp_1_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_0_mod_prsnt_n; ctrl_reg_rd_data_reg[1] <= !qsfp_0_intr_n; ctrl_reg_rd_data_reg[4] <= qsfp_0_reset_reg; @@ -623,30 +647,37 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp_1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp_1_lp_mode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 1; // configuration (one segment) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h40: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= bmc_ctrl_data_reg; - 16'h0184: ctrl_reg_rd_data_reg[31:16] <= bmc_ctrl_cmd_reg; - 16'h0188: begin + // Gecko BMC + RBB+8'h50: ctrl_reg_rd_data_reg <= 32'h0000C141; // BMC ctrl: Type + RBB+8'h54: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h58: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h5C: begin + // BMC ctrl: status ctrl_reg_rd_data_reg[15:0] <= bmc_read_data; ctrl_reg_rd_data_reg[16] <= bmc_status_done; ctrl_reg_rd_data_reg[18] <= bmc_status_timeout; ctrl_reg_rd_data_reg[19] <= bmc_status_idle; end + RBB+8'h60: ctrl_reg_rd_data_reg <= bmc_ctrl_data_reg; // BMC ctrl: data + RBB+8'h64: ctrl_reg_rd_data_reg[31:16] <= bmc_ctrl_cmd_reg; // BMC ctrl: cmd default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -1034,10 +1065,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1141,6 +1176,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py index 67721e800..74ff6f265 100644 --- a/fpga/mqnic/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/fb2CG/fpga_10g/tb/fpga_core/test_fpga_core.py @@ -440,7 +440,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/fpga/mqnic/fb2CG/fpga_25g/fpga/config.tcl b/fpga/mqnic/fb2CG/fpga_25g/fpga/config.tcl index a7b992ae8..5d2ce35b3 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/fpga/config.tcl +++ b/fpga/mqnic/fb2CG/fpga_25g/fpga/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1c2ca00e" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A56093" +set fpga_id [expr 0x4A56093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1c2c] +set board_device_id [expr 0xa00e] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1c2c} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {a00e} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/fb2CG/fpga_25g/fpga_tdma/config.tcl b/fpga/mqnic/fb2CG/fpga_25g/fpga_tdma/config.tcl index 63271a7c2..80adc6fed 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/fpga_tdma/config.tcl +++ b/fpga/mqnic/fb2CG/fpga_25g/fpga_tdma/config.tcl @@ -29,12 +29,55 @@ set params [dict create] +# collect build information +set build_date [clock seconds] +set git_hash 00000000 +set git_tag "" + +if { [catch {set git_hash [exec git rev-parse --short=8 HEAD]}] } { + puts "Error running git or project not under version control" +} + +if { [catch {set git_tag [exec git describe --tags HEAD]}] } { + puts "Error running git, project not under version control, or no tag found" +} + +puts "Build date: ${build_date}" +puts "Git hash: ${git_hash}" +puts "Git tag: ${git_tag}" + +if { ! [regsub {^.*(\d+\.\d+\.\d+([\.-]\d+)?).*$} $git_tag {\1} tag_ver ] } { + puts "Failed to extract version from git tag" + set tag_ver 0.0.1 +} + +puts "Tag version: ${tag_ver}" + # FW and board IDs -dict set params FW_ID "32'd0" -dict set params FW_VER "32'h00000001" -dict set params BOARD_ID "32'h1c2ca00e" -dict set params BOARD_VER "32'h00000001" -dict set params FPGA_ID "32'h4A56093" +set fpga_id [expr 0x4A56093] +set fw_id [expr 0x00000000] +set fw_ver $tag_ver +set board_vendor_id [expr 0x1c2c] +set board_device_id [expr 0xa00e] +set board_ver 1.0 +set release_info [expr 0x00000000] + +# PCIe IDs +set pcie_vendor_id [expr 0x1234] +set pcie_device_id [expr 0x1001] +set pcie_class_code [expr 0x020000] +set pcie_revision_id [expr 0x00] +set pcie_subsystem_vendor_id $board_vendor_id +set pcie_subsystem_device_id $board_device_id + +dict set params FPGA_ID [format "32'h%08x" $fpga_id] +dict set params FW_ID [format "32'h%08x" $fw_id] +dict set params FW_VER [format "32'h%02x%02x%02x%02x" {*}[split $fw_ver .-] 0 0 0 0] +dict set params BOARD_ID [format "32'h%04x%04x" $board_vendor_id $board_device_id] +dict set params BOARD_VER [format "32'h%02x%02x%02x%02x" {*}[split $board_ver .-] 0 0 0 0] +dict set params BUILD_DATE "32'd${build_date}" +dict set params GIT_HASH "32'h${git_hash}" +dict set params RELEASE_INFO [format "32'h%08x" $release_info] # Structural configuration @@ -159,12 +202,12 @@ dict set params STAT_ID_WIDTH "12" set pcie [get_ips pcie4_uscale_plus_0] # PCIe IDs -set_property CONFIG.vendor_id {1234} $pcie -set_property CONFIG.PF0_DEVICE_ID {1001} $pcie -set_property CONFIG.PF0_CLASS_CODE {020000} $pcie -set_property CONFIG.PF0_REVISION_ID {00} $pcie -set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID {1c2c} $pcie -set_property CONFIG.PF0_SUBSYSTEM_ID {a00e} $pcie +set_property CONFIG.vendor_id [format "%04x" $pcie_vendor_id] $pcie +set_property CONFIG.PF0_DEVICE_ID [format "%04x" $pcie_device_id] $pcie +set_property CONFIG.PF0_CLASS_CODE [format "%06x" $pcie_class_code] $pcie +set_property CONFIG.PF0_REVISION_ID [format "%02x" $pcie_revision_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_VENDOR_ID [format "%04x" $pcie_subsystem_vendor_id] $pcie +set_property CONFIG.PF0_SUBSYSTEM_ID [format "%04x" $pcie_subsystem_device_id] $pcie # Internal interface settings dict set params AXIS_PCIE_DATA_WIDTH [regexp -all -inline -- {[0-9]+} [get_property CONFIG.axisten_if_width $pcie]] diff --git a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v index 1a35fdde6..dde89bdb4 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v +++ b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A56093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1c2c_a00e, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -1529,11 +1532,14 @@ assign led_green[7] = qsfp_1_rx_block_lock_3; fpga_core #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), - .FPGA_ID(FPGA_ID), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), diff --git a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v index a86d0d89e..483dd086d 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v +++ b/fpga/mqnic/fb2CG/fpga_25g/rtl/fpga_core.v @@ -43,11 +43,14 @@ either expressed or implied, of The Regents of the University of California. module fpga_core # ( // FW and board IDs - parameter FW_ID = 32'd0, - parameter FW_VER = {16'd0, 16'd1}, - parameter BOARD_ID = {16'h1c2c, 16'ha00e}, - parameter BOARD_VER = {16'd0, 16'd1}, parameter FPGA_ID = 32'h4A56093, + parameter FW_ID = 32'h00000000, + parameter FW_VER = 32'h00_00_01_00, + parameter BOARD_ID = 32'h1c2c_a00e, + parameter BOARD_VER = 32'h01_00_00_00, + parameter BUILD_DATE = 32'd602976000, + parameter GIT_HASH = 32'hdce357bf, + parameter RELEASE_INFO = 32'h00000000, // Structural configuration parameter IF_COUNT = 2, @@ -416,6 +419,9 @@ parameter AXIL_CTRL_STRB_WIDTH = (AXIL_CTRL_DATA_WIDTH/8); parameter AXIL_IF_CTRL_ADDR_WIDTH = AXIL_CTRL_ADDR_WIDTH-$clog2(IF_COUNT); parameter AXIL_CSR_ADDR_WIDTH = AXIL_IF_CTRL_ADDR_WIDTH-5-$clog2((PORTS_PER_IF+3)/8); +localparam RB_BASE_ADDR = 16'h1000; +localparam RBB = RB_BASE_ADDR & {AXIL_CTRL_ADDR_WIDTH{1'b1}}; + initial begin if (PORT_COUNT > 8) begin $error("Error: Max port count exceeded (instance %m)"); @@ -534,13 +540,14 @@ always @(posedge clk_250mhz) begin // write operation ctrl_reg_wr_ack_reg <= 1'b0; case ({ctrl_reg_wr_addr >> 2, 2'b00}) - 16'h0040: begin - // FPGA ID + // FW ID + 8'h0C: begin + // FW ID: FPGA JTAG ID fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; end - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h0C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_0_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -548,8 +555,9 @@ always @(posedge clk_250mhz) begin qsfp_0_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h1C: begin + // I2C ctrl: control if (ctrl_reg_wr_strb[0]) begin qsfp_1_i2c_scl_o_reg <= ctrl_reg_wr_data[1]; end @@ -557,8 +565,9 @@ always @(posedge clk_250mhz) begin qsfp_1_i2c_sda_o_reg <= ctrl_reg_wr_data[9]; end end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h2C: begin + // XCVR GPIO: control 0123 if (ctrl_reg_wr_strb[0]) begin qsfp_0_reset_reg <= ctrl_reg_wr_data[4]; qsfp_0_lp_mode_reg <= ctrl_reg_wr_data[5]; @@ -568,9 +577,13 @@ always @(posedge clk_250mhz) begin qsfp_1_lp_mode_reg <= ctrl_reg_wr_data[13]; end end - // Flash - 16'h0144: begin - // QSPI control + // QSPI flash + RBB+8'h3C: begin + // SPI flash ctrl: format + fpga_boot_reg <= ctrl_reg_wr_data == 32'hFEE1DEAD; + end + RBB+8'h40: begin + // SPI flash ctrl: control 0 if (ctrl_reg_wr_strb[0]) begin qspi_dq_o_reg <= ctrl_reg_wr_data[3:0]; end @@ -582,9 +595,10 @@ always @(posedge clk_250mhz) begin qspi_cs_reg <= ctrl_reg_wr_data[17]; end end - // BMC - 16'h0180: bmc_ctrl_data_reg <= ctrl_reg_wr_data; - 16'h0184: begin + // Gecko BMC + RBB+8'h60: bmc_ctrl_data_reg <= ctrl_reg_wr_data; // BMC ctrl: data + RBB+8'h64: begin + // BMC ctrl: cmd bmc_ctrl_cmd_reg <= ctrl_reg_wr_data[31:16]; bmc_ctrl_valid_reg <= 1'b1; end @@ -596,24 +610,34 @@ always @(posedge clk_250mhz) begin // read operation ctrl_reg_rd_ack_reg <= 1'b1; case ({ctrl_reg_rd_addr >> 2, 2'b00}) - 16'h0040: ctrl_reg_rd_data_reg <= FPGA_ID; // FPGA ID - // GPIO - 16'h0110: begin - // GPIO I2C 0 + // I2C 0 + RBB+8'h00: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h04: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h08: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h10; // I2C ctrl: Next header + RBB+8'h0C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_0_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_0_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_0_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= qsfp_0_i2c_sda_o_reg; end - 16'h0114: begin - // GPIO I2C 1 + // I2C 1 + RBB+8'h10: ctrl_reg_rd_data_reg <= 32'h0000C110; // I2C ctrl: Type + RBB+8'h14: ctrl_reg_rd_data_reg <= 32'h00000100; // I2C ctrl: Version + RBB+8'h18: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h20; // I2C ctrl: Next header + RBB+8'h1C: begin + // I2C ctrl: control ctrl_reg_rd_data_reg[0] <= qsfp_1_i2c_scl_i; ctrl_reg_rd_data_reg[1] <= qsfp_1_i2c_scl_o_reg; ctrl_reg_rd_data_reg[8] <= qsfp_1_i2c_sda_i; ctrl_reg_rd_data_reg[9] <= qsfp_1_i2c_sda_o_reg; end - 16'h0120: begin - // GPIO XCVR 0123 + // XCVR GPIO + RBB+8'h20: ctrl_reg_rd_data_reg <= 32'h0000C101; // XCVR GPIO: Type + RBB+8'h24: ctrl_reg_rd_data_reg <= 32'h00000100; // XCVR GPIO: Version + RBB+8'h28: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h30; // XCVR GPIO: Next header + RBB+8'h2C: begin + // XCVR GPIO: control 0123 ctrl_reg_rd_data_reg[0] <= !qsfp_0_mod_prsnt_n; ctrl_reg_rd_data_reg[1] <= !qsfp_0_intr_n; ctrl_reg_rd_data_reg[4] <= qsfp_0_reset_reg; @@ -623,30 +647,37 @@ always @(posedge clk_250mhz) begin ctrl_reg_rd_data_reg[12] <= qsfp_1_reset_reg; ctrl_reg_rd_data_reg[13] <= qsfp_1_lp_mode_reg; end - // Flash - 16'h0140: begin - // Flash ID + // QSPI flash + RBB+8'h30: ctrl_reg_rd_data_reg <= 32'h0000C120; // SPI flash ctrl: Type + RBB+8'h34: ctrl_reg_rd_data_reg <= 32'h00000100; // SPI flash ctrl: Version + RBB+8'h38: ctrl_reg_rd_data_reg <= RB_BASE_ADDR+8'h50; // SPI flash ctrl: Next header + RBB+8'h3C: begin + // SPI flash ctrl: format ctrl_reg_rd_data_reg[7:0] <= 0; // type (SPI) ctrl_reg_rd_data_reg[15:8] <= 1; // configuration (one segment) ctrl_reg_rd_data_reg[23:16] <= 4; // data width (QSPI) ctrl_reg_rd_data_reg[31:24] <= 0; // address width (N/A for SPI) end - 16'h0144: begin - // QSPI control + RBB+8'h40: begin + // SPI flash ctrl: control 0 ctrl_reg_rd_data_reg[3:0] <= qspi_dq_i; ctrl_reg_rd_data_reg[11:8] <= qspi_dq_oe; ctrl_reg_rd_data_reg[16] <= qspi_clk; ctrl_reg_rd_data_reg[17] <= qspi_cs; end - // BMC - 16'h0180: ctrl_reg_rd_data_reg <= bmc_ctrl_data_reg; - 16'h0184: ctrl_reg_rd_data_reg[31:16] <= bmc_ctrl_cmd_reg; - 16'h0188: begin + // Gecko BMC + RBB+8'h50: ctrl_reg_rd_data_reg <= 32'h0000C141; // BMC ctrl: Type + RBB+8'h54: ctrl_reg_rd_data_reg <= 32'h00000100; // BMC ctrl: Version + RBB+8'h58: ctrl_reg_rd_data_reg <= 0; // BMC ctrl: Next header + RBB+8'h5C: begin + // BMC ctrl: status ctrl_reg_rd_data_reg[15:0] <= bmc_read_data; ctrl_reg_rd_data_reg[16] <= bmc_status_done; ctrl_reg_rd_data_reg[18] <= bmc_status_timeout; ctrl_reg_rd_data_reg[19] <= bmc_status_idle; end + RBB+8'h60: ctrl_reg_rd_data_reg <= bmc_ctrl_data_reg; // BMC ctrl: data + RBB+8'h64: ctrl_reg_rd_data_reg[31:16] <= bmc_ctrl_cmd_reg; // BMC ctrl: cmd default: ctrl_reg_rd_ack_reg <= 1'b0; endcase end @@ -1034,10 +1065,14 @@ endgenerate mqnic_core_pcie_us #( // FW and board IDs + .FPGA_ID(FPGA_ID), .FW_ID(FW_ID), .FW_VER(FW_VER), .BOARD_ID(BOARD_ID), .BOARD_VER(BOARD_VER), + .BUILD_DATE(BUILD_DATE), + .GIT_HASH(GIT_HASH), + .RELEASE_INFO(RELEASE_INFO), // Structural configuration .IF_COUNT(IF_COUNT), @@ -1141,6 +1176,7 @@ mqnic_core_pcie_us #( .AXIL_IF_CTRL_ADDR_WIDTH(AXIL_IF_CTRL_ADDR_WIDTH), .AXIL_CSR_ADDR_WIDTH(AXIL_CSR_ADDR_WIDTH), .AXIL_CSR_PASSTHROUGH_ENABLE(1), + .RB_NEXT_PTR(RB_BASE_ADDR), // AXI lite interface configuration (application control) .AXIL_APP_CTRL_DATA_WIDTH(AXIL_APP_CTRL_DATA_WIDTH), diff --git a/fpga/mqnic/fb2CG/fpga_25g/tb/fpga_core/test_fpga_core.py b/fpga/mqnic/fb2CG/fpga_25g/tb/fpga_core/test_fpga_core.py index 43c23e7ce..b0850720f 100644 --- a/fpga/mqnic/fb2CG/fpga_25g/tb/fpga_core/test_fpga_core.py +++ b/fpga/mqnic/fb2CG/fpga_25g/tb/fpga_core/test_fpga_core.py @@ -440,7 +440,7 @@ async def run_test_nic(dut): # enable queues tb.log.info("Enable queues") - await tb.driver.interfaces[0].ports[0].hw_regs.write_dword(mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) + await tb.driver.interfaces[0].ports[0].schedulers[0].rb.write_dword(mqnic.MQNIC_RB_SCHED_RR_REG_CTRL, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.driver.interfaces[0].ports[0].schedulers[0].hw_regs.write_dword(4*k, 0x00000003) diff --git a/modules/mqnic/Makefile b/modules/mqnic/Makefile index 4b6876fcc..daeaa3c9e 100644 --- a/modules/mqnic/Makefile +++ b/modules/mqnic/Makefile @@ -3,11 +3,13 @@ ifneq ($(KERNELRELEASE),) # object files to build obj-m += mqnic.o mqnic-y += mqnic_main.o +mqnic-y += mqnic_reg_block.o mqnic-y += mqnic_irq.o mqnic-y += mqnic_dev.o mqnic-y += mqnic_if.o mqnic-y += mqnic_netdev.o mqnic-y += mqnic_port.o +mqnic-y += mqnic_scheduler.o mqnic-y += mqnic_ptp.o mqnic-y += mqnic_i2c.o mqnic-y += mqnic_board.o diff --git a/modules/mqnic/mqnic.h b/modules/mqnic/mqnic.h index 3637402f7..27ccefc33 100644 --- a/modules/mqnic/mqnic.h +++ b/modules/mqnic/mqnic.h @@ -59,6 +59,13 @@ extern unsigned int mqnic_num_rx_queue_entries; struct mqnic_dev; struct mqnic_if; +struct reg_block { + u32 type; + u32 version; + u8 __iomem *regs; + u8 __iomem *base; +}; + struct mqnic_board_ops { int (*init)(struct mqnic_dev *mqnic); void (*deinit)(struct mqnic_dev *mqnic); @@ -121,17 +128,27 @@ struct mqnic_dev { struct miscdevice misc_dev; + struct reg_block *rb_list; + struct reg_block *fw_id_rb; + struct reg_block *if_rb; + struct reg_block *phc_rb; + int dev_port_max; int dev_port_limit; + u32 fpga_id; u32 fw_id; u32 fw_ver; u32 board_id; u32 board_ver; + u32 build_date; + u32 git_hash; + u32 rel_info; u32 phc_count; u32 phc_offset; + u32 if_offset; u32 if_count; u32 if_stride; u32 if_csr_offset; @@ -283,57 +300,86 @@ struct mqnic_eq_ring { u8 __iomem *hw_tail_ptr; }; +struct mqnic_sched { + struct device *dev; + struct mqnic_if *interface; + struct mqnic_port *port; + + struct reg_block *rb; + + int index; + + u32 type; + u32 offset; + u32 channel_count; + u32 channel_stride; + + u8 __iomem *hw_addr; +}; + struct mqnic_port { struct device *dev; struct mqnic_if *interface; + struct reg_block *block_rb; + struct reg_block *rb_list; + int index; u32 tx_queue_count; - u32 port_id; - u32 port_features; - u32 port_mtu; - u32 sched_count; - u32 sched_offset; - u32 sched_stride; - u32 sched_type; - - u8 __iomem *hw_addr; + struct mqnic_sched *sched[MQNIC_MAX_PORTS]; }; struct mqnic_if { struct device *dev; struct mqnic_dev *mdev; + struct reg_block *rb_list; + struct reg_block *if_ctrl_tx_rb; + struct reg_block *if_ctrl_rx_rb; + struct reg_block *event_queue_rb; + struct reg_block *tx_queue_rb; + struct reg_block *tx_cpl_queue_rb; + struct reg_block *rx_queue_rb; + struct reg_block *rx_cpl_queue_rb; + int index; int dev_port_base; int dev_port_max; int dev_port_limit; - u32 if_id; - u32 if_features; + u32 if_tx_features; + u32 if_rx_features; + + u32 max_tx_mtu; + u32 max_rx_mtu; - u32 event_queue_count; u32 event_queue_offset; + u32 event_queue_count; + u32 event_queue_stride; struct mqnic_eq_ring *event_ring[MQNIC_MAX_EVENT_RINGS]; - u32 tx_queue_count; u32 tx_queue_offset; + u32 tx_queue_count; + u32 tx_queue_stride; struct mqnic_ring *tx_ring[MQNIC_MAX_TX_RINGS]; - u32 tx_cpl_queue_count; u32 tx_cpl_queue_offset; + u32 tx_cpl_queue_count; + u32 tx_cpl_queue_stride; struct mqnic_cq_ring *tx_cpl_ring[MQNIC_MAX_TX_CPL_RINGS]; - u32 rx_queue_count; u32 rx_queue_offset; + u32 rx_queue_count; + u32 rx_queue_stride; struct mqnic_ring *rx_ring[MQNIC_MAX_RX_RINGS]; - u32 rx_cpl_queue_count; u32 rx_cpl_queue_offset; + u32 rx_cpl_queue_count; + u32 rx_cpl_queue_stride; struct mqnic_cq_ring *rx_cpl_ring[MQNIC_MAX_RX_CPL_RINGS]; u32 port_count; @@ -343,6 +389,7 @@ struct mqnic_if { u32 max_desc_block_size; + resource_size_t hw_regs_size; u8 __iomem *hw_addr; u8 __iomem *csr_hw_addr; @@ -364,7 +411,8 @@ struct mqnic_priv { bool registered; bool port_up; - u32 if_features; + u32 if_tx_features; + u32 if_rx_features; u32 event_queue_count; struct mqnic_eq_ring *event_ring[MQNIC_MAX_EVENT_RINGS]; @@ -393,6 +441,11 @@ struct mqnic_priv { // mqnic_main.c +// mqnic_reg_block.c +struct reg_block *enumerate_reg_block_list(u8 __iomem *base, size_t offset, size_t size); +struct reg_block *find_reg_block(struct reg_block *list, u32 type, u32 version, int index); +void free_reg_block_list(struct reg_block *list); + // mqnic_irq.c int mqnic_irq_init_pcie(struct mqnic_dev *mdev); void mqnic_irq_deinit_pcie(struct mqnic_dev *mdev); @@ -404,6 +457,12 @@ extern const struct file_operations mqnic_fops; int mqnic_create_interface(struct mqnic_dev *mdev, struct mqnic_if **interface_ptr, int index, u8 __iomem *hw_addr); void mqnic_destroy_interface(struct mqnic_if **interface_ptr); +u32 mqnic_interface_get_rss_mask(struct mqnic_if *interface); +void mqnic_interface_set_rss_mask(struct mqnic_if *interface, u32 rss_mask); +u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface); +void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu); +u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface); +void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu); // mqnic_netdev.c void mqnic_update_stats(struct net_device *ndev); @@ -413,16 +472,17 @@ void mqnic_destroy_netdev(struct net_device **ndev_ptr); // mqnic_port.c int mqnic_create_port(struct mqnic_if *interface, struct mqnic_port **port_ptr, - int index, u8 __iomem *hw_addr); + int index, struct reg_block *rb); void mqnic_destroy_port(struct mqnic_port **port_ptr); int mqnic_activate_port(struct mqnic_port *port); void mqnic_deactivate_port(struct mqnic_port *port); -u32 mqnic_port_get_rss_mask(struct mqnic_port *port); -void mqnic_port_set_rss_mask(struct mqnic_port *port, u32 rss_mask); -u32 mqnic_port_get_tx_mtu(struct mqnic_port *port); -void mqnic_port_set_tx_mtu(struct mqnic_port *port, u32 mtu); -u32 mqnic_port_get_rx_mtu(struct mqnic_port *port); -void mqnic_port_set_rx_mtu(struct mqnic_port *port, u32 mtu); + +// mqnic_scheduler.c +int mqnic_create_scheduler(struct mqnic_port *port, struct mqnic_sched **sched_ptr, + int index, struct reg_block *rb); +void mqnic_destroy_scheduler(struct mqnic_sched **sched_ptr); +int mqnic_scheduler_enable(struct mqnic_sched *sched); +void mqnic_scheduler_disable(struct mqnic_sched *sched); // mqnic_ptp.c void mqnic_register_phc(struct mqnic_dev *mdev); @@ -431,8 +491,8 @@ ktime_t mqnic_read_cpl_ts(struct mqnic_dev *mdev, struct mqnic_ring *ring, const struct mqnic_cpl *cpl); // mqnic_i2c.c -struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, u8 __iomem *reg); -struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, u8 __iomem *reg); +struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index); +struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index); void mqnic_i2c_bus_release(struct mqnic_i2c_bus *bus); void mqnic_i2c_adapter_release(struct i2c_adapter *adapter); int mqnic_i2c_init(struct mqnic_dev *mqnic); diff --git a/modules/mqnic/mqnic_board.c b/modules/mqnic/mqnic_board.c index 6028237c6..5591195c8 100644 --- a/modules/mqnic/mqnic_board.c +++ b/modules/mqnic/mqnic_board.c @@ -194,7 +194,7 @@ static int mqnic_generic_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // IC31 TCA9548 I2C MUX mux = create_i2c_client(adapter, "pca9548", 0x74, i2c_mux_props); @@ -235,7 +235,7 @@ static int mqnic_generic_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // U28 TCA9548 I2C MUX mux = create_i2c_client(adapter, "pca9548", 0x74, i2c_mux_props); @@ -280,7 +280,7 @@ static int mqnic_generic_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // U28 TCA9548 I2C MUX mux = create_i2c_client(adapter, "pca9548", 0x74, i2c_mux_props); @@ -316,7 +316,7 @@ static int mqnic_generic_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // U28 TCA9546 I2C MUX mux = create_i2c_client(adapter, "pca9546", 0x74, i2c_mux_props); @@ -369,7 +369,7 @@ static int mqnic_generic_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // U34 TCA9548 I2C MUX mux = create_i2c_client(adapter, "pca9548", 0x74, i2c_mux_props); @@ -397,7 +397,7 @@ static int mqnic_generic_board_init(struct mqnic_dev *mqnic) case MQNIC_BOARD_ID_ADM_PCIE_9V3: // create I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_1); + adapter = mqnic_i2c_adapter_create(mqnic, 1); // I2C EEPROM mqnic->eeprom_i2c_client = create_i2c_client(adapter, "24c02", 0x50, NULL); @@ -438,30 +438,30 @@ static struct mqnic_board_ops generic_board_ops = { .deinit = mqnic_generic_board_deinit }; -static u32 mqnic_alveo_bmc_reg_read(struct mqnic_dev *mqnic, u32 reg) +static u32 mqnic_alveo_bmc_reg_read(struct mqnic_dev *mqnic, struct reg_block *rb, u32 reg) { - iowrite32(reg, mqnic->hw_addr + 0x180); - ioread32(mqnic->hw_addr + 0x184); // dummy read - return ioread32(mqnic->hw_addr + 0x184); + iowrite32(reg, rb->regs + MQNIC_RB_ALVEO_BMC_REG_ADDR); + ioread32(rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read + return ioread32(rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); } -static void mqnic_alveo_bmc_reg_write(struct mqnic_dev *mqnic, u32 reg, u32 val) +static void mqnic_alveo_bmc_reg_write(struct mqnic_dev *mqnic, struct reg_block *rb, u32 reg, u32 val) { - iowrite32(reg, mqnic->hw_addr + 0x180); - iowrite32(val, mqnic->hw_addr + 0x184); - ioread32(mqnic->hw_addr + 0x184); // dummy read + iowrite32(reg, rb->regs + MQNIC_RB_ALVEO_BMC_REG_ADDR); + iowrite32(val, rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); + ioread32(rb->regs + MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read } -static int mqnic_alveo_bmc_read_mac(struct mqnic_dev *mqnic, int index, char *mac) +static int mqnic_alveo_bmc_read_mac(struct mqnic_dev *mqnic, struct reg_block *rb, int index, char *mac) { u32 reg = 0x0281a0 + index * 8; u32 val; - val = mqnic_alveo_bmc_reg_read(mqnic, reg); + val = mqnic_alveo_bmc_reg_read(mqnic, rb, reg); mac[0] = (val >> 8) & 0xff; mac[1] = val & 0xff; - val = mqnic_alveo_bmc_reg_read(mqnic, reg + 4); + val = mqnic_alveo_bmc_reg_read(mqnic, rb, reg + 4); mac[2] = (val >> 24) & 0xff; mac[3] = (val >> 16) & 0xff; mac[4] = (val >> 8) & 0xff; @@ -470,7 +470,7 @@ static int mqnic_alveo_bmc_read_mac(struct mqnic_dev *mqnic, int index, char *ma return 0; } -static int mqnic_alveo_bmc_read_mac_list(struct mqnic_dev *mqnic, int count) +static int mqnic_alveo_bmc_read_mac_list(struct mqnic_dev *mqnic, struct reg_block *rb, int count) { int ret, k; char mac[ETH_ALEN]; @@ -479,7 +479,7 @@ static int mqnic_alveo_bmc_read_mac_list(struct mqnic_dev *mqnic, int count) mqnic->mac_count = 0; for (k = 0; k < count; k++) { - ret = mqnic_alveo_bmc_read_mac(mqnic, k, mac); + ret = mqnic_alveo_bmc_read_mac(mqnic, rb, k, mac); if (ret) { dev_warn(mqnic->dev, "Failed to read MAC from Alveo BMC"); return -1; @@ -503,6 +503,7 @@ static int mqnic_alveo_board_init(struct mqnic_dev *mqnic) { struct i2c_adapter *adapter; struct i2c_client *mux; + struct reg_block *rb; int ret = 0; mqnic->mod_i2c_client_count = 0; @@ -527,7 +528,7 @@ static int mqnic_alveo_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // U28 TCA9546 I2C MUX mux = create_i2c_client(adapter, "pca9546", 0x74, i2c_mux_props); @@ -543,30 +544,37 @@ static int mqnic_alveo_board_init(struct mqnic_dev *mqnic) mqnic->mod_i2c_client_count = 2; - // falls through + break; case MQNIC_BOARD_ID_AU50: case MQNIC_BOARD_ID_AU280: - // init BMC - - if (mqnic_alveo_bmc_reg_read(mqnic, 0x020000) == 0 || - mqnic_alveo_bmc_reg_read(mqnic, 0x028000) != 0x74736574) { - dev_info(mqnic->dev, "Resetting Alveo CMS"); - - mqnic_alveo_bmc_reg_write(mqnic, 0x020000, 0); - mqnic_alveo_bmc_reg_write(mqnic, 0x020000, 1); - msleep(100); - } - - if (mqnic_alveo_bmc_reg_read(mqnic, 0x028000) != 0x74736574) - dev_warn(mqnic->dev, "Alveo CMS not responding"); - else - mqnic_alveo_bmc_read_mac_list(mqnic, 8); + // no I2C interfaces break; default: dev_warn(mqnic->dev, "Unknown Alveo board ID"); } + // init BMC + rb = find_reg_block(mqnic->rb_list, MQNIC_RB_ALVEO_BMC_TYPE, MQNIC_RB_ALVEO_BMC_VER, 0); + + if (rb) { + if (mqnic_alveo_bmc_reg_read(mqnic, rb, 0x020000) == 0 || + mqnic_alveo_bmc_reg_read(mqnic, rb, 0x028000) != 0x74736574) { + dev_info(mqnic->dev, "Resetting Alveo CMS"); + + mqnic_alveo_bmc_reg_write(mqnic, rb, 0x020000, 0); + mqnic_alveo_bmc_reg_write(mqnic, rb, 0x020000, 1); + msleep(100); + } + + if (mqnic_alveo_bmc_reg_read(mqnic, rb, 0x028000) != 0x74736574) + dev_warn(mqnic->dev, "Alveo CMS not responding"); + else + mqnic_alveo_bmc_read_mac_list(mqnic, rb, 8); + } else { + dev_warn(mqnic->dev, "Alveo CMS not found"); + } + return ret; } @@ -575,13 +583,13 @@ static struct mqnic_board_ops alveo_board_ops = { .deinit = mqnic_generic_board_deinit }; -static int mqnic_gecko_bmc_read(struct mqnic_dev *mqnic) +static int mqnic_gecko_bmc_read(struct mqnic_dev *mqnic, struct reg_block *rb) { u32 val; int timeout = 200; while (1) { - val = ioread32(mqnic->hw_addr + 0x188); + val = ioread32(rb->regs + MQNIC_RB_GECKO_BMC_REG_STATUS); if (val & BIT(19)) { if (val & BIT(18)) { // timed out @@ -603,40 +611,40 @@ static int mqnic_gecko_bmc_read(struct mqnic_dev *mqnic) return -1; } -static int mqnic_gecko_bmc_write(struct mqnic_dev *mqnic, u16 cmd, u32 data) +static int mqnic_gecko_bmc_write(struct mqnic_dev *mqnic, struct reg_block *rb, u16 cmd, u32 data) { int ret; - ret = mqnic_gecko_bmc_read(mqnic); + ret = mqnic_gecko_bmc_read(mqnic, rb); if (ret == -1) return ret; - iowrite32(data, mqnic->hw_addr + 0x180); - iowrite32(cmd << 16, mqnic->hw_addr + 0x184); + iowrite32(data, rb->regs + MQNIC_RB_GECKO_BMC_REG_DATA); + iowrite32(cmd << 16, rb->regs + MQNIC_RB_GECKO_BMC_REG_CMD); return 0; } -static int mqnic_gecko_bmc_query(struct mqnic_dev *mqnic, u16 cmd, u32 data) +static int mqnic_gecko_bmc_query(struct mqnic_dev *mqnic, struct reg_block *rb, u16 cmd, u32 data) { int ret; - ret = mqnic_gecko_bmc_write(mqnic, cmd, data); + ret = mqnic_gecko_bmc_write(mqnic, rb, cmd, data); if (ret) return ret; - return mqnic_gecko_bmc_read(mqnic); + return mqnic_gecko_bmc_read(mqnic, rb); } -static int mqnic_gecko_bmc_read_mac(struct mqnic_dev *mqnic, int index, char *mac) +static int mqnic_gecko_bmc_read_mac(struct mqnic_dev *mqnic, struct reg_block *rb, int index, char *mac) { int i; u16 val; for (i = 0; i < ETH_ALEN; i += 2) { - val = mqnic_gecko_bmc_query(mqnic, 0x2003, 0 + index * ETH_ALEN + i); + val = mqnic_gecko_bmc_query(mqnic, rb, 0x2003, 0 + index * ETH_ALEN + i); if (val < 0) return val; mac[i] = val & 0xff; @@ -646,7 +654,7 @@ static int mqnic_gecko_bmc_read_mac(struct mqnic_dev *mqnic, int index, char *ma return 0; } -static int mqnic_gecko_bmc_read_mac_list(struct mqnic_dev *mqnic, int count) +static int mqnic_gecko_bmc_read_mac_list(struct mqnic_dev *mqnic, struct reg_block *rb, int count) { int ret, k; char mac[ETH_ALEN]; @@ -655,7 +663,7 @@ static int mqnic_gecko_bmc_read_mac_list(struct mqnic_dev *mqnic, int count) mqnic->mac_count = 0; for (k = 0; k < count; k++) { - ret = mqnic_gecko_bmc_read_mac(mqnic, k, mac); + ret = mqnic_gecko_bmc_read_mac(mqnic, rb, k, mac); if (ret) { dev_warn(mqnic->dev, "Failed to read MAC from Gecko BMC"); return -1; @@ -678,6 +686,7 @@ static int mqnic_gecko_bmc_read_mac_list(struct mqnic_dev *mqnic, int count) static int mqnic_gecko_board_init(struct mqnic_dev *mqnic) { struct i2c_adapter *adapter; + struct reg_block *rb; int ret = 0; mqnic->mod_i2c_client_count = 0; @@ -697,35 +706,41 @@ static int mqnic_gecko_board_init(struct mqnic_dev *mqnic) request_module("at24"); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_0); + adapter = mqnic_i2c_adapter_create(mqnic, 0); // QSFP0 mqnic->mod_i2c_client[0] = create_i2c_client(adapter, "24c02", 0x50, NULL); // I2C adapter - adapter = mqnic_i2c_adapter_create(mqnic, mqnic->hw_addr + MQNIC_REG_GPIO_I2C_1); + adapter = mqnic_i2c_adapter_create(mqnic, 1); // QSFP1 mqnic->mod_i2c_client[1] = create_i2c_client(adapter, "24c02", 0x50, NULL); mqnic->mod_i2c_client_count = 2; - // init BMC - if (mqnic_gecko_bmc_query(mqnic, 0x7006, 0) <= 0) { + break; + default: + dev_warn(mqnic->dev, "Unknown board ID (Silicom Gecko BMC)"); + } + + // init BMC + rb = find_reg_block(mqnic->rb_list, MQNIC_RB_GECKO_BMC_TYPE, MQNIC_RB_GECKO_BMC_VER, 0); + + if (rb) { + if (mqnic_gecko_bmc_query(mqnic, rb, 0x7006, 0) <= 0) { dev_warn(mqnic->dev, "Gecko BMC not responding"); } else { - u16 v_l = mqnic_gecko_bmc_query(mqnic, 0x7005, 0); - u16 v_h = mqnic_gecko_bmc_query(mqnic, 0x7006, 0); + u16 v_l = mqnic_gecko_bmc_query(mqnic, rb, 0x7005, 0); + u16 v_h = mqnic_gecko_bmc_query(mqnic, rb, 0x7006, 0); dev_info(mqnic->dev, "Gecko BMC version %d.%d.%d.%d", (v_h >> 8) & 0xff, v_h & 0xff, (v_l >> 8) & 0xff, v_l & 0xff); - mqnic_gecko_bmc_read_mac_list(mqnic, 8); + mqnic_gecko_bmc_read_mac_list(mqnic, rb, 8); } - - break; - default: - dev_warn(mqnic->dev, "Unknown board ID (Silicom Gecko BMC)"); + } else { + dev_warn(mqnic->dev, "Gecko BMC not found"); } return ret; diff --git a/modules/mqnic/mqnic_ethtool.c b/modules/mqnic/mqnic_ethtool.c index b2843c00e..71770de2a 100644 --- a/modules/mqnic/mqnic_ethtool.c +++ b/modules/mqnic/mqnic_ethtool.c @@ -67,7 +67,7 @@ static int mqnic_get_ts_info(struct net_device *ndev, if (mdev->ptp_clock) info->phc_index = ptp_clock_index(mdev->ptp_clock); - if (!(priv->if_features & MQNIC_IF_FEATURE_PTP_TS) || !mdev->ptp_clock) + if (!(priv->if_tx_features & MQNIC_IF_TX_FEATURE_PTP_TS) || !mdev->ptp_clock) return 0; info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE | diff --git a/modules/mqnic/mqnic_hw.h b/modules/mqnic/mqnic_hw.h index 38a076d6c..69ddf89ff 100644 --- a/modules/mqnic/mqnic_hw.h +++ b/modules/mqnic/mqnic_hw.h @@ -68,162 +68,206 @@ #define MQNIC_BOARD_ID_EXANIC_X25 0x1ce40009 #define MQNIC_BOARD_ID_ADM_PCIE_9V3 0x41449003 -// NIC CSRs -#define MQNIC_REG_FW_ID 0x0000 -#define MQNIC_REG_FW_VER 0x0004 -#define MQNIC_REG_BOARD_ID 0x0008 -#define MQNIC_REG_BOARD_VER 0x000C +// Register blocks +#define MQNIC_RB_REG_TYPE 0x00 +#define MQNIC_RB_REG_VER 0x04 +#define MQNIC_RB_REG_NEXT_PTR 0x08 -#define MQNIC_REG_PHC_COUNT 0x0010 -#define MQNIC_REG_PHC_OFFSET 0x0014 -#define MQNIC_REG_PHC_STRIDE 0x0018 +#define MQNIC_RB_FW_ID_TYPE 0xFFFFFFFF +#define MQNIC_RB_FW_ID_VER 0x00000100 +#define MQNIC_RB_FW_ID_REG_FPGA_ID 0x0C +#define MQNIC_RB_FW_ID_REG_FW_ID 0x10 +#define MQNIC_RB_FW_ID_REG_FW_VER 0x14 +#define MQNIC_RB_FW_ID_REG_BOARD_ID 0x18 +#define MQNIC_RB_FW_ID_REG_BOARD_VER 0x1C +#define MQNIC_RB_FW_ID_REG_BUILD_DATE 0x20 +#define MQNIC_RB_FW_ID_REG_GIT_HASH 0x24 +#define MQNIC_RB_FW_ID_REG_REL_INFO 0x28 -#define MQNIC_REG_IF_COUNT 0x0020 -#define MQNIC_REG_IF_STRIDE 0x0024 -#define MQNIC_REG_IF_CSR_OFFSET 0x002C +#define MQNIC_RB_GPIO_TYPE 0x0000C100 +#define MQNIC_RB_GPIO_VER 0x00000100 +#define MQNIC_RB_GPIO_REG_GPIO_IN 0x0C +#define MQNIC_RB_GPIO_REG_GPIO_OUT 0x10 -#define MQNIC_REG_FPGA_ID 0x0040 - -#define MQNIC_REG_GPIO_OUT 0x0100 -#define MQNIC_REG_GPIO_IN 0x0104 - -#define MQNIC_REG_GPIO_I2C_0 0x0110 -#define MQNIC_REG_GPIO_I2C_1 0x0114 -#define MQNIC_REG_GPIO_I2C_2 0x0118 -#define MQNIC_REG_GPIO_I2C_3 0x011C +#define MQNIC_RB_I2C_TYPE 0x0000C110 +#define MQNIC_RB_I2C_VER 0x00000100 +#define MQNIC_RB_I2C_REG_CTRL 0x0C #define MQNIC_REG_GPIO_I2C_SCL_IN 0x00000001 #define MQNIC_REG_GPIO_I2C_SCL_OUT 0x00000002 #define MQNIC_REG_GPIO_I2C_SDA_IN 0x00000100 #define MQNIC_REG_GPIO_I2C_SDA_OUT 0x00000200 -#define MQNIC_REG_GPIO_XCVR_0123 0x0120 -#define MQNIC_REG_GPIO_XCVR_4567 0x0124 +#define MQNIC_RB_SPI_FLASH_TYPE 0x0000C120 +#define MQNIC_RB_SPI_FLASH_VER 0x00000100 +#define MQNIC_RB_SPI_FLASH_REG_FORMAT 0x0C +#define MQNIC_RB_SPI_FLASH_REG_CTRL_0 0x10 +#define MQNIC_RB_SPI_FLASH_REG_CTRL_1 0x14 -#define MQNIC_REG_GPIO_XCVR_PRSNT_IN 0x01 -#define MQNIC_REG_GPIO_XCVR_TX_FAULT_INT_IN 0x02 -#define MQNIC_REG_GPIO_XCVR_RX_LOS_IN 0x03 -#define MQNIC_REG_GPIO_XCVR_RST_OUT 0x10 -#define MQNIC_REG_GPIO_XCVR_TX_DIS_LPMODE_OUT 0x20 -#define MQNIC_REG_GPIO_XCVR_RS0_OUT 0x40 -#define MQNIC_REG_GPIO_XCVR_RS1_OUT 0x80 +#define MQNIC_RB_BPI_FLASH_TYPE 0x0000C121 +#define MQNIC_RB_BPI_FLASH_VER 0x00000100 +#define MQNIC_RB_BPI_FLASH_REG_FORMAT 0x0C +#define MQNIC_RB_BPI_FLASH_REG_ADDR 0x10 +#define MQNIC_RB_BPI_FLASH_REG_DATA 0x14 +#define MQNIC_RB_BPI_FLASH_REG_CTRL 0x18 -#define MQNIC_REG_FLASH_ID 0x0140 -#define MQNIC_REG_FLASH_BPI_ADDR 0x0144 -#define MQNIC_REG_FLASH_BPI_DATA 0x0148 -#define MQNIC_REG_FLASH_BPI_CTRL 0x014c -#define MQNIC_REG_FLASH_SPI_0_CTRL 0x0144 -#define MQNIC_REG_FLASH_SPI_1_CTRL 0x0148 +#define MQNIC_RB_ALVEO_BMC_TYPE 0x0000C140 +#define MQNIC_RB_ALVEO_BMC_VER 0x00000100 +#define MQNIC_RB_ALVEO_BMC_REG_ADDR 0x0C +#define MQNIC_RB_ALVEO_BMC_REG_DATA 0x10 -#define MQNIC_PHC_REG_FEATURES 0x0000 -#define MQNIC_PHC_REG_PTP_CUR_FNS 0x0010 -#define MQNIC_PHC_REG_PTP_CUR_NS 0x0014 -#define MQNIC_PHC_REG_PTP_CUR_SEC_L 0x0018 -#define MQNIC_PHC_REG_PTP_CUR_SEC_H 0x001C -#define MQNIC_PHC_REG_PTP_GET_FNS 0x0020 -#define MQNIC_PHC_REG_PTP_GET_NS 0x0024 -#define MQNIC_PHC_REG_PTP_GET_SEC_L 0x0028 -#define MQNIC_PHC_REG_PTP_GET_SEC_H 0x002C -#define MQNIC_PHC_REG_PTP_SET_FNS 0x0030 -#define MQNIC_PHC_REG_PTP_SET_NS 0x0034 -#define MQNIC_PHC_REG_PTP_SET_SEC_L 0x0038 -#define MQNIC_PHC_REG_PTP_SET_SEC_H 0x003C -#define MQNIC_PHC_REG_PTP_PERIOD_FNS 0x0040 -#define MQNIC_PHC_REG_PTP_PERIOD_NS 0x0044 -#define MQNIC_PHC_REG_PTP_NOM_PERIOD_FNS 0x0048 -#define MQNIC_PHC_REG_PTP_NOM_PERIOD_NS 0x004C -#define MQNIC_PHC_REG_PTP_ADJ_FNS 0x0050 -#define MQNIC_PHC_REG_PTP_ADJ_NS 0x0054 -#define MQNIC_PHC_REG_PTP_ADJ_COUNT 0x0058 -#define MQNIC_PHC_REG_PTP_ADJ_ACTIVE 0x005C +#define MQNIC_RB_GECKO_BMC_TYPE 0x0000C141 +#define MQNIC_RB_GECKO_BMC_VER 0x00000100 +#define MQNIC_RB_GECKO_BMC_REG_STATUS 0x0C +#define MQNIC_RB_GECKO_BMC_REG_DATA 0x10 +#define MQNIC_RB_GECKO_BMC_REG_CMD 0x14 -#define MQNIC_PHC_PEROUT_OFFSET 0x80 -#define MQNIC_PHC_PEROUT_STRIDE 0x40 +#define MQNIC_RB_STATS_TYPE 0x0000C004 +#define MQNIC_RB_STATS_VER 0x00000100 +#define MQNIC_RB_STATS_REG_OFFSET 0x0C +#define MQNIC_RB_STATS_REG_COUNT 0x10 +#define MQNIC_RB_STATS_REG_STRIDE 0x14 +#define MQNIC_RB_STATS_REG_FLAGS 0x18 -#define MQNIC_PHC_REG_PEROUT_CTRL 0x0000 -#define MQNIC_PHC_REG_PEROUT_STATUS 0x0004 -#define MQNIC_PHC_REG_PEROUT_START_FNS 0x0010 -#define MQNIC_PHC_REG_PEROUT_START_NS 0x0014 -#define MQNIC_PHC_REG_PEROUT_START_SEC_L 0x0018 -#define MQNIC_PHC_REG_PEROUT_START_SEC_H 0x001C -#define MQNIC_PHC_REG_PEROUT_PERIOD_FNS 0x0020 -#define MQNIC_PHC_REG_PEROUT_PERIOD_NS 0x0024 -#define MQNIC_PHC_REG_PEROUT_PERIOD_SEC_L 0x0028 -#define MQNIC_PHC_REG_PEROUT_PERIOD_SEC_H 0x002C -#define MQNIC_PHC_REG_PEROUT_WIDTH_FNS 0x0030 -#define MQNIC_PHC_REG_PEROUT_WIDTH_NS 0x0034 -#define MQNIC_PHC_REG_PEROUT_WIDTH_SEC_L 0x0038 -#define MQNIC_PHC_REG_PEROUT_WIDTH_SEC_H 0x003C +#define MQNIC_RB_PHC_TYPE 0x0000C080 +#define MQNIC_RB_PHC_VER 0x00000100 +#define MQNIC_RB_PHC_REG_CTRL 0x0C +#define MQNIC_RB_PHC_REG_CUR_FNS 0x10 +#define MQNIC_RB_PHC_REG_CUR_NS 0x14 +#define MQNIC_RB_PHC_REG_CUR_SEC_L 0x18 +#define MQNIC_RB_PHC_REG_CUR_SEC_H 0x1C +#define MQNIC_RB_PHC_REG_GET_FNS 0x20 +#define MQNIC_RB_PHC_REG_GET_NS 0x24 +#define MQNIC_RB_PHC_REG_GET_SEC_L 0x28 +#define MQNIC_RB_PHC_REG_GET_SEC_H 0x2C +#define MQNIC_RB_PHC_REG_SET_FNS 0x30 +#define MQNIC_RB_PHC_REG_SET_NS 0x34 +#define MQNIC_RB_PHC_REG_SET_SEC_L 0x38 +#define MQNIC_RB_PHC_REG_SET_SEC_H 0x3C +#define MQNIC_RB_PHC_REG_PERIOD_FNS 0x40 +#define MQNIC_RB_PHC_REG_PERIOD_NS 0x44 +#define MQNIC_RB_PHC_REG_NOM_PERIOD_FNS 0x48 +#define MQNIC_RB_PHC_REG_NOM_PERIOD_NS 0x4C +#define MQNIC_RB_PHC_REG_ADJ_FNS 0x50 +#define MQNIC_RB_PHC_REG_ADJ_NS 0x54 +#define MQNIC_RB_PHC_REG_ADJ_COUNT 0x58 +#define MQNIC_RB_PHC_REG_ADJ_ACTIVE 0x5C -// Interface CSRs -#define MQNIC_IF_REG_IF_ID 0x0000 -#define MQNIC_IF_REG_IF_FEATURES 0x0004 +#define MQNIC_RB_PHC_PEROUT_TYPE 0x0000C081 +#define MQNIC_RB_PHC_PEROUT_VER 0x00000100 +#define MQNIC_RB_PHC_PEROUT_REG_CTRL 0x0C +#define MQNIC_RB_PHC_PEROUT_REG_START_FNS 0x10 +#define MQNIC_RB_PHC_PEROUT_REG_START_NS 0x14 +#define MQNIC_RB_PHC_PEROUT_REG_START_SEC_L 0x18 +#define MQNIC_RB_PHC_PEROUT_REG_START_SEC_H 0x1C +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_FNS 0x20 +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS 0x24 +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L 0x28 +#define MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H 0x2C +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_FNS 0x30 +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS 0x34 +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L 0x38 +#define MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H 0x3C -#define MQNIC_IF_REG_EVENT_QUEUE_COUNT 0x0010 -#define MQNIC_IF_REG_EVENT_QUEUE_OFFSET 0x0014 -#define MQNIC_IF_REG_TX_QUEUE_COUNT 0x0020 -#define MQNIC_IF_REG_TX_QUEUE_OFFSET 0x0024 -#define MQNIC_IF_REG_TX_CPL_QUEUE_COUNT 0x0028 -#define MQNIC_IF_REG_TX_CPL_QUEUE_OFFSET 0x002C -#define MQNIC_IF_REG_RX_QUEUE_COUNT 0x0030 -#define MQNIC_IF_REG_RX_QUEUE_OFFSET 0x0034 -#define MQNIC_IF_REG_RX_CPL_QUEUE_COUNT 0x0038 -#define MQNIC_IF_REG_RX_CPL_QUEUE_OFFSET 0x003C -#define MQNIC_IF_REG_PORT_COUNT 0x0040 -#define MQNIC_IF_REG_PORT_OFFSET 0x0044 -#define MQNIC_IF_REG_PORT_STRIDE 0x0048 +#define MQNIC_RB_IF_TYPE 0x0000C000 +#define MQNIC_RB_IF_VER 0x00000100 +#define MQNIC_RB_IF_REG_OFFSET 0x0C +#define MQNIC_RB_IF_REG_COUNT 0x10 +#define MQNIC_RB_IF_REG_STRIDE 0x14 +#define MQNIC_RB_IF_REG_CSR_OFFSET 0x18 -#define MQNIC_IF_FEATURE_RSS (1 << 0) -#define MQNIC_IF_FEATURE_PTP_TS (1 << 4) -#define MQNIC_IF_FEATURE_TX_CSUM (1 << 8) -#define MQNIC_IF_FEATURE_RX_CSUM (1 << 9) -#define MQNIC_IF_FEATURE_RX_HASH (1 << 10) +#define MQNIC_RB_IF_CTRL_TX_TYPE 0x0000C001 +#define MQNIC_RB_IF_CTRL_TX_VER 0x00000100 +#define MQNIC_RB_IF_CTRL_TX_REG_FEATURES 0x0C +#define MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU 0x10 +#define MQNIC_RB_IF_CTRL_TX_REG_MTU 0x14 -// Port CSRs -#define MQNIC_PORT_REG_PORT_ID 0x0000 -#define MQNIC_PORT_REG_PORT_FEATURES 0x0004 -#define MQNIC_PORT_REG_PORT_MTU 0x0008 +#define MQNIC_IF_TX_FEATURE_PTP_TS (1 << 4) +#define MQNIC_IF_TX_FEATURE_CSUM (1 << 8) -#define MQNIC_PORT_REG_SCHED_COUNT 0x0010 -#define MQNIC_PORT_REG_SCHED_OFFSET 0x0014 -#define MQNIC_PORT_REG_SCHED_STRIDE 0x0018 -#define MQNIC_PORT_REG_SCHED_TYPE 0x001C -#define MQNIC_PORT_REG_SCHED_ENABLE 0x0040 +#define MQNIC_RB_IF_CTRL_RX_TYPE 0x0000C002 +#define MQNIC_RB_IF_CTRL_RX_VER 0x00000100 +#define MQNIC_RB_IF_CTRL_RX_REG_FEATURES 0x0C +#define MQNIC_RB_IF_CTRL_RX_REG_MAX_MTU 0x10 +#define MQNIC_RB_IF_CTRL_RX_REG_MTU 0x14 +#define MQNIC_RB_IF_CTRL_RX_REG_RSS_MASK 0x18 -#define MQNIC_PORT_REG_RSS_MASK 0x0080 +#define MQNIC_IF_RX_FEATURE_RSS (1 << 0) +#define MQNIC_IF_RX_FEATURE_PTP_TS (1 << 4) +#define MQNIC_IF_RX_FEATURE_CSUM (1 << 8) +#define MQNIC_IF_RX_FEATURE_HASH (1 << 9) -#define MQNIC_PORT_REG_TX_MTU 0x0100 -#define MQNIC_PORT_REG_RX_MTU 0x0200 +#define MQNIC_RB_EVENT_QM_TYPE 0x0000C010 +#define MQNIC_RB_EVENT_QM_VER 0x00000100 +#define MQNIC_RB_EVENT_QM_REG_OFFSET 0x0C +#define MQNIC_RB_EVENT_QM_REG_COUNT 0x10 +#define MQNIC_RB_EVENT_QM_REG_STRIDE 0x14 -#define MQNIC_PORT_REG_TDMA_CTRL 0x1000 -#define MQNIC_PORT_REG_TDMA_STATUS 0x1004 -#define MQNIC_PORT_REG_TDMA_TIMESLOT_COUNT 0x1008 -#define MQNIC_PORT_REG_TDMA_SCHED_START_FNS 0x1010 -#define MQNIC_PORT_REG_TDMA_SCHED_START_NS 0x1014 -#define MQNIC_PORT_REG_TDMA_SCHED_START_SEC_L 0x1018 -#define MQNIC_PORT_REG_TDMA_SCHED_START_SEC_H 0x101C -#define MQNIC_PORT_REG_TDMA_SCHED_PERIOD_FNS 0x1020 -#define MQNIC_PORT_REG_TDMA_SCHED_PERIOD_NS 0x1024 -#define MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_L 0x1028 -#define MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_H 0x102C -#define MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_FNS 0x1030 -#define MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_NS 0x1034 -#define MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_L 0x1038 -#define MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_H 0x103C -#define MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_FNS 0x1040 -#define MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_NS 0x1044 -#define MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_L 0x1048 -#define MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_H 0x104C +#define MQNIC_RB_TX_QM_TYPE 0x0000C020 +#define MQNIC_RB_TX_QM_VER 0x00000100 +#define MQNIC_RB_TX_QM_REG_OFFSET 0x0C +#define MQNIC_RB_TX_QM_REG_COUNT 0x10 +#define MQNIC_RB_TX_QM_REG_STRIDE 0x14 -#define MQNIC_PORT_FEATURE_RSS (1 << 0) -#define MQNIC_PORT_FEATURE_PTP_TS (1 << 4) -#define MQNIC_PORT_FEATURE_TX_CSUM (1 << 8) -#define MQNIC_PORT_FEATURE_RX_CSUM (1 << 9) -#define MQNIC_PORT_FEATURE_RX_HASH (1 << 10) +#define MQNIC_RB_TX_CQM_TYPE 0x0000C030 +#define MQNIC_RB_TX_CQM_VER 0x00000100 +#define MQNIC_RB_TX_CQM_REG_OFFSET 0x0C +#define MQNIC_RB_TX_CQM_REG_COUNT 0x10 +#define MQNIC_RB_TX_CQM_REG_STRIDE 0x14 -#define MQNIC_QUEUE_STRIDE 0x00000020 -#define MQNIC_CPL_QUEUE_STRIDE 0x00000020 -#define MQNIC_EVENT_QUEUE_STRIDE 0x00000020 +#define MQNIC_RB_RX_QM_TYPE 0x0000C021 +#define MQNIC_RB_RX_QM_VER 0x00000100 +#define MQNIC_RB_RX_QM_REG_OFFSET 0x0C +#define MQNIC_RB_RX_QM_REG_COUNT 0x10 +#define MQNIC_RB_RX_QM_REG_STRIDE 0x14 + +#define MQNIC_RB_RX_CQM_TYPE 0x0000C031 +#define MQNIC_RB_RX_CQM_VER 0x00000100 +#define MQNIC_RB_RX_CQM_REG_OFFSET 0x0C +#define MQNIC_RB_RX_CQM_REG_COUNT 0x10 +#define MQNIC_RB_RX_CQM_REG_STRIDE 0x14 + +#define MQNIC_RB_SCHED_BLOCK_TYPE 0x0000C003 +#define MQNIC_RB_SCHED_BLOCK_VER 0x00000100 +#define MQNIC_RB_SCHED_BLOCK_REG_OFFSET 0x0C + +#define MQNIC_RB_SCHED_RR_TYPE 0x0000C040 +#define MQNIC_RB_SCHED_RR_VER 0x00000100 +#define MQNIC_RB_SCHED_RR_REG_OFFSET 0x0C +#define MQNIC_RB_SCHED_RR_REG_CH_COUNT 0x10 +#define MQNIC_RB_SCHED_RR_REG_CH_STRIDE 0x14 +#define MQNIC_RB_SCHED_RR_REG_CTRL 0x18 +#define MQNIC_RB_SCHED_RR_REG_DEST 0x1C + +#define MQNIC_RB_SCHED_CTRL_TDMA_TYPE 0x0000C050 +#define MQNIC_RB_SCHED_CTRL_TDMA_VER 0x00000100 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_OFFSET 0x0C +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_COUNT 0x10 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_STRIDE 0x14 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_CTRL 0x18 +#define MQNIC_RB_SCHED_CTRL_TDMA_REG_TS_COUNT 0x1C + +#define MQNIC_RB_TDMA_SCH_TYPE 0x0000C060 +#define MQNIC_RB_TDMA_SCH_VER 0x00000100 +#define MQNIC_RB_TDMA_SCH_REG_TS_COUNT 0x0C +#define MQNIC_RB_TDMA_SCH_REG_CTRL 0x10 +#define MQNIC_RB_TDMA_SCH_REG_STATUS 0x14 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_FNS 0x20 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_NS 0x24 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L 0x28 +#define MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H 0x2C +#define MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_FNS 0x30 +#define MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS 0x34 +#define MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L 0x38 +#define MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H 0x3C +#define MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_FNS 0x40 +#define MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS 0x44 +#define MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L 0x48 +#define MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H 0x4C +#define MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_FNS 0x50 +#define MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS 0x54 +#define MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L 0x58 +#define MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H 0x5C #define MQNIC_QUEUE_BASE_ADDR_REG 0x00 #define MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG 0x08 diff --git a/modules/mqnic/mqnic_i2c.c b/modules/mqnic/mqnic_i2c.c index fa2a70700..e25ae8ce2 100644 --- a/modules/mqnic/mqnic_i2c.c +++ b/modules/mqnic/mqnic_i2c.c @@ -69,13 +69,16 @@ static int mqnic_i2c_get_sda(void *data) return !!(ioread32(bus->sda_in_reg) & bus->sda_in_mask); } -struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, u8 __iomem *reg) +struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, int index) { struct mqnic_i2c_bus *bus; struct i2c_algo_bit_data *algo; struct i2c_adapter *adapter; + struct reg_block *rb; - if (!reg) + rb = find_reg_block(mqnic->rb_list, MQNIC_RB_I2C_TYPE, MQNIC_RB_I2C_VER, index); + + if (!rb) return NULL; bus = kzalloc(sizeof(*bus), GFP_KERNEL); @@ -85,10 +88,10 @@ struct mqnic_i2c_bus *mqnic_i2c_bus_create(struct mqnic_dev *mqnic, u8 __iomem * // set private data bus->mqnic = mqnic; - bus->scl_in_reg = reg; - bus->scl_out_reg = reg; - bus->sda_in_reg = reg; - bus->sda_out_reg = reg; + bus->scl_in_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->scl_out_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->sda_in_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; + bus->sda_out_reg = rb->regs + MQNIC_RB_I2C_REG_CTRL; bus->scl_in_mask = MQNIC_REG_GPIO_I2C_SCL_IN; bus->scl_out_mask = MQNIC_REG_GPIO_I2C_SCL_OUT; bus->sda_in_mask = MQNIC_REG_GPIO_I2C_SDA_IN; @@ -128,9 +131,9 @@ err_free_bus: return NULL; } -struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, u8 __iomem *reg) +struct i2c_adapter *mqnic_i2c_adapter_create(struct mqnic_dev *mqnic, int index) { - struct mqnic_i2c_bus *bus = mqnic_i2c_bus_create(mqnic, reg); + struct mqnic_i2c_bus *bus = mqnic_i2c_bus_create(mqnic, index); if (!bus) return NULL; diff --git a/modules/mqnic/mqnic_if.c b/modules/mqnic/mqnic_if.c index 26e857c2e..7e13b78d0 100644 --- a/modules/mqnic/mqnic_if.c +++ b/modules/mqnic/mqnic_if.c @@ -40,6 +40,7 @@ int mqnic_create_interface(struct mqnic_dev *mdev, struct mqnic_if **interface_p { struct device *dev = mdev->dev; struct mqnic_if *interface; + struct reg_block *rb; int ret = 0; int k; u32 desc_block_size; @@ -53,59 +54,141 @@ int mqnic_create_interface(struct mqnic_dev *mdev, struct mqnic_if **interface_p interface->index = index; + interface->hw_regs_size = mdev->if_stride; interface->hw_addr = hw_addr; interface->csr_hw_addr = hw_addr + mdev->if_csr_offset; - // read ID registers - interface->if_id = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_IF_ID); - dev_info(dev, "IF ID: 0x%08x", interface->if_id); - interface->if_features = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_IF_FEATURES); - dev_info(dev, "IF features: 0x%08x", interface->if_features); + // Enumerate registers + interface->rb_list = enumerate_reg_block_list(interface->hw_addr, mdev->if_csr_offset, interface->hw_regs_size); + if (!interface->rb_list) { + ret = -EIO; + dev_err(dev, "Failed to enumerate blocks"); + goto fail; + } + + dev_info(dev, "Interface-level register blocks:"); + for (rb = interface->rb_list; rb->type && rb->version; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + interface->if_ctrl_tx_rb = find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TX_TYPE, MQNIC_RB_IF_CTRL_TX_VER, 0); + + if (!interface->if_ctrl_tx_rb) { + ret = -EIO; + dev_err(dev, "TX interface control block not found"); + goto fail; + } + + interface->if_tx_features = ioread32(interface->if_ctrl_tx_rb->regs + MQNIC_RB_IF_CTRL_TX_REG_FEATURES); + interface->max_tx_mtu = ioread32(interface->if_ctrl_tx_rb->regs + MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU); + + dev_info(dev, "IF TX features: 0x%08x", interface->if_tx_features); + dev_info(dev, "Max TX MTU: %d", interface->max_tx_mtu); + + interface->if_ctrl_rx_rb = find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_RX_TYPE, MQNIC_RB_IF_CTRL_RX_VER, 0); + + if (!interface->if_ctrl_rx_rb) { + ret = -EIO; + dev_err(dev, "RX interface control block not found"); + goto fail; + } + + interface->if_rx_features = ioread32(interface->if_ctrl_rx_rb->regs + MQNIC_RB_IF_CTRL_RX_REG_FEATURES); + interface->max_rx_mtu = ioread32(interface->if_ctrl_rx_rb->regs + MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU); + + dev_info(dev, "IF RX features: 0x%08x", interface->if_rx_features); + dev_info(dev, "Max RX MTU: %d", interface->max_rx_mtu); + + interface->event_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_EVENT_QM_TYPE, MQNIC_RB_EVENT_QM_VER, 0); + + if (!interface->event_queue_rb) { + ret = -EIO; + dev_err(dev, "Event queue block not found"); + goto fail; + } + + interface->event_queue_offset = ioread32(interface->event_queue_rb->regs + MQNIC_RB_EVENT_QM_REG_OFFSET); + interface->event_queue_count = ioread32(interface->event_queue_rb->regs + MQNIC_RB_EVENT_QM_REG_COUNT); + interface->event_queue_stride = ioread32(interface->event_queue_rb->regs + MQNIC_RB_EVENT_QM_REG_STRIDE); - interface->event_queue_count = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_EVENT_QUEUE_COUNT); - dev_info(dev, "Event queue count: %d", interface->event_queue_count); - interface->event_queue_offset = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_EVENT_QUEUE_OFFSET); dev_info(dev, "Event queue offset: 0x%08x", interface->event_queue_offset); + dev_info(dev, "Event queue count: %d", interface->event_queue_count); + dev_info(dev, "Event queue stride: 0x%08x", interface->event_queue_stride); interface->event_queue_count = min_t(u32, interface->event_queue_count, MQNIC_MAX_EVENT_RINGS); - interface->tx_queue_count = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_TX_QUEUE_COUNT); - dev_info(dev, "TX queue count: %d", interface->tx_queue_count); - interface->tx_queue_offset = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_TX_QUEUE_OFFSET); + interface->tx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); + + if (!interface->tx_queue_rb) { + ret = -EIO; + dev_err(dev, "TX queue block not found"); + goto fail; + } + + interface->tx_queue_offset = ioread32(interface->tx_queue_rb->regs + MQNIC_RB_TX_QM_REG_OFFSET); + interface->tx_queue_count = ioread32(interface->tx_queue_rb->regs + MQNIC_RB_TX_QM_REG_COUNT); + interface->tx_queue_stride = ioread32(interface->tx_queue_rb->regs + MQNIC_RB_TX_QM_REG_STRIDE); + dev_info(dev, "TX queue offset: 0x%08x", interface->tx_queue_offset); + dev_info(dev, "TX queue count: %d", interface->tx_queue_count); + dev_info(dev, "TX queue stride: 0x%08x", interface->tx_queue_stride); interface->tx_queue_count = min_t(u32, interface->tx_queue_count, MQNIC_MAX_TX_RINGS); - interface->tx_cpl_queue_count = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_TX_CPL_QUEUE_COUNT); - dev_info(dev, "TX completion queue count: %d", interface->tx_cpl_queue_count); - interface->tx_cpl_queue_offset = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_TX_CPL_QUEUE_OFFSET); + interface->tx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_CQM_TYPE, MQNIC_RB_TX_CQM_VER, 0); + + if (!interface->tx_cpl_queue_rb) { + ret = -EIO; + dev_err(dev, "TX completion queue block not found"); + goto fail; + } + + interface->tx_cpl_queue_offset = ioread32(interface->tx_cpl_queue_rb->regs + MQNIC_RB_TX_CQM_REG_OFFSET); + interface->tx_cpl_queue_count = ioread32(interface->tx_cpl_queue_rb->regs + MQNIC_RB_TX_CQM_REG_COUNT); + interface->tx_cpl_queue_stride = ioread32(interface->tx_cpl_queue_rb->regs + MQNIC_RB_TX_CQM_REG_STRIDE); + dev_info(dev, "TX completion queue offset: 0x%08x", interface->tx_cpl_queue_offset); + dev_info(dev, "TX completion queue count: %d", interface->tx_cpl_queue_count); + dev_info(dev, "TX completion queue stride: 0x%08x", interface->tx_cpl_queue_stride); interface->tx_cpl_queue_count = min_t(u32, interface->tx_cpl_queue_count, MQNIC_MAX_TX_CPL_RINGS); - interface->rx_queue_count = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_RX_QUEUE_COUNT); - dev_info(dev, "RX queue count: %d", interface->rx_queue_count); - interface->rx_queue_offset = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_RX_QUEUE_OFFSET); + interface->rx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); + + if (!interface->rx_queue_rb) { + ret = -EIO; + dev_err(dev, "RX queue block not found"); + goto fail; + } + + interface->rx_queue_offset = ioread32(interface->rx_queue_rb->regs + MQNIC_RB_RX_QM_REG_OFFSET); + interface->rx_queue_count = ioread32(interface->rx_queue_rb->regs + MQNIC_RB_RX_QM_REG_COUNT); + interface->rx_queue_stride = ioread32(interface->rx_queue_rb->regs + MQNIC_RB_RX_QM_REG_STRIDE); + dev_info(dev, "RX queue offset: 0x%08x", interface->rx_queue_offset); + dev_info(dev, "RX queue count: %d", interface->rx_queue_count); + dev_info(dev, "RX queue stride: 0x%08x", interface->rx_queue_stride); interface->rx_queue_count = min_t(u32, interface->rx_queue_count, MQNIC_MAX_RX_RINGS); - interface->rx_cpl_queue_count = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_RX_CPL_QUEUE_COUNT); - dev_info(dev, "RX completion queue count: %d", interface->rx_cpl_queue_count); - interface->rx_cpl_queue_offset = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_RX_CPL_QUEUE_OFFSET); + interface->rx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_CQM_TYPE, MQNIC_RB_RX_CQM_VER, 0); + + if (!interface->rx_cpl_queue_rb) { + ret = -EIO; + dev_err(dev, "RX completion queue block not found"); + goto fail; + } + + interface->rx_cpl_queue_offset = ioread32(interface->rx_cpl_queue_rb->regs + MQNIC_RB_RX_CQM_REG_OFFSET); + interface->rx_cpl_queue_count = ioread32(interface->rx_cpl_queue_rb->regs + MQNIC_RB_RX_CQM_REG_COUNT); + interface->rx_cpl_queue_stride = ioread32(interface->rx_cpl_queue_rb->regs + MQNIC_RB_RX_CQM_REG_STRIDE); + dev_info(dev, "RX completion queue offset: 0x%08x", interface->rx_cpl_queue_offset); + dev_info(dev, "RX completion queue count: %d", interface->rx_cpl_queue_count); + dev_info(dev, "RX completion queue stride: 0x%08x", interface->rx_cpl_queue_stride); interface->rx_cpl_queue_count = min_t(u32, interface->rx_cpl_queue_count, MQNIC_MAX_RX_CPL_RINGS); - interface->port_count = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_PORT_COUNT); - dev_info(dev, "Port count: %d", interface->port_count); - interface->port_offset = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_PORT_OFFSET); - dev_info(dev, "Port offset: 0x%08x", interface->port_offset); - interface->port_stride = ioread32(interface->csr_hw_addr + MQNIC_IF_REG_PORT_STRIDE); - dev_info(dev, "Port stride: 0x%08x", interface->port_stride); - - interface->port_count = min_t(u32, interface->port_count, MQNIC_MAX_PORTS); - // determine desc block size iowrite32(0xf << 8, hw_addr + interface->tx_queue_offset + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG); interface->max_desc_block_size = 1 << ((ioread32(hw_addr + interface->tx_queue_offset + MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) >> 8) & 0xf); @@ -122,7 +205,7 @@ int mqnic_create_interface(struct mqnic_dev *mdev, struct mqnic_if **interface_p // create rings for (k = 0; k < interface->event_queue_count; k++) { ret = mqnic_create_eq_ring(interface, &interface->event_ring[k], k, - hw_addr + interface->event_queue_offset + k * MQNIC_EVENT_QUEUE_STRIDE); + hw_addr + interface->event_queue_offset + k * interface->event_queue_stride); if (ret) goto fail; @@ -137,40 +220,51 @@ int mqnic_create_interface(struct mqnic_dev *mdev, struct mqnic_if **interface_p for (k = 0; k < interface->tx_queue_count; k++) { ret = mqnic_create_tx_ring(interface, &interface->tx_ring[k], k, - hw_addr + interface->tx_queue_offset + k * MQNIC_QUEUE_STRIDE); + hw_addr + interface->tx_queue_offset + k * interface->tx_queue_stride); if (ret) goto fail; } for (k = 0; k < interface->tx_cpl_queue_count; k++) { ret = mqnic_create_cq_ring(interface, &interface->tx_cpl_ring[k], k, - hw_addr + interface->tx_cpl_queue_offset + k * MQNIC_CPL_QUEUE_STRIDE); + hw_addr + interface->tx_cpl_queue_offset + k * interface->tx_cpl_queue_stride); if (ret) goto fail; } for (k = 0; k < interface->rx_queue_count; k++) { ret = mqnic_create_rx_ring(interface, &interface->rx_ring[k], k, - hw_addr + interface->rx_queue_offset + k * MQNIC_QUEUE_STRIDE); + hw_addr + interface->rx_queue_offset + k * interface->rx_queue_stride); if (ret) goto fail; } for (k = 0; k < interface->rx_cpl_queue_count; k++) { ret = mqnic_create_cq_ring(interface, &interface->rx_cpl_ring[k], k, - hw_addr + interface->rx_cpl_queue_offset + k * MQNIC_CPL_QUEUE_STRIDE); + hw_addr + interface->rx_cpl_queue_offset + k * interface->rx_cpl_queue_stride); if (ret) goto fail; } // create ports - for (k = 0; k < interface->port_count; k++) { - ret = mqnic_create_port(interface, &interface->port[k], k, - hw_addr + interface->port_offset + k * interface->port_stride); + interface->port_count = 0; + while (interface->port_count < MQNIC_MAX_PORTS) + { + struct reg_block *sched_block_rb = find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, interface->port_count); + + if (!sched_block_rb) + break; + + ret = mqnic_create_port(interface, &interface->port[interface->port_count], + interface->port_count, sched_block_rb); if (ret) goto fail; + + interface->port_count++; } + dev_info(dev, "Port count: %d", interface->port_count); + // create net_devices interface->dev_port_base = mdev->dev_port_max; interface->dev_port_max = mdev->dev_port_max; @@ -225,6 +319,39 @@ void mqnic_destroy_interface(struct mqnic_if **interface_ptr) if (interface->port[k]) mqnic_destroy_port(&interface->port[k]); + if (interface->rb_list) + free_reg_block_list(interface->rb_list); + *interface_ptr = NULL; kfree(interface); } + +u32 mqnic_interface_get_rss_mask(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_rx_rb + MQNIC_RB_IF_CTRL_RX_REG_RSS_MASK); +} + +void mqnic_interface_set_rss_mask(struct mqnic_if *interface, u32 rss_mask) +{ + iowrite32(rss_mask, interface->if_ctrl_rx_rb + MQNIC_RB_IF_CTRL_RX_REG_RSS_MASK); +} + +u32 mqnic_interface_get_tx_mtu(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_tx_rb + MQNIC_RB_IF_CTRL_TX_REG_MTU); +} + +void mqnic_interface_set_tx_mtu(struct mqnic_if *interface, u32 mtu) +{ + iowrite32(mtu, interface->if_ctrl_tx_rb + MQNIC_RB_IF_CTRL_TX_REG_MTU); +} + +u32 mqnic_interface_get_rx_mtu(struct mqnic_if *interface) +{ + return ioread32(interface->if_ctrl_rx_rb + MQNIC_RB_IF_CTRL_RX_REG_MTU); +} + +void mqnic_interface_set_rx_mtu(struct mqnic_if *interface, u32 mtu) +{ + iowrite32(mtu, interface->if_ctrl_rx_rb + MQNIC_RB_IF_CTRL_RX_REG_MTU); +} diff --git a/modules/mqnic/mqnic_main.c b/modules/mqnic/mqnic_main.c index 3510b69b9..b3a2cbbba 100644 --- a/modules/mqnic/mqnic_main.c +++ b/modules/mqnic/mqnic_main.c @@ -37,6 +37,7 @@ #include #include #include +#include #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 4, 0) #include @@ -110,50 +111,102 @@ static int mqnic_common_probe(struct mqnic_dev *mqnic) { int ret = 0; struct device *dev = mqnic->dev; + struct reg_block *rb; + struct rtc_time tm; int k = 0, l = 0; + // Enumerate registers + mqnic->rb_list = enumerate_reg_block_list(mqnic->hw_addr, 0, mqnic->hw_regs_size); + if (!mqnic->rb_list) { + dev_err(dev, "Failed to enumerate blocks"); + return -EIO; + } + + dev_info(dev, "Device-level register blocks:"); + for (rb = mqnic->rb_list; rb->type && rb->version; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + // Read ID registers - mqnic->fw_id = ioread32(mqnic->hw_addr + MQNIC_REG_FW_ID); + mqnic->fw_id_rb = find_reg_block(mqnic->rb_list, MQNIC_RB_FW_ID_TYPE, MQNIC_RB_FW_ID_VER, 0); + + if (!mqnic->fw_id_rb) { + ret = -EIO; + dev_err(dev, "Error: FW ID block not found"); + goto fail_rb_init; + } + + mqnic->fpga_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FPGA_ID); + mqnic->fw_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_ID); + mqnic->fw_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_FW_VER); + mqnic->board_id = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_ID); + mqnic->board_ver = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BOARD_VER); + mqnic->build_date = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_BUILD_DATE); + mqnic->git_hash = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_GIT_HASH); + mqnic->rel_info = ioread32(mqnic->fw_id_rb->regs + MQNIC_RB_FW_ID_REG_REL_INFO); + + rtc_time64_to_tm(mqnic->build_date, &tm); + + dev_info(dev, "FPGA ID: 0x%08x", mqnic->fpga_id); dev_info(dev, "FW ID: 0x%08x", mqnic->fw_id); - mqnic->fw_ver = ioread32(mqnic->hw_addr + MQNIC_REG_FW_VER); - dev_info(dev, "FW version: %d.%d", mqnic->fw_ver >> 16, mqnic->fw_ver & 0xffff); - mqnic->board_id = ioread32(mqnic->hw_addr + MQNIC_REG_BOARD_ID); + dev_info(dev, "FW version: %d.%d.%d.%d", mqnic->fw_ver >> 24, + (mqnic->fw_ver >> 16) & 0xff, + (mqnic->fw_ver >> 8) & 0xff, + mqnic->fw_ver & 0xff); dev_info(dev, "Board ID: 0x%08x", mqnic->board_id); - mqnic->board_ver = ioread32(mqnic->hw_addr + MQNIC_REG_BOARD_VER); - dev_info(dev, "Board version: %d.%d", mqnic->board_ver >> 16, mqnic->board_ver & 0xffff); + dev_info(dev, "Board version: %d.%d.%d.%d", mqnic->board_ver >> 24, + (mqnic->board_ver >> 16) & 0xff, + (mqnic->board_ver >> 8) & 0xff, + mqnic->board_ver & 0xff); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0) + dev_info(dev, "Build date: %ptRd %ptRt UTC (raw: 0x%08x)", &tm, &tm, mqnic->build_date); +#else + dev_info(dev, "Build date: %04d-%02d-%02d %02d:%02d:%02d UTC (raw: 0x%08x)", + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, mqnic->build_date); +#endif + dev_info(dev, "Git hash: %08x", mqnic->git_hash); + dev_info(dev, "Release info: %08x", mqnic->rel_info); - mqnic->phc_count = ioread32(mqnic->hw_addr + MQNIC_REG_PHC_COUNT); - dev_info(dev, "PHC count: %d", mqnic->phc_count); - mqnic->phc_offset = ioread32(mqnic->hw_addr + MQNIC_REG_PHC_OFFSET); - dev_info(dev, "PHC offset: 0x%08x", mqnic->phc_offset); + mqnic->phc_rb = find_reg_block(mqnic->rb_list, MQNIC_RB_PHC_TYPE, MQNIC_RB_PHC_VER, 0); - if (mqnic->phc_count) - mqnic->phc_hw_addr = mqnic->hw_addr + mqnic->phc_offset; + // Enumerate interfaces + mqnic->if_rb = find_reg_block(mqnic->rb_list, MQNIC_RB_IF_TYPE, MQNIC_RB_IF_VER, 0); - mqnic->if_count = ioread32(mqnic->hw_addr + MQNIC_REG_IF_COUNT); + if (!mqnic->if_rb) { + ret = -EIO; + dev_err(dev, "Error: interface block not found"); + goto fail_rb_init; + } + + mqnic->if_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_OFFSET); + mqnic->if_count = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_COUNT); + mqnic->if_stride = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_STRIDE); + mqnic->if_csr_offset = ioread32(mqnic->if_rb->regs + MQNIC_RB_IF_REG_CSR_OFFSET); + + dev_info(dev, "IF offset: 0x%08x", mqnic->if_offset); dev_info(dev, "IF count: %d", mqnic->if_count); - mqnic->if_stride = ioread32(mqnic->hw_addr + MQNIC_REG_IF_STRIDE); dev_info(dev, "IF stride: 0x%08x", mqnic->if_stride); - mqnic->if_csr_offset = ioread32(mqnic->hw_addr + MQNIC_REG_IF_CSR_OFFSET); dev_info(dev, "IF CSR offset: 0x%08x", mqnic->if_csr_offset); // check BAR size if (mqnic->if_count * mqnic->if_stride > mqnic->hw_regs_size) { + ret = -EIO; dev_err(dev, "Invalid BAR configuration (%d IF * 0x%x > 0x%llx)", mqnic->if_count, mqnic->if_stride, mqnic->hw_regs_size); - return -EIO; + goto fail_bar_size; } // Board-specific init ret = mqnic_board_init(mqnic); if (ret) { dev_err(dev, "Failed to initialize board"); - return ret; + goto fail_board; } // register PHC - if (mqnic->phc_count) + if (mqnic->phc_rb) mqnic_register_phc(mqnic); mutex_init(&mqnic->state_lock); @@ -209,9 +262,11 @@ fail_create_if: mqnic_destroy_interface(&mqnic->interface[k]); mqnic_unregister_phc(mqnic); - mqnic_board_deinit(mqnic); - +fail_board: +fail_bar_size: +fail_rb_init: + free_reg_block_list(mqnic->rb_list); return ret; } @@ -226,8 +281,8 @@ static void mqnic_common_remove(struct mqnic_dev *mqnic) mqnic_destroy_interface(&mqnic->interface[k]); mqnic_unregister_phc(mqnic); - mqnic_board_deinit(mqnic); + free_reg_block_list(mqnic->rb_list); } static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -357,7 +412,7 @@ static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent } // Check if device needs to be reset - if (ioread32(mqnic->hw_addr) == 0xffffffff) { + if (ioread32(mqnic->hw_addr+4) == 0xffffffff) { ret = -EIO; dev_err(dev, "Device needs to be reset"); goto fail_reset; @@ -367,7 +422,7 @@ static int mqnic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent ret = mqnic_irq_init_pcie(mqnic); if (ret) { dev_err(dev, "Failed to set up interrupts"); - goto fail_map_bars; + goto fail_init_irq; } // Enable bus mastering for DMA @@ -386,6 +441,7 @@ fail_common: pci_clear_master(pdev); mqnic_irq_deinit_pcie(mqnic); fail_reset: +fail_init_irq: fail_map_bars: if (mqnic->hw_addr) pci_iounmap(pdev, mqnic->hw_addr); diff --git a/modules/mqnic/mqnic_netdev.c b/modules/mqnic/mqnic_netdev.c index 2cb894c89..c97d616dc 100644 --- a/modules/mqnic/mqnic_netdev.c +++ b/modules/mqnic/mqnic_netdev.c @@ -81,15 +81,12 @@ static int mqnic_start_port(struct net_device *ndev) mqnic_activate_tx_ring(priv->tx_ring[k], priv, priv->tx_cpl_ring[k]); } - // configure ports - for (k = 0; k < priv->port_count; k++) { - // set port MTU - mqnic_port_set_tx_mtu(priv->port[k], ndev->mtu + ETH_HLEN); - mqnic_port_set_rx_mtu(priv->port[k], ndev->mtu + ETH_HLEN); + // set MTU + mqnic_interface_set_tx_mtu(priv->interface, ndev->mtu + ETH_HLEN); + mqnic_interface_set_rx_mtu(priv->interface, ndev->mtu + ETH_HLEN); - // configure RSS - mqnic_port_set_rss_mask(priv->port[k], 0xffffffff); - } + // configure RSS + mqnic_interface_set_rss_mask(priv->interface, 0xffffffff); // enable first port mqnic_activate_port(priv->port[0]); @@ -384,7 +381,8 @@ int mqnic_create_netdev(struct mqnic_if *interface, struct net_device **ndev_ptr priv->port_up = false; // associate interface resources - priv->if_features = interface->if_features; + priv->if_tx_features = interface->if_tx_features; + priv->if_rx_features = interface->if_rx_features; priv->event_queue_count = interface->event_queue_count; for (k = 0; k < interface->event_queue_count; k++) @@ -471,10 +469,10 @@ int mqnic_create_netdev(struct mqnic_if *interface, struct net_device **ndev_ptr // set up features ndev->hw_features = NETIF_F_SG; - if (priv->if_features & MQNIC_IF_FEATURE_RX_CSUM) + if (priv->if_rx_features & MQNIC_IF_RX_FEATURE_CSUM) ndev->hw_features |= NETIF_F_RXCSUM; - if (priv->if_features & MQNIC_IF_FEATURE_TX_CSUM) + if (priv->if_tx_features & MQNIC_IF_TX_FEATURE_CSUM) ndev->hw_features |= NETIF_F_HW_CSUM; ndev->features = ndev->hw_features | NETIF_F_HIGHDMA; @@ -483,8 +481,8 @@ int mqnic_create_netdev(struct mqnic_if *interface, struct net_device **ndev_ptr ndev->min_mtu = ETH_MIN_MTU; ndev->max_mtu = 1500; - if (priv->port[0] && priv->port[0]->port_mtu) - ndev->max_mtu = priv->port[0]->port_mtu - ETH_HLEN; + if (interface->max_tx_mtu && interface->max_rx_mtu) + ndev->max_mtu = min(interface->max_tx_mtu, interface->max_rx_mtu) - ETH_HLEN; netif_carrier_off(ndev); diff --git a/modules/mqnic/mqnic_port.c b/modules/mqnic/mqnic_port.c index 1aa11df1e..982cdb907 100644 --- a/modules/mqnic/mqnic_port.c +++ b/modules/mqnic/mqnic_port.c @@ -36,10 +36,13 @@ #include "mqnic.h" int mqnic_create_port(struct mqnic_if *interface, struct mqnic_port **port_ptr, - int index, u8 __iomem *hw_addr) + int index, struct reg_block *block_rb) { struct device *dev = interface->dev; struct mqnic_port *port; + struct reg_block *rb; + u32 offset; + int ret = 0; port = kzalloc(sizeof(*port), GFP_KERNEL); if (!port) @@ -54,37 +57,62 @@ int mqnic_create_port(struct mqnic_if *interface, struct mqnic_port **port_ptr, port->tx_queue_count = interface->tx_queue_count; - port->hw_addr = hw_addr; + port->block_rb = block_rb; - // read ID registers - port->port_id = ioread32(port->hw_addr + MQNIC_PORT_REG_PORT_ID); - dev_info(dev, "Port ID: 0x%08x", port->port_id); - port->port_features = ioread32(port->hw_addr + MQNIC_PORT_REG_PORT_FEATURES); - dev_info(dev, "Port features: 0x%08x", port->port_features); - port->port_mtu = ioread32(port->hw_addr + MQNIC_PORT_REG_PORT_MTU); - dev_info(dev, "Port MTU: %d", port->port_mtu); + offset = ioread32(block_rb->regs + MQNIC_RB_SCHED_BLOCK_REG_OFFSET); + + port->rb_list = enumerate_reg_block_list(interface->hw_addr, offset, interface->hw_regs_size - offset); + + if (!port->rb_list) { + ret = -EIO; + dev_err(dev, "Failed to enumerate blocks"); + goto fail; + } + + dev_info(dev, "Port-level register blocks:"); + for (rb = port->rb_list; rb->type && rb->version; rb++) + dev_info(dev, " type 0x%08x (v %d.%d.%d.%d)", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + port->sched_count = 0; + for (rb = port->rb_list; rb->type && rb->version; rb++) { + if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) { + ret = mqnic_create_scheduler(port, &port->sched[port->sched_count], + port->sched_count, rb); + + if (ret) + goto fail; + + port->sched_count++; + } + } - port->sched_count = ioread32(port->hw_addr + MQNIC_PORT_REG_SCHED_COUNT); dev_info(dev, "Scheduler count: %d", port->sched_count); - port->sched_offset = ioread32(port->hw_addr + MQNIC_PORT_REG_SCHED_OFFSET); - dev_info(dev, "Scheduler offset: 0x%08x", port->sched_offset); - port->sched_stride = ioread32(port->hw_addr + MQNIC_PORT_REG_SCHED_STRIDE); - dev_info(dev, "Scheduler stride: 0x%08x", port->sched_stride); - port->sched_type = ioread32(port->hw_addr + MQNIC_PORT_REG_SCHED_TYPE); - dev_info(dev, "Scheduler type: 0x%08x", port->sched_type); mqnic_deactivate_port(port); return 0; + +fail: + mqnic_destroy_port(port_ptr); + return ret; } void mqnic_destroy_port(struct mqnic_port **port_ptr) { struct mqnic_port *port = *port_ptr; + int k; *port_ptr = NULL; mqnic_deactivate_port(port); + for (k = 0; k < ARRAY_SIZE(port->sched); k++) + if (port->sched[k]) + mqnic_destroy_scheduler(&port->sched[k]); + + if (port->rb_list) + free_reg_block_list(port->rb_list); + kfree(port); } @@ -93,47 +121,19 @@ int mqnic_activate_port(struct mqnic_port *port) int k; // enable schedulers - iowrite32(0xffffffff, port->hw_addr + MQNIC_PORT_REG_SCHED_ENABLE); - - // enable queues - for (k = 0; k < port->tx_queue_count; k++) - iowrite32(3, port->hw_addr + port->sched_offset + k * 4); + for (k = 0; k < ARRAY_SIZE(port->sched); k++) + if (port->sched[k]) + mqnic_scheduler_enable(port->sched[k]); return 0; } void mqnic_deactivate_port(struct mqnic_port *port) { + int k; + // disable schedulers - iowrite32(0, port->hw_addr + MQNIC_PORT_REG_SCHED_ENABLE); -} - -u32 mqnic_port_get_rss_mask(struct mqnic_port *port) -{ - return ioread32(port->hw_addr + MQNIC_PORT_REG_RSS_MASK); -} - -void mqnic_port_set_rss_mask(struct mqnic_port *port, u32 rss_mask) -{ - iowrite32(rss_mask, port->hw_addr + MQNIC_PORT_REG_RSS_MASK); -} - -u32 mqnic_port_get_tx_mtu(struct mqnic_port *port) -{ - return ioread32(port->hw_addr + MQNIC_PORT_REG_TX_MTU); -} - -void mqnic_port_set_tx_mtu(struct mqnic_port *port, u32 mtu) -{ - iowrite32(mtu, port->hw_addr + MQNIC_PORT_REG_TX_MTU); -} - -u32 mqnic_port_get_rx_mtu(struct mqnic_port *port) -{ - return ioread32(port->hw_addr + MQNIC_PORT_REG_RX_MTU); -} - -void mqnic_port_set_rx_mtu(struct mqnic_port *port, u32 mtu) -{ - iowrite32(mtu, port->hw_addr + MQNIC_PORT_REG_RX_MTU); + for (k = 0; k < ARRAY_SIZE(port->sched); k++) + if (port->sched[k]) + mqnic_scheduler_disable(port->sched[k]); } diff --git a/modules/mqnic/mqnic_ptp.c b/modules/mqnic/mqnic_ptp.c index 8e88abc05..ca08ab236 100644 --- a/modules/mqnic/mqnic_ptp.c +++ b/modules/mqnic/mqnic_ptp.c @@ -44,9 +44,11 @@ ktime_t mqnic_read_cpl_ts(struct mqnic_dev *mdev, struct mqnic_ring *ring, if (unlikely(!ring->ts_valid || (ring->ts_s ^ ts_s) & 0xff00)) { // seconds MSBs do not match, update cached timestamp - ring->ts_s = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_CUR_SEC_L); - ring->ts_s |= (u64) ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_CUR_SEC_H) << 32; - ring->ts_valid = 1; + if (mdev->phc_rb) { + ring->ts_s = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_CUR_SEC_L); + ring->ts_s |= (u64) ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_CUR_SEC_H) << 32; + ring->ts_valid = 1; + } } ts_s |= ring->ts_s & 0xffffffffffffff00; @@ -68,8 +70,8 @@ static int mqnic_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) scaled_ppm = -scaled_ppm; } - nom_per_fns = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_NOM_PERIOD_FNS); - nom_per_fns = (u64) ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_NOM_PERIOD_NS) << 32; + nom_per_fns = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_NOM_PERIOD_FNS); + nom_per_fns = (u64) ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_NOM_PERIOD_NS) << 32; if (nom_per_fns == 0) nom_per_fns = 0x4ULL << 32; @@ -81,8 +83,8 @@ static int mqnic_phc_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) else adj = nom_per_fns + adj; - iowrite32(adj & 0xffffffff, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_PERIOD_FNS); - iowrite32(adj >> 32, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_PERIOD_NS); + iowrite32(adj & 0xffffffff, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_PERIOD_FNS); + iowrite32(adj >> 32, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_PERIOD_NS); dev_info(mdev->dev, "%s adj: 0x%llx", __func__, adj); @@ -93,10 +95,10 @@ static int mqnic_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) { struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); - ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_FNS); - ts->tv_nsec = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_NS); - ts->tv_sec = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_SEC_L); - ts->tv_sec |= (u64) ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_SEC_H) << 32; + ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_FNS); + ts->tv_nsec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_NS); + ts->tv_sec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_SEC_L); + ts->tv_sec |= (u64) ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_SEC_H) << 32; return 0; } @@ -108,11 +110,11 @@ static int mqnic_phc_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); ptp_read_system_prets(sts); - ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_FNS); + ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_FNS); ptp_read_system_postts(sts); - ts->tv_nsec = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_NS); - ts->tv_sec = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_SEC_L); - ts->tv_sec |= (u64) ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_GET_SEC_H) << 32; + ts->tv_nsec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_NS); + ts->tv_sec = ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_SEC_L); + ts->tv_sec |= (u64) ioread32(mdev->phc_rb->regs + MQNIC_RB_PHC_REG_GET_SEC_H) << 32; return 0; } @@ -122,10 +124,10 @@ static int mqnic_phc_settime(struct ptp_clock_info *ptp, const struct timespec64 { struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); - iowrite32(0, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_SET_FNS); - iowrite32(ts->tv_nsec, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_SET_NS); - iowrite32(ts->tv_sec & 0xffffffff, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_SET_SEC_L); - iowrite32(ts->tv_sec >> 32, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_SET_SEC_H); + iowrite32(0, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_FNS); + iowrite32(ts->tv_nsec, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_NS); + iowrite32(ts->tv_sec & 0xffffffff, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_SEC_L); + iowrite32(ts->tv_sec >> 32, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_SET_SEC_H); return 0; } @@ -142,9 +144,9 @@ static int mqnic_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) ts = timespec64_add(ts, ns_to_timespec64(delta)); mqnic_phc_settime(ptp, &ts); } else { - iowrite32(0, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_ADJ_FNS); - iowrite32(delta & 0xffffffff, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_ADJ_NS); - iowrite32(1, mdev->phc_hw_addr + MQNIC_PHC_REG_PTP_ADJ_COUNT); + iowrite32(0, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_ADJ_FNS); + iowrite32(delta & 0xffffffff, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_ADJ_NS); + iowrite32(1, mdev->phc_rb->regs + MQNIC_RB_PHC_REG_ADJ_COUNT); } return 0; @@ -153,18 +155,19 @@ static int mqnic_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) static int mqnic_phc_perout(struct ptp_clock_info *ptp, int on, struct ptp_perout_request *perout) { struct mqnic_dev *mdev = container_of(ptp, struct mqnic_dev, ptp_clock_info); - u8 __iomem *hw_addr; + struct reg_block *rb; u64 start_sec, period_sec, width_sec; u32 start_nsec, period_nsec, width_nsec; - if (perout->index >= mdev->ptp_clock_info.n_per_out) + rb = find_reg_block(mdev->rb_list, MQNIC_RB_PHC_PEROUT_TYPE, + MQNIC_RB_PHC_PEROUT_VER, perout->index); + + if (!rb) return -EINVAL; - hw_addr = mdev->phc_hw_addr + MQNIC_PHC_PEROUT_OFFSET; - if (!on) { - iowrite32(0, hw_addr + MQNIC_PHC_REG_PEROUT_CTRL); + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_CTRL); return 0; } @@ -187,22 +190,22 @@ static int mqnic_phc_perout(struct ptp_clock_info *ptp, int on, struct ptp_perou dev_info(mdev->dev, "%s: period: %lld.%09d", __func__, period_sec, period_nsec); dev_info(mdev->dev, "%s: width: %lld.%09d", __func__, width_sec, width_nsec); - iowrite32(0, hw_addr + MQNIC_PHC_REG_PEROUT_START_FNS); - iowrite32(start_nsec, hw_addr + MQNIC_PHC_REG_PEROUT_START_NS); - iowrite32(start_sec & 0xffffffff, hw_addr + MQNIC_PHC_REG_PEROUT_START_SEC_L); - iowrite32(start_sec >> 32, hw_addr + MQNIC_PHC_REG_PEROUT_START_SEC_H); + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_FNS); + iowrite32(start_nsec, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_NS); + iowrite32(start_sec & 0xffffffff, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_SEC_L); + iowrite32(start_sec >> 32, rb->regs + MQNIC_RB_PHC_PEROUT_REG_START_SEC_H); - iowrite32(0, hw_addr + MQNIC_PHC_REG_PEROUT_PERIOD_FNS); - iowrite32(period_nsec, hw_addr + MQNIC_PHC_REG_PEROUT_PERIOD_NS); - iowrite32(period_sec & 0xffffffff, hw_addr + MQNIC_PHC_REG_PEROUT_PERIOD_SEC_L); - iowrite32(period_sec >> 32, hw_addr + MQNIC_PHC_REG_PEROUT_PERIOD_SEC_H); + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_FNS); + iowrite32(period_nsec, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS); + iowrite32(period_sec & 0xffffffff, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L); + iowrite32(period_sec >> 32, rb->regs + MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H); - iowrite32(0, hw_addr + MQNIC_PHC_REG_PEROUT_WIDTH_FNS); - iowrite32(width_nsec, hw_addr + MQNIC_PHC_REG_PEROUT_WIDTH_NS); - iowrite32(width_sec & 0xffffffff, hw_addr + MQNIC_PHC_REG_PEROUT_WIDTH_SEC_L); - iowrite32(width_sec >> 32, hw_addr + MQNIC_PHC_REG_PEROUT_WIDTH_SEC_H); + iowrite32(0, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_FNS); + iowrite32(width_nsec, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS); + iowrite32(width_sec & 0xffffffff, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L); + iowrite32(width_sec >> 32, rb->regs + MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H); - iowrite32(1, hw_addr + MQNIC_PHC_REG_PEROUT_CTRL); + iowrite32(1, rb->regs + MQNIC_RB_PHC_PEROUT_REG_CTRL); return 0; } @@ -239,20 +242,29 @@ static void mqnic_phc_set_from_system_clock(struct ptp_clock_info *ptp) void mqnic_register_phc(struct mqnic_dev *mdev) { - u32 phc_features; + int perout_ch_count = 0; + struct reg_block *rb; + + if (!mdev->phc_rb) { + dev_err(mdev->dev, "PTP clock not present"); + return; + } if (mdev->ptp_clock) { dev_warn(mdev->dev, "PTP clock already registered"); return; } - phc_features = ioread32(mdev->phc_hw_addr + MQNIC_PHC_REG_FEATURES); + while ((rb = find_reg_block(mdev->rb_list, MQNIC_RB_PHC_PEROUT_TYPE, + MQNIC_RB_PHC_PEROUT_VER, perout_ch_count))) { + perout_ch_count++; + } mdev->ptp_clock_info.owner = THIS_MODULE; mdev->ptp_clock_info.max_adj = 100000000; mdev->ptp_clock_info.n_alarm = 0; mdev->ptp_clock_info.n_ext_ts = 0; - mdev->ptp_clock_info.n_per_out = phc_features & 0xff; + mdev->ptp_clock_info.n_per_out = perout_ch_count; mdev->ptp_clock_info.n_pins = 0; mdev->ptp_clock_info.pps = 0; mdev->ptp_clock_info.adjfine = mqnic_phc_adjfine; diff --git a/modules/mqnic/mqnic_reg_block.c b/modules/mqnic/mqnic_reg_block.c new file mode 100644 index 000000000..83204499a --- /dev/null +++ b/modules/mqnic/mqnic_reg_block.c @@ -0,0 +1,121 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright 2021, The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of The Regents of the + * University of California. + */ + +#include "mqnic.h" + +struct reg_block *enumerate_reg_block_list(u8 __iomem *base, size_t offset, size_t size) +{ + int max_count = 8; + struct reg_block *reg_block_list = kzalloc(max_count * sizeof(struct reg_block), GFP_KERNEL); + int count = 0; + int k; + + u8 __iomem *ptr; + + u32 rb_type; + u32 rb_version; + + if (!reg_block_list) + return NULL; + + while (1) { + reg_block_list[count].type = 0; + reg_block_list[count].version = 0; + reg_block_list[count].base = 0; + reg_block_list[count].regs = 0; + + if ((offset == 0 && count != 0) || offset >= size) + break; + + ptr = base + offset; + + for (k = 0; k < count; k++) + { + if (ptr == reg_block_list[k].regs) + { + pr_err("Register blocks form a loop"); + goto fail; + } + } + + rb_type = ioread32(ptr + MQNIC_RB_REG_TYPE); + rb_version = ioread32(ptr + MQNIC_RB_REG_VER); + offset = ioread32(ptr + MQNIC_RB_REG_NEXT_PTR); + + reg_block_list[count].type = rb_type; + reg_block_list[count].version = rb_version; + reg_block_list[count].base = base; + reg_block_list[count].regs = ptr; + + count++; + + if (count >= max_count) { + struct reg_block *tmp; + max_count += 4; + tmp = krealloc(reg_block_list, max_count * sizeof(struct reg_block), GFP_KERNEL); + if (!tmp) + goto fail; + reg_block_list = tmp; + } + } + + return reg_block_list; +fail: + kfree(reg_block_list); + return NULL; +} + +struct reg_block *find_reg_block(struct reg_block *list, u32 type, u32 version, int index) +{ + struct reg_block *rb = list; + + while (rb->type && rb->version && rb->regs) { + if (rb->type == type && (!version || rb->version == version)) { + if (index > 0) + index--; + else + return rb; + } + + rb++; + } + + return NULL; +} + +void free_reg_block_list(struct reg_block *list) +{ + kfree(list); +} diff --git a/modules/mqnic/mqnic_rx.c b/modules/mqnic/mqnic_rx.c index a704e9619..34be549ec 100644 --- a/modules/mqnic/mqnic_rx.c +++ b/modules/mqnic/mqnic_rx.c @@ -363,7 +363,7 @@ int mqnic_process_rx_cq(struct mqnic_cq_ring *cq_ring, int napi_budget) } // RX hardware timestamp - if (interface->if_features & MQNIC_IF_FEATURE_PTP_TS) + if (interface->if_rx_features & MQNIC_IF_RX_FEATURE_PTP_TS) skb_hwtstamps(skb)->hwtstamp = mqnic_read_cpl_ts(interface->mdev, rx_ring, cpl); skb_record_rx_queue(skb, rx_ring->index); diff --git a/modules/mqnic/mqnic_scheduler.c b/modules/mqnic/mqnic_scheduler.c new file mode 100644 index 000000000..21c755efc --- /dev/null +++ b/modules/mqnic/mqnic_scheduler.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: BSD-2-Clause-Views +/* + * Copyright 2021, The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation + * are those of the authors and should not be interpreted as representing + * official policies, either expressed or implied, of The Regents of the + * University of California. + */ + +#include "mqnic.h" + +int mqnic_create_scheduler(struct mqnic_port *port, struct mqnic_sched **sched_ptr, + int index, struct reg_block *rb) +{ + struct device *dev = port->dev; + struct mqnic_sched *sched; + + sched = kzalloc(sizeof(*sched), GFP_KERNEL); + if (!sched) + return -ENOMEM; + + *sched_ptr = sched; + + sched->dev = dev; + sched->interface = port->interface; + sched->port = port; + + sched->index = index; + + sched->rb = rb; + + sched->type = rb->type; + sched->offset = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_OFFSET); + sched->channel_count = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_CH_COUNT); + sched->channel_stride = ioread32(rb->regs + MQNIC_RB_SCHED_RR_REG_CH_STRIDE); + + sched->hw_addr = port->interface->hw_addr + sched->offset; + + dev_info(dev, "Scheduler type: 0x%08x", sched->type); + dev_info(dev, "Scheduler offset: 0x%08x", sched->offset); + dev_info(dev, "Scheduler channel count: %d", sched->channel_count); + dev_info(dev, "Scheduler channel stride: 0x%08x", sched->channel_stride); + + mqnic_scheduler_disable(sched); + + return 0; +} + +void mqnic_destroy_scheduler(struct mqnic_sched **sched_ptr) +{ + struct mqnic_sched *sched = *sched_ptr; + *sched_ptr = NULL; + + mqnic_scheduler_disable(sched); + + kfree(sched); +} + +int mqnic_scheduler_enable(struct mqnic_sched *sched) +{ + int k; + + // enable scheduler + iowrite32(1, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CTRL); + + // enable queues + for (k = 0; k < sched->channel_count; k++) + iowrite32(3, sched->hw_addr + k * sched->channel_stride); + + return 0; +} + +void mqnic_scheduler_disable(struct mqnic_sched *sched) +{ + // disable scheduler + iowrite32(0, sched->rb->regs + MQNIC_RB_SCHED_RR_REG_CTRL); +} diff --git a/modules/mqnic/mqnic_tx.c b/modules/mqnic/mqnic_tx.c index c7171fc0c..643a08156 100644 --- a/modules/mqnic/mqnic_tx.c +++ b/modules/mqnic/mqnic_tx.c @@ -470,7 +470,7 @@ netdev_tx_t mqnic_start_xmit(struct sk_buff *skb, struct net_device *ndev) // TX hardware timestamp tx_info->ts_requested = 0; - if (unlikely(priv->if_features & MQNIC_IF_FEATURE_PTP_TS && shinfo->tx_flags & SKBTX_HW_TSTAMP)) { + if (unlikely(priv->if_tx_features & MQNIC_IF_TX_FEATURE_PTP_TS && shinfo->tx_flags & SKBTX_HW_TSTAMP)) { dev_info(priv->dev, "%s: TX TS requested", __func__); shinfo->tx_flags |= SKBTX_IN_PROGRESS; tx_info->ts_requested = 1; diff --git a/utils/Makefile b/utils/Makefile index 1bac4add0..6ec260ece 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -19,16 +19,16 @@ all: $(BIN) %.o: %.c $(CC) $(ALL_CFLAGS) -c -o $@ $< -mqnic-config: mqnic-config.o mqnic.o timespec.o +mqnic-config: mqnic-config.o mqnic.o reg_block.o timespec.o $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ -mqnic-dump: mqnic-dump.o mqnic.o +mqnic-dump: mqnic-dump.o mqnic.o reg_block.o $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ -mqnic-fw: mqnic-fw.o mqnic.o flash.o flash_spi.o flash_bpi.o fpga_id.o bitfile.o +mqnic-fw: mqnic-fw.o mqnic.o reg_block.o flash.o flash_spi.o flash_bpi.o fpga_id.o bitfile.o $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ -mqnic-bmc: mqnic-bmc.o mqnic.o +mqnic-bmc: mqnic-bmc.o mqnic.o reg_block.o $(CC) $(ALL_CFLAGS) $(LDFLAGS) $^ -o $@ perout: perout.o timespec.o diff --git a/utils/mqnic-bmc.c b/utils/mqnic-bmc.c index 723617476..6ade53479 100644 --- a/utils/mqnic-bmc.c +++ b/utils/mqnic-bmc.c @@ -47,18 +47,18 @@ static void usage(char *name) name); } -uint32_t mqnic_alveo_bmc_reg_read(struct mqnic *dev, uint32_t reg) +uint32_t mqnic_alveo_bmc_reg_read(struct reg_block *rb, uint32_t reg) { - mqnic_reg_write32(dev->regs, 0x0180, reg); - mqnic_reg_read32(dev->regs, 0x0184); // dummy read - return mqnic_reg_read32(dev->regs, 0x0184); + mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_ADDR, reg); + mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read + return mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); } -void mqnic_alveo_bmc_reg_write(struct mqnic *dev, uint32_t reg, uint32_t val) +void mqnic_alveo_bmc_reg_write(struct reg_block *rb, uint32_t reg, uint32_t val) { - mqnic_reg_write32(dev->regs, 0x0180, reg); - mqnic_reg_write32(dev->regs, 0x0184, val); - mqnic_reg_read32(dev->regs, 0x0184); // dummy read + mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_ADDR, reg); + mqnic_reg_write32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA, val); + mqnic_reg_read32(rb->regs, MQNIC_RB_ALVEO_BMC_REG_DATA); // dummy read } struct sensor_channel { @@ -123,14 +123,14 @@ struct sensor_channel alveo_bmc_sensors[] = { {0, "", ""} }; -int mqnic_gecko_bmc_read(struct mqnic *dev) +int mqnic_gecko_bmc_read(struct reg_block *rb) { uint32_t val; int timeout = 20000; while (1) { - val = mqnic_reg_read32(dev->regs, 0x0188); + val = mqnic_reg_read32(rb->regs, MQNIC_RB_GECKO_BMC_REG_STATUS); if (val & (1 << 19)) { if (val & (1 << 18)) @@ -157,30 +157,30 @@ int mqnic_gecko_bmc_read(struct mqnic *dev) return -1; } -int mqnic_gecko_bmc_write(struct mqnic *dev, uint16_t cmd, uint32_t data) +int mqnic_gecko_bmc_write(struct reg_block *rb, uint16_t cmd, uint32_t data) { int ret; - ret = mqnic_gecko_bmc_read(dev); + ret = mqnic_gecko_bmc_read(rb); if (ret == -1) return ret; - mqnic_reg_write32(dev->regs, 0x0180, data); - mqnic_reg_write32(dev->regs, 0x0184, cmd << 16); + mqnic_reg_write32(rb->regs, MQNIC_RB_GECKO_BMC_REG_DATA, data); + mqnic_reg_write32(rb->regs, MQNIC_RB_GECKO_BMC_REG_CMD, cmd << 16); return 0; } -int mqnic_gecko_bmc_query(struct mqnic *dev, uint16_t cmd, uint32_t data) +int mqnic_gecko_bmc_query(struct reg_block *rb, uint16_t cmd, uint32_t data) { int ret; - ret = mqnic_gecko_bmc_write(dev, cmd, data); + ret = mqnic_gecko_bmc_write(rb, cmd, data); if (ret) return ret; - return mqnic_gecko_bmc_read(dev); + return mqnic_gecko_bmc_read(rb); } int main(int argc, char *argv[]) @@ -191,6 +191,7 @@ int main(int argc, char *argv[]) char *device = NULL; struct mqnic *dev; + struct reg_block *bmc_rb; name = strrchr(argv[0], '/'); name = name ? 1+name : argv[0]; @@ -227,31 +228,38 @@ int main(int argc, char *argv[]) return -1; } + printf("FPGA ID: 0x%08x\n", dev->fpga_id); printf("FW ID: 0x%08x\n", dev->fw_id); - printf("FW version: %d.%d\n", dev->fw_ver >> 16, dev->fw_ver & 0xffff); + printf("FW version: %d.%d.%d.%d\n", dev->fw_ver >> 24, + (dev->fw_ver >> 16) & 0xff, + (dev->fw_ver >> 8) & 0xff, + dev->fw_ver & 0xff); printf("Board ID: 0x%08x\n", dev->board_id); - printf("Board version: %d.%d\n", dev->board_ver >> 16, dev->board_ver & 0xffff); + printf("Board version: %d.%d.%d.%d\n", dev->board_ver >> 24, + (dev->board_ver >> 16) & 0xff, + (dev->board_ver >> 8) & 0xff, + dev->board_ver & 0xff); + printf("Build date: %08x\n", dev->build_date); + printf("Git hash: %08x\n", dev->git_hash); + printf("Release info: %08x\n", dev->rel_info); - switch (dev->board_id) { - case MQNIC_BOARD_ID_AU50: - case MQNIC_BOARD_ID_AU200: - case MQNIC_BOARD_ID_AU250: - case MQNIC_BOARD_ID_AU280: + if ((bmc_rb = find_reg_block(dev->rb_list, MQNIC_RB_ALVEO_BMC_TYPE, MQNIC_RB_ALVEO_BMC_VER, 0))) + { printf("Detected Xilinx Alveo board with MSP430 BMC\n"); printf("Attempt to communicate with CMS microblaze...\n"); - if (mqnic_alveo_bmc_reg_read(dev, 0x020000) == 0 || mqnic_alveo_bmc_reg_read(dev, 0x028000) == 0) + if (mqnic_alveo_bmc_reg_read(bmc_rb, 0x020000) == 0 || mqnic_alveo_bmc_reg_read(bmc_rb, 0x028000) == 0) { printf("Resetting CMS...\n"); // reset CMS - mqnic_alveo_bmc_reg_write(dev, 0x020000, 0); - mqnic_alveo_bmc_reg_write(dev, 0x020000, 1); + mqnic_alveo_bmc_reg_write(bmc_rb, 0x020000, 0); + mqnic_alveo_bmc_reg_write(bmc_rb, 0x020000, 1); usleep(100000); } - if (mqnic_alveo_bmc_reg_read(dev, 0x028000) != 0x74736574) + if (mqnic_alveo_bmc_reg_read(bmc_rb, 0x028000) != 0x74736574) { fprintf(stderr, "CMS not responding\n"); ret = -1; @@ -263,9 +271,9 @@ int main(int argc, char *argv[]) for (const struct sensor_channel *ptr = alveo_bmc_sensors; ptr->reg; ptr++) { uint32_t reg = 0x028000 + ptr->reg; - uint32_t val_max = mqnic_alveo_bmc_reg_read(dev, reg); - uint32_t val_avg = mqnic_alveo_bmc_reg_read(dev, reg+4); - uint32_t val_ins = mqnic_alveo_bmc_reg_read(dev, reg+8); + uint32_t val_max = mqnic_alveo_bmc_reg_read(bmc_rb, reg); + uint32_t val_avg = mqnic_alveo_bmc_reg_read(bmc_rb, reg+4); + uint32_t val_ins = mqnic_alveo_bmc_reg_read(bmc_rb, reg+8); printf("%s: %d %s (%d %s avg, %d %s max)\n", ptr->name, val_ins, ptr->unit, val_avg, ptr->unit, val_max, ptr->unit); @@ -277,10 +285,10 @@ int main(int argc, char *argv[]) { uint8_t mac[6]; uint32_t reg = 0x0281a0 + k*8; - uint32_t val = mqnic_alveo_bmc_reg_read(dev, reg); + uint32_t val = mqnic_alveo_bmc_reg_read(bmc_rb, reg); mac[0] = (val >> 8) & 0xff; mac[1] = val & 0xff; - val = mqnic_alveo_bmc_reg_read(dev, reg+4); + val = mqnic_alveo_bmc_reg_read(bmc_rb, reg+4); mac[2] = (val >> 24) & 0xff; mac[3] = (val >> 16) & 0xff; mac[4] = (val >> 8) & 0xff; @@ -294,20 +302,20 @@ int main(int argc, char *argv[]) } printf("\n"); } - - break; - case MQNIC_BOARD_ID_FB2CG_KU15P: + } + else if ((bmc_rb = find_reg_block(dev->rb_list, MQNIC_RB_GECKO_BMC_TYPE, MQNIC_RB_GECKO_BMC_VER, 0))) + { printf("Detected Silicom board with Gecko BMC\n"); - if (mqnic_gecko_bmc_query(dev, 0x7006, 0) <= 0) + if (mqnic_gecko_bmc_query(bmc_rb, 0x7006, 0) <= 0) { fprintf(stderr, "Failed to communicate with BMC\n"); ret = -1; goto err; } - uint16_t v_l = mqnic_gecko_bmc_query(dev, 0x7005, 0); - uint16_t v_h = mqnic_gecko_bmc_query(dev, 0x7006, 0); + uint16_t v_l = mqnic_gecko_bmc_query(bmc_rb, 0x7005, 0); + uint16_t v_h = mqnic_gecko_bmc_query(bmc_rb, 0x7006, 0); printf("Gecko BMC version %d.%d.%d.%d\n", (v_h >> 8) & 0xff, v_h & 0xff, (v_l >> 8) & 0xff, v_l & 0xff); @@ -318,7 +326,7 @@ int main(int argc, char *argv[]) uint8_t mac[6]; for (int i = 0; i < 6; i += 2) { - uint16_t val = mqnic_gecko_bmc_query(dev, 0x2003, 0+k*6+i); + uint16_t val = mqnic_gecko_bmc_query(bmc_rb, 0x2003, 0+k*6+i); mac[i] = val & 0xff; mac[i+1] = (val >> 8) & 0xff; } @@ -331,9 +339,9 @@ int main(int argc, char *argv[]) } printf("\n"); } - - break; - default: + } + else + { fprintf(stderr, "Board does not have BMC or BMC not currently supported\n"); ret = -1; diff --git a/utils/mqnic-config.c b/utils/mqnic-config.c index 3e49cda77..9735ea58b 100644 --- a/utils/mqnic-config.c +++ b/utils/mqnic-config.c @@ -78,6 +78,8 @@ int main(int argc, char *argv[]) int interface = 0; int port = 0; + struct reg_block *rb; + struct timespec ts_now; struct timespec ts_start; struct timespec ts_period; @@ -142,18 +144,22 @@ int main(int argc, char *argv[]) return -1; } + printf("FPGA ID: 0x%08x\n", dev->fpga_id); printf("FW ID: 0x%08x\n", dev->fw_id); - printf("FW version: %d.%d\n", dev->fw_ver >> 16, dev->fw_ver & 0xffff); + printf("FW version: %d.%d.%d.%d\n", dev->fw_ver >> 24, + (dev->fw_ver >> 16) & 0xff, + (dev->fw_ver >> 8) & 0xff, + dev->fw_ver & 0xff); printf("Board ID: 0x%08x\n", dev->board_id); - printf("Board version: %d.%d\n", dev->board_ver >> 16, dev->board_ver & 0xffff); - printf("PHC count: %d\n", dev->phc_count); - printf("PHC offset: 0x%08x\n", dev->phc_offset); - printf("PHC stride: 0x%08x\n", dev->phc_stride); - printf("IF count: %d\n", dev->if_count); - printf("IF stride: 0x%08x\n", dev->if_stride); - printf("IF CSR offset: 0x%08x\n", dev->if_csr_offset); + printf("Board version: %d.%d.%d.%d\n", dev->board_ver >> 24, + (dev->board_ver >> 16) & 0xff, + (dev->board_ver >> 8) & 0xff, + dev->board_ver & 0xff); + printf("Build date: %s UTC (raw 0x%08x)\n", dev->build_date_str, dev->build_date); + printf("Git hash: %08x\n", dev->git_hash); + printf("Release info: %08x\n", dev->rel_info); - if (dev->phc_count == 0) + if (!dev->phc_rb) { fprintf(stderr, "No PHC on card\n"); goto err; @@ -173,21 +179,35 @@ int main(int argc, char *argv[]) goto err; } - printf("IF ID: 0x%08x\n", dev_interface->if_id); - - printf("Event queue count: %d\n", dev_interface->event_queue_count); + printf("IF TX features: 0x%08x\n", dev_interface->if_tx_features); + printf("Max TX MTU: %d\n", dev_interface->max_tx_mtu); + printf("TX MTU: %d\n", mqnic_reg_read32(dev_interface->if_ctrl_tx_rb->regs, MQNIC_RB_IF_CTRL_TX_REG_MTU)); + + printf("IF RX features: 0x%08x\n", dev_interface->if_rx_features); + printf("Max RX MTU: %d\n", dev_interface->max_rx_mtu); + printf("RX MTU: %d\n", mqnic_reg_read32(dev_interface->if_ctrl_rx_rb->regs, MQNIC_RB_IF_CTRL_RX_REG_MTU)); + printf("Event queue offset: 0x%08x\n", dev_interface->event_queue_offset); - printf("TX queue count: %d\n", dev_interface->tx_queue_count); + printf("Event queue count: %d\n", dev_interface->event_queue_count); + printf("Event queue stride: 0x%08x\n", dev_interface->event_queue_stride); + printf("TX queue offset: 0x%08x\n", dev_interface->tx_queue_offset); - printf("TX completion queue count: %d\n", dev_interface->tx_cpl_queue_count); + printf("TX queue count: %d\n", dev_interface->tx_queue_count); + printf("TX queue stride: 0x%08x\n", dev_interface->tx_queue_stride); + printf("TX completion queue offset: 0x%08x\n", dev_interface->tx_cpl_queue_offset); - printf("RX queue count: %d\n", dev_interface->rx_queue_count); + printf("TX completion queue count: %d\n", dev_interface->tx_cpl_queue_count); + printf("TX completion queue stride: 0x%08x\n", dev_interface->tx_cpl_queue_stride); + printf("RX queue offset: 0x%08x\n", dev_interface->rx_queue_offset); - printf("RX completion queue count: %d\n", dev_interface->rx_cpl_queue_count); + printf("RX queue count: %d\n", dev_interface->rx_queue_count); + printf("RX queue stride: 0x%08x\n", dev_interface->rx_queue_stride); + printf("RX completion queue offset: 0x%08x\n", dev_interface->rx_cpl_queue_offset); + printf("RX completion queue count: %d\n", dev_interface->rx_cpl_queue_count); + printf("RX completion queue stride: 0x%08x\n", dev_interface->rx_cpl_queue_stride); + printf("Port count: %d\n", dev_interface->port_count); - printf("Port offset: 0x%08x\n", dev_interface->port_offset); - printf("Port stride: 0x%08x\n", dev_interface->port_stride); if (port < 0 || port >= dev_interface->port_count) { @@ -202,91 +222,107 @@ int main(int argc, char *argv[]) fprintf(stderr, "Invalid port\n"); goto err; } - - printf("Port ID: 0x%08x\n", dev_port->port_id); printf("Sched count: %d\n", dev_port->sched_count); - printf("Sched offset: 0x%08x\n", dev_port->sched_offset); - printf("Sched stride: 0x%08x\n", dev_port->sched_stride); - printf("Sched type: 0x%08x\n", dev_port->sched_type); - printf("Timeslot count: %d\n", dev_port->tdma_timeslot_count); + rb = find_reg_block(dev_port->rb_list, MQNIC_RB_TDMA_SCH_TYPE, MQNIC_RB_TDMA_SCH_VER, 0); - if (period_nsec > 0) + if (dev->phc_rb && rb) { - printf("Configure port TDMA schedule\n"); + printf("TDMA timeslot count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_COUNT)); + printf("TDMA control: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_CTRL)); + printf("TDMA status: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_STATUS)); - ts_now.tv_nsec = mqnic_reg_read32(dev->phc_regs, MQNIC_PHC_REG_PTP_CUR_NS); - ts_now.tv_sec = mqnic_reg_read32(dev->phc_regs, MQNIC_PHC_REG_PTP_CUR_SEC_L) + (((int64_t)mqnic_reg_read32(dev->phc_regs, MQNIC_PHC_REG_PTP_CUR_SEC_H)) << 32); + printf("TDMA schedule start: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_NS)); + printf("TDMA schedule period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS)); + printf("TDMA timeslot period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS)); + printf("TDMA active period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS)); - // normalize start - ts_start.tv_sec = start_nsec / NSEC_PER_SEC; - ts_start.tv_nsec = start_nsec - ts_start.tv_sec * NSEC_PER_SEC; - - // normalize period - ts_period.tv_sec = period_nsec / NSEC_PER_SEC; - ts_period.tv_nsec = period_nsec - ts_period.tv_sec * NSEC_PER_SEC; - - printf("time %ld.%09ld s\n", ts_now.tv_sec, ts_now.tv_nsec); - printf("start %ld.%09ld s\n", ts_start.tv_sec, ts_start.tv_nsec); - printf("period %ld.%09ld s\n", ts_period.tv_sec, ts_period.tv_nsec); - - if (timespec_lt(ts_start, ts_now)) + if (period_nsec > 0) { - // start time is in the past + printf("Configure port TDMA schedule\n"); - // modulo start with period - ts_start = timespec_mod(ts_start, ts_period); + ts_now.tv_nsec = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_NS); + ts_now.tv_sec = mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_SEC_L) + + (((int64_t)mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_SEC_H)) << 32); - // align time with period - struct timespec ts_aligned = timespec_sub(ts_now, timespec_mod(ts_now, ts_period)); + // normalize start + ts_start.tv_sec = start_nsec / NSEC_PER_SEC; + ts_start.tv_nsec = start_nsec - ts_start.tv_sec * NSEC_PER_SEC; - // add aligned time - ts_start = timespec_add(ts_start, ts_aligned); + // normalize period + ts_period.tv_sec = period_nsec / NSEC_PER_SEC; + ts_period.tv_nsec = period_nsec - ts_period.tv_sec * NSEC_PER_SEC; + + printf("time %ld.%09ld s\n", ts_now.tv_sec, ts_now.tv_nsec); + printf("start %ld.%09ld s\n", ts_start.tv_sec, ts_start.tv_nsec); + printf("period %ld.%09ld s\n", ts_period.tv_sec, ts_period.tv_nsec); + + if (timespec_lt(ts_start, ts_now)) + { + // start time is in the past + + // modulo start with period + ts_start = timespec_mod(ts_start, ts_period); + + // align time with period + struct timespec ts_aligned = timespec_sub(ts_now, timespec_mod(ts_now, ts_period)); + + // add aligned time + ts_start = timespec_add(ts_start, ts_aligned); + } + + printf("time %ld.%09ld s\n", ts_now.tv_sec, ts_now.tv_nsec); + printf("start %ld.%09ld s\n", ts_start.tv_sec, ts_start.tv_nsec); + printf("period %ld.%09ld s\n", ts_period.tv_sec, ts_period.tv_nsec); + + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_NS, ts_start.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L, ts_start.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H, ts_start.tv_sec >> 32); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS, ts_period.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L, ts_period.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H, ts_period.tv_sec >> 32); + + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_CTRL, 0x00000001); } - printf("time %ld.%09ld s\n", ts_now.tv_sec, ts_now.tv_nsec); - printf("start %ld.%09ld s\n", ts_start.tv_sec, ts_start.tv_nsec); - printf("period %ld.%09ld s\n", ts_period.tv_sec, ts_period.tv_nsec); + if (timeslot_period_nsec > 0) + { + printf("Configure port TDMA timeslot period\n"); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_START_NS, ts_start.tv_nsec); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_START_SEC_L, ts_start.tv_sec & 0xffffffff); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_START_SEC_H, ts_start.tv_sec >> 32); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_PERIOD_NS, ts_period.tv_nsec); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_L, ts_period.tv_sec & 0xffffffff); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_H, ts_period.tv_sec >> 32); + // normalize period + ts_timeslot_period.tv_sec = timeslot_period_nsec / NSEC_PER_SEC; + ts_timeslot_period.tv_nsec = timeslot_period_nsec - ts_timeslot_period.tv_sec * NSEC_PER_SEC; - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_CTRL, 0x00000001); - } + printf("period %ld.%09ld s\n", ts_timeslot_period.tv_sec, ts_timeslot_period.tv_nsec); - if (timeslot_period_nsec > 0) - { - printf("Configure port TDMA timeslot period\n"); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS, ts_timeslot_period.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L, ts_timeslot_period.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H, ts_timeslot_period.tv_sec >> 32); + } - // normalize period - ts_timeslot_period.tv_sec = timeslot_period_nsec / NSEC_PER_SEC; - ts_timeslot_period.tv_nsec = timeslot_period_nsec - ts_timeslot_period.tv_sec * NSEC_PER_SEC; + if (active_period_nsec > 0) + { + printf("Configure port TDMA active period\n"); - printf("period %ld.%09ld s\n", ts_timeslot_period.tv_sec, ts_timeslot_period.tv_nsec); + // normalize period + ts_active_period.tv_sec = active_period_nsec / NSEC_PER_SEC; + ts_active_period.tv_nsec = active_period_nsec - ts_active_period.tv_sec * NSEC_PER_SEC; - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_NS, ts_timeslot_period.tv_nsec); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_L, ts_timeslot_period.tv_sec & 0xffffffff); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_H, ts_timeslot_period.tv_sec >> 32); - } + printf("period %ld.%09ld s\n", ts_active_period.tv_sec, ts_active_period.tv_nsec); - if (active_period_nsec > 0) - { - printf("Configure port TDMA active period\n"); - - // normalize period - ts_active_period.tv_sec = active_period_nsec / NSEC_PER_SEC; - ts_active_period.tv_nsec = active_period_nsec - ts_active_period.tv_sec * NSEC_PER_SEC; - - printf("period %ld.%09ld s\n", ts_active_period.tv_sec, ts_active_period.tv_nsec); - - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_NS, ts_active_period.tv_nsec); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_L, ts_active_period.tv_sec & 0xffffffff); - mqnic_reg_write32(dev_port->regs, MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_H, ts_active_period.tv_sec >> 32); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS, ts_active_period.tv_nsec); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L, ts_active_period.tv_sec & 0xffffffff); + mqnic_reg_write32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H, ts_active_period.tv_sec >> 32); + } } err: diff --git a/utils/mqnic-dump.c b/utils/mqnic-dump.c index f8c5e9ea9..7e99622ab 100644 --- a/utils/mqnic-dump.c +++ b/utils/mqnic-dump.c @@ -99,36 +99,60 @@ int main(int argc, char *argv[]) return -1; } + printf("Device-level register blocks:\n"); + for (struct reg_block *rb = dev->rb_list; rb->type && rb->version; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + printf("FPGA ID: 0x%08x\n", dev->fpga_id); printf("FW ID: 0x%08x\n", dev->fw_id); - printf("FW version: %d.%d\n", dev->fw_ver >> 16, dev->fw_ver & 0xffff); + printf("FW version: %d.%d.%d.%d\n", dev->fw_ver >> 24, + (dev->fw_ver >> 16) & 0xff, + (dev->fw_ver >> 8) & 0xff, + dev->fw_ver & 0xff); printf("Board ID: 0x%08x\n", dev->board_id); - printf("Board version: %d.%d\n", dev->board_ver >> 16, dev->board_ver & 0xffff); - printf("PHC count: %d\n", dev->phc_count); - printf("PHC offset: 0x%08x\n", dev->phc_offset); - printf("PHC stride: 0x%08x\n", dev->phc_stride); + printf("Board version: %d.%d.%d.%d\n", dev->board_ver >> 24, + (dev->board_ver >> 16) & 0xff, + (dev->board_ver >> 8) & 0xff, + dev->board_ver & 0xff); + printf("Build date: %s UTC (raw 0x%08x)\n", dev->build_date_str, dev->build_date); + printf("Git hash: %08x\n", dev->git_hash); + printf("Release info: %08x\n", dev->rel_info); + + printf("IF offset: 0x%08x\n", dev->if_offset); printf("IF count: %d\n", dev->if_count); printf("IF stride: 0x%08x\n", dev->if_stride); printf("IF CSR offset: 0x%08x\n", dev->if_csr_offset); - for (int k = 0; k < dev->phc_count; k++) + if (dev->phc_rb) { - volatile uint8_t *phc_base = dev->phc_regs + k*dev->phc_stride; + int ch; - printf("PHC%d features: 0x%08x\n", k, mqnic_reg_read32(phc_base, MQNIC_PHC_REG_FEATURES)); + printf("PHC time: %ld.%09d s\n", mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_SEC_L) + + (((int64_t)mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_SEC_H)) << 32), + mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_CUR_NS)); + printf("PHC period: %d ns 0x%08x fns\n", mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_PERIOD_NS), + mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_PERIOD_FNS)); + printf("PHC nom period: %d ns 0x%08x fns\n", mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_NOM_PERIOD_NS), + mqnic_reg_read32(dev->phc_rb->regs, MQNIC_RB_PHC_REG_NOM_PERIOD_FNS)); - printf("PHC%d time: %ld.%09d s\n", k, mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_CUR_SEC_L) + (((int64_t)mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_CUR_SEC_H)) << 32), mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_CUR_NS)); - printf("PHC%d period: %d ns 0x%08x fns\n", k, mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_PERIOD_NS), mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_PERIOD_FNS)); - printf("PHC%d nom period: %d ns 0x%08x fns\n", k, mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_NOM_PERIOD_NS), mqnic_reg_read32(phc_base, MQNIC_PHC_REG_PTP_NOM_PERIOD_FNS)); - - for (int ch = 0; ch < (mqnic_reg_read32(phc_base, MQNIC_PHC_REG_FEATURES) & 0xff); ch++) + ch = 0; + for (struct reg_block *rb = dev->rb_list; rb->type && rb->version; rb++) { - volatile uint8_t *perout_base = phc_base + MQNIC_PHC_PEROUT_OFFSET + MQNIC_PHC_PEROUT_STRIDE*ch; - - printf("PHC%d perout ch %d ctrl: 0x%08x\n", k, ch, mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_CTRL)); - printf("PHC%d perout ch %d status: 0x%08x\n", k, ch, mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_STATUS)); - printf("PHC%d perout ch %d start: %ld.%09d s\n", k, ch, mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_START_SEC_L) + (((int64_t)mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_START_SEC_H)) << 32), mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_START_NS)); - printf("PHC%d perout ch %d period: %ld.%09d s\n", k, ch, mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_PERIOD_SEC_L) + (((int64_t)mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_PERIOD_SEC_H)) << 32), mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_PERIOD_NS)); - printf("PHC%d perout ch %d width: %ld.%09d s\n", k, ch, mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_WIDTH_SEC_L) + (((int64_t)mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_WIDTH_SEC_H)) << 32), mqnic_reg_read32(perout_base, MQNIC_PHC_REG_PEROUT_WIDTH_NS)); + if (rb->type == MQNIC_RB_PHC_PEROUT_TYPE && rb->version == MQNIC_RB_PHC_PEROUT_VER) + { + printf("PHC perout ch %d ctrl: 0x%08x\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_CTRL)); + printf("PHC perout ch %d start: %ld.%09d s\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_START_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_START_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_START_NS)); + printf("PHC perout ch %d period: %ld.%09d s\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_PERIOD_NS)); + printf("PHC perout ch %d width: %ld.%09d s\n", ch, mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_WIDTH_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_PHC_PEROUT_REG_WIDTH_NS)); + ch++; + } } } @@ -148,22 +172,41 @@ int main(int argc, char *argv[]) goto err; } - printf("IF ID: 0x%08x\n", dev_interface->if_id); - printf("IF features: 0x%08x\n", dev_interface->if_features); - - printf("Event queue count: %d\n", dev_interface->event_queue_count); + printf("Interface-level register blocks:\n"); + for (struct reg_block *rb = dev_interface->rb_list; rb->type && rb->version; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + + printf("IF TX features: 0x%08x\n", dev_interface->if_tx_features); + printf("Max TX MTU: %d\n", dev_interface->max_tx_mtu); + printf("TX MTU: %d\n", mqnic_reg_read32(dev_interface->if_ctrl_tx_rb->regs, MQNIC_RB_IF_CTRL_TX_REG_MTU)); + + printf("IF RX features: 0x%08x\n", dev_interface->if_rx_features); + printf("Max RX MTU: %d\n", dev_interface->max_rx_mtu); + printf("RX MTU: %d\n", mqnic_reg_read32(dev_interface->if_ctrl_rx_rb->regs, MQNIC_RB_IF_CTRL_RX_REG_MTU)); + printf("RSS mask: 0x%08x\n", mqnic_reg_read32(dev_interface->if_ctrl_rx_rb->regs, MQNIC_RB_IF_CTRL_RX_REG_RSS_MASK)); + printf("Event queue offset: 0x%08x\n", dev_interface->event_queue_offset); - printf("TX queue count: %d\n", dev_interface->tx_queue_count); + printf("Event queue count: %d\n", dev_interface->event_queue_count); + printf("Event queue stride: 0x%08x\n", dev_interface->event_queue_stride); + printf("TX queue offset: 0x%08x\n", dev_interface->tx_queue_offset); - printf("TX completion queue count: %d\n", dev_interface->tx_cpl_queue_count); + printf("TX queue count: %d\n", dev_interface->tx_queue_count); + printf("TX queue stride: 0x%08x\n", dev_interface->tx_queue_stride); + printf("TX completion queue offset: 0x%08x\n", dev_interface->tx_cpl_queue_offset); - printf("RX queue count: %d\n", dev_interface->rx_queue_count); + printf("TX completion queue count: %d\n", dev_interface->tx_cpl_queue_count); + printf("TX completion queue stride: 0x%08x\n", dev_interface->tx_cpl_queue_stride); + printf("RX queue offset: 0x%08x\n", dev_interface->rx_queue_offset); - printf("RX completion queue count: %d\n", dev_interface->rx_cpl_queue_count); + printf("RX queue count: %d\n", dev_interface->rx_queue_count); + printf("RX queue stride: 0x%08x\n", dev_interface->rx_queue_stride); + printf("RX completion queue offset: 0x%08x\n", dev_interface->rx_cpl_queue_offset); + printf("RX completion queue count: %d\n", dev_interface->rx_cpl_queue_count); + printf("RX completion queue stride: 0x%08x\n", dev_interface->rx_cpl_queue_stride); + printf("Port count: %d\n", dev_interface->port_count); - printf("Port offset: 0x%08x\n", dev_interface->port_offset); - printf("Port stride: 0x%08x\n", dev_interface->port_stride); if (port < 0 || port >= dev_interface->port_count) { @@ -181,35 +224,61 @@ int main(int argc, char *argv[]) goto err; } - printf("Port ID: 0x%08x\n", dev_port->port_id); - printf("Port features: 0x%08x\n", dev_port->port_features); - printf("Port MTU: %d\n", dev_port->port_mtu); - + printf("Port-level register blocks:\n"); + for (struct reg_block *rb = dev_port->rb_list; rb->type && rb->version; rb++) + printf(" type 0x%08x (v %d.%d.%d.%d)\n", rb->type, rb->version >> 24, + (rb->version >> 16) & 0xff, (rb->version >> 8) & 0xff, rb->version & 0xff); + printf("Sched count: %d\n", dev_port->sched_count); - printf("Sched offset: 0x%08x\n", dev_port->sched_offset); - printf("Sched stride: 0x%08x\n", dev_port->sched_stride); - printf("Sched type: 0x%08x\n", dev_port->sched_type); - printf("TX MTU: %d\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TX_MTU)); - printf("RX MTU: %d\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_RX_MTU)); - - if (dev->phc_count > 0) + for (struct reg_block *rb = dev_port->rb_list; rb->type && rb->version; rb++) { - printf("TDMA control: 0x%08x\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_CTRL)); - printf("TDMA status: 0x%08x\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_STATUS)); - printf("TDMA timeslot count: %d\n", dev_port->tdma_timeslot_count); + if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) + { + printf("Round-robin scheduler\n"); - printf("TDMA schedule start: %ld.%09d s\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_START_SEC_L) + (((int64_t)mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_START_SEC_H)) << 32), mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_START_NS)); - printf("TDMA schedule period: %ld.%09d s\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_L) + (((int64_t)mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_PERIOD_SEC_H)) << 32), mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_SCHED_PERIOD_NS)); - printf("TDMA timeslot period: %ld.%09d s\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_L) + (((int64_t)mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_SEC_H)) << 32), mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_PERIOD_NS)); - printf("TDMA active period: %ld.%09d s\n", mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_L) + (((int64_t)mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_SEC_H)) << 32), mqnic_reg_read32(dev_port->regs, MQNIC_PORT_REG_TDMA_ACTIVE_PERIOD_NS)); + printf("Sched channel count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_COUNT)); + printf("Sched channel stride: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_STRIDE)); + printf("Sched control: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CTRL)); + printf("Sched dest: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_DEST)); + } + else if (rb->type == MQNIC_RB_SCHED_CTRL_TDMA_TYPE && rb->version == MQNIC_RB_SCHED_CTRL_TDMA_VER) + { + printf("TDMA scheduler controller\n"); + + printf("Sched channel count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_COUNT)); + printf("Sched channel stride: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_CH_STRIDE)); + printf("Sched control: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_CTRL)); + printf("Sched timeslot count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_CTRL_TDMA_REG_TS_COUNT)); + } + else if (rb->type == MQNIC_RB_TDMA_SCH_TYPE && rb->version == MQNIC_RB_TDMA_SCH_VER) + { + printf("TDMA scheduler\n"); + + printf("TDMA timeslot count: %d\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_COUNT)); + printf("TDMA control: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_CTRL)); + printf("TDMA status: 0x%08x\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_STATUS)); + + printf("TDMA schedule start: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_START_NS)); + printf("TDMA schedule period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_SCH_PERIOD_NS)); + printf("TDMA timeslot period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_TS_PERIOD_NS)); + printf("TDMA active period: %ld.%09d s\n", mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_L) + + (((int64_t)mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_SEC_H)) << 32), + mqnic_reg_read32(rb->regs, MQNIC_RB_TDMA_SCH_REG_ACTIVE_PERIOD_NS)); + } } printf("TX queue info\n"); printf(" Queue Base Address E B LS CPL Head Tail Len\n"); for (int k = 0; k < dev_interface->tx_queue_count; k++) { - volatile uint8_t *base = dev_interface->regs+dev_interface->tx_queue_offset+k*MQNIC_QUEUE_STRIDE; + volatile uint8_t *base = dev_interface->regs+dev_interface->tx_queue_offset+k*dev_interface->tx_queue_stride; uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG+4) << 32); uint8_t active = (mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_QUEUE_ACTIVE_MASK) != 0; @@ -227,7 +296,7 @@ int main(int argc, char *argv[]) printf(" Queue Base Address E LS A C Int Head Tail Len\n"); for (int k = 0; k < dev_interface->tx_queue_count; k++) { - volatile uint8_t *base = dev_interface->regs+dev_interface->tx_cpl_queue_offset+k*MQNIC_CPL_QUEUE_STRIDE; + volatile uint8_t *base = dev_interface->regs+dev_interface->tx_cpl_queue_offset+k*dev_interface->tx_cpl_queue_stride; uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CPL_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CPL_QUEUE_BASE_ADDR_REG+4) << 32); uint8_t active = (mqnic_reg_read32(base, MQNIC_CPL_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_CPL_QUEUE_ACTIVE_MASK) != 0; @@ -246,7 +315,7 @@ int main(int argc, char *argv[]) printf(" Queue Base Address E B LS CPL Head Tail Len\n"); for (int k = 0; k < dev_interface->rx_queue_count; k++) { - volatile uint8_t *base = dev_interface->regs+dev_interface->rx_queue_offset+k*MQNIC_QUEUE_STRIDE; + volatile uint8_t *base = dev_interface->regs+dev_interface->rx_queue_offset+k*dev_interface->rx_queue_stride; uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_QUEUE_BASE_ADDR_REG+4) << 32); uint8_t active = (mqnic_reg_read32(base, MQNIC_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_QUEUE_ACTIVE_MASK) != 0; @@ -264,7 +333,7 @@ int main(int argc, char *argv[]) printf(" Queue Base Address E LS A C Int Head Tail Len\n"); for (int k = 0; k < dev_interface->rx_queue_count; k++) { - volatile uint8_t *base = dev_interface->regs+dev_interface->rx_cpl_queue_offset+k*MQNIC_CPL_QUEUE_STRIDE; + volatile uint8_t *base = dev_interface->regs+dev_interface->rx_cpl_queue_offset+k*dev_interface->rx_cpl_queue_stride; uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CPL_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CPL_QUEUE_BASE_ADDR_REG+4) << 32); uint8_t active = (mqnic_reg_read32(base, MQNIC_CPL_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_CPL_QUEUE_ACTIVE_MASK) != 0; @@ -283,7 +352,7 @@ int main(int argc, char *argv[]) printf(" Queue Base Address E LS A C Int Head Tail Len\n"); for (int k = 0; k < dev_interface->event_queue_count; k++) { - volatile uint8_t *base = dev_interface->regs+dev_interface->event_queue_offset+k*MQNIC_CPL_QUEUE_STRIDE; + volatile uint8_t *base = dev_interface->regs+dev_interface->event_queue_offset+k*dev_interface->event_queue_stride; uint64_t base_addr = (uint64_t)mqnic_reg_read32(base, MQNIC_CPL_QUEUE_BASE_ADDR_REG) + ((uint64_t)mqnic_reg_read32(base, MQNIC_CPL_QUEUE_BASE_ADDR_REG+4) << 32); uint8_t active = (mqnic_reg_read32(base, MQNIC_CPL_QUEUE_ACTIVE_LOG_SIZE_REG) & MQNIC_CPL_QUEUE_ACTIVE_MASK) != 0; diff --git a/utils/mqnic-fw.c b/utils/mqnic-fw.c index 673a22b29..331f82540 100644 --- a/utils/mqnic-fw.c +++ b/utils/mqnic-fw.c @@ -464,6 +464,8 @@ int main(int argc, char *argv[]) struct mqnic *dev = NULL; + struct reg_block *flash_rb = NULL; + struct flash_device *pri_flash = NULL; struct flash_device *sec_flash = NULL; @@ -566,32 +568,30 @@ int main(int argc, char *argv[]) printf("PCIe ID (device): %s\n", strrchr(device_path, '/')+1); printf("PCIe ID (upstream port): %s\n", strrchr(port_path, '/')+1); - printf("FW ID: 0x%08x\n", dev->fw_id); - printf("FW version: %d.%d\n", dev->fw_ver >> 16, dev->fw_ver & 0xffff); - printf("Board ID: 0x%08x\n", dev->board_id); - printf("Board version: %d.%d\n", dev->board_ver >> 16, dev->board_ver & 0xffff); + uint32_t flash_format = 0; + const char *fpga_part = get_fpga_part(dev->fpga_id); - uint32_t flash_id = mqnic_reg_read32(dev->regs, MQNIC_REG_FLASH_ID); - uint32_t fpga_id = mqnic_reg_read32(dev->regs, MQNIC_REG_FPGA_ID); - const char *fpga_part = get_fpga_part(fpga_id); + uint8_t flash_configuration = 0; + uint8_t flash_data_width = 0; + uint8_t flash_addr_width = 0; - uint8_t flash_type = flash_id >> 0; - uint8_t flash_configuration = flash_id >> 8; - uint8_t flash_data_width = flash_id >> 16; - uint8_t flash_addr_width = flash_id >> 24; - - printf("Flash ID: 0x%08x\n", flash_id); - printf("FPGA ID: 0x%08x\n", fpga_id); + printf("FPGA ID: 0x%08x\n", dev->fpga_id); printf("FPGA part: %s\n", fpga_part); + printf("FW ID: 0x%08x\n", dev->fw_id); + printf("FW version: %d.%d.%d.%d\n", dev->fw_ver >> 24, + (dev->fw_ver >> 16) & 0xff, + (dev->fw_ver >> 8) & 0xff, + dev->fw_ver & 0xff); + printf("Board ID: 0x%08x\n", dev->board_id); + printf("Board version: %d.%d.%d.%d\n", dev->board_ver >> 24, + (dev->board_ver >> 16) & 0xff, + (dev->board_ver >> 8) & 0xff, + dev->board_ver & 0xff); + printf("Build date: %s UTC (raw 0x%08x)\n", dev->build_date_str, dev->build_date); + printf("Git hash: %08x\n", dev->git_hash); + printf("Release info: %08x\n", dev->rel_info); - if (flash_id == 0 || flash_id == 0xffffffff) - { - fprintf(stderr, "Invalid flash ID\n"); - ret = -1; - goto skip_flash; - } - - if (fpga_id == 0 || fpga_id == 0xffffffff) + if (dev->fpga_id == 0 || dev->fpga_id == 0xffffffff) { fprintf(stderr, "Invalid FPGA ID\n"); ret = -1; @@ -602,20 +602,29 @@ int main(int argc, char *argv[]) int word_size = 8; int dual_qspi = 0; - size_t flash_size; - size_t segment_size; - size_t segment_offset; + size_t flash_size = 0; + size_t segment_size = 0; + size_t segment_offset = 0; - if (flash_type == 0 || flash_type == 2) + if ((flash_rb = find_reg_block(dev->rb_list, MQNIC_RB_SPI_FLASH_TYPE, MQNIC_RB_SPI_FLASH_VER, 0))) { + // SPI flash + flash_format = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_SPI_FLASH_REG_FORMAT); + printf("Flash type: SPI\n"); + printf("Flash format: 0x%08x\n", flash_format); + + flash_configuration = flash_format >> 8; + flash_data_width = flash_format >> 16; + flash_addr_width = flash_format >> 24; + printf("Data width: %d\n", flash_data_width); if (flash_data_width > 4) { dual_qspi = 1; - pri_flash = flash_open_spi(4, dev->regs+MQNIC_REG_FLASH_SPI_0_CTRL); - sec_flash = flash_open_spi(4, dev->regs+MQNIC_REG_FLASH_SPI_1_CTRL); + pri_flash = flash_open_spi(4, flash_rb->regs+MQNIC_RB_SPI_FLASH_REG_CTRL_0); + sec_flash = flash_open_spi(4, flash_rb->regs+MQNIC_RB_SPI_FLASH_REG_CTRL_1); if (!pri_flash || !sec_flash) { @@ -628,8 +637,7 @@ int main(int argc, char *argv[]) } else { - pri_flash = flash_open_spi(flash_data_width, - dev->regs+MQNIC_REG_FLASH_SPI_0_CTRL); + pri_flash = flash_open_spi(flash_data_width, flash_rb->regs+MQNIC_RB_SPI_FLASH_REG_CTRL_0); if (!pri_flash) { @@ -641,9 +649,18 @@ int main(int argc, char *argv[]) flash_size = pri_flash->size; } } - else if (flash_type == 1) + else if ((flash_rb = find_reg_block(dev->rb_list, MQNIC_RB_BPI_FLASH_TYPE, MQNIC_RB_BPI_FLASH_VER, 0))) { + // BPI flash + flash_format = mqnic_reg_read32(flash_rb->regs, MQNIC_RB_BPI_FLASH_REG_FORMAT); + printf("Flash type: BPI\n"); + printf("Flash format: 0x%08x\n", flash_format); + + flash_configuration = flash_format >> 8; + flash_data_width = flash_format >> 16; + flash_addr_width = flash_format >> 24; + printf("Data width: %d\n", flash_data_width); printf("Address width: %d\n", flash_addr_width); @@ -655,9 +672,9 @@ int main(int argc, char *argv[]) } pri_flash = flash_open_bpi(flash_data_width, - dev->regs+MQNIC_REG_FLASH_BPI_CTRL, - dev->regs+MQNIC_REG_FLASH_BPI_ADDR, - dev->regs+MQNIC_REG_FLASH_BPI_DATA); + flash_rb->regs+MQNIC_RB_BPI_FLASH_REG_CTRL, + flash_rb->regs+MQNIC_RB_BPI_FLASH_REG_ADDR, + flash_rb->regs+MQNIC_RB_BPI_FLASH_REG_DATA); if (!pri_flash) { @@ -670,7 +687,7 @@ int main(int argc, char *argv[]) } else { - fprintf(stderr, "Unknown flash type: %d\n", flash_type); + fprintf(stderr, "Failed to detect flash\n"); ret = -1; goto skip_flash; } @@ -1240,7 +1257,9 @@ skip_flash: // reload FPGA printf("Triggering IPROG to reload FPGA...\n"); - mqnic_reg_write32(dev->regs, MQNIC_REG_FPGA_ID, 0xFEE1DEAD); + if (flash_rb) + mqnic_reg_write32(flash_rb, MQNIC_RB_BPI_FLASH_REG_FORMAT, 0xFEE1DEAD); + mqnic_reg_write32(dev->fw_id_rb, MQNIC_RB_FW_ID_REG_FPGA_ID, 0xFEE1DEAD); // disconnect mqnic_close(dev); diff --git a/utils/mqnic.c b/utils/mqnic.c index 913287870..0477f40ba 100644 --- a/utils/mqnic.c +++ b/utils/mqnic.c @@ -38,6 +38,7 @@ either expressed or implied, of The Regents of the University of California. #include #include #include +#include #include #include #include @@ -88,7 +89,7 @@ struct mqnic *mqnic_open(const char *dev_name) goto fail_mmap_regs; } - if (mqnic_reg_read32(dev->regs, MQNIC_REG_FW_ID) == 0xffffffff) + if (mqnic_reg_read32(dev->regs, 4) == 0xffffffff) { // if we were given a PCIe resource, then we may need to enable the device char path[PATH_MAX+32]; @@ -113,46 +114,80 @@ struct mqnic *mqnic_open(const char *dev_name) } } - if (mqnic_reg_read32(dev->regs, MQNIC_REG_FW_ID) == 0xffffffff) + if (mqnic_reg_read32(dev->regs, 4) == 0xffffffff) { fprintf(stderr, "Error: device needs to be reset\n"); goto fail_reset; } - dev->fw_id = mqnic_reg_read32(dev->regs, MQNIC_REG_FW_ID); - dev->fw_ver = mqnic_reg_read32(dev->regs, MQNIC_REG_FW_VER); - dev->board_id = mqnic_reg_read32(dev->regs, MQNIC_REG_BOARD_ID); - dev->board_ver = mqnic_reg_read32(dev->regs, MQNIC_REG_BOARD_VER); + dev->rb_list = enumerate_reg_block_list(dev->regs, 0, dev->regs_size); - dev->phc_count = mqnic_reg_read32(dev->regs, MQNIC_REG_PHC_COUNT); - dev->phc_offset = mqnic_reg_read32(dev->regs, MQNIC_REG_PHC_OFFSET); - dev->phc_stride = mqnic_reg_read32(dev->regs, MQNIC_REG_PHC_STRIDE); - - if (dev->phc_count) + if (!dev->rb_list) { - dev->phc_regs = dev->regs + dev->phc_offset; + fprintf(stderr, "Error: filed to enumerate blocks\n"); + goto fail_enum; } - dev->if_count = mqnic_reg_read32(dev->regs, MQNIC_REG_IF_COUNT); - dev->if_stride = mqnic_reg_read32(dev->regs, MQNIC_REG_IF_STRIDE); - dev->if_csr_offset = mqnic_reg_read32(dev->regs, MQNIC_REG_IF_CSR_OFFSET); + // Read ID registers + dev->fw_id_rb = find_reg_block(dev->rb_list, MQNIC_RB_FW_ID_TYPE, MQNIC_RB_FW_ID_VER, 0); + + if (!dev->fw_id_rb) + { + fprintf(stderr, "Error: FW ID block not found\n"); + goto fail_enum; + } + + dev->fpga_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FPGA_ID); + dev->fw_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_ID); + dev->fw_ver = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_FW_VER); + dev->board_id = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_BOARD_ID); + dev->board_ver = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_BOARD_VER); + dev->build_date = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_BUILD_DATE); + dev->git_hash = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_GIT_HASH); + dev->rel_info = mqnic_reg_read32(dev->fw_id_rb->regs, MQNIC_RB_FW_ID_REG_REL_INFO); + + time_t build_date = dev->build_date; + struct tm *tm_info = gmtime(&build_date); + strftime(dev->build_date_str, sizeof(dev->build_date_str), "%F %T", tm_info); + + dev->phc_rb = find_reg_block(dev->rb_list, MQNIC_RB_PHC_TYPE, MQNIC_RB_PHC_VER, 0); + + // Enumerate interfaces + dev->if_rb = find_reg_block(dev->rb_list, MQNIC_RB_IF_TYPE, MQNIC_RB_IF_VER, 0); + + if (!dev->if_rb) + { + fprintf(stderr, "Interface block not found, skipping interface enumeration\n"); + dev->if_count = 0; + goto skip_interface; + } + + dev->if_offset = mqnic_reg_read32(dev->if_rb->regs, MQNIC_RB_IF_REG_OFFSET); + dev->if_count = mqnic_reg_read32(dev->if_rb->regs, MQNIC_RB_IF_REG_COUNT); + dev->if_stride = mqnic_reg_read32(dev->if_rb->regs, MQNIC_RB_IF_REG_STRIDE); + dev->if_csr_offset = mqnic_reg_read32(dev->if_rb->regs, MQNIC_RB_IF_REG_CSR_OFFSET); if (dev->if_count > MQNIC_MAX_IF) dev->if_count = MQNIC_MAX_IF; for (int k = 0; k < dev->if_count; k++) { - struct mqnic_if *interface = mqnic_if_open(dev, k, dev->regs + k*dev->if_stride); + struct mqnic_if *interface = mqnic_if_open(dev, k, dev->regs + dev->if_offset + k*dev->if_stride); if (!interface) - goto fail; + { + fprintf(stderr, "Failed to create interface %d, skipping\n", k); + continue; + } dev->interfaces[k] = interface; } +skip_interface: return dev; fail: +fail_enum: fail_reset: mqnic_close(dev); return NULL; @@ -180,6 +215,9 @@ void mqnic_close(struct mqnic *dev) dev->interfaces[k] = NULL; } + if (dev->rb_list) + free_reg_block_list(dev->rb_list); + munmap((void *)dev->regs, dev->regs_size); close(dev->fd); free(dev); @@ -207,46 +245,127 @@ struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *r goto fail; } - interface->if_id = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_IF_ID); - interface->if_features = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_IF_FEATURES); + // Enumerate registers + interface->rb_list = enumerate_reg_block_list(interface->regs, dev->if_csr_offset, interface->regs_size); - interface->event_queue_count = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_EVENT_QUEUE_COUNT); - interface->event_queue_offset = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_EVENT_QUEUE_OFFSET); - interface->tx_queue_count = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_TX_QUEUE_COUNT); - interface->tx_queue_offset = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_TX_QUEUE_OFFSET); - interface->tx_cpl_queue_count = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_TX_CPL_QUEUE_COUNT); - interface->tx_cpl_queue_offset = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_TX_CPL_QUEUE_OFFSET); - interface->rx_queue_count = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_RX_QUEUE_COUNT); - interface->rx_queue_offset = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_RX_QUEUE_OFFSET); - interface->rx_cpl_queue_count = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_RX_CPL_QUEUE_COUNT); - interface->rx_cpl_queue_offset = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_RX_CPL_QUEUE_OFFSET); + if (!interface->rb_list) + { + fprintf(stderr, "Error: filed to enumerate blocks\n"); + goto fail; + } - interface->port_count = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_PORT_COUNT); - interface->port_offset = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_PORT_OFFSET); - interface->port_stride = mqnic_reg_read32(interface->csr_regs, MQNIC_IF_REG_PORT_STRIDE); + interface->if_ctrl_tx_rb = find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_TX_TYPE, MQNIC_RB_IF_CTRL_TX_VER, 0); + + if (!interface->if_ctrl_tx_rb) + { + fprintf(stderr, "Error: TX interface control block not found\n"); + goto fail; + } + + interface->if_tx_features = mqnic_reg_read32(interface->if_ctrl_tx_rb->regs, MQNIC_RB_IF_CTRL_TX_REG_FEATURES); + interface->max_tx_mtu = mqnic_reg_read32(interface->if_ctrl_tx_rb->regs, MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU); + + interface->if_ctrl_rx_rb = find_reg_block(interface->rb_list, MQNIC_RB_IF_CTRL_RX_TYPE, MQNIC_RB_IF_CTRL_RX_VER, 0); + + if (!interface->if_ctrl_rx_rb) + { + fprintf(stderr, "Error: RX interface control block not found\n"); + goto fail; + } + + interface->if_rx_features = mqnic_reg_read32(interface->if_ctrl_rx_rb->regs, MQNIC_RB_IF_CTRL_RX_REG_FEATURES); + interface->max_rx_mtu = mqnic_reg_read32(interface->if_ctrl_rx_rb->regs, MQNIC_RB_IF_CTRL_TX_REG_MAX_MTU); + + interface->event_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_EVENT_QM_TYPE, MQNIC_RB_EVENT_QM_VER, 0); + + if (!interface->event_queue_rb) + { + fprintf(stderr, "Error: Event queue block not found\n"); + goto fail; + } + + interface->event_queue_offset = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_OFFSET); + interface->event_queue_count = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_COUNT); + interface->event_queue_stride = mqnic_reg_read32(interface->event_queue_rb->regs, MQNIC_RB_EVENT_QM_REG_STRIDE); if (interface->event_queue_count > MQNIC_MAX_EVENT_RINGS) interface->event_queue_count = MQNIC_MAX_EVENT_RINGS; + + interface->tx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_QM_TYPE, MQNIC_RB_TX_QM_VER, 0); + + if (!interface->tx_queue_rb) + { + fprintf(stderr, "Error: TX queue block not found\n"); + goto fail; + } + + interface->tx_queue_offset = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_OFFSET); + interface->tx_queue_count = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_COUNT); + interface->tx_queue_stride = mqnic_reg_read32(interface->tx_queue_rb->regs, MQNIC_RB_TX_QM_REG_STRIDE); + if (interface->tx_queue_count > MQNIC_MAX_TX_RINGS) interface->tx_queue_count = MQNIC_MAX_TX_RINGS; + + interface->tx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_TX_CQM_TYPE, MQNIC_RB_TX_CQM_VER, 0); + + if (!interface->tx_cpl_queue_rb) + { + fprintf(stderr, "Error: TX completion queue block not found\n"); + goto fail; + } + + interface->tx_cpl_queue_offset = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_OFFSET); + interface->tx_cpl_queue_count = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_COUNT); + interface->tx_cpl_queue_stride = mqnic_reg_read32(interface->tx_cpl_queue_rb->regs, MQNIC_RB_TX_CQM_REG_STRIDE); + if (interface->tx_cpl_queue_count > MQNIC_MAX_TX_CPL_RINGS) interface->tx_cpl_queue_count = MQNIC_MAX_TX_CPL_RINGS; + + interface->rx_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_QM_TYPE, MQNIC_RB_RX_QM_VER, 0); + + if (!interface->rx_queue_rb) + { + fprintf(stderr, "Error: RX queue block not found\n"); + goto fail; + } + + interface->rx_queue_offset = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_OFFSET); + interface->rx_queue_count = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_COUNT); + interface->rx_queue_stride = mqnic_reg_read32(interface->rx_queue_rb->regs, MQNIC_RB_RX_QM_REG_STRIDE); + if (interface->rx_queue_count > MQNIC_MAX_RX_RINGS) interface->rx_queue_count = MQNIC_MAX_RX_RINGS; + + interface->rx_cpl_queue_rb = find_reg_block(interface->rb_list, MQNIC_RB_RX_CQM_TYPE, MQNIC_RB_RX_CQM_VER, 0); + + if (!interface->rx_cpl_queue_rb) + { + fprintf(stderr, "Error: RX completion queue block not found\n"); + goto fail; + } + + interface->rx_cpl_queue_offset = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_OFFSET); + interface->rx_cpl_queue_count = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_COUNT); + interface->rx_cpl_queue_stride = mqnic_reg_read32(interface->rx_cpl_queue_rb->regs, MQNIC_RB_RX_CQM_REG_STRIDE); + if (interface->rx_cpl_queue_count > MQNIC_MAX_RX_CPL_RINGS) interface->rx_cpl_queue_count = MQNIC_MAX_RX_CPL_RINGS; - if (interface->port_count > MQNIC_MAX_PORTS) - interface->port_count = MQNIC_MAX_PORTS; - - for (int k = 0; k < interface->port_count; k++) + interface->port_count = 0; + while (interface->port_count < MQNIC_MAX_PORTS) { - struct mqnic_port *port = mqnic_port_open(interface, k, interface->regs + interface->port_offset + k*interface->port_stride); + struct reg_block *sched_block_rb = find_reg_block(interface->rb_list, MQNIC_RB_SCHED_BLOCK_TYPE, MQNIC_RB_SCHED_BLOCK_VER, interface->port_count); + struct mqnic_port *port; + + if (!sched_block_rb) + break; + + port = mqnic_port_open(interface, interface->port_count, sched_block_rb); if (!port) goto fail; - interface->ports[k] = port; + interface->ports[interface->port_count++] = port; } return interface; @@ -270,49 +389,46 @@ void mqnic_if_close(struct mqnic_if *interface) interface->ports[k] = NULL; } + if (interface->rb_list) + free_reg_block_list(interface->rb_list); + free(interface); } -struct mqnic_port *mqnic_port_open(struct mqnic_if *interface, int index, volatile uint8_t *regs) +struct mqnic_port *mqnic_port_open(struct mqnic_if *interface, int index, struct reg_block *block_rb) { struct mqnic_port *port = calloc(1, sizeof(struct mqnic_port)); if (!port) return NULL; + int offset = mqnic_reg_read32(block_rb->regs, MQNIC_RB_SCHED_BLOCK_REG_OFFSET); + port->mqnic = interface->mqnic; port->interface = interface; port->index = index; - port->regs_size = interface->port_stride; - port->regs = regs; + port->rb_list = enumerate_reg_block_list(interface->regs, offset, interface->regs_size); - if (port->regs >= interface->regs+interface->regs_size) + if (!port->rb_list) { - fprintf(stderr, "Error: computed pointer out of range\n"); + fprintf(stderr, "Error: filed to enumerate blocks\n"); goto fail; } - port->port_id = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_PORT_ID); - port->port_features = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_PORT_FEATURES); - port->port_mtu = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_PORT_MTU); - - port->sched_count = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_SCHED_COUNT); - port->sched_offset = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_SCHED_OFFSET); - port->sched_stride = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_SCHED_STRIDE); - port->sched_type = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_SCHED_TYPE); - - port->tdma_timeslot_count = mqnic_reg_read32(port->regs, MQNIC_PORT_REG_TDMA_TIMESLOT_COUNT); - - for (int k = 0; k < port->sched_count; k++) + port->sched_count = 0; + for (struct reg_block *rb = port->rb_list; rb->type && rb->version; rb++) { - struct mqnic_sched *sched = mqnic_sched_open(port, k, port->regs + port->sched_offset + k*port->sched_stride); + if (rb->type == MQNIC_RB_SCHED_RR_TYPE && rb->version == MQNIC_RB_SCHED_RR_VER) + { + struct mqnic_sched *sched = mqnic_sched_open(port, port->sched_count, rb); - if (!sched) - goto fail; + if (!sched) + goto fail; - port->sched[k] = sched; + port->sched[port->sched_count++] = sched; + } } return port; @@ -336,10 +452,13 @@ void mqnic_port_close(struct mqnic_port *port) port->sched[k] = NULL; } + if (port->rb_list) + free_reg_block_list(port->rb_list); + free(port); } -struct mqnic_sched *mqnic_sched_open(struct mqnic_port *port, int index, volatile uint8_t *regs) +struct mqnic_sched *mqnic_sched_open(struct mqnic_port *port, int index, struct reg_block *rb) { struct mqnic_sched *sched = calloc(1, sizeof(struct mqnic_sched)); @@ -352,8 +471,8 @@ struct mqnic_sched *mqnic_sched_open(struct mqnic_port *port, int index, volatil sched->index = index; - sched->regs_size = port->sched_stride; - sched->regs = regs; + sched->rb = rb; + sched->regs = rb->base + mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_OFFSET); if (sched->regs >= port->interface->regs+port->interface->regs_size) { @@ -361,6 +480,11 @@ struct mqnic_sched *mqnic_sched_open(struct mqnic_port *port, int index, volatil goto fail; } + sched->type = rb->type; + sched->offset = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_OFFSET); + sched->channel_count = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_COUNT); + sched->channel_stride = mqnic_reg_read32(rb->regs, MQNIC_RB_SCHED_RR_REG_CH_STRIDE); + return sched; fail: diff --git a/utils/mqnic.h b/utils/mqnic.h index bf3da251d..03d0b6dd0 100644 --- a/utils/mqnic.h +++ b/utils/mqnic.h @@ -39,6 +39,7 @@ either expressed or implied, of The Regents of the University of California. #include "mqnic_hw.h" #include "mqnic_ioctl.h" +#include "reg_block.h" #define mqnic_reg_read32(base, reg) (((volatile uint32_t *)(base))[(reg)/4]) #define mqnic_reg_write32(base, reg, val) (((volatile uint32_t *)(base))[(reg)/4]) = val @@ -52,6 +53,13 @@ struct mqnic_sched { int index; + struct reg_block *rb; + + uint32_t type; + uint32_t offset; + uint32_t channel_count; + uint32_t channel_stride; + size_t regs_size; volatile uint8_t *regs; }; @@ -65,17 +73,9 @@ struct mqnic_port { size_t regs_size; volatile uint8_t *regs; - uint32_t port_id; - uint32_t port_features; - uint32_t port_mtu; + struct reg_block *rb_list; uint32_t sched_count; - uint32_t sched_offset; - uint32_t sched_stride; - uint32_t sched_type; - - uint32_t tdma_timeslot_count; - struct mqnic_sched *sched[MQNIC_MAX_SCHED]; }; @@ -88,24 +88,39 @@ struct mqnic_if { volatile uint8_t *regs; volatile uint8_t *csr_regs; - uint32_t if_id; - uint32_t if_features; + struct reg_block *rb_list; + struct reg_block *if_ctrl_tx_rb; + struct reg_block *if_ctrl_rx_rb; + struct reg_block *event_queue_rb; + struct reg_block *tx_queue_rb; + struct reg_block *tx_cpl_queue_rb; + struct reg_block *rx_queue_rb; + struct reg_block *rx_cpl_queue_rb; + + uint32_t if_tx_features; + uint32_t if_rx_features; + + uint32_t max_tx_mtu; + uint32_t max_rx_mtu; - uint32_t event_queue_count; uint32_t event_queue_offset; - uint32_t tx_queue_count; + uint32_t event_queue_count; + uint32_t event_queue_stride; + uint32_t tx_queue_offset; - uint32_t tx_cpl_queue_count; + uint32_t tx_queue_count; + uint32_t tx_queue_stride; uint32_t tx_cpl_queue_offset; - uint32_t rx_queue_count; + uint32_t tx_cpl_queue_count; + uint32_t tx_cpl_queue_stride; uint32_t rx_queue_offset; - uint32_t rx_cpl_queue_count; + uint32_t rx_queue_count; + uint32_t rx_queue_stride; uint32_t rx_cpl_queue_offset; + uint32_t rx_cpl_queue_count; + uint32_t rx_cpl_queue_stride; uint32_t port_count; - uint32_t port_offset; - uint32_t port_stride; - struct mqnic_port *ports[MQNIC_MAX_PORTS]; }; @@ -114,21 +129,28 @@ struct mqnic { size_t regs_size; volatile uint8_t *regs; - volatile uint8_t *phc_regs; + struct reg_block *rb_list; + struct reg_block *fw_id_rb; + struct reg_block *if_rb; + struct reg_block *phc_rb; + + uint32_t fpga_id; uint32_t fw_id; uint32_t fw_ver; uint32_t board_id; uint32_t board_ver; + uint32_t build_date; + uint32_t git_hash; + uint32_t rel_info; - uint32_t phc_count; - uint32_t phc_offset; - uint32_t phc_stride; - + uint32_t if_offset; uint32_t if_count; uint32_t if_stride; uint32_t if_csr_offset; + char build_date_str[32]; + struct mqnic_if *interfaces[MQNIC_MAX_IF]; }; @@ -138,10 +160,10 @@ void mqnic_close(struct mqnic *dev); struct mqnic_if *mqnic_if_open(struct mqnic *dev, int index, volatile uint8_t *regs); void mqnic_if_close(struct mqnic_if *interface); -struct mqnic_port *mqnic_port_open(struct mqnic_if *interface, int index, volatile uint8_t *regs); +struct mqnic_port *mqnic_port_open(struct mqnic_if *interface, int index, struct reg_block *block_rb); void mqnic_port_close(struct mqnic_port *port); -struct mqnic_sched *mqnic_sched_open(struct mqnic_port *port, int index, volatile uint8_t *regs); +struct mqnic_sched *mqnic_sched_open(struct mqnic_port *port, int index, struct reg_block *rb); void mqnic_sched_close(struct mqnic_sched *sched); #endif /* MQNIC_H */ diff --git a/utils/reg_block.c b/utils/reg_block.c new file mode 100644 index 000000000..9db667432 --- /dev/null +++ b/utils/reg_block.c @@ -0,0 +1,131 @@ +/* + +Copyright 2021, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +#include "reg_block.h" + +#include "mqnic.h" + +#include +#include + +struct reg_block *enumerate_reg_block_list(volatile uint8_t *base, size_t offset, size_t size) +{ + int max_count = 8; + struct reg_block *reg_block_list = calloc(max_count, sizeof(struct reg_block)); + int count = 0; + + volatile uint8_t *ptr; + + uint32_t rb_type; + uint32_t rb_version; + + if (!reg_block_list) + return NULL; + + while (1) + { + reg_block_list[count].type = 0; + reg_block_list[count].version = 0; + reg_block_list[count].base = 0; + reg_block_list[count].regs = 0; + + if ((offset == 0 && count != 0) || offset >= size) + break; + + ptr = base + offset; + + for (int k = 0; k < count; k++) + { + if (ptr == reg_block_list[k].regs) + { + fprintf(stderr, "Register blocks form a loop\n"); + goto fail; + } + } + + rb_type = *((uint32_t *)(ptr + MQNIC_RB_REG_TYPE)); + rb_version = *((uint32_t *)(ptr + MQNIC_RB_REG_VER)); + offset = *((uint32_t *)(ptr + MQNIC_RB_REG_NEXT_PTR)); + + reg_block_list[count].type = rb_type; + reg_block_list[count].version = rb_version; + reg_block_list[count].base = base; + reg_block_list[count].regs = ptr; + + count++; + + if (count >= max_count) + { + struct reg_block *tmp; + max_count += 4; + tmp = realloc(reg_block_list, max_count * sizeof(struct reg_block)); + if (!tmp) + goto fail; + reg_block_list = tmp; + } + } + + return reg_block_list; +fail: + free(reg_block_list); + return NULL; +} + +struct reg_block *find_reg_block(struct reg_block *list, uint32_t type, uint32_t version, int index) +{ + struct reg_block *rb = list; + + while (rb->type && rb->version && rb->regs) + { + if (rb->type == type && (!version || rb->version == version)) + { + if (index > 0) + { + index--; + } + else + { + return rb; + } + } + + rb++; + } + + return NULL; +} + +void free_reg_block_list(struct reg_block *list) +{ + free(list); +} diff --git a/utils/reg_block.h b/utils/reg_block.h new file mode 100644 index 000000000..f317b3819 --- /dev/null +++ b/utils/reg_block.h @@ -0,0 +1,51 @@ +/* + +Copyright 2021, The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS OF THE UNIVERSITY OF CALIFORNIA ''AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OF THE UNIVERSITY OF CALIFORNIA OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of The Regents of the University of California. + +*/ + +#ifndef REG_BLOCK_H +#define REG_BLOCK_H + +#include +#include + +struct reg_block { + uint32_t type; + uint32_t version; + volatile uint8_t *base; + volatile uint8_t *regs; +}; + +struct reg_block *enumerate_reg_block_list(volatile uint8_t *base, size_t offset, size_t size); +struct reg_block *find_reg_block(struct reg_block *list, uint32_t type, uint32_t version, int index); +void free_reg_block_list(struct reg_block *list); + +#endif /* REG_BLOCK_H */