brig_object.cc revision 11308
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)); 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 } 202 203 } 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} 475