Vitis 内核流程为已编译的内核对象 (.xo) 提供支持,以便从主机应用和 Xilinx Runtime (XRT) 来执行软件控制。如 Vitis 统一软件平台文档中的 PL 内核属性 中所述,此流程具有非常具体的接口要求,Vitis HLS 必须满足这些要求。
-
存储器范例 (
m_axi
):内核通过存储器(如 DDR、HBM、PLRAM/BRAM/URAM)来访问数据 -
串流范例 (
axis
):数据从其他串流源(例如,视频处理器或其他内核)串流至内核中,也可从该内核流出。 -
寄存器范例 (
s_axilite
):内核通过寄存器接口来访问数据,软件则通过寄存器读/写来访问数据。
syn.rtl.reset_level
设为高电平有效状态(默认设置)。Vitis 内核流程默认会实现下列接口:
C 语言实参类型 | 范例 | 接口协议 (I/O/Inout) |
---|---|---|
标量(通过值来传递) | 寄存器 |
AXI4‑Lite (s_axilite ) |
阵列 | 存储器 |
AXI4 存储器映射 (m_axi ) |
指向阵列的指针 | 存储器 |
m_axi
|
指向标量的指针 | 寄存器 |
s_axilite
|
参考 | 寄存器 |
s_axilite
|
hls::stream | 串流 |
AXI4‑Stream (axis ) |
如上表所示,指向阵列的指针是作为 m_axi
接口(用于数据传输)来实现的,指向标量的指针则是使用 s_axilite
接口来实现的。作为常量来传递的标量值不需要读取权限,而指向标量值的指针则需要读取和写入权限。s_axilite
接口会根据 C 语言实参类型来实现一项额外的内部协议。此内部实现可使用 Vivado IP 流程的端口级协议 来控制。但如非必要,不应在 Vitis 内核流程中修改默认端口协议。
s_axilite
接口时,就是如此。您不能依靠默认接口分配,而必须为结构体的每个元素显式定义 INTERFACE 编译指示。如未定义任何 INTERFACE 编译指示或指令,则 Vitis HLS 将发出以下错误消息:ERROR: [HLS 214-312] Vitis mode requires explicit INTERFACE
pragmas for structs in the interface. Please add one INTERFACE pragma for each struct
member field for argument 'd' of function 'dut(A&)' (example.cpp:19:0)
Vitis 内核流程的默认执行模式为流水打拍执行,即启用内核的重叠执行以改善吞吐量。这是通过 s_axilite
接口上的 ap_ctrl_chain
块控制协议来指定的。
以下代码中的 vadd
函数提供了接口综合的示例。
#define VDATA_SIZE 16
typedef struct v_datatype { unsigned int data[VDATA_SIZE]; } v_dt;
extern "C" {
void vadd(const v_dt* in1, // Read-Only Vector 1
const v_dt* in2, // Read-Only Vector 2
v_dt* out_r, // Output Result for Addition
const unsigned int size // Size in integer
) {
unsigned int vSize = ((size - 1) / VDATA_SIZE) + 1;
// Auto-pipeline is going to apply pipeline to this loop
vadd1:
for (int i = 0; i < vSize; i++) {
vadd2:
for (int k = 0; k < VDATA_SIZE; k++) {
out_r[i].data[k] = in1[i].data[k] + in2[i].data[k];
}
}
}
}
vadd
函数包括:
- 两个指针输入:
in1
和in2
- 指针输出:
out_r
,结果写入其中 - 标量值
size
如果 Vitis HLS 为 Vitis 内核流程使用默认接口综合设置,那么设计将综合到含下图所示端口和接口的 RTL 块中。
该工具会在 RTL 上创建三种类型的接口端口,以处理数据流和控制流。
- 时钟、复位和中断端口:在内核中添加
ap_clk
、ap_rst_n
和interrupt
。 -
AXI4‑Lite 接口:
s_axi_control
接口中包含标量实参(如size
)、管理 m_axi 接口的地址偏移并定义块控制协议。 -
AXI4 存储器映射接口:
m_axi_gmem
接口,其中包含指针实参:in1
、in2
和out_r
。
Vitis 的 M_AXI 接口的详细信息
m_axi
) 接口允许内核在全局存储器(DDR、HBM 和 PLRAM)中读取和写入数据,存储器映射接口便于跨加速应用的不同元素进行数据共享,例如,在主机与内核之间或者在加速器卡上的内核之间。以下列出了 m_axi
接口的主要优势: - 每个接口均有独立的读取通道和写入通道
- 它支持基于突发的访问
- 它可提供未完成传输事务队列
- 认识突发访问
-
AXI4 存储器映射接口支持高达 4K 字节的高吞吐量突发,且只需单一地址阶段即可。对于突发模式传输,Vitis HLS 会使用单一基址读取或写入数据,后接多次顺序数据采样,因此,该模式支持更高的数据吞吐量。使用流水打拍的
for
循环来复制存储器时,可使用操作的突发模式。如需了解更多信息,请参阅 控制 AXI4 突发行为 或 AXI 突发传输。 - 自动端口拓宽和端口宽度对齐
-
如 端口宽度自动调整 中所述,Vitis HLS 能够自动拓宽端口宽度以便执行数据传输并改善突发访问,前提是该工具可发现突发访问。因此,突发所需的所有前置条件(如 AXI 突发传输 中所述)都必须得到满足后才能调整端口大小。
在 Vitis 内核流程中,默认启用端口宽度自动调整,可采用以下配置命令来执行此操作(请注意,其中一条命令指定为位,另一条命令则指定为字节):syn.interface.m_axi_max_widen_bitwidth=512 syn.interface.m_axi_alignment_byte_size=64
- 偏移规则
-
重要: 在 Vitis 内核流程中,操作的默认模式为 syn.interface.m_axi_offset=direct 和 syn.interface.default_slave_interface=s_axilite,并且不应更改。
正确指定偏移才能将 HLS 内核正确集成到 Vitis 系统中。如需了解更多信息,请参阅 偏移和操作模式。
- 捆绑接口 - 性能对比资源使用情况
-
默认情况下,Vitis HLS 将具有兼容选项的函数实参组合到单个
m_axi
接口适配器中,如 M_AXI 捆绑 中所述。将端口捆绑到单个接口中可消除 AXI4 逻辑,因而有助于节省器件资源,在拥塞的设计内工作时可能需要这些资源。但是,单一接口捆绑可能会限制内核性能,因为所有存储器传输都必须穿越单个接口。
m_axi
接口具有独立的读取 (READ) 和写入 (WRITE) 通道,因此单个接口即可同时执行读取和写入,但仅限单一位置。使用多个捆绑即可创建多个接口以连接到存储体,从而能够增大内核带宽和吞吐量。
Vitis 的 S_AXILITE 接口的详细信息
在 C++ 语言中,从父函数调用函数时,该函数就会开始处理数据。函数调用将在调用时推送到栈上,处理完成时则会从栈中移除以便将控制权返还给调用函数。此进程可确保父函数明确知晓子函数的状态。
由于主机和内核在 Vitis 内核流程中占用两个独立的计算空间,因此“栈”由 Xilinx Runtime (XRT) 来管理,通信则通过 s_axilite
接口来管理。此内核由软件通过 XRT 来控制,方法是读取和写入 s_axilite
接口的控制寄存器,如 S_AXILITE 控制寄存器映射 中所述。此接口具有下列特性:
- 控制协议
- 块控制协议可定义
s_axilite
接口中的控制寄存器,以便您设置控制信号来管理内核的执行和操作。 - 标量实参
- 内核上的标量数据为典型输入,可视作为编程常量或参数。主机应用通过
s_axilite
接口来传输这些值。 - 指向标量实参的指针
- 如果指向标量值的指针分配给
s_axilite
接口,那么 Vitis HLS 允许您在该指针上执行读取或写入。指针默认分配给m_axi
接口,因此您必须使用 INTERFACE 编译指示或指令将该指针手动分配给s_axilite
:int top(int *a, int *b) { #pragma HLS interface s_axilite port=a
- 偏移规则
-
注释: Vitis 内核流程会判定所需的偏移。请勿在该流程中指定
offset
选项。 - 捆绑规则
-
Vitis 内核流程仅支持单个
s_axilite
接口,这意味着所有s_axilite
接口都必须捆绑在一起。- 如不指定捆绑,那么该工具会自动创建名为
Control
的默认捆绑。 - 如果您出于某些原因想要手动指定捆绑名称,则必须将此捆绑应用于所有
s_axilite
接口以创建单一捆绑。
- 如不指定捆绑,那么该工具会自动创建名为
Vitis 的 AXIS 接口的详细信息
AXI4‑Stream 协议 (AXIS) 可定义单向通道,用于按顺序执行串流。AXI4‑Stream 接口可突发的数据量是无限的,故而能显著提升性能。不同于需要地址才能读/写存储器的 AXI4 存储器映射接口,AXIS 接口可直接将数据传递至另一个 AXIS 接口,无需地址,因此使用的器件资源更少。通过将这些功能特性相结合,即可使串流接口成为轻量级高性能接口。
AXI4‑Stream 可用于生产者与使用者之间的业界标准 ready
/valid
握手,如下图所示。当生产者发送 TVALID
信号,并且使用者通过发送 TREADY
信号来响应时,即可立即开始数据传输。此数据和控制握手应持续进行,直至 TREADY
或 TVALID
设为低位或者生产者断言 TLAST
信号有效(表示这是传输的最后一个数据包)为止。
hls::stream
,而不能使用 AXIS 接口。您应使用 hls::stream<T_data_type>
来定义串流的数据类型,使用 ap_axis
结构体类型来实现 AXIS 接口。如 AXI4-Stream 接口 中所述,ap_axis
结构体支持您选择接口实现(含旁路或不含旁路):
- 不含旁路的 AXI4-Stream 接口 可通过使用更少的资源来将 AXIS 接口实现为超轻量级接口
- 含旁路的 AXI4-Stream 接口 可实现全功能接口以提供更强大的控制能力