Structs on the Interface - 2021.1 English

Vitis High-Level Synthesis User Guide (UG1399)

Document ID
Release Date
2021.1 English

Structs on the interface are aggregated by Vitis HLS by default; combining all of the elements of a struct into a single wide vector. This allows all members of the struct to be read and written-to simultaneously.

Important: Structs on the interface are aggregated by default but can be disaggregated using the DISAGGREGATE pragma or directive. However, structs contained in streaming interfaces (axis) cannot be disaggregated, and must be manually coded as separate elements if necessary. Structs on the interface also prevent Automatic Port Width Resizing and must be coded as separate elements to enable that feature.

As part of aggregation, the elements of the struct are also aligned on a 4 byte alignment for the Vitis kernel flow, and on 1 byte alignment for the Vivado IP flow. This alignment might require the addition of bit padding to keep or make things aligned, as discussed in Struct Padding and Alignment. By default the aggregated struct is padded rather than packed, but you can pack it using the compact=bit option of the AGGREGATE pragma or directive.

The member elements of the struct are placed into the vector in the order 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. This allows more data to be accessed in a single clock cycle. Any arrays in the struct are partitioned into individual array elements and placed in the vector from lowest to highest, in order.

In the following example, struct data_t is defined in the header file shown. The struct has two data members:

  • An unsigned vector varA of type short (16-bit).
  • An array varB of four unsigned char types (8-bit).
    typedef struct {
       unsigned short varA;
       unsigned char varB[4];
       } data_t;
    data_t struct_port(data_t i_val, data_t *i_pt, data_t *o_pt);

Aggregating the struct on the interface results in a single 48-bit port containing 16 bits of varA, and 4x8 bits of varB.

Tip: The maximum bit-width of any port or bus created by data packing is 8192 bits, or 4096 bits for axis streaming interfaces.

If a struct contains arrays, the AGGREGATE directive performs a similar operation as ARRAY_RESHAPE and combines the reshaped array with the other elements in the struct. However, a struct cannot be optimized with AGGREGATE and then partitioned or reshaped. The AGGREGATE, ARRAY_PARTITION, and ARRAY_RESHAPE directives are mutually exclusive.

There are no limitations in the size or complexity of structs that can be synthesized by Vitis HLS. There can be as many array dimensions and as many members in a struct as required. The only limitation with the implementation of structs occurs when arrays are to be implemented as streaming (such as a FIFO interface). In this case, follow the same general rules that apply to arrays on the interface (FIFO Interfaces).