
局部 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 修改并不意味着一个门的补丁。
在以参考网表为输入的流程中,团队先把修改后的 RTL 综合成新的门级参考网表,再由 ECO 引擎将参考网表与现有实现进行比较,确定所需改动。这是一种常用方法。
RTL 引导 ECO 则直接利用两版 RTL 来描述功能变化。原始 RTL 表示当前实现对应的行为;修改后的 RTL 表示目标行为;现有实现网表是需要更新的对象。此外,还需要单元库以及相关的设计展开配置。
输入标记尤其需要注意:在 GOF 示例中,-ref 指定的是修改后的 RTL,-imp 指定的是原始 RTL。顶层模块、参数、宏定义和包含路径都应与预期配置保持一致。配置不一致,可能把原本很小的功能修改变成完全不同的比较问题。

两版 RTL 引导现有网表上的补丁生成。输入 RTL 之间的比较,与导出后实现网表的验证,是不同的环节。
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 的层级实例。
当一个模块在设计中被实例化多次、但只有部分实例需要修改时,这一点尤其重要。例如,手册选中了位于不同父模块下的两个子模块实例。模块级比较描述“改什么”,实例选择确定“在哪里改”。审查补丁之前,这两点都需要确认。

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 修正时,你们花时间最多的是准备参考网表、定位网表改动,还是验证补丁?
资料来源:GOF 用户手册中的“RTL Guided ECO Without Re-Synthesis”及其示例脚本;NanDigits 两百万门示例。流程图用于解释方法,层级图来自现有文档。图片中的英文标注予以保留,中文图注说明其含义。