gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
brig_object.cc
Go to the documentation of this file.
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, Anthony Gutierrez
34  */
35 
37 
38 #include <fcntl.h>
39 #include <sys/mman.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42 
43 #include <cassert>
44 #include <cstddef>
45 #include <cstdlib>
46 
47 #include "arch/hsail/Brig.h"
48 #include "base/misc.hh"
49 #include "base/trace.hh"
50 #include "debug/BRIG.hh"
51 #include "debug/HSAILObject.hh"
52 #include "debug/HSALoader.hh"
53 
54 using namespace Brig;
55 
58 
60 
61 const char *BrigObject::sectionNames[] =
62 {
63  "hsa_data",
64  "hsa_code",
65  "hsa_operand",
66  ".shstrtab"
67 };
68 
69 const char *segmentNames[] =
70 {
71  "none",
72  "flat",
73  "global",
74  "readonly",
75  "kernarg",
76  "group",
77  "private",
78  "spill",
79  "args"
80 };
81 
82 const uint8_t*
83 BrigObject::getSectionOffset(enum SectionIndex sec, int offs) const
84 {
85  // allow offs == size for dummy end pointers
86  assert(offs <= sectionInfo[sec].size);
87 
88  return sectionInfo[sec].ptr + offs;
89 }
90 
91 const char*
92 BrigObject::getString(int offs) const
93 {
94  return (const char*)(getSectionOffset(DataSectionIndex, offs) + 4);
95 }
96 
97 const BrigBase*
99 {
100  return (const BrigBase*)getSectionOffset(CodeSectionIndex, offs);
101 }
102 
103 const BrigData*
105 {
106  return (Brig::BrigData*)(getSectionOffset(DataSectionIndex, offs));
107 }
108 
109 const uint8_t*
110 BrigObject::getData(int offs) const
111 {
112  return getSectionOffset(DataSectionIndex, offs);
113 }
114 
115 const BrigOperand*
116 BrigObject::getOperand(int offs) const
117 {
118  return (const BrigOperand*)getSectionOffset(OperandsSectionIndex, offs);
119 }
120 
121 unsigned
122 BrigObject::getOperandPtr(int offs, int index) const
123 {
124  unsigned *op_offs = (unsigned*)(getData(offs + 4 * (index + 1)));
125 
126  return *op_offs;
127 }
128 
129 const BrigInstBase*
130 BrigObject::getInst(int offs) const
131 {
132  return (const BrigInstBase*)getSectionOffset(CodeSectionIndex, offs);
133 }
134 
135 HsaCode*
136 BrigObject::getKernel(const std::string &name) const
137 {
138  return nullptr;
139 }
140 
141 HsaCode*
142 BrigObject::getFunction(const std::string &name) const
143 {
144  for (int i = 0; i < functions.size(); ++i) {
145  if (functions[i]->name() == name) {
146  return functions[i];
147  }
148  }
149 
150  return nullptr;
151 }
152 
153 void
154 BrigObject::processDirectives(const BrigBase *dirPtr, const BrigBase *endPtr,
155  StorageMap *storageMap)
156 {
157  while (dirPtr < endPtr) {
158  if (!dirPtr->byteCount) {
159  fatal("Bad directive size 0\n");
160  }
161 
162  // calculate next pointer now so we can override it if needed
163  const BrigBase *nextDirPtr = brigNext(dirPtr);
164 
165  DPRINTF(HSAILObject, "Code section entry kind: #%x, byte count: %d\n",
166  dirPtr->kind, dirPtr->byteCount);
167 
168  switch (dirPtr->kind) {
170  {
172  reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
173 
174  DPRINTF(HSAILObject,"DIRECTIVE_FUNCTION: %s offset: "
175  "%d next: %d\n", getString(p->name),
176  p->firstCodeBlockEntry, p->nextModuleEntry);
177 
178  if (p->firstCodeBlockEntry != p->nextModuleEntry) {
179  // Function calls are not supported. We allow the BRIG
180  // object file to create stubs, but the function calls will
181  // not work properly if the application makes use of them.
182  warn("HSA function invocations are unsupported.\n");
183 
184  const char *name = getString(p->name);
185 
186  HsailCode *code_obj = nullptr;
187 
188  for (int i = 0; i < functions.size(); ++i) {
189  if (functions[i]->name() == name) {
190  code_obj = functions[i];
191  break;
192  }
193  }
194 
195  if (!code_obj) {
196  // create new local storage map for kernel-local symbols
197  code_obj = new HsailCode(name, p, this,
198  new StorageMap(storageMap));
199  functions.push_back(code_obj);
200  } else {
201  panic("Multiple definition of Function!!: %s\n",
202  getString(p->name));
203  }
204  }
205 
206  nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
207  }
208  break;
209 
211  {
212  const BrigDirectiveExecutable *p =
213  reinterpret_cast<const BrigDirectiveExecutable*>(dirPtr);
214 
215  DPRINTF(HSAILObject,"DIRECTIVE_KERNEL: %s offset: %d count: "
216  "next: %d\n", getString(p->name),
218 
219  const char *name = getString(p->name);
220 
221  if (name[0] == '&')
222  name++;
223 
224  std::string str = name;
225  char *temp;
226  int len = str.length();
227 
228  if (str[len - 1] >= 'a' && str[len - 1] <= 'z') {
229  temp = new char[str.size() + 1];
230  std::copy(str.begin(), str.end() , temp);
231  temp[str.size()] = '\0';
232  } else {
233  temp = new char[str.size()];
234  std::copy(str.begin(), str.end() - 1 , temp);
235  temp[str.size() - 1 ] = '\0';
236  }
237 
238  std::string kernel_name = temp;
239  delete[] temp;
240 
241  HsailCode *code_obj = nullptr;
242 
243  for (const auto &kernel : kernels) {
244  if (kernel->name() == kernel_name) {
245  code_obj = kernel;
246  break;
247  }
248  }
249 
250  if (!code_obj) {
251  // create new local storage map for kernel-local symbols
252  code_obj = new HsailCode(kernel_name, p, this,
253  new StorageMap(storageMap));
254 
255  kernels.push_back(code_obj);
256  }
257 
258  nextDirPtr = getCodeSectionEntry(p->nextModuleEntry);
259  }
260  break;
261 
263  {
264  const BrigDirectiveVariable *p =
265  reinterpret_cast<const BrigDirectiveVariable*>(dirPtr);
266 
267  uint64_t readonlySize_old =
268  storageMap->getSize(BRIG_SEGMENT_READONLY);
269 
270  StorageElement* se = storageMap->addSymbol(p, this);
271 
272  DPRINTF(HSAILObject, "DIRECTIVE_VARIABLE, symbol %s\n",
273  getString(p->name));
274 
275  if (p->segment == BRIG_SEGMENT_READONLY) {
276  // readonly memory has initialization data
277  uint8_t* readonlyData_old = readonlyData;
278 
279  readonlyData =
280  new uint8_t[storageMap->getSize(BRIG_SEGMENT_READONLY)];
281 
282  if (p->init) {
283  if ((p->type == BRIG_TYPE_ROIMG) ||
284  (p->type == BRIG_TYPE_WOIMG) ||
285  (p->type == BRIG_TYPE_SAMP) ||
286  (p->type == BRIG_TYPE_SIG32) ||
287  (p->type == BRIG_TYPE_SIG64)) {
288  panic("Read only data type not supported: %s\n",
289  getString(p->name));
290  }
291 
292  const BrigOperand *brigOp = getOperand(p->init);
293  assert(brigOp->kind ==
295 
296  const Brig::BrigData *operand_data M5_VAR_USED =
297  getBrigBaseData(((BrigOperandConstantBytes*)
298  brigOp)->bytes);
299 
300  assert((operand_data->byteCount / 4) > 0);
301 
302  uint8_t *symbol_data =
303  (uint8_t*)getData(((BrigOperandConstantBytes*)
304  brigOp)->bytes + 4);
305 
306  // copy the old data and add the new data
307  if (readonlySize_old > 0) {
308  memcpy(readonlyData, readonlyData_old,
309  readonlySize_old);
310  }
311 
312  memcpy(readonlyData + se->offset, symbol_data,
313  se->size);
314 
315  delete[] readonlyData_old;
316  }
317  }
318  }
319  break;
320 
322  {
324  reinterpret_cast<const BrigDirectiveLabel*>(dirPtr);
325 
326  panic("Label directives cannot be at the module level: %s\n",
327  getString(p->name));
328 
329  }
330  break;
331 
333  {
335  reinterpret_cast<const BrigDirectiveComment*>(dirPtr);
336 
337  DPRINTF(HSAILObject, "DIRECTIVE_COMMENT: %s\n",
338  getString(p->name));
339  }
340  break;
341 
343  {
344  DPRINTF(HSAILObject, "BRIG_DIRECTIVE_LOC\n");
345  }
346  break;
347 
349  {
351  reinterpret_cast<const BrigDirectiveModule*>(dirPtr);
352 
353  DPRINTF(HSAILObject, "BRIG_DIRECTIVE_MODULE: %s\n",
354  getString(p->name));
355  }
356  break;
357 
359  {
360  DPRINTF(HSAILObject, "DIRECTIVE_CONTROL\n");
361  }
362  break;
363 
365  {
366  DPRINTF(HSAILObject, "DIRECTIVE_PRAGMA\n");
367  }
368  break;
369 
371  {
372  DPRINTF(HSAILObject, "DIRECTIVE_EXTENSION\n");
373  }
374  break;
375 
377  {
378  DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_START\n");
379  }
380  break;
381 
383  {
384  DPRINTF(HSAILObject, "DIRECTIVE_ARG_BLOCK_END\n");
385  }
386  break;
387  default:
388  if (dirPtr->kind >= BRIG_KIND_INST_BEGIN &&
389  dirPtr->kind <= BRIG_KIND_INST_END)
390  break;
391 
392  if (dirPtr->kind >= BRIG_KIND_OPERAND_BEGIN &&
393  dirPtr->kind <= BRIG_KIND_OPERAND_END)
394  break;
395 
396  warn("Unknown Brig directive kind: %d\n", dirPtr->kind);
397  break;
398  }
399 
400  dirPtr = nextDirPtr;
401  }
402 }
403 
404 HsaObject*
405 BrigObject::tryFile(const std::string &fname, int len, uint8_t *fileData)
406 {
407  const char *brig_ident = "HSA BRIG";
408 
409  if (memcmp(brig_ident, fileData, MODULE_IDENTIFICATION_LENGTH))
410  return nullptr;
411 
412  return new BrigObject(fname, len, fileData);
413 }
414 
415 BrigObject::BrigObject(const std::string &fname, int len, uint8_t *fileData)
416  : HsaObject(fname), storageMap(new StorageMap())
417 {
418  const char *brig_ident = "HSA BRIG";
419  BrigModuleHeader *mod_hdr = (BrigModuleHeader*)fileData;
420 
421  fatal_if(memcmp(brig_ident, mod_hdr, MODULE_IDENTIFICATION_LENGTH),
422  "%s is not a BRIG file\n", fname);
423 
424  if (mod_hdr->brigMajor != BRIG_VERSION_BRIG_MAJOR ||
425  mod_hdr->brigMinor != BRIG_VERSION_BRIG_MINOR) {
426  fatal("%s: BRIG version mismatch, %d.%d != %d.%d\n",
427  fname, mod_hdr->brigMajor, mod_hdr->brigMinor,
429  }
430 
431  fatal_if(mod_hdr->sectionCount != NumSectionIndices, "%s: BRIG section "
432  "count (%d) != expected value (%d)\n", fname,
433  mod_hdr->sectionCount, NumSectionIndices);
434 
435  for (int i = 0; i < NumSectionIndices; ++i) {
436  sectionInfo[i].ptr = nullptr;
437  }
438 
439  uint64_t *sec_idx_table = (uint64_t*)(fileData + mod_hdr->sectionIndex);
440  for (int sec_idx = 0; sec_idx < mod_hdr->sectionCount; ++sec_idx) {
441  uint8_t *sec_hdr_byte_ptr = fileData + sec_idx_table[sec_idx];
442  BrigSectionHeader *sec_hdr = (BrigSectionHeader*)sec_hdr_byte_ptr;
443 
444  // It doesn't look like cprintf supports string precision values,
445  // but if this breaks, the right answer is to fix that
446  DPRINTF(HSAILObject, "found section %.*s\n", sec_hdr->nameLength,
447  sec_hdr->name);
448 
449  sectionInfo[sec_idx].ptr = new uint8_t[sec_hdr->byteCount];
450  memcpy(sectionInfo[sec_idx].ptr, sec_hdr_byte_ptr, sec_hdr->byteCount);
451  sectionInfo[sec_idx].size = sec_hdr->byteCount;
452  }
453 
454  BrigSectionHeader *code_hdr =
456 
457  DPRINTF(HSAILObject, "Code section hdr, count: %d, hdr count: %d, "
458  "name len: %d\n", code_hdr->byteCount, code_hdr->headerByteCount,
459  code_hdr->nameLength);
460 
461  // start at offset 4 to skip initial null entry (see Brig spec)
464  storageMap);
465 
466  delete[] fileData;
467 
468  DPRINTF(HSALoader, "BRIG object %s loaded.\n", fname);
469 }
470 
472 {
473  for (int i = 0; i < NumSectionIndices; ++i)
474  if (sectionInfo[i].ptr)
475  delete[] sectionInfo[i].ptr;
476 }
#define DPRINTF(x,...)
Definition: trace.hh:212
int getSize(Brig::BrigSegment segment)
Definition: hsail_code.cc:378
Bitfield< 30, 0 > index
const Brig::BrigOperand * getOperand(int offs) const
Definition: brig_object.cc:116
const std::string & name()
Definition: trace.cc:49
Bitfield< 7 > i
Definition: miscregs.hh:1378
const Brig::BrigInstBase * getInst(int offs) const
Definition: brig_object.cc:130
uint16_t byteCount
Definition: Brig.h:1179
#define panic(...)
Definition: misc.hh:153
int getBrigDataTypeBytes(BrigType16_t t)
Definition: hsail_code.cc:253
StorageElement * addSymbol(const Brig::BrigDirectiveVariable *sym, const BrigObject *obj)
Definition: hsail_code.cc:367
const char * segmentNames[]
Definition: brig_object.cc:69
StorageMap * storageMap
Definition: brig_object.hh:97
BrigOperandOffset32_t init
Definition: Brig.h:1290
uint32_t nameLength
Definition: Brig.h:1570
BrigObject(const std::string &fname, int len, uint8_t *fileData)
Definition: brig_object.cc:415
uint16_t BrigType16_t
Definition: Brig.h:142
SectionInfo sectionInfo[NumSectionIndices]
Definition: brig_object.hh:82
STL vector class.
Definition: stl.hh:40
const uint8_t * getData(int offs) const
Definition: brig_object.cc:110
BrigKind16_t kind
Definition: Brig.h:1180
BrigVersion32_t brigMajor
Definition: Brig.h:1578
#define warn(...)
Definition: misc.hh:219
const char * getString(int offs) const
Definition: brig_object.cc:92
T * brigNext(T *ptr)
Definition: brig_object.hh:125
uint8_t name[1]
Definition: Brig.h:1571
BrigVersion32_t brigMinor
Definition: Brig.h:1579
static const char * sectionNames[]
Definition: brig_object.hh:71
uint64_t offset
Definition: hsail_code.hh:227
#define fatal(...)
Definition: misc.hh:163
HsaCode * getFunction(const std::string &name) const override
Definition: brig_object.cc:142
uint64_t sectionIndex
Definition: Brig.h:1584
HsaCode * getKernel(const std::string &name) const override
Definition: brig_object.cc:136
static HsaObject * tryFile(const std::string &fname, int len, uint8_t *fileData)
Definition: brig_object.cc:405
uint32_t headerByteCount
Definition: Brig.h:1569
const Brig::BrigBase * getCodeSectionEntry(int offs) const
Definition: brig_object.cc:98
uint64_t size
Definition: hsail_code.hh:229
void processDirectives(const Brig::BrigBase *dirPtr, const Brig::BrigBase *endPtr, StorageMap *storageMap)
Definition: brig_object.cc:154
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:83
unsigned getOperandPtr(int offs, int index) const
Definition: brig_object.cc:122
int size()
Definition: pagetable.hh:146
const Brig::BrigData * getBrigBaseData(int offs) const
Definition: brig_object.cc:104
BrigSegment8_t segment
Definition: Brig.h:1299
BrigCodeOffset32_t nextModuleEntry
Definition: Brig.h:1242
uint32_t sectionCount
Definition: Brig.h:1583
static std::vector< std::function< HsaObject *(const std::string &, int, uint8_t *)> > tryFileFuncs
Definition: hsa_object.hh:58
Bitfield< 18, 16 > len
Definition: miscregs.hh:1626
BrigDataOffsetString32_t name
Definition: Brig.h:1289
uint64_t byteCount
Definition: Brig.h:1568
Bitfield< 5 > t
Definition: miscregs.hh:1382
fatal_if(p->js_features.size() > 16,"Too many job slot feature registers specified (%i)\n", p->js_features.size())
BrigDataOffsetString32_t name
Definition: Brig.h:1237
Bitfield< 0 > p
BrigCodeOffset32_t firstCodeBlockEntry
Definition: Brig.h:1241
const uint8_t * getSectionOffset(enum SectionIndex sec, int offs) const
Definition: brig_object.cc:83

Generated on Fri Jun 9 2017 13:03:47 for gem5 by doxygen 1.8.6