iT邦幫忙

2021 iThome 鐵人賽

DAY 2
1
Software Development

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

RISC-V: I-type 位元運算指令

  • 分享至 

  • xImage
  •  

看到標題一定都猜到了,
相信大家對這幾道指令都不陌生,這次實作的就是 ANDI、ORI、XORI,
對應到程式語言中,分別是 &、|、^ 的位元運算。

為了方便閱讀,接下來章節都會列出指令格式。

I-type

指令格式如下:

|31     20|19   15|14    12|11   7|6       0|
+-------------------------------------------+
|   imm   |  rs1  | funct3 |  rd  | pocode  |
+-------------------------------------------+

ANDI

rd = rs1 & imm

|31     20|19   15|14    12|11   7|6       0|
+-------------------------------------------+
|   imm   |  rs1  |  111   |  rd  | 0010011 |
+-------------------------------------------+

ORI

rd = rs1 | imm

|31     20|19   15|14    12|11   7|6       0|
+-------------------------------------------+
|   imm   |  rs1  |  110   |  rd  | 0010011 |
+-------------------------------------------+

XORI

rd = rs1 ^ imm

|31     20|19   15|14    12|11   7|6       0|
+-------------------------------------------+
|   imm   |  rs1  |  100   |  rd  | 0010011 |
+-------------------------------------------+

NOT

沒錯,和這次實作的第一道指令一樣
這個指令也是致敬 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

上一篇
RISC-V: 作為第一道指令的聰明選擇
下一篇
RISC-V: I-type 小於指令
系列文
猴子都寫得出來的 RISC-V CPU Emulator31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言