Ensure correct output for DAMAX with softfp
[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 // Arm
33 #define CPU_CORTEXA53     2
34 #define CPU_CORTEXA57     3
35 #define CPU_CORTEXA72     4
36 #define CPU_CORTEXA73     5
37 // Qualcomm
38 #define CPU_FALKOR        6
39 // Cavium
40 #define CPU_THUNDERX      7
41 #define CPU_THUNDERX2T99  8
42 //Hisilicon
43 #define CPU_TSV110        9
44
45 static char *cpuname[] = {
46   "UNKNOWN",
47   "ARMV8" ,
48   "CORTEXA53",
49   "CORTEXA57",
50   "CORTEXA72",
51   "CORTEXA73",
52   "FALKOR",
53   "THUNDERX",
54   "THUNDERX2T99",
55   "TSV110"
56 };
57
58 static char *cpuname_lower[] = {
59   "unknown",
60   "armv8",
61   "cortexa53",
62   "cortexa57",
63   "cortexa72",
64   "cortexa73",
65   "falkor",
66   "thunderx",
67   "thunderx2t99",
68   "tsv110"
69 };
70
71 int get_feature(char *search)
72 {
73
74 #ifdef linux
75         FILE *infile;
76         char buffer[2048], *p,*t;
77         p = (char *) NULL ;
78
79         infile = fopen("/proc/cpuinfo", "r");
80
81         while (fgets(buffer, sizeof(buffer), infile))
82         {
83
84                 if (!strncmp("Features", buffer, 8))
85                 {
86                         p = strchr(buffer, ':') + 2;
87                         break;
88                 }
89         }
90
91         fclose(infile);
92
93
94         if( p == NULL ) return 0;
95
96         t = strtok(p," ");
97         while( t = strtok(NULL," "))
98         {
99                 if (!strcmp(t, search))   { return(1); }
100         }
101
102 #endif
103         return(0);
104 }
105
106
107 int detect(void)
108 {
109
110 #ifdef linux
111
112         FILE *infile;
113         char buffer[512], *p, *cpu_part = NULL, *cpu_implementer = NULL;
114         p = (char *) NULL ;
115
116         infile = fopen("/proc/cpuinfo", "r");
117         while (fgets(buffer, sizeof(buffer), infile)) {
118                 if ((cpu_part != NULL) && (cpu_implementer != NULL)) {
119                         break;
120                 }
121
122                 if ((cpu_part == NULL) && !strncmp("CPU part", buffer, 8)) {
123                         cpu_part = strchr(buffer, ':') + 2;
124                         cpu_part = strdup(cpu_part);
125                 } else if ((cpu_implementer == NULL) && !strncmp("CPU implementer", buffer, 15)) {
126                         cpu_implementer = strchr(buffer, ':') + 2;
127                         cpu_implementer = strdup(cpu_implementer);
128                 }
129         }
130
131         fclose(infile);
132         if(cpu_part != NULL && cpu_implementer != NULL) {
133     // Arm
134     if (strstr(cpu_implementer, "0x41")) {
135       if (strstr(cpu_part, "0xd03"))
136         return CPU_CORTEXA53;
137       else if (strstr(cpu_part, "0xd07"))
138         return CPU_CORTEXA57;
139       else if (strstr(cpu_part, "0xd08"))
140         return CPU_CORTEXA72;
141       else if (strstr(cpu_part, "0xd09"))
142         return CPU_CORTEXA73;
143     }
144     // Qualcomm
145     else if (strstr(cpu_implementer, "0x51") && strstr(cpu_part, "0xc00"))
146       return CPU_FALKOR;
147     // Cavium
148     else if (strstr(cpu_implementer, "0x43") && strstr(cpu_part, "0x0a1"))
149                         return CPU_THUNDERX;
150     else if (strstr(cpu_implementer, "0x43") && strstr(cpu_part, "0x0af"))
151                         return CPU_THUNDERX2T99;
152     // HiSilicon
153     else if (strstr(cpu_implementer, "0x48") && strstr(cpu_part, "0xd01"))
154                         return CPU_TSV110;
155         }
156
157         p = (char *) NULL ;
158         infile = fopen("/proc/cpuinfo", "r");
159         while (fgets(buffer, sizeof(buffer), infile))
160         {
161
162                 if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)) ||
163                     (!strncmp("CPU architecture", buffer, 16)))
164                 {
165                         p = strchr(buffer, ':') + 2;
166                         break;
167                 }
168         }
169
170         fclose(infile);
171
172         if(p != NULL)
173         {
174
175                 if ((strstr(p, "AArch64")) || (strstr(p, "8")))
176                 {
177                         return CPU_ARMV8;
178
179                 }
180
181
182         }
183 #endif
184
185         return CPU_UNKNOWN;
186 }
187
188 char *get_corename(void)
189 {
190         return cpuname[detect()];
191 }
192
193 void get_architecture(void)
194 {
195         printf("ARM64");
196 }
197
198 void get_subarchitecture(void)
199 {
200         int d = detect();
201         printf("%s", cpuname[d]);
202 }
203
204 void get_subdirname(void)
205 {
206         printf("arm64");
207 }
208
209 void get_cpuconfig(void)
210 {
211
212   // All arches should define ARMv8
213   printf("#define ARMV8\n");
214   printf("#define HAVE_NEON\n"); // This shouldn't be necessary
215   printf("#define HAVE_VFPV4\n"); // This shouldn't be necessary
216
217         int d = detect();
218         switch (d)
219         {
220
221     case CPU_CORTEXA53:
222       printf("#define %s\n", cpuname[d]);
223       // Fall-through
224                 case CPU_ARMV8:
225       // Minimum parameters for ARMv8 (based on A53)
226         printf("#define L1_DATA_SIZE 32768\n");
227         printf("#define L1_DATA_LINESIZE 64\n");
228         printf("#define L2_SIZE 262144\n");
229         printf("#define L2_LINESIZE 64\n");
230         printf("#define DTB_DEFAULT_ENTRIES 64\n");
231         printf("#define DTB_SIZE 4096\n");
232         printf("#define L2_ASSOCIATIVE 4\n");
233                         break;
234
235                 case CPU_CORTEXA57:
236                 case CPU_CORTEXA72:
237                 case CPU_CORTEXA73:
238       // Common minimum settings for these Arm cores
239       // Can change a lot, but we need to be conservative
240       // TODO: detect info from /sys if possible
241       printf("#define %s\n", cpuname[d]);
242                         printf("#define L1_CODE_SIZE 49152\n");
243                         printf("#define L1_CODE_LINESIZE 64\n");
244                         printf("#define L1_CODE_ASSOCIATIVE 3\n");
245                         printf("#define L1_DATA_SIZE 32768\n");
246                         printf("#define L1_DATA_LINESIZE 64\n");
247                         printf("#define L1_DATA_ASSOCIATIVE 2\n");
248       printf("#define L2_SIZE 524288\n");
249                         printf("#define L2_LINESIZE 64\n");
250                         printf("#define L2_ASSOCIATIVE 16\n");
251                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
252                         printf("#define DTB_SIZE 4096\n");
253                         break;
254
255     case CPU_FALKOR:
256       printf("#define FALKOR\n");
257       printf("#define L1_CODE_SIZE 65536\n");
258       printf("#define L1_CODE_LINESIZE 64\n");
259       printf("#define L1_DATA_SIZE 32768\n");
260       printf("#define L1_DATA_LINESIZE 128\n");
261       printf("#define L2_SIZE 524288\n");
262       printf("#define L2_LINESIZE 64\n");
263       printf("#define DTB_DEFAULT_ENTRIES 64\n");
264       printf("#define DTB_SIZE 4096\n");
265       printf("#define L2_ASSOCIATIVE 16\n");
266       break;
267
268                 case CPU_THUNDERX:
269                         printf("#define THUNDERX\n");
270                         printf("#define L1_DATA_SIZE 32768\n");
271                         printf("#define L1_DATA_LINESIZE 128\n");
272                         printf("#define L2_SIZE 16777216\n");
273                         printf("#define L2_LINESIZE 128\n");
274                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
275                         printf("#define DTB_SIZE 4096\n");
276                         printf("#define L2_ASSOCIATIVE 16\n");
277                         break;
278
279                 case CPU_THUNDERX2T99:
280                         printf("#define THUNDERX2T99                  \n");
281                         printf("#define L1_CODE_SIZE         32768    \n");
282                         printf("#define L1_CODE_LINESIZE     64       \n");
283                         printf("#define L1_CODE_ASSOCIATIVE  8        \n");
284                         printf("#define L1_DATA_SIZE         32768    \n");
285                         printf("#define L1_DATA_LINESIZE     64       \n");
286                         printf("#define L1_DATA_ASSOCIATIVE  8        \n");
287                         printf("#define L2_SIZE              262144   \n");
288                         printf("#define L2_LINESIZE          64       \n");
289                         printf("#define L2_ASSOCIATIVE       8        \n");
290                         printf("#define L3_SIZE              33554432 \n");
291                         printf("#define L3_LINESIZE          64       \n");
292                         printf("#define L3_ASSOCIATIVE       32       \n");
293                         printf("#define DTB_DEFAULT_ENTRIES  64       \n");
294                         printf("#define DTB_SIZE             4096     \n");
295                         break;
296                         
297                 case CPU_TSV110:
298                         printf("#define TSV110                        \n");
299                         printf("#define L1_CODE_SIZE         65536    \n");
300                         printf("#define L1_CODE_LINESIZE     64       \n");
301                         printf("#define L1_CODE_ASSOCIATIVE  4        \n");
302                         printf("#define L1_DATA_SIZE         65536    \n");
303                         printf("#define L1_DATA_LINESIZE     64       \n");
304                         printf("#define L1_DATA_ASSOCIATIVE  4        \n");
305                         printf("#define L2_SIZE              524228   \n");
306                         printf("#define L2_LINESIZE          64       \n");
307                         printf("#define L2_ASSOCIATIVE       8        \n");
308                         printf("#define DTB_DEFAULT_ENTRIES  64       \n");
309                         printf("#define DTB_SIZE             4096     \n");
310                         break;  
311         }
312 }
313
314
315 void get_libname(void)
316 {
317         int d = detect();
318         printf("%s", cpuname_lower[d]);
319 }
320
321 void get_features(void)
322 {
323
324 #ifdef linux
325         FILE *infile;
326         char buffer[2048], *p,*t;
327         p = (char *) NULL ;
328
329         infile = fopen("/proc/cpuinfo", "r");
330
331         while (fgets(buffer, sizeof(buffer), infile))
332         {
333
334                 if (!strncmp("Features", buffer, 8))
335                 {
336                         p = strchr(buffer, ':') + 2;
337                         break;
338                 }
339         }
340
341         fclose(infile);
342
343
344         if( p == NULL ) return;
345
346         t = strtok(p," ");
347         while( t = strtok(NULL," "))
348         {
349         }
350
351 #endif
352         return;
353 }
354
355