misc: Rename misc.(hh|cc) to logging.(hh|cc)
[gem5.git] / src / gpu-compute / brig_object.cc
1 /*
2 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
3 * All rights reserved.
4 *
5 * For use for simulation and test purposes only
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 * Author: Steve Reinhardt, Anthony Gutierrez
34 */
35
36 #include "gpu-compute/brig_object.hh"
37
38 #include <fcntl.h>
39 #include <sys/mman.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42
43 #include <cassert>
44 #include <cstddef>
45 #include <cstdlib>
46
47 #include "arch/hsail/Brig.h"
48 #include "base/logging.hh"
49 #include "base/trace.hh"
50 #include "debug/BRIG.hh"
51 #include "debug/HSAILObject.hh"
52 #include "debug/HSALoader.hh"
53
54 using namespace Brig;
55
56 std::vector<std::function<HsaObject*(const std::string&, int, uint8_t*)>>
57 HsaObject::tryFileFuncs = { BrigObject::tryFile };
58
59 extern int getBrigDataTypeBytes(BrigType16_t t);
60
61 const char *BrigObject::sectionNames[] =
62 {
63 "hsa_data",
64 "hsa_code",
65 "hsa_operand",
66 ".shstrtab"
67 };
68
69 const char *segmentNames[] =
70 {
71 "none",
72 "flat",
73 "global",
74 "readonly",
75 "kernarg",
76 "group",
77 "private",
78 "spill",
79 "args"
80 };
81
82 const uint8_t*
83 BrigObject::getSectionOffset(enum SectionIndex sec, int offs) const
84 {
85 // allow offs == size for dummy end pointers
86 assert(offs <= sectionInfo[sec].size);
87
88 return sectionInfo[sec].ptr + offs;
89 }
90
91 const char*
92 BrigObject::getString(int offs) const
93 {
94 return (const char*)(getSectionOffset(DataSectionIndex, offs) + 4);
95 }
96
97 const BrigBase*
98 BrigObject::getCodeSectionEntry(int offs) const
99 {
100 return (const BrigBase*)getSectionOffset(CodeSectionIndex, offs);
101 }
102
103 const BrigData*
104 BrigObject::getBrigBaseData(int offs) const
105 {
106 return (Brig::BrigData*)(getSectionOffset(DataSectionIndex, offs));
107 }
108
109 const uint8_t*
110 BrigObject::getData(int offs) const
111 {
112 return getSectionOffset(DataSectionIndex, offs);
113 }
114
115 const BrigOperand*
116 BrigObject::getOperand(int offs) const
117 {
118 return (const BrigOperand*)getSectionOffset(OperandsSectionIndex, offs);
119 }
120
121 unsigned
122 BrigObject::getOperandPtr(int offs, int index) const
123 {
124 unsigned *op_offs = (unsigned*)(getData(offs + 4 * (index + 1)));
125
126 return *op_offs;
127 }
128
129 const BrigInstBase*
130 BrigObject::getInst(int offs) const
131 {
132 return (const BrigInstBase*)getSectionOffset(CodeSectionIndex, offs);
133 }
134
135 HsaCode*
136 BrigObject::getKernel(const std::string &name) const
137 {
138 return nullptr;
139 }
140
141 HsaCode*
142 BrigObject::getFunction(const std::string &name) const
143 {
144 for (int i = 0; i < functions.size(); ++i) {
145 if (functions[i]->name() == name) {
146 return functions[i];
147 }
148 }
149
150 return nullptr;
151 }
152
153 void
154 BrigObject::processDirectives(const BrigBase *dirPtr, const BrigBase *endPtr,
155 StorageMap *storageMap)
156 {
157 while (dirPtr < endPtr) {
158 if (!dirPtr->byteCount) {
159 fatal("Bad directive size 0\n");
160 }
161
162 // calculate next pointer now so we can override it if needed
163 const BrigBase *nextDirPtr = brigNext(dirPtr);
164
165 DPRINTF(HSAILObject, "Code section entry kind: #%x, byte count: %d\n",
166 dirPtr->kind, dirPtr->byteCount);
167
168 switch (dirPtr->kind) {
169 case BRIG_KIND_DIRECTIVE_FUNCTION:
170 {
171 const BrigDirectiveExecutable *p M5_VAR_USED =
172 reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
173
174 DPRINTF(HSAILObject,"DIRECTIVE_FUNCTION: %s offset: "
175 "%d next: %d\n", getString(p->name),
176 p->firstCodeBlockEntry, p->nextModuleEntry);
177
178 if (p->firstCodeBlockEntry != p->nextModuleEntry) {
179 // Function calls are not supported. We allow the BRIG
180 // object file to create stubs, but the function calls will
181 // not work properly if the application makes use of them.
182 warn("HSA function invocations are unsupported.\n");
183
184 const char *name = getString(p->name);
185
186 HsailCode *code_obj = nullptr;
187
188 for (int i = 0; i < functions.size(); ++i) {
189 if (functions[i]->name() == name) {
190 code_obj = functions[i];
191 break;
192 }
193 }
194
195 if (!code_obj) {
196 // create new local storage map for kernel-local symbols
197 code_obj = new HsailCode(name, p, this,
198 new StorageMap(storageMap));
199 functions.push_back(code_obj);
200 } else {
201 panic("Multiple definition of Function!!: %s\n",
202 getString(p->name));
203 }
204 }
205
206 nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
207 }
208 break;
209
210 case BRIG_KIND_DIRECTIVE_KERNEL:
211 {
212 const BrigDirectiveExecutable *p =
213 reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
214
215 DPRINTF(HSAILObject,"DIRECTIVE_KERNEL: %s offset: %d count: "
216 "next: %d\n", getString(p->name),
217 p->firstCodeBlockEntry, p->nextModuleEntry);
218
219 const char *name = getString(p->name);
220
221 if (name[0] == '&')
222 name++;
223
224 std::string str = name;
225 char *temp;
226 int len = str.length();
227
228 if (str[len - 1] >= 'a' && str[len - 1] <= 'z') {
229 temp = new char[str.size() + 1];
230 std::copy(str.begin(), str.end() , temp);
231 temp[str.size()] = '\0';
232 } else {
233 temp = new char[str.size()];
234 std::copy(str.begin(), str.end() - 1 , temp);
235 temp[str.size() - 1 ] = '\0';
236 }
237
238 std::string kernel_name = temp;
239 delete[] temp;
240
241 HsailCode *code_obj = nullptr;
242
243 for (const auto &kernel : kernels) {
244 if (kernel->name() == kernel_name) {
245 code_obj = kernel;
246 break;
247 }
248 }
249
250 if (!code_obj) {
251 // create new local storage map for kernel-local symbols
252 code_obj = new HsailCode(kernel_name, p, this,
253 new StorageMap(storageMap));
254
255 kernels.push_back(code_obj);
256 }
257
258 nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
259 }
260 break;
261
262 case BRIG_KIND_DIRECTIVE_VARIABLE:
263 {
264 const BrigDirectiveVariable *p =
265 reinterpret_cast<const BrigDirectiveVariable*>(dirPtr);
266
267 uint64_t readonlySize_old =
268 storageMap->getSize(BRIG_SEGMENT_READONLY);
269
270 StorageElement* se = storageMap->addSymbol(p, this);
271
272 DPRINTF(HSAILObject, "DIRECTIVE_VARIABLE, symbol %s\n",
273 getString(p->name));
274
275 if (p->segment == BRIG_SEGMENT_READONLY) {
276 // readonly memory has initialization data
277 uint8_t* readonlyData_old = readonlyData;
278
279 readonlyData =
280 new uint8_t[storageMap->getSize(BRIG_SEGMENT_READONLY)];
281
282 if (p->init) {
283 if ((p->type == BRIG_TYPE_ROIMG) ||
284 (p->type == BRIG_TYPE_WOIMG) ||
285 (p->type == BRIG_TYPE_SAMP) ||
286 (p->type == BRIG_TYPE_SIG32) ||
287 (p->type == BRIG_TYPE_SIG64)) {
288 panic("Read only data type not supported: %s\n",
289 getString(p->name));
290 }
291
292 const BrigOperand *brigOp = getOperand(p->init);
293 assert(brigOp->kind ==
294 BRIG_KIND_OPERAND_CONSTANT_BYTES);
295
296 const Brig::BrigData *operand_data M5_VAR_USED =
297 getBrigBaseData(((BrigOperandConstantBytes*)
298 brigOp)->bytes);
299
300 assert((operand_data->byteCount / 4) > 0);
301
302 uint8_t *symbol_data =
303 (uint8_t*)getData(((BrigOperandConstantBytes*)
304 brigOp)->bytes + 4);
305
306 // copy the old data and add the new data
307 if (readonlySize_old > 0) {
308 memcpy(readonlyData, readonlyData_old,
309 readonlySize_old);
310 }
311
312 memcpy(readonlyData + se->offset, symbol_data,
313 se->size);
314
315 delete[] readonlyData_old;
316 }
317 }
318 }
319 break;
320
321 case BRIG_KIND_DIRECTIVE_LABEL:
322 {
323 const BrigDirectiveLabel M5_VAR_USED *p =
324 reinterpret_cast<const BrigDirectiveLabel*>(dirPtr);
325
326 panic("Label directives cannot be at the module level: %s\n",
327 getString(p->name));
328
329 }
330 break;
331
332 case BRIG_KIND_DIRECTIVE_COMMENT:
333 {
334 const BrigDirectiveComment M5_VAR_USED *p =
335 reinterpret_cast<const BrigDirectiveComment*>(dirPtr);
336
337 DPRINTF(HSAILObject, "DIRECTIVE_COMMENT: %s\n",
338 getString(p->name));
339 }
340 break;
341
342 case BRIG_KIND_DIRECTIVE_LOC:
343 {
344 DPRINTF(HSAILObject, "BRIG_DIRECTIVE_LOC\n");
345 }
346 break;
347
348 case BRIG_KIND_DIRECTIVE_MODULE:
349 {
350 const BrigDirectiveModule M5_VAR_USED *p =
351 reinterpret_cast<const BrigDirectiveModule*>(dirPtr);
352
353 DPRINTF(HSAILObject, "BRIG_DIRECTIVE_MODULE: %s\n",
354 getString(p->name));
355 }
356 break;
357
358 case BRIG_KIND_DIRECTIVE_CONTROL:
359 {
360 DPRINTF(HSAILObject, "DIRECTIVE_CONTROL\n");
361 }
362 break;
363
364 case BRIG_KIND_DIRECTIVE_PRAGMA:
365 {
366 DPRINTF(HSAILObject, "DIRECTIVE_PRAGMA\n");
367 }
368 break;
369
370 case BRIG_KIND_DIRECTIVE_EXTENSION:
371 {
372 DPRINTF(HSAILObject, "DIRECTIVE_EXTENSION\n");
373 }
374 break;
375
376 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
377 {
378 DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_START\n");
379 }
380 break;
381
382 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
383 {
384 DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_END\n");
385 }
386 break;
387 default:
388 if (dirPtr->kind >= BRIG_KIND_INST_BEGIN &&
389 dirPtr->kind <= BRIG_KIND_INST_END)
390 break;
391
392 if (dirPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
393 dirPtr->kind <= BRIG_KIND_OPERAND_END)
394 break;
395
396 warn("Unknown Brig directive kind: %d\n", dirPtr->kind);
397 break;
398 }
399
400 dirPtr = nextDirPtr;
401 }
402 }
403
404 HsaObject*
405 BrigObject::tryFile(const std::string &fname, int len, uint8_t *fileData)
406 {
407 const char *brig_ident = "HSA BRIG";
408
409 if (memcmp(brig_ident, fileData, MODULE_IDENTIFICATION_LENGTH))
410 return nullptr;
411
412 return new BrigObject(fname, len, fileData);
413 }
414
415 BrigObject::BrigObject(const std::string &fname, int len, uint8_t *fileData)
416 : HsaObject(fname), storageMap(new StorageMap())
417 {
418 const char *brig_ident = "HSA BRIG";
419 BrigModuleHeader *mod_hdr = (BrigModuleHeader*)fileData;
420
421 fatal_if(memcmp(brig_ident, mod_hdr, MODULE_IDENTIFICATION_LENGTH),
422 "%s is not a BRIG file\n", fname);
423
424 if (mod_hdr->brigMajor != BRIG_VERSION_BRIG_MAJOR ||
425 mod_hdr->brigMinor != BRIG_VERSION_BRIG_MINOR) {
426 fatal("%s: BRIG version mismatch, %d.%d != %d.%d\n",
427 fname, mod_hdr->brigMajor, mod_hdr->brigMinor,
428 BRIG_VERSION_BRIG_MAJOR, BRIG_VERSION_BRIG_MINOR);
429 }
430
431 fatal_if(mod_hdr->sectionCount != NumSectionIndices, "%s: BRIG section "
432 "count (%d) != expected value (%d)\n", fname,
433 mod_hdr->sectionCount, NumSectionIndices);
434
435 for (int i = 0; i < NumSectionIndices; ++i) {
436 sectionInfo[i].ptr = nullptr;
437 }
438
439 uint64_t *sec_idx_table = (uint64_t*)(fileData + mod_hdr->sectionIndex);
440 for (int sec_idx = 0; sec_idx < mod_hdr->sectionCount; ++sec_idx) {
441 uint8_t *sec_hdr_byte_ptr = fileData + sec_idx_table[sec_idx];
442 BrigSectionHeader *sec_hdr = (BrigSectionHeader*)sec_hdr_byte_ptr;
443
444 // It doesn't look like cprintf supports string precision values,
445 // but if this breaks, the right answer is to fix that
446 DPRINTF(HSAILObject, "found section %.*s\n", sec_hdr->nameLength,
447 sec_hdr->name);
448
449 sectionInfo[sec_idx].ptr = new uint8_t[sec_hdr->byteCount];
450 memcpy(sectionInfo[sec_idx].ptr, sec_hdr_byte_ptr, sec_hdr->byteCount);
451 sectionInfo[sec_idx].size = sec_hdr->byteCount;
452 }
453
454 BrigSectionHeader *code_hdr =
455 (BrigSectionHeader*)sectionInfo[CodeSectionIndex].ptr;
456
457 DPRINTF(HSAILObject, "Code section hdr, count: %d, hdr count: %d, "
458 "name len: %d\n", code_hdr->byteCount, code_hdr->headerByteCount,
459 code_hdr->nameLength);
460
461 // start at offset 4 to skip initial null entry (see Brig spec)
462 processDirectives(getCodeSectionEntry(code_hdr->headerByteCount),
463 getCodeSectionEntry(sectionInfo[CodeSectionIndex].size),
464 storageMap);
465
466 delete[] fileData;
467
468 DPRINTF(HSALoader, "BRIG object %s loaded.\n", fname);
469 }
470
471 BrigObject::~BrigObject()
472 {
473 for (int i = 0; i < NumSectionIndices; ++i)
474 if (sectionInfo[i].ptr)
475 delete[] sectionInfo[i].ptr;
476 }