本文如果有錯,歡迎留言更正;此外,轉載請標明出處 http://www.cnblogs.com/IClearner/ ,作者:IC_learner
本文的主要內容是講解(約束針對的是邏輯綜合下的約束,而實戰部分則是在DC的拓撲模式下進行):
·環境屬性的約束
·設計規則的約束
·面積的約束
·實戰(部分)環境屬性的約束
1、工作環境屬性約束
輸入/輸出端口及其驅動屬性是設計規格的一部分,工作環境的約束,是對這個規格約束的一部分。
工作環境約束一方面是設置DC的工作環境,也就是DC要從在什么樣的環境下對你的設計進行約束,舉個例子,比如你的芯片要在惡劣的環境中進行工作,DC如果在優質的環境中對你的設計進行約束,你的芯片生產出來,就很有可能工作不了。因此一般就要告訴DC,使用惡劣的模型對設計進行約束。另一方面是為了保證電路的每一條時序路徑延時計算的精確性,特別是輸入/輸出路徑的精確性,單單靠外部的輸入延時和輸出延時的約束是不夠,還要提供設計的環境屬性。
這個約束可以看成是宏觀的、整體的、外在的約束,約束的內容可以從下圖看出:
·設置環境條件(set_operating_conditions):
用於描述制造工藝、工作電壓與溫度(PVT,process,voltage,temperature)這些周圍環境對延時的影響。工藝庫單元通常用“nominal”電壓和溫度來描述其默認的特性,例如:
器件與線網上的延時在條件不同的時候呈線性變換。庫文件中,包含對各種不同條件的具體描述,如slow,fast,typical等,對於芯片工作的最差、最好及典型的具體描述(具體見標准單元庫那一節)。通過設置不同的操作條件,可以覆蓋到各種不同的情況。
如果電路在不同於“nominal”電壓和或溫度的條件下工作,我們需要為設計設置工作條件(Operating Conditions),我們可以用set_operating_conditions命令把工作條件加入到設計上。綜合時,原來按"nominal”環境計算出的單元延遲和連線延遲,將按工作條件作適當的比例調整,如下圖為為延遲與工作條件的關系:
講解完工作環境條件是什么之后,下面就介紹與它有關的常見的命令以及約束。工藝庫中通常指定一個默認的工作條件.我們可以用:report_lib libname命令把廠商提供的所有工作條件列出來。
設置工作條件可用下面命令舉例如下:
set_operating_conditions -max $OPERA_CONDITION -max_library $LIB_NAME
·設置線負載模型(set_wire_load_model):
在計算時序路徑延遲時,除了需要知道門單元延遲外,還需要知道連線的延遲,如下圖所示:
門單元的延遲一般用非線性延遲模型(non-linear delay model)算出。半導體廠商提供的工藝庫中,有兩個二維表格,根據門單元的輸入轉換時間和輸出負載在表中找出門單元的延遲以及其輸出轉換時間。輸出轉換時間又作為下一級電路的輸人轉換時間。門單元的延遲在綜合庫那一節詳細介紹。
連線的延遲目前一般用(連)線負載模型( Wire Load Model,簡稱WLM)估算。WLM是廠商根據多種已經生產出來芯片的統計結果,在同樣的工藝下,計算出在某個設計規模范圍內(例如門數為0~43478.00、門數為43478.00~86956.00,等等)負載扇出為1的連線的平均長度,負載扇出為2的連線的平均長度,負載扇出為3的連線的平均長度等等。WLM是根據連線的扇出進行估算連線的RC寄生參數,一般情況下,由半導體廠商建立。廠商根據已生產出來的其他設計統計出該工藝的連線寄生參數。半導體廠商提供的工藝庫中包括了線負載模型。通常在一個綜合庫里面有多種線負載模型,不同的模型模擬不同規模的的模塊內的線上負載情況(具體見綜合庫描述那一節)。用戶也可以自己創建自己的線負載模型去更精確地模擬設計內的線上負載。連線負載模型的格式如下圖所示(上),具體格式由工藝庫決定(下):
關於線負載模型的更多內容,可以參考綜合庫/工藝庫那一節。
線負載模型為DC提供統計性估算的線網負載信息,隨后DC使用這些線網負載信息,以負載的大小為函數來模擬線上的延時(也就是設置這個約束是用來模擬線延時)。因此設置線負載模型。
如DC遇到連線的扇出大於模型中列出的最大扇出值,它將使用外推斜率(Extrapolation slope)來計算連線的長度。上例格式中,如果連線的扇出為7,而連線負載模型中最大扇出是5,連線的其長度計算如下:
講完線負載模型是什么東西,為什么設置線負載模型約束之后,下面介紹與其相關的命令。
如果要查看工藝庫中的WLM,可以使用命令:report_lib $lib_name,進行綜合時,綜合工具會默認根據設計面積和節點處的負載自動選擇合適的連線負載模型,如果要關掉自動選擇WLM,那么可以使用命令:
set auto_wire_load_selection false
然后手動選擇線負載模型的命令是:
set_wire_load_model -name $WIRE_LOAD_MODEL -library $LIB_NAME
如果連線穿越層次邊界,連接兩個不同的模塊,那么有三種方式對這種跨模塊線連接的類型進行建模,set_wire_load_mode命令用於設置連線負載模型的模式。有三種模式供選擇:top、segment和enclosed。三種模式的示意圖如下所示:
由圖可見, 該設計的頂層設計(top)包括一個子模塊, 該子模塊又包括兩個更小的模塊。 頂層設計對應的連線負載模型為50×50; 子模塊對應的連線負載模型為40×40;更小的兩個模塊對應的負載模型為20×20和30×30。
假設有一個連線貫穿兩個小模塊, 但沒有超出子模塊的范圍。 對於這種連線, 在三種模式下, 所用的連線負載模型是不同的,下面是介紹:
比較悲觀的形式:這時,top為頂層設計,電路的規模比SUB模塊大,連線負載模型最悲觀。在top模式下, 采用top層的連線負載模型, 即50×50;因此,連線的延遲最大。我們一般選用這種方式,命令如下:
set_wire_load_mode top
比較不悲觀方式:用enclosed的方式選擇WLM,該W LM對應的設計完全地包住這條連線,這時DC將選擇SUB模塊對應的連線負載模型。在enclosed模式下, 采用子模塊的連線負載模型, 即40×40;因SUB模塊比較TOP設計小,所以連線的延遲比較短(不悲觀,就是連線延時小)。對應的命令為:
set_wire_load_mode enclosed
在segmented模式下, 位於兩個小模塊中的部分采用這兩個小模塊對應的連線負載模型, 中間部分采用子模塊的連線負載模型。
驅動強度、電容負載這些約束是要經驗的,一方面是對I/O口進行約束,屬於I/O口的約束,為時序約束與時序分析提供了路徑,更是為輸入/輸出路徑延時約束的精確性提供保證;一方面是對I/O口對外的環境進行約束,可以算是屬於環境約束,因此放在這里進行講解。
·設置驅動強度(set_drive與set_driving_cell):
為input或者inout的端口設定驅動。Set_drive以電阻值為計量,0表示最大驅動強度,通常為時鍾端口;而set_driving_cell則以模擬端口驅動的器件形式計量,說明輸入端口是由一個真實的外部單元驅動。
為什么要需要為input或者inout的端口設定驅動?這是因為,對於輸入端,為了精確計算輸入電路的延時時間,DC需要知道到達輸入端口的轉換時間:
在默認情況下,DC假設輸入端口上的外部信號轉換時間是0 ,也就是從上升沿跳變到下降沿或者下降沿跳變到上升沿的時間是0,這是不符合實際情況的。通過設置驅動強度,就告訴DC這個設輸入端口實際上是由一個真實的外部單元驅動的,不是理想的;DC就會計算輸入信號的實際轉換時間,仿佛指定某一個庫單元正在驅動輸入端,下面是輸入端IN1 由FD1的輸出引腳驅動的例子:
對應的約束可以這樣寫:
set_driving_cell -lib_cell FD1 -pin Q [get_potrs IN1]
如果不用開關選項“-pin",DC將使用所找到的第一只引腳(庫中這個單元的第一個引腳,這個驅動引腳貌似是要選擇輸出的引腳)。
此外,除了通過這兩種方式,還可以直接設置輸入端口的轉換時間,如下所示:
set_input_transition 時間 [get_ports 設計對象]
·設置電容負載(set_load與set_load load of):
明確說明端口(輸入或輸出)上的外部電容負載。對於輸出端,為了精確地計算輸出電路的延時時間,DC需要知道輸出單元所驅動的總負載:
默認情況下,DC假設端口上的外部電容負載為0。我們可以指定電容負載為某些常數值,也可以通過用loacl_ of選項明確說明電容負載的值為工藝庫中某一單元引腳的負載(一般是選擇輸入引腳):
跟設計輸入輸出延時一樣,設計者往往並不知道每個模塊輸入端口的外部驅動單元和/或輸出端口的外部輸出負載。因此我們要通過負載預算(Load Budget),為輸入/輸出端口設置環境的約束。產生負載的原則如下:
1.保守起見,假設輸入端口為驅動能力弱的單元驅動(即轉換時間長);
2.限制每一個輸入端口的輸入電容(負載);
3.估算輸出端口的驅動模塊數目。
例如:(只是舉例)對於下面的電路圖:
其規格為:模塊輸入端口驅動的負載不大於10個“AND2”門的輸入引腳的負載,模塊輸出端口最多允許連接3模塊,如果某個輸出端需要連接多於3個模塊,我們要在代碼中復制該輸端口。
對應的約束為:
環境約束舉例如下所示:
語法中,設置(定義變量時),如上面的:
Set ALL_IN_EXCEPT_CLK [remove_from_collection [all_inputs] [get_ports “$CLK_NAME”]]中,后面的remove_from_collection是移除設計物集對象的意思,我們知道,DC可以將設計識別成多個對象,比如輸入端口、輸出端口等等,然后這個就是從all_inputs這個對象集合中,移除掉CLK_NAME這些代表的端口;如果命令之中有命令時,需要用[]來括起來。
然后是expr是表達式求值的意思,因為load_of取出了一個端口的負載值(因為喲load_of這個命令,即命令中有命令,因此需要加[]),這個值*10 是個表達式,因此用expr來指出求值,求值是一個命令,因此用[]括了起來。
上面中,LIB_NAME、WIRE_LOAD_MODEL、DRIVE_CELL 、DRIVE_PIN、OPERA_CONDITION這些變量的內容都不是隨便定義的,需要根據綜合庫書寫,下面進行解釋,庫的具體內容參考綜合庫那一節。
LIB_NAME:庫的名字,這里使用的惡劣的情況:
WIRE_LOAD_MODEL:線負載模型,打開slow.lib這文件,可以找到各種線負載模型:
約束中選的是w150的。
DRIVE_CELL:驅動單元,也就是用來模擬驅動輸入端的驅動單元,這要選擇庫中有的單元,比如反相器:
DRIVE_PIN:驅動管腳,為單元的輸出管腳,也就是“Y”了。
OPERA_CONDITION:這個操作環境也是要填寫庫里面有的:
設置完這些變量之后,還設置了ALL_IN_EXCEPT_CLK和MAX_LOAD變量,其中ALL_IN_EXCEPT_CLK變量代表了除了時鍾之外的輸入管腳。MAX_LOAD變量就表示了最大的負載,代表的是庫中某個單元的輸入負載值。
最后面的就是設置工作環境了。
2、設置設計規則約束
set_max_transition、set_max_fanout、set_max_capacitance
主要是設置最大轉換時間、最大扇出及最大負載電容要求,可以設置在輸入端口、輸出端口以及當前設計。舉個前面的環境約束的例子說,比如我約束了輸入端口的最大轉換時間和負載,也約束輸出最大扇出,如下圖所示:
當綜合和優化了,計算發現輸入端口實際的轉換時間比約束的大,或者負載比約束的大(模塊輸入端口驅動的負載大於10個“AND2”門的輸入引腳的負載),或者檢測到輸出端口的扇出數比約束的要多(模塊輸出端口最多允許連接3模塊,如果某個輸出端需要連接多於3個模塊),這時候就違背了設計規則,DC就會報錯了。
半導體廠商在工藝庫強加了設計規則。這些規則根據電容、轉換時間和扇出(capacitance,transition和fanout)來約束有多少個單元可以相互聯結。設計規則一般由半導體廠商提供,在使用工藝庫中的邏輯單元時對其聯結所強加的限制。例如,如果設計中一個邏輯單元的負載(其驅動的負載)大於庫中給定的其最大負載電容(max_capacitance)值,半導體廠商將不能保證該電路能正常工作。我們只可以按照設計規則的約束或按照更嚴格的設計規則約束來設計電路,而不可以放松約束。Design Compiler在綜合時使用加入緩沖器(buffering)和改變門單元的驅動能力(cell sizing)技術來滿足設計規則的目標。
庫單元的設計規則(design rule)一如下所示:
在約束工作環境的時候,調用了庫中的一些單元(的引腳),就相當間接設置了設計規則約束,我們可以不必設置。
下面我們來詳細敘述一下DC進行綜合時設計規則約束:
DC在做綜合時,把設計規則的優先級設置為最高。優先級的從高到低次序為:最大電容(max_capacitance)、最大轉換時間(max_transition)、最大扇出(max_fanout).
·最大電容(maxcapacitance)的約束,例如對於下面的電路:
對應的最大的電容約束如下:
【1】set DRIVE_PIN TECH_LIB/invla27/Y
【2】set MAX_CAP [get_attribute $DRIVE_PIN max_capacitance]
【3】set CONSERVATIVE_ MAX_CAP [expr $MAX_CAP / 2.0]
【4】set_ max_ capacitance $CONSERVATIVE_ MAX_CAP [get_ports IN1]
約束的意思是:首先【1】處,我們選擇使用綜合庫里面庫單元的一個輸出引腳作為設計中預期驅動器的最大允許電容負載,其值通過【2】得到,假設為3.5pf,也就是MAX_CAP = 3.6pf。然后通過【3】設置約束時使用的最大電容變量,除以2是在驅動器增加一些富余量使DC不會給它加滿載。最后【4】就是設置輸入引腳IN1的最大電容量為CONSERVATIVE_ MAX_CAP,也就是1.8pf。
當設置了輸入端口的負載之后,也就是:
set_load 1.2 [ get_ ports IN1]
那么DC可以給輸入端口 IN1 施加的最大內部負載是:1.8 - 1.2 = .06pf。
我們可以用“set_max_capacitance 3. 0 $ current_design”命令為整個設計中加入最大電容的設計規則。此處,用了3. 0為最大的電容值,設計時我們可以根據工藝庫和電路的具體情況,選用合適的數值。要注意不要施加過度保守的約束,以免嚴重地限制DC對設計的優化。當然,如果庫內定的值不夠恰當或者過於樂觀,我們可以手動設置,以控制設計的裕量。
·最大轉換時間(max_transition)的設計約束,例如前面的電路,可以進行下面的最大轉換時間約束:
#從工藝庫找出設計中預期驅動器的最大允許轉換時間,也就是最大轉換時間可以像這個引腳這么大,假設其值為0.400ns。
set DRIVE_ PIN TECH_ LIB/invla27/Y
set MAX_TRANS [get_attribute $DRIVE_PIN max_transition]
#在實際驅動的時候,增加一些富余量使DC不會給它加滿載,也就是實際上的轉換時間不超過CONSERVATIVE_ MAX_TRANS,也就是0.200ns。
set CONSERVATIVE_ MAX_TRANS [expr $MAX_TRANS / 2.0}]
set_ max_transition $CONSERVATIVE_ MAX_ TRANS [get_ports IN1]
約束之后,DC考慮驅動單元的類型和它的外部負載, DC限制輸入端口IN1的內部負載來滿足的設計規則,也就滿足你這個轉換時間,讓它不超過該0.2ns。
有時候我們可以在整個設計上施加最大轉換時間的設計約束,以幫助防止可能在長連線上出現的慢(長)的轉換時間,從而導致設計中出現特別長的延遲。施加最大轉換時間的設計約束也可以約束單元輸出端的轉換時間以減少其功耗。我們可以用’set_max_transition 0. 4 $ current_design,命令在整個設計中加入最大轉換時間的設計規則。此處,用了0. 4為最大轉換時間值,設計時我們可以根據工藝庫和電路的具體情況,選用合適的數值。要注意不要人為地加緊對整個設計的約束,以免限制DC對設計中真正關鍵器件的適當優化。
·最大扇出(max_fanout)的設計規則的約束,例如對於下面的電路:
用set_max_fanout命令為設計設置最大扇出的設計規則的約束,例如:
set_max_fanout 6 [get_ports IN1]
要注意set_max_fanout命令使用的是扇出負載(fanout_load),而不是絕對的扇出數目。端口的扇出負載之和必須小於最大扇出的設計規則的約束。進行上面的約束之后,DC在綜合時會查看有沒有違反規則,我們也可以自己查看有沒有違反設計規則,用下面命令可以得到單元invla和invla27的扇出負載:
get_attribute TECH_LIB/invla1/A fanout_load --->比如說是0.25
get_attribute TECH_LIB/invla27/A fanout_load --->比如說是3.0
因此就有DC可以在端口IN1連接6/0.25=24個invla1單元,或在端口IN1連接6/3. 00=2個invla27單元。但是對於上面的電路,其IN1端口的扇出負載之和為:
3*fanout_load(invla1/A)+ 2*fanout_load(invla27/A)=(3 x 0.25)+(2x3.0)=6.75
因此,電路違反了最大扇出負載的設計規則約束。
與扇出有關的還有線負載模型,線負載模型根據連線的扇出數目來估算連線電阻和電容值。連線的扇出數目定義為單元輸出引腳與其他單元的輸入引腳之間連接的數目。與連線的扇出數目不同,扇出負載屬性是附加在單元的輸入端口,不同單元可以有不同的扇出負載屬性。
我們可以用如下的命令限制整個設計的扇出負載:set_max_fanout 6 $current_design ,在對FPGA做綜合,常常使用此命令。它也適用於ASIC的綜合,特別是線負載模型和單元的輸入負載不大精確時使用。
一些工藝庫中,某些單元的引腳沒有扇出負載屬性。這時,DC會檢查庫中默認的扇出負載屬性(default_fanout_load) 。如果庫中沒有默認的扇出負載屬性,DC假設其值為“0",即這些單元的引腳不受扇出負載的設計規則約束。我們可以強制使端口的扇出數目為1,即只與一個單元連接,如果庫中單元的扇出負載最小值為1. 0,用下面的命令加上扇出負載的設計規則約束:
set_max_fanout 1.0 [all_inputs]
如果庫中單元的扇出負載最小值不為1. 0,我們需要先找出扇出負載最小的單元(假設為bufla1),計算出其扇出負載值,然后加上扇出負載的設計規則約束:
set SMALL_CELL TECH_LIB/bufla1/A
set SMALL_FOL [get_attribute $SMALL_CELL fanout_load]
#庫中單元的扇出負載最小值為0. 5000
set_max_fanout $SMALL_FOL [all_inputs]
扇出負載值是用來表示單元輸人引腳相對負載的數目,它並不表示真正的電容負載,而是個無量綱的數字。
如果我們所用的所有庫單元扇出負載為“1",那么set_max_fanout 1. 0 [all_inputs]約束將強制所有的輸人端口扇出數目為1,即它們只能與一個單元連接。否則,為了使輸入端口只能與一個單元連接,我們要找出庫中哪一個單元的扇出負載最小,在set_max_ fanout命令中使用這個值來保證在這個端口上只連接一個單元。如果單元上沒有扇出負載屬性並且庫中本身也沒有(默認)預設的扇出負載屬性,那么把它設為1. 0是有意義和效用的。我們也可以在輸出端口上指定扇出負載值。例如,假設一個內部單元驅動幾個其他的單元並且也同時驅動一個輸出端口。我們可以用set_ load命令來指定那個輸出端口的實際電容負載。set_ load命令幫助DC在綜合時遵從驅動單元的最大電容設計規則,但該命令並沒有為驅動單元的扇出提供獨立的約束。在輸出端口使用set_ fanout_ load命令時,我們可以為輸出端口建立額外的預期扇出負載模型,綜合時DC同時也會使內部驅動單元的最大扇出遵守設計規則的要求。
可以使用下面命令report_constraint -all_violators查看是否違反設計規則。
3、面積約束
下面就是進行面積的約束,也就是告訴DC綜合的電路面積要在多少以內。在介紹約束命令之前,先了解一下面積的單位。面積的單位可以是:
·2輸入與非門(2-input-NAND-gate)
·晶體管數目(Transistors)
·平方微米(Square microns)
此外,我們往往看到一個芯片是多少多少門,這多少門的數字就是拿芯片的總面積,除以2輸入與非門的面積得到的數值。用report_lib命令不可顯示面積的單位,我們要詢問半導體廠商面積的單位是什么。
如果不設置面積的約束,Design Compiler將做最小限度的面積優化。設置了面積的約束后,DC將在達到面積約束目標時退出的面積優化。如果設置面積的約束為“0" , DC將為面積做優化直到再繼續優化也不能有大的效果。這時,DC將中止優化。注意,對於很大(如百萬門電路)的設計,如將面積的約束設置為“0" , DC可能要花很長的時間為設計做面積優化。綜合時,運行的時間很長。
在超深亞微米(deep sub-micro)工藝中,一般說來,面積並不是設計的主要目標,對設計的成本影響不大。因此,我們在初次優化時,可以不設置面積的約束。優化后,檢查得到的設計面積,然后將其乘上一個百分數(例如8500),將其結果作為設計的面積約束。再為設計做增量編輯,運行“compile -inc”命令,為面積做較快的優化。這樣做,既可以優化面積,又可以縮短運行時間。
最后我們用set_max_area命令為設計作面積的約束。例如:
set_max_area 10000
當設計不是很大的時候,根據上面的描述,我們就可以使用下面的命令進行面積約束:
set_max_area 0
讓DC做最大的面積優化約束。
4、實戰
由於種種原因,這里只有環境屬性的約束的實戰,其他的約束也可以通過上面的講解和下面的這個實戰進行設計。
首先,我們來看看設計約束規格:
(設計原理圖)
(設計規范)
在前面一節的基本時序約束規范上加上下面的規范:
·DC啟動環境的設置我們根據設計原理圖和設計規范開始進行實踐:
(跟上一節一樣,這里不再重復)
·約束文件的編寫
基本的時序路徑約束和上一節一樣,不進行改動,下面進行工作環境的約束:
-->輸入端口的驅動設置:
1.要我們使用庫里面的bufbd1來驅動除了clk和Cin*之外的所有輸入端口:
這里是直接使用庫里面的單元來驅動的,根據前面的講解,我們很容易得到約束的命令為:
set_driving_cell -lib_cell bufbd1 -library cb13fs120_tsmc_max [remove_from_collection [all_inputs] [get_ports "clk Cin*"]]
(命令的格式為)set_driving_cell -lib_cell 單元的名字 -library 單元所在庫的名字 要設置約束的對象
注意:當一條命令太長,要進行分割時,使用反斜杠\作為分隔符,且反斜杠后面不能加空格。
2.Cin*是芯片級的端口,需要加上120ps的最大轉化時間,這是直接設置轉換時間,因此可以這樣約束:
set_input_transition 0.12 [get_ports Cin*]
-->輸出負載的約束:
1.除了cout輸出,其它輸出驅動值都是庫單元bufbd7的引腳I負載值的兩倍,也就是用單元的端口進行約束,因此有:
set_load [expr 2 * {[load_of cb13fs120_tsmc_max/bufbd7/I]}] [get_ports out*]
2.cout驅動最大值為25pf的負載,因此可以這樣設置:
set_load 0.025 [get_ports Cout*]
-->操作環境的設置:
由於用到了庫里面的單元,我們還在最好設置一下操作環境,雖然DC可以從啟動環境里面找到單元所在的位置庫,但是我也要設置操作環境,如下所示:
set_operating_conditions -max cb13fs120_tsmc_max
下面的步驟跟前面的一樣,這里就不展開描述了:
·啟動DC,設計讀入前的檢查
·讀入設計和檢查設計
·執行約束和檢查約束
·進行綜合
...