diff --git a/streamtools.h b/streamtools.h index bb6118c..52c12d4 100644 --- a/streamtools.h +++ b/streamtools.h @@ -571,6 +571,71 @@ void StreamingDataWidthConverter_Batch(hls::stream > & in, } } +/** + * \brief Stream Data Width Converter - Converts the width of the input stream in the output stream + * + * Used to upscale or downscale a stream, without any loss of data in the procedure. + * For downscaling (InWidth > OutWidth), InWidth has to be a multiple of OutWidth. + * For upscaling (InWidth < OutWidth), OutWidth has to be a multiple of InWidth. + * + * \tparam InWidth Width, in number of bits, of the input stream + * \tparam OutWidth Width, in number of bits, of the output stream + * \tparam NumInWords Number of input words to process + * + * \param in Input stream + * \param out Output stream + * \param numReps Number of times the function has to be called + * + */ +template +void StreamingDataWidthConverter_ParallelWindow_Batch(hls::stream > & in, + hls::stream > & out, const unsigned int numReps) { + static_assert(InWidth > OutWidth, ""); + static_assert(InWidth % OutWidth == 0, ""); + + // emit multiple output words per input word read + const unsigned int totalIters = NumInWords * numReps * NF * SF; + unsigned int o = 0; + unsigned int sf = 0; + unsigned int nf = 0; + // Resource pragma for ei (256*9*8 =) 18kb (for larger layers) + ap_uint ei = 0; + for (unsigned int t = 0; t < totalIters; t++) { +#pragma HLS pipeline style=flp II=1 + // read new input word if current out count is zero + if (o == 0) { + ei = in.read(); + } + ap_uint eo; + for (unsigned int s = 0; s < SIMD; s++){ +#pragma HLS unroll + unsigned int upper_bound = (s*Channels + sf*Channels*SIMD + nf*PE + PE) * ActWidth; + unsigned int lower_bound = (s*Channels + sf*Channels*SIMD + nf*PE) * ActWidth; + eo((s+1)*PE*ActWidth-1, s*PE*ActWidth) = ei(upper_bound - 1, lower_bound); + } + out.write(eo); + if (++o == SF*NF) { + o = 0; + } + if (++sf == SF){ + if (++nf == NF){ + nf = 0; + } + sf = 0; + } + } +} + + /** * \brief Stream Data Width Converter No Multiple - * Converts the width of the input stream in the output stream for no multiple dimensions diff --git a/tb/data/dwc_parallelwindow_config.h b/tb/data/dwc_parallelwindow_config.h new file mode 100644 index 0000000..f2e19df --- /dev/null +++ b/tb/data/dwc_parallelwindow_config.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * Copyright (c) 2019, 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. + * + ******************************************************************************/ +#define INPUT_WIDTH 144 +#define OUT_WIDTH 8 +#define NUM_REPEAT 1 +#define KERNEL1 9 +#define SIMD1 1 +#define SF1 9 +#define CHANNELS1 4 +#define PE1 2 +#define NF1 2 +#define ACTWIDTH1 4 \ No newline at end of file diff --git a/tb/dwc_parallelwindow_tb.cpp b/tb/dwc_parallelwindow_tb.cpp new file mode 100644 index 0000000..f09d06c --- /dev/null +++ b/tb/dwc_parallelwindow_tb.cpp @@ -0,0 +1,109 @@ +/****************************************************************************** + * Copyright (c) 2019, 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * Authors: Giulio Gambardella + * + * \file dwc_tb.cpp + * + * Testbench for the data-width converter HLS block + * + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#define AP_INT_MAX_W 8191 +#include "ap_int.h" +#include "weights.hpp" +#include "bnn-library.h" + +#include "data/dwc_parallelwindow_config.h" + +#include "activations.hpp" +#include "interpret.hpp" + +using namespace hls; +using namespace std; + +#define MAX_IMAGES 1 +void Testbench_dwc_parallelwindow(stream > & in, stream > & out, unsigned int numReps); + +int main() +{ + stream > input_stream("input_stream"); + stream > output_stream("output_stream"); + ap_uint golden_input [NUM_REPEAT]; + for (unsigned int counter = 0; counter < NUM_REPEAT*MAX_IMAGES; counter++) { + // Populate input stream + ap_uint value; + for (unsigned int i = 0; i < CHANNELS1 * KERNEL1; i++){ + value(INPUT_WIDTH-1, INPUT_WIDTH-ACTWIDTH1) = (ap_uint) (i + counter*CHANNELS1*KERNEL1); + value = value >> ACTWIDTH1; + } + cout << "Input stream: "; + for (unsigned int i = 0; i < CHANNELS1 * KERNEL1; i++){ + cout << value((i+1)*ACTWIDTH1-1, i*ACTWIDTH1) << ", "; + } + cout << endl; + input_stream.write(value); + golden_input[counter] = value; + } + Testbench_dwc_parallelwindow(input_stream, output_stream, MAX_IMAGES); + for (unsigned int counter=0 ; counter < NUM_REPEAT*MAX_IMAGES; counter++) + { + for (unsigned int i = 0; i < NF1; i++){ + for (unsigned int j = 0; j < SF1; j++){ + cout << "Stream read" << endl; + ap_uint value = output_stream.read(); + for (unsigned int k = 0; k < SIMD1; k++){ + for (unsigned int l = 0; l < PE1; l++){ + unsigned int lower_bound = (i*PE1 + j*SIMD1*CHANNELS1 + k*CHANNELS1 + l)*ACTWIDTH1; + unsigned int upper_bound = (i*PE1 + j*SIMD1*CHANNELS1 + k*CHANNELS1 + l + 1)*ACTWIDTH1; + ap_uint expected = golden_input[counter](upper_bound-1, lower_bound); + ap_uint computed = value(ACTWIDTH1-1, 0); + value = value >> ACTWIDTH1; + if (expected != computed){ + cout << "ERROR at {NF1, SF1, SIMD1, PE1} = " << "{" << i << ", " << j << ", " << k << ", " << l << "}, Expected/Computed = " << expected << ", " << computed << endl; + } else { + cout << "CORRECT at {NF1, SF1, SIMD1, PE1} = " << "{" << i << ", " << j << ", " << k << ", " << l << "}, Expected/Computed = " << expected << ", " << computed << endl; + } + } + } + } + } + } +} + + diff --git a/tb/dwc_parallelwindow_top.cpp b/tb/dwc_parallelwindow_top.cpp new file mode 100644 index 0000000..575c9d2 --- /dev/null +++ b/tb/dwc_parallelwindow_top.cpp @@ -0,0 +1,51 @@ +/****************************************************************************** + * Copyright (c) 2019, 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. + * + ******************************************************************************/ +/****************************************************************************** + * + * Authors: Giulio Gambardella + * + * \file dwc_top.cpp + * + * HLS Top function with a single HLS data-width converter block unit testing + * + *****************************************************************************/ +#include +using namespace hls; +#include "ap_int.h" +#include "bnn-library.h" + + +#include "data/dwc_parallelwindow_config.h" + +void Testbench_dwc_parallelwindow(stream > & in, stream > & out, unsigned int numReps){ + StreamingDataWidthConverter_Parallelwindow_Batch(in, out, numReps); +} diff --git a/tb/test_dwc_parallelwindow.tcl b/tb/test_dwc_parallelwindow.tcl new file mode 100644 index 0000000..45afdc8 --- /dev/null +++ b/tb/test_dwc_parallelwindow.tcl @@ -0,0 +1,52 @@ +############################################################################## + # Copyright (c) 2019, 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. + # +############################################################################### +############################################################################### + # + # Authors: Giulio Gambardella + # + # \file test_dwc.tcl + # + # Tcl script for HLS csim, synthesis and cosim of the datawidth converter block + # +############################################################################### +open_project hls-syn-dwc-pw +add_files dwc_parallelwindow_top.cpp -cflags "-std=c++14 -I$::env(FINN_HLS_ROOT) -I$::env(FINN_HLS_ROOT)/tb" +add_files -tb dwc_parallelwindow_tb.cpp -cflags "-std=c++14 -I$::env(FINN_HLS_ROOT) -I$::env(FINN_HLS_ROOT)/tb" +set_top Testbench_dwc_parallelwindow +open_solution sol1 +set_part {xczu3eg-sbva484-1-i} +create_clock -period 5 -name default +csim_design +csynth_design +cosim_design +export_design -format ip_catalog +exit