对于DC综合中的retiming策略早有耳闻,但是一直没有比较系统的学习和实验过,正好借着这次交付过程的归纳总结机会,把一些零零散散的收获学习记录下。
记得刚出新手村时和某位大佬聊到过,他说你逻辑里写了在某级计算一个结果,但是这个值不一定是在这一级产生的,可能是上一级产生也可能是下一级产生。当时懵懂无知我就光“啊对对对”,实际上心里想的是“是不是跟我扯呢,怎么我写在这一级出的结果还能流窜到其他级去呢,那整个逻辑链不就乱了么?”当时啥也不懂,所以也没有多问,后来想想应该说的就是综合过程的retiming策略。
综合的Retiming策略通过重新分配组合逻辑路径中的时序,达到优化电路性能的目的。具体来说,它可以在组合逻辑和时序逻辑路径中插入或删除缓冲器、反相器甚至触发器等元素,从而调整信号的传播时间,使关键路径的延迟满足设计要求。我们平时总谈起的这个DC里的retiming优化更多好像是指涉及到时序调整的操作,用一个简化的例子来说明下。假设我们现在有一个操作是D = A+B+C,在第一级时三个数相加,然后空打了一拍最后输出:
那么如果此时我们打开了retiming的开关,并且DC工具综合判断进行retime的效果会更好,那么最后综合的结果可能就变成这样了(只是单纯的举例):
工具会把一部分逻辑放到下一级去处理,这样就减轻了这一级的时序压力能够确保能够match violation。而具体什么时候会retime以何种策略retime,网上的资料有很多我也没有查太深。而后就想直观地看一看retime处理的效果和电路图(有时我确实有点执着于眼见为实了),所以在本地虚拟机里进行了一下实验。测试的代码和上图很像,只不过为了加深逻辑级数我多加了很多逻辑,输入为3个48bit data1/2/3数据输出为96bit res:
在DC中先关闭retime,以compile_ultra -incremental进行综合,之后在dc_shell中打开互连start_gui:
这版图看着是真舒服,逻辑层级清晰,谁看到不得说一句好代码♪(^∇^*)。放大具体看一下互连结构,可以清晰的看到datax_p1级的寄存器区域、p1到p2的逻辑区域、res_p2的寄存器区域和res_p3的寄存器区域:
而后具体看一下res_p2和res_p3的直接打拍区,可以发现res_p2的Q端直连到res_p3的D端,完全没有组合逻辑,这也符合不开retime的预期:
最后是report,时钟频率设的比较高最差路径-280p逻辑深度22级,自然时序是没有match的:
之后以以compile_ultra -incremental -retime进行综合,综合之后的网表就能看出来乱了很多:
放大之后还是可以大概看出来三级寄存器的分布,同时还生成一个中间模块(下图最长的那个箭头)。从这个图就能很明显的看出来,p3寄存器和p2寄存器不是直连,中间加入了逻辑,加入的逻辑集中在中间模块里:
对于这个生成的中间模块简单分析下,他内部很乱:
但是从接口和互连可以大概看出,p1到p2的一部分逻辑被放到了p1前的输入侧(即p0级),一部分被放到了p2到p3之间:
中间模块作用在p3的D端:
中间模块的输入一部分直接来自于输入datax:
最后看一下report:
没有retiming时是22级逻辑,分散到p0~p1~p2~p3三级之后最长路径变成了8级,太合理了三八二十二嘛。而后看一下时序单元数量由336增加到了883,说明确实有多出来的中间变量需要进行缓存。而组合逻辑数量是下降了的,总的面积(我这里没截)也下降了,这也比较正常面积增加减小或者大体不变都是有道理的。甚至时序单元也不一定就增加,比如部分逻辑前移了可能会省去一些寄存单元。
最后由这里延伸,最近学习到的另外一点经验就是,我们不是经常会在设计中调用DW ip吗,当DW的ip时序不满足时就可以在其后面插入寄存器(比如我们手动加2拍寄存器),然后通过set_optimize_registers命令来优化这个DW使其逻辑分散于这几拍中完成。