后端和前端一样在IC设计中扮演着非常重要的角色,甚至可以说入门的前端设计工程师对timing的理解远不如一个后端设计工程师,因此想要更好的理解电路的timing在后端P&R之后或者说在大规模的设计中后端如何实现clock对DFF的驱动,就需要学习和了解CTS,而这些对于一个优秀的前端设计人员来说,也是一个必要掌握的技能。
今天我们就来学习一下clock tree synthesis (CTS),本篇文章学习自知乎博主,原文链接为:数字后端基础技能之:CTS(上篇) - 知乎 (zhihu.com)
构思了很久应该怎样介绍CTS,最终决定分为几篇文章来一步一步介绍整个流程,尽管如此,由于在大型项目中CTS是一个比较复杂的工作,因此在本文之外可能还要有很多东西需要后端设计工程师去关心,但是我仍然希望对于初学者,通过本专栏接下来的几篇文章,能够对CTS的基本流程和做法有一个大致的思路,从而避免拿到一个design后陷入无从下手的被动。
言归正传,在P&R整个流程中,有两个对于design的PPA(power performance area)起决定性的步骤:Floorplan和CTS,尽管如此,在实际项目中,很多人可能工作数年也没有机会做一次比较全面的CTS,一方面原因在于,P&R工具尤其是现在的ICC2和innovus对于相对简单的clock tree都能很好的处理,另一方面的原因是,对于大多数无法接触TOP的工程师来说,harden block内部的clock结构大概率是比较简单的,因此就导致一些同学在做过几个项目后面对复杂的clock仍然无从下手。
针对这个现象,本文希望根据自己的经验把CTS的基本思路和做法介绍给大家,如果大家以后遇到复杂的clock时发现这里的内容对实际工作多有裨益,本文也不胜荣幸。
clock tree synthesis,顾名思义,就是对design的时钟树进行综合,主要的目的是让每个clock都能够在尽量短的时间内传达到他们驱动的所有DFF(寄存器),对于CTS,我们有三个指标希望能够尽量做到最好。
每个clock到达其所驱动的sink(DFF)的latency都尽量的短;
每个clock之内,以及有时序关系的clock之间的skew尽量小;
每个clock的common path尽量的长;
对于大多数P&R工具,CTS的flow可以总结为以下形式:
上图中可能有些名字还不太清楚他的具体含义,但是这些都会在后面的介绍中一一提及,在这里也没有将大部分单词翻译成中文,因此希望大家记住这些名词,方便在读英文的user guide时少一些障碍。
CTS策略
这是CTS的第一步,虽然在流程中只是简单的几个字,但是针对复杂的clock,这里可能需要花费大量的时间分析clock的结构,找出潜在可能出现的问题和瓶颈,并针对我们上述提出的三个指标,决定如何去综合时钟树,这一步如此重要又非常容易被忽略,以至于有些同学在遇到复杂的clock出现问题时无从分析,遑论如何改进,下面我将通过一个例子来说明,CTS策略到底是什么?
假设某芯片的clock结构可以简化为如下形式:
其中fucntion clock从两个PLL和两个IO (一个FCLK1, FCLK2)进来,test clock从两个IO(TCLK1, TCLK2)进来,从图中可以看出,在分频电路之后,进入A和D的clock不与其他模块共享。
与此同时,我们假设芯片的floorplan可以表示为如下形式(注意clock source 和模块位置与clock结构对应关系)
如果模块间的数据流关系简述为如下形式:
Block B <—> Macro 1
Block C <—> Macro 2
Macro 1 <—> Macro 2
Block A/D 为独立模块
考虑到上述时钟结构,floorplan和时许关系,我们该如何决定CTS策略呢?
在考虑策略之前,我们先回忆一下CTS的三个目标:latency尽量短;skew尽量小;common path尽量长;
先从最简单的开始:鉴于Block A/D为独立模块,他们不与其他模块产生时序关系,同时从clock结构图可以看到进入A/D的clock在选择之后没有与其他模块有交集。因此,我们只需要把A和D的clock尽量做短即可。
我们也可以把一切都交给EDA工具去做,但是这样做的结果不能保证得到我们想要的结果,最好的办法是把进入到A,D两个Block的clock选择器以及其他clock分频逻辑固定在这两个block附近(下图中的紫色区域),这样不仅能够使clock line尽量以最短的距离到达Block,同时也能够尽可能地增加common path的长度。
接下来考虑Block B/C和Macro1、2,鉴于他们之间的时许关系,我们希望他们之间的skew尽量的短,同时common path要尽量的长,在floorplan上我们可以看到他们被拜访成对称的形式,因此,最简单直接的办法就是将所有与这几个相关的逻辑都固定在两个Macro上方的正中间(假设其clock port在黄色标识的部分),如下图中红色方框所示:
到目前为止我们确定了需要preplace的逻辑以及其放置的区域,接下来我们需要考虑如何实现我们的设想,其中首要的任务就是定义CTS的sdc。
对于CTS工具来说,要进行时钟树综合,有一个必备的前提条件就是clock的定义,而后端设计者是可以根据自己的策略自己调整clock的定义的,让我们再会议一下clock的结构图。
针对上述结构,有两种常用的定义Clock的方法(时间单位ps)
1:直接从所有的clock的源头定义,此方法基本可以从func/test的sdc 中直接复制clock的定义:
creat_clock-period xxx -name PLL_CLK [get_pins PLL1/CLK] ;
2:采用分段CTS的方法,因为大部分clock结构,从选择器开始都比较简单,因此我们可以从选择器的输出端定义一系列的clock并对有时许关系的部分进行balance;之后再从各个clock源头定义并在时钟树综合的时候在选择器的输入停止,此方法的clock定义可以大致分为以下两个部分。
第一段:选择器输出端—> 各个Block
create_clock-period xxx -name MUXCLK1 [get_pins MUX1/Y]
create_clock-period xxx -name MUXCLK1 [get_pins MUX2/Y]
........
第二段:clock source —> 各个选择器
creat_clock-period xxx -name PLL_CLK [get_pins PLL1/CLK] ;
........
至于如何使工具在选择器停止,我们将在接下来的文章中继续讨论,同时我们将会把上述思路和策略通过真是的脚本和命令反映出来,希望大家继续关注。
另外,在本文中设计的design通过上述几幅图可以了解到相对详细的时钟结构,但是在实际设计中我们如何事先得知clock的结构时序关系呢?一般来说对于流程完善的大公司,绘制详细的始终结构是前端设计的工作之一,但是在实际项目中,面对的大部分design的clock结构图可能是十分简单甚至完全没有的情况,这时就需要后端工程师多一些耐心去分析design,并积极与前端的constraint设计者沟通,从而实现对design的时钟结构快速把握。
至此,CTS的策略基本构建完成,在接下来的文章中,我们将继续详细讨论这些策略的实现方法以及如何查看debug clock的结果。