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 34 */ 35 36#include "gpu-compute/hsail_code.hh" 37 38#include "arch/gpu_types.hh" 39#include "arch/hsail/Brig.h" 40#include "arch/hsail/operand.hh" 41#include "config/the_gpu_isa.hh" 42#include "debug/BRIG.hh" 43#include "debug/HSAILObject.hh" 44#include "gpu-compute/brig_object.hh" 45#include "gpu-compute/gpu_static_inst.hh" 46#include "gpu-compute/kernel_cfg.hh" 47 48using namespace Brig; 49 50int getBrigDataTypeBytes(BrigType16_t t); 51 52HsailCode::HsailCode(const std::string &name_str) 53 : HsaCode(name_str), private_size(-1), readonly_size(-1) 54{ 55} 56 57void 58HsailCode::init(const BrigDirectiveExecutable *code_dir, const BrigObject *obj, 59 StorageMap *objStorageMap) 60{ 61 storageMap = objStorageMap; 62 63 // set pointer so that decoding process can find this kernel context when 64 // needed 65 obj->currentCode = this; 66 67 if (code_dir->base.kind != BRIG_KIND_DIRECTIVE_FUNCTION && 68 code_dir->base.kind != BRIG_KIND_DIRECTIVE_KERNEL) { 69 fatal("unexpected directive kind %d inside kernel/function init\n", 70 code_dir->base.kind); 71 } 72 73 DPRINTF(HSAILObject, "Initializing code, first code block entry is: %d\n", 74 code_dir->firstCodeBlockEntry); 75 76 // clear these static vars so we can properly track the max index 77 // for this kernel 78 SRegOperand::maxRegIdx = 0; 79 DRegOperand::maxRegIdx = 0; 80 CRegOperand::maxRegIdx = 0; 81 setPrivateSize(0); 82 83 const BrigBase *entryPtr = brigNext((BrigBase*)code_dir); 84 const BrigBase *endPtr = 85 obj->getCodeSectionEntry(code_dir->nextModuleEntry); 86 87 // the instruction's byte address (relative to the base addr 88 // of the code section) 89 int inst_addr = 0; 90 // the index that points to the instruction in the instruction 91 // array 92 int inst_idx = 0; 93 std::vector<GPUStaticInst*> instructions; 94 int funcarg_size_scope = 0; 95 96 // walk through instructions in code section and directives in 97 // directive section in parallel, processing directives that apply 98 // when we reach the relevant code point. 99 while (entryPtr < endPtr) { 100 switch (entryPtr->kind) { 101 case BRIG_KIND_DIRECTIVE_VARIABLE: 102 { 103 const BrigDirectiveVariable *sym = 104 (const BrigDirectiveVariable*)entryPtr; 105 106 DPRINTF(HSAILObject,"Initializing code, directive is " 107 "kind_variable, symbol is: %s\n", 108 obj->getString(sym->name)); 109 110 StorageElement *se = storageMap->addSymbol(sym, obj); 111 112 if (sym->segment == BRIG_SEGMENT_PRIVATE) { 113 setPrivateSize(se->size); 114 } else { // spill 115 funcarg_size_scope += se->size; 116 } 117 } 118 break; 119 120 case BRIG_KIND_DIRECTIVE_LABEL: 121 { 122 const BrigDirectiveLabel *lbl = 123 (const BrigDirectiveLabel*)entryPtr; 124 125 DPRINTF(HSAILObject,"Initializing code, directive is " 126 "kind_label, label is: %s \n", 127 obj->getString(lbl->name)); 128 129 labelMap.addLabel(lbl, inst_addr, obj); 130 } 131 break; 132 133 case BRIG_KIND_DIRECTIVE_PRAGMA: 134 { 135 DPRINTF(HSAILObject, "Initializing code, directive " 136 "is kind_pragma\n"); 137 } 138 break; 139 140 case BRIG_KIND_DIRECTIVE_COMMENT: 141 { 142 DPRINTF(HSAILObject, "Initializing code, directive is " 143 "kind_comment\n"); 144 } 145 break; 146 147 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START: 148 { 149 DPRINTF(HSAILObject, "Initializing code, directive is " 150 "kind_arg_block_start\n"); 151 152 storageMap->resetOffset(BRIG_SEGMENT_ARG); 153 funcarg_size_scope = 0; 154 } 155 break; 156 157 case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END: 158 { 159 DPRINTF(HSAILObject, "Initializing code, directive is " 160 "kind_arg_block_end\n"); 161 162 funcarg_size = funcarg_size < funcarg_size_scope ? 163 funcarg_size_scope : funcarg_size; 164 } 165 break; 166 167 case BRIG_KIND_DIRECTIVE_END: 168 DPRINTF(HSAILObject, "Initializing code, dircetive is " 169 "kind_end\n"); 170 171 break; 172 173 default: 174 if (entryPtr->kind >= BRIG_KIND_INST_BEGIN && 175 entryPtr->kind <= BRIG_KIND_INST_END) { 176 177 BrigInstBase *instPtr = (BrigInstBase*)entryPtr; 178 TheGpuISA::MachInst machInst = { instPtr, obj }; 179 GPUStaticInst *iptr = decoder.decode(machInst); 180 181 if (iptr) { 182 DPRINTF(HSAILObject, "Initializing code, processing inst " 183 "byte addr #%d idx %d: OPCODE=%d\n", inst_addr, 184 inst_idx, instPtr->opcode); 185 186 TheGpuISA::RawMachInst raw_inst = decoder.saveInst(iptr); 187 iptr->instNum(inst_idx); 188 iptr->instAddr(inst_addr); 189 _insts.push_back(raw_inst); 190 instructions.push_back(iptr); 191 } 192 inst_addr += sizeof(TheGpuISA::RawMachInst); 193 ++inst_idx; 194 } else if (entryPtr->kind >= BRIG_KIND_OPERAND_BEGIN && 195 entryPtr->kind < BRIG_KIND_OPERAND_END) { 196 warn("unexpected operand entry in code segment\n"); 197 } else { 198 // there are surely some more cases we will need to handle, 199 // but we'll deal with them as we find them. 200 fatal("unexpected directive kind %d inside kernel scope\n", 201 entryPtr->kind); 202 } 203 } 204 205 entryPtr = brigNext(entryPtr); 206 } 207 208 // compute Control Flow Graph for current kernel 209 ControlFlowInfo::assignImmediatePostDominators(instructions); 210 211 max_sreg = SRegOperand::maxRegIdx; 212 max_dreg = DRegOperand::maxRegIdx; 213 max_creg = CRegOperand::maxRegIdx; 214 215 obj->currentCode = nullptr; 216} 217 218HsailCode::HsailCode(const std::string &name_str, 219 const BrigDirectiveExecutable *code_dir, 220 const BrigObject *obj, StorageMap *objStorageMap) 221 : HsaCode(name_str), private_size(-1), readonly_size(-1) 222{ 223 init(code_dir, obj, objStorageMap); 224} 225 226void 227LabelMap::addLabel(const Brig::BrigDirectiveLabel *lblDir, int inst_index, 228 const BrigObject *obj) 229{ 230 std::string lbl_name = obj->getString(lblDir->name); 231 Label &lbl = map[lbl_name]; 232 233 if (lbl.defined()) { 234 fatal("Attempt to redefine existing label %s\n", lbl_name); 235 } 236 237 lbl.define(lbl_name, inst_index); 238 DPRINTF(HSAILObject, "label %s = %d\n", lbl_name, inst_index); 239} 240 241Label* 242LabelMap::refLabel(const Brig::BrigDirectiveLabel *lblDir, 243 const BrigObject *obj) 244{ 245 std::string name = obj->getString(lblDir->name); 246 Label &lbl = map[name]; 247 lbl.checkName(name); 248 249 return &lbl; 250} 251 252int 253getBrigDataTypeBytes(BrigType16_t t) 254{ 255 switch (t) { 256 case BRIG_TYPE_S8: 257 case BRIG_TYPE_U8: 258 case BRIG_TYPE_B8: 259 return 1; 260 261 case BRIG_TYPE_S16: 262 case BRIG_TYPE_U16: 263 case BRIG_TYPE_B16: 264 case BRIG_TYPE_F16: 265 return 2; 266 267 case BRIG_TYPE_S32: 268 case BRIG_TYPE_U32: 269 case BRIG_TYPE_B32: 270 case BRIG_TYPE_F32: 271 return 4; 272 273 case BRIG_TYPE_S64: 274 case BRIG_TYPE_U64: 275 case BRIG_TYPE_B64: 276 case BRIG_TYPE_F64: 277 return 8; 278 279 case BRIG_TYPE_B1: 280 281 default: 282 fatal("unhandled symbol data type %d", t); 283 return 0; 284 } 285} 286 287StorageElement* 288StorageSpace::addSymbol(const BrigDirectiveVariable *sym, 289 const BrigObject *obj) 290{ 291 const char *sym_name = obj->getString(sym->name); 292 uint64_t size = 0; 293 uint64_t offset = 0; 294 295 if (sym->type & BRIG_TYPE_ARRAY) { 296 size = getBrigDataTypeBytes(sym->type & ~BRIG_TYPE_ARRAY); 297 size *= (((uint64_t)sym->dim.hi) << 32 | (uint64_t)sym->dim.lo); 298 299 offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type & 300 ~BRIG_TYPE_ARRAY)); 301 } else { 302 size = getBrigDataTypeBytes(sym->type); 303 offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type)); 304 } 305 306 nextOffset = offset + size; 307 308 DPRINTF(HSAILObject, "Adding SYMBOL %s size %d offset %#x, init: %d\n", 309 sym_name, size, offset, sym->init); 310 311 StorageElement* se = new StorageElement(sym_name, offset, size, sym); 312 elements.push_back(se); 313 elements_by_addr.insert(AddrRange(offset, offset + size - 1), se); 314 elements_by_brigptr[sym] = se; 315 316 return se; 317} 318 319StorageElement* 320StorageSpace::findSymbol(std::string name) 321{ 322 for (auto it : elements) { 323 if (it->name == name) { 324 return it; 325 } 326 } 327 328 return nullptr; 329} 330 331StorageElement* 332StorageSpace::findSymbol(uint64_t addr) 333{ 334 assert(elements_by_addr.size() > 0); 335 336 auto se = elements_by_addr.contains(addr); 337 338 if (se == elements_by_addr.end()) { 339 return nullptr; 340 } else { 341 return se->second; 342 } 343} 344 345StorageElement* 346StorageSpace::findSymbol(const BrigDirectiveVariable *brigptr) 347{ 348 assert(elements_by_brigptr.size() > 0); 349 350 auto se = elements_by_brigptr.find(brigptr); 351 352 if (se == elements_by_brigptr.end()) { 353 return nullptr; 354 } else { 355 return se->second; 356 } 357} 358 359StorageMap::StorageMap(StorageMap *outerScope) 360 : outerScopeMap(outerScope) 361{ 362 for (int i = 0; i < NumSegments; ++i) 363 space[i] = new StorageSpace((BrigSegment)i); 364} 365 366StorageElement* 367StorageMap::addSymbol(const BrigDirectiveVariable *sym, const BrigObject *obj) 368{ 369 BrigSegment8_t segment = sym->segment; 370 371 assert(segment >= Brig::BRIG_SEGMENT_FLAT); 372 assert(segment < NumSegments); 373 374 return space[segment]->addSymbol(sym, obj); 375} 376 377int 378StorageMap::getSize(Brig::BrigSegment segment) 379{ 380 assert(segment > Brig::BRIG_SEGMENT_GLOBAL); 381 assert(segment < NumSegments); 382 383 if (segment != Brig::BRIG_SEGMENT_GROUP && 384 segment != Brig::BRIG_SEGMENT_READONLY) { 385 return space[segment]->getSize(); 386 } else { 387 int ret = space[segment]->getSize(); 388 389 if (outerScopeMap) { 390 ret += outerScopeMap->getSize(segment); 391 } 392 393 return ret; 394 } 395} 396 397void 398StorageMap::resetOffset(Brig::BrigSegment segment) 399{ 400 space[segment]->resetOffset(); 401} 402 403StorageElement* 404StorageMap::findSymbol(BrigSegment segment, std::string name) 405{ 406 StorageElement *se = space[segment]->findSymbol(name); 407 408 if (se) 409 return se; 410 411 if (outerScopeMap) 412 return outerScopeMap->findSymbol(segment, name); 413 414 return nullptr; 415} 416 417StorageElement* 418StorageMap::findSymbol(Brig::BrigSegment segment, uint64_t addr) 419{ 420 StorageSpace *sp = space[segment]; 421 422 if (!sp) { 423 // there is no memory in segment? 424 return nullptr; 425 } 426 427 StorageElement *se = sp->findSymbol(addr); 428 429 if (se) 430 return se; 431 432 if (outerScopeMap) 433 return outerScopeMap->findSymbol(segment, addr); 434 435 return nullptr; 436 437} 438 439StorageElement* 440StorageMap::findSymbol(Brig::BrigSegment segment, 441 const BrigDirectiveVariable *brigptr) 442{ 443 StorageSpace *sp = space[segment]; 444 445 if (!sp) { 446 // there is no memory in segment? 447 return nullptr; 448 } 449 450 StorageElement *se = sp->findSymbol(brigptr); 451 452 if (se) 453 return se; 454 455 if (outerScopeMap) 456 return outerScopeMap->findSymbol(segment, brigptr); 457 458 return nullptr; 459 460} 461