source: CLRX/CLRadeonExtender/trunk/tests/amdbin/ROCmBinGen.cpp @ 3724

Last change on this file since 3724 was 3724, checked in by matszpk, 2 years ago

CLRadeonExtender: ROCmBinGen: Integrate ROCm metadata generator (untested) with ROCmBinGenerator.

File size: 6.0 KB
Line 
1/*
2 *  CLRadeonExtender - Unofficial OpenCL Radeon Extensions Library
3 *  Copyright (C) 2014-2018 Mateusz Szpakowski
4 *
5 *  This library is free software; you can redistribute it and/or
6 *  modify it under the terms of the GNU Lesser General Public
7 *  License as published by the Free Software Foundation; either
8 *  version 2.1 of the License, or (at your option) any later version.
9 *
10 *  This library is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 *  Lesser General Public License for more details.
14 *
15 *  You should have received a copy of the GNU Lesser General Public
16 *  License along with this library; if not, write to the Free Software
17 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18 */
19
20#include <CLRX/Config.h>
21#include <iostream>
22#include <sstream>
23#include <memory>
24#include <CLRX/utils/Containers.h>
25#include <CLRX/amdbin/ROCmBinaries.h>
26
27using namespace CLRX;
28
29static const char* origBinaryFiles[3] =
30{
31    CLRX_SOURCE_DIR "/tests/amdbin/rocmbins/consttest1-kaveri.hsaco.regen",
32    CLRX_SOURCE_DIR "/tests/amdbin/rocmbins/rijndael.hsaco.regen",
33    CLRX_SOURCE_DIR "/tests/amdbin/rocmbins/vectoradd-rocm.clo.regen"
34};
35
36static ROCmInput genROCmInput(const ROCmBinary& binary)
37{
38    uint32_t archMajor = 0;
39    ROCmInput rocmInput;
40    rocmInput.eflags = ULEV(binary.getHeader().e_flags);
41    // try to get comment
42    try
43    {
44        const auto& commentHdr = binary.getSectionHeader(".comment");
45        rocmInput.commentSize = ULEV(commentHdr.sh_size);
46        rocmInput.comment = (const char*)binary.getSectionContent(".comment");
47    }
48    catch(...)
49    {
50        rocmInput.commentSize = 0;
51        rocmInput.comment = nullptr;
52    }
53    rocmInput.archMinor = 0;
54    rocmInput.archStepping = 0;
55    rocmInput.target = binary.getTarget();
56    rocmInput.metadataSize = binary.getMetadataSize();
57    rocmInput.metadata = binary.getMetadata();
58    rocmInput.newBinFormat = binary.isNewBinaryFormat();
59    rocmInput.globalDataSize = binary.getGlobalDataSize();
60    rocmInput.globalData = binary.getGlobalData();
61    rocmInput.useMetadataInfo = false;
62   
63    {
64        // load .note to determine architecture (major, minor and stepping)
65        const cxbyte* noteContent = (const cxbyte*)binary.getNotes();
66        if (noteContent==nullptr)
67            throw Exception("Missing notes in inner binary!");
68        size_t notesSize = binary.getNotesSize();
69        // find note about AMDGPU
70        for (size_t offset = 0; offset < notesSize; )
71        {
72            const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
73            size_t namesz = ULEV(nhdr->n_namesz);
74            size_t descsz = ULEV(nhdr->n_descsz);
75            if (usumGt(offset, namesz+descsz, notesSize))
76                throw Exception("Note offset+size out of range");
77            if (ULEV(nhdr->n_type) == 0x3 && namesz==4 && descsz>=0x1a &&
78                ::strcmp((const char*)noteContent+offset+sizeof(Elf64_Nhdr), "AMD")==0)
79            {    // AMDGPU type
80                const uint32_t* content = (const uint32_t*)
81                        (noteContent+offset+sizeof(Elf64_Nhdr) + 4);
82                archMajor = ULEV(content[1]);
83                rocmInput.archMinor = ULEV(content[2]);
84                rocmInput.archStepping = ULEV(content[3]);
85            }
86            size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
87            offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
88        }
89    }
90    // determine device type
91    rocmInput.deviceType = GPUDeviceType::CAPE_VERDE;
92    if (archMajor==0)
93        rocmInput.deviceType = GPUDeviceType::CAPE_VERDE;
94    else if (archMajor==7)
95        rocmInput.deviceType = GPUDeviceType::BONAIRE;
96    else if (archMajor==8)
97        rocmInput.deviceType = GPUDeviceType::ICELAND;
98    else if (archMajor==9)
99        rocmInput.deviceType = GPUDeviceType::GFX900;
100    // set main code to input
101    rocmInput.codeSize = binary.getCodeSize();
102    rocmInput.code = binary.getCode();
103   
104    // get ROCm symbol
105    const size_t codeOffset = binary.getCode()-binary.getBinaryCode();
106    for (size_t i = 0; i < binary.getRegionsNum(); i++)
107    {
108        const ROCmRegion& region = binary.getRegion(i);
109        rocmInput.symbols.push_back({region.regionName, region.offset-codeOffset,
110                    region.size, region.type});
111    }
112    return rocmInput;
113}
114
115static void testOrigBinary(cxuint testCase, const char* origBinaryFilename)
116{
117    Array<cxbyte> inputData;
118    Array<cxbyte> output;
119    std::string origBinFilenameStr(origBinaryFilename);
120    filesystemPath(origBinFilenameStr); // convert to system path (native separators)
121   
122    // load input binary
123    inputData = loadDataFromFile(origBinFilenameStr.c_str());
124    ROCmBinary rocmBin(inputData.size(), inputData.data(), 0);
125    // generate input from binary
126    ROCmInput rocmInput = genROCmInput(rocmBin);
127    ROCmBinGenerator binGen(&rocmInput);
128    binGen.generate(output);
129   
130    // compare generated output with input
131    if (output.size() != inputData.size())
132    {
133        std::ostringstream oss;
134            oss << "Failed for #" << testCase << " file=" << origBinaryFilename <<
135                    ": expectedSize=" << inputData.size() <<
136                    ", resultSize=" << output.size();
137        throw Exception(oss.str());
138    }
139    for (size_t i = 0; i < inputData.size(); i++)
140        if (output[i] != inputData[i])
141        {
142            std::ostringstream oss;
143            oss << "Failed for #" << testCase << " file=" << origBinaryFilename <<
144                    ": byte=" << i;
145            throw Exception(oss.str());
146        }
147}
148
149int main(int argc, const char** argv)
150{
151    int retVal = 0;
152    for (cxuint i = 0; i < sizeof(origBinaryFiles)/sizeof(const char*); i++)
153        try
154        { testOrigBinary(i, origBinaryFiles[i]); }
155        catch(const std::exception& ex)
156        {
157            std::cerr << ex.what() << std::endl;
158            retVal = 1;
159        }
160    return retVal;
161}
Note: See TracBrowser for help on using the repository browser.