Skip to content

Latest commit

 

History

History
122 lines (84 loc) · 5.93 KB

File metadata and controls

122 lines (84 loc) · 5.93 KB

fp32_mult 设计文档(DESIGN)

本文档给出流水线架构、容器约定与全部关键数学推导,并说明各格式的特殊值处理与 SIMD 子乘器原理。

1. 流水线结构(5 级,吞吐 1 组/拍)

名称 功能
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。

2. 容器约定与指数公式(核心推导)

2.1 标量路径

尾数容器统一左对齐在 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、打包位切片、进位位选。

2.2 次正规路径

次正规字段 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。

2.3 上溢判据

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 按符号)。

2.4 下溢判据

采用舍入前 tininess(x86/ARM/glibc 惯例):Ef <= 0(精确值 < 2^(1-bias))且结果不精确即置 UF+NX——即使结果恰好舍入进最小正规数也置 UF。

3. SIMD 子乘器重组(4-lane 原理)

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 阵列,不支持(保持标量)。

4. 各格式特殊值编码

格式 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。

5. INT 语义

  • 标量:输入按补码取绝对值,24x24 阵列乘幅值,结果取 2N 位,有符号按 rs 取负,回绕;不置任何标志;
  • SIMD:每 lane 独立执行上述流程,lane 结果宽 2N 位(INT8x4 的 4 个 16 位积拼入 result[63:0])。

6. 风格合规

  • 纯 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 零警告。

7. 性能与面积(yosys 0.68 + nextpnr + icetime,iCE40 HX8K)

版本 LUT4 FF 晶体管(CMOS 估算) 关键路径
标量 3,708 557 ~50K S4 = 57 级
+SIMD 8,383 1,616 ~108K S4 = 58 级(不变)

关键路径始终是标量 S4(次正规对齐移位),lane 通路不拖慢频率;若要提速,把 S4 再切一级(6 级流水)即可。