Examples - 2023.1 English

AI Engine Kernel and Graph Programming Guide (UG1079)

Document ID
UG1079
Release Date
2023-06-23
Version
2023.1 English

Example of begin Iterator

#include "aie_api/aie.hpp"
void simple(input_buffer<cint16, adf::extents<BUFFER_SIZE>> & in, output_buffer<cint16, adf::extents<BUFFER_SIZE>> & out)
{
    // Use scalar iterator to traverse data
    auto pIn  = aie::begin(in);
    auto pOut = aie::begin(out);

    // For loop to go through all data from input_buffer via iterator
    for (unsigned i=0; i<(BUFFER_SIZE); i++)
    {
        *pOut++ = *pIn++;
    }
}

Example of begin_vector Iterator

#define VECTOR_SIZE 8
void simple(input_buffer<cint16, adf::extents<BUFFER_SIZE>> & in, output_buffer<cint16, adf::extents<BUFFER_SIZE>> & out)
{
    // Use vectoriterator to traverse data
    auto pIn  = aie::begin_vector<VECTOR_SIZE>(in);
    auto pOut = aie::begin_vector<VECTOR_SIZE>(out);

    // For loop to go through all data from input_buffer via iterator
    for (unsigned i=0; i<(BUFFER_SIZE/VECTOR_SIZE); i++)
    {
        *pOut++ = *pIn++;
    }
}

Example of cbegin Iterator

void simple(input_buffer<cint16, adf::extents<BUFFER_SIZE>> & in, output_buffer<cint16, adf::extents<BUFFER_SIZE>> & out)
{
    // Use scalar iterator to traverse data
    auto pIn  = aie::cbegin(in);
    auto pOut = aie::begin(out);

    // For loop to go through all data from input_buffer via iterator
    for (unsigned i=0; i<(BUFFER_SIZE); i++)
    {
        *pOut++ = *pIn++;
    }
}
Note: cbegin iterator is a read-only iterator. The aiecompiler will error out if the pOut iterator is declared as a cbegin iterator.

Example of cbegin_vector Iterator

#define VECTOR_SIZE 8
void simple(input_buffer<cint16, adf::extents<BUFFER_SIZE>> & in, output_buffer<cint16, adf::extents<BUFFER_SIZE>> & out)
{
    // Use vector iterator to traverse data
    auto pIn  = aie::cbegin_vector<VECTOR_SIZE>(in);
    auto pOut = aie::begin_vector<VECTOR_SIZE>(out);

    // For loop to go through all data from input_buffer via vector iterator
    // The buffer contains  (BUFFER_SIZE/VECTOR_SIZE) vectors
    for (unsigned i=0; i<(BUFFER_SIZE/VECTOR_SIZE); i++)
    {
        *pOut++ = *pIn++;
    }
}

Example of begin_random_circular Iterator

void simple(input_circular_buffer<cint16, adf::extents<BUFFER_SIZE>> & in, output_circular_buffer<cint16, adf::extents<BUFFER_SIZE>> & out)
{
    // Use scalar iterator to traverse data
    auto pIn  = aie::begin_random_circular(in);
    auto pOut = aie::begin_random_circular(out);

    pIn += BUFFER_SIZE/2; // Position the pointer at the middle of the buffer
    // Copies the second half, then the first half of the buffer onto the output
    for (unsigned i=0; i<(BUFFER_SIZE); i++)
    {
        *pOut++ = *pIn++;
    }
}

Example of begin_vector_random_circular Iterator

#define VECTOR_SIZE 8
void simple(input_circular_buffer<cint16, adf::extents<BUFFER_SIZE>> & in, output_circular_buffer<cint16, adf::extents<BUFFER_SIZE>> & out)
{
    // Use vector iterator to traverse data
    auto pIn  = aie::begin_vector_random_circular<VECTOR_SIZE>(in);
    auto pOut = aie::begin_vector_random_circular<VECTOR_SIZE>(out);

    // Position the pointer at the end of the buffer
    pIn += BUFFER_SIZE/VECTOR_SIZE;
    // Copies the input buffer onto the output buffer
    for (unsigned i=0; i<(BUFFER_SIZE/VECTOR_SIZE); i++)
    {
        *pOut++ = *pIn++;
    }
}
Note:
  • Circular buffer ports must use circular iterators. Linear buffer ports can use linear iterators or circular iterators.
  • Use vector iterators to access VECTOR_SIZE samples for each iteration. Where VECTOR_SIZE is 4 (128 bits), 8 (256 bits), 16 (512 bits), and 32 (1024 bits) for this specific example where the data-type is cint16 (32 bits).
  • Use random iterators when iterators need to be moved more than one step at a time in either direction.

Reading and Writing Data

There are several ways of reading and writing data to a one dimensional buffer port.

  • Using a raw pointer. Be aware that this mechanism must not be used with circular buffer ports.
    void simple(input_buffer<int32> & in, output_buffer<int32> & out) {
      int32 * pin = in.data();
      int32 * pout = out.data();
      for (int i = 0; i < BUFFER_SIZE; i++) {
        *pout++ = *pin++;
      }
      ...
    }
    
  • Using a scalar iterator.
    void simple(input_buffer<int32> & in, output_buffer<int32> & out) {
      auto pin = aie:begin(in);
      auto pout = aie:begin(out);
      for (int i = 0; i < BUFFER_SIZE; i++) {
        *pout++ = *pin++;
      }
      ...
    }
    
  • Using a vector iterator.
    void simple(input_buffer<int32> & in, output_buffer<int32> & out) {
      auto pin = aie::begin_vector<VECTOR_SIZE>(in);
      auto pout = aie::begin_vector<VECTOR_SIZE>(out);
      for (int i = 0; i < BUFFER_SIZE/VECTOR_SIZE; i++) {
        *pout++ = *pin++;
      }
      ...
    }