以下示例演示了 Vitis HLS 将多个实参(包括函数返回)作为 s_axilite
接口来实现的方式。由于针对 bundle
选项每条编译指示都使用相同名称,因此每个端口都分组到单个接口中。
void example(char *a, char *b, char *c)
{
#pragma HLS INTERFACE mode=s_axilite port=return bundle=BUS_A
#pragma HLS INTERFACE mode=s_axilite port=a bundle=BUS_A
#pragma HLS INTERFACE mode=s_axilite port=b bundle=BUS_A
#pragma HLS INTERFACE mode=s_axilite port=c bundle=BUS_A
#pragma HLS INTERFACE mode=ap_vld port=b
*c += *a + *b;
}
bundle
选项,Vitis HLS 会将所有实参组合到同一个 s_axilite
捆绑中,并对该端口进行自动命名。综合后的示例将作为系统的一部分,该系统具有 3 个重要元素,如下图所示:
- 与 IP 或内核交互的 x86 或嵌入式处理器上运行的主机应用
- SAXI Lite Adapter:INTERFACE 编译指示用于实现
s_axilite
适配器。该适配器具有 2 个主要函数:用于实现接口协议以便与主机进行通信,并向 IP 或内核提供控制寄存器映射。 - 实现设计逻辑的 HLS 引擎或函数
默认情况下,Vitis HLS 会为分组到单个 s_axilite
接口的每个端口分配地址。分配给端口的大小或地址范围取决于使用的实参数据类型和端口协议,如下所述。您也可以使用 offset
选项来显式定义地址,如 S_AXILITE 偏移选项 中所述。
- 端口 a:默认情况下作为
ap_none
来实现。为数据信号分配 1 个码字,并且仅使用 3 个位来进行寻址,因为实参数据类型为char
。剩余位保留不用。 - 端口 b:作为
ap_vld
来实现,由 INTERFACE 编译指示定义,如示例中所示。对应的控制寄存器大小为 2 字节(16 位),并分为 2 节,如下所示:- (0x1c) 控制信号:为控制信号分配 1 个字。
- (0x18) 数据信号:为数据信号地址分配 1 个字,并且仅使用 3 个位,因为实参数据类型为
char
。剩余位保留不用。
- 端口 c:默认情况下,作为
ap_ovld
来实现(作为输出)。对应的控制寄存器大小为 4 字节(32 位),并分为 3 节:- (0x20)
c_i
的数据信号:为输入数据信号分配 1 个码字,并且因为实参数据类型为char
,仅使用 3 个位进行寻址,剩余位保留不用。 - (0x24) 保留空间
- (0x28)
c_o
的数据信号:为输出数据信号分配 1 个字。 - (0x2c)
c_o
的控制信号:为控制信号ap_ovld
分配 1 个字,并且因为实参数据类型为char
,所以仅使用 3 个位进行寻址。剩余位保留不用。
- (0x20)
在操作中,主机应用将通过写入控制地址空间 (0x00) 来初始启动内核。主机/CPU 通过写入其他地址空间来完成初始设置,这些地址空间与示例中定义的各函数实参相关联。
端口 b 的控制信号将断言有效,随后内核才能读取端口 a 和 b(端口 a 为 ap_none
且不含控制信号)。在此之前,设计处于停滞状态并等待端口 b 的 valid 寄存器置位。每次 HLS 引擎准备好端口 b 后,输入 valid 寄存器就会清零,并且寄存器会复位为逻辑 0。
当 HLS 引擎完成计算后,端口 c 上的输出值将存储在控制寄存器内,对应的 valid 位将置位,以供主机读取。主机读取数据后,HLS 引擎会在控制寄存器 (0x00) 内写入 ap_done
位,以标记 IP 计算结束。
Vitis HLS 会在 S_AXILITE 控制寄存器映射 中报告分配的地址,并在 C 语言驱动程序文件 中提供这些地址以辅助您进行软件开发。您可使用 s_axilite
接口以利用 C 语言驱动程序文件,通过使用提供的应用编程接口 (API) 函数,可将这些文件搭配嵌入式或 x86 处理器上运行的代码来一起使用,以便您通过自己的软件来控制硬件。