浮点计算基本上涉及以科学计数法表示单位,然后决定将多少位用于 manitssa 和指数。因此,所有涉及 FP 数的计算都涉及这两个必须操纵的量。这听起来很简单,在纸上也不难做到。
我总是遇到将浮点硬件设计描述为困难的描述,并且听到/阅读诸如将数字乘以和除以 1 之类的东西可能不会给出相同的结果。这可能与要执行算术运算时如何“展开”数字有关。
不应该有一个统一的方法来设计硬件中的浮点硬件吗?为什么尽管有 IEEE 754,但这种硬件的设计和验证仍被认为是困难和具有挑战性的?
浮点计算基本上涉及以科学计数法表示单位,然后决定将多少位用于 manitssa 和指数。因此,所有涉及 FP 数的计算都涉及这两个必须操纵的量。这听起来很简单,在纸上也不难做到。
我总是遇到将浮点硬件设计描述为困难的描述,并且听到/阅读诸如将数字乘以和除以 1 之类的东西可能不会给出相同的结果。这可能与要执行算术运算时如何“展开”数字有关。
不应该有一个统一的方法来设计硬件中的浮点硬件吗?为什么尽管有 IEEE 754,但这种硬件的设计和验证仍被认为是困难和具有挑战性的?
该标准设计得很好,并且有一些细微的细节可以简化实现,例如,在舍入时,尾数的进位可能会溢出到指数。或者整数比较可以用于浮点比较......
但是,FPU 是一堆乱七八糟的组合。除了加法、乘法、除法之外,还有桶形移位器来对齐尾数、前导零计数器、舍入、标志(不精确、溢出等)、NaN 和非正规(需要额外的硬件进行计算,特别是对于 mul/div,或至少触发软件仿真异常)。
而且大多数 FPU 还需要在整数和格式(浮点数、双精度)之间进行转换。该转换硬件主要可以通过现有的浮点硬件实现,但它会产生额外的多路复用器和特殊情况......
然后是流水线。根据晶体管预算和频率,add/sub/mul 可以具有相同的吞吐量,或者双精度可以更慢,这可能会导致流水线的额外复杂性。现代 FPU 现在有一个流水线乘加运算符。
对于除法,它总是迭代的,它可以是一个单独的单元,也可以为 Newton-Raphson 或 Goldschmidt 重用乘法器。当您忙于制作除法器时,您会寻找方法来调整它的平方根...
验证很复杂,因为有很多极端情况。有一些带有测试模式的系统测试套件,用于有关所有舍入模式的“有趣”案例,但快速乘法器或除法器之类的东西太复杂而无法轻松测试。迭代除法器可能有不明显的错误(例如著名的 Pentium 错误在其 SRT 基数 4 分隔器中),乘法(牛顿)难以测试精确舍入(旧 IBM 计算机中的一些错误)。
现在使用形式化方法来证明这些部分。
现代 FPU 还实现了 SIMD 硬件,其中 FP 运算符被实例化多次以进行并行处理。
还有 x87 和 MC68881/2 FPU 的情况,它们可以计算十进制转换、双曲线和三角运算。这些操作是微编码的并使用基本的 FP 操作符,它们不是直接在硬件中实现的。
查看 opencores 可能会给出一些提示,例如:https ://opencores.org/websvn/filedetails?repname=openfpu64&path=%2Fopenfpu64%2Ftrunk%2Ffpu_mul.vhd
浮点的问题是大量烦人的极端情况。整数运算没有 NaN 的概念,但在浮点数中出现了很多。数字也必须正确规范化和非规范化。
即使您不处理所有极端情况,两个格式良好的数字的浮点加法或减法也需要大量逻辑,因为尾数的比例可能会发生巨大变化——考虑问题 1.9999 的问题(十进制) - 1.9993 = 0.0007。在浮点中,必须找到小数点的位置,这不是微不足道的,并且尾数和指数进行了调整。这甚至没有尝试处理 NaN 或非规范化数字。
处理特殊情况的所有提及都非常有效,但即使您将避免特殊情况的责任推给系统设计人员(这在用于 DSP 应用的浮点 IP 中并不少见),您的浮点运算仍然更多比同等大小的定点算法昂贵。
见证最新的 Altera/Intel FPGA,它们具有成对的“DSP 块”,并且将在每个块中执行 n 位(我认为是 32 位,但我不确定)定点数学,或者将在一对块中执行相同大小的浮点数学运算——因此浮点运算不仅会丢失精度(因为在 IEEE 32 位浮点中只有 25 个有效尾数位),而且会使用两倍的资源,对极端情况的处理非常有限。