25
25
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
26
*****************************************************************************/
27
27
28
+ #include <stdlib.h>
28
29
#include <string.h>
29
30
#ifdef __APPLE__
30
31
#include <sys/sysctl.h>
@@ -33,6 +34,20 @@ size_t length=sizeof(value);
33
34
int64_t value64 ;
34
35
size_t length64 = sizeof (value64 );
35
36
#endif
37
+ #if (defined OS_LINUX || defined OS_ANDROID )
38
+ #include <asm/hwcap.h>
39
+ #include <sys/auxv.h>
40
+ #ifndef HWCAP_CPUID
41
+ #define HWCAP_CPUID (1 << 11)
42
+ #endif
43
+ #ifndef HWCAP_SVE
44
+ #define HWCAP_SVE (1 << 22)
45
+ #endif
46
+
47
+ #define get_cpu_ftr (id , var ) ({ \
48
+ __asm__ __volatile__ ("mrs %0, "#id : "=r" (var)); \
49
+ })
50
+ #endif
36
51
37
52
#define CPU_UNKNOWN 0
38
53
#define CPU_ARMV8 1
@@ -42,11 +57,9 @@ size_t length64=sizeof(value64);
42
57
#define CPU_CORTEXA57 3
43
58
#define CPU_CORTEXA72 4
44
59
#define CPU_CORTEXA73 5
45
- #define CPU_CORTEXA76 23
46
60
#define CPU_NEOVERSEN1 11
47
61
#define CPU_NEOVERSEV1 16
48
62
#define CPU_NEOVERSEN2 17
49
- #define CPU_NEOVERSEV2 24
50
63
#define CPU_CORTEXX1 18
51
64
#define CPU_CORTEXX2 19
52
65
#define CPU_CORTEXA510 20
@@ -91,9 +104,7 @@ static char *cpuname[] = {
91
104
"CORTEXX2" ,
92
105
"CORTEXA510" ,
93
106
"CORTEXA710" ,
94
- "FT2000" ,
95
- "CORTEXA76" ,
96
- "NEOVERSEV2"
107
+ "FT2000"
97
108
};
98
109
99
110
static char * cpuname_lower [] = {
@@ -119,15 +130,17 @@ static char *cpuname_lower[] = {
119
130
"cortexx2" ,
120
131
"cortexa510" ,
121
132
"cortexa710" ,
122
- "ft2000" ,
123
- "cortexa76" ,
124
- "neoversev2"
133
+ "ft2000"
125
134
};
126
135
136
+ static int cpulowperf = 0 ;
137
+ static int cpumidperf = 0 ;
138
+ static int cpuhiperf = 0 ;
139
+
127
140
int get_feature (char * search )
128
141
{
129
142
130
- #if defined( __linux ) || defined( __NetBSD__ )
143
+ #ifdef __linux
131
144
FILE * infile ;
132
145
char buffer [2048 ], * p ,* t ;
133
146
p = (char * ) NULL ;
@@ -158,33 +171,108 @@ int get_feature(char *search)
158
171
#endif
159
172
return (0 );
160
173
}
161
-
174
+ static int cpusort (const void * model1 , const void * model2 )
175
+ {
176
+ return (* (int * )model2 - * (int * )model1 );
177
+ }
162
178
163
179
int detect (void )
164
180
{
165
181
166
- #if defined( __linux ) || defined( __NetBSD__ )
167
-
182
+ #ifdef __linux
183
+ int n ,i ,ii ;
184
+ int midr_el1 ;
185
+ int implementer ;
186
+ int cpucap [1024 ];
187
+ int cpucores [1024 ];
168
188
FILE * infile ;
169
- char buffer [512 ], * p , * cpu_part = NULL , * cpu_implementer = NULL ;
189
+ char cpupart [6 ],cpuimpl [6 ];
190
+ char * cpu_impl = NULL ,* cpu_pt = NULL ;
191
+ char buffer [2048 ], * p , * cpu_part = NULL , * cpu_implementer = NULL ;
170
192
p = (char * ) NULL ;
171
-
172
- infile = fopen ("/proc/cpuinfo" , "r" );
173
- while (fgets (buffer , sizeof (buffer ), infile )) {
174
- if ((cpu_part != NULL ) && (cpu_implementer != NULL )) {
175
- break ;
193
+ cpulowperf = cpumidperf = cpuhiperf = 0 ;
194
+ for (i = 0 ;i < 1024 ;i ++ )cpucores [i ]= 0 ;
195
+ n = 0 ;
196
+ infile = fopen ("/sys/devices/system/cpu/possible" , "r" );
197
+ if (!infile ) {
198
+ infile = fopen ("/proc/cpuinfo" , "r" );
199
+ while (fgets (buffer , sizeof (buffer ), infile )) {
200
+ if (!strncmp ("processor" , buffer , 9 ))
201
+ n ++ ;
176
202
}
177
-
178
- if ((cpu_part == NULL ) && !strncmp ("CPU part" , buffer , 8 )) {
179
- cpu_part = strchr (buffer , ':' ) + 2 ;
180
- cpu_part = strdup (cpu_part );
181
- } else if ((cpu_implementer == NULL ) && !strncmp ("CPU implementer" , buffer , 15 )) {
182
- cpu_implementer = strchr (buffer , ':' ) + 2 ;
183
- cpu_implementer = strdup (cpu_implementer );
203
+ } else {
204
+ fgets (buffer , sizeof (buffer ), infile );
205
+ sscanf (buffer ,"0-%d" ,& n );
206
+ n ++ ;
207
+ }
208
+ fclose (infile );
209
+
210
+ cpu_implementer = NULL ;
211
+ for (i = 0 ;i < n ;i ++ ){
212
+ sprintf (buffer ,"/sys/devices/system/cpu/cpu%d/regs/identification/midr_el1" ,i );
213
+ infile = fopen (buffer ,"r" );
214
+ if (!infile ) {
215
+ infile = fopen ("/proc/cpuinfo" , "r" );
216
+ for (ii = 0 ;ii < n ;ii ++ ){
217
+ cpu_part = NULL ;cpu_implementer = NULL ;
218
+ while (fgets (buffer , sizeof (buffer ), infile )) {
219
+ if ((cpu_part != NULL ) && (cpu_implementer != NULL )) {
220
+ break ;
221
+ }
222
+
223
+ if ((cpu_part == NULL ) && !strncmp ("CPU part" , buffer , 8 )) {
224
+ cpu_pt = strchr (buffer , ':' ) + 2 ;
225
+ cpu_part = strdup (cpu_pt );
226
+ cpucores [i ]= strtol (cpu_part ,NULL ,0 );
227
+
228
+ } else if ((cpu_implementer == NULL ) && !strncmp ("CPU implementer" , buffer , 15 )) {
229
+ cpu_impl = strchr (buffer , ':' ) + 2 ;
230
+ cpu_implementer = strdup (cpu_impl );
231
+ }
232
+
233
+ }
234
+ if (strstr (cpu_implementer , "0x41" )) {
235
+ if (cpucores [ii ] >= 0xd4b ) cpuhiperf ++ ;
236
+ else
237
+ if (cpucores [ii ] >= 0xd07 ) cpumidperf ++ ;
238
+ else cpulowperf ++ ;
239
+ }
240
+ else cpulowperf ++ ;
241
+ }
242
+ fclose (infile );
243
+ break ;
244
+ } else {
245
+ (void )fgets (buffer , sizeof (buffer ), infile );
246
+ midr_el1 = strtoul (buffer ,NULL ,16 );
247
+ fclose (infile );
248
+ implementer = (midr_el1 >> 24 ) & 0xFF ;
249
+ cpucores [i ] = (midr_el1 >> 4 ) & 0xFFF ;
250
+ sprintf (buffer ,"/sys/devices/system/cpu/cpu%d/cpu_capacity" ,i );
251
+ infile = fopen (buffer ,"r" );
252
+ if (!infile ) {
253
+ if (implementer == 65 ) {
254
+ if (cpucores [i ] >= 0xd4b ) cpuhiperf ++ ;
255
+ else
256
+ if (cpucores [i ] >= 0xd07 ) cpumidperf ++ ;
257
+ else cpulowperf ++ ;
258
+ }
259
+ else cpulowperf ++ ;
260
+ } else {
261
+ (void )fgets (buffer , sizeof (buffer ), infile );
262
+ sscanf (buffer ,"%d" ,& cpucap [i ]);
263
+ if (cpucap [i ] >= 1000 ) cpuhiperf ++ ;
264
+ else
265
+ if (cpucap [i ] >= 500 ) cpumidperf ++ ;
266
+ else cpulowperf ++ ;
267
+ fclose (infile );
268
+ }
184
269
}
270
+ sprintf (cpuimpl ,"0x%2x" ,implementer );
271
+ cpu_implementer = strdup (cpuimpl );
185
272
}
186
-
187
- fclose (infile );
273
+ qsort (cpucores ,1024 ,sizeof (int ),cpusort );
274
+ sprintf (cpupart ,"0x%3x" ,cpucores [0 ]);
275
+ cpu_part = strdup (cpupart );
188
276
if (cpu_part != NULL && cpu_implementer != NULL ) {
189
277
// Arm
190
278
if (strstr (cpu_implementer , "0x41" )) {
@@ -216,10 +304,6 @@ int detect(void)
216
304
return CPU_CORTEXX2 ;
217
305
else if (strstr (cpu_part , "0xd4e" )) //X3
218
306
return CPU_CORTEXX2 ;
219
- else if (strstr (cpu_part , "0xd4f" )) //NVIDIA Grace et al.
220
- return CPU_NEOVERSEV2 ;
221
- else if (strstr (cpu_part , "0xd0b" ))
222
- return CPU_CORTEXA76 ;
223
307
}
224
308
// Qualcomm
225
309
else if (strstr (cpu_implementer , "0x51" ) && strstr (cpu_part , "0xc00" ))
@@ -280,8 +364,6 @@ int detect(void)
280
364
sysctlbyname ("hw.cpufamily" ,& value64 ,& length64 ,NULL ,0 );
281
365
if (value64 == 131287967 || value64 == 458787763 ) return CPU_VORTEX ; //A12/M1
282
366
if (value64 == 3660830781 ) return CPU_VORTEX ; //A15/M2
283
- if (value64 == 2271604202 ) return CPU_VORTEX ; //A16/M3
284
- if (value64 == 1867590060 ) return CPU_VORTEX ; //M4
285
367
#endif
286
368
return CPU_ARMV8 ;
287
369
#endif
@@ -314,7 +396,7 @@ void get_cpucount(void)
314
396
{
315
397
int n = 0 ;
316
398
317
- #if defined( __linux ) || defined( __NetBSD__ )
399
+ #ifdef __linux
318
400
FILE * infile ;
319
401
char buffer [2048 ], * p ,* t ;
320
402
p = (char * ) NULL ;
@@ -331,6 +413,12 @@ int n=0;
331
413
fclose (infile );
332
414
333
415
printf ("#define NUM_CORES %d\n" ,n );
416
+ if (cpulowperf > 0 )
417
+ printf ("#define NUM_CORES_LP %d\n" ,cpulowperf );
418
+ if (cpumidperf > 0 )
419
+ printf ("#define NUM_CORES_MP %d\n" ,cpumidperf );
420
+ if (cpuhiperf > 0 )
421
+ printf ("#define NUM_CORES_HP %d\n" ,cpuhiperf );
334
422
#endif
335
423
#ifdef __APPLE__
336
424
sysctlbyname ("hw.physicalcpu_max" ,& value ,& length ,NULL ,0 );
@@ -347,7 +435,6 @@ void get_cpuconfig(void)
347
435
printf ("#define ARMV8\n" );
348
436
printf ("#define HAVE_NEON\n" ); // This shouldn't be necessary
349
437
printf ("#define HAVE_VFPV4\n" ); // This shouldn't be necessary
350
-
351
438
int d = detect ();
352
439
switch (d )
353
440
{
@@ -402,8 +489,6 @@ void get_cpuconfig(void)
402
489
break ;
403
490
404
491
case CPU_NEOVERSEV1 :
405
- printf ("#define HAVE_SVE 1\n" );
406
- case CPU_CORTEXA76 :
407
492
printf ("#define %s\n" , cpuname [d ]);
408
493
printf ("#define L1_CODE_SIZE 65536\n" );
409
494
printf ("#define L1_CODE_LINESIZE 64\n" );
@@ -431,32 +516,12 @@ void get_cpuconfig(void)
431
516
printf ("#define L2_ASSOCIATIVE 8\n" );
432
517
printf ("#define DTB_DEFAULT_ENTRIES 48\n" );
433
518
printf ("#define DTB_SIZE 4096\n" );
434
- printf ("#define HAVE_SVE 1\n" );
435
- break ;
436
- case CPU_NEOVERSEV2 :
437
- printf ("#define ARMV9\n" );
438
- printf ("#define HAVE_SVE 1\n" );
439
- printf ("#define %s\n" , cpuname [d ]);
440
- printf ("#define L1_CODE_SIZE 65536\n" );
441
- printf ("#define L1_CODE_LINESIZE 64\n" );
442
- printf ("#define L1_CODE_ASSOCIATIVE 4\n" );
443
- printf ("#define L1_DATA_SIZE 65536\n" );
444
- printf ("#define L1_DATA_LINESIZE 64\n" );
445
- printf ("#define L1_DATA_ASSOCIATIVE 4\n" );
446
- printf ("#define L2_SIZE 1048576\n" );
447
- printf ("#define L2_LINESIZE 64\n" );
448
- printf ("#define L2_ASSOCIATIVE 8\n" );
449
- // L1 Data TLB = 48 entries
450
- // L2 Data TLB = 2048 entries
451
- printf ("#define DTB_DEFAULT_ENTRIES 48\n" );
452
- printf ("#define DTB_SIZE 4096\n" ); // Set to 4096 for symmetry with other configs.
453
519
break ;
454
520
case CPU_CORTEXA510 :
455
521
case CPU_CORTEXA710 :
456
522
case CPU_CORTEXX1 :
457
523
case CPU_CORTEXX2 :
458
524
printf ("#define ARMV9\n" );
459
- printf ("#define HAVE_SVE 1\n" );
460
525
printf ("#define %s\n" , cpuname [d ]);
461
526
printf ("#define L1_CODE_SIZE 65536\n" );
462
527
printf ("#define L1_CODE_LINESIZE 64\n" );
@@ -559,8 +624,6 @@ void get_cpuconfig(void)
559
624
case CPU_VORTEX :
560
625
printf ("#define VORTEX \n" );
561
626
#ifdef __APPLE__
562
- sysctlbyname ("hw.cpufamily" ,& value64 ,& length64 ,NULL ,0 );
563
- if (value64 == 1867590060 ) printf ("#define HAVE_SME 1\n" );; //M4
564
627
sysctlbyname ("hw.l1icachesize" ,& value64 ,& length64 ,NULL ,0 );
565
628
printf ("#define L1_CODE_SIZE %lld \n" ,value64 );
566
629
sysctlbyname ("hw.cachelinesize" ,& value64 ,& length64 ,NULL ,0 );
@@ -575,7 +638,6 @@ void get_cpuconfig(void)
575
638
break ;
576
639
case CPU_A64FX :
577
640
printf ("#define A64FX\n" );
578
- printf ("#define HAVE_SVE 1\n" );
579
641
printf ("#define L1_CODE_SIZE 65535\n" );
580
642
printf ("#define L1_DATA_SIZE 65535\n" );
581
643
printf ("#define L1_DATA_LINESIZE 256\n" );
@@ -608,7 +670,7 @@ void get_libname(void)
608
670
void get_features (void )
609
671
{
610
672
611
- #if defined( __linux ) || defined( __NetBSD__ )
673
+ #ifdef __linux
612
674
FILE * infile ;
613
675
char buffer [2048 ], * p ,* t ;
614
676
p = (char * ) NULL ;
0 commit comments