可编程逻辑
今天给大家推荐今年FCCM2021上的一篇文章,介绍了一种可以在线Xilinx FPGA内部RAM内容的工作,重点是论文相关的工作还是开源的。
摘要:XBERT是一个API和设计工具集,用于使用设备的配置路径零成本访问Xilinx体系结构上的片上SRAM块。XBERT API是高级别的,允许开发人员根据应用程序源代码中的逻辑内存指定类似DMA的内存内容数据传输,因此基本上适用于任何针对Xilinx设备的设计。应用程序开发人员可以广泛地访问XBERT,它隐藏了物理映射和比特流编码的底层细节。XBERT是高效的,消耗的可重构资源为零,对Fmax没有影响。XBERT在Xilinx UltraScale+MPSoC Zynq上实现了每秒3–14兆字节(MB/s)的带宽,并在不到0.5毫秒的时间内完成了36Kb块RAM中内存的回读和转换。
1. 简介
今天的FPGA结构包括大量的分布式、嵌入式RAM块。虽然这些嵌入式RAMs最常见的用途是在FPGA结构上提供和存储计算过程中使用的数据,但从结构外部加载数据或输入或检索存储为计算输出的数据是必要的。
我们可以使用FPGA结构资源和专用结构输入/输出通道(例如AXI通道)来将数据移入和移出这些嵌入式存储器,但这会消耗FPGA结构资源以及嵌入式RAM原语上有限的读/写端口。而且,这种额外的逻辑可能会对满足应用程序计时要求带来挑战[1]。
这些嵌入式RAMs的内容也可以通过现有的专用片上网络(比特流重新配置路径)访问。因此,应该可以使用比特流重新配置路径来在不消耗任何FPGA结构资源的情况下将数据移入和移出这些嵌入式RAM块。此外,在具有嵌入式处理器的SoC FPGAs上,处理器可以作为系统计算的一部分来管理重构。
然而,将原始设计源中的逻辑内存映射到FPGA结构上的物理内存是一项具有挑战性的任务。一旦实现工具将一个较大的逻辑内存映射到多个较小的内存上,那么识别哪个物理BRAM原语保存特定的逻辑数据对于应用程序编程人员来说是不容易发现的,并且每次更改设计源并将其重新映射到FPGA时都可能发生变化。此外,用于比特流编程的数据格式与存储数据的逻辑格式不同逻辑存储器的位在BRAM初始化字符串中没有整齐地按升序排列,并且这些初始化字符串中的位随后分散在多个配置帧中。
为了满足这些需求,我们创建了Xilinx Bitstream Embedded RAM Transmission(XBERT)API,以提供一个高级接口来读取和写入逻辑内存的内容,正如应用程序开发人员在源代码级(如RTL、HLS、IP块)设计中看到的那样[1]。
透析(Transfusion)操作是读写操作的结合,它提取旧的BRAM内容并提供新的BRAM内容。重要的是,这些合并的输入操作可以比使用单独的读写操作更有效。
我们的自动工具流提取有关逻辑内存如何映射到物理嵌入式RAMs的信息,以允许XBERT API对这些内存进行操作。我们的API能够在几分之一毫秒内读取结果数据并将其转换为逻辑内存格式,从而提供以MB/s为单位的有效数据传输速率。这不如专用高速链路(例如,5 GB/s的AXI通道)快,但对于不经常访问的内存(例如,在启动时使用唯一数据编程或在程序完成时恢复数据)或中等带宽(例如,周期性参数调整)足够,具体可见节II和III-F。值得注意的是,这是在不减少Fmax或FPGA资源消耗的情况下实现的。
我们的贡献包括:
一个API,用于提供对存储在FPGA结构的嵌入式RAM中的内存的逻辑访问(第五节)
UltraScale+MPSoC Zynq的XBERT API的开源实现,包括提取逻辑↔单个内存位的物理映射和运行时支持读取和写入正在运行的FPGA内存内容(在[2]处在线)
逻辑到物理位映射的定制压缩技术,将转换表大小从兆字节减少到千字节(第七节)
基于表格的加速,可减少单个BRAM转换时间,与DMA传输时间(第八节)
API实现性能的表征(第九节)
2. 用场景
XBERT提供的一般功能有许多用例。编程BRAM配置的覆盖架构是不经常修改嵌入式RAM内容的一个明显需求,包括更新嵌入式软处理器中的程序内存内容,如RISC-V处理器核[3]、[4]、自定义VLIW[5]、自定义的VLIW[5]、[6]和向量[7]、[8]处理器。这种需要加载的指令也适用于更专业的覆盖结构的加载配置,如专用的FSM评估器[9]、[10]和神经网络[11]或模拟器[12]。
另一个用例是FPGA构建块的高速单元测试,在这里需要以全速率向被测模块提供数据并捕获结果。这可以用一个存储器将数据源输入被测模块,用另一个存储器记录结果。类似地,在使用内部逻辑分析器(ILA)或跟踪缓冲区[13]、[14]进行实时调试以在操作期间捕获数据时,我们在测试后卸载这些数据的速度通常并不重要。
最后,在极端情况下,XBERT功能可以提供一种廉价的方式来支持当前FPGA上的高级抽象,如CoRAM[15]。CoRAM提议增加专用的基础设施来管理嵌入式RAMs和中央内存之间的数据移动,并演示了在FPGA上构建覆盖网络的原型。使用XBERT,可以使用现有的重配置路径硬件支持提供相同的功能,而无需增加覆盖逻辑。
3. XBERT:概述、挑战和解决方案
本节介绍XBERT,包括XBERT这样的系统面临的挑战和操作要求,以及解决这些问题的方法和由此带来的好处。
》3.1 基本单BRAM操作
首先,考虑一下将映射到单个36Kb BRAM的简单逻辑内存的内容进行更改的简单用例。如果逻辑内存恰好是XPM实例化的内存,那么在主机上运行的Xilinx的UpdateMem程序可以更改完整比特流中的BRAM。运行Update Mem需要4秒来更改比特流以反映新的BRAM内容,而将完整的比特流加载到XCU3EG需要9毫秒。这既慢又需要使用单独的主机。
使用XBERT中最简单的write API(bert_write),我们可以在Zynq的嵌入式APU内核上运行代码时执行更新,并在1.04毫秒(快3900倍)内编写BRAM。这包括0.71 ms用于转换位(将逻辑存储器位描述转换为部分比特流)和0.25 ms用于通过Zynq PCAP将部分比特流写入设备;写入速度达到3.9MB/s带宽。重要的是,这个XBERT写操作适用于任何逻辑内存,而不仅仅是那些用XPM实例化的内存。
》3.2 基于表的转换、压缩和加速
UpdateMem运行时使用完整的Xilinx设备数据库(用于部件)和完整的设计检查点数据集(用于设计),XBERT将此信息替换为一个最小的转换表,该表描述每个逻辑内存位映射到比特流的位置。XBERT中的原始转换表最初需要238KB,但是使用压缩可以将其减少到2.3KB(第七节)。
上述1.04 ms XBERT时间的主要组成部分是翻译(0.71 ms),主要包括从逻辑存储器图像计算各个位的比特流位置。当我们向XBERT(第八节)添加一个加速的、基于表的多位翻译功能时,我们可以将其减少到0.28毫秒,因此整个写操作在0.62毫秒内完成,吞吐量为6.59 MB/s—大约是未加速情况下的两倍。
》3.3 Transfusion-组合操作以提高性能
谈到单个BRAM内存的最小DMA传输时间,我们注意到它很大(0.25毫秒),部分原因是写入发生在帧中,需要为UltraScale+体系结构中共享一帧的所有12个内存写入数据(图3)。如果我们需要在一个帧中写入多个BRAM,或者因为一个逻辑内存使用多个BRAM,或者因为我们需要写入多个恰好共享一个物理帧的逻辑内存,那么我们可以减少每个BRAM的DMA传输时间。在极端情况下,我们将每BRAM DMA传输成本降低了12倍,约为0.021 ms,因此每BRAM总写入成本约为0.32 ms(或11.75 MB/s的吞吐量,约为单次加速吞吐量的两倍)。因此,有一个scatter-gather接口是非常有效的,它允许我们指定要作为单个操作写入的完整逻辑内存集,这样API就可以最小化所需的帧写入次数。我们的transfuse API接口提供了此功能(第五节)。
虽然有写使能允许我们一次在一个帧中写入一个36Kb的BRAM,但是没有写使能控制在一个36Kb的BRAM中独立地写入两个18Kb的内存。要单独写入一个18Kb内存,我们可能需要先读取整个帧,以便在块中保留伙伴18Kb内存的值。XBERT transfuse API可以将此回读与同一物理帧(秒)中其他逻辑内存的读取结合起来(第五节)。
》3.4 处理较大内存-逻辑到物理内存映射
为了简单起见,上面的示例使用了只映射到单个BRAM的逻辑内存。在实践中,逻辑记忆常常映射到多个物理内存。当这种情况发生时,有很多选择如何将位打包到内存中。例如,在一个32×10000内存,我们已经看到Vivado将内存的底部18b([17:0])映射为5个18×2048RAMB36s,下一个9b([26:18])到三个9×4096RAMB36s,下一个4b([30:27])到两个4×8192 RAMB36s,最后一位([31])为1×16384RAM36s;这种非均匀映射只使用11个RAMB36,而在其他设计中,我们看到Vivado将一个大小类似的内存映射到一组16个RAMB36内存,每个内存宽2位,深16K个字。
最后,对于小于单个BRAM的内存,Vivado可能会将高阶地址位绑定到0以外的值,这意味着内存的逻辑0位置不会从正常预期的位置(物理BRAM的帧集的第一帧)开始。
为了解决这些复杂而繁琐的物理映射问题,XBERT工具流自动从Vivado Design CheckPoint(DCP)文件或项目中提取这些映射细节,作为其逻辑到物理内存映射功能的一部分。因此,应用程序开发人员不需要处理这些问题,他们能够专门处理逻辑内存内容,XBERT对他们隐藏了许多映射细节(第五节)。
》3.5 XBERT设计流程摘要
图1示出了XBERT的主机侧准备工具流程。从顶部开始,对用户的设计(以设计检查点的形式最少地表示)进行处理,以提取原始设计源中包含的逻辑内存的信息,从而生成一个MDD文件(第4-D节)。然后将其与从Xilinx生成的.ll文件中提取的比特流信息结合起来,为设计创建逻辑到物理内存映射信息的完整表示(mydesign_uncompressed.{c,h})。然后对其进行压缩和可选的加速,以生成一个mydesign.c文件,其中包含作为c数据结构的该信息的压缩版本。
在图的底部,最终的XBERT应用程序由三组源代码组成:(1)XBERT运行时源代码(bert.c),(2)mydesign.c文件,以及(3)用户的应用程序代码(application.c)。
这与XBERT的扩展xilfpga库(第六节) 进入最终可执行的应用程序。
图1:XBERT工具流程
》3.6 一个充分激励的例子
考虑开发一个包含四个独立存储器的哈夫曼编码加速器。这个哈夫曼编码器接收字节流,并通过将每个字节映射到一个可变长度的代码来压缩它。而且,为了获得好的压缩效果,哈夫曼码应该调整到被编码的数据。
我们将编码器设计为使用编码表(内存#1)进行任何编码,并且可以在更改编码时使用XBERT更新其内容。HDL源代码中的编码表是只读的,但是我们可以使用bert_write来加载它的内容。加载表需要1.1毫秒。如果没有XBERT,我们将需要使用AXI端口来执行加载,这样会更快,但会在设计中添加LUT和寄存器(表1)。
表1:在HUFFMAN示例中添加AXI访问对内存的影响
当我们第一次设计编码器时,我们通常希望在将数据源和数据使用者添加到设计中之前测试它的功能和速度。我们可以通过添加一个内存来保存输入数据(内存2)和一个内存来存储输出数据(内存3)。使用XBERT我们不需要其他东西。我们可以使用bert_write将编码器要压缩的新数据加载到输入存储器中,并使用bert_read恢复压缩的输出。
我们还添加了一个直方图内存,使用256个元素的内存(内存4)捕获输入数据的特征。使用bert_read,我们可以在0.45毫秒内读回这个内存的内容。如果我们每个周期压缩一个字节,这个直方图需要在每个周期上执行读写操作,这意味着它的两个端口都被使用。对于提供回读的非XBERT设计,它需要共享一个端口或复制内存以有效地提供另一个读端口。对于XBERT,两者都不是必需的。
使用XBERT我们可以读取或写入设计中的四个存储器中的任何一个。我们可以读取直方图内存内容,根据输入数据流计算新的编码表,然后将新的编码表写回到设计中,所有这些都在1.2ms内完成。
选项卡。我展示了在设计中添加AXI接口的影响(面积,Fmax)。我们在AXI子系统和Huffman解码器之间使用MMCM,这样后者就可以以最大时钟速率运行,而不受最大AXI时钟速率333MHz的限制。由于这个Huffman示例很小,因此提供对BRAMs的访问的Fmax影响很小。在更大、高度拥挤的设计中,[1]声称消除AXI-BRAM访问可以实现高达63%的Fmax改进(第4-C节)。
4. 相关工作
》4.1 物理BRAM操作应用程序和工具
许多工具都利用了这样的情况,即它们可以提供有用的功能来处理原始BRAMs,而不需要映射或转换回逻辑级别。早在2000年,Xilinx就为嵌入式RAM的部分重新配置回读和重新加载提供了实验性的低级别支持[16],[17],主要用于内存回读和清理[18]。最近,ReconOS使用比特流读写进行多任务处理[19](通过比特流加载和卸载BRAM内容)。Metawire使用比特流将数据从BRAM移动到BRAM,以提供片上网络(NoC)功能;由于它们控制着BRAM映射并从一个BRAM转移到另一个BRAM,因此它们避免了从物理映射到逻辑映射的转换[20]。
类似地,有几部著作将直接BRAM写入特定的应用程序,包括[21]-[23]。
》4.2 物理比特流API
最近的工作希望为物理层的比特流操作提供一个API。BITMAN pro提供了一个通用的物理层访问机制,可以访问BRAM内容通过change_BRAM_content(X,Y,new_config)API[24]。与上述工具一样,它需要一些更高级别的接口或手动开发操作干预来确定哪些BRAM位置需要更改,并格式化配置数据,包括将逻辑位洗牌到它们在物理配置映射中的位置。
类似地,最近在[25]中的工作提倡使用比特流回读和编辑来读写BRAM内容的方法,并演示了如何在BRAM之间复制数据。但是,它不涉及识别哪些物理内存用于特定的逻辑内存。它也没有提供完整的描述或高级工具,允许开发人员将其HLS或RTL逻辑内存内容映射到比特流中,或者提取比特流内容并重建HLS或RTL内存的状态。
》4.3 专用逻辑内存操作
Maxeler探索使用比特流路径来加载和读取他们的“映射内存”,而不是单独的低速总线[1]。他们表明,去掉低速总线及其对结构资源的相关需求,可以将他们设计的性能提高高达63%。他们的比特流接口实现了高达2MB/s的数据传输带宽。
Maxeler的用法可能与XBERT提供的最为相似。然而,Maxeler(a)仅将此BRAM路径用于编译器内部生成的内存的特定用途,(b)不提供可供开发人员用于任何内存或任何工具链的通用API(c)他们的工具必须控制逻辑内存到BRAMs的映射,因为他们没有足够的信息来确定Xilinx工具如何将逻辑内存映射到物理内存。
类似地,Xilinx Vivado提供了对更改比特流中配置存储器初始值的支持,主要是为了支持微LAZE处理器的指令存储器[26]。这包括一个BRAM内存映射信息(MMI)文件,该文件记录用于支持MicroBlaze和Xilinx参数化宏(XPM)内存的物理BRAM,以及一个UpdateMEM工具,该工具可以使用逻辑内存文件中的数据更新比特流[27]。Vivado生成的MMI并没有覆盖设计中的所有逻辑内存,UpdateMEM只生成一个完整的比特流。
XBERT通过提供对比特流读写路径的开源逻辑级访问,填补了上述相关工作中的所有空白。它容纳了所有的设计,所有的记忆,以及所有通过DCPs的工具流。
》4.4 现有的比特流操作支持
有许多工具可用于创建比特流操作工具。XBERT系统在一定程度上是基于其中一些。
Xilinx工具长期以来一直为内存生成逻辑位置(LL)文件,作为比特流回读生成的一部分[28]。LL文件包含物理BRAM中每个数据位的帧和位位置,但不提供有关逻辑内存以及如何将逻辑内存映射到多个物理BRAM块的映射信息。尽管如此,LL文件对于破译XBERT内的BRAM的帧和位位置是有用的,如图1所示。
X-Ray项目[29]和最近的U-Ray项目[30]提供了将Xilinx 7系列和UltraScale+设备中的配置位映射到帧和位位置的数据库。它们不包含特定设计中逻辑到物理内存映射的信息,但提供了用于比特流编码的信息和工具(了解比特流中物理内存位的位置)。
在X-Ray项目的基础上,BYU开发了一个开源工具prjxray-bram-patch[31],它的作用与Vivado的UpdateMEM类似,但适用于设计中的所有逻辑内存和所有设计流。bram-patch工具定义了一个内存描述数据(MDD)文件,该文件的作用与Xilinx MMI文件类似。MDD文件源自使用Tcl的Vivado设计,它为设计中的每个逻辑内存描述了逻辑内存映射到的物理内存集合、逻辑内存位在物理内存之间的分区方式以及位如何打包到物理RAMB原语的INIT字符串中。XBERT系统将此信息用作逻辑到物理映射步骤的一部分(图1)。
5. XBERT API
XBERT设计用于在Zynq SoC上的嵌入式APU内核上运行。如图2所示,它提供了逻辑级接口,高于由xilfpga提供的接口或由诸如BITMAN的物理级比特流操作工具提供的接口[24]。它通过扩展xilfpga来实现这一点,并为BRAM写入提供部分重新配置支持和命令生成(第六节)。
图2:XBERT的API分层
注:Xilinx提供的浅红色;本工程提供浅蓝色;来自[24]的浅绿色。
入门级XBERT接口是一对简单的例程,提供一个类似DMA的接口来读取或写入整个逻辑内存。
这些例程处理内存的帧格式和逻辑格式之间的位洗牌,以及执行所需的部分重新配置读写。
为了支持这些API调用,XBERT预处理工具处理MDD文件(第IV-D节)生成文件mydesign.h和mydesign.c(图1)。其中包括设计中特定内存的C代码定义,包括逻辑到物理的转换表。
上述简单API的一个限制是,每个读或写调用首先执行逻辑到物理内存的转换,然后对设备执行比特流读或写操作。如果应用程序需要读取或更新映射到同一配置帧的多个不同逻辑内存,则这可能是低效的。
为了实现更高效的传输,XBERT还提供了一个API,可以读写一组多个内存,就像分散-聚集DMA操作一样。这是bert_transfuse()调用,允许XBERT执行一组帧读取、转换,然后执行一组帧写入,覆盖可能共享一组帧的所有逻辑内存:
Bert_transfuse例程使用一个数组来描述逻辑内存集合上的操作。为了描述每个transfusion操作,它使用了一个结构(bert_meminfo)。结构指定了内存、操作(读或写)以及我们正在内存中读或写的逻辑地址范围。为了支持比64b更宽的数据,这支持一个数组,每个数组槽有多个数据字。并且,通过指定起始地址和长度,我们允许对逻辑内存中的字子集进行操作。这允许访问和更新与保存逻辑存储器的数据的BRAMs相关联的帧的子集,当仅需要读取或写入存储器的一部分时,这是更有效的。传输操作还将写入数据集与PCAP控制指令一起排列,以便可以使用单个DMA写入传输来执行这些操作,从而最小化DMA设置的开销。
APIs假定执行读写操作是安全的。应用程序负责将计算置于安全状态,即在读或写过程中不写入内存。例如,使用Vivado/VitisHLS生成的标准Xilinx IP块级接口协议[32],可以监视要完成的块(ap_done),执行XBERT操作,然后重新启动模块(ap_start)。
6. 部分重构
部分重配置是在不影响剩余资源运行的情况下加载一部分FPGA资源的配置数据。在现代Xilinx设备中,配置的原子单元是沿FPGA列组织的帧。在Xilinx UltraScale+系列中,每帧有93个32b字。由于BRAM数据只占总比特流的一小部分,因此使用部分重新配置仅访问BRAM帧与完整的比特流读写相比减少了比特流读写时间。
在现代FPGA设备中,嵌入式ram被放置在列中。UltraScale+系列具有36Kb内存(RAMB36),每个内存可以交替配置为一对18Kb内存(RAMB18)。Xilinx UltraScale+系列设备中的每个帧包含12个RAMB36存储器[33,第8章,配置帧],每个RAMB36具有144b,两个RAMB18中的每个具有72b。覆盖BRAM组需要256帧(参见图3)。帧中每个BRAM的144b组被分组为240b块。在大致位于240b块中间的帧中,每个144b RAMB36组有一个写使能位。写入允许一次更新单个BRAM36,但始终需要以帧为单位传输数据。BRAM数据帧与保持路由或LUT配置的帧是分开的。
Zynq设备包括一个处理器配置访问端口(PCAP),允许嵌入式处理器读写配置帧。对于高速接入,处理器可以配置DMA数据传输到PCAP以执行部分重新配置操作。UltraScale+PCAP的带宽为4B,峰值工作频率为200 MHz,最高支持800 MB/s[33,第8章,配置时间]。
Xilinx提供了xilfpga库[34](图2),用于在Zynq UltraScale+组件上执行DMA比特流传输。它允许对包含到PCAP的控制命令头的.bit文件进行完全比特流加载、回读和部分比特流加载。
图3:UltraScale+BRAM内容的框架组织
XBERT提供了xilfpga API中例程的扩展版本(图2)。xilfpga没有提供一个基本的比特流回读操作,因此我们修改了读操作以同时接收帧地址和帧数。XBERT还提供了write的一个版本,它接受原始帧数据并填充配置命令来设置帧地址和指定写操作,因为将原始帧数据转换为适当的部分比特流需要这些命令。这种扩展是支持写操作所必需的,因为我们正在生成自己的帧集,并且没有通常由Vivado生成比特流时生成的比特流配置命令头。
由于缺乏流量控制,FPGA读回操作只能以低于200 MHz峰值操作(秒)的速率可靠运行(第六节。2019.2 xilfpga版本中的默认配置使用PCAP时钟发生器配置(PCAP _CTRL(CRL _APB)寄存器)将时钟设置为23.8 MHz,最高吞吐量为95 MB/s。我们的经验表明,150MHz可能工作可靠,最高吞吐量为600MB/s。
7. 压缩转换表
逻辑到物理转换表(第三节) 可能很大。如果我们简单地在一个BRAM中为每个位存储一个32b帧地址和一个16b位位置,那么转换表至少是48位× 比我们希望绘制的BRAM数据总量还要大。幸运的是,有一些结构。通常情况下,当多个位在同一帧中时,我们不需要为每个位存储帧。这样可以节省3倍。
为了进一步压缩,我们利用了位位置在帧间重复的方式。为了说明这一点,我们先来考虑一个简单的BRAM设计案例。单个帧将在其144位中保存一定数量的逻辑字。在72b宽的逻辑存储器的情况下,这可以是2个逻辑字;对于8b宽的逻辑内存,这可能是16个逻辑字。将Wframe定义为该值(上面的2或16)。对于每个连续的Wframe字组,帧内的偏移位置是相同的,这允许我们通过算法确定帧偏移量(逻辑地址/Wframe),并重用帧内(最多144)位到帧内偏移量的单个位映射。对于这种单BRAM设计,这意味着我们只需要存储一个帧地址(基址)和(最多)144位偏移地址(对于一帧中的2976位可以使用12b,但是我们舍入到16b)。所以,我们最多需要32+144×16=2336b而不是48×36864=1.7 Mbits,无压缩。
一般来说,我们必须支持逻辑内存映射到物理内存的各种方法。这可能意味着并行组织多个BRAMs以支持逻辑字宽度(例如,8个BRAMs,每个BRAMs提供32b字的4b),多个BRAMs覆盖不同的地址范围以处理深度内存(例如,2个BRAMs覆盖36x2048内存,其中一个处理地址0到1023,另一个处理地址1024到2047),或其组合。甚至在某些情况下,组件BRAMs具有不均匀的子宽度和子深度(例如第三节) 是的。因此,一般的压缩情况更需要处理这些额外的不规则性。尽管如此,帧之间还是有规律性的,可以用算法来描述。这使我们能够概括单个BRAM观测值,形成一个通用的压缩策略。利用这些观察,我们显著地压缩了翻译表(表3)。
8. 加速翻译
正如我们在表4中看到的,一旦我们加快了读DMA的速度,翻译时间就比DMA传输时间慢。即使使用预编译的表,代码仍然是一次提取和插入一位。我们实现了一种多位加速转换,其中我们预先计算字(或帧)中的位序列(例如,一个字节)的影响,以创建要应用于帧(或字)的位向量,并将它们存储在表中。
这减少了处理器周期,但需要更大的转换表。我们目前的实现支持这些针对单个BRAM存储器的转换表。
9. 评价
如第三章和贯穿本文的重点,XBERT传输的大小和性能高度依赖于设计,依赖于API的使用,并且受到我们的优化的影响。在本节中,我们将评估API在多个场景中的性能,以具体描述这些不同场景的性能影响。
》9.1 方法论
我们的实验使用Vivado 2018.3,包括SDK。嵌入式ARM处理器代码编译-O3。实验在Ultra96 v2板上进行,该板包括一个包含216个RAMB36的XCZU3EG。设计是在裸机配置上运行的。我们集成了2019.2版的xilfpga源代码,原因是2018.3版的xilfpga存在缺陷。
一个主要的性能指标是有效吞吐量。有效吞吐量解释了这样一个事实,即有用的数据只是在帧中传输的数据的子集。例如,如果我们只想在UltraScale+设备帧中包含一个RAMB36的内容,则每帧可获得144个相关位,但必须传输整个2976位帧。
为了说明典型的应用场景,我们提供了两个完整的设计。这些给出了帧如何从多个逻辑存储器共享BRAMs的一些指示。
哈夫曼编码-我们的Verilog设计来自第三章F节。它有4个逻辑内存,消耗4个18和3903个LUT。每个逻辑内存都可以放在一个内存中。
翻译-演示用的网表来自于Rosetta HLS基准电路 [35]。它有11个逻辑存储器,消耗41个ramb36、9个ramb18和11109个LUTs。一些内存是大的,需要很多的BRAMs。有些内存在没有定义位的地方有间隙。
》9.2 结果
① 原始比特流数据传输
表2显示原始比特流传输时间和原始有效吞吐量。这将显示DMA传输性能和含义,而不需要翻译所需的时间,这将在下一节中分开。注意,访问一个帧中的所有BRAM(单个BRAM帧集行)可以提供最高的有效吞吐量。由于BRAM帧中的大多数位是BRAM数据位,因此有效带宽超过原始带宽的一半。请注意,即使我们关心芯片上所有BRAM中的每一位BRAM,该有效带宽也高于完整的比特流读写,因为部分读取只是读取保存BRAM数据的帧。
表2:XCZU3EG上的原始比特流读写时间
注:“帧集”是包含单个BRAM的内容的256帧的集合(图3)。
24MHz是xilfpga中的读取速度;150MHz是我们能够可靠运行DMA回读的最高速度。
② 翻译
表III报告了转换表的大小和时间,以及在逻辑和框架表示之间进行转换的有效吞吐量。
表3:XCZU3EG上的翻译时间
表III表明我们可以将大约两个数量级的转换表缩减到千字节范围内(第七节)。压缩会稍微减慢翻译速度。加速度(第八节) 大约减半翻译时间,同时添加大约与未压缩表一样大的表。在渲染的11个内存中,有7个是单BRAM内存,但是这些内存只占4%的位,所以在转换所有内存时,加速的影响很小。
③ BERT API操作
单内存:表4总结了读写一篇简单的文章的表现×64个内存,填充一个36块。第一行显示默认的读取速度(第六节) 第二个显示了将PCAP DMA读取速度提高到150mhz(600MB/s)的影响。第三行显示压缩的影响;在这种情况下,它会稍微减慢翻译速度。第四行显示了加速度的影响,这大约是平移时间的一半。
表4:基于XZCU3EG的BERT-API单RAM36性能
注:24MHz是xilfpga中的读取速度;150MHz是我们能够可靠运行DMA回读的最高速度。
接下来的三行(标记为“Frameset”)查看传输共享同一帧集的所有12个内存。第一种情况捕获对每个内存执行分离 bert_read和bert_write操作的总时间;这大约需要12倍于单个BRAM情况的时间,因为它只是单个时间的总和,并且实现了相同的带宽。中间一行使用bert_transfuse在一次操作中读取或写入所有12个存储器;结果,DMA传输时间与每个BRAM读取中的传输时间相当,而转换时间几乎是12倍,因为每个存储器必须单独转换。由于DMA传输时间与单个RAMB36读写中的转换时间大致相当,因此这将导致大约两倍的净吞吐量。帧集的最后一行显示了执行单个传输操作的影响,该操作同时读取和写入所有内存。
表中的最后一行显示从RAMB36中读写一帧(两个64b字)。这比读或写整个记忆和翻译所有的框架要花更少的时间。这里的翻译时间可以很短。然而,由于在设置DMA操作时有相当多的固定时间,因此净吞吐量很低。
④ BERT API操作
应用层:单个BRAM和所有BRAM在Tab中的帧集cases中的转换,在表4中预期典型表现。表5表示当我们读取或写入所有存储器时应用程序的透析性能。哈夫曼展示了一个2-3×透析操作的改进。渲染几乎没有什么好处,在转换的情况下,转换需要更多的时间,这可能是由于缓存效果对于容纳所有内存所需的大帧内存造成的。由于主导时间通常是在翻译中,所以在读写数据时,总输入时间基本上是线性的。
表5:基于XZCU3EG的BERT-API应用性能
注:150MHz是我们能够可靠运行DMA回读的最高速度。
10. 结论
现代FPGA上的配置路径提供了对嵌入式存储器的访问。就FPGA资源而言,它是一个轻量级接口,用于从嵌入式存储器中获取数据。XBERT提供了一个用户级API,使应用程序开发人员可以轻量级地使用此功能。使用XBERT访问逻辑内存就像API调用一样简单。这有助于在程序启动时加载初始内存状态,在程序完成、调试时恢复最终数据和状态,以及在FPGA结构和嵌入式内核之间进行不频繁的数据传输。XBERT API负责逻辑到物理的转换,包括压缩必要的转换信息和最小化必须传入和传出FPGA的数据的优化。XBERT工具流自动生成API所需的翻译信息。
全部0条评论
快来发表一下你的评论吧 !