3. Xcelium低功耗仿真环境搭建
低功耗仿真的环境搭建,本质上不是“把UPF文件丢给仿真器”这么简单。Xcelium对UPF的支持依赖一条完整的编译—精化—运行链路:UPF文件必须在正确的阶段被解析并与RTL设计绑定,仿真选项必须让电源意图生效,电源状态必须在时间零点前完成初始化,日志与覆盖率必须被显式收集。任何一环缺失,都会表现为“仿真能跑但电源行为不对”或“覆盖率收集不到电源域信息”这类隐性故障。本节按工程化流程展开,重点说明每一步的实际输入、关键配置和结果判读依据。
一、UPF编译:从文件到电源意图绑定
Xcelium处理UPF有两种典型方式:一是通过-upf选项在精化阶段加载,二是通过load_upf命令在仿真运行时加载。工程化流程推荐前者,因为电源域、电源开关、隔离单元等结构需要在精化阶段就与RTL实例绑定,否则后续电源状态控制会找不到对应对象。
假设设计顶层为soc_top,UPF文件为soc_top.upf,典型编译命令如下:
xrun -upf soc_top.upf \
-top soc_top \
-f rtl.f \
-elaborate \
-access +rwc \
-l compile.log
这里-upf指定UPF文件,-top指定顶层模块,-elaborate让工具完成精化。编译完成后,应在compile.log中确认UPF被成功解析,关键判据是出现类似UPF file 'soc_top.upf' loaded successfully以及电源域数量、电源开关数量的统计信息。如果UPF中引用的实例路径在RTL中不存在,日志会报UPF-xxx: instance not found,此时必须先修正UPF中的层次路径,而不是继续往下跑。
set_scope明确作用域,避免因顶层名变化导致绑定失败。二、仿真选项配置:让电源意图真正生效
编译通过只代表UPF被解析,不代表电源行为会在仿真中体现。Xcelium需要一组运行时选项来激活低功耗语义。常用组合如下:
-upf_version 2.1 \
-power_domain_debug \
-upf_log upf_runtime.log \
-coverage all \
-covfile cov.db
其中-upf_version要与UPF文件声明的版本一致,版本不匹配会导致部分命令被忽略;-power_domain_debug会输出电源域状态切换的详细日志,是排查电源行为异常的第一手材料;-upf_log单独记录UPF运行时事件,便于与主日志分离分析。覆盖率相关选项在下一节展开。
需要特别注意的是,如果设计中使用了电源开关(power switch)和隔离单元(isolation cell),必须确认仿真选项允许这些单元的语义被建模。若日志中出现UPF-xxx: power switch not modeled,说明开关行为未被激活,此时电源域虽然存在,但关断后输出不会进入隔离态,仿真结果会与预期不符。
三、电源状态初始化:时间零点前的关键动作
电源状态初始化是低功耗仿真中最容易被忽略的一步。默认情况下,所有电源域在仿真开始时处于UPF中定义的初始状态,但工程中往往需要显式控制:比如让某个域先上电、某个域保持关断、或在时间零点施加特定的电源序列。
Xcelium提供add_power_state和set_power_state等命令。典型做法是在testbench的initial块中,在复位释放前完成电源状态设置:
initial begin
// 时间零点:CPU域先上电,GPU域保持关断
set_power_state -domain cpu_domain -state ON;
set_power_state -domain gpu_domain -state OFF;
#100;
// 释放复位,开始正常仿真
rst_n = 1'b1;
end
这里的关键判据是:在upf_runtime.log中应看到Power state of domain cpu_domain changed to ON以及gpu_domain changed to OFF的记录,且时间戳早于复位释放时刻。如果电源状态切换发生在复位释放之后,可能导致复位期间电源域行为不确定,仿真结果不可信。
四、日志与覆盖率收集:让结果可追溯、可度量
低功耗仿真的日志不是“跑完看一眼”的附属品,而是判断电源行为是否正确的核心依据。建议至少收集三类日志:编译日志compile.log、UPF运行时日志upf_runtime.log、主仿真日志sim.log。其中upf_runtime.log应重点检查以下事件:电源域状态切换、电源开关控制信号变化、隔离单元使能/禁用、保持单元(retention cell)的保存与恢复。
覆盖率方面,Xcelium支持将低功耗相关覆盖与功能覆盖合并收集。典型命令是在仿真选项中添加-coverage all和-covfile cov.db,仿真结束后用imc或xcr打开cov.db查看。需要确认覆盖率报告中包含电源域状态覆盖、隔离控制覆盖、电源开关覆盖等条目。如果这些条目缺失,通常是因为UPF未被正确加载或-power_domain_debug未开启。
cov.db在多次仿真之间会累积。如果希望每次仿真独立统计,应在运行前删除旧数据库或使用-covfile指定新文件名,避免旧数据污染当前结果。五、工程化检查清单
将上述流程固化为可复用的检查清单,可以显著降低环境搭建的返工率。以下清单按执行顺序排列,每项均给出可观察的判据:
| 阶段 | 关键动作 | 判据 |
|---|---|---|
| UPF编译 | xrun -upf ... -elaborate |
compile.log中出现UPF loaded successfully,无instance not found |
| 仿真选项 | 配置-upf_version、-power_domain_debug |
日志中无power switch not modeled警告 |
| 电源状态初始化 | 在复位释放前调用set_power_state |
upf_runtime.log中状态切换时间戳早于复位释放 |
| 日志收集 | 分离compile.log、upf_runtime.log、sim.log | 三类日志均存在且无UPF错误码 |
| 覆盖率收集 | 添加-coverage all -covfile cov.db |
覆盖率报告中包含电源域/隔离/开关条目 |
需要强调的是,低功耗仿真环境搭建的难点不在单个命令的书写,而在于各阶段之间的依赖关系:UPF编译失败会导致后续所有电源行为失效;仿真选项缺失会让电源意图“静默失效”;电源状态初始化时机错误会让复位期间的行为不可信;日志与覆盖率收集不完整则无法定位问题和度量验证进度。因此,建议在项目初期就将上述流程脚本化,每次仿真前自动检查关键判据,而不是依赖人工逐条核对。
实际工程中,一个常见的返工场景是:仿真能跑通、波形看起来也正常,但覆盖率报告中完全没有电源域相关条目。排查顺序应是:先确认compile.log中UPF是否加载成功,再确认-power_domain_debug是否开启,最后检查cov.db是否被旧数据覆盖。按这个顺序排查,通常能在几分钟内定位到根因,而不是盲目重跑仿真。