systemc: Handle suspended processes and handle sensitivity overload.
[gem5.git] / src / gpu-compute / hsail_code.hh
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
54 class BrigObject;
55 class GPUStaticInst;
56
57 inline int
58 popcount(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
71 inline int
72 firstbit(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
85 inline int
86 lastbit(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
99 inline int
100 signbit(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
121 inline uint64_t
122 bitrev(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
136 inline uint64_t
137 mul_hi(uint32_t a, uint32_t b)
138 {
139 return ((uint64_t)a * (uint64_t)b) >> 32;
140 }
141
142 inline uint64_t
143 mul_hi(int32_t a, int32_t b)
144 {
145 return ((int64_t)a * (int64_t)b) >> 32;
146 }
147
148 inline uint64_t
149 mul_hi(uint64_t a, uint64_t b)
150 {
151 return ((uint64_t)a * (uint64_t)b) >> 32;
152 }
153
154 inline uint64_t
155 mul_hi(int64_t a, int64_t b)
156 {
157 return ((int64_t)a * (int64_t)b) >> 32;
158 }
159
160 inline uint64_t
161 mul_hi(double a, double b)
162 {
163 return 0;
164 }
165
166 class 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
205 class 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
219 const int NumSegments = Brig::BRIG_SEGMENT_AMD_GCN;
220
221 extern const char *segmentNames[];
222
223 class 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
238 class 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
265 class 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
293 typedef 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
319 class 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__