SpinalHDL(六):定点化-饱和截位

SpinalHDL(六):定点化-饱和截位

首先为什么要定点化?
在性能可接受的范围内尽可能的的压缩数据bit位宽以便节省资源
一个扰码识别的定点流程
61
灰色的全精度
蓝色是定点截位以后的位宽,对于这个算法,定点以后在大大节省资源的情况下性能几乎没有任何损失。
我们在定点的时候不是说每一个节点都需要压缩bit,而是在关键的节点尽可能压缩位宽才能做到事半功倍,
比如以上例子中的求平方,和最后的累计和输出,这两个点对硬件来说非常敏感,一个是乘法器,另外一个是缓存MEM,是面积的开销大户,
所以我们在定点的时候要特别有意去照顾这些节点,在性能可接受的情况下,能省1bit是1bit

定点介绍(低截高饱)

一般我们会分为两步来操作

  1. 低位Round操作

62
低位的Round操作有非常多类型。参见
https://en.wikipedia.org/wiki/Rounding

6t1

其实 RoundHalfUp, RoundHalfDown, RoundHalfToZero,
RoundHalfToInf, RoundHalfToEven, RounHalfToOdd
非常接近,
RoundToInf,最为常见。其中”RoundToeven,RoundToOdd”比较特别,这种Round比RoundToInf还要公平一些,但是相对稍微复杂一下,一般用在打数据统计中对精度非常敏感的场景。
SpinalHDL目前不支持这两种类型,
不同语言的round函数实际用的Round类型其实也各有不同,SpinalHDL为了保持通用,默认round采用RoundToInf,
但是我们在一般的硬件设计当中
推荐大家使用RoundToUp,这种方式选择器更少,时序面积更好,性能几乎没有太大损失。

6t2

  1. 高位饱和操作

63
主要是饱和操作,但是有时候直接截掉的需求,高位直接截掉没有数学意义,我不清楚具体用在什么地方。
除此之外,高位还有一个对称操作,比如8bit的有符号数表示范围为(-128
~ 127)如果不对称取反的话会出现+128 如果有符号数表示就得扩展为9bit
为了避免这种情况,又是需要将(-128 ~127) 对称到(-127 ~ 127),
这样在取反的时候就不用扩展1bit,性能损失几乎忽略不计,在硬件设计当中非常常见。

6t4

Verilog是怎么做的?

手动书写定点电路 封装fixpoint代码
我们用Verilog来实现定点饱和截位时,起初都是手写饱和截位电路,包括现在我看很多人还是直接手写
64
这个是极其容易出错,也是我们和算法debug追问题的高发地带。我想很多人都会遇到跟算法比对数据是遇到
差1bit对不上(实际上就是+-1),追了半天发现定点方式理解不一致,或者电路里面写错了。这种问题反反复复的发生,非常耗时耗力,很没必要。
后来出现了一种相对稳定一点的方式: 封装为饱和截位
这个可能是在verilog上能做到的最好的方式了,但是不够完美 使用方式:

1
2
fixpoint (15,11,4,1,1) u_add1_fix (.din(fixin),.dout(fixout));
fixpoint (15,10,4,1,1) u_add2_fix (.din(fixin),.dout(fixout));

源码
65
实际上这里面也就才实现了Floor,RoundToInf,RoundUp
三种Round方式,不得不用verilog generator配合一些宏,
代码看上去已经是灾难了,调试到稳定也是非常痛苦。

SpinalHDL定点如何操作

这一切到SpinalHDL上一句话就能搞定

1
2
val A  = SInt(10 bit)
val B = A.fixTo(7 downto 3) //定点化

展开来等效于

1
val B  = A.roundToInf(3).sat(3)

66
SpinalHDL完整的提供了8种Round Api

6t5

你可以直接像这样使用它

1
2
3
4
val x = UInt(8 bits)
val y = round(n) // return x-n bits(default,align=true)
val y = round(n,align=false) // return x-n+1 bits(need carry)
val y = floor(n) // return x-n bits(floor with no align argment)

当然我们鼓励你 使用fixTo ,

更直观也更安全,不需要你手动处理进位对齐的那些琐碎容易犯错的操作。
当然你愿意你完全还是可以用A.roundToInf(2).sat(3).symmetry 这种方式式去处理,不做限制。

6t6

只要你配置好roundType,以及symmetric是否对称, 就可以自由的使用fixTo,
一行搞定!

67

评论