Tcl腳本在IC設計中的應用
這是IC君的第11篇原創文章 (同步於 微信公眾號 icstudy)
平時我們了解的編程語言C,C++,Java屬於編譯型語言,它們通常是為了開發專業的軟體或者作為高性能計算之用。那如果我們只要實現一些簡單的功能呢?腳本也許是一個更合適的選擇。腳本語言是為了縮短傳統的編寫-編譯-鏈接-運行過程而創建的計算機編程語言。腳本通常是解釋運行而非編譯,有簡單、易學、易用的特性,目的就是希望使用者能夠快速完成程序的編寫工作。
IC設計中常用的腳本有Tcl、Perl、Shell、Python(最近好像很紅)等,在這些腳本裡面,Tcl的語法最為簡單,最容易上手,所以今天我們先來聊一聊它。
Tcl 是「工具控制語言(Tool Control Language)」的縮寫。Tk 是 Tcl「圖形工具箱」的擴展,它提供各種標準的 GUI 介面項,可以快速的進行高級應用程序開發。
John K. Ousterhout於 1988 年開始開發 Tcl/Tk(讀作「tickle tee-kay」),然後是加州大學伯克利分校的一名教授繼續對它進行開發。Tcl 的設計目標就是可擴展性強、容易上手的。目前大部分EDA工具都支持Tcl語言,如Design Complier、quartus、Synplify、modesim、finesim等。而且Tcl在各個平台都能運行,一般的Linux/Mac OS下面都會安裝tclsh,Windows下面可以安裝官方的ActiveTcl工具,所以大家很容易找到學習的環境。
以IC君的經驗來看,Tcl/Tk在IC領域的主要作用有3個:
1. 複雜的文本處理。Tcl可以把文本中的每一行變為一個列表,最簡單的列表就是包含由任意個空格、製表符、換行符分隔開的任意多個元素的字元串。例如,以下字元串 John anne mary jim就是一個有4個元素的列表。你可以直接根據元素編號來獲取字元串內容,想一想這個特性是不是很方便我們做文本處理,Perl是不支持這個功能的哦。另外就是正則表達式,這個是文本處理的大殺器,Tcl也是完全支持的。所以每當看到有人說Tcl比Perl弱很多,沒什麼好學的,IC君心裡就把他默默的鄙視了一百遍,那是你不會用好不好。IC君的經驗是如果我們在處理文本時用常規的sed/vim處理起來很麻煩,那就寫一個Tcl腳本來解決吧。如果還不行,那就寫兩個Tcl腳本吧。
2. 自動化執行flow。例如自動執行整個綜合的flow,得到最後的結果和report。只要敲一次鍵盤,然後就可以喝著茶等待最終的結果,是不是爽歪歪。
3. 編寫一些強大的EDA工具。之前IC君入職一年後,在項目執行的空閑時間寫了一個能夠基於晶元布局自動生成有寄生RC電路的腳本,大概幾千行的代碼。相比原來的人工flow,這個腳本大概能節省一個星期的工作時間,而且電路模型更精準,現在跟我同組的同事都在使用這個腳本。另外最近IC君發現我司的Tcl大牛寫了一個主程序3萬多行Tcl/Tk代碼的圖形界面自動建模工具。IC君在用這個工具的時候,感覺和使用大型EDA公司的工具沒太大的區別,除了GUI略丑和BUG略多之外
。由於公司不能拍照,這裡也無法向大家展示這個EDA工具。總之,如果你的腦洞足夠大,是完全可以利用Tcl/Tk開發出強大的EDA工具的。
下面我們就通過幾個Tcl腳本的例子,來具體說明一下Tcl的用法。
第1個例子是用來簡化網表的: 主要功能就是將給定subckt 裡面的電路移除掉,但是保留埠定義,網表內容如下圖所示:
#!/usr/bin/tclsh
#判斷輸入變數是不是2個,如果不是2個,提示正確用法
if {$argc!=2} {
puts "Error usage: The correct usage is delsubckt netlist subckt_name"
return 0
}
#獲取網表名
set netlist [lindex $argv 0]
set netlist_temp "$netlist.temp"
#獲取要刪除內容的Subckt名字, 如AMP
set subckt_name [lindex $argv 1]
set subckt_name [string toupper $subckt_name]
#打開網表文件為後面讀取做準備
set nop [open $netlist r]
#打開臨時文件為後面寫入做準備
set ntempop [open $netlist_temp w+]
set flag 0
set lastname ""
#只要沒到文件末尾,就一行行的讀下去
while {[gets $nop line]>=0} {
#獲取一行的第1個元素
set fname [lindex $line 0]
#將這個元素轉換為大寫格式
set fname [string toupper $fname]
#獲取一行的第2個元素
set sname [lindex $line 1]
set sname [string toupper $sname]
#判斷subckt的名字是不是屬於我們要刪除的內容
if {$flag==0&&$fname==".SUBCKT"&&$sname==$subckt_name} {
#如果是我們要找的subckt,先把subckt的定義輸出到臨時文件中
puts $ntempop $line
#設定找到的標誌
set flag 1
#繼續讀取下一行,判斷是不是開頭有+號,如果有+號,表示定義沒結束
gets $nop line
set fname [lindex $line 0]
set fi [string range $fname 0 0]
while {$fi=="+"} {
puts $ntempop $line
gets $nop line
set fname [lindex $line 0]
set fi [string range $fname 0 0]
}
}
#如果不是不是我們要找的subckt,那就直接輸入到臨時文件中去
if {$flag==0} {
puts $ntempop $line
}
#如果找到標誌為1,並且第1個元素為.ENDS, 則輸出到臨時文件中去,整個subckt內容的刪除工作完成
if {$flag==1&&$fname==".ENDS"} {
puts $ntempop $line
set flag 0
}
}
#等文件的所有行都遍歷過後,退出打開的文件句柄
close $nop
close $ntempop
#將臨時文件命名為我們原來的文件
exec mv $netlist_temp $netlist
puts "Generate $netlist successfully!"
這個腳本裡面包含了打開文件的過程,文本處理的過程,一般的文本處理套用這個腳本,改改文本處理的過程就可以實現了。總得來說,Tcl的語法還是蠻順暢的,只要想法清楚,很容易就可以用代碼實現出來。
第2個例子是關於DC綜合腳本的執行flow的:
#//顯示開始時間
sh date
# //移除DC中原有的設計
remove_design –designs
#//下面是庫的設置
set search_path [list /tools/lib/sxx25/feview_s/version1/STD/Synopsys /tools/lib/sxx25/feview_s/version1/STD/Symbol/synopsys]
set target_library { sxx25_tt.db }
set link_library { sxx25_tt.db }
set symbol_library { sxx25.sdb }
#//讀入example1.v文件
read_file -format verilog ~/example1.v
# //把EXAMPLE1指定為當前設計的頂層模塊
current_design EXAMPLE1
#//設置一些IO埠名
set clk [get_ports clk]
#//設置變數clk的值是[get_ports clk],在下面的代碼中若出現$clk字樣,則表示引用該變數的值,即用[get_ports clk]代替$clk。
set rst_n [get_ports rst_n]
set general_inputs [list a b c]
set outputs [get_ports o]
#//設置時鐘約束條件
# //創建一個周期為20ns,占空比為1的時鐘
create_clock -n clock $clk -period 20 -waveform {0 10}
set_dont_touch_network [get_clocks clock]
# //設置時鐘埠的驅動為無窮大
set_drive 0 $clk
# //設置時鐘端為理想網線
set_ideal_network [get_ports clk]
#//設置複位信號約束
set_dont_touch_network $rst_n
set_drive 0 $rst_n
set_ideal_network [get_ports rst_n]
#//設置輸入延時
set_input_delay -clock clock 8 $general_inputs
#//設置輸出延時
set_output_delay -clock clock 8 $outputs
#//設置面積約束和設計約束
set_max_fanout 4 $general_inputs
set_max_transition 0.5 [get_designs "EXAMPLE1"]
set_max_area 0
#//綜合優化
compile -map_effort medium
#//保存文件
# //保存反標文件
write -f db -hier -output ~/EXAMPLE1.db EXAMPLE1 -xg_force_db
write -f verilog -hier -output ~/EXAMPLE1netlist.v EXAMPLE1
write_sdf -version 1.0 ~/EXAMPLE1.sdf
#//產生報告並保存
report_area > EXAMPLE1.area_rpt
# //把報告面積的文件保存成EXAMPLE1.area_rpt文件,運行完腳本以後可以查看該文件。
report_constraint -all_violators > EXAMPLE1.constraint_rpt
report_timing > EXAMPLE1.timing_rpt
# //顯示結束時間
sh date
從上面的綜合腳本來看,一部分語句是Tcl原生格式的,其它的是EDA工具DC支持的語句,不過如果你對Tcl很熟悉的話,上面的代碼閱讀起來就很親切。
第3個例子是TK的,這個例子很簡單,就是寫一個hello world圖形界面:
#!/usr/bin/wish
button .hello -text Hello -command {puts stdout "Hello, World!"}
button .goodbye -text Bye! -command {exit}
pack .hello -padx 60 -pady 5
pack .goodbye -padx 60 -pady 5
代碼執行時在命令行輸入 wish test.tcl,結果如下圖所示,
當你點擊Hello按鈕,命令行會輸出Hello, World,如果點Bye,則程序退出。根據功能大家也可以猜測上面的代碼的意思。如果大家想寫一個強大的圖形端的工具,可以進一步參考Tcl/Tk的書籍。
IC君講的這些腳本例子都是拋磚引玉,大家應該很容易結合自己工作的實際需求寫出強大的腳本。
如果大家想獲取上面例子的源代碼,或者腳本之類的問題想交流一下,以及一些其它的IC問題需要交流,可以加入我們的微信群。
最近IC君深有感觸,有時候你百思不得其解的問題,跟大家交流一下,說不定就能解決哦;有時候你千辛萬苦尋找的東西,也許群友不經意間就能提供哦。
歡迎掃描二維碼進群哦:
aHR0cHM6Ly93ZWl4aW4ucXEuY29tL2cvQWVwYnlJWkxjc01CWTdiZA== (二維碼自動識別)
推薦閱讀:
※遊戲編程領域中有哪些鮮為人知的腳本語言,且為什麼它們沒有像lua一樣普及?
※如何想學點編譯原理,又不想直接看龍虎之類的書籍,太多理論,乾燥?
※目前,網頁腳本語言三個主流:PHP,JSP,.NET。究竟是一種怎麼樣的形勢?是三國鼎立,還是其他的形勢呢?各自的真正優勢,又是在哪裡?
※Lua 5.3為何很慢?該不該升級?