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()