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

相关阅读

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


定义timing组

延迟模型

timing组中包含了很多属性,其中延迟模型决定了在timing组中需要指定的延迟计算方式。单元延迟通常在逻辑库中进行建模,综合工具在优化过程中使用这些模型来预测单元延迟。互连延迟则是在综合过程中根据逻辑库中提供的线负载模型(如果工具处于线负载模式)或使用虚拟布线(Virtual Routing)(如果工具处于拓扑模式)进行估算。

对于线负载模式和拓扑模式的更多介绍,可以参考下面的博客。

Design Compiler:什么是拓扑技术(Topographical)?https://blog.csdn.net/weixin_45791458/article/details/145748306?ops_request_misc=elastic_search_misc&request_id=050cd28bb9cd705c503625b79df7bad8&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-3-145748306-null-null.nonecase&utm_term=%E6%8B%93%E6%89%91%E6%A8%A1%E5%BC%8F%E6%A8%A1%E5%9E%8B&spm=1018.2226.3001.4450Design Compiler:两种工作模式(线负载模式和拓扑模式)https://blog.csdn.net/weixin_45791458/article/details/144830461?ops_request_misc=elastic_search_misc&request_id=050cd28bb9cd705c503625b79df7bad8&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-1-144830461-null-null.nonecase&utm_term=%E6%8B%93%E6%89%91%E6%A8%A1%E5%BC%8F%E6%A8%A1%E5%9E%8B&spm=1018.2226.3001.4450

早期的Design Compiler支持多种延迟模型,比如CMOS线性延迟模型、CMOS分段线性延迟模型、CMOS2线性延迟模型、延迟计算模块延迟模型和扩展多项式延迟模型,但它们大多已经过时,目前仅支持CMOS非线性延迟模型(NLDM)。关于线性延迟模型和非线性延迟模型的更多介绍,可以参考下面的博客。

Design Compiler:线性延迟模型和非线性延迟模型https://blog.csdn.net/weixin_45791458/article/details/146131977?ops_request_misc=elastic_search_misc&request_id=7886e80d5fe2c28c56eb630856710529&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-1-146131977-null-null.nonecase&utm_term=%E5%BB%B6%E8%BF%9F%E6%A8%A1%E5%9E%8B&spm=1018.2226.3001.4450

NLDM通过定义时序弧的查找表进行表征,要使用该模型描述延迟类或约束类时序弧,需要:

  • 使用库级的lu_table_template组来定义查找表中所使用的公共信息模板(templates)
  • 使用这些模板以及本章中描述的timing组来创建查找表

查找表及其对应的模板可以是一维、二维或三维的。

delay_model属性

要指定延迟模型,可以在library组中使用delay_model属性。如果没有technology属性,delay_model属性必须作为library组中的第一个属性;否则,它应紧跟在technology属性之后。早期的delay_model属性支持generic_cmos(CMOS线性延迟模型)、piecewise_cmos(CMOS分段线性延迟模型)、cmos2(CMOS2线性延迟模型)、dcm(延迟计算模块延迟模型)、polynomial(扩展多项式延迟模型),目前仅支持table_lookup(CMOS非线性延迟模型)。

下面展示了delay_model属性的用法。

复制代码
library (demo) {
  delay_model : table_lookup;
}
定义NLDM模板

表模板用于存储可被多个查找表复用的通用表信息,指定表的参数以及各个轴上的断点(breakpoints)。需要为每个模板指定名称,以便查找表可以引用它。

若要定义查找表模板,可以在library组中使用lu_table_template组,语法如下所示。

复制代码
lu_table_template(lu_table_template_name) {
  variable_1 : value;
  variable_2 : value;
  variable_3 : value;
  index_1 ("float, ..., float");
  index_2 ("float, ..., float");
  index_3 ("float, ..., float");
}

Library Compiler提供了一个预定义的查找表模板scalar,用于那些只包含单个数值的表。

用于时序延迟(延迟类时序弧)的模板变量

用于描述时序延迟的表模板最多可以包含三个变量(variable_1、variable_2和variable_3)。这些变量表示查找表第一、第二和第三轴上的索引参数,分别用三类表示:第一类是输入引脚的转换时间:input_net_transition;第二类是输出引脚连接线网的长度和负载电容:total_output_net_capacitance、output_net_length、output_net_wire_cap和output_net_pin_cap;第三类是相关引脚连接线网的长度和负载电容related_out_total_output_net_capacitance、related_out_output_net_length、related_out_output_net_wire_cap和related_out_output_net_pin_cap。

对于每一个表,分配给不同变量的值必须来自不同的类,下表列出了不同维度下变量取值的组合方式。

|----------|----------------|----------------|----------------|
| 模板维度 | variable_1 | variable_2 | variable_3 |
| 1 | 第一类 | - | - |
| 1 | 第二类 | - | - |
| 2 | 第一类 | 第二类 | - |
| 2 | 第二类 | 第一类 | - |
| 3 | 第一类 | 第二类 | 第三类 |
| 3 | 第一类 | 第三类 | 第二类 |
| 3 | 第二类 | 第一类 | 第三类 |
| 3 | 第二类 | 第三类 | 第一类 |
| 3 | 第三类 | 第一类 | 第二类 |
| 3 | 第三类 | 第二类 | 第一类 |

用于负载相关约束(约束类时序弧)的模板变量

用于描述负载相关约束的表模板最多也可以包含三个变量。这些变量表示查找表第一、第二和第三轴上的索引参数,分别用三类表示:第一类是受约束引脚的转换时间:constrained_pin_transition;第二类是相关引脚的转换时间:related_pin_transition;第三类是相关引脚连接线网的长度和负载电容related_out_total_output_net_capacitance、related_out_output_net_length、related_out_output_net_wire_cap和related_out_output_net_pin_cap。

对于每一个表,分配给不同变量的值必须来自不同的类,下表列出了不同维度下变量取值的组合方式。

|----------|----------------|----------------|----------------|
| 模板维度 | variable_1 | variable_2 | variable_3 |
| 1 | 第一类 | - | - |
| 1 | 第二类 | - | - |
| 2 | 第一类 | 第二类 | - |
| 2 | 第二类 | 第一类 | - |
| 3 | 第一类 | 第二类 | 第三类 |
| 3 | 第一类 | 第三类 | 第二类 |
| 3 | 第二类 | 第一类 | 第三类 |
| 3 | 第二类 | 第三类 | 第一类 |
| 3 | 第三类 | 第一类 | 第二类 |
| 3 | 第三类 | 第二类 | 第一类 |

模板断点

index属性用于定义各个轴上的断点:index_1属性对应variable_1的参数取值;index_2属性对应variable_2的参数取值;index_3属性对应variable_3的参数取值。

断点值为浮点数列表,数值必须大于等于0,且按照递增顺序排列,每一维的大小由该index属性中浮点数的个数决定。

创建查找表

查找表的指定规则既适用于延迟类时序弧,也适用于约束类时序弧。创建查找表的语法如下所示。

复制代码
lu_table_name(lu_table_template_name) {
  index_1 ("float, ..., float"); /*optional*/
  index_2 ("float, ..., float"); /*optional*/
  index_3 ("float, ..., float"); /*optional*/
  values("float, ..., float", ..., "float, ..., float");
}

以下规则适用查找表组:

1、每个查找表都关联一个lu_table_template组的名称,该名称必须与库中定义的lu_table_template组名称完全一致。

2、可以在查找表中覆盖模板中的部分或全部index属性,但必须在定义values属性之前完成覆盖。

3、查找表的延迟值存储在values属性中:对于转换时间表(或者称为转换延迟表),其值必须大于等于0;对于传播延迟表和单元延迟表,可以包含负延迟值。对于一维表,延迟值用一个包含length(index_1)个浮点数的列表表示;对于二维表,延迟值用一个包含length(index_1)*length(index_2)个浮点数的列表表示;对于三维表,延迟值用一个包含length(index_1)*length(index_2)*length(index_3)个浮点数的列表表示。如果表中只有一个值,可以使用预定义的scalar表模板作为查找表的模板。

4、每一组用引号括起来的浮点数表示表中的一行:对于一维表,每组浮点数的数量必须等于length(index_1);对于二维表,每组浮点数的数量必须等于length(index_2),组的数量必须等于length(index_1);对于三维表,每组浮点数的数量必须等于length(index_3),组的数量必须等于length(index_1)*length(index_2)。

timing组中的属性

下表列出了timing组中的部分属性或组。

|----------------------------------------|-----------------------------------|
| 用途 | 属性或组 |
| 指定默认时序弧 | default_timing |
| 标识时序弧的起点(即相关引脚) | related_pin、related_bus_pins |
| 描述输入引脚对输出引脚的逻辑影响 | timing_sense |
| 将一条时序弧标识为组合逻辑类型或时序逻辑类型 | timing_type |
| 指定转换时间(转换延迟) | rise_transition、fall_transition |
| 指定总单元延迟中的传播延迟(不能与单元延迟表一起使用,需与转换延迟一起使用) | rise_propagation、fall_propagation |
| 指定单元延迟(不能与传播延迟表一起使用) | cell_rise、cell_fall |
| 指定retain延迟 | retaining_rise、retaining_fall |
| 为负载相关模型指定一个输出引脚 | related_output_pin |
| 指定时序弧何时有效 | mode |

related_pin属性定义作为时序弧起点的一个或多个引脚,主要用途是用于关联时序弧中的多个信号,该属性是所有timing组的必需组成部分。

下面展示了related_pin属性的用法。

复制代码
pin (B){
  direction : output ;
  function : "A'";
  timing () {
    related_pin : "A" ;
    ...
  }
}

正如Library Compiler:时序弧建模与约束全解析(一)一文中的"单个引脚与多个相关引脚之间的时序弧"小节所说,可以将related_pin属性作为一种快捷方式,用于为一个单元定义两条相同的时序弧。

例如,对于一个两输入NAND门,如果从两个输入引脚到输出引脚的延迟相同,那么只需要定义一条带有两个相关引脚的时序弧即可,如下面例所示。

复制代码
pin (Z) {
  direction : output;
  function : "(A * B)'" ;
  timing () {
    related_pin : "A B" ;
    ... timing information ...
  }
}

当在related_pin属性中使用bus组时,该bus组的成员或成员范围会分布到related_pin属性所属bus组的各个比特中,如Library Compiler:时序弧建模与约束全解析(一)一文中"bus组与多个相关引脚之间的时序弧"小节所说。

下面展示了一个例子,其中A和B的宽度相同。

复制代码
bus (A) {
  bus_type : bus2;
  ...
}
bus (B) {
  bus_type : bus2;
  direction : output;
  pin(B[0:1]){
    function : "A'";

    timing () {
      related_pin : "A" ;
      ... timing information ...
    }
  }
}

描述的时序弧是从A中的每个比特到B中的对应比特:A[0]到B[0]、A[1]到B[1]。

related_bus_pins属性定义作为时序弧起点的一个或多个引脚,主要用途是用于模块生成器。下面展示了一个例子,其中A和B的宽度可以不相同。

复制代码
​bus (A) {
  bus_type : bus2;
  ...
}
bus (B) {
  bus_type : bus4;
  direction : output;
  pin(B[0:3]){
    function : "A'";

    timing () {
      related_bus_pins : "A" ;
      ... timing information ...
    }
  }
}

​

描述的时序弧是从A中的每个比特到B中的每个比特:A[0]到B[0]、A[0]到B[1]、A[0]到B[2]、A[1]到B[0]、A[1]到B[1]、A[1]到B[2]。

timing_sense属性

timing_sense属性描述输入引脚在逻辑上影响输出引脚的方式(单调性)。时序分析器在路径分析过程中使用该属性来跟踪单元的极性转换。

下面展示了timing_sense属性的用法。

复制代码
timing () {
  timing_sense : positive_unate;
}

Design Compiler通常会根据引脚的逻辑功能推导timing_sense属性的值。例如,对于AND门,推导出的值是正单调性(positive_unate);对于NAND门,该值是负单调性(negative_unate);对于XOR门,该值是非单调性(non_unate)。

除非必须覆盖推导值,或者正在表征三态组件等非组合门,否则不要定义某个引脚的timing_sense属性。例如,当用户对一个输入引脚和一个输出引脚之间的多条路径进行建模时,可能需要手动定义timing_sense属性,例如在XOR门中。

如果一个输入的上升(或下降)变化会使输出上升(或下降)或者保持不变,则该函数是正单调的;如果一个输入的上升(或下降)变化会使输出函数变量下降(或上升)或者保持不变,则该函数是负单调的。对于非单调性,需要更多状态信息来确定某一特定状态转换的影响。可能出现这样的情况:一条路径是正单调性,而另一条路径是负单调性。在这种情况下,第一条时序弧被指定为positive_unate,第二条时序弧被指定为negative_unate。

注意:当timing_sense属性描述用于计算three_state_enable或three_state_disable引脚延迟的转换边沿时,它的含义与传统含义不同。如果三态单元控制引脚上的值1会使输出引脚变为Z值,那么对于three_state_disable时序弧,timing_sense为positive_unate;对于three_state_enable时序弧,timing_sense为negative_unate。如果三态单元控制引脚上的值0会使输出引脚变为Z值,那么对于three_state_disable时序弧,timing_sense为negative_unate;对于three_state_enable时序弧,timing_sense为positive_unate。

如果related_pin属性是一个输出引脚,则必须为该引脚定义timing_sense属性。

关于单调性的更多介绍,可以参考下面的博客。

静态时序分析:时序弧以及其时序敏感(单调性)https://blog.csdn.net/weixin_45791458/article/details/135970796?ops_request_misc=elastic_search_misc&request_id=f12fbb5c805a52bab6cb30a79eac6f22&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-1-135970796-null-null.nonecase&utm_term=%E5%8D%95%E8%B0%83%E6%80%A7&spm=1018.2226.3001.4450

timing_type属性

timing_type属性通过定义时序弧的类型来区分组合逻辑时序弧和时序逻辑时序弧。如果未使用该属性,则默认为组合逻辑时序弧。

必须区分组合时序类型和时序逻辑类型,因为每种类型具有不同用途。Design Compiler使用组合逻辑时序弧信息来计算时序传播过程中的物理延迟,并进行路径追踪。

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

Design Compiler使用时序逻辑时序弧信息来确定设计的优化约束(optimization constraint)。

下面展示了timing_type属性的用法。

复制代码
timing () {
  timing_type : rising_edge;
}

下表展示了timing_type属性的有效取值。

|-----------------------------------------------------------------------------------------------------------------------------------------|-----------|-----------------------------------------------|
| | 单元类型 | 功能 |
| combinational | 组合逻辑 | 描述1到0或0到1的时序弧。当timing组中没有timing_type属性时,这是默认值 |
| combinational_rise、combinational_fall | 组合逻辑 | 描述0到1或1到0的时序弧 |
| three_state_disablethree_state_disable_rise、three_state_disable_fall、three_state_enable、three_state_enable_rise、three_state_enable_fall | 组合逻辑 | 描述三态输出引脚的时序弧 |
| rising_edge、falling_edge | 时序逻辑 | 指定输入信号的哪个边沿会导致输出引脚发生转换 |
| preset、clear | 时序逻辑 | 描述异步置位和复位的时序弧 |
| hold_rising、hold_falling | 时序逻辑 | 描述用于保持时间检查的时序弧 |
| setup_rising、setup_falling | 时序逻辑 | 描述用于建立时间检查的时序弧 |
| recovery_rising、recovery_falling | 时序逻辑 | 描述用于恢复时间检查的时序弧 |
| removal_rising、removal_falling | 时序逻辑 | 描述用于移除时间检查的时序弧 |
| skew_rising、skew_falling | 时序逻辑 | 描述两个时钟信号之间最大间隔的约束,仅用于仿真 |
| minimum_period | 时序逻辑 | 描述用于最小周期检查的时序弧 |
| min_pulse_width | 组合逻辑或时序逻辑 | 描述用于最小脉宽检查的时序弧 |
| max_clock_tree_path、min_clock_tree_path | 时序逻辑 | 描述最大和最小时钟树路径检查的时序弧 |
| non_seq_setup_rising、non_seq_setup_falling、non_seq_hold_rising、non_seq_hold_falling | 组合逻辑或时序逻辑 | 描述与时钟信号无关的数据建立和保持时间检查 |
| nochange_high_high、nochange_high_low、nochange_low_high、nochange_low_low | 时序逻辑 | 描述与时钟脉冲相关的信号脉冲不变化约束 |

下面各小节分类展示了各类型的timing_type属性详细取值描述。

组合逻辑时序弧的取值

timing_type属性和timing_sense属性定义信号传播模式。默认的timing_type属性是combinational。

|--------------------------|--------------------|--------------------|-----------------|
| timing_type属性 | timing_sense属性 |||
| timing_type属性 | positive_unate | negative_unate | non_unate |
| combinational | R->R、F->F | R->F、F->R | {R,F}->{R,F} |
| combinational_rise | R->R | F->R | {R,F}->R |
| combinational_fall | F->F | R->F | {R,F}->F |
| three_state_disable | R->{0Z,1Z} | F->{0Z,1Z} | {R,F}->{0Z,1Z} |
| three_state_enable | R->{Z0,Z1} | F->{Z0,Z1} | {R,F}->{Z0,Z1} |
| three_state_disable_rise | R->0Z | F->0Z | {R,F}->0Z |
| three_state_disable_fall | R->1Z | F->1Z | {R,F}->1Z |
| three_state_enable_rise | R->Z1 | F->Z1 | {R,F}->Z1 |
| three_state_enable_fall | R->Z0 | F->Z0 | {R,F}->Z0 |

时序逻辑时序弧的取值

|---------------------|--------------------------------------------------------------------------------------------------------------------------------------|
| timing_type属性 | 描述 |
| rising_edge | 标识一条时序弧,其输出引脚对输入引脚上的上升信号敏感 |
| falling_edge | 标识一条时序弧,其输出引脚对输入引脚上的下降信号敏感 |
| preset | 置位时序弧只影响该弧终点引脚的上升到达时间,意味着当指定的相关引脚被置有效时,正在输出引脚上施加逻辑1 |
| clear | 复位时序弧只影响该弧终点引脚的下降到达时间,意味着当指定的相关引脚被置有效时,正在输出引脚上施加逻辑0 |
| hold_rising | 指定相关引脚的上升沿用于保持时间检查 |
| hold_falling | 指定相关引脚的下降沿用于保持时间检查 |
| setup_rising | 指定时钟单元上相关引脚的上升沿用于建立时间检查 |
| setup_falling | 指定时钟单元上相关引脚的下降沿用于建立时间检查 |
| recovery_rising | 使用相关引脚的上升沿进行恢复时间检查,时钟为上升沿触发 |
| recovery_falling | 使用相关引脚的下降沿进行恢复时间检查。时钟为下降沿触发 |
| removal_rising | 当单元是低电平使能锁存器或上升沿触发触发器时使用。对于低有效异步控制信号,使用rise_constraint组定义移除时间;对于高有效异步控制信号,使用fall_constraint组定义移除时间 |
| removal_falling | 当单元是高电平使能锁存器或下降沿触发触发器时使用。对于低有效异步控制信号,使用rise_constraint组定义移除时间;对于高有效异步控制信号,使用fall_constraint组定义移除时间 |
| skew_rising | 时序约束区间从相关引脚的上升沿开始测量,到timing组中父引脚的某个转换边沿结束。rise_constraint值是相关引脚上升与父引脚上升之间的最大skew time;fall_constraint值是相关引脚上升与父引脚下降之间的最大skew time |
| skew_falling | 时序约束区间从相关引脚的下降沿开始测量,到timing组中父引脚的某个转换边沿结束。rise_constraint值是相关引脚下降与父引脚上升之间的最大skew time;fall_constraint值是相关引脚下降与父引脚下降之间的最大skew time |
| minimum_period | 与min_pulse_width一起,用于指定时钟引脚的最小脉宽。时序检查在该引脚自身上执行,因此相关引脚应当相同。也可以像其他时序检查一样包含rise和fall constraints |
| min_pulse_width | 与minimum_period一起,用于指定时钟引脚的最小脉宽。时序检查在该引脚自身上执行,因此相关引脚应当相同。也可以像其他时序检查一样包含rise和fall constraints。min_pulse_width属性除了可以为标量值之外,还支持基于表的最小脉宽 |
| max_clock_tree_path | 用于时钟引脚下的timing组。定义最大时钟树路径约束。Library Compiler会检查你没有指定related_pin属性 |
| min_clock_tree_path | 用于时钟引脚下的timing组。定义最小时钟树路径约束。Library Compiler会检查你没有指定related_pin属性 |

非时序逻辑时序弧的取值

在某些非时序单元中,建立时间和保持时间约束被指定在数据引脚上,并以一个非时钟引脚作为相关引脚。为了使单元按预期工作,同一单元中的某个引脚信号必须在另一个引脚达到某种状态之前和之后的指定时间内保持稳定。

|-----------------------|------------------------------------------------------------------------------------------------------------------|
| timing_type属性 | 描述 |
| non_seq_setup_rising | 与non_seq_setup_falling一起,定义用于具有非时序行为的引脚之间建立时间检查的时序弧。时序弧中的相关引脚用于时序检查。_rising标识告诉Design Compiler,相关引脚的上升沿对建立时间检查有效 |
| non_seq_setup_falling | 与non_seq_setup_rising一起,定义用于具有非时序行为的引脚之间建立时间检查的时序弧。时序弧中的相关引脚用于时序检查。_falling标识告诉Design Compiler,相关引脚的下降沿对建立时间检查有效 |
| non_seq_hold_rising | 与non_seq_hold_falling一起,定义用于具有非时序行为的引脚之间保持时间检查的时序弧。时序弧中的相关引脚用于时序检查。_rising标识告诉Design Compiler,相关引脚的上升沿对建立时间检查有效 |
| non_seq_hold_falling | 与non_seq_hold_rising一起,定义用于具有非时序行为的引脚之间保持时间检查的时序弧。时序弧中的相关引脚用于时序检查。_falling标识告诉Design Compiler,相关引脚的下降沿对建立时间检查有效 |

nochange时序弧的取值

使用nochange时序弧来建模带有锁存使能信号的锁存器件的时序要求。这四种nochange在NLDM中定义了受约束信号和相关信号的脉冲波形。这些信息用于综合过程中的静态时序验证。

|--------------------|-------------------------|
| timing_type属性 | 描述 |
| nochange_high_high | 表示受约束引脚上的正脉冲以及相关引脚上的正脉冲 |
| nochange_high_low | 表示受约束引脚上的正脉冲以及相关引脚上的负脉冲 |
| nochange_low_high | 表示受约束引脚上的负脉冲以及相关引脚上的正脉冲 |
| nochange_low_low | 表示受约束引脚上的负脉冲以及相关引脚上的负脉冲 |

mode属性

可以在timing组中定义mode属性,该属性属于单条时序弧。当mode属性以名称和值的形式被实例化时,该时序弧处于有效状态。可以指定多个mode属性实例,但每条时序弧的每个mode属性只能有一个实例。

下面展示了mode属性的语法。

复制代码
mode (mode_name, mode_value);

如果mode_name和mode_value字符串没有事先在cell中通过mode_definition组定义,Library Compiler会发出错误信息。

下面展示了mode属性的用法。

复制代码
/* 一个mode属性实例 */
pin(my_outpin) {
  direction : output;
  timing() {
    related_pin : b;
    timing_sense : non_unate;
    mode(rw, read);
    cell_rise(delay3x3) {
      values("1.1, 1.2, 1.3", "2.0, 3.0, 4.0", "2.5, 3.5, 4.5");
    }
    rise_transition(delay3x3) {
      values("1.0, 1.1, 1.2", "1.5, 1.8, 2.0", "2.5, 3.0, 3.5");
    }
    cell_fall(delay3x3) {
      values("1.1, 1.2, 1.3", "2.0, 3.0, 4.0", "2.5, 3.5, 4.5");
    }
    fall_transition(delay3x3) {
      values("1.0, 1.1, 1.2", "1.5, 1.8, 2.0", "2.5, 3.0, 3.5");
    }
  }
}

/* 多个mode属性实例 */
library (MODE_EXAMPLE) {
  delay_model : "table_lookup";
  time_unit : "1ns";
  voltage_unit : "1V";
  current_unit : "1mA";
  pulling_resistance_unit : "1kohm";
  leakage_power_unit : "1nW" ;
  capacitive_load_unit (1, pf);
  nom_process : 1.0;
  nom_voltage : 1.0;
  nom_temperature : 125.0;
  slew_lower_threshold_pct_rise : 10 ;
  slew_upper_threshold_pct_rise : 90 ;
  input_threshold_pct_fall : 50 ;
  output_threshold_pct_fall : 50 ;
  input_threshold_pct_rise : 50 ;
  output_threshold_pct_rise : 50 ;
  slew_lower_threshold_pct_fall : 10 ;
  slew_upper_threshold_pct_fall : 90 ;
  slew_derate_from_library : 1.0 ;

  cell (mode_example) {
    mode_definition(RAM_MODE) {
      mode_value(MODE_1) {
      }
      mode_value(MODE_2) {
      }
      mode_value(MODE_3) {
      }
      mode_value(MODE_4) {
      }
    }

    interface_timing : true;
    dont_use : true;
    dont_touch : true;

    pin(Q) {
      direction : output;
      max_capacitance : 2.0;
      three_state : "!OE";

      timing() {
        related_pin : "CK";
        timing_sense : non_unate
        timing_type : rising_edge
        mode(RAM_MODE,"MODE_1 MODE_2");
        cell_rise(scalar) {
          values( " 0.0 ");
        }
        cell_fall(scalar) {
          values( " 0.0 ");
        }
        rise_transition(scalar) {
          values( " 0.0 ");
        }
        fall_transition(scalar) {
          values( " 0.0 ");
        }
      }

      timing() {
        related_pin : "OE";
        timing_sense : positive_unate
        timing_type : three_state_enable
        mode(RAM_MODE, " MODE_2 MODE_3");
        cell_rise(scalar) {
          values( " 0.0 ");
        }
        cell_fall(scalar) {
          values( " 0.0 ");
        }
        rise_transition(scalar) {
          values( " 0.0 ");
        }
        fall_transition(scalar) {
          values( " 0.0 ");
        }
      }

      timing() {
        related_pin : "OE";
        timing_sense : negative_unate
        timing_type : three_state_disable
        mode(RAM_MODE, MODE_3);
        cell_rise(scalar) {
          values( " 0.0 ");
        }
        cell_fall(scalar) {
          values( " 0.0 ");
        }
        rise_transition(scalar) {
          values( " 0.0 ");
        }
        fall_transition(scalar) {
          values( " 0.0 ");
        }
      }
    }

    pin(A) {
      direction : input;
      capacitance : 1.0;
      max_transition : 2.0;

      timing() {
        timing_type : setup_rising;
        related_pin : "CK";
        mode(RAM_MODE, MODE_2);
        rise_constraint(scalar) {
          values( " 0.0 ");
        }
        fall_constraint(scalar) {
          values( " 0.0 ");
        }
      }

      timing() {
        timing_type : hold_rising;
        related_pin : "CK";
        mode(RAM_MODE, MODE_2);
        rise_constraint(scalar) {
          values( " 0.0 ");
        }
        fall_constraint(scalar) {
          values( " 0.0 ");
        }
      }
    }

    pin(OE) {
      direction : input;
      capacitance : 1.0;
      max_transition : 2.0;
    }

    pin(CS) {
      direction : input;
      capacitance : 1.0;
      max_transition : 2.0;

      timing() {
        timing_type : setup_rising;
        related_pin : "CK";
        mode(RAM_MODE, MODE_1);
        rise_constraint(scalar) {
          values( " 0.0 ");
        }
        fall_constraint(scalar) {
          values( " 0.0 ");
        }
      }

      timing() {
        timing_type : hold_rising;
        related_pin : "CK";
        mode(RAM_MODE, MODE_1);
        rise_constraint(scalar) {
          values( " 0.0 ");
        }
        fall_constraint(scalar) {
          values( " 0.0 ");
        }
      }
    }

    pin(CK) {
      timing() {
        timing_type : "min_pulse_width";
        related_pin : "CK";
        mode(RAM_MODE , MODE_4);
        fall_constraint(scalar) {
          values( " 0.0 ");
        }
        rise_constraint(scalar) {
          values( " 0.0 ");
        }
      }

      timing() {
        timing_type : "minimum_period";
        related_pin : "CK";
        mode(RAM_MODE , MODE_4);
        rise_constraint(scalar) {
          values( " 0.0 ");
        }
        fall_constraint(scalar) {
          values( " 0.0 ");
        }
      }

      clock : true;
      direction : input;
      capacitance : 1.0;
      max_transition : 1.0;
    }

    cell_leakage_power : 0.0;
  }
}
相关推荐
日晨难再2 天前
Library Compiler:时序弧建模与约束全解析(一)
数字ic
内有小猪卖18 天前
数字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