Mapping Constraints - 2022.1 English

Versal ACAP AI Engine Programming Environment User Guide (UG1076)

Document ID
UG1076
Release Date
2022-05-25
Version
2022.1 English

The following functions help to build various types of constraints on the physical mapping of the kernels and buffers onto the AI Engine array.

Scope

A constraint must appear inside a user graph constructor.

Kernel Location Constructors

location_constraint tile(int col, int row)

This location constructor points to a specific AI Engine tile located at specified column and row within the AI Engine array. The column and row values are zero based, where the zero'th row is counted from the bottom-most row with a compute processor and the zero'th column is counted from the left-most column. The previously used constructor proc(col,row) is now deprecated.

location_constraint location<kernel> (kernel&)

This constraint provides a handle to the location of a kernel so that it can be constrained to be located on a specific tile or co-located with another kernel using the following assignment operator.

Buffer Location Constructors

location_constraint address(int col, int row, int offset)

This location constructor points to a specific data memory address offset on a specific AI Engine tile. The offset address is relative to that tile starting at zero with a maximum value of 32768 (32K).

location_constraint bank(int col, int row, int bankid)
This location constructor points to a specific data memory bank on a specific AI Engine tile. The bank ID is relative to that tile and can take values 0, 1, 2, 3.
Note: The hardware view is 8 banks of 128-bit width. The software view is 4 banks of 256 width.
location_constraint offset(int offset_value)

This location constructor specifies data memory address offset. The offset address is between 0 and 32768 (32K) and is relative to a tile allocated by the compiler.

location_constraint location<buffer> (port<T>&)

This location constructor provides a handle to the location of a buffer attached to an input, output, or inout port of a kernel. It can be used to constrain the location of the buffer to a specific address or bank, or to be on the same tile as another kernel, or to be on the same bank as another buffer using the following assignment operator. It is an error to constrain two buffers to the same address. This constructor only applies to window kernel ports.

location_constraint location<stack> (kernel&)

This location constructor provides a handle to the location of the system memory (stack and heap) of the AI Engine where the specified kernel is mapped. This provides a mechanism to constrain the location of the system memory with respect to other buffers used by that kernel.

Important: The stack location offset must be in multiples of 32 bytes.
location_constraint location<parameter> (parameter&)

This location constructor provides a handle to the location of the parameter array (for example, a lookup table) declared within a graph.

Bounding Box Constructor

location_constraint bounding_box(int column_min, int row_min, int column_max, int row_max)

This bounding box constructor specifies a rectangular bounding box for a graph to be placed in AI Engine tiles, between columns from column_min to column_max and rows from row_min to row_max. Multiple bounding box location constraints can be used in an initializer list to specify an irregular shape bounding region.

Operator Functions

location_constraint& operator=(location_constraint)

This operator expresses the equality constraint between two location constructors. It allows various types of absolute or relative location constraints to be expressed.

The following example shows how to constrain a kernel to be placed on a specified AI Engine tile.

location<kernel>(k1) = tile(3,2);

The following template shows how to constrain the location of double buffers attached to a port that are to be placed on a specific address or a bankid. At most, two elements should be specified in the initializer list to constrain the location of the double banks. Furthermore, if these buffers are read or written by a DMA engine, then they must be on the same tile.

location<buffer>(port1) = { [address(c,r,o) | bank(c,r,id)] , [address(c,r,o) | bank(c,r,id)] };

The following template shows how to constrain the location of a parameter lookup table or the system memory of a kernel to be placed on a specific address or a bankid.

location<parameter>(param1) = [address(c,r,o) | bank(c,r,id)];

location<stack>(k1) = [address(c,r,o) | bank(c,r,id)];

The following example shows how to constrain two kernels to be placed relatively on the same AI Engine. This forces them to be sequenced in topological order and be able to share memory buffers without synchronization.

location<kernel>(k1) = location<kernel>(k2);

The following example shows how to constrain a buffer, stack, or parameter location to be on the same tile as that of a kernel. This ensures that the buffer, or parameter array can be accessed by the other kernel k1 without requiring a DMA.

location<buffer>(port1) = location<kernel>(k1);

location<stack>(k2) = location<kernel>(k1);

location<parameter>(param1) = location<kernel>(k1);

The following example shows how to constrain a buffer, stack, or parameter location to be on the same bank as that of another buffer, stack, or parameter. When two double buffers are co-located, this constrains both the ping buffers to be on one bank and both the pong buffers to be on another bank.

location<buffer>(port2) = location<buffer>(port1);

location<stack>(k1) = location<buffer>(port1);

location<parameter>(param1) = location<buffer>(port1);

The following example shows how to constraint a graph to be placed within a bounding box or a joint region among multiple bounding boxes.

location<graph>(g1) = bounding_box(1,1,2,2);

location<graph>(g2) = { bounding_box(3,3,4,4), bounding_box(5,5,6,6) };
The following example shows how to constrain FIFO locations using the DMA FIFO with aie_tile/memory_tile/shim_tile, tile column number, tile row number, memory address, and size as input parameters, and/or the stream switch FIFO with aie_tile/memory_tile/shim_tile, tile column number, tile row number, and FIFO identifier as input parameters.
location(net0) = { dma_fifo(tile_type0, col0, row0, address0, size0), ss_fifo(tile_type1, col1, row1, fifo_id1), ... }

Non-Equality Function

void not_equal(location_constraint lhs, location_constraint rhs)

This function expresses lhsrhs for the two location_constraint parameters lhs and rhs. It allows relative non-collocation constraint to be specified. The not_equal buffer constraint only works for single buffers. This constraint should not be used with double buffers.

The following example shows how to specify two kernels, k1 and k2, should not be mapped to the same AI Engine.

not_equal(location<kernel>(k1), location<kernel>(k2));

The following example shows how to specify two buffers, port1 and port2, should not be mapped to the same memory bank.

not_equal(location<buffer>(port1), location<buffer>(port2));

Stamp and Repeat Constraint

The following example shows how to constraint a graph to be placed within a bounding box. In this case, the tx_chain0 graph is the reference and its objects will be placed first and stamped to graph tx_chain1 and tx_chain2. The number of rows for all identical graphs (reference plus stamp-able ones) must be the same, and must begin and end at the same parity of row, meaning if the reference graph's bounding box begins at an even row and ends at an odd row, then all of the stamped graphs must follow the same convention. This limitation occurs because of the mirrored tiles in AI Engine array. In one row the AI Engine is followed by a memory group, and in the next row the memory group is followed by an AI Engine within a tile.

location<graph>(tx_chain0) = bounding_box(0,0,3,3);
location<graph>(tx_chain1) = bounding_box(4,0,7,3);
location<graph>(tx_chain2) = bounding_box(0,4,3,7);

location<graph>(tx_chain1) = stamp(location<graph>(tx_chain0));
location<graph>(tx_chain2) = stamp(location<graph>(tx_chain0));