一种易维护的UPF层次化低功耗设计流程
刘立杰kamelo@huawei.com
深圳海思半导体有限责任公司
摘要
随着芯片的逻辑规模越来越大,我们一般都会采用层次化的设计流程。从RTL划分好模块到综合出模块网表,直到PR实现这些 模块,最后才会合入到顶层修正时序。如果要在划分的模块中插入低功耗单元,就需要对该模块定义一个UPF文件。这样如果有 多个模块就需要对应多个UPF文件。本文介绍一个新流程,就是如何从一个顶层的UPF来得到下面模块的UPF。这样我们只需要 维护一个顶层UPF,模块UPF由工具写出并保证和顶层的一致性。该流程包括综合、插入低功耗单元、形式验证整个前端实现过 程,以及因为层次化低功耗设计而需要注意的UPF定义。
Abstract
As size of ASIC design grows larger and larger, hierarchical flow is usually a better choose for us. RTL design must be partitioned into some parts, block level synthesis and P&R should be done before top level timing fixing. Every design partition has its own individual UPF file in order to insert low power cells. So many UPF files should be prepared if there are many partitions. This paper describes a new flow, which automatically generates block level UPF files from the top level UPF file by Synopsys Design Compiler, so that only one top level UPF file should be maintained. All about synthesis, low power cells insertion, formal check and best practice of UPF definition will be fully discussed.
1. 简介
本文以一个实际项目作为例子,探讨一种可以简化低功耗设计流程的方法。我们相信通过该方法即使面对极为复杂的低功耗设计,其流程也能非常清晰,而且对于交付文件的维护也更简单。
2. 层次化设计流程
随着芯片规模的增大和设计复杂度的增加,层次化设计已经越来越普遍地被应用于工程实践中。从前端设计开始就必须划分好逻辑层次,合理地规划各个模块,对各个模块都要综合出独立的网表提交给后端。后端会对每个模块都分别进行布局布线。当各个子模块的物理设计都完成后才能在顶层做最后的时序收敛工作。这种层次化的设计流程相当于将一个大型的复杂问题分解为多个小问题来求解,从而允许前后端所有工程师并行地来完成任务,大大提高了工作效率和工作质量。所以这种设计方法是目前超大规模集成电路设计的不二选择。
2.1 基于UPF的低功耗设计流程
我们的项目基于Synopsys UPF的低功耗设计流程。根据项目实 际需求,我们第一步先从RTL综合出前端网表,第二步基于该网表完成DFT相关设计得到DFT网表,然后是第三步用Design Compiler读入DFT网表和UPF文件得到LP网表,该网表根据UPF文 件的描述插入了isolation cell和level shift cell等低功耗单元。最后基于LP网表可以完成后端的物理设计工作。该流程中插入低功耗 单元的工作是Design Compiler工具根据UPF文件的描述来自动完成的,所以UPF的正确性非常重要。由于我们有多个复杂子模块 需要重复上述步骤,并且其UPF文件也要作为低功耗仿真验证、MVRC(静态低功耗检查)、Formality等工作的输入。从而对于 该UPF文件在项目中各个工作小组间的同步及维护工作也提出了很大挑战。
2.2 层次化设计流程对UPF的维护
在层次化设计流程中会分阶段提交多个子模块的网表,如果这些网表都需要插入低功耗单元,通常就需要对应的多个UPF文件。 而这些UPF却只是全芯片UPF的一部分。于是我们还需要提供全芯片的UPF文件以包含所有信息。由于UPF文件的正确性对低功 耗设计的成功至关重要,当这些文件数目变多,而且还可能来源不同的时候如何维护这些UPF文件就成了一个棘手的问题。如果 UPF的描述出现错误,将可能很难发现。
结构清晰思路流畅的UPF文件可以极大的提高设计团队合作的流畅度,并且能最大限度保证项目进度。本文介绍一种新的流程, 我们只要创建和维护一个全芯片的UPF,保证它的正确性即可保证所有模块子UPF文件的正确性。各个子模块对应的UPF文件可 以通过Design Compiler工具自动生成,依靠Design Compiler工具本身来保证UPF的一致性。
3. 项目概况
要想将低功耗技术应用于设计项目中,首先我们需要明确我们的设计意图。该项目的逻辑层次如图1所示

图 1 – 芯片框图
其中CPU_SUBSYS、DSP_SUBSYS、PERI_SUBSYS三个模块会作为独立子模块被划分出来单独完成前端和后端设计。电压域的划分方式如下:

3.1 顶层UPF
基于这样的供电行为需求,通常我们需要 写4个UPF文件分别对应上面的三个模块和一个顶层。文件与文件之间的关系经常需要手工维护,非常繁琐。不过在此我们不再需要使用那样低效的方式,而是直接在顶层去描述所有模块的信息,写出如下的6个电压域:
create_power_domain xxx_top_domain -include_scope
create_power_domain CPU_SUBSYS -elements {U_XXX_CORE/U_CPU_SUBSYS} \
-scope { U_XXX_CORE/U_CPU_SUBSYS}
create_power_domain CPU1 -elements {U_XXX_CORE/U_CPU_SUBSYS/CPU1} \
-scope{ U_XXX_CORE/U_CPU_SUBSYS/CPU1}
create_power_domain CPU2 -elements {U_XXX_CORE/U_CPU_SUBSYS/CPU2} \
-scope { U_XXX_CORE/U_CPU_SUBSYS/CPU2}
create_power_domain DSP_SUBSYS -elements {U_XXX_CORE/U_DSP_SUBSYS} \
-scope { U_XXX_CORE/U_DSP_SUBSYS}
create_power_domain PERI_SUB -elements {U_XXX_CORE/U_PERI_SUBSYS}
这里需要注意的是“-scope”参数。该参数是使用DesignCompiler自动生成子模块UPF文件的关键所在。“-scope”所指的层次就是用户希望单独拿出来做前后端设计的逻辑层次。
定义了电压域后需要定义出该电压域中有哪些电源,并定义出该电压域的主电源是什么。这里需要注意的是每个电压域的电源要 定义完全,包括level shifter cell要用到的电源都要在该电压域中定义,否则会导致level shift cell插入不成功。
create_supply_port SYS_VDD –direction in –domain xxx_top_domain
create_supply_port DSP_VDD –direction in –domain xxx_top_domain
create_supply_port VSS –direction in –domain xxx_top_domain
create_supply_net SYS_VDD –domain xxx_top_domain
create_supply_net DSP_VDD –domain xxx_top_domain
create_supply_net VSS –domain xxx_top_domain
connect_supply_net SYS_VDD –port SYS_VDD
connect_supply_net DSP_VDD –port DSP_VDD
connect_supply_net VSS –port VSS
set_domai_supply_net xxx_top_domain -primary_power_net SYS_VDD \
-primary_ground_net VSS
定义清楚的每个电压域的电源就需要定义isolation的设置。它的设置有两个,一个是isolation cell的类型,另一个是isolation的控制信号。
set_isolation dsp_iso_0 -domain U_XXX_CORE/U_DSP_SUBSYS/DSP_SUBSYS \
-clamp_value 0 \
-applies_to ouput \
-isolation_power_net SYS_VDD \
-isolation_ground_net VSS
set_isolation_control dsp_iso_0 \
-domain U_XXX_CORE/U_DSP_SUBSYS/DSP_SUBSYS \
-isolation_signal U_XXX_CORE/U_DFTMUX_ISO_DSP/Z \
-isolation_sense high \
-location parent
最后就要定义电源的状态和各个电源状态组合。
add_port_state SYS_VDD –state {media_h 0.99}
add_port_state DSP_VDD –state {dsp_h 1.40} –state {dsp_l 0.80} –state {dsp_m 0.99} –state {dsp_off off}
add_port_state VSS –state {vss_on 0.00}
create_pst xxx_pst –supplies \
{SYS_VDD \
U_XXX_CORE/U_DSP_SUBSYS/DSP_VDD \
VSS}
add_pst_state ALL_ON –pst xxx_pst –state {media_h dsp_m vss_on}
add_pst_state DSP_L –pst xxx_pst –state {media_h dsp_l vss_on}
add_pst_state DSP_H –pst xxx_pst –state {media_h dsp_h vss_on}
add_pst_state DSP_OFF –pst xxx_pst –state {media_h dsp_off vss_on}
4. UPF实现流程
当我们准备好全芯片的UPF文件后就可以开始设计实现了。基于UPF的实现流程如图2所示。首先对RTL进行综合并完成DFT 相关电路得到综合网表。然后在Design Compiler工具中读入 UPF和先前综合好的网表进行insert low power cell的操作,生成新的低功耗网表。这时的该低功耗网表已经包含了我们需要 的isolation cell和level shifter cell。
上述过程我们通过formality和MVRC来保证功能的一致性和低功耗方案的正确实现。所以DesignCompiler在输出网表的同时 还输出一个新的UPF’来作为Formality check和MVRC check的输入。

图 2 – UPF实现流程图
整个流程我们对前面提到的CPU_SUBSYS、DSP_SUBSYS、PERI_SUBSYS和XXX_TOP都要分别实现一次才能完成全芯片的设 计。而对于每一个子模块都需要一个单独的UPF文件作为DesignCompiler的输入。下面会详述各个子模块UPF文件的生成过程。
4.1 UPF文件的生成

图 3 – UPF生成关系图
在我们的流程中低功耗设计人员仅需要维护一个全芯片的UPF文件xxx_top.upf。所有子模块的UPF文件都是DesignCompiler自动生成的。大家应该比较熟悉在DesignCompiler中做timing budget的时候需要让工具将Timing Constraints从顶层传递到下面的子 模块,然后就可以写出子模块的SDC文件。其实UPF也是一种constraint,我们同样可以让Design Compiler工具把顶层的UPF约束传递下去,然后再到子模块把它写出来。基于这样的思路我们的脚本如下:
set top_design XXX_top
source –e –v ../scr/xxx_lib_setup.tcl
source –e –v ../scr/xxx_dc_setup.tcl
read_verilog –netlist /nas/fe/netlist100/CPU_SUBSYS.v
read_verilog –netlist /nas/fe/netlist100/DSP_SUBSYS.v
read_verilog –netlist /nas/fe/netlist100/PERI_SUBSYS.v
read_verilog –netlist /nas/fe/netlist95/XXX_TOP.v
source –v –e /upf/xxx_top.upf set_voltage 0.99 –obj CPU_VDD
set_voltage 0.99 –obj U_XXX_CORE/U_CPU_SUBSYS/u_cpu2/CPU2_SW_VDD
set_voltage 0.99 –obj U_XXX_CORE/U_CPU_SUBSYS/u_cpu3/CPU3_SW_VDD
set_voltage 0.99 –obj U_XXX_CORE/U_DSP_SUBSYS/DSP_VDD
set_voltage 0.99 –obj PERI_VDD
set_voltage 0.99 –obj SYS_VDD
set_voltage 0.0 –obj VSS
set_operating_conditions WCCOM
check_mv_design
characterize U_XXX_CORE/U_CPU_SUBSYS
characterize U_XXX_CORE/U_DSP_SUBSYS
current_design CPU_SUBSYS
save_upf cpu_subsys.upf
current_design DSP_SUBSYS
save_upf dsp_subsys.upf
这样我们就能轻松地得到cpu_subsys.upf和dsp_subsys.upf。如下既为工具自动生成的dsp_subsys.upf
#Generated by Design Compiler (E-2010.12) on Mon May 16 20:17:25 2011
create_power_domain xxx_top_domain –include_scope
create_power_domain DSP –elements U_DSP_SUBSYS
create_supply_net SYS_VDD –domain DSP
create_supply_net SYS_VDD –domain xxx_top_domain –reuse
create_supply_net DSP_VDD –domain DSP
create_supply_net DSP_VDD –domain xxx_top_dmoain –reuse
create_supply_net VSS –domain DSP
create_supply_net VSS –domain xxx_top_domain –reuse
create_supply_net CPU_VDD –domain xxx_top_domain
create_supply_net PERI_VDD –domain xxx_top_domain
set_domain_supply_net xxx_top_domain –primary_power_net SYS_VDD –primary_ground_net VSS
set_domain_supply_net DSP –primary_power_net DSP_VDD –primary_ground_net VSS
create_supply_port SYS_VDD –domain DSP –direction in
create_supply_port DSP_VDD –domain DSP –direction in
create_supply_port VSS –domain DSP –direction in
create_supply_port CPU_VDD –domain xxx_top_domain –direction in
create_supply_port PERI_VDD –domain xxx_top_domain –direction in
connect_supply_net SYS_VDD –ports SYS_VDD
connect_supply_net DSP_VDD –ports DSP_VDD
connect_supply_net VSS –ports VSS
connect_supply_net CPU_VDD –ports CPU_VDD
connect_supply_net PERI_VDD –ports PERI_VDD
add_port_state SYS_VDD –state {media_h 1.10000}
add_port_state DSP_VDD –state {dsp_h 1.40000}
add_port_state DSP_VDD –state {dsp_l 0.80000}
add_port_state DSP_VDD –state {dsp_off off}
add_port_state VSS –state {vss_on 0.00000}
add_port_state CPU_VDD –state {cpu_h 1.40000}
add_port_state CPU_VDD –state {cpu_l 0.80000}
add_port_state CPU_VDD –state {cpu_off off}
add_port_state PERI_VDD –state {peri_h 1.10000}
add_port_state PERI_VDD –state {peri_off off}
create_pst pst –supplies [list CPU_VDD DSP_VDD PERI_VDD SYS_VDD VSS]
add_pst_state pst_ps_1 –pst pst –state {cpu_h dsp_h peri_h media_h vss_on}
add_pst_state pst_ps_2 –pst pst –state {cpu_h dsp_l peri_h media_h vss_on}
add_pst_state pst_ps_3 –pst pst –state {cpu_h dsp_off peri_h media_h vss_on}
add_pst_state pst_ps_4 –pst pst –state {cpu_l dsp_h peri_h media_h vss_on}
add_pst_state pst_ps_5 –pst pst –state {cpu_l dsp_l peri_h media_h vss_on}
add_pst_state pst_ps_6 –pst pst –state {cpu_off dsp_off peri_h media_h vss_on}
add_pst_state pst_ps_7 –pst pst –state {cpu_off dsp_off peri_off media_h vss_on}
set_isolation dsp_iso_out_0 –domain DSP –isolation_power_net SYS_VDD –isolation_ground_net VSS
set_isolation_control dsp_iso_out_0 –domain DSP –isolation_signal charz_pin –isolation_sense high
4.2 低功耗单元插入
准备好各个子模块的UPF文件后,我们可以对需要独立交付的子模块网表进行低功耗单元的插入。插入的脚本如下:
set top_design DSP_SUBSYS
source –e –v ../scr/xxx_lib_setup.tcl
source –e –v ../scr/xxx_dc_setup.tcl
read_verilog –netlist dsp_subsys.v
link
set_dont_use [get_lib_cells */LVLHL*]
source –e –v /upf/dsp_subsys.upf
set_voltage 0.99 –obj CPU_VDD
set_voltage 0.99 –obj DSP_VDD
set_voltage 0.99 –obj PERI_VDD
set_voltage 0.99 –obj SYS_VDD
set_voltage 0.0 –obj VSS
set_operating_conditions WCCOM
check_mv_design –v
insert_mv_cells –all –verbose
check_mv_design –v
write –format verilog –hier ./dsp_subsys_upf.v
save_upf dsp_subsys_upf.upf
对这个脚本我们需要注意如下几点:
• 因为我们只在低电压到到电压的方向插入level shift cell,我 们使用的方法是用set_dont_use把高电压到低电压的LVLHL* cell禁用掉。
• 在我们的流程中为了避免在这个阶段对网表进行过多改动, 不能使用compile_ultra命令来插入低功耗单元,必须使用 insert_mv_cells命令,-all表示isolation cell和level shift cell 都需要插入,工具会根据UPF的定义先插入isolation cell,再 插入level shift cell。
• 当某些信号既需要isolation cell又需要level shift cell时工具自 动会在library中找一个带isolation功能的level shift cell,我们 称为ELS(enable level shift)cell。
• check_mv_design命令非常重要,它会报告出很多有用信 息,可以帮助定位插入低功耗单元时遇到的问题。
5. Formality检查
插入低功耗单元前后我们要做形式验证以保证逻辑功能的一致 性。低功耗形式验证与普通形式验证在使用上的唯一不同在于需要读入UPF文件。这样Formality工具就会根据UPF的定义虚拟电压域,并且模拟电源关断行为。相应的脚本我们可以从 Synopsys Solvnet上的Reference Methodology栏中下载到。
读入了UPF文件后,在图4 的Formality环境中可以看到,所有 的cell都带电源信息。从而完成与电源行为相关的验证工作。

图 4 – Formality GUI
6. 经验总结
第一次走这样的流程,所以时常会遇到问题,这里介绍一些经验分享给大家。
1. 在定义全芯片的UPF时,对于要单独写出相应UPF的电压 域,在用create_power_domain时要加上-scope选项,否则可能无法写出相应的UPF。
2. 在全芯片的UPF中我们定义isolation control信号可能是某个寄存器的Q端,但子模块的UPF中Design Compiler工具会用模块端口charz_pin来作为该isolation control信号。这时我们可能需要修改一下子模块的UPF,让它指向正确的端口 isolation control信号。
3. 在作formality时,ref这边的UPF,要把第一行#Generated By Design Compiler删除,否则formality工具不会在ref这边虚拟isolation cell,从而造成比对失败。
7. 结论及建议
对于用UPF来实现层次化低功耗设计采用本文介绍的流程会 很容易维护和管理多个UPF。每个UPF都和顶层的UPF保持一致,从而保证每个模块的低功耗设计实现都遵循设计者意图 不变。这里需要强调的是我们一定要保证顶层UPF的描述正确性,并按照本文介绍的方法产生子模块的UPF,就会得到正确 的低功耗设计。
8. 致谢
感谢synopsys的工程师葛颖峰,他耐心解答我们的每一个问题,给我们的项目很大的支持和帮助。感谢和我并肩作战的同事李祥鹏、姚琮、宋隽,这是我们共同努力的结果。
9. 参考文献
[1] Design Compiler User Guide



