01signal.com

Vivado 部分重配置实战教程

简介

这是 一个系列的四篇文章中的第二篇,讨论 Xilinx Vivado 中的部分重配置(Partial Reconfiguration,即动态功能交换 DFX)。本文的目标是逐步讲解如何在 FPGA 设计中启用部分重配置,并解释其中的每个步骤。如果你还没读过第一篇,建议先读一下,因为它解释了这些步骤背后的概念。

Xilinx 在 2020 年把部分重配置重新命名为 Dynamic Function eXchange(DFX)。DFX 是 Vivado 的菜单和提示信息中使用的表述。不过,本文仍然使用技术术语“部分重配置”。

为简单起见,本文假设工程中只有一个可重构分区。将其扩展到多个分区是相当直接的事。

本文描述的操作步骤从工程尚未启用部分重配置时开始。粗略划分,步骤如下:

布局规划的准备

在所有这些工作中,布局规划是最需要动脑的一步。它需要在“不浪费 FPGA 逻辑区域”和“确保静态分区与可重构分区在布局布线过程中不会遇到重大障碍”之间取得微妙的平衡。

因此,本文的大部分篇幅都会讨论这个话题。

在很久以前,布局规划是一种用于实现时序收敛(timing closure)的技术,它能帮助工具以合理的方式摆放逻辑。随着 FPGA 设计工具不断改进,我已经很多年没见过布局规划能帮助满足时序约束(timing constraints)了。今天,实现时序收敛的最佳策略几乎总是让工具自己做决定。

在使用部分重配置时,布局规划是必须的,因此目标是不把事情弄得更糟。这通常要靠试错。不过,获得良好结果的最简单方法是:先不加任何布局规划约束,对设计做一次实现,然后以逻辑的自然布局为起点,再尝试以适合部分重配置的方式来组织各个区域。

在插件式使用(plugin usage)场景下,布局规划可以随着工程的发展而更新。但在远程更新(Remote Update)场景下却不能这样做。所谓远程更新,是指把部分重配置用作对一个已发布设计进行版本升级的手段:在远程更新中,所有部分比特流都必须与初始比特流匹配。因此,一旦初始比特流发布,设计中的静态逻辑部分就被冻结了。这还意味着,布局规划也必须保持不变。

所以,即使在开始做部分重配置之前,首要任务也是在 FPGA 中为静态逻辑找到一个合适的区域。在这上面花太多时间没有意义,只需要获得一个合适的起点,以便之后把工程拆成两半时继续使用即可。

别搞混淆:这一步的目的不是布局规划本身,而是想看看 Vivado 在没有限制时会把逻辑放在哪里,并据此决定应把哪个区域留给静态逻辑。步骤如下:

把工程设置为支持部分重配置

Xilinx 的 UG909 给出了两种部分重配置的工作流程:

本文选用工程流程,虽然它有一些限制,其中一部分与可重构模块中的源文件类型有关(尤其是使用 block design 时)。无论如何,从工程流程入手是比较好的,因为工程流程为实现所生成的脚本,在需要时可以作为非工程流程的良好基础。

下面是在一个已有工程上启用部分重配置支持的步骤:

在这个阶段尝试对工程做一次实现,很可能会失败,并出现类似这样的错误:[DRC HDPR-30] Missing PBLOCK On Reconfigurable Cell: HD.RECONFIGURABLE cell 'pr_block_ins' must have PBLOCK assigned to itself or its descendant cells。简单说,就是必须做布局规划。

布局规划(floorplanning)

到了这个阶段,工程的状态已经刚好足够用来做布局规划了。

在把这项任务拆成小步骤之前,有几点值得先记住:

下面把它分解成步骤:

修正布局规划

这也许是部分重配置中最不令人愉快的部分:要把布局规划做到恰到好处。如果你是针对远程更新场景做这件事,这一阶段就格外重要,因为这个布局规划会在整个工程生命周期内保持不变。

需要修改布局规划的主要原因有两个:一是为了回应 Vivado 发出的严重警告,二是在后续阶段为了优化 FPGA 的使用率——目标是减少资源浪费,同时避免给布局布线制造障碍。

做修改并不困难,因为拖动 Pblock 的边界很容易;用鼠标右键点击 Pblock 并选择 Add Pblock Rectangle,也很容易给 Pblock 增加一个矩形。

严重警告往往会说明需要做什么修正。尽管如此,一定要阅读 Xilinx 用户指南 UG909 中与你所用 FPGA 布局规划限制相关的章节(第 6、7 或 8 章)。

本节其余部分讨论 7 系列 FPGA 可能遇到的问题。UltraScale FPGA 用起来要容易得多。

7 系列 FPGA 上一个常见的错误是互联瓦片列(interconnect tile column)被切开。例如:

[Constraints 18-993] The Pblock pblock_pr_block_ins has defined an area that causes the splitting of interconnect tile columns. Dynamic Function eXchange requires that the left and right paired interconnect tile columns cannot be split by a reconfigurable boundary.  This is caused by either the left or right edge of a Pblock boundary, or by the Pblock spanning over logic types not included in the Pblock ranges.  To avoid an unroutable situation, placement will be prohibited from both of these columns. To avoid placement restrictions, modify the Pblock to avoid splitting the two columns.
The column of the split contains interconnect tile INT_L_X48Y299  (SLICE_X79Y299 SLICE_X78Y299).
Please refer to the Xilinx document on Dynamic Function eXchange.
Resolution: Set the Pblock property SNAPPING_MODE to value of ON, or modify the column/X specification of the pblock to avoid this edge.

以及

[Constraints 18-996] The split between the left and right columns occurs between a reconfigurable Pblock and Static logic. The static sites are not reconfigurable. The Pblock should be adjusted to remove the column from the Pblock, unless the excluded reconfigurable and static sites are not needed for the design. Note that adjusting the Pblock will prevent prohibits and improve placement of the design, but may reduce the routability if the removed sites were needed to span across the static logic. Failure to modify the Pblock may lead to an unplaceable design if these prohibited sites are required by the design. Resolution: Set the Pblock property SNAPPING_MODE to value of ON, or modify the column/X specification of the pblock to avoid this edge. and

要解决这个问题,可以按照第一条警告的建议,把 Pblock 的 SNAPPING_MODE 属性设为 ROUTING 或 ON(很有可能 ROUTING 还不够,所以请选 ON)。这样做很可能会在 XDC 文件中添加大量类似下面的 PROHIBIT 约束:

set_property PROHIBIT true [get_sites SLICE_X79Y349]
set_property PROHIBIT true [get_sites SLICE_X78Y349]
[ ... ]
set_property PROHIBIT true [get_sites SLICE_X79Y191]
set_property PROHIBIT true [get_sites SLICE_X78Y191]
set_property PROHIBIT true [get_sites PMV_X0Y2]
set_property PROHIBIT true [get_sites SLICE_X36Y190]
set_property PROHIBIT true [get_sites SLICE_X37Y190]
[ ... ]
set_property PROHIBIT true [get_sites SLICE_X79Y176]
set_property PROHIBIT true [get_sites SLICE_X78Y176]
set_property PROHIBIT true [get_sites T14]
set_property PROHIBIT true [get_sites R15]
set_property PROHIBIT true [get_sites XADC_X0Y0]
set_property PROHIBIT true [get_sites SLICE_X36Y175]
set_property PROHIBIT true [get_sites SLICE_X37Y175]
[ ... ]

后面还有一大串。

其中的 slice 位置上的 PROHIBIT 正是用来消除前述严重警告的。其它 PROHIBIT 赋值则是为那些位于几何区域内但不允许用于该 FPGA 部分重配置的逻辑位置而添加的。UltraScale FPGA 及之后的器件所产生的 PROHIBIT 行要少得多,如果有的话。

如果只是为了消除严重警告,那么把那些逐行的 PROHIBIT 删除,只留下一条针对 slice 范围的约束,通常就够了。做法是:把 Vivado 由于改变 SNAPPING_MODE 而添加的那些 slice 范围,合并成类似下面这样的一行:

set_property PROHIBIT true [get_sites -range {SLICE_X79Y0 SLICE_X79Y349}]

这样的 XDC 行既可能解决互联列被切开的问题,又不会让文件变得庞大。

无论如何,XDC 文件中还可能会出现下面这样一行。删除它似乎也没问题:

set_property HD.PLATFORM_WRAPPER true [get_cells pr_block_ins]

把 XDC 文件缩减到刚好能消除严重警告的最小程度,看起来也许有些敷衍,但否则就会得到一个巨大的约束文件,这会给之后的维护带来混乱。以我的经验,只要没有这类警告,就可以认为设计的布局规划没有问题。

请注意:即使你手动修改了 XDC 文件,只要把 SNAPPING_MODE 改回 OFF,十有八九问题又会重新出现。

添加可重构模块

到目前为止,这种实现与层次化设计相比,实际上效果差不多,只是多了一些额外限制。虽然已经生成了一个部分比特流,但它没什么用,因为加载它之后,设计不会发生任何变化。

所以接下来的目标是创建另一个部分比特流,它基于另一个可重构模块。这需要添加一个子实现(Child Implementation)。

在继续往下读之前,请确保你对上一篇的内容还有清晰的印象,尤其是关于父实现、子实现以及 Dynamic Function eXchange 向导的部分。也请记住本文前面提到的一点:Partition Definitions 标签页中保存着当前定义好的可重构模块及其源文件。

从 Tools 菜单打开 Dynamic Function eXchange Wizard,在欢迎窗口点击 Next。

在 Edit Reconfigurable Modules 窗口,点击“+”。这会打开一个添加可重构模块的对话框。这个对话框里唯一值得关注的字段是 Reconfigurable Module Name:正如前面解释过的,这个名称用来标识该可重构逻辑。

对话框还要求把这个模块与某个分区定义的名称关联起来;不过反正这里只有一个分区(因为本文假设只定义一个分区)。

要继续,至少需要添加一个 Verilog / VHDL 源文件。之后还可以从 Partition Definitions 标签页添加更多文件。如果无法从源文件本身看出用途,那么填写这个可重构模块的顶层模块名称也比较好。

回到向导后,再次点击 Next,进入 Edit Configurations 窗口。点击“+”,输入配置名称。这个名称的唯一重要性在于它会出现在 Design Runs 窗口中。诸如 config_2 之类的名字就可以了。

配置列表中出现了一行新记录。修改该行中对应分区那一列的可重构模块,使每个配置对应一个不同的可重构模块。

最后一个窗口是 Edit Configuration Runs,用于把运行与配置关联起来。最简单的做法是删除该窗口中列出的所有运行(如果有的话),然后点击 automatically create configuration runs(自动创建配置运行)。这恰好会完成你本来要手动做的事情:创建一个父运行,把它命名为 “impl_1”,然后创建若干子运行,想叫什么名字都可以,并把它们设置为 “impl_1” 的子运行。

向导会为每个运行选择一个配置,不过这很容易修改。唯一重要的是父运行与哪个配置关联。

顺便说一句,如果你在向导中删除了所有运行,所有子运行都会消失,但 impl_1 仍然保留。

终于到了:对设计进行实现

要生成比特流,照常点击 Vivado 中的 Generate Bitstreams 即可。正如上一篇已经提到的,在部分重配置工程中,每个配置都会生成两个或三个比特流。

例如,在 UltraScale FPGA 上,比特流文件可能是:

注意,所有实现都会生成相同数量的比特流文件。也就是说,子实现也会生成初始比特流文件,因此完全可以先用某个子实现的初始比特流加载 FPGA,然后从那个状态继续操作。

如果想找一种通过 PCIe 或 USB 3.x 加载部分比特流的简单方法,参见这个页面。

所有实现都不应再出现严重警告,也不应因为关于 Pblock 和布局规划之类的抱怨而失败,因为这类问题应该已经解决了。如果仍然出现这种问题,就必须像上面所解释的那样修正布局规划。

有时候,当你点击 Generate Bitstream,而改动只发生在子实现中时,Vivado 可能会提示 “Bitstream generation has already completed and is up-to-date. Re-run anyway?”。这有点让人困惑,但点击 Yes 就会正确地运行子实现。子实现这种机制本身在 Vivado 中有点像附加功能,这也是为什么实现过程中状态行会出现类似 “write_bitstream complete. Child running” 的文字。

检查结果

部分重配置在很大程度上是关于布局的,所以检查实现后的设计是个好主意。你可以通过右键点击 Open Implemented Design,然后在弹出的子菜单中再次指向 Open Implemented Design,再从列表中选择要打开的实现。如果某个实现不在列表中,它可能已经打开了。

试试在 Implemented Design 视图的 Netlist 面板中右键点击可重构逻辑的顶层单元,选择 Highlight Leaf cells;然后再用另一种颜色对静态逻辑做同样的操作。

在同一个右键菜单中还有 Show Connectivity,它会在相互连接的逻辑单元之间画出白色直线。FPGA 上的实际布线路径当然与此不同,所以这些线是否穿过布局规划中的某个区域并不重要。不过,查看连接关系仍然有助于发现布局规划的整体组织是否让工具变得吃力。

某些看起来显然属于静态逻辑的单元被放进了可重构区域,反过来也一样——这是完全正常、也没问题的。真正需要警惕的是某个地方似乎出现拥塞——比如逻辑总体上被挤得太紧,或者在某个特定区域过于密集。如果可以,修改布局规划会有助于缓解这个问题。

另外还值得一看的是分区引脚(partition pin)的位置。它们在器件视图中显示为白色的水平条,如下图所示(点击图片可放大):

Partition pins in Vivado's device view

正如上一篇所提到的,分区引脚可以出现在可重构分区内的任何位置。不过,如果分区引脚远离分区的边界,这可能表明布线器在父实现过程中为了满足时序费了很大劲。

也可以用下面的 Tcl 命令获得分区引脚坐标的文本列表(把 pr_block_ins 改成你的可重构逻辑单元名称):

foreach s [get_pins -of [get_cells pr_block_ins]] { set partpin [get_pplocs -quiet -pins [get_pins $s]] ; puts "$s => $partpin"; }

分区引脚的坐标对应 CLB 的网格(而不是 slice 的网格)。在显示的图纸中,这些引脚被称为 Cell pins。

有些单元引脚可能没有得到分区引脚。这种情况发生在可重构模块的端口列表(和/或向量位宽)与其在静态逻辑模块中的实例化不一致时。这种不一致在 Verilog 中是合法的,但结果可能不是你想要的。运行上述 Tcl 命令可以发现这些未连接的端口,尤其是当这种不一致并非有意为之的时候。


关于 Vivado 工程设置的技术部分就到这里。不过,下一篇将讨论 FPGA 设计中一个重要的方面:如何确保逻辑替换能够可靠而顺利地进行。

本页由机器从英文翻译而来。如有疑问,请参阅原文。
Copyright © 2021-2026. All rights reserved. (dcc38493)