compute()
实参支持所有基本 C++ 数据类型:bool
、char
、int
、short
、long
、float
和 double
。下列 C++ 类型的修饰符也同样受支持:signed
、unsigned
、short
和 long
。
此外,还支持任意精度数据类型 ap_int<N>
和 ap_uint<N>
,如 Vitis HLS 工具的任意精度 (AP) 数据类型中所述。ap_int
和 ap_uint
均为 Vitis HLS 中的预定义数据类型,其中 N 为上限 1024 的整数。这样即可实现更精细的位宽控制,用于处理数据打包或者匹配全局存储器数据总线宽度时尤为实用。
compute()
接口实参可分类为“Scalar”(标量)类型的实参或“Buffer”(缓冲器)类型的实参,如下所述。
标量类型
标量实参属于基本数据类型,表示传递给 compute()
调用的单个码字。只要前述任意基本数据类型用作为 compute()
按值传递的实参,VSC 就会推断标量实参类型。例如,此处 size
和 value
均为标量:compute(int size,
float value);
用户定义的 C 语言结构体可用作为按值传递的标量实参,且适用下列规则:
- 结构体不得包含带有 C++ 位说明符的字段,例如:
int field_x:4;
- 结构体不得包含指针字段,例如:
int* ptr_field;
- 结构体的总字节大小必须是 2 的幂值。否则,您必须声明在剩余字节内填充虚拟字段(例如,
char pad[remainder]
)。
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
推断标量:
- 它仅限指向一个元素。
- 内核代码仅对其写入一个值,例如:
*out_p = result;
- 在此实参上不指定任何 VSC 指南宏。
compute()
的每个标量实参均可传递至多个 PE。在硬件中,对于提取该标量实参的每个 PE 函数,单个 AXI4‑Lite 端口都将驱动该函数的单个标量寄存器。
缓冲器类型
缓冲器是 compute()
函数的指针或阵列实参,该函数可保存一个或多个元素。在器件上基于对应平台接口(SYS_PORT
连接)对缓冲器的内容进行往来传输。该指针或阵列实参的基本(元素)类型可以是上一节中所述的任意基本数据类型。此外,用户定义的 C 语言结构体数据类型同样可用作为基本元素类型。
使用 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()
为此缓冲器分配存储器。