1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2020-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #ifndef _IGA_BACKEND_MESSAGES_MESSAGEDECODER_HPP_ 10 #define _IGA_BACKEND_MESSAGES_MESSAGEDECODER_HPP_ 11 12 #include "../../IR/Messages.hpp" 13 #include "../../Frontend/IRToString.hpp" 14 #include "../../asserts.hpp" 15 #include "../Native/Field.hpp" 16 #include "../../Models/Models.hpp" 17 18 #include <algorithm> 19 #include <functional> 20 #include <sstream> 21 #include <tuple> 22 #include <vector> 23 24 namespace iga { 25 using DescFieldFormatter = 26 std::function<void (std::stringstream &,uint32_t)>; NO_DECODE(std::stringstream &,uint32_t)27 static inline void NO_DECODE(std::stringstream &,uint32_t) { } 28 29 30 struct MessageDecoder { 31 // inputs 32 const Model &decodeModel; 33 const SFID sfid; 34 ExecSize instExecSize; 35 const SendDesc desc, exDesc; 36 37 // outputs 38 DecodeResult &result; 39 40 const int DEFAULT_EXEC_SIZE, BITS_PER_REGISTER; 41 MessageDecoderiga::MessageDecoder42 MessageDecoder( 43 Platform _platform, 44 SFID _sfid, 45 ExecSize _instExecSize, 46 SendDesc _exDesc, 47 SendDesc _desc, 48 DecodeResult &_result) 49 : decodeModel(Model::LookupModelRef(_platform)) 50 , sfid(_sfid) 51 , instExecSize(_instExecSize) 52 // 53 , desc(_desc) 54 , exDesc(_exDesc) 55 // 56 , result(_result) 57 // 58 , DEFAULT_EXEC_SIZE((_platform >= Platform::XE_HPC) ? 32 : 16) 59 , BITS_PER_REGISTER((_platform >= Platform::XE_HPC) ? 512 : 256) 60 { 61 result.info.op = SendOp::INVALID; 62 result.info.cachingL3 = result.info.cachingL1 = CacheOpt::DEFAULT; 63 result.info.elemSizeBitsRegFile = result.info.elemSizeBitsMemory = 0; 64 result.info.channelsEnabled = result.info.elemsPerAddr = 0; 65 result.info.execWidth = 66 _instExecSize != ExecSize::INVALID ? int(_instExecSize) : 0; 67 result.info.attributeSet = MessageInfo::Attr::NONE; 68 result.info.addrType = AddrType::FLAT; 69 result.info.surfaceId = 0; 70 result.info.immediateOffset = 0; 71 result.info.docs = nullptr; 72 // 73 // syntax.sfid = _sfid; 74 result.syntax.controls = "." + ToSyntax(_sfid); 75 // 76 decodePayloadSizes(); 77 } 78 platformiga::MessageDecoder79 Platform platform() const { 80 return model().platform; 81 } 82 modeliga::MessageDecoder83 const Model &model() const { 84 return decodeModel; 85 } 86 platformInRangeiga::MessageDecoder87 bool platformInRange(Platform lo, Platform hi) const { 88 return platform() >= lo && platform() <= hi; 89 } 90 setDociga::MessageDecoder91 void setDoc(const char *doc) { 92 setDoc(doc, doc, doc); 93 } setDociga::MessageDecoder94 void setDoc(const char *preXe, const char *xe, const char *) { 95 result.info.docs = chooseDoc(preXe, xe, "?"); 96 } chooseDociga::MessageDecoder97 const char *chooseDoc( 98 const char *preXe, const char *xe, const char *) const 99 { 100 preXe = preXe ? preXe : "?"; 101 xe = xe ? xe : "?"; 102 return platform() < Platform::XE ? preXe : xe; 103 } 104 105 ///////////////////////////////////////////////////////////// 106 // diagnostics 107 template < 108 typename T1, 109 typename T2 = const char *, 110 typename T3 = const char *> addDiagiga::MessageDecoder111 void addDiag( 112 DiagnosticList &dl, 113 int off, int len, 114 T1 t1, 115 T2 t2 = "", 116 T3 t3 = "") 117 { 118 std::stringstream ss; 119 ss << t1 << t2 << t3; 120 dl.emplace_back(DescField(off,len), ss.str()); 121 } 122 template <typename T1, 123 typename T2 = const char *, typename T3 = const char *> warningiga::MessageDecoder124 void warning(int off, int len, T1 t1, T2 t2 = "", T3 t3 = "") { 125 addDiag(result.warnings, off, len, t1, t2, t3); 126 } 127 template <typename T1, 128 typename T2 = const char *, typename T3 = const char *> erroriga::MessageDecoder129 void error(int off, int len, T1 t1, T2 t2 = "", T3 t3 = "") { 130 addDiag(result.errors, off, len, t1, t2, t3); 131 } 132 133 // offset +32 to 64 fetch from exDesc 134 // peeks at a field without adding it getDescBitsiga::MessageDecoder135 uint32_t getDescBits(int off, int len) const { 136 uint32_t bits = desc.imm; 137 if (off >= 32) { 138 off -= 32; 139 bits = exDesc.imm; 140 } 141 uint32_t mask = len == 32 ? 0xFFFFFFFF : ((1 << len) - 1); 142 return (int)((bits >> off) & mask); 143 } 144 getDescBitiga::MessageDecoder145 uint32_t getDescBit(int off) const { 146 return getDescBits(off, 1) != 0; 147 } 148 decodeExDescFieldiga::MessageDecoder149 uint32_t decodeExDescField( 150 const char *fieldName, 151 int off, 152 int len, 153 DescFieldFormatter fmtMeaning = NO_DECODE) 154 { 155 auto val = getDescBits(off + 32, len); 156 std::stringstream ss; 157 fmtMeaning(ss, val); 158 addField(fieldName, off + 32, len, val, ss.str()); 159 return val; 160 } decodeDescFieldiga::MessageDecoder161 uint32_t decodeDescField( 162 const char *fieldName, 163 int off, 164 int len, 165 DescFieldFormatter fmtMeaning = NO_DECODE) 166 { 167 auto val = getDescBits(off, len); 168 std::stringstream ss; 169 fmtMeaning(ss, val); 170 addField(fieldName, off, len, val, ss.str()); 171 return val; 172 } decodeDescBitFieldiga::MessageDecoder173 uint32_t decodeDescBitField( 174 const char *fieldName, 175 int off, 176 const char *zero, 177 const char *one) 178 { 179 return decodeDescField(fieldName, off, 1, 180 [&] (std::stringstream &ss, uint32_t val) { 181 ss << (val ? one : zero); 182 }); 183 } decodeDescBitFieldiga::MessageDecoder184 uint32_t decodeDescBitField( 185 const char *fieldName, 186 int off, 187 const char *one) 188 { 189 return decodeDescBitField(fieldName, off, "", one); 190 } 191 192 // normally use getDescBitsField, but in cases where you've already 193 // decoded, the meaning and just want to record the result addFieldiga::MessageDecoder194 void addField( 195 const char *fieldName, 196 int off, 197 int len, 198 uint32_t val, 199 std::string meaning) 200 { 201 Fragment f(fieldName, off, len); 202 for (const auto &fvs : result.fields) { 203 const auto &f1 = std::get<0>(fvs); 204 if (f1.overlaps(f)) { 205 // uncomment for debugging 206 // std::stringstream ss; 207 // ss << "overlapped fields: " << f1.name << " and " << f.name; 208 // IGA_ASSERT_FALSE(ss.str().c_str()); 209 return; // replicated access (don't record again) 210 } 211 } 212 result.fields.emplace_back(f, val, meaning); 213 } 214 215 /////////////////////////////////////////////////////////////////////////// 216 // decoder helpers decodeExpectediga::MessageDecoder217 bool decodeExpected( 218 int off, 219 int len, 220 const char *fieldName, 221 uint32_t expected) 222 { 223 auto val = getDescBits(off, len); 224 if (val != expected) { 225 warning(off, len, "field should be ", expected); 226 } 227 addField(fieldName, off, len, val, ""); 228 return val == expected; 229 } 230 231 // decodes MLen, RLen, and XLen if present 232 // (Src0.Length, Dst.Length, Src1.Length) 233 void decodePayloadSizes(); 234 235 /////////////////////////////////////////////////////////////////////////// 236 // the most generic setter setScatterGatherOpXiga::MessageDecoder237 void setScatterGatherOpX( 238 std::string msgSym, 239 std::string msgImpl, 240 SendOp op, 241 AddrType addrType, 242 SendDesc surfaceId, 243 CacheOpt l1, 244 CacheOpt l3, 245 int addrSize, 246 int bitsPerElemReg, int bitsPerElemMem, 247 int elemsPerAddr, 248 int simd, 249 MessageInfo::Attr extraAttrs = MessageInfo::Attr::NONE) 250 { 251 MessageInfo &mi = result.info; 252 mi.symbol = msgSym; 253 mi.description = msgImpl; 254 mi.op = op; 255 mi.cachingL1 = l1; 256 mi.cachingL3 = l3; 257 mi.addrType = addrType; 258 mi.surfaceId = surfaceId; 259 mi.attributeSet |= extraAttrs; 260 mi.addrSizeBits = addrSize; 261 mi.elemSizeBitsRegFile = bitsPerElemReg; 262 mi.elemSizeBitsMemory = bitsPerElemMem; 263 mi.elemsPerAddr = elemsPerAddr; 264 mi.channelsEnabled = 0; 265 mi.execWidth = simd; 266 } 267 setScatterGatherOpiga::MessageDecoder268 void setScatterGatherOp( 269 std::string msgSym, 270 std::string msgDesc, 271 SendOp op, 272 AddrType addrType, 273 SendDesc surfaceId, 274 int addrSize, 275 int bitsPerElem, 276 int elemsPerAddr, 277 int simd, 278 MessageInfo::Attr extraAttrs = MessageInfo::Attr::NONE) 279 { 280 setScatterGatherOpX( 281 msgSym, 282 msgDesc, 283 op, 284 addrType, 285 surfaceId, 286 CacheOpt::DEFAULT, 287 CacheOpt::DEFAULT, 288 addrSize, 289 bitsPerElem, bitsPerElem, 290 elemsPerAddr, 291 simd, 292 extraAttrs); 293 } 294 295 // for miscellaneous stuff such as fences and whatnot 296 // 297 // treat the payloads as full register units and set the op to SIMD1 setSpecialOpXiga::MessageDecoder298 void setSpecialOpX( 299 std::string msgSym, 300 std::string msgDesc, 301 SendOp op, 302 AddrType addrType, 303 SendDesc surfaceId, 304 int mlen, 305 int rlen, 306 MessageInfo::Attr extraAttrs = MessageInfo::Attr::NONE) 307 { 308 MessageInfo &mi = result.info; 309 mi.symbol = msgSym; 310 mi.description = msgDesc; 311 mi.op = op; 312 mi.cachingL1 = CacheOpt::DEFAULT; 313 mi.cachingL3 = CacheOpt::DEFAULT; 314 mi.addrType = addrType; 315 mi.surfaceId = surfaceId; 316 mi.addrSizeBits = mlen*BITS_PER_REGISTER; 317 // e.g. SIMD16 platforms are 256b (two full registers) 318 mi.elemSizeBitsRegFile = rlen*BITS_PER_REGISTER; 319 mi.elemSizeBitsMemory = mi.elemSizeBitsRegFile; 320 mi.channelsEnabled = 0; 321 mi.elemsPerAddr = 1; 322 mi.execWidth = 1; 323 mi.attributeSet = extraAttrs | MessageInfo::Attr::VALID; 324 } 325 326 // shared by subclasses 327 void addLscFenceFields( 328 std::stringstream &sym, std::stringstream &desc); 329 void addLscFenceScopeField( 330 std::stringstream &sym, std::stringstream &desc); 331 void addLscFencePortFields( 332 std::stringstream &sym, std::stringstream &desc); 333 }; // MessageDecoder 334 335 336 /////////////////////////////////////////////////////////////////////////// 337 // shared by MessageDecoderHDC, MessageDecoderOther 338 struct MessageDecoderLegacy : MessageDecoder { 339 static const int SLM_BTI = 0xFE; 340 static const int COHERENT_BTI = 0xFF; 341 static const int NONCOHERENT_BTI = 0xFD; MessageDecoderLegacyiga::MessageDecoderLegacy342 MessageDecoderLegacy( 343 Platform _platform, 344 SFID _sfid, 345 ExecSize _instExecSize, 346 SendDesc _exDesc, 347 SendDesc _desc, 348 DecodeResult &_result) 349 : MessageDecoder( 350 _platform, _sfid, _instExecSize, 351 _exDesc, _desc, _result) 352 { 353 } 354 355 // from legacy encodings decodeBTIiga::MessageDecoderLegacy356 int decodeBTI(int addrBits) { 357 int bti = (int)getDescBits(0, 8); 358 std::stringstream ss; 359 ss << "surface " << bti; 360 if (bti == SLM_BTI) { 361 ss << " (SLM)"; 362 } else if (bti == COHERENT_BTI) { 363 if (addrBits == 64) 364 ss << " A64 "; 365 else 366 ss << " A32 "; 367 ss << " (coherent stateless)"; 368 } else if (bti == NONCOHERENT_BTI) { 369 if (addrBits == 64) 370 ss << " A64"; 371 else 372 ss << " A32"; 373 ss << " (incoherent stateless)"; 374 } else if (bti == 0xFC) { 375 ss << " (SSO)"; 376 } 377 addField("BTI", 0, 8, bti, ss.str()); 378 return bti; 379 } 380 381 ///////////////////////////////////////////////////// 382 // "header" decoding decodeMDC_Higa::MessageDecoderLegacy383 bool decodeMDC_H() { // optional 384 return decodeDescBitField( 385 "Header", 386 19, 387 "absent", 388 "included") != 0; 389 } decodeMDC_HFiga::MessageDecoderLegacy390 void decodeMDC_HF() { 391 if (getDescBit(19) != 0) 392 warning(19, 1, 393 "this message forbids a header (and it's included)"); 394 } decodeMDC_HRiga::MessageDecoderLegacy395 void decodeMDC_HR() { 396 if (!decodeMDC_H()) 397 warning(19, 1, 398 "this message requires a header (and it's absent)"); 399 } decodeMDC_H2iga::MessageDecoderLegacy400 bool decodeMDC_H2() { 401 return decodeDescBitField( 402 "DualHeader", 19, "absent", 403 "included (two register header)") != 0; 404 } 405 406 /////////////////////////////////////////////////////////////////////// 407 // some shared decoder helpers decodeMDC_SM2iga::MessageDecoderLegacy408 int decodeMDC_SM2(int off) { 409 // yeah SM2 is really 1 bit (2 means two values) 410 int bits = 411 decodeDescBitField("SimdMode:MDC_SM2", off, "SIMD8", "SIMD16"); 412 return bits ? 16 : 8; 413 } 414 }; // MessageDecoderLegacy 415 416 // see MessageDecoderHDC.cpp 417 void decodeDescriptorsHDC( 418 Platform platform, SFID sfid, ExecSize execSize, 419 SendDesc exDesc, SendDesc desc, 420 DecodeResult &result); 421 422 // see MessageDecoderOther.cpp 423 void decodeDescriptorsOther( 424 Platform platform, SFID sfid, ExecSize execSize, 425 SendDesc exDesc, SendDesc desc, 426 DecodeResult &result); 427 428 void decodeDescriptorsLSC( 429 Platform platform, SFID sfid, ExecSize execSize, 430 SendDesc exDesc, SendDesc desc, 431 DecodeResult &result); 432 433 bool encodeDescriptorsLSC( 434 Platform p, 435 const VectorMessageArgs &vma, 436 SendDesc &exDesc, 437 SendDesc &desc, 438 std::string &err); 439 440 } // iga:: 441 442 #endif // _IGA_BACKEND_MESSAGES_MESSAGEDECODER_HPP_ 443