source: soft/giet_vm/applications/classif/classif.c @ 787

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

Adapt the router application to the POSIX API.

File size: 26.1 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////
2// File   : classif.c
3// Date   : november 2014
4// author : Alain Greiner
5///////////////////////////////////////////////////////////////////////////////////////
6// This multi-threaded application takes a stream of Gigabit Ethernet packets,
7// and makes packet analysis and classification, based on the source MAC address.
8// It uses the NIC peripheral, and the distributed kernel chbufs accessed by the CMA
9// component to receive and send packets on the Gigabit Ethernet port.
10//
11// It can run on architectures containing up to 16 * 16 clusters,
12// and from 3 to 8 processors per cluster.
13//
14// It requires one shared TTY terminal.
15//
16// This application is described as a TCG (Thread and Communication Graph)
17// containing (N+2) threads per cluster.
18// - one "load" thread
19// - one "store" thread
20// - N "analyse" threads
21// The containers are distributed (N+2 containers per cluster):
22// - one RX container (part of the kernel rx_chbuf), in the kernel heap.
23// - one TX container (part of the kernel tx-chbuf), in the kernel heap.
24// - N working containers (one per analysis thread), in the user heap.
25// In each cluster, the "load", analysis" and "store" threads communicates through
26// three local MWMR fifos:
27// - fifo_l2a : tranfer a full container from "load" to "analyse" thread.
28// - fifo_a2s : transfer a full container from "analyse" to "store" thread.
29// - fifo_s2l : transfer an empty container from "store" to "load" thread.
30// For each fifo, one item is a 32 bits word defining the index of an
31// available working container.
32// The pointers on the working containers, and the pointers on the MWMR fifos
33// are global arrays stored in cluster[0][0].
34//
35// The main thread exit after global initialisation, and launching the other threads:
36// It does not use the pthread_join() construct. It is executed on P[0,0,1],
37// toavoid overload on P[0,0,0].
38//
39// Initialisation is made in two steps:
40//
41// 1) The global, shared, variables are initialised by the main thread:
42//    - shared TTY
43//    - distributed heap (one heap per cluster)
44//    - distributed rx_barrier (between all "load" threads)
45//    - distributed tx_barrier (between all "store" threads)
46//    - RX kernel chbufs (used by "load" threads)
47//    - TX kernel chbufs (used by "store" threads)
48//    Then the main thread exit, after launching the "load, "store", and "analyse"
49//    threads in all clusters.
50//
51// 2) Each "load" thread allocates containers[x][y][n] from local heap,
52//    and register containers pointers in the local stack.
53//    Each "load" thread allocates data buffers & mwmr fifo descriptors
54//    from local heap, and register pointers in global arrays.
55//    Each "load" thread initialises the containers as empty in fifo_s2l.
56//    Then each "load" thread signals mwmr fifos initialisation completion
57//    to other threads in same cluster, using the local_sync[x][y] variables.
58//
59// When initialisation is completed, all threads are running in parallel:
60//
61// 1) The "load" thread get an empty working container from the fifo_s2l,
62//    transfer one container from the kernel rx_chbuf to this user container,
63//    and transfer ownership of this container to one "analysis" thread by writing
64//    into the fifo_l2a.   
65// 2) The "analyse" thread get one working container from the fifo_l2a, analyse
66//    each packet header, compute the packet type (depending on the SRC MAC address),
67//    increment the correspondint classification counter, and transpose the SRC
68//    and the DST MAC addresses fot TX tranmission.
69// 3) The "store" thread transfer get a full working container from the fifo_a2s,
70//    transfer this user container content to the the kernel tx_chbuf,
71//    and transfer ownership of this empty container to the "load" thread by writing
72//    into the fifo_s2l.   
73//     
74// Instrumentation results display is done by the "store" thread in cluster[0][0]
75// when all "store" threads completed the number of clusters specified by the
76// CONTAINERS_MAX parameter.
77///////////////////////////////////////////////////////////////////////////////////////
78
79#include "stdio.h"
80#include "user_barrier.h"
81#include "malloc.h"
82#include "user_lock.h"
83#include "mwmr_channel.h"
84
85#define X_SIZE_MAX        16
86#define Y_SIZE_MAX        16
87#define NPROCS_MAX        8
88#define CONTAINERS_MAX    5000
89#define VERBOSE_ANALYSE   0
90
91// macro to use a shared TTY
92#define printf(...);    { lock_acquire( &tty_lock ); \
93                          giet_tty_printf(__VA_ARGS__);  \
94                          lock_release( &tty_lock ); }
95
96
97///////////////////////////////////////////////////////////////////////////////////////
98//    Global variables
99// The MWMR channels (descriptors and buffers), as well as the working containers
100// used by the "analysis" threads are distributed in clusters.
101// But the pointers on these distributed structures are stored in cluster[0][0].
102///////////////////////////////////////////////////////////////////////////////////////
103
104// pointers on distributed containers
105unsigned int*         container[X_SIZE_MAX][Y_SIZE_MAX][NPROCS_MAX-2]; 
106
107// pointers on distributed mwmr fifos containing container descriptors
108mwmr_channel_t*       mwmr_l2a[X_SIZE_MAX][Y_SIZE_MAX]; 
109mwmr_channel_t*       mwmr_a2s[X_SIZE_MAX][Y_SIZE_MAX];
110mwmr_channel_t*       mwmr_s2l[X_SIZE_MAX][Y_SIZE_MAX]; 
111
112// local synchros signaling local MWMR fifos initialisation completion
113volatile unsigned int local_sync[X_SIZE_MAX][Y_SIZE_MAX]; 
114
115// lock protecting shared TTY
116user_lock_t           tty_lock;
117
118// distributed barrier between "load" threads
119giet_sqt_barrier_t    rx_barrier;
120
121// distributed barrier between "store" threads
122giet_sqt_barrier_t    tx_barrier;
123
124// instrumentation counters
125unsigned int          counter[16];
126
127// threads arguments array
128unsigned int thread_arg[16][16][4];
129
130////////////////////////////////////////////////////////////
131__attribute__ ((constructor)) void load( unsigned int* arg )
132////////////////////////////////////////////////////////////
133{
134    // get plat-form parameters
135    unsigned int x_size;                       // number of clusters in a row
136    unsigned int y_size;                       // number of clusters in a column
137    unsigned int nprocs;                       // number of processors per cluster
138    giet_procs_number( &x_size , &y_size , &nprocs );
139
140    // each "load" thread get processor identifiers
141    unsigned int    x;
142    unsigned int    y;
143    unsigned int    p;
144    giet_proc_xyp( &x, &y, &p );
145
146    // each "load" thread allocates containers[x][y][n] (from local heap)
147    // and register pointers in the local stack
148    unsigned int   n;
149    unsigned int*  cont[NPROCS_MAX-2]; 
150
151    for ( n = 0 ; n < (nprocs - 2) ; n++ )
152    {
153        container[x][y][n] = malloc( 4096 );
154        cont[n]            = container[x][y][n];
155    }
156   
157    // each "load" thread allocates data buffers for mwmr fifos (from local heap)
158    unsigned int*  data_l2a = malloc( (nprocs - 2)<<2 );
159    unsigned int*  data_a2s = malloc( (nprocs - 2)<<2 );
160    unsigned int*  data_s2l = malloc( (nprocs - 2)<<2 );
161
162    // each "load" thread allocates mwmr fifos descriptors (from local heap)
163    mwmr_l2a[x][y] = malloc( sizeof(mwmr_channel_t) );
164    mwmr_a2s[x][y] = malloc( sizeof(mwmr_channel_t) );
165    mwmr_s2l[x][y] = malloc( sizeof(mwmr_channel_t) );
166
167    // each "load" thread registers local pointers on mwmr fifos in local stack
168    mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
169    mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
170    mwmr_channel_t* fifo_s2l = mwmr_s2l[x][y];
171
172    // each "load" thread initialises local mwmr fifos descriptors
173    // ( width = 4 bytes / depth = number of analysis threads )
174    mwmr_init( fifo_l2a , data_l2a , 1 , (nprocs - 2) );
175    mwmr_init( fifo_a2s , data_a2s , 1 , (nprocs - 2) );
176    mwmr_init( fifo_s2l , data_s2l , 1 , (nprocs - 2) );
177
178   
179    // each "load" thread initialises local containers as empty in fifo_s2l
180    for ( n = 0 ; n < (nprocs - 2) ; n++ ) mwmr_write( fifo_s2l , &n , 1 );
181
182    // each "load" thread signals mwmr fifos initialisation completion
183    // to other threads in same cluster.
184    local_sync[x][y] = 1;
185
186    // only "load" thread[0][0] displays status
187    if ( (x==0) && (y==0) )
188    {
189        printf("\n[CLASSIF] load on P[%d,%d,%d] enters main loop at cycle %d\n"
190               "      &mwmr_l2a  = %x / &data_l2a  = %x\n"
191               "      &mwmr_a2s  = %x / &data_a2s  = %x\n"
192               "      &mwmr_s2l  = %x / &data_s2l  = %x\n"
193               "      &cont[0]   = %x\n"
194               "      x_size = %d / y_size = %d / nprocs = %d\n",
195               x , y , p , giet_proctime(), 
196               (unsigned int)fifo_l2a, (unsigned int)data_l2a,
197               (unsigned int)fifo_a2s, (unsigned int)data_a2s,
198               (unsigned int)fifo_s2l, (unsigned int)data_s2l,
199               (unsigned int)cont[0],
200               x_size, y_size, nprocs );
201    }
202
203    /////////////////////////////////////////////////////////////
204    // "load" thread enters the main loop (on containers)
205    unsigned int  count = 0;     // loaded containers count
206    unsigned int  index;         // available container index
207    unsigned int* temp;          // pointer on available container
208
209    while ( count < CONTAINERS_MAX ) 
210    { 
211        // get one empty container index from fifo_s2l
212        mwmr_read( fifo_s2l , &index , 1 );
213        temp = cont[index];
214
215        // get one container from  kernel rx_chbuf
216        giet_nic_rx_move( temp );
217
218        // get packets number
219        unsigned int npackets = temp[0] & 0x0000FFFF;
220        unsigned int nwords   = temp[0] >> 16;
221
222        if ( (x==0) && (y==0) )
223        {
224            printf("\n[CLASSIF] load on P[%d,%d,%d] get container %d at cycle %d"
225                   " : %d packets / %d words\n",
226                   x, y, p, index, giet_proctime(), npackets, nwords );
227        }
228
229        // put the full container index to fifo_l2a
230        mwmr_write( fifo_l2a, &index , 1 );
231
232        count++;
233    }
234
235    // all "load" threads synchronise before stats
236    sqt_barrier_wait( &rx_barrier );
237
238    // "load" thread[0][0] displays stats
239    if ( (x==0) && (y==0) ) giet_nic_rx_stats();
240
241    // all "load" thread exit
242    giet_pthread_exit("completed");
243 
244} // end load()
245
246
247//////////////////////////////////////////////////////////////
248__attribute__ ((constructor)) void store( unsigned int * arg )
249//////////////////////////////////////////////////////////////
250{
251    // get plat-form parameters
252    unsigned int x_size;                       // number of clusters in a row
253    unsigned int y_size;                       // number of clusters in a column
254    unsigned int nprocs;                       // number of processors per cluster
255    giet_procs_number( &x_size , &y_size , &nprocs );
256
257    // get processor identifiers
258    unsigned int    x;
259    unsigned int    y;
260    unsigned int    p;
261    giet_proc_xyp( &x, &y, &p );
262
263    // each "store" thread wait mwmr channels initialisation
264    while ( local_sync[x][y] == 0 ) asm volatile ("nop");
265
266    // each "store" thread registers pointers on working containers in local stack
267    unsigned int   n;
268    unsigned int*  cont[NPROCS_MAX-2]; 
269
270    for ( n = 0 ; n < (nprocs - 2) ; n++ )
271    {
272        cont[n] = container[x][y][n];
273    }
274   
275    // each "store" thread registers pointers on mwmr fifos in local stack
276    mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
277    mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
278    mwmr_channel_t* fifo_s2l = mwmr_s2l[x][y];
279
280    // only "store" thread[0][0] displays status
281    if ( (x==0) && (y==0) )
282    {
283        printf("\n[CLASSIF] store on P[%d,%d,%d] enters main loop at cycle %d\n"
284               "      &mwmr_l2a  = %x\n"
285               "      &mwmr_a2s  = %x\n"
286               "      &mwmr_s2l  = %x\n"
287               "      &cont[0]   = %x\n",
288               x , y , p , giet_proctime(), 
289               (unsigned int)fifo_l2a,
290               (unsigned int)fifo_a2s,
291               (unsigned int)fifo_s2l,
292               (unsigned int)cont[0] );
293    }
294
295    /////////////////////////////////////////////////////////////
296    // "store" thread enter the main loop (on containers)
297    unsigned int count = 0;     // stored containers count
298    unsigned int index;         // empty container index
299    unsigned int* temp;         // pointer on empty container
300
301    while ( count < CONTAINERS_MAX ) 
302    { 
303        // get one working container index from fifo_a2s
304        mwmr_read( fifo_a2s , &index , 1 );
305        temp = cont[index];
306
307        // put one container to kernel tx_chbuf
308        giet_nic_tx_move( temp );
309 
310        // get packets number
311        unsigned int npackets = temp[0] & 0x0000FFFF;
312        unsigned int nwords   = temp[0] >> 16;
313
314        if ( (x==0) && (y==0) )
315        {
316            printf("\n[CLASSIF] store on P[%d,%d,%d] get container %d at cycle %d"
317                   " : %d packets / %d words\n",
318                   x, y, p, index, giet_proctime(), npackets, nwords );
319        }
320
321        // put the working container index to fifo_s2l
322        mwmr_write( fifo_s2l, &index , 1 );
323
324        count++;
325    }
326
327    // all "store" threads synchronise before result display
328    sqt_barrier_wait( &tx_barrier );
329
330    // "store" thread[0,0] and displays results
331    if ( (x==0) && (y==0) )
332    {
333        printf("\nClassification Results\n"
334               " - TYPE 0 : %d packets\n"
335               " - TYPE 1 : %d packets\n"
336               " - TYPE 2 : %d packets\n"
337               " - TYPE 3 : %d packets\n"
338               " - TYPE 4 : %d packets\n"
339               " - TYPE 5 : %d packets\n"
340               " - TYPE 6 : %d packets\n"
341               " - TYPE 7 : %d packets\n"
342               " - TYPE 8 : %d packets\n"
343               " - TYPE 9 : %d packets\n"
344               " - TYPE A : %d packets\n"
345               " - TYPE B : %d packets\n"
346               " - TYPE C : %d packets\n"
347               " - TYPE D : %d packets\n"
348               " - TYPE E : %d packets\n"
349               " - TYPE F : %d packets\n"
350               "    TOTAL = %d packets\n",
351               counter[0x0], counter[0x1], counter[0x2], counter[0x3],
352               counter[0x4], counter[0x5], counter[0x6], counter[0x7],
353               counter[0x8], counter[0x9], counter[0xA], counter[0xB],
354               counter[0xC], counter[0xD], counter[0xE], counter[0xF],
355               counter[0x0]+ counter[0x1]+ counter[0x2]+ counter[0x3]+
356               counter[0x4]+ counter[0x5]+ counter[0x6]+ counter[0x7]+
357               counter[0x8]+ counter[0x9]+ counter[0xA]+ counter[0xB]+
358               counter[0xC]+ counter[0xD]+ counter[0xE]+ counter[0xF] );
359
360        giet_nic_tx_stats();
361    }
362
363    // all "store" thread exit
364    giet_pthread_exit("Thread completed");
365
366} // end store()
367
368
369///////////////////////////////////////////////////////////////
370__attribute__ ((constructor)) void analyse( unsigned int* arg )
371///////////////////////////////////////////////////////////////
372{
373    // get platform parameters
374    unsigned int    x_size;                                             // number of clusters in row
375    unsigned int    y_size;                     // number of clusters in a column
376    unsigned int    nprocs;                     // number of processors per cluster
377    giet_procs_number( &x_size, &y_size, &nprocs );
378
379    // get processor identifiers
380    unsigned int    x;
381    unsigned int    y;
382    unsigned int    p;
383    giet_proc_xyp( &x, &y, &p );
384
385    // each "analyse" thread wait mwmr channels initialisation
386    while ( local_sync[x][y] == 0 ) asm volatile ("nop");
387
388    // each "analyse" threads register pointers on working containers in local stack
389    unsigned int   n;
390    unsigned int*  cont[NPROCS_MAX-2]; 
391    for ( n = 0 ; n < (nprocs - 2) ; n++ )
392    {
393        cont[n] = container[x][y][n];
394    }
395
396    // each "analyse" threads register pointers on mwmr fifos in local stack
397    mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
398    mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
399
400    // only "analyse" thread[0][0] display status
401    if ( (x==0) && (y==0) )
402    {
403        printf("\n[CLASSIF] analyse on P[%d,%d,%d] enters main loop at cycle %d\n"
404               "       &mwmr_l2a = %x\n"
405               "       &mwmr_a2s = %x\n"
406               "       &cont[0]  = %x\n",
407               x, y, p, giet_proctime(), 
408               (unsigned int)fifo_l2a,
409               (unsigned int)fifo_a2s,
410               (unsigned int)cont[0] );
411    }
412     
413    //////////////////////////////////////////////////////////////////////
414    // all "analyse" threads enter the main infinite loop (on containers)
415    unsigned int  index;           // available container index
416    unsigned int* temp;            // pointer on available container
417    unsigned int  nwords;          // number of words in container
418    unsigned int  npackets;        // number of packets in container
419    unsigned int  length;          // number of bytes in current packet
420    unsigned int  first;           // current packet first word in container
421    unsigned int  type;            // current packet type
422    unsigned int  pid;             // current packet index
423
424#if VERBOSE_ANALYSE
425    unsigned int       verbose_len[10]; // save length for 10 packets in one container
426    unsigned long long verbose_dst[10]; // save dest   for 10 packets in one container
427    unsigned long long verbose_src[10]; // save source for 10 packets in one container
428#endif
429
430    while ( 1 )
431    { 
432
433#if VERBOSE_ANALYSE
434            for( pid = 0 ; pid < 10 ; pid++ )
435            {
436                verbose_len[pid] = 0;
437                verbose_dst[pid] = 0;
438                verbose_src[pid] = 0;
439            }
440#endif
441        // get one working container index from fifo_l2a
442        mwmr_read( fifo_l2a , &index , 1 );
443        temp = cont[index];
444
445        // get packets number and words number
446        npackets = temp[0] & 0x0000FFFF;
447        nwords   = temp[0] >> 16;
448
449        if ( (x==0) && (y==0) )
450        {
451            printf("\n[CLASSIF] analyse on P[%d,%d,%d] get container at cycle %d"
452                   " : %d packets / %d words\n",
453                   x, y, p, giet_proctime(), npackets, nwords );
454        }
455
456        // initialize word index in container
457        first = 34;
458
459        // loop on packets
460        for( pid = 0 ; pid < npackets ; pid++ )
461        {
462            // get packet length from container header
463            if ( (pid & 0x1) == 0 )  length = temp[1+(pid>>1)] >> 16;
464            else                     length = temp[1+(pid>>1)] & 0x0000FFFF;
465
466            // compute packet DST and SRC MAC addresses
467            unsigned int word0 = temp[first];
468            unsigned int word1 = temp[first + 1];
469            unsigned int word2 = temp[first + 2];
470
471#if VERBOSE_ANALYSE
472            unsigned long long dst = ((unsigned long long)(word1 & 0xFFFF0000)>>16) |
473                                     (((unsigned long long)word0)<<16);
474            unsigned long long src = ((unsigned long long)(word1 & 0x0000FFFF)<<32) |
475                                     ((unsigned long long)word2);
476            if ( pid < 10 )
477            {
478                verbose_len[pid] = length;
479                verbose_dst[pid] = dst;
480                verbose_src[pid] = src;
481            }
482#endif
483            // compute type from SRC MAC address and increment counter
484            type = word1 & 0x0000000F;
485            atomic_increment( &counter[type], 1 );
486
487            // exchange SRC & DST MAC addresses for TX
488            temp[first]     = ((word1 & 0x0000FFFF)<<16) | ((word2 & 0xFFFF0000)>>16);
489            temp[first + 1] = ((word2 & 0x0000FFFF)<<16) | ((word0 & 0xFFFF0000)>>16);
490            temp[first + 2] = ((word0 & 0x0000FFFF)<<16) | ((word1 & 0xFFFF0000)>>16);
491
492            // update first word index
493            if ( length & 0x3 ) first += (length>>2)+1;
494            else                first += (length>>2);
495        }
496       
497#if VERBOSE_ANALYSE
498        if ( (x==0) && (y==0) )
499        {
500            printf("\n*** Thread analyse on P[%d,%d,%d] / container %d at cycle %d\n"
501                   "   - Packet 0 : plen = %d / dst_mac = %l / src_mac = %l\n"
502                   "   - Packet 1 : plen = %d / dst_mac = %l / src_mac = %l\n"
503                   "   - Packet 2 : plen = %d / dst_mac = %l / src_mac = %l\n"
504                   "   - Packet 3 : plen = %d / dst_mac = %l / src_mac = %l\n"
505                   "   - Packet 4 : plen = %d / dst_mac = %l / src_mac = %l\n"
506                   "   - Packet 5 : plen = %d / dst_mac = %l / src_mac = %l\n"
507                   "   - Packet 6 : plen = %d / dst_mac = %l / src_mac = %l\n"
508                   "   - Packet 7 : plen = %d / dst_mac = %l / src_mac = %l\n"
509                   "   - Packet 8 : plen = %d / dst_mac = %l / src_mac = %l\n"
510                   "   - Packet 9 : plen = %d / dst_mac = %l / src_mac = %l\n",
511                   x , y , p , index , giet_proctime() , 
512                   verbose_len[0] , verbose_dst[0] , verbose_src[0] ,
513                   verbose_len[1] , verbose_dst[1] , verbose_src[1] ,
514                   verbose_len[2] , verbose_dst[2] , verbose_src[2] ,
515                   verbose_len[3] , verbose_dst[3] , verbose_src[3] ,
516                   verbose_len[4] , verbose_dst[4] , verbose_src[4] ,
517                   verbose_len[5] , verbose_dst[5] , verbose_src[5] ,
518                   verbose_len[6] , verbose_dst[6] , verbose_src[6] ,
519                   verbose_len[7] , verbose_dst[7] , verbose_src[7] ,
520                   verbose_len[8] , verbose_dst[8] , verbose_src[8] ,
521                   verbose_len[9] , verbose_dst[9] , verbose_src[9] );
522        }
523#endif
524           
525        // pseudo-random delay
526        unsigned int delay = giet_rand()>>3;
527        unsigned int time;
528        for( time = 0 ; time < delay ; time++ ) asm volatile ("nop");
529
530        // put the working container index to fifo_a2s
531        mwmr_write( fifo_a2s , &index , 1 );
532    }
533} // end analyse()
534
535//////////////////////////////////////////
536__attribute__ ((constructor)) void main()
537//////////////////////////////////////////
538{
539    // indexes for loops
540    unsigned int x , y , n;
541
542    // get identifiers for proc executing main
543    unsigned int x_id;                          // x cluster coordinate
544    unsigned int y_id;                          // y cluster coordinate
545    unsigned int p_id;                          // local processor index
546    giet_proc_xyp( &x_id , &y_id , &p_id );
547
548    // get plat-form parameters
549    unsigned int x_size;                       // number of clusters in a row
550    unsigned int y_size;                       // number of clusters in a column
551    unsigned int nprocs;                       // number of processors per cluster
552    giet_procs_number( &x_size , &y_size , &nprocs );
553
554    // shared TTY allocation
555    giet_tty_alloc( 1 );     
556    lock_init( &tty_lock);
557
558    // check plat-form parameters
559    giet_pthread_assert( ((nprocs >= 3) && (nprocs <= 8)),
560                         "[CLASSIF ERROR] number of procs per cluster must in [3...8]");
561
562    giet_pthread_assert( ((x_size >= 1) && (x_size <= 16)),
563                         "[CLASSIF ERROR] x_size must be in [1...16]");
564
565    giet_pthread_assert( ((y_size >= 1) && (y_size <= 16)),
566                         "[CLASSIF ERROR] y_size must be in [1...16]");
567
568    // distributed heap initialisation
569    for ( x = 0 ; x < x_size ; x++ ) 
570    {
571        for ( y = 0 ; y < y_size ; y++ ) 
572        {
573            heap_init( x , y );
574        }
575    }
576
577    printf("\n[CLASSIF] start at cycle %d on %d cores\n", 
578           giet_proctime(), (x_size * y_size * nprocs) );
579
580    // thread index
581    // required by pthread_create()
582    // unused in this appli because no pthread_join()
583    pthread_t   trdid; 
584
585    // rx_barrier initialisation
586    sqt_barrier_init( &rx_barrier, x_size , y_size , 1 );
587
588    // tx_barrier initialisation
589    sqt_barrier_init( &tx_barrier, x_size , y_size , 1 );
590
591    // allocate and start RX NIC and CMA channels
592    giet_nic_rx_alloc( x_size , y_size );
593    giet_nic_rx_start();
594
595    // allocate and start TX NIC and CMA channels
596    giet_nic_tx_alloc( x_size , y_size );
597    giet_nic_tx_start();
598
599    // Initialisation completed
600    printf("\n[CLASSIF] initialisation completed at cycle %d\n", giet_proctime() );
601   
602    // launch load, store and analyse threads
603    for ( x = 0 ; x < x_size ; x++ )
604    {
605        for ( y = 0 ; y < y_size ; y++ )
606        {
607            for ( n = 0 ; n < nprocs ; n++ )
608            {
609                // compute argument value
610                thread_arg[x][y][n] = (x<<8) | (y<<4) | n;
611
612                if ( n == 0 )       // "load" thread
613                {
614                    if ( giet_pthread_create( &trdid,
615                                              NULL,                  // no attribute
616                                              &load,
617                                              &thread_arg[x][y][n] ) )
618                    {
619                        printf("\n[CLASSIF ERROR] launching thread load\n" );
620                        giet_pthread_exit( NULL );
621                    }
622                    else
623                    { 
624                        printf("\n[CLASSIF] thread load activated : trdid = %x\n", trdid );
625                    }
626                }
627                else if ( n == 1 )  // "store" thread
628                {
629                    if ( giet_pthread_create( &trdid,
630                                              NULL,                  // no attribute
631                                              &store,
632                                              &thread_arg[x][y][n] ) )
633                    {
634                        printf("\n[CLASSIF ERROR] launching thread store\n" );
635                        giet_pthread_exit( NULL );
636                    }
637                    else
638                    { 
639                        printf("\n[CLASSIF] thread store activated : trdid = %x\n", trdid );
640                    }
641                }
642                else              // "analyse" threads           
643                {
644                    if ( giet_pthread_create( &trdid,
645                                              NULL,              // no attribute
646                                              &analyse,
647                                              &thread_arg[x][y][n] ) )
648                    {
649                        printf("\n[CLASSIF ERROR] launching thread analyse\n" );
650                        giet_pthread_exit( NULL );
651                    }
652                    else
653                    { 
654                        printf("\n[CLASSIF] thread analyse activated : trdid = %x\n", trdid );
655                    } 
656                }
657            }
658        }
659    }
660
661    giet_pthread_exit( "completed" );
662   
663} // end main()
664
Note: See TracBrowser for help on using the repository browser.