# Lab1:RV32I Simulator contributed by <[`Evelyn`](https://github.com/tako861225/power-of-two)> ###### tags: `RISC-V` ## Power of Two This problem is based on [LeetCode 231](https://leetcode.com/problems/power-of-two/). Given an integers, return `true` if the number is power of two that can represent to $2^{k}$ .Otherwise, return `false` ### C code ```clike= #include<stdio.h> bool isPowerOfTwo(int n){ while(n){ if (n==1) return true; if(n%2)return false; n/=2; } return false; } ``` ### Assembly code ```asm= .data argument: .word 2 str1: .string "ture" str2: .string "false" .text main: lw a0, argument # Load argument from static data addi sp, sp, -4 sw a0 ,0(sp) addi t2, t2, 1 # t2 = 1 jal ra, loop # Jump-and-link to the 'loop' label lw a0,0(sp) addi sp,sp, 4 jal ra, print # Exit program li a7, 10 ecall loop: beq a0, t2, true # if n==1 return true andi t3, a0, 1 # t3 = n % 2 bne t3, zero, false # if t3!= 0 return false srli a0, a0, 1 # shift right bne a0, zero, loop # while(n) beq a0, zero, false #if n = 0 return false true: addi a1, a1 , 1 # result ret false: addi a1, a1 , 0 ret print: mv t0, a0 #t0 = n mv a0,t0 li a7,1 ecall mv t1, a1 #result beq t1, zero, pf la a0,str1 li a7,4 ecall ret pf: la a0,str2 li a7,4 ecall ret ``` ### Pseudo instruction ```pse= 00000000 <main>: 0: 10000517 auipc x10 0x10000 4: 00052503 lw x10 0 x10 8: ffc10113 addi x2 x2 -4 c: 00a12023 sw x10 0 x2 10: 00138393 addi x7 x7 1 14: 018000ef jal x1 24 <loop> 18: 00012503 lw x10 0 x2 1c: 00410113 addi x2 x2 4 20: 034000ef jal x1 52 <print> 24: 00a00893 addi x17 x0 10 28: 00000073 ecall 0000002c <loop>: 2c: 00750c63 beq x10 x7 24 <true> 30: 00157e13 andi x28 x10 1 34: 000e1c63 bne x28 x0 24 <false> 38: 00155513 srli x10 x10 1 3c: fe0518e3 bne x10 x0 -16 <loop> 40: 00050663 beq x10 x0 12 <false> 00000044 <true>: 44: 00158593 addi x11 x11 1 48: 00008067 jalr x0 x1 0 0000004c <false>: 4c: 00058593 addi x11 x11 0 50: 00008067 jalr x0 x1 0 00000054 <print>: 54: 00050293 addi x5 x10 0 58: 00028513 addi x10 x5 0 5c: 00100893 addi x17 x0 1 60: 00000073 ecall 64: 00058313 addi x6 x11 0 68: 00030c63 beq x6 x0 24 <pf> 6c: 10000517 auipc x10 0x10000 70: f9850513 addi x10 x10 -104 74: 00400893 addi x17 x0 4 78: 00000073 ecall 7c: 00008067 jalr x0 x1 0 00000080 <pf>: 80: 10000517 auipc x10 0x10000 84: f8950513 addi x10 x10 -119 88: 00400893 addi x17 x0 4 8c: 00000073 ecall 90: 00008067 jalr x0 x1 0 ``` ### 5-stage pipelined processor ![](https://i.imgur.com/SJLP1WZ.png) There are five stage in Ripe: ![](https://i.imgur.com/gqolxKw.png) |abbreviation|work| |:---:|:---:| |IF|Instruction Fetch| |ID|Instruction Decode & Register Read| |EX|Execution or Address Calculation| |MEM|Data Memory Access| |WB|Write Back (to register)| Take `auipc x10 0x10000` as an example. ## IF ![](https://i.imgur.com/jHe6dqv.png) In IF stage,Program Counter(PC) will load the first address 0x000000000 to Instr. memory,the instr. output will be 0x10000517.Simultaneously,PC will load the next address 0x000000000+4. ## ID ![](https://i.imgur.com/f60FFmC.png) Next, decode the instruction `0x10000517` from IF which can be spilt into : opencode:auipc,wr idx: 0x0a ,imm. : 0x10000000. ## EX ![](https://i.imgur.com/K2MwSem.png) ALU result will be register plus immediate value 0x10000000 = 0x00000000+0x10000000 ## MEM ![](https://i.imgur.com/1mcQdrH.png) Load address from the result of ALU `0x10000000` ,then the value will be `0x00000010` ## WB ![](https://i.imgur.com/BpQSUPs.png) Write ALU result `0x10000000` to destination register `0x0a`