什么是TCL?
TCL,Tool Command Language,是一種腳本語言,主流的EDA工具都支持TCL進行操作。TCL經(jīng)常被用于 快速原型開發(fā),腳本編程, GUI和測試等方面。
TCL學(xué)習(xí)
接下來以一個實際的tcl腳本為例,簡單介紹TCL的使用。這個腳本是用于modelsim/qusetasim仿真的腳本,mentor將tcl進行拓展,稱之為do文件,實際語法還是TCL。腳本來自鏈接:
# testbench name without .v , .vt , .vhd , .vht
set testbench_name conv
# simulation time ; ns/us/ms/min
set sim_time 1us
# auto add files when $auto_add_file==1; add file list when $auto_add_file==0
quietly set auto_add_file 1
# project path
set prj_path E:/conv_sim
# backup path
set bkp_path E:/conv_sim/backup
# monitor resolution ratio , for example : 1920 x 1080
quietly set m_width 1920
quietly set m_height 1080
if 0 {
my first program in Tcl program
Its very simple
}
首先,第一行,TCL采用#進行單行注釋,多行注釋使用判斷句注釋,就像末尾的if那樣。TCL是一種弱語言類型,不需要聲明類型,直接通過set聲明變量并進行賦值。字符串變量直接輸入即可,不需要額外的聲明。這里直接set的變量是全局變量。
proc new_prj {new_prj_name} {
global prj_path
set new_prj_path E:/conv_sim/$new_prj_name/
quit -sim
project close
if { [file exists $new_prj_path]==0 } {
file mkdir $new_prj_path
}
project new $new_prj_path $new_prj_name work
if { [file exists $new_prj_path/src]==0 } {
file mkdir $new_prj_path/src
}
file copy -force -- $prj_path/sim.do $new_prj_path
puts “create new project successfully!”
puts “current project path : ”
pwd
}
這里定義了一個用于創(chuàng)建工程的命令new_prj。
proc為procedure的縮寫,TCL使用proc聲明過程,用proc聲明后,過程就會成為腳本的一個命令,直接使用。對于在過程中定義的變量,因為它們只能在過程中被訪問,并且當過程退出時會被自動刪除,所以稱為局部變量;在所有過程之外定義的變量我們稱之為全局變量。TCL 中,局部變量和全局變量可以同名,兩者的作用域的交集為空:局部變量的作用域是它所在的過程的內(nèi)部;全局變量的作用域則不包括所有過程的內(nèi)部。如果我們想在過程內(nèi)部引用一個全局變量的值,可以使用 global 命令。這樣在new_prj中就能訪問到全局變量prj_path。
變量的引用通過$進行引用,會直接將表達式進行替換。
quit是qusetasim的命令,用于退出軟件,加上選項-sim將只退出仿真而不會關(guān)閉軟件。project close也是qusetasim的命令,用于關(guān)閉工程。
file exists path,判斷是否存在指定文件夾。file mkdir path,創(chuàng)建文件夾。file copy -force — source targetDir 復(fù)制文件到指定目錄,這個命令把 source 中指明的文件或目錄遞歸的拷貝到目的地址 targetDir,只有當存在-force選項時,已經(jīng)存在的文件才會被覆蓋。試圖覆蓋一個非空的目錄或以一個文件覆蓋一個目錄或以一個目錄覆蓋一個文件都會導(dǎo)致錯誤。
注意,-表示開關(guān)/選項,--表示這后面再沒有開關(guān)(switchs)了,即后面以’-‘開頭的參數(shù)將不作為 switch。
puts用于打印,和sv中的$display一個作用。
proc encrypt_src {} {
global prj_path
set encrypt_path $prj_path/encrypt_src/
file mkdir $encrypt_path
set paths {}
set paths [glob -nocomplain -directory $paths */]
lappend paths $prj_path
foreach one_path $paths {
set vfiles [glob -nocomplain -directory $one_path *.v *.vt *.sv]
foreach one_file $vfiles {
set one_file_path $prj_path
vencrypt [append one_file_path $one_file] -d $encrypt_path
}
}
puts “encrypt HDL design file(s) successfully!”
}
這里利用questasim的vencrypt將工程內(nèi)的文件全部進行加密。
set paths {}創(chuàng)建一個列表,列表是TCL中的一個數(shù)據(jù)類型。
glob和file是TCL提供的兩個進行文件名操作的命令,用來操作文件或獲取文件信息。glob 命令采用一種或多種模式作參數(shù),并返回匹配這個(些)模式的所有文件的列表,其語法為:glob switches pattern pattern 。-nocomplain是一個開關(guān),使用這個開關(guān)允許glob返回空列表,不開啟的話,如果結(jié)果是空,則會返回錯誤。-directory,用于指定目錄,讓glob在這個目錄下進行匹配。pattern代表正則匹配的模式,匹配成功的文件名將添加進返回的列表。
lappend在一個列表后添加一個元素。
foreach遍歷整個列表的元素,中間變量為one_path。
vencrypt是questasim的命令,用于將文件進行加密,加密后的文件可以被questasim識別編譯,但是無法閱讀。比如下面的代碼的后半段就是前半段進行加密后的內(nèi)容。-d用于指定加密后的文件生成加密文件的存放位置。
module relu_core (
input clk, //clk
input rst_n, //reset
input [255:0] pooling_in,
input relu_bypass,
output [255:0] relu_out //output of pooling
);
wire [255:0] relu_result;
genvar i;
generate
for(i=0; i《32; i=i+1) begin
assign relu_result[i*8+7:8*i] = pooling_in[i*8+7] ? 8‘h00 : pooling_in[i*8+:8];
end
endgenerate
assign relu_out = relu_bypass ? pooling_in : relu_result;
endmodule
`pragma protect begin_protected
`pragma protect version = 1
`pragma protect encrypt_agent = “QuestaSim” , encrypt_agent_info = “10.6c”
`pragma protect key_keyowner = “Mentor Graphics Corporation” , key_keyname = “MGC-VERIF-SIM-RSA-2”
`pragma protect key_method = “rsa”
`pragma protect encoding = ( enctype = “base64” , line_length = 64 , bytes = 256 )
`pragma protect key_block
NROTnsk8pETOxl4QiAgkLU/279V7O329exd+zzLCVEaVhofiC+ppJtC4dQapAZkK
4CZaxp/gcINr0jlEzm2pBtmqhJ5Kd71mtMNPuUCpphC+J/VJ0JNsOVsVnG6dGztB
+2p8OzoWDWF4F+yAF7L6O7Vksq5afDXEwJDlkIfxzxg3PfwWjDbssR5lq731UMSE
a9cfMZZxe8OO7itVsCz/zAK+WKSZvpAlArpT2mHg76CMXN5ybxCzwXtjeAZf0piM
61waCYBncD+dloA+5uhHJxOj10CAE7jsF8rgi3bfMG/XqmneMRzL8ODqaLtolytR
h2xcuR63Zyi3tgTOeUvXSg==
`pragma protect data_method = “aes128-cbc”
`pragma protect encoding = ( enctype = “base64” , line_length = 64 , bytes = 528 )
`pragma protect data_block
8v6OffgbV/rkWBfwQvGwkfKmdYvvLkohFDLb+Qy+qVnoZgIFOFAFomkEaZ5b32l7
Qmw1d80d+hxDgn4XFA3qbNpn80H3EDx8+HhZL8GeoZw1Wkp4dlFpUcQLEJ3tNh4d
j314qMHeKj8Uu/4928YoJVMzojlFbn+vWh0ZTyzs5jLJa+EspgVZCSIvlPY9WYOQ
1HmF3kaj/0rJ35hmJXvy+ZMshKS031slUm/7jSxVj0kzdrNLGNYdgKIOvKTTu9vT
lYCjfkZSbLEGAXKWFlWSGCfqgb4sGc6uB0j+oKpE2yVOrMJaQ4rqHg0ykJiwn1fM
MwByU4SVRJK024OPjQXEL4aSQHgi0gvw30Ihxvcr4Do15HVZCBn43R6SVNvQNa0s
Nj6PLcT3jYPk9HZs0ZiykRR+LMLLlfFD9NFaN1s1PNZugAywB9TmYh8Vq1CY5w0Y
GxucPCAqYDn+jet1wFh3Rk/ybjj8ageR/4W+U0eKXF+Uu7YWfUApRkGH75Ru3yE/
f9JiC/xdmH6As5aWGzvNZk2g2BLzamLp7d4tmCQbizQSby38hKW8VOJmOzEQPWHg
UxKcN/VZzW6yPVrJxPRHRIb/qarIrx75IdFRZjYrCI9FFchJ3TASPSviufKyAWOj
jWIkYe8Z9yQ5fTMZwe7NhT27PfRe46HR9YuMP9lCCGcYplKVbG5xFwX6bRdqAqwK
`pragma protect end_protected
proc create_file_list {} {
global prj_path
set prj_files [project filenames]
set paths {}
set paths [glob -nocomplain -directory $paths */]
lappend paths $prj_path
set fd [open $prj_path/hdl_design_file_list.tcl w+]
foreach one_path $paths {
set vfiles [glob -nocomplain -directory $one_path *.v *.vt *.vhd *.vht]
foreach one_file $vfiles {
set exists_num 0
set one_file_path {}
append one_file_path $prj_path
append one_file_path $one_file
foreach one_prj_file $prj_files {
if {$one_file_path == $one_prj_file} {
incr exists_num
}
}
if {$exists_num == 0} {
puts -nonewline $fd “# ”
}
puts $fd $one_file_path
}
}
close $fd
puts “create file list successfully!”
}
這里定義了一個創(chuàng)建文件列表的過程。
set fd [open $prj_path/hdl_design_file_list.tcl w+],open命令以特定模式打開文件,返回一個文件標識符。這與c語言類似,w+ 讀寫方式打開文件,如文件存在則清空文件內(nèi)容,否則創(chuàng)建新的空文件。puts -nonewline $fd ”# “,向fd中寫入內(nèi)容,不開啟-nonewline則會在末尾添加換行符。close關(guān)閉文件。
proc add_file {} {
global prj_path auto_add_file
set add_count 0
set del_count 0
set prj_files [project filenames]
if {$auto_add_file == 1} {
set paths [glob -nocomplain -directory $prj_path */]
lappend paths $prj_path
foreach one_path $paths {
set vfiles [glob -nocomplain -directory $one_path *.v *.vt *.vhd *.vht]
foreach one_file $vfiles {
set exists_num 0
foreach one_prj_file $prj_files {
if {$one_file == $one_prj_file} {
incr exists_num
}
}
if {$exists_num == 0} {
project addfile $one_file
incr add_count
}
}
}
} elseif {$auto_add_file == 0} {
if {[file exists $prj_path/hdl_design_file_list.tcl] == 0 ||
[file size $prj_path/hdl_design_file_list.tcl] 《= 1} {
create_file_list
}
set fd [open $prj_path/hdl_design_file_list.tcl r]
set old_content [read -nonewline $fd]
close $fd
regsub -all “ ” $old_content {} new_content
regsub -all + $new_content {} new_content
foreach one_file [split $new_content
] {
if {[regexp ^# $one_file] == 0 && $one_file != “
”} {
set exists_num 0
foreach one_prj_file $prj_files {
if {$one_file == $one_prj_file} {
incr exists_num
}
}
if {$exists_num == 0} {
project addfile $one_file
incr add_count
}
} elseif {[regexp ^# $one_file] == 1 && $one_file != “
”} {
set one_file [string trim $one_file “#”]
foreach one_prj_file $prj_files {
if { $one_file == $one_prj_file} {
project removefile $one_file
incr del_count
}
}
}
}
}
puts -nonewline “add ”
puts -nonewline $add_count
puts “ file(s) successfully!”
puts -nonewline “remove ”
puts -nonewline $del_count
puts “ file(s) successfully!”
}
創(chuàng)建了添加源文件的過程。
project filenames是questasim的命令,返回當前工程的文件列表。
regsub -all “ “ $old_content {} new_content,-all 沒有這個開關(guān)時,regsub只替換第一個匹配,有了這個開關(guān),regsub將把所有匹配的地方全部替換。第二項為正則匹配表達式,第三項為目標字符串,第四項為替換內(nèi)容。regsub通過第二項進行匹配,將第三項中匹配的目標,替換為第四項,存到第五項中。
proc wave_style_set {} {
global testbench_name default_color
foreach sig [find signals $testbench_name/*] {
switch -regexp -nocase -- $sig {
/*/*rst+ {add wave -radix binary -color [lindex $default_color 0] $sig}
/*/*clk+ {add wave -radix binary -color [lindex $default_color 1] $sig}
/*/*en+ {add wave -radix binary -color [lindex $default_color 2] $sig}
/*/*cnt+ {add wave -radix decimal -color [lindex $default_color 3] $sig}
/*/*data+ {add wave -radix hex -color [lindex $default_color 4] $sig}
/*/*flag+ {add wave -radix binary -color [lindex $default_color 5] $sig}
default {add wave -radix hex -color [lindex $default_color 6] $sig}
}
}
}
創(chuàng)建了一個修改波形格式的過程。
switch -regexp -nocase — $sig ,和c語言的switch一樣。TCL 支持三種匹配方式:-exact 方式, -glob方式, -regexp 方式,缺省情況表示-glob 方式。-exact 方式表示的是精確匹配, -glob 方式的匹配方式和 string match命令的匹配方式相同, -regexp 方式是正則表達式的匹配方式。-nocase是regexp的匹配選項,是大寫字母也被當作小寫來處理,相當于不區(qū)分大小寫字符。最后一個變量就是被用來作測試的值 。每行的開頭,比如/*/*rst+ ,用這個正則匹配進行選擇。
lindex $default_color 0引用列表default_color 的第0項。
alias ne “new_prj”
alias es “encrypt_src”
alias af “add_file”
alias br “backup_prj”
alias cf “create_file_list”
alias cc “compile_changed”
alias cr “.main clear”
alias rr “run”
alias ra “run_all”
alias sw “save_wave”
alias aw “l(fā)oad_wave”
alias wr “write_report”
alias df “display_info”
alias dh “do_help”
為過程創(chuàng)建別名。通過別名也能夠調(diào)用過程
編輯:lyn
-
TCL
+關(guān)注
關(guān)注
10文章
1722瀏覽量
88569
原文標題:TCL簡單教程
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論