"實體設計"到底指什麼
在前端這條線裡,合成交給你一份網表:一張列出真實閘以及連接它們接腳的連線的清單。它告訴你晶片由*什麼*組成——這個 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 已經錨定,利用率給佈局器留足了施展的空間,電源骨架也已鋪就。*現在*——也只有到了現在——自動佈局器才能把標準單元傾倒進來。而那,正是下一篇指南接著講的地方。