第三讲:逻辑综合优化策略——综合策略选择与实战技巧
逻辑综合,说白了就是把RTL代码翻译成门级网表的过程。但同样的代码,不同的综合策略,出来的面积可能差30%以上。我刚开始做综合时,总觉得工具是万能的,后来被现实狠狠教育了一回——那次项目面积超标,我花了整整两周才找到问题根源。
今天咱们聊聊综合策略里那些真正影响面积的细节。嗯,都是我在项目里踩过的坑。
3.1 综合策略选择:area_high vs area_zero
DC(Design Compiler)里有个关键选项叫set_compile_directives,其中-area_high和-area_zero是两个极端。很多人以为选area_high就能自动把面积压到最小,其实没那么简单。
核心区别:
- area_high:激进优化,会牺牲时序来换面积。适合时序余量充足的设计。
- area_zero:保守优化,优先保证时序,面积优化力度最小。适合时序紧张的设计。
我个人习惯的做法是:先用area_high跑一版,看看面积能压到多少。如果时序违例严重,再切换到area_zero。但注意,area_high不是万能的——它可能会把一些关键路径上的逻辑过度优化,导致setup违例。
我的经验:对于控制逻辑密集的设计(比如状态机、仲裁器),area_high效果明显。但对于数据通路(比如加法器、乘法器),效果有限,因为数据通路的面积主要由位宽决定。
3.2 边界优化与展平
边界优化(Boundary Optimization)和展平(Flatten)是DC里两个容易被忽视的选项。我见过不少工程师,代码写得挺好,但综合结果面积奇大,问题就出在这两个选项上。
边界优化:DC会分析模块之间的接口,把跨模块的冗余逻辑优化掉。比如两个模块之间有个反相器链,DC可能会把它合并掉。
展平:把层次化的设计打平,让DC能看到全局逻辑,从而做更激进的资源共享。但代价是综合时间变长,而且调试困难。
我曾经踩过的坑:有一次为了追求面积,我把整个设计展平了。结果综合跑了12小时,而且后仿发现一个bug,定位问题花了三天——因为所有信号都混在一起,根本看不出层次。后来我学乖了:只在关键模块上做展平,顶层保持层次化。
建议的做法:
- 对面积敏感的模块(比如数据通路、存储控制器)单独做展平
- 对控制逻辑模块,保持层次化,只做边界优化
- 综合完成后,用
report_area -hierarchy检查各模块面积
3.3 资源共享的DC命令
资源共享是面积优化的重头戏。DC里相关的命令不多,但用好了效果显著。
核心命令:
set_compile_directives -resource_sharing true
set_optimize_registers -resource_sharing true
set_fix_multiple_port_nets -all -buffer_constants -feedthroughs
你想想看,两个加法器如果永远不会同时工作,为什么不共用同一个?DC的资源共享就是干这个的。但要注意,资源共享可能会引入额外的MUX,反而增加面积。
实战技巧:
- 先不加资源共享跑一版,记录面积
- 加上资源共享再跑一版,对比面积变化
- 如果面积反而变大,说明MUX开销超过了节省的资源
- 这种情况下,手动在RTL里做资源共享更靠谱
我记得有个项目,一个16位的乘法器被多个模块调用。DC自动资源共享后,面积反而增加了5%。我手动改成时分复用,面积降了12%。所以,工具不是万能的,关键还是得理解设计意图。
3.4 set_max_area约束的使用技巧
set_max_area是DC里最直接的面积约束。但很多人用错了——要么设得太紧导致综合失败,要么设得太松等于没用。
正确用法:
# 先跑一版不加面积约束,得到基线面积
set_max_area 0
compile_ultra
report_area
# 根据基线面积,设置合理的目标
set_max_area [expr [get_attr [current_design] area] * 0.9]
compile_ultra -incremental
为什么要先跑基线?因为不同工艺、不同库,同样的代码面积差异很大。我习惯的做法是:先不加面积约束跑一版,得到面积A。然后设set_max_area A*0.9,再跑增量编译。如果工具报无法满足,就放宽到A*0.95。
避坑指南:我曾经把set_max_area设成0,结果DC疯狂优化面积,时序完全崩了。后来才知道,set_max_area 0的意思是「面积越小越好」,但工具会优先满足时序约束。如果时序约束很紧,面积约束会被忽略。所以,面积约束要合理,别太贪心。
3.5 知识体系总览
下面这张图总结了本章的核心逻辑。我建议你把它存下来,做综合时对照着看。
3.6 实战总结
说了这么多,其实核心就几点:
- 别迷信工具:DC的默认策略不一定适合你的设计。先跑基线,再手动调整。
- 分模块优化:不同模块用不同策略。控制逻辑用
area_high,数据通路用area_zero。 - 资源共享要谨慎:自动共享不一定省面积,手动实现往往更可控。
- 面积约束要合理:
set_max_area设得太紧,工具会乱优化;设得太松,等于没设。
嗯,这些技巧看起来简单,但真正用好需要反复实践。我建议你下次做综合时,拿一个模块试试不同的策略组合,看看面积变化。只有亲手试过,才能真正理解。
一句话总结:综合策略没有银弹,理解工具行为、结合设计特点、迭代优化,才是面积优化的正道。