Merge branch 'develop' into cmake
[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 ARMV7\n");
196                         printf("#define HAVE_VFP\n");
197                         printf("#define HAVE_VFPV3\n");
198                         if ( get_feature("neon"))       printf("#define HAVE_NEON\n");
199                         if ( get_feature("vfpv4"))      printf("#define HAVE_VFPV4\n");
200                         printf("#define L1_DATA_SIZE 32768\n");
201                         printf("#define L1_DATA_LINESIZE 32\n");
202                         printf("#define L2_SIZE 1048576\n");
203                         printf("#define L2_LINESIZE 32\n");
204                         printf("#define DTB_DEFAULT_ENTRIES 128\n");
205                         printf("#define DTB_SIZE 4096\n");
206                         printf("#define L2_ASSOCIATIVE 4\n");
207                         break;
208
209                case CPU_CORTEXA15:
210                         printf("#define CORTEXA15\n");
211                         printf("#define ARMV7\n");
212                         printf("#define HAVE_VFP\n");
213                         printf("#define HAVE_VFPV3\n");
214                         if ( get_feature("neon"))       printf("#define HAVE_NEON\n");
215                         if ( get_feature("vfpv4"))      printf("#define HAVE_VFPV4\n");
216                         printf("#define L1_DATA_SIZE 32768\n");
217                         printf("#define L1_DATA_LINESIZE 32\n");
218                         printf("#define L2_SIZE 1048576\n");
219                         printf("#define L2_LINESIZE 32\n");
220                         printf("#define DTB_DEFAULT_ENTRIES 128\n");
221                         printf("#define DTB_SIZE 4096\n");
222                         printf("#define L2_ASSOCIATIVE 4\n");
223                         break;
224
225
226                 case CPU_ARMV7:
227                         printf("#define ARMV7\n");
228                         printf("#define HAVE_VFP\n");
229                         printf("#define HAVE_VFPV3\n");
230                         if ( get_feature("neon"))       printf("#define HAVE_NEON\n");
231                         if ( get_feature("vfpv4"))      printf("#define HAVE_VFPV4\n");
232                         printf("#define L1_DATA_SIZE 65536\n");
233                         printf("#define L1_DATA_LINESIZE 32\n");
234                         printf("#define L2_SIZE 512488\n");
235                         printf("#define L2_LINESIZE 32\n");
236                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
237                         printf("#define DTB_SIZE 4096\n");
238                         printf("#define L2_ASSOCIATIVE 4\n");
239                         break;
240
241                 case CPU_ARMV6:
242                         printf("#define ARMV6\n");
243                         printf("#define HAVE_VFP\n");
244                         printf("#define L1_DATA_SIZE 65536\n");
245                         printf("#define L1_DATA_LINESIZE 32\n");
246                         printf("#define L2_SIZE 512488\n");
247                         printf("#define L2_LINESIZE 32\n");
248                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
249                         printf("#define DTB_SIZE 4096\n");
250                         printf("#define L2_ASSOCIATIVE 4\n");
251                         break;
252
253         }
254 }
255
256
257 void get_libname(void)
258 {
259
260         int d = detect();
261         printf("%s", cpuname_lower[d]);
262 }
263
264
265 void get_features(void)
266 {
267
268 #ifdef linux
269         FILE *infile;
270         char buffer[2048], *p,*t;
271         p = (char *) NULL ;
272
273         infile = fopen("/proc/cpuinfo", "r");
274
275         while (fgets(buffer, sizeof(buffer), infile))
276         {
277
278                 if (!strncmp("Features", buffer, 8))
279                 {
280                         p = strchr(buffer, ':') + 2;
281                         break;
282                 }
283         }
284
285         fclose(infile);
286
287
288         if( p == NULL ) return;
289
290         t = strtok(p," ");
291         while( t = strtok(NULL," "))
292         {
293                 if (!strcmp(t, "vfp"))   { printf("HAVE_VFP=1\n"); continue; }
294                 if (!strcmp(t, "vfpv3")) { printf("HAVE_VFPV3=1\n"); continue; }
295                 if (!strcmp(t, "vfpv4")) { printf("HAVE_VFPV4=1\n"); continue; }
296                 if (!strcmp(t, "neon"))  { printf("HAVE_NEON=1\n"); continue; }
297         }
298
299 #endif
300         return;
301 }
302
303