pretty code

2025年5月17日 星期六

不枉費我放假幾個小時的努力

在一個 netlist 中,想要追蹤一個信號是件很痛苦的事XD

如果是可以開啟 EDA 的環境,比如說透過 Tessent Visualizer,只要準備好相關 library,滑鼠點擊幾下,就可以看到來龍去脈。

但很多時候,我可能只有 Vim 可用。

之前為了這種情況,寫了一個 map 自動將某個 module code 複製起來,使用 tab 開啟複製到新分頁,這樣查詢時就不會過頭,避免已經跳到別的 module 而不自知。

早上出門前突然想到,是否可以在按下 n 跳下一個位置時,顯示目前位置所在的 module name 以及行號呢?

下午回家洗完澡後,扣掉晚上吃飯時間,大概也寫了 3 ~ 4 個小時有吧?

終於在剛剛完成了,雖然只有不到 100 行 code,但卻遭遇到很多問題。

比如在 statusline 顯示變數,怎樣用 regex subgroup 切出我要的 module name,還有如果 map key 還是用 n 會一直進入無限遞迴的問題,以及針對 statusline 的修改即使是對的,但還是會報錯,必須重新出去 Vim 再進入一次才會正常的問題等等。

真的是得來不易呀,也不知道是否真能有點幫助?

但不得不說,完成的那一瞬間,爽度真是一百分有XD

2025年5月16日 星期五

好像會又好像都不會

Vim script 寫到現在,有時候會覺得好像自己什麼都不會XD

早上因為一直咳嗽,很早就起來了,想要為自己的 Netrw 加一個功能,加到剛剛都還不成功。

快要上班了,只好先用 patch 搞定,留下 echom debug 訊息,之後有空再來尋求正規解法XD

2025/05/17 更新

目前先用個變數記住 current buffer number,每次進到我的 Netrw,只要現在 buffer number 跟之前不一樣就可以放心的砍下去,好像還可以。

至於遇到 C:\..\ 這樣的路徑,也就是一直按 - 鍵,已經切到根目錄的情況,多一道檢查手續的 patch,好像也還行,暫時先這樣解決吧。

現在只差到底是否要針對 Windows 與 Linux 區分目錄符號?感覺說明看起來是不用?

目前我的 .vimrc 可以用在 

Windows gVim
Windos Git Bash
工作站 Vim

嚴格來說,也可以用在不管是公司還是家裡電腦的 WSL2 Unbuntu,但是因為工作站 Vim 版本比較舊,我的 Netrw 一些函數無法呼叫,只好還是用 Vim 內建的 Netrw。

我也懶得再去區分了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年5月12日 星期一

Vim tabline

看懂別人的 Vim plugin 有個好處,便是可以隨時把別人的 code 加到自己的 .vimrc 中!

當然,正規作法還是 follow Vim 的哲學,讓 plugin 可以 lazy loading,這樣才不會影響 Vim 啟動速度。

不過,我需要的都是小功能,加到自己的 .vimrc 還是比較方便XD

加了 tabline 後,好像已經快要沒有可以加的了?

tabline 原來只是個字串,但我們需要同時對所有 tab page 設定,格式就像下面那張圖的 command line 字串,其中 #TabLineSel# 表示目前 active 的 tab page。


之前一直不知道為啥 Windows Git Bash 會有問題,就在剛剛終於頓悟了,原來 Git Bash 中也放了一個 Vim,故我同時執行了原本的 Netrw 和我自己的,難怪每次切回 File Viewer 總是會報什麼 modifiable = off 的錯誤。


2025/05/15 更新

原來我還少設了一個 #TabLineFill#,難怪這個語法顏色怎樣都設不成功XD


2025/05/17 更新

雖然 Vim tab 不是這樣用的,但我還是習慣一個 tab 一個檔案。

不管是以前還是現在,我很少用分割視窗,可能我不喜歡使用太大螢幕的關係吧?

總之,適合自己的工作模式才是最好的,不用管別人怎樣界定。

這也正凸顯出 Vim 的過人之處,哪邊不好用就可以動手修改,難怪我會對他愛不釋手XD

2025年5月10日 星期六

Vim script 最佳學習指南


上面這個應該是我覺得寫得最好的,再加上又是中文,雖然是簡體,但還是比讀英文快多了XD

Learn Vimscript the Hard Way 雖然也是不錯,但我還是覺得敘事過慢,不用工作當然無所謂,但是畢竟人還要上班,一個傳統目錄的網站列表還是比較符合我的需求。

總之,一樣主題的書就是要多買幾本,彼此互相參照學習最快,想當年我初學 C 語言,C 語言的書買了至少有 10 來本,每本書都可以從中找到我所需要的部分,雖然這些書也早就丟光了XD

買過丟掉的書就不算了,手邊大概還有 10 來紙本書放在公司,如果電子書也不算的話,底下就是我手上目前僅存資訊相關的書籍了,很多都是我很喜歡的書,以後如果有出電子書我應該會再買一次來收藏,畢竟我家這般潮濕的天氣,什麼時候書會 gone 我都不知!

誠品就只有一個小小的櫃有資訊相關的書,至少有一半是 AI 和我不需要的文書處理的書,故每次跟我老婆說要去誠品巡巡田水,也不期待會有我想買的書。

買書還是得去天瓏,但想到要上台北還是覺得累。

不過今天還是買了一本我想看的書《無瑕的程式碼 - 函數式設計篇》,希望可以多少給我一些啟發。

人生好難呀XD













2025年5月8日 星期四

使用全域變數真的要小心,尤其在 Golang

可能我不常寫多執行緒的程式再加上常用很深的遞迴,故有時候我都會直接用全域變數XD

在別的程式語言也許還好,但在 Golang 的時候,一個變數是否是新的變數端看他是否有用到 :=

如果這時不小心,在操作全域變數時加上 :=,這時存取的就是一個新的 local 變數。

雖然除錯也花不了多少時間,但也是很難第一時間就馬上想到。

另外,為了收集資料,我的函數有時可以 for single job,有時也可以 for  accumulated job,如果這時忘記清空原本的全域變數,就會導致資料變成好幾次的累積結果。

以後除了很深的遞迴,我看還是少用全域變數XD

有時候也不是想用全域變數,但一開始如果不用一個 struct 包住變數,再加上隨著需求逐漸明朗,很多時候函數的參數都會逐漸膨脹,很容易就超過 5 個以上,再加上我的 code 大部分都函數化,有時一改就是好幾層,只好偷懶用全域變數XD

我想以我的 coding style 來說,一定要養成 struct 進,struct 出的習慣,這樣應該能避免全域變數的使用?

不過這樣 struct 也會變得腫脹,真是兩難?

2025年5月4日 星期日

我的第一版 netrw

終於有個樣子了,現在只剩下幾個問題
01. 沒有比較好的方法去禁止編輯,map key 不只影響 netrw 的 filetype,可能我的理解還是有誤。
02. statusline 不知為何沒有生效。

" for my file explorer
augroup explorer_group
    autocmd!
    autocmd BufEnter * call s:MK_Browse("")
    "autocmd FileType netrw nnoremap :q :q!
    autocmd FileType netrw nnoremap <CR> :call <SID>MK_Enter_Browse(<SID>GetCurrNetrwFile())<CR>
    "autocmd FileType netrw nnoremap i <ESC>
    "autocmd FileType netrw nnoremap I <ESC>
    "autocmd FileType netrw nnoremap a <ESC>
    "autocmd FileType netrw nnoremap A <ESC>
    "autocmd FileType netrw nnoremap x <ESC>
    "autocmd FileType netrw nnoremap s <ESC>
    "autocmd FileType netrw nnoremap y <ESC>
    "autocmd FileType netrw nnoremap p <ESC>
augroup END

function! <SID>MK_Enter_Browse(name)
    if isdirectory(a:name)
        let l:dir = a:name
        if has('win32')
            let l:dir = substitute(dir, "/", "\\", "")        
        endif
        
        execute ":e! " . l:dir
    else
        let g:MK_curr = getcwd()
        let g:MK_sv = winsaveview()
        execute ":tabe " . a:name
    endif
endfunction

function! s:MK_Browse(dir)
    " get current directory
    let curr = expand("%:p")
    if a:dir != ""
        let curr = a:dir
    endif

    " not directory, do nothing
    if !isdirectory(curr)
        execute ":set nocursorline"
        return
    endif

    " change folder for later using
    if getcwd() != curr
        call chdir(curr)
    endif

    " set up some options
    execute ":set filetype=netrw"
    execute ":setlocal nonumber"
    execute ":setlocal nowrap"
    execute ":setlocal cursorline"
    execute ":setlocal buftype=nowrite"
    
    " delete original path structure
    normal! dG

    let f_list = readdir(curr, 1)
    let n = 1

    " save paths
    let files = []
    let folders = []

    call add(folders, "../")
    call add(folders, "./")
    
    for f in f_list
        if f == ".swp" || f == "_.swp"
            continue
        endif

        let s = f
        if isdirectory(f)
            let s = s . "/"
            call add(folders, s)
        else
            call add(files, s)
        endif
    endfor
    
    " add folders
    for f in folders
        call setline(n, f)
        let n = n + 1
    endfor
    
    " add files
    for f in files
        call setline(n, f)
        let n = n + 1
    endfor

    " restore previous position
    if exists("g:MK_sv")
        if g:MK_curr == getcwd()
            call winrestview(g:MK_sv)
            unlet g:MK_sv
        endif
    endif

    " statusline
    call s:SetStatusLine()
endfunction