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

Last change on this file since 486 was 480, checked in by alain, 10 years ago

Cosmetic

File size: 10.0 KB
Line 
1/////////////////////////////////////////////////////////////////////////////////////////////
2// File   : main.c   (for classif application)
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 chbuf filled by the CMA
9// component to consume packets on the Gigabit Ethernet port.
10//
11// This application is described as a TCG (Task and Communication Graph) containing
12// - one "load" task per cluster.
13// - from one to three "analyse" tasks per cluster.
14// In each cluster, the "load" task communicates with the local "analyse" tasks through
15// a local MWMR fifo containing NB_PROCS_MAX containers (one item = one container).
16// The MWMR fifo descriptors array is defined as a global variable in cluster[0][0].
17//
18// Initialisation is done in two steps by the "load" tasks:
19// - Task "load" in cluster[0][0] initialises NIC & CMA channel, and initialises
20//   the barrier between all "load" tasks. Other "load" tasks are waiting on the
21//   global_sync synchronisation variable.
22// - In each cluster[x][y], the "load" task allocates the MWMR fifo descriptor and
23//   the data buffer in the local heap, and initializes the MWMR descriptor.
24//   The "analyse" tasks are waiting on the sync[x][y] variables.
25//     
26// When initialisation is completed, all "load and "analyse" tasks loop on containers:
27// 1) The "load" task transfer containers from the kernel chbuf associated to the
28//    NIC_RX channel (in cluster[0][0]), to the local MWMR fifo (in cluster[x][y]),
29//    after an in termediate copy in a private stack buffer.
30//    Each "load" task loads CONTAINERS_MAX containers before exit, and the
31//    task in cluster[0,0] displays the results stored in global counters filled
32//    by the "analyse" tasks when all "load" tasks reach the barrier.
33//
34// 2) The "analyse" task transfer one container from the local MWMR fifo to a private
35//    local buffer. It analyse each packet contained in the container, compute the
36//    packet type, depending on the source MAC address, and increment the counters.
37//
38// It uses the he following hardware parameters, defined in the hard_config.h file:
39// - X_SIZE       : number of clusters in a row
40// - Y_SIZE       : number of clusters in a column
41// - NB_PROCS_MAX : number of processors per cluster
42/////////////////////////////////////////////////////////////////////////////////////////////
43
44#include "stdio.h"
45#include "barrier.h"
46#include "malloc.h"
47#include "user_lock.h"
48#include "mwmr_channel.h"
49#include "hard_config.h"
50
51#define CONTAINERS_MAX   10
52
53///////////////////////////////////////////////////////////////////////////////////////////
54//    Global variables
55// The MWMR channels (descriptors and buffers) are distributed in the clusters,
56// but the pointers array is stored in cluster[0][0]
57///////////////////////////////////////////////////////////////////////////////////////////
58
59mwmr_channel_t*  mwmr[X_SIZE][Y_SIZE];        // distributed MWMR fifos pointers
60
61unsigned int     local_sync[X_SIZE][Y_SIZE];  // distributed synchros "load" / "analyse"
62
63unsigned int     global_sync = 0;             // global synchro between "load" tasks
64
65unsigned int     count[16];                   // instrumentation counters
66
67giet_barrier_t   barrier;                     // barrier between "load" (instrumentation)
68
69unsigned int     nic_channel;                 // allocated NIC channel index
70
71/////////////////////////////////////////
72__attribute__ ((constructor)) void load()
73/////////////////////////////////////////
74{
75    // get processor identifiers
76    unsigned int    x;
77    unsigned int    y;
78    unsigned int    l;
79    giet_proc_xyp( &x, &y, &l );
80
81    // local buffer to store one container in private stack
82    unsigned int  temp[1024];
83
84    // allocates data buffer for MWMR fifo in local heap
85    unsigned int*  data = malloc( NB_PROCS_MAX<<12 );
86
87    // allocates MWMR fifo descriptor in local heap
88    mwmr[x][y] = malloc( sizeof(mwmr_channel_t) );
89    mwmr_channel_t* fifo = mwmr[x][y];
90
91    // initialises local MWMR fifo : width = 4kbytes / depth = NB_PROCS_MAX
92    mwmr_init( fifo , data , 1024 , NB_PROCS_MAX );
93
94    // display for cluster[X_SIZE-1][Y_SIZE-1]
95    if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
96    giet_shr_printf("\n*** Task load starts on P[%d,%d,%d] at cycle %d\n"
97                    "      &mwmr  = %x / &data  = %x / &sync  = %x\n"
98                    "      x_size = %d / y_size = %d / nprocs = %d\n",
99                    x , y , l , giet_proctime() , 
100                    (unsigned int)fifo, (unsigned int)data, (unsigned int)(&local_sync[x][y]),
101                    X_SIZE, Y_SIZE, NB_PROCS_MAX ); 
102
103    // Task load on cluster[0,0] makes global initialisation:
104    // - NIC & CMA channels allocation & initialisation.
105    // - barrier for load tasks initialisation.
106    // Other load task wait completion.
107    if ( (x==0) && (y==0) )
108    {
109        // get NIC_RX channel
110        nic_channel = giet_nic_rx_alloc();
111
112        // start CMA transfer
113        giet_nic_rx_start();
114
115        // barrier init
116        barrier_init( &barrier, X_SIZE * Y_SIZE );
117
118        global_sync = 1;
119    }
120    else
121    {
122        while ( global_sync == 0 ) asm volatile ("nop");
123    }   
124
125    // "load" task signals MWMR initialisation to "analyse" tasks
126    local_sync[x][y] = 1;
127
128    // main loop (on containers)
129    unsigned int container = 0;
130    while ( container < CONTAINERS_MAX ) 
131    { 
132        // get one container from kernel chbuf
133        giet_nic_rx_move( nic_channel, temp );
134
135        // get packets number
136        unsigned int npackets = temp[0] & 0x0000FFFF;
137        unsigned int nwords   = temp[0] >> 16;
138
139        if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
140        giet_shr_printf("\nTask load on P[%d,%d,%d] get container %d at cycle %d"
141                        " : %d packets / %d words\n",
142                        x, y, l, container, giet_proctime(), npackets, nwords );
143
144        // put container to MWMR channel
145        mwmr_write( fifo, temp, 1 );
146
147        container++;
148    }
149
150    // all load tasks synchronise before result display
151    barrier_wait( &barrier );
152
153    // Task load in cluster[0,0] stops NIC and displays results
154    if ( (x==0) && (y==0) )
155    {
156        giet_nic_rx_stop();
157
158        giet_shr_printf("\n@@@@ Classification Results @@@\n"
159                        " - TYPE 0 : %d packets\n"
160                        " - TYPE 1 : %d packets\n"
161                        " - TYPE 2 : %d packets\n"
162                        " - TYPE 3 : %d packets\n"
163                        " - TYPE 4 : %d packets\n"
164                        " - TYPE 5 : %d packets\n"
165                        " - TYPE 6 : %d packets\n"
166                        " - TYPE 7 : %d packets\n"
167                        " - TYPE 8 : %d packets\n"
168                        " - TYPE 9 : %d packets\n"
169                        " - TYPE A : %d packets\n"
170                        " - TYPE B : %d packets\n"
171                        " - TYPE C : %d packets\n"
172                        " - TYPE D : %d packets\n"
173                        " - TYPE E : %d packets\n"
174                        " - TYPE F : %d packets\n",
175                        count[0x0], count[0x1], count[0x2], count[0x3],
176                        count[0x4], count[0x5], count[0x6], count[0x7],
177                        count[0x8], count[0x9], count[0xA], count[0xB],
178                        count[0xC], count[0xD], count[0xE], count[0xF] );
179
180        giet_nic_rx_stats();
181
182    }
183
184    // all load tasks synchronise before exit
185    barrier_wait( &barrier );
186
187    giet_exit("Task completed");
188 
189} // end load()
190
191////////////////////////////////////////////
192__attribute__ ((constructor)) void analyse()
193////////////////////////////////////////////
194{
195    // get processor identifiers
196    unsigned int    x;
197    unsigned int    y;
198    unsigned int    l;
199    giet_proc_xyp( &x, &y, &l );
200
201    // local buffer to store one container
202    unsigned int  temp[1024];
203
204    // wait MWMR channel initialisation (done by task load)
205    while ( local_sync[x][y] == 0 ) asm volatile ("nop");
206
207    // get pointer on MWMR channel descriptor
208    mwmr_channel_t* fifo = mwmr[x][y];
209
210    // display status for cluster[X_SIZE-1][Y_SIZE-1]
211    if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
212    giet_shr_printf("\n*** Task analyse starts on P[%d,%d,%d] at cycle %d\n"
213                    "       &mwmr = %x / &sync = %x\n",
214                    x, y, l, giet_proctime(), 
215                    (unsigned int)fifo, (unsigned int)(&local_sync[x][y]) );
216   
217    // main loop (on containers)
218    unsigned int nwords;     // number of words in container
219    unsigned int npackets;   // number of packets in container
220    unsigned int length;     // number of bytes in current packet
221    unsigned int word;       // current packet first word in container
222    unsigned int type;       // current packet type
223    unsigned int p;          // current packet index
224    while ( 1 )
225    { 
226        // get one container from MWMR fifo
227        mwmr_read( fifo, temp, 1 );
228
229        // get packets number
230        npackets = temp[0] & 0x0000FFFF;
231        nwords   = temp[0] >> 16;
232
233        if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
234        giet_shr_printf("\nTask analyse on P[%d,%d,%d] get container at cycle %d"
235                        " : %d packets / %d words\n",
236                                                x, y, l, giet_proctime(), npackets, nwords );
237
238        // initialize word index in container
239        word = 34;
240
241        // loop on packets
242        for( p = 0 ; p < npackets ; p++ )
243        {
244            // get packet length from container header
245            if ( (p & 0x1) == 0 )  length = temp[1+(p>>1)] >> 16;
246            else                   length = temp[1+(p>>1)] & 0x0000FFFF;
247
248            // get packet type (source mac address)
249            type = (temp[word+1] & 0x0000000F);
250
251            // increment counter
252            atomic_increment( &count[type], 1 );
253
254            // update word index
255            if ( length & 0x3 ) word += (length>>2)+1;
256            else                word += (length>>2);
257        }
258    }
259} // end analyse()
260
Note: See TracBrowser for help on using the repository browser.