简体   繁体   中英

Calculate nth Fibonacci number using RISC-V (RV32I) compiler without recursion

I have written a code for calculating nth fibonacci number in RISC-V assembly language. It has two parts- fib.s and runtest.s , which loads the value of n into a0 and calls fib , which calculates the nth fibonacci number (without recursion), loads the result into a0 itself and returns. Here is my code:

.global fib              # the runtest.s will give an a0 value as input n and call fib 
fib:
    li a1, 0             # This is a
    li a2, 1             # This is b
    li a3, 0             # This is c 
    li a4, 2             # This is i
   
    li a6, 2             # dummy, just to check a0 with
    ble a0, a6, cond1    # check if a0 <= 2
    bgt a0, a6, head     # if a0 > 2, proceed to loop

head:                    # start of loop
    add a3, a1, a2       # Here I'm implementing the space optimized version of fibonacci series without recursion:
    mv a1, a2            # for i in range(2, n+1): c = a + b; a = b; b = c; return b
    mv a2, a3            
    addi a4, a4, 1
    blt a4, a0, head
    bge a4, a0, end      # iterates n-1 times and goes to end

cond1:
    li a0, 1             # if n==1 or n==2 return 1
    li a7, 93
    ecall

end:
    mv a0, a2            # copying the value of a2 (which is b) to a0, since the testbench
    li a7, 93            # runtest.s is setup that way.
    ecall

And here is my testbench ( runtest.s ):

.global _start
_start:
    # Load 'n' into a0 and call fib
    # Test 1
    li      a0,1  # Check n'th Fib number
    call    fib
    li      a5,1  # Expected result
    bne     a0,a5,.FINISH
    # Test 2
    li      a0,3  
    call    fib
    li      a5,3  
    bne     a0,a5,.FINISH
    # Test 3
    li      a0,7  
    call    fib
    li      a5,13  
    bne     a0,a5,.FINISH
    # Test 4
    li      a0,9 
    call    fib
    li      a5,34
    bne     a0,a5,.FINISH
    # Test 5
    li      a0,20 
    call    fib
    li      a5,6765 
    bne     a0,a5,.FINISH
    # Test 6
    li      a0,30
    call    fib
    li      a5,832040 
    bne     a0,a5,.FINISH
    # Finished tests
    li      a5,0  # All passed
.FINISH:
    mv      a0, a5
    li      a7, 93
    ecall

Everytime I run this code I'm only getting a return value of 1. Can someone point out the error in this? Also if there's a better way to implement the same logic, please let me know of that as well.

I was able to get all of your testbench cases to pass in a RISC-V simulator with 3 changes:

(1) Your second test case has the wrong expected result. I'm assuming you're using 0-indexed Fibonacci numbers, since that's what most of your test cases do (eg test case 1 says Fibonacci number 1 is 1, test case 3 says Fibonacci number 7 is 13). In that case, Fibonacci number 3 should be 2, not 3.

(2) To get the correct number of iterations, in your loop, your "i" variable / register a4 should begin set to 1, not 2.

(3) You generally don't use ECALL to return from a function in RISC-V. As per the RISC-V spec, "the ECALL instruction is used to make a service request to the execution environment." It causes a precise trap and is used (for example) when implementing syscalls. Instead, there is the pseudoinstruction ret to return from a function call (similar notation to x86). ret is equivalent to jalr x0 0(ra). (That being said, maybe you've defined ecall behavior such that when a7 is 93, the equivalent of a ret is executed.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM