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