mem: Use the new unbound port reporting mechanism in the mem ports.
[gem5.git] / src / gpu-compute / hsail_code.cc
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 #include "gpu-compute/hsail_code.hh"
37
38 #include "arch/gpu_types.hh"
39 #include "arch/hsail/Brig.h"
40 #include "arch/hsail/operand.hh"
41 #include "config/the_gpu_isa.hh"
42 #include "debug/BRIG.hh"
43 #include "debug/HSAILObject.hh"
44 #include "gpu-compute/brig_object.hh"
45 #include "gpu-compute/gpu_static_inst.hh"
46 #include "gpu-compute/kernel_cfg.hh"
47
48 using namespace Brig;
49
50 int getBrigDataTypeBytes(BrigType16_t t);
51
52 HsailCode::HsailCode(const std::string &name_str)
53 : HsaCode(name_str), private_size(-1), readonly_size(-1)
54 {
55 }
56
57 void
58 HsailCode::init(const BrigDirectiveExecutable *code_dir, const BrigObject *obj,
59 StorageMap *objStorageMap)
60 {
61 storageMap = objStorageMap;
62
63 // set pointer so that decoding process can find this kernel context when
64 // needed
65 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
218 HsailCode::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
226 void
227 LabelMap::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
241 Label*
242 LabelMap::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
252 int
253 getBrigDataTypeBytes(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
287 StorageElement*
288 StorageSpace::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
319 StorageElement*
320 StorageSpace::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
331 StorageElement*
332 StorageSpace::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
345 StorageElement*
346 StorageSpace::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
359 StorageMap::StorageMap(StorageMap *outerScope)
360 : outerScopeMap(outerScope)
361 {
362 for (int i = 0; i < NumSegments; ++i)
363 space[i] = new StorageSpace((BrigSegment)i);
364 }
365
366 StorageElement*
367 StorageMap::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
377 int
378 StorageMap::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
397 void
398 StorageMap::resetOffset(Brig::BrigSegment segment)
399 {
400 space[segment]->resetOffset();
401 }
402
403 StorageElement*
404 StorageMap::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
417 StorageElement*
418 StorageMap::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
439 StorageElement*
440 StorageMap::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 }