JOVANA
Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

摆放一百万个单元

平面规划把房间布置好之后,工具就得把成十万、有时上百万个微小的逻辑单元一一塞进去——而每个单元落在哪里,决定了你的芯片是否够快、能不能布线、甚至能不能造出来。本指南带你从最初的粗略撒点,一路走到干净、合法的版图,并教你像看天气预报一样去读懂一张拥塞图。先讲直觉,把几何形状用文字描绘出来,再配上恰好够用、驱动工具运转的那几个数字。

从平面规划到单元的汪洋

上一篇指南里你搭好了平面规划——你定下芯片的外形轮廓,把大块(存储器、模拟孤岛)停放就位,并画出了供电网的环和条带。把它想象成一间空荡荡的开放式办公室:墙立起来了,电梯和供电管道也铺好了,可一张桌子都还没摆。布局这一步要做的,就是把桌子搬进来——而且数量*多得很*。

这些桌子就是标准单元:那些小巧、事先设计好的逻辑积木(一个与门、一个触发器、一个缓冲器),由你的综合工具产出。每个单元都做成同样的高度,于是它们能像书架上的书一样卡进一条条水平的行;但宽度会随它承载的逻辑多少而不同。一个实际的模块可以容纳几十万到几百万个这样的单元。布局要为它们中的每一个决定 (x, y) 安身之处。

而且布局并非凭空进行——它必须为后面布线阶段要走的线留出空间,绕开平面规划预留的阻挡区,并尊重标准单元必须对齐的那些行。一旦做错,无论流程的其余部分多么巧妙,芯片都会无法布线或时序失败。这正是布局位于前段、且至关重要的原因。

全局布局与详细布局

工具不会一口气把一百万个单元放到它们的最终位置——这个问题太庞大了,没法精确求解。它转而分两遍来做,先粗后细,就像你会先决定每件家具放进*哪个房间*,然后再把每把椅子推到位。

全局布局是粗略的那一遍。它几乎把单元当成流体来处理:把它们铺展到整片区域上,大致平衡密度、并把有连接关系的单元拉到一起,优化的是一个把总线长和拥挤程度揉在一起的代价函数。在这个阶段,单元可以坐在*任何地方*——它们可以重叠,也还不必和行对齐。目标是一个整体上良好的排布,而不是一个可制造的排布。

详细布局是精细的那一遍。它接过那团粗略的云,把每个单元轻推到一个真实、合法的安身处——卡进某一行、对齐到布局网格、彼此不重叠——同时尽量少扰动全局的格局。它做的是局部清理:交换相邻单元、让单元沿行滑动、填补空隙。可以把全局布局想成是在划分街区,而详细布局则是把每辆车端端正正地停进车位线之间。

密度与拥塞

有两个词听起来很像,含义却大不相同,把它们搞混是新手的经典陷阱。密度(或利用率)讲的是*地面空间*——可用面积里有多少被单元填满了。拥塞讲的是*线*——有多少连接想穿过某个区域,对比那里实际容得下多少布线轨道。两者完全可以一个高、一个不高。

利用率是个简单而老实的数字:可布局面积里被单元占用的那一部分。

utilization = (total cell area) / (placeable row area)

# e.g. 0.72  ->  72% full, ~28% left as breathing room
# typical placement target ~0.60-0.80 depending on the design
利用率不过就是“房间有多满”。塞得太紧,就没有余地留给缓冲器、时钟单元,以及后面布线要硬挤进去的那些线了。

微妙之处在这里:一个区域可能只是适中地满,却已经无可救药地拥塞了,因为一团连接密集的单元正好落在那儿,想穿过那块小格子的线,远多于能承载它们的金属轨道数。这就好比一个停了七成满的停车场(没问题),和一个所有车都想同时挤出去的唯一出口(彻底堵死)之间的差别。布局两者都盯着,因为后面的布线只有在线真的塞得下时才能成功。

由时序驱动的布局

到目前为止我们谈的都是空间和线。但布局还是懂时序的——这可以说是它最重要的本职。记住,信号沿一根线传播是需要时间的,线越长意味着延迟越大。于是工具会读取时序约束,尽量把处在紧张路径上的单元在物理上挨近放,缩短它们之间的连线。

最要紧的那条路径就是关键路径:两个寄存器之间最慢的那条通路,也是富余裕量最少的一条。如果布局让一条关键路径上的单元漂得很远,单单线延迟就能撑爆你的时序预算——而且后续再怎么优化也无法完全挽回。于是工具会给这些单元一种磁吸般的吸引力,在仍然兼顾密度和拥塞的前提下,把它们拉紧。

下面就是工具在布局时要对标的时序目标——一个时钟周期,它必须把每一条寄存器到寄存器的路径都塞进这个周期之内:

# Clock the design is placed to honor (vendor-neutral SDC)
create_clock -name CLK -period 1.25 [get_ports clk]   ;# 800 MHz

# A signal launched at one register must arrive at the next
# WITHIN one period (minus setup) — placement keeps the cells
# on each path close so wire delay does not eat that budget.
时钟周期就是截止期限。布局会缩短最紧张那些路径上的连线,让信号仍能及时从一个触发器赶到下一个。

合法化

经过全局布局和详细布局之后,单元*差不多*都各就各位了——但仍有少数可能重叠了一丝丝、偏离网格一星半点,或者跨在两行的边界上。合法化就是那道收尾整理的工序,把布局弄得严格*合法*:每个单元都卡进某一行、对齐到制造网格、紧贴着邻居放好,既不重叠,也没有非法的空隙。

想象一堆胡乱塞上书架的书,有的歪着,有的探出了边缘。合法化就是那位图书管理员,把每一本都推到端端正正地立在架子上、书脊对齐、彼此不叠。关键在于,它会尽量让每个单元移动*最小*的距离来摆正它——因为它每挪动一个单元都会改变线长,可能扰乱前面几遍辛辛苦苦才达成的时序。

  1. 跑全局布局:把单元铺展开以平衡密度、并把有连接关系的单元拉到一起,允许重叠和偏离网格的位置——这是粗稿。
  2. 跑详细布局:把单元轻推到各行上、形成干净的局部排布,在不扰动全局格局的前提下精修线长和拥塞。
  3. 做合法化:把每个单元卡到合法的行与网格位置上、互不重叠,每个都移动最小距离,让时序和拥塞尽量贴近前几遍得到的结果。
  4. 在如今已合法的版图上重新核查时序和拥塞;若某个区域变差了,工具可以在交给时钟树综合和布线之前,对那里做局部的重布局和重合法化。

读懂一张拥塞图

在工具的图形界面里打开一份布局、调出一张拥塞图,你会看到一幅活脱脱像是盖在芯片上的天气雷达图。整片晶粒被切成一格格的小瓦片,每片瓦片按其布线的拥挤程度被染上颜色——具体来说,是按需求与供给之比:有多少线想穿过那片瓦片,对比有多少金属轨道可供承载。

# Per-tile congestion (the number behind each color)
overflow = wires_demanded - tracks_available

#   overflow <= 0   ->  cool (blue/green): wires fit, healthy
#   overflow  > 0   ->  hot  (yellow/red): more wires than tracks -> trouble
每一片有色瓦片不过就是需求减去供给。冷色表示线塞得下;暖色表示太多线想挤过太少的轨道。

所以你就像看热度一样去读它:大片的蓝色和绿色是平静、健康、可布线的——线宽宽松松就放得下。黄色是开始紧张了。怒气冲冲的红色和橙色斑块则是热点,那里布线很可能会失败,因为想穿过的线多过能容纳它们的轨道。一份好的布局看上去大体是冷色而均匀的;一片红海,或是几处凶狠的斑块,就是你还没开始布线之前的一记警告。

是什么造成了一团红?往往是一团连接密集的逻辑被塞得太紧、是许多线不得不从一个硬核宏单元旁挤着漏过去的地方,或是平面规划在某个角落把布线空间饿瘦了。解法呼应着前面几节:让工具把那片瓦片里的单元铺开以降低局部密度、添加或调整布局阻挡区把单元引开,或者当某个宏单元卡住了一整条通道时,回头重做平面规划。