---
# System prepended metadata

title: Quiz3 of Computer Architecture (2024 Fall) 詳解

---

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