From cba8536a5f50862848901d26acb869405c2999cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20B=2E=20Preu=C3=9Fer?= <thomas.preusser@xilinx.com> Date: Mon, 10 Oct 2022 12:41:37 +0100 Subject: [PATCH] First prototype for dynamically sized FM padding. --- finn-rtllib/fmpadding/hdl/fmpadding_axi.sv | 203 ++++++++++++++++++ finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv | 125 +++++++++++ 2 files changed, 328 insertions(+) create mode 100644 finn-rtllib/fmpadding/hdl/fmpadding_axi.sv create mode 100644 finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv diff --git a/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv b/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv new file mode 100644 index 000000000..4af2598e3 --- /dev/null +++ b/finn-rtllib/fmpadding/hdl/fmpadding_axi.sv @@ -0,0 +1,203 @@ +/****************************************************************************** + * 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_axi #( + 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, + +/* + //- AXI Lite ------------------------ + // Writing + input s_axilite_AWVALID, + output s_axilite_AWREADY, + input [2: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 + 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, +*/ + + 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_axi diff --git a/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv b/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv new file mode 100644 index 000000000..ae2377f3d --- /dev/null +++ b/finn-rtllib/fmpadding/hdl/fmpadding_axi_tb.sv @@ -0,0 +1,125 @@ + +module fmpadding_axi_tb #( + int unsigned XCOUNTER_BITS = 8, + int unsigned YCOUNTER_BITS = 8, + int unsigned NUM_CHANNELS = 4, + int unsigned SIMD = 2, + int unsigned ELEM_BITS = 4 +)(); + localparam int unsigned STREAM_BITS = 8*(1 + (SIMD*ELEM_BITS-1)/8); + + //- Global Control ------------------ + logic clk = 0; + always #5ns clk = !clk; + logic rst; + + // Parameter Configuration ---------- + logic we; + logic [ 2:0] wa; + logic [31:0] wd; + + //- AXI Stream - Input -------------- + uwire s_axis_tready; + logic s_axis_tvalid; + logic [STREAM_BITS-1:0] s_axis_tdata; + + //- AXI Stream - Output ------------- + logic m_axis_tready; + uwire m_axis_tvalid; + uwire [STREAM_BITS-1:0] m_axis_tdata; + + + // DUT + fmpadding_axi #( + .XCOUNTER_BITS(XCOUNTER_BITS), + .YCOUNTER_BITS(YCOUNTER_BITS), + .NUM_CHANNELS(NUM_CHANNELS), + .SIMD(SIMD), + .ELEM_BITS(ELEM_BITS) + ) dut ( + .ap_clk(clk), .ap_rst_n(!rst), + .we, .wa, .wd, + .s_axis_tready, .s_axis_tvalid, .s_axis_tdata, + .m_axis_tready, .m_axis_tvalid, .m_axis_tdata + ); + + // Stimuli + localparam int unsigned IMAGES = 2; + localparam int unsigned XSIZE = 10; + localparam int unsigned YSIZE = 7; + localparam int unsigned PAD_LEFT = 2; + localparam int unsigned PAD_RIGHT = 3; + localparam int unsigned PAD_TOP = 1; + localparam int unsigned PAD_BOTTOM = 2; + initial begin + we = 0; + wa = 'x; + wd = 'x; + + s_axis_tvalid = 0; + s_axis_tdata = 'x; + + // Configure Parameters + rst = 1; + @(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; + @(posedge clk); + rst <= 0; + + // Feed data input + s_axis_tvalid <= 1; + for(int unsigned i = 0; i < IMAGES * (XSIZE-PAD_LEFT-PAD_RIGHT) * (YSIZE-PAD_TOP-PAD_BOTTOM) * (NUM_CHANNELS/SIMD); i++) begin + s_axis_tdata <= i; + @(posedge clk iff s_axis_tready); + if($urandom()%5 == 0) begin + s_axis_tvalid <= 0; + s_axis_tdata <= 'x; + @(posedge clk); + s_axis_tvalid <= 1; + end + end + s_axis_tvalid <= 0; + s_axis_tdata <= 'x; + end + + // Ouput Throttler + initial begin + m_axis_tready = 0; + @(posedge clk iff !rst); + m_axis_tready <= 1; + forever @(posedge clk iff m_axis_tvalid) begin + m_axis_tready <= 0; + repeat(4-$clog2(1+$urandom()%15)) @(posedge clk); + m_axis_tready <= 1; + end + end + + // Output logger + initial begin + repeat(IMAGES) begin + for(int unsigned y = 0; y < YSIZE; y++) begin + for(int unsigned x = 0; x < XSIZE; x++) begin + automatic string delim = " "; + for(int unsigned s = 0; s < NUM_CHANNELS/SIMD; s++) begin + @(posedge clk iff m_axis_tvalid && m_axis_tready); + $write("%s%02X", delim, m_axis_tdata); + delim = ":"; + end + end + $display(); + end + $display("----"); + end + $finish; + end + +endmodule : fmpadding_axi_tb -- GitLab