本文档给出流水线架构、容器约定与全部关键数学推导,并说明各格式的特殊值处理与 SIMD 子乘器原理。
| 级 | 名称 | 功能 |
|---|---|---|
| S1 | UNPACK | 按 fmt 译码格式参数(F/EW/bias/align);左对齐尾数容器;检测 NaN/sNaN/Inf/Zero/次正规;INT 绝对值转换;计算 E = ea + eb - bias;生成 NaN 结果与 NV 条件 |
| S2 | MUL | 4 个 12x12 子乘器,输入按模式 mux:标量 = 经典 24x24 分解(aa/ab/ba/bb 四象限),2-lane = 对角子乘器,4-lane = 每子乘器一路 |
| S3 | NORM | 标量:合并 4 象限为 48 位积 + 前导零计数 + 按格式对齐;lane:每路 24 位积独立归一化 |
| S4 | ROUND | 普通/次正规两路径舍入增量(fp32_rnd_inc 例化) + 次正规字段对齐 |
| S5 | PACK | 阶码修正、上溢(按模式/格式)、特殊值裁决、按格式打包;SIMD 结果/标志拼装 |
复位:valid 链(控制 FF)异步低复位;数据 FF 不复位(操作数缓冲类,项目风格约定)。反压:out_ready 拉低时全流水线冻结(无旁路),in_ready = ~stall。
尾数容器统一左对齐在 24 位:隐式位固定 bit 23,次正规尾数同样左对齐到 [22:23-F]。
sig_c = (exp_zero ? 0 : 2^23) | (frac << (23 - F))
value = sig_c * 2^(e - bias - 23) // 与 F 无关!
设乘积 p = sig_c_a * sig_c_b(48 位),归一化 p_norm = p << lz(前导 1 落在 bit 47), 再按格式对齐 p_align = p_norm >> (23 - F)。可推出:
value = p_align * 2^(ea + eb - 2*bias - 11 - F - lz) // (1)
m = p_align[47:24] // F+1 位有效尾数(有效位落在低 F+1 位)
value = m * 2^(Ef - bias - F) // (2)
(1)=(2) => Ef = ea + eb - bias + 1 - lz = E + 1 - lz // 与 FP32 完全同式!
关键结论:左对齐容器使指数公式与格式无关(E3 = E + 1 - lz),格式差异只剩三处小 mux:对齐移位 23-F、打包位切片、进位位选。
次正规字段 field = round(value * 2^(bias+F-1)),代入 (2) 与 p_align = m*2^24 + low:
field = round(p_align >> k), k = 25 - Ef // 标量(与 F 无关!)
G/R/S 取自 p_align 的 bit k-1 / k-2 / [k-3:0](k 超界时按 48/49/50 守卫截断,粘滞位恒真)。 舍入进位:普通路径在 bit F+1(mr = m + inc);次正规"舍入进最小正规数"在 bit F。
IEEE 754 §7.4(指数域无界舍入):上溢 ⟺ 舍入结果超过最大有限数。
of = (Ef > 2^EW-1) || (Ef == 2^EW-1 && (~no_inf | 舍入后尾数全 1))
- 有 Inf 格式:阈值 2^EW-1(exp 全 1 即 Inf/NaN);
- E4M3FN(无 Inf):exp=1111 且 mant!=111 是有限值(256~448),仅当舍入到 480(尾数全 1)才算上溢,上溢返回唯一 NaN(1111.111)并置 OF+NX;
- 上溢结果按舍入模式给 ±Inf 或 ±max(RTZ、RDN/RUP 按符号)。
采用舍入前 tininess(x86/ARM/glibc 惯例):Ef <= 0(精确值 < 2^(1-bias))且结果不精确即置 UF+NX——即使结果恰好舍入进最小正规数也置 UF。
24x24 阵列 = 4 个 12x12 子乘器(2x(12x24) 与 4x(12x12) 门数相同,仅合并方式不同):
标量: prod = aa<<24 + (ab+ba)<<12 + bb // aa=aH*bH, ab=aH*bL, ba=aL*bH, bb=aL*bL
2-lane: lane1 = aa, lane0 = bb // 对角子乘器,交叉象限闲置
4-lane: lane i = tile_i(独立的 8/4 位乘法) // 每子乘器输入 mux 到各自的 lane 切片
lane 数据通路是标量 S1/S3/S4/S5 的微型化(24/12 位宽),公式完全同构:
sig_c(12 位) = (exp_zero ? 0 : 2^11) | (frac << (11 - F)) // 隐式位固定 bit 11
Ef = E + 1 - lz // 同标量
k = 13 - Ef // 次正规移位(常数 13 = 12+1,与 F 无关)
G/R/S = p_align[11]/[10]/[9:0],守卫 24/25/26
lane 宽度上限的推导:NxN 阵列可拆出 K 个独立 WxW 乘法当且仅当 K <= (N/W)^2 且输入切片可独立配对。24x24 拆 12x12 得 4 个;但 8 路 8x8 需要 8 个独立 8x8,交叉项(a_i*b_j, i!=j)无法通过单一乘积分离——朴素打包会在 2^17 宽的交叉和处污染相邻积。因此:
- FP8/INT8/FP4/INT4 => 最多 4 路(子乘器数上限);
- FP16/BF16 => 2 路(16 位容器);
- INT16x2 => 需 32x32 阵列,不支持(保持标量)。
| 格式 | Inf | NaN | sNaN | 说明 |
|---|---|---|---|---|
| FP32/FP16/BF16/TF32/BF32 | S.1*.0 | S.1*.(!=0) | 静默位=0 | IEEE 标准 |
| E5M2 | S.11111.00 | S.11111.{01,10,11} | 01 | 按静默位(bit1) |
| E4M3FN | 无 | S.1111.111 | 无 | exp=1111 且 mant=000..110 为有限(256/288/.../448);上溢->NaN |
| E2M1 | S.11.0 | S.11.1 | 无 | OCP MX;PyTorch float4_e2m1fn 为无 Inf 变体(max=6.0),本项目以 OCP 为准 |
NaN 惯例:payload 取 a(a 为 NaN 时)否则 b;静默位强制置 1;NaN 符号 = a[31]^b[31];0xInf -> 本格式默认 qNaN + NV。
- 标量:输入按补码取绝对值,24x24 阵列乘幅值,结果取 2N 位,有符号按 rs 取负,回绕;不置任何标志;
- SIMD:每 lane 独立执行上述流程,lane 结果宽 2N 位(INT8x4 的 4 个 16 位积拼入 result[63:0])。
- 纯 Verilog-2001(
.v):无 logic/always_ff/always_comb/function/task; - 48/24 位前导零计数为固定 mux 树(6x8 / 3x8 三元链),无 procedural for;
- SIMD 经
generate结构性复制 4 份(项目风格约定的复制手段); - 控制 FF 复位、数据 FF 不复位;组合块默认值防 latch;
make lint零警告。
| 版本 | LUT4 | FF | 晶体管(CMOS 估算) | 关键路径 |
|---|---|---|---|---|
| 标量 | 3,708 | 557 | ~50K | S4 = 57 级 |
| +SIMD | 8,383 | 1,616 | ~108K | S4 = 58 级(不变) |
关键路径始终是标量 S4(次正规对齐移位),lane 通路不拖慢频率;若要提速,把 S4 再切一级(6 级流水)即可。