---
# System prepended metadata

title: arch2025-Homework3

---

# Assignment3: MyCPU
contributed by <[RayYang421](https://github.com/RayYang421/ca2025-mycpu)>



## 1-single-cycle
![image](https://hackmd.io/_uploads/B1WCDljebl.png)

### Test Result
```
[info] Run completed in 45 seconds, 824 milliseconds.
[info] Total number of tests run: 9
[info] Suites: completed 7, aborted 0
[info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 56 s, completed Nov 27, 2025 9:00:26 AM
```

Pass : 41 instructions
![image](https://hackmd.io/_uploads/rkWL13CZbe.png)

### Phase 1: Instruction Decode

**B-type**
| Immediate Bits | Instruction Bits | Description                 |
| -------------- | ---------------- | --------------------------- |
| imm[12]        | inst[31]         | Sign bit                    |
| imm[11]        | inst[7]          | Middle bit of branch offset |
| imm[10:5]      | inst[30:25]      | Upper bits of branch offset |
| imm[4:1]       | inst[11:8]       | Lower bits of branch offset |
| imm[0]         | 0                | Always 0 (alignment)        |

**S-type**
| Immediate Bits | Instruction Bits | Description  |
| -------------- | ---------------- | ------------ |
| imm[11:5]      | inst[31:25]      | Upper 7 bits |
| imm[4:0]       | inst[11:7]       | Lower 5 bits |

**J-type**
| Immediate Bits | Instruction Bits | Description                |
| -------------- | ---------------- | -------------------------- |
| imm[20]        | inst[31]         | Sign bit                   |
| imm[19:12]     | inst[19:12]      | Middle 8 bits              |
| imm[11]        | inst[20]         | Isolated bit in the offset |
| imm[10:1]      | inst[30:21]      | Upper-middle bits          |
| imm[0]         | 0                | Always 0 (alignment)       |

ref: 
![image](https://hackmd.io/_uploads/SJtHF5YgZe.png)

---

### Control Signal
**WriteBack data source selection**
| Category                 | Write-back Source                  | Operation                                          |
| ------------------------ | ---------------------------------- | -------------------------------------------------- |
| **R-type**               | **ALUResult**                      | Write the ALU computation result to `rd`           |
| **I-type (arith/shift)** | **ALUResult**                      | Write ALU result (rs1 + imm, logic, shift) to `rd` |
| **Load**                 | **Memory**                         | Write loaded data (from memory) to `rd`            |
| **LUI**                  | **ALUResult** (bypassed immediate) | Write upper immediate value to `rd`                |
| **AUIPC**                | **ALUResult**                      | Write `PC + imm` to `rd`                           |
| **JAL**                  | **NextInstructionAddress**         | Write `PC + 4` to `rd` (return address)            |
| **JALR**                 | **NextInstructionAddress**         | Write `PC + 4` to `rd` (return address)            |
| **Store**                | **(no write-back)**                | Store instructions do **not** write to a register  |
| **Branch**               | **(no write-back)**                | Branch instructions do **not** write to a register |

```=
  // TODO: Determine when to write back from Memory
  when(isLoad) {
    wbSource := RegWriteSource.Memory
  }
  // TODO: Determine when to write back PC+4
  .elsewhen(isJal || isJalr) {
    wbSource := RegWriteSource.NextInstructionAddress
  }
```

**ALU operand 1 selection**
The following is talk about  
| Category                 | Operation                                               |
| ------------------------ | ------------------------------------------------------- |
| **R-type**               | `op1 = rs1`, performs arithmetic/logic/shift with `rs2` |
| **I-type (arith/shift)** | `op1 = rs1`, performs arithmetic/logic/shift with `imm` |
| **Load**                 | `op1 = rs1`, computes address: `rs1 + imm`              |
| **Store**                | `op1 = rs1`, computes address: `rs1 + imm`              |
| **Branch (comparison)**  | `op1 = rs1`, compares with `rs2` (==, !=, <, >=)        |
| **JALR**                 | `op1 = rs1`, computes jump target: `rs1 + imm`          |

And we need 
| Category                        | op1 Source   |
| ------------------------------- | ------------ |
| **Branch (target calculation)** | op1 = PC     |
| **JAL**                         | op1 = PC     |
| **AUIPC**                       | op1 = PC     |
| **LUI**                         | ALU not used |

```=
  when(isBranch || isAuipc || isJal) {
    aluOp1Sel := ALUOp1Source.InstructionAddress
  }
```

**ALU operand 2 selection**
| Category                  | Operation                                               |
| ------------------------- | ------------------------------------------------------- |
| **I-type (arith/shift)**  | `op2 = imm`, used with `rs1` for arithmetic/logic/shift |
| **Load**                  | `op2 = imm`, address = `rs1 + imm`                      |
| **Store**                 | `op2 = imm`, address = `rs1 + imm`                      |
| **Branch (target calc.)** | `op2 = imm`, branch target = `PC + imm`                 |
| **JAL**                   | `op2 = imm`, jump target = `PC + imm`                   |
| **JALR**                  | `op2 = imm`, jump target = `rs1 + imm`                  |
| **AUIPC**                 | `op2 = imm`, result = `PC + imm`                        |
```=
  // TODO: Determine when to use immediate as second operand
  // Hint: Most instruction types except R-type use immediate
  when(needsImmediate) {
    aluOp2Sel := ALUOp2Source.Immediate
  }
```

### Phase 2: ALU Control (Exercise 3)

| ALU Functions | Operation          |
| ------------- | ------------------ |
| Arithmetic    | add, sub, slt,sltu |
| Logic         | and, or, xor       |
| Shift         | sll, sra, srl      |


### Phase 3: Execution Stage (Exercises 4–5)
### Branch Comparison Logic
**Unsigned Comparison**
```
InstructionsTypeB.beq -> (io.reg1_data === io.reg2_data)
InstructionsTypeB.bne -> (io.reg1_data =/= io.reg2_data)

// Unsigned comparison
InstructionsTypeB.bltu -> (io.reg1_data < io.reg2_data)
InstructionsTypeB.bgeu -> (io.reg1_data >= io.reg2_data)
```

**Signed Comparison**
```
InstructionsTypeB.blt -> (io.reg1_data.asSINT < io.reg2_data.asSINT)
InstructionsTypeB.bge -> (io.reg1_data.asSINT >= io.reg2_data.asSINT)
```
* `.asSInt` converts a UInt to an SInt by reinterpreting the same bit pattern

### Jump Target Address Calculation
* Branch = PC + immediate (PC-relative)
* JAL = PC + immediate (PC-relative)
* JALR = (rs1 + immediate) & ~1
    * ~1 is bitwise not 

### Phase 4: Memory Access (Exercises 6–7)
### Load Data Extension - Sign and Zero Extension
* Sign extension: Replicate the sign bit (MSB) to fill upper bits
    * Example: LB loads 0xFF → sign-extended to 0xFFFFFFFF 
* Zero extension: Fill upper bits with zeros
    * Example: LBU loads 0xFF → zero-extended to 0x000000FF

| Instruction | Size Loaded / Stored | Signed?  | Extension (for Load)   | Description                     |
| ----------- | -------------------- | -------- | ---------------------- | ------------------------------- |
| **LB**      | 8 bits               | Signed   | Sign-extend to 32 bits | Load a byte and sign-extend     |
| **LBU**     | 8 bits               | Unsigned | Zero-extend to 32 bits | Load a byte and zero-extend     |
| **LH**      | 16 bits              | Signed   | Sign-extend to 32 bits | Load a halfword and sign-extend |
| **LHU**     | 16 bits              | Unsigned | Zero-extend to 32 bits | Load a halfword and zero-extend |
| **LW**      | 32 bits              | N/A      | No extension needed    | Load a full word                |


### Store Data Alignment - Byte Strobes & Shifting
* Byte strobes: Control which bytes in a 32-bit word are written
* Data shifting: Align data to correct byte position in 32-bit word

| Instruction | Size Stored | Description                               |
| ----------- | ----------- | ----------------------------------------- |
| **SB**      | 8 bits      | Store lowest 8 bits (byte) to memory      |
| **SH**      | 16 bits     | Store lowest 16 bits (halfword) to memory |
| **SW**      | 32 bits     | Store full 32-bit word to memory          |

The index is not a fixed value; it is determined by the lower two bits of the memory address and changes for each store instruction depending on the address.






## 2-mmio-trap
### Test
```
[info] Run completed in 43 seconds, 112 milliseconds.
[info] Total number of tests run: 9
[info] Suites: completed 8, aborted 0
[info] Tests: succeeded 9, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.
[success] Total time: 47 s, completed Nov 28, 2025 7:12:03 AM
```
**make demo**
![image](https://hackmd.io/_uploads/BJFsmoCZWx.png)


## 3-pipeline
### Test
```
[info] Run completed in 2 minutes, 26 seconds.
[info] Total number of tests run: 29
[info] Suites: completed 3, aborted 0
[info] Tests: succeeded 27, failed 2, canceled 0, ignored 0, pending 0
[info] *** 2 TESTS FAILED ***
[error] Failed tests:
[error]         riscv.PipelineProgramTest
[error] (Test / test) sbt.TestsFailedException: Tests unsuccessful
[error] Total time: 151 s (02:31), completed Nov 28, 2025 9:54:01 AM
make: *** [Makefile:8: test] Error 1
```