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

Last change on this file since 3674 was 3674, checked in by matszpk, 3 years ago

CLRadeonExtender: Update ROCmBinGen test: add new testcase for new binary format.

File size: 5.9 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   
62    {
63        // load .note to determine architecture (major, minor and stepping)
64        const cxbyte* noteContent = (const cxbyte*)binary.getNotes();
65        if (noteContent==nullptr)
66            throw Exception("Missing notes in inner binary!");
67        size_t notesSize = binary.getNotesSize();
68        // find note about AMDGPU
69        for (size_t offset = 0; offset < notesSize; )
70        {
71            const Elf64_Nhdr* nhdr = (const Elf64_Nhdr*)(noteContent + offset);
72            size_t namesz = ULEV(nhdr->n_namesz);
73            size_t descsz = ULEV(nhdr->n_descsz);
74            if (usumGt(offset, namesz+descsz, notesSize))
75                throw Exception("Note offset+size out of range");
76            if (ULEV(nhdr->n_type) == 0x3 && namesz==4 && descsz>=0x1a &&
77                ::strcmp((const char*)noteContent+offset+sizeof(Elf64_Nhdr), "AMD")==0)
78            {    // AMDGPU type
79                const uint32_t* content = (const uint32_t*)
80                        (noteContent+offset+sizeof(Elf64_Nhdr) + 4);
81                archMajor = ULEV(content[1]);
82                rocmInput.archMinor = ULEV(content[2]);
83                rocmInput.archStepping = ULEV(content[3]);
84            }
85            size_t align = (((namesz+descsz)&3)!=0) ? 4-((namesz+descsz)&3) : 0;
86            offset += sizeof(Elf64_Nhdr) + namesz + descsz + align;
87        }
88    }
89    // determine device type
90    rocmInput.deviceType = GPUDeviceType::CAPE_VERDE;
91    if (archMajor==0)
92        rocmInput.deviceType = GPUDeviceType::CAPE_VERDE;
93    else if (archMajor==7)
94        rocmInput.deviceType = GPUDeviceType::BONAIRE;
95    else if (archMajor==8)
96        rocmInput.deviceType = GPUDeviceType::ICELAND;
97    else if (archMajor==9)
98        rocmInput.deviceType = GPUDeviceType::GFX900;
99    // set main code to input
100    rocmInput.codeSize = binary.getCodeSize();
101    rocmInput.code = binary.getCode();
102   
103    // get ROCm symbol
104    const size_t codeOffset = binary.getCode()-binary.getBinaryCode();
105    for (size_t i = 0; i < binary.getRegionsNum(); i++)
106    {
107        const ROCmRegion& region = binary.getRegion(i);
108        rocmInput.symbols.push_back({region.regionName, region.offset-codeOffset,
109                    region.size, region.type});
110    }
111    return rocmInput;
112}
113
114static void testOrigBinary(cxuint testCase, const char* origBinaryFilename)
115{
116    Array<cxbyte> inputData;
117    Array<cxbyte> output;
118    std::string origBinFilenameStr(origBinaryFilename);
119    filesystemPath(origBinFilenameStr); // convert to system path (native separators)
120   
121    // load input binary
122    inputData = loadDataFromFile(origBinFilenameStr.c_str());
123    ROCmBinary rocmBin(inputData.size(), inputData.data(), 0);
124    // generate input from binary
125    ROCmInput rocmInput = genROCmInput(rocmBin);
126    ROCmBinGenerator binGen(&rocmInput);
127    binGen.generate(output);
128   
129    // compare generated output with input
130    if (output.size() != inputData.size())
131    {
132        std::ostringstream oss;
133            oss << "Failed for #" << testCase << " file=" << origBinaryFilename <<
134                    ": expectedSize=" << inputData.size() <<
135                    ", resultSize=" << output.size();
136        throw Exception(oss.str());
137    }
138    for (size_t i = 0; i < inputData.size(); i++)
139        if (output[i] != inputData[i])
140        {
141            std::ostringstream oss;
142            oss << "Failed for #" << testCase << " file=" << origBinaryFilename <<
143                    ": byte=" << i;
144            throw Exception(oss.str());
145        }
146}
147
148int main(int argc, const char** argv)
149{
150    int retVal = 0;
151    for (cxuint i = 0; i < sizeof(origBinaryFiles)/sizeof(const char*); i++)
152        try
153        { testOrigBinary(i, origBinaryFiles[i]); }
154        catch(const std::exception& ex)
155        {
156            std::cerr << ex.what() << std::endl;
157            retVal = 1;
158        }
159    return retVal;
160}
Note: See TracBrowser for help on using the repository browser.