Intel®高层次综合编译器专业版: 最佳实践指南

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

3.3.4.1. 组件存储器

如果您在组件内声明一个数组, Intel® HLS Compiler在硬件中创建组件存储器。组件存储器有时被称为local memory(本地存储器)或者on-chip memory(片上存储器),因为它是从FPGA上可用的存储资源(例如,RAM块)创建的。

运行以下源代码片段会创建组件存储器系统、外部存储器系统的接口以及对这些存储器系统的访问:

#include <HLS/hls.h>

constexpr int SIZE = 128;
constexpr int N = SIZE - 1;

using HostInterface = ihc::mm_host<int, ihc::waitrequest<true>, 
                                       ihc::latency<0>>;

component void memoryComponent(HostInterface &hostA)
{
    hls_memory int T[SIZE]; // declaring an array as a component memory
    for (unsigned i = 0; i < SIZE; i++)
    {
        T[i] = i; // writing to component memory
    }
    for (int i = 0; i < N; i += 2)
    {
        // reading from a component memory and writing to a external 
        // Avalon memory-mapped agent component through an Avalon
        // memory-mapped host interface
        hostA[i] = T[i] + T[i + 1];
    }
}

编译器执行以下任务来构建存储器系统:

  • 从FPGA存储资源器(例如,RAM块)构建组件存储器,并将其作为单个存储器提供给数据通路。
  • 将每个数组访问映射到数据通路中的加载存储单元(LSU),该数据通路通过其端口与组件存储器进行事务处理。
  • 自动优化组件存储器几何结构,以最大限度地提高可用带宽以用于数据通路中的加载和存储。
  • 尝试保证组件存储器访问永不停顿。
要了解关于控制存储器系统架构的更多信息,请查看以下主题:

可停顿和无停顿存储器系统

对存储器的访问(读或写)可以无停顿或可停顿:
无停顿(Stall-free)存储器访问
如果存储器端口进行无争用访问,则存储器访问无停顿。如果存储器系统的每个存储器操作都是对存储器端口的无争用访问,则该存储器系统无停顿。
可停顿存储器访问
如果存储器访问对存储器端口是争用性访问,则该存储器访问可停止。当两个数据通路LSU尝试在同一时钟周期内与存储器端口进行事务处理时,这些存储器访问之一会被延时(或停顿),直到被争用的内存端口变为可用。

Intel® HLS Compiler会尝试为您的组件尽可能多地创建无停顿的存储器系统。

图 22. 无停顿和可停顿存储器系统的示例
该图显示了以下实例存储器系统:
  • A:无停顿存储系统

    该存储系统无停顿,因为即使读操作被调度到同一周期中,它们也被映射到不同的端口。不存在对存储器端口的访问争用。

  • B:无停顿存储器系统

    该存储器系统无停顿,因为两次读操作被静态调度到不同时钟周期中发生。两次读操作可以共享一个存储器端口,而不会出现任何读操作访问争用。

  • C:可停顿存储器系统

    该存储器系统可停顿,因为在同一周期中两次读操作被映射到同一端口。两次读操作同时发生。读操作需要冲突仲裁来调度它们的端口访问请求,并且仲裁会影响吞吐量。



组件存储系统由以下部分组成:
端口
存储器端口是存储器的物理访问点。端口连接到数据通路中的一个或多个加载存储单元(LSU)。LSU可以连接到一个或多个端口。一个端口可以连接一个或多个LSU。
Bank
存储器bank是组件存储系统的一个部分,它包含存储数据的子集。也就是说,为组件存储的所有数据都分为不同的Bank,每个Bank包含唯一的存储数据。

存储器系统始终至少有一个bank。

复制
存储器bank 复制是存储器bank中通过其自有端口复制的数据副本。Bank中的所有复制都包含相同的数据。可以独立于其它复制项单独访问每个复制项

一个存储器bank始终至少有一个复制项。

专用副本(Private Copy)
专用副本是在复制项中针对嵌套循环创建的数据副本,以启用外循环的并发迭代。

复制可以包含多个专用副本,外循环的每次迭代都有其自己的专用副本。由于每个外循环迭代都有其自己的专用副本,因此专用副包含的数据应该不会全部相同。

下图说明了bank、复制(replicate)、端口和专用副本之间的关系:

图 23. 显示Bank、复制(Replicate)、端口和专用副本之间关系的组件存储器原理图


启用并发无停顿存储器访问的策略

编译器使用多种策略来确保并发访问无停顿,包括:

  • 调整存储器系统的端口数量。可以通过复制存储器来启用更多读操作端口,或者通过以两倍的组件时钟速度对RAM块进行计时,使能每复制(Replicate)四个端口而非两个端口。

    以两倍的组件时钟速度对RAM块提供时钟,以使存储器系统的可用端口数量加倍,称之为双泵(double pumping)。

    复制(replicate)的所有物理访问端口都可以并发访问。

  • 将存储内容划分为一个或多个bank,使得每个bank包含原始bank中包含的数据的子集(对应于显示bank、复制、端口和专用副本之间关系的局部存储器原理图的右上角的框图)。

    组件存储器的bank可以通过数据通路并发访问。

  • 复制bank以创建多个连贯的复制内容(对应于显示bank、复制、端口和专用副本之间关系的局部存储器原理图中左下框图)。bank中的每个复制都包含相同的数据。

    复制的内容被并发加载。

  • 创建在循环嵌套内声明的数组的专用副本(对应于显示Bank、复制、端口和专用副本之间关系的局部存储器原理图中的右下角框图)。

    这些专用副本启用循环流水线,因为每个流水线并行循环迭代都会访问其自己在循环体中声明的数组的专用副本。专用副本包含的数据应该不相同。

即使编译器尽力发挥功能,由于源代码中定义的资源限制或存储器属性,仍然可能造成组件存储器系统停顿。这种情况下,编译器会尝试最小化被仲裁的存储器系统消耗的硬件资源。