今天一样是简单的 SLL、SRL、SRA 指令实作,
再一样为了 Code Stream Logger 做准备,
另外再加码一个 run 过这份程序的人一定会发现的 Bug 吧。
指令格式如下:
|31 25|24 20|19 15|14 12|11 7|6 0|
+---------------------------------------------------+
| func7 | rs2 | rs1 | funct3 | rd | opcode |
+---------------------------------------------------+
rd = rs1 << rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 001 | rd | 0110011 |
+-------------------------------------------------------+
rd = (uint_32)rs1 >> rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0000000 | rs2 | rs1 | 101 | rd | 0110011 |
+-------------------------------------------------------+
rd = rs1 >> rs2
|31 25|24 20|19 15|14 12|11 7|6 0|
+-------------------------------------------------------+
| 0100000 | rs2 | rs1 | 101 | rd | 0110011 |
+-------------------------------------------------------+
github 页面 Tag: ITDay25
这次的 Bug 是几天前做 Exception 留下来的,
当时把 Cpu 的 this
放进 shared_ptr ,
又因为 Cpu 在 main
结束的时候会解构,
会有解构两次造成 crash 的情况,
但是当时想到两个解法,其中一个是用 Raw Pointer ,
另外一个是在 Cpu 内放一个 shared_ptr,
都不是很漂亮,这个 Bug 又不影响运作过程就没立刻动手。
虽然另外指定一个什麽事都不做的 Deleter 也没比 Raw Pointer 好到哪去,
但是不用改使用介面的情况下,是最好的选择了,
至少这样做在写 Executer 的 Unit Test 可以直接用 shared_ptr。
//cpu.cpp
...
executor->set_cpu(std::shared_ptr<CPU_INTERFACE>(this, [](CPU *p){}));
...
这次正式的把 Decoder 从 Executor 移到 Instruction Decoder 了,
把程序复制贴上再取代真的有够无聊,
之後找找看有没有 vim 的功能可以加速这个过程。
改到心很累, Function Name 的部分就之後再改吧,
到时候 Refactor 预计 99% 都会删掉改写。
//executor.cpp
...
void EXECUTOR::command_dispatch()
{
switch (instruction_decoder->get_instruction()) {
case INSTRUCTION_DECODER_INTERFACE::ADDI_INSTRUCTION_ENUM:
ADDI_E();
break;
case INSTRUCTION_DECODER_INTERFACE::ANDI_INSTRUCTION_ENUM:
ANDI_E();
break;
...
//instructionDecoder.cpp
...
INSTRUCTION_DECODER_INTERFACE::Instruction INSTRUCTION_DECODER::get_instruction()
{
return cmmand_dispatch();
}
INSTRUCTION_DECODER_INTERFACE::Instruction INSTRUCTION_DECODER::cmmand_dispatch()
{
switch (get_opcode()) {
case INSTRUCTION_DECODER_INTERFACE::IMM_OP:
return imm_dispatch();
case INSTRUCTION_DECODER_INTERFACE::LUI_OP:
return LUI_INSTRUCTION_ENUM;
...
指令实作的地方把 instruction_name_map
里的注解取消了,
其他部分大家都很熟就不多说,照着贴:
//instructionDecoderInterface.h
...
SLL_FN3 = 0b001,
SRL_FN3 = 0b101,
SRA_FN3 = 0b101,
...
SLL_FN7 = 0b0000000,
SRL_FN7 = 0b0000000,
SRA_FN7 = 0b0100000,
...
//executor.cpp
...
case INSTRUCTION_DECODER_INTERFACE::SLL_FN3:
SLL_E();
//do not check FN7 for readibility, refactor in future
break;
case INSTRUCTION_DECODER_INTERFACE::SRL_FN3:
switch (instruction_decoder->get_func7()) {
case INSTRUCTION_DECODER_INTERFACE::SRL_FN7:
SRL_E();
break;
case INSTRUCTION_DECODER_INTERFACE::SRA_FN7:
SRA_E();
break;
default:
std::cout << "INVALID: Func7 in REG_OP :" << instruction_decoder->get_func3() << std::endl;
break;
}
break;
...
void EXECUTOR::SLL_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = register_file->get_value_integer(rs1) << register_file->get_value_integer(rs2);
register_file->set_value_integer(rd, value);
}
void EXECUTOR::SRL_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = (uint32_t)register_file->get_value_integer(rs1) >> register_file->get_value_integer(rs2);
register_file->set_value_integer(rd, value);
}
void EXECUTOR::SRA_E()
{
auto rd = instruction_decoder->get_rd();
auto rs1 = instruction_decoder->get_rs1();
auto rs2 = instruction_decoder->get_rs2();
auto value = register_file->get_value_integer(rs1) >> register_file->get_value_integer(rs2);
register_file->set_value_integer(rd, value);
}
...
<<: #24 No-code 之旅 — 在 Next.js 专案中实作 API
>>: [Python] 来自己建立一个Neural Network吧
挑战目标: MockNative Camp 今天来自定义Spring ExceptionHandle...
Chatbot integration- 看图学英文 大致上的概念是要利用 Line 把图片传给 c...
Pipenv 是什麽呢? 想像一下,当你现在是个专业的工程师,身上背着十几个不同类型的专案(好啦,有...
VPC使用 昨天提到了关於VPC是什麽?以及如何简单的建立VPC XPN等的内容,那今天就来说说关於...
这近一个月的疫情高峰,相信你手头上会有很多突发的任务要处理 就像是这位 Mercedes-Benz ...