These files aren't a collection of miscellaneous stuff, they're the definition of the Logger interface, and a few utility macros for calling into that interface (panic, warn, etc.). Change-Id: I84267ac3f45896a83c0ef027f8f19c5e9a5667d1 Reviewed-on: https://gem5-review.googlesource.com/6226 Reviewed-by: Brandon Potter <Brandon.Potter@amd.com> Maintainer: Gabe Black <gabeblack@google.com>
477 lines
15 KiB
C++
477 lines
15 KiB
C++
/*
|
|
* Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* For use for simulation and test purposes only
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3. Neither the name of the copyright holder nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*
|
|
* Author: Steve Reinhardt, Anthony Gutierrez
|
|
*/
|
|
|
|
#include "gpu-compute/brig_object.hh"
|
|
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <sys/types.h>
|
|
#include <unistd.h>
|
|
|
|
#include <cassert>
|
|
#include <cstddef>
|
|
#include <cstdlib>
|
|
|
|
#include "arch/hsail/Brig.h"
|
|
#include "base/logging.hh"
|
|
#include "base/trace.hh"
|
|
#include "debug/BRIG.hh"
|
|
#include "debug/HSAILObject.hh"
|
|
#include "debug/HSALoader.hh"
|
|
|
|
using namespace Brig;
|
|
|
|
std::vector<std::function<HsaObject*(const std::string&, int, uint8_t*)>>
|
|
HsaObject::tryFileFuncs = { BrigObject::tryFile };
|
|
|
|
extern int getBrigDataTypeBytes(BrigType16_t t);
|
|
|
|
const char *BrigObject::sectionNames[] =
|
|
{
|
|
"hsa_data",
|
|
"hsa_code",
|
|
"hsa_operand",
|
|
".shstrtab"
|
|
};
|
|
|
|
const char *segmentNames[] =
|
|
{
|
|
"none",
|
|
"flat",
|
|
"global",
|
|
"readonly",
|
|
"kernarg",
|
|
"group",
|
|
"private",
|
|
"spill",
|
|
"args"
|
|
};
|
|
|
|
const uint8_t*
|
|
BrigObject::getSectionOffset(enum SectionIndex sec, int offs) const
|
|
{
|
|
// allow offs == size for dummy end pointers
|
|
assert(offs <= sectionInfo[sec].size);
|
|
|
|
return sectionInfo[sec].ptr + offs;
|
|
}
|
|
|
|
const char*
|
|
BrigObject::getString(int offs) const
|
|
{
|
|
return (const char*)(getSectionOffset(DataSectionIndex, offs) + 4);
|
|
}
|
|
|
|
const BrigBase*
|
|
BrigObject::getCodeSectionEntry(int offs) const
|
|
{
|
|
return (const BrigBase*)getSectionOffset(CodeSectionIndex, offs);
|
|
}
|
|
|
|
const BrigData*
|
|
BrigObject::getBrigBaseData(int offs) const
|
|
{
|
|
return (Brig::BrigData*)(getSectionOffset(DataSectionIndex, offs));
|
|
}
|
|
|
|
const uint8_t*
|
|
BrigObject::getData(int offs) const
|
|
{
|
|
return getSectionOffset(DataSectionIndex, offs);
|
|
}
|
|
|
|
const BrigOperand*
|
|
BrigObject::getOperand(int offs) const
|
|
{
|
|
return (const BrigOperand*)getSectionOffset(OperandsSectionIndex, offs);
|
|
}
|
|
|
|
unsigned
|
|
BrigObject::getOperandPtr(int offs, int index) const
|
|
{
|
|
unsigned *op_offs = (unsigned*)(getData(offs + 4 * (index + 1)));
|
|
|
|
return *op_offs;
|
|
}
|
|
|
|
const BrigInstBase*
|
|
BrigObject::getInst(int offs) const
|
|
{
|
|
return (const BrigInstBase*)getSectionOffset(CodeSectionIndex, offs);
|
|
}
|
|
|
|
HsaCode*
|
|
BrigObject::getKernel(const std::string &name) const
|
|
{
|
|
return nullptr;
|
|
}
|
|
|
|
HsaCode*
|
|
BrigObject::getFunction(const std::string &name) const
|
|
{
|
|
for (int i = 0; i < functions.size(); ++i) {
|
|
if (functions[i]->name() == name) {
|
|
return functions[i];
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
void
|
|
BrigObject::processDirectives(const BrigBase *dirPtr, const BrigBase *endPtr,
|
|
StorageMap *storageMap)
|
|
{
|
|
while (dirPtr < endPtr) {
|
|
if (!dirPtr->byteCount) {
|
|
fatal("Bad directive size 0\n");
|
|
}
|
|
|
|
// calculate next pointer now so we can override it if needed
|
|
const BrigBase *nextDirPtr = brigNext(dirPtr);
|
|
|
|
DPRINTF(HSAILObject, "Code section entry kind: #%x, byte count: %d\n",
|
|
dirPtr->kind, dirPtr->byteCount);
|
|
|
|
switch (dirPtr->kind) {
|
|
case BRIG_KIND_DIRECTIVE_FUNCTION:
|
|
{
|
|
const BrigDirectiveExecutable *p M5_VAR_USED =
|
|
reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
|
|
|
|
DPRINTF(HSAILObject,"DIRECTIVE_FUNCTION: %s offset: "
|
|
"%d next: %d\n", getString(p->name),
|
|
p->firstCodeBlockEntry, p->nextModuleEntry);
|
|
|
|
if (p->firstCodeBlockEntry != p->nextModuleEntry) {
|
|
// Function calls are not supported. We allow the BRIG
|
|
// object file to create stubs, but the function calls will
|
|
// not work properly if the application makes use of them.
|
|
warn("HSA function invocations are unsupported.\n");
|
|
|
|
const char *name = getString(p->name);
|
|
|
|
HsailCode *code_obj = nullptr;
|
|
|
|
for (int i = 0; i < functions.size(); ++i) {
|
|
if (functions[i]->name() == name) {
|
|
code_obj = functions[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!code_obj) {
|
|
// create new local storage map for kernel-local symbols
|
|
code_obj = new HsailCode(name, p, this,
|
|
new StorageMap(storageMap));
|
|
functions.push_back(code_obj);
|
|
} else {
|
|
panic("Multiple definition of Function!!: %s\n",
|
|
getString(p->name));
|
|
}
|
|
}
|
|
|
|
nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_KERNEL:
|
|
{
|
|
const BrigDirectiveExecutable *p =
|
|
reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
|
|
|
|
DPRINTF(HSAILObject,"DIRECTIVE_KERNEL: %s offset: %d count: "
|
|
"next: %d\n", getString(p->name),
|
|
p->firstCodeBlockEntry, p->nextModuleEntry);
|
|
|
|
const char *name = getString(p->name);
|
|
|
|
if (name[0] == '&')
|
|
name++;
|
|
|
|
std::string str = name;
|
|
char *temp;
|
|
int len = str.length();
|
|
|
|
if (str[len - 1] >= 'a' && str[len - 1] <= 'z') {
|
|
temp = new char[str.size() + 1];
|
|
std::copy(str.begin(), str.end() , temp);
|
|
temp[str.size()] = '\0';
|
|
} else {
|
|
temp = new char[str.size()];
|
|
std::copy(str.begin(), str.end() - 1 , temp);
|
|
temp[str.size() - 1 ] = '\0';
|
|
}
|
|
|
|
std::string kernel_name = temp;
|
|
delete[] temp;
|
|
|
|
HsailCode *code_obj = nullptr;
|
|
|
|
for (const auto &kernel : kernels) {
|
|
if (kernel->name() == kernel_name) {
|
|
code_obj = kernel;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!code_obj) {
|
|
// create new local storage map for kernel-local symbols
|
|
code_obj = new HsailCode(kernel_name, p, this,
|
|
new StorageMap(storageMap));
|
|
|
|
kernels.push_back(code_obj);
|
|
}
|
|
|
|
nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_VARIABLE:
|
|
{
|
|
const BrigDirectiveVariable *p =
|
|
reinterpret_cast<const BrigDirectiveVariable*>(dirPtr);
|
|
|
|
uint64_t readonlySize_old =
|
|
storageMap->getSize(BRIG_SEGMENT_READONLY);
|
|
|
|
StorageElement* se = storageMap->addSymbol(p, this);
|
|
|
|
DPRINTF(HSAILObject, "DIRECTIVE_VARIABLE, symbol %s\n",
|
|
getString(p->name));
|
|
|
|
if (p->segment == BRIG_SEGMENT_READONLY) {
|
|
// readonly memory has initialization data
|
|
uint8_t* readonlyData_old = readonlyData;
|
|
|
|
readonlyData =
|
|
new uint8_t[storageMap->getSize(BRIG_SEGMENT_READONLY)];
|
|
|
|
if (p->init) {
|
|
if ((p->type == BRIG_TYPE_ROIMG) ||
|
|
(p->type == BRIG_TYPE_WOIMG) ||
|
|
(p->type == BRIG_TYPE_SAMP) ||
|
|
(p->type == BRIG_TYPE_SIG32) ||
|
|
(p->type == BRIG_TYPE_SIG64)) {
|
|
panic("Read only data type not supported: %s\n",
|
|
getString(p->name));
|
|
}
|
|
|
|
const BrigOperand *brigOp = getOperand(p->init);
|
|
assert(brigOp->kind ==
|
|
BRIG_KIND_OPERAND_CONSTANT_BYTES);
|
|
|
|
const Brig::BrigData *operand_data M5_VAR_USED =
|
|
getBrigBaseData(((BrigOperandConstantBytes*)
|
|
brigOp)->bytes);
|
|
|
|
assert((operand_data->byteCount / 4) > 0);
|
|
|
|
uint8_t *symbol_data =
|
|
(uint8_t*)getData(((BrigOperandConstantBytes*)
|
|
brigOp)->bytes + 4);
|
|
|
|
// copy the old data and add the new data
|
|
if (readonlySize_old > 0) {
|
|
memcpy(readonlyData, readonlyData_old,
|
|
readonlySize_old);
|
|
}
|
|
|
|
memcpy(readonlyData + se->offset, symbol_data,
|
|
se->size);
|
|
|
|
delete[] readonlyData_old;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_LABEL:
|
|
{
|
|
const BrigDirectiveLabel M5_VAR_USED *p =
|
|
reinterpret_cast<const BrigDirectiveLabel*>(dirPtr);
|
|
|
|
panic("Label directives cannot be at the module level: %s\n",
|
|
getString(p->name));
|
|
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_COMMENT:
|
|
{
|
|
const BrigDirectiveComment M5_VAR_USED *p =
|
|
reinterpret_cast<const BrigDirectiveComment*>(dirPtr);
|
|
|
|
DPRINTF(HSAILObject, "DIRECTIVE_COMMENT: %s\n",
|
|
getString(p->name));
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_LOC:
|
|
{
|
|
DPRINTF(HSAILObject, "BRIG_DIRECTIVE_LOC\n");
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_MODULE:
|
|
{
|
|
const BrigDirectiveModule M5_VAR_USED *p =
|
|
reinterpret_cast<const BrigDirectiveModule*>(dirPtr);
|
|
|
|
DPRINTF(HSAILObject, "BRIG_DIRECTIVE_MODULE: %s\n",
|
|
getString(p->name));
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_CONTROL:
|
|
{
|
|
DPRINTF(HSAILObject, "DIRECTIVE_CONTROL\n");
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_PRAGMA:
|
|
{
|
|
DPRINTF(HSAILObject, "DIRECTIVE_PRAGMA\n");
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_EXTENSION:
|
|
{
|
|
DPRINTF(HSAILObject, "DIRECTIVE_EXTENSION\n");
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
|
|
{
|
|
DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_START\n");
|
|
}
|
|
break;
|
|
|
|
case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
|
|
{
|
|
DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_END\n");
|
|
}
|
|
break;
|
|
default:
|
|
if (dirPtr->kind >= BRIG_KIND_INST_BEGIN &&
|
|
dirPtr->kind <= BRIG_KIND_INST_END)
|
|
break;
|
|
|
|
if (dirPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
|
|
dirPtr->kind <= BRIG_KIND_OPERAND_END)
|
|
break;
|
|
|
|
warn("Unknown Brig directive kind: %d\n", dirPtr->kind);
|
|
break;
|
|
}
|
|
|
|
dirPtr = nextDirPtr;
|
|
}
|
|
}
|
|
|
|
HsaObject*
|
|
BrigObject::tryFile(const std::string &fname, int len, uint8_t *fileData)
|
|
{
|
|
const char *brig_ident = "HSA BRIG";
|
|
|
|
if (memcmp(brig_ident, fileData, MODULE_IDENTIFICATION_LENGTH))
|
|
return nullptr;
|
|
|
|
return new BrigObject(fname, len, fileData);
|
|
}
|
|
|
|
BrigObject::BrigObject(const std::string &fname, int len, uint8_t *fileData)
|
|
: HsaObject(fname), storageMap(new StorageMap())
|
|
{
|
|
const char *brig_ident = "HSA BRIG";
|
|
BrigModuleHeader *mod_hdr = (BrigModuleHeader*)fileData;
|
|
|
|
fatal_if(memcmp(brig_ident, mod_hdr, MODULE_IDENTIFICATION_LENGTH),
|
|
"%s is not a BRIG file\n", fname);
|
|
|
|
if (mod_hdr->brigMajor != BRIG_VERSION_BRIG_MAJOR ||
|
|
mod_hdr->brigMinor != BRIG_VERSION_BRIG_MINOR) {
|
|
fatal("%s: BRIG version mismatch, %d.%d != %d.%d\n",
|
|
fname, mod_hdr->brigMajor, mod_hdr->brigMinor,
|
|
BRIG_VERSION_BRIG_MAJOR, BRIG_VERSION_BRIG_MINOR);
|
|
}
|
|
|
|
fatal_if(mod_hdr->sectionCount != NumSectionIndices, "%s: BRIG section "
|
|
"count (%d) != expected value (%d)\n", fname,
|
|
mod_hdr->sectionCount, NumSectionIndices);
|
|
|
|
for (int i = 0; i < NumSectionIndices; ++i) {
|
|
sectionInfo[i].ptr = nullptr;
|
|
}
|
|
|
|
uint64_t *sec_idx_table = (uint64_t*)(fileData + mod_hdr->sectionIndex);
|
|
for (int sec_idx = 0; sec_idx < mod_hdr->sectionCount; ++sec_idx) {
|
|
uint8_t *sec_hdr_byte_ptr = fileData + sec_idx_table[sec_idx];
|
|
BrigSectionHeader *sec_hdr = (BrigSectionHeader*)sec_hdr_byte_ptr;
|
|
|
|
// It doesn't look like cprintf supports string precision values,
|
|
// but if this breaks, the right answer is to fix that
|
|
DPRINTF(HSAILObject, "found section %.*s\n", sec_hdr->nameLength,
|
|
sec_hdr->name);
|
|
|
|
sectionInfo[sec_idx].ptr = new uint8_t[sec_hdr->byteCount];
|
|
memcpy(sectionInfo[sec_idx].ptr, sec_hdr_byte_ptr, sec_hdr->byteCount);
|
|
sectionInfo[sec_idx].size = sec_hdr->byteCount;
|
|
}
|
|
|
|
BrigSectionHeader *code_hdr =
|
|
(BrigSectionHeader*)sectionInfo[CodeSectionIndex].ptr;
|
|
|
|
DPRINTF(HSAILObject, "Code section hdr, count: %d, hdr count: %d, "
|
|
"name len: %d\n", code_hdr->byteCount, code_hdr->headerByteCount,
|
|
code_hdr->nameLength);
|
|
|
|
// start at offset 4 to skip initial null entry (see Brig spec)
|
|
processDirectives(getCodeSectionEntry(code_hdr->headerByteCount),
|
|
getCodeSectionEntry(sectionInfo[CodeSectionIndex].size),
|
|
storageMap);
|
|
|
|
delete[] fileData;
|
|
|
|
DPRINTF(HSALoader, "BRIG object %s loaded.\n", fname);
|
|
}
|
|
|
|
BrigObject::~BrigObject()
|
|
{
|
|
for (int i = 0; i < NumSectionIndices; ++i)
|
|
if (sectionInfo[i].ptr)
|
|
delete[] sectionInfo[i].ptr;
|
|
}
|