pragma HLS data_pack
Description
Packs the data fields of a struct
into a single scalar with a wider word
width.
The DATA_PACK
pragma is used for packing all the elements of a
struct
into a single wide vector to reduce the memory required for the
variable, while allowing all members of the struct
to be read and written
to simultaneously. The bit alignment of the resulting new wide-word can be inferred from the
declaration order of the struct
fields. The first field takes the LSB of
the vector, and the final element of the struct
is aligned with the MSB of
the vector.
If the struct
contains arrays, the DATA_PACK
pragma performs a similar operation as the ARRAY_RESHAPE
pragma and combines the reshaped array with the
other elements in the struct
. Any arrays declared inside
the struct
are completely partitioned and reshaped into a
wide scalar and packed with other scalar fields. However, a struct
cannot be optimized with DATA_PACK
and
ARRAY_PARTITION
or ARRAY_RESHAPE
, as those pragmas are mutually exclusive.
DATA_PACK
optimization on struct
objects 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, the
DATA_PACK
pragma also lets you align data in the packed
struct
along 8-bit boundaries if needed.
If a struct
port is to be implemented with an AXI4 interface you should
consider using the DATA_PACK <byte_pad>
option to
automatically align member elements of the struct
to 8-bit boundaries. The
AXI4-Stream protocol requires that TDATA
ports of the IP have a width in
multiples of 8. It is a specification violation to define an AXI4-Stream IP with a
TDATA
port width that is not a multiple of 8, therefore, it is a
requirement to round up TDATA
widths to byte multiples. Refer to "Interface
Synthesis and Structs" in Vivado Design Suite User Guide: High-Level Synthesis
(UG902) for more information.
Syntax
Place the pragma near the definition of the struct
variable to pack:
#pragma HLS data_pack variable=<variable> \
instance=<name> <byte_pad>
Where:
variable=<variable>
: is the variable to be packed.instance=<name>
: Specifies the name of resultant variable after packing. If no <name> is specified, the input <variable> is used.<byte_pad>
: 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 wholestruct
first, then pad it upward to the next 8-bit boundary.field_level
: First pad each individual element (field) of thestruct
on 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 intoTDATA
, 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
Packs struct
array 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 function foo
, 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 the DATA_PACK
pragma is specified for in
and out
arguments to rgb_to_hsv
function 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
- pragma HLS array_partition
- pragma HLS array_reshape
- Vivado Design Suite User Guide: High-Level Synthesis (UG902)