Five instructions total — two scalar converts, two vector converts, one widening FMA. The encoding trick: the 2-bit fmt field is full (S/D/H/Q), so BF16 identifies itself through new rs2/vs1 sub-field codes inside the existing convert encodings.
| Encoding | Semantics & flags | |
|---|---|---|
| fcvt.bf16.s rd, rs1 (Zfbfmin) | OP-FP, funct5 01000 (FCVT), fmt=H, rs2-field = 01000 | Narrowing FP32 → BF16, rounds per rm. Flags: Overflow, Underflow, Inexact, Invalid. |
| fcvt.s.bf16 rd, rs1 (Zfbfmin) | OP-FP, fmt=S, rs2-field = 00110 | Widening BF16 → FP32 — EXACT: shift left 16, zero-fill, NaN-box. Only Invalid (sNaN input). |
| vfncvtbf16.f.f.w vd, vs2, vm (Zvfbfmin) | OP-V VFUNARY0 (funct6 010010), vs1-code 11101, OPFVV | Vector FP32 → BF16 per frm; SEW must be 16 (else reserved). EEW: vs2=32 in, vd=16 out. |
| vfwcvtbf16.f.f.v vd, vs2, vm (Zvfbfmin) | VFUNARY0, vs1-code 01101 | Vector BF16 → FP32, exact. |
| vfwmaccbf16.vv / .vf (Zvfbfwma) | OP-V funct6 111011, OPFVV / OPFVF | BF16 × BF16 with the UNROUNDED product added to the FP32 accumulator in vd; single rounding per frm. .vf reads the scalar BF16 from an f-register (NaN-box checked). All four flags possible. |
The FMA’s fused-ness comes cheap: an 8×8-bit significand product
needs at most 16 bits, which FP32’s 24-bit significand holds exactly
— so the instruction is precisely equivalent to the documented
expansion (vfwcvtbf16 both operands, then vfmacc; or
fcvt.s.bf16 + vfwcvtbf16 + vfmacc.vf for the scalar form). No
extra internal precision required.
Hardware Designer Notes
If you build one BF16 thing, build vfwmaccbf16: it is the inner loop of every transformer inference kernel, and its datapath is your existing FP32 FMA with an 8×8 front end. The converts alone (Zfbfmin/Zvfbfmin) are days of work; budget the FMA verification against your FP32 suite with truncated stimulus.
Minimal Linux-boot hart MUST
- Decode the new rs2/vs1 sub-field codes exactly; neighboring convert encodings remain their old selves and SEW≠16 vector forms are reserved
- For vfwmaccbf16: feed the 16-bit exact product into the existing FP32 FMA datapath — no rounding between multiply and add
- NaN-box-check the .vf scalar operand like any other vector-scalar FP read
MAY simplify / trap-and-emulate
- Share the FP32→BF16 narrower with your FP32 rounder (it is a 16-bit-shorter tail of the same logic)
- Implement Zvfbfwma as double-pumped BF16 lanes over the FP32 accumulators — the area math that makes BF16 worthwhile
Check yourself — BF16 instructions
1.Why can FCVT.S.BF16 never be inexact, while FCVT.BF16.S can raise Overflow/Underflow/Inexact?
2.What makes vfwmaccbf16 'fused', and what's it equivalent to?
3.How do the BF16 converts squeeze into the OP-FP encoding without a new fmt code?