iT邦幫忙

2021 iThome 鐵人賽

DAY 2
0
Software Development

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

RISC-V: I-type 移位指令

  • 分享至 

  • xImage
  •  

今天又發現新鮮的 Bug 拉!
我養蟲,蟲養我,
今天的我拯救昨天的我。

幸好 Code Base 還小,
不然每天猴肉測試實在不是辦法,
小猴子都快 Debug De 成老猴子了,
好想抽時間補 Unit Test 阿...

I-type

指令格式如下:

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

SLLI

rd = rs1 << shamt

|31   25|24   20|19   15|14    12|11   7|6       0|
+-------------------------------------------------+
|   0   | shamt |  rs1  |  001   |  rd  | 0010011 |
+-------------------------------------------------+

SRLI

rd = (uint32_t) rs1 >> shamt

|31   25|24   20|19   15|14    12|11   7|6       0|
+-------------------------------------------------+
|   0   | shamt |  rs1  |  101   |  rd  | 0010011 |
+-------------------------------------------------+

SRAI

比較特別的是 opcode 和 funct3 都和 SRLI 一樣,
需要用 imm 的某個 bit 來判斷是哪一種。
rd = rs1 >> shamt

|31   25|24   20|19   15|14    12|11   7|6       0|
+-------------------------------------------------+
|  32   | shamt |  rs1  |  101   |  rd  | 0010011 |
+-------------------------------------------------+

實際程式

github 頁面 Tag: ITDay13

這次的問題是因為漏算了已經先左移的部分,
在跑 Test Binary Code 的 SLLI 會變成 shamt 每次都拿到 8,
修改結果如下:

int32_t INSTRUCTION_DECODER::get_imm(uint32_t end, uint32_t start)
{
	return sc_dt::sc_int<32>(instruction_value) << (31-end) >> (31 - end + start);
}

三道指令內容都很單純是位移,比較特別的是 imm 有一部份用來當 shamnt,
另外一部分用來區別 SRLISRAI

//executor.cpp
...
				case INSTRUCTION_DECODER_INTERFACE::SLLI_FN3:
					SLLI_E();
					break;
				case INSTRUCTION_DECODER_INTERFACE::SRLI_FN3://same as INSTRUCTION_DECODER_INTERFACE::SRAI_FN3
					if(instruction_decoder->get_imm(30, 30) == 0)
					{
						SRLI_E();
					}
					else
					{
						SRAI_E();
					}
					break;
...
void EXECUTOR::SLLI_E()
{
	auto rs1 = instruction_decoder->get_rs1();
	auto rd = instruction_decoder->get_rd();

	auto value = register_file->get_value_integer(rs1) << (uint32_t) instruction_decoder->get_imm(24, 20);
	register_file->set_value_integer(rd, value);
	//TODO: just for test, move these to decoder and logger in future
...
}
void EXECUTOR::SRLI_E()
{
	auto rs1 = instruction_decoder->get_rs1();
	auto rd = instruction_decoder->get_rd();

	auto value = (uint32_t) register_file->get_value_integer(rs1) >> (uint32_t) instruction_decoder->get_imm(24, 20);
	register_file->set_value_integer(rd, value);
...
}
void EXECUTOR::SRAI_E()
{
	auto rs1 = instruction_decoder->get_rs1();
	auto rd = instruction_decoder->get_rd();

	auto value = register_file->get_value_integer(rs1) >> (uint32_t) instruction_decoder->get_imm(24, 20);
	register_file->set_value_integer(rd, value);
...
}
                
//instructionDecoderInterface.h
...
		SLLI_FN3 = 0b001,
		SRLI_FN3 = 0b101,
		SRAI_FN3 = 0b101,
...

執行結果

前面的不重要就省略,從 SLTIU 給值,
配合 SLLISRLISRAI 幾道指令區別不同運算結果,
最後的數值以 Signed Integer 表示。

$ make run
./simulator

        SystemC 2.3.3-Accellera --- Sep 17 2021 22:09:07
        Copyright (c) 1996-2018 by all Contributors,
        ALL RIGHTS RESERVED
...
SLTIU
rs1: 2
rd: 2
value: 1
SLLI
rs1: 2
rd: 3
value: -2147483648
SRLI
rs1: 3
rd: 4
value: 1073741824
SRAI
rs1: 3
rd: 5
value: -1073741824

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

尚未有邦友留言

立即登入留言