@@ -9,21 +9,45 @@ set -euo pipefail
99
1010et_root=$( cd " $( dirname " ${BASH_SOURCE[0]} " ) /../.." && pwd)
1111build_dir=" ${ESPRESSIF_BUILD_DIR:- ${et_root} / cmake-out-esp-emulator} "
12+ espnn_kernels=" ${ESPRESSIF_NN_KERNELS:- optimized} "
13+ case " ${espnn_kernels} " in
14+ optimized) espnn_config=CONFIG_NN_OPTIMIZED ;;
15+ ansi) espnn_config=CONFIG_NN_ANSI_C ;;
16+ * ) echo " ESPRESSIF_NN_KERNELS must be optimized or ansi" >&2 ; exit 1 ;;
17+ esac
1218export ESPRESSIF_TOOLS_DIR=" ${ESPRESSIF_TOOLS_DIR:- ${RUNNER_TEMP:-/ tmp} / executorch-espressif} "
1319mkdir -p " ${build_dir} "
1420build_dir=$( cd " ${build_dir} " && pwd)
1521cd " ${et_root} "
1622
1723collect_artifacts () {
24+ local file operator_dir artifact_dir
1825 if [[ -n " ${RUNNER_ARTIFACT_DIR:- } " ]]; then
1926 mkdir -p " ${RUNNER_ARTIFACT_DIR} /esp32s3"
2027 for file in " ${build_dir} " /* .log " ${build_dir} " /* .bpte \
28+ " ${build_dir} " /espnn-* -sdkconfig \
29+ " ${build_dir} /espnn-tests" /* .bpte \
30+ " ${build_dir} /espnn-tests/manifest.json" \
31+ " ${build_dir} /espnn-tests/operators.txt" \
32+ " ${et_root} /examples/espressif/project/dependencies.lock" \
2133 " ${build_dir} /firmware/merged-binary.bin" \
2234 " ${build_dir} /firmware/executorch_esp_runner.elf" ; do
2335 if [[ -f " ${file} " ]]; then
2436 cp " ${file} " " ${RUNNER_ARTIFACT_DIR} /esp32s3/"
2537 fi
2638 done
39+ for operator_dir in " ${build_dir} " /operator-library-* ; do
40+ [[ -d " ${operator_dir} " ]] || continue
41+ artifact_dir=" ${RUNNER_ARTIFACT_DIR} /esp32s3/${operator_dir##*/ } "
42+ mkdir -p " ${artifact_dir} "
43+ for file in " ${operator_dir} " /* .log " ${operator_dir} " /* .bpte \
44+ " ${operator_dir} /sdkconfig" " ${operator_dir} " /* .elf \
45+ " ${operator_dir} /merged-binary.bin" ; do
46+ if [[ -f " ${file} " ]]; then
47+ cp " ${file} " " ${artifact_dir} /"
48+ fi
49+ done
50+ done
2751 fi
2852}
2953trap collect_artifacts EXIT
@@ -34,13 +58,27 @@ source "${ESPRESSIF_TOOLS_DIR}/setup_path.sh"
3458
3559python examples/espressif/export_smoke_model.py \
3660 --output " ${build_dir} /smoke.bpte" 2>&1 | tee " ${build_dir} /export.log"
61+ python examples/espressif/export_espnn_test_programs.py \
62+ --output-dir " ${build_dir} /espnn-tests" 2>&1 | tee " ${build_dir} /espnn-export.log"
63+
64+ # One runtime serves the smoke test and the ESP-NN programs. quantized_ops_lib
65+ # registers kernels outside the selected list, so the registry is sized
66+ # explicitly instead of from the list. The quantized kernels' parallel_for
67+ # runs inline without pthreadpool, which needs POSIX calls ESP-IDF lacks.
68+ espnn_ops=$( tr -d ' \n' < " ${build_dir} /espnn-tests/operators.txt" \
69+ | tr ' ,' ' \n' | grep -v ' ^quantized_decomposed::' | paste -sd, -)
70+ if [[ " ${espnn_kernels} " == optimized ]]; then
71+ espnn_ops=" ${espnn_ops} ,aten::sin.out"
72+ fi
3773
3874cmake --preset esp-baremetal -G Ninja -B " ${build_dir} /runtime" \
3975 -DCMAKE_TOOLCHAIN_FILE=" ${IDF_PATH} /tools/cmake/toolchain-esp32s3.cmake" \
4076 -DCMAKE_BUILD_TYPE=Release \
4177 -DEXECUTORCH_BUILD_DEVTOOLS=ON \
42- -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=OFF \
43- -DEXECUTORCH_SELECT_OPS_LIST=aten::add.out,aten::mul.out \
78+ -DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
79+ -DEXECUTORCH_SELECT_OPS_LIST=" aten::add.out,aten::mul.out,${espnn_ops} " \
80+ -DMAX_KERNEL_NUM=256 \
81+ -DEXECUTORCH_BUILD_PTHREADPOOL=OFF -DEXECUTORCH_BUILD_CPUINFO=OFF \
4482 2>&1 | tee " ${build_dir} /runtime-configure.log"
4583cmake --build " ${build_dir} /runtime" \
4684 2>&1 | tee " ${build_dir} /runtime-build.log"
@@ -66,3 +104,64 @@ timeout 130s esp-emu --chip esp32s3 \
66104 --net user --psram-size 8M --timeout 120s --exit-on ' Program complete.' \
67105 2>&1 | tee " ${build_dir} /emulator.log"
68106python examples/espressif/test_emulator.py " ${build_dir} /emulator.log"
107+
108+ # ESP-NN backend: run every exported program through the ExecuTorch runtime
109+ # and the ESP-NN delegate, and check it against the bundled host reference.
110+ espnn_firmware_dir=" ${build_dir} /espnn-${espnn_kernels} -firmware"
111+ espnn_sdkconfig=" ${build_dir} /espnn-${espnn_kernels} -sdkconfig"
112+ espnn_defaults=" ${build_dir} /espnn-${espnn_kernels} .defaults"
113+ printf ' %s=y\n' " ${espnn_config} " > " ${espnn_defaults} "
114+ # Runs a command with its output in a log, and shows the log's tail on failure.
115+ logged () {
116+ local log=" ${build_dir} /$1 "
117+ shift
118+ if ! " $@ " > " ${log} " 2>&1 ; then
119+ tail -n 60 " ${log} "
120+ echo " FAIL: see ${log} " >&2
121+ return 1
122+ fi
123+ }
124+ while read -r -u 3 name atol rtol; do
125+ espnn_log_prefix=" espnn-${espnn_kernels} -${name} "
126+ logged " ${espnn_log_prefix} -configure.log" \
127+ idf.py -C examples/espressif/project -B " ${espnn_firmware_dir} " \
128+ -DIDF_TARGET=esp32s3 \
129+ -DSDKCONFIG=" ${espnn_sdkconfig} " \
130+ " -DSDKCONFIG_DEFAULTS=sdkconfig.defaults;${espnn_defaults} " \
131+ -DET_ESPNN_BACKEND=ON \
132+ -DET_BUILD_DIR_PATH=" ${build_dir} /runtime" \
133+ -DET_PTE_FILE_PATH=" ${build_dir} /espnn-tests/${name} .bpte" \
134+ -DET_BUNDLE_IO=ON -DET_NUM_INFERENCES=1 \
135+ -DET_ATOL=" ${atol} " -DET_RTOL=" ${rtol} " reconfigure
136+ if ! grep -qx " ${espnn_config} =y" " ${espnn_sdkconfig} " ; then
137+ echo " Expected ${espnn_config} =y in ${espnn_sdkconfig} " >&2
138+ exit 1
139+ fi
140+ logged " ${espnn_log_prefix} -build.log" cmake --build " ${espnn_firmware_dir} "
141+ logged " ${espnn_log_prefix} -merge.log" \
142+ idf.py -C examples/espressif/project -B " ${espnn_firmware_dir} " merge-bin
143+ logged " ${espnn_log_prefix} -emulator.log" \
144+ timeout 90s esp-emu --chip esp32s3 \
145+ --firmware " ${espnn_firmware_dir} /merged-binary.bin" \
146+ --elf " ${espnn_firmware_dir} /executorch_esp_runner.elf" \
147+ --net user --psram-size 8M --timeout 60s --exit-on ' Program complete.'
148+ echo -n " ${espnn_kernels} /${name} : "
149+ python examples/espressif/test_emulator.py " ${build_dir} /${espnn_log_prefix} -emulator.log"
150+ done 3< <( python -c '
151+ import json, sys
152+ for entry in json.load(open(sys.argv[1])):
153+ print(entry["name"], entry["atol"], entry["rtol"])
154+ ' " ${build_dir} /espnn-tests/manifest.json" )
155+
156+ if [[ " ${espnn_kernels} " == optimized ]]; then
157+ # Stop on failure so later cases cannot overwrite its firmware and logs.
158+ ESPRESSIF_BUILD_DIR=" ${build_dir} " python -m pytest \
159+ -x -v --tb=short backends/espressif/test/ops -k implementation \
160+ 2>&1 | tee " ${build_dir} /operator-library-tests.log"
161+ for sdkconfig in " ${build_dir} " /operator-library-* /sdkconfig; do
162+ if ! grep -qx ' CONFIG_NN_OPTIMIZED=y' " ${sdkconfig} " ; then
163+ echo " Expected CONFIG_NN_OPTIMIZED=y in ${sdkconfig} " >&2
164+ exit 1
165+ fi
166+ done
167+ fi
0 commit comments