最近項目上用了不少大驅動的 buffer,signal EM 這項檢查又一直排在很靠后的位置——等它跑出來的時候,離 TO 已經不遠了:一批 buffer 直出的 net,在報告上掛了一長串違例。
這個時間點是最難受的。timing 剛簽完,版圖剛收斂,每一條違例對應的"標準修法"都讓人頭皮發麻:驅動換小?netlist 動了,timing 重簽;插 buffer 分段?重新布局布線,DRC 重來;加寬拉遠?手工改十幾條 net,改完還得祈禱別引入新問題。離 TO 越近,每一步大動作的代價越像是拆東墻補西墻。
所以問題只剩一個:有沒有一種影響足夠小、又確實有效的修法?工具里躺著的 fix_signal_em,聽名字就是干這個的。man page 攏共三行:讀違例、修違例、完事。
一鍵修復,聽著很美。但它到底干什么?是給你換小驅動、插 buffer,還是動線?修完會不會把 timing 搞崩?影響范圍到底多小?問了一圈沒人說得清,文檔也不寫。那就自己拆開看。
先把答案放這:它既不動 netlist,也不動 cell,干的事就一件——把違例的線加寬,然后局部重繞。這正好踩在"影響小"的點上:不改驅動、不動時序路徑上的邏輯,只把幾段線的寬度抬上去。但真正值得說的是后半句:它只修某一類違例,對另一類基本裝死。而這兩類怎么區分,直接決定你拿到違例報告之后該怎么干活。
實驗環境交代一下:一個已經完成布線的小設計(開源的 picorv32,五千多條 net),某 40nm 工藝,工具是我手上的當前版本。EM 規則用原廠格式的 iRCX 文件,-format IRCX 讀進去。順手說一句:讀完規則,花十秒鐘看一眼報告里的 Required 列,有數值才算規則真綁定上了;層名對不上的層會報 SIGEM-006 被靜默忽略。這個小檢查能防住"規則沒吃上、違例假干凈"的烏龍。
規則吃上了,輪到主角登場。
先跑一遍修復前報告:16 條 net、34 個布線段的 PEAK 型違例,全在 M2/M3/M4 上。然后 fix_signal_em,盯 log。
它的動作分三步,log 里寫得明明白白:先對違例段生成一套加寬用的非默認布線規則(NDR,名字就叫 sigem_rule_w1、w2 這樣的),然后調 route_eco 做增量重布線,最后重新分析一遍。全程不碰 netlist——不會把你的 X20 換成 X8,也不插 buffer。迭代一輪就結束。
但第一輪的結果很尷尬:修完再分析,16 條 net 一條沒少,幾何 diff 是零。log 里一行小字暴露了原因:它生成的 NDR"與默認規則等價"——等于沒加寬,白跑一趟。
為什么裝死?注意這批違例的兩個特征:全是 PEAK 型,全部位于頂層端口直連的 net 上。后面四輪對照實驗,就是圍著這兩個特征做的。
那它什么時候真修?我把限值收緊,逼它出手。
端口 net 的 PEAK 違例有個特點:電流是端口理想激勵打出來的(端口給的是標準激勵模型,不是真實 cell 在驅動),跟內部驅動強度無關。我把規則里的 RMS 限值收緊約 4.5 倍,讓 RMS 型違例冒出來,總數漲到 30 條 net、48 個段,再跑 fix_signal_em。
這次它真修了:修完只剩 2 條 net、3 個段。28 條 net 修復成功,route_eco 一共更新了 104 條 net。
拿其中一條 mem_rdata[31] 做修前修后的幾何對比,動作看得清清楚楚:靠近驅動端的 M2/M3/M4 主干,線寬從 0.07 μm 加到 0.14 μm,整整一倍;局部拓撲重繞,多出新的疊孔和一小段 M5 跳線;離驅動端遠的段,一動不動。
![mem_rdata[31] 修前(左)修后(右)整網對比,注意主干位置和新增的過孔](https://static.mianbaoban-assets.eet-china.com/xinyu-images/MBXY-CR-4ff982a913aa3b7eddad588bd8ba77cc.png)
放大到端口附近看,加寬一目了然——左邊修前,右邊修后,黃色 M2、橙色 M3、紫色 M4 全都粗了一倍:

原理就這么樸素:電流密度 = 電流 / 截面積,加寬一倍,限值跟著翻倍,違例消失。它不改電流,只抬限值。
四輪對照實驗,測出了它的邊界。
第一輪已經說了:全是 PEAK 型、全是端口 net,它零動作。第二輪我把活動率拉高 4 倍,想看看能不能逼出更多違例——結果一條新的都沒有。PEAK 電流由驅動強度決定,跟 toggle rate 無關,這條對以后排查很有用:PEAK 違例別去折騰活動率,去查驅動。
第三輪把限值收緊 10 倍,違例還是只長在端口 net 上。第四輪換 AVG 型收緊 50 倍,AVG 違例依然是零——小設計上 AVG 電流比限值低兩個量級,基本不可能違例。第五輪就是上面說的,RMS 收緊,它修了 28 條。
修完后剩下的 2 條 net 值得一看:一條 RMS、一條 PEAK,都在 die 邊緣的端口直連 net 上——這種位置它盡力了也沒全修掉。但更有意思的是對照:修前 16 條帶 PEAK 違例的 net,有 15 條的 PEAK 跟著 RMS 一起被修掉了。所以準確的說法是:工具不是修不了 PEAK,而是不會為純 PEAK 違例啟動修復(第一、三輪,零動作);一旦有 RMS 違例觸發加寬,PEAK 違例大多被順帶清掉。
順帶清掉這事在原理上完全講得通:PEAK 限值和 RMS 一樣,是線寬的線性函數(原廠模型里就是 C1·w/√r 這種形式),報告里違例段的 Required 列會直接告訴你加到多寬能過(我這個實驗里就是 0.07 加到 0.09)。加寬降不了 PEAK 電流本身(電流由驅動強度和波形決定),但 EM 判定是電流對限值,抬限值和降電流是等效的兩條路——一次加寬,整條限值曲線都抬上去了,RMS、PEAK 一起受益。
那純 PEAK 場景它為什么不動手?說實話,我這組數據分不開兩個變量:那批純 PEAK 違例恰好全在 die 邊緣的端口直連 net 上,是 PEAK 類型本身不修,還是端口 net 位置特殊(理想激勵算出來的電流本來就保守,工具可能選擇不碰),不能下定論。能下定論的是現象:它給那批違例生成的 NDR 退化成了默認規則,零動作。另外 block 內部、鎖定的 shape、pin 內部的違例,它會直接標 unfixable,這些要在 block 級處理。
所以回到開頭的問題:你項目里那批大 buffer 的 EM 違例,它能修嗎?
看違例類型。報告里每一行都標了 AVG / RMS / PEAK:
AVG 和 RMS 型,放心交給它。這正是快 TO 時最想要的那類修復:不動 netlist、不動 cell、不把版圖打回重布,只是把幾十段線的寬度抬一檔、局部重繞幾根 via——timing 上的影響就是這幾段線的電容略增,動過哪幾段線、影響多大,都擺得清清楚楚,風險和換驅動、大 ECO 完全不是一個量級。當然修完該做的確認不能省:report_signal_em -violated 復查一遍,timing 快速過一眼,確認沒有新傷。
PEAK 型要分兩種情況看。如果同一條 net 上同時掛著 RMS(或 AVG)違例,不用你操心——修 RMS 的加寬會把 PEAK 限值一起抬上去,PEAK 違例順帶就清了。我第五輪實驗里,16 條帶 PEAK 違例的 net 有 15 條就是這么被捎帶修掉的。
真正麻煩的是純 PEAK 違例:實測這個版本不會為它們啟動修復(NDR 退化成默認規則)。但注意,這不是說加寬對 PEAK 沒用——上面說了,PEAK 限值同樣隨線寬線性漲。這里有個實測有效的變通:把 RMS 限值收緊,讓這批 net 冒出 RMS 違例,修復器就肯動手了——加寬一上,PEAK 限值跟著抬;再配 -nets 定點,只修你點名的 net。我實測指定 2 根全修干凈,同樣掛著違例但沒點名的旁觀網一根線沒動。修完記得換回正式規則,復查一遍 PEAK 確認真過。實在不想折騰規則的,也可以按 Required 列的目標寬度手工建 NDR 再 route_eco(這條我沒實測,用之前先驗證)。真正需要從驅動側下手(壓驅動強度、buffer 分段)的,是加寬沒布線空間、或者差得太多加不滿的情況。
順手把可直接用的命令序列放這,注意前兩步不做,分析根本不生效:
# 1. 開 signal EM(默認是關的!)
set_scenario_status <你的scenario> -signal_em true
# 2. 活動率鋪滿,否則大量 net 被 zero-toggle 跳過
set_switching_activity -static_probability 0.2 -toggle_rate 0.1 [get_nets -hier *]
# 3. 讀規則,iRCX 格式;讀完好先驗證 Required 列
read_signal_em_constraints -format IRCX <原廠規則.ircx>
report_signal_em -nets [get_nets <挑一根 clk>] -verbose
# 4. 修前基線
report_signal_em -violated -verbose
# 5. 修;也可以 -nets 只修指定的 net,層次化結構里很有用
fix_signal_em
# fix_signal_em -nets [get_nets {mem_rdata*}]
# 6. 修后確認
report_signal_em -violated -verbose
三個實操提醒。一是它內部的 route_eco 會清掉 undo 歷史,跑 fix 之前先 save_block 或者把幾何 dump 出來,萬一修砸了能回退,而且修前修后對比也靠這份備份。二是 -nets 只是范圍過濾器,不是強制開關:實測把三條 FC 自己判定無違例的 net 喂進去,log 直接一句"There is no fixable signal EM violations",一根線都不動。所以如果你的違例清單來自 RedHawk 這類 signoff 工具,拿給 FC 修之前,先確認 FC 自己的分析也能看到這些違例——兩邊規則、活動率、corner 沒對齊的話,它是不認賬的。三是 signoff 級的 EM 結論還是以 RedHawk 這類專門工具為準,fix_signal_em 是 in-design 的修復手段,不是簽收依據。
最后留個問題:你們項目的 signal EM 違例,是 AVG/RMS 型多還是 PEAK 型多?如果也是 PEAK 型扎堆,你們是靠什么手段過的評審——按 Required 手工加寬、壓驅動、分段,還是跟 foundry 要壽命模型重新算?評論區聊聊。