16
16
17
17
#include < functional>
18
18
#include < iostream>
19
+ #include < mutex>
20
+ #include < shared_mutex>
19
21
#include < tuple>
22
+
20
23
namespace mlir {
21
24
namespace xegpu {
22
25
namespace uArch {
@@ -99,6 +102,17 @@ struct Restriction {
99
102
std::any apply () { return std::apply (func, data); }
100
103
};
101
104
105
+ // Architecture HW component hierarchy to present thread, core, socket ...
106
+ struct uArchHierarchyComponent {
107
+ std::string name = " " ; // optional name of the hierarchy component
108
+ // no. of lower hierarchy component it contains, e.g., for PVC XeCore it
109
+ // contains 8 threads, so no_of_component=8
110
+ uint no_of_component;
111
+ // Constructor
112
+ uArchHierarchyComponent (const std::string &name, uint no_of_component)
113
+ : name(name), no_of_component(no_of_component) {}
114
+ };
115
+
102
116
// An enum class to represent the functional unit of an instruction
103
117
enum class FunctionalUnit {
104
118
ALU,
@@ -179,6 +193,12 @@ struct Instruction {
179
193
// std::string pipeline;
180
194
// std::string resource;
181
195
// std::string comment;
196
+ Instruction (std::string name, std::string desc, std::string opcode,
197
+ FunctionalUnit fu, InstructionType itype, InstructionScope sc,
198
+ UnitOfComputation uoc)
199
+ : name(std::move(name)), description(std::move(desc)),
200
+ opcode (std::move(opcode)), functional_unit(fu), type(itype), scope(sc),
201
+ unit_of_computation(uoc) {}
182
202
};
183
203
184
204
// A struct to represent register file information
@@ -189,18 +209,30 @@ struct RegisterFileInfo {
189
209
num_regs_per_thread_per_mode; // number of registers per thread per mode
190
210
uint num_banks;
191
211
uint bank_size;
212
+
213
+ // Constructor
214
+ RegisterFileInfo (uint size, const std::vector<std::string> &mode,
215
+ const std::vector<uint> &numRegs, uint num_banks,
216
+ uint bank_size)
217
+ : size(size), mode(mode), num_regs_per_thread_per_mode(numRegs),
218
+ num_banks (num_banks), bank_size(bank_size) {}
192
219
};
193
220
194
221
// A struct to represent cache information
195
222
struct CacheInfo {
196
223
uint size;
197
- uint associativity;
198
224
uint line_size;
199
- uint num_banks;
200
- uint bank_size;
201
- uint num_ports;
202
- uint port_width;
203
- uint bank_conflicts;
225
+ // At which component level the cache is shared
226
+ uArchHierarchyComponent component;
227
+ // uint associativity;
228
+ // uint num_banks;
229
+ // uint bank_size;
230
+ // uint num_ports;
231
+ // uint port_width;
232
+ // uint bank_conflicts;
233
+ // Constructor
234
+ CacheInfo (uint size, uint line_size, const uArchHierarchyComponent &component)
235
+ : size(size), line_size(line_size), component(component) {}
204
236
};
205
237
206
238
// A struct to represent the uArch
@@ -225,19 +257,38 @@ struct CacheInfo {
225
257
struct uArch {
226
258
std::string name; // similar to target triple
227
259
std::string description;
260
+ // Represent the whole uArch hierarchy
261
+ // For 2 stack Intel PVC it would look something like this:
262
+ // uArchHierarchy[0] = {thread, 0}
263
+ // uArchHierarchy[1] = {XeCore, 8}
264
+ // uArchHierarchy[2] = {XeSlice, 16}
265
+ // uArchHierarchy[3] = {XeStack, 4}
266
+ // uArchHierarchy[4] = {gpu, 2}
267
+ std::vector<uArchHierarchyComponent> uArch_hierarchy;
228
268
// Different kind of regiger file information (e.g., GRF, ARF, etc.)
229
- std::vector< RegisterFileInfo> register_file_info;
269
+ std::map<std::string, RegisterFileInfo> register_file_info;
230
270
// Each level of cache is indexed lower to higher in the vector
231
271
// (e.g., L1 indexed at 0, L2 at 1 and so on) L1, L2, L3, etc.
232
272
std::vector<CacheInfo> cache_info;
233
- std::vector< Instruction *> instructions;
273
+ std::map<std::string, Instruction *> instructions;
234
274
std::vector<Restriction<> *> restrictions;
275
+
276
+ // Constructor
277
+ uArch (const std::string &name, const std::string &description,
278
+ const std::vector<uArchHierarchyComponent> &uArch_hierarchy = {},
279
+ const std::map<std::string, RegisterFileInfo> ®ister_file_info = {},
280
+ const std::vector<CacheInfo> &cache_info = {},
281
+ const std::map<std::string, Instruction *> &instructions = {},
282
+ const std::vector<Restriction<> *> &restrictions = {})
283
+ : name(name), description(description), uArch_hierarchy(uArch_hierarchy),
284
+ register_file_info (register_file_info), cache_info(cache_info),
285
+ instructions(instructions), restrictions(restrictions) {}
235
286
};
236
287
237
288
// A struct to represent shared memory information
238
289
struct SharedMemory {
239
- uint size;
240
- uint alignment;
290
+ uint size; // in bytes
291
+ uint alignment; // in bytes
241
292
// @TODO: Add more fields as needed
242
293
// uint latency;
243
294
// uint throughput;
@@ -247,6 +298,9 @@ struct SharedMemory {
247
298
// uint bank_size;
248
299
// uint bank_conflicts;
249
300
// uint num_banks;
301
+
302
+ // Constructor
303
+ SharedMemory (uint size, uint alignment) : size(size), alignment(alignment) {}
250
304
};
251
305
252
306
// For future use case in Xe4+
@@ -293,6 +347,7 @@ struct TileOpInterface {
293
347
// @param array_len, array length
294
348
virtual bool validate (Tile tile, Tile surface, mlir::Type dataType,
295
349
uint surface_pitch, uint array_len = 1 ) = 0;
350
+ virtual ~TileOpInterface () = default ;
296
351
};
297
352
298
353
enum class MatrixType { MatrixA, MatrixB, MatrixC, MatrixD };
@@ -304,11 +359,75 @@ struct MatrixOpInterface {
304
359
virtual std::vector<uint> getSupportedN (mlir::Type type) = 0;
305
360
virtual std::vector<std::pair<unsigned , unsigned >>
306
361
getSupportedMatrix (mlir::Type type, MatrixType matrixType) = 0 ;
362
+
363
+ virtual ~MatrixOpInterface () = default ;
307
364
};
308
365
366
+ struct uArchMap {
367
+ public:
368
+ // Singleton instance
369
+ static uArchMap &instance () {
370
+ static uArchMap instance;
371
+ return instance;
372
+ }
373
+
374
+ // Insert or update a key-value pair
375
+ void insert (const std::string &key, uArch value) {
376
+ std::unique_lock lock (mutex_);
377
+ map_[key] = value;
378
+ }
379
+
380
+ // Get a value by key (concurrent safe read)
381
+ std::optional<uArch> get (const std::string &key) const {
382
+ std::shared_lock lock (mutex_);
383
+ auto it = map_.find (key);
384
+ if (it != map_.end ())
385
+ return it->second ;
386
+ return std::nullopt;
387
+ }
388
+
389
+ // Check if a key exists
390
+ bool contains (const std::string &key) const {
391
+ std::shared_lock lock (mutex_);
392
+ return map_.find (key) != map_.end ();
393
+ }
394
+
395
+ // Remove a key
396
+ bool erase (const std::string &key) {
397
+ std::unique_lock lock (mutex_);
398
+ return map_.erase (key) > 0 ;
399
+ }
400
+
401
+ private:
402
+ uArchMap () = default ;
403
+ uArchMap (const uArchMap &) = delete ;
404
+ uArchMap &operator =(const uArchMap &) = delete ;
405
+
406
+ mutable std::shared_mutex mutex_;
407
+ std::map<std::string, uArch> map_;
408
+ };
409
+
410
+ // std::unordered_map<std::string, uArch> uArchMap;
411
+ // std::shared_mutex uArchMapMutex;
412
+
413
+ // void getuArch(const std::string &key) {
414
+ // std::shared_lock<std::shared_mutex> lock(uArchMapMutex);
415
+ // auto it = uArchMap.find(key);
416
+ // if(it != uArchMap.end())
417
+ // return *it;
418
+ // else
419
+
420
+ // // safe concurrent read
421
+ // }
422
+
423
+ // void AdduArch(const std::string &key, uArch &value) {
424
+ // std::unique_lock<std::shared_mutex> lock(uArchMapMutex);
425
+
426
+ // // exclusive write
427
+ // }
428
+
309
429
} // namespace uArch
310
430
} // namespace xegpu
311
431
} // namespace mlir
312
432
313
433
#endif // MLIR_DIALECT_XEGPU_UTILS_UARCH_H
314
- // ===--- uArch.h ---------------------------------------*- C++ -*-===//
0 commit comments