diff --git a/.ci/docker/build.sh b/.ci/docker/build.sh index 6440a3c1d68..e09cdc0ffe5 100755 --- a/.ci/docker/build.sh +++ b/.ci/docker/build.sh @@ -34,17 +34,13 @@ case "${IMAGE_NAME}" in exit 1 esac +# NB: All files needed to build the Docker image needs to be in .ci/docker +# folder so that the image hash is updated correctly when they change. The +# good news is that links can be setup to refer to them from other locations + TORCH_VERSION=$(cat ci_commit_pins/pytorch.txt) BUILD_DOCS=1 -# Copy requirements-lintrunner.txt from root to here -cp ../../requirements-lintrunner.txt ./ - -# Copy arm setup script from root to here -# TODO(huydhn): Figure out a way to rebuild the Docker image automatically -# with a new image hash when the content here is updated -cp -r ../../examples/arm/ ./arm - docker build \ --no-cache \ --progress=plain \ diff --git a/.ci/docker/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake b/.ci/docker/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake new file mode 100644 index 00000000000..918edadb593 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake @@ -0,0 +1,105 @@ +# +# Copyright (c) 2020-2022 Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed 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 +# +# 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. +# + +# Copied this file from core_platform/cmake/toolchain/arm-non-eabi-gcc.cmake +# And modified to align better with cs300 platform + +set(TARGET_CPU "cortex-m55" CACHE STRING "Target CPU") +string(TOLOWER ${TARGET_CPU} CMAKE_SYSTEM_PROCESSOR) + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_C_COMPILER "arm-none-eabi-gcc") +set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") +set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") +set(CMAKE_LINKER "arm-none-eabi-ld") + +set(CMAKE_EXECUTABLE_SUFFIX ".elf") +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# Select C/C++ version +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 14) + +set(GCC_CPU ${CMAKE_SYSTEM_PROCESSOR}) +string(REPLACE "cortex-m85" "cortex-m55" GCC_CPU ${GCC_CPU}) + +# Compile options +add_compile_options( + -mcpu=${GCC_CPU} + -mthumb + "$<$:-gdwarf-3>" + "$<$:-fno-unwind-tables;-fno-rtti;-fno-exceptions>" + -fdata-sections + -ffunction-sections) + +# Compile defines +add_compile_definitions( + "$<$>:NDEBUG>") + +# Link options +add_link_options( + -mcpu=${GCC_CPU} + -mthumb + --specs=nosys.specs) + +# Set floating point unit +if(CMAKE_SYSTEM_PROCESSOR MATCHES "\\+fp") + set(FLOAT hard) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "\\+nofp") + set(FLOAT soft) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m33(\\+|$)" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m55(\\+|$)" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m85(\\+|$)") + set(FLOAT hard) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m4(\\+|$)" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m7(\\+|$)") + set(FLOAT hard) + set(FPU_CONFIG "fpv4-sp-d16") + add_compile_options(-mfpu=${FPU_CONFIG}) + add_link_options(-mfpu=${FPU_CONFIG}) +else() + set(FLOAT soft) +endif() + +if(FLOAT) + add_compile_options(-mfloat-abi=${FLOAT}) + add_link_options(-mfloat-abi=${FLOAT}) +endif() + +add_link_options(LINKER:--nmagic,--gc-sections) + +# Compilation warnings +add_compile_options( + # -Wall + # -Wextra + # -Wcast-align + # -Wdouble-promotion + # -Wformat + # -Wmissing-field-initializers + # -Wnull-dereference + # -Wredundant-decls + # -Wshadow + # -Wswitch + # -Wswitch-default + # -Wunused + # -Wno-redundant-decls + -Wno-psabi +) diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch new file mode 100644 index 00000000000..8928c16c39e --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch @@ -0,0 +1,35 @@ +From 949334fe4cfd84c4d4682a92d055be26670670be Mon Sep 17 00:00:00 2001 +From: Digant Desai +Date: Tue, 3 Oct 2023 21:20:21 -0700 +Subject: [Executorch 1/7] Add README + +--- + applications/executorch_tests/README.md | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + create mode 100644 applications/executorch_tests/README.md + +diff --git a/applications/executorch_tests/README.md b/applications/executorch_tests/README.md +new file mode 100644 +index 0000000..f2dfb05 +--- /dev/null ++++ b/applications/executorch_tests/README.md +@@ -0,0 +1,16 @@ ++## ExecuTorch ++A unified ML software stack within the PyTorch platform for edge devices. It ++defines new compiler entry points as well as a state-of-art runtime. ++ ++Home: https://github.com/pytorch/executorch/ ++ ++### executor_runner ++ ++This test is a simple wrapper around ExecuTorch runtime, capable of running ++`.pte` model files compatible with ExecuTorch. ++ ++If configured correctly with `ET_*` CMake variables pointing to the ExecuTorch ++project build, then this test bin executes `model.pte.h` file converted from ++`model.pte` using `pte_to_header.py`, from the ExecuTorch project root dir, ++containing an ExecuTorch compatible PyTorch model on the Costrone 300 FVP using ++ExecuTorch runtime. +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch new file mode 100644 index 00000000000..5d5baaad1d1 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch @@ -0,0 +1,25 @@ +From ef976aa04e7d6b7571e9791900f9d80aeb0338da Mon Sep 17 00:00:00 2001 +From: Digant Desai +Date: Thu, 28 Sep 2023 18:05:03 -0700 +Subject: [Executorch 2/7] regress cmake version from 3.21 --> 3.20 + +--- + targets/corstone-300/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/targets/corstone-300/CMakeLists.txt b/targets/corstone-300/CMakeLists.txt +index 62205bb..7dda8a1 100644 +--- a/targets/corstone-300/CMakeLists.txt ++++ b/targets/corstone-300/CMakeLists.txt +@@ -42,7 +42,7 @@ set(MEMORY_ARENA "dram" CACHE STRING "Memory config for arena") + # Project + ############################################################################# + +-cmake_minimum_required(VERSION 3.21) ++cmake_minimum_required(VERSION 3.20) + + project(ethos-u-corstone-300 VERSION 0.0.1) + +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch new file mode 100644 index 00000000000..5343f9c524f --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch @@ -0,0 +1,52 @@ +From cbda805f968a45205c9d3d4a2f4cb534e207d504 Mon Sep 17 00:00:00 2001 +From: Digant Desai +Date: Thu, 28 Sep 2023 18:05:30 -0700 +Subject: [Executorch 3/7] Disable warnings to reduce verbosity + +--- + cmake/toolchain/arm-none-eabi-gcc.cmake | 28 ++++++++++++------------- + 1 file changed, 14 insertions(+), 14 deletions(-) + +diff --git a/cmake/toolchain/arm-none-eabi-gcc.cmake b/cmake/toolchain/arm-none-eabi-gcc.cmake +index 093005e..0e6a2ed 100644 +--- a/cmake/toolchain/arm-none-eabi-gcc.cmake ++++ b/cmake/toolchain/arm-none-eabi-gcc.cmake +@@ -85,21 +85,21 @@ add_link_options(LINKER:--nmagic,--gc-sections) + + # Compilation warnings + add_compile_options( +- -Wall +- -Wextra ++ # -Wall ++ # -Wextra + +- -Wcast-align +- -Wdouble-promotion +- -Wformat +- -Wmissing-field-initializers +- -Wnull-dereference +- -Wredundant-decls +- -Wshadow +- -Wswitch +- -Wswitch-default +- -Wunused ++ # -Wcast-align ++ # -Wdouble-promotion ++ # -Wformat ++ # -Wmissing-field-initializers ++ # -Wnull-dereference ++ # -Wredundant-decls ++ # -Wshadow ++ # -Wswitch ++ # -Wswitch-default ++ # -Wunused + +- -Wno-redundant-decls ++ # -Wno-redundant-decls + +- -Wno-psabi ++ # -Wno-psabi + ) +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch new file mode 100644 index 00000000000..8ccd3b7b1a6 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch @@ -0,0 +1,33 @@ +From 02eb3615cdb2cc963f20e103893f76499c98ad50 Mon Sep 17 00:00:00 2001 +From: Digant Desai +Date: Mon, 2 Oct 2023 20:39:39 -0700 +Subject: [Executorch 4/7] New phdr for .data section + +--- + targets/corstone-300/platform.ld | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/targets/corstone-300/platform.ld b/targets/corstone-300/platform.ld +index 8d77329..8de77c4 100644 +--- a/targets/corstone-300/platform.ld ++++ b/targets/corstone-300/platform.ld +@@ -94,6 +94,7 @@ PHDRS + { + rom_exec PT_LOAD; + rom_dram PT_LOAD; ++ data PT_LOAD; /* HACK: New prog header for .data (and friends) going in DTCM */ + null PT_NULL; + } + +@@ -247,7 +248,7 @@ SECTIONS + /* All data end */ + __data_end__ = .; + +- } > DTCM :rom_exec ++ } > DTCM :data + + .sram.bss : + { +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch new file mode 100644 index 00000000000..175a7b6f303 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch @@ -0,0 +1,84 @@ +From 55019e4eb8d39f3fb1fb303380e903294604837c Mon Sep 17 00:00:00 2001 +From: Digant Desai +Date: Tue, 3 Oct 2023 21:20:07 -0700 +Subject: [Executorch 5/7] Add pte to header script + +--- + .../executorch_tests/pte_to_header.py | 65 +++++++++++++++++++ + 1 file changed, 65 insertions(+) + create mode 100644 applications/executorch_tests/pte_to_header.py + +diff --git a/applications/executorch_tests/pte_to_header.py b/applications/executorch_tests/pte_to_header.py +new file mode 100644 +index 0000000..37d88aa +--- /dev/null ++++ b/applications/executorch_tests/pte_to_header.py +@@ -0,0 +1,65 @@ ++# Copyright (c) Meta Platforms, Inc. and affiliates. ++# All rights reserved. ++# ++# This source code is licensed under the BSD-style license found in the ++# LICENSE file in the root directory of this source tree. ++ ++import binascii ++import os ++from argparse import ArgumentParser, ArgumentTypeError ++ ++# Also see: https://git.mlplatform.org/ml/ethos-u/ml-embedded-evaluation-kit.git/tree/scripts/py/gen_model_cpp.py ++ ++bytes_per_line = 32 ++hex_digits_per_line = bytes_per_line * 2 ++ ++ ++def input_file_path(path): ++ if os.path.exists(path): ++ return path ++ else: ++ raise ArgumentTypeError(f"input filepath:{path} does not exist") ++ ++ ++parser = ArgumentParser() ++parser.add_argument( ++ "--pte", ++ help="ExecuTorch .pte model file", ++ type=input_file_path, ++ required=True, ++) ++parser.add_argument( ++ "--outdir", ++ help="Output dir for model_pte.h", ++ type=str, ++ required=False, ++ default=".", ++) ++parser.add_argument( ++ "--section", ++ help="Section attribute for the data array", ++ type=str, ++ required=False, ++ default=".sram.data", ++) ++args = parser.parse_args() ++outfile = os.path.join(args.outdir, "model_pte.h") ++attr = f'__attribute__((section("{args.section}"), aligned(16))) char ' ++ ++with open(args.pte, "rb") as fr, open( ++ outfile, "w" ++) as fw: ++ data = fr.read() ++ hexstream = binascii.hexlify(data).decode("utf-8") ++ hexstring = attr + "model_pte[] = {" ++ ++ for i in range(0, len(hexstream), 2): ++ if 0 == (i % hex_digits_per_line): ++ hexstring += "\n" ++ hexstring += "0x" + hexstream[i : i + 2] + ", " ++ ++ hexstring += "};\n" ++ fw.write(hexstring) ++ print( ++ f"Input: {args.pte} with {len(data)} bytes. Output: {outfile} with {len(hexstring)} bytes. Section: {args.section}." ++ ) +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch new file mode 100644 index 00000000000..7aaa7851c54 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch @@ -0,0 +1,283 @@ +From 25f530f4ef8d994f61fe979e94b4c929ff2481e6 Mon Sep 17 00:00:00 2001 +From: Digant Desai +Date: Thu, 28 Sep 2023 19:07:51 -0700 +Subject: [Executorch 6/7] Add executorch_runner test + +--- + applications/CMakeLists.txt | 2 + + applications/executorch_tests/CMakeLists.txt | 76 +++++++++++ + applications/executorch_tests/runner.cpp | 133 +++++++++++++++++++ + cmake/helpers.cmake | 13 +- + 4 files changed, 222 insertions(+), 2 deletions(-) + create mode 100644 applications/executorch_tests/CMakeLists.txt + create mode 100644 applications/executorch_tests/runner.cpp + +diff --git a/applications/CMakeLists.txt b/applications/CMakeLists.txt +index 1fa2b2e..68e5427 100644 +--- a/applications/CMakeLists.txt ++++ b/applications/CMakeLists.txt +@@ -28,6 +28,8 @@ add_subdirectory(threadx_demo) + + add_subdirectory(message_handler_openamp) + ++add_subdirectory(executorch_tests) ++ + if (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang") + # Only armclang supported for now + add_subdirectory(trustzone_inference) +diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt +new file mode 100644 +index 0000000..c95d53e +--- /dev/null ++++ b/applications/executorch_tests/CMakeLists.txt +@@ -0,0 +1,76 @@ ++# ++# Copyright (c) 2021 Arm Limited. All rights reserved. ++# ++# SPDX-License-Identifier: Apache-2.0 ++# ++# Licensed 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 ++# ++# 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. ++# ++ ++if (NOT TARGET ethosu_core_driver) ++ return() ++endif() ++ ++#### ++#### ExecuTorch demo app/test ++#### ++ ++set(ET_DIR_PATH "<..>/executorch" CACHE PATH "Path to ExecuTorch dir") ++set(ET_BUILD_DIR_PATH "${ET_DIR_PATH}/cmake-out" CACHE PATH "Path to ExecuTorch build dir") ++set(ET_INCLUDE_PATH "${ET_DIR_PATH}/.." CACHE PATH "Path to ExecuTorch headers") ++set(ET_PTE_FILE_PATH "${ET_PTE_FILE_PATH}" CACHE PATH "Path to ExecuTorch model pte") ++ ++get_filename_component(ET_BUILD_DIR_PATH ${ET_BUILD_DIR_PATH} REALPATH) ++get_filename_component(ET_DIR_PATH ${ET_DIR_PATH} REALPATH) ++get_filename_component(ET_INCLUDE_PATH ${ET_INCLUDE_PATH} REALPATH) ++get_filename_component(ET_PTE_FILE_PATH ${ET_PTE_FILE_PATH} REALPATH) ++ ++message("**********************") ++message("ExecuTorch dir (ET_DIR_PATH) : ${ET_DIR_PATH}") ++message("ExecuTorch build dir(ET_BUILD_DIR_PATH) : ${ET_BUILD_DIR_PATH}") ++message("ExecuTorch headers (ET_INCUDE_PATH) : ${ET_INCLUDE_PATH}") ++message("ExecuTorch pte file (ET_PTE_FILE_PATH) : ${ET_PTE_FILE_PATH}") ++message("**********************") ++ ++set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") ++set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_ops_lib.a") ++set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") ++ ++add_custom_target( ++ gen_model_header ALL ++ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/fake_dep ++) ++ ++add_custom_command( ++ OUTPUT ++ ${CMAKE_CURRENT_BINARY_DIR}/fake_dep ++ ${CMAKE_CURRENT_BINARY_DIR}/model_pte.h ++ COMMAND ${PYTHON_EXECUTABLE} ./pte_to_header.py --pte ${ET_PTE_FILE_PATH} ++ --out ${CMAKE_CURRENT_BINARY_DIR} ++ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ++ ) ++ ++ethosu_add_executable_test(executor_runner PRIVATE ++ WHOLE_ARCHIVE TRUE ++ SOURCES runner.cpp ++ LIBRARIES ++ ${LIB_ET_RUNTIME} ++ ${LIB_ET_OP_REGISTRATION} ++ ${LIB_ET_OP_KERNELS}) ++ ++add_dependencies(executor_runner gen_model_header) ++ ++target_include_directories(executor_runner PRIVATE ++${ET_INCLUDE_PATH} ++${CMAKE_CURRENT_BINARY_DIR}) ++ ++# TODO Memory setup +diff --git a/applications/executorch_tests/runner.cpp b/applications/executorch_tests/runner.cpp +new file mode 100644 +index 0000000..7ef920d +--- /dev/null ++++ b/applications/executorch_tests/runner.cpp +@@ -0,0 +1,133 @@ ++/* Copyright (c) Meta Platforms, Inc. and affiliates. ++ * All rights reserved. ++ * ++ * This source code is licensed under the BSD-style license found in the ++ * LICENSE file in the root directory of this source tree. ++ */ ++ ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++// Model file - TODO make this configurable through CMake ++#include "model_pte.h" ++ ++using namespace std; ++using torch::executor::Result; ++using torch::executor::Error; ++ ++__attribute__((section(".sram.data"), aligned(16))) uint8_t method_allocator_pool[4 * 1024U]; ++ ++void et_pal_init(void) {} ++ ++__ET_NORETURN void et_pal_abort(void) { ++ __builtin_trap(); ++} ++ ++et_timestamp_t et_pal_current_ticks(void) { ++ // libc.a - warning: _gettimeofday is not implemented and will always fail ++ return 11223344; ++} ++ ++/** ++ * Emit a log message via platform output (serial port, console, etc). ++ */ ++void et_pal_emit_log_message( ++ __ET_UNUSED et_timestamp_t timestamp, ++ et_pal_log_level_t level, ++ const char* filename, ++ __ET_UNUSED const char* function, ++ size_t line, ++ const char* message, ++ __ET_UNUSED size_t length) { ++ fprintf( ++ stderr, ++ "%c executorch:%s:%zu] %s\n", ++ level, ++ filename, ++ line, ++ message); ++} ++ ++int main() { ++ torch::executor::runtime_init(); ++ ++ auto loader = torch::executor::util::BufferDataLoader(model_pte, sizeof(model_pte)); ++ ET_LOG(Info, "Model PTE file loaded. Size: %lu bytes.", sizeof(model_pte)); ++ Result program = torch::executor::Program::load(&loader); ++ if(!program.ok()) { ++ ET_LOG(Info,"Program loading failed @ 0x%p: 0x%" PRIx32, model_pte, program.error()); ++ } ++ ++ ET_LOG(Info,"Model buffer loaded, has %lu methods", program->num_methods()); ++ ++ const char* method_name = nullptr; ++ { ++ const auto method_name_result = program->get_method_name(0); ++ ET_CHECK_MSG(method_name_result.ok(), "Program has no methods"); ++ method_name = *method_name_result; ++ } ++ ET_LOG(Info,"Running method %s", method_name); ++ ++ Result method_meta = program->method_meta(method_name); ++ if (!method_meta.ok()) { ++ ET_LOG(Info,"Failed to get method_meta for %s: 0x%x", ++ method_name, (unsigned int)method_meta.error()); ++ } ++ ++ torch::executor::MemoryAllocator method_allocator{ ++ torch::executor::MemoryAllocator(sizeof(method_allocator_pool), method_allocator_pool)}; ++ ++ std::vector> planned_buffers; // Owns the memory ++ std::vector> planned_spans; // Passed to the allocator ++ size_t num_memory_planned_buffers = method_meta->num_memory_planned_buffers(); ++ ++ for (size_t id = 0; id < num_memory_planned_buffers; ++id) { ++ size_t buffer_size = static_cast(method_meta->memory_planned_buffer_size(id).get()); ++ ET_LOG(Info,"Setting up planned buffer %zu, size %zu.", id, buffer_size); ++ ++ planned_buffers.push_back(std::make_unique(buffer_size)); ++ planned_spans.push_back({planned_buffers.back().get(), buffer_size}); ++ } ++ ++ torch::executor::HierarchicalAllocator planned_memory( ++ {planned_spans.data(), planned_spans.size()}); ++ ++ torch::executor::MemoryManager memory_manager(&method_allocator, &planned_memory); ++ ++ Result method = program->load_method(method_name, &memory_manager); ++ if(!method.ok()) { ++ ET_LOG(Info,"Loading of method %s failed with status 0x%" PRIx32, method_name, method.error()); ++ } ++ ET_LOG(Info,"Method loaded."); ++ ++ ET_LOG(Info,"Preparing inputs..."); ++ auto inputs = torch::executor::util::PrepareInputTensors(*method); ++ ET_LOG(Info,"Input prepared."); ++ ++ ET_LOG(Info,"Starting the model execution..."); ++ Error status = method->execute(); ++ if(status != Error::Ok){ ++ ET_LOG(Info,"Execution of method %s failed with status 0x%" PRIx32, method_name, status); ++ } else { ++ ET_LOG(Info,"Model executed successfully."); ++ } ++ ++ std::vector outputs(method->outputs_size()); ++ ET_LOG(Info, "%zu outputs: ", outputs.size()); ++ status = method->get_outputs(outputs.data(), outputs.size()); ++ ET_CHECK(status == Error::Ok); ++ for (int i = 0; i < outputs.size(); ++i) { ++ for (int j = 0; j < outputs[i].toTensor().numel(); ++j) { ++ printf("Output[%d][%d]: %f\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); ++ } ++ } ++ return 0; ++} +diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake +index a21d9f0..036f189 100644 +--- a/cmake/helpers.cmake ++++ b/cmake/helpers.cmake +@@ -85,7 +85,7 @@ endfunction() + ############################################################################# + + function(ethosu_add_executable target) +- cmake_parse_arguments(ARGS "" "TARGET_LIBRARY" "SOURCES;LIBRARIES" ${ARGN}) ++ cmake_parse_arguments(ARGS "WHOLE_ARCHIVE" "TARGET_LIBRARY" "SOURCES;LIBRARIES" ${ARGN}) + add_executable(${target}) + + target_sources(${target} PRIVATE +@@ -95,8 +95,17 @@ function(ethosu_add_executable target) + set(ARGS_TARGET_LIBRARY ethosu_target_init) + endif() + ++ if (ARGS_WHOLE_ARCHIVE) ++ set(PRE_LINKER_FLAGS "-Wl,--whole-archive") ++ set(POST_LINKER_FLAGS "-Wl,--no-whole-archive") ++ endif() ++ + target_link_libraries(${target} PRIVATE +- ${ARGS_TARGET_LIBRARY} ${ARGS_LIBRARIES}) ++ ${PRE_LINKER_FLAGS} ++ ${ARGS_TARGET_LIBRARY} ++ ${ARGS_LIBRARIES} ++ ${POST_LINKER_FLAGS} ++ ) + + ethosu_eval_link_options(${target}) + +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch new file mode 100644 index 00000000000..d02bbdcb9c5 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch @@ -0,0 +1,136 @@ +From f6855b68b4847f6a1209b8b27a32a6b04543a0be Mon Sep 17 00:00:00 2001 +From: Rob Elliott +Date: Wed, 4 Oct 2023 13:31:33 +0000 +Subject: [Executorch 7/7] Add delegate runner test + +Signed-off-by: Rob Elliott +--- + applications/executorch_tests/CMakeLists.txt | 13 +++++++------ + applications/executorch_tests/pte_to_header.py | 11 +++++++++-- + applications/executorch_tests/runner.cpp | 10 ++++++++-- + cmake/toolchain/arm-none-eabi-gcc.cmake | 6 ++---- + 4 files changed, 26 insertions(+), 14 deletions(-) + +diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt +index c95d53e..5f70e8e 100644 +--- a/applications/executorch_tests/CMakeLists.txt ++++ b/applications/executorch_tests/CMakeLists.txt +@@ -42,6 +42,7 @@ message("ExecuTorch pte file (ET_PTE_FILE_PATH) : ${ET_PTE_FILE_PATH}") + message("**********************") + + set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") ++set(LIB_ET_ETHOS "${ET_BUILD_DIR_PATH}/backends/arm/libexecutorch_delegate_ethos_u.a") + set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_ops_lib.a") + set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") + +@@ -55,9 +56,9 @@ add_custom_command( + ${CMAKE_CURRENT_BINARY_DIR}/fake_dep + ${CMAKE_CURRENT_BINARY_DIR}/model_pte.h + COMMAND ${PYTHON_EXECUTABLE} ./pte_to_header.py --pte ${ET_PTE_FILE_PATH} +- --out ${CMAKE_CURRENT_BINARY_DIR} ++ --outdir ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +- ) ++) + + ethosu_add_executable_test(executor_runner PRIVATE + WHOLE_ARCHIVE TRUE +@@ -65,12 +66,12 @@ ethosu_add_executable_test(executor_runner PRIVATE + LIBRARIES + ${LIB_ET_RUNTIME} + ${LIB_ET_OP_REGISTRATION} +- ${LIB_ET_OP_KERNELS}) +- +-add_dependencies(executor_runner gen_model_header) ++ ${LIB_ET_OP_KERNELS} ++ ${LIB_ET_ETHOS} ++) + + target_include_directories(executor_runner PRIVATE + ${ET_INCLUDE_PATH} + ${CMAKE_CURRENT_BINARY_DIR}) + +-# TODO Memory setup ++add_dependencies(executor_runner gen_model_header) +diff --git a/applications/executorch_tests/pte_to_header.py b/applications/executorch_tests/pte_to_header.py +index 37d88aa..be3282d 100644 +--- a/applications/executorch_tests/pte_to_header.py ++++ b/applications/executorch_tests/pte_to_header.py +@@ -30,11 +30,18 @@ parser.add_argument( + ) + parser.add_argument( + "--outdir", +- help="Output dir for model_pte.h", ++ help="Output dir for model header", + type=str, + required=False, + default=".", + ) ++parser.add_argument( ++ "--outfile", ++ help="Output filename for model header", ++ type=str, ++ required=False, ++ default="model_pte.h", ++) + parser.add_argument( + "--section", + help="Section attribute for the data array", +@@ -43,7 +50,7 @@ parser.add_argument( + default=".sram.data", + ) + args = parser.parse_args() +-outfile = os.path.join(args.outdir, "model_pte.h") ++outfile = os.path.join(args.outdir, args.outfile) + attr = f'__attribute__((section("{args.section}"), aligned(16))) char ' + + with open(args.pte, "rb") as fr, open( +diff --git a/applications/executorch_tests/runner.cpp b/applications/executorch_tests/runner.cpp +index 7ef920d..9dc3519 100644 +--- a/applications/executorch_tests/runner.cpp ++++ b/applications/executorch_tests/runner.cpp +@@ -16,9 +16,10 @@ + #include + #include + +-// Model file - TODO make this configurable through CMake ++// Model file, built from pte file passed to CMAKE as ET_PTE_FILE_PATH + #include "model_pte.h" + ++using namespace exec_aten; + using namespace std; + using torch::executor::Result; + using torch::executor::Error; +@@ -125,8 +126,13 @@ int main() { + status = method->get_outputs(outputs.data(), outputs.size()); + ET_CHECK(status == Error::Ok); + for (int i = 0; i < outputs.size(); ++i) { ++ Tensor t = outputs[i].toTensor(); + for (int j = 0; j < outputs[i].toTensor().numel(); ++j) { +- printf("Output[%d][%d]: %f\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); ++ if( t.scalar_type() == ScalarType::Int ) { ++ printf("Output[%d][%d]: %d\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); ++ } else { ++ printf("Output[%d][%d]: %f\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); ++ } + } + } + return 0; +diff --git a/cmake/toolchain/arm-none-eabi-gcc.cmake b/cmake/toolchain/arm-none-eabi-gcc.cmake +index 0e6a2ed..fdb0d7c 100644 +--- a/cmake/toolchain/arm-none-eabi-gcc.cmake ++++ b/cmake/toolchain/arm-none-eabi-gcc.cmake +@@ -98,8 +98,6 @@ add_compile_options( + # -Wswitch + # -Wswitch-default + # -Wunused +- +- # -Wno-redundant-decls +- +- # -Wno-psabi ++ -Wno-redundant-decls ++ -Wno-psabi + ) +-- +2.42.0 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch new file mode 100644 index 00000000000..68a32f1998e --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch @@ -0,0 +1,24 @@ +From 64cda3dc786f2436177de7ee8805526e216afa74 Mon Sep 17 00:00:00 2001 +From: Hansong Zhang +Date: Wed, 1 Nov 2023 22:03:53 -0700 +Subject: [PATCH] Use new LIB_ET_OP_REGISTRATION lib path + +--- + applications/executorch_tests/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt +index 5f70e8e..a07f22f 100644 +--- a/applications/executorch_tests/CMakeLists.txt ++++ b/applications/executorch_tests/CMakeLists.txt +@@ -43,7 +43,7 @@ message("**********************") + + set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") + set(LIB_ET_ETHOS "${ET_BUILD_DIR_PATH}/backends/arm/libexecutorch_delegate_ethos_u.a") +-set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_ops_lib.a") ++set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/examples/arm/libarm_ops_lib.a") + set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") + + add_custom_target( +-- +2.39.3 diff --git a/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch new file mode 100644 index 00000000000..a329577a46c --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch @@ -0,0 +1,25 @@ +From 8ee58a2ac02693ec5f261c866fc333d268f253d4 Mon Sep 17 00:00:00 2001 +From: Hansong Zhang +Date: Thu, 2 Nov 2023 14:48:03 -0700 +Subject: [PATCH] Use libportable_ops_lib instead + +--- + applications/executorch_tests/CMakeLists.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt +index a07f22f..174b911 100644 +--- a/applications/executorch_tests/CMakeLists.txt ++++ b/applications/executorch_tests/CMakeLists.txt +@@ -43,7 +43,7 @@ message("**********************") + + set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") + set(LIB_ET_ETHOS "${ET_BUILD_DIR_PATH}/backends/arm/libexecutorch_delegate_ethos_u.a") +-set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/examples/arm/libarm_ops_lib.a") ++set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/examples/arm/libportable_ops_lib.a") + set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") + + add_custom_target( +-- +2.39.3 + diff --git a/.ci/docker/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch b/.ci/docker/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch new file mode 100644 index 00000000000..e131ca76ee8 --- /dev/null +++ b/.ci/docker/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch @@ -0,0 +1,129 @@ +From ef07230fbb15edbf27ecaf48994fb157430a5e7c Mon Sep 17 00:00:00 2001 +From: Rob Elliott +Date: Thu, 5 Oct 2023 16:45:42 +0000 +Subject: [PATCH] Improve rescale codegen for TOSA + +Signed-off-by: Rob Elliott +--- + ethosu/vela/tosa_graph_optimiser.py | 56 +++++++++++------------------ + ethosu/vela/tosa_mapping.py | 2 +- + 2 files changed, 22 insertions(+), 36 deletions(-) + +diff --git a/ethosu/vela/tosa_graph_optimiser.py b/ethosu/vela/tosa_graph_optimiser.py +index df6b575..b2e3697 100644 +--- a/ethosu/vela/tosa_graph_optimiser.py ++++ b/ethosu/vela/tosa_graph_optimiser.py +@@ -337,7 +337,8 @@ def rewrite_concat(op): + + def remove_memory_ops(op, arch): + if op.run_on_npu and op.type in (Op.Reshape, Op.Identity): +- bypass_memory_only_ops(op) ++ # TODO: is this ok - function doesn't use arch or nng ++ bypass_memory_only_ops(op, arch, None) + + + def rewrite_activation(op, arch, nng): +@@ -357,7 +358,6 @@ def rewrite_activation(op, arch, nng): + + return op + +- + def rewrite_rescale(op, arch, nng): + if op.type == Op.Rescale: + ifm = op.ifm +@@ -368,7 +368,7 @@ def rewrite_rescale(op, arch, nng): + prev_op = ifm.ops[0] + + # TODO currently not supported +- assert len(ifm.consumer_list) == 1 ++ #assert len(ifm.consumer_list) == 1 + + input_zp = op.attrs["input_zp"] + output_zp = op.attrs["output_zp"] +@@ -390,6 +390,9 @@ def rewrite_rescale(op, arch, nng): + assert False + ifm.quantization.zero_point = input_zp + ofm.quantization.zero_point = output_zp ++ ++ assert False == per_channel, "Don't like per_channel!" ++ + for s, m in zip(shift, multiplier): + # TODO these are the TOSA limitations + assert m >= 0 +@@ -403,45 +406,28 @@ def rewrite_rescale(op, arch, nng): + else: + rounding_mode = RoundingMode.HalfUp + +- if prev_op.type.is_depthwise_conv2d_op() or prev_op.type.is_conv2d_op() or prev_op.type == Op.FullyConnected: ++ fuse = len(ifm.ops) == 1 and prev_op.type.is_depthwise_conv2d_op() or prev_op.type.is_conv2d_op() ++ if fuse: ++ # TODO: ERROR: bias.values didn't exist for an op like Add - presumably not a capability of that op + assert len(multiplier) == len(shift) == len(prev_op.bias.values) +- +- if ifm.dtype == DataType.int32 and per_channel: +- prev_op.explicit_scaling = explicit_scaling +- prev_op.rounding_mode = rounding_mode +- +- # Bypass op +- prev_op.set_output_tensor(ofm) +- DebugDatabase.add_optimised(op, prev_op) +- return op +- else: +- print("Warning, unsupported fusing of TOSA Rescale previous operator is of type:", prev_op.type) +- assert False +- # TODO which are the cases we need to and can do standalone Rescale? +- # TODO should we try to identify a conversion uint8<->int8 accomplished by 2 RESCALE ops? +- # origin might be TFLite op QUANTIZE, should we look to see if they can be translated to QUANTIZE? +- # limited to these at the moment: +- elif ( +- (ifm.dtype == DataType.int8 and ofm.dtype == DataType.int8) +- or (ifm.dtype == DataType.uint8 and ofm.dtype == DataType.int8) +- or (ifm.dtype == DataType.int8 and ofm.dtype == DataType.uint8) +- ): +- # Create NOP performing the RESCALE ++ # TODO: generate replacement fusion code from below ++ assert False, "Fusion possible but i've not implemented it" ++ else: ++ # Generate Rescale behaviour attached to a compatible NOP ++ # TODO: I assume this attaches a new operator into the graph?? + avgpool_op = replace_rescale_with_avg_pool(op) + avgpool_op.rounding_mode = rounding_mode +- ++ + if per_channel: +- # TODO +- avgpool_op.explicit_scaling = explicit_scaling +- print("Warning, unsupported TOSA Rescale") +- assert False ++ assert False, "Assert above removed but still not implemented... :/" + else: + avgpool_op.explicit_scaling = explicit_scaling +- else: +- print("Warning, unsupported fusing of TOSA Rescale previous operator is of type:", prev_op.type) +- assert False +- return op + ++ #print( len(multiplier), len(shift), len(prev_op.get_bias_tensors()) ) ++ #print( ifm.dtype, "PC:", per_channel, op.type ) ++ #print( ifm.dtype, ofm.dtype ) ++ ++ return op + + def convert_pad_in_width(op): + """ +diff --git a/ethosu/vela/tosa_mapping.py b/ethosu/vela/tosa_mapping.py +index 2dafd81..ed5aa2e 100644 +--- a/ethosu/vela/tosa_mapping.py ++++ b/ethosu/vela/tosa_mapping.py +@@ -148,7 +148,7 @@ transpose_conv_attrs = AttrSerializer( + ) + transpose_attrs = AttrSerializer("TransposeAttribute", (("perms", is_vec),)) + axis_attrs = AttrSerializer("AxisAttribute", ("axis",)) +-reshape_attrs = AttrSerializer("ReshapeAttribute", (("shape", is_vec),)) ++reshape_attrs = AttrSerializer("ReshapeAttribute", (("newShape", is_vec),)) + slice_attrs = AttrSerializer("SliceAttribute", (("start", is_vec), ("size", is_vec))) + tile_attrs = AttrSerializer("TileAttribute", (("multiplies", is_vec),)) + resize_attrs = AttrSerializer( +-- +2.41.0 + diff --git a/.ci/docker/examples/arm/setup.sh b/.ci/docker/examples/arm/setup.sh new file mode 100755 index 00000000000..1094e008e55 --- /dev/null +++ b/.ci/docker/examples/arm/setup.sh @@ -0,0 +1,246 @@ +#!/usr/bin/env bash +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +set -eu + +if [[ "${1:-'.'}" == "-h" || "${#}" -eq 0 || "${#}" -gt 2 ]]; then + echo "Usage: $(basename $0) <--i-agree-to-the-contained-eula> [path-to-a-scratch-dir]" + echo "Supplied args: $*" + exit 1 +fi + +######## +### Helper functions +######## +function get_os_name() { + # Returns the name of the system i.e. Linux or Darwin + uname -s +} + +function get_cpu_arch() { + # Returns the cpu architecture like arm64 or x86-64 + uname -m +} + +function verify_md5() { + [[ $# -ne 2 ]] \ + && { echo "[${FUNCNAME[0]}] Invalid number of args, expecting 2, but got $#"; exit 1; } + local ref_checksum="${1}" + local file="${2}" + + local file_checksum="$(md5sum $file | awk '{print $1}')" + if [[ ${ref_checksum} != ${file_checksum} ]]; then + echo "Mismatched MD5 checksum for file: ${file}. Expecting ${ref_checksum} but got ${file_checksum}. Exiting." + exit 1 + fi +} + +######## +### Hardcoded constants +######## +script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) + +if [[ $(get_cpu_arch) == "x86_64" ]]; then + # FVP + fvp_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_20_Linux64.tgz?rev=018659bd574f4e7b95fa647e7836ccf4&hash=22A79103C6FA5FFA7AFF3BE0447F3FF9" + fvp_model_dir="Linux64_GCC-9.3" + fvp_md5_checksum="98e93b949d0fbac977292d8668d34523" + + # toochain + toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz" + toolchain_dir="arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi" + toolchain_md5_checksum="00ebb1b70b1f88906c61206457eacb61" +elif [[ $(get_cpu_arch) == "aarch64" ]]; then + # FVP + fvp_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_20_Linux64_armv8l.tgz?rev=9cc6e9a32bb947ca9b21fa162144cb01&hash=7657A4CF27D42E892E3F08D452AAB073" + fvp_model_dir="Linux64_armv8l_GCC-9.3" + fvp_md5_checksum="cbbabbe39b07939cff7a3738e1492ef1" + + # toochain + toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-aarch64-arm-none-eabi.tar.xz" + toolchain_dir="arm-gnu-toolchain-12.3.rel1-aarch64-arm-none-eabi" + toolchain_md5_checksum="02c9b0d3bb1110575877d8eee1f223f2" +else + echo "[main] Error: only x86-64 & aarch64 architecture is supported for now!"; exit 1; +fi + +# ethos-u +ethos_u_repo_url="https://review.mlplatform.org/ml/ethos-u/ethos-u" +ethos_u_base_rev="0995223100e3da8011700f58e491f1bf59511e3c" + +######## +### Mandatory user args +######## +eula_acceptance="${1:-'.'}"; shift +if [[ "${eula_acceptance}" != "--i-agree-to-the-contained-eula" ]]; then + echo "Must pass first positional argument '--i-agree-to-the-contained-eula' to agree to EULA associated with downloading the FVP. Exiting!" + exit 1 +fi + +######## +### Optional user args +######## +root_dir=${1:-"${script_dir}/ethos-u-scratch"} +root_dir=$(realpath ${root_dir}) + +######## +### Functions +######## + +function setup_fvp() { + # Download and install the Corstone 300 FVP simulator platform + cd "${root_dir}" + if [[ ! -e FVP_cs300.tgz ]]; then + echo "[${FUNCNAME[0]}] Downloading FVP ..." + curl --output FVP_cs300.tgz "${fvp_url}" + verify_md5 ${fvp_md5_checksum} FVP_cs300.tgz + fi + + echo "[${FUNCNAME[0]}] Installing FVP ..." + rm -rf FVP + mkdir -p FVP + cd FVP + tar xf ../FVP_cs300.tgz + ./FVP_Corstone_SSE-300.sh --i-agree-to-the-contained-eula --force --destination ./ --quiet --no-interactive + + fvp_bin_path="$(cd models/${fvp_model_dir} && pwd)" + export PATH=${PATH}:${fvp_bin_path} + + hash FVP_Corstone_SSE-300_Ethos-U55 + echo "export PATH=\${PATH}:${fvp_bin_path}" >> ${setup_path_script} + +} + +function setup_toolchain() { + # Download and install the arm-none-eabi toolchain + cd "${root_dir}" + if [[ ! -e gcc.tar.xz ]]; then + echo "[${FUNCNAME[0]}] Downloading toolchain ..." + curl --output gcc.tar.xz "${toolchain_url}" + verify_md5 ${toolchain_md5_checksum} gcc.tar.xz + fi + + echo "[${FUNCNAME[0]}] Installing toolchain ..." + rm -rf "${toolchain_dir}" + tar xf gcc.tar.xz + toolchain_bin_path="$(cd ${toolchain_dir}/bin && pwd)" + export PATH=${PATH}:${toolchain_bin_path} + hash arm-none-eabi-gcc + echo "export PATH=\${PATH}:${toolchain_bin_path}" >> ${setup_path_script} +} + +function setup_ethos_u() { + # This is the main dir which will pull more repos to do baremetal software dev for cs300 + echo "[${FUNCNAME[0]}] Setting up the repo" + cd "${root_dir}" + [[ ! -d ethos-u ]] && \ + git clone ${ethos_u_repo_url} + cd ethos-u + git reset --hard ${ethos_u_base_rev} + python3 ./fetch_externals.py fetch + pip install pyelftools + echo "[${FUNCNAME[0]}] Done @ $(git describe --all --long 3> /dev/null) in ${root_dir}/ethos-u dir." +} + +function patch_repo() { + # This is a temporary hack until it finds a better home in one for the ARM Ml repos + name="$(basename $repo_dir)" + echo -e "[${FUNCNAME[0]}] Preparing ${name}..." + cd $repo_dir + + git reset --hard ${base_rev} + + patch_dir=${script_dir}/ethos-u-setup/${name}/patches/ + [[ -e ${patch_dir} && $(ls -A ${patch_dir}) ]] && \ + git am -3 ${patch_dir}/*.patch + + echo -e "[${FUNCNAME[0]}] Patched ${name} @ $(git describe --all --long 2> /dev/null) in ${repo_dir} dir.\n" +} + +function setup_tosa_reference_model() { + # The debug flow on the host includes running on a reference implementation of TOSA + # This is useful primarily for debug of quantization accuracy, but also for internal + # errors for the early codebase + cd "${root_dir}" + if [[ ! -e reference_model ]]; then + git clone https://review.mlplatform.org/tosa/reference_model -b main + cd reference_model + git submodule update --init --recursive + cd .. + fi + cd reference_model + mkdir -p build + cd build + cmake .. + n=$(nproc) + make -j"$((n - 5))" + cd reference_model + tosa_bin_path=`pwd` + echo "export PATH=\${PATH}:${tosa_bin_path}" >> "${setup_path_script}" +} + +function setup_vela() { + # + # Prepare the Vela compiler for AoT to Ethos-U compilation + # + cd "${root_dir}" + if [[ ! -e ethos-u-vela ]]; then + git clone https://review.mlplatform.org/ml/ethos-u/ethos-u-vela + repo_dir="${root_dir}/ethos-u-vela" + base_rev=00a15db3e1a188b25065d095152d701f4394cdc5 + patch_repo + fi + cd "${root_dir}/ethos-u-vela" + pip install . +} + +######## +### main +######## +# do basic checks +# Make sure we are on a supported platform +[[ $(get_cpu_arch) != "x86_64" ]] && [[ $(get_cpu_arch) != "aarch64" ]] \ + && { echo "[main] Error: only x86-64 & aarch64 architecture is supported for now!"; exit 1; } + +# No OSx support for FVP +[[ "$(get_os_name)" != "Linux" ]] \ + && { echo "[main] Error: only Linux os is supported for now!"; exit 1; } + +cd "${script_dir}" + +# Setup the root dir +mkdir -p "${root_dir}" +cd "${root_dir}" +echo "[main] Using root dir ${root_dir}" + +setup_path_script="${root_dir}/setup_path.sh" +echo "" > "${setup_path_script}" + +# Setup FVP +setup_fvp + +# Setup toolchain +setup_toolchain + +# Setup the ethos-u dev environment +setup_ethos_u + +# Patch the ethos-u dev environment to include executorch application +repo_dir="${root_dir}/ethos-u/core_platform" +base_rev=204210b1074071532627da9dc69950d058a809f4 +patch_repo + +# Setup the tosa_reference_model +setup_tosa_reference_model + +# Setup vela and patch in codegen fixes +setup_vela + +echo "[main] update path by doing 'source ${setup_path_script}'" + +echo "[main] success!" +exit 0 diff --git a/.ci/docker/requirements-lintrunner.txt b/.ci/docker/requirements-lintrunner.txt new file mode 100644 index 00000000000..e5caf38c59e --- /dev/null +++ b/.ci/docker/requirements-lintrunner.txt @@ -0,0 +1,22 @@ +# Lintrunner itself +lintrunner==0.11.0 +lintrunner-adapters==0.11.0 + +# Flake 8 and its dependencies +flake8==6.0.0 +flake8-breakpoint==1.1.0 +flake8-bugbear==23.6.5 +flake8-comprehensions==3.12.0 +flake8-pyi==23.5.0 +mccabe==0.7.0 +pycodestyle==2.10.0 +torchfix==0.1.1 + +# UFMT +black==22.12.0 +ufmt==2.0.1 +usort==1.0.5 + +# Other linters +clang-format==12.0.1 +cmakelint==1.4.1 diff --git a/.ci/docker/ubuntu/Dockerfile b/.ci/docker/ubuntu/Dockerfile index 4680fc2ee5c..277f3f9fd3b 100644 --- a/.ci/docker/ubuntu/Dockerfile +++ b/.ci/docker/ubuntu/Dockerfile @@ -67,7 +67,7 @@ RUN if [ -n "${LINTRUNNER}" ]; then bash ./install_linter.sh; fi RUN rm install_linter.sh utils.sh requirements-lintrunner.txt ARG ARM_SDK -COPY --chown=ci-user:ci-user ./arm /opt/arm +COPY --chown=ci-user:ci-user ./examples/arm /opt/arm # Set up ARM SDK if needed RUN if [ -n "${ARM_SDK}" ]; then git config --global user.email "ossci@example.com"; git config --global user.name "OSS CI"; bash /opt/arm/setup.sh --i-agree-to-the-contained-eula /opt/arm-sdk; chown -R ci-user:ci-user /opt/arm-sdk; fi diff --git a/.github/workflows/docker-builds.yml b/.github/workflows/docker-builds.yml index f48a5ab6f3c..c5b76d357db 100644 --- a/.github/workflows/docker-builds.yml +++ b/.github/workflows/docker-builds.yml @@ -6,8 +6,6 @@ on: paths: - .ci/docker/** - .github/workflows/docker-builds.yml - - requirements-lintrunner.txt - - examples/arm/** push: branches: - main @@ -15,8 +13,6 @@ on: paths: - .ci/docker/** - .github/workflows/docker-builds.yml - - requirements-lintrunner.txt - - examples/arm/** schedule: - cron: 1 3 * * 3 diff --git a/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake b/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake deleted file mode 100644 index 918edadb593..00000000000 --- a/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake +++ /dev/null @@ -1,105 +0,0 @@ -# -# Copyright (c) 2020-2022 Arm Limited. All rights reserved. -# -# SPDX-License-Identifier: Apache-2.0 -# -# Licensed 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 -# -# 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. -# - -# Copied this file from core_platform/cmake/toolchain/arm-non-eabi-gcc.cmake -# And modified to align better with cs300 platform - -set(TARGET_CPU "cortex-m55" CACHE STRING "Target CPU") -string(TOLOWER ${TARGET_CPU} CMAKE_SYSTEM_PROCESSOR) - -set(CMAKE_SYSTEM_NAME Generic) -set(CMAKE_C_COMPILER "arm-none-eabi-gcc") -set(CMAKE_CXX_COMPILER "arm-none-eabi-g++") -set(CMAKE_ASM_COMPILER "arm-none-eabi-gcc") -set(CMAKE_LINKER "arm-none-eabi-ld") - -set(CMAKE_EXECUTABLE_SUFFIX ".elf") -set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - -# Select C/C++ version -set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 14) - -set(GCC_CPU ${CMAKE_SYSTEM_PROCESSOR}) -string(REPLACE "cortex-m85" "cortex-m55" GCC_CPU ${GCC_CPU}) - -# Compile options -add_compile_options( - -mcpu=${GCC_CPU} - -mthumb - "$<$:-gdwarf-3>" - "$<$:-fno-unwind-tables;-fno-rtti;-fno-exceptions>" - -fdata-sections - -ffunction-sections) - -# Compile defines -add_compile_definitions( - "$<$>:NDEBUG>") - -# Link options -add_link_options( - -mcpu=${GCC_CPU} - -mthumb - --specs=nosys.specs) - -# Set floating point unit -if(CMAKE_SYSTEM_PROCESSOR MATCHES "\\+fp") - set(FLOAT hard) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "\\+nofp") - set(FLOAT soft) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m33(\\+|$)" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m55(\\+|$)" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m85(\\+|$)") - set(FLOAT hard) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m4(\\+|$)" OR - CMAKE_SYSTEM_PROCESSOR MATCHES "cortex-m7(\\+|$)") - set(FLOAT hard) - set(FPU_CONFIG "fpv4-sp-d16") - add_compile_options(-mfpu=${FPU_CONFIG}) - add_link_options(-mfpu=${FPU_CONFIG}) -else() - set(FLOAT soft) -endif() - -if(FLOAT) - add_compile_options(-mfloat-abi=${FLOAT}) - add_link_options(-mfloat-abi=${FLOAT}) -endif() - -add_link_options(LINKER:--nmagic,--gc-sections) - -# Compilation warnings -add_compile_options( - # -Wall - # -Wextra - # -Wcast-align - # -Wdouble-promotion - # -Wformat - # -Wmissing-field-initializers - # -Wnull-dereference - # -Wredundant-decls - # -Wshadow - # -Wswitch - # -Wswitch-default - # -Wunused - # -Wno-redundant-decls - -Wno-psabi -) diff --git a/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake b/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake new file mode 120000 index 00000000000..14f678c44ec --- /dev/null +++ b/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake @@ -0,0 +1 @@ +../../../.ci/docker/examples/arm/ethos-u-setup/arm-none-eabi-gcc.cmake \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch b/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch deleted file mode 100644 index 8928c16c39e..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 949334fe4cfd84c4d4682a92d055be26670670be Mon Sep 17 00:00:00 2001 -From: Digant Desai -Date: Tue, 3 Oct 2023 21:20:21 -0700 -Subject: [Executorch 1/7] Add README - ---- - applications/executorch_tests/README.md | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - create mode 100644 applications/executorch_tests/README.md - -diff --git a/applications/executorch_tests/README.md b/applications/executorch_tests/README.md -new file mode 100644 -index 0000000..f2dfb05 ---- /dev/null -+++ b/applications/executorch_tests/README.md -@@ -0,0 +1,16 @@ -+## ExecuTorch -+A unified ML software stack within the PyTorch platform for edge devices. It -+defines new compiler entry points as well as a state-of-art runtime. -+ -+Home: https://github.com/pytorch/executorch/ -+ -+### executor_runner -+ -+This test is a simple wrapper around ExecuTorch runtime, capable of running -+`.pte` model files compatible with ExecuTorch. -+ -+If configured correctly with `ET_*` CMake variables pointing to the ExecuTorch -+project build, then this test bin executes `model.pte.h` file converted from -+`model.pte` using `pte_to_header.py`, from the ExecuTorch project root dir, -+containing an ExecuTorch compatible PyTorch model on the Costrone 300 FVP using -+ExecuTorch runtime. --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch b/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch new file mode 120000 index 00000000000..0740aff3b9f --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0001-Executorch-Add-README.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch b/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch deleted file mode 100644 index 5d5baaad1d1..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch +++ /dev/null @@ -1,25 +0,0 @@ -From ef976aa04e7d6b7571e9791900f9d80aeb0338da Mon Sep 17 00:00:00 2001 -From: Digant Desai -Date: Thu, 28 Sep 2023 18:05:03 -0700 -Subject: [Executorch 2/7] regress cmake version from 3.21 --> 3.20 - ---- - targets/corstone-300/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/targets/corstone-300/CMakeLists.txt b/targets/corstone-300/CMakeLists.txt -index 62205bb..7dda8a1 100644 ---- a/targets/corstone-300/CMakeLists.txt -+++ b/targets/corstone-300/CMakeLists.txt -@@ -42,7 +42,7 @@ set(MEMORY_ARENA "dram" CACHE STRING "Memory config for arena") - # Project - ############################################################################# - --cmake_minimum_required(VERSION 3.21) -+cmake_minimum_required(VERSION 3.20) - - project(ethos-u-corstone-300 VERSION 0.0.1) - --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch b/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch new file mode 120000 index 00000000000..be96eebc4e5 --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0002-Executorch-local-patch-regress-cmake-version-from-3..patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch b/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch deleted file mode 100644 index 5343f9c524f..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch +++ /dev/null @@ -1,52 +0,0 @@ -From cbda805f968a45205c9d3d4a2f4cb534e207d504 Mon Sep 17 00:00:00 2001 -From: Digant Desai -Date: Thu, 28 Sep 2023 18:05:30 -0700 -Subject: [Executorch 3/7] Disable warnings to reduce verbosity - ---- - cmake/toolchain/arm-none-eabi-gcc.cmake | 28 ++++++++++++------------- - 1 file changed, 14 insertions(+), 14 deletions(-) - -diff --git a/cmake/toolchain/arm-none-eabi-gcc.cmake b/cmake/toolchain/arm-none-eabi-gcc.cmake -index 093005e..0e6a2ed 100644 ---- a/cmake/toolchain/arm-none-eabi-gcc.cmake -+++ b/cmake/toolchain/arm-none-eabi-gcc.cmake -@@ -85,21 +85,21 @@ add_link_options(LINKER:--nmagic,--gc-sections) - - # Compilation warnings - add_compile_options( -- -Wall -- -Wextra -+ # -Wall -+ # -Wextra - -- -Wcast-align -- -Wdouble-promotion -- -Wformat -- -Wmissing-field-initializers -- -Wnull-dereference -- -Wredundant-decls -- -Wshadow -- -Wswitch -- -Wswitch-default -- -Wunused -+ # -Wcast-align -+ # -Wdouble-promotion -+ # -Wformat -+ # -Wmissing-field-initializers -+ # -Wnull-dereference -+ # -Wredundant-decls -+ # -Wshadow -+ # -Wswitch -+ # -Wswitch-default -+ # -Wunused - -- -Wno-redundant-decls -+ # -Wno-redundant-decls - -- -Wno-psabi -+ # -Wno-psabi - ) --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch b/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch new file mode 120000 index 00000000000..e27184c030b --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0003-Executorch-local-patch-Disable-warnings-to-reduce-ve.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch b/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch deleted file mode 100644 index 8ccd3b7b1a6..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 02eb3615cdb2cc963f20e103893f76499c98ad50 Mon Sep 17 00:00:00 2001 -From: Digant Desai -Date: Mon, 2 Oct 2023 20:39:39 -0700 -Subject: [Executorch 4/7] New phdr for .data section - ---- - targets/corstone-300/platform.ld | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/targets/corstone-300/platform.ld b/targets/corstone-300/platform.ld -index 8d77329..8de77c4 100644 ---- a/targets/corstone-300/platform.ld -+++ b/targets/corstone-300/platform.ld -@@ -94,6 +94,7 @@ PHDRS - { - rom_exec PT_LOAD; - rom_dram PT_LOAD; -+ data PT_LOAD; /* HACK: New prog header for .data (and friends) going in DTCM */ - null PT_NULL; - } - -@@ -247,7 +248,7 @@ SECTIONS - /* All data end */ - __data_end__ = .; - -- } > DTCM :rom_exec -+ } > DTCM :data - - .sram.bss : - { --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch b/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch new file mode 120000 index 00000000000..0dd6bf9953c --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0004-Executorch-local-patch-New-phdr-for-.data-section.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch b/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch deleted file mode 100644 index 175a7b6f303..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 55019e4eb8d39f3fb1fb303380e903294604837c Mon Sep 17 00:00:00 2001 -From: Digant Desai -Date: Tue, 3 Oct 2023 21:20:07 -0700 -Subject: [Executorch 5/7] Add pte to header script - ---- - .../executorch_tests/pte_to_header.py | 65 +++++++++++++++++++ - 1 file changed, 65 insertions(+) - create mode 100644 applications/executorch_tests/pte_to_header.py - -diff --git a/applications/executorch_tests/pte_to_header.py b/applications/executorch_tests/pte_to_header.py -new file mode 100644 -index 0000000..37d88aa ---- /dev/null -+++ b/applications/executorch_tests/pte_to_header.py -@@ -0,0 +1,65 @@ -+# Copyright (c) Meta Platforms, Inc. and affiliates. -+# All rights reserved. -+# -+# This source code is licensed under the BSD-style license found in the -+# LICENSE file in the root directory of this source tree. -+ -+import binascii -+import os -+from argparse import ArgumentParser, ArgumentTypeError -+ -+# Also see: https://git.mlplatform.org/ml/ethos-u/ml-embedded-evaluation-kit.git/tree/scripts/py/gen_model_cpp.py -+ -+bytes_per_line = 32 -+hex_digits_per_line = bytes_per_line * 2 -+ -+ -+def input_file_path(path): -+ if os.path.exists(path): -+ return path -+ else: -+ raise ArgumentTypeError(f"input filepath:{path} does not exist") -+ -+ -+parser = ArgumentParser() -+parser.add_argument( -+ "--pte", -+ help="ExecuTorch .pte model file", -+ type=input_file_path, -+ required=True, -+) -+parser.add_argument( -+ "--outdir", -+ help="Output dir for model_pte.h", -+ type=str, -+ required=False, -+ default=".", -+) -+parser.add_argument( -+ "--section", -+ help="Section attribute for the data array", -+ type=str, -+ required=False, -+ default=".sram.data", -+) -+args = parser.parse_args() -+outfile = os.path.join(args.outdir, "model_pte.h") -+attr = f'__attribute__((section("{args.section}"), aligned(16))) char ' -+ -+with open(args.pte, "rb") as fr, open( -+ outfile, "w" -+) as fw: -+ data = fr.read() -+ hexstream = binascii.hexlify(data).decode("utf-8") -+ hexstring = attr + "model_pte[] = {" -+ -+ for i in range(0, len(hexstream), 2): -+ if 0 == (i % hex_digits_per_line): -+ hexstring += "\n" -+ hexstring += "0x" + hexstream[i : i + 2] + ", " -+ -+ hexstring += "};\n" -+ fw.write(hexstring) -+ print( -+ f"Input: {args.pte} with {len(data)} bytes. Output: {outfile} with {len(hexstring)} bytes. Section: {args.section}." -+ ) --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch b/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch new file mode 120000 index 00000000000..ab98ad0e929 --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0005-Executorch-Add-pte-to-header-script.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch b/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch deleted file mode 100644 index 7aaa7851c54..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch +++ /dev/null @@ -1,283 +0,0 @@ -From 25f530f4ef8d994f61fe979e94b4c929ff2481e6 Mon Sep 17 00:00:00 2001 -From: Digant Desai -Date: Thu, 28 Sep 2023 19:07:51 -0700 -Subject: [Executorch 6/7] Add executorch_runner test - ---- - applications/CMakeLists.txt | 2 + - applications/executorch_tests/CMakeLists.txt | 76 +++++++++++ - applications/executorch_tests/runner.cpp | 133 +++++++++++++++++++ - cmake/helpers.cmake | 13 +- - 4 files changed, 222 insertions(+), 2 deletions(-) - create mode 100644 applications/executorch_tests/CMakeLists.txt - create mode 100644 applications/executorch_tests/runner.cpp - -diff --git a/applications/CMakeLists.txt b/applications/CMakeLists.txt -index 1fa2b2e..68e5427 100644 ---- a/applications/CMakeLists.txt -+++ b/applications/CMakeLists.txt -@@ -28,6 +28,8 @@ add_subdirectory(threadx_demo) - - add_subdirectory(message_handler_openamp) - -+add_subdirectory(executorch_tests) -+ - if (CMAKE_CXX_COMPILER_ID STREQUAL "ARMClang") - # Only armclang supported for now - add_subdirectory(trustzone_inference) -diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt -new file mode 100644 -index 0000000..c95d53e ---- /dev/null -+++ b/applications/executorch_tests/CMakeLists.txt -@@ -0,0 +1,76 @@ -+# -+# Copyright (c) 2021 Arm Limited. All rights reserved. -+# -+# SPDX-License-Identifier: Apache-2.0 -+# -+# Licensed 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 -+# -+# 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. -+# -+ -+if (NOT TARGET ethosu_core_driver) -+ return() -+endif() -+ -+#### -+#### ExecuTorch demo app/test -+#### -+ -+set(ET_DIR_PATH "<..>/executorch" CACHE PATH "Path to ExecuTorch dir") -+set(ET_BUILD_DIR_PATH "${ET_DIR_PATH}/cmake-out" CACHE PATH "Path to ExecuTorch build dir") -+set(ET_INCLUDE_PATH "${ET_DIR_PATH}/.." CACHE PATH "Path to ExecuTorch headers") -+set(ET_PTE_FILE_PATH "${ET_PTE_FILE_PATH}" CACHE PATH "Path to ExecuTorch model pte") -+ -+get_filename_component(ET_BUILD_DIR_PATH ${ET_BUILD_DIR_PATH} REALPATH) -+get_filename_component(ET_DIR_PATH ${ET_DIR_PATH} REALPATH) -+get_filename_component(ET_INCLUDE_PATH ${ET_INCLUDE_PATH} REALPATH) -+get_filename_component(ET_PTE_FILE_PATH ${ET_PTE_FILE_PATH} REALPATH) -+ -+message("**********************") -+message("ExecuTorch dir (ET_DIR_PATH) : ${ET_DIR_PATH}") -+message("ExecuTorch build dir(ET_BUILD_DIR_PATH) : ${ET_BUILD_DIR_PATH}") -+message("ExecuTorch headers (ET_INCUDE_PATH) : ${ET_INCLUDE_PATH}") -+message("ExecuTorch pte file (ET_PTE_FILE_PATH) : ${ET_PTE_FILE_PATH}") -+message("**********************") -+ -+set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") -+set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_ops_lib.a") -+set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") -+ -+add_custom_target( -+ gen_model_header ALL -+ DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/fake_dep -+) -+ -+add_custom_command( -+ OUTPUT -+ ${CMAKE_CURRENT_BINARY_DIR}/fake_dep -+ ${CMAKE_CURRENT_BINARY_DIR}/model_pte.h -+ COMMAND ${PYTHON_EXECUTABLE} ./pte_to_header.py --pte ${ET_PTE_FILE_PATH} -+ --out ${CMAKE_CURRENT_BINARY_DIR} -+ WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -+ ) -+ -+ethosu_add_executable_test(executor_runner PRIVATE -+ WHOLE_ARCHIVE TRUE -+ SOURCES runner.cpp -+ LIBRARIES -+ ${LIB_ET_RUNTIME} -+ ${LIB_ET_OP_REGISTRATION} -+ ${LIB_ET_OP_KERNELS}) -+ -+add_dependencies(executor_runner gen_model_header) -+ -+target_include_directories(executor_runner PRIVATE -+${ET_INCLUDE_PATH} -+${CMAKE_CURRENT_BINARY_DIR}) -+ -+# TODO Memory setup -diff --git a/applications/executorch_tests/runner.cpp b/applications/executorch_tests/runner.cpp -new file mode 100644 -index 0000000..7ef920d ---- /dev/null -+++ b/applications/executorch_tests/runner.cpp -@@ -0,0 +1,133 @@ -+/* Copyright (c) Meta Platforms, Inc. and affiliates. -+ * All rights reserved. -+ * -+ * This source code is licensed under the BSD-style license found in the -+ * LICENSE file in the root directory of this source tree. -+ */ -+ -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+// Model file - TODO make this configurable through CMake -+#include "model_pte.h" -+ -+using namespace std; -+using torch::executor::Result; -+using torch::executor::Error; -+ -+__attribute__((section(".sram.data"), aligned(16))) uint8_t method_allocator_pool[4 * 1024U]; -+ -+void et_pal_init(void) {} -+ -+__ET_NORETURN void et_pal_abort(void) { -+ __builtin_trap(); -+} -+ -+et_timestamp_t et_pal_current_ticks(void) { -+ // libc.a - warning: _gettimeofday is not implemented and will always fail -+ return 11223344; -+} -+ -+/** -+ * Emit a log message via platform output (serial port, console, etc). -+ */ -+void et_pal_emit_log_message( -+ __ET_UNUSED et_timestamp_t timestamp, -+ et_pal_log_level_t level, -+ const char* filename, -+ __ET_UNUSED const char* function, -+ size_t line, -+ const char* message, -+ __ET_UNUSED size_t length) { -+ fprintf( -+ stderr, -+ "%c executorch:%s:%zu] %s\n", -+ level, -+ filename, -+ line, -+ message); -+} -+ -+int main() { -+ torch::executor::runtime_init(); -+ -+ auto loader = torch::executor::util::BufferDataLoader(model_pte, sizeof(model_pte)); -+ ET_LOG(Info, "Model PTE file loaded. Size: %lu bytes.", sizeof(model_pte)); -+ Result program = torch::executor::Program::load(&loader); -+ if(!program.ok()) { -+ ET_LOG(Info,"Program loading failed @ 0x%p: 0x%" PRIx32, model_pte, program.error()); -+ } -+ -+ ET_LOG(Info,"Model buffer loaded, has %lu methods", program->num_methods()); -+ -+ const char* method_name = nullptr; -+ { -+ const auto method_name_result = program->get_method_name(0); -+ ET_CHECK_MSG(method_name_result.ok(), "Program has no methods"); -+ method_name = *method_name_result; -+ } -+ ET_LOG(Info,"Running method %s", method_name); -+ -+ Result method_meta = program->method_meta(method_name); -+ if (!method_meta.ok()) { -+ ET_LOG(Info,"Failed to get method_meta for %s: 0x%x", -+ method_name, (unsigned int)method_meta.error()); -+ } -+ -+ torch::executor::MemoryAllocator method_allocator{ -+ torch::executor::MemoryAllocator(sizeof(method_allocator_pool), method_allocator_pool)}; -+ -+ std::vector> planned_buffers; // Owns the memory -+ std::vector> planned_spans; // Passed to the allocator -+ size_t num_memory_planned_buffers = method_meta->num_memory_planned_buffers(); -+ -+ for (size_t id = 0; id < num_memory_planned_buffers; ++id) { -+ size_t buffer_size = static_cast(method_meta->memory_planned_buffer_size(id).get()); -+ ET_LOG(Info,"Setting up planned buffer %zu, size %zu.", id, buffer_size); -+ -+ planned_buffers.push_back(std::make_unique(buffer_size)); -+ planned_spans.push_back({planned_buffers.back().get(), buffer_size}); -+ } -+ -+ torch::executor::HierarchicalAllocator planned_memory( -+ {planned_spans.data(), planned_spans.size()}); -+ -+ torch::executor::MemoryManager memory_manager(&method_allocator, &planned_memory); -+ -+ Result method = program->load_method(method_name, &memory_manager); -+ if(!method.ok()) { -+ ET_LOG(Info,"Loading of method %s failed with status 0x%" PRIx32, method_name, method.error()); -+ } -+ ET_LOG(Info,"Method loaded."); -+ -+ ET_LOG(Info,"Preparing inputs..."); -+ auto inputs = torch::executor::util::PrepareInputTensors(*method); -+ ET_LOG(Info,"Input prepared."); -+ -+ ET_LOG(Info,"Starting the model execution..."); -+ Error status = method->execute(); -+ if(status != Error::Ok){ -+ ET_LOG(Info,"Execution of method %s failed with status 0x%" PRIx32, method_name, status); -+ } else { -+ ET_LOG(Info,"Model executed successfully."); -+ } -+ -+ std::vector outputs(method->outputs_size()); -+ ET_LOG(Info, "%zu outputs: ", outputs.size()); -+ status = method->get_outputs(outputs.data(), outputs.size()); -+ ET_CHECK(status == Error::Ok); -+ for (int i = 0; i < outputs.size(); ++i) { -+ for (int j = 0; j < outputs[i].toTensor().numel(); ++j) { -+ printf("Output[%d][%d]: %f\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); -+ } -+ } -+ return 0; -+} -diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake -index a21d9f0..036f189 100644 ---- a/cmake/helpers.cmake -+++ b/cmake/helpers.cmake -@@ -85,7 +85,7 @@ endfunction() - ############################################################################# - - function(ethosu_add_executable target) -- cmake_parse_arguments(ARGS "" "TARGET_LIBRARY" "SOURCES;LIBRARIES" ${ARGN}) -+ cmake_parse_arguments(ARGS "WHOLE_ARCHIVE" "TARGET_LIBRARY" "SOURCES;LIBRARIES" ${ARGN}) - add_executable(${target}) - - target_sources(${target} PRIVATE -@@ -95,8 +95,17 @@ function(ethosu_add_executable target) - set(ARGS_TARGET_LIBRARY ethosu_target_init) - endif() - -+ if (ARGS_WHOLE_ARCHIVE) -+ set(PRE_LINKER_FLAGS "-Wl,--whole-archive") -+ set(POST_LINKER_FLAGS "-Wl,--no-whole-archive") -+ endif() -+ - target_link_libraries(${target} PRIVATE -- ${ARGS_TARGET_LIBRARY} ${ARGS_LIBRARIES}) -+ ${PRE_LINKER_FLAGS} -+ ${ARGS_TARGET_LIBRARY} -+ ${ARGS_LIBRARIES} -+ ${POST_LINKER_FLAGS} -+ ) - - ethosu_eval_link_options(${target}) - --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch b/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch new file mode 120000 index 00000000000..98cfad8a516 --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0006-Executorch-Add-executorch_runner-test.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch b/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch deleted file mode 100644 index d02bbdcb9c5..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch +++ /dev/null @@ -1,136 +0,0 @@ -From f6855b68b4847f6a1209b8b27a32a6b04543a0be Mon Sep 17 00:00:00 2001 -From: Rob Elliott -Date: Wed, 4 Oct 2023 13:31:33 +0000 -Subject: [Executorch 7/7] Add delegate runner test - -Signed-off-by: Rob Elliott ---- - applications/executorch_tests/CMakeLists.txt | 13 +++++++------ - applications/executorch_tests/pte_to_header.py | 11 +++++++++-- - applications/executorch_tests/runner.cpp | 10 ++++++++-- - cmake/toolchain/arm-none-eabi-gcc.cmake | 6 ++---- - 4 files changed, 26 insertions(+), 14 deletions(-) - -diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt -index c95d53e..5f70e8e 100644 ---- a/applications/executorch_tests/CMakeLists.txt -+++ b/applications/executorch_tests/CMakeLists.txt -@@ -42,6 +42,7 @@ message("ExecuTorch pte file (ET_PTE_FILE_PATH) : ${ET_PTE_FILE_PATH}") - message("**********************") - - set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") -+set(LIB_ET_ETHOS "${ET_BUILD_DIR_PATH}/backends/arm/libexecutorch_delegate_ethos_u.a") - set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_ops_lib.a") - set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") - -@@ -55,9 +56,9 @@ add_custom_command( - ${CMAKE_CURRENT_BINARY_DIR}/fake_dep - ${CMAKE_CURRENT_BINARY_DIR}/model_pte.h - COMMAND ${PYTHON_EXECUTABLE} ./pte_to_header.py --pte ${ET_PTE_FILE_PATH} -- --out ${CMAKE_CURRENT_BINARY_DIR} -+ --outdir ${CMAKE_CURRENT_BINARY_DIR} - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} -- ) -+) - - ethosu_add_executable_test(executor_runner PRIVATE - WHOLE_ARCHIVE TRUE -@@ -65,12 +66,12 @@ ethosu_add_executable_test(executor_runner PRIVATE - LIBRARIES - ${LIB_ET_RUNTIME} - ${LIB_ET_OP_REGISTRATION} -- ${LIB_ET_OP_KERNELS}) -- --add_dependencies(executor_runner gen_model_header) -+ ${LIB_ET_OP_KERNELS} -+ ${LIB_ET_ETHOS} -+) - - target_include_directories(executor_runner PRIVATE - ${ET_INCLUDE_PATH} - ${CMAKE_CURRENT_BINARY_DIR}) - --# TODO Memory setup -+add_dependencies(executor_runner gen_model_header) -diff --git a/applications/executorch_tests/pte_to_header.py b/applications/executorch_tests/pte_to_header.py -index 37d88aa..be3282d 100644 ---- a/applications/executorch_tests/pte_to_header.py -+++ b/applications/executorch_tests/pte_to_header.py -@@ -30,11 +30,18 @@ parser.add_argument( - ) - parser.add_argument( - "--outdir", -- help="Output dir for model_pte.h", -+ help="Output dir for model header", - type=str, - required=False, - default=".", - ) -+parser.add_argument( -+ "--outfile", -+ help="Output filename for model header", -+ type=str, -+ required=False, -+ default="model_pte.h", -+) - parser.add_argument( - "--section", - help="Section attribute for the data array", -@@ -43,7 +50,7 @@ parser.add_argument( - default=".sram.data", - ) - args = parser.parse_args() --outfile = os.path.join(args.outdir, "model_pte.h") -+outfile = os.path.join(args.outdir, args.outfile) - attr = f'__attribute__((section("{args.section}"), aligned(16))) char ' - - with open(args.pte, "rb") as fr, open( -diff --git a/applications/executorch_tests/runner.cpp b/applications/executorch_tests/runner.cpp -index 7ef920d..9dc3519 100644 ---- a/applications/executorch_tests/runner.cpp -+++ b/applications/executorch_tests/runner.cpp -@@ -16,9 +16,10 @@ - #include - #include - --// Model file - TODO make this configurable through CMake -+// Model file, built from pte file passed to CMAKE as ET_PTE_FILE_PATH - #include "model_pte.h" - -+using namespace exec_aten; - using namespace std; - using torch::executor::Result; - using torch::executor::Error; -@@ -125,8 +126,13 @@ int main() { - status = method->get_outputs(outputs.data(), outputs.size()); - ET_CHECK(status == Error::Ok); - for (int i = 0; i < outputs.size(); ++i) { -+ Tensor t = outputs[i].toTensor(); - for (int j = 0; j < outputs[i].toTensor().numel(); ++j) { -- printf("Output[%d][%d]: %f\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); -+ if( t.scalar_type() == ScalarType::Int ) { -+ printf("Output[%d][%d]: %d\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); -+ } else { -+ printf("Output[%d][%d]: %f\n", i, j, outputs[i].toTensor().const_data_ptr()[j]); -+ } - } - } - return 0; -diff --git a/cmake/toolchain/arm-none-eabi-gcc.cmake b/cmake/toolchain/arm-none-eabi-gcc.cmake -index 0e6a2ed..fdb0d7c 100644 ---- a/cmake/toolchain/arm-none-eabi-gcc.cmake -+++ b/cmake/toolchain/arm-none-eabi-gcc.cmake -@@ -98,8 +98,6 @@ add_compile_options( - # -Wswitch - # -Wswitch-default - # -Wunused -- -- # -Wno-redundant-decls -- -- # -Wno-psabi -+ -Wno-redundant-decls -+ -Wno-psabi - ) --- -2.42.0 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch b/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch new file mode 120000 index 00000000000..f918a80cbf0 --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0007-Executorch-Add-delegate-runner-test.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch b/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch deleted file mode 100644 index 68a32f1998e..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 64cda3dc786f2436177de7ee8805526e216afa74 Mon Sep 17 00:00:00 2001 -From: Hansong Zhang -Date: Wed, 1 Nov 2023 22:03:53 -0700 -Subject: [PATCH] Use new LIB_ET_OP_REGISTRATION lib path - ---- - applications/executorch_tests/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt -index 5f70e8e..a07f22f 100644 ---- a/applications/executorch_tests/CMakeLists.txt -+++ b/applications/executorch_tests/CMakeLists.txt -@@ -43,7 +43,7 @@ message("**********************") - - set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") - set(LIB_ET_ETHOS "${ET_BUILD_DIR_PATH}/backends/arm/libexecutorch_delegate_ethos_u.a") --set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_ops_lib.a") -+set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/examples/arm/libarm_ops_lib.a") - set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") - - add_custom_target( --- -2.39.3 diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch b/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch new file mode 120000 index 00000000000..5488a625f9c --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0008-Use-new-LIB_ET_OP_REGISTRATION-lib-path.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch b/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch deleted file mode 100644 index a329577a46c..00000000000 --- a/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 8ee58a2ac02693ec5f261c866fc333d268f253d4 Mon Sep 17 00:00:00 2001 -From: Hansong Zhang -Date: Thu, 2 Nov 2023 14:48:03 -0700 -Subject: [PATCH] Use libportable_ops_lib instead - ---- - applications/executorch_tests/CMakeLists.txt | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/applications/executorch_tests/CMakeLists.txt b/applications/executorch_tests/CMakeLists.txt -index a07f22f..174b911 100644 ---- a/applications/executorch_tests/CMakeLists.txt -+++ b/applications/executorch_tests/CMakeLists.txt -@@ -43,7 +43,7 @@ message("**********************") - - set(LIB_ET_RUNTIME "${ET_BUILD_DIR_PATH}/libexecutorch.a") - set(LIB_ET_ETHOS "${ET_BUILD_DIR_PATH}/backends/arm/libexecutorch_delegate_ethos_u.a") --set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/examples/arm/libarm_ops_lib.a") -+set(LIB_ET_OP_REGISTRATION "${ET_BUILD_DIR_PATH}/examples/arm/libportable_ops_lib.a") - set(LIB_ET_OP_KERNELS "${ET_BUILD_DIR_PATH}/kernels/portable/libportable_kernels.a") - - add_custom_target( --- -2.39.3 - diff --git a/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch b/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch new file mode 120000 index 00000000000..3277c23b894 --- /dev/null +++ b/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/core_platform/patches/0009-Executorch-Use-libportable_ops_lib-instead.patch \ No newline at end of file diff --git a/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch b/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch deleted file mode 100644 index e131ca76ee8..00000000000 --- a/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch +++ /dev/null @@ -1,129 +0,0 @@ -From ef07230fbb15edbf27ecaf48994fb157430a5e7c Mon Sep 17 00:00:00 2001 -From: Rob Elliott -Date: Thu, 5 Oct 2023 16:45:42 +0000 -Subject: [PATCH] Improve rescale codegen for TOSA - -Signed-off-by: Rob Elliott ---- - ethosu/vela/tosa_graph_optimiser.py | 56 +++++++++++------------------ - ethosu/vela/tosa_mapping.py | 2 +- - 2 files changed, 22 insertions(+), 36 deletions(-) - -diff --git a/ethosu/vela/tosa_graph_optimiser.py b/ethosu/vela/tosa_graph_optimiser.py -index df6b575..b2e3697 100644 ---- a/ethosu/vela/tosa_graph_optimiser.py -+++ b/ethosu/vela/tosa_graph_optimiser.py -@@ -337,7 +337,8 @@ def rewrite_concat(op): - - def remove_memory_ops(op, arch): - if op.run_on_npu and op.type in (Op.Reshape, Op.Identity): -- bypass_memory_only_ops(op) -+ # TODO: is this ok - function doesn't use arch or nng -+ bypass_memory_only_ops(op, arch, None) - - - def rewrite_activation(op, arch, nng): -@@ -357,7 +358,6 @@ def rewrite_activation(op, arch, nng): - - return op - -- - def rewrite_rescale(op, arch, nng): - if op.type == Op.Rescale: - ifm = op.ifm -@@ -368,7 +368,7 @@ def rewrite_rescale(op, arch, nng): - prev_op = ifm.ops[0] - - # TODO currently not supported -- assert len(ifm.consumer_list) == 1 -+ #assert len(ifm.consumer_list) == 1 - - input_zp = op.attrs["input_zp"] - output_zp = op.attrs["output_zp"] -@@ -390,6 +390,9 @@ def rewrite_rescale(op, arch, nng): - assert False - ifm.quantization.zero_point = input_zp - ofm.quantization.zero_point = output_zp -+ -+ assert False == per_channel, "Don't like per_channel!" -+ - for s, m in zip(shift, multiplier): - # TODO these are the TOSA limitations - assert m >= 0 -@@ -403,45 +406,28 @@ def rewrite_rescale(op, arch, nng): - else: - rounding_mode = RoundingMode.HalfUp - -- if prev_op.type.is_depthwise_conv2d_op() or prev_op.type.is_conv2d_op() or prev_op.type == Op.FullyConnected: -+ fuse = len(ifm.ops) == 1 and prev_op.type.is_depthwise_conv2d_op() or prev_op.type.is_conv2d_op() -+ if fuse: -+ # TODO: ERROR: bias.values didn't exist for an op like Add - presumably not a capability of that op - assert len(multiplier) == len(shift) == len(prev_op.bias.values) -- -- if ifm.dtype == DataType.int32 and per_channel: -- prev_op.explicit_scaling = explicit_scaling -- prev_op.rounding_mode = rounding_mode -- -- # Bypass op -- prev_op.set_output_tensor(ofm) -- DebugDatabase.add_optimised(op, prev_op) -- return op -- else: -- print("Warning, unsupported fusing of TOSA Rescale previous operator is of type:", prev_op.type) -- assert False -- # TODO which are the cases we need to and can do standalone Rescale? -- # TODO should we try to identify a conversion uint8<->int8 accomplished by 2 RESCALE ops? -- # origin might be TFLite op QUANTIZE, should we look to see if they can be translated to QUANTIZE? -- # limited to these at the moment: -- elif ( -- (ifm.dtype == DataType.int8 and ofm.dtype == DataType.int8) -- or (ifm.dtype == DataType.uint8 and ofm.dtype == DataType.int8) -- or (ifm.dtype == DataType.int8 and ofm.dtype == DataType.uint8) -- ): -- # Create NOP performing the RESCALE -+ # TODO: generate replacement fusion code from below -+ assert False, "Fusion possible but i've not implemented it" -+ else: -+ # Generate Rescale behaviour attached to a compatible NOP -+ # TODO: I assume this attaches a new operator into the graph?? - avgpool_op = replace_rescale_with_avg_pool(op) - avgpool_op.rounding_mode = rounding_mode -- -+ - if per_channel: -- # TODO -- avgpool_op.explicit_scaling = explicit_scaling -- print("Warning, unsupported TOSA Rescale") -- assert False -+ assert False, "Assert above removed but still not implemented... :/" - else: - avgpool_op.explicit_scaling = explicit_scaling -- else: -- print("Warning, unsupported fusing of TOSA Rescale previous operator is of type:", prev_op.type) -- assert False -- return op - -+ #print( len(multiplier), len(shift), len(prev_op.get_bias_tensors()) ) -+ #print( ifm.dtype, "PC:", per_channel, op.type ) -+ #print( ifm.dtype, ofm.dtype ) -+ -+ return op - - def convert_pad_in_width(op): - """ -diff --git a/ethosu/vela/tosa_mapping.py b/ethosu/vela/tosa_mapping.py -index 2dafd81..ed5aa2e 100644 ---- a/ethosu/vela/tosa_mapping.py -+++ b/ethosu/vela/tosa_mapping.py -@@ -148,7 +148,7 @@ transpose_conv_attrs = AttrSerializer( - ) - transpose_attrs = AttrSerializer("TransposeAttribute", (("perms", is_vec),)) - axis_attrs = AttrSerializer("AxisAttribute", ("axis",)) --reshape_attrs = AttrSerializer("ReshapeAttribute", (("shape", is_vec),)) -+reshape_attrs = AttrSerializer("ReshapeAttribute", (("newShape", is_vec),)) - slice_attrs = AttrSerializer("SliceAttribute", (("start", is_vec), ("size", is_vec))) - tile_attrs = AttrSerializer("TileAttribute", (("multiplies", is_vec),)) - resize_attrs = AttrSerializer( --- -2.41.0 - diff --git a/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch b/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch new file mode 120000 index 00000000000..d012bebc0ab --- /dev/null +++ b/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch @@ -0,0 +1 @@ +../../../../../.ci/docker/examples/arm/ethos-u-setup/ethos-u-vela/patches/0001-Improve-rescale-codegen-for-TOSA.patch \ No newline at end of file diff --git a/examples/arm/setup.sh b/examples/arm/setup.sh deleted file mode 100755 index 1094e008e55..00000000000 --- a/examples/arm/setup.sh +++ /dev/null @@ -1,246 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) Meta Platforms, Inc. and affiliates. -# All rights reserved. -# -# This source code is licensed under the BSD-style license found in the -# LICENSE file in the root directory of this source tree. - -set -eu - -if [[ "${1:-'.'}" == "-h" || "${#}" -eq 0 || "${#}" -gt 2 ]]; then - echo "Usage: $(basename $0) <--i-agree-to-the-contained-eula> [path-to-a-scratch-dir]" - echo "Supplied args: $*" - exit 1 -fi - -######## -### Helper functions -######## -function get_os_name() { - # Returns the name of the system i.e. Linux or Darwin - uname -s -} - -function get_cpu_arch() { - # Returns the cpu architecture like arm64 or x86-64 - uname -m -} - -function verify_md5() { - [[ $# -ne 2 ]] \ - && { echo "[${FUNCNAME[0]}] Invalid number of args, expecting 2, but got $#"; exit 1; } - local ref_checksum="${1}" - local file="${2}" - - local file_checksum="$(md5sum $file | awk '{print $1}')" - if [[ ${ref_checksum} != ${file_checksum} ]]; then - echo "Mismatched MD5 checksum for file: ${file}. Expecting ${ref_checksum} but got ${file_checksum}. Exiting." - exit 1 - fi -} - -######## -### Hardcoded constants -######## -script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd) - -if [[ $(get_cpu_arch) == "x86_64" ]]; then - # FVP - fvp_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_20_Linux64.tgz?rev=018659bd574f4e7b95fa647e7836ccf4&hash=22A79103C6FA5FFA7AFF3BE0447F3FF9" - fvp_model_dir="Linux64_GCC-9.3" - fvp_md5_checksum="98e93b949d0fbac977292d8668d34523" - - # toochain - toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi.tar.xz" - toolchain_dir="arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi" - toolchain_md5_checksum="00ebb1b70b1f88906c61206457eacb61" -elif [[ $(get_cpu_arch) == "aarch64" ]]; then - # FVP - fvp_url="https://developer.arm.com/-/media/Arm%20Developer%20Community/Downloads/OSS/FVP/Corstone-300/FVP_Corstone_SSE-300_11.22_20_Linux64_armv8l.tgz?rev=9cc6e9a32bb947ca9b21fa162144cb01&hash=7657A4CF27D42E892E3F08D452AAB073" - fvp_model_dir="Linux64_armv8l_GCC-9.3" - fvp_md5_checksum="cbbabbe39b07939cff7a3738e1492ef1" - - # toochain - toolchain_url="https://armkeil.blob.core.windows.net/developer/Files/downloads/gnu/12.3.rel1/binrel/arm-gnu-toolchain-12.3.rel1-aarch64-arm-none-eabi.tar.xz" - toolchain_dir="arm-gnu-toolchain-12.3.rel1-aarch64-arm-none-eabi" - toolchain_md5_checksum="02c9b0d3bb1110575877d8eee1f223f2" -else - echo "[main] Error: only x86-64 & aarch64 architecture is supported for now!"; exit 1; -fi - -# ethos-u -ethos_u_repo_url="https://review.mlplatform.org/ml/ethos-u/ethos-u" -ethos_u_base_rev="0995223100e3da8011700f58e491f1bf59511e3c" - -######## -### Mandatory user args -######## -eula_acceptance="${1:-'.'}"; shift -if [[ "${eula_acceptance}" != "--i-agree-to-the-contained-eula" ]]; then - echo "Must pass first positional argument '--i-agree-to-the-contained-eula' to agree to EULA associated with downloading the FVP. Exiting!" - exit 1 -fi - -######## -### Optional user args -######## -root_dir=${1:-"${script_dir}/ethos-u-scratch"} -root_dir=$(realpath ${root_dir}) - -######## -### Functions -######## - -function setup_fvp() { - # Download and install the Corstone 300 FVP simulator platform - cd "${root_dir}" - if [[ ! -e FVP_cs300.tgz ]]; then - echo "[${FUNCNAME[0]}] Downloading FVP ..." - curl --output FVP_cs300.tgz "${fvp_url}" - verify_md5 ${fvp_md5_checksum} FVP_cs300.tgz - fi - - echo "[${FUNCNAME[0]}] Installing FVP ..." - rm -rf FVP - mkdir -p FVP - cd FVP - tar xf ../FVP_cs300.tgz - ./FVP_Corstone_SSE-300.sh --i-agree-to-the-contained-eula --force --destination ./ --quiet --no-interactive - - fvp_bin_path="$(cd models/${fvp_model_dir} && pwd)" - export PATH=${PATH}:${fvp_bin_path} - - hash FVP_Corstone_SSE-300_Ethos-U55 - echo "export PATH=\${PATH}:${fvp_bin_path}" >> ${setup_path_script} - -} - -function setup_toolchain() { - # Download and install the arm-none-eabi toolchain - cd "${root_dir}" - if [[ ! -e gcc.tar.xz ]]; then - echo "[${FUNCNAME[0]}] Downloading toolchain ..." - curl --output gcc.tar.xz "${toolchain_url}" - verify_md5 ${toolchain_md5_checksum} gcc.tar.xz - fi - - echo "[${FUNCNAME[0]}] Installing toolchain ..." - rm -rf "${toolchain_dir}" - tar xf gcc.tar.xz - toolchain_bin_path="$(cd ${toolchain_dir}/bin && pwd)" - export PATH=${PATH}:${toolchain_bin_path} - hash arm-none-eabi-gcc - echo "export PATH=\${PATH}:${toolchain_bin_path}" >> ${setup_path_script} -} - -function setup_ethos_u() { - # This is the main dir which will pull more repos to do baremetal software dev for cs300 - echo "[${FUNCNAME[0]}] Setting up the repo" - cd "${root_dir}" - [[ ! -d ethos-u ]] && \ - git clone ${ethos_u_repo_url} - cd ethos-u - git reset --hard ${ethos_u_base_rev} - python3 ./fetch_externals.py fetch - pip install pyelftools - echo "[${FUNCNAME[0]}] Done @ $(git describe --all --long 3> /dev/null) in ${root_dir}/ethos-u dir." -} - -function patch_repo() { - # This is a temporary hack until it finds a better home in one for the ARM Ml repos - name="$(basename $repo_dir)" - echo -e "[${FUNCNAME[0]}] Preparing ${name}..." - cd $repo_dir - - git reset --hard ${base_rev} - - patch_dir=${script_dir}/ethos-u-setup/${name}/patches/ - [[ -e ${patch_dir} && $(ls -A ${patch_dir}) ]] && \ - git am -3 ${patch_dir}/*.patch - - echo -e "[${FUNCNAME[0]}] Patched ${name} @ $(git describe --all --long 2> /dev/null) in ${repo_dir} dir.\n" -} - -function setup_tosa_reference_model() { - # The debug flow on the host includes running on a reference implementation of TOSA - # This is useful primarily for debug of quantization accuracy, but also for internal - # errors for the early codebase - cd "${root_dir}" - if [[ ! -e reference_model ]]; then - git clone https://review.mlplatform.org/tosa/reference_model -b main - cd reference_model - git submodule update --init --recursive - cd .. - fi - cd reference_model - mkdir -p build - cd build - cmake .. - n=$(nproc) - make -j"$((n - 5))" - cd reference_model - tosa_bin_path=`pwd` - echo "export PATH=\${PATH}:${tosa_bin_path}" >> "${setup_path_script}" -} - -function setup_vela() { - # - # Prepare the Vela compiler for AoT to Ethos-U compilation - # - cd "${root_dir}" - if [[ ! -e ethos-u-vela ]]; then - git clone https://review.mlplatform.org/ml/ethos-u/ethos-u-vela - repo_dir="${root_dir}/ethos-u-vela" - base_rev=00a15db3e1a188b25065d095152d701f4394cdc5 - patch_repo - fi - cd "${root_dir}/ethos-u-vela" - pip install . -} - -######## -### main -######## -# do basic checks -# Make sure we are on a supported platform -[[ $(get_cpu_arch) != "x86_64" ]] && [[ $(get_cpu_arch) != "aarch64" ]] \ - && { echo "[main] Error: only x86-64 & aarch64 architecture is supported for now!"; exit 1; } - -# No OSx support for FVP -[[ "$(get_os_name)" != "Linux" ]] \ - && { echo "[main] Error: only Linux os is supported for now!"; exit 1; } - -cd "${script_dir}" - -# Setup the root dir -mkdir -p "${root_dir}" -cd "${root_dir}" -echo "[main] Using root dir ${root_dir}" - -setup_path_script="${root_dir}/setup_path.sh" -echo "" > "${setup_path_script}" - -# Setup FVP -setup_fvp - -# Setup toolchain -setup_toolchain - -# Setup the ethos-u dev environment -setup_ethos_u - -# Patch the ethos-u dev environment to include executorch application -repo_dir="${root_dir}/ethos-u/core_platform" -base_rev=204210b1074071532627da9dc69950d058a809f4 -patch_repo - -# Setup the tosa_reference_model -setup_tosa_reference_model - -# Setup vela and patch in codegen fixes -setup_vela - -echo "[main] update path by doing 'source ${setup_path_script}'" - -echo "[main] success!" -exit 0 diff --git a/examples/arm/setup.sh b/examples/arm/setup.sh new file mode 120000 index 00000000000..7c0e1f91d88 --- /dev/null +++ b/examples/arm/setup.sh @@ -0,0 +1 @@ +../../.ci/docker/examples/arm/setup.sh \ No newline at end of file diff --git a/requirements-lintrunner.txt b/requirements-lintrunner.txt deleted file mode 100644 index e5caf38c59e..00000000000 --- a/requirements-lintrunner.txt +++ /dev/null @@ -1,22 +0,0 @@ -# Lintrunner itself -lintrunner==0.11.0 -lintrunner-adapters==0.11.0 - -# Flake 8 and its dependencies -flake8==6.0.0 -flake8-breakpoint==1.1.0 -flake8-bugbear==23.6.5 -flake8-comprehensions==3.12.0 -flake8-pyi==23.5.0 -mccabe==0.7.0 -pycodestyle==2.10.0 -torchfix==0.1.1 - -# UFMT -black==22.12.0 -ufmt==2.0.1 -usort==1.0.5 - -# Other linters -clang-format==12.0.1 -cmakelint==1.4.1 diff --git a/requirements-lintrunner.txt b/requirements-lintrunner.txt new file mode 120000 index 00000000000..7a05642a591 --- /dev/null +++ b/requirements-lintrunner.txt @@ -0,0 +1 @@ +.ci/docker/requirements-lintrunner.txt \ No newline at end of file