翻译_怎样优化面积和时序_1
Rober B. Wiegand
系列目录
摘要
时序收敛和面积优化通常被认为是两个相互排斥的目标。但实际上,面积优化可以对设计产生许多积极的影响,包括改进时序。
尽管没有单一的神奇方法能够保证在满足时序要求的同时得到最小的设计,但多种因素的结合可以显著地减少时序关键设计中的面积。
本文将讨论减少面积的好处,解决一些担忧,并详细介绍一整套技巧,这些技巧结合起来可以在保持时序的同时显著减少面积。
1.0 引言
随着时钟频率的提高、设计的复杂性增加,以及市场紧迫的时间要求,面积优化在ASIC设计中可能会被忽视。
这就像是“好、快、便宜 - 任选其二”的困境,其中“好”代表时序/设计收敛,“快”代表快速上市,“便宜”代表面积和功耗的优化。当快速上市成为首要目标时,面积优化和时序收敛似乎成了不可兼得的目标。
在2000年SNUG San Jose会议上,Synopsys的一个教程“从Design Compiler中获取面积和延迟的最大效益”就体现了这种观念,该教程分为两个部分,一部分针对面积优化,另一部分针对时序优化。
面积缩减技术经常被因为“不适用于时序关键设计”的声明而被忽视。但所有设计都是时序关键的!另一个忽视面积缩减技术的原因是设计的时间表非常紧张。但理解了面积缩减的潜在好处后,最佳的方法似乎是在流程的适当阶段内置面积缩减技术,以在最小化对时序和时间表的影响的同时获得最大效益。
2.0 为什么尺寸很重要
“Gate saved is a penny earned.”(每节省一个门,就相当于赚了一分钱)在核心受限的设计中,节省的每一点尺寸都能直接降低芯片的成本,因为这样可以在每个晶圆上制造更多的芯片。这反过来可以提高成本竞争力或增加利润空间。随着生产量的增加,成本效益也会随之增长。
减少可放置实例的数量和导线数量有助于降低布线拥塞。制造一个更容易布线的设计,无论是对于内核受限还是IO引脚受限的设计,都有助于缩短上市时间。
通过减少导线数量和逻辑层次,可以改善时序收敛。但需要注意的是,缩小芯片尺寸会提高利用率和拥塞(以及边缘电容效应),这反过来又会影响时序收敛。在时序收敛方面,我们可能会达到一个平衡点,但仍然可以保持因面积减少而带来的成本优势。
另一个减少面积的好处是改善功耗。简单来说,更少的逻辑门意味着更低的功耗。在较少的导线上驱动较少的电容也会减少功耗。改善功耗可以影响封装选择和市场竞争力,这两者都有助于公司的利润。
最后,面积减少可以提高可靠性、测试性和产量。更少的逻辑门和导线意味着制造缺陷出现的地方更少,这有助于保持产量和利润——这是另一个财务上的好处。更少的逻辑门和导线还意味着测试“卡住”条件的节点更少,这可以减少测试时间,从而进一步节省成本。
简而言之,尺寸的减少可以在多个方面带来好处,包括成本效益、设计可布性、时序收敛、功耗降低、以及提高可靠性和产量。这些都是提高公司财务表现的关键因素。
3.0 解决担忧
假设所有设计都是时序和时间表关键的,显然的担忧是,一个人如何在不负面影响时序收敛和时间表的情况下考虑面积优化。也许最有效的保障是拥有一套标准化的综合脚本和方法论,其中内置了面积减少技术。这样,项目中就不需要脚本架构(无论是为了面积还是其他任何事情)。不必为每个项目从头开始构建脚本,可以显著降低风险,并允许在流程开发中考虑面积减少技术。
将面积减少技术“内置于流程中”,时间表压力就不能成为跳过面积优化的理由。应该在与项目无关的测试用例上运行面积减少技术,以验证它们的效果和对时序的影响。项目脚本编写应该只包括异常管理和将设计映射到流程。这允许独立于项目的流程开发和优化,大大降低了风险。如果为了面积目的脚本或修改了异常,运行测试用例将最小化任何增加风险的感知。
4.0 关键方法论问题
一些主要的面积优化对象包括时间表压力、感知风险、自上而下的编译、过度约束、未能使用选择性取消分组——特别是在设计组件上,以及未能在RTL中为资源共享编码。所有这些问题都可以通过坚持既定的方法论来管理。
正如前面所讨论的,仅仅拥有一个脚本化的综合方法论就能解决前两个问题。第三个、第四个和第五个问题必须在脚本和方法论中得到解决。最后一个问题必须在综合之前通过包括面积考虑在内的公认和遵循的RTL编码指南来解决。
4.1 不要使用自上而下的编译
上述提到的关键方法论问题之一是自上而下与自下而上的编译策略的使用。
尽管自上而下的编译策略允许综合对时序有完全的可见性,但使用这种方法来优化面积是非常困难的。
尝试在大型设计上执行自上而下的编译时添加激进的面积约束实际上是不切实际的,因为这会影响运行时间。一个更实际且对面积友好的方法是使用自下而上的方法,配合激进的max_area
约束。
为了克服通常与这种方法相关的时序困难,应该使用多通道自下而上的方法,连续细化下层约束(使用特征值或预算),结合自上而下的增量优化。
通过使用分而治之的方法,自下而上的策略允许面积优化技术如max_area
在合理的运行时间内有更大的影响。尽管对于max_area
约束的值有许多观点,我发现max_area 0
在使用多通道方法时始终能产生积极的结果。
4.2 不要过度约束
另一个关键的方法论问题涉及到过度约束设计的做法。过度约束会通过迫使设计过度构建、在单元上使用比必要更高的驱动强度,以及强制使用更占用面积的设计组件实现,从而消耗面积。
现实和逐步细化的约束对面积更友好。
应该在脚本和方法论中内置的默认约束,应该反映合理的输入和输出延迟、输入驱动器和输出负载。
例如,**使用1X
驱动触发器的Q
输出引脚作为默认驱动单元引脚,使用1X
驱动NAND
门的A
输入引脚的4倍作为模块的默认输出负载。**对于默认输入延迟,允许驱动触发器的时钟到Q加上一个小的线延迟。
对于默认输出延迟,允许驱动触发器的设置时间加上一个小的线延迟。
使用虚拟时钟来约束组合块的I/O,或者更倾向于将组合块不分组到它们的父设计中。组合路径和“蛇形”路径,可能还有一些顺序路径,最初会被欠约束。这将在单通道方法论中造成很大困难。但是,通过使用多通道方法论,约束将在后续通道中被细化,而不会过度约束整个设计。
4.3 用设计规则来保留余量
传统上,过度约束是为了减少由于非时序感知布局工具引起的时序损失。
随着当前广泛使用时序驱动的布局工具,时序精度(特别是关于预测的时钟插入延迟和偏斜)可能比时序余量更为重要。然而,建议用设计规则而不是时序约束来为设计保留余量。
一个例子是在布局前收紧max_transition值,然后在布局后将其放宽到一个可接受的值。
另一个例子是在编译设计时使用10到20的max_fanout来减少布局中意外时序波动。
另一个例子是在编译块的所有输入端口上设置max_fanout。输入和设计上的max_fanout约束结合,可以防止在设计层次结构中更高层次上出现高扇出负载的意外,并且限制了时序驱动布局工具需要执行的缓冲区数量。
我发现将输入max_fanout值设置为1非常有效,有时在多通道编译策略的最后一通道中可以取消这个约束。任何由此产生的不必要的缓冲将在综合中的核心级别增量优化中被优化掉。
再次强调,这些基于设计规则的余量技术应该被内置到脚本和方法论中。
4.4 使用选择性取消分组
还有一个关键的方法论问题是关于使用选择性取消分组和对已经编译的设计应用 set_dont_touch
属性。
非常小的设计,尤其是纯组合逻辑的设计,应尽可能将其子模块取消分组到它们的父模块中。编译生成的层次结构,包括设计组件和多路选择器操作组件,也应该进行取消分组处理。取消分组这些组件可以移除边界条件,从而允许进一步的面积优化。
如果在编译前就进行取消分组,由于综合需要一次性考虑更多的设计内容,可能会导致运行时间变长。分层编译虽然在运行时间上有优势,但会消耗更多的面积,并且需要进行分层保存,这会导致在整个设计中产生同一子模块的多个版本。
为了同时获得运行时间优势和面积优化,可以先加载父模块和子模块,然后进行分层编译以利用运行时间优势。编译完成后,对子模块和编译生成的层次结构进行取消分组,应用 set_dont_touch
属性到设计上,并在不切换层次结构的情况下保存。
随后进行的高努力 max_area 0
增量编译将通过消除层次结构边界来获得面积上的优化。不要在不包含逻辑的纯层次结构模块上执行编译。相反,应加载设计,进行链接,应用包括 set_dont_touch
在内的约束,然后在不切换层次结构的情况下保存并运行报告。
当一个高级模块主要包含层次结构但只有很少的逻辑时,应按照上述程序进行,但有一个变化:在应用约束后,将逻辑分组到一个临时设计中,编译这个临时设计,然后将编译后的逻辑取消分组并重新整合回父模块,在保存和运行报告之前不要切换层次结构。
这种方法大大提高了运行时间,并通过防止综合在设计更高层次插入不必要的缓冲区来节省面积。通过多通道方法,子模块中的违规问题可以在后续的编译通道中得到修复。
4.5 RTL编码问题
最后,通过在一套RTL编码指南中包含一些面积和资源共享的考虑,可以进一步改善面积结果。
这些考虑包括推断操作符而不是实例化设计组件,在同一个always块中编写可共享的操作符,以及使用带有infer_mux指令的case语句来推断寄存器源MUX。
通过手工实例化设计组件,会丢失几个面积优势。首先,**只有在同一个always块内推断出可共享的操作符时,资源共享才会发生。**即使在不同的wire语句中推断出操作符,也不会发生资源共享。通过直接实例化设计组件,会阻止资源共享。
其次,像transform_csa和optimize_registers(也称为BOA/BRT,或行为优化算术和行为重定时)这样的时序和面积转换不能在实例化的设计组件上执行(优化寄存器可以,但不是最优的)。
transform_csa命令可以通过将多个算术操作符合并为单个进位保存加法器(CSA)树,在末端保存(且仅有)一个进位传播加法,从而获得巨大的时序和面积好处。如果CSA树是流水线化的,optimize_registers命令可以通过在时序裕度允许的情况下,将寄存器组滑动到需要较少寄存器的阶段来改善面积。如果不是,通过在阶段之间平衡时序裕度来改善时序。transform_csa命令需要推断出的操作符,而两个命令都需要DC Ultra许可证。
手工实例化设计组件的一些传统原因包括使用加法器上的进位输入和进位输出端口,或从Verilog RTL生成有符号乘法器。
always @(a or b or carry_in ) begin
{carry_out, sum} = a + b + carry_in;
end
使用以下变量设置:
hdlin_use_cin = true
Verilog中的有符号乘数有点麻烦,但可以通过示例1中所示的函数调用来推断:
module sgn_mult (a, b, y);
input [7:0] a, b;
output [15:0] y;
reg [15:0] y;
function [15:0] mult_tc; /*2's comp signed mult*/
input [7:0] A;
input [7:0] B;
reg sgn;
// synopsys map_to_operator MULT_TC_OP
// synopsys return_port_name Z
begin
// synopsys translate_off
sgn = A[7] ^ B[7];
if (A[7] == 1'b1) A = ~A + 1'b1;
if (B[7] == 1'b1) B = ~B + 1'b1;
mult_tc = A * B;
if (sgn == 1'b1) mult_tc = ~mult_tc + 1'b1;
// synopsys translate_on
end
endfunction
always @ (a or b) begin
y = mult_tc (a, b); // a*b
end
endmodule
Example 1. Coding a Signed Multiplier in Verilog
知道何时和何时不推断MUX也很重要。
当数据路径中的MUX源包含常量时,不应该推断MUX,因为它们会阻止常量允许的逻辑缩减。
当MUX的源都是寄存器驱动时,MUX将通过减少门数、可放置实例的数量和它们之间的互连来产生最佳的面积效益,并产生更规则的结构。
要知道非常重要的一点是Verilog条件运算符构造C-SEL ? A : B
不会在合成中自动推断MUX。
为了保证MUX,即使是2对1的MUX,使用一个完全指定的case语句和//synopsys的inter_mux指令。如果没有inter_mux指令,即使是完全指定的case语句也可能不会合成MUX。另外,使用以下变量设置:
hdlin_infer_mux = default
将该变量设置为“all”将消除对infer_mux指令的需要,但是带有常量的case语句也会产生mux,并失去常量允许的逻辑缩减。