iT邦幫忙

2021 iThome 鐵人賽

DAY 2
1
Software Development

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

RISC-V: ECALL/EBREAK 指令

  • 分享至 

  • xImage
  •  

進到了系統指令的環節,
一樣先參考 RISC-V-TLMexactstep 的做法,
恩...一言難盡。

先從指令介紹開始吧!

I-type

指令格式如下:

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

ECALL

用來執行需要更高權限才能執行的功能,
例如作業系統的 system call,
在目前參考的指令及版本有提到原先是叫 SCALL,
但因為需要支援更多的使用情境,改成 ECALL。

|31     20|19   15|14    12|11   7|6       0|
+-------------------------------------------+
|    0    | 00000 |  000  | 00000 | 1110011 |
+-------------------------------------------+

EBREAK

用來中斷程式的運作,
讓系統可以把使用權轉交給 Debugger。

其實 Debugger 的 Break Point 就是用這個指令實現的,
只是偷偷把指定位置的指令換掉了不跟使用者講而已!

和 ECALL 一樣,
在目前參考的指令及版本有提到原先是叫 SBREAK,
但因為需要支援更多的使用情境,改成 EBREAK。

|31     20|19   15|14    12|11   7|6       0|
+-------------------------------------------+
|    1    | 00000 |  000  | 00000 | 1110011 |
+-------------------------------------------+

實際程式

github 頁面 Tag: ITDay21

ECALL 在 RISC-V-TLM 的做法就是直接結束模擬。
exactstep 實作上把 ECALL 接起來自己做掉,
並沒有跳到某個位置執行軟體註冊的 Handler 再跳回來的過程。

根據規格書對 Bare metal hardware platforms 的描述:
The hardware platform defines an execution environment
that begins at power-on reset.",
exactstep 的做法應該是符合規範的。
但還是比較喜歡讓 Software 有彈性的做法,
目前先依照 RISC-V-TLM 的行為實作,
日後再擴充。

EBREAK 則是會發生 Trap,目前沒有實作相關機制來處理,
等之後把 Interrupt 和 CSR 的部分做出來再回來拯救這個指令吧!

//instructionDecoderInterface.h
...
		SYSTEM_OP = 0b1110011,
...
	enum Func12 {
		ECALL_FN12 = 0b0,
		EBREAK_FN12 = 0b1,
	};

...
//executor.cpp
...
		case INSTRUCTION_DECODER_INTERFACE::SYSTEM_OP:
			system_dispatch();
			break;
...
void EXECUTOR::system_dispatch()
{
	switch (instruction_decoder->get_func12()) {
		case INSTRUCTION_DECODER_INTERFACE::ECALL_FN12:
			ECALL_E();
			break;
		case INSTRUCTION_DECODER_INTERFACE::EBREAK_FN12:
			EBREAK_E();
			break;
		default:
			std::cout << "INVALID: Func3 in MISC_MEM_OP :" << instruction_decoder->get_func3() << std::endl;
			break;
	}
}
...
void EXECUTOR::ECALL_E()
{
	sc_core::sc_stop();
}
void EXECUTOR::EBREAK_E()
{
	sc_core::sc_stop();
}

新增了一個 system 專用的 get_func12

//instructionDecoder.cpp
...
uint32_t INSTRUCTION_DECODER::get_func12()
{
	return instruction_value.range(31, 20);
}
...

加了一段測試程式,讓最後一道指令 ECALL 結束 Simulator 的運作。
也因為這樣,Cpu 裡面的 Cycle Limit 可以移除了,
之後等做出 Exception 系列功能,
就可以用 Illegal Instruction Exceptions 取代。

//memory.cpp
...
		0b000000000000'00000'000'00000'1110011, //ECALL
...
//cpu.cpp
...
void CPU::cpu_thread(void)
{
	while(true) {
		step();
		wait(delay);
	}
}
...

上一篇
RISC-V: Memory Fence 指令
下一篇
RISC-V: R-type 算術指令
系列文
猴子都寫得出來的 RISC-V CPU Emulator31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言