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

Last change on this file since 464 was 461, checked in by alain, 10 years ago

1) replace the "giet_locks.c" library by the "user_lock.c" library (the new library uses a ticket allocator).
2) introduce new syscalls in the stdio.c file, to support the NIC peripheral.
3) modify the MWMR library to use the lock with ticket allocator, and to separate the fifo descriptor and the data buffer.

  • Property svn:executable set to *
File size: 11.0 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 "user_lock.h"
12
13//////////////////////////////////////
14void mwmr_init( mwmr_channel_t*  mwmr,
15                unsigned int*    buffer,     // buffer base address
16                unsigned int     width,      // number of words per item
17                unsigned int     nitems )    // max number of items
18{
19
20#if GIET_DEBUG_MWMR
21unsigned int    x;
22unsigned int    y;
23unsigned int    lpid;
24giet_proc_xyp( &x, &y, &lpid );
25giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] initialises fifo %x / "
26                " buffer = %x / width = %d / nitems = %d\n",
27                x, y, lpid, (unsigned int)mwmr, (unsigned int)buffer, width, nitems );
28#endif
29
30    mwmr->ptw   = 0;
31    mwmr->ptr   = 0;
32    mwmr->sts   = 0;
33    mwmr->width = width;
34    mwmr->depth = width * nitems;
35    mwmr->data  = buffer;
36
37    lock_init( &mwmr->lock );
38}
39
40
41///////////////////////////////////////////////////
42unsigned int nb_mwmr_write( mwmr_channel_t * mwmr, 
43                            unsigned int *   buffer, 
44                            unsigned int     items)
45{
46
47#if GIET_DEBUG_MWMR
48unsigned int    x;
49unsigned int    y;
50unsigned int    lpid;
51giet_proc_xyp( &x, &y, &lpid );
52#endif
53
54    unsigned int n;
55    unsigned int spaces; // number of empty slots (in words)
56    unsigned int nwords; // requested transfer length (in words)
57    unsigned int depth;  // channel depth (in words)
58    unsigned int width;  // channel width (in words)
59    unsigned int sts;    // channel sts
60    unsigned int ptw;    // channel ptw
61
62    if (items == 0) return 0;
63
64    // get the lock
65    lock_acquire( &mwmr->lock );
66
67    // access fifo status
68    depth  = mwmr->depth;
69    width  = mwmr->width;
70    sts    = mwmr->sts;
71    ptw    = mwmr->ptw;
72    spaces = depth - sts;
73    nwords = width * items;
74
75    if (spaces >= nwords) // transfer items, release lock and return
76    { 
77        for (n = 0; n < nwords; n++) 
78        {
79            mwmr->data[ptw] = buffer[n];
80            if ((ptw + 1) == depth)  ptw = 0; 
81            else                     ptw = ptw + 1;
82        }
83        mwmr->sts = mwmr->sts + nwords;
84        mwmr->ptw = ptw;
85
86#if GIET_DEBUG_MWMR
87giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] writes %d words in fifo %x : sts = %d\n",
88                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
89#endif
90
91        lock_release( &mwmr->lock );
92        return items;
93    }
94    else if (spaces < width) // release lock and return
95    {
96        lock_release( &mwmr->lock );
97        return 0;
98    }
99    else // transfer as many items as possible, release lock and return
100    {
101        nwords = (spaces / width) * width;    // integer number of items
102        for (n = 0; n < nwords; n++) 
103        {
104            mwmr->data[ptw] = buffer[n];
105            if ((ptw + 1) == depth) ptw = 0;
106            else                    ptw = ptw + 1;
107        }
108        mwmr->sts = sts + nwords;
109        mwmr->ptw = ptw;
110
111#if GIET_DEBUG_MWMR
112giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] writes %d words in fifo %x : sts = %d\n",
113                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
114#endif
115
116        lock_release( &mwmr->lock );
117        return (nwords / width);
118    }
119} // end nb_mwmr_write()
120
121
122
123//////////////////////////////////////////////////
124unsigned int nb_mwmr_read( mwmr_channel_t * mwmr, 
125                           unsigned int *   buffer,
126                           unsigned int     items) 
127{
128
129#if GIET_DEBUG_MWMR
130unsigned int    x;
131unsigned int    y;
132unsigned int    lpid;
133giet_proc_xyp( &x, &y, &lpid );
134#endif
135
136    unsigned int n;
137    unsigned int nwords; // requested transfer length (words)
138    unsigned int depth;  // channel depth (words)
139    unsigned int width;  // channel width (words)
140    unsigned int sts;    // channel sts   (words)
141    unsigned int ptr;    // channel ptr   (words)
142
143    if (items == 0) return 0;
144
145    // get the lock
146    lock_acquire( &mwmr->lock );
147
148    // access fifo status
149    depth  = mwmr->depth;
150    width  = mwmr->width;
151    sts    = mwmr->sts;
152    ptr    = mwmr->ptr;
153    nwords = width * items;
154
155    if (sts >= nwords) // transfer items, release lock and return
156    {
157        for (n = 0; n < nwords; n++) 
158        {
159            buffer[n] = mwmr->data[ptr];
160            if ((ptr + 1) == depth)  ptr = 0;
161            else                     ptr = ptr + 1;
162        }
163        mwmr->sts = mwmr->sts - nwords;
164        mwmr->ptr = ptr;
165
166#if GIET_DEBUG_MWMR
167giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] read %d words in fifo %x : sts = %d\n",
168                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
169#endif
170
171        lock_release( &mwmr->lock );
172        return items;
173    }
174    else if (sts < width) // release lock and return
175    {
176
177#if GIET_DEBUG_MWMR
178giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] read nothing in fifo %x : sts = %d\n",
179                x, y, lpid, (unsigned int)mwmr, mwmr->sts );
180#endif
181
182        lock_release( &mwmr->lock );
183        return 0;
184    }
185    else // transfer as many items as possible, release lock and return
186    {
187        nwords = (sts / width) * width; // integer number of items
188        for (n = 0 ; n < nwords ; n++) 
189        {
190            buffer[n] = mwmr->data[ptr];
191            if ((ptr + 1) == depth)  ptr = 0;
192            else                     ptr = ptr + 1;
193        }
194        mwmr->sts = sts - nwords;
195        mwmr->ptr = ptr;
196
197#if GIET_DEBUG_MWMR
198giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] read %d words in fifo %x : sts = %d\n",
199                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
200#endif
201
202        lock_release( &mwmr->lock );
203        return (nwords / width);
204    }
205} // nb_mwmr_read()
206
207
208
209////////////////////////////////////////
210void mwmr_write( mwmr_channel_t * mwmr, 
211                 unsigned int *   buffer, 
212                 unsigned int     items ) 
213{
214
215#if GIET_DEBUG_MWMR
216unsigned int    x;
217unsigned int    y;
218unsigned int    lpid;
219giet_proc_xyp( &x, &y, &lpid );
220#endif
221
222    unsigned int n;
223    unsigned int spaces; // number of empty slots (in words)
224    unsigned int nwords; // requested transfer length (in words)
225    unsigned int depth;  // channel depth (in words)
226    unsigned int width;  // channel width (in words)
227    unsigned int sts;    // channel sts
228    unsigned int ptw;    // channel ptw
229
230    if (items == 0)  return;
231
232    while (1) 
233    {
234        // get the lock
235        lock_acquire( &mwmr->lock );
236
237        // compute spaces and nwords
238        depth = mwmr->depth;
239        width = mwmr->width;
240        sts  = mwmr->sts;
241        ptw  = mwmr->ptw;
242        spaces = depth - sts;
243        nwords = width * items;
244
245        if (spaces >= nwords) // write nwords, release lock and return
246        {
247            for (n = 0; n < nwords; n++) 
248            {
249                mwmr->data[ptw] = buffer[n];
250                if ((ptw + 1) == depth)  ptw = 0; 
251                else                     ptw = ptw + 1;
252            }
253            mwmr->ptw = ptw;
254            mwmr->sts = sts + nwords;
255
256#if GIET_DEBUG_MWMR
257giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] writes %d words in fifo %x : sts = %d\n",
258                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
259#endif
260
261            lock_release( &mwmr->lock );
262            return;
263        }
264        else if (spaces < width) // release lock and retry           
265        {
266            lock_release( &mwmr->lock );
267        }
268        else // write as many items as possible, release lock and retry
269        {
270            nwords = (spaces / width) * width;  // integer number of items
271            for (n = 0; n < nwords; n++) 
272            {
273                mwmr->data[ptw] = buffer[n];
274                if ((ptw + 1) == depth)  ptw = 0; 
275                else                     ptw = ptw + 1;
276            }
277            mwmr->sts = sts + nwords;
278            mwmr->ptw = ptw;
279            buffer = buffer + nwords;
280            items = items - (nwords/width);
281
282#if GIET_DEBUG_MWMR
283giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] writes %d words in fifo %x : sts = %d\n",
284                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
285#endif
286
287            lock_release( &mwmr->lock );
288        }
289
290        // we could deschedule before retry...
291        // giet_context_switch();
292    }
293} // end mwmr_write()
294
295
296//////////////////////////////////////
297void mwmr_read( mwmr_channel_t * mwmr, 
298                unsigned int *   buffer, 
299                unsigned int     items) 
300{
301
302#if GIET_DEBUG_MWMR
303unsigned int    x;
304unsigned int    y;
305unsigned int    lpid;
306giet_proc_xyp( &x, &y, &lpid );
307#endif
308
309    unsigned int n;
310    unsigned int nwords; // requested transfer length (in words)
311    unsigned int depth;  // channel depth (in words)
312    unsigned int width;  // channel width (in words)
313    unsigned int sts;    // channel sts
314    unsigned int ptr;    // channel ptr
315
316    if (items == 0) return;
317
318    while (1) 
319    {
320        // get the lock
321        lock_acquire( &mwmr->lock );
322
323        // compute nwords
324        depth  = mwmr->depth;
325        width  = mwmr->width;
326        sts    = mwmr->sts;
327        ptr    = mwmr->ptr;
328        nwords = width * items;
329
330        if (sts >= nwords) // read nwords, release lock and return
331        {
332            for (n = 0; n < nwords; n++) 
333            {
334                buffer[n] = mwmr->data[ptr];
335                if ((ptr + 1) == depth)  ptr = 0;
336                else                     ptr = ptr + 1;
337            }
338            mwmr->sts = mwmr->sts - nwords;
339            mwmr->ptr = ptr;
340
341#if GIET_DEBUG_MWMR
342giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] read %d words in fifo %x : sts = %d\n",
343                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
344#endif
345
346            lock_release( &mwmr->lock );
347            return;
348        }
349        else if (sts < width) // release lock and retry
350        {
351            lock_release( &mwmr->lock );
352        }
353        else // read as many items as possible, release lock and retry
354        {   
355            nwords = (sts / width) * width; // integer number of items
356            for (n = 0; n < nwords; n++) 
357            {
358                buffer[n] = mwmr->data[ptr];
359                if ((ptr + 1) == depth) ptr = 0;
360                else                    ptr = ptr + 1;
361            }
362            mwmr->sts = sts - nwords;
363            mwmr->ptr = ptr;
364            buffer = buffer + nwords;
365            items = items - (nwords/width);
366
367#if GIET_DEBUG_MWMR
368giet_shr_printf("\n[MWMR DEBUG] Proc[%d,%d,%d] read %d words in fifo %x : sts = %d\n",
369                x, y, lpid, nwords, (unsigned int)mwmr, mwmr->sts );
370#endif
371
372            lock_release( &mwmr->lock );
373        }
374
375        // we could deschedule before retry...
376        // giet_context_switch();
377    }
378} // end mwmr_read()
379
380
381// Local Variables:
382// tab-width: 4
383// c-basic-offset: 4
384// c-file-offsets:((innamespace . 0)(inline-open . 0))
385// indent-tabs-mode: nil
386// End:
387// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
388
Note: See TracBrowser for help on using the repository browser.