第一道指令先从 Immediat 系列开始吧
指令系列会依照时间安排增减速度,
一方面是因为上一篇留下的技术债要想办法 Refactor,
另一方面是要留时间提前准备接下来的内容。
根据 Andes RISC-V Conf’21 的资讯,
Tiny ONNC build 出来的执行档可以在 Bare Metal 环境下执行,
这段时间会对相关的 Softwere Stack 进行研究,
预计会用 ONNC 或者 tiny ONNC 来为这篇系列文收尾。
期待这次的成果,一定是大拇指的拉!
指令格式如下:
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| imm | rs1 | funct3 | rd | pocode |
+-------------------------------------------+
ADDI 会把 rs1 + imm 存到 rd 里面。
运算时遇到 Overflow 不进行任何处理,
直接把最低的 32 bit 放到 rd 内。
|31 20|19 15|14 12|11 7|6 0|
+-------------------------------------------+
| imm | rs1 | 000 | rd | 0010011 |
+-------------------------------------------+
没错, 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_decoder
和 register_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 的理由和之前一样,不再赘述。
1.意义 (1)jQuery = ƒ (函式库) console.log(typeof jQuery...
component组件之间相互发送数据,传递数据的方式是使用 props。Props代表属性,用於将...
当要开发一个大型专案的时候,往往会落入一个错误的认知,就是认为投入的人数越多,开发越快。 软件开发需...
前言 本篇文章介绍 SwiftUI 的元件—GeometryReader。 实作 打开一个新专案 建...
前言 Hi, 我是鱼板伯爵今天要教如何利用Theme结合Bloc来切换主题配色,教学内容只会撷取片段...