Skip to content

Supported pragmas

gggg100 edited this page Oct 20, 2024 · 8 revisions

WORK IN PROGRESS - This documentation is partial.

Interface pragmas

When the --generate-interface=INFER option is set, the user is responsible for specifying the desired accelerator interfaces, usually on a per-argument basis. The information can be encoded in an XML file passed through the --interface-xml-filename command-line option or inserted in the source code with pragmas.

Interface pragmas have the following syntax (case sensitive):

#pragma HLS interface port=<signal_name> mode=<interface_type> [offset=direct] [bundle=<bundle_name>]

  • signal_name is the name of the variable that must be associated with the interface;
  • interface_type identifies what kind of interface will be generated;
  • offset=direct must be added if interface_type is m_axi;
  • bundle_name can be used if interface_type is m_axi, to create one instance of the interface for every bundle name. Signals associated with the same bundle name will share the interface, while signals using different bundle names will use different interfaces. If no bundle is specified, all signals will share the same interface. The default bundle name is gmem.

Available interface types are: none (corresponding to Xilinx ap_none), none_registered (ap_none with registered ports), bus (minimal memory interface), fifo (Xilinx ap_fifo), handshake (Xilinx ap_hs), valid (Xilinx ap_vld), o_valid (Xilinx ap_ovld), acknowledge (Xilinx ap_ack), array (Xilinx ap_memory), m_axi (AXI4-Master), axis (AXI4-Stream).

Examples

#pragma HLS interface port = var1 mode = m_axi offset = direct
#pragma HLS interface port = var2 mode = m_axi offset = direct
short function (short * var1, unsigned short *var2)
{
    /* Function code here */
}

This module needs to access two different addresses over an AXI bus. Addresses are passed as input to the function. For each function parameter, a pragma must be added immediately before the function definition, specifying that the interface type is m_axi. Since data for both parameters is available over the same bus, the bundle name can be omitted, and both will use the default bundle name. Bambu will treat the two function parameters var1 and var2 as AXI addresses; when generating a module for the function, a wrapper for the specified module will be generated as well and it will act as an AXI master node. Accesses to var1 and var2 will result in read/write requests from the wrapper to the bus.

#pragma HLS interface port = var1 mode = m_axi offset = direct bundle=gmem0
#pragma HLS interface port = var2 mode = m_axi offset = direct bundle=gmem1
short function (short * var1, unsigned short *var2)
{
    /* Function code here */
}

In this case, the two parameters are addresses on two different AXI buses. Each parameter requires a pragma specifying the use of m_axi, bundle names must now be specified because there is a need for two separate interfaces. Bambu will generate two AXI interfaces, each handling the data of one of the two addresses.

AXI cache pragmas

When requesting an AXI interface, it is possible to add a customizable cache that can help reduce the average memory access latency by accessing data in the cache rather than performing the full transaction over the AXI bus.

Cache pragmas have the following syntax (case sensitive):

#pragma HLS cache bundle=<bundle_name> line_count=<lines> line_size=<elements> [<cache_option> ...]

Cache options are separated by whitespaces, can be specified in any order, and are in the form <option_type> = <value>. More detailed information on the caches generated by Bambu will be available on a different page of the Wiki.

Option Default value Description
bundle -- Name of the AXI bundle that is going to use this cache, matching the one specified in one of the HLS_interface pragmas
line_count -- Number of lines in a way. If the value provided by the user is not a power of two, the number of lines will be the next power of two
line_size -- Number of elements in a cache line (not number of bytes). If the value provided by the user is not a power of two, the number of elements will be the next power of two
ways 1 Number of ways in the cache. If the value provided by the user is not a power of two, the number of ways will be the next power of two
bus_size size of the data type associated with the cache Width of the RDATA and WDATA signals in the AXI bus. Available values are 32, 64, 128, 256, 512, and 1024
buffer_size 2 Size of the buffer storing pending write transactions. If the value provided by the user is not a power of two, the buffer size will be the next power of two
rep_policy lru Type of replacement policy used by the cache, available values are lru (least recently used) and tree (tree-based pseudo-lru). This option has no effect if the number of ways is 1
write_policy wt Write policy used by the cache, available values are wt (write through no allocate) and wb (write back allocate)

Bambu does not support associating multiple bundles to the same cache. Either the bundles must be merged, or multiple caches must be used.

Associating a single variable in a bundle to a cache is also not supprted. Either the variable must have its own bundle, or the cache must be associated with all the signals in the bundle.

Examples

#pragma HLS interface port = var1 mode = m_axi offset = direct bundle=gmem0
#pragma HLS interface port = var2 mode = m_axi offset = direct bundle=gmem1
#pragma HLS cache bundle = gmem0 line_size = 64 line_count = 16
#pragma HLS cache ways = 4 line_count = 32 bundle = gmem1 write_policy = wb 
buffer_size = 2 rep_policy = tree bus_size = 64 line_size = 16
void function (int * var1, int * var2)
{ 
    /* Function code here */
}

Two caches are generated, one associated with bundle gmem0 (and variable var1), the other associated with bundle gmem1 (and variable var2).

The first cache pragma specifies the mandatory options, leaving the rest to their default values: the generated cache will have a single way of 16 lines containing 64 ints each. The data bus will have the size of an int, and the write buffer will contain 2 pending write transactions. The write policy will be write through and the replacement policy will be irrelevant since there is only one way.

The second cache will have 4 ways, each containing 32 lines of 16 ints. The data bus will be 64 bits wide, and the write buffer will contain 2 pending write transactions. The write policy will be write back and the tree-based pseudo-lru replacement policy will be used to select cache lines that must be overwritten.

#pragma HLS interface port = var1 mode = m_axi offset = direct bundle=gmem0
#pragma HLS interface port = var2 mode = m_axi offset = direct bundle=gmem0
#pragma HLS cache bundle = gmem0 line_size = 64 line_count = 16
void function (int * var1, int * var2)
{
    /* Function code here */
}

Same bundle for both variables associated to one cache, resulting in memory accesses to both var1 and var2 that are intercepted by the same cache.

#pragma HLS interface port = var1 mode = m_axi offset = direct bundle=gmem0
#pragma HLS interface port = var2 mode = m_axi offset = direct bundle=gmem1
#pragma HLS cache ways = 4 line_count = 32 bundle = gmem1 write_policy = wb 
buffer_size = 2 rep_policy = tree bus_size = 64 line_size = 16
void function (int * var1, int * var2)
{
    /* Function code here */
}

Accesses to var2 will be intercepted by a cache, accesses to var1 will result in direct requests on the AXI bus.

Clone this wiki locally