之前所讲的CTS,或者说一般我们的CTS流程,都是完全由工具自动建tree(图左): 从sink点开始cluster,然后逐渐做到root点。还有一种的做tree的方式:首先是从root做到多个固定点(TAP点),然后再从sink点做到最近的TAP点。这种方式一般又可以分为两种:flexible-Htree(图中)和Mesh(图右)的方式。 下面简单的列举了三种方式的优缺点 由于Mesh的方式功耗很大,很少用到,所以一般都用Flexible-Htree,有的可能把这种结构称为fishbone,有时候也被叫做Multi-Tap CTS。 下面先简单介绍一下Flexible-Htree的基本流程,再对每一步进行详细的分析:
有下面三种方式:
2. insert_ccopt_source_group_roots 代替手工的方式,其结果和图左一样 3. 上面的方式,在root和TAP之前没有没有其他buffer,这样会有tran的问题,或者后期需要手工加入buffer-tree,另一种更常用的方式就是采用 create_ccopt_flexible_htree synthesize_ccopt_flexible_htree 其结果如图右,和图左区别就是多了root到tap之间的buffer create_htree命令用于定义htree,只是定义,不会对插入任何buffer和TAP synthesize_htree命令则用于实现刚才定义的htree,会加入buffer和TAP 如果采用了前两种方式创建的TAP,那么从root到TAP之间的net设置为dont-touch和ideal,否则这些net会被ccopt加入buffer。 这里需要注意的是,synthesize_htree命令,他是严格的按照target_max_trans的要求来插入buffer的。如果你synthesize_htree失败了,很可能是因为它没法在合适的距离插入buffer,可以试试将这个trans值设大点
上面做完之后,所有的sink都是挂在一个TAP上的,这当然不是我们想要的,我们想要的是sink挂到最近的TAP上,如下图左所示。 运行ccopt_design命令会自动分配。如果你想快速的看到分配的结果,那么可以采用assign_clock_tree_source_groups命令。 理想情况下,从TAP到sink只有buffer,结果会像上图左一样。但是实际情况下,有各种ICG,AND,MUX的各种逻辑。最极端的例子,如上图右,所有的sink点都从一个ICG来。如果不对ICG进行clone,即使分配完之后还是全部sink都连接到一个TAP上,其他TAP都是floating。所以htree一定要用到clone。 如何clone或者如何控制clone? 按照之前做法,我们需要设置下面的参数: 但后两种控制clone的办法在分配sink这一步并不起作用,这两个变量只在真正做tree的时候才起作用。控制分配sink是由变量clustering_source_group*来控制的。我们运行一下下面的命令: 发现什么没有任何相关的变量存在,不要急,我们有办法让他们显形,再运行下面的命令: 再打开my_ccopt_config/prop_store_2.tcl.gz,我们就可以看到相关的变量了。这里就对这三个变量进行分析。
每个TAP可以驱动的sink的数目 除上面的方法外,我们还可以强制让某个sink点挂到某个TAP上: 例如下面的命令强制让$pinname挂到TAP_cell_1上面 好了一切都做好了,下面我们就看看做出来的质量怎么样,我们就来分析分析log。在ccopt_design中,分配sink的操作是在clustering阶段一开始就做的,(不清楚clustering步骤的翻翻前面CTS的介绍)。下图的数字不一定准确,已经经过作者的修改。所以不要去计算为什么数据不一致。
如下所示,共有7258+1+6+1=7266个CG。 下图的log显示了可以加入多少个额外的CG:其中的0.2就是我们上面设置的变量 下面以【CLU】关键字开头的行就是分配完sink之后的结果。 htree__*表示的是clock_tree,不是指TAP点。当然一个htree对应一个TAP点。 anchor表示TAP点的位置 size表示每个htree或TAP点挂载的sink数目。 radius表示这些sink的物理分布 mst 不清楚 L1ICGs、L2ICGS,没必要了解,不过本文下面还是会介绍介绍 ResultSummary我就不多说了,
下图展示了L*ICG如何计算,图画的丑,见谅。下图中红色表示sink,黑色表示CG。 L1=4 ; L2=2 ; L3=2 ; L4=1. 下面是做完之后的状态,可以发现,ICG多了11个,logic多了11个 |
|