Tool Command Language(TCL)


TCL脚本是大多数EDA工具的交互命令语言,所以跨平台复用性高。

TCL是一种解释执行的脚本语言,是用一个C/C++语言过程库实现。

运行 tclsh

可在Linux中使用语句tclsh运行TCL文件

tclsh test.tcl

或者使用命令行模式,注意使用exit退出命令行模式

在这里插入图片描述

下面对TCL进行介绍

1. 语法

一个TCL脚本可包含一个和多个命令

每个命令第一个单词表示命令名,其他单词则是字符串类型的参数,相互之间用空格隔开

多个命令之间可用换行符or分号隔开

例如

# 变量x的值是字符串"10"
set x 10;

# 变量y的值是字符串"x+100",而不是110,注意!!!
set y x+100;

TCL注释用#表示
可以将命令名看作是函数名,后面每个空格隔开一个参数。例如set x 10;就类似C语言中set(x,10);
所以说,参数数目要匹配。例如set a 1 2;并不会将a的值设定为"1 2",而是报错参数超过了2

那么我想用计算x+100的值并赋给y,怎么操作呢?

1.1. 替换

替换的作用就是告诉TCL解释器,用到的变量的值而非字符串

变量替换 $

含义是将字符串中的"x"替换成 变量x的值"10"

x前加上个$符号就行,即

set y $x+100;

但注意,此处y的值还不是字符串"110",而是字符串"10+100",所以变量替换还没完。

TCL脚本中,除了命令,不带$一律按照字符串处理

我们还需要告诉TCL解释器,将"10+100"当做一个表达式计算

如果有下划线则$会包含下划线,即
set x 1;set x_1 2;set y $x_1;,则y的值为"2"而不是"1_1"

命令替换 []

含义是将字符串解释成一个命令,例如

# 会报错,认为该命令参数超过2
set y expr $x+100;

# y的值是字符串“110
set y [expr $x+100];

这里的expr命令就是将后面的字符串看作一个表达式进行计算

反斜杠替换 \

其实就是C语言中的ANSI C中的制表符,这下知道怎么写空格啦

#a的值为“1 2 3
set a 1\ 2\ 3;

TCL支持的反斜杠替换为

反斜线序列含义
\ 空格
\n换行
\tTab

双引号 “”

除了直接使用\表示空格外,还可以使用双引号,双引号 只处理$、[]两种替换

例如

set x 10;
set x_1 20;

# 表示y的值为"10 ddd"
set y "$x ddd";

# 想表示为"$x ddd",但报错
set y "$"x" ddd"";

觉得容易搞混的话,可以每次都这么写set b "abc";set a "10";就知道那些都是字符串了

2. 变量

对于简单变量,包含两个部分内容,名字和值

set 与 unset

定义一个变量、返回一个变量的值 或 删除多个变量

set与unset的定义如下:

# 为变量定义值
set [变量名] [];

# 清除变量
unset [变量名1or数组1] [变量名2or数组2] [变量名2or数组2] ...;

例如

set a 1;
set b 2;
set c $a.1;
set e "cdf $ab";

# 删除变量a、b、c、d、e
unset a b c d e;

字符串加 append

把字符串加到某个变量后面

append [变量名] [];

例子

set a def;
# a的值为"defghi"
append a ghi;

整数加 incr

将原来的值加上一个整数,要求原值和新加的值都是整数

incr [变量名] [整数常量];

例子

set b 2;
incr b 3;

2.2. 字符串

返回字符串 format

返回一个字符串,类似于Systemverilog中的$sformatf()

注意%d、%s等制表符都是通用的

format "[字符串]" $[变量1] $[变量2] $[变量3] ...

例子

set nums 10;
set msg [format "number of pears is %d" $nums]; 

scan

可以看作是format的逆,format根据几个变量凑成一个字符串,而scan则是从一个字符串中提取信息给几个变量.

#显然带制表符的字符串a 中制表符数目要与后面的变量数目相同
scan "[字符串s]" "[带制表符的字符串s]" [变量1] [变量2] [变量3] ...

例子

scan "number of bananas is 24 6" "number of bananas is %d %d" a b;
puts $a;
puts $b;

执行运算 expr

表示将后面的字符串当做数学函数执行运算,

expr [表达式];

例如

set x 2;
expr $x*sin($x<3);

匹配正则表达式 regexp

判断字符串是否与某正则表达式匹配,返回1或0

正则表达式含义

字符含义
.任意字符检查
^从头开始检查
$从末尾进行检查
a、b、c等字符对应字符检查
*进行0次或多次检查
+进行1次或多次检查

3. 数据结构

3.1. 关联数组

是数组但本质上还是关联数组

set 与 unset

set表示向关联数组内添加元素,unset表示去除

set [数组名]([]) [];
unset [数组名]([]);

例子

set day(monday) 1;
set day(tuesday) 2;
set a $day(monday);
unset day(monday);

3.2. 列表

TCL中使用{}来表示一个列表,各元素用空格隔开,列表可以相互嵌套

set a {1 2 3 {4 5 6}};

元素组成列表 list

使用list可返回由多个元素(也可以为列表) 组成的列表

list [元素1] [元素2] [元素3] ......

例子

# l的值为{{a b c d} {e f {g h} i j}},而不是{a b c d e f {g h} i j}!!!
set l [list {a b c d} {e f {g h} i j}];

列表组成列表 concat

使用concat可返回由多个列表 组成的新列表

concat [列表1] [列表2] [列表3] ......

例子

# l的值为{a b c d e f {g h} i j},而不是{{a b c d} {e f {g h} i j}}!!!
set l [concat {a b c d} {e f {g h} i j}];

返回列表元素 lindex

格式如下

lindex [列表] [整数下标];

例子

# a的值为 {e f g}
set a [lindex {a b c d {e f g}} 4];

返回列表元素个数 llength

一维列表元素的个数

llength [列表];

例子

# a的值为 6
set a [llength {a b c d {e f g} h,i,j,k}];

下标插入元素 linsert

返回插入新元素之后的列表

linset [列表] [下标] [元素1] [元素2] [元素3] ...;

例子

# a的值为 {a {1,2,3} {4 5 6} 7 b c d {e f g}}
set a [linsert {a b c d {e f g}} 1 {1,2,3} {4 5 6} 7 ];

列表拆分为TCL脚本,并顺序执行 eval

eval的功能是将列表拆分为TCL脚本,依次执行

# 变量initiate是列表,但写的是脚本
set initiate {
	set a 1;
	set b 2;
	set c 3;
};

set initiate [concat $initiate {set d 4;}];

# 等价于执行set a 1;set b 2;set c 3;set d 4;
eval $initiate;

# 打印 1;set
puts [lindex $initiate 2];

不仅可以拆分命令,还可以拆分值

例如

# 注意这里的filelist的值是一个列表!!!例如{uart_tx.v uart_rx.v uart.v}
set filelist [glob -nocomplain *.v];

# 执行的是 file delete uart_tx.v;file delete uart_rx.v;file delete uart.v;
# 注意不能丢掉eval,否则file delete命令的参数就成了一个由多个文件名组成的列表!!!
eval file delete filelist;

TCL脚本构造命令eval

4. 子程序

4.1. 控制流

和众多语言一样,该有的控制语句都有

if

注意写法细节,见下面的原型

# 注意if{要有一个空格,否则TCL会当做一个命令
# 每个{一定要放在上一行,否则TCL会读完上一行就认为if结束

if {表达式1}{
	TCL脚本1;
} elseif {表达式2}{
	TCL脚本2;
} elseif {表达式3}{
	TCL脚本3;
} else {
	TCL脚本4;
}

例子如下

if {$x == 1}{
	set nums(first) $x;
}elseif {$x == 2}{
	set nums(second) $x;
}elseif {$x == 3}{
	set nums(third) $x;
}else {
	set nums(first) 0;
	incr nums(first);
}

while

写法如下

while {表达式}{
	TCL脚本;
}

for

各表达与C语言中的for循环类似

for {表达式1} {表达式2} {表达式3}{
	TCL脚本;
} 

例如

for {set i 0} {$i <= 10} {incr i 1}{
	lappend b [lindex $a $i]
} 

foreach

foreach [下标标量] $[列表]{
	TCL脚本;
}

switch

类似于case语句,原型如下

switch [可选参数] $[列表]{
	[匹配模式1] {TCL脚本1}
	[匹配模式2] {TCL脚本2}
	...
}

这里的 [可选参数] 如下:

# 精确匹配
-exact

# 与string match匹配方式相同,默认为这个
-glob

# 正则表达式匹配
-regexp

break 与 continue

这个与C语言的含义相同,直接用

4.2. 过程

函数 proc

类似于C语言中的函数,可以定义和调用,也可以使用return

# 过程定义
proc [过程名] { [形参1] [形参2] [形参3] ... }{
	TCL脚本1;
	return TCL脚本2;
}

# 过程调用
[过程名] [实参1] [实参2] [实参3] ...;

例如

proc adder { nums }{
	set sum 0;
	for{set i 0;} {$i < 4} {incr i 1}{
		incr sum $nums($i);
}
	return sum;
}
set a(0) 11;
set a(1) 1;
set a(2) 6;
set a(3) 91;
set res [adder a];

认识全局变量 global

注意TCL的proc内部不认识全局变量,必须使用global a来引用全局变量a

例如

set a 10;

# 只有声明了global a,过程块才认识a
proc use {}{
	global a;
	return [expr $a+10];
}

5. 文件与目录

5.1. 文件访问

source

读一个文件,并将整个该文件的内容作为一个脚本求值

source e:/test/hmwk.tcl

返回文件句柄 open 与 close

open以某种访问方式打开文件,并返回指向该文件的字符串(类似于指向该文件的句柄)

close加上指向该文件的$字符串,表示关闭

set f [open [文件路径] [访问方式]];

其中[访问方式]有
r:只读,默认方式
r+:	读写
w:	重写,创建/查找文件内容,并清空重写
w+:	读重写,创建/查找文件内容,并清空重写、可读
a:	只写,文件必须存在,且指向文件尾
a+:	读写,文件必须存在,且指向文件尾

# 关闭文件
close $f;

文件读 gets

可多次调用逐行读取文件赋给变量,并返回该行的字符数,文件尾返回-1

# 变量1是可选的,用于获取文件某行的内容
gets $[指向文件的变量] [可选变量1]

例子

proc read { filename }{
	set f [open $filename r];
	set linesnum 0;
	
	# line是每一行的内容,[gets $f line]返回的是该行的字符数
	while { [gets $f line] > 0 }{
		incr linesnum 1;
	}
	return $linesnum;
}

set fn "abc.v";
set fn_lines [read $fn];

文件写 puts

可多次调用将变量的内容逐行写入文件,返回空字符串

同时可以用于打印内容

# 指向文件的变量是可选的,没有就在Linux终端打印
puts $[可选指向文件的变量] [变量]

例子

set name "wdnmd";
puts $name;

5.2. 文件控制

cd、pwd

与Linux一样,用于更改操作目录

注意Linux、TCL表示目录均为’/‘,而不是windows中的’\'

# pwd没有参数,返回当前操作路径
set dir [pwd];

cd [路径字符串]

搜索文件 glob

用于在某目录下使用正则表达式 搜索文件,返回文件名集合

# -nocomplain表示找不到文件不会报错
glob [可选的-nocomplain] [正则表达式];
cd "/home/mywork";
set filelist [glob -nocomplain *.v *.sv];
puts filelist;

文件控制 file

用于对文件进行控制

部分原型如下

# 返回文件是否存在于当前目录下
file exists [文件];

# 创建目录
file mkdir [目录1] [目录2] [目录3] ...;

# 将文件或目录复制到目标目录下, 只有开启-force才会覆盖
file copy [可选的-force] [文件1or目录1] [文件2or目录2] [文件3or目录3] ... [目标目录];

# 删除文件或目录
file delete [文件1or目录1] [文件2or目录2] [文件3or目录3] ... ;

例如对搜索到的某些文件进行删除

# 注意glob返回的是列表,而file delete作用的是多个空格隔开的参数
# 故所以使用eval解析
eval file delete [glob *.v];

# 等价于下面这些
file delete a.v;
file delete b.v;
......
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值