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 IS_RELEASE_DLL
10
11 #include "Common_ISA.h"
12 #include "Common_ISA_util.h"
13
14 #include "VISADefines.h"
15 #include "IsaVerification.h"
16
17 #include "IsaDisassembly.h"
18 #include "PreDefinedVars.h"
19 #include "Attributes.hpp"
20
21 #include "G4_IR.hpp"
22 /* stdio.h portability code start */
23 #ifdef _WIN32
24 #else
25 #define _scprintf(...) \
26 snprintf(NULL, 0, __VA_ARGS__)
27 #endif
28
29 #include <iostream>
30 #include <sstream>
31 #include <string>
32 #include <limits>
33
34 using namespace vISA;
35
36 #define REPORT_HEADER(opt, cond, ...) \
37 do if (!(cond)) { \
38 int sz = _scprintf(__VA_ARGS__) + 1; \
39 char* buf = (char*)malloc(sz); \
40 assert(buf != NULL); \
41 memset(buf, 0, sz); \
42 SNPRINTF(buf, sz, __VA_ARGS__); \
43 error_list.push_back(createIsaError( \
44 isaHeader, header, std::string(buf), opt)); \
45 free(buf); \
46 } while (0)
47
48
49 #define REPORT_INSTRUCTION(opt, cond, ...) \
50 do if (!(cond)) { \
51 int sz = _scprintf(__VA_ARGS__) + 1; \
52 char* buf = (char*)malloc(sz); \
53 assert(buf != NULL); \
54 memset(buf, 0, sz); \
55 SNPRINTF(buf, sz, __VA_ARGS__); \
56 error_list.push_back(createIsaError( \
57 isaHeader, header, std::string(buf), opt, inst)); \
58 free(buf); \
59 } while (0)
60
toString() const61 std::string raw_opnd::toString() const
62 {
63 std::stringstream sstr;
64 sstr << "V" << index;
65 if (offset != 0)
66 {
67 sstr << "." << offset;
68 }
69 return sstr.str();
70 }
71
writeReport(const char * filename)72 void vISAVerifier::writeReport(const char* filename)
73 {
74 if (kerror_list.size() > 0 || error_list.size() > 0)
75 {
76 std::ofstream report;
77 report.open(filename);
78
79 if (kerror_list.size() > 0)
80 {
81 report << "Kernel Header / Declare Errors:\n";
82 for (auto I = kerror_list.begin(), E = kerror_list.end(); I != E; I++)
83 report << (*I) << "\n";
84 report << "\n\n\n";
85 }
86
87 report << "Instruction / Operand / Region Errors:\n";
88
89 for (auto I = error_list.begin(), E = error_list.end(); I != E; I++)
90 report << (*I) << "\n";
91
92 report << "\n\n\n";
93 report.close();
94 }
95 }
96
getDstIndex(const CISA_INST * inst)97 static int getDstIndex(const CISA_INST* inst)
98 {
99 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
100 int dstIndex = -1;
101 if (inst->opnd_count > 0)
102 {
103 switch (ISA_Inst_Table[opcode].type)
104 {
105 case ISA_Inst_Mov:
106 case ISA_Inst_Arith:
107 case ISA_Inst_Logic:
108 case ISA_Inst_Address:
109 dstIndex = 0;
110 break;
111 case ISA_Inst_Compare:
112 dstIndex = 1;
113 break;
114 default:
115 break; // Prevent gcc warning
116 }
117 }
118 return dstIndex;
119 }
120
121 // diagDumpInstructionOperandDecls() is used to generate the error report
diagDumpInstructionOperandDecls(const common_isa_header & isaHeader,const print_format_provider_t * header,const CISA_INST * inst,Options * options)122 static std::string diagDumpInstructionOperandDecls(
123 const common_isa_header& isaHeader,
124 const print_format_provider_t* header,
125 const CISA_INST* inst,
126 Options *options)
127 {
128 std::stringstream sstr;
129
130 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
131
132 for (unsigned i = 0; i < inst->opnd_count; i++)
133 {
134 if (inst->opnd_array[i]->opnd_type == CISA_OPND_VECTOR)
135 {
136 const vector_opnd& opnd = getVectorOperand(inst, i);
137 uint32_t index = opnd.getOperandIndex();
138
139 if (numPreDefinedVars <= index && index < header->getVarCount())
140 switch (opnd.getOperandClass())
141 {
142 case OPERAND_STATE :
143 case OPERAND_GENERAL : sstr << printVariableDecl (header, index-numPreDefinedVars, options); break;
144 case OPERAND_ADDRESS :
145 case OPERAND_INDIRECT : sstr << printAddressDecl (isaHeader, header, index); break;
146 case OPERAND_PREDICATE : sstr << printPredicateDecl (header, index); break;
147 case OPERAND_ADDRESSOF : sstr << "ADDRESSOF Operand decl... are those even allowed>\n"; break;
148 case OPERAND_IMMEDIATE : sstr << "Immediate operand: " << getPrimitiveOperand<unsigned>(inst, i) << "\n"; break;
149 default : sstr << "Operand type: " << opnd.getOperandClass() << " unable to print." << "\n"; break;
150 }
151 }
152 else if (inst->opnd_array[i]->opnd_type == CISA_OPND_RAW)
153 {
154 uint32_t index = getRawOperand(inst, i).index;
155 if (numPreDefinedVars <= index && index < header->getVarCount() + numPreDefinedVars)
156 sstr << printVariableDecl(header, index-numPreDefinedVars, options);
157 }
158 else if (inst->opnd_array[i]->opnd_type == CISA_OPND_OTHER) // new loader only
159 {
160 }
161 else
162 {
163 sstr << "unknown operand?";
164 }
165
166 sstr << "\n";
167 if (i != inst->opnd_count-1)
168 sstr << std::setw(33) << " ";
169 }
170
171 return sstr.str();
172 }
173
createIsaError(const common_isa_header & isaHeader,const print_format_provider_t * header,std::string msg,Options * opt,const CISA_INST * inst=NULL)174 static std::string createIsaError(
175 const common_isa_header& isaHeader,
176 const print_format_provider_t* header,
177 std::string msg,
178 Options *opt,
179 const CISA_INST* inst = NULL)
180 {
181 std::stringstream sstr;
182 if (!inst)
183 sstr << "\n/-------------------------------------------!!!KERNEL HEADER ERRORS FOUND!!!-------------------------------------------\\\n";
184 else
185 sstr << "\n/--------------------------------------------!!!INSTRUCTION ERROR FOUND!!!---------------------------------------------\\\n";
186 sstr << std::setw(33) << "Error in CISA routine with name: " << (char*)header->getString(header->getNameIndex()) << "\n";
187 sstr << std::setw(33) << "Error Message: " << msg << "\n";
188
189 if (NULL != inst)
190 {
191 sstr << std::setw(33) << "Diagnostics:\n";
192 sstr << std::setw(33) << " Instruction variables' decls: ";
193 sstr << diagDumpInstructionOperandDecls(isaHeader, header, inst, opt) << "\n";
194 sstr << std::setw(33) << " Violating Instruction: " << printInstruction(header, inst, opt) << "\n";
195 }
196
197 sstr << "\\----------------------------------------------------------------------------------------------------------------------/\n";
198 return sstr.str();
199 }
200
201 // If region/offset is available, return true; otherwise, return false.
getRegion(const vector_opnd & VecOpnd,uint16_t & row_offset,uint16_t & col_offset,uint16_t & v_stride,uint16_t & width,uint16_t & h_stride) const202 bool vISAVerifier::getRegion(const vector_opnd& VecOpnd,
203 uint16_t& row_offset, uint16_t& col_offset,
204 uint16_t& v_stride, uint16_t& width, uint16_t& h_stride) const
205 {
206 Common_ISA_Operand_Class operand_class = VecOpnd.getOperandClass();
207
208 uint16_t region = 0;
209 row_offset = 0;
210 col_offset = 0;
211
212 switch (operand_class)
213 {
214 case OPERAND_GENERAL:
215 region = VecOpnd.opnd_val.gen_opnd.region;
216 row_offset = VecOpnd.opnd_val.gen_opnd.row_offset;
217 col_offset = VecOpnd.opnd_val.gen_opnd.col_offset;
218 break;
219 case OPERAND_INDIRECT:
220 region = VecOpnd.opnd_val.indirect_opnd.region;
221 break;
222 default:
223 return false;
224 }
225
226 Common_ISA_Region_Val w = (Common_ISA_Region_Val)((region >> 4) & 0xF);
227 Common_ISA_Region_Val h = (Common_ISA_Region_Val)((region >> 8) & 0xF);
228 Common_ISA_Region_Val v = (Common_ISA_Region_Val)((region) & 0xF);
229
230 v_stride = Common_ISA_Get_Region_Value(v);
231 h_stride = Common_ISA_Get_Region_Value(h);
232 width = Common_ISA_Get_Region_Value(w);
233 return true;
234 }
235
getOperandVISAType(const CISA_INST * I,unsigned Ix) const236 VISA_Type vISAVerifier::getOperandVISAType(const CISA_INST* I, unsigned Ix) const
237 {
238 switch (getOperandType(I, Ix))
239 {
240 case CISA_OPND_VECTOR:
241 {
242 const vector_opnd& vec_opnd = getVectorOperand(I, Ix);
243 return getVectorOperandType(header, vec_opnd);
244 }
245 case CISA_OPND_RAW:
246 {
247 const raw_opnd& raw_opnd = getRawOperand(I, Ix);
248 return getRawOperandType(header, raw_opnd);
249 }
250 default:
251 break;
252 }
253 return ISA_TYPE_NUM;
254 }
255
256 // If any of I's operands uses the GivenType, return true; otherwise, return false.
useGivenVISAType(const CISA_INST * I,VISA_Type GivenType) const257 bool vISAVerifier::useGivenVISAType(const CISA_INST* I, VISA_Type GivenType) const
258 {
259 ISA_Opcode opc = (ISA_Opcode)I->opcode;
260 int ndst = (int)ISA_Inst_Table[opc].n_dsts;
261 if (opc == ISA_CMP)
262 {
263 // cmp's 1st opnd is cmp relop, which returns ISA_TYPE_NUM as its type.
264 // Thus, it is ignored as expected.
265 ++ndst;
266 }
267 for (int j = 0; j < ndst; j++)
268 {
269 VISA_Type dstType = getOperandVISAType(I, j);
270 if (dstType == GivenType)
271 return true;
272 }
273 for (int j = 0; j < ISA_Inst_Table[opc].n_srcs; j++)
274 {
275 VISA_Type srcType = getOperandVISAType(I, j + ndst);
276 if (srcType == GivenType)
277 return true;
278 }
279 return false;
280 }
281
verifyPredicateDecl(unsigned declID)282 void vISAVerifier::verifyPredicateDecl(unsigned declID)
283 {
284 std::string declError =
285 std::string(" Error in predicate variable decl: ") + printPredicateDecl(header, declID);
286
287 REPORT_HEADER(options,header->getPred(declID)->name_index < header->getStringCount(), "P%d's name index(%d) is not valid: %s", declID, header->getPred(declID)->name_index, declError.c_str());
288
289 switch (header->getPred(declID)->num_elements)
290 {
291 case 1:
292 case 2:
293 case 4:
294 case 8:
295 case 16:
296 case 32:
297 break;
298 default:
299 REPORT_HEADER(options,false, "P%d's number of elements(%d) is not valid: %s", declID, header->getPred(declID)->num_elements, declError.c_str());
300 }
301 }
302
verifyAddressDecl(unsigned declID)303 void vISAVerifier::verifyAddressDecl(unsigned declID)
304 {
305 std::string declError = std::string(" Error in address variable decl: ") +
306 printAddressDecl(isaHeader, header, declID);
307
308 REPORT_HEADER(options,header->getAddr(declID)->name_index < header->getStringCount(), "A%d's name index(%d) is not valid: %s", declID, header->getAddr(declID)->name_index, declError.c_str());
309 REPORT_HEADER(options,header->getAddr(declID)->num_elements <= 16, "Max possible address registers are 16 on BDW+: %s", declError.c_str());
310
311 /// TODO: Fix/Reenable this verification check.
312 #if 0
313 switch (header->getAddr(declID)->num_elements)
314 {
315 case 1:
316 case 2:
317 case 4:
318 case 8:
319 case 16:
320 break;
321 default:
322 REPORT_HEADER(options,false, "A%d's number of elements(%d) is not valid.", declID, header->getAddr(declID)->num_elements);
323 }
324 #endif
325 }
326
verifyVariableDecl(unsigned declID)327 void vISAVerifier::verifyVariableDecl(
328 unsigned declID)
329 {
330 std::string declError = std::string(" Error in CISA variable decl: ") +
331 printVariableDecl(header, declID, options);
332
333 const var_info_t* var = header->getVar(declID);
334 VISA_Align align = var->getAlignment();
335
336 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
337
338 REPORT_HEADER(options, var->name_index < header->getStringCount(),
339 "V%d's name index(%d) is not valid: %s",
340 declID + numPreDefinedVars, var->name_index,
341 declError.c_str());
342
343 switch (var->getType())
344 {
345 case ISA_TYPE_V:
346 case ISA_TYPE_VF:
347 case ISA_TYPE_BOOL:
348 case ISA_TYPE_UV:
349 REPORT_HEADER(options,false, "V%d's type(%s) is not legal: %s", declID, CISATypeTable[var->getType()].typeName, declError.c_str());
350 return;
351 default:
352 break; // Prevent gcc warning
353 }
354
355 REPORT_HEADER(options, var->num_elements != 0 && var->num_elements <= COMMON_ISA_MAX_VARIABLE_SIZE,
356 "V%d's number of elements(%d) is out of range: %s",
357 declID + numPreDefinedVars, var->num_elements,
358 declError.c_str());
359 REPORT_HEADER(options, !(var->alias_index == 0 && var->alias_offset != 0),
360 "V%d's alias offset must be zero when it is not aliased: %s",
361 declID + numPreDefinedVars, declError.c_str());
362
363 if (var->alias_index >= numPreDefinedVars)
364 {
365 const var_info_t* currAliasVar = header->getVar(var->alias_index-numPreDefinedVars);
366 unsigned totalOffset = var->alias_offset;
367
368 std::set<uint32_t> visitedAliasIndices;
369
370 while (currAliasVar->alias_index >= numPreDefinedVars)
371 {
372 if (visitedAliasIndices.find(currAliasVar->alias_index) != visitedAliasIndices.end())
373 {
374 REPORT_HEADER(options,false, "Circular alias detected, alias index: %d", currAliasVar->alias_index);
375 break;
376 }
377
378 visitedAliasIndices.insert(currAliasVar->alias_index);
379
380 REPORT_HEADER(options,currAliasVar->alias_index < header->getVarCount() + numPreDefinedVars,
381 "Aliased variable aliases to an invalid alias index. "
382 "Variable count: %d. invalid index: %d. %s",
383 header->getVarCount() + numPreDefinedVars,
384 currAliasVar->alias_index, declError.c_str());
385
386 totalOffset += currAliasVar->alias_offset;
387 currAliasVar = header->getVar(currAliasVar->alias_index-numPreDefinedVars);
388 }
389
390 if (currAliasVar->alias_index < header->getVarCount() + numPreDefinedVars)
391 {
392 REPORT_HEADER(options,totalOffset < (currAliasVar->num_elements * (unsigned)CISATypeTable[currAliasVar->getType()].typeSize),
393 "Variable decl's alias offset exceeds the bounds of the aliased variable decl allocation size: %s", declError.c_str());
394 VISA_Align baseAlign = std::max(currAliasVar->getAlignment(), currAliasVar->getTypeAlignment());
395 REPORT_HEADER(options, baseAlign >= var->getTypeAlignment(),
396 "base variable must be at least type-aligned to this variable: %s", declError.c_str());
397 }
398 }
399
400 switch (align)
401 {
402 case ALIGN_BYTE:
403 break;
404 case ALIGN_WORD:
405 break;
406 case ALIGN_DWORD:
407 break;
408 case ALIGN_QWORD:
409 break;
410 case ALIGN_OWORD:
411 break;
412 case ALIGN_GRF:
413 break;
414 case ALIGN_2_GRF:
415 break;
416 case ALIGN_HWORD:
417 break;
418 case ALIGN_32WORD:
419 break;
420 case ALIGN_64WORD:
421 break;
422 default:
423 REPORT_HEADER(options,false, "V%d's variable alignment is not a valid alignment value: %s", declID, declError.c_str());
424 }
425
426 REPORT_HEADER(options, !(var->alias_index != 0 &&
427 var->alias_index >=
428 header->getVarCount() + numPreDefinedVars),
429 "V%d's alias index must point to a valid CISA variable index "
430 "between 0 and %d. Currently points to invalid index V%d: %s",
431 declID + numPreDefinedVars,
432 header->getVarCount() + numPreDefinedVars - 1,
433 var->alias_index, declError.c_str());
434
435 /// INFO: Got rid of this verification check a long time ago.
436 /// Checking for unused variables is not that important
437 /// and it made it a lot simpler for refactoring to just
438 /// get rid of code that did the analysis required for it.
439 #if 0
440 REPORT_HEADER(options,m_used, "V%d is an unused variable in the CISA bytecode. Find out why it is declared.", declID);
441 #endif
442 }
443
444 // get the start byte offset from the top level declare
getStartByteOffset(const print_format_provider_t * header,const var_info_t * var,unsigned int numPredefinedVars)445 static unsigned int getStartByteOffset(
446 const print_format_provider_t* header,
447 const var_info_t* var,
448 unsigned int numPredefinedVars)
449 {
450 unsigned int offset = 0;
451 while (var->alias_index != 0)
452 {
453 offset += var->alias_offset;
454 if (var->alias_index <= numPredefinedVars)
455 {
456 // predefined variables don't have aliases, so we can stop
457 break;
458 }
459 else
460 {
461 var = header->getVar(var->alias_index-numPredefinedVars);
462 }
463 }
464 return offset;
465 }
466
verifyRegion(const CISA_INST * inst,unsigned i)467 void vISAVerifier::verifyRegion(
468 const CISA_INST* inst,
469 unsigned i)
470 {
471 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
472 /// Dataport instructions must be verified separately
473 if (ISA_Inst_Data_Port == ISA_Inst_Table[opcode].type) return;
474
475 ASSERT_USER(inst->opnd_array[i]->opnd_type == CISA_OPND_VECTOR, "Should only be verifying region on a vector operand");
476 const vector_opnd& vect = getVectorOperand(inst, i);
477
478 uint32_t operand_index = vect.getOperandIndex();
479 Common_ISA_Operand_Class operand_class = vect.getOperandClass();
480
481 unsigned dstIndex = getDstIndex(inst);
482
483 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
484
485 uint16_t region = 0;
486 uint8_t row_offset = 0;
487 uint8_t col_offset = 0;
488
489 switch (operand_class)
490 {
491 case OPERAND_GENERAL:
492 region = vect.opnd_val.gen_opnd.region;
493 row_offset = vect.opnd_val.gen_opnd.row_offset;
494 col_offset = vect.opnd_val.gen_opnd.col_offset;
495 break;
496 case OPERAND_INDIRECT:
497 region = vect.opnd_val.indirect_opnd.region;
498 break;
499 default:
500 return;
501 }
502
503 Common_ISA_Region_Val width = (Common_ISA_Region_Val)((region >> 4) & 0xF);
504 Common_ISA_Region_Val h_stride = (Common_ISA_Region_Val)((region >> 8) & 0xF);
505 Common_ISA_Region_Val v_stride = (Common_ISA_Region_Val)((region ) & 0xF);
506
507 short v_stride_val = Common_ISA_Get_Region_Value(v_stride);
508 short h_stride_val = Common_ISA_Get_Region_Value(h_stride);
509 short width_val = Common_ISA_Get_Region_Value(width );
510
511 /// INFO: Catch zero width, because we'll sigsegv otherwise.
512 REPORT_INSTRUCTION(options,width_val, "CISA region has width of 0");
513
514 uint8_t exec_sz = 0;
515 switch (inst->getExecSize())
516 {
517 case EXEC_SIZE_1: exec_sz = 1; break;
518 case EXEC_SIZE_2: exec_sz = 2; break;
519 case EXEC_SIZE_4: exec_sz = 4; break;
520 case EXEC_SIZE_8: exec_sz = 8; break;
521 case EXEC_SIZE_16: exec_sz = 16; break;
522 case EXEC_SIZE_32: exec_sz = 32; break;
523 default: REPORT_INSTRUCTION(options, false, "Invalid execution size");
524 }
525
526 if (i == dstIndex)
527 {
528 REPORT_INSTRUCTION(options,0 != h_stride_val, "Horizontal Stride should not be 0 for a destination operand.");
529
530 // for dst set width = exec size and vstride = width * hstride, so their bound can be verified
531 width_val = exec_sz;
532 v_stride_val = width_val * h_stride_val;
533 }
534
535 if (width_val == 0)
536 {
537 return;
538 }
539
540 REPORT_INSTRUCTION(options,h_stride != REGION_NULL, "Horizontal Stride should not be REGION_NULL");
541
542 switch (h_stride_val)
543 {
544 case 0:
545 case 1:
546 case 2:
547 case 4:
548 break;
549 default: REPORT_INSTRUCTION(options,false, "Legal CISA region horizontal stride parameter values: {0, 1, 2, 4}.");
550 }
551
552 if (width != REGION_NULL)
553 {
554 switch (width_val)
555 {
556 case 1:
557 case 2:
558 case 4:
559 case 8:
560 case 16:
561 break;
562 default: REPORT_INSTRUCTION(options,false, "Legal CISA region width parameter values: {1, 2, 4, 8, 16}.");
563 }
564
565 REPORT_INSTRUCTION(options,exec_sz >= width_val, "Execution size must be greater than width.");
566 if (exec_sz < width_val)
567 {
568 // no point in continuing verifiication
569 return;
570 }
571 }
572
573 if (v_stride != REGION_NULL)
574 {
575 switch (v_stride_val)
576 {
577 case 0:
578 case 1:
579 case 2:
580 case 4:
581 case 8:
582 case 16:
583 case 32:
584 break;
585 default: REPORT_INSTRUCTION(options,false, "Legal CISA region vertical stride parameter values: {0, 1, 2, 4, 8, 16, 32}.");
586 }
587 }
588 else if (dstIndex != i)
589 {
590 // check for out-of-bound addresses for VxH operand
591 int numAddr = exec_sz / width_val;
592 REPORT_INSTRUCTION(options, numAddr <= 16, "Number of Address for indirect operand exceeds 16");
593 }
594
595 if (operand_index >= numPreDefinedVars)
596 if (operand_class == OPERAND_GENERAL)
597 {
598 const var_info_t* var = header->getVar(vect.getOperandIndex()-numPreDefinedVars);
599 VISA_Type isa_type = getVectorOperandType(header, vect);
600 unsigned VN_size = CISATypeTable[isa_type].typeSize;
601
602 uint16_t num_elements = var->num_elements;
603 unsigned var_size = VN_size * num_elements;
604
605 unsigned last_region_elt_byte;
606 if (width_val != -1)
607 {
608 unsigned last_region_element = (((exec_sz / width_val) - 1) * v_stride_val) +
609 ((width_val - 1) * h_stride_val);
610 last_region_elt_byte = (last_region_element * VN_size) + VN_size - 1;
611 }
612 else
613 {
614 // DstRegRegion with width 0 (width_val=-1)
615 last_region_elt_byte =
616 (exec_sz - 1) * h_stride_val * VN_size + VN_size - 1;
617 }
618
619 // Check if the operand may touch more than 2 GRFs due to bad alignment
620 // So far vISA is able to handle the splitting of:
621 // moves, logic, cmp and arithmetic instructions
622 if (ISA_Inst_Table[opcode].type != ISA_Inst_Mov &&
623 ISA_Inst_Table[opcode].type != ISA_Inst_Logic &&
624 ISA_Inst_Table[opcode].type != ISA_Inst_Compare &&
625 ISA_Inst_Table[opcode].type != ISA_Inst_Arith)
626 {
627 REPORT_INSTRUCTION(options, (COMMON_ISA_GRF_REG_SIZE * 2u) > last_region_elt_byte,
628 "CISA operand region access out of 2 GRF boundary (within %d bytes): %d",
629 (COMMON_ISA_GRF_REG_SIZE * 2),
630 last_region_elt_byte);
631
632 // check if the operand may touch more than 2 GRFs due to bad alignment
633 unsigned startByte = getStartByteOffset(header, var, numPreDefinedVars) +
634 row_offset * COMMON_ISA_GRF_REG_SIZE +
635 col_offset * CISATypeTable[var->getType()].typeSize;
636 unsigned endByte = startByte + last_region_elt_byte;
637 unsigned startGRF = startByte / COMMON_ISA_GRF_REG_SIZE;
638 unsigned endGRF = endByte / COMMON_ISA_GRF_REG_SIZE;
639 REPORT_INSTRUCTION(options, endGRF == startGRF || endGRF == (startGRF + 1),
640 "CISA operand accesses more than 2 GRF due to mis-alignment: start byte offset = %d, end byte offset = %d",
641 startByte, endByte);
642 }
643
644 unsigned firstElementIndex = row_offset * COMMON_ISA_GRF_REG_SIZE + col_offset;
645
646 for (int i = 0; i < exec_sz / width_val; i++)
647 {
648 for (int j = 0; j < width_val; j++)
649 {
650 unsigned region_offset = firstElementIndex +
651 (((i * v_stride_val) + (j * h_stride_val)) * VN_size);
652
653 if (region_offset > var_size)
654 {
655 #ifndef DLL_MODE
656 std::cout << "WARNING: CISA region and offset cause an out of bounds byte access: "<< region_offset << "\n";
657 std::cout << "An access should not exceed the declared allocation size: " << var_size << "\n";
658 std::cout << " The access fails the following check to determine correct bounds (see CISA manual section 5.1 Region-based Addressing):\n";
659 std::cout << " (row_offset * GRF_SIZE + col_offset) + (((i * v_stride) + (j * h_stride)) * type_size) <= type_size * num_elements:\n";
660 std::cout << "(" << (int)row_offset << " * "<< COMMON_ISA_GRF_REG_SIZE << " + "<< (int)col_offset << ") + (((" <<
661 i << " * " << v_stride_val <<") + (" << j <<" * " << h_stride_val << ")) * " << VN_size <<
662 ") <= " << VN_size << " * " << num_elements << "\n";
663 std::cout << "Violating Instruction: " <<
664 printInstruction(header, inst, options) << "\n";
665 #endif // DLL_MODE
666 }
667 }
668 }
669 }
670
671 }
672
isDWordType(VISA_Type type)673 static bool isDWordType(VISA_Type type)
674 {
675 return CISATypeTable[type].typeSize == 4;
676 }
677
678 // verify if this raw operand has the correct type as determined by typeFunc (false means illegal type)
679 // Many vISA messages require the raw operand to have certain types
verifyRawOperandType(const CISA_INST * inst,const raw_opnd & opnd,bool (* typeFunc)(VISA_Type))680 void vISAVerifier::verifyRawOperandType(
681 const CISA_INST* inst,
682 const raw_opnd& opnd,
683 bool (*typeFunc)(VISA_Type))
684 {
685 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
686 uint32_t variable_count = header->getVarCount();
687
688 uint32_t opnd_index = opnd.index;
689
690 if (opnd_index < variable_count + numPreDefinedVars &&
691 numPreDefinedVars <= opnd_index)
692 {
693 const var_info_t* currVar = header->getVar(opnd_index-numPreDefinedVars);
694 REPORT_INSTRUCTION(options,typeFunc(currVar->getType()), "Raw Operand %s has incorrect type %s",
695 opnd.toString().c_str(), CISATypeTable[currVar->getType()].typeName);
696 }
697 }
698
verifyRawOperand(const CISA_INST * inst,unsigned i)699 void vISAVerifier::verifyRawOperand(
700 const CISA_INST* inst, unsigned i)
701 {
702 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
703 uint32_t variable_count = header->getVarCount();
704
705 const raw_opnd& opnd = getRawOperand(inst, i);
706
707 if (numPreDefinedVars > opnd.index)
708 {
709 return; // allow raw operands to be predefined variables
710 }
711
712 uint32_t opnd_index = opnd.index - numPreDefinedVars;
713 uint16_t opnd_offset = opnd.offset;
714
715
716 if (opnd_index < variable_count)
717 {
718 const var_info_t* currVar = header->getVar(opnd_index);
719 unsigned totalOffset = opnd_offset;
720
721 std::set<uint32_t> visitedAliasIndices;
722
723 while (numPreDefinedVars <= currVar->alias_index)
724 {
725 if (visitedAliasIndices.find(currVar->alias_index) != visitedAliasIndices.end())
726 {
727 REPORT_INSTRUCTION(options,false, "Circular alias detected, alias index: %d", currVar->alias_index);
728 break;
729 }
730
731 visitedAliasIndices.insert(currVar->alias_index);
732
733 REPORT_INSTRUCTION(options,currVar->alias_index < variable_count + numPreDefinedVars,
734 "Aliased variable aliases to an invalid alias index. "
735 "Variable count: %d. invalid index: %d",
736 variable_count + numPreDefinedVars,
737 currVar->alias_index);
738
739 totalOffset += currVar->alias_offset;
740 if (numPreDefinedVars > currVar->alias_index)
741 {
742 break; // // allow alias index to be predefined variables
743 }
744 currVar = header->getVar(currVar->alias_index-numPreDefinedVars);
745 }
746
747 if (currVar->getSize() >= numEltPerGRF<Type_UB>() && totalOffset % numEltPerGRF<Type_UB>() != 0)
748 {
749 // raw operand must be GRF-aligned if it's >= 1GRF
750 REPORT_INSTRUCTION(options,false, "Raw operand should be GRF-aligned: Raw offset is %d", totalOffset);
751 }
752
753 if (numPreDefinedVars <= currVar->alias_index)
754 {
755 REPORT_INSTRUCTION(options,totalOffset < currVar->num_elements * (unsigned)CISATypeTable[currVar->getType()].typeSize,
756 "A CISA raw operand's offset field must be within the allocated operand size. "
757 "Raw offset is %d, allocated number of elements is %d",
758 (int)opnd_offset, (int)currVar->num_elements);
759 }
760 }
761 else
762 {
763 /// TODO: Verify predefined vars.
764 }
765 }
766
isReadWritePreDefinedVar(const common_isa_header & isaHeader,uint32_t index,uint32_t byteOffset)767 static bool isReadWritePreDefinedVar(
768 const common_isa_header& isaHeader, uint32_t index, uint32_t byteOffset)
769 {
770 PreDefinedVarsInternal internalIndex = mapExternalToInternalPreDefVar(index);
771 if (internalIndex == PreDefinedVarsInternal::ARG || internalIndex == PreDefinedVarsInternal::RET || internalIndex == PreDefinedVarsInternal::FE_SP ||
772 internalIndex == PreDefinedVarsInternal::FE_FP || internalIndex == PreDefinedVarsInternal::CR0 || internalIndex == PreDefinedVarsInternal::DBG ||
773 internalIndex == PreDefinedVarsInternal::VAR_NULL)
774 {
775 return true;
776 }
777 else if (internalIndex == PreDefinedVarsInternal::TSC && byteOffset == 16)
778 {
779 // tm0.4
780 return true;
781 }
782 else if (internalIndex == PreDefinedVarsInternal::SR0 && (byteOffset == 8 || byteOffset == 12))
783 {
784 // sr0.2, sr0.3
785 return true;
786 }
787 else
788 {
789 return false;
790 }
791 }
792
verifyVectorOperand(const CISA_INST * inst,unsigned i)793 void vISAVerifier::verifyVectorOperand(
794 const CISA_INST* inst,
795 unsigned i)
796 {
797 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
798
799 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
800
801 const vector_opnd& opnd = getVectorOperand(inst, i);
802
803 uint32_t operand_index = opnd.getOperandIndex();
804 Common_ISA_Operand_Class operand_class = opnd.getOperandClass();
805 VISA_Modifier operand_modifier = opnd.getOperandModifier();
806
807
808 unsigned dstIndex = getDstIndex(inst);
809
810 if (inst->opnd_count <= 0)
811 {
812 REPORT_INSTRUCTION(options,false, "Incorrect number of operands loaded.");
813 return;
814 }
815
816 if (operand_class != OPERAND_GENERAL && operand_class != OPERAND_INDIRECT)
817 {
818 REPORT_INSTRUCTION(options,operand_modifier == MODIFIER_NONE,
819 "Operand modifier for non-general and "
820 "non-indirect operands must be MODIFIER_NONE.");
821 }
822
823 switch (operand_modifier)
824 {
825 case MODIFIER_ABS:
826 case MODIFIER_NEG:
827 case MODIFIER_SAT:
828 case MODIFIER_NEG_ABS:
829 if (!isShiftOp(opcode))
830 {
831 REPORT_INSTRUCTION(options,ISA_Inst_Table[opcode].type != ISA_Inst_Logic,
832 "Only arithmetic modifiers should be used with "
833 "arithmetic instruction general or indirect operands.");
834 }
835 break;
836 case MODIFIER_NOT:
837 REPORT_INSTRUCTION(options,ISA_Inst_Table[opcode].type == ISA_Inst_Logic,
838 "Only logical modifiers should be used with "
839 "logical instruction general or indirect operands.");
840 break;
841 default:
842 break; // Prevent gcc warning
843 }
844
845 if (operand_class == OPERAND_IMMEDIATE)
846 {
847 /// Do checks for immediate operands here
848 REPORT_INSTRUCTION(options,getVectorOperandType(header, opnd) != ISA_TYPE_BOOL,
849 "Boolean types for immediate (constant literals) operands are disallowed.");
850 }
851
852 if (operand_class == OPERAND_GENERAL)
853 {
854 REPORT_INSTRUCTION(options,operand_index < header->getVarCount() + numPreDefinedVars, "Variable V%d is not declaired in CISA symtab.", operand_index);
855
856 if (operand_index < header->getVarCount() + numPreDefinedVars &&
857 numPreDefinedVars <= operand_index)
858 {
859 //var_info_t* var = &header->variables[operand_index-numPreDefinedVars];
860 /// do some var verifications here.
861
862 //VISA_Type isa_type_decl = (VISA_Type)((var->bit_properties) & 0xF);
863 //VISA_Type isa_type_var = getVectorOperandType(isaHeader, header, opnd);
864
865 }
866 }
867
868 verifyRegion(inst, i);
869
870 if (dstIndex == i)
871 {
872 REPORT_INSTRUCTION(options,operand_class != OPERAND_IMMEDIATE, "Constant Immediate operands are not allowed to be used as destination operands.");
873
874 if (operand_class == OPERAND_GENERAL)
875 {
876 if (operand_index < numPreDefinedVars)
877 {
878 uint32_t byteOffset = opnd.opnd_val.gen_opnd.row_offset * COMMON_ISA_GRF_REG_SIZE +
879 opnd.opnd_val.gen_opnd.col_offset *
880 Get_VISA_Type_Size(getPredefinedVarType(mapExternalToInternalPreDefVar(operand_index)));
881 REPORT_INSTRUCTION(options, isReadWritePreDefinedVar(isaHeader, operand_index, byteOffset), "Not allowed to write to a read only variable");
882 }
883 }
884 }
885
886 // ToDo: add bounds check for pre-defined variables
887 }
888
verifyOperand(const CISA_INST * inst,unsigned i)889 void vISAVerifier::verifyOperand(
890 const CISA_INST* inst,
891 unsigned i)
892 {
893 if (inst->opcode == ISA_DPAS || inst->opcode == ISA_DPASW)
894 {
895 // skip, as dpas is verified in verifyInstructionMisc().
896 return;
897 }
898 MUST_BE_TRUE(header, "Argument Exception: argument header is NULL.");
899 MUST_BE_TRUE(inst , "Argument Exception: argument inst is NULL.");
900 MUST_BE_TRUE(inst->opnd_count > i, "No such operand, i, for instruction inst.");
901 switch (getOperandType(inst, i))
902 {
903 case CISA_OPND_OTHER : /* unable to verify some random primitive operand. */ break;
904 case CISA_OPND_VECTOR : verifyVectorOperand(inst, i); break;
905 case CISA_OPND_RAW : verifyRawOperand (inst, i); break;
906 default : MUST_BE_TRUE(false, "Invalid operand type.");
907 }
908 }
909
verifyInstructionSVM(const CISA_INST * inst)910 void vISAVerifier::verifyInstructionSVM(
911 const CISA_INST* inst)
912 {
913 if (hasExecSize((ISA_Opcode)inst->opcode))
914 {
915 REPORT_INSTRUCTION(options, EXEC_SIZE_32 != inst->getExecSize(),
916 "Execution size should not be SIMD32 for SVM messages.");
917 }
918 }
919
verifyInstructionMove(const CISA_INST * inst)920 void vISAVerifier::verifyInstructionMove(
921 const CISA_INST* inst)
922 {
923 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
924
925 unsigned i = 0;
926
927 uint8_t opext = opcode == ISA_FMINMAX ? getPrimitiveOperand<uint8_t>(inst, i++) : 0;
928
929 const vector_opnd& dst = getVectorOperand(inst, i++);
930 const vector_opnd& src0 = getVectorOperand(inst, i++);
931
932 Common_ISA_Operand_Class operand_class_dst = dst.getOperandClass();
933 Common_ISA_Operand_Class operand_class_src0 = src0.getOperandClass();
934
935 switch (opcode)
936 {
937 case ISA_MOV:
938 {
939 VISA_Type dstType = getVectorOperandType(header, dst);
940 VISA_Type src0Type = getVectorOperandType(header, src0);
941 VISA_Modifier dstModifier = dst.getOperandModifier();
942
943 if (OPERAND_PREDICATE == operand_class_src0)
944 {
945 REPORT_INSTRUCTION(options,EXEC_SIZE_1 == inst->getExecSize(),
946 "Execution size for a flag copy mov instruction should be 1, as it is a scalar copy.");
947 REPORT_INSTRUCTION(options, IsIntType(dstType) && dstType != ISA_TYPE_Q && dstType != ISA_TYPE_UQ,
948 "dst operand type for a flag copy mov instruction should be non-64-bit integer.");
949 REPORT_INSTRUCTION(options,CISATypeTable[dstType].typeSize >= CISATypeTable[src0Type].typeSize,
950 "dst operand type for a flag copy mov instruction should be "
951 "greater than or equal to the size of the src0 operand's type size.");
952 REPORT_INSTRUCTION(options,dstModifier != MODIFIER_SAT,
953 "saturation is not allowed for dst operands of a flag copy mov instruction");
954 REPORT_INSTRUCTION(options,inst->pred.isNullPred(),
955 "predication is not allowed for dst operands of a flag copy mov instruction");
956 }
957
958 /* Commented out because we are too lame to follow our own specification. */
959 /*
960 REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_GENERAL ||
961 operand_class_dst == OPERAND_INDIRECT,
962 "Destination operand of CISA MOV instruction only "
963 "supports general and indirect operands.");
964
965 REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL ||
966 operand_class_src0 == OPERAND_INDIRECT ||
967 operand_class_src0 == OPERAND_IMMEDIATE,
968 "Source0 operand of CISA MOV instruction only "
969 "supports general, indirect, and immediate operands.");
970 */
971 break;
972 }
973
974 case ISA_MOVS:
975 {
976 REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_GENERAL ||
977 operand_class_dst == OPERAND_STATE,
978 "Destination operand of CISA MOVS instruction only "
979 "supports general and indirect operands.");
980
981 REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL ||
982 operand_class_src0 == OPERAND_STATE ||
983 operand_class_src0 == OPERAND_INDIRECT ||
984 operand_class_src0 == OPERAND_IMMEDIATE,
985 "Source0 operand of CISA MOVS instruction only "
986 "supports general, indirect, and immediate operands.");
987 break;
988 }
989 case ISA_BF_CVT:
990 {
991 REPORT_INSTRUCTION(options, getGenxPlatform() >= XeHP_SDV,
992 "BF_CVT is only supported on this platform");
993 REPORT_INSTRUCTION(options, operand_class_dst == OPERAND_GENERAL,
994 "Destination operand of BF_CVT instruction only "
995 "supports general and operands.");
996
997 REPORT_INSTRUCTION(options, operand_class_src0 == OPERAND_GENERAL,
998 "Source0 operand of BF_CVT instruction only "
999 "supports general, operands.");
1000
1001 VISA_Type dstType = getVectorOperandType(header, dst);
1002 VISA_Type src0Type = getVectorOperandType(header, src0);
1003
1004 // toBeDeletedSoon: checking ISA_TYPE_HF tool
1005 if (dstType == ISA_TYPE_UW || dstType == ISA_TYPE_HF)
1006 {
1007 REPORT_INSTRUCTION(options, src0Type == ISA_TYPE_F,
1008 "BF_CVT with UW(actually BF) dst must have F src");
1009 }
1010 else if (src0Type == ISA_TYPE_UW || src0Type == ISA_TYPE_HF)
1011 {
1012 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F,
1013 "BF_CVT with UW(actually BF) src must have F dst");
1014 }
1015 else
1016 {
1017 REPORT_INSTRUCTION(options, false,
1018 "BF_CVT must have either UW(actually BF) dst or src");
1019 }
1020
1021 VISA_Modifier dstModifier = dst.getOperandModifier();
1022 REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE,
1023 "destination modifier not supported for BF conversion");
1024
1025 VISA_Modifier srcModifier = src0.getOperandModifier();
1026 REPORT_INSTRUCTION(options, srcModifier == MODIFIER_NONE,
1027 "source modifier not supported for BF conversion");
1028 break;
1029
1030 }
1031 case ISA_FCVT:
1032 {
1033 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_PVC,
1034 "fcvt is not supported on the selected platform");
1035
1036 REPORT_INSTRUCTION(options, operand_class_dst == OPERAND_GENERAL,
1037 "Destination operand of fcvt instruction only "
1038 "supports general and operands.");
1039
1040 REPORT_INSTRUCTION(options, operand_class_src0 == OPERAND_GENERAL,
1041 "Source0 operand of fcvt instruction only "
1042 "supports general, operands.");
1043
1044 VISA_Type dstType = getVectorOperandType(header, dst);
1045 VISA_Type src0Type = getVectorOperandType(header, src0);
1046
1047 if (dstType == ISA_TYPE_UB)
1048 {
1049 REPORT_INSTRUCTION(options, src0Type == ISA_TYPE_HF,
1050 "F_CVT with UB(actually BF8) dst must have HF src");
1051 }
1052 else if (src0Type == ISA_TYPE_UB)
1053 {
1054 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_HF,
1055 "F_CVT with UB(actually BF8) src must have HF dst");
1056 }
1057 else if (dstType == ISA_TYPE_UD)
1058 {
1059 REPORT_INSTRUCTION(options, src0Type == ISA_TYPE_F,
1060 "F_CVT with UD(actually TF32) dst must have F src");
1061 }
1062 else if (src0Type == ISA_TYPE_UD)
1063 {
1064 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F,
1065 "F_CVT with UD(actually TF32) src0 must have F dst");
1066 }
1067 else
1068 {
1069 REPORT_INSTRUCTION(options, false,
1070 "F_CVT must have either UB(actually BF8) dst or src");
1071 }
1072
1073 VISA_Modifier dstModifier = dst.getOperandModifier();
1074 VISA_Modifier srcModifier = src0.getOperandModifier();
1075 REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE,
1076 "destination modifier not supported for BF8/TF32 conversion");
1077 REPORT_INSTRUCTION(options, srcModifier == MODIFIER_NONE,
1078 "source modifier not supported for BF8/TF32 conversion");
1079 break;
1080
1081 }
1082 case ISA_SETP:
1083 {
1084 REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_PREDICATE,
1085 "Destination operand of CISA SETP instruction only "
1086 "supports predicate operands.");
1087
1088
1089 REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL ||
1090 operand_class_src0 == OPERAND_INDIRECT ||
1091 operand_class_src0 == OPERAND_IMMEDIATE,
1092 "Source0 operand of CISA SETP instruction only "
1093 "supports general, indirect, and immediate operands.");
1094 break;
1095 }
1096 case ISA_SEL:
1097 case ISA_FMINMAX:
1098 {
1099 REPORT_INSTRUCTION(options,opext <= 1, "FMINMAX opext must be either 0x0 or 0x1 (min or max).");
1100
1101 const vector_opnd& src1 = getVectorOperand(inst, i++);
1102 Common_ISA_Operand_Class operand_class_src1 = src1.getOperandClass();
1103
1104 REPORT_INSTRUCTION(options,operand_class_dst == OPERAND_GENERAL ||
1105 operand_class_dst == OPERAND_INDIRECT,
1106 "Destination operand of CISA SEL instruction only "
1107 "supports general and indirect operands.");
1108
1109 REPORT_INSTRUCTION(options,operand_class_src0 == OPERAND_GENERAL ||
1110 operand_class_src0 == OPERAND_INDIRECT ||
1111 operand_class_src0 == OPERAND_IMMEDIATE,
1112 "Source0 operand of CISA SEL instruction only "
1113 "supports general, indirect, and immediate operands.");
1114
1115 REPORT_INSTRUCTION(options,operand_class_src1 == OPERAND_GENERAL ||
1116 operand_class_src1 == OPERAND_INDIRECT ||
1117 operand_class_src1 == OPERAND_IMMEDIATE,
1118 "Source1 operand of CISA SEL instruction only "
1119 "supports general, indirect, and immediate operands.");
1120 break;
1121 }
1122 default: REPORT_INSTRUCTION(options,false, "Illegal Move Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1123 }
1124 }
1125
verifyInstructionSync(const CISA_INST * inst)1126 void vISAVerifier::verifyInstructionSync(
1127 const CISA_INST* inst)
1128 {
1129 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1130 switch (opcode)
1131 { case ISA_BARRIER : return;
1132 case ISA_SAMPLR_CACHE_FLUSH : return;
1133 case ISA_WAIT : return;
1134 case ISA_FENCE : return;
1135 case ISA_YIELD : return;
1136 case ISA_SBARRIER : return;
1137 case ISA_NBARRIER : return;
1138 default: REPORT_INSTRUCTION(options,false, "Illegal Synchronization Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1139 }
1140 }
1141
verifyInstructionControlFlow(const CISA_INST * inst)1142 void vISAVerifier::verifyInstructionControlFlow(
1143 const CISA_INST* inst)
1144 {
1145 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1146
1147 switch (opcode)
1148 {
1149 case ISA_JMP:
1150 case ISA_CALL:
1151 {
1152 bool isFC = static_cast<G4_Label*>(inst->opnd_array[0]->g4opnd)->isFCLabel();
1153 auto labelId = getPrimitiveOperand<uint16_t>(inst, 0);
1154 if (labelId >= header->getLabelCount())
1155 {
1156 REPORT_INSTRUCTION(options, false, "bad label id %d", labelId);
1157 }
1158 else
1159 {
1160 auto iter = labelDefs.find(labelId);
1161 if (iter == labelDefs.end() && !isFC)
1162 {
1163 labelDefs[labelId] = false;
1164 }
1165 // nothing needs to be done if the label is already in the map
1166 }
1167 break;
1168 }
1169 case ISA_RET:
1170 case ISA_FRET:
1171 case ISA_IFCALL:
1172 case ISA_FADDR: // no checks for now
1173 break;
1174 case ISA_SUBROUTINE:
1175 case ISA_LABEL:
1176 {
1177 auto labelId = getPrimitiveOperand<uint16_t>(inst, 0);
1178 if (labelId >= header->getLabelCount())
1179 {
1180 REPORT_INSTRUCTION(options, false, "bad label id %d", labelId);
1181 }
1182 else
1183 {
1184 auto iter = labelDefs.find(labelId);
1185 if (iter != labelDefs.end() && iter->second)
1186 {
1187 REPORT_INSTRUCTION(options, false, "label is redefined");
1188 }
1189 labelDefs[labelId] = true;
1190 }
1191 break;
1192 }
1193 case ISA_FCALL:
1194 {
1195 break;
1196 }
1197 case ISA_SWITCHJMP:
1198 {
1199 REPORT_INSTRUCTION(options, !irBuilder->hasFusedEU(), "switchjmp is not supported on this platform");
1200 break;
1201 }
1202 default: REPORT_INSTRUCTION(options,false, "Illegal Scalar Control Flow Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1203 }
1204 }
1205
verifyInstructionMisc(const CISA_INST * inst)1206 void vISAVerifier::verifyInstructionMisc(
1207 const CISA_INST* inst)
1208 {
1209 unsigned i = 0;
1210 unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
1211
1212 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1213 switch (opcode)
1214 {
1215 case ISA_VME_IME:
1216 {
1217 uint8_t stream_mode = getPrimitiveOperand<uint8_t>(inst, i++);
1218 REPORT_INSTRUCTION(options,stream_mode == VME_STREAM_DISABLE ||
1219 stream_mode == VME_STREAM_OUT ||
1220 stream_mode == VME_STREAM_IN ||
1221 stream_mode == VME_STREAM_IN_OUT,
1222 "CISA ISA_VME_IME instruction uses illegal stream mode.");
1223
1224 uint8_t search_ctrl = getPrimitiveOperand<uint8_t>(inst, i++);
1225 REPORT_INSTRUCTION(options,search_ctrl == VME_SEARCH_SINGLE_REF_SINGLE_REC_SINGLE_START ||
1226 search_ctrl == VME_SEARCH_SINGLE_REF_SINGLE_REC_DUAL_START ||
1227 search_ctrl == VME_SEARCH_SINGLE_REF_DUAL_REC ||
1228 search_ctrl == VME_SEARCH_DUAL_REF_DUAL_REC,
1229 "CISA ISA_VME_IME instruction uses illegal search ctrl.");
1230
1231 i++; /// uni input
1232 i++; /// ime input
1233
1234 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1235 REPORT_INSTRUCTION(options,(unsigned)surface < numPreDefinedSurfs + header->getSurfaceCount(),
1236 "CISA ISA_VME_IME uses undeclared surface.");
1237
1238 break;
1239 }
1240 case ISA_VME_SIC:
1241 {
1242 i++; /// uni input
1243 i++; /// sic input
1244
1245 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1246 REPORT_INSTRUCTION(options,(unsigned)surface < numPreDefinedSurfs + header->getSurfaceCount(),
1247 "CISA ISA_VME_SIC uses undeclared surface.");
1248
1249 break;
1250 }
1251 case ISA_VME_FBR:
1252 {
1253 getRawOperand(inst, i++); // const raw_opnd& UNIInput
1254 getRawOperand(inst, i++); // const raw_opnd& FBRInput
1255
1256 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
1257 REPORT_INSTRUCTION(options,(unsigned)surface < numPreDefinedSurfs + header->getSurfaceCount(),
1258 "CISA ISA_VME_FBR uses undeclared surface.");
1259
1260 Common_ISA_Operand_Class operand_class_FBRMbMode = getVectorOperand(inst, i++).getOperandClass();
1261 REPORT_INSTRUCTION(options,operand_class_FBRMbMode == OPERAND_GENERAL ||
1262 operand_class_FBRMbMode == OPERAND_INDIRECT ||
1263 operand_class_FBRMbMode == OPERAND_IMMEDIATE,
1264 "FBRMbMode operand of CISA VME_FBR instrution should "
1265 "be either a general, indirect, or immediate operand.");
1266
1267 Common_ISA_Operand_Class operand_class_FBRSubMbShape = getVectorOperand(inst, i++).getOperandClass();
1268 REPORT_INSTRUCTION(options,operand_class_FBRSubMbShape == OPERAND_GENERAL ||
1269 operand_class_FBRSubMbShape == OPERAND_INDIRECT ||
1270 operand_class_FBRSubMbShape == OPERAND_IMMEDIATE,
1271 "FBRSubMbShape operand of CISA VME_FBR instrution should "
1272 "be either a general, indirect, or immediate operand.");
1273
1274 Common_ISA_Operand_Class operand_class_FBRSubPredMode = getVectorOperand(inst, i++).getOperandClass();
1275 REPORT_INSTRUCTION(options,operand_class_FBRSubPredMode == OPERAND_GENERAL ||
1276 operand_class_FBRSubPredMode == OPERAND_INDIRECT ||
1277 operand_class_FBRSubPredMode == OPERAND_IMMEDIATE,
1278 "FBRSubPredMode operand of CISA VME_FBR instrution should "
1279 "be either a general, indirect, or immediate operand.");
1280
1281 getRawOperand(inst, i++); // const raw_opnd& output
1282
1283 break;
1284 }
1285 case ISA_VME_IDM:
1286 {
1287 break;
1288 }
1289 case ISA_LOC:
1290 {
1291 break;
1292 }
1293 case ISA_FILE:
1294 {
1295 break;
1296 }
1297 case ISA_RAW_SEND:
1298 {
1299 getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t modifier
1300
1301 getPrimitiveOperand<uint8_t>(inst, i++); // unit8_t exMsgDesc
1302
1303 uint8_t numSrc = getPrimitiveOperand<uint8_t>(inst, i++);
1304 REPORT_INSTRUCTION(options,numSrc >= 1 && numSrc <= 15, "Number of message source GRFs must be between 1 and 15");
1305
1306 uint8_t numDst = getPrimitiveOperand<uint8_t>(inst, i++);
1307 REPORT_INSTRUCTION(options,numDst <= 16, "Number of message destination GRFs must be between 0 and 16");
1308
1309 const vector_opnd& desc = getVectorOperand(inst, i++);
1310 Common_ISA_Operand_Class operand_class_desc = desc.getOperandClass();
1311 REPORT_INSTRUCTION(options, operand_class_desc == OPERAND_GENERAL ||
1312 operand_class_desc == OPERAND_INDIRECT ||
1313 operand_class_desc == OPERAND_IMMEDIATE,
1314 "desc operand of CISA RAW_SEND instrution should "
1315 "be either a general, indirect, or immediate operand.");
1316
1317 if (operand_class_desc == OPERAND_IMMEDIATE)
1318 {
1319 /// Structure describes a send message descriptor. Only expose
1320 /// several data fields; others are unnamed.
1321 struct MsgDescLayout {
1322 uint32_t funcCtrl : 19; // Function control (bit 0:18)
1323 uint32_t headerPresent : 1; // Header present (bit 19)
1324 uint32_t rspLength : 5; // Response length (bit 20:24)
1325 uint32_t msgLength : 4; // Message length (bit 25:28)
1326 uint32_t simdMode2 : 1; // 16-bit input (bit 29)
1327 uint32_t returnFormat : 1; // 16-bit return (bit 30)
1328 uint32_t EOT : 1; // EOT
1329 };
1330
1331 /// View a message descriptor in two different ways:
1332 /// - as a 32-bit unsigned integer
1333 /// - as a structure
1334 /// This simplifies the implementation of extracting subfields.
1335 union DescData {
1336 uint32_t value;
1337 MsgDescLayout layout;
1338 }udesc;
1339
1340 udesc.value = desc.opnd_val.const_opnd._val.ival;
1341
1342 REPORT_INSTRUCTION(options, numSrc >= udesc.layout.msgLength,
1343 "message length mismatch for raw send: msgLength (%d) must be not greater than numSrc (%d)",
1344 udesc.layout.msgLength, numSrc);
1345 REPORT_INSTRUCTION(options, numDst >= udesc.layout.rspLength,
1346 "response length mismatch for raw send: rspLength (%d) must be not greater than numDst (%d)",
1347 udesc.layout.rspLength, numDst);
1348 }
1349
1350
1351 /// src: todo
1352 /// dst: todo
1353
1354 break;
1355 }
1356 case ISA_RAW_SENDS:
1357 {
1358 getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t modifier
1359
1360 uint8_t numSrc0 = getPrimitiveOperand<uint8_t>(inst, i++);
1361 REPORT_INSTRUCTION(options,numSrc0 >= 1 && numSrc0 <= 32, "Number of source0 GRFs must be between 1 and 32");
1362
1363 uint8_t numSrc1 = getPrimitiveOperand<uint8_t>(inst, i++);
1364 REPORT_INSTRUCTION(options, numSrc1 <= 32, "Number of source1 GRFs must be between 1 and 32");
1365
1366 uint8_t numDst = getPrimitiveOperand<uint8_t>(inst, i++);
1367 REPORT_INSTRUCTION(options,numDst <= 32, "Number of message destination GRFs must be between 0 and 32");
1368
1369 getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t exMsgDesc
1370
1371 Common_ISA_Operand_Class operand_class_desc = getVectorOperand(inst, i++).getOperandClass();
1372 REPORT_INSTRUCTION(options,operand_class_desc == OPERAND_GENERAL ||
1373 operand_class_desc == OPERAND_INDIRECT ||
1374 operand_class_desc == OPERAND_IMMEDIATE,
1375 "desc operand of CISA RAW_SEND instrution should "
1376 "be either a general, indirect, or immediate operand.");
1377
1378 /// src0: todo
1379 /// src1: todo
1380 /// dst: todo
1381
1382 break;
1383 }
1384 case ISA_3D_URB_WRITE:
1385 {
1386 uint8_t numOut = getPrimitiveOperand<uint8_t>(inst, i++);
1387 getPrimitiveOperand<uint16_t>(inst, i++); // uint16_t channelMask
1388 uint16_t globalOff = getPrimitiveOperand<uint16_t>(inst, i++);
1389
1390 REPORT_INSTRUCTION(options,!(numOut < 1 || numOut > 8) , "Valid range for num_out parameter of URB write is [1,8]");
1391 REPORT_INSTRUCTION(options,globalOff <= 2047, "Valid range for global_offset parameter of URB write is [0,2047]");
1392 REPORT_INSTRUCTION(options, inst->getExecSize() == EXEC_SIZE_1 || inst->getExecSize() == EXEC_SIZE_8,
1393 "Only execution size of 1 or 8 is supported for URB write");
1394
1395 break;
1396 }
1397 case ISA_DPAS:
1398 case ISA_DPASW:
1399 {
1400 auto FNIsInt = [](VISA_Type Ty) -> bool {
1401 return (Ty == ISA_TYPE_UD || Ty == ISA_TYPE_D);
1402 };
1403 auto FNIsIntOrFloat = [](VISA_Type Ty) -> bool {
1404 bool isHFOrBF = false;
1405 if (getGenxPlatform() >= GENX_PVC)
1406 {
1407 // W or UW means BF
1408 isHFOrBF = (Ty == ISA_TYPE_HF || Ty == ISA_TYPE_UW || Ty == ISA_TYPE_W);
1409 }
1410 return (Ty == ISA_TYPE_UD || Ty == ISA_TYPE_D || Ty == ISA_TYPE_F || isHFOrBF);
1411 };
1412
1413 // No predicate
1414 REPORT_INSTRUCTION(options, inst->pred.isNullPred(), "%s inst does not support predicate", ISA_Inst_Table[opcode].str);
1415
1416 // execsize must be simd8 for XeHP_SDV and simd16 for PVC
1417 if (getGenxPlatform() >= GENX_PVC)
1418 {
1419 REPORT_INSTRUCTION(options, opcode != ISA_DPASW,
1420 "%s instuction is not supported on selected platform", ISA_Inst_Table[opcode].str);
1421 REPORT_INSTRUCTION(options, inst->getExecSize() == EXEC_SIZE_16,
1422 "Only execution size of 16 is supported for %s on platform %s",
1423 ISA_Inst_Table[opcode].str, getGenxPlatformString(getGenxPlatform()));
1424 }
1425 else
1426 {
1427 REPORT_INSTRUCTION(options, inst->getExecSize() == EXEC_SIZE_8,
1428 "Only execution size of 8 is supported for %s on platform %s",
1429 ISA_Inst_Table[opcode].str, getGenxPlatformString(getGenxPlatform()));
1430 }
1431
1432 // dst
1433 verifyRawOperand(inst, i);
1434 const raw_opnd& dst = getRawOperand(inst, i);
1435 verifyRawOperandType(inst, dst, FNIsIntOrFloat);
1436
1437 // src0
1438 verifyRawOperand(inst, ++i);
1439 const raw_opnd& src0 = getRawOperand(inst, i);
1440 verifyRawOperandType(inst, src0, FNIsIntOrFloat);
1441
1442 // src1
1443 verifyRawOperand(inst, ++i);
1444 const raw_opnd& src1 = getRawOperand(inst, i);
1445 verifyRawOperandType(inst, src1, FNIsInt);
1446
1447 // src2
1448 const vector_opnd& src2 = getVectorOperand(inst, ++i);
1449 VISA_Type src2Ty = getVectorOperandType(header, src2);
1450 VISA_Modifier src2Mod = src2.getOperandModifier();
1451 REPORT_INSTRUCTION(options, src2Mod == MODIFIER_NONE, "Modifier not allowed for %s", ISA_Inst_Table[opcode].str);
1452 REPORT_INSTRUCTION(options, FNIsInt(src2Ty), "Only U/UD allowed for %s", ISA_Inst_Table[opcode].str);
1453
1454 break;
1455 }
1456 case ISA_LIFETIME:
1457 {
1458 uint8_t properties = getPrimitiveOperand<uint8_t>(inst, i++);
1459 getPrimitiveOperand<uint32_t>(inst, i++); // uint32_t varId
1460
1461 unsigned char type = (properties >> 4) & 0x3;
1462
1463 if (type != OPERAND_GENERAL && type != OPERAND_ADDRESS && type != OPERAND_PREDICATE)
1464 {
1465 REPORT_INSTRUCTION(options, false, "Invalid encoding for register file");
1466 }
1467
1468 break;
1469 }
1470 default: REPORT_INSTRUCTION(options,false, "Illegal Miscellaneous Flow Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
1471 }
1472 }
1473
1474 /// Returns true if this vector operand is an integer immediate constant and
1475 /// its value fits into an expected type. Returns false, otherwise.
1476 ///
checkImmediateIntegerOpnd(const vector_opnd & opnd,VISA_Type expected_type)1477 bool vISAVerifier::checkImmediateIntegerOpnd(
1478 const vector_opnd& opnd,
1479 VISA_Type expected_type)
1480 {
1481 MUST_BE_TRUE(IsIntType(expected_type), "integer type expected");
1482
1483 // Not an immediate.
1484 if (!opnd.isImmediate())
1485 return false;
1486
1487 VISA_Type opnd_type = opnd.getImmediateType();
1488 if (!IsIntOrIntVecType(opnd_type))
1489 {
1490 return false;
1491 }
1492
1493 bool is_vector = (opnd_type == ISA_TYPE_V || opnd_type == ISA_TYPE_UV);
1494 if (is_vector)
1495 {
1496 // if the operand type is unsigned, then always fits;
1497 // if the expected type is signed, then always fits;
1498 // otherwise, to be determined.
1499 if ((opnd_type == ISA_TYPE_UV) || IsSingedIntType(expected_type))
1500 return true;
1501 }
1502
1503 // Retrieve the immediate integer value.
1504 int64_t val = 0;
1505 if (opnd_type == ISA_TYPE_Q || opnd_type == ISA_TYPE_UQ)
1506 val = typecastVals(&opnd.opnd_val.const_opnd._val.lval, opnd_type);
1507 else
1508 val = typecastVals(&opnd.opnd_val.const_opnd._val.ival, opnd_type);
1509
1510 // The operand type is signed, and the expected type is unsigned.
1511 // All elements in this packed integer vector should be non-negative,
1512 // otherwise it does not fit.
1513 if (is_vector)
1514 {
1515 MUST_BE_TRUE(IsUnsignedIntType(expected_type), "unexpected signed type");
1516
1517 // Truncate to 32 bit, each 4 bits consist of a vector component.
1518 // Sign bits are 3, 7, 11, 15, 19, 23, 27 and 31.
1519 return ((int32_t)val & 0x88888888) == 0;
1520 }
1521
1522 switch (expected_type) {
1523 case ISA_TYPE_B:
1524 return (int8_t)val == val;
1525 case ISA_TYPE_UB:
1526 return (val >= 0) && ((uint8_t)val == val);
1527 case ISA_TYPE_W:
1528 return (int16_t)val == val;
1529 case ISA_TYPE_UW:
1530 return (val >= 0) && ((uint16_t)val == val);
1531 case ISA_TYPE_D:
1532 return (int32_t)val == val;
1533 case ISA_TYPE_UD:
1534 return (val >= 0) && ((uint32_t)val == val);
1535 case ISA_TYPE_Q:
1536 {
1537 // It does not fit into Q only if operand has type UQ and its value
1538 // exceeds the limit.
1539 if (opnd_type == ISA_TYPE_UQ)
1540 {
1541 // The actual value is to reprensent as an unsigned integer.
1542 uint64_t u_val = static_cast<uint64_t>(val);
1543 return u_val <= (uint64_t)std::numeric_limits<int64_t>::max();
1544 }
1545
1546 // Fit for all other cases.
1547 return true;
1548 }
1549 case ISA_TYPE_UQ:
1550 {
1551 // UQ values fit.
1552 if (opnd_type == ISA_TYPE_UQ)
1553 return true;
1554
1555 // Not UQ, but Q or smaller types.
1556 return val >= 0;
1557 }
1558 default:
1559 break;
1560 }
1561 return false;
1562 }
1563
verifyInstructionArith(const CISA_INST * inst)1564 void vISAVerifier::verifyInstructionArith(
1565 const CISA_INST* inst)
1566 {
1567 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1568
1569 if (opcode == ISA_SRND)
1570 {
1571 verifyInstructionSrnd(inst);
1572 return;
1573 }
1574 if (useGivenVISAType(inst, ISA_TYPE_BF))
1575 {
1576 // Let bfmode verifier to verify it.
1577 return;
1578 }
1579
1580 unsigned i = 0;
1581 const vector_opnd& dst = getVectorOperand(inst, i);
1582 VISA_Type dstType = getVectorOperandType(header, dst);
1583 VISA_Modifier dstModifier = dst.getOperandModifier();
1584 auto platform = getGenxPlatform();
1585
1586 REPORT_INSTRUCTION(options, dst.getOperandClass() == OPERAND_GENERAL ||
1587 dst.getOperandClass() == OPERAND_INDIRECT,
1588 "Destination of CISA arithmetic instruction should be general or indirect operand.");
1589
1590 REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE ||
1591 dstModifier == MODIFIER_SAT,
1592 "Illegal destination modifier for CISA arithmetic instruction.");
1593
1594 // check if sat is allowed for this instruction
1595 if (dstModifier == MODIFIER_SAT)
1596 {
1597 switch (opcode)
1598 {
1599 case ISA_FRC:
1600 case ISA_LZD:
1601 case ISA_MOD:
1602 case ISA_MULH:
1603 case ISA_MADW:
1604 REPORT_INSTRUCTION(options, false,
1605 "%s does not support saturation",
1606 ISA_Inst_Table[opcode].str);
1607 break;
1608 case ISA_DIV:
1609 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || dstType == ISA_TYPE_HF,
1610 "%s does not support saturation on integer types.",
1611 ISA_Inst_Table[opcode].str);
1612 default:
1613 break;
1614 }
1615 }
1616
1617 if (dstType == ISA_TYPE_DF)
1618 {
1619 if (opcode != ISA_MUL && opcode != ISA_ADD && opcode != ISA_MAD && opcode != ISA_DIV &&
1620 opcode != ISA_INV && opcode != ISA_SQRTM && opcode != ISA_SQRT && opcode != ISA_DIVM)
1621 {
1622 REPORT_INSTRUCTION(options, false,
1623 "Only mul/add/mad/div/inv/sqrtm/sqrt/divm are allowed to use double precision floating point operands.");
1624 }
1625 }
1626
1627 if ((opcode == ISA_DIV && IsIntType(dstType)) || opcode == ISA_MOD)
1628 {
1629 REPORT_INSTRUCTION(options, platform < XeHP_SDV, "int divide/remainder is not supported for this platform");
1630 }
1631
1632 /// check dst type is supported by the instruction
1633 switch (opcode)
1634 {
1635 case ISA_COS:
1636 case ISA_EXP:
1637 case ISA_LOG:
1638 case ISA_POW:
1639 case ISA_SIN:
1640 /// float and half float
1641 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || dstType == ISA_TYPE_HF,
1642 "%s only supports single and half float type", ISA_Inst_Table[opcode].str);
1643 break;
1644 case ISA_RNDD:
1645 case ISA_RNDU:
1646 case ISA_RNDE:
1647 case ISA_RNDZ:
1648 case ISA_PLANE:
1649 case ISA_DP2:
1650 case ISA_DP3:
1651 case ISA_DP4:
1652 case ISA_DPH:
1653 case ISA_FRC:
1654 case ISA_LRP:
1655 /// float only
1656 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F, "%s only supports single float type", ISA_Inst_Table[opcode].str);
1657 break;
1658 case ISA_LINE:
1659 /// float or int only
1660 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || IsIntType(dstType),
1661 "%s only supports integer and single precision float types", ISA_Inst_Table[opcode].str);
1662 break;
1663 case ISA_AVG:
1664 case ISA_MOD:
1665 /// int only
1666 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD ||
1667 dstType == ISA_TYPE_D ||
1668 dstType == ISA_TYPE_UW ||
1669 dstType == ISA_TYPE_W ||
1670 dstType == ISA_TYPE_UB ||
1671 dstType == ISA_TYPE_B,
1672 "%s only supports integer type", ISA_Inst_Table[opcode].str);
1673 break;
1674 case ISA_LZD:
1675 /// UD only
1676 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD, "lzd only supports UD type");
1677 break;
1678 case ISA_MULH:
1679 case ISA_DP4A:
1680 case ISA_MADW:
1681 /// U or UD only
1682 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_D || dstType == ISA_TYPE_UD,
1683 "%s only support D/UD dst type", ISA_Inst_Table[opcode].str);
1684 break;
1685 case ISA_SAD2:
1686 case ISA_SAD2ADD:
1687 /// dst must be w or uw
1688 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_W || dstType == ISA_TYPE_UW, "sad2/sad2add only supports W/UW dst type.");
1689 REPORT_INSTRUCTION(options, getPlatformGeneration(getGenxPlatform()) != PlatformGen::XE, "sad2/sad2add is not supported on Xe.");
1690 break;
1691 case ISA_ADDC:
1692 case ISA_SUBB:
1693 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD, "%s only supports single UD type", ISA_Inst_Table[opcode].str);
1694 break;
1695 case ISA_ADD3:
1696 case ISA_ADD3O:
1697 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_UD || dstType == ISA_TYPE_D ||
1698 dstType == ISA_TYPE_UW || dstType == ISA_TYPE_W,
1699 "%s only supports interger D/W type", ISA_Inst_Table[opcode].str);
1700 break;
1701 default:
1702 REPORT_INSTRUCTION(options, dstType == ISA_TYPE_F || dstType == ISA_TYPE_DF || dstType == ISA_TYPE_HF || IsIntType(dstType), "%s has illegal dst type", ISA_Inst_Table[opcode].str);
1703 }
1704
1705 // verify each source operand
1706 for (unsigned i = 0; i < ISA_Inst_Table[opcode].n_srcs; i++)
1707 {
1708 const vector_opnd& src = getVectorOperand(inst, i + ISA_Inst_Table[opcode].n_dsts); /// dst is at index 0, addc/subbb have two destinations
1709 VISA_Type srcType = getVectorOperandType(header, src);
1710 VISA_Modifier srcModifier = src.getOperandModifier();
1711
1712 REPORT_INSTRUCTION(options, srcModifier != MODIFIER_SAT && srcModifier != MODIFIER_NOT,
1713 "unsupported source modifier for arithmetic instruction");
1714
1715 REPORT_INSTRUCTION(options, src.getOperandClass() == OPERAND_GENERAL ||
1716 src.getOperandClass() == OPERAND_INDIRECT ||
1717 src.getOperandClass() == OPERAND_IMMEDIATE,
1718 "source in arithmetic instruction must be general, indirect, or immediate");
1719
1720 if (srcType == ISA_TYPE_DF)
1721 {
1722 if (opcode != ISA_MUL && opcode != ISA_ADD && opcode != ISA_MAD && opcode != ISA_DIV &&
1723 opcode != ISA_INV && opcode != ISA_SQRTM && opcode != ISA_SQRT && opcode != ISA_DIVM)
1724 {
1725 REPORT_INSTRUCTION(options, false,
1726 "Only mul/add/mad/div/inv/sqrtm/sqrt/divm are allowed to use double precision floating point operands.");
1727 }
1728 }
1729
1730 if (dstType == ISA_TYPE_F ||
1731 dstType == ISA_TYPE_DF ||
1732 dstType == ISA_TYPE_HF ||
1733 srcType == ISA_TYPE_DF ||
1734 srcType == ISA_TYPE_F ||
1735 srcType == ISA_TYPE_HF)
1736 {
1737 REPORT_INSTRUCTION(options, dstType == srcType ||
1738 (dstType == ISA_TYPE_F && srcType == ISA_TYPE_VF) ||
1739 (dstType == ISA_TYPE_F && srcType == ISA_TYPE_HF) ||
1740 (dstType == ISA_TYPE_HF && srcType == ISA_TYPE_F),
1741 "Arithmetic instructions that use single or double precision or half float types "
1742 "must use the same type for all of their operannds: dst(%s) and src%d(%s).",
1743 CISATypeTable[dstType].typeName, i, CISATypeTable[srcType].typeName);
1744 }
1745 else
1746 {
1747 /// source must have integer type
1748 REPORT_INSTRUCTION(options, IsIntType(srcType) ||
1749 (src.getOperandClass() == OPERAND_IMMEDIATE &&
1750 (srcType == ISA_TYPE_V || srcType == ISA_TYPE_UV)),
1751 "immediate src%d has %d type, and it must have integer type", i, srcType);
1752 }
1753
1754 switch (opcode)
1755 {
1756 case ISA_SAD2:
1757 case ISA_SAD2ADD:
1758 {
1759 bool is_valid_imm = false;
1760 if (i == 2)
1761 {
1762 is_valid_imm = checkImmediateIntegerOpnd(src, ISA_TYPE_W) ||
1763 checkImmediateIntegerOpnd(src, ISA_TYPE_UW);
1764 }
1765 else
1766 {
1767 is_valid_imm = checkImmediateIntegerOpnd(src, ISA_TYPE_B) ||
1768 checkImmediateIntegerOpnd(src, ISA_TYPE_UB);
1769 }
1770 REPORT_INSTRUCTION(options, is_valid_imm ||
1771 (i == 2 && (srcType == ISA_TYPE_W || srcType == ISA_TYPE_UW)) ||
1772 (i <= 1 && (srcType == ISA_TYPE_B || srcType == ISA_TYPE_UB)),
1773 "sad2/sad2add only supports B/UB types for src0 and src1; W/UW for src2 (sad2add). src%d has invalid type.", i);
1774 break;
1775 }
1776 case ISA_MUL:
1777 case ISA_DIV:
1778 REPORT_INSTRUCTION(options, srcType != ISA_TYPE_Q && srcType != ISA_TYPE_UQ,
1779 "mul does not support Q/UQ types for src%d", i);
1780 break;
1781 case ISA_DIVM:
1782 REPORT_INSTRUCTION(options, srcType == ISA_TYPE_F || srcType == ISA_TYPE_DF || srcType == ISA_TYPE_VF,
1783 "ieee div does not support types for src%d, other than F/DF/VF", i);
1784 break;
1785 case ISA_SQRTM:
1786 REPORT_INSTRUCTION(options, srcType == ISA_TYPE_F || srcType == ISA_TYPE_DF || srcType == ISA_TYPE_VF,
1787 "ieee sqrt does not support types for src%d, other than F/DF/VF", i);
1788 break;
1789 case ISA_ADDC:
1790 case ISA_SUBB:
1791 {
1792 REPORT_INSTRUCTION(options, srcType == ISA_TYPE_UD || srcType == ISA_TYPE_UV,
1793 "%s src0 and src1 only supports single UD type", ISA_Inst_Table[opcode].str);
1794 break;
1795 }
1796 case ISA_DP4A:
1797 REPORT_INSTRUCTION(options,
1798 srcType == ISA_TYPE_D || srcType == ISA_TYPE_UD,
1799 "%s src0 and src1 only supports single UD type",
1800 ISA_Inst_Table[opcode].str);
1801 break;
1802 case ISA_ADD3:
1803 case ISA_ADD3O:
1804 REPORT_INSTRUCTION(options,
1805 srcType == ISA_TYPE_D || srcType == ISA_TYPE_UD ||
1806 srcType == ISA_TYPE_W || srcType == ISA_TYPE_UW,
1807 "%s src operand only supports integer D/W type", ISA_Inst_Table[opcode].str);
1808 break;
1809 default:
1810 break; // Prevent gcc warning
1811 }
1812 }
1813
1814 // check for IEEE macros support
1815 // !hasMadm() check
1816 bool noMadm = (platform == GENX_ICLLP || platform == GENX_TGLLP);
1817 noMadm |= platform == GENX_DG2;
1818 if (noMadm)
1819 {
1820 bool fOpcodeIEEE = (opcode == ISA_DIVM) || (opcode == ISA_SQRTM);
1821 bool dfOpcodeIEEE = fOpcodeIEEE || (opcode == ISA_INV) || (opcode == ISA_DIV) || (opcode == ISA_SQRT);
1822 REPORT_INSTRUCTION(options,
1823 !(dstType == ISA_TYPE_DF && dfOpcodeIEEE) &&
1824 !(dstType == ISA_TYPE_F && fOpcodeIEEE),
1825 "IEEE instruction %s is not supported on %s platform",
1826 ISA_Inst_Table[opcode].str, getGenxPlatformString(platform));
1827 }
1828 }
1829
verifyInstructionLogic(const CISA_INST * inst)1830 void vISAVerifier::verifyInstructionLogic(
1831 const CISA_INST* inst)
1832 {
1833 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1834
1835 bool pred_logic = false;
1836 unsigned opend_count = inst->opnd_count;
1837 if (opcode == ISA_BFN)
1838 {
1839 // check opnd type of the last opend, which is BooleanFuncCtrl
1840 REPORT_INSTRUCTION(options,
1841 getOperandType(inst, opend_count - 1) == CISA_OPND_OTHER,
1842 "last opnd should be CISA_OPND_OTHER type");
1843 // skip below type check for booleanFuncCtrl
1844 --opend_count;
1845 }
1846 for (unsigned i = 0; i < opend_count; i++)
1847 {
1848 const vector_opnd& opnd = getVectorOperand(inst, i);
1849 VISA_Type opnd_type = getVectorOperandType(header, opnd);
1850
1851 REPORT_INSTRUCTION(
1852 options, opnd.getOperandClass() != OPERAND_ADDRESS,
1853 "Common ISA Logic instrutions are not allowed to have address operands.");
1854
1855 REPORT_INSTRUCTION(options,
1856 !pred_logic || opnd_type == ISA_TYPE_BOOL,
1857 "Operand type of logic operantion for predicate operands should all be BOOL "
1858 "(ie if one operand is BOOL they all have to be BOOL).");
1859
1860 if (opcode == ISA_ROR || opcode == ISA_ROL)
1861 {
1862 switch (opnd_type)
1863 {
1864 case ISA_TYPE_B:
1865 case ISA_TYPE_UB:
1866 REPORT_INSTRUCTION(options, false,
1867 "ror/rol does not support i8 types");
1868 break;
1869 case ISA_TYPE_UQ:
1870 case ISA_TYPE_Q:
1871 // This string was changed from "ror/rol only support i64 types on PVC+" due to IP leak concers.
1872 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_PVC,
1873 "ror/rol does not support i64 types on the selected platform");
1874 break;
1875 default:
1876 break;
1877 }
1878 }
1879
1880 switch (opnd_type)
1881 {
1882 case ISA_TYPE_B:
1883 case ISA_TYPE_UB:
1884 case ISA_TYPE_W:
1885 case ISA_TYPE_D:
1886 case ISA_TYPE_UW:
1887 case ISA_TYPE_UD:
1888 case ISA_TYPE_V:
1889 case ISA_TYPE_UV:
1890 break;
1891 case ISA_TYPE_UQ:
1892 case ISA_TYPE_Q:
1893 REPORT_INSTRUCTION(options,opcode != ISA_FBL && opcode != ISA_FBH && opcode != ISA_CBIT,
1894 "fbl/fbh/cbit does not support Q/UQ type.");
1895 break;
1896 case ISA_TYPE_BOOL:
1897 {
1898 pred_logic = true;
1899 REPORT_INSTRUCTION(options, inst->pred.isNullPred(),
1900 "Predicate can not be used in logic operantion for predicate operands.");
1901 break;
1902 }
1903 case ISA_TYPE_DF:
1904 case ISA_TYPE_F:
1905 case ISA_TYPE_HF:
1906 {
1907 REPORT_INSTRUCTION(options,false,
1908 "All operands of logic instructions must be of integral type! opnd %d has float type %d",
1909 i, (int)(opnd_type));
1910 break;
1911 }
1912 default:
1913 {
1914 REPORT_INSTRUCTION(options,false,
1915 "All operands of logic instructions must be of integral type! opnd %d has unknow type %d",
1916 i, (int)(opnd_type));
1917 }
1918 }
1919 }
1920 }
1921
verifyInstructionCompare(const CISA_INST * inst)1922 void vISAVerifier::verifyInstructionCompare(
1923 const CISA_INST* inst)
1924 {
1925 /// opnd0 opnd1 opnd2 opnd3
1926 /// cmp.rel_op (exec_size) dst src1 src2
1927
1928 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1929 ASSERT_USER(ISA_CMP == opcode, "illegal opcode for compare instruction");
1930
1931 for (unsigned i = 0; i < inst->opnd_count; i++)
1932 {
1933 if (i > 0)
1934 {
1935 Common_ISA_Operand_Class operand_class = getVectorOperand(inst, i).getOperandClass();
1936 switch (i)
1937 {
1938 case 1:
1939 REPORT_INSTRUCTION(options,operand_class == OPERAND_PREDICATE || operand_class == OPERAND_GENERAL,
1940 "CISA compare instruction destination only supports a predicate operand.");
1941 break;
1942 default:
1943 REPORT_INSTRUCTION(options,operand_class != OPERAND_ADDRESS && operand_class != OPERAND_PREDICATE,
1944 "CISA compare instruction sources do not support address or predicate operands.");
1945 break;
1946 }
1947 }
1948 else
1949 {
1950 /// TODO: Verify rel_op
1951 }
1952 }
1953 }
1954
verifyInstructionAddress(const CISA_INST * inst)1955 void vISAVerifier::verifyInstructionAddress(
1956 const CISA_INST* inst)
1957 {
1958 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
1959 ASSERT_USER(ISA_ADDR_ADD == opcode, "Illegal opcode for address instruction.");
1960
1961 for (unsigned i = 0; i < inst->opnd_count; i++)
1962 {
1963 Common_ISA_Operand_Class operand_class = getVectorOperand(inst, i).getOperandClass();
1964
1965 if (0 == i)
1966 {
1967 REPORT_INSTRUCTION(options,operand_class == OPERAND_ADDRESS,
1968 "CISA address instruction destination only supports an address operand.");
1969 continue;
1970 }
1971
1972 REPORT_INSTRUCTION(options,operand_class != OPERAND_PREDICATE,
1973 "CISA ADDR_ADD instruction sources do not support predicate operands.");
1974 if (1 == i)
1975 {
1976 if (operand_class == OPERAND_GENERAL)
1977 {
1978 uint32_t numPredefinedVars = Get_CISA_PreDefined_Var_Count();
1979 uint32_t varIndex = getVectorOperand(inst, i).opnd_val.gen_opnd.index;
1980 REPORT_INSTRUCTION(options, varIndex >= numPredefinedVars, "Can not take the address of a pre-defined variable");
1981 }
1982 else if (operand_class == OPERAND_STATE)
1983 {
1984 if (getVectorOperand(inst, i).getStateOpClass() == STATE_OPND_SURFACE)
1985 {
1986 uint32_t numPredefinedSurfs = Get_CISA_PreDefined_Surf_Count();
1987 uint32_t surfIndex = getVectorOperand(inst, i).opnd_val.state_opnd.index;
1988 REPORT_INSTRUCTION(options, surfIndex >= numPredefinedSurfs, "Can not take the address of a pre-defined surface");
1989 }
1990 }
1991 }
1992
1993 if (2 == i)
1994 {
1995 VISA_Type opnd_type = getVectorOperandType(header, getVectorOperand(inst, i));
1996 REPORT_INSTRUCTION(options,opnd_type == ISA_TYPE_B || opnd_type == ISA_TYPE_UB ||
1997 opnd_type == ISA_TYPE_W || opnd_type == ISA_TYPE_UW,
1998 "Data type of the second source of ADDR_ADD should be WORD or BYTE.");
1999 }
2000
2001 }
2002 }
2003
verifyInstructionSampler(const CISA_INST * inst)2004 void vISAVerifier::verifyInstructionSampler(const CISA_INST* inst)
2005 {
2006 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2007 unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
2008 unsigned i = 0;
2009
2010 switch (opcode)
2011 {
2012 case ISA_SAMPLE_UNORM:
2013 {
2014 uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
2015 REPORT_INSTRUCTION(options,channel, "CISA SAMPLER ISA_SAMPLE_UNORM instruction only accepts non-zero channel masks.");
2016
2017 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2018 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA SAMPLER ISA_SAMPLE_UNORM instruction uses undeclared sampler.");
2019
2020 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2021 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for the SAMPLER instruction ISA_SAMPLE_UNORM.");
2022 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2023 "CISA SAMPLER instruction ISA_SAMPLE_UNORM uses undefined surface.");
2024
2025 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2026 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2027 operand_class_uoff == OPERAND_INDIRECT ||
2028 operand_class_uoff == OPERAND_IMMEDIATE,
2029 "u_offset operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2030 "be either a general, indirect, or immediate operand.");
2031
2032 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2033 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2034 operand_class_voff == OPERAND_INDIRECT ||
2035 operand_class_voff == OPERAND_IMMEDIATE,
2036 "v_offset operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2037 "be either a general, indirect, or immediate operand.");
2038
2039
2040 Common_ISA_Operand_Class operand_class_udelta = getVectorOperand(inst, i++).getOperandClass();
2041 REPORT_INSTRUCTION(options,operand_class_udelta == OPERAND_GENERAL ||
2042 operand_class_udelta == OPERAND_INDIRECT ||
2043 operand_class_udelta == OPERAND_IMMEDIATE,
2044 "u_delta operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2045 "be either a general, indirect, or immediate operand.");
2046
2047 Common_ISA_Operand_Class operand_class_vdelta = getVectorOperand(inst, i++).getOperandClass();
2048 REPORT_INSTRUCTION(options,operand_class_vdelta == OPERAND_GENERAL ||
2049 operand_class_vdelta == OPERAND_INDIRECT ||
2050 operand_class_vdelta == OPERAND_IMMEDIATE,
2051 "v_delta operand of CISA SAMPLER ISA_SAMPLE_UNORM instrution should "
2052 "be either a general, indirect, or immediate operand.");
2053
2054 /// dst: TODO
2055
2056 break;
2057 }
2058 case ISA_LOAD:
2059 case ISA_SAMPLE:
2060 {
2061 uint8_t mod = getPrimitiveOperand<uint8_t>(inst, i++);
2062
2063 if (opcode == ISA_SAMPLE)
2064 {
2065 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2066 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA SAMPLER SAMPLE/LOAD instruction uses undeclared sampler.");
2067 }
2068
2069 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2070 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for the SAMPLER instruction ISA_SAMPLE/ISA_LOAD.");
2071 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2072 "CISA SAMPLER instruction ISA_SAMPLE/ISA_LOAD uses undefined surface.");
2073
2074 uint8_t channel = mod & 0xF;
2075 REPORT_INSTRUCTION(options,channel, "CISA SAMPLER ISA_SAMPLE/ISA_LOAD instruction only accepts non-zero channel masks.");
2076
2077 uint8_t SIMD_mode = (mod >> 4) & 0x3;
2078 if ((unsigned)SIMD_mode == 0)
2079 {
2080 SIMD_mode = 8;
2081 }
2082 else if ((unsigned)SIMD_mode == 1)
2083 {
2084 SIMD_mode = 16;
2085 }
2086 else
2087 {
2088 REPORT_INSTRUCTION(options,false, "Illegal SIMD mode used in ISA_SAMPLE/ISA_LOAD inst.");
2089 }
2090
2091 /// u/r/v/dst:TODO
2092
2093 break;
2094 }
2095 case ISA_3D_SAMPLE:
2096 {
2097 uint8_t value = getPrimitiveOperand<uint8_t>(inst, i++);
2098 bool pixelNullMask = (value & (1<<5)) != 0;
2099 bool cpsEnable = (value & (1<<6)) != 0;
2100 VISASampler3DSubOpCode subOp = VISASampler3DSubOpCode(value & 0x1F);
2101
2102 if (pixelNullMask)
2103 {
2104 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_SKL,
2105 "Pixel Null Mask Enable only valid for SKL+");
2106 }
2107
2108 if (cpsEnable)
2109 {
2110 auto execSize = inst->getExecSize();
2111
2112 REPORT_INSTRUCTION(options,
2113 execSize == EXEC_SIZE_8 || execSize == EXEC_SIZE_16,
2114 "CPS LOD Compensation Enable must be disabled unless"
2115 " SIMD mode is simd8* or simd16*");
2116
2117 bool isSupportedOp = subOp == VISA_3D_SAMPLE ||
2118 subOp == VISA_3D_SAMPLE_B ||
2119 subOp == VISA_3D_SAMPLE_C ||
2120 subOp == VISA_3D_SAMPLE_B_C ||
2121 subOp == VISA_3D_LOD;
2122
2123 REPORT_INSTRUCTION(options, isSupportedOp,
2124 "CPS LOD Compensation Enable is only supported for"
2125 " sample, sample_b, sample_b_c, sample_c and LOD");
2126 }
2127 break;
2128 }
2129 case ISA_3D_LOAD:
2130 case ISA_3D_GATHER4:
2131 {
2132 uint8_t value = getPrimitiveOperand<uint8_t>(inst, i++);
2133 bool pixelNullMask = (value >> 5) != 0;
2134
2135 if (pixelNullMask)
2136 {
2137 REPORT_INSTRUCTION(options, getGenxPlatform() >= GENX_SKL,
2138 "Pixel Null Mask Enable only valid for SKL+");
2139 }
2140 break;
2141 }
2142 case ISA_3D_INFO:
2143 case ISA_3D_RT_WRITE:
2144 case ISA_3D_URB_WRITE:
2145 {
2146 // TODO: Add verification code for 3d specific opcodes
2147 break;
2148 }
2149 case ISA_AVS:
2150 {
2151 uint8_t channel = getPrimitiveOperand<uint8_t>(inst, i++);
2152 REPORT_INSTRUCTION(options,channel, "CISA SAMPLER AVS instruction only accepts non-zero channel masks.");
2153
2154 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2155 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA MINMAXFILTER instruction uses undeclared sampler.");
2156
2157 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2158 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for the SAMPLER AVS instruction.");
2159 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2160 "CISA VA instruction MINMAX uses undefined surface.");
2161
2162 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2163 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2164 operand_class_uoff == OPERAND_INDIRECT ||
2165 operand_class_uoff == OPERAND_IMMEDIATE,
2166 "u_offset operand of CISA SAMPLER AVS instrution should "
2167 "be either a general, indirect, or immediate operand.");
2168
2169 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2170 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2171 operand_class_voff == OPERAND_INDIRECT ||
2172 operand_class_voff == OPERAND_IMMEDIATE,
2173 "v_offset operand of CISA SAMPLER AVS instrution should "
2174 "be either a general, indirect, or immediate operand.");
2175
2176 Common_ISA_Operand_Class operand_class_udelta = getVectorOperand(inst, i++).getOperandClass();
2177 REPORT_INSTRUCTION(options,operand_class_udelta == OPERAND_GENERAL ||
2178 operand_class_udelta == OPERAND_INDIRECT ||
2179 operand_class_udelta == OPERAND_IMMEDIATE,
2180 "u_delta operand of CISA SAMPLER AVS instrution should "
2181 "be either a general, indirect, or immediate operand.");
2182
2183 Common_ISA_Operand_Class operand_class_vdelta = getVectorOperand(inst, i++).getOperandClass();
2184 REPORT_INSTRUCTION(options,operand_class_vdelta == OPERAND_GENERAL ||
2185 operand_class_vdelta == OPERAND_INDIRECT ||
2186 operand_class_vdelta == OPERAND_IMMEDIATE,
2187 "v_delta operand of CISA SAMPLER AVS instrution should "
2188 "be either a general, indirect, or immediate operand.");
2189
2190 Common_ISA_Operand_Class operand_class_u2d = getVectorOperand(inst, i++).getOperandClass();
2191 REPORT_INSTRUCTION(options,operand_class_u2d == OPERAND_GENERAL ||
2192 operand_class_u2d == OPERAND_INDIRECT ||
2193 operand_class_u2d == OPERAND_IMMEDIATE,
2194 "u2d operand of CISA SAMPLER AVS instrution should "
2195 "be either a general, indirect, or immediate operand.");
2196
2197 Common_ISA_Operand_Class operand_class_groupid = getVectorOperand(inst, i++).getOperandClass();
2198 REPORT_INSTRUCTION(options,operand_class_groupid == OPERAND_GENERAL ||
2199 operand_class_groupid == OPERAND_INDIRECT ||
2200 operand_class_groupid == OPERAND_IMMEDIATE,
2201 "groupid operand of CISA SAMPLER AVS instrution should "
2202 "be either a general, indirect, or immediate operand.");
2203
2204 Common_ISA_Operand_Class operand_class_verticalBlockNumber = getVectorOperand(inst, i++).getOperandClass();
2205 REPORT_INSTRUCTION(options,operand_class_verticalBlockNumber == OPERAND_GENERAL ||
2206 operand_class_verticalBlockNumber == OPERAND_INDIRECT ||
2207 operand_class_verticalBlockNumber == OPERAND_IMMEDIATE,
2208 "verticalBlockNumber operand of CISA SAMPLER AVS instrution should "
2209 "be either a general, indirect, or immediate operand.");
2210
2211 uint8_t cntrl = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2212
2213 switch (cntrl)
2214 {
2215 case 0:
2216 case 1:
2217 case 2:
2218 case 3: break;
2219 default: REPORT_INSTRUCTION(options,false, "cntrl for CISA SAMPLER AVS intruction should be a "
2220 "value 0-3 (8/16bit full/chrominance down sample).");
2221 }
2222
2223 Common_ISA_Operand_Class operand_class_v2d = getVectorOperand(inst, i++).getOperandClass();
2224 REPORT_INSTRUCTION(options,operand_class_v2d == OPERAND_GENERAL ||
2225 operand_class_v2d == OPERAND_INDIRECT ||
2226 operand_class_v2d == OPERAND_IMMEDIATE,
2227 "v2d operand of CISA SAMPLER AVS instrution should "
2228 "be either a general, indirect, or immediate operand.");
2229
2230 uint8_t execMode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2231
2232 switch (execMode)
2233 {
2234 case 0:
2235 case 1:
2236 case 2:
2237 case 3: break;
2238 default: REPORT_INSTRUCTION(options,false, "execMode for CISA SAMPLER AVS intruction should "
2239 "be a value 0-3 (16x4, 8x4, 16x8, or 4x4).");
2240 }
2241
2242 Common_ISA_Operand_Class operand_class_iefbypass = getVectorOperand(inst, i++).getOperandClass();
2243 REPORT_INSTRUCTION(options,operand_class_iefbypass == OPERAND_GENERAL ||
2244 operand_class_iefbypass == OPERAND_INDIRECT ||
2245 operand_class_iefbypass == OPERAND_IMMEDIATE,
2246 "iefbypass operand of CISA SAMPLER AVS instruction should "
2247 "be either a general, indirect, or immediate operand.");
2248
2249 /// dst: TODO
2250
2251 break;
2252 }
2253 case ISA_VA:
2254 {
2255 ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
2256 switch (subOpcode)
2257 {
2258 case MINMAX_FOPCODE:
2259 {
2260 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2261 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2262 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2263 "CISA VA instruction MINMAX uses undefined surface.");
2264
2265 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2266 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2267 operand_class_uoff == OPERAND_INDIRECT ||
2268 operand_class_uoff == OPERAND_IMMEDIATE,
2269 "u_offset operand of CISA MINMAX instrution should "
2270 "be either a general, indirect, or immediate operand.");
2271
2272 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2273 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2274 operand_class_voff == OPERAND_INDIRECT ||
2275 operand_class_voff == OPERAND_IMMEDIATE,
2276 "v_offset operand of CISA MINMAX instrution should "
2277 "be either a general, indirect, or immediate operand.");
2278
2279 /// mmf mode
2280 const vector_opnd& mmf = getVectorOperand(inst, i++);
2281 if (mmf.getOperandClass() == OPERAND_IMMEDIATE)
2282 {
2283 unsigned val = mmf.opnd_val.const_opnd._val.ival;
2284 ASSERT_USER(val <= VA_MIN_ENABLE, "MINMAX MMF Mode operand out of range.");
2285 }
2286
2287 /// dst: TODO
2288
2289 break;
2290 }
2291 case MINMAXFILTER_FOPCODE:
2292 {
2293 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2294 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA MINMAXFILTER instruction uses undeclared sampler.");
2295
2296 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2297 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2298 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2299 "CISA VA instruction MINMAXFILTER uses undefined surface.");
2300
2301 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2302 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2303 operand_class_uoff == OPERAND_INDIRECT ||
2304 operand_class_uoff == OPERAND_IMMEDIATE,
2305 "u_offset operand of CISA MINMAXFILTER instrution should "
2306 "be either a general, indirect, or immediate operand.");
2307
2308 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2309 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2310 operand_class_voff == OPERAND_INDIRECT ||
2311 operand_class_voff == OPERAND_IMMEDIATE,
2312 "v_offset operand of CISA MINMAXFILTER instrution should "
2313 "be either a general, indirect, or immediate operand.");
2314
2315 getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t cntrl, &0xf
2316 getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t execMode, &0xf
2317
2318 /// mmf mode
2319 const vector_opnd& mmf = getVectorOperand(inst, i++);
2320 if (mmf.getOperandClass() == OPERAND_IMMEDIATE)
2321 {
2322 unsigned val = mmf.opnd_val.const_opnd._val.ival;
2323 ASSERT_USER(val <= VA_MIN_ENABLE, "MINMAXFILTER MMF Mode operand out of range.");
2324 }
2325
2326 /// dst
2327
2328 break;
2329 }
2330 case BoolCentroid_FOPCODE:
2331 case Centroid_FOPCODE:
2332 {
2333 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2334 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2335 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs< header->getSurfaceCount(),
2336 "CISA VA VA CENTROID/BOOLCENTROID instruction MINMAX uses undefined surface.");
2337
2338 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2339 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2340 operand_class_uoff == OPERAND_INDIRECT ||
2341 operand_class_uoff == OPERAND_IMMEDIATE,
2342 "u_offset operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2343 "be either a general, indirect, or immediate operand.");
2344
2345 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2346 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2347 operand_class_voff == OPERAND_INDIRECT ||
2348 operand_class_voff == OPERAND_IMMEDIATE,
2349 "v_offset operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2350 "be either a general, indirect, or immediate operand.");
2351
2352 Common_ISA_Operand_Class operand_class_vsize = getVectorOperand(inst, i++).getOperandClass();
2353 REPORT_INSTRUCTION(options,operand_class_vsize == OPERAND_GENERAL ||
2354 operand_class_vsize == OPERAND_INDIRECT ||
2355 operand_class_vsize == OPERAND_IMMEDIATE,
2356 "v_size operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2357 "be either a general, indirect, or immediate operand.");
2358
2359 /// h size
2360 if (subOpcode == BoolCentroid_FOPCODE)
2361 {
2362 Common_ISA_Operand_Class operand_class_hsize = getVectorOperand(inst, i++).getOperandClass();
2363 REPORT_INSTRUCTION(options,operand_class_hsize == OPERAND_GENERAL ||
2364 operand_class_hsize == OPERAND_INDIRECT ||
2365 operand_class_hsize == OPERAND_IMMEDIATE,
2366 "h_size operand of CISA VA CENTROID/BOOLCENTROID instrution should "
2367 "be either a general, indirect, or immediate operand.");
2368 }
2369
2370 /// dst: TODO
2371
2372 break;
2373 }
2374 case Convolve_FOPCODE:
2375 case Dilate_FOPCODE:
2376 case ERODE_FOPCODE:
2377 {
2378 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2379 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA CONVOLVE/ERODE/DILATE instruction uses undeclared sampler.");
2380
2381 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2382 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA instructions.");
2383 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2384 "CISA VA CONVOLVE/ERODE/DILATE instruction MINMAX uses undefined surface.");
2385
2386 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2387 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2388 operand_class_uoff == OPERAND_INDIRECT ||
2389 operand_class_uoff == OPERAND_IMMEDIATE,
2390 "u_offset operand of CISA CONVOLVE/ERODE/DILATE instrution should "
2391 "be either a general, indirect, or immediate operand.");
2392
2393 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2394 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2395 operand_class_voff == OPERAND_INDIRECT ||
2396 operand_class_voff == OPERAND_IMMEDIATE,
2397 "v_offset operand of CISA CONVOLVE/ERODE/DILATE instrution should "
2398 "be either a general, indirect, or immediate operand.");
2399
2400 /// uint8_t execMode = ((getPrimitiveOperand<uint8_t>(inst, i)) & 0x3);
2401 /// uint8_t regionSize = ((getPrimitiveOperand<uint8_t>(inst, i)) & 0xC) >> 0x2;
2402 /// dst: TODO
2403
2404 break;
2405 }
2406 default:
2407 REPORT_INSTRUCTION(options,false, "Invalid VA sub-opcode: %d.", subOpcode);
2408 }
2409
2410 break;
2411 }
2412 case ISA_VA_SKL_PLUS:
2413 {
2414 ISA_VA_Sub_Opcode subOpcode = (ISA_VA_Sub_Opcode)getPrimitiveOperand<uint8_t>(inst, i++);
2415 switch (subOpcode)
2416 {
2417 case VA_OP_CODE_LBP_CORRELATION:
2418 {
2419 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2420 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2421 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2422 "CISA VA++ instruction LBP Correlation uses undefined surface.");
2423
2424 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2425 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2426 operand_class_uoff == OPERAND_INDIRECT ||
2427 operand_class_uoff == OPERAND_IMMEDIATE,
2428 "u_offset operand of CISA LBP Correlation instrution "
2429 "should be either a general, indirect, or immediate operand.");
2430
2431 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2432 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2433 operand_class_voff == OPERAND_INDIRECT ||
2434 operand_class_voff == OPERAND_IMMEDIATE,
2435 "v_offset operand of CISA LBP Correlation instrution "
2436 "should be either a general, indirect, or immediate operand.");
2437
2438 Common_ISA_Operand_Class operand_class_disparity = getVectorOperand(inst, i++).getOperandClass();
2439 REPORT_INSTRUCTION(options,operand_class_disparity == OPERAND_GENERAL ||
2440 operand_class_disparity == OPERAND_INDIRECT ||
2441 operand_class_disparity == OPERAND_IMMEDIATE,
2442 "Disparity operand of CISA LBP Correlation instrution "
2443 "should be either a general, indirect, or immediate operand.");
2444
2445 /// dst
2446 /// TODO: Check dst for type W for for GRF alignment
2447
2448 break;
2449 }
2450 case VA_OP_CODE_1PIXEL_CONVOLVE:
2451 case VA_OP_CODE_1D_CONVOLVE_VERTICAL:
2452 case VA_OP_CODE_1D_CONVOLVE_HORIZONTAL:
2453 {
2454 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2455 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA++ instruction uses undeclared sampler.");
2456
2457 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2458 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2459 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2460 "CISA VA++ instruction uses undefined surface.");
2461
2462 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2463 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2464 operand_class_uoff == OPERAND_INDIRECT ||
2465 operand_class_uoff == OPERAND_IMMEDIATE,
2466 "u_offset operand of CISA VA++ instrution "
2467 "should be either a general, indirect, or immediate operand.");
2468
2469 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2470 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2471 operand_class_voff == OPERAND_INDIRECT ||
2472 operand_class_voff == OPERAND_IMMEDIATE,
2473 "v_offset operand of CISA VA++ instrution "
2474 "should be either a general, indirect, or immediate operand.");
2475
2476 uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2477
2478 switch (mode & 0x3)
2479 {
2480 case 0: break;
2481 case 2: break;
2482 case 3: break;
2483 default: REPORT_INSTRUCTION(options,false, "Invalid mode field for CISA VA++ instruction. "
2484 "Only 4x16, 1x16, and 1x1 (in the case of "
2485 "1 pixel convolve) are supported.");
2486 }
2487
2488 break;
2489 }
2490 case VA_OP_CODE_LBP_CREATION:
2491 {
2492 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2493 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2494 REPORT_INSTRUCTION(options,surface-numPreDefinedSurfs < header->getSurfaceCount(),
2495 "CISA LBP Creation VA++ instruction uses undefined surface.");
2496
2497 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2498 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2499 operand_class_uoff == OPERAND_INDIRECT ||
2500 operand_class_uoff == OPERAND_IMMEDIATE,
2501 "u_offset operand of CISA LBP Creation VA++ instrution "
2502 "should be either a general, indirect, or immediate operand.");
2503
2504 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2505 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2506 operand_class_voff == OPERAND_INDIRECT ||
2507 operand_class_voff == OPERAND_IMMEDIATE,
2508 "v_offset operand of CISA LBP Creation VA++ instrution "
2509 "should be either a general, indirect, or immediate operand.");
2510
2511 uint8_t mode = ((getPrimitiveOperand<uint8_t>(inst, i++)) & 0xF);
2512
2513 switch (mode & 0x3)
2514 {
2515 case 0: break;
2516 case 1: break;
2517 case 2: break;
2518 default: REPORT_INSTRUCTION(options,false, "Invalid mode field for CISA LBP Creation VA++ instruction. "
2519 "Only 5x5, 3x3, or both modes are supported.");
2520 }
2521
2522 /// dst
2523 /// TODO: Checks for modes/types/decls
2524
2525 break;
2526 }
2527 case VA_OP_CODE_FLOOD_FILL:
2528 {
2529 getPrimitiveOperand<uint8_t>(inst, i++); // uint8_t is8Connect
2530
2531 i++; /// h-mask
2532
2533 Common_ISA_Operand_Class operand_class_vmask_left = getVectorOperand(inst, i++).getOperandClass();
2534 REPORT_INSTRUCTION(options,operand_class_vmask_left == OPERAND_GENERAL ||
2535 operand_class_vmask_left == OPERAND_INDIRECT ||
2536 operand_class_vmask_left == OPERAND_IMMEDIATE,
2537 "Pixel direction v-mask left of CISA VA++ FloodFill instruction only "
2538 "supports general, indirect, and immediate operands.");
2539
2540 Common_ISA_Operand_Class operand_class_vmask_right = getVectorOperand(inst, i++).getOperandClass();
2541 REPORT_INSTRUCTION(options,operand_class_vmask_right == OPERAND_GENERAL ||
2542 operand_class_vmask_right == OPERAND_INDIRECT ||
2543 operand_class_vmask_right == OPERAND_IMMEDIATE,
2544 "Pixel direction v-mask right of CISA VA++ FloodFill instruction only "
2545 "supports general, indirect, and immediate operands.");
2546
2547 Common_ISA_Operand_Class operand_class_loopcount = getVectorOperand(inst, i++).getOperandClass();
2548 REPORT_INSTRUCTION(options,operand_class_loopcount == OPERAND_GENERAL ||
2549 operand_class_loopcount == OPERAND_INDIRECT ||
2550 operand_class_loopcount == OPERAND_IMMEDIATE,
2551 "loop_count of Common ISA sample instrution is invalid type.");
2552
2553 break;
2554 }
2555 case VA_OP_CODE_CORRELATION_SEARCH:
2556 {
2557 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2558 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2559 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2560 "CISA VA++ instruction uses undefined surface.");
2561
2562 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2563 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2564 operand_class_uoff == OPERAND_INDIRECT ||
2565 operand_class_uoff == OPERAND_IMMEDIATE,
2566 "u_offset of Common ISA Meida LD/ST instrution "
2567 "should not be address or predicate operand.");
2568
2569 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2570 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2571 operand_class_voff == OPERAND_INDIRECT ||
2572 operand_class_voff == OPERAND_IMMEDIATE,
2573 "v_offset of Common ISA Meida LD/ST instrution "
2574 "should not be address or predicate operand.");
2575
2576 Common_ISA_Operand_Class operand_class_verticalOrigin = getVectorOperand(inst, i++).getOperandClass();
2577 REPORT_INSTRUCTION(options,operand_class_verticalOrigin == OPERAND_GENERAL ||
2578 operand_class_verticalOrigin == OPERAND_INDIRECT ||
2579 operand_class_verticalOrigin == OPERAND_IMMEDIATE,
2580 "CISA VA++ instruction Correlation search operand verticalOrigin "
2581 "can only be of operand class general, indirect, or immediate.");
2582
2583 Common_ISA_Operand_Class operand_class_horizontalOrigin = getVectorOperand(inst, i++).getOperandClass();
2584 REPORT_INSTRUCTION(options,operand_class_horizontalOrigin == OPERAND_GENERAL ||
2585 operand_class_horizontalOrigin == OPERAND_INDIRECT ||
2586 operand_class_horizontalOrigin == OPERAND_IMMEDIATE,
2587 "CISA VA++ instruction Correlation search operand horizontalOrigin "
2588 "can only be of operand class general, indirect, or immediate.");
2589
2590 Common_ISA_Operand_Class operand_class_xDirectionSize = getVectorOperand(inst, i++).getOperandClass();
2591 REPORT_INSTRUCTION(options,operand_class_xDirectionSize == OPERAND_GENERAL ||
2592 operand_class_xDirectionSize == OPERAND_INDIRECT ||
2593 operand_class_xDirectionSize == OPERAND_IMMEDIATE,
2594 "CISA VA++ instruction Correlation search operand xDirectionSize "
2595 "can only be of operand class general, indirect, or immediate.");
2596
2597 Common_ISA_Operand_Class operand_class_yDirectionSize = getVectorOperand(inst, i++).getOperandClass();
2598 REPORT_INSTRUCTION(options,operand_class_yDirectionSize == OPERAND_GENERAL ||
2599 operand_class_yDirectionSize == OPERAND_INDIRECT ||
2600 operand_class_yDirectionSize == OPERAND_IMMEDIATE,
2601 "CISA VA++ instruction Correlation search operand yDirectionSize "
2602 "can only be of operand class general, indirect, or immediate.");
2603
2604 Common_ISA_Operand_Class operand_class_xDirectionSearchSize = getVectorOperand(inst, i++).getOperandClass();
2605 REPORT_INSTRUCTION(options,operand_class_xDirectionSearchSize == OPERAND_GENERAL ||
2606 operand_class_xDirectionSearchSize == OPERAND_INDIRECT ||
2607 operand_class_xDirectionSearchSize == OPERAND_IMMEDIATE,
2608 "CISA VA++ instruction Correlation search operand xDirectionSearchSize "
2609 "can only be of operand class general, indirect, or immediate.");
2610
2611 Common_ISA_Operand_Class operand_class_yDirectionSearchSize = getVectorOperand(inst, i++).getOperandClass();
2612 REPORT_INSTRUCTION(options,operand_class_yDirectionSearchSize == OPERAND_GENERAL ||
2613 operand_class_yDirectionSearchSize == OPERAND_INDIRECT ||
2614 operand_class_yDirectionSearchSize == OPERAND_IMMEDIATE,
2615 "CISA VA++ instruction Correlation search operand yDirectionSearchSize "
2616 "can only be of operand class general, indirect, or immediate.");
2617
2618 /// dst
2619 /// TODO: Check dst type that it is only Type_D
2620
2621 break;
2622 }
2623 case ISA_HDC_CONV:
2624 case ISA_HDC_ERODE:
2625 case ISA_HDC_DILATE:
2626 case ISA_HDC_LBPCORRELATION:
2627 case ISA_HDC_LBPCREATION:
2628 case ISA_HDC_MMF:
2629 case ISA_HDC_1PIXELCONV:
2630 case ISA_HDC_1DCONV_H:
2631 case ISA_HDC_1DCONV_V:
2632 {
2633 if (subOpcode != ISA_HDC_LBPCORRELATION &&
2634 subOpcode != ISA_HDC_LBPCREATION)
2635 {
2636 /// sampler
2637 uint8_t sampler = getPrimitiveOperand<uint8_t>(inst, i++);
2638 REPORT_INSTRUCTION(options,sampler < header->getSamplerCount(), "CISA VA++ instruction uses undeclared sampler.");
2639 }
2640
2641 //input surface
2642 uint8_t surface = getPrimitiveOperand<uint8_t>(inst, i++);
2643 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2644 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2645 "CISA VA++ instruction uses undefined surface.");
2646
2647 //u_offset
2648 Common_ISA_Operand_Class operand_class_uoff = getVectorOperand(inst, i++).getOperandClass();
2649 REPORT_INSTRUCTION(options,operand_class_uoff == OPERAND_GENERAL ||
2650 operand_class_uoff == OPERAND_INDIRECT ||
2651 operand_class_uoff == OPERAND_IMMEDIATE,
2652 "u_offset of Common ISA HDC INSTRUCTION "
2653 "should not be address or predicate operand.");
2654
2655 //v_offset
2656 Common_ISA_Operand_Class operand_class_voff = getVectorOperand(inst, i++).getOperandClass();
2657 REPORT_INSTRUCTION(options,operand_class_voff == OPERAND_GENERAL ||
2658 operand_class_voff == OPERAND_INDIRECT ||
2659 operand_class_voff == OPERAND_IMMEDIATE,
2660 "v_offset of Common ISA HDC instruction "
2661 "should not be address or predicate operand.");
2662
2663 if (subOpcode == ISA_HDC_CONV ||
2664 subOpcode == ISA_HDC_MMF ||
2665 subOpcode == ISA_HDC_1PIXELCONV ||
2666 subOpcode == ISA_HDC_1DCONV_H ||
2667 subOpcode == ISA_HDC_1DCONV_V)
2668 {
2669 //pixel size
2670 //FOr 2D Convovle bit 4 is for indicating SKL or BDW mode
2671 uint8_t pixel_size = getPrimitiveOperand<uint8_t>(inst, i++)&0XF;
2672 REPORT_INSTRUCTION(options,pixel_size < 2, "CISA VA++ instruction uses invalid output pixel size.");
2673 }
2674
2675 if (subOpcode == ISA_HDC_MMF ||
2676 subOpcode == ISA_HDC_LBPCREATION)
2677 {
2678 //mode
2679 uint8_t mode = getPrimitiveOperand<uint8_t>(inst, i++);
2680 REPORT_INSTRUCTION(options,mode <= 2, "CISA VA++ instruction uses invalid mode.");
2681 }
2682
2683 if (subOpcode == ISA_HDC_LBPCORRELATION)
2684 {
2685 /// disparity
2686 Common_ISA_Operand_Class operand_class_disparity = getVectorOperand(inst, i++).getOperandClass();
2687 REPORT_INSTRUCTION(options,operand_class_disparity == OPERAND_GENERAL ||
2688 operand_class_disparity == OPERAND_INDIRECT ||
2689 operand_class_disparity == OPERAND_IMMEDIATE,
2690 "disparity of Common ISA HDC LBPCORRELATION "
2691 "should not be address or predicate operand.");
2692 }
2693
2694 if (subOpcode == ISA_HDC_1PIXELCONV)
2695 {
2696 /// offsets raw operand
2697 i++;
2698 }
2699
2700 /// dst surface
2701 uint8_t dstsurface = getPrimitiveOperand<uint8_t>(inst, i++);
2702 REPORT_INSTRUCTION(options,0 != dstsurface, "Surface T0 (the SLM surface) is not allowed for VA++ instructions.");
2703 REPORT_INSTRUCTION(options,dstsurface < numPreDefinedSurfs + header->getSurfaceCount(),
2704 "CISA VA++ instruction uses undefined destination surface.");
2705
2706 /// x offset
2707 Common_ISA_Operand_Class operand_class_xoff = getVectorOperand(inst, i++).getOperandClass();
2708 REPORT_INSTRUCTION(options,operand_class_xoff == OPERAND_GENERAL ||
2709 operand_class_xoff == OPERAND_INDIRECT ||
2710 operand_class_xoff == OPERAND_IMMEDIATE,
2711 "x_offset of Common ISA HDC instruction "
2712 "should not be address or predicate operand.");
2713
2714 /// y offset
2715 Common_ISA_Operand_Class operand_class_yoff = getVectorOperand(inst, i++).getOperandClass();
2716 REPORT_INSTRUCTION(options,operand_class_yoff == OPERAND_GENERAL ||
2717 operand_class_yoff == OPERAND_INDIRECT ||
2718 operand_class_yoff == OPERAND_IMMEDIATE,
2719 "y_offset of Common ISA HDC instruction "
2720 "should not be address or predicate operand.");
2721 break;
2722 }
2723 default:
2724 REPORT_INSTRUCTION(options,false, "Invalid VA++ sub-opcode: %d.", subOpcode);
2725 }
2726
2727 break;
2728 }
2729 default: REPORT_INSTRUCTION(options,false, "Illegal Sampler Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
2730 }
2731 }
2732
verifyInstructionSIMDFlow(const CISA_INST * inst)2733 void vISAVerifier::verifyInstructionSIMDFlow(
2734 const CISA_INST* inst)
2735 {
2736 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2737 switch (opcode)
2738 {
2739 case ISA_GOTO:
2740 {
2741 auto labelId = getPrimitiveOperand<uint16_t>(inst, 0);
2742 if (labelId >= header->getLabelCount())
2743 {
2744 REPORT_INSTRUCTION(options, false, "bad label id %d", labelId);
2745 }
2746 else
2747 {
2748 auto iter = labelDefs.find(labelId);
2749 if (iter == labelDefs.end())
2750 {
2751 labelDefs[labelId] = false;
2752 }
2753 // nothing needs to be done if the label is already in the map
2754 }
2755 break;
2756 }
2757 default: REPORT_INSTRUCTION(options,false, "Illegal SIMD CF Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
2758 }
2759 }
2760
isUDType(VISA_Type T)2761 static bool isUDType(VISA_Type T)
2762 {
2763 return ISA_TYPE_UD == T;
2764 }
2765
isDType(VISA_Type T)2766 static bool isDType(VISA_Type T)
2767 {
2768 return ISA_TYPE_D == T;
2769 }
2770
isDorUDTYpe(VISA_Type T)2771 static bool isDorUDTYpe(VISA_Type T)
2772 {
2773 return isUDType(T) || isDType(T);
2774 }
2775
isFType(VISA_Type T)2776 static bool isFType(VISA_Type T)
2777 {
2778 return ISA_TYPE_F == T;
2779 }
2780
verifyInstructionDataport(const CISA_INST * inst)2781 void vISAVerifier::verifyInstructionDataport(
2782 const CISA_INST* inst)
2783 {
2784 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
2785 unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
2786
2787 unsigned i = 0;
2788
2789 uint8_t surface = 0;
2790 uint8_t modifier = 0;
2791
2792 switch (opcode)
2793 {
2794 case ISA_MEDIA_ST:
2795 case ISA_MEDIA_LD:
2796 {
2797 uint8_t plane = 0;
2798 uint8_t block_width = 0;
2799 uint8_t block_height = 0;
2800
2801 if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2802 {
2803 modifier = getPrimitiveOperand<uint8_t>(inst, i++); // for skipping the modifier
2804
2805 if (ISA_MEDIA_LD == opcode)
2806 REPORT_INSTRUCTION(options,modifier < MEDIA_LD_Mod_NUM,
2807 "MEDIA_LD modifier must be 0-5 not %d", modifier);
2808
2809 if (ISA_MEDIA_ST == opcode)
2810 REPORT_INSTRUCTION(options,modifier < MEDIA_ST_Mod_NUM,
2811 "MEDIA_ST modifier must be 0-3 not %d", modifier);
2812 }
2813
2814 surface = getPrimitiveOperand<uint8_t>(inst, i++);
2815 REPORT_INSTRUCTION(options,0 != surface, "Surface T0 (the SLM surface) is not allowed for MEDIA_LD/MEDIA_ST");
2816 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2817 "CISA dataport instruction uses an undeclared surface.");
2818
2819 if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2820 {
2821 plane = getPrimitiveOperand<uint8_t>(inst, i++);
2822 REPORT_INSTRUCTION(options,plane <= 3, "MEDIA_LD/MEDIA_ST plane must be in the range [0, 3]: %d", plane);
2823 }
2824
2825 block_width = getPrimitiveOperand<uint8_t>(inst, i++);
2826 block_height = getPrimitiveOperand<uint8_t>(inst, i++);
2827
2828 if (ISA_MEDIA_LD == opcode || ISA_MEDIA_ST == opcode)
2829 {
2830 REPORT_INSTRUCTION(options,1 <= block_width && block_width <= COMMON_ISA_MAX_MEDIA_BLOCK_WIDTH_BDW_PLUS,
2831 "MEDIA_LD/MEDIA_ST block width must be in the range [1, 32]: %d",
2832 block_width);
2833
2834 REPORT_INSTRUCTION(options,1 <= block_height && block_height <= COMMON_ISA_MAX_MEDIA_BLOCK_HEIGHT,
2835 "MEDIA_LD/MEDIA_ST block height must be in the range [1, 64]: %d",
2836 block_height);
2837 }
2838
2839 if (ISA_MEDIA_LD == opcode)
2840 {
2841 REPORT_INSTRUCTION(options,((1 <= block_width && block_width <= 4 && block_height <= 64) ||
2842 (5 <= block_width && block_width <= 8 && block_height <= 32) ||
2843 (9 <= block_width && block_width <= 16 && block_height <= 16) ||
2844 (17 <= block_width && block_width <= 32 && block_height <= 8) ||
2845 (33 <= block_width && block_width <= 64 && block_height <= 4)) &&
2846 (block_width * block_height <= 256 ),
2847 "MEDIA_LD only supports objects that fit into a single dataport "
2848 "transaction where block width <= 64 bytes and size <= 256 bytes. "
2849 "Block width: %d. Block height: %d", block_width, block_height);
2850 }
2851 else if (ISA_MEDIA_ST == opcode)
2852 {
2853 REPORT_INSTRUCTION(options,((1 <= block_width && block_width <= 4 && block_height <= 64) ||
2854 (5 <= block_width && block_width <= 8 && block_height <= 32) ||
2855 (9 <= block_width && block_width <= 16 && block_height <= 16) ||
2856 (17 <= block_width && block_width <= 32 && block_height <= 8) ||
2857 (33 <= block_width && block_width <= 64 && block_height <= 4)) &&
2858 (block_width * block_height <= 256 ),
2859 "MEDIA_ST only supports objects that fit into a single dataport "
2860 "transaction where block width <= 64 bytes and size <= 256 bytes. "
2861 "Block width: %d. Block height: %d", block_width, block_height);
2862 }
2863
2864 Common_ISA_Operand_Class operand_class_xoff = getVectorOperand(inst, i++).getOperandClass();
2865 REPORT_INSTRUCTION(options,operand_class_xoff != OPERAND_ADDRESS && operand_class_xoff != OPERAND_PREDICATE,
2866 "x_offset of Common ISA Meida LD/ST instrution should not be address or predicate operand.");
2867
2868 Common_ISA_Operand_Class operand_class_yoff = getVectorOperand(inst, i++).getOperandClass();
2869 REPORT_INSTRUCTION(options,operand_class_yoff != OPERAND_ADDRESS && operand_class_yoff != OPERAND_PREDICATE,
2870 "y_offset of Common ISA Meida LD/ST instrution should not be address or predicate operand.");
2871
2872 break;
2873 }
2874 case ISA_OWORD_ST:
2875 case ISA_OWORD_LD:
2876 case ISA_OWORD_LD_UNALIGNED:
2877 {
2878 uint8_t size = getPrimitiveOperand<uint8_t>(inst, i++);
2879 size = size & 0x7;
2880
2881 REPORT_INSTRUCTION(options,size < OWORD_NUM_ILLEGAL,
2882 "OWORD_LD*/OWORD_ST size must be in the range [0, 3] "
2883 "(ie, OWord block size must be 1/2/4/8. OWord block size: %d", size);
2884
2885 if (ISA_OWORD_ST != opcode)
2886 {
2887 modifier = getPrimitiveOperand<uint8_t>(inst, i++);
2888 }
2889
2890 surface = getPrimitiveOperand<uint8_t>(inst, i++);
2891 if (getGenxPlatform() < GENX_ICLLP)
2892 {
2893 REPORT_INSTRUCTION(options, 0 != surface, "Surface T0 (the SLM surface) is not allowed for OWORD_LD*/OWORD_ST");
2894 }
2895 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2896 "CISA dataport instruction uses an undeclared surface.");
2897
2898 Common_ISA_Operand_Class operand_class = getVectorOperand(inst, i++).getOperandClass();
2899 REPORT_INSTRUCTION(options,operand_class != OPERAND_ADDRESS && operand_class != OPERAND_PREDICATE,
2900 "Offset of Common ISA OWORD LD/ST instrutions should not be address or predicate operands.");
2901
2902 break;
2903 }
2904 case ISA_GATHER:
2905 case ISA_SCATTER:
2906 {
2907 uint8_t elt_size = 0;
2908 uint8_t num_elts = 0;
2909 if (ISA_SCATTER == opcode || ISA_GATHER == opcode)
2910 {
2911 elt_size = getPrimitiveOperand<uint8_t>(inst, i++);
2912 elt_size = elt_size & 0x3;
2913 switch ((GATHER_SCATTER_ELEMENT_SIZE)elt_size)
2914 {
2915 case GATHER_SCATTER_BYTE:
2916 elt_size = 1;
2917 break;
2918 case GATHER_SCATTER_WORD:
2919 elt_size = 2;
2920 break;
2921 case GATHER_SCATTER_DWORD:
2922 elt_size = 4;
2923 break;
2924 default:
2925 REPORT_INSTRUCTION(options,false, "Incorrect element size for Gather/Scatter CISA inst.");
2926 break;
2927 }
2928 }
2929
2930 if (ISA_GATHER == opcode)
2931 getPrimitiveOperand<uint8_t>(inst, i++);
2932
2933 num_elts = getPrimitiveOperand<uint8_t>(inst, i++);
2934 num_elts = num_elts & 0x3;
2935 if ((unsigned)num_elts == 0) num_elts = 8;
2936 else if ((unsigned)num_elts == 1) num_elts = 16;
2937 else if ((unsigned)num_elts == 2) num_elts = 1;
2938
2939 surface = getPrimitiveOperand<uint8_t>(inst, i++);
2940 //SLM uses surface0 as seen in nbody_SLM: gather
2941 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2942 "CISA dataport instruction uses an undeclared surface.");
2943
2944 Common_ISA_Operand_Class operand_class_goff = getVectorOperand(inst, i++).getOperandClass();
2945 REPORT_INSTRUCTION(options,operand_class_goff != OPERAND_ADDRESS && operand_class_goff != OPERAND_PREDICATE,
2946 "global_offset of Common ISA gather/scatter instrution should not be address or predicate operand.");
2947
2948 // check that dst/src have dword type
2949 getRawOperand(inst, i++); // const raw_opnd& elementOffset
2950 const raw_opnd& srcDst = getRawOperand(inst, i++);
2951 verifyRawOperandType(inst, srcDst, isDWordType);
2952 break;
2953 }
2954 case ISA_GATHER4_TYPED:
2955 case ISA_SCATTER4_TYPED:
2956 {
2957 if (getVersionAsInt(isaHeader.major_version, isaHeader.minor_version) >=
2958 getVersionAsInt(3, 2))
2959 {
2960 uint8_t ch_mask = 0;
2961 ch_mask = getPrimitiveOperand<uint8_t>(inst, i++);
2962 ch_mask = ch_mask & 0xF;
2963 REPORT_INSTRUCTION(options,ch_mask != 0x0, "At least one channel must be enabled for TYPED GATEHR4/SCATTER4");
2964
2965 surface = getPrimitiveOperand<uint8_t>(inst, i++);
2966 REPORT_INSTRUCTION(options, (0 != surface && 5 != surface), "Surface T0/T5 (the SLM surface) is not allowed for TYPED SCATTTER4/GATHER4");
2967 REPORT_INSTRUCTION(options,surface < numPreDefinedSurfs + header->getSurfaceCount(),
2968 "CISA dataport TYPED SCATTTER4/GATHER4 instruction uses an undeclared surface.");
2969 }
2970 break;
2971 }
2972 case ISA_GATHER4_SCALED:
2973 case ISA_SCATTER4_SCALED:
2974 {
2975 break;
2976 }
2977 case ISA_GATHER_SCALED:
2978 case ISA_SCATTER_SCALED:
2979 {
2980 break;
2981 }
2982 case ISA_DWORD_ATOMIC:
2983 {
2984 unsigned subOpc = getPrimitiveOperand<uint8_t>(inst, i++);
2985 auto subOp = static_cast<VISAAtomicOps>(subOpc & 0x1F);
2986 switch (subOp) {
2987 default:
2988 REPORT_INSTRUCTION(options, false, "Invalid DWORD ATOMIC sub op.");
2989 case ATOMIC_ADD:
2990 case ATOMIC_SUB:
2991 case ATOMIC_INC:
2992 case ATOMIC_DEC:
2993 case ATOMIC_MIN:
2994 case ATOMIC_MAX:
2995 case ATOMIC_XCHG:
2996 case ATOMIC_CMPXCHG:
2997 case ATOMIC_AND:
2998 case ATOMIC_OR:
2999 case ATOMIC_XOR:
3000 case ATOMIC_IMIN:
3001 case ATOMIC_IMAX:
3002 case ATOMIC_PREDEC:
3003 case ATOMIC_FMAX:
3004 case ATOMIC_FMIN:
3005 case ATOMIC_FCMPWR:
3006 case ATOMIC_FADD:
3007 case ATOMIC_FSUB:
3008 break;
3009 }
3010 surface = getPrimitiveOperand<uint8_t>(inst, i++);
3011 REPORT_INSTRUCTION(options, surface < numPreDefinedSurfs + header->getSurfaceCount(),
3012 "CISA dataport instruction uses an undeclared surface.");
3013
3014 const raw_opnd& offsets = getRawOperand(inst, i++);
3015 verifyRawOperandType(inst, offsets, isUDType);
3016
3017 // Check remaining raw operands.
3018 VISAAtomicOps subOpKind = static_cast<VISAAtomicOps>(subOpc);
3019 bool (*typeFn)(VISA_Type) = 0;
3020 switch (subOpKind) {
3021 default:
3022 typeFn = isUDType;
3023 break;
3024 case ATOMIC_IMAX:
3025 case ATOMIC_IMIN:
3026 typeFn = isDType;
3027 break;
3028 case ATOMIC_ADD:
3029 case ATOMIC_SUB:
3030 typeFn = isDorUDTYpe;
3031 break;
3032 case ATOMIC_FMAX:
3033 case ATOMIC_FMIN:
3034 case ATOMIC_FCMPWR:
3035 case ATOMIC_FADD:
3036 case ATOMIC_FSUB:
3037 typeFn = isFType;
3038 break;
3039 }
3040
3041 // Check src0:
3042 //
3043 // - for INC and DEC operations, src0 must be V0 (the null variable);
3044 // - for IMIN and IMAX it must have type D;
3045 // - for all other operations, it must have type UD.
3046 const raw_opnd& src0 = getRawOperand(inst, i++);
3047 if (subOpKind == ATOMIC_INC || subOpKind == ATOMIC_DEC || subOpKind == ATOMIC_PREDEC)
3048 {
3049 REPORT_INSTRUCTION(options, src0.index == 0,
3050 "src0 in ISA_DWORD_ATOMIC inst must be "
3051 "V0 for INC/DEC/PREDEC.");
3052 }
3053 else
3054 {
3055 verifyRawOperandType(inst, src0, typeFn);
3056 }
3057 // Check src1:
3058 //
3059 // - for CMPXCHG operation, it must have type UD;
3060 // - for all other operations, it must be V0 (the null variable).
3061 //
3062 const raw_opnd& src1 = getRawOperand(inst, i++);
3063 if (subOpKind == ATOMIC_CMPXCHG || subOpKind == ATOMIC_FCMPWR)
3064 {
3065 verifyRawOperandType(inst, src1, typeFn);
3066 }
3067 else
3068 {
3069 REPORT_INSTRUCTION(options, src1.index == 0,
3070 "src1 in ISA_DWORD_ATOMIC inst must be "
3071 "V0 for non CMPXCHG operations.");
3072 }
3073 // Check dst:
3074 //
3075 // - for IMIN and IMAX, it must have type D;
3076 // - for all other operations, it must have type UD.
3077 //
3078 const raw_opnd& dst = getRawOperand(inst, i++);
3079 verifyRawOperandType(inst, dst, typeFn);
3080 break;
3081 }
3082 case ISA_3D_TYPED_ATOMIC:
3083 case ISA_3D_RT_WRITE:
3084 case ISA_QW_GATHER:
3085 case ISA_QW_SCATTER:
3086 {
3087 // no verification for now
3088 break;
3089 }
3090 default: REPORT_INSTRUCTION(options,false, "Illegal dataport Instruction Opcode: %d, %s.", opcode, ISA_Inst_Table[opcode].str);
3091 }
3092 }
3093
verifyBFMixedMode(const CISA_INST * inst)3094 void vISAVerifier::verifyBFMixedMode(const CISA_INST* inst)
3095 {
3096 // Only verify inst type: Mov/Compare/Arith for BF mixed mode
3097 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
3098 switch (ISA_Inst_Table[opcode].type)
3099 {
3100 case ISA_Inst_Mov:
3101 case ISA_Inst_Arith:
3102 case ISA_Inst_Compare:
3103 break;
3104 default:
3105 return;
3106 }
3107
3108 if (!useGivenVISAType(inst, ISA_TYPE_BF))
3109 {
3110 // Skip if inst does not use BF
3111 return;
3112 }
3113
3114 if (!irBuilder->hasBFMixMode())
3115 {
3116 REPORT_INSTRUCTION(options, false, "BF type is not allowed on this platform");
3117 return;
3118 }
3119
3120 switch (opcode)
3121 {
3122 case ISA_MUL:
3123 case ISA_MAD:
3124 case ISA_MOV:
3125 case ISA_ADD:
3126 case ISA_SEL:
3127 case ISA_CMP:
3128 break;
3129 default:
3130 REPORT_INSTRUCTION(options, false, "BF opnd is not allowed on this instruction");
3131 return;
3132 }
3133
3134 // Only F or BF are allowed
3135 // opernads: 0 : srcStart-1 --> dst
3136 // srcStart : n_srcs-1 --> src
3137 int srcStart = (int)ISA_Inst_Table[opcode].n_dsts;
3138
3139 // CMP's target must be bool, skip checking cmp's dst
3140 if (opcode != ISA_CMP)
3141 {
3142 for (int j = 0; j < srcStart; j++)
3143 {
3144 VISA_Type dstType = getOperandVISAType(inst, j);
3145 REPORT_INSTRUCTION(options,
3146 (dstType == ISA_TYPE_F || dstType == ISA_TYPE_BF),
3147 "Dst opnd in BF mixed mode should be either BF or F");
3148 }
3149 }
3150 else {
3151 // cmp's 1st opnd is cmp relop
3152 ++srcStart;
3153 }
3154 for (int j = 0; j < ISA_Inst_Table[opcode].n_srcs; j++)
3155 {
3156 VISA_Type srcType = getOperandVISAType(inst, j + srcStart);
3157 REPORT_INSTRUCTION(options,
3158 (srcType == ISA_TYPE_F || srcType == ISA_TYPE_BF),
3159 "Src opnd in BF mixed mode should be either BF or F");
3160 }
3161 return;
3162 }
3163
3164 struct LscInstVerifier {
3165 const common_isa_header &isaHeader;
3166 const print_format_provider_t* header;
3167 const CISA_INST* inst;
3168 std::stringstream errorStream;
3169 Options *options;
3170 int execSize;
3171
3172 LscOpInfo opInfo;
3173 LSC_OP subOp;
3174 LSC_SFID sfid;
3175
3176 int currOpIx = 0;
3177
LscInstVerifierLscInstVerifier3178 LscInstVerifier(
3179 const common_isa_header& _isaHeader,
3180 const print_format_provider_t* _header,
3181 const CISA_INST* _inst,
3182 Options *_options)
3183 : isaHeader(_isaHeader)
3184 , header(_header)
3185 , inst(_inst)
3186 , options(_options)
3187 {
3188 if (_inst->opcode == ISA_LSC_FENCE) {
3189 subOp = LSC_FENCE;
3190 sfid = getNextEnumU8<LSC_SFID>();
3191 } else if (_inst->opcode == ISA_LSC_TYPED) {
3192 subOp = getNextEnumU8<LSC_OP>();
3193 sfid = LSC_TGM;
3194 } else {
3195 subOp = getNextEnumU8<LSC_OP>();
3196 sfid = getNextEnumU8<LSC_SFID>();
3197 }
3198 (void)LscOpInfoFind(subOp, opInfo);
3199 execSize = 1;
3200 switch (inst->execsize & 0xF) {
3201 case EXEC_SIZE_1: execSize = 1; break;
3202 case EXEC_SIZE_2: execSize = 2; break;
3203 case EXEC_SIZE_4: execSize = 4; break;
3204 case EXEC_SIZE_8: execSize = 8; break;
3205 case EXEC_SIZE_16: execSize = 16; break;
3206 case EXEC_SIZE_32: execSize = 32; break;
3207 }
3208 }
3209
3210 ///////////////////////////////////////////////////////////////////////////
3211 template <typename T>
getPrimitiveLscInstVerifier3212 T getPrimitive(int absOpIx) {
3213 return getPrimitiveOperand<T>(inst, absOpIx);
3214 }
3215
3216 template <typename T>
getNextEnumU8LscInstVerifier3217 T getNextEnumU8() {
3218 return (T)getPrimitive<uint8_t>(currOpIx++);
3219 }
3220 template <typename T>
getNextLscInstVerifier3221 T getNext() {
3222 return getPrimitive<T>(currOpIx++);
3223 }
3224
3225 // LSC_TYPED and non-block2d LSC_UNTYPED
3226 // "next" because it advances the operand pointer
getNextDataShapeLscInstVerifier3227 LSC_DATA_SHAPE getNextDataShape() {
3228 // chmask only valid on LSC_LOAD_QUAD/LSC_STORE_QUAD
3229 // but retained in the binary format
3230 LSC_DATA_SHAPE dataShape { };
3231 dataShape.size = getNextEnumU8<LSC_DATA_SIZE>();
3232 dataShape.order = getNextEnumU8<LSC_DATA_ORDER>();
3233 // untyped and typed have both data elems and chmask
3234 // (even though the IR only uses one)
3235 auto dataElems = getNextEnumU8<LSC_DATA_ELEMS>();
3236 int chMask = (int)getNextEnumU8<int>();
3237 if (opInfo.hasChMask()) {
3238 dataShape.chmask = chMask;
3239 } else {
3240 (void)chMask; // not used
3241 dataShape.elems = dataElems;
3242 }
3243 return dataShape;
3244 }
getNextDataShape2DLscInstVerifier3245 LSC_DATA_SHAPE_BLOCK2D getNextDataShape2D() {
3246 LSC_DATA_SHAPE_BLOCK2D dataShape2D { };
3247 dataShape2D.size = getNextEnumU8<LSC_DATA_SIZE>();
3248 dataShape2D.order = getNextEnumU8<LSC_DATA_ORDER>();
3249 dataShape2D.blocks = (int)getNext<uint8_t>();
3250 dataShape2D.width = (int)getNext<uint16_t>();
3251 dataShape2D.height = (int)getNext<uint16_t>();
3252 dataShape2D.vnni = getNext<uint8_t>() != 0;
3253 return dataShape2D;
3254 }
3255
3256 ///////////////////////////////////////////////////////////////////////////
3257
3258 template <typename T1, typename T2 = const char *, typename T3 = const char *>
verifyLscInstVerifier3259 bool verify(bool z, T1 t1, T2 t2 = "", T3 t3 = "") {
3260 if (!z)
3261 error(t1, t2, t3);
3262 return z;
3263 }
3264 template <typename T1, typename T2 = const char *, typename T3 = const char *>
errorLscInstVerifier3265 void error(T1 t1, T2 t2 = "", T3 t3 = "") {
3266 std::stringstream ss;
3267 ss << " * ";
3268 ss << t1;
3269 ss << t2;
3270 ss << t3;
3271 ss << "\n";
3272 errorStream << ss.str();
3273 }
badEnumLscInstVerifier3274 void badEnum(const char *which, int value) {
3275 std::stringstream ss;
3276 ss << "0x" << std::hex << std::uppercase << value << ": ";
3277 ss << which;
3278 error(ss.str());
3279 }
3280
verifyDataSizeLscInstVerifier3281 int verifyDataSize(LSC_DATA_SIZE dataSize) {
3282 int dataSizeBytes = 0;
3283 switch (dataSize) {
3284 case LSC_DATA_SIZE_8b: dataSizeBytes = 1; break;
3285 case LSC_DATA_SIZE_16b: dataSizeBytes = 2; break;
3286 case LSC_DATA_SIZE_32b: dataSizeBytes = 4; break;
3287 case LSC_DATA_SIZE_64b: dataSizeBytes = 8; break;
3288 case LSC_DATA_SIZE_8c32b: dataSizeBytes = 4; break;
3289 case LSC_DATA_SIZE_16c32b: dataSizeBytes = 4; break;
3290 case LSC_DATA_SIZE_16c32bH: dataSizeBytes = 4; break;
3291 default: badEnum("invalid LSC_DATA_SIZE", dataSize);
3292 }
3293 return dataSizeBytes;
3294 }
3295
verifyDataOrderLscInstVerifier3296 bool verifyDataOrder(LSC_DATA_ORDER dataOrder) {
3297 bool transposed = false;
3298 switch (dataOrder) {
3299 case LSC_DATA_ORDER_NONTRANSPOSE: transposed = false; break;
3300 case LSC_DATA_ORDER_TRANSPOSE: transposed = true; break;
3301 default: badEnum("invalid LSC_DATA_ORDER", dataOrder);
3302 }
3303 return transposed;
3304 }
3305
verifyDataElemsLscInstVerifier3306 int verifyDataElems(LSC_DATA_ELEMS dataElems) {
3307 int vecSize = 0;
3308 switch (dataElems) {
3309 case LSC_DATA_ELEMS_1: vecSize = 1; break;
3310 case LSC_DATA_ELEMS_2: vecSize = 2; break;
3311 case LSC_DATA_ELEMS_3: vecSize = 3; break;
3312 case LSC_DATA_ELEMS_4: vecSize = 4; break;
3313 case LSC_DATA_ELEMS_8: vecSize = 8; break;
3314 case LSC_DATA_ELEMS_16: vecSize = 16; break;
3315 case LSC_DATA_ELEMS_32: vecSize = 32; break;
3316 case LSC_DATA_ELEMS_64: vecSize = 64; break;
3317 break;
3318 default: badEnum("LSC_DATA_ELEMS", dataElems);
3319 }
3320 return vecSize;
3321 }
3322
verifyDataShapeLscInstVerifier3323 void verifyDataShape(LSC_DATA_SHAPE dataShape) {
3324 int dataSizeBytes = verifyDataSize(dataShape.size);
3325 if (dataSizeBytes == 0)
3326 return; // verifyDataSize reported error
3327
3328
3329 bool transposed = verifyDataOrder(dataShape.order);
3330 if (transposed) {
3331 verify(!opInfo.hasChMask(),
3332 "LSC_DATA_ORDER_TRANSPOSE on ", opInfo.mnemonic);
3333 verify(execSize == 1,
3334 "LSC_DATA_ORDER_TRANSPOSE requires ExecSize of 1");
3335 verify(!opInfo.isAtomic(),
3336 "LSC atomics do not support transpose mode");
3337 } else if (opInfo.hasChMask()) {
3338 // quad store (store_cmask) can only support X, XY, XYZ, XYZW
3339 if (opInfo.op == LSC_STORE_QUAD) {
3340 verify(
3341 dataShape.chmask == LSC_DATA_CHMASK_X ||
3342 dataShape.chmask ==
3343 (LSC_DATA_CHMASK_X|LSC_DATA_CHMASK_Y) ||
3344 dataShape.chmask ==
3345 (LSC_DATA_CHMASK_X|LSC_DATA_CHMASK_Y|
3346 LSC_DATA_CHMASK_Z) ||
3347 dataShape.chmask == (LSC_DATA_CHMASK_X|LSC_DATA_CHMASK_Y
3348 |LSC_DATA_CHMASK_Z|LSC_DATA_CHMASK_W),
3349 "lsc_store_quad channel mask must be contiguous "
3350 "(.x, .xy, .xyz, or .xyzw)");
3351 }
3352 } else if (!opInfo.isBlock2D()) {
3353 // SIMT access not block2d
3354 verify(
3355 (dataShape.elems == LSC_DATA_ELEMS_1) ||
3356 (dataShape.size == LSC_DATA_SIZE_32b ||
3357 dataShape.size == LSC_DATA_SIZE_64b),
3358 "only D32 and D64 support vector load");
3359 if (sfid == LSC_UGML) {
3360 verify(
3361 dataShape.elems == LSC_DATA_ELEMS_1 ||
3362 dataShape.elems == LSC_DATA_ELEMS_2 ||
3363 dataShape.elems == LSC_DATA_ELEMS_4,
3364 "UGML only supports vector sizes 1, 2, and 4");
3365 } else if (sfid == LSC_SLM || sfid == LSC_UGM) {
3366 verify(
3367 dataShape.elems == LSC_DATA_ELEMS_1 ||
3368 dataShape.elems == LSC_DATA_ELEMS_2 ||
3369 dataShape.elems == LSC_DATA_ELEMS_3 ||
3370 dataShape.elems == LSC_DATA_ELEMS_4 ||
3371 dataShape.elems == LSC_DATA_ELEMS_8,
3372 "SLM/UGM only supports vector sizes 1, 2, 3, 4, and 8");
3373 }
3374 if (opInfo.isAtomic()) {
3375 verify(
3376 dataShape.size == LSC_DATA_SIZE_16c32b ||
3377 dataShape.size == LSC_DATA_SIZE_32b ||
3378 dataShape.size == LSC_DATA_SIZE_64b,
3379 "LSC atomics only support D16U32, D32, or D64");
3380 // TODO: opInfo.op == LSC_ATOMIC_ICAS only in B0+ (none in A0)
3381 verify(
3382 sfid != LSC_SLM ||
3383 dataShape.size != LSC_DATA_SIZE_64b ||
3384 opInfo.op == LSC_ATOMIC_ICAS,
3385 "LSC SLM D64 atomics only support icas");
3386 {
3387 verify(
3388 (opInfo.op != LSC_ATOMIC_FADD && opInfo.op != LSC_ATOMIC_FSUB) ||
3389 (sfid == LSC_UGM || sfid == LSC_UGML),
3390 "LSC atomic fadd/fsub only support UGM and UGML");
3391 }
3392 }
3393 }
3394
3395 int vecSize = 0;
3396 if (!opInfo.hasChMask()) {
3397 vecSize = verifyDataElems(dataShape.elems);
3398 if (vecSize != 1) {
3399 if (opInfo.isAtomic()) {
3400 error("LSC_DATA_ELEMS must be 1 for atomic operations");
3401 }
3402 switch (dataShape.size) {
3403 case LSC_DATA_SIZE_8c32b:
3404 case LSC_DATA_SIZE_16c32b:
3405 case LSC_DATA_SIZE_16c32bH:
3406 error("LSC_DATA_SIZE: conversion types may not use vector");
3407 break;
3408 default: break;
3409 }
3410 }
3411 } else if (dataShape.chmask == 0) {
3412 error("LSC_DATA_SHAPE::chmask: must not be 0");
3413 } else if (dataShape.chmask & ~0xF) {
3414 error("LSC_DATA_SHAPE::chmask: has high bits set");
3415 } else {
3416 vecSize = 0;
3417 for (int i = 0; i < 4; i++)
3418 if (dataShape.chmask & (1<<i))
3419 vecSize++;
3420 }
3421 if (vecSize == 0)
3422 return;
3423
3424 // data payloads cannot be more than 8 registers
3425 const uint32_t BYTES_PER_REG = COMMON_ISA_GRF_REG_SIZE;
3426 int dataRegs = 0;
3427 if (transposed) {
3428 // must be SIMD1 (whether they had that right or not, it will be)
3429 // (and we've already complained about it if not)
3430 dataRegs = std::max<int>(1, vecSize*dataSizeBytes/BYTES_PER_REG);
3431 } else {
3432 //
3433 // int execSize = BYTES_PER_REG/2;
3434 // apparently :d32x8 and :d64x4 are permissible if SIMD16, so
3435 // we'll pull the real ExecSize
3436 //
3437 // TODO: we need to recheck with HW that they indeed put this
3438 // optimization in
3439 int regPerVecElem =
3440 std::max<int>(1,dataSizeBytes*execSize/BYTES_PER_REG);
3441 dataRegs = vecSize*regPerVecElem;
3442 }
3443 if (opInfo.op != LSC_LOAD_BLOCK2D)
3444 verify(dataRegs <= 8, "this message accesses more than 8 registers");
3445 }
3446
verifyCachingOptsLscInstVerifier3447 void verifyCachingOpts() {
3448 auto l1 = getNextEnumU8<LSC_CACHE_OPT>();
3449 auto l3 = getNextEnumU8<LSC_CACHE_OPT>();
3450 if (sfid == LSC_TGM || sfid == LSC_UGML) {
3451 verify(l1 == LSC_CACHING_DEFAULT && l3 == LSC_CACHING_DEFAULT,
3452 "Messages to UGML and TGM require default cache settings"
3453 " (#53561)");
3454 return;
3455 }
3456 uint32_t enc = 0;
3457 LSC_CACHE_OPTS cacheOpts {l1, l3};
3458 // set isBits17_19 to false to check for all cases
3459 if (!LscTryEncodeCacheOpts(opInfo, cacheOpts, enc, false)) {
3460 if (opInfo.isLoad()) {
3461 error("invalid cache-control options for load (#53560)");
3462 } else if (opInfo.isAtomic()) {
3463 if (cacheOpts.l1 != LSC_CACHE_OPT::LSC_CACHING_UNCACHED) {
3464 error("atomics must use options with uncached L1"
3465 " (#53561 & #53542 [19:17])");
3466 } else {
3467 error("invalid cache-control options for atomic (#53561)");
3468 }
3469 } else {
3470 error("invalid cache-control options for store (#53561)");
3471 }
3472 }
3473 // TODO: we should proscribe default/default if prefetch
3474 }
3475
verifyAddrSizeLscInstVerifier3476 void verifyAddrSize(LSC_ADDR_SIZE addrSize) {
3477 // ADDR payloads limited to 4 registers
3478 //
3479 // SIMD32 64b will fit in PVC (as will SIMD16 64b on DG2)
3480 // ==> nothing to check
3481 switch (addrSize) {
3482 case LSC_ADDR_SIZE_16b:
3483 verify(
3484 sfid == LSC_SLM,
3485 ":a16 (LSC_ADDR_SIZE_16b) only allowed on .slm SFID");
3486 break;
3487 case LSC_ADDR_SIZE_32b:
3488 break;
3489 case LSC_ADDR_SIZE_64b:
3490 if (sfid == LSC_TGM || sfid == LSC_SLM)
3491 error(".tgm not allowed on :a64 (LSC_ADDR_SIZE_64b)");
3492 if (subOp == LSC_LOAD_BLOCK2D || subOp == LSC_STORE_BLOCK2D)
3493 error("block2d does not allow 64b address types");
3494 break;
3495 default:
3496 break;
3497 }
3498 }
3499
verifyAddressTypeLscInstVerifier3500 void verifyAddressType(LSC_ADDR_TYPE addrType, int surfIxAbs) {
3501 if (!verifyVectorOperand("Surface", surfIxAbs)) {
3502 return;
3503 }
3504 const auto &vo = getVectorOperand(inst, surfIxAbs);
3505
3506 switch (addrType) {
3507 case LSC_ADDR_TYPE_FLAT:
3508 verify(sfid != LSC_TGM, ".tgm may not use flat address model");
3509 switch (vo.tag & 0x7) {
3510 case OPERAND_IMMEDIATE:
3511 verify(
3512 vo.opnd_val.const_opnd._val.ival == 0,
3513 "Surface: for LSC_ADDR_TYPE_FLAT only imm 0 or V0 allowed");
3514 break; // okay
3515 case OPERAND_GENERAL:
3516 verify(
3517 vo.opnd_val.gen_opnd.index == 0,
3518 "Surface: must be null (V0) reg for LSC_ADDR_TYPE_FLAT");
3519 break;
3520 default:
3521 error("Surface: invalid operand type");
3522 }
3523 break;
3524 case LSC_ADDR_TYPE_BSS:
3525 case LSC_ADDR_TYPE_SS:
3526 case LSC_ADDR_TYPE_BTI:
3527 verify(sfid != LSC_SLM, "slm must use flat address model");
3528 switch (vo.tag & 0x7) {
3529 case OPERAND_IMMEDIATE:
3530 break;
3531 case OPERAND_GENERAL:
3532 verify(vo.opnd_val.gen_opnd.index != 0,
3533 "Surface: must not be null (V0) reg for non-FLAT AddrType");
3534 break;
3535 default:
3536 error("Surface: invalid operand type");
3537 }
3538 break;
3539 default: badEnum("LSC_ADDR_TYPE is invalid", addrType); break;
3540 }
3541 }
3542
verifyRawOperandLscInstVerifier3543 bool verifyRawOperand(const char *which, int absIx) {
3544 if (getOperandType(inst, absIx) != CISA_OPND_RAW) {
3545 error(which, ": expected vISA RawOperand");
3546 return false;
3547 }
3548 return true;
3549 }
3550
verifyRawOperandNullLscInstVerifier3551 bool verifyRawOperandNull(const char *which, int absIx) {
3552 if (!verifyRawOperand(which, absIx)) {
3553 return false;
3554 } else {
3555 const raw_opnd &ro = getRawOperand(inst, absIx);
3556 if (ro.index != 0) {
3557 error(which, "; operand must be null");
3558 return false;
3559 }
3560 return true;
3561 }
3562 }
3563
verifyRawOperandNonNullLscInstVerifier3564 bool verifyRawOperandNonNull(const char *which, int absIx) {
3565 if (!verifyRawOperand(which, absIx)) {
3566 return false;
3567 } else {
3568 const raw_opnd &ro = getRawOperand(inst, absIx);
3569 if (ro.index == 0) {
3570 error(which, ": operand must not be null");
3571 return false;
3572 }
3573 return true;
3574 }
3575 }
3576
verifyVectorOperandLscInstVerifier3577 bool verifyVectorOperand(const char *which, int absIx) {
3578 if (getOperandType(inst, absIx) != CISA_OPND_VECTOR) {
3579 error(which, ": expected vISA vector operand");
3580 return false;
3581 }
3582 return true;
3583 }
verifyVectorOperandNotNullLscInstVerifier3584 bool verifyVectorOperandNotNull(const char *which, int absIx) {
3585 if (!verifyVectorOperand(which, absIx)) {
3586 return false;
3587 }
3588 const vector_opnd &vo = getVectorOperand(inst, absIx);
3589 if (!vo.isImmediate() && vo.getOperandIndex() == 0) {
3590 error(which, ": vector operand must not be null");
3591 return false;
3592 }
3593 return true;
3594 }
3595
3596 // check dst and src1 and src2
verifyDataOperandsLscInstVerifier3597 void verifyDataOperands(int dstOpIx, int src1DataIx) {
3598 if (opInfo.isStore()) {
3599 verifyRawOperandNull("DstData", dstOpIx);
3600 } else {
3601 // atomics and loads can have either null or non-null
3602 verifyRawOperand("DstData", dstOpIx); // DstData
3603 }
3604
3605 if (opInfo.isLoad()) {
3606 verifyRawOperandNull("Src1Data", src1DataIx);
3607 if (!opInfo.isStrided() && !opInfo.isBlock2D())
3608 verifyRawOperandNull("Src2Data", src1DataIx+1);
3609 } else if (opInfo.isStore()) {
3610 verifyRawOperandNonNull("Src1Data", src1DataIx);
3611 if (!opInfo.isStrided() && !opInfo.isBlock2D())
3612 verifyRawOperandNull("Src2Data", src1DataIx+1);
3613 } else if (opInfo.isAtomic()) {
3614 if (opInfo.extraOperands > 0) {
3615 verifyRawOperandNonNull(
3616 "Src1Data (in binary atomic)", src1DataIx);
3617 } else {
3618 verifyRawOperandNull(
3619 "Src1Data (in binary atomic)", src1DataIx);
3620 }
3621 if (opInfo.extraOperands == 2) {
3622 verifyRawOperandNonNull(
3623 "Src2Data (in ternary atomic)", src1DataIx+1);
3624 } else {
3625 verifyRawOperandNull(
3626 "Src2Data (in ternary atomic)", src1DataIx+1);
3627 }
3628 }
3629 }
3630
3631 ///////////////////////////////////////////////////////////////////////////
verifyFenceLscInstVerifier3632 void verifyFence() {
3633 // SLM only gets .group and .none
3634 // c.f. ASpec 5.4.1.12.9 "Fence Message Handling" (pg 62)
3635 auto fenceOp = getNextEnumU8<LSC_FENCE_OP>();
3636 auto scope = getNextEnumU8<LSC_SCOPE>();
3637 switch (fenceOp) {
3638 case LSC_FENCE_OP_NONE:
3639 break;
3640 case LSC_FENCE_OP_EVICT:
3641 case LSC_FENCE_OP_INVALIDATE:
3642 case LSC_FENCE_OP_DISCARD:
3643 case LSC_FENCE_OP_CLEAN:
3644 case LSC_FENCE_OP_FLUSHL3:
3645 verify(sfid != LSC_SLM, "lsc_fence.slm fence op must be .none");
3646 break;
3647 default:
3648 badEnum("invalid LSC_FENCE",fenceOp);
3649 break;
3650 }
3651 switch (scope) {
3652 case LSC_SCOPE_GROUP:
3653 break;
3654 case LSC_SCOPE_LOCAL:
3655 case LSC_SCOPE_TILE:
3656 case LSC_SCOPE_GPU:
3657 case LSC_SCOPE_GPUS:
3658 case LSC_SCOPE_SYSREL:
3659 case LSC_SCOPE_SYSACQ:
3660 verify(sfid != LSC_SLM, "lsc_fence.slm must use .group scope");
3661 break;
3662 default:
3663 badEnum("invalid LSC_SCOPE",scope);
3664 break;
3665 }
3666 }
3667
3668 ///////////////////////////////////////////////////////////////////////////
verifyUntypedBlock2DLscInstVerifier3669 void verifyUntypedBlock2D() {
3670 bool valid = true;
3671
3672 verifyCachingOpts();
3673 //
3674 const auto dataShape2D = getNextDataShape2D();
3675 int dataSizeBytes = verifyDataSize(dataShape2D.size);
3676 verifyDataOrder(dataShape2D.order);
3677 valid &= verify(dataShape2D.blocks > 0,
3678 "block2d blocks (vec_len) must be >= 1");
3679 valid &= verify(dataShape2D.height > 0, "blocks2d height must be > 0");
3680 valid &= verify(dataShape2D.width > 0, "blocks2d width must be > 0");
3681 valid &= verify(
3682 opInfo.op != LSC_STORE_BLOCK2D || !dataShape2D.vnni,
3683 "block2d stores may not use VNNI transform");
3684 valid &= verify(
3685 opInfo.op != LSC_STORE_BLOCK2D || dataShape2D.blocks == 1,
3686 "block2d stores must have block count==1");
3687
3688 if (!valid)
3689 return;
3690
3691 bool transpose = dataShape2D.order == LSC_DATA_ORDER_TRANSPOSE;
3692 bool transform = dataShape2D.vnni;
3693 int cols = !transpose ? dataShape2D.width : dataShape2D.height;
3694 valid &= verify(cols*dataSizeBytes <= 64,
3695 cols*dataSizeBytes, ": block2d cols * data size must be <= 64");
3696 int rows = !transpose ? dataShape2D.height : dataShape2D.width;
3697 valid &= verify(rows <= 32,
3698 rows, ": block2d row count must be less than <= 32");
3699 //
3700 // HAS constraints on valid block dimensions
3701 // c.f. HAS 5.1.2.1 Allowed Sizes (pg 6) - NN
3702 // c.f. HAS 5.1.3.1 Allowed Sizes (pg 9) - TN
3703 // c.f. HAS 5.1.1.1 Allowed Sizes (pg 12) - TN
3704 // c.f. HAS 5.2.1.1 Allowed Sizes (pg 15) - TT
3705 //
3706 // in general all but (TN) can use block counts as follows
3707 // data size block count (vec_len)
3708 // u8/u16: 1, 2, and 4
3709 // u32: 1 and 2
3710 // u64: 1
3711 //
3712 // TN must use a block size of vec len of 1
3713 if (!transpose || transform) {
3714 switch (dataShape2D.size) {
3715 case LSC_DATA_SIZE_8b:
3716 valid &= verify(
3717 dataShape2D.blocks == 1 || dataShape2D.blocks == 2 ||
3718 dataShape2D.blocks == 4,
3719 dataShape2D.blocks,
3720 ": block2d count (vec_len) must be 1, 2, or 4 for u8");
3721 break;
3722 case LSC_DATA_SIZE_16b:
3723 valid &= verify(
3724 dataShape2D.blocks == 1 || dataShape2D.blocks == 2 ||
3725 dataShape2D.blocks == 4,
3726 dataShape2D.blocks,
3727 ": block2d count (vec_len) must be 1, 2, or 4 for u16");
3728 break;
3729 case LSC_DATA_SIZE_32b:
3730 valid &= verify(
3731 dataShape2D.blocks == 1 || dataShape2D.blocks == 2,
3732 dataShape2D.blocks,
3733 ": block2d count (vec_len) must be 1 or 2 for u32");
3734 break;
3735 case LSC_DATA_SIZE_64b:
3736 valid &= verify(
3737 dataShape2D.blocks == 1,
3738 dataShape2D.blocks,
3739 ": block2d count (vec_len) must be 1 for u64");
3740 break;
3741 default:
3742 error("invalid data type size for block2d load");
3743 return;
3744 }
3745 } else {
3746 valid &= verify(
3747 dataShape2D.blocks == 1,
3748 "block2d count (vec_len) must be 1 for block2d transposed");
3749 }
3750 if (!valid)
3751 return;
3752
3753 //
3754 if (dataShape2D.blocks > 16) {
3755 // this constrains us to the encoding space; specific hardware
3756 // may have additional constraints (e.g. only 1, 2, and 4)
3757 error("block2d data shape block count (array/vec len) > 16");
3758 }
3759
3760 //
3761 /////////////////////////////////////////
3762 // now we're at the register operands
3763 //
3764 verifyVectorOperandNotNull("SurfaceBase", currOpIx+1);
3765 verifyVectorOperandNotNull("SurfaceWidth", currOpIx+2);
3766 verifyVectorOperandNotNull("SurfaceHeight", currOpIx+3);
3767 verifyVectorOperandNotNull("SurfacePitch", currOpIx+4);
3768 verifyVectorOperandNotNull("OffsetX", currOpIx+5);
3769 verifyVectorOperandNotNull("OffsetY", currOpIx+6);
3770 //
3771 verifyDataOperands(currOpIx, currOpIx+1+6);
3772 }
3773
3774 ///////////////////////////////////////////////////////////////////////////
verifyUntypedBasicLscInstVerifier3775 void verifyUntypedBasic() {
3776 verifyCachingOpts();
3777
3778 //
3779 auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
3780 uint16_t immediateScale = getNext<uint16_t>();
3781 if ((immediateScale & (immediateScale-1)) != 0) {
3782 error("immediate scale must be power of two "
3783 "(someone could enable this though)");
3784 }
3785 int32_t immediateOffset = getNext<int32_t>();
3786
3787 auto addrSize = getNextEnumU8<LSC_ADDR_SIZE>();
3788 verifyAddrSize(addrSize);
3789 if (addrSize == LSC_ADDR_SIZE_16b) {
3790 if (immediateOffset > 0x7FFF || immediateOffset < -0x7FFF) {
3791 error("immediate offset overflows A16 address arithmetic");
3792 }
3793 }
3794
3795 auto dataShape = getNextDataShape();
3796 verifyDataShape(dataShape);
3797
3798 // now we are at the registers
3799 verifyAddressType(addrType, currOpIx); // Surface
3800
3801 const char *src0Name = opInfo.isStrided() ? "Src0AddrBase" : "Src0Addr";
3802 int src1DataIx = !opInfo.isStrided() ? currOpIx+3 : currOpIx+4;
3803 verifyRawOperand(src0Name, currOpIx+2); // Src0Addr
3804 if (opInfo.isStrided()) {
3805 if (verifyVectorOperand("Src0AddrStride", currOpIx+3)) {
3806 const auto &vo = getVectorOperand(inst, currOpIx+3);
3807 switch (vo.tag & 0x7) {
3808 case OPERAND_IMMEDIATE:
3809 if (vo.opnd_val.const_opnd._val.ival > 0xFFFF) {
3810 error("Src0AddrStride: pitch exceeds 16 bits");
3811 }
3812 break; // okay
3813 case OPERAND_GENERAL:
3814 if (vo.opnd_val.gen_opnd.index == 0) {
3815 error("Src0AddrStride",
3816 "VectorOperand must be immediate or non-null");
3817 }
3818 break;
3819 default:
3820 error("Src0AddrStride", "invalid operand type");
3821 }
3822 }
3823 }
3824
3825 verifyDataOperands(currOpIx+1, src1DataIx);
3826 }
3827
3828 ///////////////////////////////////////////////////////////////////////////
verifyTypedLscInstVerifier3829 void verifyTyped() {
3830 verifyCachingOpts();
3831
3832 auto addrType = getNextEnumU8<LSC_ADDR_TYPE>();
3833 auto addrSize = getNextEnumU8<LSC_ADDR_SIZE>();
3834 verifyAddrSize(addrSize);
3835
3836 auto dataShape = getNextDataShape();
3837 verifyDataShape(dataShape);
3838
3839 verifyAddressType(addrType, currOpIx);
3840
3841 // check all the Src0Addr fields (U, V, R, LOD)
3842 if (opInfo.op == LSC_READ_STATE_INFO) {
3843 verifyRawOperandNull("Src0Addr_Us", currOpIx+2); // U's
3844 verifyRawOperandNull("Src0Addr_Vs", currOpIx+3); // V's
3845 verifyRawOperandNull("Src0Addr_Rs", currOpIx+4); // R's
3846 verifyRawOperandNull("Src0Addr_LODs", currOpIx+5); // LOD's
3847 } else {
3848 verifyRawOperandNonNull("Src0Addr_Us", currOpIx+2); // U's
3849 verifyRawOperand("Src0Addr_Vs", currOpIx+3); // V's
3850 verifyRawOperand("Src0Addr_Rs", currOpIx+4); // R's
3851 verifyRawOperand("Src0Addr_LODs", currOpIx+5); // LOD's
3852 }
3853
3854 // check Dst, Src1, and Src2
3855 verifyDataOperands(currOpIx+1, currOpIx+6);
3856 }
3857
verifyLscInstVerifier3858 void verify() {
3859 if (opInfo.mnemonic == nullptr || opInfo.op == LSC_INVALID) {
3860 error("invalid LSC subop");
3861 return;
3862 }
3863 if (inst->opcode == ISA_LSC_FENCE) {
3864 verifyFence();
3865 } else if (inst->opcode == ISA_LSC_UNTYPED) {
3866 if (subOp == LSC_LOAD_BLOCK2D || subOp == LSC_STORE_BLOCK2D) {
3867 verifyUntypedBlock2D();
3868 } else {
3869 verifyUntypedBasic();
3870 }
3871 } else if (inst->opcode == ISA_LSC_TYPED) {
3872 verifyTyped();
3873 } else {
3874 badEnum("invalid LSC op code", inst->opcode);
3875 }
3876 }
3877 }; // LscInstVerifier
3878
verifyInstructionLsc(const CISA_INST * inst)3879 void vISAVerifier::verifyInstructionLsc(const CISA_INST *inst)
3880 {
3881 // This mostly comes from: https://gfxspecs.intel.com/Predator/Home/Index/53578
3882 // But there's also a spreadsheet floating around
3883 LscInstVerifier verifier(isaHeader, header, inst, options);
3884 verifier.verify();
3885 if (verifier.errorStream.tellp() > 0) {
3886 std::stringstream ss;
3887 ss << "in instruction " << printInstruction(header, inst, options) << "\n";
3888 ss << verifier.errorStream.str();
3889 error_list.push_back(ss.str());
3890 }
3891 }
3892
verifyInstructionSrnd(const CISA_INST * inst)3893 void vISAVerifier::verifyInstructionSrnd(const CISA_INST* inst)
3894 {
3895 const vector_opnd& dst = getVectorOperand(inst, 0);
3896 VISA_Type dstType = getVectorOperandType(header, dst);
3897 VISA_Modifier dstModifier = dst.getOperandModifier();
3898
3899 // dst
3900 REPORT_INSTRUCTION(options, dst.getOperandClass() == OPERAND_GENERAL,
3901 "Destination of this CISA instruction should be general operand.");
3902
3903 REPORT_INSTRUCTION(options, dstModifier == MODIFIER_NONE,
3904 "Destination modifier for this CISA instruction is not allowed.");
3905
3906 // src
3907 const vector_opnd& src0 = getVectorOperand(inst, 1);
3908 VISA_Type src0Type = getVectorOperandType(header, src0);
3909 VISA_Modifier src0Modifier = src0.getOperandModifier();
3910 const vector_opnd& src1 = getVectorOperand(inst, 2);
3911 VISA_Type src1Type = getVectorOperandType(header, src1);
3912 VISA_Modifier src1Modifier = src1.getOperandModifier();
3913
3914 REPORT_INSTRUCTION(options, src0Modifier == MODIFIER_NONE && src1Modifier == MODIFIER_NONE,
3915 "Source modifiers for this instruction are not allowed");
3916 REPORT_INSTRUCTION(options,
3917 (src0.getOperandClass() == OPERAND_GENERAL || src0.getOperandClass() == OPERAND_IMMEDIATE) &&
3918 (src1.getOperandClass() == OPERAND_GENERAL || src1.getOperandClass() == OPERAND_IMMEDIATE),
3919 "Sources in this instruction must be general or immediate");
3920
3921 // Verify types
3922 REPORT_INSTRUCTION(options, src0Type == src1Type,
3923 "Src0 and src1 should have the same type for this instruction");
3924 REPORT_INSTRUCTION(options,
3925 (dstType == ISA_TYPE_UB && src0Type == ISA_TYPE_HF) ||
3926 (dstType == ISA_TYPE_HF && src0Type == ISA_TYPE_F),
3927 "Src and Dst types mismatch. Only (dst=ub, src=hf) or (dst=hf, src=f) supported.");
3928 }
3929
verifyKernelAttributes()3930 void vISAVerifier::verifyKernelAttributes()
3931 {
3932 /// Verify SLMSize, if present, shows up only once
3933 unsigned int numSLMSize = 0;
3934 unsigned int numNamedBarrierCnt = 0;
3935 for (unsigned int i = 0; i < header->getAttrCount(); i++)
3936 {
3937 auto attr = header->getAttr(i);
3938 const char* attrName = header->getString(attr->nameIndex);
3939 Attributes::ID aID = Attributes::getAttributeID(attrName);
3940 if (aID == Attributes::ATTR_SLMSize)
3941 {
3942 numSLMSize++;
3943 }
3944 else if (aID == Attributes::ATTR_NBarrierCnt)
3945 {
3946 numNamedBarrierCnt++;
3947 }
3948 }
3949
3950 REPORT_HEADER(options, numSLMSize <= 1,
3951 "More than 1 kernel attribute defined %s",
3952 Attributes::getAttributeName(Attributes::ATTR_SLMSize));
3953
3954 REPORT_HEADER(options, numNamedBarrierCnt <= 1,
3955 "More than 1 kernel attribute defined %s",
3956 Attributes::getAttributeName(Attributes::ATTR_NBarrierCnt));
3957 }
3958
verifyKernelHeader()3959 void vISAVerifier::verifyKernelHeader()
3960 {
3961 /// Verify variable decls.
3962 unsigned numPreDefinedVars = Get_CISA_PreDefined_Var_Count();
3963 unsigned numPreDefinedSurfs = Get_CISA_PreDefined_Surf_Count();
3964 for (unsigned i = 0; i < header->getVarCount(); i++)
3965 {
3966 verifyVariableDecl(i);
3967 }
3968
3969 /// Verify address decls.
3970 for (unsigned i = 0; i < header->getAddrCount(); i++)
3971 {
3972 verifyAddressDecl(i);
3973 }
3974
3975 /// Verify predicate decls.
3976 for (unsigned i = 0; i < header->getPredCount(); i++)
3977 {
3978 verifyPredicateDecl(i);
3979 }
3980
3981 /// Verify labels.
3982 for (unsigned i = 0; i < header->getLabelCount(); i++)
3983 {
3984 REPORT_HEADER(options,header->getLabel(i)->name_index < header->getStringCount(),
3985 "label%d's name index(%d) is not valid", i, header->getLabel(i)->name_index);
3986 }
3987
3988 /// Verify sampler.
3989 for (unsigned i = 0; i < header->getSamplerCount(); i++)
3990 {
3991 REPORT_HEADER(options,header->getSampler(i)->name_index < header->getStringCount(),
3992 "S%d's name index(%d) is not valid", i, header->getSampler(i)->name_index);
3993 REPORT_HEADER(options,header->getSampler(i)->num_elements <= COMMON_ISA_MAX_SAMPLER_SIZE,
3994 "S%d's number of elements(%d) is not vaild", i, header->getSampler(i)->num_elements);
3995 }
3996
3997 /// Verify surface.
3998 unsigned int numPredSurf = Get_CISA_PreDefined_Surf_Count();
3999 for (unsigned i = numPredSurf; i < header->getSurfaceCount(); i++)
4000 {
4001 REPORT_HEADER(options,header->getSurface(i)->name_index < header->getStringCount(),
4002 "T%d's name index(%d) is not valid", i, header->getSurface(i)->name_index);
4003 REPORT_HEADER(options,header->getSurface(i)->num_elements <= COMMON_ISA_MAX_SURFACE_SIZE,
4004 "T%d's number of elements(%d) is not valid", i, header->getSurface(i)->num_elements);
4005 }
4006
4007 // Verify inputs.
4008 // v3.3+, kernel may have explicit arguments followed by implicit ones.
4009 // This information is only used by the CM runtime, not by Finalizer.
4010 unsigned implicitIndex = header->getInputCount();
4011 uint32_t versionNum = getVersionAsInt(isaHeader.major_version, isaHeader.minor_version);
4012 if (versionNum >= getVersionAsInt(3, 3))
4013 {
4014 for (unsigned i = 0; i < header->getInputCount(); i++)
4015 {
4016 if (header->getInput(i)->getImplicitKind() != 0)
4017 {
4018 implicitIndex = i;
4019 break;
4020 }
4021 }
4022 }
4023
4024 // [Begin, end) is an interval for each input. We check two things
4025 // - no overlap
4026 // - do not overflow i.e. end < 32 * (256 - 1)
4027 for (unsigned i = 0; i < header->getInputCount(); i++)
4028 {
4029 {
4030 auto pi = header->getInput(i);
4031 unsigned Begin = pi->offset;
4032 unsigned End = Begin + pi->size;
4033 if (End >= (uint32_t) (getGRFSize() * (256 - 1)))
4034 {
4035 REPORT_HEADER(options, false, "Input V%d is out of bound [%d, %d)", pi->index, Begin, End);
4036 }
4037 for (unsigned j = 0; j < i; ++j)
4038 {
4039 auto pj = header->getInput(j);
4040 unsigned Begin1 = pj->offset, End1 = pj->offset + pj->size;
4041 if ((Begin >= Begin1 && Begin < End1) ||
4042 (Begin1 >= Begin && Begin1 < End))
4043 {
4044 REPORT_HEADER(options, false, "Input V%d = [%d, %d) intersects with V%d = [%d, %d)",
4045 pi->index, Begin, End, pj->index, Begin1, End1);
4046 }
4047 }
4048 }
4049
4050 if (i >= implicitIndex)
4051 {
4052 REPORT_HEADER(
4053 options, header->getInput(i)->getImplicitKind() != 0,
4054 "Explicit input %d must not follow an implicit input %d", i,
4055 implicitIndex);
4056 }
4057 switch (header->getInput(i)->getInputClass())
4058 {
4059 case INPUT_GENERAL:
4060 if (header->getInput(i)->index < numPreDefinedVars)
4061 {
4062 REPORT_HEADER(options,false, "Input %d points to an invalid variable(%d)", i, header->getInput(i)->index);
4063 }
4064 else
4065 {
4066 int varId = header->getInput(i)->index - numPreDefinedVars;
4067 int varSize = header->getVar(varId)->num_elements * CISATypeTable[header->getVar(varId)->getType()].typeSize;
4068 REPORT_HEADER(options,varSize == header->getInput(i)->size,
4069 "Input %d's size(%d) does not agree with its variable (V%d)'s", i, header->getInput(i)->size, varId + numPreDefinedVars);
4070 if (header->getInput(i)->size < getGRFSize())
4071 {
4072 // check that input does not straddle GRF boundary
4073 auto beginGRF = header->getInput(i)->offset / getGRFSize();
4074 auto endGRF = (header->getInput(i)->offset + header->getInput(i)->size - 1) / getGRFSize();
4075 REPORT_HEADER(options, beginGRF == endGRF, "Input %s is <1 GRF but straddles GRF boundary", header->getInput(i)->dcl->getName());
4076 }
4077 }
4078 break;
4079 case INPUT_SAMPLER:
4080 REPORT_HEADER(options,header->getInput(i)->index < header->getSamplerCount(),
4081 "Input%d points to an invalid sampler index(%d)", i, header->getInput(i)->index);
4082 break;
4083 case INPUT_SURFACE:
4084 if (header->getInput(i)->index-numPredSurf >= header->getSurfaceCount() || header->getInput(i)->index < numPredSurf)
4085 {
4086 REPORT_HEADER(options,false, "Input%d points to an invalid/predefined surface index(%d)", i, header->getInput(i)->index);
4087 }
4088 else
4089 {
4090 int surfaceSize;
4091 surfaceSize = header->getSurface(header->getInput(i)->index-numPreDefinedSurfs)->num_elements * CISATypeTable[ISA_TYPE_UD].typeSize;
4092
4093 REPORT_HEADER(options,surfaceSize == header->getInput(i)->size, "Input%d's size(%d) does not agree with its surface's", i, header->getInput(i)->size);
4094 }
4095 break;
4096 default:
4097 REPORT_HEADER(options,false, "Input%d has invalid operand class(%d)", i, header->getInput(i)->getInputClass());
4098 }
4099 /// TODO: Consider adding offset checks here.
4100 }
4101
4102 verifyKernelAttributes();
4103 }
4104
finalize()4105 void vISAVerifier::finalize()
4106 {
4107 for (auto iter : labelDefs)
4108 {
4109 if (!(iter.second))
4110 {
4111 const label_info_t* lblInfo = header->getLabel(iter.first);
4112 if (lblInfo->kind != LABEL_FC)
4113 {
4114 REPORT_HEADER(options, false, "undefined label: %s", header->getString(lblInfo->name_index));
4115 }
4116 }
4117 }
4118 }
4119
verifyInstruction(const CISA_INST * inst)4120 void vISAVerifier::verifyInstruction(
4121 const CISA_INST* inst)
4122 {
4123 ISA_Opcode opcode = (ISA_Opcode)inst->opcode;
4124
4125 if (!(ISA_RESERVED_0 < opcode && opcode < ISA_NUM_OPCODE))
4126 {
4127 REPORT_INSTRUCTION(options, false, "Invalid vISA opcode: %d", opcode);
4128 return;
4129 }
4130
4131 TARGET_PLATFORM instPlatform = CISA_INST_table[opcode].platf;
4132 if (instPlatform != ALL)
4133 {
4134 // We assume instructions are backward compatible
4135 // instructions that are not should have their own checks elsewhere
4136 REPORT_INSTRUCTION(options, getGenxPlatform() >= instPlatform, "vISA instruction not supported on this platform");
4137 }
4138
4139 for (unsigned i = 0; i < inst->opnd_count; i++)
4140 verifyOperand(inst, i);
4141
4142 if (hasExecSize(opcode))
4143 {
4144 auto execSize = inst->getExecSize();
4145 REPORT_INSTRUCTION(options, execSize < EXEC_SIZE_ILLEGAL, "vISA instruction uses an illegal execution size.");
4146 // check for illegal combinations of emask and execution size
4147 REPORT_INSTRUCTION(options, Get_VISA_Exec_Size(execSize) + getvISAMaskOffset(inst->getExecMask()) <= 32,
4148 "vISA instruction has illegal combination of execution size and mask");
4149 }
4150
4151 if (hasPredicate(opcode))
4152 {
4153 uint16_t predicateNum = inst->pred.getId();
4154 REPORT_INSTRUCTION(options,predicateNum < header->getPredCount() + COMMON_ISA_NUM_PREDEFINED_PRED, "CISA instruction uses an illegal predicate value.");
4155 }
4156
4157 switch (ISA_Inst_Table[opcode].type)
4158 {
4159 case ISA_Inst_SVM: verifyInstructionSVM (inst); break;
4160 case ISA_Inst_Mov: verifyInstructionMove (inst); break;
4161 case ISA_Inst_Sync: verifyInstructionSync (inst); break;
4162 case ISA_Inst_Flow: verifyInstructionControlFlow (inst); break;
4163 case ISA_Inst_Misc: verifyInstructionMisc (inst); break;
4164 case ISA_Inst_Arith: verifyInstructionArith (inst); break;
4165 case ISA_Inst_Logic: verifyInstructionLogic (inst); break;
4166 case ISA_Inst_Compare: verifyInstructionCompare (inst); break;
4167 case ISA_Inst_Address: verifyInstructionAddress (inst); break;
4168 case ISA_Inst_Sampler: verifyInstructionSampler (inst); break;
4169 case ISA_Inst_SIMD_Flow: verifyInstructionSIMDFlow (inst); break;
4170 case ISA_Inst_Data_Port: verifyInstructionDataport (inst); break;
4171 case ISA_Inst_LSC: verifyInstructionLsc (inst); break;
4172 default:
4173 {
4174 std::stringstream sstr;
4175 sstr << "Illegal or unimplemented CISA instruction (opcode, type): (" <<
4176 opcode << ", " << ISA_Inst_Table[opcode].type << ").";
4177 ASSERT_USER(false, sstr.str());
4178 }
4179 }
4180
4181 // Verify particular features
4182 verifyBFMixedMode(inst);
4183 }
4184
4185 #endif // IS_RELEASE_DLL
4186
4187