今天的任務就是要把RISC-V Test跑起來,然後看有哪些錯誤。
RISC-V TEST Pass/Fail判斷
首先我們觀察RISC-V Test發現他最後會走到fail或pass,兩個function的最後一道指令都是ecall。
並且在ecall前,a7會被放93,而如果是success a0會填0,如果是failed a0會被放gp,而gp對應的是執行到幾個測試。
首先這邊93的意思是用來跟system溝通,在有OS的環境a7內的值不同代表想要執行的ecall不一樣,而93參考這裡,代表的是EXIT。
因此我們可以這麼做,當ecall發生且a7是93時結束模擬,並回傳a0內的值。
要注意的是這是在baremetal下才要這樣做,如果是在有OS的環境OS會自己幫你把application關掉,不要多此一舉。
1'st Run, linker script issue
第一支程式我們選擇rv64ui-p-add,執行下去發現還在Load code的時候就segFault了Q Q。
確認後發現,RISC-V Test的code都放在0x80000000開始的位置,為了方便我們修改為0x00000000開始。
2'nd run, ZERO reg issue
重新執行,發現會hang住,而為了方便debug我們設計一個簡易的log系統,其中底下印的insnType及倒的reg都是針對這次的debug去改,實際上只要先印出PC和insn本身即可。
追查後發現我們的reg[0]被改過之後導致bnez指令錯誤,但reg[0]在RISC-V spec內無論怎麼讀都應該是0,因此我們修改在每一次的step前把reg[0]設回0。
3'rd run, pass...?
執行到Ecall,simulator結束,並且觀察到輸出結果是0,為了保險起見同時檢查objdump。
6a0是pass段的ecall,看起來是順利完成,比我想像中的還順利。
Regression環境
測試完ADD之後我們可以來建立環境大量進行測試,否則一支一支這樣測試會有點慢,我們這邊簡單寫一個python script去幫助我們。
import os
import sys
def run_aliss(folder_name, pattern_list_file):
with open(pattern_list_file, 'r') as file:
patterns = [line.strip() for line in file.readlines()]
if not os.path.exists(folder_name):
print("No file" + folder_name + "found")
return
for pattern in patterns:
aliss_command = f"./ALISS -e {folder_name}/{pattern}"
os.system(aliss_command)
if __name__ == "__main__":
if len(sys.argv) != 3:
print("python3 run_aliss.py folder_name pattern_list")
sys.exit(1)
folder_name = sys.argv[1]
pattern_list_file = sys.argv[2]
run_aliss(folder_name, pattern_list_file)
這個script會根據pattern_list裡面的值,到folder裡面去依序執行,同時在ecall exit時把a0的值印出來,這樣就可以一次判斷跑的結果。
執行結果如下,
rv64i/rv64ui-p-add
return value = 0
rv64i/rv64ui-p-addi
return value = 0
rv64i/rv64ui-p-addiw
return value = 0
rv64i/rv64ui-p-addw
return value = 0
rv64i/rv64ui-p-and
return value = 0
rv64i/rv64ui-p-andi
return value = 0
rv64i/rv64ui-p-auipc
return value = 0
rv64i/rv64ui-p-beq
return value = 0
rv64i/rv64ui-p-bge
return value = 0
rv64i/rv64ui-p-bgeu
return value = 13
rv64i/rv64ui-p-blt
return value = 0
rv64i/rv64ui-p-bltu
return value = 7
rv64i/rv64ui-p-bne
return value = 0
rv64i/rv64ui-p-fence_i
return value = 0
rv64i/rv64ui-p-jal
return value = 0
rv64i/rv64ui-p-jalr
return value = 7
rv64i/rv64ui-p-lb
return value = 0
rv64i/rv64ui-p-lbu
return value = 0
rv64i/rv64ui-p-ld
return value = 0
rv64i/rv64ui-p-lh
return value = 0
rv64i/rv64ui-p-lhu
return value = 0
rv64i/rv64ui-p-lui
return value = 0
rv64i/rv64ui-p-lw
return value = 0
rv64i/rv64ui-p-lwu
return value = 0
rv64i/rv64ui-p-ma_data
return value = 93
rv64i/rv64ui-p-or
return value = 0
rv64i/rv64ui-p-ori
return value = 0
rv64i/rv64ui-p-sb
return value = 0
rv64i/rv64ui-p-sd
return value = 0
rv64i/rv64ui-p-sh
return value = 0
rv64i/rv64ui-p-simple
return value = 0
rv64i/rv64ui-p-sll
return value = 43
rv64i/rv64ui-p-slli
return value = 101
rv64i/rv64ui-p-slliw
return value = 0
rv64i/rv64ui-p-sllw
return value = 35
rv64i/rv64ui-p-slt
return value = 0
rv64i/rv64ui-p-slti
return value = 0
rv64i/rv64ui-p-sltiu
return value = 17
rv64i/rv64ui-p-sltu
return value = 29
rv64i/rv64ui-p-sra
return value = 0
rv64i/rv64ui-p-srai
return value = 0
rv64i/rv64ui-p-sraiw
return value = 91
rv64i/rv64ui-p-sraw
return value = 35
rv64i/rv64ui-p-srl
return value = 7
rv64i/rv64ui-p-srli
return value = 7
rv64i/rv64ui-p-srliw
return value = 7
rv64i/rv64ui-p-srlw
return value = 7
rv64i/rv64ui-p-sub
return value = 0
rv64i/rv64ui-p-subw
return value = 0
rv64i/rv64ui-p-sw
return value = 0
rv64i/rv64ui-p-xor
return value = 0
rv64i/rv64ui-p-xori
return value = 0
其中0的代表pass,而有值的代表錯在哪一次測試,可以看到有些指令還是有一些問題,我會趁明天假日修一點,並蒐集比較常見的錯誤分享給大家,而今天主要是完成該環境,透過以上環境我們可以大量跑riscv-test並找到錯誤的位置,待全部修好之後就可以跑Linux啦。
碎碎念 : 終於執行完一支elf啦,雖然後面看到還有許多錯誤,但至少我們踏出成功的第一步了...