ASIC设计学习笔记——使用Design Compiler进行综合

文章目录

  • 前言
  • 1. 基本概念
    • 1.1 综合(Synthesis)
    • 1.2 使用Design Compiler进行综合
  • 2. 使用DC进行编译
    • 2.1 进入DC环境
    • 2.2 编译过程
      • 2.2.1 设置搜索路径
      • 2.2.2 库环境设置
      • 2.2.3 编译参数配置
      • 2.2.4 读入设计
      • 2.2.5 编译命令
      • 2.2.6 保存编译结果
        • 2.2.6.1 输出文件格式说明
        • 2.2.6.2 保存报告
    • 2.3 其他常用命令
    • 2.4 完整脚本
  • 4. 可能遇到的问题和解决方案
    • 4.1 Net ‘Q’ or a directly connected net is driven by more than one source,and not all drivers are three-state.(ELAB-366)
    • 4.2 verilog ‘assign’ or ‘tran’ statements are written out(VO-4)
  • 5. 总结
  • 6. 参考文献


前言

综合是ASIC的前端设计中极为重要的步骤,所谓的综合过程,是指将行为级描述的电路、RTL级的电路转换到门级网表的过程。本文介绍使用Synopsys公司的Design Compiler作为工具完成综合的过程。


1. 基本概念

1.1 综合(Synthesis)

在ASIC开发中,当使用verilog等硬件描述语言完成对所需要的功能的代码编写和仿真后,可以使用软件来进行翻译,将HDL描述的行为级代码转换为门级电路。这个转换为门级电路的实现与优化工作就是综合。
下图是一个基本的设计流程框图,其中“Design implementation”就是指综合的过程。
ASIC设计学习笔记——使用Design Compiler进行综合_第1张图片

综合本身的过程包括三个阶段:

  • 转换(translation):这一步是将HDL的描述转换成一个与工艺独立的RTL级网表,网表中RTL模块通过连线互联
  • 映射(mapping):接着根据具体指定的工艺库,将RTL级的网表映射到工艺库上,成为门级网表
  • 优化(optimization):最后根据设计者施加的延时、面积等约束条件,对门级网表进行优化。
    这个过程可以用下图表示:
    ASIC设计学习笔记——使用Design Compiler进行综合_第2张图片

1.2 使用Design Compiler进行综合

使用Design Compiler进行综合的过程和通用的综合过程相同,也包括转换、优化和映射三部分,如下图所示。
ASIC设计学习笔记——使用Design Compiler进行综合_第3张图片

  • 在转换阶段,DC读入HDL文件,使用自带的gtech.db库中的RTL级单元来组成与工艺无关的中间网表,这个过程,也就是使用DC的read_vhdl或read_verilog命令读入设计未见的过程,这一过程中,如果需要引入其他的库,可以通过read_db命令读入,这一过程的中间结果也可以通过write命令写入到一个.db文件中
  • 在优化映射阶段,DC对已有的中间网表进行分析,去掉其中的冗余单元,并对不满足约束条件的路径进行优化,再将优化后的电路映射到芯片制造商提供的工艺库上。这个过程也就是DC的compile命令,其输出可以通过write命令写入到文件中,如.v, .db或者.edif文件。

2. 使用DC进行编译

2.1 进入DC环境

在已经安装好Synopsis的工具链的环境里执行如下命令可以进入dc_shell。

$ dc_shell

如果只是想执行某一个编译脚本,则可以直接运行如下命令执行该tcl脚本:

$ dc_shell -f <script>.tcl

2.2 编译过程

2.2.1 设置搜索路径

  • lappend search_path : 设置查找HDL源码和库文件的目录,其中lappend为添加该目录到搜索路径中。
lappend search_path 
lappend search_path 
lappend search_path 

如果HDL代码中用到`include原语包含其他HDL代码,则编译时也是从search_path中寻找include的文件。因此如果有这样的文件,则也需要将这些文件所在的目录加入到search_path中。

2.2.2 库环境设置

  • link_library:链接库,用于查找HDL代码中引用的各个模块,常用的IP库等都需要加入到链接库中,同时,需要加上“*”,用于表示要链接内存中所有的库,包括之前编译的其他HDL代码生成的子模块等;
  • target_library:synthesis的map阶段需要的实际工艺库,一般由厂商提供,格式为.db文件,厂商有时会提供.lib格式的文件,此时需要使用synopsys提供的library_compiler工具进行转换。
  • synthetic_library:如果不是使用默认的综合库,则需要设置该值,比如对于扩展的DesignWare,需要在synthetic_library中设置,同时需要在link_library中设置相应的库以使得在链接的时候DC可以搜索到相应运算符的实现。
set synthetic_library "dw_foundation.sldb"
set link_library     "*  $synthetic_library"
set target_library ""

2.2.3 编译参数配置

2.2.4 读入设计

有两种方式读入设计:

  • 使用analyze和elabrate两条命令分阶段读取,仅能用于VHDL和verilog。其中:
    • analyze命令用以分析HDL代码,在为设计建立通用库上的逻辑结构前检查设计的错误,并将中间结果存入指定的库中。
    • elaborate命令用于建立设计在GTECH库上的结构级描述,为后续的优化和映射做好准备。
  • 使用read命令直接读取,可以一步完成analyze&elaborate的工作,并且read命令还可以用来读取db、EDIF等格式的设计
set src_list {     \
    top.v            \
    interface.v   \
    reg_map.v   \
    gpio.v          \
    cpu.v           \
}
analyze -format verilog $src_list
elaborate bb_top

2.2.5 编译命令

  • current_design mytop:读入设计后,开始编译前,需要使用current_design命令设置当前设计;
  • uniquify :为设计中的每一个模块产生一个名字唯一的拷贝,可根据每个模块本身特有的环境做优化和映射;
  • link:将读到的DC Memory中的模块连接起来,此时如果出现“unresolved design reference”警告,则不能继续往下,可能是link_library设置错误,或者没有加上"*";
  • compile_ultra:执行编译操作,使用compile_ultra而不是compile命令,compile_ultra会打开一些优化选项,使用一些附加的优化能力,但需要单独的license支持,且编译时间更长。如无其他特殊因素,建议一直使用compile_ultra命令编译。

2.2.6 保存编译结果

2.2.6.1 输出文件格式说明

  • .v文件:以verilog形式保存的门级网表文件
  • .sdf文件:用于仿真时进行时序反标的文件
  • .sdc文件:约束文件,保存有当前设计的约束信息
  • .ddc文件:完整的工程文件,可以通过该文件恢复全部工作环境
  • .svf文件:用于后面的形式验证的映射文件

2.2.6.2 保存报告

  • 使用report_clock命令可以输出时钟信息到文件
  • 使用report_constraint命令可以输出约束信息到文件
  • 使用report_timing命令可以输出时序信息到文件
  • 使用report_disable_timing命令可以输出被disable的时序信息到文件
  • 使用report_area命令可以输出面积信息到文件
  • 使用report_power命令可以输出功耗信息到文件
  • 使用report_qor命令可以输出时序信息到文件

2.3 其他常用命令

  • set_dont_touch:在当前设计和库单元上设置单元格、网格、引用和设计的dont_touch属性,以防止在优化期间修改和替换这些对象;
  • set_wire_load_mode:设置模块间连线负载模式,有三种情况:enclosed、top和segmented;
  • set_wire_load_model:设置模块内部连线模型;
  • compile_seqmap_propagate_constants:默认值为true。控制编译命令是否尝试识别和删除常量寄存器,并且在整个过程中传播常量值。
  • all_fanout:返回指定源扇出中的一组引脚、端口或者单元
  • hdlin_preserve_sequential:在设计中控制复杂的和读取的命令是否保留了卸载的顺序单元
  • sh_continue_on_error:允许脚本出错时继续执行命令
  • sh_source_emits_line_number:指示发出信息的错误消息严重级别,列出该消息发生时的脚本名和行号:E代表只报error;W代表报error和warning
  • set_load:指定端口或者网络上设置的load属性
  • load_of:返回指定端口cell的pin电容
  • set_fix_multiple_port_nets:在当前的设计或设计列表设置固定多路网属性到指定的值
  • report_timing -slack_lesser_than 1 报告小于1ns的时序路径
  • max_path 指定每个路径组报告的路径数
  • nworst 指定每个端点报告的最大路径数,默认为1,只会报告给定端点结束的最坏路径。
  • delay max min 报告路径组中的建立时间和保持时间的关键路径,max为建立时间
  • 用group创建层次,ungroup解除层次关系:
  • 设置面积约束:set_max_area 100 单位面积在不同的工艺库下所指的的一样:以二输入与非门的面积为单位面积、以单个管子所占面积为单位面积、以实际面积1um2为单位面积。在不知道的情况下可以综合一个二输入与非门来看数值,来确定具体所指。
  • 定义时钟:create_clock -period 10 [get_ports clk]
  • set_dont_touch_network [get_clocks clk]
  • 设置输入输出约束:set_input_delay -max 4 -clock clk [get_ports A]
  • set_output_delay -max 4 -clock clk [get_ports B]
  • 检查约束:report_port -verbose 报告当前设计中定义的I/O端口属性和施加的约束
  • report_clock:报告当前设计中定义的时钟及其属性情况
  • reset_design:删除当前设计中所有的属性值和约束(该句命令一般位于脚本第一句)。
  • 移除设计remove_design -design
  • list_libs:列出内存中所有可用的库
  • check_timing:检查是否有路径没有加入约束
  • check_design:检查设计中是否具有悬空的管脚或者输出短接的情况
  • write_script:将施加的约束和属性写出到一个文件内
  • reset_design:
  • 列出命令的开关选项:help -v set_input_delay
  • 集合中删除元素:set all_except_clk [remove_from_collection [all_inputs] [get_ports clk] ]
  • 引入时钟偏差:set_clock_uncertainty 0.5 [get_clocks clk]
  • 时钟源延时:set_clock_latency -source
  • 网络时钟延时:set_clock_latency
  • 布局后综合:set_propagated_clock
  • 同步多时钟:虚拟时钟 creat_clock -period 20 -name CLKA 红色部分必须指定,没有端口或者管脚

2.4 完整脚本

######################################################################
# configurations
set_host_options -max_cores 6
set hdlin_auto_save_templates true   

######################################################################
# set search path for libraries
lappend search_path ../../asic/dc/libraries
lappend search_path ../../srcs/sources_1/rtl/bb
lappend search_path ../../srcs/sources_1/inc/asic
set target_library   "tcbn55lpbwp12ttc_ccs.db"
set link_library     "* tcbn55lpbwp12ttc_ccs.db"

######################################################################
# set source files
set bb_list { \
top.v \
interface.v \
reg_map.v \
}

######################################################################
# read in the design
analyze -format verilog $bb_list
elaborate top
current_design top
uniquify
link

set mydesign "myasic"
set_svf "${mydesign}.svf"

######################################################################
# set constraints
create_clock pclk -period 8.012 -waveform {0.000 4.006}
set_drive 0 pclk
set_dont_touch_network pclk
set_clock_transition 0.01 [get_clocks pclk]
set_clock_uncertainty 0.01 [get_clocks pclk]
set_clock_latency 0 [get_clocks pclk]

create_clock clk_125m -period 8.012 -waveform {0.000 4.006}
set_drive 0 clk_125m
set_dont_touch_network clk_125m
set_clock_transition 0.01 [get_clocks clk_125m]
set_clock_uncertainty 0.01 [get_clocks clk_125m]
set_clock_latency 0 [get_clocks clk_125m]

set_false_path -from [get_clocks pclk] -to [get_clocks clk_125m]
set_false_path -from [get_clocks clk_125m] -to [get_clocks pclk]

set_input_delay 0.01 -clock pclk -rise [get_ports presetn]
set_input_delay 0.01 -clock clk_125m -rise [get_ports rst_n]

set_critical_range 0.10 [current_design]
set_max_fanout 16 bb_top
set_max_transition 0.1 bb_top
set verilogout_no_tri true
set verilogout_equation false
set timing_enable_multiple_clocks_per_reg true

######################################################################
# compile
compile_ultra -incremental -timing_high_effort_script

######################################################################
# write results to files
write -format ddc -hier -o "${mydesign}.ddc"
write -format verilog -hier -o "${mydesign}.v"
write_sdf "${mydesign}.sdf"
write_sdc -version 1.9 -nosplit "${mydesign}.sdc"
report_clock > "clock.txt"
report_timing -transition_time -capacitance -max_path 1000 > "timing.txt"
report_disable_timing > "disable_timing.txt"
report_area > "area.txt"
report_qor > "qor.txt"
report_power > "power.txt"
exit

4. 可能遇到的问题和解决方案

4.1 Net ‘Q’ or a directly connected net is driven by more than one source,and not all drivers are three-state.(ELAB-366)

可能原因和解决方案:

  • 不能在两个always下对同一个变量进行操作,也不能在多个block下进行赋值,比如嵌套的for循环。

4.2 verilog ‘assign’ or ‘tran’ statements are written out(VO-4)

可能原因和解决方案:

  • block的port如果是inout信号,DC会产生tri wire语句和tran原语,因此需要进行下面的设置:
    set verilogout_no_tri=true
  • 当设计中出现同一模块的input port和output port直接相连,需要用如下命令配置:
    set_fix_multiple_port_nets -feedthrough
    set_fix_multiple_port_nets -all -buffer_constants
  • 设计中可能存在dont_touch属性的net,可用如下命令的net的dont_touch移除
    define_name_rules MY_RULES -equal_ports_nets
    change_name -hier -rules MY_RULES -verbose

5. 总结

本文给出DC的综合的实际操作过程,作为实战案例,可以帮助初学者快速入门。

6. 参考文献

  • SYNOPSYS逻辑综合及DESIGNCOMPILER的使用, https://www.freesion.com/article/9064495015/
  • DC命令总结, https://blog.csdn.net/y183128184/article/details/109563386
  • DC学习(时序分析和命令), https://blog.csdn.net/buzhiquxiang/article/details/104848401
  • DC学习(综合与优化), https://blog.csdn.net/buzhiquxiang/article/details/104873055

你可能感兴趣的:(学习,fpga开发)