Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
53ef2f1
tests(sve): port movbe reload-path trio from missing_testcases_202610…
Oct 10, 2026
6f155cd
tests(sve): port mrn_rmw load-path family from missing_testcases_2026…
Oct 10, 2026
96dee40
tests(sve): port mrn constructed family from missing_testcases_202610…
Oct 10, 2026
d9bea0e
tests(sve): port reload-necessity and lane/axis probes from missing_t…
Oct 10, 2026
e1caf58
tests(sve): port neon_rot_ldr_at_top base variants from missing_testc…
Oct 10, 2026
d6670ce
tests(sve): port rowmajor instrumented variants from missing_testcase…
Oct 10, 2026
fab8485
tests(sve): port K-cells from missing_testcases_20261009 — k5far/k5in…
Oct 10, 2026
135355e
tests(sve): port arm-0102 trigger-recipe variants from missing_testca…
Oct 10, 2026
134dd6b
docs: sync README counts + docs_xu batch record for missing_testcases…
Oct 10, 2026
88528cc
docs(docs_xu): T10 reliability (0-63 half-core) + T11 effectiveness e…
Oct 11, 2026
8e29606
plan: T12 all-core incl-122 stress batch (44 tests x 30min) per user …
Oct 11, 2026
cec0ccb
docs(docs_xu): T12 all-core incl-122 stress results — 44/44 pass, 0 S…
Oct 12, 2026
313dbcb
tests(sve): neon_rot_ldr_at_top_rowmajor_sve add cold-path bit dump o…
Oct 12, 2026
cfa58ff
fix(sve): size arm0102 tail slack for the active SVE vector length
Oct 12, 2026
a2d1767
fix(sve): size phase scratch for the architectural max VL in MRN/stor…
Oct 12, 2026
a142a25
fix(sve): build movbe svtbl indices and fail-path buffers for the act…
Oct 12, 2026
8c51170
fix(selftest): emit SMSTART/SMSTOP via .inst — GCC 13 rejects arch=ar…
Oct 12, 2026
11ad214
tests(sve): neon_rot_ldr_at_top variants add cold-path bit dump (6 te…
Oct 12, 2026
ddb00d1
tests(sve): neon_rot 2src/store_only/u8x16 + mite add cold-path bit d…
Oct 12, 2026
426dc5c
tests(sve): rotate arm0102 sub-block ops by sub-block index, not elem…
Oct 12, 2026
b34776d
tests(sve): create movbe_log parent before nested dump dir in rowmajo…
Oct 12, 2026
c0c1699
tests(sve): honor tail predicate in neon_rot_u8x16_sve tail stores
Oct 12, 2026
3dcfb01
tests(sve): fix mls operand order and narrow inputs to 15 bits in mla…
Oct 12, 2026
fcb2f9c
tests(sve): compare movbe cold-path miscompares against the tested re…
Oct 12, 2026
b55063c
tests(sve): report incomplete golden-file write in movbe_dump_golden_sve
Oct 12, 2026
dd31295
docs(sve): correct plan cpuset, phase sizing and file count from review
Oct 12, 2026
d01ff98
tests(sve): report the pre-swap input separately from the tested reload
Oct 12, 2026
6ab1f11
tests(sve): keep the u8x16 full-VL tail reload within the buffers
Oct 12, 2026
19b26d6
tests(sve): mrn family add cold-path bit dump / value-complete fail m…
Oct 12, 2026
ffcc7a3
framework: fix lane-offset histogram single-line log_yaml message
Oct 12, 2026
cf63210
tests(sve): key sve512_fcmla_arm golden on rotation index, not angle
Oct 12, 2026
f335b56
tests(sve): fix sve512_pred_ops_arm FMA operand order and predicate m…
Oct 12, 2026
8db1de9
tests(sve): prime FFR with SETFFR before LDFF1 in sve512_pred_ops_arm
Oct 12, 2026
3524436
tests(sve): arm0102/swizzle/movbe_sve add cold-path bit dump (7 tests)
Oct 12, 2026
644b6b1
tests(sve): mem family add cold-path bit dump (3 tests)
Oct 12, 2026
64e9da8
tests(sve): arithmetic acl_gemm/gmp_bigadd add cold-path bit dump (2 …
Oct 12, 2026
6a82ca9
tests(sve): fma2 movdq2q add cold-path bit dump (1 test)
Oct 12, 2026
0d040a3
tests(sve): mesh consistency variants add sum-bit + failing-vector re…
Oct 12, 2026
4b56f8c
tests(sve): mesh sum-only variants add sum-bit records + writing_test…
Oct 12, 2026
5e8e2d6
tests(sve): mesh_upi_sve_sym add sum-bit + failing-vector records (co…
Oct 12, 2026
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
153 changes: 153 additions & 0 deletions docs/docs_xu/2026-10-10-missing-testcases-sve-port.md

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions docs/misc/writing_tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -970,3 +970,13 @@ SDCShield's public API can be found in
in this file are documented. Readers should consult
[sandstone.h](../framework/sandstone.h) for information about SDCShield's API
that is not covered in this guide.

### Failure dumps: cold-path bit records (纪律)

SDC 证据要求失败时记录 golden/actual/xor 逐元素值。热路径(比较调用、分支、
report_fail_msg)不得因加 dump 而改变指令时序——所有 dump 代码必须位于
"健康核永远不进"的失败分支内部(自有 `{}` 块、自有 `_dump_` 前缀局部变量、
无 early return),上限 8 条 mismatch + 1 行总数。提交前用 objdump 对照热循环
不变(参考 tests/cpu/sve/core179/movbe_dump_probe_* 与本目录 55 个测试的
2026-10-12 批量改造)。框架 `memcmp_or_fail` 自带 mismatch dump,新测试
优先用它;只在需要保留自定义比较结构时才手写冷路径 dump。
482 changes: 482 additions & 0 deletions docs/superpowers/plans/2026-10-10-missing-testcases-sve-port.md

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions docs/superpowers/plans/2026-10-12-fix-lane-offsets-yaml-message.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Fix: `lane offsets` histogram message violates the `log_yaml()` two-line protocol

## Context

PR #232 (`feat/sve-port-avx53`) CI job **Build binary for CPU** fails, but the
failure is **not** caused by any PR #232 change:

- Failing bats case: `selftest_datacompare` → `not ok 95`, running
`sdcshield ... -e selftest_datacomparefail_uint8_t`.
- Crash: `../framework/logging.cpp:1571: void format_and_print_raw_yaml(...):
Assertion 'nl >= 0' failed.` → `Aborted (core dumped)` (exit 134).

The offending code lives in `framework/sandstone_run.cpp`
(`SandstoneMemcmpOrFail::report`), added by commit `e899b283`
(2026-09-17, SDC excitation enhancement suite) and already present on
`origin/main` (merged via PR #233). The PR only *exposes* it because
`.github/workflows/pr.yaml` triggers `build-cpu` **only on `pull_request`**
(never on a push to `main`) and builds with `-Dbuildtype=debugoptimized`,
where `assert()` is active (`b_ndebug=if-release`).

## Root cause

`log_yaml(char levelchar, const char *yaml)` prepends a `'\n'` to the caller
string (`log_thread_yaml` → `log_message_for_thread(..., '\n', yaml)`). The
formatter `format_and_print_raw_yaml` then expects a **two-line** message:

1. line 1 (empty, from the prepended `'\n'`) → heading, defaults to `details:`;
2. line 2 → the optional `text:` description, which must be terminated by a
`'\n'`; remaining lines form the `details:` body.

The histogram code passed a **single line**
(`"lane offsets: N mismatching bytes in [a..b] (...)"`), so after the leading
empty line there is no second `'\n'` → `message.find('\n') == -1` → the
`assert(nl >= 0)` fires in debug builds. Release builds (`NDEBUG`) skip the
assert and silently produce malformed output, which is why the default local
`builddir` build does not reproduce it.

## Fix

Make the histogram emit a well-formed two-line message: the first line is the
`text:` description (`lane offsets`), the second is the histogram detail.

- File: `framework/sandstone_run.cpp` (our own code — upstream
`logging.cpp` is left untouched, per the additive-port rule).
- `std::string hist = "lane offsets:";` → `"lane offsets\n"`.
- Drop the leading space in the appended stat line.

Resulting YAML:

```yaml
- level: warning
text: 'lane offsets'
details:
1 mismatching bytes in [0..0] (single-lane pattern — one bad physical unit fingerprint)
```

## Verification (100% real)

- debugoptimized build (`builddir-dbg`, same flags as CI) — before: `exit=134`
+ `Assertion 'nl >= 0' failed`; after: all 18 `selftest_datacomparefail_*`
cases exit **1** (expected fail), no `Aborted`, well-formed `text:`/`details:`.
- release build (`builddir`): `ninja` clean, zero warnings.
- regression: `./builddir/sdcshield -e zstd19 -t 2000 -n 1` → `exit: pass`.
- x86 non-regression by inspection: platform-independent string formatting, no
arch guards touched.
138 changes: 138 additions & 0 deletions docs/superpowers/plans/2026-10-12-fix-sve-arm64-new-test-failures.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
# Fix: two PR #232 SVE arm64 tests fail their own golden on SVE hardware

## Context

After the `log_yaml` fix (`ffcc7a35`) unblocked the `run selftests` bats
step, the CI job **Build binary for CPU** advanced to `run tests quickly`
and exposed two **newly added** PR #232 tests failing (job
`114901375828`, run `38275921824`):

- `sve512_fcmla_arm` → `Failed at .../sve512_fcmla_arm.cpp:243: golden
worked-example self-check failed (rot 90) ??? test bug, not SDC`
- `sve512_pred_ops_arm` → `Failed at .../sve512_pred_ops_arm.cpp:296: SVE
predicate-network SDC detected (whilelt/svnot/FADDA/FFR/FMAXV)`

Both report on every thread with a deterministic seed → not intermittent
hardware SDC. Local Kunpeng 920 has **no SVE**, so both tests `skip`
(`test compiled with sve`) and cannot reproduce locally; the defects are
proven by code semantics + the ARM FCMLA / ACLE `svmla` definitions.

Both are **golden bugs in the tests**, not SDC and not port defects. They
were masked earlier because CI never reached `run tests quickly`.

## Root cause 1 — `sve512_fcmla_arm.cpp` (rotation dispatch key mismatch)

`fcmla_golden_pair(..., int rot)` dispatches with `switch (rot)` on
**angles** (`case 0/90/180/270`), but every caller passes the loop
**index** `rot = 0..3`:

- self-check (line 238) and chain-golden in `test_init` (line 186) both do
`for (int rot = 0; rot < 4; ++rot) ... fcmla_golden_pair(..., rot)`.

So index `0` hits `case 0` (correct), but indices `1/2/3` all fall into
`default` (the 270° formula → `(8,-6)`). Expected `expect[1] = (-8,6)`
(90°) → self-check fails and reports `rot * 90 = 90`, exactly the CI
message. The hardware dispatch (`fcmla_hw_rot0/90/180/270`, lines 258–261)
is index-keyed, so the chain golden is also computed with the wrong
rotation.

The per-rotation **formulas are correct** (verified against ARM DDI 0616
FCMLA pseudocode: rot 90 → `re += -b_im*c_im; im += b_im*c_re`). Only
the dispatch key is wrong.

## Root cause 2 — `sve512_pred_ops_arm.cpp` (svmla operand order + `_x`)

ACLE: `svmla_f64_x(pg, op1, op2, op3)` = `op1 + op2 * op3` (op1 is the
addend/accumulator). Repo precedent: `svmla_f32_x(pg, vc, va, vb)` = `c +
a*b` ([fma_tail_sve.cpp:64]); `svcmla_f64_m(pg, acc, b, c, rot)`.

Every call here passes `vsrc` as **op1**: `svmla_f64_x(pg, vsrc, vsrc,
vdst)` = `vsrc + vsrc*vdst`, not the documented `fma(src, src, dst)`:

- §1 exact variant: `svmla_f64_x(pg, vsrc, vsrc, vz)` with `vz=0` gives
`vsrc + vsrc*0 = src`; golden is `fma(src,src,0)=src²` → mismatch.
- §1 sentinel check: `_x` is "inactive lanes don't care"; the SVE FMLA
merges with the destination op1 (`vsrc`), so masked-out lanes become
`src`, not `SENTINEL` → "sentinel clobbered".
- §2 and the timed re-loop share the same operand order bug.

So checking inactive-lane preservation with the `_x` form is unsound by
construction; the fix uses the merging `_m` form with the accumulator as
op1.

## Fix

Two independent, minimal units (one patch each, per repo rule 1).

### Unit A — `tests/cpu/arm64/sve512_fcmla_arm.cpp`

Key the golden `switch` on the rotation **index** `0..3` to match every
caller and the hardware dispatch (`case 90→1`, `case 180→2`, default→3),
and document that `rot` is the index (0/90/180/270).

### Unit B — `tests/cpu/arm64/sve512_pred_ops_arm.cpp`

Rewrite §1/§2 and the re-loop to the correct form:

- accumulate into the destination: `svmla_f64_m(pg, dst, src, src)` =
`dst + src*src` (op1 = accumulator);
- use the **merging** `_m` form so masked-out lanes are architecturally
preserved and the sentinel check is sound;
- active lanes carry a finite, exactly-representable addend (`BASE=1.5`)
so the computed lanes have a deterministic byte-exact golden; inactive
lanes keep the NaN `SENTINEL`;
- golden = `fma(src, src, BASE)` for active lanes, `SENTINEL` bit-exact
for inactive ones.

§3 (FADDA) verified correct by inspection and left unchanged. §4 was
initially believed correct too — that proved wrong on the next CI run, see
Root cause 3.

## Root cause 3 — `sve512_pred_ops_arm.cpp` §4 (FFR readback without SETFFR)

After unit A (commit `cf63210a`) and unit B (commit `f335b564`) landed,
CI run `38277871409` still failed `run tests quickly`, but the failure
moved from line 296 to line **264** (the aggregate report), i.e. the only
remaining sub-check failing was §4. The warning is suppressed in the CI
console by the default verbosity, but the run-log artifact
(`test-linux-GCC-arm64-logs`, `quick.yaml`) preserves it:

> `W> sve512_pred_ops: FFR not all-true after mapped LDFF1 (count=0, expected 2)`

The test read FFR with `svrdffr()` **without priming it first**. Per the
ARM SVE first-fault model (confirmed against the ARM first-fault-load
flow: *"SETFFR — reset the FFR to all-ones; LDFF1 … if any subsequent
element faults, the hardware silently suppresses that fault and clears
FFR from that lane onward"*, and the FFR reference: *"可以使用 SETFFR
指令初始化该值"*), an `LDFF1` only **clears** the FFR bit of a faulting
element — it never **sets** a bit. So without `SETFFR` the readback is the
previous, undefined FFR state; on the CI runner that state was 0, giving
`count=0` instead of `2` (VL=128 → 2 doublewords).

Empirically verified on the local GCC 12 aarch64 toolchain: for
`svldff1_f64(all, p)` GCC emits a real `ldff1d` (no relaxation to `ld1`),
and emits `setffr` **only** when `svsetffr()` is present in the source.

### Unit C — `tests/cpu/arm64/sve512_pred_ops_arm.cpp`

Call `svsetffr()` immediately before the §4 `svldff1_f64`, so the FFR bit
for each non-faulting lane is the architecturally defined 1, and the
`svrdffr()`/`svcntp_b64` comparison against the all-true operating
predicate is meaningful. Update the §4 doc comment accordingly.


## Verification (100% real)

- `ninja -C builddir` clean, zero new warnings.
- Both tests on non-SVE Kunpeng 920 → `result: skip`, `skip-reason: 'test
compiled with sve'`, `exit: pass` (no crash / no assert).
- Regression `./builddir/sdcshield -e zstd19 -t 2000 -n 1` → `exit: pass`.
- Correctness of the rewritten golden proven by hand: for `src ∈
{-1.5,-0.5,0.5,1.5}`, `BASE=1.5`, active-lane golden `src²+1.5 ∈
{1.75,3.75}` is exact; FADDA sum over VL (multiple of 4) is exactly 0.
- x86-64 untouched (files are `#ifdef __aarch64__` only).
- Unit C: `objdump -d` of the rebuilt
`builddir/tests/cpu/arm64/libtests_arm64_sve.a.p/sve512_pred_ops_arm.cpp.o`
shows `setffr` immediately followed by `ldff1d {z0.d}, p0/z, …` in the §4
path (grep `setffr` → 2 hits, `ldff1` → 2 hits).
- Final oracle: CI `Build binary for CPU` → `run tests quickly` green.
9 changes: 7 additions & 2 deletions framework/sandstone_run.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,12 @@ void SandstoneMemcmpOrFail::report(const void *_actual, const void *_expected, s
// unit, while scattered offsets suggest a datapath/buffer fault).
// Failure-branch only: the pass path never runs this loop.
{
std::string hist = "lane offsets:";
// log_yaml(char, const char *) expects a pre-formatted YAML
// message: first line = "text:" description, following lines =
// indented details. The heading below is the description, the
// histogram is the detail body; a single-line message would trip
// the parser's second-line assert (debug builds only).
std::string hist = "lane offsets\n";
ptrdiff_t first_bad = -1, last_bad = -1;
size_t count = 0;
for (size_t i = 0; i < size; ++i) {
Expand All @@ -345,7 +350,7 @@ void SandstoneMemcmpOrFail::report(const void *_actual, const void *_expected, s
if (count > 0) {
// per-8-byte lane summary (f64/f32 vector lanes both
// align to 4/8-byte boundaries; report byte offsets)
hist += stdprintf(" %zu mismatching bytes in [%td..%td]",
hist += stdprintf("%zu mismatching bytes in [%td..%td]",
count, first_bad, last_bad);
if (count == 1)
hist += " (single-lane pattern — one bad physical unit fingerprint)";
Expand Down
19 changes: 11 additions & 8 deletions framework/selftest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -889,11 +889,15 @@ static int selftest_crash_run(struct test *test, int thread)
// anything else -> unexpected, reported as failure
// ---------------------------------------------------------------------------
#ifdef __aarch64__
// The framework library compiles at the baseline march (no +sme), so the
// SME probe function lifts its target locally (random.cpp precedent:
// per-function #pragma GCC target).
#pragma GCC push_options
#pragma GCC target("arch=armv9-a+sme")
// The SME probe must NOT lift the march per-function: '#pragma GCC
// target("arch=armv9-a+sme")' hard-fails on upstream GCC 13 (the +sme
// modifier is GCC 14+; only openEuler's GCC 12.3 backport accepts it —
// caught by the ubuntu-24.04 CodeQL runner, 2026-10-12, after PR #231
// landed). SMSTART/SMSTOP are MSR (immediate) encodings fixed by the
// ISA, so emit them via .inst — compiler-independent (GCC 12/13/14,
// clang) and byte-identical to the smstart za / smstop za mnemonics
// (objdump-verified: d503457f / d503447f). Probe semantics unchanged:
// attempt SMSTART; a kernel that has not enabled SME traps SIGILL.
static int selftest_sme_sigill_probe_run(struct test *test, int)
{
pid_t pid = fork();
Expand All @@ -905,8 +909,8 @@ static int selftest_sme_sigill_probe_run(struct test *test, int)
// Attempt to enter+exit streaming ZA mode. If the kernel has not
// enabled SME, SMSTART traps SIGILL here.
__asm__ volatile(
"smstart za\n\t"
"smstop za\n\t"
".inst 0xd503457f\n\t" // smstart za
".inst 0xd503447f\n\t" // smstop za
::: "memory");
_exit(0);
}
Expand Down Expand Up @@ -935,7 +939,6 @@ static int selftest_sme_sigill_probe_run(struct test *test, int)
status);
return EXIT_FAILURE;
}
#pragma GCC pop_options
#endif

static void cause_sigill()
Expand Down
10 changes: 6 additions & 4 deletions tests/cpu/arm64/sve512_fcmla_arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,24 +91,26 @@ struct FcmlaData {
#ifdef __aarch64__

// Scalar golden step for one lane pair, per the DDI 0616 expansion above.
// `rot` is the rotation INDEX 0..3 = 0/90/180/270 degrees, matching both
// the callers (loop index) and the hardware dispatch (fcmla_hw_rot*).
static inline void fcmla_golden_pair(double &acc_e, double &acc_i,
double b_e, double b_i,
double c_e, double c_i, int rot)
{
switch (rot) {
case 0:
case 0: // 0 degrees
acc_e = std::fma( b_e, c_e, acc_e);
acc_i = std::fma( b_e, c_i, acc_i);
break;
case 90:
case 1: // 90 degrees
acc_e = std::fma(-b_i, c_i, acc_e);
acc_i = std::fma( b_i, c_e, acc_i);
break;
case 180:
case 2: // 180 degrees
acc_e = std::fma(-b_e, c_e, acc_e);
acc_i = std::fma(-b_e, c_i, acc_i);
break;
default: // 270
default: // 3 -> 270 degrees
acc_e = std::fma( b_i, c_i, acc_e);
acc_i = std::fma(-b_i, c_e, acc_i);
break;
Expand Down
Loading
Loading