RTL 引导 ECO:把一处小幅 RTL 修改转成有针对性的网表补丁
设计后期的一处 RTL 修改,如何落实到数百万门的实现网表?本文通过赋值修改示例,介绍 GOF RTL 引导 ECO 的输入配置、补丁生成、层级实例选择及分阶段验证,并说明如何评估补丁规模、周转时间和物理影响。

RTL 引导 ECO:把一处小幅 RTL 修改转成有针对性的网表补丁

原始 RTL 与修改后 RTL 引导现有网表的 ECO,并对补丁进行验证

局部 RTL 修正描述修改意图,现有实现网表则是需要打补丁的对象。

设计后期,RTL 中的一条赋值需要修改,实现团队却要把它落实到包含数百万门的网表中。看懂源码改动通常不难;在综合优化后的实现中定位对应逻辑、准确修改并证明结果正确,往往需要更多工作。

是否必须先等待全设计重新综合,生成新的参考网表?对于局部功能修改,GOF 的 RTL 引导 ECO 流程提供了另一条路径:把原始 RTL、修改后的 RTL 和现有实现网表作为输入,生成有针对性的补丁。

一个例子:把常量改为数据位

以 NanDigits 已有的示例为例。在某个 case 分支内,当 disp_data[17:13] 等于 5'h1f 时,r0 原来被赋值为常量一,现在需要改为 disp_data[1]。else 分支和其他 case 分支保持原有行为。

// Illustrative excerpt inside the affected case branch
// Before:
if (disp_data[17:13] == 5'h1f)
    r0 = 1'b1;
else
    r0 = 1'b0;

// After:
if (disp_data[17:13] == 5'h1f)
    r0 = disp_data[1];
else
    r0 = 1'b0;

真正的工程问题不止这一行修改:这段行为在优化后的网表中对应哪些逻辑?怎样改变它,同时保留周边行为?综合可能合并、重构或消除源码中的逻辑,因此一行 RTL 修改并不意味着一个门的补丁。

把修改前后的功能意图一起带入 ECO

在以参考网表为输入的流程中,团队先把修改后的 RTL 综合成新的门级参考网表,再由 ECO 引擎将参考网表与现有实现进行比较,确定所需改动。这是一种常用方法。

RTL 引导 ECO 则直接利用两版 RTL 来描述功能变化。原始 RTL 表示当前实现对应的行为;修改后的 RTL 表示目标行为;现有实现网表是需要更新的对象。此外,还需要单元库以及相关的设计展开配置。

输入标记尤其需要注意:在 GOF 示例中,-ref 指定的是修改后的 RTL,-imp 指定的是原始 RTL。顶层模块、参数、宏定义和包含路径都应与预期配置保持一致。配置不一致,可能把原本很小的功能修改变成完全不同的比较问题。

两版 RTL 进行比较,比较结果与现有实现网表及单元库共同用于生成 ECO,随后验证修改后的网表和脚本

两版 RTL 引导现有网表上的补丁生成。输入 RTL 之间的比较,与导出后实现网表的验证,是不同的环节。

从 RTL 比较到可审查的 ECO 操作

rtl_compare() 比较两版 RTL,其结果供 fix_design() 在更新实现网表时使用。文档所述流程允许跳过门级网表之间的比较阶段。

这里的关键是不必为了生成新的参考网表而执行全设计重新综合。流程内部仍可能涉及设计展开、逻辑生成、优化或映射。它也不是把文本差异直接套用到门电路上,而是要处理优化后实现中的功能差异。

下面的示意脚本根据文档示例整理。用于实际项目之前,需要替换文件名、单元库和顶层模块名,并补充设计的宏定义、包含路径、参数及约束。

use strict;
setup_eco("rtl_guided_example");
read_library("standard_cells.lib");
read_rtl('-ref', "modified_rtl.sv");
read_rtl('-imp', "original_rtl.sv");
set_top("chip_top");
rtl_compare();

# Optional text-format SVF: load before read_design().
# read_svf('-imp', "synthesis.svf.txt");
read_design('-imp', "implementation.v");
set_top("chip_top");
fix_design();
report_eco();
check_design();
write_perl("rtl_guided_patch.pl");
write_verilog("implementation_eco.v");

report_eco() 用于查看改动;write_perl() 保存 ECO 操作,便于审查和复用;write_verilog() 导出修改后的网表。check_design() 检查悬空连接等结构问题,不能代替功能等价验证。这里展示的是补丁生成流程,并非完整的签核脚本。

让修改范围与功能变化相匹配

局部更新不一定需要比较整个 RTL 设计。文档中的流程支持对受影响子模块的原始 RTL 和修改后 RTL 进行比较,再通过 set_path_prefix() 选择需要应用 ECO 的层级实例。

当一个模块在设计中被实例化多次、但只有部分实例需要修改时,这一点尤其重要。例如,手册选中了位于不同父模块下的两个子模块实例。模块级比较描述“改什么”,实例选择确定“在哪里改”。审查补丁之前,这两点都需要确认。

SOC 层级中选中了 SUB_MOD1 和 SUB_MOD3 下的两个 SUB_MOD_A 实例

GOF 文档中的已有示例:比较子模块 RTL 时,选择需要修改的层级实例。绿色标记表示选中的子模块实例。

尽早生成补丁,再逐阶段检查实现

手册建议先在布局前网表上生成 ECO,再把生成的 ECO 脚本应用到 DFT 和布局后网表。这样可以先得到一份可审查的初始补丁,再处理后续实现阶段带来的变化。

脚本复用仍需要工程检查。边界优化、层级变化和对象重命名,都可能影响操作能否按预期应用。应检查脚本的适用性、审查结果网表,并在各阶段完成验证。前一阶段应用成功,并不能证明同一脚本可在所有后续网表上原样重放。

验证真正要交付的结果

需要使用项目的等价验证流程和适当假设,确认修改后的实现符合目标功能。GOF LEC 可支持开发过程中的检查;最终签核则遵循团队认可的流程,例如 Formality 或 Conformal LEC。

对于已插入扫描链的设计,功能模式下对 scan enable 和 test mode 的假设必须符合实际设计。手册中的示例约束不是通用配置。逻辑验证之后,还应完成所需的时序、布局布线、物理和 DFT 检查。功能等价本身并不代表时序已经收敛,也不代表可以直接流片。

用有代表性的修改评估周转时间

在 NanDigits 报告的一个两百万门案例中,RTL 引导 ECO 在 30 分钟以内完成。这是特定案例的结果,并非运行时间保证。公开材料没有提供足够的原始日志、机器配置和测量边界,无法据此进行独立的性能对比。本文也没有执行新的基准测试。

对于局部的中小规模功能变化,例如条件修改、数据选择或控制赋值调整,这一流程值得评估。前提是两版 RTL 的配置一致,而且现有实现与原始设计相对应。大范围架构调整或重大状态变化,需要另行评估。

面对下一项已批准的 RTL 修正,可以记录从开始处理到获得可审查、通过验证的补丁所需的总时间,同时记录补丁规模、验证结果和物理影响。这样的记录,比单独比较 ECO 命令的运行时间,更有助于判断 RTL 引导 ECO 在实际实现流程中的价值。

设计后期出现局部 RTL 修正时,你们花时间最多的是准备参考网表、定位网表改动,还是验证补丁?

用有代表性的 ECO 评估 GOF

资料来源:GOF 用户手册中的“RTL Guided ECO Without Re-Synthesis”及其示例脚本;NanDigits 两百万门示例。流程图用于解释方法,层级图来自现有文档。图片中的英文标注予以保留,中文图注说明其含义。

感谢阅读,更多文章点击这里:【专栏:NanDigits】
留言(0)
还没有留言,来说两句吧。
留言需要 登录 或 注册(注册后需通过邮箱验证)。
相关文章