1 /**************************************************************************
2 Copyright (c) 2013, The OpenBLAS Project
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions are
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
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 *****************************************************************************/
33 #define CPU_CORTEXA53 2
34 #define CPU_CORTEXA57 3
35 #define CPU_CORTEXA72 4
36 #define CPU_CORTEXA73 5
40 #define CPU_THUNDERX 7
41 #define CPU_THUNDERX2T99 8
45 static char *cpuname[] = {
58 static char *cpuname_lower[] = {
71 int get_feature(char *search)
76 char buffer[2048], *p,*t;
79 infile = fopen("/proc/cpuinfo", "r");
81 while (fgets(buffer, sizeof(buffer), infile))
84 if (!strncmp("Features", buffer, 8))
86 p = strchr(buffer, ':') + 2;
94 if( p == NULL ) return 0;
97 while( t = strtok(NULL," "))
99 if (!strcmp(t, search)) { return(1); }
113 char buffer[512], *p, *cpu_part = NULL, *cpu_implementer = NULL;
116 infile = fopen("/proc/cpuinfo", "r");
117 while (fgets(buffer, sizeof(buffer), infile)) {
118 if ((cpu_part != NULL) && (cpu_implementer != NULL)) {
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);
132 if(cpu_part != NULL && cpu_implementer != NULL) {
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;
145 else if (strstr(cpu_implementer, "0x51") && strstr(cpu_part, "0xc00"))
148 else if (strstr(cpu_implementer, "0x43") && strstr(cpu_part, "0x0a1"))
150 else if (strstr(cpu_implementer, "0x43") && strstr(cpu_part, "0x0af"))
151 return CPU_THUNDERX2T99;
153 else if (strstr(cpu_implementer, "0x48") && strstr(cpu_part, "0xd01"))
158 infile = fopen("/proc/cpuinfo", "r");
159 while (fgets(buffer, sizeof(buffer), infile))
162 if ((!strncmp("model name", buffer, 10)) || (!strncmp("Processor", buffer, 9)) ||
163 (!strncmp("CPU architecture", buffer, 16)))
165 p = strchr(buffer, ':') + 2;
175 if ((strstr(p, "AArch64")) || (strstr(p, "8")))
188 char *get_corename(void)
190 return cpuname[detect()];
193 void get_architecture(void)
198 void get_subarchitecture(void)
201 printf("%s", cpuname[d]);
204 void get_subdirname(void)
209 void get_cpuconfig(void)
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
222 printf("#define %s\n", cpuname[d]);
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");
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");
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");
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");
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");
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");
315 void get_libname(void)
318 printf("%s", cpuname_lower[d]);
321 void get_features(void)
326 char buffer[2048], *p,*t;
329 infile = fopen("/proc/cpuinfo", "r");
331 while (fgets(buffer, sizeof(buffer), infile))
334 if (!strncmp("Features", buffer, 8))
336 p = strchr(buffer, ':') + 2;
344 if( p == NULL ) return;
347 while( t = strtok(NULL," "))