4、逻辑综合优化:面积、时序与功耗的权衡,Yosys中的优化命令
好,咱们进入逻辑综合最核心的部分——优化。
说白了,综合就是把RTL代码变成门级网表。但光变出来不行,你还得让它满足面积小、跑得快、功耗低这三个要求。可惜,这三者往往是互相打架的。你想想看,想让电路跑得快,就得用大驱动单元,面积就大了,功耗也跟着涨。想省面积,用最小尺寸的单元,时序又可能崩了。
这就是我们常说的PPA(Performance, Power, Area)三角权衡。我在项目中遇到过好几次,老板说“面积再压一压”,结果时序直接红了,最后又得往回退。所以,做优化之前,心里得有个优先级。
4.1 优化的三个维度:面积、时序、功耗
咱们先简单捋一下这三个维度在Yosys里是怎么体现的。
- 面积优化:说白了就是减少使用的逻辑门数量。Yosys会尝试共享公共子表达式,合并冗余逻辑。
- 时序优化:目标是减少关键路径的延迟。Yosys会通过逻辑重组、单元重映射来缩短路径。
- 功耗优化:这个在Yosys里相对弱一些,主要是通过门控时钟(如果RTL写了)和减少不必要的翻转来实现。
我个人习惯,在综合初期先跑一遍面积优化,看看网表有多大。然后根据时序约束,再跑一遍时序优化。最后回头看看功耗,如果功耗超标,再针对性调整。
核心原则:没有完美的优化,只有满足约束的优化。你的目标是让设计“刚好”满足时序,同时面积和功耗尽可能小。
4.2 Yosys中的优化命令详解
Yosys提供了很多优化命令。我挑几个最常用的,也是我平时用得最多的,给你讲讲。
4.2.1 opt:通用优化命令
opt 是Yosys的瑞士军刀。它会自动执行一系列标准优化步骤。我建议你每次做完一个大的变换后,都跑一遍 opt。
# 最简单的用法
opt
# 带选项的用法,比如只做常数传播
opt -full
这个命令会做常数传播、简化表达式、删除未使用的信号等等。嗯,这里要注意,opt -full 会做更激进的优化,有时候会把一些你故意保留的层次结构给优化掉。如果你需要保留某些层次,慎用。
4.2.2 share:资源共享
这个命令专门用来减少面积。它会查找设计中可以共享的运算单元,比如多个加法器如果输入有重叠,它可以合并成一个。
# 共享算术单元
share
我曾经在一个图像处理模块里,发现两个乘法器其实可以共享,因为它们的输入在大部分时间是一样的。用 share 之后,面积直接降了15%。
4.2.3 abc:调用ABC工具进行逻辑综合
这是Yosys里最强大的优化命令。ABC是一个外部逻辑综合工具,Yosys可以调用它来做深层次的逻辑优化,包括技术映射和时序驱动优化。
# 基本用法,使用标准单元库进行映射
abc -liberty my_library.lib
# 时序驱动优化,需要提供SDC约束
abc -liberty my_library.lib -constr my_constraints.sdc
我个人习惯,在综合流程的最后阶段,一定会跑一遍 abc 来做最终的时序优化。它会根据你的时序约束,重新选择标准单元,比如把慢的单元换成快的,或者调整逻辑结构。
小技巧:如果你发现时序不满足,可以试试 abc -dff 选项。这个选项会让ABC尝试优化寄存器之间的逻辑,有时候效果出奇的好。
4.2.4 splitnets 和 opt_clean:清理网表
这两个命令虽然不起眼,但很重要。splitnets 会把多bit的线网拆成单bit的,方便后续优化。opt_clean 会删除所有没有输出的模块和信号。
# 拆分线网
splitnets
# 清理未使用的信号和模块
opt_clean
我建议你在每次优化之后,都跑一遍 opt_clean。不然网表里会残留很多“垃圾”,影响后续的分析。
4.3 优化策略:先面积,后时序,再功耗
在实际项目中,我一般会按这个顺序来:
- 第一步:面积优化。先用
opt和share把面积压到最小。这时候时序可能很差,没关系。 - 第二步:时序优化。加载时序约束,用
abc做时序驱动优化。如果时序不满足,我会回头看看RTL代码,是不是哪里写得太复杂了。 - 第三步:功耗优化。Yosys本身对功耗优化支持有限,但你可以通过
setundef命令把未定义的信号设为0,减少不必要的翻转。另外,检查一下门控时钟是否被正确综合了。
避坑指南:我曾经在一个项目中,为了追求极致的面积,把 opt -full 和 share 都用上了。结果综合出来的网表时序完全乱套,关键路径比预期长了30%。后来我才发现,过度共享导致逻辑深度增加了。所以,优化要适度,不要为了省一点面积而牺牲时序。
4.4 一个完整的优化脚本示例
最后,给你一个我常用的优化脚本片段,你可以直接拿去用。
# 读取设计后,先做基本优化
hierarchy -check
proc
opt
fsm
opt
share
opt
# 拆分线网并清理
splitnets
opt_clean
# 技术映射和时序优化
abc -liberty my_library.lib -constr my_constraints.sdc
# 再次清理
opt_clean
# 检查统计信息
stat -liberty my_library.lib
这个脚本覆盖了从基本优化到时序优化的全过程。你只需要替换 my_library.lib 和 my_constraints.sdc 为你自己的文件就行。
好了,关于逻辑综合优化,咱们就聊到这儿。记住,优化不是一蹴而就的,需要反复迭代。多跑几次,多看看报告,慢慢你就有感觉了。