Este exemplo de design mostra um procedimento personalizado, que você pode usar em arquivos SDC, que devolve uma lista de todos os clocks que alimentam um pino. O procedimento pode ser útil se você precisar criar clocks gerados sem saber outros nomes de clock em um design. O exemplo de design simplificado de reutilização com restrições dinâmicas de SDC fornece mais detalhes e um exemplo de como usar o procedimento personalizado descrito nesta página.
O código completo para o procedimento está na parte inferior da página, seguindo uma explicação completa de como o procedimento funciona. Para usar o procedimento get_clocks_driving_pins personalizado em um arquivo SDC, certifique-se de que o procedimento foi definido e depois o chame como qualquer outro comando SDC. Há duas maneiras fáceis de garantir que o procedimento foi definido antes do uso:
- Salve o código de procedimento em um arquivo SDC separado e inclua o arquivo SDC no projeto.
- Copie e colar o código de procedimento na parte superior de qualquer arquivo SDC, antes que o procedimento get_clocks_driving_pins personalizado seja usado.
Arquivo SDC separado
Salvar o código de procedimento em um arquivo SDC separado mantém o código separado do resto de suas restrições e facilita a reutilização em outros projetos. Se você usar um arquivo SDC separado, você deve adicionar o arquivo SDC com o procedimento à lista de arquivos do projeto, e ele deve aparecer acima de qualquer arquivo SDC que utilize o procedimento. Listá-lo acima de outros arquivos SDC garante que o software Quartus® II define o procedimento antes de usá-lo, sempre que os arquivos SDC são lidos.
Copiar e colar
Copiar e colar o código de procedimento no mesmo arquivo SDC em que ele é usado resulta em menos arquivos SDC em um projeto. Se você estiver criando um arquivo SDC para um módulo que será reutilizado por outros designers, pode ser mais simples incluir todas as restrições e código de suporte em um único arquivo SDC. Você deve incluir o código de procedimento no arquivo SDC antes do primeiro uso do procedimento para que ele seja definido antes do uso. Normalmente, você o colocaria no topo do arquivo para atender a esse requisito.
Operação de script
Obter uma lista de todos os clocks em um design que alimenta um pino leva três etapas principais:
- Obtenha todos os clocks e crie um mapeamento de seus nós de destino para os clocks nos nós de destino.
- Obtenha uma lista de nós com clocks neles que estão no caminho do fanin para o pino especificado.
- A partir desta lista de nós, encontre o nó mais próximo do pino especificado e devolva os clocks nesse nó.
Passo 1. Obtenha todos os clocks e crie mapeamento
O código Tcl a seguir obtém todos os clocks no design e cria o mapeamento (com uma matriz Tcl) de um nó para os clocks no nó.
catch { array unset nodes_with_clocks } conjunto de matriz nodes_with_clocks [lista] # Iterar sobre cada clock no design foreach_in_collection clock_id [all_clocks] { definir clock_name [get_clock_info -name $clock_id] # Cada clock é aplicado a nós. Obtenha a coleção de nós de destino foreach_in_collection target_id [get_clock_info-targets $clock_id] { # Associo o nome do clock com seu conjunto de nó de destino target_name [get_node_info -name $target_id] lappend nodes_with_clocks($target_name) $clock_name } }
Os clocks virtuais não têm alvos, portanto, nenhum mapeamento é feito com um relógio virtual. No código de procedimento completo listado abaixo, as informações sobre o tipo de nós de destino (registro, pino, célula ou porta) são salvas para uso posterior.
Passo 2. Obtenha nós com clocks no caminho de fanin
A segunda etapa é encontrar o subconjunto de nós com clocks que estão no caminho do fanin para o pino especificado. Para cada nó com clocks (encontrados na etapa 1), obtenha a fanin para o pino especificado através do nó. Se houver uma fanin, o nó está no caminho de fanin para o pino. Se não houver fanin, o nó não está no caminho de fanin para o pino.
O código Tcl a seguir itera em todos os nós com clocks da etapa 1 e usa o comando get_fanins para determinar se cada nó está no caminho de fanin do pino especificado. Se o nó estiver no caminho de fanin do pino especificado, o nó será salvo na pin_drivers lista.
set pin_drivers [list] # Iterate sobre todos os nós no mapeamento criado na etapa 1 foreach node_with_clocks [nomes de matriz nodes_with_clocks] { # Obtenha quaisquer fanins para o pino especificado através do conjunto de nó atual fanin_col [get_fanins -clock -através de $node_with_clock $pin_name] # Se houver pelo menos um nó de fanin, o nó atual está no caminho de fanin # para o pino especificado, então salve-o. se { 0 < [get_collection_size $fanin_col] } { lappend pin_drivers $node_with_clocks } } }
O código de procedimento completo listado abaixo usa informações adicionais sobre o tipo de nó para especificar uma coleção específica do tipo para o valor -através no comando get_fanins.
Passo 3. Encontre o nó mais próximo do pino especificado
A pin_drivers agora tem uma lista de todos os nós com clocks que estão no caminho do fanin para o pino especificado. Esta etapa encontra o nó mais próximo do pino especificado. Embora haja mais de um nó na lista pin_drivers, o código pega os dois primeiros nós da lista e verifica se um está no caminho do fanin para o outro. Se estiver no caminho de fanin, o primeiro nó deve estar mais longe do pino do que o segundo nó, para que ele possa ser removido da lista.
enquanto { 1 < [llength $pin_drivers] } { # Obtenha os dois primeiros nós no conjunto de listas pin_drivers node_a [lindex $pin_drivers 0] definido node_b [lindex $pin_drivers 1] # Verifique se o node_b está no caminho de fanin do node_a set fanin_col [get_fanins -clock -through $node_b $node_a] # Se houver pelo menos um nó de fanin, node_b deve estar mais longe do pino especificado do que node_a está. # Se não houver nó de fanin, node_b deve estar mais próximo do pino # especificado do que node_a é. se { 0 < [get_collection_size] } { # node_a está mais perto do pino. # Remova node_b da lista pin_drivers conjunto pin_drivers [lreplace $pin_drivers 1 1] } outra { # node_b está mais perto do pino. # Remova node_a do conjunto de listas pin_drivers pin_drivers [lreplace $pin_drivers 0 0 0] } } # O nó deixado em pin_drivers é o nó que conduz o conjunto de pinos especificado node_driving_pin [lindex $pin_drivers 0] # Procure os clocks no nó no mapeamento da etapa 1 e devolva-os de volta $nodes_with_clocks($node_driving_pin_pin
O código de procedimento completo listado abaixo usa informações adicionais sobre o tipo de nó para especificar uma coleção específica do tipo para o valor -através no comando get_fanins.
Código completo do procedimento
O código completo do procedimento get_clocks_driving_pin personalizado está listado abaixo. Ele inclui recursos adicionais de verificação de erros e suporte que não são descritos em detalhes acima.
proc get_clocks_feeding_pin { pin_name } { # Antes da etapa 1, execute uma verificação de erro para garantir que pin_name # passado para o procedimento corresponda a um e apenas um pino. # Devolva um erro se ele não corresponder a um e apenas um pino. definir pin_col [get_pins -compatibility_mode $pin_name] se { 0 == [get_collection_size $pin_col] } { erro de código de devolução "Nenhum pino corresponde $pin_name" } elseif { 1 < [get_collection_size $pin_col] } { erro de código de devolução "$pin_name matches [get_collection_size $pin_col]\ pinos, mas deve corresponder a apenas um" } # Inicializar variáveis usadas na captura do procedimento { array unset nodes_with_clocks } catch { array unset node_types } conjunto de matrizes nodes_with_clocks [lista] conjunto de matriz node_types [lista] definido pin_drivers [lista] # Etapa 1. Obtenha todos os clocks no design e crie um mapeamento de #os nós de destino para os clocks nos nós de destino # Iterate em cada clock no design foreach_in_collection clock_id [all_clocks] { definir clock_name [get_clock_info-name $clock_id] definido clock_target_col [get_clock_info-targets $clock_id] # Cada clock é aplicado a nós. Obtenha a coleção de nós de destino foreach_in_collection target_id [get_clock_info-targets $clock_id] { # Associo o nome do clock com seu conjunto de nó de destino target_name [get_node_info-name $target_id] lappend nodes_with_clocks(nodes_with_clocks $target_name) $clock_name # Salve o tipo do nó de destino para o conjunto de uso posterior target_type [get_node_info -type $target_id] definido node_types($target_name) $target_type } } Passo 2. Obtenha uma lista de nós com clocks neles que estão no caminho de fanin # para o pino especificado # Iterate sobre todos os nós no mapeamento criado na etapa 1 para cada node_with_clocks [nomes de matriz nodes_with_clocks] { # Use o tipo do nó de destino para criar uma coleção de nº específico do tipo para o valor -através no comando get_fanins. comutador -exact -- $node_types($node_with_clocks) { "pino" { definir through_col [get_pins $node_with_clocks] } "porta" { definir through_col [get_ports $node_with_clocks] } "célula" { definir through_col [get_cells $node_with_clocks] } "reg" { definir through_col [get_registers $node_with_clocks] } padrão { erro de código de devolução "$node_types($node_with_clocks) não é tratado\ como um tipo de fanin pelo script" } } # Obtenha quaisquer fanins para o pino especificado através do conjunto de nó atual fanin_col [get_fanins -clock -through $through_col $pin_name] # Se houver pelo menos um nó de fanin, o nó atual está no caminho #fanin para o pino especificado, então salve-o. se { 0 < [get_collection_size $fanin_col] } { lappend pin_drivers $node_with_clocks } } antes da etapa 3, execute uma verificação de erro para garantir que pelo menos um # dos nós com clocks no design está no caminho de fanin para # o pino especificado. se { 0 == [llength $pin_drivers] } { erro de código de devolução "Não é possível encontrar nenhum nó com clocks que conduzam $pin_name" } # Etapa 3. Na lista de nós criados na etapa 2, encontre o nó # mais próximo do pino especificado e devolva os clocks nesse nó. enquanto { 1 < [llength $pin_drivers] } { # Obtenha os dois primeiros nós no conjunto de listas pin_drivers node_a [lindex $pin_drivers 0] conjunto node_b [lindex $pin_drivers 1] # Use o tipo do nó de destino para criar uma coleção de #específica para o valor -através no comando get_fanins. comutador -exact -- $node_types($node_b) { "pino" { definir through_col [get_pins $node_b] } "porta" { definir through_col [get_ports $node_b] } "célula" { definir through_col [get_cells $node_b] } "reg" " {set through_col [get_registers $node_b] } padrão { erro de código de devolução "$node_types($node_b) não é tratado\ como um tipo de fanin pelo script" } } # Verifique se node_b está no caminho de fanin do node_a set fanin_col [get_fanins -clock -through $through_col $node_a] # Se houver pelo menos um nó de fanin, node_b deve estar mais longe do pino especificado do que node_a estiver. # Se não houver nó de fanin, node_b deve estar mais próximo do pino # especificado do que node_a é. se { 0 < [get_collection_size $fanin_col] } { # node_a está mais perto do pino. # Remova node_b do conjunto de listas pin_drivers pin_drivers [lreplace $pin_drivers 1 1] } outra { # node_b está mais perto do pino # Remova node_a do conjunto de listas pin_drivers pin_drivers [lrange $pin_drivers 1 end] } } # O nó deixado em pin_drivers é o nó que conduz o conjunto de pinos especificado node_driving_pin [lindex $pin_drivers 0] # Procure os clocks no nó no mapeamento da etapa 1 e devolvê-los $nodes_with_clocks($node_driving_pin) }