做低功耗项目做到想拍桌子的时候,大多数时候问题都出在时钟网络。芯片面积里触发器占掉三到四成,时钟树再把这些触发器的时钟端全部串起来,功耗、时序、拥塞全搅在一起。Multi-bit FF(MBFF)就是把多个单bit触发器打包成一个cell,共享内部时钟缓冲,从根上减少时钟端电容和时钟树的分叉数量。DCT/DCG作为综合阶段就能做物理优化的工具,对MBFF的支持已经非常成熟,但真要把它用好,并且和SPG(列式电源开关管)流程一起跑通,有不少细节属于面试不问、文档不写、项目里踩坑才能学到的内容。
这篇文章主要围绕DCT/DCG里做Multi-bit FF物理优化的完整流程来写:从库准备、参数配置、compile阶段的行为,到和后端SPG流程衔接时需要注意的物理约束、IR drop影响和ECO风险。同时把我在实际项目里遇到过的几个典型问题和排查方法整理出来。适合正在做7nm、12nm、28nm低功耗芯片(尤其是MCU、IoT SoC和AI加速器)后端实现,或者在前端综合阶段就想把功耗压下去的工程师参考。文章重点不是罗列命令,而是解释每个步骤“为什么这么做”,以及不这么做会出什么问题。
1. 从功耗账本说起:Multi-bit FF优化到底省在哪里
1.1 一个容易忽略的功耗大头
芯片动态功耗由三部分构成:寄存器本身的开关功耗、组合逻辑的开关功耗,以及时钟网络的翻转功耗。寄存器本身的开关功耗只和数据翻转率有关,很难通过物理手段改变。组合逻辑功耗依赖于逻辑综合的质量。真正被低估的是时钟网络——时钟树上的缓冲器数量巨大,而且时钟每周期都在翻转,翻转率接近100%,这导致时钟网络的功耗往往能占到芯片总动态功耗的30%到50%。
MBFF解决的就是这个大头。以一个4bit的触发器组为例:如果使用4个单bit FF,每个FF内部都有自己独立的时钟反相器链,时钟端总电容是4份。合并成一个4bit MBFF之后,内部共享时钟缓冲,时钟端电容可以降到单bit FF的1.5倍到2倍左右。也就是说,时钟网络看到的负载直接减少了50%以上。时钟树上的buffer数量也随之减少,因为每个MBFF的物理尺寸比4个单bit FF更紧凑,摆放位置更集中,时钟树绕线的距离也更短。功耗收益是叠加的。
1.2 MBFF的面积与布局收益
从面积角度看,MBFF的优势同样成立。单bit FF的标准单元高度固定,宽度通常在0.6微米到1.2微米之间(取决于工艺和驱动强度)。如果把4个单bit FF放在一起,它们之间会有边界间距,单元内部的阱连接、电源轨连接也是各自独立的。MBFF通过共享阱区和电源连接,把cell内部的公共结构合并,整体宽度可以减少15%到25%。在同样的floorplan面积里,用MBFF意味着能塞下更多的逻辑,或者可以缩小芯片面积。
对布局后端来说,MBFF还有一个隐藏好处:减少了需要摆放和布线的instance数量。一个100万触发器的设计,如果MBFF优化覆盖率做到70%,instance数量大约减少20万个。Placement runtime、时钟树综合的sink数量、布线时的pin density都有明显改善。在拥塞比较严重的模块里,这个效果比手动调整floorplan更直接。
1.3 什么时候不值得用MBFF
不是所有设计都适合MBFF。有几个场景需要慎重:
- 每个bit的时钟门控独立。如果4个FF分别由4个不同的clock gate控制,它们无法合并成一个MBFF(不同时钟域或不同门控信号)。
- DFT扫描链结构复杂。某些MBFF的scan chain连接方式受限,如果设计里大量使用锁定或重定时扫描单元,需要先检查库是否支持对应类型的MBFF。
- 高扇出复位信号。MBFF合并后,内部多个bit共享复位端,如果复位信号本身就有很高的扇出,合并后局部congestion可能加重。
所以,MBFF优化不是无脑开启就能躺赢。工程上要先理解设计的数据流结构,再决定优化的激进程度。
2. DCT/DCG实操前置:库准备与数据流检查
2.1 确认库里的MBFF单元到底有没有
很多项目在DCG里跑完compile才发现MBFF覆盖率是0%,查到最后就是Lib里没有定义MBFF单元。Standard cell library在交付时通常会提供两类触发器:
- 普通单bit FF,cell名字类似DFF_Q_X4、DFFRNQ_X2
- MBFF(或叫multi-bit flop),cell名字类似DFF4_Q_X4、MBFF_4X、DFF2_QN_X8
在dc_shell里可以用以下方式检查:
# 查看当前target library里所有包含DFF关键字的cell list_lib -lib [get_object_name [current_design]] report_cell [get_cells -filter "ref_name =~ *DFF*"] -verbose更直接的方法是直接查lib文件里有没有multi-bit cell的属性和面积。用文本编辑器打开.lib文件,搜索“multibit”或者“multi_bit”关键字:
# 在dc_shell里用grep检查lib内容 get_attribute [get_lib_cells */*DFF2*] area get_attribute [get_lib_cells */*DFF4*] area如果库里确实没有MBFF单元,那后续所有参数配置都是白搭。这时候只能回到两个选择:找工艺厂确认是否有多bit触发器单元;或者考虑在后端PR阶段用工具做“MBFF merge”(比如Fusion Compiler里的optimize_mbff)。但这篇文章主要讲综合阶段的做法,假设库是支持MBFF的。
2.2 MilkyWay/NDM数据流的准备要点
DCT(Design Compiler Topographical)和DCG(Design Compiler Graphical)在数据流上的要求不同:
- DCT时代主要用MilkyWay参考库,综合时需要提供一个布局参考,工具在优化时会调用abstract模型来估算线长和拥塞。
- DCG(新版本也叫DC Ultra Graphical)已经全面转向NDM(Next-generation Data Model)或者nlib格式,参考库需要来自Fusion Compiler/ICC2的NDM library。
实践里的一个常见坑是:库的NDM版本和DCG的版本不匹配。DCG版本更新之后,旧NDM库可能需要重新用icv_ndm或fc_ndm工具做一次upgrade,否则工具在读库的时候会报缺少physical信息,或者silently回退到wireload model模式。一旦回退到wireload模式,DCG的物理优化能力就完全失效了,MBFF优化也会因为缺少物理信息而表现异常。
检查是否成功进入physical模式:
# 在compile之前查看current_design的physical信息 current_design get_attribute [current_design] is_physical # 如果返回true,说明当前设计已经挂接物理库如果is_physical为false,先检查link_library和target_library中是否把NDM物理库配置正确。
2.3 确认target library的版本一致性
另一个低级的坑是target library同时列了多个不同版本的.lib文件,有些包含MBFF单元,有些不包含。工具在做逻辑映射时优先选用面积/功耗最优的单元,但如果没有约束MBFF的映射范围,工具可能会选到不支持MBFF的库里的单bit FF,导致优化失败。
在dc_setup.tcl里合理配置:
set target_library {sc9_ff.db sc9_mbff.db} set link_library {* sc9_ff.db sc9_mbff.db dw01.db dw02.db}如果设计里既用了常规库,又用了MBFF增强库,建议用set_multibit_options里的库筛选参数配合使用。工具只会选择在逻辑库中定义且物理实现的MBFF cell。
3. 核心参数配置:set_multibit_options到底在干什么
3.1 mode选择:single、multiple还是all
set_multibit_options是控制MBFF优化的核心命令:
set_multibit_options -mode {single | multiple | all} \ -min_bit_size 2 \ -max_bit_size 32 \ -type {reg | pmbff | all}参数含义:
- mode single:只允许生成bit数完全相同的MBFF,比如2个单bit合并成1个2bit单元,4个单bit合并成1个4bit单元。这种模式下,合并规则最简单,工具容易满足,覆盖率取决于库的大小。
- mode multiple:允许多种bit数混合,比如3个单bit合并成一个4bit单元,多出来的1个bit位置视为dummy。这个模式覆盖率更高,但物理上可能产生空的bit位,浪费面积。
- mode all:不限制组合方式,工具根据时序、面积、功耗综合评分决定最佳合并策略,覆盖率最高,但优化时间更长。
工程上我的建议是:第一次跑先使用mode multiple配合min_bit_size 2,看覆盖率报告和时序结果,再决定是否放宽到mode all。直接上mode all会引起综合时间显著增加,而且优化得过于激进时,后续后端布局很可能因为合并后的MBFF尺寸太大,反而增加legalization难度。
3.2 min_bit_size与max_bit_size的权衡
min_bit_size的意思是最少合并几个bit才算一个MBFF。设成2意味着只合并2bit及以上的,1bit的单独保留。设成4则完全忽略2bit合并,直接跳4bit以上。后者覆盖率低,但是平均节省的功耗更多——4bit合并比2bit合并的效率更高(因为共享时钟缓冲的比例更大)。
max_bit_size则取决于库中提供的最大MBFF bit数。如果库最大只有8bit,设成32完全没有意义。更重要的是,max_bit_size设太大时,工具会倾向于生成大MBFF,但大MBFF在布局时通常占据多个site行,和SPG的列式供电布局冲突会更明显。
我在实际项目里的经验值:
| 设计类型 | min_bit_size | max_bit_size | 备注 |
|---|---|---|---|
| 低功耗IoT SoC | 2 | 8 | 以4bit/8bit为主 |
| 高性能AI加速器 | 4 | 16 | 更激进,配合Fusion Compiler后期再优化 |
| 测试芯片/FPGA验证 | 2 | 4 | 覆盖率不是重点,时序收敛优先 |
3.3 处理扫描链与MBFF的兼容问题
DFT扫描链对MBFF优化是个大限制。因为MBFF内部的scan chain连接是固定的,比如DFF4的scan out连接到bit1的Q端,外部输入只能从bit0的SI进入。如果设计里scan cell的连接顺序和工具要求的bit顺序冲突,工具就会放弃合并这些寄存器。
处理方式有两种:
第一种:先做scan replacement,再跑MBFF。在DCG里设置:
set_scan_element false set_scan_register_type no_scan # 或者在使用compile_ultra时结合-scan参数 compile_ultra -scan -spg工具会优先保证扫描链的完整性和测试覆盖率,在同一个clock gate控制下、扫描链顺序兼容的寄存器才会被合并成MBFF。
第二种:接受部分寄存器不合并。在report_multibit里查看unmerged寄存器的原因。如果是scan order不匹配,可以考虑调整DFT约束或者重新映射扫描单元。
这里有个小技巧:我习惯在综合前先跑一遍dft_drc检查,确认scan chain定义无误后,再开MBFF优化。否则综合完了回头发现scan insertion失败,又要重新跑一遍compile,浪费时间。
4. 完整物理优化流程实录:从逻辑综合到物理收敛
4.1 DCG的物理综合流程到底做了什么
DCG(DCT的后续演进)在compile_ultra过程中实际上分成了两个大阶段:逻辑综合阶段和物理优化阶段。逻辑综合阶段完成RTL到门级网表的映射,物理优化阶段则通过布局和布线预估来迭代修复时序和congestion问题。对于MBFF而言,工具真正的合并行为主要发生在物理优化阶段,因为此时工具能预估每个寄存器的物理位置,判断哪些寄存器在物理上适合合并。
整个流程大致是:
# 1. 读入设计和约束(这部分和普通DC流程完全一致) read_verilog rtl/top.v current_design top link source constraints.tcl source power_intent.tcl # 如果设计用了UPF,需要在这里读入 # 2. 配置MBFF优化选项 set_multibit_options -mode multiple -min_bit_size 2 -max_bit_size 8 -type all # 3. 配置SPG相关的物理约束(后面第5部分详细讲) set_spg_options -mode power_gating -library spg_lib # 4. compile_ultra运行 compile_ultra -spg -retime -no_seq_output_init # 5. 检查MBFF报告 report_multibit -type all report_qor这里需要注意,compile_ultra里的-spg选项是配合SPG流程的开关,不是每个项目都必须开。如果设计根本没有使用SPG单元库,开了反而可能报错。老版本里对应的选项是-no_spg或者-spg,要根据实际工具版本来确认。
4.2 为什么选择在综合阶段做MBFF而不是放到后端
有些工程师会问,MBFF在后端PR工具(ICC2/Fusion Compiler)里也能做,为什么要放到综合阶段?
答案在于时序收敛的效率。综合阶段做MBFF优化,工具可以在逻辑映射时就考虑到合并后单元的物理尺寸和引脚位置,直接优化netlist本身。后端再做MBFF merge,本质上是基于已有的place结果做单元替换和摆放调整,受到的限制更多,而且做完merge之后通常还需要重新做一遍timing优化。
DCG做物理综合的真正优势是:它在逻辑网表层面直接生成MBFF物理信息,单元之间的连接关系在初始netlist里就已经按MBFF的pin定义构建好了,后续PR阶段不需要大幅改动网表结构,时序收敛路径更平滑。另外,综合阶段就完成MBFF优化,可以把功耗收益直接反馈到功耗预算估算里,便于更早确定封装和散热方案。
4.3 优化过程中的迭代策略
实际项目中,DCG跑完第一次compile之后,覆盖率通常不会一步到位。常见的迭代策略是:
第一次运行:先只用set_multibit_options默认参数,不要盲目扩大优化范围。看report_multibit里显示的unmerged寄存器数量以及unmerged原因。典型原因包括:寄存器之间存在组合逻辑、时钟门控不共享、复位端不一致、扫描链顺序不兼容。
第二次运行:根据第一次的unmerged原因,做两种调整:
- 如果大量寄存器因为“时钟门控不共享”而无法合并,检查RTL代码里的门控时钟生成方式。把结构相同的clock gate信号直接用create_clock或者set_clock_gating_check统一约束,工具更容易识别。
- 如果因为“复位端不一致”而无法合并,需要检查是否为异步复位。MBFF通常要求所有bit的复位端来自同一信号。如果存在多个异步复位域,考虑用同步复位替代异步复位(在满足功能安全要求的前提下)。
第三次运行:确认覆盖率稳定后,再调整min_bit_size和max_bit_size来微调面积和功耗的平衡点。这里有一个经验判断:覆盖率在60%到80%之间是合理的。超过90%通常说明设计里寄存器结构非常规整(比如大量相同位宽的寄存器组),但也要小心工具过度合并导致拥塞。覆盖率低于40%则说明RTL结构可能不利于MBFF优化,需要先改代码,不要一直调工具参数。
4.4 检查优化结果的三个关键报告
compile结束后,不要急着导出netlist。先看三个报告:
# 1. 覆盖率报告 report_multibit -type all # 2. 层次化功耗报告,重点看clock network部分 report_power -hierarchy -sort_by {total_power} # 3. 拥塞预估和时序报告 report_congestion report_timing -path_type full -delay_type maxreport_multibit的输出要重点看两个指标:
- Multi-bit cell数量:比如总共生成了多少个2bit/4bit/8bit cell
- Bit覆盖率:合并进MBFF的bit数占总寄存器bit数的比例
如果覆盖率很低(小于40%),不要急着加大优化力度。先用下面的命令查看unmerged寄存器的分布:
report_multibit -unmerged -list这个报告会分类列出未合并的寄存器以及原因。最常见的几条原因是时钟域不同、复位信号不同、扫描链顺序不同、存在Q端直接被使用导致bit位置冲突等。针对性地修改RTL里寄存器的时钟域划分或数据路径,比盲目调工具参数有效率得多。
5. 与SPG流程的碰撞:必须避开的坑
5.1 SPG到底是什么,它和普通Power Gating有什么区别
SPG(Standard-cell Power Gating)是一种基于标准单元库实现的列式电源门控方案。传统的power gating用单独的power switch cell插入到电源网络上,开关断开时将整个block或区域断电。SPG则把开关管单元和标准单元做在同一个row上,通过列方向上的电源轨切换来实现更细粒度的电源控制。
SPG的优势在于:开关颗粒度更小,支持更精细的power domain划分;不需要额外占用大面积的switch cell区域;动态电压降(IR drop)特性更好,因为开关管更靠近被测单元。
但这带来一个直接的物理约束:SPG的开关管单元会占用标准单元行内的site位置,导致可用于摆放普通逻辑的site数量减少。MBFF本身又是面积比较大的单元,两者叠加之后,行利用率(row utilization)会急剧上升,拥塞风险变大。
DCG对SPG的支持核心是识别SPG库中定义的power switch cell,并在布局预估时将它们作为特殊placement block处理。编译时使用:
set_spg_options -mode power_gating -library spg_lib compile_ultra -spg如果设计里没有定义任何power domain,也没有UPF文件,这一步可以直接跳过。
5.2 MBFF合并后对SPG供电网络的影响
这部分是实际项目里最容易被忽略的地方。MBFF合并后,同一个cell内的多个bit共享同一个电源网络连接,局部电流密度会发生变化。假设4个单bit FF分布在不同的row上,它们各自从附近的电源rail取电;合并成一个4bit MBFF后,4个bit集中在同一个位置,从周围的power via取电,局部IR drop上升。
在DCG阶段,工具可以通过physical density约束间接控制这种影响。比如设定在某些SPG power domain区域内的max_cell_density:
set_app_options -name place.coarse.max_density -value 0.7 # 或者针对特定block设置 set_app_options -name place.coarse.max_density -value 0.65 -block spg_test_block经验上,有SPG的区域,MBFF的max_bit_size建议控制在8bit以内,同时min_bit_size设成4以上(避免大量2bit单元占用过多site)。如果max_bit_size太大,生成16bit甚至32bit的MBFF,在SPG区域里几乎找不到足够大的连续空白区域合法摆放,工具会把单元推得很远,时序全面崩坏。
5.3 UPF电源意图对MBFF合并的约束级别
UPF(Unified Power Format)在综合阶段定义了power domain、power switch、isolation和retention策略。MBFF合并时,工具需要检查寄存器是否属于同一个power domain,以及是否包含retention功能。
关键点在于:retention flop不能被普通MBFF优化合并掉。因为retention flop用于保存掉电前的状态,它有额外的电源连接(VDD retention rail)。工具合并时如果忽略了这个差异,会生成一个不带retention功能的普通MBFF,直接导致状态保存在掉电过程中丢失——芯片直接挂掉。
在DCG里用下面的约束确保retention flop不被误合并:
set_multibit_options -mode multiple -min_bit_size 2 -max_bit_size 8 -type {reg} # type指定为reg而不是all,就是为了规避pmbff以及retention相关单元如果设计里同时存在普通寄存器和retention寄存器,需要在UPF里正确声明set_retention,工具才能区分。对于retention寄存器,明确排除在优化范围之外。检查方法:
report_power_domain -verbose # 确认每个power domain里寄存器的类型和供电连接5.4 SPG区域里的DFT和测试策略冲突
还有一个容易踩的坑来自DFT。SPG区域在测试模式下会进入特殊的测试电源状态,如果MBFF优化把扫描链上的寄存器合并到不同power domain之间的边界区域,扫描测试激励可能无法正常传递。
解决思路是:在综合阶段为SPG区域的DFT相关信号设置高优先级属性,确保扫描链上的寄存器不跨domain合并,或者使用set_scan_register_type限制扫描单元的类型:
set_scan_register_type no_scan # 或者将某些扫描单元设置为dcg type,限制优化行同时,在UPF或约束文件里手动指定power domain边界,避免工具把不同domain的寄存器合并到同一个MBFF里。domain边界和MBFF cell的物理位置需要在report_multibit后手动抽查几个关键cell,确认没有跨domain合并。
5.5 SPG流程的5个常见坑速查
| 坑 | 现象 | 解决方案 |
|---|---|---|
| 库文件缺少SPG cell定义 | compile报错或SPG选项无效 | 确认.lib中定义了power switch cell,且spg_lib在target library中 |
| UPF定义不完整 | retention flop被合并成普通MBFF | 在UPF中正确定义set_retention,并在set_multibit_options里排除retention单元 |
| MBFF尺寸过大 | SPG区域内congestion严重 | 在SPG domain设置较低max_density,或限制max_bit_size |
| 时钟门控信号不共享 | MBFF覆盖率低 | RTL层统一门控时钟信号,减少多个独立时钟门控 |
| IR drop超标 | 后端PR阶段EM/IR失败 | 综合阶段限制局部cell density,提前做power估算 |
6. 常见问题排查实录:那些我在项目里踩过的雷
6.1 MBFF覆盖率突然下降,原因可能是RTL更新
有一个项目,DCT阶段MBFF覆盖率一直稳定在75%左右,但某个版本的RTL更新之后,覆盖率掉到了50%。网表对比之后发现,新的RTL里大量寄存器加了“异步清零”逻辑,而且清零信号在模块里被倒了好几级。MBFF合并要求所有bit的复位端必须来自同一个信号,清零逻辑路径不同导致工具判断这些寄存器“复位端不一致”,放弃了合并。
处理方式是:在综合前先把这些相邻的寄存器做一次逻辑化简,或者手动在RTL里把时钟门控和复位逻辑统一。RTL的编码风格(比如是否用if-else嵌套生成门控时钟)对MBFF覆盖率的影响极其显著。经验法则是:想要高MBFF覆盖率,RTL里寄存器尽量遵循“同一时钟源、同一复位信号、同一门控信号”的三同原则。
6.2 合并后的MBFF时序反而变差了
另一个项目里,MBFF优化覆盖率做到85%以上,但timing却比优化前差了。原因分析后确认:MBFF优化为了追求覆盖率,把两个物理距离很远的寄存器强行合并成一个MBFF cell。工具在做place时,虽然网表里寄存器已经变成了一个cell,但cell的输入输出引脚还在原来的位置附近,导致绕线长度反而增加了。
DCG的physical optimization在这里起到了很关键的作用,但前提是工具能准确预估合并后的单元位置。解决思路是设置allowed_relative_positions参数,限制合并的寄存器之间的物理距离:
set_multibit_options -mode multiple \ -min_bit_size 2 \ -max_bit_size 8 \ -allowed_relative_positions {compatible}allowed_relative_positions有几种取值,比如compatible表示寄存器之间可以有一定距离,identical表示物理上必须紧邻。默认情况下工具会用比较宽松的规则,但当timing变差时,收严这个参数能有效缩小搜索空间。
6.3 用report_multibit定位“僵尸位”
有时工具会报告生成了4bit MBFF,但其中一个bit始终没有有效Q端逻辑。这种情况叫“僵尸位”(dummy bit or dead bit)。原因通常是3个寄存器在物理位置上接近,但找不到3bit的MBFF单元,工具硬生生用4bit单元合并了它们,浪费一个bit位。
僵尸位会带来两个问题:
- 面积浪费,理论上应该节省功耗,结果面积不降反升
- 布线拥塞,因为多了一个无用的Q端pin需要绕线处理
排查方法:
report_multibit -type all -verbose找出bit位使用不完整的MBFF,然后调整min_bit_size或者优化RTL里的寄存器数量对齐,尽量让寄存器个数是2的幂次或者与库里MBFF的bit数匹配。
6.4 和后端衔接时的网表一致性检查
DCG跑完之后,导出的netlist在送往ICC2/Fusion Compiler之前,必须做一次formal check和一个物理信息的完整性检查:
write -format ddc -hierarchy -output top.ddc write -format verilog -hierarchy -output top_netlist.v write_sdf top.sdf write_upf top.upf在后端读入netlist后,用以下方式验证:
# 在Fusion Compiler / ICC2里 check_physical_design check_mv_design -verbose # 确认MBFF cell的物理信息完整,没有缺失的电源pin连接曾经遇到一个情况:DCG里MBFF覆盖率看着正常,但导出到后端后,某些MBFF单元报“cannot find legal location”。最后定位发现是MilkyWay/NDM库中MBFF cell的PR boundary定义有问题,部分单元的row高度不一致。这种情况下需要回库去检查单元的高度定义,而不是在流程里调参数能解决的。
6.5 一组实用排查命令清单
| 问题 | 排查命令/方法 |
|---|---|
| 覆盖率为0 | 检查lib中是否有MBFF单元;检查is_physical属性;检查set_multibit_options是否在compile之前生效 |
| 覆盖率低 | report_multibit -unmerged;查看unmerged原因;检查时钟门控、复位信号是否一致 |
| 覆盖率“过高”但时序差 | 收严allowed_relative_positions;降低max_bit_size;检查僵尸位 |
| 面积不降反升 | 报告僵尸位数量;检查min_bit_size设置;对比report_power中的net power |
| DCG编译时间突然变长 | 查看MBFF优化选项的变化;检查是否有系统自动将mode切换为all;适当限制max_bit_size |
写在最后:一个关于效率的体会
我记得第一次在项目里用DCG做MBFF优化的时候,光是把覆盖率从40%调到70%就折腾了两周。后来发现最核心的瓶颈不在工具,而是RTL风格太随意——复位信号五花八门、门控时钟满天飞,工具再聪明也没法把不兼容的东西硬凑到一起。从那以后,我习惯在做综合前先花半天时间梳理整个design里寄存器的时钟域和复位域,把明显可以被合并的寄存器提前在RTL里整理成相同的时钟门控结构。这件事做完,MBFF覆盖率顺其自然就上去了,后端的SPG流程也不会因为奇怪的单元组合出问题。
如果你正准备在自己的项目里用DCT/DCG跑MBFF优化,我的建议是:先花一个小时确认库和UPF的完整度,再花半天调通第一次compile,最后根据report_multibit的报告做一轮针对性的RTL改进。这个顺序能帮你省掉最痛苦的反复试错过程。工具本身的功能已经足够强,真正决定功耗优化上限的,往往是你对设计数据流和物理约束的理解深度。