Vitis HLS Alignment Rules and Semantics - 2022.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2022-12-07
Version
2022.2 English

Given the behavior of the GCC compiler described previously, this section will detail how Vitis HLS uses aligned and packed attributes to create efficient hardware. First, you need to understand the Aggregate and Disaggregate features in Vitis HLS. Structures or class objects in the code, for instance internal and global variables, are disaggregated by default. Disaggregation implies that the structure/class is decomposed into separate objects, one for each struct/class member. The number and type of elements created are determined by the contents of the struct itself. Arrays of structs are implemented as multiple arrays, with a separate array for each member of the struct.

However, structs used as arguments to the top-level function are kept aggregated by default. Aggregation implies that all the elements of a struct are collected into a single wide vector. This allows all members of the struct to be read and written simultaneously. The member elements of the struct are placed into the vector in the order in which they appear in the C/C++ code: the first element of the struct is aligned on the LSB of the vector and the final element of the struct is aligned with the MSB of the vector. Any arrays in the struct are partitioned into individual array elements and placed in the vector from lowest to the highest order.

Table 1. Interface Arguments and Internal Variables
  Behavior without AGGREGATE pragma Behavior with AGGREGATE pragma (compact=auto or not specified)
Interface Argument Internal Variable Interface Argument Internal variable

AXI protocol interface

(m_axi/s_axilite/axis)

aggregate compact=none N/A compact=none N/A
Struct/Class containing hls::stream object Automatically disaggregate the struct/class Automatically disaggregate the struct/class N/A N/A
other interface protocols aggregate compact=bit Automatically disaggregated compact=bit compact=bit

The goal of the default aggregation behavior in Vitis HLS is to use an x86_64-gnu-linux memory layout at the top level hardware interface while optimizing the internal hardware for better quality of results (QoR). The above table shows the default behavior of Vitis HLS. Two modes are shown in the table: the default mode where the AGGREGATE pragma is not specified by the user, and the case where the AGGREGATE pragma is specified by the user.

In the case of AXI4 interfaces (m_axi/s_axilite/axis), a structure is padded by default according to the order of elements of the struct as explained in Data Structure Padding. This aggregates the structure to a size that is the closest power of 2, and so some padding may be applied in this case. This in effect infers the compact=none option on the AGGREGATE pragma.

In the case of other interface protocols, the struct is packed at the bit-level, so the aggregated vector is only the size of the various elements of the struct, This in effect infers the compact=bit option on the AGGREGATE pragma.

The only exception to the above rules is when using hls::stream in the interface indirectly (i.e. the hls::stream object is specified inside a struct/class that is then used as the type of an interface port). The struct containing the hls::stream object is always disaggregated into its individual member elements.