Skip to content

GI-FPU-002: three named cascade entry points are the entire remaining gap to a complete falcon M7 image (attitude#tick, ekf#estimate, position#tick) — everything else in the chain now works #1069

Description

@avrabe

Summary

Three named functions are the entire remaining distance between the PulseEngine toolchain and a complete falcon flight-cascade image for the Cortex-M7. Everything else in the chain now works: the components publish with all required markers, meld fuses and packs them, and the result compiles to a self-contained, executing M7 image. Only these three fail, all on GI-FPU-002.

Filing fresh because the prior anchors are closed (#369#782#869#881, all CLOSED) and GI-FPU-002 is currently tracked only inside the #242 epic, so there is no actionable item for it.

The three functions

pulseengine:falcon-cascade/attitude@0.7.0#tick
  GI-FPU-002: VFP register file exhausted (S0..S15 all live) — f32 expression too deep (phase 1)

pulseengine:falcon-cascade/ekf@0.7.0#estimate
  GI-FPU-002: VFP register file exhausted (S0..S15 all live) — f32 expression too deep (phase 1)

pulseengine:falcon-cascade/position@0.7.0#tick
  GI-FPU-002 phase 2: caller-saved VFP D-register file exhausted (D0..D7 all live) — f64 expression too deep

Consequence, measured on the fused image:

stage exported in the M7 image?
rate yes
mixer yes
attitude no
position no
iekf / ekf no

2 of 5. The cascade cannot close a control loop on target without the other three.

Fully public repro — no jess-private inputs

# 1. pull the six published components (anonymous)
for c in iekf position attitude rate mixer; do
  TOK=$(curl -s "https://ghcr.io/token?scope=repository:pulseengine/falcon/$c:pull&service=ghcr.io" | jq -r .token)
  D=$(curl -s -H "Authorization: Bearer $TOK" -H "Accept: application/vnd.oci.image.manifest.v1+json" \
      https://ghcr.io/v2/pulseengine/falcon/$c/manifests/1.134.1 | jq -r .layers[0].digest)
  curl -sL -H "Authorization: Bearer $TOK" https://ghcr.io/v2/pulseengine/falcon/$c/blobs/$D -o $c.wasm
done

# 2. fuse + pack (meld 0.52.0) — accepts, 1 page / 64 KB
meld fuse --memory shared --pack-rebase iekf.wasm position.wasm attitude.wasm rate.wasm mixer.wasm -o cascade.wasm
loom optimize cascade.wasm -o cascade.loom.wasm

# 3. lower (synth 0.55.0)
synth compile cascade.loom.wasm --relocatable -t cortex-m7dp -o cascade.o     # 3 skips, 18 functions
synth compile cascade.loom.wasm -t cortex-m7dp --cortex-m -o cascade.elf      # EXEC, 65,452 B

The self-contained image is real and runs: I have it executing on an RT1176 Renode model — linear memory initialised byte-exact (verified at non-zero probes), 214,696 instructions retired, PC in the export region. So this is not a paper artifact; it is a working image that is simply missing three functions.

The two sub-problems

1. Phase-1 S-register exhaustion (attitude#tick, ekf#estimate) — deep f32 expression trees in the control math exceed the caller-saved S-register file. D8..D15 are callee-saved and currently untouched; using them is push/pop in prologue/epilogue and would roughly double the available file.

2. Phase-2 D-register exhaustion (position#tick) — this one is worth a second look, because position is f32-only code. The f64 pressure comes from synth's own inline-f64 lowering of the i64↔float conversions added in v0.52. The --builtins routing proposed in #869 (__aeabi_ul2f/l2f/ul2d/l2d, core-register based, zero VFP pressure) was described in that issue's acceptance comment but never implemented — the lowering went inline-f64 instead.

That choice has a second consequence worth stating: it pins any conversion-carrying function to cortex-m7dp. mixer (no conversion) lowers on m7dp, m7 and m4f; rate lowers only on m7dp. So the estimator cannot be built for the single-precision M4 core it is architecturally assigned to — not for lack of hardware capability, but from the lowering strategy for one conversion.

Definition of done

Those three symbols reaching nm → T in the fused image — i.e. 5 of 5 cascade stages exported, which is a complete falcon cascade for the M7.

Standing offer

Point me at any branch and I will run it against the real fused cascade and the per-stage components and report the delta by symbol name, including reading the generated code for soundness rather than only checking that symbols appeared. That loop has caught two "green in isolation, no movement in the real op-mix" cases already (#369#782, #869→v0.52), so it is worth running before a release rather than after.

No urgency implied — rate and mixer lower today and there is on-target work in front of me regardless. This is a request to track, not to prioritise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions