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 #include "BinaryCISAEmission.h"
10 #include "JitterDataStruct.h"
11 #include "VISAKernel.h"
12 
13 #include <fstream>
14 
15 #define SIZE_VALUE cisa_kernel->getBytesWritten()
16 #define SIZE_VALUE_INST cisa_kernel->getBytesWritten() - cisa_kernel->getKernelDataSize()
17 
18 using namespace vISA;
19 
Emit(VISAKernelImpl * cisa_kernel,unsigned int & binarySize)20 int CBinaryCISAEmitter::Emit(VISAKernelImpl * cisa_kernel, unsigned int& binarySize)
21 {
22     cisa_kernel->finalizeKernel();
23     const kernel_format_t * kernelInfo = cisa_kernel->getKernelFormat();
24 
25     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->string_count, sizeof(kernelInfo->string_count));
26 
27     for (uint32_t i = 0; i < kernelInfo->string_count; i++)
28     {
29         cisa_kernel->writeInToCisaBinaryBuffer(kernelInfo->strings[i], (int) strlen(kernelInfo->strings[i])+1);
30     }
31 
32     DEBUG_PRINT_SIZE("size after string_count: ", SIZE_VALUE);
33 
34     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->name_index, sizeof(kernelInfo->name_index));
35 
36     DEBUG_PRINT_SIZE("size after name_index: ", SIZE_VALUE);
37 
38     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->variable_count, sizeof(kernelInfo->variable_count));
39 
40     for (uint32_t i = 0; i < kernelInfo->variable_count; i++)
41     {
42         emitVarInfo(cisa_kernel, &kernelInfo->variables[i]);
43     }
44 
45     DEBUG_PRINT_SIZE("size after variables: ", SIZE_VALUE);
46 
47     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->address_count, sizeof(kernelInfo->address_count));
48 
49     for (int i = 0; i < kernelInfo->address_count; i++)
50     {
51         emitAddressInfo(cisa_kernel, &kernelInfo->addresses[i]);
52     }
53 
54     DEBUG_PRINT_SIZE("size after addresses: ", SIZE_VALUE);
55 
56     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->predicate_count, sizeof(kernelInfo->predicate_count));
57 
58     for (int i = 0; i < kernelInfo->predicate_count; i++)
59     {
60         emitPredicateInfo(cisa_kernel, &kernelInfo->predicates[i]);
61     }
62 
63     DEBUG_PRINT_SIZE("size after predicates: ", SIZE_VALUE);
64 
65     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->label_count, sizeof(kernelInfo->label_count));
66 
67     for (int i = 0; i < kernelInfo->label_count; i++)
68     {
69         emitLabelInfo(cisa_kernel, &kernelInfo->labels[i]);
70     }
71 
72     DEBUG_PRINT_SIZE("size after labels: ", SIZE_VALUE);
73 
74     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->sampler_count, sizeof(kernelInfo->sampler_count));
75 
76     for (int i = 0; i <kernelInfo->sampler_count; i++)
77     {
78         emitStateInfo(cisa_kernel, &kernelInfo->samplers[i]);
79     }
80 
81     DEBUG_PRINT_SIZE("size after samplers: ", SIZE_VALUE);
82 
83     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->surface_count, sizeof(kernelInfo->surface_count));
84 
85     for (int i = 0; i <kernelInfo->surface_count; i++)
86     {
87         emitStateInfo(cisa_kernel, &kernelInfo->surfaces[i]);
88     }
89 
90     DEBUG_PRINT_SIZE("size after surfaces: ", SIZE_VALUE);
91 
92     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->vme_count, sizeof(kernelInfo->vme_count));
93 
94     DEBUG_PRINT_SIZE("size after VMEs: ", SIZE_VALUE);
95 
96     if (cisa_kernel->getIsKernel())
97     {
98         cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->input_count, sizeof(kernelInfo->input_count));
99 
100         for (uint32_t i = 0; i < kernelInfo->input_count; i++)
101         {
102             emitInputInfo(cisa_kernel, &kernelInfo->inputs[i]);
103         }
104 
105         DEBUG_PRINT_SIZE("size after inputs: ", SIZE_VALUE);
106     }
107 
108     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->size, sizeof(kernelInfo->size));
109 
110     DEBUG_PRINT_SIZE("size after size: ", SIZE_VALUE);
111 
112     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->entry, sizeof(kernelInfo->entry));
113 
114     DEBUG_PRINT_SIZE("size after entry: ", SIZE_VALUE);
115 
116     if (!cisa_kernel->getIsKernel())
117     {
118         cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->input_size, sizeof(kernelInfo->input_size));
119         DEBUG_PRINT_SIZE("size after input size: ", SIZE_VALUE);
120 
121         cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->return_type, sizeof(kernelInfo->return_type));
122         DEBUG_PRINT_SIZE("size after return type: ", SIZE_VALUE);
123     }
124 
125     cisa_kernel->writeInToCisaBinaryBuffer(&kernelInfo->attribute_count, sizeof(kernelInfo->attribute_count));
126 
127     for (int i = 0; i < kernelInfo->attribute_count; i++)
128     {
129         this->emitAttributeInfo(cisa_kernel, &kernelInfo->attributes[i]);
130     }
131 
132     DEBUG_PRINT_SIZE("size after attributes: ", SIZE_VALUE);
133 
134     std::list<CisaFramework::CisaInst *>::iterator inst_iter = cisa_kernel->getInstructionListBegin();
135     std::list<CisaFramework::CisaInst *>::iterator inst_iter_end = cisa_kernel->getInstructionListEnd();
136 
137     int status = VISA_SUCCESS;
138     for (; inst_iter != inst_iter_end; inst_iter++)
139     {
140         CisaFramework::CisaInst * inst = *inst_iter;
141 
142         const CISA_INST * cisa_inst = inst->getCISAInst();
143         const VISA_INST_Desc * inst_desc = inst->getCISAInstDesc();
144         status = emitCisaInst(cisa_kernel, cisa_inst, inst_desc);
145         if (status != VISA_SUCCESS)
146         {
147             break;
148         }
149     }
150 
151     return status;
152 }
153 
emitCisaInst(VISAKernelImpl * cisa_kernel,const CISA_INST * inst,const VISA_INST_Desc * desc)154 int CBinaryCISAEmitter::emitCisaInst(
155     VISAKernelImpl* cisa_kernel, const CISA_INST* inst, const VISA_INST_Desc* desc)
156 {
157     bool     useSubDesc    = false;
158     uint8_t  subOpcode     = 0;
159     unsigned reverseOffset = 0;
160 
161     cisa_kernel->writeInToCisaBinaryBuffer(&desc->opcode, sizeof(desc->opcode));
162 
163     unsigned opndCount = desc->opnd_num;
164 
165     for (unsigned i = 0; i < opndCount; i++)
166     {
167         unsigned currendOpndIndex = i - reverseOffset;
168 
169         if (inst->opnd_array != NULL && inst->opnd_array[currendOpndIndex] == NULL)
170         {
171             assert(0);
172             return VISA_FAILURE;
173         }
174 
175         if (!useSubDesc && desc->opnd_desc[i].opnd_type == OPND_SUBOPCODE)
176         {
177             useSubDesc = true;
178             subOpcode = getPrimitiveOperand<uint8_t>(inst, i);
179             cisa_kernel->writeInToCisaBinaryBuffer(&subOpcode, sizeof(subOpcode));
180             opndCount += desc->getSubInstDesc(subOpcode).opnd_num;
181         }
182         else if ((useSubDesc == false && desc->opnd_desc[i].opnd_type == OPND_EXECSIZE) ||
183                  (useSubDesc == true  && desc->getSubInstDesc(subOpcode).opnd_desc[i-1].opnd_type == OPND_EXECSIZE))
184         {
185             cisa_kernel->writeInToCisaBinaryBuffer(&inst->execsize, sizeof(inst->execsize));
186             reverseOffset++;
187         }
188         else if ((useSubDesc == false && desc->opnd_desc[i  ].opnd_type == OPND_PRED) ||
189                  (useSubDesc == true  && desc->getSubInstDesc(subOpcode).opnd_desc[i-1].opnd_type == OPND_PRED))
190 
191         {
192             auto predInBinary = inst->pred.getPredInBinary();
193             cisa_kernel->writeInToCisaBinaryBuffer(&predInBinary, inst->pred.getPredInBinarySize());
194             reverseOffset++;
195         }
196         else if (inst->opnd_array != NULL && inst->opnd_array[currendOpndIndex]->opnd_type == CISA_OPND_OTHER)
197         {
198             cisa_kernel->writeInToCisaBinaryBuffer(&inst->opnd_array[currendOpndIndex]->_opnd.other_opnd, inst->opnd_array[currendOpndIndex]->size);
199         }
200         else if (inst->opnd_array != NULL && inst->opnd_array[currendOpndIndex]->opnd_type == CISA_OPND_VECTOR)
201         {
202             emitVectorOpnd(cisa_kernel, &inst->opnd_array[currendOpndIndex]->_opnd.v_opnd);
203         }
204         else if (inst->opnd_array != NULL && inst->opnd_array[currendOpndIndex]->opnd_type == CISA_OPND_RAW)
205         {
206             emitRawOpnd(cisa_kernel, &inst->opnd_array[currendOpndIndex]->_opnd.r_opnd);
207         }
208     }
209 
210     DEBUG_PRINT_SIZE_INSTRUCTION("size after instruction: ", desc->opcode, SIZE_VALUE_INST);
211     return VISA_SUCCESS;
212 }
213 
emitVarInfo(VISAKernelImpl * cisa_kernel,var_info_t * var)214 void CBinaryCISAEmitter::emitVarInfo(VISAKernelImpl * cisa_kernel, var_info_t * var)
215 {
216     cisa_kernel->writeInToCisaBinaryBuffer(&var->name_index, sizeof(var->name_index));
217     cisa_kernel->writeInToCisaBinaryBuffer(&var->bit_properties, sizeof(var->bit_properties));
218     cisa_kernel->writeInToCisaBinaryBuffer(&var->num_elements, sizeof(var->num_elements));
219     cisa_kernel->writeInToCisaBinaryBuffer(&var->alias_index, sizeof(var->alias_index));
220     cisa_kernel->writeInToCisaBinaryBuffer(&var->alias_offset, sizeof(var->alias_offset));
221 
222     cisa_kernel->writeInToCisaBinaryBuffer(&var->alias_scope_specifier, sizeof(var->alias_scope_specifier));
223 
224     cisa_kernel->writeInToCisaBinaryBuffer(&var->attribute_count, sizeof(var->attribute_count));
225 
226     for (int i = 0; i < var->attribute_count; i++)
227     {
228         emitAttributeInfo(cisa_kernel, &var->attributes[i]);
229     }
230 }
231 
emitStateInfo(VISAKernelImpl * cisa_kernel,state_info_t * var)232 void CBinaryCISAEmitter::emitStateInfo(VISAKernelImpl * cisa_kernel, state_info_t * var)
233 {
234     cisa_kernel->writeInToCisaBinaryBuffer(&var->name_index, sizeof(var->name_index));
235     cisa_kernel->writeInToCisaBinaryBuffer(&var->num_elements, sizeof(var->num_elements));
236     cisa_kernel->writeInToCisaBinaryBuffer(&var->attribute_count, sizeof(var->attribute_count));
237 
238     for (int i = 0; i < var->attribute_count; i++)
239     {
240         emitAttributeInfo(cisa_kernel, &var->attributes[i]);
241     }
242 }
243 
emitAddressInfo(VISAKernelImpl * cisa_kernel,addr_info_t * addr)244 void CBinaryCISAEmitter::emitAddressInfo(VISAKernelImpl * cisa_kernel, addr_info_t * addr)
245 {
246     cisa_kernel->writeInToCisaBinaryBuffer(&addr->name_index, sizeof(addr->name_index));
247     cisa_kernel->writeInToCisaBinaryBuffer(&addr->num_elements, sizeof(addr->num_elements));
248     cisa_kernel->writeInToCisaBinaryBuffer(&addr->attribute_count, sizeof(addr->attribute_count));
249 
250     for (int i = 0; i < addr->attribute_count; i++)
251     {
252         emitAttributeInfo(cisa_kernel, &addr->attributes[i]);
253     }
254 }
255 
emitPredicateInfo(VISAKernelImpl * cisa_kernel,pred_info_t * pred)256 void CBinaryCISAEmitter::emitPredicateInfo(VISAKernelImpl * cisa_kernel, pred_info_t * pred)
257 {
258     cisa_kernel->writeInToCisaBinaryBuffer(&pred->name_index, sizeof(pred->name_index));
259     cisa_kernel->writeInToCisaBinaryBuffer(&pred->num_elements, sizeof(pred->num_elements));
260     cisa_kernel->writeInToCisaBinaryBuffer(&pred->attribute_count, sizeof(pred->attribute_count));
261 
262     for (int i = 0; i < pred->attribute_count; i++)
263     {
264         emitAttributeInfo(cisa_kernel, &pred->attributes[i]);
265     }
266 }
267 
emitLabelInfo(VISAKernelImpl * cisa_kernel,label_info_t * lbl)268 void CBinaryCISAEmitter::emitLabelInfo(VISAKernelImpl * cisa_kernel, label_info_t * lbl)
269 {
270     cisa_kernel->writeInToCisaBinaryBuffer(&lbl->name_index, sizeof(lbl->name_index));
271     cisa_kernel->writeInToCisaBinaryBuffer(&lbl->kind, sizeof(lbl->kind));
272     cisa_kernel->writeInToCisaBinaryBuffer(&lbl->attribute_count, sizeof(lbl->attribute_count));
273 
274     for (int i = 0; i < lbl->attribute_count; i++)
275     {
276         emitAttributeInfo(cisa_kernel, &lbl->attributes[i]);
277     }
278 }
279 
emitInputInfo(VISAKernelImpl * cisa_kernel,input_info_t * in)280 void CBinaryCISAEmitter::emitInputInfo(VISAKernelImpl * cisa_kernel, input_info_t * in)
281 {
282     cisa_kernel->writeInToCisaBinaryBuffer(&in->kind, sizeof(in->kind));
283     cisa_kernel->writeInToCisaBinaryBuffer(&in->index, sizeof(in->index));
284     cisa_kernel->writeInToCisaBinaryBuffer(&in->offset, sizeof(in->offset));
285     cisa_kernel->writeInToCisaBinaryBuffer(&in->size, sizeof(in->size));
286 }
287 
emitAttributeInfo(VISAKernelImpl * cisa_kernel,attribute_info_t * attr)288 void CBinaryCISAEmitter::emitAttributeInfo(VISAKernelImpl *cisa_kernel, attribute_info_t * attr)
289 {
290     cisa_kernel->writeInToCisaBinaryBuffer(&attr->nameIndex, sizeof(attr->nameIndex));
291     cisa_kernel->writeInToCisaBinaryBuffer(&attr->size, sizeof(attr->size));
292 
293     if (attr->isInt)
294     {
295         switch (attr->size)
296         {
297             case 0: break;  // Attribute without Value
298             case sizeof(int8_t): cisa_kernel->writeInToCisaBinaryBuffer((int8_t *)(&attr->value.intVal), attr->size); break;
299             case sizeof(int16_t): cisa_kernel->writeInToCisaBinaryBuffer((int16_t*)(&attr->value.intVal), attr->size); break;
300             case sizeof(int32_t): cisa_kernel->writeInToCisaBinaryBuffer((int32_t*)(&attr->value.intVal), attr->size); break;
301             default:
302                 assert(0);
303                 break;
304         }
305     }
306     else
307         cisa_kernel->writeInToCisaBinaryBuffer(attr->value.stringVal, attr->size);
308 }
309 
emitVectorOpnd(VISAKernelImpl * cisa_kernel,vector_opnd * cisa_opnd)310 void CBinaryCISAEmitter::emitVectorOpnd(VISAKernelImpl * cisa_kernel, vector_opnd * cisa_opnd)
311 {
312     cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->tag, sizeof(cisa_opnd->tag));
313 
314     switch (cisa_opnd->tag & 0x7)
315     {
316     case OPERAND_GENERAL:
317         {
318             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.gen_opnd.index, sizeof(cisa_opnd->opnd_val.gen_opnd.index));
319             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.gen_opnd.row_offset, sizeof(cisa_opnd->opnd_val.gen_opnd.row_offset));
320             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.gen_opnd.col_offset, sizeof(cisa_opnd->opnd_val.gen_opnd.col_offset));
321             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.gen_opnd.region, sizeof(cisa_opnd->opnd_val.gen_opnd.region));
322             break;
323         }
324     case OPERAND_ADDRESS:
325         {
326             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.addr_opnd.index, sizeof(cisa_opnd->opnd_val.addr_opnd.index));
327             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.addr_opnd.offset, sizeof(cisa_opnd->opnd_val.addr_opnd.offset));
328             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.addr_opnd.width, sizeof(cisa_opnd->opnd_val.addr_opnd.width));
329             break;
330         }
331     case OPERAND_INDIRECT:
332         {
333             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.indirect_opnd.index, sizeof(cisa_opnd->opnd_val.indirect_opnd.index));
334             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.indirect_opnd.addr_offset, sizeof(cisa_opnd->opnd_val.indirect_opnd.addr_offset));
335             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.indirect_opnd.indirect_offset, sizeof(cisa_opnd->opnd_val.indirect_opnd.indirect_offset));
336             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.indirect_opnd.bit_property, sizeof(cisa_opnd->opnd_val.indirect_opnd.bit_property));
337             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.indirect_opnd.region, sizeof(cisa_opnd->opnd_val.indirect_opnd.region));
338             break;
339         }
340     case OPERAND_PREDICATE:
341         {
342             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.pred_opnd.index, sizeof(cisa_opnd->opnd_val.pred_opnd.index));
343             break;
344         }
345     case OPERAND_IMMEDIATE:
346         {
347             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.const_opnd.type, sizeof(cisa_opnd->opnd_val.const_opnd.type));
348             if (cisa_opnd->opnd_val.const_opnd.type == ISA_TYPE_DF)
349                 cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.const_opnd._val.dval, sizeof(double));
350             else if (cisa_opnd->opnd_val.const_opnd.type == ISA_TYPE_Q || cisa_opnd->opnd_val.const_opnd.type == ISA_TYPE_UQ)
351                 cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.const_opnd._val.lval, sizeof(unsigned long long));
352             else
353                 cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.const_opnd._val.ival, sizeof(unsigned int));
354             break;
355         }
356     case OPERAND_STATE:
357         {
358             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.state_opnd.opnd_class, sizeof(cisa_opnd->opnd_val.state_opnd.opnd_class));
359             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.state_opnd.index, sizeof(cisa_opnd->opnd_val.state_opnd.index));
360             cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->opnd_val.state_opnd.offset, sizeof(cisa_opnd->opnd_val.state_opnd.offset));
361             break;
362         }
363     default:
364         {
365             MUST_BE_TRUE(0, "Invalid Vector Operand Class. Size cannot be determined.");
366             break;
367         }
368     }
369 }
emitRawOpnd(VISAKernelImpl * cisa_kernel,raw_opnd * cisa_opnd)370 void CBinaryCISAEmitter::emitRawOpnd(VISAKernelImpl * cisa_kernel, raw_opnd * cisa_opnd)
371 {
372     cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->index, sizeof(cisa_opnd->index));
373     cisa_kernel->writeInToCisaBinaryBuffer(&cisa_opnd->offset, sizeof(cisa_opnd->offset));
374 }
375