source: soft/giet_vm/transpose/main.c @ 305

Last change on this file since 305 was 295, checked in by alain, 11 years ago

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File size: 17.2 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////////////////
2// File   : main.c   (for transpose application)
3// Date   : february 2014
4// author : Alain Greiner
5//
6// This application makes a transpose for a NN*NN pixels sequence of images.
7// The image sequence is read from a file (one byte per pixel).
8// The input and output buffers containing the image are distributed in all clusters.
9//
10// - The image size NN must be a power of 2.
11// - The number of clusters containing processors (X_SIZE*Y_SIZE-1) must be a power of 2.
12// - The number of processors per cluster (NB_PROCS_MAX) must be a power of 2.
13// - The image size NN must be larger or equal to the total number of processor.
14//
15// For each image the application makes a self test (checksum for each line).
16// The actual display on the frame buffer is optional (controled by DISPLAY_OK define)
17///////////////////////////////////////////////////////////////////////////////////////////////
18
19#include "hard_config.h"
20#include "stdio.h"
21#include "malloc.h"
22#include "barrier.h"
23
24#define NN                  128                 // image size : nlines = npixels = 128
25#define NB_IMAGES           5                   // number of images to be handled
26#define FILE_PATHNAME       "misc/images.raw"   // file pathname on disk
27
28#define VERBOSE_OK          0                   // display a detailed log on TTY  when non zero
29#define INSTRUMENTATION_OK  0                   // display statistcs on TTY when non zero
30
31///////////////////////////////////////////////////////
32// global variables stored in seg_data in cluster(0,0)
33///////////////////////////////////////////////////////
34
35// instrumentation counters
36// for each processor (up to 4 processors)
37// in each cluster (up to 32 clusters)
38unsigned int LOAD_START[32][4];
39unsigned int LOAD_END  [32][4];
40unsigned int TRSP_START[32][4];
41unsigned int TRSP_END  [32][4];
42unsigned int DISP_START[32][4];
43unsigned int DISP_END  [32][4];
44
45// arrays of pointers on distributed buffers
46// one input buffer & one output buffer per cluster
47unsigned char*  buf_in [32];
48unsigned char*  buf_out[32];
49
50// array of heap names
51// one heap per cluster
52char*        heap_name[32] = { "trsp_heap_0" , "trsp_heap_1" , "trsp_heap_2" , "trsp_heap_3" ,
53                               "trsp_heap_4" , "trsp_heap_5" , "trsp_heap_6" , "trsp_heap_7" ,
54                               "trsp_heap_8" , "trsp_heap_9" , "trsp_heap_10", "trsp_heap_11",
55                               "trsp_heap_12", "trsp_heap_13", "trsp_heap_14", "trsp_heap_15",
56                               "trsp_heap_16", "trsp_heap_17", "trsp_heap_18", "trsp_heap_19",
57                               "trsp_heap_20", "trsp_heap_21", "trsp_heap_22", "trsp_heap_23",
58                               "trsp_heap_24", "trsp_heap_25", "trsp_heap_26", "trsp_heap_27",
59                               "trsp_heap_28", "trsp_heap_29", "trsp_heap_30", "trsp_heap_31" };
60
61// checksum variables
62unsigned check_line_before[NN];
63unsigned check_line_after[NN];
64
65// synchronisation barriers
66giet_barrier_t barrier_0;
67giet_barrier_t barrier_1;
68giet_barrier_t barrier_2;
69giet_barrier_t barrier_3;
70giet_barrier_t barrier_4;
71
72volatile unsigned int init_ok = 1;
73
74//////////////////////////////////////////
75__attribute__ ((constructor)) void main()
76{
77
78    int          file;                                          // file descriptor for images
79    unsigned int l;                                             // line index for loops
80    unsigned int p;                                             // pixel index for loops
81    unsigned int proc_id     = giet_procid();                   // processor id
82    unsigned int nclusters   = X_SIZE*(Y_SIZE-1);               // number of clusters with procs
83    unsigned int lpid        = proc_id % NB_PROCS_MAX;          // local processor id
84    unsigned int cluster_xy  = proc_id / NB_PROCS_MAX;          // cluster index (8 bits format)
85    unsigned int x           = cluster_xy >> Y_WIDTH;           // x coordinate
86    unsigned int y           = cluster_xy & ((1<<Y_WIDTH)-1);   // y coordinate
87    unsigned int ntasks      = nclusters * NB_PROCS_MAX;        // number of tasks
88    unsigned int npixels     = NN * NN;                         // number of pixel per image
89    unsigned int nblocks     = npixels / 512;                   // number of blocks per image
90    unsigned int image       = 0;
91 
92    // cluster_id is a "continuous" index from (0 to nclusters-1)
93    // for a cluster with coordinates (x,y)
94    unsigned int cluster_id  = (x * (Y_SIZE-1)) + y;               
95
96    // task_id is a "continuous" index (from 0 to ntasks-1
97    // for the the task running on processor[x,y,lpid]
98    unsigned int task_id = (cluster_id * NB_PROCS_MAX) + lpid;
99
100    giet_shr_printf("\n*** Proc [%d,%d,%d] enters main() at cycle %d ***\n", 
101                    x, y, lpid, giet_proctime() );
102
103    // processor [0,0,0] makes parameters checking and barriers initialization
104    if ( proc_id == 0 )
105    {
106        if ((NB_PROCS_MAX != 1) && (NB_PROCS_MAX != 2) && (NB_PROCS_MAX != 4))
107        { 
108            giet_exit("[TRANSPOSE ERROR] NB_PROCS_MAX must be 1, 2 or 4");
109        }
110        if ((nclusters != 1) && (nclusters != 2) && (nclusters != 4) && (nclusters != 8) &&
111            (nclusters != 16) && (nclusters != 32) )
112        {
113            giet_exit("[TRANSPOSE ERROR] number of clusters must be 2,4,8,16,32");
114        }
115        if ( ntasks > NN )
116        {
117            giet_exit("[TRANSPOSE ERROR] number of tasks larger than number of lines");
118        }
119
120        barrier_init( &barrier_0, ntasks );
121        barrier_init( &barrier_1, ntasks );
122        barrier_init( &barrier_2, ntasks );
123        barrier_init( &barrier_3, ntasks );
124        barrier_init( &barrier_4, ntasks );
125
126        giet_shr_printf("\n*** Proc [%d,%d,%d] completes barrier init at cycle %d\n",
127                        0, 0, 0, giet_proctime() );
128        init_ok = 0;
129    }
130    else   // others processors wait initialisation completion
131    {
132        while ( init_ok == 1 );
133    }
134   
135    // The buffers containing the images are distributed in clusters
136    // (one buf_in and one buf_out per cluster).
137    // Each buffer contains (NN*NN / nclusters) bytes.
138    // They are allocated in the cluster heap by processor with (lpid == 0).
139    if ( lpid == 0 )
140    {
141        unsigned int heap_base;
142        giet_vobj_get_vbase( "transpose",
143                             heap_name[cluster_id],
144                             &heap_base );
145
146        buf_in[cluster_id]  = (unsigned char*)heap_base;
147        buf_out[cluster_id] = (unsigned char*)(heap_base + NN*NN/nclusters);
148
149        giet_shr_printf("\n*** Proc [%d,%d,%d] completes buffer allocation at cycle %d\n"
150                        " - buf_in  = %x\n"
151                        " - buf_out = %x\n",
152                        x, y, 0, giet_proctime(), 
153                        (unsigned int)buf_in[cluster_id], 
154                        (unsigned int)buf_out[cluster_id] );
155
156        // open file containing images
157        file = giet_fat_open( "misc/images.raw", 0);
158
159        giet_assert( (file >= 0), 
160                     "[TRANSPOSE ERROR] cannot open file misc/images.raw");
161
162        giet_shr_printf("\n*** Proc [%d,%d,%d] completes _fat_open at cycle %d\n",
163                            x, y, 0, giet_proctime() ); 
164    }
165
166    //////////////////////////////////////////////////
167    // all tasks wait buffer allocation completion
168    //////////////////////////////////////////////////
169    barrier_wait( &barrier_0 );
170
171    // Main loop (on images)
172    while (image < NB_IMAGES)
173    {
174        // pseudo parallel load from disk to buf_in buffer : nblocks/nclusters blocks
175        // only task running on processor with (lpid == 0) does it
176
177        LOAD_START[cluster_id][lpid] = giet_proctime();
178
179        if (lpid == 0)
180        {
181            giet_shr_printf("\n*** Proc [%d,%d,%d] starts load for image %d at cycle %d\n",
182                           x, y, 0, image, giet_proctime() );
183
184            giet_fat_read( file,
185                           buf_in[cluster_id],
186                           (nblocks / nclusters),
187                           ((image*nblocks) + ((nblocks*cluster_id)/nclusters)) );
188
189            giet_shr_printf("\n*** Proc [%d,%d,0] completes load for image %d at cycle %d\n",
190                            x, y, image, giet_proctime() );
191        }
192
193        LOAD_END[cluster_id][lpid] = giet_proctime();
194
195        //////////////////////////////////////////////////
196        // all tasks wait buf_in load completion
197        //////////////////////////////////////////////////
198        barrier_wait( &barrier_1 );
199
200        // parallel transpose from buf_in to buf_out
201        // each task makes the transposition for nlt lines (nlt = NN/ntasks)
202        // from line [task_id*nlt] to line [(task_id + 1)*nlt - 1]
203        // (p,l) are the absolute pixel coordinates in the source image
204
205        giet_shr_printf("\n*** proc [%d,%d,%d] starts transpose for image %d at cycle %d\n", 
206                        x, y, lpid, image, giet_proctime());
207
208        TRSP_START[cluster_id][lpid] = giet_proctime();
209
210        unsigned int nlt   = NN / ntasks;      // number of lines per task
211        unsigned int nlc   = NN / nclusters;   // number of lines per cluster
212
213        unsigned int src_cluster;
214        unsigned int src_index;
215        unsigned int dst_cluster;
216        unsigned int dst_index;
217
218        unsigned char byte;
219
220        unsigned int first = task_id * nlt;    // first line index for a given task
221        unsigned int last  = first + nlt;      // last line index for a given task
222
223        for ( l = first ; l < last ; l++ )
224        {
225
226#if VERBOSE_OK
227giet_shr_printf(" - Proc[%d,%d,%d] process line %d\n", x, y, lpid, l );
228#endif
229
230            check_line_before[l] = 0;
231         
232            // in each iteration we transfer one byte
233            for ( p = 0 ; p < NN ; p++ )
234            {
235                // read one byte from local buf_in
236                src_cluster = l / nlc;
237                src_index   = (l % nlc)*NN + p;
238                byte        = buf_in[src_cluster][src_index];
239
240                // compute checksum
241                check_line_before[l] = check_line_before[l] + byte;
242
243                // write one byte to remote buf_out
244                dst_cluster = p / nlc; 
245                dst_index   = (p % nlc)*NN + l;
246                buf_out[dst_cluster][dst_index] = byte;
247            }
248        }
249
250        giet_shr_printf("\n*** proc [%d,%d,%d] completes transpose for image %d at cycle %d\n", 
251                        x, y, lpid, image, giet_proctime() );
252
253        TRSP_END[cluster_id][lpid] = giet_proctime();
254
255        //////////////////////////////////////////////////
256        // all tasks wait transpose completion
257        //////////////////////////////////////////////////
258        barrier_wait( &barrier_2 );
259
260        // optional parallel display from local buf_out to frame buffer
261        // all processors contribute to display using memcpy...
262
263        if ( ( X_IO != 0) || (Y_IO != 0) )  // external frame buffer available
264        {
265            giet_shr_printf("\n*** proc [%d,%d,%d] starts display for image %d at cycle %d\n", 
266                            x, y, lpid, image, giet_proctime() );
267
268            DISP_START[cluster_id][lpid] = giet_proctime();
269
270            unsigned int  npt   = npixels / ntasks;   // number of pixels per task
271
272            giet_fb_sync_write( npt * task_id, 
273                                &buf_out[cluster_id][lpid*npt], 
274                                npt );
275
276            giet_shr_printf("\n*** Proc [%d,%d,%d] completes display for image %d at cycle %d\n",
277                            x, y, lpid, image, giet_proctime() );
278
279            DISP_END[cluster_id][lpid] = giet_proctime();
280
281            //////////////////////////////////////////////////
282            // all tasks wait display completion
283            //////////////////////////////////////////////////
284            barrier_wait( &barrier_3 );
285        }
286
287        // checksum done by processor (lpid == 0) in each cluster
288
289        if ( lpid == 0 )
290        {
291            giet_shr_printf("\n*** Proc [%d,%d,%d] starts checks for image %d at cycle %d\n",
292                            x, y, lpid, image, giet_proctime() );
293
294            unsigned int success = 1;
295            unsigned int start   = cluster_id * nlc;
296            unsigned int stop    = start + nlc;
297
298            for ( l = start ; l < stop ; l++ )
299            {
300                check_line_after[l] = 0;
301
302                for ( p = 0 ; p < NN ; p++ )
303                {
304                    // read one byte in remote buffer
305                    src_cluster = p / nlc;
306                    src_index   = (p % nlc)*NN + l;
307
308                    unsigned char byte = buf_out[src_cluster][src_index];
309
310                    check_line_after[l] = check_line_after[l] + byte;
311                }
312
313#if VERBOSE_OK
314giet_shr_printf(" - l = %d / before = %d / after = %d \n",
315                l, check_line_before[l], check_line_after[l] );
316#endif
317                if ( check_line_before[l] != check_line_after[l] ) success = 0;
318            }
319
320            if ( success ) 
321            {
322                giet_shr_printf("\n*** proc [%d,%d,0] : checksum OK for image %d\n",
323                                x, y, image );
324            }
325            else
326            {
327                giet_shr_printf("\n*** proc [%d,%d,0] : checksum KO for image %d\n",
328                                x, y, image );
329            }
330        }
331
332        // instrumentation done by processor [0,0,0]
333
334        if ( (proc_id == 0) && INSTRUMENTATION_OK )
335        {
336            int cc, pp;
337            unsigned int min_load_start = 0xFFFFFFFF;
338            unsigned int max_load_start = 0;
339            unsigned int min_load_ended = 0xFFFFFFFF;
340            unsigned int max_load_ended = 0;
341            unsigned int min_trsp_start = 0xFFFFFFFF;
342            unsigned int max_trsp_start = 0;
343            unsigned int min_trsp_ended = 0xFFFFFFFF;
344            unsigned int max_trsp_ended = 0;
345            unsigned int min_disp_start = 0xFFFFFFFF;
346            unsigned int max_disp_start = 0;
347            unsigned int min_disp_ended = 0xFFFFFFFF;
348            unsigned int max_disp_ended = 0;
349
350            for (cc = 0; cc < nclusters; cc++)
351            {
352                for (pp = 0; pp < NB_PROCS_MAX; pp++)
353                {
354                    if (LOAD_START[cc][pp] < min_load_start)  min_load_start = LOAD_START[cc][pp];
355                    if (LOAD_START[cc][pp] > max_load_start)  max_load_start = LOAD_START[cc][pp];
356                    if (LOAD_END[cc][pp]   < min_load_ended)  min_load_ended = LOAD_END[cc][pp]; 
357                    if (LOAD_END[cc][pp]   > max_load_ended)  max_load_ended = LOAD_END[cc][pp];
358                    if (TRSP_START[cc][pp] < min_trsp_start)  min_trsp_start = TRSP_START[cc][pp];
359                    if (TRSP_START[cc][pp] > max_trsp_start)  max_trsp_start = TRSP_START[cc][pp];
360                    if (TRSP_END[cc][pp]   < min_trsp_ended)  min_trsp_ended = TRSP_END[cc][pp];
361                    if (TRSP_END[cc][pp]   > max_trsp_ended)  max_trsp_ended = TRSP_END[cc][pp];
362                    if (DISP_START[cc][pp] < min_disp_start)  min_disp_start = DISP_START[cc][pp];
363                    if (DISP_START[cc][pp] > max_disp_start)  max_disp_start = DISP_START[cc][pp];
364                    if (DISP_END[cc][pp]   < min_disp_ended)  min_disp_ended = DISP_END[cc][pp];
365                    if (DISP_END[cc][pp]   > max_disp_ended)  max_disp_ended = DISP_END[cc][pp];
366                }
367            }
368
369            giet_shr_printf(" - LOAD_START : min = %d / max = %d / med = %d / delta = %d\n",
370                            min_load_start, max_load_start, (min_load_start+max_load_start)/2, 
371                            max_load_start-min_load_start); 
372
373            giet_shr_printf(" - LOAD_END   : min = %d / max = %d / med = %d / delta = %d\n",
374                            min_load_ended, max_load_ended, (min_load_ended+max_load_ended)/2, 
375                            max_load_ended-min_load_ended); 
376
377            giet_shr_printf(" - TRSP_START : min = %d / max = %d / med = %d / delta = %d\n",
378                            min_trsp_start, max_trsp_start, (min_trsp_start+max_trsp_start)/2, 
379                            max_trsp_start-min_trsp_start); 
380
381            giet_shr_printf(" - TRSP_END   : min = %d / max = %d / med = %d / delta = %d\n",
382                            min_trsp_ended, max_trsp_ended, (min_trsp_ended+max_trsp_ended)/2, 
383                            max_trsp_ended-min_trsp_ended); 
384
385            giet_shr_printf(" - DISP_START : min = %d / max = %d / med = %d / delta = %d\n",
386                            min_disp_start, max_disp_start, (min_disp_start+max_disp_start)/2, 
387                            max_disp_start-min_disp_start); 
388
389            giet_shr_printf(" - DISP_END   : min = %d / max = %d / med = %d / delta = %d\n",
390                            min_disp_ended, max_disp_ended, (min_disp_ended+max_disp_ended)/2, 
391                            max_disp_ended-min_disp_ended); 
392        }
393
394        image++;
395
396        //////////////////////////////////////////////////
397        // all tasks wait instrumentation completion
398        //////////////////////////////////////////////////
399        barrier_wait( &barrier_4 );
400
401    } // end while image     
402
403    giet_exit("Completed");
404
405} // end main()
406
407// Local Variables:
408// tab-width: 3
409// c-basic-offset:
410// c-file-offsets:((innamespace . 0)(inline-open . 0))
411// indent-tabs-mode: nil
412// End:
413
414// vim: filetype=cpp:expandtab:shiftwidth=3:tabstop=3:softtabstop=3
415
416
417
Note: See TracBrowser for help on using the repository browser.