4
4
#pragma once
5
5
6
6
#include " types.h"
7
+ #include " debug.h"
7
8
8
9
namespace pcm
9
10
{
@@ -25,6 +26,7 @@ struct PCM_API TopologyEntry // describes a core
25
26
int32 die_grp_id;
26
27
int32 socket_id;
27
28
int32 socket_unique_core_id;
29
+ int32 l3_cache_id = -1 ;
28
30
int32 native_cpu_model = -1 ;
29
31
enum DomainTypeID
30
32
{
@@ -103,7 +105,7 @@ inline void fillEntry(TopologyEntry & entry, const uint32 & smtMaskWidth, const
103
105
entry.socket_unique_core_id = entry.core_id ;
104
106
}
105
107
106
- inline bool initCoreMasks (uint32 & smtMaskWidth, uint32 & coreMaskWidth, uint32 & l2CacheMaskShift)
108
+ inline bool initCoreMasks (uint32 & smtMaskWidth, uint32 & coreMaskWidth, uint32 & l2CacheMaskShift, uint32 & l3CacheMaskShift )
107
109
{
108
110
// init constants for CPU topology leaf 0xB
109
111
// adapted from Topology Enumeration Reference code for Intel 64 Architecture
@@ -154,24 +156,62 @@ inline bool initCoreMasks(uint32 & smtMaskWidth, uint32 & coreMaskWidth, uint32
154
156
155
157
(void ) coreMaskWidth; // to suppress warnings on MacOS (unused vars)
156
158
157
- #ifdef PCM_DEBUG_TOPOLOGY
158
- uint32 threadsSharingL2;
159
- #endif
160
- uint32 l2CacheMaskWidth;
159
+ uint32 threadsSharingL2 = 0 ;
160
+ uint32 l2CacheMaskWidth = 0 ;
161
161
162
162
pcm_cpuid (0x4 , 2 , cpuid_args); // get ID for L2 cache
163
163
l2CacheMaskWidth = 1 + extract_bits_32 (cpuid_args.array [0 ],14 ,25 ); // number of APIC IDs sharing L2 cache
164
- #ifdef PCM_DEBUG_TOPOLOGY
165
164
threadsSharingL2 = l2CacheMaskWidth;
166
- #endif
167
165
for ( ; l2CacheMaskWidth > 1 ; l2CacheMaskWidth >>= 1 )
168
166
{
169
167
l2CacheMaskShift++;
170
168
}
171
- #ifdef PCM_DEBUG_TOPOLOGY
172
- std::cerr << " DEBUG: Number of threads sharing L2 cache = " << threadsSharingL2
173
- << " [the most significant bit = " << l2CacheMaskShift << " ]\n " ;
174
- #endif
169
+ DBG (1 , " Number of threads sharing L2 cache = " , threadsSharingL2, " [the most significant bit = " , l2CacheMaskShift , " ]" );
170
+
171
+ uint32 threadsSharingL3 = 0 ;
172
+ uint32 l3CacheMaskWidth = 0 ;
173
+
174
+ pcm_cpuid (0x4 , 3 , cpuid_args); // get ID for L3 cache
175
+ l3CacheMaskWidth = 1 + extract_bits_32 (cpuid_args.array [0 ], 14 , 25 ); // number of APIC IDs sharing L3 cache
176
+ threadsSharingL3 = l3CacheMaskWidth;
177
+ for ( ; l3CacheMaskWidth > 1 ; l3CacheMaskWidth >>= 1 )
178
+ {
179
+ l3CacheMaskShift++;
180
+ }
181
+ DBG (1 , " Number of threads sharing L3 cache = " , threadsSharingL3, " [the most significant bit = " , l3CacheMaskShift , " ]" );
182
+
183
+ uint32 it = 0 ;
184
+
185
+ for (int i = 0 ; i < 100 ; ++i)
186
+ {
187
+ uint32 threadsSharingCache = 0 ;
188
+ uint32 CacheMaskWidth = 0 ;
189
+ uint32 CacheMaskShift = 0 ;
190
+ pcm_cpuid (0x4 , it, cpuid_args);
191
+ const auto cacheType = extract_bits_32 (cpuid_args.array [0 ], 0 , 4 );
192
+ if (cacheType == 0 )
193
+ {
194
+ break ; // no more caches
195
+ }
196
+ const char * cacheTypeStr = nullptr ;
197
+ switch (cacheType)
198
+ {
199
+ case 1 : cacheTypeStr = " data" ; break ;
200
+ case 2 : cacheTypeStr = " instruction" ; break ;
201
+ case 3 : cacheTypeStr = " unified" ; break ;
202
+ default : cacheTypeStr = " unknown" ; break ;
203
+ }
204
+ const auto level = extract_bits_32 (cpuid_args.array [0 ], 5 , 7 );
205
+ CacheMaskWidth = 1 + extract_bits_32 (cpuid_args.array [0 ], 14 , 25 ); // number of APIC IDs sharing cache
206
+ threadsSharingCache = CacheMaskWidth;
207
+ for ( ; CacheMaskWidth > 1 ; CacheMaskWidth >>= 1 )
208
+ {
209
+ CacheMaskShift++;
210
+ }
211
+ DBG (1 , " Max number of threads sharing L" , level , " " , cacheTypeStr , " cache = " , threadsSharingCache, " [the most significant bit = " , CacheMaskShift , " ]" ,
212
+ " shift = " , CacheMaskShift);
213
+ ++it;
214
+ }
175
215
}
176
216
return true ;
177
217
}
0 commit comments