2 * Copyright (c) 2012-2015 Advanced Micro Devices, Inc.
5 * For use for simulation and test purposes only
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
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.
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.
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.
33 * Author: Steve Reinhardt
36 #ifndef __HSAIL_CODE_HH__
37 #define __HSAIL_CODE_HH__
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"
58 popcount(uint64_t src, int sz)
62 for (int i = 0; i < sz; ++i) {
72 firstbit(uint64_t src, int sz)
76 for (i = 0; i < sz; ++i) {
86 lastbit(uint64_t src, int sz)
90 for (int i = 0; i < sz; ++i) {
100 signbit(uint64_t src, int sz)
104 if (src & (1 << (sz - 1))) {
105 for (int i = 0; i < sz - 1; ++i) {
111 for (int i = 0; i < sz - 1; ++i) {
122 bitrev(uint64_t src, int sz)
126 for (int i = 0; i < sz; ++i) {
137 mul_hi(uint32_t a, uint32_t b)
139 return ((uint64_t)a * (uint64_t)b) >> 32;
143 mul_hi(int32_t a, int32_t b)
145 return ((int64_t)a * (int64_t)b) >> 32;
149 mul_hi(uint64_t a, uint64_t b)
151 return ((uint64_t)a * (uint64_t)b) >> 32;
155 mul_hi(int64_t a, int64_t b)
157 return ((int64_t)a * (int64_t)b) >> 32;
161 mul_hi(double a, double b)
176 bool defined() { return value != -1; }
179 checkName(std::string &_name)
184 assert(name == _name);
189 define(std::string &_name, int _value)
192 assert(_value != -1);
207 std::map<std::string, Label> map;
212 void addLabel(const Brig::BrigDirectiveLabel *lbl, int inst_index,
213 const BrigObject *obj);
215 Label *refLabel(const Brig::BrigDirectiveLabel *lbl,
216 const BrigObject *obj);
219 const int NumSegments = Brig::BRIG_SEGMENT_AMD_GCN;
221 extern const char *segmentNames[];
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)
240 typedef std::map<const Brig::BrigDirectiveVariable*, StorageElement*>
243 std::list<StorageElement*> elements;
244 AddrRangeMap<StorageElement*> elements_by_addr;
245 DirVarToSE_map elements_by_brigptr;
250 StorageSpace(Brig::BrigSegment _class) : nextOffset(0)
254 StorageElement *addSymbol(const Brig::BrigDirectiveVariable *sym,
255 const BrigObject *obj);
257 StorageElement* findSymbol(std::string name);
258 StorageElement* findSymbol(uint64_t addr);
259 StorageElement* findSymbol(const Brig::BrigDirectiveVariable *brigptr);
261 int getSize() { return nextOffset; }
262 void resetOffset() { nextOffset = 0; }
267 StorageMap *outerScopeMap;
268 StorageSpace *space[NumSegments];
271 StorageMap(StorageMap *outerScope = nullptr);
273 StorageElement *addSymbol(const Brig::BrigDirectiveVariable *sym,
274 const BrigObject *obj);
276 StorageElement* findSymbol(Brig::BrigSegment segment, std::string name);
277 StorageElement* findSymbol(Brig::BrigSegment segment, uint64_t addr);
279 StorageElement* findSymbol(Brig::BrigSegment segment,
280 const Brig::BrigDirectiveVariable *brigptr);
282 // overloaded version to avoid casting
284 findSymbol(Brig::BrigSegment8_t segment, std::string name)
286 return findSymbol((Brig::BrigSegment)segment, name);
289 int getSize(Brig::BrigSegment segment);
290 void resetOffset(Brig::BrigSegment segment);
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
319 class HsailCode final : public HsaCode
322 TheGpuISA::Decoder decoder;
324 StorageMap *storageMap;
326 uint32_t kernarg_start;
327 uint32_t kernarg_end;
328 int32_t private_size;
330 int32_t readonly_size;
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
339 HsailCode(const std::string &name_str,
340 const Brig::BrigDirectiveExecutable *code_dir,
341 const BrigObject *obj,
342 StorageMap *objStorageMap);
344 // this version is used to create a placeholder when
345 // we encounter a kernel-related directive before the
347 HsailCode(const std::string &name_str);
349 void init(const Brig::BrigDirectiveExecutable *code_dir,
350 const BrigObject *obj, StorageMap *objStorageMap);
353 generateHsaKernelInfo(HsaKernelInfo *hsaKernelInfo) const
355 hsaKernelInfo->sRegCount = max_sreg + 1;
356 hsaKernelInfo->dRegCount = max_dreg + 1;
357 hsaKernelInfo->cRegCount = max_creg + 1;
359 hsaKernelInfo->static_lds_size = getSize(Brig::BRIG_SEGMENT_GROUP);
361 hsaKernelInfo->private_mem_size =
362 roundUp(getSize(Brig::BRIG_SEGMENT_PRIVATE), 8);
364 hsaKernelInfo->spill_mem_size =
365 roundUp(getSize(Brig::BRIG_SEGMENT_SPILL), 8);
369 getSize(MemorySegment segment) const
371 Brig::BrigSegment brigSeg;
374 case MemorySegment::NONE:
375 brigSeg = Brig::BRIG_SEGMENT_NONE;
377 case MemorySegment::FLAT:
378 brigSeg = Brig::BRIG_SEGMENT_FLAT;
380 case MemorySegment::GLOBAL:
381 brigSeg = Brig::BRIG_SEGMENT_GLOBAL;
383 case MemorySegment::READONLY:
384 brigSeg = Brig::BRIG_SEGMENT_READONLY;
386 case MemorySegment::KERNARG:
387 brigSeg = Brig::BRIG_SEGMENT_KERNARG;
389 case MemorySegment::GROUP:
390 brigSeg = Brig::BRIG_SEGMENT_GROUP;
392 case MemorySegment::PRIVATE:
393 brigSeg = Brig::BRIG_SEGMENT_PRIVATE;
395 case MemorySegment::SPILL:
396 brigSeg = Brig::BRIG_SEGMENT_SPILL;
398 case MemorySegment::ARG:
399 brigSeg = Brig::BRIG_SEGMENT_ARG;
401 case MemorySegment::EXTSPACE0:
402 brigSeg = Brig::BRIG_SEGMENT_AMD_GCN;
405 fatal("Unknown BrigSegment type.\n");
408 return getSize(brigSeg);
413 getSize(Brig::BrigSegment segment) const
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);
421 return storageMap->getSize(segment);
427 findSymbol(Brig::BrigSegment segment, uint64_t addr)
429 return storageMap->findSymbol(segment, addr);
433 setPrivateSize(int32_t _private_size)
435 private_size = _private_size;
439 refLabel(const Brig::BrigDirectiveLabel *lbl, const BrigObject *obj)
441 return labelMap.refLabel(lbl, obj);
445 #endif // __HSAIL_CODE_HH__