专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

芯片设计:tcl脚本编写

作者:huqin   来源:本站原创   点击数:  更新时间:2014年04月30日   【字体:

 作者:白栎旸

tcl脚本在芯片设计中用于modelsim do脚本的编写,数字设计软件的自动化都需要tcl。
阅读以下文档时,大家可以一边读,一边打开modelsim,在命令行上进行输入,命令行可以运行tcl程序。
 
以下介绍中顺便介绍modelsim的命令,请不要把它与tcl的语法混淆。
(1)注释方法,同shell一样用#,但注释和代码是分行写的,不能写在一行。
 
(2)变量定义和赋值:tcl将所有值当做字符,所以“set x 10”中的10是字符,而不被理解为真正的10。对比其他语言,perl是自动匹配,即编译器自动判断是数字还是字符,C语言是用户告诉编译器是int还是char。
    【字符赋值】:set x 10,或 set x $a
    在tcl中,变量 a 被赋值后,在后面的程序中出现 a,说明是变量 a,后面的程序出现 $a, 只表示一个具体的字符或数字,跟 a 没有一点关系。
    像tcl这种默认字符的处理方式给处理字符带来方便,但数学计算却并不方便,下面介绍如何将字符变成数字:
    【数字赋值】:使用 expr 命令,如:set y [expr 10+100],则y的值就是110,注意:110仍然是个字符。
  在赋值、数学计算中,都使用[],而不是传统的(),如:[expr [expr 1+2]*3]。所以最   好不用tcl进行数学运算,只用它处理字符和文件,数学运算非它所长。
    【变量运算】:set y [expr $x+100],y的值仍然是110.
  如果一个变量叫 abc = 10,则 set y [expr $abc+100],y是110,说明 $abc 被当作一个
  整体处理了。如果怕不保险,可以用 ${abc},即 set y [expr ${abc}+100],这和perl的
  用法是一样的。
 
(3)显示变量的值:"puts 文件句柄 $x",或者"puts $x"(默认文件句柄为stdout),或者直接 "set x",会显示 $x 的值。
(4)取消变量: unset x y z,注销了 x y z 三个变量。
(5)追加变量值:
     set x 10
     append x abc, 则 x 的值是10abc
  
(6)关键字、关键字符:当变量赋值时,有些字符在tcl语法中有特殊含义,如果需要将其当作一般字符赋值,请进行字符转义,
     例1: [ ,请使用 \[ 标识,set x \[,则 x =[
     例2: set x \[2],则 x = [2],注意,]前面没有\
   
  以下列出关键字符:
     \空格  ———— 空格
     \[     ———— [
     \$     ———— $
     \n     ———— 换行
     \t     ———— 制表符
     \r     ———— 回车
     \x48   ———— 0x48对应的ASC码字符
     \756   ———— 0756(八进制)对应的ASC码字符
  
  此外,可以使用""或{},如:set x "1 2 3",x = "1 2 3",
  ""的用法: 编译器仍然编译""里面的内容,如:set x "$y",则 x = y的值;“[express]”也会被编译。
  {}的用法: 编译器不编译{}中的任何内容,如:set y {\n},则 y = \n.{}其实是定义数组的方式,看后面
 
(7)数组(集合):虽然人们管它叫 list,但我看就是个广义数组,类似matlab中cell的数据结构。以下是数组的概念和操作:
    【定义数组】:set x {1 2 3},等同于 set x [list 1 2 3],前者比较容易写。
    【数组嵌套】:set x 1 2 3 {3 4 5}
    【合并数组】:set $z [concatlist $x $y]
    【从数组中取一个元素】:lindex $x 2,从$x中取从0开始第2个元素。
    【数组的长度】:llength $x
    【插入数组元素】:linsert $x 3 $y,在原数组$x的3位置插入一个新数组$y,序号3位置可以使用end表示最后一个。
    【替换数组元素】:lreplace $x 1 3 5 7,将原数组$x的第1~3位置元素替换为5和7。
    【截取数组】:lrange $x 1 3,截取原数组$x的第1~3位置的一段。
    【尾部追加数组元素】:lappend x 1 3 4,在原数组x的后面加入元素1 3 4。注意:该命令与上面的数组命令不同。上面的数组命令只产生一个新的数组,原数组x不变,而本命令会改变原数组x本身。因此我们不写成“lappend $x 1 3 4”,而应该写成“lappend x 1 3 4”。
    【在数组元素中查找】:lsearch $x 33,在数组 $x 中查找33,找到后返回序号,未找到返回-1。搜索命令可以加控制选项:-exact(完全匹配,不支持通配符*等),-glob(支持通配符的查找),-regexp(正则表达式)。如下:lsearch -regexp $x .*3.+。
    【数组排序】:lsort 选项 $x,如果不写选项,默认按ASC码顺序排列。其他选项有: 
                  -integer:整数排列,2不会拍到10后面
                  -real:按浮点数排列
                  -increasing:ASC码升序排列
                  -decreasing:ASC码降序排列
    【将string拆成数组】:split "abc" {},将字符串abc拆成数组a b c,{}是拆分的依据,即把每个字符都拆开。也可以用其他依据,如:split "a:b:c" :,结果还是 a b c
    【将数组变成string】:join {1 2 3} :,结果是一个字符串1:2:3
 
(8)条件判断:tcl编译器是早期编译器,比较“弱智”,对“换行符”、“空格”等都敏感。“换行符”用来标识一行命令结束(类似C语言中的;),“空格”用来划分命令和参数。因此,在tcl复杂语言结构中,使用“换行”和“空格”一定要注意。
     if {条件1} { //注意“空格”和“换行”的位置。条件、结果都用{},不用()。
        结果1
     } elseif {条件2} {
        结果2
     } else {
        结果3
     }
 
     switch 选项 $x {
a -    // - 表示“a情况 ~ b情况”
        b {结果1}
        c {结果2}
        default {结果3}
     }
     switch的选项有:-exact(准确匹配),-glob(整体匹配),-regexp(regular expression正则表达式匹配)
     
(9)循环结构: tcl循环支持 break 和 continue .
     while {条件} {
        循环体
     }
     
     for {条件} {
        循环体
     }
   
     foreach i $a {    //$a 是个数组
      循环体
     }
 
     foreach 还可以多变量赋值,如下:
     foreach i {1 2 3} j {4 5 6} {
         循环体
     }
 
(10)动态命令:set x "expr 3+2",eval $x,显示为5。
(11)自定义函数:在tcl中也可以写函数,供脚本调用。函数定义方法如下:
      proc 函数名 参数列表 {函数功能块},例如:proc add {x y} {expr $x+$y},写完后,调用时写add     1 3,执行结果为4。支持return。
      在函数外定义的变量,如果要在函数中使用,并继承原来的值,需要在“函数功能块”中用:global x进   行声明。
      可以给函数的参数定义默认值:proc add {{x 1} {y 2}} {expr $x+$y}。
      可以让函数携带非固定数量的参数,关键词是args,例如: proc add {args} {......},args是作为列   表使用的,而非单独一个元素。
 
 (12)字符串操作:tcl数字处理是繁琐的,而对字符串操作是它的强项,因为tcl主要用于命令行中对文件名、目录名、路径等字符串进行操作。
  【格式化字符串】:在C语言和perl中,我们使用sprintf来格式化字符串,或输出到屏幕上,或输出到另一个字符串变量中。在tcl中,完成相同功能的命令叫format,例如:format "%s is %d" $x $y,使用时把C语言中的逗号改成空格,没有括号,就是tcl的表达方式。
  【字符串匹配】:使用perl语言的话,用模式匹配符 =~ 进行正则表达式匹配超容易,在tcl中稍麻烦一些,使用命令:regexp,格式为:
      regexp {pattern} string,
      如果pattern匹配string,则返回1,否则返回0. 例如:regexp {abc} baiabc001,abc在baiabc001中出现,匹配成功,返回1。
       匹配命令regexp也可以像perl一样从string中截取变量的值,赋给变量,例如:
       regexp {(.).+([0-1]+)} "baiguangyu001" x y z,则x匹配整个baiguangyu001,y匹配第一个b,z匹配最后一个1。
       打开选项-indices可以返回匹配的位置,如regexp -indices {(.).+([0-1]+)} "baiguangyu001" x y z,x的值是{0 12},表示匹配整个字符串,y的值是{0 0},表示从第一个字符开始,到第一个字符结束。z的值是{12 12},从第12个字符开始,又从第12个字符结束。
  【字符串替换】:regexp是字符串匹配,相当于perl中的m//,而regsub是字符串替换,相当于perl中的s//。
格式为:regsub option pattern string substr whole_str_aft
用pattern在string中匹配,匹配上以后,用substr替代匹配部分,替换后的整个string存在whole_str_aft里。
在option处可以加选项,相当于perl中的m//igx之类的。具体选项有:-nocase:不区分大小写//i,-all就是//g.
  【字符串比较】:string compare [-nocase] [-length 10] str1 str2,
比较str1和str2,如果有length 10,就是只比较前10个字符。返回值:-1(小于),0(等于),1(大于)
  【字符串比较】:string equal [-nocase] [-length 10] str1 str2,返回值:1(等于),0(不等于)。
  【字符串长度】:string length str,返回str的长度。
  【字符串大小写互转】:string tolower str,将str变小写。
                        string toupper str,将str变大写。
 
 (13)文件访问:对于tcl来说,一个重点是字符串,另一个重点就是文件操作。
  【打开文件】:set x [open $filename r],同perl中的:open x,"<$filename";同C语言的:x=fopen(filename,"r"); r是读,w是写,a是追加,r+是读写。
  【关闭文件】:close $x
  【逐行读取文件】:关键命令gets,while {gets $x line},把x句柄的每一行赋给line变量。类似perl中的:while($line = <$x>),但perl更简单。
  【写文件】:“puts 文件句柄 内容”
  【3种特殊的文件句柄】:stdin,stdout,stderr。
  【刷新缓冲区】:有时候内容显示不出来,就用flush命令,“flush 句柄”。
  【文件指针跳跃】:“seek 句柄 偏移 坐标原点”,坐标原点只有3种:start,current,end
  【获知文件指针】:“tell 句柄”,“eof 句柄”说明文件是否已经读完
 
 (14)目录文件管理:
  【查找文件或目录名】:glob name1 name2 ....,用来查找当前工作目录中是否有name文件,name的格式不是模式匹配的,所以需要文件名的全称,也支持通配符,但不支持正则表达式。通配符有*,集合符有[ab](表示ab中的一个字符),{a1,a2}类似[ab]但是个组集合。如果怕报错,写一个-nocomplain,即便没找到,也只返回空。例如:
    glob -nocomplain {abc,a123}/*hd.[co],可以匹配abc/1hd.c,a123/Ahd.o等。
  【显示文件的访问时间】:file atime name,atime就是access time(访问时间),返回一个很莫名其妙的时间。
  【显示文件的修改时间】:file mtime name,mtime就是manipulate time(操作时间).
  【显示文件大小】:file size name,单位是字节。
  【显示文件类型】:file type name,类型有:file,directory,characterspecial(字符设备),blockspecial(块设备),fifo,link,socket.
  【拷贝文件】:file copy [-force] source target
  【删除文件或目录】:file delete [-force] name
  【获知文件路径】:file dirname name
  【获知文件是否可执行】:file executable name
  【获知文件或目录是否存在】:file exists name
  【获知文件扩展名】:file extension name
  【获知文件名是否是目录名】:file isdirectory name
  【获知文件是否是个软连接】:file lstat name,lstat就是link state
  【新建目录】:file mkdir dirname1 dirname2
  【文件改名】:file rename [-force] source target,类似linux的mv命令,可以用于剪切和粘贴。
 
 (15)在tcl中调用perl脚本:
   tcl的功能有限,很多复杂处理还需要用perl实现较快,以下是tcl调用perl的方法:
   set x [exec perl abc.pl],其中abc.pl是被调用的perl脚本的文件名。
   如果abc.pl的内容为:
   $a = 4; $b = 3; $c = $a+$b; print $c;
   则 x 被赋值为 7.
关闭窗口

相关文章