source: soft/giet_vm/applications/mjpeg/mjpeg.c @ 736

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

Modify the mjpeg application to support an optional
DCT hardware coprocessor.

File size: 14.4 KB
Line 
1/////////////////////////////////////////////////////////////////////////////////////////
2// File   : mjpeg.c   
3// Date   : octobre 2015
4// author : Alain Greiner
5/////////////////////////////////////////////////////////////////////////////////////////
6// This multi-threaded application illustrates "pipe-line" parallelism, and message
7// passing programming model, on top of the POSIX threads API.
8// It makes the parallel decompression of a MJPEG bitstream contained in a file.
9// The application is described as a TCG (Task and Communication Graph), and all
10// communications between threads uses MWMR channels,.
11// It uses the chained buffer DMA component to display the images on the graphic display.
12// It contains 6 types of threads (plus the "main" thread, that makes initialisation)
13// and 7 types of MWMR communication channels:
14// - the TG thread is only mapped in cluster[0,0], but all other threads
15//   (DEMUX, VLD, IQZZ, IDCT, LIBU) are replicated in all clusters.
16// - all MWMR channels are replicated in all clusters.
17// The number of cluster cannot be larger than 16*16.
18// The number of processors per cluster is not constrained.
19// The frame buffer size must fit the decompressed images size.
20// It uses one TTY terminal shared by all tasks.
21/////////////////////////////////////////////////////////////////////////////////////////
22
23#include <stdio.h>
24#include <mwmr_channel.h>
25#include <malloc.h>
26#include <stdlib.h>
27#include "mjpeg.h"
28#include <mapping_info.h>     // for coprocessor types and modes
29
30
31// macro to use a shared TTY
32#define PRINTF(...)    lock_acquire( &tty_lock ); \
33                       giet_tty_printf(__VA_ARGS__);  \
34                       lock_release( &tty_lock );
35
36///////////////////////////////////////////////
37//       Global variables
38///////////////////////////////////////////////
39
40uint32_t         fd;    // file descriptor for the file containing the MJPEG stream
41
42// arrays of pointers on MWMR channels
43mwmr_channel_t*  tg_2_demux[256];         // one per cluster
44mwmr_channel_t*  demux_2_vld_data[256];   // one per cluster
45mwmr_channel_t*  demux_2_vld_huff[256];   // one per cluster
46mwmr_channel_t*  demux_2_iqzz[256];       // one per cluster
47mwmr_channel_t*  vld_2_iqzz[256];         // one per cluster
48mwmr_channel_t*  iqzz_2_idct[256];        // one per cluster
49mwmr_channel_t*  idct_2_libu[256];        // one per cluster
50
51// thread trdid ( for pthread_create() and pthread_join() )
52pthread_t   trdid_tg; 
53pthread_t   trdid_demux[256];             // one per cluster
54pthread_t   trdid_vld[256];               // one per cluster
55pthread_t   trdid_iqzz[256];              // one per cluster
56pthread_t   trdid_idct[256];              // one per cluster
57pthread_t   trdid_libu[256];              // one per cluster
58
59user_lock_t      tty_lock;                // lock protecting shared TTY
60
61uint8_t*         cma_buf[256];            // CMA buffers (one per cluster)
62void*            cma_sts[256];            // CMA buffers status
63
64uint32_t         fbf_width;               // Frame Buffer width
65uint32_t         fbf_height;              // Frame Buffer height
66
67uint32_t         nblocks_h;               // number of blocks in a column
68uint32_t         nblocks_w;               // number of blocks in a row   
69
70uint32_t         date[MAX_IMAGES];        // date of libu completion
71
72////////////////////////////////////////////////
73// declare thread functions
74////////////////////////////////////////////////
75
76extern void tg( );
77extern void demux( uint32_t index );
78extern void vld( uint32_t index );
79extern void iqzz( uint32_t index );
80extern void idct( uint32_t index );
81extern void libu( uint32_t index );
82
83/////////////////////////////////////////
84__attribute__ ((constructor)) void main()
85/////////////////////////////////////////
86{
87    // get platform parameters
88    uint32_t  x_size;
89    uint32_t  y_size;
90    uint32_t  nprocs;
91    giet_procs_number( &x_size , &y_size , &nprocs );
92
93    // shared TTY allocation
94    giet_tty_alloc( 1 );
95    lock_init( &tty_lock );
96
97    // check platform parameters
98    giet_pthread_assert( (nprocs <= 6),
99                         "[MJPEG ERROR] nprocs cannot be larger than 4");
100
101    giet_pthread_assert( (x_size <= 16),
102                         "[MJPEG ERROR] x_size cannot be larger than 16");
103
104    giet_pthread_assert( (y_size <= 16),
105                         "[MJPEG ERROR] y_size cannot be larger than 16");
106
107    giet_pthread_assert( (MAX_IMAGES >= (x_size*y_size)),
108                         "MJPEG ERROR] number of images smaller than x_size * y_size");
109
110    // check frame buffer size
111    giet_fbf_size( &fbf_width , &fbf_height );
112
113    giet_pthread_assert( ((fbf_width & 0x7) == 0) && ((fbf_height & 0x7) == 0) ,
114                         "[MJPEG ERROR] image width and height must be multiple of 8");
115
116    // request frame buffer and CMA channel allocation
117    giet_fbf_alloc();
118    giet_fbf_cma_alloc( x_size * y_size );
119
120    // file name and image size acquisition
121    char          file_pathname[256];
122    uint32_t      image_width;
123    uint32_t      image_height;
124
125    if ( INTERACTIVE_MODE )
126    {
127        PRINTF("\n[MJPEG] enter path for JPEG stream file (default is plan_48.mjpg)\n> ") 
128        giet_tty_gets( file_pathname , 256 );
129
130        if ( file_pathname[0] == 0 )
131        {
132            strcpy( file_pathname , "/misc/plan_48.mjpg" );
133            image_width  = 48;
134            image_height = 48;
135        }
136        else
137        {
138            PRINTF("\n[MJPEG] enter image width\n> ") 
139            giet_tty_getw( &image_width );
140            PRINTF("\n[MJPEG] enter image height\n> ") 
141            giet_tty_getw( &image_height );
142            PRINTF("\n") 
143        }
144    }
145    else
146    {
147        strcpy( file_pathname , "/misc/plan_48.mjpg" );
148        image_width  = 48;
149        image_height = 48;
150    }
151   
152    giet_pthread_assert( (image_width == fbf_width) && (image_height == fbf_height) ,
153                         "[MJPEG ERROR] image size doesn't fit frame buffer size");
154 
155    PRINTF("\n\n[MJPEG] starts for stream %s\n", file_pathname )
156
157    // compute nblocks_h & nblocks_w
158    nblocks_w = fbf_width / 8;
159    nblocks_h = fbf_height / 8;
160
161    // open file containing the MJPEG bit stream
162    int fd = giet_fat_open( file_pathname , 0 );
163
164    giet_pthread_assert( (fd >= 0),
165                         "[MJPEG ERROR] cannot open MJPEG stream file");
166
167    // index for loops
168    uint32_t x;
169    uint32_t y;
170    uint32_t n;
171
172    uint32_t*  buffer; 
173
174    // initialise distributed heap,
175    // allocate MWMR channels
176    // allocate buffers for CMA
177    for ( x = 0 ; x < x_size ; x++ ) 
178    {
179        for ( y = 0 ; y < y_size ; y++ ) 
180        {
181            uint32_t index = x*y_size + y;
182
183            // initialise heap[x][y]
184            heap_init( x , y );
185
186            // allocate MWMR channels in cluster[x][y]
187            tg_2_demux[index]       = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
188            buffer                  = remote_malloc( 4 * TG_2_DEMUX_DEPTH , x , y );
189            mwmr_init( tg_2_demux[index] , buffer , 1 , TG_2_DEMUX_DEPTH );
190
191            demux_2_vld_data[index] = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
192            buffer                  = remote_malloc( 4 * DEMUX_2_VLD_DATA_DEPTH , x , y );
193            mwmr_init( demux_2_vld_data[index] , buffer , 1 , DEMUX_2_VLD_DATA_DEPTH );
194
195            demux_2_vld_huff[index] = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
196            buffer                  = remote_malloc( 4 * DEMUX_2_VLD_HUFF_DEPTH , x , y );
197            mwmr_init( demux_2_vld_huff[index] , buffer , 1 , DEMUX_2_VLD_HUFF_DEPTH );
198
199            demux_2_iqzz[index]     = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
200            buffer                  = remote_malloc( 4 * DEMUX_2_IQZZ_DEPTH , x , y );
201            mwmr_init( demux_2_iqzz[index] , buffer , 1 , DEMUX_2_IQZZ_DEPTH );
202
203            vld_2_iqzz[index]       = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
204            buffer                  = remote_malloc( 4 * VLD_2_IQZZ_DEPTH , x , y );
205            mwmr_init( vld_2_iqzz[index] , buffer , 1 , VLD_2_IQZZ_DEPTH );
206
207            iqzz_2_idct[index]      = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
208            buffer                  = remote_malloc( 4 * IQZZ_2_IDCT_DEPTH , x , y );
209            mwmr_init( iqzz_2_idct[index] , buffer , 1 , IQZZ_2_IDCT_DEPTH );
210
211            idct_2_libu[index]      = remote_malloc( sizeof( mwmr_channel_t ) , x , y );
212            buffer                  = remote_malloc( 4 * IDCT_2_LIBU_DEPTH , x , y );
213            mwmr_init( idct_2_libu[index] , buffer , 1 , IDCT_2_LIBU_DEPTH );
214
215            // allocate and register CMA buffers in cluster[x][y]
216            cma_buf[index] = remote_malloc( fbf_width * fbf_height , x , y );
217            cma_sts[index] = remote_malloc( 64 , x , y );
218            giet_fbf_cma_init_buf( index , cma_buf[index] , cma_sts[index] );
219        }
220    }
221
222    // start CMA channel
223    giet_fbf_cma_start();
224
225    PRINTF("\n[MJPEG] main thread completes initialisation for %d cores\n",
226           x_size * y_size * nprocs )
227
228    mwmr_channel_t* ptr;
229
230    for ( n = 0 ; n < x_size*y_size ; n++ )
231    {
232        ptr = tg_2_demux[n];
233        PRINTF(" - tg_2_demux[%d]  = %x / &lock = %x / &buf = %x / size = %d\n",
234               n, ptr, (uint32_t)&ptr->lock, (uint32_t)ptr->data, ptr->depth<<2 ) 
235
236        ptr = demux_2_vld_data[n];
237        PRINTF(" - demux_2_vld[%d] = %x / &lock = %x / &buf = %x / size = %d\n",
238               n, ptr, (uint32_t)&ptr->lock, (uint32_t)ptr->data, ptr->depth<<2 ) 
239
240        ptr = vld_2_iqzz[n];
241        PRINTF(" - vld_2_iqzz[%d]  = %x / &lock = %x / &buf = %x / size = %d\n",
242               n, ptr, (uint32_t)&ptr->lock, (uint32_t)ptr->data, ptr->depth<<2 ) 
243
244        ptr = iqzz_2_idct[n];
245        PRINTF(" - iqzz_2_idct[%d] = %x / &lock = %x / &buf = %x / size = %d\n",
246               n, ptr, (uint32_t)&ptr->lock, (uint32_t)ptr->data, ptr->depth<<2 ) 
247
248        ptr = idct_2_libu[n];
249        PRINTF(" - idct_2_libu[%d] = %x / &lock = %x / &buf = %x / size = %d\n",
250               n, ptr, (uint32_t)&ptr->lock, (uint32_t)ptr->data, ptr->depth<<2 ) 
251    }
252
253    // launch all threads : precise mapping is defined in the mjpeg.py file
254    uint32_t index;
255
256    if ( giet_pthread_create( &trdid_tg, NULL, &tg , NULL ) )
257    giet_pthread_exit( "error launching thread tg\n");
258
259    for ( x = 0 ; x < x_size ; x++ )
260    {
261        for ( y = 0 ; y < y_size ; y++ )
262        {
263            index = x * y_size + y;
264
265            // DEMUX 
266            if ( giet_pthread_create( &trdid_demux[index], NULL, &demux , (void*)index ) )
267            giet_pthread_exit( "error launching thread demux\n");
268
269            // VLD
270            if ( giet_pthread_create( &trdid_vld[index], NULL, &vld , (void*)index ) )
271            giet_pthread_exit( "error launching thread vld\n");
272
273            // IQZZ
274            if ( giet_pthread_create( &trdid_iqzz[index], NULL, &iqzz , (void*)index ) )
275            giet_pthread_exit( "error launching thread iqzz");
276
277            // IDCT
278            if ( USE_DCT_COPROC )  // allocate, initialise, and start hardware coprocessor
279            {
280                giet_coproc_channel_t in_channel;
281                giet_coproc_channel_t out_channel;
282                uint32_t  cluster_xy  = (x<<4) + y;
283                uint32_t  coproc_type = 2;
284                uint32_t  info;
285
286                // allocate DCT coprocessor
287                giet_coproc_alloc( cluster_xy , coproc_type , &info );
288
289                // initialize channels
290                in_channel.channel_mode = MODE_MWMR;
291                in_channel.buffer_size  = (iqzz_2_idct[index]->depth)<<2;
292                in_channel.buffer_vaddr = (uint32_t)(iqzz_2_idct[index]->data);
293                in_channel.status_vaddr = (uint32_t)(&iqzz_2_idct[index]->sts);
294                in_channel.lock_vaddr   = (uint32_t)(&iqzz_2_idct[index]->lock);
295   
296                giet_coproc_channel_init( cluster_xy , coproc_type , 0 , &in_channel );
297
298                out_channel.channel_mode = MODE_MWMR;
299                out_channel.buffer_size  = (idct_2_libu[index]->depth)<<2;
300                out_channel.buffer_vaddr = (uint32_t)(idct_2_libu[index]->data);
301                out_channel.status_vaddr = (uint32_t)(&idct_2_libu[index]->sts);
302                out_channel.lock_vaddr   = (uint32_t)(&idct_2_libu[index]->lock);
303
304                giet_coproc_channel_init( cluster_xy , coproc_type , 1 , &out_channel );
305
306                // start coprocessor
307                giet_coproc_run( cluster_xy , coproc_type );
308            }
309            else                   // launches a software thread
310            {
311                if ( giet_pthread_create( &trdid_idct[index], NULL, &idct , (void*)index ) )
312                giet_pthread_exit( "error launching thread idct\n");
313            }
314
315            // LIBU
316            if ( giet_pthread_create( &trdid_libu[index], NULL, &libu , (void*)index ) )
317            giet_pthread_exit( "error launching thread libu\n");
318        }
319    }
320
321    // wait all threads completion
322
323    if ( giet_pthread_join( trdid_tg , NULL ) )
324    { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for tg\n" ) }
325
326    for ( x = 0 ; x < x_size ; x++ )
327    {
328        for ( y = 0 ; y < y_size ; y++ )
329        {
330            index = x * y_size + y;
331
332            if ( giet_pthread_join( trdid_demux[index] , NULL ) )
333            { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for demux[%d]\n", index ) }
334
335            if ( giet_pthread_join( trdid_vld[index] , NULL ) )
336            { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for vld[%d]\n", index ) }
337
338            if ( giet_pthread_join( trdid_iqzz[index] , NULL ) )
339            { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for iqzz[%d]\n", index ) }
340
341            if ( USE_DCT_COPROC == 0 )
342            {
343                if ( giet_pthread_join( trdid_idct[index] , NULL ) )
344                { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for idct[%d]\n", index ) }
345            }
346
347            if ( giet_pthread_join( trdid_libu[index] , NULL ) )
348            { PRINTF("\n[MJPEG ERROR] calling giet_pthread_join() for libu[%d]\n", index ) }
349
350            if ( USE_DCT_COPROC )
351            {
352                uint32_t  cluster_xy  = (x<<4) + y;
353                uint32_t  coproc_type = 2;
354                giet_coproc_release( cluster_xy , coproc_type );
355            }
356        }
357    }
358
359    // instrumentation
360
361    uint32_t image;
362    PRINTF("\n[MJPEG] Instumentation Results\n" )
363    for ( image = 0 ; image < MAX_IMAGES ; image++ )
364    { PRINTF(" - Image %d : completed at cycle %d\n", image , date[image]) }
365
366    giet_pthread_exit( "main completed" );
367   
368} // end main()
369
Note: See TracBrowser for help on using the repository browser.