看到標題一定都猜到了,
相信大家對這幾道指令都不陌生,這次實作的就是 ANDI、ORI、XORI,
對應到程式語言中,分別是 &、|、^ 的位元運算。
為了方便閱讀,接下來章節都會列出指令格式。
指令格式如下:
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| imm | rs1 | funct3 | rd | pocode |
+-------------------------------------------+
rd = rs1 & imm
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| imm | rs1 | 111 | rd | 0010011 |
+-------------------------------------------+
rd = rs1 | imm
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| imm | rs1 | 110 | rd | 0010011 |
+-------------------------------------------+
rd = rs1 ^ imm
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| imm | rs1 | 100 | rd | 0010011 |
+-------------------------------------------+
沒錯,和這次實作的第一道指令一樣,
這個指令也是致敬 XORI,
RISC-V 的 imm 運算前都會進行 sign extension,
只要填入 -1 ,就會變成:
rd = rs1 ^ (0xFFFF)
= ~rs1
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| -1 | rs1 | 100 | rd | 0010011 |
+-------------------------------------------+
github 頁面 Tag: ITDay11
這次修了一個已知的小 Bug,
一開始在 Register File 其實沒有實作 x0 Hard Wire to Zero 的功能。
導致寫入 x0 實際上也是會把值存進去的,讀取也會讀取實際的值。
還有一個 Bug 在 Decoder 裡面,留著明天處理,
答案其實在 Console 印出來的運算結果裡面,大家可以先猜猜看囉。
太習慣平常的工作流程了,
開發沒有 Unit Test 保護,寫起來實在沒什麼沒安全感。
//register.cpp
void REGISTER::set_value_integer(unsigned int register_index, int32_t value)
{
if(register_index == 0)
return;
...
}
int32_t REGISTER::get_value_integer(unsigned int register_index)
{
if(register_index == 0)
return 0;
...
}
這次在 Decoder 新增了 Func3
,增加可讀性。
也把 OP_IMM
改成 IMM_OP
,
讓 vim 的 auto complete 能夠更精準地提供選項。
//instructionDecoderInterface.h
enum Opcode {
IMM_OP = 0b0010011,
};
enum Func3 {
//IMM_OP
ADDI_FN3 = 0b000,
ANDI_FN3 = 0b111,
ORI_FN3 = 0b110,
XORI_FN3 = 0b100,
};
在 Executor 裡面新增 ANDI、ORI、XORI 的實作,
另外把 if 用 switch 取代,減少重複性的程式碼。
void EXECUTOR::execute()
{
switch (instruction_decoder->get_opcode()) {
case INSTRUCTION_DECODER_INTERFACE::IMM_OP:
switch (instruction_decoder->get_func3()) {
case INSTRUCTION_DECODER_INTERFACE::ADDI_FN3:
ADDI_E();
break;
case INSTRUCTION_DECODER_INTERFACE::ANDI_FN3:
ANDI_E();
break;
case INSTRUCTION_DECODER_INTERFACE::XORI_FN3:
ORI_E();
break;
case INSTRUCTION_DECODER_INTERFACE::ORI_FN3:
XORI_E();
break;
default:
std::cout << "INVALID: Func3 in IMM_OP :" << instruction_decoder->get_func3() << std::endl;
break;
}
break;
default:
std::cout << "INVALID: Opcode :" << instruction_decoder->get_opcode() << std::endl;
break;
}
}
$ make run
./simulator
SystemC 2.3.3-Accellera --- Sep 17 2021 22:09:07
Copyright (c) 1996-2018 by all Contributors,
ALL RIGHTS RESERVED
ADDI
rs1: 0
rd: 1
value: 1
ADDI
rs1: 1
rd: 2
value: 4096
ADDI
rs1: 0
rd: 0
value: 0