/* * _xc_test_combined_embedded_par_comms.xc * * Created on: 18. apr. 2021 * Author: teig */ /* --------- VER COMMITS ------------------------------------------------------------------------------- 20Apr2021 008 Comments (and again) 20Apr2021 007 Had forgotten to remove cycle_cnt in all interfaces: not needed! 20Apr2021 006 Testing out combinations up to stopping code limit (no proceed), ready for blog note 218 Also compile log and run logs at the end of this file 18Apr2021 005 More configs. All run! Kind of coclusion that it is (PROBABLY) NOT ANY BETTER THAN THE POLLED SYNCHRONISATION OF _xc_test_Toroid_2.xc TOP_26_TESTING_SYNCH_PHASE In that case, since it's the client's which HAVE TO (?) have a timerafter and thus cannot be distributable, this synch mechansim will add to the use of interface connections 18Apr2021 004 Runs! 18Apr2021 003 Before timerafter in my_synch_task 18Apr2021 002 Runs further, change in main 18Apr2021 000 Compiles but stops */ #include // core #include // delay_milliseconds(..), XS1_TIMER_HZ etc #include "debug_conf.h" #include "debug_print.h" // lib_printing takes about 5500 bytes on tile[0] (-DDEBUG_PRINT_ENABLE_ALL=1 in Makefile) // BOOLEAN #include if C99 // See http://www.teigfam.net/oyvind/home/technology/165-xc-code-examples/#bool typedef enum {false,true} bool; // 0,1 This typedef matches any integer-type type like long, int, unsigned, char, bool typedef signed int time32_t; // signed int (=signed) or unsigned int (=unsigned) both ok, as long as they are monotoneously increasing // XC/XMOS 100 MHz increment every 10 ns for max 2exp32 = 4294967296, // ie. divide by 100 mill = 42.9.. seconds // See LOGS at the end of this file #define MY_CONFIG 2 // 1 runs // 2 runs #if (MY_CONFIG==1) #define NUM_SYNCHED_NODES 3 // Other combinations compile, #define NUM_SYNCHED_NODES_COMBINED 1 // but run then stops (no proceed). Only this combination runs #elif (MY_CONFIG==2) #define NUM_SYNCHED_NODES 10 // Hard coded for 3 or 10. Both combinations RUN #else #error No MY_CONFIG defined #endif typedef interface con_if_t { unsigned SET_GET (const unsigned value); } con_if_t; [[distributable]] void my_server_task (server con_if_t if_con[NUM_SYNCHED_NODES]) { debug_printf ("%s\n", "my_server_task started"); unsigned value = 0; while (true) { select { case if_con[unsigned ix].SET_GET (const unsigned value_in) -> {unsigned value_ret} : { debug_printf ("SET_GET[%u] received\n", ix); value = value + value_in; value_ret = value; } break; } } } #if (MY_CONFIG==1) // FROM CLIENTS TO SYNCH: typedef interface wait_if_t { void WAIT_EVENT (void); } wait_if_t; // FROM SYNCH TO CLIENTS: typedef interface next_if_t { void NEXT_EVENT (void); } next_if_t; [[combinable]] void my_synch_task ( server wait_if_t if_wait [NUM_SYNCHED_NODES], client next_if_t if_next [NUM_SYNCHED_NODES]) { debug_printf ("my_synch_task started NUM_SYNCHED_NODES %u, NUM_SYNCHED_NODES_COMBINED %u\n", NUM_SYNCHED_NODES, NUM_SYNCHED_NODES_COMBINED); timer tmr; // one tick every 10 ns time32_t time_ticks; unsigned iof_send_next = 0; unsigned synched_num = 0; unsigned cycle_cnt = 0; while (1) { // looping required since not NORMAL task select { case (iof_send_next != 0) => tmr when timerafter (time_ticks) :> void : { iof_send_next--; debug_printf ("NEXT [%u] send\n", iof_send_next); if_next[iof_send_next].NEXT_EVENT(); debug_printf ("NEXT [%u] sent\n", iof_send_next); tmr :> time_ticks; // now } break; case if_wait[unsigned ix].WAIT_EVENT () : { debug_printf ("WAIT [%u] received, cycle_cnt %u\n", ix, cycle_cnt); synched_num++; if (synched_num == NUM_SYNCHED_NODES) { synched_num = 0; iof_send_next = NUM_SYNCHED_NODES; cycle_cnt++; // par [[combine]] par () here not allowed, taks must be function // Found no combination that the compiler accepted } } break; } } } [[combinable]] void my_client_task ( const unsigned iof_client, client con_if_t if_con, client wait_if_t if_wait, server next_if_t if_next) { debug_printf ("my_client_task %u started\n", iof_client); timer tmr; // one tick every 10 ns time32_t time_ticks; bool synching = false; unsigned cycle_cnt = 0; // Just for time_ticks unsigned value = iof_client + 1; tmr :> time_ticks; // now while (true) { select { case (synching==false) => tmr when timerafter (time_ticks) :> void : { value += if_con.SET_GET (value); debug_printf ("WAIT [%u] send\n", iof_client); if_wait.WAIT_EVENT(); debug_printf ("WAIT [%u] sent\n", iof_client); cycle_cnt++; synching = true; } break; case if_next.NEXT_EVENT(): { debug_printf ("NEXT [%u] received\n", iof_client); synching = false; tmr :> time_ticks; // now time_ticks += (XS1_TIMER_KHZ * ((iof_client+1) * (cycle_cnt%10))); // Random'ish } break; } } } int main (void) { con_if_t if_con [NUM_SYNCHED_NODES]; wait_if_t if_wait [NUM_SYNCHED_NODES]; next_if_t if_next [NUM_SYNCHED_NODES]; par { par { on tile[0].core[0]: my_synch_task (if_wait, if_next); on tile[0].core[1]: my_server_task (if_con); on tile[0]: par { par (unsigned ix = 0; ix < (NUM_SYNCHED_NODES-NUM_SYNCHED_NODES_COMBINED); ix++) { my_client_task (ix, if_con[ix], if_wait[ix], if_next[ix]); } } } on tile[0]: par { [[combine]] par (unsigned ix = (NUM_SYNCHED_NODES-NUM_SYNCHED_NODES_COMBINED); ix < NUM_SYNCHED_NODES; ix++) { my_client_task (ix, if_con[ix], if_wait[ix], if_next[ix]); } } } return 0; } #elif (MY_CONFIG==2) // FROM CLIENTS TO SYNCH AND CALLS BACK: typedef interface synch_if_t { [[notification]] slave void WAIT_EVENT (void); [[clears_notification]] void NEXT_CALL (void); } synch_if_t; [[combinable]] void my_synch_task ( client synch_if_t if_synch [NUM_SYNCHED_NODES]) { debug_printf ("my_synch_task started NUM_SYNCHED_NODES %u\n", NUM_SYNCHED_NODES); timer tmr; // one tick every 10 ns time32_t time_ticks; unsigned iof_send_next = 0; unsigned cycle_cnt = 0; unsigned synched_num = 0; while (1) { // looping required since not NORMAL task select { case (iof_send_next != 0) => tmr when timerafter (time_ticks) :> void : { iof_send_next--; debug_printf ("NEXT [%u] send\n", iof_send_next); if_synch[iof_send_next].NEXT_CALL(); debug_printf ("NEXT [%u] sent\n", iof_send_next); tmr :> time_ticks; // now } break; case if_synch[unsigned ix].WAIT_EVENT() : { debug_printf ("WAIT [%u] received \n", ix); synched_num++; if (synched_num == NUM_SYNCHED_NODES) { synched_num = 0; iof_send_next = NUM_SYNCHED_NODES; cycle_cnt++; } } break; } } } [[combinable]] void my_client_task_ ( const unsigned iof_client, client con_if_t if_con, server synch_if_t if_synch) { debug_printf ("my_client_task %u started\n", iof_client); timer tmr; // one tick every 10 ns time32_t time_ticks; bool synching = false; unsigned cycle_cnt = 0; unsigned value = iof_client + 1; tmr :> time_ticks; // now while (true) { select { case (synching==false) => tmr when timerafter (time_ticks) :> void : { value += if_con.SET_GET (value); debug_printf ("WAIT [%u] send\n", iof_client); if_synch.WAIT_EVENT(); debug_printf ("WAIT [%u] sent\n", iof_client); cycle_cnt++; synching = true; } break; case if_synch.NEXT_CALL(): { debug_printf ("NEXT [%u] received cycle_cnt %u \n", iof_client, cycle_cnt); synching = false; tmr :> time_ticks; // now time_ticks += (XS1_TIMER_KHZ * ((iof_client+1) * (cycle_cnt%10))); // Random'ish } break; } } } [[distributable]] void my_client_task ( const unsigned iof_client, client con_if_t if_con, server synch_if_t if_synch) { debug_printf ("my_client_task %u started\n", iof_client); unsigned cycle_cnt = 0; unsigned value = iof_client + 1; debug_printf ("WAIT [%u] send\n", iof_client); if_synch.WAIT_EVENT(); debug_printf ("WAIT [%u] sent\n", iof_client); while (true) { select { case if_synch.NEXT_CALL(): { debug_printf ("NEXT [%u] received cycle_cnt %u \n", iof_client, cycle_cnt); value += if_con.SET_GET (value); debug_printf ("WAIT [%u] send\n", iof_client); delay_milliseconds(100); if_synch.WAIT_EVENT(); debug_printf ("WAIT [%u] sent\n", iof_client); cycle_cnt++; } break; } } } int main (void) { con_if_t if_con [NUM_SYNCHED_NODES]; synch_if_t if_synch [NUM_SYNCHED_NODES]; par { on tile[0]: par { my_synch_task (if_synch); my_server_task (if_con); } #define DO_DISTRIBUTE 0 // NUM_SYNCHED_NODES == 10 // 0: Cores:2 Timers:2 Chanends:22 RUNS // 1: Cores:1 Timers:1 Chanends:11 RUNS #if (DO_DISTRIBUTE==0) on tile[0]: par { [[combine]] par (unsigned ix = 0; ix < NUM_SYNCHED_NODES; ix++) { my_client_task_ (ix, if_con[ix], if_synch[ix]); // my_client_task (ix, if_con[ix], if_synch[ix]); // Saves nothing since it's started as combinable } } #elif (DO_DISTRIBUTE==1) // THIS IS THE "BEST" CONFIG, BUT IT STILL USES ONE chanend PER my_client_task, // SO HAVING THIS GLOBAL SYNCH MECHANISM IS (PROBABLY) NOT ANY BETTER THAN THE // POLLED SYNCHRONISATION OF _xc_test_Toroid_2.xc TOP_26_TESTING_SYNCH_PHASE par { on tile[0]: [[distribute]] my_client_task (0, if_con[0], if_synch[0]); on tile[0]: [[distribute]] my_client_task (1, if_con[1], if_synch[1]); on tile[0]: [[distribute]] my_client_task (2, if_con[2], if_synch[2]); #if (NUM_SYNCHED_NODES==10) on tile[0]: [[distribute]] my_client_task (3, if_con[3], if_synch[3]); on tile[0]: [[distribute]] my_client_task (4, if_con[4], if_synch[4]); on tile[0]: [[distribute]] my_client_task (5, if_con[5], if_synch[5]); on tile[0]: [[distribute]] my_client_task (6, if_con[6], if_synch[6]); on tile[0]: [[distribute]] my_client_task (7, if_con[7], if_synch[7]); on tile[0]: [[distribute]] my_client_task (8, if_con[8], if_synch[8]); on tile[0]: [[distribute]] my_client_task (9, if_con[9], if_synch[9]); #endif } #endif } return 0; } #endif // ================================ // COMPILATION LOG and RUNTIME LOGS // ================================ #if (MY_CONFIG==1) /* Constraint check for tile[0]: Cores available: 8, used: 5 . OKAY Timers available: 10, used: 5 . OKAY Chanends available: 32, used: 14 . OKAY Memory available: 262144, used: 9220 . OKAY (Stack: 4108, Code: 4112, Data: 1000) Constraints checks PASSED. Constraint check for tile[1]: Cores available: 8, used: 1 . OKAY Timers available: 10, used: 1 . OKAY Chanends available: 32, used: 0 . OKAY Memory available: 262144, used: 1072 . OKAY (Stack: 348, Code: 596, Data: 128) Constraints checks PASSED. my_server_task started my_client_task 0 started my_client_task 1 started my_synch_task started NUM_SYNCHED_NODES 3, NUM_SYNCHED_NODES_COMBINED 1 my_client_task 2 started SET_GET[0] received WAIT [0] send SET_GET[1] received WAIT [0] received, cycle_cnt 0 SET_GET[2] received WAIT [0] sent WAIT [1] send WAIT [2] send WAIT [1] received, cycle_cnt 0 WAIT [1] sent WAIT [2] received, cycle_cnt 0 WAIT [2] sent NEXT [2] send NEXT [2] received NEXT [2] sent NEXT [1] send NEXT [1] received NEXT [1] sent NEXT [0] send NEXT [0] received NEXT [0] sent SET_GET[0] received WAIT [0] send WAIT [0] received, cycle_cnt 1 WAIT [0] sent SET_GET[1] received WAIT [1] send WAIT [1] received, cycle_cnt 1 WAIT [1] sent SET_GET[2] received WAIT [2] send WAIT [2] received, cycle_cnt 1 WAIT [2] sent NEXT [2] send NEXT [2] received NEXT [2] sent NEXT [1] send NEXT [1] received NEXT [1] sent NEXT [0] send NEXT [0] received NEXT [0] sent SET_GET[0] received WAIT [0] send WAIT [0] received, cycle_cnt 2 WAIT [0] sent SET_GET[1] received WAIT [1] send WAIT [1] received, cycle_cnt 2 WAIT [1] sent SET_GET[2] received WAIT [2] send WAIT [2] received, cycle_cnt 2 */ #elif (MY_CONFIG==2) /* Constraint check for tile[0]: Cores available: 8, used: 2 . OKAY Timers available: 10, used: 2 . OKAY Chanends available: 32, used: 22 . OKAY Memory available: 262144, used: 12364 . OKAY (Stack: 4564, Code: 6616, Data: 1184) Constraints checks PASSED. Constraint check for tile[1]: Cores available: 8, used: 1 . OKAY Timers available: 10, used: 1 . OKAY Chanends available: 32, used: 0 . OKAY Memory available: 262144, used: 1072 . OKAY (Stack: 348, Code: 596, Data: 128) Constraints checks PASSED. my_server_task started my_client_task 0 started my_synch_task started NUM_SYNCHED_NODES 10 my_client_task 1 started my_client_task 2 started my_client_task 3 started my_client_task 4 started my_client_task 5 started my_client_task 6 started my_client_task 7 started my_client_task 8 started my_client_task 9 started SET_GET[0] received WAIT [0] send WAIT [0] sent WAIT [0] received SET_GET[1] received WAIT [1] send WAIT [1] sent WAIT [1] received SET_GET[2] received WAIT [2] send WAIT [2] sent WAIT [2] received SET_GET[3] received WAIT [3] send WAIT [3] sent WAIT [3] received SET_GET[4] received WAIT [4] send WAIT [4] sent WAIT [4] received SET_GET[5] received WAIT [5] send WAIT [5] sent WAIT [5] received SET_GET[6] received WAIT [6] send WAIT [6] sent WAIT [6] received SET_GET[7] received WAIT [7] send WAIT [7] sent WAIT [7] received SET_GET[8] received WAIT [8] send WAIT [8] sent WAIT [8] received SET_GET[9] received WAIT [9] send WAIT [9] sent WAIT [9] received NEXT [9] send NEXT [9] received cycle_cnt 1 NEXT [9] sent NEXT [8] send NEXT [8] received cycle_cnt 1 NEXT [8] sent NEXT [7] send NEXT [7] received cycle_cnt 1 NEXT [7] sent NEXT [6] send NEXT [6] received cycle_cnt 1 NEXT [6] sent NEXT [5] send NEXT [5] received cycle_cnt 1 NEXT [5] sent NEXT [4] send NEXT [4] received cycle_cnt 1 NEXT [4] sent NEXT [3] send NEXT [3] received cycle_cnt 1 NEXT [3] sent NEXT [2] send NEXT [2] received cycle_cnt 1 NEXT [2] sent NEXT [1] send NEXT [1] received cycle_cnt 1 NEXT [1] sent NEXT [0] send NEXT [0] received cycle_cnt 1 NEXT [0] sent SET_GET[0] received WAIT [0] send WAIT [0] sent WAIT [0] received SET_GET[1] received WAIT [1] send WAIT [1] sent WAIT [1] received SET_GET[2] received WAIT [2] send WAIT [2] sent WAIT [2] received SET_GET[3] received WAIT [3] send WAIT [3] sent WAIT [3] received SET_GET[4] received WAIT [4] send WAIT [4] sent WAIT [4] received SET_GET[5] received WAIT [5] send WAIT [5] sent WAIT [5] received SET_GET[6] received WAIT [6] send WAIT [6] sent WAIT [6] received SET_GET[7] received WAIT [7] send WAIT [7] sent WAIT [7] received SET_GET[8] received WAIT [8] send WAIT [8] sent WAIT [8] received SET_GET[9] received WAIT [9] send WAIT [9] sent WAIT [9] received NEXT [9] send NEXT [9] received cycle_cnt 2 NEXT [9] sent NEXT [8] send NEXT [8] received cycle_cnt 2 NEXT [8] sent NEXT [7] send NEXT [7] received cycle_cnt 2 NEXT [7] sent NEXT [6] send NEXT [6] received cycle_cnt 2 NEXT [6] sent NEXT [5] send NEXT [5] received cycle_cnt 2 NEXT [5] sent NEXT [4] send NEXT [4] received cycle_cnt 2 NEXT [4] sent NEXT [3] send NEXT [3] received cycle_cnt 2 NEXT [3] sent NEXT [2] send NEXT [2] received cycle_cnt 2 NEXT [2] sent NEXT [1] send NEXT [1] received cycle_cnt 2 NEXT [1] sent NEXT [0] send NEXT [0] received cycle_cnt 2 NEXT [0] sent SET_GET[0] received WAIT [0] send WAIT [0] sent WAIT [0] received SET_GET[1] received WAIT [1] send WAIT [1] sent WAIT [1] received SET_GET[2] received WAIT [2] send WAIT [2] sent WAIT [2] received SET_GET[3] received WAIT [3] send WAIT [3] sent WAIT [3] received SET_GET[4] received WAIT [4] send WAIT [4] sent WAIT [4] received SET_GET[5] received WAIT [5] send WAIT [5] sent WAIT [5] received SET_GET[6] received WAIT [6] send WAIT [6] sent WAIT [6] received SET_GET[7] received WAIT [7] send WAIT [7] sent WAIT [7] received SET_GET[8] received WAIT [8] send WAIT [8] sent WAIT [8] received SET_GET[9] received WAIT [9] send WAIT [9] sent WAIT [9] received NEXT [9] send NEXT [9] received cycle_cnt 3 */ #endif