You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

dynamic_arm64.c 11 kB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. /*********************************************************************/
  2. /* Copyright 2009, 2010 The University of Texas at Austin. */
  3. /* All rights reserved. */
  4. /* */
  5. /* Redistribution and use in source and binary forms, with or */
  6. /* without modification, are permitted provided that the following */
  7. /* conditions are met: */
  8. /* */
  9. /* 1. Redistributions of source code must retain the above */
  10. /* copyright notice, this list of conditions and the following */
  11. /* disclaimer. */
  12. /* */
  13. /* 2. Redistributions in binary form must reproduce the above */
  14. /* copyright notice, this list of conditions and the following */
  15. /* disclaimer in the documentation and/or other materials */
  16. /* provided with the distribution. */
  17. /* */
  18. /* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY OF TEXAS AT */
  19. /* AUSTIN ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, */
  20. /* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
  21. /* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
  22. /* DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OF TEXAS AT */
  23. /* AUSTIN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, */
  24. /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
  25. /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE */
  26. /* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */
  27. /* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */
  28. /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
  29. /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT */
  30. /* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE */
  31. /* POSSIBILITY OF SUCH DAMAGE. */
  32. /* */
  33. /* The views and conclusions contained in the software and */
  34. /* documentation are those of the authors and should not be */
  35. /* interpreted as representing official policies, either expressed */
  36. /* or implied, of The University of Texas at Austin. */
  37. /*********************************************************************/
  38. #include "common.h"
  39. #if (defined OS_LINUX || defined OS_ANDROID)
  40. #include <asm/hwcap.h>
  41. #include <sys/auxv.h>
  42. #endif
  43. extern gotoblas_t gotoblas_ARMV8;
  44. #ifdef DYNAMIC_LIST
  45. #ifdef DYN_CORTEXA53
  46. extern gotoblas_t gotoblas_CORTEXA53;
  47. #else
  48. #define gotoblas_CORTEXA53 gotoblas_ARMV8
  49. #endif
  50. #ifdef DYN_CORTEXA57
  51. extern gotoblas_t gotoblas_CORTEXA57;
  52. #else
  53. #define gotoblas_CORTEXA57 gotoblas_ARMV8
  54. #endif
  55. #ifdef DYN_CORTEXA72
  56. extern gotoblas_t gotoblas_CORTEXA72;
  57. #else
  58. #define gotoblas_CORTEXA72 gotoblas_ARMV8
  59. #endif
  60. #ifdef DYN_CORTEXA73
  61. extern gotoblas_t gotoblas_CORTEXA73;
  62. #else
  63. #define gotoblas_CORTEXA73 gotoblas_ARMV8
  64. #endif
  65. #ifdef DYN_FALKOR
  66. extern gotoblas_t gotoblas_FALKOR;
  67. #else
  68. #define gotoblas_FALKOR gotoblas_ARMV8
  69. #endif
  70. #ifdef DYN_TSV110
  71. extern gotoblas_t gotoblas_TSV110;
  72. #else
  73. #define gotoblas_TSV110 gotoblas_ARMV8
  74. #endif
  75. #ifdef DYN_THUNDERX
  76. extern gotoblas_t gotoblas_THUNDERX;
  77. #else
  78. #define gotoblas_THUNDERX gotoblas_ARMV8
  79. #endif
  80. #ifdef DYN_THUNDERX2T99
  81. extern gotoblas_t gotoblas_THUNDERX2T99;
  82. #else
  83. #define gotoblas_THUNDERX2T99 gotoblas_ARMV8
  84. #endif
  85. #ifdef DYN_THUNDERX3T110
  86. extern gotoblas_t gotoblas_THUNDERX3T110;
  87. #else
  88. #define gotoblas_THUNDERX3T110 gotoblas_ARMV8
  89. #endif
  90. #ifdef DYN_EMAG8180
  91. extern gotoblas_t gotoblas_EMAG8180;
  92. #else
  93. #define gotoblas_EMAG8180 gotoblas_ARMV8
  94. #endif
  95. #ifdef DYN_NEOVERSEN1
  96. extern gotoblas_t gotoblas_NEOVERSEN1;
  97. #else
  98. #define gotoblas_NEOVERSEN1 gotoblas_ARMV8
  99. #endif
  100. #ifdef DYN_NEOVERSEV1
  101. extern gotoblas_t gotoblas_NEOVERSEV1;
  102. #else
  103. #define gotoblas_NEOVERSEV1 gotoblas_ARMV8
  104. #endif
  105. #ifdef DYN_NEOVERSEN2
  106. extern gotoblas_t gotoblas_NEOVERSEN2;
  107. #else
  108. #define gotoblas_NEOVERSEN2 gotoblas_ARMV8
  109. #endif
  110. #ifdef DYN_CORTEX_A55
  111. extern gotoblas_t gotoblas_CORTEXA55;
  112. #else
  113. #define gotoblas_CORTEXA55 gotoblas_ARMV8
  114. #endif
  115. #else
  116. extern gotoblas_t gotoblas_CORTEXA53;
  117. extern gotoblas_t gotoblas_CORTEXA57;
  118. extern gotoblas_t gotoblas_CORTEXA72;
  119. extern gotoblas_t gotoblas_CORTEXA73;
  120. extern gotoblas_t gotoblas_FALKOR;
  121. extern gotoblas_t gotoblas_THUNDERX;
  122. extern gotoblas_t gotoblas_THUNDERX2T99;
  123. extern gotoblas_t gotoblas_TSV110;
  124. extern gotoblas_t gotoblas_EMAG8180;
  125. extern gotoblas_t gotoblas_NEOVERSEN1;
  126. extern gotoblas_t gotoblas_NEOVERSEV1;
  127. extern gotoblas_t gotoblas_NEOVERSEN2;
  128. extern gotoblas_t gotoblas_THUNDERX3T110;
  129. extern gotoblas_t gotoblas_CORTEXA55;
  130. #endif
  131. extern void openblas_warning(int verbose, const char * msg);
  132. #define NUM_CORETYPES 13
  133. /*
  134. * In case asm/hwcap.h is outdated on the build system, make sure
  135. * that HWCAP_CPUID is defined
  136. */
  137. #ifndef HWCAP_CPUID
  138. #define HWCAP_CPUID (1 << 11)
  139. #endif
  140. #define get_cpu_ftr(id, var) ({ \
  141. __asm__ __volatile__ ("mrs %0, "#id : "=r" (var)); \
  142. })
  143. static char *corename[] = {
  144. "armv8",
  145. "cortexa53",
  146. "cortexa57",
  147. "cortexa72",
  148. "cortexa73",
  149. "falkor",
  150. "thunderx",
  151. "thunderx2t99",
  152. "tsv110",
  153. "emag8180",
  154. "neoversen1",
  155. "neoversev1",
  156. "neoversen2",
  157. "thunderx3t110",
  158. "cortexa55",
  159. "unknown"
  160. };
  161. char *gotoblas_corename(void) {
  162. if (gotoblas == &gotoblas_ARMV8) return corename[ 0];
  163. if (gotoblas == &gotoblas_CORTEXA53) return corename[ 1];
  164. if (gotoblas == &gotoblas_CORTEXA57) return corename[ 2];
  165. if (gotoblas == &gotoblas_CORTEXA72) return corename[ 3];
  166. if (gotoblas == &gotoblas_CORTEXA73) return corename[ 4];
  167. if (gotoblas == &gotoblas_FALKOR) return corename[ 5];
  168. if (gotoblas == &gotoblas_THUNDERX) return corename[ 6];
  169. if (gotoblas == &gotoblas_THUNDERX2T99) return corename[ 7];
  170. if (gotoblas == &gotoblas_TSV110) return corename[ 8];
  171. if (gotoblas == &gotoblas_EMAG8180) return corename[ 9];
  172. if (gotoblas == &gotoblas_NEOVERSEN1) return corename[10];
  173. if (gotoblas == &gotoblas_NEOVERSEV1) return corename[11];
  174. if (gotoblas == &gotoblas_NEOVERSEN2) return corename[12];
  175. if (gotoblas == &gotoblas_THUNDERX3T110) return corename[13];
  176. if (gotoblas == &gotoblas_CORTEXA55) return corename[14];
  177. return corename[NUM_CORETYPES];
  178. }
  179. static gotoblas_t *force_coretype(char *coretype) {
  180. int i ;
  181. int found = -1;
  182. char message[128];
  183. for ( i=0 ; i < NUM_CORETYPES; i++)
  184. {
  185. if (!strncasecmp(coretype, corename[i], 20))
  186. {
  187. found = i;
  188. break;
  189. }
  190. }
  191. switch (found)
  192. {
  193. case 0: return (&gotoblas_ARMV8);
  194. case 1: return (&gotoblas_CORTEXA53);
  195. case 2: return (&gotoblas_CORTEXA57);
  196. case 3: return (&gotoblas_CORTEXA72);
  197. case 4: return (&gotoblas_CORTEXA73);
  198. case 5: return (&gotoblas_FALKOR);
  199. case 6: return (&gotoblas_THUNDERX);
  200. case 7: return (&gotoblas_THUNDERX2T99);
  201. case 8: return (&gotoblas_TSV110);
  202. case 9: return (&gotoblas_EMAG8180);
  203. case 10: return (&gotoblas_NEOVERSEN1);
  204. case 11: return (&gotoblas_NEOVERSEV1);
  205. case 12: return (&gotoblas_NEOVERSEN2);
  206. case 13: return (&gotoblas_THUNDERX3T110);
  207. case 14: return (&gotoblas_CORTEXA55);
  208. }
  209. snprintf(message, 128, "Core not found: %s\n", coretype);
  210. openblas_warning(1, message);
  211. return NULL;
  212. }
  213. static gotoblas_t *get_coretype(void) {
  214. int implementer, variant, part, arch, revision, midr_el1;
  215. char coremsg[128];
  216. #if (!defined OS_LINUX && !defined OS_ANDROID)
  217. return NULL;
  218. #else
  219. if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
  220. #ifdef __linux
  221. FILE *infile;
  222. char buffer[512], *p, *cpu_part = NULL, *cpu_implementer = NULL;
  223. p = (char *) NULL ;
  224. infile = fopen("/sys/devices/system/cpu/cpu0/regs/identification/midr_el1","r");
  225. if (!infile) return NULL;
  226. fgets(buffer, sizeof(buffer), infile);
  227. midr_el1=strtoul(buffer,NULL,16);
  228. fclose(infile);
  229. #else
  230. snprintf(coremsg, 128, "Kernel lacks cpuid feature support. Auto detection of core type failed !!!\n");
  231. openblas_warning(1, coremsg);
  232. return NULL;
  233. #endif
  234. } else {
  235. get_cpu_ftr(MIDR_EL1, midr_el1);
  236. }
  237. /*
  238. * MIDR_EL1
  239. *
  240. * 31 24 23 20 19 16 15 4 3 0
  241. * -----------------------------------------------------------------
  242. * | Implementer | Variant | Architecture | Part Number | Revision |
  243. * -----------------------------------------------------------------
  244. */
  245. implementer = (midr_el1 >> 24) & 0xFF;
  246. part = (midr_el1 >> 4) & 0xFFF;
  247. switch(implementer)
  248. {
  249. case 0x41: // ARM
  250. switch (part)
  251. {
  252. case 0xd03: // Cortex A53
  253. return &gotoblas_CORTEXA53;
  254. case 0xd07: // Cortex A57
  255. return &gotoblas_CORTEXA57;
  256. case 0xd08: // Cortex A72
  257. return &gotoblas_CORTEXA72;
  258. case 0xd09: // Cortex A73
  259. return &gotoblas_CORTEXA73;
  260. case 0xd0c: // Neoverse N1
  261. return &gotoblas_NEOVERSEN1;
  262. case 0xd49:
  263. return &gotoblas_NEOVERSEN2;
  264. case 0xd40:
  265. return &gotoblas_NEOVERSEV1;
  266. case 0xd05: // Cortex A55
  267. return &gotoblas_CORTEXA55;
  268. }
  269. break;
  270. case 0x42: // Broadcom
  271. switch (part)
  272. {
  273. case 0x516: // Vulcan
  274. return &gotoblas_THUNDERX2T99;
  275. }
  276. break;
  277. case 0x43: // Cavium
  278. switch (part)
  279. {
  280. case 0x0a1: // ThunderX
  281. return &gotoblas_THUNDERX;
  282. case 0x0af: // ThunderX2
  283. return &gotoblas_THUNDERX2T99;
  284. case 0x0b8: // ThunderX3
  285. return &gotoblas_THUNDERX3T110;
  286. }
  287. break;
  288. case 0x48: // HiSilicon
  289. switch (part)
  290. {
  291. case 0xd01: // tsv110
  292. return &gotoblas_TSV110;
  293. }
  294. break;
  295. case 0x50: // Ampere
  296. switch (part)
  297. {
  298. case 0x000: // Skylark/EMAG8180
  299. return &gotoblas_EMAG8180;
  300. }
  301. break;
  302. case 0x51: // Qualcomm
  303. switch (part)
  304. {
  305. case 0xc00: // Falkor
  306. return &gotoblas_FALKOR;
  307. }
  308. break;
  309. default:
  310. snprintf(coremsg, 128, "Unknown CPU model - implementer %x part %x\n",implementer,part);
  311. openblas_warning(1, coremsg);
  312. }
  313. return NULL;
  314. #endif
  315. }
  316. void gotoblas_dynamic_init(void) {
  317. char coremsg[128];
  318. char coren[22];
  319. char *p;
  320. if (gotoblas) return;
  321. p = getenv("OPENBLAS_CORETYPE");
  322. if ( p )
  323. {
  324. gotoblas = force_coretype(p);
  325. }
  326. else
  327. {
  328. gotoblas = get_coretype();
  329. }
  330. if (gotoblas == NULL)
  331. {
  332. snprintf(coremsg, 128, "Falling back to generic ARMV8 core\n");
  333. openblas_warning(1, coremsg);
  334. gotoblas = &gotoblas_ARMV8;
  335. }
  336. if (gotoblas && gotoblas->init) {
  337. strncpy(coren, gotoblas_corename(), 20);
  338. sprintf(coremsg, "Core: %s\n", coren);
  339. openblas_warning(2, coremsg);
  340. gotoblas -> init();
  341. } else {
  342. openblas_warning(0, "OpenBLAS : Architecture Initialization failed. No initialization function found.\n");
  343. exit(1);
  344. }
  345. }
  346. void gotoblas_dynamic_quit(void) {
  347. gotoblas = NULL;
  348. }