1 /**************************************************************************
2   Copyright (c) 2013, The OpenBLAS Project
3   All rights reserved.
4   Redistribution and use in source and binary forms, with or without
5   modification, are permitted provided that the following conditions are
6   met:
7   1. Redistributions of source code must retain the above copyright
8   notice, this list of conditions and the following disclaimer.
9   2. Redistributions in binary form must reproduce the above copyright
10   notice, this list of conditions and the following disclaimer in
11   the documentation and/or other materials provided with the
12   distribution.
13   3. Neither the name of the OpenBLAS project nor the names of
14   its contributors may be used to endorse or promote products
15   derived from this software without specific prior written permission.
16   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19   ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBLAS PROJECT OR CONTRIBUTORS BE
20   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23   CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
25   USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26   *****************************************************************************/
27 
28 #include <string.h>
29 
30 #define CPU_UNKNOWN     	0
31 #define CPU_ARMV6       	1
32 #define CPU_ARMV7       	2
33 #define CPU_CORTEXA9       	3
34 #define CPU_CORTEXA15       	4
35 
36 static char *cpuname[] = {
37   "UNKNOWN",
38   "ARMV6",
39   "ARMV7",
40   "CORTEXA9",
41   "CORTEXA15"
42 };
43 
44 
45 static char *cpuname_lower[] = {
46   "unknown",
47   "armv6",
48   "armv7",
49   "cortexa9",
50   "cortexa15"
51 };
52 
53 
get_feature(char * search)54 int get_feature(char *search)
55 {
56 
57 #ifdef __linux
58 	FILE *infile;
59   	char buffer[2048], *p,*t;
60   	p = (char *) NULL ;
61 
62   	infile = fopen("/proc/cpuinfo", "r");
63 
64 	while (fgets(buffer, sizeof(buffer), infile))
65 	{
66 
67 		if (!strncmp("Features", buffer, 8))
68 		{
69 			p = strchr(buffer, ':') + 2;
70 			break;
71       		}
72   	}
73 
74   	fclose(infile);
75 
76 
77 	if( p == NULL ) return 0;
78 
79 	t = strtok(p," ");
80 	while( t = strtok(NULL," "))
81 	{
82 		if (!strcmp(t, search))   { return(1); }
83 	}
84 
85 #endif
86 	return(0);
87 }
88 
89 
detect(void)90 int detect(void)
91 {
92 
93 #ifdef __linux
94 
95 	FILE *infile;
96   	char buffer[512], *p;
97   	p = (char *) NULL ;
98 
99   	infile = fopen("/proc/cpuinfo", "r");
100 	while (fgets(buffer, sizeof(buffer), infile))
101 	{
102 
103 		if (!strncmp("CPU part", buffer, 8))
104 		{
105 			p = strchr(buffer, ':') + 2;
106 			break;
107       		}
108   	}
109 
110   	fclose(infile);
111   	if(p != NULL) {
112 	  if (strstr(p, "0xc09")) {
113 	    return CPU_CORTEXA9;
114 	  }
115 	  if (strstr(p, "0xc0f")) {
116 	    return CPU_CORTEXA15;
117 	  }
118 	  if (strstr(p, "0xd07")) {
119 	    return CPU_ARMV7;  //ARMV8 on 32-bit
120 	  }
121 
122 	}
123 
124   	p = (char *) NULL ;
125   	infile = fopen("/proc/cpuinfo", "r");
126 
127 	while (fgets(buffer, sizeof(buffer), infile))
128 	{
129 
130 		if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)))
131 		{
132 			p = strchr(buffer, ':') + 2;
133 			break;
134       		}
135   	}
136 
137   	fclose(infile);
138 
139   	if(p != NULL)
140 	{
141 
142 		if (strstr(p, "ARMv7"))
143 		{
144 			 if ( get_feature("vfpv4"))
145 			 	return CPU_ARMV7;
146 
147 			 if ( get_feature("vfpv3"))
148 			 	return CPU_ARMV7;
149 
150 			 if ( get_feature("vfp"))
151 			 	return CPU_ARMV6;
152 
153 
154 		}
155 
156 		if (strstr(p, "ARMv6"))
157 		{
158 			 if ( get_feature("vfp"))
159 			 	return CPU_ARMV6;
160 		}
161 
162 
163 	}
164 
165   	p = (char *) NULL ;
166   	infile = fopen("/proc/cpuinfo", "r");
167 
168 	while (fgets(buffer, sizeof(buffer), infile))
169 	{
170 
171 		if ((!strncmp("CPU architecture", buffer, 16)))
172 		{
173 			p = strchr(buffer, ':') + 2;
174 			break;
175       		}
176   	}
177   	fclose(infile);
178   	if(p != NULL) {
179 	  if (strstr(p, "8")) {
180 	    return CPU_ARMV7;  //ARMV8 on 32-bit
181 	  }
182 
183 	}
184 #else
185 #if (__ARM_ARCH == 7)
186 	return CPU_ARMV7;
187 #else
188 	return CPU_ARMV6;
189 #endif
190 #endif
191 
192 	return CPU_UNKNOWN;
193 }
194 
get_corename(void)195 char *get_corename(void)
196 {
197 	return cpuname[detect()];
198 }
199 
get_architecture(void)200 void get_architecture(void)
201 {
202 	printf("ARM");
203 }
204 
get_subarchitecture(void)205 void get_subarchitecture(void)
206 {
207 	int d = detect();
208 	printf("%s", cpuname[d]);
209 }
210 
get_subdirname(void)211 void get_subdirname(void)
212 {
213 	printf("arm");
214 }
215 
get_cpuconfig(void)216 void get_cpuconfig(void)
217 {
218 
219 	int d = detect();
220 	switch (d)
221 	{
222 	       case CPU_CORTEXA9:
223     			printf("#define CORTEXA9\n");
224     			printf("#define ARMV7\n");
225     			printf("#define HAVE_VFP\n");
226     			printf("#define HAVE_VFPV3\n");
227 			if ( get_feature("neon"))	printf("#define HAVE_NEON\n");
228 			if ( get_feature("vfpv4"))	printf("#define HAVE_VFPV4\n");
229     			printf("#define L1_DATA_SIZE 32768\n");
230     			printf("#define L1_DATA_LINESIZE 32\n");
231     			printf("#define L2_SIZE 1048576\n");
232     			printf("#define L2_LINESIZE 32\n");
233     			printf("#define DTB_DEFAULT_ENTRIES 128\n");
234     			printf("#define DTB_SIZE 4096\n");
235     			printf("#define L2_ASSOCIATIVE 4\n");
236 			break;
237 
238 	       case CPU_CORTEXA15:
239     			printf("#define CORTEXA15\n");
240     			printf("#define ARMV7\n");
241     			printf("#define HAVE_VFP\n");
242     			printf("#define HAVE_VFPV3\n");
243 			if ( get_feature("neon"))	printf("#define HAVE_NEON\n");
244 			if ( get_feature("vfpv4"))	printf("#define HAVE_VFPV4\n");
245     			printf("#define L1_DATA_SIZE 32768\n");
246     			printf("#define L1_DATA_LINESIZE 32\n");
247     			printf("#define L2_SIZE 1048576\n");
248     			printf("#define L2_LINESIZE 32\n");
249     			printf("#define DTB_DEFAULT_ENTRIES 128\n");
250     			printf("#define DTB_SIZE 4096\n");
251     			printf("#define L2_ASSOCIATIVE 4\n");
252 			break;
253 
254 
255 		case CPU_ARMV7:
256     			printf("#define ARMV7\n");
257     			printf("#define HAVE_VFP\n");
258     			printf("#define HAVE_VFPV3\n");
259 			if ( get_feature("neon"))	printf("#define HAVE_NEON\n");
260 			if ( get_feature("vfpv4"))	printf("#define HAVE_VFPV4\n");
261     			printf("#define L1_DATA_SIZE 65536\n");
262     			printf("#define L1_DATA_LINESIZE 32\n");
263     			printf("#define L2_SIZE 512488\n");
264     			printf("#define L2_LINESIZE 32\n");
265     			printf("#define DTB_DEFAULT_ENTRIES 64\n");
266     			printf("#define DTB_SIZE 4096\n");
267     			printf("#define L2_ASSOCIATIVE 4\n");
268 			break;
269 
270 		case CPU_ARMV6:
271     			printf("#define ARMV6\n");
272     			printf("#define HAVE_VFP\n");
273     			printf("#define L1_DATA_SIZE 65536\n");
274     			printf("#define L1_DATA_LINESIZE 32\n");
275     			printf("#define L2_SIZE 512488\n");
276     			printf("#define L2_LINESIZE 32\n");
277     			printf("#define DTB_DEFAULT_ENTRIES 64\n");
278     			printf("#define DTB_SIZE 4096\n");
279     			printf("#define L2_ASSOCIATIVE 4\n");
280 			break;
281 
282 	}
283 }
284 
285 
get_libname(void)286 void get_libname(void)
287 {
288 
289 	int d = detect();
290 	printf("%s", cpuname_lower[d]);
291 }
292 
293 
get_features(void)294 void get_features(void)
295 {
296 
297 #ifdef __linux
298 	FILE *infile;
299   	char buffer[2048], *p,*t;
300   	p = (char *) NULL ;
301 
302   	infile = fopen("/proc/cpuinfo", "r");
303 
304 	while (fgets(buffer, sizeof(buffer), infile))
305 	{
306 
307 		if (!strncmp("Features", buffer, 8))
308 		{
309 			p = strchr(buffer, ':') + 2;
310 			break;
311       		}
312   	}
313 
314   	fclose(infile);
315 
316 
317 	if( p == NULL ) return;
318 
319 	t = strtok(p," ");
320 	while( t = strtok(NULL," "))
321 	{
322 		if (!strcmp(t, "vfp"))   { printf("HAVE_VFP=1\n"); continue; }
323 		if (!strcmp(t, "vfpv3")) { printf("HAVE_VFPV3=1\n"); continue; }
324 		if (!strcmp(t, "vfpv4")) { printf("HAVE_VFPV4=1\n"); continue; }
325 		if (!strcmp(t, "neon"))  { printf("HAVE_NEON=1\n"); continue; }
326 	}
327 
328 #endif
329 	return;
330 }
331 
332 
333