From 03ccfb5ec314813701702b444927f308ee929783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20B=2E=20Preu=C3=9Fer?= <thomas.preusser@xilinx.com> Date: Tue, 11 Oct 2022 15:17:34 +0100 Subject: [PATCH] Added AXI-Light adapter to dynamically-sized feature map padding. --- finn-rtllib/fmpadding/hdl/axi2we.sv | 122 ++++++++++++ finn-rtllib/fmpadding/hdl/fmpadding.sv | 177 ++++++++++++++++++ finn-rtllib/fmpadding/hdl/fmpadding_axi.sv | 149 +++------------ finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv | 67 +++++-- 4 files changed, 376 insertions(+), 139 deletions(-) create mode 100644 finn-rtllib/fmpadding/hdl/axi2we.sv create mode 100644 finn-rtllib/fmpadding/hdl/fmpadding.sv diff --git a/finn-rtllib/fmpadding/hdl/axi2we.sv b/finn-rtllib/fmpadding/hdl/axi2we.sv new file mode 100644 index 000000000..0740eac5f --- /dev/null +++ b/finn-rtllib/fmpadding/hdl/axi2we.sv @@ -0,0 +1,122 @@ +/****************************************************************************** + * Copyright (C) 2022, Advanced Micro Devices, Inc. + * 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. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 HOLDER 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. + * + * @brief AXI-Light adapter for trivial write enable interface. + * @author Thomas B. Preußer <tpreusse@amd.com> + *****************************************************************************/ + +module axi2we #( + int unsigned ADDR_BITS +)( + //- Global Control ------------------ + input logic ap_clk, + input logic ap_rst_n, + + //- AXI Lite ------------------------ + // Writing + input s_axilite_AWVALID, + output s_axilite_AWREADY, + input [ADDR_BITS-1:0] s_axilite_AWADDR, + + input s_axilite_WVALID, + output s_axilite_WREADY, + input [31:0] s_axilite_WDATA, + input [ 3:0] s_axilite_WSTRB, + + output s_axilite_BVALID, + input s_axilite_BREADY, + output [1:0] s_axilite_BRESP, + + // Reading tied to all-ones + input s_axilite_ARVALID, + output s_axilite_ARREADY, + input [3:0] s_axilite_ARADDR, + + output s_axilite_RVALID, + input s_axilite_RREADY, + output [31:0] s_axilite_RDATA, + output [ 1:0] s_axilite_RRESP, + + // Write Enable Interface + output logic we, + output logic [ADDR_BITS-1:0] wa, + output logic [ 31:0] wd +); + + uwire clk = ap_clk; + uwire rst = !ap_rst_n; + + + logic WABusy = 0; + logic WDBusy = 0; + logic [ADDR_BITS-1:0] Addr = 'x; + logic [ 31:0] Data = 'x; + + assign we = WABusy && WDBusy && s_axilite_BREADY; + assign wa = Addr; + assign wd = Data; + + uwire clr_wr = rst || we; + always_ff @(posedge clk) begin + if(clr_wr) begin + WABusy <= 0; + Addr <= 'x; + WDBusy <= 0; + Data <= 'x; + end + else begin + if(!WABusy) begin + WABusy <= s_axilite_AWVALID; + Addr <= s_axilite_AWADDR; + end + if(!WDBusy) begin + WDBusy <= s_axilite_WVALID; + Data <= s_axilite_WDATA; + end + end + end + assign s_axilite_AWREADY = !WABusy; + assign s_axilite_WREADY = !WDBusy; + assign s_axilite_BVALID = WABusy && WDBusy; + assign s_axilite_BRESP = '0; // OK + + // Answer all reads with '1 + logic RValid = 0; + uwire clr_rd = rst || (RValid && s_axilite_RREADY); + always_ff @(posedge clk) begin + if(clr_rd) RValid <= 0; + else if(!RValid) RValid <= s_axilite_ARVALID; + end + assign s_axilite_ARREADY = !RValid; + assign s_axilite_RVALID = RValid; + assign s_axilite_RDATA = '1; + assign s_axilite_RRESP = '0; // OK + +endmodule : axi2we diff --git a/finn-rtllib/fmpadding/hdl/fmpadding.sv b/finn-rtllib/fmpadding/hdl/fmpadding.sv new file mode 100644 index 000000000..7e408f624 --- /dev/null +++ b/finn-rtllib/fmpadding/hdl/fmpadding.sv @@ -0,0 +1,177 @@ +/****************************************************************************** + * Copyright (C) 2022, Advanced Micro Devices, Inc. + * 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. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * 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 HOLDER 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. + * + * @brief Feature map padding. + * @author Thomas B. Preußer <tpreusse@amd.com> + *****************************************************************************/ + +module fmpadding #( + int unsigned XCOUNTER_BITS, + int unsigned YCOUNTER_BITS, + int unsigned NUM_CHANNELS, + int unsigned SIMD, + int unsigned ELEM_BITS, + localparam int unsigned STREAM_BITS = 8*(1 + (SIMD*ELEM_BITS-1)/8) +)( + //- Global Control ------------------ + input logic ap_clk, + input logic ap_rst_n, + + // Parameter Configuration ---------- + input logic we, + input logic [ 2:0] wa, + input logic [31:0] wd, + + //- AXI Stream - Input -------------- + output logic s_axis_tready, + input logic s_axis_tvalid, + input logic [STREAM_BITS-1:0] s_axis_tdata, + + //- AXI Stream - Output ------------- + input logic m_axis_tready, + output logic m_axis_tvalid, + output logic [STREAM_BITS-1:0] m_axis_tdata +); + + uwire clk = ap_clk; + uwire rst = !ap_rst_n; + + //----------------------------------------------------------------------- + // Dynamically configurable state + typedef logic [XCOUNTER_BITS-1:0] xcount_t; + xcount_t XEnd = 0; + xcount_t XOn = 0; + xcount_t XOff = 0; + + typedef logic [YCOUNTER_BITS-1:0] ycount_t; + ycount_t YEnd = 0; + ycount_t YOn = 0; + ycount_t YOff = 0; + always_ff @(posedge clk) begin + if(we) begin + unique case(wa) + 0: XOn <= wd; + 1: XOff <= wd; + 2: XEnd <= wd; + + 4: YOn <= wd; + 5: YOff <= wd; + 6: YEnd <= wd; + + default: assert(0) else begin + $error("Illegal write address."); + $stop; + end + endcase + end + end + + //----------------------------------------------------------------------- + // Cascaded enables for the nested counters: SCount, XCount, YCount + uwire sen; + uwire xen; + uwire yen; + + //- S-Counter: SIMD fold ------------ + initial begin + if((NUM_CHANNELS < 1) || (NUM_CHANNELS % SIMD != 0)) begin + $error("Channel count must be SIMD multiple."); + $finish; + end + end + // Count SF-2, SF-3, ..., 1, 0, -1 + localparam int unsigned SF = NUM_CHANNELS/SIMD; + typedef logic [$clog2(SF-1):0] scount_t; + scount_t SCount = SF-2; + + assign xen = sen && SCount[$left(SCount)]; + uwire sclr = rst || xen; + always_ff @(posedge clk) begin + if(sclr) SCount <= SF-2; + else if(sen) SCount <= SCount - 1; + end + + //- X-Counter: image width ---------- + xcount_t XCount = 0; + + assign yen = xen && (XCount == XEnd); + uwire xclr = rst || yen; + always_ff @(posedge clk) begin + if(xclr) XCount <= 0; + else if(xen) XCount <= XCount + 1; + end + uwire xfwd = (XOn <= XCount) && (XCount < XOff); + + //- Y-Counter: image height --------- + ycount_t YCount = 0; + + uwire yclr = rst || (yen && (YCount == YEnd)); + always_ff @(posedge clk) begin + if(yclr) YCount <= 0; + else if(yen) YCount <= YCount + 1; + end + uwire yfwd = (YOn <= YCount) && (YCount < YOff); + + //----------------------------------------------------------------------- + // Input forwarding and edge padding + typedef struct { + logic vld; + logic [STREAM_BITS-1:0] dat; + } buf_t; + buf_t A = '{ vld: 0, dat: 'x }; + buf_t B = '{ vld: 0, dat: 'x }; + + uwire fwd = xfwd && yfwd; + assign sen = (m_axis_tready || !B.vld) && (s_axis_tvalid || A.vld || !fwd); + assign s_axis_tready = !A.vld; + assign m_axis_tvalid = B.vld; + assign m_axis_tdata = B.dat; + + always_ff @(posedge clk) begin + if(rst) begin + B <= '{ vld: 0, dat: 'x }; + end + else if(m_axis_tready || !B.vld) begin + B.vld <= s_axis_tvalid || A.vld || !fwd; + B.dat <= !fwd? '0 : A.vld? A.dat : s_axis_tdata; + end + end + + always_ff @(posedge clk) begin + if(rst) begin + A <= '{ vld: 0, dat: 'x }; + end + else begin + A.vld <= (A.vld || s_axis_tvalid) && ((B.vld && !m_axis_tready) || !fwd); + if(!A.vld) A.dat <= s_axis_tdata; + end + end + +endmodule : fmpadding diff --git a/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv b/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv index 4af2598e3..f5313801e 100644 --- a/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv +++ b/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv @@ -44,7 +44,6 @@ module fmpadding_axi #( input logic ap_clk, input logic ap_rst_n, -/* //- AXI Lite ------------------------ // Writing input s_axilite_AWVALID, @@ -69,11 +68,6 @@ module fmpadding_axi #( input s_axilite_RREADY, output [31:0] s_axilite_RDATA, output [ 1:0] s_axilite_RRESP, -*/ - - input logic we, - input logic [ 2:0] wa, - input logic [31:0] wd, //- AXI Stream - Input -------------- output logic s_axis_tready, @@ -86,118 +80,35 @@ module fmpadding_axi #( output logic [STREAM_BITS-1:0] m_axis_tdata ); - uwire clk = ap_clk; - uwire rst = !ap_rst_n; - - //----------------------------------------------------------------------- - // Dynamically configurable state - typedef logic [XCOUNTER_BITS-1:0] xcount_t; - xcount_t XEnd = 0; - xcount_t XOn = 0; - xcount_t XOff = 0; - - typedef logic [YCOUNTER_BITS-1:0] ycount_t; - ycount_t YEnd = 0; - ycount_t YOn = 0; - ycount_t YOff = 0; - always_ff @(posedge clk) begin - if(we) begin - unique case(wa) - 0: XOn <= wd; - 1: XOff <= wd; - 2: XEnd <= wd; - - 4: YOn <= wd; - 5: YOff <= wd; - 6: YEnd <= wd; - - default: assert(0) else begin - $error("Illegal write address."); - $stop; - end - endcase - end - end - - //----------------------------------------------------------------------- - // Cascaded enables for the nested counters: SCount, XCount, YCount - uwire sen; - uwire xen; - uwire yen; - - //- S-Counter: SIMD fold ------------ - initial begin - if((NUM_CHANNELS < 1) || (NUM_CHANNELS % SIMD != 0)) begin - $error("Channel count must be SIMD multiple."); - $finish; - end - end - // Count SF-2, SF-3, ..., 1, 0, -1 - localparam int unsigned SF = NUM_CHANNELS/SIMD; - typedef logic [$clog2(SF-1):0] scount_t; - scount_t SCount = SF-2; - - assign xen = sen && SCount[$left(SCount)]; - uwire sclr = rst || xen; - always_ff @(posedge clk) begin - if(sclr) SCount <= SF-2; - else if(sen) SCount <= SCount - 1; - end - - //- X-Counter: image width ---------- - xcount_t XCount = 0; - - assign yen = xen && (XCount == XEnd); - uwire xclr = rst || yen; - always_ff @(posedge clk) begin - if(xclr) XCount <= 0; - else if(xen) XCount <= XCount + 1; - end - uwire xfwd = (XOn <= XCount) && (XCount < XOff); - - //- Y-Counter: image height --------- - ycount_t YCount = 0; - - uwire yclr = rst || (yen && (YCount == YEnd)); - always_ff @(posedge clk) begin - if(yclr) YCount <= 0; - else if(yen) YCount <= YCount + 1; - end - uwire yfwd = (YOn <= YCount) && (YCount < YOff); - - //----------------------------------------------------------------------- - // Input forwarding and edge padding - typedef struct { - logic vld; - logic [STREAM_BITS-1:0] dat; - } buf_t; - buf_t A = '{ vld: 0, dat: 'x }; - buf_t B = '{ vld: 0, dat: 'x }; - - uwire fwd = xfwd && yfwd; - assign sen = (m_axis_tready || !B.vld) && (s_axis_tvalid || A.vld || !fwd); - assign s_axis_tready = !A.vld; - assign m_axis_tvalid = B.vld; - assign m_axis_tdata = B.dat; - - always_ff @(posedge clk) begin - if(rst) begin - B <= '{ vld: 0, dat: 'x }; - end - else if(m_axis_tready || !B.vld) begin - B.vld <= s_axis_tvalid || A.vld || !fwd; - B.dat <= !fwd? '0 : A.vld? A.dat : s_axis_tdata; - end - end - - always_ff @(posedge clk) begin - if(rst) begin - A <= '{ vld: 0, dat: 'x }; - end - else begin - A.vld <= (A.vld || s_axis_tvalid) && ((B.vld && !m_axis_tready) || !fwd); - if(!A.vld) A.dat <= s_axis_tdata; - end - end + // AXI-Lite Adapter + uwire we; + uwire [ 2:0] wa; + uwire [31:0] wd; + axi2we #(.ADDR_BITS(3)) axilight_adapter ( + .ap_clk, .ap_rst_n, + + .s_axilite_AWVALID, .s_axilite_AWREADY, .s_axilite_AWADDR, + .s_axilite_WVALID, .s_axilite_WREADY, .s_axilite_WDATA, .s_axilite_WSTRB, + .s_axilite_BVALID, .s_axilite_BREADY, .s_axilite_BRESP, + + .s_axilite_ARVALID, .s_axilite_ARREADY, .s_axilite_ARADDR, + .s_axilite_RVALID, .s_axilite_RREADY, .s_axilite_RDATA, .s_axilite_RRESP, + + .we, .wa, .wd + ); + + // Actual Padding + fmpadding #( + .XCOUNTER_BITS(XCOUNTER_BITS), .YCOUNTER_BITS(YCOUNTER_BITS), + .NUM_CHANNELS(NUM_CHANNELS), .SIMD(SIMD), + .ELEM_BITS(ELEM_BITS) + ) padding ( + .ap_clk, .ap_rst_n, + + .we, .wa, .wd, + + .s_axis_tready, .s_axis_tvalid, .s_axis_tdata, + .m_axis_tready, .m_axis_tvalid, .m_axis_tdata + ); endmodule : fmpadding_axi diff --git a/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv b/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv index ae2377f3d..fedf5dcb6 100644 --- a/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv +++ b/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv @@ -13,10 +13,14 @@ module fmpadding_axi_tb #( always #5ns clk = !clk; logic rst; - // Parameter Configuration ---------- - logic we; - logic [ 2:0] wa; - logic [31:0] wd; + // AXI-Light for Parameter Configuration + logic s_axilite_AWVALID; + uwire s_axilite_AWREADY; + logic [2:0] s_axilite_AWADDR; + + logic s_axilite_WVALID; + uwire s_axilite_WREADY; + logic [31:0] s_axilite_WDATA; //- AXI Stream - Input -------------- uwire s_axis_tready; @@ -38,7 +42,13 @@ module fmpadding_axi_tb #( .ELEM_BITS(ELEM_BITS) ) dut ( .ap_clk(clk), .ap_rst_n(!rst), - .we, .wa, .wd, + + .s_axilite_AWVALID, .s_axilite_AWREADY, .s_axilite_AWADDR, + .s_axilite_WVALID, .s_axilite_WREADY, .s_axilite_WDATA, .s_axilite_WSTRB('1), + .s_axilite_BVALID(), .s_axilite_BREADY('1), .s_axilite_BRESP(), + .s_axilite_ARVALID('0), .s_axilite_ARREADY(), .s_axilite_ARADDR('x), + .s_axilite_RVALID(), .s_axilite_RREADY('0), .s_axilite_RDATA(), .s_axilite_RRESP(), + .s_axis_tready, .s_axis_tvalid, .s_axis_tdata, .m_axis_tready, .m_axis_tvalid, .m_axis_tdata ); @@ -51,29 +61,45 @@ module fmpadding_axi_tb #( localparam int unsigned PAD_RIGHT = 3; localparam int unsigned PAD_TOP = 1; localparam int unsigned PAD_BOTTOM = 2; + + task axi_write(input logic [2:0] wa, input logic [31:0] wd); + s_axilite_AWVALID <= 1; + s_axilite_AWADDR <= wa; + @(posedge clk iff s_axilite_AWREADY); + s_axilite_AWVALID <= 0; + s_axilite_AWADDR <= 'x; + + s_axilite_WVALID <= 1; + s_axilite_WDATA <= wd; + @(posedge clk iff s_axilite_WREADY); + s_axilite_WVALID <= 0; + s_axilite_WDATA <= 'x; + endtask : axi_write + + initial begin - we = 0; - wa = 'x; - wd = 'x; + s_axilite_AWVALID = 0; + s_axilite_AWADDR = 'x; + s_axilite_WVALID = 0; + s_axilite_WDATA = 'x; s_axis_tvalid = 0; s_axis_tdata = 'x; // Configure Parameters - rst = 1; + rst = 0; @(posedge clk); - we <= 1; - /* XOn */ wa <= 0; wd <= PAD_LEFT; @(posedge clk); - /* XOff */ wa <= 1; wd <= XSIZE - PAD_RIGHT; @(posedge clk); - /* XEnd */ wa <= 2; wd <= XSIZE - 1; @(posedge clk); - /* YOn */ wa <= 4; wd <= PAD_TOP; @(posedge clk); - /* YOff */ wa <= 5; wd <= YSIZE - PAD_BOTTOM; @(posedge clk); - /* YEnd */ wa <= 6; wd <= YSIZE - 1; @(posedge clk); - we <= 0; - wa <= 'x; - wd <= 'x; + /* XOn */ axi_write(0, PAD_LEFT); + /* XOff */ axi_write(1, XSIZE - PAD_RIGHT); + /* XEnd */ axi_write(2, XSIZE - 1); + /* YOn */ axi_write(4, PAD_TOP); + /* YOff */ axi_write(5, YSIZE - PAD_BOTTOM); + /* YEnd */ axi_write(6, YSIZE - 1); + @(posedge clk); + rst <= 1; @(posedge clk); rst <= 0; + @(posedge clk); // Feed data input s_axis_tvalid <= 1; @@ -91,7 +117,7 @@ module fmpadding_axi_tb #( s_axis_tdata <= 'x; end - // Ouput Throttler + // Output Throttler initial begin m_axis_tready = 0; @(posedge clk iff !rst); @@ -105,6 +131,7 @@ module fmpadding_axi_tb #( // Output logger initial begin + @(negedge rst); repeat(IMAGES) begin for(int unsigned y = 0; y < YSIZE; y++) begin for(int unsigned x = 0; x < XSIZE; x++) begin -- GitLab