diff --git a/notebooks/FCLayer_graph.onnx b/notebooks/FCLayer_graph.onnx index 3f29f902b0d98e55af7955a99965642db9621e2e..950c78a9de7224b83ff46da4920da1baa5d80d61 100644 Binary files a/notebooks/FCLayer_graph.onnx and b/notebooks/FCLayer_graph.onnx differ diff --git a/notebooks/FINN-CodeGenerationAndCompilation.ipynb b/notebooks/FINN-CodeGenerationAndCompilation.ipynb index e3f0f03e8c10d6c9c53c2e58d0b7418ddab5d70a..f73b0f5610af51a9a178cb986e1ac9d6e9bcfa56 100644 --- a/notebooks/FINN-CodeGenerationAndCompilation.ipynb +++ b/notebooks/FINN-CodeGenerationAndCompilation.ipynb @@ -245,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -283,7 +283,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -547,6 +547,101 @@ "### Compilation" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<font size=\"3\">The compilation is a transformation pass like the code generation. The code of this transformation is shown below. </font>" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "class Compile(Transformation):\n", + " \"\"\"Compile for all nodes in model\"\"\"\n", + "\n", + " def __init__(self):\n", + " super().__init__()\n", + "\n", + " def apply(self, model):\n", + " for node in model.graph.node:\n", + " op_type = node.op_type\n", + " if node.domain == \"finn\":\n", + " backend_attribute = util.get_by_name(node.attribute, \"backend\")\n", + " if backend_attribute is None:\n", + " continue\n", + " backend_value = backend_attribute.s.decode(\"UTF-8\")\n", + " if backend_value == \"fpgadataflow\":\n", + " try:\n", + " # lookup op_type in registry of CustomOps\n", + " inst = registry.custom_op[op_type](node)\n", + " # ensure that code is generated\n", + " assert inst.get_nodeattr(\"code_gen_dir\") != \"\"\n", + " # call the compilation function for this node\n", + " inst.compile_singlenode_code()\n", + " # ensure that executable path is now set\n", + " assert inst.get_nodeattr(\"executable_path\") != \"\"\n", + " except KeyError:\n", + " # exception if op_type is not supported\n", + " raise Exception(\n", + " \"Custom op_type %s is currently not supported.\" % op_type\n", + " )\n", + " return (model, False)\n", + "\n" + ] + } + ], + "source": [ + "from finn.transformation.fpgadataflow.compile import Compile\n", + "showSrc(Compile)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "<font size=\"3\">The scheme resembles that of the code generation transformation pass. The pass iterates over all nodes in the model and if `domain=\"finn\"` and `backend=\"fpgadataflow\"` is True, the compilation is activated for that node. First an instance of the node is created and checked whether the code was generated. For this the node attribute `code_gen_dir` is checked. If it exists, the function `compile_singlenode_code()` can be executed. Then it is checked whether the path to the executable has been set. There is an exception if the custom op_type is not supported. \n", + "\n", + "The actual compilation is done with the function `compile_singlenode_code()`. What happens inside the function is shown below.</font>" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " def compile_singlenode_code(self):\n", + " code_gen_dir = self.get_nodeattr(\"code_gen_dir\")\n", + " builder = CppBuilder()\n", + " builder.append_includes(\"-I/workspace/finn/src/finn/data/cpp\")\n", + " builder.append_includes(\"-I/workspace/cnpy/\")\n", + " builder.append_includes(\"-I/workspace/finn-hlslib\")\n", + " builder.append_includes(\"-I/workspace/vivado-hlslib\")\n", + " builder.append_includes(\"--std=c++11\")\n", + " builder.append_sources(code_gen_dir + \"/*.cpp\")\n", + " builder.append_sources(\"/workspace/cnpy/cnpy.cpp\")\n", + " builder.append_includes(\"-lz\")\n", + " builder.set_executable_path(code_gen_dir + \"/node_model\")\n", + " builder.build(code_gen_dir)\n", + " self.set_nodeattr(\"executable_path\", builder.executable_path)\n", + "\n" + ] + } + ], + "source": [ + "showSrc(StreamingFCLayer_Batch.compile_singlenode_code)" + ] + }, { "cell_type": "code", "execution_count": null,