# Quiz3 of Computer Architecture (2024 Fall) 詳解 ## Problem `A` 先備知識: 1. enum A 大題的目標是做出一個 RISC-V 指令的模擬器 而且要能做到 fetch, decode, and execute 1. 這部分在?? ```c enum { /* I-type integer computation or integer register-immediate */ INTEGER_COMP_RI = 0x13, LUI = #A01 /* Your answer here */, AUIPC = #A02 /* Your answer here */, /* ECALL and EBREAK */ ECALL = 0x73, }; ``` 這部分很顯然在考對 I-type instruction 的了解(可以看白算盤 2.10) `LUI` 是 Load upper immediate 的縮寫 `auipc` is used for PC-relative memory addressing 2. 這部分在考大家是否了解 RiSC-V 指令的結構 ```c enum { RD_SHIFT = #A03 /* Your answer here */, RS1_SHIFT = #A04 /* Your answer here */, RS2_SHIFT = 20, FUNCT3_SHIFT = #A05 /* Your answer here */, FUNCT7_SHIFT = 25 }; ``` 這部分要從 `cpu_decode` 來回推 ```c void cpu_decode(uint32_t raw, insn_t *inst) { uint8_t opcode = raw & OPCODE_MASK; uint8_t rd = (raw >> RD_SHIFT) & REG_ADDR_MASK; uint8_t rs1 = (raw >> RS1_SHIFT) & REG_ADDR_MASK; uint8_t rs2 = (raw >> RS2_SHIFT) & REG_ADDR_MASK; uint8_t funct3 = (raw >> FUNCT3_SHIFT) & FUNCT3_MASK; uint8_t funct7 = (raw >> FUNCT7_SHIFT) & FUNCT7_MASK; inst->opcode = opcode; inst->rd = rd, inst->rs1 = rs1, inst->rs2 = rs2; inst->funct3 = funct3; inst->funct7 = funct7; } ``` 3. 這部分(應該)是涉及到 imm 的讀取 ```c static inline int32_t u_imm(uint32_t raw) { /* imm[20:0] = inst[31:12] */ return ((int32_t) raw & 0xFFFFF000); } ``` 4. 這部分在???? ```c void cpu_execute(cpu_t *cpu, uint32_t raw) { cpu_decode(raw, &inst); cpu->regs[0] = 0; switch (inst.opcode) { case INTEGER_COMP_RI: { int32_t imm = i_imm(raw); switch (inst.funct3) { case ADDI: cpu->regs[inst.rd] = cpu->regs[inst.rs1] + imm; break; default: fatal("Unknown FUNCT3 for INTEGER_COMP_RI"); } break; } case LUI: { int32_t imm = u_imm(raw); cpu->regs[inst.rd] = imm; break; } case AUIPC: { int32_t imm = u_imm(raw); cpu->regs[inst.rd] = (cpu->pc + (#A07 /* Your answer here */)) + imm; break; } case ECALL: if (raw == 0x100073) break; /* EBREAK */ ecall_handler(cpu); break; default: fatal("Illegal Instruction 0x%x\n", inst.opcode); } } ``` 5. 而這部分又是在? ```c int main(int argc, char *argv[]) { if (argc < 2) { printf("Usage: %s [filename]\n", argv[0]); exit(-1); } const char *filename = argv[1]; FILE *file = fopen(filename, "rb"); if (!file) { printf("Failed to open %s\n", filename); exit(-1); } fseek(file, 0L, SEEK_END); size_t code_size = ftell(file); rewind(file); uint8_t *code = malloc(code_size); fread(code, sizeof(uint8_t), code_size, file); fclose(file); cpu_t *cpu = cpu_new(code, code_size); while (1) { uint32_t raw = cpu_fetch(cpu); cpu->pc += #A08 /* Your answer here */; if (cpu->pc > code_size) break; cpu_execute(cpu, raw); if (!cpu->pc) break; } cpu_free(cpu); return 0; } ``` 這應該是整大題最簡單的部分 `cpu->pc` 是 要執行下一個指令就要加4 ## Problem `B`