rhdl_fpga_planner/lib.rs
1//! Planner for one U280 shared by Ed25519, DSig and a SHA-512 line.
2//!
3//! # Building for Wolverine's U280
4//!
5//! The planner runs on the host; it chooses configurations and does not emit a
6//! U280 image. From the workspace root, `cargo tuner` runs the planner for both
7//! papers and `cargo tuner-ed25519` selects Ed25519 alone. For just this library,
8//! use `cargo build --locked -p rhdl_fpga_planner`.
9//!
10//! Take the selected configuration to the front-page build instructions for
11//! [Ed25519](../rhdl_ed25519_scalable_core/index.html#building-for-wolverines-u280)
12//! or [DSig](../rhdl_dsig_scalable_core/index.html#building-for-wolverines-u280):
13//! generate RTL, package and link with Vitis 2023.2, then check routed acceptance.
14//! A planner estimate is not evidence that a configuration fits or meets timing.
15//!
16//! Run commands from the workspace root. Before compilation or RTL generation,
17//! record ownership in `PROJECT_COORDINATION.md` and
18//! `/home/sahasta/Development/FPGA_COORDINATION.md`, and use the applicable
19//! nonblocking `local-heavy.lock`; `crates/ed25519/tools/bounded.sh` wraps local
20//! Cargo commands with that lock and resource limits. Reserve Wolverine builds
21//! in both ledgers too, then use `crates/dsig/tools/with-u280-lock.sh` to hold
22//! `u280.lock`. Do not bypass a busy lock.
23//!
24//! # The question it answers
25//!
26//! *Given a budget of LUTs, DSPs, BRAM and URAM, how should the chip be
27//! divided, and how many signatures and how many verifications per second
28//! does it deliver?* Two papers ask it with different modules ([`Mode`]):
29//!
30//! - **Ed25519 paper** ([`Mode::Ed25519`]): Ed25519 signing and Ed25519
31//! verification.
32//! - **DSig paper** ([`Mode::Dsig`]): DSig signing and DSig verification,
33//! each with the Ed25519 work it relies on.
34//! - **uBFT modes** ([`Mode::UbftEd25519`], [`Mode::UbftDsig`]): the same
35//! schemes as a service beside a uBFT replica. Only uBFT modules take
36//! part ([`Component::ubft`]). The replica's footprint comes off the
37//! whole device, and the headline is a consensus slot's crypto time
38//! rather than a rate ([`ubft`]).
39//!
40//! In both, a **SHA-512 line** is shared by every module that hashes on it.
41//! Its allowance comes out of the budget (65k LUTs and 20 DSPs of the
42//! default 485k and 4,520): the **LUT split** is SHA | DSig | Ed25519 in the
43//! DSig paper and SHA | Ed25519 in the Ed25519 paper, each summing to 100 %.
44//!
45//! # Two sides: signing and verifying
46//!
47//! Signing and verification are independent services: a chip can be built
48//! to sign a lot and verify little, or the opposite. So the budget is split
49//! into a **sign side** and a **verify side** by two powers ([`Powers`]),
50//! and each side reports its own delivered rate. A side can need several
51//! modules ([`Side::roles`]):
52//!
53//! | Paper | Sign side delivers | needs per operation | Verify side delivers | needs per operation |
54//! |---|---|---|---|---|
55//! | Ed25519 | Ed25519 signatures | 1 Ed25519 sign | Ed25519 verifications | 1 Ed25519 verify |
56//! | DSig | DSig signatures | 1 DSig sign + 1/K Ed25519 sign | DSig verifications | 1 DSig verify + (1 − h) Ed25519 verify |
57//!
58//! `K` is DSig's batch size (one Ed25519 signature certifies `K` one-time
59//! keys) and `h` the fraction of verifications that find their batch's
60//! root already verified ([`Context::cache_hit`]).
61//!
62//! # How a plan is made
63//!
64//! 1. **Shares.** The SHA line's allowance comes off the top; each other
65//! module gets a percentage of what is left of the LUTs, DSPs, BRAM and
66//! URAM ([`shares`], [`Budget::rest`]).
67//! 2. **Best build per share.** Each module is a [`Component`]: given a
68//! share it returns the best build that fits ([`Plan`]): resources,
69//! **capacity** (operations per second), latency, and the SHA-512 blocks
70//! it hashes.
71//! 3. **Lending** ([`plan_chip`]). What modules leave unused of their share
72//! is counted in real units and lent to the module whose re-plan raises
73//! the delivered rates most, until no module gains. The line's unused
74//! allowance (its pipelines come in steps) is lent too.
75//! 3b. **The remainder.** What lending could not turn into delivered rate
76//! is still handed out, pro rata by power and then to whoever can use
77//! it, so every module grows (more capacity, more headroom) and nothing
78//! sits idle that a module could use.
79//! 4. **Delivered rates** ([`deliver`]). A side delivers the smallest
80//! `capacity / need` over its roles. If both sides together want more
81//! SHA-512 blocks than the line supplies, both are scaled down to fit.
82//! 5. **Background** ([`layout`], DSig paper): the budget is the HBSS
83//! foreground plus the EdDSA background (summing to 100 %), and the
84//! background is split between Ed25519 sign and verify (100 %); either
85//! can be set or chosen to deliver the most.
86//! 6. **Splitting between sides** ([`balance_mix`], key B in the TUI):
87//! the sign power that maximizes `min(sign, verify / mix)`, where the
88//! **mix** is the verifications wanted per signature. The powers can also
89//! be set by hand.
90//!
91//! Every number is a *model* unless the component marks it
92//! [measured](Plan::measured) (synthesized or routed in Vivado).
93//!
94//! The `tui` feature adds [`tui::run`], the interactive front end.
95//!
96//! # Where to go next
97//!
98//! | You want to... | Read |
99//! |---|---|
100//! | understand how a plan and its build config come about, step by step | [`decisions`] (start here) |
101//! | change what a paper needs per operation | [`Mode::need`], then [`deliver`] |
102//! | change how the budget is split | [`apply_layout`], [`layout`], [`balance_mix`] |
103//! | add a module | [`Component`] and [`Plan`]; an example is `rhdl_ed25519_scalable_core::planner` |
104//! | plan crypto for uBFT | [`ubft`] (replica, baseline, slot time), then [`Mode::admits`] |
105//! | change the screen | [`tui`] (`App` holds the state, `draw` renders) |
106//! | see the whole chip | the root crate `rhdl_signatures`: its guide and `tuner` binary |
107
108#![warn(missing_docs)]
109
110pub mod decisions;
111
112/// The interactive terminal front end (feature `tui`).
113#[cfg(feature = "tui")]
114pub mod tui;
115
116// The model, one file per step of "How a plan is made". Everything is
117// re-exported here, so the crate's API stays flat (`rhdl_fpga_planner::Plan`).
118mod component;
119mod delivered;
120mod layout;
121mod lending;
122mod resources;
123mod shares;
124pub mod ubft;
125pub mod build_apply;
126mod workload;
127
128pub use component::*;
129pub use delivered::*;
130pub use layout::*;
131pub use lending::*;
132pub use resources::*;
133pub use shares::*;
134pub use workload::*;
135
136#[cfg(test)]
137pub(crate) mod demo;
138#[cfg(test)]
139mod tests;