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#ifndef __HSAIL_CODE_HH__ 37#define __HSAIL_CODE_HH__ 38 39#include <cassert> 40#include <list> 41#include <map> 42#include <string> 43#include <vector> 44 45#include "arch/gpu_decoder.hh" 46#include "arch/hsail/Brig.h" 47#include "base/addr_range_map.hh" 48#include "base/intmath.hh" 49#include "config/the_gpu_isa.hh" 50#include "gpu-compute/hsa_code.hh" 51#include "gpu-compute/hsa_kernel_info.hh" 52#include "gpu-compute/misc.hh" 53 54class BrigObject; 55class GPUStaticInst; 56 57inline int 58popcount(uint64_t src, int sz) 59{ 60 int cnt = 0; 61 62 for (int i = 0; i < sz; ++i) { 63 if (src & 1) 64 ++cnt; 65 src >>= 1; 66 } 67 68 return cnt; 69} 70 71inline int 72firstbit(uint64_t src, int sz) 73{ 74 int i; 75 76 for (i = 0; i < sz; ++i) { 77 if (src & 1) 78 break; 79 src >>= 1; 80 } 81 82 return i; 83} 84 85inline int 86lastbit(uint64_t src, int sz) 87{ 88 int i0 = -1; 89 90 for (int i = 0; i < sz; ++i) { 91 if (src & 1) 92 i0 = i; 93 src >>= 1; 94 } 95 96 return i0; 97} 98 99inline int 100signbit(uint64_t src, int sz) 101{ 102 int i0 = -1; 103 104 if (src & (1 << (sz - 1))) { 105 for (int i = 0; i < sz - 1; ++i) { 106 if (!(src & 1)) 107 i0 = i; 108 src >>= 1; 109 } 110 } else { 111 for (int i = 0; i < sz - 1; ++i) { 112 if (src & 1) 113 i0 = i; 114 src >>= 1; 115 } 116 } 117 118 return i0; 119} 120 121inline uint64_t 122bitrev(uint64_t src, int sz) 123{ 124 uint64_t r = 0; 125 126 for (int i = 0; i < sz; ++i) { 127 r <<= 1; 128 if (src & 1) 129 r |= 1; 130 src >>= 1; 131 } 132 133 return r; 134} 135 136inline uint64_t 137mul_hi(uint32_t a, uint32_t b) 138{ 139 return ((uint64_t)a * (uint64_t)b) >> 32; 140} 141 142inline uint64_t 143mul_hi(int32_t a, int32_t b) 144{ 145 return ((int64_t)a * (int64_t)b) >> 32; 146} 147 148inline uint64_t 149mul_hi(uint64_t a, uint64_t b) 150{ 151 return ((uint64_t)a * (uint64_t)b) >> 32; 152} 153 154inline uint64_t 155mul_hi(int64_t a, int64_t b) 156{ 157 return ((int64_t)a * (int64_t)b) >> 32; 158} 159 160inline uint64_t 161mul_hi(double a, double b) 162{ 163 return 0; 164} 165 166class Label 167{ 168 public: 169 std::string name; 170 int value; 171 172 Label() : value(-1) 173 { 174 } 175 176 bool defined() { return value != -1; } 177 178 void 179 checkName(std::string &_name) 180 { 181 if (name.empty()) { 182 name = _name; 183 } else { 184 assert(name == _name); 185 } 186 } 187 188 void 189 define(std::string &_name, int _value) 190 { 191 assert(!defined()); 192 assert(_value != -1); 193 value = _value; 194 checkName(_name); 195 } 196 197 int 198 get() 199 { 200 assert(defined()); 201 return value; 202 } 203}; 204 205class LabelMap 206{ 207 std::map<std::string, Label> map; 208 209 public: 210 LabelMap() { } 211 212 void addLabel(const Brig::BrigDirectiveLabel *lbl, int inst_index, 213 const BrigObject *obj); 214 215 Label *refLabel(const Brig::BrigDirectiveLabel *lbl, 216 const BrigObject *obj); 217}; 218 219const int NumSegments = Brig::BRIG_SEGMENT_AMD_GCN; 220 221extern const char *segmentNames[]; 222 223class StorageElement 224{ 225 public: 226 std::string name; 227 uint64_t offset; 228 229 uint64_t size; 230 const Brig::BrigDirectiveVariable *brigSymbol; 231 StorageElement(const char *_name, uint64_t _offset, int _size, 232 const Brig::BrigDirectiveVariable *sym) 233 : name(_name), offset(_offset), size(_size), brigSymbol(sym) 234 { 235 } 236}; 237 238class StorageSpace 239{ 240 typedef std::map<const Brig::BrigDirectiveVariable*, StorageElement*> 241 DirVarToSE_map; 242 243 std::list<StorageElement*> elements; 244 AddrRangeMap<StorageElement*> elements_by_addr; 245 DirVarToSE_map elements_by_brigptr; 246 247 uint64_t nextOffset; 248 249 public: 250 StorageSpace(Brig::BrigSegment _class) : nextOffset(0) 251 { 252 } 253 254 StorageElement *addSymbol(const Brig::BrigDirectiveVariable *sym, 255 const BrigObject *obj); 256 257 StorageElement* findSymbol(std::string name); 258 StorageElement* findSymbol(uint64_t addr); 259 StorageElement* findSymbol(const Brig::BrigDirectiveVariable *brigptr); 260 261 int getSize() { return nextOffset; } 262 void resetOffset() { nextOffset = 0; } 263}; 264 265class StorageMap 266{ 267 StorageMap *outerScopeMap; 268 StorageSpace *space[NumSegments]; 269 270 public: 271 StorageMap(StorageMap *outerScope = nullptr); 272 273 StorageElement *addSymbol(const Brig::BrigDirectiveVariable *sym, 274 const BrigObject *obj); 275 276 StorageElement* findSymbol(Brig::BrigSegment segment, std::string name); 277 StorageElement* findSymbol(Brig::BrigSegment segment, uint64_t addr); 278 279 StorageElement* findSymbol(Brig::BrigSegment segment, 280 const Brig::BrigDirectiveVariable *brigptr); 281 282 // overloaded version to avoid casting 283 StorageElement* 284 findSymbol(Brig::BrigSegment8_t segment, std::string name) 285 { 286 return findSymbol((Brig::BrigSegment)segment, name); 287 } 288 289 int getSize(Brig::BrigSegment segment); 290 void resetOffset(Brig::BrigSegment segment); 291}; 292 293typedef enum 294{ 295 BT_DEFAULT, 296 BT_B8, 297 BT_U8, 298 BT_U16, 299 BT_U32, 300 BT_U64, 301 BT_S8, 302 BT_S16, 303 BT_S32, 304 BT_S64, 305 BT_F16, 306 BT_F32, 307 BT_F64, 308 BT_NULL 309} base_type_e; 310 311/* @class HsailCode 312 * the HsailCode class is used to store information 313 * about HSA kernels stored in the BRIG format. it holds 314 * all information about a kernel, function, or variable 315 * symbol and provides methods for accessing that 316 * information. 317 */ 318 319class HsailCode final : public HsaCode 320{ 321 public: 322 TheGpuISA::Decoder decoder; 323 324 StorageMap *storageMap; 325 LabelMap labelMap; 326 uint32_t kernarg_start; 327 uint32_t kernarg_end; 328 int32_t private_size; 329 330 int32_t readonly_size; 331 332 // We track the maximum register index used for each register 333 // class when we load the code so we can size the register files 334 // appropriately (i.e., one more than the max index). 335 uint32_t max_creg; // maximum c-register index 336 uint32_t max_sreg; // maximum s-register index 337 uint32_t max_dreg; // maximum d-register index 338 339 HsailCode(const std::string &name_str, 340 const Brig::BrigDirectiveExecutable *code_dir, 341 const BrigObject *obj, 342 StorageMap *objStorageMap); 343 344 // this version is used to create a placeholder when 345 // we encounter a kernel-related directive before the 346 // kernel itself 347 HsailCode(const std::string &name_str); 348 349 void init(const Brig::BrigDirectiveExecutable *code_dir, 350 const BrigObject *obj, StorageMap *objStorageMap); 351 352 void 353 generateHsaKernelInfo(HsaKernelInfo *hsaKernelInfo) const 354 { 355 hsaKernelInfo->sRegCount = max_sreg + 1; 356 hsaKernelInfo->dRegCount = max_dreg + 1; 357 hsaKernelInfo->cRegCount = max_creg + 1; 358 359 hsaKernelInfo->static_lds_size = getSize(Brig::BRIG_SEGMENT_GROUP); 360 361 hsaKernelInfo->private_mem_size = 362 roundUp(getSize(Brig::BRIG_SEGMENT_PRIVATE), 8); 363 364 hsaKernelInfo->spill_mem_size = 365 roundUp(getSize(Brig::BRIG_SEGMENT_SPILL), 8); 366 } 367 368 int 369 getSize(MemorySegment segment) const 370 { 371 Brig::BrigSegment brigSeg; 372 373 switch (segment) { 374 case MemorySegment::NONE: 375 brigSeg = Brig::BRIG_SEGMENT_NONE; 376 break; 377 case MemorySegment::FLAT: 378 brigSeg = Brig::BRIG_SEGMENT_FLAT; 379 break; 380 case MemorySegment::GLOBAL: 381 brigSeg = Brig::BRIG_SEGMENT_GLOBAL; 382 break; 383 case MemorySegment::READONLY: 384 brigSeg = Brig::BRIG_SEGMENT_READONLY; 385 break; 386 case MemorySegment::KERNARG: 387 brigSeg = Brig::BRIG_SEGMENT_KERNARG; 388 break; 389 case MemorySegment::GROUP: 390 brigSeg = Brig::BRIG_SEGMENT_GROUP; 391 break; 392 case MemorySegment::PRIVATE: 393 brigSeg = Brig::BRIG_SEGMENT_PRIVATE; 394 break; 395 case MemorySegment::SPILL: 396 brigSeg = Brig::BRIG_SEGMENT_SPILL; 397 break; 398 case MemorySegment::ARG: 399 brigSeg = Brig::BRIG_SEGMENT_ARG; 400 break; 401 case MemorySegment::EXTSPACE0: 402 brigSeg = Brig::BRIG_SEGMENT_AMD_GCN; 403 break; 404 default: 405 fatal("Unknown BrigSegment type.\n"); 406 } 407 408 return getSize(brigSeg); 409 } 410 411 private: 412 int 413 getSize(Brig::BrigSegment segment) const 414 { 415 if (segment == Brig::BRIG_SEGMENT_PRIVATE) { 416 // with the code generated by new HSA compiler the assertion 417 // does not hold anymore.. 418 //assert(private_size != -1); 419 return private_size; 420 } else { 421 return storageMap->getSize(segment); 422 } 423 } 424 425 public: 426 StorageElement* 427 findSymbol(Brig::BrigSegment segment, uint64_t addr) 428 { 429 return storageMap->findSymbol(segment, addr); 430 } 431 432 void 433 setPrivateSize(int32_t _private_size) 434 { 435 private_size = _private_size; 436 } 437 438 Label* 439 refLabel(const Brig::BrigDirectiveLabel *lbl, const BrigObject *obj) 440 { 441 return labelMap.refLabel(lbl, obj); 442 } 443}; 444 445#endif // __HSAIL_CODE_HH__ 446