This is an automated email from the ASF dual-hosted git repository.
jroesch pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git
The following commit(s) were added to refs/heads/main by this push:
new cbc035f Update uTVM code to work with the nRF5340DK dev board. (#7331)
cbc035f is described below
commit cbc035f70a0cd2b3b85681fb77f843bb9b74b1ea
Author: Matt Welsh (OctoML) <[email protected]>
AuthorDate: Wed Jan 27 20:59:26 2021 -0800
Update uTVM code to work with the nRF5340DK dev board. (#7331)
* Various fixes to get nRF5340 working. Not yet there.
* nRF5340 test runs locally.
* Various fixes to get nRF5340 working. Not yet there.
* nRF5340 test runs locally.
* Add `nrfjprog --recover` for nRF5340DK
* Cleanup.
* Remove debugging code.
* Revert submodule update.
* Remove debugging code.
* Fix comment.
* Remove -keys argument.
* Adding some debugging code
* Fix passing west command to ZephyrFlasher.
* Various fixes to get nRF5340 working. Not yet there.
* nRF5340 test runs locally.
* Add `nrfjprog --recover` for nRF5340DK
* Cleanup.
* Various fixes to get nRF5340 working. Not yet there.
* nRF5340 test runs locally.
* Remove debugging code.
* Fix comment.
* Remove -keys argument.
* Fix merge.
---
apps/microtvm/reference-vm/zephyr/pyproject.toml | 3 +++
python/tvm/micro/contrib/zephyr.py | 23 ++++++++++++++---
python/tvm/target/target.py | 3 +++
tests/micro/qemu/conftest.py | 9 +++++++
tests/micro/qemu/test_zephyr.py | 33 +++++++++++++-----------
5 files changed, 53 insertions(+), 18 deletions(-)
diff --git a/apps/microtvm/reference-vm/zephyr/pyproject.toml
b/apps/microtvm/reference-vm/zephyr/pyproject.toml
index f21c272..b4cfc54 100644
--- a/apps/microtvm/reference-vm/zephyr/pyproject.toml
+++ b/apps/microtvm/reference-vm/zephyr/pyproject.toml
@@ -64,6 +64,9 @@ scipy = "^1.4"
python = "^3.6"
tornado = "^6"
typed_ast = "^1.4"
+pyyaml = "^5.4.1"
+pyserial = "^3.5"
+
# AutoTVM
xgboost = {version = "^1.1", optional = true}
diff --git a/python/tvm/micro/contrib/zephyr.py
b/python/tvm/micro/contrib/zephyr.py
index fa032e2..ed1c986 100644
--- a/python/tvm/micro/contrib/zephyr.py
+++ b/python/tvm/micro/contrib/zephyr.py
@@ -191,7 +191,7 @@ class ZephyrCompiler(tvm.micro.Compiler):
with open(os.path.join(output, "main.c"), "w"):
pass
- # expecetd not to exist after populate_tvm_libs
+ # expected not to exist after populate_tvm_libs
build_dir = os.path.join(output, "__tvm_build")
os.mkdir(build_dir)
self._subprocess_env.run(
@@ -241,11 +241,12 @@ class ZephyrCompiler(tvm.micro.Compiler):
def flasher_factory(self):
return compiler.FlasherFactory(
ZephyrFlasher,
- (self._west_cmd,),
+ (self._board,),
dict(
zephyr_base=self._zephyr_base,
project_dir=self._project_dir,
subprocess_env=self._subprocess_env.default_overrides,
+ west_cmd=self._west_cmd,
),
)
@@ -291,7 +292,7 @@ class ZephyrFlasher(tvm.micro.compiler.Flasher):
def __init__(
self,
- west_cmd,
+ board,
zephyr_base=None,
project_dir=None,
subprocess_env=None,
@@ -300,6 +301,7 @@ class ZephyrFlasher(tvm.micro.compiler.Flasher):
flash_args=None,
debug_rpc_session=None,
serial_timeouts=None,
+ west_cmd=None,
):
zephyr_base = zephyr_base or os.environ["ZEPHYR_BASE"]
sys.path.insert(0, os.path.join(zephyr_base, "scripts", "dts"))
@@ -310,6 +312,7 @@ class ZephyrFlasher(tvm.micro.compiler.Flasher):
finally:
sys.path.pop(0)
+ self._board = board
self._zephyr_base = zephyr_base
self._project_dir = project_dir
self._west_cmd = west_cmd
@@ -414,6 +417,20 @@ class ZephyrFlasher(tvm.micro.compiler.Flasher):
build_dir = os.path.dirname(
micro_binary.abspath(micro_binary.labelled_files["cmake_cache"][0])
)
+
+ # The nRF5340DK requires an additional `nrfjprog --recover` before
each flash cycle.
+ # This is because readback protection is enabled by default when this
device is flashed.
+ # Otherwise, flashing may fail with an error such as the following:
+ # ERROR: The operation attempted is unavailable due to readback
protection in
+ # ERROR: your device. Please use --recover to unlock the device.
+ if (
+ self._board.startswith("nrf5340dk")
+ and self._get_flash_runner(cmake_entries) == "nrfjprog"
+ ):
+ recover_args = ["nrfjprog", "--recover"]
+ recover_args.extend(self._get_nrf_device_args())
+ self._subprocess_env.run(recover_args, cwd=build_dir)
+
west_args = (
self._west_cmd
+ ["flash", "--build-dir", build_dir, "--skip-rebuild"]
diff --git a/python/tvm/target/target.py b/python/tvm/target/target.py
index 161cd54..0ebf31a 100644
--- a/python/tvm/target/target.py
+++ b/python/tvm/target/target.py
@@ -234,7 +234,10 @@ def micro(model="unknown", options=None):
trans_table = {
"host": [],
"stm32f746xx": ["-mcpu=cortex-m7", "-march=armv7e-m"],
+ "nrf5340dk": ["-mcpu=cortex-m33"],
}
+ if model not in trans_table:
+ raise ValueError(f"Model {model} not supported by tvm.target.micro.")
opts = _merge_opts(
trans_table[model] + ["-runtime=c", "--system-lib", f"-model={model}"],
options,
diff --git a/tests/micro/qemu/conftest.py b/tests/micro/qemu/conftest.py
index e6cd9f2..3fc54df 100644
--- a/tests/micro/qemu/conftest.py
+++ b/tests/micro/qemu/conftest.py
@@ -14,6 +14,7 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+import pytest
def pytest_addoption(parser):
@@ -25,8 +26,16 @@ def pytest_addoption(parser):
"for microTVM tests."
),
)
+ parser.addoption(
+ "--west-cmd", default="west", help="Path to `west` command for
flashing device."
+ )
def pytest_generate_tests(metafunc):
if "platform" in metafunc.fixturenames:
metafunc.parametrize("platform",
metafunc.config.getoption("microtvm_platforms").split(","))
+
+
[email protected]
+def west_cmd(request):
+ return request.config.getoption("--west-cmd")
diff --git a/tests/micro/qemu/test_zephyr.py b/tests/micro/qemu/test_zephyr.py
index ab3a25d..865c7f8 100644
--- a/tests/micro/qemu/test_zephyr.py
+++ b/tests/micro/qemu/test_zephyr.py
@@ -43,15 +43,15 @@ DEBUG = False
TARGET = None
-def _make_sess_from_op(model, zephyr_board, op_name, sched, arg_bufs):
+def _make_sess_from_op(model, zephyr_board, west_cmd, op_name, sched,
arg_bufs):
target = tvm.target.target.micro(model)
with tvm.transform.PassContext(opt_level=3,
config={"tir.disable_vectorize": True}):
mod = tvm.build(sched, arg_bufs, target, target_host=target,
name=op_name)
- return _make_session(model, target, zephyr_board, mod)
+ return _make_session(model, target, zephyr_board, west_cmd, mod)
-def _make_session(model, target, zephyr_board, mod):
+def _make_session(model, target, zephyr_board, west_cmd, mod):
test_name = f"{os.path.splitext(os.path.abspath(__file__))[0]}-{model}"
prev_build = f"{test_name}-last-build.micro-binary"
workspace_root = (
@@ -65,8 +65,9 @@ def _make_session(model, target, zephyr_board, mod):
project_dir = os.path.join(os.path.dirname(__file__) or ".",
"zephyr-runtime")
compiler = zephyr.ZephyrCompiler(
project_dir=project_dir,
- board="nucleo_f746zg" if "stm32f746" in str(target) else "qemu_x86",
+ board=zephyr_board,
zephyr_toolchain_variant="zephyr",
+ west_cmd=west_cmd,
)
opts = tvm.micro.default_options(f"{project_dir}/crt")
@@ -106,12 +107,12 @@ def _make_session(model, target, zephyr_board, mod):
return tvm.micro.Session(**session_kw)
-def _make_add_sess(model, zephyr_board):
+def _make_add_sess(model, zephyr_board, west_cmd):
A = tvm.te.placeholder((2,), dtype="int8")
B = tvm.te.placeholder((1,), dtype="int8")
C = tvm.te.compute(A.shape, lambda i: A[i] + B[0], name="C")
sched = tvm.te.create_schedule(C.op)
- return _make_sess_from_op(model, zephyr_board, "add", sched, [A, B, C])
+ return _make_sess_from_op(model, zephyr_board, west_cmd, "add", sched, [A,
B, C])
# The models that should pass this configuration. Maps a short, identifying
platform string to
@@ -119,11 +120,12 @@ def _make_add_sess(model, zephyr_board):
PLATFORMS = {
"host": ("host", "qemu_x86"),
"stm32f746xx": ("stm32f746xx", "nucleo_f746zg"),
+ "nrf5340dk": ("nrf5340dk", "nrf5340dk_nrf5340_cpuapp"),
}
# The same test code can be executed on both the QEMU simulation and on real
hardware.
-def test_compile_runtime(platform):
+def test_compile_runtime(platform, west_cmd):
"""Test compiling the on-device runtime."""
model, zephyr_board = PLATFORMS[platform]
@@ -141,11 +143,11 @@ def test_compile_runtime(platform):
system_lib.get_function("add")(A_data, B_data, C_data)
assert (C_data.asnumpy() == np.array([6, 7])).all()
- with _make_add_sess(model, zephyr_board) as sess:
+ with _make_add_sess(model, zephyr_board, west_cmd) as sess:
test_basic_add(sess)
-def test_platform_timer(platform):
+def test_platform_timer(platform, west_cmd):
"""Test compiling the on-device runtime."""
model, zephyr_board = PLATFORMS[platform]
@@ -168,11 +170,11 @@ def test_platform_timer(platform):
assert result.mean > 0
assert len(result.results) == 3
- with _make_add_sess(model, zephyr_board) as sess:
+ with _make_add_sess(model, zephyr_board, west_cmd) as sess:
test_basic_add(sess)
-def test_relay(platform):
+def test_relay(platform, west_cmd):
"""Testing a simple relay graph"""
model, zephyr_board = PLATFORMS[platform]
shape = (10,)
@@ -188,7 +190,7 @@ def test_relay(platform):
with tvm.transform.PassContext(opt_level=3,
config={"tir.disable_vectorize": True}):
graph, mod, params = tvm.relay.build(func, target=target)
- with _make_session(model, target, zephyr_board, mod) as session:
+ with _make_session(model, target, zephyr_board, west_cmd, mod) as session:
graph_mod = tvm.micro.create_local_graph_runtime(
graph, session.get_system_lib(), session.context
)
@@ -254,14 +256,14 @@ class CcompilerAnnotator(ExprMutator):
return super().visit_call(call)
-def check_result(relay_mod, model, zephyr_board, map_inputs, out_shape,
result):
+def check_result(relay_mod, model, zephyr_board, west_cmd, map_inputs,
out_shape, result):
"""Helper function to verify results"""
TOL = 1e-5
target = tvm.target.target.micro(model)
with tvm.transform.PassContext(opt_level=3,
config={"tir.disable_vectorize": True}):
graph, mod, params = tvm.relay.build(relay_mod, target=target)
- with _make_session(model, target, zephyr_board, mod) as session:
+ with _make_session(model, target, zephyr_board, west_cmd, mod) as session:
rt_mod = tvm.micro.create_local_graph_runtime(
graph, session.get_system_lib(), session.context
)
@@ -280,7 +282,7 @@ def check_result(relay_mod, model, zephyr_board,
map_inputs, out_shape, result):
tvm.testing.assert_allclose(out.asnumpy(), results[idx], rtol=TOL,
atol=TOL)
-def test_byoc_utvm(platform):
+def test_byoc_utvm(platform, west_cmd):
"""This is a simple test case to check BYOC capabilities of uTVM"""
model, zephyr_board = PLATFORMS[platform]
x = relay.var("x", shape=(10, 10))
@@ -335,6 +337,7 @@ def test_byoc_utvm(platform):
),
model=model,
zephyr_board=zephyr_board,
+ west_cmd=west_cmd,
)