iT邦幫忙

2021 iThome 鐵人賽

DAY 2
2
Software Development

猴子都寫得出來的 RISC-V CPU Emulator系列 第 28

Run HEX File 之 Debug 總集篇

今天就是 Debug 總集篇,
前面都是用猴子自己瞎掰設計的 Code Stream 來驗證,
這次終於能夠真的執行一個由 gcc 編譯出來的程式了!

Debug開發流程

相信大家都還記得昨天提到的 ADDI
觀察結構,很明顯的是要去存取 stack,
先設定一個記憶體位置讓它順利執行,
之後會嘗試用 readelf 從 Binary File 得到資訊來驗證

//cpu.cpp
...
       register_file->set_pc(0x1054);
       register_file->set_value_integer(REGISTER_INTERFACE::x2, 0x3FFFFFF);
       while(true) {
                step();
                wait(delay);
        }
...

中間發現有 SW 指令有 Misalignment 的問題,
先假裝硬體支援,讓它繼續執行:

sw address: 3fffffb
Store and AMO Address Misalignment, end simulation!
exception!
current_pc: 0x1058 target_pc: 0x105c SW 2 8 28 rs1Value: 0x3ffffdf rs2Value: 0x0 rdValue: 0x0 immValue: 0x1c

執行之後發現程式不會跟之前一樣觸發 ILLEGAL_INSTRUCTION_EXCEPTION停下來,
為了觀察前面的執行結果,
限制執行的時間 cycle 數:

       int i=0;
       while(true && i<500) {
                step();
                wait(delay);
               i++;
        }

觀察 Logger 輸出,
發現是 loop 無法結束,會一直無窮迴圈:

current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x14a rdValue: 0x0 immValue: 0xffffffe0
current_pc: 0x1068 target_pc: 0x106c LW 8 12 15 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x14a immValue: 0xffffffec
current_pc: 0x106c target_pc: 0x1070 ADDI 15 5 15 rs1Value: 0x14f rs2Value: 0x0 rdValue: 0x14f immValue: 0x5
sw address: 3ffffe7
current_pc: 0x1070 target_pc: 0x1074 SW 8 15 8 rs1Value: 0x3ffffff rs2Value: 0x14f rdValue: 0x0 immValue: 0xffffffe8
current_pc: 0x1074 target_pc: 0x1078 LW 8 12 15 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x14a immValue: 0xffffffec
current_pc: 0x1078 target_pc: 0x107c ADDI 15 1 15 rs1Value: 0x14b rs2Value: 0x0 rdValue: 0x14b immValue: 0x1
sw address: 3ffffeb
current_pc: 0x107c target_pc: 0x1080 SW 8 15 12 rs1Value: 0x3ffffff rs2Value: 0x14b rdValue: 0x0 immValue: 0xffffffec
current_pc: 0x1080 target_pc: 0x1084 LW 8 12 14 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x14b immValue: 0xffffffec
current_pc: 0x1084 target_pc: 0x1088 ADDI 0 9 15 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x9 immValue: 0x9
current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x14b rdValue: 0x0 immValue: 0xffffffe0

用 grep 把 BGE 撈出來看

make run | grep BGE

最後發現是 BGE 的 Bug!
從輸出可以看到 rs2(0x14a) > rs1(0x9)
但是還是會跳回去 address 0x1068,而不是 address 0x108c

...
current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x149 rdValue: 0x0 immValue: 0xffffffe0
current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x14a rdValue: 0x0 immValue: 0xffffffe0
current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x14b rdValue: 0x0 immValue: 0xffffffe0
current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x14c rdValue: 0x0 immValue: 0xffffffe0
...

實際程式

github 頁面 Tag: ITDay28

原來是不小心把 rs2 填成 rs1,
修正後就沒問題了:

//executor.cpp
...
(register_file->get_value_integer(rs1) >= register_file->get_value_integer(rs2) ?
...

執行結果

可以看到程式在執行到 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x9
然後就跳到下一行,
正常的執行到 JALR 並結束程式。

$make run
...
sw address: 3ffffeb
current_pc: 0x107c target_pc: 0x1080 SW 8 15 12 rs1Value: 0x3ffffff rs2Value: 0x9 rdValue: 0x0 immValue: 0xffffffec
current_pc: 0x1080 target_pc: 0x1084 LW 8 12 14 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x9 immValue: 0xffffffec
current_pc: 0x1084 target_pc: 0x1088 ADDI 0 9 15 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x9 immValue: 0x9
current_pc: 0x1088 target_pc: 0x1068 BGE 15 14 1 rs1Value: 0x9 rs2Value: 0x9 rdValue: 0x0 immValue: 0xffffffe0
current_pc: 0x1068 target_pc: 0x106c LW 8 12 15 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x9 immValue: 0xffffffec
current_pc: 0x106c target_pc: 0x1070 ADDI 15 5 15 rs1Value: 0xe rs2Value: 0x0 rdValue: 0xe immValue: 0x5
sw address: 3ffffe7
current_pc: 0x1070 target_pc: 0x1074 SW 8 15 8 rs1Value: 0x3ffffff rs2Value: 0xe rdValue: 0x0 immValue: 0xffffffe8
current_pc: 0x1074 target_pc: 0x1078 LW 8 12 15 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x9 immValue: 0xffffffec
current_pc: 0x1078 target_pc: 0x107c ADDI 15 1 15 rs1Value: 0xa rs2Value: 0x0 rdValue: 0xa immValue: 0x1
sw address: 3ffffeb
current_pc: 0x107c target_pc: 0x1080 SW 8 15 12 rs1Value: 0x3ffffff rs2Value: 0xa rdValue: 0x0 immValue: 0xffffffec
current_pc: 0x1080 target_pc: 0x1084 LW 8 12 14 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0xa immValue: 0xffffffec
current_pc: 0x1084 target_pc: 0x1088 ADDI 0 9 15 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x9 immValue: 0x9
current_pc: 0x1088 target_pc: 0x108c BGE 15 14 1 rs1Value: 0x9 rs2Value: 0xa rdValue: 0x0 immValue: 0xffffffe0
current_pc: 0x108c target_pc: 0x1090 ADDI 0 0 0 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x0 immValue: 0x0
current_pc: 0x1090 target_pc: 0x1094 ADDI 0 0 0 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x0 immValue: 0x0
current_pc: 0x1094 target_pc: 0x1098 LW 2 28 8 rs1Value: 0x3ffffdf rs2Value: 0x0 rdValue: 0x0 immValue: 0x1c
current_pc: 0x1098 target_pc: 0x109c ADDI 2 0 2 rs1Value: 0x3ffffff rs2Value: 0x0 rdValue: 0x3ffffff immValue: 0x20
current_pc: 0x109c target_pc: 0x0 JALR 1 0 0 rs1Value: 0x0 rs2Value: 0x0 rdValue: 0x0 immValue: 0x0
INVALID: Opcode :0
Illegal Instruction, end simulation!
exception!

Info: /OSCI/SystemC: Simulation stopped by user.

小小的結語

呼,到這邊為止,
這個 Simulator 算是完成了吧。

雖然有些地方用簡化的方式處理,
還跑著不知道從哪裡生出來的執行檔,
但是 Logger 很有用, Simulator 也正常跑完了。

接下來就是收尾的部分了,
還要交代一下怎麼準備編譯環境,
再給這個專案一個範例程式和使用說明。

嘗試性的寫了 Memory Hierarchy 的文章,
也花了很多時間研究和準備 ONNC、
Branch Predictor、OOO Execution 相關章節,
但還是覺得目前的進度來說不適合放在這個系列文,
不是走馬看花,就是花太多時間導致專案目標無法達成,
就留待賽後吧。

這段時間每天都在觀察自己的變化,
興趣廣泛是優點也是缺點,
雖然很容易因為時間不夠放棄一些東西,
但是當一隻每天都對新知識興致勃勃的猴子也過得蠻快樂的。


上一篇
Program Loader
下一篇
Hello World: 編譯環境建立
系列文
猴子都寫得出來的 RISC-V CPU Emulator31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言