本文如果有错,欢迎留言更正;此外,转载请标明出处 http://www.cnblogs.com/IClearner/  ,作者:IC_learner

本文的主要内容是讲解(约束针对的是逻辑综合下的约束,而实战部分则是在DC的拓扑模式下进行):

    ·环境属性的约束

    ·设计规则的约束

    ·面积的约束

    ·实战(部分)环境属性的约束

1、工作环境属性约束

  输入/输出端口及其驱动属性是设计规格的一部分,工作环境的约束,是对这个规格约束的一部分。

  工作环境约束一方面是设置DC的工作环境,也就是DC要从在什么样的环境下对你的设计进行约束,举个例子,比如你的芯片要在恶劣的环境中进行工作,DC如果在优质的环境中对你的设计进行约束,你的芯片生产出来,就很有可能工作不了。因此一般就要告诉DC,使用恶劣的模型对设计进行约束。另一方面是为了保证电路的每一条时序路径延时计算的精确性,特别是输入/输出路径的精确性,单单靠外部的输入延时和输出延时的约束是不够,还要提供设计的环境属性。

这个约束可以看成是宏观的、整体的、外在的约束,约束的内容可以从下图看出:

             

    ·设置环境条件(set_operating_conditions)

  用于描述制造工艺、工作电压与温度(PVT,process,voltage,temperature)这些周围环境对延时的影响。工艺库单元通常用“nominal”电压和温度来描述其默认的特性,例如:

             

  器件与线网上的延时在条件不同的时候呈线性变换。库文件中,包含对各种不同条件的具体描述,如slow,fast,typical等,对于芯片工作的最差、最好及典型的具体描述(具体见标准单元库那一节)。通过设置不同的操作条件,可以覆盖到各种不同的情况。

  如果电路在不同于“nominal”电压和或温度的条件下工作,我们需要为设计设置工作条件(Operating Conditions),我们可以用set_operating_conditions命令把工作条件加入到设计上。综合时,原来按"nominal”环境计算出的单元延迟和连线延迟,将按工作条件作适当的比例调整,如下图为为延迟与工作条件的关系:

           

  讲解完工作环境条件是什么之后,下面就介绍与它有关的常见的命令以及约束。工艺库中通常指定一个默认的工作条件.我们可以用:report_lib  libname命令把厂商提供的所有工作条件列出来。

  设置工作条件可用下面命令举例如下:

  set_operating_conditions  -max $OPERA_CONDITION  -max_library  $LIB_NAME

 

    ·设置线负载模型(set_wire_load_model):

  在计算时序路径延迟时,除了需要知道门单元延迟外,还需要知道连线的延迟,如下图所示:

                

  门单元的延迟一般用非线性延迟模型(non-linear delay model)算出。半导体厂商提供的工艺库中,有两个二维表格,根据门单元的输入转换时间输出负载在表中找出门单元的延迟以及其输出转换时间。输出转换时间又作为下一级电路的输人转换时间。门单元的延迟在综合库那一节详细介绍。

  连线的延迟目前一般用(连)线负载模型( Wire  Load  Model,简称WLM)估算。WLM是厂商根据多种已经生产出来芯片的统计结果,在同样的工艺下,计算出在某个设计规模范围内(例如门数为0~43478.00、门数为43478.00~86956.00,等等)负载扇出为1连线的平均长度,负载扇出为2的连线的平均长度,负载扇出为3的连线的平均长度等等。WLM是根据连线的扇出进行估算连线的RC寄生参数,一般情况下,由半导体厂商建立。厂商根据已生产出来的其他设计统计出该工艺的连线寄生参数。半导体厂商提供的工艺库中包括了线负载模型。通常在一个综合库里面有多种线负载模型,不同的模型模拟不同规模的的模块内的线上负载情况(具体见综合库描述那一节)。用户也可以自己创建自己的线负载模型去更精确地模拟设计内的线上负载。连线负载模型的格式如下图所示(上),具体格式由工艺库决定(下):

           

              

  关于线负载模型的更多内容,可以参考综合库/工艺库那一节。

  线负载模型为DC提供统计性估算的线网负载信息,随后DC使用这些线网负载信息,以负载的大小为函数来模拟线上的延时(也就是设置这个约束是用来模拟线延时)。因此设置线负载模型。

  如DC遇到连线的扇出大于模型中列出的最大扇出值,它将使用外推斜率(Extrapolation slope)来计算连线的长度。上例格式中,如果连线的扇出为7,而连线负载模型中最大扇出是5,连线的其长度计算如下:

        

        

  讲完线负载模型是什么东西,为什么设置线负载模型约束之后,下面介绍与其相关的命令。

  如果要查看工艺库中的WLM,可以使用命令:report_lib  $lib_name,进行综合时,综合工具会默认根据设计面积和节点处的负载自动选择合适的连线负载模型,如果要关掉自动选择WLM,那么可以使用命令:

    set  auto_wire_load_selection  false

  然后手动选择线负载模型的命令是:

    set_wire_load_model  -name  $WIRE_LOAD_MODEL  -library  $LIB_NAME

  如果连线穿越层次边界,连接两个不同的模块,那么有三种方式对这种跨模块线连接的类型进行建模,set_wire_load_mode命令用于设置连线负载模型的模式。有三种模式供选择:top、segment和enclosed。三种模式的示意图如下所示:

             

 

             

  由图可见, 该设计的顶层设计(top)包括一个子模块, 该子模块又包括两个更小的模块。 顶层设计对应的连线负载模型为50×50; 子模块对应的连线负载模型为40×40;更小的两个模块对应的负载模型为20×20和30×30。

  假设有一个连线贯穿两个小模块, 但没有超出子模块的范围。 对于这种连线, 在三种模式下, 所用的连线负载模型是不同的,下面是介绍:

  比较悲观的形式:这时,top为顶层设计,电路的规模比SUB模块大,连线负载模型最悲观。在top模式下, 采用top层的连线负载模型, 即50×50;因此,连线的延迟最大。我们一般选用这种方式,命令如下:

        set_wire_load_mode  top 

  比较不悲观方式:用enclosed的方式选择WLM,该W LM对应的设计完全地包住这条连线,这时DC将选择SUB模块对应的连线负载模型。在enclosed模式下, 采用子模块的连线负载模型, 即40×40;因SUB模块比较TOP设计小,所以连线的延迟比较短(不悲观,就是连线延时小)。对应的命令为:

      set_wire_load_mode   enclosed

   在segmented模式下, 位于两个小模块中的部分采用这两个小模块对应的连线负载模型,  中间部分采用子模块的连线负载模型。

 

 

  驱动强度、电容负载这些约束是要经验的,一方面是对I/O口进行约束,属于I/O口的约束,为时序约束与时序分析提供了路径,更是为输入/输出路径延时约束的精确性提供保证;一方面是对I/O口对外的环境进行约束,可以算是属于环境约束,因此放在这里进行讲解。

 

    ·设置驱动强度(set_drive与set_driving_cell)

  为input或者inout的端口设定驱动。Set_drive以电阻值为计量,0表示最大驱动强度,通常为时钟端口;而set_driving_cell则以模拟端口驱动的器件形式计量,说明输入端口是由一个真实的外部单元驱动。

  为什么要需要为input或者inout的端口设定驱动?这是因为,对于输入端,为了精确计算输入电路的延时时间,DC需要知道到达输入端口转换时间

           

  在默认情况下,DC假设输入端口上的外部信号转换时间是0 ,也就是从上升沿跳变到下降沿或者下降沿跳变到上升沿的时间是0,这是不符合实际情况的。通过设置驱动强度,就告诉DC这个设输入端口实际上是由一个真实的外部单元驱动的,不是理想的;DC就会计算输入信号的实际转换时间,仿佛指定某一个库单元正在驱动输入端,下面是输入端IN1 由FD1的输出引脚驱动的例子:

           

  对应的约束可以这样写:

      set_driving_cell  -lib_cell  FD1  -pin  Q  [get_potrs  IN1]

如果不用开关选项“-pin",DC将使用所找到的第一只引脚(库中这个单元的第一个引脚,这个驱动引脚貌似是要选择输出的引脚)。

   此外,除了通过这两种方式,还可以直接设置输入端口的转换时间,如下所示:

        set_input_transition   时间    [get_ports 设计对象]

 

 

    ·设置电容负载(set_load与set_load load of)

  明确说明端口(输入或输出)上的外部电容负载。对于输出端,为了精确地计算输出电路的延时时间,DC需要知道输出单元所驱动的总负载:

           

  默认情况下,DC假设端口上的外部电容负载为0。我们可以指定电容负载为某些常数值,也可以通过用loacl_ of选项明确说明电容负载的值为工艺库中某一单元引脚的负载(一般是选择输入引脚

           

  跟设计输入输出延时一样,设计者往往并不知道每个模块输入端口的外部驱动单元和/或输出端口的外部输出负载。因此我们要通过负载预算(Load Budget),为输入/输出端口设置环境的约束。产生负载的原则如下:

    1.保守起见,假设输入端口为驱动能力弱的单元驱动(即转换时间长);

    2.限制每一个输入端口的输入电容(负载);

    3.估算输出端口的驱动模块数目。

  例如:(只是举例)对于下面的电路图:

           

  其规格为:模块输入端口驱动的负载不大于10个“AND2”门的输入引脚的负载,模块输出端口最多允许连接3模块,如果某个输出端需要连接多于3个模块,我们要在代码中复制该输端口

对应的约束为:

           

  环境约束举例如下所示:

           

  语法中,设置(定义变量时),如上面的:

    Set  ALL_IN_EXCEPT_CLK  [remove_from_collection [all_inputs]  [get_ports  $CLK_NAME]]中,后面的remove_from_collection是移除设计物集对象的意思,我们知道,DC可以将设计识别成多个对象,比如输入端口、输出端口等等,然后这个就是从all_inputs这个对象集合中,移除掉CLK_NAME这些代表的端口;如果命令之中有命令时,需要用[]来括起来。

  然后是expr是表达式求值的意思,因为load_of取出了一个端口的负载值(因为哟load_of这个命令,即命令中有命令,因此需要加[]),这个值*10 是个表达式,因此用expr来指出求值,求值是一个命令,因此用[]括了起来。

  上面中,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_CLKMAX_LOAD变量,其中ALL_IN_EXCEPT_CLK变量代表了除了时钟之外的输入管脚。MAX_LOAD变量就表示了最大的负载,代表的是库中某个单元的输入负载值。

最后面的就是设置工作环境了。

 

2、设置设计规则约束

  set_max_transition、set_max_fanout、set_max_capacitance

  主要是设置最大转换时间、最大扇出及最大负载电容要求,可以设置在输入端口、输出端口以及当前设计。举个前面的环境约束的例子说,比如我约束了输入端口的最大转换时间和负载,也约束输出最大扇出,如下图所示:

               

 

  当综合和优化了,计算发现输入端口实际的转换时间约束的大,或者负载比约束的大(模块输入端口驱动的负载大于10个“AND2”门的输入引脚的负载),或者检测到输出端口的扇出数比约束的要多(模块输出端口最多允许连接3模块,如果某个输出端需要连接多于3个模块),这时候就违背了设计规则,DC就会报错了。

  半导体厂商在工艺库强加了设计规则。这些规则根据电容、转换时间和扇出(capacitance,transition和fanout)来约束有多少个单元可以相互联结。设计规则一般由半导体厂商提供,在使用工艺库中的逻辑单元时对其联结所强加的限制。例如,如果设计中一个逻辑单元的负载(其驱动的负载)大于库中给定的其最大负载电容(max_capacitance)值,半导体厂商将不能保证该电路能正常工作。我们只可以按照设计规则的约束或按照更严格的设计规则约束来设计电路,而不可以放松约束。Design Compiler在综合时使用加入缓冲器(buffering)和改变门单元的驱动能力(cell sizing)技术来满足设计规则的目标。

  库单元的设计规则(design rule)一如下所示:

                 

  在约束工作环境的时候,调用了库中的一些单元(的引脚),就相当间接设置了设计规则约束,我们可以不必设置。

下面我们来详细叙述一下DC进行综合时设计规则约束:

  DC在做综合时,把设计规则的优先级设置为最高。优先级的从高到低次序为:最大电容(max_capacitance)、最大转换时间(max_transition)、最大扇出(max_fanout).

  ·最大电容(maxcapacitance)的约束,例如对于下面的电路:

                 

对应的最大的电容约束如下:

    【1】set  DRIVE_PIN  TECH_LIB/invla27/Y

    【2】set  MAX_CAP  [get_attribute   $DRIVE_PIN   max_capacitance]

    【3】set   CONSERVATIVE_ MAX_CAP   [expr  $MAX_CAP  /  2.0]

    【4】set_ max_ capacitance  $CONSERVATIVE_ MAX_CAP  [get_ports  IN1]

  约束的意思是:首先【1】处,我们选择使用综合库里面库单元的一个输出引脚作为设计中预期驱动器的最大允许电容负载,其值通过【2】得到,假设为3.5pf,也就是MAX_CAP = 3.6pf。然后通过【3】设置约束时使用的最大电容变量,除以2是在驱动器增加一些富余量使DC不会给它加满载。最后【4】就是设置输入引脚IN1的最大电容量为CONSERVATIVE_ MAX_CAP,也就是1.8pf。

当设置了输入端口的负载之后,也就是:

      set_load  1.2   [ get_ ports  IN1]

那么DC可以给输入端口 IN1 施加的最大内部负载是:1.8 - 1.2 = .06pf。

  我们可以用“set_max_capacitance 3. 0  $ current_design”命令为整个设计中加入最大电容的设计规则。此处,用了3. 0为最大的电容值,设计时我们可以根据工艺库和电路的具体情况,选用合适的数值。要注意不要施加过度保守的约束,以免严重地限制DC对设计的优化。当然,如果库内定的值不够恰当或者过于乐观,我们可以手动设置,以控制设计的裕量。

 

  ·最大转换时间(max_transition)的设计约束,例如前面的电路,可以进行下面的最大转换时间约束:

    #从工艺库找出设计中预期驱动器的最大允许转换时间,也就是最大转换时间可以像这个引脚这么大,假设其值为0.400ns。

    set   DRIVE_ PIN   TECH_ LIB/invla27/Y

    set   MAX_TRANS  [get_attribute  $DRIVE_PIN  max_transition]

    #在实际驱动的时候,增加一些富余量使DC不会给它加满载,也就是实际上的转换时间不超过CONSERVATIVE_ MAX_TRANS,也就是0.200ns。

    set CONSERVATIVE_ MAX_TRANS  [expr $MAX_TRANS / 2.0}]

    set_ max_transition   $CONSERVATIVE_ MAX_ TRANS  [get_ports   IN1]

  约束之后,DC考虑驱动单元的类型和它的外部负载, DC限制输入端口IN1的内部负载来满足的设计规则,也就满足你这个转换时间,让它不超过该0.2ns。

有时候我们可以在整个设计上施加最大转换时间的设计约束,以帮助防止可能在长连线上出现的慢(长)的转换时间,从而导致设计中出现特别长的延迟。施加最大转换时间的设计约束也可以约束单元输出端的转换时间以减少其功耗。我们可以用’set_max_transition 0. 4  $ current_design,命令在整个设计中加入最大转换时间的设计规则。此处,用了0. 4为最大转换时间值,设计时我们可以根据工艺库和电路的具体情况,选用合适的数值。要注意不要人为地加紧对整个设计的约束,以免限制DC对设计中真正关键器件的适当优化。

 

  ·最大扇出(max_fanout)的设计规则的约束,例如对于下面的电路:

           

  用set_max_fanout命令为设计设置最大扇出的设计规则的约束,例如:

      set_max_fanout   6   [get_ports   IN1]

  要注意set_max_fanout命令使用的是扇出负载(fanout_load),而不是绝对的扇出数目。端口的扇出负载之和必须小于最大扇出的设计规则的约束。进行上面的约束之后,DC在综合时会查看有没有违反规则,我们也可以自己查看有没有违反设计规则,用下面命令可以得到单元invla和invla27的扇出负载:

    get_attribute  TECH_LIB/invla1/A   fanout_load   --->比如说是0.25

    get_attribute  TECH_LIB/invla27/A   fanout_load  --->比如说是3.0

因此就有DC可以在端口IN1连接6/0.25=24个invla1单元,或在端口IN1连接6/3. 00=2个invla27单元。但是对于上面的电路,其IN1端口的扇出负载之和为:

    3*fanout_load(invla1/A)+ 2*fanout_load(invla27/A)=(3 x 0.25)+(2x3.0)=6.75

因此,电路违反了最大扇出负载的设计规则约束。

  与扇出有关的还有线负载模型,线负载模型根据连线的扇出数目来估算连线电阻和电容值。连线的扇出数目定义为单元输出引脚与其他单元的输入引脚之间连接的数目。与连线的扇出数目不同,扇出负载属性是附加在单元的输入端口,不同单元可以有不同的扇出负载属性。

  我们可以用如下的命令限制整个设计的扇出负载:set_max_fanout  6  $current_design ,在对FPGA做综合,常常使用此命令。它也适用于ASIC的综合,特别是线负载模型和单元的输入负载不大精确时使用。

  一些工艺库中,某些单元的引脚没有扇出负载属性。这时,DC会检查库中默认的扇出负载属性(default_fanout_load) 。如果库中没有默认的扇出负载属性,DC假设其值为“0",即这些单元的引脚不受扇出负载的设计规则约束我们可以强制使端口的扇出数目为1,即只与一个单元连接,如果库中单元的扇出负载最小值为1. 0,用下面的命令加上扇出负载的设计规则约束:

    set_max_fanout  1.0  [all_inputs]

如果库中单元的扇出负载最小值不为1. 0,我们需要先找出扇出负载最小的单元(假设为bufla1),计算出其扇出负载值,然后加上扇出负载的设计规则约束:

    set   SMALL_CELL   TECH_LIB/bufla1/A

    set   SMALL_FOL   [get_attribute   $SMALL_CELL   fanout_load]

    #库中单元的扇出负载最小值为0. 5000

    set_max_fanout   $SMALL_FOL    [all_inputs]

  扇出负载值是用来表示单元输人引脚相对负载的数目,它并不表示真正的电容负载,而是个无量纲的数字

  如果我们所用的所有库单元扇出负载为“1",那么set_max_fanout 1. 0   [all_inputs]约束将强制所有的输人端口扇出数目为1,即它们只能与一个单元连接。否则,为了使输入端口只能与一个单元连接,我们要找出库中哪一个单元的扇出负载最小,在set_max_ fanout命令中使用这个值来保证在这个端口上只连接一个单元。如果单元上没有扇出负载属性并且库中本身也没有(默认)预设的扇出负载属性,那么把它设为1. 0是有意义和效用的。我们也可以在输出端口上指定扇出负载值。例如,假设一个内部单元驱动几个其他的单元并且也同时驱动一个输出端口。我们可以用set_ load命令来指定那个输出端口的实际电容负载。set_ load命令帮助DC在综合时遵从驱动单元的最大电容设计规则,但该命令并没有为驱动单元的扇出提供独立的约束。在输出端口使用set_ fanout_ load命令时,我们可以为输出端口建立额外的预期扇出负载模型,综合时DC同时也会使内部驱动单元的最大扇出遵守设计规则的要求。

可以使用下面命令report_constraint   -all_violators查看是否违反设计规则。

 

3、面积约束

下面就是进行面积的约束,也就是告诉DC综合的电路面积要在多少以内。在介绍约束命令之前,先了解一下面积的单位。面积的单位可以是:

  ·2输入与非门(2-input-NAND-gate)

  ·晶体管数目(Transistors)

  ·平方微米(Square microns)

  此外,我们往往看到一个芯片是多少多少门,这多少门的数字就是拿芯片的总面积,除以2输入与非门的面积得到的数值。用report_lib命令不可显示面积的单位,我们要询问半导体厂商面积的单位是什么。

  如果不设置面积的约束,Design Compiler将做最小限度的面积优化。设置了面积的约束后,DC将在达到面积约束目标时退出的面积优化。如果设置面积的约束为“0" , DC将为面积做优化直到再继续优化也不能有大的效果。这时,DC将中止优化。注意,对于很大(如百万门电路)的设计,如将面积的约束设置为“0" , DC可能要花很长的时间为设计做面积优化。综合时,运行的时间很长。

  在超深亚微米(deep sub-micro)工艺中,一般说来,面积并不是设计的主要目标,对设计的成本影响不大。因此,我们在初次优化时,可以不设置面积的约束。优化后,检查得到的设计面积,然后将其乘上一个百分数(例如8500),将其结果作为设计的面积约束。再为设计做增量编辑,运行“compile -inc”命令,为面积做较快的优化。这样做,既可以优化面积,又可以缩短运行时间。

  最后我们用set_max_area命令为设计作面积的约束。例如:

      set_max_area  10000

  当设计不是很大的时候,根据上面的描述,我们就可以使用下面的命令进行面积约束:

      set_max_area  0

让DC做最大的面积优化约束。

 

 

4、实战

由于种种原因,这里只有环境属性的约束的实战,其他的约束也可以通过上面的讲解和下面的这个实战进行设计。

首先,我们来看看设计约束规格:

(设计原理图)

            

 

(设计规范)

在前面一节的基本时序约束规范上加上下面的规范:

            

·DC启动环境的设置我们根据设计原理图和设计规范开始进行实践:

(跟上一节一样,这里不再重复)

 

·约束文件的编写

  基本的时序路径约束和上一节一样,不进行改动,下面进行工作环境的约束:

-->输入端口的驱动设置:

  1.要我们使用库里面的bufbd1来驱动除了clk和Cin*之外的所有输入端口:

    这里是直接使用库里面的单元来驱动的,根据前面的讲解,我们很容易得到约束的命令为:

  set_driving_cell  -lib_cell  bufbd1  -library  cb13fs120_tsmc_max  [remove_from_collection  [all_inputs]  [get_ports "clk Cin*"]]

  (命令的格式为)set_driving_cell  -lib_cell  单元的名字  -library  单元所在库的名字  要设置约束的对象

    注意:当一条命令太长,要进行分割时,使用反斜杠\作为分隔符,且反斜杠后面不能加空格。

  2.Cin*是芯片级的端口,需要加上120ps的最大转化时间,这是直接设置转换时间,因此可以这样约束:

      set_input_transition  0.12  [get_ports  Cin*]

-->输出负载的约束:

  1.除了cout输出,其它输出驱动值都是库单元bufbd7的引脚I负载值的两倍,也就是用单元的端口进行约束,因此有:

      set_load [expr 2 * {[load_of cb13fs120_tsmc_max/bufbd7/I]}] [get_ports out*]

  2.cout驱动最大值为25pf的负载,因此可以这样设置:

    set_load 0.025 [get_ports Cout*]

-->操作环境的设置:

   由于用到了库里面的单元,我们还在最好设置一下操作环境,虽然DC可以从启动环境里面找到单元所在的位置库,但是我也要设置操作环境,如下所示:

      set_operating_conditions -max cb13fs120_tsmc_max

 

下面的步骤跟前面的一样,这里就不展开描述了:

·启动DC,设计读入前的检查

 

·读入设计和检查设计

 

·执行约束和检查约束

 

·进行综合

...

 

posted on 2017-03-27 20:51  IC_learner  阅读(29110)  评论(8编辑  收藏  举报