2 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
5 * For use for simulation and test purposes only
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
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.
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.
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.
33 * Author: Steve Reinhardt, Anthony Gutierrez
36 #include "gpu-compute/brig_object.hh"
40 #include <sys/types.h>
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"
56 std::vector
<std::function
<HsaObject
*(const std::string
&, int, uint8_t*)>>
57 HsaObject::tryFileFuncs
= { BrigObject::tryFile
};
59 extern int getBrigDataTypeBytes(BrigType16_t t
);
61 const char *BrigObject::sectionNames
[] =
69 const char *segmentNames
[] =
83 BrigObject::getSectionOffset(enum SectionIndex sec
, int offs
) const
85 // allow offs == size for dummy end pointers
86 assert(offs
<= sectionInfo
[sec
].size
);
88 return sectionInfo
[sec
].ptr
+ offs
;
92 BrigObject::getString(int offs
) const
94 return (const char*)(getSectionOffset(DataSectionIndex
, offs
) + 4);
98 BrigObject::getCodeSectionEntry(int offs
) const
100 return (const BrigBase
*)getSectionOffset(CodeSectionIndex
, offs
);
104 BrigObject::getBrigBaseData(int offs
) const
106 return (Brig::BrigData
*)(getSectionOffset(DataSectionIndex
, offs
));
110 BrigObject::getData(int offs
) const
112 return getSectionOffset(DataSectionIndex
, offs
);
116 BrigObject::getOperand(int offs
) const
118 return (const BrigOperand
*)getSectionOffset(OperandsSectionIndex
, offs
);
122 BrigObject::getOperandPtr(int offs
, int index
) const
124 unsigned *op_offs
= (unsigned*)(getData(offs
+ 4 * (index
+ 1)));
130 BrigObject::getInst(int offs
) const
132 return (const BrigInstBase
*)getSectionOffset(CodeSectionIndex
, offs
);
136 BrigObject::getKernel(const std::string
&name
) const
142 BrigObject::getFunction(const std::string
&name
) const
144 for (int i
= 0; i
< functions
.size(); ++i
) {
145 if (functions
[i
]->name() == name
) {
154 BrigObject::processDirectives(const BrigBase
*dirPtr
, const BrigBase
*endPtr
,
155 StorageMap
*storageMap
)
157 while (dirPtr
< endPtr
) {
158 if (!dirPtr
->byteCount
) {
159 fatal("Bad directive size 0\n");
162 // calculate next pointer now so we can override it if needed
163 const BrigBase
*nextDirPtr
= brigNext(dirPtr
);
165 DPRINTF(HSAILObject
, "Code section entry kind: #%x, byte count: %d\n",
166 dirPtr
->kind
, dirPtr
->byteCount
);
168 switch (dirPtr
->kind
) {
169 case BRIG_KIND_DIRECTIVE_FUNCTION
:
171 const BrigDirectiveExecutable
*p M5_VAR_USED
=
172 reinterpret_cast<const BrigDirectiveExecutable
*>(dirPtr
);
174 DPRINTF(HSAILObject
,"DIRECTIVE_FUNCTION: %s offset: "
175 "%d next: %d\n", getString(p
->name
),
176 p
->firstCodeBlockEntry
, p
->nextModuleEntry
);
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");
184 const char *name
= getString(p
->name
);
186 HsailCode
*code_obj
= nullptr;
188 for (int i
= 0; i
< functions
.size(); ++i
) {
189 if (functions
[i
]->name() == name
) {
190 code_obj
= functions
[i
];
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
);
201 panic("Multiple definition of Function!!: %s\n",
206 nextDirPtr
= getCodeSectionEntry(p
->nextModuleEntry
);
210 case BRIG_KIND_DIRECTIVE_KERNEL
:
212 const BrigDirectiveExecutable
*p
=
213 reinterpret_cast<const BrigDirectiveExecutable
*>(dirPtr
);
215 DPRINTF(HSAILObject
,"DIRECTIVE_KERNEL: %s offset: %d count: "
216 "next: %d\n", getString(p
->name
),
217 p
->firstCodeBlockEntry
, p
->nextModuleEntry
);
219 const char *name
= getString(p
->name
);
224 std::string str
= name
;
226 int len
= str
.length();
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';
233 temp
= new char[str
.size()];
234 std::copy(str
.begin(), str
.end() - 1 , temp
);
235 temp
[str
.size() - 1 ] = '\0';
238 std::string kernel_name
= temp
;
241 HsailCode
*code_obj
= nullptr;
243 for (const auto &kernel
: kernels
) {
244 if (kernel
->name() == kernel_name
) {
251 // create new local storage map for kernel-local symbols
252 code_obj
= new HsailCode(kernel_name
, p
, this,
253 new StorageMap(storageMap
));
255 kernels
.push_back(code_obj
);
258 nextDirPtr
= getCodeSectionEntry(p
->nextModuleEntry
);
262 case BRIG_KIND_DIRECTIVE_VARIABLE
:
264 const BrigDirectiveVariable
*p
=
265 reinterpret_cast<const BrigDirectiveVariable
*>(dirPtr
);
267 uint64_t readonlySize_old
=
268 storageMap
->getSize(BRIG_SEGMENT_READONLY
);
270 StorageElement
* se
= storageMap
->addSymbol(p
, this);
272 DPRINTF(HSAILObject
, "DIRECTIVE_VARIABLE, symbol %s\n",
275 if (p
->segment
== BRIG_SEGMENT_READONLY
) {
276 // readonly memory has initialization data
277 uint8_t* readonlyData_old
= readonlyData
;
280 new uint8_t[storageMap
->getSize(BRIG_SEGMENT_READONLY
)];
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",
292 const BrigOperand
*brigOp
= getOperand(p
->init
);
293 assert(brigOp
->kind
==
294 BRIG_KIND_OPERAND_CONSTANT_BYTES
);
296 const Brig::BrigData
*operand_data M5_VAR_USED
=
297 getBrigBaseData(((BrigOperandConstantBytes
*)
300 assert((operand_data
->byteCount
/ 4) > 0);
302 uint8_t *symbol_data
=
303 (uint8_t*)getData(((BrigOperandConstantBytes
*)
306 // copy the old data and add the new data
307 if (readonlySize_old
> 0) {
308 memcpy(readonlyData
, readonlyData_old
,
312 memcpy(readonlyData
+ se
->offset
, symbol_data
,
315 delete[] readonlyData_old
;
321 case BRIG_KIND_DIRECTIVE_LABEL
:
323 const BrigDirectiveLabel M5_VAR_USED
*p
=
324 reinterpret_cast<const BrigDirectiveLabel
*>(dirPtr
);
326 panic("Label directives cannot be at the module level: %s\n",
332 case BRIG_KIND_DIRECTIVE_COMMENT
:
334 const BrigDirectiveComment M5_VAR_USED
*p
=
335 reinterpret_cast<const BrigDirectiveComment
*>(dirPtr
);
337 DPRINTF(HSAILObject
, "DIRECTIVE_COMMENT: %s\n",
342 case BRIG_KIND_DIRECTIVE_LOC
:
344 DPRINTF(HSAILObject
, "BRIG_DIRECTIVE_LOC\n");
348 case BRIG_KIND_DIRECTIVE_MODULE
:
350 const BrigDirectiveModule M5_VAR_USED
*p
=
351 reinterpret_cast<const BrigDirectiveModule
*>(dirPtr
);
353 DPRINTF(HSAILObject
, "BRIG_DIRECTIVE_MODULE: %s\n",
358 case BRIG_KIND_DIRECTIVE_CONTROL
:
360 DPRINTF(HSAILObject
, "DIRECTIVE_CONTROL\n");
364 case BRIG_KIND_DIRECTIVE_PRAGMA
:
366 DPRINTF(HSAILObject
, "DIRECTIVE_PRAGMA\n");
370 case BRIG_KIND_DIRECTIVE_EXTENSION
:
372 DPRINTF(HSAILObject
, "DIRECTIVE_EXTENSION\n");
376 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START
:
378 DPRINTF(HSAILObject
, "DIRECTIVE_ARG_BLOCK_START\n");
382 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END
:
384 DPRINTF(HSAILObject
, "DIRECTIVE_ARG_BLOCK_END\n");
388 if (dirPtr
->kind
>= BRIG_KIND_INST_BEGIN
&&
389 dirPtr
->kind
<= BRIG_KIND_INST_END
)
392 if (dirPtr
->kind
>= BRIG_KIND_OPERAND_BEGIN
&&
393 dirPtr
->kind
<= BRIG_KIND_OPERAND_END
)
396 warn("Unknown Brig directive kind: %d\n", dirPtr
->kind
);
405 BrigObject::tryFile(const std::string
&fname
, int len
, uint8_t *fileData
)
407 const char *brig_ident
= "HSA BRIG";
409 if (memcmp(brig_ident
, fileData
, MODULE_IDENTIFICATION_LENGTH
))
412 return new BrigObject(fname
, len
, fileData
);
415 BrigObject::BrigObject(const std::string
&fname
, int len
, uint8_t *fileData
)
416 : HsaObject(fname
), storageMap(new StorageMap())
418 const char *brig_ident
= "HSA BRIG";
419 BrigModuleHeader
*mod_hdr
= (BrigModuleHeader
*)fileData
;
421 fatal_if(memcmp(brig_ident
, mod_hdr
, MODULE_IDENTIFICATION_LENGTH
),
422 "%s is not a BRIG file\n", fname
);
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
);
431 fatal_if(mod_hdr
->sectionCount
!= NumSectionIndices
, "%s: BRIG section "
432 "count (%d) != expected value (%d)\n", fname
,
433 mod_hdr
->sectionCount
, NumSectionIndices
);
435 for (int i
= 0; i
< NumSectionIndices
; ++i
) {
436 sectionInfo
[i
].ptr
= nullptr;
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
;
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
,
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
;
454 BrigSectionHeader
*code_hdr
=
455 (BrigSectionHeader
*)sectionInfo
[CodeSectionIndex
].ptr
;
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
);
461 // start at offset 4 to skip initial null entry (see Brig spec)
462 processDirectives(getCodeSectionEntry(code_hdr
->headerByteCount
),
463 getCodeSectionEntry(sectionInfo
[CodeSectionIndex
].size
),
468 DPRINTF(HSALoader
, "BRIG object %s loaded.\n", fname
);
471 BrigObject::~BrigObject()
473 for (int i
= 0; i
< NumSectionIndices
; ++i
)
474 if (sectionInfo
[i
].ptr
)
475 delete[] sectionInfo
[i
].ptr
;