2022年12月16日 星期五

自動修復 Hold Time Violation 的程式

以下程式會自動讀取 timing report 中的 hold time violation,跟據 clock pin name 找到 flip-flop,並且在 flip-flop output pin 的 net 上自動加入 delay cell。反覆執行以上動作直到所有的 hold time violation 都被修復為止。

In Tcl File:

proc fix_hold_time_violations {} {
    report_timing -delay_type min > top_hold.rpt
    set target_pin [exec python get_hold_time_violation.py top_hold.rpt]
    while {$target_pin != {}} {
        set target_net [get_nets -of_objects $target_pin]
        insert_buffer [get_nets $target_net] DELAY_CELL_NAME
        legalize_placement -cells [get_cells -hierarchical {eco_cell*}]
        route_zrt_eco -reroute modified_nets_only
        report_timing -delay_type min > top_hold.rpt
        set target_pin [exec python get_hold_time_violation.py top_hold.rpt]
    }
    derive_pg_connection -power_net VDD -ground_net VSS -power_pin VDD -ground_pin VSS
}

In Python File:

import sys
clock_pin_name1 = "CP"
clock_pin_name2 = "CLK"
if len(sys.argv) == 2:
    fname = sys.argv[1]
    with open(fname, "r") as f:
        lines = f.readlines()
        need_fix = 0
        for i in range(len(lines)):
            line = lines[i]
            if "slack" in line:
                if "VIOLATED" in line:
                    need_fix = 1
                break
        if need_fix:
            start = 0
            for i in range(len(lines)):
                line = lines[i]
                if "clock network delay" in line:
                    start = i
                    break
            if start:
                target_cell = ""
                for i in range(start, len(lines)):
                    line = lines[i]
                    if "/" + clock_pin_name1 in line or "/" + clock_pin_name2 in line:
                        start = i + 1
                        target_cell = line.split()[1][1:-1]
                        break
                if target_cell != "":
                    for i in range(start, len(lines)):
                        line = lines[i]
                        if target_cell in line:
                            start = i + 1
                            target_pin = line.split()[0]
                            print(target_pin)
                            break

2022年12月14日 星期三

自動修復 Short Error 的程式

以下程式利用 IC Compiler 的 verify_lvs 指令回報發生 short error 的 nets,用 python 將 short nets 擷取出來,將其刪除並重新繞線。反覆執行此流程直到所有 short errors 都被修復為止。

In Tcl File:

proc fix_short_nets {} {
    verify_lvs > lvs_result.txt
    set short_nets [exec python get_short_nets.py lvs_result.txt]
    while {$short_nets != {}} {
        remove_net_routing $short_nets
        route_zrt_eco -nets $short_nets -reroute modified_nets_only
        verify_lvs > lvs_result.txt
        set short_nets [exec python3 get_short_nets.py lvs_result.txt]
    }
}

In Python File:

import sys
short_net_list = []
if len(sys.argv) == 2:
    fname = sys.argv[1]
    with open(fname, "r") as f:
        lines = f.readlines()
        record = 0
        for line in lines:
            if "ERROR :" in line and "nets short together." in line:
                record = 1
            elif line == "\n":
                record = 0
            if record and not "ERROR :" in line:
                net = line.split()[0]
                if net != "VDD" and net != "VSS":
                    short_net_list.append(net)
for net in short_net_list:
    print(net, end = ' ')

2022年11月30日 星期三

Clock Gating 是什麼?怎麼做?

 

在同步數位邏輯電路中,所有 flip-flop 都是由一個 clock 訊號來觸發。由於 clock 是不斷地進行振盪的訊號,即使 flip-flop 的資料沒有改變,只要 clock 訊號變化,都會造成 flip-flop 上的能源消耗。為了降低晶片的功耗,clock gating 是一樣很重要的技術。

其概念是在 flip-flop 不需要運作的時候,將其 clock 訊號停住。在 standard cell library 中有提供 Clock Gating Cell,如下圖所示。

其中 E 是一個 enable 訊號,當 E = 1 時,代表 flip-flop 需要被觸發。當 E = 0 時,代表 flip-flop 不需要運作。GCLK 是 gated clock,是由一個 AND gate 產生,只有當 Q = 1 時,GCLK 才會等於 CLK,否則 GCLK 都是 0。

從波形中可以看出,當 E 改變時,Q 並不會馬上跟著改變,而要等到 CLK = 0 的時候,Q 才會變成 E。這樣做的用意是為了避免 GCLK 上產生毛刺 (glitch)。由於 clock 的 rising/falling edge 會觸發運算,在 clock 上的 glitch 是不允許的。

各位可以試著畫圖看看,假如直接讓 E 來控制 AND gate,當 E 從 1 變成 0 時,會使 GCLK 產生一個 glitch。(請記得 E 訊號是由 clock rising edge 觸發的,因此它總是會稍晚於 clock rising edge。)

大家應該也有注意到,除了 E 以外,還有一個 TE 訊號,這是 test enable 訊號。當我們要進行測試時,必須透過 scan chain 來進行,此時必須讓 clock 能夠送到所有的 flip-flop 上,因此當 TE = 1 時,GCLK 會一直等於 CLK。

要如何加入 clock gating 呢?目前的 Design Compiler 都有支援,可以自動根據 RTL code 來判斷哪些 flip-flop 要執行 clock gating 來降低 power consumption。由於 Clock Gating Cell 本身會占用面積,也是會耗電,假如每個 flip-flop 都進行 clock gating,並非最好的做法。這部份 Design Compiler 也會協助判斷。

只要在進行合成的時候,在 compile 指令後面加上一個 -gate_clock 的選項即可,如下:

compile_ultra -gate_clock


2022年8月12日 星期五

如何對 black box macro 進行時序約束

 進行 place and route 時,可能有些 macro 是 full-custom design,沒有針對此 macro 建立 timing library,對 IC compiler 來說,就是一個黑盒子,對於這種 black box macro,可透過以下指令進行時序約束。

Black Box Macro 的 Clock

set_clock_tree_exceptions -stop_pins [get_pins macro/CLK]

Black Box Macro 的輸入訊號

set_output_delay -max $MACRO_IN_DELAY -clock clk -reference_pin [get_pins macro/CLK] [get_pins macro/IN]

set_output_delay -min $MACRO_HOLD -clock clk -reference_pin [get_pins macro/CLK] [get_pins macro/IN]

$MACRO_IN_DELAY 是 macro 輸入訊號抵達內部 flip-flop 的延遲時間。$MACRO_HOLD 是內部 flip-flop 所需的 hold time 的負值 ($MACRO_HOLD 是負數)。

Black Box Macro 的輸出訊號

set_input_delay -max $MACRO_CLK_Q -clock clk -reference_pin [get_pins macro/CLK] [get_pins macro/OUT]

set_input_delay -min 0.0 -clock clk -reference_pin [get_pins macro/CLK] [get_pins macro/OUT]

$MACRO_CLK_Q 是 macro 內部flip-flop 的 clock to output 時間。

-max 和 -min 的設定都是必要的,假如只設定了 max delay,min delay 的延遲時間就會與 max delay 一樣。

參考資料

Static Timing Analysis for Nanometer Designs: A Practical Approach (2009)
by Rakesh Chadha & J. Bhasker

如何載入 max/min delay library 進行 setup/hold time 分析

Design Compiler 或 IC Compiler 預設都是會使用在 target library 和 link_library 中第一個讀取到的 .db 檔。但是做 timing analysis 時,我們要用 worst case library 來分析 setup time,用 best case library 來分析 hold time。以下說明如何載入 max/min delay library,這部分是在 .synopsys_dc.setup 檔中進行。

在 target_library 中,要引入 max delay 的 standard cell library:

set target_library "std_cell_max.db"

在 link library 中,要引入 max/min delay 的 memory library、io library:

set link_library "* $target_library dw_foundation.sldb \
    std_cell_min.db \
    io_max.db \
    io_min.db \
    memory_max.db \
    memory_min.db \
    "

接下來我們要設定在 max/min timing analysis 時所使用的 library:

set_min_library std_cell_max.db \
-min_version std_cell_min.db

set_min_library io_max.db \
-min_version io_min.db

set_min_library memory_max.db \
-min_version memory_min.db

如此一來,Design Compiler 和 IC Compiler 就會根據以上設定的 max/min delay library 來進行 setup/hold time analysis。若沒有用 set_operating_conditions 來選擇 operating condition 的話,會直接使用 max/min delay library 中的 default operating condition。

2022年7月28日 星期四

修復 short routing nets

 
當做完 routing 後,可用 verify_lvs 指令檢查是否有 open / short 錯誤。當發生 short 錯誤時,可將發生 short 的 routing net 刪除,並且用 route_zrt_eco 指令重新進行繞線。若有多條 nets 發生 short 可一次處理,可用以下指令。

set short_nets [list net0 net1 net2 net3]
remove_net_routing $short_nets
route_zrt_eco -nets $short_nets -reroute modified_nets_only

如果發生 short 的 net 是 power net,不可將其刪除,只要刪除 signal net 就好。修復 open / short 時有可能會產生其它的 timing violations,必須再次進行檢查,直到 short 和 timing violation 全部都修復為止。

修復 max capacitance / max transition time violations

 

繞線時走線太遠,或是 cell output 驅動的負載太大,都會產生 max capacitance 與 max transition time violations,修復方法是在這些 routing nets 上插入 buffer。

insert_buffer [get_nets net0] BUFFD0BWP40

一開始先使用較小 size 的 buffer,若還是有 violations,則在新產生的 net 上面再插入較大 size 的 buffer。

insert_buffer [get_nets eco_net] BUFFD2BWP40

插入 buffer 後可用 report_constraint -all 指令再次確認是否有解決 violations。若仍未解決,可加入更大 size 的 buffer。若解決了,就用以下指令將插入的 buffer 進行適當的 placement,並進行繞線。

legalize_placement -cells [get_cells {eco_cell_0 eco_cell_1}]
route_zrt_eco -reroute modified_nets_only

完成後要記得將這些新加入的 buffer 連接上 VDD/VSS。

derive_pg_connection -power_net $DGZ_POWER -ground_net $DGZ_GROUND -power_pin $DGZ_POWER -ground_pin $DGZ_GROUND

2022年7月21日 星期四

將 APR 後的 gds 檔和 memory 及 analog macro 的 gds 合併

做完 APR 以後,產出的 gds 檔中沒有 memory 和 analog macro 的 layout,需要將這些 macro 的 layout 進行合併,可使用以下指令。

calibredrv -a layout filemerge -smartdiff -rename -preserve merge_filterfile\
    -in top_apr.gds \
    -in memory.gds \
    -in analog_macro.gds \
    -out top_apr_merge.gds \
    -topcell top_apr

-smartdiff
由於在不同的 gds 中可能存在相同名稱的 cell,當合併時會造成某些 cell 被覆蓋掉,加上這個選項,就可以自動辨別 cell 的內容,當 cell 內容不同時會自動重新命名。

-in
定義要被合併的 gds 路徑與檔名。

-out
定義輸出的 gds 的路徑與檔名。

-topcell
指定 top cell 的名稱。

-preserve
在 -preserve 後面的 merge_filterfile 是一個檔案,其內容如下:

analog_macro.gds    analog_macro_module_name  -nohier
memory.gds             memory_module_name            -nohier

由於在原本 APR 後產生的 memory 和 analog macro 要用真實的 layout 換掉,因此在 merge_filter_file 中定義 analog_macro.gds 和 memory.gds 是合併後保留的。

-nohier 表示只有 analog_macro 的最上層 hierarchy 會被強制保留,其它內容還是會透過 smartdiff 進行比對,決定是否需要重新命名。如果沒有加上 -nohier,會造成 memory.gds 或 analog_macro.gds 中的 cell 可能把 top_apr.gds 裡面同名的 cell 覆蓋掉。


將 gate level netlist 轉成 LVS 用的 spice netlist

 

v2lvs -64 -i \
    -v top_apr.v \
    -v memory.v \
    -lsr standard_cell_library.spi \
    -lsr io_cell_library.spi \
    -lsr memory.spi \
    -lsr analog_macro.sp \
    -s standard_cell_library.spi \
    -s io_cell_library.spi \
    -s memory.spi \
    -s analog_macro.sp \
    -o top_apr.sp

-v            將 top module、memory 的 verilog code 加入
-lsr          將 standard cell library、io cell library、memory 和 analog macro 的 spice netlist 加入
-s            在產生的 spice netlist 的一開頭加入 .include 的指令,把需要的檔案引入
-o            定義輸出檔案名稱

如何使 Virtuoso 產生的 netlist pin order 符合 library 中的順序

 

做完 Automatic Placement & Routing (APR) 後,要產生 netlist 進行 LVS。

如果 IC 內部有 analog macro,analog macro 中也有用到 standard cell 的話,可能會發現 virtuoso 轉出的 netlist 中的 pin order 和 standard cell library 中的定義不一致。 

解決方式為:

1. 在執行 virtuoso 的目錄下建立一個名為 .simrc 的檔案

2. 在檔案中加入以下文字 auCdlCDFPinCntrl=t