tcl编程
文章目录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