Library Compiler:时序弧建模与约束全解析(一)

相关阅读

Library Compilerhttps://blog.csdn.net/weixin_45791458/category_13154201.html?spm=1001.2014.3001.5482


时序弧主要分为两大类:时序延迟(timing delays),即电路的实际时序行为,以及时序约束(timing constraints),即电路边界处的约束条件。本系列将介绍相关的时序概念,并说明用于设置约束和定义延迟的timing组。

理解时序弧

时序弧(timing arcs)与网表中的互连信息一起,构成了路径分析过程中路径追踪器(path tracer)所遍历的时序路径,这正如静态时序分析:典型与非典型时序路径的约束详解(一)一文所说。每一条时序弧都包含一个起点(startpoint)和一个终点(endpoint)(注意将其与时序路径的起点和终点区分开来),起点可以是输入引脚、输出引脚(似乎不那么常见,见"建模方法的选择"一节)或双向引脚,终点则始终是输出引脚或双向引脚。唯一的例外是约束类时序弧,例如两个输入引脚之间的建立时间(setup)或保持时间(hold)约束。

图1展示了一个与门拥有的两个时序弧,它们都是从输入到输出的延迟类时序弧。

图1 与门的AC和BC时序弧

除此之外,还必须区分组合逻辑类型(combinational timing)和时序逻辑类型(sequential timing)的时序弧,因为两者用途不同,可通过timing组中的timing_type属性进行区分。

Design Compiler使用组合逻辑时序弧信息来计算时序传播过程中的物理延迟,并进行路径追踪,时序分析工具同样依赖这些时序弧来完成电路的时序分析。

Design Compiler使用时序逻辑时序弧信息来确定设计的优化约束(optimization constraint),关于优化约束的更多内容,可以参考下面的博客。

Design Compiler:什么是代价函数(Cost Function)?https://blog.csdn.net/weixin_45791458/article/details/149296216?ops_request_misc=elastic_search_misc&request_id=c62c8dec320922145e6e1d0963128fcc&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-1-149296216-null-null.nonecase&utm_term=cost&spm=1018.2226.3001.4450

组合逻辑时序弧

组合逻辑时序弧用于描述组合逻辑单元的时序信息。该时序弧附着在一个输出引脚(output pin)上,其相关引脚(related pin)可以是输入引脚,也可以是另一个输出引脚。组合逻辑时序弧的timing_type属性可以是以下类型之一(它们都是延迟类时序弧):

  • combinational
  • combinational_rise
  • combinational_fall
  • three_state_disable
  • three_state_disable_rise
  • three_state_disable_fall
  • three_state_enable
  • three_state_enable_rise
  • three_state_enable_fall

时序逻辑时序弧

时序逻辑时序弧用于描述时序逻辑单元的时序信息。在描述时钟沿与数据输出之间关系时,该时序弧被视为延迟类时序弧。而在描述时钟沿与数据输入之间关系时,该时序弧被视为约束类时序弧。时序逻辑时序弧的timing_type属性可以是以下类型之一:

  • 边沿敏感延迟:rising_edge、falling_edge
  • 异步置位和复位延迟:preset、clear
  • 建立/保持时间约束:setup_rising、setup_falling、hold_rising、hold_falling
  • 非时序建立/保持时间约束:non_seq_setup_rising、non_seq_setup_falling、non_seq_hold_rising、non_seq_hold_falling
  • 恢复/移除时间约束:recovery_rising、recovery_falling、removal_rising、removal_falling
  • 不变化约束:nochange_high_high、nochange_high_low、nochange_low_high、nochange_low_low

建模方法的选择

对于如图2所示的组合逻辑单元,其时序信息可以采用两种方式进行建模,如图3所示。

图2 两个反相器组成的单元

在图3中,模型A定义了两条时序弧:第一条时序弧从输入引脚A开始到输出引脚Y结束;第二条时序弧从输入引脚A开始到输出引脚Z结束。这是最简单的建模方式。

对于该单元的模型B,同样包含两条时序弧,但相比模型A更加精确:第一条时序弧从输入引脚A开始到输出引脚Y结束(与模型A相同);第二条时序弧则不同,它从输出引脚Y开始到输出引脚Z结束,该时序弧用于建模输出引脚Y端负载对输出引脚Z延迟的影响。

图3 两种建模方法对比

模型B展示的输出引脚到输出引脚的时序弧既可以用于组合逻辑单元,也可以用于时序逻辑单元。

定义timing组

timing组包含下游工具在建模时序弧和进行路径追踪时所需的信息。它用于定义单元内部的时序弧,以及时钟信号与数据信号之间的关系。timing组可以描述以下内容:

  • 输入引脚和输出引脚之间的时序关系
  • 两个输出引脚之间的时序关系
  • 通过非组合逻辑单元的时序弧
  • 触发器或锁存器输入端的建立时间和保持时间约束(输入引脚到输入引脚)
  • (可选)时序弧的名称

timing组一般定义在pin组(也可以是bundle组)中,其语法如下所示:

复制代码
library (lib_name) {
  cell (cell_name) {
    pin (pin_name) {
      timing () {
        ... timing description ...
      }
    }
  }
}

timing组应定义在时序弧终点所在的pin组中,如"理解时序弧"一节中图示的输出引脚C。需要注意的是,虽然Library Compiler允许在两个引脚之间定义多条时序弧,但其他工具在解析同一对引脚上的多条时序弧时,可能会存在兼容性问题。

使用timing组对时序弧命名

在timing组中,可以为不同的时序弧指定名称。在最简单的情况下,一条时序弧存在于一个已定义的引脚和一个通过related_pin属性指定的相关引脚之间。

然而,在实际建模中,可能会存在多条时序弧,其形式多种多样。下面列出了六种可能的多重时序弧情况,后续章节将进一步说明如何配置这些情况:

  • 单个相关引脚与已定义的bundle组中的多个成员引脚之间
  • 多个相关引脚与已定义的bundle组中的多个成员引脚之间
  • 单个相关引脚与已定义的bus组中的多个比特之间
  • 多个相关引脚与已定义的bus组中的多个比特之间
  • 已定义的bus组中的多个比特与相关bus引脚(具有指定宽度)之间
  • 内部引脚与终点bus组中的所有比特之间
单个引脚与单个相关引脚之间的时序弧

对于单个引脚与单个相关引脚之间的时序弧,可以在timing组中通过指定名称来标识,如下例所示:

复制代码
cell (my_inverter) {
  ...
  pin (A) {
    direction : input;
    capacitance : 1;
  }

  pin (B) {
    direction : output;
    function : "A'";

    timing (A_B) {
      related_pin : "A";
      ...
    } /* end timing() */

  } /* end pin B */
} /* end cell */

该时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| A | B | A_B |

单个引脚与多个相关引脚之间的时序弧

本节描述当timing组位于某个pin组中,且时序弧具有多个相关引脚时,如何标识这些时序弧。如下例所示,可以通过在timing组中使用名称列表来标识多条时序弧。

复制代码
cell (my_and) {
  ...
  pin (A) {
    direction : input;
    capacitance : 1;
  }
  pin (B) {
    direction : input;
    capacitance : 2;
  }
  pin (C) {
    direction : output
    function : "A B";
    timing (A_C, B_C) {
      related_pin : "A B";
      ...
    }/* end timing() */
  }/* end pin B */
}/* end cell */

这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| A | C | A_C |
| B | C | B_C |

bundle组与单个相关引脚之间的时序弧

当timing组位于一个包含多个成员引脚的bundle组中,并且只有一个相关引脚时,需要在timing组中通过名称列表来指定由此产生的多条时序弧。

Library Compiler假定:名称列表中的第一个名称,对应从相关引脚到bundle组的成员列表中第一个引脚的时序弧,名称列表中的第二个名称,对应从相关引脚到bundle组的成员列表中第二个引脚的时序弧,依此类推。下面展示了一个例子。

复制代码
...
bundle (Q){
  members (Q0, Q1, Q2, Q3);
  direction : output;
  function : "IQ";

  timing (G_Q0, G_Q1, G_Q2, G_Q3){
    timing_type : rising_edge;
    related_pin : "G";
  }
}

如果G是一个引脚(而不是另一个bundle组),这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| G | Q0 | G_Q0 |
| G | Q1 | G_Q1 |
| G | Q2 | G_Q2 |
| G | Q3 | G_Q3 |

如果G是另一个成员数为4的bundle组,且G0、G1、G2和G3是G的成员引脚,这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| G0 | Q0 | G_Q0 |
| G1 | Q1 | G_Q1 |
| G2 | Q2 | G_Q2 |
| G3 | Q3 | G_Q3 |

bundle组与多个相关引脚之间的时序弧

当timing组位于一个包含多个成员的bundle组内,并且每个成员都有对应的相关引脚时,需要在timing组中通过名称列表来指定由此产生的多条时序弧。

Library Compiler假定:名称列表中的第一个名称,对应从第一个相关引脚到bundle组的成员列表中第一个引脚的时序弧,名称列表中的第二个名称,对应从第二个相关引脚到bundle组的成员列表中第二个引脚的时序弧,依此类推。下面展示了一个例子。

复制代码
bundle (Q){
  members (Q0, Q1, Q2, Q3);
  direction : output;
  function : "IQ";
  timing (G_Q0, H_Q0, G_Q1, H_Q1, G_Q2, H_Q2, G_Q3, H_Q3){
    timing_type : rising_edge;
    related_pin : "G H";
  }
}

如果G是一个引脚(而不是另一个bundle组),这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| G | Q0 | G_Q0 |
| H | Q0 | H_Q0 |
| G | Q1 | G_Q1 |
| H | Q1 | H_Q1 |
| G | Q2 | G_Q2 |
| H | Q2 | H_Q2 |
| G | Q3 | G_Q3 |
| H | Q3 | H_Q3 |

如果G是另一个成员数为4的bundle组,且G0、G1、G2和G3是G的成员引脚,这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| G0 | Q0 | G_Q0 |
| H | Q0 | H_Q0 |
| G1 | Q1 | G_Q1 |
| H | Q1 | H_Q1 |
| G2 | Q2 | G_Q2 |
| H | Q2 | H_Q2 |
| G3 | Q3 | G_Q3 |
| H | Q3 | H_Q3 |

如果H也是一个成员数为4的bundle组,则适用同样的规则。

bus组与单个相关引脚之间的时序弧

本节描述当timing组位于一个包含多个比特的bus组中,并且这些比特共享同一个相关引脚时,如何标识由此产生的时序弧。可以通过在timing组中使用名称列表来标识这些多条时序弧。

Library Compiler假定:名称列表中的第一个名称,对应从相关引脚到bus组中最高有效位(MSB)的时序弧,名称列表中的第二个名称,对应从相关引脚到bus组中第二个最高有效位的时序弧,依此类推。下面展示了一个例子。

复制代码
...
bus (X){
  /* assuming MSB is X[0] */
  bus_type : bus4;
  direction : output;
  capacitance : 1;

  pin (X[0:3]){
    function : "B'";

    timing (B_X0, B_X1, B_X2, B_X3){
      related_pin : "B";
    }
  }
}

如果B是一个引脚(而不是另一个4位的bus组),这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| B | X[0] | B_X0 |
| B | X[1] | B_X1 |
| B | X[2] | B_X2 |
| B | X[3] | B_X3 |

如果B是另一个4位的bus组,且B[0]是B的最高有效位,这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| B[0] | X[0] | B_X0 |
| B[1] | X[1] | B_X1 |
| B[2] | X[2] | B_X2 |
| B[3] | X[3] | B_X3 |

bus组与多个相关引脚之间的时序弧

本节描述当timing组位于一个包含多个比特的bus组中,并且每个比特都有其对应的相关引脚时所产生的时序弧。可以通过在timing组中输入名称列表来标识这些多条时序弧。

Library Compiler假定:名称列表中的第一个名称,对应从第一个相关引脚到bus组中最高有效位的时序弧,名称列表中的第二个名称,对应从第二个相关引脚到bus组中第二个最高有效位的时序弧,依此类推。下面展示了一个例子。

复制代码
bus (X){
  /* assuming MSB is X[0] */
  bus_type : bus4;
  direction : output;
  capacitance : 1;

  pin (X[0:3]){
    function : "B'";

    timing (B_X0, C_X0, B_X1, C_X1, B_X2, C_X2, B_X3, C_X3){
      related_pin : "B C";
    }
  }
}

如果B是引脚(而不是另一个4位的bus组),这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| B | X[0] | B_X0 |
| C | X[0] | C_X0 |
| B | X[1] | B_X1 |
| C | X[1] | C_X1 |
| B | X[2] | B_X2 |
| C | X[2] | C_X2 |
| B | X[3] | B_X3 |
| C | X[3] | C_X3 |

如果B是另一个4位的bus组,且B[0]是B的最高有效位,这些时序弧的定义如下表所示:

|--------|--------|--------|
| 起点 | 终点 | 名称 |
| B[0] | X[0] | B_X0 |
| C | X[0] | C_X0 |
| B[1] | X[1] | B_X1 |
| C | X[1] | C_X1 |
| B[2] | X[2] | B_X2 |
| C | X[2] | C_X2 |
| B[3] | X[3] | B_X3 |
| C | X[3] | C_X3 |

如果C也是一个4位的bus组,则适用同样的规则。

相关推荐
内有小猪卖17 天前
数字IC设计流程及术语
硬件架构·数字ic
70asunflower1 个月前
研发一款CPU/SoC,到底需要哪些IP和功能单元?
芯片设计·数字ic·模拟ic
日晨难再1 个月前
Power Compiler:UPF模式下的单元映射规则
数字ic
日晨难再1 个月前
Innovus:Cadence那些曾经的布局布线工具
数字ic
日晨难再1 个月前
Genus:Cadence那些曾经的综合工具
数字ic
内有小猪卖1 个月前
Cadence 和 Synopsys 厂家设计流程
硬件架构·数字ic
日晨难再1 个月前
数字IC基础:HDL数字仿真器的历史
数字ic
日晨难再2 个月前
Design Compiler&HDL Compiler:可综合操作符SELECT_OP和MUX_OP的推断和综合
数字ic
日晨难再3 个月前
HDL Compiler:hdlin_preserve_sequential变量和preserve_sequential综合指令的使用
数字ic