# Assignment1: RISC-V Assembly and Instruction Pipeline
**LeetCode: 326.Power of Three**
> Given an integer n, return true if it is a power of three. Otherwise, return false.
>
> Example 1:
> Input: n = 27
> Output: true
>
> Example 2:
> Input: n = 0
> Output: false
>
> Example 3:
> Input: n = 9
> Output: true
>
> Example 4:
> Input: n = 45
> Output: false
---
**C code:**
```c=
#include <stdio.h>
#include <stdbool.h>
bool isPowerOfThree(int n){
if(n==0)
return false;
if(n==1)
return true;
while(n%3 == 0){
if(n == 3)
return true;
n=n/3;
}
return false;
}
int main() {
int n = 27;
bool x = isPowerOfThree(n);
printf("%s\n", x ? "true" : "false");
return 0;
}
```
---
**Assembly code:**
```assembly=
.data
argument: .word 27
str1: .string "true"
str2: .string "false"
.text
main:
lw a0, argument # load the argument from static data
jal isPowerOfThree # Jump to 'isPowerOfThree' and link
li a7, 10 # exit program
ecall
isPowerOfThree:
addi t0, x0, 1 # t0 = 1
beq a0, x0, else # if a0 == 0, go to 'else'
beq a0, t0, then # if a0 == 1, go to 'then'
addi t0, x0, 3 # t0 = 3
rem t1, a0, t0 # t1 = a0 % 3
bne t1, x0, else # if t1 != 0, go to 'else'
j loop # jump to 'loop'
loop:
beq a0, t0, then # if a0 == 3, go to 'then'
div a0, a0, t0 # a0 = a0 / t0
rem t1, a0, t0 # t1 = a0 % 3
bne t1, x0, else # if t1 != 0, go to 'else'
j loop # jump to 'loop'
then:
la a0, str1 # load string
addi a7, x0, 4 # print string
ecall
jr ra # go back to main
else:
la a0, str2 # load string
addi a7, x0, 4 # print string
ecall
jr ra # go back to main
```
---
**Five-stage pipeline in RISC-V: IF-ID-EX-MEM-WB**
> IF = Instruction fetch, ID = Instruction decode, EX = Execute, MEM = Memory access, WB = Register write back
There are multiple processer models which can be selected in Ripes, the following image shows RISC-V 5-Stage Processor model.

Here we discuss the pipeline process of the example above in details.
# IF:

PC passes 0x00000000 to Instr. memory and then will be equal to 0x00000004 or jump address.
# ID:

Decode the instruction. Store "rd:0x0a" in IDEX and pass "opcode:AUIPC" to Imm.
Note: "auipc" is U-type.

# EX:

The output of ALU is 0x10000000.
# MEM:

Pass the value 0x10000000 to MEM/WB.
# WB:

The value 0x10000000 will be passed to a0 register.
---
**Memory update**
Before the instruction discussed above is performed, the value in a0 register is 0x00000000.

After it is performed, the value in a0 register changes to 0x10000000.

Note: The image below shows the address of stored data in memory.

---