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

Last change on this file since 814 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
RevLine 
[258]1//////////////////////////////////////////////////////////////////////////////////
[450]2// File     : mwmr_channel.c         
[258]3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
[461]8#include "mwmr_channel.h"
9#include "giet_config.h"
10#include "stdio.h"
[722]11#include "stdint.h"
[461]12#include "user_lock.h"
[258]13
[735]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
[450]20//////////////////////////////////////
21void mwmr_init( mwmr_channel_t*  mwmr,
[722]22                uint32_t*        buffer,     // buffer base address
23                uint32_t         width,      // number of words per item
24                uint32_t         nitems )    // max number of items
[450]25{
26
[468]27#if GIET_DEBUG_USER_MWMR
[722]28uint32_t    x;
29uint32_t    y;
30uint32_t    lpid;
[461]31giet_proc_xyp( &x, &y, &lpid );
[722]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 );
[461]35#endif
36
[450]37    mwmr->ptw   = 0;
38    mwmr->ptr   = 0;
39    mwmr->sts   = 0;
40    mwmr->width = width;
[461]41    mwmr->depth = width * nitems;
42    mwmr->data  = buffer;
[450]43
[461]44    lock_init( &mwmr->lock );
[450]45}
46
47
[722]48///////////////////////////////////////
49void mwmr_dump( mwmr_channel_t*  mwmr )
[450]50{
[722]51    // get the lock
52    lock_acquire( &mwmr->lock );
[258]53
[722]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
[468]86#if GIET_DEBUG_USER_MWMR
[722]87uint32_t    x;
88uint32_t    y;
89uint32_t    lpid;
[461]90giet_proc_xyp( &x, &y, &lpid );
91#endif
[258]92
[722]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
[258]100
[461]101    if (items == 0) return 0;
[258]102
103    // get the lock
[461]104    lock_acquire( &mwmr->lock );
[258]105
106    // access fifo status
[461]107    depth  = mwmr->depth;
108    width  = mwmr->width;
109    sts    = mwmr->sts;
110    ptw    = mwmr->ptw;
[258]111    spaces = depth - sts;
[461]112    nwords = width * items;
[258]113
[461]114    if (spaces >= nwords) // transfer items, release lock and return
[450]115    { 
[461]116        for (n = 0; n < nwords; n++) 
[450]117        {
[461]118            mwmr->data[ptw] = buffer[n];
[450]119            if ((ptw + 1) == depth)  ptw = 0; 
120            else                     ptw = ptw + 1;
[258]121        }
122        mwmr->sts = mwmr->sts + nwords;
123        mwmr->ptw = ptw;
[461]124
[468]125#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]129#endif
130
131        lock_release( &mwmr->lock );
132        return items;
[258]133    }
[450]134    else if (spaces < width) // release lock and return
135    {
[461]136        lock_release( &mwmr->lock );
[258]137        return 0;
138    }
[450]139    else // transfer as many items as possible, release lock and return
140    {
[258]141        nwords = (spaces / width) * width;    // integer number of items
[461]142        for (n = 0; n < nwords; n++) 
[450]143        {
[461]144            mwmr->data[ptw] = buffer[n];
[450]145            if ((ptw + 1) == depth) ptw = 0;
146            else                    ptw = ptw + 1;
[258]147        }
148        mwmr->sts = sts + nwords;
149        mwmr->ptw = ptw;
[461]150
[468]151#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]155#endif
156
157        lock_release( &mwmr->lock );
[258]158        return (nwords / width);
159    }
160} // end nb_mwmr_write()
161
162
[450]163
164//////////////////////////////////////////////////
[722]165uint32_t nb_mwmr_read( mwmr_channel_t*  mwmr, 
166                       uint32_t*        buffer,
167                       uint32_t         items) 
[450]168{
169
[468]170#if GIET_DEBUG_USER_MWMR
[722]171uint32_t    x;
172uint32_t    y;
173uint32_t    lpid;
[461]174giet_proc_xyp( &x, &y, &lpid );
175#endif
[450]176
[722]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)
[461]183
184    if (items == 0) return 0;
185
[450]186    // get the lock
[461]187    lock_acquire( &mwmr->lock );
[450]188
189    // access fifo status
[461]190    depth  = mwmr->depth;
191    width  = mwmr->width;
192    sts    = mwmr->sts;
193    ptr    = mwmr->ptr;
194    nwords = width * items;
[450]195
[461]196    if (sts >= nwords) // transfer items, release lock and return
[450]197    {
[461]198        for (n = 0; n < nwords; n++) 
[450]199        {
[461]200            buffer[n] = mwmr->data[ptr];
[450]201            if ((ptr + 1) == depth)  ptr = 0;
202            else                     ptr = ptr + 1;
203        }
204        mwmr->sts = mwmr->sts - nwords;
205        mwmr->ptr = ptr;
[461]206
[468]207#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]211#endif
212
213        lock_release( &mwmr->lock );
214        return items;
[450]215    }
216    else if (sts < width) // release lock and return
217    {
[461]218        lock_release( &mwmr->lock );
[450]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
[461]224        for (n = 0 ; n < nwords ; n++) 
[450]225        {
[461]226            buffer[n] = mwmr->data[ptr];
[450]227            if ((ptr + 1) == depth)  ptr = 0;
228            else                     ptr = ptr + 1;
229        }
230        mwmr->sts = sts - nwords;
231        mwmr->ptr = ptr;
[461]232
[468]233#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]237#endif
238
239        lock_release( &mwmr->lock );
[450]240        return (nwords / width);
241    }
242} // nb_mwmr_read()
243
244
245
246////////////////////////////////////////
[722]247void mwmr_write( mwmr_channel_t*  mwmr, 
248                 uint32_t *       buffer, 
249                 uint32_t         items ) 
[450]250{
[461]251
[468]252#if GIET_DEBUG_USER_MWMR
[722]253uint32_t    x;
254uint32_t    y;
255uint32_t    lpid;
[461]256giet_proc_xyp( &x, &y, &lpid );
257#endif
258
[735]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
[258]266
[461]267    if (items == 0)  return;
[258]268
[450]269    while (1) 
270    {
[258]271        // get the lock
[461]272        lock_acquire( &mwmr->lock );
[258]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;
[461]280        nwords = width * items;
[258]281
[450]282        if (spaces >= nwords) // write nwords, release lock and return
283        {
[461]284            for (n = 0; n < nwords; n++) 
[450]285            {
[461]286                mwmr->data[ptw] = buffer[n];
[450]287                if ((ptw + 1) == depth)  ptw = 0; 
288                else                     ptw = ptw + 1;
[258]289            }
290            mwmr->ptw = ptw;
291            mwmr->sts = sts + nwords;
[461]292
[468]293#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]297#endif
298
299            lock_release( &mwmr->lock );
[735]300
[258]301            return;
302        }
[461]303        else if (spaces < width) // release lock and retry           
[450]304        {
[461]305            lock_release( &mwmr->lock );
[258]306        }
[461]307        else // write as many items as possible, release lock and retry
[450]308        {
[258]309            nwords = (spaces / width) * width;  // integer number of items
[461]310            for (n = 0; n < nwords; n++) 
[450]311            {
[461]312                mwmr->data[ptw] = buffer[n];
[450]313                if ((ptw + 1) == depth)  ptw = 0; 
314                else                     ptw = ptw + 1;
[258]315            }
316            mwmr->sts = sts + nwords;
317            mwmr->ptw = ptw;
318            buffer = buffer + nwords;
[461]319            items = items - (nwords/width);
320
[468]321#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]325#endif
326
327            lock_release( &mwmr->lock );
[258]328        }
[461]329
[731]330        // deschedule before retry
331        giet_pthread_yield();
[258]332    }
333} // end mwmr_write()
334
335
[450]336//////////////////////////////////////
[722]337void mwmr_read( mwmr_channel_t*  mwmr, 
338                uint32_t*        buffer, 
339                uint32_t         items) 
[450]340{
[461]341
[468]342#if GIET_DEBUG_USER_MWMR
[722]343uint32_t    x;
344uint32_t    y;
345uint32_t    lpid;
[461]346giet_proc_xyp( &x, &y, &lpid );
347#endif
348
[722]349    uint32_t n;
[735]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
[258]355
[461]356    if (items == 0) return;
[258]357
[450]358    while (1) 
359    {
[258]360        // get the lock
[461]361        lock_acquire( &mwmr->lock );
[258]362
363        // compute nwords
[461]364        depth  = mwmr->depth;
365        width  = mwmr->width;
366        sts    = mwmr->sts;
367        ptr    = mwmr->ptr;
368        nwords = width * items;
[258]369
[450]370        if (sts >= nwords) // read nwords, release lock and return
371        {
[461]372            for (n = 0; n < nwords; n++) 
[450]373            {
[461]374                buffer[n] = mwmr->data[ptr];
[450]375                if ((ptr + 1) == depth)  ptr = 0;
376                else                     ptr = ptr + 1;
[258]377            }
378            mwmr->sts = mwmr->sts - nwords;
379            mwmr->ptr = ptr;
[461]380
[468]381#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]385#endif
386
387            lock_release( &mwmr->lock );
[735]388
[258]389            return;
390        }
[461]391        else if (sts < width) // release lock and retry
[450]392        {
[461]393            lock_release( &mwmr->lock );
[258]394        }
[461]395        else // read as many items as possible, release lock and retry
[450]396        {   
[258]397            nwords = (sts / width) * width; // integer number of items
[461]398            for (n = 0; n < nwords; n++) 
[450]399            {
[461]400                buffer[n] = mwmr->data[ptr];
[450]401                if ((ptr + 1) == depth) ptr = 0;
402                else                    ptr = ptr + 1;
[258]403            }
404            mwmr->sts = sts - nwords;
405            mwmr->ptr = ptr;
406            buffer = buffer + nwords;
[461]407            items = items - (nwords/width);
408
[468]409#if GIET_DEBUG_USER_MWMR
[722]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 );
[461]413#endif
414
415            lock_release( &mwmr->lock );
[258]416        }
[461]417
[731]418        // deschedule before retry
419        giet_pthread_yield();
[258]420    }
421} // end mwmr_read()
422
423
[722]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 );
[731]482
483            // deschedule if channel empty
484            if (items == 0 ) giet_pthread_yield();
[722]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 );
[731]526
527                // deschedule if channel empty
528                if (items == 0 ) giet_pthread_yield();
[722]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   
[258]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.