diff --git a/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py b/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py index 463896b4331cf68337b0070e257f27fab36b0031..08778c276aab98aa9ffb9ab708e22e783cfdaf35 100644 --- a/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py +++ b/src/finn/custom_op/fpgadataflow/convolutioninputgenerator.py @@ -34,6 +34,11 @@ from pyverilator import PyVerilator from finn.core.datatype import DataType from finn.custom_op.fpgadataflow import HLSCustomOp +# ONNX i/o tensor shape assumptions for ConvolutionInputGenerator: +# input 0 is the input tensor, shape NHWC = (1, IFMDim, IFMDim, IFMChannels) +# output 0 is the output tensor, shape NHWC: +# = (1, OFMDim, OFMDim, (ConvKernelDim^2)*IFMChannels) + class ConvolutionInputGenerator(HLSCustomOp): """Class that corresponds to finn-hlslib ConvolutionInputGenerator @@ -46,7 +51,6 @@ class ConvolutionInputGenerator(HLSCustomOp): my_attrs = { "ConvKernelDim": ("i", True, 0), "IFMChannels": ("i", True, 0), - "Input_precision": ("i", True, 0), "IFMDim": ("i", True, 0), "OFMDim": ("i", True, 0), "SIMD": ("i", True, 0), @@ -84,7 +88,8 @@ class ConvolutionInputGenerator(HLSCustomOp): def get_stream_width(self): """Returns stream width, input and output stream width are equal for the sliding window function""" - return self.get_nodeattr("SIMD") * self.get_nodeattr("Input_precision") + ibits = self.get_input_datatype().bitwidth() + return self.get_nodeattr("SIMD") * ibits def get_number_output_values(self): k = self.get_nodeattr("ConvKernelDim") @@ -218,7 +223,7 @@ class ConvolutionInputGenerator(HLSCustomOp): #define SIMD1 {}\n #define Stride1 {}\n #define numReps {}""".format( self.get_nodeattr("ConvKernelDim"), self.get_nodeattr("IFMChannels"), - self.get_nodeattr("Input_precision"), + self.get_input_datatype().bitwidth(), self.get_nodeattr("IFMDim"), self.get_nodeattr("OFMDim"), self.get_nodeattr("SIMD"), diff --git a/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py b/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py index d2740feb662faddf0286e46688cbfc48c36c6bd0..c898393608f5f8f31b6044a5505f5903743eb346 100644 --- a/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py +++ b/tests/fpgadataflow/test_fpgadataflow_convinputgenerator.py @@ -103,7 +103,6 @@ def make_single_slidingwindow_modelwrapper( k, ifm_ch, ifm_dim, ofm_dim, simd, stride, idt ): - ip = idt.bitwidth() odt = idt out_pix = ofm_dim * ofm_dim @@ -122,7 +121,6 @@ def make_single_slidingwindow_modelwrapper( backend="fpgadataflow", ConvKernelDim=k, IFMChannels=ifm_ch, - Input_precision=ip, IFMDim=ifm_dim, OFMDim=ofm_dim, SIMD=simd, @@ -164,7 +162,9 @@ def prepare_inputs(input_tensor, idt): @pytest.mark.parametrize("ifm_ch", [1]) # , 2, 3, 4]) # Stride @pytest.mark.parametrize("stride", [1, 2]) -def test_fpgadataflow_slidingwindow(idt, k, ifm_dim, ifm_ch, stride): +# execution mode +@pytest.mark.parametrize("exec_mode", ["npysim", "rtlsim"]) +def test_fpgadataflow_slidingwindow(idt, k, ifm_dim, ifm_ch, stride, exec_mode): simd = ifm_ch ofm_dim = int(((ifm_dim - k) / stride) + 1) @@ -172,25 +172,25 @@ def test_fpgadataflow_slidingwindow(idt, k, ifm_dim, ifm_ch, stride): model = make_single_slidingwindow_modelwrapper( k, ifm_ch, ifm_dim, ofm_dim, simd, stride, idt ) - model = model.transform(SetExecMode("npysim")) - model = model.transform(CodeGen_npysim()) - model = model.transform(Compile()) + + if exec_mode == "npysim": + model = model.transform(SetExecMode("npysim")) + model = model.transform(CodeGen_npysim()) + model = model.transform(Compile()) + elif exec_mode == "rtlsim": + model = model.transform(SetExecMode("rtlsim")) + model = model.transform(GiveUniqueNodeNames()) + model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5)) + model = model.transform(HLSSynth_IPGen()) + else: + raise Exception("Unknown exec_mode in test_fpgadataflow_slidingwindow") # prepare input data input_dict = prepare_inputs(x, idt) - # execute model y_produced = oxe.execute_onnx(model, input_dict)["outp"] y_expected = im2col_indices(x, k, stride) # reshape expected output to match node output oshape = y_produced.shape y_expected = y_expected.reshape(oshape) - - assert (y_produced == y_expected).all(), "npysim failed" - - model = model.transform(SetExecMode("rtlsim")) - model = model.transform(GiveUniqueNodeNames()) - model = model.transform(CodeGen_ipgen("xc7z020clg400-1", 5)) - model = model.transform(HLSSynth_IPGen()) - y_produced = oxe.execute_onnx(model, input_dict)["outp"] - assert (y_produced == y_expected).all(), "rtlsim failed" + assert (y_produced == y_expected).all()