專注電子技術(shù)學(xué)習(xí)與研究
當(dāng)前位置:單片機(jī)教程網(wǎng) >> MCU設(shè)計實例 >> 瀏覽文章

芯片設(shè)計:tcl腳本編寫

作者:huqin   來源:本站原創(chuàng)   點擊數(shù):  更新時間:2014年04月30日   【字體:

 作者:白櫟旸

tcl腳本在芯片設(shè)計中用于modelsim do腳本的編寫,數(shù)字設(shè)計軟件的自動化都需要tcl。
閱讀以下文檔時,大家可以一邊讀,一邊打開modelsim,在命令行上進(jìn)行輸入,命令行可以運(yùn)行tcl程序。
 
以下介紹中順便介紹modelsim的命令,請不要把它與tcl的語法混淆。
(1)注釋方法,同shell一樣用#,但注釋和代碼是分行寫的,不能寫在一行。
 
(2)變量定義和賦值:tcl將所有值當(dāng)做字符,所以“set x 10”中的10是字符,而不被理解為真正的10。對比其他語言,perl是自動匹配,即編譯器自動判斷是數(shù)字還是字符,C語言是用戶告訴編譯器是int還是char。
    【字符賦值】:set x 10,或 set x $a
    在tcl中,變量 a 被賦值后,在后面的程序中出現(xiàn) a,說明是變量 a,后面的程序出現(xiàn) $a, 只表示一個具體的字符或數(shù)字,跟 a 沒有一點關(guān)系。
    像tcl這種默認(rèn)字符的處理方式給處理字符帶來方便,但數(shù)學(xué)計算卻并不方便,下面介紹如何將字符變成數(shù)字:
    【數(shù)字賦值】:使用 expr 命令,如:set y [expr 10+100],則y的值就是110,注意:110仍然是個字符。
  在賦值、數(shù)學(xué)計算中,都使用[],而不是傳統(tǒng)的(),如:[expr [expr 1+2]*3]。所以最   好不用tcl進(jìn)行數(shù)學(xué)運(yùn)算,只用它處理字符和文件,數(shù)學(xué)運(yùn)算非它所長。
    【變量運(yùn)算】:set y [expr $x+100],y的值仍然是110.
  如果一個變量叫 abc = 10,則 set y [expr $abc+100],y是110,說明 $abc 被當(dāng)作一個
  整體處理了。如果怕不保險,可以用 ${abc},即 set y [expr ${abc}+100],這和perl的
  用法是一樣的。
 
(3)顯示變量的值:"puts 文件句柄 $x",或者"puts $x"(默認(rèn)文件句柄為stdout),或者直接 "set x",會顯示 $x 的值。
(4)取消變量: unset x y z,注銷了 x y z 三個變量。
(5)追加變量值:
     set x 10
     append x abc, 則 x 的值是10abc
  
(6)關(guān)鍵字、關(guān)鍵字符:當(dāng)變量賦值時,有些字符在tcl語法中有特殊含義,如果需要將其當(dāng)作一般字符賦值,請進(jìn)行字符轉(zhuǎn)義,
     例1: [ ,請使用 \[ 標(biāo)識,set x \[,則 x =[
     例2: set x \[2],則 x = [2],注意,]前面沒有\(zhòng)
   
  以下列出關(guān)鍵字符:
     \空格  ———— 空格
     \[     ———— [
     \$     ———— $
     \n     ———— 換行
     \t     ———— 制表符
     \r     ———— 回車
     \x48   ———— 0x48對應(yīng)的ASC碼字符
     \756   ———— 0756(八進(jìn)制)對應(yīng)的ASC碼字符
  
  此外,可以使用""或{},如:set x "1 2 3",x = "1 2 3",
  ""的用法: 編譯器仍然編譯""里面的內(nèi)容,如:set x "$y",則 x = y的值;“[express]”也會被編譯。
  {}的用法: 編譯器不編譯{}中的任何內(nèi)容,如:set y {\n},則 y = \n.{}其實是定義數(shù)組的方式,看后面
 
(7)數(shù)組(集合):雖然人們管它叫 list,但我看就是個廣義數(shù)組,類似matlab中cell的數(shù)據(jù)結(jié)構(gòu)。以下是數(shù)組的概念和操作:
    【定義數(shù)組】:set x {1 2 3},等同于 set x [list 1 2 3],前者比較容易寫。
    【數(shù)組嵌套】:set x 1 2 3 {3 4 5}
    【合并數(shù)組】:set $z [concatlist $x $y]
    【從數(shù)組中取一個元素】:lindex $x 2,從$x中取從0開始第2個元素。
    【數(shù)組的長度】:llength $x
    【插入數(shù)組元素】:linsert $x 3 $y,在原數(shù)組$x的3位置插入一個新數(shù)組$y,序號3位置可以使用end表示最后一個。
    【替換數(shù)組元素】:lreplace $x 1 3 5 7,將原數(shù)組$x的第1~3位置元素替換為5和7。
    【截取數(shù)組】:lrange $x 1 3,截取原數(shù)組$x的第1~3位置的一段。
    【尾部追加數(shù)組元素】:lappend x 1 3 4,在原數(shù)組x的后面加入元素1 3 4。注意:該命令與上面的數(shù)組命令不同。上面的數(shù)組命令只產(chǎn)生一個新的數(shù)組,原數(shù)組x不變,而本命令會改變原數(shù)組x本身。因此我們不寫成“lappend $x 1 3 4”,而應(yīng)該寫成“lappend x 1 3 4”。
    【在數(shù)組元素中查找】:lsearch $x 33,在數(shù)組 $x 中查找33,找到后返回序號,未找到返回-1。搜索命令可以加控制選項:-exact(完全匹配,不支持通配符*等),-glob(支持通配符的查找),-regexp(正則表達(dá)式)。如下:lsearch -regexp $x .*3.+。
    【數(shù)組排序】:lsort 選項 $x,如果不寫選項,默認(rèn)按ASC碼順序排列。其他選項有: 
                  -integer:整數(shù)排列,2不會拍到10后面
                  -real:按浮點數(shù)排列
                  -increasing:ASC碼升序排列
                  -decreasing:ASC碼降序排列
    【將string拆成數(shù)組】:split "abc" {},將字符串a(chǎn)bc拆成數(shù)組a b c,{}是拆分的依據(jù),即把每個字符都拆開。也可以用其他依據(jù),如:split "a:b:c" :,結(jié)果還是 a b c
    【將數(shù)組變成string】:join {1 2 3} :,結(jié)果是一個字符串1:2:3
 
(8)條件判斷:tcl編譯器是早期編譯器,比較“弱智”,對“換行符”、“空格”等都敏感。“換行符”用來標(biāo)識一行命令結(jié)束(類似C語言中的;),“空格”用來劃分命令和參數(shù)。因此,在tcl復(fù)雜語言結(jié)構(gòu)中,使用“換行”和“空格”一定要注意。
     if {條件1} { //注意“空格”和“換行”的位置。條件、結(jié)果都用{},不用()。
        結(jié)果1
     } elseif {條件2} {
        結(jié)果2
     } else {
        結(jié)果3
     }
 
     switch 選項 $x {
a -    // - 表示“a情況 ~ b情況”
        b {結(jié)果1}
        c {結(jié)果2}
        default {結(jié)果3}
     }
     switch的選項有:-exact(準(zhǔn)確匹配),-glob(整體匹配),-regexp(regular expression正則表達(dá)式匹配)
     
(9)循環(huán)結(jié)構(gòu): tcl循環(huán)支持 break 和 continue .
     while {條件} {
        循環(huán)體
     }
     
     for {條件} {
        循環(huán)體
     }
   
     foreach i $a {    //$a 是個數(shù)組
      循環(huán)體
     }
 
     foreach 還可以多變量賦值,如下:
     foreach i {1 2 3} j {4 5 6} {
         循環(huán)體
     }
 
(10)動態(tài)命令:set x "expr 3+2",eval $x,顯示為5。
(11)自定義函數(shù):在tcl中也可以寫函數(shù),供腳本調(diào)用。函數(shù)定義方法如下:
      proc 函數(shù)名 參數(shù)列表 {函數(shù)功能塊},例如:proc add {x y} {expr $x+$y},寫完后,調(diào)用時寫add     1 3,執(zhí)行結(jié)果為4。支持return。
      在函數(shù)外定義的變量,如果要在函數(shù)中使用,并繼承原來的值,需要在“函數(shù)功能塊”中用:global x進(jìn)   行聲明。
      可以給函數(shù)的參數(shù)定義默認(rèn)值:proc add {{x 1} {y 2}} {expr $x+$y}。
      可以讓函數(shù)攜帶非固定數(shù)量的參數(shù),關(guān)鍵詞是args,例如: proc add {args} {......},args是作為列   表使用的,而非單獨一個元素。
 
 (12)字符串操作:tcl數(shù)字處理是繁瑣的,而對字符串操作是它的強(qiáng)項,因為tcl主要用于命令行中對文件名、目錄名、路徑等字符串進(jìn)行操作。
  【格式化字符串】:在C語言和perl中,我們使用sprintf來格式化字符串,或輸出到屏幕上,或輸出到另一個字符串變量中。在tcl中,完成相同功能的命令叫format,例如:format "%s is %d" $x $y,使用時把C語言中的逗號改成空格,沒有括號,就是tcl的表達(dá)方式。
  【字符串匹配】:使用perl語言的話,用模式匹配符 =~ 進(jìn)行正則表達(dá)式匹配超容易,在tcl中稍麻煩一些,使用命令:regexp,格式為:
      regexp {pattern} string,
      如果pattern匹配string,則返回1,否則返回0. 例如:regexp {abc} baiabc001,abc在baiabc001中出現(xiàn),匹配成功,返回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},表示從第一個字符開始,到第一個字符結(jié)束。z的值是{12 12},從第12個字符開始,又從第12個字符結(jié)束。
  【字符串替換】:regexp是字符串匹配,相當(dāng)于perl中的m//,而regsub是字符串替換,相當(dāng)于perl中的s//。
格式為:regsub option pattern string substr whole_str_aft
用pattern在string中匹配,匹配上以后,用substr替代匹配部分,替換后的整個string存在whole_str_aft里。
在option處可以加選項,相當(dāng)于perl中的m//igx之類的。具體選項有:-nocase:不區(qū)分大小寫//i,-all就是//g.
  【字符串比較】:string compare [-nocase] [-length 10] str1 str2,
比較str1和str2,如果有l(wèi)ength 10,就是只比較前10個字符。返回值:-1(小于),0(等于),1(大于)
  【字符串比較】:string equal [-nocase] [-length 10] str1 str2,返回值:1(等于),0(不等于)。
  【字符串長度】:string length str,返回str的長度。
  【字符串大小寫互轉(zhuǎn)】: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+是讀寫。
  【關(guān)閉文件】:close $x
  【逐行讀取文件】:關(guān)鍵命令gets,while {gets $x line},把x句柄的每一行賦給line變量。類似perl中的:while($line = <$x>),但perl更簡單。
  【寫文件】:“puts 文件句柄 內(nèi)容”
  【3種特殊的文件句柄】:stdin,stdout,stderr。
  【刷新緩沖區(qū)】:有時候內(nèi)容顯示不出來,就用flush命令,“flush 句柄”。
  【文件指針跳躍】:“seek 句柄 偏移 坐標(biāo)原點”,坐標(biāo)原點只有3種:start,current,end
  【獲知文件指針】:“tell 句柄”,“eof 句柄”說明文件是否已經(jīng)讀完
 
 (14)目錄文件管理:
  【查找文件或目錄名】:glob name1 name2 ....,用來查找當(dāng)前工作目錄中是否有name文件,name的格式不是模式匹配的,所以需要文件名的全稱,也支持通配符,但不支持正則表達(dá)式。通配符有*,集合符有[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,單位是字節(jié)。
  【顯示文件類型】:file type name,類型有:file,directory,characterspecial(字符設(shè)備),blockspecial(塊設(shè)備),fifo,link,socket.
  【拷貝文件】:file copy [-force] source target
  【刪除文件或目錄】:file delete [-force] name
  【獲知文件路徑】:file dirname name
  【獲知文件是否可執(zhí)行】:file executable name
  【獲知文件或目錄是否存在】:file exists name
  【獲知文件擴(kuò)展名】: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中調(diào)用perl腳本:
   tcl的功能有限,很多復(fù)雜處理還需要用perl實現(xiàn)較快,以下是tcl調(diào)用perl的方法:
   set x [exec perl abc.pl],其中abc.pl是被調(diào)用的perl腳本的文件名。
   如果abc.pl的內(nèi)容為:
   $a = 4; $b = 3; $c = $a+$b; print $c;
   則 x 被賦值為 7.
關(guān)閉窗口

相關(guān)文章