RISC-V: 作为第一道指令的聪明选择

第一道指令先从 Immediat 系列开始吧
指令系列会依照时间安排增减速度,
一方面是因为上一篇留下的技术债要想办法 Refactor,
另一方面是要留时间提前准备接下来的内容。

根据 Andes RISC-V Conf’21 的资讯,
Tiny ONNC build 出来的执行档可以在 Bare Metal 环境下执行,
这段时间会对相关的 Softwere Stack 进行研究,
预计会用 ONNC 或者 tiny ONNC 来为这篇系列文收尾。
期待这次的成果,一定是大拇指的拉!

I-type

指令格式如下:

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

ADDI

ADDI 会把 rs1 + imm 存到 rd 里面。
运算时遇到 Overflow 不进行任何处理,
直接把最低的 32 bit 放到 rd 内。

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

NOP

没错, opcode 和 funct3 都没有打错,跟 ADDI 一模一样,
从黑洞拿 0,加 0 再塞回去,官方认证的 NOP。
实做一道指令可以当两道用,赞!

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

实际程序

github 页面 Tag: ITDay10

这次新增了 EXECUTOR 来管理 CPU 的执行部分,
在 CPU 内只会呼叫 execute 让 EXECUTOR 执行 decoder 内的指令。

class EXECUTOR_INTERFACE
{
public:
	virtual void execute() = 0;
	void set_instruction_decoder(const std::shared_ptr<INSTRUCTION_DECODER_INTERFACE> &instance)
	{

		instruction_decoder = instance;
	}
	void set_register_file(const std::shared_ptr<REGISTER_INTERFACE> &instance)
	{
		register_file = instance;
	}

protected:
	std::shared_ptr<INSTRUCTION_DECODER_INTERFACE> instruction_decoder;
	std::shared_ptr<REGISTER_INTERFACE> register_file;
};

这次实作了第一道指令:ADDI
同时这道指令也是 NOP,因为 destination 写到 x0 并不会影响 x0 的值。

void EXECUTOR::execute()
{
	if(instruction_decoder->get_opcode() == INSTRUCTION_DECODER_INTERFACE::OP_IMM &&
	   instruction_decoder->get_func3() == 0b000) {
		auto rs1 = instruction_decoder->get_rs1();
		auto rd = instruction_decoder->get_rd();

		auto value = register_file->get_value_integer(rs1) + instruction_decoder->get_imm(31, 20);
		register_file->set_value_integer(rd, value);
...
	}
}

EXECUTOR 需要 memory、register file 和 instruction decoder 的配合才能工作,
这次先只把 instruction_decoderregister_file 放进去。

class EXECUTOR_INTERFACE
{
...
	std::shared_ptr<INSTRUCTION_DECODER_INTERFACE> instruction_decoder;
	std::shared_ptr<REGISTER_INTERFACE> register_file;
};

前面的文章有提到,记忆体分成 explict 和 implict 存取,
这边将 explice 存取由 EXECUTOR 处理, implict 存取则由 CPU 统一负责。
Instance 由 CPU 管理,所以在 setter 中做了对应的修改。

void CPU::set_register_file(const std::shared_ptr<REGISTER_INTERFACE> &instance)
{
...
		executor->set_register_file(register_file);
...
}

void CPU::set_instruction_decoder(const std::shared_ptr<INSTRUCTION_DECODER_INTERFACE> &instance)
{
...
		executor->set_instruction_decoder(instruction_decoder);
...
}

void CPU::set_executor(const std::shared_ptr<EXECUTOR_INTERFACE> &instance)
{
...
		executor->set_instruction_decoder(instruction_decoder);
...
		executor->set_register_file(register_file);
}

shared_ptr 和做 interface 的理由和之前一样,不再赘述。


<<:  第十九天:初探 Gradle Plugins

>>:  [Day 10] 测试串接

Day 28 (Jq)

1.意义 (1)jQuery = ƒ (函式库) console.log(typeof jQuery...

Day08 React Props-组件属性

component组件之间相互发送数据,传递数据的方式是使用 props。Props代表属性,用於将...

Day04:团队的组成

当要开发一个大型专案的时候,往往会落入一个错误的认知,就是认为投入的人数越多,开发越快。 软件开发需...

Day20:SwiftUI—GeometryReader

前言 本篇文章介绍 SwiftUI 的元件—GeometryReader。 实作 打开一个新专案 建...

[Day20] Flutter - Theme: Dark mode & Light mode(part4)

前言 Hi, 我是鱼板伯爵今天要教如何利用Theme结合Bloc来切换主题配色,教学内容只会撷取片段...