Quartus® II Tcl 示例:报告逻辑级数

author-image

作者

在优化设计时,查看寄存器之间的逻辑级数信息是很有用的。下面的脚本生成一个逗号分隔值 (.csv) 文件,其中包含设计中具有不同逻辑级数的路径数量。可以在 Excel 中绘制此数据的图表或创建直方图,按逻辑级数显示路径分布。

如果两个寄存器之间有多个逻辑路径,此脚本以逻辑级数最多的路径为准。例如,如果两个寄存器之间有一个四级路径和一个两级路径,将被视为一个四级路径。

此脚本生成一个名为 <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 选项的值指定为 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 }
}