05 · 故障注入、第一处差异与修复回归

在独立构建中注入一个确定性数据错误,串起日志、CSV 和波形定位,证明检查器有效。

先修知识能读 Verilog 与基本 shell 命令;按本系列前序章节完成对应验收。

适用环境统一工程 course_fifo / tb_top;SA Run 基线;命令依据 WXE 24.05,工具配对及资源配置以站点验证为准。

验证状态原创 RTL 与脚本已软件测试;Cadence 编译、硬件执行与 trace 待目标设备验证。

本文目录让失败可解释,再谈排障经验配置示例:只在故障构建定义宏操作步骤:从本地失败到目标设备复现预期输出:错误必须由独立检查器发现从第一处差异反推根因常见排障误区与校验失败典型故障:把检查器改成接受错误值

让失败可解释,再谈排障经验

本章在同一 FIFO 工程中加入一个确定性故障:读数据的最低位被翻转。它通过编译宏 COURSE_BUG 控制,正常源码与故障源码不需要手工来回编辑,分别保存在 local/sa 与 local-bug/sa-bug 构建中。这个案例由本站构造,不是客户事故。目标是证明检查器能捕获错误,并把第一处日志差异映射到波形中的具体更新。

可控故障的证据链正常输入第 0 笔 = 3故障读出XOR 低位 1检查器实际 2 ≠ 3修复回归独立正常构建数量一致不等于数据正确;先定位第一个错误事务
可控故障的证据链(原创示意,非器件引脚图;窄屏可横向滑动)

配置示例:只在故障构建定义宏

正常读操作把 mem[rp] 送到 dout,故障分支额外异或 8 位常量 1。输入 3 的二进制最低位因此从 1 变成 0,实际输出为 2;这是可以手算的根因。故障不改变指针、count 或握手,因此最终事务数仍然可能正确。这正好说明只比较完成数量不足以证明功能通过。

原工程的受控教学故障。flow.py compile --bug 才启用,正常构建不受影响。

SystemVerilog
`ifdef COURSE_BUG
  dout <= mem[rp] ^ 8'h01;
`else
  dout <= mem[rp];
`endif

操作步骤:从本地失败到目标设备复现

先用本地模拟器验证诊断路径,预期失败本身就是实验的一部分。工具返回非零时不要马上修脚本使其吞掉退出码;应读取 run.log 中首个 COURSE_MISMATCH。设备侧使用相同宏和输入,只把执行位置切换到 SA;若需要失败现场,使用 wave 模式保留会话与原始 trace,再进行第四章的离线导出。

  1. 编译独立故障版本

    预期与判定:build/local-bug 与正常 build/local 分开,避免污染已通过的基线。

  2. 运行 bug01 并保留非零退出

    预期与判定:首条差异应为 seq=0 expected=3 actual=2 cycle=13。

  3. 按需要在 SA 故障构建复现

    预期与判定:使用 sa-bug 和 wave 模式,功能失败时 runner 仍非零;从 run.json 找 trace_path。

  4. 回到正常构建做回归

    预期与判定:复用相同输入运行 fix01,64 笔逐笔通过且与 golden 一致。

在解压后的 palladium-course 工程根目录执行。标为硬件步骤的命令需在已配置的授权 Linux 环境验证。

Bash
python3 flow.py compile local --bug
python3 flow.py run local --bug --id bug01 --vcd
# 上一条应非零退出;阅读 runs/bug01/run.log
python3 flow.py run local --id fix01
python3 flow.py compare runs/golden/transactions.csv runs/fix01/transactions.csv

# 以下两条需要目标 Palladium 环境
python3 flow.py compile sa --bug
python3 flow.py run sa --bug --id bug-wave --mode wave

预期输出:错误必须由独立检查器发现

下面是本站软件故障变体的实际诊断值。COURSE_DONE 仍可能显示 sent 与 received 都为 64,但 mismatches 非零,不能被计为通过。wave 模式会允许 Tcl 完成采集后退出,再由调度器依据结果判失败;因此“采集成功”与“功能失败”可以同时成立。两个状态都应保留,不应把非零退出码强行改成零。

首条差异及 64 个错误由软件自测复现;SA 波形分支是待设备验证的操作流程。

Text
COURSE_MISMATCH seq=0 expected=3 actual=2 cycle=13
COURSE_DONE sent=64 received=64 mismatches=64 cycles=121 full_stall=32
# 普通模式:Testbench 报 COURSE_FAIL,进程非零
# wave 模式:采集后调度器报 COURSE_RESULT,仍非零

# 正常构建回归:
COMPARE_PASS: 64 ordered transactions match

从第一处差异反推根因

先看 seq=0 的输入是否确实为 3、是否被接受,再看该次读出前 empty 是否为 0。若输入与握手都正确而 dout 变为 2,继续核对读数据通路,不要先修改 Scoreboard 的期望公式。本例故障在输出更新处;真实项目还可能涉及存储读延迟、参数、字节序和复位。保持输入不变逐项排除,比从最后一次超时追查更直接。

第一处差异定位表
证据本例观察下一步
输入 CSV / 驱动第 0 笔为 3确认写入被接受
读边沿前rd_en=1 且 empty=0确认本笔读取有效
读边沿后dout=2,期望 3检查读数据通路
故障编译记录存在 COURSE_BUG对照 XOR 分支
正常构建复测dout=3,无差异确认修复未修改期望模型

常见排障误区与校验失败

失败用例应足够小且输入明确。更换随机种子、减少事务数、关闭检查器或修改期望值都可能让表面错误消失,却不能证明原问题被修复。本站调度器会重新校验 CSV,并保留独立运行标识;整理问题时同时提交构建身份、第一处差异和相关波形窗口,而不只发送一张没有时间或版本标识的截图。

排障误区与处理
现象 / 本包标识检查点正确处理
bug 版本没有失败build.json 的 bug 字段与命令确认 --bug 用于编译和运行,未误用正常 snapshot
CSV 数量正确但值错误逐笔内容与期望公式保留非零退出,不只比较数量
COURSE_STALE_BUILD修改了源码却复用旧编译归档并重新编译,不手改摘要
修复后换了输入才通过运行记录的 N 与输入公式用原始失败条件复测,再扩展覆盖

典型故障:把检查器改成接受错误值

当检查器暴露差异时,应先证明规格与参考模型正确,再修改设计。下面的案例说明如何避免循环论证:如果期望值直接从 DUT 输出计算,或为了消除失败把 3 改成 2,那么测试已经失去独立性。正常版通过与故障版失败必须同时成立,才能证明该检查至少能覆盖本类错误。

完成检查

  • 故障版第一笔错误可复现且非零退出
  • 日志、CSV 与波形使用同一个运行和构建身份
  • 正常版回归通过,检查器与黄金期望未被改写

延伸阅读与来源

本文为黄河电子原创教学说明。产品命令与支持范围请以实际安装版本的官方文档为准。

继续阅读

硬件仿真

首次使用前的工程检查清单

准备版本、输入和模型,减少第一次编译的无效往返。

10 分钟
硬件仿真

如何选择 SA/ICE 及交互方式

根据测试环境所在位置与目标接口要求选择运行流程。

11 分钟
硬件仿真

完成最小设计的编译运行

把第一次平台运行拆为有检查点的五个阶段。

10 分钟