# Lab1: RV32I Simulator
###### tags: `RISC-V`
This is a GCD (Greatest Common Divisor) program with Euclidean Algorithm.
```nasm=
.data
num1: .word 120 # number 1 (u)
num2: .word 78 # number 2 (v)
str1: .string "\n"
nums: .word 30 10
.text
main:
lw s0, num1 # u
lw s1, num2 # v
# check u or v is 0
beqz s1, print
beqz s0, assign
# use Euclidean algorithm
loop:
mv s2, s1
rem s1, s0, s1
mv s0, s2
bnez s1, loop
j print
assign:
mv s0, s1
j print
print:
addi a7, x0, 1 # print_int ecall
add a0, s0, x0 # integer
ecall
exit:
```
This program use Euclidean algorithm to calculate GCD. In each loop, the program will modulo two numbers and write new values to original values. Until one of values becomes 0, the program will print the result and terminate.
## Pipeline
Pipeline has 5 stages, IF, ID, EX, MEM and WB. We use pipeline to improve the efficiency of program.
- IF (Instruction Fetch)
- Fetch the instruction from the Instruction Memory.
- It's depends on the PC (program counter) which is a register can record the address of the instruction being executed at the current time.
- PC will be change if some instructions happen like `beq`, `jal`, `j` etc.
- ID (Instruction Decode)
- Registers fetch and instruction decode.
- It also has some control signals which can decide the register behavior. like write data, clear bit etc.
- EX (Execution)
- This stage will execute the instruction according to the opcode.
- In branch instruction will check the result is true/false to set the flag and change the PC.
- MEM (Mem structure)
- Write/Read data with the data memory.
- It's decide the address of the memory according to opcode.
- It has two signals `MemRead` and `MemWrite` which can distinguish between write and read operation.
- WB (Write Back)
- Write ALU output back to the register file.
- it has a signal `MemtoReg` which decide whether write data back to the register file.
## Description
- `lw s1, num2` and `beqz s1, print`
- RAW (read after write) can cause data hazard without forwarding
- `lw` will get a value from memory to `s1` on DM, but `beqz` want to read `s1` on ID. Thus, using a `nop` to avoid the data hazard, and forwarding the DM to the register.

- the value from memory will be written into register on the WB stage.

- `bnez s1, loop`
- After the ALU, it knew the branch condition is met. The program needed to flush last two instructions, and refetched the instruction.
- Before jump, the result of ALU will send to a MUX in order to change the PC (program counter). Meanwhile, the clear bit in IFID and IDEX will be set.

- After jump

- `j print`
- Like the above condition. The program will jump to another location. Thus, it needed to flush the last two instructions, too.
