1
+ /*
2
+ * Copyright (C) 2024 Intel Corporation
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing,
11
+ * software distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions
14
+ * and limitations under the License.
15
+ *
16
+ * SPDX-License-Identifier: Apache-2.0
17
+ */
18
+
19
+ #include " mlir/Bindings/Python/PybindAdaptors.h"
20
+
21
+ #if defined(__x86_64__) || defined(_M_X64) || defined(__i386__) || \
22
+ defined (_M_IX86)
23
+ // x86 or x86_64 specific code
24
+ void cpuid(int info[4 ], int leaf, int subleaf) {
25
+ __asm__ __volatile__ (" cpuid"
26
+ : " =a" (info[0 ]), " =b" (info[1 ]), " =c" (info[2 ]),
27
+ " =d" (info[3 ])
28
+ : " a" (leaf), " c" (subleaf));
29
+ }
30
+
31
+ std::vector<int > getCacheSizes () {
32
+ int info[4 ];
33
+ cpuid (info, 0 , 0 );
34
+ int nIds = info[0 ];
35
+ int caches[3 ] = {};
36
+ for (int i = 0 ; i <= nIds; ++i) {
37
+ cpuid (info, 4 , i);
38
+ int cacheType = info[0 ] & 0x1F ;
39
+ if (cacheType == 0 ) {
40
+ break ;
41
+ }
42
+ if (cacheType == 2 ) {
43
+ // skip instruction cache
44
+ continue ;
45
+ }
46
+ int cacheLevel = (info[0 ] >> 5 ) & 0x7 ;
47
+ int cacheLinesPerTag = ((info[1 ] >> 0 ) & 0xFFF ) + 1 ;
48
+ int cacheAssociativity = ((info[1 ] >> 12 ) & 0x3FF ) + 1 ;
49
+ int cachePartitions = ((info[1 ] >> 22 ) & 0x3FF ) + 1 ;
50
+ int cacheSets = info[2 ] + 1 ;
51
+ int cacheSize =
52
+ cacheLinesPerTag * cacheAssociativity * cachePartitions * cacheSets;
53
+ if (cacheLevel >= 1 && cacheLevel <= 3 ) {
54
+ caches[cacheLevel - 1 ] = cacheSize;
55
+ }
56
+ }
57
+ return std::vector<int >(std::begin (caches), std::end (caches));
58
+ }
59
+
60
+ bool isFeatureSupported (int function_id, int register_idx, int bit) {
61
+ int info[4 ];
62
+ cpuid (info, function_id, 0 );
63
+ return (info[register_idx] & (1 << bit)) != 0 ;
64
+ }
65
+
66
+ int getMaxVectorWidth () {
67
+ if (isFeatureSupported (7 , 1 , 16 )) { // Check for AVX-512F support
68
+ return 512 ;
69
+ } else if (isFeatureSupported (1 , 2 , 28 )) { // Check for AVX support
70
+ return 256 ;
71
+ } else if (isFeatureSupported (1 , 3 , 25 )) { // Check for SSE support
72
+ return 128 ;
73
+ }
74
+ return 64 ; // Default to 64 if none of the above features are supported
75
+ }
76
+ #else
77
+ std::vector<int > getCacheSizes () { return {}; }
78
+
79
+ int getMaxVectorWidth { return 0 ; }
80
+ #endif
81
+
82
+ PYBIND11_MODULE (_cpuinfo, m) {
83
+ m.doc () = " Graph-compiler MLIR Python binding" ;
84
+ m.def (" get_cache_sizes" , &getCacheSizes, " Get CPU L1,L2,L3 cache size" );
85
+ m.def (" get_max_vector_width" , &getMaxVectorWidth,
86
+ " Get CPU supported max vector width" );
87
+ }
0 commit comments