戰(zhàn):打造FPGA仿真腳本自動(dòng)生成工具)
從手動(dòng)找文件到一鍵生成仿真腳本我的Tcl/Tk仿真文件管理小工具做FPGA開發(fā)久了你會(huì)發(fā)現(xiàn)一個(gè)特別不起眼但特別耗時(shí)間的環(huán)節(jié)——整理仿真文件列表。尤其是當(dāng)工程從別人手里交過來或者你同時(shí)維護(hù)三四個(gè)項(xiàng)目的時(shí)候光是把所有RTL文件、IP核文件、仿真Testbench收集齊、排好順序就能耗掉大半個(gè)下午。我一開始也是硬扛每次都在Modelsim里手寫vlog命令一個(gè)文件一個(gè)文件地加加到后來眼睛都花了。后來實(shí)在忍不了花了幾天時(shí)間用Tcl/Tk寫了一個(gè)小工具專門干這件事自動(dòng)掃描工程目錄下的所有HDL文件解析模塊之間的依賴關(guān)系界面上勾選一下就能直接生成Modelsim/Vivado能跑的仿真腳本。這篇文章就把這個(gè)工具的設(shè)計(jì)思路和實(shí)現(xiàn)細(xì)節(jié)完整拆一遍分享給同樣被文件管理折磨過的FPGA工程師。1. 為什么必須做這個(gè)工具仿真文件管理的三個(gè)真實(shí)痛點(diǎn)先說說我到底被什么逼到?jīng)Q定自己寫工具。1.1 從零散文件到完整仿真環(huán)境的隱性成本FPGA仿真的前置工作遠(yuǎn)比想象中繁瑣。一個(gè)稍微像樣點(diǎn)的工程光RTL文件可能就有幾十上百個(gè)再加上Vivado生成的IP核文件、約束文件、Testbench、內(nèi)存初始化文件亂七八糟堆在好多個(gè)目錄里。仿真器不會(huì)自動(dòng)幫你找文件你必須告訴它每個(gè)文件從哪里來、以什么順序編譯。這個(gè)文件清單就是整個(gè)仿真流程的第一步也是最容易被低估的一步。我統(tǒng)計(jì)過自己一個(gè)中規(guī)模項(xiàng)目光是把所有文件準(zhǔn)確無誤地整理進(jìn)ModelSim平均要花掉30到45分鐘而且這還是建立在文件都在正常位置的前提下。如果有人動(dòng)過目錄結(jié)構(gòu)或者某個(gè)文件被移走排查起來更是血虧。1.2 手工維護(hù)文件清單的連鎖錯(cuò)誤手工維護(hù)文件清單最大的問題還不是慢而是容易出錯(cuò)。你少加一個(gè)文件仿真環(huán)境的編譯階段直接報(bào)錯(cuò)你文件順序排錯(cuò)了編譯時(shí)變量聲明找不到定義你忘記加某個(gè)IP的輸出文件頂層模塊直接找不到對(duì)應(yīng)端口。這些錯(cuò)誤本身不難解決但定位它們非常消耗耐心。尤其是做biss-c、fpga pcie這類需要多級(jí)仿真層次的項(xiàng)目文件的組織方式和編譯順序會(huì)直接影響仿真結(jié)果的正確性。我見過有同事用手在excel表里維護(hù)文件清單每次改工程都要來回比對(duì)那個(gè)維護(hù)成本實(shí)在太高了。1.3 團(tuán)隊(duì)協(xié)作時(shí)文件結(jié)構(gòu)不可控另外一個(gè)痛點(diǎn)來自團(tuán)隊(duì)協(xié)作。每個(gè)人都有自己的命名習(xí)慣和目錄組織方式有人喜歡把Testbench放在頂層目錄有人喜歡按模塊建文件夾。你拿到了別人的工程文件光理解他的目錄邏輯就要花不少時(shí)間。如果有一個(gè)工具能自動(dòng)掃描目錄、識(shí)別文件類型、生成清晰的文件列表整個(gè)交接過程會(huì)順暢很多。我決定自己寫這個(gè)工具核心訴求就三個(gè)能自動(dòng)掃描目錄、能智能判斷文件類型、能一鍵把選中的文件輸出成標(biāo)準(zhǔn)仿真腳本。而選型的答案落在了Tcl/Tk上。2. Tcl/Tk在FPGA工具鏈里的天然優(yōu)勢(shì)可能有人會(huì)問做個(gè)界面工具用Python不香嗎反正Tkinter也是Tk。這個(gè)問題的答案恰恰是在實(shí)際使用中才深刻體會(huì)到的。2.1 所有主流FPGA工具都內(nèi)置Tcl解釋器Vivado內(nèi)置了Tcl 8.5Quartus支持Tcl腳本ModelSim和Questa更是深度集成Tcl。這意味著你只要學(xué)會(huì)了用Tcl腳本操作FPGA工具就能極端流暢地把自己的工具和第三方EDA軟件串聯(lián)起來沒有跨語言調(diào)用的阻抗消耗。舉個(gè)例子我的工具生成完文件列表后可以直接把Vivado的XCI文件路徑解析出來生成一段Tcl腳本交給Vivado的tcl console執(zhí)行IP核就被添加進(jìn)工程了。Python也做得到但你需要考慮進(jìn)程間通信、路徑轉(zhuǎn)義、字符串編碼等等一堆細(xì)節(jié)完全沒有Tcl/Tk里那種我就是這里的人的順滑感。2.2 Tk的GUI組件足以覆蓋工具類軟件的全部需求Tcl/Tk的GUI能力經(jīng)常被低估。很多人覺得Tk做出來的界面丑、控件少但真正用來寫內(nèi)部工具Tk提供的組件已經(jīng)完全夠用。我用到的核心組件就這幾個(gè)ttk::treeview做文件列表樹ttk::button做按鈕ttk::combobox做路徑模式選擇ttk::progressbar顯示掃描進(jìn)度。這些組件拼出來的界面雖然談不上驚艷但勝在輕量、啟動(dòng)快、無外部依賴。內(nèi)部分發(fā)的工具軟件穩(wěn)定性永遠(yuǎn)比美觀重要。同事拿到一個(gè)單文件exe雙擊就能跑起來這比什么都強(qiáng)。2.3 一套代碼跨平臺(tái)Windows和Linux通吃FPGA開發(fā)環(huán)境天然是跨平臺(tái)的。有人用Windows有人用Linux有人在服務(wù)器上跑仿真。Tcl/Tk腳本天然跨平臺(tái)不需要改一行代碼就能在兩邊運(yùn)行這個(gè)優(yōu)勢(shì)幫我省掉了大量平臺(tái)適配的功夫。我之前用C#寫過類似的工具Windows上跑得挺好一到Linux服務(wù)器上就徹底抓瞎。換到Tcl/Tk之后這個(gè)煩惱徹底消失了。3. 工具的整體架構(gòu)從掃描目錄到生成腳本的三階段流水線整個(gè)工具的核心邏輯可以拆成三段流水線文件發(fā)現(xiàn)、文件分類與依賴解析、腳本生成。這三段各自獨(dú)立每一段都有清晰的輸入輸出邊界。3.1 文件發(fā)現(xiàn)利用Tcl的glob和file命令遍歷目錄第一件事是遞歸遍歷指定目錄找出所有可能的HDL文件。我用的核心命令是glob配合file命令完成目錄遍歷。proc scan_dir {dir {exts {.v .sv .svh .vhd .vhdl .xci .mif .coe}}} { set result [list] set dir [file normalize $dir] if {![file isdirectory $dir]} { return $result } # 遞歸獲取所有文件 set all_files [list] foreach ext $exts { set pattern [file join $dir *$ext] # glob的-glob模式會(huì)把通配符當(dāng)作文件名處理需要小心 foreach f [glob -nocomplain -directory $dir -types f *$ext] { lappend all_files $f } } # 遞歸處理子目錄 foreach sub [glob -nocomplain -directory $dir -types d *] { set sub_result [scan_dir $sub $exts] set all_files [concat $all_files $sub_result] } return $all_files }這里有幾個(gè)容易被坑的點(diǎn)。第一glob -nocomplain必須加否則掃描的目錄里沒有匹配文件時(shí)它會(huì)直接拋錯(cuò)界面就崩了。第二file normalize會(huì)把相對(duì)路徑轉(zhuǎn)成絕對(duì)路徑這在后面生成絕對(duì)路徑的仿真腳本時(shí)非常關(guān)鍵。第三默認(rèn)的glob不區(qū)分大小寫在Linux上你想要的.SV文件會(huì)被跳過所以我在Windows和Linux下用了不同的后綴匹配邏輯。遞歸遍歷的性能不需要過度擔(dān)心我測(cè)試過包含300多個(gè)文件的工程目錄掃描耗時(shí)在1到2秒以內(nèi)完全在可接受范圍內(nèi)。3.2 文件分類識(shí)別RTL、Testbench、IP核和初始化文件文件掃描完之后下一步是分類。分類規(guī)則我總結(jié)了一套優(yōu)先級(jí)體系按順序判斷命中即歸類。proc classify_file {fpath} { set fname [file tail $fpath] set ext [string tolower [file extension $fpath]] set lname [string tolower $fname] # 規(guī)則1: 擴(kuò)展名權(quán)重最高的話直接判定 if {$ext eq .xci || $ext eq .xcix} { return ip } if {$ext eq .mif || $ext eq .coe} { return mem } # 規(guī)則2: 文件名含tb/testbench/sim_的優(yōu)先歸為仿真文件 if {[regexp -nocase {^(tb_|sim_|.*_tb$|.*_test$|testbench)} $lname]} { return tb } # 規(guī)則3: 默認(rèn)歸為RTL if {$ext eq .v || $ext eq .sv || $ext eq .vhd || $ext eq .vhdl} { return rtl } return other }這套規(guī)則解決了我之前手工分類時(shí)90%以上的判斷場(chǎng)景。有些特例需要人工調(diào)整但工具的定位本來就是幫你做掉重復(fù)勞動(dòng)保留人工兜底的能力。Testbench的識(shí)別規(guī)則是這套體系里最重要的因?yàn)榉抡婺_本生成時(shí)Testbench文件的編譯順序通常是最后——它依賴前面所有的RTL和IP文件。3.3 腳本生成把用戶選擇翻譯成可執(zhí)行的仿真命令分類完成之后工具會(huì)往界面左側(cè)的Treeview里填充文件樹每個(gè)文件前面加一個(gè)復(fù)選框。用戶在界面上勾選需要參與仿真的文件點(diǎn)擊生成仿真腳本工具就把選中的文件按照依賴關(guān)系排序后輸出成一段完整的ModelSim或Vivado仿真腳本。ModelSim的編譯腳本核心其實(shí)就是幾條命令# 生成結(jié)果示例compile_sim.do vlib work vmap work work vlog -sv -work work E:/project/src/top_module.v vlog -sv -work work E:/project/src/sub_module_a.v vlog -sv -work work E:/project/sim/testbench/tb_top.v vsim -c -work work work.tb_top run -all對(duì)于Vivado生成的就是一段Tcl腳本核心是add_files和set_property# 生成結(jié)果示例add_sim_files.tcl add_files -norecurse [list E:/project/src/top_module.v E:/project/src/sub_module_a.v] set_property source_mgmt_mode All [current_project] update_compile_order -fileset sim_1這段腳本里做了幾個(gè)關(guān)鍵處理識(shí)別勾選的Testbench文件并把它們放到vsim命令后面作為頂層識(shí)別IP核文件并調(diào)整編譯順序?qū)β窂浇y(tǒng)一做正斜杠轉(zhuǎn)換避免Windows反斜杠在轉(zhuǎn)義時(shí)搞出各種幺蛾子。4. 界面交互的關(guān)鍵設(shè)計(jì)讓腳本工具變得好用工具好不好用界面交互占了七成。技術(shù)腳本可以樸素但交互細(xì)節(jié)必須做到位。4.1 用ttk::treeview組織多層級(jí)的文件結(jié)構(gòu)文件列表我用的是ttk::treeview每個(gè)目錄節(jié)點(diǎn)是一個(gè)treeitem文件掛在其下。樹形展示的好處是層次感清楚你一眼就能看出哪些文件屬于哪個(gè)模塊。ttk::treeview .flist -columns {type size mtime} -show tree headings .flist heading #0 -text 文件路徑 .flist heading type -text 分類 .flist heading size -text 大小 .flist heading mtime -text 修改時(shí)間Treeview每一項(xiàng)的-values里放的是文件的分類、大小、修改時(shí)間。用戶點(diǎn)擊表頭可以排序這在大工程里特別有用。我加了點(diǎn)擊表頭排序的功能比如按分類排序后所有Testbench文件會(huì)自動(dòng)聚在一起方便批量勾選。4.2 路徑記憶與工程管理從每次配置到一鍵恢復(fù)早期的版本每次打開都要手動(dòng)選擇目錄用了幾回就煩了。后來我加了一個(gè)配置文件機(jī)制用Tcl自帶的registryWindows或者一個(gè)簡(jiǎn)單的配置文件Linux存取最近使用的路徑。# 保存工程配置到文件 proc save_config {} { set cfg_file [file join [file dirname [info script]] tool_config.ini] set fp [open $cfg_file w] puts $fp last_dir: $last_dir puts $fp last_output: $last_output close $fp }打開工具時(shí)會(huì)自動(dòng)讀取配置恢復(fù)上次的工作目錄和輸出目錄直接進(jìn)入掃描流程。這個(gè)小小的改動(dòng)讓工具的日常使用體驗(yàn)提升了一個(gè)檔次。4.3 工作進(jìn)度反饋不要讓用戶對(duì)著空白界面干等掃描大目錄時(shí)GUI線程如果沒有反饋用戶很容易以為程序假死了。Tcl/Tk的update命令可以強(qiáng)制刷新事件循環(huán)讓界面在長(zhǎng)時(shí)間操作中保持響應(yīng)。proc scan_progress {current total} { .progress configure -value [expr {double($current) / $total * 100}] update idletasks }不過update idletasks有個(gè)小問題如果掃描過程中用戶點(diǎn)了其他按鈕會(huì)觸發(fā)重入。我的解決辦法是在掃描前設(shè)置一個(gè)is_scanning標(biāo)志位掃描過程中禁掉所有可能產(chǎn)生沖突的按鈕和輸入框避免交互競(jìng)態(tài)。另外我遵循一個(gè)原則任何耗時(shí)超過2秒的操作都必須有進(jìn)度提示。哪怕就是一個(gè)滾動(dòng)條和一行文字也比讓用戶干等強(qiáng)很多。4.4 錯(cuò)誤處理與日志輸出把排查成本降到最低工具在給用戶省時(shí)間的同時(shí)也要為用戶留著排查問題的線索。我在界面底部加了一塊日志區(qū)所有關(guān)鍵操作都會(huì)實(shí)時(shí)記錄下來掃描了多少文件、哪些文件被歸入哪類、腳本生成過程中有沒有跳過異常文件、配置文件有沒有成功寫入。日志區(qū)同時(shí)顯示在界面上并寫入一個(gè)log_日期.txt文件。這樣用戶在使用工具過程中如果遇到異常可以直接把這個(gè)日志文件發(fā)給我或者自己排查問題定位起來非常高效。這個(gè)設(shè)計(jì)理念很簡(jiǎn)單工具我做得很傻瓜但底層邏輯全部透明可查。5. 依賴解析的進(jìn)化從順序編譯到自動(dòng)排序一開始我以為生成腳本只要把所有文件并列輸出就好反正Modelsim能自己處理編譯順序和依賴關(guān)系。后來實(shí)測(cè)發(fā)現(xiàn)Modelsim對(duì)跨文件依賴的處理并沒有想象中那么智能至少有以下兩種情況會(huì)出亂子。5.1 跨文件的include路徑依賴Verilog里的include指令引入的文件名是相對(duì)于當(dāng)前文件所在目錄解析的一旦文件被挪了位置include就失效了。我的工具掃描文件時(shí)會(huì)把所有文件按相對(duì)路徑記錄下來在生成腳本時(shí)自動(dòng)給編譯命令加上incdir參數(shù)把工程里所有包含.svh頭文件的目錄都塞進(jìn)去。proc collect_incdirs {file_list} { set incdirs [list] foreach f $file_list { set dir [file dirname $f] if {[llength [glob -nocomplain -directory $dir *.svh]] 0} { lappend incdirs $dir } } return [lsort -unique $incdirs] }這個(gè)處理在真實(shí)項(xiàng)目中解決了我反復(fù)踩過的一個(gè)坑Testbench里include了一個(gè)頭文件而頭文件不在當(dāng)前工作目錄下結(jié)果編譯時(shí)一整排報(bào)錯(cuò)最后發(fā)現(xiàn)只是路徑?jīng)]指對(duì)。5.2 IP核文件的編譯順序調(diào)整Vivado生成的IP核文件通常包含一個(gè).xci文件和若干輸出文件其中核心的輸出文件是一個(gè).vhoVHDL輸出或者.vVerilog輸出。這些文件編譯順序必須在其他RTL文件之前。我的工具在文件分類階段就已經(jīng)把IP核單獨(dú)標(biāo)記出來了生成腳本時(shí)會(huì)先把它們排在最前面。# 排序策略IP優(yōu)先RTL次之Testbench最后 proc cmp_files {a b} { set order_a [expr {[classify_file $a] eq ip ? 0 : ([classify_file $a] eq tb ? 2 : 1)}] set order_b [expr {[classify_file $b] eq ip ? 0 : ([classify_file $b] eq tb ? 2 : 1)}] return [expr {$order_a - $order_b}] }這一步讓編譯時(shí)的錯(cuò)誤量大幅下降尤其是面對(duì)包含MIG、LVDS這類復(fù)雜IP的工程時(shí)以前手動(dòng)調(diào)編譯順序的痛苦被徹底終結(jié)了。5.3 稀疏依賴圖的顯式聲明從compile到保存project對(duì)于特別復(fù)雜的工程光靠編譯順序不夠。我的工具還支持導(dǎo)出一個(gè)完整的project.tcl里面包含了set_propertyfile_type等完整屬性設(shè)置可以直接通過Vivado的source命令加載。這種做法的好處是不僅仿真能用綜合實(shí)現(xiàn)階段也能復(fù)用這套文件管理邏輯。proc generate_vivado_project {files ip_files} { set fp [open vivado_project.tcl w] puts $fp # 自動(dòng)生成的Vivado工程腳本 puts $fp create_project -in_memory -part xc7a100tcsg324-1 puts $fp add_files -norecurse [list \$ip_files\] puts $fp add_files -norecurse [list \$files\] puts $fp update_compile_order -fileset sim_1 puts $fp set_property top tb_top [get_filesets sim_1] close $fp }實(shí)際測(cè)下來用這個(gè)腳本創(chuàng)建的Vivado工程和手動(dòng)Create Project新建的工程幾乎完全一致省去了大量的GUI點(diǎn)選操作。6. 實(shí)測(cè)效果與幾個(gè)印象深刻的坑工具開發(fā)完成后我拿手頭三個(gè)真實(shí)項(xiàng)目跑了完整測(cè)試效果和數(shù)據(jù)都超出預(yù)期。6.1 三個(gè)真實(shí)項(xiàng)目的使用效果對(duì)比第一個(gè)項(xiàng)目是一個(gè)基于Zynq的FMC通信工程RTL文件47個(gè)IP核8個(gè)Testbench 3個(gè)。以前手動(dòng)整理文件清單需要大約25分鐘用工具后從掃描到生成仿真腳本只花了6秒。第二個(gè)項(xiàng)目是一個(gè)圖像處理工程文件更多有120多個(gè)RTL文件、20多個(gè)IP核手動(dòng)整理清單接近1個(gè)小時(shí)工具掃描加生成腳本耗時(shí)不到20秒。第三個(gè)項(xiàng)目是一個(gè)PCIE相關(guān)工程各個(gè)模塊分散在十幾個(gè)目錄里工具的優(yōu)勢(shì)最明顯。項(xiàng)目類型文件數(shù)量手動(dòng)整理耗時(shí)工具耗時(shí)編譯一次通過率FMC通信58約25分鐘約10秒80%提升圖像處理145約60分鐘約20秒70%提升PCIE擴(kuò)展37約30分鐘約8秒90%提升這里的編譯一次通過率指的是生成腳本后直接在Modelsim里跑不因文件缺失或順序錯(cuò)誤而報(bào)錯(cuò)的概率。工具的排序邏輯在PCIE工程里表現(xiàn)最好因?yàn)槟莻€(gè)工程的目錄層次最復(fù)雜手動(dòng)排錯(cuò)率很高。6.2 坑一Windows路徑反斜杠的轉(zhuǎn)義地獄這是我在開發(fā)過程中遇到的最大的坑。Windows文件路徑默認(rèn)使用反斜杠\在Tcl字符串里反斜杠是轉(zhuǎn)義符直接拼接路徑會(huì)得到完全錯(cuò)誤的結(jié)果。set bad_path E:\project\src\top.v # 在Tcl里這個(gè)字符串的實(shí)際內(nèi)容是 E:projectsrc op.v解決辦法是統(tǒng)一使用正斜杠/Tcl和ModelSim都能識(shí)別。我在所有路徑輸入的入口處做了一個(gè)轉(zhuǎn)換把用戶輸入的所有\(zhòng)替換成/并在保存配置時(shí)也用正斜杠存儲(chǔ)。這個(gè)處理極小但少了它整個(gè)工具在Windows上的行為會(huì)變成一場(chǎng)災(zāi)難。另一個(gè)和路徑有關(guān)的坑是file normalize在Tcl 8.5與8.6之間的行為差異。Vivado內(nèi)置的Tcl是8.5ModelSim可能是8.6我在用file normalize處理符號(hào)鏈接時(shí)發(fā)現(xiàn)兩者處理結(jié)果不一樣后來干脆避開這個(gè)命令自己寫了一段相對(duì)路徑轉(zhuǎn)絕對(duì)路徑的邏輯穩(wěn)太多了。6.3 坑二Tcl對(duì)中文字符和特殊字符的處理FPGA工程文件路徑里經(jīng)常會(huì)出現(xiàn)中文而Tcl 8.5默認(rèn)的file命令在某些平臺(tái)下對(duì)非ASCII字符的兼容性不好。我的解決方案是在腳本開頭顯式指定編碼encoding system utf-8這一行解決了我遇到的亂碼和文件打開失敗問題。另外路徑中如果包含空格、括號(hào)、$這些特殊字符直接拼到命令里會(huì)被Tcl解釋器吃掉。我用了一個(gè)quote_path函數(shù)把所有路徑用花括號(hào)包起來避免特殊字符干擾。6.4 坑三glob對(duì)隱藏目錄的誤判掃描的時(shí)候glob -types d *會(huì)把隱藏目錄比如.git也掃進(jìn)來這些目錄里往往沒有HDL文件還會(huì)拖慢掃描速度。我加了過濾邏輯跳過所有以.開頭的目錄掃描性能和結(jié)果準(zhǔn)確度都有改善。7. 后續(xù)可以繼續(xù)擴(kuò)展的方向你如果看完也想做一個(gè)類似工具或者打算在自己現(xiàn)有的基礎(chǔ)上繼續(xù)加功能下面幾個(gè)方向我覺得特別有價(jià)值。7.1 支持更多仿真器和第三方工具的導(dǎo)出格式目前工具直接支持的輸出格式是ModelSim腳本和Vivado的Tcl腳本。VCS、Questa、Riviera這些工具雖然也都基于Tcl但命令細(xì)節(jié)有差異。如果把輸出格式做成插件模式每種仿真器一個(gè)模板工具的通用性會(huì)強(qiáng)很多。7.2 集成編譯反饋實(shí)現(xiàn)編譯-報(bào)錯(cuò)-定位閉環(huán)現(xiàn)在工具只負(fù)責(zé)生成腳本編譯報(bào)錯(cuò)后的定位還是靠Modelsim自己的窗口。如果你在生成仿真腳本時(shí)記錄了文件路徑和行列號(hào)的映射關(guān)系編譯報(bào)錯(cuò)時(shí)就能在工具里直接點(diǎn)擊錯(cuò)誤信息跳到對(duì)應(yīng)文件的源代碼位置。這個(gè)功能做出來后整個(gè)仿真調(diào)試的效率還能再上一個(gè)臺(tái)階。7.3 和版本管理工具聯(lián)動(dòng)Git已成FPGA工程標(biāo)配掃描文件時(shí)如果結(jié)合git status輸出工具就能高亮顯示哪些文件剛剛被修改過這樣你在重新生成仿真文件清單時(shí)就會(huì)特別留意最近改動(dòng)的部分排查問題更快。最后分享一個(gè)我的使用習(xí)慣在寫這個(gè)工具之前我有個(gè)體會(huì)做FPGA開發(fā)真正耗費(fèi)心力的常常不是那些高大上的時(shí)序收斂和復(fù)雜的協(xié)議實(shí)現(xiàn)反而是這些看起來不起眼但每天都繞不開的重復(fù)性勞動(dòng)。仿真文件整理就是典型代表。工具的研發(fā)或許需要幾天時(shí)間但折算成長(zhǎng)期節(jié)省的時(shí)間回報(bào)率極其可觀。我現(xiàn)在養(yǎng)成一個(gè)習(xí)慣每次新開工一個(gè)工程第一件事就是把工程的頂層目錄用這個(gè)工具掃一遍確認(rèn)文件分類正確、依賴關(guān)系清晰然后才正式開始寫代碼和仿真。這種前置的文件環(huán)境體檢讓我后面所有的排錯(cuò)都順暢很多。如果你也常年在多個(gè)工程之間切換強(qiáng)烈建議嘗試用Tcl/Tk寫點(diǎn)小工具不必一上來就追求功能齊全。從掃描目錄列出文件這個(gè)小功能開始逐步擴(kuò)展你會(huì)發(fā)現(xiàn)Tcl/Tk這老牌組合在FPGA領(lǐng)域真是被低估的金礦。