C++ 任意精度整数类型 - 2023.2 简体中文

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 简体中文

C++ 语言中的原生数据类型以 8 位为边界(8 位、16 位、32 位,和 64 位)。RTL 信号和运算支持任意位长。

Vitis HLS 为 C++ 提供任意精度数据类型,允许以任意位宽指定 C++ 代码中的变量和运算:6 位、17 位、234 位以及(最高)1024 位。

提示: 允许的默认最大宽度为 1024 位。可通过在包含 ap_int.h 头文件之前定义含正整数(小于或等于 4096)的 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_ROOTVitis HLS 安装目录。

以下示例中所示的代码与 标准类型 中的“基本算术”示例中所示的代码相同。在此示例中,要综合的顶层函数中的数据类型指定为 dinA_tdinB_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 位输入)。输出类型已优化,准确性更高,例如,out2inAinB 之和)只需 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());