Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
203 changes: 190 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,16 @@ jobs:
UBSAN_OPTIONS: print_stacktrace=1
run: ctest --test-dir build ${{ env.CTEST_COMMON }} ${{ matrix.labels }}

# The family's error model, A3: every engine's headers and the three C
# ABIs build with exceptions off (clang, -fno-exceptions, warnings fatal).
# Tests and examples are off: gtest's EXPECT_THROW and the examples' catch
# blocks need exceptions, and the headers' own exceptions-off compile is
# the hosted legs' <engine>.Family.HeadersCompileWithoutExceptions. What
# this job adds is the C boundary: the create paths validate first and
# carry no try/catch in such a build.
# The family's error model, A3, as a consumer that forbids both exceptions
# and RTTI builds it (the roadmap's Q5 and A12): every engine's battery,
# examples and C ABI under -fno-exceptions -fno-rtti (TAP_SR_NO_EXCEPTIONS_RTTI),
# warnings fatal. Rejections are death tests here (tests/support/tap_sr_test/
# expect_rejected.h) and the C ABIs' create paths validate first and carry
# no try/catch. The job keeps its A3 name so its check stays the same.
no-exceptions:
name: Linux Clang, -fno-exceptions (engines + C ABIs)
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 30
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
with:
Expand All @@ -170,13 +169,16 @@ jobs:
run: >
cmake -B build
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_CXX_FLAGS=-fno-exceptions
-DTAP_SR_BUILD_TESTS=OFF -DTAP_SR_BUILD_EXAMPLES=OFF -DTAP_SR_BUILD_CAPI=ON
-DTAP_SR_NO_EXCEPTIONS_RTTI=ON
-DTAP_SR_BUILD_TESTS=ON -DTAP_SR_BUILD_EXAMPLES=ON -DTAP_SR_BUILD_CAPI=ON
-DTAP_SR_ASYNC_WERROR=ON -DTAP_SR_BRIDGE_WERROR=ON -DTAP_SR_RATIONAL_WERROR=ON

- name: Build
run: cmake --build build -j 4

- name: Test
run: ctest --test-dir build ${{ env.CTEST_COMMON }} -j 4

# Cross-compiled correctness under emulation, one job per (target, engine):
# every engine is built in one tree and each job runs one engine's label
# with that engine's own exclusions and parallelism, as each repository ran
Expand Down Expand Up @@ -292,6 +294,120 @@ jobs:
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m33-mps2.cmake
exclude: ""
# The same nine legs as a consumer that forbids exceptions and RTTI
# builds them (the roadmap's Q5 and A12: a current one ships every
# engine this way on these three targets), with each leg's own
# exclusions and budget.
- target: hexagon
title: Hexagon cross, no exceptions/RTTI
engine: async
label: async
timeout: 45
jobs: 1
build_type: Release
toolchain: cmake/hexagon-linux-musl.cmake
exclude: AsrcQuality|AsrcLock|TwoThreadStress|Threads\.|TransparentPrototypeMeetsSpec|MultiChannel\.|Feasibility|Reset\.
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: hexagon
title: Hexagon cross, no exceptions/RTTI
engine: bridge
label: bridge
timeout: 30
jobs: 4
build_type: Release
toolchain: cmake/hexagon-linux-musl.cmake
exclude: ""
# rational: the host measurements are excluded on Hexagon (the two
# unmeetable-spec tests, which search every length on the design
# grid in soft double and outlast the per-test timeout; the coverage matrix's tone batteries, 182 chains in double per
# profile, and the relaxation tables' searches, which run every
# candidate length through the design grid: the 70 dB tables alone
# exceed the job's budget under qemu-hexagon, and the quantized and
# relaxed Q15 tables' stopbands through a 16384-point DFT); on the Arm legs
# bare_metal_main.cpp bakes in its own
# filter (the fine-grid sweeps of the long designs and the
# matrix suite).
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: hexagon
title: Hexagon cross, no exceptions/RTTI
engine: rational
label: rational
timeout: 20
jobs: 4
build_type: Release
toolchain: cmake/hexagon-linux-musl.cmake
exclude: UnmeetableSpec|Matrix\.EveryRowMeets|RelaxationTablesAreTheSearch|QuantizedTablesAttainTheirStatedStopbands|RelaxedQ15TablesStopbandsAreStated
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: m55
title: Cortex-M55 cross, no exceptions/RTTI
engine: rational
label: rational
timeout: 20
jobs: 1
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m55-mps3.cmake
exclude: ""
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: m33
title: Cortex-M33 cross, no exceptions/RTTI
engine: rational
label: rational
timeout: 20
jobs: 1
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m33-mps2.cmake
exclude: ""
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: m55
title: Cortex-M55 cross, no exceptions/RTTI
engine: async
label: async
timeout: 30
jobs: 1
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m55-mps3.cmake
exclude: ""
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: m55
title: Cortex-M55 cross, no exceptions/RTTI
engine: bridge
label: bridge
timeout: 20
jobs: 1
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m55-mps3.cmake
exclude: ""
# ~23 min of emulated suite against a 40-minute budget.
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: m33
title: Cortex-M33 cross, no exceptions/RTTI
engine: async
label: async
timeout: 40
jobs: 1
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m33-mps2.cmake
exclude: ""
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
- target: m33
title: Cortex-M33 cross, no exceptions/RTTI
engine: bridge
label: bridge
timeout: 20
jobs: 1
build_type: MinSizeRel
toolchain: cmake/arm-cortex-m33-mps2.cmake
exclude: ""
cmake_extra: -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
suffix: -no-exceptions-rtti
env:
# Prebuilt open-source toolchain (BSD-3) published by Qualcomm/Quicinc;
# binary artifacts are hosted on CodeLinaro and linked from the
Expand Down Expand Up @@ -372,6 +488,7 @@ jobs:
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DCMAKE_TOOLCHAIN_FILE=${{ matrix.toolchain }}
-DTAP_SR_BUILD_EXAMPLES=OFF
${{ matrix.cmake_extra }}

- name: Build
run: cmake --build build -j 4
Expand All @@ -380,16 +497,16 @@ jobs:
shell: bash
run: |
args=(--test-dir build ${{ env.CTEST_COMMON }} -L '^${{ matrix.label }}$'
-j ${{ matrix.jobs }} -V --output-log ctest-${{ matrix.target }}-${{ matrix.engine }}.log)
-j ${{ matrix.jobs }} -V --output-log ctest-${{ matrix.target }}-${{ matrix.engine }}${{ matrix.suffix }}.log)
if [ -n '${{ matrix.exclude }}' ]; then args+=(-E '${{ matrix.exclude }}'); fi
ctest "${args[@]}"

- name: Upload test log
if: ${{ !cancelled() }}
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ctest-${{ matrix.target }}-${{ matrix.engine }}
path: ctest-${{ matrix.target }}-${{ matrix.engine }}.log
name: ctest-${{ matrix.target }}-${{ matrix.engine }}${{ matrix.suffix }}
path: ctest-${{ matrix.target }}-${{ matrix.engine }}${{ matrix.suffix }}.log

# ------------------------------------------------------------------------
# Template: genuine Tensilica HiFi4/HiFi5 coverage. The HiFi audio ISA,
Expand Down Expand Up @@ -608,6 +725,43 @@ jobs:
if: ${{ !cancelled() }}
run: python3 scripts/ceilings.py measure --engine rational --target ${{ matrix.target }} --build-dir build

# The same workloads as the family's exceptions-off consumer builds
# them (TAP_SR_NO_EXCEPTIONS_RTTI, the roadmap's A12), counted against
# the SAME baselines: the engines' hot paths are their own (out-of-line
# entries, rational's cursor), so the two configurations are identical
# to the instruction, and this is what pins that. The ceilings are
# recorded for the exceptions build only.
- name: Build workloads without exceptions or RTTI
if: ${{ !cancelled() }}
run: |
case "${{ matrix.target }}" in
m55) tc=cmake/arm-cortex-m55-mps3.cmake ;;
m33) tc=cmake/arm-cortex-m33-mps2.cmake ;;
hexagon) tc=cmake/hexagon-linux-musl.cmake ;;
esac
cmake -B build-noexc -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE=$tc \
-DTAP_SR_BUILD_TESTS=OFF -DTAP_SR_BUILD_EXAMPLES=OFF \
-DTAP_SR_BUILD_ICOUNT_BENCH=ON -DTAP_SR_NO_EXCEPTIONS_RTTI=ON
cmake --build build-noexc -j 4

- name: Ratchet async (no exceptions, no RTTI)
if: ${{ !cancelled() }}
run: >
python3 scripts/icount.py --engine async --target ${{ matrix.target }}
--build-dir build-noexc --plugin /tmp/libinsncount.so

- name: Ratchet bridge (no exceptions, no RTTI)
if: ${{ !cancelled() }}
run: >
python3 scripts/icount.py --engine bridge --target ${{ matrix.target }}
--build-dir build-noexc --plugin /tmp/libinsncount.so

- name: Ratchet rational (no exceptions, no RTTI)
if: ${{ !cancelled() }}
run: >
python3 scripts/icount.py --engine rational --target ${{ matrix.target }}
--build-dir build-noexc --plugin /tmp/libinsncount.so

# The host ratchet (the roadmap's A8): each engine's float converter in
# 128-frame blocks at 2 and 12 channels, built natively and counted under
# callgrind (<engine>/bench/icount/host_main.cpp, scripts/icount.py
Expand Down Expand Up @@ -660,6 +814,29 @@ jobs:
if: ${{ !cancelled() }}
run: python3 scripts/icount.py --engine rational --target host --build-dir build

# The exceptions-off configuration (A12), against the same baselines.
- name: Build the host workloads without exceptions or RTTI
if: ${{ !cancelled() }}
run: |
cmake -B build-noexc -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=g++-13 \
-DTAP_SR_BUILD_TESTS=OFF -DTAP_SR_BUILD_EXAMPLES=OFF -DTAP_SR_BUILD_ICOUNT_BENCH=ON \
-DTAP_SR_NO_EXCEPTIONS_RTTI=ON
targets=$(cmake --build build-noexc --target help | sed -n 's/^\(tap_sr_[a-z]*_hostcount_[a-z0-9_]*\):.*/\1/p')
test -n "$targets"
cmake --build build-noexc -j 4 --target $targets

- name: Ratchet async (no exceptions, no RTTI)
if: ${{ !cancelled() }}
run: python3 scripts/icount.py --engine async --target host --build-dir build-noexc

- name: Ratchet bridge (no exceptions, no RTTI)
if: ${{ !cancelled() }}
run: python3 scripts/icount.py --engine bridge --target host --build-dir build-noexc

- name: Ratchet rational (no exceptions, no RTTI)
if: ${{ !cancelled() }}
run: python3 scripts/icount.py --engine rational --target host --build-dir build-noexc

# Each engine README's instruction-count table derives 1:1 from its
# committed baselines, and its ceilings tables from bench/ceilings.json;
# regenerating them must produce no diff.
Expand Down
12 changes: 11 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ made this tree (sections 5–6). Do not re-derive what it settles.
- **Clean renames, no aliases (D7).** Retired options fail the configure
(`cmake/retired_options.cmake`); retired override macros hit an `#error`; retired words fail
the style job (`scripts/retired_words.txt`, `scripts/check_retired_words.py`). Do not add aliases.
- **Exceptions and RTTI stay optional (A12, Q5).** A current consumer builds all three engines
with `-fno-exceptions -fno-rtti` on the M33, M55 and Hexagon, and the 1.0 freeze covers that
configuration (P14). No header may use RTTI or rely on exceptions beyond `tap::dsp::raise`. A
test that rejects or accepts a configuration goes through `TAP_SR_EXPECT_REJECTED`,
`TAP_SR_EXPECT_REJECTED_WITH` or `TAP_SR_EXPECT_ACCEPTED`
(`tests/support/tap_sr_test/expect_rejected.h`), never `EXPECT_THROW` or a `try` of its own;
`-DTAP_SR_NO_EXCEPTIONS_RTTI=ON` reproduces the gated build, and CI runs it hosted and on the
nine QEMU legs.
- **One meaning per profile name (A4, the 2026-10 audit response).** Each engine's quality tiers
are its own ladder, stated with its numbers in the root README's profile table, and a profile
name means one thing across the family: `bridge` and `rational` share four names at the same
Expand Down Expand Up @@ -84,7 +92,9 @@ over statistical sampling, and measured numbers stated with their provenance.
(`cmake/arm-cortex-*.cmake`, one-shot `bare_metal_main.cpp` per engine) and on Hexagon under
`qemu-hexagon`, and the instruction-count ratchet gates every workload of every engine two-sided
at ±3 % (`scripts/icount.py --engine async|bridge|rational --target m33|m55|hexagon`, baselines in
`<engine>/bench/baselines.json`). A change that moves a count beyond tolerance re-records the
`<engine>/bench/baselines.json`), built with exceptions and again without them or RTTI
(`TAP_SR_NO_EXCEPTIONS_RTTI`) against the same baselines: the engines' hot paths are their own
(A12), so the two builds count the same. A change that moves a count beyond tolerance re-records the
baseline in the same PR; an improvement beyond tolerance fails too, by design. Guest markers
(`SRT_ICOUNT_DONE`, `RATIO_ICOUNT_DONE`, `RATIONAL_ICOUNT_DONE`) are part of the counted binaries
and never change. A `callmax_*` scenario is the worst single call instead of a total
Expand Down
17 changes: 17 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ option(TAP_SR_BUILD_COMPARE_SHIM "Build the comparison notebooks' competitor shi
option(TAP_SR_ASYNC_WERROR "Treat warnings as errors in the async engine's own targets" OFF)
option(TAP_SR_BRIDGE_WERROR "Treat warnings as errors in the bridge engine's own targets" OFF)
option(TAP_SR_RATIONAL_WERROR "Treat warnings as errors in the rational engine's own targets" OFF)
# The configuration a consumer that forbids both builds every engine in (the
# roadmap's Q5 and A12: a current one does, on the M33, M55 and Hexagon):
# every target this tree adds from here on, GoogleTest and every engine's
# battery, examples, C ABI and ratchet workloads, compiles C++ with
# -fno-exceptions -fno-rtti. The engines need nothing for it (A3: validate()
# before constructing, rejections terminate through tap::dsp::raise; no
# header uses RTTI); the option builds the evidence. An option rather than
# CMAKE_CXX_FLAGS, which would replace the cross toolchains' _INIT flags.
# Directory scope; GCC and Clang only.
option(TAP_SR_NO_EXCEPTIONS_RTTI "Build every target with -fno-exceptions -fno-rtti" OFF)
if(TAP_SR_NO_EXCEPTIONS_RTTI)
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|AppleClang)$"
OR CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
message(FATAL_ERROR "TAP_SR_NO_EXCEPTIONS_RTTI needs GCC or Clang (got ${CMAKE_CXX_COMPILER_ID})")
endif()
add_compile_options(-fno-exceptions -fno-rtti)
endif()

# GoogleTest is fetched once, by whichever engine's tests/ is configured
# first; the other engines' FetchContent_MakeAvailable is then a no-op. Its
Expand Down
Loading
Loading