Aggregate Memory Mapped Interface
This is an example of the AGGREGATE pragma or directive for an m_axi
interface. The following is the aggregation_of_m_axi_ports example
available on GitHub.
struct A {
char foo; // 1 byte
short bar; // 2 bytes
};
int dut(A* arr) {
#pragma HLS interface m_axi port=arr depth=10
#pragma HLS aggregate variable=arr compact=auto
int sum = 0;
for (unsigned i=0; i<10; i++) {
auto tmp = arr[i];
sum += tmp.foo + tmp.bar;
}
return sum;
}
For the above example, the size of the m_axi
interface port
arr
is 3 bytes (or 24 bits) but due to the AGGREGATE
compact=auto
pragma, the size of the port will be aligned to 4 bytes
(or 32 bits) as this is the closest power of 2. Vitis HLS will issue the following message in the log file:
INFO: [HLS 214-241] Aggregating maxi variable 'arr' with compact=none mode in 32-bits (example.cpp:19:0)
AGGREGATE
pragma is specified. But even without the pragma, the
tool will automatically aggregate and pad the interface port arr
to
4 bytes as the default behavior for an AXI interface port.Aggregate Structs on the Interface
This is an example of the AGGREGATE pragma or directive for an ap_fifo
interface. The following is the aggregation_of_struct example available
on GitHub.
struct A {
int myArr[3]; // 4 bytes per element (12 bytes total)
ap_int<23> length; // 23 bits
};
int dut(A arr[N]) {
#pragma HLS interface ap_fifo port=arr
#pragma HLS aggregate variable=arr compact=auto
int sum = 0;
for (unsigned i=0; i<10; i++) {
auto tmp = arr[i];
sum += tmp.myArr[0] + tmp.myArr[1] + tmp.myArr[2] + tmp.length;
}
return sum;
}
For ap_fifo
interface, the struct will packed at the bit-level with
or without aggregate pragma.
In the above example, the AGGREGATE
pragma will create a port of size 119 bits for port arr
. The array myArr
will take 12
bytes (or 96 bits) and the element length
will take
23 bits for a total of 119 bits. Vitis HLS will
issue the following message in the log file:
INFO: [HLS 214-241] Aggregating fifo (array-to-stream) variable 'arr' with compact=bit mode
in 119-bits (example.cpp:19:0)
Aggregate Nested Struct Port
This is an example of the AGGREGATE pragma or directive in the Vivado IP flow. The following is the aggregation_of_nested_structs example available on GitHub.
#define N 8
struct T {
int m; // 4 bytes
int n; // 4 bytes
bool o; // 1 byte
};
struct S {
int p; // 4 bytes
T q; // 9 bytes
};
void top(S a[N], S b[N], S c[N]) {
#pragma HLS interface bram port=c
#pragma HLS interface ap_memory port=a
#pragma HLS aggregate variable=a compact=byte
#pragma HLS aggregate variable=b compact=bit
#pragma HLS aggregate variable=c compact=byte
for (int i=0; i<N; i++) {
c[i].q.m = a[i].q.m + b[i].q.m;
c[i].q.n = a[i].q.n - b[i].q.n;
c[i].q.o = a[i].q.o || b[i].q.o;
c[i].p = a[i].q.n;
}
}
In the above example, the aggregation algorithm will create a port of size 104 bits
for ports a
, and c
as the
compact=byte
option was specified in the aggregate pragma but
the compact=bit
default option is used for port b
and its packed size will be 97 bits. The nested structures S
and
T
are aggregated to encompass three 32 bit member variables (p,
m, and n) and one bit/byte member variable (o
).
b
will be automatically inferred as an m_axi
port and will not allow
the compact=bit
setting.INFO: [HLS 214-241] Aggregating bram variable 'b' with compact=bit mode in 97-bits (example.cpp:19:0)
INFO: [HLS 214-241] Aggregating bram variable 'a' with compact=byte mode in 104-bits (example.cpp:19:0)
INFO: [HLS 214-241] Aggregating bram variable 'c' with compact=byte mode in 104-bits (example.cpp:19:0)