C++ 语言中的原生数据类型以 8 位为边界(8 位、16 位、32 位,和 64 位)。RTL 信号和运算支持任意位长。
Vitis HLS 为 C++ 提供任意精度数据类型,允许以任意位宽指定 C++ 代码中的变量和运算:6 位、17 位、234 位以及(最高)1024 位。
AP_INT_MAX_W
宏来覆盖此默认值。任意精度数据类型相比于原生 C++ 类型,存在 2 项主要优势:
- 硬件质量更高:例如,如需 17 位乘法器,任意精度类型可指定在计算中精确使用 17 位。
如无任意精度数据类型,则必须使用 32 位整数数据类型实现 17 位乘法,从而导致以多个 DSP 模块来实现乘法。
- 准确的 C++ 仿真/分析:C++ 代码中的任意精度数据类型允许使用精确位宽执行 C++ 仿真,并允许 C++ 仿真在执行综合前确认算法的功能(和准确性)。
C++ 中的任意精度类型不具有 C 的任何劣势:
- C++ 任意类型可使用标准 C++ 编译器来进行编译(C++ 不含等效于
apcc
的命令)。 - C++ 任意精度类型不存在“整数提升问题”。
用户经常将文件扩展名从 .c 更改为 .cpp,因此此类文件可作为 C++ 来编译,并且不存在上述问题。
对于 C++ 语言,头文件 ap_int.h 用于定义任意精度整数数据类型 ap_(u)int<W>
。例如,ap_int<8>
表示 8 位有符号的整数数据类型,而 ap_uint<234>
表示 234 位无符号的整数类型。
ap_int.h 文件位于 $HLS_ROOT/include 目录中,其中 $HLS_ROOT 是 Vitis HLS 安装目录。
以下示例中所示的代码与 标准类型 中的“基本算术”示例中所示的代码相同。在此示例中,要综合的顶层函数中的数据类型指定为 dinA_t
、dinB_t
,以此类推 。
#include "cpp_ap_int_arith.h"
void cpp_ap_int_arith(din_A inA, din_B inB, din_C inC, din_D inD,
dout_1 *out1, dout_2 *out2, dout_3 *out3, dout_4 *out4
) {
// Basic arithmetic operations
*out1 = inA * inB;
*out2 = inB + inA;
*out3 = inC / inA;
*out4 = inD % inA;
}
在此示例的最新更新中,使用的是 C++ 任意精度类型:
- 将头文件 ap_int.h 添加到源代码。
- 将原生 C++ 类型更改为任意精度类型
ap_int<N>
或ap_uint<N>
,其中N
表示介于 1 到 1024 之间的位大小(如上所述,可根据需要扩展至 4K 位)。
数据类型在 cpp_ap_int_arith.h 头文件中定义。
通过与 标准类型 中的“基本算术”示例比较可以发现,输入数据类型已减缩,以表示实际输入数据的最大大小(例如,8 位输入 inA
减缩至 6 位输入)。输出类型已优化,准确性更高,例如,out2
(inA
与 inB
之和)只需 13 位,而不是 32 位。
以下示例显示了 C++ 任意精度类型的基本算术。
#ifndef _CPP_AP_INT_ARITH_H_
#define _CPP_AP_INT_ARITH_H_
#include <stdio.h>
#include "ap_int.h"
#define N 9
// Old data types
//typedef char dinA_t;
//typedef short dinB_t;
//typedef int dinC_t;
//typedef long long dinD_t;
//typedef int dout1_t;
//typedef unsigned int dout2_t;
//typedef int32_t dout3_t;
//typedef int64_t dout4_t;
typedef ap_int<6> dinA_t;
typedef ap_int<12> dinB_t;
typedef ap_int<22> dinC_t;
typedef ap_int<33> dinD_t;
typedef ap_int<18> dout1_t;
typedef ap_uint<13> dout2_t;
typedef ap_int<22> dout3_t;
typedef ap_int<6> dout4_t;
void cpp_ap_int_arith(dinA_t inA,dinB_t inB,dinC_t inC,dinD_t inD,dout1_t
*out1,dout2_t *out2,dout3_t *out3,dout4_t *out4);
#endif
任意精度整数完成综合后,所生成的设计的功能与 标准类型 相同。它使用内置 ap_int
方法 .to_int()
将 ap_int
结果转换为整数类型,以配合标准 fprintf
函数一起使用,而不是使用 C++ cout
运算符将结果输出到文件。
fprintf(fp, %d*%d=%d; %d+%d=%d; %d/%d=%d; %d mod %d=%d;\n,
inA.to_int(), inB.to_int(), out1.to_int(),
inB.to_int(), inA.to_int(), out2.to_int(),
inC.to_int(), inA.to_int(), out3.to_int(),
inD.to_int(), inA.to_int(), out4.to_int());