Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@
[submodule "trycatch"]
path = modules/trycatch/lib_trycatch
url = [email protected]:xmos/lib_trycatch.git
[submodule "modules/multitile_support/tests/tile_map_defines/modules/fwk_rtos"]
path = modules/multitile_support/tests/tile_map_defines/modules/fwk_rtos
url = [email protected]:xmos/fwk_rtos.git
[submodule "modules/multitile_support/tests/tile_map_defines/modules/xmos_cmake_toolchain"]
path = modules/multitile_support/tests/tile_map_defines/modules/xmos_cmake_toolchain
url = [email protected]:xmos/xmos_cmake_toolchain.git
87 changes: 87 additions & 0 deletions modules/multitile_support/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Multi-Tile Support

This module provides support for starting an application on multiple tiles
and communicating between those tiles. Support is provided for applications
using 2 or 4 tile XCore devices.

## Starting a multi-tile application

Starting a multi-tile application on an XCore device requires that an
entry point be defined for each tile. These entry points replace the
C standard main() entry point and are defined in tile_map.xc. In order
to make communication possible between the tiles of an XCore device,
the multi-tile entry points provide an XCore channel between each pair
of tiles used.

A set of weak implementations is provided for inclusion in your
project by adding tile_map_defaults.c to your build sources. This allows
the application code for on tile to be compiled and tested without
adding code for other tiles.

### Standard two tile configuration (e.g. XCore.ai)

Most applications will use a single XCore device with two tiles. In this
case, the application the C code needs two entry points, and the
prototypes (for tiles 0 and 1 respectively) will be:

void main_tile0(chanend_t c);
void main_tile1(chanend_t c);

The *chanend_t c* can be used on each tile to communicate with the other
tile by making use of the functions defined in **<xcore/channel.h>**. Note
that any channel communication operation (e.g. *chan_out_word(c, 100);* )
on one tile must be matched by the opposite channel operation on the
other tile (e.g. *int a = chan_in_word(c);* )

To achieve this configuration, the required preprocessor defines are:

PLATFORM_SUPPORTS_TILE_0 = 1
PLATFORM_SUPPORTS_TILE_1 = 1
PLATFORM_USES_TILE_0 = 1
PLATFORM_USES_TILE_1 = 1
MINIMISE_MAIN_TILE_ARGS

### Alternate configurations

In general, the code entry point prototype for each tile *X* which has both
**PLATFORM_SUPPORTS_TILE_*X* = 1** and **PLATFORM_USES_TILE_*X* = 1**
will be:

void main_tile*X* (*ARGS*);

If **MINIMISE_MAIN_TILE_ARGS** is not defined, each tile has an entry point of
the form:

void main_tile*X*(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3);

where *X* is the tile number. The four arguments are channel ends that
connect to each of the other tiles. In the above protoype, c*Y* indicates a
channel to tile *Y*. Where a tile *Y* is not both supported and used, or the
channel indicates a loopback (i.e. *X* == *Y*), that channel end argument is
not a valid channel end, and must not be used.

If **MINIMISE_MAIN_TILE_ARGS** is defined, the entry point prototype for
tiles defined as both supported and used will be as described above except
that invalid channel ends are removed. For example, if tiles 0, 2 and 3 are
available and used and MINIMISE_MAIN_TILE_ARGS is defined, the entry point
prototypes would be:

void main_tile0(chanend c2, chanend c3);
void main_tile2(chanend c0, chanend c3);
void main_tile3(chanend c0, chanend c2);

When setting preprocessor defines, using the **MINIMISE_MAIN_TILE_ARGS** define
also means that **PLATFORM_SUPPORTS_TILE_*X*** and **PLATFORM_USES_TILE_*X***
that are undefined are considered to be the equivalent to being set to 0.



## Inter-tile communication

The entry point prototypes provide a single channel for communication between
each tile pair by passing a dedicated channel end (*chanend_t*) to those two
tiles. In general, a chanend can only be used by a single thread running on a
core of the tile to which the channel end was provided. To establish
additional channels between tiles, this module provides an api which makes use
of the single channel passed to the code entry point to establish additional
channels.
238 changes: 238 additions & 0 deletions modules/multitile_support/api/main_tile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
// Copyright 2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.

/*
main_tile.h

This file provides prototypes for the entry point for each tile on an XCore
device. Including this file with your application will allow entry point
errors to be picked up at compile time rather than at the link stage.

Please see the multi-tile support module README for further details.
*/
#include <platform.h>

#include <xcore/chanend.h>

extern "C"
{

#ifndef MINIMISE_MAIN_TILE_ARGS

void main_tile0(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3);
void main_tile1(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3);
void main_tile2(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3);
void main_tile3(chanend_t c0, chanend_t c1, chanend_t c2, chanend_t c3);

#else // MINIMISE_MAIN_TILE_ARGS

// ---------------- Minimised Argument Prototypes ---------------------
// Common to all
#define MAIN_TAIL );

// -------------------- Tile 0 prototype ------------------------------
#if ((PLATFORM_SUPPORTS_TILE_0 == 1) && (PLATFORM_USES_TILE_0 == 1))

#define MAIN0_HEAD void main_tile0(

// c0
// channel c0 is loopback so it is never in the minimised argument set
#define MAIN0_ARG0

// c1
#if ((PLATFORM_SUPPORTS_TILE_1 == 1) && (PLATFORM_USES_TILE_1 == 1))
#define MAIN0_ARG1 chanend_t c_0to1
#define ARGS_STARTED
#else
#define MAIN0_ARG1
#endif


// c2
#if ((PLATFORM_SUPPORTS_TILE_2 == 1) && (PLATFORM_USES_TILE_2 == 1))

#ifdef ARGS_STARTED
#define MAIN0_ARG2 , chanend_t c_0to2
#else
#define MAIN0_ARG2 chanend_t c_0to2
#endif

#define ARGS_STARTED

#else
#define MAIN0_ARG2
#endif


// c3
#if ((PLATFORM_SUPPORTS_TILE_3 == 1) && (PLATFORM_USES_TILE_3 == 1))

#ifdef ARGS_STARTED
#define MAIN0_ARG3 , chanend_t c_0to3
#else
#define MAIN0_ARG3 chanend_t c_0to3
#endif

#else
#define MAIN0_ARG3
#endif


MAIN0_HEAD MAIN0_ARG0 MAIN0_ARG1 MAIN0_ARG2 MAIN0_ARG3 MAIN_TAIL
#endif // ----------------- End tile 0 prototype --------------------------



// -------------------- Tile 1 prototype ------------------------------
#if ((PLATFORM_SUPPORTS_TILE_1 == 1) && (PLATFORM_USES_TILE_1 == 1))

#define MAIN1_HEAD void main_tile1(


// c0
#if ((PLATFORM_SUPPORTS_TILE_0 == 1) && (PLATFORM_USES_TILE_0 == 1))
#define MAIN1_ARG0 chanend_t c_1to0
#define ARGS_STARTED
#else
#define MAIN1_ARG0
#endif

// c1
// channel c1 is loopback so it is never in the minimised argument set
#define MAIN1_ARG1


// c2
#if ((PLATFORM_SUPPORTS_TILE_2 == 1) && (PLATFORM_USES_TILE_2 == 1))
#ifdef ARGS_STARTED
#define MAIN1_ARG2 , chanend_t c_1to2
#else
#define MAIN1_ARG2 chanend_t c_1to2
#endif

#define ARGS_STARTED

#else
#define MAIN1_ARG2
#endif


// c3
#if ((PLATFORM_SUPPORTS_TILE_3 == 1) && (PLATFORM_USES_TILE_3 == 1))

#ifdef ARGS_STARTED
#define MAIN1_ARG3 , chanend_t c_1to3
#else
#define MAIN1_ARG3 chanend_t c_1to3
#endif

#else
#define MAIN1_ARG3
#endif


MAIN1_HEAD MAIN1_ARG0 MAIN1_ARG1 MAIN1_ARG2 MAIN1_ARG3 MAIN_TAIL
#endif // ----------------- End tile 1 prototype --------------------------



// -------------------- Tile 2 prototype ------------------------------
#if ((PLATFORM_SUPPORTS_TILE_2 == 1) && (PLATFORM_USES_TILE_2 == 1))
#define MAIN2_HEAD void main_tile2(

// c0
#if ((PLATFORM_SUPPORTS_TILE_0 == 1) && (PLATFORM_USES_TILE_0 == 1))
#define MAIN2_ARG0 chanend_t c_2to0
#define ARGS_STARTED
#else
#define MAIN2_ARG0
#endif

#if ((PLATFORM_SUPPORTS_TILE_1 == 1) && (PLATFORM_USES_TILE_1 == 1))
#ifdef ARGS_STARTED
#define MAIN2_ARG1 , chanend_t c_2to1
#else
#define MAIN2_ARG1 chanend_t c_2to1
#endif

#define ARGS_STARTED

#else
#define MAIN3_ARG1
#endif

// c2
// channel c2 is loopback so it is never in the minimised argument set
#define MAIN2_ARG2


// c3
#if ((PLATFORM_SUPPORTS_TILE_3 == 1) && (PLATFORM_USES_TILE_3 == 1))

#ifdef ARGS_STARTED
#define MAIN2_ARG3 , chanend_t c_2to3
#else
#define MAIN2_ARG3 chanend_t c_2to3
#endif

#else
#define MAIN2_ARG3
#endif


MAIN2_HEAD MAIN2_ARG0 MAIN2_ARG1 MAIN2_ARG2 MAIN2_ARG3 MAIN_TAIL
#endif // ----------------- End tile 2 prototype --------------------------



// -------------------- Tile 3 prototype ------------------------------
#if ((PLATFORM_SUPPORTS_TILE_3 == 1) && (PLATFORM_USES_TILE_3 == 1))
#define MAIN3_HEAD void main_tile3(

// c0
#if ((PLATFORM_SUPPORTS_TILE_0 == 1) && (PLATFORM_USES_TILE_0 == 1))
#define MAIN3_ARG0 chanend_t c_3to0
#define ARGS_STARTED
#else
#define MAIN3_ARG0
#endif

#if ((PLATFORM_SUPPORTS_TILE_1 == 1) && (PLATFORM_USES_TILE_1 == 1))
#ifdef ARGS_STARTED
#define MAIN3_ARG1 , chanend_t c_3to1
#else
#define MAIN3_ARG1 chanend_t c_3to1
#endif

#define ARGS_STARTED

#else
#define MAIN3_ARG1
#endif


// c2
#if ((PLATFORM_SUPPORTS_TILE_2 == 1) && (PLATFORM_USES_TILE_2 == 1))
#ifdef ARGS_STARTED
#define MAIN3_ARG2 , chanend_t c_3to2
#else
#define MAIN3_ARG2 chanend_t c_3to2
#endif

#define ARGS_STARTED

#else
#define MAIN3_ARG2
#endif

// c3
// channel c3 is loopback so it is never in the minimised argument set
#define MAIN3_ARG3


MAIN3_HEAD MAIN3_ARG0 MAIN3_ARG1 MAIN3_ARG2 MAIN3_ARG3 MAIN_TAIL
#endif // ----------------- End tile 3 prototype --------------------------

#endif // MINIMISE_MAIN_TILE_ARGS
}

Loading