3. Xcelium门级仿真环境搭建

门级仿真与RTL仿真最大的差别,不在于仿真器本身,而在于“被仿真的对象”从可综合的RTL代码变成了由综合工具输出的门级网表。网表里只有标准单元、宏单元、IO单元以及它们之间的连线,没有行为级描述,也没有参数化的抽象。因此,Xcelium要跑通一个门级用例,必须先把三件事对齐:工艺库的仿真模型、网表的单元引用名、以及仿真器对时序信息的处理方式。本节围绕这三件事,完成工具配置、库映射、网表编译、仿真选项设置,并跑通第一个门级仿真用例。

一、门级仿真环境的四个组成

一个可运行的门级仿真环境由四部分构成:仿真器(xrun/xmsim)、工艺库仿真模型(.v/.sv 格式的单元功能与时序模型)、门级网表(综合输出的 .v 网表)、以及测试平台(Testbench,通常复用RTL阶段的TB,但需要加上SDF反标和时序检查)。四者的关系可以用下面的结构图表示:网表通过实例化的单元名去库模型中查找对应的module,SDF文件把延迟信息反标到网表的实例和连线上,TB提供激励并观察输出。

Xcelium 门级仿真环境组成与数据流 工艺库仿真模型 std_cell.v / io.v / sram.v 功能 + 时序 + 单元名 (-v 编译进库) 门级网表 top_netlist.v 实例化标准单元/宏单元 (顶层 DUT) SDF 延迟文件 top.sdf IOPATH / INTERCONNECT (-sdf max:top:top.sdf) 单元名匹配 反标延迟 测试平台 Testbench tb_top.sv 激励 + 时序检查 + 结果比对 例化 DUT Xcelium 仿真器 xrun / xmsim 编译 + 精化 + 仿真 编译/运行 仿真输出 波形 shm.vcd log / 时序违例报告 产生 库模型提供单元定义,网表提供连接关系,SDF 提供延迟,TB 提供激励与检查,Xcelium 完成编译与仿真

二、工具配置与库映射

Xcelium的门级仿真通常用 xrun 一条命令完成编译、精化和运行,也可以用 xmvlog + xmelab + xmsim 分步执行。门级场景推荐分步,因为编译库模型和网表往往需要不同的选项。第一步是把工艺库模型编译进一个逻辑库,例如 work_lib:

# 建立库目录并映射逻辑名
mkdir -p work_lib
echo 'DEFINE work_lib ./work_lib' > cds.lib
echo 'INCLUDE $CDS_INST_DIR/tools/inca/files/cds.lib' >> cds.lib

# 编译工艺库仿真模型(功能+时序)
xmvlog -work work_lib \
       -sv \
       ./lib/std_cell.v \
       ./lib/io_cell.v \
       ./lib/sram_1024x32.v

# 编译门级网表与测试平台
xmvlog -work work_lib \
       -sv \
       ./netlist/top_netlist.v \
       ./tb/tb_top.sv

这里的关键是库映射:网表里实例化的单元名(如 NAND2X1、DFFRX1)必须能在 work_lib 中找到同名module。如果综合时使用了 -lib 或 link_library 指定了库名,而仿真时库模型文件名或module名不一致,就会出现 module 'NAND2X1' not found 的编译错误。排查方法是先在网表中搜索一个单元名,再在库模型文件中搜索同名module,确认两者完全一致(大小写敏感)。

如果工艺库提供的是加密模型(.v 中带 `protect 或 .svp),需要用 -v 或 -y 指定库搜索路径,而不是直接编译源文件。例如 -y ./lib +libext+.v+.sv,让Xcelium按单元名自动到目录中查找。

三、仿真选项设置

门级仿真的选项比RTL阶段多,核心是三类:时序反标、时序检查、以及性能与调试。下面是一组可直接参考的 xmelab 选项:

xmelab -work work_lib \
       -elaborate \
       -snapshot top_snap \
       -timescale 1ns/1ps \
       -sdf max:tb_top.dut:./sdf/top.sdf \
       -negdelay \
       -notimingchecks \
       -access +rwc \
       -define FUNCTIONAL \
       top_netlist tb_top

逐项说明:-sdf max:tb_top.dut:./sdf/top.sdf 表示把SDF中的最大延迟反标到TB中 dut 实例下,冒号前是SDF的corner(max/min/typ),中间是反标路径,最后是SDF文件;-negdelay 允许负延迟(某些工艺的hold检查会出现);-notimingchecks 在功能验证阶段关闭时序检查,避免大量违例淹没功能错误,等时序验证阶段再打开;-access +rwc 开放信号读写,便于在TB中强制或探测内部节点;-define FUNCTIONAL 用于条件编译,让TB在门级和RTL之间切换。

门级仿真中 -notimingchecks 与 -sdf 并不矛盾:前者关闭的是setup/hold等时序检查任务,后者仍然把延迟反标到路径上,因此功能波形仍带延迟。若要做时序签核,必须去掉 -notimingchecks,并配合 -timingchecks 和合适的 -negdelay 设置。

四、跑通第一个门级用例

以一个简单的4位计数器为例。RTL阶段TB已经能跑通,门级阶段需要做三处适配:第一,把DUT例化改为网表顶层模块名;第二,在TB中加入SDF反标语句(如果不用命令行 -sdf);第三,把复位和时钟的初始等待时间加长,因为门级路径有延迟,复位释放到第一个时钟沿之间需要留出足够的建立时间。

// tb_top.sv 片段
initial begin
  $sdf_annotate("./sdf/top.sdf", tb_top.dut, , "sdf.log", "MAXIMUM");
  clk = 0;
  rst_n = 0;
  #200 rst_n = 1;      // 门级下复位保持时间加长
  #2000;
  $display("TEST %s", (cnt === 4'hA) ? "PASS" : "FAIL");
  $finish;
end
always #5 clk = ~clk;  // 100MHz

运行命令:

xmsim -snapshot top_snap -gui -shm -shm_path ./wave &
# 或批处理模式
xmsim -snapshot top_snap -batch -logfile sim.log

判断用例是否跑通,看三个信号:sim.log 中是否有 TEST PASS;波形中 cnt 是否在时钟沿后按预期递增,且跳变沿相对时钟有可见延迟(说明SDF已生效);sdf.log 中是否有 Annotation completed 且无大量 Failed to annotate。如果 cnt 跳变与时钟完全对齐、没有任何延迟,说明SDF没有反标成功,需要检查 -sdf 的路径和实例名是否与网表一致。

五、常见问题与排查顺序

  • module not found:库模型未编译或单元名不匹配,检查 cds.lib 与 xmvlog -work 是否指向同一逻辑库。
  • SDF annotation failed:实例路径写错,用 -sdf max:/tb_top/dut:... 或先在TB中打印 %m 确认层次名。
  • X 态传播:门级未初始化节点多,检查复位是否覆盖所有寄存器,必要时在TB中对关键节点做 force 初始化。
  • 仿真速度慢:门级事件多,可关闭 -access +rwc、减少 $dumpvars 层次、用 -shm 替代 VCD。

完成以上步骤后,第一个门级用例即可跑通。此时环境已经具备库映射、网表编译、SDF反标和基本时序检查能力,后续的时序签核、功耗分析和形式验证都可以在此基础上展开。