Understanding XE files and how they are loaded

This short tutorial aims to help you understand:

  • How a multi-tile application is stored inside an XE file

  • How to use XOBJDUMP to explore the contents of an XE file

  • How XRUN (and thus XGDB) coordinates the loading and execution of an XE file

Prepare an XE file

First, build a.xe as per the example in Targeting multiple tiles.

Examine the XE file

Before we run a.xe, let’s understand what’s inside it.

The XOBJDUMP tool is used to examine and manipulate the contents of an XE file. Let’s have a look at the innards of a.xe using xobjdump --sector-info. This lists the contents or ‘sectors’ of the .xe package:

$ xobjdump --sector-info a.xe
a.xe: file format: xcore-xe

Xmos binary sector information: file: a.xe

0: NODEDESC sector, part number: 0x5633
1: ELF sector for tile[0] (node 0, tile 0)
2: CALL sector. Address: 0x00000000
3: ELF sector for tile[1] (node 0, tile 1)
4: CALL sector. Address: 0x00000000
5: ELF sector for tile[0] (node 0, tile 0)
6: GOTO sector. Address: 0x00000000
7: ELF sector for tile[1] (node 0, tile 1)
8: GOTO sector. Address: 0x00000000
9: SYSCONFIG sector
10: XN sector
11: PROGINFO sector
12: XSCOPE sector
13: LASTSEC sector

Why are there four ELFs within the package? We only wrote one application!

It’s because the XCORE-200-EXPLORER target describes two cores or ‘tiles’ within one XMOS package. An application ELF is always generated by the tools for each tile. In this case our Hello from tile 0 is generated by the ELF in sector 5 on executing on tile[0]; the ELF in sector 7 generates our Hello from tile 1 by executing on tile[1].

But what about the ELFs in sectors 1 and 3? These are automatically generated. They contain start-of-day SoC and tile setup code which is executed prior to loading of the application ELF(s). The setup code is added to the setup ELFs because:

  • Some setup may be required before loading of the application ELF is possible and/or;

  • Setup placed in the setup ELFs does not waste space in the application ELF.

Note

Single-tile applications on multi-tile targets

If you create the single-tile application:

single-tile.c
#include <stdio.h>

int main(void) {
  printf("Hello world!\n");
  return 0;
}

…and build it specifying a multi-tile target (say the two-tile XCORE-200-EXPLORER):

$ xcc -target=XCORE-200-EXPLORER single-tile.c

…then an XE file containing 4 ELFs will still be produced; two setup ELFs and two application ELFs. The single-tile application ELF will default to execute on tile[0]; another automatically generated application ELF will execute on tile[1]. The automatically generated application ELF simply halts tile[1].

Load and execute the XE file

We now aim to illustrate the general description of how an XE file is booted by showing how XRUN loads and executes a.xe. Run a.xe with XRUN using the xrun --verbose: option:

$ xrun --io --verbose a.xe

A lot of output is produced. Here’s a shortened summary of the interesting bits. The first part confirms that the XRUN tool is actually just a convenience wrapper of the debugger tool XGDB:

>>>> xgdb script (/tmp/.xrun11863-5NG8M6AT/xeload_auto.gdb)
...
<<<<< xgdb script

>>>> xgdb cmd:
...
<<<< xgdb cmd

The next part shows XGDB loading and executing the two setup ELFs:

Loading setup image to XCore 0
Loading section .text, size 0x158 lma 0x40000
Loading section .cp.rodata, size 0x18 lma 0x40158
Loading section .dp.data, size 0x10 lma 0x40170
Start address 0x40000, load size 384
...

Loading setup image to XCore 1
Loading section .text, size 0x40 lma 0x40000
Loading section .cp.rodata, size 0x18 lma 0x40040
Start address 0x40000, load size 88
...

The next part shows XGDB loading and executing the two application ELFs:

Loading application image to XCore 0
Loading section .crt, size 0xac lma 0x40000
Loading section .init, size 0x1a lma 0x400ac
Loading section .fini, size 0x2e lma 0x400c6
Loading section .text, size 0x4b1c lma 0x400f4
Loading section .cp.rodata, size 0x108 lma 0x44c10
Loading section .cp.rodata.4, size 0x5c lma 0x44d18
Loading section .cp.const4, size 0x28 lma 0x44d74
Loading section .cp.rodata.string, size 0x84 lma 0x44d9c
Loading section .cp.rodata.cst4, size 0xcc lma 0x44e20
Loading section .dp.data, size 0x20 lma 0x44ef0
Loading section .dp.data.4, size 0x24 lma 0x44f10
Start address 0x40000, load size 20272
...

Loading application image to XCore 1
Loading section .crt, size 0xac lma 0x40000
Loading section .init, size 0x1a lma 0x400ac
Loading section .fini, size 0x2e lma 0x400c6
Loading section .text, size 0x4aec lma 0x400f4
Loading section .cp.rodata, size 0x100 lma 0x44be0
Loading section .cp.rodata.4, size 0x5c lma 0x44ce0
Loading section .cp.const4, size 0x28 lma 0x44d3c
Loading section .cp.rodata.string, size 0x84 lma 0x44d64
Loading section .cp.rodata.cst4, size 0xcc lma 0x44de8
Loading section .dp.data, size 0x20 lma 0x44eb8
Loading section .dp.data.4, size 0x24 lma 0x44ed8
Start address 0x40000, load size 20216
...

The last part shows XGDB displaying the printf() output and waiting for the application to complete before returning control to the terminal:

Hello from tile 0
Hello from tile 1

Program exited normally.