diff --git a/notebooks/end2end_example/bnn-pynq/cnv_end2end_example.ipynb b/notebooks/end2end_example/bnn-pynq/cnv_end2end_example.ipynb index a141caf423f5238245b509e077d32c6bd1a85fcd..b49c5f3c3eb68961f08041a2c51a46bf66452c81 100644 --- a/notebooks/end2end_example/bnn-pynq/cnv_end2end_example.ipynb +++ b/notebooks/end2end_example/bnn-pynq/cnv_end2end_example.ipynb @@ -71,14 +71,25 @@ "source": [ "## 1. Brevitas Export, FINN Import and Tidy-Up\n", "\n", - "Similar to what we did in the TFC-w1a1 end-to-end notebook, we will start by exporting the [pretrained CNV-w1a1 network](https://github.com/Xilinx/brevitas/tree/master/brevitas_examples/bnn_pynq) to ONNX, importing that into FINN and running the \"tidy-up\" transformations to have a first look at the topology." + "Similar to what we did in the TFC-w1a1 end-to-end notebook, we will start by exporting the [pretrained CNV-w1a1 network](https://github.com/Xilinx/brevitas/tree/master/src/brevitas_examples/bnn_pynq) to ONNX, importing that into FINN and running the \"tidy-up\" transformations to have a first look at the topology." ] }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/workspace/brevitas/src/brevitas_examples/bnn_pynq/models/CNV.py:106: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n", + " x = 2.0 * x - torch.tensor([1.0], device=x.device)\n", + "/workspace/brevitas/src/brevitas/quant_tensor/__init__.py:74: TracerWarning: torch.tensor results are registered as constants in the trace. You can safely ignore this warning if you use this function to create tensors out of constant variables that would be the same every time you call this function. In any other case, this might cause the trace to be incorrect.\n", + " training = torch.tensor(training, dtype=torch.bool)\n" + ] + } + ], "source": [ "import onnx\n", "from finn.util.test import get_test_model_trained\n", @@ -108,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 3, "metadata": {}, "outputs": [ { @@ -125,17 +136,17 @@ " <iframe\n", " width=\"100%\"\n", " height=\"400\"\n", - " src=\"http://0.0.0.0:8081/\"\n", + " src=\"http://localhost:8081/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " ></iframe>\n", " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f25b19194a8>" + "<IPython.lib.display.IFrame at 0x7f912af76550>" ] }, - "execution_count": 27, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -157,19 +168,19 @@ "source": [ "### Adding Pre- and Postprocessing <a id='prepost'></a>\n", "\n", - "TODO" + "Preprocessing and postprocessing steps can be added directly in the ONNX graph. In this case, the preprocessing step divides the input `uint8` data by 255 so the inputs to the CNV-w1a1 network are bounded between [0, 1]. The postprocessing step takes the output of the network and returns the index (0-9) of the image category with the highest probability (top-1). " ] }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "/workspace/finn/src/finn/transformation/infer_data_layouts.py:113: UserWarning: Assuming 4D input is NCHW\n", + "/workspace/finn-base/src/finn/transformation/infer_data_layouts.py:114: UserWarning: Assuming 4D input is NCHW\n", " warnings.warn(\"Assuming 4D input is NCHW\")\n" ] } @@ -197,14 +208,35 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from finn.transformation.insert_topk import InsertTopK\n", + "from finn.transformation.infer_datatypes import InferDataTypes\n", + "\n", + "# postprocessing: insert Top-1 node at the end\n", + "model = model.transform(InsertTopK(k=1))\n", + "chkpt_name = build_dir+\"/end2end_cnv_w1a1_pre_post.onnx\"\n", + "# tidy-up again\n", + "model = model.transform(InferShapes())\n", + "model = model.transform(FoldConstants())\n", + "model = model.transform(GiveUniqueNodeNames())\n", + "model = model.transform(GiveReadableTensorNames())\n", + "model = model.transform(InferDataTypes())\n", + "model = model.transform(RemoveStaticGraphInputs())\n", + "model.save(chkpt_name)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\n", "Stopping http://0.0.0.0:8081\n", "Serving '/workspace/finn/end2end_cnv_w1a1_pre_post.onnx' at http://0.0.0.0:8081\n" ] @@ -216,37 +248,22 @@ " <iframe\n", " width=\"100%\"\n", " height=\"400\"\n", - " src=\"http://0.0.0.0:8081/\"\n", + " src=\"http://localhost:8081/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " ></iframe>\n", " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f25b1919518>" + "<IPython.lib.display.IFrame at 0x7f8ffd85a760>" ] }, - "execution_count": 29, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ - "from finn.transformation.insert_topk import InsertTopK\n", - "from finn.transformation.infer_datatypes import InferDataTypes\n", - "\n", - "# postprocessing: insert Top-1 node at the end\n", - "model = model.transform(InsertTopK(k=1))\n", - "chkpt_name = build_dir+\"/end2end_cnv_w1a1_pre_post.onnx\"\n", - "# tidy-up again\n", - "model = model.transform(InferShapes())\n", - "model = model.transform(FoldConstants())\n", - "model = model.transform(GiveUniqueNodeNames())\n", - "model = model.transform(GiveReadableTensorNames())\n", - "model = model.transform(InferDataTypes())\n", - "model = model.transform(RemoveStaticGraphInputs())\n", - "model.save(chkpt_name)\n", - "\n", "showInNetron(build_dir+\"/end2end_cnv_w1a1_pre_post.onnx\")" ] }, @@ -268,7 +285,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -311,14 +328,13 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\n", "Stopping http://0.0.0.0:8081\n", "Serving '/workspace/finn/end2end_cnv_w1a1_streamlined.onnx' at http://0.0.0.0:8081\n" ] @@ -330,17 +346,17 @@ " <iframe\n", " width=\"100%\"\n", " height=\"400\"\n", - " src=\"http://0.0.0.0:8081/\"\n", + " src=\"http://localhost:8081/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " ></iframe>\n", " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f25b19a9470>" + "<IPython.lib.display.IFrame at 0x7f91ac6e6f70>" ] }, - "execution_count": 31, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -360,9 +376,18 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/workspace/finn/src/finn/custom_op/fpgadataflow/streamingfclayer_batch.py:591: UserWarning: Clipping some thresholds in \n", + " warnings.warn(\"Clipping some thresholds in %s\" % self.onnx_node.name)\n" + ] + } + ], "source": [ "import finn.transformation.fpgadataflow.convert_to_hls_layers as to_hls\n", "from finn.transformation.fpgadataflow.create_dataflow_partition import (\n", @@ -409,7 +434,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 10, "metadata": { "scrolled": false }, @@ -418,7 +443,6 @@ "name": "stdout", "output_type": "stream", "text": [ - "\n", "Stopping http://0.0.0.0:8081\n", "Serving '/workspace/finn/end2end_cnv_w1a1_dataflow_parent.onnx' at http://0.0.0.0:8081\n" ] @@ -430,17 +454,17 @@ " <iframe\n", " width=\"100%\"\n", " height=\"400\"\n", - " src=\"http://0.0.0.0:8081/\"\n", + " src=\"http://localhost:8081/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " ></iframe>\n", " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f25b18b7668>" + "<IPython.lib.display.IFrame at 0x7f8ffd85ae20>" ] }, - "execution_count": 36, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -458,14 +482,13 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\n", "Stopping http://0.0.0.0:8081\n", "Serving '/workspace/finn/end2end_cnv_w1a1_dataflow_model.onnx' at http://0.0.0.0:8081\n" ] @@ -477,17 +500,17 @@ " <iframe\n", " width=\"100%\"\n", " height=\"400\"\n", - " src=\"http://0.0.0.0:8081/\"\n", + " src=\"http://localhost:8081/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " ></iframe>\n", " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f25b18fe860>" + "<IPython.lib.display.IFrame at 0x7f8ffd832280>" ] }, - "execution_count": 33, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -505,7 +528,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -549,14 +572,13 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\n", "Stopping http://0.0.0.0:8081\n", "Serving '/workspace/finn/end2end_cnv_w1a1_folded.onnx' at http://0.0.0.0:8081\n" ] @@ -568,17 +590,17 @@ " <iframe\n", " width=\"100%\"\n", " height=\"400\"\n", - " src=\"http://0.0.0.0:8081/\"\n", + " src=\"http://localhost:8081/\"\n", " frameborder=\"0\"\n", " allowfullscreen\n", " ></iframe>\n", " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f252e5a6278>" + "<IPython.lib.display.IFrame at 0x7f8ff1243af0>" ] }, - "execution_count": 35, + "execution_count": 13, "metadata": {}, "output_type": "execute_result" } @@ -605,11 +627,24 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 14, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/workspace/finn/src/finn/transformation/fpgadataflow/floorplan.py:107: UserWarning: 32 nodes have no entry in the provided floorplan, SLR was set to -1\n", + " warnings.warn(\n", + "/workspace/finn/src/finn/transformation/fpgadataflow/insert_fifo.py:154: UserWarning: Overriding input FIFO depth to 32\n", + " warnings.warn(\"Overriding input FIFO depth to 32\")\n", + "/workspace/finn/src/finn/transformation/fpgadataflow/insert_fifo.py:200: UserWarning: Overriding output FIFO depth to 32\n", + " warnings.warn(\"Overriding output FIFO depth to 32\")\n" + ] + } + ], "source": [ - "test_pynq_board = \"Pynq-Z1\"\n", + "test_pynq_board = \"Pynq-Z2\"\n", "target_clk_ns = 10\n", "\n", "from finn.transformation.fpgadataflow.make_zynq_proj import ZynqBuild\n", @@ -631,18 +666,19 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Welcome to PYNQ Linux, based on Ubuntu 18.04 (GNU/Linux 5.4.0-xilinx-v2020.1 armv7l)\r\n", + "Welcome to PYNQ Linux, based on Ubuntu 18.04 (GNU/Linux 4.19.0-xilinx-v2019.1 armv7l)\r\n", "\r\n", - " * Pure upstream Kubernetes 1.21, smallest, simplest cluster ops!\r\n", + " * Super-optimized for small spaces - read how we shrank the memory\r\n", + " footprint of MicroK8s to make it the smallest full K8s around.\r\n", "\r\n", - " https://microk8s.io/\r\n" + " https://ubuntu.com/blog/microk8s-memory-optimisation\r\n" ] } ], @@ -665,7 +701,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -678,16 +714,16 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'/home/xilinx/finn_dev_maltanar/pynq_deployment_obskagv5'" + "'/home/xilinx/finn_dev_jduarte/pynq_deployment_yrxnwrak'" ] }, - "execution_count": 23, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -699,19 +735,21 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "total 4216\r\n", - "-rw-r--r-- 1 xilinx xilinx 8508 Sep 21 13:19 driver.py\r\n", - "drwxr-xr-x 4 xilinx xilinx 4096 Sep 21 13:19 finn\r\n", - "-rw-r--r-- 1 xilinx xilinx 4045671 Sep 21 13:19 resizer.bit\r\n", - "-rw-r--r-- 1 xilinx xilinx 246205 Sep 21 13:19 resizer.hwh\r\n", - "-rw-r--r-- 1 xilinx xilinx 1727 Sep 21 13:19 validate.py\r\n" + "total 4240\r\n", + "-rw-rw-r-- 1 xilinx xilinx 18616 Jun 28 20:42 driver_base.py\r\n", + "-rw-r--r-- 1 xilinx xilinx 4868 Jun 28 20:42 driver.py\r\n", + "drwxr-xr-x 4 xilinx xilinx 4096 Jun 28 20:42 finn\r\n", + "-rw-r--r-- 1 xilinx xilinx 4045671 Jun 28 20:42 resizer.bit\r\n", + "-rw-r--r-- 1 xilinx xilinx 247083 Jun 28 20:42 resizer.hwh\r\n", + "drwxr-xr-x 2 xilinx xilinx 4096 Jun 28 20:42 runtime_weights\r\n", + "-rw-rw-r-- 1 xilinx xilinx 4107 Jun 28 20:42 validate.py\r\n" ] } ], @@ -728,16 +766,16 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 19, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "<matplotlib.image.AxesImage at 0x7f89a07e6eb8>" + "<matplotlib.image.AxesImage at 0x7f917faeb6d0>" ] }, - "execution_count": 2, + "execution_count": 19, "metadata": {}, "output_type": "execute_result" }, @@ -774,7 +812,7 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ @@ -791,7 +829,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -800,7 +838,7 @@ "array([[3.]], dtype=float32)" ] }, - "execution_count": 44, + "execution_count": 21, "metadata": {}, "output_type": "execute_result" } @@ -836,7 +874,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -846,7 +884,7 @@ "[sudo] password for xilinx: Requirement already satisfied: dataset_loading from git+https://github.com/fbcotter/dataset_loading.git@0.0.4#egg=dataset_loading in /usr/local/lib/python3.6/dist-packages\n", "Requirement already satisfied: Pillow in /usr/lib/python3/dist-packages (from dataset_loading)\n", "Requirement already satisfied: scipy in /usr/lib/python3/dist-packages (from dataset_loading)\n", - "Connection to 192.168.2.99 closed.\n" + "Connection to 99.121.248.96 closed.\n" ] } ], @@ -867,7 +905,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -877,18 +915,18 @@ "[sudo] password for xilinx: Tar File found in dest_dir. Not Downloading again\n", "Extracting Python CIFAR10 data.\n", "Files extracted\n", - "batch 0 / 10 : total OK 851 NOK 149\n", - "batch 1 / 10 : total OK 1683 NOK 317\n", - "batch 2 / 10 : total OK 2522 NOK 478\n", - "batch 3 / 10 : total OK 3370 NOK 630\n", - "batch 4 / 10 : total OK 4207 NOK 793\n", - "batch 5 / 10 : total OK 5044 NOK 956\n", - "batch 6 / 10 : total OK 5887 NOK 1113\n", - "batch 7 / 10 : total OK 6728 NOK 1272\n", - "batch 8 / 10 : total OK 7570 NOK 1430\n", - "batch 9 / 10 : total OK 8419 NOK 1581\n", + "batch 1 / 10 : total OK 851 NOK 149\n", + "batch 2 / 10 : total OK 1683 NOK 317\n", + "batch 3 / 10 : total OK 2522 NOK 478\n", + "batch 4 / 10 : total OK 3370 NOK 630\n", + "batch 5 / 10 : total OK 4207 NOK 793\n", + "batch 6 / 10 : total OK 5044 NOK 956\n", + "batch 7 / 10 : total OK 5887 NOK 1113\n", + "batch 8 / 10 : total OK 6728 NOK 1272\n", + "batch 9 / 10 : total OK 7570 NOK 1430\n", + "batch 10 / 10 : total OK 8419 NOK 1581\n", "Final accuracy: 84.190000\n", - "Connection to 192.168.2.99 closed.\n" + "Connection to 99.121.248.96 closed.\n" ] } ], @@ -900,7 +938,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "We see that the final top-1 accuracy is 84.19%, which is very close to the 84.22% reported on the [BNN-PYNQ accuracy table in Brevitas](https://github.com/Xilinx/brevitas/tree/master/brevitas_examples/bnn_pynq). " + "We see that the final top-1 accuracy is 84.19%, which is very close to the 84.22% reported on the [BNN-PYNQ accuracy table in Brevitas](https://github.com/Xilinx/brevitas/tree/master/src/brevitas_examples/bnn_pynq). " ] }, { @@ -927,7 +965,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.8" + "version": "3.8.5" } }, "nbformat": 4,