diff --git a/src/finn/custom_op/fpgadataflow/thresholding_batch.py b/src/finn/custom_op/fpgadataflow/thresholding_batch.py index 562bab0f18990096f7364b3a4e2bcbbbf4ce2b58..2429bf6190f822fb4a6c988fcbb34152d5a338e0 100644 --- a/src/finn/custom_op/fpgadataflow/thresholding_batch.py +++ b/src/finn/custom_op/fpgadataflow/thresholding_batch.py @@ -73,6 +73,8 @@ class Thresholding_Batch(HLSCustomOp): # [4] is four vectors (like a FC layer with batch=4) # [1, 4, 4] is four * four vectors (like a conv layer with batch=1) "numInputVectors": ("ints", False, [1]), + # initialization value for the thresholding accumulator + "ActVal": ("i", False, 0), } my_attrs.update(super().get_nodeattr_types()) return my_attrs @@ -321,7 +323,7 @@ class Thresholding_Batch(HLSCustomOp): threshold_tensor.shape[-1], tdt_hls, odt_hls, - export_odt.min(), + self.get_nodeattr("ActVal"), "std::less_equal<%s>" % tdt_hls, ) ) diff --git a/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py b/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py index c6edd6104e48e88a9233777a29e41b60fbb588ca..d4d5b006493b8db1da0184e98ba35493d3e6ccbd 100644 --- a/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py +++ b/src/finn/transformation/fpgadataflow/convert_to_hls_layers.py @@ -820,7 +820,19 @@ class InferThresholdingLayer(Transformation): assert ifc % pe == 0, "Requirement IFC divisable by PE is violated." odt = model.get_tensor_datatype(thl_output) - # create and insert new StreamingFCLayer node + scale = getCustomOp(node).get_nodeattr("out_scale") + assert ( + scale == 1.0 + ), "MultiThreshold out_scale must be equal to 1.0 for HLS conversion." + actval = getCustomOp(node).get_nodeattr("out_bias") + assert ( + int(actval) == actval + ), "MultiThreshold out_bias must be integer for HLS conversion." + actval = int(actval) + assert (not odt.signed()) or ( + actval < 0 + ), "Signed output requres actval < 0" + # create and insert new Thresholding_Batch node new_node = helper.make_node( "Thresholding_Batch", [thl_input, thl_threshold], @@ -832,6 +844,7 @@ class InferThresholdingLayer(Transformation): inputDataType=idt.name, outputDataType=odt.name, numInputVectors=list(thl_in_shape[:-1]), + ActVal=actval, ) graph.node.insert(insert_point, new_node) # remove old node diff --git a/tests/fpgadataflow/test_fpgadataflow_thresholding.py b/tests/fpgadataflow/test_fpgadataflow_thresholding.py index ad69b89d8a159f6eb423c0739bdb4c0dd5103792..75fa625ff00ad6d367e2d6c94d98705f391fb9be 100644 --- a/tests/fpgadataflow/test_fpgadataflow_thresholding.py +++ b/tests/fpgadataflow/test_fpgadataflow_thresholding.py @@ -48,7 +48,7 @@ from finn.custom_op.registry import getCustomOp from finn.analysis.fpgadataflow.exp_cycles_per_layer import exp_cycles_per_layer -def make_single_thresholding_modelwrapper(T, pe, idt, odt): +def make_single_thresholding_modelwrapper(T, pe, idt, odt, actval): NumChannels = T.shape[0] inp = helper.make_tensor_value_info("inp", TensorProto.FLOAT, [1, NumChannels]) @@ -66,6 +66,7 @@ def make_single_thresholding_modelwrapper(T, pe, idt, odt): PE=pe, inputDataType=idt.name, outputDataType=odt.name, + ActVal=actval, ) graph = helper.make_graph( nodes=[Thresholding_node], @@ -112,7 +113,12 @@ def test_fpgadataflow_thresholding(idt, act, nf, ich, exec_mode): # provide non-decreasing thresholds T = np.sort(T, axis=1) - model = make_single_thresholding_modelwrapper(T, pe, idt, odt) + if odt == DataType.BIPOLAR: + actval = 0 + else: + actval = odt.min() + + model = make_single_thresholding_modelwrapper(T, pe, idt, odt, actval) if exec_mode == "cppsim": model = model.transform(PrepareCppSim())