Changeset 228 for soft/giet_vm/libs/mwmr_channel.c
- Timestamp:
- Feb 12, 2013, 6:33:31 PM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/libs/mwmr_channel.c
r207 r228 19 19 // can be used to get the virtual base address of the channel from it's name. 20 20 // 21 // An MWMR transaction transfer 21 // An MWMR transaction transfer an integer number of items, and an item is 22 22 // an integer number of unsigned int (32 bits words). 23 23 // The max number of words that can be stored in a MWMR channel is defined by the … … 39 39 // If the lock is already taken a fixed delay is introduced before retry. 40 40 ////////////////////////////////////////////////////////////////////////////// 41 void mwmr_lock_acquire(unsigned int* lock_address) 42 { 43 register unsigned int* plock = lock_address; 44 register unsigned int delay = 100; 41 void mwmr_lock_acquire(unsigned int * lock_address) { 42 register unsigned int * plock = lock_address; 43 register unsigned int delay = 100; 45 44 asm volatile ( 46 "mwmr_lock_try: 47 "ll $2, 0(%0) 48 "bnez $2, mwmr_lock_delay 49 "li $3, 1 50 "sc $3, 0(%0) 51 "bnez $3, mwmr_lock_ok 52 "mwmr_lock_delay: 45 "mwmr_lock_try: \n" 46 "ll $2, 0(%0) \n" /* $2 <= lock current value */ 47 "bnez $2, mwmr_lock_delay \n" /* retry after delay if lock busy */ 48 "li $3, 1 \n" /* $3 <= argument for sc */ 49 "sc $3, 0(%0) \n" /* try to get lock */ 50 "bnez $3, mwmr_lock_ok \n" /* exit if atomic */ 51 "mwmr_lock_delay: \n" 53 52 "move $4, %1 \n" /* $4 <= delay */ 54 53 "mwmr_lock_loop: \n" 55 "beqz $4, mwmr_lock_loop 56 "addi $4, $4, -1 57 "j mwmr_lock_try 58 "nop 59 "mwmr_lock_ok: 54 "beqz $4, mwmr_lock_loop \n" /* test end delay */ 55 "addi $4, $4, -1 \n" /* $4 <= $4 - 1 */ 56 "j mwmr_lock_try \n" /* retry ll */ 57 "nop \n" 58 "mwmr_lock_ok: \n" 60 59 : 61 60 :"r"(plock), "r"(delay) 62 61 :"$2", "$3", "$4"); 63 62 } 64 ////////////////////////////////////////////////////////////////////////////// 65 // nb_mwmr_write() 63 64 65 ////////////////////////////////////////////////////////////////////////////// 66 // nb_mwmr_write() 66 67 // This is a non-blocking function. 67 68 // The nitems parameter is the number of items to be transfered. … … 72 73 // the number of read items (it can be 0). 73 74 ////////////////////////////////////////////////////////////////////////////// 74 unsigned int nb_mwmr_write( mwmr_channel_t* mwmr, 75 unsigned int* buffer, 76 unsigned int nitems ) 77 { 78 unsigned int x; 79 unsigned int spaces; // number of empty slots (in words) 80 unsigned int nwords; // requested transfer length (in words) 81 unsigned int depth; // channel depth (in words) 82 unsigned int width; // channel width (in words) 83 unsigned int sts; // channel sts 84 unsigned int ptw; // channel ptw 85 86 if(nitems == 0) return 0; 75 unsigned int nb_mwmr_write(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 76 unsigned int x; 77 unsigned int spaces; // number of empty slots (in words) 78 unsigned int nwords; // requested transfer length (in words) 79 unsigned int depth; // channel depth (in words) 80 unsigned int width; // channel width (in words) 81 unsigned int sts; // channel sts 82 unsigned int ptw; // channel ptw 83 84 if (nitems == 0) { 85 return 0; 86 } 87 87 88 88 // get the lock 89 mwmr_lock_acquire( &mwmr->lock);89 mwmr_lock_acquire(&mwmr->lock); 90 90 91 91 // access fifo status 92 depth 93 width 94 sts 95 ptw 92 depth = mwmr->depth; 93 width = mwmr->width; 94 sts = mwmr->sts; 95 ptw = mwmr->ptw; 96 96 spaces = depth - sts; 97 97 nwords = width * nitems; 98 98 99 if( spaces >= nwords ) // transfer nitems, release lock and return 100 { 101 for ( x = 0 ; x < nwords ; x++ ) 102 { 99 if (spaces >= nwords) { // transfer nitems, release lock and return 100 for (x = 0; x < nwords; x++) { 103 101 mwmr->data[ptw] = buffer[x]; 104 if ( (ptw + 1) == depth ) ptw = 0; 105 else ptw = ptw + 1; 106 } 107 mwmr->sts = mwmr->sts + nwords; 108 mwmr->ptw = ptw; 102 if ((ptw + 1) == depth) { 103 ptw = 0; 104 } 105 else { 106 ptw = ptw + 1; 107 } 108 } 109 mwmr->sts = mwmr->sts + nwords; 110 mwmr->ptw = ptw; 109 111 mwmr->lock = 0; 110 112 return nitems; 111 113 } 112 113 else if ( spaces < width ) // release lock and return 114 { 114 else if (spaces < width) { 115 // release lock and return 115 116 mwmr->lock = 0; 116 117 return 0; 117 118 } 118 else // transfer as many items as possible, release lock and return 119 { 120 nwords = (spaces/width) * width; // integer number of items 121 for ( x = 0 ; x < nwords ; x++ ) 122 { 119 else { 120 // transfer as many items as possible, release lock and return 121 nwords = (spaces / width) * width; // integer number of items 122 for (x = 0; x < nwords; x++) { 123 123 mwmr->data[ptw] = buffer[x]; 124 if ( (ptw + 1) == depth ) ptw = 0; 125 else ptw = ptw + 1; 126 } 127 mwmr->sts = sts + nwords; 128 mwmr->ptw = ptw; 129 mwmr->lock = 0; 130 return (nwords/width); 124 if ((ptw + 1) == depth) { 125 ptw = 0; 126 } 127 else { 128 ptw = ptw + 1; 129 } 130 } 131 mwmr->sts = sts + nwords; 132 mwmr->ptw = ptw; 133 mwmr->lock = 0; 134 return (nwords / width); 131 135 } 132 136 } // end nb_mwmr_write() 133 137 134 ////////////////////////////////////////////////////////////////////////////// 135 // mwmr_write() 138 139 ////////////////////////////////////////////////////////////////////////////// 140 // mwmr_write() 136 141 // This blocking function returns only when the transfer is completed. 137 142 // The nitems parameter is the number of items to be transfered. … … 142 147 // after a random delay. 143 148 ////////////////////////////////////////////////////////////////////////////// 144 void mwmr_write( mwmr_channel_t* mwmr, 145 unsigned int* buffer, 146 unsigned int nitems ) 147 { 148 unsigned int x; 149 unsigned int spaces; // number of empty slots (in words) 150 unsigned int nwords; // requested transfer length (in words) 151 unsigned int depth; // channel depth (in words) 152 unsigned int width; // channel width (in words) 153 unsigned int sts; // channel sts 154 unsigned int ptw; // channel ptw 155 156 if(nitems == 0) return; 157 158 while(1) 159 { 149 void mwmr_write(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 150 unsigned int x; 151 unsigned int spaces; // number of empty slots (in words) 152 unsigned int nwords; // requested transfer length (in words) 153 unsigned int depth; // channel depth (in words) 154 unsigned int width; // channel width (in words) 155 unsigned int sts; // channel sts 156 unsigned int ptw; // channel ptw 157 158 if (nitems == 0) { 159 return; 160 } 161 162 while (1) { 160 163 // get the lock 161 164 mwmr_lock_acquire(&mwmr->lock); 162 165 163 166 // compute spaces and nwords 164 depth 165 width 166 sts 167 ptw 167 depth = mwmr->depth; 168 width = mwmr->width; 169 sts = mwmr->sts; 170 ptw = mwmr->ptw; 168 171 spaces = depth - sts; 169 172 nwords = width * nitems; 170 173 171 if( spaces >= nwords ) // write nwords, release lock and return 172 { 173 for ( x = 0 ; x < nwords ; x++ ) 174 { 174 if (spaces >= nwords) { 175 // write nwords, release lock and return 176 for (x = 0; x < nwords; x++) { 175 177 mwmr->data[ptw] = buffer[x]; 176 if ( (ptw + 1) == depth ) ptw = 0; 177 else ptw = ptw + 1; 178 } 179 mwmr->ptw = ptw; 180 mwmr->sts = sts + nwords; 178 if ((ptw + 1) == depth) { 179 ptw = 0; 180 } 181 else { 182 ptw = ptw + 1; 183 } 184 } 185 mwmr->ptw = ptw; 186 mwmr->sts = sts + nwords; 181 187 mwmr->lock = 0; 182 188 return; 183 189 } 184 else if ( spaces < width ) // release lock and retry after delay 185 { 186 mwmr->lock = 0; 187 for ( x = giet_rand()>>8 ; x > 0 ; x-- ) asm volatile ( "nop" ); 188 } 189 else // write as many items as possible, release lock and retry after delay 190 { 191 nwords = (spaces/width) * width; // integer number of items 192 for ( x = 0 ; x < nwords ; x++ ) 193 { 190 else if (spaces < width) { 191 // release lock and retry after delay 192 mwmr->lock = 0; 193 } 194 else { 195 // write as many items as possible, release lock and retry after delay 196 nwords = (spaces / width) * width; // integer number of items 197 for (x = 0; x < nwords; x++) { 194 198 mwmr->data[ptw] = buffer[x]; 195 if ( (ptw + 1) == depth ) ptw = 0; 196 else ptw = ptw + 1; 197 } 198 mwmr->sts = sts + nwords; 199 mwmr->ptw = ptw; 200 buffer = buffer + nwords; 201 nitems = nitems - (nwords/width); 202 mwmr->lock = 0; 203 } 204 // random delay before retry 205 for ( x = giet_rand()>>6 ; x > 0 ; x-- ) asm volatile ( "nop" ); 199 if ((ptw + 1) == depth) { 200 ptw = 0; 201 } 202 else { 203 ptw = ptw + 1; 204 } 205 } 206 mwmr->sts = sts + nwords; 207 mwmr->ptw = ptw; 208 buffer = buffer + nwords; 209 nitems = nitems - (nwords/width); 210 mwmr->lock = 0; 211 } 212 giet_context_switch(); 206 213 } 207 214 } // end mwmr_write() 208 215 209 ////////////////////////////////////////////////////////////////////////////// 210 // nb_mwmr_read() 216 217 ////////////////////////////////////////////////////////////////////////////// 218 // nb_mwmr_read() 211 219 // This is a non-blocking function. 212 220 // The nitems parameter is the number of items to be transfered. … … 217 225 // the number of read items (it can be 0). 218 226 ////////////////////////////////////////////////////////////////////////////// 219 unsigned int nb_mwmr_read( mwmr_channel_t* mwmr, 220 unsigned int* buffer, 221 unsigned int nitems ) 222 { 223 unsigned int x; 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 ptr; // channel ptr 229 230 if(nitems == 0) return 0; 227 unsigned int nb_mwmr_read(mwmr_channel_t * mwmr, unsigned int * buffer, unsigned int nitems) { 228 unsigned int x; 229 unsigned int nwords; // requested transfer length (in words) 230 unsigned int depth; // channel depth (in words) 231 unsigned int width; // channel width (in words) 232 unsigned int sts; // channel sts 233 unsigned int ptr; // channel ptr 234 235 if (nitems == 0) { 236 return 0; 237 } 231 238 232 239 // get the lock 233 mwmr_lock_acquire( &mwmr->lock);240 mwmr_lock_acquire(&mwmr->lock); 234 241 235 242 // access fifo status 236 depth 237 width 238 sts 239 ptr 243 depth = mwmr->depth; 244 width = mwmr->width; 245 sts = mwmr->sts; 246 ptr = mwmr->ptr; 240 247 nwords = width * nitems; 241 248 242 if( sts >= nwords ) // transfer nitems, release lock and return 243 { 244 for ( x = 0 ; x < nwords ; x++ ) 245 { 249 if (sts >= nwords) { 250 // transfer nitems, release lock and return 251 for (x = 0; x < nwords; x++) { 246 252 buffer[x] = mwmr->data[ptr]; 247 if ( (ptr + 1) == depth ) ptr = 0; 248 else ptr = ptr + 1; 249 } 250 mwmr->sts = mwmr->sts - nwords; 251 mwmr->ptr = 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; 252 262 mwmr->lock = 0; 253 263 return nitems; 254 264 } 255 256 else if ( sts < width ) // release lock and return 257 { 265 else if (sts < width) { 266 // release lock and return 258 267 mwmr->lock = 0; 259 268 return 0; 260 269 } 261 else // transfer as many items as possible, release lock and return 262 { 263 nwords = (sts/width) * width; // integer number of items 264 for ( x = 0 ; x < nwords ; x++ ) 265 { 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++) { 266 274 buffer[x] = mwmr->data[ptr]; 267 if ( (ptr + 1) == depth ) ptr = 0; 268 else ptr = ptr + 1; 269 } 270 mwmr->sts = sts - nwords; 271 mwmr->ptr = ptr; 272 mwmr->lock = 0; 273 return (nwords/width); 274 } 275 } // nb_mwmr_read() 276 277 ////////////////////////////////////////////////////////////////////////////// 278 // mwmr_read() 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() 279 292 // This blocking function returns only when the transfer is completed. 280 293 // The nitems parameter is the number of items to be transfered. … … 285 298 // after a random delay. 286 299 ////////////////////////////////////////////////////////////////////////////// 287 void mwmr_read( mwmr_channel_t* mwmr, 288 unsigned int* buffer, 289 unsigned int nitems ) 290 { 291 unsigned int x; 292 unsigned int nwords; // requested transfer length (in words) 293 unsigned int depth; // channel depth (in words) 294 unsigned int width; // channel width (in words) 295 unsigned int sts; // channel sts 296 unsigned int ptr; // channel ptr 297 298 if(nitems == 0) return; 299 300 while(1) 301 { 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) { 302 313 // get the lock 303 mwmr_lock_acquire( &mwmr->lock);314 mwmr_lock_acquire(&mwmr->lock); 304 315 305 316 // compute nwords 306 depth 307 width 308 sts 309 ptr 317 depth = mwmr->depth; 318 width = mwmr->width; 319 sts = mwmr->sts; 320 ptr = mwmr->ptr; 310 321 nwords = width * nitems; 311 322 312 if( sts >= nwords ) // read nwords, release lock and return 313 { 314 for ( x = 0 ; x < nwords ; x++ ) 315 { 323 if (sts >= nwords) { 324 // read nwords, release lock and return 325 for (x = 0; x < nwords; x++) { 316 326 buffer[x] = mwmr->data[ptr]; 317 if ( (ptr + 1) == depth ) ptr = 0; 318 else ptr = ptr + 1; 319 } 320 mwmr->sts = mwmr->sts - nwords; 321 mwmr->ptr = ptr; 327 if ((ptr + 1) == depth) { 328 ptr = 0; 329 } 330 else { 331 ptr = ptr + 1; 332 } 333 } 334 mwmr->sts = mwmr->sts - nwords; 335 mwmr->ptr = ptr; 322 336 mwmr->lock = 0; 323 337 return; 324 338 } 325 else if ( sts < width ) // release lock and retry after delay 326 { 327 mwmr->lock = 0; 328 for ( x = giet_rand()>>8 ; x > 0 ; x-- ) asm volatile ( "nop" ); 329 } 330 else // read as many items as possible, release lock and retry after delay 331 { 332 nwords = (sts/width) * width; // integer number of items 333 for ( x = 0 ; x < nwords ; x++ ) 334 { 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 344 nwords = (sts / width) * width; // integer number of items 345 for (x = 0; x < nwords; x++) { 335 346 buffer[x] = mwmr->data[ptr]; 336 if ( (ptr + 1) == depth ) ptr = 0; 337 else ptr = ptr + 1; 338 } 339 mwmr->sts = sts - nwords; 340 mwmr->ptr = ptr; 341 buffer = buffer + nwords; 342 nitems = nitems - (nwords/width); 343 mwmr->lock = 0; 344 } 345 // random delay before retry 346 for ( x = giet_rand()>>6 ; x > 0 ; x-- ) asm volatile ( "nop" ); 347 if ((ptr + 1) == depth) { 348 ptr = 0; 349 } 350 else { 351 ptr = ptr + 1; 352 } 353 } 354 mwmr->sts = sts - nwords; 355 mwmr->ptr = ptr; 356 buffer = buffer + nwords; 357 nitems = nitems - (nwords/width); 358 mwmr->lock = 0; 359 } 360 giet_context_switch(); 347 361 } 348 362 } // end mwmr_read() 349 363 350 364 365 // Local Variables: 366 // tab-width: 4 367 // c-basic-offset: 4 368 // c-file-offsets:((innamespace . 0)(inline-open . 0)) 369 // indent-tabs-mode: nil 370 // End: 371 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4 372
Note: See TracChangeset
for help on using the changeset viewer.