Skip to content
This repository was archived by the owner on Nov 27, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 100 additions & 8 deletions lib_xcore_c/src/xcore_c_select.S
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,29 @@
# define _SELECT_CALLBACK_STACK_SIZE 1
#endif

// Callback functions may be triggered during select setup phase.
// If this happens, we need to re-run the setup.
// It is always safe to re-run the setup.
// We need a rerun-address, and arguments r0 & r1
// The data is layed out to make access most efficient.
.section .dp.bss,"awd",@nobits
.cc_top _xcore_c_select_rerun.data,_xcore_c_select_rerun
#ifdef __XS2A__
.align 8
#else
.align 4
#endif
.type _xcore_c_select_rerun,@object
_xcore_c_select_rerun:
#ifdef __XS2A__
.size _xcore_c_select_rerun, (4*2*8)*2
.space (4*2*8)*2 // {recall,r0}[number of threads], {r1,padding}[number of threads]
#else
.size _xcore_c_select_rerun, 4*8*3
.space 4*8*3 // recall[number of threads], r0[number of threads], r1[number of threads]
#endif
.cc_bottom _xcore_c_select_rerun.data

.text

.globl _xcore_c_select_callback_common
Expand All @@ -26,7 +49,24 @@ _xcore_c_select_callback_common:
bla r1 // The select_callback_t function.
ldw lr, sp[_SELECT_CALLBACK_STACK_SIZE]
ldaw sp, sp[_SELECT_CALLBACK_STACK_SIZE]
waiteu // setsr 0x1
// Do we need to re-run the select setup or can we do a waite?
ldaw r3, dp[_xcore_c_select_rerun]
get r11, id
#ifdef __XS2A__
ldd r2, r0, r3[r11]
waitef r2 // setsr 0x1
add r11, r11, 8
ldd r1, r3, r3[r11]
bau r2; // re-run the select setup.
#else
ldw r2, r3[r11]
waitef r2 // setsr 0x1 // no rerun needed
add r11, r11, 8
ldw r0, r3[r11]
add r11, r11, 8
ldw r1, r3[r11]
bau r2; // re-run the select setup.
#endif
.cc_bottom _xcore_c_select_callback_common.function
.set _xcore_c_select_callback_common.nstackwords, 0
.globl _xcore_c_select_callback_common.nstackwords
Expand Down Expand Up @@ -72,18 +112,27 @@ _select_non_callback:

.globl select_wait
#ifdef __XS2A__
.issue_mode dual
.issue_mode single
.align 4
#else
.align 2
#endif
.type select_wait,@function
.cc_top select_wait.function,select_wait
select_wait:
waiteu // setsr 0x1
select_wait: // no args.
#ifdef __XS2A__
nop // handle dual issue.
ENTSP_lu6 0
#endif
// clear the recall state
ldc r2, 0
ldaw r3, dp[_xcore_c_select_rerun]
get r11, id
#ifdef __XS2A__
std r2, r0, r3[r11]
#else
stw r2, r3[r11]
#endif
waiteu // setsr 0x1
// function returns via _select_non_callback
.cc_bottom select_wait.function
.set select_wait.nstackwords, 0 + _select_non_callback.nstackwords
Expand All @@ -106,10 +155,23 @@ select_wait:
#endif
.type select_no_wait,@function
.cc_top select_no_wait.function,select_no_wait
select_no_wait:
select_no_wait: // r0 = 'nowait' return
#ifdef __XS2A__
ENTSP_lu6 0
#endif
// set up the recall state
ldap r11, _select_no_wait_rerun
add r2, r11, 0
ldaw r3, dp[_xcore_c_select_rerun]
get r11, id
#ifdef __XS2A__
std r2, r0, r3[r11]
#else
stw r2, r3[r11]
add r11, r11, 8
stw r0, r3[r11]
#endif
_select_no_wait_rerun:
setsr 0x1 // Enable events
#if defined(__XS2A__)
nop // Allow channel events to fire
Expand Down Expand Up @@ -139,10 +201,23 @@ select_no_wait:
#endif
.type select_wait_ordered,@function
.cc_top select_wait_ordered.function,select_wait_ordered
select_wait_ordered:
select_wait_ordered: // r0 = resoure_order[]
#ifdef __XS2A__
ENTSP_lu6 0
#endif
// set up the recall state
ldap r11, _select_wait_ordered_rerun
add r2, r11, 0
ldaw r3, dp[_xcore_c_select_rerun]
get r11, id
#ifdef __XS2A__
std r2, r0, r3[r11]
#else
stw r2, r3[r11]
add r11, r11, 8
stw r0, r3[r11]
#endif
_select_wait_ordered_rerun:
clre // disable all 'select event' resources
setsr 0x1 // Enable events on core
ldc r2, 0 // Resource list index
Expand Down Expand Up @@ -177,10 +252,27 @@ select_wait_ordered_done:
#endif
.type select_no_wait_ordered,@function
.cc_top select_no_wait_ordered.function,select_no_wait_ordered
select_no_wait_ordered:
select_no_wait_ordered: // r0 = 'nowait' return, r1 = resoure_order[]
#ifdef __XS2A__
ENTSP_lu6 0
#endif
// set up the recall state
ldap r11, _select_no_wait_ordered_rerun
add r2, r11, 0
ldaw r3, dp[_xcore_c_select_rerun]
get r11, id
#ifdef __XS2A__
std r2, r0, r3[r11]
add r11, r11, 8
std r1, r1, r3[r11]
#else
stw r2, r3[r11]
add r11, r11, 8
stw r0, r3[r11]
add r11, r11, 8
stw r1, r3[r11]
#endif
_select_no_wait_ordered_rerun:
clre // disable all 'select event' resources
setsr 0x1 // Enable events on core
ldc r2, 0 // Resource list index
Expand Down
41 changes: 25 additions & 16 deletions tests/select_handler_functions.expect
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
Received 0 on channel c
Received 1 on channel c
Timer event data 0xFEEDBEEF
Received 0 on channel d
Received 0 on channel c
Received 1 on channel d
Received 2 on channel c
Received 1 on channel c
Timer event data 0xFEEDBEEF
Received 2 on channel d
Received 2 on channel c
Timer event data 0xFEEDBEEF
Timer event data 0xFEEDBEEF
Received 3 on channel c
Received 3 on channel d
Received 3 on channel c
Timer event data 0xFEEDBEEF
Timer event data 0xFEEDBEEF
Received 4 on channel c
Received 4 on channel d
Received 555 on channel c
Received 556 on channel c
Received 333 on channel d
Received 4 on channel c
Received 555 on channel c
Received 334 on channel d
Received 557 on channel c
Received 556 on channel c
Timer event data 0xFEEDBEEF
Received 335 on channel d
Received 558 on channel c
Received 557 on channel c
Timer event data 0xFEEDBEEF
Timer event data 0xFEEDBEEF
Received 336 on channel d
Received 559 on channel c
Received 337 on channel d
Received 558 on channel c
Timer event data 0xFEEDBEEF
Timer event data 0xFEEDBEEF
Received 337 on channel d
Received 666 on channel d
Received 667 on channel d
Received 559 on channel c
Received 1110 on channel c
Received 1111 on channel c
Received 666 on channel d
Timer event data 0xFEEDBEEF
Received 667 on channel d
Received 1112 on channel c
Received 668 on channel d
Received 1112 on channel c
Timer event data 0xFEEDBEEF
Received 1113 on channel c
Received 669 on channel d
Timer event data 0xFEEDBEEF
Received 1114 on channel c
Received 1113 on channel c
Timer event data 0xFEEDBEEF
Received 670 on channel d
Timer event data 0xFEEDBEEF
Received 1114 on channel c

4 changes: 2 additions & 2 deletions tests/select_handler_functions/src/main.xc
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ int main()
// Provide test data
for (int test = 0; test < num_tests; ++test) {
for (int i = 0; i < 5; i++) {
c <: 555*test + i;
delay_ticks(5000 * i);
c <: 555*test + i;
}
}

// Provide test data
for (int test = 0; test < num_tests; ++test) {
for (int i = 0; i < 5; i++) {
d <: 333*test + i;
delay_ticks(5000 * i);
d <: 333*test + i;
}
}
}
Expand Down
19 changes: 12 additions & 7 deletions tests/select_handler_functions/src/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,22 @@ static const int period = 10000;
// For XS1 support all values passed to the event_setup function must have bit 16 set
typedef enum {
EVENT_CHAN_C = ENUM_ID_BASE,
EVENT_CHAN_D
EVENT_CHAN_D,
EVENT_NONE,
} event_choice_t;

void test_select_function(chanend c, chanend d)
void test_select_function(chanend c, chanend d, hwtimer_t t)
{
// Setup the channels to generate events
chanend_setup_select(c, EVENT_CHAN_C);
chanend_setup_select(d, EVENT_CHAN_D);
chanend_enable_trigger(c);
chanend_enable_trigger(d);

resource_t ids[4] = {t, d, c, 0};

for (int count = 0; count < 10; count++) {
event_choice_t choice = select_wait();
event_choice_t choice = select_no_wait_ordered(EVENT_NONE,ids);
switch (choice) {
case EVENT_CHAN_C: {
// Read value and clear event
Expand All @@ -38,6 +41,8 @@ void test_select_function(chanend c, chanend d)
debug_printf("Received %d on channel d\n", x);
break;
}
case EVENT_NONE:
count--;
}
}
chanend_disable_trigger(c);
Expand Down Expand Up @@ -76,19 +81,19 @@ void test(chanend c, chanend d)
// Test 1: Run the test function with the timer enabled
uint32_t time;
hwtimer_get_time(t, &time);
hwtimer_setup_select_callback(t, time + period, (void*)&data, SELECT_CALLBACK(handle_timer));
hwtimer_setup_select_callback(t, time-10, (void*)&data, SELECT_CALLBACK(handle_timer));
hwtimer_enable_trigger(t);
test_select_function(c, d);
test_select_function(c, d, t);
hwtimer_disable_trigger(t);

// Test 2: Run the test function again with the timer disabled
test_select_function(c, d);
test_select_function(c, d, t);

// Test 3: Run the test function again with the timer enabled
hwtimer_get_time(t, &time);
hwtimer_change_trigger_time(t, time + period);
hwtimer_enable_trigger(t);
test_select_function(c, d);
test_select_function(c, d, t);
hwtimer_disable_trigger(t);

hwtimer_free(&t);
Expand Down