Expand description
The planner: predicts throughput and resources for every profile and picks one from a LUT and DSP budget.
A Profile is fb/sha/sc plus fused; written as four numbers
(15/11/3/1) the last one is 1 for one batch-compress machine and 0 for
fused mode, the same order as ED25519_SCALABLE_PROFILE. Budgets (Budget) are
percentages of the project caps: LUT_CAP (260,000; up to 200 %) and
DSP_CAP (7,000; up to the U280’s 9,024). The planner reports the
smallest LUT percentage that still gives a working signer
(min_lut_percent) and the DSP percentage beyond which more DSPs do not
help (useful_dsp_percent).
§Throughput model
Profile::cycles_per_sign is the slowest of these stages:
| Stage | Cycles per signature | 15/11/3/1 |
|---|---|---|
| fixed-base machines | FB_BUNDLES / fb / UTIL_MACHINE (fused: plus the SHA term) | 26.94 |
| SHA-512 rings | 3 · 81 / sha / UTIL_SHA | 24.93 |
| scalar rings | 2 · 32 / sc / UTIL_RING | 23.70 |
| batch compression | CP_BUNDLES / CP_BATCH / UTIL_MACHINE | 13.63 |
| compress credits | (FB_BUNDLES·32 + CP_BUNDLES·CP_CONTEXTS + CREDIT_OVERHEAD) / 2048 | 23.25 |
| admission | 2 | 2.00 |
The utilizations are conservative (the fixed-base machines measured
0.99–0.997); CREDIT_OVERHEAD is fitted to measured runs. 15/11/3/1
measured 26.43 against the predicted 26.94.
§Resource model
yosys_calibrated uses Yosys leaf maps (in mapping/) plus structural
adjustments for blocks not yet mapped; structural is a hand estimate.
DSPs trade for LUTs the way Vivado does under synth_design -max_dsp: a
multiply tile without a DSP becomes fabric, and spare DSPs absorb wide
adders (USE_DSP).
The largest uncertainty: about 8,600 of each multiplier’s LUTs are
its 225 chain additions P = PCIN + A·B. Yosys packs that pattern into
DSPs for 7-series but not UltraScale+; Vivado infers such cascades.
calibrated assumes packing (15/11/3/1 ≈ 219k LUT); with
yosys_calibrated(false) it would not fit 260k. Only Vivado settles it.
Every resource number here is an estimate, and the clock
(DESIGN_MHZ) is a target until routed.
§Using it
cargo run --release --bin ed25519_plan -- --lut 100 --dsp 100 --mhz 205
cargo run --release --bin ed25519_plan -- --lut 100 --dsp 100 --target 7000000
cargo run --release --bin ed25519_plan -- --sweep
cargo run --release --bin ed25519_plan -- --lut 100 --dsp 100 --out plans/s100
cargo tuner-ed25519 # at the repository root: the planner TUI, Ed25519 only--out writes the plan, its ED25519_SCALABLE_PROFILE value and a
Vivado synth.tcl that rejects an over-budget result. The fast way to
iterate on the model is tools/hostmodel (no hardware build).
Structs§
- Block
Cost - One block’s resources, per instance.
Profile::estimatemultiplies each row by the instance count and then trades DSPs for LUTs usingtiles/lut_per_tileandadder_dsps/lut_per_adder_dsp. - Budget
- Planner request: resource allowances and the clock to project at.
- Cost
Table - Per-block costs used by
Profile::estimate. Built either bystructural(hand estimate) oryosys_calibrated(Yosys leaf maps plus structural adjustments); replace rows with Vivado measurements as they become available. - Estimate
- Resource and throughput estimate of a profile under a DSP limit, as
returned by
Profile::estimate. All values are model output, not measurements. - Profile
- A buildable signer profile: how many of each replicated block the
signer instantiates.
Profile::env_valueturns it into theED25519_SCALABLE_PROFILEstring thatbuild.rsreads.
Constants§
- CP_
BATCH - Points per compression batch (one batch inversion amortized over them).
- CP_
BUNDLES - Bundles of one 32-point batch compression (compiler output); shared by
the
CP_BATCHpoints of the batch. - CP_
CONTEXTS - Batch-compress machine contexts (barrel slots, each holding one batch).
- CREDIT_
OVERHEAD - Credit hold time in cycles beyond the two programs’ issue latency
(queueing, batch filling, hashing). Calibrated from native simulation: with 1,024
credits, 12/6/2/1 and 13/8/2/1 measured 45.7 and 44.1 cycles/signature,
i.e. ~45k cycles per credit against 15.7k + 22.0k of issue latency for
the programs of that time (492 fixed-base bundles, the older compress
machine). With today’s programs the issue latency in the formula is
FB_BUNDLES·32 + CP_BUNDLES·CP_CONTEXTS= 12,544 + 27,072 cycles. Rechecked 2026-10-19 on fix13 8,0,2,1: 1,026 signatures in flight at 46.46 cycles/signature is a mean hold of ~47.7k cycles, i.e. 39.6k + 8.1k. - DESIGN_
MHZ - Design clock in MHz (the project’s target frequency, not yet a routed result). Used to turn cycles per signature into signatures per second.
- DEVICE_
BRAM36 - Physical BRAM36 count of the xcu280.
planrejects profiles above it; there is no separate project BRAM cap. - DEVICE_
DSP - Physical DSP48E2 count of the xcu280 (device data sheet). Hard ceiling on any DSP budget.
- DEVICE_
LUT - Physical LUT count of the xcu280 (for reference; budgets use
LUT_CAP). - DSP_CAP
- Project DSP cap (100 %), in DSP48E2 blocks. Below the device’s
DEVICE_DSP, so DSP percentages may exceed 100 (up to ~128.9 %). - FB_
BUNDLES - Bundles (issue slots) in the fixed-base program, from the microcode
compiler (see
programs). Each bundle occupies one machine slot, so this is the machine time per signature in cycles at full utilization. - FUSED_
BUNDLES - Bundles of the fused fixed-base + per-point inversion program (compiler
output). Used instead of
FB_BUNDLESin fused mode. - LUT_CAP
- Project LUT cap (100 %), in LUTs. A project budget, well below the
device’s
DEVICE_LUT. - SIGN_
CONTEXTS - Sign contexts (requests in flight). Caps the compress credit pool.
- UTIL_
MACHINE - Sustainable utilization of a barrel field machine (0.997 measured in simulation; 0.97 kept as margin). Planned builds on the shared SHA line (native simulation, 2026-10-16): 9,0,2,1 ran 41.83 cycles/signature on a full line (effective utilization 1.04; this model says 44.90), 44.76 on a fold10 line (0.97) and 4,0,1,1 96.18 on fold4 (1.02; model 101.03), so the margin covers the slowest measured line.
- UTIL_
RING - Assumed sustainable utilization of a scalar ring (not measured).
- UTIL_
SHA - Sustainable utilization of a SHA-512 ring, as a fraction of its ideal
rate (conservative simulation fit, see
cycles_per_sign).
Functions§
- calibrated
- The planner’s default cost table:
yosys_calibratedwith packed post-adders. Useyosys_calibrated(false)for the pessimistic bound. - candidates
- Every profile the planner considers: 1..=40 fixed-base machines,
1..=24 SHA rings, 1..=6 scalar rings, with and without fusing (the same
ranges as
crate::frontier). The search is exhaustive, so these ranges bound what the planner can return; at 200 % of the LUT cap the best profile stays well inside them. - describe
- Human-readable report of a plan: profile, budget, resource estimate with its source, cycle model and the synthesis settings to use.
- min_
lut_ percent - Smallest LUT percentage at which some profile fits under
dsp_percent(the lower end of the LUT slider), counting only profiles whose BRAM fits the device. Infinity if no candidate exists. - plan
- Best profile for a budget: highest rate (capped at the target), then
fewest LUTs, then fewest DSPs.
Nonewhen nothing fits. A profile fits when its LUTs, DSPs and BRAM36 are within the budget and the device. - plan_
json - JSON record of a plan (
schemascalable-plan-1).statusis alwaysestimate-unmeasured; measured counts come from themeasured.jsonthatsynth_tclwrites. - structural
- The built-in structural estimate: hand-counted from the block structure, never synthesized. The crate’s unit tests use it because it does not depend on mapping results.
- synth_
tcl - Vivado out-of-context synthesis gate enforcing the plan’s budget.
- useful_
dsp_ percent - DSP percentage above which no profile within 200 % LUTs uses more DSPs: the DSP count of the best plan with the largest LUT and DSP allowances.
- write_
plan - Write
plan.json,plan.txt,synth.tclandconstraints.xdctodir. Nothing is launched; the files are inputs for a reserved synthesis host. The XDC constrains the clock port to the budget’s assumed clock (period in ns = 1000 / MHz). - yosys_
calibrated - Leaf costs from Yosys 0.55
synth_xilinx -family xcupmaps of the generated netlists (mapping), withpackedselecting whether the multiplier’s 225 column-chain additions are absorbed into the DSP48E2 post-adders (P = PCIN + A*B).