Ignore:
Timestamp:
Nov 11, 2014, 4:18:38 PM (10 years ago)
Author:
alain
Message:

1) Introducing an explicit channel initialisation function in the MWMR library.
2) Defining new system calls in stdio.c to support user access to the NIC.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_libs/mwmr_channel.c

    r345 r450  
    11//////////////////////////////////////////////////////////////////////////////////
    2 // File     : mwmr_channel_.c         
     2// File     : mwmr_channel.c         
    33// Date     : 01/04/2012
    44// Author   : alain greiner
    55// Copyright (c) UPMC-LIP6
    66///////////////////////////////////////////////////////////////////////////////////
    7 // The mwmr_channel.c and mwmr_channel.h files are part of the GIET nano-kernel.
    8 // This  middleware implements a user level Multi-Writers / Multi-Readers
    9 // communication channel, that can be used by parallel multi-tasks applications
    10 // respecting the TCG (Tasks and Communications Graph) formalism.
    11 //
    12 // The mwmr_read() and mwmr_write() functions do not require a system call.
    13 // The channel itself must have been allocated in a non cacheable segment,
    14 // if the platform does not provide hardware cache coherence.
    15 //
    16 // ALL MWMR channels must be defined in the mapping_info data structure,
    17 // to be initialised by the GIET in the boot phase.
    18 // The vobj_get_vbase() system call (defined in stdio.c and stdio.h files)
    19 // can be used to get the virtual base address of the channel from it's name.
    20 //
    21 // An MWMR transaction transfer    an integer number of items, and an item is
    22 // an integer number of unsigned int (32 bits words).
    23 // The max number of words that can be stored in a MWMR channel is defined by the
    24 // "depth" parameter, and the "width" parameter define the minimal number of
    25 // word contained in an atomic item. Therefore, the "depth" parameter must be
    26 // a multiple of the "width" parameter.
    27 //
    28 // Both the mwmr_read() and mwmr_write() functions are blocking functions.
    29 // A private lock provides exclusive access to the MWMR channel, that can have
    30 // a variable number of producers and a variable number of consumers.
    31 ///////////////////////////////////////////////////////////////////////////////////
    327
    338#include <mwmr_channel.h>
    349#include <stdio.h>
    3510
    36 //////////////////////////////////////////////////////////////////////////////
    37 //  mwmr_lock_aquire()
    38 // This blocking function returns only when the lock has been taken.
    39 // If the lock is already taken a fixed delay is introduced before retry.
    40 //////////////////////////////////////////////////////////////////////////////
    41 void mwmr_lock_acquire(unsigned int * lock_address) {
    42     register unsigned int * plock = lock_address;
    43     register unsigned int delay = 100;
     11//////////////////////////////////////
     12void mwmr_init( mwmr_channel_t*  mwmr,
     13                unsigned int     width,      // numer of words per item
     14                unsigned int     items )     // max number of items
     15{
     16    if ( ((items * width)) > 1018 )
     17    giet_exit("[MWMR ERROR] in mwmr_init() : buffer size larger than 4072 bytes\n");
     18
     19    mwmr->ptw   = 0;
     20    mwmr->ptr   = 0;
     21    mwmr->sts   = 0;
     22    mwmr->width = width;
     23    mwmr->depth = width * items;
     24    mwmr->lock  = 0;
     25
     26#if GIET_DEBUG_MWMR
     27giet_shr_printf("[MWMR DEBUG] Initialise MWMR channel\n"
     28                " - vbase = %x\n"
     29                " - width = %d\n"
     30                " - depth = %d\n",
     31                (unsigned int)mwmr, width, items );
     32#endif
     33}
     34
     35
     36///////////////////////////////////////////////////
     37static void mwmr_lock_acquire( unsigned int* lock )
     38{
     39    register unsigned int*  plock = lock;
     40    register unsigned int   delay = 100;
    4441    asm volatile (
    4542            "1:                               \n"
     
    6360
    6461
    65 //////////////////////////////////////////////////////////////////////////////
    66 //       nb_mwmr_write()
    67 // This is a non-blocking function.
    68 // The nitems parameter is the number of items to be transfered.
    69 // The requested transfer is therefore (nitems * width) words.
    70 // It takes the lock for exclusive access before testing the channel state.
    71 // If there is not enough data in mwmr channel to read nitems,
    72 // it reads as many items as possible, releases the lock, and returns
    73 // the number of read items (it can be 0).
    74 //////////////////////////////////////////////////////////////////////////////
    75 unsigned int nb_mwmr_write(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) {
     62///////////////////////////////////////////////////
     63unsigned int nb_mwmr_write( mwmr_channel_t * mwmr,
     64                            unsigned int * buffer,
     65                            unsigned int nitems)
     66{
    7667    unsigned int x;
    7768    unsigned int spaces; // number of empty slots (in words)
     
    8273    unsigned int ptw;    // channel ptw
    8374
    84     if (nitems == 0) {
    85         return 0;
    86     }
     75    if (nitems == 0) return 0;
    8776
    8877    // get the lock
     
    9786    nwords = width * nitems;
    9887
    99     if (spaces >= nwords) { // transfer nitems, release lock and return
    100         for (x = 0; x < nwords; x++) {
     88    if (spaces >= nwords) // transfer nitems, release lock and return
     89    {
     90        for (x = 0; x < nwords; x++)
     91        {
    10192            mwmr->data[ptw] = buffer[x];
    102             if ((ptw + 1) == depth) {
    103                 ptw = 0;
    104             }
    105             else {
    106                 ptw = ptw + 1;
    107             }
     93            if ((ptw + 1) == depth)  ptw = 0;
     94            else                     ptw = ptw + 1;
    10895        }
    10996        mwmr->sts = mwmr->sts + nwords;
     
    11299        return nitems;
    113100    }
    114     else if (spaces < width) {
    115         // release lock and return
     101    else if (spaces < width) // release lock and return
     102    {
    116103        mwmr->lock = 0;
    117104        return 0;
    118105    }
    119     else {
    120         // transfer as many items as possible, release lock and return
     106    else // transfer as many items as possible, release lock and return
     107    {
    121108        nwords = (spaces / width) * width;    // integer number of items
    122         for (x = 0; x < nwords; x++) {
     109        for (x = 0; x < nwords; x++)
     110        {
    123111            mwmr->data[ptw] = buffer[x];
    124             if ((ptw + 1) == depth) {
    125                 ptw = 0;
    126             }
    127             else {
    128                 ptw = ptw + 1;
    129             }
     112            if ((ptw + 1) == depth) ptw = 0;
     113            else                    ptw = ptw + 1;
    130114        }
    131115        mwmr->sts = sts + nwords;
     
    137121
    138122
    139 //////////////////////////////////////////////////////////////////////////////
    140 //    mwmr_write()
    141 // This blocking function returns only when the transfer is completed.
    142 // The nitems parameter is the number of items to be transfered.
    143 // The requested transfer is therefore (nitems * width) words.
    144 // It takes the lock for exclusive access before testing the channel state.
    145 // If there is not enough space in mwmr channel to write nitems,
    146 // it writes as many items as possible, releases the lock, and retry
    147 // after a random delay.
    148 //////////////////////////////////////////////////////////////////////////////
    149 void mwmr_write(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) {
     123
     124//////////////////////////////////////////////////
     125unsigned int nb_mwmr_read( mwmr_channel_t * mwmr,
     126                           unsigned int *   buffer,
     127                           unsigned int     nitems)
     128{
     129    unsigned int x;
     130    unsigned int nwords; // requested transfer length (in words)
     131    unsigned int depth;  // channel depth (in words)
     132    unsigned int width;  // channel width (in words)
     133    unsigned int sts;    // channel sts
     134    unsigned int ptr;    // channel ptr
     135
     136    if (nitems == 0) return 0;
     137
     138    // get the lock
     139    mwmr_lock_acquire(&mwmr->lock);
     140
     141    // access fifo status
     142    depth = mwmr->depth;
     143    width = mwmr->width;
     144    sts = mwmr->sts;
     145    ptr = mwmr->ptr;
     146    nwords = width * nitems;
     147
     148    if (sts >= nwords) // transfer nitems, release lock and return
     149    {
     150        for (x = 0; x < nwords; x++)
     151        {
     152            buffer[x] = mwmr->data[ptr];
     153            if ((ptr + 1) == depth)  ptr = 0;
     154            else                     ptr = ptr + 1;
     155        }
     156        mwmr->sts = mwmr->sts - nwords;
     157        mwmr->ptr = ptr;
     158        mwmr->lock = 0;
     159        return nitems;
     160    }
     161    else if (sts < width) // release lock and return
     162    {
     163        mwmr->lock = 0;
     164        return 0;
     165    }
     166    else // transfer as many items as possible, release lock and return
     167    {
     168        nwords = (sts / width) * width; // integer number of items
     169        for (x = 0 ; x < nwords ; x++)
     170        {
     171            buffer[x] = mwmr->data[ptr];
     172            if ((ptr + 1) == depth)  ptr = 0;
     173            else                     ptr = ptr + 1;
     174        }
     175        mwmr->sts = sts - nwords;
     176        mwmr->ptr = ptr;
     177        mwmr->lock = 0;
     178        return (nwords / width);
     179    }
     180} // nb_mwmr_read()
     181
     182
     183
     184////////////////////////////////////////
     185void mwmr_write( mwmr_channel_t * mwmr,
     186                 unsigned int *   buffer,
     187                 unsigned int     nitems )
     188{
    150189    unsigned int x;
    151190    unsigned int spaces; // number of empty slots (in words)
     
    156195    unsigned int ptw;    // channel ptw
    157196
    158     if (nitems == 0) {
    159         return;
    160     }
    161 
    162     while (1) {
     197    if (nitems == 0)  return;
     198
     199    while (1)
     200    {
    163201        // get the lock
    164202        mwmr_lock_acquire(&mwmr->lock);
     
    172210        nwords = width * nitems;
    173211
    174         if (spaces >= nwords) {
    175             // write nwords, release lock and return
    176             for (x = 0; x < nwords; x++) {
     212        if (spaces >= nwords) // write nwords, release lock and return
     213        {
     214            for (x = 0; x < nwords; x++)
     215            {
    177216                mwmr->data[ptw] = buffer[x];
    178                 if ((ptw + 1) == depth) {
    179                     ptw = 0;
    180                 }
    181                 else {
    182                     ptw = ptw + 1;
    183                 }
     217                if ((ptw + 1) == depth)  ptw = 0;
     218                else                     ptw = ptw + 1;
    184219            }
    185220            mwmr->ptw = ptw;
     
    188223            return;
    189224        }
    190         else if (spaces < width) {
    191             // release lock and retry after delay
    192             mwmr->lock = 0;
    193         }
    194         else {
    195             // write as many items as possible, release lock and retry after delay
     225        else if (spaces < width) // release lock and deschedule           
     226        {
     227            mwmr->lock = 0;
     228        }
     229        else // write as many items as possible, release lock and deschedule
     230        {
    196231            nwords = (spaces / width) * width;  // integer number of items
    197             for (x = 0; x < nwords; x++) {
     232            for (x = 0; x < nwords; x++)
     233            {
    198234                mwmr->data[ptw] = buffer[x];
    199                 if ((ptw + 1) == depth) {
    200                     ptw = 0;
    201                 }
    202                 else {
    203                     ptw = ptw + 1;
    204                 }
     235                if ((ptw + 1) == depth)  ptw = 0;
     236                else                     ptw = ptw + 1;
    205237            }
    206238            mwmr->sts = sts + nwords;
     
    215247
    216248
    217 //////////////////////////////////////////////////////////////////////////////
    218 //       nb_mwmr_read()
    219 // This is a non-blocking function.
    220 // The nitems parameter is the number of items to be transfered.
    221 // The requested transfer is therefore (nitems * width) words.
    222 // It takes the lock for exclusive access before testing the channel state.
    223 // If there is not enough data in mwmr channel to read nitems,
    224 // it reads as many items as possible, releases the lock, and returns
    225 // the number of read items (it can be 0).
    226 //////////////////////////////////////////////////////////////////////////////
    227 unsigned int nb_mwmr_read(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) {
     249//////////////////////////////////////
     250void mwmr_read( mwmr_channel_t * mwmr,
     251                unsigned int *   buffer,
     252                unsigned int     nitems)
     253{
    228254    unsigned int x;
    229255    unsigned int nwords; // requested transfer length (in words)
     
    233259    unsigned int ptr;    // channel ptr
    234260
    235     if (nitems == 0) {
    236         return 0;
    237     }
    238 
    239     // get the lock
    240     mwmr_lock_acquire(&mwmr->lock);
    241 
    242     // access fifo status
    243     depth = mwmr->depth;
    244     width = mwmr->width;
    245     sts = mwmr->sts;
    246     ptr = mwmr->ptr;
    247     nwords = width * nitems;
    248 
    249     if (sts >= nwords) {
    250         // transfer nitems, release lock and return
    251         for (x = 0; x < nwords; x++) {
    252             buffer[x] = mwmr->data[ptr];
    253             if ((ptr + 1) == depth) {
    254                 ptr = 0;
    255             }
    256             else {
    257                 ptr = ptr + 1;
    258             }
    259         }
    260         mwmr->sts = mwmr->sts - nwords;
    261         mwmr->ptr = ptr;
    262         mwmr->lock = 0;
    263         return nitems;
    264     }
    265     else if (sts < width) {
    266         // release lock and return
    267         mwmr->lock = 0;
    268         return 0;
    269     }
    270     else {
    271         // transfer as many items as possible, release lock and return
    272         nwords = (sts / width) * width; // integer number of items
    273         for (x = 0 ; x < nwords ; x++) {
    274             buffer[x] = mwmr->data[ptr];
    275             if ((ptr + 1) == depth) {
    276                 ptr = 0;
    277             }
    278             else {
    279                 ptr = ptr + 1;
    280             }
    281         }
    282         mwmr->sts = sts - nwords;
    283         mwmr->ptr = ptr;
    284         mwmr->lock = 0;
    285         return (nwords / width);
    286     }
    287 } // nb_mwmr_read()
    288 
    289 
    290 //////////////////////////////////////////////////////////////////////////////
    291 //    mwmr_read()
    292 // This blocking function returns only when the transfer is completed.
    293 // The nitems parameter is the number of items to be transfered.
    294 // The requested transfer is therefore (nitems * width) words.
    295 // It takes the lock for exclusive access before testing the channel state.
    296 // If there is not enough data in mwmr channel to read nitems,
    297 // it reads as many items as possible, releases the lock, and retry
    298 // after a random delay.
    299 //////////////////////////////////////////////////////////////////////////////
    300 void mwmr_read( mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) {
    301     unsigned int x;
    302     unsigned int nwords; // requested transfer length (in words)
    303     unsigned int depth;  // channel depth (in words)
    304     unsigned int width;  // channel width (in words)
    305     unsigned int sts;    // channel sts
    306     unsigned int ptr;    // channel ptr
    307 
    308     if (nitems == 0) {
    309         return;
    310     }
    311 
    312     while (1) {
     261    if (nitems == 0) return;
     262
     263    while (1)
     264    {
    313265        // get the lock
    314266        mwmr_lock_acquire(&mwmr->lock);
     
    321273        nwords = width * nitems;
    322274
    323         if (sts >= nwords) {
    324             // read nwords, release lock and return
    325             for (x = 0; x < nwords; x++) {
     275        if (sts >= nwords) // read nwords, release lock and return
     276        {
     277            for (x = 0; x < nwords; x++)
     278            {
    326279                buffer[x] = mwmr->data[ptr];
    327                 if ((ptr + 1) == depth) {
    328                     ptr = 0;
    329                 }
    330                 else {
    331                     ptr = ptr + 1;
    332                 }
     280                if ((ptr + 1) == depth)  ptr = 0;
     281                else                     ptr = ptr + 1;
    333282            }
    334283            mwmr->sts = mwmr->sts - nwords;
     
    337286            return;
    338287        }
    339         else if (sts < width) {
    340             // release lock and retry after delay
    341             mwmr->lock = 0;
    342         }
    343         else {   // read as many items as possible, release lock and retry after delay
     288        else if (sts < width) // release lock and deschedule
     289        {
     290            mwmr->lock = 0;
     291        }
     292        else // read as many items as possible, release lock and deschedule
     293        {   
    344294            nwords = (sts / width) * width; // integer number of items
    345             for (x = 0; x < nwords; x++) {
     295            for (x = 0; x < nwords; x++)
     296            {
    346297                buffer[x] = mwmr->data[ptr];
    347                 if ((ptr + 1) == depth) {
    348                     ptr = 0;
    349                 }
    350                 else {
    351                     ptr = ptr + 1;
    352                 }
     298                if ((ptr + 1) == depth) ptr = 0;
     299                else                    ptr = ptr + 1;
    353300            }
    354301            mwmr->sts = sts - nwords;
Note: See TracChangeset for help on using the changeset viewer.