vivado HLS学习之数据类型使用

C、C++语言中数据类型为8bit整数倍如: 
• char (8-bit) 
• short (16-bit) 
• int (32-bit) 
• long long (64-bit) 
• float (32-bit) 
• double (64-bit) 
vivado HLS 的任意精度数据类型:

Language Integer Data Type Required Header
C [u]int< W>(1024 bits) .#include< ap_cint.h>
C++ ap_[u]int< W>(1024 bits) .#include< ap_int.h>
C++ ap_[u]fixed< W,I,Q,O,N> .#include< ap_fixed.h>

对于ap_[u]int类型
在Vivado Hls里是支持copy initialization(Y)和direct initialization(Y)这两种方式来进行初始化例如: 
int data_i = 5; 
ap_int<8> a_8bit_data_c = 18; 
ap_int<8> a_8bit_data_d (18); 
ap_int<8> a_8bit_data_r2("0b010010",2); //表示2进制
ap_int<8> a_8bit_data_r8("0o22",8); //表示8进制
ap_int<8> a_8bit_data_r10("18",10); //表示10进制
ap_int<8> a_8bit_data_r16("0x12",16); //表示16进制

对于ap_[u]fixed类型

定义如下

ap_[u]fixed<int W,    int I,    ap_q_mode Q,    ap_o_mode O,    ap_sat_bits N>;

这里W代表整个数据的字长,I代表整数部分的字长,那么小数部分被的字长就是W-I,Q表示量化模式(针对低位部分),O表示溢出模式,针对高位部分,例如:

ap_fixed<3, 2, AP_RND, AP_SAT> UAPFixed4 = 1.25; // Yields: 1.5
ap_fixed<3, 2, AP_RND, AP_SAT> UAPFixed4 = -1.25; // Yields: -1.0
AP_RND 指示该值应舍入到最接近ap_ [u]定点类型的可表示值。

ap_fixed<3, 2, AP_RND_ZERO, AP_SAT> UAPFixed4 = 1.25; // Yields: 1.0
ap_fixed<3, 2, AP_RND_ZERO, AP_SAT> UAPFixed4 = -1.25; // Yields: -1.0
 AP_RND_ZERO 指示该值向零取整(AP_RND_MIN_INF 向负无穷取整,AP_RND_INF 向正无穷取整)

p_ufixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = 19.0; // Yields: 15.0 4位无符号最大能取到15
ap_fixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = 19.0; // Yields: 7.0 4位有符号数最大能取到7
ap_ufixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = -19.0; // Yields: 0.0   4位无符号最大能取到0
ap_fixed<4, 4, AP_RND, AP_SAT> UAPFixed4 = -19.0; // Yields: -8.0 4位有符号极限能取到-8

AP_SAT 表示取到剩余位数能表示的最大的值

ap_ufixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = 19.0; // Yields: 0.0
ap_fixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = 19.0; // Yields: 0.0
ap_ufixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = -19.0; // Yields: 0.0
ap_fixed<4, 4, AP_RND, AP_SAT_ZERO> UAPFixed4 = -19.0; // Yields: 0.0

ap_ufixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = 19.0; // Yields: 3.0 10011取低4位就是3
ap_fixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = 31.0; // Yields: -1.0 
ap_ufixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = -19.0; // Yields: 13.0
ap_fixed<4, 4, AP_RND, AP_WRAP> UAPFixed4 = -19.0; // Yields: -3.0
 

对于浮点类型

对于单精度类型浮点需要有后缀f,对于双精度则可以省略,例如: 
double data1(2.0) 
flout data2(2.0f) 

Vivado Hls对这些数据类型都是支持的,并且还提供一个数学库hls_math.h,它对C语言(math.h)和C++(cmath.h)都是支持的,这种支持包括单精度,双精度浮点的一些函数,还包括对数据类型本身的支持。

ap_int<2> data; 
ap_int<4> x3 = -3; 
ap_uint<4> x4= 3; 
data3 = x3; 
data4 = x4; 
这里得到的data3为-1(0b11),data4为-1(0b11),这是由于data为有符号数据类型,导致结果错误。 
ap_fixed<4> data5 = 1.25; 
ap_fixed<3> data6 = data5 
这里得到的data6为1.5(0b01.1),导致数据精度的损失。

显式数据类型的转换

显式数据类型的转换有两种方式,一种是通过“( )”操作,另一种是在C++中通过类似调用函数的方式进行转换,例如: 
`ap_uint<3> i1 = 2; 
ap_uint<4> i2= 7; 
ap_ufixed<6> i3 = i2 / i1; 
ap_ufixed<6> i4 =(ap_ufixed<6>) i2 / i1; 
ap_ufixed<6> i5 = ap_ufixed<6> (i2 )/ i1; 
cout << “The result of i5 :\t” << i5>这里得到的i3为3,而i4和i5为3.5,3.5才是我们要的结果,因此对于显式数据类型的转换,可以(括号数据类型类型)+变量名 和 数据类型+(变量名)来完成转换。

复合数据类型

struct类型

对于结构体中的元素,Vivado hls里提供相应的data pack优化方式,这种优化方式分为两种,即field_level 和struct_level。field_level所有元素的位宽必须以8 bits为边界,比如说,一个变量为6 bits就必须扩展到8 bits,如果一个struct有五个元素,每个元素6 bits,每个元素扩展到8 bits,此时总位宽就会被扩展为40 bits。

struct_level不改变每个元素的实际位宽,但是对于封装后的总位宽要以8 bits为边界,比如说,上面的·总位宽就会被扩展到32 bits。 

比较这两种类型的data pack优化方式,会发现两者的clock,latency和interval,以及资源利用率都是一致的。data pack可以降低latency和interval,提高数据的吞吐率,这是因为这里data pack对for循环进行展开。

Enum

Enumerated Type是将一个数值定义为一个符号常量,需要用到关键字enum。枚举类型的元素会被自动的分配到一个整数,其中起始值为0,后面依次加1。这样是为了提高代码的可读性。

vivado HLS学习之数据类型使用

总结

这里主要介绍vivado HLS中数据类型的使用。一般使用中主要用的最常用的几种

ap_int<8> a_8bit_data_c = 18; 
ap_int<8> a_8bit_data_d (18); 

int data_i = 5;