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:
out. By default the Vitis compiler will map these three parameters to the same AXI4 interface (
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
bundle keyword on the INTERFACE pragma
defines the name of the port. The Vitis 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.
gmemname 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
create two distinct ports:
gmem1. The kernel will access
out data through the
weights data will be accessed through the
gmem1 port. As a result, the kernel will be able to make parallel
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
compilation, resulting in a compiled kernel object (XO) file with two separate AXI interfaces,
m_axi_gmem1, that can be connected to global memory as needed. During 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.