Skip to content

Commit b71926f

Browse files
zingofacebook-github-bot
authored andcommitted
Arm backend: Add options when using run.sh (pytorch#5627)
Summary: This will enable you to build for different target, specify models from the command line and also control output folder used. Pull Request resolved: pytorch#5627 Reviewed By: digantdesai Differential Revision: D63637343 Pulled By: mergennachin fbshipit-source-id: cec5830b0a6a406cd72b7a2fecf3ff229fa2d359
1 parent 77e7ad1 commit b71926f

File tree

4 files changed

+144
-53
lines changed

4 files changed

+144
-53
lines changed

examples/arm/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ $ ./setup.sh --i-agree-to-the-contained-eula [optional-scratch-dir]
2525
2626
# Step [2] - build + run ExecuTorch and executor_runner baremetal application
2727
# suited for Corstone300 to run a simple PyTorch model.
28-
$ ./run.sh [same-optional-scratch-dir-as-before]
28+
$ ./run.sh [--scratch-dir=same-optional-scratch-dir-as-before]
2929
```
3030
### Online Tutorial
3131

examples/arm/aot_arm_compiler.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,15 @@ def forward(self, x):
148148
}
149149

150150
targets = [
151-
"ethos-u85-128",
151+
"ethos-u55-32",
152+
"ethos-u55-64",
152153
"ethos-u55-128",
154+
"ethos-u55-256",
155+
"ethos-u85-128",
156+
"ethos-u85-256",
157+
"ethos-u85-512",
158+
"ethos-u85-1024",
159+
"ethos-u85-2048",
153160
"TOSA",
154161
]
155162

@@ -160,23 +167,23 @@ def get_compile_spec(target: str, intermediates: bool) -> ArmCompileSpecBuilder:
160167
spec_builder = (
161168
ArmCompileSpecBuilder().tosa_compile_spec().set_permute_memory_format(True)
162169
)
163-
elif target == "ethos-u55-128":
170+
elif "ethos-u55" in target:
164171
spec_builder = (
165172
ArmCompileSpecBuilder()
166173
.ethosu_compile_spec(
167-
"ethos-u55-128",
174+
target,
168175
system_config="Ethos_U55_High_End_Embedded",
169176
memory_mode="Shared_Sram",
170177
extra_flags="--debug-force-regor --output-format=raw",
171178
)
172179
.set_permute_memory_format(args.model_name in MODEL_NAME_TO_MODEL.keys())
173180
.set_quantize_io(True)
174181
)
175-
elif target == "ethos-u85-128":
182+
elif "ethos-u85" in target:
176183
spec_builder = (
177184
ArmCompileSpecBuilder()
178185
.ethosu_compile_spec(
179-
"ethos-u85-128",
186+
target,
180187
system_config="Ethos_U85_SYS_DRAM_Mid",
181188
memory_mode="Shared_Sram",
182189
extra_flags="--output-format=raw",
@@ -323,7 +330,9 @@ def get_args():
323330

324331
model_name = os.path.basename(os.path.splitext(args.model_name)[0])
325332
output_name = f"{model_name}" + (
326-
f"_arm_delegate_{args.target}" if args.delegate is True else ""
333+
f"_arm_delegate_{args.target}"
334+
if args.delegate is True
335+
else f"_arm_{args.target}"
327336
)
328337

329338
if args.output is not None:

examples/arm/executor_runner/arm_perf_monitor.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,20 @@ void ethosu_inference_begin(struct ethosu_driver* drv, void*) {
3939
ETHOSU_PMU_PMCCNTR_CFG_Set_Start_Event(drv, ETHOSU_PMU_NPU_ACTIVE);
4040

4141
// Setup 4 counters
42+
#if defined(ETHOSU55) || defined(ETHOSU65)
4243
ETHOSU_PMU_Set_EVTYPER(drv, 0, ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED);
4344
ETHOSU_PMU_Set_EVTYPER(drv, 1, ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED);
4445
ETHOSU_PMU_Set_EVTYPER(drv, 2, ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN);
4546
ETHOSU_PMU_Set_EVTYPER(drv, 3, ETHOSU_PMU_NPU_IDLE);
47+
#elif defined(ETHOSU85)
48+
ETHOSU_PMU_Set_EVTYPER(drv, 0, ETHOSU_PMU_EXT0_RD_DATA_BEAT_RECEIVED);
49+
ETHOSU_PMU_Set_EVTYPER(drv, 1, ETHOSU_PMU_EXT1_RD_DATA_BEAT_RECEIVED);
50+
ETHOSU_PMU_Set_EVTYPER(drv, 2, ETHOSU_PMU_EXT0_WR_DATA_BEAT_WRITTEN);
51+
ETHOSU_PMU_Set_EVTYPER(drv, 3, ETHOSU_PMU_NPU_IDLE);
52+
#else
53+
#error No NPU target defined
54+
#endif
55+
4656
// Enable 4 counters
4757
ETHOSU_PMU_CNTR_Enable(drv, 0xf);
4858

@@ -160,9 +170,17 @@ void StopMeasurements() {
160170
for (size_t i = 0; i < ethosu_pmuCountersUsed; i++) {
161171
ET_LOG(Info, "ethosu_pmu_cntr%zd : %" PRIu64, i, ethosu_pmuEventCounts[i]);
162172
}
173+
#if defined(ETHOSU55) || defined(ETHOSU65)
163174
ET_LOG(
164175
Info,
165176
"Ethos-U PMU Events:[ETHOSU_PMU_AXI0_RD_DATA_BEAT_RECEIVED, ETHOSU_PMU_AXI1_RD_DATA_BEAT_RECEIVED, ETHOSU_PMU_AXI0_WR_DATA_BEAT_WRITTEN, ETHOSU_PMU_NPU_IDLE]");
177+
#elif defined(ETHOSU85)
178+
ET_LOG(
179+
Info,
180+
"Ethos-U PMU Events:[ETHOSU_PMU_EXT0_RD_DATA_BEAT_RECEIVED, ETHOSU_PMU_EXT1_RD_DATA_BEAT_RECEIVED, ETHOSU_PMU_EXT0_WR_DATA_BEAT_WRITTEN, ETHOSU_PMU_NPU_IDLE]");
181+
#else
182+
#error No NPU target defined
183+
#endif
166184
}
167185

168186
#else

examples/arm/run.sh

Lines changed: 110 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,58 @@
99

1010
set -eu
1111

12-
if [[ "${1:-'.'}" == "-h" || "${#}" -gt 2 ]]; then
13-
echo "Usage: $(basename $0) [path-to-a-scratch-dir]"
14-
echo "Supplied args: $*"
15-
exit 1
16-
fi
12+
1713

1814
########
1915
### Hardcoded constants
2016
########
2117
script_dir=$(cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd)
2218

23-
# Ethos-u
24-
root_dir=${1:-"${script_dir}/ethos-u-scratch"}
19+
# Default Ethos-u tool folder override with --scratch-dir=<FOLDER>
20+
root_dir=${script_dir}/ethos-u-scratch
21+
22+
model_name=""
23+
aot_arm_compiler_flags="--delegate --quantize"
24+
target="ethos-u55-128"
25+
output_folder_set=false
26+
output_folder="."
27+
build_only=false
28+
29+
help() {
30+
echo "Usage: $(basename $0) [options]"
31+
echo "Options:"
32+
echo " --model_name=<MODEL> Model to run, can be a builtin, examples/models or a filename Default to all builtin models"
33+
echo " --aot_arm_compiler_flags=<FLAGS> Only used if --model_name is used Default: ${aot_arm_compiler_flags}"
34+
echo " --target=<TARGET> Target to build and run for Default: ${target}"
35+
echo " --output=<FOLDER> Output folder Default: ${output_folder}"
36+
echo " --build_only Only build, don't run FVP"
37+
echo " --scratch-dir=<FOLDER> Path to your Ethos-U scrach dir if you not using default"
38+
exit 0
39+
}
40+
41+
for arg in "$@"; do
42+
case $arg in
43+
-h|--help) help ;;
44+
--model_name=*) model_name="${arg#*=}";;
45+
--aot_arm_compiler_flags=*) aot_arm_compiler_flags="${arg#*=}";;
46+
--target=*) target="${arg#*=}";;
47+
--output=*) output_folder="${arg#*=}" ; output_folder_set=true ;;
48+
--build_only) build_only=true ;;
49+
--scratch-dir=*) root_dir="${arg#*=}";;
50+
*)
51+
;;
52+
esac
53+
done
54+
2555
root_dir=$(realpath ${root_dir})
56+
output_folder=$(realpath ${output_folder})
57+
mkdir -p ${output_folder}
58+
if [ "$output_folder_set" = true ] ; then
59+
executor_runner_path=${output_folder}
60+
else
61+
executor_runner_path=${script_dir}/executor_runner
62+
fi
63+
executor_runner_path=$(realpath ${executor_runner_path})
2664

2765
ethos_u_root_dir="$(cd ${root_dir}/ethos-u && pwd)"
2866
ethos_u_build_dir=${ethos_u_root_dir}/core_platform/build
@@ -38,26 +76,26 @@ _setup_msg="please refer to ${script_dir}/ethos-u-setup/setup.sh to properly ins
3876

3977
# Generate a pte file
4078
function generate_pte_file() {
41-
[[ $# -ne 2 ]] && { echo "[${FUNCNAME[0]}]" "Expecting model and delegate flag, got, $*"; exit 1; }
79+
[[ $# -ne 2 ]] && { echo "[${FUNCNAME[0]}]" "Expecting model and model_compiler_flags flag, got, $*"; exit 1; }
4280
local model=${1}
43-
local delegate=${2}
81+
local model_compiler_flags=${2}
4482

45-
local model_filename=${model}.pte
46-
if [[ "${delegate}" == *"--delegate"* ]]; then
83+
local model_filename=${model}_arm_${target}.pte
84+
if [[ "${model_compiler_flags}" == *"--delegate"* ]]; then
4785
# Name aligned with default aot_arm_compiler output - run.sh only supports
4886
# running on Corstone-300 with Ethos-U55 FVP at the moment.
49-
model_filename=${model}_arm_delegate_ethos-u55-128.pte
87+
model_filename=${model}_arm_delegate_${target}.pte
5088
fi
5189
cd $et_root_dir
5290

5391
local pte_file
54-
pte_file=$(realpath ${model_filename})
92+
pte_file=$(realpath ${output_folder}/${model_filename})
5593
rm -f "${pte_file}"
5694

5795
# We are using the aot_lib from build_quantization_aot_lib below
5896
SO_LIB=$(find cmake-out-aot-lib -name libquantized_ops_aot_lib.so)
5997

60-
python3 -m examples.arm.aot_arm_compiler --model_name="${model}" ${delegate} --so_library="$SO_LIB" 1>&2
98+
python3 -m examples.arm.aot_arm_compiler --model_name="${model}" --target=${target} ${model_compiler_flags} --output ${output_folder} --so_library="$SO_LIB" 1>&2
6199
[[ -f ${pte_file} ]] || { >&2 echo "Failed to generate a pte file - ${pte_file}"; exit 1; }
62100
echo "${pte_file}"
63101
}
@@ -100,7 +138,7 @@ function build_executorch() {
100138
-DCMAKE_BUILD_TYPE=Release \
101139
-DEXECUTORCH_ENABLE_LOGGING=ON \
102140
-DEXECUTORCH_BUILD_ARM_BAREMETAL=ON \
103-
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
141+
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
104142
-DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \
105143
-DFLATC_EXECUTABLE="$(which flatc)" \
106144
-DCMAKE_TOOLCHAIN_FILE="${toolchain_cmake}" \
@@ -134,43 +172,55 @@ function build_executorch_runner() {
134172
echo "[${FUNCNAME[0]}] Generating ExecuTorch libraries"
135173
[[ $# -ne 1 ]] && { echo "[${FUNCNAME[0]}]" "Expecting a single pte file as argument got, $*"; exit 1; }
136174
local pte=${1}
175+
if [[ ${target} == *"ethos-u55"* ]]; then
176+
local target_cpu=cortex-m55
177+
else
178+
local target_cpu=cortex-m85
179+
fi
137180
cd ${script_dir}/executor_runner
138181
cmake -DCMAKE_TOOLCHAIN_FILE=${toolchain_cmake} \
139-
-DTARGET_CPU=cortex-m55 \
140-
-B cmake-out \
141-
-DETHOS_SDK_PATH:PATH=${ethos_u_root_dir} \
142-
-DET_DIR_PATH:PATH=${et_root_dir} \
143-
-DET_BUILD_DIR_PATH:PATH=${et_build_dir} \
144-
-DET_PTE_FILE_PATH:PATH="${pte}" \
182+
-DTARGET_CPU=${target_cpu} \
183+
-DETHOSU_TARGET_NPU_CONFIG=${target} \
184+
-B ${executor_runner_path}/cmake-out \
185+
-DETHOS_SDK_PATH:PATH=${ethos_u_root_dir} \
186+
-DET_DIR_PATH:PATH=${et_root_dir} \
187+
-DET_BUILD_DIR_PATH:PATH=${et_build_dir} \
188+
-DET_PTE_FILE_PATH:PATH="${pte}" \
145189
-DPYTHON_EXECUTABLE=$(which python3)
146190
echo "[${FUNCNAME[0]}] Configured CMAKE"
147191

148192
n=$(nproc)
149-
cmake --build cmake-out -- -j"$((n - 5))" arm_executor_runner
193+
cmake --build ${executor_runner_path}/cmake-out -- -j"$((n - 5))" arm_executor_runner
150194
echo "[${FUNCNAME[0]}] Generated baremetal elf file:"
151-
find cmake-out -name "arm_executor_runner"
152-
echo "executable_text: $(find -name arm_executor_runner -exec size {} \; | grep -v filename | awk '{print $1}') bytes"
153-
echo "executable_data: $(find -name arm_executor_runner -exec size {} \; | grep -v filename | awk '{print $2}') bytes"
154-
echo "executable_bss: $(find -name arm_executor_runner -exec size {} \; | grep -v filename | awk '{print $3}') bytes"
155-
echo "pte_data_size: $(stat -c%s ${pte}) bytes"
195+
find ${executor_runner_path}/cmake-out -name "arm_executor_runner"
196+
echo "executable_text: $(find ${executor_runner_path}/cmake-out -name arm_executor_runner -exec size {} \; | grep -v filename | awk '{print $1}') bytes"
197+
echo "executable_data: $(find ${executor_runner_path}/cmake-out -name arm_executor_runner -exec size {} \; | grep -v filename | awk '{print $2}') bytes"
198+
echo "executable_bss: $(find ${executor_runner_path}/cmake-out -name arm_executor_runner -exec size {} \; | grep -v filename | awk '{print $3}') bytes"
156199
}
157200

158201
# Execute the executor_runner on FVP Simulator
159202
function run_fvp() {
160203
[[ $# -ne 1 ]] && { echo "[${FUNCNAME[0]}]" "Expexted elf binary name, got $*"; exit 1; }
161204
local elf_name=${1}
162-
elf=$(find ${script_dir}/executor_runner -name "${elf_name}")
205+
elf=$(find ${executor_runner_path} -name "${elf_name}")
163206
[[ ! -f $elf ]] && { echo "[${FUNCNAME[0]}]: Unable to find executor_runner elf: ${elf}"; exit 1; }
164-
FVP_Corstone_SSE-300_Ethos-U55 \
165-
-C cpu0.CFGITCMSZ=11 \
166-
-C ethosu.num_macs=128 \
167-
-C mps3_board.visualisation.disable-visualisation=1 \
168-
-C mps3_board.telnetterminal0.start_telnet=0 \
169-
-C mps3_board.uart0.out_file='-' \
170-
-C mps3_board.uart0.shutdown_on_eot=1 \
171-
-a "${elf}" \
172-
--timelimit 120 || true # seconds
173-
echo "[${FUNCNAME[0]} Simulation complete, $?"
207+
num_macs=$(echo ${target} | cut -d - -f 3)
208+
if [[ ${target} == *"ethos-u55"* ]]; then
209+
echo "Running ${elf} for ${target} run with FVP_Corstone_SSE-300_Ethos-U55 num_macs:${num_macs}"
210+
FVP_Corstone_SSE-300_Ethos-U55 \
211+
-C cpu0.CFGITCMSZ=11 \
212+
-C ethosu.num_macs=${num_macs} \
213+
-C mps3_board.visualisation.disable-visualisation=1 \
214+
-C mps3_board.telnetterminal0.start_telnet=0 \
215+
-C mps3_board.uart0.out_file='-' \
216+
-C mps3_board.uart0.shutdown_on_eot=1 \
217+
-a "${elf}" \
218+
--timelimit 120 || true # seconds
219+
echo "[${FUNCNAME[0]} Simulation complete, $?"
220+
else
221+
echo "Running ${elf} for ${target} is not supported"
222+
exit 1
223+
fi
174224
}
175225

176226
#######
@@ -199,17 +249,31 @@ hash arm-none-eabi-gcc \
199249
build_executorch
200250
build_quantization_aot_lib
201251

202-
# the test models run, and whether to delegate
203-
test_model=( "softmax" "add" "add3" "mv2" )
204-
test_delegate=( "" "--delegate" "--delegate" "--delegate --quantize" )
252+
if [[ -z "$model_name" ]]; then
253+
# the test models run, and whether to delegate
254+
test_model=( "softmax" "add" "add3" "mv2" )
255+
model_compiler_flags=( "" "--delegate" "--delegate" "--delegate --quantize" )
256+
else
257+
test_model=( "$model_name" )
258+
model_compiler_flags=( "$aot_arm_compiler_flags" )
259+
fi
205260

206261
# loop over running the AoT flow and executing the model on device
207262
for i in "${!test_model[@]}"; do
208-
printf "Running e2e flow for model '%s' with flags '%s'\n" "${test_model[i]}" "${test_delegate[i]}"
209-
pte=$(generate_pte_file "${test_model[i]}" "${test_delegate[i]}")
210-
# Rebuild the application as the pte is imported as a header/c array
211-
build_executorch_runner "${pte}"
212-
run_fvp arm_executor_runner
263+
echo "--------------------------------------------------------------------------------"
264+
printf "Running e2e flow for model '%s' with flags '%s'\n" "${test_model[i]}" "${model_compiler_flags[i]}"
265+
echo "--------------------------------------------------------------------------------"
266+
pte=$(generate_pte_file "${test_model[i]}" "${model_compiler_flags[i]}")
267+
stat --printf="Generated pte_data_size: %s bytes\npte_file:%n\n" ${pte}
268+
if [[ ${target} == *"TOSA"* ]]; then
269+
echo "Build for ${target} skip generating .elf and running"
270+
else
271+
# Rebuild the application as the pte is imported as a header/c array
272+
build_executorch_runner "${pte}"
273+
if [ "$build_only" = false ] ; then
274+
run_fvp arm_executor_runner
275+
fi
276+
fi
213277
done
214278

215279
exit 0

0 commit comments

Comments
 (0)