默认情况下,Vitis HLS 会使接口上的结构体保持处于聚合状态,将任一结构体的所有元素都组合到一个单宽矢量中。这样即可同时读写结构体的所有成员。您可使用 DISAGGREGATE 编译指示或指令对接口中的结构体进行解聚。当结构体包含一个或多个 hls::stream
对象时,Vitis HLS 将按下文接口中含 hls::stream
元素的结构体中所述,对结构体进行自动解聚。
v++
命令一起使用时,此输出将出错。要支持 Vitis 内核流程,您必须将此结构体手动拆分为其组成成分元素,并将任意 hls::stream
对象定义为使用 AXIS 接口。在聚合过程中,针对 Vitis 内核流程,结构体的所有元素都在 4 字节对齐位置对齐,对于 Vivado IP 流程,则在 1 字节对齐位置对齐。此对齐可能需要添加位填充,以对齐各元素或者使各元素保持对齐,如 结构体填充与对齐 中所述。默认情况下,聚合的结构体将进行填充而不是打包,但在 Vivado IP 流程中,您可使用 AGGREGATE 编译指示或指令的 compact=bit
选项将其打包。但定义为 AXI4 接口的任意端口(m_axi
、s_axilite
或 axis
)都无法使用 compact=bit
。
该结构体的成员元素按 C/C++ 语言代码中所示顺序置于该矢量内:结构体的第一个元素对齐矢量的 LSB,结构体的最后一个元素对齐矢量的 MSB。这样即可在单一时钟周期内访问更多数据。结构体中的任意阵列都分区到独立阵列元素中,并按从低到高的顺序置于矢量内。
在以下示例中所示头文件内定义 struct data_t
。此结构体包含 2 个数据成员:
- 无符号的矢量
varA
,类型为short
(16 位)。 - 阵列
varB
,含 4 种unsigned char
类型(8 位)。typedef struct { unsigned short varA; unsigned char varB[4]; } data_t; data_t struct_port(data_t i_val, data_t *i_pt, data_t *o_pt);
在接口上聚合结构体会生成单个 48 位端口,其中包含 16 位 varA
和 4x8 位 varB
。
axis
串流接口则为 4096 位。对于 Vitis HLS 可综合的结构体的大小或复杂性并无限制。结构体中可包含所需的任意数量的阵列维度和成员。仅当阵列作为串流(例如,FIFO 接口)来实现时,才会出现结构体实现的唯一限制。在此情况下,请遵循适用于接口(FIFO 接口)上的阵列的常规规则进行操作。
接口上含 hls::stream 元素的结构体
包含 hls::stream
元素的接口上的用户定义的结构体将由 Vitis HLS 自动进行解聚。在 Vivado IP 流程中,支持解聚的结构体,并且导出的 IP 将能够按期望的方式工作。但 Vitis 内核流程则不支持此解聚的结构体,并且导出的内核 (.xo) 搭配 v++ --link
命令一起使用时,将导致出错。要支持 Vitis 内核流程,您必须将此结构体手动拆分为其组成成分元素,并将 hls::stream
对象定义为使用 AXIS 接口。
如有结构体已自动解聚,Vitis HLS 会将任意 INTERFACE 编译指示应用于已解聚的结构体的各个元素。如果针对此结构体仅指定一条 INTERFACE 编译指示,那么它将应用于该结构体的每个元素。如果您为已解聚的结构体的每个元素都提供一个 INTERFACE 编译指示,则会按期望方式来应用编译指示。