Questo esempio di progettazione mostra una procedura personalizzata, che è possibile utilizzare nei file SDC, che restituisce un elenco di tutti i clock che alimentano un pin. La procedura può essere utile se è necessario creare clock generati senza conoscere altri nomi di clock in un progetto. L'esempio di progettazione Semplifica il riutilizzo della progettazione con vincoli SDC dinamici fornisce maggiori dettagli e un esempio di come utilizzare la procedura personalizzata descritta in questa pagina.
Il codice completo della procedura è nella parte inferiore della pagina, seguendo una spiegazione completa del funzionamento della procedura. Per utilizzare la procedura personalizzata get_clocks_driving_pins in un file SDC, assicurarsi che la procedura sia stata definita, quindi chiamarla come qualsiasi altro comando SDC. Esistono due modi semplici per garantire che la procedura sia stata definita prima dell'uso:
- Salvare il codice di procedura in un file SDC separato e includere il file SDC nel progetto.
- Copiare e incollare il codice di procedura nella parte superiore di qualsiasi file SDC, prima che venga utilizzata la procedura personalizzata get_clocks_driving_pins.
File SDC separato
Il salvataggio del codice di procedura in un file SDC separato mantiene il codice separato dal resto dei vincoli e rende più semplice il riutilizzo in altri progetti. Se si utilizza un file SDC separato, è necessario aggiungere il file SDC con la procedura all'elenco dei file nel progetto e deve apparire sopra tutti i file SDC che utilizzano la procedura. Elencarlo sopra altri file SDC assicura che il software Quartus® II definisca la procedura prima di utilizzarla, ogni volta che vengono letti i file SDC.
Copiare e incollare
La copia e l'incolla del codice di procedura nello stesso file SDC in cui viene utilizzato comporta un minor numero di file SDC in un progetto. Se si sta creando un file SDC per un modulo che verrà riutilizzato da altri progettisti, potrebbe essere più semplice includere tutti i vincoli e il codice di supporto in un singolo file SDC. È necessario includere il codice di procedura nel file SDC prima del primo utilizzo della procedura in modo che sia definito prima dell'utilizzo. In genere, lo si mette nella parte superiore del file per soddisfare questo requisito.
Operazione script
Ottenere un elenco di tutti gli orologi in un design che alimenta un pin richiede tre passaggi principali:
- Ottieni tutti i clock e crea una mappatura dai loro nodi di destinazione ai clock sui nodi di destinazione.
- Ottieni un elenco di nodi con clock su di essi che si trovano sul percorso della ventola al pin specificato.
- Da quell'elenco di nodi, trovare il nodo più vicino al pin specificato e restituire i clock su quel nodo.
Passaggio 1. Ottieni tutti i clock e crea mappatura
Il seguente codice Tcl ottiene tutti i clock nella progettazione e crea il mapping (con un array Tcl) da un nodo ai clock sul nodo.
catch { array unset nodes_with_clocks } array set nodes_with_clocks [list] # Iterate over each clock in the design foreach_in_collection clock_id [all_clocks] { set clock_name [get_clock_info -name $clock_id] # Ogni clock viene applicato ai nodi. Ottieni la raccolta di nodi di destinazione foreach_in_collection target_id [get_clock_info -targets $clock_id] { # Associare il nome del clock al relativo nodo di destinazione impostato target_name [get_node_info -name $target_id] nodes_with_clocks($target_name) $clock_name } }
I clock virtuali non hanno obiettivi, quindi non viene mai effettuata alcuna mappatura con un clock virtuale. Nel codice di procedura completo elencato di seguito, le informazioni sul tipo di nodi di destinazione (registro, pin, cella o porta) vengono salvate per un utilizzo successivo.
Passaggio 2. Ottieni nodi con clock nel percorso fanin
Il secondo passo è trovare il sottoinsieme di nodi con clock che si trovano sul percorso fanin del pin specificato. Per ciascun nodo con clock (trovato nel passaggio 1), portare la ventola al pin specificato tramite il nodo. Se è presente una ventola, il nodo si trova nel percorso della ventola al pin. Se non c'è ventola, il nodo non è sul percorso della ventola del pin.
Il seguente codice Tcl scorre tutti i nodi con clock dal passaggio 1 e utilizza il comando get_fanins per determinare se ciascun nodo si trova sul percorso fanin del pin specificato. Se il nodo si trova sul percorso fanin del pin specificato, il nodo viene salvato nell'elenco pin_drivers.
impostare pin_drivers [elenco] # Iterate su tutti i nodi nel mapping creato nel passaggio 1 foreach node_with_clocks [nomi di array nodes_with_clocks] { # Ottieni qualsiasi ventola sul pin specificato tramite il nodo corrente impostato fanin_col [get_fanins -clock -through $node_with_clock $pin_name] # Se è presente almeno un nodo fanin, il nodo corrente si trova sul percorso # fanin del pin specificato, quindi salvarlo. if { 0 < [get_collection_size $fanin_col] } { lappend pin_drivers $node_with_clocks } }
Il codice di procedura completo elencato di seguito utilizza ulteriori informazioni sul tipo di nodo per specificare una raccolta specifica del tipo per il valore -through nel comando get_fanins.
Passaggio 3. Trova il nodo più vicino al pin specificato
La variabile pin_drivers ora ha un elenco di tutti i nodi con clock che si trovano sul percorso fanin del pin specificato. Questo passaggio trova il nodo più vicino al pin specificato. Sebbene nell'elenco pin_drivers sia presente più di un nodo, il codice prende i primi due nodi nell'elenco e verifica se uno è sul percorso della ventola rispetto all'altro. Se si trova sul percorso della ventola, il primo nodo deve essere più lontano dal pin rispetto al secondo nodo, in modo che possa essere rimosso dall'elenco.
while { 1 < [llength $pin_drivers] } { # Ottieni i primi due nodi nell'elenco pin_drivers impostato node_a [lindex $pin_drivers 0] impostato node_b [lindex $pin _drivers 1] # Verificare se node_b si trova sul percorso fanin di node_a impostato fanin_col [get_fanins -clock -through $node_b $node_a] # Se è presente almeno un nodo fanin, node_b deve essere più distante dal pin specificato rispetto a node_a. # Se non c'è alcun nodo fanin, node_b deve essere più vicino al pin # specificato di node_a. se { 0 < [get_collection_size] } { # node_a è più vicino al pin. # Rimuovere node_b dall'elenco pin_drivers impostato pin_drivers [lreplace $pin_drivers 1 1] } altrimenti { # node_b è più vicino al pin. # Rimuovi node_a dall'elenco pin_drivers impostato pin_drivers [lreplace $pin_drivers 0] } } } # L'unico nodo rimasto in pin_drivers è il nodo che guida il set di pin specificato node_driving_pin [lindex $pin_drivers 0] # Cerca i clock sul nodo nel mapping dal passaggio 1 e restituiscili $nodes_with_clocks($node_driving_pin
Il codice di procedura completo elencato di seguito utilizza informazioni aggiuntive sul tipo di nodo per specificare una raccolta specifica del tipo per il valore -through nel comando get_fanins.
Codice di procedura completo
Il codice completo per la procedura personalizzata get_clocks_driving_pin è elencato di seguito. Include ulteriori funzionalità di controllo degli errori e supporto che non sono descritte nei dettagli sopra.
proc get_clocks_feeding_pin { pin_name } { # Prima del passaggio 1, eseguire un controllo di errore per assicurarsi che pin_name # passato alla procedura corrisponda a un solo pin. # Restituire un errore se non corrisponde a un solo pin. set pin_col [get_pins -compatibility_mode $pin_name] se { 0 == [get_collection_size $pin_col] } { return -code error "No pins match $pin_name" } elseif { 1 < [get_collection_size $pin_col] } { return -code error "$pin_name matches [get_collection_size $pin_col]\ pin ma deve corrispondere solo a uno" } # Inizializza le variabili utilizzate nella procedura catch { array unset nodes_with_clocks } catch { array unset node_types } set di array nodes_with_clocks [list] set di array node_types [elenco] impostato pin_drivers [elenco] # Passaggio 1. Ottieni tutti i clock nella progettazione e crea un mapping dai nodi di destinazione ai clock sui nodi di destinazione # Iterate su ogni clock nella progettazione foreach_in_collection clock_id [all_clocks] { impostare clock_name [get_clock_info -name $clock_id] impostato clock_target_col [get_clock_info -targets $clock_id] # Ogni clock viene applicato ai nodi. Ottieni la raccolta di nodi di destinazione foreach_in_collection target_id [get_clock_info -targets $clock_id] { # Associare il nome del clock al relativo nodo di destinazione impostato target_name nodes_with_clocks($target $target) [get_node_info -name $target_id] nome_) $clock_name # Salvare il tipo di nodo di destinazione per l'uso successivo impostato target_type [get_node_info -type $target_id] impostato node_types($target_name) $target_type } } # Passaggio 2. Ottieni un elenco di nodi con clock su di essi che si trovano sul percorso # fanin del pin specificato # Iterate su tutti i nodi nel mapping creato nel passaggio 1 foreach node_with_clocks [nomi di array nodes_with_clocks] { # Utilizza il tipo del nodo di destinazione per creare una raccolta di numeri specifica del tipo per il valore -through nel comando get_fanins. switch -exact -- $node_types($node_with_clocks) { "pin" { set through_col [get_pins $node_with_clocks] } "port" { set through_col [get_ports $node_with_clocks] } "cell" { set through_col [get_cells $node_with_clocks] } "reg" { set through_col [get_registers $node_with_clocks] } default { return -code error "$node_types($node_with_clocks) non è gestito\ come tipo fanin dallo script" } } # Ottieni tutte le ventola sul pin specificato tramite il nodo corrente impostato fanin_col [get_fanins -clock -through $through_col $pin_name] # Se è presente almeno un nodo fanin, il nodo corrente si trova sul percorso # fanin del pin specificato, quindi salvalo. se { 0 < [get_collection_size $fanin_col] } { lappend pin_drivers $node_with_clocks } } # Prima del passaggio 3, eseguire un controllo di errore per assicurarsi che almeno un numero di nodi con clock nella progettazione sia sul percorso fanin per # il pin specificato. if { 0 == [llength $pin_drivers] } { return -code error "Impossibile trovare alcun nodo con clock che unità $pin_name" } # Passaggio 3. Dall'elenco dei nodi creati nel passaggio 2, trovare il nodo #più vicino al pin specificato e restituire i clock su quel nodo. while { 1 < [llength $pin_drivers] } { # Ottieni i primi due nodi nell'elenco pin_drivers impostato node_a [lindex $pin_drivers 0] impostato node_b [lindex $pin_drivers 1] # Utilizzare il tipo del nodo di destinazione per creare un insieme di numeri specifico del tipo per il valore -through nel comando get_fanins. switch -exact -- $node_types($node_b) { "pin" { set through_col [get_pins $node_b] } "port" { set through_col [get_ports $node_b] } "cell" { set through_col [get_cells $node_b] } "reg" { set through_col [get_registers $node_b] } default { return -code error "$node_types($node_b) non è gestito\ come tipo fanin dallo script" } } # Verificare se node_b si trova sul percorso fanin di node_a set fanin_col [get_fanins -clock -through $through_col $node_a] # Se è presente almeno un nodo fanin, node_b deve essere più lontano dal pin specificato rispetto a node_a. # Se non c'è alcun nodo fanin, node_b deve essere più vicino al pin # specificato di node_a. se { 0 < [get_collection_size $fanin_col] } { # node_a è più vicino al pin. # Rimuovi node_b dall'elenco pin_drivers impostato pin_drivers [lreplace $pin_drivers 1 1] } else { # node_b è più vicino al pin # Rimuovi node_a dall'elenco pin_drivers impostato pin_drivers [lrange $pin_drivers 1 end] } } # L'unico nodo rimasto in pin_drivers è il nodo che guida il set di pin specificato node_driving_pin [lindex $pin_drivers 0] # Cerca i clock sul nodo nel mapping dal passaggio 1 e restituire $nodes_with_clocks ($node_driving_pin) }