source: soft/giet_vm/applications/router/router.c @ 771

Last change on this file since 771 was 720, checked in by alain, 9 years ago

Adapt the router application to the POSIX API.

File size: 8.8 KB
Line 
1/////////////////////////////////////////////////////////////////////////////////////////////
2// File   : router.c   
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 threads : one "producer", one "consumer" and N "router"),
9// plus the "main" thread, that makes the global initialisation, launches the other
10// threads, and exit.
11// It contains 2 MWMR channels per cluster : "fifo_in" and "fifo_out", that are
12// allocated by the main thread in the user heaps distributed in all clusters.
13// - The "producer" task writes token in all the  "fifo_in".
14// - The N "router" tasks read token from "fifo_in" and write them into "fifo_out".
15// - The "consumer" task read token from "fifo_out" and displays instrumentation results.
16// Token are indexed (by the producer) from 0 to NMAX-1.
17// The router task contains a random delay emulating a variable processing time.
18// For instrumentation, the "consumer_tab" array is filled by the "consumer" task.
19// Each entry contain the arrival order to the consumer task.
20/////////////////////////////////////////////////////////////////////////////////////////////
21
22
23#include "stdio.h"
24#include "mwmr_channel.h"
25#include "mapping_info.h"
26#include "hard_config.h"
27#include "malloc.h"
28
29#define VERBOSE  1
30#define NMAX     32       // total number of token
31#define DEPTH    32       // MWMR channels depth
32
33
34// macro to use a shared TTY
35#define printf(...);  { lock_acquire( &tty_lock ); \
36                        giet_tty_printf(__VA_ARGS__);  \
37                        lock_release( &tty_lock ); }
38
39// lock protecting shared TTY
40user_lock_t           tty_lock;
41
42 
43// arguments for the producer, consumer, and router functions
44typedef struct
45{
46    mwmr_channel_t*  pin;       // pointer on the MWMR input fifo
47    mwmr_channel_t*  pout;      // pointer on the MWMR output fifo
48    unsigned int     x_size;    // number of clusters in a row
49    unsigned int     y_size;    // number of clusters in a column
50} args_t;
51
52
53// arrays of pointers
54mwmr_channel_t*  fifo_in[16][16];
55mwmr_channel_t*  fifo_out[16][16];
56
57
58/////////////////////////////////////////////
59__attribute__ ((constructor)) void producer()
60{
61    unsigned int    x      = 0;             // destination cluster coordinate
62    unsigned int    y      = 0;             // destination cluster coordinate
63    unsigned int    token  = 0;             // token value
64
65    // get plat-form parameters
66    unsigned int x_size;                    // number of clusters in a row
67    unsigned int y_size;                    // number of clusters in a column
68    unsigned int nprocs;                    // unused
69    giet_procs_number( &x_size , &y_size , &nprocs );
70
71   // loop on the clusters
72    while ( token < NMAX )
73    {
74        // try to write a token in fifo_in[x,y]
75        if ( nb_mwmr_write( fifo_in[x][y] , &token , 1 ) == 1 )
76        {
77            if ( VERBOSE ) printf("[PRODUCER] token %d sent to cluster(%d,%d)"
78                                  " at cycle %d\n", token , x , y , giet_proctime() );
79            token++;
80        }
81
82        // compute next cluster coordinates
83        x++;
84        if ( x == x_size )
85        {
86            x = 0;
87            y++;
88            if ( y == y_size ) y = 0;
89        }
90    }
91
92    giet_pthread_exit( "Producer task completed");
93
94} // end producer()
95
96/////////////////////////////////////////////
97__attribute__ ((constructor)) void consumer()
98{
99    unsigned int    x      = 0;             // source cluster coordinate
100    unsigned int    y      = 0;             // source cluster coordinate
101    unsigned int    n      = 0;             // index of received token
102    unsigned int    token;                  // token value
103    unsigned int    consumer_tab[NMAX];     // received token array
104
105    // get plat-form parameters
106    unsigned int x_size;                    // number of clusters in a row
107    unsigned int y_size;                    // number of clusters in a column
108    unsigned int nprocs;                    // unused
109    giet_procs_number( &x_size , &y_size , &nprocs );
110
111    // loop on the clusters
112    while ( n < NMAX )
113    { 
114        // try to read a token from fifo_out[x,y]
115        if ( nb_mwmr_read( fifo_out[x][y] , &token , 1 ) == 1 )
116        {
117            consumer_tab[n] = token;
118            n++;
119
120            if ( VERBOSE ) printf("[CONSUMER] token %d received at cycle %d\n",
121                                  token , giet_proctime() );
122        }
123
124        // compute next cluster coordinates
125        x++;
126        if ( x == x_size )
127        {
128            x = 0;
129            y++;
130            if ( y == y_size ) y = 0;
131        }
132    }
133
134    // instrumentation display
135    giet_tty_printf("\n[CONSUMER] displays instrumentation results\n");
136    for( n = 0 ; n < NMAX ; n++ )
137    {
138        giet_tty_printf(" - arrival = %d / value = %d\n", n , consumer_tab[n] );
139    }
140
141    giet_pthread_exit( "Consumer task completed");
142
143} // end consumer()
144
145////////////////////////////////////////////
146__attribute__ ((constructor)) void compute()
147{
148    unsigned int    token;           // token value
149    unsigned int        count;           // tempo
150
151    // get proc coordinates
152    unsigned int  x;
153    unsigned int  y;
154    unsigned int  p;
155    giet_proc_xyp( &x , &y , &p );
156
157    // main loop
158    while(1)
159    {
160        mwmr_read( fifo_in[x][y] , &token , 1 );
161        for ( count = 0 ; count < (giet_rand() << 2) ; count++ ) asm volatile ( "nop" );
162        mwmr_write( fifo_out[x][y] , &token , 1 );
163
164        if ( VERBOSE ) printf("[COMPUTE] token %d handled at cycle %d on P[%d,%d,%d]\n", 
165                              token , giet_proctime() , x , y , p );
166    }
167} // end compute()
168
169
170/////////////////////////////////////////
171__attribute__ ((constructor)) void main()
172{
173    // get plat-form parameters
174    unsigned int x_size;                       // number of clusters in a row
175    unsigned int y_size;                       // number of clusters in a column
176    unsigned int nprocs;                       // number of processors per cluster
177    giet_procs_number( &x_size , &y_size , &nprocs );
178
179    // shared TTY allocation
180    giet_tty_alloc( 1 );     
181    lock_init( &tty_lock);
182
183    // check plat-form parameters
184    giet_pthread_assert( ((nprocs >= 3) && (nprocs <= 8)),
185                         "[ROUTER ERROR] nprocs per cluster must be in [3...8]");
186
187    giet_pthread_assert( ((x_size >= 1) && (x_size <= 16)),
188                         "[ROUTER ERROR] x_size must be in [1...16]");
189
190    giet_pthread_assert( ((y_size >= 1) && (y_size <= 16)),
191                         "[ROUTER ERROR] y_size must be in [1...16]");
192
193    // index for loops
194    unsigned int x;
195    unsigned int y;
196    unsigned int n;
197
198    // distributed heap initialisation, plus
199    // MWMR channels and associated buffers allocation
200    for ( x = 0 ; x < x_size ; x++ ) 
201    {
202        for ( y = 0 ; y < y_size ; y++ ) 
203        {
204            heap_init( x , y );
205
206            // allocate MWMR channel descriptors in cluster[x][y]
207                fifo_in[x][y]  = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
208                fifo_out[x][y] = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
209
210                // allocate data buffers in cluster[x][y]
211                unsigned int* buf_in  = remote_malloc( 4*DEPTH , x , y );           
212                unsigned int* buf_out = remote_malloc( 4*DEPTH , x , y );           
213
214                // initialize MWMR channels
215                mwmr_init( fifo_in[x][y]  , buf_in  , 1 , DEPTH );
216                mwmr_init( fifo_out[x][y] , buf_out , 1 , DEPTH );
217        }
218    }
219
220    printf("\n[ROUTER] main completes initialisation at cycle %d for %d cores\n", 
221           giet_proctime(), (x_size * y_size * nprocs) );
222
223    // thread index and function for pthread_create()
224    pthread_t   trdid; 
225    void*       function;
226
227    // launch producer, consumer and router threads
228    for ( x = 0 ; x < x_size ; x++ )
229    {
230        for ( y = 0 ; y < y_size ; y++ )
231        {
232            for ( n = 0 ; n < nprocs ; n++ )
233            {
234                if      ( (x==0) && (y==0) && (n==0) )  function = &producer;
235                else if ( (x==0) && (y==0) && (n==1) )  function = &consumer;
236                else                                    function = &compute;
237               
238                if ( giet_pthread_create( &trdid,
239                                          NULL,                  // no attribute
240                                          function,
241                                          NULL ) )               // no argument
242                {
243                    printf("\n[ROUTER ERROR] launching thread on P[%d,%d,%d]\n", x, y, n );
244                    giet_pthread_exit( NULL );
245                }
246            }
247        }
248    }
249
250    giet_pthread_exit( "main completed" );
251   
252} // end main()
Note: See TracBrowser for help on using the repository browser.