source: soft/giet_vm/giet_libs/mwmr_channel.c @ 735

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

Introduce two new arguments "cluster_xy" and "coproc_type"
in the system calls related to hardware coprocessors.

  • Property svn:executable set to *
File size: 18.6 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : mwmr_channel.c         
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include "mwmr_channel.h"
9#include "giet_config.h"
10#include "stdio.h"
11#include "stdint.h"
12#include "user_lock.h"
13
14// macro to use a shared TTY
15#define PRINTF(...)    lock_acquire( &tty_lock ); \
16                       giet_tty_printf(__VA_ARGS__);  \
17                       lock_release( &tty_lock );
18extern user_lock_t tty_lock;
19
20//////////////////////////////////////
21void mwmr_init( mwmr_channel_t*  mwmr,
22                uint32_t*        buffer,     // buffer base address
23                uint32_t         width,      // number of words per item
24                uint32_t         nitems )    // max number of items
25{
26
27#if GIET_DEBUG_USER_MWMR
28uint32_t    x;
29uint32_t    y;
30uint32_t    lpid;
31giet_proc_xyp( &x, &y, &lpid );
32giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] initialises mwmr channel %x"
33                "\n buffer = %x / width = %d / nitems = %d\n",
34                x, y, lpid, (uint32_t)mwmr, (uint32_t)buffer, width, nitems );
35#endif
36
37    mwmr->ptw   = 0;
38    mwmr->ptr   = 0;
39    mwmr->sts   = 0;
40    mwmr->width = width;
41    mwmr->depth = width * nitems;
42    mwmr->data  = buffer;
43
44    lock_init( &mwmr->lock );
45}
46
47
48///////////////////////////////////////
49void mwmr_dump( mwmr_channel_t*  mwmr )
50{
51    // get the lock
52    lock_acquire( &mwmr->lock );
53
54    giet_tty_printf("\n[DEBUG MWMR] &fifo = %x / width = %d / depth = %d"
55                    "\n             sts = %d / ptr = %d / ptw = %d\n",
56                    (uint32_t)mwmr, mwmr->width, mwmr->depth,
57                     mwmr->sts, mwmr->ptr, mwmr->ptw );
58    uint32_t line, word, value;
59    for ( line = 0 ; line < ((mwmr->depth)>>2) ; line++ )
60    {
61        giet_tty_printf(" line %d :  ", line );
62        for ( word = 0 ; word < 4 ; word++ )
63        {
64            value = mwmr->data[line*4+word];
65            giet_tty_printf(" %x %x %x %x",
66                            (value    ) & 0xFF,
67                            (value>>8 ) & 0xFF,
68                            (value>>16) & 0xFF,
69                            (value>>24) & 0xFF );
70        }
71        giet_tty_printf("\n");
72    }
73
74    // release the lock
75    lock_release( &mwmr->lock );
76
77}
78
79
80//////////////////////////////////////////////
81uint32_t nb_mwmr_write( mwmr_channel_t*  mwmr, 
82                        uint32_t*        buffer, 
83                        uint32_t         items)
84{
85
86#if GIET_DEBUG_USER_MWMR
87uint32_t    x;
88uint32_t    y;
89uint32_t    lpid;
90giet_proc_xyp( &x, &y, &lpid );
91#endif
92
93    uint32_t n;
94    uint32_t spaces; // number of empty slots (in words)
95    uint32_t nwords; // requested transfer length (in words)
96    uint32_t depth;  // channel depth (in words)
97    uint32_t width;  // channel width (in words)
98    uint32_t sts;    // channel sts
99    uint32_t ptw;    // channel ptw
100
101    if (items == 0) return 0;
102
103    // get the lock
104    lock_acquire( &mwmr->lock );
105
106    // access fifo status
107    depth  = mwmr->depth;
108    width  = mwmr->width;
109    sts    = mwmr->sts;
110    ptw    = mwmr->ptw;
111    spaces = depth - sts;
112    nwords = width * items;
113
114    if (spaces >= nwords) // transfer items, release lock and return
115    { 
116        for (n = 0; n < nwords; n++) 
117        {
118            mwmr->data[ptw] = buffer[n];
119            if ((ptw + 1) == depth)  ptw = 0; 
120            else                     ptw = ptw + 1;
121        }
122        mwmr->sts = mwmr->sts + nwords;
123        mwmr->ptw = ptw;
124
125#if GIET_DEBUG_USER_MWMR
126giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] nb_mwmr_write() for %d words"
127                "\n %d words written / fifo %x / sts = %d\n",
128                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
129#endif
130
131        lock_release( &mwmr->lock );
132        return items;
133    }
134    else if (spaces < width) // release lock and return
135    {
136        lock_release( &mwmr->lock );
137        return 0;
138    }
139    else // transfer as many items as possible, release lock and return
140    {
141        nwords = (spaces / width) * width;    // integer number of items
142        for (n = 0; n < nwords; n++) 
143        {
144            mwmr->data[ptw] = buffer[n];
145            if ((ptw + 1) == depth) ptw = 0;
146            else                    ptw = ptw + 1;
147        }
148        mwmr->sts = sts + nwords;
149        mwmr->ptw = ptw;
150
151#if GIET_DEBUG_USER_MWMR
152giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] nb_mwmr_write() for %d words"
153                "\n %d words written / fifo %x / sts = %d\n",
154                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
155#endif
156
157        lock_release( &mwmr->lock );
158        return (nwords / width);
159    }
160} // end nb_mwmr_write()
161
162
163
164//////////////////////////////////////////////////
165uint32_t nb_mwmr_read( mwmr_channel_t*  mwmr, 
166                       uint32_t*        buffer,
167                       uint32_t         items) 
168{
169
170#if GIET_DEBUG_USER_MWMR
171uint32_t    x;
172uint32_t    y;
173uint32_t    lpid;
174giet_proc_xyp( &x, &y, &lpid );
175#endif
176
177    uint32_t n;
178    uint32_t nwords; // requested transfer length (words)
179    uint32_t depth;  // channel depth (words)
180    uint32_t width;  // channel width (words)
181    uint32_t sts;    // channel sts   (words)
182    uint32_t ptr;    // channel ptr   (words)
183
184    if (items == 0) return 0;
185
186    // get the lock
187    lock_acquire( &mwmr->lock );
188
189    // access fifo status
190    depth  = mwmr->depth;
191    width  = mwmr->width;
192    sts    = mwmr->sts;
193    ptr    = mwmr->ptr;
194    nwords = width * items;
195
196    if (sts >= nwords) // transfer items, release lock and return
197    {
198        for (n = 0; n < nwords; n++) 
199        {
200            buffer[n] = mwmr->data[ptr];
201            if ((ptr + 1) == depth)  ptr = 0;
202            else                     ptr = ptr + 1;
203        }
204        mwmr->sts = mwmr->sts - nwords;
205        mwmr->ptr = ptr;
206
207#if GIET_DEBUG_USER_MWMR
208giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] nb_mwmr_read() for %d words"
209                "\n %d words read / fifo %x / sts = %d\n",
210                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
211#endif
212
213        lock_release( &mwmr->lock );
214        return items;
215    }
216    else if (sts < width) // release lock and return
217    {
218        lock_release( &mwmr->lock );
219        return 0;
220    }
221    else // transfer as many items as possible, release lock and return
222    {
223        nwords = (sts / width) * width; // integer number of items
224        for (n = 0 ; n < nwords ; n++) 
225        {
226            buffer[n] = mwmr->data[ptr];
227            if ((ptr + 1) == depth)  ptr = 0;
228            else                     ptr = ptr + 1;
229        }
230        mwmr->sts = sts - nwords;
231        mwmr->ptr = ptr;
232
233#if GIET_DEBUG_USER_MWMR
234giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] nb_mwmr_read() for %d words"
235                "\n %d words read / fifo %x / sts = %d\n",
236                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
237#endif
238
239        lock_release( &mwmr->lock );
240        return (nwords / width);
241    }
242} // nb_mwmr_read()
243
244
245
246////////////////////////////////////////
247void mwmr_write( mwmr_channel_t*  mwmr, 
248                 uint32_t *       buffer, 
249                 uint32_t         items ) 
250{
251
252#if GIET_DEBUG_USER_MWMR
253uint32_t    x;
254uint32_t    y;
255uint32_t    lpid;
256giet_proc_xyp( &x, &y, &lpid );
257#endif
258
259    uint32_t          n;
260    uint32_t          spaces; // number of empty slots (in words)
261    uint32_t          nwords; // requested transfer length (in words)
262    uint32_t          depth;  // channel depth (in words)
263    uint32_t          width;  // channel width (in words)
264    volatile uint32_t sts;    // channel status
265    volatile uint32_t ptw;    // channel ptw
266
267    if (items == 0)  return;
268
269    while (1) 
270    {
271        // get the lock
272        lock_acquire( &mwmr->lock );
273
274        // compute spaces and nwords
275        depth = mwmr->depth;
276        width = mwmr->width;
277        sts  = mwmr->sts;
278        ptw  = mwmr->ptw;
279        spaces = depth - sts;
280        nwords = width * items;
281
282        if (spaces >= nwords) // write nwords, release lock and return
283        {
284            for (n = 0; n < nwords; n++) 
285            {
286                mwmr->data[ptw] = buffer[n];
287                if ((ptw + 1) == depth)  ptw = 0; 
288                else                     ptw = ptw + 1;
289            }
290            mwmr->ptw = ptw;
291            mwmr->sts = sts + nwords;
292
293#if GIET_DEBUG_USER_MWMR
294giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] mwmr_write() for %d words"
295                "\n %d words written / fifo %x / sts = %d\n",
296                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
297#endif
298
299            lock_release( &mwmr->lock );
300
301            return;
302        }
303        else if (spaces < width) // release lock and retry           
304        {
305            lock_release( &mwmr->lock );
306        }
307        else // write as many items as possible, release lock and retry
308        {
309            nwords = (spaces / width) * width;  // integer number of items
310            for (n = 0; n < nwords; n++) 
311            {
312                mwmr->data[ptw] = buffer[n];
313                if ((ptw + 1) == depth)  ptw = 0; 
314                else                     ptw = ptw + 1;
315            }
316            mwmr->sts = sts + nwords;
317            mwmr->ptw = ptw;
318            buffer = buffer + nwords;
319            items = items - (nwords/width);
320
321#if GIET_DEBUG_USER_MWMR
322giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] mwmr_write() for %d words"
323                "\n %d words written / fifo %x / sts = %d\n",
324                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
325#endif
326
327            lock_release( &mwmr->lock );
328        }
329
330        // deschedule before retry
331        giet_pthread_yield();
332    }
333} // end mwmr_write()
334
335
336//////////////////////////////////////
337void mwmr_read( mwmr_channel_t*  mwmr, 
338                uint32_t*        buffer, 
339                uint32_t         items) 
340{
341
342#if GIET_DEBUG_USER_MWMR
343uint32_t    x;
344uint32_t    y;
345uint32_t    lpid;
346giet_proc_xyp( &x, &y, &lpid );
347#endif
348
349    uint32_t n;
350    uint32_t          nwords; // requested transfer length (in words)
351    uint32_t          depth;  // channel depth (in words)
352    uint32_t          width;  // channel width (in words)
353    volatile uint32_t sts;    // channel status
354    volatile uint32_t ptr;    // channel ptr
355
356    if (items == 0) return;
357
358    while (1) 
359    {
360        // get the lock
361        lock_acquire( &mwmr->lock );
362
363        // compute nwords
364        depth  = mwmr->depth;
365        width  = mwmr->width;
366        sts    = mwmr->sts;
367        ptr    = mwmr->ptr;
368        nwords = width * items;
369
370        if (sts >= nwords) // read nwords, release lock and return
371        {
372            for (n = 0; n < nwords; n++) 
373            {
374                buffer[n] = mwmr->data[ptr];
375                if ((ptr + 1) == depth)  ptr = 0;
376                else                     ptr = ptr + 1;
377            }
378            mwmr->sts = mwmr->sts - nwords;
379            mwmr->ptr = ptr;
380
381#if GIET_DEBUG_USER_MWMR
382giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] mwmr_read() for %d words"
383                "\n %d words read / fifo %x / sts = %d\n",
384                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
385#endif
386
387            lock_release( &mwmr->lock );
388
389            return;
390        }
391        else if (sts < width) // release lock and retry
392        {
393            lock_release( &mwmr->lock );
394        }
395        else // read as many items as possible, release lock and retry
396        {   
397            nwords = (sts / width) * width; // integer number of items
398            for (n = 0; n < nwords; n++) 
399            {
400                buffer[n] = mwmr->data[ptr];
401                if ((ptr + 1) == depth) ptr = 0;
402                else                    ptr = ptr + 1;
403            }
404            mwmr->sts = sts - nwords;
405            mwmr->ptr = ptr;
406            buffer = buffer + nwords;
407            items = items - (nwords/width);
408
409#if GIET_DEBUG_USER_MWMR
410giet_tty_printf("\n[DEBUG MWMR] P[%d,%d,%d] mwmr_read() for %d words"
411                "\n %d words read / fifo %x / sts = %d\n",
412                x, y, lpid, items*width , nwords, (uint32_t)mwmr, mwmr->sts );
413#endif
414
415            lock_release( &mwmr->lock );
416        }
417
418        // deschedule before retry
419        giet_pthread_yield();
420    }
421} // end mwmr_read()
422
423
424
425
426
427
428
429
430/////////////////////////////////////////////
431void mwmr_bufio_init( mwmr_bufio_t*    bufio,       
432                      uint8_t*         buffer, 
433                      uint32_t         size,       // number of bytes
434                      uint32_t         is_input,
435                      mwmr_channel_t*  mwmr )
436{
437    uint32_t bytes_per_item = (mwmr->width)<<2;
438
439    giet_pthread_assert( ((size % bytes_per_item) == 0) ,
440    "ERROR in mwmr_bufio_init() : BUFIO size must be multiple of MWMR item size\n"); 
441
442    bufio->mwmr     = mwmr;
443    bufio->is_input = is_input;
444    bufio->base     = buffer;
445    bufio->ptr      = 0;
446    bufio->max      = 0;
447    bufio->nitems   = size / bytes_per_item; 
448    bufio->nbytes   = size;
449}  // end mwmr_bufio_init()
450
451////////////////////////////////////////////
452void mwmr_bufio_dump( mwmr_bufio_t*  bufio )
453{
454    giet_tty_printf("\n[DEBUG MWMR] &bufio = %x / &mwmr = %x / &buffer = %x"
455                    "\n             is_input = %d / nbytes = %d / ptr = %d / max = %d\n",
456                    bufio , bufio->mwmr , bufio->base,
457                    bufio->is_input , bufio->nbytes , bufio->ptr , bufio->max );
458    uint32_t i = 0;
459    while ( i < bufio->nbytes )
460    {
461        giet_tty_printf(" %x", bufio->base[i] );
462        if ( (i & 0xF) == 0xF ) giet_tty_printf("\n");
463        i++;
464    }
465    giet_tty_printf("\n");
466}  // end mwmr_bufio_dump()
467   
468////////////////////////////////////////////////////
469uint8_t mwmr_bufio_read_byte( mwmr_bufio_t*  bufio )
470{
471    giet_pthread_assert( ( bufio->is_input ) ,
472    "ERROR in mwmr_bufio_read_byte() : bufio not input\n"); 
473
474    uint8_t ret;
475
476    if ( bufio->ptr == 0 )  // refill
477    {
478        uint32_t items;
479        do
480        {
481            items = nb_mwmr_read( bufio->mwmr , (uint32_t*)bufio->base , bufio->nitems );
482
483            // deschedule if channel empty
484            if (items == 0 ) giet_pthread_yield();
485        } 
486        while ( items == 0 );
487        bufio->max = items * ((bufio->mwmr->width)<<2);
488
489#if GIET_DEBUG_USER_MWMR
490giet_tty_printf("\n[DEBUG MWMR] mwmr_bufio_read_byte() read %d bytes from mwmr\n",
491                bufio->max );
492uint32_t i = 0;
493while ( i < bufio->max )
494{
495    giet_tty_printf(" %x", bufio->base[i] );
496    if ( (i & 0xF) == 0xF ) giet_tty_printf("\n");
497    i++;
498}
499giet_tty_printf("\n");
500#endif
501
502    }
503
504    ret = bufio->base[bufio->ptr];
505    bufio->ptr++;
506    if ( bufio->ptr == bufio->max ) bufio->ptr = 0;
507    return ret;
508
509}  // end mwmr_bufio_read_byte()
510
511///////////////////////////////////////////
512void mwmr_bufio_skip( mwmr_bufio_t*  bufio,
513                      uint32_t       length )
514{
515    giet_pthread_assert( ( bufio->is_input ) ,
516    "ERROR in mwmr_bufio_skip() : bufio not input\n"); 
517
518    while ( length )
519    {
520        if ( bufio->ptr == 0 )  // refill
521        {
522            uint32_t items;
523            do
524            {
525                items = nb_mwmr_read( bufio->mwmr , (uint32_t*)bufio->base , bufio->nitems );
526
527                // deschedule if channel empty
528                if (items == 0 ) giet_pthread_yield();
529            } 
530            while ( items == 0 );
531            bufio->max = items * ((bufio->mwmr->width)<<2);
532
533#if GIET_DEBUG_USER_MWMR
534giet_tty_printf("\n[DEBUG MWMR] mwmr_bufio_skip() read %d bytes from mwmr\n",
535                bufio->max );
536uint32_t i = 0;
537while ( i < bufio->max )
538{
539    giet_tty_printf(" %x", bufio->base[i] );
540    if ( (i & 0xF) == 0xF ) giet_tty_printf("\n");
541    i++;
542}
543giet_tty_printf("\n");
544#endif
545
546        }
547
548        bufio->ptr++;
549        if ( bufio->ptr == bufio->max ) bufio->ptr = 0;
550        length--;
551    }
552}  // end mwmr_bufio_skip()
553                     
554/////////////////////////////////////////////
555void mwmr_bufio_align( mwmr_bufio_t*  bufio )
556{
557    giet_pthread_assert( ( bufio->is_input ) ,
558    "ERROR in mwmr_bufio_align() : bufio not input\n");
559
560    uint32_t bytes_per_item = (bufio->mwmr->width)<<2;
561    uint32_t offset = bufio->ptr % bytes_per_item;
562
563    // align ptr on next item boundary if required
564    if ( offset )
565    {
566        bufio->ptr = bufio->ptr + bytes_per_item - offset;
567        if ( bufio-> ptr == bufio->max ) bufio->ptr = 0;
568    }
569}  // end mwmr_bufio_align()
570
571
572/////////////////////////////////////////////////
573void mwmr_bufio_write_byte( mwmr_bufio_t*  bufio,
574                            uint8_t        value )
575{
576    giet_pthread_assert( ( !bufio->is_input ) ,
577    "ERROR in mwmr_bufio_write_byte() : bufio not output\n"); 
578
579    bufio->base[bufio->ptr] = value;
580
581    bufio->ptr++;
582    if ( bufio->ptr == bufio->nbytes )  // flush bufio
583    {
584        // move data to mwmr channel
585        mwmr_write( bufio->mwmr , (uint32_t*)bufio->base , bufio->nitems );
586
587        // reinitialise bufio
588        bufio->ptr = 0;
589
590#if GIET_DEBUG_USER_MWMR
591giet_tty_printf("\n[DEBUG MWMR] mwmr_bufio_write_byte() write %d bytes to mwmr\n", 
592                bufio->nbytes );
593uint32_t i = 0;
594while ( i < bufio->nbytes )
595{
596    giet_tty_printf(" %x", bufio->base[i] );
597    if ( (i & 0xF) == 0xF ) giet_tty_printf("\n");
598    i++;
599}
600giet_tty_printf("\n");
601#endif
602    }
603}  // end mwmr_bufio_write_byte()
604
605/////////////////////////////////////////////
606void mwmr_bufio_flush( mwmr_bufio_t*  bufio )
607{
608    giet_pthread_assert( ( !bufio->is_input ) ,
609    "ERROR in mwmr_bufio_flush() : bufio not output\n"); 
610
611    uint32_t i;
612
613    uint32_t bytes_per_item = (bufio->mwmr->width)<<2;
614
615    // do nothing if bufio empty
616    if ( bufio->ptr == 0 ) return;
617   
618    // compute number of items and extra bytes to be moved to MWMR channel
619    uint32_t nitems = bufio->ptr / bytes_per_item;
620    uint32_t offset = bufio->ptr % bytes_per_item; 
621
622    // completes last item with 0 if required
623    if ( offset )
624    { 
625        for( i = bufio->ptr;
626             i < bufio->ptr + bytes_per_item - offset ; 
627             i++ ) bufio->base[i] = 0;
628
629        nitems++;
630    }
631
632#if GIET_DEBUG_USER_MWMR
633giet_tty_printf("\n[DEBUG MWMR] mwmr_bufio_flush() write %d bytes to mwmr\n", 
634                nitems * bytes_per_item );
635uint32_t j = 0;
636while ( j < (nitems * bytes_per_item) )
637{
638    giet_tty_printf(" %x", bufio->base[j] );
639    if ( (j & 0xF) == 0xF ) giet_tty_printf("\n");
640    j++;
641}
642giet_tty_printf("\n");
643#endif
644
645    // move nitems to mwmr channel
646    mwmr_write( bufio->mwmr , (uint32_t*)bufio->base , nitems );
647
648    // reinitialise bufio
649    bufio->ptr = 0;
650
651}  // end mwmr_bufio_flush()
652
653
654   
655// Local Variables:
656// tab-width: 4
657// c-basic-offset: 4
658// c-file-offsets:((innamespace . 0)(inline-open . 0))
659// indent-tabs-mode: nil
660// End:
661// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
662
Note: See TracBrowser for help on using the repository browser.