Changeset 744 for trunk/softs/giet_tsar/stdio.c
- Timestamp:
- Jul 10, 2014, 11:23:57 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/softs/giet_tsar/stdio.c
r743 r744 1 1 //////////////////////////////////////////////////////////////////////////////////////// 2 2 // File : stdio.c 3 // Written by Alain Greiner 4 // Date : janvier 2014 3 // Written by Alain Greiner 4 // Date : janvier 2014 5 5 // 6 6 // This file defines various functions that can be used by applications to access … … 112 112 // Memcopy taken from MutekH. 113 113 //////////////////////////////////////////////////////////////////////////////////////// 114 in_drivers void* _memcpy( void* _dst, 115 const void* _src, 114 in_drivers void* _memcpy( void* _dst, 115 const void* _src, 116 116 unsigned int size ) 117 117 { … … 120 120 if ( ! ((unsigned int)dst & 3) && ! ((unsigned int)src & 3) ) 121 121 { 122 while (size > 3) 122 while (size > 3) 123 123 { 124 124 *dst++ = *src++; … … 130 130 unsigned char *csrc = (unsigned char*)src; 131 131 132 while (size--) 132 while (size--) 133 133 { 134 134 *cdst++ = *csrc++; … … 141 141 in_drivers void _extended_memcpy( unsigned int dst_cluster, 142 142 unsigned int dst_address, 143 unsigned int src_cluster,144 143 unsigned int src_address, 145 144 unsigned int length ) … … 205 204 { 206 205 asm volatile( 207 "mfc0 $8, $12 \n" 206 "mfc0 $8, $12 \n" 208 207 "ori $8, $8, 1 \n" 209 208 "mtc0 $8, $12 \n" … … 260 259 261 260 //////////////////////////////////////////////////////////////////////////// 262 // This function makes a physical read access to a 32 bits word in memory, 261 // This function makes a physical read access to a 32 bits word in memory, 263 262 // after a temporary paddr extension. 264 263 //////////////////////////////////////////////////////////////////////////// … … 273 272 "mtc0 $3, $12 \n" /* IRQ disabled */ 274 273 275 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 274 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 276 275 "lw %0, 0(%1) \n" /* value <= *paddr */ 277 276 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ … … 285 284 } 286 285 //////////////////////////////////////////////////////////////////////////// 287 // This function makes a physical read access to a single byte in memory, 286 // This function makes a physical read access to a single byte in memory, 288 287 // after a temporary paddr extension. 289 288 //////////////////////////////////////////////////////////////////////////// … … 298 297 "mtc0 $3, $12 \n" /* IRQ disabled */ 299 298 300 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 299 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 301 300 "lb %0, 0(%1) \n" /* value <= *paddr */ 302 301 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ … … 310 309 } 311 310 //////////////////////////////////////////////////////////////////////////// 312 // This function makes a physical write access to a 32 bits word in memory, 311 // This function makes a physical write access to a 32 bits word in memory, 313 312 // after a temporary DTLB address extension. 314 313 //////////////////////////////////////////////////////////////////////////// 315 in_drivers void _word_extended_write( unsigned int cluster, 314 in_drivers void _word_extended_write( unsigned int cluster, 316 315 unsigned int address, 317 unsigned int word ) 316 unsigned int word ) 318 317 { 319 318 int sr = _sr_read(); … … 323 322 "mtc0 $3, $12 \n" /* IRQ disabled */ 324 323 325 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 324 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 326 325 "sw %0, 0(%1) \n" /* *paddr <= value */ 327 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 326 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 328 327 329 328 "sync \n" … … 335 334 } 336 335 //////////////////////////////////////////////////////////////////////////// 337 // This function makes a physical write access to single byte in memory, 336 // This function makes a physical write access to single byte in memory, 338 337 // after a temporary DTLB de-activation and address extension. 339 338 //////////////////////////////////////////////////////////////////////////// 340 in_drivers void _byte_extended_write( unsigned int cluster, 339 in_drivers void _byte_extended_write( unsigned int cluster, 341 340 unsigned int address, 342 unsigned char byte ) 341 unsigned char byte ) 343 342 { 344 343 int sr = _sr_read(); … … 348 347 "mtc0 $3, $12 \n" /* IRQ disabled */ 349 348 350 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 349 "mtc2 %2, $24 \n" /* PADDR_EXT <= msb */ 351 350 "sb %0, 0(%1) \n" /* *paddr <= value */ 352 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 351 "mtc2 $0, $24 \n" /* PADDR_EXT <= 0 */ 353 352 354 353 "sync \n" … … 361 360 362 361 /////////////////////////////////////////////////////////////////////////////////////// 363 // Exit (suicide) after printing message on TTY0 362 // Exit (suicide) after printing message on TTY0 364 363 /////////////////////////////////////////////////////////////////////////////////////// 365 364 in_drivers void _exit() … … 418 417 // - If there is only one terminal, it is supposed to be shared, and used by 419 418 // all processors: a lock must be taken before display. 420 // - If there is several terminals, and the number of processors is smaller 421 // than the number of terminals, there is one terminal per processor, but 419 // - If there is several terminals, and the number of processors is smaller 420 // than the number of terminals, there is one terminal per processor, but 422 421 // the TTY index is not equal to the proc_id, due to cluster indexing policy: 423 422 // proc_id = cluster_xy * NB_PROCS_MAX + local_id (with cluster_xy = x << Y_WIDTH + y) … … 434 433 // returns the number of characters that have been actually written. 435 434 /////////////////////////////////////////////////////////////////////////////////////// 436 in_drivers int _tty_write( char* buffer, 437 unsigned int length, 435 in_drivers int _tty_write( char* buffer, 436 unsigned int length, 438 437 unsigned int channel ) 439 438 { … … 464 463 // and returns 1 if the register is full. 465 464 /////////////////////////////////////////////////////////////////////////////////////// 466 in_drivers int _tty_read( char* buffer, 465 in_drivers int _tty_read( char* buffer, 467 466 unsigned int channel ) 468 467 { … … 493 492 // This function displays a 32 bits unsigned int as an hexa string on TTY0. 494 493 /////////////////////////////////////////////////////////////////////////////// 495 in_drivers void _tty_putx(unsigned int val) 494 in_drivers void _tty_putx(unsigned int val) 496 495 { 497 496 static const char HexaTab[] = "0123456789ABCDEF"; … … 503 502 buf[10] = 0; 504 503 505 for (c = 0; c < 8; c++) 506 { 504 for (c = 0; c < 8; c++) 505 { 507 506 buf[9 - c] = HexaTab[val & 0xF]; 508 507 val = val >> 4; … … 514 513 // This function displays a 32 bits unsigned int as a decimal string on TTY0. 515 514 /////////////////////////////////////////////////////////////////////////////// 516 in_drivers void _tty_putd( unsigned int val ) 515 in_drivers void _tty_putd( unsigned int val ) 517 516 { 518 517 static const char DecTab[] = "0123456789"; … … 523 522 buf[10] = 0; 524 523 525 for (i = 0; i < 10; i++) 526 { 527 if ((val != 0) || (i == 0)) 524 for (i = 0; i < 10; i++) 525 { 526 if ((val != 0) || (i == 0)) 528 527 { 529 528 buf[9 - i] = DecTab[val % 10]; 530 529 first = 9 - i; 531 530 } 532 else 531 else 533 532 { 534 533 break; … … 540 539 541 540 ////////////////////////////////////////////////////////////////////////////// 542 // This function try to take the hardwired lock protecting exclusive access 541 // This function try to take the hardwired lock protecting exclusive access 543 542 // to TTY terminal identified by the channel argument. 544 543 // It returns only when the lock has been successfully taken. … … 552 551 553 552 ////////////////////////////////////////////////////////////////////////////// 554 // This function releases the hardwired lock protecting exclusive access 553 // This function releases the hardwired lock protecting exclusive access 555 554 // to TTY terminal identified by the channel argument. 556 555 ////////////////////////////////////////////////////////////////////////////// … … 577 576 // check TTY channel 578 577 l = (proc_id % NB_PROCS_MAX); 579 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 578 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 580 579 y = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1); 581 580 channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l; … … 600 599 // The <DEL> character is interpreted, and previous characters can be 601 600 // cancelled. All others characters are ignored. 602 // When the <LF> or <CR> character is received, the string is converted 601 // When the <LF> or <CR> character is received, the string is converted 603 602 // to an unsigned int value. If the number of decimal digit is too large 604 603 // for the 32 bits range, the zero value is returned. … … 624 623 // check TTY channel 625 624 l = (proc_id % NB_PROCS_MAX); 626 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 625 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 627 626 y = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1); 628 627 channel = (x * Y_SIZE + y) * NB_PROCS_MAX + l; … … 702 701 703 702 // compute TTY channel : 704 // if the number of TTY channels is smaller 703 // if the number of TTY channels is smaller 705 704 // than the number of clusters, use TTY_0_0 706 705 // else, TTY channel <= cluster index … … 711 710 else 712 711 { 713 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 712 x = (proc_id / NB_PROCS_MAX) >> Y_WIDTH; 714 713 y = (proc_id / NB_PROCS_MAX) & ((1<<Y_WIDTH) - 1); 715 714 channel = (x * Y_SIZE + y); 716 715 } 717 716 718 // take the TTY lock 717 // take the TTY lock 719 718 _tty_get_lock( channel ); 720 719 721 720 printf_text: 722 721 723 while (*format) 722 while (*format) 724 723 { 725 724 unsigned int i; 726 725 for (i = 0; format[i] && format[i] != '%'; i++) 727 726 ; 728 if (i) 727 if (i) 729 728 { 730 729 _tty_write( format, i, channel ); 731 730 format += i; 732 731 } 733 if (*format == '%') 732 if (*format == '%') 734 733 { 735 734 format++; … … 762 761 break; 763 762 case ('d'): // decimal signed integer 764 if (val < 0) 763 if (val < 0) 765 764 { 766 765 val = -val; … … 768 767 } 769 768 case ('u'): // decimal unsigned integer 770 for( i=0 ; i<10 ; i++) 769 for( i=0 ; i<10 ; i++) 771 770 { 772 771 buf[9-i] = HexaTab[val % 10]; … … 778 777 case ('x'): // hexadecimal integer 779 778 _tty_write( "0x", 2, channel ); 780 for( i=0 ; i<8 ; i++) 779 for( i=0 ; i<8 ; i++) 781 780 { 782 781 buf[7-i] = HexaTab[val % 16U]; … … 858 857 ////////////////////////////////////////////////////////////////////////////////////////// 859 858 // The block size is 512 bytes. 860 // The functions below use the three variables _ioc_lock _ioc_done, 859 // The functions below use the three variables _ioc_lock _ioc_done, 861 860 // and _ioc_status for synchronisation. 862 861 // - As the IOC component can be used by several programs running in parallel, 863 862 // the _ioc_lock variable guaranties exclusive access to the device. 864 863 // The _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock. 865 // and set _ioc_lock to a non zero value. 864 // and set _ioc_lock to a non zero value. 866 865 // The _ioc_write() and _ioc_read() functions are blocking, polling the _ioc_lock 867 866 // variable until the device is available. … … 873 872 // reset the _ioc_done variable to zero, and releases the _ioc_lock variable. 874 873 /////////////////////////////////////////////////////////////////////////////////////// 875 // If USE_RAMDISK is set, we access a "virtual" block device controler implemented 874 // If USE_RAMDISK is set, we access a "virtual" block device controler implemented 876 875 // as a memory-mapped segment in cluster [0,0] at address seg_ramdisk_base. 877 876 // The tranfer being fully synchronous, the IOC interrupt is not activated. … … 879 878 880 879 /////////////////////////////////////////////////////////////////////////////////////// 881 // This blocking function is used by the _ioc_read() and _ioc_write() functions 880 // This blocking function is used by the _ioc_read() and _ioc_write() functions 882 881 // to get _ioc_lock using LL/SC. 883 882 /////////////////////////////////////////////////////////////////////////////////////// 884 883 in_drivers void _ioc_get_lock() 885 884 { 886 register unsigned int* plock = (unsigned int*)&_ioc_lock; 885 register unsigned int* plock = (unsigned int*)&_ioc_lock; 887 886 888 887 asm volatile ( … … 890 889 "ll $2, 0(%0) \n" // $2 <= _ioc_lock 891 890 "bnez $2, 1b \n" // retry if busy 892 "li $3, 1 \n" // prepare argument for sc 891 "li $3, 1 \n" // prepare argument for sc 893 892 "sc $3, 0(%0) \n" // try to set _ioc_busy 894 "beqz $3, 1b \n" // retry if not atomic 893 "beqz $3, 1b \n" // retry if not atomic 895 894 ::"r"(plock) :"$2","$3"); 896 895 } … … 903 902 // - ext : cluster index for the memory buffer 904 903 /////////////////////////////////////////////////////////////////////////////////////// 905 in_drivers void _ioc_write( size_t lba, 906 void* buffer, 904 in_drivers void _ioc_write( size_t lba, 905 void* buffer, 907 906 size_t count, 908 907 size_t ext ) … … 923 922 src_address, 924 923 count*512 ); 925 924 926 925 _ioc_status = BLOCK_DEVICE_WRITE_SUCCESS; 927 926 _ioc_done = 1; … … 946 945 // - ext : cluster index for the memory buffer 947 946 /////////////////////////////////////////////////////////////////////////////////////// 948 in_drivers void _ioc_read( size_t lba, 949 void* buffer, 947 in_drivers void _ioc_read( size_t lba, 948 void* buffer, 950 949 size_t count, 951 950 size_t ext ) … … 995 994 { 996 995 // waiting for completion 997 while (_ioc_done == 0) asm volatile("nop"); 998 996 while (_ioc_done == 0) asm volatile("nop"); 997 999 998 // reset synchronisation variables 1000 999 _ioc_done = 0; … … 1028 1027 // FRAME_BUFFER 1029 1028 ////////////////////////////////////////////////////////////////////////////////////// 1030 // The _fb_sync_write & _fb_sync_read functions use a memcpy strategy to implement 1029 // The _fb_sync_write & _fb_sync_read functions use a memcpy strategy to implement 1031 1030 // the transfer between a data buffer and the frame buffer. 1032 1031 // They are blocking until completion of the transfer. … … 1041 1040 // - ext : cluster_xy for the user buffer 1042 1041 ////////////////////////////////////////////////////////////////////////////////////// 1043 in_drivers void _fb_sync_write( unsigned int offset, 1044 unsigned int buffer, 1042 in_drivers void _fb_sync_write( unsigned int offset, 1043 unsigned int buffer, 1045 1044 unsigned int length, 1046 1045 unsigned int ext ) … … 1049 1048 unsigned int src_cluster = ext; 1050 1049 unsigned int dst_address = (unsigned int)&seg_fbf_base + offset; 1051 unsigned int dst_cluster = (X_IO << Y_WIDTH) | Y_IO; // cluster_xy for I/O 1052 1053 _extended_memcpy( dst_cluster, 1050 1051 _extended_memcpy( CLUSTER_IO, 1054 1052 dst_address, 1055 1053 src_cluster, … … 1066 1064 // - ext : cluster_xy for the user buffer 1067 1065 ////////////////////////////////////////////////////////////////////////////////////// 1068 in_drivers void _fb_sync_read( unsigned int offset, 1069 unsigned int buffer, 1066 in_drivers void _fb_sync_read( unsigned int offset, 1067 unsigned int buffer, 1070 1068 unsigned int length, 1071 1069 unsigned int ext ) … … 1074 1072 unsigned int dst_cluster = ext; 1075 1073 unsigned int src_address = (unsigned int)&seg_fbf_base + offset; 1076 unsigned int src_cluster = (X_IO << Y_WIDTH) | Y_IO; // cluster_xy for I/O1077 1074 1078 1075 _extended_memcpy( dst_cluster, 1079 1076 dst_address, 1080 src_cluster,1077 CLUSTER_IO, 1081 1078 src_address, 1082 1079 length ); … … 1093 1090 //int* mmc_address = (int*)&seg_mmc_base; 1094 1091 unsigned int cluster_xy = _procid() / NB_PROCS_MAX; 1095 1092 1096 1093 _tty_printf( "WRITE ERROR signaled by Memory Cache in cluster %x\n", cluster_xy ); 1097 1094 } 1098 1095 1099 1096 /////////////////////////////////////////////////////////////////////////////////////// 1100 // Release a software spin-lock 1097 // Release a software spin-lock 1101 1098 /////////////////////////////////////////////////////////////////////////////////////// 1102 1099 in_drivers void _release_lock(size_t index) 1103 1100 1104 1101 { 1105 if( index >= NB_LOCKS ) 1102 if( index >= NB_LOCKS ) 1106 1103 { 1107 1104 _tty_get_lock( 0 ); … … 1110 1107 _exit(); 1111 1108 } 1112 1109 1113 1110 _spin_lock[index] = 0; 1114 1111 } … … 1132 1129 1133 1130 register int delay = ((_proctime() +_procid()) & 0xF) << 4; 1134 register int * plock = (int *) &_spin_lock[index]; 1131 register int * plock = (int *) &_spin_lock[index]; 1135 1132 1136 1133 asm volatile ("_locks_llsc: \n" 1137 1134 "ll $2, 0(%0) \n" // $2 <= _locks_lock 1138 1135 "bnez $2, _locks_delay \n" // random delay if busy 1139 "li $3, 1 \n" // prepare argument for sc 1136 "li $3, 1 \n" // prepare argument for sc 1140 1137 "sc $3, 0(%0) \n" // try to set _locks_busy 1141 "bnez $3, _locks_ok \n" // exit if atomic 1138 "bnez $3, _locks_ok \n" // exit if atomic 1142 1139 "_locks_delay: \n" 1143 1140 "move $4, %1 \n" // $4 <= delay … … 1155 1152 // - barrier_count[index] <= N 1156 1153 // - barrier_lock[index] <= 0 1157 // All tasks try to initialize the barrier, but the initialisation 1154 // All tasks try to initialize the barrier, but the initialisation 1158 1155 // is done by only one task, using LL/SC instructions. 1159 // This cooperative initialisation is questionnable, 1156 // This cooperative initialisation is questionnable, 1160 1157 // because the barrier can ony be initialised once... 1161 1158 ////////////////////////////////////////////////////////////////////////////////////// … … 1176 1173 // parallel initialisation using atomic instructions LL/SC 1177 1174 asm volatile ("_barrier_init_test: \n" 1178 "ll $2, 0(%0) \n" // read barrier_value 1175 "ll $2, 0(%0) \n" // read barrier_value 1179 1176 "bnez $2, _barrier_init_done \n" 1180 1177 "move $3, %3 \n" 1181 1178 "sc $3, 0(%0) \n" // try to write barrier_value 1182 1179 "beqz $3, _barrier_init_test \n" 1183 "move $3, %3 \n" 1180 "move $3, %3 \n" 1184 1181 "sw $3, 0(%1) \n" // barrier_count <= barrier_value 1185 "move $3, $0 \n" // 1182 "move $3, $0 \n" // 1186 1183 "sw $3, 0(%2) \n" // barrier_lock <= 0 1187 1184 "_barrier_init_done: \n" … … 1190 1187 1191 1188 ////////////////////////////////////////////////////////////////////////////////////// 1192 // This blocking function uses a busy_wait technics (on the barrier_lock value), 1193 // because the GIET does not support dynamic scheduling/descheduling of tasks. 1189 // This blocking function uses a busy_wait technics (on the barrier_lock value), 1190 // because the GIET does not support dynamic scheduling/descheduling of tasks. 1194 1191 // The barrier state is actually defined by two variables: 1195 1192 // _barrier_count[index] define the number of particpants that are waiting 1196 // _barrier_lock[index] define the bool variable whose value is polled 1193 // _barrier_lock[index] define the bool variable whose value is polled 1197 1194 // The last participant change the value of _barrier_lock[index] to release the barrier... 1198 1195 // There is at most 16 independant barriers, and an error is returned … … 1201 1198 in_drivers void _barrier_wait(unsigned int index) 1202 1199 { 1203 register int* pcount = (int*)&_barrier_count[index]; 1200 register int* pcount = (int*)&_barrier_count[index]; 1204 1201 register int count; 1205 int lock = _barrier_lock[index]; 1202 int lock = _barrier_lock[index]; 1206 1203 1207 1204 if ( index >= NB_BARRIERS ) … … 1212 1209 _exit(); 1213 1210 } 1214 1211 1215 1212 // parallel decrement _barrier_count[index] using atomic instructions LL/SC 1216 1213 // input : pointer on _barrier_count[index] … … 1238 1235 while ( lock == _barrier_lock[index] ); 1239 1236 } 1240 } 1237 } 1241 1238 1242 1239
Note: See TracChangeset
for help on using the changeset viewer.