-
Notifications
You must be signed in to change notification settings - Fork 1k
Add OSS CI to cross-compile and run the Cadence Xtensa backend (#20208) #20208
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| #!/bin/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. | ||
| # | ||
| # Cross-compile cadence_executor_runner for a Cadence Xtensa core and (by | ||
| # default) smoke-test it on the Instruction Set Simulator with a trivial model. | ||
| # | ||
| # Requires the Xtensa toolchain env to already be set (run | ||
| # .ci/scripts/setup-xtensa-tools.sh <backend> first): XTENSA_TOOLCHAIN, | ||
| # TOOLCHAIN_VER, XTENSA_SYSTEM, XTENSA_CORE, XTENSAD_LICENSE_FILE, | ||
| # CADENCE_OPT_FLAG, and xt-clang on PATH. | ||
| # | ||
| # Usage: | ||
| # .ci/scripts/build-cadence-xtensa.sh [--no-run] | ||
| # --no-run : compile only, skip the ISS smoke test | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| RUN_SMOKE=1 | ||
| [[ "${1:-}" == "--no-run" ]] && RUN_SMOKE=0 | ||
|
|
||
| : "${XTENSA_TOOLCHAIN:?run setup-xtensa-tools.sh first}" | ||
| : "${TOOLCHAIN_VER:?run setup-xtensa-tools.sh first}" | ||
| : "${XTENSA_CORE:?run setup-xtensa-tools.sh first}" | ||
| : "${CADENCE_OPT_FLAG:?run setup-xtensa-tools.sh first}" | ||
|
|
||
| NPROC=$(nproc) | ||
| echo "=== building cadence_executor_runner for ${XTENSA_CORE} (${CADENCE_OPT_FLAG}) ===" | ||
| xt-clang --version | head -1 | ||
|
|
||
| rm -rf cmake-out | ||
| CXXFLAGS="-fno-exceptions -fno-rtti" cmake \ | ||
| -DCMAKE_TOOLCHAIN_FILE=./backends/cadence/cadence.cmake \ | ||
| -DCMAKE_INSTALL_PREFIX=cmake-out \ | ||
| -DCMAKE_BUILD_TYPE=Release \ | ||
| -DEXECUTORCH_BUILD_CADENCE=ON \ | ||
| "-D${CADENCE_OPT_FLAG}=ON" \ | ||
| -DEXECUTORCH_BUILD_PORTABLE_OPS=ON \ | ||
| -DEXECUTORCH_BUILD_CADENCE_RUNNER=ON \ | ||
| -DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF \ | ||
| -DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \ | ||
| -DEXECUTORCH_ENABLE_LOGGING=ON \ | ||
| -DEXECUTORCH_BUILD_PTHREADPOOL=OFF \ | ||
| -DEXECUTORCH_BUILD_CPUINFO=OFF \ | ||
| -DEXECUTORCH_USE_DL=OFF \ | ||
| -DEXECUTORCH_BUILD_KERNELS_LLM=OFF \ | ||
| -DEXECUTORCH_BUILD_DEVTOOLS=OFF \ | ||
| -DHAVE_FNMATCH_H=OFF \ | ||
| -DFLATCC_ALLOW_WERROR=OFF \ | ||
| -DPYTHON_EXECUTABLE="$(which python3)" \ | ||
| -Bcmake-out . | ||
|
|
||
| cmake --build cmake-out --target cadence_executor_runner -j"${NPROC}" | ||
|
|
||
| RUNNER="cmake-out/backends/cadence/cadence_executor_runner" | ||
| if [[ ! -f "${RUNNER}" ]]; then | ||
| echo "ERROR: ${RUNNER} was not produced" >&2 | ||
| exit 1 | ||
| fi | ||
| command -v file >/dev/null 2>&1 && file "${RUNNER}" || true | ||
| echo "Build OK: ${RUNNER}" | ||
|
|
||
| if [[ "${RUN_SMOKE}" == "0" ]]; then | ||
| echo "Skipping ISS smoke test (--no-run)." | ||
| exit 0 | ||
| fi | ||
|
|
||
| echo "=== ISS smoke test: export add.pte and run on xt-run --turbo ===" | ||
| python3 -m examples.portable.scripts.export --model_name=add >/dev/null | ||
| LOG=$(mktemp) | ||
| xt-run --turbo "${RUNNER}" --model_path=add.pte 2>&1 | tee "${LOG}" | ||
| if ! grep -q "Model executed successfully" "${LOG}"; then | ||
| echo "ERROR: ISS smoke test did not report success for ${XTENSA_CORE}" >&2 | ||
| exit 1 | ||
| fi | ||
| echo "ISS smoke test passed for ${XTENSA_CORE}." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,164 @@ | ||
| #!/bin/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. | ||
| # | ||
| # Download and install the licensed Cadence Xtensa toolchain + core config for | ||
| # a given backend, then export the environment that | ||
| # backends/cadence/cadence.cmake and xt-run need. | ||
| # | ||
| # The artifacts (host tools, the core tarball, and the bundled license) cannot | ||
| # be hosted publicly, so they are fetched at runtime from an auth-gated object | ||
| # store. The store location is provided by the caller via XTENSA_S3_BUCKET (set | ||
| # from a CI variable); credentials are obtained out of band before this runs. | ||
| # | ||
| # Usage: | ||
| # XTENSA_S3_BUCKET=<bucket> .ci/scripts/setup-xtensa-tools.sh <backend> | ||
| # backend = hifi4 | vision | fusion_g3 | ||
| # | ||
| # In GitHub Actions this appends the toolchain env to $GITHUB_ENV so later | ||
| # steps inherit it. Run locally to populate a workspace for manual builds. | ||
| # | ||
| # Modeled on .ci/scripts/setup-arm-baremetal-tools.sh. | ||
|
|
||
| set -euo pipefail | ||
|
|
||
| BACKEND="${1:-}" | ||
| if [[ -z "${BACKEND}" ]]; then | ||
| echo "ERROR: usage: XTENSA_S3_BUCKET=<bucket> $0 <hifi4|vision|fusion_g3>" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| S3_BUCKET="${XTENSA_S3_BUCKET:-}" | ||
| if [[ -z "${S3_BUCKET}" ]]; then | ||
| echo "ERROR: XTENSA_S3_BUCKET is not set (provide it from a CI variable)." >&2 | ||
| exit 1 | ||
| fi | ||
| # Objects live flat at the bucket root by default; set these to put toolchains | ||
| # and cores under key prefixes instead. | ||
| S3_TOOLCHAIN_PREFIX="${XTENSA_S3_TOOLCHAIN_PREFIX:-}" | ||
| S3_CORE_PREFIX="${XTENSA_S3_CORE_PREFIX:-}" | ||
|
|
||
| # Per-backend mapping: core tarball, toolchain tarball, core name, OPT flag. | ||
| # The toolchain's clang major must match the core's codegen plugin: | ||
| # hifi4 / fusion_g3 cores (RI-2022.10, clang 10) -> RI-2022.9 host tools | ||
| # vision core (RJ-2025.5, clang 15) -> RJ-2025.5 host tools | ||
| case "${BACKEND}" in | ||
| hifi4) | ||
| CORE_NAME="hifi4_ss_spfpu_7_et_ci2" | ||
| CORE_TARBALL="hifi4_ss_spfpu_7_et_ci2_linux.tgz" | ||
| TOOLCHAIN_TARBALL="XtensaTools_RI_2022_9_linux.tgz" | ||
| TOOLCHAIN_VER="RI-2022.9-linux" | ||
| OPT_FLAG="EXECUTORCH_NNLIB_OPT" | ||
| ;; | ||
| fusion_g3) | ||
| CORE_NAME="XRC_FuG3_TYP_SPVFPU_et_c2" | ||
| CORE_TARBALL="XRC_FuG3_TYP_SPVFPU_et_c2_linux.tgz" | ||
| TOOLCHAIN_TARBALL="XtensaTools_RI_2022_9_linux.tgz" | ||
| TOOLCHAIN_VER="RI-2022.9-linux" | ||
| OPT_FLAG="EXECUTORCH_FUSION_G3_OPT" | ||
| ;; | ||
| vision) | ||
| CORE_NAME="XRC_Vision_110_AO_et_ci2" | ||
| CORE_TARBALL="XRC_Vision_110_AO_et_ci2_linux.tgz" | ||
| TOOLCHAIN_TARBALL="XtensaTools_RJ_2025_5_linux.tgz" | ||
| TOOLCHAIN_VER="RJ-2025.5-linux" | ||
| OPT_FLAG="EXECUTORCH_VISION_OPT" | ||
| ;; | ||
| *) | ||
| echo "ERROR: unknown backend '${BACKEND}' (expected hifi4|vision|fusion_g3)" >&2 | ||
| exit 1 | ||
| ;; | ||
| esac | ||
|
|
||
| XTENSA_ROOT="${XTENSA_ROOT:-/tmp/xtensa}" | ||
| TOOLS_ROOT="${XTENSA_ROOT}/tools" # contains <ver>-linux/XtensaTools | ||
| CORES_ROOT="${XTENSA_ROOT}/cores" # contains <corever>-linux/<core> | ||
| REGISTRY_ROOT="${XTENSA_ROOT}/registry/${CORE_NAME}" | ||
| DL_DIR="${XTENSA_ROOT}/download" | ||
| mkdir -p "${TOOLS_ROOT}" "${CORES_ROOT}" "${REGISTRY_ROOT}" "${DL_DIR}" | ||
|
|
||
| s3_get() { | ||
| # $1 = s3 key, $2 = local dest | ||
| local key="$1" dest="$2" | ||
| echo "Downloading s3://${S3_BUCKET}/${key} ..." | ||
| aws s3 cp "s3://${S3_BUCKET}/${key}" "${dest}" --only-show-errors | ||
| } | ||
|
|
||
| extract_tgz() { | ||
| # $1 = .tgz, $2 = dest dir. Some vendor core tarballs carry trailing bytes | ||
| # after a valid gzip stream; gzip then exits 2 ("trailing garbage ignored") | ||
| # even though the archive decompressed fully, which aborts `tar xzf`. Key the | ||
| # success check off tar's exit, not gzip's. | ||
| local tgz="$1" dest="$2" rc | ||
| set +o pipefail | ||
| gzip -dc "${tgz}" 2>/dev/null | tar xf - -C "${dest}" | ||
| rc=${PIPESTATUS[1]} | ||
| set -o pipefail | ||
| [[ "${rc}" -eq 0 ]] || { echo "ERROR: failed to extract ${tgz} (tar rc=${rc})" >&2; exit 1; } | ||
| } | ||
|
|
||
| # 1. Toolchain (host xt-clang/xt-run). Skip re-extract if already present. | ||
| if [[ ! -d "${TOOLS_ROOT}/${TOOLCHAIN_VER}/XtensaTools" ]]; then | ||
| s3_get "${S3_TOOLCHAIN_PREFIX:+${S3_TOOLCHAIN_PREFIX}/}${TOOLCHAIN_TARBALL}" "${DL_DIR}/${TOOLCHAIN_TARBALL}" | ||
| extract_tgz "${DL_DIR}/${TOOLCHAIN_TARBALL}" "${TOOLS_ROOT}" | ||
| fi | ||
| TOOLCHAIN_HOME="${TOOLS_ROOT}/${TOOLCHAIN_VER}/XtensaTools" | ||
| if [[ ! -x "${TOOLCHAIN_HOME}/bin/xt-clang" ]]; then | ||
| echo "ERROR: xt-clang not found at ${TOOLCHAIN_HOME}/bin after extract" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| # 2. Core config (ISA libs, params, examples, bundled magic-key license). | ||
| s3_get "${S3_CORE_PREFIX:+${S3_CORE_PREFIX}/}${CORE_TARBALL}" "${DL_DIR}/${CORE_TARBALL}" | ||
| extract_tgz "${DL_DIR}/${CORE_TARBALL}" "${CORES_ROOT}" | ||
| CORE_DIR=$(echo "${CORES_ROOT}"/*/"${CORE_NAME}") | ||
| if [[ ! -d "${CORE_DIR}" ]]; then | ||
| echo "ERROR: core dir for ${CORE_NAME} not found under ${CORES_ROOT}" >&2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| # 3. Build a local Xtensa core registry with the XPG-internal build paths in | ||
| # the params file rewritten to our extracted toolchain + core locations. | ||
| # The vendor ships params referencing /././home/xpgcust/... build paths. | ||
| PARAMS_SRC="${CORE_DIR}/config/${CORE_NAME}-params" | ||
| TOOLS_PFX=$(sed -n 's/^install-prefix = //p' "${PARAMS_SRC}" | head -1) | ||
| TOOLSUB_PFX=$(sed -n 's/^xtensa-tools = //p' "${PARAMS_SRC}" | head -1) | ||
| CFG_PFX=$(sed -n 's/^config-prefix = //p' "${PARAMS_SRC}" | head -1) | ||
| sed \ | ||
| -e "s|${TOOLS_PFX}|${TOOLCHAIN_HOME}|g" \ | ||
| -e "s|${TOOLSUB_PFX}|${TOOLCHAIN_HOME}/Tools|g" \ | ||
| -e "s|${CFG_PFX}|${CORE_DIR}|g" \ | ||
| "${PARAMS_SRC}" > "${REGISTRY_ROOT}/${CORE_NAME}-params" | ||
| ln -sf "${CORE_NAME}-params" "${REGISTRY_ROOT}/default-params" | ||
|
|
||
| LICENSE_FILE="${CORE_DIR}/misc/license.dat" | ||
|
|
||
| # 4. Export environment. cadence.cmake reads XTENSA_TOOLCHAIN/TOOLCHAIN_VER; | ||
| # xt-clang/xt-run read XTENSA_SYSTEM/XTENSA_CORE; xtensad reads | ||
| # XTENSAD_LICENSE_FILE (the bundled uncounted magic key, no server needed). | ||
| emit() { | ||
| # Export into the current shell (so callers that `source` this script get the | ||
| # vars) and append to $GITHUB_ENV (so later workflow steps inherit them too). | ||
| echo "$1" | ||
| export "${1?}" | ||
| if [[ -n "${GITHUB_ENV:-}" ]]; then echo "$1" >> "${GITHUB_ENV}"; fi | ||
| } | ||
| echo "=== Xtensa env for backend '${BACKEND}' (core ${CORE_NAME}) ===" | ||
| emit "XTENSA_TOOLCHAIN=${TOOLS_ROOT}" | ||
| emit "TOOLCHAIN_VER=${TOOLCHAIN_VER}" | ||
| emit "XTENSA_SYSTEM=${REGISTRY_ROOT}" | ||
| emit "XTENSA_CORE=${CORE_NAME}" | ||
| emit "XTENSAD_LICENSE_FILE=${LICENSE_FILE}" | ||
| emit "CADENCE_OPT_FLAG=${OPT_FLAG}" | ||
| if [[ -n "${GITHUB_PATH:-}" ]]; then | ||
| echo "${TOOLCHAIN_HOME}/bin" >> "${GITHUB_PATH}" | ||
| fi | ||
| export PATH="${TOOLCHAIN_HOME}/bin:${PATH}" | ||
|
|
||
| echo "=== sanity ===" | ||
| xt-clang --version 2>&1 | head -1 | ||
| xt-run --show-config=cores 2>&1 | sed -n '/available/,/registry/p' | head -6 | ||
| echo "Xtensa toolchain ready for ${BACKEND}." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| # Reusable: cross-compile cadence_executor_runner for one Cadence Xtensa core. | ||
| # | ||
| # A native job (not linux_job_v2) because the GitHub OIDC token must be minted on | ||
| # the runner host: the ACTIONS_ID_TOKEN_REQUEST_* vars do not cross into | ||
| # linux_job_v2's docker exec. So the role is assumed on the host, then the build | ||
| # runs inside the CI image via docker run with the creds passed in. Binding the | ||
| # environment also gives the OIDC token the environment claim. The licensed | ||
| # toolchain + core configs are fetched at runtime from an auth-gated store; | ||
| # role/region/store come from CI variables and are not committed. | ||
| name: xtensa-build | ||
|
|
||
| on: | ||
| workflow_call: | ||
| inputs: | ||
| backend: | ||
| description: "Cadence backend to build (hifi4 | vision | fusion_g3)" | ||
| required: true | ||
| type: string | ||
| ref: | ||
| description: "Git ref to check out" | ||
| required: false | ||
| type: string | ||
| default: "" | ||
|
|
||
| jobs: | ||
| build: | ||
| name: ${{ inputs.backend }} | ||
| runs-on: linux.2xlarge | ||
| environment: cadence | ||
| permissions: | ||
| id-token: write | ||
| contents: read | ||
| steps: | ||
| - name: Checkout executorch | ||
| uses: actions/checkout@v4 | ||
| with: | ||
| submodules: recursive | ||
| ref: ${{ inputs.ref }} | ||
|
|
||
| - name: Calculate docker image | ||
| id: calculate-docker-image | ||
| uses: pytorch/test-infra/.github/actions/calculate-docker-image@main | ||
| with: | ||
| docker-image-name: ci-image:executorch-ubuntu-22.04-clang12 | ||
|
|
||
| - name: Pull docker image | ||
| run: docker pull "${{ steps.calculate-docker-image.outputs.docker-image }}" | ||
|
|
||
| - name: Assume Cadence artifacts role (host OIDC) | ||
| uses: aws-actions/configure-aws-credentials@v4 | ||
| with: | ||
| role-to-assume: ${{ vars.CADENCE_CI_AWS_ROLE }} | ||
| aws-region: ${{ vars.CADENCE_CI_AWS_REGION }} | ||
|
|
||
| - name: Cross-compile cadence_executor_runner | ||
| env: | ||
| DOCKER_IMAGE: ${{ steps.calculate-docker-image.outputs.docker-image }} | ||
| BACKEND: ${{ inputs.backend }} | ||
| XTENSA_S3_BUCKET: ${{ vars.CADENCE_CI_S3_BUCKET }} | ||
| shell: bash | ||
| run: | | ||
| set -eux | ||
| # OIDC/role assumption already happened on the host above; pass the | ||
| # resulting AWS creds and the store/backend into the CI image, where | ||
| # the toolchain download + cross-compile run. | ||
| docker run --rm \ | ||
| -e BACKEND -e XTENSA_S3_BUCKET \ | ||
| -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \ | ||
| -e AWS_DEFAULT_REGION -e AWS_REGION \ | ||
| -v "${GITHUB_WORKSPACE}:/work/executorch" -w /work/executorch \ | ||
| "${DOCKER_IMAGE}" \ | ||
| bash -c ' | ||
| set -exo pipefail | ||
| eval "$(/opt/conda/bin/conda shell.bash hook)" | ||
| conda activate "$(conda env list --json | jq -r ".envs | .[-1]")" | ||
| ./install_requirements.sh > /dev/null | ||
| pip install --quiet awscli | ||
| # hifi4/fusion_g3 optimized kernels need the foss-xtensa nnlib | ||
| # sources, which are not vendored in executorch; the cadence | ||
| # installer clones them. vision has no nnlib dependency. | ||
| if [ "${BACKEND}" != "vision" ]; then | ||
| backends/cadence/install_requirements.sh | ||
| fi | ||
| source .ci/scripts/setup-xtensa-tools.sh "${BACKEND}" | ||
| .ci/scripts/build-cadence-xtensa.sh --no-run | ||
| chmod -R a+rX cmake-out | ||
| ' | ||
|
|
||
| - name: Upload runner | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: cadence-xtensa-build-${{ inputs.backend }} | ||
| path: cmake-out/backends/cadence/cadence_executor_runner | ||
| if-no-files-found: error | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to note that being able to access to this environment means being able to access the S3 bucket. The access can be granted in several ways: