IEEE binary16 — the ML-era storage format — arrives as fmt code 10 (H), depending on F, with NaN-boxing one level down: a half sits boxed inside a single (inside a double inside a quad, recursively, as the register file allows).
Zfh — the full arithmetic set
Every S instruction, at fmt=H: FLH/FSH (FLH NaN-boxes the loaded value; FSH ignores all but rs2’s low 16 bits; both bit-transparent), the arithmetic five plus four fused multiply-adds, integer converts (W/WU always, L/LU on RV64), the FCVT triangle to S — and D and Q when present — FSGNJ[N/X].H, compares, FCLASS.H, and the FMV pair: FMV.X.H sign-extends the 16-bit encoding into rd (sign-bit copies, NaN payloads intact); FMV.H.X NaN-boxes rs1’s low 16 bits into the f-register.
Zfhmin — storage only
| Detail | |
|---|---|
| Included | FLH, FSH, FMV.X.H, FMV.H.X, FCVT.S.H, FCVT.H.S (+ FCVT.D.H/H.D with D, FCVT.Q.H/H.Q with Q). |
| Excluded | ALL arithmetic, compares, classify — and even FSGNJ.H, since FSGNJ.S moves register values regardless of what format they hold. |
| The compute pattern | Convert up → operate in single → convert down. Faithful (correctly rounded) for add/sub/mul/div/sqrt. |
| Integer-convert emulation | int8/16 → S → H is exact; int32 needs the D detour (or accept 1 ulp via S); likewise int64 needs Q or the tolerance. |
Hardware Designer Notes
Half-precision converters are small (the 11-bit significand path is trivial next to your existing single/double units); the real cost of full Zfh is verification across five formats × rounding modes × NaN-boxing levels. Zfhmin is the sweet spot unless you’re building for ML inference kernels that genuinely stay in fp16.
Minimal Linux-boot hart MUST
- For Zfhmin: only the pack/unpack and convert paths — the FPU datapath stays single/double width
- Enforce NaN-box checking on H operands (upper FLEN−16 bits all ones, else treat as canonical NaN) and FSH’s ignore-upper-bits rule
MAY simplify / trap-and-emulate
- Implement Zfh arithmetic by internally widening to single and rounding back — but the FMA must then be genuinely fused at half precision to avoid the documented 1-ulp deviation
- Choose Zfhmin over Zfh (RVA23 mandates only Zfhmin): it captures most of the storage-format value at a fraction of the verification surface
Check yourself — half-precision
1.What's the design thesis behind Zfhmin's instruction selection?
2.FMV.X.H moves a half value to an integer register on RV64. What fills bits 63:16?
3.Why does converting a 32-bit integer to half precision need a detour through DOUBLE for exact rounding?