01signal.com

Remote Update 与 Vivado上的 Partial Reconfiguration

这是关于 Partial Reconfiguration或 Dynamic Function eXchange (DFX) 与 Xilinx的 Vivado的四篇系列文章中的最后一篇。它主要面向那些想在 Remote Update 场景中使用 Partial Reconfiguration 的人。这篇文章是假设你已经阅读了前三篇。

介绍

讨论了 Partial Reconfiguration 的一般情况,然后讨论了 Vivado为此目的的常用程序,这篇文章为在 FPGA的 logic的 Remote Update 上使用这种技术奠定了基础。

这种使用场景的主要问题是 partial bitstream 需要与可能几年前生成的 initial bitstream 兼容。因此,原始 Parent Implementation 必须在 reconfigurable logic的 implementation 期间可用,或者必须重新生成以产生完全相同的结果——即完全相同的 place and route。

可以保持整个 Vivado 项目完整,从而避免重新运行 Parent Implementation 。如果重复此 implementation ,我也可能获得完全相同的结果。然而,基于这两种方法中的任何一种,都很难确保将来发布 partial bitstreams 的可能性。

这个问题有一个可靠的解决方案,但是要了解它是如何工作的,首先要熟悉 DCPs 和 OOCs。以下是对这两个主题的简要介绍。

Design Checkpoint (DCP)

回想一下, Vivado 通过几个 Design runs执行 FPGA design的 implementation ,这些 Design runs通常命名为 synth_1、 impl_1 以及归类为 Out-of-Context module runs (OOCs) 的附加 runs 。

每个这样的 run 包括执行一个 Tcl script,它生成一个临时的“in-memory project”,加载 design 文件,设置属性和属性,并调用执行 synthesis、 placing、 routing、生成 bitstreams和其他任务的 Tcl 函数。

这个 in-memory project 不会在磁盘上创建文件,与 GUI中可见的 Vivado 项目无关。它是内存中的 object ,允许使用 Tcl 命令执行许多顺序操作。

随着 implementation 的发展, Design CheckPoints (DCP) 文件被写入磁盘(借助 Tcl中的 write_checkpoint 命令)。 DCP 文件的内容是 in-memory project的 snapshot 。换句话说,它是一个 database ,它反映了已加载的 design 文件以及自加载以来对项目所做的操作。

例如, synthesis run (通常命名为 synth_1)可能会加载所有 HDL 文件、 constraint 文件和 IP 文件,然后使用一个名为 synth_design 的 Tcl 命令来执行 HDL 文件的 synthesis 。结果是所有这些 sources (包括 IPs)中的一个大 netlist 。但是请注意, netlist 作为 in-memory project的一部分存储在内存中。因此, synthesis run的 Tcl script 对 write_checkpoint 进行函数调用以创建 DCP 文件,该文件是 synthesis的产品。 synth_1 run到此结束。

事实上,由 synth_1 生成的 DCP 被称为 netlist DCP ,尽管它通常也包含来自 XDC 文件的 constraints 。

随后出现的 implementation run (通常称为 impl_1)创建一个新的 in-memory project 并读取此 netlist DCP (以及其他)作为以下操作的起点。这个 run 写入了几个 DCP 文件,每个文件都是经过处理阶段的项目的 snapshot (例如 optimize design、 place、 physically optimize、 route 等)。

所有 runs,包括 synth_1,都可以将 DCPs 加载到它们的 in-memory project中。这是他们通常做的事情。

Out Of Context (OOC) Module Runs

在 Vivado中, IPs 通常是借助 GUI 工具来配置的。完成后, script 会生成 source files (主要是 HDL 和 constraint 文件)并在这些文件上执行 synthesis 。这会产生一个 netlist DCP,然后将其加载到主项目的 synthesis run 和 implementation runs中。通过消除重新生成 IPs 的 sources 并一遍又一遍地执行其 synthesis 的需要,这减少了整个项目的 implementation 完成所需的时间。

Vivado run 获取原始产品( IP的配置信息、一些 HDL 文件或其他任何东西)并将其转换为 netlist DCP,在 Vivado的术语中称为 Out-Of-Context run 。该术语仅与 Vivado相关,据我所知没有其他用途。这实际上是一个相当糟糕的名称选择。

这个 netlist DCP 由 synthesis run 和 implementation runs加载,通常借助 Tcl 命令 read_ip,通常归结为加载由 OOC run生成的 DCP 。

Vivado 还允许在主工程中选择一个 HDL module ,并要求将其 synthesis 执行为 OOC (通过在 Project Manager的 source tree 中右键单击 source 并选择“Set as Out-of-Context for Synthesis…”)。

OOCs 的缺点是,当 synthesizer 将整个 design 作为单个项目时, synthesizer 可以跨 modules 的边界执行某些优化。所以个别 synthesis 凭借 OOCs 可能会降低性能以及浪费资源。

OOCs 和 DCPs 与 Partial Reconfiguration

当一个 source 文件被选为 reconfigurable module的 top-level 时, Vivado 为这个 module 及其 submodules的 synthesis 创建一个 OOC run 。这个 run 生成一个 netlist DCP 用于相关的 implementation。 Parent Implementation 和 Child Implementations都是如此: reconfigurable module 始终以单独的 DCP表示。

然而,这个 netlist DCP 在 Parent Implementation 和 Child Implementations中的使用方式不同: 分配给 Parent Implementation 的 netlist DCP 由 synth_1 和 impl_1加载,就像在常规 implementation中加载 IP 一样。涉及 Partial Reconfiguration 的事实主要通过 floorplanning强加的 placement constraints 影响这个过程。

另一方面, Child Implementation没有专用的 synthesis 相位。相反,它将 reconfigurable module的 netlist DCP 与来自 Parent Implementation 的最终 DCP (即 place and route之后的 DCP )混合在一起。更准确地说, Child Implementation 取了 Parent Implementation的最终 DCP,移除了 reconfigurable logic的部分,并插入了自己的 reconfigurable module的 netlist DCP 。有点像去除蔬菜的中间部分来制作酿西葫芦或类似的东西。

现在是时候将其分解为 Tcl 命令了。

Parent-Child implementations的螺母和螺栓

在 Tcl 文件中查找 implementation 的工作原理,该文件具有项目的名称(加上 .tcl 后缀)。该文件与创建 implementation文件的目录位于同一目录中。

特别是 child implementation 的 implementation script 很有趣。相关用户指南 UG909中的第 3 章(“Vivado Software Flow”)显示并解释了 script,即使没有直接这么说,这并非巧合。

就像刚才提到的, Parent的 implementation并没有什么特别之处,只是它的 reconfigurable module的 netlist 依赖了一个 DPC ,并且应用了 floorplanning constraints 。它或多或少像任何 hierarchical design。

但随后 Parent Implementation 写入两个 bitstreams 而不是一个,凭借如下 Tcl 命令:

write_bitstream -force -no_partial_bitfile theproject.bit
write_bitstream -force -cell pr_block_ins pr_block_ins_lpf_partial.bit

然后它创建 DCP 稍后由 Child Implementation使用:

update_design -cell pr_block_ins -black_box
lock_design -level routing
write_checkpoint -force theproject_postroute_physopt_bb.dcp

回想一下,当这部分运行时,有一个 in-memory project,它从加载 netlist DCPs开始,并经过 place and route 和所有其他优化。这三个 Tcl 行是在写完 bitstream之后执行的,所以 in-memory project 是真正的最后阶段。

现在是打洞做西葫芦馅的好时机: update_design 命令将 reconfigurable module 变成 black box。换句话说,它的所有 logic 都被移除了,为其他 logic 提供了进入的空间。

那么 design 的 place and route 就通过 lock_design 指令锁定。之后将项目的 snapshot 写入 theproject_postroute_physopt_bb.dcp。 “bb”当然代表“Black Box”。

Child Implementation的 script 中的相关部分如下:

create_project -in_memory -part xc7k325tffg900-2
set_property design_mode GateLvl [current_fileset]
add_files -quiet .../impl_1/theproject_postroute_physopt_bb.dcp
add_files -quiet .../two_synth_1/pr_block.dcp
set_property SCOPED_TO_CELLS pr_block_ins [get_files .../bpf_synth_1/pr_block.dcp]
link_design -top theproject -part xc7k325tffg900-2 -reconfig_partitions pr_block_ins
opt_design
write_checkpoint -force theproject_opt.dcp
[ ... ]

从这一点开始,它继续到 place and route 等。

注意上面的 implementation script 只消耗两个源,而且都是 DCPs:

当 implementation 继续运行时,第一个 DCP 被锁定的事实确保了 static logic 没有任何移动。尽管如此, reconfigurable module的 place and route 还是照常完成,基于 netlist DCP。

附带说明一下,如果存在属于 reconfigurable module的 XCI IPs ,则在上面的两个 add_files 命令之间为每个 IP添加如下一行:

read_ip -quiet .../theproject.srcs/sources_1/ip/blkmem/blkmem.xci

不过,这对 Partial Reconfiguration来说并不特别——在任何 implementation中都是这样。

就在写这两个 bitstreams之前, Child Implementation 验证它得到的 routed design 与 Parent Implementation的 static logic 兼容,特别是关于 place and route。

用于此的 Tcl 命令类似于:

pr_verify -full_check -initial /path/to/impl_1/theproject_postroute_physopt.dcp -additional /path/to/child_1_impl_1/theproject_routed.dcp -file child_1_impl_1_pr_verify.log

请注意,这将比较两个 DCP 文件,而不考虑 in-memory project。 Parent Implementation的 routed DCP 与 Child Implementation的最终 DCP 进行比较。此比较的输出转到名为 *_pr_verify.log的文件。

这种比较保证了 partial bitstream 是兼容的,即当 parent的 bitstream 已经加载到 FPGA中时,它可以被加载。它通过 static partition的 logic elements 和 routing。

如果存在不兼容,pr_verify 将返回失败状态。如果发生这种情况,将阻止在 Vivado的 script 中创建 bitstreams 。在编写自定义 implementation scripts时牢记这一步骤很重要。

这个验证没有理由失败,但如果失败了, bitstream generation 就会失败,并出现很多错误,比如“ERROR: [Constraints 18-891] HDPRVerify-08: design check point .../impl_1/theproject_postroute_physopt.dcp places instance ... at site SLICE_X118Y125, yet design check point .../impl_2/theproject_routed.dcp does not. Both check point must have the same static placement result”。

这些错误消息可能会达到 100的限制,然后被静音。

Remote Update 场景解决方案

从上面回想一下,挑战是当 reconfigurable logic 的 implementation 作为 Child Implementation执行时,原始 Parent Implementation 的结果必须可用。

brute-force 解决方案是制作整个 Vivado 项目目录的副本,以及它可能依赖的任何文件。当需要生成新的 partial bitstream 时,恢复所有文件,强制 Parent Implementation 为最新,并仅为 Child Implementation 创建 bitstream 。这种方法在技术上是可以的,但从长远来看可能会很烦人。如果选择这种方式,请务必手动运行 pr_verify 对原始 Parent Implementation的 DCP 文件,因为这种方法不会检测到 Parent Implementation的无意更改。

还有另外两种选择,它们基于关于 Parent Implementation 和 Child Implementations 如何交互的知识,即通过两个 DCP 文件,如上所述。这两种选择的明显优势是您知道自己在做什么。

这两种选择背后的原理是确保 partial bitstream 依赖于与 initial bitstream一起生成的两个 DCP 文件,我将其称为Golden DCPs。

第一种选择是将 partial bitstream 的 implementation 作为 Tcl script 与 non-project flow进行。本质上,这意味着运行 Vivado 为 Child Implementation创建的 script ,但是将其修改为使用 Golden DCPs。更准确地说,修改 link_design 命令和 pr_verify 命令的参数,使它们依赖于 Golden DCPs。

这种替代方案的主要缺点是运行带有 non-project flow 的 Tcl script 不能很好地与 Vivado的 GUI集成,因此处理消息、打开 implemented design 进行审查等变得相当困难。

Golden DCPs hack

理想情况下,可以自动修改由 Vivado 为 Child Implementation run生成的 script ,因此它与 Golden DCPs相关。不幸的是,似乎没有可靠的方法来做到这一点。

但是 Vivado 允许定义 Tcl scripts 以在 implementation中的某些阶段之前和之后执行。这些 scripts 是从 implementation run的 script执行的,所以它们不能用来改变 run的 script 本身。

然而,这为一种有点丑陋的方法打开了大门,这是第二种选择: 这个想法是用 Golden DCPs覆盖 Parent Implementation 的 DCPs 。通过这样做, Child Implementation 可以正常运行,但依赖于 Golden DCPs,而不管 Parent Implementation 碰巧生成了什么。

这种方法的好处是与 Vivado 的常规工作习惯保持不变: 对 reconfigurable logic进行了更改, Vivado 为 reconfigurable module的 synthesis 重新运行 OOC ,然后为生成 partial bitstream的 Child Implementation 。由于 static logic没有做任何改动,所以 Vivado 没有理由启动其相关的 runs。

实现这种 Golden DPC 复制方法的 Tcl script 是

if { [catch {
    set parentimpldir "[ file normalize "../impl_1"]"
    set goldendir "[ file normalize "/path/to/golden"]"

    file copy -force "[file normalize "$goldendir/theproject_postroute_physopt_bb.dcp"]" "$parentimpldir/"
    file copy -force "[file normalize "$goldendir/theproject_postroute_physopt.dcp"]" "$parentimpldir/"
} errmsg ] } {
    send_msg_id golden-reconfig-1 error "Failed to copy golden parent reconfiguration file(s): $errmsg"
    return -code error
}

此 script 假定 Parent Implementation 保存在与 Child Implementation 目录相邻的“impl_1”目录中(很可能是),并且两个 Golden DCPs 存储在此 script第 3 行中定义的目录中。

在 Design Runs 选项卡上右键单击 child run (例如 child_0_impl_1),选择“Change Run Settings…”并在打开的 dialog 中,将 Design Initialization 的 tcl.pre (init_design)设置为 script。或者,在 Tcl中,如果 script 保存为 golden_pr.tcl:

add_files -fileset utils_1 -norecurse /path/to/golden_pr.tcl
set_property STEPS.INIT_DESIGN.TCL.PRE [ get_files /path/to/golden_pr.tcl -of [get_fileset utils_1] ] [get_runs child_0_impl_1]

使用此 script 时要记住的重要一点是忽略 Vivado 提供的有关 Parent Implementation的所有信息,以及代表其生成的任何文件。 Vivado 可能会打开它的 Implemented Design GUI 并显示它的报告,但这一切很可能是完全无关的。所以这是一个混乱的开端。

第二个可能的烦恼是 Vivado 可能会不时运行 Parent Implementation 以响应项目设置的更改,甚至是 constraints 文件中的更改。这可以通过右键单击 Design Runs 选项卡中的相关行并选择“Force Up-to-Date”来解决。该菜单仅在 run 处于 Out-of-Date 状态时出现,即完成但 Vivado 认为需要刷新。相关的 Tcl 命令例如

set_property needs_refresh false [get_runs synth_1]

与 Golden DCPs一起保存哪些文件

显然, Golden DCPs 必须保存在安全的地方,以保持将来生成兼容 bitstream 文件的能力。除了这些,将整个 Vivado 项目压缩成 .tar.gz / .zip 文件以快速恢复实际上是一个好主意。或者,除此之外,可以使用 File > Project > Archive… 或类似的东西生成 project archive

archive_project /path/to/theproject.xpr.zip -force -include_local_ip_cache -include_config_settings

但是请注意,项目文件以及 Vivado 项目中的其他文件都可能包含 absolute paths,因此将项目部署到另一个目录或另一台计算机上可能无法按预期工作。存档也是如此。

使用哪个 Vivado 版本已写入所有可能的报告文件和 .xpr 项目文件中,但记下这一点不会有什么坏处。可能保留该 Vivado版本的可执行副本,即使没有明显的理由说明软件升级很重要。将来自一个 Vivado 版本的 Golden DCPs 与来自另一个版本的 reconfigurable logic的 netlist DCP 混合可能会正常工作。但这不是 Vivado 计划要做的事情。

总而言之,最小的文件集是:

请注意, clearing bitstream 在 Ultrascale FPGAs 上的使用与 FPGA中已经存在的 logic 有关。这就是为什么必须保存与 initial bitstream 相关的 clearing bitstream 。另请注意,如果 initial bitstream 是某些 Child Implementation的结果,则必须保存该 implementation 的 clearing bitstream 。

至于保存 Parent Implementation的 sources 很重要,因为它决定了 static logic 和 reconfigurable logic之间的连接。例如,如果编辑 sources ,将 port 添加到 reconfigurable logic ,并且此 port 出现 instantiation,则 partition pins 的集合会更改。因此, reconfigurable logic 的 netlist 将具有原始 static design中未出现的外部 pins 。

当发生这种不匹配时, child implementation 会失败并显示一条错误消息,例如“ERROR: [Netlist 29-77] Could not replace (cell 'pr_block_bb', library 'work_pr_block_ins_pr_block_ins_4', file 'NOFILE') with (cell 'pr_block', library 'work', file 'pr_block.edf') because of a port interface mismatch; in strict mode, no extra ports are allowed. 8 ports are missing on the original cell. 5 of the missing ports are: 'thingy[7]' 'thingy[6]' 'thingy[5]' 'thingy[1]' 'thingy[0]'”。

在这种情况下实际上失败的是 link_design 命令(见上文),它将 static logic 和 combinatorial logic 粘合在一起。

避免这个问题的简单明了的方法是不改变 design的 static 部分,也不改变 reconfigurable logic的 port list 。

但是,在项目的 static 部分进行更改实际上是可以的: 只是 reconfigurable module 的 instantiation 必须保持不变。只要 implementation 顺利通过,包括最后的验证,都没有问题。

概括

尽管对于 Partial Reconfiguration的 Remote Update 使用没有完全平滑的解决方案,但仍有一些可用的策略来实现这一目标。

重要的一点是,原则上,只需两个 Golden DCPs 即可为现有项目构建和验证 partial bitstream 。

无论此处介绍的策略看起来多么不合常规,请记住, pr_verify 执行的验证是对 partial bitstream 和 static logic 之间已经存在的兼容性的全面检查。只要使用正确的 Golden DCP 进行此验证,并且测试通过,就无需担心其他任何问题。另外,当然, Child Implementation 可以达到 timing constraints,但对于 design的任何 implementation 都是如此。

此页面由英文自动翻译。 如果有不清楚的地方,请参考原始页面
Copyright © 2021-2024. All rights reserved. (6f913017)