brig_object.cc (11308:7d8836fd043d) brig_object.cc (11734:d5ffebd89eb2)
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/misc.hh"
49#include "base/trace.hh"
50#include "debug/BRIG.hh"
51#include "debug/HSAILObject.hh"
52#include "debug/HSALoader.hh"
53
54using namespace Brig;
55
56std::vector<std::function<HsaObject*(const std::string&, int, uint8_t*)>>
57 HsaObject::tryFileFuncs = { BrigObject::tryFile };
58
59extern int getBrigDataTypeBytes(BrigType16_t t);
60
61const char *BrigObject::sectionNames[] =
62{
63 "hsa_data",
64 "hsa_code",
65 "hsa_operand",
66 ".shstrtab"
67};
68
69const char *segmentNames[] =
70{
71 "none",
72 "flat",
73 "global",
74 "readonly",
75 "kernarg",
76 "group",
77 "private",
78 "spill",
79 "args"
80};
81
82const uint8_t*
83BrigObject::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
91const char*
92BrigObject::getString(int offs) const
93{
94 return (const char*)(getSectionOffset(DataSectionIndex, offs) + 4);
95}
96
97const BrigBase*
98BrigObject::getCodeSectionEntry(int offs) const
99{
100 return (const BrigBase*)getSectionOffset(CodeSectionIndex, offs);
101}
102
103const BrigData*
104BrigObject::getBrigBaseData(int offs) const
105{
106 return (Brig::BrigData*)(getSectionOffset(DataSectionIndex, offs));
107}
108
109const uint8_t*
110BrigObject::getData(int offs) const
111{
112 return getSectionOffset(DataSectionIndex, offs);
113}
114
115const BrigOperand*
116BrigObject::getOperand(int offs) const
117{
118 return (const BrigOperand*)getSectionOffset(OperandsSectionIndex, offs);
119}
120
121unsigned
122BrigObject::getOperandPtr(int offs, int index) const
123{
124 unsigned *op_offs = (unsigned*)(getData(offs + 4 * (index + 1)));
125
126 return *op_offs;
127}
128
129const BrigInstBase*
130BrigObject::getInst(int offs) const
131{
132 return (const BrigInstBase*)getSectionOffset(CodeSectionIndex, offs);
133}
134
135HsaCode*
136BrigObject::getKernel(const std::string &name) const
137{
138 return nullptr;
139}
140
141HsaCode*
142BrigObject::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
153void
154BrigObject::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) {
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/misc.hh"
49#include "base/trace.hh"
50#include "debug/BRIG.hh"
51#include "debug/HSAILObject.hh"
52#include "debug/HSALoader.hh"
53
54using namespace Brig;
55
56std::vector<std::function<HsaObject*(const std::string&, int, uint8_t*)>>
57 HsaObject::tryFileFuncs = { BrigObject::tryFile };
58
59extern int getBrigDataTypeBytes(BrigType16_t t);
60
61const char *BrigObject::sectionNames[] =
62{
63 "hsa_data",
64 "hsa_code",
65 "hsa_operand",
66 ".shstrtab"
67};
68
69const char *segmentNames[] =
70{
71 "none",
72 "flat",
73 "global",
74 "readonly",
75 "kernarg",
76 "group",
77 "private",
78 "spill",
79 "args"
80};
81
82const uint8_t*
83BrigObject::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
91const char*
92BrigObject::getString(int offs) const
93{
94 return (const char*)(getSectionOffset(DataSectionIndex, offs) + 4);
95}
96
97const BrigBase*
98BrigObject::getCodeSectionEntry(int offs) const
99{
100 return (const BrigBase*)getSectionOffset(CodeSectionIndex, offs);
101}
102
103const BrigData*
104BrigObject::getBrigBaseData(int offs) const
105{
106 return (Brig::BrigData*)(getSectionOffset(DataSectionIndex, offs));
107}
108
109const uint8_t*
110BrigObject::getData(int offs) const
111{
112 return getSectionOffset(DataSectionIndex, offs);
113}
114
115const BrigOperand*
116BrigObject::getOperand(int offs) const
117{
118 return (const BrigOperand*)getSectionOffset(OperandsSectionIndex, offs);
119}
120
121unsigned
122BrigObject::getOperandPtr(int offs, int index) const
123{
124 unsigned *op_offs = (unsigned*)(getData(offs + 4 * (index + 1)));
125
126 return *op_offs;
127}
128
129const BrigInstBase*
130BrigObject::getInst(int offs) const
131{
132 return (const BrigInstBase*)getSectionOffset(CodeSectionIndex, offs);
133}
134
135HsaCode*
136BrigObject::getKernel(const std::string &name) const
137{
138 return nullptr;
139}
140
141HsaCode*
142BrigObject::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
153void
154BrigObject::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 panic("Function calls are not fully supported yet!!: %s\n",
180 getString(p->name));
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");
181
182 const char *name = getString(p->name);
183
184 HsailCode *code_obj = nullptr;
185
186 for (int i = 0; i < functions.size(); ++i) {
187 if (functions[i]->name() == name) {
188 code_obj = functions[i];
189 break;
190 }
191 }
192
193 if (!code_obj) {
194 // create new local storage map for kernel-local symbols
195 code_obj = new HsailCode(name, p, this,
196 new StorageMap(storageMap));
197 functions.push_back(code_obj);
198 } else {
199 panic("Multiple definition of Function!!: %s\n",
200 getString(p->name));
201 }
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 }
202
203 }
204 }
205
204 nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
205 }
206 break;
207
208 case BRIG_KIND_DIRECTIVE_KERNEL:
209 {
210 const BrigDirectiveExecutable *p =
211 reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
212
213 DPRINTF(HSAILObject,"DIRECTIVE_KERNEL: %s offset: %d count: "
214 "next: %d\n", getString(p->name),
215 p->firstCodeBlockEntry, p->nextModuleEntry);
216
217 const char *name = getString(p->name);
218
219 if (name[0] == '&')
220 name++;
221
222 std::string str = name;
223 char *temp;
224 int len = str.length();
225
226 if (str[len - 1] >= 'a' && str[len - 1] <= 'z') {
227 temp = new char[str.size() + 1];
228 std::copy(str.begin(), str.end() , temp);
229 temp[str.size()] = '\0';
230 } else {
231 temp = new char[str.size()];
232 std::copy(str.begin(), str.end() - 1 , temp);
233 temp[str.size() - 1 ] = '\0';
234 }
235
236 std::string kernel_name = temp;
237 delete[] temp;
238
239 HsailCode *code_obj = nullptr;
240
241 for (const auto &kernel : kernels) {
242 if (kernel->name() == kernel_name) {
243 code_obj = kernel;
244 break;
245 }
246 }
247
248 if (!code_obj) {
249 // create new local storage map for kernel-local symbols
250 code_obj = new HsailCode(kernel_name, p, this,
251 new StorageMap(storageMap));
252
253 kernels.push_back(code_obj);
254 }
255
256 nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
257 }
258 break;
259
260 case BRIG_KIND_DIRECTIVE_VARIABLE:
261 {
262 const BrigDirectiveVariable *p =
263 reinterpret_cast<const BrigDirectiveVariable*>(dirPtr);
264
265 uint64_t readonlySize_old =
266 storageMap->getSize(BRIG_SEGMENT_READONLY);
267
268 StorageElement* se = storageMap->addSymbol(p, this);
269
270 DPRINTF(HSAILObject, "DIRECTIVE_VARIABLE, symbol %s\n",
271 getString(p->name));
272
273 if (p->segment == BRIG_SEGMENT_READONLY) {
274 // readonly memory has initialization data
275 uint8_t* readonlyData_old = readonlyData;
276
277 readonlyData =
278 new uint8_t[storageMap->getSize(BRIG_SEGMENT_READONLY)];
279
280 if (p->init) {
281 if ((p->type == BRIG_TYPE_ROIMG) ||
282 (p->type == BRIG_TYPE_WOIMG) ||
283 (p->type == BRIG_TYPE_SAMP) ||
284 (p->type == BRIG_TYPE_SIG32) ||
285 (p->type == BRIG_TYPE_SIG64)) {
286 panic("Read only data type not supported: %s\n",
287 getString(p->name));
288 }
289
290 const BrigOperand *brigOp = getOperand(p->init);
291 assert(brigOp->kind ==
292 BRIG_KIND_OPERAND_CONSTANT_BYTES);
293
294 const Brig::BrigData *operand_data M5_VAR_USED =
295 getBrigBaseData(((BrigOperandConstantBytes*)
296 brigOp)->bytes);
297
298 assert((operand_data->byteCount / 4) > 0);
299
300 uint8_t *symbol_data =
301 (uint8_t*)getData(((BrigOperandConstantBytes*)
302 brigOp)->bytes + 4);
303
304 // copy the old data and add the new data
305 if (readonlySize_old > 0) {
306 memcpy(readonlyData, readonlyData_old,
307 readonlySize_old);
308 }
309
310 memcpy(readonlyData + se->offset, symbol_data,
311 se->size);
312
313 delete[] readonlyData_old;
314 }
315 }
316 }
317 break;
318
319 case BRIG_KIND_DIRECTIVE_LABEL:
320 {
321 const BrigDirectiveLabel M5_VAR_USED *p =
322 reinterpret_cast<const BrigDirectiveLabel*>(dirPtr);
323
324 panic("Label directives cannot be at the module level: %s\n",
325 getString(p->name));
326
327 }
328 break;
329
330 case BRIG_KIND_DIRECTIVE_COMMENT:
331 {
332 const BrigDirectiveComment M5_VAR_USED *p =
333 reinterpret_cast<const BrigDirectiveComment*>(dirPtr);
334
335 DPRINTF(HSAILObject, "DIRECTIVE_COMMENT: %s\n",
336 getString(p->name));
337 }
338 break;
339
340 case BRIG_KIND_DIRECTIVE_LOC:
341 {
342 DPRINTF(HSAILObject, "BRIG_DIRECTIVE_LOC\n");
343 }
344 break;
345
346 case BRIG_KIND_DIRECTIVE_MODULE:
347 {
348 const BrigDirectiveModule M5_VAR_USED *p =
349 reinterpret_cast<const BrigDirectiveModule*>(dirPtr);
350
351 DPRINTF(HSAILObject, "BRIG_DIRECTIVE_MODULE: %s\n",
352 getString(p->name));
353 }
354 break;
355
356 case BRIG_KIND_DIRECTIVE_CONTROL:
357 {
358 DPRINTF(HSAILObject, "DIRECTIVE_CONTROL\n");
359 }
360 break;
361
362 case BRIG_KIND_DIRECTIVE_PRAGMA:
363 {
364 DPRINTF(HSAILObject, "DIRECTIVE_PRAGMA\n");
365 }
366 break;
367
368 case BRIG_KIND_DIRECTIVE_EXTENSION:
369 {
370 DPRINTF(HSAILObject, "DIRECTIVE_EXTENSION\n");
371 }
372 break;
373
374 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
375 {
376 DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_START\n");
377 }
378 break;
379
380 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
381 {
382 DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_END\n");
383 }
384 break;
385 default:
386 if (dirPtr->kind >= BRIG_KIND_INST_BEGIN &&
387 dirPtr->kind <= BRIG_KIND_INST_END)
388 break;
389
390 if (dirPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
391 dirPtr->kind <= BRIG_KIND_OPERAND_END)
392 break;
393
394 warn("Unknown Brig directive kind: %d\n", dirPtr->kind);
395 break;
396 }
397
398 dirPtr = nextDirPtr;
399 }
400}
401
402HsaObject*
403BrigObject::tryFile(const std::string &fname, int len, uint8_t *fileData)
404{
405 const char *brig_ident = "HSA BRIG";
406
407 if (memcmp(brig_ident, fileData, MODULE_IDENTIFICATION_LENGTH))
408 return nullptr;
409
410 return new BrigObject(fname, len, fileData);
411}
412
413BrigObject::BrigObject(const std::string &fname, int len, uint8_t *fileData)
414 : HsaObject(fname), storageMap(new StorageMap())
415{
416 const char *brig_ident = "HSA BRIG";
417 BrigModuleHeader *mod_hdr = (BrigModuleHeader*)fileData;
418
419 fatal_if(memcmp(brig_ident, mod_hdr, MODULE_IDENTIFICATION_LENGTH),
420 "%s is not a BRIG file\n", fname);
421
422 if (mod_hdr->brigMajor != BRIG_VERSION_BRIG_MAJOR ||
423 mod_hdr->brigMinor != BRIG_VERSION_BRIG_MINOR) {
424 fatal("%s: BRIG version mismatch, %d.%d != %d.%d\n",
425 fname, mod_hdr->brigMajor, mod_hdr->brigMinor,
426 BRIG_VERSION_BRIG_MAJOR, BRIG_VERSION_BRIG_MINOR);
427 }
428
429 fatal_if(mod_hdr->sectionCount != NumSectionIndices, "%s: BRIG section "
430 "count (%d) != expected value (%d)\n", fname,
431 mod_hdr->sectionCount, NumSectionIndices);
432
433 for (int i = 0; i < NumSectionIndices; ++i) {
434 sectionInfo[i].ptr = nullptr;
435 }
436
437 uint64_t *sec_idx_table = (uint64_t*)(fileData + mod_hdr->sectionIndex);
438 for (int sec_idx = 0; sec_idx < mod_hdr->sectionCount; ++sec_idx) {
439 uint8_t *sec_hdr_byte_ptr = fileData + sec_idx_table[sec_idx];
440 BrigSectionHeader *sec_hdr = (BrigSectionHeader*)sec_hdr_byte_ptr;
441
442 // It doesn't look like cprintf supports string precision values,
443 // but if this breaks, the right answer is to fix that
444 DPRINTF(HSAILObject, "found section %.*s\n", sec_hdr->nameLength,
445 sec_hdr->name);
446
447 sectionInfo[sec_idx].ptr = new uint8_t[sec_hdr->byteCount];
448 memcpy(sectionInfo[sec_idx].ptr, sec_hdr_byte_ptr, sec_hdr->byteCount);
449 sectionInfo[sec_idx].size = sec_hdr->byteCount;
450 }
451
452 BrigSectionHeader *code_hdr =
453 (BrigSectionHeader*)sectionInfo[CodeSectionIndex].ptr;
454
455 DPRINTF(HSAILObject, "Code section hdr, count: %d, hdr count: %d, "
456 "name len: %d\n", code_hdr->byteCount, code_hdr->headerByteCount,
457 code_hdr->nameLength);
458
459 // start at offset 4 to skip initial null entry (see Brig spec)
460 processDirectives(getCodeSectionEntry(code_hdr->headerByteCount),
461 getCodeSectionEntry(sectionInfo[CodeSectionIndex].size),
462 storageMap);
463
464 delete[] fileData;
465
466 DPRINTF(HSALoader, "BRIG object %s loaded.\n", fname);
467}
468
469BrigObject::~BrigObject()
470{
471 for (int i = 0; i < NumSectionIndices; ++i)
472 if (sectionInfo[i].ptr)
473 delete[] sectionInfo[i].ptr;
474}
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
404HsaObject*
405BrigObject::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
415BrigObject::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
471BrigObject::~BrigObject()
472{
473 for (int i = 0; i < NumSectionIndices; ++i)
474 if (sectionInfo[i].ptr)
475 delete[] sectionInfo[i].ptr;
476}