Dataflow
数据流是另一种数字设计技术,在概念上类似于流水线。数据流的目标是在粗粒度级别上表示并行性。就软件执行而言,这种转换适用于单个程序中函数的并行执行。
Vivado HLS通过基于输入和输出评估程序不同功能之间的交互来提取这种级别的并行性。最简单的并行情况是函数在不同的数据集上工作并且彼此不通信。在这种情况下,Vivado HLS为每个函数分配FPGA逻辑资源,然后独立地运行模块。更复杂的情况是,一个函数为另一个函数提供结果,这是软件程序中的典型情况。这种情况称为消费者-生产者情景。
Vivado HLS支持消费者-生产者场景的两种使用模型。
在第一个使用模型中,生产者在消费者开始操作之前创建一个完整的数据集。并行性是通过实例化一对排列为内存库ping和pong的BRAM内存来实现的。在函数调用期间,每个函数只能访问一个内存库(ping或pong)。当新的函数调用开始时,HLS生成的电路切换生产者和消费者的内存连接。这种方法保证了函数的正确性,但限制了跨函数调用的可实现并行性水平。
在第二个使用模型中,使用者可以开始使用生产者的部分结果,并且可实现的并行级别被扩展到包括函数调用中的执行。Vivado HLS为这两个功能生成的模块通过使用先进先出(FIFO)内存电路连接。该存储器电路在软件编程中充当队列,提供模块之间的数据级同步。
在函数调用期间的任何时候,两个硬件模块都在执行其编程。唯一的例外是消费者模块在开始计算之前等待生产者提供一些数据。在Vivado HLS术语中,用户模块的等待时间称为间隔或启动间隔(II)。
硬件设计的基本概念
处理器和FPGA之间的关键区别之一是处理架构是否固定。这种差异直接影响每个目标的编译器的工作方式。性能是应用程序映射到处理器功能的程度以及正确执行所需的处理器指令数的函数。
相比之下,FPGA类似于一块有一盒构建块的白板。HLS编译器的工作是从最适合软件程序的构建块盒中创建处理架构。指导Vivado HLS编译器创建最佳处理体系结构的过程需要硬件设计概念的基础知识。
时钟频率
处理器时钟频率是确定特定算法的执行平台时要考虑的第一项之一。一个常用的准则是,高时钟频率转换为算法的更高性能执行率。
延迟和流水线
延迟和流水线是HLS中的重要概念,延迟表示执行完成一次运算或者任务需要的时间,是完成一条或一组指令以生成应用程序结果值所需的时钟周期数。应用程序延迟是FPGA和处理器的关键性能指标。在这两种情况下,延迟问题都是通过使用流水线 来解决的。在处理器中,流水线意味着下一条指令可以在当前指令完成之前启动执行。这允许指令集处理中所需的开销阶段重叠。处理器流水线的最佳情况结果如图所示。
通过重叠指令的执行,处理器实现了五条指令应用程序九个时钟周期的延迟。
在FPGA中,不存在与指令处理相关的开销周期。但在FPGA中进行流水线处理的原因与在处理器中进行流水线处理的原因相同,为了提高应用程序性能。
FPGA中的流水线是插入更多寄存器以将大型计算块分解为较小段的过程。这种计算分区增加了绝对时钟周期数的延迟,但通过允许自定义电路以更高的时钟频率运行来提高性能。
吞吐量
吞吐量也可以表示为输入(输出)延时,表示每两次输入或者输出之间的时间间隔。吞吐量是用于确定实现的总体性能的另一个指标。它是处理逻辑接受下一个输入数据样本所需的时钟周期数。
内存体系结构和布局
通用内存体系结构由基于将数据传输到处理器所需的时钟周期数的慢、中或快的内存组成。
此表中显示的内存体系结构假设向用户提供单个大内存空间。 在这个内存空间内,用户分配和释放区域来存储程序数据。 在这种系统中,提高性能的唯一方法是尽可能多地重用缓存中的数据。
为实现这一目标,软件工程师必须花费大量时间查看缓存跟踪、重构软件算法以增加数据局部性,并管理内存分配以最小化程序的瞬时内存占用。尽管所有这些技术都可以跨处理器移植,但结果却并非如此。 软件程序必须针对它运行的每个处理器进行调整,以最大限度地提高性能。
凭借使用基于处理器的存储器的经验,软件工程师在处理 FPGA 中的存储器时遇到的第一个区别是缺乏固定的片上存储器架构。
基于 FPGA 的系统可以连接到慢速和中速存储器,但在可用的快速存储器方面表现出最大程度的差异。 也就是说,Vivado HLS 编译器不是重构软件以最好地利用现有缓存,而是构建了一个快速内存架构,以最适合算法中的数据布局 。 最终的 FPGA 实现可以有一个或多个不同大小的内部组,这些组可以相互独立地访问。
FPGA 代码缺乏动态内存分配。如果想进行内存分配必须把大小固定。Vivado HLS 编译器构建了一个为应用量身定制的内存架构。这种定制的内存架构是由程序中内存块的大小以及在整个程序执行过程中如何使用数据来塑造的。当前最先进的 FPGA 编译器(例如 Vivado HLS)要求在编译时完全可分析应用程序的内存需求。
静态内存分配的好处是 Vivado HLS 可以以不同的方式为数组 A 实现内存。 根据算法中的计算,Vivado HLS 编译器可以将 A 的内存实现为寄存器、移位寄存器、FIFO 或 BRAM。
寄存器
内存的寄存器实现是最快的内存结构。 在这种实现风格中,A 的每个条目都成为一个独立的实体。 每个独立实体都嵌入到计算中,无需处理逻辑或额外延迟即可使用。
移位寄存器
在处理器编程术语中,可以将移位寄存器视为队列的一种特殊情况。 在这个实现中,A 的每个元素在计算的不同部分被多次使用。 移位寄存器的关键特性是可以在每个时钟周期访问 A 的每个元素。 此外,将所有数据项移动到下一个相邻的存储容器只需要一个时钟周期。
许多 C 算法通过数组顺序移动数据。将一个新值添加到数组的开头,通过数组移位现有数据并删除最旧的数据。C语言中没有和移位寄存器完全吻合的语法元素。
SRL架构资源最有效地实现所需的移位寄存器。当在移位寄存器中间访问数据时,逻辑综合不能直接推断 SRL 。 但是逻辑综合可能使用触发器实现移位寄存器的电路。
移位寄存器,移位寄存器是一种存储器,存在里边的数据可以从低位向高位移动或从高位向低位移动。
为了利用移位寄存器,HLS提供了ap_shift_reg 类,以便于进行使用移位寄存器资源。
FIFO
可以将 FIFO 视为具有单个入口点和单个出口点的队列。这种结构通常用于在程序循环或函数之间传输数据。不涉及寻址逻辑,实现细节完全由 Vivado HLS 编译器处理。
BRAM
BRAM是嵌入FPGA结构中的随机存取存储器。Xilinx FPGA设备包括许多这样的嵌入式存储器。存储器的确切数量取决于设备。在处理器编程术语中,这种内存可以被视为具有以下限制的缓存:
- 不实现通常在处理器缓存中发现的缓存一致性、冲突和缓存未命中跟踪逻辑。
- 仅在设备通电时保持其值。
- 支持对两个不同内存位置的并行同周期访问。
reference
- UG998