端口宽度自动调整 - 2023.2 简体中文

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

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 简体中文

Vitis 工具流程中,Vitis HLS 能够自动将 m_axi 接口端口的大小调整为 512 位,以改善突发访问能力。但是,端口宽度自动调整仅支持标准 C 语言数据类型和 2 的幂值 struct 大小,其中对指针分配拓宽后期望的字节大小。如果该工具无法自动拓宽此端口,那么您可通过使用矢量或任意精度 (AP) 作为该端口的数据类型来手动更改端口宽度。

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

Vitis HLS 使用以下 2 条命令来自动调整端口宽度:

  • syn.interface.m_axi_max_widen_bitwidth=<N>:指令该工具将 M-AXI 接口上的突发自动拓宽至指定的位宽。<N> 的值必须为 2 的幂(介于 0 到 1024 之间)。
  • syn.interface.m_axi_alignment_byte_size=<N>:请注意,突发拓宽还需要强大的对齐属性。假定映射到 m_axi 接口的指针至少对齐到所提供的宽度(以字节为单位,值为 2 的幂)。这样有助于自动进行突发拓宽。
Vitis 内核流程中,默认通过以下命令启用端口宽度自动调整功能:
syn.interface.m_axi_max_widen_bitwidth=512
syn.interface.m_axi_alignment_byte_size=64
Vivado IP 流程中,默认禁用此功能:
syn.interface.m_axi_max_widen_bitwidth=0
syn.interface.m_axi_alignment_byte_size=1

仅当工具可看到突发访问时,端口宽度自动调整功能才能调整端口大小。因此,突发所需的所有前置条件(如 AXI 突发传输 中所述)都必须得到满足后才能调整端口大小。这些前置条件包括:

  • 必须按单调递增访问顺序(访问的存储器位置和访问时间两方面都是如此)。不能访问位于先前访问的两处存储器位置之间的存储器位置,即没有重叠。
  • 从全局存储器进行访问时使用的模式应采用顺序访问模式,并具有下列附加要求:
    • 顺序访问需在原语类型或非矢量的 2 的幂大小的聚合类型上进行
    • 顺序访问的起始位置需对齐到拓宽后的字大小
    • 顺序访问的长度需被拓宽因子整除

以下代码示例在后续计算过程中使用:

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))
    • 在上述代码中,该工具支持非完美循环嵌套。如果 a 和 b 捆绑到相同端口,那么由于冲突,该工具将不会在 a 和 b 上扩展突发。如果 a 和 b 捆绑到不同端口,那么该工具将在 a 和 b 上将突发扩展至外层循环。因此,该公式将缩短为:
      length = (ceil((loop-bound of index inner loops)) * #(of access-patterns))

      或者:length = ceil(128) *32 = 4096

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

使用端口宽度自动调整功能有利有弊,您需在使用时审慎考量。此功能特性改善的是访问吞吐量,而不是数据类型大小。它还会添加更多必要资源,以缓冲巨型矢量,并且可能需要将数据相应转换为数据路径大小。