Changeset 450
- Timestamp:
- Nov 11, 2014, 4:18:38 PM (10 years ago)
- Location:
- soft/giet_vm/giet_libs
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_libs/mwmr_channel.c
r345 r450 1 1 ////////////////////////////////////////////////////////////////////////////////// 2 // File : mwmr_channel _.c2 // File : mwmr_channel.c 3 3 // Date : 01/04/2012 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 6 /////////////////////////////////////////////////////////////////////////////////// 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-Readers9 // communication channel, that can be used by parallel multi-tasks applications10 // 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 is22 // 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 the24 // "depth" parameter, and the "width" parameter define the minimal number of25 // word contained in an atomic item. Therefore, the "depth" parameter must be26 // 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 have30 // a variable number of producers and a variable number of consumers.31 ///////////////////////////////////////////////////////////////////////////////////32 7 33 8 #include <mwmr_channel.h> 34 9 #include <stdio.h> 35 10 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 ////////////////////////////////////// 12 void 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 27 giet_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 /////////////////////////////////////////////////// 37 static void mwmr_lock_acquire( unsigned int* lock ) 38 { 39 register unsigned int* plock = lock; 40 register unsigned int delay = 100; 44 41 asm volatile ( 45 42 "1: \n" … … 63 60 64 61 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 /////////////////////////////////////////////////// 63 unsigned int nb_mwmr_write( mwmr_channel_t * mwmr, 64 unsigned int * buffer, 65 unsigned int nitems) 66 { 76 67 unsigned int x; 77 68 unsigned int spaces; // number of empty slots (in words) … … 82 73 unsigned int ptw; // channel ptw 83 74 84 if (nitems == 0) { 85 return 0; 86 } 75 if (nitems == 0) return 0; 87 76 88 77 // get the lock … … 97 86 nwords = width * nitems; 98 87 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 { 101 92 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; 108 95 } 109 96 mwmr->sts = mwmr->sts + nwords; … … 112 99 return nitems; 113 100 } 114 else if (spaces < width) {115 // release lock and return101 else if (spaces < width) // release lock and return 102 { 116 103 mwmr->lock = 0; 117 104 return 0; 118 105 } 119 else {120 // transfer as many items as possible, release lock and return106 else // transfer as many items as possible, release lock and return 107 { 121 108 nwords = (spaces / width) * width; // integer number of items 122 for (x = 0; x < nwords; x++) { 109 for (x = 0; x < nwords; x++) 110 { 123 111 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; 130 114 } 131 115 mwmr->sts = sts + nwords; … … 137 121 138 122 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 ////////////////////////////////////////////////// 125 unsigned 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 //////////////////////////////////////// 185 void mwmr_write( mwmr_channel_t * mwmr, 186 unsigned int * buffer, 187 unsigned int nitems ) 188 { 150 189 unsigned int x; 151 190 unsigned int spaces; // number of empty slots (in words) … … 156 195 unsigned int ptw; // channel ptw 157 196 158 if (nitems == 0) { 159 return; 160 } 161 162 while (1) { 197 if (nitems == 0) return; 198 199 while (1) 200 { 163 201 // get the lock 164 202 mwmr_lock_acquire(&mwmr->lock); … … 172 210 nwords = width * nitems; 173 211 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 { 177 216 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; 184 219 } 185 220 mwmr->ptw = ptw; … … 188 223 return; 189 224 } 190 else if (spaces < width) {191 // release lock and retry after delay192 mwmr->lock = 0; 193 } 194 else {195 // write as many items as possible, release lock and retry after delay225 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 { 196 231 nwords = (spaces / width) * width; // integer number of items 197 for (x = 0; x < nwords; x++) { 232 for (x = 0; x < nwords; x++) 233 { 198 234 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; 205 237 } 206 238 mwmr->sts = sts + nwords; … … 215 247 216 248 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 ////////////////////////////////////// 250 void mwmr_read( mwmr_channel_t * mwmr, 251 unsigned int * buffer, 252 unsigned int nitems) 253 { 228 254 unsigned int x; 229 255 unsigned int nwords; // requested transfer length (in words) … … 233 259 unsigned int ptr; // channel ptr 234 260 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 { 313 265 // get the lock 314 266 mwmr_lock_acquire(&mwmr->lock); … … 321 273 nwords = width * nitems; 322 274 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 { 326 279 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; 333 282 } 334 283 mwmr->sts = mwmr->sts - nwords; … … 337 286 return; 338 287 } 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 { 344 294 nwords = (sts / width) * width; // integer number of items 345 for (x = 0; x < nwords; x++) { 295 for (x = 0; x < nwords; x++) 296 { 346 297 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; 353 300 } 354 301 mwmr->sts = sts - nwords; -
soft/giet_vm/giet_libs/mwmr_channel.h
r278 r450 4 4 // Author : alain greiner 5 5 // Copyright (c) UPMC-LIP6 6 /////////////////////////////////////////////////////////////////////////////////// 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 // WARNING : ALL MWMR channels must be defined in the mapping, 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. 6 31 /////////////////////////////////////////////////////////////////////////////////// 7 32 … … 11 36 /////////////////////////////////////////////////////////////////////////////////// 12 37 // MWMR channel structure 13 // The data arraysize is defined to obtain sizeof(mwmr_channel_t) = 4096 bytes.14 // The actual size can be redefined in the mapping info data structure.38 // The data buffer size is defined to obtain sizeof(mwmr_channel_t) = 4096 bytes. 39 // The actual buffer size cannot be larger than 4072 bytes (1018 words). 15 40 /////////////////////////////////////////////////////////////////////////////////// 16 41 … … 30 55 ////////////////////////////////////////////////////////////////////////////// 31 56 57 void mwmr_init( mwmr_channel_t* mwmr, 58 unsigned int width, // number of words per item 59 unsigned int items ); // max number of items 60 32 61 void mwmr_write( mwmr_channel_t* mwmr, 33 unsigned int* buffer, 34 unsigned int nitems ); 62 unsigned int* buffer, // user buffer vbase address 63 unsigned int nitems ); // number of items to transfer 35 64 36 void mwmr_ read(mwmr_channel_t* mwmr,37 unsigned int* buffer, 38 unsigned int nitems ); 65 void mwmr_write( mwmr_channel_t* mwmr, 66 unsigned int* buffer, // user buffer vbase address 67 unsigned int nitems ); // number of items to transfer 39 68 40 69 unsigned int nb_mwmr_read ( mwmr_channel_t * mwmr, 41 70 unsigned int * buffer, 42 71 unsigned int nitems ); 43 44 72 45 73 unsigned int nb_mwmr_write( mwmr_channel_t * mwmr, -
soft/giet_vm/giet_libs/stdio.c
r438 r450 541 541 ////////////////////////////////////////////////////////////////////////////////// 542 542 543 ///////////////////// 544 void giet_nic_alloc() 545 { 546 if ( sys_call( SYSCALL_NIC_ALLOC, 547 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_alloc()"); 548 } 549 550 /////////////////////////////////////// 551 void giet_nic_sync_send( void* buffer ) 552 { 553 if ( sys_call( SYSCALL_NIC_SYNC_SEND, 543 //////////////////////// 544 void giet_nic_rx_alloc() 545 { 546 if ( sys_call( SYSCALL_NIC_RX_ALLOC, 547 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_rx_alloc()"); 548 } 549 550 //////////////////////// 551 void giet_nic_tx_alloc() 552 { 553 if ( sys_call( SYSCALL_NIC_TX_ALLOC, 554 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_tx_alloc()"); 555 } 556 557 //////////////////////// 558 void giet_nic_rx_start() 559 { 560 if ( sys_call( SYSCALL_NIC_RX_START, 561 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_rx_start()"); 562 } 563 564 //////////////////////// 565 void giet_nic_tx_start() 566 { 567 if ( sys_call( SYSCALL_NIC_TX_START, 568 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_tx_start()"); 569 } 570 571 ///////////////////////////////////// 572 void giet_nic_rx_move( void* buffer ) 573 { 574 if ( sys_call( SYSCALL_NIC_RX_MOVE, 554 575 (unsigned int)buffer, 555 0, 0, 0 ) ) giet_exit("error in giet_nic_ sync_send()");556 } 557 558 ///////////////////////////////////// /////559 void giet_nic_ sync_receive( void* buffer )560 { 561 if ( sys_call( SYSCALL_NIC_ SYNC_RECEIVE,576 0, 0, 0 ) ) giet_exit("error in giet_nic_rx_move()"); 577 } 578 579 ///////////////////////////////////// 580 void giet_nic_tx_move( void* buffer ) 581 { 582 if ( sys_call( SYSCALL_NIC_TX_MOVE, 562 583 (unsigned int)buffer, 563 0, 0, 0 ) ) giet_exit("error in giet_nic_sync_receive()"); 564 } 584 0, 0, 0 ) ) giet_exit("error in giet_nic_tx_move()"); 585 } 586 587 //////////////////////// 588 void giet_nic_rx_stop() 589 { 590 if ( sys_call( SYSCALL_NIC_RX_STOP, 591 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_rx_start()"); 592 } 593 594 //////////////////////// 595 void giet_nic_tx_stop() 596 { 597 if ( sys_call( SYSCALL_NIC_TX_STOP, 598 0, 0, 0, 0 ) ) giet_exit("error in giet_nic_tx_start()"); 599 } 600 565 601 566 602 /////////////////////////////////////////////////////////////////////////////////// -
soft/giet_vm/giet_libs/stdio.h
r438 r450 46 46 #define SYSCALL_VOBJ_GET_LENGTH 0x1B 47 47 #define SYSCALL_GET_XY 0x1C 48 #define SYSCALL_NIC_ALLOC0x1D49 #define SYSCALL_NIC_SYNC_SEND0x1E50 #define SYSCALL_NIC_SYNC_RECEIVE0x1F48 // 0x1D 49 // 0x1E 50 // 0x1F 51 51 52 52 #define SYSCALL_FAT_OPEN 0x20 … … 66 66 // 0x2E 67 67 // 0x2F 68 69 #define SYSCALL_NIC_RX_ALLOC 0x30 70 #define SYSCALL_NIC_TX_ALLOC 0x31 71 #define SYSCALL_NIC_RX_START 0x32 72 #define SYSCALL_NIC_TX_START 0x33 73 #define SYSCALL_NIC_RX_MOVE 0x34 74 #define SYSCALL_NIC_TX_MOVE 0x35 75 #define SYSCALL_NIC_RX_STOP 0x36 76 #define SYSCALL_NIC_TX_STOP 0x37 77 // 0x38 78 // 0x39 79 // 0x3A 80 // 0x3B 81 // 0x3C 82 // 0x3D 83 // 0x3E 84 // 0x3F 68 85 69 86 ////////////////////////////////////////////////////////////////////////////////// … … 195 212 ////////////////////////////////////////////////////////////////////////// 196 213 197 extern void giet_nic_alloc(); 198 199 extern void giet_nic_sync_send( void* buffer); 200 201 extern void giet_nic_sync_receive( void* buffer ); 214 extern void giet_nic_rx_alloc(); 215 216 extern void giet_nic_tx_alloc(); 217 218 extern void giet_nic_rx_start(); 219 220 extern void giet_nic_tx_start(); 221 222 extern void giet_nic_rx_move( void* buffer); 223 224 extern void giet_nic_tx_move( void* buffer ); 225 226 extern void giet_nic_rx_stop(); 227 228 extern void giet_nic_tx_stop(); 202 229 203 230 //////////////////////////////////////////////////////////////////////////
Note: See TracChangeset
for help on using the changeset viewer.