Skip to content

Commit 18c71e8

Browse files
Arm backend: Use cmake for building in Ethos-U jupyter example (#13630)
Building the example application using cmake is now straight forward enough to not need any helper scripts. Additionally simplify the the example + path setup in the executor runner cmake script and make the default path match the example. cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 Signed-off-by: Adrian Lundell <[email protected]>
1 parent 62f8a8e commit 18c71e8

File tree

3 files changed

+48
-46
lines changed

3 files changed

+48
-46
lines changed

backends/arm/scripts/corstone_utils.cmake

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
# LICENSE file in the root directory of this source tree.
55

66
function(fetch_ethos_u_content ETHOS_SDK_PATH ET_DIR_PATH)
7+
message(STATUS "Fetching Ethos-U content into ${ETHOS_SDK_PATH}")
8+
79
file(MAKE_DIRECTORY ${ETHOS_SDK_PATH}/../ethos_u)
810
include(FetchContent)
911
set(ethos_u_base_tag "25.05")
@@ -55,7 +57,6 @@ function(fetch_ethos_u_content ETHOS_SDK_PATH ET_DIR_PATH)
5557
"pwd && source backends/arm/scripts/utils.sh && patch_repo ${ETHOS_SDK_PATH}/core_platform ${core_platform_base_rev} ${patch_dir}"
5658
WORKING_DIRECTORY ${ET_DIR_PATH} COMMAND_ECHO STDOUT
5759
)
58-
5960
endfunction()
6061

6162
function(add_corstone_subdirectory SYSTEM_CONFIG ETHOS_SDK_PATH)

examples/arm/ethos_u_minimal_example.ipynb

Lines changed: 43 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@
1818
"source": [
1919
"# Ethos-U delegate flow example\n",
2020
"\n",
21-
"This guide demonstrates the full flow for running a module on Arm Ethos-U using ExecuTorch. \n",
21+
"This guide demonstrates the full flow for running a module on Arm Ethos-U55 using ExecuTorch.\n",
2222
"Tested on Linux x86_64 and macOS aarch64. If something is not working for you, please raise a GitHub issue and tag Arm.\n",
2323
"\n",
2424
"Before you begin:\n",
2525
"1. (In a clean virtual environment with a compatible Python version) Install executorch using `./install_executorch.sh`\n",
2626
"2. Install Arm cross-compilation toolchain and simulators using `./examples/arm/setup.sh --i-agree-to-the-contained-eula`\n",
27-
"3. Add Arm cross-compilation toolchain and simulators to PATH using `./examples/arm/ethos-u-scratch/setup_path.sh` \n",
2827
"\n",
2928
"With all commands executed from the base `executorch` folder.\n",
3029
"\n",
@@ -70,7 +69,7 @@
7069
"source": [
7170
"To run on Ethos-U the `graph_module` must be quantized using the `arm_quantizer`. Quantization can be done in multiple ways and it can be customized for different parts of the graph; shown here is the recommended path for the EthosUBackend. Quantization also requires calibrating the module with example inputs.\n",
7271
"\n",
73-
"Again printing the module, it can be seen that the quantization wraps the node in quantization/dequantization nodes which contain the computed quanitzation parameters.",
72+
"Again printing the module, it can be seen that the quantization wraps the node in quantization/dequantization nodes which contain the computed quanitzation parameters.\n",
7473
"\n",
7574
"With the default passes for the Arm Ethos-U backend, assuming the model lowers fully to the Ethos-U, the exported program is composed of a Quantize node, Ethos-U custom delegate and a Dequantize node. In some circumstances, you may want to feed quantized input to the Neural Network straight away, e.g. if you have a camera sensor outputting (u)int8 data and keep all the arithmetic of the application in the int8 domain. For these cases, you can apply the `exir/passes/quantize_io_pass.py`. See the unit test in `backends/arm/test/passes/test_ioquantization_pass.py`for an example how to feed quantized inputs and obtain quantized outputs.\n"
7675
]
@@ -88,13 +87,11 @@
8887
")\n",
8988
"from torchao.quantization.pt2e.quantize_pt2e import convert_pt2e, prepare_pt2e\n",
9089
"\n",
91-
"target = \"ethos-u55-128\"\n",
92-
"\n",
9390
"# Create a compilation spec describing the target for configuring the quantizer\n",
9491
"# Some args are used by the Arm Vela graph compiler later in the example. Refer to Arm Vela documentation for an\n",
9592
"# explanation of its flags: https://gitlab.arm.com/artificial-intelligence/ethos-u/ethos-u-vela/-/blob/main/OPTIONS.md\n",
9693
"spec_builder = ArmCompileSpecBuilder().ethosu_compile_spec(\n",
97-
" target,\n",
94+
" target=\"ethos-u55-128\",\n",
9895
" system_config=\"Ethos_U55_High_End_Embedded\",\n",
9996
" memory_mode=\"Shared_Sram\",\n",
10097
" extra_flags=\"--output-format=raw --debug-force-regor\"\n",
@@ -139,7 +136,6 @@
139136
"metadata": {},
140137
"outputs": [],
141138
"source": [
142-
"import os\n",
143139
"from executorch.backends.arm.ethosu import EthosUPartitioner\n",
144140
"from executorch.exir import (\n",
145141
" EdgeCompileConfig,\n",
@@ -165,15 +161,10 @@
165161
" config=ExecutorchBackendConfig(extract_delegate_segments=False)\n",
166162
" )\n",
167163
"\n",
168-
"executorch_program_manager.exported_program().module().print_readable()\n",
164+
"_ = executorch_program_manager.exported_program().module().print_readable()\n",
169165
"\n",
170166
"# Save pte file\n",
171-
"cwd_dir = os.getcwd()\n",
172-
"pte_base_name = \"simple_example\"\n",
173-
"pte_name = pte_base_name + \".pte\"\n",
174-
"pte_path = os.path.join(cwd_dir, pte_name)\n",
175-
"save_pte_program(executorch_program_manager, pte_name)\n",
176-
"assert os.path.exists(pte_path), \"Build failed; no .pte-file found\""
167+
"save_pte_program(executorch_program_manager, \"ethos_u_minimal_example.pte\")"
177168
]
178169
},
179170
{
@@ -183,7 +174,7 @@
183174
"## Build executor runtime\n",
184175
"\n",
185176
"After the AOT compilation flow is done, the runtime can be cross compiled and linked to the produced .pte-file using the Arm cross-compilation toolchain. This is done in two steps:\n",
186-
"1. Build and install the executorch library and EthosUDelegate.\n",
177+
"1. Build and install the executorch libraries and EthosUDelegate.\n",
187178
"2. Build and link the `arm_executor_runner` and generate kernel bindings for any non delegated ops."
188179
]
189180
},
@@ -193,22 +184,37 @@
193184
"metadata": {},
194185
"outputs": [],
195186
"source": [
196-
"import subprocess\n",
197-
"\n",
198-
"# Setup paths\n",
199-
"et_dir = os.path.join(cwd_dir, \"..\", \"..\")\n",
200-
"et_dir = os.path.abspath(et_dir)\n",
201-
"script_dir = os.path.join(et_dir, \"backends\", \"arm\", \"scripts\")\n",
202-
"\n",
203-
"# Cross-compile executorch \n",
204-
"subprocess.run(os.path.join(script_dir, \"build_executorch.sh\"), shell=True, cwd=et_dir)\n",
205-
"\n",
206-
"# Cross-compile executorch runner\n",
207-
"args = f\"--pte={pte_path} --target={target}\"\n",
208-
"subprocess.run(os.path.join(script_dir, \"build_executor_runner.sh\") + \" \" + args, shell=True, cwd=et_dir)\n",
209-
"\n",
210-
"elf_path = os.path.join(cwd_dir, pte_base_name, \"cmake-out\", \"arm_executor_runner\")\n",
211-
"assert os.path.exists(elf_path), \"Build failed; no .elf-file found\""
187+
"%%bash\n",
188+
"# Ensure the arm-none-eabi-gcc toolchain and FVP:s are available on $PATH\n",
189+
"source ethos-u-scratch/setup_path.sh\n",
190+
"\n",
191+
"# Build executorch libraries cross-compiled for arm baremetal to executorch/cmake-out-arm\n",
192+
"cmake --preset arm-baremetal \\\n",
193+
"-DCMAKE_BUILD_TYPE=Release \\\n",
194+
"-B../../cmake-out-arm ../..\n",
195+
"cmake --build ../../cmake-out-arm --target install -j$(nproc) "
196+
]
197+
},
198+
{
199+
"cell_type": "code",
200+
"execution_count": null,
201+
"metadata": {},
202+
"outputs": [],
203+
"source": [
204+
"%%bash \n",
205+
"source ethos-u-scratch/setup_path.sh\n",
206+
"\n",
207+
"# Build example executor runner application to examples/arm/ethos_u_minimal_example\n",
208+
"cmake -DCMAKE_TOOLCHAIN_FILE=$(pwd)/ethos-u-setup/arm-none-eabi-gcc.cmake \\\n",
209+
" -DCMAKE_BUILD_TYPE=Release \\\n",
210+
" -DET_PTE_FILE_PATH=ethos_u_minimal_example.pte \\\n",
211+
" -DTARGET_CPU=cortex-m55 \\\n",
212+
" -DETHOSU_TARGET_NPU_CONFIG=ethos-u55-128 \\\n",
213+
" -DMEMORY_MODE=Shared_Sram \\\n",
214+
" -DSYSTEM_CONFIG=Ethos_U55_High_End_Embedded \\\n",
215+
" -Bethos_u_minimal_example \\\n",
216+
" executor_runner\n",
217+
"cmake --build ethos_u_minimal_example -j$(nproc) -- arm_executor_runner"
212218
]
213219
},
214220
{
@@ -217,7 +223,7 @@
217223
"source": [
218224
"# Run on simulated model\n",
219225
"\n",
220-
"We can finally use the `backends/arm/scripts/run_fvp.sh` utility script to run the .elf-file on simulated Arm hardware. This Script runs the model with an input of ones, so the expected result of the addition should be close to 2."
226+
"We can finally use the `backends/arm/scripts/run_fvp.sh` utility script to run the .elf-file on simulated Arm hardware. The example application is by default built with an input of ones, so the expected result of the quantized addition should be close to 2."
221227
]
222228
},
223229
{
@@ -226,8 +232,11 @@
226232
"metadata": {},
227233
"outputs": [],
228234
"source": [
229-
"args = f\"--elf={elf_path} --target={target}\"\n",
230-
"subprocess.run(os.path.join(script_dir, \"run_fvp.sh\") + \" \" + args, shell=True, cwd=et_dir)"
235+
"%%bash \n",
236+
"source ethos-u-scratch/setup_path.sh\n",
237+
"\n",
238+
"# Run the example\n",
239+
"../../backends/arm/scripts/run_fvp.sh --elf=ethos_u_minimal_example/arm_executor_runner --target=ethos-u55-128"
231240
]
232241
}
233242
],

examples/arm/executor_runner/CMakeLists.txt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ endif()
3535

3636
# Example ExecuTorch demo for bare metal Cortex-M based systems
3737
set(ET_DIR_PATH
38-
"../../.."
38+
"${CMAKE_CURRENT_SOURCE_DIR}/../../.."
3939
CACHE PATH "Path to ExecuTorch dir"
4040
)
4141
set(ET_BUILD_DIR_PATH
42-
"${ET_DIR_PATH}/cmake-out"
43-
CACHE PATH "Path to ExecuTorch build dir"
42+
"${ET_DIR_PATH}/cmake-out-arm"
43+
CACHE PATH "Path to ExecuTorch build/install dir"
4444
)
4545
set(ET_INCLUDE_PATH
4646
"${ET_DIR_PATH}/.."
@@ -83,14 +83,6 @@ message(STATUS "SYSTEM_CONFIG is ${SYSTEM_CONFIG}")
8383
message(STATUS "MEMORY_MODE is ${MEMORY_MODE}")
8484
message(STATUS "ET_NUM_INFERENCES is ${ET_NUM_INFERENCES}")
8585

86-
get_filename_component(ET_BUILD_DIR_PATH ${ET_BUILD_DIR_PATH} REALPATH)
87-
get_filename_component(ET_DIR_PATH ${ET_DIR_PATH} REALPATH)
88-
get_filename_component(ET_INCLUDE_PATH ${ET_INCLUDE_PATH} REALPATH)
89-
get_filename_component(ETHOS_SDK_PATH ${ETHOS_SDK_PATH} REALPATH)
90-
if(NOT ${SEMIHOSTING})
91-
get_filename_component(ET_PTE_FILE_PATH ${ET_PTE_FILE_PATH} REALPATH)
92-
endif()
93-
9486
# By default, use 2MB of temporary scratch buffer For Dedicated_Sram, use 64MB
9587
# for the temporary scratch buffer and 384KB for the fast scratch buffer(the
9688
# cache, applicable only for Ethos-U65 and Ethos-U85)

0 commit comments

Comments
 (0)