tcl脚本编程知识点总结


mark

软件设置文件

以下是sysnopsys工具的setup文件,一般会把一些常用的设置以及脚本放入其中。

mark

command-line editer设置

如果习惯于vi或者emac编辑器,可以修改命令行的快捷键

icc2中已经不再使用set_cle_options命令。

可以使用sh_line_editing_mode或者

set_ app_options -as_ user_default -name shell. common. line_editing_ mode -value vi

log文件设置

set _pid [pid]
set filename_log_file “filename.log$pid”

压缩无用信息

suppress_message CMD-029

环境变量

可通过环境变量在文件间传递参数信息。

得到环境变量值

getenv name= set env(name)

设置环境变量

setenv name value=set env(name) value

执行系统命令

exec cmd
sh cmd
两者区别, exec不支持通配符,而sh支持

mark

尽量使用tcl命令

以下是一些系统命令与tcl命令的对应关系

mark

通过简单脚本来替代系统命令也是推荐的。

mark

tcl中数据类型

string

关于string’相关的命令总结

mark

list

创建list的三种方式

mark

使用花括号将无法进行变量替换,避免这种情况,建议使用list命令

mark

list操作相关命令总结

command task
concat Concatenates lists and returns a new list.
join Joins elements of a list into a string.
lappend Appends elements to a list.
lindex Returns a specific element from a list.
linsert Inserts elements into a list.
list Returns a list formed from its arguments.
11ength Returns the number of elements in a list.
lminus Removes one or more named elements from a list and returns a new list.
lrange Extracts elements from a list.
lreplace Replaces a specified range of elements in a list.
lsearch Searches a list for a regular expression.
lsort Sorts a list
split Splits a string into a list.

array

创建

1
set ArrayName(Index) value

size of array

1
array size variablename

indices of Array

1
array names variablename

array iteration

1
2
3
4
set languages(0) Tcl
set languages(1) "C Language"
for { set index 0 } { $index < [array size languages] } {incr index } {
puts "languages($index) : $languages($index)"}

Indices of Array

1
array names variablename

Iteration of Associative Array

1
2
3
4
5
set personA(Name) "Dave"
set personA(Age) 14
foreach index [array names personA] {
puts "personA($index): $personA($index)"
}

array 转为 list

1
2
3
% array set arr { a aaa b bbb }
% array get arr
a aaa b bbb

array不支持多维

1
2
3
4
5
# 下面是非常象二维array的一维array
% set arr(x1)(y2) 12
12
% array name arr
x1)(y1 x1)(y2
1
2
3
4
5
6
7
#比较常见的一种假二维array
% set arr(x1,y1) 11
11
% set arr(x1,y2) 12
12
% array name arr
x1,y2 x1,y1

dict

1
dict option arg1 ?arg2 ... argN?

操作字典,具体操作由option决定,option支持以下选项:

create

1
dict create ?key1 value1 key2 value2 ...keyN valueN?

返回一个新字典,包含传入的key、value映射。

append

1
dict append dictName key ?string ...?

将给定的string追加到字典dictName中键key的值后面。如果key不存在,则相当于新增一个key的映射。如果未指定string,则视为空字符串。多个string会合并为一个字符串。此命令返回更新后的字典。

lapend

1
dict lappend dictName key ?value ...?

将给定的value追加到dictName中指定key对应的列表中,可以同时追加多个value,如果key对应的值不是列表,会创建一个列表,并将原有值和追加的值放到列表中。如果key存在,但没有指定value,则不做任何操作。如果dictName中不存在key,则视为空列表,若此时value也未指定则会添加一个键为key值为空列表的元素,若指定了value则会将value作为列表的元素。如果key对应的值不能表示为列表则会报错。

exists

1
dict exists dictValue key ?key ...?

判断给定的键key是否存在于给定的字典dictValue中,如果存在返回true,否则返回false。exists只能判断一个键是否存在,当传入多个key时,会将多个key作为嵌套字典的键路径进行查找。

get

1
dict get dictValue ?key ...?

获取dictValue中指定key的值,如果想获取嵌套字典中的值,则需要传入多个key作为键的路径。如果没有指定key则返回包含所有键值对的列表。如果字典中不存在指定的键则会报错。

incr

1
dict incr dictName key ?increment?

将字典dictName中指定key对应的值增加increment。如果未指定increment,则默认增加1。如果不存在指定的key,则视为0。如果key对应的值不是整数则会报错。

keys

1
dict keys dictValue ?globPattern?

返回包含dictValue所有键的列表。如果指定了globPattern,则只返回与之匹配的键的列表。列表中的键按其插入字典的顺序返回。

values

1
dict values dictValue ?globPattern?

返回包含字典dictValue的值的列表。如果指定了globPattern,则只返回根据string match规则与其匹配的值的列表。返回值按其插入字典dictValue的顺序排列。

set

1
dict set dictName key ?key ...? value

使用value替换字典dictName中key对应的值。如果dictName中不存在key,则值会新增key到value的映射。当存在多个键时表示更新嵌套字典,此时如果第一个key不存在,则会新增一个嵌套字典。如果第一个key存在但是后面的key不存在则会报错missing value to go with key。

update

1
dict update dictName key varName ?key varName ...? body

使用映射dictName中key对应的值的变量varName执行body中的脚本。如果dictName没有指定的key,则其对应的变量varname为未设置。当body终止时,对varName所做的更改都会被会写到字典内即使body的结果是一个错误或其他异常,除非字典不可读所有的更新都被静默的丢弃。除非发成异常,否则dict update的结果是body的执行结果。建议只在本地作用域内使用此命令,因为dict update命令中的变量varName在命令完成后,除非显示的执行unset,否则仍然存在。此外,只有当body终止时,才会更改dictName中的内容。

replace

1
dict replace dictValue ?key value ...?

返回一个新的字典,包括传入的dictValue以及一些额外的或不同的键值对。如果不传如键值对key、value,则返回的新字典与dictValue相同。键值对必须是成对出现,否则会报错。dictValue中存在的key会用心的value替换,不存在的key会新增到新的字典。

unset

1
dict unset dictName key ?key ...?

删除字典dictName中key对应的值。如果dictName中不存在key,则不进行任何操作。当存在多个键时表示删除嵌套字典中的元素,此时的键路径上除了最后一个key可以不存在外,前面的key必须存在,否则会报错key “xxx” not known in dictionary。

remove

1
dict remove dictValue ?key ...?

返回一个新的字典,字典包括键为key以外的所有dictValue中的键值对。如果不指定任何键则返回的字典与dictValue相同,如果key不在dictValue中,则不进行任何操作。

size

1
dict size dictValue

返回dictValue中键值对的数量,不包括值中嵌套的字典中的键值对。

merge

1
dict merge ?dictValue ...?

返回一个新的字典,包含dictValue中的所有元素,多个dictValue具有相同的key的元素的时,最后一次出现的key对应的值会出现在新的字典中。

info

1
dict info dictValue

返回字典信息,信息的具体格式取决于字典的实现方式。由于字典是散列表实现的,所以放回结果类似于array statistics命令。

with

1
dict with dictName ?key ...? body

与update类似,使用dictName中key对应的值执行body中的脚本。如果key为多个表示嵌套字典的键路径,此时会使用键路径对应的字典执行body中的脚本。字典中key对应的值会映射到与key同名的变量中。与dict update一样,如果dictName不可读或者字典调整导致键路径没有对应的值,则会静默丢弃字典的更新。除非发成异常,否则dict with的结果是body的执行结果。建议只在本地作用域内使用此命令,因为dict with命令中的变量在命令完成后,除非显示的执行unset,否则仍然存在。此外,只有当body终止时,才会更改dictName中的内容。当body终止时如果dictName不是字典则会产生错误。因此当字典中的键与字典变量dictName有冲突时不建议使用此命令。

for

1
dict for {keyName valueName} dictValue body

用于遍历字典dictValue,在执行body中脚本时,字典中每个键值对的键和值会分别分配给名为指定的keyName和valueName变量。dict for命令的结果为空字符串。当在body执行过程中遇到break时,会中止循环,结束dict for命令。当遇到continue命令时,会结束本轮循环。字典按键值对的插入顺序进行遍历。

filter

1
dict filter dictValue filterType arg ?arg ...?

返回一个新的与指定过滤类型匹配的键值对的字典。filterType支持三种类型:

key

1
dict filter dictValue key ?globPattern ...?

返回以stirng match的方式键与模式globPattern匹配的键值对。

value

1
dict filter dictValue value ?globPattern ...?

返回以stirng match的方式值与模式globPattern匹配的键值对。

script

1
dict filter dictValue script {keyName valueName} script

通过将键赋值给变量keyName,值赋值给变量valueName,根据srcipt脚本的布尔值结果来确定键值对是否匹配。当脚本结果为true时,表示键值对匹配。字典按键值对的插入顺序进行遍历。当在srcipt执行过程中遇到break时,会中止循环,结束dict filter命令。当遇到continue命令时,会结束本轮循环。

map

1
dict map {keyName valueName} dictValue body

Tcl8.6新增的命令。此命令通过执行body中的命令,对字典dictValue中的键值进行转换,然后返回一个新的包含转换后的键值对的字典。名为keyName、valueName对应于dictValue中键值对的键与值。每次body执行完后,变量keyName、valueName的值即为新字典的键值。当在body执行过程中遇到break时,会中止循环,结束dict map命令。当遇到continue命令时,会结束本轮循环。另外要注意的是,如果不想对值做改变,需要对其进行显示的set操作,否则值会被设置为body中最后一个命令的返回值。

简单示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
set dic [dict create a 1 b 2 c 3]
dict append dic ab 4 5
dict append dic a 6
dict append dic ab
dict exists $dic a
dict get $dic b
dict incr dic a
dict incr dic a 2
dict lappend dic a
dict lappend dic a 1
dict lappend dic e
dict lappend dic e 1 2 3 4 5
dict keys $dic
dict keys $dic a*
dict set dic a 19 2
dict set dic f g h 8
dict unset dic i
dict unset dic f g h
dict unset dic f h
dict size $dic
dic update dic a varA b varB h varH { dict set varA 19 3;incr varB;set varH "H" }
puts $dic
puts $varA
set newDic [dict replace $dic a 1 b 2 d 4]
puts $newDic
puts $dic
set newDic [dict remove $dic a e g]
puts $newDic
puts $dic
dict values $dic
dict values $dic 3
dict values $dic 4*
dict remove $dic a e i
puts $newDic
puts $dic
set newDic [dict merge {a 1 b 2} {c 3 d 4 b 5}]
puts $newDic
dict info $dic
dict with dic a { incr 19;puts $19;}
puts $dic
dict for {k v} $dic {puts "$k--$v";}
dict filter $dic key a*
dict filter $dic value 4*
dict filter $dic script {k v} { expr { $k < "e"} }
dict map { k v } $dic { set k $k$k; set v $v;}
dict map { k v } $dic { set k $k$k;}

collection

synopsys 工具独有的数据类型,有序,可以理解为工具中objects(cell net blockage …)的集合

相关命令:

command description
add_to_collection Add object(s) to a collection. Result is new collection
append_to_collection Add object(s) to a collection. Modifies variable
as_collection Find a collection or iter_collection by name; result a collection
collection_to_list format collection contents as a Tcl list
compare_collections Return 0 if two collections contain the same objects
copy_collection Make a copy of a collection. Result is new collection
filter collection Filter a collection, resulting in new collection
foreach_in_collection Iterate over a collection
index_collection Extract object(s) from collection. Result is new collec tion
remove_from collection Remove object(s) from a collection. Result is new collection
sizeof_collection Get the number of objects in collection
sort_collection Create a sorted copy of the collection

另外,所有的get_*都会返回collection。

当我们有一个或者多个很大的collection时,后续的一些命令可能会变得非常慢。因为每个命令结束后都要花额外的时间去维护这些collection,确保这些collection继续有效。
比如:

1
2
3
icc2_shell > set C1 [get_cells xxx]
icc2_shell > sizeof_collection$C
12,000,000

现在有个collection C1,有2M的cell在里面。接着你做eco,删除design里的一个cell A。这时工具会自动更新collection C1,如果A在C1里,则会把A从C1里删除掉。不然,后面使用C1可能会产生各种错误了。这种维护会消耗不少的时间。
所以,当你不再需要个collection时,及时的把它unset掉。不然,它一直存在,一直需要维护,直到退出。

推荐使用append_to_collection代替add_to_collection,特别是在一个loop里,需要非常多次的循环操作时。append_to_collection会快很多,因为它直接修改collection,而不是像add_to_collection那样先加,再返回到一个新的collection。

文件操作

相关命令

mark

文件名拓展

1
2
glob pattern1 pattern2 pattern3 ...
set flist [glob *.em *.volt]

控制结构

if else

mark

switch

mark

switch的三种匹配模式
• The test_value expression and the pattern match exactly (-exact).
• The pattern uses wildcards (-glob).
• The pattern is a regular expression (-regexp).
举例:

1
2
3
4
5
6
switch -exact $vendor_library {
Xlib {set_max_delay 2.8 [all_outputs]}
Ylib { - }
Zlib {set_max_delay 3.1 [all_outputs]}
default {set_max_delay 3.4 [all_outputs]}
}

while

1
while {expression} {while_command while_command ... }

举例:

1
2
3
4
5
set p 0
while {$p <= 10} {
echo "$p squared is: [expr $p * $p]"
incr p
}

for

1
2
3
4
5
6
7
for {init} {test} {reinit} {
body
}

for {set p 0} {$p <= 10} {incr p} {
echo "$p squared is: [expr $p * $p]"
}

foreach

1
2
3
4
5
foreach variable_name list {
foreach_command
foreach_command
...
}

foreach_in_collection

1
2
3
foreach_in_collection collection_item collection {
body
}

循环控制语句

1
2
continue; # 继续下一个循环
break; #终止循环

procedure

提供参数默认值的方法

1
2
3
4
5
6
proc max {{a 0} {b 0}} {
if {$a > $b} {
return $a
}
return $b
}

使用特殊参数args实现可变参数

args,放到proedure的argument的最后的位置。那么命令多有多余的argument都会作为args这个list中的一个item
举例

1
2
3
4
5
6
7
8
9
proc demo {first {second "none"} args} {
puts "first = $first"
puts "second = $second"
puts "args = $args"
}

demo one
demo one two
demo one two three four five

Native的TCL command,在proc里的运行速度是直接运行时的2~5倍!所以对于循环次数很多,计算很多的脚本,尽量放在proc里。

其原因是,ICC2在执行proc时,会把proc预编译成byte code,所以会比直接执行TCL快很多。

举例:
一个简单的循环累加脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
icc2_shell> time {
for {set x 1} {$x < 10000} {incr x} {incr a 1};
echo $a
}
9999
2295 microseconds per iteration
icc2_shell> proc bb {} {
for {set x 1} {$x < 10000} {incr x} {incr a 1};
echo $a
}
icc2_shell> time {bb}
9999
417 microseconds per iteration

这是一个简单的循环累加,用proc比不用proc快了5倍。

延伸阅读,本号关于tcl相关技巧的文章:

TCL技巧:如何更优雅的报出cell的总面积

TCL技巧:一个超级实用的Debug方法

mark


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以邮件至 admin@graymount.top,也可以关注微信公众号"白山头"直接留言。

文章标题:tcl脚本编程知识点总结

本文作者:白山头

发布时间:2020-04-01, 17:15:29

最后更新:2020-04-01, 17:15:40

原始链接:http://graymount.top/2020/04/01/tcl/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录