TCL腳本語言
Tcl(Tool Command Language)是一種很通用的腳本語言,它幾乎在所有的平臺上都可以解釋運行,而且VIVADO也提供了TCL命令行。最近發(fā)現(xiàn)TCL腳本貌似比GUI下操作VIVADO效率高一些,方便一些。而且最近跟著官網文檔做SDSOC的flatform,發(fā)現(xiàn)xilinx官網的文檔里都是用TCL命令來完成操作,于是決心學習一下TCL的語法。
應用程序(如VIVADO)使用Tcl作為它的命令語言的好處:
1 Tcl提供了標準語法,一旦用戶掌握了Tcl就可以很容易的發(fā)布命令給基于Tcl的程序。
2 Tcl實現(xiàn)了很多的功能,使你的工作變得很方便。
命令格式
一條Tcl的命令串包含了多條命令時,用換行符或分號來隔開
而每一條命令包含了一個域的集合,域使用空白分開的,第一個域是一個命令的名字,其它的是作為參數來傳給它
數據類型
Tcl只支持一種數據結構:字符串。所有的命令、命令里的所有的參數、命令的結果、變量全部都是都是字符串。
簡單實例:
set i 123
將123這個字符串賦值給i變量
unset i
清除變量
set i hi
將hi這個字符串賦值給i變量
set i “hi hello”
hi hello中有空格,所以加引號
set i 123;#開始注釋
注意注釋前,要先用分號,把命令結束掉,或者換行注釋
基本語法和基礎命令
在VIVADO中的TCL命令行里,學習這些基本語法
(Windows下 –》 開始 –》 所有程序 –》 Xilinx Design Tools –》 Vivado xxx –》 Vivado xxx Tcl Shell)
1》使用$符號引用變量
其中puts是打印命令
2》使用[]將命令返回值,作為新命令的參數
set j 232命令會返回值232
新命令就成了 set i 232
這里稍微復雜一點點的例子:
set i a[set j b][set k c]
最后的結果就是:j=b ; k=c ; i=abc
3》數組
數組不需要聲明,直接賦值即可,也不必按照順序來:
set i(1) 123 ; set i(16) hi
當然也支持任意維數的數組:
set i(1,2,3) hi
引用的時候直接$i(1,2,3)即可
· parray命令
可以打印出一個數組的全部信息:
· array命令
命令格式:array option arrayName
option 是 操作選項,有如下可選:
name : 返回數組的所有元素的名稱
size : 返回數組的長度
startsearch : 初始化一次遍歷,返回一個遍歷標識符(searchId),這個searchId在下面用到,(是可以多個遍歷同時進行的)
下面的命令格式為:array option arrayName searchId
-》nextelement : 返回數組中下一個元素,如果沒有返回空
-》anymore : 如果接下來還有元素,返回1,否則返回0
-》donesearch : 結束遍歷
4》字符串命令
· string命令
命令格式:string option string1 string2
option 是 操作選項,有如下可選:
compare : 按照字母的排序方式比較,string1 《,=,》string2,分別返回-1,0,1
match : 判斷string1和string2是否匹配
first : 檢索string2中第一次出現(xiàn)string1的位置,如果沒有出現(xiàn)string1則返回-1
last : 和first相反
trim : 從string1中刪除開頭和結尾的,string2的字符
命令格式:string option string
tolower : 返回string中的所有字符被轉換為小寫字符后的新字符串
toupper : 返回string中的所有字符串轉換為大寫后的字符串
trimleft : ,去除string左空白,類似的還有trimright
length : 返回string1的長度
range :
string range abcdef 1 2,返回輸出結果為bc
· append命令
字符串追加,可以無限拼接
set i a
append i b c d
puts $i
i變量的值就成了 abcd,注意append i b c d命令,而不是append $i b c d
· split命令
命令格式:split 字符串 分割符,將字符串轉換為列表
5》數字操作
tcl中只有string類型的變量,所以當進行數字運算的時候,需要用到incr和expr操作命令
· incr命令
a變量自加-3:incr a -3
a變量自加1 : incr a
· expr命令
類似C語言中的算術操作符有(在Tcl 中的邏輯:真為1,假為0):
!、* 、/、 %、+、-、《《、 》》 、《 、》 、《= 、》= 、== 、!=、& 、^ 、|、&&、 || 、x ? y : z
除此之外,expr還能夠識別一些函數及其返回值:
abs(x) 、round(x) 、sin(x)、cos(x) 等
使用方法:expr 表達式
6》list列表
類似python中的列表,比如:{abc {def {jkl ccc}}}是一個有兩個元素的列表 abc和{def {jkl ccc}},Tcl中對list的命令有:
(首先set l {abc {def {jkl ccc}}},下面實例中將對這個l列表進行操作)
需要注意的是:大部分命令都是對$l進行處理,也把就是l的內容字符串取出來,再處理,并不會對l列表的內容造成影響
需要注意的是lappend命令,lappend $l abcd是無效的,必須lappend l abcd才能實現(xiàn)列表內容的更新,而且是直接更改列表的內容
7》proc自定義函數
proc:
proc hello {str} {
puts hello:$str
}
需要注意的是,如果不能一行寫完,那建議按照如下格式來定義(主要是要將“{”放到第一行的末尾):
第一行: proc+(空格)+函數名+(空格)+{參數}+(空格)+{
中間行: 邏輯運算
最后行: }
全局變量global:
用于將過程中的局部變量變成外界可操作的全局變量
proc hello {} {
global x
set x hi
set i hello}
上述代碼,執(zhí)行結果:
return命令:
proc hello {} {return world}
set i [hello]
return命令沒啥好說的,上述代碼的結果是,將i變量賦值為world字符串
8》流控制
if 流控制
這個同樣建議按照格式來:
第一行: if+(空格)+{表達式}+(空格)+{
中間行: 邏輯運算
第N行: }+(空格)+else+(空格)+{
中間行: 邏輯運算
最后行: }
switch流控制
例子如下,一目了然:
switch 2 {
1 {puts 111}
2 {puts 222}
3 {puts 333}
default {puts xxx}
}
case流控制
case abcd in a {puts 111} *bc* {puts 333} default {puts xxx}
上述程序對字符串abcd進行判斷:
條件一 : 字符串為a
條件二 : 不管字符串的前后字符是啥,只要中間有bc子字符串即可
條件三 : default
9》循環(huán)控制
foreach循環(huán):
假如想要將0,3,2,1按照順序分別放到上述switch的判決條件(列表)里,輸出四個結果,那就需要這個foreach了:
foreach i {0 3 2 1} {
switch $i {
1 {puts 111}
2 {puts 222}
3 {puts 333}
default {puts xxx}
}
}
for循環(huán):
TCL的for循環(huán)也是很類似C語言的:
for {set i 0} {$i 《 10} {incr i} {
puts $i
}
初始化i=0,范圍 i《10 ,循環(huán)i=i+1
while循環(huán):
set i 10
while {$i!=5} {
puts $i
incr i -1
}
運行的結果,自己就可以想象了
10》字符串轉為命令
eval命令:
set a set ; set b i ; set c hello ; eval $a $b $c
上述代碼就等效于:set i hello
eval將字符串的內容,作為命令,執(zhí)行
11》打印輸出
之前的那個puts命令也是可以打印到命令行,但是,也只是能打印出來而已,而這個format類似于C中的sprintf(用于格式化輸出):
format命令:
format可以這樣用:
format “%s %d” hello 666
set i [format “%s %d” hello 666]
scan命令:
說到format,剛好一起把scan說了,這兩個命令可以看做是相反的一對, 前者組合成字符串,后者把字符串拆分后賦值給變量
scan 12.34.56.78 %d.%d.%d.%d a b c d
將12.34.56.78拆分,并分別賦值給a b c d四個變量,命令返回賦值成功的變量的個數
puts命令:
puts當然也可以打印到文件中
set f [open test.txt w]
puts -nonewline $f “hello\n”
puts $f “world”
close $f
puts -nonewline $f “hello\n”表示的是強制不換行打印,否則自動追加一個換行符
文件系統(tǒng)
基本常用操作:
gets –》 一次讀一行文件
puts –》 寫入文件
open –》 打開文件
close –》 關閉文件
flush –》 刷新緩沖區(qū)
cd命令
和shell中的cd一樣
pwd命令
用于查看當前所在的目錄
open命令
打開文件,返回文件描述符
命令格式:open 文件名 模式,支持6種模式,和其他編程語言中的文件IO,也是很相似的,模式如下:
r 模式: 打開只讀文件(文件必須存在)
r+ 模式: 打開可讀寫文件[r+和a+模式可以類比]
w 模式: 打開只寫文件,若文件存在則清空內容;若文件不存在則創(chuàng)建文件。
a 模式: 以追加方式打開只寫文件,若文件不存在,則創(chuàng)建;如果文件存在,則會在文件內容最后面追加寫入的數據
xxxx
理論上說open |文件名 模式,在文件名前加個“|”符號,可以以管道的模式打開文件,但是測試一直沒有成功,之后用到的話再回來解決吧
xxxx
read命令
set f [open test.txt r]
read $f 6
close $f
可以使用eof命令,判斷文件是否讀完了,eof $f,讀完返回1,否則返回0
上述代碼直接從文件中讀6個字節(jié);如果想把文件內容全部讀出,則直接read $f;如果想一行一行讀則使用gets命令:gets $f
source命令
命令格式:source $f
從對應的文件中讀出內容,并傳給Tcl解釋執(zhí)行
tell命令
返回文件的指針位置,命令格式:tell $f
file命令
命令格式:file option name
option操作選項較多,就直接列個表了,表示如下:
除此之外,file 的 stat 狀態(tài)操作選項:
命令格式:file stat name k,結果存在數組k里
glob命令
1)查看當前目錄下的文件(類似shell中的ls)
glob *
2)查看當前目錄下特定后綴的文件
glob *.txt *.tcl
3)查看當前目錄下的txt、txl、tcl和tct文件:
glob {*t[xc][tl]}
4)查看當前目錄下的子目錄里查看txt、txl、tcl和tct文件:
用“\”分割路徑,格式為:glob {{目錄1,目錄2等}\\*.后綴}
5)-type選擇查看類型:
命令格式:glob -type {類型1 類型2 等} 目標目錄
類型有:
類型 含義
b 塊設備
c 字符設備
d 代表目錄
f 文件
l 代表符號鏈接
p 代表命名管道
s 代表套接字
r 讀
w 寫
x 可執(zhí)行
seek命令
用于調整文件指針
命令seek $f 2,文件指針定位到序號為2,現(xiàn)在有一個文件名為s1.txt,內容為hello字符串,那么,設計一個程序實現(xiàn)從第三個字符串開始讀文件內容:
info命令獲取信息
假如創(chuàng)建了一個過程:proc hello { a b c } {puts hi}
執(zhí)行命令:info args hello,則返回a b c,參數列表
執(zhí)行命令:info body hello,則返回puts hi,函數體
info procs,返回所有的過程的列表
info procs hello,如果存在hello過程則返回hello字符串,不存在則不返回
info commands,則列出解釋器支持的所有命令
info commands create_ip,create_ip是vivado支持的tcl命令,所以這個info返回的值是create_ip,如果不支持該命令的話,則不返回值
info exists kkk,判斷kkk變量是否存在
info vars,返回當前變量名的列表
info vars i,如果存在該i變量則返回i字符串,不存在則不返回
info globals,返回全局變量的列表
info globals env,如果存在該env全局變量則返回env,不存在則不返回
info locals,返回local變量列表
info locals i,如果存在該i局部變量則返回i,不存在則不返回
info hostname,返回主機名
info cmdcount,則返回當前解釋器已經執(zhí)行的命令個數
info tclversion,返回解釋器版本號
info level,返回當前的在棧中的絕對位置
info level 1,如果加了參數數字,則返回該層的命令和參數
注:uplevel命令(連接參數)
既然說了level那就把uplevel命令說了,level值為0代表頂層,level代表在棧中的絕對位置,過程調用的時候,一層比一層的level值高1,被調用的過程中若想在上一層的環(huán)境中執(zhí)行操作,那么就需要uplevel命令了
proc hello {} { uplevel set a “helloworld” }
set a hi ; hello ; puts $a
注:upvar命令(連接變量)
既然說了uplevel那就把upvar命令也說了吧,其類似于uplevel命令,但是其側重的是在不同層之間連接單一變量
proc hello {a} {upvar $a x ; set x helloworld}
set i hi ; hello i ; puts $i
系統(tǒng)異常、系統(tǒng)監(jiān)視
catch命令
用于阻止因錯誤而導致的中斷執(zhí)行,類似python中的異常,執(zhí)行成功返回0,否則返回1
unknown命令
我將這個指令歸為異常指令
使用方法:首先定義一個unknown過程,這個過程的參數為cwd(命令)和args(參數)
proc unknown {cwd args} {
puts commend:$cwd
puts args:$args
}
這樣的話,當有未知命令或者打錯了代碼的話,就可以通過unknown過程,控制錯誤
time命令
time “set i 10”,該命令將計算執(zhí)行的時間
trace命令
監(jiān)視變量的存儲的命令,感覺暫時用不到,需要用到的時候再看
命名空間namespace
命名空間是命令和變量的集合,通過命名空間的封裝,來保證他們不會影響其它命名空間的變量和命令
設置新命名空間
首先定義兩個hello過程,其中一個在hlf命名空間內,然后測試
namespace eval hlf {pro hello {} {puts hello_hlf}}
pro hello {} {puts hello_all}
設置新變量
直接通過set hlf::i 888,就可以對hlf空間的i進行設置
刪除命名空間
命令:namespace delete hlf
不同命名空間共享變量和過程
通過export和import命令,完成一個命名空間導出過程,另一個命名空間將其導入,完成過程共享
對命名空間的變量進行設置或訪問
variable命令,以例子說明:
namespace eval hlf {
variable i 5
proc next {} {variable i;return [incr i]}
proc reset {} {variable i;set i 0}
}
目前的理解就是可以在同一命名空間內的不同過程中傳遞變量,也就不深究了
到此為止算是對TCL的基本使用有了一個大致的理解,里面還有很多具體的函數和函數選項沒有涉及到,如果之后用的到的話再做補充吧,但是我覺得,應對VIVADO的TCL的語法,這些基礎語法應該足夠了的,接下來就是對VIVADO自帶的TCL的庫里的函數,進行一個了解了
之后遇到不懂的命令,就直接輸入命令 -help,就可以看到一堆幫助了
評論
查看更多