Bluespec SystemVerilog(BSV) 及 MIT 體系結構公開課 筆記

yjmstr發表於2024-10-10

前言

早年 MIT 有三門用 bsv 作為硬體描述語言的體系結構課程,代號分別為 6.004,6.175 和 6.375. 根據 MIT CS course list,現在這三門課分別改名為了 6.1910、6.1920 和 6.5900. 本文是自學這三門課所需的 bsv 時記錄的筆記,內容主要來源於這三門課目前公開的資料(6.175 16fall, 6.375 19fall)。

環境配置

在 windows11 wsl2-ubuntu22.04 和 ArchLinux 上均搭建了實驗環境,透過 Git 進行多端開發。

ArchLinux 上透過 yay -S bluespec-git 構建 bsc 時 GHC 會報錯,考慮到後續需要使用 Connectal,ArchLinux 對 Connectal 的支援不完善,此處採用 kazutoiris 的 docker 映象 進行實驗。

在用 docker 做 6.375lab3 的 p2 時,會報錯缺少 fft3w,暫時先不用 docker 做,做完以後再用 docker

6.175

lab5

和 ysyx 差不多,從單週期開始,寫到多週期,再到兩級流水,再到兩級 BTB.

2016 版的 lab5 用 Scemi 模擬,2017 版用 connectal。這裡我們做 2017 版的 lab5。

執行 bash init.sh 時可能會報錯 “RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8)”,開全域性代理 + 執行下述命令後暫時解決:git config --global http.postBuffer 524288000

隨後指令碼會使用 curl 下載 ply-3.9.tar.gz,但指令碼中的連結已經失效,我們可以手動從 https://github.com/dabeaz/archive/blob/main/ply/ply-3.9.tar.gz 下載。此外,指令碼會將 connectal 中的 python script 全部替換為 python2.7 script,但最新拉下來的 connectal 資料夾裡的 Makefile 用得其實是 python3 script。這裡要麼把 ply 和 py 都改用最新版(沒試過),要麼全部對齊到實驗當年的版本。我的選擇是把 python3 改回 python2.7

由於 bsc 版本問題,實驗程式碼的一些部分需要修改以後才能跑通,例如 tagged Valid 要改為 tagged Valid False,並修改相應暫存器的型別從 Maybe#(void) 改為 Maybe#(Bool)。

lab5 初始程式碼缺少 simple.S,並且 Makefile 中的工具鏈路徑需要手動修改一下。此處透過 apt 安裝交叉編譯工具鏈,並把 Makefile 中的路徑改成 /usr/bin/ 下的路徑,上網扒了個 Simple.S 過來。

實驗自帶的 Makefile 中傳遞了 -m32 引數給交叉編譯工具鏈,但現在 GCC 和 RISC-V Spec 的版本均已更新,I 擴充套件中也不再包含 Zicsr 指令,需要寫 -march=rv32i_zicsr 代替,並去掉 -m32,此外若編譯工具鏈時使用的 abi 不是 ilp32, 則需要加上 -mabi=ilp32 選項。

配置好交叉編譯工具鏈後,make 會報錯缺少 mtohost 這個 CSR,mtohost 並不屬於 RISC-V 標準(曾經是非標準 HTIF 的一部分,現在已經被移除了),主要是用於測試。我們需要把 mtohost 換成別的 CSR。後續要讀出時,也要把 mfromhost 換成對應的 CSR。

自行編譯的工具鏈不帶有 elf2hex 工具,可以 git clone git://github.com/sifive/elf2hex.git 下載。編譯之後建立一個軟連結到 /opt/riscv/bin/ 下並命名為 elf2hex 即可。需要注意的是要改一下 Makefile 中 elf2hex 的引數的格式。

elf2hex 報錯:elf2hex: could not find objcopy。可以直接用 vim 修改 elf2hex 指令碼,把裡面的 objcopy 路徑改了。
此外 make 的執行還需要安裝 python. docker 裡已經有 python3 了,可以裝個 python2 來跑 make。直接用 python-is-python3 的話可能還得修改 python 指令碼里的部分語法。

編譯 benchmark 時也需要進行上述修改,此外 crt.S 中會用到 eret 這個指令,其對應的具體指令與當前特權級有關。

編譯專案時會報錯 ply.lex 找不到,經檢查發現是 ln -s 無法有效建立指向 ply 資料夾的軟連結,直接把 ply 資料夾裡的檔案複製過來也可以。

編譯 benchmark 時會報錯 median.riscv: no such file. 這是因為傳給 elf2hex 的路徑不對。

修復之後 make 會報錯 bk_init 函式引數只有兩個,但是用的時候傳了三個引數。connectal 的原始碼 connectal/scripts /Makefile.connectal.build 中對 bsc 的版本進行了判斷,在 bsc major 小於等於 2019 時會使用三個引數,否則使用兩個引數。看上去這個判斷沒有正確執行,導致了出錯。我們可以手動調整相應位置的程式碼。

修復之後 make 執行模擬會報錯缺了兩個庫:

/usr/bin/ld: cannot find -lbskernel: No such file or directory
/usr/bin/ld: cannot find -lbsprim: No such file or directory

這同樣是 connectal 對 bsc 的版本判斷未生效導致的。我們可以手動修改 Makefile.connectal.build 中的內容,去掉對老舊版本 bsc 的判斷。

跑 run_asm.sh 模擬時會報錯 ERROR: ld.so: object 'libSegFault.so' from LD_PRELOAD cannot be preloaded (cannot open shared object file): ignored./bin/sh: 1: cannot open /home/ubuntu/MIT_BSV/6.175lab5/connectal/boardinfo/.json: No such file. https://lemire.me/blog/2023/05/01/under-linux-libsegfault-and-addr2line-are-underrated/ 中提到現在版本 工具鏈似乎移除了 libsegfault,自從 ubuntu22.04 開始,需要安裝 glibc-tools 才能獲得這個庫。透過 apt 在 docker 中安裝後不再報錯。

此外注意到會報 ERROR: Executing unsupported instruction at pc: 00000200. Exiting,懷疑是生成的 vmh 有問題,檢視 vmh 轉換指令碼,發現每行讀八個字元,但是 vmh 檔案每行只有兩個字元。注意:這個 bug 修復之前執行 run_asm.sh 可能會導致 bne 測例死迴圈,生成巨大的 log。

重讀了一遍 https://mp.weixin.qq.com/s?__biz=MzkwNTMzOTE2MA==&mid=2247485751&idx=3&sn=36a5323b3c32984bb94c97b313aa0c23&chksm=c0f80140f78f8856abd37f667cbd06a3267eed4ed34c1d36f16f527d8613ea14d1dbdcad0b8f&scene=21#wechat_redirect,發現 6.175 的 lab5 要改的地方還蠻多的,run_asm.sh 和 run_bmarks.sh 都要改。

6.375

lab2

dlopen 報錯

做 6.375 的 lab2 時,按照講義 make simulation 隨後 ./out 報瞭如下錯誤:

Error: dlopen: ./out.so: undefined symbol: _Z12dollar_fopenPKcPKSsS2_
    invoked from within
"sim load $model_name $top_module"
    (file "/opt/tools/bsc/lib/tcllib/bluespec/bluesim.tcl" line 188)

上網搜到如下帖子後按照帖子裡的方法新增 -ffat-lto-objects 引數重新編譯 bsc,還是會報這個錯誤。

解決方法:在 BluespecSV-CN 交流群裡問群友得知,可以將 bscflags 的 -Xc++ -D_GLIBCXX_USE_CXX11_ABI=0 刪掉,或者將 0 改為 1 即可。

lab3

p2 ref.c

沒看懂 p2 要幹嘛,意思是要根據 ref.c 造一組新測例餵給 bsv?暫時跳過

ToMP & FromMP

實現流水線中的 ToMP 和 FromMP 模組,用 Cordic 演算法轉換直角座標和極座標。Cordic 的程式碼已經給我們了,直接呼叫就行。

寫完以後往流水線里加三個模組。

最終結果和期望結果在 char 15 line 1 不同。上 Github 扒了個其他人寫好的程式碼跑了一下,也是這樣。暫時認為實現是正確的。

lab4

connectal

用 Docker 做。如果直接用非 root 賬戶 make simulation,可能會遇到許可權不足的問題。這種情況下可以在啟動容器時指定 -root 選項切換到 root 賬戶做。

p1 make simulation 的結果和期望結果在 char 15 line 1 不同,和 lab3 的結果在 char 787 line 1 處不同。

用到 FPGA 的實驗部分暫時跳過,但還是掃一眼講義中的內容。(* synthesize*) 可以讓編譯器不內聯某個模組,而是為該模組生成單獨的檔案和模組。

多型模組前面不能直接加 (* synthesize *),這是由於 Verilog 不支援多型。因此我們需要在多型模組所使用到的各個非多型模組前面加 (* synthesize *)。需要注意的是,如果一個模組加了 provisos 就不能 synthesize 了。

connectal 僅支援 Bit#(n) 型別的訊號,因此需要把 FixedPoint#(16, 16) 轉換成 Bit#(32) 才能在 connectal 中使用。呼叫硬體中的方法時可以把 Bit#(32) 透過 unpack 轉換為 FixedPoint#(16, 16),硬體返回的 FixedPoint#(16, 16) 結果可以透過 pack 轉換為 Bit#(32)。

unpack 的作用是將 Bit 表示轉換為其它 Bluespec 中的型別。

做完 p7 跑 make run_simulation 會報錯,改用直接執行 ubuntu.exe 的方式可以執行並跑出 out.pcm,但模擬結束時會出現 [sock_fd_write:184] error in sendmsg -1 104 xsim_disconnect:75 pint=0x7761f8001000 calling $finish Aborted (core dumped)

相關文章