Skip to content

Commit

Permalink
[µTVM] Add support for mps2_an521 board (#7813)
Browse files Browse the repository at this point in the history
* [µTVM] Zephyr: Allow user inform if a board is emulated

Some boards supported by Zephyr that run emulated by default, i.e. their
.yaml config file sets the field "simulation: qemu", don't have the
prefix "qemu_" on their names, so µTVM can't currently recognize it as
an emulated target to properly use the QEMU transporter (instead of the
serial port) to open a session against it. Such a boards usually have
real physical (hardware) counterparts, being specific boards and not
generic or "fake" ones simply tied to a CPU type of interest.

That commit allows the µTVM user to explicitly inform that µTVM needs
to use the QEMU transporter to open a session against a given board by
adding the suffix "-qemu" to the board name. That is necessary because
for boards that don't have the name prefixed by "qemu_" and even though
run emulated by default on Zephyr there is no easy way to detect them,
since it's not possible to determine it by looking at any Cmake
generated file or by using the `west` command to query that info.

The case where the board is emulated by default but has the prefix
"qemu_" in its board name is already handled by the current code.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>

* [µTVM] Add new target mps2_an521

This commit adds a new µTVM target to support the Arm reference board
MPS2-AN521, which is based upon a Cortex-m33 core.

For more details about that board, please see:
http://developer.arm.com/tools-and-software/development-boards/fpga-prototyping-boards/mps2

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>

* [µTVM] Add an example for the mps2_an521 board

This commit adds an example on how to run the Zephyr demo under apps/
using as a target the Arm mps2_an521 board, which is emulated by default
on Zephyr. The example is added to the tutorial script micro_tflite.py,
where other examples for other targets exist.

Signed-off-by: Gustavo Romero <gustavo.romero@linaro.org>

* Fix lint

Fix lint accordingly to the CI error.

* Satisfy lint

Satisfy lint about boolean expression format.

* Address suggestion from Andrew

Address suggestion from Andrew in the review.

Also updates the comment about suffix being trimmed off.

Thanks,
Gustavo
  • Loading branch information
gromero authored Apr 13, 2021
1 parent 5c7ea7c commit 9782e6e
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 34 deletions.
28 changes: 28 additions & 0 deletions apps/microtvm/zephyr/demo_runtime/boards/mps2_an521.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# 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.
#
# This file is specific to the MPS2-AN512 board.

# For intrinsics used by generated optimized operators.
CONFIG_CMSIS_DSP=y

# For random number generation.
CONFIG_ENTROPY_GENERATOR=y
CONFIG_TEST_RANDOM_GENERATOR=y

# For debugging.
CONFIG_LED=n
24 changes: 18 additions & 6 deletions python/tvm/micro/contrib/zephyr.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,17 @@ def __init__(
f"project_dir supplied to ZephyrCompiler does not exist: {project_dir}"
)

self._qemu = "qemu" in board

# For Zephyr boards that run emulated by default but don't have the prefix "qemu_" in their
# board names, a suffix "-qemu" is added by users of µTVM when specifying the board name to
# inform that the QEMU transporter must be used just like for the boards with the prefix.
# Zephyr does not recognize the suffix, so we trim it off before passing it.
if "-qemu" in board:
board = board.replace("-qemu", "")

self._board = board

if west_cmd is None:
self._west_cmd = [sys.executable, "-mwest.app.main"]
elif isinstance(west_cmd, str):
Expand Down Expand Up @@ -257,14 +267,17 @@ def binary(self, output, objects, options=None, link_main=True, main_options=Non
"cmake_cache": ["CMakeCache.txt"],
"device_tree": [os.path.join("zephyr", "zephyr.dts")],
},
immobile="qemu" in self._board,
immobile=bool(self._qemu),
)

@property
def flasher_factory(self):
return compiler.FlasherFactory(
ZephyrFlasher,
(self._board,),
(
self._board,
self._qemu,
),
dict(
zephyr_base=self._zephyr_base,
project_dir=self._project_dir,
Expand Down Expand Up @@ -316,6 +329,7 @@ class ZephyrFlasher(tvm.micro.compiler.Flasher):
def __init__(
self,
board,
qemu,
zephyr_base=None,
project_dir=None,
subprocess_env=None,
Expand All @@ -336,6 +350,7 @@ def __init__(
sys.path.pop(0)

self._board = board
self._qemu = qemu
self._zephyr_base = zephyr_base
self._project_dir = project_dir
self._west_cmd = west_cmd
Expand Down Expand Up @@ -447,10 +462,7 @@ def _zephyr_transport(self, micro_binary):
)

def flash(self, micro_binary):
cmake_entries = read_cmake_cache(
micro_binary.abspath(micro_binary.labelled_files["cmake_cache"][0])
)
if "qemu" in cmake_entries["BOARD"]:
if self._qemu:
return self._zephyr_transport(micro_binary)

build_dir = os.path.dirname(
Expand Down
1 change: 1 addition & 0 deletions python/tvm/target/target.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ def intel_graphics(model="unknown", options=None):
"host": [],
"stm32f746xx": ["-mcpu=cortex-m7", "-march=armv7e-m"],
"nrf5340dk": ["-mcpu=cortex-m33"],
"mps2_an521": ["-mcpu=cortex-m33"],
}


Expand Down
2 changes: 2 additions & 0 deletions tests/lint/check_file_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,9 @@
"apps/microtvm/zephyr/demo_runtime/boards/nrf5340dk_nrf5340_cpuapp.conf",
"apps/microtvm/zephyr/demo_runtime/boards/nucleo_f746zg.conf",
"apps/microtvm/zephyr/demo_runtime/boards/stm32f746g_disco.conf",
"apps/microtvm/zephyr/demo_runtime/boards/mps2_an521.conf",
"apps/microtvm/zephyr/demo_runtime/qemu-hack/qemu-system-i386",
"apps/microtvm/zephyr/demo_runtime/qemu-hack/qemu-system-arm",
"apps/microtvm/zephyr/demo_runtime/qemu-hack/qemu-system-riscv32",
"apps/microtvm/zephyr/demo_runtime/qemu-hack/qemu-system-riscv64",
# microTVM Virtual Machines
Expand Down
62 changes: 34 additions & 28 deletions tutorials/micro/micro_tflite.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,25 +174,33 @@
# Defining the target
# -------------------
#
# 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. When running on a simulated target, choose "host" below:
# TARGET = tvm.target.target.micro("host")

# %%
# Compiling for physical hardware
# When running on physical hardware, choose a target and a board that
# describe the hardware. The STM32F746 Nucleo target and board is chosen in
# this commented code. Another option would be to choose the same target but
# the STM32F746 Discovery board instead. The disco board has the same
# microcontroller as the Nucleo board but a couple of wirings and configs
# differ, so it's necessary to select the "stm32f746g_disco" board below.
#
# .. code-block:: python
# 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 for the selected TARGET. When running on a simulated target of the
# same architecture as the host (where this Python script is executed) choose "host" below for the
# TARGET and a proper board/VM to run it (Zephyr will create the right QEMU VM based on BOARD. In
# the example below the x86 arch is selected and a x86 VM is picked up accordingly:
#
TARGET = tvm.target.target.micro("host")
# BOARD = "nucleo_f746zg" # or "stm32f746g_disco"
BOARD = "qemu_x86"
#
# Compiling for physical hardware
# When running on physical hardware, choose a TARGET and a BOARD that describe the hardware. The
# STM32F746 Nucleo target and board is chosen in the example below. Another option would be to
# choose the STM32F746 Discovery board instead. Since that board has the same MCU as the Nucleo
# board but a couple of wirings and configs differ, it's necessary to select the "stm32f746g_disco"
# board to generated the right firmware image.
#
# TARGET = tvm.target.target.micro("stm32f746xx")
# BOARD = "nucleo_f746zg" # or "stm32f746g_disco#"
#
# For some boards, Zephyr runs them emulated by default, using QEMU. For example, below is the
# TARGET and BOARD used to build a microTVM firmware for the mps2-an521 board. Since that board
# runs emulated by default on Zephyr the suffix "-qemu" is added to the board name to inform
# microTVM that the QEMU transporter must be used to communicate with the board. If the board name
# already has the prefix "qemu_", like "qemu_x86", then it's not necessary to add that suffix.
#
# TARGET = tvm.target.target.micro("mps2_an521")
# BOARD = "mps2_an521-qemu"

######################################################################
# Now, compile the model for the target:
Expand All @@ -203,9 +211,8 @@
graph, c_mod, c_params = relay.build(mod, target=TARGET, params=params)


# %%
# Compiling for a simulated device
# --------------------------------
# Compiling for a host simulated device
# -------------------------------------
#
# First, compile a static microTVM runtime for the targeted device. In this case, the host simulated
# device is used.
Expand All @@ -214,11 +221,10 @@
os.path.join(tvm.micro.get_standalone_crt_dir(), "template", "host")
)

# %%
# Compiling for physical hardware
# For physical hardware, comment out the previous section and use this compiler definition instead.
#
# .. code-block:: python
# Compiling for physical hardware (or an emulated board, like the mps_an521)
# --------------------------------------------------------------------------
# For physical hardware, comment out the previous section selecting TARGET and BOARD and use this
# compiler definition instead of the one above.
#
# import subprocess
# from tvm.micro.contrib import zephyr
Expand All @@ -227,15 +233,15 @@
# project_dir = os.path.join(repo_root, "apps", "microtvm", "zephyr", "demo_runtime")
# compiler = zephyr.ZephyrCompiler(
# project_dir=project_dir,
# board=BOARD if "stm32f746" in str(TARGET) else "qemu_x86",
# board=BOARD,
# zephyr_toolchain_variant="zephyr",
# )
#
# opts = tvm.micro.default_options(f"{project_dir}/crt")
#
# enable printing memory usage statistics of the runtime image
# generated by Zephyr compiler for the physical hardware
# logging.basicConfig(level="INFO")
#
# # Enable printing memory usage statistics for the runtime image generated by Zephyr
# logging.basicConfig(level="INFO")

workspace = tvm.micro.Workspace()
micro_binary = tvm.micro.build_static_runtime(
Expand Down

0 comments on commit 9782e6e

Please sign in to comment.