第3部分:块浮点运算
在使用定点算术时,我们必须注意样本可能取的逻辑值的范围,以避免溢出用于表示它们的尾数。BFP(块浮点)算术将允许我们在编译时避免做出这些决策。相反,我们将根据对操作输入的了解,在执行操作时动态选择指数。
在本节中:
快速提醒
在第2部分中,我们使用定点算术实现了数字 FIR 滤波器。在第3部分中,我们将更新它 以使用块浮点(BFP)算术。
-
在第3A部分中,BFP向量对象和BFP向量算术都是用纯C实现的,以演示操作在底层是如何工作的。
-
在第3B部分中,第3A部分的某些C例程被优化的
lib_xcore_math库调用的向量API替换。 -
在第3C部分中,第3A部分的BFP向量对象被
lib_xcore_math中定义的BFP向量类型替换,而第7阶段的向量API调用被lib_xcore_math的BFP API中的操作替换。
组件函数(Component Functions)
Part 3中的各个阶段的结构与Part 2类似,每个阶段都使用了几个函数的不同版本。这次情况稍微复杂一些,每个阶段都实现了7个不同的函数:
filter_task()filter_frame()filter_sample()calc_headroom()tx_frame()rx_frame_bfp()rx_and_merge_frame()
filter_task()、filter_sample()和tx_frame()在之前的阶段中扮演了相似的角色。
filter_frame()位于调用栈中的filter_task()和filter_sample()之间。在BFP中,我们通常调用一次计算整个向量值的操作。filter_frame()在Part 3中扮演了这个角色。在Part 3中,filter_sample()被filter_frame()用于计算单个输出元素,而filter_frame()被filter_task()用于一次计算整个输出帧。
calc_headroom()是一个辅助函数,用于计算BFP向量的头空间。
tx_frame()的行为与Part 2中的相似,但是它接收到的输出帧可能不使用所需的输出指数,因此tx_frame()需要将样本值强制转换为正确的输出指数,然后将其发送到Tile 0。
在Part 3中,rx_and_merge_frame()和rx_frame()共同扮演了之前阶段中rx_frame()的角色。rx_frame()的行为与之前类似,但不会将帧合并到样本历史中。相反,它只报告新帧的尾数、指数和头空间。
rx_and_merge_frame()是一个不寻常的函数,它将表示样本历史的BFP向量作为参数。它通过调用rx_frame()获取表示新帧的BFP向量,然后必须将新的数据帧合并到样本历史中。
这是一个不寻常的BFP操作,因为在我们将新的数据帧合并到样本历史之前,我们必须确保新的和旧的样本数据使用相同的指数。