# Assignment1: RISC-V Assembly and Instruction Pipeline contributed by < [`qoo332001`](https://github.com/qoo332001) > ###### tags: `RISC-V` `computer architure 2021` ## homework [maxSubArray](https://leetcode.com/problems/maximum-subarray/submissions/) ### c code ```c #include<stdio.h> int maxSubArray(int* nums, int numsSize); int main(){ int a[9]={-2,1,-3,4,-1,2,1,-5,4}; int len1=sizeof(a)/sizeof(int); int best,i; best=maxSubArray(a,len1); printf("best= %d\n",best); } int maxSubArray(int* nums, int numsSize) { int i; int best = 0x80000000; int currsum = 0; for (i = 0; i < numsSize; i++) { if(currsum<0){ currsum =nums[i]; }else{ currsum = currsum + nums[i]; } if(best<currsum) best=currsum; } return best; } ``` ### assembly code ```c .data arr1: .word -2,1,-3,4,-1,2,1,-5,4 len1: .word 9 minint: .word 0x80000000 .text # s1 = nums base address # s2 = array1 length # s3 = min_Integer # t0=i # t1=best # t2=currsum main: la s1,arr1 #load array address to s1 lw s2,len1 #load array size to s2 lw s3,minint #load the smallest integer to s3 add a0,s1,zero #set parameter to a0 add a1,s2,zero #set parameter to a1 jal maxSubArray #and set ra=PC+4 and jump to labet "maxSubArray" li a7, 1 # set system call number:print a0 register as integer ecall addi a0,zero,1 li a7, 10 # set system call number:end program ecall maxSubArray: addi sp,sp,-20 #change stackpointer and push to stack to save main fucntion local variables sw t0,16(sp) #push t0 register sw t1,12(sp) #push t1 register sw t2,8(sp) #push t2 register sw t3,4(sp) #push t3 register sw t4,0(sp) #push t4 register add t0,zero,zero #i=0 add t1,s3,zero #best=min_Integer add t2,zero,zero #currsum=0 loop: slt t3,t0,a1 #if(i < numsSize) then t3=1 beq t3,zero,next #if(t3!=1) then break loop slli t3,t0,2 #t3=i*4 add t4,s1,t3 #t4=nums[i] address lw t4,0(t4) #t4=nums[i] slt t3,t2,zero #if(currsum<0) then t3=1 bne t3,zero,L1 #if(t3!=0) then jump L1 add t2,t2,t4 #else currsum = currsum + nums[i]; j L2 L1: add t2,t4,zero #currsum=nums[i] L2: slt t3,t1,t2 # if(best<currsum) then t3=1 beq t3,zero,L3 # if(t3==0) then jump L3 add t1,t2,zero # best=currsum L3: addi t0,t0,1 #i++ j loop next: add a0,zero,t1 #return best lw t0,16(sp) #restore the saved register t0 lw t1,12(sp) #restore the saved register t1 lw t2,8(sp) #restore the saved register t2 lw t3,4(sp) #restore the saved register t3 lw t4,0(sp) #restore the saved register t4 addi sp,sp,20 #change stackpointer to finish stack pop jr ra #jump to main functionc ``` :::warning Can you use fewer instructions? :notes: jserv ::: ## Analysis ### Pseudo Instructions Ripe translated abi code to asm code: ``` 00000000 <main>: 0: 10000497 auipc x9 0x10000 4: 00048493 addi x9 x9 0 8: 10000917 auipc x18 0x10000 c: 01c92903 lw x18 28 x18 10: 10000997 auipc x19 0x10000 14: 0189a983 lw x19 24 x19 18: 00048533 add x10 x9 x0 1c: 000905b3 add x11 x18 x0 20: 018000ef jal x1 24 <maxSubArray> 24: 00100893 addi x17 x0 1 28: 00000073 ecall 2c: 00100513 addi x10 x0 1 30: 00a00893 addi x17 x0 10 34: 00000073 ecall 00000038 <maxSubArray>: 38: fec10113 addi x2 x2 -20 3c: 00512023 sw x5 0 x2 40: 00612223 sw x6 4 x2 44: 00712423 sw x7 8 x2 48: 01c12623 sw x28 12 x2 4c: 01d12823 sw x29 16 x2 50: 000002b3 add x5 x0 x0 54: 00098333 add x6 x19 x0 58: 000003b3 add x7 x0 x0 0000005c <loop>: 5c: 00b2ae33 slt x28 x5 x11 60: 020e0c63 beq x28 x0 56 <next> 64: 00229e13 slli x28 x5 2 68: 01c48eb3 add x29 x9 x28 6c: 000eae83 lw x29 0 x29 70: 0003ae33 slt x28 x7 x0 74: 000e1663 bne x28 x0 12 <L1> 78: 01d383b3 add x7 x7 x29 7c: 0080006f jal x0 8 <L2> 00000080 <L1>: 80: 000e83b3 add x7 x29 x0 00000084 <L2>: 84: 00732e33 slt x28 x6 x7 88: 000e0463 beq x28 x0 8 <L3> 8c: 00038333 add x6 x7 x0 00000090 <L3>: 90: 00128293 addi x5 x5 1 94: fc9ff06f jal x0 -56 <loop> 00000098 <next>: 98: 00600533 add x10 x0 x6 9c: 00012283 lw x5 0 x2 a0: 00412303 lw x6 4 x2 a4: 00812383 lw x7 8 x2 a8: 00c12e03 lw x28 12 x2 ac: 01012e83 lw x29 16 x2 b0: 01410113 addi x2 x2 20 b4: 00008067 jalr x0 x1 0 ``` ### illustrate each stage in pipeline * `IF`:fetch instruction from memory * `ID`:decoder the instructions include opcode and operands. * `EX`:perform the ALU calculation for result or effective address * `MEM`:access memory if needed * `WB`:write the result to destination register ### Control Hazards after jal instruction there are two instruction has been loaded when a jump is detected,it will be flush loaded instruction and load new instruction after jump. ![](https://i.imgur.com/bV3RagQ.png) ![](https://i.imgur.com/WISPWcR.png) ### Data Hazards when next instruction's source register need to use the last instruction's destination source,it will happen Data Hazard. two way to slove Data Hazard: 1. Data forwarding:forwarding data from stage MEM to EX 2. add two NOP instructions ![](https://i.imgur.com/qDDNNYK.png) data forwarding register x28 from stage MEM to EXE,for slove data hazard. ### local variables To protect main function variables,it need to push all register you changed in callee to stack. push to stack at the beginning of fuction: ``` 38: fec10113 addi x2 x2 -20 3c: 00512023 sw x5 0 x2 40: 00612223 sw x6 4 x2 44: 00712423 sw x7 8 x2 48: 01c12623 sw x28 12 x2 4c: 01d12823 sw x29 16 x2 ``` pop from stack at the end of fuction: ``` 9c: 00012283 lw x5 0 x2 a0: 00412303 lw x6 4 x2 a4: 00812383 lw x7 8 x2 a8: 00c12e03 lw x28 12 x2 ac: 01012e83 lw x29 16 x2 b0: 01410113 addi x2 x2 20 ``` register will not change after executing the function before call function: ![](https://i.imgur.com/BMux31C.png) after execution function: ![](https://i.imgur.com/akgPn3Y.png) ## Memory * .data from 0x10000000 to 0x10000028 ![](https://i.imgur.com/hL8hKpf.png) * .text from 0x00000000 to 0x000000bc ![](https://i.imgur.com/gJE1kP5.png) . . . ![](https://i.imgur.com/SDwkMVz.png)