Part 3 — 中後端收斂:讓 RTL 之後每一步都跑得過(EDA:開源補完、商業共存)

RTL 寫完,其實只走完一半。它後面還有一整排陌生又細瑣的步驟——合成、STA、PnR、CTS、DRC、LVS、IR,再加上類比——每一步都得真的跑起來、而且通過驗證。這一篇講我怎麼把開源 EDA 工具接成 AI 的手和眼,又怎麼把「開源那一段」補完到能產出 production-ready 的成果;而商業工具,隨時歡迎付費插進來。

RTL 之後,才是真正的曠野

前兩篇談的是把流程建起來、再用 benchmark 把「Spec→RTL」磨到全過。但講句老實話,寫出 RTL 只是整條流程裡最舒服的那一段。真正陌生、真正細瑣的,全在 RTL 之後——這就是三段式架構裡的第三段:中後端的收斂

從 RTL 往下,你要把它一路送過:合成、靜態時序(STA)、DFT、佈局規劃、擺放、時脈樹合成(CTS)、繞線、寄生萃取、DRC、LVS、IR-drop 與 antenna 檢查,最後才出 GDS;類比還有它自己的 A1–A9 一條軌。每一步都是一支演化了幾十年的獨立工具,有自己的 CLI、自己的腳本語法、自己的 log 格式、自己一整套稀奇古怪的失敗方式。對一個對這條流程還很陌生的軟體人來說,這一段是最難、也最花時間的地方。

而它最大的挑戰不是「難算」,是現有的開源工具有洞,會讓流程卡在半路、產不出可以拿去流片的成果。要讓 RTL 之後的每一步都真的跑得過,得先做兩件事:先讓 AI 摸得到這些工具,再把工具本身缺的那幾塊補起來。

先給 AI 一雙手和眼:MCP-EDA server

AI 很會寫 code、很會聊 RTL,但它摸不到真正的 Yosys、OpenROAD、KLayout。所以第一件事,是幫它裝上手和眼——這就是 Vibe-IC 裡的 MCP-EDA server 在做的事。

它把每一個真實的 EDA 動作,都包成一個 AI 可以直接呼叫的 tool:eda_syntheda_staeda_pnreda_drc_klayouteda_lvseda_spice……幾十個,幾乎每個後端步驟都有一個對應。走的是 MCP(Model Context Protocol)——Anthropic 提出的開放協定,Claude Code 原生就會講,所以 plugin 一裝就自動註冊,使用者什麼都不用配。我做軟體久了很清楚一件事:能不自己造輪子就不要造;MCP 剛好把「工具怎麼宣告參數、呼叫怎麼傳、結果怎麼回」這些最容易做爛的事,整套標準化掉了。

但這雙「手」還得配一雙「眼」,原因是我這個軟體人在這條路上踩得最痛的一點:這些工具很多時候不會好好跟你說它失敗了。 ngspice 在 batch 模式下 .measure 量測失敗,process 卻乖乖回 rc=0,CI 就當它過了;有些工具會給你一份看起來很乾淨的報告,底下的結果其實是錯的。所以每個 MCP tool 不只是「幫 AI 按按鈕」,它同時把工具吐出來的 log 一行一行解析、把退場碼(exit code)當一回事,回一份結構化的 JSON,並對產物算 SHA-256 存證。這樣一來,下游那條確定性的合規閘,才能拿真證據去核對,而不是聽 AI 嘴上說一句「過了」就算數。這一點,跟整個 plugin 的反虛報精神是同一件事——那是下一篇的主題。

開源工具有洞:把「開源那一段」補完

手和眼接上之後,真正的工作才開始。走真實設計時我很快撞牆:開源 EDA 工具本身是有洞的。 不是那種「當場報錯」的好 bug,是更麻煩的一種——工具給你 exit 0、給你一份乾淨報告,但結果其實不對;或者在真實寄生、真實 corner 下直接崩掉,整條後端流程斷在半路。如果架構只是「呼叫工具、相信工具」,那你就原封不動地繼承了它的每一個洞,產不出能流片的東西。

所以我做了一個對軟體人來說再自然不過的決定:把工具 fork 下來,自己把缺的那幾塊補起來。 我想先把這件事的定位講清楚,免得被誤會成在跟誰較勁——我補的,是「這條 end-to-end 流程裡,開源的那一段」。目標很單純:讓開源工具鏈能一路跑到 production-ready、跑到簽核級,而不是卡在「這一步得換別的工具」就停手。這是我自己流程的一部分,把它補完是我的責任,不是等別人。

到目前為止,一共 fork 了 13 個開源工具,而且 13 個全部都帶了我自己的修補(yosys、OpenROAD、OpenSTA、magic、netgen、iverilog、verilator、KLayout、ngspice、cocotb、cocotb-coverage、pyuvm、sby)——其中 12 個由 Dockerfile 直接 pin 住版本,OpenSTA 則是透過 OpenROAD 的 src/sta submodule pin。有一點要分清楚:「帶了我的修補」和「直接消費上游的能力」是兩件事。以 verilator 為例,我補的是 constrained-random 求解,而它的多執行緒模擬是上游本來就有、我直接拿來用——後者不代表前者不存在。xschem 目前還沒 fork,直接用上游。這些全部推到公開的 github.com/vibeic 組織下(每個都是真的、upstream-tracked 的 fork,上游修好我能拉、我修好的也能貢獻回去),再統一打包成一個公開的 Docker image:

ghcr.io/vibeic/vibeic-eda:0.2.17   # 以 fork 過的 IIC-OSIC-TOOLS 為底,疊上這些 fork 的修復

裝 Vibe-IC 的人 docker pull 一下,就拿到整套修好的工具鏈。而我給自己定的紀律是:每一個修復都要附一份可重現的 FAIL→PASS 證明——拿沒改過的原版跑一次(示範它會沉默地錯、會 crash、會假通過),再拿改過的 fork 跑同一個 case(示範它現在對了),兩份輸出並列,而且要被獨立重跑驗過才算數。FIX_STATUS 這份活的記分板,到現在記著 30 個已證明的 FAIL→PASS 修復,每一列都掛著它的證明。

還有一點我想講清楚,因為它是整個 Vibe-IC 的立場:我補開源,不代表我排斥商業。 這條流程強調的是「它本身是 end-to-end 的」,至於工具——開源也好、商業也好——都能用。如果哪天一家商業 EDA 廠商想把工具插進這個 plugin、成為整條流程的一環,我非常歡迎;使用者付費使用它就好,就跟付費使用平台上一顆 IP 一樣自然。我要的是一條能一路跑通的流程,不是一場工具的站隊。

一個具體的證據:svrfdrc

「開源到底能不能做到簽核級?」與其空談,我給一個我自己跑過、印象最深的證據。

晶圓廠給的簽核 DRC 規則,通常以 SVRF 這種規則格式撰寫,一份動輒好幾萬行。KLayout 的 DRC 引擎本身其實非常強,幾何運算樣樣都有,但它原本不吃 SVRF 語法,所以拿它去跑一份 foundry deck 這條路,本來是斷的。我沒有把「這一步需要別的工具」當成停手的理由,而是在 KLayout 裡自寫了一個獨立的原生 svrfdrc C++ buddy:它直接 parse 一份約 8.7 萬行、224 層、4,533 條規則的真實 foundry SVRF deck,把每一條規則翻成 KLayout DRC 引擎的原生 operation,然後在引擎裡跑。

難處全在語意對齊:SVRF 有很多格式特有的細節,翻錯一個就會 phantom 出成千上萬個假違規,得一條 rule family 一條 rule family 去 root-cause、歸零。最後在這份完整的 foundry deck 上跑到 {'PASS': 4533}0 violation,通過我們自己的一致性驗證,而且是端到端跑在 plugin 的 runner 裡、不是手動湊出來的——完全不需要商業授權

我特別講這一個,不是要證明誰比誰強,而是想說明一件很單純的事:一個獨立的開源引擎,也能把一份完整的 foundry 簽核 deck 從頭跑到底、跑乾淨。 這就是「開源那一段」被補完之後的樣子——它能站上簽核級。

逐塊誠實比一比:哪些追平、哪些還差

把整條流程逐塊拆開之後,我可以誠實地列一張表:每一塊,開源工具「已經追平的部分」和「還差的部分」分別在哪。先把結論放前面——除了先進節點 PDK 那道硬牆之外,大多數差距是投入的差距,不是可能性的差距:工程可補、邏輯可解,不是原理上做不到(這個第一性原理,我在第 3 篇談過,這裡只補上逐工具的實測)。

這張表涵蓋上面那 13 個 fork 裡的 12 個,剛好是流程的兩端:驗證側 6 個(模擬、驗證框架、形式驗證)與後端側 6 個(合成一路到簽核),最後再加上 PDK 那一列;唯一沒列進來的是 magic(GDS streamout 與寄生萃取)。「我們的強化」欄位寫的是我實際改進、且有 FAIL→PASS 證明的東西;每一格後面都跟著「還差」,因為補完一塊不等於追平一塊。

環節 開源工具 對照的商業工具 我的誠實評估 我們的強化
模擬(RTL/閘級) iverilog(+ Verilator) VCS / Xcelium 4-state RTL 與閘級模擬可用;單次模擬的吞吐仍不及商用平行引擎 iverilog fork 補上 SystemVerilog-2012 testbench 覆蓋(nonblocking-event codegen 段錯誤修復、compilation-unit package 排序、forward-declared $dumpvarsbreak;continue;),讓原本為 VCS/Xcelium 寫的 testbench 能在開源模擬器上跑;Verilator fork 則補上 constrained-random 求解($countbits 帶單一非常數控制、power-of-2 base 搭配變數指數),至於多執行緒模擬(--threads)與平行 verilation,是上游本來就有、我們直接消費的能力。還差:事件驅動引擎本質序列(vvp 的 vthread 是協程、不是 OS 平行),大型迴歸的贏面在多次獨立執行的 fan-out,不在單次模擬。
驗證框架 cocotb / cocotb-coverage / pyuvm UVM (SystemVerilog) + 商用 coverage / VIP Python 驗證環境堪用;商用 VIP 生態仍是明顯缺口 cocotb fork 的平行 multi-DUT/multi-seed 迴歸派發;cocotb-coverage fork 的覆蓋率 DB 平行 tree-reduce 合併、constrained-random 求解器可擴展性(串流 + reservoir sampling,O(1) 記憶體均勻抽樣)、coverage rank/merge/closure;pyuvm fork 的 RAL accessors、TLM comparators、sequencer arbitration。還差:覆蓋率資料庫(UCIS/UCDB)對開源生態是 external-by-design;pyuvm 受單一模擬器序列事件迴圈與 GIL 束縛,intra-test 平行不可得。
形式驗證 SymbiYosys (sby) + Yosys formal JasperGold / VC Formal bounded 與 unbounded safety property 可證;liveness 與 X-propagation 仍是真缺口 sby fork 這輪落地多項 formal 能力補強(V18/V19/V23/V24/V26–V28/V30/V38–V42/V46/V49/V50 等,含 package layout 與 version-drift 修正);平行 task/engine 排程上游本來就有,直接用。還差:unbounded liveness 需要容器內沒有的 aiger/aigsmt 引擎家族;formal X-propagation 需要一個還不存在的 yosys dual-rail X-encoding transform pass——這兩個沒解決。
邏輯合成 Yosys Design Compiler 中小規模的合成/映射/等價已可用;超大規模 QoR 仍差 模組級平行合成(fork 自寫的 thread pool)、ABC 面積回收/sizing QoR pass、read_liberty 整合式 clock-gating cell、D-latch→liberty 映射、tri-state fanin 保留。還差:ABC 的模組內核心仍是序列的——本列說的超大規模 QoR 差距就卡在這裡。
靜態時序 OpenSTA PrimeTime 核心時序引擎追平;進階簽核模型(AOCV/POCV)完整度差一截——最接近追平的一塊 fork 補上簽核級 SI 與 timing-ECO 核心:串擾 delta-delay、含 generated/divided clock 的 CRPR/CPPR、POCV/LVF sigma table 讀取(正是本列點名的那塊)。還差:SI-aware delay 目前是獨立指令,還沒摺進 arrival/required 的傳播圖裡。
佈局繞線 OpenROAD Innovus / ICC2 sky130 等級可一路跑到 GDS;超大規模的收斂速度與 QoR 明顯落後 真實寄生下的 post-detail-route 修復(順手修掉原版的 Signal-11 崩潰)、先進節點 DRC 完整度(原版 router 會靜默略過的 LEF58 MIN-STEP MAX-EDGES)、per-net 權重的時序/擁擠驅動 IO pin placement、PDN strap 與 decap sizing 反解並用獨立場解算器把關。還差:超大規模設計的收斂速度與 QoR 仍落後,跟本列的評估一致。
DRC 簽核 KLayout Calibre 引擎已達簽核級;讀 foundry SVRF deck 由自寫的 svrfdrc 補齊 原生 SVRF DRC 引擎與可直接讀 foundry 簽核 deck 的 svrfdrc driver、16 個原生簽核 operation(多重曝光著色、critical-area 分析、CMP 密度梯度、原生 ERC/電壓感知間距、RVE 結果庫);這輪還 root-cause 掉一個 tl::Thread use-after-free:wait() 沒有真的 pthread_join,worker 的 closure 在 OS thread 還在收尾時就被釋放,--threads 下間歇性把 heap 弄壞(ThreadSanitizer 6 個 data race → 0;250+ 次超額訂閱壓測 0 崩潰;報告在不同 thread 數下 byte-identical)。這種 bug 只有真的拿大 deck 跑起來才會現形。
LVS 簽核 Netgen Calibre 修掉沉默假通過後可信;規模化仍需硬化 讓上一欄那句「修掉沉默假通過」成立的,就是這幾個修復:black-box 零對應 pin 防護(black box 不該以 0 個 pin 就 MATCH)、property/tolerance 依 PDK setup 逐元件帶入、short/open 定位、PERC-lite 浮接網路與缺 well-tie 的 ERC。還差:規模化的硬化。
類比環境 ngspice / xschem Spectre / Virtuoso 最大缺口:單次模擬能用,整合設計環境還差很多 AC 頻率掃描的 process 級平行(結果完全一致,8 jobs 約 5.5×)、強化過的 flat-DSPF 寄生讀取器(原版會靜默丟棄格式錯誤的寄生卡,我們改成驗證並拒收)、OpenMP device-eval build、Monte-Carlo/PVT corner fan-out。還差:本列的重點沒有改變——缺的是整合設計環境(xschem 我甚至還沒 fork),不是模擬器本身。
先進節點 PDK sky130 / GF180 / IHP 各家 ≤7nm 硬牆:目前無可量產的開源 ≤7nm,只有預測式 ASAP7 把 ASAP7(ASU/ARM 的 7nm FinFET 預測式 PDK,BSD 授權)與 NanGate45 加進 image,成為一等公民的 enablement。但這沒有推倒那道硬牆:預測式/教學用途,不具流片能力,背後沒有晶圓廠承接;它的作用只是讓整條流程能在 7nm 級的節點上被實際操練一遍。

看完這張表,你會發現一個模式:除了 PDK 那道硬牆,其餘差距幾乎都是「還沒有人把某個 pass 寫上去、某個 corner case 補完、某段 log 好好解析」這一類的事。商業工具領先,很多時候不是因為別人原理上碰不到,而是它把成千上萬個邊角案例,用幾十年不間斷的工程投入,一個一個補完了;開源這邊,只是還缺人力去補。而這正是我樂觀的地方——這種洞,是可以一個一個補起來的,而 AI 正在大幅壓低補洞的成本。

想看即時、逐工具的版本(隨著 fork 補洞而更新),可以看 EDA Forks 頁上「我們的 fork 還做不到什麼」那張表。

老實說,還差哪幾塊

方向我很確定,但今天的成果遠不完善。有幾塊缺口我得誠實講清楚,不然這篇就變成宣傳了:

但要說清楚:這些缺口,絕大多數是「補洞」的工程,而不是原理上的不可能。而過去這段時間,我做的正是這件事——針對這些開源 EDA 工具,對標商用等級,把「能解的差距」用近乎 brute force 的方式一塊一塊補起來。凡是我研究得出補法的落後,幾乎都補上了;剩下的,主要就是上面那道 PDK 硬牆、類比整合環境、以及超大規模的收斂與 QoR。

所以,與其說我要「對抗」商用 EDA,不如說商用 EDA 是我的標竿。我拿它當對照,一步一步追上去;我相信這套開源流程總有一天能追到它、甚至更好。商用 EDA 還有沒有市場?當然有,那塊需求不會消失——至於這些廠商怎麼轉型,不在這篇的範圍。就像 Linux 出現時,並沒有完全取代掉伺服器的市場,也沒有取代 Windows 在 PC 桌面的位置——一個更開放的選項出現,未必是誰取代誰,而更多是把餅做大、讓更多人能上桌。


把 RTL 之後的每一步都接上真工具、再把開源那一段逐段補到簽核級——中後端的收斂,大概就是這一個月最硬、也最踏實的一段工作。而支撐這一切能被信任的,其實是一條更底層的原則:不管是我自己的流程,還是我腳下踩的工具,都不准對我謊報 PASS。 下一篇,我想把這條原則整個攤開來講:為什麼在一個交給 AI 跑的 IC 流程裡,最需要防的從來不是「算不出來」,而是「假裝算出來了」。