前言:对在EDA仿真工具中使用的TCL语言做了简单介绍。
TCL解释语言
- TCL在EDA工具中使用。
- TCL(Tool Command Language)是一种解释执行的脚本语言,使用c、c++语言的过程库实现。
- TCL脚本执行依赖于解释器(逐行执行)。
- TCL有效命令行以命令+字符串(结合空格间隔符)形成。
- 置换($、[]、 \)和引用(“”, {})。
- 命令eval、expr、source、exec
- 掌握{*}配合glob等返回list后的操作。
- TCL中的注释是#,类似于 //。
1. 基本用法
一个TCL脚本可以包含一个或多个命令,命令之间必须用换行符隔开。
set a 1
set b 2
或set a 1; set b 2 //TCL有效命令行以命令+字符串(结合空格间隔符)形成
TCL有效命令行以命令+字符串(结合空格间隔符)形成。
- set是有效命令 a是字符串参数。
- TCL的每一个命令包含一个或几个单词,第一个单词代表命令名,另外的单词则是这个命令的参数,单词之间必须用空格或Tab键隔开。
- TCL在分析命令时,把所有的命令参数都当做字符串看待
%set x 10 //定义变量x,并把x的值赋为10
%set y x+100 //y的值是x+100 ,而不是110
上述代码,x被看做字符串 x+100的一部分,如果想使用x的值10,会必须告诉TCL:这里的x不是字符串,是变量的值。这时候就会用到置换功能。
2. 置换功能
TCL提供三种形式的置换:变量置换、命令置换和反斜杠置换。
2.1 变量置换
- 变量置换由$符号标记,会导致变量的值插入一个单词中。
%set y $x+100 //y的值是10+100,x被置换成它的值100
这时,y的值还不是110,而是10+100, 此时TCL把10+100看成一个字符串而不是表达式,y要想得到值110,必须使用命令置换,使TCL把10+100看成一个表达式并求值。
2.2 命令置换
- 命令置换是由[]括起来的TCL命令及其参数,会导致某一个命令的所有或部分单词被另一个命令的结果所代替。
%set y [expr $ x+100]
y的值为110,当TCL遇到字符’ [ ’ 时,会把随后的expr作为命令名,执行与expr对应的c过程。如果去掉[] ,此时会报错,因为TCL只会把第一个单词作为命令,其他单词只是字符串。
2.3 反斜杠置换
- 反斜杠置换可以在单词符号中插入,插入符号会把特殊符号当做普通符号处理。
%set msg multiple\ space
如果没有\的话 此时有四个单词,TCL会报错,加了\后,空格不会被当做分隔符,mulltiple space被认为是一个单词。
2.4 双引号和花括号
-
双引号和花括号可以把分隔符等特殊符号当做普通字符,与反斜杠相同,但有所不同。
-
对双引号中的各种分隔符将不做处理。但对换行符、 $ 和[] 两种置换符会正常处理。
%ser y " $x ddd" //x会被转换
3. TCL中的变量
- TCL简单变量包含两部分,名字和值(可以是任意字符串),可以从在上面的代码中看出来。
- 在变量置换时, $符号与 $f符号之后第一个不是字符、数字和下划线之间的内容作为置换的变量。
%set a 2
%set a.1 4
%set b $a.1
执行最后一个命令时,置换的是 $a,最终结果为2.1,与我们想象的结果不同。这时候可以使用{}把变量名括起来。
%set b ${a.1} //结果为4
- TCL中set能生成一个变量,也能读取或改变一个变量的值。
%set a {kdfj kdfg}//定义a并赋值
%set a //读取a的值
3.1 变量:数组
- 数组是元素的集合。 与之前所学的数组不同。
%set day(monday)1
%set day(tuesday)2
day为数组名,monday、tuesday分别为数组中的元素,值分别为1和2.
3.2 相关命令
- unset删除变量,可以同时删除很多个。
%unset a b day(monday)
- append把文本加到变量的后面。
% set t hello
%append t " !" //结果为hello!
- incr把一个变量值加上一个整数。要求两个值都是整数。
%set n 2; incr n 3
3.3 表达式
- TCL支持常用的数学函数
%set x 2
%expt 2*sin(3)
数学函数只有出现在expr之后才有意义
- list在TCl中表示集合,可以嵌套,里边的元素默认为字符串。
- 生成一个list,1 2 {3 4 }是list 的元素。
%list 1 2 {3 4}
- 合并两个listconact
%concat{1 2 3 }{4 5 6}// {1 2 3 4 5 6}
- 返回第n个元素 lindex list n
%lindex {1 2 {3 4}} 2
- 返回list的元素个数llength list
%llength{1 2 {3 4}}
- list插入元素
%linsert {1 3 4} 1 2 3 //结果为1234
- if
if{ $x>0 } { //花括号必须在这里,if与花括号直接有空格
...
}else{
...}
- 循环命令while
set b " " //给b一个变量
set i [expr [llength $a] -1]//
while { $i>0}{
lappend b [lindex $a $i] //把a的值给b
incr i -1 //给i-1
}
- 循环变量for
语法:for init test reinit body
参数init是一个初始化脚本,第二个参数test是一个表达式,用来决定循环什么时候中断,第三个reinit是重新初始化的脚本,第四个body也是脚本,代表循环体。
假设a是一个链表,把a 的复制到b
set b ""
for {set i [expr[llength $a] -]} { $i>0} {incr i -1} {lappend b [lindex $a $i]}
- foreach
foreach varname list body
第一个参数varname是一个变量。第二个参数list是一个集合,第三个参数body是循环体,每次取得一个元素都会循环一次。
set b ""
foreach i $a{
set b [linsert $b 0 $i]
}
- switch
一旦switch找到一个模式匹配,就会执行相应的脚本,并返回脚本的值。
%switch $x{
b {incr t1}
c {inct t2}}
- 在循环体中,可以用break和continue命令中断循环。 break命令结束整个循环过程并从循环中跳出,continue结束本次循环。
- source命令读一个文件并把这个文件内容作为脚本求值。
%source e:/tcl&c/hello.tcl
- eval命令用来构造和执行TCL脚本。把所有参数以空格隔开组合到一起,并进行求值。
%eval set a 2; set b 4
- TCL中过程由proc命令产生
%proc add {x y }{expr $x+ $y}
- proc命令的第一个参数是要定义的过程名字,第二个参数为参数列表,参数之间空格隔开,第三个参数为过程体,生成命令后可以调用。
%add 1 2 //3
在定义过程中,可以使用return在任何地方中断过程,并返回参数作为结果。
3.3 局部变量和全局变量
%set a 4
%proc sample {x}{
global a //声明a来自外部
incr a
return[expr $a + $x]}
%sample 3
%set a
- 字符串操作
format formatstring ? vlue value…?
按formatstring提供的格式,把各个value的值组合到formatstring中形成新字符串,并返回。
%set name john
%set age 20
%set masg[format "%s is %d years old" $name $age]
//john is 20 years old
- scan
scan是format命令的逆。
%scan "some 26 34 " "some %d %d " a b
%set a //26
%set b //34
- 文件访问
open name ? access?
open命令,以access方式打开name。
- 使用pwd和cd管理工作目录。pwd返回当前目录的完整路径,没有参数,cd切换工作目录。
- glob和file用来操作或获取文件。
glob命令采用一种或多种模式作为参数,并返回所有文件的列表。
%glob *.c * .h //把文件中后缀是.c 和.h的找出来
file delete *.tmp //错误不识别 *
file delete{*}[glob *.tmp]
eval file delete[glob *.tmp]
file copy? force??source target
这个命令把source中指明的文件或目录递归的拷贝到目的地址,只有当存在force选项时,已经存在的文件才会被覆盖。试图覆盖一个非空的目录、以文件覆盖目录、目录覆盖文件都会报错
file mkdir dir? dir ...? //创建dir中指明的目录
file owned name //name是否存在,存在返回1,否则0
file executable name //name是否可以执行,可以返回1,否则0