From 232464c7f7d8265c9df987916471cc989d5c2fe9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20B=2E=20Preu=C3=9Fer?= <thomas.preusser@xilinx.com> Date: Wed, 4 May 2022 17:02:47 +0100 Subject: [PATCH] Prototype for checksumming over stream data. --- finn-rtllib/checksum/checksum.cpp | 51 +++++++++++ finn-rtllib/checksum/checksum.hpp | 114 +++++++++++++++++++++++ finn-rtllib/checksum/checksum_tb.sv | 136 ++++++++++++++++++++++++++++ 3 files changed, 301 insertions(+) create mode 100644 finn-rtllib/checksum/checksum.cpp create mode 100644 finn-rtllib/checksum/checksum.hpp create mode 100644 finn-rtllib/checksum/checksum_tb.sv diff --git a/finn-rtllib/checksum/checksum.cpp b/finn-rtllib/checksum/checksum.cpp new file mode 100644 index 000000000..494adee85 --- /dev/null +++ b/finn-rtllib/checksum/checksum.cpp @@ -0,0 +1,51 @@ +/****************************************************************************** + * Copyright (c) 2022, Xilinx, 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 Validation top-level module for checksum component. + * @author Thomas B. Preußer <tpreusse@amd.com> + * + *******************************************************************************/ +#include "checksum.hpp" + + +using T = ap_uint<32>; + +void checksum_top( + hls::stream<T> &src, + hls::stream<T> &dst, + ap_uint<32> &chk +) { +#pragma HLS interface port=src axis +#pragma HLS interface port=dst axis +#pragma HLS interface port=chk ap_ovld +#pragma HLS interface port=return ap_ctrl_none +#pragma HLS dataflow + checksum<60, 4>(src, dst, chk); +} diff --git a/finn-rtllib/checksum/checksum.hpp b/finn-rtllib/checksum/checksum.hpp new file mode 100644 index 000000000..ed45b5d57 --- /dev/null +++ b/finn-rtllib/checksum/checksum.hpp @@ -0,0 +1,114 @@ +/****************************************************************************** + * Copyright (c) 2022, Xilinx, 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 Checksum over stream-carried data frames. + * @author Thomas B. Preußer <tpreusse@amd.com> + * + *******************************************************************************/ +#include <hls_stream.h> +#include <ap_int.h> + + +/** + * Computes a checksum over a forwarded stream assumed to carry frames of + * N words further subdivided into K subwords. + * - Subword slicing can be customized typically by using a lambda. + * The provided DefaultSubwordSlicer assumes an `ap_(u)int`-like word + * type with a member `width` and a range-based slicing operator. It + * further assumes a little-endian arrangement of subwords within words + * for the canonical subword stream order. + * - Subwords wider than 23 bits are folded using bitwise XOR across + * slices of 23 bits starting from the LSB. + * - The folded subword values are weighted according to their position + * in the stream relative to the start of frame by a periodic weight + * sequence 1, 2, 3, ... + * - The weighted folded subword values are reduced to a checksum by an + * accumulation module 2^24. + * - A checksum is emitted for each completed frame. It is the concatenation + * of an 8-bit (modulo 256) frame counter and the 24-bit frame checksum. + */ +template<typename T, unsigned K> class DefaultSubwordSlicer { + static_assert(T::width%K == 0, "Word size must be subword multiple."); + static constexpr unsigned W = T::width/K; +public: + ap_uint<W> operator()(T const &x, unsigned const j) const { +#pragma HLS inline + return x((j+1)*W-1, j*W); + } +}; + +template< + unsigned N, // number of data words in a frame + unsigned K, // subword count per data word + typename T, // type of stream-carried data words + typename F = DefaultSubwordSlicer<T, K> // f(T(), j) to extract subwords +> +void checksum( + hls::stream<T> &src, + hls::stream<T> &dst, + ap_uint<32> &chk, + F&& f = F() +) { + ap_uint<2> coeff[3] = { 1, 2, 3 }; + ap_uint<24> s = 0; + + for(unsigned i = 0; i < N; i++) { +#pragma HLS pipeline II=1 style=flp + T const x = src.read(); + + // Pass-thru copy + dst.write(x); + + // Actual checksum update + for(unsigned j = 0; j < K; j++) { +#pragma HLS unroll + auto const v0 = f(x, j); + constexpr unsigned W = 1 + (decltype(v0)::width-1)/23; + ap_uint<K*23> v = v0; + ap_uint< 23> w = 0; + for(unsigned k = 0; k < W; k++) { + w ^= v(23*k+22, 23*k); + } + s += (coeff[j%3][1]? (w, ap_uint<1>(0)) : ap_uint<24>(0)) + (coeff[j%3][0]? w : ap_uint<23>(0)); + } + + // Re-align coefficients + for(unsigned j = 0; j < 3; j++) { +#pragma HLS unroll + ap_uint<3> const cc = coeff[j] + ap_uint<3>(K%3); + coeff[j] = cc(1, 0) + cc[2]; + } + } + + // Frame counter & output + static ap_uint<8> cnt = 0; +#pragma HLS reset variable=cnt + chk = (cnt++, s); +} diff --git a/finn-rtllib/checksum/checksum_tb.sv b/finn-rtllib/checksum/checksum_tb.sv new file mode 100644 index 000000000..cec4e1b5b --- /dev/null +++ b/finn-rtllib/checksum/checksum_tb.sv @@ -0,0 +1,136 @@ +/****************************************************************************** + * Copyright (c) 2022, Xilinx, 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 Testbench for checksum component. + * @author Thomas B. Preußer <tpreusse@amd.com> + * + *******************************************************************************/ +module checksum_tb; + + //----------------------------------------------------------------------- + // Global Control + logic clk = 0; + always #5ns clk = !clk; + logic rst; + + //----------------------------------------------------------------------- + // DUT + localparam int unsigned N = 60; // words per frame + localparam int unsigned K = 4; // subwords per word + localparam int unsigned W = 8; // subword size + + logic [K-1:0][W-1:0] src_TDATA; + logic src_TVALID; + uwire src_TREADY; + + uwire [K-1:0][W-1:0] dst_TDATA; + uwire dst_TVALID; + logic dst_TREADY; + + uwire [31:0] chk; + uwire chk_vld; + + checksum_top dut ( + .ap_clk(clk), .ap_rst_n(!rst), + .src_TDATA, .src_TVALID, .src_TREADY, + .dst_TDATA, .dst_TVALID, .dst_TREADY, + .chk, .chk_ap_vld(chk_vld), + .ap_local_block(), .ap_local_deadlock() + ); + + //----------------------------------------------------------------------- + // Stimulus + logic [K-1:0][W-1:0] Bypass [$] = {}; + logic [31:0] Checksum[$] = {}; + initial begin + src_TDATA = 'x; + src_TVALID = 0; + + rst = 1; + repeat(9) @(posedge clk); + rst <= 0; + + for(int unsigned r = 0; r < 311; r++) begin + automatic logic [23:0] sum = 0; + src_TVALID <= 1; + for(int unsigned i = 0; i < N; i++) begin + for(int unsigned k = 0; k < K; k++) begin + automatic logic [W-1:0] v = $urandom()>>17; + src_TDATA[k] <= v; + sum += ((K*i+k)%3 + 1) * v; + end + @(posedge clk iff src_TREADY); + Bypass.push_back(src_TDATA); + end + src_TVALID <= 0; + $display("Expect: %02x:%06x", r[7:0], sum); + Checksum.push_back({r, sum}); + end + + repeat(8) @(posedge clk); + $finish; + end + + //----------------------------------------------------------------------- + // Output Validation + + // Drain and check pass-thru stream + assign dst_TREADY = 1; + always_ff @(posedge clk iff dst_TVALID) begin + assert(Bypass.size()) begin + automatic logic [K-1:0][W-1:0] exp = Bypass.pop_front(); + assert(dst_TDATA === exp) else begin + $error("Unexpected output %0x instead of %0x.", dst_TDATA, exp); + $stop; + end + end + else begin + $error("Spurious data output."); + $stop; + end + end + + // Validate checksum reports + always_ff @(posedge clk iff chk_vld) begin + $display("Check: %02x:%06x", chk[31:24], chk[23:0]); + assert(Checksum.size()) begin + automatic logic [31:0] exp = Checksum.pop_front(); + assert(chk === exp) else begin + $error("Unexpected checksum %0x instead of %0x.", chk, exp); + $stop; + end + end + else begin + $error("Spurious checksum output."); + $stop; + end + end + +endmodule : checksum_tb -- GitLab