用金屬把一切連起來
到這一步,佈局已經把每個標準單元停進了各自的格子,時脈樹合成也把時脈接好了。可你退後一步打量整顆晶片,會發現一件讓人不安的事:這是一座沒有道路的高樓城市。每個單元的輸入、輸出接腳都孤零零地立在那兒,在電學上彼此隔絕,等著被連起來。網表裡寫著*「這個 NAND 的輸出必須送到那三個正反器的輸入」*——可眼下還沒有任何東西把這個訊號在實體上送過去。繞線就是鋪下金屬、真正完成這些連接的那一步。
你可以把它想成:在已經分配好的地址之間鋪路。繞線器的活兒,是為設計中的每一條網路,從每個驅動接腳到它要餵的每個負載接腳,畫出一條連續的金屬帶——而一顆現代晶片有數以百萬計的網路。它不能直接畫直線,因為那樣導線會交叉、短路在一起。於是它把這些線穿織進一張層疊的網格裡,就像一座城市把車流分攤到地面街道、高架橋和隧道上,讓車輛永不相撞。
金屬堆疊(BEOL)
電晶體本身住在最底層,刻在矽裡——那一層叫前段製程(front end of line,FEOL)。疊在它們*上方*的一切都是繞線,那就是後段製程(back end of line,BEOL):一疊由絕緣層隔開的金屬層,在選定的位置上下打通。這就是你的路網,而且是真正意義上的多層結構——想像十幾層甚至更多層的高速公路一層疊一層,每一層的車道都只朝一個方向跑,於是相鄰兩層是相互垂直交叉,而不是去搶同一條車道。
對後端工程師來說最要緊的一點是:每一層並不一樣。最底下的幾層金屬(就叫它們 M1、M2)又薄又窄——用來在相鄰單元之間做短距離的本地跳接正合適,但單位長度的電阻很大,像一條擁擠的單車道窄巷。上層金屬則又厚又寬——電阻低,專為橫跨整顆晶片的長途奔襲以及供電網路而生,像一條六車道的高速公路。所以繞線器並不把各層當成可以隨意替換的:短的本地網路留在底下,又長又時序緊要的網路以及電源則被「升」到樓上,那裡的金屬又粗又快。
# Resistance of a wire segment (intuition, not a tool command) # R = rho * Length / (Width * Thickness) # Thinner + narrower lower layers -> small (W * Thickness) -> larger R. # Same length on a thick upper layer is far less resistive.
全域繞線 → 詳細繞線
你不會一口氣把整顆晶片繞完,就像導航軟體不會在你還沒倒出車道之前,就把整趟行程逐條車道地算清楚。繞線器分兩遍來做,先粗後細,而這兩遍之間的區別,正是這一節要建立的整套思維模型。
全域繞線是在「區域」這個層級上做規劃。整顆晶片被切成一張粗粒度的方格網(這些格子常叫 *gcell*),繞線器為每條網路大致定下*它會穿過哪些格子、騎在哪些金屬層上*——此時還一根精確的線都不畫。這就是高速公路規劃的視角:「這個訊號往東北方向,穿過這幾片街區,主要走上層樓面。」尤為關鍵的是,全域繞線還會統計有多少導線想穿過每條格子邊界,於是它能在真正動手之前就看到麻煩——太多車都想擠同一個上匝道。
詳細繞線接著才是真正的鋪路。它拿過全域規劃,把實際的金屬鋪在合法的軌道上——也就是每一層上預先定好的「車道」——挑定確切的寬度、確切的位置、確切的導孔點,把所有東西都對齊到晶圓代工廠允許的格點上。導線就是在這一步從「意圖」變成真正的幾何圖形。
- 全域繞線:把晶片切成粗格子,給每條網路分配一條大致路徑和一份層預算,並估算導線會在哪裡堆積。
- 軌道分配:在每條網路選定的層上,給它指定具體的車道,把車流攤開,好讓詳細繞線那一步有騰挪的餘地。
- 詳細繞線:畫出確切的金屬線段和導孔,全部對齊到合法的軌道和格點位置上。
- 搜尋與修復(search-and-repair):揪出剩下的違規之處,對惹事的導線做拆線重繞,直到佈局乾淨為止。
導孔與換層
一個訊號光靠一層樓是到不了目的地的——它遲早得換層,就像司機得離開地面街道、上到高架橋上去。各金屬層之間在設計上本就是相互絕緣的,所以導線要在相鄰兩層之間跳轉,唯一的去處就是在絕緣層裡特意打通的那個垂直連接:導孔(via)。導孔就是這疊金屬層的上下匝道。
一個導孔只連相鄰的兩層——M1 到 M2、M2 到 M3,依此類推。要從低層一路爬到上面的厚金屬層,繞線器就得搭一座導孔疊(via stack):一列上下疊起來的導孔,每層一個,筆直地穿過這些樓層。一個從底下 M1 上某個單元接腳出發的訊號,正是這樣被吊上 M6 這條高速,再一路降下來搆到它的負載。
繞線中的壅塞與 DRC
晶片上有些街區想穿過去的導線,遠遠多過能容下它們的車道數。這就是壅塞:某個區域裡對繞線軌道的需求超過了供給。它通常能追溯到更早做出的選擇——佈局時單元堆得太密,或是許多網路匯聚到的某個熱點——這也是為什麼壅塞是後端工程師收到的、提示「平面規劃或佈局得再看一眼」的最響亮訊號。當一個區域過度壅塞,詳細繞線器就是塞不下所有導線、又不違規,於是你要麼得到失敗,要麼得到難看的繞遠——把導線拉長,進而傷害時序。
而且繞線器並不能哪兒塞得下就往哪兒塞金屬——它畫的每一根線,都必須一邊畫一邊遵守晶圓代工廠的規則,也就是設計規則。同一層上的兩根線之間至少要隔開一個最小距離,否則就會短路、或是根本造不出來;每根線都有最小線寬;導孔還有自己的包覆(enclosure)和間距規則。繞線器本質上是在解一道巨大的裝箱難題,而每一塊拼圖都得遵守晶圓廠寫下的那本規則手冊。
當繞線器確實撞上一個一遍走不掉的違規時,它就退而求其次,使出拆線重繞(rip-up and reroute):把惹事的導線扯掉,再沿一條能避開衝突的不同路徑重新鋪下去。你可以想像:重鋪一段路來緩解一處塞車,然後再去查查,看自己是不是一不小心在兩個街區外又造出了一處新的塞。它天生就是迭代式的,這也是為什麼繞一個大模塊可能要跑上好幾個小時。
導線不是免費的(RC)
下面這個觀念會直接把你帶進下一篇。在前端的世界裡,一根導線幾乎就是免費、瞬時的連接——電路圖上的一根線而已。而在下面這裡,它是一條實實在在的金屬帶,而真實的金屬有兩個躲不掉的屬性:電阻(R),因為金屬會阻礙電流;以及電容(C),因為這根線挨著別的導體,會像一個小電容的兩塊極板那樣,在它們之間存住電荷。
這兩者合在一起,就讓每根導線都帶上了一份延遲。直覺很簡單:訊號沒法瞬間把一根線的電壓翻轉過來,因為它得先把電流*推過*電阻,去給電容充上電——而這個 R 乘以 C 的乘積越大,導線就要越久才能穩定下來。一條又長、又走在底層薄金屬上的網路,是兩頭吃虧的最壞情形:薄金屬帶來一大堆電阻,長度又帶來一大堆電容。這正是長網路被「升」到上層厚金屬去的更深層原因——金屬更粗就砍掉了 R,延遲也就跟著降下來。
# Why a wire now costs time (intuition, not a tool command) # wire delay grows with R * C # R larger on thin/narrow lower layers # C larger for long wires and tightly-packed neighbors # => long net on thin metal = slow. Same net on thick upper metal = faster.