pragma HLS data_pack

Description

Packs the data fields of astructinto a single scalar with a wider word width.

TheDATA_PACKpragma is used for packing all the elements of astructinto a single wide vector to reduce the memory required for the variable, while allowing all members of thestructto be read and written to simultaneously. The bit alignment of the resulting new wide-word can be inferred from the declaration order of thestructfields. The first field takes the LSB of the vector, and the final element of thestructis aligned with the MSB of the vector.

If thestructcontains arrays, theDATA_PACKdirective performs a similar operation as theARRAY_RESHAPEpragma and combines the reshaped array with the other elements in thestruct. Any arrays declared inside thestructare completely partitioned and reshaped into a wide scalar and packed with other scalar fields. However, astructcannot be optimized withDATA_PACKandARRAY_PARTITIONorARRAY_RESHAPE, as those pragmas are mutually exclusive.

Important:You should exercise some caution when using the DATA_PACKoptimization on structobjects with large arrays. If an array has 4096 elements of type int, this will result in a vector (and port) of width 4096*32=131072 bits. Vivado HLS can create this RTL design, however it is very unlikely logic synthesis will be able to route this during the FPGA implementation.

In general, Xilinx recommends that you use arbitrary precision (or bit-accurate) data types. Standard C types are based on 8-bit boundaries (8-bit, 16-bit, 32-bit, 64-bit), however, using arbitrary precision data types in a design lets you specify the exact bit-sizes in the C code prior to synthesis. The bit-accurate widths result in hardware operators that are smaller and faster. This allows more logic to be placed in the FPGA and for the logic to execute at higher clock frequencies. However, theDATA_PACKpragma also lets you align data in the packedstructalong 8-bit boundaries if needed.

If astructport is to be implemented with an AXI4 interface you should consider using theDATA_PACKoption to automatically align member elements of thestructto 8-bit boundaries. The AXI4-Stream protocol requires thatTDATAports of the IP have a width in multiples of 8. It is a specification violation to define an AXI4-Stream IP with aTDATAport width that is not a multiple of 8, therefore, it is a requirement to round upTDATAwidths to byte multiples. Refer to "Interface Synthesis and Structs" inVivado Design Suite User Guide: High-Level Synthesis(UG902) for more information.

Syntax

Place the pragma near the definition of thestructvariable to pack:

#pragma HLS data_pack variable=\ instance=

Where:

  • variable=: is the variable to be packed.
  • instance=: Specifies the name of resultant variable after packing. If nois specified, the inputis used.
  • : Optionally specifies whether to pack data on an 8-bit boundary (8-bit, 16-bit, 24-bit...). The two supported values for this option are:
    • struct_level: Pack the wholestructfirst, then pad it upward to the next 8-bit boundary.
    • field_level: First pad each individual element (field) of thestructon an 8-bit boundary, then pack thestruct.
    Tip:Deciding whether multiple fields of data should be concatenated together before ( field_level) or after ( struct_level) alignment to byte boundaries is generally determined by considering how atomic the data is. Atomic information is data that can be interpreted on its own, whereas non-atomic information is incomplete for the purpose of interpreting the data. For example, atomic data can consist of all the bits of information in a floating point number. However, the exponent bits in the floating point number alone would not be atomic. When packing information into TDATA, generally non-atomic bits of data are concatenated together (regardless of bit width) until they form atomic units. The atomic units are then aligned to byte boundaries using pad bits where necessary.

Example 1

Packsstructarray AB[17] with three 8-bit field fields (R, G, B) into a new 17 element array of 24 bits.

typedef struct{ unsigned char R, G, B; } pixel; pixel AB[17]; #pragma HLS data_pack variable=AB

Example 2

Packs struct pointer AB with three 8-bit fields (typedef struct {unsigned char R, G, B;} pixel) in functionfoo, into a new 24-bit pointer.

typedef struct{ unsigned char R, G, B; } pixel; pixel AB; #pragma HLS data_pack variable=AB

Example 3

In this example theDATA_PACKpragma is specified forinandoutarguments torgb_to_hsvfunction to instruct the compiler to do pack the structure on an 8-bit boundary to improve the memory access:

void rgb_to_hsv(RGBcolor* in, // Access global memory as RGBcolor struct-wise HSVcolor* out, // Access Global Memory as HSVcolor struct-wise int size) { #pragma HLS data_pack variable=in struct_level #pragma HLS data_pack variable=out struct_level ... }

See Also