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