Vector addition with RISC-V RVV

Writing a small vector addition program for RISC-V RVV in hybrid C and assembly.

Previously the C program we wrote used C RVV intrinsics, but you might want to use the RISC-V RVV assembly instructions instead.

We use C to handle the setting up of the vector arrays and the display of these vectors to the terminal. Doing I/O in assembly language is, at best, painful, so I have no issue with letting C take the weight.

In this example we will be using RVV version 1.0. The Makefile has been set up for using with SPIKE, but I have tested the code on my Banana Pi F3 and it runs.

Below is the Makefile, the C file and the assembly function that the C program calls.

Makefile

CFLAGS=-march=rv64gcv -mabi=lp64d -mno-relax
CC=riscv64-unknown-linux-gnu-gcc
SRC=main.c RVVaddition.s
TARGET=RVVaddition

$(TARGET):$(SRC)
	$(CC) -v $(CFLAGS) -o $(TARGET) $(SRC)

run:
	$(RISCV)/riscv-isa-sim/build/spike --isa=RV64IMACV $(RISCV)/riscv-pk/build/pk ./$(TARGET)

clean:
	rm -f $(TARGET)

main.c

/* 
 * program to add two 4 evelmet vectors together
 * using RISC-V RVV assembly instructions
 */
 
#include <stdio.h>

// Function prototype for the vec_add assembly function
void vec_add(int *vec1, int *vec2, int *result);

int main() {
    // Initialize two small vectors and a result vector
    int vectorA[4] = {1, 2, 3, 4};
    int vectorB[4] = {5, 6, 7, 8};
    int vectorC[4] = {0};

    // Output vectorA and vectorB to the terminal
    printf("Vector A: ");
    for (int i = 0; i < 4; i++) {
        printf("%2d ", vectorA[i]);
    }
    printf("\n");

    printf("Vector B: ");
    for (int i = 0; i < 4; i++) {
        printf("%2d ", vectorB[i]);
    }
    printf("\n");

    // Call the vec_add assembly function to add 
    // vectorA and vectorB and return vectorC
    vec_add(vectorA, vectorB, vectorC);

    // Output the result to the terminal
    printf("vector C: ");
    for (int i = 0; i < 4; i++) {
        printf("%2d ", vectorC[i]);
    }
    printf("\n");

    return 0;
}

RVVaddition.s

# RISC-V assembly function to add two 4 element vectors
# and return the result to the calling C program

.global vec_add

.section .text
vec_add:
    # Set vector length to 4 elements of 32 bits each
    li t0, 4                  # Number of elements
    vsetvli t0, t0, e32, m2   # Set vector length to 4 elements of 
                              # 32-bit each, with 2 registers per element
    
    # Load vectors from memory
    vle32.v v0, (a0)          # Load vec1 into v0
    vle32.v v8, (a1)          # Load vec2 into v8
    
    # Perform vector addition
    vadd.vv v0, v0, v8        # v0 = v0 + v8
    
    # Store result in memory
    vse32.v v0, (a2)          # Store v0 into result
    
    ret                       # Return to calling program

Compile and Run

me@bpif3:make
me@bpif3:./RVVaddition
Vector A:  1  2  3  4
Vector B:  5  6  7  8
Vector C:  6  8 10 12

Mission Accomplished

And there we have it, you have managed to do a vector addition of two 4 element arrays in RISC-V assembly with a calling C program handling the I/O.