ARM64: Fix auto detect of ARM64 cpus
[platform/upstream/openblas.git] / cpuid_arm64.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_ARMV8               1
32 #define CPU_CORTEXA57           2
33 #define CPU_VULCAN              3
34 #define CPU_THUNDERX            4
35
36 static char *cpuname[] = {
37   "UNKNOWN",
38   "ARMV8" ,
39   "CORTEXA57",
40   "VULCAN",
41   "THUNDERX"
42 };
43
44 static char *cpuname_lower[] = {
45   "unknown",
46   "armv8" ,
47   "cortexa57",
48   "vulcan",
49   "thunderx"
50 };
51
52 int get_feature(char *search)
53 {
54
55 #ifdef linux
56         FILE *infile;
57         char buffer[2048], *p,*t;
58         p = (char *) NULL ;
59
60         infile = fopen("/proc/cpuinfo", "r");
61
62         while (fgets(buffer, sizeof(buffer), infile))
63         {
64
65                 if (!strncmp("Features", buffer, 8))
66                 {
67                         p = strchr(buffer, ':') + 2;
68                         break;
69                 }
70         }
71
72         fclose(infile);
73
74
75         if( p == NULL ) return 0;
76
77         t = strtok(p," ");
78         while( t = strtok(NULL," "))
79         {
80                 if (!strcmp(t, search))   { return(1); }
81         }
82
83 #endif
84         return(0);
85 }
86
87
88 int detect(void)
89 {
90
91 #ifdef linux
92
93         FILE *infile;
94         char buffer[512], *p, *cpu_part = NULL, *cpu_implementer = NULL;
95         p = (char *) NULL ;
96
97         infile = fopen("/proc/cpuinfo", "r");
98         while (fgets(buffer, sizeof(buffer), infile)) {
99                 if ((cpu_part != NULL) && (cpu_implementer != NULL)) {
100                         break;
101                 }
102
103                 if ((cpu_part == NULL) && !strncmp("CPU part", buffer, 8)) {
104                         cpu_part = strchr(buffer, ':') + 2;
105                         cpu_part = strdup(cpu_part);
106                 } else if ((cpu_implementer == NULL) && !strncmp("CPU implementer", buffer, 15)) {
107                         cpu_implementer = strchr(buffer, ':') + 2;
108                         cpu_implementer = strdup(cpu_implementer);
109                 }
110         }
111
112         fclose(infile);
113         if(cpu_part != NULL && cpu_implementer != NULL) {
114                 if (strstr(cpu_part, "0xd07") && strstr(cpu_implementer, "0x41"))
115                         return CPU_CORTEXA57;
116                 else if (strstr(cpu_part, "0x516") && strstr(cpu_implementer, "0x42"))
117                         return CPU_VULCAN;
118                 else if (strstr(cpu_part, "0x0a1") && strstr(cpu_implementer, "0x43"))
119                         return CPU_THUNDERX;
120         }
121
122         p = (char *) NULL ;
123         infile = fopen("/proc/cpuinfo", "r");
124         while (fgets(buffer, sizeof(buffer), infile))
125         {
126
127                 if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)) ||
128                     (!strncmp("CPU architecture", buffer, 16)))
129                 {
130                         p = strchr(buffer, ':') + 2;
131                         break;
132                 }
133         }
134
135         fclose(infile);
136
137         if(p != NULL)
138         {
139
140                 if (strstr(p, "AArch64"))
141                 {
142                         return CPU_ARMV8;
143
144                 }
145
146
147         }
148 #endif
149
150         return CPU_UNKNOWN;
151 }
152
153 char *get_corename(void)
154 {
155         return cpuname[detect()];
156 }
157
158 void get_architecture(void)
159 {
160         printf("ARM64");
161 }
162
163 void get_subarchitecture(void)
164 {
165         int d = detect();
166         printf("%s", cpuname[d]);
167 }
168
169 void get_subdirname(void)
170 {
171         printf("arm64");
172 }
173
174 void get_cpuconfig(void)
175 {
176
177         int d = detect();
178         switch (d)
179         {
180
181                 case CPU_ARMV8:
182                         printf("#define ARMV8\n");
183                         printf("#define L1_DATA_SIZE 32768\n");
184                         printf("#define L1_DATA_LINESIZE 64\n");
185                         printf("#define L2_SIZE 262144\n");
186                         printf("#define L2_LINESIZE 64\n");
187                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
188                         printf("#define DTB_SIZE 4096\n");
189                         printf("#define L2_ASSOCIATIVE 4\n");
190                         break;
191
192                 case CPU_VULCAN:
193                         printf("#define VULCAN                        \n");
194                         printf("#define HAVE_VFP                      \n");
195                         printf("#define HAVE_VFPV3                    \n");
196                         printf("#define HAVE_NEON                     \n");
197                         printf("#define HAVE_VFPV4                    \n");
198                         printf("#define L1_CODE_SIZE         32768    \n");
199                         printf("#define L1_CODE_LINESIZE     64       \n");
200                         printf("#define L1_CODE_ASSOCIATIVE  8        \n");
201                         printf("#define L1_DATA_SIZE         32768    \n");
202                         printf("#define L1_DATA_LINESIZE     64       \n");
203                         printf("#define L1_DATA_ASSOCIATIVE  8        \n");
204                         printf("#define L2_SIZE              262144   \n");
205                         printf("#define L2_LINESIZE          64       \n");
206                         printf("#define L2_ASSOCIATIVE       8        \n");
207                         printf("#define L3_SIZE              33554432 \n");
208                         printf("#define L3_LINESIZE          64       \n");
209                         printf("#define L3_ASSOCIATIVE       32       \n");
210                         printf("#define DTB_DEFAULT_ENTRIES  64       \n");
211                         printf("#define DTB_SIZE             4096     \n");
212                         break;
213
214                 case CPU_CORTEXA57:
215                         printf("#define CORTEXA57\n");
216                         printf("#define HAVE_VFP\n");
217                         printf("#define HAVE_VFPV3\n");
218                         printf("#define HAVE_NEON\n");
219                         printf("#define HAVE_VFPV4\n");
220                         printf("#define L1_CODE_SIZE 49152\n");
221                         printf("#define L1_CODE_LINESIZE 64\n");
222                         printf("#define L1_CODE_ASSOCIATIVE 3\n");
223                         printf("#define L1_DATA_SIZE 32768\n");
224                         printf("#define L1_DATA_LINESIZE 64\n");
225                         printf("#define L1_DATA_ASSOCIATIVE 2\n");
226                         printf("#define L2_SIZE 2097152\n");
227                         printf("#define L2_LINESIZE 64\n");
228                         printf("#define L2_ASSOCIATIVE 16\n");
229                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
230                         printf("#define DTB_SIZE 4096\n");
231                         break;
232
233                 case CPU_THUNDERX:
234                         printf("#define ARMV8\n");
235                         printf("#define THUNDERX\n");
236                         printf("#define L1_DATA_SIZE 32768\n");
237                         printf("#define L1_DATA_LINESIZE 128\n");
238                         printf("#define L2_SIZE 16777216\n");
239                         printf("#define L2_LINESIZE 128\n");
240                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
241                         printf("#define DTB_SIZE 4096\n");
242                         printf("#define L2_ASSOCIATIVE 16\n");
243                         break;
244         }
245 }
246
247
248 void get_libname(void)
249 {
250         int d = detect();
251         printf("%s", cpuname_lower[d]);
252 }
253
254 void get_features(void)
255 {
256
257 #ifdef linux
258         FILE *infile;
259         char buffer[2048], *p,*t;
260         p = (char *) NULL ;
261
262         infile = fopen("/proc/cpuinfo", "r");
263
264         while (fgets(buffer, sizeof(buffer), infile))
265         {
266
267                 if (!strncmp("Features", buffer, 8))
268                 {
269                         p = strchr(buffer, ':') + 2;
270                         break;
271                 }
272         }
273
274         fclose(infile);
275
276
277         if( p == NULL ) return;
278
279         t = strtok(p," ");
280         while( t = strtok(NULL," "))
281         {
282         }
283
284 #endif
285         return;
286 }
287
288