/* * top_20_occam_like_xc.h * * Created on: 12. mars 2021 * Author: teig */ #ifndef TOP_20_OCCAM_LIKE_XC_H_ #define TOP_20_OCCAM_LIKE_XC_H_ #if (TOPOLOGY != TOP_20_HAS_2_TILE_004_T0_2N_BY3SUB_T1_2N_BY3SUB_RUNS_FAIR) #error Not TOP_20 #endif /* _______ ____ _____ ___ ___ |__ __/ __ \| __ \ |__ \ / _ \ | | | | | | |__) | ) | | | | | | | | | | ___/ / /| | | | | | | |__| | | / /_| |_| | |_| \____/|_| |____|\___/ */ // ========================================= // CLIENT TASKS (ONE ROOT AND ONE STANDARD) // ========================================= // typedef chan ... chans don't have types. It's up to the user to ensure that sent and received are equal void Client_node_3_composite_par_root ( // With ROOT_WAIT_FOR_NEXT_ROUND_US=0 round trip about 1.24 us const unsigned iof_row, const unsigned iof_col, chanend chan_0, chanend chan_1, chanend chan_2, out buffered port:4 outP4_leds) { node_context_t context; const params_t params = init_params (); temp_degC_t temp_degC = init_temp (iof_row,iof_col, params); init_wt (iof_row, iof_col, context.wt, params); init_context (iof_row, iof_col, context); // Root only timer tmr; time32_t time_ticks; time32_t time_start_ticks; time32_t time_stop_ticks; unsigned leds = BOARD_LEDS_INIT; outP4_leds <: leds; PRINT_BANNER_ROOT (context, CLIENT_ROOT_STR, "Client_node_3_composite_par_root", temp_degC, TOP_STR); XSCOPE_INT (VALUE, XSCOPE_SCALE_MAX); XSCOPE_INT (VALUE, XSCOPE_SCALE_MIN); tmr :> time_ticks; while (1) { select { case tmr when timerafter (time_ticks) :> time_start_ticks : { // No skew here par { { // subtask 1 chan_0 <: temp_degC; chan_0 :> context.temps_degC[0]; } { // subtask 2 chan_1 <: temp_degC; chan_1 :> context.temps_degC[1]; } { // subtask 3 chan_2 <: temp_degC; chan_2 :> context.temps_degC[2]; } } context.cycle_cnt++; temp_degC = calculate_new_temp_from_flow (context, temp_degC); PRINT_VALUES_WITH_TIME (context, CLIENT_ROOT_STR, tmr, temp_degC); // Swap LED leds xor_eq BOARD_LED_MASK_GREEN_ONLY; // J1.7 CH1 XCORE-200-EXPLORER outP4_leds <: leds; XSCOPE_INT (VALUE, leds ? XSCOPE_VALUE_TRUE : XSCOPE_VALUE_FALSE); tmr :> time_stop_ticks; { const time32_t time_used_ticks = time_stop_ticks - time_start_ticks; if (time_used_ticks >= ROOT_WAIT_FOR_NEXT_ROUND_US) { // Re-read "now" when ROOT_WAIT_FOR_NEXT_ROUND_US is shorter than round trip (here 0 or 1 us). // Round trip is about 1.25 us, almost "unbelievably" fast since all the other // three nodes also start and stop their communication subtasks and communicate back // and forth, even across tiles tmr :> time_ticks; // This seems to take "no time" } else { // ROOT_WAIT_FOR_NEXT_ROUND_US here typically 2 us and above time_ticks += ROOT_WAIT_FOR_NEXT_ROUND_US; // No skew } } } break; } } } // Client_node_3_composite_par_root void Client_node_3_composite_par ( const unsigned iof_row, const unsigned iof_col, chanend chan_0, chanend chan_1, chanend chan_2) { node_context_t context; const params_t params = init_params (); temp_degC_t temp_degC = init_temp (iof_row,iof_col, params); init_wt (iof_row, iof_col, context.wt, params); init_context (iof_row, iof_col, context); PRINT_BANNER (context, CLIENT_STR, "Client_node_3_composite_par", temp_degC); while (1) { // Client_node_3_composite_par par { { // subtask 1 chan_0 <: temp_degC; chan_0 :> context.temps_degC[0]; } { // subtask 2 chan_1 <: temp_degC; chan_1 :> context.temps_degC[1]; } { // subtask 3 chan_2 <: temp_degC; chan_2 :> context.temps_degC[2]; } } context.cycle_cnt++; temp_degC = calculate_new_temp_from_flow (context, temp_degC); PRINT_VALUES (context, CLIENT_STR, temp_degC); } } // Client_node_3_composite_par // ============= // SERVER TASK // ============= void Server_node_3_composite_par ( const unsigned iof_row, const unsigned iof_col, chanend chan_0, chanend chan_1, chanend chan_2) { node_context_t context; const params_t params = init_params (); temp_degC_t temp_degC = init_temp (iof_row,iof_col, params); init_wt (iof_row, iof_col, context.wt, params); init_context (iof_row, iof_col, context); PRINT_BANNER (context, SERVER_STR, "Server_node_3_composite_par", temp_degC); while (1) { // Server_node_3_composite_par par { { // subtask 1 chan_0 :> context.temps_degC[0]; chan_0 <: temp_degC; } { // subtask 2 chan_1 :> context.temps_degC[1]; chan_1 <: temp_degC; } { // subtask 3 chan_2 :> context.temps_degC[2]; chan_2 <: temp_degC; } } context.cycle_cnt++; temp_degC = calculate_new_temp_from_flow (context, temp_degC); PRINT_VALUES (context, SERVER_STR, temp_degC); } } // Server_node_3_composite_par // ---------------------- // ALWAYS TOROID TOPOLOGY // ---------------------- int main (void) { #if (TOP_WARNINGS==1) // From "makefile" #warning TOP_STR "Top_20 runs" #endif /* Constraint check for tile[0]: Cores available: 8, used: 6 . OKAY Timers available: 10, used: 6 . OKAY Chanends available: 32, used: 7 . OKAY Memory available: 262144, used: 5220 . OKAY (Stack: 1076, Code: 3328, Data: 816) Constraints checks PASSED. Constraint check for tile[1]: Cores available: 8, used: 6 . OKAY Timers available: 10, used: 6 . OKAY Chanends available: 32, used: 7 . OKAY Memory available: 262144, used: 4908 . OKAY (Stack: 1076, Code: 3060, Data: 772) Constraints checks PASSED. Build Complete TOP_20_HAS_2_TILE_004_T0_2N_BY3SUB_T1_2N_BY3SUB_RUNS_FAIR par on tile[0]: par Client (0 0) par subtask 1 on core[0] subtask 2 on core[1] subtask 1 on core[2] Server (0 1) par subtask 1 on core[3] subtask 2 on core[4] subtask 1 on core[5] on tile[1]: par Client (1 0) par subtask 1 on core[0] subtask 2 on core[1] subtask 1 on core[2] Server (1 1) par subtask 1 on core[3] subtask 2 on core[4] subtask 1 on core[5] */ #define VER_NS_X [1][0][1] // NS North-South top-bottom #define HOR_1_EW [1][0][2] // EW EastWest belt side-to-side #define HOR_1_A [1][0][0] // [A,B,C] Between horisontal columns #define VER_01_X [0][0][1] // [X,Y,Z] Between vertical rows #define HOR_0_EW [0][0][2] // EW EastWest belt side-to-side #define HOR_0_A [0][0][0] // [A,B,C] Between horisontal columns chan chans [NUM_ROWS][NUM_PAIRS_PER_ROW][NUM_CONNS_PER_NODE]; // [ROW][PAIR][CONN] = [R][P][C] // [ 2 ][ 1 ][ 3 ] par { on tile[0]: par { Client_node_3_composite_par_root (0,0, chans HOR_0_EW, chans VER_NS_X, chans HOR_0_A, outP4_leds); Server_node_3_composite_par (0,1, chans HOR_0_A, chans VER_01_X, chans HOR_0_EW); } on tile[1]: par { Client_node_3_composite_par (1,0, chans HOR_1_EW, chans VER_01_X, chans HOR_1_A); Server_node_3_composite_par (1,1, chans HOR_1_A, chans VER_NS_X, chans HOR_1_EW); } } return 0; } // main #endif /* TOP_20_OCCAM_LIKE_XC_H_ */ // ====================================================== // Simplified code for the presentation at IEEE-COPA 2021 // ====================================================== void Client_node ( const unsigned iof_row, const unsigned iof_col, chanend chan_0, chanend chan_1, chanend chan_2) { node_context_t context; const params_t params = init_params (); temp_degC_t temp_degC = init_temp ( iof_row,iof_col, params); init_wt (iof_row, iof_col, context.wt, params); init_context (iof_row, iof_col, context); while (1) { // Client_node_3_composite_par par { { // subtask 1 chan_0 <: temp_degC; chan_0 :> context.temps_degC[0]; } { // subtask 2 chan_1 <: temp_degC; chan_1 :> context.temps_degC[1]; } { // subtask 3 chan_2 <: temp_degC; chan_2 :> context.temps_degC[2]; } } context.cycle_cnt++; temp_degC = calculate_new_temp_from_flow ( context, temp_degC); } } // ============= // SERVER TASK // ============= void Server_node ( const unsigned iof_row, const unsigned iof_col, chanend chan_0, chanend chan_1, chanend chan_2) { node_context_t context; const params_t params = init_params (); temp_degC_t temp_degC = init_temp ( iof_row,iof_col, params); init_wt (iof_row, iof_col, context.wt, params); init_context (iof_row, iof_col, context); while (1) { par { { // subtask 1 chan_0 :> context.temps_degC[0]; chan_0 <: temp_degC; } { // subtask 2 chan_1 :> context.temps_degC[1]; chan_1 <: temp_degC; } { // subtask 3 chan_2 :> context.temps_degC[2]; chan_2 <: temp_degC; } } context.cycle_cnt++; temp_degC = calculate_new_temp_from_flow ( context, temp_degC); } }