Vivado之TCL脚本语言基本语法介绍

可编程逻辑

1366人已加入

描述

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 : 结束遍历

TCL

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 表达式

TCL

6》list列表

类似python中的列表,比如:{abc {def {jkl ccc}}}是一个有两个元素的列表 abc和{def {jkl ccc}},Tcl中对list的命令有:

(首先set l {abc {def {jkl ccc}}},下面实例中将对这个l列表进行操作)

TCL

需要注意的是:大部分命令都是对$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+(空格)+{

中间行: 逻辑运算

最后行: }

TCL

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操作选项较多,就直接列个表了,表示如下:

TCL

除此之外,file 的 stat 状态操作选项:

命令格式:file stat name k,结果存在数组k里

TCL

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,如果加了参数数字,则返回该层的命令和参数

TCL

注: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

目前的理解就是可以在同一命名空间内的不同过程中传递变量,也就不深究了

到此为止算是对TCL的基本使用有了一个大致的理解,里面还有很多具体的函数和函数选项没有涉及到,如果之后用的到的话再做补充吧,但是我觉得,应对VIVADO的TCL的语法,这些基础语法应该足够了的,接下来就是对VIVADO自带的TCL的库里的函数,进行一个了解了

之后遇到不懂的命令,就直接输入命令 -help,就可以看到一堆帮助了

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分