在 Vitis 工具流程中,Vitis HLS 能够自动将 m_axi
接口端口的大小调整为 512 位,以改善突发访问能力。但是,端口宽度自动调整仅支持标准 C 语言数据类型,不支持非聚合类型,例如,ap_int
、ap_uint
、struct
或 array
。
重要: 接口上的结构体会阻止端口的自动拓宽操作。您必须将结构体拆分为多个独立元素才能启用该功能。
Vitis HLS 使用以下 2 条命令来自动调整端口宽度:
-
config_interface -m_axi_max_widen_bitwidth <N>
:指令该工具将 M-AXI 接口上的突发自动拓宽至指定的位宽。<N> 的值必须为 2 的幂(介于 0 到 1024 之间)。 -
config_interface -m_axi_alignment_byte_size <N>
:请注意,突发拓宽还需要强大的对齐属性。假定映射到m_axi
接口的指针至少对齐到所提供的宽度(以字节为单位,值为 2 的幂)。这样有助于自动进行突发拓宽。
在 Vitis 内核流程中,默认通过以下命令启用自动调整端口宽度大小功能。
config_interface -m_axi_max_widen_bitwidth 512
config_interface -m_axi_alignment_byte_size 64
在 Vivado IP 流程中,默认禁用此功能:
config_interface -m_axi_max_widen_bitwidth 0
config_interface -m_axi_alignment_byte_size 0
仅当工具可看到突发访问时,自动调整端口宽度大小功能才能调整端口大小。因此,突发所需的所有前置条件(如 AXI 突发传输 中所述)都必须得到满足后才能调整端口大小。这些前置条件包括:
- 必须按单调递增访问顺序(访问的存储器位置和访问时间两方面都是如此)。不能访问位于先前访问的两处存储器位置之间的存储器位置,即没有重叠。
- 从全局存储器进行访问时使用的模式应采用顺序访问模式,并具有下列附加要求:
- 需对非矢量类型执行顺序访问
- 顺序访问的起始位置需对齐到拓宽后的字大小。
- 顺序访问的长度需被拓宽因子整除。
以下代码示例在后续计算过程中使用:
vadd_pipeline:
for (int i = 0; i < iterations; i++) {
#pragma HLS LOOP_TRIPCOUNT min = c_len/c_n max = c_len/c_n
// Pipelining loops that access only one variable is the ideal way to
// increase the global memory bandwidth.
read_a:
for (int x = 0; x < N; ++x) {
#pragma HLS LOOP_TRIPCOUNT min = c_n max = c_n
#pragma HLS PIPELINE II = 1
result[x] = a[i * N + x];
}
read_b:
for (int x = 0; x < N; ++x) {
#pragma HLS LOOP_TRIPCOUNT min = c_n max = c_n
#pragma HLS PIPELINE II = 1
result[x] += b[i * N + x];
}
write_c:
for (int x = 0; x < N; ++x) {
#pragma HLS LOOP_TRIPCOUNT min = c_n max = c_n
#pragma HLS PIPELINE II = 1
c[i * N + x] = result[x];
}
}
}
}
上述代码的自动最优化宽度需通过 3 个步骤来执行:
- 该工具检查 read_a 循环中的访问模式数量。每个循环迭代期间有一次访问,因此最优化判定接口位宽为 32= 32 *1(整数变量位宽 * 访问次数)。
- 该工具会尝试使用以下表达式来达到
config_interface m_axi_max_widen_bitwidth 512
指定的默认最大值。length = (ceil((loop-bound of index inner loops) * (loop-bound of index - outer loops)) * #(of access-patterns))
- 在以上代码中,外层循环为非完美循环,因此外层循环上将不存在突发传输。因此,长度将仅包含内层循环。因此,该公式将缩短为:
length = (ceil((loop-bound of index inner loops)) * #(of access-patterns))
或者:length = ceil(128) *32 = 4096
- 在以上代码中,外层循环为非完美循环,因此外层循环上将不存在突发传输。因此,长度将仅包含内层循环。因此,该公式将缩短为:
- 计算所得是否为 2 的幂?如果是,那么长度将限为
m_axi_max_widen_bitwidth
所指定的宽度。
使用端口宽度自动调整功能有利有弊,您需在使用时审慎考量:此功能可缩短来自 DDR 的读取时延,因为该工具读取的是大矢量而不是数据类型大小。它还会添加更多必要资源,以缓冲巨型矢量,并将数据相应转换为数据路径大小。