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