ARM64: Add Cavium THUNDERX Target
[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, *cpu_implementer;
95         p = (char *) NULL ;
96
97         infile = fopen("/proc/cpuinfo", "r");
98         while (fgets(buffer, sizeof(buffer), infile)) {
99
100                 if (!strncmp("CPU part", buffer, 8)) {
101                         cpu_part = strchr(buffer, ':') + 2;
102                         break;
103                 } else if (!strncmp("CPU implementer", buffer, 15)) {
104                         cpu_implementer = strchr(buffer, ':') + 2;
105                         break;
106                 }
107         }
108
109         fclose(infile);
110         if(cpu_part != NULL && cpu_implementer != NULL) {
111                 if (strstr(cpu_part, "0xd07") && strstr(cpu_implementer, "0x41"))
112                         return CPU_CORTEXA57;
113                 else if (strstr(cpu_part, "0x516") && strstr(cpu_implementer, "0x42"))
114                         return CPU_VULCAN;
115                 else if (strstr(cpu_part, "0x0a1") && strstr(cpu_implementer, "0x43"))
116                         return CPU_THUNDERX;
117         }
118
119         p = (char *) NULL ;
120         infile = fopen("/proc/cpuinfo", "r");
121         while (fgets(buffer, sizeof(buffer), infile))
122         {
123
124                 if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)) ||
125                     (!strncmp("CPU architecture", buffer, 16)))
126                 {
127                         p = strchr(buffer, ':') + 2;
128                         break;
129                 }
130         }
131
132         fclose(infile);
133
134         if(p != NULL)
135         {
136
137                 if (strstr(p, "AArch64"))
138                 {
139                         return CPU_ARMV8;
140
141                 }
142
143
144         }
145 #endif
146
147         return CPU_UNKNOWN;
148 }
149
150 char *get_corename(void)
151 {
152         return cpuname[detect()];
153 }
154
155 void get_architecture(void)
156 {
157         printf("ARM64");
158 }
159
160 void get_subarchitecture(void)
161 {
162         int d = detect();
163         printf("%s", cpuname[d]);
164 }
165
166 void get_subdirname(void)
167 {
168         printf("arm64");
169 }
170
171 void get_cpuconfig(void)
172 {
173
174         int d = detect();
175         switch (d)
176         {
177
178                 case CPU_ARMV8:
179                         printf("#define ARMV8\n");
180                         printf("#define L1_DATA_SIZE 32768\n");
181                         printf("#define L1_DATA_LINESIZE 64\n");
182                         printf("#define L2_SIZE 262144\n");
183                         printf("#define L2_LINESIZE 64\n");
184                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
185                         printf("#define DTB_SIZE 4096\n");
186                         printf("#define L2_ASSOCIATIVE 4\n");
187                         break;
188
189                 case CPU_VULCAN:
190                         printf("#define VULCAN                        \n");
191                         printf("#define HAVE_VFP                      \n");
192                         printf("#define HAVE_VFPV3                    \n");
193                         printf("#define HAVE_NEON                     \n");
194                         printf("#define HAVE_VFPV4                    \n");
195                         printf("#define L1_CODE_SIZE         32768    \n");
196                         printf("#define L1_CODE_LINESIZE     64       \n");
197                         printf("#define L1_CODE_ASSOCIATIVE  8        \n");
198                         printf("#define L1_DATA_SIZE         32768    \n");
199                         printf("#define L1_DATA_LINESIZE     64       \n");
200                         printf("#define L1_DATA_ASSOCIATIVE  8        \n");
201                         printf("#define L2_SIZE              262144   \n");
202                         printf("#define L2_LINESIZE          64       \n");
203                         printf("#define L2_ASSOCIATIVE       8        \n");
204                         printf("#define L3_SIZE              33554432 \n");
205                         printf("#define L3_LINESIZE          64       \n");
206                         printf("#define L3_ASSOCIATIVE       32       \n");
207                         printf("#define DTB_DEFAULT_ENTRIES  64       \n");
208                         printf("#define DTB_SIZE             4096     \n");
209                         break;
210
211                 case CPU_CORTEXA57:
212                         printf("#define CORTEXA57\n");
213                         printf("#define HAVE_VFP\n");
214                         printf("#define HAVE_VFPV3\n");
215                         printf("#define HAVE_NEON\n");
216                         printf("#define HAVE_VFPV4\n");
217                         printf("#define L1_CODE_SIZE 49152\n");
218                         printf("#define L1_CODE_LINESIZE 64\n");
219                         printf("#define L1_CODE_ASSOCIATIVE 3\n");
220                         printf("#define L1_DATA_SIZE 32768\n");
221                         printf("#define L1_DATA_LINESIZE 64\n");
222                         printf("#define L1_DATA_ASSOCIATIVE 2\n");
223                         printf("#define L2_SIZE 2097152\n");
224                         printf("#define L2_LINESIZE 64\n");
225                         printf("#define L2_ASSOCIATIVE 16\n");
226                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
227                         printf("#define DTB_SIZE 4096\n");
228                         break;
229
230                 case CPU_THUNDERX:
231                         printf("#define ARMV8\n");
232                         printf("#define THUNDERX\n");
233                         printf("#define L1_DATA_SIZE 32768\n");
234                         printf("#define L1_DATA_LINESIZE 128\n");
235                         printf("#define L2_SIZE 16777216\n");
236                         printf("#define L2_LINESIZE 128\n");
237                         printf("#define DTB_DEFAULT_ENTRIES 64\n");
238                         printf("#define DTB_SIZE 4096\n");
239                         printf("#define L2_ASSOCIATIVE 16\n");
240                         break;
241         }
242 }
243
244
245 void get_libname(void)
246 {
247         int d = detect();
248         printf("%s", cpuname_lower[d]);
249 }
250
251 void get_features(void)
252 {
253
254 #ifdef linux
255         FILE *infile;
256         char buffer[2048], *p,*t;
257         p = (char *) NULL ;
258
259         infile = fopen("/proc/cpuinfo", "r");
260
261         while (fgets(buffer, sizeof(buffer), infile))
262         {
263
264                 if (!strncmp("Features", buffer, 8))
265                 {
266                         p = strchr(buffer, ':') + 2;
267                         break;
268                 }
269         }
270
271         fclose(infile);
272
273
274         if( p == NULL ) return;
275
276         t = strtok(p," ");
277         while( t = strtok(NULL," "))
278         {
279         }
280
281 #endif
282         return;
283 }
284
285