"物理设计"到底指什么
在前端这条线里,综合交给你一份网表:一张列出真实门以及连接它们引脚的连线的清单。它告诉你芯片由*什么*组成——这个 NAND 驱动那个触发器——却对每样东西*摆在哪里*只字不提。网表纯粹是连接关系;它完全没有几何信息。想象一份房屋的布线图,它标出了每个插座和开关、以及哪根线接哪根线,却从不说明任何东西位于哪个房间。物理设计要填补的,正是这道缺口。
物理设计(即*后端*,简称布局布线)就是把这张扁平、没有位置的网表变成硅片上具体排布的手艺:每个标准单元都拿到一个 *(x, y)* 坐标,每根连线都变成一条在引脚之间穿行的真实金属条。前端问的是"逻辑行为对不对?",后端问的则是那个赤裸裸的物理问题:"这一切究竟*塞得下*、连得通、跑得够快、并且通电后还能正常工作吗?"
你正要起步的这套流程有一个固定次序,每一步都依赖于前一步:布局规划 → 布局 → 时钟树综合(CTS)→ 布线 → 提取 + 时序签核 → 物理验证(DRC/LVS)→ 功耗签核 → 流片。本指南讲的是最初的第一级台阶——布局规划——因为在你确定所有东西所栖身的那块地的形状之前,你既无法放置一个单元,也无法布一根线、查一处时序。
网表 → 几何
咱们把"没有几何信息"这个概念落到实处。网表里的一个实例,看起来就是一个带命名引脚、引脚接到各条网络上的零件——和你在综合末尾看到的结构形式一模一样。读读下面这段代码,留意*缺了什么*:通篇没有一个坐标、尺寸或层次。工具知道这两个单元是连在一起的;却完全不知道它们最终是紧贴在一起、还是相隔一毫米。
// Netlist: connectivity only — NO location, NO size, NO layer NAND2_X1 u_g ( .A(a), .B(b), .Y(n1) ); // where is u_g? unknown DFF_X1 u_q ( .D(n1), .CLK(clk), .Q(q) ); // where is u_q? unknown // 'n1' says u_g.Y connects to u_q.D — but not how far the wire must travel
物理设计补上了网表所缺的三样东西。第一,给每个单元一个位置——硅片上的一个 *(x, y)*,像把书摆上书架那样对齐到固定的单元行上。第二,真实的连线——每条网络都变成一层或多层布线层上的物理金属,有实实在在的长度、宽度和拐弯。第三,一种距离感——一旦单元有了位置,工具终于知道某根线是 5 µm 还是 500 µm 长,而*那段长度要花掉真实的时间*,因为线越长,信号要充电的电阻和电容(RC)就越大。
晶粒、核心与布局规划
在放置任何东西之前,你要先决定那块*地的形状*。晶粒(die)是你将从晶圆上切下来的那整块矩形硅片——相当于地界线。紧贴它内侧的是核心(core):你的标准单元和单元行所栖身的那片可用内部区域。核心边缘与晶粒边缘之间那一圈空间,留给 I/O 焊盘和密封环——把它想成一块可建地皮四周的人行道和围栏。核心几乎总是一个规整的矩形,因为标准单元住在笔直、等高的单元行里,而单元行铺在矩形的地上最为高效。
布局规划就是在一个单元都还没放置之前画好这张规划图——而城市规划这个类比恰如其分。规划师不会随手把房子扔下去碰运气;他们先划分区、为大型公共建筑预留地块、规划主干道、铺好供水与供电的主管线。*然后*才轮到一栋栋房子填进街区。你的布局规划做的是同一件事:定下晶粒和核心的尺寸、为大块电路预留区域、规划信号将穿行的宽阔通道、铺好电源网格——这一切都赶在那一大群小小的标准单元涌入之前完成。
有两个数字为这张规划图定调:核心面积(你有多少可建的地)和纵横比(aspect ratio)(它的宽高形状)。接近正方形的核心,能让最长的那根线尽量短而均衡;又长又窄的核心,则可能让某个远角缺少布线余地。你是在还不确切知道家具将如何摆放之前就在挑这块地皮——这正是为什么布局规划既靠算术、也同样靠判断。
摆放宏单元与 I/O
你设计里并非样样都是小小的标准单元。有些部件是宏单元(macro)——大块的、预先做好的、形状固定的电路块,比如 SRAM 存储器、PLL 或模拟 IP。如果说标准单元是房子,那宏单元就是体育场和购物中心:它们占据大片矩形地盘,有着别的东西都不许压上去的硬边界,而且*你要先用手工把它们摆好。*其余的一切都得绕着它们走,所以一旦把它们摆错,整张规划图都会跟着遭殃。
好的宏单元摆放,遵循几条颠扑不破的经验法则。把宏单元推向核心的边缘和角落,像把衣柜靠墙摆那样,好让中央敞开,留给那片标准单元的海洋。让每个宏单元的引脚朝内,朝向跟它对话的逻辑,这样那些连接才能保持短——一块存储器若把数据引脚对着空荡荡的晶粒边缘,那每一根不得不绕回来的线都是浪费。还要留出一圈净空通道(halo,即环绕空隙)围在每个宏单元四周,好让信号和电源有地方从旁边绕过,就像你在家具周围留出过道一样。
- 先用手工摆放宏单元:把那些大块的固定电路块推到边缘和角落,让它们的引脚朝向用到它们的逻辑,并在每个周围保留一圈布线净空(halo)。
- 分配 I/O——决定信号和电源从晶粒的哪里进来。把相关的引脚归在一起,并把每个 I/O 放在它所服务的片上逻辑附近,好让从焊盘到逻辑的那根线保持短。
- 让核心内部保持敞开。你在中央守护出来的那片宽阔矩形空间,正是自动布局器稍后将成千上万个标准单元倾倒进去的地方。
- 对通道做一次合理性检查:在脑子里把最繁忙的那些连接走一遍,确认它们有敞开的车道可以通行——就在任何单元被放置之前。
利用率:多满才算太满?
这是每张布局规划都必须回答的问题:你该把单元往核心里塞得多紧?塞得太松,你就在浪费昂贵的硅片;塞得太紧,连线就无处可走,整个设计变得根本布不通线。把这件事概括成一个数字,就是利用率(utilization)——直观地讲,它无非是*你那块可建的地有多大比例被建筑物占去了。*一块几乎空着的地皮,布线很便宜却很浪费;一块从墙到墙塞得满满当当的地皮,则连修路的地方都不剩。
具体而言,利用率就是你所有单元的面积,与它们所栖身的核心面积之比:
utilization = total_cell_area / core_area # Example: 0.42 mm^2 of cells in a 0.60 mm^2 core utilization = 0.42 / 0.60 = 0.70 # 70% full # So: core_area = total_cell_area / target_utilization # 0.42 / 0.65 ~= 0.646 mm^2 of core to aim for ~65% full
在布局规划的早期,你通常会把目标定在大约 60–70%。那段刻意留出的空隙并不是浪费——它是布线器给连线腾出的呼吸空间,再加上留给那些缓冲器和时钟树单元的地方,而这些单元是后续步骤还要往你的设计里*添加*的。要是你头一天就塞到 90%,你就等于悄悄许下了一个根本兑现不了的承诺——以为有地方留给连线和未来的单元,实则没有,而你将在下游以布不通线的拥塞来偿还这笔账。
电源网格的骨架
布局规划要铺的最后一样东西——也是最早*以物理形态存在*的东西之一——就是电源传输网络,即 PDN。那成千上万个单元里的每一个,都需要稳定的供电电压和接地回流,而这股电力得通过金属抵达它们,不是靠变魔术。所以早在单元到来之前,你就要先搭起一副电源布线的骨架:好比在房子建起来*之前*就把供水和供电的主管线沿着每一条街铺设好,因为你总不能把一个建好的街区刨开来补一根水管。
把它想象成一张实实在在用金属画出来的网格。宽阔的金属环(ring)绕着核心一圈,载着电源和地;从这些环出发,一格格规整的条带(strap)横贯整片芯片——水平条带走一个金属层,垂直条带走另一个金属层,在每一处交叉点缝合起来,好让电流能绕开障碍流动。再往最底层,细细的电源轨(rail)沿着每一行标准单元铺过去,从上方的条带上引出电力,好让每个单元就地啜饮它那一口电。环喂条带、条带喂电源轨、电源轨喂单元——这是一套从宽阔高速公路一路降到社区小街的层级结构。
布局规划一旦完成,这块地就准备好了:晶粒和核心已经定好尺寸,宏单元和 I/O 已经锚定,利用率给布局器留足了施展的空间,电源骨架也已铺就。*现在*——也只有到了现在——自动布局器才能把标准单元倾倒进来。而那,正是下一篇指南接着讲的地方。