從腦中草圖到一片晶圓:整條流程
在前幾階你設計了一套架構:會前遞結果的管線、一層層的快取,也許還有個加速器。你最終用 Verilog 把它寫出來——幾萬行描述的是*行為*:當時脈一跳,這個暫存器載入那個總和。你沒有寫的,是任何一顆電晶體、任何一條線、任何一塊金屬矩形。然而一顆現代 SoC 有數百億顆電晶體、數十層像城市道路般疊起的金屬層。你的行為描述與那個物理現實之間的鴻溝,完全由軟體跨越,而那套軟體的總稱就是 EDA——電子設計自動化。
整條流程是一場接力,每一棒都把你的設計「降階」到更貼近物理的形態。把它想成編譯,只是目標不是機器碼——而是一組光罩,晶圓廠會用EUV 光把它印出來。
- 邏輯合成——把你的 RTL 翻譯成一張由通用布林閘組成的網表,並針對面積、速度與功耗最佳化。
- 技術映射——把那些通用閘換成晶圓廠標準元件庫裡的真實元件(這顆 NAND4、那顆驅動強度 2 的正反器)。
- 分割與平面規劃——把龐大設計切成可管理的區塊,並決定每個區塊住在晶粒上的哪裡。
- 佈局——為每一顆元件指定區塊內精確的 (x, y) 位置。
- 時脈樹與繞線——建出時脈分配網路,再用真實的金屬線跨越各金屬層,把每個接腳連起來。
- 簽核——在投片(tape-out)前,驗證時序、功耗,並確認佈局遵守晶圓廠的每一條規則。
邏輯合成:把行為變成閘
從最上層開始。邏輯合成是硬體世界的編譯器。它讀進你的 RTL,搞清楚每一塊在計算什麼布林函數,然後吐出一張由閘組成的組合邏輯網路——AND、OR、NOT、XOR、多工器——再加上保存狀態的正反器。關鍵是它一邊做、一邊*最小化*你選定的某個成本:閘數最少(面積)、關鍵路徑最短(速度),或切換最少(功耗)。同一行 RTL `assign y = a & b | a & c;`,依你要什麼,可以變成兩顆閘或一顆、變快或變慢。
RTL (what you wrote): One synthesised form (what you get):
assign y = a & b | a & c; a --|&|---\
b --| | \
|OR|-- y
a --|&|--/
c --| |
Boolean-minimised: y = a & (b | c) -> one AND + one OR, fewer transistors工具怎麼*知道* `a & b | a & c` 等於 `a & (b | c)`?它得對布林函數做形式化推理——比較兩個、證明它們相同,或找出更便宜的那個。經典的資料結構是二元決策圖(BDD):一張壓縮過、具標準形的圖,把布林函數表示成一連串「這個輸入是 1 就走這、否則走那」的決策。化簡到標準形後,兩個函數相等若且唯若它們的 BDD 是同一張圖——等價性檢查就變成指標比對。
SAT 求解器:默默證明一切的主力
在大量 EDA 的底下——等價性檢查、形式化性質驗證,甚至部分繞線與測試樣式產生——躺著一個看似簡單到不行的問題。給定一個布林公式,存不存在*任何一組*真假指派,能讓整個式子為真?這就是布林可滿足性,簡稱 SAT,而回答它的程式就是 SAT 求解器。SAT 是史上第一個被證明為 NP-complete 的問題(Cook,1971),所以最壞情況下毫無希望。近 25 年的劇情大轉折是:現代求解器能在幾秒內輾過擁有數百萬變數的*真實世界*實例。
你要怎麼用一個回答「能/不能滿足」的神諭,去*證明*兩個電路相等?你建一個 miter(對撞器):把兩個電路接到相同輸入,再把它們的輸出 XOR 在一起,問 SAT:「這個 XOR 有可能為 1 嗎?」如果求解器說*不可滿足*,那就沒有任何輸入能讓它們不同——它們被證明等價。如果它回傳一組可滿足指派,那組指派就是一個具體的反例,精確指出哪些輸入讓它們分道揚鑣。把驗證問題轉成可滿足性問題的這一招,正是形式化等價檢查跳動的心臟。
golden circuit --+ (your RTL) |---[XOR]--- miter_out ask SAT: "miter_out = 1 ?" revised circuit --+ (after synthesis) UNSAT -> outputs can never differ -> circuits are EQUIVALENT (proof) SAT -> here is an input vector that makes them differ -> BUG, with witness
落到矽上:先分割,再佈局
現在你手上有一張網表——數百萬顆映射過的閘,以及它們之間的線。下一份工作極度物理:替每一顆閘在一塊平坦的矽矩形上給出 (x, y) 座標。但你沒辦法一次最佳化數百萬個物件,所以工具先做電路分割:把網表切成一群群「內部講很多話、跨切口講很少」的群集。把跨越分割邊界的線數最小化,正是 min-cut(最小切割),而經典啟發法——Kernighan–Lin,後來的 Fiduccia–Mattheyses——會反覆在兩半之間交換節點來縮小切割。跨切口的線越少,之後長距離繞線就越少,意味著更小的延遲與更低的功耗。
等平面規劃把各區塊的形狀定下來,工具就跑佈局演算法,把元件的確切位置釘死。現代佈局器大多是解析式(analytic)的:把每條線都當成一根把相連元件拉在一起的彈簧(最小化彈簧總能量,也就是總線長),解一個巨大的二次最佳化——然後再做*合法化*,把重疊、散開的結果輕推到合法的元件格點上。它有個更老、更直觀的親戚,就在下面:把佈局當成冷卻中的金屬。
模擬退火:借物理之力逃離壞答案
面對一個有數十億種排法、又沒有最佳解公式的問題,你要怎麼最佳化?整個 EDA 裡最優美的答案之一,直接來自冶金學。鐵匠退火金屬時,會把它加熱到原子能自由晃動,再*慢慢*冷卻;原子就會安頓進一個低能量、近乎完美的晶體。冷得太快(淬火)原子就會凍結成一團混亂、高能量、滿是缺陷的狀態。模擬退火就是把這套物理變成演算法。
- 為目前的解定義一個能量(成本)——以佈局來說,就是總線長加上壅塞加上時序懲罰。
- 做一個小小的隨機移動——交換兩顆元件,或把一顆挪動一點。
- 如果這步降低能量,永遠接受。如果它升高能量,仍以機率 e^(-ΔE/T) 接受。
- 依冷卻排程慢慢調低溫度 T,讓「往高處走」的步隨時間越來越罕見。
- 當 T 趨近零、解不再進步時停止——它已「凍結」進一個不錯的局部最佳。
那一行——*接受一些讓情況變差的步*——就是全部的訣竅。一個只肯往下走的貪婪最佳化器,會困在它跌進的第一個山谷裡。藉由在還「熱」的時候容忍偶爾往上一步,退火能爬出一個平庸的谷、找到更深的谷。隨著冷卻,它逐漸定型。這是一種刻意、可控地早期變差,好讓它晚期變優秀的搜尋。
accept_prob(dE, T) = (dE <= 0) ? 1.0 : exp(-dE / T)
T high (hot): exp(-dE/T) ~ 1 -> almost any move accepted (explore widely)
T low (cold): exp(-dE/T) ~ 0 -> only improving moves (refine, commit)
cost landscape: you are here
v
\ good /----\ * /\ <- greedy stops in this shallow dip
\ (deep) / \__/ \___ <- annealing's uphill jumps reach the deep one
\__valley_/繞線,以及裁決這一切的時序圖
元件擺好了,現在把它們連起來。繞線演算法必須為每一條網路跨越十幾層鋪設真實金屬,遵守間距規則、閃避阻擋物,且絕不讓兩條無關的網路短路。它的核心是 3D 格點上的最短路徑搜尋——Lee 的迷宮繞線器,或 A*——外面包著全域/細部兩階段,以及經典的拆線重繞(rip-up and reroute):當網路為同一條軌道爭執,就把輸的那條拆掉、另尋路徑。工具就這樣繞超過十億個連線;它居然會收斂,本身就是奇蹟。
但一顆*連起來*的晶片,不等於一顆*能動*的晶片。它還得夠快:每一個由正反器發出的訊號,都必須在下一個捕捉它的時脈邊緣之前,抵達下一顆正反器。要為數十億條路徑檢查這件事、又不模擬任何一條波形,是靜態時序分析的工作——而它立基於一個優雅的點子:時序圖。
把整個電路建模成一張有向圖:每個閘的接腳是一個節點,每個閘延遲與線延遲是一條帶權邊。從某顆正反器輸出到下一顆正反器輸入的最長路徑——關鍵路徑——決定了晶片能跑的最快時脈。在一般圖裡找最長路徑是 NP-hard,但時序圖是一張 DAG(沒有組合迴路),而在 DAG 裡,最長路徑只要一次拓撲序掃描就能以線性時間解出。這正是為什麼 STA 能在幾分鐘內、而非幾千年內,替整顆晶片打分。
FF1/Q --[g1: 0.12ns]--> a --[wire: 0.05]--> b --[g2: 0.20]--> c --[wire: 0.08]--> D/FF2
Arrival time at each node = max over incoming edges (longest path so far):
AT(a)=0.12 AT(b)=0.17 AT(c)=0.37 AT(D)=0.45 ns
Required time at D = clock_period - setup = 1.00 - 0.10 = 0.90 ns
SLACK = Required - Arrival = 0.90 - 0.45 = +0.45 ns -> PASS (timing met)
(negative slack = critical path too slow = the chip fails at this frequency)現在退一步,看清這條學習軌道的整道弧線。你學會了像架構師一樣*思考*——管線、危障、快取、平行、加速器。這最後一階,展示的是把那份意圖化為原子的機器。你做的每一個架構抉擇,最終都會落成 EDA 工具必須滿足的一個旋鈕:更深的管線縮短時序圖量測的關鍵路徑;更大的快取變成平面規劃器得擺放的巨大巨集;加速器規律的資料流,會讓繞線器的工作變得輕鬆、或者擁塞到不可能。架構與 EDA 不是兩個世界——它們是同一道連續降階的兩端。再留意工具箱裡那份深層的一致性:合成與驗證靠 BDD 與 SAT 求解器、分割靠 min-cut 啟發法、佈局與平面規劃靠 模擬退火與解析式求解器、繞線靠 帶拆線重繞的最短路徑搜尋、時序靠 DAG 上的最長路徑。它們沒有一個找到完美解;它們全都找到一個好到能印、快到能迭代的解——而這正是一個十億電晶體的設計能被一隊人類真正打造出來的唯一原因。