GOF ECO是一款芯片网表功能ECO的软件。在项目中后期或流片之后,发现逻辑功能有BUG或者设计需求有变更时,不需要重走“综合 -> DFT -> APR”的完整流程,利用GOF ECO即可自动分析新旧两个版本的差异,并对APR网表进行局部修改。GOF ECO不仅大大缩短了芯片ECO的Turn-around时间,还大大提升了芯片复杂逻辑ECO的成功率。
如上图所示,当我们设计(RTL)上有改动,并充分仿真验证确认功能正确后,就可以开始网表ECO工作了。大致分为以下几个步骤:
下面将详细描述和解释每一个步骤的实现方法和注意事项。
这些文件通常来自于不同的部门或组,我们要确保ECO所需文件的准确性,防止用错文件版本,确保后续ECO工作正常开展。
需要提前收集的文件如下:
并对老设计做逻辑等价性检查(LEC),来确保收集到的文件和版本是正确的:
这一步是可选的,但我们建议做,因为新RTL与老APR网表中间经过了很多次优化,这些优化使得网表结构发生了巨大的变化,而这些变化会加大逻辑功能ECO的难度和准确性。对于超大规模设计,重新综合一次需要两三天或者一周,这个时候我们建议可以先忽略这一步。
一般来说,这一步我们用原有的综合脚本重新跑一次即可。
逻辑一致性检查结果的正确性和合理性是保证网表ECO效果的前提。GOF ECO正是利用一致性检查的技术来分析两个设计的差异,来找到应该修理的地方。如果一致性检查有虚假的不等价,GOF ECO就很可能会做一些无用的修改,会或多或少影响补丁的大小和ECO的成功率。
用GOF做一致性检查的流程如下:
下面是参考代码:
# gof_lec.pl
use strict;
# 读入lib库
read_library("art.5nm.lib");
read_library("sram.lib");
read_library("analog.lib");
# RTL流程
my $rtl_flow = 1;
if($rtl_flow){
# 设置define和include
set_define("SYNTHESIS");
set_define("NO_SIM");
set_inc_dirs("/project/nd900/vlib/include", "/project/nd900/IPS/include");
# 读入老RTL
my @rtl_old = ("ref0.sv", "ref1.sv", "ref2.sv");
read_rtl('-ref', @rtl_old);
# 读入新RTL
my @rtl_new = ("imp0.sv", "imp1.sv", "imp2.sv");
read_rtl('-imp', @rtl_new);
# 设置顶层模块
set_top("topmod");
# 对比RTL
rtl_compare;
}
# 读入重新综合的网表
read_design("-ref", "reference.gv");
# 读入老的APR网表
read_design("-imp", "implementation.gv");
# 设置顶层
set_top("topmod");
# 设置DFT约束
set_ignore_output("scan_out*");
set_pin_constant("scan_enable", 0);
set_pin_constant("scan_mode", 0);
# 做一致性检查
run_lec();
运行gof_lec.pl的脚本,分析不等价的点是否合理:
gof -run gof_lec.pl
先确认log里unmapped点是否合理。当设计里新加了dff或者输出端口,GOF LEC就会分析出这些新加的点并报出来。
如果有不合理的点报出来,就要debug找到原因:
start_gui
来启动GUI常见的电路图调试方法:
在确认一致性检查报出的不等价的点都是合理的情况下,就可以正式开始ECO了。
参考脚本如下:
# gof_eco.pl
use strict;
undo_eco(); #<-- 撤销之前的改动
setup_eco("eco20221102"); #<-- 设计ECO的名字,GOF ECO输出网表中新加的cell和连线会自动加上这个前缀
# 读入lib库
read_library("art.5nm.lib");
read_library("sram.lib");
read_library("analog.lib");
# RTL流程
my $rtl_flow = 1;
if($rtl_flow){
# 设置define和include
set_define("SYNTHESIS");
set_define("NO_SIM");
set_inc_dirs("/project/nd900/vlib/include", "/project/nd900/IPS/include");
# 读入老RTL
my @rtl_old = ("ref0.sv", "ref1.sv", "ref2.sv");
read_rtl('-ref', @rtl_old);
# 读入新RTL
my @rtl_new = ("imp0.sv", "imp1.sv", "imp2.sv");
read_rtl('-imp', @rtl_new);
# 设置顶层模块
set_top("topmod");
# 对比RTL
rtl_compare;
}
# 读入重新综合的网表
read_design("-ref", "reference.gv");
# 读入老的APR网表
read_design("-imp", "implementation.gv");
# 设置顶层
set_top("topmod");
# 设置DFT约束
set_ignore_output("scan_out*");
set_pin_constant("scan_enable", 0);
set_pin_constant("scan_mode", 0);
# 不需要再次做一致性检查
# run_lec();
# 执行ECO
fix_design();
report_eco();
# 确认eco后的等价性,如果等价,逻辑ECO就基本结束了
run_lec();
# 写出eco网表和脚本
write_verilog("eco.gv");
write_soce2("eco.tcl");
运行gof_lec.pl的脚本,分析不等价的点是否合理:
gof -run gof_eco.pl
前面大部分的设置与一致性检查的脚本是相同的,只是把最后run_lec()
换成fix_design()
。在fix_design
的时候,GOF ECO会先自动做一次LEC,分析出不等价的点,然后对不等价的点做eco修改。
在ECO结束后,通过report_eco
来确认改动大小,可以看到哪些模块增加了多少cell、删除了多少cell、改动多少根连线。我们需要根据ECO report来判断本次ECO的改动是否后端能够实现。
再通过run_lec()
确认一下修改之后是否完全等价,以防止遇到一些特殊情况,GOF ECO没有能完全修复。当然,也需要用业界认可的LEC工具,如formality或者conformal,来确认最终的ECO是否正确。如果不等价,可以用GOF电路图的方式来进一步分析和解决。
最后,写出ECO网表和脚本。
当流片回来测试后发现有问题时,就需要进行PostMask ECO。这时只能利用提前放置Spare Cells来改金属层。与PreMask的流程区别如下:
my $postmask = 1;
if($postmask){
# Postmask时读入def文件
read_def("topmod.def");
# 设置sparecell列表
get_spare_cells("spr_1/spr_gate*");
# 设置约束
set_constraints("-num", "and<3,or<3");
# 映射到sparecell
map_spare_cells();
# 查看ECO报告
report_eco();
}
# 写出eco网表和脚本
write_verilog("eco.gv");
write_soce2("eco.tcl");
在做postmask常常遇到附近资源不够或者连线比较拥挤,这时可以调整set_constraints()
的设置,多尝试几种方案。
后端工具里的操作和流程不属于这份入门教程的范围,但我们有一些有用的建议:
大部分基础问题都可以在《GOF用户手册》里找到答案。如果仍然不能解决,都可以向我们的技术支持人员(support@nandigits.cn)咨询。