TCL脚本言语
Tcl(Tool Command Language)是一种很通用的脚本言语,它简直在一切的平台上都能够解说运转,并且VIVADO也供给了TCL指令行。最近发现TCL脚本形似比GUI下操作VIVADO效率高一些,便利一些。并且最近跟着官网文档做SDSOC的flatform,发现xilinx官网的文档里都是用TCL指令来完结操作,所以决计学习一下TCL的语法。
应用程序(如VIVADO)运用Tcl作为它的指令言语的优点:
1 Tcl供给了规范语法,一旦用户把握了Tcl就能够很简略的发布指令给根据Tcl的程序。
2 Tcl完结了许多的功用,使你的作业变得很便利。
3 TCl可作为程序间通讯的接口。
指令格局
一条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中榜首次呈现string1的方位,假设没有呈现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才干完结列表内容的更新,并且是直接更改列表的内容
7》proc自界说函数
proc:
proc hello {str} {
puts hello:$str
}
需求留意的是,假设不能一行写完,那主张依照如下格局来界说(主要是要将“{”放到榜首行的结尾):
榜首行: proc+(空格)+函数名+(空格)+{参数}+(空格)+{
中心行: 逻辑运算
最终行: }
全局变量global:
用于将进程中的局部变量变成外界可操作的全局变量
proc hello {} {
global x
set x hi
set i hello}
上述代码,履行成果:
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》循环操控
foreach循环:
假设想要将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循环:
TCL的for循环也是很相似C言语的:
for {set i 0} {$i 《 10} {incr i} {
puts $i
}
初始化i=0,规模 i《10 ,循环i=i+1
while循环:
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将字符串的内容,作为指令,履行
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”表明的是强制不换行打印,不然主动追加一个换行符
文件体系
根本常用操作:
gets –》 一次读一行文件
puts –》 写入文件
open –》 翻开文件
close –》 封闭文件
flush –》 改写缓冲区
cd指令
和shell中的cd相同
pwd指令
用于检查当时地点的目录
open指令
翻开文件,回来文件描述符
指令格局:open 文件名 形式,支撑6种形式,和其他编程言语中的文件IO,也是很相似的,形式如下:
r 形式: 翻开只读文件(文件有必要存在)
r+ 形式: 翻开可读写文件[r+和a+形式能够类比]
w 形式: 翻开只写文件,若文件存在则清空内容;若文件不存在则创立文件。
a 形式: 以追加方法翻开只写文件,若文件不存在,则创立;假设文件存在,则会在文件内容最终面追加写入的数据
xxxx
理论上说open |文件名 形式,在文件名前加个“|”符号,能够以管道的形式翻开文件,可是测验一向没有成功,之后用到的话再回来处理吧
xxxx
read指令
set f [open test.txt r]
read $f 6
close $f
能够运用eof指令,判别文件是否读完了,eof $f,读完回来1,不然回来0
上述代码直接从文件中读6个字节;假设想把文件内容悉数读出,则直接read $f;假设想一行一行读则运用gets指令:gets $f
source指令
指令格局:source $f
从对应的文件中读出内容,并传给Tcl解说履行
tell指令
回来文件的指针方位,指令格局:tell $f
file指令
指令格局:file option name
option操作选项较多,就直接列个表了,表明如下:
除此之外,file 的 stat 状况操作选项:
指令格局: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 可履行
seek指令
用于调整文件指针
指令seek $f 2,文件指针定位到序号为2,现在有一个文件名为s1.txt,内容为hello字符串,那么,规划一个程序完结从第三个字符串开端读文件内容:
info指令获取信息
假设创立了一个进程:proc hello { a b c } {puts hi}
履行指令:info args hello,则回来a b c,参数列表
履行指令: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,则回来当时解说器现已履行的指令个数
info tclversion,回来解说器版本号
info level,回来当时的在栈中的肯定方位
info level 1,假设加了参数数字,则回来该层的指令和参数
注:uplevel指令(衔接参数)
已然说了level那就把uplevel指令说了,level值为0代表顶层,level代表在栈中的肯定方位,进程调用的时分,一层比一层的level值高1,被调用的进程中若想在上一层的环境中履行操作,那么就需求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
体系反常、体系监督
catch指令
用于阻挠因过错而导致的中止履行,相似python中的反常,履行成功回来0,不然回来1
unknown指令
我将这个指令归为反常指令
运用方法:首要界说一个unknown进程,这个进程的参数为cwd(指令)和args(参数)
proc unknown {cwd args} {
puts commend:$cwd
puts args:$args
}
这样的话,当有不知道指令或许打错了代码的话,就能够经过unknown进程,操控过错
time指令
time “set i 10”,该指令将核算履行的时刻
trace指令
监督变量的存储的指令,感觉暂时用不到,需求用到的时分再看
命名空间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,就能够看到一堆协助了