Quartus® II Tcl Beispiel: Timing-Reporting für beliebige Pfade

author-image

Von

Die list_path und report_timing Tcl-Befehle sind sehr leistungsstark, haben aber einige Einschränkungen. Path-Endpunkte müssen Taktfrequenzen, Pins oder Register sein. Außerdem melden diese Befehle nicht alle Kombinationspfade zwischen den Endgeräten. Dieses erweiterte Skriptbeispiel unterstützt die Berichterstattung über den zeitlichen Ablauf beliebiger Pfade in Ihrem Design (einschließlich kombinierter Endgeräte) und meldet alle Kombinationspfade zwischen Endgeräten. Das Skript verwendet einen iterativen Suchalgorithmus, um Pfade zu finden. Der Algorithmus hält an Pins an und registriert sich, um übermäßige Laufzeiten zu vermeiden.

Sie können Knotennamen, Platzhalter oder Timegroup-Namen für quelle und ziel angeben. Timegroup-Ausschlüsse werden von diesem Skript nicht unterstützt; eine Warnung wird angezeigt, wenn Sie eine Zeitgruppe angeben, die Ausschlüsse für die Endgeräte enthält und die Ausschlüsse ignoriert werden.

Sie können die Ausgabe des Skripts in eine.csv-Datei(Comma Separated Value) leiten. Der Standarddateiname ist p2p_timing.csv. Darüber hinaus können Sie die Ausgabe des Skripts an einen Bereich im Zeitablaufbericht Ihres Projekts weiterleiten. Der Standardfenstername ist Punkt-zu-Punkt-Timing.

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

Wenn Sie die Ausgabe an eine Datei senden möchten, die nicht der Standarddateiname ist, müssen Sie sowohl die Optionen -write_file als auch -file <output file name> angeben. Wenn Sie die Ausgabe an ein Berichtfenster senden möchten, das sich von dem Namen des Standardberichtsfensters unterscheidet, müssen Sie sowohl die Optionen -write_panel als auch -panel <report panel> angeben.

Kopieren Sie die folgenden Tcl-Befehle in eine Datei und benennen Sie sie p2p_timing.tcl.

Paket muss cmdline sein 
load_package advanced_timing 
Bericht load_package 

Globaler Quartus 
Variable ::argv0 $::quartus(args) 

Einstellen von Optionen { \ 
   { "from.arg" "" "Source node name" } \ 
   { "to.arg" "" "Zielknotenname" } \ 
   { "project.arg" "" "Projektname" } \ 
   { "file.arg" "p2p_timing.csv" "Ausgabe des csv-Dateinamens" } \ 
   { "write_file" "" "Schreiben Sie die Ausgabe in eine Datei" } \ 
   { "panel.arg" "Punkt-zu-Punkt-Timing" "Name des Bedienfelds melden" } \ 
   { "write_panel" "" "Schreiben Sie die Ausgabe in ein Berichtfenster" } \ 
} 

array set opts [::cmdline::getoptions ::argv0 $options "Bad option"] 
############################################################## 
# 
# liefert eine Liste mit Knotennamen und entsprechenden Knoten-IDs 
Anzahl für Designnamen, die dem Musterargument entsprechen. 
Anzahl Jedes Muster, das nicht mit den Namen im Design übereinstimmt, hat ein 
Anzahl der leeren Liste zurückgegeben 
# Beispiel: Geben Sie "reset" (Zurücksetzen) durch und holen Sie sich { reset 3 } zurück. 
# 
############################################################## 
proc get_node_ids { pattern } { 
   Array-Set name_to_node [Liste] 

wenn { [string equal "" $pattern] } { 
      Zurücksende [Liste] 
   }

# Ist das Muster tatsächlich der Name einer Zeitgruppe? 
   Anzahl, wenn ja, dann werden die Mitglieder des Skripts rekursiv von 
   Anzahl der Zeitgruppe. 
   Mitglieder festlegen [get_all_global_assignments -name TIMEGROUP_MEMBER -section_id $pattern] 

Anzahl, wenn Mitglieder der Sammlung vorhanden sind, 
   # das Muster ist eine Zeitgruppe 
   wenn { 0 < [get_collection_size $members]} { 
      # Warnen Sie, ob es Ausschlüsse gibt, weil das Skript 
      Anzahl übersprungen Ausschlüsse 
      wenn {0 < [get_collection_size [get_all_global_assignments -name TIMEGROUP_EXCLUSION -section_id $pattern]] } { 
         post_message-Typ mit der Warnung "Ausschlüsse in Timegroup-$pattern" 
      } 

# Gehen Sie durch jedes Element in der Zeitgruppe. 
      foreach_in_collection Zuweisung $members { 
         Anzahl Jedes Element in der Sammlung ist eine Liste wie folgt: 
         Anzahl {$pattern} {TIMEGROUP_MEMBER} {node/real pattern} 
         Array Set sub_collection_names [get_node_ids [$assignment 2]] 

foreach node_name [Array-Namen sub_collection_names] { 
            setzen sie name_to_node($node_name) $sub_collection_names($node_name) 
         } 
      } 
   } else { 
      Anzahl: Es handelt sich nicht um eine Timegroup 
      Anzahl aller Timing-Knoten im Design iterieren, 
      Anzahl der Überprüfung, ob der Name mit dem angegebenen Muster übereinstimmt 
      foreach_in_collection node_id [get_timing_nodes -type all] { 
         setzen Sie node_name [get_timing_node_info -info name $node_id] 
         wenn { [string match [escape_brackets $pattern] $node_name] } { 
            name_to_node($node_name) $node_id festlegen 
         } 
      } 
   } 
   return [Array get name_to_node]
} 

############################################################## 
# 
# Dieses Verfahren findet Kombinationspfade zwischen einer Quelle 
Anzahl Knoten und eine Liste der Zielknoten. Es gibt eine Liste von 
Anzahl der Pfade zwischen den Knoten. Jeder Pfad besteht aus einem Dreifache 
Anzahl der Knoten-ID sowie Verbindungsverzögerung und Zellenverzögerung aus dem 
Anzahl vorheriger Knoten. 
# Das Verfahren beendet das Durchlaufen der Netliste in einem Register 
Anzahl oder Pin, damit es keine Pfade findet, die durch Register gehen. 
#
############################################################## 
proc find_combinational_paths_between {queue dest_nodes} { 
   num_iterations 0 festlegen 
   Pfade festlegen [Liste] 
   
während {0 < [llength $queue]} { 
      Anzahl Bericht über den Fortschritt der Schleife im Tausendfachen 
      Anzahl der Iterationen incr num_iterations 
      wenn { 1000 == $num_iterations } { 
         num_iterations 0 festlegen 
         post_message "Die Pfade [llength $queue] werden überprüft." 
      } 
      
# Geben Sie den ersten Pfad aus der Warteschlange ein. 
      # Beim ersten Mal, wenn das Verfahren aufgerufen wird, wird die Warteschlange 
      # ist nur eine Zahl, der Quellknoten. 
      Set Path [$queue 0] 
      set queue [lrange $queue 1 End] 
      
# Holen Sie sich den letzten Knoten im Pfad und dann in der Foreach-Schleife 
      Anzahl der Fanout-Belegung von diesem Knoten 
      set last_triplet_in_path [$path End] 
      set last_node_in_path [$last_triplet_in_path 0] 
 
# Extrahieren Sie nur die Knoten-IDs im aktuellen Pfad. 
      # Dies wird später verwendet, um sicherzustellen, dass Keine Schleifen durchlaufen werden. 
      nodes_in_path festlegen [collapse_triplets_to_node_list $path] 

# Holen Sie sich alle Fanouts des letzten Knotens in diesem Pfad und erstellen Sie 
      # neue Pfade mit ihnen, um die Warteschlange zu verschieben. 
      foreach n [get_timing_node_fanout $last_node_in_path] { 
         foreach { node_id ic_delay cell_delay } $n { 
            Brechen 
         }
 
wenn { -1 != [lsearch $dest_nodes $node_id] } { 
            Anzahl, wenn sich dieser Knoten im Pfad in der Liste befindet 
            Anzahl der Zielknoten, es gibt einen Pfad. 
            Anzahl Hinzufügen zur Liste der Pfade zwischen den Knoten 
            new_path $path Lappend einstellen 
            new_path $n 
            Lappend-Pfade $new_path 
         } 

wenn { -1 == [lsearch $nodes_in_path $node_id] } { 
            Anzahl, wenn sich dieser Knoten im Pfad nicht im Pfad befindet 
            # bereits, dies ist keine Schleife. Schieben Sie es auf die 
            Anzahl Warteschlange, wenn es sich um einen Kombinations- oder Taktknoten handelt. 
            # Der Pfad wird nicht gedrückt, wenn es sich bei diesem Knoten um einen 
            Anzahl registrieren oder fix. 
            # So einen neuen Pfad in der Warteschlange verschieben, 
            Anzahl, selbst wenn dieser Knoten im Pfad möglicherweise übereinstimmt 
            Anzahl eines Endknotens, sorgt für eine möglichst lange Zeit 
            Anzahl der Pfade gefunden. 
            setzen Sie node_type [get_timing_node_info -info-Typ $node_id] 
            switch -exact -- $node_type { 
               " "" (nicht mehr) – 
               CLK { 
                  next_path $path festlegen 
                  Lappend-next_path $n 
                  lappend Warteschlange $next_path 
               } 
               Standard { 
               } 
            } 
         } 
      }
   }
   $paths zurücksende 
} 

############################################################## 
# 
# Fügt zwei Verzögerungsnummern hinzu und gibt das Ergebnis zurück. 
Anzahl Verzögerungsnummern sind im Formular "Werteinheiten", bei denen Einheiten 
Anzahl kann Nanosekunden (ns) oderOsekunden (ps) sein, und der Wert kann 
Anzahl x{1,3} sein, wenn es sich bei den Einheiten um 1,3} oder x+.y{1,3} handelt, wenn die 
Anzahl der Einheiten sind Nanosekunden. Bei diesem Verfahren kommen Verzögerungen zu 
Anzahl Nanosekunden und fügt die Werte hinzu. 
Beispiel: add_delays "1.234 ns" "56 ps" # 
############################################################## 
proc add_delays { a b } { 
   wenn { ![ regexp {^([\d\.] +)\s+([np]s)$} $a Match a_value a_unit] } { 
      post_message -Typ-Fehler "Teile der Zeit konnte nicht bestimmt werden: $a" 
   } 

wenn { ![ regexp {^([\d\.] +)\s+([np]s)$} $b Match b_value b_unit] } { 
      post_message Fehler "Teile der Zeit konnte nicht bestimmt werden: $b" 
   } 
  
Anzahl der Konvertierung aller Dinge in Nanosekunden, falls erforderlich 
   wenn { [string equal -nocase ps $a_unit] } { 
      setzen Sie a_value_ps [Format "%.3f" $a_value] 
      setzen sie a_value [Format "%.3f" [expr { $a_value_ps / 1000 }]] 
   } 

wenn { [string equal -nocase ps $b_unit] } { 
      setzen Sie b_value_ps [Format "%.3f" $b_value] 
      setzen sie b_value [Format "%.3f" [expr { $b_value_ps / 1000 }]] 
   } 

Anzahl der Einheiten ist jetzt gleich und Nanosekunden. 
   # Fügen Sie einfach die Zahlen zusammen. 
   setzen Sie sum_value [Format "%.3f" [expr { $a_value + $b_value }]] 
  
rückgabe "$sum_value ns" 
} 

############################################################## 
# 
Anzahl der Formate und Anzahl der Knotennamen im Pfad mit dem  
Anzahl der Verzögerungen zwischen den Knoten. 
# 
############################################################## 
proc print_path_delays { path {iteration first}} { 
   source_triplet einstellen [$path 0] 
   set source_node [$source_triplet 0] 
   setzen Sie source_node_name [get_timing_node_info -info-Name $source_node] 
   stellen Sie source_node_loc [get_timing_node_info -info location $source_node] ein. 
   
Anzahl der Verzögerungen zuerst ausdrucken 
   wenn { [String gleich "first" $iteration] } { 
      accumulate_data [Liste "IC(0.000 ns)" "CELL(0.000 ns)"] 
   } else { 
      set ic_delay [$source_triplet 1] 
      set cell_delay [$source_triplet 2] 
      accumulate_data [Liste "IC($ic_delay)" "CELL($cell_delay)"] 
   } 
   accumulate_data [Liste $source_node_loc $source_node_name] 
   print_accumulated_data 

Anzahl auf dem rest des Pfades rekursionieren 
   wenn { 1 < [llength $path] } { 
      print_path_delays [lrange $path 1 Ende] andere 
   } 
} 

############################################################## 
# 
Anzahl der IC- und Zellen-Verzögerungen auf dem angegebenen Pfad und 
# gibt eine Liste mit gesamter Verbindungsverzögerung und gesamter Zelle zurück 
Anzahl Der Verzögerung. 
# 
############################################################## 
proc end_to_end_delay { Path } { 
   setzen Sie ic_total "0,000 ns" 
   stellen Sie cell_total "0,000 ns" ein 
   
# Dies führt durch Knoten 1, um am Ende des Pfades zu enden, da die 
   Anzahl der ersten Knoten im Pfad ist die Quelle und jeder Knoten im 
   #path enthält die Verzögerungen vom Knoten, der den Knoten unterstützt. Das 
   #source hat keinen Knoten, was zu Verzögerungen kommt. 
   foreach n [lrange $path 1 Ende] { 
      foreach { node_id ic_delay cell_delay } $n { 
         Brechen 
      } 
      setzen Sie ic_total [add_delays $ic_total $ic_delay] 
      setzen Sie cell_total [add_delays $cell_total $cell_delay] 
   } 

rückgabe [list $ic_total $cell_total] 
} 

##############################################################
# 
# Stellt sicher, dass die angegebene Quelle und die ziele in der 
# design, ermittelt die Kombinationspfade zwischen ihnen und 
Anzahl der Pfade. 
# 
############################################################## 
proc find_paths_and_display { source dest } { 
   Array-Set-Quellen [get_node_ids $source] 
   Array Set Dests [get_node_ids $dest] 

nodes_exist 1 festlegen 

# Stellen Sie sicher, dass die genannten Knoten vorhanden sind 
   wenn { 0 == [llength [array get sources]] } { 
      nodes_exist 0 festlegen 
      post_message -Typfehler "In Ihrem Design wurden keine knotengleichen $source gefunden." 
   } 
   wenn { 0 == [llength [array get dests]] } { 
      nodes_exist 0 festlegen 
      post_message Fehler "Es wurden keine Knoten gefunden, die $dest in Ihrem Design übereinstimmen." 
   } 

# Wenn ja, suchen Sie nach Pfaden.   wenn { $nodes_exist } { 
      Anzahl Holen Sie sich die Liste der Zielknoten-ID 
      dest_node_ids festlegen [Liste] 
      foreach d [array names dests] { 
         lappend dest_node_ids $dests($d) 
      } 

Anzahl der Schritte durch alle Knoten 
      foreach s [array names sources] { 
         Pfade festlegen [find_combinational_paths_between $sources($s) $dest_node_ids] 
         wenn { 0 == [llength $paths] } {  
            post_message "Von $s bis $dest gibt es keinen Kombinationspfad" 
         } else { 
            Foreach-Pfad $paths { 
               Anzahl drucken Sie den Pfad aus 
               print_path_delays $path 

Anzahl der Verbindungs- und Zellenverzögerungen und 
               # drucken Sie sie unter dem Pfad aus. 
               foreach {total_ic_delay total_cell_delay } [end_to_end_delay $path] { 
                  Brechen 
               } 
               accumulate_data [listet $total_ic_delay $total_cell_delay] 
               accumulate_data [Liste [add_delays $total_ic_delay $total_cell_delay]] 

Anzahl der Anrufe bei print_accumulated_data 
               Anzahl hier, eine zum Drucken der Summen der Verbindungen 
               Anzahl- und Zellenverzögerungen und einer zum Generieren eines Leeren 
               Anzahl der Zeile in der Ausgabe. 
               print_accumulated_data print_accumulated_data 
            } 
         } 
      }
   } 
} 

############################################################## 
# 
# Ein Pfad besteht aus Tripmen von Informationen – Knoten-ID, 
Anzahl der Verbindungsverzögerung und Zellenverzögerung. Dieses Verfahren wird extrahiert 
Anzahl der Knoten-ID aus jedem Triplet in der Reihenfolge und gibt eine Liste zurück 
Anzahl der Knoten-IDS 
# 
############################################################## 
proc collapse_triplets_to_node_list { l } { 
   to_return festlegen [Liste] 
   Foreach-Triplet-$l { 
      lappend to_return [$triplet 0] 
   } 
   rückgabe $to_return 
} 

############################################################## 
# 
# Verkettung von Informationen zu einer globalen Variable in der Vorbereitung 
Anzahl für den Ausgedruckten. 
# 
############################################################## 
proc accumulate_data { data } { 
   globales", "verschwenkungsverbinder"-Set [Concat $accum $data] 
}
 
############################################################## 
# 
Anzahl drucken Sie die gesammelten Daten aus. 
Nr. Es wird standardmäßig ausgedruckt und optional in eine Datei ein 
Anzahl CSV-Format, wenn das Datei-Handle vorhanden ist, und optional in ein 
Anzahl des Berichtsfensters, wenn das Berichtfenster vorhanden ist (kein Wert von -1) 
# 
############################################################## 
proc print_accumulated_data {} { 
   Globale panel_id 
   setzt [join $accum ","] 

# Schreiben Sie es in eine Datei? 
   wenn { [Info vorhanden fh] } { 
      setzt $fh [join $accum "," ] 
   } 

Anzahl Hinzufügen zum Berichtfenster? 
   wenn { -1 != $panel_id } { 
      Anzahl, wenn die Berichtbedienfeldreihe nicht über 4 Elemente hat 
      Anzahl darin, pad es auf 4. 
      während { 4 > [llength $accum] } { 
         lappend [Liste] 
      } 
      add_row_to_table -id $panel_id $accum 
   } 
   Anzahl Löschen Sie die Informationen in der globalen Variable. 
   einstellen [Liste] 
}

############################################################## 
############################################################## 
# 
Anzahl Ende der Verfahren, Beginn des Skripts 
# 
############################################################## 
##############################################################
# 
Anzahl globaler Variablen, die Daten zum Drucken speichern, und das Panel 
Anzahl-ID für einen optionalen Berichtbereich 

einstellen [Liste] 
panel_id -1 einstellen 

wenn { [string equal "" $opts(project)] } { 
   Anzahl der Nutzungsoptionen drucken, wenn das Skript ohne aufgerufen wird 
   Anzahl der Behauptungen 
   setzt [::cmdline::usage $options] 
} elseif { [string equal "" $opts(project)] } { 
   post_message -type error (Projekt mit der Option -project angeben) ein. 
} elseif { ! [project_exists $opts(Projekt)] } { 
   post_message -type error (Projekt $opts(Projekt) ist in diesem Verzeichnis nicht vorhanden." 
} elseif { [string equal "" $opts(from)] } { 
   post_message -type error (Geben Sie mit der Option -from einen Namen oder ein Platzhaltermuster an.) 
} elseif { [string equal "" $opts(to)] } { 
   post_message -geben Sie den Fehler "Geben Sie mit der Option -to einen Namen oder ein Platzhaltermuster an." 
} else { 
   festlegen cur_revision [get_current_revision $opts(Projekt)] 
   project_open $opts (Projekt) – Revision $cur_revision 

# Versuchen Sie, die Timing-Netliste zu erstellen. Dieser Befehl würde ausfallen 
   Anzahl, wenn z. B. quartus_fit noch nicht ausgeführt wurde. 
   wenn { [catch { create_timing_netlist } msg ] } { 
      fehler post_message (Fehlertyp) $msg 
   } else { 

# Bereiten Sie sich darauf vor, die Ausgabe falls erforderlich in eine Datei zu schreiben 
      wenn { 1 == $opts(write_file) } { 
         wenn { [catch {open $opts(file) w} fh] } { 
            post_message -Typfehler "Konnte $opts(write_file) nicht öffnen): $fh" wurde nicht angezeigt fh 
         } else { 
            post_message "Ausgabe in $opts(Datei)schreiben" 
            # Fügen Sie zur Ausgabedatei einige einführende Informationen hinzu 
            setzt $fh "Bericht über Pfade von $opts(von) zu $opts(zu)" 
            setzt $fh "Generiert auf [Taktformat [Taktsekunden]]" 
            setzt $fh "" setzt $fh "IC-Verzögerung,Zellenverzögerung,Knotenstandort,Knotenname" 
         } 
      } 

# Bereiten Sie sich darauf vor, die Ausgabe falls erforderlich in ein Berichtfenster zu schreiben 
      wenn { 1 == $opts(write_panel) } { 
         # Laden Sie den Bericht, löschen Sie das Bedienfeld, falls er bereits vorhanden ist. 
         Erstellen Sie ein neues Bedienfeld und fügen Sie die Überschriftenzeile hinzu. 
         load_report 
         setzen Sie panel_id [get_report_panel_id "Timing Analyzer|| $opts(Panel)"] 
         wenn { -1 != $panel_id } { 
            delete_report_panel -id $panel_id 
         } 
        setzen Sie panel_id [create_report_panel -Tabelle "Timing Analyzer|| $opts(Panel)"] 
        add_row_to_table -id $panel_id [Liste "IC-Verzögerung" "Zellenverzögerung" "Knotenstandort" "Knotenname"] 
      } 
      find_paths_and_display $opts(von) $opts(zu) 

Anzahl schließen Sie ggf. die Ausgabedatei 
      wenn { [info exists fh] } { close $fh } 

Anzahl Speichern Sie ggf. das Berichtfenster. 
      wenn { -1 != $panel_id } { 
         save_report_database 
         unload_report 
      } 
   } 
   project_close 
}    

Der Inhalt dieser Seite ist eine Kombination aus menschlicher und computerbasierter Übersetzung des originalen, englischsprachigen Inhalts. Dieser Inhalt wird zum besseren Verständnis und nur zur allgemeinen Information bereitgestellt und sollte nicht als vollständig oder fehlerfrei betrachtet werden. Sollte eine Diskrepanz zwischen der englischsprachigen Version dieser Seite und der Übersetzung auftreten, gilt die englische Version. Englische Version dieser Seite anzeigen.