今天一樣是簡單的 SLT、SLTU 指令實作,
並為了 Code Stream Logger 做準備,
唯一有趣的是遇到 g++ 未實做的 feature 導致編譯錯誤,
只好改用別種方式實做。
指令格式如下:
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------+
| func7 | rs2 | rs1 | funct3 | rd | opcode |
+---------------------------------------------------+
rd = rs1 < rs2 ? 1 : 0
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 010 | rd | 0110011 |
+-------------------------------------------------------+
rd = (uint32_t)rs1 < (uint32_t)rs2 ? 1 : 0
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 011 | rd | 0110011 |
+-------------------------------------------------------+
github 頁面 Tag: ITDay24
RISC-V-TLM 的 Logger 設計不太適合接下來的模擬用途,
作者客製化每道指令的 Log 內容,為了可讀性犧牲了一致性,
這樣的設計也在維護上容易有一些小疏失,
接下來實做的時候會嘗試重新設計 Logger 的部分,
這次先把 Code Stream Logger 需要用到的指令和指令名稱列出來。
Instruction Name 需要從數字一對一對應到字串,本來想用 std::array
做,
和 exactstep 類似,結果遇到了 g++ 很有禮貌的說:sorry, unimplemented: non-trivial designated initializers not supported
先改用 std::map
實做。
//instructionDecoderInterface.h
...
enum Instruction {
ADDI_INSTRUCTION_ENUM,
ANDI_INSTRUCTION_ENUM,
ORI_INSTRUCTION_ENUM,
XORI_INSTRUCTION_ENUM,
...
std::map<Instruction, std::string> instruction_name_map = {
{ADDI_INSTRUCTION_ENUM,"ADDI"},
{ANDI_INSTRUCTION_ENUM,"ANDI"},
{ORI_INSTRUCTION_ENUM,"ORI"},
{XORI_INSTRUCTION_ENUM,"XORI"},
...
指令實作:
//instructionDecoderInterface.h
...
SLT_FN3 = 0b010,
SLTU_FN3 = 0b011,
...
SLT_FN7 = 0b0000000,
SLTU_FN7 = 0b0000000,
...
//executor.cpp
...
case INSTRUCTION_DECODER_INTERFACE::SLT_FN3:
SLT_E();
//do not check FN7 for readibility, refactor in future
break;
case INSTRUCTION_DECODER_INTERFACE::SLTU_FN3:
SLTU_E();
//do not check FN7 for readibility, refactor in future
break;
...
void EXECUTOR::SLT_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = register_file->get_value_integer(rs1) < register_file->get_value_integer(rs2) ? 1 : 0;
register_file->set_value_integer(rd, value);
}
void EXECUTOR::SLTU_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = (uint32_t)register_file->get_value_integer(rs1) < (uint32_t)register_file->get_value_integer(rs2) ? 1 : 0;
register_file->set_value_integer(rd, value);
}
...