This is an automated email from the ASF dual-hosted git repository.
areusch 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 ed6e7c0 [microTVM] Enable micro tvmc tutorial testing in CI (#10555)
ed6e7c0 is described below
commit ed6e7c07a5bd995c6e169a891c4af34561e01033
Author: Mehrdad Hessar <[email protected]>
AuthorDate: Wed Mar 16 14:38:33 2022 -0700
[microTVM] Enable micro tvmc tutorial testing in CI (#10555)
* Add script convertor
* Address comments: added test
* address comments
---
docs/script_convert.py | 94 ++++++++++++
.../{micro_tvmc.py => micro_tvmc.sh} | 110 +++++++-------
tests/python/{unittest => ci}/test_ci.py | 5 +-
tests/python/ci/test_script_converter.py | 162 +++++++++++++++++++++
.../task_lint.sh => python/ci/test_utils.py} | 41 +-----
...k_lint.sh => task_convert_scripts_to_python.sh} | 42 +-----
tests/scripts/task_lint.sh | 3 +
tests/scripts/task_python_docs.sh | 3 +
tests/scripts/task_python_microtvm.sh | 3 +-
9 files changed, 324 insertions(+), 139 deletions(-)
diff --git a/docs/script_convert.py b/docs/script_convert.py
new file mode 100644
index 0000000..edd173b
--- /dev/null
+++ b/docs/script_convert.py
@@ -0,0 +1,94 @@
+# 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.
+
+import argparse
+import pathlib
+
+BASH = "# bash"
+BASH_IGNORE = "# bash-ignore"
+BASH_MULTILINE_COMMENT_START = ": '"
+BASH_MULTILINE_COMMENT_END = "'"
+
+
+def bash_to_python(src_path: pathlib.Path, dest_path: pathlib.Path):
+ """Convert a bash script file to a Python format compatible with Sphinx
doc."""
+ with open(src_path, "r") as src_f:
+ with open(dest_path, "w") as dest_f:
+ line = src_f.readline()
+ bash_block = []
+ bash_detected = False
+ bash_ignore_detected = False
+ new_line_required = False
+ while line:
+ line = line.strip("\n").strip("\r")
+ if bash_detected:
+ if line == BASH:
+ # write the bash block to destination
+ if new_line_required:
+ dest_f.write("\n")
+ python_code = "# .. code-block:: bash\n#\n"
+ for bash_line in bash_block:
+ python_code += f"#\t {bash_line}\n"
+ python_code += "#"
+ dest_f.write(python_code)
+
+ bash_detected = False
+ bash_block = []
+ new_line_required = True
+ else:
+ # add new bash command line
+ bash_block.append(line)
+ elif bash_ignore_detected:
+ if line == BASH_IGNORE:
+ bash_ignore_detected = False
+ new_line_required = True
+ else:
+ new_line_required = False
+ pass
+ else:
+ if line == BASH:
+ bash_detected = True
+ elif line == BASH_IGNORE:
+ bash_ignore_detected = True
+ elif line in [BASH_MULTILINE_COMMENT_START,
BASH_MULTILINE_COMMENT_END]:
+ if new_line_required:
+ dest_f.write("\n")
+ dest_f.write('"""')
+ new_line_required = True
+ else:
+ if new_line_required:
+ dest_f.write("\n")
+ dest_f.write(f"{line}")
+ new_line_required = True
+
+ line = src_f.readline()
+ if new_line_required:
+ dest_f.write("\n")
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Convert tutorial script to
Python.")
+ parser.add_argument("script", type=str, help="Path to script file.")
+ args = parser.parse_args()
+
+ src_path = pathlib.Path(args.script)
+ dest_path = src_path.parent / f"{src_path.stem}.py"
+ bash_to_python(src_path, dest_path)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/gallery/how_to/work_with_microtvm/micro_tvmc.py
b/gallery/how_to/work_with_microtvm/micro_tvmc.sh
old mode 100644
new mode 100755
similarity index 85%
rename from gallery/how_to/work_with_microtvm/micro_tvmc.py
rename to gallery/how_to/work_with_microtvm/micro_tvmc.sh
index 423e0f1..0b78921
--- a/gallery/how_to/work_with_microtvm/micro_tvmc.py
+++ b/gallery/how_to/work_with_microtvm/micro_tvmc.sh
@@ -15,7 +15,7 @@
# specific language governing permissions and limitations
# under the License.
-"""
+: '
.. _tutorial-micro-tvmc:
Executing a Tiny Model with TVMC Micro
@@ -25,7 +25,7 @@ Executing a Tiny Model with TVMC Micro
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::
@@ -42,6 +42,10 @@ and run the model all using `tvmc micro` command.
# ./docker/bash.sh tlcpack/ci-qemu
#
+# bash-ignore
+shopt -s expand_aliases
+alias tvmc="python3 -m tvm.driver.tvmc"
+# bash-ignore
############################################################
# Using TVMC Micro
@@ -55,16 +59,15 @@ and run the model all using `tvmc micro` command.
#
# To check if you have TVMC command installed on your machine, you can run:
#
-# .. code-block:: bash
-#
-# tvmc --help
-#
+# bash
+tvmc --help
+# bash
# 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
+# bash
+tvmc micro --help
+# bash
#
# 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
@@ -80,10 +83,9 @@ and run the model all using `tvmc micro` command.
#
# 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
-#
+# bash
+wget
https://github.com/tensorflow/tflite-micro/raw/main/tensorflow/lite/micro/examples/magic_wand/magic_wand.tflite
+# bash
############################################################
# Compiling a TFLite model to a Model Library Format
@@ -95,19 +97,18 @@ and run the model all using `tvmc micro` command.
#
# 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
-#
+# 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
+# bash
# 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'``.
@@ -122,14 +123,13 @@ and run the model all using `tvmc micro` command.
# 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
-#
+# bash
+tvmc micro create \
+ project \
+ model.tar \
+ zephyr \
+ --project-option project_type=host_driven zephyr_board=qemu_x86
+# bash
# 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>`_.
@@ -148,26 +148,24 @@ and run the model all using `tvmc micro` command.
# 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
-#
+# bash
+tvmc micro build \
+ project \
+ zephyr \
+ --project-option zephyr_board=qemu_x86
+# bash
# 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
-#
+# bash
+tvmc micro flash \
+ project \
+ zephyr \
+ --project-option zephyr_board=qemu_x86
+# bash
############################################################
# Run Tiny Model on Micro Target
@@ -179,14 +177,14 @@ and run the model all using `tvmc micro` command.
# 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
+# bash
+tvmc run \
+ --device micro \
+ project \
+ --project-option zephyr_board=qemu_x86 \
+ --fill-mode ones \
+ --print-top 4
+# bash
# # Output:
# #
# # INFO:__main__:b'[100%] [QEMU] CPU: qemu32,+nx,+pae\n'
diff --git a/tests/python/unittest/test_ci.py b/tests/python/ci/test_ci.py
similarity index 99%
rename from tests/python/unittest/test_ci.py
rename to tests/python/ci/test_ci.py
index 645f239..4c7ad7c 100644
--- a/tests/python/unittest/test_ci.py
+++ b/tests/python/ci/test_ci.py
@@ -15,16 +15,13 @@
# specific language governing permissions and limitations
# under the License.
-import pathlib
import subprocess
import sys
import json
import textwrap
-import tempfile
-
import pytest
-REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent.parent.parent
+from test_utils import REPO_ROOT
class TempGit:
diff --git a/tests/python/ci/test_script_converter.py
b/tests/python/ci/test_script_converter.py
new file mode 100644
index 0000000..a792c13
--- /dev/null
+++ b/tests/python/ci/test_script_converter.py
@@ -0,0 +1,162 @@
+# 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.
+
+import sys
+
+import pytest
+
+from tvm.contrib import utils
+
+from test_utils import REPO_ROOT
+
+sys.path.insert(0, str(REPO_ROOT / "docs"))
+from script_convert import (
+ bash_to_python,
+ BASH,
+ BASH_IGNORE,
+ BASH_MULTILINE_COMMENT_START,
+ BASH_MULTILINE_COMMENT_END,
+)
+
+
+def test_bash_cmd():
+ temp = utils.tempdir()
+ src_path = temp / "src.sh"
+ dest_path = temp / "dest.py"
+
+ with open(src_path, "w") as src_f:
+ src_f.write(BASH)
+ src_f.write("\n")
+ src_f.write("tvmc\n")
+ src_f.write(BASH)
+ src_f.write("\n")
+
+ bash_to_python(src_path, dest_path)
+
+ with open(dest_path, "r") as dest_f:
+ generated_cmd = dest_f.read()
+
+ expected_cmd = "# .. code-block:: bash\n" "#\n" "#\t tvmc\n" "#\n"
+
+ assert generated_cmd == expected_cmd
+
+
+def test_bash_ignore_cmd():
+ temp = utils.tempdir()
+ src_path = temp / "src.sh"
+ dest_path = temp / "dest.py"
+
+ with open(src_path, "w") as src_f:
+ src_f.write("# start\n")
+ src_f.write(BASH_IGNORE)
+ src_f.write("\n")
+ src_f.write("tvmc\n")
+ src_f.write(BASH_IGNORE)
+ src_f.write("\n")
+ src_f.write("# end\n")
+
+ bash_to_python(src_path, dest_path)
+
+ with open(dest_path, "r") as dest_f:
+ generated_cmd = dest_f.read()
+
+ expected_cmd = "# start\n" "# end\n"
+ assert generated_cmd == expected_cmd
+
+
+def test_no_command():
+ temp = utils.tempdir()
+ src_path = temp / "src.sh"
+ dest_path = temp / "dest.py"
+
+ with open(src_path, "w") as src_f:
+ src_f.write("# start\n")
+ src_f.write("# description\n")
+ src_f.write("end\n")
+
+ bash_to_python(src_path, dest_path)
+
+ with open(dest_path, "r") as dest_f:
+ generated_cmd = dest_f.read()
+
+ expected_cmd = "# start\n" "# description\n" "end\n"
+ assert generated_cmd == expected_cmd
+
+
+def test_text_and_bash_command():
+ temp = utils.tempdir()
+ src_path = temp / "src.sh"
+ dest_path = temp / "dest.py"
+
+ with open(src_path, "w") as src_f:
+ src_f.write("# start\n")
+ src_f.write(BASH)
+ src_f.write("\n")
+ src_f.write("tvmc\n")
+ src_f.write(BASH)
+ src_f.write("\n")
+ src_f.write("# end\n")
+
+ bash_to_python(src_path, dest_path)
+
+ with open(dest_path, "r") as dest_f:
+ generated_cmd = dest_f.read()
+
+ expected_cmd = "# start\n" "# .. code-block:: bash\n" "#\n" "#\t tvmc\n"
"#\n" "# end\n"
+
+ assert generated_cmd == expected_cmd
+
+
+def test_last_line_break():
+ temp = utils.tempdir()
+ src_path = temp / "src.sh"
+ dest_path = temp / "dest.py"
+
+ with open(src_path, "w") as src_f:
+ src_f.write("# start\n")
+ src_f.write("# end\n")
+
+ bash_to_python(src_path, dest_path)
+
+ with open(dest_path, "r") as dest_f:
+ generated_cmd = dest_f.read()
+
+ expected_cmd = "# start\n" "# end\n"
+
+ assert generated_cmd == expected_cmd
+
+
+def test_multiline_comment():
+ temp = utils.tempdir()
+ src_path = temp / "src.sh"
+ dest_path = temp / "dest.py"
+
+ with open(src_path, "w") as src_f:
+ src_f.write(BASH_MULTILINE_COMMENT_START)
+ src_f.write("\n")
+ src_f.write("comment\n")
+ src_f.write(BASH_MULTILINE_COMMENT_END)
+ src_f.write("\n")
+
+ bash_to_python(src_path, dest_path)
+
+ with open(dest_path, "r") as dest_f:
+ generated_cmd = dest_f.read()
+
+ expected_cmd = '"""\n' "comment\n" '"""\n'
+
+ assert generated_cmd == expected_cmd
diff --git a/tests/scripts/task_lint.sh b/tests/python/ci/test_utils.py
old mode 100755
new mode 100644
similarity index 52%
copy from tests/scripts/task_lint.sh
copy to tests/python/ci/test_utils.py
index 0a01bea..0ad88f1
--- a/tests/scripts/task_lint.sh
+++ b/tests/python/ci/test_utils.py
@@ -1,4 +1,3 @@
-#!/usr/bin/env bash
# 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
@@ -16,42 +15,6 @@
# specific language governing permissions and limitations
# under the License.
-set -euxo pipefail
+import pathlib
-cleanup()
-{
- rm -rf /tmp/$$.*
-}
-trap cleanup 0
-
-
-echo "Checking file types..."
-python3 tests/lint/check_file_type.py
-
-echo "Checking ASF license headers..."
-tests/lint/check_asf_header.sh --local
-
-echo "Linting the C++ code..."
-tests/lint/cpplint.sh
-
-echo "clang-format check..."
-tests/lint/clang_format.sh
-
-echo "Rust check..."
-tests/lint/rust_format.sh
-
-echo "black check..."
-tests/lint/python_format.sh
-
-echo "Linting the Python code..."
-tests/lint/pylint.sh
-tests/lint/flake8.sh
-
-echo "Linting the JNI code..."
-tests/lint/jnilint.sh
-
-echo "Checking C++ documentation..."
-tests/lint/cppdocs.sh
-
-echo "Type checking with MyPy ..."
-tests/scripts/task_mypy.sh
+REPO_ROOT = pathlib.Path(__file__).resolve().parent.parent.parent.parent
diff --git a/tests/scripts/task_lint.sh
b/tests/scripts/task_convert_scripts_to_python.sh
similarity index 54%
copy from tests/scripts/task_lint.sh
copy to tests/scripts/task_convert_scripts_to_python.sh
index 0a01bea..b2164cb 100755
--- a/tests/scripts/task_lint.sh
+++ b/tests/scripts/task_convert_scripts_to_python.sh
@@ -16,42 +16,6 @@
# specific language governing permissions and limitations
# under the License.
-set -euxo pipefail
-
-cleanup()
-{
- rm -rf /tmp/$$.*
-}
-trap cleanup 0
-
-
-echo "Checking file types..."
-python3 tests/lint/check_file_type.py
-
-echo "Checking ASF license headers..."
-tests/lint/check_asf_header.sh --local
-
-echo "Linting the C++ code..."
-tests/lint/cpplint.sh
-
-echo "clang-format check..."
-tests/lint/clang_format.sh
-
-echo "Rust check..."
-tests/lint/rust_format.sh
-
-echo "black check..."
-tests/lint/python_format.sh
-
-echo "Linting the Python code..."
-tests/lint/pylint.sh
-tests/lint/flake8.sh
-
-echo "Linting the JNI code..."
-tests/lint/jnilint.sh
-
-echo "Checking C++ documentation..."
-tests/lint/cppdocs.sh
-
-echo "Type checking with MyPy ..."
-tests/scripts/task_mypy.sh
+SCRIPTS_DIR=$(dirname "${BASH_SOURCE[0]}")
+TVM_DIR=$(cd "${SCRIPTS_DIR}" && git rev-parse --show-toplevel)
+python3 "${TVM_DIR}/docs/script_convert.py"
"${TVM_DIR}/gallery/how_to/work_with_microtvm/micro_tvmc.sh"
diff --git a/tests/scripts/task_lint.sh b/tests/scripts/task_lint.sh
index 0a01bea..a6021e6 100755
--- a/tests/scripts/task_lint.sh
+++ b/tests/scripts/task_lint.sh
@@ -25,6 +25,9 @@ cleanup()
trap cleanup 0
+echo "Convert scripts to Python..."
+tests/scripts/task_convert_scripts_to_python.sh
+
echo "Checking file types..."
python3 tests/lint/check_file_type.py
diff --git a/tests/scripts/task_python_docs.sh
b/tests/scripts/task_python_docs.sh
index 9266280..b947c65 100755
--- a/tests/scripts/task_python_docs.sh
+++ b/tests/scripts/task_python_docs.sh
@@ -58,6 +58,9 @@ sphinx_precheck() {
function join_by { local IFS="$1"; shift; echo "$*"; }
+# Convert bash tutorials to Python format
+tests/scripts/task_convert_scripts_to_python.sh
+
# These warnings are produced during the docs build for various reasons and are
# known to not signficantly affect the output. Don't add anything new to this
# list without special consideration of its effects, and don't add anything
with
diff --git a/tests/scripts/task_python_microtvm.sh
b/tests/scripts/task_python_microtvm.sh
index 4fb303e..d13ee91 100755
--- a/tests/scripts/task_python_microtvm.sh
+++ b/tests/scripts/task_python_microtvm.sh
@@ -41,9 +41,10 @@ run_pytest ctypes python-microtvm-stm32 tests/micro/stm32
run_pytest ctypes python-microtvm-common-qemu_x86 tests/micro/common
--board=qemu_x86
run_pytest ctypes python-microtvm-common-due tests/micro/common
--test-build-only --board=due
-# # Tutorials running with host CRT
+# Tutorials
python3 gallery/how_to/work_with_microtvm/micro_tflite.py
python3 gallery/how_to/work_with_microtvm/micro_autotune.py
+./gallery/how_to/work_with_microtvm/micro_tvmc.sh
# Tutorials running with Zephyr
export TVM_MICRO_USE_HW=1