Contoh Quartus® II Tcl: Pelaporan Waktu Jalur Arbitrer

author-image

Oleh

Perintah list_path dan report_timing Tcl sangat kuat, tetapi mereka memiliki beberapa batasan. Endpoint path harus berupa clock, pin, atau register. Selain itu, perintah tersebut tidak melaporkan setiap jalur kombinasi di antara endpoint. Contoh skrip lanjutan ini mendukung waktu pelaporan pada jalur semena-mena dalam desain Anda (termasuk endpoint kombinasi), dan melaporkan semua jalur kombinasi antar endpoint. Skrip menggunakan algoritma pencarian iteratif untuk menemukan jalur. Algoritma berhenti di pin dan mendaftar untuk mencegah waktu proses yang berlebihan.

Anda dapat menentukan nama node, wildcard, atau nama grup waktu untuk sumber dan tujuan. Pengecualian grup waktu tidak didukung oleh skrip ini; peringatan akan ditampilkan jika Anda menentukan grup waktu yang berisi pengecualian untuk endpoint, dan pengecualian diabaikan.

Anda dapat mengarahkan keluaran skrip ke berkas Comma Separated Value(.csv). Nama file bawaan adalah p2p_timing.csv. Selain itu, Anda dapat mengarahkan keluaran skrip ke panel dalam laporan waktu proyek Anda. Nama panel bawaanadalah Pengaturan Waktu Poin ke Titik .

quartus_tan -t p2p_timing.tcl -project <project name> -from <node name|wildcard|timegroup name> -to <node name| |timegroupldcard> [-write_file] [-file <output nama file>] [-write_panel] [-panel < nama panel <laporan>]

Jika Anda ingin mengarahkan keluaran ke berkas yang berbeda dari nama berkas bawaan, Anda harus menentukan nama berkas -write_file dan -file <output> opsi. Jika Anda ingin mengarahkan keluaran ke panel laporan yang berbeda dari nama panel laporan bawaan, Anda harus menentukan nama panel -write_panel dan -panel <report> opsi.

Salin perintah Tcl berikut ke berkas dan beri nama p2p_timing.tcl.

paket memerlukan cmdline 
load_package advanced_timing 
laporan load_package 

kuartus global 
variabel ::argv0 $::quartus(args) 

atur opsi { \ 
   { "from.arg" "" "Nama node sumber" } \ 
   { "to.arg" "" "Nama node tujuan" } \ 
   { "project.arg" "" "Nama proyek" } \ 
   { "file.arg" "p2p_timing.csv" "Nama berkas csv keluaran" } \ \ 
   { "write_file" "" "Tulis keluaran ke file" } \ 
   { "panel.arg" "Waktu titik-ke-titik" "Nama panel laporan" } \ 
   { "write_panel" "" "Tulis keluaran ke panel laporan" } \ 
} 

array set opts [:cmdline::getoptions ::argv0 $options "Bad option"] 
############################################################## 
# 
# Mengembalikan daftar nama node dan ID node terkait 
# untuk nama desain yang cocok dengan argumen pola. 
# Pola apa pun yang tidak cocok dengan nama dalam desain memiliki 
Daftar kosong # dikembalikan 
# Contoh: Pass in "reset" dan dapatkan { reset 3 } kembali 
# 
############################################################## 
proc get_node_ids { pattern } { 
   set array name_to_node [daftar] 

jika { [string sama dengan "" $pattern] } { 
      return [daftar] 
   }

# Apakah pola sebenarnya adalah nama grup waktu? 
   # Jika ya, maka skrip secara rekurtif mendapatkan anggota 
   # grup waktu. 
   set anggota [get_all_global_assignments -name TIMEGROUP_MEMBER -section_id $pattern] 

# Jika ada anggota koleksi, 
   # pola adalah grup waktu 
   jika { 0 < [get_collection_size $members]} { 
      # Peringatkan jika ada pengecualian, karena skrip 
      # lewati pengecualian 
      jika {0 < [get_collection_size [get_all_global_assignments -name TIMEGROUP_EXCLUSION -section_id $pattern]] } { 
         post_message -type warning "Skipping exclusions in timegroup $pattern" 
      } 

# Tembus setiap item dalam grup waktu. 
      $members tugas foreach_in_collection { 
         # Setiap item dalam koleksi adalah daftar seperti ini: 
         # {$pattern} {TIMEGROUP_MEMBER} {node/real pattern} 
         set array sub_collection_names [get_node_ids [lindex $assignment 2]] 

node_name foreach [nama array sub_collection_names] { 
            set name_to_node($node_name) $sub_collection_names($node_name) 
         } 
      } 
   } lain { 
      # Ini bukan grup waktu 
      # Iterasi melalui semua node waktu dalam desain, 
      # memeriksa apakah nama cocok dengan pola yang ditentukan 
      foreach_in_collection node_id [get_timing_nodes -type all] { 
         set node_name [nama -get_timing_node_info -info $node_id] 
         jika { [string cocok [escape_brackets $pattern] $node_name] } { 
            set name_to_node($node_name) $node_id 
         } 
      } 
   } 
   return [array get name_to_node]
} 

############################################################## 
# 
# Prosedur ini menemukan jalur kombinasi antara sumber 
# node dan daftar node tujuan. Mengembalikan daftar 
# jalur di antara node. Setiap jalur terdiri dari triplet 
# node ID, dan penundaan interkoneksi dan penundaan sel dari 
# node sebelumnya. 
# Prosedur berhenti melintas netlist di register 
# atau pin, sehingga tidak menemukan jalur yang melalui register. 
#
############################################################## 
proc find_combinational_paths_between {queue dest_nodes} { 
   atur num_iterations 0 
   set path [daftar] 
   
sementara {0 < [llength $queue]} { 
      # Laporkan perkembangan loop setiap ribuan 
      # iterasi incr num_iterations 
      jika { 1000 == $num_iterations } { 
         atur num_iterations 0 
         post_message "Memeriksa jalur [llength $queue]." 
      } 
      
# Pop jalur pertama dari antrean. 
      # Saat pertama kali prosedur dipanggil, antrean 
      # hanya satu angka, node sumber. 
      set path [lindex $queue 0] 
      atur antrean [lrange $queue 1 akhir] 
      
# Dapatkan node terakhir di jalur, kemudian di loop foreach 
      # dapatkan kipas dari node itu 
      set last_triplet_in_path [lindex $path akhir] 
      set last_node_in_path [lindex $last_triplet_in_path 0] 
 
# Ekstrak hanya ID node di jalur saat ini. 
      # Ini digunakan nanti untuk memastikan loop tidak dilalui. 
      set nodes_in_path [collapse_triplets_to_node_list $path] 

# Dapatkan semua kipas node terakhir di jalur ini dan buatlah 
      # jalur baru dengannya untuk mendorong antrean. 
      foreach n [get_timing_node_fanout $last_node_in_path] { 
         foreach { node_id ic_delay cell_delay } $n { 
            Istirahat 
         }
 
jika { -1 != [lsearch $dest_node $node_id] } { 
            # Jika node ini ada di dalam daftar 
            # node tujuan, ada jalur. 
            # Tambahkan ke daftar jalur di antara node 
            set new_path $path lappend 
            new_path $n 
            jalur lappend $new_path 
         } 

jika { -1 == [lsearch $nodes_in_path $node_id] } { 
            # Jika node ini di jalur tidak ada di jalur 
            # sudah, ini bukan sebuah loop. Dorong pada 
            # antrean jika merupakan node kombinasi atau clock. 
            # Jalur tidak didorong jika node ini adalah 
            # daftar atau pin. 
            # Mendorong jalur baru pada antrean seperti ini, 
            # meskipun node di jalur ini mungkin cocok 
            # node akhir, memastikan kemungkinan terpanjang 
            # jalur ditemukan. 
            set node_type [get_timing_node_info -info type $node_id] 
            switch -exact -- $node_type { 
               sisir - 
               clk { 
                  atur next_path $path 
                  next_path $n cacat 
                  antrean lappend $next_path 
               } 
               bawaan { 
               } 
            } 
         } 
      }
   }
   $paths pengembalian 
} 

############################################################## 
# 
# Menambahkan dua angka tunda dan mengembalikan hasilnya. 
# Nomor tunda dalam bentuk "unit nilai" di mana unit 
# dapat berupa nanoseconds (ns) atau picoseconds (ps), dan nilai mungkin 
# jadilah x{1,3} jika unit picosecond, atau x+.y{1,3} jika 
# unit adalah nanodetik. Prosedur ini menormalkan penundaan ke 
# nanodetik dan menambahkan nilai. 
# Contoh: add_delays "1,234 ns" "56 ps" # 
############################################################## 
add_delays proc { a b } { 
   jika { ![ regexp {^([\d\.] +)\s+([np]s)$} $a cocok dengan a_value a_unit] } { 
      galat -type post_message "Tidak dapat menentukan bagian waktu: $a" 
   } 

jika { ![ regexp {^([\d\.] +)\s+([np]s)$} $b cocok dengan b_value b_unit] } { 
      galat -type post_message "Tidak dapat menentukan bagian waktu: $b" 
   } 
  
# Konversikan segalanya menjadi nanodetik jika diperlukan 
   jika { [string sama dengan -nocase ps $a_unit] } { 
      set a_value_ps [format "%.3f" $a_value] 
      set a_value [format "%.3f" [expr { $a_value_ps / 1000 }]] 
   } 

jika { [string sama dengan -nocase ps $b_unit] } { 
      set b_value_ps [format "%.3f" $b_value] 
      set b_value [format "%.3f" [expr { $b_value_ps / 1000 }]] 
   } 

# Kini unit setara, dan nanodetik. 
   # Cukup tambahkan angka bersama-sama. 
   set sum_value [format "%.3f" [expr { $a_value + $b_value }]] 
  
mengembalikan "$sum_value ns" 
} 

############################################################## 
# 
# Format dan cetak nama node di jalur dengan  
# penundaan di antara node. 
# 
############################################################## 
proc print_path_delays { path {iteration first}} { 
   set source_triplet [lindex $path 0] 
   set source_node [lindex $source_triplet 0] 
   set source_node_name [nama -get_timing_node_info -info $source_node] 
   set source_node_loc [get_timing_node_info -info location $source_node] 
   
# Cetak penundaan terlebih dahulu 
   jika { [string sama dengan "pertama" $iteration] } { 
      accumulate_data [list "IC(0.000 ns)" "CELL(0.000 ns)"] 
   } lain { 
      set ic_delay [lindex $source_triplet 1] 
      set cell_delay [lindex $source_triplet 2] 
      accumulate_data [daftar "IC($ic_delay)" "CELL($cell_delay)"] 
   } 
   accumulate_data [daftar $source_node_loc $source_node_name] 
   print_accumulated_data 

# Berulang di sisa jalur 
   jika { 1 < [llength $path] } { 
      print_path_delays [lrange $path 1 ujung] lainnya 
   } 
} 

############################################################## 
# 
# Menjumlahkan keterlambatan IC dan sel pada jalur dan 
# mengembalikan daftar dengan penundaan interkoneksi total dan total sel 
# tunda. 
# 
############################################################## 
proc end_to_end_delay { path } { 
   set ic_total "0,000 ns" 
   set cell_total "0,000 ns" 
   
# Ini melewati node 1 hingga akhir di jalur karena 
   # node pertama di path adalah sumber dan setiap node di 
   # path berisi keterlambatan dari node yang mendahuluinya. Tje 
   # sumber tidak memiliki node yang mendahuluinya, sehingga tidak memiliki penundaan. 
   foreach n [lrange $path 1 ujung] { 
      pendeta { node_id ic_delay cell_delay } $n { 
         Istirahat 
      } 
      set ic_total [add_delays $ic_total $ic_delay] 
      set cell_total [add_delays $cell_total $cell_delay] 
   } 

return [daftar $ic_total $cell_total] 
} 

##############################################################
# 
# Memastikan sumber dan tujuan tertentu ada di 
# desain, temukan jalur kombinasi di antara keduanya, dan 
# mencetak jalur. 
# 
############################################################## 
proc find_paths_and_display { source dest } { 
   sumber rangkaian array [get_node_ids $source] 
   set dest array [get_node_ids $dest] 

set nodes_exist 1 

# Pastikan node yang bernama ada 
   jika { 0 == [llength [array get sources]] } { 
      atur nodes_exist 0 
      post_message -type error "Node yang cocok $source ditemukan dalam desain Anda." 
   } 
   jika { 0 == [llength [array get dests]] } { 
      atur nodes_exist 0 
      post_message -type error "Node yang cocok $dest ditemukan dalam desain Anda." 
   } 

# Jika mereka melakukannya, temukan jalurnya.   jika { $nodes_exist } { 
      # Dapatkan daftar id node tujuan 
      set dest_node_ids [daftar] 
      foreach d [nama array dests] { 
         dest_node_ids $dests lappend ($d) 
      } 

# Tembus semua dari node 
      foreach s [sumber nama array] { 
         set path [find_combinational_paths_between $sources($s) $dest_node_ids] 
         jika { 0 == [llength $paths] } {  
            post_message "Tidak ada jalur kombinasi dari $s hingga $dest" 
         } lain { 
            jalur pendeta $paths { 
               # Cetak jalurnya 
               print_path_delays $path 

# Jumlahkan keterlambatan interkoneksi dan sel dan 
               # cetak di bawah jalur. 
               {total_ic_delay total_cell_delay } [end_to_end_delay $path] { 
                  Istirahat 
               } 
               accumulate_data [list $total_ic_delay $total_cell_delay] 
               accumulate_data [list [add_delays $total_ic_delay $total_cell_delay]] 

# Ada dua panggilan ke print_accumulated_data 
               # di sini, satu untuk mencetak jumlah interkoneksi 
               # dan keterlambatan sel, dan satu untuk menghasilkan kosong 
               # baris dalam keluaran. 
               print_accumulated_data print_accumulated_data 
            } 
         } 
      }
   } 
} 

############################################################## 
# 
# Sebuah jalur terdiri dari triplet informasi - node id, 
# penundaan interkoneksi, dan penundaan sel. Prosedur ini mengekstrak 
# id node dari setiap triplet secara berurutan dan mengembalikan daftar 
# id node 
# 
############################################################## 
collapse_triplets_to_node_list proc { l } { 
   set to_return [daftar] 
   triplet triplet $l { 
      to_return lappend [lindex $triplet 0] 
   } 
   return $to_return 
} 

############################################################## 
# 
# Menggabungkan informasi ke variabel global dalam persiapan 
# untuk dicetak. 
# 
############################################################## 
accumulate_data proc { data } { 
   akumulasi set akumulasi global [concat $accum $data] 
}
 
############################################################## 
# 
# Cetak data yang terakumulasi. 
# Ini dicetak ke standar keluar dan opsional ke file masuk 
# Format CSV jika ada pegangan file, dan opsional ke 
# panel laporan jika panel laporan ada (bukan nilai -1) 
# 
############################################################## 
proc print_accumulated_data {} { 
   akumulasi global fh panel_id 
   menempatkan [bergabung dengan $accum ","] 

# Tuliskan ke file? 
   jika { [info ada fh] } { 
      menempatkan $fh [bergabung dengan $accum ","] 
   } 

# Tambahkan ke panel laporan? 
   jika { -1 != $panel_id } { 
      # Jika baris panel laporan tidak memiliki 4 item 
      # di dalamnya, pad ke 4. 
      sementara { 4 > [llength $accum] } { 
         akumulasi lappend [daftar] 
      } 
      $accum -id -id add_row_to_table $panel_id 
   } 
   # Hapus informasi dalam variabel global. 
   atur akumulasi [daftar] 
}

############################################################## 
############################################################## 
# 
# Akhir prosedur, awal skrip 
# 
############################################################## 
##############################################################
# 
# Variabel global untuk menahan data untuk pencetakan, dan panel 
# ID untuk panel laporan opsional 

atur akumulasi [daftar] 
set panel_id -1 

jika { [string sama dengan "" $opts(project)] } { 
   # Opsi penggunaan cetak jika skrip dipanggil tanpa 
   # argumen 
   puts [:cmdline::$options penggunaan] 
} elseif { [string sama dengan "" $opts(proyek)] } { 
   post_message -type error "Sebutkan proyek dengan opsi -project." 
} elseif {! [project_exists $opts(proyek)] } { 
   post_message -type error "Project $opts(project) tidak ada di direktori ini." 
} elseif { [string sama dengan "" $opts(dari)] } { 
   post_message -type error "Sebutkan nama atau pola wildcard dengan opsi -from." 
} elseif { [string sama dengan "" $opts(to)] } { 
   post_message -type error "Sebutkan pola nama atau wildcard dengan opsi -to." 
} lain { 
   set cur_revision [get_current_revision $opts(proyek)] 
   project_open $opts(project) -revisi $cur_revisi 

# Cobalah untuk membuat daftar waktu. Perintah ini akan gagal 
   # jika quartus_fit belum dijalankan, misalnya. 
   jika { [penangkapan { create_timing_netlist } msg ] } { 
      $msg galat -tipe post_message 
   } lain { 

# Bersiaplah untuk menulis keluaran ke file jika diperlukan 
      jika { 1 == $opts(write_file) } { 
         jika { [menangkap {open $opts(file) w} fh] } { 
            galat -tipe post_message "Tidak dapat membuka $opts(write_file): $fh" unset fh 
         } lain { 
            post_message "Menulis keluaran ke $opts(file)" 
            # Tambahkan beberapa informasi pengantar ke file output 
            menempatkan $fh "Laporan jalur dari $opts(dari) ke $opts(ke)" 
            menempatkan $fh "Dihasilkan pada [format clock [clock detik]]" 
            menempatkan $fh "" menempatkan $fh "IC tunda, Tunda sel, lokasi Node, Nama Node" 
         } 
      } 

# Bersiaplah untuk menulis keluaran ke panel laporan jika diperlukan 
      jika { 1 == $opts(write_panel) } { 
         # Muat laporan, hapus panel jika sudah ada, 
         # buat panel baru, dan tambahkan baris judul. 
         load_report 
         set panel_id [get_report_panel_id "Timing Analyzer|| $opts(panel)"] 
         jika { -1 != $panel_id } { 
            delete_report_panel -id $panel_id 
         } 
        set panel_id [create_report_panel -table "Timing Analyzer|| $opts(panel)"] 
        add_row_to_table -id $panel_id [list "IC delay" "Cell delay" "Node location" "Node name"] 
      } 
      find_paths_and_display $opts (dari) $opts(ke) 

# tutup berkas keluaran jika perlu 
      jika { [info ada fh] } { close $fh } 

# Simpan panel laporan jika perlu 
      jika { -1 != $panel_id } { 
         save_report_database 
         unload_report 
      } 
   } 
   project_close 
}    

Isi halaman ini adalah kombinasi terjemahan manusia dan komputer dari konten berbahasa Inggris. Konten ini diberikan hanya untuk kenyamanan Anda serta sebagai informasi umum dan tidak bisa dianggap sebagai lengkap atau akurat. Jika terdapat kontradiksi antara versi bahasa Inggris halaman ini dan terjemahannya, versi bahasa Inggris akan didahulukan. Lihat versi bahasa Inggris halaman ini.