之前看过一个华为tcl的手册,看过数字集成电路静态时序分析这门课,加上在时序分析中用过一些,趁着双十一买了高亚军老师新出的《vivado/Tcl零基础入门与案例实战》。
Tcl是一门脚本语言,同时也是跟python类似的解释性语言,所谓的解释性语言就是执行时候顺序解释执行,而不需要编译,当然它也比较慢。同时,tcl语言数据类型与其他语言不同,它默认数据类型为string类。
安装好vivado后会默认带一个vivado tcl shell,可以直接用这个来跑代码。
也可以按照下面的方式来跑Tcl脚本(引用来自于数字集成电路静态时序分析),下面的博客都是在wish.exe上面跑的。
Tcl的常用写法就是一行代码一个指令,但是也可以在一行写多个指令,中间用;分开,但是加上;的语句执行结果不会被打印(类似于Matlab)。
(System32) 1 % set x 1
1
(System32) 2 % set x 2
2
(System32) 3 % set x 1;set x 2
2
Tcl在注释时候需要在命令的第一个字符位置,分号可以表示一条指令的结束,所以注释#可以出现在两个位置,一行的开始,分号的后面。多行注释这可以使用\。
我们也可以发现如果分号右边是注释,它还是会返回分号左边指令的结果,所以我认为加上;的一行语句会打印最后一个有效的指令,这里注释没有意义,所以会打印最后一个指令输出结果为1。
如果注释大段,有三种方式:if命令、花括号、proc过程。
(System32) 1 % #一行的开始
(System32) 2 % set x 1;#分号的后面
1
(System32) 3 % #123 \
> 231
(System32) 4 % #if方法
(System32) 5 % if {0} {set x 10 ; set y 20;}
(System32) 6 % #花括号
(System32) 7 % set commment {set x 20; set y 20;}
set x 20; set y 20;
(System32) 8 % #proc过程,类似于函数,只有被调用才会出现。
(System32) 9 % proc set_commment{}{set x 20; set y 10;}
Tcl对于变量名没有严格要求,通过set来赋值,对于大小写敏感。
set <变量名> <变量值>
incr指令也能用来赋值
incr <变量名> <变量值,若缺省变量名初始值为1,否则加上变量值>
其中变量名以及变量值的数值都必须为整数
Tcl报错会将错误信息保存在全局变量errorInfo中
puts $errorInfo
打印错误信息的位置
(System32) 1 % set x 1
1
(System32) 2 % incr y
1
(System32) 3 % incr y 1
2
(System32) 4 % incr y -1
1
(System32) 5 % incr y 0.1
expected integer but got "0.1"
(System32) 6 % puts $errorInfo
expected integer but got "0.1"
(reading increment)
invoked from within
"incr y 0.1"
unset <变量名>
取消定义的变量,如果未定义会报错
info exists <变量名>
判断变量是否已经定义,若存在返回1,否则0
info tclversion
返回tcl版本
info hostname
返回主机名
(System32) 1 % set x 1
1
(System32) 2 % info exist x
1
(System32) 3 % unset x
(System32) 4 % unset y
can't unset "y": no such variable
(System32) 5 % info exist y
0
(System32) 6 % info tclversion
8.6
(System32) 7 % info hostname
laptop-5bsbjpik
变量的置换,时刻记住tcl里面数据类型以string为主,set x y并不会把y的变量值赋值给x,而是把y赋值给了x,如要一个$来获得y的变量值,即 set x $y,就会把y的变量值赋值给x,这就类似于c++里面的指针,可以类比y是一个对于它数值的指针,通过增加一个$用来访问指针对应地址空间的数值大小。
此外,Tcl对于变量名,会认为-以及.当做字符串分隔符来用,这个时候可以把变量名用{}括起来来避免报错。
append <变量名> <变量值>
这就相当于string的加号,直接在数值后面增加新数值位数
(System32) 1 % set x 1
1
(System32) 2 % set y x
x
(System32) 3 % set y $x
1
(System32) 4 % set a-b 1
1
(System32) 5 % set z $a-b
can't read "a": no such variable
(System32) 6 % set z ${a-b}
1
(System32) 7 % set a.b 1
1
(System32) 8 % set z $a.b
can't read "a": no such variable
(System32) 9 % set z ${a.b}
1
(System32) 10 % append z 21
121
$在同一层级下执行时,只会发生一次置换(最右边的$)。 对于$$var,有两种方式解决,一种是通过subst指令,一种是通过[]([]用于命令置换)。
(System32) 1 % set x 1
1
(System32) 2 % set y x
x
(System32) 3 % puts $$y ;#只执行最右边的$y
$x
(System32) 4 % subst $$y ;#方法一,用subst
1
(System32) 5 % puts [set $y] ;#方法二,用[]
1
(System32) 6 % puts [set [set y]] ;# $y等价于[set y]
1
[ ]用于命令置换,通常与expr一起配合使用,表示将执行结果以表达式形式返回。
(System32) 1 % set a 1
1
(System32) 2 % set b [$a*$a]
invalid command name "1*1"
(System32) 3 % set b [expr $a*$a]
1
反斜线置换\主要用于被当成特殊字符的换行符、空格、"["、"$"等,相当于c++字符串里面的\。
(System32) 1 % set a \$a
$a
(System32) 2 % set b a[x]
invalid command name "x"
(System32) 3 % set b a\[a\]
a[a]
(System32) 4 % set a \\
\
(System32) 5 % set a \b
(System32) 6 % set a \\b
\b
Tcl的置换只有两条规则,一是解析指令从左到右扫描一次,二是置换只会发生一层(即$$a只会置换右边的$a,左边的$被保存下来了)。
{ }里面的置换可能会被阻止(为什么是可能?如果是用来进行置换操作会阻碍里面的置换,但是如果用来做界限符比如if、循环语句、switch语句、数学表达式则不需要阻止);
“ ”则不会被影响。
同时使用时,最外层的符号决定一切!
(System32) 1 % set b "you are a {$a}"
you are a {1}
(System32) 2 % set b {you are $a "$a" }
you are $a "$a"
set a 1 | 赋值a=1 |
incr a 1 | a=a+1 |
incr a | a=1 |
puts $errorInfo |
打印错误信息的位置 |
unset a |
取消定义的变量a,如果a未定义会报错 |
info exists a | 判断变量是否已经定义,若存在返回1,否则0 |
info tclversion |
返回tcl版本 |
info hostname |
返回主机名 |
append a 1 |
若a=1,现在a=11 |
$$y | 若y=1,则返回$1 |
subst $$y | 执行两次$ |
puts "Hello World" | 打印Hello World |
set a [expr $c*$c] | 若c=2,将执行结果4,以表达式返回给a |
[1]vivado/Tcl零基础入门与案例实战
[2]数字集成电路静态时序分析