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;
248 Brig::BrigSegment segment;
251 StorageSpace(Brig::BrigSegment _class)
252 : nextOffset(0), segment(_class)
256 StorageElement *addSymbol(const Brig::BrigDirectiveVariable *sym,
257 const BrigObject *obj);
259 StorageElement* findSymbol(std::string name);
260 StorageElement* findSymbol(uint64_t addr);
261 StorageElement* findSymbol(const Brig::BrigDirectiveVariable *brigptr);
263 int getSize() { return nextOffset; }
264 void resetOffset() { nextOffset = 0; }
269 StorageMap *outerScopeMap;
270 StorageSpace *space[NumSegments];
273 StorageMap(StorageMap *outerScope = nullptr);
275 StorageElement *addSymbol(const Brig::BrigDirectiveVariable *sym,
276 const BrigObject *obj);
278 StorageElement* findSymbol(Brig::BrigSegment segment, std::string name);
279 StorageElement* findSymbol(Brig::BrigSegment segment, uint64_t addr);
281 StorageElement* findSymbol(Brig::BrigSegment segment,
282 const Brig::BrigDirectiveVariable *brigptr);
284 // overloaded version to avoid casting
286 findSymbol(Brig::BrigSegment8_t segment, std::string name)
288 return findSymbol((Brig::BrigSegment)segment, name);
291 int getSize(Brig::BrigSegment segment);
292 void resetOffset(Brig::BrigSegment segment);
314 * the HsailCode class is used to store information
315 * about HSA kernels stored in the BRIG format. it holds
316 * all information about a kernel, function, or variable
317 * symbol and provides methods for accessing that
321 class HsailCode final : public HsaCode
324 TheGpuISA::Decoder decoder;
326 StorageMap *storageMap;
328 uint32_t kernarg_start;
329 uint32_t kernarg_end;
330 int32_t private_size;
332 int32_t readonly_size;
334 // We track the maximum register index used for each register
335 // class when we load the code so we can size the register files
336 // appropriately (i.e., one more than the max index).
337 uint32_t max_creg; // maximum c-register index
338 uint32_t max_sreg; // maximum s-register index
339 uint32_t max_dreg; // maximum d-register index
341 HsailCode(const std::string &name_str,
342 const Brig::BrigDirectiveExecutable *code_dir,
343 const BrigObject *obj,
344 StorageMap *objStorageMap);
346 // this version is used to create a placeholder when
347 // we encounter a kernel-related directive before the
349 HsailCode(const std::string &name_str);
351 void init(const Brig::BrigDirectiveExecutable *code_dir,
352 const BrigObject *obj, StorageMap *objStorageMap);
355 generateHsaKernelInfo(HsaKernelInfo *hsaKernelInfo) const
357 hsaKernelInfo->sRegCount = max_sreg + 1;
358 hsaKernelInfo->dRegCount = max_dreg + 1;
359 hsaKernelInfo->cRegCount = max_creg + 1;
361 hsaKernelInfo->static_lds_size = getSize(Brig::BRIG_SEGMENT_GROUP);
363 hsaKernelInfo->private_mem_size =
364 roundUp(getSize(Brig::BRIG_SEGMENT_PRIVATE), 8);
366 hsaKernelInfo->spill_mem_size =
367 roundUp(getSize(Brig::BRIG_SEGMENT_SPILL), 8);
371 getSize(MemorySegment segment) const
373 Brig::BrigSegment brigSeg;
376 case MemorySegment::NONE:
377 brigSeg = Brig::BRIG_SEGMENT_NONE;
379 case MemorySegment::FLAT:
380 brigSeg = Brig::BRIG_SEGMENT_FLAT;
382 case MemorySegment::GLOBAL:
383 brigSeg = Brig::BRIG_SEGMENT_GLOBAL;
385 case MemorySegment::READONLY:
386 brigSeg = Brig::BRIG_SEGMENT_READONLY;
388 case MemorySegment::KERNARG:
389 brigSeg = Brig::BRIG_SEGMENT_KERNARG;
391 case MemorySegment::GROUP:
392 brigSeg = Brig::BRIG_SEGMENT_GROUP;
394 case MemorySegment::PRIVATE:
395 brigSeg = Brig::BRIG_SEGMENT_PRIVATE;
397 case MemorySegment::SPILL:
398 brigSeg = Brig::BRIG_SEGMENT_SPILL;
400 case MemorySegment::ARG:
401 brigSeg = Brig::BRIG_SEGMENT_ARG;
403 case MemorySegment::EXTSPACE0:
404 brigSeg = Brig::BRIG_SEGMENT_AMD_GCN;
407 fatal("Unknown BrigSegment type.\n");
410 return getSize(brigSeg);
415 getSize(Brig::BrigSegment segment) const
417 if (segment == Brig::BRIG_SEGMENT_PRIVATE) {
418 // with the code generated by new HSA compiler the assertion
419 // does not hold anymore..
420 //assert(private_size != -1);
423 return storageMap->getSize(segment);
429 findSymbol(Brig::BrigSegment segment, uint64_t addr)
431 return storageMap->findSymbol(segment, addr);
435 setPrivateSize(int32_t _private_size)
437 private_size = _private_size;
441 refLabel(const Brig::BrigDirectiveLabel *lbl, const BrigObject *obj)
443 return labelMap.refLabel(lbl, obj);
447 #endif // __HSAIL_CODE_HH__