RISC-V: ECALL/EBREAK 指令

进到了系统指令的环节,
一样先参考 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);
	}
}
...

<<:  [第二十只羊] 迷雾森林舞会XIV 进房间聊天 hotwire + stimulus 起步走

>>:  [Day20] 第二十章 - 修改登入画面 (使用bootstrap 4.6的范例)

day17 : kafka服务应用 on K8S (上)

kafka是一套与昨天的NATS类似的分布式MQ系统,会用这两套也不是想要做差异比较,单纯只是有多一...

[Day02] TS: 泛型(Generics)能干嘛?

「泛型(Generics)」是 TypeScript 中很常会使用到的功能,泛型的概念简单来说,就是...

【C#】物件导向的三大特性

今天我们来看到~物件导向的三大特性~ 什麽是物件呢~ 物件是指类别的实例。 例如,有一个类别是Car...

除此之外,还有什麽吗?

这一天原本想贴一贴学员心得,所以完全没有准备什麽内容。 学员毕业心得,没有强制要每个离开的学员写。...

Day 03:转吧转吧七彩霓虹灯之 p10k

更新 我把从第一天到现在每天的 Home 目录都放上 GitHub 了,README.md 里面有...