2525 USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2626 *****************************************************************************/
2727
28+ #include <stdlib.h>
2829#include <string.h>
2930#ifdef __APPLE__
3031#include <sys/sysctl.h>
@@ -33,6 +34,20 @@ size_t length=sizeof(value);
3334int64_t value64 ;
3435size_t length64 = sizeof (value64 );
3536#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
3651
3752#define CPU_UNKNOWN 0
3853#define CPU_ARMV8 1
@@ -42,11 +57,9 @@ size_t length64=sizeof(value64);
4257#define CPU_CORTEXA57 3
4358#define CPU_CORTEXA72 4
4459#define CPU_CORTEXA73 5
45- #define CPU_CORTEXA76 23
4660#define CPU_NEOVERSEN1 11
4761#define CPU_NEOVERSEV1 16
4862#define CPU_NEOVERSEN2 17
49- #define CPU_NEOVERSEV2 24
5063#define CPU_CORTEXX1 18
5164#define CPU_CORTEXX2 19
5265#define CPU_CORTEXA510 20
@@ -91,9 +104,7 @@ static char *cpuname[] = {
91104 "CORTEXX2" ,
92105 "CORTEXA510" ,
93106 "CORTEXA710" ,
94- "FT2000" ,
95- "CORTEXA76" ,
96- "NEOVERSEV2"
107+ "FT2000"
97108};
98109
99110static char * cpuname_lower [] = {
@@ -119,15 +130,17 @@ static char *cpuname_lower[] = {
119130 "cortexx2" ,
120131 "cortexa510" ,
121132 "cortexa710" ,
122- "ft2000" ,
123- "cortexa76" ,
124- "neoversev2"
133+ "ft2000"
125134};
126135
136+ static int cpulowperf = 0 ;
137+ static int cpumidperf = 0 ;
138+ static int cpuhiperf = 0 ;
139+
127140int get_feature (char * search )
128141{
129142
130- #if defined( __linux ) || defined( __NetBSD__ )
143+ #ifdef __linux
131144 FILE * infile ;
132145 char buffer [2048 ], * p ,* t ;
133146 p = (char * ) NULL ;
@@ -158,33 +171,108 @@ int get_feature(char *search)
158171#endif
159172 return (0 );
160173}
161-
174+ static int cpusort (const void * model1 , const void * model2 )
175+ {
176+ return (* (int * )model2 - * (int * )model1 );
177+ }
162178
163179int detect (void )
164180{
165181
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 ];
168188 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 ;
170192 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 ++ ;
176202 }
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+ }
184269 }
270+ sprintf (cpuimpl ,"0x%2x" ,implementer );
271+ cpu_implementer = strdup (cpuimpl );
185272 }
186-
187- fclose (infile );
273+ qsort (cpucores ,1024 ,sizeof (int ),cpusort );
274+ sprintf (cpupart ,"0x%3x" ,cpucores [0 ]);
275+ cpu_part = strdup (cpupart );
188276 if (cpu_part != NULL && cpu_implementer != NULL ) {
189277 // Arm
190278 if (strstr (cpu_implementer , "0x41" )) {
@@ -216,10 +304,6 @@ int detect(void)
216304 return CPU_CORTEXX2 ;
217305 else if (strstr (cpu_part , "0xd4e" )) //X3
218306 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 ;
223307 }
224308 // Qualcomm
225309 else if (strstr (cpu_implementer , "0x51" ) && strstr (cpu_part , "0xc00" ))
@@ -280,8 +364,6 @@ int detect(void)
280364 sysctlbyname ("hw.cpufamily" ,& value64 ,& length64 ,NULL ,0 );
281365 if (value64 == 131287967 || value64 == 458787763 ) return CPU_VORTEX ; //A12/M1
282366 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
285367#endif
286368 return CPU_ARMV8 ;
287369#endif
@@ -314,7 +396,7 @@ void get_cpucount(void)
314396{
315397int n = 0 ;
316398
317- #if defined( __linux ) || defined( __NetBSD__ )
399+ #ifdef __linux
318400 FILE * infile ;
319401 char buffer [2048 ], * p ,* t ;
320402 p = (char * ) NULL ;
@@ -331,6 +413,12 @@ int n=0;
331413 fclose (infile );
332414
333415 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 );
334422#endif
335423#ifdef __APPLE__
336424 sysctlbyname ("hw.physicalcpu_max" ,& value ,& length ,NULL ,0 );
@@ -347,7 +435,6 @@ void get_cpuconfig(void)
347435 printf ("#define ARMV8\n" );
348436 printf ("#define HAVE_NEON\n" ); // This shouldn't be necessary
349437 printf ("#define HAVE_VFPV4\n" ); // This shouldn't be necessary
350-
351438 int d = detect ();
352439 switch (d )
353440 {
@@ -402,8 +489,6 @@ void get_cpuconfig(void)
402489 break ;
403490
404491 case CPU_NEOVERSEV1 :
405- printf ("#define HAVE_SVE 1\n" );
406- case CPU_CORTEXA76 :
407492 printf ("#define %s\n" , cpuname [d ]);
408493 printf ("#define L1_CODE_SIZE 65536\n" );
409494 printf ("#define L1_CODE_LINESIZE 64\n" );
@@ -431,32 +516,12 @@ void get_cpuconfig(void)
431516 printf ("#define L2_ASSOCIATIVE 8\n" );
432517 printf ("#define DTB_DEFAULT_ENTRIES 48\n" );
433518 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.
453519 break ;
454520 case CPU_CORTEXA510 :
455521 case CPU_CORTEXA710 :
456522 case CPU_CORTEXX1 :
457523 case CPU_CORTEXX2 :
458524 printf ("#define ARMV9\n" );
459- printf ("#define HAVE_SVE 1\n" );
460525 printf ("#define %s\n" , cpuname [d ]);
461526 printf ("#define L1_CODE_SIZE 65536\n" );
462527 printf ("#define L1_CODE_LINESIZE 64\n" );
@@ -559,8 +624,6 @@ void get_cpuconfig(void)
559624 case CPU_VORTEX :
560625 printf ("#define VORTEX \n" );
561626#ifdef __APPLE__
562- sysctlbyname ("hw.cpufamily" ,& value64 ,& length64 ,NULL ,0 );
563- if (value64 == 1867590060 ) printf ("#define HAVE_SME 1\n" );; //M4
564627 sysctlbyname ("hw.l1icachesize" ,& value64 ,& length64 ,NULL ,0 );
565628 printf ("#define L1_CODE_SIZE %lld \n" ,value64 );
566629 sysctlbyname ("hw.cachelinesize" ,& value64 ,& length64 ,NULL ,0 );
@@ -575,7 +638,6 @@ void get_cpuconfig(void)
575638 break ;
576639 case CPU_A64FX :
577640 printf ("#define A64FX\n" );
578- printf ("#define HAVE_SVE 1\n" );
579641 printf ("#define L1_CODE_SIZE 65535\n" );
580642 printf ("#define L1_DATA_SIZE 65535\n" );
581643 printf ("#define L1_DATA_LINESIZE 256\n" );
@@ -608,7 +670,7 @@ void get_libname(void)
608670void get_features (void )
609671{
610672
611- #if defined( __linux ) || defined( __NetBSD__ )
673+ #ifdef __linux
612674 FILE * infile ;
613675 char buffer [2048 ], * p ,* t ;
614676 p = (char * ) NULL ;
0 commit comments