如何处理任意精度的数据类型-数据类型的初始化、转换- 复合数据类型在HLS中的应用-Vivado HLS中的C++基本运算
一. 如何处理任意精度的数据类型
- C语言支持的数据类型有字符型、整型(有符号(signed可省略)和无符号(unsigned不可省略))、浮点型、boolean类型等的,需要注意的是char 16_t和char 30_t这两个数据类型在Vivado HLS中是不支持的;
- Vivado HLS继承了传统的C/C++包含的数据类型,包括char、short、int、float和double,又由于这些数据类型都是以8为边界的(8、16、32、64),有时候对于某些操作来说不够高效(比如进行18位的两个数的加法,需要定义两个32位的数),因此引入任意精度的数据类型来提高硬件效率;
- 定义任意精度数据类型时最好将它声明在头文件里,方便debug;
- 使用sizeof打印我们定义数据实际占用的内存空间;
二. 数据类型的初始化、转换
1. 变量定义和初始化
关于拷贝初始化和直接初始化的区别:https://blog.****.net/linda_ds/article/details/82807006#commentBox
需要注意的是copy initialization不允许隐式转换,必须直接由初始化器(先类型转换等)产生T类型。在初始化尽可能的每行只初始化一个变量。
ap_[u]fixed<W,I,Q,O>中的W是指总共的位数;I是整数部分的位数,W-I就是小数部分的位数;Q是量化模式,针对低位部分;O是溢出模式,针对高位部分。var1是1,var2是1.5,var3是3,var4是7.
定义单精度浮点类型的时要有后缀f。此外还有一个数学库是C和C++的综合
2. 隐式数据类型转换
隐式的数据类型转换包括Numeric promotion和Numeric conversion两种,promotion其实是一种安全的方式,把小类型的向大类型的数据转化(对于有符号数就是符号位的扩展,对于无符号数就是扩展0);conversion是将大类型向小类型转换,这种转换可能会导致数据的损失甚至结果的错误。
3. 显式数据类型转换
通过括号的方式:
位宽变化:
显式数据类型转换包括()和C++中采用的类似于调用函数的转换两种方式,我们的原则就是大数据不溢出,小数据不损失。
4. 获取变量数据类型
利用头文件# include中的 typeid函数来获取;
三. 复合数据类型在HLS中的应用
C++常用的两种符合数据类型:结构体和枚举类型
1. 结构体
- scalar members被映射成scalar端口,默认情况下数组被映射成memory端口;
- 建议将结构体预先在头文件中声明;
- 对于结构体中的这些元素HLS提供了相应的优化方式——data packing,优化方式有两种,一种是field_level,结构体中每个元素都以8为边界;一种是struct_level,先保留每个元素的位宽,之后再将其扩展到以8为边界;
两种Data Pack Mode的不同:
2. 枚举类型
枚举类型,实际上他是把一个数值定义为一个符号常量,关键字enum,对于枚举类型,其中的元素会被会被自动的分配到一个整数,那么初始值为零,后续的会比前面的大一。
struct 和 enum这两种类型都可以在顶层作为接口出现,如果结构体出现在顶层函数中会被data pack directive封装,枚举类型出现在顶层函数中作为接口,它实质上是一个整数,Vivado HLS会自动推断数据位宽。
四. Vivado HLS中的C++基本运算
进行基本运算时要特别注意数据位宽的处理,总体原则就是大数不溢出,小数不损失。
- 算术运算符
- 自增、自减运算符
- 条件和关系运算符
- 逻辑运算和位运算
- 递归在vivado hls中是不支持的