Synopsys:对象集合 相关阅读Synopsyshttps://blog.csdn.net/weixin_45791458/category_12812219.html?spm1001.2014.3001.5482目录为什么使用对象集合创建/删除/访问对象集合显示对象集合中的对象名/数量向对象集合中添加/移除对象比较对象集合中的内容从对象集合中提取单个对象遍历对象集合通过迭代向对象集合中添加对象通过迭代从对象集合中移除对象对于Synopsys的EDA工具如Design Compiler、PrimeTime、IC Compiler等对象集合(Collections)是一个基本的概念许多命令在执行操作时都需要接收或返回由一个或多个对象组成的集合本文就将介绍对象集合。关于Synopsys中设计对象的更多介绍可以参考下面的博客。Synopsys设计对象https://blog.csdn.net/weixin_45791458/article/details/147015140?ops_request_miscelastic_search_miscrequest_id58b392c0b3d9d3c7a1ec3fef31c13605biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-1-147015140-null-null.541^v3^pc_search_result_blog8utm_term%E8%AE%BE%E8%AE%A1%E5%AF%B9%E8%B1%A1spm1018.2226.3001.4450为什么使用对象集合Tcl语言提供了列表(List)它本质上是按照特定格式组织起来的字符串虽然可以使用列表来引用对象但这种方式存在以下缺点1、列表的内存使用效率较低每个对象名都以完整字符串的形式存储对于多个层次对象其层次路径会被重复、冗余地存储。2、列表的运行效率较低必须通过字符串比较在设计数据库中搜索每个列表元素所对应的对象。对于层次对象名在搜索过程中还需要进行额外处理以逐级识别各个层次最终定位到叶级对象。3、列表无法明确区分对象类型列表中的元素本身并不包含对象类型信息。例如CLK究竟表示一个端口还是一个同名的线网4、列表无法提供额外的对象信息除了对象名之外列表元素本身不提供任何有关对象的信息。例如无法仅通过一个时钟名列表获取其中各个时钟的周期也无法仅通过一个单元名列表获取其中各个单元的面积。为了解决这些问题基于Tcl语言的Synopsys的EDA工具提供了对象集合作为引用对象的一种方式对象集合是一种二进制数据结构用于引用由一个或多个对象组成的集合。其中每个对象的引用都直接指向相应的内部数据结构因此即使需要处理数千个对象对象集合仍然具有很高的运行效率和内存使用效率。对象集合中的大部分对象都具有object_class属性用于指明该对象所属的类型。对象集合既可以只包含一种类型的对象即同构对象集合(Homogeneous Collection)也可以包含多种不同类型的对象即异构对象集合(Heterogeneous Collection)。每种对象都提供了额外的属性可以利用这些属性获取该设对象的更多信息。例如时钟对象具有period属性用于表示时钟周期单元对象具有area属性用于表示单元面积。这些属性值可以直接从EDA工具的内部数据结构中获取也可以由EDA工具在查询时动态计算得到因此属性查询同样具有较高的执行效率。创建/删除/访问对象集合通常可以使用get_*和all_*类命令创建对象集合。例如要创建一个包含所有名称以o开头、并且由FD2库单元例化得到的单元集合可以使用以下命令dcnxt_shell get_cells o* -filter ref_name FD2 {o_reg1 o_reg2 o_reg3 o_reg4}尽管回显的返回值看起来像一个列表但实际上并不是为了方便用户查看返回对象集合的命令自动调用了query_objects命令显示对象名列表。对象集合通过一个集合句柄(Collection Handle)进行引用本质上是一个字符串值类似指针EDA工具会将这个字符串与对象集合的内部数据结构关联起来。大多数接受对象作为参数的命令都支持并推荐使用对象而不是列表作为参数如下博客所示。SDC命令详解使用集合(Collection)而不是字符串(String)/列表(List)作为命令参数https://chenzhang.blog.csdn.net/article/details/147144571对象集合可以是临时的也可以在整个EDA工具会话期间持续存在。如果将一个嵌套的对象集合命令用作另一个命令的参数那么由嵌套命令创建的对象集合只会在该命令的作用范围内存在。例如可以使用以下命令为单元i1和i2设置size_only属性dcnxt_shell set_size_only [get_cells i1 i2] true 1如果希望对象集合在当前EDA工具会话中持续存在可以将其赋值给一个变量随后可以使用这个变量作为其他命令的参数值如下所示dcnxt_shell set my_pins [get_pins o*/CP] {o_reg1/CP o_reg2/CP} dcnxt_shell get_cells -of_objects $my_pins {o_reg1 o_reg2}只要变量仍然引用对应的集合句柄该对象集合就会持续存在如果使用unset命令删除了变量定义或将其他值赋给变量与该变量关联的对象集合也会删除。需要注意的是对于Synopsys的EDA工具如果把一个关联了对象集合的变量赋值给另一个变量会创建一份新的副本而不是共享同一个对象集合就像在Python中的列表赋值那样这与Tcl列表一致。关于Python中的赋值引用的更多信息可以参考下面的博客。Python赋值的本质其实是引用https://blog.csdn.net/weixin_45791458/article/details/142834055?ops_request_miscelastic_search_miscrequest_id6fe5940fa597db72747b52dd4239db52biz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-2-142834055-null-null.541^v3^pc_search_result_blog8utm_termPython%20%E8%B5%8B%E5%80%BCspm1018.2226.3001.4450在部分EDA工具如Design Compiler和IC Compiler中如果用户使用current_design命令切换了当前设计则相对原当前设计得到的对象集合会暂时失效部分EDA工具不会失效如IC Compiler II少部分类型的对象集合如时序路径timing_path会永久失效如下所示dcnxt_shell current_design top Current design is top. {top} dcnxt_shell set a [get_cells bot1] {bot1} dcnxt_shell set b [get_timing_paths] {path1} dcnxt_shell query_objects $a {bot1} dcnxt_shell query_objects $b {path1} dcnxt_shell current_design bot Current design is bot. {bot} dcnxt_shell query_objects $a Error: No such collection _sel24 (SEL-001) dcnxt_shell query_objects $b Error: No such collection _sel156 (SEL-001) dcnxt_shell current_design top Current design is top. {top} dcnxt_shell query_objects $a {bot1} dcnxt_shell query_objects $b Error: No such collection _sel156 (SEL-001)对象集合相关命令通常提供一些选项以便更加精细地控制对象的获取方式。例如get_pins命令提供了-leaf选项用于跨层次边界搜索并只考虑叶单元上的引脚关于get_pins命令的更多信息可以参考下面的博客。SDC命令详解使用get_pins命令进行查询https://blog.csdn.net/weixin_45791458/article/details/147985165?ops_request_miscelastic_search_miscrequest_ide9013962c789231b0d8d3dcb8bfb1d3cbiz_id0utm_mediumdistribute.pc_search_result.none-task-blog-2~all~ElasticSearch~search_v2-1-147985165-null-null.541^v3^pc_search_result_blog8utm_termget_pinsspm1018.2226.3001.4450显示对象集合中的对象名/数量所有返回对象集合的命令在交互式命令提示符下返回对象集合时都会隐式地显示对象集合中的对象名。不过为了获得更灵活的显示方式可以显式使用query_objects命令显示对象集合中的对象名使用-verbose选项还可以同时显示对象类型。query_objects命令生成的输出与交互式环境下回显的返回值类似查询结果会被格式化为Tcl列表的形式以便用户直接查看结果。例如可以使用以下命令显示所有名称以字符串in开头的端口dcnxt_shell set a [get_ports in*] {in0 in1 in2} dcnxt_shell query_objects $a # 必须添加$前缀 {in0 in1 in2}用户甚至可以使用query_objects命令直接访问数据库如下所示dcnxt_shell query_objects -class port in* {in0 in1 in2}要控制显示的列表中的最大对象名数量可以使用query_objects命令的-truncate选项或设置collection_result_display_limit变量默认为100。如果只需要获取对象集合中的对象数量而不是显示对象名称可以使用sizeof_collection命令如下所示dcnxt_shell sizeof_collection $all_cells 23856如果需要生成更加详细的对象集合报告包括自定义格式的报告可以使用report_collection命令。向对象集合中添加/移除对象向对象集合中添加对象有两种方式每种方式适用于不同的用途与之前谈到的赋值类似这里的添加也会创建副本1、向已有对象集合中添加对象可以使用append_to_collection命令向已有的对象集合中添加对象。使用时需要指定关联了对象集合的变量名需要注意的是这里不能添加$前缀这是与其他大多数对象集合操作命令的区别然后指定要添加的对象集合如下所示dcnxt_shell query_objects $a {cell1} dcnxt_shell append_to_collection a [get_ports *] {cell1 in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1]}由于新对象是在数据结构层面直接复制到已有的对象集合中因此该操作的执行速度非常快。2、将多个对象集合合并为一个对象集合可以使用add_to_collection命令将两个对象集合合并并将合并后的结果作为一个新的对象集合返回如下所示dcnxt_shell query_objects $clock_sources {clk} dcnxt_shell query_objects $reset_sources {rst_n} dcnxt_shell set possible_sources \ [add_to_collection $clock_sources $reset_sources] {clk rst_n}需要注意的是只有在需要将多个对象集合合并为一个对象集合时才应使用add_to_collection命令如果只是向已有对象集合中添加新对象则应使用append_to_collection命令add_to_collection命令在运行过程中会创建和销毁临时对象集合。3、使用Tcl列表保存多个对象集合对象集合列表可以创建Tcl列表使其包含多个对象集合。但不建议这么做因为Tcl列表可能会受到原对象集合的影响如下所示dcnxt_shell set a [get_ports *] {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0] out_sum[7] out_sum[6] out_sum[5] out_sum[4] out_sum[3] out_sum[2] out_sum[1] out_sum[0]} dcnxt_shell set b [get_cells *] {u_adder} dcnxt_shell set c $a $b _sel179 _sel180 dcnxt_shell query_objects [lindex $c 0] {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0] out_sum[7] out_sum[6] out_sum[5] out_sum[4] out_sum[3] out_sum[2] out_sum[1] out_sum[0]} dcnxt_shell query_objects [lindex $c 1] {u_adder} dcnxt_shell unset a dcnxt_shell unset b dcnxt_shell query_objects [lindex $c 0] Error: No such collection _sel179 (SEL-001) dcnxt_shell query_objects [lindex $c 1] {u_adder}可以使用remove_from_collection命令从对象集合中移除对象。remove_from_collection命令会创建一个新的对象集合其中包含原始对象集合中除指定移除对象之外的所有对象remove_from_collection命令在运行过程中会创建和销毁临时对象集合。如果移除操作后集合中不再包含任何元素则该命令返回一个空字符串。需要注意的是原始对象集合不会被修改。例如可以使用以下命令创建一个包含除CLOCK之外所有输入端口的对象集合dcnxt_shell set data_ports [remove_from_collection [all_inputs] {CLOCK}] {in1 in2}可以指定一个对象名列表或一个对象集合作为需要移除的对象。需要注意待移除对象的类型必须与原始对象集合中的对象类型一致。例如不能从一个单元对象集合中移除一个端口对象集合。如果对象集合曾经处于异构对象集合状态那么不能指定一个对象名列表作为需要移除的对象如下所示dcnxt_shell set a [get_ports in_*] {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell remove_from_collection $a in_b {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0]} dcnxt_shell remove_from_collection $a in_a {in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell set a [append_to_collection a [get_nets in_*]] {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0] in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell remove_from_collection $a in_a Warning: Nothing implicitly matched in_a (SEL-003) {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0] in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell remove_from_collection $a in_b Warning: Nothing implicitly matched in_b (SEL-003) {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0] in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell set a [remove_from_collection $a [get_nets in_*]] {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell remove_from_collection $a in_a Warning: Nothing implicitly matched in_a (SEL-003) {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]} dcnxt_shell remove_from_collection $a in_b Warning: Nothing implicitly matched in_b (SEL-003) {in_a[7] in_a[6] in_a[5] in_a[4] in_a[3] in_a[2] in_a[1] in_a[0] in_b[7] in_b[6] in_b[5] in_b[4] in_b[3] in_b[2] in_b[1] in_b[0]}比较对象集合中的内容可以使用compare_collections命令比较两个对象集合的内容。如果两个对象集合包含完全相同的一组对象并且任何一个对象集合中都不存在无法匹配的对象那么compare_collections命令返回0否则返回非零值如下所示dcnxt_shell compare_collections [get_cells *] [get_cells *] 0默认情况下两个对象集合中对象的排列顺序不会影响比较结果。如果希望比较结果与对象的排列顺序有关可以在比较时使用compare_collections命令的-order_dependent选项。要判断一个对象集合是否为空可以使用Tcl语言中的字符串比较操作将其与空字符串进行比较如下所示dcnxt_shell if {$my_cells eq {}} { # ...集合为空... } dcnxt_shell if {$my_cells ne {}} { # ...集合不为空... }要判断一个待查找对象集合中的所有对象是否都存在于另一个被搜索对象集合中可以使用remove_from_collection命令后再与空字符串进行比较如下所示dcnxt_shell if {[remove_from_collection $needle $haystack] eq {}} { # $needle 中的所有对象都存在于 $haystack 中 }要确定两个对象集合是否存在共同对象以及这些共同对象具体是什么可以使用remove_from_collection命令的-intersect选项如果两个对象集合不存在任何共同对象该命令将返回一个空对象集合如下所示dcnxt_shell remove_from_collection -intersect $fanin_pins $fanout_pins从对象集合中提取单个对象对象集合是有序的其中的对象按照从0到n-1的索引进行编号其中n为对象集合中的对象数量。可以使用index_collection命令根据索引提取对象集合中的对象与之前谈到的赋值类似这里的提取也会创建副本。1、提取单个对象指定一个索引值即可提取单个对象这相当于Tcl语言中的lindex命令如下所示dcnxt_shell index_collection $my_ports 3 {A[12]}2、提取指定范围的对象指定一个范围的起始索引和结束索引即可提取该范围内的对象这相当于Tcl语言中的lrange命令如下所示dcnxt_shell index_collection $my_ports 3 5 {A[12] A[11] A[10]}与相应的Tcl命令一样index_collection命令也可以使用end或end-value的形式指定索引如下所示dcnxt_shell index_collection $my_ports end {test_se} dcnxt_shell index_collection $my_ports end-2 end {test_si6 test_si7 test_se}需要注意的是虽然get_*和all_*类命令可能没有在文档中明确说明其返回的对象集合中对象的排列顺序但这些命令会以确定性的顺序创建对象集合。换句话说多次执行相同的命令会创建相同的 对象集合。遍历对象集合可以使用foreach_in_collection命令遍历对象集合中的每个元素。foreach_in_collection命令可以嵌套在其他控制结构中包括另一个foreach_in_collection命令。在每次迭代过程中迭代变量都会被赋值为一个恰好包含一个对象的对象集合不能使用Tcl语言中的的foreach命令遍历对象集合如下所示dcnxt_shell foreach_in_collection this_cell [get_cells *] { ... }通过迭代向对象集合中添加对象如果需要在循环过程中不断向对象集合中添加对象应使用append_to_collection命令直接对该对象集合进行原地添加如下所示# 从空对象集合开始用于累积符合条件的对象 set qualifying_cells {} # 遍历对象集合并根据条件 # 添加符合要求的对象 foreach_in_collection this_cell $all_cells { if {...some criteria...} { append_to_collection qualifying_cells $this_cell } }不要使用add_to_collection命令在循环中逐个添加对象因为这种方式会在循环过程中不断创建和销毁临时对象集合从而产生显著的性能开销。通过迭代从对象集合中移除对象如果需要在循环过程中从对象集合中移除对象应先使用append_to_collection命令构建一个包含所有待移除对象的对象集合然后在循环结束后统一移除这些对象如下所示# 从空对象集合开始用于累积待移除对象 set cells_to_remove {} # 遍历对象集合并根据条件 # 收集所有需要移除的对象 foreach_in_collection this_cell $all_cells { if {...some criteria...} { append_to_collection cells_to_remove $this_cell } } # 循环结束后从完整集合中统一移除这些对象 set all_cells [remove_from_collection $all_cells $cells_to_remove]不要使用remove_from_collection命令在循环中逐个移除对象因为这种方式会在循环过程中不断创建和销毁临时对象集合从而产生显著的性能开销。报告对象集合将对象集合信息写入文件2019版本推出的write_collection命令允许将对象集合中对象的属性值信息以逗号分隔(CSV)或制表符分隔(TSV)的格式写入文件。默认情况下该命令会按照输入对象集合中对象的排列顺序将每个对象的名称和对象类型写入逗号分隔值的文件如下所示dcnxt_shell set a [get_cells] {U1 C9 I_0 C11 I_1} dcnxt_shell write_collection $a -file file.out dcnxt_shell sh cat file.out name,object_class U1,cell C9,cell I_0,cell C11,cell I_1,cell如果希望以制表符分隔值的格式写入信息可以使用write_collection命令的-format tsv选项如下所示dcnxt_shell set a [get_cells] {U1 C9 I_0 C11 I_1} dcnxt_shell write_collection $a -file file.out -format tsv dcnxt_shell sh cat file.out name object_class U1 cell C9 cell I_0 cell C11 cell I_1 cell如果希望自定义输出内容可以使用write_collection命令的 -columns选项指定需要在报告中显示的属性列表。该选项支持嵌套属性如下所示dcnxt_shell set my_path [get_timing_paths] {path1} dcnxt_shell set my_points [get_attribute $my_path points] {point6 point7 point8 point9 point10 point11} dcnxt_shell write_collection $my_points -file out.txt -columns {object object.name arrival} dcnxt_shell sh cat out.txt object,object.name,arrival b,b,0 U3/B,B,0 U3/Y,Y,0.0204919 U2/B0,B0,0.0204919 U2/Y,Y,0.0518479 y,y,0.0518479对于Design Compiler而言未定义的嵌套属性值在输出文件中对应的字段将保留为空工具不会产生警告未定义的非嵌套属性不会出现在输出文件中工具会产生ATTR-1警告。对于PrimeTime未定义的属性值不会出现在输出文件中如果是未定义的应用属性输出文件中对应的字段将保留为空工具会产生ATTR-1警告。如果某个属性值是对象集合且只包含一个对象则输出该对象的名称如果包含多个对象则输出这些对象的类型和数量