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

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

1) introduce the stdint.h file to define uint*_t and int*_t types.
2) introduce the bufio service in the mwmr library.
3) modify the fbf_cma system calls to support chbuf containing more than 2 buffers.

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