void cnn( int *pixel, // Input pixel
int *weights, // Input Weight Matrix
int *out, // Output pixel
... // Other input or Output ports
In the example above, the kernel function has three pointer parameters:
pixel
, weights
, and
out
. By default the Vitis compiler will map these three parameters to the same AXI4 interface (m_axi
).
The default interface mapping inferred by the compiler is equivalent to the following INTERFACE pragmas:
#pragma HLS INTERFACE m_axi port=pixel offset=slave bundle=gmem
#pragma HLS INTERFACE m_axi port=weights offset=slave bundle=gmem
#pragma HLS INTERFACE m_axi port=out offset=slave bundle=gmem
The bundle
keyword on the INTERFACE pragma
defines the name of the port. The system compiler will create a port for each unique bundle
name, resulting in a compiled kernel object (XO) file that has a single AXI interface, m_axi_gmem
. When the same bundle
name is used for different interfaces, this results in these interfaces being mapped to same
port.
gmem
name is short for global memory; however, it is not a keyword and is just
used for consistency. You can assign your own names for the bundles.Sharing ports helps save FPGA resources by eliminating AXI interfaces, but it
can limit the performance of the kernel because all the memory transfers have to go through a
single port. The m_axi
port has independent READ and WRITE
channels, so with a single m_axi
port, you can do reads and
writes simultaneously. However, the bandwidth and throughput of the kernel can be increased by
creating multiple ports, using different bundle names, to connect to multiple memory banks.
There are many options for configuring the INTERFACE, as described in . Some
reasons to manually define an INTERFACE pragma in your code could include:
- Specifying the bundle for the INTERFACE pragma to separate AXI signals into separate bundles.
- Specifying the interface width to deviate from default int = 64 bytes (512-bits).
- Specifying AXI properties for burst transactions.
void cnn( int *pixel, // Input pixel
int *weights, // Input Weight Matrix
int *out, // Output pixel
... // Other input or Output ports
#pragma HLS INTERFACE m_axi port=pixel offset=slave bundle=gmem
#pragma HLS INTERFACE m_axi port=weights offset=slave bundle=gmem1
#pragma HLS INTERFACE m_axi port=out offset=slave bundle=gmem
In the example above, two bundle
names
create two distinct ports: gmem
and gmem1
. The kernel will
access pixel
and out
data
through the gmem
port, while weights
data will be accessed through the gmem1
port. As a result, the kernel will be able to make parallel accesses to pixel
and weights
, potentially
improving the throughput of the kernel.
bundle=
names using all lowercase characters, so you can
assign it to a specific memory bank using the connectivity.sp option. The INTERFACE pragma is used during v++
compilation, resulting in a compiled kernel object (XO) file with two separate AXI interfaces,
m_axi_gmem
and m_axi_gmem1
, that can be connected to global memory as needed. During system
compiler linking, the separate interfaces can be mapped to different global memory banks using
the connectivity.sp option in a configuration file, as
described in Mapping Kernel Ports to Memory.