diff --git a/src/finn/custom_op/fpgadataflow/rtl/convolutioninputgenerator_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/convolutioninputgenerator_rtl.py index 321522e7ba..5be4bcec45 100755 --- a/src/finn/custom_op/fpgadataflow/rtl/convolutioninputgenerator_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/convolutioninputgenerator_rtl.py @@ -927,11 +927,6 @@ def generate_hdl(self, model, fpgapart, clk): shutil.copy2(os.environ["FINN_ROOT"] + "/finn-rtllib/swg/swg_common.sv", code_gen_dir) shutil.copy2(os.environ["FINN_ROOT"] + "/finn-rtllib/swg/swg_pkg.sv", code_gen_dir) - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) - def prepare_rtlsim(self): """Creates a Verilator emulation library for the RTL code generated for this node, sets the rtlsim_so attribute to its path and returns @@ -964,31 +959,6 @@ def prepare_rtlsim(self): self.set_nodeattr("rtlsim_so", sim.lib._name) return sim - def code_generation_ipi(self): - """Constructs and returns the TCL for node instantiation in Vivado IPI.""" - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - - sourcefiles = [ - "swg_pkg.sv", - self.get_nodeattr("gen_top_module") + "_wrapper.v", - self.get_nodeattr("gen_top_module") + "_impl.sv", - "swg_common.sv", - ] - - if self.get_nodeattr("dynamic_mode"): - sourcefiles += [self.get_nodeattr("gen_top_module") + "_axilite.v"] - - sourcefiles = [os.path.join(code_gen_dir, f) for f in sourcefiles] - - cmd = [] - for f in sourcefiles: - cmd += ["add_files -norecurse %s" % (f)] - cmd += [ - "create_bd_cell -type module -reference %s %s" - % (self.get_nodeattr("gen_top_module"), self.onnx_node.name) - ] - return cmd - def get_verilog_top_module_intf_names(self): # Overload default HLSCustomOp implementation to add axilite control IF """Return a dict of names of input and output interfaces. diff --git a/src/finn/custom_op/fpgadataflow/rtl/fmpadding_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/fmpadding_rtl.py index cc49446ea3..d7d4b40d8a 100644 --- a/src/finn/custom_op/fpgadataflow/rtl/fmpadding_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/fmpadding_rtl.py @@ -201,10 +201,6 @@ def generate_hdl(self, model, fpgapart, clk): sv_files = ["fmpadding_axi.sv", "fmpadding.sv", "axi2we.sv"] for sv_file in sv_files: shutil.copy(rtlsrc + "/" + sv_file, code_gen_dir) - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) def prepare_rtlsim(self): """Creates a Verilator emulation library for the RTL code generated @@ -235,25 +231,3 @@ def prepare_rtlsim(self): # save generated lib filename in attribute self.set_nodeattr("rtlsim_so", sim.lib._name) return sim - - def code_generation_ipi(self): - """Constructs and returns the TCL for node instantiation in Vivado IPI.""" - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - - sourcefiles = [ - "fmpadding_axi.sv", - "fmpadding.sv", - "axi2we.sv", - self.get_nodeattr("gen_top_module") + ".v", - ] - - sourcefiles = [os.path.join(code_gen_dir, f) for f in sourcefiles] - - cmd = [] - for f in sourcefiles: - cmd += ["add_files -norecurse %s" % (f)] - cmd += [ - "create_bd_cell -type module -reference %s %s" - % (self.get_nodeattr("gen_top_module"), self.onnx_node.name) - ] - return cmd diff --git a/src/finn/custom_op/fpgadataflow/rtl/matrixvectoractivation_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/matrixvectoractivation_rtl.py index 3e81aa93e0..623f14415b 100644 --- a/src/finn/custom_op/fpgadataflow/rtl/matrixvectoractivation_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/matrixvectoractivation_rtl.py @@ -28,6 +28,7 @@ import numpy as np import os +import shutil from pyverilator.util.axi_utils import reset_rtlsim, toggle_clk from finn.custom_op.fpgadataflow.matrixvectoractivation import MVAU @@ -145,38 +146,17 @@ def dsp_estimation(self, fpgapart): mult_dsp = np.ceil(P / 4) * Q return int(mult_dsp) + def code_generation_ipi(self): + return MVAU.code_generation_ipi(self) + def instantiate_ip(self, cmd): # instantiate the RTL IP - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - rtllib_dir = os.path.join(os.environ["FINN_ROOT"], "finn-rtllib/mvu/") - sourcefiles = [ - os.path.join(code_gen_dir, self.get_nodeattr("gen_top_module") + "_wrapper.v"), - rtllib_dir + "mvu_vvu_axi.sv", - rtllib_dir + "replay_buffer.sv", - rtllib_dir + "mvu_4sx4u.sv", - rtllib_dir + "mvu_vvu_8sx9_dsp58.sv", - rtllib_dir + "mvu_8sx8u_dsp48.sv", - ] - for f in sourcefiles: - cmd.append("add_files -norecurse %s" % (f)) - mem_mode = self.get_nodeattr("mem_mode") - if mem_mode == "internal_decoupled": - cmd.append( - "create_bd_cell -type hier -reference %s /%s/%s" - % ( - self.get_nodeattr("gen_top_module"), - self.onnx_node.name, - self.onnx_node.name, - ) - ) + vlnv = self.get_nodeattr("ip_vlnv") + node_name = self.onnx_node.name + if self.get_nodeattr("mem_mode") == "internal_decoupled": + cmd.append("create_bd_cell -type ip -vlnv %s /%s/%s" % (vlnv, node_name, node_name)) else: - cmd.append( - "create_bd_cell -type hier -reference %s %s" - % ( - self.get_nodeattr("gen_top_module"), - self.onnx_node.name, - ) - ) + cmd.append("create_bd_cell -type ip -vlnv %s %s" % (vlnv, node_name)) def _resolve_segment_len(self, clk): # Insert pipeline registers in the DSP58 chain to meet target clock frequency @@ -253,10 +233,16 @@ def generate_hdl(self, model, fpgapart, clk): ) as f: f.write(template_wrapper.replace("$FORCE_BEHAVIORAL$", str(1))) - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) + rtllib_dir = os.path.join(os.environ["FINN_ROOT"], "finn-rtllib/mvu/") + sourcefiles = [ + rtllib_dir + "mvu_vvu_axi.sv", + rtllib_dir + "replay_buffer.sv", + rtllib_dir + "mvu_4sx4u.sv", + rtllib_dir + "mvu_vvu_8sx9_dsp58.sv", + rtllib_dir + "mvu_8sx8u_dsp48.sv", + ] + for f in sourcefiles: + shutil.copy(f, code_gen_dir) def prepare_codegen_default(self, fpgapart, clk): template_path = os.environ["FINN_ROOT"] + "/finn-rtllib/mvu/mvu_vvu_axi_wrapper.v" diff --git a/src/finn/custom_op/fpgadataflow/rtl/streamingdatawidthconverter_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/streamingdatawidthconverter_rtl.py index e79782eb6d..19c1cd04b3 100644 --- a/src/finn/custom_op/fpgadataflow/rtl/streamingdatawidthconverter_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/streamingdatawidthconverter_rtl.py @@ -162,10 +162,6 @@ def generate_hdl(self, model, fpgapart, clk): sv_files = ["dwc_axi.sv", "dwc.sv"] for sv_file in sv_files: shutil.copy(rtlsrc + "/" + sv_file, code_gen_dir) - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) def prepare_rtlsim(self): """Creates a Verilator emulation library for the RTL code generated @@ -195,24 +191,3 @@ def prepare_rtlsim(self): # save generated lib filename in attribute self.set_nodeattr("rtlsim_so", sim.lib._name) return sim - - def code_generation_ipi(self): - """Constructs and returns the TCL for node instantiation in Vivado IPI.""" - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - - sourcefiles = [ - "dwc_axi.sv", - "dwc.sv", - self.get_nodeattr("gen_top_module") + ".v", - ] - - sourcefiles = [os.path.join(code_gen_dir, f) for f in sourcefiles] - - cmd = [] - for f in sourcefiles: - cmd += ["add_files -norecurse %s" % (f)] - cmd += [ - "create_bd_cell -type module -reference %s %s" - % (self.get_nodeattr("gen_top_module"), self.onnx_node.name) - ] - return cmd diff --git a/src/finn/custom_op/fpgadataflow/rtl/streamingfifo_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/streamingfifo_rtl.py index f8f27cb647..a6b50bfbcc 100644 --- a/src/finn/custom_op/fpgadataflow/rtl/streamingfifo_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/streamingfifo_rtl.py @@ -115,10 +115,6 @@ def generate_hdl(self, model, fpgapart, clk): f.write(template) shutil.copy(rtlsrc + "/Q_srl.v", code_gen_dir) - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) def execute_node(self, context, graph): mode = self.get_nodeattr("exec_mode") @@ -177,23 +173,7 @@ def execute_node(self, context, graph): def code_generation_ipi(self): impl_style = self.get_nodeattr("impl_style") if impl_style == "rtl": - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - - sourcefiles = [ - "Q_srl.v", - self.get_nodeattr("gen_top_module") + ".v", - ] - - sourcefiles = [os.path.join(code_gen_dir, f) for f in sourcefiles] - - cmd = [] - for f in sourcefiles: - cmd += ["add_files -norecurse %s" % (f)] - cmd += [ - "create_bd_cell -type module -reference %s %s" - % (self.get_nodeattr("gen_top_module"), self.onnx_node.name) - ] - return cmd + return RTLBackend.code_generation_ipi(self) elif impl_style == "vivado": cmd = [] node_name = self.onnx_node.name diff --git a/src/finn/custom_op/fpgadataflow/rtl/thresholding_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/thresholding_rtl.py index c31f90af0b..815bbdafc7 100644 --- a/src/finn/custom_op/fpgadataflow/rtl/thresholding_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/thresholding_rtl.py @@ -228,7 +228,7 @@ def prepare_codegen_rtl_values(self, model): with open(thresh_file, "w") as f: for val in threshs: f.write(val + "\n") - code_gen_dict["$THRESHOLDS_PATH$"] = ['"./%s_"' % self.onnx_node.name] + code_gen_dict["$THRESHOLDS_PATH$"] = [f'"{t_path}/{self.onnx_node.name}_"'] # Identify the module name code_gen_dict["$MODULE_NAME_AXI_WRAPPER$"] = [ @@ -336,12 +336,6 @@ def generate_hdl(self, model, fpgapart, clk): # dump filled-in template to destination directory for compilation file_only_path = rtl_file_path.split("/")[-1] self.dump_rtl_data(code_gen_dir, file_only_path, data) - - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - # i.e. during the HLSSynthIP() transformation - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) return def prepare_rtlsim(self): @@ -472,31 +466,6 @@ def execute_node(self, context, graph): ) ) - def code_generation_ipi(self): - """Constructs and returns the TCL commands for node instantiation as an RTL - block.""" - rtl_file_list = [ - x.replace("thresholding_template_wrapper", self.get_nodeattr("gen_top_module")) - for x in self.get_rtl_file_list() - ] - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - source_target = "./ip/verilog/rtl_ops/%s" % self.onnx_node.name - cmd = ["file mkdir %s" % source_target] - - for rtl_file in rtl_file_list: - cmd.append( - "add_files -copy_to %s -norecurse %s" - % (source_target, os.path.join(code_gen_dir, rtl_file)) - ) - - # Create an RTL block, not an IP core (-type ip) - cmd.append( - "create_bd_cell -type module -reference %s %s" - % (self.get_nodeattr("gen_top_module"), self.onnx_node.name) - ) - - return cmd - def get_verilog_top_module_intf_names(self): intf_names = super().get_verilog_top_module_intf_names() if self.get_nodeattr("runtime_writeable_weights") == 1: diff --git a/src/finn/custom_op/fpgadataflow/rtl/vectorvectoractivation_rtl.py b/src/finn/custom_op/fpgadataflow/rtl/vectorvectoractivation_rtl.py index 32943d86cf..1aea0cea24 100644 --- a/src/finn/custom_op/fpgadataflow/rtl/vectorvectoractivation_rtl.py +++ b/src/finn/custom_op/fpgadataflow/rtl/vectorvectoractivation_rtl.py @@ -28,6 +28,7 @@ import numpy as np import os +import shutil from pyverilator.util.axi_utils import reset_rtlsim, toggle_clk from qonnx.core.datatype import DataType @@ -147,39 +148,17 @@ def dsp_estimation(self, fpgapart): Q = self.get_nodeattr("SIMD") return int(P * np.ceil(Q / 3)) + def code_generation_ipi(self): + return VVAU.code_generation_ipi(self) + def instantiate_ip(self, cmd): # instantiate the RTL IP - code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") - rtllib_dir = os.path.join(os.environ["FINN_ROOT"], "finn-rtllib/mvu/") - sourcefiles = [ - os.path.join(code_gen_dir, self.get_nodeattr("gen_top_module") + "_wrapper.v"), - rtllib_dir + "mvu_vvu_axi.sv", - rtllib_dir + "replay_buffer.sv", - rtllib_dir + "mvu_4sx4u.sv", - rtllib_dir + "mvu_vvu_8sx9_dsp58.sv", - rtllib_dir + "mvu_8sx8u_dsp48.sv", - ] - for f in sourcefiles: - cmd.append("add_files -norecurse %s" % (f)) - - mem_mode = self.get_nodeattr("mem_mode") - if mem_mode == "internal_decoupled": - cmd.append( - "create_bd_cell -type hier -reference %s /%s/%s" - % ( - self.get_nodeattr("gen_top_module"), - self.onnx_node.name, - self.onnx_node.name, - ) - ) + vlnv = self.get_nodeattr("ip_vlnv") + node_name = self.onnx_node.name + if self.get_nodeattr("mem_mode") == "internal_decoupled": + cmd.append("create_bd_cell -type ip -vlnv %s /%s/%s" % (vlnv, node_name, node_name)) else: - cmd.append( - "create_bd_cell -type hier -reference %s %s" - % ( - self.get_nodeattr("gen_top_module"), - self.onnx_node.name, - ) - ) + cmd.append("create_bd_cell -type ip -vlnv %s %s" % (vlnv, node_name)) def generate_hdl(self, model, fpgapart, clk): # Generate params as part of IP preparation @@ -216,10 +195,16 @@ def generate_hdl(self, model, fpgapart, clk): ) as f: f.write(template_wrapper.replace("$FORCE_BEHAVIORAL$", str(1))) - # set ipgen_path and ip_path so that HLS-Synth transformation - # and stich_ip transformation do not complain - self.set_nodeattr("ipgen_path", code_gen_dir) - self.set_nodeattr("ip_path", code_gen_dir) + rtllib_dir = os.path.join(os.environ["FINN_ROOT"], "finn-rtllib/mvu/") + sourcefiles = [ + rtllib_dir + "mvu_vvu_axi.sv", + rtllib_dir + "replay_buffer.sv", + rtllib_dir + "mvu_4sx4u.sv", + rtllib_dir + "mvu_vvu_8sx9_dsp58.sv", + rtllib_dir + "mvu_8sx8u_dsp48.sv", + ] + for f in sourcefiles: + shutil.copy(f, code_gen_dir) def _resolve_segment_len(self, clk): # Insert pipeline registers in the DSP58 chain to meet target clock frequency diff --git a/src/finn/custom_op/fpgadataflow/rtlbackend.py b/src/finn/custom_op/fpgadataflow/rtlbackend.py index 2e4d647b22..4be322e82f 100644 --- a/src/finn/custom_op/fpgadataflow/rtlbackend.py +++ b/src/finn/custom_op/fpgadataflow/rtlbackend.py @@ -26,8 +26,12 @@ # 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. +import os +import subprocess from abc import ABC, abstractmethod +from finn.custom_op.fpgadataflow import templates + class RTLBackend(ABC): """RTLBackend class all custom ops that correspond to a module in finn-rtllib @@ -49,12 +53,51 @@ def generate_hdl(self, model, fpgapart, clk): def prepare_rtlsim(self): pass - @abstractmethod def code_generation_ipi(self): - pass + """Constructs and returns the TCL for node instantiation in Vivado IPI.""" + vlnv = self.get_nodeattr("ip_vlnv") + cmd = ["create_bd_cell -type ip -vlnv %s %s" % (vlnv, self.onnx_node.name)] + return cmd + + def code_generation_pack_ip(self, fpgapart): + """Pack RTL as IP""" + code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") + # prepare the IP packaging tcl template + template = templates.ip_package_tcl + self.code_gen_dict.clear() + self.code_gen_dict["$TOPNAME$"] = [self.get_nodeattr("gen_top_module")] + self.code_gen_dict["$PART$"] = [fpgapart] + # note: setting the root dir as absolute can cause path problems + # the ipgen script will be invoked from the sources dir so root_dir=. is OK + self.code_gen_dict["$VERILOG_DIR$"] = ["."] + for key in self.code_gen_dict: + # transform list into long string separated by '\n' + code_gen_line = "\n".join(self.code_gen_dict[key]) + template = template.replace(key, code_gen_line) + f = open(os.path.join(code_gen_dir, "package_ip.tcl"), "w") + f.write(template) + f.close() + # create a shell script and call Vivado to invoke the IP pkg script + make_project_sh = code_gen_dir + "/make_ip.sh" + working_dir = os.environ["PWD"] + with open(make_project_sh, "w") as f: + f.write("#!/bin/bash \n") + f.write("cd {}\n".format(code_gen_dir)) + f.write("vivado -mode batch -source package_ip.tcl\n") + f.write("cd {}\n".format(working_dir)) + bash_command = ["bash", make_project_sh] + process_compile = subprocess.Popen(bash_command, stdout=subprocess.PIPE) + process_compile.communicate() + # set ipgen_path and ip_path to point to the new packaged IP + self.set_nodeattr("ipgen_path", code_gen_dir) + self.set_nodeattr("ip_path", code_gen_dir) + vlnv = "xilinx.com:hls:%s:1.0" % (self.get_nodeattr("gen_top_module")) + self.set_nodeattr("ip_vlnv", vlnv) + self.code_gen_dict.clear() def code_generation_ipgen(self, model, fpgapart, clk): self.generate_hdl(model, fpgapart, clk) + self.code_generation_pack_ip(fpgapart) # TODO: Implement alternative def hls_sname(self): diff --git a/src/finn/custom_op/fpgadataflow/templates.py b/src/finn/custom_op/fpgadataflow/templates.py index 3d89a0ab23..c0c1d3c93c 100644 --- a/src/finn/custom_op/fpgadataflow/templates.py +++ b/src/finn/custom_op/fpgadataflow/templates.py @@ -117,98 +117,27 @@ set Version "1.0" set DisplayName "$TOPNAME$" set Description "An IP generated by Xilinx FINN" -set Device "zynq" +set Part "$PART$" set Catalog "/UserIP" set RootDir "$VERILOG_DIR$" ## Variables set Top "$TOPNAME$" -set VerilogFiles [glob -nocomplain $RootDir/*] - - -## Enter IP directory -cd [file dir [info script]] - -## Generate sub cores -set IPs "" -set IPFiles "" - -## Basic info -set core [ipx::create_core $Vendor $Library $IPName $Version] -set_property display_name $DisplayName $core -set_property description $Description $core -set_property taxonomy $Catalog $core -set_property supported_families { \ - artix7 Production \ - artix7l Production \ - kintex7 Production \ - kintex7l Production \ - kintexu Production \ - kintexuplus Production \ - versal Production \ - versalprime Production \ - virtex7 Production \ - virtexu Production \ - virtexuplus Production \ - virtexuplusHBM Production \ - zynq Production \ - zynquplus Production \ - aartix7 Production \ - azynq Production \ - qartix7 Production \ - qkintex7 Production \ - qkintex7l Production \ - qvirtex7 Production \ - qzynq Production \ -} $core; - -## Add verilog files -if {[llength $VerilogFiles] > 0} { - # synthesis - set group [ipx::add_file_group xilinx_verilogsynthesis $core] - foreach f [concat $VerilogFiles $IPFiles] { - set current_file [ipx::add_file $f $group] - if {[file ext $f] == ".dat"} { - set_property type "mif" $current_file - } - } - set_property model_name $Top $group - if {$IPs != ""} { - set_property component_subcores $IPs $group - } - - # simulation - set group [ipx::add_file_group xilinx_verilogbehavioralsimulation $core] - foreach f [concat $VerilogFiles $IPFiles] { - set current_file [ipx::add_file $f $group] - if {[file ext $f] == ".dat"} { - set_property type "mif" $current_file - } - } - set_property model_name $Top $group - if {$IPs != ""} { - set_property component_subcores $IPs $group - } -} -## Import ports -ipx::add_ports_from_hdl \ - -top_level_hdl_file $RootDir/$Top.v \ - -top_module_name $Top \ - $core - -## Infer interfaces -ipx::infer_bus_interface ap_clk xilinx.com:signal:clock_rtl:1.0 [ipx::current_core] -ipx::infer_bus_interface ap_rst_n xilinx.com:signal:reset_rtl:1.0 [ipx::current_core] -ipx::infer_bus_interface {in0_$HLS_SNAME$_TDATA in0_$HLS_SNAME$_TVALID in0_$HLS_SNAME$_TREADY} xilinx.com:interface:axis_rtl:1.0 [ipx::current_core] -ipx::infer_bus_interface {out_$HLS_SNAME$_TREADY out_$HLS_SNAME$_TDATA out_$HLS_SNAME$_TVALID} xilinx.com:interface:axis_rtl:1.0 [ipx::current_core] -ipx::associate_bus_interfaces -busif in0_$HLS_SNAME$ -clock ap_clk [ipx::current_core] -ipx::associate_bus_interfaces -busif out_$HLS_SNAME$ -clock ap_clk [ipx::current_core] - -## Finalize -set_property core_revision 2 [ipx::current_core] -ipx::create_xgui_files [ipx::current_core] -ipx::update_checksums [ipx::current_core] +## Create project with source files +create_project -in_memory -part $Part +add_files [glob -nocomplain $RootDir/*.v $RootDir/*.sv $RootDir/*.dat] +set_property top $Top [current_fileset] + +## Package IP +ipx::package_project -root_dir $RootDir \ + -vendor $Vendor -library $Library -name $IPName -version $Version \ + -taxonomy $Catalog \ + -force_update_compile_order \ + -force +set_property type mif [ipx::get_files -type data -of_objects [ipx::get_file_groups -of_objects [ipx::current_core]]] +set_property display_name $DisplayName [ipx::current_core] +set_property description $Description [ipx::current_core] ipx::save_core [ipx::current_core] ipx::archive_core $Top.zip [ipx::current_core] """ diff --git a/src/finn/transformation/fpgadataflow/prepare_ip.py b/src/finn/transformation/fpgadataflow/prepare_ip.py index a74e0f7afc..3056bd29a1 100644 --- a/src/finn/transformation/fpgadataflow/prepare_ip.py +++ b/src/finn/transformation/fpgadataflow/prepare_ip.py @@ -30,7 +30,7 @@ import os import qonnx.custom_op.registry as registry import warnings -from qonnx.transformation.base import Transformation +from qonnx.transformation.base import NodeLocalTransformation from finn.util.basic import make_build_dir from finn.util.fpgadataflow import is_hls_node, is_rtl_node @@ -59,7 +59,7 @@ def _codegen_single_node(node, model, fpgapart, clk): raise Exception("Custom op_type %s is currently not supported." % op_type) -class PrepareIP(Transformation): +class PrepareIP(NodeLocalTransformation): """Call custom implementation to generate code for single custom node and create folder that contains all the generated files. All nodes in the graph must have the fpgadataflow backend attribute and @@ -88,8 +88,7 @@ def __init__(self, fpgapart, clk): self.fpgapart = fpgapart self.clk = clk - def apply(self, model): - for node in model.graph.node: - if is_hls_node(node) or is_rtl_node(node): - _codegen_single_node(node, model, self.fpgapart, self.clk) - return (model, False) + def applyNodeLocal(self, node): + if is_hls_node(node) or is_rtl_node(node): + _codegen_single_node(node, self.ref_input_model, self.fpgapart, self.clk) + return (node, False)