1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #ifndef G4_SEND_DESCS_HPP
10 #define G4_SEND_DESCS_HPP
11
12 #include "Common_ISA.h"
13
14 #include <string>
15 #include <ostream>
16 #include <utility>
17
18 namespace vISA
19 {
20 enum class SendAccess
21 {
22 INVALID = 0,
23 READ_ONLY, // e.g. load
24 WRITE_ONLY, // e.g. store
25 READ_WRITE // e.g. an atomic with return
26 };
27 static const int LDST_LOAD_GROUP = 0x100;
28 static const int LDST_STORE_GROUP = 0x200;
29 static const int LDST_ATOMIC_GROUP = 0x400;
30 static const int LDST_OTHER_GROUP = 0x800;
31 //
32 // load/store operation
33 enum class LdStOp {
34 INVALID = 0,
35 //
36 LOAD = LDST_LOAD_GROUP + 1,
37 LOAD_QUAD, // e.g. untyped load (loading XYZW)
38 LOAD_STRIDED, // same as load, but 1 address (obeys exec mask)
39 LOAD_BLOCK2D,
40 //
41 STORE_GROUP = LDST_STORE_GROUP + 1,
42 STORE,
43 STORE_QUAD,
44 STORE_STRIDED,
45 STORE_BLOCK2D,
46 //
47 // atomics
48 ATOMIC_GROUP = LDST_ATOMIC_GROUP + 1,
49 ATOMIC_LOAD,
50 ATOMIC_STORE,
51 //
52 ATOMIC_FADD,
53 ATOMIC_FSUB,
54 ATOMIC_FMIN,
55 ATOMIC_FMAX,
56 ATOMIC_FCAS,
57 //
58 ATOMIC_IINC,
59 ATOMIC_IDEC,
60 ATOMIC_IADD,
61 ATOMIC_ISUB,
62 ATOMIC_ICAS,
63 ATOMIC_SMIN,
64 ATOMIC_SMAX,
65 ATOMIC_UMIN,
66 ATOMIC_UMAX,
67 //
68 ATOMIC_AND,
69 ATOMIC_XOR,
70 ATOMIC_OR,
71 // others ...
72 };
73 std::string ToSymbol(LdStOp);
74
75 enum class LdStOrder {
76 INVALID = 0,
77 //
78 SCALAR, // aka "transposed", typically SIMD1, should be (W)
79 VECTOR, // normal vector message or atomic (honors the execution mask)
80 };
81 enum class AddrType {
82 INVALID = 0,
83 //
84 FLAT,
85 SS, BSS,
86 BTI
87 };
88
89 // Cache controls
90 // only certain combinations are legal
91 enum class Caching {
92 // the invalid value for caching
93 INVALID = 0,
94 //
95 CA, // cached (load)
96 DF, // default (load/store)
97 RI, // read-invalidate (load)
98 WB, // writeback (store)
99 UC, // uncached (load)
100 ST, // streaming (load/store)
101 WT, // writethrough (store)
102 };
103 std::string ToSymbol(Caching);
104 // default, default returns ""
105 std::string ToSymbol(Caching,Caching);
106
107 struct ImmOff {
108 bool is2d;
109 union {
110 int immOff;
111 struct {short immOffX, immOffY;};
112 };
ImmOffvISA::ImmOff113 ImmOff(int imm) : is2d(false), immOff(imm) { }
ImmOffvISA::ImmOff114 ImmOff(short immX, short immY) : is2d(true), immOffX(immX), immOffY(immY) { }
ImmOffvISA::ImmOff115 ImmOff() : ImmOff(0) { }
116 };
117
118 enum class LdStAttrs {
119 NONE = 0,
120 //
121 // for atomic messages that don't indicate if the return value is used
122 ATOMIC_RETURN = 0x0001,
123 //
124 // for cases where the message does not imply if it is a scratch access
125 SCRATCH_SURFACE = 0x0002,
126 };
operator |(LdStAttrs a0,LdStAttrs a1)127 static inline LdStAttrs operator|(LdStAttrs a0, LdStAttrs a1) {
128 return LdStAttrs(int(a0) | int(a1));
129 }
130
131 // Abstraction for the nubmer of elements each address loads.
132 // Generally this is just a simple value (e.g. V4 would be 4), but we
133 // also support the channel mask nonsense added by LOAD_QUAD, STORE_QUAD.
134 struct ElemsPerAddr {
135 // A friendly four-element bitset that is inductively closed and
136 // correct under the custom | operator below
137 enum class Chs {
138 INVALID = 0,
139 //
140 X = 1,
141 Y = 2,
142 Z = 4,
143 W = 8,
144 //
145 XY = X | Y,
146 XZ = X | Z,
147 XW = X | W,
148 XYZ = X | Y | Z,
149 XYW = X | Y | W,
150 XZW = X | Z | W,
151 XYZW = X | Y | Z | W,
152 //
153 YZ = Y | Z,
154 YW = Y | W,
155 YZW = Y | Z | W,
156 //
157 ZW = Z | W,
158 };
159
160 // works on both channel masks and vector lengths
161 int getCount() const;
162
isChannelMaskvISA::ElemsPerAddr163 bool isChannelMask() const {return isChMask;}
164
165 // asserts if not isChannelMask()
166 Chs getMask() const;
167
168 std::string str() const;
169
ElemsPerAddrvISA::ElemsPerAddr170 ElemsPerAddr(int _count) : isChMask(false), count(_count) { }
ElemsPerAddrvISA::ElemsPerAddr171 ElemsPerAddr(Chs chs) : isChMask(true), channels(chs) { }
172 private:
173 bool isChMask;
174 union {
175 int count;
176 Chs channels;
177 };
178 }; // ElemsPerAddr
operator |(ElemsPerAddr::Chs c0,ElemsPerAddr::Chs c1)179 static inline ElemsPerAddr::Chs operator|(
180 ElemsPerAddr::Chs c0, ElemsPerAddr::Chs c1)
181 {
182 return ElemsPerAddr::Chs(int(c0) | int(c1));
183 }
184
185
186 class G4_Operand;
187
188 // Base class for all send descriptors.
189 // (Note that G4_SendDesc could be reused by more than one instruction.)
190 class G4_SendDesc
191 {
192 friend class G4_InstSend;
193
194 protected:
195 // The execution size for this message.
196 G4_ExecSize execSize;
197
198 // Limit access to G4_InstSend and any derived classes.
setExecSize(G4_ExecSize v)199 void setExecSize(G4_ExecSize v) { execSize = v; }
200
201 public:
202 enum class Kind {INVALID, RAW, LDST};
203
204 Kind kind;
205
206 SFID sfid;
207
G4_SendDesc(Kind k,SFID _sfid)208 G4_SendDesc(Kind k, SFID _sfid) : kind(k), sfid(_sfid), execSize(g4::SIMD_UNDEFINED) { }
G4_SendDesc(Kind k,SFID _sfid,G4_ExecSize _execSize)209 G4_SendDesc(Kind k, SFID _sfid, G4_ExecSize _execSize)
210 : kind(k),
211 sfid(_sfid),
212 execSize(_execSize)
213 {}
214
getSFID() const215 SFID getSFID() const {return sfid;}
216
217 // execSize: need to set it in the ctor
getExecSize() const218 G4_ExecSize getExecSize() const { return execSize; }
219
isRaw() const220 bool isRaw() const {return kind == Kind::RAW;}
isLdSt() const221 bool isLdSt() const {return kind == Kind::LDST;}
222 //
223 bool isHDC() const;
224 bool isLSC() const;
isSampler() const225 bool isSampler() const {return getSFID() == SFID::SAMPLER;}
226 //
227 virtual bool isEOT() const = 0;
228 virtual bool isSLM() const = 0;
229 virtual bool isTyped() const = 0;
230 virtual bool isAtomic() const = 0;
231 virtual bool isBarrier() const = 0;
232 virtual bool isFence() const = 0;
233 //
234 // This gives a general access type
235 virtual SendAccess getAccessType() const = 0;
isRead() const236 bool isRead() const {
237 return
238 getAccessType() == SendAccess::READ_ONLY ||
239 getAccessType() == SendAccess::READ_WRITE;
240 }
isWrite() const241 bool isWrite() const {
242 return
243 getAccessType() == SendAccess::WRITE_ONLY ||
244 getAccessType() == SendAccess::READ_WRITE;
245 }
isReadWrite() const246 bool isReadWrite() const {
247 return getAccessType() == SendAccess::READ_WRITE;
248 }
249 //
250 // Returns the caching behavior of this message if known.
251 // Returns Caching::INVALID if the message doesn't support caching
252 // controls.
253 virtual std::pair<Caching,Caching> getCaching() const = 0;
getCachingL1() const254 Caching getCachingL1() const {return getCaching().first;}
getCachingL3() const255 Caching getCachingL3() const {return getCaching().second;}
256 virtual void setCaching(Caching l1, Caching l3) = 0;
257 //
258 // generally in multiples of full GRFs, but a few exceptions such
259 // as OWord and HWord operations may make this different
260 virtual size_t getDstLenBytes() const = 0;
261 virtual size_t getSrc0LenBytes() const = 0;
262 virtual size_t getSrc1LenBytes() const = 0;
263 //
264 // These round up to the nearest register.
265 // For legacy uses (e.g. MessageLength, exMessageLength(), ...)
266 // (e.g. an OWord block read will report 1 register)
267 // Favor the get{Dst,Src0,Src1}LenBytes() methods.
268 size_t getDstLenRegs() const;
269 size_t getSrc0LenRegs() const;
270 size_t getSrc1LenRegs() const;
271 //
272 // true if the message is a scratch space access (e.g. scratch block read)
273 virtual bool isScratch() const = 0;
274 //
isScratchRead() const275 bool isScratchRead() const{return isScratch() && isRead();}
isScratchWrite() const276 bool isScratchWrite() const {return isScratch() && isWrite();}
277 //
278 // message offset in terms of bytes
279 // e.g. scratch offset
280 virtual int getOffset() const = 0;
281
282 // Returns the associated surface (if any)
283 // This can be a BTI (e.g. a0 register or G4_Imm if immediate)
284 virtual G4_Operand *getSurface() const = 0;
285
286 virtual std::string getDescription() const = 0;
287 };
288
289
290 ///////////////////////////////////////////////////////////////////////////////
291 // high-level load/store descriptors
292
293 //
294 // A Load/Store message descriptor
295 // Unlike G4_SendDescRaw, this descriptor will be encoded by the
296 // IGA adapter or further back.
297 //
298 // Just because you can specify it here does not mean there's a valid message.
299 // Check canEncode().
300 struct G4_SendDescLdSt : G4_SendDesc {
301 // The message op
302 LdStOp op;
303
304 // E.g. flat, bti, ...
305 AddrType addrType;
306 //
307 // e.g. 64 for A64, 32 for A32
308 int addrBits;
309 //
310 // Untyped linear acccesses will have 1 (general case)
311 // Typed messages can have 1-4.
312 // Any two dimensions block opreations will have 2.
313 int addrDims;
314
315 //
316 // The number of bits per element loaded from memory by this message.
317 // E.g. D32 would be 32
318 // E.g. D8U32 ==> 8
319 int elemBitsMem;
320 //
321 // The number of bits each element occupies in the register file
322 // This is generally the same as memory with minor exceptions for aligned
323 // loads (e.g. byte scattered loads that align bytes or words to 32b)
324 // e.g. D8U32 has 32 for this and 8 for `elemBitsMem`
325 int elemBitsReg;
326 //
327 // The number of elements we load per address.
328 // e.g. D32V4 would be 4
329 // for load_quad/store_quad this will be 1, 2, 3, 4
330 // e.g. V3 would imply .XYZ
331 // exotic strided load_quad stuff like .ZW is illegal
332 // i.e. we only support .X, .XY, .XYZ, and .XYZW
333 int elemPerAddr;
334 //
335 // The data order message kind
336 LdStOrder order; // "transposed" ==> 1 address
337
338 // The caching options for L1 and L3
339 Caching l1, l3;
340
341 // an immediate offset to add to each element (if supported)
342 ImmOff immOff;
343
344 // For messages that take a surface (e.g. a0.#)
345 // This must be either:
346 // - nullptr for FLAT messages such as stateless global memory or SLM
347 // - reference to an a0.# register
348 // - an immediate value (for an immediate BTI)
349 // - for BSS/SS this is a reference to an a0 register
350 G4_Operand *surface = nullptr;
351
352 // Other miscellaneous attributes that cannot be deduced from the
353 // information above
354 LdStAttrs attrs;
355
356 // In some rare cases we must explicitly override message payload sizes.
357 // 1. prefetches use a null dst and set rLen = 0
358 // 2. e.g. block2d puts block sizes in a header
359 short overrideDstLengthBytesValue = -1;
360 short overrideSrc0LengthBytesValue = -1;
361 short overrideSrc1LengthBytesValue = -1;
362
363 G4_SendDescLdSt(
364 SFID sfid,
365 LdStOp _op,
366 G4_ExecSize _execSize,
367 //
368 // addr params
369 AddrType at, int _addrBits, int _addrDims,
370 //
371 // data params
372 int elemBitsMem, int elemBitsReg, int elemsPerAddr,
373 LdStOrder _order,
374 //
375 // ext info
376 Caching _l1, Caching _l3,
377 G4_Operand *surf,
378 ImmOff _immOff,
379 LdStAttrs _attrs);
380
operator newvISA::G4_SendDescLdSt381 void *operator new(size_t sz, Mem_Manager &m) { return m.alloc(sz); }
382
383 ///////////////////////////////////////////////////////////////////////////
384 // queries (getters)
385
386 // Checks if a message has a valid encoding on the current platform
387 // an optional error diagnostic can give you a failure hint.
388 bool canEncode(std::string *error = nullptr) const;
389
hasAttrsvISA::G4_SendDescLdSt390 bool hasAttrs(LdStAttrs a) const {
391 return (int(a) & int(attrs)) == int(a);
392 }
393
394 virtual size_t getSrc0LenBytes() const override;
395 virtual size_t getSrc1LenBytes() const override;
396 virtual size_t getDstLenBytes() const override;
397
398 virtual SendAccess getAccessType() const override;
getCachingvISA::G4_SendDescLdSt399 virtual std::pair<Caching,Caching> getCaching() const override {return std::make_pair(l1, l3);}
400 virtual void setCaching(Caching l1, Caching l3) override;
401 //
getOffsetvISA::G4_SendDescLdSt402 virtual int getOffset() const override {return immOff.immOff;}
getSurfacevISA::G4_SendDescLdSt403 virtual G4_Operand *getSurface() const override {return surface;}
404 //
isEOTvISA::G4_SendDescLdSt405 virtual bool isEOT() const override {return false;}
406 virtual bool isSLM() const override;
407 virtual bool isAtomic() const override;
isBarriervISA::G4_SendDescLdSt408 virtual bool isBarrier() const override {return false;}
isFencevISA::G4_SendDescLdSt409 virtual bool isFence() const override {return false;}
isScratchvISA::G4_SendDescLdSt410 virtual bool isScratch() const override {return hasAttrs(LdStAttrs::SCRATCH_SURFACE);}
411 virtual bool isTyped() const override;
412
getDescriptionvISA::G4_SendDescLdSt413 virtual std::string getDescription() const override {return str();}
414 void str(std::ostream &os) const;
415 std::string str() const;
416
417 ///////////////////////////////////////////////////////////////////////////
418 // mutators (setters)
overrideSrc0LengthBytesvISA::G4_SendDescLdSt419 void overrideSrc0LengthBytes(size_t lenBytes) {
420 MUST_BE_TRUE(lenBytes == (size_t)-1 || lenBytes <= (1 << 15) - 1,
421 "value out of range");
422 overrideSrc0LengthBytesValue = lenBytes;
423 }
overrideSrc1LengthBytesvISA::G4_SendDescLdSt424 void overrideSrc1LengthBytes(size_t lenBytes) {
425 MUST_BE_TRUE(lenBytes == (size_t)-1 || lenBytes <= (1 << 15) - 1,
426 "value out of range");
427 overrideSrc1LengthBytesValue = lenBytes;
428 }
overrideDstLengthBytesvISA::G4_SendDescLdSt429 void overrideDstLengthBytes(size_t lenBytes) {
430 MUST_BE_TRUE(lenBytes == (size_t)-1 || lenBytes <= (1 << 15) - 1,
431 "value out of range");
432 overrideDstLengthBytesValue = lenBytes;
433 }
434 }; // G4_SendDescLdSt
435
436
437 ////////////////////////////////////////////////////////////////////////////
438 class IR_Builder;
439
440 class G4_SendDescRaw : public G4_SendDesc
441 {
442 private:
443 /// Structure describes a send message descriptor. Only expose
444 /// several data fields; others are unnamed.
445 struct MsgDescLayout {
446 uint32_t funcCtrl : 19; // Function control (bit 0:18)
447 uint32_t headerPresent : 1; // Header present (bit 19)
448 uint32_t rspLength : 5; // Response length (bit 20:24)
449 uint32_t msgLength : 4; // Message length (bit 25:28)
450 uint32_t simdMode2 : 1; // 16-bit input (bit 29)
451 uint32_t returnFormat : 1; // 16-bit return (bit 30)
452 uint32_t EOT : 1; // EOT
453 };
454
455 /// View a message descriptor in two different ways:
456 /// - as a 32-bit unsigned integer
457 /// - as a structure
458 /// This simplifies the implementation of extracting subfields.
459 union DescData {
460 uint32_t value;
461 MsgDescLayout layout;
462 } desc;
463
464 /// Structure describes an extended send message descriptor.
465 /// Only expose several data fields; others are unnamed.
466 struct ExtendedMsgDescLayout {
467 uint32_t funcID : 4; // bit 0:3
468 uint32_t unnamed1 : 1; // bit 4
469 uint32_t eot : 1; // bit 5
470 uint32_t extMsgLength : 5; // bit 6:10
471 uint32_t cps : 1; // bit 11
472 uint32_t RTIndex : 3; // bit 12-14
473 uint32_t src0Alpha : 1; // bit 15
474 uint32_t extFuncCtrl : 16; // bit 16:31
475 };
476
477 /// View an extended message descriptor in two different ways:
478 /// - as a 32-bit unsigned integer
479 /// - as a structure
480 /// This simplifies the implementation of extracting subfields.
481 union ExtDescData {
482 uint32_t value;
483 ExtendedMsgDescLayout layout;
484 } extDesc;
485
486 SendAccess accessType;
487
488 /// Whether funcCtrl is valid
489 bool funcCtrlValid;
490
491 // sampler surface pointer?
492 G4_Operand *m_sti;
493 G4_Operand *m_bti; // BTI or other surface pointer
494
495 /// indicates this message is an LSC message
496 bool isLscDescriptor = false;
497 // sfid now stored separately from the ExDesc[4:0] since the new LSC format
498 // no longer uses ExDesc for that information
499 int src1Len;
500 bool eotAfterMessage = false;
501
502 public:
503 static const int SLMIndex = 0xFE;
504
505 G4_SendDescRaw(
506 uint32_t fCtrl, uint32_t regs2rcv, uint32_t regs2snd,
507 SFID fID, uint16_t extMsgLength, uint32_t extFCtrl,
508 SendAccess access, G4_Operand* bti, G4_Operand* sti, IR_Builder& builder);
509
510 /// Construct a object with descriptor and extended descriptor values.
511 /// used in IR_Builder::createSendMsgDesc(uint32_t desc, uint32_t extDesc, SendAccess access)
512 G4_SendDescRaw(
513 uint32_t desc, uint32_t extDesc, SendAccess access,
514 G4_Operand* bti, G4_Operand* sti);
515
516 /// Preferred constructor takes an explicit SFID and src1 length
517 G4_SendDescRaw(
518 SFID sfid,
519 uint32_t desc,
520 uint32_t extDesc,
521 int src1Len,
522 SendAccess access,
523 G4_Operand *bti,
524 bool isValidFuncCtrl);
525
526 // Preferred constructor takes an explicit SFID and src1 length
527 // Need execSize, so it is created for a particular send.
528 G4_SendDescRaw(
529 SFID sfid,
530 uint32_t desc,
531 uint32_t extDesc,
532 int src1Len,
533 SendAccess access,
534 G4_Operand* bti,
535 G4_ExecSize execSize,
536 bool isValidFuncCtrl);
537
operator new(size_t sz,Mem_Manager & m)538 void *operator new(size_t sz, Mem_Manager &m) { return m.alloc(sz); }
539
createExtDesc(SFID funcID,bool isEot=false)540 static uint32_t createExtDesc(SFID funcID, bool isEot = false)
541 {
542 return createExtDesc(funcID, isEot, 0, 0);
543 }
544
createMRTExtDesc(bool src0Alpha,uint8_t RTIndex,bool isEOT,uint32_t extMsgLen,uint16_t extFuncCtrl)545 static uint32_t createMRTExtDesc(bool src0Alpha, uint8_t RTIndex, bool isEOT, uint32_t extMsgLen, uint16_t extFuncCtrl)
546 {
547 ExtDescData data;
548 data.value = 0;
549 data.layout.funcID = SFIDtoInt(SFID::DP_WRITE);
550 data.layout.RTIndex = RTIndex;
551 data.layout.src0Alpha = src0Alpha;
552 data.layout.eot = isEOT;
553 data.layout.extMsgLength = extMsgLen;
554 data.layout.extFuncCtrl = extFuncCtrl;
555 return data.value;
556 }
557
createExtDesc(SFID funcID,bool isEot,unsigned extMsgLen,unsigned extFCtrl=0)558 static uint32_t createExtDesc(SFID funcID,
559 bool isEot,
560 unsigned extMsgLen,
561 unsigned extFCtrl = 0)
562 {
563 ExtDescData data;
564 data.value = 0;
565 data.layout.funcID = SFIDtoInt(funcID);
566 data.layout.eot = isEot;
567 data.layout.extMsgLength = extMsgLen;
568 data.layout.extFuncCtrl = extFCtrl;
569 return data.value;
570 }
571
createDesc(uint32_t fc,bool headerPresent,unsigned msgLength,unsigned rspLength)572 static uint32_t createDesc(uint32_t fc, bool headerPresent,
573 unsigned msgLength, unsigned rspLength)
574 {
575 DescData data;
576 data.value = fc;
577 data.layout.headerPresent = headerPresent;
578 data.layout.msgLength = static_cast<uint16_t>(msgLength);
579 data.layout.rspLength = static_cast<uint16_t>(rspLength);
580 return data.value;
581 }
582
getFuncId() const583 SFID getFuncId() const {return sfid;}
584
getFuncCtrl() const585 uint32_t getFuncCtrl() const {
586 return desc.layout.funcCtrl;
587 }
588
589 ////////////////////////////////////////////////////////////////////////
590 // LSC-related operations
isLscOp() const591 bool isLscOp() const {return isLscDescriptor;}
getLscOp() const592 LSC_OP getLscOp() const {
593 assert(isLscOp());
594 return static_cast<LSC_OP>(desc.value & 0x3F);
595 }
596 LSC_ADDR_TYPE getLscAddrType() const;
597 int getLscAddrSizeBytes() const; // e.g. a64 => 8
598 LSC_DATA_ORDER getLscDataOrder() const;
599
isEOTInst() const600 bool isEOTInst() const { return eotAfterMessage; }
601 void setEOT();
602
603 // query methods common for all raw sends
604 uint16_t ResponseLength() const;
MessageLength() const605 uint16_t MessageLength() const { return desc.layout.msgLength; }
extMessageLength() const606 uint16_t extMessageLength() const { return (uint16_t)src1Len; }
isDataPortRead() const607 bool isDataPortRead() const { return accessType != SendAccess::WRITE_ONLY; }
isDataPortWrite() const608 bool isDataPortWrite() const { return accessType != SendAccess::READ_ONLY; }
getAccess() const609 SendAccess getAccess() const { return accessType; }
isValidFuncCtrl() const610 bool isValidFuncCtrl() const { return funcCtrlValid; }
611 bool isHeaderPresent() const;
612 void setHeaderPresent(bool val);
613
614 ///////////////////////////////////////////////////////////////////////
615 // for HDC messages only (DC0/DC1/DC2/DP_DCRO(aka DP_CC))
616 //
617
618 //////////////////////////////////////
619 // calling these functions on non-HDC may assert
getExtFuncCtrl() const620 uint16_t getExtFuncCtrl() const {
621 MUST_BE_TRUE(isHDC(), "getExtFuncCtrl on non-HDC message");
622 return extDesc.layout.extFuncCtrl;
623 }
624 uint32_t getHdcMessageType() const;
625 bool isAtomicMessage() const;
626 uint16_t getHdcAtomicOp() const;
627
628 bool isSLMMessage() const;
629 unsigned getEnabledChannelNum() const;
630 unsigned getBlockNum() const;
631 unsigned getBlockSize() const;
632 bool isOwordLoad() const;
633 // OW1H ==> implies 2 (but shouldn't be used)
634 // asserts isOwordLoad()
635 unsigned getOwordsAccessed() const;
636
637 bool isHdcTypedSurfaceWrite() const;
638
639 // return offset in unit of HWords
getScratchRWOffset() const640 uint16_t getScratchRWOffset() const
641 {
642 MUST_BE_TRUE(isScratchRW(), "Message is not scratch space R/W.");
643 return (getFuncCtrl() & 0xFFFu);
644 }
645
isScratchRW() const646 bool isScratchRW() const
647 {
648 // legacy DC0 scratch msg: bit[18] = 1
649 return getSFID() == SFID::DP_DC0 && ((getFuncCtrl() & 0x40000u) != 0);
650 }
isScratchRead() const651 bool isScratchRead() const
652 {
653 return isScratchRW() && (getFuncCtrl() & 0x20000u) == 0;
654 }
isScratchWrite() const655 bool isScratchWrite() const
656 {
657 return isScratchRW() && (getFuncCtrl() & 0x20000u) != 0;
658 }
659 // in terms of HWords (1, 2, 4, or 8)
getScratchRWSize() const660 uint16_t getScratchRWSize() const
661 {
662 MUST_BE_TRUE(isScratchRW(), "Message is not scratch space R/W.");
663 uint16_t bitV = ((getFuncCtrl() & 0x3000u) >> 12);
664 return 0x1 << bitV;
665 }
666 bool isByteScatterRW() const;
667 bool isDWScatterRW() const;
668 bool isQWScatterRW() const;
669 bool isUntypedRW() const;
670
671 bool isA64Message() const;
672
673 // for sampler mesasges only
isSampler() const674 bool isSampler() const { return getFuncId() == SFID::SAMPLER; }
isCPSEnabled() const675 bool isCPSEnabled() const { return extDesc.layout.cps != 0; }
676 uint32_t getSamplerMessageType() const;
677 bool is16BitInput() const;
678 bool is16BitReturn() const;
679
isThreadMessage() const680 bool isThreadMessage() const {
681 return getSFID() == SFID::GATEWAY || getSFID() == SFID::SPAWNER;
682 }
683
684
isLSCTyped() const685 bool isLSCTyped() const {return isTyped() && isLSC();}
686 // atomic write or explicit barrier
isBarrierOrAtomic() const687 bool isBarrierOrAtomic() const {
688 return isAtomicMessage() || isBarrier();
689 }
690
getBti() const691 const G4_Operand *getBti() const {return m_bti;}
getBti()692 G4_Operand *getBti() {return m_bti;}
getSti() const693 const G4_Operand *getSti() const {return m_sti;}
getSti()694 G4_Operand *getSti() {return m_sti;}
695
696 // In rare cases we must update the surface pointer
697 // The send instructions also keeps a copy of the ExDesc parameter
698 // as a proper source operand (e.g. for dataflow algorithms).
699 // When they update their copy, they need to do the same for us.
setSurface(G4_Operand * newSurf)700 void setSurface(G4_Operand *newSurf) {m_bti = newSurf;}
701
getDesc() const702 uint32_t getDesc() const { return desc.value; }
getExtendedDesc() const703 uint32_t getExtendedDesc() const { return extDesc.value; }
704
705 std::string getDescription() const override;
706 private:
707 void setBindingTableIdx(unsigned idx);
708
709 public:
710 ///////////////////////////////////////////////////////////////////////////
711 // for the generic interface
712 virtual size_t getSrc0LenBytes() const override;
713 virtual size_t getDstLenBytes() const override;
714 virtual size_t getSrc1LenBytes() const override;
715 //
getAccessType() const716 virtual SendAccess getAccessType() const override {return accessType;}
717 virtual std::pair<Caching,Caching> getCaching() const override;
718 virtual void setCaching(Caching l1, Caching l3) override;
719 //
720 virtual int getOffset() const override;
getSurface() const721 virtual G4_Operand *getSurface() const override {return m_bti;}
722 //
isEOT() const723 virtual bool isEOT() const override {return isEOTInst();}
isSLM() const724 virtual bool isSLM() const override {return isSLMMessage();}
isAtomic() const725 virtual bool isAtomic() const override {return isAtomicMessage();}
726 virtual bool isBarrier() const override;
727 virtual bool isFence() const override;
isScratch() const728 virtual bool isScratch() const override {return isScratchRW();}
729 virtual bool isTyped() const override;
730 //
731 }; // G4_SendDescRaw
732
733 } // vISA::
734
735 #endif // G4_SEND_DESCS_HPP
736