Quartus® II Tcl 例: ロジックのレポートレベル

author-image

投稿者:

デザインを最適化するのに、レジスター間のロジックのレベルに関する情報をビューすることが役立ちます。以下のスクリプトは、デザイン内の異なるレベルのロジックを持つパスの数を含む、コンマ区切り値 (.csv) ファイルを生成します。このデータを図表にするか、Excel* でヒストグラムを作成して、ロジックのレベルごとのパス分布を示せます。

2 つのレジスター間に複数のロジックパスがある場合、このスクリプトは、ロジックの最大レベルのみカウントします。例えば、2 つのレジスターに、レベル 4 のパスが 1 つ、およびレベル 2 のパスが 2 つある場合、レベル 4 のパスが 1 つとカウントされます。

このスクリプトは、<revision name>.levels_of_logic.csv. という名前の CSV ファイルを生成します。

仮にスクリプトを保存するファイルの名前を、report_levels_of_logic.tcl とすると、下記のコマンドでこれを実行できます。

quartus_tan -t report_levels_of_logic.tcl -project <project name> [-revision <revision name>] [-name_pattern <string to match>]

-name_pattern オプションを使用して、デザインにおけるパスのカウントを特定の階層に制限できます。ツールコマンド言語 (Tcl) ワイルドカード・マッチングに一致する文字列を指定します。-name_pattern オプション用に値を指定しない場合、デフォルトの * になります。例えば、デザイン内の mult:inst6|lpm_mult:lpm_mult_component 階層間のレジスターのロジックレベルをレポートしたい場合、-name_pattern オプションの値に、specify mult:inst6|lpm_mult:lpm_mult_component* を指定します。

load_package advanced_timing
package require cmdline

set options {\
    { "project.arg" "" "Project name" } \
    { "revision.arg" "" "Revision name" } \
    { "name_pattern.arg" "*" "Restrict to registers matching this pattern"}
}

array set opts [::cmdline::getoptions quartus(args) $options]
array set num_levels [list]

# プロジェクトを開いてリビジョン名を取得します
if { [string equal "" $opts(revision)] } {
    project_open $opts(project) -current_revision
} else {
    project_open $opts(project) -revision $opts(revision)
}
set rev [get_current_revision]

# タイミング・ネットリストを準備します
if { [catch { create_timing_netlist; create_p2p_delays } res] } {
    post_message -type error $res
    project_close
    qexit -error
}

# デザイン内にあるすべてのレジスターで繰り返します
foreach_in_collection dest [get_timing_nodes -type reg] {

    # レジスターノードにフィードするキーパー
    #  (レジスター、ピン、クロック) のリストを入手
    set delays_from_keepers [get_delays_from_keepers $dest]
    
    # デスティネーションのレジスター名がパターンに合わない場合、
    # 単に次へ行きます。
    set dest_name [get_timing_node_info -info name $dest]
    if { ! [string match $opts(name_pattern) $dest_name] } {
        continue
    }
    # レジスターノードにフィードするすべてのキーパーを検証
    foreach delay $delays_from_keepers {

        set src [lindex $delay 0]

        # キーパーにはピンおよびクロックを含められますが、ここで必要なのはレジスターのみです。
        if { ! [string equal "reg" [get_timing_node_info -info type $src]] } {
            continue
        }

        # ソースのレジスター名がパターンに合わない場合、
        # 単に次へ行きます
        set src_name [get_timing_node_info -info name $src]
        if { ! [string match $opts(name_pattern) $src_name] } {
            continue
        }

        # このポイントで、ソース名およびデスティネーション名はいずれも
        # パターンに合っており、これはレジスター間パスです。
        # get_delay_path コマンドは、パス上のノードのリストを
        # 返します。パスの長さはリストの長さです。
        # リストにはソースおよびデスティネーションのレジスターが含まれているため、
        # レジスター間のロジックのレベルは
  
  


- 2
        set path [get_delay_path -type longest -from $src -to $dest]
        set levels_of_logic [expr { [llength $path] - 2 } ]
        
        # アレイ内の情報を保存します
        if { [info exists num_levels($levels_of_logic)] } {
            incr num_levels($levels_of_logic)
        } else {
            set num_levels($levels_of_logic) 1
        }
    }
}

project_close

# 情報をファイルに書き出します
if { [catch {open ${rev}.levels_of_logic.csv w} fh] } {
    post_message -type error $fh
} else {

    # 説明ヘッダーをそのファイルに書き込みます
    puts $fh "Levels of logic for project $opts(project) revision $rev"
    puts $fh "File generated by Quartus® II $quartus(version) on \
        [clock format [clock seconds]]"
    puts $fh "\nReporting paths for register names matching $opts(name_pattern)"
    puts $fh "Levels of logic,Number in design"

    foreach level [lsort -integer [array names num_levels]] {

        if { [catch { puts $fh "$level,$num_levels($level)" } res] } {
            post_message -type error $res
            break
        }
    }
    catch { close $fh }
}