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 |
---|