1. 为什么Sequential Pattern值得单独拎出来讲
做数字芯片DFT的同行都有个共识:组合逻辑的ATPG相对好啃,真正让人头疼的是带时序深度的Sequential Pattern。我刚开始接触Tessent那会儿,跑组合pattern一天能收敛好几轮,一上sequential就卡住,工具报abort、覆盖率上不去、仿真对不上,各种问题轮番来。后来项目做多了才慢慢摸清楚,sequential pattern的生成不是简单把工具参数一填就完事,它涉及时钟定义、时序约束、扫描链配置、pattern类型选择、仿真验证等一整条链路,任何一个环节出问题都会导致最终pattern不可用。
这篇内容主要面向已经有一定ATPG基础、正在用Tessent做sequential pattern生成的DFT工程师。我会把整个流程从环境准备到pattern输出、从参数配置到常见报错排查,按实际项目操作的顺序完整梳理一遍。里面涉及的参数和脚本都来自我实际项目中的配置,你可以直接参考修改后用到自己的设计上。对于刚入门的同学,建议先把组合pattern的流程跑通再来看这篇,不然有些概念可能会觉得跳跃。
核心关键词先明确一下:Tessent是西门子EDA旗下的DFT工具套件,ATPG是自动测试向量生成,Sequential Pattern指的是需要多个时钟周期才能检测到故障的测试向量,跟纯组合pattern最大的区别在于它依赖时序路径上的状态传播。常见问题排查这部分我会单独用一章来讲,把我在项目中踩过的坑和对应的解决思路整理成速查表。
2. Sequential Pattern生成的整体设计与思路拆解
2.1 组合pattern和sequential pattern的本质区别
很多人刚开始做ATPG的时候会有一个误区,觉得sequential pattern就是组合pattern多跑几个cycle而已。实际上两者的差异远不止cycle数。组合pattern假设故障效应只需要一个时钟周期就能传播到可观测点,工具在生成时不需要考虑时序单元之间的状态依赖。而sequential pattern必须把故障效应通过一系列时序单元逐级传播,每一级都需要时钟控制,工具需要搜索一个多周期的激励序列才能激活并传播故障。
这个差异直接导致几个后果。第一,sequential pattern的搜索空间比组合pattern大几个数量级,工具运行时间会显著增加。第二,sequential pattern对时钟定义和时序约束的依赖非常强,如果时钟波形定义不对,工具根本没法正确搜索。第三,sequential pattern的仿真验证更复杂,因为需要按周期施加激励并检查多周期的响应。理解这三点,后面很多配置和排查思路就顺了。
2.2 为什么选择Tessent做sequential ATPG
市面上做ATPG的工具不止一家,Tessent在这个领域的优势主要体现在几个方面。一是它对sequential depth的支持比较成熟,工具内部有专门的时序搜索算法,能处理较深的时序路径。二是Tessent的pattern类型划分很细,basic scan、full sequential、clock sequential等模式可以按需选择,灵活性高。三是它和Tessent Shell的集成度高,从设计读入、DFT插入到ATPG、仿真验证可以在同一套环境里完成,减少了工具间切换的成本。
在实际项目中,我通常会用Tessent先跑basic scan pattern看组合覆盖率,然后再开sequential模式补覆盖率。这样分阶段做的好处是,如果组合阶段就有大量uncovered fault,说明设计或约束本身有问题,先解决这些再上sequential,能避免在sequential阶段浪费大量时间。
2.3 整体流程的架构设计
一个完整的sequential pattern生成流程,我一般分成六个阶段来组织。第一阶段是环境准备,包括设计读入、库文件配置、DFT模式设置。第二阶段是时钟和时序约束定义,这是sequential pattern的核心前提。第三阶段是扫描链配置和pattern类型选择。第四阶段是ATPG运行和覆盖率分析。第五阶段是pattern仿真验证。第六阶段是pattern格式输出和后续交付。
这六个阶段不是严格线性的,实际项目中经常需要回到前面的阶段调整。比如ATPG覆盖率不达标,可能需要回头检查时钟约束是否完整;仿真对不上,可能需要重新确认扫描链配置。所以我在搭建流程的时候,会把每个阶段的配置写成独立的脚本文件,方便单独修改和重跑,而不是把所有配置堆在一个大脚本里。
3. 核心细节解析与实操要点
3.1 环境准备阶段的关键配置
环境准备看起来简单,但很多后续问题的根源都在这里。首先是库文件的读入,Tessent需要标准单元库、IO库、存储器库等多类库文件。我一般会在脚本里用read_verilog读设计,用read_cell_library读库,顺序不能反,否则工具可能找不到单元定义。
# 读入库文件 read_cell_library ./libs/std_cell.lib read_cell_library ./libs/io_cell.lib read_cell_library ./libs/memory.lib # 读入设计 read_verilog ./rtl/top.v read_verilog ./rtl/sub_module.v # 设置顶层模块 set_current_design top这里有个细节要注意:库文件的corner选择。做ATPG一般用typical corner就够了,但如果设计对时序比较敏感,建议用worst corner的库,这样生成的pattern在时序上更保守,仿真通过率更高。我遇到过用fast corner库生成pattern、结果在slow corner仿真时setup违例导致pattern失效的情况,后来统一改用worst corner就没再出过这个问题。
另一个容易忽略的点是设计中的black box处理。如果设计里有一些不需要做ATPG的模块,比如模拟IP或第三方加密模块,需要在脚本里用add_black_box或set_dont_touch标记出来,否则工具会尝试对这些模块做ATPG,浪费时间还可能报错。
3.2 时钟定义:sequential pattern的命门
时钟定义是sequential pattern生成中最关键也最容易出错的部分。Tessent需要知道每个时钟的周期、波形、相位关系,才能正确搜索多周期激励。我一般用add_clock命令来定义时钟,需要指定时钟源、周期、上升沿和下降沿位置。
# 定义主时钟 add_clock -name clk_main -period 10 -waveform {0 5} -source [get_ports clk] # 定义分频时钟 add_clock -name clk_div2 -period 20 -waveform {0 10} -source [get_pins div_reg/Q] # 定义时钟之间的相位关系 set_clock_relationship -from clk_main -to clk_div2 -phase 0这里有几个实操要点。第一,时钟周期要和实际设计一致,不能随便填。如果周期填得太小,工具可能找不到满足时序的激励序列;填得太大,pattern数量会增加。第二,多时钟设计一定要定义时钟之间的相位关系,否则工具会假设时钟完全异步,导致搜索空间爆炸。第三,对于门控时钟,需要确保在ATPG模式下门控使能是打开的,否则时钟传不到后续时序单元。
我踩过的一个坑是:设计里有一个时钟是内部PLL产生的,我在ATPG时没有正确bypass PLL,导致工具认为这个时钟不存在,大量时序单元没有被覆盖。后来在DFT模式下加了PLL bypass逻辑,把参考时钟直接引到PLL输出端,问题才解决。所以时钟定义不只是写几条命令,还要确认DFT模式下的时钟路径是否正确。
3.3 扫描链配置与pattern类型选择
扫描链配置决定了pattern怎么加载和卸载。Tessent支持多种扫描链模式,我一般用set_scan_configuration来设置扫描链的数量、长度和时钟域。
# 设置扫描链配置 set_scan_configuration -chain_count 8 \ -clock_mixing mix_clocks \ -add_lockup true # 设置扫描链的时钟域 set_scan_configuration -clock_domain clk_main \ -chain_count 4 set_scan_configuration -clock_domain clk_div2 \ -chain_count 4-clock_mixing mix_clocks这个选项允许不同时钟域的扫描链混合,但需要加lockup latch来避免跨时钟域的hold问题。-add_lockup true就是自动插入lockup latch。如果设计对面积敏感,也可以手动控制lockup latch的插入位置。
pattern类型选择方面,Tessent提供了几种模式。basic scan只做组合ATPG,速度快但覆盖率有限。full sequential做完整的时序ATPG,覆盖率最高但运行时间最长。clock sequential是折中方案,按时钟周期逐步搜索,适合时序深度不太大的设计。我在项目中一般先用basic scan跑一轮,看看覆盖率基线,然后根据uncovered fault的类型决定是否上full sequential。
# 先跑basic scan set_pattern_type -basic_scan run_atpg -auto_compression # 再跑sequential补充 set_pattern_type -full_sequential run_atpg -auto_compression3.4 ATPG运行参数调优
ATPG运行阶段的参数调优直接影响覆盖率和运行时间。我常用的几个参数包括-auto_compression自动压缩pattern、-effort high提高搜索力度、-abort_limit设置abort上限。
# 设置ATPG运行参数 set_atpg -effort high set_atpg -abort_limit 100 set_atpg -max_cycles 50 run_atpg -auto_compression-effort high会让工具花更多时间搜索,适合覆盖率要求高的场景。-abort_limit控制单个fault的搜索次数上限,设得太小会导致大量fault被abort,设得太大运行时间会很长。我一般从100开始试,如果abort的fault比较多再往上调。-max_cycles限制sequential pattern的最大周期数,这个参数需要根据设计的时序深度来定。如果设得太小,深时序路径上的fault覆盖不到;设得太大,pattern数量会膨胀。
这里有个经验:-max_cycles不要一上来就设很大。我一般先设20跑一轮,看看覆盖率,然后逐步增加到50、100,观察覆盖率增长曲线。如果增加到某个值后覆盖率不再明显提升,说明大部分可覆盖的fault已经覆盖了,再增加只会增加pattern数量。
4. 实操过程与核心环节实现
4.1 完整脚本流程与执行顺序
把前面几个阶段的配置串起来,一个完整的sequential pattern生成脚本大概长这样。我按实际执行顺序排列,每一步都有明确的意图。
# ========== 第一阶段:环境准备 ========== read_cell_library ./libs/std_cell_wc.lib read_verilog ./rtl/top.v set_current_design top # 设置DFT模式 set_dft_signal -view existing_dft -type ScanClock -port clk -timing {45 55} set_dft_signal -view existing_dft -type Reset -port rst_n -active_state 0 set_dft_signal -view existing_dft -type ScanEnable -port scan_en -active_state 1 # ========== 第二阶段:时钟定义 ========== add_clock -name clk_main -period 10 -waveform {0 5} -source [get_ports clk] set_clock_relationship -from clk_main -to clk_main -phase 0 # ========== 第三阶段:扫描链配置 ========== set_scan_configuration -chain_count 8 -clock_mixing mix_clocks -add_lockup true set_scan_path -chain chain_0 -scan_enable scan_en -scan_in si_0 -scan_out so_0 # ... 其他扫描链配置 # ========== 第四阶段:ATPG运行 ========== set_pattern_type -full_sequential set_atpg -effort high -abort_limit 100 -max_cycles 50 run_atpg -auto_compression # ========== 第五阶段:覆盖率报告 ========== report_faults -summary report_faults -not_detected > uncovered_faults.rpt # ========== 第六阶段:pattern输出 ========== write_patterns ./patterns/sequential_pattern.stil -format stil -replace write_patterns ./patterns/sequential_pattern.v -format verilog -replace这个脚本可以直接作为模板使用,需要根据具体设计修改库文件路径、端口名、扫描链数量等参数。我建议把每个阶段的配置放在独立的tcl文件里,用source命令依次调用,这样调试的时候可以单独重跑某个阶段,不用从头再来。
4.2 覆盖率分析与uncovered fault处理
ATPG跑完之后,覆盖率分析是下一步的重点。Tessent的report_faults命令可以输出详细的fault分类,我一般会关注几个关键指标:test coverage、fault coverage、ATPG effectiveness。
# 输出覆盖率摘要 report_faults -summary # 输出未检测到的fault详情 report_faults -not_detected -verbose > undetected.rpt # 输出abort的fault report_faults -aborted > aborted.rpt对于uncovered fault,我一般按类型分类处理。如果是uncontrolled类型的fault,说明fault点的激励无法从扫描链或primary input控制到,需要检查扫描链配置或增加测试点。如果是unobserved类型的fault,说明故障效应传播不到可观测点,可能需要增加时序深度或调整时钟约束。如果是aborted类型的fault,说明工具搜索超时,可以尝试提高-abort_limit或-effort。
我遇到过一个典型案例:设计中有一个跨时钟域的握手逻辑,fault覆盖率一直上不去。查了uncovered fault报告后发现,大部分fault是uncontrolled,原因是握手逻辑的使能信号来自另一个时钟域,在ATPG模式下没有被正确初始化。后来在DFT模式下加了跨时钟域的bypass逻辑,让使能信号可以被扫描链直接控制,覆盖率从85%提升到了96%。
4.3 Pattern仿真验证的关键步骤
Pattern生成之后必须做仿真验证,确认pattern在实际时序下能正确检测故障。Tessent支持生成Verilog testbench和STIL格式的pattern,我一般用Verilog testbench做门级仿真。
// 生成的testbench结构示意 initial begin // 初始化 scan_en = 0; rst_n = 0; #100 rst_n = 1; // 加载pattern scan_en = 1; // 扫描链加载数据 // ... // 施加时钟脉冲 scan_en = 0; // 捕获响应 // ... end仿真验证的重点是检查pattern的时序是否正确。我一般会关注几个点:扫描链加载和卸载的时序是否满足setup/hold要求、时钟脉冲的数量和位置是否与pattern定义一致、捕获响应的时刻是否在时钟有效沿之后。如果仿真出现X态传播或时序违例,需要回到ATPG阶段检查时钟约束和扫描链配置。
有个实操技巧:仿真时先用少量pattern跑一遍,确认基本时序没问题,再跑全量pattern。全量仿真时间可能很长,先用小批量验证能快速发现问题,避免浪费时间。
4.4 Pattern格式输出与交付
Pattern输出格式取决于后续的测试设备。STIL格式是通用格式,大多数ATE设备都支持。Verilog格式适合做仿真验证。有些项目还需要WGL格式或VCD格式,Tessent都支持。
# 输出STIL格式 write_patterns ./patterns/seq_pattern.stil -format stil -replace # 输出Verilog格式 write_patterns ./patterns/seq_pattern.v -format verilog -replace # 输出WGL格式 write_patterns ./patterns/seq_pattern.wgl -format wgl -replace输出的时候要注意pattern的命名和版本管理。我一般会在文件名里加上日期和版本号,比如seq_pattern_v1.2_20240115.stil,避免不同版本的pattern混淆。另外,输出的pattern文件要跟覆盖率报告一起归档,方便后续追溯。
5. 常见问题与排查技巧实录
5.1 ATPG运行报错与abort问题排查
Sequential ATPG运行中最常见的问题就是abort。工具报abort的原因有很多,我整理了一个速查表。
| 报错信息 | 可能原因 | 排查思路 | 解决方法 |
|---|---|---|---|
| ATPG aborted due to timeout | 搜索空间太大 | 检查时钟约束是否完整 | 增加abort_limit,或减少max_cycles |
| No pattern found for fault | 故障不可控或不可观测 | 查看uncovered fault报告 | 增加测试点或调整扫描链 |
| Clock not defined | 时钟约束缺失 | 检查add_clock命令 | 补充时钟定义 |
| Scan chain broken | 扫描链配置错误 | 检查scan_path设置 | 重新配置扫描链 |
| Simulation mismatch | 时序约束不一致 | 对比ATPG和仿真时钟 | 统一时钟定义 |
我遇到最多的是timeout问题。有一次跑一个大型SoC的sequential ATPG,工具跑了六个小时还没结束,最后报timeout。查了之后发现是时钟约束里漏了一个分频时钟,工具把这个时钟当成了自由振荡的时钟,搜索空间爆炸。补上时钟定义后,运行时间降到了四十分钟。
另一个常见问题是scan chain broken。这个报错通常是因为扫描链的scan_in和scan_out端口配置错了,或者扫描链的时钟域不匹配。我一般会用report_scan_chains命令检查扫描链的配置,确认每条链的输入输出端口和时钟域都正确。
5.2 覆盖率不达标的原因分析与解决
覆盖率不达标是另一个高频问题。我一般按以下步骤排查。
第一步,看覆盖率报告里的fault分类。如果uncontrolled占多数,说明激励控制有问题,重点检查扫描链和primary input的可控性。如果unobserved占多数,说明观测路径有问题,重点检查时序深度和观测点。如果aborted占多数,说明搜索力度不够,调整ATPG参数。
第二步,检查是否有black box或dont_touch模块影响了覆盖率。这些模块内部的fault不会被ATPG覆盖,如果它们占了设计的大部分面积,覆盖率自然上不去。确认这些模块是否真的不需要覆盖,如果不需要,在覆盖率报告里排除它们。
第三步,检查时钟约束是否完整。我遇到过一个案例,设计里有一个时钟是门控的,在ATPG模式下门控使能没有被打开,导致这个时钟域的所有时序单元都覆盖不到。后来在DFT模式下强制打开门控使能,覆盖率提升了8个百分点。
第四步,考虑增加测试点。如果以上都排查了还是覆盖不到,可能需要在设计里插入测试点,比如增加观测点或控制点。Tessent支持自动插入测试点,可以用add_test_point命令。
5.3 仿真对不上的调试思路
Pattern仿真对不上是让人很头疼的问题。仿真对不上通常表现为:仿真结果里检测到的fault数量和ATPG报告不一致,或者仿真出现X态传播。
我一般按以下顺序排查。首先确认仿真用的网表和ATPG用的网表是同一个版本,有时候网表更新了但pattern没重新生成,就会对不上。其次确认仿真用的库文件和ATPG用的库文件是同一个corner,fast corner和slow corner的时序差异可能导致仿真结果不同。然后检查仿真testbench里的时钟定义是否和ATPG脚本里的时钟定义一致,包括周期、波形、相位关系。
X态传播的问题通常是因为设计里有未初始化的时序单元。在ATPG模式下,工具会假设所有时序单元都可以被扫描链初始化为确定值。但在仿真中,如果某些时序单元没有被正确初始化,就会传播X态。解决方法是在仿真testbench里增加初始化序列,或者在ATPG脚本里设置set_atpg -initial_state来指定初始状态。
5.4 实操避坑经验汇总
最后分享几个我在项目中总结的避坑经验。
第一,时钟定义一定要和设计文档核对。我见过太多因为时钟定义错误导致ATPG失败的案例。建议在定义时钟之前,先画一张时钟树图,把所有时钟源、分频、门控关系理清楚。
第二,扫描链配置要留余量。扫描链数量不要刚好够用,建议多配一两条备用链。如果后续设计修改增加了时序单元,备用链可以直接用,不用重新配置。
第三,ATPG参数不要一次调到最激进。先用保守参数跑一轮,确认基本流程没问题,再逐步调优。我一般先用-effort medium和-abort_limit 50跑一轮,看看覆盖率和运行时间,再决定是否加码。
第四,pattern仿真要分批次做。全量pattern仿真可能跑几个小时,建议先跑10%的pattern确认时序没问题,再跑全量。如果10%就有问题,全量跑了也是浪费时间。
第五,覆盖率报告要存档。每次ATPG运行后,把覆盖率报告和uncovered fault报告存档,方便后续对比。如果某次修改后覆盖率下降了,可以快速定位是哪个环节出了问题。
第六,DFT模式下的时钟和复位要仔细检查。很多ATPG问题根源都在DFT模式配置上,比如时钟没有bypass PLL、复位没有正确释放、门控时钟没有打开。建议在ATPG之前先用report_dft_signals检查一遍DFT信号配置。
第七,跨时钟域逻辑要特别关注。跨时钟域的握手逻辑、异步FIFO等结构在ATPG中容易出问题,建议在DFT设计阶段就考虑好这些结构的可测试性,必要时增加bypass逻辑或测试点。
这些经验都是我在实际项目中踩坑踩出来的,希望能帮你少走一些弯路。Sequential pattern生成没有捷径,就是把每个环节的细节都做扎实,时钟定义清楚、扫描链配置正确、ATPG参数合理、仿真验证到位,覆盖率自然就上去了。