模擬過了不代表 FPGA 會動,更不代表 silicon 會動。AI 最危險的不是做錯,而是很有自信地告訴你它做對了。這篇是我踩過的坑,以及我為什麼把誠實變成結構性的東西——沒有真證據,就不准報 PASS。

寫了很多年軟體,我對 AI coding 最怕的一件事,不是它做錯,而是它幾乎永遠會告訴你「成功了」。你叫它寫一段程式、跑一輪測試、修一個 bug,它回你一段工整的總結:「已完成,測試通過。」語氣篤定、格式漂亮。可是你打開 log 一看——測試根本沒跑、或者 exit code 是 0 但裡面全是 error、或者它把該驗證的那一步默默跳過了。
在純軟體世界,這種幻覺式 PASS 雖然討厭,但還活得下去——多跑一次、上 CI、丟到 production,遲早會現形,代價通常是幾分鐘到幾小時。可是對 IC 流程還很陌生的我,幾乎沒花什麼時間就看懂了差別:在晶片設計裡,一個假的 PASS 是會要人命的。 一組光罩動輒是天文數字,一次流片是好幾個月。sim 過了,不代表你的 RTL 上了 FPGA 會動;FPGA 會動,不代表做成 silicon 會動。每往下一層,物理現實就多咬你一口——寄生效應、時序、DRC、LVS。如果 AI 在中間任何一站對我說謊,我可能要到最貴的那一站才發現。
所以我很早就認定:這條流程要能被信任,誠實必須是結構性的,不能是「看模型今天心情好不好」。
Phase 1 是整條流程的入口:把一段自然語言的意圖,攤開成 L1 到 L27 的分層設計 JSON,下游的 RTL、模擬、合成、簽核全都吃這份文件。這一步做不紮實,後面全部是虛的。
我一開始訓練 Phase 1 的產出,分數很好看——一批題目 30/30 全過,我那時還蠻得意的。直到某天我停下來問自己一個很簡單的問題:這 30 分,是誰打的、量的到底是什麼?
答案很難堪。那個 30/30 量的是「格式對不對、欄位有沒有填」,不是「內容有沒有真的把設計講清楚」。它是我自己出題、自己改考卷、還給自己送分。當我換上一套誠實的標準——真的去問「這份 L-doc 能不能讓一個完全不知情的下游把 RTL 寫對」——重新評一遍,分數從 30/30 掉到 0/10。
0/10。不是 3、不是 5,是 0。那是我做這個專案以來最清醒的一次打臉:原來先前所有的「進展」,量的都是虛的東西。
奇妙的是,掉到 0 反而讓我鬆一口氣,因為從那之後每一分都是真的。爬回來只有一個笨辦法:把每一次失敗,都拆成一條程式可以檢查的規則。 產出漏掉介面時序的定義,就在覆蓋度迴圈裡加一條:少了某類必要欄位就直接 FAIL,不准往下走。兩個子模組的 port 命名對不上,就把「port 只在一個 canonical 的地方定義一次、而且先於任何 RTL」變成硬性前置條件。產出「看起來完整」但其實是空殼,就加一條 gate:top-level 必須把所有東西實例化,不准留 stub。Phase 1 是一分一分、一條 gate 一條 gate 疊回來的,每一分背後都有一支跑得動、重現得了的檢查程式。
那次教訓,正是我把一條 doctrine 刻進 plugin 規格描述裡的原因:anti-fabrication——provenance audit-chain、real-artifact + SHA256 attestation、gate self-assertion、canonical-flow compliance、chip-agnostic source guard——no fabrication, no hallucinated PASS。 拆開來講,它有幾條互相咬合的原則:
PASS / PASS_WITH_WAIVERS / FAIL。絕不允許用 LLM 說一句「看起來沒問題」來當作通過。判斷可以是 AI 做的,但裁決一定是程式做的。{"pass": true},下游偷懶的 gate 就讀這個布林值當作通過,等於被告自己當法官。有一支專門的檢查會掃描流程定義,只要哪個 gate 讀的是自己這一步寫的旗標,就 FAIL。一句話:要報成功,先把證據攤在桌上,而且證據要能被一支不信任你的程式獨立驗過。
這些都不是假想。舉一個具體的例子:我在 fork 一個開源 LVS 工具(netgen)時,撞見電晶體屬性根本對不上、它卻回報 Circuits match uniquely 的情況。LVS 的沉默假通過,正是那種會讓一顆版圖跟電路對不起來的晶片一路走到流片的洞——所以它被我修成正確地判定 do NOT match。
第二個坑更嚇人,因為它不是「我不會」,而是「我自己的系統騙了我」。有一段時間我在跑一個 case,連續 36 次 FAIL。我理所當然地以為是 RTL 的問題,一輪一輪去改 RTL、改 testbench,改到懷疑人生,數字動都不動。
直到我停下來,不看被測的設計,改去看負責判定的那套機制本身,才找到真正的病灶。問題根本不在設計,在治理(governance):有一支本該把關的 gate,在它依賴的工具「不存在」的時候,選擇了沉默容忍——工具沒裝、沒跑起來,它不報錯,反而往下放行。於是整條流程在一個「其實根本沒驗證」的狀態下一路往前,最後在別的地方才炸開。我改的那 36 次全改錯了地方,因為系統從一開始回報給我的訊號就是假的。
這就是所謂的 governance hole:一個系統可以在「沒有真正驗證」的情況下,仍然回報通過的縫隙。它比一個普通 bug 危險得多,因為它會系統性地把你指向錯的方向。修法完全符合那條 doctrine:把「沉默容忍」改成「硬性 FAIL」。工具缺席就是 FAIL;harness 要做逐位元組的自我驗證,證明它真的跑了、真的比對了,而不是空手回一個 rc=0。
整件事,可以濃縮成一句話:一個假的 PASS,會偷走你之後幾十輪修錯地方的時間;一個誠實的 FAIL,會直接把你帶到病灶面前。
同一條原則,也解決了 benchmark 一個更微妙的誠實問題。我們公布的分數,衡量的是確定性 runner 這條產品鏈能做到什麼,不是一個裸 LLM 配上同樣的工具、靠一次運氣好的 prompt 能凹出什麼。
以 CVDP 這種外部 benchmark 為例:解題器只准讀 input.prompt 加 input.context,隱藏的測試 harness、cocotb testbench、golden 解答全是禁區 oracle。而這件事不是靠自律,是有一支 regression guard 去證明——帶著 oracle 跑、跟不帶 oracle 跑,emit 出來的位元組完全一樣。 只要偷看會讓輸出改變,這支 guard 就 FAIL。誠實在這裡不是口號,是一個結構不變量。在這個前提下,乾淨的盲測 pass rate 才是誠實收斂出來的——而且每一份結果檔都寫明自己是哪個 image、哪個模型跑的,任何人都能清一台機器、重現同一個數字。
如果這一年只讓我留下一句話,那會是:在一個你不熟、又長又難、還很容易蒙混的領域裡,誠實是唯一能讓你真正前進的東西。 我寧可要 0/10 的真相,也不要 30/30 的自欺——因為那個 0 是可以往上蓋的實地,那個 30 是沙。
這就是為什麼我說誠實是護城河,不是美德。功能誰都能往流程上再疊;難複製的,是一條一條 gate 堆出來、拒絕對你說謊的流程。Vibe-IC 從 v1.0.0 一路走到 v1.4.x、大約 600 個 commit,其中絕大多數都是修掉一整類的假通過——每一個,都是把我踩過的一個坑,變成流程之後再也不會掉進去的規則。人類工程師靠痛過的教訓長記性;這套 plugin 靠一支支 gate 把教訓變成再也不會重犯的規則。這份累積,就是護城河。
紀律講到這裡。下一篇,我想把這條「不准對我謊報 PASS」的原則,一路帶到真實的硬體上——一個跑在 FPGA 板子上、由 AI 自己燒錄 SOF、用相機讀燈號、自己 tune 到收斂的驗證閉環。到那裡你會看到,「信任」不是嘴上說的,而是一台機器去讀真實的結果、再決定要不要重跑。