From afe63114d242ccb462b1bfa09f0be05528d50baa Mon Sep 17 00:00:00 2001 From: auphelia <jakobapk@web.de> Date: Wed, 8 Jan 2020 16:56:27 +0000 Subject: [PATCH] [IP Generation] Added functionality to run the .tcl script and build an IP component from a specific node --- src/finn/core/utils.py | 29 +++++++++++++++ src/finn/custom_op/fpgadataflow/__init__.py | 15 ++++++-- src/finn/transformation/fpgadataflow/ipgen.py | 36 +++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 src/finn/transformation/fpgadataflow/ipgen.py diff --git a/src/finn/core/utils.py b/src/finn/core/utils.py index 0ea2392d9..0a6e5718d 100644 --- a/src/finn/core/utils.py +++ b/src/finn/core/utils.py @@ -1,6 +1,7 @@ import random import string import subprocess +import os import numpy as np import onnx @@ -248,3 +249,31 @@ class CppBuilder: bash_command = ["bash", self.compile_script] process_compile = subprocess.Popen(bash_command, stdout=subprocess.PIPE) process_compile.communicate() + +class IPGenBuilder: + def __init__(self): + self.tcl_script = "" + self.ipgen_path = "" + self.code_gen_dir = "" + self.ipgen_script="" + + def append_tcl(self, tcl_script): + self.tcl_script = tcl_script + + def set_ipgen_path(self, path): + self.ipgen_path = path + + def build(self, code_gen_dir): + self.code_gen_dir = code_gen_dir + self.ipgen_script = str(self.code_gen_dir) + "/ipgen.sh" + working_dir = os.environ["PWD"] + f = open(self.ipgen_script, "w") + f.write("#!/bin/bash \n") + f.write("cd {}\n".format(code_gen_dir)) + f.write("vivado_hls {}\n".format(self.tcl_script)) + f.write("cd {}\n".format(working_dir)) + f.close() + bash_command = ["bash", self.ipgen_script] + process_compile = subprocess.Popen(bash_command, stdout=subprocess.PIPE) + process_compile.communicate() + diff --git a/src/finn/custom_op/fpgadataflow/__init__.py b/src/finn/custom_op/fpgadataflow/__init__.py index be2e9e3a3..5a9634896 100644 --- a/src/finn/custom_op/fpgadataflow/__init__.py +++ b/src/finn/custom_op/fpgadataflow/__init__.py @@ -3,7 +3,7 @@ import numpy as np import os import subprocess from finn.custom_op import CustomOp -from finn.core.utils import CppBuilder +from finn.core.utils import CppBuilder, IPGenBuilder class HLSCustomOp(CustomOp): @@ -68,8 +68,7 @@ class HLSCustomOp(CustomOp): set config_clkperiod $CLKPERIOD$ open_project $config_proj_name - add_files $config_hwsrcdir/top_$TOPFXN$.cpp -cflags - "-std=c++0x -I$config_bnnlibdir" + add_files $config_hwsrcdir/top_$TOPFXN$.cpp -cflags "-std=c++0x -I$config_bnnlibdir" set_top $config_toplevelfxn open_solution sol1 @@ -89,6 +88,7 @@ class HLSCustomOp(CustomOp): "code_gen_dir_npysim": ("s", False, ""), "code_gen_dir_ipgen": ("s", False, ""), "executable_path": ("s", False, ""), + "ipgen_path": ("s", False, ""), } def code_generation_ipgen(self, model, fpgapart, clk): @@ -133,6 +133,15 @@ class HLSCustomOp(CustomOp): f.close() self.code_gen_dict.clear() + def ipgen_singlenode_code(self): + node = self.onnx_node + code_gen_dir = self.get_nodeattr("code_gen_dir_ipgen") + builder = IPGenBuilder() + builder.append_tcl(code_gen_dir + "/hls_syn_{}.tcl".format(node.name)) + builder.set_ipgen_path(code_gen_dir + "/project_{}".format(node.name)) + builder.build(code_gen_dir) + self.set_nodeattr("ipgen_path", builder.ipgen_path) + def code_generation_npysim(self, model): node = self.onnx_node self.generate_params(model) diff --git a/src/finn/transformation/fpgadataflow/ipgen.py b/src/finn/transformation/fpgadataflow/ipgen.py new file mode 100644 index 000000000..c9457863f --- /dev/null +++ b/src/finn/transformation/fpgadataflow/ipgen.py @@ -0,0 +1,36 @@ +import finn.core.utils as util +import finn.custom_op.registry as registry +from finn.transformation import Transformation + + +class IPGen(Transformation): + """Compile for all nodes in model""" + + def __init__(self): + super().__init__() + + def apply(self, model): + for node in model.graph.node: + op_type = node.op_type + if node.domain == "finn": + backend_attribute = util.get_by_name(node.attribute, "backend") + if backend_attribute is None: + continue + backend_value = backend_attribute.s.decode("UTF-8") + if backend_value == "fpgadataflow": + try: + # lookup op_type in registry of CustomOps + inst = registry.custom_op[op_type](node) + # ensure that code is generated + assert inst.get_nodeattr("code_gen_dir_ipgen") != "" + # call the compilation function for this node + inst.ipgen_singlenode_code() + # ensure that executable path is now set + assert inst.get_nodeattr("ipgen_path") != "" + except KeyError: + # exception if op_type is not supported + raise Exception( + "Custom op_type %s is currently not supported." % op_type + ) + return (model, False) + -- GitLab