Struct Padding and Alignment - 2023.2 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
UG1399
Release Date
2023-12-18
Version
2023.2 English

Structs in Vitis HLS can have different types of padding and alignment depending on the use of __attributes__ or #pragmas. These features are described below.

Disaggregate
By default, structs in the code as internal variables are disaggregated into individual elements. The number and type of elements created are determined by the contents of the struct itself. Vitis HLS will decide whether a struct will be disaggregated or not based on certain optimization criteria.
Tip: You can use the AGGREGATE pragma or directive to prevent the default disaggregation of structs in the code.
Figure 1. Disaggregated Struct
Aggregate
Aggregating structs on the interface is the default behavior of the tool, as discussed in Structs in the Interface. Vitis HLS joins the elements of the struct, aggregating the struct into a single data unit. This is done in accordance with the AGGREGATE pragma or directive, although you do not need to specify the pragma as this is the default for structs on the interface. The aggregate process may also involve bit padding for elements of the struct, to align the byte structures on a default 4-byte alignment, or specified alignment.
Tip: The tool can issue a warning when bits are added to pad the struct, by specifying -Wpadded as a compiler flag.
Aligned
By default, Vitis HLS will align struct on a 4-byte alignment, padding elements of the struct to align it to a 32-bit width. However, you can use the __attribute__((aligned(X))) to add padding between elements of the struct, to align it on "X" byte boundaries.

Important: Note that "X" can only be defined as a power of 2.

The __attribute__((aligned)) does not change the sizes of variables it is applied to, but may change the memory layout of structures by inserting padding between elements of the struct. As a result the size of the structure will change.

Data types in struct with custom data widths, such as ap_int, are allocated with sizes which are powers of 2. Vitis HLS adds padding bits for aligning the size of the data type to a power of 2.

Vitis HLS will also pad the bool data type to align it to 8 bits.

In the following example, the size of varA in the struct will be padded to 8 bits instead of 5.

struct example  {
ap_int<5> varA;
unsigned short int varB;
unsigned short int varC;
int d;
};
Figure 2. Aligned Struct Implementation
The padding used depends on the order and size of elements of your struct. In the following code example, the struct alignment is 4 bytes, and Vitis HLS will add 2 bytes of padding after the first element, varA, and another 2 bytes of padding after the third element, varC. The total size of the struct will be 96-bits.
struct data_t {
  short varA;
  int varB;
  short varC;
};
However, if you rewrite the struct as follows, there will be no need for padding, and the total size of the struct will be 64-bits.
struct data_t {
  short varA;
  short varC;
  int varB;
};
Packed
Specified with __attribute__(packed(X)), Vitis HLS packs the elements of the struct so that the size of the struct is based on the actual size of each element of the struct. In the following example, this means the size of the struct is 72 bits:
Figure 3. Packed Struct Implementation
Tip: This can also be achieved using the compact=bit option of the AGGREGATE pragma or directive.