接口数据类型 - 2022.1 简体中文

Vitis 统一软件平台文档 应用加速开发 (UG1393)

Document ID
UG1393
Release Date
2022-05-25
Version
2022.1 简体中文

compute() 实参支持所有基本 C++ 数据类型:boolcharintshortlongfloatdouble。下列 C++ 类型的修饰符也同样受支持:signedunsignedshortlong

此外,还支持任意精度数据类型 ap_int<N>ap_uint<N>,如 Vitis HLS 工具的任意精度 (AP) 数据类型中所述。ap_intap_uint 均为 Vitis HLS 中的预定义数据类型,其中 N 为上限 1024 的整数。这样即可实现更精细的位宽控制,用于处理数据打包或者匹配全局存储器数据总线宽度时尤为实用。

compute() 接口实参可分类为“Scalar”(标量)类型的实参或“Buffer”(缓冲器)类型的实参,如下所述。

标量类型

标量实参属于基本数据类型,表示传递给 compute() 调用的单个码字。只要前述任意基本数据类型用作为 compute() 按值传递的实参,VSC 就会推断标量实参类型。例如,此处 sizevalue 均为标量:compute(int size, float value);

提示: 标量码字的传输是实用 AXI4-Lite 硬件接口来完成的。

用户定义的 C 语言结构体可用作为按值传递的标量实参,且适用下列规则:

  • 结构体不得包含带有 C++ 位说明符的字段,例如:int field_x:4;
  • 结构体不得包含指针字段,例如:int* ptr_field;
  • 结构体的总字节大小必须是 2 的幂值。否则,用户必须声明在剩余字节内填充虚拟字段(例如,char pad[remainder])。
标量实参始终按值传递,并且通常作为加速器的输入。不允许标准 C++ 引用实参。例如:
compute(int size, float& result_value) // reference argument is not allowed

但如果 PE 函数实参仍为引用,则可使用 C++ 指针类型代替引用。例如:

my_acc::compute(int inp, data_t *out_p) { // reference not allowed
  my_PE(inp, *out_p); // deref the ptr for my_PE out_ref
  my_PE_two(inp ... ); // passing inp to multiple PEs is allowed
}
my_acc::my_PE(int in, data_t &out_ref) { // reference is allowed
...
// application code
my_acc::send_while ... { ...
  out_p = my_acc::alloc_buf(bp, 1);  // required
  my_acc::compute(inp, out_p);

满足下列所有条件时,VSC 将为输出实参 out_p 推断标量:

  • 它仅限指向一个元素。
    重要: 应用代码必须使用 alloc_buf() 分配大小为 1 的存储器,如 VPP_ACC 类 API 中所述。
  • 内核代码仅对其写入一个值,例如:*out_p = result;
  • 在此实参上不指定任何 VSC 指南宏。

compute() 的每个标量实参均可传递至多个 PE。在硬件中,对于提取该标量实参的每个 PE 函数,单个 AXI4-Lite 端口都将驱动该函数的单个标量寄存器。

缓冲器类型

缓冲器是 compute() 函数的指针或阵列实参,该函数可保存一个或多个元素。在器件上基于对应平台接口(SYS_PORT 连接)对缓冲器的内容进行往来传输。该指针或阵列实参的基本(元素)类型可以是上一节中所述的任意基本数据类型。此外,用户定义的 C 语言结构体数据类型同样可用作为基本元素类型。

注释: 缓冲器类型的实参在器件上和 CPU 主机内部都需要相应的全局存储器空间。因此,使用指针类型时,需要应用代码才能调用存储器分配(VPP_ACC 类 API 中描述的 alloc_buf)。

使用 C 语言结构体作为指针或阵列的基本类型时,适用下列规则:

  • 结构体不得包含带有 C++ 位说明符的段,例如:int field_x:4;
  • 结构体不得包含指针字段,例如:int* ptr_field;
重要:compute() 接口内不允许 C++ 数据修饰符(如 const, register, volatile)。

以下示例显示了缓冲器类型的实参所允许和不允许的编码样式:

// accelerator interface
my_acc::compute(int A, int *B, int C[10]) {
...
// application code
int S, *BB, *CC;
my_acc::send_while ... { ...
  BB = my_acc::alloc_buf( ... ); // required
  CC = my_acc::alloc_buf( ... ); // required
  compute (S, AA, BB);

在以上示例中,compute() 实参 A 和 B 在应用代码中以相同方式来处理,因此必须为这些缓冲器实参分配存储器。

提示: compute() 的每个缓冲器实参都只能传递到其中的单个 PE 函数。

在此示例中,A 属于标量输入实参。调用程序仅将整数实参传递到 compute() 调用,值则使用 AXI4-Lite 传输给器件。而 B 和 C 则是缓冲器实参。这两个实参可用作为输入、输出、双向或远程实参。调用程序必须使用 alloc_buf() 为此缓冲器分配存储器。