Skip to content

Commit ddc5e7d

Browse files
authored
[cadence] Add PR-triggered hifi op-test stage on the Xtensa ISS
Differential Revision: D110457351 Pull Request resolved: pytorch#20682
1 parent 769b0cf commit ddc5e7d

5 files changed

Lines changed: 280 additions & 0 deletions

File tree

.ci/scripts/test-cadence-xtensa.sh

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
#
8+
# Build the Cadence Xtensa op-level gtest tests for the configured backend and
9+
# run them on the Instruction Set Simulator (xt-run).
10+
#
11+
# Requires the Xtensa toolchain env to already be set (run
12+
# .ci/scripts/setup-xtensa-tools.sh <backend> first): XTENSA_TOOLCHAIN,
13+
# TOOLCHAIN_VER, XTENSA_CORE, CADENCE_OPT_FLAG, and xt-clang/xt-run on PATH.
14+
#
15+
# Unlike build-cadence-xtensa.sh (the runner, built -fno-exceptions -fno-rtti),
16+
# the gtest tests need exceptions + RTTI, so those flags are NOT set here.
17+
18+
set -euo pipefail
19+
20+
: "${XTENSA_TOOLCHAIN:?run setup-xtensa-tools.sh first}"
21+
: "${TOOLCHAIN_VER:?run setup-xtensa-tools.sh first}"
22+
: "${XTENSA_CORE:?run setup-xtensa-tools.sh first}"
23+
: "${CADENCE_OPT_FLAG:?run setup-xtensa-tools.sh first}"
24+
25+
# Map the optimized-kernel flag to the backend dir + gtest target name.
26+
case "${CADENCE_OPT_FLAG}" in
27+
EXECUTORCH_NNLIB_OPT) TARGET_DIR=hifi ;;
28+
EXECUTORCH_VISION_OPT) TARGET_DIR=vision ;;
29+
EXECUTORCH_FUSION_G3_OPT) TARGET_DIR=fusion_g3 ;;
30+
*)
31+
echo "ERROR: unknown CADENCE_OPT_FLAG='${CADENCE_OPT_FLAG}'" >&2
32+
exit 1
33+
;;
34+
esac
35+
TEST_TARGET="cadence_${TARGET_DIR}_op_tests"
36+
TEST_ELF="cmake-out/backends/cadence/${TARGET_DIR}/operators/tests/${TEST_TARGET}"
37+
38+
NPROC=$(nproc)
39+
echo "=== building ${TEST_TARGET} for ${XTENSA_CORE} (${CADENCE_OPT_FLAG}) ==="
40+
xt-clang --version | head -1
41+
42+
rm -rf cmake-out
43+
cmake \
44+
-DCMAKE_TOOLCHAIN_FILE=./backends/cadence/cadence.cmake \
45+
-DCMAKE_INSTALL_PREFIX=cmake-out \
46+
-DCMAKE_BUILD_TYPE=Release \
47+
-DEXECUTORCH_BUILD_CADENCE=ON \
48+
"-D${CADENCE_OPT_FLAG}=ON" \
49+
-DEXECUTORCH_BUILD_PORTABLE_OPS=ON \
50+
-DEXECUTORCH_BUILD_CADENCE_OP_TESTS=ON \
51+
-DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF \
52+
-DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \
53+
-DEXECUTORCH_ENABLE_LOGGING=ON \
54+
-DEXECUTORCH_BUILD_PTHREADPOOL=OFF \
55+
-DEXECUTORCH_BUILD_CPUINFO=OFF \
56+
-DEXECUTORCH_USE_DL=OFF \
57+
-DEXECUTORCH_BUILD_KERNELS_LLM=OFF \
58+
-DEXECUTORCH_BUILD_DEVTOOLS=OFF \
59+
-DHAVE_FNMATCH_H=OFF \
60+
-DFLATCC_ALLOW_WERROR=OFF \
61+
-DPYTHON_EXECUTABLE="$(which python3)" \
62+
-Bcmake-out .
63+
64+
cmake --build cmake-out --target "${TEST_TARGET}" -j"${NPROC}"
65+
66+
if [[ ! -f "${TEST_ELF}" ]]; then
67+
echo "ERROR: ${TEST_ELF} was not produced" >&2
68+
exit 1
69+
fi
70+
71+
echo "=== running ${TEST_TARGET} on xt-run ==="
72+
LOG=$(mktemp)
73+
# --exit_with_target_code propagates gtest_main's exit code, so a failing test
74+
# fails this step; also assert on the gtest summary lines as a backstop.
75+
xt-run --turbo --exit_with_target_code "${TEST_ELF}" 2>&1 | tee "${LOG}"
76+
if grep -q "\[ FAILED \]" "${LOG}"; then
77+
echo "ERROR: gtest reported failures for ${TEST_TARGET}" >&2
78+
exit 1
79+
fi
80+
if ! grep -q "\[ PASSED \]" "${LOG}"; then
81+
echo "ERROR: ${TEST_TARGET} did not report a gtest PASSED summary" >&2
82+
exit 1
83+
fi
84+
echo "Cadence ${TARGET_DIR} op tests passed on ${XTENSA_CORE}."

.github/workflows/_xtensa_test.yml

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# Reusable: build + run the Cadence Xtensa op-level gtest tests for one core on
2+
# the Instruction Set Simulator (xt-run). Mirrors _xtensa_build.yml's native
3+
# OIDC + docker-run skeleton (running xt-run needs the same licensed toolchain),
4+
# then builds the gtest op-test ELF and runs it on the simulator. The runner
5+
# cross-compile and these op tests are separate build configs (the tests need
6+
# exceptions/RTTI that the runner build disables), so this is a self-contained
7+
# job rather than consuming the runner artifact.
8+
name: xtensa-test
9+
10+
on:
11+
workflow_call:
12+
inputs:
13+
backend:
14+
description: "Cadence backend to test (hifi4 | vision | fusion_g3)"
15+
required: true
16+
type: string
17+
ref:
18+
description: "Git ref to check out"
19+
required: false
20+
type: string
21+
default: ""
22+
23+
jobs:
24+
test:
25+
name: ${{ inputs.backend }}
26+
runs-on: linux.2xlarge
27+
environment: cadence
28+
permissions:
29+
id-token: write
30+
contents: read
31+
steps:
32+
- name: Checkout executorch
33+
uses: actions/checkout@v4
34+
with:
35+
submodules: recursive
36+
ref: ${{ inputs.ref }}
37+
38+
- name: Calculate docker image
39+
id: calculate-docker-image
40+
uses: pytorch/test-infra/.github/actions/calculate-docker-image@main
41+
with:
42+
docker-image-name: ci-image:executorch-ubuntu-22.04-clang12
43+
44+
- name: Pull docker image
45+
run: docker pull "${{ steps.calculate-docker-image.outputs.docker-image }}"
46+
47+
- name: Assume Cadence artifacts role (host OIDC)
48+
uses: aws-actions/configure-aws-credentials@v4
49+
with:
50+
role-to-assume: ${{ vars.CADENCE_CI_AWS_ROLE }}
51+
aws-region: ${{ vars.CADENCE_CI_AWS_REGION }}
52+
53+
- name: Build and run op tests on xt-run
54+
env:
55+
DOCKER_IMAGE: ${{ steps.calculate-docker-image.outputs.docker-image }}
56+
BACKEND: ${{ inputs.backend }}
57+
XTENSA_S3_BUCKET: ${{ vars.CADENCE_CI_S3_BUCKET }}
58+
shell: bash
59+
run: |
60+
set -eux
61+
# OIDC/role assumption already happened on the host above; pass the
62+
# resulting AWS creds and the store/backend into the CI image, where
63+
# the toolchain download + op-test build + xt-run happen.
64+
docker run --rm \
65+
-e BACKEND -e XTENSA_S3_BUCKET \
66+
-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \
67+
-e AWS_DEFAULT_REGION -e AWS_REGION \
68+
-v "${GITHUB_WORKSPACE}:/work/executorch" -w /work/executorch \
69+
"${DOCKER_IMAGE}" \
70+
bash -c '
71+
set -exo pipefail
72+
eval "$(/opt/conda/bin/conda shell.bash hook)"
73+
conda activate "$(conda env list --json | jq -r ".envs | .[-1]")"
74+
./install_requirements.sh > /dev/null
75+
pip install --quiet awscli
76+
# hifi4/fusion_g3 optimized kernels need the foss-xtensa nnlib
77+
# sources, which are not vendored in executorch; the cadence
78+
# installer clones them. vision has no nnlib dependency.
79+
if [ "${BACKEND}" != "vision" ]; then
80+
backends/cadence/install_requirements.sh
81+
fi
82+
source .ci/scripts/setup-xtensa-tools.sh "${BACKEND}"
83+
.ci/scripts/test-cadence-xtensa.sh
84+
'

.github/workflows/build-cadence-runner.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,25 @@ jobs:
8787
backend: hifi4
8888
ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}
8989

90+
# Op-level gtest tests on the Xtensa ISS, mirroring cpu-build -> cpu-test. The
91+
# op tests are a self-contained cross-compile (the gtests need exceptions and
92+
# RTTI that the runner build disables), so this does not consume hifi-build's
93+
# artifact; needs: hifi-build only to fail fast when the backend cannot build.
94+
hifi-op-test:
95+
needs: hifi-build
96+
if: >-
97+
github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' ||
98+
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository) ||
99+
(github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name != github.repository &&
100+
contains(github.event.pull_request.labels.*.name, 'CLA Signed') && contains(github.event.pull_request.labels.*.name, 'meta-exported'))
101+
permissions:
102+
id-token: write
103+
contents: read
104+
uses: ./.github/workflows/_xtensa_test.yml
105+
with:
106+
backend: hifi4
107+
ref: ${{ (github.event_name == 'pull_request' || github.event_name == 'pull_request_target') && github.event.pull_request.head.sha || github.sha }}
108+
90109
vision-build:
91110
if: >-
92111
github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' ||

backends/cadence/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,13 @@ if(EXECUTORCH_BUILD_CADENCE_RUNNER)
132132
endif()
133133
target_link_options(cadence_executor_runner PRIVATE -static -lm)
134134
endif()
135+
136+
# Cadence op-level gtest tests, cross-compiled for the Xtensa ISS (run via
137+
# xt-run). Built only when EXECUTORCH_BUILD_CADENCE_OP_TESTS is ON and the
138+
# selected backend ships a tests dir. See .ci/scripts/test-cadence-xtensa.sh.
139+
if(EXECUTORCH_BUILD_CADENCE_OP_TESTS
140+
AND EXISTS
141+
"${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_DIR}/operators/tests/CMakeLists.txt"
142+
)
143+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${TARGET_DIR}/operators/tests)
144+
endif()
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
# All rights reserved.
3+
#
4+
# This source code is licensed under the BSD-style license found in the
5+
# LICENSE file in the root directory of this source tree.
6+
#
7+
# gtest op-level tests for the Cadence HiFi backend, cross-compiled for Xtensa
8+
# and run on the Instruction Set Simulator (xt-run). Each test calls the kernel
9+
# directly (impl::HiFi::native::<op>) and checks with EXPECT_TENSOR_EQ, mirroring
10+
# the BUCK tests. Built only when EXECUTORCH_BUILD_CADENCE_OP_TESTS is ON; see
11+
# .ci/scripts/test-cadence-xtensa.sh.
12+
13+
cmake_minimum_required(VERSION 3.19)
14+
15+
# Tame the vendored googletest build on the Xtensa clang toolchain. It hardcodes
16+
# -Werror -Wconversion on its own sources, which clang-10 trips (e.g. an int ->
17+
# signed char narrowing in gtest-port.h); -Wno-error keeps those non-fatal. A
18+
# ccache launcher also preprocesses then recompiles the .i, where the -I dirs
19+
# are unused and clang warns; -Qunused-arguments silences that. These land after
20+
# googletest's own flags, so they win, and apply to this whole subtree.
21+
add_compile_options(-Qunused-arguments -Wno-error)
22+
23+
# Let files say "include <executorch/path/to/header.h>".
24+
set(_common_include_directories
25+
${EXECUTORCH_ROOT}/.. ${EXECUTORCH_ROOT}/runtime/core/portable_type/c10
26+
)
27+
28+
# Build googletest FOR the Xtensa target. find_package(GTest) would resolve the
29+
# HOST gtest, which cannot link Xtensa objects, so add the source tree instead.
30+
# The cadence toolchain uses -stdlib=libc++ (exceptions/RTTI/iostream
31+
# available); the ISS is single-threaded, so disable pthreads.
32+
if(NOT TARGET gtest)
33+
set(gtest_disable_pthreads
34+
ON
35+
CACHE BOOL "" FORCE
36+
)
37+
set(INSTALL_GTEST
38+
OFF
39+
CACHE BOOL "" FORCE
40+
)
41+
add_subdirectory(
42+
${EXECUTORCH_ROOT}/third-party/googletest
43+
${CMAKE_CURRENT_BINARY_DIR}/googletest
44+
)
45+
endif()
46+
47+
# Op-level gtests, one source per operator. Each calls its kernel directly and
48+
# checks with EXPECT_TENSOR_EQ, mirroring the BUCK tests.
49+
add_executable(
50+
cadence_hifi_op_tests
51+
test_op_cat.cpp
52+
test_op_dequantize_per_tensor_out.cpp
53+
test_op_div.cpp
54+
test_op_im2row_out.cpp
55+
test_op_permute_copy.cpp
56+
test_op_quantize_per_tensor.cpp
57+
test_op_quantized_conv2d_out.cpp
58+
test_op_quantized_matmul_out.cpp
59+
test_op_quantized_relu_out.cpp
60+
test_op_transpose_copy.cpp
61+
${EXECUTORCH_ROOT}/runtime/core/exec_aten/testing_util/tensor_util.cpp
62+
)
63+
target_compile_definitions(cadence_hifi_op_tests PRIVATE GTEST_HAS_PTHREAD=0)
64+
target_include_directories(
65+
cadence_hifi_op_tests PRIVATE ${_common_include_directories}
66+
${CMAKE_BINARY_DIR}
67+
)
68+
69+
# Direct-call: link the libs that define the kernels under test. custom_ops has
70+
# the quantized ops; aten_ops_cadence has the aten-compliant ops (cat, div,
71+
# im2row, permute, transpose); cadence_kernels is the shared nnlib layer;
72+
# executorch provides the platform layer the tests' runtime_init() needs. No
73+
# cadence_ops_lib registry is needed for direct-call tests.
74+
target_link_libraries(
75+
cadence_hifi_op_tests
76+
PRIVATE gtest
77+
gtest_main
78+
gmock
79+
executorch
80+
custom_ops
81+
aten_ops_cadence
82+
cadence_kernels
83+
)

0 commit comments

Comments
 (0)