source: soft/giet_vm/giet_kernel/sys_handler.c @ 488

Last change on this file since 488 was 478, checked in by alain, 10 years ago

1) The chained buffer structure has been modified to have one single buffer descriptor per cache line (64 bytes),
in order to simplify the software cache coherence between L2 and L3 caches when the IO bridge is used.
A new buffer_descriptor_t structure has been defined, and the fbf_chbuf_t and nic_chbuf_t structures have been adapted.
2) The NIC related system call handler _sys_nic_start() and _sys_nic_move() have been modified to support a distributed
kernel chbuf (one 4 Kbytes buffer per cluster), in order to support the one Gbit Ethernet NIC controller throughput.

  • the _sys_nic_start() function initialises the distributed chbuf, using the distributed heap.
  • the _sys_nic_move() function transfer one 4 KBytes container from the local kernel chbuf to an user local buffer.

This approach has been validated on the "classif" application: no packet loss with 16 clusters for average packet
length = 600 bytes and inter-packet gap = 300 cycles.

  • Property svn:executable set to *
File size: 45.0 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : sys_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner and joel porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <sys_handler.h>
9#include <tty_driver.h>
10#include <tim_driver.h>
11#include <ioc_driver.h>
12#include <nic_driver.h>
13#include <mmc_driver.h>
14#include <cma_driver.h>
15#include <ctx_handler.h>
16#include <fat32.h>
17#include <utils.h>
18#include <kernel_malloc.h>
19#include <tty0.h>
20#include <vmem.h>
21#include <hard_config.h>
22#include <giet_config.h>
23#include <mapping_info.h>
24
25#if !defined(SEG_BOOT_MAPPING_BASE)
26# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
27#endif
28
29#if !defined(NB_TTY_CHANNELS)
30# error: You must define NB_TTY_CHANNELS in the hard_config.h file
31#endif
32
33#if (NB_TTY_CHANNELS < 1)
34# error: NB_TTY_CHANNELS cannot be smaller than 1!
35#endif
36
37#if !defined(NB_TIM_CHANNELS)
38# error: You must define NB_TIM_CHANNELS in the hard_config.h file
39#endif
40
41#if !defined(NB_NIC_CHANNELS)
42# error: You must define NB_NIC_CHANNELS in the hard_config.h file
43#endif
44
45#if !defined(NB_CMA_CHANNELS)
46# error: You must define NB_CMA_CHANNELS in the hard_config.h file
47#endif
48
49#if !defined(GIET_NO_HARD_CC)
50# error: You must define GIET_NO_HARD_CC in the giet_config.h file
51#endif
52
53#if !defined ( GIET_NIC_MAC4 )
54# error: You must define GIET_NIC_MAC4 in the giet_config.h file
55#endif
56
57#if !defined ( GIET_NIC_MAC2 )
58# error: You must define GIET_NIC_MAC2 in the giet_config.h file
59#endif
60
61
62////////////////////////////////////////////////////////////////////////////
63//     Channel allocators for peripherals
64//     (TTY[0] is reserved for kernel)
65////////////////////////////////////////////////////////////////////////////
66
67unsigned int _tty_channel_allocator    = 1;
68unsigned int _tim_channel_allocator    = 0;
69unsigned int _cma_channel_allocator    = 0;
70unsigned int _nic_rx_channel_allocator = 0;
71unsigned int _nic_tx_channel_allocator = 0;
72
73////////////////////////////////////////////////////////////////////////////
74//     NIC_RX and NIC_TX chbuf arrays
75////////////////////////////////////////////////////////////////////////////
76
77nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
78
79nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
80
81////////////////////////////////////////////////////////////////////////////
82// FBF related chbuf descriptors array, indexed by the CMA channel index.
83// Physical addresses of these chbuf descriptors required for L2 cache sync.
84////////////////////////////////////////////////////////////////////////////
85
86fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
87
88unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
89
90////////////////////////////////////////////////////////////////////////////
91//    Initialize the syscall vector with syscall handlers
92// Note: This array must be synchronised with the define in file stdio.h
93////////////////////////////////////////////////////////////////////////////
94const void * _syscall_vector[64] = 
95{
96    &_sys_proc_xyp,         /* 0x00 */
97    &_get_proctime,         /* 0x01 */
98    &_sys_tty_write,        /* 0x02 */
99    &_sys_tty_read,         /* 0x03 */
100    &_sys_tty_alloc,        /* 0x04 */
101    &_sys_tty_get_lock,     /* 0x05 */
102    &_sys_tty_release_lock, /* 0x06 */
103    &_sys_heap_info,        /* 0x07 */
104    &_sys_local_task_id,    /* 0x08 */
105    &_sys_global_task_id,   /* 0x09 */ 
106    &_sys_fbf_cma_alloc,    /* 0x0A */
107    &_sys_fbf_cma_start,    /* 0x0B */
108    &_sys_fbf_cma_display,  /* 0x0C */
109    &_sys_fbf_cma_stop,     /* 0x0D */
110    &_sys_task_exit,        /* 0x0E */
111    &_sys_procs_number,     /* 0x0F */
112
113    &_sys_fbf_sync_write,   /* 0x10 */
114    &_sys_fbf_sync_read,    /* 0x11 */
115    &_sys_thread_id,        /* 0x12 */
116    &_sys_ukn,              /* 0x13 */
117    &_sys_tim_alloc,        /* 0x14 */
118    &_sys_tim_start,        /* 0x15 */ 
119    &_sys_tim_stop,         /* 0x16 */
120    &_sys_ukn,              /* 0x17 */
121    &_sys_ukn,              /* 0x18 */   
122    &_context_switch,       /* 0x19 */
123    &_sys_vobj_get_vbase,   /* 0x1A */
124    &_sys_vobj_get_length,  /* 0x1B */
125    &_sys_xy_from_ptr,      /* 0x1C */
126    &_sys_ukn,              /* 0x1D */
127    &_sys_ukn,              /* 0x1E */
128    &_sys_ukn,              /* 0x1F */
129
130    &_fat_user_open,        /* 0x20 */
131    &_fat_user_read,        /* 0x21 */
132    &_fat_user_write,       /* 0x22 */
133    &_fat_user_lseek,       /* 0x23 */
134    &_fat_fstat,            /* 0x24 */
135    &_fat_close,            /* 0x25 */
136    &_sys_ukn,              /* 0x26 */
137    &_sys_ukn,              /* 0x27 */
138    &_sys_ukn,              /* 0x28 */
139    &_sys_ukn,              /* 0x29 */
140    &_sys_ukn,              /* 0x2A */
141    &_sys_ukn,              /* 0x2B */
142    &_sys_ukn,              /* 0x2C */
143    &_sys_ukn,              /* 0x2D */
144    &_sys_ukn,              /* 0x2E */
145    &_sys_ukn,              /* 0x2F */
146
147    &_sys_nic_alloc,        /* 0x30 */
148    &_sys_nic_start,        /* 0x31 */
149    &_sys_nic_move,         /* 0x32 */
150    &_sys_nic_stop,         /* 0x33 */
151    &_sys_nic_stats,        /* 0x34 */
152    &_sys_nic_clear,        /* 0x35 */ 
153    &_sys_ukn,              /* 0x36 */
154    &_sys_ukn,              /* 0x37 */
155    &_sys_ukn,              /* 0x38 */   
156    &_sys_ukn,              /* 0x39 */
157    &_sys_ukn,              /* 0x3A */
158    &_sys_ukn,              /* 0x3B */
159    &_sys_ukn,              /* 0x3C */
160    &_sys_ukn,              /* 0x3D */
161    &_sys_ukn,              /* 0x3E */
162    &_sys_ukn,              /* 0x3F */
163};
164
165
166//////////////////////////////////////////////////////////////////////////////
167//             TTY related syscall handlers
168//////////////////////////////////////////////////////////////////////////////
169
170////////////////////
171int _sys_tty_alloc()
172{
173    // get a new TTY terminal index
174    unsigned int channel = _atomic_increment( &_tty_channel_allocator, 1 );
175    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
176    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
177
178    if ( channel >= NB_TTY_CHANNELS )
179    {
180        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n");
181        return -1;
182    }
183    else
184    {
185        _printf("\n[GIET WARNING] TTY channel %d allocated "
186                " to thread %d in vspace %d\n", channel, thread, vspace );
187        _set_context_slot( CTX_TTY_ID, channel );
188        return 0;
189    }
190}
191
192/////////////////////////////////////////////////
193int _sys_tty_write( const char*  buffer,   
194                    unsigned int length,    // number of characters
195                    unsigned int channel)   // channel index
196{
197    unsigned int  nwritten;
198
199    // compute and check tty channel
200    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
201    if( channel >= NB_TTY_CHANNELS ) return -1;
202
203    // write string to TTY channel
204    for (nwritten = 0; nwritten < length; nwritten++) 
205    {
206        // check tty's status
207        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
208
209        // write one byte
210        if (buffer[nwritten] == '\n') 
211        {
212            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
213        }
214        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
215    }
216   
217    return nwritten;
218}
219
220////////////////////////////////////////////////
221int _sys_tty_read( char*        buffer, 
222                   unsigned int length,    // unused
223                   unsigned int channel)   // channel index
224{
225    // compute and check tty channel
226    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
227    if( channel >= NB_TTY_CHANNELS ) return -1;
228
229    // read one character from TTY channel
230    if (_tty_rx_full[channel] == 0) 
231    {
232        return 0;
233    }
234    else 
235    {
236        *buffer = _tty_rx_buf[channel];
237        _tty_rx_full[channel] = 0;
238        return 1;
239    }
240}
241
242///////////////////////////////////////////
243int _sys_tty_get_lock( unsigned int   channel,
244                       unsigned int * save_sr_ptr )
245{
246    // compute and check tty channel
247    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
248    if( channel >= NB_TTY_CHANNELS ) return -1;
249
250    _it_disable( save_sr_ptr );
251    _sbt_lock_acquire( &_tty_tx_lock[channel] );
252    return 0;
253}
254
255///////////////////////////////////////////////
256int _sys_tty_release_lock( unsigned int   channel,
257                           unsigned int * save_sr_ptr )
258{
259    // compute and check tty channel
260    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
261    if( channel >= NB_TTY_CHANNELS ) return -1;
262
263    _sbt_lock_release( &_tty_tx_lock[channel] );
264    _it_restore( save_sr_ptr );
265    return 0;
266}
267
268//////////////////////////////////////////////////////////////////////////////
269//             TIM related syscall handlers
270//////////////////////////////////////////////////////////////////////////////
271
272////////////////////
273int _sys_tim_alloc()
274{
275    // get a new timer index
276    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
277    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
278    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
279
280    if ( channel >= NB_TIM_CHANNELS )
281    {
282        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
283        return -1;
284    }
285    else
286    {
287        _printf("\n[GIET WARNING] TIM channel %d allocated "
288                " to thread %d in vspace %d\n", channel, thread, vspace );
289        _set_context_slot( CTX_TIM_ID, channel );
290        return 0;
291    }
292}
293
294/////////////////////////////////////////
295int _sys_tim_start( unsigned int period )
296{
297    // get timer index
298    unsigned int channel = _get_context_slot( CTX_TIM_ID );
299    if ( channel >= NB_TIM_CHANNELS )
300    {
301        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
302        return -1;
303    }
304
305    // start timer
306    _timer_start( channel, period );
307
308    return 0;
309}
310
311///////////////////
312int _sys_tim_stop()
313{
314    // get timer index
315    unsigned int channel = _get_context_slot( CTX_TIM_ID );
316    if ( channel >= NB_TIM_CHANNELS )
317    {
318        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
319        return -1;
320    }
321
322    // stop timer
323    _timer_stop( channel );
324
325    return 0;
326}
327
328//////////////////////////////////////////////////////////////////////////////
329//             NIC related syscall handlers
330//////////////////////////////////////////////////////////////////////////////
331
332#define NIC_CONTAINER_SIZE 4096
333
334///////////////////////////////////////////
335int _sys_nic_alloc( unsigned int is_rx )
336{
337
338#if GIET_DEBUG_NIC
339unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
340_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n",
341        thread, _get_proctime() );
342#endif
343
344    unsigned int nic_channel;
345    unsigned int cma_channel;
346
347    // get a NIC_RX or NIC_TX channel index
348    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
349    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
350
351    if ( (nic_channel >= NB_NIC_CHANNELS) )
352    {
353        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
354        return -1;
355    }
356
357    // get a CMA channel index
358    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
359
360    if ( cma_channel >= NB_CMA_CHANNELS )
361    {
362        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
363        return -1;
364    }
365
366    // register nic_index and cma_index in task context
367    if ( is_rx )
368    {
369        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
370        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
371    }
372    else
373    {
374        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
375        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
376    }
377
378#if GIET_DEBUG_NIC
379_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d : "
380        "NIC channel = %d / CMA channel = %d\n", 
381        thread, _get_proctime(), nic_channel, cma_channel );
382#endif
383
384    return nic_channel;
385} // end _sys_nic_alloc()
386
387////////////////////////////////////////
388int _sys_nic_start( unsigned int is_rx )
389{
390
391#if GIET_DEBUG_NIC
392unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
393_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_start() at cycle %d\n",
394        thread , _get_proctime() );
395#endif
396
397    unsigned int nic_channel;
398    unsigned int cma_channel;
399
400    // get NIC channel index and CMA channel index
401    if ( is_rx )
402    {
403        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
404        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
405    }
406    else
407    {
408        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
409        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
410    }
411
412#if GIET_DEBUG_NIC
413_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d"
414        " get NIC channel = %d / CMA channel = %d\n",
415        thread, _get_proctime(), nic_channel, cma_channel );
416#endif
417
418    if ( nic_channel >= NB_NIC_CHANNELS )
419    {
420        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
421        return -1;
422    }
423    if ( cma_channel >= NB_CMA_CHANNELS )
424    {
425        _printf("\n[GIET_ERROR] in _sys_nic_start(): CMA channel not allocated\n");
426        return -1;
427    }
428
429    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
430    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
431
432    // These variables are used for the various V2P translation
433    unsigned int       ptab  = _get_context_slot(CTX_PTAB_ID);
434    unsigned int       ppn;
435    unsigned int       flags;
436    unsigned int       vaddr;
437
438    // allocate two containers per cluster
439    unsigned int        cx;           // container X coordinate
440    unsigned int        cy;           // container Y coordinate
441    unsigned int        index;        // container index in chbuf
442    unsigned long long  cont_paddr;   // container physical address
443   
444    for ( cx = 0 ; cx < X_SIZE ; cx++ )
445    {
446        for ( cy = 0 ; cy < Y_SIZE ; cy++ )
447        {
448            // compute index in chbuf
449            index = (cx * Y_SIZE) + cy; 
450
451            // allocate the container
452            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
453
454            // compute container physical address
455            _v2p_translate( (page_table_t*)ptab,
456                            vaddr>>12,
457                            &ppn,
458                            &flags );
459            cont_paddr = (((unsigned long long)ppn) << 12) | (vaddr & 0x00000FFF);
460
461            // initialize chbuf
462            if ( is_rx ) _nic_rx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
463            else         _nic_tx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
464
465#if GIET_DEBUG_NIC
466_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start()"
467        " allocates container in cluster[%d,%d] : vaddr = %x / paddr = %l\n",
468        thread , cx , cy , vaddr , cont_paddr );
469#endif
470        }
471    }
472
473    // compute the NIC chbuf descriptor physical address
474    unsigned int offset;
475    if ( is_rx ) offset = 0x4000;
476    else         offset = 0x4010;
477    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
478                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
479
480#if GIET_DEBUG_NIC
481_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start()"
482        " get NIC chbuf : paddr = %l\n",
483        thread , nic_chbuf_pbase );
484#endif
485
486    // compute the kernel chbuf descriptor physical address
487    if ( is_rx ) vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
488    else         vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
489    _v2p_translate( (page_table_t*)ptab,
490                     vaddr>>12,
491                     &ppn,
492                     &flags );
493    ker_chbuf_pbase = (((unsigned long long)ppn) << 12) | (vaddr & 0x00000FFF);
494
495#if GIET_DEBUG_NIC
496_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start()"
497        " get kernel chbuf : vaddr = %x / paddr = %l\n",
498        thread , vaddr , ker_chbuf_pbase );
499#endif
500
501    // sync the kernel chbuf in L2 after write in L2
502    _mmc_sync( ker_chbuf_pbase, sizeof( nic_chbuf_t ) );
503
504    // initializes CMA registers defining the source & destination chbufs
505    if ( is_rx )               // NIC to kernel
506    {
507        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
508        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
509        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
510        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
511        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
512        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, X_SIZE*Y_SIZE );
513    }
514    else                      // kernel to NIC
515    {
516        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
517        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
518        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, X_SIZE*Y_SIZE );
519        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
520        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
521        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
522    }
523
524    // start CMA transfer
525    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
526    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );                   // OUT_OF_ORDER mode
527    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
528
529    // activates NIC channel
530    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 ); 
531
532#if GIET_DEBUG_NIC
533_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
534        thread , _get_proctime() );
535#endif
536
537    return 0;
538}  // end sys_nic_start()
539
540//////////////////////////////////////
541int _sys_nic_move( unsigned int is_rx,
542                   unsigned int channel,
543                   void*        buffer )
544{
545
546#if GIET_DEBUG_NIC
547unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
548_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
549        thread , _get_proctime() );
550#endif
551
552    // get cluster coordinates for the processor running the calling task
553    unsigned int  procid = _get_procid();
554    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
555    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
556   
557    unsigned long long user_buffer_paddr;    // user buffer physical address
558    unsigned long long kernel_buffer_paddr;  // kernel buffer physical address
559    unsigned long long kernel_chbuf_paddr;   // kernel chbuf physical address
560    unsigned long long buffer_desc;          // kernel buffer descriptor
561    unsigned long long buffer_desc_paddr;    // kernel buffer descriptor physical address
562    unsigned int       index;                // kernel buffer index in chbuf
563
564    // The following variables are used for V2P translation
565    unsigned int ptab = _get_context_slot( CTX_PTAB_ID );
566    unsigned int ppn;
567    unsigned int flags;
568    unsigned int vaddr;
569
570    // Compute user buffer physical address and check access rights
571    vaddr = (unsigned int)buffer;
572    _v2p_translate( (page_table_t*)ptab,
573                     vaddr>>12,
574                     &ppn,
575                     &flags );
576
577    if ( (flags & PTE_U) == 0 )
578    {
579        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
580        return -1;
581    }
582    user_buffer_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
583
584#if GIET_DEBUG_NIC
585_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
586        thread, user_buffer_paddr );
587#endif
588
589    // check NIC channel index
590    if ( channel >= NB_NIC_CHANNELS )
591    {
592        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
593        return -1;
594    }
595
596    // get kernel chbuf virtual address
597    nic_chbuf_t* chbuf;
598    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
599    else          chbuf = &_nic_tx_chbuf[channel];
600
601    // compute kernel chbuf physical address (required for sync)
602    vaddr = (unsigned int)chbuf;
603    _v2p_translate( (page_table_t*)ptab,
604                     vaddr>>12,
605                     &ppn,
606                     &flags );
607    kernel_chbuf_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
608
609    // poll chbuf until success
610    while ( 1 )
611    {
612        // compute buffer index and buffer descriptor paddr
613        index = (Y_SIZE * cx) + cy;
614        buffer_desc_paddr = kernel_chbuf_paddr + (index<<6);
615
616        // inval buffer descriptor in L2 before read in L2
617        _mmc_inval( buffer_desc_paddr , 8 );
618        buffer_desc = chbuf->buffer[index].desc;
619
620#if GIET_DEBUG_NIC
621_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read buffer descriptor %d\n"
622        " at cycle = %d / paddr = %l / buffer descriptor = %l\n",
623        thread, index, _get_proctime(), buffer_desc_paddr, buffer_desc );
624#endif
625
626        // test buffer status and break if found
627        if ( ( is_rx != 0 ) && (buffer_desc >> 63) == 1 )  break;
628        if ( ( is_rx == 0 ) && (buffer_desc >> 63) == 0 )  break;
629    }
630
631    // compute kernel buffer physical address
632    kernel_buffer_paddr = buffer_desc & 0x0000FFFFFFFFFFFFULL;
633   
634    // move one container, using a physical_memcpy
635    if ( is_rx )
636    {
637        // inval kernel buffer in L2 before read in L2
638        _mmc_inval( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
639
640        // transfer data from kernel buffer to user buffer
641        _physical_memcpy( user_buffer_paddr, 
642                          kernel_buffer_paddr, 
643                          NIC_CONTAINER_SIZE );
644#if GIET_DEBUG_NIC
645_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
646        "kernel buffer %l to user buffer %l at cycle %d\n",
647        thread , kernel_buffer_paddr , user_buffer_paddr , _get_proctime() );
648#endif
649
650    }
651    else
652    {
653        // transfer data from user buffer to kernel buffer
654        _physical_memcpy( kernel_buffer_paddr, 
655                          user_buffer_paddr, 
656                          NIC_CONTAINER_SIZE );
657
658        // sync kernel buffer in L2 after write in L2
659        _mmc_sync( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
660
661#if GIET_DEBUG_NIC
662_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
663        "user buffer %l to kernel buffer %l at cycle %d\n",
664        thread , user_buffer_paddr , kernel_buffer_paddr , _get_proctime() );
665#endif
666
667    }
668
669    // update kernel chbuf status
670    if ( is_rx ) chbuf->buffer[index].desc = kernel_buffer_paddr & 0x0000FFFFFFFFFFFFULL;
671    else         chbuf->buffer[index].desc = kernel_buffer_paddr | 0x8000000000000000ULL;
672
673    // sync kernel chbuf in L2 after write in L2
674    _mmc_sync( kernel_chbuf_paddr + (index<<6) , 8 );
675
676#if GIET_DEBUG_NIC
677_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
678        thread , index , _get_proctime() );
679#endif
680
681    return 0;
682} // end _sys_nic_move()
683
684////////////////////////////////////////
685int _sys_nic_stop( unsigned int is_rx )
686{
687    unsigned int nic_channel;
688    unsigned int cma_channel;
689
690    // get NIC channel index and CMA channel index
691    if ( is_rx )
692    {
693        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
694        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
695    }
696    else
697    {
698        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
699        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
700    }
701
702    if ( nic_channel >= NB_NIC_CHANNELS )
703    {
704        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
705        return -1;
706    }
707    if ( cma_channel >= NB_CMA_CHANNELS )
708    {
709        _printf("\n[GIET_ERROR] in _sys_nic_start(): CMA channel not allocated\n");
710        return -1;
711    }
712
713    // desactivates the NIC channel
714    _nic_channel_stop( nic_channel, is_rx );
715
716    // desactivates the CMA channel
717    _cma_channel_stop( cma_channel );
718
719    return 0;
720}
721
722////////////////////////////////////////
723int _sys_nic_clear( unsigned int is_rx )
724{
725    unsigned int nic_channel;
726
727    // get NIC channel
728    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
729    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
730
731    if ( nic_channel >= NB_NIC_CHANNELS )
732    {
733        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
734        return -1;
735    }
736
737    if ( is_rx )
738    {
739        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
740        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
741        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
742        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
743        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
744        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
745        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
746        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
747        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
748    } 
749    else
750    {
751        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
752        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
753        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
754        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
755        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
756        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
757        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
758    }
759    return 0;
760}
761
762////////////////////////////////////////
763int _sys_nic_stats( unsigned int is_rx )
764{
765    unsigned int nic_channel;
766
767    // get NIC channel
768    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
769    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
770
771    if ( nic_channel >= NB_NIC_CHANNELS )
772    {
773        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
774        return -1;
775    }
776
777    if ( is_rx )
778    {
779        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
780        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
781        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
782        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
783        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
784        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
785        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
786        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
787
788        _printf("\n### Network Controller RX Statistics ###\n"
789                "- packets received : %d\n"
790                "- too small        : %d\n"
791                "- too big          : %d\n"
792                "- fifo full        : %d\n" 
793                "- crc fail         : %d\n" 
794                "- dst mac fail     : %d\n" 
795                "- channel full     : %d\n" 
796                "- broadcast        : %d\n",
797                received,
798                too_small,
799                too_big,
800                fifo_full,
801                crc_fail,
802                dst_fail,
803                ch_full,
804                broadcast );
805    } 
806    else
807    {
808        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
809        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
810        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
811        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
812        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
813        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
814
815        _printf("\n### Network Controller TX Statistics ###\n"
816                "- packets received : %d\n"
817                "- too small        : %d\n"
818                "- too big          : %d\n"
819                "- src mac fail     : %d\n" 
820                "- bypass           : %d\n" 
821                "- broadcast        : %d\n",
822                received,
823                too_big,
824                too_small,
825                src_fail,
826                bypass,
827                broadcast );
828    }
829    return 0;
830}
831
832/////////////////////////////////////////////////////////////////////////////////////////
833//    FBF related syscall handlers
834/////////////////////////////////////////////////////////////////////////////////////////
835
836/////////////////////////////////////////////
837int _sys_fbf_sync_write( unsigned int offset,
838                         void*        buffer,
839                         unsigned int length )
840{
841    char* fbf_address = (char *)SEG_FBF_BASE + offset;
842    memcpy( fbf_address, buffer, length);
843
844    return 0;
845}
846
847/////////////////////////////////////////////
848int _sys_fbf_sync_read(  unsigned int offset,
849                         void*        buffer,
850                         unsigned int length )
851{
852    char* fbf_address = (char *)SEG_FBF_BASE + offset;
853    memcpy( buffer, fbf_address, length);
854
855    return 0;
856}
857
858////////////////////////
859int _sys_fbf_cma_alloc()
860{
861   // get a new CMA channel index
862    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
863    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
864    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
865
866    if ( channel >= NB_CMA_CHANNELS )
867    {
868        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
869        return -1;
870    }
871    else
872    {
873        _printf("\n[GIET WARNING] FBF_CMA channel %d allocated "
874                " to thread %d in vspace %d\n", channel, thread, vspace );
875        _set_context_slot( CTX_CMA_FB_ID, channel );
876        return 0;
877    }
878} // end sys_fbf_cma_alloc()
879
880////////////////////////////////////////////
881int _sys_fbf_cma_start( void*        vbase0, 
882                        void*        vbase1, 
883                        unsigned int length ) 
884{
885#if NB_CMA_CHANNELS > 0
886
887    unsigned int       ptab;            // page table virtual address
888    unsigned int       vaddr;           // virtual address
889    unsigned int       flags;           // protection flags
890    unsigned int       ppn;             // physical page number
891    unsigned long long chbuf_paddr;     // physical address of source chbuf descriptor
892
893    // get channel index
894    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
895
896    if ( channel >= NB_CMA_CHANNELS )
897    {
898        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
899        return -1;
900    }
901
902#if GIET_DEBUG_FBF_CMA
903_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_start()\n"
904        " - channel      = %d\n"
905        " - buf0   vbase = %x\n"
906        " - buf1   vbase = %x\n"
907        " - buffer size  = %x\n",
908        channel,
909        (unsigned int)vbase0,
910        (unsigned int)vbase1,
911        length );
912#endif
913
914    // checking user buffers virtual addresses and length alignment
915    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 
916    {
917        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer not word aligned\n");
918        return -1;
919    }
920
921    // get page table virtual address
922    ptab = _get_context_slot(CTX_PTAB_ID);
923
924    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
925    vaddr = ((unsigned int)SEG_FBF_BASE);
926    _v2p_translate( (page_table_t*) ptab, 
927                    (vaddr >> 12),
928                    &ppn, 
929                    &flags );
930
931    _fbf_chbuf[channel].fbf.desc = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
932
933    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
934    vaddr = (unsigned int)vbase0; 
935    _v2p_translate( (page_table_t*) ptab, 
936                    (vaddr >> 12),
937                    &ppn, 
938                    &flags );
939    if ((flags & PTE_U) == 0) 
940    {
941        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 0 not in user space\n");
942        return -1;
943    }
944
945    _fbf_chbuf[channel].buf0.desc = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
946
947    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
948    vaddr = (unsigned int)vbase1; 
949    _v2p_translate( (page_table_t*) ptab, 
950                    (vaddr >> 12),
951                    &ppn, 
952                    &flags );
953    if ((flags & PTE_U) == 0) 
954    {
955        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 1 not in user space\n");
956        return -1;
957    }
958
959    _fbf_chbuf[channel].buf1.desc = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
960
961    // initializes buffer length
962    _fbf_chbuf[channel].length = length;
963
964    // Compute and register physical adress of the chbuf descriptor
965    vaddr = (unsigned int)(&_fbf_chbuf[channel]);
966    _v2p_translate( (page_table_t*) ptab, 
967                    (vaddr >> 12),
968                    &ppn, 
969                    &flags );
970 
971    chbuf_paddr = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
972
973    _fbf_chbuf_paddr[channel] = chbuf_paddr;
974
975
976    if ( USE_IOB )
977    {
978        // SYNC request for channel descriptor
979        _mmc_sync( chbuf_paddr, 32 );
980    }
981
982#if GIET_DEBUG_FBF_CMA
983_printf(" - fbf    pbase = %l\n"
984        " - buf0   pbase = %l\n"
985        " - buf1   pbase = %l\n"
986        " - chbuf  pbase = %l\n",
987        _fbf_chbuf[channel].fbf.desc,
988        _fbf_chbuf[channel].buf0.desc,
989        _fbf_chbuf[channel].buf1.desc,
990        chbuf_paddr );
991#endif
992
993    // call CMA driver to start transfer
994    _cma_channel_start( channel, 
995                        chbuf_paddr,
996                        2,
997                        chbuf_paddr + 128,
998                        1,
999                        length );
1000    return 0;
1001
1002#else
1003
1004    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1005    return -1;
1006
1007#endif
1008} // end _sys_fbf_cma_start()
1009
1010/////////////////////////////////////////////////////
1011int _sys_fbf_cma_display( unsigned int buffer_index )
1012{
1013#if NB_CMA_CHANNELS > 0
1014
1015    volatile unsigned int long long user_buffer_desc;
1016    volatile unsigned int           full = 1;
1017
1018    // get channel index
1019    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1020
1021    if ( channel >= NB_CMA_CHANNELS )
1022    {
1023        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : CMA channel index too large\n");
1024        return -1;
1025    }
1026
1027#if GIET_DEBUG_FBF_CMA
1028_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
1029        " - channel      = %d\n"
1030        " - buffer       = %d\n",
1031        channel, buffer_index );
1032#endif
1033
1034    if ( buffer_index == 0 )    // user buffer 0
1035    {
1036        // waiting user buffer released by the CMA component)
1037        while ( full )
1038        { 
1039            // INVAL L1 and L2 cache copies of user buffer descriptor, because
1040            // it has been modified in RAM by the CMA component
1041            _dcache_buf_invalidate( (unsigned int)&_fbf_chbuf[channel].buf0.desc , 8 );
1042            _mmc_inval( _fbf_chbuf_paddr[channel] , 8 );
1043
1044            // get user buffer descriptor
1045            user_buffer_desc = _fbf_chbuf[channel].buf0.desc;
1046
1047            // get user buffer descriptor status
1048            full = ( (unsigned int)(user_buffer_desc>>63) );
1049        }
1050
1051        // SYNC request for the user buffer, because
1052        // it will be read from XRAM by the CMA component
1053        _mmc_sync( user_buffer_desc, _fbf_chbuf[channel].length );
1054
1055        // set user buffer status, and SYNC request, because this buffer
1056        // descriptor will be read from XRAM by the CMA component
1057        _fbf_chbuf[channel].buf0.desc = user_buffer_desc | 0x8000000000000000ULL;
1058        _mmc_sync( _fbf_chbuf_paddr[channel] , 8 );
1059
1060        // reset fbf buffer status, and SYNC request, because this buffer
1061        // descriptor will be read from XRAM by the CMA component
1062        _fbf_chbuf[channel].fbf.desc  = _fbf_chbuf[channel].fbf.desc & 0x7FFFFFFFFFFFFFFFULL;
1063        _mmc_sync( _fbf_chbuf_paddr[channel] + 128 , 8 );
1064    }
1065    else                        // user buffer 1
1066    {
1067        // waiting user buffer released by the CMA component)
1068        while ( full )
1069        { 
1070            // INVAL L1 and L2 cache copies of user buffer descriptor, because
1071            // it has been modified in RAM by the CMA component
1072            _dcache_buf_invalidate( (unsigned int)&_fbf_chbuf[channel].buf1.desc , 8 );
1073            _mmc_inval( _fbf_chbuf_paddr[channel] + 64 , 8 );
1074
1075            // get user buffer descriptor
1076            user_buffer_desc = _fbf_chbuf[channel].buf1.desc;
1077
1078            // get user buffer descriptor status
1079            full = ( (unsigned int)(user_buffer_desc>>63) );
1080        }
1081
1082        // SYNC request for the user buffer, because
1083        // it will be read from XRAM by the CMA component
1084        _mmc_sync( user_buffer_desc, _fbf_chbuf[channel].length );
1085
1086        // set user buffer status, and SYNC request, because this buffer
1087        // descriptor will be read from XRAM by the CMA component
1088        _fbf_chbuf[channel].buf1.desc = user_buffer_desc | 0x8000000000000000ULL;
1089        _mmc_sync( _fbf_chbuf_paddr[channel] , 8 );
1090
1091        // reset fbf buffer status, and SYNC request, because this buffer
1092        // descriptor will be read from XRAM by the CMA component
1093        _fbf_chbuf[channel].fbf.desc  = _fbf_chbuf[channel].fbf.desc & 0x7FFFFFFFFFFFFFFFULL;
1094        _mmc_sync( _fbf_chbuf_paddr[channel] + 128 , 8 );
1095    }
1096
1097#if GIET_DEBUG_FBF_CMA
1098_printf(" - fbf    desc = %l\n"
1099        " - buf0   desc = %l\n"
1100        " - buf1   desc = %l\n",
1101        _fbf_chbuf[channel].fbf.desc,
1102        _fbf_chbuf[channel].buf0.desc,
1103        _fbf_chbuf[channel].buf1.desc );
1104#endif
1105
1106    return 0;
1107
1108#else
1109
1110    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1111    return -1;
1112
1113#endif
1114} // end _sys_fbf_cma_display()
1115
1116
1117///////////////////////
1118int _sys_fbf_cma_stop()
1119{
1120#if NB_CMA_CHANNELS > 0
1121
1122    // get channel index
1123    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1124
1125    if ( channel >= NB_CMA_CHANNELS )
1126    {
1127        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
1128        return -1;
1129    }
1130
1131    // Desactivate CMA channel
1132    _cma_channel_stop( channel );
1133
1134    return 0;
1135
1136#else
1137
1138    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
1139    return -1;
1140
1141#endif
1142} // end _sys_fbf_cma_stop()
1143
1144
1145//////////////////////////////////////////////////////////////////////////////
1146//           Miscelaneous syscall handlers
1147//////////////////////////////////////////////////////////////////////////////
1148
1149///////////////
1150int _sys_ukn() 
1151{
1152    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
1153    return -1;
1154}
1155
1156////////////////////////////////////
1157int _sys_proc_xyp( unsigned int* x,
1158                   unsigned int* y,
1159                   unsigned int* p )
1160{
1161    unsigned int gpid = _get_procid();  // global processor index from CPO register
1162
1163    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
1164    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1165    *p = gpid & ((1<<P_WIDTH)-1);
1166
1167    return 0;
1168}
1169
1170//////////////////////////////////
1171int _sys_task_exit( char* string ) 
1172{
1173    unsigned int date       = _get_proctime();
1174
1175    unsigned int gpid       = _get_procid();
1176    unsigned int cluster_xy = gpid >> P_WIDTH;
1177    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
1178    unsigned int x          = cluster_xy >> Y_WIDTH;
1179    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
1180
1181    unsigned int task_id    = _get_context_slot(CTX_LTID_ID);
1182
1183    // print exit message
1184    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
1185            "\n       Cause : %s\n\n",
1186            task_id, x, y, lpid, date, string );
1187
1188    // goes to sleeping state
1189    _set_context_slot(CTX_RUN_ID, 0);
1190
1191    // deschedule
1192    _context_switch();
1193
1194    return 0;
1195} 
1196
1197//////////////////////
1198int _context_switch() 
1199{
1200    unsigned int save_sr;
1201
1202    _it_disable( &save_sr );
1203    _ctx_switch();
1204    _it_restore( &save_sr );
1205
1206    return 0;
1207}
1208
1209////////////////////////
1210int _sys_local_task_id()
1211{
1212    return _get_context_slot(CTX_LTID_ID);
1213}
1214
1215/////////////////////////
1216int _sys_global_task_id()
1217{
1218    return _get_context_slot(CTX_GTID_ID);
1219}
1220
1221////////////////////
1222int _sys_thread_id()
1223{
1224    return _get_context_slot(CTX_TRDID_ID);
1225}
1226
1227//////////////////////////////////////
1228int _sys_procs_number( unsigned int  x, 
1229                       unsigned int  y, 
1230                       unsigned int* number )
1231{
1232    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1233    mapping_cluster_t * cluster = _get_cluster_base(header);
1234
1235    if ( (x < X_SIZE) && (y < Y_SIZE) )
1236    {
1237        *number = cluster[(x*Y_SIZE)+y].procs;
1238        return 0;
1239    }
1240    else 
1241    {
1242        _printf("\n[GIET ERROR] in _sys_procs_number() : illegal (x,y) coordinates\n" );
1243        return -1;
1244    }
1245}
1246
1247///////////////////////////////////////////////////////
1248int _sys_vobj_get_vbase( char*             vspace_name, 
1249                         char*             vobj_name, 
1250                         unsigned int*     vbase ) 
1251{
1252    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1253    mapping_vspace_t * vspace = _get_vspace_base(header);
1254    mapping_vobj_t * vobj     = _get_vobj_base(header);
1255
1256    unsigned int vspace_id;
1257    unsigned int vobj_id;
1258
1259    // scan vspaces
1260    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1261    {
1262        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1263        {
1264            // scan vobjs
1265            for (vobj_id = vspace[vspace_id].vobj_offset; 
1266                 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 
1267                 vobj_id++) 
1268            {
1269                if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0) 
1270                {
1271                    *vbase = vobj[vobj_id].vbase;
1272                    return 0;
1273                }
1274            } 
1275        }
1276    } 
1277    return -1;    // not found
1278}
1279
1280/////////////////////////////////////////////////////////
1281int _sys_vobj_get_length( char*         vspace_name, 
1282                          char*         vobj_name,
1283                          unsigned int* length ) 
1284{
1285    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1286    mapping_vspace_t * vspace = _get_vspace_base(header);
1287    mapping_vobj_t * vobj     = _get_vobj_base(header);
1288
1289    unsigned int vspace_id;
1290    unsigned int vobj_id;
1291
1292    // scan vspaces
1293    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1294    {
1295        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1296        {
1297            // scan vobjs
1298            for (vobj_id = vspace[vspace_id].vobj_offset; 
1299                 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 
1300                 vobj_id++) 
1301            {
1302                if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0) 
1303                {
1304                    *length = vobj[vobj_id].length;
1305                    return 0;
1306                }
1307            } 
1308        }
1309    } 
1310    return -1;    // not found
1311}
1312
1313////////////////////////////////////////
1314int _sys_xy_from_ptr( void*         ptr,
1315                      unsigned int* x,
1316                      unsigned int* y )
1317{
1318    unsigned int ppn;
1319    unsigned int flags;
1320    unsigned int vpn  = (((unsigned int)ptr)>>12);
1321   
1322    // get the page table pointer
1323    page_table_t* pt = (page_table_t*)_get_context_slot( CTX_PTAB_ID ); 
1324
1325    // compute the physical address
1326    _v2p_translate( pt, vpn, &ppn, &flags );
1327
1328    *x = (ppn>>24) & 0xF;
1329    *y = (ppn>>20) & 0xF;
1330    return 0;
1331}
1332
1333/////////////////////////////////////////
1334int _sys_heap_info( unsigned int* vaddr, 
1335                    unsigned int* length,
1336                    unsigned int  x,
1337                    unsigned int  y ) 
1338{
1339    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1340    mapping_task_t *   tasks   = _get_task_base(header);
1341    mapping_vobj_t *   vobjs   = _get_vobj_base(header);
1342    mapping_vspace_t * vspaces = _get_vspace_base(header);
1343
1344    unsigned int task_id;
1345    unsigned int vspace_id;
1346    unsigned int vobj_id = 0xFFFFFFFF;
1347
1348    // searching the heap vobj_id
1349    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
1350    {
1351        // get vspace global index
1352        vspace_id = _get_context_slot(CTX_VSID_ID);
1353
1354        // scan all tasks in vspace
1355        unsigned int min = vspaces[vspace_id].task_offset ;
1356        unsigned int max = min + vspaces[vspace_id].tasks ;
1357        for ( task_id = min ; task_id < max ; task_id++ )
1358        {
1359            if ( tasks[task_id].clusterid == (x * Y_SIZE + y) )
1360            {
1361                vobj_id = tasks[task_id].heap_vobj_id;
1362                if ( vobj_id != 0xFFFFFFFF ) break;
1363            }
1364        }
1365    }
1366    else                                // searching in the calling task
1367    {
1368        task_id = _get_context_slot(CTX_GTID_ID);
1369        vobj_id = tasks[task_id].heap_vobj_id;
1370    }
1371
1372    // analysing the vobj_id
1373    if ( vobj_id != 0xFFFFFFFF ) 
1374    {
1375        *vaddr  = vobjs[vobj_id].vbase;
1376        *length = vobjs[vobj_id].length;
1377        return 0;
1378    }
1379    else 
1380    {
1381        *vaddr  = 0;
1382        *length = 0;
1383        return -1;
1384    }
1385}  // end _sys_heap_info()
1386
1387
1388// Local Variables:
1389// tab-width: 4
1390// c-basic-offset: 4
1391// c-file-offsets:((innamespace . 0)(inline-open . 0))
1392// indent-tabs-mode: nil
1393// End:
1394// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1395
Note: See TracBrowser for help on using the repository browser.