.. note::
    :class: sphx-glr-download-link-note

    Click :ref:`here <sphx_glr_download_how_to_work_with_microtvm_micro_tvmc.py>` to download the full example code
.. rst-class:: sphx-glr-example-title

.. _sphx_glr_how_to_work_with_microtvm_micro_tvmc.py:


.. _tutorial-micro-tvmc:

Executing a Tiny Model with TVMC Micro
======================================
**Author**: `Mehrdad Hessar <https://github.com/mehrdadh>`_

This tutorial explains how to compile a tiny model for a micro device,
build a program on Zephyr platform to execute this model, flash the program
and run the model all using `tvmc micro` command.

.. note::
    This tutorial is explaining using TVMC Mirco on Zephyr platform. You need
    to install Zephyr dependencies before processing with this tutorial. Alternatively,
    you can run this tutorial in one of the following ways which has Zephyr depencencies already installed.

    * Use `microTVM Reference Virtual Machines <https://tvm.apache.org/docs/how_to/work_with_microtvm/micro_reference_vm.html#sphx-glr-how-to-work-with-microtvm-micro-reference-vm-py>`_.
    * Use QEMU docker image provided by TVM. Following these you will download and login to the docker image:

    .. code-block:: bash

      cd tvm
      ./docker/bash.sh tlcpack/ci-qemu


Using TVMC Micro
###########################################################

 TVMC is a command-line tool which is installed as a part of TVM Python packages. Accessing this
 package varies based on your machine setup. In many cases, you can use the ``tvmc`` command directly.
 Alternatively, if you have TVM as a Python module on your ``$PYTHONPATH``, you can access this
 driver with ``python -m tvm.driver.tvmc`` command. This tutorial will use TVMC command as
 ``tvmc`` for simplicity.

 To check if you have TVMC command installed on your machine, you can run:

 .. code-block:: bash

	  tvmc --help

 To compile a model for microtvm we use ``tvmc compile`` subcommand. The output of this command
 is used in next steps with ``tvmc micro`` subcommands. You can check the availability of TVMC Micro using:

 .. code-block:: bash

	  tvmc micro --help


 The main tasks that you can perform using ``tvmc micro`` are ``create``, ``build`` and ``flash``.
 To read about specific options under a givern subcommand, use
 ``tvmc micro <subcommand> --help``. We will use each subcommand in this tutorial.


Obtain a Tiny Model
###########################################################

 For this tutorial, we will use Magic Wand model from tflite micro. Magic Wand is a
 Depthwise Convolution Layer model which recognizes gestures with an accelerometer.

 For this tutorial we will be using the model in tflite format.

 .. code-block:: bash

	  wget https://github.com/tensorflow/tflite-micro/raw/main/tensorflow/lite/micro/examples/magic_wand/magic_wand.tflite


Compiling a TFLite model to a Model Library Format
###########################################################

 Model Library Format (MLF) is an output format that TVM provides for micro targets. MLF is a tarball
 containing a file for each piece of the TVM compiler output which can be used on micro targets outside
 TVM environment. Read more about `Model Library Format <https://tvm.apache.org/docs//arch/model_library_format.html>`_.

 Here, we generate a MLF file for ``qemu_x86`` Zephyr board. To generate MLF output for the ``magic_wand`` tflite model:

 .. code-block:: bash

	  tvmc compile magic_wand.tflite \
	      --target='c -keys=cpu -link-params=0 -model=host' \
	      --runtime=crt \
	      --runtime-crt-system-lib 1 \
	      --executor='graph' \
	      --executor-graph-link-params 0 \
	      --output model.tar \
	      --output-format mlf \
	      --pass-config tir.disable_vectorize=1 \
	      --disabled-pass=AlterOpLayout

 This will generate a ``model.tar`` file which contains TVM compiler output files. To run this command for
 a different Zephyr device, you need to update ``target``. For instance, for ``nrf5340dk_nrf5340_cpuapp`` board
 the target is ``--target='c -keys=cpu -link-params=0 -model=nrf5340dk'``.


Create a Zephyr Project Using Model Library Format
###########################################################

 To generate a Zephyr project we use TVM Micro subcommand ``create``. We pass the MLF format and the path
 for the project to ``create`` subcommand along with project options. Project options for each
 platform (Zephyr/Arduino) are defined in their Project API server file. To generate Zephyr project, run:

 .. code-block:: bash

	  tvmc micro create \
	      project \
	      model.tar \
	      zephyr \
	      --project-option project_type=host_driven zephyr_board=qemu_x86

 This will generate a ``Host-Driven`` Zephyr project for ``qemu_x86`` Zephyr board. In Host-Driven template project,
 the Graph Executor will run on host and perform the model execution on Zephyr device by issuing commands to the
 device using an RPC mechanism. Read more about `Host-Driven Execution <https://tvm.apache.org/docs/arch/microtvm_design.html#host-driven-execution>`_.

 To get more information about TVMC Micro ``create`` subcommand:

 .. code-block:: bash

     tvmc micro create --help


Build and Flash Zephyr Project Using TVMC Micro
###########################################################

 Next step is to build the Zephyr project which includes TVM generated code for running the tiny model, Zephyr
 template code to run a model in Host-Driven mode and TVM runtime source/header files. To build the project:

 .. code-block:: bash

	  tvmc micro build \
	      project \
	      zephyr \
	      --project-option zephyr_board=qemu_x86

 This will build the project in ``project`` directory and generates binary files under ``project/build``. To build
 Zephyr project for a different Zephyr board, change ``zephyr_board`` project option.

 Next, we flash the Zephyr binary file to Zephyr device. For ``qemu_x86`` Zephyr board this step does not
 actually perform any action since QEMU will be used, however you need this step for physical hardware.

 .. code-block:: bash

	  tvmc micro flash \
	      project \
	      zephyr \
	      --project-option zephyr_board=qemu_x86


Run Tiny Model on Micro Target
###########################################################

 After flashing the device, the compiled model and TVM RPC server are programmed on the device.
 The Zephyr board is waiting for host to open a communication channel. MicroTVM devices typicall communicate
 using a serial communication (UART). To run the flashed model on the device using TVMC, we use ``tvmc run`` subcommand
 and pass ``--device micro`` to specify the device type. This command will open a communication channel, set input
 values using ``Graph Executor`` on host and run full model on the device. Then it gets output from the device.

 .. code-block:: bash

	  tvmc run \
	      --device micro \
	      project \
	      --project-option zephyr_board=qemu_x86 \
	      --fill-mode ones \
	      --print-top 4

     # Output:
     #
     # INFO:__main__:b'[100%] [QEMU] CPU: qemu32,+nx,+pae\n'
     # remote: microTVM Zephyr runtime - running
     # INFO:__main__:b'[100%] Built target run\n'
     # [[3.         1.         2.         0.        ]
     # [0.47213247 0.41364592 0.07525456 0.03896701]]

 Specifically, this command sets the input of the model to all ones and shows the four values of the output with their indices.