From 394d1fa2c02a71a8a5ce5e6a5c4cff3c16c3a3a6 Mon Sep 17 00:00:00 2001 From: Yaman Umuroglu <maltanar@gmail.com> Date: Thu, 22 Sep 2022 09:50:30 +0200 Subject: [PATCH] [Refactor] deprecate singuler in/outFIFODepth: in/outFIFODepths only --- src/finn/builder/build_dataflow_config.py | 2 +- .../fpgadataflow/channelwise_op_batch.py | 4 +-- .../custom_op/fpgadataflow/hlscustomop.py | 7 ++--- .../fpgadataflow/matrixvectoractivation.py | 7 +++-- .../fpgadataflow/thresholding_batch.py | 4 +-- .../fpgadataflow/vectorvectoractivation.py | 7 +++-- .../fpgadataflow/convert_to_hls_layers.py | 1 + .../fpgadataflow/insert_fifo.py | 30 ++++++------------- .../fpgadataflow/set_fifo_depths.py | 26 +++++++++++----- tests/end2end/test_end2end_bnn_pynq.py | 4 +-- 10 files changed, 47 insertions(+), 45 deletions(-) diff --git a/src/finn/builder/build_dataflow_config.py b/src/finn/builder/build_dataflow_config.py index 13946c9d1..51e751610 100644 --- a/src/finn/builder/build_dataflow_config.py +++ b/src/finn/builder/build_dataflow_config.py @@ -257,7 +257,7 @@ class DataflowBuildConfig: #: setting the FIFO sizes. auto_fifo_strategy: Optional[ AutoFIFOSizingMethod - ] = AutoFIFOSizingMethod.CHARACTERIZE + ] = AutoFIFOSizingMethod.LARGEFIFO_RTLSIM #: Memory resource type for large FIFOs #: Only relevant when `auto_fifo_depths = True` diff --git a/src/finn/custom_op/fpgadataflow/channelwise_op_batch.py b/src/finn/custom_op/fpgadataflow/channelwise_op_batch.py index 3ed76db29..9d08a2432 100644 --- a/src/finn/custom_op/fpgadataflow/channelwise_op_batch.py +++ b/src/finn/custom_op/fpgadataflow/channelwise_op_batch.py @@ -103,8 +103,8 @@ class ChannelwiseOp_Batch(HLSCustomOp): "paramDataType": ("s", True, ""), "outputDataType": ("s", True, ""), # input and output FIFO depths - "inFIFODepth": ("i", False, 0), - "outFIFODepth": ("i", False, 0), + "inFIFODepths": ("ints", False, [0]), + "outFIFODepths": ("ints", False, [0]), # number of input vectors, examples: # [1] is a single vector (like a FC layer with batch=1) # [4] is four vectors (like a FC layer with batch=4) diff --git a/src/finn/custom_op/fpgadataflow/hlscustomop.py b/src/finn/custom_op/fpgadataflow/hlscustomop.py index 79ae69575..7d322dc37 100644 --- a/src/finn/custom_op/fpgadataflow/hlscustomop.py +++ b/src/finn/custom_op/fpgadataflow/hlscustomop.py @@ -108,12 +108,9 @@ class HLSCustomOp(CustomOp): # ID of FPGA device to which this Op is allocated, in # a multi-FPGA setting "device_id": ("i", False, 0), - # input and output FIFO depths - "inFIFODepth": ("i", False, 2), - "outFIFODepth": ("i", False, 2), # input and output FIFO depths for multi-I/O nodes - "inFIFODepths": ("ints", False, []), - "outFIFODepths": ("ints", False, []), + "inFIFODepths": ("ints", False, [2]), + "outFIFODepths": ("ints", False, [2]), "output_hook": ("s", False, ""), # accumulated characteristic function over two periods "io_chrc_in": ("t", False, np.asarray([], dtype=np.int32)), diff --git a/src/finn/custom_op/fpgadataflow/matrixvectoractivation.py b/src/finn/custom_op/fpgadataflow/matrixvectoractivation.py index d5dbc86c4..e78a918e8 100644 --- a/src/finn/custom_op/fpgadataflow/matrixvectoractivation.py +++ b/src/finn/custom_op/fpgadataflow/matrixvectoractivation.py @@ -1227,8 +1227,11 @@ class MatrixVectorActivation(HLSCustomOp): self.code_gen_dict["$PRAGMAS$"].append( "#pragma HLS INTERFACE axis port=out name=out_" + self.hls_sname() ) - in_fifo_depth = self.get_nodeattr("inFIFODepth") - out_fifo_depth = self.get_nodeattr("outFIFODepth") + # TODO can we deprecate this entirely? this looks like legacy code + # that does not really serve a purpose - FIFO sizes are not typically + # allocated at this point; at best they are set to 2 as the default + in_fifo_depth = 2 + out_fifo_depth = 2 # insert depth pragmas only if specified if in_fifo_depth != 0: self.code_gen_dict["$PRAGMAS$"].append( diff --git a/src/finn/custom_op/fpgadataflow/thresholding_batch.py b/src/finn/custom_op/fpgadataflow/thresholding_batch.py index 828ddd973..110e456cb 100644 --- a/src/finn/custom_op/fpgadataflow/thresholding_batch.py +++ b/src/finn/custom_op/fpgadataflow/thresholding_batch.py @@ -76,8 +76,8 @@ class Thresholding_Batch(HLSCustomOp): "weightDataType": ("s", True, ""), "outputDataType": ("s", True, ""), # input and output FIFO depths - "inFIFODepth": ("i", False, 0), - "outFIFODepth": ("i", False, 0), + "inFIFODepths": ("ints", False, [0]), + "outFIFODepths": ("ints", False, [0]), # number of input vectors, examples: # [1] is a single vector (like a FC layer with batch=1) # [4] is four vectors (like a FC layer with batch=4) diff --git a/src/finn/custom_op/fpgadataflow/vectorvectoractivation.py b/src/finn/custom_op/fpgadataflow/vectorvectoractivation.py index abcb1c756..6391f27bb 100644 --- a/src/finn/custom_op/fpgadataflow/vectorvectoractivation.py +++ b/src/finn/custom_op/fpgadataflow/vectorvectoractivation.py @@ -578,8 +578,11 @@ class VectorVectorActivation(HLSCustomOp): self.code_gen_dict["$PRAGMAS$"].append( "#pragma HLS INTERFACE axis port=out name=out_" + self.hls_sname() ) - in_fifo_depth = self.get_nodeattr("inFIFODepth") - out_fifo_depth = self.get_nodeattr("outFIFODepth") + # TODO can we deprecate this entirely? this looks like legacy code + # that does not really serve a purpose - FIFO sizes are not typically + # allocated at this point; at best they are set to 2 as the default + in_fifo_depth = 2 + out_fifo_depth = 2 # insert depth pragmas only if specified if in_fifo_depth != 0: self.code_gen_dict["$PRAGMAS$"].append( diff --git a/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py b/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py index 429bc34ff..753dbb0f8 100644 --- a/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py +++ b/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py @@ -1234,6 +1234,7 @@ class InferDuplicateStreamsLayer(Transformation): inputDataType=dt.name, numInputVectors=vecs, NumOutputStreams=n_outputs, + outFIFODepths=[2] * n_outputs, name="DuplicateStreams_Batch_" + node.name, ) diff --git a/src/finn/transformation/fpgadataflow/insert_fifo.py b/src/finn/transformation/fpgadataflow/insert_fifo.py index b9222cf3e..e75d1880c 100644 --- a/src/finn/transformation/fpgadataflow/insert_fifo.py +++ b/src/finn/transformation/fpgadataflow/insert_fifo.py @@ -138,14 +138,8 @@ class InsertFIFO(Transformation): # check if outFIFOdepth attribute of first node # and inFIFOdepth attribute of consumer node is equal - if idx_out == 0: - n0_depth = n0.get_nodeattr("outFIFODepth") - else: - n0_depth = n0.get_nodeattr("outFIFODepths")[idx_out] - if idx_inp == 0: - n1_depth = n1.get_nodeattr("inFIFODepth") - else: - n1_depth = n1.get_nodeattr("inFIFODepths")[idx_inp] + n0_depth = n0.get_nodeattr("outFIFODepths")[idx_out] + n1_depth = n1.get_nodeattr("inFIFODepths")[idx_inp] if n0_depth == n1_depth: fifo_depth = n0_depth @@ -187,18 +181,12 @@ class InsertFIFO(Transformation): if inp == output_name: consumer.input[idx] = fifo_output_tensor.name # ensure created FIFO depth is reflected on both sides - if idx_out == 0: - n0.set_nodeattr("outFIFODepth", fifo_depth) - else: - odepths = n0.get_nodeattr("outFIFODepths") - odepths[idx_out] = fifo_depth - n0.set_nodeattr("outFIFODepths", odepths) - if idx_inp == 0: - n1.set_nodeattr("inFIFODepth", fifo_depth) - else: - idepths = n1.get_nodeattr("inFIFODepths") - idepths[idx_inp] = fifo_depth - n1.set_nodeattr("inFIFODepths", idepths) + odepths = n0.get_nodeattr("outFIFODepths") + odepths[idx_out] = fifo_depth + n0.set_nodeattr("outFIFODepths", odepths) + idepths = n1.get_nodeattr("inFIFODepths") + idepths[idx_inp] = fifo_depth + n1.set_nodeattr("inFIFODepths", idepths) graph_modified = True @@ -221,7 +209,7 @@ class InsertFIFO(Transformation): else: fld_shape = n0.get_folded_input_shape(inp_ind) dtype = n0.get_input_datatype(inp_ind) - fifo_depth = n0.get_nodeattr("inFIFODepth") + fifo_depth = n0.get_nodeattr("inFIFODepths")[inp_ind] if fifo_depth <= 2: warnings.warn("Overriding input FIFO depth to 32") diff --git a/src/finn/transformation/fpgadataflow/set_fifo_depths.py b/src/finn/transformation/fpgadataflow/set_fifo_depths.py index 90ea853b6..f715aaeff 100644 --- a/src/finn/transformation/fpgadataflow/set_fifo_depths.py +++ b/src/finn/transformation/fpgadataflow/set_fifo_depths.py @@ -250,14 +250,21 @@ class InsertAndSetFIFODepths(Transformation): ) assert node.op_type != "StreamingFIFO", "Found existing StreamingFIFO node" node = getCustomOp(node) + ifd = node.get_nodeattr("inFIFODepths") + ofd = node.get_nodeattr("outFIFODepths") if self.max_depth is not None: - node.set_nodeattr("inFIFODepth", self.max_depth) - node.set_nodeattr("outFIFODepth", self.max_depth) + ifd = [self.max_depth] * len(ifd) + ofd = [self.max_depth] * len(ofd) else: - i_depth = np.prod(node.get_folded_input_shape()[:-1]) - o_depth = np.prod(node.get_folded_output_shape()[:-1]) - node.set_nodeattr("inFIFODepth", i_depth) - node.set_nodeattr("outFIFODepth", o_depth) + # set each FIFO to its tensor size + # (except stream width hence the :-1) + for i in range(len(ifd)): + ifd[i] = np.prod(node.get_folded_input_shape(i)[:-1]) + for o in range(len(ofd)): + ofd[o] = np.prod(node.get_folded_output_shape(o)[:-1]) + node.set_nodeattr("inFIFODepths", ifd) + node.set_nodeattr("outFIFODepths", ofd) + if node.onnx_node.op_type in extw_optypes: mmode = node.get_nodeattr("mem_mode") if mmode == "external": @@ -380,8 +387,11 @@ class InsertAndSetFIFODepths(Transformation): reset_implementation(node_inst) del fifos[node.name] else: - getCustomOp(node).set_nodeattr("inFIFODepth", 0) - getCustomOp(node).set_nodeattr("outFIFODepth", 0) + inst = getCustomOp(node) + ifd = inst.get_nodeattr("inFIFODepths") + ofd = inst.get_nodeattr("outFIFODepths") + inst.set_nodeattr("inFIFODepths", [0] * len(ifd)) + inst.set_nodeattr("outFIFODepths", [0] * len(ofd)) # for every extw node we changed from external to decoupled, # change back and reset implementation if node.op_type in extw_optypes: diff --git a/tests/end2end/test_end2end_bnn_pynq.py b/tests/end2end/test_end2end_bnn_pynq.py index 103f18b51..5f787d1f8 100644 --- a/tests/end2end/test_end2end_bnn_pynq.py +++ b/tests/end2end/test_end2end_bnn_pynq.py @@ -569,8 +569,8 @@ class TestEnd2End: for node in hls_layers: if node.op_type != "StreamingFIFO": op_inst = getCustomOp(node) - assert op_inst.get_nodeattr("inFIFODepth") == 0 - assert op_inst.get_nodeattr("outFIFODepth") == 0 + assert op_inst.get_nodeattr("inFIFODepths") == [0] + assert op_inst.get_nodeattr("outFIFODepths") == [0] model.save( get_checkpoint_name( topology, wbits, abits, QONNX_export, "fifodepth_" + kind -- GitLab