1 /*========================== begin_copyright_notice ============================
2 
3 Copyright (C) 2017-2021 Intel Corporation
4 
5 SPDX-License-Identifier: MIT
6 
7 ============================= end_copyright_notice ===========================*/
8 
9 #ifndef IGA_IR_TYPES_HPP
10 #define IGA_IR_TYPES_HPP
11 
12 // WARNING: the IR is subject to change without any notice.  External tools
13 // should use the official interfaces in the external API.  Those interfaces
14 // are tested between releases and maintained even with changes to the IR.
15 
16 
17 #include <cstdint>
18 #include <tuple>
19 
20 #include "../EnumBitset.hpp"
21 #include "../api/iga_bxml_enums.hpp"
22 #include "../api/iga_types_ext.hpp"
23 
24 namespace iga
25 {
26 
27 // The GEN platform version
28 enum class Platform
29 {
30 // GEN version encoding. The version encoding must be the same as GEN_VER in iga.h
31 #define IGA_GEN_VER_ORDINAL(MAJ,MIN) ((MAJ)<<16)|(MIN)
32 
33 // XE version encoding. The version encoding must be the same as XE_VER in iga.h
34 #define IGA_XE_VER_ORDINAL(XE,SUBVER) (((XE)<<24)|SUBVER)
35 
36     INVALID     = 0,
37 
38     GEN6        = IGA_GEN_VER_ORDINAL( 6, 0 ),
39     GEN7        = IGA_GEN_VER_ORDINAL( 7, 0 ),
40     GEN7P5      = IGA_GEN_VER_ORDINAL( 7, 5 ),
41     GEN8        = IGA_GEN_VER_ORDINAL( 8, 0 ),
42     GEN8LP      = IGA_GEN_VER_ORDINAL( 8, 1 ),
43     GEN9        = IGA_GEN_VER_ORDINAL( 9, 0 ),
44     GEN9LP      = IGA_GEN_VER_ORDINAL( 9, 1 ),
45     GEN9P5      = IGA_GEN_VER_ORDINAL( 9, 5 ),
46     GEN10       = IGA_GEN_VER_ORDINAL(10, 0 ),
47     GEN11       = IGA_GEN_VER_ORDINAL(11, 0 ),
48     // XE version
49     XE          = IGA_XE_VER_ORDINAL(1, 0), // TGL
50     XE_HP       = IGA_XE_VER_ORDINAL(1, 1), // XE_HP
51     XE_HPG      = IGA_XE_VER_ORDINAL(1, 2),
52     XE_HPC      = IGA_XE_VER_ORDINAL(1, 4), // XeHPC-XT, preserved (1, 3) for XeHPC-XL
53     FUTURE      = 0x7FFFFFFF
54 #undef IGA_GEN_VER_ORDINAL
55 };
56 
57 struct Predication
58 {
59     PredCtrl  function;
60     bool      inverse; // TODO: enum
61 
Predicationiga::Predication62     Predication() : function(PredCtrl::NONE), inverse(false) { }
Predicationiga::Predication63     Predication(PredCtrl ctrl, bool inv) : function(ctrl), inverse(inv) { }
64 };
65 
66 
67 typedef BranchCtrl BranchCntrl; // for backwards compatibility
68 
ExecSizeToInt(ExecSize es)69 static inline int ExecSizeToInt(ExecSize es)
70 {
71     return static_cast<int>(es);
72 }
ExecSizeFromInt(int es)73 static inline ExecSize ExecSizeFromInt(int es)
74 {
75     return static_cast<ExecSize>(es);
76 }
77 
78 // for math macro register access (madm, math.invm, and math.rsqrtm)
79 // e.g.  madm (8) r13.mme2:f  r14:mme7:f  r16:nomme ...
80 //                    ^^^^        ^^^^        ^^^^^
81 enum class MathMacroExt
82 {
83     INVALID,
84     MME0,    // encodes as 0000b
85     MME1,    // encodes as 0001b
86     MME2,    // encodes as 0010b
87     MME3,    // encodes as 0011b
88     MME4,    // encodes as 0100b
89     MME5,    // encodes as 0101b
90     MME6,    // encodes as 0110b
91     MME7,    // encodes as 0111b
92     NOMME,   // encodes as 1000b
93 };
94 
95 
96 // how much to shift <right,left> to get to from byte offset
97 // to subregister offset
98 //   I.e. subReg = (byteOff << left) >> right;
99 // this allows us to scale a subregister byte offset up OR down
100 static inline std::tuple<uint32_t, uint32_t>
TypeSizeShiftsOffsetToSubreg(Type type)101     TypeSizeShiftsOffsetToSubreg(Type type)
102 {
103     uint32_t shl = 0, shr = 0; // by default no scaling
104 
105     switch (type) {
106     // subbyte types
107     case Type::U1:
108         shl = 3;
109         break;
110     case Type::U2:
111     case Type::S2:
112         shl = 2;
113         break;
114     case Type::U4:
115     case Type::S4:
116         shl = 1;
117         break;
118 
119     case Type::QF:
120     case Type::BF8:
121         break;
122     case Type::TF32:
123         shr = 2;
124         break;
125 
126     // 1-byte types
127     case Type::UB:
128     case Type::B:
129         break;
130     // 2-byte types
131     case Type::UW:
132     case Type::W:
133     case Type::HF:
134     case Type::BF:
135         shr = 1;
136         break;
137     // 4-byte types
138     case Type::UD:
139     case Type::D:
140     case Type::F:
141     case Type::NF: // NF regions the same as F
142         shr = 2;
143         break;
144     case Type::UQ:
145     case Type::Q:
146     case Type::DF:
147         shr = 3;
148         break;
149     default: // invalid types
150         break;
151     }
152     return std::make_tuple(shl,shr);
153 }
154 
155 // e.g. Type::UD == 32
TypeSizeInBits(Type t)156 static inline uint32_t TypeSizeInBits(Type t)
157 {
158     auto ti = TypeSizeShiftsOffsetToSubreg(t);
159     return (8 << std::get<1>(ti)) >> std::get<0>(ti);
160 }
TypeSizeInBitsWithDefault(Type type,int dft=0)161 static inline uint32_t TypeSizeInBitsWithDefault(Type type, int dft = 0)
162 {
163     return type == Type::INVALID ? dft : TypeSizeInBits(type);
164 }
TypeIs64b(Type t)165 static inline bool TypeIs64b(Type t)
166 {
167     return TypeSizeInBitsWithDefault(t,0) == 64;
168 }
TypeIsFloating(Type t)169 static inline bool TypeIsFloating(Type t)
170 {
171     switch (t)
172     {
173     case Type::F:
174     case Type::BF:
175     case Type::QF:
176     case Type::BF8:
177     case Type::TF32:
178     case Type::HF:
179     case Type::DF:
180     case Type::VF:
181     case Type::NF:
182         return true;
183     default:
184         return false;
185     }
186 }
187 // static inline bool TypeIsSubByte(Type t) {
188 //    return std::get<1>(TypeSizeShiftsOffsetToSubreg(t)) > 0;
189 // }
190 
191 struct Region {
192     enum class Vert {
193         VT_0       =  0,
194         VT_1       =  1,
195         VT_2       =  2,
196         VT_4       =  4,
197         VT_8       =  8,
198         VT_16      = 16,
199         VT_32      = 32,
200 
201         VT_VxH     = 31, // special VxH mode for indirect region
202         VT_INVALID = 63,
203     };
204     enum class Width {
205         WI_1       =  1,
206         WI_2       =  2,
207         WI_4       =  4,
208         WI_8       =  8,
209         WI_16      = 16,
210         WI_INVALID = 31
211     };
212     enum class Horz {
213         HZ_0       =  0, // not permitted on DstOps (unless MBZ)
214         HZ_1       =  1,
215         HZ_2       =  2,
216         HZ_4       =  4,
217         HZ_INVALID = 15
218     };
219     union {
220         struct {
221             unsigned int v : 6;
222             unsigned int w : 5;
223             unsigned int h : 4;
224         };
225         uint32_t bits;
226     };
227 
setiga::Region228     constexpr void set(Vert _v, Width _w, Horz _h) {
229         this->bits = 0; // clear padding
230         v = static_cast<unsigned int>(_v);
231         w = static_cast<unsigned int>(_w);
232         h = static_cast<unsigned int>(_h);
233     }
234 
setiga::Region235     constexpr void set(Vert vt) {
236         v = static_cast<unsigned int>(vt);
237     }
setiga::Region238     constexpr void set(Width wi) {
239         w = static_cast<unsigned int>(wi);
240     }
setiga::Region241     constexpr void set(Horz hz) {
242         h = static_cast<unsigned int>(hz);
243     }
setDstHziga::Region244     constexpr void setDstHz(Horz hz) {
245         set(Vert::VT_INVALID, Width::WI_INVALID, hz);
246     }
247 
getHziga::Region248     Horz    getHz() const {return static_cast<Horz>(h);}
getVtiga::Region249     Vert    getVt() const {return static_cast<Vert>(v);}
getWiiga::Region250     Width   getWi() const {return static_cast<Width>(w);}
251 
252     // checks if a region is invalid (assembler will program it to correct bits)
isInvalidiga::Region253     bool isInvalid() const {
254         return *this == INVALID;
255     }
256     // checks if a region is of the for <V;W,H>
isVWHiga::Region257     bool isVWH() const {
258         return
259             getVt() != Vert::VT_INVALID &&
260             getWi() != Width::WI_INVALID &&
261             getHz() != Horz::HZ_INVALID;
262     }
263 
264     // define [in]equality based on bits
operator ==iga::Region265     bool operator ==(const Region &b) const {
266         // careful: fails if padding differs (we prevent that now)
267         return b.bits == bits;
268     }
operator !=iga::Region269     bool operator !=(const Region &b) const {
270         return  !(*this == b);
271     }
272 
273 
274     // some useful region constants
275     static const Region INVALID; // all RESERVED elements
276     //
277     // dst
278     static const Region DST1;    // <1>
279     static const Region DST2;    // <2>
280     static const Region DST4;    // <4>
281     //
282     // generalized src regions
283     static const Region SRC010;  // <0;1,0> (broadcast scalar)
284     static const Region SRC110;  // <1;1,0> (packed access)
285     static const Region SRC210;  // <2;1,0> (even strided access)
286     static const Region SRC410;  // <4;1,0> (quarter stided access)
287     //
288     // older src regions
289     static const Region SRC221;  // <2;2,1>
290     static const Region SRC441;  // <4;4,1>
291     static const Region SRC881;  // <8;8,1>
292     static const Region SRCFF1;  // <16;16,1>
293     //
294     // special cases
295     // ternary src0/src1
296     static const Region SRC0X0;  // <0;0> (ternary align1 src0 and src1)
297     static const Region SRC2X1;  // <2;1> (ternary align1 src0 and src1)
298     static const Region SRC1X0;  // <1;0> XE_LP changes 2 to 1 in encoding
299     static const Region SRC4X1;  // <4;1> (ternary align1 src0 and src1)
300     // ternary src2
301     static const Region SRC8X1;  // <8;1> (ternary align1 src0 and src1)
302     static const Region SRCXX0;  // <0>   (ternary align1 src2)
303     static const Region SRCXX1;  // <1>   (ternary align1 src2)
304     static const Region SRCXX2;  // <2>   (ternary align1 src2)
305 };
306 
307 // A set of instruction options
308 typedef EnumBitset<InstOpt> InstOptSet;
309 
310 
311 struct RegRef {
312     uint16_t  regNum    = 0;
313     uint16_t  subRegNum = 0;
314 
RegRefiga::RegRef315     constexpr RegRef() { }
RegRefiga::RegRef316     constexpr RegRef(uint16_t rNum, uint16_t srNum)
317         : regNum(rNum), subRegNum(srNum) { }
RegRefiga::RegRef318     constexpr RegRef(int rNum, int srNum)
319         : regNum((uint8_t)rNum), subRegNum((uint8_t)srNum) { }
RegRefiga::RegRef320     constexpr RegRef(uint32_t rNum, uint32_t srNum)
321         : regNum((uint8_t)rNum), subRegNum((uint8_t)srNum) { }
322 
operator ==iga::RegRef323     bool operator==(const RegRef &rr) const {
324         return regNum == rr.regNum && subRegNum == rr.subRegNum;
325     }
operator !=iga::RegRef326     bool operator!=(const RegRef &rr) const {
327         return !(*this == rr);
328     }
329 };
330 
331 static constexpr RegRef REGREF_INVALID {0xFF, 0xFF};
332 static constexpr RegRef REGREF_ZERO_ZERO {0, 0};
333 
334 struct SendDesc {
335     enum class Kind {IMM, REG32A};
336     Kind type;
337 
338     union {
339         RegRef         reg;
340         uint32_t       imm;
341     };
342 
SendDesciga::SendDesc343     constexpr SendDesc() : SendDesc(0) { }
SendDesciga::SendDesc344     constexpr SendDesc(uint32_t desc) : type(Kind::IMM), imm(desc) { }
SendDesciga::SendDesc345     constexpr SendDesc(RegRef a0r) : type(Kind::REG32A), reg(a0r) { }
346 
isRegiga::SendDesc347     bool isReg() const {return type == Kind::REG32A;}
isImmiga::SendDesc348     bool isImm() const {return type == Kind::IMM;}
349 };
350 
351 } // namespace
352 #endif
353