void init() { // Init core enumerations me.coreID = e_get_coreid(); e_coords_from_coreid(me.coreID, &me.row, &me.col); me.row = me.row - E_FIRST_CORE_ROW; me.col = me.col - E_FIRST_CORE_COL; me.corenum = me.row * E_COLS_IN_CHIP + me.col; me.coreIDh = me.coreID; e_neighbor_id((e_coreid_t *) &me.coreIDh, E_PREV_CORE, E_ROW_WRAP); me.coreIDv = me.coreID; e_neighbor_id((e_coreid_t *) &me.coreIDv, E_PREV_CORE, E_COL_WRAP); me.coreIDn = me.coreID; e_neighbor_id((e_coreid_t *) &me.coreIDn, E_NEXT_CORE, E_CHIP_WRAP); // Initialize the mailbox shared buffer pointers Mailbox.pBase = (void *) SHARED_DRAM; Mailbox.pA = Mailbox.pBase + offsetof(shared_buf_t, A[0]); Mailbox.pB = Mailbox.pBase + offsetof(shared_buf_t, B[0]); Mailbox.pC = Mailbox.pBase + offsetof(shared_buf_t, C[0]); Mailbox.pCore = Mailbox.pBase + offsetof(shared_buf_t, core); // Initialize per-core parameters - core data structure // Initialize pointers to the operand matrices ping-pong arrays me.bank[_BankA][_PING] = (void *) &(AA[0][0][0]); me.bank[_BankA][_PONG] = (void *) &(AA[1][0][0]); me.bank[_BankB][_PING] = (void *) &(BB[0][0][0]); me.bank[_BankB][_PONG] = (void *) &(BB[1][0][0]); me.bank[_BankC][_PING] = (void *) &(CC [0][0]); // Initialize the pointer addresses of the arrays in the horizontal and vertical target // cores, where the submatrices data will be swapped, and the inter-core sync signals. me.tgt_bk[_BankA][_PING] = _gptr(me.coreIDh, me.bank[_BankA][_PONG]); me.tgt_bk[_BankA][_PONG] = _gptr(me.coreIDh, me.bank[_BankA][_PING]); me.tgt_synch = _gptr(me.coreIDh, (&(me.synch))); me.tgt_bk[_BankB][_PING] = _gptr(me.coreIDv, me.bank[_BankB][_PONG]); me.tgt_bk[_BankB][_PONG] = _gptr(me.coreIDv, me.bank[_BankB][_PING]); me.tgt_syncv = _gptr(me.coreIDv, (&(me.syncv))); me.tgt_go_sync = _gptr(me.coreIDn, (&(me.go_sync))); me.tgt_dma_sync = _gptr(me.coreIDn, (&(me.dma_sync))); me.pingpong = _PING; // Clear the inter-core sync signals me.synch = 0; me.syncv = 0; me.go_sync = 0; me.dma_sync = (me.corenum == 0) ? 1 : 0; // Init the host-accelerator sync signals Mailbox.pCore->go[me.corenum] = 0; if (me.corenum == 0) Mailbox.pCore->ready = 1; me.count = 0; return; }
void init() { // Init core enumerations me.coreID = e_get_coreid(); e_coords_from_coreid(me.coreID, &me.row, &me.col); me.row = me.row - E_FIRST_CORE_ROW; me.col = me.col - E_FIRST_CORE_COL; me.corenum = me.row * E_COLS_IN_CHIP + me.col; me.coreIDn = me.coreID; e_neighbor_id((e_coreid_t *) &me.coreIDn, E_NEXT_CORE, E_CHIP_WRAP); // Initialize the mailbox shared buffer pointers Mailbox.pBase = (void *) MAILBOX_ADDRESS; Mailbox.pGo = Mailbox.pBase + offsetof(mbox_t, go[0]); Mailbox.pReady = Mailbox.pBase + offsetof(mbox_t, ready[0]); Mailbox.pClocks = Mailbox.pBase + offsetof(mbox_t, clocks); #if 0 Mailbox.pOutputBuffer = Mailbox.pBase + offsetof(mbox_t, output_buffer[0]); Mailbox.pOutputReady = Mailbox.pBase + offsetof(mbox_t, output_ready); #endif Mailbox.pTimer0 = Mailbox.pBase + offsetof(mbox_t, timer0); Mailbox.pTimer1 = Mailbox.pBase + offsetof(mbox_t, timer1); // Init the ports init_input_port(&X); // Set the port pointer, the address must be global scale.X = (me.coreID << 20) | (int) &X; #ifdef FULL init_output_port(&Y); scale.Y = (me.coreID << 20) | (int) &Y; #endif scale.coreID = me.coreID; // Set the global actor pointer(don't forget to use global address) actors.scale = (me.coreID << 20) | (int) &scale; me.count = 0; // Coefficients W0[0] = 2048; W0[1] = 2676; W0[2] = 2841; W0[3] = 1609; W1[0] = 2048; W1[1] = 1108; W1[2] = 565; W1[3] = 2408; ww0 = W0[0]; ww1 = 2048; index0 = 0; // Init the host-accelerator sync signals Mailbox.pReady[me.corenum] = &me.mystate; return; }
int main(void) { unsigned mesh_reg; unsigned mesh_reg_modify; unsigned time_c, time_p; unsigned time; unsigned tran,k,i,j,h,m,n,q; unsigned *mailbox, *mode; unsigned *commander; unsigned *counter; unsigned *master, *slave, *p; unsigned *row, *col; unsigned *n_row, *n_col; unsigned *neighbour0, *neighbour1, *neighbour2, *neighbour3; row = (unsigned *)0x5000; col = (unsigned *)0x5004; n_row = (unsigned *)0x5008; n_col = (unsigned *)0x500c; master = (unsigned *)0x2000; p =(unsigned *) 0x2000; slave = (unsigned *) e_get_global_address(*row, *col, p); commander = (unsigned *)0x5100; p = (unsigned *) 0x5300; counter = (unsigned *) e_get_global_address(*row, *col, p); mailbox = (unsigned *)0x6000; mode = (unsigned *)0x5400; tran = 2048; // Core number k = (e_group_config.core_row)*e_group_config.group_cols + (e_group_config.core_col); // Broadcast to all the other neighbours p = (unsigned *)0x5100; e_neighbor_id(E_PREV_CORE, E_ROW_WRAP, n_row, n_col); neighbour0 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_ROW_WRAP, n_row, n_col); neighbour1 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_PREV_CORE, E_COL_WRAP, n_row, n_col); neighbour2 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_COL_WRAP, n_row, n_col); neighbour3 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; // Initialize master and slave for(i=0; i<tran; i++) { master[i] = 0xdeadbee9; slave[i] = 0x00000000; } while(1) { //Clear the mode box mode[0] = 0xdeadbeef; // Clear the start commander commander[0] = 0x00000000; // Wait for the mesh event while(mode[0] == 0xdeadbeef) {}; q = mode[0]; mesh_reg = e_reg_read(E_REG_MESH_CONFIG); mesh_reg_modify = mesh_reg & 0xffffff0f; mesh_reg_modify = mesh_reg_modify |mesh_type[1][q]; e_reg_write(E_REG_MESH_CONFIG, mesh_reg_modify); // Set the ctimer e_ctimer_set(E_CTIMER_0, E_CTIMER_MAX) ; // Waiting for the signal to start transfering while(commander[0] != 0xdeadbeef) {}; // Start the ctimer and select the time type time_p = e_ctimer_start(E_CTIMER_0, E_CTIMER_MESH_0); // Broadcast to all the other neighbours neighbour0[0] = 0xdeadbeef; neighbour1[0] = 0xdeadbeef; neighbour2[0] = 0xdeadbeef; neighbour3[0] = 0xdeadbeef; e_dma_copy(slave, master, 0x2000); // Wait for transfer finishing while(slave[2047] != 0xdeadbee9 ) {}; counter[k] = 1; // Get the time now time_c = e_ctimer_get(E_CTIMER_0); time = time_p - time_c; // Output the result mailbox[q] = time; // Load the original value of E_REG_MESH_CONFIG e_reg_write(E_REG_MESH_CONFIG, mesh_reg); // Check if all the mesh events have been through if(q == 12) { break; } } return 0; }
int main(void) { unsigned time_c, time_p; unsigned time; unsigned i,j,q,h,m,n,k; unsigned *commander; unsigned *counter; unsigned *mailbox; unsigned *n_row, *n_col; unsigned *neighbour0, *neighbour1, *neighbour2, *neighbour3, *p; commander = (unsigned *)0x6100; counter = (unsigned *)0x6300; mailbox = (unsigned *)0x5000; n_row = (unsigned *)0x5100; n_col = (unsigned *)0x5200; p = (unsigned *)0x6100; // Broadcast to all neighbours e_neighbor_id(E_PREV_CORE, E_ROW_WRAP, n_row, n_col); neighbour0 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_ROW_WRAP, n_row, n_col); neighbour1 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_PREV_CORE, E_COL_WRAP, n_row, n_col); neighbour2 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_COL_WRAP, n_row, n_col); neighbour3 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; // Get core information k = e_group_config.core_row * e_group_config.group_cols + e_group_config.core_col; // Clear the counter of finishing transfering for(i=0; i<(e_group_config.group_rows*e_group_config.group_cols); i++) { counter[i] = 0; } // Initialize the commander and counter for the specific core counter[k] = 1; commander[0] = 0x00000000; // Set the ctimer e_ctimer_set(E_CTIMER_0, E_CTIMER_MAX) ; // Waiting for the signal of starting transfering while(commander[0] != (unsigned)0xdeadbeef) {}; // Broadcast the signal to neighbours neighbour0[0] = 0xdeadbeef; neighbour1[0] = 0xdeadbeef; neighbour2[0] = 0xdeadbeef; neighbour3[0] = 0xdeadbeef; // Start the ctimer and select the time type time_p = e_ctimer_start(E_CTIMER_0, E_CTIMER_CLK); while(1) { if((counter[0]&counter[1]&counter[2]&counter[3]&counter[4]&counter[5] &counter[6]&counter[7]&counter[8]&counter[9]&counter[10]&counter[11] &counter[12]&counter[13]&counter[14]&counter[15]) != 0) { time_c = e_ctimer_get(E_CTIMER_0); break; } } time = time_p - time_c; mailbox[0] = time; return 0; }
int main(void) { unsigned time_c, time_p; unsigned time; unsigned tran,k,i,j,q,h,m,n; unsigned *commander; unsigned *n_row, *n_col, *p, *nei_row, *nei_col; unsigned *neighbour, *neighbour0; unsigned *master; unsigned *counter; // Define the mailbox master = (unsigned *)0x2000; n_row = (unsigned *)0x6000; n_col = (unsigned *)0x6004; neighbour0 = (unsigned *)0x6008; nei_row = (unsigned *) 0x600c; nei_col = (unsigned *) 0x6010; p =(unsigned *) 0x2000; commander = (unsigned *)0x6100; counter = (unsigned *)0x80806300; tran = 2048; // Get the neighbour global address e_neighbor_id(E_PREV_CORE, E_ROW_WRAP, n_row, n_col); neighbour = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; k = (*n_row)*e_group_config.group_cols + (*n_col); commander[0] = 0x00000000; // Broadcast to the next core p = (unsigned *)0x6100; e_neighbor_id(E_NEXT_CORE, E_COL_WRAP, nei_row, nei_col); neighbour0 = (unsigned *) e_get_global_address(*nei_row, *nei_col, p) ; // Initialize master and slave for(i=0; i<tran; i++) { master[i] = 0xdeadbee1; neighbour[i] = 0x00000000; } // Waiting for the signal to start transfering while(commander[0] != (unsigned) 0xdeadbeef) {}; // Broadcast the signal to neighbour neighbour0[0] = 0xdeadbeef; // Write to all neighbour cores e_dma_copy(neighbour, master, 0x2000); while(1) { if(neighbour[2047] == 0xdeadbee1) { counter[e_group_config.core_row * (e_group_config.group_cols/2) + e_group_config.core_col] = 1; break; } } return 0; }
int main(void) { unsigned k,i,j; e_dma_desc_t dma_desc[4]; unsigned *dst, *src, *dst1, *src1, *dst2, *src2; unsigned tran; unsigned tran1; unsigned index[3]; unsigned neighbour_core; unsigned *n_row, *n_col, *p; unsigned *mailbox, *mailbox1, *mailbox2, *mailbox3; n_row = (unsigned *)0x00006400; n_col = (unsigned *)0x00006404; tran = 128; p = 0x0000; // Get the core id of neighbour core e_neighbor_id(E_NEXT_CORE, E_ROW_WRAP, n_row, n_col); neighbour_core = (unsigned) e_get_global_address(*n_row, *n_col, p); // Define the mailbox mailbox = (unsigned *)0x6000; mailbox1 = (unsigned *)0x6100; mailbox2 = (unsigned *)0x6200; mailbox3 = (unsigned *)0x6300; // Initialize the buffer address for dma chain test src = (int *)0x2000; dst = (int *)(neighbour_core + (unsigned)0x2000); src1 = (int *)0x2300; dst1 = (int *)(neighbour_core + (unsigned)0x2500); src2 = (int *)0x2600; dst2 = (int *)(neighbour_core + (unsigned)0x2a00); // Test for word size // Initialize the source and destination buffer for (i=0; i<tran; i++) { src[i] = 0xaaaaaaaa; src1[i] = 0xbbbbbbbb; src2[i] = 0xcccccccc; } for (i=0; i<tran*6; i++) { dst[i] = 0x00000000; } // Prepare for the descriptor for 2d dma e_dma_set_desc(E_DMA_0,(E_DMA_ENABLE|E_DMA_MASTER|E_DMA_WORD), 0x0000, 0x0004, 0x0004, 0x0080, 0x0003, 0x0104 , 0x0304, (void *)src,(void *)dst, &dma_desc[0]); // Start transaction e_dma_start(&dma_desc[0], E_DMA_0); // Wait e_dma_wait(E_DMA_0); // Check the destination buffer value index[0] = checkbuffer(dst, (unsigned)0xaaaaaaaa, tran); index[1] = checkbuffer(dst1, (unsigned)0xbbbbbbbb, tran); index[2] = checkbuffer(dst2, (unsigned)0xcccccccc, tran); if((index[0]|index[1]|index[2]) == 0) { mailbox[0] = 0xffffffff; }else { mailbox[0] = 0x00000000; } // Test for doubleword size // Initialize the source and destination buffer for (i=0; i<tran; i++) { src[i] = 0xaaaaaaaa; src1[i] = 0xbbbbbbbb; src2[i] = 0xcccccccc; } for (i=0; i<tran*6; i++) { dst[i] = 0x00000000; } // Prepare for the descriptor for 2d dma e_dma_set_desc(E_DMA_0,(E_DMA_ENABLE|E_DMA_MASTER|E_DMA_DWORD), 0x0000, 0x0008, 0x0008, 0x0040, 0x0003, 0x0108 , 0x0308, (void *)src,(void *)dst, &dma_desc[0]); // Start transaction e_dma_start(&dma_desc[0], E_DMA_0); // Wait e_dma_wait(E_DMA_0); // Check the destination buffer value index[0] = checkbuffer(dst, (unsigned)0xaaaaaaaa, tran); index[1] = checkbuffer(dst1, (unsigned)0xbbbbbbbb, tran); index[2] = checkbuffer(dst2, (unsigned)0xcccccccc, tran); if((index[0]|index[1]|index[2]) == 0) { mailbox1[0] = 0xffffffff; }else { mailbox1[0] = 0x00000000; } // Test for half size // Initialize the source and destination buffer for (i=0; i<tran; i++) { src[i] = 0xaaaaaaaa; src1[i] = 0xbbbbbbbb; src2[i] = 0xcccccccc; } for (i=0; i<tran*6; i++) { dst[i] = 0x00000000; } // Prepare for the descriptor for 2d dma e_dma_set_desc(E_DMA_0,(E_DMA_ENABLE|E_DMA_MASTER|E_DMA_HWORD), 0x0000, 0x0002, 0x0002, 0x0100, 0x0003, 0x0102 , 0x0302, (void *)src,(void *)dst, &dma_desc[0]); // Start transaction e_dma_start(&dma_desc[0], E_DMA_0); // Wait e_dma_wait(E_DMA_0); // Check the destination buffer value index[0] = checkbuffer(dst, (unsigned)0xaaaaaaaa, tran); index[1] = checkbuffer(dst1, (unsigned)0xbbbbbbbb, tran); index[2] = checkbuffer(dst2, (unsigned)0xcccccccc, tran); if((index[0]|index[1]|index[2]) == 0) { mailbox2[0] = 0xffffffff; }else { mailbox2[0] = 0x00000000; } // Test for byte size // Initialize the source and destination buffer for (i=0; i<tran; i++) { src[i] = 0xaaaaaaaa; src1[i] = 0xbbbbbbbb; src2[i] = 0xcccccccc; } for (i=0; i<tran*6; i++) { dst[i] = 0x00000000; } // Prepare for the descriptor for 2d dma e_dma_set_desc(E_DMA_0,(E_DMA_ENABLE|E_DMA_MASTER|E_DMA_BYTE), 0x0000, 0x0001, 0x0001, 0x0200, 0x0003, 0x0101 , 0x0301, (void *)src,(void *)dst, &dma_desc[0]); // Start transaction e_dma_start(&dma_desc[0], E_DMA_0); // Wait e_dma_wait(E_DMA_0); // Check the destination buffer value index[0] = checkbuffer(dst, (unsigned)0xaaaaaaaa, tran); index[1] = checkbuffer(dst1, (unsigned)0xbbbbbbbb, tran); index[2] = checkbuffer(dst2, (unsigned)0xcccccccc, tran); if((index[0]|index[1]|index[2]) == 0) { mailbox3[0] = 0xffffffff; }else { mailbox3[0] = 0x00000000; } return 0; }
int main(void) { unsigned time_c, time_p; unsigned time; unsigned tran,k,i,j,q,h,m,n; unsigned *box; unsigned *n_row, *n_col, *p; unsigned *neighbour_n; unsigned *neighbour_s; unsigned *neighbour_w; unsigned *neighbour_e; unsigned *master; // Define the mailbox master = (unsigned *)0x2000; box = (unsigned *) 0x5000; n_row = (unsigned *)0x6000; n_col = (unsigned *)0x6004; tran = 2048; p =(unsigned *) 0x2000; // Get the neighbour global address e_neighbor_id(E_NEXT_CORE, E_ROW_WRAP, n_row, n_col); neighbour_e = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_PREV_CORE, E_ROW_WRAP, n_row, n_col); neighbour_w = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_COL_WRAP, n_row, n_col); neighbour_s = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_PREV_CORE, E_COL_WRAP, n_row, n_col); neighbour_n = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; // Test the writing bandwidth // Initialize master and slave for(i=0; i<tran; i++) { master[i] = 0xdeadbeef; neighbour_e[i] = 0x00000000; neighbour_w[i] = 0x00000000; neighbour_s[i] = 0x00000000; neighbour_n[i] = 0x00000000; } // Set the ctimer e_ctimer_set(E_CTIMER_0, E_CTIMER_MAX) ; // Start the ctimer and select the time type time_p = e_ctimer_start(E_CTIMER_0, E_CTIMER_CLK); // Write to all neighbour cores e_dma_copy(neighbour_e, master, 0x2000); e_dma_copy(neighbour_w, master, 0x2000); e_dma_copy(neighbour_s, master, 0x2000); e_dma_copy(neighbour_n, master, 0x2000); // Get the time now time_c = e_ctimer_get(E_CTIMER_0); time = time_p - time_c; // Output the result box[0] = time; // Test the reading bandwidth // Initialize master and slave for(i=0; i<tran; i++) { master[i] = 0x00000000; neighbour_e[i] = 0xdeadbee1; neighbour_w[i] = 0xdeadbee2; neighbour_s[i] = 0xdeadbee3; neighbour_n[i] = 0xdeadbee4; } // Set the ctimer e_ctimer_set(E_CTIMER_0, E_CTIMER_MAX) ; // Start the ctimer and select the time type time_p = e_ctimer_start(E_CTIMER_0, E_CTIMER_CLK); // Read from all neighbour cores e_dma_copy(master, neighbour_e, 0x2000); e_dma_copy(master, neighbour_w, 0x2000); e_dma_copy(master, neighbour_s, 0x2000); e_dma_copy(master, neighbour_n, 0x2000); // Get the time now time_c = e_ctimer_get(E_CTIMER_0); time = time_p - time_c; // Output the result box[1] = time; return 0; }
int main(void) { unsigned mesh_reg; unsigned mesh_reg_modify; unsigned time_c, time_p; unsigned time; unsigned time_c1, time_p1; unsigned time1; unsigned i,j,q,m,n,k; unsigned *commander; unsigned *counter; unsigned *mailbox,*mode; unsigned *n_row, *n_col; unsigned *neighbour0, *neighbour1, *neighbour2, *neighbour3, *p; commander = (unsigned *)0x5100; counter = (unsigned *)0x5300; mailbox = (unsigned *)0x6000; mode = (unsigned *)0x5400; n_row = (unsigned *)0x5008; n_col = (unsigned *)0x500c; p = (unsigned *)0x5100; // Broadcast to neighbours e_neighbor_id(E_PREV_CORE, E_ROW_WRAP, n_row, n_col); neighbour0 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_ROW_WRAP, n_row, n_col); neighbour1 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_PREV_CORE, E_COL_WRAP, n_row, n_col); neighbour2 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; e_neighbor_id(E_NEXT_CORE, E_COL_WRAP, n_row, n_col); neighbour3 = (unsigned *) e_get_global_address(*n_row, *n_col, p) ; // Get core information k = e_group_config.core_row * e_group_config.group_cols + e_group_config.core_col; while(1) { // Clear the counter of finishing transfering for(m=0; m<(e_group_config.group_rows*e_group_config.group_cols); m++) { counter[m] = 0; } // Initialize the commander and counter counter[k] = 1; //Clear the mode box mode[0] = 0xdeadbeef; // Clear the start commander commander[0] = 0x00000000; // Wait for the mesh event while(mode[0] == 0xdeadbeef) {}; q = mode[0]; mesh_reg = e_reg_read(E_REG_MESH_CONFIG); mesh_reg_modify = mesh_reg & 0xffffff0f; mesh_reg_modify = mesh_reg_modify |mesh_type[1][q]; e_reg_write(E_REG_MESH_CONFIG, mesh_reg_modify); // Set the ctimer e_ctimer_set(E_CTIMER_0, E_CTIMER_MAX) ; // Waiting for the signal to start transfering while(commander[0] != 0xdeadbeef) {}; // Start the ctimer and select the time type time_p = e_ctimer_start(E_CTIMER_0, E_CTIMER_MESH_0); // Broadcast to all the other neighbours neighbour0[0] = 0xdeadbeef; neighbour1[0] = 0xdeadbeef; neighbour2[0] = 0xdeadbeef; neighbour3[0] = 0xdeadbeef; while((counter[0]&counter[1]&counter[2]&counter[3]&counter[4]&counter[5]&counter[6] &counter[7]&counter[8]&counter[9]&counter[10]&counter[11]&counter[12]&counter[13] &counter[14]&counter[15]) == 0) {}; time_c = e_ctimer_get(E_CTIMER_0); time = time_p - time_c; mailbox[(*mode)] = time; // Load the original value to E_REG_MESH_CONFIG system register e_reg_write(E_REG_MESH_CONFIG, mesh_reg); if(mode[0] == 12) { break; } } return 0; }