昨天已經把 Memory Write 的功能做完了,
今天稍微輕鬆一點,就來完成 Memory Store 指令吧。
剛剛又發現 LH, LHU Test Binary Code 其實有 Misalignment Access 的 Bug,
如果有實做 Trap 就會發現了,
另外 Ececutable Enviroment Intergace (EEI),規範了 L/S 系列指令可以存取的範圍。
也可以規定 Misaligned Memory Access 是硬體有支援,
或者發生 Trap 讓軟體處理。
10/8 補充:Trap 的部分因為考量到存取的 Address Space 可以是 Memory Mapped Device,
可能有 Side Effect,規格書分成兩種 Exception 來處理,
一種是 address misalignment trap,另外一種是 fatal trap,
指令格式如下:
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------------+
| imm[11:5] | rs2 | rs1 | funct3 | imm[4:0] | opcode |
+---------------------------------------------------------+
Write(base + imm[11:0], src, 1)
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------------+
| imm[11:5] | src | base | 000 | imm[4:0] | 0100011 |
+---------------------------------------------------------+
Write(base + imm[11:0], src, 2)
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------------+
| imm[11:5] | src | base | 001 | imm[4:0] | 0100011 |
+---------------------------------------------------------+
Write(base + imm[11:0], src, 4)
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------------+
| imm[11:5] | src | base | 010 | imm[4:0] | 0100011 |
+---------------------------------------------------------+
github 頁面 Tag: ITDay16
為了準備今天的測試,順便修改了昨天的 LH, LHU,
意外發現昨天竟然整個 Binary Code 都寫錯了,竟然少了 func3 欄位!
可怕的是還意外的跑出正確的結果,在大家還沒發現之前趕快自己改掉!
這件事偶爾會發生,
雖然在寫 Unit Test 的過程中為了減少出錯機率,會盡量保持邏輯簡單,
但是因為是人寫的,還是會有錯誤的發生,
唯一的解決方案就是看到的當下趕快修好。
Unit Test 或者各種自動化測試並不是萬靈丹,
它只是幫助我們減少 80% 犯錯的機會而已,
那剩下的 20% 該怎麼辦?
就交給路過的猴子吧!
//memory.cpp
0b000000000100'00000'001'00111'0000011, //LH x7 = sign_ext(read(4, 2))
0b000000000100'00000'101'01000'0000011, //LHU x8 = read(4, 2)
指令實做的部分:
//executor.cpp
...
case INSTRUCTION_DECODER_INTERFACE::STORE_OP:
switch (instruction_decoder->get_func3()) {
case INSTRUCTION_DECODER_INTERFACE::SB_FN3:
SB_E();
break;
case INSTRUCTION_DECODER_INTERFACE::SH_FN3:
SH_E();
break;
case INSTRUCTION_DECODER_INTERFACE::SW_FN3:
SW_E();
break;
default:
std::cout << "INVALID: Func3 in STORE_OP :" << instruction_decoder->get_func3() << std::endl;
break;
}
...
void EXECUTOR::SH_E()
{
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto offset = (instruction_decoder->get_imm(31, 25) << 5) |
(instruction_decoder->get_imm(11, 7) & 0x1F);
auto addr = register_file->get_value_integer(rs1) + offset;
address_space->write(addr, register_file->get_value_integer(rs2), 2);
...
}
...
//instructionDecoderInterface.h
...
STORE_OP = 0b0100011,
...
SB_FN3 = 0b000,
SH_FN3 = 0b001,
SW_FN3 = 0b010,
...