hsail_code.cc revision 12888
12086SN/A/* 22086SN/A * Copyright (c) 2012-2015 Advanced Micro Devices, Inc. 35268Sksewell@umich.edu * All rights reserved. 42086SN/A * 52086SN/A * For use for simulation and test purposes only 62086SN/A * 72086SN/A * Redistribution and use in source and binary forms, with or without 82086SN/A * modification, are permitted provided that the following conditions are met: 92086SN/A * 102086SN/A * 1. Redistributions of source code must retain the above copyright notice, 112086SN/A * this list of conditions and the following disclaimer. 122086SN/A * 132086SN/A * 2. Redistributions in binary form must reproduce the above copyright notice, 142086SN/A * this list of conditions and the following disclaimer in the documentation 152086SN/A * and/or other materials provided with the distribution. 162086SN/A * 172086SN/A * 3. Neither the name of the copyright holder nor the names of its contributors 182086SN/A * may be used to endorse or promote products derived from this software 192086SN/A * without specific prior written permission. 202086SN/A * 212086SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 222086SN/A * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 232086SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 242086SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 252086SN/A * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 262086SN/A * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 272086SN/A * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 282665Ssaidi@eecs.umich.edu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 292665Ssaidi@eecs.umich.edu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 302665Ssaidi@eecs.umich.edu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 312686Sksewell@umich.edu * POSSIBILITY OF SUCH DAMAGE. 322086SN/A * 334202Sbinkertn@umich.edu * Author: Steve Reinhardt 342086SN/A */ 354202Sbinkertn@umich.edu 368775Sgblack@eecs.umich.edu#include "gpu-compute/hsail_code.hh" 378758Sgblack@eecs.umich.edu 384202Sbinkertn@umich.edu#include "arch/gpu_types.hh" 398775Sgblack@eecs.umich.edu#include "arch/hsail/Brig.h" 408745Sgblack@eecs.umich.edu#include "arch/hsail/operand.hh" 416313Sgblack@eecs.umich.edu#include "config/the_gpu_isa.hh" 428775Sgblack@eecs.umich.edu#include "debug/BRIG.hh" 438775Sgblack@eecs.umich.edu#include "debug/HSAILObject.hh" 448775Sgblack@eecs.umich.edu#include "gpu-compute/brig_object.hh" 458758Sgblack@eecs.umich.edu#include "gpu-compute/gpu_static_inst.hh" 468775Sgblack@eecs.umich.edu#include "gpu-compute/kernel_cfg.hh" 478758Sgblack@eecs.umich.edu 488775Sgblack@eecs.umich.eduusing namespace Brig; 498775Sgblack@eecs.umich.edu 504997Sgblack@eecs.umich.eduint getBrigDataTypeBytes(BrigType16_t t); 514202Sbinkertn@umich.edu 528758Sgblack@eecs.umich.eduHsailCode::HsailCode(const std::string &name_str) 534997Sgblack@eecs.umich.edu : HsaCode(name_str), private_size(-1), readonly_size(-1) 548745Sgblack@eecs.umich.edu{ 558775Sgblack@eecs.umich.edu} 564997Sgblack@eecs.umich.edu 575192Ssaidi@eecs.umich.eduvoid 588775Sgblack@eecs.umich.eduHsailCode::init(const BrigDirectiveExecutable *code_dir, const BrigObject *obj, 592086SN/A StorageMap *objStorageMap) 604202Sbinkertn@umich.edu{ 614202Sbinkertn@umich.edu storageMap = objStorageMap; 624202Sbinkertn@umich.edu 634202Sbinkertn@umich.edu // set pointer so that decoding process can find this kernel context when 644202Sbinkertn@umich.edu // needed 654202Sbinkertn@umich.edu 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