Lograr que los relojes desafilen un pin

author-image

Por

Este ejemplo de diseño muestra un procedimiento personalizado, que se puede utilizar en archivos SDC, que devuelve una lista de todos los relojes que alimentan un pin. El procedimiento puede ser útil si necesita crear relojes generados sin saber otros nombres de reloj en un diseño. El ejemplo de diseño Simplificar la reutilización del diseño con restricciones dinámicas de SDC proporciona más detalles y un ejemplo de cómo utilizar el procedimiento personalizado descrito en esta página.

El código completo del procedimiento se encuentra en la parte inferior de la página, siguiendo una explicación completa del funcionamiento del procedimiento. Para utilizar el get_clocks_driving_pins procedimiento personalizado en un archivo de SDC, asegúrese de que el procedimiento se haya definido y, a continuación, llámenos como cualquier otro comando de SDC. Hay dos maneras sencillas de garantizar que el procedimiento se haya definido antes de usarlo:

  • Guarde el código de procedimiento en un archivo de SDC independiente e incluya el archivo SDC en el proyecto.
  • Copie y pega el código de procedimiento en la parte superior de cualquier archivo SDC antes de utilizar el get_clocks_driving_pins procedimiento personalizado.

Archivo SDC separado

Guardar el código de procedimiento en un archivo SDC separado mantiene el código separado del resto de las restricciones y simplifica la reutilización en otros proyectos. Si utiliza un archivo SDC independiente, debe agregar el archivo SDC con el procedimiento a la lista de archivos del proyecto y debe aparecer por encima de cualquier archivo SDC que utilice el procedimiento. Enumerarlo arriba de otros archivos SDC garantiza que el software Quartus® II define el procedimiento antes de usarlo, cada vez que se leen archivos SDC.

Copiar y pasta

Si copia y pega el código de procedimiento en el mismo archivo SDC en el que se utiliza se obtienen menos archivos SDC en un proyecto. Si está creando un archivo SDC para un módulo que serán reutilizados por otros diseñadores, puede ser más sencillo incluir todas las restricciones y el código compatible en un solo archivo SDC. Debe incluir el código de procedimiento en el archivo SDC antes del primer uso del procedimiento, de modo que se defina antes de usarlo. Por lo general, la colocaría en la parte superior del archivo para satisfacer este requisito.

Funcionamiento del script

Obtener una lista de todos los relojes en un diseño que alimenta un pin toma tres pasos principales:

  1. Obtenga todos los relojes y cree una asignación de sus nodos de destino a los relojes en los nodos de destino.
  2. Obtenga una lista de nodos con relojes en ellos que se encuentran en la ruta de acceso del ventilador al pin especificado.
  3. En esa lista de nodos, encuentre el nodo más cercano al pin especificado y devuelva los relojes en ese nodo.

Paso 1. Obtenga todos los relojes y cree mapeos

El siguiente código Tcl obtiene todos los relojes en el diseño y crea el mapeo (con una matriz Tcl) de un nodo a los relojes en el nodo.

catch { array unset nodes_with_clocks }
array set nodes_with_clocks [list]

# Iteración en cada reloj en el diseño
foreach_in_collection clock_id [all_clocks] {

    set clock_name [get_clock_info -name $clock_id]

    # Cada reloj se aplica a los nodos. Obtenga la colección de nodos de destino
    foreach_in_collection target_id [get_clock_info -targets $clock_id] { # Asocie el nombre del reloj a su conjunto de nodos de

        destino target_name
        [get_node_info -name $target_id]
        lappend nodes_with_clocks($target_name) $clock_name
    }
}

Los relojes virtuales no tienen objetivos, por lo que nunca se realiza ningún mapeo con un reloj virtual. En el código de procedimiento completo que se muestra a continuación, se guarda información sobre el tipo de los nodos de destino (registro, pin, celda o puerto) para su uso posterior.

Paso 2. Obtenga nodos con relojes en Fanin Path

El segundo paso es encontrar el subconjunto de nodos con relojes que están en la ruta de acceso del ventilador al pin especificado. Para cada nodo con relojes (se encuentra en el paso 1), obtenga la entrada del ventilador hasta el pin especificado a través del nodo. Si hay un ventilador, el nodo se encuentra en la ruta de ventilador hacia el pin. Si no hay ventilador, el nodo no se encuentra en la ruta de acceso del ventilador al pin.

El siguiente código Tcl itera por todos los nodos con relojes del paso 1 y utiliza el comando get_fanins para determinar si cada nodo está en la ruta de fanin del pin especificado. Si el nodo está en la ruta de acceso del pin especificado, se guarda el nodo en la lista de pin_drivers.

establezca pin_drivers [list]

# Iteración en todos los nodos en la asignación creada en el paso 1
forecad node_with_clocks [nombres de matriz nodes_with_clocks] {

    # Obtener cualquier ventilador en el pin especificado a través del nodo actual establecido fanin_col
    [get_fanins -clock -through $node_with_clock $pin_name]

    # Si hay al menos un nodo de ventilador, el nodo actual está en la
    ruta de acceso # fanin al pin especificado,  así que guárdelo.
    if { 0 < [get_collection_size $fanin_col] } {
        lappend pin_drivers $node_with_clocks
    }
}

El código de procedimiento completo que se muestra a continuación utiliza información adicional sobre el tipo de nodo para especificar una colección específica de tipo para el valor -through en el comando get_fanins.

Paso 3. Buscar el nodo más cercano al pin especificado

La variable pin_drivers ahora tiene una lista de todos los nodos con relojes que están en la ruta de acceso del ventilador al pin especificado. Este paso encuentra el nodo más cercano al pin especificado. Si bien hay más de un nodo en la lista pin_drivers, el código toma los dos primeros nodos de la lista y comprueba si uno está en la ruta de acceso del ventilador al otro. Si está en la ruta de acceso de ventilador, el primer nodo debe estar más lejos del pin que el segundo nodo, por lo que se puede eliminar de la lista.

while { 1 < [llength $pin_drivers] } {

    # Obtenga los dos primeros nodos de la lista de pin_drivers
    establecidos node_a [lindex $pin_drivers 0]
    establecidos node_b [lindex $pin_drivers 1]

    # Compruebe si node_b está en la ruta de acceso del node_a establecer fanin_col
    [get_fanins -clock -through $node_b $node_a]

    # Si hay al menos un nodo de ventilador,  node_b debe estar más
    lejos del pin especificado que node_a.
    # Si no hay ningún nodo de ventilador, node_b debe estar más cerca del
    pin especificado nro. que node_a lo sea.
    si { 0 < [get_collection_size] } {

        # node_a está más cerca del pin.
        # Elimine node_b de la lista de pin_drivers
        establecida pin_drivers [lreplace $pin_drivers 1 1]

    } else { # node_b está más cerca del

        pin.
        # Elimine node_a de la lista de pin_drivers
        conjunto pin_drivers [lreplace $pin_drivers 0 0] } } Cantidad El nodo que queda en pin_drivers es el nodo que impulsa el conjunto de

pines especificado node_driving_pin
[lindex $pin_drivers 0] # Busque los

relojes en el nodo en la asignación desde el paso 1 y devuelvalos
$nodes_with_clocks($node_driving_pin

El código de procedimiento completo que se muestra a continuación utiliza información adicional sobre el tipo de nodo para especificar una colección específica de tipo para el valor -through en el comando get_fanins.

Código de procedimiento completo

A continuación, se muestra el código completo para el procedimiento personalizado get_clocks_driving_pin. Incluye características adicionales de comprobación de errores y compatibilidad que no se describen en detalle anteriormente.

proc get_clocks_feeding_pin { pin_name } { # Antes del

    paso 1, realice una verificación de error para asegurarse de que el número de pin_name
    que se pasó al procedimiento coincida con un solo pin.
    # Devuelva un error si no coincide con un solo pin.
    establezca pin_col [get_pins -compatibility_mode $pin_name]
    if { 0 == [get_collection_size $pin_col] } { error de código de
        devolución "No hay pines que coincidan $pin_name"
    } elseif { 1 < [get_collection_size $pin_col] } {
        error de código de devolución "$pin_name coincide con [get_collection_size $pin_col]\
            pines, pero debe coincidir solo con uno"
    } # Initialize variables
    
    utilizadas en el procedimiento
    catch { array unset nodes_with_clocks } catch
    { array unset node_types } array set
    nodes_with_clocks [list]
    conjunto de matrices node_types [list]
    establecido pin_drivers [list]
    
    n.º paso 1. Obtenga todos los relojes en el diseño y cree una asignación de
    # los nodos de destino a los relojes en los nodos de destino #

    Iterar sobre cada reloj en el foreach_in_collection clock_id de diseño
    [all_clocks] {

        establecer clock_name [get_clock_info -name $clock_id]
        establecer clock_target_col [get_clock_info -targets $clock_id]
        
        # Cada reloj se aplica a los nodos. Obtenga la colección de nodos de destino
        foreach_in_collection target_id [get_clock_info -targets $clock_id] { # Asocie el nombre del reloj a su conjunto de nodos de

            destino target_name
            [get_node_info -name $target_id]
            lappend nodes_with_clocks($target) $clock_name) $clock_name

            # Guarde el tipo del nodo de destino para utilizar más tarde establezca target_type
            [get_node_info -type $target_id]
            set node_types($target_name) $target_type
        }
    }

    N.° paso 2. Obtenga una lista de nodos con relojes en ellos que se encuentran en la
    ruta # fanin al pin especificado

    # Iterar por todos los nodos en la asignación creada en el paso 1
    forecad node_with_clocks [nombres de matriz nodes_with_clocks] { # Utilice el tipo del nodo de destino para crear una colección # específica del

        tipo para el valor
        -through en el 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 { error de código de devolución
            "$node_types($node_with_clocks) no se maneja\ como un tipo de
                ventilador por el script" }
        }

        # Obtenga cualquier fanins en el pin especificado a través del nodo actual
        establecido fanin_col [get_fanins -clock -through $through_col $pin_name]

        # Si hay al menos un nodo de ventilador, el nodo actual está en la
        ruta # fanin al pin especificado, así que guárdelo.
        if { 0 < [get_collection_size $fanin_col] } {
            lappend pin_drivers $node_with_clocks } } Cantidad antes del
    paso

    3, realice una verificación de error para asegurarse de que al menos un
    número de nodos con relojes en el diseño esté en la ruta de acceso del ventilador hasta
    el pin especificado.
    if { 0 == [llength $pin_drivers] } { error de
        código de devolución "No se puede encontrar ningún nodo con relojes que unidades $pin_name"
    }
    
    N.° paso 3. De la lista de nodos creados en el paso 2, encuentre el
    n.° de nodo más cercano al pin especificado y devuelva los relojes en ese nodo.

    while { 1 < [llength $pin_drivers] } {

        # Obtenga los dos primeros nodos en la lista de pin_drivers
        establecidos node_a [lindex $pin_drivers 0]
        set node_b [lindex $pin_drivers 1] # Utilice el tipo del nodo de destino para crear una colección # específica del
        
        tipo para el valor
        -through en el 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" {  establecido through_col [get_registers $node_b] } predeterminado { error de
            código de devolución "$node_types($node_b) no se maneja\ como un tipo de
                ventilador por el script" } }
        Cantidad de

        verificación de si node_b está en la ruta de acceso del ventilador de node_a        
        establezca fanin_col [get_fanins -clock -through $through_col $node_a] # Si

        hay al menos un nodo de ventilador, node_b debe estar más lejos del pin especificado que
        node_a.
        # Si no hay ningún nodo de ventilador, node_b debe estar más cerca del
        pin especificado nro. que node_a lo sea.
        if { 0 < [get_collection_size $fanin_col] } {

            # node_a está más cerca del pin.
            # Elimine node_b de la lista de pin_drivers
            establecida pin_drivers [lreplace $pin_drivers 1 1]

        } else { # node_b está más cerca del pin # Quitar node_a de la

            lista de pin_drivers establecido pin_drivers
            [lrange $pin_drivers 1 end] } } # El nodo que queda en pin_drivers es el nodo que impulsa el conjunto de
    
    pines especificado node_driving_pin
    [lindex $pin_drivers 0]

    # Busque los relojes en el nodo en la asignación del paso 1 y devolverlos
    $nodes_with_clocks($node_driving_pin)
}

El contenido de esta página es una combinación de la traducción humana y automática del contenido original en inglés. Este contenido se ofrece únicamente para su comodidad como información general y no debe considerarse completa o precisa. Si hay alguna contradicción entre la versión en inglés de esta página y la traducción, prevalecerá la versión en inglés. Consulte la versión en inglés de esta página.