ロジックレベルのレポート

author-image

投稿者:

デザインのタイミングをクローズする際、失敗したパスにあるロジックレベル数を把握することが、しばしば役立ちます。タイミング・アナライザーは、パスのタイミングをレポートする際にロジックレベル数を表示しますが、一連のパスのロジックレベル数を記載するデフォルトのレポートはありません。このデザイン例では、一連のパスのロジックレベル数を示すレポートを作成するのに使用できる、カスタム・プロシージャーを定義しています。

カスタム・プロシージャーは、report_timing コマンドと同じ因数をサポートします。report_timing コマンドで使用するのと同じオプションを、カスタム・プロシージャーでも使用する必要があります。また、カスタム・プロシージャーは、次の 3 つの追加オプションをサポートしています。-greater_than <value>、-less_than <value>、および -file <report file> です。-greater_than オプションおよび -less_than オプションを使用して、ロジックの指定レベル以上または以下のパスのレポートを制限できます。-file オプションを使用して、レポートをファイルに書き込むことができます。

カスタム・プロシージャーは、ワースト・タイミング・スラックのパスのロジックレベル数を表示します。デザイン内のパスをディスプレイするのに、必ずしもロジックレベルの最大数を示すとは限りません。ワースト・タイミング・スラックのパスは、ロジックレベルの最大数を持つパスであるとは限りませんが、多くの場合はそうです。

プロシージャー操作

カスタム・プロシージャーは、以下のステップを使用します。

  1. レポート条件を満たすパスのリストを取得する
  2. 各パスのロジックレベル数を取得する
  3. ロジックレベル数およびパス情報をチャートにディスプレイする

ステップ 1: パスのリストを取得する

カスタム・プロシージャーは、get_timing_paths コマンドを使用します。これは、report_timing コマンドと同じ因数をサポートします。report_timing 用の任意のオプションを使用して、タイミング分析を制御できます。例えば、ロジックレベル数のレポートを、特定のレジスター名で終わるパスに制限できます。以下の Tcl コードは、プロシージャー・デフィニションを示しており、すべての因数を get_timing_paths コマンドにパスします。

proc report_levels_of_logic { args } {
    
    # すべての因数を get_timing_paths に直接パスします
    if { [catch { eval get_timing_paths $args } paths_col] } {
        post_message -type error $paths_col
        return
    }
}

ステップ 2: 各パスのロジックレベル数を取得する

paths_col 変数でパス・コレクションを反復するループを使用して、各パスのロジックレベル数を抽出します。Tcl マトリクスデータ構造のパスに関する情報を保存します。これは、結果をプリントアウトするのに使用します。保存される情報は、ロジックレベル数、パスのスラック、ならびにソースおよびデスティネーションのノード名です。

foreach_in_collection path_obj $paths_col {

        # パス内にロジックレベルはいくつありますか
        set levels_of_logic [get_path_info -num_logic_levels $path_obj]
        
        # パス情報をマトリクスに追加します。
        $logic_levels_matrix add row [list \
            $levels_of_logic \
            [get_path_info -slack $path_obj] \
            [get_node_info -name [get_path_info -from $path_obj]] \
            [get_node_info -name [get_path_info -to $path_obj]] ]
    }

ステップ 3: チャート内のパス情報をディスプレイする

最後に、マトリクス変数に保存されたすべてのパス情報をディスプレイします。この例では、マトリクスをプリントアウト用にフォーマットするため、Tcl レポートパッケージを使用します。以下のコードは、マトリクスに見出し行を追加し、レポートのビジュアルスタイルを定義し、セルパディングを設定し、レポートを表示します。

# ヘッダー行を追加します
        $logic_levels_matrix insert row 0 \
            [list "Levels of logic" "Slack" "From" "To"]
    
        # 結果の表をプリントアウトするのにスタイルを定義する必要があります
        catch { ::report::rmstyle basicrpt }
        ::report::defstyle basicrpt {{cap_rows 1}} {
            data        set [split "[string repeat " "   [columns]];"]
            top         set [split "[string repeat "+ - " [columns]]+"]
            bottom      set [top get]
            topcapsep   set [top get]
            topdata     set [data get]
            top         enable
            topcapsep   enable
            bottom      enable
            tcaption    $cap_rows
        }
        
        # レポートを作成し、列の設定でパディングとしてスペースを 1 つ開け、
        # 指定したフォーマットでマトリクスをプリントアウトします
        catch { r destroy }
        ::report::report r 4 style basicrpt
        for { set col 0 } { $col < [r columns]} { incr col } {
            r pad $col both " "
        }
        post_message "Levels of logic\n[r printmatrix $logic_levels_matrix]"

カスタム・プロシージャー

カスタム・プロシージャー用の下記のコードには、レポートをファイルに書き込むオプションと、ロジックレベル数がユーザー定義値以上または以下の場合を除いて、パスをレポートする制限のオプションが含まれています。

これらは、カスタム・プロシージャーの使用方法の例です。

  • report_levels_of_logic -setup -greater_than 10 -to [get_registers data*] -npaths 1000
  • report_levels_of_logic -hold -from_clock core_50 -npaths 50 -file levels.txt

カスタム・プロシージャーを使用するには、下記のTcl コードを report_levels_of_logic.tcl という名前のファイルに保存します。次に、タイミング・アナライザー Tcl プロンプトで、コマンド source report_levels_of_logic.tcl を使用します。ファイルを調達することで、カスタム・プロシージャーを定義します。これで、新しく定義したコマンド report_levels_of_logic を、タイミング・アナライザーを終了するまで使用できます。

package require cmdline
package require struct::matrix
package require report

proc report_levels_of_logic { args } {

    set options {
        { "less_than.arg" "" "Limit to paths with less than this number" }
        { "greater_than.arg" "" "Limit to paths with greater than this number" }
        { "file.arg" "" "Output file name" }
        
    }
    array set opts [::cmdline::getKnownOptions args $options]

    # プロシージャーがいくつかの引数で呼び出されるようにします
    if { [string equal "" $opts(less_than)] && [string equal "" $opts(greater_than)] } {
        post_message -type warning "You must specify a numeric value\
            for -less_than or -greater_than"
        return
    }
    
    # プロシージャーが数字の引数で呼び出されるようにします
    if { ![string is double $opts(less_than)] } {
        post_message -type warning "You must specify a numeric value\
            for -less_than"
        return
    }
    if { ![string is double $opts(greater_than)] } {
        post_message -type warning "You must specify a numeric value\
            for -greater_than"
        return
    }
    
    # 失敗したパスに関する情報を保存するマトリクスを作成します
    set logic_levels_matrix [::struct::matrix]
    $logic_levels_matrix add columns 4

    # 不明な引数をすべて直接 get_timing_paths にパスします
    if { [catch { eval get_timing_paths $args } paths_col] } {
        post_message -type error $paths_col
        return
    }
    
    # タイミングパスのリストを検査して、ロジックレベルに関する
    # 情報を取得します
    foreach_in_collection path_obj $paths_col {
    
        # ロジックレベル数が指定した範囲の外にない限り、
        # パスがレポートされると想定します。
        set include_path 1
        
        # パス内にロジックレベルはいくつありますか
        set levels_of_logic [get_path_info -num_logic_levels $path_obj]
        
        # 下限を指定した場合、ロジックレベルが
        # 下限以下の場合はパスをレポートしません
        if { ! [string equal "" $opts(less_than)] } {
            if { $levels_of_logic >= $opts(less_than) } {
                set include_path 0
            }
        }
        
        # 上限を指定した場合、ロジックレベルが
        # 上限以上の場合はパスをレポートしません
        if { ! [string equal "" $opts(greater_than)] } {
            if { $levels_of_logic <= $opts(greater_than) } {
                set include_path 0
            }
        }
        
        # パスのロジックレベルが範囲内にある場合、
        # それをレポートします
        if { $include_path } {
        
            $logic_levels_matrix add row [list \
                $levels_of_logic \
                [get_path_info -slack $path_obj] \
                [get_node_info -name [get_path_info -from $path_obj]] \
                [get_node_info -name [get_path_info -to $path_obj]] ]
        }
    }
    # get_timing_paths からのすべてのパスの検査が終了しました
    
    # マトリクスに行がある場合、パスが条件に一致しています。
    # この情報の表をプリントアウトする必要があります。
    if { 0 == [$logic_levels_matrix rows] } {
    
        # 条件に一致するパスがありません
        # クイックメッセージをプリントアウトします
        post_message "No paths meet the criteria to report levels of logic"
        
        # ファイルを開く際エラーになる場合は、それを伝えるメッセージをプリント
        # します。もしくは、条件に適したパスがないと伝えます
        if { ! [string equal "" $opts(file)] } {
            if { [catch { open $opts(file) w } fh] } {
                post_message -type error "Couldn't open file: $fh"
            } else {
                puts $fh "No paths meet the criteria to report levels of logic"
                catch { close $fh }
            }
        }
    
    } else {
    
        # ヘッダー行を追加します
        $logic_levels_matrix insert row 0 \
            [list "Levels of logic" "Slack" "From" "To"]
    
        # 結果の表をプリントアウトするため、スタイルを定義する必要があります
        catch { ::report::rmstyle basicrpt }
        ::report::defstyle basicrpt {{cap_rows 1}} {
            data        set [split "[string repeat " "   [columns]];"]
            top         set [split "[string repeat "+ - " [columns]]+"]
            bottom      set [top get]
            topcapsep   set [top get]
            topdata     set [data get]
            top         enable
            topcapsep   enable
            bottom      enable
            tcaption    $cap_rows
        }
        
        # レポートを作成し、列の設定でパディングとしてスペースを 1 つ開け、
        # 指定したフォーマットでマトリクスをプリントアウトします
        catch { r destroy }
        ::report::report r 4 style basicrpt
        for { set col 0 } { $col < [r columns]} { incr col } {
            r pad $col both " "
        }
        post_message "Levels of logic\n[r printmatrix $logic_levels_matrix]"
        
        # ファイル名が指定されている場合、ファイルにレポートを保存します
        if { ! [string equal "" $opts(file)] } {
            if { [catch { open $opts(file) w } fh] } {
                post_message -type error "Couldn't open file: $fh"
            } else {
                puts $fh "Levels of logic"
                r printmatrix2channel $logic_levels_matrix $fh
                catch { close $fh }
            }
        }
    }
}