3. FSDB波形数据库生成与优化
FSDB(Fast Signal Database)是 Verdi 原生波形数据库,也是 SoC 验证中故障定位的主要数据来源。与 VCD 相比,FSDB 采用压缩编码与分块索引,在同等信号规模下体积通常可缩小一个数量级,同时支持按层次、按时间窗口快速检索。但 FSDB 的生成并非“打开开关即可”,dump 策略、信号选择、层次控制与存储优化之间存在明确的取舍关系:dump 得越全,回放精度越高,但磁盘占用与仿真开销也越大;dump 得越省,仿真跑得快,却可能在定位故障时发现关键信号缺失,只能重跑。本节围绕这一平衡展开。
一、FSDB dump 的三种基本策略
在仿真侧,FSDB 的生成通常通过 Verdi 提供的 PLI/VPI 接口或仿真器内置的 FSDB dump 选项完成。按触发方式可分为三类:
- 全程 dump:从仿真 0 时刻到结束持续记录。优点是回放完整,任何时间点的信号都可查;缺点是文件巨大,长时间 SoC 仿真可能达到数百 GB。
- 窗口 dump:只在指定时间区间内记录,例如
$fsdbDumpoff与$fsdbDumpon配合,在复位释放后到关键事务结束之间开启。适合已知故障大致时间范围时的复现。 - 事件触发 dump:由断言失败、错误标志置位或特定事务 ID 命中触发,只保留故障前后一段“现场”。这是 SoC 验证中最常用的方式,兼顾精度与体积。
选择策略的核心判断依据是:故障是否可复现、复现时间是否可控。若故障随机出现且时间不可预测,应优先保证全程 dump 或加大窗口;若故障由特定激励触发,则事件触发 dump 更经济。
二、信号选择:从“全 dump”到“按需 dump”
信号选择决定 FSDB 中记录哪些对象。常见做法是先用 $fsdbDumpvars 指定顶层或模块层次,再通过 $fsdbDumpvars(0, top.u_dut.u_core) 这类调用限定范围。更精细的控制包括:
- 按信号类型过滤:只 dump 时钟、复位、状态机状态、总线请求/应答、错误标志等定位必需信号,跳过大量数据通路中间节点。
- 按位宽过滤:对宽总线可只 dump 有效字节或关键字段,例如只记录
data[31:0]中的data[7:0]命令字段。 - 按层次深度过滤:限制 dump 深度,避免把子模块内部所有寄存器全部展开。
一个实用的信号选择清单可以按“故障定位必需度”分级:一级为时钟、复位、顶层握手;二级为状态机、FIFO 满空、仲裁授权;三级为数据通路与内部寄存器。一级必须 dump,二级按模块开启,三级仅在定向复现时临时加入。
三、dump 层次控制与存储优化
层次控制通过 $fsdbDumpvars(depth, module) 的 depth 参数实现。depth=0 表示只 dump 指定模块本身,depth=1 表示包含其直接子模块,依此类推。对于 SoC 中重复实例化的子模块(如多个 CPU 核、多个 DMA 通道),可以只对故障相关实例开启 dump,其余实例关闭,从而显著降低文件体积。
存储优化还可从以下角度入手:
- 压缩选项:FSDB 支持压缩级别设置,较高压缩率会略微增加仿真时的 CPU 开销,但可减少 30%~50% 磁盘占用。
- 分文件存储:按时间或按模块拆分为多个 FSDB 文件,便于并行加载与局部回放。
- 定期清理:对已定位并归档的故障,保留精简后的 FSDB,删除原始大文件。
四、回放精度与存储的平衡
回放精度取决于三个因素:时间分辨率、信号覆盖度和采样方式。FSDB 默认按仿真时间步记录变化,若仿真时间精度为 1ps,则时间轴精度也为 1ps。降低时间分辨率(如只记录 1ns 边界)可减小文件,但可能丢失毛刺和亚稳态窗口。信号覆盖度则直接决定能否在回放中观察到故障传播路径。
平衡的方法是:先保证关键路径信号与时间精度,再对非关键区域降采样或关闭。例如,对时钟域交叉和异步接口保留高精度,对已稳定的数据通路只记录事务级变化。实际项目中,可将 FSDB 分为“调试用高精度文件”和“归档用精简文件”两套,前者用于定位,后者用于回归对比。
五、一个可参考的 FSDB 配置片段
以下示例展示在仿真 testbench 中按层次与信号级别控制 FSDB dump 的典型写法。示例参数为教学假设,实际使用时需根据仿真器与项目命名调整。
initial begin
// 设置 FSDB 文件与压缩级别
$fsdbDumpfile("wave_top.fsdb");
$fsdbDumpvars(0, tb_top.u_dut.u_core); // 只 dump core 层次
$fsdbDumpvars(1, tb_top.u_dut.u_dma); // DMA 含一级子模块
$fsdbDumpoff; // 默认关闭
// 复位释放后开启窗口 dump
wait (tb_top.u_dut.u_core.rst_n == 1'b1);
#1000;
$fsdbDumpon;
// 错误触发时保留现场
fork
begin
@(tb_top.u_dut.u_core.err_flag);
$fsdbDumpoff;
end
join_none
end
该片段中,$fsdbDumpvars(0, ...) 只记录 core 模块自身信号,$fsdbDumpvars(1, ...) 额外记录 DMA 的直接子模块。通过 $fsdbDumpoff 与 $fsdbDumpon 形成窗口,再以 err_flag 触发关闭,可在故障发生后立即冻结波形,避免后续无关激励继续写入。
六、结果观察与判断依据
生成 FSDB 后,应检查三件事:文件大小是否在预期范围内、关键信号是否完整、时间轴是否覆盖故障窗口。在 Verdi 中打开 FSDB,使用 Get Signals 搜索一级信号清单,确认时钟、复位、状态机状态均存在;拖动时间轴到故障发生点,观察信号跳变是否连续、有无缺失段。若发现关键信号缺失,应回到信号选择清单补充;若文件过大,则优先降低非关键层次的 dump 深度或启用更高压缩级别。
综上,FSDB 的生成与优化是一个“按需记录、分层控制、精度优先”的过程。策略决定记录范围,信号选择决定记录内容,层次控制决定记录深度,存储优化决定记录成本,而回放精度则是最终验收标准。五者需要在项目初期就形成约定,并在故障定位过程中根据实际缺失情况动态调整,而不是等到波形打不开时才回头补救。