# ARCH2025: Discussion on Nov. 18 GitHub repository: [dozingmoon/ca2025-mycpu](https://github.com/dozingmoon/ca2025-mycpu) --- ### From [2025-11-18 CA](https://hackmd.io/QERe1qMbSra0UqdfEPUhMw?view#dozingmoon): > Take `addi` for example. Show details in MyCPU > 1. Fetch intructions from InstructionMemory > 2. Decode: `addi` is I-type > 3. Execute (no ~~WB~~**[memory-write needed]**) ## Fetch instructions from Instruction Memory CPU fetches instruction `0x28c28293 addi x5, x5, 652` from memory, which is initiated by `TestTopModule.scala` ```scala //TestTopModule.scala mem.io.instruction_address := cpu.io.instruction_address cpu.io.instruction := mem.io.instruction ``` ```scala //CPU.scala io.instruction_address := inst_fetch.io.instruction_address inst_fetch.io.rom_instruction := io.instruction ``` ```scala // InstructonFetch.scala io.instruction_address := pc io.id_instruction := Mux(io.instruction_valid, io.rom_instruction, InstructionsNop.nop) ``` ![image](https://hackmd.io/_uploads/r1xcfYubbg.png) ## Decode: Check which type `addi` is We retrieve the `opcode` of `addi` `('b0010011)`, and lookup the instruction types to extend the immediate field of I-type instructions `(=0x284)`. ```scala // Execute.scala // ... object InstructionTypes { val L = "b0000011".U val I = "b0010011".U val S = "b0100011".U val RM = "b0110011".U val B = "b1100011".U } class InstructionDecode extends Module{ //... val opcode = io.instruction(6, 0) val funct3 = io.instruction(14, 12) val funct7 = io.instruction(31, 25) val rd = io.instruction(11, 7) val rs1 = io.instruction(19, 15) val rs2 = io.instruction(24, 20) io.ex_immediate := MuxLookup(opcode, Cat(Fill(20, io.instruction(31)), io.instruction(31, 20)) )( IndexedSeq( InstructionTypes.I -> Cat(Fill(21, io.instruction(31)), io.instruction(30, 20)), //... ) ) } ``` ![image](https://hackmd.io/_uploads/rJqCfYdW-g.png) ## Execute: What operations are done? `ALU` will receive the control signal decoded from `opcode`, `funct3` and `funct7` by`ALUControl`, and `Execute` will select the operand source. `ALU` will enter the switch case, matching `ALUFunctions.add`, and do add to `op1` and `op2`. ```scala // Execute.scala // ... alu_ctrl.io.opcode := opcode alu_ctrl.io.funct3 := funct3 alu_ctrl.io.funct7 := funct7 alu.io.func := alu_ctrl.io.alu_funct val reg1_data = // forwarding... alu.io.op1 := Mux( io.aluop1_source === ALUOp1Source.InstructionAddress, io.instruction_address, reg1_data ) val reg2_data = // forwarding... alu.io.op2 := Mux( io.aluop2_source === ALUOp2Source.Immediate, io.immediate, reg2_data ) // ... ``` ```scala // ALU.scala // ... io.result := 0.U switch(io.func) { is(ALUFunctions.add) { io.result := io.op1 + io.op2 } // ... ``` ![image](https://hackmd.io/_uploads/B1yg7tO-We.png) ## Memory: No memory access needed ![image](https://hackmd.io/_uploads/BkeZmFd--g.png) ## Write-Back ![image](https://hackmd.io/_uploads/rkGf7tOWWx.png)