/* * top_03_guarded_xc.h * * Created on: 25. feb. 2021 * Author: teig */ #ifndef TOP_03_GUARDED_XC_H_ #define TOP_03_GUARDED_XC_H_ #if (TOPOLOGY != TOP_03G_HAS_2_TILE_016_NODE_T0_2N_AS_CC_6CN_T1_8CN_NO_BUILD) // in _xc_test_combinable.xc #error #endif // This has to do with [[guarded]] // Compile with AVOID_COMPILER_CRASH==1 to see that this source code compiles (but without any "main") // XMOS ticket #158323# on 2021 02 26 // XMOS ticket #32474# on 2020 02 11 // XMOS ticket #31286# on 2018 06 26 // xcc1: internal compiler error // Failed in // /jenkins/RELEASE_14_4/sb/tools_xcc1_c_llvm/FrontEnd/Lowering/lower_combined_pars.cpp, line 183 // info->stateObj // I have reported this to XMOS some years ago, but it still exists on 14.4.1 typedef interface g_conn_if_t { [[guarded]] {pos_t, unsigned} do_io_server ( const unsigned value_to, const pos_t pos, const unsigned call_cnt); } g_conn_if_t; // TASK Server_node_guarded // #if (TOP_03G_AS_PARTLY_DISTRUBUTED == 1) [[distributable]] #elif (TOP_03G_AS_PARTLY_DISTRUBUTED == 0) [[combinable]] #endif void Server_node_guarded ( const unsigned iof_row, const unsigned iof_col, server g_conn_if_t i_conn_0, // An array here is not allowed if I need individual guards server g_conn_if_t i_conn_1, server g_conn_if_t i_conn_2, const unsigned iof_pair) { server_context_t context; bool guard_0 = true; bool guard_1 = true; bool guard_2 = true; init_value (iof_row, iof_col, context.vals); debug_print ("(%u %u):S[%u] = %u.%u.d%u\n", iof_row, iof_col, context.vals.value, iof_row, iof_pair, NUM_CONNS_PER_NODE); // un-const ok, since I don't change them anyhow: context.my_pos.iof_row = iof_row; context.my_pos.iof_col = iof_col; context.cycle_cnt = 0; context.num_neighbours_seen = 0; context.time_tmr :> context.time_now_ticks; context.time_previous_ticks = context.time_now_ticks; while (1) { select { case guard_0 => i_conn_0.do_io_server ( const unsigned value_to, const pos_t client_pos, const unsigned call_cnt) -> {pos_t pos_return, unsigned value_from} : { context.iof_client = context.num_neighbours_seen; context.iof_connections[context.iof_client] = 0; // {pos_return, value_from} = Handle_server (value_to, client_pos, call_cnt, context); if (context.num_neighbours_seen == 0) { // zero set in Handle_server when all seen guard_0 = true; guard_1 = true; guard_2 = true; } else { guard_0 = false; } } break; case guard_1 => i_conn_1.do_io_server ( const unsigned value_to, const pos_t client_pos, const unsigned call_cnt) -> {pos_t pos_return, unsigned value_from} : { context.iof_client = context.num_neighbours_seen; context.iof_connections[context.iof_client] = 1; // {pos_return, value_from} = Handle_server (value_to, client_pos, call_cnt, context); if (context.num_neighbours_seen == 0) { // zero set in Handle_server when all seen guard_0 = true; guard_1 = true; guard_2 = true; } else { guard_1 = false; } } break; case guard_2 => i_conn_2.do_io_server ( const unsigned value_to, const pos_t client_pos, const unsigned call_cnt) -> {pos_t pos_return, unsigned value_from} : { context.iof_client = context.num_neighbours_seen; context.iof_connections[context.iof_client] = 2; // {pos_return, value_from} = Handle_server (value_to, client_pos, call_cnt, context); if (context.num_neighbours_seen == 0) { // zero set in Handle_server when all seen guard_0 = true; guard_1 = true; guard_2 = true; } else { guard_2 = false; } } break; } } } // Server_node_guarded bool Handle_client_guarded ( // return true when NUM_CONNS_PER_NODE client g_conn_if_t i_conn_0, // Hard coded: not possible to use NUM_CONNS_PER_NODE-dimensioned array here client g_conn_if_t i_conn_1, client g_conn_if_t i_conn_2, client_context_t &context) { bool all_servers_handled = false; debug_print_special ("HC0 %u\n", context.iof_server); DEBUG_PRINT_HANDLE_CLIENT_1 (context); switch (context.iof_server) { // Hard coded with NUM_CONNS_PER_NODE==3 case 0 : { {context.server_pos[0], context.vals.values[0]} = i_conn_0.do_io_server (context.vals.value, context.my_pos, context.call_cnt); } break; // OUTPUT and INPUT case 1 : { {context.server_pos[1], context.vals.values[1]} = i_conn_1.do_io_server (context.vals.value, context.my_pos, context.call_cnt); } break; // OUTPUT and INPUT case 2 : { {context.server_pos[2], context.vals.values[2]} = i_conn_2.do_io_server (context.vals.value, context.my_pos, context.call_cnt); } break; // OUTPUT and INPUT // default: break; // Not possible, crash } context.call_cnts[context.iof_server] = context.call_cnt; DEBUG_PRINT_HANDLE_CLIENT_2 (context); context.iof_server++; context.call_cnt = (context.call_cnt+1) % CALL_CNT_MAX; context.time_tmr :> context.timeout_ticks; // AFTER now = immediate (i.e. as often as possible), or will get added ROOT_WAIT_FOR_NEXT_ROUND_US later all_servers_handled = (context.iof_server == NUM_CONNS_PER_NODE); if (all_servers_handled) { const unsigned old_value = context.vals.value; time32_t time_used_ticks; bool overflow; {overflow, context.vals.value} = Calculate (context.vals); // In Handle_client context.iof_server = 0; context.time_tmr :> context.timeout_ticks; time_used_ticks = context.timeout_ticks - context.time_previous_ticks; if (time_used_ticks > 0) { const unsigned time_sec = (unsigned) time_used_ticks / (unsigned) XS1_TIMER_HZ; } else { fail ("time_used_ticks <= 0"); // Zero time or longer than some 21 seconds (2exp31 * 10 ns) } context.time_previous_ticks = context.timeout_ticks; DEBUG_PRINT_HANDLE_CLIENT_3 (context, old_value, overflow); context.cycle_cnt++; } else {} context.timeout_ticks += ROOT_WAIT_FOR_NEXT_ROUND_US; // delay_tics used in Server_node. No skew here return all_servers_handled; } // Handle_client_guarded [[combinable]] void Client_node_guarded ( const unsigned iof_row, const unsigned iof_col, client g_conn_if_t i_conn_0, // Hard coded: not possible to use NUM_CONNS_PER_NODE-dimensioned array here const unsigned iof_row_0, const unsigned iof_pair_0, const unsigned iof_link_0, client g_conn_if_t i_conn_1, const unsigned iof_row_1, const unsigned iof_pair_1, const unsigned iof_link_1, client g_conn_if_t i_conn_2, const unsigned iof_row_2, const unsigned iof_pair_2, const unsigned iof_link_2) { client_context_t context; init_value (iof_row, iof_col, context.vals); debug_print ("(%u %u):C[%u] = %u.%u.%u - %u.%u.%u - %u.%u.%u\n", iof_row, iof_col, context.vals.value, iof_row_0, iof_pair_0, iof_link_0, iof_row_1, iof_pair_1, iof_link_1, iof_row_2, iof_pair_2, iof_link_2); // un-const ok, since I don't change them anyhow: context.my_pos.iof_row = iof_row; context.my_pos.iof_col = iof_col; context.cycle_cnt = 0; context.iof_server = 0; context.call_cnt = 0; context.time_tmr :> context.timeout_ticks; // AFTER now = immediate context.time_previous_ticks = context.timeout_ticks; while (1) { select { case context.time_tmr when timerafter (context.timeout_ticks) :> void : { // Needed, since main select in combinable function cannot have default case Handle_client_guarded (i_conn_0, i_conn_1, i_conn_2, context); } break; } } } // Client_node_guarded #endif /* TOP_03_GUARDED_XC_H_ */