文章目录0. 基础语法0.1 普通变量0.2 list, 列表0.3 array, 数组0.4 循环0.4.1 for0.4.2 foreach0.5 分支0.5.1 if..else0.5.2 switch1. 从命令行获取参数(好像并不是很强大)2 proc参数2.1 位置参数2.2 默认参数2.3 可变参数2.4 参数解析3. 读写文件3.1 按行读入文件3.2 写文件4. 正则匹配5. catch6. 非整数运算7. 四舍五入, 伪随机数8. eval和exec9. 进制转换0. 基础语法0.1 普通变量#变量赋值 set x This is a string set y 1.24 #打印变量 puts $x puts $y0.2 list, 列表#列表赋值 set la [list a b {c d}] #llength: 获取list长度 puts [llength $la] ; # 3 #lindex: 根据idx获取元素 set e2 [lindex $la 2] puts $e2 ; # c d #lsearch: 在list中查找指定元素 lsearch $la b; # 1, 返回b的idx. #lappend: 追加元素, 可以追加多个 lappend la ef gh; # 注意会修改la本身 puts $la; # a b {c d} ef gh #linsert: 在指定位置插入元素, 可以插入多个 set la_new [linsert $la 1 x y z] puts $la_new ; # a x y z b {c d} #lrange: 返回first~last的元素 #lreplace: 替换first~last的元素 #lsort: list排序 #concat: 多个list合并为一个list set la [list a b] set lb [list x y] set lc [concat la lb] puts $lc ; # a b x y0.3 array, 数组array set arr {} ; # 创建空array, 清空已有array array set arr {a 1 b 2 c 3 de 4} ; # array设置元素, 设置多个 set arr(f) 5 ; # array设置元素, 设置一个 puts [array size arr] ; # 5, array长度, key-val对的数目 puts $arr(de) ; # 4, 获取key de对应的值, 注意, 不需要在de外面加引号. #遍历array # de - 4 # a - 1 # f - 5 # b - 2 # c - 3 foreach k [array names arr] { set v $arr($k) puts $k - $v } #判断arr是否存在: if [array exists arr] { puts array arr exists. } #判断key是否存在: info exists arr($k) # $arr(b) 2 if [info exists arr(b)] { puts \$arr(b) $arr(b) }0.4 循环0.4.1 forset la [list a b c d e] for {set i 0} {$i[llength $la]} {incr i} { puts $i: la[$i] }0.4.2 foreach#待循环的list set la [list a b c d e] set lb [list 1 2 3 4 5 6] # 循环单个list, 每次取一个元素 foreach ele $la { puts $ele } # 循环单个list, 每次取多个元素 foreach {ele0 ele1} $la { puts $ele0, $ele1 } # 循环多个list, 循环次数以最长的list为准, 不足的补空元素 foreach ea $la eb $lb { puts $ea: $eb }0.5 分支0.5.1 if…elseset a 100 if {$a 10} { puts \$a is 10 } elseif {$a 20} { puts \$a is 20 } else { puts \$a is neither 10 nor 20 }条件表达式中可以使用: || !if {! [file exists file_name]} { puts file not exists } else { puts file exists } set a 10 if {! [expr $a10]} { puts a ! 10 } else { puts a 10 } if {[file exists file_name] $a10} { puts file exists and a10 }0.5.2 switchproc get_instr {location name} { set value 0x00 switch $location { SMSG { switch $name { BYPASS {set value 0x00} FLOAD_RUN {set value 0x30} default {puts Error: cannot find instr for $location.$name} } } PROC { switch $name { BYPASS {set value 0x00} BIST_RUN {set value 0x11} default {puts Error: cannot find instr for $location.$name} } } default {puts Error: first param must be SMSG or PROC} } return value }puts [get_instr “PROC” “BIST_RUN”]1. 从命令行获取参数(好像并不是很强大)array set a0 $argv foreach opt {-i -o} { puts $opt - $a0($opt) }运行$ ex.tcl -i abc -o xyz -i - abc -o - xyz2 proc参数2.1 位置参数proc add {x y} { ;# x和y是位置参数 set r [expr $x$y] ;# 使用x和y时要加$号, 计算加法时要使用expr return $r } set a [add 2 4] ;# 调用proc, 如果要赋值给其它变量需要使用set puts $a ;# 得到62.2 默认参数注意默认参数要放到参数列表后面, 可以有多个proc add {x {y 1}} { ;# y是默认参数, 如果不提供, 则y1 set r [expr $x$y] return $r } set a [add 2 4] ;# 调用proc, y提供值 puts $a ;# 得到6 set a [add 2] ;# 调用proc, y不提供值, 使用默认值1 puts $a ;# 得到32.3 可变参数参数数目可变, 使用关键字args接收.proc add {args} { ;# args是关键字不能改为其它 set r 0 foreach e $args { set r [expr $r$e] } return $r } set a [add 1 2 3] ;# 调用proc, 提供多个参数 puts $a ;# 得到6 set a [add 1 2 3 4] ;# 调用proc, 提供多个参数 puts $a ;# 得到102.4 参数解析在EDA工具中(比如dc_shell, pt_shell等)提供了两个命令: parse_proc_argument和define_proc_atrributes,可以用来解析proc参数, 但原生的tcl应该不支持.proc add {args} { ;# 解析参数, 并把结果放到变量results中, results是个array ;# 注意这个命令需要与define_proc_atrributes联合使用, ;# 否则会报告Error: extra position option -x_value等, ;# 意思是这不知道如何解析这些参数. parse_proc_arguments -args $args results ;# 查看下results的内容 foreach argname [array names results] { puts $argname: $results($argname) ;# 打印每个参数和对应值 } ;# 访问参数-x_value, x得到-x_value的值, -x_value是通过define_proc_atrributes定义的. set x $results(-x_value) ;# 访问参数-y_value, y得到-y_value的值, 它是可选的, 需要给的默认值 if [info exists results(-y_value)] { set y $results(-y_value) } else { set y 0 } ;# 访问参数-z_value, z得到-z_value的值, 它是可选的, 需要给的默认值 if [info exists results(-z_value)] { set z $results(-z_value) } else { set z 0 } return [expr $x$y$z] } ;# 给add定义属性 ;# 定义的参数(-x_value,-y_value,-z_value), 在交互界面调用命令时, 可以通过tab补全参数全名, 就像dc/pt的命令参数一样 define_proc_attributes add \ -info add at most 3 numbers \ ;# 帮助信息, 在help add时显示的内容 -define_args { ;# 定义参数 {-x_value first added x int required} ;# -x_value必须提供 {-y_value second added y int optional} ;# -y_value可选 {-z_value third added z int optional} ;# -z_value可选 } set a [add -x_value 1] ;# 1 set a [add -x_value 1 -y_value 2] ;# 3 set a [add -x_value 1 -y_value 2 -z_value 3] ;# 63. 读写文件3.1 按行读入文件set FH [open ../rpt/$file r] while {[gets $FH line] 0} { puts $line } close $FH3.2 写文件set FH [open file.txt w] puts -nonewline $FH hello puts $FH world. close $FH4. 正则匹配# regexp, 匹配 set line 123abc456 if [regexp {^(\d)([a-z])} $line all_match match1 match2] { puts $all_match ; # 123abc, 整个正则表达式匹配到的内容 puts $match1 ; # 123 , 第1个括号匹配到的内容 puts $match2 ; # abc , 第2个括号匹配到的内容 } # regsub, 替换 set atpg_se atpg_se[4] regsub {\[} $atpg_se {_} atpg_se_mark ;# $atpg_se不被修改, atpg_se_mark获得修改后的值 regsub {\]} $atpg_se_mark {} atpg_se_mark ;# 新值赋值给atpg_se_mark puts $atpg_se_mark ; # atpg_se_45. catch当运行的命令出现错误时, catch语句返回1if [catch {open file.txt r} FH] { puts Error: file.txt not opened } else { puts open file.txt while {[gets $FH line] 0} { puts $line } }6. 非整数运算set a [expr 100 * double(1)/3] # 返回33.333333333333336% # 如果不使用double, 则只会返回整数部分 # [expr 100 * 1/3] 返回33 # [expr 1/3 * 100] 返回0 puts $a% # 33.333333333333336% set b [format %.2f $a] puts $b% # 33.33%7. 四舍五入, 伪随机数# 四舍五入 set a 2.3 set b [expr round($a)] #注意, 要通过expr调用, 调用时后面要加圆括号 puts $b # 2, 四舍五入2.3变为2 # 生成0~1之间的伪随机小数 set c [expr rand()] # 注意, 要通过expr调用. puts $c # 0.45033995969519 # 生成0~9之间的伪随机整数 set d [expr round(9*rand())] puts $d # 58. eval和exec# eval 动态执行tcl语句 set cmd puts 123 eval $cmd # 123 # exec 执行unix shell命令(或windows cmd命令) set a [exec find . -name run*] puts $a # 打印出find命令的标准输出9. 进制转换binary用于操作二进制字符串.包含四个子命令:binary format: 将普通tcl字符串转换为二进制字符串. binary scan : 将二进制字符串转为普通tcl字符串. binary encode: 将二进制字符串进行编码. binary decode: 将编码后的二进制字符串进行解码.二进制字符串的范围是\u0000~\u00FF, 所以如果不想丢失数据, 需要先进行转换.# 普通tcl字符串, 内容是16进制的字符 set hex_str FF00CC # 将普通tcl字符串$hex转为二进制格式, # H : 表示待处理的字符串中是16进制字符 # * : 表示待处理的字符串list长度任意?? set bin_fmt [binary format H* $hex_str] # 将二进制数据($bin_fmt)转为普通tcl字符串, 存储到变量$bits中 binary scan $bin_fmt B* bits # 打印$bits puts $bits ;# 1111111110000000011001100 # 将$bits格式化为特定长度的str, %0*s, 中的*, 表示通过变量指定长度 set width 28 set bits_28 [format %0*s $width, $bits] puts $bits_28 ; 00001111111110000000011001100 #遍历$bits_28 set len [string length $bits_28] for {set i 0} {$i[expr $len-1]} {incr i} { set i_str [expr $len-1-$i] puts $i - [string index $bits_28 $i_str] } # 0 - 0 # 1 - 0 # 2 - 1 # 3 - 1 # 4 - 0 # 5 - 0 # 6 - 1 # 7 - 1 # 8 - 0 # 9 - 0 # 10 - 0 # 11 - 0 # 12 - 0 # 13 - 0 # 14 - 0 # 15 - 0 # 16 - 1 # 17 - 1 # 18 - 1 # 19 - 1 # 20 - 1 # 21 - 1 # 22 - 1 # 23 - 1 # 24 - 0 # 25 - 0 # 26 - 0 # 27 - 0