Quartus® II Tcl 示例:文件中的版本号递增

author-image

作者

在项目中维护版本号的一种方法是在每次编译期间对文件中的版本号进行递增。要执行此任务,脚本必须解析文件,以便定位版本号,对版本号进行递增,然后使用新版本号重写文件。如果文件较短且除版本号之外几乎没有其它内容,可以在每次运行脚本时从头写入新文件。但是,如果文件是较长的设计文件,编辑版本号所在的行可能比从头编写新文件更可行。

定位版本号

脚本使用正则表达式定位文件中的版本号。版本号所在的行应具有唯一格式,否则可能会有多行与正则表达式匹配。创建唯一格式的一种方法是在版本号所在的行添加唯一注释。此唯一注释可以包含在正则表达式中。以下是设计文件中包含唯一注释、版本号所在的行以及与此行匹配的正则表达式 Tcl 命令的示例。

设计文件行

data_out <= 16'h41; // Design Version Number

正则表达式

regexp {^\s+data_out <= \d+'h([[:xdigit:]]+); // Design Version Number$} \ $line match version_number

([[:xdigit:]]+) 模式匹配至少有一位数的十六进制数字,并将其保存在名为 version_number 的匹配变量中。

进行版本号递增

可以对 Tcl 中的十六进制数字进行递增。在 Tcl 中,十六进制数字用前导 0x 表示。如果版本号并非以 0x 开头,在递增之前将数字转换为基数 10 可能更容易。对于十六进制数字,以下命令显示了将十六进制字符串转换为基数 10、对其进行递增并将其再次转换为十六进制的示例。

set hex_value "AA"
scan $hex_value "%x" decimal_value
incr decimal_value
set new_hex_value [format "%X" $decimal_value]
# $new_hex_value 现在为 "AB"

重写文件

如果设计文件较短,并且仅包含有关版本号的信息,可以使用一系列 puts 命令编写包含递增版本号的新文件。

如果设计文件较长,仅更改版本号所在的行通常更容易,因为在 Tcl 脚本中对文件内容进行硬编码并不可行。

以下程序解析了设计文件并使用版本信息更新此行。与正则表达式不匹配的行将在不修改的情况下写入新文件。对与正则表达式匹配的行中的版本号进行递增,然后将此行写入新文件。

proc update_version_number { input_file output_file} {

    # 如果无法打开输入文件,返回错误。
    if { [catch {open $input_file} input] } {
        return -code error $input
    }

    # 如果无法打开输出文件,返回错误
    if { [catch {open $output_file w} output] } {
        return -code error $output
    }

    # 一次读取输入文件中的一行
    while {-1 != [gets $input line] } {

        # 此正则表达式针对的是靠近
        # 本网页顶部的设计文件行。
        # 必须根据文件对其进行相应的更改。
        if { [regexp {^\s+data_out <= \d+'h([[:xdigit:]]+); // Design Version Number$} \ $line match version_number] } { # 将十六进制版本号转换为基数 10,然后对其进行递增。
scan $version_number "%x" decimal_value incr decimal_value set new_version_number [format "%X" $decimal_value] # 用新版本号替换旧版本号
regsub h${version_number} $line h${new_version_number} line } # 将此行写入新文件
puts $output $line } close $input close $output }   </pre>

在 Tcl 脚本中,可以调用以下示例中所示的程序:此示例假设在系统命令提示符下运行 Tcl 脚本,并将要更新的文件名作为脚本的参数。

set file_name [lindex $quartus(args) 0]
set output_file_name ${file_name}.updated_version_number

if { [catch { update_version_number $file_name $output_file_name } res] } {
    post_message -type critical_warning "Could not update version number: $res"
} else {

    if { [catch { file rename -force $output_file_name $file_name } res ] } {
        post_message -type critical_warning \
            "Could not update version number: $res"
    }
}