xrun 完全指南:仿真、覆盖率与门级调试全掌握

发布时间:2026/10/2 5:22:23
xrun 完全指南:仿真、覆盖率与门级调试全掌握 简介这是一份面向硬件验证工程师、芯片设计师及半导体设计自动化学习者的 Cadence Xcelium(xrun) 数字仿真操作指南。文档从 Linux 环境下的安装配置检查切入系统讲解单步仿真、compile/elaborate/sim 多阶段分离流程、常用 option 及 xcelium.d 目录机制并深入覆盖 shm/db/fsdb 三类波形生成、覆盖率收集、Gate Level Simulation 延时反标与 timing check 关闭等高级功能针对复杂工程中的典型报错如 generate 命名不规范、license 不足等也给出了具体排查思路与解决选项。资源为单份 PDF 文档大小约 505KB内容浓缩而完整适合项目规划、日常仿真实施和故障排查时快速查阅。目前已有 2049 人学习下载是入门到进阶 Xcelium 工具链的实用参考资料。1. xrun 到底是什么一个命令解决不了的仿真问题这篇文章全讲透Cadence Xcelium 这个名字很多做数字验证的工程师张口就来但真要上手跑通一个工程靠的还是它底下那个叫xrun的命令。这篇笔记从 xrun 基础操作讲起一路到覆盖率收集、门级仿真和疑难 debug帮你把日常用得到的特性按命令行粒度串一遍。我拆这份资料时最直接的感受是xrun 看着是一堆 option 的堆砌其实背后有一条非常清晰的逻辑线——从单步仿真到分阶段仿真从波形生成到覆盖率、到 GLS 时序反标。你只要理解了这条线以后遇到陌生报错排查思路是有章可循的不是靠瞎试。记得我第一次用 xrun 的时候对着一份乱糟糟的工程脚本被*E,UNKNOWNSYM这类报错折腾到夜里。后来把-helpargs、xmhelp这些工具用起来才发现大部分问题在命令行阶段就能定位。这篇就把这些方法写透新手可以照着敲熟手可以直接跳到 debug 和进阶部分看参数边界。2. 跑通第一个仿真单步模式与三步分离的完整操作2.1 环境检查装没装、能不能用两句话定位先解决一个最基础的问题——xrun 到底在不在你的 Linux 环境里。$ which xrun // 打印 xrun 的路径确认可以直接被调用 $ xrun -version // 查看 xrun 的版本信息确认版本符合工程要求这两个命令是每次开工前我必跑的。which的作用不是告诉你装没装是告诉你shell 能不能找到它。很多时候环境变量PATH没配好xrun 装了你照样调不到。xrun -version更关键因为 Xcelium 不同版本对 SystemVerilog 特性和语法检查的严格程度不一样同一个工程换版本可能有完全不同的报错行为。从资源文档里可以看到 xrun 核心有三段xmvlog对应 compilexmelab对应 elaboratexmsim对应 sim。这三个名字后面 debug 时要记住因为xmhelp查错误就是按这三个工具名查的。2.2 单步仿真一条命令的省心与局限xrun 默认是单步仿真意思是它自己把 compile编译、elaborate细化、sim仿真三个阶段一次性跑完。$ xrun test.v // 一个命令仿真完成不用手动区分三个阶段单步仿真的优点是省事。写一个小模块、跑一个简单 testbench一条命令下去该出的波形、log 都有了。但它的局限也很明显你没法在 compile 之后、simulate 之前插入额外操作也没法只重跑仿真而跳过编译。工程一旦变大比如几千个文件、有 IP 有 memory model单步仿真的效率就很尴尬了改一行代码要全量重来。所以实际工程里我更推荐把阶段拆开这也是这份文档里最有价值的部分三个阶段对应三个命令但它们之间有联动关系不是完全独立的。2.3 三步分离compile、elaborate、sim 的联动机制$ xrun -compile test.v // 阶段一编译源码生成 library 写入 xcelium.d 目录 $ xrun -elaborate test.v // 阶段二细化设计生成 snapshot $ xrun -R // 阶段三加载 snapshot 并执行仿真注意文档里强调了一个细节如果 elaborate 之前没做 compile当前 elaborate 会自动执行 compile。也就是说-elaborate自带对 compile 的依赖检查。-R则会在当前目录自动检测 elaborate 生成的 snapshot找到就 load找不到会报错。这个联动机制在日常使用中很有用。比如你只改了 testbench 里的约束没动 RTL那重新 elaborate 就够不必重新 compile 所有设计文件。但 xrun 的默认重载机制会更激进——它检测到代码有任何修改会重新走完整的 compileelaborate。想强制跳过这个检测用-clean$ xrun -clean test.v // 忽略之前的编译结果强制全量重来-clean在两种场景下是救命的一是之前 compile 是在不同 option 组合下跑的snapshot 状态不可信二是改了-timescale、-access这类影响全局的 option旧结果不能复用。但反过来如果只是改了局部源码我一般不给-clean让 xrun 自己去做增量省时间。2.4 基础 option 速记每个参数的含义和适用边界文档列了一批最常用的 option我按实际使用频率整理成下面这张表Option作用备注-6464bit 模式大设计、内存吃紧时必开-sv支持 SystemVerilog 语言工程里有.sv文件就加上-access rwc设置访问权限读、写、执行需要 dump 波形、force 信号时必须有-timescale 1ns/1ps设置仿真时间精度单位/精度能细化不能粗化-f filename扫描文件列表大型工程用 f 文件管理源码列表-top module指定仿真顶层多顶层或自动检测失败时用-l filename指定 log 路径和名字不指定默认是xrun.log-errormax nerror 数达到 n 时仿真退出防止无效跑仿真浪费时间-parseinfo include打印 compile 阶段 include 信息排查 include 路径问题时用这里重点说两个容易踩坑的。-access rwc的rwc分别对应 read、write、execute如果你要在仿真中通过force改信号值或者用 UCLI 做交互操作r是远不够的得rwc全给。-timescale的单位可以比精度大但精度不能比单位大比如1ns/1ps合法1us/1ns也合法反过来写1ps/1ns就会报错。这是很经典的翻车点我看过不少人栽在这上面。2.5 查 option 的正确姿势1521 个选项别硬背xrun 文档里明确写了全部 option 有 1521 个但你常用的可能就二三十个。所以查帮助的本事比记背参数更值钱。$ xrun -helpargs option // 打印出指定 option 的作用和用法 $ xrun -helpall xrun_all_option.txt // 把全部 option 内容导出成文件 $ xmhelp tool error // 查错误类型与原因tool 填 xmvlog/xmelab/xmsim我发现-helpall导出的文件配合 grep 是效率最高的查找方式。比如你想找所有和 coverage 相关的选项直接grep -i coverage xrun_all_option.txt就出来了比自己翻 PDF 文档快得多。xmhelp这个命令很多老手都不用但它其实是被忽视的 debug 利器。看到 log 里*E开头的报错第一反应应该是xmhelp xmelab error code它会给出一段规范化的错误原因描述比在代码里瞎找效率高。比如*E,CUVIMG这类诡异错误不查说明你根本不知道问题出在 generate 块的命名规范上这个在第 5 章避坑部分我会重点展开。3. xcelium.d 目录与文件机制黑匣子里到底装了什么3.1 compile 产物与 snapshot文件的来龙去脉xrun 在compile阶段生成的是 library编译库在elaborate阶段生成的是 snapshot仿真快照这两个东西都放在xcelium.d目录下。很多人跑完仿真看到这个目录问能不能删答案是能删但不建议随便删因为它就是 xrun 的增量缓存删了下次全量重来。我一般的工作习惯是工程收尾归档时不带xcelium.d但日常迭代中留着它。文档里提到一个排查技巧就是当你怀疑 snapshot 状态不对时不要直接-clean先用工具检查 snapshot 的生成情况$ xmls -64 // 查看 64bit snapshot 的生成情况这里有个细节值得注意xmls默认查找的是 32bit snapshot如果你的仿真工具跑在 64bit 模式下必须加-64否则会出现明明生成过 snapshot 却查不到的诡异现象。我刚开始就被这事坑过一次后来记住多少位的仿真器就用多少位的 xmls 查这个口诀才没再犯。3.2 默认重载机制xrun 到底在检测什么文档里说得很清楚如果之前做过 compile 或 elaboratexrun 默认会检测代码是否有修改若无修改则直接重新载入旧结果。这个机制省时间但也有它的不透明之处——它检测的是文件时间戳和内容不是文件数量。有时候你往工程里加了一个新文件以为会被自动识别结果 xrun 根本不理会为什么因为它检测的对象是上一次命令中显式列出的文件集合新文件没进命令行它就没理由知道。所以我的习惯是文件列表变了直接用-clean或显式重新-compile不要赌 xrun 的自动检测。另外-clean这个选项的语义是忽略之前的全部结果它会清掉旧 snapshot 和 library在时序仿真、覆盖率合并等对编译选项敏感的步骤里我用-clean的频率明显更高。3.3 xrun 的增量编译边界什么能增量什么不能结合文档内容我总结出自己能接受的增量边界给新人做个参考可以增量只改 RTL 内部逻辑不改端口、不改参数化配置、不改模块例化关系。尽量别增量改 testbench 顶层结构、改define、改include 文件路径、换 timescale。必须全量换语言标准比如从 Verilog 换成 SystemVerilog、开/关覆盖率收集、切换 32/64bit、改 access 权限。这个边界不是官方规定而是我实际踩出来的经验。覆盖率收集这个点很微妙因为-coverage是在 elaborate 阶段植入 instrumentation 的如果你第一次没加-coverage跑了 elaborate第二次只是在命令里加了-coverage想重新跑xrun 可能因为代码没变而直接复用旧的编译结果导致覆盖率选项根本没生效。正确的做法是任何会影响仿真器内部行为的 option 变更都强制-clean不要依赖 xrun 的自动检测。4. 高级功能实操波形生成、覆盖率收集与门级仿真的完整参数链4.1 三种波形格式的取舍shm、db、fsdb 分别给谁用仿真不 dump 波形等于白跑但波形格式选错是很多新手的隐藏痛点。文档里明确列了三种格式shm 给 Cadence 自家 SimVision 用db 给 Indago 用fsdb 给 Verdi 用。$ xrun test.v -input wave.tcl // tcl 脚本定义波形 dump 行为和时长这里-input指定的是 tcl 脚本而脚本里会根据你需要调对应波形库的 task。我实际项目里最常用的是 fsdb因为验证环境里看波形的主力工具是 Verdi。但注意 fsdb 不是 xrun 内置支持的格式需要显式加载 debpli 插件$ xrun test.v -loadpli1 ${FSDB_INST_DIR}/.../boot/debpli.so:novas_pli_boot-loadpli1的作用是加载 PLI 库novas_pli_boot是 Verdi 提供的初始化函数名。省略这个选项的直接后果是仿真 log 里不会报错但 fsdb 文件就是生成不出来非常隐蔽。我第一次遇到这问题花了半小时排查最后发现是环境变量FSDB_INST_DIR没定义加载路径本身就是空的。4.2 覆盖率收集B/E/F/T/U/All 六个字母背后的含义收集覆盖率是验证收敛的依据xrun 支持按类型选择性收集$ xrun test.v -coverage B // 收集 branch coverage $ xrun test.v -coverage E // 收集 expression coverage $ xrun test.v -coverage F // 收集 FSM coverage $ xrun test.v -coverage T // 收集 toggle coverage $ xrun test.v -coverage U // 收集 conditional(expression) coverage $ xrun test.v -coverage All // 全部都要实际项目里我一般用-coverage All单次跑全量收集最后用imcIncisive Metrics Center做 merge 和分析。真正容易翻车的是-covoverwrite。这个 option 的作用是允许覆盖率数据被覆盖写入不加它时第二次跑仿真不会覆盖第一次的覆盖率数据而是累积合并。这在跑回归时是好事因为你要的是多轮累加不是单轮结果。但如果你刻意要对比两轮不同参数下的覆盖率差异就必须加-covoverwrite把上一轮清掉$ xrun test.v -coverage All -covoverwrite覆盖率收集的另一个边界是它也不能脱离 compile/elaborate 单独开启。我的血泪经验是开覆盖率时老老实实-clean全量重来省那几分钟编译时间换来的是覆盖率数据无效的排查成本不划算。4.3 门级仿真SDF 反标与时序检查的完整链路GLSGate Level Simulation是后端 netlist 验证的核心环节。文档从$sdf_annotate反标切入我把完整参数链整理如下$ xrun netlist.v testbench.v -notimingcheck -nospecify -sdf_verbose这里的参数语义要拆开讲-notimingcheck不做时序检查。它关掉的是$setup、$hold、$width这些时序检查原语让仿真在时序违例时不报 violation。-nospecify让 specify 块完全不起作用。这比-notimingcheck更粗暴连 specify 里的延时都不算。-sdf_verbose把 SDF 反标的具体信息打到 log 上。这个在排查为什么某个 cell 的延时没有反标进去时是必开项。我实际做 GLS 时还常配一个参数-sdf_verbose跑第一遍确认所有 instance 都反标到了确认无误再关掉跑正式回归因为 verbose 输出会拖慢仿真速度。如果一个 SDF 文件只反标了部分模块可以用-sdf_verbose看反标统计但更精细的控制要结合代码里的$sdf_annotate写区域限定。另外文档里给了-tfile来精细关闭特定模块的时序检查$ xrun netlist.v testbench.v -tfile tcheck.filetcheck.file 内容是这样组织的PATH test.dut.ff_i0 -tcheck // 关闭 ff_i0 的 timing check PATH test.dut_i $setup -tcheck // 只关闭 dut 的 setup timing check PATH test... -tcheck // 关闭 test 所有下属层次 timing check第一行是关闭ff_i0这个 instance 的全部时序检查第二行只看setup这类第三行的...是通配指test下所有层次的 timing check 全部关闭。实际使用时我建议尽量精确到 instance不要滥用...通配因为它会把关键路径的时序检查也关掉门级仿真就失去了一半意义。4.4 特殊扩展名与性能剖析参数几条少有人提但关键的选项文档里还埋了几个平时不太被人注意、但在特定场景非常顶用的选项$ xrun test.v11 -sysv_ext .v11 // 把 .v11 结尾的文件识别为 SystemVerilog $ xrun test.v -vlog_ext .v11 // 把 .v11 结尾的文件识别为 Verilog $ xrun test.v -profile // 生成 profile.out含各组件时间与内存消耗 $ xrun test.v -profoutput prof.txt // 指定 profile 输出文件不覆盖默认的 profile.out我在多版本混合项目里用过-sysv_ext这类扩展名选项。公司自研 IP 库里有旧的.v文件其实内容是 SV 语法不想为了适配去改文件后缀就用-sysv_ext .v暴力把.v全识别为 SV——这招好用但慎用因为它影响所有.v的解析方式如果有老工程混合了纯 Verilog会把语法检查标准提高一个档次导致旧代码报一堆无辜错误。-profile是我排查性能问题时的第一选择。当仿真跑得异常慢先开-profile看 profile.out 里的时间分布如果大部分时间花在 license check 上那是 license 服务器的问题如果花在 PLI 回调上那是你 testbench 的$monitor或者 force/release 太频繁。这个诊断思路远比盲目优化 RTL 代码效率高。5. 避坑与调试实战五条踩坑记录从 *E 报错到仿真死循环全解析5.1 隐式命名报错*E,CUVIMG的根因与 check 方法现象elaborate 阶段报*E,CUVIMG提示 implicit name 在 hierarchy 中出错代码里怎么看怎么觉得逻辑没问题。原因这个报错十有八九出在 generate 块上。Verilog-2001 规定 generate 块必须显式命名你没写名字或者名字写得不规范xrun 无法在 hierarchical path 中引用它就报隐式名字错误。实际工程里if generate嵌套在for generate内部、又没有给中间层命名的情况我也见到过。解决按标准写法给 generate 块补名字比如genvar i; generate for (i0; i8; ii1) begin : gen_blk ... end endgenerate。如果想放宽 xrun 对这类问题的语法检查可以在 compile 阶段加-genhier。但这个选项是放宽不是修复建议只是临时绕过最终还是要改代码补名字。5.2 license 报错NOLICN 的三种可能性排查现象仿真在 elaberate 通过后、开始 simulation 的瞬间log 里出现xmsim: *F,NOLICN: Unable to checkout license for the simulation. lic_error -18仿真直接退出。原因xrun 只在 simulation 阶段才检测 licensecompile 和 elaborate 阶段不检测。所以你这个报错不是编译出问题而是模拟阶段拿不到 license 授权。解决如果确认服务器上 license 剩余数量充足问题可能出在你没有某些 feature 的授权。用 Linux 命令看 license 安装信息$ lmstat -a -c $LM_LICENSE_FILE // 如果 LM_LICENSE_FILE 指向 license 文件 $ lmstat -a -c $CDS_LIC_FILE // 如果 CDS_LIC_FILE 指向 license 文件如果 license 不够用xrun 提供了排队等待机制$ xrun test.v -licqueue // 提交后进入 license 等待队列等到了再跑实际使用中-licqueue适合大量并行回归。注意排队时间不设上限regression 跑到凌晨job 就排队挂到凌晨。所以不是无脑加这个选项要评估队列深度。5.3 仿真挂死先看波形还是先看 profile顺序不能错现象仿真器进程还在但 log 长时间不增长看起来像是死循环。原因不一定是死循环。文档把这三种情况都列出来了我在实际项目中都遇到前两种解决第一步先打开波形窗口看波形时间轴是否在前进。时间轴在走仿真就没挂只是慢时间轴完全不动那才是真的堵住了。第二步如果时间轴不动加-gui -linedebug定位卡住的代码行这个组合会把当前执行位置实时反映在源码窗口上。第三步加-profile看 profile.out重点看 license check 时间如果它异常巨大说明仿真卡在等待 license 上不是死循环而是许可瓶颈。要是做的是 gate level 仿真还有一个非常容易被忽略的点零延迟门级震荡。门级网表的组合环如果没有延时就可能高频振荡仿真器陷进去出不来。加-gateloopwarn会打印具体震荡路径信息用这个定位到底是哪个 loop 在振再去查后端 netlist 是否插了必要的 delay cell。5.4 -loadpli1 大小写和路径顺序fsdb 生成的一个隐性隐患现象-input wave.tcl指定了 fsdb dump 脚本仿真正常跑完但目标目录下根本没有 fsdb 文件也不报错。原因-loadpli1的路径不对或者环境变量FSDB_INST_DIR没有定义xrun 静默忽略了加载后面 tcl 里调fsdbDumpfile时找不到对应 task但因为 tcl 脚本没做错误检查仿真照跑。解决严格按照文档样例写完整路径-loadpli1 ${FSDB_INST_DIR}/.../boot/debpli.so:novas_pli_boot并且用bash -c echo $FSDB_INST_DIR先确认变量存在。另外检查-loadpli1是否在 compile 阶段之前被参数解析器处理这个 option 必须出现在 xrun 命令行中不能直接写进 f 文件f 文件里加载有时序问题。5.5-timescale写反工具不报错但结果全歪的情况现象仿真不报任何错误但波形上的延迟时间完全对不上。比如预期的时钟是 10ns 周期波形量出来是 10ms。原因-timescale 1ps/1ns这种精度比单位大的写法不正确。单位规定了时间值的度量单位精度规定了时间值可以精确到的程度。精度不能比单位更粗实际使用时很多人写反了也不报错但所有延时都按错误换算输出结果整个仿真时间轴都失真。解决确认时间语义是单位比精度大或相等。1ns/1ps是标准推荐1us/1ns也稳妥。如果你要测亚稳态需要皮秒级精度就写1ns/1ps而不是反过来。另外多个文件混合时xrun 默认按最精细的精度做全局时间精度这可能拖慢整体仿真速度可以考虑在关键模块上缩小精度范围。6. 代码与参数技巧速查一个工程从编译到调试的完整命令行参考6.1 日常迭代的完整 xrun 命令模板实际项目里我常写的 xrun 命令比文档里的单命令要长不少通常是一个 f 文件加一堆全局 optionxrun -f rtl.f -f tb.f -sv -64 -access rwc \ -timescale 1ns/1ps -top tb_top \ -coverage All -covoverwrite \ -input wave.tcl -l run.log这份命令在一天内会反复用。注意-sv的使用场景是 f 文件列表里既有.v也有.sv加这个是让 .sv 文件按 SystemVerilog 标准解析如果没有.sv文件加了无害但也没必要。-top tb_top指定顶层避免多顶层模块的存在让 xrun 无法自动识别。-input wave.tcl走的是 tcl 脚本里面由fsdbDumpfile这类 task 控制波形文件生成不在命令行里直接指定格式便于仿真前改波形配置而不动 xrun 主体命令。6.2 性能排查两步走profile 优先linedebug 兜底遇到仿真速度慢到可疑的情况我有固定的排查路径$ xrun test.v -profile -profoutput prof_i0.txt打开 prof_i0.txt 看时间分布。重点看两类时间license check 时间如果占到总时长 10% 以上说明 license 在拖后腿和各个编译组件耗时。xrun 的 profile 输出里包含了检查 license 时间、各组件消耗仿真时间这些数据能帮你精确区分是 license 瓶颈、PLI 回调瓶颈还是 RTL 本身仿真慢。如果 profile 显示 license check 正常、组件消耗均衡但还是慢再用-gui -linedebug挂在仿真上看它停在哪一行判断是测试代码里的循环等待问题还是 RTL 本身的死循环逻辑。6.3 门级震荡与 SDF 反标的最后兜底门级仿真时如果出现时序异常反复、仿真停在某些门级路径上我最后会开这三个参数组合$ xrun netlist.v tb.v -sdf_verbose -gateloopwarn -notimingcheck-sdf_verbose打印所有 SDF 反标条目方便确认反标量-gateloopwarn把组合环位置提示出来避免仿真真死在里面-notimingcheck在初步验证功能阶段关掉时序约束让功能先对上。等前两步通过后再把-notimingcheck去掉跑正式时序验证。这套流程做完工程 speed 和正确性才都收住。现在我每次起新工程第一件事就是把 xrun 这份命令模板、tcl 脚本结构和 f 文件组织方式一起拷过来宁可在开头多花十分钟搭框架也绝不在跑完一轮回归后才回头补 option。也希望我的这份拆解对你上手机器有帮助。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询