文章目录
- 前言
- 一、安装
- 二、变量列表
- 1、置换subtitution
- 2、变量
- 3、数组
- 4、列表
- 5、一些命令
- 三、控制流
- 1、if语句
- 2、foreach
- 3、break:直接结束循环
- 4、continue:结束本次循环
- 5、while
- 6、for循环
- 7、switch
- 四、过程函数
- 1、proc自定义函数
- 2、全局变量和局部变量
- 五、正则表达式
- 1、锚位^ $
- 2、正则匹配指令 regexp
- 3、( )捕获变量
- 六、文本处理
- 1、读写文件
- 2、glob和file
- 例题
- 七、Synopsys TCL语言
- 1、对象:cell, net, port, pin
- 2、有条件地查找对象
- 3、总结
前言
2022.11.21 开始学习TCL语言
2023.3.21 更新
TCL(Tool Command Language
)命令的格式是命令+字符串
,第一个是命令,后面都是字符串,tcl的解释器(逐行执行
)会根据命令去对后面的字符串进行相关操作。
注释符号:#
一、安装
启动tcl命令行,以%开头
sudo apt install tcl //安装tcl
tclsh //启动tcl
%
二、变量列表
1、置换subtitution
(1)变量置换$
:把 $ 后面的变量置换成对应的值
set a 2
puts $a //输出2set b $a+100 //b=2+100,并不是102,2+100只是个字符串
(2)命令置换[]
:[ ]内是独立的TCL指令
tcl解释器会把[ ]里面的内容看作是命令去执行,执行完之后的102,去给变量b,102仍然是个字符串
set b [expr $a+100] //必须要加[]
set a [expr 3+3] //6
expr 5/2 //2
expr 5.0/2 //2.5
expr 5/2.0 //2.5
(3)反斜杠置换\
\t
:制表符
\n
:换行
第一种写法会报错,解释器会识别到set给a的字符串有两个
第二种写法解释器会把中间的空格当作分隔符,hello world会被看成一个单词
第三种是可以的
set a hello world
set a hello\ world
set a {hello world}
(4)双引号和花括号
" "
:对$
和[]
分别进行变量置换和命令置换,对各种分隔符不做处理,如空格等
set y "$a add" //y=2 add
set a 2
set y 0.5
puts "[expr $x+$y]" //2.5
puts "\[expr $x+$y\]" //[expr 2+0.5]
puts "\[expr \$x+\$y\]" //[expr $x+$y]
{ }
:所有字符都是普通字符
set a 2
set a.1 4
set b $a.1 //b=2.1
set b ${a.1} //b=4
2、变量
设置:set
变量名 变量值
取值:puts
$ 变量名
set a 2
puts $a
puts ${a}_1 //2_1
3、数组
类似于SV中的关联数组,索引值可以是整型也可以是字符串
不可以单独声明一个数组,数组只能和数组元素一起声明
定义:set 数组名(元素名)值
取值:$数组名(元素名)
set day(monday) 1
puts $day(monday) //输出为1
array size cell_1 //3array names cell_1
4、列表
标量的有序集合 ,列表可以嵌套,里面元素可以是列表
定义:set 列表名 {元素1 元素2…}
取值:$列表名
list 1 2 {3 4}
set list1 {1 2 3}
puts $list1 //1 2 3
只有lappend使用的时候不要加$符号
//TCL里面第一个总是命令
set list1 {1 2 3}
set list2 {4 5 6}concat $list1 $list2llength $list1 //3
llength [concat $list1 $list2] //6lindex $list1 1 //从0开始记数,输出为2
lindex $list1 [expr [llength $list1] - 1] //获取最后一个元素lappend list1 4 //在末尾插入4
lappend list1 $list2 //1 2 3 {4 5 6}
lindex $list1 3 //4 5 6
lindex [lindex $list1 3] 0 //4lsort $list1 //安装ASCII排序,由小到大
lsort -real $list1 //按照浮点数大小
lsort -unique $list1 //唯一化,删除重复元素
5、一些命令
unset
:删除变量或数组元素
append
:把文本添加到一个变量后面
incr
:把一个变量加上整数,都必须是整数类型
expr
:经常用,TCL支持常用的数学函数,凡是计算都要加上这个
eval
:构造和执行tcl脚本的命令,可以接收多个参数,把这些参数用空格隔开然后创建一个脚本
unset a b
set txt hello
append txt "!how are you"
incr b 3
三、控制流
1、if语句
if {cond1}{
…
}elseif{cond2}{
…
} else {
…
}
上面是if的格式,花括号要放在上一行(固定格式)
2、foreach
foreach 变量 列表 循环主题
按照顺序取列表里面的每一个变量
set list1 {1 2 3}
foreach i $list1{puts $i
}
3、break:直接结束循环
set list1 {3 2 1}
foreach i $list1{if{$i == 2}{break}puts $i
} //最后只输出3
4、continue:结束本次循环
set list1 {3 2 1}
foreach i $list1{if{$i == 2}{continue}puts $i
} //最后输出3 1
5、while
while{cond1}{
…
}
只要条件满足就一直执行花括号里面的命令,不满足条件停止循环,while中断并返回一个空字符串
6、for循环
for 参数初始化 判断条件 重新初始化参数 循环主体
先判断语句符合,进入循环,重新初始化参数,再进行判断
for {set i 3}{$i>0}{incr i-1}{puts i
} //输出3 2 1
7、switch
switch option string{
…
}
option的选项默认是glob
-glob
:匹配字符串
-regexpr
:正则表达式的匹配方式
-exact
:精确匹配
switch $x{b {incr t1}c {incr t2}
}
四、过程函数
1、proc自定义函数
proc 参数名 参数列表 函数主体
可以写return或者不写
proc add {a b} {set sun [expr $a + $b]return $sum
}
add 3 4 //输出为7
2、全局变量和局部变量
全局变量
:在所有过程之外定义的变量。
局部变量
:对于在过程中定义的变量,因为它们只能在过程中被访问,并且当过程退出时会被自动删除。
指令global
:可以在过程内部引用全部变量
set a 4
proc sample {x}{global aincr areturn [expr $a + $x]
}
sample 3 //输出为8
五、正则表达式
正则表达式是一种特殊的字符串模式,用来去匹配符合规则的字符串。
\w
:匹配字母、数字、下划线
\d
:匹配数字
\s
:表示空格
.
:表示任意一个字符
先写代表的字符,再写个数匹配
1、锚位^ $
2、正则匹配指令 regexp
regexp {^\d+.*\d+$} "1 dsg 1" //匹配以数字开头数字结尾的字符串
//输出为1 表示匹配成功
3、( )捕获变量
% regexp {\s(\d+).*} "snow is 30 years old" total age
% puts $total30 years old
% puts $age
30% regexp {\d+} "snow is 30 years old" age //直接匹配其中的数字
1
% puts $age
30
六、文本处理
1、读写文件
open
:open 文件 打开方式
r
:读模式,默认方式w
:写模式w+
:读写,文件存在则清空内容,否则创建新文件r+
:读写,文件必须存在a
:只写,文件必须存在,指针指向文件尾a+
:读写,指针指向文件尾,文件不存在就创建
gets
:gets fileId 变量名,gets读fileId标识的文件的下一行,并把该行赋给变量,并返回该行的字符数(文件尾返回-1)
close
:close fileid
% set INPUTFILE [open file.txt r] //以只读的方式打开文件
file3 //三个字符,里面每行分别是1 2 3
% while {[gets $INPUTFILE line]>=0} {//读取文件,把每一行复制给line这个变量
puts "$line" //输出该变量,为什么要用引号?
}
1
2
3
% close $INPUTFILE //关闭文件
% set INPUTFILE [open file.txt w] //以写的方式打开
file5 //这里输出的是获得的句柄值
% puts $INPUTFILE "123" //写入的值完全覆盖之前的1 2 3
% close $INPUTFILE //一定要记得关闭文件
2、glob和file
glob
:查找当前目录下的文件,返回列表,进行模糊查找。再使用参数展开语法{*}
把列表元素作为独立参数给其他指令
file
:可以执行文件相关的一些操作
glob *.sv *.v
file delete {*}[glob *.sv *.v] //分别删除sv和v文件
eval file delete [glob *.sv *.v] //这种方式也可以,eval命令会把接收的参数用空格隔开
例题
先把a = 1, b = 2,c = 3存到文件里面
把代码写到test.tcl
文件里面,然后在source test.tcl
输出结果就是6!
set sum 0
set IN [open file.txt r]
while {[gets $IN line] >=0} {if { [regexp {^\w\s+=\s+(\d)} $line total num]} {set sum [expr $sum + $num]}
}
close $IN
puts $sum
七、Synopsys TCL语言
reference
:ENCORDER、REGFILE、INV
instance
:U1、U2、U3、U4
//这些是Synopsis TCL的指令
get_ports CLK //找到CLK这个端口 输出为{CLK}
get_ports * //所有端口 {A B C D CLK OUT1[0] OUT1[1]}
get_ports C* //匹配C开头的端口get_cell U4 //找到design
get_cell *
get_cell U*
get_cells *3 //输出 {U3}get_nets INV*
get_nets *//查找design中有多少个net,两种方式
llength [get_object_name[get_nets *]] //get_object_name把它转换为列表,再去获得列表的长度,这里用的TCL自身的语法
sizeof_collection [get_nets *] //get_nets 得到的数据类型为集合collection,sizeof_collection为synopsis TCL指令,直接获得集合的大小get_pins */Z //查看design当中有哪些pin的名字叫做Z {INV0/Z INV1/Z}
get_pins */Q* //查看design当中有哪些pin的名字以Q开头 {ENCODER/Q0 ....}
1、对象:cell, net, port, pin
- 任何一个属性都可以用
get_attribute
得到, list_attribute –class *
可以得到所有object 的属性,- 部分属性可以用
set_attribute
来设置
1.1 Cell object
属性 ref_name
: 用来保存其map到的reference cell名称
get_attribute [get_cells –h U3] ref_name //输出 {INV}
1.2 Pin object
属性 owner_net
: 用来保存与之相连的net的名称
get_attribute [get_pins U2/A] owner_net //输出 {BUS0}
1.3 Port object
属性 direction
: 用来保存port 的方向
get_attribute [get_ports A] direction //输出 {in}
1.4 Net object
属性 full_name
: 用来保存net的名称
get_attribute [get_nets INV0] full_name //输出为INV0
get_object_name [get_nets INV0] //输出为INV0get_attribute INV0 full_name
Error: No attribute found
2、有条件地查找对象
2.1 get_ * -f
get_ports * -f "direction == in"
{A B C D CLK}get_pins * -f "direction == out"
{U1/Q0 U1/Q1 U2/Z U3/Z U4 REGFILE/Q[1] REGFILE/Q[0]}get_cells * -f "ref_name == INV"
{U2 U3}
2.2 get_ -of
不同对象的连接关系:
- port-net
- net-port/pin
- pin-net
- cell-pin
get_nets -of [get_port A] //A,单数和复数好像没有区别get_net -of [get_pin U2/A] //BUS0get_pin -of [get_net INV1] //U3/Zget_pins -of [get_cell U4] //{U4/D0 U4/D1 REGFILE/Q1 REGFILE/Q2}
3、总结
-filter:==相等 !=不相等 =~匹配 !~不匹配
-nocase:不区分大小写