3. 低功耗设计意图与UPF标准
低功耗综合与实现的核心难点,并不在于“把某个开关关掉”,而在于如何把设计者的低功耗意图,用一套可被工具一致理解、可被仿真验证、可被实现工具执行的描述语言固定下来。UPF(Unified Power Format,IEEE 1801)正是承担这一职责的标准。它不描述电路功能,而是描述电源结构:哪些逻辑属于哪个电源域、域在什么条件下上电或断电、断电时哪些信号需要隔离、跨域信号是否需要电平转换、断电期间哪些寄存器状态必须保留。理解 UPF,本质上是理解“电源意图如何映射到物理实现”。
UPF 的语法骨架:命令、对象与作用域
UPF 以 Tcl 命令集的形式存在,通常写在独立的 .upf 文件中,在综合或实现流程中按顺序加载。它的语法结构可以概括为三层:创建对象(如 create_power_domain、create_supply_port)、建立连接(如 connect_supply_net、set_domain_supply_net)、施加约束(如 set_isolation、set_level_shifter、set_retention)。命令之间存在明显的先后依赖:电源域必须先创建,才能在其中定义电源端口和开关;隔离与保持策略必须绑定到已存在的域或电源网络,否则工具会报“对象未定义”。
UPF 的作用域由 -domain、-elements、-applies_to 等选项控制。一个常见误区是:把 set_isolation 写在顶层却未指定作用域,导致策略被施加到全部跨域路径,既浪费面积又可能引入时序问题。正确做法是明确“哪条边界、哪个方向、哪些信号”。
电源域:低功耗意图的第一层划分
电源域(Power Domain)是一组共享同一供电策略的实例、端口和网络的集合。划分电源域的依据通常是“是否需要独立关断”。例如一个 SoC 可划分为 Always-On 域(AON,常开)、CPU 域(可 DVFS)、GPU 域(可断电)、外设域(可断电但需保持唤醒逻辑)。在 UPF 中,电源域通过 create_power_domain PD_CPU -elements {u_cpu} 建立,随后用 create_supply_port 和 create_supply_net 定义该域的供电端口与网络,再用 connect_supply_net 把网络接到端口上。
电源域划分不是越细越好。域越多,隔离、电平转换、保持寄存器的数量就越多,面积和验证复杂度随之上升。工程上通常以“关断粒度”和“唤醒延迟”为权衡依据:关断收益大、唤醒可接受的模块才单独成域。
电源开关、隔离、电平转换与保持寄存器
电源开关(Power Switch)负责在物理上接通或切断某个域的供电。UPF 中用 create_power_switch 描述开关的控制信号、输入输出电源网络以及开关类型(如 header switch 位于电源与域之间,footer switch 位于域与地之间)。开关的控制信号本身必须来自常开域,否则域关断后开关将无法被重新打开,这是典型的“自锁死”错误。
隔离(Isolation)解决的是“断电域输出悬空”问题。当一个域断电后,其输出信号可能漂移到中间电平,污染下游常开逻辑。UPF 用 set_isolation 指定隔离单元的位置(-location self 或 -location parent)、隔离值(-clamp_value 0 或 1)以及隔离使能信号(-isolation_signal)。隔离使能必须在域断电前有效、上电后失效,通常由常开域中的电源管理控制器产生。
电平转换(Level Shifter)处理的是“不同电压域之间信号摆幅不匹配”。例如 1.2V 域驱动 1.8V 域时,需要升压转换;反之需要降压转换。UPF 用 set_level_shifter 指定方向(-applies_to inputs/outputs/both)、位置和规则(如 -rule low_to_high)。电平转换与隔离是两类不同问题:隔离针对断电,电平转换针对电压差,二者可能同时需要。
保持寄存器(Retention Register)用于在域断电期间保存关键状态。普通寄存器断电即丢失,保持寄存器内部含一个由常开电源供电的“影子”存储单元,断电前把主寄存器值复制到影子单元,上电后再恢复。UPF 用 set_retention 指定保持电源网络、保存/恢复控制信号以及需要保持的寄存器列表。保持策略的代价是面积和漏电,因此只对“必须记住”的状态使用,如配置寄存器、状态机当前状态。
一个可执行的 UPF 片段示例
下面给出一个简化但结构完整的 UPF 片段,用于描述“CPU 域可断电、输出需隔离、跨到 AON 域需升压、关键寄存器需保持”的场景。参数为教学示例,非实测数据。
# 1. 创建电源域
create_power_domain PD_AON -elements {u_aon}
create_power_domain PD_CPU -elements {u_cpu}
# 2. 定义供电端口与网络
create_supply_port VDD_AON -domain PD_AON
create_supply_port VDD_CPU -domain PD_CPU
create_supply_net VDD_AON_NET -domain PD_AON
create_supply_net VDD_CPU_NET -domain PD_CPU
connect_supply_net VDD_AON_NET -ports {VDD_AON}
connect_supply_net VDD_CPU_NET -ports {VDD_CPU}
# 3. 电源开关:控制信号来自 AON
create_power_switch SW_CPU \
-domain PD_CPU \
-input_supply_port {vin VDD_AON_NET} \
-output_supply_port {vout VDD_CPU_NET} \
-control_port {sleep_ctrl u_aon/pwr_ctrl} \
-on_state {on vin {!sleep_ctrl}}
# 4. 隔离:CPU 输出到 AON,断电时钳位 0
set_isolation ISO_CPU_OUT \
-domain PD_CPU \
-isolation_power_net VDD_AON_NET \
-isolation_ground_net VSS \
-clamp_value 0 \
-applies_to outputs \
-isolation_signal u_aon/iso_en
# 5. 电平转换:CPU(1.2V) 到 AON(1.8V)
set_level_shifter LS_CPU_TO_AON \
-domain PD_CPU \
-applies_to outputs \
-rule low_to_high \
-location parent
# 6. 保持寄存器
set_retention RET_CPU \
-domain PD_CPU \
-retention_power_net VDD_AON_NET \
-save_signal u_aon/save_en \
-restore_signal u_aon/restore_en \
-elements {u_cpu/reg_state[*]}
加载这段 UPF 后,综合工具会在跨域边界自动插入隔离单元、电平转换器和保持寄存器,并在网表中保留相应的电源连接信息。验证时可通过 UPF 感知仿真检查:当 sleep_ctrl 拉高、CPU 域断电后,CPU 输出是否被钳位到 0,AON 域是否未收到悬空信号;上电后 restore_en 是否把保持寄存器的值恢复。若仿真中出现 X 态传播到 AON 域,通常说明隔离策略未覆盖该路径或隔离使能时序不正确。
从意图到实现:UPF 在流程中的位置
UPF 不是一次性写完就固定的文件。在 RTL 阶段,它用于驱动低功耗仿真和综合;在实现阶段,它指导电源规划、开关插入和物理验证;在签核阶段,它配合 UPF 感知的静态检查工具确认没有遗漏的跨域路径。一个常见的工程实践是:先写“最小可用 UPF”覆盖主要电源域和开关,再随设计迭代逐步补充隔离、电平转换和保持策略,每补充一类策略就运行一次 UPF 感知检查,避免问题堆积到后期。
理解 UPF 的关键,是把它看作一份“电源契约”:它规定了每个域在每种电源状态下的行为边界。只有契约清晰、完整、无歧义,后续的综合、布局布线和验证才能在同一套语义下协同工作。