Wednesday 7 January 2015

Timing C Code Running On the XMOS xCORE Architecture

I recently had to show a customer how long a piece of code took to execute on the XMOS xCORE.

The nice thing about the xCORE is that it includes hardware timers that can be directly accessed from the application.

In order to be able to benchmark the code I knew there would be a small overhead to call the timers from the top level C code so my first task was to calculate this.

Having calculated the overhead I was now free to benchmark the actual code then remove the overhead to print the correct time.

As an aside, one of the great benefits of the XMOS architecture is how debug_printf's are implemented. Essentially the output of a printf can be routed over the inter-processor communications link called xCONNECT, in real-time. This allows debug_printf's to be located directly inside real-time code, unlike other microcontrollers where locating a printf inside an interrupt service routine is guaranteed to cause a run-time exception (AKA crash). Note, the code below uses regular printfs so that it can be compiled to run on any CPU, with suitable #defines/#ifs around the XMOS benchmarking code.

Here is the benchmarking code showing the performance of a simple piece of C code, with inline assembly:

#include <stdio.h>
#include "xbenchmark.h"

int main (void) 
{
  int start_time, end_time, overhead_time;
  overhead_time = xbench_init();

  start_time = xbench_get_time();
  asm ("nop");
  asm ("nop");
  end_time = xbench_get_time();
  
  printf ("Elapsed time = %d cycles\n", end_time - start_time - overhead_time);

  return (0);
}

Here is the xbenchmark.h file:

// XMOS Benchmarking Functions

int xbench_get_time(void);

int xbench_init(void);


Here is the xbenchmark.xc file:

// XMOS Benchmarking Functions

// Include files
#include <xs1.h>

timer t;

int xbench_get_time(void)
{
    int time;
    t :> time;
    return(time);
}

int xbench_init(void)
{
    int start_time, end_time;

    start_time = xbench_get_time();
    end_time = xbench_get_time();
    return(end_time - start_time);
}

Here is the command for compiling the C code:

xcc -O3 app.c xbenchmark.xc -target=XCORE-200-EXPLORER -o app.xe

And here is the output:

Elapsed time = 2 cycles

Phew, two nops takes two cycles :-)

Notes
XMOS use the incredible LLVM compiler, which I am sure will one day take over from GCC. It is almost never necessary to revert to assembly code but if you need to then you can see from the above example just how easy it is to use.
In order to read and write to the XMOS hardware (such as the timer, as shown above) it is necessary to use XC, rather than C, as shown above. The XC functions are documented in the XMOS Programming Guide : https://www.xmos.com/download/public/XMOS-Programming-Guide-(documentation)(E).pdf.

If you have found this solution useful then please do hit the Google (+1) button so that others may be able to find it as well.
Numerix-DSP Libraries : http://www.numerix-dsp.com/eval/

No comments:

Post a Comment