Communicating between tiles#

Usually application code running on separate tiles will need to communicate and synchronise their activity. Such communication is passed via internal interconnect and between devices using xLINKs. See xCONNECT architecture. A top-level multi-tile XC file can also declare channels between the tiles it places entry-points on.

Declaring a channel in the multi-tile file#

The XK-EVK-XU316 has two tiles and interconnect for communication between the tiles within the package. The tools will automatically configure a channel via the interconnect using multitile.xc as below:

Listing 4 multitile.xc#
#include <platform.h>

typedef chanend chanend_t;

extern "C" {
  void main_tile0(chanend_t);
  void main_tile1(chanend_t);
}

int main(void)
{
  chan c;

  par {
    on tile[0]: main_tile0(c);
    on tile[1]: main_tile1(c);
  }

  return 0;
}

In this example, the tile level entrypoint functions each accept a chanend. In the forward-declarations these functions take a chanend argument; this is compatible with a lib_xcore chanend_t at link-time. The chan keyword is used in main to declare a channel. When a channel is passed to tile-level main, an end is automatically assigned to each entrypoint which uses it. In the task-level entrypoints, these chanends are used just like local ones.

Using the channel#

In the tile-level entrypoints, the chanends are used as per Programming an XCORE tile with C and lib_xcore. This time in main.c, we have a more interesting pair of tile functions. Each is passed a chanend_t c, and they use it to communicate between tiles and synchronise their activities.

Listing 5 main.c#
#include <stdio.h>
#include <xcore/channel.h>

#define ITERATIONS 10

void main_tile0(chanend_t c)
{
  int result = 0;
  
  printf("Tile 0: Result %d\n", result);

  chan_out_word(c, ITERATIONS);
  result = chan_in_word(c);

  printf("Tile 0: Result %d\n", result);
}

void main_tile1(chanend_t c)
{
  int iterations = chan_in_word(c);

  int accumulation = 0;

  for (int i = 0; i < iterations; i++)
  {
    accumulation += i;
    printf("Tile 1: Iteration %d Accumulation: %d\n", i, accumulation);
  }

  chan_out_word(c, accumulation);
}

Building and executing this multi-tile application produces the expected result:

$ xcc -target=XK-EVK-XU316 multitile.xc main.c
$ xrun --io a.xe
Tile 0: Result 0
Tile 1: Iteration 0 Accumulation: 0
Tile 1: Iteration 1 Accumulation: 1
Tile 1: Iteration 2 Accumulation: 3
Tile 1: Iteration 3 Accumulation: 6
Tile 1: Iteration 4 Accumulation: 10
Tile 1: Iteration 5 Accumulation: 15
Tile 1: Iteration 6 Accumulation: 21
Tile 1: Iteration 7 Accumulation: 28
Tile 1: Iteration 8 Accumulation: 36
Tile 1: Iteration 9 Accumulation: 45
Tile 0: Result 45

Summary#

You have now written a multi-tile application which, through the declarations in multitile.xc, sets up a channel between the tiles and provides pre-allocated chanends of for each end of this channel to the C functions.