From 7b4bc16e1b03ed3d975764f277d7174c78b4828b Mon Sep 17 00:00:00 2001 From: Chris Sidebottom Date: Wed, 2 Feb 2022 10:24:09 +0000 Subject: [PATCH] [microTVM] TVMCon 2021 Zephyr Demo with CMSIS-NN This is adds a Zephyr Demo showing how to integrate TVM directly into your embedded application. It runs a keyword spotting model with the Zephyr RTOS using CMSIS-NN with the Ahead-of-Time (AOT) executor and the stack allocation strategy. --- Jenkinsfile | 4 + apps/microtvm/zephyr_cmsisnn/.gitignore | 2 + apps/microtvm/zephyr_cmsisnn/CMakeLists.txt | 92 +++++++++++++++++++ apps/microtvm/zephyr_cmsisnn/README.md | 43 +++++++++ .../zephyr_cmsisnn/include/crt_config.h | 54 +++++++++++ .../zephyr_cmsisnn/model/convert_input.py | 67 ++++++++++++++ .../zephyr_cmsisnn/model/convert_labels.py | 43 +++++++++ apps/microtvm/zephyr_cmsisnn/model/input.txt | 1 + apps/microtvm/zephyr_cmsisnn/model/labels.txt | 12 +++ apps/microtvm/zephyr_cmsisnn/prj.conf | 22 +++++ apps/microtvm/zephyr_cmsisnn/run_demo.sh | 54 +++++++++++ apps/microtvm/zephyr_cmsisnn/src/main.c | 83 +++++++++++++++++ tests/scripts/task_demo_microtvm.sh | 23 +++++ 13 files changed, 500 insertions(+) create mode 100644 apps/microtvm/zephyr_cmsisnn/.gitignore create mode 100644 apps/microtvm/zephyr_cmsisnn/CMakeLists.txt create mode 100644 apps/microtvm/zephyr_cmsisnn/README.md create mode 100644 apps/microtvm/zephyr_cmsisnn/include/crt_config.h create mode 100644 apps/microtvm/zephyr_cmsisnn/model/convert_input.py create mode 100644 apps/microtvm/zephyr_cmsisnn/model/convert_labels.py create mode 100644 apps/microtvm/zephyr_cmsisnn/model/input.txt create mode 100644 apps/microtvm/zephyr_cmsisnn/model/labels.txt create mode 100644 apps/microtvm/zephyr_cmsisnn/prj.conf create mode 100755 apps/microtvm/zephyr_cmsisnn/run_demo.sh create mode 100644 apps/microtvm/zephyr_cmsisnn/src/main.c create mode 100755 tests/scripts/task_demo_microtvm.sh diff --git a/Jenkinsfile b/Jenkinsfile index d806d3c27fe6..ff3b5a56ed3c 100755 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -369,6 +369,10 @@ stage('Build') { script: "${docker_run} ${ci_qemu} ./tests/scripts/task_python_microtvm.sh", label: 'Run microTVM tests', ) + sh ( + script: "${docker_run} ${ci_qemu} ./tests/scripts/task_demo_microtvm.sh", + label: 'Run microTVM demos', + ) junit 'build/pytest-results/*.xml' } } diff --git a/apps/microtvm/zephyr_cmsisnn/.gitignore b/apps/microtvm/zephyr_cmsisnn/.gitignore new file mode 100644 index 000000000000..faa3be6bbc82 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/.gitignore @@ -0,0 +1,2 @@ +build +*.tflite diff --git a/apps/microtvm/zephyr_cmsisnn/CMakeLists.txt b/apps/microtvm/zephyr_cmsisnn/CMakeLists.txt new file mode 100644 index 000000000000..7f0db59ca088 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/CMakeLists.txt @@ -0,0 +1,92 @@ +# 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. + +cmake_minimum_required(VERSION 3.20.0) +set(BOARD mps3_an547) +set(EMU_PLATFORM armfvp) + +find_package(Zephyr) +project(my_zephyr_app) + +if (NOT DEFINED CMSIS_PATH) + set(CMSIS_PATH /opt/arm/ethosu/cmsis/) +endif() + +set(TVMC_COMMAND python3 -m tvm.driver.tvmc) +set(TVMC_ARGS + --target="cmsis-nn -mcpu=cortex-m55, c" # CMSIS-NN and C targets + --runtime=crt # C Runtime + --executor=aot # Ahead-of-Time Executor + --executor-aot-unpacked-api=1 # Direct internal calls to operators + --executor-aot-interface-api=c # Expose C interface to the model + --pass-config=tir.disable_vectorize=1 # Disable vectorizer for C output + --output-format=mlf # Output Model Library Format tarball +) + +set(TVM_RUNTIME + ${CMAKE_CURRENT_BINARY_DIR}/runtime/src/runtime/crt/common/crt_backend_api.c + ${CMAKE_CURRENT_BINARY_DIR}/runtime/src/runtime/crt/memory/stack_allocator.c +) +set(CODEGEN_OUTPUT + ${CMAKE_CURRENT_BINARY_DIR}/codegen/host/src/default_lib0.c + ${CMAKE_CURRENT_BINARY_DIR}/codegen/host/src/default_lib1.c + ${CMAKE_CURRENT_BINARY_DIR}/codegen/host/src/default_lib2.c +) +set(DATA_FILES + ${CMAKE_CURRENT_BINARY_DIR}/inputs.c + ${CMAKE_CURRENT_BINARY_DIR}/outputs.c + ${CMAKE_CURRENT_BINARY_DIR}/labels.c +) +set(CMSIS_SOURCES + ${CMSIS_PATH}/CMSIS/NN/Source/SoftmaxFunctions/arm_softmax_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/ConvolutionFunctions/arm_convolve_wrapper_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/ConvolutionFunctions/arm_convolve_1_x_n_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/ConvolutionFunctions/arm_convolve_1x1_s8_fast.c + ${CMSIS_PATH}/CMSIS/NN/Source/ConvolutionFunctions/arm_convolve_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/ConvolutionFunctions/arm_nn_mat_mult_kernel_s8_s16.c + ${CMSIS_PATH}/CMSIS/NN/Source/FullyConnectedFunctions/arm_fully_connected_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/NNSupportFunctions/arm_nn_mat_mult_nt_t_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/NNSupportFunctions/arm_nn_vec_mat_mult_t_s8.c + ${CMSIS_PATH}/CMSIS/NN/Source/NNSupportFunctions/arm_q7_to_q15_with_offset.c +) + +add_custom_command( + OUTPUT ${TVM_RUNTIME} + OUTPUT ${CODEGEN_OUTPUT} + COMMAND ${TVMC_COMMAND} compile ${TVMC_ARGS} ${CMAKE_CURRENT_SOURCE_DIR}/model/cnn_s_quantized.tflite + COMMAND tar xf ${CMAKE_CURRENT_BINARY_DIR}/module.tar + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) +add_custom_command( + OUTPUT ${DATA_FILES} + COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/model/convert_input.py ${CMAKE_CURRENT_SOURCE_DIR}/model/input.txt ${CMAKE_CURRENT_BINARY_DIR} + COMMAND python3 ${CMAKE_CURRENT_SOURCE_DIR}/model/convert_labels.py ${CMAKE_CURRENT_SOURCE_DIR}/model/labels.txt ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +target_sources(app PRIVATE + src/main.c + ${TVM_RUNTIME} + ${CODEGEN_OUTPUT} + ${DATA_FILES} + ${CMSIS_SOURCES} +) +target_include_directories(app + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include + PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/runtime/include ${CMAKE_CURRENT_BINARY_DIR}/codegen/host/include + PUBLIC ${CMSIS_PATH}/CMSIS/NN/Include/ ${CMSIS_PATH}/CMSIS/DSP/Include +) diff --git a/apps/microtvm/zephyr_cmsisnn/README.md b/apps/microtvm/zephyr_cmsisnn/README.md new file mode 100644 index 000000000000..cccf97947ef6 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/README.md @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + +# Zephyr RTOS Demo with CMSIS-NN + +This project was used for the [TVMCon 2021 talk on Cortex-M improvements to TVM](https://www.youtube.com/watch?v=6a7o8U-8Op4). It runs a keyword spotting model with the Zephyr RTOS using CMSIS-NN with the Ahead-of-Time (AOT) executor and the stack allocation strategy. + +The application starts from [the Zephyr base project](https://docs.zephyrproject.org/latest/application/index.html#application) and makes minimal changes to integrate TVM. To try it out, first refer to the [Zephyr Getting Started](https://docs.zephyrproject.org/latest/getting_started/index.html) page to setup your tooling such as `west` (you can also use the `tlcpack/ci_qemu` image). Then download the [Fixed Virtual Platform (FVP) based on Arm(R) Corstone(TM)-300 software](https://developer.arm.com/tools-and-software/open-source-software/arm-platforms-software/arm-ecosystem-fvps) and set the path for Zephyr to find it: + +``` +export ARMFVP_BIN_PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4/ +``` + +Download the keyword spotting model to the `model` directory: +``` +wget \ + https://github.com/ARM-software/ML-zoo/blob/ee35139af86bdace5e502b09fe8b9da9cb1f06bb/models/keyword_spotting/cnn_small/tflite_int8/cnn_s_quantized.tflite \ + -O model/cnn_s_quantized.tflite +``` + +Checkout [CMSIS_5](https://github.com/ARM-software/CMSIS_5.git) (default is `/opt/arm/ethosu/cmsis` to reflect `tlcpack/ci_qemu`): +``` +git clone "https://github.com/ARM-software/CMSIS_5.git" cmsis +``` + +And run the demo using `west`, with the path to CMSIS: +``` +west build -t run -- -DCMSIS_PATH=/opt/arm/ethosu/cmsis +``` diff --git a/apps/microtvm/zephyr_cmsisnn/include/crt_config.h b/apps/microtvm/zephyr_cmsisnn/include/crt_config.h new file mode 100644 index 000000000000..a84ad991bdb9 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/include/crt_config.h @@ -0,0 +1,54 @@ +/* + * 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. + */ + +/*! + * \file include/crt_config.h + * \brief CRT configuration for demo app. + */ +#ifndef TVM_RUNTIME_CRT_CONFIG_H_ +#define TVM_RUNTIME_CRT_CONFIG_H_ + +/*! Log level of the CRT runtime */ +#define TVM_CRT_LOG_LEVEL TVM_CRT_LOG_LEVEL_DEBUG + +/*! Support low-level debugging in MISRA-C runtime */ +#define TVM_CRT_DEBUG 0 + +/*! Maximum supported dimension in NDArray */ +#define TVM_CRT_MAX_NDIM 6 +/*! Maximum supported arguments in generated functions */ +#define TVM_CRT_MAX_ARGS 10 +/*! Maximum supported string length in dltype, e.g. "int8", "int16", "float32" + */ +#define TVM_CRT_MAX_STRLEN_DLTYPE 10 +/*! Maximum supported string length in function names */ +#define TVM_CRT_MAX_STRLEN_FUNCTION_NAME 120 +/*! Maximum supported string length in parameter names */ +#define TVM_CRT_MAX_STRLEN_PARAM_NAME 80 + +/*! Maximum number of registered modules. */ +#define TVM_CRT_MAX_REGISTERED_MODULES 2 + +/*! Size of the global function registry, in bytes. */ +#define TVM_CRT_GLOBAL_FUNC_REGISTRY_SIZE_BYTES 512 + +/*! Maximum packet size, in bytes, including the length header. */ +#define TVM_CRT_MAX_PACKET_SIZE_BYTES 512 + +#endif // TVM_RUNTIME_CRT_CONFIG_H_ diff --git a/apps/microtvm/zephyr_cmsisnn/model/convert_input.py b/apps/microtvm/zephyr_cmsisnn/model/convert_input.py new file mode 100644 index 000000000000..7b10e86b0f57 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/model/convert_input.py @@ -0,0 +1,67 @@ +# 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 os +import pathlib +import sys +import numpy as np + + +def create_file(name, prefix, tensor_name, tensor_data, output_path): + """ + This function generates a header file containing the data from the numpy array provided. + """ + file_path = pathlib.Path(f"{output_path}/" + name).resolve() + # Create header file with npy_data as a C array + raw_path = file_path.with_suffix(".c").resolve() + with open(raw_path, "w") as header_file: + header_file.write( + "#include \n" + "#include \n" + f"const size_t {tensor_name}_len = {tensor_data.size};\n" + f"{prefix} float {tensor_name}_storage[] = " + ) + header_file.write("{") + for i in np.ndindex(tensor_data.shape): + header_file.write(f"{tensor_data[i]}, ") + header_file.write("};\n\n") + + +def create_files(input_file, output_dir): + """ + This function generates C files for the input and output arrays required to run inferences + """ + # Create out folder + os.makedirs(output_dir, exist_ok=True) + + # Create input header file + input_data = np.loadtxt(input_file) + create_file("inputs", "const", "input", input_data, output_dir) + + # Create output header file + output_data = np.zeros([12], np.float32) + create_file( + "outputs", + "", + "output", + output_data, + output_dir, + ) + + +if __name__ == "__main__": + create_files(sys.argv[1], sys.argv[2]) diff --git a/apps/microtvm/zephyr_cmsisnn/model/convert_labels.py b/apps/microtvm/zephyr_cmsisnn/model/convert_labels.py new file mode 100644 index 000000000000..d1bce6d798b0 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/model/convert_labels.py @@ -0,0 +1,43 @@ +# 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 os +import pathlib +import sys + + +def create_labels_header(labels_file, output_path): + """ + This function generates a header file containing the ImageNet labels as an array of strings + """ + labels_path = pathlib.Path(labels_file).resolve() + file_path = pathlib.Path(f"{output_path}/labels.c").resolve() + + with open(labels_path) as f: + labels = f.readlines() + + with open(file_path, "w") as header_file: + header_file.write(f"char* labels[] = {{") + + for _, label in enumerate(labels): + header_file.write(f'"{label.rstrip()}",') + + header_file.write("};\n") + + +if __name__ == "__main__": + create_labels_header(sys.argv[1], sys.argv[2]) diff --git a/apps/microtvm/zephyr_cmsisnn/model/input.txt b/apps/microtvm/zephyr_cmsisnn/model/input.txt new file mode 100644 index 000000000000..3f8625fc4c04 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/model/input.txt @@ -0,0 +1 @@ +1.550000000000000000e+02 2.500000000000000000e+01 1.530000000000000000e+02 2.070000000000000000e+02 1.300000000000000000e+01 5.100000000000000000e+01 1.010000000000000000e+02 2.270000000000000000e+02 2.800000000000000000e+01 2.220000000000000000e+02 2.500000000000000000e+01 8.100000000000000000e+01 1.860000000000000000e+02 2.100000000000000000e+01 8.600000000000000000e+01 1.090000000000000000e+02 8.900000000000000000e+01 1.740000000000000000e+02 2.490000000000000000e+02 1.920000000000000000e+02 1.490000000000000000e+02 2.520000000000000000e+02 1.860000000000000000e+02 1.170000000000000000e+02 8.200000000000000000e+01 1.820000000000000000e+02 2.460000000000000000e+02 1.930000000000000000e+02 2.200000000000000000e+01 1.750000000000000000e+02 1.870000000000000000e+02 1.860000000000000000e+02 4.200000000000000000e+01 2.230000000000000000e+02 1.180000000000000000e+02 1.540000000000000000e+02 1.580000000000000000e+02 2.280000000000000000e+02 1.700000000000000000e+02 4.600000000000000000e+01 5.900000000000000000e+01 1.830000000000000000e+02 9.900000000000000000e+01 6.500000000000000000e+01 1.210000000000000000e+02 3.500000000000000000e+01 2.000000000000000000e+02 2.070000000000000000e+02 5.000000000000000000e+01 8.000000000000000000e+01 2.500000000000000000e+02 1.350000000000000000e+02 1.590000000000000000e+02 4.100000000000000000e+01 1.800000000000000000e+02 8.400000000000000000e+01 1.370000000000000000e+02 5.000000000000000000e+00 1.740000000000000000e+02 1.930000000000000000e+02 5.400000000000000000e+01 1.480000000000000000e+02 3.000000000000000000e+01 4.800000000000000000e+01 5.700000000000000000e+01 2.150000000000000000e+02 2.010000000000000000e+02 6.000000000000000000e+00 5.200000000000000000e+01 1.500000000000000000e+01 5.000000000000000000e+01 1.290000000000000000e+02 1.150000000000000000e+02 1.450000000000000000e+02 2.440000000000000000e+02 6.500000000000000000e+01 1.740000000000000000e+02 3.200000000000000000e+01 3.800000000000000000e+01 9.300000000000000000e+01 2.360000000000000000e+02 2.170000000000000000e+02 2.120000000000000000e+02 1.940000000000000000e+02 2.300000000000000000e+02 1.790000000000000000e+02 3.000000000000000000e+00 8.700000000000000000e+01 2.100000000000000000e+01 1.530000000000000000e+02 1.940000000000000000e+02 1.680000000000000000e+02 2.040000000000000000e+02 1.530000000000000000e+02 1.930000000000000000e+02 4.800000000000000000e+01 7.000000000000000000e+00 1.460000000000000000e+02 2.500000000000000000e+01 1.180000000000000000e+02 2.130000000000000000e+02 2.320000000000000000e+02 5.000000000000000000e+01 1.570000000000000000e+02 4.000000000000000000e+00 1.270000000000000000e+02 2.300000000000000000e+01 2.120000000000000000e+02 4.300000000000000000e+01 1.610000000000000000e+02 4.500000000000000000e+01 2.410000000000000000e+02 1.740000000000000000e+02 1.040000000000000000e+02 7.700000000000000000e+01 2.030000000000000000e+02 7.400000000000000000e+01 1.690000000000000000e+02 3.700000000000000000e+01 7.800000000000000000e+01 2.110000000000000000e+02 1.070000000000000000e+02 1.930000000000000000e+02 5.000000000000000000e+01 3.300000000000000000e+01 1.370000000000000000e+02 1.000000000000000000e+02 6.900000000000000000e+01 1.150000000000000000e+02 1.690000000000000000e+02 4.000000000000000000e+01 5.000000000000000000e+00 2.700000000000000000e+01 1.500000000000000000e+01 1.660000000000000000e+02 2.400000000000000000e+02 7.500000000000000000e+01 2.060000000000000000e+02 7.700000000000000000e+01 5.500000000000000000e+01 2.090000000000000000e+02 2.800000000000000000e+01 1.900000000000000000e+01 2.700000000000000000e+01 2.400000000000000000e+02 2.030000000000000000e+02 6.200000000000000000e+01 2.450000000000000000e+02 2.540000000000000000e+02 1.210000000000000000e+02 1.360000000000000000e+02 8.000000000000000000e+01 8.300000000000000000e+01 1.980000000000000000e+02 6.200000000000000000e+01 3.200000000000000000e+01 1.820000000000000000e+02 6.700000000000000000e+01 2.240000000000000000e+02 7.600000000000000000e+01 1.170000000000000000e+02 4.000000000000000000e+01 3.000000000000000000e+00 6.000000000000000000e+00 1.570000000000000000e+02 2.520000000000000000e+02 7.800000000000000000e+01 1.750000000000000000e+02 2.420000000000000000e+02 1.770000000000000000e+02 1.220000000000000000e+02 1.710000000000000000e+02 2.390000000000000000e+02 8.300000000000000000e+01 2.000000000000000000e+00 2.160000000000000000e+02 7.000000000000000000e+00 1.900000000000000000e+02 2.520000000000000000e+02 8.300000000000000000e+01 6.100000000000000000e+01 9.700000000000000000e+01 1.090000000000000000e+02 9.300000000000000000e+01 2.270000000000000000e+02 2.300000000000000000e+02 2.280000000000000000e+02 1.260000000000000000e+02 1.340000000000000000e+02 1.710000000000000000e+02 1.020000000000000000e+02 8.300000000000000000e+01 2.000000000000000000e+02 1.370000000000000000e+02 8.600000000000000000e+01 3.600000000000000000e+01 1.690000000000000000e+02 6.000000000000000000e+00 1.420000000000000000e+02 4.900000000000000000e+01 2.120000000000000000e+02 1.780000000000000000e+02 4.300000000000000000e+01 1.920000000000000000e+02 4.200000000000000000e+01 2.900000000000000000e+01 1.490000000000000000e+02 1.020000000000000000e+02 1.040000000000000000e+02 6.000000000000000000e+00 4.300000000000000000e+01 1.240000000000000000e+02 2.190000000000000000e+02 1.530000000000000000e+02 1.700000000000000000e+02 5.800000000000000000e+01 1.700000000000000000e+01 2.470000000000000000e+02 2.160000000000000000e+02 2.020000000000000000e+02 1.100000000000000000e+01 2.490000000000000000e+02 2.150000000000000000e+02 1.200000000000000000e+01 1.230000000000000000e+02 2.410000000000000000e+02 2.230000000000000000e+02 2.100000000000000000e+02 2.480000000000000000e+02 0.000000000000000000e+00 1.900000000000000000e+02 5.700000000000000000e+01 1.660000000000000000e+02 7.200000000000000000e+01 1.220000000000000000e+02 1.600000000000000000e+01 5.600000000000000000e+01 6.400000000000000000e+01 2.010000000000000000e+02 1.300000000000000000e+01 2.370000000000000000e+02 1.760000000000000000e+02 2.240000000000000000e+02 1.880000000000000000e+02 9.300000000000000000e+01 2.320000000000000000e+02 1.290000000000000000e+02 3.000000000000000000e+00 5.900000000000000000e+01 4.100000000000000000e+01 1.400000000000000000e+02 1.680000000000000000e+02 1.730000000000000000e+02 6.500000000000000000e+01 2.220000000000000000e+02 2.020000000000000000e+02 2.080000000000000000e+02 2.170000000000000000e+02 2.290000000000000000e+02 1.660000000000000000e+02 9.000000000000000000e+01 1.170000000000000000e+02 1.440000000000000000e+02 4.000000000000000000e+00 3.800000000000000000e+01 1.720000000000000000e+02 1.330000000000000000e+02 2.300000000000000000e+02 1.920000000000000000e+02 2.270000000000000000e+02 3.700000000000000000e+01 5.200000000000000000e+01 2.500000000000000000e+01 1.000000000000000000e+02 5.800000000000000000e+01 6.100000000000000000e+01 5.400000000000000000e+01 2.600000000000000000e+01 1.100000000000000000e+02 2.270000000000000000e+02 8.000000000000000000e+01 1.000000000000000000e+02 8.700000000000000000e+01 1.300000000000000000e+01 1.970000000000000000e+02 8.000000000000000000e+00 1.280000000000000000e+02 5.800000000000000000e+01 1.080000000000000000e+02 5.000000000000000000e+01 6.200000000000000000e+01 1.530000000000000000e+02 7.800000000000000000e+01 4.900000000000000000e+01 2.250000000000000000e+02 1.780000000000000000e+02 2.600000000000000000e+01 2.350000000000000000e+02 2.530000000000000000e+02 1.940000000000000000e+02 2.540000000000000000e+02 4.600000000000000000e+01 1.590000000000000000e+02 2.060000000000000000e+02 6.600000000000000000e+01 2.090000000000000000e+02 2.380000000000000000e+02 1.970000000000000000e+02 1.930000000000000000e+02 3.100000000000000000e+01 1.910000000000000000e+02 1.400000000000000000e+01 2.190000000000000000e+02 2.470000000000000000e+02 2.300000000000000000e+01 1.930000000000000000e+02 1.540000000000000000e+02 3.200000000000000000e+01 8.000000000000000000e+00 1.300000000000000000e+01 1.100000000000000000e+02 1.960000000000000000e+02 1.970000000000000000e+02 8.600000000000000000e+01 2.250000000000000000e+02 1.520000000000000000e+02 1.110000000000000000e+02 1.190000000000000000e+02 1.370000000000000000e+02 2.370000000000000000e+02 2.000000000000000000e+01 5.600000000000000000e+01 6.900000000000000000e+01 9.300000000000000000e+01 7.100000000000000000e+01 8.000000000000000000e+01 2.700000000000000000e+01 8.100000000000000000e+01 2.510000000000000000e+02 8.000000000000000000e+01 1.130000000000000000e+02 1.680000000000000000e+02 9.300000000000000000e+01 8.200000000000000000e+01 1.980000000000000000e+02 2.290000000000000000e+02 1.050000000000000000e+02 2.300000000000000000e+01 1.040000000000000000e+02 1.380000000000000000e+02 1.010000000000000000e+02 1.510000000000000000e+02 2.160000000000000000e+02 5.900000000000000000e+01 7.900000000000000000e+01 2.600000000000000000e+01 1.970000000000000000e+02 2.500000000000000000e+01 7.000000000000000000e+01 1.800000000000000000e+01 3.500000000000000000e+01 1.040000000000000000e+02 2.150000000000000000e+02 3.800000000000000000e+01 8.200000000000000000e+01 8.700000000000000000e+01 1.420000000000000000e+02 1.410000000000000000e+02 2.530000000000000000e+02 8.900000000000000000e+01 1.190000000000000000e+02 1.850000000000000000e+02 1.850000000000000000e+02 1.050000000000000000e+02 1.120000000000000000e+02 2.800000000000000000e+01 1.590000000000000000e+02 2.020000000000000000e+02 5.900000000000000000e+01 5.100000000000000000e+01 1.830000000000000000e+02 1.010000000000000000e+02 2.330000000000000000e+02 1.850000000000000000e+02 1.370000000000000000e+02 1.380000000000000000e+02 1.980000000000000000e+02 8.300000000000000000e+01 2.090000000000000000e+02 1.780000000000000000e+02 2.150000000000000000e+02 1.830000000000000000e+02 9.500000000000000000e+01 1.890000000000000000e+02 7.900000000000000000e+01 3.900000000000000000e+01 2.520000000000000000e+02 2.340000000000000000e+02 5.300000000000000000e+01 1.580000000000000000e+02 1.040000000000000000e+02 1.030000000000000000e+02 1.170000000000000000e+02 2.060000000000000000e+02 2.300000000000000000e+02 1.250000000000000000e+02 1.070000000000000000e+02 2.250000000000000000e+02 1.710000000000000000e+02 2.380000000000000000e+02 5.500000000000000000e+01 2.530000000000000000e+02 2.460000000000000000e+02 2.100000000000000000e+02 2.080000000000000000e+02 1.530000000000000000e+02 3.500000000000000000e+01 1.200000000000000000e+02 1.130000000000000000e+02 1.010000000000000000e+02 7.500000000000000000e+01 4.300000000000000000e+01 1.870000000000000000e+02 6.400000000000000000e+01 6.700000000000000000e+01 2.170000000000000000e+02 1.400000000000000000e+01 4.800000000000000000e+01 1.060000000000000000e+02 1.790000000000000000e+02 8.000000000000000000e+01 1.180000000000000000e+02 1.790000000000000000e+02 3.000000000000000000e+00 2.180000000000000000e+02 2.600000000000000000e+01 2.540000000000000000e+02 1.220000000000000000e+02 1.210000000000000000e+02 4.000000000000000000e+00 3.400000000000000000e+01 1.980000000000000000e+02 1.580000000000000000e+02 6.000000000000000000e+00 9.700000000000000000e+01 1.000000000000000000e+00 1.280000000000000000e+02 2.030000000000000000e+02 1.500000000000000000e+01 2.700000000000000000e+01 2.090000000000000000e+02 9.700000000000000000e+01 1.910000000000000000e+02 1.590000000000000000e+02 1.470000000000000000e+02 1.200000000000000000e+02 4.000000000000000000e+01 2.800000000000000000e+01 8.500000000000000000e+01 1.930000000000000000e+02 2.700000000000000000e+01 1.140000000000000000e+02 1.300000000000000000e+02 1.580000000000000000e+02 1.400000000000000000e+02 6.700000000000000000e+01 5.100000000000000000e+01 2.300000000000000000e+02 1.020000000000000000e+02 7.200000000000000000e+01 1.100000000000000000e+02 2.330000000000000000e+02 1.790000000000000000e+02 9.300000000000000000e+01 1.760000000000000000e+02 2.180000000000000000e+02 5.200000000000000000e+01 0.000000000000000000e+00 1.770000000000000000e+02 1.020000000000000000e+02 2.300000000000000000e+01 1.060000000000000000e+02 1.720000000000000000e+02 3.500000000000000000e+01 2.170000000000000000e+02 1.170000000000000000e+02 2.300000000000000000e+02 2.400000000000000000e+02 1.380000000000000000e+02 2.270000000000000000e+02 diff --git a/apps/microtvm/zephyr_cmsisnn/model/labels.txt b/apps/microtvm/zephyr_cmsisnn/model/labels.txt new file mode 100644 index 000000000000..ba416458b011 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/model/labels.txt @@ -0,0 +1,12 @@ +_silence_ +_unknown_ +yes +no +up +down +left +right +on +off +stop +go \ No newline at end of file diff --git a/apps/microtvm/zephyr_cmsisnn/prj.conf b/apps/microtvm/zephyr_cmsisnn/prj.conf new file mode 100644 index 000000000000..59ca3154a2af --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/prj.conf @@ -0,0 +1,22 @@ +# 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. + +# newlib needed for math.h +CONFIG_NEWLIB_LIBC=y + +# emulate finite stack size +CONFIG_MAIN_STACK_SIZE=256 diff --git a/apps/microtvm/zephyr_cmsisnn/run_demo.sh b/apps/microtvm/zephyr_cmsisnn/run_demo.sh new file mode 100755 index 000000000000..13d163b5f7c2 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/run_demo.sh @@ -0,0 +1,54 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# 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. + +set -e +set -x +set -o pipefail + +MODEL_URL=https://github.com/ARM-software/ML-zoo/raw/ee35139af86bdace5e502b09fe8b9da9cb1f06bb/models/keyword_spotting/cnn_small/tflite_int8 +MODEL_FILE=cnn_s_quantized.tflite + +LOGDIR="$(mktemp -d)" + +cleanup() +{ + rm -rf "$LOGDIR" + pkill FVP +} + +trap cleanup EXIT + +# Clean up previous build +rm -rf build + +# Download model file +wget $MODEL_URL/$MODEL_FILE -O model/$MODEL_FILE + +# System doesn't automatically exit so we wait for the output +# and kill it ourselves +export ARMFVP_BIN_PATH=/opt/arm/FVP_Corstone_SSE-300/models/Linux64_GCC-6.4/ +west zephyr-export +west build +west build -t run &> ${LOGDIR}/west.log & +WEST_PID=$! + +# Wait for "exit" keyword +until grep -m 1 "exit" ${LOGDIR}/west.log; do sleep 1 ; done + +# Check the log for correct output +grep "The word is 'down'!" ${LOGDIR}/west.log diff --git a/apps/microtvm/zephyr_cmsisnn/src/main.c b/apps/microtvm/zephyr_cmsisnn/src/main.c new file mode 100644 index 000000000000..7696915f7aa2 --- /dev/null +++ b/apps/microtvm/zephyr_cmsisnn/src/main.c @@ -0,0 +1,83 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tvmgen_default.h" + +extern char* labels[12]; +extern float input_storage[490]; +extern float output_storage[12]; + +extern const size_t output_len; + +static uint8_t g_crt_workspace[TVMGEN_DEFAULT_WORKSPACE_SIZE + 256]; +tvm_workspace_t app_workspace; + +void TVMLogf(const char* msg, ...) { + va_list args; + va_start(args, msg); + vfprintf(stderr, msg, args); + va_end(args); +} + +void __attribute__((noreturn)) TVMPlatformAbort(tvm_crt_error_t error_code) { + fprintf(stderr, "TVMPlatformAbort: %d\n", error_code); + exit(-1); +} + +tvm_crt_error_t TVMPlatformMemoryAllocate(size_t num_bytes, DLDevice dev, void** out_ptr) { + uintptr_t ret = StackMemoryManager_Allocate(&app_workspace, num_bytes, out_ptr); + return ret; +} + +tvm_crt_error_t TVMPlatformMemoryFree(void* ptr, DLDevice dev) { + return StackMemoryManager_Free(&app_workspace, ptr); +} + +void main(void) { + StackMemoryManager_Init(&app_workspace, g_crt_workspace, TVMGEN_DEFAULT_WORKSPACE_SIZE); + + struct tvmgen_default_inputs inputs = {.input = input_storage}; + struct tvmgen_default_outputs outputs = {.output = output_storage}; + + if (tvmgen_default_run(&inputs, &outputs) != 0) { + printk("Model run failed\n"); + exit(-1); + } + + // Calculate index of max value + float max_value = 0.0; + size_t max_index = -1; + for (unsigned int i = 0; i < output_len; ++i) { + if (output_storage[i] > max_value) { + max_value = output_storage[i]; + max_index = i; + } + } + printk("The word is '%s'!\n", labels[max_index]); + exit(0); +} diff --git a/tests/scripts/task_demo_microtvm.sh b/tests/scripts/task_demo_microtvm.sh new file mode 100755 index 000000000000..383e69374b51 --- /dev/null +++ b/tests/scripts/task_demo_microtvm.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# 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. + +set -euxo pipefail + +pushd apps/microtvm/zephyr_cmsisnn +./run_demo.sh +popd