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

Last change on this file since 468 was 457, checked in by alain, 10 years ago

Introducing the "classif" application.
Updating the "transpose", "convol", and "router" applications.

File size: 13.7 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 Gigabit Ethernet packets stream, and
7// makes a packet analysis and classification, based on the source MAC address.
8// It uses the NIC peripheral, and the chained buffer build by the CMA component
9// to consume packets on the Gigabit Ethernet port.
10//
11// It 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 descriptor and the data buffer containing the containers are defined
17// as global variables distributed in (up to) 16 clusters.
18//
19// WARNING: the platform cannot contain more than 16 clusters: (X_SIZE < 4) && (Y_SIZE < 4)
20//
21// 1) The "load" task transfer one container from the kernel chbuf associated to the
22//    NIC_RX channel, to a private buffer. Then it copies this bufferer to the local MWMR fifo.
23//    Each "load" task loads CONTAINERS_MAX containers before exit, and the
24//    task in cluster[0,0] displays the results stored in global counters filled
25//    by the "analyse" tasks.
26//
27// 2) The "analyse" task transfer one container from the local MWMR fifo to a private
28//    local buffer. It analyse each packet contained in the container, compute the
29//    packet type, depending on the 4 MSB bits of the source MAC address,
30//    and increment the corresponding counters.
31//
32// It uses the he following hardware parameters, defined in the hard_config.h file:
33// - X_SIZE       : number of clusters in a row
34// - Y_SIZE       : number of clusters in a column
35// - NB_PROCS_MAX : number of processors per cluster
36/////////////////////////////////////////////////////////////////////////////////////////////
37
38#include "stdio.h"
39#include "barrier.h"
40#include "malloc.h"
41#include "user_lock.h"
42#include "mwmr_channel.h"
43#include "hard_config.h"
44
45#define LOAD_VERBOSE     0
46#define ANALYSE_VERBOSE  0
47#define CONTAINERS_MAX   10
48
49///////////  distributed data /////////////////////////////////////////////////////////////
50// - fifo_x_y is the local MWMR fifo descriptor
51// - data_x_y is the local MWMR fifo data buffer
52// - sync_x_y is the local variable signaling MWMR fifo initialisation
53///////////  distributed data /////////////////////////////////////////////////////////////
54
55#if ( (X_SIZE > 0) && (Y_SIZE > 0) )
56__attribute__((section (".data_0_0")))  mwmr_channel_t fifo_0_0;
57__attribute__((section (".data_0_0")))  unsigned int   data_0_0[NB_PROCS_MAX<<10];
58__attribute__((section (".data_0_0")))  unsigned int   sync_0_0 = 0;
59#endif
60#if ( (X_SIZE > 0) && (Y_SIZE > 1) )
61__attribute__((section (".data_0_1")))  mwmr_channel_t fifo_0_1;
62__attribute__((section (".data_0_1")))  unsigned int   data_0_1[NB_PROCS_MAX<<10];
63__attribute__((section (".data_0_1")))  unsigned int   sync_0_1 = 0;
64#endif
65#if ( (X_SIZE > 0) && (Y_SIZE > 2) )
66__attribute__((section (".data_0_2")))  mwmr_channel_t fifo_0_2;
67__attribute__((section (".data_0_2")))  unsigned int   data_0_2[NB_PROCS_MAX<<10];
68__attribute__((section (".data_0_2")))  unsigned int   sync_0_2 = 0;
69#endif
70#if ( (X_SIZE > 0) && (Y_SIZE > 3) )
71__attribute__((section (".data_0_3")))  mwmr_channel_t fifo_0_3;
72__attribute__((section (".data_0_3")))  unsigned int   data_0_3[NB_PROCS_MAX<<10];
73__attribute__((section (".data_0_3")))  unsigned int   sync_0_3 = 0;
74#endif
75#if ( (X_SIZE > 1) && (Y_SIZE > 0) )
76__attribute__((section (".data_1_0")))  mwmr_channel_t fifo_1_0;
77__attribute__((section (".data_1_0")))  unsigned int   data_1_0[NB_PROCS_MAX<<10];
78__attribute__((section (".data_1_0")))  unsigned int   sync_1_0 = 0;
79#endif
80#if ( (X_SIZE > 1) && (Y_SIZE > 1) )
81__attribute__((section (".data_1_1")))  mwmr_channel_t fifo_1_1;
82__attribute__((section (".data_1_1")))  unsigned int   data_1_1[NB_PROCS_MAX<<10];
83__attribute__((section (".data_1_1")))  unsigned int   sync_1_1 = 0;
84#endif
85#if ( (X_SIZE > 1) && (Y_SIZE > 2) )
86__attribute__((section (".data_1_2")))  mwmr_channel_t fifo_1_2;
87__attribute__((section (".data_1_2")))  unsigned int   data_1_2[NB_PROCS_MAX<<10];
88__attribute__((section (".data_1_2")))  unsigned int   sync_1_2 = 0;
89#endif
90#if ( (X_SIZE > 1) && (Y_SIZE > 3) )
91__attribute__((section (".data_1_3")))  mwmr_channel_t fifo_1_3;
92__attribute__((section (".data_1_3")))  unsigned int   data_1_3[NB_PROCS_MAX<<10];
93__attribute__((section (".data_1_3")))  unsigned int   sync_1_3 = 0;
94#endif
95#if ( (X_SIZE > 2) && (Y_SIZE > 0) )
96__attribute__((section (".data_2_0")))  mwmr_channel_t fifo_2_0;
97__attribute__((section (".data_2_0")))  unsigned int   data_2_0[NB_PROCS_MAX<<10];
98__attribute__((section (".data_2_0")))  unsigned int   sync_2_0 = 0;
99#endif
100#if ( (X_SIZE > 2) && (Y_SIZE > 1) )
101__attribute__((section (".data_2_1")))  mwmr_channel_t fifo_2_1;
102__attribute__((section (".data_2_1")))  unsigned int   data_2_1[NB_PROCS_MAX<<10];
103__attribute__((section (".data_2_1")))  unsigned int   sync_2_1 = 0;
104#endif
105#if ( (X_SIZE > 2) && (Y_SIZE > 2) )
106__attribute__((section (".data_2_2")))  mwmr_channel_t fifo_2_2;
107__attribute__((section (".data_2_2")))  unsigned int   data_2_2[NB_PROCS_MAX<<10];
108__attribute__((section (".data_2_2")))  unsigned int   sync_2_2 = 0;
109#endif
110#if ( (X_SIZE > 2) && (Y_SIZE > 3) )
111__attribute__((section (".data_2_3")))  mwmr_channel_t fifo_2_3;
112__attribute__((section (".data_2_3")))  unsigned int   data_2_3[NB_PROCS_MAX<<10];
113__attribute__((section (".data_2_3")))  unsigned int   sync_2_3 = 0;
114#endif
115#if ( (X_SIZE > 3) && (Y_SIZE > 0) )
116__attribute__((section (".data_3_0")))  mwmr_channel_t fifo_3_0;
117__attribute__((section (".data_3_0")))  unsigned int   data_3_0[NB_PROCS_MAX<<10];
118__attribute__((section (".data_3_0")))  unsigned int   sync_3_0 = 0;
119#endif
120#if ( (X_SIZE > 3) && (Y_SIZE > 1) )
121__attribute__((section (".data_3_1")))  mwmr_channel_t fifo_3_1;
122__attribute__((section (".data_3_1")))  unsigned int   data_3_1[NB_PROCS_MAX<<10];
123__attribute__((section (".data_3_1")))  unsigned int   sync_3_1 = 0;
124#endif
125#if ( (X_SIZE > 3) && (Y_SIZE > 2) )
126__attribute__((section (".data_3_2")))  mwmr_channel_t fifo_3_2;
127__attribute__((section (".data_3_2")))  unsigned int   data_3_2[NB_PROCS_MAX<<10];
128__attribute__((section (".data_3_2")))  unsigned int   sync_3_2 = 0;
129#endif
130#if ( (X_SIZE > 3) && (Y_SIZE > 3) )
131__attribute__((section (".data_3_3")))  mwmr_channel_t fifo_3_3;
132__attribute__((section (".data_3_3")))  unsigned int   data_3_3[NB_PROCS_MAX<<10];
133__attribute__((section (".data_3_3")))  unsigned int   sync_3_3 = 0;
134#endif
135
136/////////// shared variables in cluster[0,0] //////////////////////////
137
138__attribute__((section (".data_0_0")))  unsigned int count[16];
139
140__attribute__((section (".data_0_0")))  giet_barrier_t barrier;
141
142__attribute__((section (".data_0_0")))  unsigned int global_init_ok = 0;
143
144__attribute__((section (".data_0_0")))  unsigned int nic_channel;
145
146
147/////////////////////////////////////////
148__attribute__ ((constructor)) void load()
149/////////////////////////////////////////
150{
151    // get processor identifiers
152    unsigned int    x;
153    unsigned int    y;
154    unsigned int    l;
155    giet_proc_xyp( &x, &y, &l );
156
157    if (X_SIZE > 4 )  giet_exit("The X_SIZE parameter cannot be larger than 4\n");
158    if (Y_SIZE > 4 )  giet_exit("The Y_SIZE parameter cannot be larger than 4\n");
159
160    // local buffer to store one container
161    unsigned int  temp[1024];
162
163    // get pointer on local MWMR fifo descriptor and data buffer
164    unsigned int    offset = ((x * 4) + y) * 0x10000;
165    mwmr_channel_t* fifo = (mwmr_channel_t*)(((unsigned int)&fifo_0_0) + offset);
166    unsigned int*   data = (unsigned int*)  (((unsigned int)data_0_0)  + offset);
167    unsigned int*   sync = (unsigned int*)  (((unsigned int)&sync_0_0) + offset);
168
169    if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
170    giet_shr_printf("\n*** Task load starts on P[%d,%d,%d] at cycle %d\n"
171                    "      &fifo = %x / &data = %x / &sync = %x\n",
172                    x, y, l, giet_proctime(), 
173                    (unsigned int)fifo, (unsigned int)data, (unsigned int)sync ); 
174
175    // Task load on cluster[0,0] makes global initialisation:
176    // - NIC & CMA channels allocation & initialisation.
177    // - barrier for all load tasks initialisation.
178    // Other load task wait completion.
179    if ( (x==0) && (y==0) )
180    {
181        // get NIC_RX channel
182        nic_channel = giet_nic_rx_alloc();
183
184        // start CMA transfer
185        giet_nic_rx_start();
186
187        // barrier init
188        barrier_init( &barrier, X_SIZE * Y_SIZE );
189
190        global_init_ok = 1;
191    }
192    else
193    {
194        while ( global_init_ok == 0 ) asm volatile ("nop");
195    }   
196
197    // Each load task initialises local MWMR fifo (width = 4kbytes / depth = NB_PROCS_MAX)
198    mwmr_init( fifo , data , 1024 , NB_PROCS_MAX );
199
200    // signal MWMR fifo initialisation completion
201    *sync = 1;
202
203    // main loop (on containers)
204    unsigned int container = 0;
205    while ( container < CONTAINERS_MAX ) 
206    { 
207        // get one container from kernel chbuf
208        giet_nic_rx_move( nic_channel, temp );
209
210        // get packets number
211        unsigned int npackets = temp[0] & 0x0000FFFF;
212        unsigned int nwords   = temp[0] >> 16;
213
214        if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
215        giet_shr_printf("\nTask load on P[%d,%d,%d] get container %d at cycle %d"
216                        " : %d packets / %d words\n",
217                        x, y, l, container, giet_proctime(), npackets, nwords );
218
219        // put container to MWMR channel
220        mwmr_write( fifo, temp, 1 );
221
222        container++;
223    }
224
225    // all load tasks synchronise before result display
226    barrier_wait( &barrier );
227
228    // Task load in cluster[0,0] displays counters and stops NIC / CMA transfer
229    if ( (x==0) && (y==0) )
230    {
231        giet_shr_printf("\n@@@@ Clasification Results @@@\n"
232                        " - TYPE 0 : %d packets\n"
233                        " - TYPE 1 : %d packets\n"
234                        " - TYPE 2 : %d packets\n"
235                        " - TYPE 3 : %d packets\n"
236                        " - TYPE 4 : %d packets\n"
237                        " - TYPE 5 : %d packets\n"
238                        " - TYPE 6 : %d packets\n"
239                        " - TYPE 7 : %d packets\n"
240                        " - TYPE 8 : %d packets\n"
241                        " - TYPE 9 : %d packets\n"
242                        " - TYPE A : %d packets\n"
243                        " - TYPE B : %d packets\n"
244                        " - TYPE C : %d packets\n"
245                        " - TYPE D : %d packets\n"
246                        " - TYPE E : %d packets\n"
247                        " - TYPE F : %d packets\n",
248            count[0x0], count[0x1], count[0x2], count[0x3],
249            count[0x4], count[0x5], count[0x6], count[0x7],
250            count[0x8], count[0x9], count[0xA], count[0xB],
251            count[0xC], count[0xD], count[0xE], count[0xF] );
252
253        giet_nic_rx_stop();
254
255        giet_nic_rx_stats();
256
257    }
258
259    // all load tasks synchronise before exit
260    barrier_wait( &barrier );
261
262    giet_exit("Task completed");
263 
264} // end load()
265
266////////////////////////////////////////////
267__attribute__ ((constructor)) void analyse()
268////////////////////////////////////////////
269{
270    // get processor identifiers
271    unsigned int    x;
272    unsigned int    y;
273    unsigned int    l;
274    giet_proc_xyp( &x, &y, &l );
275
276    // local buffer to store one container
277    unsigned int  temp[1024];
278
279    // get pointer on MWMR channel descriptor
280    unsigned int    offset = ((x * 4) + y) * 0x10000;
281    mwmr_channel_t* fifo = (mwmr_channel_t*)(((unsigned int)&fifo_0_0) + offset);
282    unsigned int*   sync = (unsigned int*)  (((unsigned int)&sync_0_0) + offset);
283
284    if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
285    giet_shr_printf("\n*** Task analyse starts on P[%d,%d,%d] at cycle %d\n"
286                    "       &fifo = %x / &sync = %x\n",
287                    x, y, l, giet_proctime(), 
288                    (unsigned int)fifo, (unsigned int)sync );
289   
290    // wait MWMR channel initialisation (done by task load)
291    while ( *sync == 0 ) asm volatile ("nop");
292
293    // infinite loop (on containers)
294    unsigned int nwords;     // number of words in container
295    unsigned int npackets;   // number of packets in container
296    unsigned int length;     // number of bytes in current packet
297    unsigned int word;       // current packet first word in container
298    unsigned int type;       // current packet type
299    unsigned int p;          // current packet index
300    while ( 1 )
301    { 
302        // get one container from MWMR fifo
303        mwmr_read( fifo, temp, 1 );
304
305        // get packets number
306        npackets = temp[0] & 0x0000FFFF;
307        nwords   = temp[0] >> 16;
308
309        if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
310        giet_shr_printf("\nTask analyse on P[%d,%d,%d] get container at cycle %d"
311                        " : %d packets / %d words\n",
312                                                x, y, l, giet_proctime(), npackets, nwords );
313
314        // initialize word index in container
315        word = 34;
316
317        // loop on packets
318        for( p = 0 ; p < npackets ; p++ )
319        {
320            // get packet length from container header
321            if ( (p & 0x1) == 0 )  length = temp[1+(p>>1)] >> 16;
322            else                   length = temp[1+(p>>1)] & 0x0000FFFF;
323
324            // get packet type (source mac address 4 MSB bits)
325            type = (temp[word+1] & 0x0000F000) >> 12;
326
327            // increment counter
328            atomic_increment( &count[type], 1 );
329
330            // update word index
331            if ( length & 0x3 ) word += (length>>2)+1;
332            else                word += (length>>2);
333        }
334    }
335} // end analyse()
336
Note: See TracBrowser for help on using the repository browser.