3. 综合工具入门:Design Compiler基本流程
好,咱们开始聊DC。Design Compiler,Synopsys家的看家工具。
说实话,我刚入行那会儿,第一次打开DC的界面,心里是有点懵的。满屏的英文,一堆命令行,感觉像回到了DOS时代。但用久了你会发现,这玩意儿其实挺纯粹的——它只关心一件事:把你写的RTL代码,变成门级网表。
3.1 DC能干什么?
简单说,DC就是个翻译官。它把Verilog/VHDL这种高级语言,翻译成由标准单元库里的门电路组成的网表。同时,它还要保证这个网表能满足你的时序、面积、功耗要求。
我个人习惯把DC的工作分成三步:
- 读入设计:把RTL代码和库文件吃进去
- 施加约束:告诉DC,你要跑多快、用多大面积
- 综合优化:DC自己琢磨怎么映射到门级电路
核心知识点:DC综合的本质是“约束驱动”。你给什么约束,它就往什么方向优化。不给约束?那它就会随便搞,结果往往不是你想要的。
下面这张图,是我自己总结的DC综合流程,你一看就明白:
3.2 启动DC
启动DC有两种方式:命令行和图形界面。
我个人更推荐命令行。为什么?因为脚本可以复用,方便回归。你想想看,一个项目做几个月,每次综合都要点鼠标,那不得累死?
我的习惯:我一般用 dc_shell-t 启动命令行模式。如果想看波形或者做debug,再用 design_vision 启动GUI。
启动命令很简单:
# 启动命令行模式
dc_shell-t
# 启动图形界面模式
design_vision
嗯,这里要注意。启动之后,DC会加载你的.synopsys_dc.setup文件。这个文件里配置了库路径、搜索路径等。我见过不少新手,启动DC后报错说找不到库,其实就是.setup文件没配好。
避坑指南:我曾经在一个项目里,因为.setup文件里写错了库的路径,结果综合出来的网表全是空的。查了两天才发现是路径少了个斜杠。所以,启动后第一件事,用 list_libs 检查库是否加载成功。
3.3 读取设计文件
设计文件读入,说白了就是把你的RTL代码告诉DC。DC支持多种格式:Verilog、VHDL、SystemVerilog等。
常用的命令有两个:
- read_verilog:直接读入Verilog文件
- analyze + elaborate:先分析语法,再例化设计
我一般用第二种方式。为什么?因为analyze会检查语法错误,elaborate会帮你展开层次结构。如果代码里有例化错误,elaborate阶段就能发现。
# 方式一:直接读入
read_verilog {top.v module_a.v module_b.v}
# 方式二:分析+例化(推荐)
analyze -format verilog {top.v module_a.v module_b.v}
elaborate top
关键点:elaborate之后,DC会生成一个名为 top 的设计(就是你指定的顶层模块)。这时候可以用 link 命令来连接所有子模块。如果link报错,说明有模块没找到或者例化名不匹配。
我记得有一次,一个同事的代码在仿真里跑得好好的,但DC就是link不过。查了半天,发现是某个子模块的文件名和模块名不一致。DC是按模块名找文件的,不是按文件名。这个坑,你记住。
3.4 设置约束
约束,是DC综合的灵魂。没有约束,DC就不知道往哪个方向优化。
约束主要分三类:
| 约束类型 | 常用命令 | 说明 |
|---|---|---|
| 时序约束 | create_clock, set_input_delay, set_output_delay | 定义时钟周期、输入输出延迟 |
| 面积约束 | set_max_area | 限制综合后的面积上限 |
| 设计规则约束 | set_max_fanout, set_max_transition | 保证物理实现的可行性 |
时序约束是最核心的。我一般这样写:
# 创建时钟,周期10ns,占空比50%
create_clock -name clk -period 10 [get_ports clk]
# 设置输入延迟(假设外部延迟为2ns)
set_input_delay -clock clk 2 [all_inputs]
# 设置输出延迟(假设外部延迟为3ns)
set_output_delay -clock clk 3 [all_outputs]
# 设置面积约束(可选)
set_max_area 0
我的经验:set_max_area 0 的意思是让DC在满足时序的前提下,尽量把面积做小。但别指望它真的能到0,这只是个优化方向。实际项目中,我一般先跑一版不加面积约束的,看看时序能不能过。时序过了,再加面积约束去压面积。
你可能会问:约束设错了会怎样?
嗯,这个问题问得好。我曾经在一个项目里,把时钟周期设成了1ns(实际应该是10ns)。结果DC综合出来的电路面积巨大,功耗也高得离谱。因为DC以为你要跑1GHz,拼命插寄存器、优化路径。后来发现是约束写错了,改回来重新综合,面积直接降了一半。
避坑指南:约束不是越紧越好。过紧的约束会导致DC过度优化,增加面积和功耗。过松的约束又可能导致时序不满足。我的建议是:先按芯片目标频率的80%设约束,综合一版看看余量,再逐步收紧。
3.5 执行综合
约束设好了,就可以跑综合了。核心命令就一个:
compile_ultra
compile_ultra 是DC目前最推荐的综合命令。它比老版的 compile 优化效果更好,特别是对时序和面积的平衡。
当然,你也可以加一些选项:
compile_ultra -no_autoungroup -retime
- -no_autoungroup:保持层次结构,不自动打平。方便后端的物理设计。
- -retime:允许DC移动寄存器位置来优化时序。这个选项很强大,但也会增加综合时间。
综合完成后,DC会生成一系列报告。我最常看的是:
- report_timing:看时序是否满足
- report_area:看面积大小
- report_power:看功耗估算
最后,把综合好的网表写出来:
write -format verilog -hierarchy -output top_synth.v
好了,DC的基本流程就是这样。启动、读设计、设约束、跑综合、出网表。每一步都有坑,但走一遍就熟了。我个人觉得,DC综合最考验人的不是命令,而是对约束的理解。约束设得好,综合就成功了一半。
总结一句话:DC综合,七分靠约束,三分靠命令。把约束想清楚,比背一百条命令都管用。
可可精品资料库