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

Last change on this file since 454 was 450, checked in by alain, 10 years ago

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.

  • Property svn:executable set to *
File size: 9.7 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 <stdio.h>
10
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;
41    asm volatile (
42            "1:                               \n"
43            "ll   $2,    0(%0)                \n" /* $2 <= lock current value */
44            "bnez $2,    2f                   \n" /* retry after delay if lock busy */
45            "li   $3,    1                    \n" /* $3 <= argument for sc */
46            "sc   $3,    0(%0)                \n" /* try to get lock */
47            "bnez $3,    3f                   \n" /* exit if atomic */
48            "2:                               \n"
49            "move $4,    %1                   \n" /* $4 <= delay */
50            "4:                               \n"
51            "beqz $4,    4b                   \n" /* test end delay */
52            "addi $4,    $4,  -1              \n" /* $4 <= $4 - 1 */
53            "j           1b                   \n" /* retry ll */
54            "nop                              \n"
55            "3:                               \n"
56            :
57            :"r"(plock), "r"(delay)
58            :"$2", "$3", "$4");
59} 
60
61
62///////////////////////////////////////////////////
63unsigned int nb_mwmr_write( mwmr_channel_t * mwmr, 
64                            unsigned int * buffer, 
65                            unsigned int nitems)
66{
67    unsigned int x;
68    unsigned int spaces; // number of empty slots (in words)
69    unsigned int nwords; // requested transfer length (in words)
70    unsigned int depth;  // channel depth (in words)
71    unsigned int width;  // channel width (in words)
72    unsigned int sts;    // channel sts
73    unsigned int ptw;    // channel ptw
74
75    if (nitems == 0) return 0;
76
77    // get the lock
78    mwmr_lock_acquire(&mwmr->lock);
79
80    // access fifo status
81    depth = mwmr->depth;
82    width = mwmr->width;
83    sts = mwmr->sts;
84    ptw = mwmr->ptw;
85    spaces = depth - sts;
86    nwords = width * nitems;
87
88    if (spaces >= nwords) // transfer nitems, release lock and return
89    { 
90        for (x = 0; x < nwords; x++) 
91        {
92            mwmr->data[ptw] = buffer[x];
93            if ((ptw + 1) == depth)  ptw = 0; 
94            else                     ptw = ptw + 1;
95        }
96        mwmr->sts = mwmr->sts + nwords;
97        mwmr->ptw = ptw;
98        mwmr->lock = 0;
99        return nitems;
100    }
101    else if (spaces < width) // release lock and return
102    {
103        mwmr->lock = 0;
104        return 0;
105    }
106    else // transfer as many items as possible, release lock and return
107    {
108        nwords = (spaces / width) * width;    // integer number of items
109        for (x = 0; x < nwords; x++) 
110        {
111            mwmr->data[ptw] = buffer[x];
112            if ((ptw + 1) == depth) ptw = 0;
113            else                    ptw = ptw + 1;
114        }
115        mwmr->sts = sts + nwords;
116        mwmr->ptw = ptw;
117        mwmr->lock = 0;
118        return (nwords / width);
119    }
120} // end nb_mwmr_write()
121
122
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{
189    unsigned int x;
190    unsigned int spaces; // number of empty slots (in words)
191    unsigned int nwords; // requested transfer length (in words)
192    unsigned int depth;  // channel depth (in words)
193    unsigned int width;  // channel width (in words)
194    unsigned int sts;    // channel sts
195    unsigned int ptw;    // channel ptw
196
197    if (nitems == 0)  return;
198
199    while (1) 
200    {
201        // get the lock
202        mwmr_lock_acquire(&mwmr->lock);
203
204        // compute spaces and nwords
205        depth = mwmr->depth;
206        width = mwmr->width;
207        sts  = mwmr->sts;
208        ptw  = mwmr->ptw;
209        spaces = depth - sts;
210        nwords = width * nitems;
211
212        if (spaces >= nwords) // write nwords, release lock and return
213        {
214            for (x = 0; x < nwords; x++) 
215            {
216                mwmr->data[ptw] = buffer[x];
217                if ((ptw + 1) == depth)  ptw = 0; 
218                else                     ptw = ptw + 1;
219            }
220            mwmr->ptw = ptw;
221            mwmr->sts = sts + nwords;
222            mwmr->lock = 0;
223            return;
224        }
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        {
231            nwords = (spaces / width) * width;  // integer number of items
232            for (x = 0; x < nwords; x++) 
233            {
234                mwmr->data[ptw] = buffer[x];
235                if ((ptw + 1) == depth)  ptw = 0; 
236                else                     ptw = ptw + 1;
237            }
238            mwmr->sts = sts + nwords;
239            mwmr->ptw = ptw;
240            buffer = buffer + nwords;
241            nitems = nitems - (nwords/width);
242            mwmr->lock = 0;
243        }
244        giet_context_switch();
245    }
246} // end mwmr_write()
247
248
249//////////////////////////////////////
250void mwmr_read( mwmr_channel_t * mwmr, 
251                unsigned int *   buffer, 
252                unsigned int     nitems) 
253{
254    unsigned int x;
255    unsigned int nwords; // requested transfer length (in words)
256    unsigned int depth;  // channel depth (in words)
257    unsigned int width;  // channel width (in words)
258    unsigned int sts;    // channel sts
259    unsigned int ptr;    // channel ptr
260
261    if (nitems == 0) return;
262
263    while (1) 
264    {
265        // get the lock
266        mwmr_lock_acquire(&mwmr->lock);
267
268        // compute nwords
269        depth = mwmr->depth;
270        width = mwmr->width;
271        sts = mwmr->sts;
272        ptr = mwmr->ptr;
273        nwords = width * nitems;
274
275        if (sts >= nwords) // read nwords, release lock and return
276        {
277            for (x = 0; x < nwords; x++) 
278            {
279                buffer[x] = mwmr->data[ptr];
280                if ((ptr + 1) == depth)  ptr = 0;
281                else                     ptr = ptr + 1;
282            }
283            mwmr->sts = mwmr->sts - nwords;
284            mwmr->ptr = ptr;
285            mwmr->lock = 0;
286            return;
287        }
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        {   
294            nwords = (sts / width) * width; // integer number of items
295            for (x = 0; x < nwords; x++) 
296            {
297                buffer[x] = mwmr->data[ptr];
298                if ((ptr + 1) == depth) ptr = 0;
299                else                    ptr = ptr + 1;
300            }
301            mwmr->sts = sts - nwords;
302            mwmr->ptr = ptr;
303            buffer = buffer + nwords;
304            nitems = nitems - (nwords/width);
305            mwmr->lock = 0;
306        }
307        giet_context_switch();
308    }
309} // end mwmr_read()
310
311
312// Local Variables:
313// tab-width: 4
314// c-basic-offset: 4
315// c-file-offsets:((innamespace . 0)(inline-open . 0))
316// indent-tabs-mode: nil
317// End:
318// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
319
Note: See TracBrowser for help on using the repository browser.