You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by GitBox <gi...@apache.org> on 2021/09/12 19:16:51 UTC

[GitHub] [tvm] sergey-grovety opened a new pull request #8990: [microTVM] Update support for ARMv7m intrinsic

sergey-grovety opened a new pull request #8990:
URL: https://github.com/apache/tvm/pull/8990


    - Improved implementaion of gemm function for conv2d
    - Removed %4 restriction for channels
    - Added test case to verify SMLAD intrinsic speed acceleration
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] mehrdadh commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r709458696



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       can we use [ARM Cortex-M3 Emulation (QEMU)](https://docs.zephyrproject.org/latest/boards/arm/qemu_cortex_m3/doc/index.html)?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] mehrdadh commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r719734837



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,225 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import test_utils
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                test_utils.loadCMSIS(model_files_path)
+                tf.add(model_files_path, arcname=os.path.relpath(model_files_path, tar_temp_dir))
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            test_utils.create_header_file("input_data", sample, "include", tf)
+            test_utils.create_header_file(
+                "output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf
+            )
+
+        project, _ = test_utils.build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(
+        temp_dir, board, west_cmd, lowered, build_config, sample, output_shape
+    )
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = test_utils.get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "mps2_an521",
+        "stm32f746xx_disco",

Review comment:
       this board name has changed recently to `stm32f746g_disco`.
   https://github.com/apache/tvm/pull/8998/files




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-929345342


   > not sure if we should land #9092 first and refactor test logic there? otherwise aside from the two comments i think we can merge and move forwards.
   
   Yes. Need to clean up from this.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] mehrdadh commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r707500113



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):

Review comment:
       same here.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):

Review comment:
       Some of the functions in this fire are in common with https://github.com/apache/tvm/blob/a36200411180d5d8b9501c90937629117317d0bb/tests/micro/zephyr/test_zephyr_aot.py
   I suggest to add a `test_utils.py` file under `tests/micro/zephyr/` to reuse these functions.

##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       add a new line here.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):

Review comment:
       same here.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (

Review comment:
       suggestion: move this to conftest.py so we could reuse it in all three test files.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):

Review comment:
       same here.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r711897736



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       @u99127 do you suggest any other CI test we could use? otherwise, we can test on-device for now.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-931777605


   thanks @sergey-grovety and team!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r708141924



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (

Review comment:
       Ok




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r719513626



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746g_disco" ] || [ $board == "nucleo_f746zg" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       we discussed offline and have decided to proceed with local testing in this PR. in a follow-on, we will add support for Corstone 300 tests.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r707587171



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       curious if you are including CMSIS-NN anywhere?

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       while this should essentially always pass, i'm wondering if it may be a bit brittle to check in to TVM's mainline CI. in general with µTVM, we'll gauge performance using an offline process (at least for now). it might be better to track performance regressions using that flow rather than this.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-923092946


   > just a heads up about this PR: #9026
   > I added a test_utils.py in this PR for other reasons and after merge you need to rebase with main to avoid merge conflict.
   
   Ok


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] mehrdadh commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-923035055


   just a heads up about this PR: https://github.com/apache/tvm/pull/9026
   I added a test_utils.py in this PR for other reasons and after merge you need to rebase with main to avoid merge conflict.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r708476285



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):

Review comment:
       Ok

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):

Review comment:
       Ok

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):

Review comment:
       Ok

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):

Review comment:
       Ok




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-920335684


   > for the test image maybe you could reuse this image: https://github.com/apache/tvm/blob/main/tests/micro/testdata/mnist/digit-2.jpg
   
   Yes, sure.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r716987495



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746g_disco" ] || [ $board == "nucleo_f746zg" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       could you move this to tests/scripts/task_python_microtvm.sh? This is just the base-box pre-release test, where we just want to do a smoke test to make sure that Zephyr is working with attached hardware.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):

Review comment:
       can you move to a test-util per my comment on other PR?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r717665531



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):

Review comment:
       Ok




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-925143913


   > @sergey-grovety i chatted with @u99127 and he indicated his preference is to use the ARM FVP to test these schedules. those platforms should properly support SMLAD intrinsic and any other Cortex-M55 changes. The Corstone300 FVP is available on ci_cpu and an example of using it is [here](https://github.com/apache/tvm/blob/main/tests/python/relay/aot/corstone300.mk). could you see if you can adopt this approach for testing? you'd add a test to tests/python/unittest, i guess. it's not quite the conventional spot, but the typical topi tests are run in ci_gpu.
   
   Sure, we will try to adopt ARM FPV in next PR. We skip performance test for QEMU board for now, validating result only. Is it ok?


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r709432323



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       it's tempting to inline `read_and_pad`, which should get inlined by the compiler at codegen time. CMSIS 5 is [under ASF 2.0](https://github.com/ARM-software/CMSIS_5/blob/develop/LICENSE.txt). the tricky thing is that there are quite a lot of header dependencies designed to support a variety of toolchains. it would be nice to preserve support for those.
   
   given that, i'm tempted to opt for downloading CMSIS to the temporary directory. we will likely need to come up with a solution for this more broadly to work with CMSIS-NN as well cc @ashutosh-arm @u99127 @manupa-arm 




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-924471382


   @sergey-grovety i chatted with @u99127 and he indicated his preference is to use the ARM FVP to test these schedules. those platforms should properly support SMLAD intrinsic and any other Cortex-M55 changes. The Corstone300 FVP is available on ci_cpu and an example of using it is [here](https://github.com/apache/tvm/blob/main/tests/python/relay/aot/corstone300.mk). could you see if you can adopt this approach for testing? you'd add a test to tests/python/unittest, i guess. it's not quite the conventional spot, but the typical topi tests are run in ci_gpu.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-926212214


   @sergey-grovety so long as the QEMU supports the SMLAD instruction i'm fine with that. please fix the merge conflict and we can proceed to the next PR.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r708480379



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       Not now. It seems we need download subset of CMSIS inside the test temporary folder to be able to build test project. Isn't so?
   Another option is to eliminate need of CMSIS inside gemm C code implementation..




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r709406621



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       @u99127 did we add this to the regression tests yet? I think I just saw the Makefile change, but not sure we have rebuilt the ci_qemu image to include the FVP yet?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] mehrdadh commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-919339009


   for the test image maybe you could reuse this image: https://github.com/apache/tvm/blob/main/tests/micro/testdata/mnist/digit-2.jpg


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r709527891



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       Ok. Will download subset of CMSIS headers in temporary directory for this specific test.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r719840689



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,225 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import test_utils
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                test_utils.loadCMSIS(model_files_path)
+                tf.add(model_files_path, arcname=os.path.relpath(model_files_path, tar_temp_dir))
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            test_utils.create_header_file("input_data", sample, "include", tf)
+            test_utils.create_header_file(
+                "output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf
+            )
+
+        project, _ = test_utils.build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(
+        temp_dir, board, west_cmd, lowered, build_config, sample, output_shape
+    )
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = test_utils.get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "mps2_an521",
+        "stm32f746xx_disco",

Review comment:
       @sergey-grovety given the CI is green and upcoming work on the test strategy feel free to address this in a follow-on.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch merged pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch merged pull request #8990:
URL: https://github.com/apache/tvm/pull/8990


   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r716987495



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746g_disco" ] || [ $board == "nucleo_f746zg" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       could you move this to tests/scripts/task_python_microtvm.sh? This is just the base-box pre-release test, where we just want to do a smoke test to make sure that Zephyr is working with attached hardware.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):

Review comment:
       can you move to a test-util per my comment on other PR?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] mehrdadh commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
mehrdadh commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r716849515



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):
+    REPO_PATH = "ARM-software/CMSIS_5"
+    BRANCH = "master"
+    API_PATH_URL = f"https://api.github.com/repos/{REPO_PATH}/git/trees"
+    RAW_PATH_URL = f"https://raw.githubusercontent.com/{REPO_PATH}/{BRANCH}"
+
+    url = "https://api.github.com/repos/ARM-software/CMSIS_5/git/trees/master?recursive=1"
+    r = requests.get(url)
+    res = r.json()
+
+    include_trees = {}
+
+    for file in res["tree"]:
+        if file["path"] in {"CMSIS/DSP/Include", "CMSIS/DSP/Include/dsp", "CMSIS/NN/Include"}:
+            include_trees.update({file["path"]: file["sha"]})
+
+    for path, sha in include_trees.items():
+        url = f"{API_PATH_URL}/{sha}"
+        content = json.load(urlopen(url))
+        temp_path = f"{temp_dir}"
+        if path == "CMSIS/DSP/Include/dsp":
+            temp_path = f"{temp_dir}/dsp"
+            if not os.path.isdir(temp_path):
+                os.makedirs(temp_path)
+        for item in content["tree"]:
+            if item["type"] == "blob":
+                file_name = item["path"]
+                file_url = f"{RAW_PATH_URL}/{path}/{file_name}"
+                print(file_name, "   ", file_url)
+                try:
+                    urlretrieve(file_url, f"{temp_path}/{file_name}")
+                except HTTPError as e:
+                    print(f"Failed to download {file_url}: {e}")
+
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                _loadCMSIS(model_files_path)
+                tf.add(model_files_path, arcname=os.path.relpath(model_files_path, tar_temp_dir))
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            create_header_file("input_data", sample, "include", tf)
+            create_header_file(
+                "output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf
+            )
+
+        project, _ = build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(
+        temp_dir, board, west_cmd, lowered, build_config, sample, output_shape
+    )
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "mps2_an521",
+        "stm32f746xx_disco",
+        "nucleo_f746zg",
+        "nucleo_l4r5zi",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "mnist"
+
+    relay_mod, params = _open_tflite_model()
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_simd = _apply_desired_layout_simd(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_simd = _apply_desired_layout_no_simd(relay_mod)
+
+    target = tvm.target.target.micro(
+        model,
+        options=[
+            "-keys=arm_cpu,cpu",
+            "-link-params=1",
+            "--executor=aot",
+            "--unpacked-api=1",
+            "--interface-api=c",
+        ],
+    )
+
+    temp_dir_simd = temp_dir / "simd"
+    temp_dir_no_simd = temp_dir / "nosimd"
+
+    os.makedirs(temp_dir_simd, exist_ok=True)
+    os.makedirs(temp_dir_no_simd, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_simd = relay.build(relay_mod_simd, target, params=params)
+        lowered_no_simd = relay.build(relay_mod_no_simd, target, params=params)
+        result_simd, time_simd = _run_model(
+            temp_dir_simd, board, west_cmd, lowered_simd, build_config, sample, output_shape
+        )
+        result_no_simd, time_no_simd = _run_model(
+            temp_dir_no_simd, board, west_cmd, lowered_no_simd, build_config, sample, output_shape
+        )
+
+    assert result_no_simd == result_simd == 2
+
+    if board not in [

Review comment:
       Could you please clarify why this board is excluded?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#issuecomment-929345342


   > not sure if we should land #9092 first and refactor test logic there? otherwise aside from the two comments i think we can merge and move forwards.
   
   Yes. Need to clean up from this.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r716900954



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):
+    REPO_PATH = "ARM-software/CMSIS_5"
+    BRANCH = "master"
+    API_PATH_URL = f"https://api.github.com/repos/{REPO_PATH}/git/trees"
+    RAW_PATH_URL = f"https://raw.githubusercontent.com/{REPO_PATH}/{BRANCH}"
+
+    url = "https://api.github.com/repos/ARM-software/CMSIS_5/git/trees/master?recursive=1"
+    r = requests.get(url)
+    res = r.json()
+
+    include_trees = {}
+
+    for file in res["tree"]:
+        if file["path"] in {"CMSIS/DSP/Include", "CMSIS/DSP/Include/dsp", "CMSIS/NN/Include"}:
+            include_trees.update({file["path"]: file["sha"]})
+
+    for path, sha in include_trees.items():
+        url = f"{API_PATH_URL}/{sha}"
+        content = json.load(urlopen(url))
+        temp_path = f"{temp_dir}"
+        if path == "CMSIS/DSP/Include/dsp":
+            temp_path = f"{temp_dir}/dsp"
+            if not os.path.isdir(temp_path):
+                os.makedirs(temp_path)
+        for item in content["tree"]:
+            if item["type"] == "blob":
+                file_name = item["path"]
+                file_url = f"{RAW_PATH_URL}/{path}/{file_name}"
+                print(file_name, "   ", file_url)
+                try:
+                    urlretrieve(file_url, f"{temp_path}/{file_name}")
+                except HTTPError as e:
+                    print(f"Failed to download {file_url}: {e}")
+
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                _loadCMSIS(model_files_path)
+                tf.add(model_files_path, arcname=os.path.relpath(model_files_path, tar_temp_dir))
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            create_header_file("input_data", sample, "include", tf)
+            create_header_file(
+                "output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf
+            )
+
+        project, _ = build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(
+        temp_dir, board, west_cmd, lowered, build_config, sample, output_shape
+    )
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "mps2_an521",
+        "stm32f746xx_disco",
+        "nucleo_f746zg",
+        "nucleo_l4r5zi",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "mnist"
+
+    relay_mod, params = _open_tflite_model()
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_simd = _apply_desired_layout_simd(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_simd = _apply_desired_layout_no_simd(relay_mod)
+
+    target = tvm.target.target.micro(
+        model,
+        options=[
+            "-keys=arm_cpu,cpu",
+            "-link-params=1",
+            "--executor=aot",
+            "--unpacked-api=1",
+            "--interface-api=c",
+        ],
+    )
+
+    temp_dir_simd = temp_dir / "simd"
+    temp_dir_no_simd = temp_dir / "nosimd"
+
+    os.makedirs(temp_dir_simd, exist_ok=True)
+    os.makedirs(temp_dir_no_simd, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_simd = relay.build(relay_mod_simd, target, params=params)
+        lowered_no_simd = relay.build(relay_mod_no_simd, target, params=params)
+        result_simd, time_simd = _run_model(
+            temp_dir_simd, board, west_cmd, lowered_simd, build_config, sample, output_shape
+        )
+        result_no_simd, time_no_simd = _run_model(
+            temp_dir_no_simd, board, west_cmd, lowered_no_simd, build_config, sample, output_shape
+        )
+
+    assert result_no_simd == result_simd == 2
+
+    if board not in [

Review comment:
       Time performance measurements on QEMU emulator are always equal to zero.

##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):

Review comment:
       Ok

##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746g_disco" ] || [ $board == "nucleo_f746zg" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       It seems moving to tests/scripts/task_python_microtvm.sh make no sense. The only supported platform there is qemu_x86 for now. We don't run our test with it. And mps2_an521 disabled.
   BTW, all tests in tests/micro/zephyr must be called, isn't it?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r709531309



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       We've failed to use qemu_cortex_m3 from Zephyr. It;s crashed inside no mater using SMLAD or not.
   QEMU support for m55 in Zephyr is not implemented yet, afaik.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r711916315



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       @areusch Will test with QEMU 5 shortly... With MPS2-AN521 qemu emulator.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r717705052



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746g_disco" ] || [ $board == "nucleo_f746zg" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       It seems moving to tests/scripts/task_python_microtvm.sh make no sense. The only supported platform there is qemu_x86 for now. We don't run our test with it. And mps2_an521 disabled.
   BTW, all tests in tests/micro/zephyr must be called, isn't it?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] areusch commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
areusch commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r709435990



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       @u99127 i'm remembering now i'm not sure if we intended to add Corstone to regression. what do you think of using one of the Zephyr QEMU targets?




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] u99127 commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
u99127 commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r708113500



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       You should be able to write this test with AoT and using the Corstone-300 FVP or indeed QEMU, the Cortex-M55 is an implementation of the Armv8-M architecture which is a superset of the Armv7-M architecture and thus contains the SMLAD intrinsic. Thus we would be able to get functional testing going using the Corstone-300 FVP or QEMU.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r708170291



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       Ok




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r716900954



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,267 @@
+# 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 logging
+import os
+import pathlib
+import sys
+import tarfile
+import tempfile
+
+from urllib.request import urlopen, urlretrieve
+from urllib.error import HTTPError
+import json
+
+import pytest
+import numpy as np
+
+import requests
+
+from test_utils import create_header_file
+from test_utils import build_project
+from test_utils import get_message
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+from tvm import relay
+
+from tvm.contrib.download import download_testdata
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+
+def _open_tflite_model():
+    # Import TFLite model
+
+    model_url = "https://github.com/tlc-pack/web-data/raw/main/testdata/microTVM/model/mnist_model_quant.tflite"
+    model_path = download_testdata(model_url, "mnist_model_quant.tflite", module="model")
+
+    tflite_model_buf = open(model_path, "rb").read()
+
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWOI"], "nn.conv2d": ["NHWC", "HWOI"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _apply_desired_layout_no_simd(relay_mod):
+
+    desired_layouts = {"qnn.conv2d": ["NHWC", "HWIO"], "nn.conv2d": ["NHWC", "HWIO"]}
+
+    seq = tvm.transform.Sequential(
+        [relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)]
+    )
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+
+def _loadCMSIS(temp_dir):
+    REPO_PATH = "ARM-software/CMSIS_5"
+    BRANCH = "master"
+    API_PATH_URL = f"https://api.github.com/repos/{REPO_PATH}/git/trees"
+    RAW_PATH_URL = f"https://raw.githubusercontent.com/{REPO_PATH}/{BRANCH}"
+
+    url = "https://api.github.com/repos/ARM-software/CMSIS_5/git/trees/master?recursive=1"
+    r = requests.get(url)
+    res = r.json()
+
+    include_trees = {}
+
+    for file in res["tree"]:
+        if file["path"] in {"CMSIS/DSP/Include", "CMSIS/DSP/Include/dsp", "CMSIS/NN/Include"}:
+            include_trees.update({file["path"]: file["sha"]})
+
+    for path, sha in include_trees.items():
+        url = f"{API_PATH_URL}/{sha}"
+        content = json.load(urlopen(url))
+        temp_path = f"{temp_dir}"
+        if path == "CMSIS/DSP/Include/dsp":
+            temp_path = f"{temp_dir}/dsp"
+            if not os.path.isdir(temp_path):
+                os.makedirs(temp_path)
+        for item in content["tree"]:
+            if item["type"] == "blob":
+                file_name = item["path"]
+                file_url = f"{RAW_PATH_URL}/{path}/{file_name}"
+                print(file_name, "   ", file_url)
+                try:
+                    urlretrieve(file_url, f"{temp_path}/{file_name}")
+                except HTTPError as e:
+                    print(f"Failed to download {file_url}: {e}")
+
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                _loadCMSIS(model_files_path)
+                tf.add(model_files_path, arcname=os.path.relpath(model_files_path, tar_temp_dir))
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            create_header_file("input_data", sample, "include", tf)
+            create_header_file(
+                "output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf
+            )
+
+        project, _ = build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(
+        temp_dir, board, west_cmd, lowered, build_config, sample, output_shape
+    )
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "mps2_an521",
+        "stm32f746xx_disco",
+        "nucleo_f746zg",
+        "nucleo_l4r5zi",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "mnist"
+
+    relay_mod, params = _open_tflite_model()
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_simd = _apply_desired_layout_simd(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_simd = _apply_desired_layout_no_simd(relay_mod)
+
+    target = tvm.target.target.micro(
+        model,
+        options=[
+            "-keys=arm_cpu,cpu",
+            "-link-params=1",
+            "--executor=aot",
+            "--unpacked-api=1",
+            "--interface-api=c",
+        ],
+    )
+
+    temp_dir_simd = temp_dir / "simd"
+    temp_dir_no_simd = temp_dir / "nosimd"
+
+    os.makedirs(temp_dir_simd, exist_ok=True)
+    os.makedirs(temp_dir_no_simd, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_simd = relay.build(relay_mod_simd, target, params=params)
+        lowered_no_simd = relay.build(relay_mod_no_simd, target, params=params)
+        result_simd, time_simd = _run_model(
+            temp_dir_simd, board, west_cmd, lowered_simd, build_config, sample, output_shape
+        )
+        result_no_simd, time_no_simd = _run_model(
+            temp_dir_no_simd, board, west_cmd, lowered_no_simd, build_config, sample, output_shape
+        )
+
+    assert result_no_simd == result_simd == 2
+
+    if board not in [

Review comment:
       Time performance measurements on QEMU emulator are always equal to zero.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r711021647



##########
File path: apps/microtvm/reference-vm/zephyr/base-box/base_box_test.sh
##########
@@ -37,3 +37,5 @@ if [ $board == "stm32f746xx" ]; then
 else
     pytest tests/micro/zephyr/test_zephyr_aot.py --zephyr-board=${board}
 fi
+
+pytest tests/micro/zephyr/test_zephyr_armv7m.py --zephyr-board=${board}

Review comment:
       Done.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org



[GitHub] [tvm] sergey-grovety commented on a change in pull request #8990: [microTVM] Update support for ARMv7m intrinsic

Posted by GitBox <gi...@apache.org>.
sergey-grovety commented on a change in pull request #8990:
URL: https://github.com/apache/tvm/pull/8990#discussion_r712068246



##########
File path: tests/micro/zephyr/test_zephyr_armv7m.py
##########
@@ -0,0 +1,293 @@
+# 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 io
+import logging
+import os
+import pathlib
+import sys
+import logging
+import tarfile
+import tempfile
+
+import pytest
+import numpy as np
+
+import tvm
+import tvm.rpc
+import tvm.micro
+import tvm.testing
+import tvm.relay as relay
+
+from tvm.micro.interface_api import generate_c_interface_header
+
+import conftest
+
+_LOG = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO)
+
+PLATFORMS = conftest.PLATFORMS
+
+TEMPLATE_PROJECT_DIR = (
+    pathlib.Path(__file__).parent
+    / ".."
+    / ".."
+    / ".."
+    / "apps"
+    / "microtvm"
+    / "zephyr"
+    / "template_project"
+).resolve()
+
+
+def _read_line(fd, timeout_sec: int):
+    data = ""
+    new_line = False
+    while True:
+        if new_line:
+            break
+        new_data = fd.read(1, timeout_sec=timeout_sec)
+        logging.debug(f"read data: {new_data}")
+        for item in new_data:
+            new_c = chr(item)
+            data = data + new_c
+            if new_c == "\n":
+                new_line = True
+                break
+    return data
+
+
+def _get_message(fd, expr: str, timeout_sec: int):
+    while True:
+        data = _read_line(fd, timeout_sec)
+        logging.debug(f"new line: {data}")
+        if expr in data:
+            return data
+
+def _build_project(temp_dir, zephyr_board, west_cmd, mod, build_config, extra_files_tar=None):
+    template_project_dir = (
+        pathlib.Path(__file__).parent
+        / ".."
+        / ".."
+        / ".."
+        / "apps"
+        / "microtvm"
+        / "zephyr"
+        / "template_project"
+    ).resolve()
+    project_dir = temp_dir / "project"
+    project = tvm.micro.generate_project(
+        str(template_project_dir),
+        mod,
+        project_dir,
+        {
+            "extra_files_tar": extra_files_tar,
+            "project_type": "aot_demo",
+            "west_cmd": west_cmd,
+            "verbose": bool(build_config.get("debug")),
+            "zephyr_board": zephyr_board,
+        },
+    )
+    project.build()
+    return project, project_dir
+
+
+def _create_header_file(tensor_name, npy_data, output_path, tar_file):
+    """
+    This method generates a header file containing the data contained in the numpy array provided.
+    It is used to capture the tensor data (for both inputs and expected outputs).
+    """
+    header_file = io.StringIO()
+    header_file.write("#include <stddef.h>\n")
+    header_file.write("#include <stdint.h>\n")
+    header_file.write("#include <dlpack/dlpack.h>\n")
+    header_file.write(f"const size_t {tensor_name}_len = {npy_data.size};\n")
+
+    if npy_data.dtype == "int8":
+        header_file.write(f"int8_t {tensor_name}[] =")
+    elif npy_data.dtype == "int32":
+        header_file.write(f"int32_t {tensor_name}[] = ")
+    elif npy_data.dtype == "uint8":
+        header_file.write(f"uint8_t {tensor_name}[] = ")
+    elif npy_data.dtype == "float32":
+        header_file.write(f"float {tensor_name}[] = ")
+    else:
+        raise ValueError("Data type not expected.")
+
+    header_file.write("{")
+    for i in np.ndindex(npy_data.shape):
+        header_file.write(f"{npy_data[i]}, ")
+    header_file.write("};\n\n")
+
+    header_file_bytes = bytes(header_file.getvalue(), "utf-8")
+    raw_path = pathlib.Path(output_path) / f"{tensor_name}.h"
+    ti = tarfile.TarInfo(name=str(raw_path))
+    ti.size = len(header_file_bytes)
+    ti.mode = 0o644
+    ti.type = tarfile.REGTYPE
+    tar_file.addfile(ti, io.BytesIO(header_file_bytes))
+
+
+
+
+def _open_tflite_model(model_path: str):
+    # Import TFLite model
+    tflite_model_buf = open(model_path, "rb").read()
+    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)
+
+    relay_mod, params = relay.frontend.from_tflite(tflite_model)
+
+    return relay_mod, params
+
+def _get_test_data(testdata_dir):
+
+    from PIL import Image
+
+    image_files = ["digit-2.jpg"]
+
+    for file in image_files:
+        img = Image.open(testdata_dir / file).resize((28, 28))
+        img = np.asarray(img).astype("uint8")
+        sample = np.reshape(img, -1)
+
+    output_shape = (1, 10)
+
+    return sample, output_shape
+
+
+def _apply_desired_layout_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWOI'], 'nn.conv2d': ['NHWC', 'HWOI']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _apply_desired_layout_no_isa(relay_mod):
+
+    desired_layouts = {'qnn.conv2d': ['NHWC', 'HWIO'], 'nn.conv2d': ['NHWC', 'HWIO']}
+
+    seq = tvm.transform.Sequential([relay.transform.RemoveUnusedFunctions(), relay.transform.ConvertLayout(desired_layouts)])
+
+    with tvm.transform.PassContext(opt_level=3):
+        return seq(relay_mod)
+
+def _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    with tempfile.NamedTemporaryFile() as tar_temp_file:
+        with tarfile.open(tar_temp_file.name, "w:gz") as tf:
+            with tempfile.TemporaryDirectory() as tar_temp_dir:
+                model_files_path = os.path.join(tar_temp_dir, "include")
+                os.mkdir(model_files_path)
+                header_path = generate_c_interface_header(
+                    lowered.libmod_name, ["input_1"], ["output"], model_files_path
+                )
+                tf.add(header_path, arcname=os.path.relpath(header_path, tar_temp_dir))
+
+            _create_header_file("input_data", sample, "include", tf)
+            _create_header_file("output_data", np.zeros(shape=output_shape, dtype="float32"), "include", tf)
+
+        project, _ = _build_project(
+            temp_dir,
+            board,
+            west_cmd,
+            lowered,
+            build_config,
+            extra_files_tar=tar_temp_file.name,
+        )
+
+    return project
+
+
+def _run_model(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape):
+
+    project = _generate_project(temp_dir, board, west_cmd, lowered, build_config, sample, output_shape)
+
+    project.flash()
+
+    with project.transport() as transport:
+        timeout_read = 60
+        # _get_message(transport, "#wakeup", timeout_sec=timeout_read)
+        transport.write(b"start\n", timeout_sec=5)
+        result_line = _get_message(transport, "#result", timeout_sec=timeout_read)
+
+    result_line = result_line.strip("\n")
+    result_line = result_line.split(":")
+    result = int(result_line[1])
+    time = int(result_line[2])
+    logging.info(f"Result: {result}\ttime: {time} ms")
+
+    return result, time
+
+
+@tvm.testing.requires_micro
+def test_armv7m_intrinsic(temp_dir, board, west_cmd, tvm_debug):
+    """Testing a ARM v7m SIMD extension."""
+
+    if board not in [
+        "nrf5340dk",
+        "stm32f746xx_disco",
+        "stm32f746xx_nucleo",
+        "stm32l4r5zi_nucleo",
+    ]:
+        pytest.skip(msg="Platform does not support ARM v7m SIMD extenion.")
+
+    model = conftest.ZEPHYR_BOARDS[board]
+
+    build_config = {"debug": tvm_debug}
+
+    this_dir = pathlib.Path(os.path.dirname(__file__))
+    testdata_dir = this_dir.parent / "testdata" / "armv7m"
+
+    relay_mod, params = _open_tflite_model(testdata_dir / "mnist_model_quant.tflite")
+
+    sample, output_shape = _get_test_data(testdata_dir)
+
+    relay_mod_isa = _apply_desired_layout_isa(relay_mod)
+    # kernel layout "HWIO" is not supported by arm_cpu SIMD extension (see tvm\python\relay\op\strategy\arm_cpu.py)
+    relay_mod_no_isa = _apply_desired_layout_no_isa(relay_mod)
+
+    target = tvm.target.target.micro(
+        model, options=["-keys=arm_cpu,cpu", "-link-params=1", "--executor=aot", "--unpacked-api=1", "--interface-api=c"]
+    )
+
+    temp_dir_isa = temp_dir / "isa"
+    temp_dir_no_isa = temp_dir / "noisa"
+
+    os.makedirs(temp_dir_isa, exist_ok=True)
+    os.makedirs(temp_dir_no_isa, exist_ok=True)
+
+    with tvm.transform.PassContext(opt_level=3, config={"tir.disable_vectorize": True}):
+        lowered_isa = relay.build(relay_mod_isa, target, params=params)
+        lowered_no_isa = relay.build(relay_mod_no_isa, target, params=params)
+        result_isa, time_isa = _run_model(temp_dir_isa, board, west_cmd, lowered_isa, build_config, sample, output_shape)
+        result_no_isa, time_no_isa = _run_model(temp_dir_no_isa, board, west_cmd, lowered_no_isa, build_config, sample, output_shape)
+
+    assert result_no_isa == result_isa
+    assert time_no_isa > time_isa

Review comment:
       Running on QEMU MPS2-AN521 target results both performance time are equal to zero. Escape this from evaluating in this particular test.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@tvm.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org