3. Xcelium门级仿真环境搭建
门级仿真与RTL仿真最大的差别,不在于仿真器本身,而在于“被仿真的对象”从可综合的RTL代码变成了由综合工具输出的门级网表。网表里只有标准单元、宏单元、IO单元以及它们之间的连线,没有行为级描述,也没有参数化的抽象。因此,Xcelium要跑通一个门级用例,必须先把三件事对齐:工艺库的仿真模型、网表的单元引用名、以及仿真器对时序信息的处理方式。本节围绕这三件事,完成工具配置、库映射、网表编译、仿真选项设置,并跑通第一个门级仿真用例。
一、门级仿真环境的四个组成
一个可运行的门级仿真环境由四部分构成:仿真器(xrun/xmsim)、工艺库仿真模型(.v/.sv 格式的单元功能与时序模型)、门级网表(综合输出的 .v 网表)、以及测试平台(Testbench,通常复用RTL阶段的TB,但需要加上SDF反标和时序检查)。四者的关系可以用下面的结构图表示:网表通过实例化的单元名去库模型中查找对应的module,SDF文件把延迟信息反标到网表的实例和连线上,TB提供激励并观察输出。
二、工具配置与库映射
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 或 -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反标和基本时序检查能力,后续的时序签核、功耗分析和形式验证都可以在此基础上展开。