source: soft/giet_vm/applications/classif/main.c @ 536

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

Blap.

File size: 23.6 KB
RevLine 
[502]1///////////////////////////////////////////////////////////////////////////////////////
[457]2// File   : main.c   (for classif application)
3// Date   : november 2014
4// author : Alain Greiner
[502]5///////////////////////////////////////////////////////////////////////////////////////
[480]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.
[488]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.
[457]10//
[502]11// It can run on architectures containing up to 16 * 16 clusters,
12// and up to 8 processors per cluster.
13//
14// This application is described as a TCG (Task and Communication Graph)
15// containing (N+2) tasks per cluster:
[488]16// - one "load" task
[502]17// - one "store" task
[488]18// - N "analyse" tasks
[502]19// The containers are distributed (N+2 containers per cluster):
[488]20// - one RX container (part of the kernel rx_chbuf), in the kernel heap.
21// - one TX container (part of the kernel tx-chbuf), in the kernel heap.
22// - N working containers (one per analysis task), in the user heap.
23// In each cluster, the "load", analysis" and "store" tasks communicates through
24// three local MWMR fifos:
25// - fifo_l2a : tranfer a full container from "load" to "analyse" task.
26// - fifo_a2s : transfer a full container from "analyse" to "store" task.
27// - fifo_s2l : transfer an empty container from "store" to "load" task.
28// For each fifo, one item is a 32 bits word defining the index of an
29// available working container.
30// The pointers on the working containers, and the pointers on the MWMR fifos
31// are global arrays stored in cluster[0][0].
[457]32// a local MWMR fifo containing NB_PROCS_MAX containers (one item = one container).
[480]33// The MWMR fifo descriptors array is defined as a global variable in cluster[0][0].
[457]34//
[502]35// Initialisation is done in two steps by the "load" & "store" tasks:
36// - Task "load" in cluster[0][0] initialises the barrier between all "load" tasks,
37//   allocates NIC & CMA RX channel, and starts the NIC_CMA RX transfer.
38//   Other "load" tasks are waiting on the load_sync synchronisation variable.
39//   Task "store" in cluster[0][0] initialises the barrier between all "store" tasks,
40//   allocates NIC & CMA TX channels, and starts the NIC_CMA TX transfer.
41//   Other "store" tasks are waiting on the store_sync synchronisation variable.
42// - When this global initialisation is completed, the "load" task in all clusters
43//   allocates the working containers and the MWMR fifos descriptors from the
44//   user local heap. In each cluster, the "analyse" and "store" tasks are waiting
45//   the local initialisation completion on the local_sync[x][y] variables.
[488]46//
47// When initialisation is completed, all tasks loop on containers:
48// 1) The "load" task get an empty working container from the fifo_s2l,
49//    transfer one container from the kernel rx_chbuf to this user container,
50//    and transfer ownership of this container to one "analysis" task by writing
51//    into the fifo_l2a.   
52// 2) The "analyse" task get one working container from the fifo_l2a, analyse
53//    each packet header, compute the packet type (depending on the SRC MAC address),
54//    increment the correspondint classification counter, and transpose the SRC
55//    and the DST MAC addresses fot TX tranmission.
56// 3) The "store" task transfer get a full working container from the fifo_a2s,
57//    transfer this user container content to the the kernel tx_chbuf,
58//    and transfer ownership of this empty container to the "load" task by writing
59//    into the fifo_s2l.   
[502]60//     
61// Instrumentation results display is done by the "store" task in cluster[0][0]
62// when all "store" tasks completed the number of clusters specified by the
63// CONTAINERS_MAX parameter.
64///////////////////////////////////////////////////////////////////////////////////////
[457]65
66#include "stdio.h"
[502]67#include "user_barrier.h"
[457]68#include "malloc.h"
69#include "user_lock.h"
70#include "mwmr_channel.h"
71
[502]72#define X_SIZE_MAX      16
73#define Y_SIZE_MAX      16
74#define NPROCS_MAX      8
[536]75#define CONTAINERS_MAX  50
[502]76#define VERBOSE_ANALYSE 0
[457]77
[502]78///////////////////////////////////////////////////////////////////////////////////////
[473]79//    Global variables
[488]80// The MWMR channels (descriptors and buffers), as well as the working containers
81// used by the "analysis" tasks are distributed in clusters.
82// But the pointers on these distributed structures are shared arrays
83// stored in cluster[0][0].
[502]84///////////////////////////////////////////////////////////////////////////////////////
[457]85
[502]86// pointers on distributed containers
87unsigned int*       container[X_SIZE_MAX][Y_SIZE_MAX][NPROCS_MAX-2]; 
[457]88
[488]89// pointers on distributed mwmr fifos containing : temp[x][y][l] container descriptors
[502]90mwmr_channel_t*     mwmr_l2a[X_SIZE_MAX][Y_SIZE_MAX]; 
91mwmr_channel_t*     mwmr_a2s[X_SIZE_MAX][Y_SIZE_MAX];
92mwmr_channel_t*     mwmr_s2l[X_SIZE_MAX][Y_SIZE_MAX]; 
[457]93
[488]94// local synchros signaling local MWMR fifos initialisation completion
[502]95volatile unsigned int        local_sync[X_SIZE_MAX][Y_SIZE_MAX]; 
[457]96
[488]97// global synchro signaling global initialisation completion
[502]98volatile unsigned int        load_sync  = 0; 
99volatile unsigned int        store_sync = 0; 
[457]100
[488]101// instrumentation counters
102unsigned int        counter[16];
[457]103
[502]104// distributed barrier between "load" tasks
105giet_sqt_barrier_t  rx_barrier;
[457]106
[502]107// distributed barrier between "store" tasks
108giet_sqt_barrier_t  tx_barrier;
109
[488]110// NIC_RX and NIC_TX channel index
111unsigned int        nic_rx_channel;
112unsigned int        nic_tx_channel;
113
[480]114/////////////////////////////////////////
[457]115__attribute__ ((constructor)) void load()
[480]116/////////////////////////////////////////
[457]117{
[502]118    // each "load" task get platform parameters
119    unsigned int    x_size;                                             // number of clusters in a row
120    unsigned int    y_size;                     // number of clusters in a column
121    unsigned int    nprocs;                     // number of processors per cluster
122    giet_procs_number( &x_size, &y_size, &nprocs );
123
124    giet_assert( (x_size <= X_SIZE_MAX) && 
125                 (y_size <= Y_SIZE_MAX) && 
126                 (nprocs <= NPROCS_MAX) , 
127                 "[CLASSIF ERROR] illegal platform parameters" );
128
[488]129    // each "load" task get processor identifiers
[457]130    unsigned int    x;
131    unsigned int    y;
132    unsigned int    l;
133    giet_proc_xyp( &x, &y, &l );
134
[502]135    // "load" task[0][0] initialises barrier between all load tasks,
[488]136    // allocates the NIC & CMA RX channels, and start the NIC_CMA RX transfer.
137    // Other "load" tasks wait completion
138    if ( (x==0) && (y==0) )
139    {
[502]140        giet_shr_printf("\n*** Task load on P[%d][%d][%d] starts at cycle %d\n"
141                        "  x_size = %d / y_size = %d / nprocs = %d\n",
142                        x , y , l , giet_proctime() , x_size, y_size, nprocs );
[488]143 
[502]144        sqt_barrier_init( &rx_barrier, x_size , y_size , 1 );
145        nic_rx_channel = giet_nic_rx_alloc( x_size , y_size );
[488]146        giet_nic_rx_start( nic_rx_channel );
147        load_sync = 1;
148    }
149    else
150    {
151        while ( load_sync == 0 ) asm volatile ("nop");
152    }   
[457]153
[502]154    // each load tasks allocates containers[x][y][n] (from local heap)
[488]155    // and register pointers in the local stack
156    unsigned int   n;
[502]157    unsigned int*  cont[NPROCS_MAX-2]; 
158    unsigned int   analysis_tasks = nprocs-2;
[473]159
[502]160    for ( n = 0 ; n < analysis_tasks ; n++ )
[488]161    {
162        container[x][y][n] = malloc( 4096 );
163        cont[n]            = container[x][y][n];
164    }
165   
[502]166    // each load task allocates data buffers for mwmr fifos (from local heap)
167    unsigned int*  data_l2a = malloc( analysis_tasks<<2 );
168    unsigned int*  data_a2s = malloc( analysis_tasks<<2 );
169    unsigned int*  data_s2l = malloc( analysis_tasks<<2 );
[473]170
[502]171    // each load task allocates mwmr fifos descriptors (from local heap)
[488]172    mwmr_l2a[x][y] = malloc( sizeof(mwmr_channel_t) );
173    mwmr_a2s[x][y] = malloc( sizeof(mwmr_channel_t) );
174    mwmr_s2l[x][y] = malloc( sizeof(mwmr_channel_t) );
[473]175
[502]176    // each load task registers local pointers on mwmr fifos in local stack
[488]177    mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
178    mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
179    mwmr_channel_t* fifo_s2l = mwmr_s2l[x][y];
180
[502]181    // each load task initialises local mwmr fifos descriptors
[488]182    // ( width = 4 bytes / depth = number of analysis tasks )
[502]183    mwmr_init( fifo_l2a , data_l2a , 1 , analysis_tasks );
184    mwmr_init( fifo_a2s , data_a2s , 1 , analysis_tasks );
185    mwmr_init( fifo_s2l , data_s2l , 1 , analysis_tasks );
[488]186
187   
[502]188    // each load task initialises local containers as empty in fifo_s2l
189    for ( n = 0 ; n < analysis_tasks ; n++ ) mwmr_write( fifo_s2l , &n , 1 );
[488]190
[502]191    // each load task[x][y] signals mwmr fifos initialisation completion
[488]192    // to other tasks in same cluster[x][y]
193    local_sync[x][y] = 1;
194
[502]195    // load task[0][0] displays status
[488]196    if ( (x==0) && (y==0) )
197    giet_shr_printf("\n*** Task load on P[%d,%d,%d] enters main loop at cycle %d\n"
198                    "      nic_rx_channel = %d / nic_tx_channel = %d\n"
199                    "      &mwmr_l2a  = %x / &data_l2a  = %x\n"
200                    "      &mwmr_a2s  = %x / &data_a2s  = %x\n"
201                    "      &mwmr_s2l  = %x / &data_s2l  = %x\n"
202                    "      &cont[0]   = %x\n"
[473]203                    "      x_size = %d / y_size = %d / nprocs = %d\n",
[488]204                    x , y , l , giet_proctime(), 
205                    nic_rx_channel , nic_tx_channel,
206                    (unsigned int)fifo_l2a, (unsigned int)data_l2a,
207                    (unsigned int)fifo_a2s, (unsigned int)data_a2s,
208                    (unsigned int)fifo_s2l, (unsigned int)data_s2l,
209                    (unsigned int)cont[0],
[502]210                    x_size, y_size, nprocs );
[488]211 
212    /////////////////////////////////////////////////////////////
[502]213    // All load tasks enter the main loop (on containers)
214    unsigned int  count = 0;     // loaded containers count
215    unsigned int  index;         // available container index
216    unsigned int* temp;          // pointer on available container
[457]217
[488]218    while ( count < CONTAINERS_MAX ) 
219    { 
[502]220        // get one empty container index from fifo_s2l
[488]221        mwmr_read( fifo_s2l , &index , 1 );
222        temp = cont[index];
223
[502]224        // get one container from  kernel rx_chbuf
[488]225        giet_nic_rx_move( nic_rx_channel, temp );
226
227        // get packets number
228        unsigned int npackets = temp[0] & 0x0000FFFF;
229        unsigned int nwords   = temp[0] >> 16;
230
[502]231        if ( (x==0) && (y==0) )
[488]232        giet_shr_printf("\n*** Task load on P[%d,%d,%d] get container %d at cycle %d"
233                        " : %d packets / %d words\n",
234                        x, y, l, count, giet_proctime(), npackets, nwords );
235
[502]236        // put the full container index to fifo_l2a
[488]237        mwmr_write( fifo_l2a, &index , 1 );
238
239        count++;
240    }
241
242    // all "load" tasks synchronise before stats
[502]243    sqt_barrier_wait( &rx_barrier );
[488]244
245    // "load" task[0][0] stops the NIC_CMA RX transfer and displays stats
246    if ( (x==0) && (y==0) ) 
[457]247    {
[488]248        giet_nic_rx_stop( nic_rx_channel );
249        giet_nic_rx_stats( nic_rx_channel );
250    }
[457]251
[488]252    // all "load" task exit
253    giet_exit("Task completed");
254 
255} // end load()
[457]256
257
[488]258//////////////////////////////////////////
259__attribute__ ((constructor)) void store()
260//////////////////////////////////////////
261{
[502]262    // each "load" task get platform parameters
263    unsigned int    x_size;                                             // number of clusters in row
264    unsigned int    y_size;                     // number of clusters in a column
265    unsigned int    nprocs;                     // number of processors per cluster
266    giet_procs_number( &x_size, &y_size, &nprocs );
267
[488]268    // get processor identifiers
269    unsigned int    x;
270    unsigned int    y;
271    unsigned int    l;
272    giet_proc_xyp( &x, &y, &l );
273
274    // "store" task[0][0] initialises the barrier between all "store" tasks,
275    // allocates NIC & CMA TX channels, and starts the NIC_CMA TX transfer.
276    // Other "store" tasks wait completion.
277    if ( (x==0) && (y==0) )
278    {
[502]279        giet_shr_printf("\n*** Task store on P[%d][%d][%d] starts at cycle %d\n"
280                        "  x_size = %d / y_size = %d / nprocs = %d\n",
281                        x , y , l , giet_proctime() , x_size, y_size, nprocs );
[488]282 
[502]283        sqt_barrier_init( &tx_barrier , x_size , y_size , 1 );
284        nic_tx_channel = giet_nic_tx_alloc( x_size , y_size );
[488]285        giet_nic_tx_start( nic_tx_channel );
286        store_sync = 1;
[457]287    }
288    else
289    {
[488]290        while ( store_sync == 0 ) asm volatile ("nop");
[457]291    }   
292
[488]293    // all "store" tasks wait mwmr channels initialisation
294    while ( local_sync[x][y] == 0 ) asm volatile ("nop");
[457]295
[502]296    // each "store" tasks register pointers on working containers in local stack
[488]297    unsigned int   n;
[502]298    unsigned int   analysis_tasks = nprocs-2;
299    unsigned int*  cont[NPROCS_MAX-2]; 
300
301    for ( n = 0 ; n < analysis_tasks ; n++ )
[488]302    {
303        cont[n] = container[x][y][n];
304    }
305   
306    // all "store" tasks register pointers on mwmr fifos in local stack
307    mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
308    mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
309    mwmr_channel_t* fifo_s2l = mwmr_s2l[x][y];
310
311    // "store" task[0][0] displays status
312    if ( (x==0) && (y==0) )
313    giet_shr_printf("\n*** Task store on P[%d,%d,%d] enters main loop at cycle %d\n"
314                    "      &mwmr_l2a  = %x\n"
315                    "      &mwmr_a2s  = %x\n"
316                    "      &mwmr_s2l  = %x\n"
317                    "      &cont[0]   = %x\n",
318                    x , y , l , giet_proctime(), 
319                    (unsigned int)fifo_l2a,
320                    (unsigned int)fifo_a2s,
321                    (unsigned int)fifo_s2l,
322                    (unsigned int)cont[0] );
323
324
325    /////////////////////////////////////////////////////////////
326    // all "store" tasks enter the main loop (on containers)
327    unsigned int count = 0;     // stored containers count
328    unsigned int index;         // empty container index
329    unsigned int* temp;         // pointer on empty container
330
331    while ( count < CONTAINERS_MAX ) 
[457]332    { 
[488]333        // get one working container index from fifo_a2s
334        mwmr_read( fifo_a2s , &index , 1 );
335        temp = cont[index];
[457]336
[488]337        // put one container to  kernel tx_chbuf
338        giet_nic_tx_move( nic_tx_channel, temp );
339
[457]340        // get packets number
341        unsigned int npackets = temp[0] & 0x0000FFFF;
342        unsigned int nwords   = temp[0] >> 16;
343
[502]344        if ( (x==0) && (y==0) )
[488]345        giet_shr_printf("\n*** Task store on P[%d,%d,%d] get container %d at cycle %d"
[457]346                        " : %d packets / %d words\n",
[488]347                        x, y, l, count, giet_proctime(), npackets, nwords );
[457]348
[488]349        // put the working container index to fifo_s2l
350        mwmr_write( fifo_s2l, &index , 1 );
[457]351
[488]352        count++;
[457]353    }
354
[488]355    // all "store" tasks synchronise before result display
[502]356    sqt_barrier_wait( &tx_barrier );
[457]357
[488]358    // "store" task[0,0] stops NIC_CMA TX transfer and displays results
[457]359    if ( (x==0) && (y==0) )
360    {
[488]361        giet_nic_tx_stop( nic_tx_channel );
[473]362
[480]363        giet_shr_printf("\n@@@@ Classification Results @@@\n"
[457]364                        " - TYPE 0 : %d packets\n"
365                        " - TYPE 1 : %d packets\n"
366                        " - TYPE 2 : %d packets\n"
367                        " - TYPE 3 : %d packets\n"
368                        " - TYPE 4 : %d packets\n"
369                        " - TYPE 5 : %d packets\n"
370                        " - TYPE 6 : %d packets\n"
371                        " - TYPE 7 : %d packets\n"
372                        " - TYPE 8 : %d packets\n"
373                        " - TYPE 9 : %d packets\n"
374                        " - TYPE A : %d packets\n"
375                        " - TYPE B : %d packets\n"
376                        " - TYPE C : %d packets\n"
377                        " - TYPE D : %d packets\n"
378                        " - TYPE E : %d packets\n"
[488]379                        " - TYPE F : %d packets\n"
380                        "    TOTAL = %d packets\n",
381                        counter[0x0], counter[0x1], counter[0x2], counter[0x3],
382                        counter[0x4], counter[0x5], counter[0x6], counter[0x7],
383                        counter[0x8], counter[0x9], counter[0xA], counter[0xB],
384                        counter[0xC], counter[0xD], counter[0xE], counter[0xF],
385                        counter[0x0]+ counter[0x1]+ counter[0x2]+ counter[0x3]+
386                        counter[0x4]+ counter[0x5]+ counter[0x6]+ counter[0x7]+
387                        counter[0x8]+ counter[0x9]+ counter[0xA]+ counter[0xB]+
388                        counter[0xC]+ counter[0xD]+ counter[0xE]+ counter[0xF] );
[457]389
[488]390        giet_nic_tx_stats( nic_tx_channel );
[457]391    }
392
[488]393    // all "store" task exit
[457]394    giet_exit("Task completed");
395
[488]396} // end store()
397
398
[457]399////////////////////////////////////////////
400__attribute__ ((constructor)) void analyse()
401////////////////////////////////////////////
402{
[502]403    // each "load" task get platform parameters
404    unsigned int    x_size;                                             // number of clusters in row
405    unsigned int    y_size;                     // number of clusters in a column
406    unsigned int    nprocs;                     // number of processors per cluster
407    giet_procs_number( &x_size, &y_size, &nprocs );
408
[457]409    // get processor identifiers
410    unsigned int    x;
411    unsigned int    y;
412    unsigned int    l;
413    giet_proc_xyp( &x, &y, &l );
414
[488]415    if ( (x==0) && (y==0) )
416    {
[502]417        giet_shr_printf("\n*** Task analyse on P[%d][%d][%d] starts at cycle %d\n"
418                        "  x_size = %d / y_size = %d / nprocs = %d\n",
419                        x , y , l , giet_proctime() , x_size, y_size, nprocs );
[488]420    }
421 
422    // all "analyse" tasks wait mwmr channels initialisation
[473]423    while ( local_sync[x][y] == 0 ) asm volatile ("nop");
424
[488]425    // all "analyse" tasks register pointers on working containers in local stack
426    unsigned int   n;
[502]427    unsigned int   analysis_tasks = nprocs-2;
428    unsigned int*  cont[NPROCS_MAX-2]; 
429    for ( n = 0 ; n < analysis_tasks ; n++ )
[488]430    {
431        cont[n] = container[x][y][n];
432    }
[457]433
[488]434    // all "analyse" tasks register pointers on mwmr fifos in local stack
435    mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
436    mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
437
438    // "analyse" task[0][0] display status
439    if ( (x==0) && (y==0) )
440    giet_shr_printf("\n*** Task analyse on P[%d,%d,%d] enters main loop at cycle %d\n"
441                    "       &mwmr_l2a = %x\n"
442                    "       &mwmr_a2s = %x\n"
443                    "       &cont[0]  = %x\n",
[457]444                    x, y, l, giet_proctime(), 
[488]445                    (unsigned int)fifo_l2a,
446                    (unsigned int)fifo_a2s,
447                    (unsigned int)cont[0] );
448     
449    /////////////////////////////////////////////////////////////
450    // all "analyse" tasks enter the main loop (on containers)
451    unsigned int  index;           // available container index
452    unsigned int* temp;            // pointer on available container
453    unsigned int  nwords;          // number of words in container
454    unsigned int  npackets;        // number of packets in container
455    unsigned int  length;          // number of bytes in current packet
456    unsigned int  first;           // current packet first word in container
457    unsigned int  type;            // current packet type
458    unsigned int  p;               // current packet index
459
460#if VERBOSE_ANALYSE
461    unsigned int       verbose_len[10]; // save length for all packets in one container
462    unsigned long long verbose_dst[10]; // save length for all packets in one container
463    unsigned long long verbose_src[10]; // save length for all packets in one container
464#endif
465
[457]466    while ( 1 )
467    { 
468
[488]469#if VERBOSE_ANALYSE
470            for( p = 0 ; p < 10 ; p++ )
471            {
472                verbose_len[p] = 0;
473                verbose_dst[p] = 0;
474                verbose_src[p] = 0;
475            }
476#endif
477        // get one working container index from fifo_l2a
478        mwmr_read( fifo_l2a , &index , 1 );
479        temp = cont[index];
480
481        // get packets number and words number
[457]482        npackets = temp[0] & 0x0000FFFF;
483        nwords   = temp[0] >> 16;
484
[488]485        if ( (x==0) && (y==0) )
486        giet_shr_printf("\n*** Task analyse on P[%d,%d,%d] get container at cycle %d"
[457]487                        " : %d packets / %d words\n",
488                                                x, y, l, giet_proctime(), npackets, nwords );
489
490        // initialize word index in container
[488]491        first = 34;
[457]492
493        // loop on packets
494        for( p = 0 ; p < npackets ; p++ )
495        {
496            // get packet length from container header
497            if ( (p & 0x1) == 0 )  length = temp[1+(p>>1)] >> 16;
498            else                   length = temp[1+(p>>1)] & 0x0000FFFF;
499
[488]500            // compute packet DST and SRC MAC addresses
501            unsigned int word0 = temp[first];
502            unsigned int word1 = temp[first + 1];
503            unsigned int word2 = temp[first + 2];
[457]504
[502]505#if VERBOSE_ANALYSE
[488]506            unsigned long long dst = ((unsigned long long)(word1 & 0xFFFF0000)>>16) |
507                                     (((unsigned long long)word0)<<16);
508            unsigned long long src = ((unsigned long long)(word1 & 0x0000FFFF)<<32) |
509                                     ((unsigned long long)word2);
510            if ( p < 10 )
511            {
512                verbose_len[p] = length;
513                verbose_dst[p] = dst;
514                verbose_src[p] = src;
515            }
516#endif
517            // compute type from SRC MAC address and increment counter
518            type = word1 & 0x0000000F;
519            atomic_increment( &counter[type], 1 );
[457]520
[488]521            // exchange SRC & DST MAC addresses for TX
522            temp[first]     = ((word1 & 0x0000FFFF)<<16) | ((word2 & 0xFFFF0000)>>16);
523            temp[first + 1] = ((word2 & 0x0000FFFF)<<16) | ((word0 & 0xFFFF0000)>>16);
524            temp[first + 2] = ((word0 & 0x0000FFFF)<<16) | ((word1 & 0xFFFF0000)>>16);
525
526            // update first word index
527            if ( length & 0x3 ) first += (length>>2)+1;
528            else                first += (length>>2);
[457]529        }
[488]530       
531#if VERBOSE_ANALYSE
532        if ( (x==0) && (y==0) )
533        giet_shr_printf("\n*** Task analyse on P[%d,%d,%d] completes at cycle %d\n"
534                        "   - Packet 0 : plen = %d / dst_mac = %l / src_mac = %l\n"
535                        "   - Packet 1 : plen = %d / dst_mac = %l / src_mac = %l\n"
536                        "   - Packet 2 : plen = %d / dst_mac = %l / src_mac = %l\n"
537                        "   - Packet 3 : plen = %d / dst_mac = %l / src_mac = %l\n"
538                        "   - Packet 4 : plen = %d / dst_mac = %l / src_mac = %l\n"
539                        "   - Packet 5 : plen = %d / dst_mac = %l / src_mac = %l\n"
540                        "   - Packet 6 : plen = %d / dst_mac = %l / src_mac = %l\n"
541                        "   - Packet 7 : plen = %d / dst_mac = %l / src_mac = %l\n"
542                        "   - Packet 8 : plen = %d / dst_mac = %l / src_mac = %l\n"
543                        "   - Packet 9 : plen = %d / dst_mac = %l / src_mac = %l\n",
544                        x , y , l , giet_proctime() , 
545                        verbose_len[0] , verbose_dst[0] , verbose_src[0] ,
546                        verbose_len[1] , verbose_dst[1] , verbose_src[1] ,
547                        verbose_len[2] , verbose_dst[2] , verbose_src[2] ,
548                        verbose_len[3] , verbose_dst[3] , verbose_src[3] ,
549                        verbose_len[4] , verbose_dst[4] , verbose_src[4] ,
550                        verbose_len[5] , verbose_dst[5] , verbose_src[5] ,
551                        verbose_len[6] , verbose_dst[6] , verbose_src[6] ,
552                        verbose_len[7] , verbose_dst[7] , verbose_src[7] ,
553                        verbose_len[8] , verbose_dst[8] , verbose_src[8] ,
554                        verbose_len[9] , verbose_dst[9] , verbose_src[9] );
555#endif
556           
557        // pseudo-random delay
558        for( p = 0 ; p < (giet_rand()>>4) ; p++ ) asm volatile ("nop");
559
560        // put the working container index to fifo_a2s
561        mwmr_write( fifo_a2s , &index , 1 );
[457]562    }
563} // end analyse()
564
Note: See TracBrowser for help on using the repository browser.