在前面一章介绍完施加约束之后,接下来要做的工作就是将设计进行综合编译(compile),本文我们将主要讨论综合编译的过程。主要分为这样几个部分:

  • 优化的三个阶段及其特点
  • 编译的策略
  • 编译层次化的设计

一、优化的三个阶段

这一节我们介绍Design Compiler进行优化的三个阶段:结构级、逻辑级以及门级,在不同的阶段,DC运用的方法和优化余地是不一样的,我们将对这几个阶段的特点和优化方法进行一个介绍,这里一起归纳一下,希望能加深认识。

上图是这三个阶段的关系图,可以看到,结构级属于最高的抽象层次,当读入Verilog代码或者没有经过映射的db文件后,DC的优化从这个阶段层次开始,可以说,结构级是优化的最高层次,所以对DC来说,这个层次的综合可以称为高层次综合(High-Level Synthesis)。结构层的下一个优化阶段是逻辑级阶段,也是读入映射过的db文件的DC的初始优化阶段。再往下一个阶段是门级阶段,也是优化的最后阶段,这里所要作的工作主要就是GTECH到工艺库的映射。

1、结构级优化

因为结构级是优化过程中层次最高的一级,因此它也是DC可以采用的优化方法最多的一级,它的主要优化方法如下图所示

1)DesignWare选择

DW选择是结构级优化的一个很主要的特点,在这个阶段DC能够根据设计者施加的时序或者面积的约束在DW的不同实现方式中找到它认为最佳的实现方案。比如加法器的实现方式一共有如下几种

其中DW Foundation需要有专门的license,而且使用之前还要设置综合库(synthetic library)。

2)共享子表达式(Sub-Expressions)

这里的子表达式主要是指数学表达式,比如下面这个例子,如果按照原来的语句综合,会包含6各加法器,但是如果表达式之间的公共项提取出来,便可以大大的减小面积,如下图

如果要直接综合出共享后的电路,可以在编写RTL代码的时候强制指定共享项:

3)资源共享(Resource Sharing)

资源共享的原理与共享子表达式类似,只不过这里指的所谓资源是一些HDL的运算符和表达式,比如加(+)、减(-)、乘(*)、除(/)以及大于(>)、大于等于(>=)、小于(<)、小于等于(<=)。比如给定一个语句

DC会根据具体的约束条件综合出最符合要求的结构来。

4)运算符排序(Operator Reordering)

对于下面这个表达式Z <= A + B + C + D(输出Z是施加了一定时序约束),DC最初是按照从左至右的顺序计算的,也就是说它最初的排序如下

如果几个输入信号到达的时间相同,DC会通过运算符排序优化成下图的平衡的结构,减小延时:

如果A信号较迟到达,则综合出的电路结构会如下 :

2、逻辑级优化

在经过结构级优化之后,电路被转化成了工艺无关的GTECH库的形式,这级也称为逻辑级,对于逻辑级优化来说,只有一个方法,那就是——结构化 (structure)或者扁平化(flatten)。

1)结构化(structure)

结构化是DC在逻辑级的默认的优化方法,它是指:使用电路的一些中间项构成一个多级的电路结构。如下图的电路一共有三级逻辑,下一级的输入是上一级的输出,使用这种优化方法一般情况下能综合出兼顾时序和面积的电路来。

结构化电路的典型是奇偶校验电路。

2)扁平化(flatten)

扁平化是将所有的组合逻辑打平成乘积项和(SOP)的两级结构,类似与可编程阵列逻辑(PAL)。使用这种结构的特点由于没有利用中间项,综合后电路面积将会变得很大,但是却不一定能取得较好的时序。

扁平化结构的电路和设置扁平化的DC命令如下所示:

dc_shell > set_flatten true -effort low | medium | high

综合结构化和扁平化的特点,可以归纳如下:

由于DC默认是用结构化的方式综合逻辑级电路,而且这种方式可以得到兼顾时序和面积的结果,因此我们可以先用这种(结构化)方式优化。在优化后的电路中找出关键路径,看看关键路径上有没有符合使用SOP电路的模块,再将这些方便使用SOP的模块set_flatten,以便取得最佳的效果。

3、门级优化

门级优化是优化的最后阶段,它所要完成的任务就是将GTECH的电路映射到最终的工艺库中,并且保证映射后的电路不违反设计规则(Design Rule)。

1)工艺映射

工艺映射包括组合逻辑映射时序逻辑映射。组合逻辑映射是指DC使用工艺库中的各种门替换GTECH单元,并选择能实现相同逻辑的符合时序及面积要求的单元。

时序逻辑映射的方法和组合逻辑相类似,也是出于速度和面积的考虑,尽量使用复杂的时序单元吸收一部分组合逻辑。

2)设计规则检查(DRC)

对于工艺库的单元而言,Foundry都指定了每个单元的工作条件的限制,比如最大电容(max_capacitance)等等,这些限制也可以称为设计规则(Design Rule),在设计规则限定的范围内,Foundry提供的参数才有实际的意义。比如一个单元允许的最大电容为5pf,而实际工作电路中出现的电容值为10pf,那么这时,便违反了设计规则,单元的参数也就不能确保是准确的了。

因此,DC在作门级优化的时候,在映射的过程中也会检查电路的设计规则,一般的做法是在单元中插入buffer增加驱动能力,或者将小驱动的单元替换为大单元。设计规则检查分为两个过程——DRC I 和DRC II 。

DRC I是指Design Compiler在不影响电路的时序和面积的前提下修正违反规则的一些单元,如果在这个前提下不能完全修正,则要进行下一步的检查,即DRC II,这一步的修正必然是以牺牲一部分时序和面积为代价的。

二、编译策略

编译过程是指设计经过三个阶段的优化,最终形成门级网表的过程,在这一节里,我们主要就编译的策略,它包含如下几方面的内容——

  • 中断编译的方法
  • 从报告中检查时序,调整策略
  • 修正保持时间违反(Hold time violations)

1、中断编译的方法

在DC-Tcl的界面下,当我们键入compile命令时,DC就开始了编译,也就是优化的过程。优化是在设计规则的条件下,运用不同的算法,综合最终出满足时序和面积的电路。优化首先是时序驱动(timing-driven)的一个过程,其次再是面积。如果找到了一个满足时序和面积等约束的电路,编译将会停止;如果通过种种编译仍不能满足时序,编译也会停止下来;另外,我们也可以人为的中断编译。

人为中断编译的方法是键入Ctrl-C,经过一段时间的等待后(有可能时间会很长),优化过程暂停,并弹出如下菜单:

这里有四个选项,设计者可以根据情况作出选择。

DC在编译的过程中,会自动打印出一个报表,报告编译的总时间,设计的面积,关键路径的时序违反和总共时序违反情况,我们可以根据需要更改打印的列项目:

2、分析报告,调整策略

一般情况下,我们先作一个默认的编译,这样一般可以取得既快又准确的结果,然后在编译完成后使用一些报告时序的命令,并分析它们的输出结果,使用的命令主要有

从这些报告中,我们可以看到电路中是否有违反的约束,如果有,那么它是什么类型,还有电路中的最大负裕量(worst negative slack)是多少,等等。下面我们就几个常见的约束违反情况,谈谈纠正它的综合策略

1)较大的时序违例

以下图为例

从report_constraint –all这个命令的报告可以看出,需要到达的时间是1.20ns,而实际到达为2.84ns,违反了1.64ns。之所以判断它是一个较大时序违反的情况,并不是因为1.64这个绝对值很大,而是相比较需要时间而言,1.64是一个较大的值。一般而言,如果电路中的最大负裕量(简称WNS)所占时钟周期的15%以上的话,可以认为电路存在较大的时序违反

确认存在较大时序违反之后,下一步就是找出原因,消除违反情况。可供参考的步骤有下面几种:

  1. 检查约束条件,看是否有疏漏或错误
  2. 检查模块划分,看组合逻辑是否穿过多个模块
  3. 重新编译优化后的网表
  4. 修改RTL代码

重新编译(Re-Compile)

        当重新读入映射后的网表进行重新编译时,DC会自动将门级的网表重新返回到GTECH的结构,相当于逻辑级。然后分别进行逻辑级和门级的优化,但是同时也可以进行DesignWare的替换。

如果设计者仅仅将映射后的网表拿来再做一次compile,编译后的结果并不会不一定会比原来的好,无非把以前做过的优化再跑一遍。因此,重新编译之前会改变一些参数,如——改变设计约束、改变set_structure和set_flatten参数以及改变编译的map_effort

改变map_effort重新编译

        对设计进行编译的时候,有三种编译级别可以选择,它们分别时低级、中级和高级。

dc_shell > compile -map_effort low | medium | high

不同的级别编译要求的编译时间和编译结果都各不相同,compile –map_effort low编译时间最短,但是结果不一定好,它一般用于设计预估(Design Exploration),不用在重新编译环节。
compile –map_effort medium是DC默认的编译级别,大多能在一定的时间内得到较为满意的结果。这也是我们推荐的初始编译级别。

compile –map_effort high 编译的过程中会使用前面的级别中没有的算法,因此它所要求的时间是最多的,结果也是相对最好的。这种级别一般用在重新编译的阶段。

修改RTL代码

        修改源代码所能取得的效果是最直接的,同时也是代价最高的。修改代码后,DC会从最上层的结构级开始优化,前面也讨论过,越上层次的优化方法越多。所以通常这样得到的结果也越满意。但是,修改代码也不一定放之四海皆准的方法,因此并不是所有的设计我们都能获得源代码,同时也不是可以随便修改的。

2)较小的时序违例

以下图为例

从上图看出,相比较1.20的允许路径延时,0.10的负最大裕量(WNS)是比较小的(小于15%),而且已经认定了约束和模块划分都是正确的,那么应该怎样修复这个错误呢?

这里主要讲一下Incremental Mapping:

dc_shell > compile -incremental_mapping

这个开关告诉DC,在重新编译的时候不需要把网表返回到GTECH结构,因此也不需要作逻辑级优化,速度也较一般的编译更省时间。这里DC所要作的是进行门级单元的替换,即在不违反设计规则的情况下用延时小的单元替换延时较大的单元。另外,如果读入的是db格式的网表,在这个阶段也可以进行DesignWare的替换。

如果要同时优化多条路径,需要使用另外一个命令——set_critical_range。这个命令设置的critical_range是以WNS的值为基准的,优化的是和这个值的绝对值差设置值的那些路径。因此,如果设置值为0,那么就仅仅优化一条关键路径。

dc_shell > set_critical_range 2 [current_design]

3)设计规则违反

有些时候的时序违反是由于设计规则违反引起的,比如说一个单元的扇出(fanout)过大,导致它的transition time的时间迅速增加。对于这种情况,我们可以通过

dc_shell > report_net -connections -verbose

dc_shell > report_timing -net

两个命令审查连线的连接和负载情况。

要修正设计规则的错误,可以使用一个编译的开关:

dc_shell > compile -only_design_rule

如下面这个例子,为了满足最大电容的规则,在A端口的内部加上了一个buffer,用于缓冲N路径对A的负载。

3、修正保持时间违例

一个时序电路要想正常工作,除了必须满足建立时间要求之外,也需要满足保持时间要求。虽然保持时间检查和建立时间检查是同样重要的,但是我们在实际综合的过程中却不是把它们同时考虑,而是更多的把保持时间的检查放到布局后。这是因为

  • 时钟偏移必须要到布局完成后才能得到准确值
  • 修正保持时间的通常做法是插入buffer,而这可能会增加建立时间违反的可能性,并且增大了组合电路的面积
  • 保持时间检查用的一般都是电路工作的最佳条件,而在这个条件下,连线延时往往是被忽略的,连线延时也是必须在布局后才准确。

如果确定要同时作建立和保持时间检查,那么在施加电路约束的时候要加入相应的开关,如:

以及设置各自的工艺库——

默认情况下,DC不修正保持时间的违反。如果确定要作修正,需要先设置一个变量再作检查 :

dc_shell > set_fix_hold [all clocks]

dc_shell > compile -only_design_rule

加上only_design_rule的开关后,编译过程中仅仅更换单元大小,并增加buffer,以便修正设计规则违反和保持时间违反。

三、层次化设计的编译

一个层次化设计的编译过程包含两个阶段:1、将所有的子模块映射到门级,2、优化。

在一个层次化的设计中,我们可能会遇到下面这种情况

上图中,被综合的模块中D_design中含有三个子模块U1、U2和U3,其中U1和U3都是由模块Ades例化而来,这里的Ades称为多次例化的模块。对于这样一个设计,在compile之前使用check_design作检查的时候会报一个warning,即设计中存在多次例化的模块(multiple instantiations),如果在这种情况下,我们不考虑多次例化的模块(Ades),那么在继续的compile时候程序会终止退出。因此,必须对它进行处理,这里我们介绍两种方法——uniquify和compile + dont_touch。

1、uniquify

使用uniquify,DC会对每个例化的模块作一份拷贝,然后对它们分别取一个名字,即把不同的例化模块当作不同的两个模块处理。

注意看上图,U1和U3两个模块的设计名分别由原来的Ades变成了Ades_0和Ades_1,因此在编译时,DC会将它们当作两个不同的模块,这样就可以根据它们不同的周围环境作优化。

使用uniquify的具体实现方法如下

dc_shell > uniquify

dc_shell > compile

2、compile + dont_touch

这种方法先将多次例化的模块作单独的约束和编译,然后在整合到上一级模块的过程中将它的属性设置为dont_touch,再编译。

上图中,U1和U3两个模块的设计名都没有变化,只是在编译D_design之前先将Ades编译一次。这样U1和U3实际上是一模一样的模块。

compile+dont_touch的实现方法如下

这里的约束文件有两个,一个是Ades的Aconstraints.tcl,另一个是D_design的Dconstraints.tcl,并且在source后一个约束文件之前要对编译过的Ades设置成dont_touch。
在设置了dont_touch属性之后,编译D_design的时候就会忽略Ades,这样有好处也有坏处,好处是可以保护模块不被修改,但是这样同时也限制了DC对U1和U3的进一步的优化。

3、uniquify Vs compile + dont_touch

通过对上述两种方法的介绍,我们不难看出它们各自的优缺点——

compile+dont_touch由于只需要对多次例化的模块编译一次,因此可以减少整个设计的编译时间,也可以减少内存的使用量。在多次例化的模块很复杂并且工作站的硬件条件有限的情况下,使用这种方法的优越性的比较明显的。还有,如果这个Ades是一个第三方提供的硬核(hard-core),那么我们也只能使用这种方法。

使用这种方法的缺陷也是显而易见的:由于顶层模块在编译的时候Ades设置了dont_touch,这就妨碍了DC针对Ades的各个实例周围环境的不同的进一步优化,从而使得结果不能真实的反映各个实例周围的环境变化。

uniquify由于把各个多例化模块作为独立的模块来看,因此DC可以分别针对它们作出更好的优化,从而得到的结果也是比较理想的。缺点就是编译的时间稍微较长,但是对于一些不大的模块来说,这些是可以忽略的。

正因为uniquify可以综合出更好的结果,所以如果一般推荐使用uniquify解决多例化模块的综合问题

Design Compiler指南——设计综合过程相关推荐

  1. Design Compiler指南——后综合过程

    本文我们着重讨论使用Design Compiler综合大型设计时要注意的一些问题,比如怎样调整综合方法,出现约束违反后怎样修正,怎样给不同的子模块作时序和负载预算,以及给整个设计在具体综合之前先作一个 ...

  2. Design Compiler指南——预综合过程

    预综合过程是指在综合过程之前的一些为综合作准备的步骤,包括Design Compiler的启动.设置各种库文件.创建启动脚本文件.读入设计文件.DC中的设计对象.各种模块的划分以及Verilog的编码 ...

  3. Design Compiler指南——概述和基本流程

    综合是前端模块设计中的重要步骤之一,综合的过程是将行为描述的电路.RTL级的电路转换到门级的过程:Design Compiler是Synopsys公司用于做电路综合的核心工具,它可以方便地将HDL语言 ...

  4. Design Compiler指南——施加设计约束

    Design Compiler是一个约束驱动(constrain-driven)的综合工具,它的结果是与设计者施加的约束条件密切相关的.在本文里,我们主要讨论怎样给电路施加约束条件,这些约束主要包括- ...

  5. IC Compiler指南——数据准备

    一.概述 ICC数据设置的文件关系框图如图: 后端工具在数据设置阶段需要对两大类数据进行设置,包括从前端设计继承的综合数据 以及后端设计需要的物理数据. 综合数据主要包括前端逻辑综合已经设置过的逻辑与 ...

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

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

  7. Design Compiler初体验

    安装VCS之后,在装DC果然顺手很多啊! 不过关于VCS的安装,还没有补给大家!尽快的! 不过现在很想和Synopsys的其它软件安装一个补给大家!   安装版本DC2009 安装环境RED HAT5 ...

  8. 逻辑综合重点解析(Design Compiler篇)

    前言 本文摘录自微信公众号 "数字芯片实验室" 欢迎关注 1.逻辑综合(Logic Synthesis)分为哪三个步骤? 逻辑综合的行为是将数字电路的寄存器传输级描述(RTL,Re ...

  9. Synopsys Design Compiler基础

    目录 引言 综合环境 启动文件 系统库变量 DC设计对象.变量和属性 对象 变量 属性 找寻设计对象 数据组织 引言 Synopsys Design Compiler (DC) 和 Design Vi ...

最新文章

  1. 802.1x 客户端获取ip过程 很详细
  2. java 线程分配_Java多线程原子引用分配
  3. 编程之美-从无头单链表中删除节点方法整理
  4. 35岁以前把下面十件事做好
  5. Android安全笔记-Service基本概念
  6. java常用的日期类介绍
  7. tcp测试监听工具_linux 下两款网络性能测试工具介绍
  8. 【实习】T100开发学习笔记
  9. samba 开通_LINUX开启SAMBA服务
  10. Spring4-@PostConstruct和@PreDestroy注解的使用
  11. 74cms前台getshell漏洞
  12. Windows安装mysql8并设置开机自启动
  13. CocosCreator实现不规则的点击区域监听
  14. linux 繁体中文转为简体,linux - 安装OpenCC(简体繁体转换)
  15. php elasticsearch更新文档
  16. saltstack-本地安装rpm方式
  17. 视频分析(MATLAB)——MV分镜头图像分类
  18. 交换机和猫、路由器到底有什么区别?
  19. 在线图片转成html,在线将JPEG 转换成HTML。 免费将.jpeg 转换成.html。
  20. 不同频率的晶振在电子产品中有什么作用?

热门文章

  1. 微信浏览器取消缓存的方法
  2. 【Silverlight】解决DataTemplate绑定附加属性
  3. Hbase 各个角色的工作。
  4. ARP协议,以及ARP欺骗
  5. vue问题四:富文本编辑器上传图片
  6. python基础知识-列表,元组,字典
  7. 向上弹出菜单jQuery插件
  8. 学习File API用于前端读取文件
  9. egg --- 初始化一个egg项目基本结构说明
  10. node --- 模块化连接MongoDB数据库的参数设置方案之一