???????本文我們著重討論使用Design Compiler綜合大型設計時要注意的一些問題,比如怎樣調整綜合方法,出現約束違反后怎樣修正,怎樣給不同的子模塊作時序和負載預算,以及給整個設計在具體綜合之前先作一個預估(Design Exploration)等等。
一、編譯一個大型設計
????????對于一個大型設計而言,由于模塊規模的擴大,編譯時間也相應的變長,要長達幾個小時甚至超過一天,這樣的時間對于講究”Time to market”的設計者是比較重要的。因此就更加注重編譯的技巧,本節我們主要討論下面三個方面的技巧——
- 編譯層次化設計的技巧
- 第二次(Second-pass)編譯技巧
- characterize
1、層次化編譯
????????對一個大型設計來講,有兩種層次化編譯技巧——自上而下(Top-down)以及自下而上(Bottom-up)。自上而下的方法是指將整個設計一次性讀入,施加頂層約束后直接進行編譯;自下而上的方法則先一個個編譯比較底層的子模塊,給它們加入時序和負載預算,然后在頂層將各個子模塊整合起來。
1)自上而下(Top-down)
????????上圖是自上而下編譯方法的具體步驟,可以看出假如頂層設計是RISC_CORE這個模塊,則先直接將它讀入,然后處理多次例化的模塊,施加頂層約束后就直接編譯。它的代碼基本上如下所示?
????????自上而下的編譯方法有一個明顯的優點,即它使得設計者無需考慮各個子模塊之間的依賴關系,也就不需要制定子模塊之間的時序和負載預算,這一切都由Design Compiler自動考慮。另外,使用這種方法也使得設計者編寫腳本變得簡單,維護起來也比較方便。?
????????在介紹自上而下的編譯方法的時候,我們還要順便提及DC編譯的一種模式——Simple Compile Mode(簡單編譯模式)。這種模式在設計沒有嚴格的約束的情況下能取得較快的編譯速度,另外多例化模塊的處理也自動進行。下面是RISC_CORE的Simple Compile Mode腳本:
????????可見,使用這種模式省去了uniquify這句,同時編譯之前要先設置一個變量set_simple_comile_mod。?
2)自下而上(Bottom-Up)
????????自下而上的編譯方法其步驟如下圖所示????????
????????和前一種方法不同,自下而上的編譯方法需要先單獨編譯各個子模塊,在編譯子模塊的同時要考慮到與其它模塊之間的關系,看是否滿足約束,然后再讀入頂層文件,施加頂層約束,頂層編譯完成之后還必須看頂層約束是否滿足。下面是單個模塊編譯的腳本:
????????下面是頂層模塊編譯腳本:
?????????從上面的過程不難看出Bottom-Up方法的一些特點:
????????優點是利用了”分而治之”的策略,這對于大型的不可能一次編譯的設計是十分有用的;另外它也擺脫了Top-down方法的對工作站硬件條件的限制,使得大型設計也能在一般的機器上編譯完成。
????????缺點是實現步驟比較多,尤其對各個模塊之間的時序和負載預算要求很高,如果不注意會很容易造成違反。
????????綜合上述兩種方法,我們可以做一個小結:對于規模不算太大的設計,我們推薦使用Top-down的編譯方法,這樣可以在不長的時間內得到滿意的結果。對于其他需要Bottom-Up的設計,我們必須確認時序負載預算能很好的反映實際的工作情況。
2、第二次(Second-pass)編譯
?????????第二階段(Second-Pass)編譯是指當第一階段(First-Pass)編譯出現違反之后,分析違反原因從而重新編譯的過程,對應的還有第零(Zero-Pass)階段編譯。
????????關于第二階段編譯,前面的編譯策略中有比較詳細的介紹,上一節介紹的Top-down的第二階段編譯的步驟主要有
- 檢查模塊劃分
- 檢查約束腳本
- 用更高的map_effort編譯——compile –inc –map_effort high
????????這一節中,我們主要討論用Bottom-Up方法編譯后出現違反的情況
1)重新編譯頂層模塊
????????這種方法是在Bottom-Up出現頂層模塊時序違反的情況下采用的,具體的命令如下:
dc_shell > compile? -top
????????這個命令僅僅修正頂層子模塊之間的路徑,因此速度會比compile –inc更快。
2)修正設計預算(Design Budget)
????????設計預算對于Bottom-Up的方法來說是至關重要的,在預算的時候,我們都盡量能收緊(Tighten)每一個子模塊時序、負載和驅動的預算,例如我們在最初介紹設計預算的時候,舉的例子是給本模塊留整條路徑的40%,因此模塊之間能夠空出20%的裕量。在編譯子模塊的時候能盡量做到滿足預算的要求。這樣最后整合頂層設計的時候就不會出現大的問題。
????????如果出現問題了,一個方法就是調整預算腳本。看看施加的約束是否與綜合后的電路相吻合。下一節,我們將介紹調整設計預算的一個很有用的命令——characterize。
3、characterize
????????Characterize這個命令用于映射到門級的子模塊,作用是計算出該子模塊周圍的環境(延時、負載和驅動),并將得到的實際值作為該子模塊的新的約束。如下圖一個例子
????????由于整個設計已經映射到了門級,因此這個例子可以計算出子模塊U2周圍的輸入輸出延時、輸入驅動和輸出負載的實際值。然后將這些實際值施加在U2模塊中,作為U2的新的約束。這種方法有點類似于給U2的周圍照了一張照片。U2施加了新的約束之后,就可以在這個基礎上做一次高級別的編譯。
????????通過write_script命令,我們可以看到characterize之后到底照下了哪些信息
????????characterize給我們提供了一種比較好的第二次編譯的方法,加入一個子模塊所占的延時很重,就可以在保持其他模塊不動的情況下將這個子模塊重新編譯一次,當然重新編譯可以從HDL代碼開始,下面是一個例子:
????????這個例子和前一個例子的不同在于,它沒用compile –inc high,而是直接將它從內存中刪除,讀入它的源文件重新編譯,這樣可以取得較上一種方法更好的結果。
????????characterize無疑向我們提供一種較好的子模塊二次編譯方法,但是同時它也有一定的局限性,在使用的時候務必要注意——
- 它要求所有的模塊必須映射到門級,這是使用characterize的一個前提。
- characterize只能一次對一個子模塊使用,即給U2作characterize的時候U1和U3模塊必須保持不變,否則U2得到的環境就不是確定的值。
- characterize將外界環境直接作為它的約束,這使得它和其他的子模塊之間不存在任何裕量(margin),這些裕量全部被該子模塊吸收。
二、設計預估
????????設計預估(Design Exploration)是指在整個設計的RTL代碼尚處在驗證的階段就對設計進行預先綜合的過程,在這一節里,我們將討論相比瀑布式的設計流程,設計預估的優點以及設計預估的流程,這些內容可能更多的不是介紹Design Compiler的使用,而是設計方法學問題。
1、為什么要設計預估
????????
????????上圖左邊是一個傳統的設計流程,這個流程先作HDL代碼的編寫,在代碼仿真通過之后作設計綜合,然后插入掃描單元,通過以后作后端的物理設計,直到最后交給Foundry流片。這種流程之所以稱為瀑布式的是因為后面的步驟都必須等前一個步驟完成之后才能進行。
????????稍加分析,不難發現這種流程有很大的危險性,從上圖的右半部分可以看到,從綜合到后端設計,每一個步驟都不可能不產生錯誤,如綜合的時候碰到RTL代碼引起的時序違反,加入掃描單元后發現測試覆蓋率很低,后端布線由于過于擁擠而布不通,等等。這些錯誤如果可以通過工具的技巧修復還好,如果不能修復,就必須要返回到前面的步驟直至RTL代碼的修改,這樣做的代價是隨著從前到后迅速增加的 。
????????因此,要提高設計的效率,就必須在很早的情況下就發現問題并解決它,越是拖到后面,則越不劃算。最理想的情況就是在編寫RTL代碼的時候就萬無一失,并且在這個時候就能估算出最后的芯片面積和運行速度,以及內部長線的延時。這種思想就要進行設計預估的初衷。
????????下面是引入設計預估之后的設計流程圖
????????在這個流程中,前端邏輯設計與后端物理設計同時進行,在編寫code的同時,對芯片的初步布局和布線先作一個規劃,然后檢查工藝庫中提供的連線負載模型(WLM),根據實際需要創建新的負載模型。而code在仿真的同時也可以作一個設計規劃,在設計規劃的時候調用新的WLM,以便得出更加真實的結果。
????????在設計預估做完,code仿真完成之后,就可以正式編譯設計的主要模塊,并將它們整合到頂層模塊中去。同時對這些模塊進行布局重新創建更加真實的WLM,直到最后的分析直至流片。
????????可以看到這個流程是一個前端與后端同時進行的過程,也是一個不斷融合的過程。前端的設計者總是想盡早知道模塊在實際的芯片中的位置,以便得到準確的WLM。這樣才能盡量把錯誤提前找出來,避免留到后面的高成本。
2、設計預估的目標
????????在上面的這個流程中,設計預估是與code的功能驗證平行進行的,而不是等到功能驗證完成后再作。每當code的改動足以影響系統性能的時候,我們都需要進行一次設計預估。
????????一般說來,設計預估有下面幾個目標——
- 驗證代碼的可綜合性:這是設計預估的一個基本功能,不能綜合的代碼對后面的一切步驟都只能是空談。
- 控制代碼的時序違反在一定的范圍(10-15%):預估后的網表的時序違反如果超過這個范圍就可以即使更改代碼,保證在正式綜合的時候能通過調整綜合參數達到時序要求,而不再該代碼。
- 驗證施加的約束的真實性和充分性:設計約束不是設計者憑空想象出來的,他需要通過多次的設計預估,并對得到的網表進行分析,從而對施加的約束不斷修正,讓他能足夠反映真實情況,并且不漏掉容易忽視的約束條件。
- 鑒別時序的特殊情況:大型設計中難免會有一些DC不能綜合或者無需綜合的路徑,設計預估需要把這些路徑找到。
- 鑒別模塊劃分問題:模塊劃分可以在編寫code的時候進行,也可以在DC的約束腳本中用group/ungroup完成,設計預估需要得到一個較好的設計劃分。
- 鑒別測試問題:測試問題我們再DFT課程中詳細介紹。
- 保證WLM的合理:WLM是DC處理連線延時的依據之一,合理的WLM可以保證時序準確性。
3、設計預估的流程
????????上面的設計預估流程可以看出設計預估包括——讀入HDL代碼,施加約束,加入掃描鏈,分析綜合結果,根據初始化布局和創建的新WLM分析時序等等。每當其中一個步驟出現大的錯誤,都需要修改代碼。?