list_path和report_timing Tcl 指令功能強大,但有一些局限性。路徑端點必須是時鐘、針腳或收銀機。此外,這些命令不會回報端點之間的每一條組合路徑。此進階腳本範例支援報告設計中任意路徑(包括組合端點)的時間,並報告端點之間的所有組合路徑。腳本使用反復搜尋演算法來尋找路徑。演算法止于針腳和收銀機,以防止過度執行時間。
您可以為來源和目的地指定節點名稱、萬用字元或時間組名稱。此腳本不支援時組排除;如果您指定包含端點排除的時組,並且忽略排除值,便會顯示警告。
您可以將腳本的輸出引導至逗號分離值(.csv)檔案。預設檔案名 是p2p_timing.csv。此外,您可以將腳本的輸出導向專案計時報告中的面板。預設面板名稱為 點對點計時。
quartus_tan -t p2p_timing.tcl -project <project name>-從<節點名稱|wildcard|timegroup 名稱>-到<節點名稱> |wildcard|timegroup 名稱> [-write_file] [檔案<出量檔案名>] [-write_panel] [面板<報告面板名稱>]
如果您想要將輸出導向不同于預設檔案名的檔,則必須同時指定 -write_file 和 -file <輸出檔案名稱>選項。如果您想要將輸出導向不同于預設報告面板名稱的報告面板,則必須同時指定 -write_panel 和 -面板<回報面板名稱>選項。
將下列 Tcl 命令複製到檔案中,並將其命名為 p2p_timing.tcl。
封裝需要 cmdline load_package advanced_timing load_package報告 全球 quartus 變數:argv0 $:quartus (args) 設定選項 { { 「來自.arg」「」「來源節點名稱」\ { 「to.arg」「「目的地節點名稱」\ { 「project.arg」「「專案名稱」\ { 「file.arg」「p2p_timing.csv」「輸出 csv 檔案名」\ { 「write_file」「「將輸出寫入檔案」\ { 「panel.arg」「點對點計時」「報告面板名稱」\ { 「write_panel」「「將輸出寫入報告面板」\ } 陣列設定選擇 [:cmdline::getoptions::argv0 $options「錯誤選項」] ############################################################## # # 退回節點名稱與對應節點 ID 的清單 符合模式參數的設計名稱編號。 # 任何不符合設計名稱的模式都有 退回的空清單 # 範例:在「重設」中傳遞,然後將 { 重設 3 = 回復 # ############################################################## proc get_node_ids { 模式 \ { 陣列集 name_to_node [清單] 如果 { [字串等於」$pattern] { { 退回 [清單] } #模式是否真的是時間組的名稱? # 如果是,則腳本會重複取得會員 # 時間組。 設定會員 [get_all_global_assignments - 名稱 TIMEGROUP_MEMBER -section_id $pattern] # 如果有任何成員的系列, # 模式是時間組 如果 { 0 < [get_collection_size $members]\ { # 警告是否有排除,因為腳本 # 跳過排除 如果 {0 < [get_collection_size [get_all_global_assignments- 名稱 TIMEGROUP_EXCLUSION -section_id $pattern]] { post_message類型警告「在時組$pattern中排除排除功能」 } # 在時間組中流覽每個專案。 foreach_in_collection分配$members { # 系列中的每一個專案都是這樣的清單: # {$pattern\ {TIMEGROUP_MEMBER\ {node/real pattern] 陣列集 sub_collection_names [get_node_ids [lindex $assignment 2]] foreach node_name [陣列名稱稱 sub_collection_names] { 設定name_to_node($node_name)$sub_collection_name($node_name) } } { 其他 { # 它不是時間組 # 在設計中反復傳遞所有計時節點, # 檢查名稱是否符合指定的模式 foreach_in_collection node_id [get_timing_nodes -type all] { 設定node_name [get_timing_node_info -資訊名稱 $node_id] 如果 { [字串匹配 [escape_brackets $pattern] $node_name] { { 設定name_to_node($node_name)$node_id } } } 退回 [陣列取得name_to_node] } ############################################################## # # 這個程式會在來源之間找到組合路徑 # 節點與目的地節點清單。它會退回清單 節點之間的 # 路徑。每條路徑都由三人組成 節點 ID 數量,以及互連延遲和單元延遲 # 先前的節點。 # 程式停止在收銀機中流覽網路清單 # 或針腳,因此找不到通過收銀機的路徑。 # ############################################################## proc find_combinational_paths_between {佇列 dest_nodes\ { { 設定num_iterations 0 設定路徑 [清單] {0 < [llength $queue]\ { # 每千次報告迴圈的進展 # 反覆運算不斷num_iterations 如果 { 1000 == $num_iterations { { 設定num_iterations 0 post_message「檢查 [llength $queue] 路徑。」 } # 從佇列中彈出第一條路徑。 # 第一次呼叫程式,即佇列 # 只是一個數位,來源節點。 設定路徑 [lindex $queue 0] 設定佇列 [lrange $queue 1 結束] # 在路徑上取得最後一個節點,然後在前方迴圈中 # 從該節點獲得風扇 設定last_triplet_in_path [lindex $path端] 設定last_node_in_path [lindex $last_三重_in_path 0] # 僅擷取目前路徑中的節點 ID。 # 這稍後會使用,以確保迴圈不會經過。 設定nodes_in_path [collapse_triplets_to_node_list $path] # 在此路徑上取得最後一個節點的所有風扇,然後製作 # 與他們一起推動佇列的新路徑。 foreach n [get_timing_node_fanout $last_node_in_path] { foreach { node_id ic_delay cell_delay \ $n { 打破 } 如果 { -1 != [lsearch $dest_節點 $node_id] { { # 如果路徑上的這個節點在清單中 # 目的地節點,有一條路徑。 # 將其新增到節點之間的路徑清單中 設定new_path $path圈數 new_path $n lappend Path $new_path } 如果 { -1 == [lsearch $nodes_in_path $node_id] { { # 如果路徑上的這個節點不在路徑上 # 已經不是迴圈了。將其推上 如果是組合節點或頻率節點,則會排佇列。 # 如果這個節點是 a,則不會開啟路徑 # 註冊或插針。 # 在這樣的佇列上推動一條新路徑, # 儘管路徑上的這個節點可能相符 # 端點,確保盡可能長 找到 # 路徑。 設定node_type [get_timing_node_info -資訊類型 $node_id] 交換器 -精確 - $node_type { comb - clk { 設定next_path $path 膝上型next_path $n lappend 佇列 $next_path } 預設 { } } } } } 退回$paths } ############################################################## # # 新增兩個延遲編號並退回結果。 # 延遲編號以單位的「價值單位」形式出現 # 可能是奈秒 (ns) 或 picosecond (ps),而且值可能 # 如果單位為 picoseconds,則為 x{1,3®,或 x+.y{1,3®(如果為 x+.y{1,3®) # 單位為奈秒。此程式將延遲標準化到 # 奈秒,並新增值。 編號範例:add_delays「1.234 ns」「56 ps」# ############################################################## proc add_delays { a b = { 如果 { !]RegExp {^([\d\.]+)\s+([np]s)$® $a比a_value a_unit] { { post_message類型錯誤「無法判斷時間的某些部分:$a」 } 如果 { !]RegExp {^([\d\.]+)\s+([np]s)$® $b比b_value b_unit] { { post_message類型錯誤「無法判斷時間的某些部分:$b」 } # 視需要將一切轉換為奈秒 如果 { [字串等於 -nocase ps $a_unit] { { 設定a_value_ps [格式化 」。3f" $a_value] 設定a_value [格式化」。3f" [expr { $a_value_ps / 1000 []] } 如果 { [字串等於 -nocase ps $b_unit] { { 設定b_value_ps [格式化 」。3f" $b_value] 設定b_value [格式化」。3f" [expr { $b_value_ps / 1000 []] } # 現在單位是等的,是奈秒。 # 只要將數位加起來即可。 設定sum_value [格式化」。3f" [expr { $a_value + $b_value []] 退回「$sum_value ns」 } ############################################################## # # 格式化並列印路徑上的節點名稱與 節點之間的延遲編號。 # ############################################################## proc print_path_delays { Path {iteration first\\ { { 設定source_triplet [lindex $path 0] 設定source_node [lindex $source_三重 0] 設定source_node_name [get_timing_node_info──資訊名稱 $source_節點] 設定source_node_loc [get_timing_node_info 『──資訊位置 $source_節點] # 先列印延遲 如果 { [字串等於「第一」$iteration] { { accumulate_data [列出「IC(0.000 ns)」「CELL (0.000 ns)」] { 其他 { 設定ic_delay [lindex $source_三重 1] 設定cell_delay [lindex $source_三重 2] accumulate_data [列出「IC($ic_延遲)」「CELL($cell_延遲)」] } accumulate_data [清單 $source_node_loc $source_node_name] print_accumulated_data # 在路徑的其他部分重複 如果 { 1 < [llength $path] { { print_path_delays [lrange $path 1 端] 其他 } } ############################################################## # # 將指定路徑上的 IC 和單元延遲總和 # 退回總互連延遲和總單元的清單 # 延遲。 # ############################################################## proc end_to_end_delay { 路徑 \ { 設定ic_total「0.000 ns」 設定cell_total「0.000 ns」 # 這要經過節點 1 到路徑結束,因為 路徑中的第一個節點是來源,以及每個節點 # 路徑包含之前節點的延遲。# 來源前面有節點,所以沒有延遲。 foreach n [lrange $path 1 結束] { foreach { node_id ic_delay cell_delay \ $n { 打破 } 設定ic_total [add_delays $ic_total $ic_延遲] 設定cell_total [add_delays $cell_total $cell_延遲] } 退回 [清單 $ic_total $cell_total] } ############################################################## # # 確保其中包含特定來源與目的地 # 設計、找到它們之間的組合路徑,以及 # 列印路徑。 # ############################################################## proc find_paths_and_display { 來源 dest \ { 陣列設定來源 [get_node_ids $source] 陣列集 dests [get_node_ids $dest] 設定nodes_exist 1 # 確保已命名的節點存在 如果 { 0 == [llength [Array 取得來源]] { { { 設定nodes_exist 0 post_message類型錯誤:「設計中發現了與$source相符的節點。」 } 如果 { 0 == [llength [Array get dests]] { { 設定nodes_exist 0 post_message類型錯誤:「設計中發現了與$dest相符的節點。」 } # 如果他們這樣做,請尋找路徑。 如果 { $nodes_exist { # 取得目的地節點 IDS 清單 設定dest_node_ids [清單] foreach d [陣列名稱稱 dests] { 膝上型dest_node_ids $dests($d) } # 從節點穿過所有 foreach 的 [陣列名稱稱來源] { 設定路徑 [find_combinational_paths_between $sources($s)$dest_node_ids] 如果 { 0 == [llength $paths] { { post_message「從$s到$dest不存在任何組合路徑」 { 其他 { foreach 路徑 $paths { # 列印出路徑 print_path_delays $path # 總和互連和單元延遲,以及 # 在路徑下列印出來。 foreach {total_ic_delay total_cell_delay [ end_to_end_delay $path] { { 打破 } accumulate_data [清單 $total_ic_延遲 $total_cell_延遲] accumulate_data [清單 [add_delays $total_ic_延遲 $total_cell_延遲]] # 有兩個電話要print_accumulated_data #這裡,一個要列印互連總和 #和單元延遲,一個產生空白 輸出第一行。 print_accumulated_data print_accumulated_data } } } } } ############################################################## # # 路徑由三重資訊組成 - 節點 ID, # 互連延遲,以及單元延遲。此程式解壓縮 # 每個三重組的節點 ID 順序,然後退回清單 節點 ids 數量 # ############################################################## proc collapse_triplets_to_node_list { l { { 設定to_return [清單] foreach 三重$l { lappend to_return [lindex $triplet 0] } 退貨$to_退貨 } ############################################################## # # 將資訊串流至全球變數準備中 已列印出來的編號。 # ############################################################## proc accumulate_data { 資料 { { 全球累積設定累積 [concat $accum $data] } ############################################################## # # 列印出已累積的資料。 # 列印成標準,然後選購到檔案中 如果檔案處理存在,則 CSV 格式,並選用到 a 如果報告面板存在時, # 報告面板 (不具有 -1 的值) # ############################################################## proc print_accumulated_data {\ { 全球累積 fh panel_id 放 [加入$accum」,] # 把它寫到檔案中? 如果 { [資訊存在 fh] { { 將$fh [加入 $accum」,] } # 將其加入報告面板中? 如果 { -1 != $panel_id { # 如果報告面板行沒有 4 個專案 #在其中,將它墊到 4。 而 { 4 > [llength $accum] { { lappend 累積 [清單] } add_row_to_table -id $panel_id $accum } # 清除全球變數中的資訊。 設定累積 [清單] } ############################################################## ############################################################## # 程式結束,腳本開始 # ############################################################## ############################################################## # 持有印刷資料與面板的全球變數 選用報告面板的編號 ID 設定累積 [清單] 設定panel_id -1 如果 { [字串等於」$opts(專案)] { { # 如果未撥打腳本,請列印使用選項 # 爭辯 放 [:cmdline::使用$options] \ elseif { [字串等於」$opts(專案)] { { post_message類型錯誤「使用專案選項指定專案」。 \ elseif { ![project_exists $opts(專案)]]{ post_message類型錯誤「專案$opts(專案)在本目錄中不存在。」 \ elseif { [字串等於」$opts(從)]{ { post_message類型錯誤「從選項中指定名稱或萬用字元模式」。 { elseif { [字串等於」$opts (to)] { { post_message類型錯誤「指定名稱或萬用字元模式與-to 選項」。 { 其他 { 設定cur_revision [get_current_revision $opts(專案)] project_open $opts(專案) -修訂版 $cur_修訂版 # 嘗試建立計時網路清單。此命令會失效 例如,如果quartus_fit尚未執行。 如果 { [捕捉 { create_timing_netlist [ msg ] { { post_message -輸入錯誤$msg { 其他 { # 必要時準備將輸出寫入檔案 如果 { 1 == $opts(write_file) { { 如果 { [捕捉 {open $opts (檔案) w™ fh] { { { post_message類型錯誤「無法開啟$opts(write_file):$fh」未設定 fh { 其他 { post_message「將輸出寫入$opts(檔案)」 # 將一些介紹資訊新增到輸出檔案中 將$fh「從$opts(從)到$opts(至))的路徑報告」 將$fh「以 [頻率格式 [頻率秒]] 產生」 將$fh「」放$fh「IC 延遲、單元延遲、節點位置、節點名稱」 } } # 必要時準備將輸出寫入報告面板 如果 { 1 =$opts(write_panel) { { # 載入報告,如果已經存在,請刪除面板, # 建立新的面板,並新增標題列。 load_report 設定panel_id [get_report_panel_id」計時分析器||$opts(面板)」] 如果 { -1 != $panel_id { delete_report_panel -id $panel_id } 設定panel_id [create_report_panel 『──計時分析器||$opts(面板)」] add_row_to_table -id $panel_id [清單「IC 延遲」「單元延遲」「節點位置」「節點名稱」] } find_paths_and_display $opts(從) $opts(至) 如有需要,請關閉輸出檔案 如果 { [資訊存在 fh] \ { 關閉$fh ® 如有需要,請儲存報告面板 如果 { -1 != $panel_id { save_report_database unload_report } } project_close }