hsail_code.cc revision 11308:7d8836fd043d
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
48using namespace Brig;
49
50int getBrigDataTypeBytes(BrigType16_t t);
51
52HsailCode::HsailCode(const std::string &name_str)
53    : HsaCode(name_str), private_size(-1), readonly_size(-1)
54{
55}
56
57void
58HsailCode::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    int inst_idx = 0;
88    std::vector<GPUStaticInst*> instructions;
89    int funcarg_size_scope = 0;
90
91    // walk through instructions in code section and directives in
92    // directive section in parallel, processing directives that apply
93    // when we reach the relevant code point.
94    while (entryPtr < endPtr) {
95        switch (entryPtr->kind) {
96          case BRIG_KIND_DIRECTIVE_VARIABLE:
97           {
98                const BrigDirectiveVariable *sym =
99                    (const BrigDirectiveVariable*)entryPtr;
100
101                DPRINTF(HSAILObject,"Initializing code, directive is "
102                        "kind_variable, symbol is: %s\n",
103                        obj->getString(sym->name));
104
105                StorageElement *se = storageMap->addSymbol(sym, obj);
106
107                if (sym->segment == BRIG_SEGMENT_PRIVATE) {
108                    setPrivateSize(se->size);
109                } else { // spill
110                    funcarg_size_scope += se->size;
111                }
112            }
113            break;
114
115          case BRIG_KIND_DIRECTIVE_LABEL:
116            {
117                const BrigDirectiveLabel *lbl =
118                    (const BrigDirectiveLabel*)entryPtr;
119
120                DPRINTF(HSAILObject,"Initializing code, directive is "
121                        "kind_label, label is: %s \n",
122                        obj->getString(lbl->name));
123
124                labelMap.addLabel(lbl, inst_idx, obj);
125            }
126            break;
127
128          case BRIG_KIND_DIRECTIVE_PRAGMA:
129            {
130                DPRINTF(HSAILObject, "Initializing code, directive "
131                        "is kind_pragma\n");
132            }
133            break;
134
135          case BRIG_KIND_DIRECTIVE_COMMENT:
136            {
137                DPRINTF(HSAILObject, "Initializing code, directive is "
138                        "kind_comment\n");
139            }
140            break;
141
142          case BRIG_KIND_DIRECTIVE_ARG_BLOCK_START:
143            {
144                DPRINTF(HSAILObject, "Initializing code, directive is "
145                        "kind_arg_block_start\n");
146
147                storageMap->resetOffset(BRIG_SEGMENT_ARG);
148                funcarg_size_scope = 0;
149            }
150            break;
151
152          case BRIG_KIND_DIRECTIVE_ARG_BLOCK_END:
153            {
154                DPRINTF(HSAILObject, "Initializing code, directive is "
155                        "kind_arg_block_end\n");
156
157                funcarg_size = funcarg_size < funcarg_size_scope ?
158                                              funcarg_size_scope : funcarg_size;
159            }
160            break;
161
162          case BRIG_KIND_DIRECTIVE_END:
163            DPRINTF(HSAILObject, "Initializing code, dircetive is "
164                    "kind_end\n");
165
166            break;
167
168          default:
169            if (entryPtr->kind >= BRIG_KIND_INST_BEGIN &&
170                entryPtr->kind <= BRIG_KIND_INST_END) {
171
172                BrigInstBase *instPtr = (BrigInstBase*)entryPtr;
173                TheGpuISA::MachInst machInst = { instPtr, obj };
174                GPUStaticInst *iptr = decoder.decode(machInst);
175
176                if (iptr) {
177                    DPRINTF(HSAILObject, "Initializing code, processing inst "
178                            "#%d idx %d: OPCODE=%d\n",
179                            inst_idx,  _insts.size(), instPtr->opcode);
180
181                    TheGpuISA::RawMachInst inst_num = decoder.saveInst(iptr);
182                    iptr->instNum(inst_idx);
183                    _insts.push_back(inst_num);
184                    instructions.push_back(iptr);
185                }
186                ++inst_idx;
187            } else if (entryPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
188                       entryPtr->kind < BRIG_KIND_OPERAND_END) {
189                warn("unexpected operand entry in code segment\n");
190            } else {
191                // there are surely some more cases we will need to handle,
192                // but we'll deal with them as we find them.
193                fatal("unexpected directive kind %d inside kernel scope\n",
194                      entryPtr->kind);
195            }
196        }
197
198        entryPtr = brigNext(entryPtr);
199    }
200
201    // compute Control Flow Graph for current kernel
202    ControlFlowInfo::assignImmediatePostDominators(instructions);
203
204    max_sreg = SRegOperand::maxRegIdx;
205    max_dreg = DRegOperand::maxRegIdx;
206    max_creg = CRegOperand::maxRegIdx;
207
208    obj->currentCode = nullptr;
209}
210
211HsailCode::HsailCode(const std::string &name_str,
212                     const BrigDirectiveExecutable *code_dir,
213                     const BrigObject *obj, StorageMap *objStorageMap)
214    : HsaCode(name_str), private_size(-1), readonly_size(-1)
215{
216    init(code_dir, obj, objStorageMap);
217}
218
219void
220LabelMap::addLabel(const Brig::BrigDirectiveLabel *lblDir, int inst_index,
221                   const BrigObject *obj)
222{
223    std::string lbl_name = obj->getString(lblDir->name);
224    Label &lbl = map[lbl_name];
225
226    if (lbl.defined()) {
227        fatal("Attempt to redefine existing label %s\n", lbl_name);
228    }
229
230    lbl.define(lbl_name, inst_index);
231    DPRINTF(HSAILObject, "label %s = %d\n", lbl_name, inst_index);
232}
233
234Label*
235LabelMap::refLabel(const Brig::BrigDirectiveLabel *lblDir,
236                   const BrigObject *obj)
237{
238    std::string name = obj->getString(lblDir->name);
239    Label &lbl = map[name];
240    lbl.checkName(name);
241
242    return &lbl;
243}
244
245int
246getBrigDataTypeBytes(BrigType16_t t)
247{
248    switch (t) {
249      case BRIG_TYPE_S8:
250      case BRIG_TYPE_U8:
251      case BRIG_TYPE_B8:
252        return 1;
253
254      case BRIG_TYPE_S16:
255      case BRIG_TYPE_U16:
256      case BRIG_TYPE_B16:
257      case BRIG_TYPE_F16:
258        return 2;
259
260      case BRIG_TYPE_S32:
261      case BRIG_TYPE_U32:
262      case BRIG_TYPE_B32:
263      case BRIG_TYPE_F32:
264        return 4;
265
266      case BRIG_TYPE_S64:
267      case BRIG_TYPE_U64:
268      case BRIG_TYPE_B64:
269      case BRIG_TYPE_F64:
270        return 8;
271
272      case BRIG_TYPE_B1:
273
274      default:
275        fatal("unhandled symbol data type %d", t);
276        return 0;
277    }
278}
279
280StorageElement*
281StorageSpace::addSymbol(const BrigDirectiveVariable *sym,
282                        const BrigObject *obj)
283{
284    const char *sym_name = obj->getString(sym->name);
285    uint64_t size = 0;
286    uint64_t offset = 0;
287
288    if (sym->type & BRIG_TYPE_ARRAY) {
289        size = getBrigDataTypeBytes(sym->type & ~BRIG_TYPE_ARRAY);
290        size *= (((uint64_t)sym->dim.hi) << 32 | (uint64_t)sym->dim.lo);
291
292        offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type &
293                         ~BRIG_TYPE_ARRAY));
294    } else {
295        size = getBrigDataTypeBytes(sym->type);
296        offset = roundUp(nextOffset, getBrigDataTypeBytes(sym->type));
297    }
298
299    nextOffset = offset + size;
300
301    DPRINTF(HSAILObject, "Adding %s SYMBOL %s size %d offset 0x%x, init: %d\n",
302            segmentNames[segment], sym_name, size, offset, sym->init);
303
304    StorageElement* se = new StorageElement(sym_name, offset, size, sym);
305    elements.push_back(se);
306    elements_by_addr.insert(AddrRange(offset, offset + size - 1), se);
307    elements_by_brigptr[sym] = se;
308
309    return se;
310}
311
312StorageElement*
313StorageSpace::findSymbol(std::string name)
314{
315    for (auto it : elements) {
316        if (it->name == name) {
317            return it;
318        }
319    }
320
321    return nullptr;
322}
323
324StorageElement*
325StorageSpace::findSymbol(uint64_t addr)
326{
327    assert(elements_by_addr.size() > 0);
328
329    auto se = elements_by_addr.find(addr);
330
331    if (se == elements_by_addr.end()) {
332        return nullptr;
333    } else {
334        return se->second;
335    }
336}
337
338StorageElement*
339StorageSpace::findSymbol(const BrigDirectiveVariable *brigptr)
340{
341    assert(elements_by_brigptr.size() > 0);
342
343    auto se = elements_by_brigptr.find(brigptr);
344
345    if (se == elements_by_brigptr.end()) {
346        return nullptr;
347    } else {
348        return se->second;
349    }
350}
351
352StorageMap::StorageMap(StorageMap *outerScope)
353    : outerScopeMap(outerScope)
354{
355    for (int i = 0; i < NumSegments; ++i)
356        space[i] = new StorageSpace((BrigSegment)i);
357}
358
359StorageElement*
360StorageMap::addSymbol(const BrigDirectiveVariable *sym, const BrigObject *obj)
361{
362    BrigSegment8_t segment = sym->segment;
363
364    assert(segment >= Brig::BRIG_SEGMENT_FLAT);
365    assert(segment < NumSegments);
366
367    return space[segment]->addSymbol(sym, obj);
368}
369
370int
371StorageMap::getSize(Brig::BrigSegment segment)
372{
373    assert(segment > Brig::BRIG_SEGMENT_GLOBAL);
374    assert(segment < NumSegments);
375
376    if (segment != Brig::BRIG_SEGMENT_GROUP &&
377        segment != Brig::BRIG_SEGMENT_READONLY) {
378        return space[segment]->getSize();
379    } else {
380        int ret = space[segment]->getSize();
381
382        if (outerScopeMap) {
383            ret += outerScopeMap->getSize(segment);
384        }
385
386        return ret;
387    }
388}
389
390void
391StorageMap::resetOffset(Brig::BrigSegment segment)
392{
393    space[segment]->resetOffset();
394}
395
396StorageElement*
397StorageMap::findSymbol(BrigSegment segment, std::string name)
398{
399    StorageElement *se = space[segment]->findSymbol(name);
400
401    if (se)
402        return se;
403
404    if (outerScopeMap)
405        return outerScopeMap->findSymbol(segment, name);
406
407    return nullptr;
408}
409
410StorageElement*
411StorageMap::findSymbol(Brig::BrigSegment segment, uint64_t addr)
412{
413    StorageSpace *sp = space[segment];
414
415    if (!sp) {
416        // there is no memory in segment?
417        return nullptr;
418    }
419
420    StorageElement *se = sp->findSymbol(addr);
421
422    if (se)
423        return se;
424
425    if (outerScopeMap)
426        return outerScopeMap->findSymbol(segment, addr);
427
428    return nullptr;
429
430}
431
432StorageElement*
433StorageMap::findSymbol(Brig::BrigSegment segment,
434                       const BrigDirectiveVariable *brigptr)
435{
436    StorageSpace *sp = space[segment];
437
438    if (!sp) {
439        // there is no memory in segment?
440        return nullptr;
441    }
442
443    StorageElement *se = sp->findSymbol(brigptr);
444
445    if (se)
446        return se;
447
448    if (outerScopeMap)
449        return outerScopeMap->findSymbol(segment, brigptr);
450
451    return nullptr;
452
453}
454