pretty code

顯示具有 Shell Script 標籤的文章。 顯示所有文章
顯示具有 Shell Script 標籤的文章。 顯示所有文章

2025年6月29日 星期日

學習如何學習

#!/bin/bash

items=(
A
B
C
)

for ((i=0; i < ${#items[@]}; i++));
do
    item=${items[$i]}
    echo ${item}
done


上面是 bash script 使用 array 的範例,坦白說我從來都記不住,每次需要時都是去我的 blog 搜尋。

換句話說,我記住的不是程式語法,而是我需要的語法在哪裡?

這個語法可能是在 blog,我寫過的 code 中,或是書本的某個章節。

我也不知道這樣好是不好,但我就是不喜歡背書。

今天剛好 Youtube 跳出薑餅資在談學習的一支影片,這個人是我覺得學習相關的知識說得還不錯的 Youtuber。

我想學習如何學習是件很重要的事,雖說每個人喜歡的方法都不同!

總之,我就是只想記住指標的指標在哪裡,我想記住的不是指標本身XD

2025年6月23日 星期一

shell script 真的很難 debug

可能我還不習慣 debug shell script?

上星期五想要檢查一個 list 檔案的每個項目是否存在於另一個 log 中,殊不知一個這麼簡單的東東,我到今天下班前才有空把它搞定,雖然也是因為我今天根本沒時間靜下心來思考的緣故?

總之,我的架構是用 cat list 取得所有項目,然後再把它應用在 for loop 中,不確定這樣是不是大家常用的做法,但至少我覺得這樣的語法我比較不會忘記XD

下面是我回家模擬的結果。


雖然我知道原本的錯誤是誤把 \r 也餵進 grep 的 pattern,但我一時之間也無法解釋第一個 inst_b 怎麼會印的跟我想的不一樣?

改天再來想想 ...

2025/06/23 洗完澡更新

詢問 Bard 的結果,這個語法我應該記不住XD

#!/bin/bash

list=list.txt
source=hier.txt

while IFS= read -r pattern; do
    pattern=`echo $pattern | tr -d '\r'`
    echo $pattern
    grep -E $pattern $source
    echo -----------
done < $list

2025/06/24 更新

大概可以猜出為什麼會印出 @inst_b 了?

原本應該是印出 #inst_b@,但因為 inst_b 後面有一個 \r 回車字元,故跳回 # 位置,然後印出 @,所以 # 就被覆蓋掉了?

這應該還算是一個合理的解釋吧XD

2025年5月14日 星期三

dcman

之前在某篇文章學到 dcman 的用法,讓我可以在沒有 DC license 的情況下還是可以查詢指令說明。

不過,對於 message ID 形式的訊息,比如 VER-970 這樣的 ID,只能在 dc_shell 下用 man 查詢。

雖然辦公室的人很少用 DC,但只是想查個東西,還要等待 DC 啟動,少說也要好幾秒,更別提為了不讓到處都是 DC 的 command.log,個人習慣還是先切換到我自己的 temp 目錄才去啟動 dc_shell。

雖然我有設定 alias 不用打那一長串指令,但還是覺得不開心XD

昨天研究了一下,終於知道為什麼原來的 dcman 不起作用!

man -M 指定的資料夾中,man database 需要符合一定的結構,就我初步看來 DC message ID 形式的 man database 多了一層資料夾,難怪都會查無資料。

解決方式也很簡單,另外寫一個簡單的 bash script,遇到像是 VER-970 這樣的查詢,使用 - 割出前後字串,前面字串就是那多了一層的資料夾名稱,接著再接上 VER-970 以及後面的副檔名即可。

str=$(echo $1 | sed -En 's/([a-zA-Z]+)-(.*)/\1 \2/p')
str=($str)

folder=${str[0]}

整個查詢會變成下面這個樣子

man -l xxxxxxx/VER/VER-970.n 

測試了一下,果然如我想像中一樣可以順利執行,也順便測了 C2 C3 C9 等 DFT 錯誤訊息,目前看來都還可以正常工作。

另外,跟這個主題無關,為了讓自己的 bash script 更有彈性,有些跟著 script 的設定檔,最好還是指定 script 所在的 folder 變成絕對路徑,這樣的好處是當你使用 alias 執行自己的 bash script,我們可以切到要傳遞檔案的那個路徑,這時就不會有找不到設定檔的錯誤發生。

還有要傳遞的檔案,最好也是使用絕對路徑,這樣傳進去 EDA Tool 裡面也不會找不到檔案。

其實不管是 Python 或是 Go 也是如此,畢竟我們會希望把工具放到某個路徑,而不是把檔案複製到工具路徑再去執行,這樣一來,執行路徑就會很清爽,工作起來也更開心XD

SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )

file1=$(realpath $1)

2025/05/15 更新

據我所知,DC 有幾份文件是關於指令、變數以及錯誤訊息,如果習慣查詢 PDF 的話,也可以不用像我一樣使用 man 來查詢。

不過,兩邊的內容都是一樣的,坦白說,都一樣爛XD

個人覺得御三家中,文件寫得最好的是 Cadence,至少 LEC 是我覺得讀起來最順的,其次是 Simens,至於 Synopsys 我就不予置評了!

2025年3月10日 星期一

bash script 的框架

今天為了解一個小 bug,花了我快 40 分鐘。

雖然早就知道 local 的用法,但今天沒有意會到之前寫的程式沒有在函數中的參數加上 local 修飾字,導致我不小心改到外面的全域變數,難怪看了快 40 分鐘才找到問題。

我覺得,即使是 bash script,最好還是要用 main 函數並在所有的函數中都使用 local 關鍵字修飾變數,這樣就不會誤改到全域變數了。

下面是示意圖,Line 13 就是忘了加 local 導致改到全域變數了,這也是我今天耍笨的地方。

2025年2月21日 星期五

2025 week 08 新玩意

01. bash script pointer to variable

有時候,我們就是需要變數的變數,原來只要像下面這樣,就可以達到此目的。

不論是一般變數或是陣列都可以用。


02. bash script in EDA world

今天在試 Tessent run_synthesis command 時,發現它產生出來的 script 居然也是 bash script 而不是 csh script。

這是否意味著,只能用 C Shell 跑 EDA 工具的都市傳說早就已經不復存在?

坦白說,bash script 還是比較好用!

2024年9月5日 星期四

2024 week 36 新玩意

01. 跳板工作站顯目提醒

前幾天自己耍笨,以為工作站沒有安裝相關軟體,又麻煩老闆重傳一次檔案XD

但這樣下去不行,下次搞不好又會忘記跌股?年紀大了,不能依賴自己的記憶。

原本想要加一個 dispatcher,就是 shell 收到指令,都要先攔截進到這個 dispatcher,就可以趁機檢查工作站名稱並提醒自己,但不知道有沒有這種東西?

還好昨天突然想到可以用 prompt,就是那個 shell 提示。

Bash 要設定 $PS1,C Shell 則是要設定 $prompt,兩者顏色語法好像也不一樣?


02. DC 獨立男人

DC 可能因為一直改版,有些指令參數跟以前不一樣,一般都是進到 dc_shell,再用 man 指令查詢。不過,部門只有一套授權,所以當在 log 發現 Error 時,只能等到 DC 跑完才能查XD

前天因為沒什麼睡,昨天下午在完成老闆交代的任務後,就不勉強自己繼續看 Spec,而是上網查詢一下 csh 相關知識,終於讓我無意間看到好東東

alias dcman "man -M $SYNOPSYS/doc/syn/man"

之後就可以直接打 dcman create_clock 查詢了。

03. DC check tcl 語法

也是從同一個網站看來,前天加入自動化 build 不同參數 DC 時,很多錯誤都要等到執行到那邊才會知道,這也是將流程拆分成不同檔案的缺點,無法一目了然的看到並發現錯誤。我們可以用 DC 自帶的 tool 來檢查,只是不知道能不能從進入點 tcl 一直檢查到所有 tcl 檔案?早上進辦公室後在確認一下。

dcprocheck xxx.tcl

2024年9月3日 星期二

天下大勢,分久必合,合久必分

之前將某 VLSI Synthesis 專案架構加到某個 Open Source 的框架當中,當時心裡就想,這樣其實會失去彈性,我個人是比較支持原本那樣的架構,不要走中央集權的模式。

果不其然,下午有個需求想知道某專案的上限在哪?這樣的需求還是要透過自動化處理比較 Smart,還好之前是用最低限度修改的方式將專案加入到框架當中,稍微想了一下,複製了幾個檔案,為了不要大改之前的東西並重複利用 config.mk 原本的內容,在某專案根目錄又加回了 Makefile,方便我在根目錄中觸發自動化流程。

此次修改最麻煩的是 C Shell 一些語法撰寫,我想一般人應該都比較熟悉 Bash,在不斷的 Google 下,終於順利將自動化流程跑起來,但也花了我一個半小時XD

本次快速重點

01. 不管是 Tcl or C Shell 變數都可以用 {} 包住,避免串接時失敗。
02. @ 是 C Shell 用來執行數學運算。
03. bc 是用來處理浮點數並格式化。


小專案單次合成雖然很快,但也要跑將近一個小時,本想晚上回到家吃完飯再用 VPN 連回公司確認一下是否有照我的想法一個接一個的自動化跑下去,無奈公司電腦網路在休眠時常常會無端斷線,只好明天再來看看結果如何?

經過這次事件,明白到自己還是缺少 C Shell 以及 Tcl 相關書籍,趕快買了 2 本書壓壓驚,Tcl 就算了,C Shell 的書還真是難找,只好找了一本快 30 年前的書XD

不得不說,O'Reilly 出版商真是有情有義,在 Google Play 買的書都沒有 DRM 保護,直接就可以下載,也算是節省了我一些時間。

有沒有人可以告訴我使用 Bash 跑商業 EDA tool 到底會不會有問題呀?我實在不想繼續考古下去了…

2024/09/04 更新

作夢都夢到自己在改 C Shell script,有沒有這麼可怕XD

害我半夜三點起來就沒睡了,趕緊把最近買的五本書使用自己開發的 kobofileserver 上傳到 Kobo Elipsa 電子書閱讀器上,然後就沒然後了XD

一直到剛剛都還在看著 PTT 追新聞,我也算是有情有義的男人吧XD


感謝網友 usimon 建議增加多檔上傳功能,原來這功能還真是好用,可能是我以前只會循序邏輯的執行事情吧XD

難道這就是傳說中的單核單執行緒先佔式多工老男人腦XD

2024/09/04 到公司後更新

恨呀,果然有問題,偏偏昨天 VPN 連不回來。

昨天犯了一個錯誤,都怪該死的 DC command 語法,害我不小心中招XD

{$clock} 因為在 Tcl 裡面,{} 就跟 Bash 的單引號一樣,是當純字串的,想單然爾,我昨天的心力都白費了。

解決方式也很簡單,跳脫大小括弧即可。

\{$clock\}

但是人生就是有那麼多 But,此招對 DC 這個聖鬥士無效,它就是需要 {},無奈之下,只好將該 command 改用 echo 自動化產生 Tcl script。

為了這個臭蟲,早上雖然提早來公司,但又花了我一個小時 debug,今天真不是我的天呀!

2024年8月27日 星期二

2024 week 35 新玩意

01. the Linux way to solve problems

這兩天在查一個上禮拜聽同事學習分享時所討論到的問題,為了查這個問題,我需要將 RTL module 分開成個別檔案,才不會用 vim search 時過了頭看到錯的地方XD

之前雖然知道可以在 module 第一行用 V + /endmodule 複製整個 module code,但需要用 :tabe 貼上並儲存下來,故我之前用 vim 時都省略儲存下來的步驟,反正要看的 module 數量也不多,每次重作即可。

不要小看每天這樣重複選取複製的時間,累積下來也很可觀,如果可以,我還是習慣在下班時關掉工作站的所有工作階段,故還是要有個機制快速來產生我要 trace 的檔案。

即使是這樣的需求,用 C 語言寫也是很簡單的,最主要 line array 要宣告夠大,畢竟我已經在 RTL 看到不只超過一行長度的 wire 宣告。

但是既然現在都在 Linux 工作站做事,我們就要用 the linux way 來解決問題!也就是善用組合的力量。

查了一下,用 sed 可以跨行尋找 pattern,指令如下:

sed -n '/module XXX /,/endmodule/p'  RTL.v

注意 XXX module name 後面要空一格或是加上 port declaration 的左括號,這要看 RTL coding style,不然假設你有模組 XXX、XXX_1,則全部都會被複製下來。


感覺這個需求還蠻常用的,將整個 script 改寫成變數驅動並放進我的工作站工具箱中。注意,c shell 沒辦法宣告 array,故這裡還是建議使用 bash。

$@ 命令列參數
modules=("aa" "bb" "cc")  bash array
${#modules[@]} 取得陣列個數
unset modules[0] 移除陣列第一個元素


2024/08/29 更新

前天話才說完,今天就遇到不同 coding style 的 module declaration。

這個有點棘手,但不是因為現在這個 case 棘手,而是隨著這個衍生而來的 case 棘手。

綜合我目前看過的 coding style 至少有 3 種:

module pattern (xxx, xxx)
module pattern(xxx,xxx)
module pattern
(

如果下 module pattern\s*\(* 並不能解決 pattern 及 pattern_x 在 sed 一起出現的問題,但我現在想不到更好的方式只用一個 regex 就可以解決的。

2024年7月10日 星期三

2024 week 28 新玩意

01. 工作站 grep

假設我要找 cell,但不要 .db 的檔案。

grep -r pattern --exclude="*.db"

也可以正向表列

grep -r pattern --include="*.lib"

至於為什麼要加上雙引號?那是因為整個指令傳給 grep 時,*.lib 會被 shell 轉譯過一遍,所以會造成問題,因此要加上雙引號或單引號。

不過照連結所述,當前目錄如果沒有 .lib 檔案應該是要沒問題的,我不確定是否是工作站 grep 版本過舊導致。


晚上用 Windows 11 WSL - Ubuntu 22.04.2 LTS 試了一下,確實是不用加上星號,看來是版本問題?


2024/07/12 更新

更精確來說,既然問題是出在被 shell 過了一手,那應該是 shell 版本的問題,工作站使用的是 tcsh,在我改用 bash 後,這個問題就消失了。

為了之後工作效率著想,以後不管是 glob or regex pattern,最好都用雙引號框住,才不會在急著需要做甚麼事的時候又出問題。

晚上在 WSL 裝了 tcsh 6.21.00,不加上雙引號仍然會有問題,開始懷疑是 tcsh 的 feature 了XD



02. Yosy 執行方式

Yosys 總共有好幾種執行方式:

Run directly
直接執行,手動下 command。

-c *.tcl ( refer to tcl command )
將指令寫在 tcl script 中,最前面要加上 yosys -import,才可以執行 yosys command。

使用這個模式的好處是可以用 tcl 語法,靈活性最大。

-s *.ys ( refer to script command )
將指令寫在 script 中,與 -c 差別在不需要 yosys -import 就可以執行 yosys command。

也因為不是走 tcl callbak,故整個檔案的解析都在 run_frontend 這個函數中。

yosys *.ys
同上,會在 run_frontend 中,執行 default auto command 並靠副檔名決定執行 script command。

嚴格來說上面兩個 run_frontend 執行的地方不一樣,這裡是在 while (optind < argc) 的敘述裡。

yosys xxx
因為沒有副檔名可供判斷,故在 run_frontend 中便會報錯。


03. 工作站 Shell

因為 EDA tool 緣故,大部分工作站預設的 Shell 都是跑 csh(tcsh)。但是自己寫的 Shell script,如果第一行沒有指定 Shell,則預設是跑 bash。

我想一般人應該都是比較熟悉 bash 吧?我不確定此行為是我們工作站獨有,還是 Linux 都是這樣?不過經我剛才在 WSL Ubuntu 上 22.04 實測,看起來未指定第一行會以預設 Shell 來執行。


04. alias 進階用法


雖然我後來才知道有 realpath 這個外部 command 可用,但當初想知道如何用 awk 達成此目的,也算在 shell script 中撞了一堆坑,故想要留下個記錄。以後凡事還是要先 Google,畢竟你的需求別人應該也早就碰到過了,很多事應該不用都自己來才合理。

話說回來,想要用 alias 包裝 command,遇到像雙引號或是 $ 這種特殊符號,就是用接續的方式來處理指令。

畫橘色線的是一個一個串接指令的字串,雙引號和 $ 是直接在 Shell 中,故要加上跳脫字元。

我這裡用的 shell 是 bash,tcsh 也是同樣的道理,差別在 alias 語法不是用等號而是空白。

2024/07/19 更新

晚上實測一下,realpath 無法接受 pipeline,故也不是萬能!

想要在當前目錄下找 Cell Library - realpath *.lib
想要用 grep 遞迴搜尋 Cell name - 還是只能用 awk 也就是這邊用的 alias ($9 改 $1 比較通用,有需要再用 awk 切一次)方式。

2024年4月10日 星期三

2024 week 15 新玩意

01. awk sum

假設有一文字檔內容如下:

ABC    1
ABC    2

可以用 cat txt_file | awk 'BEGIN {sum = 0} {sum += $2} END {print sum}' 得到加總後數字。

02. VIM vertical column rule

使用下面指令便可以在 8 的位置增加一條垂直線,方便觀看階層資料。

set colorcolumn=8

03. VIM 摺疊文字

選取文字後

zf 摺疊
zo 打開

04. VIM 選取一大片文字

V + xxgg 

05. Synthesis 小疑問

最近在做合成時,發現有些 instance 在做完合成後會被吃掉,連帶原本的 module RTL code 也會一併被移除,雖然覺得是因為這個實體的 output 未被任何 logic 使用,但還是很不確定,最後看到一個寫得很清楚的文章。


結論不只是 output,input 也會有同樣的狀況。

06. tcsh redirect

一般較常用的 bash
ls > file 2>&1

tcsh
ls >& file

2022年1月25日 星期二

Shell Script 速成

記錄一下常用語法,懶得每次都要 Google 或是看 PDF 電子書。

變數篇

變數宣告
ABC=XXXXXXX
$ABC

要傳遞出去變環境變數
export ABC=XXXXXX

雙引號中的變數會被展開,單引號則是普通字串
"${ABC}/${DEF}"

上次指令結果
$?

將指令結果變成變數
ABC=$(ls | grep XX) or ABC=`ls | grep XX)

取得不含指令本身之目錄名稱,%表示從後面找最短匹配並丟掉
$(dirname $0)
${0%/*}

Array
Ans=(1258 1414)

取 Array 第一個元素
${Ans[$i]}

取得 Array 元素個數
${#Anss[@]}


流程篇

[ ] 前後要留一個空格

隱形 if ~ then 語法
$ABC 存在則做某事,-d 則是表示目錄
[ -e $ABC ] && do something

if 語法,有特殊字元要跳脫,例如大於或小於
if [ "$? == "0" ]; then
    echo "ok"
else
    echo "error"
fi

不需跳脫 <
if [[ $ABC < $DEF ]]; then
    echo '$ABC < $DEF'
fi

for loop 使用
for ((i=0; i<$max; i=i+1))
do
     echo $i
done

Logs=("abc" "def")
for log in ${Logs[@]}
do
    echo $log
done