From 016c425a44468f419eab97f8e9cde05072a49e26 Mon Sep 17 00:00:00 2001 From: Michal Danilowicz Date: Mon, 16 Sep 2024 16:44:54 +0000 Subject: [PATCH 1/5] [Feature] Timeout template added --- src/finn/custom_op/fpgadataflow/hlsbackend.py | 14 ++++++ src/finn/custom_op/fpgadataflow/templates.py | 45 +++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/finn/custom_op/fpgadataflow/hlsbackend.py b/src/finn/custom_op/fpgadataflow/hlsbackend.py index d8210fd684..c03a9029db 100644 --- a/src/finn/custom_op/fpgadataflow/hlsbackend.py +++ b/src/finn/custom_op/fpgadataflow/hlsbackend.py @@ -474,3 +474,17 @@ def get_ap_int_max_w(self): ret = max([instream, outstream]) assert ret <= 8191, "AP_INT_MAX_W=%d is larger than allowed maximum of 8191" % ret return ret + + def timeout_value(self): + """Set timeout value for HLS functions defined for one clock cycle""" + self.code_gen_dict["$TIMEOUT_VALUE$"] = ["100"] + + def timeout_condition(self): + """Set timeout condition for HLS functions defined for one clock cycle""" + self.code_gen_dict["$TIMEOUT_CONDITION$"] = ["out_{}.empty()".format(self.hls_sname())] + + def timeout_read_stream(self): + """Set reading output stream procedure for HLS functions defined for one clock cycle""" + self.code_gen_dict["$TIMEOUT_READ_STREAM$"] = [ + "debug_out_{} << out_{}.read();".format(self.hls_sname(), self.hls_sname()) + ] diff --git a/src/finn/custom_op/fpgadataflow/templates.py b/src/finn/custom_op/fpgadataflow/templates.py index 3d89a0ab23..7ef74118ec 100644 --- a/src/finn/custom_op/fpgadataflow/templates.py +++ b/src/finn/custom_op/fpgadataflow/templates.py @@ -58,6 +58,51 @@ """ +# template for single node execution with timeout (for single clock hls operations) +docompute_template_timeout = """ +#define AP_INT_MAX_W $AP_INT_MAX_W$ +#include "cnpy.h" +#include "npy2apintstream.hpp" +#include "npy2vectorstream.hpp" +#include +#include "bnn-library.h" + +// includes for network parameters +$GLOBALS$ + +// defines for network parameters +$DEFINES$ + +int main(){ +$PRAGMAS$ + +$STREAMDECLARATIONS$ + +$READNPYDATA$ + +unsigned timeout = 0; +while(timeout < $TIMEOUT_VALUE$){ + +$DOCOMPUTE$ + +if($TIMEOUT_CONDITION$){ +timeout++; +} + +else{ +$TIMEOUT_READ_STREAM$ +timeout = 0; +} +} + +$DATAOUTSTREAM$ + +$SAVEASCNPY$ + +} + +""" + # templates for single node ip generation # cpp file From fe69308ef293093239d4c8137f80e71375e9bfaf Mon Sep 17 00:00:00 2001 From: mdaniowi Date: Fri, 20 Sep 2024 16:02:40 +0100 Subject: [PATCH 2/5] [Feature] npy2vectorstream.hpp include added to docompute_template --- src/finn/custom_op/fpgadataflow/templates.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/finn/custom_op/fpgadataflow/templates.py b/src/finn/custom_op/fpgadataflow/templates.py index 7ef74118ec..d2100a7516 100644 --- a/src/finn/custom_op/fpgadataflow/templates.py +++ b/src/finn/custom_op/fpgadataflow/templates.py @@ -32,6 +32,7 @@ #define AP_INT_MAX_W $AP_INT_MAX_W$ #include "cnpy.h" #include "npy2apintstream.hpp" +#include "npy2vectorstream.hpp" #include #include "bnn-library.h" From f21da72ba791ec1a9423f7761b8806843dc417a0 Mon Sep 17 00:00:00 2001 From: auphelia Date: Thu, 5 Dec 2024 14:42:22 +0000 Subject: [PATCH 3/5] First draft of enabling both cpp interfaces in cppsim --- src/finn/custom_op/fpgadataflow/hlsbackend.py | 55 +++++++++++++------ 1 file changed, 39 insertions(+), 16 deletions(-) diff --git a/src/finn/custom_op/fpgadataflow/hlsbackend.py b/src/finn/custom_op/fpgadataflow/hlsbackend.py index c03a9029db..98b1dc80c9 100644 --- a/src/finn/custom_op/fpgadataflow/hlsbackend.py +++ b/src/finn/custom_op/fpgadataflow/hlsbackend.py @@ -54,6 +54,8 @@ def get_nodeattr_types(self): "code_gen_dir_cppsim": ("s", False, ""), "executable_path": ("s", False, ""), "res_hls": ("s", False, ""), + # temporary node attribute to keep track of interface style of hls ops + "cpp_interface": ("s", False, "packed", {"packed", "hls_vector"}), } def get_all_verilog_paths(self): @@ -206,7 +208,13 @@ def code_generation_cppsim(self, model): self.dataoutstrm() self.save_as_npy() - template = templates.docompute_template + if self.get_nodeattr("cpp_interface") == "hls_vector": + self.timeout_value() + self.timeout_condition() + self.timeout_read_stream() + template = templates.docompute_template_timeout + else: + template = templates.docompute_template for key in self.code_gen_dict: # transform list into long string separated by '\n' @@ -422,27 +430,42 @@ def dataoutstrm(self): if dtype == DataType["BIPOLAR"]: # use binary for bipolar storage dtype = DataType["BINARY"] - elem_bits = dtype.bitwidth() - packed_bits = self.get_outstream_width() - packed_hls_type = "ap_uint<%d>" % packed_bits elem_hls_type = dtype.get_hls_datatype_str() npy_type = "float" npy_out = "%s/output.npy" % code_gen_dir oshape = self.get_folded_output_shape() oshape_cpp_str = str(oshape).replace("(", "{").replace(")", "}") - self.code_gen_dict["$DATAOUTSTREAM$"] = [ - 'apintstream2npy<%s, %s, %d, %s>(out_%s, %s, "%s");' - % ( - packed_hls_type, - elem_hls_type, - elem_bits, - npy_type, - self.hls_sname(), - oshape_cpp_str, - npy_out, - ) - ] + cpp_interface = self.get_nodeattr("cpp_interface") + + if cpp_interface == "packed": + elem_bits = dtype.bitwidth() + packed_bits = self.get_outstream_width() + packed_hls_type = "ap_uint<%d>" % packed_bits + + self.code_gen_dict["$DATAOUTSTREAM$"] = [ + 'apintstream2npy<%s, %s, %d, %s>(out_%s, %s, "%s");' + % ( + packed_hls_type, + elem_hls_type, + elem_bits, + npy_type, + self.hls_sname(), + oshape_cpp_str, + npy_out, + ) + ] + else: + self.code_gen_dict["$DATAOUTSTREAM$"] = [ + 'vectorstream2npy<%s, %s, SIMD>(debug_out_%s, %s, "%s");' + % ( + elem_hls_type, + npy_type, + self.hls_sname(), + oshape_cpp_str, + npy_out, + ) + ] def save_as_npy(self): """Function to generate the commands for saving data in .npy file in c++""" From 0b5e80e2c0d41051f3969d49cda2ffae74470df8 Mon Sep 17 00:00:00 2001 From: auphelia Date: Mon, 9 Dec 2024 14:14:54 +0000 Subject: [PATCH 4/5] [HLSBackend] Update hls vector cppsim methods --- src/finn/custom_op/fpgadataflow/hlsbackend.py | 49 +++++++++++++------ 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/finn/custom_op/fpgadataflow/hlsbackend.py b/src/finn/custom_op/fpgadataflow/hlsbackend.py index 98b1dc80c9..d8397c67fd 100644 --- a/src/finn/custom_op/fpgadataflow/hlsbackend.py +++ b/src/finn/custom_op/fpgadataflow/hlsbackend.py @@ -379,24 +379,40 @@ def read_npy_data(self): if dtype == DataType["BIPOLAR"]: # use binary for bipolar storage dtype = DataType["BINARY"] - elem_bits = dtype.bitwidth() - packed_bits = self.get_instream_width() - packed_hls_type = "ap_uint<%d>" % packed_bits elem_hls_type = dtype.get_hls_datatype_str() npy_type = "float" npy_in = "%s/input_0.npy" % code_gen_dir self.code_gen_dict["$READNPYDATA$"] = [] - self.code_gen_dict["$READNPYDATA$"].append( - 'npy2apintstream<%s, %s, %d, %s>("%s", in0_%s);' - % ( - packed_hls_type, - elem_hls_type, - elem_bits, - npy_type, - npy_in, - self.hls_sname(), + + cpp_interface = self.get_nodeattr("cpp_interface") + + if cpp_interface == "packed": + elem_bits = dtype.bitwidth() + packed_bits = self.get_instream_width() + packed_hls_type = "ap_uint<%d>" % packed_bits + self.code_gen_dict["$READNPYDATA$"].append( + 'npy2apintstream<%s, %s, %d, %s>("%s", in0_%s);' + % ( + packed_hls_type, + elem_hls_type, + elem_bits, + npy_type, + npy_in, + self.hls_sname(), + ) + ) + else: + folded_shape = self.get_folded_input_shape() + self.code_gen_dict["$READNPYDATA$"].append( + 'npy2vectorstream<%s, %s, %d>("%s", in0_%s, false);' + % ( + elem_hls_type, + npy_type, + folded_shape[-1], + npy_in, + self.hls_sname(), + ) ) - ) def strm_decl(self): """Function to generate the commands for the stream declaration in c++, @@ -456,12 +472,13 @@ def dataoutstrm(self): ) ] else: + folded_shape = self.get_folded_output_shape() self.code_gen_dict["$DATAOUTSTREAM$"] = [ - 'vectorstream2npy<%s, %s, SIMD>(debug_out_%s, %s, "%s");' + 'vectorstream2npy<%s, %s, %d>(strm, %s, "%s");' % ( elem_hls_type, npy_type, - self.hls_sname(), + folded_shape[-1], oshape_cpp_str, npy_out, ) @@ -509,5 +526,5 @@ def timeout_condition(self): def timeout_read_stream(self): """Set reading output stream procedure for HLS functions defined for one clock cycle""" self.code_gen_dict["$TIMEOUT_READ_STREAM$"] = [ - "debug_out_{} << out_{}.read();".format(self.hls_sname(), self.hls_sname()) + "strm << out_{}.read();".format(self.hls_sname()) ] From 95bc8a66eb721e8924a820b2b2994792bdbda457 Mon Sep 17 00:00:00 2001 From: auphelia Date: Mon, 9 Dec 2024 14:36:11 +0000 Subject: [PATCH 5/5] [HLSBackend] Increase time out value --- src/finn/custom_op/fpgadataflow/hlsbackend.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/finn/custom_op/fpgadataflow/hlsbackend.py b/src/finn/custom_op/fpgadataflow/hlsbackend.py index d8397c67fd..4677960ea8 100644 --- a/src/finn/custom_op/fpgadataflow/hlsbackend.py +++ b/src/finn/custom_op/fpgadataflow/hlsbackend.py @@ -517,7 +517,7 @@ def get_ap_int_max_w(self): def timeout_value(self): """Set timeout value for HLS functions defined for one clock cycle""" - self.code_gen_dict["$TIMEOUT_VALUE$"] = ["100"] + self.code_gen_dict["$TIMEOUT_VALUE$"] = ["1000"] def timeout_condition(self): """Set timeout condition for HLS functions defined for one clock cycle"""