Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MicroTVM tutorial using the STM32F746 discovery board #5655

Merged
merged 15 commits into from
Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@
'../tutorials/dev',
'../tutorials/topi',
'../tutorials/deployment',
'../tutorials/micro',
'../vta/tutorials/frontend',
'../vta/tutorials/optimize',
'../vta/tutorials/autotvm'])
Expand Down
4 changes: 4 additions & 0 deletions tutorials/micro/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.. _tutorial-micro:
tom-gall marked this conversation as resolved.
Show resolved Hide resolved

Micro TVM
---------
218 changes: 218 additions & 0 deletions tutorials/micro/micro_tflite.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
"""
Micro TVM with TFLite Models
============================
**Author**: `Tom Gall <https://github.com/tom-gall>`_

This tutorial is an introduction to working with MicroTVM and a TFLite
model with Relay.
"""

# %%
# Setup
# -----
#
# To get started, TFLite package needs to be installed as prerequisite.
#
# install tflite
#
# .. code-block:: bash
liangfu marked this conversation as resolved.
Show resolved Hide resolved
#
# pip install tflite=2.1.0 --user
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow RST syntax to put the extra indentation, otherwise it's not rendered as code.

Please try reproduce the the rendered html by running

make html

in <tvm_root>/docs directory, so that the tutorial could be more reader friendly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly make html dies with an exception :

python3 -m sphinx -b html -d _build/doctrees . _build/html
Running Sphinx v3.1.0
loading pickled environment... done
[autosummary] generating autosummary for: api/links.rst, api/python/autotvm.rst, api/python/contrib.rst, api/python/driver.rst, api/python/error.rst, api/python/graph_runtime.rst, api/python/index.rst, api/python/ir.rst, api/python/micro.rst, api/python/ndarray.rst, ..., vta/index.rst, vta/install.rst, vta/tutorials/autotvm/tune_relay_vta.rst, vta/tutorials/frontend/deploy_classification.rst, vta/tutorials/frontend/deploy_detection.rst, vta/tutorials/index.rst, vta/tutorials/matrix_multiply.rst, vta/tutorials/optimize/convolution_opt.rst, vta/tutorials/optimize/matrix_multiply_opt.rst, vta/tutorials/vta_get_started.rst
generating gallery...
generating gallery for tutorials... [ 33%] relay_quick_start.py
Extension error:
Handler <function generate_gallery_rst at 0x7f23e55b04d0> for event 'builder-inited' threw an exception
make: *** [Makefile:70: html] Error 2

I'm using ./tests/scripts/task_sphinx_precheck.sh which seems to generate less than perfect html when viewed elsewhere. I'm less than confident that the html generated is acceptable :-/

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to get this to work by deleting the other tutorials. I haven't seen that specific exception, though. I did build your tutorial locally and I think it looks okay now. i'll add a couple of small nitpicks which you could fix if you want to be a perfectionist about it.

#
# or you could generate TFLite package yourself. The steps are the following:
#
# Get the flatc compiler.
tom-gall marked this conversation as resolved.
Show resolved Hide resolved
# Please refer to https://github.com/google/flatbuffers for details
# and make sure it is properly installed.
#
# .. code-block:: bash
#
# flatc --version
#
# Get the TFLite schema.
#
# .. code-block:: bash
#
# wget https://raw.githubusercontent.com/tensorflow/tensorflow/r1.13/tensorflow/lite/schema/schema.fbs
#
# Generate TFLite package.
#
# .. code-block:: bash
#
# flatc --python schema.fbs
#
# Add the current folder (which contains generated tflite module) to PYTHONPATH.
#
# .. code-block:: bash
#
# export PYTHONPATH=${PYTHONPATH:+$PYTHONPATH:}$(pwd)
#
# To validate that the TFLite package was installed successfully, ``python -c "import tflite"``
#
# CMSIS needs to be downloaded and the CMSIS_ST_PATH environment variable setup
# This tutorial only supports the STM32F7xx series of boards.
# Download from : https://www.st.com/en/embedded-software/stm32cubef7.html
# After you've expanded the zip file
#
# .. code-block:: bash
#
# export CMSIS_ST_PATH=/path/to/STM32Cube_FW_F7_V1.16.0/Drivers/CMSIS

# %%
# Recreating your own Pre-Trained TFLite model
# --------------------------------------------
#
# The tutorial downloads a pretrained TFLite model. When working with microcontrollers
# you need to be mindful these are highly resource constrained devices as such standard
# models like MobileNet may not fit into their modest memory.
#
# For this tutorial, we'll make use of one of the TF Micro example models.
#
# If you wish to replicate the training steps see:
# https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/micro/examples/hello_world/train
#
# .. note::
#
# If you accidentally download the example pretrained model from:
# wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/micro/hello_world_2020_04_13.zip
# this will fail due to an unimplemented opcode (114)

import os
import numpy as np
import tvm
import tvm.micro as micro
from tvm.contrib.download import download_testdata
from tvm.contrib import graph_runtime, util
from tvm import relay

# %%
# Load and prepare the Pre-Trained Model
# --------------------------------------
#
# Load the pretrained TFLite model from a file in your current
# directory into a buffer

model_url = 'https://people.linaro.org/~tom.gall/sine_model.tflite'
tqchen marked this conversation as resolved.
Show resolved Hide resolved
model_file = 'sine_model.tflite'
model_path = download_testdata(model_url, model_file, module='data')

tflite_model_buf = open(model_path, "rb").read()

######################################################################
# Using the buffer, transform into a tflite model python object
try:
import tflite
tflite_model = tflite.Model.GetRootAsModel(tflite_model_buf, 0)
except AttributeError:
import tflite.Model
tflite_model = tflite.Model.Model.GetRootAsModel(tflite_model_buf, 0)

######################################################################
# Print out the version of the model
version = tflite_model.Version()
print ("Model Version: " + str(version))

######################################################################
# Parse the python model object to convert it into a relay module
# and weights.
# It is important to note that the input tensor name must match what
# is contained in the model.
#
# If you are unsure what that might be, this can be discovered by using
# the visualize.py script within the Tensorflow project.
# See : How do I inspect a .tflite file? `<https://www.tensorflow.org/lite/guide/faq>`_

input_tensor = "dense_4_input"
input_shape = (1,)
input_dtype = "float32"

mod, params = relay.frontend.from_tflite(tflite_model,
shape_dict={input_tensor: input_shape},
dtype_dict={input_tensor: input_dtype})

# %%
# Running on device
# ----------------------------------------------
#
# Setup the device config which is what will be used to communicate
# with the microcontroller (a STM32F746 Discovery board)
TARGET = 'c -device=micro_dev'
dev_config = micro.device.arm.stm32f746xx.generate_config("127.0.0.1", 6666)

######################################################################
tom-gall marked this conversation as resolved.
Show resolved Hide resolved
# Next with the dev_config, we establish a micro session and create
# a context
#
# .. code-block:: python
#
# with micro.Session(dev_config) as sess:
# ctx = tvm.micro_dev(0)

######################################################################
# Now we create a build config for relay. turning off two options
# and then calling relay.build which will result in a C source
# file.
#
# .. code-block:: python
#
# with tvm.transform.PassContext(opt_level=3, config={'tir.disable_vectorize': True},disabled_pass=['FuseOps']):
# graph, c_mod, params = relay.build(mod, target=TARGET, params=params)

######################################################################
# With the c_mod that is the handle to our C source code, we create a
# micro module, followed by a compiled object which behind the scenes
# is linked to the microTVM runtime for running on the target board
#
# .. code-block:: python
#
# micro_mod = micro.create_micro_mod(c_mod, dev_config)
# mod = graph_runtime.create(graph, micro_mod, ctx)

######################################################################
# Pass the weights to get ready to perform inference
#
# .. code-block:: python
tom-gall marked this conversation as resolved.
Show resolved Hide resolved
#
# mod.set_input(**params)

######################################################################
# The model consumes a single float32 value and returns a predicted
# sine value.
# To pass the input value we construct a tvm.nd.array object
# with a single contrived number as input. For this model values of
# 0 to 2Pi are acceptable.
#
# .. code-block:: python
#
# mod.set_input(input_tensor, tvm.nd.array(np.array([0.5], dtype="float32")))

######################################################################
# Run the model on device
#
# .. code-block:: python
#
# mod.run()

######################################################################
# Get output from the run and print
#
# .. code-block:: python
#
# tvm_output = mod.get_output(0).asnumpy()
# print("result is: "+str(tvm_output))