設計流程裡產出的東西,最後要落成哪一種資料。 我的第一次在做的時候其實是塞進資料庫裡 (sqlite)。這邊聽起來合理,但卻會遇到那種被 argu 說要證明我 DB 裡的資料跟他 local 是同源的,也就是得自證在寫進資料庫的這一動做,是真的拿 designer 手上跑出來的結果寫進去的,實際上很多跑 APR 的情況都是自己跑自己的,他們的版本結果可能隨時都在變,如果看到一些當下不符合他們預期的,第一個就會怪罪到這個區塊來,更有甚者會直接質疑產生資料的程式
說白了,就都是人的問題,所以乾脆把資料吐出來,隨時都可以核對
這就是為什麼我寧可用一份份 JSON 當儲存,而不是用資料庫。EDA 工具的命令列幾乎只認得 TCL,所以我們會先在工具裡用 dict 先把要的資料先裝滿,再轉成 JSON 拿去上傳
跑完 PV DRC 個數是 12。網頁上寫 12。主管問:你確定?面對這種題目你需要的不是一個很會查詢的倉庫,而是一條短到能當面走完的對帳路徑,搞不好有人會在本地偷偷重跑忘記上傳,又或是東改西改不按照正常 flow 走:這時候你只需要打開這次上傳的那份資料看一下路徑,然後貼給你主管就能解釋這些事情的原因了
SQLite 很擅長處理後面那種資料很多、條件複雜的處理。但不擅長解決這種問題。一個 .db 檔用普通編輯器打開來看起來是亂碼。要對,你得會連進去、記表名、寫一查詢 (你大概率沒法在那個環境裡輕鬆的搞個 sql 的 viewer)、還要確定自己看的是資料是源自於某一 Run,這不是團隊裡的每個人都能做到的事
JSON 它就是一份人眼看得懂的文字檔。有疑慮,打開來對。跟報告有疑慮,搜同一個欄位名。我感覺對設計團隊來講, 0 技術門檻且能馬上對,比好用跟很會查更重要許多
JSON 被選上,不是因為它是網頁圈的流行格式,而是它剛好同時做到三件我在乎的事。
有疑慮,可以馬上對。 它是純文字,縮排之後層次就是層次。DRC、urate 的 DESIGN、SignOff 某一項的 status 等等。工程師不必先學查詢,只要會搜尋就好
同一份形狀,可以做很多事、接到很多應用。 瀏覽器原生就懂它,所以網頁不必再發明一套讀檔格式。Python、腳本、各種小工具也懂它,所以同一份上傳檔可以拿去畫頁、拿去做檢查、拿去產摘要、拿去跟另一份做交叉比對。之後的 QC、報告連動、Waive,都還是在消費這份形狀,而不是各自再轉一次。換句話說,JSON 不是「給網頁用的暫存」,而是 流程與畫面共用的中立貨櫃。貨櫃標準一訂,後面要接什麼應用,都是拆箱,不是再造輪子。
改資料,網頁可以立刻再畫一次。 沒有表結構遷移,沒有寫入儀式。新的一次 run 就是新的一份檔;改了一個數字要驗畫面,就是改檔、刷新。檔案一換,下一次載入就是新世界,對核對中的人,這種樸素很有用:你知道自己改的就是網頁吃的那一份。
JSON 當然也有代價。它沒有真正的型別約束,數字可能變成字串,缺欄位也不會在寫入時被擋。檔一多、單一檔一肥,全部一起掃會慢。不適合很多人同時改同一筆 (但我們沒這個困擾)。我們本來就以一次 run 一份檔為單位,本來就用刷新換即時。
我們要的結果是活在 Innovus、ICC、PrimeTime 這類工具裡。這些工具對外的命令語言,主軸幾乎都是 TCL。實作現場的自動化 script 也都長在這上面:設定、屬性、檢查、倒報告,入口幾乎都是 .tcl。你不能假設工具會幫你內建一份漂亮的 JSON 匯出,要在別的語言裡遙控,往往還是繞回「生一段 TCL 再送進去」。
流程大概是這樣子:
EDA 工具(只好好聽 TCL)
│ 用命令把數字、狀態、檢查項取出來
▼
TCL dict
│ 走完一次 run,整箱轉成文字
▼
JSON 檔(可以對、可以傳、可以給網頁立刻畫)
│
▼
上傳 → 大廳讀到 → 畫面更新
因為抽資料不是一次做完。流程前段可能先拿到設計名稱,中段才有利用,結尾才有 DRC 與 QA。你需要一個 在 TCL 裡就存在的巢狀容器,讓不同階段往同一個地方塞,最後才一次倒出來。
TCL 有很多語法,但我們用得到的其實很少。先記住一句話:在 TCL 裡,幾乎什麼都是字串。 數字 12 和文字 12 常常是同一種東西,真正的型別要等到翻譯成 JSON 時再收乾淨。剩下只要會兩種容器:list 與 dict。
list 是有順序的一排。適合「很多個同層的名字」,例如一串檢查項、一串 block。
set checks {drc urate qa}
llength $checks ;# 3
lindex $checks 0 ;# drc
lappend checks timing ;# 接到後面
dict 是鍵對值,值還可以再是 dict。這就是我們說的那只箱子。TCL 8.5 之後是內建命令,不必外掛。
# 空箱子,再一層一層塞
set box [dict create]
dict set box meta project SM8466
dict set box meta block ss_ep_top
dict set box item drc all 12
# 取出來對帳
dict get $box item drc all ;# 12
dict exists $box item urate ;# 0,還沒抽
# 子樹也可以整段換
dict set box item stage_qa status PASS
dict set 的中間那些字就是路徑:item → drc → all。這跟 JSON 物件的層級幾乎同一張圖,所以最後翻譯才走得直。流程哪一段拿得到哪一段,就 dict set 進對應的鍵;缺的鍵不要先填零,讓「沒有這個鍵」本身代表還沒抽。
日常大概這幾個就夠:dict create、dict set、dict get、dict exists。
箱子的分層,最好一開始就接近你最後想給人看的分層
這次 run 的箱子
├─ 是誰 專案、block、階段、版本、誰跑的、什麼時候
├─ 設計資訊 製程、利用率、單元密度……
├─ 指標 DRC、繞線繞路、VT 分佈……
└─ 檢查 SignOff 的每一項:狀態、數值、準則
箱子只帶走要被問、要被畫、要被對的那一層。工作目錄、暫時檔、報告原文,出門就變噪音。能在 dict 裡先把關鍵鍵印出來跟報告對的,不要拖到網頁上才對。
TCL dict 很適合活在工具裡,不適合當網站與其他應用的共同語言。最後一棒是 把 dict 轉成 JSON 文字,寫成一份檔,再上傳
流程往 dict 裡累積 → 對過關鍵欄位 → 譯成 JSON → 上傳 → 刷新就能看
沒有第四個帳本。網頁上看見怪數字,對帳順序固定:網頁 ← JSON ← dict 當時的鍵 ← 工具命令。哪一層斷了,就修哪一層。
倒出來的層級應該還認得出來——還是同樣的鍵。網頁不必知道這份檔是哪家工具產的。 工具可以換,箱子的分層不要跟著換。 之後加利用率、加父親是誰,都是在箱子裡加鍵,而不是另開一種檔。能進 dict 的關係,就不要只靠人腦。