Changeset 399 for soft/giet_vm/giet_common/utils.c
- Timestamp:
- Aug 12, 2014, 6:39:26 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
soft/giet_vm/giet_common/utils.c
r378 r399 22 22 extern static_scheduler_t* _schedulers[NB_PROCS_MAX<<(X_WIDTH+Y_WIDTH)]; 23 23 24 /////////////////////////////////////////////////////////////////////////////////// 25 // This function implements a pseudo-random delay. 26 // The val argument define approximately an exponentially increasing mean delay, 27 // and should not be larger than 32. 28 /////////////////////////////////////////////////////////////////////////////////// 29 void _random_wait( unsigned int val ) 30 { 31 unsigned int mask = (1<<(val&0x1F))-1; 32 unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask; 33 asm volatile( "move $3, %0 \n" 34 "loop_nic_completed: \n" 35 "addi $3, $3, -1 \n" 36 "bnez $3, loop_nic_completed \n" 37 "nop \n" 38 : 39 : "r" (delay) 40 : "$3" ); 41 } 42 /////////////////////////////////////////////////////////////////////////////////// 43 // Copy a source memory buffer content to a dest memory buffer (size bytes) 44 // Code taken from MutekH. 45 /////////////////////////////////////////////////////////////////////////////////// 46 void* memcpy( void* dest, // dest buffer vbase 47 const void* source, // source buffer vbase 48 unsigned int size ) // bytes 49 { 50 unsigned int* idst = (unsigned int*)dest; 51 unsigned int* isrc = (unsigned int*)source; 52 53 // word-by-word copy 54 if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3)) 55 { 56 while (size > 3) 57 { 58 *idst++ = *isrc++; 59 size -= 4; 60 } 61 } 62 63 unsigned char* cdst = (unsigned char*)dest; 64 unsigned char* csrc = (unsigned char*)source; 65 66 /* byte-by-byte copy */ 67 while (size--) 68 { 69 *cdst++ = *csrc++; 70 } 71 return dest; 72 } 73 ////////////////////////////////////////////////////////////////////////////////// 74 // Fill a byte string with a byte value. 75 ////////////////////////////////////////////////////////////////////////////////// 76 void * memset( void* dest, 77 int value, 78 unsigned int count ) 79 { 80 // word-by-word copy 81 unsigned int* idst = dest; 82 unsigned int data = (((unsigned char)value) ) | 83 (((unsigned char)value) << 8) | 84 (((unsigned char)value) << 16) | 85 (((unsigned char)value) << 24) ; 86 87 if ( ! ((unsigned int)idst & 3) ) 88 { 89 while ( count > 3 ) 90 { 91 *idst++ = data; 92 count -= 4; 93 } 94 } 95 96 // byte-by-byte copy 97 unsigned char* cdst = dest; 98 while (count--) 99 { 100 *cdst++ = (unsigned char)value; 101 } 102 return dest; 103 } 104 105 ////////////////////////////////////////////////////////////////////////////////// 106 // This function implements an interactive break for debug. 107 // Execution continue when typing any character on TTY0. 108 // The "str" argument is supposed to indicate the break location. 109 ////////////////////////////////////////////////////////////////////////////////// 110 void _break( char* string ) 111 { 112 char byte; 113 114 _printf("\n[GIET DEBUG] break from %s / continue ?\n", string ); 115 _getc( &byte ); 116 } 117 118 ////////////////////////////////////////////////////////////////////////////////// 119 // Processor suicide: infinite loop 120 ////////////////////////////////////////////////////////////////////////////////// 121 __attribute__((noreturn)) 122 void _exit() 123 { 124 unsigned int procid = _get_procid(); 125 unsigned int lpid = procid % NB_PROCS_MAX; 126 unsigned int cluster_xy = procid / NB_PROCS_MAX; 127 unsigned int x = cluster_xy >> Y_WIDTH; 128 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 129 130 131 _printf("\n[GIET PANIC] processor[%d,%d,%d] suicide...\n", x, y, lpid ); 132 133 while (1) { asm volatile ("nop"); } 134 } 135 /////////////////////////////////////////////////////////////////////////////////// 136 // CP0 and CP2 registers access functions 24 25 /////////////////////////////////////////////////////////////////////////////////// 26 // CP0 registers access functions 137 27 /////////////////////////////////////////////////////////////////////////////////// 138 28 … … 149 39 } 150 40 /////////////////////////////////////////////////////////////////////////////////// 151 // Returns PTPR register content.152 ///////////////////////////////////////////////////////////////////////////////////153 unsigned int _get_mmu_ptpr()154 {155 unsigned int ret;156 asm volatile( "mfc2 %0, $0 \n"157 : "=r"(ret) );158 return ret;159 }160 ///////////////////////////////////////////////////////////////////////////////////161 // Returns MODE register content.162 ///////////////////////////////////////////////////////////////////////////////////163 unsigned int _get_mmu_mode()164 {165 unsigned int ret;166 asm volatile( "mfc2 %0, $1 \n"167 : "=r"(ret) );168 return ret;169 }170 ///////////////////////////////////////////////////////////////////////////////////171 41 // Returns EPC register content. 172 42 /////////////////////////////////////////////////////////////////////////////////// … … 238 108 return ret; 239 109 } 240 //////////////////////////////////////////////////////////////////////////////241 // Returns index of the currently running task from the processor scheduler.242 //////////////////////////////////////////////////////////////////////////////243 unsigned int _get_current_task_id()244 {245 static_scheduler_t * psched = (static_scheduler_t *) _get_sched();246 return (unsigned int) (psched->current);247 }248 249 110 ////////////////////////////////////////////////////////////////////////////// 250 111 // Save SR value into save_sr_ptr variable and disable IRQs. … … 262 123 *save_sr_ptr = sr; 263 124 } 264 //////////////////////////////////////////////////////////////////////////////265 // Enables IRQs266 //////////////////////////////////////////////////////////////////////////////267 void _it_enable()268 {269 asm volatile( "li $3, 0x00000001 \n"270 "mfc0 $4, $12 \n"271 "or $3, $3, $4 \n"272 "mtc0 $3, $12 \n"273 ::: "$3", "$4", "memory" );274 }275 125 276 126 ////////////////////////////////////////////////////////////////////////////// … … 287 137 288 138 ////////////////////////////////////////////////////////////////////////////// 139 // This function set a new value in CP0 SCHED register. 140 // (virtual base address of the processor scheduler). 141 ////////////////////////////////////////////////////////////////////////////// 142 void _set_sched(unsigned int val) 143 { 144 asm volatile ( "mtc0 %0, $4, 2 \n" 145 : 146 :"r" (val) ); 147 } 148 149 /////////////////////////////////////////////////////////////////////////////////// 150 // CP2 registers access functions 151 /////////////////////////////////////////////////////////////////////////////////// 152 153 /////////////////////////////////////////////////////////////////////////////////// 154 // Returns PTPR register content. 155 /////////////////////////////////////////////////////////////////////////////////// 156 unsigned int _get_mmu_ptpr() 157 { 158 unsigned int ret; 159 asm volatile( "mfc2 %0, $0 \n" 160 : "=r"(ret) ); 161 return ret; 162 } 163 /////////////////////////////////////////////////////////////////////////////////// 164 // Returns MODE register content. 165 /////////////////////////////////////////////////////////////////////////////////// 166 unsigned int _get_mmu_mode() 167 { 168 unsigned int ret; 169 asm volatile( "mfc2 %0, $1 \n" 170 : "=r"(ret) ); 171 return ret; 172 } 173 ////////////////////////////////////////////////////////////////////////////// 289 174 // This function set a new value for the MMU PTPR register. 290 175 ////////////////////////////////////////////////////////////////////////////// … … 305 190 :"r" (val) 306 191 :"memory" ); 307 }308 //////////////////////////////////////////////////////////////////////////////309 // This function set a new value in CP0 SCHED register.310 // (virtual base address of the processor scheduler).311 //////////////////////////////////////////////////////////////////////////////312 void _set_sched(unsigned int val)313 {314 asm volatile ( "mtc0 %0, $4, 2 \n"315 :316 :"r" (val) );317 192 } 318 193 … … 355 230 //////////////////////////////////////////////////////////////////////////// 356 231 void _physical_write( unsigned long long paddr, 357 unsigned int value )232 unsigned int value ) 358 233 { 359 234 unsigned int lsb = (unsigned int)paddr; … … 419 294 //////////////////////////////////////////////////////////////////////////// 420 295 void _physical_write_ull( unsigned long long paddr, 421 296 unsigned long long value ) 422 297 { 423 298 unsigned int addr_lsb = (unsigned int)paddr; … … 450 325 // This function makes a memcpy from a source buffer to a destination buffer 451 326 // using physical addresses, after a temporary DTLB de-activation. 452 // source and destination buffers must be aligned, and size must be327 // source and destination buffers must be word aligned, and size must be 453 328 // multiple of 4 bytes. 454 329 /////////////////////////////////////////////////////////////////////////////////// 455 330 void _physical_memcpy( unsigned long long dst_paddr, // dest buffer paddr 456 457 331 unsigned long long src_paddr, // source buffer paddr 332 unsigned int size ) // bytes 458 333 { 459 334 // check alignment constraints … … 509 384 /////////////////////////////////////////////////////////////////////////////////// 510 385 void _io_extended_write( unsigned int* vaddr, 511 386 unsigned int value ) 512 387 { 513 388 unsigned long long paddr; … … 892 767 } 893 768 894 /////////////////////////////////////////////////////////////////////////////////// 895 // Compare two strings s1 & s2 (no more than n characters) 896 /////////////////////////////////////////////////////////////////////////////////// 897 unsigned int _strncmp( const char * s1, 898 const char * s2, 899 unsigned int n ) 900 { 901 unsigned int i; 902 for (i = 0; i < n; i++) 903 { 904 if (s1[i] != s2[i]) return 1; 905 if (s1[i] == 0) break; 906 } 907 return 0; 908 } 909 910 /////////////////////////////////////////////////////////////////////////////////// 911 // Copy source string to dest string 912 /////////////////////////////////////////////////////////////////////////////////// 913 char* _strcpy( char* dest, char* source ) 914 { 915 if (!dest || !source) return dest; 916 917 while (*source) 918 *(dest++) = *(source++); 919 920 return dest; 921 } 922 923 /////////////////////////////////////////////////////////////////////////////////// 924 // Invalidate all data cache lines corresponding to a memory 925 // buffer (identified by an address and a size). 926 // TODO This should be replaced by a write to the CP2 MMU_DCACHE_INVAL 927 // register, to be more processor independant. 928 /////////////////////////////////////////////////////////////////////////////////// 929 void _dcache_buf_invalidate( void * buffer, 930 unsigned int size) 931 { 932 unsigned int i; 933 unsigned int tmp; 934 unsigned int line_size; 935 936 // compute data cache line size based on config register (bits 12:10) 937 asm volatile( 938 "mfc0 %0, $16, 1" 939 : "=r" (tmp) ); 940 tmp = ((tmp >> 10) & 0x7); 941 line_size = 2 << tmp; 942 943 // iterate on cache lines 944 for (i = 0; i < size; i += line_size) 945 { 946 asm volatile( 947 " cache %0, %1" 948 : :"i" (0x11), "R" (*((unsigned char *) buffer + i)) ); 949 } 950 } 951 769 770 ////////////////////////////////////////////////////////////////////////////// 771 // Scheduler and tasks context access functions 772 ////////////////////////////////////////////////////////////////////////////// 773 774 ////////////////////////////////////////////////////////////////////////////// 775 // Returns index of the currently running task from the processor scheduler. 776 ////////////////////////////////////////////////////////////////////////////// 777 unsigned int _get_current_task_id() 778 { 779 static_scheduler_t * psched = (static_scheduler_t *) _get_sched(); 780 return (unsigned int) (psched->current); 781 } 952 782 //////////////////////////////////////////////////////////////////////////////////// 953 783 // This function returns the content of a context slot 954 // for a nytask identified by the ltid argument (local task index),784 // for a task identified by the ltid argument (local task index), 955 785 // and the gpid argument (global processor index) 956 786 //////////////////////////////////////////////////////////////////////////////////// … … 962 792 return psched->context[ltid][slot]; 963 793 } 964 965 794 //////////////////////////////////////////////////////////////////////////////////// 966 795 // This function updates the content of a context slot … … 976 805 psched->context[ltid][slot] = value; 977 806 } 978 979 807 //////////////////////////////////////////////////////////////////////////////////// 980 808 // This function returns the content of a context slot … … 987 815 return psched->context[task_id][slot]; 988 816 } 989 990 817 //////////////////////////////////////////////////////////////////////////////////// 991 818 // This function updates the content of a context slot for the running task. … … 998 825 psched->context[task_id][slot] = value; 999 826 } 1000 1001 ///////////////////////////////////////////////////////////////////////////////////1002 // This function returns the information associated to a heap : vaddr and length.1003 // - If (x < X_SIZE) and (y < Y_SIZE), it return the heap associated to any task1004 // running in cluster(x,y).1005 // - Else, it return the heap associated to the calling task.1006 // It uses the global task index (CTX_GTID_ID, unique for each giet task) and the1007 // vspace index (CTX_VSID_ID), that are defined in the calling task context1008 // to find the vobj_id containing the heap.1009 // Return 0 if success. Return non zero if not found.1010 ///////////////////////////////////////////////////////////////////////////////////1011 unsigned int _heap_info( unsigned int* vaddr,1012 unsigned int* length,1013 unsigned int x,1014 unsigned int y )1015 {1016 mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;1017 mapping_task_t * tasks = _get_task_base(header);1018 mapping_vobj_t * vobjs = _get_vobj_base(header);1019 mapping_vspace_t * vspaces = _get_vspace_base(header);1020 1021 unsigned int task_id;1022 unsigned int vspace_id;1023 unsigned int vobj_id = 0xFFFFFFFF;1024 1025 // searching the heap vobj_id1026 if ( (x < X_SIZE) && (y < Y_SIZE) ) // searching a task in cluster(x,y)1027 {1028 // get vspace global index1029 vspace_id = _get_context_slot(CTX_VSID_ID);1030 1031 // scan all tasks in vspace1032 unsigned int min = vspaces[vspace_id].task_offset ;1033 unsigned int max = min + vspaces[vspace_id].tasks ;1034 for ( task_id = min ; task_id < max ; task_id++ )1035 {1036 if ( tasks[task_id].clusterid == (x * Y_SIZE + y) )1037 {1038 vobj_id = tasks[task_id].heap_vobj_id;1039 if ( vobj_id != 0xFFFFFFFF ) break;1040 }1041 }1042 }1043 else // searching in the calling task1044 {1045 task_id = _get_context_slot(CTX_GTID_ID);1046 vobj_id = tasks[task_id].heap_vobj_id;1047 }1048 1049 // analysing the vobj_id1050 if ( vobj_id != 0xFFFFFFFF )1051 {1052 *vaddr = vobjs[vobj_id].vaddr;1053 *length = vobjs[vobj_id].length;1054 return 0;1055 }1056 else1057 {1058 *vaddr = 0;1059 *length = 0;1060 return 1;1061 }1062 } // end _heap_info()1063 827 1064 828 ///////////////////////////////////////////////////////////////////////////// … … 1186 950 } 1187 951 952 /////////////////////////////////////////////////////////////////////////////////// 953 // Miscelaneous functions 954 /////////////////////////////////////////////////////////////////////////////////// 955 956 /////////////////////////////////////////////////////////////////////////////////// 957 // This function implements a pseudo-random delay. 958 // The val argument define approximately an exponentially increasing mean delay, 959 // and should not be larger than 32. 960 /////////////////////////////////////////////////////////////////////////////////// 961 void _random_wait( unsigned int val ) 962 { 963 unsigned int mask = (1<<(val&0x1F))-1; 964 unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask; 965 asm volatile( "move $3, %0 \n" 966 "loop_nic_completed: \n" 967 "addi $3, $3, -1 \n" 968 "bnez $3, loop_nic_completed \n" 969 "nop \n" 970 : 971 : "r" (delay) 972 : "$3" ); 973 } 974 ////////////////////////////////////////////////////////////////////////////////// 975 // This function implements an interactive break for debug. 976 // Execution continue when typing any character on TTY0. 977 // The "str" argument is supposed to indicate the break location. 978 ////////////////////////////////////////////////////////////////////////////////// 979 void _break( char* string ) 980 { 981 char byte; 982 983 _printf("\n[GIET DEBUG] break from %s / continue ?\n", string ); 984 _getc( &byte ); 985 } 986 987 ////////////////////////////////////////////////////////////////////////////////// 988 // Processor suicide: infinite loop 989 ////////////////////////////////////////////////////////////////////////////////// 990 __attribute__((noreturn)) 991 void _exit() 992 { 993 unsigned int procid = _get_procid(); 994 unsigned int lpid = procid % NB_PROCS_MAX; 995 unsigned int cluster_xy = procid / NB_PROCS_MAX; 996 unsigned int x = cluster_xy >> Y_WIDTH; 997 unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1); 998 999 1000 _printf("\n[GIET PANIC] processor[%d,%d,%d] suicide...\n", x, y, lpid ); 1001 1002 while (1) { asm volatile ("nop"); } 1003 } 1004 /////////////////////////////////////////////////////////////////////////////////// 1005 // Compare two strings s1 & s2 (no more than n characters) 1006 /////////////////////////////////////////////////////////////////////////////////// 1007 unsigned int _strncmp( const char * s1, 1008 const char * s2, 1009 unsigned int n ) 1010 { 1011 unsigned int i; 1012 for (i = 0; i < n; i++) 1013 { 1014 if (s1[i] != s2[i]) return 1; 1015 if (s1[i] == 0) break; 1016 } 1017 return 0; 1018 } 1019 1020 /////////////////////////////////////////////////////////////////////////////////// 1021 // Copy source string to dest string 1022 /////////////////////////////////////////////////////////////////////////////////// 1023 char* _strcpy( char* dest, char* source ) 1024 { 1025 if (!dest || !source) return dest; 1026 1027 while (*source) 1028 *(dest++) = *(source++); 1029 1030 return dest; 1031 } 1032 1033 /////////////////////////////////////////////////////////////////////////////////// 1034 // Invalidate all data cache lines corresponding to a memory 1035 // buffer (identified by an address and a size). 1036 // TODO This should be replaced by a write to the CP2 MMU_DCACHE_INVAL 1037 // register, to be more processor independant. 1038 /////////////////////////////////////////////////////////////////////////////////// 1039 void _dcache_buf_invalidate( void * buffer, 1040 unsigned int size) 1041 { 1042 unsigned int i; 1043 unsigned int tmp; 1044 unsigned int line_size; 1045 1046 // compute data cache line size based on config register (bits 12:10) 1047 asm volatile( 1048 "mfc0 %0, $16, 1" 1049 : "=r" (tmp) ); 1050 tmp = ((tmp >> 10) & 0x7); 1051 line_size = 2 << tmp; 1052 1053 // iterate on cache lines 1054 for (i = 0; i < size; i += line_size) 1055 { 1056 asm volatile( 1057 " cache %0, %1" 1058 : :"i" (0x11), "R" (*((unsigned char *) buffer + i)) ); 1059 } 1060 } 1061 /////////////////////////////////////////////////////////////////////////////////// 1062 // This function returns the information associated to a heap : vaddr and length. 1063 // - If (x < X_SIZE) and (y < Y_SIZE), it return the heap associated to any task 1064 // running in cluster(x,y). 1065 // - Else, it return the heap associated to the calling task. 1066 // It uses the global task index (CTX_GTID_ID, unique for each giet task) and the 1067 // vspace index (CTX_VSID_ID), that are defined in the calling task context 1068 // to find the vobj_id containing the heap. 1069 // Return 0 if success. Return non zero if not found. 1070 /////////////////////////////////////////////////////////////////////////////////// 1071 unsigned int _heap_info( unsigned int* vaddr, 1072 unsigned int* length, 1073 unsigned int x, 1074 unsigned int y ) 1075 { 1076 mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE; 1077 mapping_task_t * tasks = _get_task_base(header); 1078 mapping_vobj_t * vobjs = _get_vobj_base(header); 1079 mapping_vspace_t * vspaces = _get_vspace_base(header); 1080 1081 unsigned int task_id; 1082 unsigned int vspace_id; 1083 unsigned int vobj_id = 0xFFFFFFFF; 1084 1085 // searching the heap vobj_id 1086 if ( (x < X_SIZE) && (y < Y_SIZE) ) // searching a task in cluster(x,y) 1087 { 1088 // get vspace global index 1089 vspace_id = _get_context_slot(CTX_VSID_ID); 1090 1091 // scan all tasks in vspace 1092 unsigned int min = vspaces[vspace_id].task_offset ; 1093 unsigned int max = min + vspaces[vspace_id].tasks ; 1094 for ( task_id = min ; task_id < max ; task_id++ ) 1095 { 1096 if ( tasks[task_id].clusterid == (x * Y_SIZE + y) ) 1097 { 1098 vobj_id = tasks[task_id].heap_vobj_id; 1099 if ( vobj_id != 0xFFFFFFFF ) break; 1100 } 1101 } 1102 } 1103 else // searching in the calling task 1104 { 1105 task_id = _get_context_slot(CTX_GTID_ID); 1106 vobj_id = tasks[task_id].heap_vobj_id; 1107 } 1108 1109 // analysing the vobj_id 1110 if ( vobj_id != 0xFFFFFFFF ) 1111 { 1112 *vaddr = vobjs[vobj_id].vaddr; 1113 *length = vobjs[vobj_id].length; 1114 return 0; 1115 } 1116 else 1117 { 1118 *vaddr = 0; 1119 *length = 0; 1120 return 1; 1121 } 1122 } // end _heap_info() 1123 1124 1125 /////////////////////////////////////////////////////////////////////////////////// 1126 // Required by GCC 1127 /////////////////////////////////////////////////////////////////////////////////// 1128 1129 /////////////////////////////////////////////////////////////////////////////////// 1130 // Copy a source memory buffer content to a dest memory buffer (size bytes) 1131 // Code taken from MutekH. 1132 /////////////////////////////////////////////////////////////////////////////////// 1133 void* memcpy( void* dest, // dest buffer vbase 1134 const void* source, // source buffer vbase 1135 unsigned int size ) // bytes 1136 { 1137 unsigned int* idst = (unsigned int*)dest; 1138 unsigned int* isrc = (unsigned int*)source; 1139 1140 // word-by-word copy 1141 if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3)) 1142 { 1143 while (size > 3) 1144 { 1145 *idst++ = *isrc++; 1146 size -= 4; 1147 } 1148 } 1149 1150 unsigned char* cdst = (unsigned char*)dest; 1151 unsigned char* csrc = (unsigned char*)source; 1152 1153 /* byte-by-byte copy */ 1154 while (size--) 1155 { 1156 *cdst++ = *csrc++; 1157 } 1158 return dest; 1159 } 1160 ////////////////////////////////////////////////////////////////////////////////// 1161 // Fill a byte string with a byte value. 1162 ////////////////////////////////////////////////////////////////////////////////// 1163 void * memset( void* dest, 1164 int value, 1165 unsigned int count ) 1166 { 1167 // word-by-word copy 1168 unsigned int* idst = dest; 1169 unsigned int data = (((unsigned char)value) ) | 1170 (((unsigned char)value) << 8) | 1171 (((unsigned char)value) << 16) | 1172 (((unsigned char)value) << 24) ; 1173 1174 if ( ! ((unsigned int)idst & 3) ) 1175 { 1176 while ( count > 3 ) 1177 { 1178 *idst++ = data; 1179 count -= 4; 1180 } 1181 } 1182 1183 // byte-by-byte copy 1184 unsigned char* cdst = dest; 1185 while (count--) 1186 { 1187 *cdst++ = (unsigned char)value; 1188 } 1189 return dest; 1190 } 1191 1192 1188 1193 // Local Variables: 1189 1194 // tab-width: 4
Note: See TracChangeset
for help on using the changeset viewer.