A Simple Example: Multiplying Two Vectors

To illustrate the concepts, we consider the implementation of a simple multiplcation of two vectors. The code can be found in hwdesign/vector_mult/vmult_vitis. The main program is in src/vmult.cpp which contains the follwing code (along with a number of #pragma statements that we will describe later).

void vec_mult(data_t *a, data_t *b, data_t *c, int n) {

    // Buffering to optimize memory access
    data_t a_buf[MAX_SIZE], b_buf[MAX_SIZE];
    data_t c_buf[MAX_SIZE];

    // Check for size limit
    if (n > MAX_SIZE) 
        n = MAX_SIZE;

    // Load into local buffers
    input_loop:  for (int i = 0; i < n; i++) {
        a_buf[i] = a[i];
        b_buf[i] = b[i];
    } 

    // Multiplication loop with optional pipelining / unrolling
    mult_loop:  for (int i = 0; i < n; i++) {
        c_buf[i] = a_buf[i] * b_buf[i];
    }


    // Store results back to global memory
    output_loop:  for (int i = 0; i < n; i++) {
        c[i] = c_buf[i];
    }
}

So the code reads data into local buffers, a_buf and b_buf, multiplies them and stores the result c_buf back to external memory. In this unit, we focus on the optimization of the multiplication loop, mult_loop.

We address the data transfer into and out of IP cores in a later unit. The data types are data_t, which can be set to either int or float. We will discuss the effect of data types in subsequent units as well.

Building and Simulating the the Vector Multiplier

The design files for this Vitis project are in the repo hwdesign/vector_mult/vmult_vitis. Follow the instructions to create the Vitis HLS project, modifyng the instructions for these design files.

One of the design files is include/vmult.h. The top of the file include/vmult.h provides a number of parameters that we can vary to see the effect of the optimization:

#define PIPELINE_EN 0  // Enables pipelining
#define UNROLL_FACTOR 1  // Unrolls loops when > 1
#define MAX_SIZE 1024  // Array size to test
#define DATA_FLOAT 1   // Data type:  1= float, 0=int

To try different optimizations, we will simply changes the values and re-run synthesis.

But, before we synthesize the Vitis IP, let’s make sure that the model is functionally correct by running it against the testbench. In the Vitis IDE GUI, go the Flow Panel (left sidebar) and select C Simulation->Run. This will run the testbench that generates two vectors a and b and confirms that the output is expected. Among many outputs you see in the Output window is Test passed!.


Go to the initial synthesis.


This site uses Just the Docs, a documentation theme for Jekyll.