Intel® 高层次综合编译器专业版Pro版: 参考手册

ID 683349
日期 12/04/2023
Public
文档目录

4.4.3.2. 存储器访问合并和加载-存储单元

Intel® HLS Compiler可能会将多个存储器访问合并为一个更宽的存储器访问,以节省实例化LSU的个数。

当编译器合并存储器访问时,被称为static coalescing,因为合并发生在编译时。这种静态合并与dynamic coalescing由突发合并LSU完成。

当编译器检测到多个存储器操作访问存储器中的连续位置时,通常会尝试静态合并。这种合并通常会有益处,因为它减少了争夺共享存储器接口的LSU个数。

编译器合并的存储器访问最高达到已访问存储器接口的宽度。对于外部存储器接口,最大宽度由您正在访问的外部存储器属性预先确定。对于组件(内部)存储器接口,编译器可以根据编译器创建的存储器几何结构设置最大宽度。有关组件存储器的更多详细信息,请参阅组件存储器(存储器属性)

对于以下代码实例, Intel® HLS Compiler将4字节宽的加载操作静态合并为一个16字节宽的加载操作。对四个存储操作也进行了类似的合并。合并加载和存储操作可将对Avalon MM Host接口所需的访问次数减少到4次。

#include "HLS/hls.h"

component void
static_coalescing(ihc::mm_host<int, ihc::dwidth<128>, ihc::awidth<32>,
                               ihc::aspace<1>, ihc::latency<0>> &in,
                  ihc::mm_host<int, ihc::dwidth<128>, ihc::awidth<32>,
                               ihc::aspace<2>, ihc::latency<0>> &out,
                  int i) {
  // Four loads statically coalesced into one 16 bytes wide load
  int a1 = in[3 * i + 0];
  int a2 = in[3 * i + 1];
  int a3 = in[3 * i + 2];
  int a4 = in[3 * i + 3];

  // Four stores statically coalesced into one 16 bytes wide store
  out[3 * i + 0] = a4;
  out[3 * i + 1] = a3;
  out[3 * i + 2] = a2;
  out[3 * i + 3] = a1;
}
此实例的High-Level Design Reports(高级设计报告)中System Viewer显示为,该设计仅有一个加载和一个存储,每个宽度为128位。
图 6. System Viewer显示合并的存储器访问


如果您的编码风格可以保证存储器访问不会出现不对齐的情况,则编译器可以推断出静态合并的对齐LSU。请考虑如下代码实例:
component int alignedRead(AHost &A, unsigned int i)
{
    hls_register int memory_line[PARALLEL_WORDS] = {};

    int word_base = PARALLEL_WORDS * (i / PARALLEL_WORDS);

#pragma unroll
    for (int j = 0; j < PARALLEL_WORDS; j++)
    {
        int idx_base = PARALLEL_WORDS * ((i + j) / PARALLEL_WORDS);
        bool doesntWrap = idx_base == word_base;

        if (doesntWrap)
        {
            memory_line[j] = A[i + j];
        }
    }
    ...
}

编译器推断出一个非对齐LSU,因为编译器无法确定j的所有值都是从存储器A的相同字读取而来。即使j的范围恰好好与存储器的一个字匹配,该访问仍然可能会换行到另一个字。可能需要多次读取。如果您以字宽对齐为基础编写访问的代码,则编译器可以保证不会发生换行,从而编译器会为您提供对齐的LSU。