EDA后端从基础到实战 - 第4节

DC启动与脚本结构:从零开始跑综合

说实话,很多新手第一次打开Design Compiler时,面对那个黑乎乎的shell窗口,心里是发怵的。我当年也一样,对着dc_shell-t敲了半天,不知道下一步该干嘛。其实DC的启动没那么玄乎,说白了就两种方式:图形界面和命令行模式。

DC的两种启动方式

图形界面适合刚入门时看看综合结果,真正干活还得靠命令行。我个人习惯用dc_shell-t模式,脚本化运行,方便回归和版本管理。

# 命令行模式启动
dc_shell-t

# 图形界面启动
design_vision

嗯,这里要注意:dc_shell-t是Tcl模式,支持Tcl脚本语法。如果你用dc_shell,那是旧的Synopsys模式,现在基本淘汰了。我建议你直接上dc_shell-t,别走弯路。

脚本结构:我的标准模板

一个完整的DC综合脚本,我通常会分成四个部分:

  1. 库文件设置 — 告诉DC用哪个工艺库
  2. 读入设计 — 把RTL代码喂给DC
  3. 时序约束 — 告诉DC你的频率目标
  4. 综合与输出 — 跑综合,吐出门级网表

下面是我常用的脚本框架,你可以直接拿去改:

# ============================================
# Part 1: 库文件设置
# ============================================
set target_library "scc40nll_hs_rvt_tt_1p1v_25c.db"
set link_library "* $target_library"
set symbol_library "scc40nll_hs_rvt.sdb"

# ============================================
# Part 2: 读入设计
# ============================================
analyze -format verilog {./rtl/top.v ./rtl/sub_module.v}
elaborate top
current_design top
link

# ============================================
# Part 3: 时序约束
# ============================================
create_clock -name clk -period 10 [get_ports clk]
set_clock_uncertainty -setup 0.2 [get_clocks clk]
set_input_delay -max 2.0 -clock clk [get_ports data_in]
set_output_delay -max 2.5 -clock clk [get_ports data_out]

# ============================================
# Part 4: 综合与输出
# ============================================
compile_ultra
write -format verilog -output ./output/top_synth.v
write_sdc ./output/top_synth.sdc

我在项目中遇到过一个问题:有人把target_library和link_library搞混了。target_library是DC用来映射门电路的库,link_library是解析实例化模块用的。如果你只设了target_library没设link_library,DC会报一堆"找不到模块"的错误。

时序约束设置:别让芯片跑不起来

时序约束是综合中最关键的一步。你想想看,如果约束设错了,综合出来的电路要么太松(浪费面积),要么太紧(根本跑不到)。

时钟约束:核心中的核心

时钟约束决定了你的芯片能跑多快。最基本的设置就两个:时钟周期和时钟不确定性。

# 设置时钟周期为10ns,对应100MHz
create_clock -name clk -period 10 [get_ports clk]

# 时钟不确定性:包含jitter和margin
set_clock_uncertainty -setup 0.2 [get_clocks clk]
set_clock_uncertainty -hold 0.05 [get_clocks clk]

为什么setup和hold的不确定性不一样?setup uncertainty要留大一点,因为工艺偏差、电压波动主要影响setup。hold uncertainty可以小一些,hold问题更多是局部偏差。我曾经因为把hold uncertainty设得太大,导致综合结果面积暴增20%,后来才发现是这里的问题。

输入输出延迟:告诉DC外面的世界

芯片不是孤立存在的,它要和外部电路交互。输入延迟告诉DC数据从外部时钟沿到芯片引脚的延迟,输出延迟告诉DC数据从芯片引脚到外部寄存器的延迟。

# 输入延迟:外部数据在时钟沿后2ns到达
set_input_delay -max 2.0 -clock clk [get_ports data_in]
set_input_delay -min 0.5 -clock clk [get_ports data_in]

# 输出延迟:外部电路需要数据在时钟沿前2.5ns准备好
set_output_delay -max 2.5 -clock clk [get_ports data_out]
set_output_delay -min 0.3 -clock clk [get_ports data_out]

这里有个坑:min delay对应的是hold检查,max delay对应的是setup检查。很多人只设max不设min,结果hold违例一堆。我建议你两个都设,哪怕min设个0.1ns也行。

面积与功耗优化策略:鱼和熊掌怎么兼得

面积、功耗、性能,这三者永远在打架。DC提供了多种优化策略,关键看你怎么取舍。

面积优化:别让芯片太大

DC默认会优先优化时序,面积是次要目标。如果你想压面积,可以试试这些方法:

# 设置面积约束
set_max_area 0

# 启用面积优化
compile_ultra -area_high_effort_script

set_max_area 0的意思是"能压多小压多小"。但要注意,这可能会牺牲时序。我一般先跑一版不加面积约束的,看看时序余量,再决定要不要压面积。

功耗优化:低功耗设计的实战技巧

功耗优化分动态功耗和静态功耗。DC的compile_ultra自带了一些低功耗选项:

# 启用功耗优化
set_power_prediction true
compile_ultra -gate_clock -retime

# 时钟门控:最有效的低功耗手段
set_clock_gating_style -sequential_cell latch -positive_edge_logic {and} -negative_edge_logic {or}
insert_clock_gating

时钟门控是降低动态功耗的利器。我在一个项目中做过对比:不加时钟门控,功耗是120mW;加了之后降到85mW,降幅接近30%。代价是面积增加了不到5%,完全值得。

我的经验:功耗优化要分步走。先跑一版不加功耗优化的,看看基线功耗。然后逐步打开优化选项,每次只改一个参数,对比结果。这样你能清楚知道每个选项到底起了多大作用。

综合报告解读:别被数字忽悠了

综合跑完后,DC会生成一堆报告。新手往往只看"有没有违例",老手会从报告里读出更多信息。

时序报告:看余量,别只看违例

时序报告里最重要的不是WNS(最差负余量),而是TNS(总负余量)。WNS告诉你最差的那条路径有多差,TNS告诉你所有违例路径的总和。如果WNS是-0.5ns但TNS只有-1ns,说明只有一两条路径有问题,修起来不难。如果TNS是-100ns,那问题就大了。

# 生成时序报告
report_timing -delay_type max -nworst 10 -path_type full_clock

面积报告:看结构,别只看数字

面积报告会列出每个模块用了多少门。我习惯先看组合逻辑和时序逻辑的比例。如果组合逻辑占比超过70%,说明设计可能偏控制逻辑;如果时序逻辑占比高,说明寄存器多,可能是数据通路。

# 生成面积报告
report_area -hierarchy

功耗报告:看动态和静态的占比

功耗报告会告诉你动态功耗和静态功耗各占多少。在先进工艺下(28nm以下),静态功耗占比越来越高。如果你发现静态功耗占比超过40%,可以考虑用多阈值电压库来优化。

# 生成功耗报告
report_power -hierarchy
注意:DC的功耗估算只是预估值,和实际芯片的功耗可能有20%-30%的偏差。别完全相信报告上的数字,但可以用它来做相对比较——比如优化前和优化后的功耗变化趋势。

知识体系总览

下面这张图总结了本章的核心内容,你可以把它当作一个快速索引:

DC综合实战知识体系 DC启动与脚本结构 • dc_shell-t vs design_vision • 脚本四步法:库→读入→约束→综合 • target_library与link_library区别 • 常用Tcl命令速查 时序约束设置 • 时钟约束:周期、不确定性 • 输入延迟:setup/hold检查 • 输出延迟:外部电路时序 • 虚假路径与多周期路径 面积与功耗优化 • set_max_area 0 极限压缩 • 时钟门控:功耗降低30% • 多阈值电压库选择 • 面积与性能的权衡 综合报告解读 • WNS vs TNS:谁更重要 • 面积报告:组合/时序比例 • 功耗报告:动态/静态占比 • 报告对比:优化前后差异 DC 综合 四大模块相互关联,时序约束是核心,面积和功耗是优化目标,报告是验证手段

这张图把DC综合的四个核心模块串起来了。启动和脚本是基础,时序约束是灵魂,面积功耗优化是手艺,报告解读是检验标准。四个模块缺一不可。

好了,这一章的内容就到这里。记住一句话:DC综合不是跑一遍就完事的,它是一个迭代优化的过程。多跑几版,多对比报告,慢慢你就能找到感觉了。

可可精品资料库