4. 逻辑综合优化技术

Design Compiler 在把 RTL 映射到工艺库之后,真正决定 PPA(功耗、性能、面积)的往往是优化阶段。综合优化不是单一动作,而是一组可以按层次、按边界、按资源分别施加的策略。理解这些策略的适用条件,比记住命令本身更重要。本节围绕结构化(Structural)、展平化(Flattening)、边界优化(Boundary Optimization)和资源共享(Resource Sharing)四类技术展开,并用一个面积与速度权衡的案例说明参数调优思路。

一、四类优化策略的定位

结构化优化保留设计的层次,在每一层内部做逻辑重构,例如提取公共子表达式、重排布尔网络、合并等价逻辑。它的优点是编译快、可读性好、便于后续 ECO,缺点是跨层次共享机会被层次边界挡住。展平化则把指定层次“打平”,让优化器看到全局逻辑,从而获得更大的重组空间,代价是网表可读性下降、编译时间上升、增量修改困难。边界优化介于两者之间:它不破坏层次,但允许优化器跨越边界移动、复制或重组逻辑,典型手段包括边界常量传播、寄存器边界重定时(retiming)和端口逻辑吸收。资源共享则针对算术与比较类算子,在互斥或时序错开的运算之间复用同一个硬件单元,用面积换吞吐或延迟。

四类综合优化策略的作用范围与代价 结构化优化 层次内逻辑重构 公共子表达式提取 布尔网络重排 代价低 · 可读性好 展平化 跨层次全局重组 消除层次冗余 面积/时序收益大 编译慢 · 难 ECO 边界优化 跨边界逻辑移动 常量传播 / 重定时 端口逻辑吸收 保留层次 · 收益中 资源共享 互斥运算复用单元 加法器/乘法器共享 面积换吞吐 面积降 · 需调度 面积优先 速度优先 资源共享 + 展平化 面积最小,延迟可能增大 结构化 + 边界优化 平衡方案,保留层次 展平化 + 重定时 速度最优,面积代价高 优化策略选择 = 在面积、速度、编译时间与可维护性之间取平衡 注:图中收益与代价为定性示意,实际数值取决于设计与工艺库

二、结构化与展平化的实际操作

在 Design Compiler 中,层次控制通过 set_ungroup 与 ungroup 完成。常见做法是:对时序关键路径所在的子模块设置 set_ungroup false 保留层次,对纯组合、无复用价值的中间层设置 set_ungroup true 允许展平。例如:

# 保留顶层与关键子模块层次
set_ungroup [get_designs "top"] false
set_ungroup [get_designs "u_core/u_alu"] false

# 允许展平纯组合中间层
set_ungroup [get_designs "u_core/u_mux_tree"] true

# 编译时启用边界优化
compile_ultra -boundary_optimization -gate_clock

# 对特定模块做局部展平
ungroup [get_designs "u_core/u_mux_tree"]

需要注意,ungroup 一旦执行,原层次名在网表中消失,后续用 report_area、report_timing 定位问题时路径名会变化。因此建议在综合脚本中保留一份“展平前”的层次快照,便于对比。边界优化通常与 compile_ultra 配合使用,它会尝试把端口上的常量、寄存器或组合逻辑吸收到相邻层次,减少边界上的冗余缓冲与逻辑。

三、资源共享的触发条件

资源共享不是自动发生的,它依赖两个前提:运算在时间上互斥,或运算结果在不同周期被使用。Design Compiler 在 compile_ultra 中会识别互斥条件(如 if/else 分支、case 分支),并尝试复用算术单元。若设计中有两个加法器分别位于互斥分支,工具可能合并为一个加法器加多路选择器。但若两个加法器在同一周期都被使用,则无法共享。可以通过 set_resource_allocation 与 set_implementation 对特定算子施加约束,例如指定加法器使用何种架构(行波进位、超前进位等)。

资源共享的收益通常体现在面积上,但会引入额外的多路选择器和控制逻辑,可能增加关键路径延迟。是否共享,应结合时序报告判断。

四、面积与速度权衡案例

假设一个示例设计:数据通路包含 4 个 16 位加法器,分别用于四个互斥的运算模式,目标工艺库为 40nm,时钟周期约束 2.0ns。初始综合采用全展平、不共享资源的策略,得到面积约 18500 μm²,关键路径 1.72ns,时序满足。若把面积作为首要目标,可尝试以下调优:

调优项操作面积变化(示例)时序变化(示例)
资源共享合并互斥加法器约 -12%关键路径 +0.15ns
局部展平仅展平 mux 树约 -4%基本不变
边界优化开启 boundary_optimization约 -3%可能略优
过度展平全部 ungroup约 -6%编译时间 +40%

表中数据为教学示例的合理假设,用于说明趋势,并非实测结果。实际调优时,建议按“先边界优化、再局部展平、最后资源共享”的顺序逐步施加,每步后用 report_area 和 report_timing -max_paths 5 观察变化。若资源共享后关键路径超出约束,可对共享后的加法器单独设置 set_max_delay 或改用更快实现架构,而不是直接放弃共享。

不要为了追求面积指标而盲目展平所有层次。展平会破坏模块边界,使后续形式验证、功耗分析和 ECO 变得困难。建议只对确认无复用价值、且时序不敏感的层次做展平。

五、参数调优的检查清单

  • 确认时钟约束与输入输出延迟已正确设置,否则优化方向会偏离。
  • 先用 check_design 排除悬空端口、多驱动等结构问题。
  • 对关键模块保留层次,对纯组合中间层允许展平。
  • 开启 -boundary_optimization,观察端口逻辑是否被吸收。
  • 识别互斥运算,评估资源共享的面积收益与延迟代价。
  • 每次调优后对比面积、时序、编译时间三项指标,避免单指标优化。

综合优化的本质是在约束空间内寻找可行解,而不是追求某一项指标的极值。结构化、展平化、边界优化和资源共享各自解决不同层面的问题,理解它们的作用范围与代价,才能在面积与速度之间做出有依据的取舍。