lib_xcore#

lib_xcore is a system library that provides a C API for the underlying hardware features of an xcore tile. A header file is provided for each functional area, and can be included with a line such as:

#include <xcore/port.h>

By default, lib_xcore is automatically added to the list of libraries for linking, so there is no need to use xcc -l.

API details#

xcore/assert.h#

Provides assertions similar to those defined by the standard C assert.h.

Assertions provided by this header are intended by behave similarly to the C standard assert. However by default, when enabled, these macros will expand to ‘hardware assisted’ assertions which cause processor exceptions upon failure. ‘Hardware assisted’ assertions can execute quickly and do not print any diagnostic information. This makes these assertions suitable for applications where small code size is desirable.

The behaviour of the (expansion of) macros defined in this header varies depending on the macros defined at the point it is first included. Specifically:

  • If NDEBUG is defined all assertions will expand to ((void)0);

  • Otherwise, if LIBXCORE_XASSERT_IS_ASSERT is not defined then the assertions will be ‘hardware assisted’ and will trap on failure without printing any diagnostic information;

  • Otherwise (i.e. LIBXCORE_XASSERT_IS_ASSERT is defined and NDEBUG is not) the assertions will be implemented in terms of the C standard library assert.

Defines

_XCORE_XASSERT_EMPTY#
_XCORE_XASSERT_HIDE(_X)#
_XCORE_XASSERT_NOT_AFTER(_C)#
_XCORE_XASSERT_TRUE(_CONDITION)#
_XCORE_XASSERT_FALSE(_CONDITION)#
xassert(__condition)#

Assert that a given expression evaluates true.

Asserts that condition is true (nonzero). The actual behaviour when condition is false depends on the which configuration macros are defined.

Attention

condition should not have side effects as these will not be executed when assertions are ineffective.

Parameters:
  • __condition – The expression which is expected to evaluate true

xassert_not(__condition)#

Assert that a given expression evaluates false.

Asserts that condition is false (0). The actual behaviour when condition is true depends on the which configuration macros are defined.

Attention

condition should not have side effects as these will not be executed when assertions are ineffective.

Parameters:
  • __condition – The expression which is expected to evaluate true

xassert_not_after(__timestamp)#

Assert that the given timestamp is not in the past.

On XS2 and onwards this macro implements a timing assertion based on the reference clock. When LIBXCORE_XASSERT_IS_ASSERT is defined an approximation of the ‘hardware’ assert’s condition is used however this may be less accurate as checking the timestamp cannot be performed as a single instruction.

The macro LIBXCORE_HAS_TIMING_ASSERTIONS will be defined if and only if this assertion can be effective on the current platform.

Attention

timestamp should not have side effects as these will not be executed when assertions are ineffective (including when timing assertions are not available on the current platform).

Warning

On XS1 devices this assertion will have no effect.

Parameters:
  • __timestamp – The timestamp which is expected not to be in the past

xcore/chanend.h#

Low level channel end API.

Attention

It is strongly recommended that higher-level ‘channel’ protocols are used e.g. xcore/channel.h or xcore/channel_streaming.h

Typedefs

typedef resource_t chanend_t#

Opaque channel end type for use in C/C++ code.

Attention

Users must not access its raw underlying type.

Functions

inline chanend_t chanend_alloc()#

Allocate a single chanend.

If there are no channel ends available the function returns 0.

Note

When the channel end is no longer required, chanend_free() should be called to deallocate it.

Returns:

Allocated chanend (0 if none are available)

inline void chanend_free(chanend_t __c)#

Deallocate a single chanend.

Attention

The last transfer on the chanend must have been a CT_END token.

Parameters:
  • __c – chanend to free.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chanend, an input/output is pending, or it has not received/sent a CT_END token.

Throws ET_RESOURCE_DEP:

another core is actively using the chanend.

inline void chanend_set_dest(chanend_t __c, chanend_t __dst)#

Set the destination of a chanend.

Parameters:
  • __c – chanend to set.

  • __dst – Destination chanend.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chanend.

Throws ET_RESOURCE_DEP:

another core is actively using the chanend.

inline chanend_t chanend_get_dest(chanend_t __c)#
inline void chanend_out_byte(chanend_t __c, char __b)#
inline void chanend_out_word(chanend_t __c, uint32_t __w)#
inline void chanend_out_control_token(chanend_t __c, char __ct)#
inline char chanend_in_byte(chanend_t __c)#
inline uint32_t chanend_in_word(chanend_t __c)#
inline char chanend_in_control_token(chanend_t __c)#
inline void chanend_check_control_token(chanend_t __c, const char __ct)#
inline int chanend_test_control_token_next_byte(chanend_t __c)#
inline int chanend_test_control_token_next_word(chanend_t __c)#
inline int chanend_test_dest_local(chanend_t __c)#
inline void chanend_set_network(chanend_t __c, uint32_t __net)#
inline unsigned chanend_get_network(chanend_t __c)#
inline void chanend_out_end_token(resource_t __c)#
inline void chanend_check_end_token(resource_t __c)#

xcore/channel_streaming.h#

Streaming channel API.

Functions

inline streaming_channel_t s_chan_alloc()#

Allocate a streaming channel by allocating two hardware chan-ends and joining them.

If there are not enough chan-ends available the function returns a streaming_channel_t with both fields set to 0.

Attention

The chan-ends must be accessed on the same tile

Note

When the streaming_channel_t is no longer required, s_chan_free() should be called to deallocate it.

Returns:

streaming_channel_t variable holding the two initialised and joined chan-ends or 0s.

inline void s_chan_free(streaming_channel_t __c)#

Deallocate a streaming_channel_t by freeing its two hardware chan-ends.

Parameters:
Throws ET_LINK_ERROR:

a chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated channel, or an input/output is pending.

Throws ET_RESOURCE_DEP:

another core is actively using the channel.

inline void s_chan_out_word(chanend_t __c, uint32_t __data)#

Output a word over a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

  • __data – The word to be output

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

inline void s_chan_out_byte(chanend_t __c, uint8_t __data)#

Output an byte over a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

  • __data – The byte to be output

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

inline void s_chan_out_buf_word(chanend_t __c, const uint32_t __buf[], size_t __n)#

Output a block of data over a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

  • __buf – A pointer to the buffer containing the data to send

  • __n – The number of words to send

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

inline void s_chan_out_buf_byte(chanend_t __c, const uint8_t __buf[], size_t __n)#

Output a block of data over a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

  • __buf – A pointer to the buffer containing the data to send

  • __n – The number of bytes to send

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

inline uint32_t s_chan_in_word(chanend_t __c)#

Input a word from a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or has pending control token.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Returns:

The word read from the channel

inline uint8_t s_chan_in_byte(chanend_t __c)#

Input a byte from a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or has pending control token.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Returns:

The byte read from the channel

inline void s_chan_in_buf_word(chanend_t __c, uint32_t __buf[], size_t __n)#

Input a block of data from a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

  • __buf – A pointer to the memory region to fill

  • __n – The number of words to receive

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or has pending control token.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

inline void s_chan_in_buf_byte(chanend_t __c, uint8_t __buf[], size_t __n)#

Input a block of data from a streaming_channel_t.

Parameters:
  • __c – The streaming chan-end

  • __buf – A pointer to the memory region to fill

  • __n – The number of bytes to receive

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or has pending control token.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

struct streaming_channel_t#
#include <channel_streaming.h>

Public Members

chanend_t end_a#
chanend_t end_b#

xcore/channel_transaction.h#

API for transaction-based channel communications.

Typedefs

typedef __xcore_transacting_chanend_t transacting_chanend_t#

An opaque type for handling transactions.

Users must not access its raw underlying type.

Functions

inline transacting_chanend_t chan_init_transaction_master(chanend_t __c)#

Start a transaction (master).

This initiates a transaction on a channel.

A transacting_chanend_t is used to temporarily open a transaction route through a channel. During the transaction, you can use transaction channel operations for increased efficiency. You can create a transacting chanend from a normal chanend using chan_init_transaction_master() and chan_init_transaction_slave().

This called must be matched by a call to chan_init_transaction_slave() on the other end of the channel.

Note

A transaction must be closed with chan_complete_transaction().

Parameters:
  • __c – chan-end to initialize the transaction on.

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Returns:

the intialized master transacting_chanend_t

inline transacting_chanend_t chan_init_transaction_slave(chanend_t __c)#

Start a transaction (slave).

This call must be matched by a call to chan_init_transaction_master() on the other end of the channel.

Note

A transaction must be closed with chan_complete_transaction().

Warning

The original channed c must not be used until the transaction is closed.

Parameters:
  • __c – chan-end to initialize the transaction on. chanend is invalidated

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or does not contain CT_END token.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Returns:

the intialized slave transacting_chanend_t

inline chanend_t chan_complete_transaction(transacting_chanend_t __tc)#

Completes a transaction. After this call the route between the two ends of the channel is freed allowing other channels to use the communication network.

Whilst the transacting_chanend_t is now invalid, the channel remains allocated, awaiting another transaction or deallocation.

Note

This call must be accompanied by a call to chan_complete_transaction() on the other end of the channel.

Parameters:
  • __tc – Transacting chan-end to close.

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Returns:

The original chan-end which is valid once again.

inline void t_chan_out_word(transacting_chanend_t *__tc, uint32_t __data)#

Output a word over a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

  • __data – Word to be output

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc argument.

inline void t_chan_out_byte(transacting_chanend_t *__tc, uint8_t __data)#

Output an byte over a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

  • __data – Byte to be output

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc argument.

inline void t_chan_out_buf_word(transacting_chanend_t *__tc, const uint32_t __buf[], size_t __n)#

Output a block of data over a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

  • __buf[in] Pointer to the buffer containing the data to send

  • __n – Number of words to send

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc or buf[] argument.

inline void t_chan_out_buf_byte(transacting_chanend_t *__tc, const uint8_t __buf[], size_t __n)#

Output a block of data over a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

  • __buf[in] Pointer to the buffer containing the data to send

  • __n – Number of bytes to send

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc or buf[] argument.

inline uint32_t t_chan_in_word(transacting_chanend_t *__tc)#

Input a word from a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc argument.

Returns:

Word read from tc

inline uint8_t t_chan_in_byte(transacting_chanend_t *__tc)#

Input a byte from a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc or data argument.

Returns:

Byte read from tc

inline void t_chan_in_buf_word(transacting_chanend_t *__tc, uint32_t __buf[], size_t __n)#

Input a block of data from a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

  • __buf[in] Pointer to the memory region to fill

  • __n – The number of words to receive

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid tc or buf[] argument.

inline void t_chan_in_buf_byte(transacting_chanend_t *__tc, uint8_t __buf[], size_t __n)#

Input a block of data from a transacting chan-end.

Parameters:
  • __tc[inout] Transacting chan-end

  • __buf[in] Pointer to the memory region to fill

  • __n – The number of bytes to receive

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid __tc or __buf argument.

xcore/channel.h#

API for channel communications.

Typedefs

typedef streaming_channel_t channel_t#

Helper type for passing around both ends of a channel.

Functions

inline channel_t chan_alloc()#

Allocates a channel by allocating two hardware chan-ends and joining them.

If there are not enough chan-ends available the function returns a channel_t with both fields set to 0.

Note

When the channel_t is no longer required, chan_free() should be called to deallocate it.

Warning

The chan-ends must be accessed on the same tile.

Returns:

The channel_t (both fields will be 0 if allocation was not possible)

inline void chan_free(channel_t __c)#

Deallocate a channel by freeing its constituent chan-ends.

Parameters:
  • __c – channel_t to free

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chanend.

inline void chan_out_word(chanend_t __c, uint32_t __data)#

Output a word over a channel.

Parameters:
  • __c – The chan-end

  • __data – The word to be output

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

inline void chan_out_byte(chanend_t __c, uint8_t __data)#

Output a byte over a channel.

Parameters:
  • __c – The chan-end

  • __data – The byte to be output

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

inline void chan_out_buf_word(chanend_t __c, const uint32_t __buf[], size_t __n)#

Output a block of data over a channel.

Parameters:
  • __c – The chan-end

  • __buf[in] A pointer to the buffer containing the data to send

  • __n – The number of words to send

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

inline void chan_out_buf_byte(chanend_t __c, const uint8_t __buf[], size_t __n)#

Output a block of data over a channel.

Parameters:
  • __c – The chan-end

  • __buf[in] A pointer to the buffer containing the data to send

  • __n – The number of bytes to send

Throws ET_LINK_ERROR:

chan-end destination is not set.

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

inline uint32_t chan_in_word(chanend_t __c)#

Input a word from a channel.

Parameters:
  • __c – The chan-end

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid **data* argument.

Returns:

The word which was read from the channel

inline uint8_t chan_in_byte(chanend_t __c)#

Input a byte from a channel.

Parameters:
  • __c – The chan-end

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid **data* argument.

Returns:

The byte which was read from the channel

inline void chan_in_buf_word(chanend_t __c, uint32_t __buf[], size_t __n)#

Input a block of data from a channel.

Parameters:
  • __c – The chan-end

  • __buf[out] A pointer to the memory region to fill

  • __n – The number of words to receive

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

inline void chan_in_buf_byte(chanend_t __c, uint8_t __buf[], size_t __n)#

Input a block of data from a channel.

Parameters:
  • __c – The chan-end

  • __buf[out] A pointer to the memory region to fill

  • __n – The number of bytes to receive

Throws ET_ILLEGAL_RESOURCE:

not an allocated chan-end, or channel handshaking corrupted.

Throws ET_RESOURCE_DEP:

another core is actively using the chan-end.

Throws ET_LOAD_STORE:

invalid buf[] argument.

xcore/clock.h#

Hardware clock API.

Typedefs

typedef resource_t xclock_t#

Clock handle type.

Functions

inline void clock_enable(xclock_t __id)#

Enables a specified clock block so that it may be used.

Should be called before any other operations are performed on the given id. When the clock is no longer required is should be disabled again with clock_disable().

Parameters:
  • __id – The id of the clock to enable

Throws ET_ILLEGAL_RESOURCE:

not a valid clock.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_disable(xclock_t __clk)#

Disable a clock.

/note Once disabled, a the clock must be re-enabled using clock_enable() before it can be used again.

Parameters:
  • __clk – The clock to be disabled

Throws ET_ILLEGAL_RESOURCE:

not a valid clock.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_start(xclock_t __clk)#

Start a clock.

Parameters:
  • __clk – The clock to start running

Throws ET_ILLEGAL_RESOURCE:

not a valid clock.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_stop(xclock_t __clk)#

Stop a clock.

Waits until the clock is low and then pauses a clock.

Parameters:
  • __clk – The clock to stop

Throws ET_ILLEGAL_RESOURCE:

not a valid clock.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_set_source_port(xclock_t __clk, resource_t __p)#

Configure a clock’s source to a 1-bit port.

A clock can be a 1-bit port, the reference clock or the xCORE clock. Note that if the xCORE clock is used then a non-zero divide must be used for ports to function correctly.

Parameters:
  • __clk – The clock to configure

  • __p – The 1-bit port to set as the clock input. Attempting to set a port which is not 1-bit as the input will cause an exception.

Throws ET_ILLEGAL_RESOURCE:

not a valid clock or port, or the clock is running, or p not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_set_source_clk_ref(xclock_t __clk)#

Configure a clock’s source to be the 100MHz reference clock.

Parameters:
  • __clk – The clock to configure

Throws ET_ILLEGAL_RESOURCE:

not a valid clock, or the clock is running.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_set_source_clk_xcore(xclock_t __clk)#

Configure a clock’s source to be the xCORE clock.

Note

When using the xCORE clock as the clock input a divide of > 0 must be used for the ports to function correclty.

Parameters:
  • __clk – The clock to configure

Throws ET_ILLEGAL_RESOURCE:

not a valid clock, or the clock is running.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_set_divide(xclock_t __clk, uint8_t __divide)#

Configure the divider for a clock.

A clock can divide its input signal by an integer value which this function specifies. The XS2 architecture supports dividing the signal from a 1-bit port while the XS1 architecture will raise a trap if a non-zero divide is used with a 1-bit port input.

If the divide is 0 then the value signal will be passed through the clock. If the value is non-zero then the clock output will be divided by 2*divide.

Warning

If the clock has been started then this will raise a trap.

Parameters:
  • __clk – The clock to configure

  • __divide – The divide value

Throws ET_ILLEGAL_RESOURCE:

not a valid clock, or the clock is running.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

inline void clock_set_ready_src(xclock_t __clk, resource_t __ready_source)#

Sets a clock to use a 1-bit port for the ready-in signal.

If the port is not a 1-bit port then an exception is raised. The ready-in port controls when data is sampled from the pins.

Parameters:
  • __clk – The clock to configure.

  • __ready_source – The 1-bit port to use for the ready-in signal.

Throws ET_ILLEGAL_RESOURCE:

not a valid clock, or ready_source not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing the clock.

xcore/hwtimer.h#

API for using hardware timers to measure and wait time.

Typedefs

typedef resource_t hwtimer_t#

brief Hardware timer handle type.

Functions

inline void hwtimer_free_xc_timer(void)#

Deallcoates the hardware timer automatically allocated.

for xC use. Each logical core is allocated a hardware timer that is multiplexed and used by the xC ‘timer’ interface. This multiplexed timer is not accessible from C. If the logical core is not running any xC code, or any xC code is not making use of the ‘timer’ resource type, the allocated hardware timer may be retrieved for use as a hwtimer_t.

Note

This call must be paired with a call to hwtimer_realloc_xc_timer() prior to the logical core completing its tasks.

Note

The xScope link also requires a hardware timer.

Throws ET_ILLEGAL_RESOURCE:

timer has already been deallocated.

inline void hwtimer_realloc_xc_timer(void)#

Reallcoates a logical core’s xC hardware timer that was.

deallocated by a call to hwtimer_free_xc_timer().

Attention

There must be an available hw timer when this call is made, otherwise a trap will be raised.

Throws ET_ECALL:

no available hw timer, reallocation failed.

inline hwtimer_t hwtimer_alloc(void)#

Allocates a hardware timer.

If there are no timers available then 0 is returned.

Note

When the timer is no longer required, hwtimer_free() should be called to deallocate it.

Returns:

Timer handle to the allocated timer

inline void hwtimer_free(hwtimer_t __t)#

Deallocate a timer.

Parameters:
  • __t – The timer to be freed

Throws ET_ILLEGAL_RESOURCE:

not an allocated timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

inline uint32_t hwtimer_get_time(hwtimer_t __t)#

Get the current time from the timer.

If there is a trigger time setup, the call will stall until after the trigger time. For select and interrupt event, calling hwtimer_get_time() will clear the event.

Parameters:
  • __t – The timer to read

Throws ET_ILLEGAL_RESOURCE:

not an allocated timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

Returns:

The time value (a 32-bit value)

inline uint32_t hwtimer_get_trigger_time(hwtimer_t __t)#

Get the trigger time value.

The trigger time value is set using hwtimer_set_trigger_time(). The trigger may be cleared using hwtimer_clear_trigger_time().

Parameters:
  • __t – The timer whose time value is requested.

Throws ET_ILLEGAL_RESOURCE:

not a valid timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

Returns:

The time value

inline void hwtimer_set_trigger_time(hwtimer_t __t, uint32_t __time)#

Setup an event trigger on a timer.

Note

This will cause hwtimer_get_time() to pause until the specified time. The trigger may be cleared using hwtimer_clear_trigger_time().

Note

hwtimer_wait_until(), hwtimer_delay(), hwtimer_setup_select() and hwtimer_setup_select_callback() call hwtimer_set_trigger_time()

Parameters:
  • __t – The timer to setup a event trigger on.

  • __time – The time at which the timer will trigger an event. The default timer ticks are at a 10ns resolution.

Throws ET_ILLEGAL_RESOURCE:

not a valid timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

inline void hwtimer_change_trigger_time(hwtimer_t __t, uint32_t __time)#

Change the time at which a timer trigger will fire.

This function modifies the time at which a previously setup trigger fires. It is used to set a new trigger time after a select or interrupt event has occurred.

Parameters:
  • __t – The timer to change

  • __time – The time at which the timer will trigger an event. The default timer ticks are at a 10ns resolution.

Throws ET_ILLEGAL_RESOURCE:

not a valid timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

inline void hwtimer_clear_trigger_time(hwtimer_t __t)#

Clear an event trigger on a timer.

Makes sure no triggers are setup on a timer. Should be called when a timer is no longer being used for select and interrupt events.

Parameters:
  • __t – The timer to tear down events on

Throws ET_ILLEGAL_RESOURCE:

not a valid timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

inline uint32_t hwtimer_wait_until(resource_t __t, uint32_t __until)#

Wait until after a specified time.

Attention

This will destroy any select or interrupt event triggers set on this resource.

Parameters:
  • __t – The timer to use for timing

  • __until – The time to wait until

Throws ET_ILLEGAL_RESOURCE:

not an allocated timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

Returns:

The time we actually waited until

inline void hwtimer_delay(resource_t __t, uint32_t __period)#

Delay for a specified time using a specific timer.

Attention

This will destroy any select or interrupt event triggers set on this resource

Parameters:
  • __t – The timer resource to use

  • __period – The amount of time to wait (in reference time ticks, usually 10ns steps)

Throws ET_ILLEGAL_RESOURCE:

not an allocated timer.

Throws ET_RESOURCE_DEP:

another core is actively using the timer.

Throws ET_LOAD_STORE:

invalid **now* argument.

inline int hwtimer_time_after(uint32_t __a, uint32_t __b)#

Compare two timestamps.

Convenience function which checks if a timestamp a is later than another timestamp . Returns a nonzero value if a occurs after b, or zero otherwise. Returns 0 if a and b are equal.

Note

Timestamps have a limited range and can overflow and wrap to 0 (hence they cannot be compared trivially). A timestamp is considered ‘after’ another one if it is ahead by no more than half the range of a hwtimer.

Note

Equivalent to XC’s timeafter from xs1.h

Parameters:
  • __a – Timestamp to compare to __b

  • __b – Reference timestamp

inline uint32_t get_reference_time(void)#

get the chip reference time

Gets the current reference time without requiring an allocated timer on chips where a reference time is available. This can be tested with LIBXCORE_HWTIMER_HAS_REFERENCE_TIME which will be defined if and only if a refence time is available. If no reference time is available then 0 is returned.

Returns:

The reference time

xcore/interrupt_wrappers.h#

Helpers for implementing interrupt-enabled functions.

Defines

LIBXCORE_KSTACK_WORDS#

Specify the minimum kernel stack size the interrupt permitting function should create.

The user may specify a minimum kstack size by setting the LIBXCORE_KSTACK_WORDS define in their Makefile. This should be done when the kstack is being used by more than interrupt_callback_t functions.

DEFINE_INTERRUPT_PERMITTED(__group, __ret, __root_function, ...)#

Define a function that allows interrupts to occur within its scope.

This macro will define two functions for you:

  • An ordinary function that may be called directly Its signature will be ( ... )

  • A function that will also reserve space for and set up a stack for handling interrupts. The function name is accessed using the INTERRUPT_PERMITTED() macro

You would normally use this macro on the definition of the root function which will be called in a par statement. The interrupt stack (kernel stack) is created on the core’s stack with the ksp and sp being modified as necessary. When the functions exits, neither the kernel stack nor ksp is valid.

The kernel stack allocated has enough space for the interrupt_callback_t function (+callees) in the given group. The use of the group identifier allows a kernel stack to be no larger than that required by its greediest member.

The user may specify a larger kernel stack by defining LIBXCORE_KSTACK_WORDS.

Example usage:

DEFINE_INTERRUPT_PERMITTED(groupA, int, rootfunc, chanend c, int i)
{
  // This is the body of 'int rootfunc(chanend c, int i)'
}

Warning

The kernel stack is not re-entrant so kernel mode must not be masked from within an interrupt_callback_t

Parameters:
  • __group – this is the group of interrupt_callback_t function that may be safely enabled - see DEFINE_INTERRUPT_CALLBACK()

  • __ret – the return type of the ordinary function; the return type must be a non-union, non-aggregate type not larger than int

  • __root_function – the name of the ordinary function

  • ... – the arguments of the ordinary function; there may be no more than 4 parameters, and they must each have non-union, non-aggregate type not larger than int

DECLARE_INTERRUPT_PERMITTED(__ret, __root_function, ...)#

Declare an interrupt permitting function.

Use this macro when you require a declaration of your interrupt permitting function types

Example usage:

// In another file:
//   DEFINE_INTERRUPT_PERMITTED(groupA, int, rootfunc, chanend c, int i)
//   DEFINE_INTERRUPT_PERMITTED(groupB, void, anotherfunc, void)
DECLARE_INTERRUPT_PERMITTED(int, rootfunc, chanend c, int i);
DECLARE_INTERRUPT_PERMITTED(void, anotherfunc, void);
...
  par {
      int ret = INTERRUPT_PERMITTED(rootfunc)(c,i);  // kstack for groupA.
      INTERRUPT_PERMITTED(anotherfunc)();  // kstack for groupB.

Parameters:
  • __ret – the return type of the ordinary function

  • __root_function – the name of the ordinary function; the return type must be a non-union, non-aggregate type not larger than int

  • ... – the arguments of the ordinary function; there may be no more than 4 parameters, and they must each have non-union, non-aggregate type not larger than int

INTERRUPT_PERMITTED(__root_function)#

The name of the defined interrupt permitting function.

Use this macro for retriving the name of the declared interrupt function. This is the name used to invoke the function.

Returns:

the name of the defined interrupt permitting function

DEFINE_INTERRUPT_CALLBACK(__group, __intrpt, __data)#

Define an interrupt handling function.

This macro will define two functions for you:

  • An ordinary function that may be called directly Its signature will be void ( void* )

  • An interrupt_callback_t function for passing to a res_setup_interrupt_callback function. The interrupt_callback_t function name is accessed using the INTERRUPT_CALLBACK() macro

Example usage:

DEFINE_INTERRUPT_CALLBACK(groupA, myfunc, arg)
{
  // This is the body of 'void myfunc(void* arg)'
}

Warning

The kernel stack is not re-entrant so kernel mode must not be masked from within an interrupt_callback_t

Parameters:
  • __group – the group of interrupt_callback_t function we belong to see DEFINE_INTERRUPT_PERMITTED()

  • __intrpt – this is the name of the ordinary function

  • __data – the name to use for the void* argument

DECLARE_INTERRUPT_CALLBACK(__intrpt, __data)#

Declare an interrupt handling function.

Use this macro when you require a declaration of your interrupt function types

Example usage:

DECLARE_INTERRUPT_CALLBACK(myfunc, arg);
chanend_setup_interrupt_callback(c, 0 , INTERRUPT_CALLBACK(myfunc));

Parameters:
  • __intrpt – this is the name of the ordinary function

  • __data – the name to use for the void* argument

INTERRUPT_CALLBACK(__intrpt)#

The name of the defined interrupt_callback_t function.

Use this macro for retriving the name of the declared interrupt callback function. This is the name that is passed to *_setup_interrupt_callback() for registration.

Returns:

the name of the defined interrupt_callback_t function

xcore/interrupt.h#

API for configuring interrupts.

Functions

inline void interrupt_mask_all(void)#

Mask all interrupts on this logical core.

Prevent any enabled triggerable_setup_interrupt_callback() functions from triggering. This has no effect on TRIGGERABLE_SETUP_EVENT_VECTOR() triggering. They can be restored by using interrupt_unmask_all().

inline void interrupt_unmask_all(void)#

Unmask all interrupts on this logical core.

Allow triggerable_setup_interrupt_callback() functions to trigger. They can be suppressed by using interrupt_mask_all().

xcore/lock.h#

provides hardware-based locking

Typedefs

typedef resource_t lock_t#

Hardware lock handle type.

Functions

inline lock_t lock_alloc()#

Allocates a lock.

If there are no locks availble the function returns 0.

Note

When the lock is no longer required, lock_free() must be called to deallocate it.

Returns:

handle for the allocated lock, 0 is no locks were available

inline void lock_free(lock_t __l)#

Deallocates a given lock.

The lock must be released prior to calling this function.

Parameters:
  • __l – The lock_t to be freed

Throws ET_ILLEGAL_RESOURCE:

not an allocated lock, or the lock has not been released.

Throws ET_RESOURCE_DEP:

another core is actively changing the lock.

Throws ET_LOAD_STORE:

invalid l argument.

inline void lock_acquire(lock_t __l)#

Acquire a lock.

Only one core at a time can acquire a lock. This provides a hardware mutex which have very low overheads. If another thread has already acquired this lock then this function will pause until the lock is released and this core becomes the owner.

Parameters:
  • __l – The lock_t to acquire

Throws ET_ILLEGAL_RESOURCE:

not an allocated lock.

Throws ET_RESOURCE_DEP:

another core is actively changing the lock.

inline void lock_release(lock_t __l)#

Release a lock.

Releases the lock and allocates the next owner from the list of waiting cores in round-robin manner.

Note

There are no checks that the core releasing the lock is the current owner.

Parameters:
  • __l – The lock_t to use release

Throws ET_ILLEGAL_RESOURCE:

not an allocated lock.

Throws ET_RESOURCE_DEP:

another core is actively changing the lock.

xcore/minicache.h#

Cache maintenance interface for the XS3 MiniCache.

The minicache is fully associative and consists of a small number of naturally aligned lines. The minicache caches all reads and writes to and from software memory and external RAM. A single read or write can cause up to two lines to be filled or evicted (in the case that the address range affected spans multiple lines). When there are insufficient lines free to service a fill then allocated lines will be evicted, up to the number of lines to be filled. Evicted lines are chosen based a ‘psuedo leaast recently used’ algorithm.

Flush and invlidate operations queue until the cache is idle (i.e. until all ongoing fills and evicts have finished). During this wait, and whilst the operation completes, all new loads and stores through the cache will block.

This header is only available when targeting platforms with a compatible cache.

Functions

inline void minicache_prefetch(volatile const void *__address)#

Prefetch an address into the cache without blocking.

Begins filling a cache line corresponding to the given __address. The address must be word-aligned and within a read-enabled region. If the region is an ‘uncached’ one (e.g. RAM) then this has no effect. If the address is cache line-aligned then a single line will be filled, otherwise the line corresponding to the address will be prefetched and additionally the next line in the address space (if such a line would have a valid address).

For each line prefetched:

  • If the address is already in the cache then no action is taken;

  • Otherwise, a fill is started for that line;

  • If there is not an available (unallocated) cache line, then an allocated one will be evicted before the fill can begin.

Prefetching an address is non-blocking even if it causes a fill and/or eviction.

If the address does not correspond to a valid region, is not word aligned, or is within a region for which filling is disabled then a trap will occur.

Parameters:
  • __address – The address to prefetch

inline void minicache_flush(void)#

Flush all dirty data in the cache back to its respective memory.

Sets a flush operation waiting on the cache. This will wait for all ongoing fills and then write all dirty lines back to their respective memories. The data remains in the cache, however its dirty state is cleared. During the flush operation (and whilst waiting to start it) all access to cached memory is blocking.

Note

If an invalidate operation is already waiting when a flush is queued, it is unspecified which will execute first.

inline void minicache_invalidate(void)#

Invalidates all data in the cache.

Sets an invalidate operation waiting on the cache. This will mark all cache lines invalid - meaning that any unflushed writes are effectively reversed.

/note If a flush is queued before an invlidate has completed it is unspecified which will execute first.

/warning This may cause the observed value at a cached address to change.

xcore/parallel.h#

Helper macros for fork/join style parallel execution.

Defines

PAR_FUNCS(...)#

Calls a list of void (void*) functions with each utilising a different hardware thread.

Expands to a block which evaluates each of the given function call descriptions such that each runs in a different thread. For each PFUNC, a stack will be allocated from the current stack and used to call FUNCTION with ARGUMENT

as its sole argument. The block is blocking until all function calls have returned.

There must be at least enough unallocated logical cores to execute each PFUNC in its own thread, including the current thread as one available logical core.

Example:

PAR_FUNCS(PFUNC(my_print_function, "Hello 1"),
          PFUNC(my_print_function, "Hello 2"));

See also

PFUNC

Note

One function call will be evaluated in the current thread.

Parameters:
  • ... – Functions to call, each the result of expanding PFUNC

PFUNC(_FUNCTION, _ARGUMENT)#

Specifies a parallelised function call.

Expands to a function call description which can be used as an argument to PAR_FUNCS.

See also

PAR_FUNCS

Parameters:
  • _FUNCTION – a function with signature void (void *)

  • _ARGUMENT – the argument to pass to _FUNCTION - must be implicitly convertible to void *

DECLARE_JOB(_NAME, _ARG_TYPES_PACK)#

Declare a void function with arbitrary parameters which can be dispatched in another thread.

Expands to the declaration of a function named _NAME

and additional definitions required to execute that function in a different thread.

The

_ARG_TYPES_PACK parameter must be a comma-separated sequence of permitted types; permitted types may be:
  • A type specifier with optional qualification (e.g. int, const unsigned, enum my_enum). In the case of an enum, union or struct a declaration list must not be included.

  • An (optionally qualified) pointer to a permitted type.

All parameter types must be complete at the point where DECLARE_JOB() is expanded, unless the first parameter type is void in which case this must be the only parameter and the parameter pack must be exactly (void) (i.e. an alias of void must not be used).

Example:

DECLARE_JOB(thread_sum, (const unsigned *, size_t, unsigned long *));
void thread_sum(const unsigned * const ints, const size_t number, unsigned long * const result) {
  unsigned long sum = 0;
  for (size_t i = 0; i < number; i += 1) { sum += ints[i]; }
  *result = sum;
}

See also

Note

These restrictions mean that array types and pointer-to-function types may not appear in a parameter pack. However, typedefs of these types are allowed.

Parameters:
  • _NAME – Name of function to declare

  • _ARG_TYPES_PACK – A pack of type specifiers which form the parameter part of the function signature (must not include names)

PAR_JOBS(...)#

Calls, in parallel, a list of functions declared using DECLARE_JOB.

Expands to a block which executes each of the given function call specifications such that each call takes place in a different hardware thread. Each call specification should be the result of expanding PJOB and the FUNCTION should be one which was declared using DECLARE_JOB. Each thread’s stack will be allocated from the current stack. Each function will execute as if FUNCTION ARGPACK

; had been executed in its assigned thread. The block is blocking until all functions have returned.

There must be at least enough unallocated logical cores to execute each PJOB in its own thread, including the current thread as one available logical core.

Example:

unsigned long sum1, sum2;
PAR_JOBS(PJOB(thread_sum, (ints1, ints1_length, &sum1)),
         PJOB(thread_sum, (ints2, ints2_length, &sum2)));

See also

Note

One function call will be evaluated in the current thread.

Parameters:
  • ... – Function call specifications as expanded from PJOB.

PJOB(_FUNCTION, _ARGPACK)#

Specifies a parallelised call of a function declared with DECLARE_JOB.

Expands to a function call description which can be used as an argument to PAR_JOBS.

Parameters:
  • _FUNCTION – a function which was declared using DECLARE_JOB

  • _ARGPACK – pack of the arguments to pass to _FUNCTION - each must be implicitly convertible to its respective parameter type. E.g. (5, NULL) for void(int, int *)

PAR_SYNC#

Job parameter macro to access the respective thread’s synchronizer.

When expanded as a parameter to PJOB as part of a PAR_JOBS expansion, expands to a value compatible with synchronizer_t which represents that thread’s synchronizer handle. This can be used to synchronise all threads in the PAR_JOBS when used with par_jobs_synchronize .

Note

As synchronization affects all threads in the enclosing PAR_JOBS, it is never useful for any PJOB in a PAR_JOBS to include a PAR_SYNC parameter unless all PJOBs in that PAR_JOBS do so.

Warning

Accessing the synchroniser forces allocation of a hardware synchroniser resource, even if one would not ordinarily be required. This means that a PAR_JOBS expansion with only a single PJOB will require a hardware synchroniser if that PJOB is passed PAR_SYNC. This can potentially lead to synchroniser exhaustion. Note that par_jobs_synchronize has no observable effect if there is only one thread in the group.

Typedefs

typedef resource_t synchronizer_t#

Synchronizer handle which may be used to explicitly synchronise jobs executed by PAR_JOBS.

Note

The synchronizer handles for each thread in a PAR_JOBS are neither guaranteed to compare equal nor non-equal to other handles, regardless of whether they are participating in the same PAR_JOBS.

Warning

Synchronizer handles are not portable between threads; they are meaningful only within the thread to which they are originally passed by a PAR_JOBS expansion.

Functions

inline void par_jobs_synchronize(const synchronizer_t __s)#

Synchronise all threads in a PAR_JOBS.

When passed a value of type synchronizer_t, as obtained using PAR_SYNC as a parameter to the PAR_JOBS which started the current thread, blocks until all threads started by that PAR_JOBS call par_jobs_synchronize with their respective synchronizer_t values. If all other threads started by the PAR_JOBS are already blocking in a call to par_jobs_synchronize then causes all of those threads to return from those calls, and returns immediately.

If the synchronizer passed was not obtained by expanding PAR_SYNC in the parameter pack of the PJOB expansion relating to the calling thread, the behaviour is undefined. That is, synchronizers must not be passed between threads, including to child threads.

If any thread calls par_jobs_synchronize when any other job in the respective PAR_JOBS has already returned, or if any job returns whilst another job in its respective PAR_JOBS is blocked on a call to par_jobs_synchronize, then the behaviour is undefined. Effectively, each job in a PAR_JOBS expansion must call par_jobs_synchronize the same number of times

Parameters:
  • __s – The synchronizer handle for this thread

xcore/port_protocol.h#

Helper functions for port usage patterns.

Functions

inline void port_protocol_in_handshake(port_t __p, port_t __readyin, port_t __readyout, xclock_t __clk)#

Configure a port to be a clocked input port in handshake mode.

If the ready-in or ready-out ports are not 1-bit ports, an exception is raised. The ready-out port is asserted on the falling edge of the clock when the port’s buffer is not full. The port samples its pins on its sampling edge when both the ready-in and ready-out ports are asserted.

By default the port’s sampling edge is the rising edge of clock. This can be changed by the function port_set_sample_falling_edge().

Note

A handshaken port must be buffered, so this function will also make the port buffered.

Parameters:
  • __p – The port to configure

  • __readyin – A 1-bit port to use for the ready-in signal

  • __readyout – A 1-bit port to use for the ready-out signal

  • __clk – The clock used to configure the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock or clock is running, or readyin/readyout not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing a port/clock

inline void port_protocol_out_handshake(port_t __p, port_t __readyin, port_t __readyout, xclock_t __clk, uint32_t __initial)#

Configures a port to be a clocked output port in handshake mode.

If the ready-in or ready-out ports are not 1-bit ports an exception is raised. the port drives the initial value on its pins until an output statement changes the value driven.

The ready-in port is read on the sampling edge of the port. outputs are driven on the next falling edge of the clock where the previous value read from the ready-in port was high.

On the falling edge of the clock the ready-out port is driven high if data is output on that edge, otherwise it is driven low.

By default the port’s sampling edge is the rising edge of clock. this can be changed by the function port_set_sample_falling_edge().

Note

A handshaken port must be buffered, so this function will also make the port buffered.

Parameters:
  • __p – the port to configure

  • __readyin – a 1-bit port to use for the ready-in signal

  • __readyout – a 1-bit port to use for the ready-out signal

  • __clk – the clock used to configure the port

  • __initial – the initial value to output on the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock or clock is running, or readyin/readyout not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing a port/clock

inline void port_protocol_in_strobed_master(port_t __p, port_t __readyout, xclock_t __clk)#

Configures a port to be a clocked input port in strobed master mode.

If the ready-out port is not a 1-bit port, an exception is raised. the ready-out port is asserted on the falling edge of the clock when the port’s buffer is not full. the port samples its pins on its sampling edge after the ready-out port is asserted.

By default the port’s sampling edge is the rising edge of clock. this can be changed by the function set_port_sample_delay().

Note

A strobed port must be buffered, so this function will also make the port buffered.

Parameters:
  • __p – the port to configure

  • __readyout – a 1-bit port to use for the ready-out signal

  • __clk – the clock used to configure the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock or clock is running, or readyout not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing a port/clock

inline void port_protocol_out_strobed_master(port_t __p, port_t __readyout, xclock_t __clk, uint32_t __initial)#

Configures a port to be a clocked output port in strobed master mode.

If the ready-out port is not a 1-bit port, an exception is raised. the port drives the initial value on its pins until an output statement changes the value driven. outputs are driven on the next falling edge of the clock. on the falling edge of the clock the ready-out port is driven high if data is output on that edge, otherwise it is driven low.

Note

A strobed port must be buffered, so this function will also make the port buffered.

Parameters:
  • __p – the port to configure

  • __readyout – a 1-bit port to use for the ready-out signal

  • __clk – the clock used to configure the port

  • __initial – the initial value to output on the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock or clock is running, or readyout not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing a port/clock

inline void port_protocol_in_strobed_slave(port_t __p, port_t __readyin, xclock_t __clk)#

Configures a port to be a clocked input port in strobed slave mode.

If the ready-in port is not a 1-bit port, an exception is raised. the port samples its pins on its sampling edge when the ready-in signal is high. by default the port’s sampling edge is the rising edge of clock. this can be changed by the function set_port_sample_delay().

Note

A strobed port must be buffered, so this function will also make the port buffered.

Parameters:
  • __p – the port to configure

  • __readyin – a 1-bit port to use for the ready-in signal

  • __clk – the clock used to configure the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock or clock is running, or readyin not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing a port/clock

inline void port_protocol_out_strobed_slave(port_t __p, port_t __readyin, xclock_t __clk, uint32_t __initial)#

Configures a port to be a clocked output port in strobed slave mode.

If the ready-in port is not a 1-bit port, an exception is raised. the port drives the initial value on its pins until an output statement changes the value driven. the ready-in port is read on the port’s sampling edge. outputs are driven on the next falling edge of the clock where the previous value read from the ready-in port is high. by default the port’s sampling edge is the rising edge of clock. this can be changed by the function set_port_sample_delay().

Note

A strobed port must be buffered, so this function will also make the port buffered.

Parameters:
  • __p – the port to configure

  • __readyin – a 1-bit port to use for the ready-in signal

  • __clk – the clock used to configure the port

  • __initial – the initial value to output on the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock or clock is running, or readyin not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing a port/clock

xcore/port.h#

API for IO using ports.

Defines

PORT_TIMESTAMP_MIN#

Lowest legal value for a port timestamp.

PORT_TIMESTAMP_MAX#

Largest legal value for a port timestamp.

Typedefs

typedef resource_t port_t#

Port handle type.

typedef uint32_t port_timestamp_t#

Integer type capable of holding all possible values of a port timestamp.

Note

The actual valid range of timestamps is given by PORT_TIMESTAMP_MIN and PORT_TIMESTAMP_MAX which are the lowest and highest valid timestamps respectively.

Enums

enum port_type_t#

Enumeration to declare how the port was set up.

Values:

enumerator PORT_UNBUFFERED#
enumerator PORT_BUFFERED#

Functions

inline void port_enable(port_t __p)#

Enables a port.

Either this function or port_start_buffered() must be called once for each variable of type port before use. port_disable() must be called afterwards.

The port’s state is set to: input, unbuffered, inout_data, no_invert, rising_edge, master, no_ready, no triggers, clocked by XS1_CLKBLK_REF.

See also

port_enable_buffered

Parameters:
  • __p – The port to enable

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_reset(port_t __p)#

Reset a port.

Clears a ports settings back to the default state at port_enable().

Parameters:
  • __p – The port to be reset

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_start_buffered(port_t __p, size_t __transfer_width)#

Allocates a port to buffer and serialise/deserialise data.

Either this function or port_enable() must be called once for each port_t before it is used.

See also

port_enable

Parameters:
  • __p – Value that identifies which port to drive

  • __transfer_width – Number of bits to serialise; must be 1, 4, 8, or 32. The number of bits must be >= to the physical port width.

Throws ET_ILLEGAL_RESOURCE:

not a valid port, or is not legal width for the port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_disable(port_t __p)#

Disable a port.

Disables the port so it is no longer ready for use. It must be re-enabled if it is used again.

Parameters:
  • __p – The port to be disabled

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_transfer_width(port_t __p, size_t __transfer_width)#

Change the transfer width of a port.

The default transfer width is the same as the physical port width.

Attention

A port must have been set to buffered if the width is different from the physical port width

Parameters:
  • __p – The port to change the transfer width of

  • __transfer_width – Number of bits to serialise; must be 1, 4, 8, or 32. The number of bits must be >= to the physical port width.

Throws ET_ILLEGAL_RESOURCE:

not a valid port, or is not legal width for the port, or the port is unbuffered.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_buffered(port_t __p)#

Sets a port to be buffered.

Configures a port into buffered mode where it can automatically serialise or deserialise data.

Parameters:
  • __p – The port to set as buffered

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_unbuffered(port_t __p)#

Sets a port to be unbuffered (default state).

Configures a port into unbuffered mode. Note that before this is called, a a port needs to have its transfer width equal to the port width and be configured as a master port.

Parameters:
  • __p – The port to set as unbuffered

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_write_control_word(port_t __p, uint32_t __word)#

Configure the port with a platform-specific value.

Uses the value of __word to configure the port. The effect of this is platform dependent.

Parameters:
  • __p – The port to configure

  • __word – The config word to set on the port

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port or __word is not valid

inline void port_set_clock(port_t __p, xclock_t __clk)#

Set the clock clocking a port.

Changes the clock used for a port’s control functions. The default clock is XS1_CLKBLK_REF.

Parameters:
  • __p – Port whose clock is being changed.

  • __clk – Clock to attach to the port.

Throws ET_ILLEGAL_RESOURCE:

not a valid port/clock, or clock is running.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_inout_data(port_t __p)#

Set a port drive out the data value (default state).

Parameters:
  • __p – Port to change the mode of.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_out_clock(port_t __p)#

Set a port to drive out its clocking signal.

Configures the port to drive the clock signal instead of its own data values. The clock signal that is driven out is configured using the port_set_clock() function.

Parameters:
  • __p – Port to change the mode of.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_out_ready(port_t __p, port_t __ready_source)#

Set a port to drive out the ready signal of another port.

Configures the port to drive the ready signal of another port instead of its own data values.

Parameters:
  • __p – Port to change the mode of. This must be a 1-bit port or this function will trap.

  • __ready_source – The port whose ready signal will be output.

Throws ET_ILLEGAL_RESOURCE:

  • not a valid port

  • p not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_invert(port_t __p)#

Set the port to invert its data.

Configures a port to invert the data on the pin. This can be reverted by calling port_set_no_invert().

Parameters:
  • __p – Port to set its data to be inverted. This must be a 1-bit port or a trap will be raised.

Throws ET_ILLEGAL_RESOURCE:

  • not a valid port

  • p not a one bit port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_no_invert(port_t __p)#

Set the port to not invert its data (default state).

Configures a port to not invert the data on the pin.

Parameters:
  • __p – Port to set the data to not be inverted.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_sample_falling_edge(port_t __p)#

Set the port to sample on the falling edge.

The default is for a port to sample data on the rising edge of the clock. This function changes the port to sample on the falling edge instead. This change can be reverted by calling port_set_sample_rising_edge().

Parameters:
  • __p – Port to change its sampling edge.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_sample_rising_edge(port_t __p)#

Set the port to sample on the rising edge (default state).

Restores a port to sampling data on the rising edge of the clock.

Parameters:
  • __p – Port to change its sampling edge.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_master(port_t __p)#

Set the port to master mode (default state).

Configures a port to be a master. This is only relevant when using ready signals (port_set_ready_strobed() / port_set_ready_handshake()).

See also

xcore/port_protocol.h

Note

It is highly recommended to use the port_protocol_* functions to put a port into its desired mode as the order of operations is critical.

Parameters:
  • __p – Port to set as a master

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_slave(port_t __p)#

Set the port to slave mode.

Configures a port to be a master. This is only relevant when using a ready strobe (port_set_ready_strobed())

See also

xcore/port_protocol.h

Attention

the port must be set to use a ready strobe, otherwise this function will raise an exception.

Note

It is highly recommended to use the port_protocol_* functions to put a port into its desired mode as the order of operations is critical.

Parameters:
  • __p – Port to set as a slave

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_no_ready(port_t __p)#

Set the port to use no ready signals (default state).

Changes a port to not use ready signals. A port can be configured to use strobes or handshaking signals using port_set_ready_strobed() or port_set_ready_handshake().

See also

xcore/port_protocol.h

Attention

the port must be a master port otherwise this function will raise an exception.

Note

It is highly recommended to use the port_protocol_* functions to put a port into its desired mode as the order of operations is critical.

Parameters:
  • __p – Port to change to not use ready signals

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_ready_strobed(port_t __p)#

Set the port to use a single strobe.

Changes a port to not use ready signals. A port can be configured to use strobes or handshaking signals using port_set_ready_strobed() or port_set_ready_handshake().

See also

xcore/port_protocol.h

Attention

the port must be a buffered port otherwise this function will raise an exception.

Note

It is highly recommended to use the port_protocol_* functions to put a port into its desired mode as the order of operations is critical.

Parameters:
  • __p – Port to change to not use ready signals

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_ready_handshake(port_t __p)#

Set the port to be fully handshaken.

Changes a port to use both a ready input and drive a ready output in order to control when data is sampled or written.

See also

xcore/port_protocol.h

Attention

the port must be a master buffered port otherwise this function will raise an exception.

Note

It is highly recommended to use the port_protocol_* functions to put a port into its desired mode as the order of operations is critical.

Parameters:
  • __p – Port to change to not use ready signals

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline port_timestamp_t port_get_trigger_time(port_t __p)#

Gets the timestamp of the last input or output operation on a port.

Note

The returned timestamp will be a valid timestamp no less than PORT_TIMESTAMP_MIN and no greater than PORT_TIMESTAMP_MAX.

Parameters:
  • __p – The port to get the timestamp from

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The timestamp of the last operation

inline void port_set_trigger_time(port_t __p, port_timestamp_t __t)#

Set the timestamp at which the port will input/output data.

Sets the time condition for the next input or output on a port. If the port is unbuffered or the buffer is empty/full a call to port_in() or port_out() will pause until the specified time. The trigger is cleared by a input/output or by calling port_clear_trigger_time(). The given timestamp must be a valid port timestamp no less than PORT_TIMESTAMP_MIN and no greater than PORT_TIMESTAMP_MAX.

Parameters:
  • __p – The port to set the condition on

  • __t – The port timestamp to match

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively using the port.

inline void port_clear_trigger_time(port_t __p)#

Clear the timestamp trigger on a port.

Clears any trigger_time condition on the port so the next input or output will happen unconditionally in respect to the timestamp. This function does not clear the trigger_in condition on the port.

Parameters:
  • __p – The port to clear the trigger_time on

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_trigger_in_equal(port_t __p, uint32_t __v)#

Setup an event to trigger on a port when its input value matches.

On a unbuffered port the trigger will apply to all future inputs until the trigger is set again. On an buffered port the trigger will only hold for the next input after which the trigger_in_equal will be cleared.

Parameters:
  • __p – The port to set the trigger on

  • __v – The value to match

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_set_trigger_in_not_equal(port_t __p, uint32_t __v)#

Setup an event to trigger on a port when its input value does not matches.

On a unbuffered port the trigger will apply to all future inputs until the trigger is set again. On an buffered port the trigger will only hold for the next input after which the trigger_in_not_equal will be cleared.

Parameters:
  • __p – The port to set the trigger on

  • __v – The value to not match

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline void port_clear_trigger_in(port_t __p)#

Clear the in trigger on a port.

Clears any trigger_in condition on the port so the next input will happen unconditionally in respect to the input value. This function does not clear the trigger_time condition on the port.

Parameters:
  • __p – The port to clear the trigger_in on

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline uint32_t port_peek(port_t __p)#

Peek at the value on a port.

Peeking a port returns the current value on the pins of a port, regardless of whether the port is an output or input and without affecting its direciton. Peek will not pause, regardless of any triggers that have been set.

Parameters:
  • __p – Port to be peeked

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Returns:

The current value on the pins

inline void port_out(port_t __p, uint32_t __data)#

Outputs a value onto a port.

In the case of an unbuffered port, the value will be driven on the pins on the next clock cycle. In the case of a buffered port, the data will be stored in the buffer, and be serialised onto the output pins.

If there is a time trigger setup and the port is unbuffered or the buffer is full the call will pause until the specified time.

Parameters:
  • __p – Port to output to

  • __data – Value to output

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline uint32_t port_in(port_t __p)#

Input a value from a port.

For unbuffered port with no trigger, the data will be whatever is on the input pins. For unbuffered port with a trigger, the data will be the value read when the trigger fired. The call will pause if the trigger has not yet fired. For buffered port, this function will pause until the buffer is filled up with deserialised data.

Parameters:
  • __p – Port to input from

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The inputted data

inline uint32_t port_out_shift_right(port_t __p, uint32_t __data)#

Outputs a value onto a port and shift the output data.

In the case of an unbuffered port, the value will be driven on the pins on the next clock cycle. In the case of a buffered port, the data will be stored in the buffer, and be serialised onto the output pins.

If there is a time trigger setup and the port is unbuffered or the buffer is full the call will pause until the specified time.

Parameters:
  • __p – Port to output to

  • __datadata is shifted right by the transfer width of the port, with the bits shifting out onto the port.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The remaining shifted bits of data

inline uint32_t port_in_shift_right(port_t __p, uint32_t __data)#

Input a value from a port and shift the data.

For unbuffered port with no trigger, the data will be whatever is on the input pins. For unbuffered port with a trigger, the data will be the value read when the trigger fired. The call will pause if the trigger has not yet fired. For buffered port, this function will pause until the buffer is filled up with deserialised data.

Parameters:
  • __p – Port to input from

  • __data – Initial value to shift input data into

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

Result of shifting data right by the port width and storing the input data in the most significant bits

inline void port_out_at_time(port_t __p, port_timestamp_t __t, uint32_t __data)#

Outputs a value onto a port at a specified port timestamp.

In the case of an unbuffered port, the value will be driven on the pins when on the clock cycle that moves the port timestamp to the specified time. In the case of a buffered port, the data will be stored in the buffer, and be serialised onto the output pins at the point that the time is reached. The given timestamp must be a valid port timestamp no less than PORT_TIMESTAMP_MIN and no greater than PORT_TIMESTAMP_MAX.

Parameters:
  • __p – Port to output to

  • __t – The timestamp to do the output on

  • __data – Value to output

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline uint32_t port_in_at_time(port_t __p, port_timestamp_t __t)#

Input data from a port when its counter is at a specific time.

In the case of an unbuffered port, the data will be inputted when the counter reaches time t. In the case of a buffered port, an input will wait until the given time and then will start capturing data, returning a value when the buffer is full. The given timestamp must be a valid port timestamp no less than PORT_TIMESTAMP_MIN and no greater than PORT_TIMESTAMP_MAX.

Parameters:
  • __p – Port to input from

  • __t – The timestamp to do input on

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The inputted data

inline uint32_t port_out_shift_right_at_time(port_t __p, port_timestamp_t __t, uint32_t __data)#

Outputs a value onto a port at a specified time and shifts the output data.

In the case of an unbuffered port, the value will be driven on the pins when on the clock cycle that moves the port counter to the specified time. In the case of a buffered port, the data will be stored in the buffer, and be serialised onto the output pins at the point that the time is reached. The given timestamp must be a valid port timestamp no less than PORT_TIMESTAMP_MIN and no greater than PORT_TIMESTAMP_MAX.

Parameters:
  • __p – Port to output to

  • __t – The timestamp of the output

  • __data – data is shifted right by the transfer width of the port, with the bits shifting out onto the port.

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The remaining shifted bits

inline uint32_t port_in_shift_right_at_time(port_t __p, port_timestamp_t __t, uint32_t __data)#

Input data from a port at a specific time and shift the data.

In the case of an unbuffered port, the data will be inputted when the counter reaches time t. In the case of a buffered port, an input will wait until the given time and then will start capturing data, returning a value when the buffer is full. The given timestamp must be a valid port timestamp no less than PORT_TIMESTAMP_MIN and no greater than PORT_TIMESTAMP_MAX.

Parameters:
  • __p – Port to input from

  • __t – The timestamp to do input on

  • __data – Initial value to shift input data into

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

Result of shifting data right by the port width and storing the input data in the most significant bits

inline uint32_t port_in_when_pinseq(port_t __p, port_type_t __pt, uint32_t __value)#

Input data from a port when its pins match a specific value.

In the case of an unbuffered port, the data inputted be identical to the value. In the case of a buffered port, an input will wait until the value appears on the pins and then return that value and some previous values that have been deserialised.

Parameters:
  • __p – Port to input from

  • __pt – If port is buffered or unbuffered.

  • __value – The value to match against the pins

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The inputted data

inline uint32_t port_in_when_pinsneq(port_t __p, port_type_t __pt, uint32_t __value)#

Input data from a port when its pins do not match a specific value.

In the case of an unbuffered port, the inputted data will be the non-matching pin values. In the case of a buffered port, this function will wait until a non matching value appears on the pins, and then return that value and previous values that have been deserialised.

Parameters:
  • __p – Port to input from

  • __pt – If port is buffered or unbuffered.

  • __value – The value to match against the pins

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The inputted data

inline uint32_t port_in_shift_right_when_pinseq(port_t __p, port_type_t __pt, uint32_t __value, uint32_t __data)#

Input data from a port when its pins match a specific value and shift the data.

In the case of an unbuffered port, the data inputted be identical to the value. In the case of a buffered port, an input will wait until the value appears on the pins and then return that value and some previous values that have been deserialised.

Parameters:
  • __p – Port to input from

  • __pt – If port is buffered or unbuffered.

  • __value – The value to match against the pins

  • __data – Initial value to shift input data into

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

Result of shifting data right by the port width and storing the input data in the most significant bits

inline uint32_t port_in_shift_right_when_pinsneq(port_t __p, port_type_t __pt, uint32_t __value, uint32_t __data)#

Input data from a port when its pins do not match a specific value and shift the data.

In the case of an unbuffered port, the inputted data will be the non-matching pin values. In the case of a buffered port, this macro will wait until a non matching value appears on the pins, and then return that value and previous values that have been deserialised.

Parameters:
  • __p – Port to input from

  • __pt – If port is buffered or unbuffered.

  • __value – The value to match against the pins

  • __data – Initial value to shift input data into

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

Result of shifting data right by the port width and storing the input data in the most significant bits

inline void port_clear_buffer(port_t __p)#

Clears the buffer used by a port.

Any data sampled by the port which has not been input by the processor is discarded. Any data output by the processor which has not been driven by the port is discarded. If the port is in the process of serialising output, it is interrupted immediately. If a pending output would have caused a change in direction of the port then that change of direction does not take place. If the port is driving a value on its pins when this function is called then it continues to drive the value until an output statement changes the value driven.

Parameters:
  • __p – The port whose buffer is to be cleared

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

inline size_t port_endin(port_t __p)#

Ends the current input on a buffered port.

The number of bits sampled by the port but not yet input by the processor is returned. This count includes both data in the transfer register and data in the shift register used for deserialisation. Subsequent inputs on the port return transfer-width bits of data until there is less than one transfer-width bits of data remaining. Any remaining data can be read with one further input, which returns transfer-width bits of data with the remaining buffered data in the most significant bits of this value.

Parameters:
  • __p – The port to end the current input on

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Returns:

The number of bits of data remaining

inline size_t port_force_input(port_t __p, uint32_t *__data)#

Force an input on a buffered port.

Perform an input on a buffered port even if the buffer is only partially full.

Parameters:
  • __p – The port to do the input on

  • __data[out] The inputted data

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively changing the port.

Throws ET_LOAD_STORE:

invalid data argument.

Returns:

The number of bits input

inline void port_set_trigger_value(port_t __p, uint32_t __value)#

Sets the trigger value for a port with a configured trigger.

Changes only the trigger value of a port which has already been configured to trigger on a value using port_set_trigger_in_equal() or port_set_trigger_in_not_equal().

Parameters:
  • __p – The port to change the trigger value of

  • __value – The new trigger value to set

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively using the port.

inline void port_sync(port_t __p)#

Synchronise with the port to ensure all data has been output.

Block until all data has been shifted out of the port, with the final port-width bits being held for one clock period.

Parameters:
  • __p – The port to synchronise

Throws ET_ILLEGAL_RESOURCE:

not a valid port.

Throws ET_RESOURCE_DEP:

another core is actively using the port.

inline void port_set_shift_count(port_t __p, uint32_t __sc)#

Set the port shift count for input and output operations.

Parameters:
  • __p – The port to set the shift count for

  • __sc – Shift count to set

Throws ET_ILLEGAL_RESOURCE:

Not a valid buffered port, or the shift count is not valid for the port width.

Throws ET_RESOURCE_DEP:

another core is actively using the port.

inline void port_out_part_word(port_t __p, uint32_t __d, uint32_t __bitp)#

Output a part word to a port.

Writes a specified number of bits of a given value to the a buffered port

Note

This is equivalent to using port_set_shift_count() followed by port_out()

Parameters:
  • __p – The port to output to

  • __d – The word to take the part word from

  • __bitp – The number of bits of __d to output.

Throws ET_ILLEGAL_RESOURCE:

Not a valid buffered port, the port is busy, or an invalid part-word width has been used.

Throws ET_RESOURCE_DEP:

another core is actively using the port.

inline int port_time_after(port_timestamp_t __a, port_timestamp_t __b)#

Compare two port timestamps.

Convenience function which checks if a port timestamp a is later than another port timestamp . Returns a nonzero value if a occurs after b, or zero otherwise. Returns 0 if a and b are equal.

Note

Port timestamps have a limited range and can overflow and wrap to 0 (hence they cannot be compared trivially). A timestamp is considered ‘after’ another one if it is ahead by no more than half the range of a port timer.

Note

Equivalent to XC’s porttimeafter from xs1.h

Parameters:
  • __a – Port timestamp to compare to __b

  • __b – Reference port timestamp

xcore/select.h#

Macros for efficiently handling events from multiple resources.

Provides macros which expand to code for efficiently waiting for events on an arbitrary group of resources (analogous to a socket select). The general form of user code is:

SELECT_MACRO(CASE_MACRO([...,] CASE_LABEL) [, ...])
// "select block":
{
CASE_LABEL:
  [...;]
  CASE_TERMINATOR;
[...;]
} // End of select block

Where:

SELECT_MACRO defines the how the checking of events is implemented and is one of:

  • SELECT_RES() - Repeatedly wait for an event on an arbitrary set of resources.

  • SELECT_RES_ORDERED() - Repeatedly wait for an event on an arbitrary set of events giving priority to resources based on order.

CASE_MACRO determines the condition under which a case label will be jumped to and is one of:
  • CASE_THEN() - Unconditionally wait for an event on a given resource.

  • CASE_GUARD_THEN() - Wait for an event on a given resource if a condition evaluates true.

  • CASE_NGUARD_THEN() - Wait for an event on a given resource is a condition evaluates false.

  • DEFAULT_THEN() - Defines a label to jump to if no enabled resource events are ready.

  • DEFAULT_GUARD_THEN() - Defines a label to jump to if no enabled resource events are ready and a condition evaluates true.

  • DEFAULT_NGUARD_THEN() Defines a label to jump to if no enabled resource events are ready and a condition evaluates false.

CASE_LABEL is a label inside the ‘select block’

The select block is compound statement consisting of sequences of statements prefixed with a CASE_LABEL and followed by a CASE_TERMINATOR

CASE_TERMINATOR determines whether control exits the select block or handles further events and is one of:

  • break - Exits the select block

  • continue - Waits for/handles another event or default

  • SELECT_CONTINUE_RESET - Restores the configuration of the immediately enclosing select block and continues.

  • SELECT_CONTINUE_NO_RESET - Continues to handle another event in the immediately inclosing select block without applying global resource setup.

The default case is a case with no associated resource which is passed using one of the DEFAULT_* macros. There may only be one default case; if more than one expansion of a DEFAULT_* macro is passed to a SELECT_MACRO then it is unspecified which one is effective, even if a condition means only one can ever be enabled. If the effective default case is expanded from DEFAULT_GUARD_THEN() and its condition is false or it is expanded from DEFAULT_NGUARD_THEN() and its condition is true, then the effect is as if there were no default case.

When the code expanded from a SELECT_MACRO is executed, qualifying resources are checked for events. Qualifying resources are those which were passed to the immediately enclosing select block’s SELECT_MACRO:

If there is an event waiting on a qualifying resource then control is transferred to the associated label (as passed to its CASE_MACRO). If no such event is available then:
  • If there is a default case (and it is not disabled by a condition) then control is transferred to the associated label;

  • Otherwise execution pauses until an event is available at which point control is transferred to its associated label.

Control continues as usual within a select block until a CASE_TERMINATOR is executed. At that point the behaviour depends on the terminator:
  • If control reaches a break then control will exit the immediately enclosing select block.

  • If control reaches the expansion of SELECT_CONTINUE_NO_RESET then the effect is as if control were transferred back to the beginning of the expansion of the SELECT_MACRO, except that some setup is skipped. If an inner (i.e. nested) SELECT_MACRO expansion has been executed (even as a result of calling a function), since control was transferred into the immediately enclosing select block by the immediately preceding SELECT_MACRO expansion, then the use of SELECT_CONTINUE_NO_RESET to terminate the outer select construct has undefined behaviour.

  • If control reaches the expansion of SELECT_CONTINUE_RESET then the effect is as if control were transferred to the beginning of the expansion of the SELECT_MACRO for the immediately enclosing select block. This effectively resets the select construct and makes ineffective any setup performed by any nested SELECT_MACRO which would affect the execution of the immediately enclosing one.

  • If control reaches a continue then the effect is as if control had reached the expansion of SELECT_CONTINUE_RESET if a SELECT_MACRO expansion has been executed since since control was transferred into the immediately enclosing select block by the immediately preceding SELECT_MACRO. Otherwise the effect is as if the expansion of SELECT_CONTINUE_RESET were executed.

  • If control reaches the end of a select block without reaching a CASE_TERMINATOR then the behaviour will be as if a CASE_TERMINATOR had been reached but it is unspecified which one. (Thus this may result in undefined behaviour if a nested select construct has been executed.)

The behaviour is undefined if control is transferred into a select block by any other means than by:
  • Executing the immediately preceding SELECT_MACRO expansion;

  • Returning from a function call;

  • Executing a CASE_TERMINATOR. Additionally, transferring control out of a select block by any means other than calling a function or executing break as a CASE_TERMINATOR has undefined behaviour.

If the expansion of a SELECT_MACRO or a CASE_TERMINATOR is executed and:
  • There are no qualifying resources, and

  • There is no default case or the effective default case is disabled by a condition,

then the behaviour is undefined. CASE_MACRO (including default case) conditions are evaluated on initial entry to the SELECT_MACRO expansion and after each execution of a CASE_TERMINATOR other than break. If evaluation of a case condition has side effects then the behaviour is of the select construct is undefined.

If a CASE_LABEL is placed within a select block such that it would be illegal to use goto to jump to it from the point at which SELECT_MACRO is expanded, then the behaviour is undefined.

Each resource passed (though a CASE_MACRO) to a SELECT_MACRO must be unique within that SELECT_MACRO expansion, otherwise the behaviour of the select construct is undefined. That is, the same resource must not be used for two different cases. This applies even if cases are guarded by mutually exclusive conditions.

Note

This is intended to provide a safe means of handling further events if arbitrary code has been executed which may have used a select construct. Its use is likely to incur a runtime performance penalty compared to using the most appropriate of SELECT_CONTINUE_RESET and SELECT_CONTINUE_NO_RESET.

Note

Normal language rules apply - break and continue affect the relevant enclosing construct - so if they are nested within e.g. a loop then they will not terminate the select block. This also applies to other case terminators which must only appear within a select block. Thus it is impossible to exit a select block from a function.

Defines

SELECT_RES(...)#

Repeatedly wait for an event on an arbitrary set of resources.

Selects on one or more resources with an optional default. If more than one event is available then it is upspecified which one will be taken.

Example:

int button_up = 1;
int button_event_count = 0;

SELECT_RES(
  CASE_GUARD_THEN(button_chanend, button_event_count < 21, event_button_chanend),
  CASE_THEN(led_chanend, event_led_chanend),
  DEFAULT_NGUARD_THEN(button_up, default_label))
{
default_label:
  puts("Button is still down!");
  SELECT_RESET;
event_button_chanend:
  {
    uint32_t tmp = chan_in_word(button_chanend);
    chan_out_word(led_chanend, tmp);
    button_up = tmp;
  }
  button_event_count += 1;
  continue;
event_led_chanend:
  {
    uint32_t tmp = chan_in_word(led_chanend);
    chan_out_word(button_chanend, tmp);
  }
  continue;
}

Parameters:
  • ... – case specifications as expanded from the CASE_* or DEFAULT_* macros

SELECT_RES_ORDERED(...)#

Repeatedly wait for an event on an arbitrary set of events giving priority to resources based on order.

Behaviour is like SELECT_RES() except that events are checked in the order their respective CASE_* expansions are passed. This can be used to ensure that high priority events are serviced before lower priority ones.

If there is an event on the highest priority qualifying resource upon execution of the expansion of SELECT_RES_ORDERED(), or a select terminator within its immediately following select block, then if is guaranteed that event will be taken. For any other priority in this case (if it is the highest priority event) then it is guarateed that it will be taken, but only if no higher priority event becomes available (in which case the event taken is unspecified). If no event is available then the default case will be taken if there is a default case and it is enabled. If there is no default case or the default case is disabled by a condition then execution will pause and wait for an event on a qualifying resource - in this case prioties no longer apply and the first event which becomes available will be taken.

Note

There is a runtime overhead associated with checking events in order so it is suggested that SELECT_RES() be used whenever possible.

Parameters:
  • ... – case specifications as expanded from the CASE_* or DEFAULT_* macros

SELECT_CONTINUE_RESET#

Restores the configuration of the immediately enclosing select block and continues.

This may be used instead of continue as a select terminator if a different (to the immediately enclosing one) select construct has been executed. The effect is that the resource setup which happens at the start of the select construct is guaranteed to re-run so that the correct events will be enabled. Using this instead of continue (when required) is likely to result in a slight performance boost as it eliminates the need to check global state.

SELECT_CONTINUE_NO_RESET#

Continues to handle another event in the immediately inclosing select block without applying global resource setup.

This may be used in stead of continue as a select terminator if different select block has not been executed during handling of the previous event (or default). In the event that another select construct has executed this will have undefined behaviour.

Using this instead of continue (when safe to do so) is likely to result in a slight performance improvement.

CASE_THEN(_RES, _LABEL)#

Unconditionally wait for an event on a given resource.

Parameters:
  • _RES – The resource to wait for an event on.

  • _LABEL – The label (within the following select block) to jump to when an event occurs on res.

CASE_GUARD_THEN(_RES, _GUARD_EXPR, _LABEL)#

Wait for an event on a given resource if a condition evaluates true.

Parameters:
  • _RES – The resource to wait for an event on.

  • _GUARD_EXPR – Expression to evaluate to determine if this case should be enabled. Must not have side effects.

  • _LABEL – The label (within the following select block) to jump to when an event occurs on res.

CASE_NGUARD_THEN(_RES, _GUARD_EXPR, _LABEL)#

Wait for an event on a given resource is a condition evaluates false.

Parameters:
  • _RES – The resource to wait for an event on.

  • _GUARD_EXPR – Expression to evaluate to determine if this case should be disabled. Must not have side effects.

  • _LABEL – The label (within the following select block) to jump to when an event occurs on res.

DEFAULT_THEN(_LABEL)#

Defines a label to jump to if no enabled resource events are ready.

Parameters:
  • _LABEL – The label (within the following select block) to jump to if there are no events to take.

DEFAULT_GUARD_THEN(_GUARD_EXPR, _LABEL)#

Defines a label to jump to if no enabled resource events are ready and a condition evaluates true.

Parameters:
  • _LABEL – The label (within the following select block) to jump to if there are no events to take.

  • _GUARD_EXPR – Expression to determine it the default case should be enabled.

DEFAULT_NGUARD_THEN(_GUARD_EXPR, _LABEL)#

Defines a label to jump to if no enabled resource events are ready and a condition evaluates false.

Parameters:
  • _LABEL – The label (within the following select block) to jump to if there are no events to take.

  • _GUARD_EXPR – Expression to determine it the default case should be disabled.

xcore/swmem_evict.h#

API for implementing software memory fill (write)

Defines

SWMEM_EVICT_SIZE_WORDS#

Number of words which must be evicted per eviction request.

Typedefs

typedef resource_t swmem_evict_t#

Handle type for a SwMem evict resource.

typedef const void *evict_slot_t#

Pointer to an eviction slot - this is the lowest address which must be evicted.

typedef uint32_t evict_mask_t#

Functions

inline swmem_evict_t swmem_evict_get(void)#

Gets and enables a swmem evict resource.

The handle must be passed to swmem_evict_free() before this function is called again.

Returns:

The swmem evict handle.

inline void swmem_evict_free(swmem_evict_t __r)#

Disables a swmem evict resource as returned by swmem_evict_get()

inline evict_slot_t swmem_evict_in_address(swmem_evict_t __r)#

Returns the slot handle of the waiting swmem eviction request, blocks if there isn’t one.

When a eviction request is raised, the contents of the ‘eviction slot’ are available to be read until the request is completed. Fulfilling the request may unblock another thread which is attempting to write.

The handle returned is the lowest address in the eviction request; the length of the request is always SWMEM_EVICT_SIZE_WORDS words.

Words can be read from the eviction slot individually using swmem_evict_read_word(); once all required words have been read swmem_evict_read_word_done() should be called to complete the request. Alternatively, swmem_evict_to_buffer() may be used to read and complete the request in a single call.

Parameters:
  • __r – The swmem evict resource handle

Returns:

An eviction slot handle

inline uint32_t swmem_evict_read_word(swmem_evict_t __r, evict_slot_t __slot, unsigned __word_index)#

Read a single word from an eviction slot.

Returns the word from the eviction slot at the given index. To complete the eviction swmem_evict_read_word_done() should be called.

Parameters:
Returns:

The word at the given __word_index within the evict slot

inline evict_mask_t swmem_evict_get_dirty_mask(swmem_evict_t __r, evict_slot_t __slot)#

Gets the dirty mask for the current eviction.

The mask returned is a bytewise dirty mask with one bit per byte in the entire eviction slot. This must only be called before the eviction request has been completed - i.e. it must be called before swmem_evict_read_word_done() or swmem_evict_to_buffer() for a given eviction request.

A byte is dirty if it has been written since it was last filled, or if it has been written but has never been filled (see swmem_fill.h).

The least significant bit in the dirty mask corresponds to the lowest byte address in the fill slot and each subsequent byte address corresponds to the next least significant bit of the dirty mask.

Parameters:
  • __r – The evict resource

  • __slot – The current eviction slot

Returns:

A bytewise dirty mask for the given eviction on the given resource

inline void swmem_evict_read_word_done(swmem_evict_t __r, evict_slot_t __slot)#

Complete an eviction and unblock waiting threads.

This should be called after swmem_evict_read_word() has been used to get all required words from the evict request.

Note

It is not necessary (or safe) to call this if the request is fulfilled by calling swmem_evict_to_buffer().

Parameters:
  • __r – The swmem evict resource handle

  • __slot – The evict slot for the current eviction requesst

inline void swmem_evict_to_buffer(swmem_evict_t __r, evict_slot_t __slot, uint32_t *__buf)#

Evict a slot into a buffer.

For an evict slot returned by swmem_evict_in_address(), reads the eviction slot into the given buffer and completes the eviction.

Note

If the dirty mask is required for the data read then it should be retrieved prior to calling this function. (Since the eviction will be complete on return.)

Parameters:

xcore/swmem_fill.h#

API for implementing software memory fill (read)

Defines

SWMEM_FILL_SIZE_WORDS#

Number of words which must be filled per fill request.

Typedefs

typedef uint32_t swmem_fill_buffer_t[SWMEM_FILL_SIZE_WORDS]#

Buffer type which holds the correct number of words for a complete fill.

typedef resource_t swmem_fill_t#

Handle type for a SwMem fill resource.

typedef const void *fill_slot_t#

Pointer to a fill slot - this is the lowest address which must be filled.

Functions

inline swmem_fill_t swmem_fill_get(void)#

Gets and enables a swmem fill resource.

The handle must be passed to swmem_fill_free() before this function is called again.

Returns:

The swmem fill handle.

inline void swmem_fill_free(swmem_fill_t __r)#

Disables a swmem fill resource as returned by swmem_fill_get()

See also

swmem_fill_get()

inline fill_slot_t swmem_fill_in_address(swmem_fill_t __r)#

Returns the slot handle of the waiting swmem fill request, blocks if there isn’t one.

When a fill request is raised, the complete ‘fill slot’ must be populated. There are two ways of doing this:

The handle returned is the lowest address in the fill request; the length of the fill request is always SWMEM_FILL_SIZE_WORDS words.

Parameters:
  • __r – The swmem fill resource handle

Returns:

A fill slot handle which must be populated

inline void swmem_fill_populate_word(swmem_fill_t __r, fill_slot_t __slot, unsigned __word_index, uint32_t __value)#

Populate a single word in a fill slot.

Fills a single word in a fill slot for a waiting fill request. The fill slot must be the last one returned by swmem_fill_in_address() and the fill request must not have been completed either by calling swmem_fill_populate_word_done() or by calling swmem_fill_populate_from_buffer(). To fulfill a request this function should be called for each word in the fill slot (i.e. with word_index set to each of [0, SWMEM_FILL_SIZE_WORDS). Once all words have been populated in the fill slot, swmem_fill_populate_word_done() should be called to complete the fulfillment of the request and unblock any threads waiting for the fill.

Note

It is safe to call this multiple times for the same word_index of a fill request, but only the last such call will have any effect.

Parameters:
  • __r – The swmem fill resource handle

  • __slot – The fill slot to populate (returned by swmem_fill_in_address())

  • __word_index – The index of the word (must be less than SWMEM_FILL_SIZE_WORDS)

  • __value – The value to set at the given index

inline void swmem_fill_populate_word_done(swmem_fill_t __r, fill_slot_t __slot)#

Complete a fill and unblock waiting threads.

This should be called after swmem_fill_populate_word() has been used to fill each word in the fill request.

Note

It is not necessary (or safe) to call this if the request is fulfilled by calling swmem_fill_populate_from_buffer().

Parameters:
  • __r – The swmem fill resource handle

  • __slot – The fill slot for the ongoing fill request

inline void swmem_fill_populate_from_buffer(swmem_fill_t __r, fill_slot_t __slot, const uint32_t *__source)#

Service a fill request using data in a suitably sized buffer.

For a fill slot returned by swmem_fill_in_address(), services the waiting fill request using data from __source - this must point to a buffer of at least SWMEM_FILL_SIZE_WORDS words; source[0] will be used to fill the 0th word in the fill slot, and so on.

Parameters:

xcore/thread.h#

Hardware-assisted threading support.

Typedefs

typedef resource_t xthread_t#

Handle for a single joinable thread.

typedef resource_t threadgroup_t#

Handle for a group of threads which are jointly joinable.

typedef void (*thread_function_t)(void*)#

Callback type which can be executed in another thread.

Enums

enum thread_mode_t#

Thread mode bits enumeration.

Mode bits which may be passed to local_thread_mode_set_bits() and local_thread_mode_clear_bits() or to interpret the result of calling local_thread_mode_get_bits().

Note

The effect of setting/clearing these bits is platform-dependent; setting/clearing a bit is not guaranteed to have any effect.

Values:

enumerator thread_mode_fast#

Fast mode bit

enumerator thread_mode_high_priority#

High priority mode bit

Functions

inline threadgroup_t thread_group_alloc(void)#

Allocates a hardware thread.

Attempts to allocate a thread group from the pool on the current tile.

Note

The thread group should be freed using thread_group_free() when it is no longer required. (Or freed as a consequence of calling thread_group_wait_and_free().)

Returns:

A thread group handle, or 0 if none were available.

inline void thread_group_add(const threadgroup_t __group, const thread_function_t __func, void *const __argument, void *const __stack_base)#

Add a new task to a thread group.

Adds a thead function invocation to a thread group allocated using thread_group_alloc(). This configures a hardware thread to execute func with argument as its sole parameter and with its stack pointer initialised to stack_base. stack_base must be word aligned and point to the last word of a block of memory sufficient to satisfy func’s stack requirements. That is, for a stack requirement of s words, [stack_base-s*word_size, stack_base] will be used as the thread’s stack and will be clobbered.

Note

Execution of func will not begin until the group is started using thread_group_start().

Parameters:
  • __group – Thread group handle as returned by thread_group_alloc().

  • __func – Function to call in separate thread with signature void(void*).

  • __argument[in] Parameter to pass to func.

  • __stack_base[in] Word aligned pointer to the last word of the region to use as a stack when calling func. Note that this can be calculated with stack_base().

inline __xcore_bool_t thread_group_try_add(const threadgroup_t __group, const thread_function_t __func, void *const __argument, void *const __stack_base)#

Attempts to add a new task to a thread group.

As thread_group_add() except returns false if no threads are available. If false is returned, the thread group has not been modified and no new resources have been allocated. If the result is nonzero then the task was successfully added to the group and will be launched when the group is started.

Parameters:
  • __group – Thread group handle as returned by thread_group_alloc().

  • __func – Function to call in separate thread with signature void(void*).

  • __argument[in] Parameter to pass to func.

  • __stack_base[in] Word aligned pointer to the last word of the region to use as a stack when calling func. Note that this can be calculated with stack_base().

inline void thread_group_start(const threadgroup_t __group)#

Starts all threads in a group running.

Starts execution of the thread functions for each thread in the group (as added using thread_group_add()). This function will return immediately regardless of the state of the threads.

Note

Use thread_group_wait() or thread_group_wait_and_free() to wait for the thread group to finish.

Parameters:
  • __group – The thread group to start.

inline void thread_group_free(const threadgroup_t __group)#

Frees a thread group.

Returns the thread group to the pool so that it may be allocated again. The group handle is invalid once passed to this function so must not be re-used.

Attention

This function must not be called on a thread group which has been started but not waited upon, even if its constituent threads have finished executing.

Parameters:
  • __group – The group to free.

inline void thread_group_wait(const threadgroup_t __group)#

Wait for all threads in a thread group to finish.

The group must have been started using thread_group_start(). Calls to this function will block until all threads in the group have finished executing. Upon return of this function, the group remains valid but will no longer have any threads associated with it. The group may be re-used but threads must be re-added to it.

Note

Since the group remains valid, it should be freed with thread_group_free() if no longer required.

Parameters:
  • __group – The group to wait for completion.

inline void thread_group_wait_and_free(const threadgroup_t __group)#

Waits for a thread group to finish then frees it.

Helper to both wait for and free a thread group. The group must have been started using thread_group_start() and the group will be invalid once this function returns.

Calls

inline xthread_t xthread_alloc_and_start(const thread_function_t __func, void *const __argument, void *const __stack_base)#

Runs a function in another thread and returns a waitable handle.

Starts executing func in a separate hardware thread with argument as its sole parameter and with its stack pointer initialised to stack_base. stack_base must be word aligned and point to the last word of a block of memory sufficient to satisfy func’s stack requirements. That is, for a stack requirement of s words, [stack_base-s*word_size, stack_base] will be used as the thread’s stack and will be clobbered.

Note

The thread will begin execution immediately and this function will return. The thread will not be returned to the pool upon completion - it is necessary to call xthread_wait_and_free() to free the thread so that it may be reused.

Parameters:
  • __func – Function to call in separate thread with signature void(void*).

  • __argument[in] Parameter to pass to func.

  • __stack_base[in] Word aligned pointer to the last word of the region to use as a stack when calling func. Note that this can be calculated with stack_base().

Returns:

A waitable handle for the hardware thread, or zero if the thread resource could not be allocated.

inline void xthread_wait_and_free(const xthread_t __xthread)#

Wait for a thread to finish and then free it.

thread must have been allocated and started using xthread_alloc_and_start(). Calls to this function will block until the function called by thread has returned and upon completion it will free the associated hardware thread. thread must not be re-used after it has been freed.

Parameters:
inline void run_async(const thread_function_t __func, void *const __argument, void *const __stack_base)#

Runs a function in another hardware thread.

Starts executing func in a separate hardware thread with argument as its sole parameter and with its stack pointer initialised to stack_base. stack_base must be word aligned and point to the last word of a block of memory sufficient to satisfy func’s stack requirements. That is, for a stack requirement of s words, [stack_base-s*word_size, stack_base] will be used as the thread’s stack and will be clobbered.

Note

The associated hardware thread will be freed once func returns, but it is not trivially possible to determine wether or not this has happened from the calling thread. If it necessary to wait for the completion of func then xthread_alloc_and_start() and xthread_wait_and_free() should be used instead.

Parameters:
  • __func – Function to call in separate thread with signature void(void*).

  • __argument[in] Parameter to pass to func.

  • __stack_base[in] Word aligned pointer to the last word of the region to use as a stack when calling func. Note that this can be calculated with stack_base().

inline void *stack_base(void *const __mem_base, size_t const __words)#

Returns a stack pointer suitable for use as a stack_base argument given a base address and a size.

Given a base pointer (e.g. as returned by malloc or found by taking the address of an object) and the size of the intended stack in words, returns a stack base pointer to the last word of the stack - which is suitable for passing to the stack_base arguments of xthread_alloc_and_start(), run_async() and thread_group_add(). The given base address must be suitably aligned as the resulting stack pointer is required to be aligned also. The alignment requirement is a multiple of the word size and is target dependent. The resulting pointer will be a valid stack pointer for a stack words words in size. If used as a stack pointer for a function with a stack requirement no greater than words words then the memory region used as a stack by that function will not be beyond [mem_base, (char *)mem_base + words*WORD_SIZE) in either direction.

Parameters:
  • __mem_base[in] The base (lowest) address of the object/region to use as a stack. Must be word aligned.

  • __words – Size of the stack the returned pointed will return to in words

Returns:

The stack pointer.

inline void local_thread_mode_set_bits(const thread_mode_t __mode)#

Set mode bits for the current thread.

Sets platform-dependent mode bits for the calling thread given a mask of bits to set. The mode bits passed must be a value from thread_mode_t or the bitwise disjunuction of two or more such values. The actual effect of setting mode bits varies by target; no bit is guaranteed to have any particular effect or any effect whatsoever. This function can only set bits - using a mode value with a bit unset will not clear that bit in the local thread mode. Instead, local_thread_mode_clear_bits() must be used.

Parameters:
  • __mode – Mask of bits to set

inline thread_mode_t local_thread_mode_get_bits(void)#

Get the current thread’s mode bits.

Gets the platform-dependent mode bits for the current thread. The value returned will be the bitwise disjunction of zero or more values from thread_mode_t, and those members may be used as masks to interpret the result of this function.

Returns:

The calling thread’s mode bits

inline void local_thread_mode_clear_bits(const thread_mode_t __mode)#

Clear bits in the current thread’s mode.

Given a mask, clear any bits which are set in that mask in the current thread’s mode. The mask must be a value from thread_mode_t or the bitwise disjunction of two or more such values. This can be used to unset bits which were set using local_thread_mode_set_bits().

Parameters:
  • __mode – The mask of bits to clear

xcore/triggerable.h#

Functions applicable to Chanends, Ports and Timers for configuring events and interrupts.

Low level API for handling events and interrupts. It is generally recommended to use the SELECT API instead.

See also

  • xcore/select.h

  • xcore/interrupt.h

Note

A resource may only be configured for interrupts or events at a given time. Configuring interrupts for a resource may overwrite any event configuration and configuring events may overwrite any interrupt configurataion. A trigger controls the condition for both interrups and for events (whichever is enabled for the resource).

Defines

TRIGGERABLE_EV_BASE#

Minimum event vector value.

Interrupt values passed as iunterrupt data must be no less than this value. On targets where this is nonzero, the value must be in the range: [ TRIGGERABLE_EV_BASE, 2*TRIGGERABLE_EV_BASE )

TRIGGERABLE_SETUP_EVENT_VECTOR(__resource, __label)#

Configure the vector which handles events on a given resource.

Expands to a statement which configures the event vector for the given resource such that handling an event on that resource causes control to transfer to the given label.

Note

This will overwrite any interrupt vector which has been set on the resource.

Parameters:
  • __resource – The resource to configure

  • __label – The label to jump to when an event is handled on resource

Throws ET_ILLEGAL_RESOURCE:

not a valid chanend, port or timer

Throws ET_RESOURCE_DEP:

another core is actively using the resource.

TRIGGERABLE_WAIT_EVENT(__labels...)#

Wait for a configured and enabled event to occur.

Expands to a statements which waits for a configured event to occur and jumps to its event vector. Note that any possible event vector which may be jumped to (i.e. the labels configured as event vectors on all resources where events are enabled and an event may occur) must be passed as arguments otherwise the effect is undefined. Passing labels which cannot be reached by an enabled event may be ill formed if jumping to that label would be ill formed and may result in sub-optimal performance.

For a resource to raise an event:

Attention

The expansion of this macro will block until the trigger occurs on a resource where events are enabled. If no events are enabled then this can never complete.

Parameters:
  • __labels – The labels configured as event vectors for all events which may occur.

TRIGGERABLE_TAKE_EVENT(__labels...)#

Jump to an event vector if an event is ready.

Has the same effect as TRIGGERABLE_WAIT_EVENT() except that if no event is waiting then this expansion does not block.

Parameters:
  • __labels – Labels which may be jumped to if an event is ready

Typedefs

typedef __xcore_interrupt_callback_t interrupt_callback_t#

Interrupt handler type.

Functions

inline void triggerable_setup_interrupt_callback(resource_t __res, void *__data, interrupt_callback_t __func)#

Setup interrupt event on a resource.

Once the interrupts is setup you need to call port_enable_trigger() to enable it.

Parameters:
  • __res – The resource to setup the interrupt event on.

  • __data[in] The value to be passed to the interrupt_callback_t function On XS1 bit 16 must be set (see TRIGGERABLE_EV_BASE)

  • __func – The interrupt_callback_t function to handle events

Throws ET_ILLEGAL_RESOURCE:

not a valid chanend, port or timer

Throws ET_RESOURCE_DEP:

another core is actively using the resource.

Throws ET_ECALL:

when xassert enabled, on XS1 bit 16 not set in data.

inline void triggerable_enable_trigger(resource_t __res)#

Enable the trigger for a given resource.

This will allow the resource the generate events or interrupts when its trigger occurs.

Parameters:
  • __res – Resource to enable the trigger of

Throws ET_ILLEGAL_RESOURCE:

not a valid chanend, port or timer

Throws ET_RESOURCE_DEP:

another core is actively using the resource.

inline void triggerable_disable_trigger(resource_t __res)#

Disable the trigger for a given resource.

This prevents the resource generating events or interrupts.

Parameters:
  • __res – Resource to disable the trigger of

Throws ET_ILLEGAL_RESOURCE:

not a valid chanend, port or timer

Throws ET_RESOURCE_DEP:

another core is actively using the resource.

inline void triggerable_set_trigger_enabled(resource_t __res, int __enabled)#

Set the trigger enabled or disabled on a given resource.

Has the same effect as calling triggerable_enable_trigger() or triggerable_disable_trigger() depending on the value of enabled. However, this may perform better when the value of enabled is not statically known.

Parameters:
  • __res – The resource to enaable or disable the trigger of

  • __enabled – State to set on the trigger - if true it is enabled, otherwise it is disabled

Throws ET_ILLEGAL_RESOURCE:

not a valid chanend, port or timer

Throws ET_RESOURCE_DEP:

another core is actively using the resource.

inline void triggerable_disable_all(void)#

Disables all triggers in the current thread and masks interrupts.

Disables the triggers on all resources in use by the current thread and disabled interrupts as if with interrupt_mask_all().