Professional Documents
Culture Documents
Design Compiler理论与实战
Design Compiler理论与实战
一、前言
已经学习 DC 的使用有一段时间了,在学习期间,参考了一些书,写了一些总结。
我也不把总结藏着掖着了,记录在博客园里面,一方面是记录自己的学习记录,
另一方面是分享给大家,希望大家能够得到帮助。参考的书籍有很多,大概如下:
虞希清老师的《专用集成电路设计实用教程》
西电出版社的《数字 IC 系统设计》
好像还有《SoC 设计方法与实现》《数字集成电路设计与技术》
DC 工作流程主要分为这三步:
就是把路径调整一下,门给改一下等等。
多丰富的信息,比如映射的门电路信息与网表、.v 格式的网表、延时信息(sdf)、
网表文件是实际意义的网表文件,而.v 这个形式的网表问价是用来做后仿真
的文件。
延时信息的得出:线负载模型、拓扑结构模型(现在)。
2、DC 的启动方式
启动 DC 的方式有三种:
能用这种方式)。
启动方式是:$design_vision
我们可以通过 man design_vision 或者 design_vision -help 来查看 DC
的启动选项:
关于什么是拓扑模式,为什么要启动拓扑模式,后面会有相关的叙述。
此外,还有下面的启动方式:
dc_shell: DC 以命令行的格式启动:$dc_shell
不过我们可以发现,这些选项是一致的,是告诉我们如何启动 DC,启动 DC
的时候可以加载哪些选项。
本写进去以后,DC 读取才真正工作。而这种批处理模式是,在启动的同时,
告诉 DC 执行哪些脚本,例如:
动信息,进而排除错误。
本教程这三种方式在后面都有流程介绍,本教程以命令行和批处理为主,其
设计的主要操作方式。
3、DC-Tcl 语言的基本结构
Tcl 的语法比较简单,依葫芦画瓢就可以知道写的是什么了。
设置变量
example.tcl 的内容为:
的值.
if-else 语句:
与 C 语言、Verilog 语言不一样,这里的条件是用大括号{}来进行包括的,
然后要执行的内容也是通过{}来表示的。特别注意,{}的使用都有空格间隔开
检查没有错误,进行执行:
switch 结构
puts 也是显示/打印的命令,执行后的结果如下:
还可以添加默认的选项:
执行后,显示:
while 循环
执行的结果如下:
for 循环
运行的结果如下所示:
for 循环的格式跟 C 语言一样,也有三个选项,初始条件,停止循环条件,
变量递增选项。
Continue 跟 C 语言一样,不执行本次循环。
数组(列表)与数组(列表)的遍历
的内容有 5 项。
附注:foreach_incollection 对物集(collection)遍历。关于物集这个概
念在后面会有说到,这里先提及一下,有一个初步印象。
执行结果如下:
子程序的定义和调用:
最后是文件的处理:文件的读写
执行的结果如下所示:
命令,比如说自己的函数、错误处理、正则表达式等,此外还要结合 DC 的
命令,总之就是具体问题具体分析。
三、DC 综合流程
1、基本流程概述
首先给三个图,一个图是高层次设计的流程图:
下面是我对这张图的理解:
1. 设计之前,准备好库、HDL 代码的思想、约束生成;然后根据设计思想
用 RTL 源码详细地、完整地为设计建立模型、定义设计中寄存器结构和
数目、定义设计中的组合电路功能、定义设计中寄存器时钟等等的设计
规格和实现。
2. 完成 RTL 源码设计之后,应让设计开发与功能仿真并行进行:
在设计开发阶段,我们使用 DC 来实现特定的设计目标(设计规则和
优化约束),以及执行默认选项的初步综合。
如果设计开发结果未能在 10%的偏差范围内满足时序目标,则需要
修正 HDL 代码,然后重复设计开发和功能验证的过程。
在功能仿真中,通过特定的工具来确定设计是否能按如所需的功能工
作。
如果设计未能满足功能要求, 我们必须修改设计代码以及重复设计
开发和功能仿真。继续设计开发和功能仿真直至设计功能正确及满
足小于 10%偏差的时序目标。
3. 使用 DC 完成设计的综合并满足设计目标.这个过程包括三个步骤,即综
然后设计的约束对电路进行逻辑综合和优化,使电路能满足设计的目标
或者约束,最后使用目标工艺库的逻辑单元映射成门级网表,在将设计
综合成门级网表之后,要验证此时的设计是否满足设计目标.如果不能满
足设计目标,此时需要产生及分析报告确定问题及解决问题
4. 当设计满足功能、时序以及其他的设计目标的时候,需要执行物理层设计
最后分析物理层设计的性能,也就是使用 DC 的拓扑模式,加入
floorplan 的物理信息后进行综合分析设计的性能。如果结果未能满足
设计目标,应返回第三步.如果满足设计目标,则本部分设计周期完成.
一个图是 DC 在设计流程中的位置:
这个图将上面的流程图细化,着重与 DC 的部分,描述了使用 DC 进行逻辑综合
时要做的事,同时,也是对前面的流程图解说的图形概述。在综合的时候,首先
最后一个图是,使用 DC 进行基本的逻辑综合的流程图与相应的命令:
这个图给出了使用 DC 进行逻辑综合时的基本步骤,我们根据这个图运行 DC,
下面是这个图的具体解说:
2 指定库文件,需要指定的库文件包括:
综合库(synthetic library)下面是库的解释,具体的解释在后面有说,这里先
Target library
Link library
具体内容,后面会专门进行说明。
Symbol library
Synthetic library
Create_mw_lib
设计的读入过程是将设计文件载入内存,并将其转换为 DC 的中间格式,
即 GTECH 格式,GTECH 格式由“soft macros” 如 adders,
种组件具有多种结构。
二者在使用中的区别:
设计。
定义对象包括工艺参数(温度、电压等),I/O 端口属性(负载、驱动、
设计约束包括设计规则约束和优化约束,设计规则约束(design rule
constraint)由工艺库决定,在设计编译过程中必须满足,用于使电路
能按功能要求正常工作。设计优化约束定义了 DC 要达到的时序和面积
优化目标,该约束由用户指定,DC 在不违反设计规则约束的前提下,
遵循此约束综合设计。
有的环境和约束设置针对顶层设计,虽然此种策略自动考虑到相关的内
防止在之后的编译过程中被修改,所有同层子设计编译完成后,再编译
之上的父设计,直至顶层设计编译完成。Bottom-up 策略允许大规模设
计,因为该策略不需要所有设计同时驻入内存。
用 Compile 命令执行综合与优化过程,还可以利用一些选项指导编译和
优化过程。
8 分析及解决设计中存在的问题 -
DC 可以产生一些报告以反应设计的综合和优化结果,如:时序、面积、
约束等报告,这些报告有助于分析和解决设计中存在的问题以改善综合
DC 不会自动存储综合后的设计结果,因而需要在离开 DC 时手动存储
设计数据。比如存储网表、延时信息等数据文件。
2、实战
在这里,我们将实战一下,做一下实验,让大家体验一下流程:
首先准备好文件:
TOP.con 文件是需要我们书写的,这里已经写好了,我们来看一下就好了。
.synopsys_dc.setup 的内容:
common_setup.tcl 文件定义了库的名字和名称,上面是逻辑库,下面物理
库:
5 行:定义库的搜索路径,当找不到库时,从这个路径中寻找
10 行:定义图形库变量
15 行:定义顶层设计库的变量名称
17 行:定义 milkyway(参考)库(的位置)
19 行:定义工艺库(的位置)
21 行:定义寄生参数库(的位置)
23 行:定义工艺库和寄生参数库的映射关系库(的位置)
dc_setup.tcl 的内容:
dc_setup.tcl 文件就是指定库了,而不是单单地定义了,set_app_var 是定
义 DC 内部变量,4~7 这是指定搜索路径个各种库的路径和名称
下面的物理库设置中:
13 行:指定 milkyway(参考)库的名称
14 行:指定当前设计的库的名称
19 行:打开当前的设计库
20 行:加载寄生参数(库)
启动 DC
这里是流程演示,因此我们使用图形化的方式启动:
design_vision -topo
读入设计前的检查
-->检查库是否正确设置:
-->检查逻辑库和物理库的一致性:
Check_library
检查可能不会通过,结果不影响综合的话,可以忽略
-->检查寄生参数文件和工艺库文件的一致性:(物理综合的时候需要检查)
check_tlu_plus_files
通过的话会有三个 passed
读入设计和查看设计
-->读入设计:
用法如下所示:
-->设置当前设计
要综合哪个模块,就把哪个模块设置为当前设计;
查看当前设计:current_design
设置当前设计:current_design TOP
-->link 设计
Link 设计,查看当前要综合的设计是否缺少子模块:
link
返回值是 1,说明子模块完整
然后 list_libs 是查看库和库的路径,这个命令也可以检查是否读入了对应的
约束设计(也就是上面流程图中的各种 set)
我们通过执行约束文件来约束设计:
source TOP.con
其他选项我们在后面会叙述,我们这里只说一下 5 行的 reset_design,这个就
是剔除之前所有的约束,防止影响下面的约束。
进行综合
Compile_ultra(这是在拓扑模式下进行综合的命令)
综合后的检查
report_timing (查看时序报告)
report_are (查看面积情况)
保存综合后的设计
总结,大概的流程为:
准备好文件—>启动 DC—>读入设计前的检查—>读入设计和查看设计—>
约束设计—>综合—>综合后检查(与优化)—>保存优化后的设计
四、DC 启动环境的设置
主要内容有:
启动环境的概述
路径变量的定义与解释
库的指定与解释
1、启动环境配置简述
DC 的启动环境,也就是那些库的设定。配置 DC 的启动环境主要
它配置了 DC 启动过程中要执行哪些命令、干哪些事。其中,search_path 、
target_library...等等(后面会讲,放在这里给大家留个印象),这些是 DC
内部的变量名称,用来告诉 DC 做那些事的方法。
一般.synopsys_dc.setup 文件有三个:
2 一个在用户目录下,这个文件没事也不要动他;
3 还有一个当前工作目录下,也就是启动 DC 的目录下(没有就需要
自己创建),这个是要我们自己写的,这个想怎么动就怎么动。我们配置
DC 的启动环境,就是在启动的目录创建.synopsys_dc.setup 并且修改它。
此外,这个文件名字不能随意更改,按照默认的名字来,DC 在启动的过程
中会自动读取各个名字的文件。(如果改变了它的名字,就需要通过 source
命令 source 一下)。
2、.synopsys_dc.setup 配置文件的书写
如下图所示,一般设计的的目录文件夹管理:
合时的信息。进入综合文件夹:
有 5 个文件夹,mapped 是存放综合完成之后的文件的目录,这些文件是经
过综合库映射的。Unmaped 是存放综合时没有经过工艺库映射所得到的文
这个目录里面,我们要进行创建.synopsys_dc.setup 文件并且编写这个文件:
文件的内容主要是指定这个四个库(的名称和路径):
当然这个不是这个文件的全部内容,这个文件的全部内容如下(后面有这个
文件内容的讲解):
3、.synopsys_dc.setup 的讲解
都是在终端打印相应的信息而已,提供我们判断 DC 是否按照我们设定的环
境进行启动以及启动到哪一步。“#”开头的是注释部分。31 行(包括 31
设置库的时候,就可以使用这些变量,而不是用长长的路径了,同时也让别
人了解你这个路径是什么意思。依次定义:
①设计目录(SYN_ROOT_PATH)的路径:也就是你的总的设计路径,在这
个路径下面进行仿真、综合、形式验证等等的操作。
③配置文件的路径(CONFIG_PATH):放置 DC 的一些配置文件,这里的
设计没有任何的配置文件,因此没有进行设置。
④脚本路径(SCRIPT_PATH):放置约束脚本的路径。
⑤未映射文件的路径(UNMAPPED_PATH):放置 DC 没有用工艺库进行
⑥映射后的文件的路径(MAPPED_PATH):放置 DC 最终优化后得到的结
⑦放置报告的路径(REPORT_PATH):放置 DC 运行过程中的一些报告,比
如启动报告,使用约束脚本运行中的报告,时序报告、面积报告等,通过查
阅这些报告,分析 DC 是否按照我们预料中的情况进行启动、运行,分析设
计是否满足要求等。
作时的路径。
了,这个是 DC 内部命令格式,指定设计和库的工作路径。
库的路径,至于什么是符号库,前面也有解说了。关联一些图形化库,使用
GUI 界面的时候,就可以看到综合得到的门级网表的图形化界面。否则看不
到。
由于我用的是台积电 90 纳米的库,图形化符号库及其路径如下图所示:
第一个就是库的路径看,后面那个是库的名称;由于我们需要定义的是库的
路径,因此自然是写路径,而不是写库的名字。
具体信息,后面会进行讲解。我的库的路径和名称如下:
肯定都 OK 了的。
此这里就要强调一下:
set : 自己自定义的一些变量,方便定义系统变量的时候,不用那么麻烦;主
要是定义。
定有:search_path、synthetic_library、target_library、link_library、
symbol_library 以及其他的一些命令开关等。
当定义完这些“自定义”的变量之后,我们就要做一些正经事了,就是指定
DC 要用到的库了。
⑩③指定搜索路径(Search_path):当读入了一些工艺库时,忘了设置它
些路径进行寻找相关的库文件;或者,当需要多个.v 文件时,通过这个变量
加换行符\,而且\后面不能有空格),list 是列表的意思,意思是这个
search_path 有多个(路径)变量,第一个路径变量搜索不到(库或者需要
的文件),可以从下一个路径中找;中间的 . 的意思好像是当前目录。
接下来就是指定库文件了。在前面粗略地说了一下各个库的意思,下面在介
绍指定库的同时,也接收这些库在 DC 中的作用,但是库里面的具体内容不
在下面说明,将在后面进行介绍。
此外,当需要用到这个库的一些比较高端的 IP 核的时候,是需要相关的证
书的。
例如当你在代码中用来“*”或者“+”这操作,那么 DC 会通过这个你指定
的综合库进行映射或者优化这些操作符(就是翻译成门电路)。这个库非必
须指定。在这些库的名称如下所
际的门级电路时所需要的标准单元库。这个库指定为半导体制造商提供的工
艺库。库里面的具体内容后面详细说明。这里指定的就是库的名字。
附注:启动 DC 之后,可以通过 printvar target_library 查看工艺库名称。
⑩⑥指定链接库(link_library):这里指定的就是库的名字了,链接库可以
从下面几点理解:
层模块设计(比如 IP 核)。作用是:用于分辨电路中逻辑门和子模块的功
能,然后用实际的库单元或者子模块代替它们;在由上而下的综合工程中,
接起来,因此当读入的文件是门级网表(比如用到了 IP 核的网表)时,需
网表中门单元电路的功能而报错。
设为 link_library,而将单元综合库 B 设为 target_library,重新映射一下就
可以了。
路径面前加*号表示开辟一块单独的内存空间给 DC 自己使用,然后先搜寻
到内存里;这时 DC 在进行综合的时候,发现缺少某个东西,于是就先从库
a 里面找,找不到时就会从列表里面的变量路径中找)。
一般情况下,我们只用一个工艺库,需要引用目标工艺库,因此指定
⑩⑦最后是指定图形化符号库(symbol_library):这里指定的就是库的名字了,
这个前面说得比较详细了,这里不再重述。
防止后端工程师拿到的网表中带一些奇怪的符号从而引起不必要的错误。
注意:
·库的指定只需要指定 target_library、link_library,其他的可以不指定;
·上面的库设置仅仅适用于逻辑综合,也就是非拓扑模式下的综合;拓扑模
式下,需要使用到物理库,或者相关的物理布局等信息;对于拓扑模式下的综合,
我们在前面的流程中提及到,在后面的实验中,我们也会进行相关的解释。
·最后,一般情况下(以后的文章中),为了方便管理,我们会像上一节那样:
变量)。
是用 set_app_var 进行指定,此外指定的是具体的某一个库,而不仅仅是路径,
DC 会从 search_path 里面寻找到这些库。
内容。
五、综合库(时序库)和 DC 的设计对象
前面一直说到综合库/工艺库这些东西,现在就来讲讲讲综合库里面有什么东西,
标准单元库
DC 的设计对象
Design Ware 库
1、标准单元库
绝大多数的数字设计流程都是基于标准单元的半定制设计流程。标准单元库
包含了反相器、缓冲、与非、或非、与或非、锁存器、触发器等等逻辑单元
综合模型的物理信息,标准单元是完成通用功能的逻辑,具有同等的高度(宽
度可以不同),这样方便了数字后端的自动布局布线。
1 概述
一个 ASIC 综合库包括如下信息:
一系列单元(包括单元的引脚)。
每个单元的面积(在深亚微米中,一般用平方微米表示,在亚微米工艺
下,一般用门来称呼,至于具体的单位,可以咨询半导体制造商)。
每个输出引脚的逻辑功能。
每个输入到输出的传递延时,输出到输出的传递延时;inout 到输出的
传递延时。
2 内容与结构
库文件主要包括如下信息:
·单元(cell)(的信息):主要有功能、时间(包括时序器件的约束,如建
立和保持)、面积(面积的单位不在里面定义,可按照规律理解,一般询问半导
体厂商)、功耗、测试等。
·工作环境/条件(Operating conditions):制程(process)(电压和温度
的比例因数 k,表示不同的环境之间,各参数缩放的比例)
·设计规则约束(Design ):最大最小电容、最大最小转换时间、最大最小
扇出。
工艺库的结构如下:
文本描述如下所示:
我使用的 TSMC90nm 的工艺库,我用 slow.lib 这个库来给大家介绍:
这个库总共三万多行,不可能每一行都解说,因此我按照结构进行介绍。
打开这个.lib 文件,可以看到最前面:
最前面的是这些注释,描述的是:制程(是慢的模型)、电压、温度等数据信息。
接下来才是真正的库的信息:
库组(大结构):
Library(library_name){
......
......
A 首先是库的属性的描述:
下面是这张图的解释:
通用属性描述(general attribute)
主要是工艺类型、延迟模型、替代交换方式、库特征、总线命名方式等信息
延迟模型:指明在计算延迟时用的那个模型,主要有 generic_cmos(默认值)、
table-lookup(非线性模型)、piecewise-cmos(optional)、dcm(Delay
Calculation Module)、polynomial。这个库使用的非线性模型。
替代交换方式:这里选的是匹配封装的方式。具体的信息可以查阅其他治疗
或者询问半导体厂商。
库特征:报告延迟计算,也就是这个库具有延迟计算的特征。
总线命名方式:定义库中总线命名规则。例如:
bus_naming_style:"Bus%spin%d";这个库没有进行总线规则的命名。
库的文档资料属性(document attribute)
主要是库的版本、库的日期、还有注释。例如:
2005"。
修正版属性定义库的版本号码,例如 Revision:1.3;
Rights Reserved.”
定义单位属性(unit attribute)
voltage_unit(电压单位)、current_ unit(电流单位)、
pulling_resistance_unit(上/下拉电阻单位)、capacitive_load_unit(电容负
载单位)、leakage_power_unit(漏电功耗单位)。
单位属性确定测量的单位,例如可在库中用毫微秒(nanoseconds)或皮法拉
(picofar-ads)作为时间和电容负载的单位。注:关于面积的单位,前面已经
说了,这里不再详述。
B 接下来是环境描述:
主要包括操作条件(operation conditions)、临界条件定义(threshold
definitions)、默认的一些环境属性(default attributes)、一些(时序、
功耗)模型(templates)、比例缩放因子(k-factors)、I/O pad 属性(pad
attributes)、线负载模型(wire-loads)。
操作条件(operation conditions)
在工艺库中,用操作条件设置了制程(process)、温度(temperature)、
电压(voltage)与 RC 树模型(tree_type)。
在综合和静态时序分析时,DC 要用到这些信息来计算电路的延迟,而库中
的这组操作条件为基础(也就是 nom_xxxx)操作条件。一个工艺库只有这
么一组基础的操作条件,如果要使用不同的操作条件,则需要借助 K 参数了
(见后面)。制程、温度、电压这些很好理解,下面主要说一下这个 RC 树
模型(tree_type)。
tree-type 属性定义了布局之前延时的计算方式。此外,wire_load_model
线负载模型(后面有讲)是根据连线的扇出来估算连线的 RC 寄生参数的,
连线延时(从驱动引脚的状态变化到每个接受单元输入引脚的状态变化,线
负载模型设每个分枝的延迟是一样的。)的一个示例如下图所示:
在这个简单的电路中,BUF1 的输出驱动两个单元:BUF2 与 BUF3。在物理
在布局前,假设这两根线有相同的寄生电阻与寄生电容,即
Cwire1-Cwire2=R1-R2 。
这个延时就有三种计算模型,这三种模型有两种理解方式,这两种理解方式
是等价的。
第一种理解方式的三种模型:
Cwire*(Cwire 1+Cwire2)这个乘积表示连线的等效电容,Rwire(R1+R2)
示:
本例中取值为 2.
第二种理解方式的三种模型:
无论是从哪一种方式理解,这个库中使用的是平衡树的模型。
临界条件定义(threshold definitions)
主要是定义一些极限值,比如时钟抖动的最大最小值、输出输出的上升下降
沿的最大最小值等等信息,如下图所示:
默认的一些环境属性(default attributes)
主要是默认漏电流功耗密度、标准单元的漏电流功耗、扇出负载最大值、输
出引脚的电容、IO 类型的端口电容、输入引脚的电容、最大转换时间。
一些(时序、功耗)模型(templates)
都是写查找表模型,主要是功耗(比如输入转移时间的功耗)、时序(比如
输入线转换的延时、建立时间和保持时间的延时)等等,根据不同的操作环
境,进行查表进行选择对应的参数。
比例缩放因子(k-factors)
由于一般库中只有单元“nom_xxx”的值,为了计算不同的制程、电压和温
度下单元的延迟(或者说是计算不同的操作条件),库中提供了比例缩放因
子:
比例因子有许多,这里只是列举了这几个。
延迟:
(1+(DP*KfactorP))*(1+(DV*KfactorV))*(1+(DT*KfactorT))
其中:
delta = current-nominal ;
温度对延时的影响。
时候达到高电平、什么时候是低电平。
线负载模型(wire-loads)
工艺库的线负载模型如下所示:
DC 采用 wire-load 模型在布局前预估连线的延时。通常,在工艺库中,根
据不同的芯片面积给出了几种模型(上图所示)。这些模型定义了电容、电
fanout-length 设置了与扇出数相关的导线的长度。
有时候,除了扇出与长度,该属性还包括其他参数的值(这个工艺库没有),
例如 average_capacitance、standard_deviation 与 number_of_nets,在
DC 产生导线负载模型时会自动写出这些值。对于超过 fanout-length 属性
的节点,可将该导线分成斜率不同的几段,以确定它的值。
C 工艺库剩下的全是标准单元(cell)的描述:如反相器、触发器、与非门、
或非门的描述等:
标准单元内容概述
综合库中的每个单元都包括一系列的属性,以描述功能、时序与其他的信息。
DRC 错误。
3*2>4)。
值,则该节点不能连接。如果发生违例,则 DC 用一个具有更大
max_capacitance 值的单元来取代驱动单元。
在对输出引脚的描述中,给出了该引脚的功能定义,以及与输入弓}脚相关的
延时。输入引脚定义了它的引脚电容与方向。这个电容值不能与
max_capacitance 仅用来进行设计规则检查。
对于另一个设计就可能不太合适。这时候,需要设计者对综合库进行“剪裁”。
当然,这种“剪裁”必须比库中的定义更为严格。如将一个库中 buffd0 的
单元的延时--在一个单元的综合库中,最核心的是对时序和功耗的描述。一
个单元的延时跟以下因素有关:
器件内部固有的延时、输入转换时间(也称为输入上升/下降时间)、负载(驱
动的负载及连线)、温度、电压、制程变化。
前三个因素是由电路本身的特性所决定的,后三个因素是由环境决定的。在
实际电路中,输入转换时间、负载与连接单元的电路有关,所以我们只需要
列出在不同的输入转换时间、不同的负载下单元的延时就可以了。这个延时
包括器件的内部固有延时。此外,利用前面提到 K 缩放因子,将温度、电压、
制程的影响也考虑进来。如下面的这个反相器单元,它的延时就可以通过输
入转换时间和负载决定:
说到单元的延时,不得不说计算单元延时的模型。
两种模型精度较差,已经被淘汰,主要用非线性延时模型。下面进行解释非
线性延时模型。
非线性延时模型也称为二维非线性延时模型。在该模型中,用二维列表的形
式给出单元在特定的输入转换时间、输出负载下的延迟(包括单元的延时和
单元的输出转换时间):
单元的输出转换时间又成为其驱动的下级单入的输 ru 转换时间。库中每个
ns 。
对于在范围之内的点,可以用插值的方法得到;对于在范围之外的点,可以用
外推的方法得到。线性插值如下图所示:
计算延时的公式为:
Z=A+BXX+CXY+DXXXY
转换时间。
输入的上升、下降时间是由上一级输出的上升、下降时间得到的。输出节点
的电容可以由负载的输入引脚电容及连线负载计算得到。在综合时,使用导
线负载表可以预测导线负载。导线负载模型在综合库中进行了定义。当然,
用户也可以自己生成连线负载模型。该模型也是用查找表的方式,列出在不
同负载下的平均连线延迟。在布局之后,可以得到更为精确的导线长度。在
布线后,可以得到最确切的导线长度。可以用该导线负载来计算最终的延时,
以便进行静态时序分析与时序计算。
使用线性插值的举例:一个标准单元的延迟查找表如下图所示:
在查找表中,根据不同的输入转换时间和输出节点电容,列出了标准单元的
0.002 pF,则从表中无法直接查找到延时,需要通过线性插值的方法来求得
该值:
计算延时的第一步,是求出延时公式中的系数 A, B, C, D,然后根据实际
的输入转换时间和输出电容求出实际的延时。
找表中的相应的 4 值代入延时公式,可得:
接下来,我们将实际的节点电容、输入转换时间代入延时公式,可以得到这
种情形下该单元的实际延时为:
单位为 ns,输出转换时间、短路功耗的计算与此类似。
可以显示出某一节点处延迟或输出转换时间的具体求解过程。
前面对标准单元库的内容和结构有了一个概述,下面对一个反相器单元和一
个寄存器单元进行详细解说。
反相器的综合模型
综合库中主要给出了各端口的功能、电容、功耗及延时等信息(不同的库模
型信息种类可能不一样)。反相器的功耗主要分为两部分:静态功耗和动态
功耗。 其中静态功耗是指泄漏功耗,动态功耗包括翻转时的短路功耗及节
点电容的充放电所消耗的功耗。节点电容充放电消耗的功耗仅跟 VDD、节
点翻转率及节点电容有关。其中,VDD 和节点电容是固定的,节点翻转率
跟输入激励有关,需要通过仿真激励进行计算。因此,在综合库中,不列出
充放电功耗。而短路功耗跟输入转换时间和节点电容有关,一般以查找表的
具体的反相器的综合模型如下所示:
当然,上面看到的只是部分内容,有些内容折叠起来了比如输入引脚的等效负载、
输出引脚的短路功耗等被折叠起来了,下面进行讲解:
引脚 A 表示反相器的输入(上图),展开后可以看到输入的引脚的等效负载,
也就是等效电容的大小。
输出管脚
里面主要包含了引脚的功能(function)、短路功耗(internal_power)、时序
信息(timing)、输出的最大负载(max_capacitance)等信息。
短路功耗信息(internal_power):
展开短路信息如下图所示:
(index_1)及节点电容(index_2)有关;根据不同的信息进行查表,表的值
如下图所示:
也给出了从高到低的短路功耗(fall_power),功耗跟输入信号的转换时间及节
点电容有关;具体内容类似从低到高时的短路功耗,不再详述。
时序信息(timing):
主要包括相关引脚、时序敏感类型、单元延时、转换时间等。
Cell_rise 给出了 Y 从低到高时单元的延时,延时跟输入转换时间和节点电容有
关:
Rise_transition 给出 Y 从低到高时输出的延时(transtion),跟输入转换时间和
节点电容:
Cell_fall、fall_transition:则是对应 Y 从高到低时的单元延时和输出延时,也
是跟输入转换时间和节点电容有关。
cell_leakage_power:单元的泄漏功耗,有时候,也给出在不同条件时的泄漏
功耗(也就是查表的方式):
反相器作为组合逻辑最简单、最经典的模型,其综合库的模型内容就如上所示了,
下面介绍时序逻辑的。
寄存器单元的综合模型
寄存单元综合库模型主要包括以下内容:
单元面积;
D 端短路功耗;
D 端的建立时间约束和保持时间约束;
CK 时钟引脚上的短路功耗;
CK 时钟引脚上的最小脉宽要求;
Q 输出端的短路功耗;
Q 输出端的延时;
Q 输出端的最大负载约束;
单元的泄漏功耗
其综合库内容如下所示:
上面综合库的具体内容下面进行具体叙述:
D 端口(引脚):
输入端口,主要包含输入的等效负载、短路功耗、时序信息。
internal_power,D 端消耗的短路功耗:
rise_power 给出 D 端由低电平变到高电平时的短路功耗,跟输入转换时间有关,
电容为定值:
关,电容为定值。
Timing,时序信息:
时序信息。
rise-constraint:给出 D 端由低电平变到高电平时的 setup 约束,跟 D 端输入
转换时间和时钟的转换时间有关:
时间和时钟的转换时间有关。
前面我们看到,有两个 timing,一个既然是建立时间了,那么另外一个就是保
持时间了:
间和时钟的转换时间有关:
间和时钟的转换时间有关。
CK 端口:
这个是时钟端口,主要给出了输入的负载、最大转换时间约束、短路电流、高低
电平的最小脉宽要求,如下图所示。
Internal_power,短路功耗:
min_pulse_width_high、min_pulse_width_low :给出了时钟高低电平的最
小脉宽要求。
ff:描述寄存器的功能。
Q 端口:
主要描述 Q 的功能,短路功耗,时序信息,输出最大的负载电容。
Internal_power,短路功耗:
rise_power 给出了输出端由低电平变到高电平时的短路功耗,跟输入转换时间、
Q 端负载及 QN 端负载有关:
fall_power 则输出端由高电平变到低电平时的短路功耗,跟输入转换时间、Q
端负载及 QN 端负载有关。
Timing,时序信息:
说明 Q 端口与 CK 的上升沿有关。
输出节点电容有关:
间和输出节点电容有关:
和输出节点电容有关;
时间和输出节点电容有关。
max_capacitance,则是最大输出负载电容约束。
QN 管脚,跟 Q 管脚类似,不进行陈述了。
cell_leakage_power 给出了默认单元漏电流大小。而下面的不同漏电流,则是
根据端口信号处在不同状态时的漏电流大小
注:对于有复位信号的寄存器,还有可能有下面的信息:
· 复位引脚上的短路功耗;
· 复位引脚上的最小脉宽要求;
· 输出端的输出转换时间(相对于时钟);
· 输出端的输出转换时间(相对于异步复位信号);
· 输出端的延时(相对于异步复位信号);
2、DC 的设计对象
在了解了综合库之后,下面介绍一下 DC 的设计对象,虽然这个设计对象相对于
综合库没有那么重要,但是还是要了解一下的。
功能是什么,这个模块有哪些端口等等信息。但是对于 DC 来说,它不像我们那
DC 支持 8 中设计对象:
Design : 具有某种或多种逻辑功能的电路描述;
在 DC 读入设计时候,可以通过下面命令查看这些对象:
Query:访问某一个对象,
Sizeof:查某一个(对象)集合的大小。
对象具有某些属性,比如:
端口(port)的属性有:方向、驱动单元、负载、最大电容约束等等
单元(cell)的属性有:层次化、不触碰 等待;
时钟的属性有:周期、抖动等;
写约束,就是通过对设计对象的属性进行约束,至于要约束什么,怎么约束,在
后面进行介绍。
3、Design Ware 库
生产厂家库(Foundry Libraries)
都是事先验证过的、可重复使用的、参数化的、可综合的,并且不受工艺的约束。
法(Functional Inferencing)。运算符号推论法是直接在设计中使用“+、一、*、>、
一和<”等的运算符号。功能推论法是在设计中例化(instantiate) DesignWare
DWF_sqrt_tc 单元。
计得更快,设计的质量更高,增加设计的生产力和设计的可重复使用性,减少设
多个结构(算法)来完成该运算。这样就允许 DC 在优化过程中评估速度/面积的折
衷,选择最好的实现结果。对于一个给定的功能,如果有多个 DesignWare 的
使用 DesignWare 中 IP 的方法如下图所示:
下所示:
本文的总结主要参考了《专用集成电路设计使用教程》、《数字 IC 系统设计》,
局部图片来自这两本书。
六、基本的时序路径约束
时序约束可以很复杂,这里我们先介绍基本的时序路径约束,复杂的时序约束我
们将在后面进行介绍。
在本节的主要内容如下所示:
时序路径和关键路径的介绍
建立时间、保持时间简述
时钟的约束(寄存器-寄存器之间的路径约束)
输入延时的约束
输出延时的约束
组合逻辑的约束
结合设计规格进行实战
结构和数目、电路的拓扑结构、寄存器之间的组合逻辑功能以及寄存器与 I/O 端
口之间的组合逻辑功能。但代码中并不包括电路的时间(路径的延时)和电路面积
(门数)。综合工具现在不能很好地支持异步电路,甚至不支持异步电路,因此时
序路径的约束主要是针对同步电路的,关于异步的电路的约束,后面也会进行相
关的说明。
1、时序路径与关键路径
我们来看一下同步电路,常见的结构如下所示:
中间是我们设计的模块(芯片),对于同步电路,为了使电路能正常工作,
即电路在我们规定的工作频率和工作环境下能功能正确地工作,我们需要对
设计中的所有时序路径进行约束。那么时序路径是什么呢?下面进行解说:
时序路径是一个点到点的数据通路, 数据沿着时序路径进行传递。每条时
序路径有一个起点(Startpoint)和一个终点(Endpoint)。
起点定义为:
输入端口
触发器或寄存器的时钟引脚:CK
终点定义为:
输出端口
时序器件的除时钟引脚外的所有输人引脚:D DQ
输出端口、 输入端口到输出端口。如下面这个电路中:
就有 4 条路径:
1:从输入端口 A 到 FF1 的 D 端;
好看一点的图如下:
径 4 比较少见。
2、常见的时序路径约束
①建立时间、保存时间和亚稳态
在进行约束的时候,先了解触发器的三个概念:建立时间、保持时间以及亚
稳态。这里只是简单地介绍一下,关于建立时间和保持时间的深入介绍,请
查看我的博文:http://www.cnblogs.com/IClearner/p/6443539.html,
关于亚稳态的深入介绍,请查看我的博文:
http://www.cnblogs.com/IClearner/p/6475943.html
建立时间:时钟有效沿到来之前的某段时间内,数据必须稳定,否则触发器
如下图所示:
立时间和保持时间的情况;而 D2 则是建立时间没有满足,因此不能成功锁
存住输入的高电平;D3 保持时间不满足,也不能成功锁存输入的高电平。
亚稳态:每个触发器都有其规定的建立(setup)和保持(hold)时间参数,该参
数存放在由半导体厂商所提供的工艺库中。假如触发器由时钟的上升沿触发,
在这个时间参数内,输入信号是不允许发生变化的。否则在信号的建立或保
持时间中对其采样,得到的结果是不可预知的,有可能是 0 或者 1,即亚稳
态。
有了这三个概念之后,我们可以对路径进行约束了。约束就是为了满足寄存
器的建立时间(和保持时间),我们先对模块内的路径进行约束,也就是下面
电路框图中的中间部分:
对于中间的部分路径,可以用前面的那个路径图来描述:
也就是主要约束这些类型的路径,本小节主要讲的就是这些路径的约束。
②路径 2(寄存器到寄存器之间的路径)的约束:
我们先从寄存器到寄存器之间的路径 2 开始;前面说到了,为什么要约束时
寄存器与寄存器之间的组合逻辑延时、连线延时这些种延时。因为数据是随
着时钟的节拍一拍一拍往后传的,因此这里的寄存器与寄存器之间的路径约
束,就是对时钟的建模,或者是说对时钟的约束。下面进行说明:
时间/转换延时、寄存器与寄存器之间的组合逻辑延时、连线延时)之后到
是说,你的那些延时不能过大,延时一旦过大,数据可能就不满足建立时间
的关系,甚至还更新不了。举个例子说:
的 D 端传来,经过组合逻辑,在下一个节拍(20ns 这一时刻)的时候传到
头所示;但是由于延时太大,下一个节拍到来了(20ns 到了),这个高电
能得到更新,或者不满足建立时间,由此可能引起锁存错误。当对时钟进行
建模之后,拍长也就决定了,也就是那些延时(触发器的翻转时间/转换延
时、寄存器与寄存器之间的组合逻辑延时、连线延时)最大是多少也就知道
了,通过对时钟进行建模,也就是通过对寄存器与寄存之间的路径进行约束,
DC 就知道了这条路径运行的最大延时,就会选择合适的单元来满足这些延
时的约束,如果 DC 选来选去,发现最牛逼的单元得到的电路延时还是很大,
设计了(比如修改约束或者修改代码)。
/转换延时、寄存器与寄存器之间的组合逻辑延时、连线延时)之后到达 FF2
的 D 端的时间,不能小于某个值。也就是说,这些延时也不能太小。举个极
端的例子说,在 0ns 的时候,触发器有效沿到来,FF1 和 FF2 都要更新下数
FF2 更新数据失败,要锁存住的低电平可能就产生亚稳态。因此就有传输延
否稳定(若不稳定,就违反了建立时间),而保持时间是在发送数据的同一
就违反了保持时间);关于保持时间的分析比建立时间的分析提前一个时钟
周期沿这一点需要注意。
然而,保持时间一般是能够满足的,也就是传输延时一般是大于触发器的保
持时间的,即使满足不了,在后端版图设计的时候,也可以有修改措施(比
如路径加缓冲器增加延时)。因此我们在约束的时候,我们一般不关注保持
时间,而是注重建立时间。
经过上面一大堆的废话,相信大家已经对这个约束过程有一定的了解了,下
面进行概括一下,并进行时钟建模。
通过上面的讲解,我们知道,一般情况下,如果寄存器和寄存器之间组合电
建立时间),电路的功能会不正确,将不能正常工作。如果已知电路的时钟工
作频率,就知道了寄存器和寄存器之间组合电路的最大时延,如下图所示:
图中路径 X 的最大时延应满足下列关系:
这两个参数都由工艺库提供。总结完成之后,下面对时钟进行建模,也就是
寄存器到寄存器之间的路径进行约束,时钟的建模是比较复杂的,因此先一
步一步地讲解,最后给出约束脚本。
定义时钟的命令为:create_clock。假设时钟周期为 10ns,定义时钟的命令
就是:
对于的时钟波形为:
定义时钟时(虚拟时钟除外,虚拟时钟在后面说),我们必须定义时钟周期(也
以加上一些可选项(option)来定义时钟的占空因数(duty cycle),偏移
(offset/skew)和时钟名( clock name),我们可以通过 man create_clock 来
查看命令的相关选项。
一旦定义了时钟,对于寄存器之间的路径,我们已经做了约束。我们可以用
report_clock 命令来查看所定义的时钟以及其属性。如果我们需要使用时钟
的两个沿(上升沿和下降沿),时钟的占空因数将影响时序的约束。
然而单单定义一个时钟周期进行约束寄存器与寄存器之间的路径很显然是
过于理想的,需要再添加其他的时钟属性,在添加之前,需要知道时钟的偏
移(skew)、抖动(jitter)、转换时间(transition)、延时(latency)
这几个概念或者这几个时钟的属性,这些属性请查看我的另一篇博文:
http://www.cnblogs.com/IClearner/p/6440488.html
该博文详细介绍了时钟的建模,也就是路径 2 的约束。
这里讨论的是模块前后使用的是同一个时钟 CLK,如下图所示,至于使用不
在后面说。
在上图中,在 Clk 时钟上升沿,通过外部电路的寄存器 FF1 发送数据经过输
接收。它们之间的时序关系如下图所示:
对于我们要综合的模块,DC 综合输入的组合逻辑,也就是上面的电路 N,
时间)呢?在进行约束之前,DC 是不知道的,因此我们通过约束这条路径,
也就是告诉 DC 外部的延时(包括寄存器翻转延时和组合逻辑、线网的传输
如果延时还是太大,DC 就会报错。因此我们要进行输入端口的约束,告诉
外部电路的延时是多少,以便 DC 约束输入的组合逻辑。
如果我们已知输入端口的外部电路的延迟(假设为 4 ns,包括翻转延时和外
部的逻辑延时),就可以很容易地计算出留给综合电路输入端到寄存器 N 的
最大允许延迟:
我们指定外部逻辑用了多少时间,DC 计算还有多少时间留给内部逻辑。在
的最大延迟为 10 - 4 - Tsetup = 6 。
例如,对于下面的电路:
输入端口延时的约束如下所示:
对应的时序关系图如下所示:
如果触发器 U1 的建立时间为 1ns,则 N 逻辑允许的最大延迟为:
20 - 7 .4 - 1 = 11 .6 ns
的延时就是 20-11.6-1=7.4ns.
上面是没有考虑不确定因素情况,当考虑不确定因素时,则有:
间为 1ns,外部输入延时为 D(包括前级寄存器翻转和组合逻辑的延时),
则 N 逻辑允许的最大延迟 S 为:
20-D-U-1=S,同样可以得到外部输入的延时为:20-U-1-S=D
当输入的组合逻辑有多个输入端口时,如下图所示:
则可以用下面命令对除时钟以外的所有输人端口设置约束:
的输入端口中除掉时钟 Clk。
如果要移掉多个时钟,用下面的命令:
3、实战
首先设计的模块如下所示:
设计(约束)规格书如下所示:
(时钟的定义)
(寄存器建立时间定义)
(输入输出端口的延时定义)
(组合逻辑的定义)
上面的规格定义用来给我们进行时序约束使用,现在实践开始。
-->common_setup.tcl 文件:
由于这里有物理库,因此可以使用 DC 的拓扑模式进行启动。
-->dc_setup.tcl 文件:
-->.synopsys_dc.setup 文件:
-->启动的时候,我们使用管道开关,把 DC 的启动信息保存到
入库:read_db sc_max.db
-->然后我们查看与这个库相关联的工艺库:list_libs,结果为:
-->接着我们查看库信息:
要保存信息到文件,后面的{}中存放的是要执行的命令。
然后在终端读取相应库的单位信息,时序单位为 ns,电容单位为 pf
创建约束
在完成启动文件的书写之后,我就需要根据设计规格书,进行书写约束了
-->时钟的约束(寄存器和寄存器之间的路径约束):
1.时钟频率为 333.33MHz,因此时钟周期就是 3ns:
这里我们就要设置不确定因素了,由于设计规格声明是对建立时间
留余量,因此我们主要考虑建立时间的不确定因素:
首先是时钟偏移为±30ps,则有可能是前级时钟往后移 30ps,同时本
=60ps;
然后是时钟抖动,前级的时钟抖动影响不到本级,因此只需要考虑
本级的时钟抖动,由于是考虑建立时间,因此考虑本级时钟往前抖
40ps,即对于建立时间抖动的不确定因素为 40ps;
因此对于建立时间,总的不确定时间为 60+40+50=150ps=0.15ns:
6.时钟转换时间为 0.12ns:
-->输入延迟约束(输入路径的约束):
1.规定模块内 data1 和 data2 端口的逻辑 S 延时最大为 2.2ns,并没有
直接告诉外部逻辑的延时,因此我们需要计算:
因此有:
-->输出延时约束(输出路径的约束):
2.内部延时为 810ns,应用前面的公式:时钟周期-内部延时(翻转与内部
组合逻辑延时)-不确定时间=外部延时(外部组合逻辑+后级寄存器的
建立时间),于是有:3-0.81-0.15=2.04ns,于是有:
3.意思是外部延时只有后级寄存器的建立时间要求:
set_output_delay -max 0.4 -clock clk [get_ports out3]
-->组合逻辑的约束:
根据前面的公式可以得到:
3-0.15-输入延时-2.45=输出延时,于是可以得到:
输入延时+输出延时 = 0.4ns
由于设计规格没有规定这个比例,因此只要满足输入输出延时的关系满足上
面的式子都可以,如果综合后有违规,我们后面可以再适当调整一下,设置
为:
-->检查语法:
启动 DC
读入设计前的检查
读入设计(和查看设计)
这里就不具体演示了。
应用约束和查看约束
check_timing,返回值为 1,表示执行成功。
-->验证时钟是否约束正确:
report_clock
report_clock -skew
report_port -verbose
-->保存约束好的设计:
综合
(简单的步骤跟流程一样)
综合后检查(与优化)
(简单的步骤跟流程一样)
保存综合后的设计
(简单的步骤跟流程一样)
④路径 3(寄存器到输出端口)的约束:
与外部输出电路的的电路图如下所示:
之间的时序关系如下图所示,我们要要约束的的组合路径电路 S 的延时,要
DC 计算它的延时是否能够满足时序关系,就要告诉 DC 外部输出的延时大
概是多少:
当我们已知外部电路的延迟(假设为 5.4ns),就可以很容易地计算出留给要
综合电路输出端口的最大延迟,如下图所示:
有:
我们指定外部逻辑用了多少时间,DC 将会计算还有多少时间留给内部逻辑。
举个例子说,对于下面的这个电路模型:
寄存器到输出端口的时序路径约束为:
对应的时序关系图如下所示:
时序路径就会违规,DC 就会报错。
外部输出延时为 X(包括外部组合逻辑和后级寄存器的建立时间),时钟周
期为 T,那么就有:
T-S=X,知道了最大的内部延时 S,就可以算出输出外部允许的最大延时 X
就有:
T-Y-S=X,因此外部输出延时 X,可以直接得到,也可以通过内部延时间 S
(和不确定时间 Y)接计算得出 X。
在这里说一下关于输入路径延时和输出路径延时的一些实际情况。 进行
SOC 设计时,由于电路比较大,需要对设计进行划分,在一个设计团队中,
每个设计者负责一个或几个模块。设计者往往并不知道每个模块的外部输入
延迟和/或外部输出的建立要求(这些要求或许在设计规格书里面写有,或
许没有,当没有的时候设计者就不知道了),如下图所示:
这时,我们可以通过建立时间预算(Time Budget),为输入/输出端口设置时
序的约束,也就是先预置这些延时,大家先商量好(或者设计规格书声明好)。
但是预置多少才合适呢?就有下面的基本原则了:
DC 要求我们对所有的时间路径作约束,而不应该在综合时还留有未加约束
的路径。我们可以假设输人和输出的内部电路仅仅用了时钟周期的 40%。如
果设计中所有的模块都按这种假定设置对输人/输出进行约束,将还有 20%
示:
举个例子说,对于前面的电路,就要按照这么一个比例进行设置:
对应的约束为:
如果设计中的模块以寄存器的输出进行划分,时间预算将变得较简单,如下
图所示:
时间预算的约束为:
⑤路径 4 的约束
路径 4 是组合逻辑的路径,组合逻辑的约束可能需要虚拟时钟的概念。组合
逻辑可能有两种中情况,一种是前面电路中的路径 4
模块里面有输入端口到输出端口的组合逻辑外,也有时序逻辑,也就是模块
里面有时钟,那么就可以对于路径 4,就下面的电路模型进行约束
时钟周期减去两端,就得到了中间的延时约束了,对于上面的模型,可以这
样约束为:
B] -to [get_ports D]
当然,最后一句的约束可有可无。对于多时钟的同步约束,只需要修改相应
的延时和时钟就可以了,可以参考前面的多时钟同步时序约束那里。
合逻辑延时),外部输出延时为 G(组合逻辑延时+后级寄存器建立时间),
另外一种是纯的组合逻辑,模块内部没有时钟:
这种时钟需要用到虚拟时钟的概念,后面介绍有虚拟时钟的约束时,再进行
说明。
七、环境、设计规则和面积约束
本文的主要内容是讲解(约束针对的是逻辑综合下的约束,而实战部分则是在 DC
的拓扑模式下进行):
环境属性的约束
设计规则的约束
面积的约束
实战(部分)环境属性的约束
1、工作环境属性约束
输入/输出端口及其驱动属性是设计规格的一部分,工作环境的约束,是对
这个规格约束的一部分。
境下对你的设计进行约束,举个例子,比如你的芯片要在恶劣的环境中进行
工作,DC 如果在优质的环境中对你的设计进行约束,你的芯片生产出来,
就很有可能工作不了。因此一般就要告诉 DC,使用恶劣的模型对设计进行
约束。另一方面是为了保证电路的每一条时序路径延时计算的精确性,特别
是输入/输出路径的精确性,单单靠外部的输入延时和输出延时的约束是不
够,还要提供设计的环境属性。
这个约束可以看成是宏观的、整体的、外在的约束,约束的内容可以从下图
看出:
设置环境条件(set_operating_conditions):
用于描述制造工艺、工作电压与温度(PVT,process,voltage,temperature)
这些周围环境对延时的影响。工艺库单元通常用“nominal”电压和温度来
描述其默认的特性,例如:
器件与线网上的延时在条件不同的时候呈线性变换。库文件中,包含对各种
及典型的具体描述(具体见标准单元库那一节)。通过设置不同的操作条件,
可以覆盖到各种不同的情况。
如果电路在不同于“nominal”电压和或温度的条件下工作,我们需要为设
计设置工作条件(Operating Conditions),我们可以用
set_operating_conditions 命令把工作条件加入到设计上。综合时,原来按
"nominal”环境计算出的单元延迟和连线延迟,将按工作条件作适当的比例
调整,如下图为为延迟与工作条件的关系:
讲解完工作环境条件是什么之后,下面就介绍与它有关的常见的命令以及约
束。工艺库中通常指定一个默认的工作条件.我们可用:report_lib libname
命令把厂商提供的所有工作条件列出来。
设置工作条件可用下面命令举例如下:
$LIB_NAME
设置线负载模型(set_wire_load_model)
在计算时序路径延迟时,除了需要知道门单元延迟外,还需要知道连线的延
迟,如下图所示:
出负载在表中找出门单元的延迟以及其输出转换时间。输出转换时间又作为
下一级电路的输人转换时间。门单元的延迟在综合库那一节详细介绍。
估算。WLM 是厂商根据多种已经生产出来芯片的统计结果,在同样的工艺
下,计算出在某个设计规模范围内(例如门数为 0~43478.00、门数为
43478.00~86956.00,等等)负载扇出为 1 的连线的平均长度,负载扇出为 2
线的扇出进行估算连线的 RC 寄生参数,一般情况下,由半导体厂商建立。
厂商根据已生产出来的其他设计统计出该工艺的连线寄生参数。半导体厂商
提供的工艺库中包括了线负载模型。通常在一个综合库里面有多种线负载模
型,不同的模型模拟不同规模的的模块内的线上负载情况(具体见综合库描
述那一节)。用户也可以自己创建自己的线负载模型去更精确地模拟设计内
的线上负载。连线负载模型的格式如下图所示(上),具体格式由工艺库决
定(下):
关于线负载模型的更多内容,可以参考综合库/工艺库那一节。
负载信息,以负载的大小为函数来模拟线上的延时(也就是设置这个约束是
用来模拟线延时)。因此设置线负载模型。
如 DC 遇到连线的扇出大于模型中列出的最大扇出值,它将使用外推斜率
(Extrapolation slope)来计算连线的长度。上例格式中,如果连线的扇出为
7,而连线负载模型中最大扇出是 5,连线的其长度计算如下:
讲完线负载模型是什么东西,为什么设置线负载模型约束之后,下面介绍与
其相关的命令。
行综合时,综合工具会默认根据设计面积和节点处的负载自动选择合适的连
线负载模型,如果要关掉自动选择 WLM,那么可以使用命令:
然后手动选择线负载模型的命令是:
set_wire_load_model -name $WIRE_LOAD_MODEL -library $LIB_
NAME
如果连线穿越层次边界,连接两个不同的模块,那么有三种方式对这种跨模
块线连接的类型进行建模,set_wire_load_mode 命令用于设置连线负载模
型的模式。有三种模式供选择:top、segment 和 enclosed。三种模式的
示意图如下所示:
30。
假设有一个连线贯穿两个小模块, 但没有超出子模块的范围。 对于这种连
线,在三种模式下,所用的连线负载模型是不同的,下面是介绍:
50;因此,连线的延迟最大。我们一般选用这种方式,命令如下:
set_wire_load_mode top
比较 TOP 设计小,所以连线的延迟比较短(不悲观,就是连线延时小)。
对应的命令为:
set_wire_load_mode enclosed
的连线负载模型, 中间部分采用子模块的连线负载模型。
于 I/O 口的约束,为时序约束与时序分析提供了路径,更是为输入/输出路
以算是属于环境约束,因此放在这里进行讲解。
设置驱动强度(set_drive 与 set_driving_cell)
器件形式计量,说明输入端口是由一个真实的外部单元驱动。
为什么要需要为 input 或者 inout 的端口设定驱动?这是因为,对于输入端,
为了精确计算输入电路的延时时间,DC 需要知道到达输入端口的转换时间:
升沿跳变到下降沿或者下降沿跳变到上升沿的时间是 0,这是不符合实际情
况的。通过设置驱动强度,就告诉 DC 这个设输入端口实际上是由一个真实
的外部单元驱动的,不是理想的;DC 就会计算输入信号的实际转换时间,
引脚驱动的例子:
对应的约束可以这样写:
如果不用开关选项“-pin",DC 将使用所找到的第一只引脚(库中这个单元
的第一个引脚,这个驱动引脚貌似是要选择输出的引脚)。
此外,除了通过这两种方式,还可以直接设置输入端口的转换时间,如下所
示:
set_input_transition 时间 [get_ports 设计对象]
明确说明端口(输入或输出)上的外部电容负载。对于输出端,为了精确地
计算输出电路的延时时间,DC 需要知道输出单元所驱动的总负载
中某一单元引脚的负载(一般是选择输入引脚):
跟设计输入输出延时一样,设计者往往并不知道每个模块输入端口的外部驱
动单元和/或输出端口的外部输出负载。因此我们要通过负载预算(Load
Budget),为输入/输出端口设置环境的约束。产生负载的原则如下:
1.保守起见,假设输入端口为驱动能力弱的单元驱动(即转换时间长);
2.限制每一个输入端口的输入电容(负载);
3.估算输出端口的驱动模块数目。
例如:(只是举例)对于下面的电路图:
其规格为:模块输入端口驱动的负载不大于 10 个“AND2”门的输入引脚
的负载,模块输出端口最多允许连接 3 模块,如果某个输出端需要连接多于
3 个模块,我们要在代码中复制该输端口。
对应的约束
环境约束举例如下
语法中,设置(定义变量时),如上面的:
remove_from_collection 是移除设计物集对象的意思,我们知道,DC 可以
将设计识别成多个对象,比如输入端口、输出端口等等,然后这个就是从
令之中有命令时,需要用[]来括起来。
上面中,LIB_NAME、WIRE_LOAD_MODEL、DRIVE_CELL 、DRIVE_PIN、
OPERA_CONDITION 这些变量的内容都不是随便定义的,需要根据综合库
书写,下面进行解释,库的具体内容参考综合库那一节。
LIB_NAME:库的名字,这里使用的恶劣的情况:
WIRE_LOAD_MODEL:线负载模型,打开 slow.lib 这文件,可以找到各种
线负载模型:
约束中选的是 w150 的。
DRIVE_CELL:驱动单元,也就是用来模拟驱动输入端的驱动单元,这要选
择库中有的单元,比如反相器:
DRIVE_PIN:驱动管脚,为单元的输出管脚,也就是“Y”了。
OPERA_CONDITION:这个操作环境也是要填写库里面有的:
设置完这些变量之后,还设置了 ALL_IN_EXCEPT_CLK 和 MAX_LOAD 变量,
其中 ALL_IN_EXCEPT_CLK 变量代表了除了时钟之外的输入管脚。
MAX_LOAD 变量就表示最大的负载,代表的是库中某个单元的输入负载值。
最后面的就是设置工作环境了。
2、设置设计规则约束
set_max_transition、set_max_fanout、set_max_capacitance
主要是设置最大转换时间、最大扇出及最大负载电容要求,可以设置在输入
端口、输出端口以及当前设计。举个前面的环境约束的例子说,比如我约束
了输入端口的最大转换时间和负载,也约束输出最大扇出,如下图所示
当综合和优化了,计算发现输入端口实际的转换时间比约束的大,或者负载
比约束的大(模块输入端口驱动的负载大于 10 个“AND2”门的输入引脚
的负载),或者检测到输出端口的扇出数比约束的要多(模块输出端口最多
半导体厂商在工艺库强加了设计规则。这些规则根据电容、转换时间和扇出
(capacitance,transition 和 fanout)来约束有多少个单元可以相互联结。设
计规则一般由半导体厂商提供,在使用工艺库中的逻辑单元时对其联结所强
加的限制。例如,如果设计中一个逻辑单元的负载(其驱动的负载)大于库中
给定的其最大负载电容(max_capacitance)值,半导体厂商将不能保证该电
路能正常工作。我们只可以按照设计规则的约束或按照更严格的设计规则约
冲器(buffering)和改变门单元的驱动能力(cell sizing)技术来满足设计规则
的目标。
库单元的设计规则(design rule)一如下所示:
在约束工作环境的时候,调用了库中的一些单元(的引脚),就相当间接设
置了设计规则约束,我们可以不必设置。
下面我们来详细叙述一下 DC 进行综合时设计规则约束:
DC 在做综合时,把设计规则的优先级设置为最高。优先级的从高到低次序
为:最大电容(max_capacitance)、最大转换时间(max_transition)、最大扇
出(max_fanout).
最大电容(max_capacitance)的约束
例如对于下面的电路:
对应的最大的电容约束如下:
IN1]
约束的意思是:首先【1】处,我们选择使用综合库里面库单元的一个输出
引脚作为设计中预期驱动器的最大允许电容负载,其值通过【2】得到,假
MAX_CAP,也就是 1.8pf。
当设置了输入端口的负载之后,也就是:
set_load 1.2 [ get_ ports IN1]
我们可以用“set_max_capacitance 3. 0 $ current_design”命令为整个
设计中加入最大电容的设计规则。此处,用了 3. 0 为最大的电容值,设计时
我们可以根据工艺库和电路的具体情况,选用合适的数值。要注意不要施加
过度保守的约束,以免严重地限制 DC 对设计的优化。当然,如果库内定的
值不够恰当或者过于乐观,我们可以手动设置,以控制设计的裕量。
最大转换时间(max_transition)的设计约束
例如前面的电路,可以进行下面的最大转换时间约束:
#从工艺库找出设计中预期驱动器的最大允许转换时间,也就是最大转换时
间可以像这个引脚这么大,假设其值为 0.400ns。
#在实际驱动的时候,增加一些富余量使 DC 不会给它加满载,也就是实际
的内部负载来满足的设计规则,也就满足你这个转换时间,让它不超过该
0.2ns。
有时候我们可以在整个设计上施加最大转换时间的设计约束,以帮助防止可
能在长连线上出现的慢(长)的转换时间,从而导致设计中出现特别长的延迟。
施加最大转换时间的设计约束也可以约束单元输出端的转换时间以减少其
功耗。我们可以用’set_max_transition 0. 4 $ current_design,命令在
整个设计中加入最大转换时间的设计规则。此处,用了 0. 4 为最大转换时间
值,设计时我们可以根据工艺库和电路的具体情况,选用合适的数值。要注
意不要人为地加紧对整个设计的约束,以免限制 DC 对设计中真正关键器件
的适当优化。
最大扇出(max_fanout)的设计规则的约束
例如对于下面的电路:
用 set_max_fanout 命令为设计设置最大扇出的设计规则的约束,例如:
的扇出数目。端口的扇出负载之和必须小于最大扇出的设计规则的约束。进
行上面的约束之后,DC 在综合时会查看有没有违反规则,我们也可以自己
出负载:
负载之和为:
3*fanout_load(invla1/A)+ 2*fanout_load(invla27/A)=(3 x
0.25)+(2x3.0)=6.75
因此,电路违反了最大扇出负载的设计规则约束。
与扇出有关的还有线负载模型,线负载模型根据连线的扇出数目来估算连线
电阻和电容值。连线的扇出数目定义为单元输出引脚与其他单元的输入引脚
之间连接的数目。与连线的扇出数目不同,扇出负载属性是附加在单元的输
入端口,不同单元可以有不同的扇出负载属性。
我们可以用如下的命令限制整个设计的扇出负载:
确时使用。
一些工艺库中,某些单元的引脚没有扇出负载属性。这时,DC 会检查库中
默认的扇出负载属性(default_fanout_load) 。如果库中没有默认的扇出负
载属性,DC 假设其值为“0",即这些单元的引脚不受扇出负载的设计规则
约束。我们可以强制使端口的扇出数目为 1,即只与一个单元连接,如果库
中单元的扇出负载最小值为 1. 0,用下面的命令加上扇出负载的设计规则约
束:
如果库中单元的扇出负载最小值不为 1. 0,我们需要先找出扇出负载最小的
单元(假设为 bufla1),计算出其扇出负载值,然后加上扇出负载的设计规则
约束:
中单元的扇出负载最小值为 0. 5000
扇出负载值是用来表示单元输人引脚相对负载的数目,它并不表示真正的电
容负载,而是个无量纲的数字。
如果我们所用的所有库单元扇出负载为“1",那么 set_max_fanout 1.
0 [all_inputs]约束将强制所有的输人端口扇出数目为 1,即它们只能与一
个单元连接。否则,为了使输入端口只能与一个单元连接,我们要找出库中
在这个端口上只连接一个单元。如果单元上没有扇出负载属性并且库中本身
也没有(默认)预设的扇出负载属性,那么把它设为 1. 0 是有意义和效用的。
我们也可以在输出端口上指定扇出负载值。例如,假设一个内部单元驱动几
驱动单元的最大电容设计规则,但该命令并没有为驱动单元的扇出提供独立
建立额外的预期扇出负载模型,综合时 DC 同时也会使内部驱动单元的最大
扇出遵守设计规则的要求。
下面就是进行面积的约束,也就是告诉 DC 综合的电路面积要在多少以内。
在介绍约束命令之前,先了解一下面积的单位。面积的单位可以是:
2 输入与非门(2-input-NAND-gate)
晶体管数目(Transistors)
平方微米(Square microns)
此外,我们往往看到一个芯片是多少多少门,这多少门的数字就是拿芯片的
面积的单位,我们要询问半导体厂商面积的单位是什么。
了面积的约束后,DC 将在达到面积约束目标时退出的面积优化。如果设置
面积的约束为“0" , DC 将为面积做优化直到再继续优化也不能有大的效果。
这时,DC 将中止优化。注意,对于很大(如百万门电路)的设计,如将面积的
约束设置为“0" , DC 可能要花很长的时间为设计做面积优化。综合时,运
行的时间很长。
在超深亚微米(deep sub-micro)工艺中,一般说来,面积并不是设计的主要
目标,对设计的成本影响不大。因此,我们在初次优化时,可以不设置面积
的约束。优化后,检查得到的设计面积,然后将其乘上一个百分数(例如 8500),
将其结果作为设计的面积约束。再为设计做增量编辑,运行“compile -inc”
命令,为面积做较快的优化。这样做,既可以优化面积,又可以缩短运行时
间。
当设计不是很大的时候,根据上面的描述,我们就可以使用下面的命令进行
面积约束:
set_max_area 0
让 DC 做最大的面积优化约束。
4、实战
由于种种原因,这里只有环境属性的约束的实战,其他的约束也可以通过上
面的讲解和下面的这个实战进行设计。
首先,我们来看看设计约束规格:
(设计原理图)
(设计规范)
在前面一节的基本时序约束规范上加上下面的规范:
DC 启动环境的设置我们根据设计原理图和设计规范开始进行实践:
(跟上一节一样,这里不再重复)
约束文件的编写
基本的时序路径约束和上一节一样,不进行改动,下面进行工作环境的约束:
-->输入端口的驱动设置:
这里是直接使用库里面的单元来驱动的,根据前面的讲解,我们很容易得到
约束的命令为:
在库的名字 要设置约束的对象
注意:当一条命令太长,要进行分割时,使用反斜杠\作为分隔符,且反斜
杠后面不能加空格。
换时间,因此可以这样约束:
-->输出负载的约束:
1.除了 cout 输出,其它输出驱动值都是库单元 bufbd7 的引脚 I 负载值的两
倍,也就是用单元的端口进行约束,因此有:
[get_ports out*]
-->操作环境的设置:
由于用到了库里面的单元,我们还在最好设置一下操作环境,虽然 DC 可以
从启动环境里面找到单元所在的位置库,但是我也要设置操作环境,如下所
示:
下面的步骤跟前面的一样,这里就不展开描述了
八、DC 逻辑综合及优化
对进行时序路径、工作环境、设计规则等进行约束完成之后,DC 就可以进行综
合、优化时序了,DC 的优化步骤将在下面进行讲解。然而,当普通模式下不能
进行优化的,就需要我们进行编写脚本来改进 DC 的优化来达到时序要求。理论
部分以逻辑综合为主,不涉及物理库信息。在实战部分,我们将在 DC 的拓扑模
式下进行。(本文主要参考虞希清的《专用集成电路设计实用教程》来写的总结
整理与实验拓展)主要内容有:
DC 的逻辑综合及优化过程
时序优化及方法
实战
1、DC 的综合优化阶段
命令。电路综合优化包括三个阶段,在这三个阶段,都对设计作优化,如下
图所示:
主要包括:第一阶段的结构级的优化(Architectural-Level Optimization)、
第二阶段的逻辑级优化(Logic-Level Optimization)、最后阶段的门级优化
(Gate-Level Optimization)。
结构级优化包括的内容如下:
①设计结构的选择(Implementation Selection):
在 DesignWare 中选择最合适的结构或算法实现电路的功能。
②数据通路的优化(Data-path Optimization):
选择 CSA 等算法优化数据通路的设计。
也就是多个表达式/等式中,有共同的表达式,进行共享,举例如下:
有等式:
SUM1<=A+B+C;
SUM2<=A+B+D;
SUM3<= A+B+E;
很容易看出,上面的等式中有共同的表达式 A+B,那么代码子表达
式 A+B 可以被共用,原等式可改为:
Temp=A+B;
SUM1<=Temp+C;
SUM2<= Temp+D;
SUM3<=Temp+E;
这种方法可以把比较器的数目减少,共享共同的子表达式。
④资源共享(Resource Sharing):
对于下面的代码
DC 中经过资源共享之后,就会得到综合出仅用一个加法器和两个多
路传输器的设计,如下图所示,从而节省资源:
算术运算资源共享的默认策略是约束驱动的。我们也可以指示 DC
area,如下所示:
如果不希望资源共享,可以将即将变量 hlo_resource_allocation 设
置为 none,这时候,我们还是要进行算术运算的资源共享,那么我
们必须在 RTL 代码中写出相应的代码,如下所示
⑤重新排序运算符号(Reordering Operators):
始。
如下图所示:
电路的总延迟等于一个乘法器的延迟加上 4 个加法器的延迟。为了
使电路的延迟减少,我们可以改变表达式的次序或用括号强制电路
用不同的拓扑结构
这时得到的综合结构为:
电路的总延迟等于一个乘法器的延迟加上 2 个加法器的延迟,比原
来的电路少了 2 个加法器的延迟。
逻辑优化的内容如下
化的过程中,可以作结构(Structuring)优化和展(开)平(Flattening)优化。
①结构优化:
结构(Structuring)优化用共用子表达式来减少逻辑,这种方式既可
用作速度优化又可用作面积优化。结构优化是 DC 默认的逻辑级优
化策略。结构优化在作逻辑优化时,在电路中加入中间变量和逻辑
结构。DC 作结构优化时,寻找设计中的共用子表达式。例如,对于
下面的电路,优化前为:
做完结构优化后,电路和功能表达式为:
值得一提的是逻辑级的结构优化中共用子表达式和前面结构级的共
用子表达式是不同的,逻辑级的结构优化指门级电路的共用子表达
式,结构级的是算术电路的共用子表达式。逻辑级结构优化并不会
改变设计的层次,用下面的命令设置结构优化:
set_structure true
②展平优化:
展平优化把组合逻辑路径减少为两级,变为乘积之和
(sum-of-products,简称 SOP)的电路,即先与(and)后或(or)的电
路,如下图所示:
这种优化主要用作速度的优化,电路的面积可能会很大。用下面的
命令设置展平优化:
high 其中一个就可以了)
命令选项“-effort”后的默认值为 low,对大部分设计来说,默认
值都能收到好的效果。如果电路不易展平,优化就停止。如果把选
力展平设计。如果把选项“-effort”后的值设为 high,展平的进程
将继续直到完成。这时,可能要花很多时间进行展平优化。
结构(Structuring)优化和展平(Flattening)优化的比较:
以下内容:
映射的优化过程包括 4 个阶段:
阶段 1:延迟优化
阶段 2:设计规则修整
阶段 3:以时序为代价的设计规则修整
阶段 4:面积优化。
段 4)将努力地去减少设计的面积。门级优化时需要映射组合功能和时序
功能:
组合功能的映射的过程为:DC 从目标库中选择组合单元组成设计,该
设计能满足时间和面积的要求,如下图所示:
时序功能的映射的过程为:DC 从目标库中选择时序单元组成设计,该
设计能满足时间和面积的要求,为了提高速度和减少面积,DC 会选择比
较复杂的时序单元,如下所示:
设计规则修整的介绍如下:工艺库中包括厂商为每个单元指定的设计规
则。设计规则有:max_capacitance,max_transition 和 max_fanout。映
射过程中,DC 会检查电路是否满足设计规则的约束,如有违反之处.DC
设计规则的修整。修正设计规则的步骤如下所示:
DC 进行进行优化的时候,如果下面的条件之一都满足了:
果收益递减的阶段,即再综合下去对结果也不能有多大的改善。
这时 DC 就会进行中断优化,停止综合。
(4) 其他的优化情况(需要加上一定的综合选项开关)
比如一个寄存器驱动多个寄存器时,可能会违反设计规则,DC 会把就
驱动寄存器进行复用,同时把被驱动的进行分割
(使用 DC 的拓扑模式,加上 -timing 选项才能自动地使用上面的这种
寄存器复制的优化)
当你的设计中出现多次例化的情况时,也就是下面的情况:
在这种情况下,DC 在编译时,会复制每个例化的模块。每个模块对应
一个拷贝,并且有一个独一无二的名字。这样 DC 可以根据每个模块本
身特有的环境做优化和映射,如下图所示((模块名字唯一化)):
字唯一的拷贝。DC 在为设计做综合(compile)时,也会自动地为每一个
模块产生一个唯一的有名字的拷贝。变量 uniquify_naming_style 可以
用来控制多次例化子模块每个拷贝的命名方式。其详细的使用方法可以
在 DC'中用“man uniquify_naming_style”来查看。
2、时序优化及方法
DC 综合之后,我们查看详细的报告,如果没有违规,设计既能满足时间和
面积的要求又不违犯设计规则,那么综合完成。可以把门级网表和设计约束
和面积的要求或违犯设计规则等,就要分析问题所在,判断问题的大小,然
后采取适当的措施解决问题。问题往往是时序的问题,发生时序违规时可以
采取相应的措施,如下图所示:
(1)当违规得比较严重时,也就是时序的违规(timing violation)在时钟
(2)时序违规在 25%以下,有下面的时序优化方法:
命令适用于时序要求比较严格,高性能的设计。使用该命令可以得
到更好的延迟质量( delay QoR ),特别适用于高性能的算术电路优
化。该命令非常容易使用,它自动设置所有所需的选项和变量。下
面是这个命令的一些介绍:
compile_ultra 命令包含了以时间为中心的优化算法,在编辑过程中
使用的算法有:
optimization);
为算术运算选择适当的宏单元结构;
从 DesignWare 库中选择最好的数据通路实现电路;
映射宽扇入(Wide-fanin)门以减少逻辑级数;
积极进取地使用逻辑复制进行负载隔离;
在关键路径自动取消层次划分(Auto-ungrouping of
hierarchies)。
简单易用,它的开关选项有:
部分解释如下所示:
-scan :做可测试(DFT)编辑;
-no_autoungroup :关掉自动取消划分特性;
-no_boundary_optimization :不作边界优化;
-no_uniquify : 加速含多次例化模块的设计的运行时间
-area_high_effort_script : 面积优化
-timinq_high_effort_script : 时序优化
上面的开关部分说明如下所示:
使用 compile_ultra 命令时,如使用下面变量的设置,所有的
DesignWare 层次自动地被取消:
也就是说,你调用的一个加法器和一个乘法器,本来他们是以 IP 核
的形式,或者说是以模块的形式进行综合的,但是设置了上面那么
变量之后,综合后那个模块的界面就没有了,你不知道哪些门电路
是加法器的,哪些是乘法器的。
使用 compile_ultra 命令时,使用下面的变量设置,如果设计中有
一些模块的规模小于或等于变量的值,模块层次被自动取消:
=500)
也就是说,假设你有一个模块 A 是一个小的乘法器,并且调用了模
块 B,一个模块 B 是一个小的加法器,使用没有设置这条命令的情
况综合,那么我们可以看到模块 A 中乘法器对应的门电路是哪些,
同样也可以看到模块 B 的加法器是由哪些门电路构成的,模块 A 和
模块 B 之间有层次、有界限;当设置上面的那条命令之后,我们就
哪些门电路构成,或者说你看到了某一个与门,但是你并不知道它
是构成乘法器的还是构成加法器的。
常数、没有连接的引脚和补码(complement)信息进行优化,如下图
所示:
也就是说,边界优化会把边界引脚一些固定的电平、固定的逻辑进
行优化。
级网表的时序进行优化,也可以对寄存器的面积进行优化。BRT 通
过对门级网表进行管道传递(pipeline)(或者称之为流水线),使设
计的传输量(throughput)更快。BRT 有两个命令:
optimize_registers :适用于包含寄存器的门级网表(不是
compile_ultra 的开关选项)。
pipeline_design :适用于纯组合电路的门级网表。
对于寄存器的的优化,举例如下,对于下面的电路,既包含有组合
逻辑电路又包含有寄存器:
后级的寄存器与寄存器之间的时序路径延迟为 10. 2 ns,而时钟周
期为 10 ns,因此,这条路径时序违规。但是前级的寄存器与寄存器
之间的时序路径延迟为 7. 5 ns,有时间的冗余。使用
optimize_registers 命令,可以将后级的部分组合逻辑移到前级,
使所有的寄存器与寄存器之间的时序路径延迟都小于时钟周期,满
足寄存器建立时间的要求。optimize_registers 命令首先对时序做
优化,然后对面积作优化。优化后,在模块的入/输出边界,电路的
功能保持不变。该命令只对门级网表作优化。
除了单独使用这个命令之外,还可以在编译的时候往往加上选项
选项的功能也就是:当有一个路径不满足,而相邻的路径满足要求
时,DC 会进行路径间的逻辑迁移,以同时满足两条路径的要求,这
也叫 adaptive retiming,如下图所示:
对于纯组合逻辑的流水线(管道)优化,举例如下,对于纯组合逻
辑电路进行优化如下所示:
左边电路,是一个纯组合电路,它的路径延迟为 23. 0 ns。对这个
电路进行管道传递优化后,得到右边所示的电路。显然,电路的传
输量(throughput)加快了。需要注意的是,在使用这个命令时,需
么来的。
-inc 是使用增量编译。这条命令就是进行支持可测性设计的增量编
如下图所示:
③使用自定义路径组合关键范围
在介绍这种优化方法之前,先来了解一下路径分组与延时。
路径分组:
DC 为了便于分析电路的时间,时序路径又被分组。路径按照控
制它们终点的时钟进行分组。如果路径不被时钟控制,这些路径
被归类于默认(Default)的路径组。我们可以用
report_path_group 命令来报告当前设计中的路径分组情况。
例如,对于下面的电路,我们来看一下路径及分组情况
根据上图可以知道,图中共有 5 个终点(四个寄存器和一个输出)。
时钟 CLK1 控制 3 个终点,在 CLK1 的控制下有 8 条路径。时钟
为一终点,它不受任何时钟控制,其起点为第二级寄存器的时钟
引脚,在它的控制下只有一条路径,这条路径被归类于默认的路
路径的延时:
间弧((timing arcs),如下图所示:
DC 就是通过时间弧来计算路径延时。因为时间弧描述单元或/
和连线的时序特性。单元的时间弧由工艺库定义,包括单元的延
连线的时间弧由网表定义。在上面电路中,时间弧有连线的延迟,
型计算;连线延迟在版图前用线负载模型计算;RC 寄生参数的分
配用操作条件中的“Tree-type”属性决定;工作条件又决定制程、
电压和温度对连线及单元延迟的影响。
此外,路径的延迟与起点的边沿有关,如下图所示:
假设连线延迟为 0,如果起点为上升沿,则该条路径的延迟等于
1. 5 ns。如果起点为下降沿,则该条路径的延迟等于 2. 0 ns。
由此可见,单元的时间弧是边沿敏感的。Design Compiler 说
明了每一条路径延迟的边沿敏感性。还有需要强调的是 Design
Compiler 默认的行为是假设寄存器之间的最大延迟约束
为:TCLK - FF21ibSetup,即数据从发送边沿到接收边沿的最大
延迟时间要小于一个时钟周期,如下图所示:
骤:
把设计分解成单独的时间组;
每条路径计算两次延迟,一次起点为上升沿,另一次起点为
下降沿;
在每个路径组里找出关键路径(critical path),即延迟最大的
路径;
显示每个时间组的时间报告。
关于怎么阅读时序报告,我们后面进行介绍。
DC 的默认行为是对关键路径作优化。当它不能为关键路径找到
一个更好的优化解决方案时,综合过程就停止。DC 不会对次关
键路径(Sub-critical paths)作进一步的优化。因此,如果关键路
径不能满足时序的要求,违反时间的约束,次关键路径也不会被
优化,它们仅仅被映射到工艺库,如下图所示:
对于下面的电路,假设加设计约束后,所有的路径属于同样的时
钟组,也就是只有一个路径组:
如果组合电路部分的优化不能满足时序要求,并且关键路径在组
合电路里,根据 DC 的默认行为,组合电路中关键路径的优化将
会阻碍了与它属于相同时钟组的寄存器和寄存器之间路径的优
化。防止出现这种情况可用下面两种方法:自定义路径组和设置
关键范围。
综合时,工具只对一个路径组的最差(延时最长)的路径作独立的
优化,但并不阻碍另外自定义路径组的路径优化。产生自定义路
径组也可以帮助综合器在做时序分析时采用各自击破
报告每个时序路径组的时序路径。这样可以帮助我们对设计的某
个区域进行孤立,对优化作更多的控制,并分析出问题所在,如
下图所示的:
产生自定义路径组的命令如下所示:
l_outputs]
上面的命令产生三个自定义的路径组,加上原有的路径组,即寄
径组),现在有 4 个路径组。组合电路的路径,属于“COMBO”
组,由于该路径组的起点是输入端,在执行
后,命令中用了选项“-from [all_inputs]",它们原先属于
“INPUTS”组。在执行“group_path -name
被移到“OUTPUTS”组,因为开关选项‘'-from”的优先级高
于选项”-to”,因此组合电路的路径还是留在“INPUTS”路径
组。但是由于
“group_path -name COMBO -from [all_inputs]
-to [all-outputs]”命令中同时使用了开关选项“-from”和
“-to" ,组合电路路径的起点和终点同时满足要求,因此它们最
终归属于“COMBO”组。DC 以这种方式工作来防止由于命令
次序的改变而使结果不同。我们可以用 report_path_group 命
令来得到设计中时序路径组的情况。
产生自定义的路径组后,路径优化如下图所示,此时,寄存器和
寄存器之间的路径可以得到优化:
DC 可以指定权重进行优化,当某些路径的时序比较差的时候,
可以通过指定权重,着重优化该路径。权重最高 5,其次是 2,
DC 默认只对一个路径组内的关键路径进行时序优化,但是我们
可以设置 DC 在关键路径的延时下面某个延时值之内的路径进
行优化,因此我们可以使用下面的命令设置关键范围:
set_critical_range 2 [current_design]
路径作优化,解决相关次关键路径的时序问题可能也可以帮助关
键路径的优化。时序优化的示意图如下所示:
变差,DC 将不改进次关键路径的时序。我们建议关键范围的值
不要超过关键路径总值的 10%。
自定义路径组+关键范围
这是将自定义路径组合关键范围结合起来,也就是在每一个路径
组用指定的关键范围来设置设计的关键范围,命令如下所示:
同时使用自定义时序路径组和关键范围,会使 DC 运行时间加长,
并且需要使用计算机的很多内存。但这种方法值得一试,因为
DC 默认地只在每个路径组优化关键路径。如果在一条路径上关
键路径不能满足时间,它不会尝试其他的方法对该时序路径组的
其他路径做优化。如果能使 DC 对更多的路径做优化,它可能在
对设计的其他部分做更好的优化。在数据通路的设计中,很多时
序路径是相互关联的,对次关键路径的优化可能会改进关键路径
的时序。设置关键范围后.即使 DC 不能减少设计中的最差负数
冗余(Worst NegativeSlack),它也会减少设计中总的负数冗余
下面是自定义路径组和关键范围的主要区别:
自定义路径组: 用户自定义路径组后,如果设计的总性能有改善,
DC 允许以牺牲一个路径组的路径时序(时序变差)为代价,而使
另一个路径组的路径时序有改善。在设计中加入一个路径组可能
会使时序最差的路径时序变得更差。
关键范围: 关键范围不允许因为改进次关键路径的时序而使同一
个路径组的关键路径时序变得更差。如果设计中有多个路径组,
我们只对其中的一个路径组设置了关键范围,而不是对整个设计
中的所有路径组都设置了关键范围,DC 只会并行地对几条路径
优化,运行时间不会增加很多。
④重新划分模块(Repartition Block)
模块的划分是在设计一开始就进行的,但是由于我们是注重 DC 这个工具的
使用,因此放在这里讲解。
层次结构与模块划分:
进行设计的。一些大的设计,其逻辑层次可能多达十几层。SoC 设计中一般
层次化的 IC 设计趋势如下所示:
SoC 设计由一些模块组成,如下图所示:
同样,图中已综合逻辑电路(例如 RISC_CORE),一般也由一些子模块组成。
对于设计复杂规模又大的电路,我们需要对它进行划分(Partitioning),然后
对划分后比较简单规模又小的电路作处理(如综合)。这时,由于电路小,处
理和分析比较方便简单。容易较快地达到要求。再把已处理好的小电路集成
为原来的大电路,如下图所示:
做划分的原因很多,下面是其中的几个原因:
不同的功能块(如 Memory,uP,ADC,Codec、控制器等等);
设计大小和复杂度(模块处理时间适中,设计大小一般设为一个晚上的运
行时间,白天进行人工处理和调试,晚上机器运行,第二天上午检查运
行结果);
方便设计的团队管理项目(每个设计工程师负责一个或几个模块);
设计再使用(设计中使用 IP);
划分模块关系到时序,时序不好的情况下,可以进行重新划分模块,因此就
要求我们在划分模块的时候,对设计进行合适的划分。
可用例化(instantiation)定义设计的层次结构和模块(hierarchical
新的层次结构。如果设计中,我们用符号(+,一,*,/,…)来标示算术运算
电路,我们需要对整个电路作层次结构的设计,对整个设计进行划分,使每
个模块以及整个电路的综合结果能满足我们的目标。
例如下面的设计中:
长,这部分的电路面积较大。 如果我们对设计的划分作出修改,相关的组
综合工具中对组合电路优化的技术现在能得到充分的使用。这时,电路的面
如果我们对设计的划分作另一种修改,如下所示,我们将得到最好的划分:
合电路没有了层次的分隔,综合工具中对组合电路优化的技术能得到充分的
使用。并且,由于组合电路和寄存器的数据输入端相连,综合工具在对时序
电路进行优化时,可以选择一个更复杂的触发器((JK,T,Muxed 和
Clock-enabled 等),把一部分组合电路吸收集成到触发器里。从而使电路
对于一般的设计,好的模块划分如下图所示:
在这样的划分下,模块的输出边界是寄存器的输出端。由于组合电路之间没
有边界,其输出连接到寄存器的数据输入端,我们可以充分利用综合工具对
组合电路和时序电路的优化技术,得到最优的结果,同时也简化了设计的约
束。图中每个模块除时钟端口外的所有输入端口延时是相同的,等于寄存器
在前面的时序路径约束中有说过。
上面是推荐的模块划分模式,下面就来说一下哪些是要避免的模块划分方式。
作模块划分时,应尽量避免使用胶合逻辑(Glue Logic),胶合逻辑如下图
胶合逻辑是连接到模块的组合逻辑。图中,顶层的与非门(HAND gate)仅仅是
个例化的单元,由于胶合逻辑不能被其他模块吸收,优化受到了限制。如果采用
由底向上(bottom up)的策略,我们需要在顶层做额外的编译(compile)。避免
使用胶合逻辑(Glue Logic)的划分如下所示:
胶合逻辑可以和其他逻辑一起优化,顶层设计也只是结构化的网表。不需要再做
编译。
模块划分的修改
第一次的模块划分可能存在时序违规,可能需要重新划分模块,这里就来介绍一
下模块划分的修改问题。我们知道,设计越大,计算机对设计作综合时所需要的
没有限制。我们在对设计做编译时,需要考虑划分模块规模的大小应与现有的计
算机中央处理器(CPU)和内存资源相匹配。尽量避免下面划分不当情况:
模块太小:由于人工划分的模块边界,使得优化受到限制,综合的结果可能不是
最优的。
模块太大:做编辑所需的运行时间可能会太长,由于要求设计的周期短,我们不
能等太久。
一般来说,根据现有的计算机资源和综合软件的运算速度,按我们所期望的周转
作综合时,比较合理的运行时间为一个晚上。白天我们对电路进行设计和修改,
写出编译的脚本。下班前,用脚本把设计输人到 DC,对设计作综合优化,第二
天早上回来检查结果。
设计至少划分为 3 层的层次结构:顶层(Top-level)、中间层(Mid-level)、核心
功能(Functional Core),如下图所示:
测试(Untestable)的、JTAG 电路与工艺相关、异步电路的设计、约束和综合与
同步电路不同,所以也放在与核心功能不同的模块里。
这里主要介绍同步电路的设计与综合。 为了使电路的综合结果最优化,综合的
运行时间适中,我们需要对设计作合适的划分。如果现有的划分不能满足要求,
的命令对划分作修改。下面介绍在 DC 里用命令修改划分。
DC 以两种方法修改划分:自动修改划分和手动修改划分。
自动修改划分:
DC 在综合时将自动取消(去掉)小的模块分区。取消模块分区由变量(前面也有
提及到这些命令):
compile_auto_ungroup_delay_num_cells
compile_auto_ungroup_area_num_cells
辑时取消了那些分区。如在 DC 中使用命令:
compile -ungroup_all
DC 在综合时将自动取消所有的模块分区或层次结构。此时,设计将只有顶层一
手工修改划分:
手动修改划分是指用户用命令指示所有的修改。使用“group”和“ungroup”
命令修改设计里的划分,如下图所示:
group 命令产生新的层次模块,效果如下图所示:
ungroup 命令取消一个或所有的模块分区,效果如下图所示:
如要在当前设计中取消所有的层次结构,可以使用下面的命令:
U3
得到的效果如下图所示:
最后,为了防止再次划分模块,这里总结一下模块划分的策略:
不要通过层次边界分离组合电路
把寄存器的输出作为划分的边界
模块的规模大小适中,运行时间合理
到不同的模块
这样划分好处是:结果更好——设计小又快、简化综合过程——简化约束和脚
本、编译速度更快一一更快周转时间(turnaround)。
下面是实战环节
3、实战
在本次实战里面,我们主要根据给出的原理图和综合规范,实践 DC 的综合优化
技术,在拓扑模式下进行,因此还有可能涉及一些物理设计的内容,我们一步一
步来进行吧。
设计原理图:
(顶层模块示意图:)
(子模块示意图一:)
(子模块示意图二:)
(子模块示意图三:)
综合规范:
(可用资源规范:)
(设计和约束文件说明:)
(布局规划说明:)
(设计规范:)
首先我们来简单分析一下这个综合规范:
可用资源规范:也就是通过运行那个脚本来查看你的电脑有多少可用来综合的核
心,这里我们跳过,不用理他。
位置和名字,RTL 文件和名字以及时序环境等约束都我们不需要改。
布局规划说明:由于我们使用的是拓扑模式下的综合,这个布局规划提供给了我
们物理的约束信息。
设计规范说明:其实这个是综合的规范说明,告诉你需要在综合过程中,要对哪
些模块进行怎么样的处理,从而达到某种要求,这里面的 10 条规范我们后面在
时间过程中都会介绍。
行具体描述)
·进行编写设计约束文件,由于这里一方面没有给出时序和环境属性等方面设计
规范,一方面给出了相关的设计约束文件,因此我们不需要进行撰写了,我来看
一下吧:
时序和环境属性的约束:
从上到下依次是:清除以前的约束、时钟的约束、输入端口延时的约束、输入端
口环境属性的约束、输出端口延时约束、输出端口环境属性的约束。
布局规划中,包含的物理信息,对于了相应地物理约束,如下所示:
约束都给我们准备好了,我们就可以启动 DC 了
·启动 DC,进行读入设计前的检查(这里跟之前的章节一样,不再陈述)
形式验证要用到,命令如下:
set_svf STOTO.svf
·读入设计和检查设计(很前面的章节已经,这里不再陈述)
·执行时序约束,查看约束是否满足,同时执行非默认的物理约束:
source STOTO.con #Design Constrain
check_timing
report_clock
·根据设计规范,应用不同的优化命令:
器到寄存器之间的路径,因此,我们可以进行路径分组,并且更关注时钟那一组,
也就是寄存器到寄存器那一组,优化的命令如下所示:
然后我们可以查看时候进行了设置:report_path_group,得到结果如下:
register_timing,也就是纯的流水线,因此也不能被打散,因此需要设置:
设置之后我们需要查看是否设置正确(设置正确会返回 false )
要设置为 false
解,我们可以这样约束:
然后检查是不是约束成功,或者约束对了:
如下图所示,返回应为 true:
如下所示:
但是输出寄存器不能动,也就是保持原来的寄存器,因此需要约束:
然后检查一下是否正确:
-->保存在综合之前保存一下我们的设计:
·进行综合:
根据要求 8:设计是时序关键的,因此我们要在综合的时候加上-timing 选
-retiming 选项优化进行寄存器、组合逻辑等的优化;综合使用的命令如下
所示:
·综合后检查与处理:
-->综合完成之后,我们可以查查看我们用了哪些特性(这一步可以忽略):
(这些特性都是大把大把地烧钱啊)
-->查看哪些模块是否被打散,即验证与约束的是否一致:
可以知道:MIDDLE, OUTPUT, DONT_PIPELINE, GLUE, ARITH and RANDOM
这些模块都被打散了; 没有被打散的,也就是保存了模块结构的只有下面的这三
的都被打散了,也就是找不到模块的边界了。
-->查看是否有约束违规:
这里我们通过重定义的形式,把生成的时序报告保存到文件中:
-->查看时序报告:
下面我们就来看看这个这个时序报告的一部分吧:
从上面的报告我们可以知道,虽然一些模块被打散了,但是模块的例化名还在,
我们可以通过例化名来找到原件所在的模块,方便我们查看延时不合理时提供定
位;这也就是模块例化名字唯一化的一个好处。
-->保存设计:
得事):
set_svf -off
·查看寄存器是否被移动等操作,也就是查看优化技术的结果细节(有兴趣的可
以仔细看下,深入了解)
些组合逻辑被分割了,我们现在就来看看那些被移动,一方面是纯粹的查看进行
了解一些优化技术,另一方面是看看是否存在约束与预期不符合的情况。
线寄存器被移动过了:
位后缀名是 z1 跟 s1)
-->我们还可以查看例化的名字原来的模块名字,如下所示:
查看原来的 I_IN 模块:
有返回值,说明这个寄存器存在,没有被移动过(移动过之后就被换了例化名字):
然后我们来查看一下 z1_reg,可以看到找不到对象,说明被移动了:
流水线中的寄存器的被命名为 R_* ):
上面是 INPUT 模块中被 retiming 移动的寄存器,我们可以查看该模块是否有不
被移动的寄存器:
get_cells I_IN/*_reg*
有返回值,说明是存在有不被移动的寄存器的。
-->通过下面的命令:
优化的实战部分都这里就结束了,最后,DC 的优化命令有很多,不懂的可以通
过 man 命令查看。
九、逻辑综合后的形式验证
这里来讲一下 formality 的使用,貌似跟 tcl 和 DC 没有很强的联系;然而说没
有联系,也是不正确的。在综合完成之后,可以进行形式验证。此外这里不是专
2、书写相应地流程文件:
3、启动 formality:
fm_shell
-->
-->
-->
-->
4、执行我们写的脚本
得到结果如下,说明验证通过了: