diff --git a/build/gtsrb/build.py b/build/gtsrb/build.py new file mode 100644 index 0000000..9b470e6 --- /dev/null +++ b/build/gtsrb/build.py @@ -0,0 +1,125 @@ +# Copyright (C) 2024, Advanced Micro Devices, Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * Neither the name of FINN nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# 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 finn.builder.build_dataflow as build +import finn.builder.build_dataflow_config as build_cfg +from finn.builder.build_dataflow_config import default_build_dataflow_steps +from qonnx.core.datatype import DataType +import os +import shutil +import numpy as np +from onnx import helper as oh + +models = [ + "cnv_1w1a_gtsrb", +] + +# which platforms to build the networks for +zynq_platforms = ["Pynq-Z1"] +platforms_to_build = zynq_platforms + + +def custom_step_add_preproc(model, cfg): + # GTSRB data with raw uint8 pixels is divided by 255 prior to training + # reflect this in the inference graph so we can perform inference directly + # on raw uint8 data + in_name = model.graph.input[0].name + new_in_name = model.make_new_valueinfo_name() + new_param_name = model.make_new_valueinfo_name() + div_param = np.asarray(255.0, dtype=np.float32) + new_div = oh.make_node( + "Div", + [in_name, new_param_name], + [new_in_name], + name="PreprocDiv", + ) + model.set_initializer(new_param_name, div_param) + model.graph.node.insert(0, new_div) + model.graph.node[1].input[0] = new_in_name + # set input dtype to uint8 + model.set_tensor_datatype(in_name, DataType["UINT8"]) + return model + + +custom_build_steps = [custom_step_add_preproc] + default_build_dataflow_steps + + +# determine which shell flow to use for a given platform +def platform_to_shell(platform): + if platform in zynq_platforms: + return build_cfg.ShellFlowType.VIVADO_ZYNQ + else: + raise Exception("Unknown platform, can't determine ShellFlowType") + + +# create a release dir, used for finn-examples release packaging +os.makedirs("release", exist_ok=True) + +for platform_name in platforms_to_build: + shell_flow_type = platform_to_shell(platform_name) + vitis_platform = None + # for Zynq, use the board name as the release name + # e.g. ZCU104 + release_platform_name = platform_name + platform_dir = "release/%s" % release_platform_name + os.makedirs(platform_dir, exist_ok=True) + for model_name in models: + # set up the build configuration for this model + cfg = build_cfg.DataflowBuildConfig( + output_dir="output_%s_%s" % (model_name, release_platform_name), + target_fps=3000, + synth_clk_period_ns=10.0, + board=platform_name, + steps=custom_build_steps, + folding_config_file="folding_config/cnv_gtsrb_folding_config.json", + shell_flow_type=shell_flow_type, + vitis_platform=vitis_platform, + generate_outputs=[ + build_cfg.DataflowOutputType.ESTIMATE_REPORTS, + build_cfg.DataflowOutputType.STITCHED_IP, + build_cfg.DataflowOutputType.RTLSIM_PERFORMANCE, + build_cfg.DataflowOutputType.BITFILE, + ], + save_intermediate_models=True, + default_swg_exception=True, + ) + model_file = "models/%s.onnx" % model_name + # launch FINN compiler to build + build.build_dataflow_cfg(model_file, cfg) + # copy bitfiles into release dir if found + bitfile_gen_dir = cfg.output_dir + "/bitfile" + files_to_check_and_copy = [ + "finn-accel.bit", + "finn-accel.hwh", + "finn-accel.xclbin", + ] + for f in files_to_check_and_copy: + src_file = bitfile_gen_dir + "/" + f + dst_file = platform_dir + "/" + f.replace("finn-accel", model_name) + if os.path.isfile(src_file): + shutil.copy(src_file, dst_file) diff --git a/build/gtsrb/folding_config/cnv_gtsrb_folding_config.json b/build/gtsrb/folding_config/cnv_gtsrb_folding_config.json new file mode 100644 index 0000000..d96d432 --- /dev/null +++ b/build/gtsrb/folding_config/cnv_gtsrb_folding_config.json @@ -0,0 +1,78 @@ +{ + "Defaults": {}, + "Thresholding_rtl_0": { + "PE": 1 + }, + "ConvolutionInputGenerator_rtl_0": { + "SIMD": 3, + "ram_style": "distributed" + }, + "MVAU_hls_0": { + "PE": 16, + "SIMD": 3, + "ram_style": "auto" + }, + "ConvolutionInputGenerator_rtl_1": { + "SIMD": 32, + "ram_style": "distributed" + }, + "MVAU_hls_1": { + "PE": 32, + "SIMD": 32, + "ram_style": "auto" + }, + "ConvolutionInputGenerator_rtl_2": { + "SIMD": 32, + "ram_style": "distributed" + }, + "MVAU_hls_2": { + "PE": 16, + "SIMD": 32, + "ram_style": "auto" + }, + "ConvolutionInputGenerator_rtl_3": { + "SIMD": 32, + "ram_style": "distributed" + }, + "MVAU_hls_3": { + "PE": 16, + "SIMD": 32, + "ram_style": "auto" + }, + "ConvolutionInputGenerator_rtl_4": { + "SIMD": 32, + "ram_style": "distributed" + }, + "MVAU_hls_4": { + "PE": 4, + "SIMD": 32, + "ram_style": "auto" + }, + "ConvolutionInputGenerator_rtl_5": { + "SIMD": 32, + "ram_style": "distributed" + }, + "MVAU_hls_5": { + "PE": 1, + "SIMD": 32, + "ram_style": "auto" + }, + "MVAU_hls_6": { + "PE": 1, + "SIMD": 4, + "ram_style": "auto" + }, + "MVAU_hls_7": { + "PE": 1, + "SIMD": 8, + "ram_style": "auto" + }, + "MVAU_hls_8": { + "PE": 4, + "SIMD": 1, + "ram_style": "auto" + }, + "LabelSelect_hls_0": { + "PE": 1 + } +} diff --git a/build/gtsrb/models/download-model.sh b/build/gtsrb/models/download-model.sh new file mode 100644 index 0000000..79359df --- /dev/null +++ b/build/gtsrb/models/download-model.sh @@ -0,0 +1,2 @@ +#!/bin/bash +wget https://github.com/fastmachinelearning/qonnx_model_zoo/raw/feature/gtsrb_cnv/models/GTSRB/Brevitas_CNV1W1A/cnv_1w1a_gtsrb.onnx \ No newline at end of file diff --git a/ci/Jenkinsfile b/ci/Jenkinsfile index 60ac21d..1219b35 100644 --- a/ci/Jenkinsfile +++ b/ci/Jenkinsfile @@ -23,7 +23,8 @@ pipeline { "kws", "mobilenet-v1", "resnet50", - "vgg10-radioml"] + "vgg10-radioml", + "gtsrb"] createParallelBuilds(buildList) createReleaseArea(buildList) } diff --git a/finn_examples/models.py b/finn_examples/models.py index 8076124..c22e190 100644 --- a/finn_examples/models.py +++ b/finn_examples/models.py @@ -67,6 +67,17 @@ "num_outputs": 1, } +_gtsrb_cnv_io_shape_dict = { + "idt": DataType["UINT8"], + "odt": DataType["INT16"], + "ishape_normal": (1, 32, 32, 3), + "oshape_normal": (1, 44), + "ishape_folded": (1, 1, 32, 32, 3, 1), + "oshape_folded": (1, 11, 4), + "ishape_packed": (1, 1, 32, 32, 3, 1), + "oshape_packed": (1, 11, 8), +} + _bincop_cnv_io_shape_dict = { "idt": [DataType["UINT8"]], "odt": [DataType["UINT8"]], @@ -352,7 +363,6 @@ def resnet50_w1a2_imagenet(target_platform=None): runtime_weight_dir=runtime_weight_dir, ) - def vgg10_w4a4_radioml(target_platform=None): target_platform = resolve_target_platform(target_platform) driver_mode = get_driver_mode() @@ -366,7 +376,6 @@ def vgg10_w4a4_radioml(target_platform=None): fclk_mhz=fclk_mhz, ) - def mlp_w2a2_unsw_nb15(target_platform=None): target_platform = resolve_target_platform(target_platform) driver_mode = get_driver_mode() @@ -376,3 +385,10 @@ def mlp_w2a2_unsw_nb15(target_platform=None): return FINNExampleOverlay( filename, driver_mode, _unsw_nb15_mlp_io_shape_dict, fclk_mhz=fclk_mhz ) + +def cnv_w1a1_gtsrb(target_platform=None): + target_platform = resolve_target_platform(target_platform) + driver_mode = get_driver_mode() + model_name = "cnv-gtsrb-w1a1" + filename = find_bitfile(model_name, target_platform) + return FINNExampleOverlay(filename, driver_mode, _gtsrb_cnv_io_shape_dict) \ No newline at end of file diff --git a/finn_examples/notebooks/6_traffic_sign_recognition_gtsrb.ipynb b/finn_examples/notebooks/6_traffic_sign_recognition_gtsrb.ipynb new file mode 100644 index 0000000..f512b3e --- /dev/null +++ b/finn_examples/notebooks/6_traffic_sign_recognition_gtsrb.ipynb @@ -0,0 +1,441 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Initialize the accelerator" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "application/javascript": [ + "\n", + "try {\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%microblaze/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n", + "} catch (e) {};\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "\n", + "try {\n", + "require(['notebook/js/codecell'], function(codecell) {\n", + " codecell.CodeCell.options_default.highlight_modes[\n", + " 'magic_text/x-csrc'] = {'reg':[/^%%pybind11/]};\n", + " Jupyter.notebook.events.one('kernel_ready.Kernel', function(){\n", + " Jupyter.notebook.get_cells().map(function(cell){\n", + " if (cell.cell_type == 'code'){ cell.auto_highlight(); } }) ;\n", + " });\n", + "});\n", + "} catch (e) {};\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "from finn_examples import models\n", + "accel = models.cnv_w1a1_gtsrb()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Expected input shape and datatype: (1, 32, 32, 3) UINT8\n", + "Expected output shape and datatype: (1, 44) INT16\n" + ] + } + ], + "source": [ + "print(\"Expected input shape and datatype: %s %s\" % (str(accel.ishape_normal), str(accel.idt)))\n", + "print(\"Expected output shape and datatype: %s %s\" % (str(accel.oshape_normal), str(accel.odt)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Load the GTSRB dataset" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "from os import path\n", + "import urllib\n", + "import numpy as np\n", + "dataset_local = \"/tmp/traffic-signs-data.zip\"\n", + "if not path.isfile(dataset_local):\n", + " dataset_url = \"https://d17h27t6h515a5.cloudfront.net/topher/2017/February/5898cd6f_traffic-signs-data/traffic-signs-data.zip\"\n", + " urllib.request.urlretrieve(dataset_url, dataset_local)\n", + " ! unzip {dataset_local} -d /tmp\n", + "\n", + "dataset_dict = np.load(\"/tmp/test.p\")\n", + "testx = dataset_dict[\"features\"]\n", + "testy = dataset_dict[\"labels\"]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "gtsrb_classes = [\n", + " '20 Km/h', \n", + " '30 Km/h', \n", + " '50 Km/h', \n", + " '60 Km/h', \n", + " '70 Km/h', \n", + " '80 Km/h', \n", + " 'End 80 Km/h', \n", + " '100 Km/h', \n", + " '120 Km/h', \n", + " 'No overtaking', \n", + " 'No overtaking for large trucks', \n", + " 'Priority crossroad', \n", + " 'Priority road', \n", + " 'Give way', \n", + " 'Stop', \n", + " 'No vehicles', \n", + " 'Prohibited for vehicles with a permitted gross weight over 3.5t including their trailers, and for tractors except passenger cars and buses', \n", + " 'No entry for vehicular traffic', \n", + " 'Danger Ahead', \n", + " 'Bend to left', \n", + " 'Bend to right', \n", + " 'Double bend (first to left)', \n", + " 'Uneven road', \n", + " 'Road slippery when wet or dirty', \n", + " 'Road narrows (right)', \n", + " 'Road works', \n", + " 'Traffic signals', \n", + " 'Pedestrians in road ahead', \n", + " 'Children crossing ahead', \n", + " 'Bicycles prohibited', \n", + " 'Risk of snow or ice', \n", + " 'Wild animals', \n", + " 'End of all speed and overtaking restrictions', \n", + " 'Turn right ahead', \n", + " 'Turn left ahead', \n", + " 'Ahead only', \n", + " 'Ahead or right only', \n", + " 'Ahead or left only', \n", + " 'Pass by on right', \n", + " 'Pass by on left', \n", + " 'Roundabout', \n", + " 'End of no-overtaking zone', \n", + " 'End of no-overtaking zone for vehicles with a permitted gross weight over 3.5t including their trailers, and for tractors except passenger cars and buses', \n", + " 'Not a roadsign'\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Dataset shape is (12630, 32, 32, 3)\n" + ] + } + ], + "source": [ + "print(\"Dataset shape is \" + str(testx.shape))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Classify a single image" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "test_single_x = testx[0]\n", + "test_single_y = testy[0]" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAP8AAAD8CAYAAAC4nHJkAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvAOZPmwAAHRlJREFUeJztnVuMXNd1pv91TlU1+8Jbs0mqeRGpmy1rZJmSO4pvMewECRTDgOzBwLAfDD0YYTCIgRjIPAgeYOwB5sGZiW34IXBAj4QoA8eX+AIrE2NiR/CMknFGFmVJlChaskSREqkmmxS7ye5ms7vrnDUPVXRa9PlXF/tSTWX/H0Cweq/aZ+/addY5VfuvtZa5O4QQ6ZGt9QSEEGuDnF+IRJHzC5Eocn4hEkXOL0SiyPmFSBQ5vxCJIucXIlHk/EIkSm05nc3sHgBfAZAD+O/u/oXo+b39G3zj4LZq45J+aWiBrYu/XPQyMHKbZXV+yHjAwLSE123BOvp80DG6d7BjRmMFJi+WMBY/ZHTmhPMIjM0mX6s8565Gjxm8L2VRvR7TkxOYnZkOX95lluz8ZpYD+HMAvwvgBIDHzexhd3+O9dk4uA2f/OP/Vm0s+ZubkUVw5MEMm9RSBmN5eHKSN6mcC+ZxkVp6erdTW+HBG1/y1+blTGV7Frwss15qa86forbM1lFbSd6b3Bp8IgWf5Pz8BT5Wyc+Dsqy+QGXGndgLfsGeL3i/iYnXqG3DhiFqaxbV76f3cPecmhivbP+H7/wF7XMly/nYfzeAF939qLvPAfgmgHuXcTwhRBdZjvPvBPDqgr9PtNuEEG8CVn3Dz8z2m9lBMzt4cYp/dBNCdJflOP9JALsX/L2r3fYG3P2Au4+4+0jfwIZlDCeEWEmW4/yPA7jFzG4wswaAjwN4eGWmJYRYbZa82+/uTTP7NIC/R0vqe9DdDy/aLyfXm2iTnez2l2SXtNWJ7+jXavxlF01+zIJsmefBMhoGqA3Od6kjxS6PrtlZ9Q58qGIEMlTNruP9Sr4rnjOFxvhrthp/XX29XJGwQBIrvPqYHkmwxucRvddbd+6mtrn54FzNqudigSq1fbD6ffnHHq7AXMmydH53/yGAHy7nGEKItUG/8BMiUeT8QiSKnF+IRJHzC5Eocn4hEmVZu/1LIWMRcEHkSUEkj1oQ12PBSyuC4AzL+EFrdIpBkEgYoBMEMwX9oiA8FgQVvGQaIdYejVuCtSrJ+2xBBKTlgfQZyG9RoFNOAnjK4OTJAjmyLIP1COTDLDi/mfyZBetREnlwkXjFNx6/42cKIf5VIecXIlHk/EIkipxfiESR8wuRKF3d7TcAGdkZjwJPMpY9KwjsybMePo9gxzlfQhavIOtTGEASBe9kwWW5GWzdO3lt5fws7VPOBbaCpyjLLNjdJsFTeY2n8crq/D1DjQf2hPIHs5XBGkYpviJlJ7BFwUJG+kXn6ZJyJF6B7vxCJIqcX4hEkfMLkShyfiESRc4vRKLI+YVIlK5Kfe5OZap6HgS5kEtUAV7uqhmoJPVAz1tKkEsUCNIMcgIy2RMA5qd5pZ9L56urtQDA+dFXK9vHT75E+0xN/FrS5V/RnJ+mNgSSWF6vftO2bdtB++zc+2+obWDrHj7WBp4V2tdV26Lzw5i2jEUqm4Vlw7hkyoKg8kCOzOtEMu1c6dOdX4hUkfMLkShyfiESRc4vRKLI+YVIFDm/EImyLKnPzI4BmARQAGi6+0jcgafq8yjnXrNafnOax4zn/WtNI8gjF8o1JB9cM5BxZnnE3JmxM9R26pdPUNu5Y89Qm02fq2zPAwkzih7jeQsBC0Mgq5vPjp2lXcYO89dVG+BRfdvewuXDPfs+XNnev2Uv7XMpkNgQ5I0EglJvUb7GvFqytqAcWuQvnbISOv8H3Z2/o0KIaxJ97BciUZbr/A7gR2b2hJntX4kJCSG6w3I/9r/P3U+a2TYAPzazX7j7owuf0L4o7AeADZuGljmcEGKlWNad391Ptv8fA/B9AHdXPOeAu4+4+0jvAP8NthCiuyzZ+c2s38zWX34M4PcAPLtSExNCrC7L+di/HcD3rRXmVAPw1+7+v8IeDjiRnOYCdaV+9TkYYVFyySAKD4G8QhRHTI3zCLyzR7l8dfb5g9RWnBultnqQjLOluv4685EqFySXDKPEoqgzkp00LGkVSI7Nc5eo7fjjXGyaPnu+sn3nre+mfba8ldusj396bUbnY3SfpSXAllbqrVOW7PzufhTAO5Y9AyHEmiCpT4hEkfMLkShyfiESRc4vRKLI+YVIlK4m8AS4qpEHElCTXKOiyKYs4xFWpQcSivOkoNNnq6PwRl94mvY5+9w/Uls2xSWqPIgQswa/Zvdv3FLdvvtm2mdg805q6+sPpK1A6ps883pl+4VTp2mfC2M8kahfeo3agtyvGD/6cmV7Ocnl2XKWJy0dvuP91OaNQWorAum5JOd+oBzSmoweFYC8At35hUgUOb8QiSLnFyJR5PxCJIqcX4hE6W65Ljic7GwWwXWoTnY2y2C3uQx3V/lYF89PUdtrLx2pbD/3i8doH5s6xW0+T20btw9T23W33M773XRbZXttyy7aJ69vorZo77gMalcNWvWpZaRcGwCcP8V3+1959p+p7dRhHiDVP1sd2DN1Zoz2OR2MVevhLjP0tg9S21y+jtqY+JSTIC0AMK8+h6+iWpfu/EKkipxfiESR8wuRKHJ+IRJFzi9Eosj5hUiUrkp9ZoY8q77eRPnPSlYmK5DzIomqOcPLa42/8iK1nX+hWlIqJ7lEVc/5TIb37qG2Hbe/l9rWXc+zp3kPke0ynrcwklnNArkpWH8QGdMaPHBq026+Huu37Ka2wWEetPTCT/+usr0xzgOFJsaqg5IAID/8U2rbtI0HSGVD1RIsAHiduGFUco7mmlRgjxBiEeT8QiSKnF+IRJHzC5Eocn4hEkXOL0SiLCr1mdmDAD4MYMzdb2+3DQL4FoC9AI4B+Ji7j3cyoJG4o3pQMorlJbOwXBePmJs6Vx3pBQCvv3iI2pqvv1LZ3hPkC9y8k1cmHn47l/P6rr+T2ooGz6tXEkkvC+O9gnyBgURoQdkzJkVFJ1wzmEc+wOe//a2/wY9ZNirbj/6f79A+jRkeiXl+lJ87oy/8b2q7boDLgGW9eo4erD0KIvV1rvR1dOf/SwD3XNF2P4BH3P0WAI+0/xZCvIlY1Pnd/VEA565ovhfAQ+3HDwH4yArPSwixyiz1O/92d79cRvYUWhV7hRBvIpa94eetL+T0m4aZ7Tezg2Z2cGbqwnKHE0KsEEt1/tNmNgwA7f9pTiR3P+DuI+4+0jvAN6qEEN1lqc7/MID72o/vA/CDlZmOEKJbdCL1fQPABwAMmdkJAJ8D8AUA3zazTwE4DuBjnQ1nVB4q5iO5qVrm8SDBYTHHpaGJU9WSHQBcOn2U2upldXLPjZs30j7Dt95FbX27uZw3W+ujtixInFkS/bNZcOkzD47X5N3gzte/RqTbIki6Gt6KghJr+ToeXbh17x2V7RdOczlv4pkfUVsxxyP+Tr10nNo27akuGwYA9b7qT8Ru1RIgAJSsXBft8ess6vzu/gli+p2rGEcIcY2hX/gJkShyfiESRc4vRKLI+YVIFDm/EInS1QSecIcTqcdyfh0qSYRYAR71NDPFa+6df+1VarOZaWqrk+E27riO9tmw663U1uzppTZkPNFlEcheMxerk5OeHOUS5vzF56ltdprXmOup8zn29FT3y2v8eLUal7YaNf5e9zS4LNpDJNOhG3nSz4vHX6C2udcnqG1mfJbbzrxEbfXrbiKGQdoniqjsFN35hUgUOb8QiSLnFyJR5PxCJIqcX4hEkfMLkSjdlfoAACQaKUhW6ETqmw9Czi5NXeK2idPUVi+5XNM7UC0b1bfzOnJlz1ZqOz8+SW0XJs9Q2xyJLgSAmamZyvZjY1dmYvsXXnryJ9TWW3BZMb5zEEk3TNQa1QzkI9VJ/UcA2Ll9oLL9He/5t7TPuiGedHVmnMuRtSY/dy6+zus5bpivfj9zVncRAEhC1midrkR3fiESRc4vRKLI+YVIFDm/EIki5xciUbq+208De4Icc2ySRbC1OT/Fd9JthpdcKo3npWtsqA60yDfw3eGpIJdgeZGnMm/M8uvyky/wwJP+rFoZmZmqDvgBgKzgATooqtUDIEyrh4zswDvJPQfEO9VFwbPT1VnpKgD5peod+N6Snx99g5upbaJWrR4AAGa5wjQ7yc85zFavcdnHz0XPe6rbw7Jsb0R3fiESRc4vRKLI+YVIFDm/EIki5xciUeT8QiRKJ+W6HgTwYQBj7n57u+3zAP4AwOXok8+6+w87GTAjUkQQPwIvqyWPMpB45oJcfMU8l2RqpNwVANRJzromyVcHAFMzfCwveD44C/K39YIHl2C+WjbysO4Wt0XyW3znIFJfVFDKuS0LAoKMBH4BQC2vXqtag8ub2QDPrehZYKMWYG6Or3FB3hsmiwNAHqxHp3RyhL8EcE9F+5fdfV/7X0eOL4S4dljU+d39UQA8HlQI8aZkOZ8dPm1mh8zsQTPjP4kSQlyTLNX5vwrgJgD7AIwC+CJ7opntN7ODZnZwZpr/nFUI0V2W5PzuftrdC2/9UPtrAO4OnnvA3UfcfaS3v7oOuRCi+yzJ+c1seMGfHwXw7MpMRwjRLTqR+r4B4AMAhszsBIDPAfiAme1DS904BuAPOx2wJNpRGcg8TH1zkg8QiGVAC/pFx2QlxaYDSeb4KC8NdvQwz51XTnOJMK9z2eiGbTurj5dxedAb/B4wO8dPkSh3XuNqksn9aiKBdBucH3k9kAEb1fMvg5yRlvG5W9QvjKgL7rPkteXB+jLL1az6os7v7p+oaH7gKsYQQlyD6Bd+QiSKnF+IRJHzC5Eocn4hEkXOL0SidDWBpwOYIxFYjUBCKYl+4eAJDkGiuQDAAwklDDprVht9nktURVmdaBEASue/it61o5/3mw/KfE1Xr+PmDdton7138pJiWRAx5x4kmCQ2FqEJAEUQ+TY916Q2NHn5svUbyCle4+tbzPBoS3c+Dw/kzXo9KEdHIvQi2a4sq+fhgSR6JbrzC5Eocn4hEkXOL0SiyPmFSBQ5vxCJIucXIlG6Xqsvy4gUEUhKRiQUVg8OAOrruJSDeh+3BUsyN10tsW0squvBAcC2wd3UNrphPbW9NnaI2m7awqW5uY3ViT+np0dpnxMTPIKw2eS2ouSvu6e3+rXN8rcZPXN8rL51PElqZlx+mzUS1ef83Jmb5NKhB7Iii1gFgFr/RmrL+6rXqpbxc7EomDyoWn1CiEWQ8wuRKHJ+IRJFzi9Eosj5hUiULu/2O4wEHhRR7jwnu/3Btat/A9/Rt0AJKCf4MS9NV+/0bp1+nfbZe/Od1DY5s4/a5rZwJeCdu3dR28DO66sNwWsOwqPQDHIhRkFQ46fOV7Y/+fJh2mfuxM+o7S17ePmyXXvfS23ZQHXw1NR5rixcPPsatVmTl4EzXgEM9Y08sKrMq8/VggSStQbrPICHoTu/EIki5xciUeT8QiSKnF+IRJHzC5Eocn4hEqWTcl27AfwVgO1oiTsH3P0rZjYI4FsA9qJVsutj7j6+yNEAElARlcnKiKxRM95nXT8PBFkXyC5zY8epbWZuprL9wivHaJ+bbhijtvfccSu1NfFWaqsF5aRA8sHlwXU+DzS7eh7kVgxEwm3Xb6ps/8DwEO3TnOPr0cj5a27U+Ps5P1+dQ3Hstcdon7lxXmKt7jzP4Lp+njdyy3Ye4GV5tUZIYncAADn1l5XN4dcE8CfufhuAdwH4IzO7DcD9AB5x91sAPNL+WwjxJmFR53f3UXf/efvxJIAjAHYCuBfAQ+2nPQTgI6s1SSHEynNV3/nNbC+AOwE8BmC7u18OEj+F1tcCIcSbhI6d38wGAHwXwGfc/cJCm7eShVd+2TCz/WZ20MwOzkxfqHqKEGIN6Mj5zayOluN/3d2/124+bWbDbfswgMqdLXc/4O4j7j7S279hJeYshFgBFnV+a+XQegDAEXf/0gLTwwDuaz++D8APVn56QojVopOovvcC+CSAZ8zsqXbbZwF8AcC3zexTAI4D+NjihzKA5CXLSi6hsNJPlgc5/Pq41Ldxx03UdvrEL6itOVX9tWV89BQ/3vNcUtpxF5e9vKdaKgMANy6/sXyHzSC3mweBe6F0FElRVv2eNWo89G1dvoPajEiYAFAW/DR+/US1dDt1lOdILKa5PNuo83XcvHOY99vMIzHLevW56kHkXlmS0nG0x6+zqPO7+z+Blw37nasYSwhxDaFf+AmRKHJ+IRJFzi9Eosj5hUgUOb8QidLVBJ4Gh5FopKjIEFWigpJLyLh+NbhzL7Wdu24PtTVfPlfZfnGKl3A6eeRpamv0X0dtg2+5m9rmenhyTyclzEje1DaBDBh1K3k/okSF0YUejOa8Ihdef+U0tY0erpZaZ079kvbJUR29CQA9m3ki0aEb305t6OORh0VJ3DA6vVmpus6rdenOL0SqyPmFSBQ5vxCJIucXIlHk/EIkipxfiETpcq0+gAl3QdAWrGBRbDy6La9xbaixnkeWDd82Qm3HzlVHe5XjL9M+F85epLajT/wttc3P8ijHHbe/h9ouNQYq251E+wGARQlBnSelNONrnJPkqvNlkKh1licEPXPsJLW9+tw/U9vk8Scr2+sFf19qffw1b7vlZmrrH76D2soajzKtUdmOOwVfqc61Pt35hUgUOb8QiSLnFyJR5PxCJIqcX4hE6epufyu/d3XwBstJBgAZy9VX8j3P0rkSUG/wHdFN26+nth1vf3dl+8kneSBIOcnz+50f4zv6k//3x9R27Pn/R203v/O3KtuHdr+T9mn08qzKpV8KbNSEYr7aOD7Gg3BOHqnemQeAs6/wAKn582eprYfkf8wafPK73/Y2ahu6+V3Ulq/fSm1UsAKQgZwHGVcdyiCoqlN05xciUeT8QiSKnF+IRJHzC5Eocn4hEkXOL0SiLCr1mdluAH+FVgluB3DA3b9iZp8H8AcAzrSf+ll3/2F4LPCwAw+Ui4LUk8qjDHNlFHTCB6v38MCTzbv3Vhv8g7TPa8/+lNqaE9WlpACgdmmO2i6ePENth8f+rtrQz4Nf6n3VwUAAUO/pobZmwddqdqZa/vRpnu/QL/Fgm6icW0/G3+uegeogrutvvYv22fq236S2xtBeaivrXJqLcig2mWwXyHn0eFdRr6sTnb8J4E/c/edmth7AE2Z2WYT+srv/WefDCSGuFTqp1TcKYLT9eNLMjgDYudoTE0KsLlf1nd/M9gK4E8DlfMifNrNDZvagmW1e4bkJIVaRjp3fzAYAfBfAZ9z9AoCvArgJwD60Phl8kfTbb2YHzezgxenqEtdCiO7TkfObWR0tx/+6u38PANz9tLsX7l4C+BqAyioT7n7A3UfcfaSvn/+GXAjRXRZ1fjMzAA8AOOLuX1rQPrzgaR8F8OzKT08IsVp0stv/XgCfBPCMmT3VbvssgE+Y2T60xIVjAP5wsQM5HE5CwcpAfmO6RknyxAGA1YJSUkUgoeQ8/Kp3U7Uk1tv7FtpnwyDfCnnhMS6/4dwRamrOTVNbOV8te9kElweLwMYFRyAL8sUZ0Zws0LwKXpgNWZ2P1Res8Z7bf6Oyff0Nd/KxBvl+drPGXaaMyp4ZP68yY+c37UL7XE25rk52+/+JHDLU9IUQ1zb6hZ8QiSLnFyJR5PxCJIqcX4hEkfMLkShdTeBpMC4PBdFIVL0I+rBEoYt1zEP5qlqKqvXyaK7Gnhup7a4gWeiZlx+nttO/OExtxenqBJnW5ElGveRJOmMFlktzrGOtwctW9Q9tp7ahvXupbeuNt1BbvnlPZbs3+A/Oiixwi+ici0qRsZJcAEpyXkWRrsEsOn6m7vxCJIqcX4hEkfMLkShyfiESRc4vRKLI+YVIlK5KfQCQ5dX6RRkkgzQiGxVB2FOW85dWM17jr4iUkrL6WlkGkYBByUD01KuTSwLAriDB5LYb9lHb9PnxyvaL4ydpn7lLE9RWNnnizFrOF2vduurEn30bttA+fRt5rbtGP+9njV5qQ1b9BrCgOABhDUhjdSMBFIHMVgbHdCL1ZbwLjEQJXo06qDu/EIki5xciUeT8QiSKnF+IRJHzC5Eocn4hEqXLUp8DJBIsc65rsCuUB5FS7oEtiL7yIMGkEdkIWSA5BtpLHl171wX18+q8Nt2m/uqouaEd19E+LNkmALjzU8SNp/ckii5Q4/ImwHXRMng/m0H4m1n1WtWyYB7B8eaDGpBZkKQzWmNqCs5FJiFfRak+3fmFSBU5vxCJIucXIlHk/EIkipxfiERZdLffzNYBeBRAT/v533H3z5nZDQC+CWALgCcAfNLdo+pOAPhuugdTaTard+etFgRLRIEUwQ42sqCcVDFb3cX48bJoB7sIAkiMX5ejMlkZCTwpSJk0AMiXqJqU4DvmLLAqjKcJdtLj+1SQS5AM6HnQZwlBZgBQBiqSBfkOSzLJWlCOjgcRrWwOv1kAv+3u70CrHPc9ZvYuAH8K4MvufjOAcQCf6nhUIcSas6jze4up9p/19j8H8NsAvtNufwjAR1ZlhkKIVaGj7/xmlrcr9I4B+DGAlwBMuPvlz2knAPDSpkKIa46OnN/dC3ffB2AXgLsB3NrpAGa238wOmtnBi9OTS5ymEGKluardfnefAPATAO8GsMnsVztduwBUpopx9wPuPuLuI33965c1WSHEyrGo85vZVjPb1H7cC+B3ARxB6yLw79pPuw/AD1ZrkkKIlaeTwJ5hAA9ZK2lYBuDb7v4/zew5AN80s/8C4EkADyx2IAcPwijBZa9eMksP5LD5SP4JErgVYYARCUoKxvJgLI9qYUVlsoLchU0iN1kQYVQGcqQF888Cqa9okn7B7YblpWuxhMAYABkxNgOZNSO5GlvGQII1nu8wkgGzGnvdgQRL16rzLH6LOr+7HwJwZ0X7UbS+/wsh3oToF35CJIqcX4hEkfMLkShyfiESRc4vRKJYlLNuxQczOwPgePvPIQBnuzY4R/N4I5rHG3mzzWOPu/O6ZwvoqvO/YWCzg+4+siaDax6ah+ahj/1CpIqcX4hEWUvnP7CGYy9E83gjmscb+Vc7jzX7zi+EWFv0sV+IRFkT5zeze8zseTN70czuX4s5tOdxzMyeMbOnzOxgF8d90MzGzOzZBW2DZvZjM/tl+//NazSPz5vZyfaaPGVmH+rCPHab2U/M7DkzO2xmf9xu7+qaBPPo6pqY2Toz+5mZPd2ex39ut99gZo+1/eZbZtZY1kDu3tV/aBVkewnAjQAaAJ4GcFu359GeyzEAQ2sw7vsB3AXg2QVt/xXA/e3H9wP40zWax+cB/Icur8cwgLvaj9cDeAHAbd1ek2AeXV0TtOJyB9qP6wAeA/AuAN8G8PF2+18A+PfLGWct7vx3A3jR3Y96K9X3NwHcuwbzWDPc/VEA565ovhetRKhAlxKiknl0HXcfdfeftx9PopUsZie6vCbBPLqKt1j1pLlr4fw7Aby64O+1TP7pAH5kZk+Y2f41msNltrv7aPvxKQDb13AunzazQ+2vBav+9WMhZrYXrfwRj2EN1+SKeQBdXpNuJM1NfcPvfe5+F4DfB/BHZvb+tZ4Q0Lry4+qqLa8kXwVwE1o1GkYBfLFbA5vZAIDvAviMu19YaOvmmlTMo+tr4stImtspa+H8JwHsXvA3Tf652rj7yfb/YwC+j7XNTHTazIYBoP3/2FpMwt1Pt0+8EsDX0KU1MbM6Wg73dXf/Xru562tSNY+1WpP22FedNLdT1sL5HwdwS3vnsgHg4wAe7vYkzKzfzNZffgzg9wA8G/daVR5GKxEqsIYJUS87W5uPogtrYq0aWA8AOOLuX1pg6uqasHl0e026ljS3WzuYV+xmfgitndSXAPzHNZrDjWgpDU8DONzNeQD4BlofH+fR+u72KbRqHj4C4JcA/gHA4BrN438AeAbAIbScb7gL83gfWh/pDwF4qv3vQ91ek2AeXV0TAHeglRT3EFoXmv+04Jz9GYAXAfwNgJ7ljKNf+AmRKKlv+AmRLHJ+IRJFzi9Eosj5hUgUOb8QiSLnFyJR5PxCJIqcX4hE+f/v3sRbPjbpNQAAAABJRU5ErkJggg==\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "from matplotlib import pyplot as plt\n", + "\n", + "plt.imshow(test_single_x)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Expected class is:\n", + "Prohibited for vehicles with a permitted gross weight over 3.5t including their trailers, and for tractors except passenger cars and buses\n" + ] + } + ], + "source": [ + "print(\"Expected class is:\\n%s\" % (gtsrb_classes[test_single_y]))" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Accelerator result is:\n", + "Prohibited for vehicles with a permitted gross weight over 3.5t including their trailers, and for tractors except passenger cars and buses\n" + ] + } + ], + "source": [ + "accel_y = accel.execute(test_single_x.reshape(accel.ishape_normal))\n", + "print(\"Accelerator result is:\\n%s\" % (gtsrb_classes[np.argmax(accel_y)]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Validate accuracy on GTSRB test set" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Ready to run validation, test images tensor has shape (30, 421, 3072)\n", + "Accelerator buffer shapes are (421, 1, 32, 32, 3, 1) for input, (421, 11, 8) for output\n" + ] + } + ], + "source": [ + "batch_size = 421\n", + "total = testx.shape[0]\n", + "accel.batch_size = batch_size\n", + "n_batches = int(total / batch_size)\n", + "\n", + "batch_imgs = testx.reshape(n_batches, batch_size, -1)\n", + "batch_labels = testy.reshape(n_batches, batch_size)\n", + "obuf_normal = np.empty_like(accel.obuf_packed_device)\n", + "print(\"Ready to run validation, test images tensor has shape %s\" % str(batch_imgs.shape))\n", + "print(\"Accelerator buffer shapes are %s for input, %s for output\" % (str(accel.ishape_packed), str(accel.oshape_packed)) )" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "batch 0 / 30 : total OK 401 NOK 20\n", + "batch 1 / 30 : total OK 798 NOK 44\n", + "batch 2 / 30 : total OK 1203 NOK 60\n", + "batch 3 / 30 : total OK 1605 NOK 79\n", + "batch 4 / 30 : total OK 2003 NOK 102\n", + "batch 5 / 30 : total OK 2404 NOK 122\n", + "batch 6 / 30 : total OK 2806 NOK 141\n", + "batch 7 / 30 : total OK 3210 NOK 158\n", + "batch 8 / 30 : total OK 3609 NOK 180\n", + "batch 9 / 30 : total OK 4009 NOK 201\n", + "batch 10 / 30 : total OK 4404 NOK 227\n", + "batch 11 / 30 : total OK 4805 NOK 247\n", + "batch 12 / 30 : total OK 5205 NOK 268\n", + "batch 13 / 30 : total OK 5605 NOK 289\n", + "batch 14 / 30 : total OK 5996 NOK 319\n", + "batch 15 / 30 : total OK 6403 NOK 333\n", + "batch 16 / 30 : total OK 6796 NOK 361\n", + "batch 17 / 30 : total OK 7200 NOK 378\n", + "batch 18 / 30 : total OK 7596 NOK 403\n", + "batch 19 / 30 : total OK 7994 NOK 426\n", + "batch 20 / 30 : total OK 8397 NOK 444\n", + "batch 21 / 30 : total OK 8804 NOK 458\n", + "batch 22 / 30 : total OK 9213 NOK 470\n", + "batch 23 / 30 : total OK 9616 NOK 488\n", + "batch 24 / 30 : total OK 10010 NOK 515\n", + "batch 25 / 30 : total OK 10414 NOK 532\n", + "batch 26 / 30 : total OK 10817 NOK 550\n", + "batch 27 / 30 : total OK 11218 NOK 570\n", + "batch 28 / 30 : total OK 11619 NOK 590\n", + "batch 29 / 30 : total OK 12021 NOK 609\n" + ] + } + ], + "source": [ + "ok = 0\n", + "nok = 0\n", + "for i in range(n_batches):\n", + " ibuf_normal = batch_imgs[i].reshape(accel.ibuf_packed_device.shape)\n", + " exp = batch_labels[i]\n", + " # to avoid the slower software implementation during data unpacking,\n", + " # we make manual calls to buffer copies and execute_on_buffers\n", + " # all this could have been replaced with accel.execute() otherwise\n", + " accel.copy_input_data_to_device(ibuf_normal)\n", + " accel.execute_on_buffers()\n", + " obuf_normal = np.empty_like(accel.obuf_packed_device)\n", + " accel.copy_output_data_from_device(obuf_normal)\n", + " # this line provides fast unpacking using numpy primitives\n", + " # instead of using FINN's unpack functions\n", + " quick_out = obuf_normal.view(np.uint16).reshape(accel.batch_size, 44)\n", + " obuf_argmax = np.argmax(quick_out, axis=-1)\n", + " ok_batch = (obuf_argmax == exp).sum()\n", + " nok_batch = (batch_size-ok_batch)\n", + " ok += ok_batch\n", + " nok += nok_batch\n", + " \n", + " print(\"batch %d / %d : total OK %d NOK %d\" % (i+1, n_batches, ok, nok))" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Final accuracy: 95.17814726840855%\n" + ] + } + ], + "source": [ + "acc = 100.0 * ok / (total)\n", + "print(\"Final accuracy: {}%\".format(acc))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run built-in benchmarks" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'DRAM_in_bandwidth[MB/s]': 8.867975173609915,\n", + " 'DRAM_out_bandwidth[MB/s]': 0.25403053882736737,\n", + " 'batch_size': 100,\n", + " 'copy_input_data_to_device[ms]': 2.284526824951172,\n", + " 'copy_output_data_from_device[ms]': 0.20766258239746094,\n", + " 'fclk[mhz]': 100.0,\n", + " 'fold_input[ms]': 0.14352798461914062,\n", + " 'pack_input[ms]': 0.10251998901367188,\n", + " 'runtime[ms]': 34.64150428771973,\n", + " 'throughput[images/s]': 2886.7106684928112,\n", + " 'unfold_output[ms]': 0.0762939453125,\n", + " 'unpack_output[ms]': 1504.5325756072998}" + ] + }, + "execution_count": 26, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "accel.batch_size = 100\n", + "accel.throughput_test()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}