1+1=10

记记笔记,放松一下...

Intel Quartus Prime Lite 小记(三)

接前面Quartus Prime Lite小记二,断断续续看了好几天Quaruts基本用法了,在学习Verilog或VHDL之前,应该把git和quartus整合搞定...

回顾

  • 编写verilog文件 mytest2.v
  • 编写脚本my_setup.tcl
  • 运行quartus_sh命令,完成项目创建和编译工作,得到 mytest3.sof文件

在小记二中,我们有了一个 verilog文件 mytest2.v,文件内定义了一个mytest2的模块。

我们写了一个tcl脚本my_setup.tcl

project_new mytest3 -overwrite

set_global_assignment -name FAMILY "MAX 10"
set_global_assignment -name DEVICE 10M50SAE144C8G 
set_global_assignment -name TOP_LEVEL_ENTITY mytest2
set_global_assignment -name PROJECT_OUTPUT_DIRECTORY "output_files"
set_global_assignment -name VERILOG_FILE mytest2.v

set_location_assignment PIN_6 -to x1
set_location_assignment PIN_7 -to x2
set_location_assignment PIN_8 -to f

通过执行如下命令创建一个完整工程:

quartus_sh -t my_setup.tcl

得到文件

  • mytest3.qpf
  • mytest3.qsf

再执行编译

quartus_sh --flow compile mytest3

即可得到:

  • mytest3.sof

那么..., 如何获取git信息,并体现在编译输出的文件名中...

Git基础

Git作为分布式的源码管理工具,没有可以类比SVN的递增值。

  • 提交的唯一标识是一个长长的SHA值:
git rev-parse  HEAD
  • 要短一点也可以
git rev-parse --short HEAD

用这个东西肯定是正确的,但是现实中用它,对用户很不友好...,友好的方式可以选择...

  • 打上tag,使用describe,可以获取类似 "v1.0-3-gabc123" 的字符串
git descrbe

如果偷懒的话,直接用提交数可以(确保和中央仓库同步),在一些小项目中,这么做比较简单,但是不严谨:

  • 获取提交数
git rev-list --count HEAD
  • 或者提交数加上当前提交的日期,获取日期可以通过:
git log -1 --format=%cd --date=format:%Y%m%d%H%M%S

编译过程中执行自定义脚本

quaruts允许配置如下钩子:

  • PRE_FLOW_SCRIPT_FILE 指定流程开始前要执行的脚本
  • POST_MODULE_SCRIPT_FILE 指定编译每个阶段执行完执行的脚本(比如map、fit、asm每个阶段执行完的时候)
  • POST_FLOW_SCRIPT_FILE指定流程结束后执行的脚本

在.qsf中进行配置,语法如下:

set_global_assignment -name <assignment name> <executable>:<script name>

执行时,quartus会转换成如下命令进行执行

<executable> -t <script name> <flow or module name> <project name> <revision name>

输出git信息

编写一个脚本 get_git_info.tcl:

# 获取最新提交的哈希值
set commit_hash [exec git rev-parse HEAD]
set commit_count [exec git rev-list --count HEAD]

# 将哈希值写入文件
set file [open "version_info.txt" "w"]
puts $file "$commit_count $commit_hash"
close $file

加入到.qsf文件中:

set_global_assignment -name PRE_FLOW_SCRIPT_FILE quartus_sh:get_git_info.tcl

在命令行中,或者在quartus中,执行编译操作,即可得到一个包含版本信息的文件

  • version_info.txt

注意:该文件不会被 quartus_sh --clean 清理。

为了避免脚本在git仓库之外执行,或者git找不到造成崩溃问题,可以调整一下脚本:

# 尝试获取最新提交的哈希值和提交计数
set commit_hash ""
set commit_count ""

catch {
    set commit_hash [exec git rev-parse HEAD]
    set commit_count [exec git rev-list --count HEAD]
} err

# 检查是否成功获取了信息
if {$commit_hash eq "" || $commit_count eq ""} {
    set commit_hash "unknown"
    set commit_count "0"
}

# 将哈希值和计数写入文件
set file [open "version_info.txt" "w"]
puts $file "$commit_count $commit_hash"
close $file

这只是一个demo,理论上,我们应该可以将git信息输出到项目文件,或者被verilog或vhdl包含的文件中。进而编译进固件中,并可以被后续上位机读取。

修改sof文件名

没找到如何直接配置sof和pof的文件名,只要写一个tcl脚本,编译结束后,直接拷贝出来,拷贝成我们想要的文件名。

脚本 my_post.tcl:

# 定义源文件夹和目标文件夹
set source_folder "output_files"
set target_folder "./"

# 确保目标文件夹存在,如果不存在,则创建
if {![file exists $target_folder]} {
    file mkdir $target_folder
}

# 获取Git提交次数
if {[catch {exec git rev-list --count HEAD} git_commit_count]} {
    puts "Error getting git commit count: $git_commit_count"
    exit 1
}

# 获取最后一次提交的日期,格式为YYYYMMDDHHMMSS
if {[catch {exec git log -1 --format=%cd --date=format:%Y%m%d%H%M%S} git_last_commit_date]} {
    puts "Error getting last commit date: $git_last_commit_date"
    exit 1
}

# 移除任何可能的双引号
set git_last_commit_date [string map {\" ""} $git_last_commit_date]

# 遍历指定类型的文件
foreach filetype {sof pof} {
    set files [glob -nocomplain -directory $source_folder *.$filetype]
    foreach file_path $files {
        # 获取文件名(不含扩展名)
        set filename [file rootname [file tail $file_path]]
        # 获取文件扩展名
        set extension [file extension $file_path]
        # 构造新的文件名
        set new_filename "${target_folder}/${filename}_${git_commit_count}_${git_last_commit_date}${extension}"

        # 尝试复制文件,捕获并报告任何错误
        if {[catch {file copy -force -- $file_path $new_filename} error_message]} {
            puts "Error copying file from $file_path to $new_filename: $error_message"
        } else {
            puts "Successfully copied $file_path to $new_filename"
        }
    }
}

puts "Operation completed successfully."

在 .psf 进行配置:

set_global_assignment -name POST_FLOW_SCRIPT_FILE quartus_sh:my_post.tcl

.gitignore

先记录一个 Git ignore file for quartus II projects · GitHub作为后续参考,后面需要时再调整

# Need to keep all HDL files
# *.vhd
# *.v

# ignore Quartus II generated files
*_generation_script*
*_inst.vhd
*.bak
*.cmp
*.done
*.eqn
*.hex
*.html
*.jdi
*.jpg
# *.mif
*.pin
*.pof
*.ptf.*
*.qar
*.qarlog
*.qws
*.rpt
*.smsg
*.sof
*.sopc_builder
*.summary
*.tcl
*.txt # Explicitly add any text files used
*~
*example*
*sopc_*
# *.sdc # I want those timing files

# ignore Quartus II generated folders
*/db/
*/incremental_db/
*/simulation/
*/timing/
*/testbench/
*/*_sim/
incremental_db/
db/
_output_files/
PLLJ_PLLSPE_INFO.txt

禁止更新 .qsf文件

quartus执行时会自动 .qsf文件,这对于源码管控很不友好...

看一下通过GUI界面执行编译时,后台的命令:

quartus_map --read_settings_files=on --write_settings_files=off mytest3 -c mytest3
quartus_fit --read_settings_files=off --write_settings_files=off mytest3 -c mytest3
quartus_asm --read_settings_files=off --write_settings_files=off mytest3 -c mytest3
quartus_pow --read_settings_files=off --write_settings_files=off mytest3 -c mytest3
quartus_sta mytest3 -c mytest3

估计问题出在quartus_sta上?

先记录一下,后面慢慢了解...

参考