Quartus® II Tcl 範例:任意路徑計時報告

author-image

作者

list_pathreport_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
}    

這個頁面的內容綜合了英文原始內容的人工翻譯譯文與機器翻譯譯文。本內容是基於一般資訊目的,方便您參考而提供,不應視同完整或準確的內容。如果這個頁面的英文版與譯文之間發生任何牴觸,將受英文版規範及管轄。 查看這個頁面的英文版。