# 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. ![](https://i.imgur.com/ROgCMcD.png) Here we discuss the pipeline process of the example above in details. # IF: ![](https://i.imgur.com/vfOufnq.png) PC passes 0x00000000 to Instr. memory and then will be equal to 0x00000004 or jump address. # ID: ![](https://i.imgur.com/BTb7qN6.png) Decode the instruction. Store "rd:0x0a" in IDEX and pass "opcode:AUIPC" to Imm. Note: "auipc" is U-type. ![](https://i.imgur.com/H8cPi7J.png) # EX: ![](https://i.imgur.com/hyOGWGE.png) The output of ALU is 0x10000000. # MEM: ![](https://i.imgur.com/7QPC7pF.png) Pass the value 0x10000000 to MEM/WB. # WB: ![](https://i.imgur.com/hnyP6iJ.png) 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. ![](https://i.imgur.com/lQxESh1.png) After it is performed, the value in a0 register changes to 0x10000000. ![](https://i.imgur.com/Z9bqgaf.png) Note: The image below shows the address of stored data in memory. ![](https://i.imgur.com/QfQGUs6.png) ---