逻辑综合实施流程

  • 1. DC启动
    • 1.1 四种启动方式
    • 1.2 日志文件
    • 1.3 启动文件
  • 2. 读入设计文件
    • 2.1 read
    • 2.2 analyze&elaborate
    • 2.3 link
  • 3. 施加设计约束
    • 3.1 面积约束
    • 3.2 时序约束
      • 定义时钟
        • clock_latency
        • clock_uncertainty
        • generated_clock
        • propagated_clock
        • clock transtion
      • I/O 端口时序
        • 输入延迟(input_delay)
        • 输出延迟(output_delay)
      • 组合逻辑约束
        • max_delay
        • min_delay
      • 时序例外
        • 伪路径
        • 多周期路径
    • 3.3 DRC约束
      • 最大转换时间
      • 最大扇出负载
      • 最大负载电容
    • 3.4 Tcl脚本示例
  • 4. 施加环境约束
    • 4.1 工作条件
    • 4.2 输出容性负载
    • 4.2 输入驱动强度
      • set_drive
      • set_driving_cell
      • set_ideal_network
    • 4.3 互连线延时
    • 4.4 线负载工作方式
    • 4.5 约束检查
  • 5 编译和输出
    • 编译指令
    • 输出文件内容
    • 时序报告具体内容
  • 设计综合(优化)
  • 后综合过程
  • 参考资料

具体介绍使用Synopsys的Design Compiler进行综合的过程,整个过程大致可以分为以下几个部分:

其中预综合过程包含以下内容:

更加具体的流程如下:

1. DC启动

1.1 四种启动方式

  1. dc_shell [-f script]

启动后,使用DCSH命令,DCSH 是基于Synopsys自身语言的命令行接口。(也就是说这种启动方式只能使用Synopsys TCL)

  1. dc_shell -t [-f script]

该命令则可以使用标准TCL语言。(自动化程度更高)

  1. design_analyzerdesign_vision

两个都是启动图形化界面。
design_analyzer 对应的是dc_shell的命令行方式, 所以不能在 design_analyzer 里运行 tcl 命令。 另外需要注意的是: design_analyzer 的工作模式不是用于编辑电路图的, 它只能用于显示 HDL 语言描述电路的电路图
design_vision 是与 tcl 对应的图形方式。

使用design_vision启动如下:


此时打开的图形化界面如下:

这里,先使用 dc_shell,再使用gui_start也可以达到相同的效果。

1.2 日志文件

DC启动时,会在启动目录下,生成如下三个日志文件:

1.3 启动文件

Synopsys产品很类似,他们都有启动文件.synopsys_dc.setup,就是 DC 在启动的时候首先读入的文件,用于初始化工具,其中PT需要单独的启动文件 .synopsys_pt.setup。该文件是一个隐藏文件,需要使用ls -a来查看。
DC在启动的时候, 会自动按顺序在以下三个目录下搜索该文件(如下图所示),对 DC 的工作环境进行初始化:

  1. $SYNOPSYS/admin/setup 目录下, DC 安装的标准初始化文件
  2. 当前用户的 $HOME 目录下, 一般用于设置一些用户本人使用的变量以及一些个性化设置。
  3. DC 启动所在的目录下,一般是和具体设计相关的特定设置。

按照上述三个启动文件的顺序,后面读取的 setup 文件可以覆盖前面文件中的设置。 该文件主要包括库的设置、 工作路径的设置以及一些常用命令别名的设置等等。由于 dcshell 的启动脚本和 tcl 的脚本语法不一致, 所以如果只有一种方式的启动脚本,那么运行另一种方式的时候会报错。 因此, DC的启动脚本有一种兼容两种方式的格式。
启动文件示例:


文件的第一段设置工艺库和链接库, 第二段设置符号库和搜索路径, 第三段设置 DC 命令的别名。

2. 读入设计文件

DC读入设计文件有两种方式,一是read指令,二是analyzeelaborate的组合。

2.1 read

具体示例如下:

read -format verilog[db, vhdl ...] file // DCSH mode
read_db file.db                         // Tcl mode
read_verilog file.v                     // Tcl mode
read_vhdl file.vhd                      // Tcl mode

DC可以读取设计流程中任何一种数据格式,如行为级描述、RTL级描述、门级网表等,但是不同的数据格式使的DC综合的起点不同,也就是说,即使实现相同的功能,也可能会产生不同的结果

2.2 analyze&elaborate

  1. 该命令仅能用于VHDL和verilog。
  2. read命令其实是一步完成analyze&elaborate的工作,
  3. 该组合命令和read都是读入设计文件,如果执行进行综合,更推荐使用组合命令,两者的一些区别如下:

语法格式:

analyze [-library library_name] [-format verilog | vhdl | sverilog] file_list

  • library:指定中间结果存放的库,即Linux系统下的一个目录,默认为当前目录,也可以用define_design_lib命令指定。
  • format:HDL源文件的类型,即verilog或vhdl或sverilog。
  • file_list:源代码文件名列表,文件名的指定可以通过TCL的链表命令{}、“”、[list file_name]等三种方法之一完成。

elaborate design_name [-library library_name] [-parameters param_list]

  • deisgn_name:指需要进行描述的设计。
  • library:用于保存设计的结构级描述。
  • parameters:指定给设计传递的参数,若省略则参数使用缺省值;参数用“”括起来。

示例:

dc_shell-t>analyze -f verilog [list ctrl_0723.v、datapath_0723.v、ram16s.v、ram16x1s.v、regfile.v、xram16.v、xr16.v、memctrl.v、vga.v、xsoc.v]

2.3 link

当读取完所有要综合的模块之后,需要使用link命令将读取到DC存储区的模块或者示例连接起来。

link前还需要使用current_design指定顶层模块为当前设计,DC默认将最后读入的一个模块作为顶层模块。link后还需要使用uniquify进行实例唯一化。
对于被多次实例化的同一子设计,由于其例化后的工作环境各不相同,因此,需要用uniquify 命令为每个实例在内存中创建一份副本,以便区分开每个实例。DC可以根据不同的应用环境进行合适的优化。

指令示例如下:

dc_shell-t> current_design topModuleName      # 设置顶层设计为当前设计
dc_shell-t> link                 # 链接
dc_shell-t> uniquify             # 实例唯一化

3. 施加设计约束

Design Compiler 是一个约束驱动的综合工具,它的结果是和设计着施加的约束条件密切相关的。约束条件主要包括时序约束面积约束两部分。
DC综合是一个迭代的过程,会对RTL代码进行修改,指导满足时序约束为止,如下图:

前面介绍了DC的设计对象,各种约束的施加其实就是对设计对象设置了相应的属性。设计对象的属性按照cell、clock、design、library cell、 net、 pin、 port、 read-only、 reference等进行划分,通常用到较多的attribute 包括:area、 dont _touch、 load 、rise_drive、fall_drive, max_rise_drive、max_fall_drive、 rise_delay 、fall_delay、 plus_uncertinty、minus_uncertainty, propagated_clock, pin_direction. Port_direction。
查看特定设计对象的特定属性时,可以使命令get_attributes,比如,查看时钟端口 CIK 的上升沿驱动能力:

dc_ shell-t> get_attribute [get ports CLK] rise_drive
3.283230

再比如查看工艺库smic18ss 中单元 NAND2BIHIDIX的面积:

dc_shell-t> get_attribute [get_lib_cells smicI8_ss/NAND2B1HD1X] area
7.564000

3.1 面积约束

面积是主要的成本因素,电路面积要尽可能小,速度要尽可能快,但速度越快面积就要大。

面积约束指令示例:

dc_shell-t> current_design PRGRM_CNT_TOP
dc_shell-t> set_max_area  100

上面的例子给PRGRM_CNT_TOP的设计施加了一个最大面积100单位的约束。100的具体单位是有Foundary规定的,定义这个单位有三种可能的标准:

  • 两输入与非门的个数(2-input-NAND-gate)
  • 晶体管个数(transistors)
  • 实际的面积,如平方微米(square mils)

对于时序优先的设计,通常设置其最大面积为0,意指在时序收敛的前提下尽可能的优化面积。命令为:

dc_shell-t>set_max_area 0.0

3.2 时序约束

逻辑综合的过程中,除了面积之外,要达到的目标是约束电路中的所有时序路径,从而实现对工作频率的约束。
设计中的时序路径可以划分为以下四种:

  • 输入到寄存器的路径
  • 寄存器到寄存器之间的路径
  • 寄存器到输出的路径
  • 输入到输入的路径


对于图中的路径X,是一个寄存器到寄存器的路径,对于该组合路径而言,其最大裕量是一个时钟周期,因此定义时钟周期就可以实现对该路径的约束。

定义时钟

在电路综合的过程中,所有的时序电路和组合电路的优化都要以时钟为基准来计算路径延迟,因此,一般都要在综合的时候指定时钟,将其作为估计路径延时的基准
对时钟进行定义的具体内容如下:

时钟定义语法格式:

create_clcok [-name clock_name] [source_objects] [-period period_value] [-waveform edge_list]
# name:为创建的时间指定一个名称,如果省略该项,时钟名称为source_objects中第一个对象的名称,如果后续 source_objects省略,则该项必须指定,这种情况下创建的是虛拟时钟,用于约束组合逻辑的相对延时条件;
# source_objects:用于创建时钟的引脚或端口名称;
# -period:创建时钟的周期,单位由工艺库决定,一般为 ns;
# -waveform:指定时钟上升沿和下降沿的时刻,从而决定时钟信号的占空比;如果略去该项,默认时钟占空比为50%,上升沿的时刻为0。

时钟定义示例1

dc_shell-t> create_clock -period 10 [get_ports Clk]
dc_shell-t> set_dont_touch_network [get_clocks Clk]

create_clock定义了一个时钟,set_dont_touch_network给时钟定义了一个dont_touch属性,即综合的时候不对Clk信号行优化。
如果不加这句,DC会根据Clk的负载自动对他产生Buffer,而在实际的电路设计中,时钟树(Clock Tree)的综合有自己特别的方法,它需要考虑到实际布线后的物理信息,所以 DC不需要在这里对它进行处理,就算处理了也不会符合要求。
DC综合是一个理想情况,单元的实际位置并没有固定下来,没有办法实现一个实际的时钟网络。DC得到的时钟是很不准确的,在布局布线的时候还要把这个不准确的时钟网络删除,然后重新做一个正确的网络,因此没必要在该阶段进行时钟综合。

时钟定义示例2 :

比如在输入端口 CLK创建一个周期为10ns,名称为clk的时钟,命令为:

dc_shell-t> create_clock -name clk -period 10 [get_ports CLK]

该时钟的占空比为 50%,若要时钟占空比为 40%,命令可改为:

dc_shell-t> create_clock -name clk -period 10 -waveform [0 4] [get_ports CLK]

create_clock命令创建的时钟是理想时钟,没有延时。可以通过指定latench,uncertainty等约束条件来模拟真实时钟,相应的命令为:set_clock_latencyset_ clock_uncertainty

clock_latency

set_clock_latency命令用于定义时钟网络的延迟,包括source_latencynetwork_latency
source_latency是从时钟源到时钟定义位置的延迟,network_latency是时钟定义位置到触发器时钟输入端的延迟。
语法格式:

set_clock_latency [-source] delay object_list
# -source:指定latency为source_latency,若没有该选项,则为network latency.
# delay:时钟延时的值。
# object_list::指定latency所在的时钟、端口、引脚的对象列表。

示例:

dc_shell-t> set_clock_latency -source 3 [get clocks CLK]
dc_shell-t> set_clock_latency 3 [get clocks CLK]

clock_uncertainty

Latency指定了时钟的延时,后端版图设计的结果可能会引起时钟网络的时序在一定范围内变化,因此可以使uncertainty来为 DC 的综合与优化提供一定的时间裕度。uncertainty分为 plus uncertainty(保持时间检查时用)和 min uncertainty(建立时问检查时用)。设置uncertainty的命令及其格式为:

set_clock_uncertainty [-setup] uncertainty
# -setup:指定仅用于建立时间检查的uncertainty,默认情记下 uncertaing同时用于建立时间和保持时间检查。
# uncertainty:时钟不确定性的值。

generated_clock

实际中在一些复杂设计上可能会用到分频或倍频时钟,DC 不能为这些时钟自动创建时钟对象,这就要用到 create_generated_clock 命令。其语法格式为:

create_generated clock [-name clock_name] -source master_pin [-divide_by divide_factor | -multiply_by multiply_factor] source_objects
# -name:指定生成时钟的名称。
# -source:指定主时钟。
# -divide:指定分频系数。
# -multiply:指定倍频系数。
# source_objects:指定生成时钟所在的端口或引脚列表。

比如,当时钟信号DIVIDE是主时钟SYSCLK的2分频,其命令为:

dc_shell-t>create_generated_clock -name DIVIDE -source SYSCLK divide_by 2 [get_pins U4/Q]

propagated_clock

前面介绍的时钟定义需要手工为其设置各种条件,而对于布图后的时钟信号只需指定其为传播时钟,则DC会将时钟树上的延时属性自动加载到所指定的设计对象上,其命令为 set_propagated_clock

clock transtion

由于时钟的负载很大,时钟的翻转时间往往也很大,这与实际是不符的,因此需要为时钟信号指定一个固定的翻转时间,命令为set_clock_transtion

综合前面几条命令,现要设计创建一个时钟,周期 10ns, network_latency为 1ns, source_latency为3ns,时钟翻转时间为 0.3ns,建立时间检查的不确定性为0.5ns,完整的脚本命令为:

create_clock -period 10 [get_ports CLK]
set_clock_latency 1 [get_clocks CLK]
set_clock_latency -source 3 [get_clocks CLK]
set_clock_uncertainty -setup 0.5 [get_clocks CLK]
set_clock_transition 0.3 [get_clocks CLK]
set_dont_touch_network [get_clocks CLK]

注意:当内核逻辑加上 PAD 后,时钟应定义在“时钟PAD”的输出上(假定为D,同时为其设置dont_touch 属性,并将输出线(假定为pad_clk_o。)设为ideal_network。具体脚本命令为:

set T 10
create_clock -period $T -waveform [list 0 $T/2] -name clk [get pins PAD INS/CLK PAD/D]
……
set_dont touch network [get_clocks CLK]
set_ideal_network [get_nets PAD_INS/pad_clk_o]

I/O 端口时序

如下图,通过定义时钟,实现了对路径X的约束,但是路径N和路径S的还没有被约束,这个时候就要定义IO相对clock的时序。

输入延迟(input_delay)

对于输入端口,定义输入延迟

输入延时指的是被综合模块外的寄存器触发的信号在到达被综合模块之前经过的延时,在图中就是外围触发器的clk-q的延时加上M电路延时。
(制定好输入延时之后,就可以确定出路径N的延时范围,只要其延时在这个范围内,信号就能正确传递。)

语法格式:

set_input_delay delay_value [clock clock_name] [-max] [-min] port_pin_list 。
# delay_value:设定的输入延时的大小,单位由工艺库决定,一般为ns。
# -clock:输入延时所参考关联的时钟;
# -max:最大延时(建立时间)
# -min:最小延时(保持时间)
# port_pin_list:当前设计中设定输入延时的输入端口或内部引脚的列表。

示例1:

dc_shell-t> set_input_delay -max 4 -clock Clk [get_ports A]
  • [get_ports A] : 将输入延时施加到A端口上
  • max 4 :端口最大延时(最大延时用于建立时间,最小延时用于保持时间)
  • clock Clk :延时值的基准时钟(即针对哪个时钟的延时)(电路中有多个时钟域,每个时钟域都有对应的输入和输出引脚,所以要指定时钟)

示例2:

假设待综合电路如上图所示,需要施加的时序约束如下:

create_clock -period 20 [get_ports CLK]
set_dont_touch_network [get_clocks CLK]
set_input_delay -max 7.4 -clcok Clk [get_ports A]

因为外部电路模块中给定的延时说明了worst,所以要将输入延时设为max

输出延迟(output_delay)

对于输入端口,定义输出延迟

信号在被综合模块的触发器U3里触发,被外围的一个触发器接收。对外围电路而言,它有一个T电路延时和外围触发器的建立时间。当确定了他们的延时之后,被综合模块内部的输出路径延时范围也就确定下来了


指令语法格式:

set_output_delay delay_value [-clock clock_name] [-max] [-min] port_pin_list
# delay_value: 设定的输出延时的大小,单位由工艺库快定,一般为ns。
# -clock:输出延时所参考关联的时钟。
# -max:指定最长路径的输出延时。
# -min:指定最短路径的输出延时。
# port_pin_list:当前设计中设定输出延时的输出端口或内部引脚的列表。

示例:

dc_shell-t> set_output_delay -max 5.4 -clock Clk [get_ports B]

输入延迟和输出延迟的概念好像是一样的,只是针对的但当前电路而言有了输入和输出之分。两者都是时钟周期减去输入或输出延时得到当前待综合模块的输入或输出路径的时序约束。

组合逻辑约束

对于纯组合逻辑,一般使用set_max_delayset_min_dealy进行约束,也可以使虚拟时钟。

max_delay

set_max_delay 用于在当前设计中指定从任意起点到任意终点的最大延时。
语法格式为:

set_max_delay delay_value [-from from_list] [-through through_list] [-to to_list] [-group_path group_name]
# delay_valve:指定最大延时的值,单位由工艺库决定,一般为 ns.
# -from:延时约束的起点列表;
# -through:延时路径经过的节点列表。
# -to:延时约束的终点列表.
# -group_path:建立一个时序关键路径的组,用于重点优化。

group_path选项对编译时间有较大影响,而且该组优化的优先级高,可能会导致其他的时序违例。因此该选项(或单独使用 group_ path命令)通常作为综合优化的最后手段使用。
比如设定从UO的CP端经单元U1和U2的Z端到达U3的A端的最大延时为5.0ns,则命令为:

set_max_delay 5.0 -from [get_pins U0/CP] -through [list UI/Z U2/Z] -to [get_pins U3/A]

min_delay

set_min_delay用于在当前设计中指定路径的最小延时,与set_max_delay相对,该命令与set_fix_hold命令配合使用修正电路的保持时间,如果发生min_delay 违规,在不增大 max_delay 的情况下综合工具会自动添加合适的延时单元来修复违规。语法格式为:

set_min_delay delay_value [-from from_list] [-through through_list] [-to to_list]
# delay_value:指定最小延时的值,单位由工艺库决定,一般为ns。
# -from:延时约束的起点列表。
# -through:延时路径经过的节点列表。
# -to:延时约束的终点列表。

比如设定从UO的Cp端经单元 U1和U2 的Z端到达 U3 的A端的最小延时为 3.0ns,则命令为:

set_min_delay 3.0 -from [get_pins U0/CP] -through [list UI/Z U2/Z] -to [get_pins U3/A]

时序例外

由于每条路径都有timing_constraints,所以才能进行时序分析,但在某些情况下,有些路径的时序分析没有意义,要想忽略这些路径的分析,就要设定时序例外。
除了前面讲的 set_max_delayset_min_delay 指定的时序例外之外,另有两类时序例外:伪路径多周期路径,分别有set_false_pathset_multicycle_path命令来指定。

伪路径

伪路径也称为虚假路径,指时序分析时不需要关心的路径。DC不能自动识别伪路径,故需要显示指定。set_false_path 命令用于去掉特定路径上时序约束,
对异步逻辑和逻辑上的虚假路径非常有用。语法格式为:

set_false_path [-from from_list] [-through through_list] [-to to_list]
# -from:伪路径的起点列表。
# -through:伪路径经过的节点列表。
# -to:伪路径的终点列表。

比如设定ff1的CP端经单元U1 和U2 的Z端到达ff2的D端的路径为伪路径,则命令为:

dc_ shell-t>set_false_path -from [get_pins ffI/CP] -through [list U1/Z U2/Z] -to [get_pins ff2/D]

如果设计中有多个时钟,那么由一个时钟域 到另一个时钟域之间的路径为伪路径,需要一一标示,可以重复调用 set_false_path 命令,也可以采用如下的脚本命令:

foreach_in_collection clk1 [all_clocks] {foreach_in_collection clk2 [remove_from_collection [all_clocks] [get_clocks $clk1]] {set_false_path -from [get_clocks $clk1] -to [get_clocks $clk2] }
}

多周期路径

多周期路径指两级相邻寄存器之间的组合逻辑延时较大,不能在1个时钟周期完成。因此需要设定为多周期路径,由set_multicycle_path命令完成。语法格式为:

set_multicycle_path path_multiplier [-setup] [-hold] [-from form_list] [-through through_list] [-to to_list]
# path_multiplier:指定路径的时钟周期数。
# -setup:指定该路径针对建立时间检查;
# -hold:指定该路径针对保持时间检查;
# -from:多周期路径的起点列表;
# -through:多周期路径经过的节点列表;
# -to:多周期路径的终点列表。

示例:

上图为多周期路径示意图,比如在上图所示的设计中,时钟周期为10ns,而其中一级加法器的延时近60ns,那么约束方法为:

dc_shell-t>create_clock -period 10 [get clocks clk]
de shell-t>set_multicycle_path 6 -setup -to [get_pins c_reg[*]/D]

3.3 DRC约束

设计规则约束指为保证最终电路可以正常工作,而由工艺库定义的必须遵守的规则,也称隐含约束。一般用于限制在电容、翻转时间、扇出等因素影响,下一个单元可以和多少个其他单元相连,这些规则是必须遵守的,且比其他规则具有更高的优先级。设计规则约束由 set_max_transitionset_max_fanoutset_max_ capacitance组成。(工艺库本身制定了,但是可以根据需求,人为指定,更加严苛或者宽松。)

最大转换时间

约束design中的信号、端口、net最大transition不能超过这个值,当然是越小越严苛了,net的transition time取决于net的负载(fanout),负载越大,transition time越大。

翻转时间是指引脚或端口的电平翻转所需要的时间。工艺库中一般都会给出该值,如果要为特定的端口、设计或时钟组指定特定的翻转时间,可以采用 set_max_transition命令,其语法格式为:

dc_shell-t> set_max_transition transition_value object list
# transition_value: 设定的最大翻转时间。
# object_list    :设定其翻转时间为 transition_value 的对象列表.。

示例:

dc_shell-t> set_max_transition 1.0 [all_designs]
# 本例中设定所有设计的最大翻转时间为1.0ns

最大扇出负载

design,net,output port进行操作,设定的不是具体的电容值扇出负载值是用来表示单元输入引脚相对负载的数目,它并不表示真正的电容负载,而是个无量纲的数字。

扇出负载是指互连线可以驱动的扇出数目,这与容性负载不同。扇出负载没有量纲,在计算时 DC 把一个驱动引脚所连接的所有输入引脚的扇出负载相加,得出该驱动引脚的扇出负载值,并把该值与设定的max_ fan_out相此较。工艺库中设定了扇出负载的默认值,通过set_max_fanout可以进行修改。如果两者不同,综合时会以数值较小,即更严格的值为准

语法格式:

dc_shell-t> set_max_fanout fanout_value object_list
# fanout_value:设定的max_fanout的属性值。
# object_list:设定的 max_fanout 属性为 fanout_value的端口或设计的对象列表。

示例:

dc_shell-t> set_max_fanout 8 [get designs mem_ctrl]
# 设mem_ctrl 的max_fanout为8,则该设计中所有的互连线都被约束。

补充:load vs. fanout_load vs. fanout

  1. load 指互连线上各种容性负载的总和,单位是电容的单位。
  2. fanout_load 是指一个互连线所能驱动的输入引脚的容性负载换算成扇出得到的一个相对值,没有量纲;而且1个输入引脚的容性负载换算成扇出得到的 fanout_load不一定为 1。
  3. fanout则指一个互连线所能驱动的输入引脚的数目。
    命令set_max_fanout 中设定的 fanout_value 指的是 fanoutload。

最大负载电容

max_capacitance属性由命令set_max_capacitance完成。该命令与set_max_transition是相互独立的。

语法格式:

dc_shell-t> set_max_capacitance capacitance_value object_list
# capacitance_value:设定的 max_capacitance属性值。
# object_list :设定的 max_capacitance 属性为 capacitance_value 的端口或设计对象列表。

示例:

dc_shell-t> set LOAD_OF_A [load_of_smic13_ss/NAND2HD2X/A]
dc_shell-t> set_max_capacitance [expr $LOAD_OF_A*10] [all designs]

本例设定所有设计的max_capacitance为 smic13_ss/NAND2HDD2X/A 电容的10倍,即0.0838869,该设计中所有的互连线都被约束。该例中的值可在 DC-Tcl 命令行中直接得到。

3.4 Tcl脚本示例

sh date  # 显示时间
remove_design -designs # 移除DC中原有的设计
################################
#   set library   #
################################
set search_path [lsit ********]
set target_library {tt.db}
set link_library {* tt.db}
set symbol_library {tt.sdb}
################################
#   void warning Info   #
################################
# 屏蔽掉一些无意义的warning信息
suppress_message VER-130
suppress_message VER-129
suppress_message VER-318
suppress_message ELAB-311
suppress_message VER-936
################################
#   read design   #
################################
read_file -format verilog ~/example1.v
#analyze -format verilog ~/example1.v
#elaborate EXAMPLE1
current_design EXAMPLE1 # 指定顶层模块,否则会默认把最后一个读入的module设为top
uniquify
check_design
################################
#   define IO port name   #
################################
set clk [get_ports clk] # 设置变量的clk的值是[get_ports clk],在下面的代码中若出现$clk字样,则表示该变量的值,即用[get_ports clk]代替$clk
set rst_n [get_ports rst_n]
set general_inputs [list a b c]
set outputs [get_ports o]
################################
#   set constraints   #
################################
# 1 set constraints for clock signals
create_clock -n clock $clk -period 20 -waveform {0 10}
set_dont_touch_network [get_clocks clock]
set_drive 0 $clk # 设置时钟端口的驱动为无穷大
set_ideal_network [get_ports clk] # 设置时钟端口为理想网络  这两条设置保证了逻辑综合阶段的时钟是非常理想的(时钟网络不参与综合)
# 2 set constraints for reset signals
set_dont_touch_network $rst_n
set_drive 0 $rst_n
set_ideal_network [get_ports rst_n] # 复位信号同样这样设置,因为复位信号的重要性仅次于时钟信号
# 3 set input delay
set_input_delay -clock clock 8 $general_inputs
# 4 set output delay
set_output_delay -clock clock 8 $outputs
# 5 set design rule constraints
set_max_fanout 4 $general_inputs
set_max_transition 0.5 [get_designs "EXAMPLE1"]
# 6 set area constraint
set_max_area 0 # 在满足时序的条件下,尽可能减小面积

4. 施加环境约束

除了时序的DRC等约束外,电路还有一些其他因素影响电路的延时,如下:

  • 供电电压、外界温度
  • 电平转换时间(transition time) : 输入输出的外围电路的驱动能力和负载大小决定的
  • 电路内部的互连线延时

所以这一部分的约束如下:

4.1 工作条件

工作条件包括温度、电压和工艺参数。晶圆厂提供的单元库中单元延时是在一个标准条件下得到的,比如温度为25℃,工作电压为1.8V,工艺参数为1.0。
一旦工作条件发生了改变,电路的时序特性也必将受到影响。以上三者对时序的影响如下:

晶圆厂在建库的时候,已经考虑到了参数变化的影响,所以在工艺库中提供了几种工作条件模型:最好情况、典型情况、最差情况。
在逻辑综合的时候,一般只考虑最差情况(延时最大,用于建立时间检查)和最好情况(延时最小,用于保持时间检查)。

由于在逻辑综合阶段以最大化建立时间为目标,所以工作条件通常设为最坏情況。对应命令为:set_operating_conditions

dc_shell-t> set_operating_ conditions WORST

若同时指定最好情况和最坏情况,对修正保持时间违例比较有用,但自前一般不推荐使用。

dc_shell-t> set_operating_ conditions -max WORST -min BEST

4.2 输出容性负载

为了准确估计模块输出的时序,除了需要知道输出延时外,还需要知道所接电路的负载情况。如果输出负载过大,会加大电路的transition time,影响时序特性。DC默认的输出负载为0,即相当于不接负载,这样综合出来的电路时序显然过于乐观,不能反应实际工作情况。

使用set_load指令来设定输入负载值,负载值可以是一个具体的值,也可以是工艺库中现有单元的load值。语法格式如下:

dc_shell-t> set_load value objects
# value:设定的容性负载值(非负实数);
# objects:当前设计中设定容性负载的对象列表,包括端口、互连线等。
dc_shell-t> set_load load_of lib/cell/pin

示例:

# 1. 固定值
dc_shell-t> set_load 3 [all_outptus] # 设置所有输出端口的容性负载为 3pf
# 2. 单元load值
# 2.1
dc_shell-t> set_load [load_of my_lib/NAND2HD2X/A] [get_potrs OUT1]
# 2.2 采用 smic13_ss库中NAND2HD2X 的引脚A上的电容的10 倍表示所有输出端口的负载
dc_shell-t> set LOAD_OF_A [load_of my_lib/NAND2HD2X/A]
dc_shell-t> set_load [expr $LOAD_OF_A*10] [all outputs]

4.2 输入驱动强度

为了精确计算输入电路的时序,DC需要知道 input port 的 transition 时间。默认情况下DC假定外部信号的transition time 为 0 ,使用set_driving_cell允许用户可以自行定一个实际的外部驱动cell,可以让DC能够计算一个实际的(non-zero)transition time。

在DC中,驱动强度用电阻值表示,阻值越小表示驱动能力越大,默认情况下DC认为输入端口的驱动电阻阻值为0,即驱动强度无限大。但0值通常用于时钟和复位等扇出很大的端口。对其他端口,为避免这种不切实际的驱动强度,可以采用set_driveset_driving_cell两条命令来设置输入端口的驱动强度。

set_drive

set_drive命令通过直接指定驱动电阻值对输入端口或双向端口设置fall_drive或rise_drive 属性。语法格式为:

set_drive resistance [-rise] [-fall] port_list
# resistance:非负的驱动电阻值,该值越小表示驱动强度越大;
# -rise/-fall :指定是rise_drive属性还是fall_drive属性,如果都不指定,则rise_drive=fall_drive=resistance。
# port_list:驱动强度设置为resistance 的输入端口或双向端口列表。

示例:

dc_shell-t> set_drive 0 [list clk rst_n] # 时钟和复位端口的驱动强度设为无穷大。

set_drive 命令可以和drive_of命令结合使用,比如采用 smicl3_ ss 库中单元IVHID1X的引脚Z的驱动能力表示clkrst_n的驱动能力,其命令为:

dc_shell-t> set_drive [expr [drive_of smic13_ss/IVHD1X/Z] [list clk rst]

若用 smic13_ss库中单元 INVHD1X 的引脚Z的驱动强度的 8倍表示 clk 的驱动强度,则命令为:

dc_shell-t> set_drive [expr [drive_of smic3_ss/INVHDIX/Z]*8] [get_ports clk]

set_driving_cell

set_driving_cell命令对输入端口或双向端口的驱动电阻进行建模,将端口的驱动强度设定为驱动单元(只有一个输出)或驱动单元特定引脚的驱动强度,同时也把驱动单元的设计规则约束应用于待指定驱动强度的端口。语法格式为:

set_driving_cell [-lib_cell lib_cell_name] [-library lib] [-pin pin_name] [-no_design rule] port_list
# -lib_cell:用于驱动设计输入端口的库单元名称。
# -library:lib_cell 所在库的名称,若当前仅读入唯一的目标库且驱动单元就在该库中,则该选项可省略。
# -pin:用于驱动设计输入端口的单元引脚名称,若单元只有一个输出,该项可略去;若有多个输出,但不指定,则DC采用第一个找到的引脚。
# -no_design_rule:该选项要求 DC 忽咯驱动单元引脚上的设计规则。
# port_list:设置驱动强度的输入端口或双向端口列表。

示例1:

dc_shell-t> set_driving_cell -lib_cell and2a0 \[get_ports IN1]

示例2:
用smic13I0_02_line_ss库中单元 PLBI8N 的驱动强度表示所有输入端口的驱动强度,其命令为:

dc_shell-t> set_driving_cell -library smic13I0_02_line_ss -lib_cell PLBI8N [all_inputs]

set_ideal_network

如果设计中包含PAD模块,那么在指定时钟、复位等高扇出端口的驱动能力时,应使set_ideal_network命令,且其强度应施加在 PAD 单元的输出线上。比如,时钟端口经PAD单元RAD_INS送入,PAD_INS的输出引脚连接到互连线PAD_CLK_O上,则其命令设置为:

dc_shell-t> set_ideal_network -no_ propagate [get_nets PAD_INS/PAD_CLK_O]

set_drive命令只对线性延时模型是准确的,而对非线性延时模型不适用,set_driving_cell命令对各种延迟模型都适用,故对时钟、复位外的其他端口设置驱动强度时建议使用 set_driving_cell 命令

4.3 互连线延时

在DC综合的过程中,连线延时是通过设置连线负载模型(wire load model)确定的,连线负载模型基于连线的扇出,估计它的电阻电容等寄生参数,它是也是由Foundry提供的。Foundry根据其他用这个工艺流片的芯片的连线延时进行统计,从而得到这个值。

连线负载模型的标准格式如下:

连线延时的计算是根据连线的扇出,通过查找表计算长度,然后计算电阻和电容。若扇出值超出表中的值(假设为7),那么DC就要根据扇出和长度的斜率(Slope)推算出此时的连线长度。

在每一种工作条件下都会有很多种负载模型,各种负载模型对应不同大小的模块的连线,如上图的模型近似认为是160K门大小的模块适用的。模块越小,它的单位长度的电阻及电容值也越小,负载模型对应的参数也越小。


根据综合后的面积大小,自动选择线负载模型。

具体语法格式:

set_wire_load_model -name model_name [-library lib]
# -name:线负载模型的名称
# -library:包含所指定线负载模型的库名称,若当前读入的目标库唯一则该选项可省略。

4.4 线负载工作方式

前以小节的线负载模型考虑的都是同一模块内部的连线,对于连接不同模块之间的连线,其线负载模型需要通过设定连线负载模式(wireload model mode)来指定。

连线负载模式包括围绕(enclosed)、顶层(top)、分段(segmented)三种。设定指令为:set_wire_load_mode

如下图所示,一根连线连接了B2和B1两个模块,这两个模块都位于TOP下的SUB这个子模块中。

  • 围绕(enclosed):连接B1和B2的连线的负载模型用围绕它们的模块的负载模型代替,即用SUB的负载模型;
  • 顶层(top):用顶层模块的负载模型代替;
  • 分段(segmented ):分别根据穿过的三段的模型相加得到。

4.5 约束检查

在定义完环境属性之后,我们可以使用下面的几个命令检查约束是否施加成功。

  • check_timing:检查设计是否有路径没有加入约束
  • check_design:检查设计中是否有悬空管脚或者输出短接的情况
  • write_script:将施加的约束和属性写出到一个文件中,可以检查这个文件看看是否正确。(该文件很重要,后续的设计的流程都要以该部分内容为时序基准)

5 编译和输出

在完成设计约束、DRC、环境约束之后,就可以进行编译,然后得到逻辑综合的结果和输出文件。
(在编译之前还需要进行一些优化策略的选择,后续在了解这一部分)

编译指令

compile命令进行设计或模块的编译,将HDL代码映射到指定的目标库。其选项可用于设计的映射优化,语法格式为:

compile [-map_effort medium|high]
[-area_effort none|low|medium|high]
[-incremental_mapping]
[-ungroup_all]
[-auto_ungroup area|delay]
[-no_design_rule | -only_design_rule | -only_hold_time]
# -map_effort:综合映射的努力程度,有medium和high两个选项,缺省默认为medium项,缺省为值与 map_ctfort 的值相同。
# -area_effort:综合器面积优化的努力程度,有1ow,medium,high三个选项,缺省默认为medium;
# -incremental_mapping:称为增量编译,指示综合器在前一次综合结果的基础上进一步优化,只用在门级,通常用于改善时序和修正 DRC违规。增量编译时,DC 会进行各种映射优化以改善时序。若只对设计修正DRC,可以加上
# -only_desien_rule 选项;
# -ungroup_all:对设计中除了具有dont_touch属性的设计外全去除层次。
# -auto_ungroup:对设计中的层次结构根据需要自动去除层次。

比如,在初次编译时采用 medium 的映射努力,增量编译时采用high的映射努力,相应命令为:

#1st compile
compile -map_effort medium
#2nd compile
current_design xsoc
compile -incremental -map_effort high

编译时,DC提供了compie_ultra命令,包括许多高级的综合优化算法,可以使关键路径的分析和优化在最短时间内完成。

输出文件内容

以具体脚本为例,介绍输出的具体内容,如下所示:

################################
#   complie_design   #
################################
compile -map_effort medium
################################
#   write *.db and *.v   #
################################
write -f db -hier -output ~/EXAMPLE1.db # 保存整个工程
write -f verilog -hier -output ~/EXAMPLE1netlist.v # 逻辑综合后的网表,用于布局布线和后仿真
write_sdf -version 2.1 ~/EXAMPLE1.sdf # sdf反标文件,标注了使用的标准单元的延时值,后仿真也需要文件
################################
#   generate reports   #
################################
report_area> EXAMPLE!.area_rpt # 面积报告,包括时序电路面积、组合逻辑电路面积、总面积
report_timing> EXAMPLE1.timing_rpt # 时序报告,查看建立时间和保持时间是否满足要求
report_constraint -all_violators> EXAMPLE1.constraint_rpt # 违例报告,逻辑综合过程中没有达到的约束
sh date # 显示时间

时序报告具体内容

时序报告的内容主要包括:表头、数据发射路径、数据捕获路径、时序结果

设计综合(优化)

电路模块设计规划(以利于更好的进行约束),Design Compiler综合优化的过程(三大优化阶段,结构级,逻辑级,门级),时序分析的具体过程等综合过程中的一些详细信息。
(更加具体的优化策略后续再看)

后综合过程

综合完毕该怎么看结果,时序违反该如何解决?这就是后综合过程所要解决的问题。在综合之后,通过分析综合报告,可以得知此次的电路综合结果如何,根据不符合的要求,进行重新约束,甚至重新设计电路。在这个阶段特别值得一提的是综合预估,因为在写综合约束脚本的时候,需要确定约束条件,规格书一般不能够涉及到如此细节的部分,所以需要根据实际电路进行综合预估,这个步骤是在代码编写完之后,与验证同时进行的,目的在于大致估计电路是否符合要求,此时的预综合过程与正式的综合过程是一样的,但要求会宽松许多,时序违反的要求大概为 10%-15%,也就是说电路即使有10%-15%的电路不满足时序也没有关系。

参考资料

芯动力 —— 硬件加速设计方法
EDA12–DC脚本命令(一)

【DC综合】逻辑综合的实施流程相关推荐

  1. DC综合简介及基本流程

    一:首先我们要知道DC综合是用来干什么的. DC综合用一句话概括就是将RTL级描述的电路在工艺.面积.时序等约束下转换为基于工艺库的门级网表.综合包括三个阶段:转换.优化. 1.转换:将RTL级描述转 ...

  2. Tcl与Design Compiler (三)——DC综合的流程

    本文如果有错,欢迎留言更正:此外,转载请标明出处 http://www.cnblogs.com/IClearner/  ,作者:IC_learner 1.基本流程概述 首先给三个图,一个图是高层次设计 ...

  3. Design Compiler - DC综合的流程(三)

    转载文章,来源出处 http://www.cnblogs.com/IClearner/ ,作者:IC_learner ========================================= ...

  4. Design Compiler (三)——DC综合的流程

    1.基本流程概述 首先给三个图,一个图是高层次设计的流程图: 下面是我对这张图的理解: ① 设计之前,准备好库.HDL代码的思想.约束生成:然后根据设计思想用 RTL 源码详细地.完整地为设计建立模型 ...

  5. Tcl与Design Compiler (八)——DC的逻辑综合与优化

    本文如果有错,欢迎留言更正:此外,转载请标明出处 http://www.cnblogs.com/IClearner/  ,作者:IC_learner 对进行时序路径.工作环境.设计规则等进行约束完成之 ...

  6. DC的逻辑综合与优化

    目录 引言 一.DC的综合优化阶段 (1)结构级的优化(Architectural-Level Optimization) ①设计结构的选择(Implementation Selection): ②数 ...

  7. Design Compiler (八)——DC的逻辑综合与优化

    对进行时序路径.工作环境.设计规则等进行约束完成之后,DC就可以进行综合.优化时序了,DC的优化步骤将在下面进行讲解.然而,当普通模式下不能进行优化的,就需要我们进行编写脚本来改进DC的优化来达到时序 ...

  8. DC综合——学习笔记

    DC综合--学习笔记 一.DC综合简介 1.1 什么是综合? 1.2 综合需要的文件 1.3 综合输出的文件 1.4 电路综合的要求 1.4.1 综合脚本的要求 1.4.2 综合结果的要求 二.DC综 ...

  9. DC综合的一些基本概念

    转载:https://www.cnblogs.com/leaftime/archive/2013/08/15/3259156.html 1.1 什么是DC? DC(Design Compiler)是S ...

最新文章

  1. LTE: MIB和SIB,小区选择和重选规则
  2. 产品经理跪求程序员修改需求
  3. C++_泛型编程与标准库(八)
  4. C发展史:KR C/C89/C99/C11 C++发展史: C++98/C++03/C++11
  5. ubuntu远程桌面
  6. sqlite3 外键支持
  7. Android 系统(198)---Android解放双手之Gradle自动化打包实战
  8. 万万没想到,面试中,连 ClassLoader类加载器 也能问出这么多问题.....
  9. boot2源码-事务
  10. gz键盘增强小工具_资深程序员:Python中你不知道的那些小工具
  11. 《计算机网络 自顶向下方法》(第7版)答案(第一章)(一)
  12. python分层抽样_抽样方法—分层抽样
  13. Mac上好用的音乐软件是哪个?MacOS专业音乐制作软件推荐
  14. 为何我的孩子不沉迷网络游戏
  15. 手动释放ubuntu内存
  16. vue综合项目——悦听音乐播放器
  17. 如何删除PDF文件中其中一页?
  18. 工程师的浪漫:用机械臂画一个爱心
  19. python不重复排列组合_python解决排列组合
  20. 走进JavaWeb技术世界7:Tomcat和其他WEB容器的区别

热门文章

  1. 用pip安装指定版本的包遇到的坑
  2. HEVC 参考帧管理(RPS)
  3. PIL获取照片exif 批量修改手机照片名字为拍摄时间
  4. Jetson TX2 power mode功耗模式
  5. 腾讯课堂电脑版麦克风怎么打开
  6. 【图灵机器人】图灵机器人API V2版使用采坑指南
  7. 2015.02.08——张佳莉
  8. python实现录屏录音小工具
  9. Kafka 安装、使用
  10. 程序员就是这样聊天把女朋友聊没的。。。