Index: soft/giet_vm/applications/classif/main.c
===================================================================
--- soft/giet_vm/applications/classif/main.c	(revision 488)
+++ soft/giet_vm/applications/classif/main.c	(revision 502)
@@ -1,7 +1,7 @@
-/////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
 // File   : main.c   (for classif application)
 // Date   : november 2014
 // author : Alain Greiner
-/////////////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////////////
 // This multi-threaded application takes a stream of Gigabit Ethernet packets,
 // and makes packet analysis and classification, based on the source MAC address.
@@ -9,10 +9,13 @@
 // component to receive and send packets on the Gigabit Ethernet port. 
 //
-// This application is described as a TCG (Task and Communication Graph) containing
-// (N+2) tasks per cluster:
+// It can run on architectures containing up to 16 * 16 clusters,
+// and up to 8 processors per cluster.
+//
+// This application is described as a TCG (Task and Communication Graph) 
+// containing (N+2) tasks per cluster:
 // - one "load" task
+// - one "store" task
 // - N "analyse" tasks
-// - one "store" task
-// The 4 Kbytes containers are diributed (N+2 containers per cluster):
+// The containers are distributed (N+2 containers per cluster):
 // - one RX container (part of the kernel rx_chbuf), in the kernel heap.
 // - one TX container (part of the kernel tx-chbuf), in the kernel heap.
@@ -30,16 +33,16 @@
 // The MWMR fifo descriptors array is defined as a global variable in cluster[0][0]. 
 //
-// Initialisation is done in two steps by the "load" tasks:
-// - Task "load" in cluster[0][0] initialises NIC & CMA channel, and initialises 
-//   the barrier between all "load" tasks. Other "load" tasks are waiting on the
-//   global_sync synchronisation variable.
-// - In each cluster[x][y], the "load" task allocates the working containers
-//   and the MWMR fifos descriptors in the local heap.
-//   The "analyse" tasks are waiting on the sync[x][y] variables.
+// Initialisation is done in two steps by the "load" & "store" tasks:
+// - Task "load" in cluster[0][0] initialises the barrier between all "load" tasks,
+//   allocates NIC & CMA RX channel, and starts the NIC_CMA RX transfer.
+//   Other "load" tasks are waiting on the load_sync synchronisation variable.
+//   Task "store" in cluster[0][0] initialises the barrier between all "store" tasks,
+//   allocates NIC & CMA TX channels, and starts the NIC_CMA TX transfer.
+//   Other "store" tasks are waiting on the store_sync synchronisation variable.
+// - When this global initialisation is completed, the "load" task in all clusters
+//   allocates the working containers and the MWMR fifos descriptors from the
+//   user local heap. In each cluster, the "analyse" and "store" tasks are waiting
+//   the local initialisation completion on the local_sync[x][y] variables.
 //
-// Instrumentation results display is done by the "store" task in cluster[0][0]
-// when all "store" tasks completed the number of clusters specified by the
-// CONTAINERS_MAX parameter.
-//     
 // When initialisation is completed, all tasks loop on containers:
 // 1) The "load" task get an empty working container from the fifo_s2l,
@@ -47,33 +50,31 @@
 //    and transfer ownership of this container to one "analysis" task by writing
 //    into the fifo_l2a.    
-//
 // 2) The "analyse" task get one working container from the fifo_l2a, analyse
 //    each packet header, compute the packet type (depending on the SRC MAC address),
 //    increment the correspondint classification counter, and transpose the SRC
 //    and the DST MAC addresses fot TX tranmission.
-//
 // 3) The "store" task transfer get a full working container from the fifo_a2s,
 //    transfer this user container content to the the kernel tx_chbuf,
 //    and transfer ownership of this empty container to the "load" task by writing
 //    into the fifo_s2l.   
-//
-// This application uses the following hardware parameters (hard_config.h file):
-// - X_SIZE       : number of clusters in a row
-// - Y_SIZE       : number of clusters in a column
-// - NB_PROCS_MAX : number of processors per cluster
-/////////////////////////////////////////////////////////////////////////////////////////
+//     
+// Instrumentation results display is done by the "store" task in cluster[0][0]
+// when all "store" tasks completed the number of clusters specified by the
+// CONTAINERS_MAX parameter.
+///////////////////////////////////////////////////////////////////////////////////////
 
 #include "stdio.h"
-#include "barrier.h"
+#include "user_barrier.h"
 #include "malloc.h"
 #include "user_lock.h"
 #include "mwmr_channel.h"
-#include "hard_config.h"
-
-#define CONTAINERS_MAX  5
-#define VERBOSE_ANALYSE 1
-#define ANALYSIS_TASKS  (NB_PROCS_MAX - 2)
-
-/////////////////////////////////////////////////////////////////////////////////////////
+
+#define X_SIZE_MAX      16
+#define Y_SIZE_MAX      16
+#define NPROCS_MAX      8
+#define CONTAINERS_MAX  500
+#define VERBOSE_ANALYSE 0
+
+///////////////////////////////////////////////////////////////////////////////////////
 //    Global variables
 // The MWMR channels (descriptors and buffers), as well as the working containers 
@@ -81,27 +82,29 @@
 // But the pointers on these distributed structures are shared arrays
 // stored in cluster[0][0].
-/////////////////////////////////////////////////////////////////////////////////////////
-
-// pointers on distributed temp[x][y][n] containers
-unsigned int*       container[X_SIZE][Y_SIZE][ANALYSIS_TASKS];  
+///////////////////////////////////////////////////////////////////////////////////////
+
+// pointers on distributed containers
+unsigned int*       container[X_SIZE_MAX][Y_SIZE_MAX][NPROCS_MAX-2];  
 
 // pointers on distributed mwmr fifos containing : temp[x][y][l] container descriptors
-mwmr_channel_t*     mwmr_l2a[X_SIZE][Y_SIZE];  
-mwmr_channel_t*     mwmr_a2s[X_SIZE][Y_SIZE];
-mwmr_channel_t*     mwmr_s2l[X_SIZE][Y_SIZE]; 
+mwmr_channel_t*     mwmr_l2a[X_SIZE_MAX][Y_SIZE_MAX];  
+mwmr_channel_t*     mwmr_a2s[X_SIZE_MAX][Y_SIZE_MAX];
+mwmr_channel_t*     mwmr_s2l[X_SIZE_MAX][Y_SIZE_MAX]; 
 
 // local synchros signaling local MWMR fifos initialisation completion
-unsigned int        local_sync[X_SIZE][Y_SIZE];  
+volatile unsigned int        local_sync[X_SIZE_MAX][Y_SIZE_MAX];  
 
 // global synchro signaling global initialisation completion
-unsigned int        load_sync  = 0; 
-unsigned int        store_sync = 0; 
+volatile unsigned int        load_sync  = 0; 
+volatile unsigned int        store_sync = 0; 
 
 // instrumentation counters
 unsigned int        counter[16];
 
-// distributed barriers (between "load" and "store" tasks)
-giet_sbt_barrier_t  rx_barrier;
-giet_sbt_barrier_t  tx_barrier;
+// distributed barrier between "load" tasks
+giet_sqt_barrier_t  rx_barrier;
+
+// distributed barrier between "store" tasks
+giet_sqt_barrier_t  tx_barrier;
 
 // NIC_RX and NIC_TX channel index
@@ -113,4 +116,15 @@
 /////////////////////////////////////////
 {
+    // each "load" task get platform parameters
+    unsigned int    x_size;						// number of clusters in a row
+    unsigned int    y_size;                     // number of clusters in a column
+    unsigned int    nprocs;                     // number of processors per cluster
+    giet_procs_number( &x_size, &y_size, &nprocs );
+
+    giet_assert( (x_size <= X_SIZE_MAX) && 
+                 (y_size <= Y_SIZE_MAX) && 
+                 (nprocs <= NPROCS_MAX) , 
+                 "[CLASSIF ERROR] illegal platform parameters" );
+
     // each "load" task get processor identifiers
     unsigned int    x;
@@ -119,14 +133,15 @@
     giet_proc_xyp( &x, &y, &l );
 
-    // "load" task[0][0] initialises barrier between load tasks,
+    // "load" task[0][0] initialises barrier between all load tasks,
     // allocates the NIC & CMA RX channels, and start the NIC_CMA RX transfer.
     // Other "load" tasks wait completion
     if ( (x==0) && (y==0) )
     {
-        giet_shr_printf("\n*** Task load on P[%d][%d][%d] starts at cycle %d\n",
-                        x , y , l , giet_proctime() );
+        giet_shr_printf("\n*** Task load on P[%d][%d][%d] starts at cycle %d\n"
+                        "  x_size = %d / y_size = %d / nprocs = %d\n",
+                        x , y , l , giet_proctime() , x_size, y_size, nprocs );
  
-        sbt_barrier_init( &rx_barrier, X_SIZE*Y_SIZE , 1 );
-        nic_rx_channel = giet_nic_rx_alloc();
+        sqt_barrier_init( &rx_barrier, x_size , y_size , 1 );
+        nic_rx_channel = giet_nic_rx_alloc( x_size , y_size );
         giet_nic_rx_start( nic_rx_channel );
         load_sync = 1;
@@ -137,10 +152,11 @@
     }    
 
-    // all load tasks allocate containers[x][y][n] (from local heap)
+    // each load tasks allocates containers[x][y][n] (from local heap)
     // and register pointers in the local stack
     unsigned int   n;
-    unsigned int*  cont[ANALYSIS_TASKS]; 
-
-    for ( n = 0 ; n < ANALYSIS_TASKS ; n++ )
+    unsigned int*  cont[NPROCS_MAX-2]; 
+    unsigned int   analysis_tasks = nprocs-2;
+
+    for ( n = 0 ; n < analysis_tasks ; n++ )
     {
         container[x][y][n] = malloc( 4096 );
@@ -148,34 +164,34 @@
     }
     
-    // all load tasks allocate data buffers for mwmr fifos (from local heap)
-    unsigned int*  data_l2a = malloc( ANALYSIS_TASKS<<2 );
-    unsigned int*  data_a2s = malloc( ANALYSIS_TASKS<<2 );
-    unsigned int*  data_s2l = malloc( ANALYSIS_TASKS<<2 );
-
-    // all load tasks allocate mwmr fifos descriptors (from local heap)
+    // each load task allocates data buffers for mwmr fifos (from local heap)
+    unsigned int*  data_l2a = malloc( analysis_tasks<<2 );
+    unsigned int*  data_a2s = malloc( analysis_tasks<<2 );
+    unsigned int*  data_s2l = malloc( analysis_tasks<<2 );
+
+    // each load task allocates mwmr fifos descriptors (from local heap)
     mwmr_l2a[x][y] = malloc( sizeof(mwmr_channel_t) );
     mwmr_a2s[x][y] = malloc( sizeof(mwmr_channel_t) );
     mwmr_s2l[x][y] = malloc( sizeof(mwmr_channel_t) );
 
-    // all "load" tasks register local pointers on mwmr fifos in local stack
+    // each load task registers local pointers on mwmr fifos in local stack
     mwmr_channel_t* fifo_l2a = mwmr_l2a[x][y];
     mwmr_channel_t* fifo_a2s = mwmr_a2s[x][y];
     mwmr_channel_t* fifo_s2l = mwmr_s2l[x][y];
 
-    // all "load" tasks initialise local mwmr fifos descriptors
+    // each load task initialises local mwmr fifos descriptors
     // ( width = 4 bytes / depth = number of analysis tasks )
-    mwmr_init( fifo_l2a , data_l2a , 1 , ANALYSIS_TASKS );
-    mwmr_init( fifo_a2s , data_a2s , 1 , ANALYSIS_TASKS );
-    mwmr_init( fifo_s2l , data_s2l , 1 , ANALYSIS_TASKS );
+    mwmr_init( fifo_l2a , data_l2a , 1 , analysis_tasks );
+    mwmr_init( fifo_a2s , data_a2s , 1 , analysis_tasks );
+    mwmr_init( fifo_s2l , data_s2l , 1 , analysis_tasks );
 
     
-    // all "load" tasks initialise local containers as empty in fifo_s2l
-    for ( n = 0 ; n < ANALYSIS_TASKS ; n++ ) mwmr_write( fifo_s2l , &n , 1 );
-
-    // each "load" task[x][y] signals mwmr fifos initialisation completion
+    // each load task initialises local containers as empty in fifo_s2l
+    for ( n = 0 ; n < analysis_tasks ; n++ ) mwmr_write( fifo_s2l , &n , 1 );
+
+    // each load task[x][y] signals mwmr fifos initialisation completion
     // to other tasks in same cluster[x][y]
     local_sync[x][y] = 1;
 
-    // "load" task[0][0] displays status
+    // load task[0][0] displays status
     if ( (x==0) && (y==0) )
     giet_shr_printf("\n*** Task load on P[%d,%d,%d] enters main loop at cycle %d\n"
@@ -192,19 +208,19 @@
                     (unsigned int)fifo_s2l, (unsigned int)data_s2l,
                     (unsigned int)cont[0],
-                    X_SIZE, Y_SIZE, NB_PROCS_MAX );
+                    x_size, y_size, nprocs );
  
     /////////////////////////////////////////////////////////////
-    // All "load" tasks enter the main loop (on containers)
-    unsigned int count = 0;     // loaded containers count
-    unsigned int index;         // available container index
-    unsigned int* temp;         // pointer on available container
+    // All load tasks enter the main loop (on containers)
+    unsigned int  count = 0;     // loaded containers count
+    unsigned int  index;         // available container index
+    unsigned int* temp;          // pointer on available container
 
     while ( count < CONTAINERS_MAX ) 
     { 
-        // get one empty count index from fifo_s2l
+        // get one empty container index from fifo_s2l
         mwmr_read( fifo_s2l , &index , 1 );
         temp = cont[index];
 
-        // get one count from  kernel rx_chbuf
+        // get one container from  kernel rx_chbuf
         giet_nic_rx_move( nic_rx_channel, temp );
 
@@ -213,10 +229,10 @@
         unsigned int nwords   = temp[0] >> 16;
 
-        if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
+        if ( (x==0) && (y==0) )
         giet_shr_printf("\n*** Task load on P[%d,%d,%d] get container %d at cycle %d"
                         " : %d packets / %d words\n",
                         x, y, l, count, giet_proctime(), npackets, nwords );
 
-        // put the full count index to fifo_l2a
+        // put the full container index to fifo_l2a
         mwmr_write( fifo_l2a, &index , 1 );
 
@@ -225,5 +241,5 @@
 
     // all "load" tasks synchronise before stats
-    sbt_barrier_wait( &rx_barrier );
+    sqt_barrier_wait( &rx_barrier );
 
     // "load" task[0][0] stops the NIC_CMA RX transfer and displays stats
@@ -244,4 +260,10 @@
 //////////////////////////////////////////
 {
+    // each "load" task get platform parameters
+    unsigned int    x_size;						// number of clusters in row
+    unsigned int    y_size;                     // number of clusters in a column
+    unsigned int    nprocs;                     // number of processors per cluster
+    giet_procs_number( &x_size, &y_size, &nprocs );
+
     // get processor identifiers
     unsigned int    x;
@@ -250,5 +272,4 @@
     giet_proc_xyp( &x, &y, &l );
 
-
     // "store" task[0][0] initialises the barrier between all "store" tasks,
     // allocates NIC & CMA TX channels, and starts the NIC_CMA TX transfer.
@@ -256,9 +277,10 @@
     if ( (x==0) && (y==0) )
     {
-        giet_shr_printf("\n*** Task store on P[%d][%d][%d] starts at cycle %d\n",
-                        x , y , l , giet_proctime() );
+        giet_shr_printf("\n*** Task store on P[%d][%d][%d] starts at cycle %d\n"
+                        "  x_size = %d / y_size = %d / nprocs = %d\n",
+                        x , y , l , giet_proctime() , x_size, y_size, nprocs );
  
-        sbt_barrier_init( &tx_barrier , X_SIZE*Y_SIZE , 1 );
-        nic_tx_channel = giet_nic_tx_alloc();
+        sqt_barrier_init( &tx_barrier , x_size , y_size , 1 );
+        nic_tx_channel = giet_nic_tx_alloc( x_size , y_size );
         giet_nic_tx_start( nic_tx_channel );
         store_sync = 1;
@@ -272,8 +294,10 @@
     while ( local_sync[x][y] == 0 ) asm volatile ("nop");
 
-    // all "store" tasks register pointers on working containers in local stack
+    // each "store" tasks register pointers on working containers in local stack
     unsigned int   n;
-    unsigned int*  cont[ANALYSIS_TASKS]; 
-    for ( n = 0 ; n < ANALYSIS_TASKS ; n++ )
+    unsigned int   analysis_tasks = nprocs-2;
+    unsigned int*  cont[NPROCS_MAX-2]; 
+
+    for ( n = 0 ; n < analysis_tasks ; n++ )
     {
         cont[n] = container[x][y][n];
@@ -318,5 +342,5 @@
         unsigned int nwords   = temp[0] >> 16;
 
-        if ( (x==X_SIZE-1) && (y==Y_SIZE-1) )
+        if ( (x==0) && (y==0) )
         giet_shr_printf("\n*** Task store on P[%d,%d,%d] get container %d at cycle %d"
                         " : %d packets / %d words\n",
@@ -330,5 +354,5 @@
 
     // all "store" tasks synchronise before result display
-    sbt_barrier_wait( &tx_barrier );
+    sqt_barrier_wait( &tx_barrier );
 
     // "store" task[0,0] stops NIC_CMA TX transfer and displays results 
@@ -377,4 +401,10 @@
 ////////////////////////////////////////////
 {
+    // each "load" task get platform parameters
+    unsigned int    x_size;						// number of clusters in row
+    unsigned int    y_size;                     // number of clusters in a column
+    unsigned int    nprocs;                     // number of processors per cluster
+    giet_procs_number( &x_size, &y_size, &nprocs );
+
     // get processor identifiers
     unsigned int    x;
@@ -385,6 +415,7 @@
     if ( (x==0) && (y==0) )
     {
-        giet_shr_printf("\n*** Task analyse on P[%d][%d][%d] starts at cycle %d\n",
-                        x , y , l , giet_proctime() );
+        giet_shr_printf("\n*** Task analyse on P[%d][%d][%d] starts at cycle %d\n"
+                        "  x_size = %d / y_size = %d / nprocs = %d\n",
+                        x , y , l , giet_proctime() , x_size, y_size, nprocs );
     }
  
@@ -394,6 +425,7 @@
     // all "analyse" tasks register pointers on working containers in local stack
     unsigned int   n;
-    unsigned int*  cont[ANALYSIS_TASKS]; 
-    for ( n = 0 ; n < ANALYSIS_TASKS ; n++ )
+    unsigned int   analysis_tasks = nprocs-2;
+    unsigned int*  cont[NPROCS_MAX-2]; 
+    for ( n = 0 ; n < analysis_tasks ; n++ )
     {
         cont[n] = container[x][y][n];
@@ -471,9 +503,9 @@
             unsigned int word2 = temp[first + 2];
 
+#if VERBOSE_ANALYSE 
             unsigned long long dst = ((unsigned long long)(word1 & 0xFFFF0000)>>16) |
                                      (((unsigned long long)word0)<<16);
             unsigned long long src = ((unsigned long long)(word1 & 0x0000FFFF)<<32) |
                                      ((unsigned long long)word2);
-#if VERBOSE_ANALYSE 
             if ( p < 10 )
             {
