Buffer Location Constraints - 2025.2 English - UG1603

AI Engine-ML Kernel and Graph Programming Guide (UG1603)

Document ID
UG1603
Release Date
2025-11-26
Version
2025.2 English

The AI Engine-ML compiler tries to automatically allocate buffers for buffers, lookup tables, and runtime parameters in the most efficient manner possible. However, you might want to explicitly control their placement in memory. Similar to the kernels shown previously in this section, buffers inferred on a kernel port can also use location constraints. You can map them to specific tiles, banks, or address offsets. The following example illustrates this.

#include <adf.h>
#include "kernels.h"
#define NUMCORES (COLS*ROWS) 

template <int COLS, int ROWS, int STARTCOL, int STARTROW>
class indep_nodes_graph2 : public adf::graph {
 public:
   adf::kernel kr[NUMCORES];
   adf::port<input> datain[NUMCORES] ;
   adf::port<output> dataout[NUMCORES] ;
  
 indep_nodes_graph() {
  for (int i = 0; i < COLS; i++) {
    for (int j = 0; j < ROWS; j++) {
      int k = i*ROWS + j;
      kr[k] = adf::kernel::create(mykernel);
      adf::source(kr[k])  = "kernels/kernel.cc";
      adf::runtime<ratio>(kr[k]) = 0.9;
      adf::location<adf::kernel>(kr[k]) = adf::tile(STARTCOL+i, STARTROW+j); // kernel location
      adf::location<adf::buffer>(kr[k].in[0]) = 
        { adf::address(STARTCOL+i, STARTROW+j, 0x0), 
          adf::address(STARTCOL+i, STARTROW+j, 0x2000) };          // double buffer location
      adf::location<adf::stack>(kr[k]) = adf::bank(STARTCOL+i, STARTROW+j, 2); // stack location
      adf::location<adf::buffer>(kr[k].out[0]) = adf::location<adf::kernel>(kr[k]); // relative buffer location
    }
  }

  for (int i = 0; i < NUMCORES; i++) {
    adf::connect(datain[i], kr[i].in[0]);
    adf::connect(kr[i].out[0], dataout[i]);
  }
 };
};

In the previous code, the location of double buffers at port kr[k].in[0] is constrained to the specific memory tile address offsets that are created using the address(col,row,offset) constructor. Furthermore, the location of the system memory (including the sync buffer, stack and static heap) for the processor that executes kernel instance kr[k] is constrained to a particular bank using the bank(col,row,bankid) constructor. Finally, the tile location of the buffers connected to the port kr[k].out[0] is constrained to be the same tile as that of the kernel instance kr[k]. Buffer location constraints are applied on kernel buffer ports.

The second example shows how a buffer constraint (for PING and PONG buffers) can be added to a constraints file. The constraints file can be specified with the --constraints option of the AI Engine compiler.
{
  "PortConstraints": {
    "gr.k[0].in[0]": {
      "buffers": [{
          "column": 16,
          "row": 1,
          "bankId": 0,
          "offset": 16320
        }, {
          "column": 16,
          "row": 1,
          "bankId": 3,
          "offset": 0
        }]
    }
  }
}
If a graph has an RTP port, you can optionally constrain an additional selector word. This applies to PING, PONG and the selector word as shown:
{
  "PortConstraints": {
    "gr.fir24.in[1]": {
      "buffers": [{
          "column": 17,
          "row": 1,
          "bankId": 0,
          "offset": 16320
        }, {
          "column": 17,
          "row": 1,
          "bankId": 3,
          "offset": 0
        }, {
          "column": 18,
          "row": 1,
          "bankId": 0,
          "offset": 16224
        }]
    }
  }
}
Important: Using location constraint constructors and equality relations between them, you can make fine-grain mapping decisions that the compiler must honor. However, you must be careful because it is easy to create constraints that are impossible for the compiler to satisfy. For example, the compiler does not allow two buffers to be mapped to the same address offset.