自动调整端口宽度大小 - 2021.2 Chinese

Vitis 高层次综合用户指南 (UG1399)

Document ID
UG1399
Release Date
2021-12-15
Version
2021.2 Chinese

Vitis 工具流程中,Vitis HLS 能够自动将 m_axi 接口端口的大小调整为 512 位,以改善突发访问能力。但是,端口宽度自动调整仅支持标准 C 语言数据类型,不支持非聚合类型,例如,ap_intap_uintstructarray

重要: 接口上的结构体会阻止端口的自动拓宽操作。您必须将结构体拆分为多个独立元素才能启用该功能。

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 个步骤来执行:

  1. 该工具检查 read_a 循环中的访问模式数量。每个循环迭代期间有一次访问,因此最优化判定接口位宽为 32= 32 *1(整数变量位宽 * 访问次数)。
  2. 该工具会尝试使用以下表达式来达到 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

  3. 计算所得是否为 2 的幂?如果是,那么长度将限为 m_axi_max_widen_bitwidth 所指定的宽度。

使用端口宽度自动调整功能有利有弊,您需在使用时审慎考量:此功能可缩短来自 DDR 的读取时延,因为该工具读取的是大矢量而不是数据类型大小。它还会添加更多必要资源,以缓冲巨型矢量,并将数据相应转换为数据路径大小。