TetraMAX 实战:S1 扫描链阻断与门级仿真 X 态的排查与修复全记录
专栏:iLoveIC Aug. 10, 2026, 12:15 p.m. 3 阅读
这次排障最深的体会是"同一个缺陷,在三个层面有三种表现":DFTC 少声明了两个 Constant 信号,到了 TetraMAX 是 S1 链阻断,到了门级仿真又变成漫天 X 态。第一层用 add_pi_constraints 打补丁能过 DRC、出 pattern,看似好了,其实只是"TetraMAX 知道了"而"testbench 不知道"——工具内部视图和协议文件不一致,是最隐蔽的坑。另外一点:遇到 X 不要急着看波形大海捞针,先算清楚 X 集中在哪些脚、出现在哪个阶段,再用探针沿控制信号追,两轮就能收敛。

工具:Synopsys TetraMAX O-2018.06-SP1、Cadence Xcelium xrun 19.09
设计:digital_top(数字顶层,DFTMAX 压缩,4 扫描口对 48 条内部链)
关键词:run_drc、S1 chain blocked、add_pi_constraints、test_setup、MAX testbench、X 态、stil2verilog
前情:《DFT Compiler 实战:扫描链没有连到指定端口的排查与修复全记录》(同设计的 DFT 插入阶段)

一、问题现象

DFT 插入完成后进入 ATPG 阶段,cd atpg/syn/run && make atpg,TetraMAX 在 run_drc 阶段直接阵亡:

Begin compressor chain I/O checking: #undefined_io=96 ...
End compressor chain output checking: #resolved=0, #ambiguous=48, #failed=0, #undefined_inputs=48
Begin scan chain operation checking...
Error: Chain 1 blocked at DFF gate u_sub_a_top/.../data_out_reg_1_ (225355) after tracing 0 cells. (S1-1)
Error: Chain 2 blocked at DFF gate ... (S1-2)
...48 条链,全军覆没 ...
Error: Design rules checking failed: cannot exit DRC command mode. (M100)

48 条压缩链全部在链尾第一个 DFF 处被阻断(after tracing 0 cells),compressor 链 I/O 解析 0 条成功。链构建(build model)阶段完全正常,说明网表本身没读坏——问题出在扫描移位路径的状态上。

二、第一轮排查:S1 阻断的根因

2.1 从报错 DFF 顺藤摸瓜

S1 的 trace 方向是从扫描输出口向回追,"blocked at DFF after tracing 0 cells" 意味着刚摸到链尾 DFF 就过不去了——能通过 DFF 的条件是:移位时 SE 有效、时钟可控、异步复位释放。48 条链横跨所有子系统都同症状挂掉,必然是全局性信号出了问题

在网表里追链 1 尾触发器 u_sub_a_top/u_sub_a_cal/u_sub5_cal/data_out_reg_1_ 的时钟:

SDFQRM2TM data_out_reg_1_ ( .D(N1343), .SD(data_out[2]), .SE(IN94),
                            .CK(net117207), .RB(IN20), .Q(data_out[1]) );

net117207 来自一个 test_point 版 ICG(时钟门控单元):

module SNPS_CLOCK_GATE_HIGH_xxx_sub_cal_0_test_84 ( CLK, EN, ENCLK, TE,
        scan_mode, digital_top_P2D_CLK_5__in );
  LAGCESM12TM latch ( .CK(CLK), .E(EN), .SE(scan_mode), .GCK(n5) );
  MUX2M2TM U1 ( .A(n5), .B(digital_top_P2D_CLK_5__in), .S(scan_mode),
        .Z(ENCLK) );
endmodule

只有 scan_mode=1 时,扫描时钟 P2D_SCAN_CLOCK 才能旁路功能门控时钟到达 DFF。 继续向上追 scan_mode:IN80 ← n336 ← IN92 ← IN111 ← 顶层 n1795 = BUF(ATPG_EN),而 ATPG_EN 的来源是:

AN2M22TM u_AND_scan_mode ( .A(P2D_ATPG), .B(P2D_TEST), .Z(ATPG_EN) );

全片扫描时钟切换逻辑由 P2D_ATPG AND P2D_TEST 控制

2.2 查 SPF:两个模式脚从未被约束

DFTC 写出的 digital_top_dft_compressed.spf 里:

  • test_setup 只强制了 A2D_RST_PORB=1, P2D_SCAN_CLOCK=0, P2D_SCAN_COMPRESS_EN=1

  • load_unload 的 C 向量 "all_inputs" = \r93 N 1 \r27 N 0 \r17 N 1 \r7 N——按 all_inputs 信号表逐位对照,只有第 94 位(A2D_RST_PORB)=1、第 122 位(P2D_SCAN_CLOCK)=0、第 140 位(P2D_SCAN_COMPRESS_EN)=1;第 117 位 P2D_ATPG 和第 146 位 P2D_TEST 都是 N(未知态)

于是 ATPG_EN = X → scan_mode = X → 每个扫描 DFF 的时钟为 X → 全部 48 条链在第一个 DFF 处被堵死。SE 路径(P2D_SCAN_EN 经 buffer 直连 test_se)和复位路径检查下来都是干净的,唯独这个模式脚没人管。

2.3 修复与验证

tmax.tclrun_drc 之前加两行:

add_pi_constraints 1 P2D_ATPG
add_pi_constraints 1 P2D_TEST

重跑后 run_drc 直接通过,48 条链全部识别(链长 476/475),compressor 连接解析正常。ATPG 顺利生成 1859 个 pattern 和串/并行 testbench。

三、第二轮排查:仿真 290 万个 X mismatch

3.1 现象

run_sim_parallel.csh(xrun + MAX testbench)跑完,xrun.log2,936,022 处 got=x

  • 4 个扫描输出口 D2P_SCAN_DATA_OUT[0]/[1]/[2]/[3] 各约 53 万次——几乎每个移位周期的输出比较都是 X;

  • 大量功能 PO(D2A_TX_DA0、D2A_VDDT_、D2E_)在 capture 时也读出 X,从 pattern 0 的第一个 capture(T=540ns)就开始。

3.2 探针定位:ATPG_EN 的"X 窗口"

直接跑 xrun 探针(-input probe.tclvalue/drivers 命令)采样关键信号:

T=125ns: ATPG=1 TEST=1 COMPRESS_EN=1 EN=1        ← test_setup 生效,一切正常
T=225ns: ATPG=x TEST=x SCAN_EN=1 EN=x       ← pattern 0 的 load_unload 开始,EN 掉回 X
T=350ns: EN=x, SCAN_CLOCK=1X 窗口内时钟正在脉冲!
T=425ns: EN=1                            ← capture 过程的 F 语句把它们拉回 1
T=625ns: EN=x                            ← 下一个 pattern 的 load_unload,又掉回 X

机制清楚了:MAX testbench 按 STIL 字面执行——C 向量里值为 N 的输入脚会被驱动成 X。每个 pattern 的 load_unload C 一执行,P2D_ATPG/P2D_TEST 就掉回 X(它们的位置是 N),ATPG_EN 跟着变 X,而此时移位时钟正在脉冲——测试点 ICG 的 MUX 选择端为 X,全片扫描单元的时钟为 X,链内容当场被摧毁。capture 过程里的 F { P2D_TEST=1; P2D_ATPG=1; }(这是 add_pi_constraints 带给 STIL 的)执行时机在 load_unload 之后,救不回来。

一句话:add_pi_constraints 只修正了 TetraMAX 内部的仿真视图(DRC、ATPG、期望值),并没有改 SPF 协议本身的 C 向量——而 Verilog testbench 是拿协议逐位驱动的。两边视图不一致,TMAX 认为链里是已知值,xrun 里全是 X。

3.3 修复:给 SPF 的 C 向量补上约束

备份后修改 digital_top_dft_compressed.spf

  • 4 处 C 向量(load_unload + 各 capture 过程):

# 原:\r93 N 1 \r27 N 0 \r17 N 1 \r7 N
# 改:\r93 N 1 \r22 N 1 \r4 N 0 \r17 N 1 \r5 N 1 N
#     (即第 117P2D_ATPG=1、第 146P2D_TEST=1,总位数 147 不变)
  • test_setup 的 V 语句补上 "P2D_ATPG" = 1; "P2D_TEST" = 1;

重跑 tmax 再生成 pattern 和 testbench,再跑并行仿真:

XTB: Simulation of 1859 patterns completed with 0 mismatches (time: 929700.00 ns, cycles: 9297)

1859 个 pattern,0 mismatch,收工。

四、治本:回到 DFT Compiler 把约束写进协议

手改 SPF 只是权宜之计(DFT 流程重跑会覆盖)。正确做法是在 DFTC 脚本里声明这两个脚为测试恒值,让 write_test_protocol 自带约束:

# -port 接受 Tcl 列表,一行即可;分两行写也完全等价
# 注意不能用 P2D_ATPG/P2D_TEST 这种斜杠写法,会被当成一个端口名
set_dft_signal -view existing_dft -type Constant -active_state 1 -port {P2D_ATPG P2D_TEST}

几个要点:

  • 用 existing_dft 而不是 specu_AND_scan_mode 这个 AND 门在网表里已经存在,不需要 DC 建任何物理连接,只是告诉协议/DRC"测试期间这两脚恒为 1"。(视图语义详见前一篇博客:existing_dft 只读不建,spec 才指导建设。)

  • 用 Constant 而不是 TestMode+encoding:encoding 只在对应模式生效,而 ATPG_EN 要求所有扫描模式都为 1。

  • 位置:放在 create_test_protocol 之前(自然也就早于 insert_dft)——Constant 是在生成协议那一步固化进去的。

  • 多模式归属:流程里有 define_test_mode 的话,注意 set_dft_signal 不带 -test_mode 只作用于最后定义的模式,必要时加 -test_mode all

  • 验证:新 SPF 里 grep 确认 test_setup 含 "P2D_ATPG" = 1; "P2D_TEST" = 1,且 load_unload C 向量对应位为 1。

五、过程中踩过的环境坑(顺带记录)

  1. 无 DISPLAY 时 make atpg 跑不了:Makefile 里裸调 tmax 会进 GUI 模式。SSH 无显示环境下用 tmax -shell tmax.tcl 等效。

  2. write_testbench 内部调 stil2verilog 会弹 xterm:无显示环境下失败。Xvfb 又因服务器缺 X11 字体(could not open default font 'fixed')起不来。最终方案:跳过 tmax 的封装,直接跑 stil2verilog ../stil/patterns_parallel.stil ../sim/dft_testbench_parallel -replace(并行)/ -serial(串行),产物与原流程逐字节一致。

  3. 同一目录重跑 xrun 会覆盖 xrun.log:分析旧日志前先备份或先提取统计。

六、知识点总结

  1. S1 "blocked at DFF after tracing 0 cells" 的读法:trace 从扫描口向回追,0 cells 表示链尾第一个 DFF 就过不去——优先查全局信号:扫描时钟是否到达、SE 是否有效、异步复位是否释放。48 条链同症状挂掉,基本不可能是局部问题。

  2. test_point 版 ICG 是时钟路径的关键嫌疑人MUX(A=功能门控时钟, B=扫描时钟, S=scan_mode) 结构下,scan_mode 的来源链(本例 P2D_ATPG AND P2D_TEST)必须全程已知。

  3. add_pi_constraints 的作用域只是 TetraMAX 内部:它约束 DRC/ATPG 仿真和 STIL 期望值,还会在 capture 过程里补 F 语句,但不会修改来自 SPF 的 load_unload C 向量。协议文件本身的缺陷必须回协议层(或 DFTC)修。

  4. MAX testbench 把 C 向量里的 N 驱动为 X:STIL 里 N 是"未知",TB 如实照办。凡是在测试期间必须恒定的脚,一定要在协议里写死,不能指望"没人动它"。

  5. X 态排查三板斧:先统计 mismatch 集中在哪些脚/哪个阶段(shift vs capture)→ 再用 xrun -input probe.tclvalue/drivers 沿锥体逐级追 → 重点怀疑控制信号(时钟门控、模式选择、复位),而不是数据路径。

七、心得

这次排障最深的体会是"同一个缺陷,在三个层面有三种表现":DFTC 少声明了两个 Constant 信号,到了 TetraMAX 是 S1 链阻断,到了门级仿真又变成漫天 X 态。第一层用 add_pi_constraints 打补丁能过 DRC、出 pattern,看似好了,其实只是"TetraMAX 知道了"而"testbench 不知道"——工具内部视图和协议文件不一致,是最隐蔽的坑。另外一点:遇到 X 不要急着看波形大海捞针,先算清楚 X 集中在哪些脚、出现在哪个阶段,再用探针沿控制信号追,两轮就能收敛。

感谢阅读,更多文章点击这里:【专栏:iLoveIC】
最新20篇