Whole-engine fabric budget: about 2.5x the DE25-Standard in logic; architecture and board to decide #170
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
bcox/tymbal#170
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
An estimate of what the whole instrument costs on the fabric, made on 2026-10-06 while stage F9.1b slice 1 (branch
f9-1b-slice1, commit 7523bbcd) was closing. It answers one question: does every layer engine fit the DE25-Standard, and if not, by how much.Nothing was run for the estimate. Figures are read from fit reports, the price ledger and the C++ sources, and each is labeled measured, derived or guess. The estimate is joan's (the FPGA specialist agent); the license and form-factor checks at the end were made separately.
Verdict
Device: Agilex 5 A5ED013BB32AE4SCS, 46,800 ALMs, 358 M20K, 188 DSP blocks. Engine clock 250 MHz; a 48 kHz sample is 5,106 cycles.
"Whole image now" is the
hps_lwcompile at 7523bbcd, which plays 3 of the 19 factory VA patches at ratio 1, one layer, 128 voice indices.The measured anchor
The part of the verdict that is not a guess:
u_layeris 12,388 ALMs in place (measured,golden_top.fit.rptby entity).The remaining VA paths are a guess of 4k to 9k ALMs, from slice 1's 4,599 ALMs for about five features. The other engines' 45k to 70k is a sum of guesses by analogy: only one composed layer has ever been fitted. That is the weakest number here.
What binds, and why
ALMs.
mod_op1,974, the bit-serial reciprocal 1,310, the envelope 1,224,svf_coefficients804,sync_slave792.M20K.
Bulk storage is off-chip on any board.
fabric::kRegionPages) against 64 MB of fabric SDRAM and under 1 MB of M20K in total.DSP, pooled. One 32x32 pool member gives about 3,600 products a sample at 70% use.
Cycles. Each engine's pass must fit 5,106 on its own. These need replicated lanes, paid in ALMs, whatever the board:
Per engine
Twelve kinds are registered (
LayerKind,plugin/program.h). Multiplies are per voice-layer per 48 kHz sample, counted from source by hand, not instrumented. Almost none fits one 27x27: operands are 32x32 or 21x39, so a multiplier is 2 DSP blocks.The factory bank averages 1.4 layers a patch.
What the answer hinges on
The step up, if it is taken
The device is the Agilex 5 E-Series 065B: 222,400 ALMs, 1,611 M20K, 846 DSP blocks (Altera's product tables, 2026.08.07). That is 4.75x the logic and 4.5x the memory of the 013B.
Cheapest measurements, in order
dsp/fixed.h's multiply over the factory bank, giving measured products a voice-sample per patch and the FM ratios patches actually derive. Replaces every hand count above.//plugin:state_censuswith patch and ratio named (minutes). Settles M20K per slot, which the ledger still marks unverified.CoupledMode) or the FM tick with a 16x1025 wide decimator (a day or two). The only way to a second ALM data point. More than about 5k ALMs beyond shared primitives confirms 2x-plus.hps_lwfor A5ED065BB32AE4S before buying (free, about an hour), to see whether timing holds at 250 MHz on the larger die.A trigger that needs no extra work: if the full VA layer passes about 24k ALMs on the current path during the ratio-4 stage (F9.1c), the purchase is decided without item 3.
Decisions this ticket is for
Sources
docs/superpowers/ledgers/2026-10-03-fabric-prices.mdon branchf9-1b-slice1: rows 15a-c, 16, 17, 18a-h; "The ratio-4 price, stage F9.1a"; "The second voice path, stage F9.1b slice 1".hps_lwcompile and the layer's standalone fit at 7523bbcd (golden_top.fit.rpt,va_layer_fit.fit.rpt; build outputs, not in git).docs/superpowers/specs/2026-10-03-f4-fabric-shape-design.md;fabric/fabric.h(kRegionPages);plugin/program.h(LayerKind).Measurements 1, 2 and 4 of "Cheapest measurements", run 2026-10-06 on main at
36827bd2. Measurement 3 (a second engine's skeleton fit) is not done.4.
hps_lwcompiled for A5ED065BB32AE4S (measured)The current board image with only the part name changed. 11 minutes, no errors, no critical warnings.
pll_inst|pll_outclk1, needs 250 MHz): 268.1 MHz, restricted to 258.87 MHz by minimum pulse width.1. Products per voice-layer per 48 kHz sample (measured)
Branch
m170-software-counts(five commits on36827bd2, not merged): a counting mode forMulExactandLerpindsp/fixed.h, aDSP_MULwrap on the 232 productsdsp/wrote on raw integers, and//plugin:product_census. One note, one voice, every factory patch, at its demo key and its low and high keys; mean over sustain, and the worst single sample.bazel run --copt=-DTYMBAL_PRODUCT_CENSUS //plugin:product_censusfixed.h-only count: 37% of FM, 34% of unvoiced, 32% of partial, 27% of VA.What the count is not: it counts products performed, and the C++ skips a unity gain, a bypassed band and an untaken branch that a fixed pipeline would spend a turn on. Effect returns were fed silence. Multiplies by small literals and by a sign are left out. Constant operands could be separated only to a floor of 0 to 8% by kind.
2. Hot state per slot (measured,
//plugin:state_census,-O3)Bytes of the C++ layer object a held note's render touches. Not RTL state bits; region storage, tables and patch data reached by pointer are not seen.
-O0disagreement is explained and-O3stands: at-O0a by-value read of aSampleis a memory copy the sanitizer hooks do not trace (moog-lead reads 632 B, less than its FIR's history).-O1agrees with-O3on nine patches.What this does to the verdict
Measurement 3, run 2026-10-06: a second engine's skeleton, fitted.
rtl/dsp/modal_skeletonon branchm170-modal-skeleton(714a2d19, not merged):dsp::ModeBank<kModes, CoupledMode>'s whole per-mode work for V voices of M modes in K lanes, a mode a cycle a lane, eleven multiplies a mode. Bit-exact against the header in Verilator (1.26M mode-steps and 93,600 reads at 78 voices of 128 modes in 2 lanes, 0 mismatched; eight injections, all caught).Fits (measured, A5ED013BB32AE4SCS, alone at 245.76 MHz)
pool_multiplyat 65 to 76 each, four 23 x 39 rotation multipliers at 14 to 18 each); RAM decode and muxes 106; everything else 1,040 (the reads' accumulate, round and saturate 477, the lane's control 163, the inject sums 169, the rotation's adds and requantize 149, delay lines 83).Against the ticket's test
The test was: more than about 5k ALMs beyond shared primitives confirms 2x-plus.
ModeBank::RefreshMode(two modes a voice-sample, each aScaleByOctaves, twoSinelookups and a divide, and 64 more bits a mode, about 52 M20K derived); the junction forces and ceilings; the strings junction, a second walk of a voice's modes; the exciters and their envelopes; the matrix; the envelope follower; the strip. The lane also reads the sites afterAdvancewhere the header reads them before, and the correction for weights that move is not priced.What it does decide
Logic was the ticket's binding resource. For this engine it is not: block RAM and DSP are.
So on the DE25-Standard, full-polyphony modal and the full VA layer do not coexist, whatever the architecture; modal at about a quarter of that load does. On the 065B the bank at 128 x 128 is about 3% of the ALMs, 14% of the M20K and 10% of the DSP blocks (derived from the device totals).
Decision (bcox, 2026-10-07)
Both boards are targets: the DE25-Standard and the Agilex 5 E-Series 065B Modular Development Kit.
Order of work
What this settles, of "Decisions this ticket is for"
Recorded in
CLAUDE.mdunder "Targets".