Given the behavior of the GCC compiler described previously, this section
will detail how Vitis HLS uses
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.
|Interface Argument||Internal Variable||Interface Argument||Internal variable|
AXI protocol interface
||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
In the case of AXI4 interfaces
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
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.