Quartus® II Tcl 例: すべてのピンの仮想化

author-image

投稿者:

プロジェクトでモジュラー・ロジックロック・リージョン・デザイン・フローを使用する場合、モジュールバーチャル I/O ピンにあるすべての I/O ピンを、トップレベル・デザインのモジュールへ簡単にインポートする方法にする選択ができます。また、IP コアをコンパイルして使用リソースの数を見たいものの、対象デバイスには使用ピン数が多すぎる場合、ピンを仮想にすることでコアを適合させられます。

以下のシンプルなプロシージャーで、デザインにあるすべてのピンをバーチャル I/O ピンにします。まず、デザインを合成して、どのノードがピンであるかを確定します。次に、名前 ID のコレクションをデザインにあるピンに対応するよう設定してから、VIRTUAL_PIN 代入をすべてのピンに適用します。最後に、export_assignments コマンドで、すべての新規代入をプロジェクトの Quartus® II 設定ファイル (.qsf) に書き込みます。

この例で使用する、get_names および get_name_info コマンドは、Quartus® II ソフトウェアのバージョン 4.0 (::quartus::project パッケージのバージョン 2.0) から利用可能です。Quartus® II ソフトウェアのバージョン 3.0 から動作可能なコードは、このページの最後にある例を参照してください。高度な機能が他にもあります。

load_package flow

proc make_all_pins_virtual {} {

    execute_module -tool map

    set name_ids [get_names -filter * -node_type pin]

    foreach_in_collection name_id $name_ids {
        set pin_name [get_name_info -info full_path $name_id]
        post_message "Making VIRTUAL_PIN assignment to $pin_name"
        set_instance_assignment -to $pin_name -name VIRTUAL_PIN ON
    }
    export_assignments
}

サンプルコードの改良

サンプルコードを改善できるさまざまな方法があります。

既存の VIVIAL_PIN 代入の削除

以下のコマンドをプロシージャーの最初に追加して、既存の VIVRTUAL_PIN 代入を削除できます。これは、代入を確実に既知の状態にするのに役立つステップです。このコマンドを、execute_module コマンドの前に追加します。

remove_all_instance_assignments -name VIRTUAL_PIN

クロックなど特定のピンを手動で除外

Quartus® II ソフトウェアで、デザインに合わせたタイミングの最適化を実行するには、クロック設定を適用してあるクロックを、対象デバイスのトップレベル I/O ピンに接続する必要があります。これは、他のピンがすべて仮想 I/O ピンである場合にも有効です。従って、上記の基本例では、クロックを含むすべてのピンに VIRTUAL_PIN 代入が適用されるため、Quartus® II ソフトウェアがコンパイル中にタイミング最適化するのを防ぎます。

プロシージャーにパラメーターを追加して、VIRTUAL_PIN 代入から除外する信号のリストを許可できます。通常このリストには、デザイン内のクロックピンの名前を記載します。以下の例では、除外する名前のリストを許可します。また、上記で説明した、既存の VIRTUAL_PIN 代入を削除するコマンドも含まれています。

load_package flow
package require cmdline

proc make_all_pins_virtual { args } {

    set options {\
        { "exclude.arg" "" "List of signals to exclude" } \
    }
    array set opts [::cmdline::getoptions quartus(args) $options]

    remove_all_instance_assignments -name VIRTUAL_PIN
    execute_module -tool map
    set name_ids [get_names -filter * -node_type pin]

    foreach_in_collection name_id $name_ids {
        set pin_name [get_name_info -info full_path $name_id]

        if { -1 == [lsearch -exact $opts(excludes) $pin_name] } {
            post_message "Making VIRTUAL_PIN assignment to $pin_name"
            set_instance_assignment -to $pin_name -name VIRTUAL_PIN ON
        } else {
            post_message "Skipping VIRTUAL_PIN assignment to $pin_name"
        }
    }
    export_assignments
}

このコマンドでプロシージャーを呼び出せます。この例は、デザイン内に、clk_a および clk_b の 2 つのクロックが含まれている想定です。

make_all_pins_virtual -exclude { clk_a clk_b }

クロックの自動特定および処理

特定の信号を除外する以前の例のデメリットは、手入力が必要なことです。::quartus::advanced_timing パッケージに入っているコマンドで、クロック信号を確定できます。このパッケージの読み込みは、quartus_tan でのみ実行できるので、以下の例では quartus_tan を使用してスクリプトを実行する必要があります。この例にあるコマンドは、すべて Quartus® II ソフトウェアのバージョン 3.0 からサポートされています。

自動識別クロックには、USE_CLK_FOR_VIRTUAL_PIN 代入のアプリケーションを自動化できる利点があります。USE_CLK_FOR_VIRTUAL_PIN 代入を VIRTUAL_PIN 代入と共に使用して、クロック設定をデザイン内のクロックとアソシエイトできます。これにより、デザインを仮想 I/O ピンでコンパイルする際、Quartus® II Fitter にタイミング要件に関する正確な情報が提供されます。この代入に関する詳細は、Quartus® II ヘルプにある、仮想ピンクロック・ロジック・オプション のトピックを参照してください。

以下のプロシージャー例では、デザイン内のすべての I/O ピンを仮想 I/O ピンにします。また、必要に応じて仮想ピンクロック設定の代入も行います。

まず、サンプルコードとデザインを合成します。次に、新規作成の前に既存のタイミング・ネットリスト削除を試行します。get_timing_nodes コマンドで、タイミング・ネットリストから 2 つのノード・コレクション (pin_ids および clk_ids) を作成します。2 つのコレクションは排他的です。クロックが I/O ピン上にある場合でも、clk_ids コレクション内のノードは、pin_ids コレクション内に存在しません。

最初の foreach_in_collection ループは、デザイン内の各ピン (クロックピンを除く) の名前を取得し、それに VIRTUAL_PIN 代入を行います。

2 番目の foreach_in_collection ループは、デザイン内の各クロックの名前を取得します。get_instance_assignment コマンドは、対応するクロック設定があれば、それを取得します。クロックにクロック設定が存在しない (文字列が空欄ではない) 場合、スクリプトはクロック設定名の値で、クロック名に USE_CLOCK_FOR_VIRTUAL_PIN 代入を行います。

load_package flow
load_package timing
load_package advanced_timing

proc make_all_pins_virtual { } {

    remove_all_instance_assignments -name VIRTUAL_PIN
    remove_all_instance_assignments -name USE_CLK_FOR_VIRTUAL_PIN

    execute_module -tool map
    catch { delete_timing_netlist }
    create_timing_netlist -post_map
    
    set pin_ids [get_timing_nodes -type pin]
    set clk_ids [get_timing_nodes -type clk]
    
    # Make VIRTUAL_PIN assignments to every pin in the design
    foreach_in_collection pin_id $pin_ids {

        set pin_name [get_timing_node_info -info name $pin_id]
        post_message "Making VIRTUAL_PIN assignment to $pin_name"
        set_instance_assignment -to $pin_name -name VIRTUAL_PIN ON
    }

    # For each clock in the design, check whether it has a 
    # corresponding CLOCK_SETTINGS assignment.
    foreach_in_collection clk_id $clk_ids {

        set clk_name [get_timing_node_info -info name $clk_id]
        set clk_stgs [get_instance_assignment -to $clk_name -name \ 
           CLOCK_SETTINGS]

        # If there is a clock setting for this clock, make the
        # USE_CLK_FOR_VIRTUAL_PIN assignment
        if { ![string equal "" $clk_stgs] } {
            post_message "Making USE_CLK_FOR_VIRTUAL_PIN assignment \
                to $clk_name with value $clk_stgs"
            set_instance_assignment -to $clk_name \
                -name USE_CLK_FOR_VIRTUAL_PIN $clk_stgs
        }
    }
    export_assignments
}