跳转至

浮点运算单元(FPU)

项目中使用的 FPU 是来自于 pulp-platformFPnew。我们对其使用 Chisel 进行了适配,单独形成 此项目。下列内容为 FPnew 文档 的翻译,接口均修改为 Chisel 版本。

FPnew 是一个支持标准 RISC-V 操作和多精度格式的参数化浮点单元,使用 SystemVerilog 编写。

顶层接口

FPU 的顶层模块是 FPNew,这一节将给出接口的详细描述。FPnew 使用同步接口在 FPU 与外界间握手和传输数据。

参数

FPU 的主要配置通过 FPConfig 类型完成,实现中提供了默认的选择。支持的配置如下:

名称 类型 描述
fLen Int FPU 的最大浮点宽度
tagWidth Int 操作标签宽度
pipelineStages Int 数据同步拍数

Note

目前 Chisel 的适配中,并未支持原版的所有参数。其他参数的默认配置可参见 此文件

端口

FPnew 对外接口类型为 FPIO,包括以下四个成员:

名称 方向 类型 描述
req in Flipped(Decoupled(FPRequest)) 向 FPU 发出的请求
resp out Decoupled(FPResponse) FPU 的响应
flush in Bool 清空(同步流水线复位)
busy out Bool FPU 正在执行操作

注意到 reqresp 都是 Decoupled 类型,即除数据外还包括 readyvalid 的握手信号。

其中 FPRequest 类型定义为:

名称 类型 描述
operands Vec(3, UInt(fLen.W)) 操作数
roundingMode FPRoundingMode 浮点舍入模式
op FpOperation 操作选择
opModifier Bool 操作修饰符
srcFormat FPFloatFormat 源浮点数格式
dstFormat FPFloatFormat 目标浮点数格式
intFormat FPIntFormat 整数格式
vectorialOp Bool 向量操作选择
tag UInt(tagWidth.W) 操作标签

FPResponse 类型定义为:

名称 类型 描述
result UInt(fLen.W) 操作结果
status FPStatus RISC-V 浮点状态标记 fflags
tag UInt(tagWidth.W) 操作标签

数据类型

下面列出了 FPnew 使用的各种数据类型(包括枚举量)。

FPRoundingMode - 浮点舍入模式

下面列出了可用的浮点舍入模式,其编码与 RISC-V 中使用的相同。

名称 编码值 舍入模式
RNE 3'b000 向最近舍入到偶数(默认)
RTZ 3'b001 向零舍入
RDN 3'b010 向负无穷大舍入
RUP 3'b011 向正无穷大舍入
RMM 3'b100 向最近舍入并远离零
DYN 3'b111 RISC-V 动态舍入模式,传递给指令是无效的
FPOperation - 浮点操作

操作修饰符 opModifier 可用于更改操作的行为。如果没有特别指明,则操作使用第一个操作数(operands(0))。

名称 修饰符 操作
FMADD 0 融合乘加 ((op[0] * op[1]) + op[2])
FMADD 1 融合乘减 ((op[0] * op[1]) - op[2])
FNMSUB 0 取反的融合乘减 (-(op[0] * op[1]) + op[2])
FNMSUB 1 取反的融合乘加 (-(op[0] * op[1]) - op[2])
ADD 0 加法 (op[1] + op[2]) 注意操作数下标
ADD 1 减法 (op[1] - op[2]) 注意操作数下标
MUL 0 乘法 (op[0] * op[1])
DIV 0 除法 (op[0] / op[1])
SQRT 0 平方根
SGNJ 0 符号注入,使用舍入模式来编码操作
RNE: op[0] 使用 sign(op[1])
RTZ: op[0] 使用 ~sign(op[1])
RDN: op[0] 使用 sign(op[0]) ^ sign(op[1])
RUP: op[0] (不做修改)
SGNJ 1 与上面相同,但是给出符号扩展而非 NaN-装箱 的结果
MINMAX 0 取最大/最小值,使用舍入模式来编码操作
RNE: minimumNumber(op[0], op[1])
RTZ: maximumNumber(op[0], op[1])
CMP 0 比较,使用舍入模式来编码操作
RNE: op[0] <= op[1]
RTZ: op[0] < op[1]
RDN: op[0] == op[1]
CLASSIFY 0 分类,返回 RISC-V 类别块
F2F 0 浮点-浮点转换,使用 srcFormatdstFormat 指定的类型
F2I 0 浮点-有符号整数转换,使用 srcFormatintFormat 指定的类型
F2I 1 浮点-无符号整数转换,使用 srcFormatintFormat 指定的类型
I2F 0 有符号整数-浮点转换,使用 intFormatdstFormat 指定的类型
I2F 1 无符号整数-浮点转换,使用 intFormatdstFormat 指定的类型
CPKAB 0 op[0]op[1] 转换并包装进向量 op[2] 的条目 0, 1
CPKAB 1 op[0]op[1] 转换并包装进向量 op[2] 的条目 2, 3
CPKCD 0 op[0]op[1] 转换并包装进向量 op[2] 的条目 4, 5
CPKCD 1 op[0]op[1] 转换并包装进向量 op[2] 的条目 6, 7
FPFloatFormat - 浮点数格式
名称 格式 宽度 指数宽度 尾数宽度
Fp32 IEEE binary32 32 bit 8 23
Fp64 IEEE binary64 64 bit 11 52
Fp16 IEEE binary16 16 bit 5 10
Fp8 binary8 8 bit 5 2
Fp16Alt binary16alt 16 bit 8 7
FPIntFormat - 整数格式
名称 宽度
Int8 8 bit
Int16 16 bit
Int32 32 bit
Int64 64 bit
FPStatus - 浮点状态标志
名称 描述
NV 无效操作
DZ 除零
OF 向上溢出
UF 向下溢出
NX 非精确操作

NaN-装箱(NaN-Boxing)

RISC-V 对于系统中所有比可用的最大宽度窄的浮点数强制要求进行 NaN-装箱,也就是说较窄的格式的所有未使用的高位都需要置为 1,否则该值将被视为不可用(一个 NaN)。

Note

默认会检查输入值是否正确进行 NaN-装箱,此行为可以关闭(见配置一节)。 FPU 给出的窄浮点数总是进行 NaN-装箱,整数输出总是进行符号扩展(即使是无符号数)。

握手接口

FPnew 的输入和输出都使用 valid/ready 握手接口来控制数据的流动。握手协议和通用协议(如 AXI)中使用的相同:

  • 置位的 valid 信号表明对应接口上的数据是有效并且稳定的。
  • 一旦 valid 置位,在握手完成前 不允许 取消。
  • 置位的 ready 信号表明接口在下一个时钟正沿能够处理数据。
  • 一旦 validready 在同一个时钟正沿置位,事务就完成了。
  • 在事务完成后,valid 可以保持置位,为下一次传输提供新数据。
  • 协议方向是 自顶向下 的。ready 可以依赖于 valid,但是 valid 不允许 依赖于 ready

操作标签

操作标签是附带在操作上的元数据,用于关联结果和对应的操作。标签经过 FPU 时不会被修改,总是与和它们一同发射的指令保持一致。

通过 tagWidth 参数,可以控制标签的宽度。


最后更新: April 8, 2020
作者: Harry Chen