# 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`