| [451] | 1 | ///////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2 | // File   : main.c   (for router application) | 
|---|
|  | 3 | // Date   : november 2014 | 
|---|
|  | 4 | // author : Alain Greiner | 
|---|
|  | 5 | ///////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 6 | // This multi-threaded application emulates a packet routing communication application, | 
|---|
|  | 7 | // described as a TCG (Task and Communication Graph). | 
|---|
|  | 8 | // It contains 2 + N tasks : one "producer", one "consumer" and N "router") | 
|---|
|  | 9 | // It contains 2 MWMR channels : "fifo_in" and "fifo_out". | 
|---|
|  | 10 | // - The "producer" task writes NMAX token into "fifo_in". | 
|---|
|  | 11 | // - The N "router" tasks read token from "fifo_in" and write them into "fifo_out". | 
|---|
|  | 12 | // - The "consumer" task read token from "fifo_out" and displays instrumentation results. | 
|---|
|  | 13 | // Token are indexed (by the producer) from 0 to NMAX-1. | 
|---|
|  | 14 | // The router task contain a random delay emulating a variable processing time. | 
|---|
|  | 15 | // | 
|---|
|  | 16 | // This application is intended to run on a multi-processors, multi-clusters architecture, | 
|---|
|  | 17 | //  with one thread per processor. | 
|---|
|  | 18 | // | 
|---|
|  | 19 | // It uses the he following hardware parameters, defined in the hard_config.h file: | 
|---|
|  | 20 | // - X_SIZE       : number of clusters in a row | 
|---|
|  | 21 | // - Y_SIZE       : number of clusters in a column | 
|---|
|  | 22 | // - NB_PROCS_MAX : number of processors per cluster | 
|---|
|  | 23 | // | 
|---|
|  | 24 | // There is two global arrays (indexed by the token index) for insrumentation: | 
|---|
|  | 25 | // - The "router_tab" array is filled concurrently by all "router" tasks. | 
|---|
|  | 26 | //   Each entry contains the processor index that routed the token. | 
|---|
|  | 27 | // - The "consumer_tab" array is filled by the "consumer" task. | 
|---|
|  | 28 | //   Each entry contain the arrival order to the consumer task. | 
|---|
|  | 29 | ///////////////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 30 |  | 
|---|
| [191] | 31 | #include "stdio.h" | 
|---|
|  | 32 | #include "mwmr_channel.h" | 
|---|
|  | 33 | #include "mapping_info.h" | 
|---|
| [295] | 34 | #include "hard_config.h" | 
|---|
| [191] | 35 |  | 
|---|
| [345] | 36 |  | 
|---|
| [451] | 37 | #define NMAX   50                       // total number of token | 
|---|
|  | 38 | #define DEPTH  20           // MWMR channels depth | 
|---|
| [191] | 39 |  | 
|---|
| [457] | 40 | //////////////// MWMR channels and associated buffers  ///////////////////// | 
|---|
| [451] | 41 |  | 
|---|
|  | 42 | __attribute__((section (".data_in")))  mwmr_channel_t fifo_in; | 
|---|
| [457] | 43 | __attribute__((section (".data_in")))  unsigned int   buf_in[DEPTH]; | 
|---|
|  | 44 |  | 
|---|
| [451] | 45 | __attribute__((section (".data_out"))) mwmr_channel_t fifo_out; | 
|---|
| [457] | 46 | __attribute__((section (".data_out"))) unsigned int   buf_out[DEPTH]; | 
|---|
| [451] | 47 |  | 
|---|
|  | 48 | //////////////// Instrumentation Counters ////////////////////////////////// | 
|---|
|  | 49 |  | 
|---|
|  | 50 | __attribute__((section (".data_out")))  unsigned int consumer_tab[NMAX]; | 
|---|
|  | 51 | __attribute__((section (".data_out")))  unsigned int router_tab[NMAX]; | 
|---|
|  | 52 |  | 
|---|
|  | 53 |  | 
|---|
|  | 54 |  | 
|---|
| [191] | 55 | ///////////////////////////////////////////// | 
|---|
|  | 56 | __attribute__ ((constructor)) void producer() | 
|---|
|  | 57 | { | 
|---|
|  | 58 |  | 
|---|
|  | 59 | unsigned int        n; | 
|---|
|  | 60 | unsigned int        buf; | 
|---|
|  | 61 |  | 
|---|
| [432] | 62 | // get processor identifiers | 
|---|
|  | 63 | unsigned int    x; | 
|---|
|  | 64 | unsigned int    y; | 
|---|
|  | 65 | unsigned int    lpid; | 
|---|
|  | 66 | giet_proc_xyp( &x, &y, &lpid ); | 
|---|
| [191] | 67 |  | 
|---|
| [451] | 68 | giet_shr_printf("\n*** Starting task producer on P[%d,%d,%d] at cycle %d\n", | 
|---|
|  | 69 | x, y, lpid, giet_proctime() ); | 
|---|
| [191] | 70 |  | 
|---|
| [451] | 71 | // initializes fifo_in | 
|---|
| [457] | 72 | mwmr_init( &fifo_in, buf_in, 1 , DEPTH ); | 
|---|
| [295] | 73 |  | 
|---|
| [264] | 74 | // main loop : display token value = source index | 
|---|
| [191] | 75 | for(n = 0 ; n < NMAX ; n++) | 
|---|
|  | 76 | { | 
|---|
|  | 77 | buf = n; | 
|---|
| [451] | 78 | mwmr_write( &fifo_in , &buf , 1 ); | 
|---|
| [191] | 79 | } | 
|---|
|  | 80 |  | 
|---|
| [295] | 81 | giet_exit( "Producer task completed"); | 
|---|
| [191] | 82 |  | 
|---|
|  | 83 | } // end producer() | 
|---|
|  | 84 |  | 
|---|
|  | 85 | ///////////////////////////////////////////// | 
|---|
|  | 86 | __attribute__ ((constructor)) void consumer() | 
|---|
|  | 87 | { | 
|---|
|  | 88 | unsigned int        n; | 
|---|
|  | 89 | unsigned int        buf; | 
|---|
|  | 90 |  | 
|---|
| [432] | 91 | // get processor identifiers | 
|---|
|  | 92 | unsigned int    x; | 
|---|
|  | 93 | unsigned int    y; | 
|---|
|  | 94 | unsigned int    lpid; | 
|---|
|  | 95 | giet_proc_xyp( &x, &y, &lpid ); | 
|---|
| [191] | 96 |  | 
|---|
| [451] | 97 | giet_shr_printf("\n*** Starting task consumer on P[%d,%d,%d] at cycle %d\n", | 
|---|
|  | 98 | x, y, lpid, giet_proctime() ); | 
|---|
| [191] | 99 |  | 
|---|
| [451] | 100 | // initializes fifo_out | 
|---|
| [457] | 101 | mwmr_init( &fifo_out, buf_out, 1 , DEPTH ); | 
|---|
| [295] | 102 |  | 
|---|
| [451] | 103 | // main loop : register token arrival index and value | 
|---|
|  | 104 | for( n = 0 ; n < NMAX ; n++ ) | 
|---|
| [191] | 105 | { | 
|---|
| [451] | 106 | mwmr_read( &fifo_out , &buf , 1 ); | 
|---|
|  | 107 | consumer_tab[n] = buf; | 
|---|
| [191] | 108 | } | 
|---|
|  | 109 |  | 
|---|
| [451] | 110 | // instrumentation display | 
|---|
|  | 111 | giet_shr_printf("\n"); | 
|---|
|  | 112 | for( n = 0 ; n < NMAX ; n++ ) | 
|---|
|  | 113 | { | 
|---|
|  | 114 | giet_shr_printf("@@@ arrival = %d / value = %d / router = %x\n", | 
|---|
|  | 115 | n, consumer_tab[n], router_tab[n] ); | 
|---|
|  | 116 | } | 
|---|
|  | 117 |  | 
|---|
| [295] | 118 | giet_exit( "Consumer task completed"); | 
|---|
| [191] | 119 |  | 
|---|
|  | 120 | } // end consumer() | 
|---|
|  | 121 |  | 
|---|
|  | 122 | /////////////////////////////////////////// | 
|---|
|  | 123 | __attribute__ ((constructor)) void router() | 
|---|
|  | 124 | { | 
|---|
| [264] | 125 | unsigned int        buf; | 
|---|
| [295] | 126 | unsigned int        n; | 
|---|
| [191] | 127 | unsigned int        tempo; | 
|---|
|  | 128 |  | 
|---|
| [432] | 129 | // get processor identifiers | 
|---|
|  | 130 | unsigned int    x; | 
|---|
|  | 131 | unsigned int    y; | 
|---|
|  | 132 | unsigned int    lpid; | 
|---|
|  | 133 | giet_proc_xyp( &x, &y, &lpid ); | 
|---|
| [191] | 134 |  | 
|---|
| [451] | 135 | giet_shr_printf("\n*** Starting task router on P[%d,%d,%d] at cycle %d\n", | 
|---|
|  | 136 | x, y, lpid, giet_proctime() ); | 
|---|
| [191] | 137 |  | 
|---|
| [451] | 138 | // waiting fifo_in and fifo_out initialisation | 
|---|
|  | 139 | while( (fifo_in.depth == 0) || (fifo_out.depth == 0) ) asm volatile( "nop" ); | 
|---|
| [191] | 140 |  | 
|---|
|  | 141 | // main loop | 
|---|
|  | 142 | while(1) | 
|---|
|  | 143 | { | 
|---|
| [451] | 144 | mwmr_read( &fifo_in , &buf , 1 ); | 
|---|
|  | 145 |  | 
|---|
|  | 146 | tempo = giet_rand(); | 
|---|
|  | 147 | for ( n = 0 ; n < tempo ; n++ ) asm volatile ( "nop" ); | 
|---|
|  | 148 |  | 
|---|
|  | 149 | router_tab[buf] = (x<<(Y_WIDTH + P_WIDTH)) + (y<<P_WIDTH) + lpid; | 
|---|
|  | 150 |  | 
|---|
|  | 151 | mwmr_write( &fifo_out , &buf , 1 ); | 
|---|
| [191] | 152 | } | 
|---|
| [451] | 153 | } // end router | 
|---|