Other features

There are two features we did not yet discuss. The first is timers, which are useful for getting information on the running time of your programs. The second is intervening in programs that are currently running on the Epiphany using the host.

Timers

We provide two mechanisms for getting running time information. The first uses the first timer (of the two) on the Epiphany core and is accurate for relatively short time intervals (less than about 7 seconds). It is used in the following manner:

float t_start = bsp_time();
// ... perform computation
float t_end = bsp_time();
float result = t_end - t_start;

The variable result than holds the time taken for the computation in seconds. If you want access to the number of clockcycles used for the computation we provide a similar function ebsp_raw_time() which gives the number of clockcycles as an unsigned integer:

unsigned int t_start = bsp_raw_time();
// ... perform computation
unsigned int t_end = bsp_raw_time();
unsigned int result = t_end - t_start;

Note that the default Epiphany clockfrequency is about 600 MHz, such that 600000000 cycles is equal to one second.

Note that there are two separate timers available on the Epiphany cores, identified by E_CTIMER_0 and E_CTIMER_1. The Epiphany BSP library will only use E_CTIMRE_0 so you are free to use the other timer in any way you require, using the Epiphany SDK.

The second method uses the system clock of the host to obtain the elapsed time. Because of varying amounts of latency this can be very inaccurate (its precision is in the order of milliseconds), but supports time intervals of arbitrary length. This timer can be used by calling the function ebsp_host_time():

float t_start = ebsp_host_time();
// ... perform (long) computation
float t_end = ebsp_host_time();
float result = t_end - t_start;

Interrupts

It is possible to set up interrupt handlers using the Epiphany SDK functionality. The only interrupt that is explicitely and necessarily handled by the EBSP library is E_DMA1_INT. For more information on the using the DMA engine, see the section on memory management. There is a timer interrupt that can be used if needed. The Epiphany BSP library uses neither of the two timre interrupts. The maximum number of cycles that can be counted using the raw timer is UINT_MAX which is roughly 7 seconds on the 600 MHz cores. After reaching this maximum value, an interrupt will be fired.

Callbacks

If you want to use the host processor together with the Epiphany processor, you require some sort of syncing mechanism. In particular you might want to react to data that has been sent to external memory, or use the ARM in a map-reduce kind of setting. For this we provide a callback mechanism using ebsp_set_sync_callback. You can provide a function pointer, and this function will get called each time a core calls ebsp_host_sync:

// on the host
void callback() {
    printf("ebsp_host_sync called on the Epiphany");
    // communicate with cores or react to data
}

..
bsp_begin(bsp_nprocs());
ebsp_set_sync_callback(callback);
..

Similarly we provide a callback mechanism for bsp_end, which can be useful when developing your own library on top of EBSP.

Interface (Timer and callback)

Host

void ebsp_set_sync_callback(void (*cb)())

Set the (optional) callback for synchronizing epiphany cores with the host program.

This callback is called when all Epiphany cores have called ebsp_host_sync(). Note that this does not happen at bsp_sync().

Parameters
  • cb: A function pointer to the callback function

void ebsp_set_end_callback(void (*cb)())

Set the (optional) callback for finalizing.

This callback is called when ebsp_spmd() finishes. It is primarily used by the ebsp memory inspector and should not be needed.

Parameters
  • cb: A function pointer to the callback function

Epiphany

float bsp_time()

Obtain the time in seconds since bsp_begin() was called.

The native Epiphany timer does not support time differences longer than UINT_MAX/(600000000) which is roughly 7 seconds.

Return
A floating point value with the number of elapsed seconds since the call to bsp_begin()

If you want to measure longer time intervals, we suggest you use the (less accurate) ebsp_host_time().

Remark
Using this in combination with ebsp_raw_time() leads to unspecified behaviour, you should only use one of these in your program.
Remark
This uses the internal Epiphany E_CTIMER_0 timer so the second timer can be used for other purposes.

unsigned int ebsp_raw_time()

Obtain the number of clockcycles that have passed since the previous call to ebsp_raw_time().

This function has less overhead than bsp_time.

Return
An unsigned integer with the number of clockcycles

Divide the number of clockcycles by 600 000 000 to get the time in seconds.

Remark
Using this in combination with bsp_time() leads to unspecified behaviour, you should only use one of these in your program.
Remark
This uses the internal Epiphany E_CTIMER_0 timer so the second timer can be used for other purposes.

float ebsp_host_time()

Obtain the time in seconds since bsp_begin() was called.

This function uses the system clock of the host to obtain the elapsed time. Because of varying amounts of latency this can be very inaccurate (its precision is in the order of milliseconds), but it supports time intervals of arbitrary length.

Return
A floating point value with the number of seconds since bsp_begin()