????????Design Compiler是一個約束驅動(constrain-driven)的綜合工具,它的結果是與設計者施加的約束條件密切相關的。在本文里,我們主要討論怎樣給電路施加約束條件,這些約束主要包括——時序和面積約束、電路的環境屬性、時序和負載在不同模塊之間的分配以及時序分析。
一、時序和面積
????????上圖是RTL模塊的綜合示意圖,可以看出在RTL代碼仿真通過以后,就開始將它進行綜合,綜合時需要對他加入約束和設計屬性的信息,DC根據這些約束將RTL模塊綜合成門級網表,然后分析綜合出的網表是否滿足約束條件,如果不滿足就要修改約束條件,甚至重寫RTL代碼。值得注意的是,上面提到的僅僅是RTL模塊的綜合過程,而不是整個芯片的綜合,整個芯片是由很多這樣的模塊組成的,它的綜合過程與上圖描述的過程有一定的區別,具體我們將在后面進行討論。?
1、定義面積約束
????????因為芯片面積直接關系到芯片的成本,面積越大,成本越高,因此,集成電路的設計總是希望面積盡量小,以減小芯片成本。定義面積約束是通過set_max_area命令來完成的,比如:
dc_shell > current_design PRGRM_CNT_TOP
dc_shell > set_max_area 100
????????上面的例子給PRGRM_CNT_TOP的設計施加了一個最大面積100單位的約束。100的具體單位是由Foundry規定的,定義這個單位有三種可能的標準:
- 一種是將一個二輸入與非門的大小作為單位1;
- 第二種是以晶體管的數目規定單位;
- 第三種則是根據實際的面積(平方微米等等)。
????????至于設計者具體用的是哪種單位,可以通過下面的一個小技巧得到——即先綜合一個二輸入與非門,用report_area看他的面積是多少,如果是1,則是按照第一種標準定義的;如果是4,則是第二種標準;如果是其他的值,則為第三種標準。
2、同步設計的特點
????????同步時序電路是DC綜合的前提,因此這里有必要先討論一下同步時序電路的特點及目標。這里所討論的同步時序電路的特點是——電路中的信號從一個受時鐘控制的寄存器觸發,到達另一個受時鐘控制的寄存器。而我們要達到的目標是——約束電路中所有的時序路徑,這些時序路徑可以分為三類:輸入到寄存器的路徑 、寄存器到寄存器之間的路徑以及寄存器到輸出的路徑。他們分別對應與下圖所示的標號為N、X和S的電路。
????????假設在上面的電路中,我們要控制觸發器FF2到FF3之間的時序,即X電路的延時,那要通過什么方式讓DC知道呢?顯然一個直觀的辦法就是定義系統的時鐘Clk,如果我們定義好了Clk的周期,那么DC會自動的盡量保證從FF2觸發的信號能在一個周期內到達FF3寄存器。假如周期是10ns,FF3觸發器的建立時間(setup time)是1ns,那么留給X電路的延時最大只能有10-1=9ns。
3、定義時鐘
????????在電路綜合的過程中,所有時序電路以及組合電路的優化都是以時鐘為基準來計算路徑延遲的,因此,一般都要在綜合的時候指定時鐘,作為估計路徑延遲的基準。定義時鐘的時候我們必須定義它的時鐘源(Clock source),時鐘源可以是端口也可以是管腳;另外還必須定義時鐘的周期。另外有一些可選項,比如占空比(Duty Cycle)、時鐘偏差(Clock Skew)和時鐘名字(Clock Name)。定義時鐘采用一個語句create_clock完成——
dc_shell > create_clock -period 10 [get_ports? Clk]
dc_shell > set_dont_touch_network??[get_ports? Clk]
????????第一句定義了一個周期為10ns的時鐘①,它的時鐘源是一個稱為Clk的端口。
????????第二句對所有定義的時鐘網絡設置為don’t_touch,即綜合的時候不對Clk信號優化。如果不加這句,DC會根據Clk的負載自動對他產生Buffer,而在實際的電路設計中,時鐘樹(Clock Tree)的綜合有自己特別的方法,它需要考慮到實際布線后的物理信息,所以DC不需要在這里對它進行處理,就算處理了也不會符合要求。
4、約束輸入路徑
????????
????????從上圖可以看出,我們所要定義的輸入延時是指被綜合模塊外的寄存器觸發的信號在到達被綜合模塊之前經過的延時,在上圖中就是外圍觸發器的clk-q的延時加上M電路的延時。當確定這段延時之后,被綜合模塊內部的電路延時的范圍也可以確定下來了。加入時鐘周期是20ns,輸入延時是4ns,內部觸發器的建立時間為1.0ns,那么就可以推斷出要使電路正常工作,N電路的延時最大不能超過20-4-1.0=15.0ns。
????????設置輸入延時是通過DC的set_input_delay命令完成的——?
dc_shell > set_input_delay -max 4 -clock Clk??[get_ports A]
????????如上面的語句指出了被綜合模塊的端口A的最大輸入延時為4ns。-max選項是指明目前設置的是輸入的最大延遲,為了滿足時序單元建立時間(setup time)的要求。另外還有一個選項是-min,它是針對保持時間的約束使用的。-clk是指出這個端口受哪個時鐘周期的約束。
5、約束輸出路徑
????????上圖中,信號在被綜合模塊的觸發器U3里觸發,被外圍的一個觸發器接收。對外圍電路而言,它有一個T電路延時和外圍觸發器的建立時間。當確定了他們的延時之后,被綜合模塊內部的輸出路徑延時范圍也就確定下來了。假如,時鐘周期20ns,輸出延時5.4ns,U3觸發器的clk-q延時為1.0ns,那么輸入路徑S的最大延時就是20-5.4-1.0=13.6ns。
????????設置輸入延時是通過DC的set_output_delay命令完成的——
?dc_shell > set_output_delay -max 5.4 -clock Clk??[get_ports B]
????????上面的語句指出了被綜合模塊的輸出端口B的最大輸出延時為5.4ns。-max選項是指明目前設置的是輸入的最大延遲;-clk是指出這個端口受哪個時鐘周期的約束。
????????至此,模塊的面積、時鐘、輸入輸出延時都施加了相應的約束。在施加了這些約束之后,可以使用下面的幾個命令檢查約束是否施加成功——
- report_port –verbose 報告在當前設計中所有的輸入輸出端口屬性和施加的約束值
- report_clock 報告當前設計中定義的時鐘及其屬性情況
- reset_design 刪除當前設計中所有的屬性值和約束(通常用在約束腳本的第一句)
- list_libs 列出內存中所有可用的庫
二、環境屬性
????????在上一節中,我們主要討論了怎樣電路中加入時序約束,如設置clock周期、設置輸入輸出延時等,但是僅僅靠這些約束還是不夠的。因為還要考慮到被綜合模塊周圍環境的變化,舉個例子說,如果當外界的溫度變化,或者電路的供電電壓發生變化時,延時會相應的改變,所以這些方面也是必須考慮到的。類似的上一節僅僅約束了輸入輸出的延時,而沒有考慮到他們的電平轉化時間(transition time),這些是有輸入輸出的外圍電路的驅動能力和負載大小決定的。另外,電路內部的互連線的延時也沒有估計在內。這一節我們主要討論怎樣給電路施加這些環境屬性。
1、設置輸出負載
????????為了更加準確的估計模塊輸出的時序,除了知道它的輸出延時之外還要知道輸出所接電路的負載情況,如果輸出負載過大會加大電路的transition time,影響時序特性。另外,由于DC默認輸出負載為0,即相當于不接負載的情況,這樣綜合出來的電路時序顯然過于樂觀,不能反映實際工作情況。
????????設置輸出負載是通過DC的set_load命令完成的。該命令有兩種用法,一種是直接給端口賦一個具體的值,另外則結合另一個命令load_of指出它的負載相當于工藝庫中的哪個單元的負載值。
????????例如下圖,給OUT1端口設了一個負載為5的值。這里的單位也是由Foundry提供,具體的單位,可以通過report_lib命令查看,一般而言是pf。
? ? ? ? 采用第二種方法從下圖中可以看出,第一條語句說明OUT1端口接的負載值是my_lib中and2a0單元的A管腳的負載值。第二條語句則多用了TCL語言的表達式的語法,它說的是,OUT1相當于接了三個inv1a0單元的A管腳的負載值。一般后面的這種方法用的多些。
2、設置輸入驅動
????????與設置輸出負載類似,為了更加準確的估計模塊輸入的時序,我們同樣需要知道輸入端口所接單元的驅動能力。在默認的情況下,DC認為驅動輸入的單元的驅動能力為無窮大,也就是說,transition time為0。
????????設置輸入驅動是通過DC的set_driving_cell命令完成的。set_driving_cell是指定使用庫中的某一個單元來驅動輸入端口。該命令是在輸入端口之前假想一個驅動單元,然后按照該單元的輸出電阻來計算transition time,從而計算輸入端口到門單元電路的延遲。
?dc_shell > set_driving_cell -lib_cell and2a0 [get_ports IN1]
3、設置工作條件
????????工作條件包括三方面的內容——溫度、電壓以及工藝。在Foundry提供的工藝庫里,它的各個單元的延時是在一個“標準”(nominal)條件下得到的,比如說溫度25.0度、工藝參數1.0和工作電壓1.8V。一旦工作條件發生了改變,電路的時序特性也必將收到影響,以上三方面的因素對電路時序的影響如下所示:
在較為先進的工藝中,會出現溫度翻轉效應,即低溫反而導致delay更大,所以在使用庫的時候,要詳細閱讀庫的說明。
????????從圖中可以看出,單元的延時會隨著溫度的上升而增加;隨著電壓的上升而減小;隨著工藝尺寸的增大而增大。以上的這些工作條件的變化,Foundry在建庫的時候已經考慮到了,因此它在工藝庫中提供了幾種工作條件的模型(operating condition model)以供設計者選擇。這些工作條件一般分為三種:最好情況(best case)、典型情況(typical case)以及最差情況(worst case)。我們為了以后能使電路正常的工作在上面的三種情況下,在綜合的時候就必需要將他們考慮進來。一般綜合只要考慮到最差和最好兩種情況,最差情況用于作基于建立時間(setup time)的時序分析,最好情況用于作基于保持時間(hold time)的時序分析。
????????在默認情況下,Design Compiler不會自動指定工作條件,我們可以先通過report_lib命令來列出在當前的工藝庫里提供了哪幾種工作條件——
????????然后指定需要用到的工作條件,在做建立時間分析的時候需要用到最差情況的條件:
?dc_shell > set_operating_conditions -max "slow_125_1.62"
????????如果我們既要分析建立時間,又要分析保持時間那么就要同時指定最差和最好情況:
dc_shell > set_min_library?core_slow.db -min_version core_fast.db
dc_shell > set_operating_conditions -max "slow_125_1.62" -min "fast_0_1.98"
????????其中core_slow.db和core_fast.db分別是最差和最好條件下的工藝庫文件,第一句話先用set_min_library設定作保持時間檢查的庫,第二句話則分別對應了兩種時間檢查需要用到的工作條件。
4、設置連線負載模型
????????在DC綜合的過程中,連線延時是通過設置連線負載模型(wire load model)確定的。連線負載模型基于連線的扇出,估計它的電阻電容等寄生參數,它是也是由Foundry提供的。Foundry根據其他用這個工藝流片的芯片的連線延時進行統計,從而得到這個值。
????????下面是一個負載模型的例子
?????????這個例子可以通過命令report_lib得到,它是ssc_core_slow這個工作條件下的一個名為160KGATES的負載模型。其中時間單位為1ns,電容負載單位為1pf,電阻單位為1kΩ。從圖中可以看出單位長度的電阻以及電容值,DC在估算連線延時時,會先算出連線的扇出,然后根據扇出查表,得出長度,再在長度的基礎上計算出它的電阻和電容的大小。若扇出值超出表中的值(假設為7),那么DC就要根據扇出和長度的斜率(Slop)推算出此時的連線長度來。
????????事實上,在每一種工作條件下都會有很多種負載模型,各種負載模型對應不同大小的模塊的連線,如上圖的模型近似認為是160K門大小的模塊適用的。可以認為,模塊越小,它的單位長度的電阻及電容值也越小,負載模型對應的參數也越小。
????????設置輸入驅動是通過DC的set_wire_load_model命令完成的。
dc_shell > current_design addtwo?
dc_shell > set_wire_load_model -name 160KGATES
????????如上面的語句,則設置了addtwo這個模塊的連線負載模型為160KGATES。
????????另外我們也可以讓DC自動根據綜合出來的模塊的大小選擇負載模型,這個選項在默認下是打開的。如下圖所示,當綜合出的電路的面積小于43478.00時,使用5KGATES的模型,屬于43478.00和86956.00之間時,使用10KGATES的模型。
????????以上討論的情況是一個模塊內部連線的負載模型的估計。如果連線連接的是不同的模塊,那么它的負載模型又將怎么估計呢?這就要用到連線負載模式(set_wire_load_mode)這個命令了。
????????連線負載模式一共有3種,圍繞(enclosed)、頂層(top)以及分段(segmented)。如上圖所示,一根連線連接了B2和B2兩個模塊,這兩個模塊都位于TOP下的SUB這個子模塊中,
- 圍繞模式是指連接B1和B2的連線的負載模型用圍繞它們的模塊的負載模型代替,即用SUB的負載模型;
- 頂層模式是指用頂層模塊的負載模型代替;
- 分段模式顧名思義,分別根據穿過的三段的模型相加得到。
????????如果要設置成圍繞模式,可以使用如下命令?
dc_shell > set_wire_load_mode?enclosed
當然,約束中時序約束還有很多需要詳細了解,會在其他文中介紹。。。