Fix cortex-a15 detecting bug.
[platform/upstream/openblas.git] / cpuid_arm.c
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   "UNKOWN",
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
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;
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
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
119         }
120
121         p = (char *) NULL ;
122         infile = fopen("/proc/cpuinfo", "r");
123
124         while (fgets(buffer, sizeof(buffer), infile))
125         {
126
127                 if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)))
128                 {
129                         p = strchr(buffer, ':') + 2;
130                         break;
131                 }
132         }
133
134         fclose(infile);
135
136         if(p != NULL)
137         {
138
139                 if (strstr(p, "ARMv7"))
140                 {
141                          if ( get_feature("vfpv4"))
142                                 return CPU_ARMV7;
143
144                          if ( get_feature("vfpv3"))
145                                 return CPU_ARMV7;
146
147                          if ( get_feature("vfp"))
148                                 return CPU_ARMV6;
149
150
151                 }
152
153                 if (strstr(p, "ARMv6"))
154                 {
155                          if ( get_feature("vfp"))
156                                 return CPU_ARMV6;
157                 }
158
159
160         }
161 #endif
162
163         return CPU_UNKNOWN;
164 }
165
166 char *get_corename(void)
167 {
168         return cpuname[detect()];
169 }
170
171 void get_architecture(void)
172 {
173         printf("ARM");
174 }
175
176 void get_subarchitecture(void)
177 {
178         int d = detect();
179         printf("%s", cpuname[d]);
180 }
181
182 void get_subdirname(void)
183 {
184         printf("arm");
185 }
186
187 void get_cpuconfig(void)
188 {
189
190         int d = detect();
191         switch (d)
192         {
193                case CPU_CORTEXA9:
194                         printf("#define CORTEXA9\n");
195                         printf("#define HAVE_VFP\n");
196                         printf("#define HAVE_VFPV3\n");
197                         if ( get_feature("neon"))       printf("#define HAVE_NEON\n");
198                         if ( get_feature("vfpv4"))      printf("#define HAVE_VFPV4\n");
199                         printf("#define L1_DATA_SIZE 32768\n");
200                         printf("#define L1_DATA_LINESIZE 32\n");
201                         printf("#define L2_SIZE 1048576\n");
202                         printf("#define L2_LINESIZE 32\n");
203                         printf("#define DTB_DEFAULT_ENTRIES 128\n");
204                         printf("#define DTB_SIZE 4096\n");
205                         printf("#define L2_ASSOCIATIVE 4\n");
206                         break;
207
208                case CPU_CORTEXA15:
209                         printf("#define CORTEXA15\n");
210                         printf("#define HAVE_VFP\n");
211                         printf("#define HAVE_VFPV3\n");
212                         if ( get_feature("neon"))       printf("#define HAVE_NEON\n");
213                         if ( get_feature("vfpv4"))      printf("#define HAVE_VFPV4\n");
214                         printf("#define L1_DATA_SIZE 32768\n");
215                         printf("#define L1_DATA_LINESIZE 32\n");
216                         printf("#define L2_SIZE 1048576\n");
217                         printf("#define L2_LINESIZE 32\n");
218                         printf("#define DTB_DEFAULT_ENTRIES 128\n");
219                         printf("#define DTB_SIZE 4096\n");
220                         printf("#define L2_ASSOCIATIVE 4\n");
221                         break;
222
223
224                 case CPU_ARMV7:
225                         printf("#define ARMV7\n");
226                         printf("#define HAVE_VFP\n");
227                         printf("#define HAVE_VFPV3\n");
228                         if ( get_feature("neon"))       printf("#define HAVE_NEON\n");
229                         if ( get_feature("vfpv4"))      printf("#define HAVE_VFPV4\n");
230                         printf("#define L1_DATA_SIZE 65536\n");
231                         printf("#define L1_DATA_LINESIZE 32\n");
232                         printf("#define L2_SIZE 512488\n");
233                         printf("#define L2_LINESIZE 32\n");
234                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
235                         printf("#define DTB_SIZE 4096\n");
236                         printf("#define L2_ASSOCIATIVE 4\n");
237                         break;
238
239                 case CPU_ARMV6:
240                         printf("#define ARMV6\n");
241                         printf("#define HAVE_VFP\n");
242                         printf("#define L1_DATA_SIZE 65536\n");
243                         printf("#define L1_DATA_LINESIZE 32\n");
244                         printf("#define L2_SIZE 512488\n");
245                         printf("#define L2_LINESIZE 32\n");
246                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
247                         printf("#define DTB_SIZE 4096\n");
248                         printf("#define L2_ASSOCIATIVE 4\n");
249                         break;
250
251         }
252 }
253
254
255 void get_libname(void)
256 {
257
258         int d = detect();
259         printf("%s", cpuname_lower[d]);
260 }
261
262
263 void get_features(void)
264 {
265
266 #ifdef linux
267         FILE *infile;
268         char buffer[2048], *p,*t;
269         p = (char *) NULL ;
270
271         infile = fopen("/proc/cpuinfo", "r");
272
273         while (fgets(buffer, sizeof(buffer), infile))
274         {
275
276                 if (!strncmp("Features", buffer, 8))
277                 {
278                         p = strchr(buffer, ':') + 2;
279                         break;
280                 }
281         }
282
283         fclose(infile);
284
285
286         if( p == NULL ) return;
287
288         t = strtok(p," ");
289         while( t = strtok(NULL," "))
290         {
291                 if (!strcmp(t, "vfp"))   { printf("HAVE_VFP=1\n"); continue; }
292                 if (!strcmp(t, "vfpv3")) { printf("HAVE_VFPV3=1\n"); continue; }
293                 if (!strcmp(t, "vfpv4")) { printf("HAVE_VFPV4=1\n"); continue; }
294                 if (!strcmp(t, "neon"))  { printf("HAVE_NEON=1\n"); continue; }
295         }
296
297 #endif
298         return;
299 }
300
301