diff --git a/notebooks/end2end_example/tfc_end2end_example.ipynb b/notebooks/end2end_example/tfc_end2end_example.ipynb index 64a87571afcc52aa081344f9579f4ba74111a1a9..2f8e0207fb5856182ca77f6df03f3cef572eeaab 100644 --- a/notebooks/end2end_example/tfc_end2end_example.ipynb +++ b/notebooks/end2end_example/tfc_end2end_example.ipynb @@ -42,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -85,9 +85,18 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/workspace/brevitas_cnv_lfc/training_scripts/models/TFC.py:85: 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]).to(self.device)\n" + ] + } + ], "source": [ "import onnx\n", "from finn.util.test import get_test_model_trained\n", @@ -107,15 +116,13 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "\n", - "Stopping http://0.0.0.0:8081\n", "Serving '/workspace/finn/tfc_w1_a1.onnx' at http://0.0.0.0:8081\n" ] }, @@ -133,10 +140,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f186ccfbe10>" + "<IPython.lib.display.IFrame at 0x7f4310b476a0>" ] }, - "execution_count": 7, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" } @@ -154,7 +161,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -239,7 +246,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -266,7 +273,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -292,10 +299,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f186e386240>" + "<IPython.lib.display.IFrame at 0x7f43177c2a20>" ] }, - "execution_count": 10, + "execution_count": 6, "metadata": {}, "output_type": "execute_result" } @@ -316,7 +323,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -329,11 +336,14 @@ " def apply(self, model):\n", " streamline_transformations = [\n", " ConvertSubToAdd(),\n", + " ConvertDivToMul(),\n", " BatchNormToAffine(),\n", " ConvertSignToThres(),\n", " MoveAddPastMul(),\n", " MoveScalarAddPastMatMul(),\n", + " MoveScalarAddPastConv(),\n", " MoveScalarMulPastMatMul(),\n", + " MoveScalarMulPastConv(),\n", " MoveAddPastMul(),\n", " CollapseRepeatedAdd(),\n", " CollapseRepeatedMul(),\n", @@ -341,6 +351,7 @@ " FactorOutMulSignMagnitude(),\n", " AbsorbMulIntoMultiThreshold(),\n", " Absorb1BitMulIntoMatMul(),\n", + " Absorb1BitMulIntoConv(),\n", " RoundAndClipThresholds(),\n", " ]\n", " for trn in streamline_transformations:\n", @@ -369,7 +380,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -395,10 +406,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f186cd470b8>" + "<IPython.lib.display.IFrame at 0x7f431826d860>" ] }, - "execution_count": 12, + "execution_count": 8, "metadata": {}, "output_type": "execute_result" } @@ -423,7 +434,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -449,10 +460,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f17f04bbc18>" + "<IPython.lib.display.IFrame at 0x7f42977e39b0>" ] }, - "execution_count": 13, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -490,7 +501,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": { "scrolled": false }, @@ -518,10 +529,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f1868061eb8>" + "<IPython.lib.display.IFrame at 0x7f43177c73c8>" ] }, - "execution_count": 14, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -552,7 +563,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -578,10 +589,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f186cc55e48>" + "<IPython.lib.display.IFrame at 0x7f43177c2f60>" ] }, - "execution_count": 15, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -604,7 +615,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -613,7 +624,7 @@ "text": [ "\n", "Stopping http://0.0.0.0:8081\n", - "Serving '/tmp/finn_maltanar/dataflow_partition_h1c4i5gn/df_model.onnx' at http://0.0.0.0:8081\n" + "Serving '/tmp/finn_jakobap/dataflow_partition_sqcfkplo/df_model.onnx' at http://0.0.0.0:8081\n" ] }, { @@ -630,10 +641,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f17f04c70f0>" + "<IPython.lib.display.IFrame at 0x7f42977d4978>" ] }, - "execution_count": 16, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -654,7 +665,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ @@ -674,7 +685,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -708,7 +719,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -734,17 +745,24 @@ " 'noActivation': ('i', False, 0),\n", " 'inFIFODepth': ('i', False, 0),\n", " 'outFIFODepth': ('i', False, 0),\n", + " 'numInputVectors': ('ints', False, [1]),\n", + " 'mem_mode': ('s', False, 'const'),\n", " 'backend': ('s', True, 'fpgadataflow'),\n", " 'code_gen_dir_npysim': ('s', False, ''),\n", " 'code_gen_dir_ipgen': ('s', False, ''),\n", " 'executable_path': ('s', False, ''),\n", " 'ipgen_path': ('s', False, ''),\n", + " 'ip_path': ('s', False, ''),\n", + " 'ip_vlnv': ('s', False, ''),\n", " 'exec_mode': ('s', False, ''),\n", " 'sim_cycles': ('i', False, 0),\n", - " 'rtlsim_trace': ('s', False, '')}" + " 'rtlsim_trace': ('s', False, ''),\n", + " 'res_estimate': ('s', False, ''),\n", + " 'res_hls': ('s', False, ''),\n", + " 'res_synth': ('s', False, '')}" ] }, - "execution_count": 19, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -770,7 +788,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 16, "metadata": {}, "outputs": [], "source": [ @@ -804,7 +822,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -830,10 +848,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f1868061d30>" + "<IPython.lib.display.IFrame at 0x7f43177c7518>" ] }, - "execution_count": 21, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -866,14 +884,14 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "dict_keys(['Ultra96', 'Pynq-Z1'])\n" + "dict_keys(['Ultra96', 'Pynq-Z1', 'Pynq-Z2', 'ZCU104'])\n" ] } ], @@ -885,12 +903,12 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "# change this if you have a different PYNQ board, see list above\n", - "pynq_board = \"Ultra96\"\n", + "pynq_board = \"Pynq-Z1\"\n", "fpga_part = pynq_part_map[pynq_board]\n", "target_clk_ns = 5" ] @@ -916,7 +934,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -938,7 +956,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 22, "metadata": {}, "outputs": [], "source": [ @@ -957,7 +975,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -983,10 +1001,10 @@ " " ], "text/plain": [ - "<IPython.lib.display.IFrame at 0x7f17f04c9470>" + "<IPython.lib.display.IFrame at 0x7f42977edf60>" ] }, - "execution_count": 26, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -1008,7 +1026,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -1037,7 +1055,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -1045,8 +1063,8 @@ "output_type": "stream", "text": [ "#!/bin/bash \r\n", - "cd /tmp/finn_maltanar/code_gen_ipgen_StreamingFCLayer_Batch_5f0hmok_\r\n", - "vivado_hls /tmp/finn_maltanar/code_gen_ipgen_StreamingFCLayer_Batch_5f0hmok_/hls_syn_StreamingFCLayer_Batch_0.tcl\r\n", + "cd /tmp/finn_jakobap/code_gen_ipgen_StreamingFCLayer_Batch_0_pfp8r_i6\r\n", + "vivado_hls /tmp/finn_jakobap/code_gen_ipgen_StreamingFCLayer_Batch_0_pfp8r_i6/hls_syn_StreamingFCLayer_Batch_0.tcl\r\n", "cd /workspace/finn\r\n" ] } @@ -1067,7 +1085,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -1077,9 +1095,9 @@ "\r\n", "set config_proj_name project_StreamingFCLayer_Batch_0\r\n", "puts \"HLS project: $config_proj_name\"\r\n", - "set config_hwsrcdir \"/tmp/finn_maltanar/code_gen_ipgen_StreamingFCLayer_Batch_5f0hmok_\"\r\n", + "set config_hwsrcdir \"/tmp/finn_jakobap/code_gen_ipgen_StreamingFCLayer_Batch_0_pfp8r_i6\"\r\n", "puts \"HW source dir: $config_hwsrcdir\"\r\n", - "set config_proj_part \"xczu3eg-sbva484-1-e\"\r\n", + "set config_proj_part \"xc7z020clg400-1\"\r\n", "\r\n", "set config_bnnlibdir \"/workspace/finn-hlslib\"\r\n", "\r\n", @@ -1128,7 +1146,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 27, "metadata": {}, "outputs": [], "source": [ @@ -1148,22 +1166,22 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[key: \"vivado_stitch_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j\"\n", ", key: \"vivado_stitch_vlnv\"\n", "value: \"xilinx_finn:finn:finn_design:1.0\"\n", ", key: \"wrapper_filename\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", "]" ] }, - "execution_count": 31, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -1174,16 +1192,16 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 29, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "'/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo'" + "'/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j'" ] }, - "execution_count": 32, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } @@ -1208,7 +1226,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -1248,7 +1266,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 31, "metadata": { "scrolled": true }, @@ -1257,17 +1275,19 @@ "data": { "text/plain": [ "[key: \"vivado_stitch_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j\"\n", ", key: \"vivado_stitch_vlnv\"\n", "value: \"xilinx_finn:finn:finn_design:1.0\"\n", ", key: \"wrapper_filename\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", ", key: \"vivado_pynq_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_pynq_proj_hq9mfroo\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j\"\n", + ", key: \"vivado_synth_rpt\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j/synth_report.xml\"\n", "]" ] }, - "execution_count": 34, + "execution_count": 31, "metadata": {}, "output_type": "execute_result" } @@ -1281,7 +1301,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 32, "metadata": {}, "outputs": [ { @@ -1307,7 +1327,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 33, "metadata": {}, "outputs": [], "source": [ @@ -1330,26 +1350,30 @@ }, { "cell_type": "code", - "execution_count": 37, - "metadata": {}, + "execution_count": 34, + "metadata": { + "scrolled": true + }, "outputs": [ { "data": { "text/plain": [ "[key: \"vivado_stitch_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j\"\n", ", key: \"vivado_stitch_vlnv\"\n", "value: \"xilinx_finn:finn:finn_design:1.0\"\n", ", key: \"wrapper_filename\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", ", key: \"vivado_pynq_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_pynq_proj_hq9mfroo\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j\"\n", + ", key: \"vivado_synth_rpt\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j/synth_report.xml\"\n", ", key: \"vivado_pynq_bitfile\"\n", - "value: \"/tmp/finn_maltanar/vivado_pynq_proj_hq9mfroo/resizer.bit\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j/resizer.bit\"\n", "]" ] }, - "execution_count": 37, + "execution_count": 34, "metadata": {}, "output_type": "execute_result" } @@ -1363,7 +1387,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 35, "metadata": {}, "outputs": [], "source": [ @@ -1381,7 +1405,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -1399,74 +1423,131 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 44, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "\r\n", + "import argparse\r\n", "\r\n", "from pynq import Overlay\r\n", "import numpy as np\r\n", "from pynq import allocate\r\n", + "import time\r\n", "from finn.util.data_packing import (\r\n", " finnpy_to_packed_bytearray,\r\n", " packed_bytearray_to_finnpy\r\n", ")\r\n", "from finn.core.datatype import DataType\r\n", "\r\n", - "bitfile_path = \"resizer.bit\"\r\n", - "ol = Overlay(bitfile_path)\r\n", - "dma=ol.axi_dma_0\r\n", + "def load_input(N):\r\n", + " ishape_normal = (N, 784)\r\n", + " # load desired input .npy file\r\n", + " ibuf_normal = np.load(\"input.npy\")\r\n", + " # ensure that shape is as expected\r\n", + " assert ibuf_normal.shape == ishape_normal\r\n", + " return ibuf_normal\r\n", "\r\n", - "# declare input/output types and shapes for the accelerator\r\n", - "# input FINN DataType\r\n", - "idt = DataType.BINARY\r\n", - "# normal, folded and packed input shapes\r\n", - "ishape_normal = (1, 784)\r\n", - "ishape_folded = (1, 49, 16)\r\n", - "ishape_packed = (1, 49, 2)\r\n", - "# output FINN DataType\r\n", - "odt = DataType.UINT32\r\n", - "# normal, folded and packed output shapes\r\n", - "oshape_normal = (1, 10)\r\n", - "oshape_folded = (1, 1, 10)\r\n", - "oshape_packed = (1, 1, 40)\r\n", + "def pack_input(ibuf_normal, N):\r\n", + " # input FINN DataType\r\n", + " idt = DataType.BINARY\r\n", + " ishape_folded = (N, 49, 16)\r\n", + " # convert to folded form\r\n", + " ibuf_folded = ibuf_normal.reshape(ishape_folded)\r\n", + " # pack the input buffer, reversing both SIMD dim and endianness\r\n", + " ibuf_packed = finnpy_to_packed_bytearray(\r\n", + " ibuf_folded, idt, reverse_endian=True, reverse_inner=True\r\n", + " )\r\n", + " return ibuf_packed\r\n", "\r\n", - "# load desired input .npy file\r\n", - "ibuf_normal = np.load(\"input.npy\")\r\n", - "# ensure that shape is as expected\r\n", - "assert ibuf_normal.shape == ishape_normal\r\n", - "# convert to folded form\r\n", - "ibuf_folded = ibuf_normal.reshape(ishape_folded)\r\n", + "def unpack_output(obuf_packed, N):\r\n", + " # output FINN DataType\r\n", + " odt = DataType.UINT32\r\n", + " oshape_folded = (N, 1, 10)\r\n", + " # unpack the packed output buffer from accelerator\r\n", + " obuf_folded = packed_bytearray_to_finnpy(\r\n", + " obuf_packed, odt, oshape_folded, reverse_endian=True, reverse_inner=True\r\n", + " )\r\n", + " return obuf_folded\r\n", "\r\n", - "# pack the input buffer, reversing both SIMD dim and endianness\r\n", - "ibuf_packed = finnpy_to_packed_bytearray(\r\n", - " ibuf_folded, idt, reverse_endian=True, reverse_inner=True\r\n", - ")\r\n", - "# allocate a PYNQ buffer for the packed input buffer\r\n", - "ibuf_packed_device = allocate(shape=ishape_packed, dtype=np.uint8)\r\n", - "# copy the packed data into the PYNQ buffer\r\n", - "# TODO optimization: pack directly into the PYNQ buffer?\r\n", - "np.copyto(ibuf_packed_device, ibuf_packed)\r\n", + "def save_output(obuf_folded, N):\r\n", + " # convert to normal reshape and save\r\n", + " oshape_normal = (N, 10)\r\n", + " obuf_normal = obuf_folded.reshape(oshape_normal)\r\n", + " np.save(\"output.npy\", obuf_normal)\r\n", "\r\n", - "# allocate a PYNQ buffer for the returned packed output buffer\r\n", - "obuf_packed = allocate(shape=oshape_packed, dtype=np.uint8)\r\n", + "if __name__ == \"__main__\":\r\n", + " parser = argparse.ArgumentParser(description='Please select functional verification (\"remote_pynq\") or throughput test (\"throughput_test\")')\r\n", + " parser.add_argument('exec_mode', help='metadata prop exec_mode as string')\r\n", + " args = parser.parse_args()\r\n", + " exec_mode = args.exec_mode\r\n", "\r\n", - "# set up the DMA and wait until all transfers complete\r\n", - "dma.sendchannel.transfer(ibuf_packed_device)\r\n", - "dma.recvchannel.transfer(obuf_packed)\r\n", - "dma.sendchannel.wait()\r\n", - "dma.recvchannel.wait()\r\n", + " bitfile_path = \"resizer.bit\"\r\n", + " ol = Overlay(bitfile_path)\r\n", + " dma=ol.axi_dma_0\r\n", + " ctrl_regs=ol.resize_accel_0\r\n", + " # AXI lite register offset for number of iterations\r\n", + " # used by TLastMarker to signal end of transmission for AXI CDMA\r\n", + " REG_OFFSET_NUM_ITERS = 0x10\r\n", "\r\n", - "# unpack the packed output buffer from accelerator\r\n", - "obuf_folded = packed_bytearray_to_finnpy(\r\n", - " obuf_packed, odt, oshape_folded, reverse_endian=True, reverse_inner=True\r\n", - ")\r\n", - "# convert to normal reshape and save\r\n", - "obuf_normal = obuf_folded.reshape(oshape_normal)\r\n", - "np.save(\"output.npy\", obuf_normal)\r\n" + " # number of samples for inference\r\n", + " if exec_mode == \"remote_pynq\":\r\n", + " N = 1\r\n", + " elif exec_mode == \"throughput_test\":\r\n", + " res={}\r\n", + " N = 1000\r\n", + " else:\r\n", + " raise Exception(\"Exec mode has to be set to remote_pynq or throughput_test\")\r\n", + "\r\n", + " # declare input/output types and shapes for the accelerator\r\n", + " ishape_packed = (N, 49, 2)\r\n", + " oshape_packed = (N, 1, 40)\r\n", + " \r\n", + " if exec_mode == \"remote_pynq\":\r\n", + " ibuf_normal = load_input(N)\r\n", + " ibuf_packed = pack_input(ibuf_normal, N)\r\n", + " elif exec_mode == \"throughput_test\":\r\n", + " ibuf_packed = np.asarray(np.random.uniform(low=0, high=1, size=tuple(ishape_packed)), dtype=np.uint8)\r\n", + "\r\n", + " # set up TLastMarker with correct num. samples\r\n", + " ctrl_regs.write(REG_OFFSET_NUM_ITERS, N)\r\n", + "\r\n", + " # allocate a PYNQ buffer for the packed input buffer\r\n", + " ibuf_packed_device = allocate(shape=ishape_packed, dtype=np.uint8)\r\n", + " # copy the packed data into the PYNQ buffer\r\n", + " # TODO optimization: pack directly into the PYNQ buffer?\r\n", + " np.copyto(ibuf_packed_device, ibuf_packed)\r\n", + "\r\n", + " # allocate a PYNQ buffer for the returned packed output buffer\r\n", + " obuf_packed = allocate(shape=oshape_packed, dtype=np.uint8)\r\n", + "\r\n", + " if exec_mode == \"throughput_test\":\r\n", + " # measure runtime of network\r\n", + " start = time.time()\r\n", + "\r\n", + " # set up the DMA and wait until all transfers complete\r\n", + " dma.sendchannel.transfer(ibuf_packed_device)\r\n", + " dma.recvchannel.transfer(obuf_packed)\r\n", + " dma.sendchannel.wait()\r\n", + " dma.recvchannel.wait()\r\n", + "\r\n", + "\r\n", + " if exec_mode == \"throughput_test\":\r\n", + " end = time.time()\r\n", + " runtime = end - start\r\n", + " res[\"runtime[ms]\"] = runtime*1000\r\n", + " res[\"throughput[images/s]\"] = N / runtime\r\n", + " file = open(\"nw_metrics.txt\", \"w\")\r\n", + " file.write(str(res))\r\n", + " file.close()\r\n", + "\r\n", + " else:\r\n", + " obuf_folded = unpack_output(obuf_packed, N)\r\n", + " save_output(obuf_folded, N)\r\n", + "\r\n" ] } ], @@ -1493,16 +1574,17 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 57, "metadata": {}, "outputs": [], "source": [ "from finn.transformation.fpgadataflow.make_deployment import DeployToPYNQ\n", - "ip = \"192.168.3.1\"\n", + "ip = \"51.37.26.64\"\n", + "port = \"23\"\n", "username = \"xilinx\"\n", - "password = \"xilinx\"\n", + "password = \"x1l1nx_f1nn\"\n", "target_dir = \"/home/xilinx/finn_tfc_end2end_example\"\n", - "model = model.transform(DeployToPYNQ(ip, username, password, target_dir))\n", + "model = model.transform(DeployToPYNQ(ip, port, username, password, target_dir))\n", "model.save(build_dir + \"/tfc_w1_a1_pynq_deploy.onnx\")" ] }, @@ -1515,42 +1597,46 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 58, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "[key: \"vivado_stitch_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j\"\n", ", key: \"vivado_stitch_vlnv\"\n", "value: \"xilinx_finn:finn:finn_design:1.0\"\n", ", key: \"wrapper_filename\"\n", - "value: \"/tmp/finn_maltanar/vivado_stitch_proj_oo2lpoeo/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", + "value: \"/tmp/finn_jakobap/vivado_stitch_proj_tqp4ib4j/finn_vivado_stitch_proj.srcs/sources_1/bd/finn_design/hdl/finn_design_wrapper.v\"\n", ", key: \"vivado_pynq_proj\"\n", - "value: \"/tmp/finn_maltanar/vivado_pynq_proj_hq9mfroo\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j\"\n", + ", key: \"vivado_synth_rpt\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j/synth_report.xml\"\n", ", key: \"vivado_pynq_bitfile\"\n", - "value: \"/tmp/finn_maltanar/vivado_pynq_proj_hq9mfroo/resizer.bit\"\n", + "value: \"/tmp/finn_jakobap/vivado_pynq_proj_gkwfg31j/resizer.bit\"\n", ", key: \"pynq_driver_dir\"\n", - "value: \"/tmp/finn_maltanar/pynq_driver_25t8u9sd\"\n", + "value: \"/tmp/finn_jakobap/pynq_driver_1r1_0kz6\"\n", ", key: \"pynq_ip\"\n", - "value: \"192.168.3.1\"\n", + "value: \"51.37.26.64\"\n", + ", key: \"pynq_port\"\n", + "value: \"23\"\n", ", key: \"pynq_username\"\n", "value: \"xilinx\"\n", ", key: \"pynq_password\"\n", - "value: \"xilinx\"\n", + "value: \"x1l1nx_f1nn\"\n", ", key: \"pynq_target_dir\"\n", "value: \"/home/xilinx/finn_tfc_end2end_example\"\n", ", key: \"pynq_deployment_dir\"\n", - "value: \"/tmp/finn_maltanar/pynq_deployment_mpyziv7h\"\n", + "value: \"/tmp/finn_jakobap/pynq_deployment_kvurnk0c\"\n", ", key: \"pynq_deploy_dir\"\n", - "value: \"/tmp/finn_maltanar/pynq_deployment_mpyziv7h\"\n", + "value: \"/tmp/finn_jakobap/pynq_deployment_kvurnk0c\"\n", ", key: \"exec_mode\"\n", "value: \"remote_pynq\"\n", "]" ] }, - "execution_count": 42, + "execution_count": 58, "metadata": {}, "output_type": "execute_result" } @@ -1561,34 +1647,23 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 59, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "/home/xilinx/finn_tfc_end2end_example/pynq_deployment_1oyo7x66:\r\n", - "total 5820\r\n", - "-rw-r--r-- 1 xilinx xilinx 1934 Feb 13 13:36 driver.py\r\n", - "drwxr-xr-x 4 xilinx xilinx 4096 Feb 13 13:36 finn\r\n", - "-rw-r--r-- 1 xilinx xilinx 3264 Feb 13 14:24 input.npy\r\n", - "-rw-r--r-- 1 root root 120 Feb 13 14:24 output.npy\r\n", - "-rw-r--r-- 1 xilinx xilinx 5568787 Feb 13 13:36 resizer.bit\r\n", - "-rw-r--r-- 1 xilinx xilinx 368173 Feb 13 13:36 resizer.hwh\r\n", - "-rw-r--r-- 1 root root 32 Feb 13 14:24 sds_trace_data.dat\r\n", - "\r\n", - "/home/xilinx/finn_tfc_end2end_example/pynq_deployment_mpyziv7h:\r\n", - "total 5808\r\n", - "-rw-r--r-- 1 xilinx xilinx 1934 Feb 28 16:09 driver.py\r\n", - "drwxr-xr-x 4 xilinx xilinx 4096 Feb 28 16:09 finn\r\n", - "-rw-r--r-- 1 xilinx xilinx 5568787 Feb 28 16:09 resizer.bit\r\n", - "-rw-r--r-- 1 xilinx xilinx 368173 Feb 28 16:09 resizer.hwh\r\n" + "total 4284\r\n", + "-rw-r--r-- 1 xilinx xilinx 3861 Apr 27 12:36 driver.py\r\n", + "drwxr-xr-x 4 xilinx xilinx 4096 Apr 27 12:37 finn\r\n", + "-rw-r--r-- 1 xilinx xilinx 4045675 Apr 27 12:36 resizer.bit\r\n", + "-rw-r--r-- 1 xilinx xilinx 329531 Apr 27 12:36 resizer.hwh\r\n" ] } ], "source": [ - "! sshpass -p {password} ssh {username}@{ip} 'ls -l {target_dir}/*'" + "! sshpass -p {password} ssh {username}@{ip} -p {port} 'ls -l {target_dir}/*'" ] }, { @@ -1600,16 +1675,16 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 60, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "<matplotlib.image.AxesImage at 0x7f17e0a82e10>" + "<matplotlib.image.AxesImage at 0x7f4277550ef0>" ] }, - "execution_count": 44, + "execution_count": 60, "metadata": {}, "output_type": "execute_result" } @@ -1633,7 +1708,7 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 61, "metadata": {}, "outputs": [], "source": [ @@ -1653,7 +1728,7 @@ }, { "cell_type": "code", - "execution_count": 48, + "execution_count": 62, "metadata": {}, "outputs": [], "source": [ @@ -1675,7 +1750,7 @@ }, { "cell_type": "code", - "execution_count": 49, + "execution_count": 63, "metadata": {}, "outputs": [ { @@ -1684,13 +1759,13 @@ "<BarContainer object of 10 artists>" ] }, - "execution_count": 49, + "execution_count": 63, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "<Figure size 432x288 with 1 Axes>" ] @@ -1720,6 +1795,37 @@ "We see that the network correctly predicts this as a digit 2 with high probability. This concludes our tutorial on how to take a simple fully-connected BNN all the way down to hardware with FINN, and execute it remotely on a PYNQ board." ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Throughput Test on PYNQ Board <a id='throughput'></a>\n", + "In addition to the functional verification, FINN also offers the possibility to measure the network performance directly on the PYNQ board. This can be done using the core function `throughput_test`. In the next section we import the function and execute it.\n", + "First we extract the `remote_exec_model` again and pass it to the function. The function returns the metrics of the network as dictionary." + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Network metrics: \n", + "{'runtime[ms]': 3.5953521728515625, 'throughput[images/s]': 278136.8700265252}\n" + ] + } + ], + "source": [ + "from finn.core.throughput_test import throughput_test\n", + "\n", + "child_model = ModelWrapper(getCustomOp(sdp_node).get_nodeattr(\"model\"))\n", + "res = throughput_test(child_model)\n", + "print(\"Network metrics: \\n\" + str(res))" + ] + }, { "cell_type": "code", "execution_count": null,