第四章:统一功耗格式(UPF)详解
各位同学,今天我们来聊聊UPF。说实话,UPF这东西刚出来的时候,我还挺抵触的——又得学一套新语法。但做了几个低功耗项目之后,我彻底服气了。没有UPF,你根本没法系统性地管理芯片的功耗意图。
UPF全称是Unified Power Format,统一功耗格式。它最早由Synopsys和ARM等公司推动,现在已经是IEEE 1801标准了。目前主流用的是UPF 2.0和UPF 3.0。我个人习惯用UPF 2.1,兼容性最好,工具支持也最成熟。
4.1 UPF 2.0 vs UPF 3.0:到底差在哪?
先说说这两个版本的区别。UPF 2.0是2013年左右的版本,它把电源域、电平转换器、隔离单元这些基础概念都定义清楚了。UPF 3.0呢,主要增加了对复杂电源状态机的支持,比如多电压域的动态电压频率调整(DVFS)。
我举个例子你就明白了:
- UPF 2.0:适合做静态的低功耗设计,比如always-on域和关断域
- UPF 3.0:适合做动态的功耗管理,比如CPU核在不同负载下切换电压
嗯,这里要注意:如果你的芯片只用到了电源关断和简单的电压切换,UPF 2.0完全够用。别为了追新而用3.0,工具支持反而可能出问题。
4.2 电源域定义:create_power_domain
电源域是UPF的核心概念。说白了,就是把芯片上需要独立供电的区域圈出来。语法很简单:
create_power_domain PD_CPU \
-elements {u_cpu_top} \
-supply {primary VDD_CPU} \
-supply {secondary VDD_MEM}
这里我解释一下几个关键参数:
- -elements:指定这个域包含哪些模块。可以是实例名,也可以是层次路径
- -supply:定义这个域用什么电源。primary是主电源,secondary是备用电源
4.3 电源状态表:add_port_state 与 create_pst
电源状态表,说白了就是告诉工具:我的芯片在什么状态下,各个电源域应该是什么电压。先看端口状态定义:
add_port_state VDD_CPU -state {ON 1.0} -state {OFF 0.0}
add_port_state VDD_GPU -state {ON 0.9} -state {OFF 0.0}
add_port_state VDD_MEM -state {ON 1.2} -state {RET 0.6}
然后创建电源状态表:
create_pst chip_pst -supplies {VDD_CPU VDD_GPU VDD_MEM}
add_pst_state sleep -pst chip_pst -state {OFF OFF RET}
add_pst_state active -pst chip_pst -state {ON ON ON}
add_pst_state gpu_only -pst chip_pst -state {OFF ON RET}
你看,这样定义之后,工具就能理解:
- 在sleep模式下,CPU和GPU都关断,内存保持
- 在active模式下,所有域都正常工作
- 在gpu_only模式下,只有GPU工作,CPU关断,内存保持
4.4 电平转换器:跨电压域的桥梁
当两个电源域电压不同时,信号从一个域传到另一个域,就需要电平转换器。UPF里用set_level_shifter来指定:
set_level_shifter LS_CPU2GPU \
-domain PD_CPU \
-source PD_CPU \
-sink PD_GPU \
-applies_to outputs \
-rule low_to_high \
-location self
这里几个参数要注意:
- -source和-sink:指定源域和目标域
- -applies_to:可以选outputs、inputs或both。我一般选outputs,在源域输出端做转换
- -rule:low_to_high表示从低压到高压,high_to_low反之
- -location:self表示放在源域内,parent表示放在父域
4.5 隔离单元:关断域的守门员
当一个域关断时,它的输出信号会变成未知态(X)。如果不做隔离,这些X会传播到其他域,导致功能错误。隔离单元就是干这个的:
set_isolation ISO_CPU2GPU \
-domain PD_CPU \
-source PD_CPU \
-sink PD_GPU \
-applies_to outputs \
-clamp_value 0 \
-isolation_supply VDD_GPU
关键参数:
- -clamp_value:隔离时输出钳位到0还是1。我一般选0,因为低功耗设计里0更省电
- -isolation_supply:隔离单元用什么电源供电。注意,隔离单元必须用目标域的电源,否则它自己也会关断
4.6 实战中的UPF设计流程
好了,理论讲完了,我给大家梳理一下实际项目中的UPF设计流程:
- 第一步:划分电源域。根据芯片架构,把需要独立供电的模块圈出来。比如CPU、GPU、内存控制器、外设等
- 第二步:定义电源端口。用create_supply_port和create_supply_net定义每个域的电源网络
- 第三步:创建电源状态表。用add_port_state和create_pst定义所有可能的电源模式
- 第四步:添加电平转换器和隔离单元。用set_level_shifter和set_isolation处理跨域信号
- 第五步:验证。用Synopsys的VC LP工具跑一遍UPF检查,确保没有遗漏
嗯,这里我要强调一下:UPF不是写一遍就完事的。随着设计迭代,UPF也要不断更新。我建议你把UPF和RTL代码一起做版本管理,每次修改都要做回归验证。
4.7 小结
今天的内容就到这里。UPF这东西,刚开始学觉得语法多、规则复杂,但用熟了之后你会发现,它其实是低功耗设计里最值得花时间学的东西。没有UPF,你根本没法系统性地管理芯片的功耗意图。
下一章我们会讲综合阶段的低功耗优化,到时候会用到今天学的UPF知识。建议大家先把UPF的语法练熟,尤其是电源状态表和隔离单元的配置,这是最容易出错的地方。
好,今天就到这里。有问题随时找我。