HLS Vector Library - 2023.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 English
Important: To use hls::vector objects in your code include the header file hls_vector.h. An example vector application can be found in Vitis-HLS-Introductory-Examples/Modeling on GitHub.

Vector Data Type Usage

The vector data type is provided to easily model and synthesize SIMD-type vector operations. AMD Vitis™ HLS vector data type can be defined as follows, where T is a primitive or user-defined type with most of the arithmetic operations defined on it. N is an integer greater than zero. Once a vector type variable is declared it can be used like any other primitive type variable to perform arithmetic and logic operations.

#include <hls_vector.h>
hls::vector<T,N>  aVec;
Tip: The best performance is achieved when both the bit-width of T and N are integer powers of 2.

Memory Layout

For any vector type defined as hls::vector<T,N>, the storage is guaranteed to be contiguous of size sizeof(T)*N and aligned to the greatest power of 2 such that the allocated size is at least sizeof(T)*N. In particular, when N is a power of 2 and sizeof(T) is a power of 2, vector<T, N> is aligned to its total size. This matches vector implementation on most architectures.

Tip: When sizeof(T)*N is an integer power of 2, the allocated size will be exactly sizeof(T)*N, otherwise the allocated size will be larger to make alignment possible.

The following example shows the definition of a vector class that aligns itself as described above.

constexpr size_t gp2(size_t N)
{
    return (N > 0 && N % 2 == 0) ? 2 * gp2(N / 2) : 1;
}
 
template<typename T, size_t N> class alignas(gp2(sizeof(T) * N)) vector
{
    std::array<T, N> data;
};

Following are different examples of alignment:

hls::vector<char,8> char8Vec; // aligns on 8 Bytes boundary
hls::vector<int,8> int8Vec; // aligns on 32 byte boundary

Requirements and Dependencies

Vitis HLS vector types requires support for C++ 14 or later. It has the following dependencies on the standard headers:

  • <array>
    • std::array<T, N>
  • <cassert>
    • assert
  • <initializer_list>
    • std::initializer_list<T>

Supported Operations

  • Initialization:
    hls::vector<int, 4> x; // uninitialized
    hls::vector<int, 4> y = 10; // scalar initialized: all elements set to 10
    hls::vector<int, 4> z = {0, 1, 2, 3}; // initializer list (must have 4 elements)
    hls::vector<ap_int, 4> a; // uninitialized arbitrary precision data type
  • Access:
    The operator[] enables access to individual elements of the vector, similar to a standard array:
    x[i] = ...; // set the element at index i
    ... = x[i]; // value of the element at index i
  • Arithmetic:

    They are defined recursively, relying on the matching operation on T.

    Table 1. Arithmetic Operation
    Operation In Place Expression Reduction (Left Fold)
    Addition += + reduce_add
    Subtraction -= - non-associative
    Multiplication *= * reduce_mult
    Division /= / non-associative
    Remainder %= % non-associative
    Bitwise AND &= & reduce_and
    Bitwise OR |= | reduce_or
    Bitwise XOR ^= ^ reduce_xor
    Shift Left <<= << non-associative
    Shift Right >>= >> non-associative
    Pre-increment ++x none unary operator
    Pre-decrement --x none unary operator
    Post-increment x++ none unary operator
    Post-decrement x-- none unary operator
  • Comparison:

    Lexicographic order on vectors (returns bool):

    Table 2. Operation
    Operation Expression
    Less than <
    Less or equal <=
    Equal ==
    Different !=
    Greater or equal >=
    Greater than >