在屈辱和战争之间,你选择了屈辱,
那么你在屈辱以后,还要面对战争。
-- 丘吉尔
书接上回,今天我们来聊一聊RTL级功耗计算的问题。上篇讲到有很多种低功耗设计方法,那么在项目中选择哪些来做呢?在抉择前如果有数据支撑那是最好,可以根据数据来判断要实现何种复杂度的低功耗设计。如果是迭代产品,可以参考上一代芯片的实测数据。可要是新项目呢?这时候就需要基于RTL做功耗分析了。
以前经常会被问一个问题,“RTL级计算出的功耗与silicon比有多大差别呢”。这个问题还真不是一句两句就能说的清楚的。今天就试着从原理上讲一下。
我们知道,RTL就是一堆代码,是完全没有功耗信息的。而芯片内部是一大堆由晶体管组成的各种各样的标准单元(standard cell)。怎么把两者扯上关系呢?在SoC设计流程上有一步“逻辑综合”的过程,那么在RTL功耗计算的时候是不是也需要这一步骤呢?答对了,确实需要。各家的RTL计算工具(为了避免广告嫌疑就不说具体的工具名称了)在内部都要完成这个操作。但是跟综合工具做的不会完全一样(不展开,有兴趣的私聊),我给这步起了一个名字“预综合”,以示区分。
通过预综合,我们的RTL变成了一堆register和与非门这样的器件。在开始计算前,还需要一些基本的输入数据,第一是每个器件的基本功耗信息,第二是每个器件在给定时间窗内的翻转次数。
先说第一个,我们可以从foundry厂提供的lib文件中直接找到每个器件的功耗信息。一般会在lib文件的开头定义基本信息,例如电压/电流/电阻的单位,如下图:
同时也会定义每个cell的leakage,大概长这样:
还记得上篇提到的吗,输入值不同,leakage也略有不同,在上图就体现出来了,管脚A是0还是1,leakage power不一样。
Internal power表大概长这样:
还有switch power,因为与负载电容有关,在lib里面不能直接查表获得,要通过wire\_load估算:
以上只是用了一个最简单的buffer举例,对于多输入的cell,情况要复杂一点。至此,关于leakage,internal和switch的基本信息全都有了。
再说第二个,一般会有两种方法提供翻转次数信息。第一种是通过仿真波形,这个好理解,在vcd或者fsdb波形中会记录每次的信号变化,把波形中的信号和预综合出来的器件标对上就可以了。可能有细心的同学会问,“不对呀,波形里面都是RTL的信号,能和每个器件对起来吗”。这个其实不用担心,模块的所有primary input和register全能对应上,剩下的组合逻辑即使对不上也能推导出来,对不?更细心的同学可能会发现,这里好像忽略了glitch。在RTL功耗计算里面的确默认会忽略glitch,这是因为RTL的波形里面就没有timing信息呀。现在的仿真工具一般会提供参数来设置glitch比例,除非必需,不建议初次使用就打开这个选项。
有时候在项目初期可能还给不出vcd或者fsdb波形,这时候要想计算RTL功耗就需要用第二种办法了,设置toggle rate。这里toggle rate的定义是,在一个时钟周期内平均翻转的次数。比如clock信号,如果完全不做gating的话,那么其toggle rate就是2(一个周期内上下翻转了两次),如果做了gating,那么一定是一个小于2的值(可以根据项目中gating力度估计一下);对于register而言,最大toggle rate是1(每个周期都翻转),一般会在0.1-0.2之间。
有了上述的信息,接下来就可以计算了。在计算的时候,有两种方式。第一种是计算average power,顾名思义就是用户给定一个时间窗口,工具计算该窗口内的平均功耗值,简单说就是把时间窗内所有器件的所有翻转造成的能量消耗叠加起来除以时间(怎么感觉我在说绕口令似的)。第二种计算方式就是time-based power,做法是根据用户设定,把时间窗均匀切分成若干小的时间窗,每个时间窗内计算一次。与第一种计算方式不同的是,这种方式会得出很多个功耗数据(每个间隔一个),把这些数据连起来就是功耗随时间变化的图。贴个图帮大家直观感受一下,横坐标是时间,纵坐标是功耗值。
总结一下RTL功耗计算的步骤,和把大象关进冰箱的问题一样,拢共分三步:第一步,预综合,第二步,提取与功耗相关的信息;第三步,计算。
至于netlist功耗计算,就不需要第一步了,更简单了。
再回到一开始的问题,用RTL计算出的功耗和silicon比到底差多少?这个问题实在太难回答了,我就说说可能会引起偏差的地方吧,大家可以自己思考。首先是预综合阶段,这一步毕竟不同于真正的逻辑综合,功耗仿真工具只能做到尽量与逻辑综合一致(对于EDA工具来说也需要tradeoff,速度/精度/容量)。如果两边信息不一致,可能偏差更大。举个例子,如果在综合工具里面设置了dont\_use,而没有告诉功耗工具这个信息,那么两边选用的cell可能差别很大。另外一个偏差比较大的地方是时钟树。随着工艺的升级,时钟树消耗的功耗比重越来越大。SoC设计流程里面是在做物理设计的时候插入时钟树的,而功耗仿真在RTL阶段就需要这个信息。怎么给能保证偏差小?还有一个影响较大的因素,Cload。在物理设计完成后,所有的器件摆放和走线都固定了;可是在RTL阶段是没有这些信息的呀,所以工具只能根据fanout等信息去估计一个值出来。后端工程师在做物理设计时的一些策略也可能会造成影响,记得以前在知乎上看过一篇文章,文章作者发现估算的功耗值(RTL和网表都做了仿真)与silicon偏差很大,费尽力气后意外发现是由于后端工程师插了大量的decap所致。最后还有一个因素是,如果芯片内部有模拟模块,这是RTL功耗仿真所不能做的,完全取决于IP厂商或模拟团队给的功耗值有多准确。造成偏差的因素还有很多,这里权当抛砖引玉吧。
说到这里,估计一些同学会追问,“既然RTL功耗计算很容易偏差,那么等逻辑综合完拿到网表再算功耗不是更香吗”。诚然,用网表文件和波形文件一起计算功耗的确会更准确一些,毕竟没有了预综合步骤,减少了很多不确定因素。但是,我们计算功耗仅仅是为了得到一个准确值吗?我们拿着准确但是不可接受的功耗值和网表又能做些什么呢?主席教导我们,“不忘初心,牢记使命”。在项目初期,我们不是为了算功耗而算,我们是为了优化功耗而算。做RTL级功耗计算最大意义就是帮助架构师和设计师更好的优化芯片和内部模块。
【后记】罗里吧嗦的写多了,各位看官受累啦。想深入研究的同学可以仔细对照lib文件和《liberty user guide》。
作者:老秦谈芯
来源:https://mp.weixin.qq.com/s/ic1JSJ19e8TCTJS6-0fKHA
作者微信公众号
相关文章推荐
更多IC设计技术干货请关注IC设计技术专栏。