| 1 | ///////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 2 | // File : main.c (for router application) |
|---|
| 3 | // Date : november 2014 |
|---|
| 4 | // author : Alain Greiner |
|---|
| 5 | ///////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 6 | // This multi-threaded application illustrates "task-farm" parallelism. |
|---|
| 7 | // It is 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 contains 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 | // Implementation note: |
|---|
| 31 | // The synchronisation variables fifo_in, fifo_out, and tty_lock are initialised by the |
|---|
| 32 | // "producer" task. Other tasks are waiting on the init_ok variable until completion. |
|---|
| 33 | ///////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 34 | |
|---|
| 35 | |
|---|
| 36 | #include "stdio.h" |
|---|
| 37 | #include "mwmr_channel.h" |
|---|
| 38 | #include "mapping_info.h" |
|---|
| 39 | #include "hard_config.h" |
|---|
| 40 | |
|---|
| 41 | #define VERBOSE 1 |
|---|
| 42 | #define NMAX 50 // total number of token |
|---|
| 43 | #define DEPTH 20 // MWMR channels depth |
|---|
| 44 | |
|---|
| 45 | // MWMR channels and associated buffers |
|---|
| 46 | |
|---|
| 47 | __attribute__((section (".data_in"))) mwmr_channel_t fifo_in; |
|---|
| 48 | __attribute__((section (".data_in"))) unsigned int buf_in[DEPTH]; |
|---|
| 49 | |
|---|
| 50 | __attribute__((section (".data_out"))) mwmr_channel_t fifo_out; |
|---|
| 51 | __attribute__((section (".data_out"))) unsigned int buf_out[DEPTH]; |
|---|
| 52 | |
|---|
| 53 | // Instrumentation Counters |
|---|
| 54 | |
|---|
| 55 | __attribute__((section (".data_out"))) unsigned int consumer_tab[NMAX]; |
|---|
| 56 | __attribute__((section (".data_out"))) unsigned int router_tab[NMAX]; |
|---|
| 57 | |
|---|
| 58 | // synchronisation variables |
|---|
| 59 | |
|---|
| 60 | unsigned int init_ok = 0; |
|---|
| 61 | |
|---|
| 62 | ///////////////////////////////////////////// |
|---|
| 63 | __attribute__ ((constructor)) void producer() |
|---|
| 64 | { |
|---|
| 65 | |
|---|
| 66 | unsigned int n; |
|---|
| 67 | unsigned int buf; |
|---|
| 68 | |
|---|
| 69 | // get processor identifiers |
|---|
| 70 | unsigned int x; |
|---|
| 71 | unsigned int y; |
|---|
| 72 | unsigned int p; |
|---|
| 73 | giet_proc_xyp( &x , &y , &p ); |
|---|
| 74 | |
|---|
| 75 | // allocates a private TTY |
|---|
| 76 | giet_tty_alloc( 0 ); |
|---|
| 77 | |
|---|
| 78 | // initialises TTY lock |
|---|
| 79 | // lock_init( &tty_lock ); |
|---|
| 80 | |
|---|
| 81 | // initializes fifo_in |
|---|
| 82 | mwmr_init( &fifo_in , buf_in , 1 , DEPTH ); |
|---|
| 83 | |
|---|
| 84 | // initializes fifo_out |
|---|
| 85 | mwmr_init( &fifo_out , buf_out , 1 , DEPTH ); |
|---|
| 86 | |
|---|
| 87 | init_ok = 1; |
|---|
| 88 | |
|---|
| 89 | giet_tty_printf("\n[Producer] completes initialisation on P[%d,%d,%d] at cycle %d\n", |
|---|
| 90 | x , y , p , giet_proctime() ); |
|---|
| 91 | |
|---|
| 92 | // main loop |
|---|
| 93 | for(n = 0 ; n < NMAX ; n++) |
|---|
| 94 | { |
|---|
| 95 | buf = n; |
|---|
| 96 | mwmr_write( &fifo_in , &buf , 1 ); |
|---|
| 97 | |
|---|
| 98 | if ( VERBOSE ) |
|---|
| 99 | giet_tty_printf(" - token %d sent at cycle %d\n", n , giet_proctime() ); |
|---|
| 100 | } |
|---|
| 101 | |
|---|
| 102 | giet_exit( "Producer task completed"); |
|---|
| 103 | |
|---|
| 104 | } // end producer() |
|---|
| 105 | |
|---|
| 106 | ///////////////////////////////////////////// |
|---|
| 107 | __attribute__ ((constructor)) void consumer() |
|---|
| 108 | { |
|---|
| 109 | unsigned int n; |
|---|
| 110 | unsigned int buf; |
|---|
| 111 | |
|---|
| 112 | // get processor identifiers |
|---|
| 113 | unsigned int x; |
|---|
| 114 | unsigned int y; |
|---|
| 115 | unsigned int p; |
|---|
| 116 | giet_proc_xyp( &x, &y, &p ); |
|---|
| 117 | |
|---|
| 118 | // allocates a private TTY |
|---|
| 119 | giet_tty_alloc( 0 ); |
|---|
| 120 | |
|---|
| 121 | while ( init_ok == 0 ) asm volatile( "nop" ); |
|---|
| 122 | |
|---|
| 123 | giet_tty_printf("\n[Consumer] starts execution on P[%d,%d,%d] at cycle %d\n", |
|---|
| 124 | x, y, p, giet_proctime() ); |
|---|
| 125 | |
|---|
| 126 | // main loop |
|---|
| 127 | for( n = 0 ; n < NMAX ; n++ ) |
|---|
| 128 | { |
|---|
| 129 | mwmr_read( &fifo_out , &buf , 1 ); |
|---|
| 130 | consumer_tab[n] = buf; |
|---|
| 131 | |
|---|
| 132 | if ( VERBOSE ) |
|---|
| 133 | giet_tty_printf(" - token %d received at cycle %d\n", buf , giet_proctime() ); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | // instrumentation display |
|---|
| 137 | giet_tty_printf("\n[Consumer] displays instrumentation results\n"); |
|---|
| 138 | for( n = 0 ; n < NMAX ; n++ ) |
|---|
| 139 | { |
|---|
| 140 | giet_tty_printf(" - arrival = %d / value = %d / router = %x\n", |
|---|
| 141 | n , consumer_tab[n] , router_tab[n] ); |
|---|
| 142 | } |
|---|
| 143 | |
|---|
| 144 | giet_exit( "Consumer completed" ); |
|---|
| 145 | |
|---|
| 146 | } // end consumer() |
|---|
| 147 | |
|---|
| 148 | /////////////////////////////////////////// |
|---|
| 149 | __attribute__ ((constructor)) void router() |
|---|
| 150 | { |
|---|
| 151 | unsigned int buf; |
|---|
| 152 | unsigned int n; |
|---|
| 153 | unsigned int tempo; |
|---|
| 154 | |
|---|
| 155 | // get processor identifiers |
|---|
| 156 | unsigned int x; |
|---|
| 157 | unsigned int y; |
|---|
| 158 | unsigned int p; |
|---|
| 159 | giet_proc_xyp( &x, &y, &p ); |
|---|
| 160 | |
|---|
| 161 | // allocates a private TTY |
|---|
| 162 | giet_tty_alloc( 0 ); |
|---|
| 163 | |
|---|
| 164 | giet_tty_printf("\n[Router] starts execution on P[%d,%d,%d] at cycle %d\n", |
|---|
| 165 | x, y, p, giet_proctime() ); |
|---|
| 166 | |
|---|
| 167 | while ( init_ok == 0 ) asm volatile( "nop" ); |
|---|
| 168 | |
|---|
| 169 | // main loop |
|---|
| 170 | while(1) |
|---|
| 171 | { |
|---|
| 172 | mwmr_read( &fifo_in , &buf , 1 ); |
|---|
| 173 | |
|---|
| 174 | tempo = giet_rand(); |
|---|
| 175 | for ( n = 0 ; n < tempo ; n++ ) asm volatile ( "nop" ); |
|---|
| 176 | |
|---|
| 177 | router_tab[buf] = (x<<(Y_WIDTH + P_WIDTH)) + (y<<P_WIDTH) + p; |
|---|
| 178 | |
|---|
| 179 | mwmr_write( &fifo_out , &buf , 1 ); |
|---|
| 180 | |
|---|
| 181 | if ( VERBOSE ) |
|---|
| 182 | giet_tty_printf(" - token %d routed at cycle %d\n", buf , giet_proctime() ); |
|---|
| 183 | } |
|---|
| 184 | } // end router |
|---|