1//===------- Offload API tests - gtest environment ------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Environment.hpp"
10#include "Fixtures.hpp"
11#include "llvm/Support/CommandLine.h"
12#include "llvm/Support/MemoryBuffer.h"
13#include <OffloadAPI.h>
14#include <fstream>
15
16using namespace llvm;
17
18// Wrapper so we don't have to constantly init and shutdown Offload in every
19// test, while having sensible lifetime for the platform environment
20struct OffloadInitWrapper {
21 OffloadInitWrapper() { olInit(); }
22 ~OffloadInitWrapper() { olShutDown(); }
23};
24static OffloadInitWrapper Wrapper{};
25
26static cl::opt<std::string>
27 SelectedPlatform("platform", cl::desc("Only test the specified platform"),
28 cl::value_desc("platform"));
29
30raw_ostream &operator<<(raw_ostream &Out,
31 const ol_platform_handle_t &Platform) {
32 size_t Size;
33 olGetPlatformInfoSize(Platform, OL_PLATFORM_INFO_NAME, &Size);
34 std::vector<char> Name(Size);
35 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_NAME, Size, Name.data());
36 Out << Name.data();
37 return Out;
38}
39
40raw_ostream &operator<<(raw_ostream &Out, const ol_device_handle_t &Device) {
41 size_t Size;
42 olGetDeviceInfoSize(Device, OL_DEVICE_INFO_NAME, &Size);
43 std::vector<char> Name(Size);
44 olGetDeviceInfo(Device, OL_DEVICE_INFO_NAME, Size, Name.data());
45 Out << Name.data();
46 return Out;
47}
48
49void printPlatforms() {
50 SmallDenseSet<ol_platform_handle_t> Platforms;
51 using DeviceVecT = SmallVector<ol_device_handle_t, 8>;
52 DeviceVecT Devices{};
53
54 olIterateDevices(
55 [](ol_device_handle_t D, void *Data) {
56 static_cast<DeviceVecT *>(Data)->push_back(D);
57 return true;
58 },
59 &Devices);
60
61 for (auto &Device : Devices) {
62 ol_platform_handle_t Platform;
63 olGetDeviceInfo(Device, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),
64 &Platform);
65 Platforms.insert(Platform);
66 }
67
68 for (const auto &Platform : Platforms) {
69 errs() << " * " << Platform << "\n";
70 }
71}
72
73const std::vector<TestEnvironment::Device> &TestEnvironment::getDevices() {
74 static std::vector<TestEnvironment::Device> Devices{};
75 if (Devices.empty()) {
76 // If a specific platform is requested, filter to devices belonging to it.
77 if (const char *EnvStr = getenv(name: "OFFLOAD_UNITTEST_PLATFORM")) {
78 if (SelectedPlatform != "")
79 errs() << "Warning: --platform argument ignored as "
80 "OFFLOAD_UNITTEST_PLATFORM env var overrides it.\n";
81 SelectedPlatform = EnvStr;
82 }
83
84 if (SelectedPlatform != "") {
85 olIterateDevices(
86 [](ol_device_handle_t D, void *Data) {
87 ol_platform_handle_t Platform;
88 olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),
89 &Platform);
90 ol_platform_backend_t Backend;
91 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,
92 sizeof(Backend), &Backend);
93 std::string PlatformName;
94 raw_string_ostream S(PlatformName);
95 S << Platform;
96 if (PlatformName == SelectedPlatform &&
97 Backend != OL_PLATFORM_BACKEND_HOST) {
98 std::string Name;
99 raw_string_ostream NameStr(Name);
100 NameStr << PlatformName << "_" << D;
101 static_cast<std::vector<TestEnvironment::Device> *>(Data)
102 ->push_back({D, Name});
103 }
104 return true;
105 },
106 &Devices);
107 } else {
108 // No platform specified, discover every device that isn't the host.
109 olIterateDevices(
110 [](ol_device_handle_t D, void *Data) {
111 ol_platform_handle_t Platform;
112 olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),
113 &Platform);
114 ol_platform_backend_t Backend;
115 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,
116 sizeof(Backend), &Backend);
117 if (Backend != OL_PLATFORM_BACKEND_HOST) {
118 std::string Name;
119 raw_string_ostream NameStr(Name);
120 NameStr << Platform << "_" << D;
121 static_cast<std::vector<TestEnvironment::Device> *>(Data)
122 ->push_back({D, Name});
123 }
124 return true;
125 },
126 &Devices);
127 }
128 }
129
130 return Devices;
131}
132
133ol_device_handle_t TestEnvironment::getHostDevice() {
134 static ol_device_handle_t HostDevice = nullptr;
135
136 if (!HostDevice) {
137 olIterateDevices(
138 [](ol_device_handle_t D, void *Data) {
139 ol_platform_handle_t Platform;
140 olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),
141 &Platform);
142 ol_platform_backend_t Backend;
143 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND, sizeof(Backend),
144 &Backend);
145
146 if (Backend == OL_PLATFORM_BACKEND_HOST) {
147 *(static_cast<ol_device_handle_t *>(Data)) = D;
148 return false;
149 }
150
151 return true;
152 },
153 &HostDevice);
154 }
155
156 return HostDevice;
157}
158
159// TODO: Allow overriding via cmd line arg
160const std::string DeviceBinsDirectory = DEVICE_CODE_PATH;
161
162bool TestEnvironment::loadDeviceBinary(
163 const std::string &BinaryName, ol_device_handle_t Device,
164 std::unique_ptr<MemoryBuffer> &BinaryOut) {
165
166 // Get the platform type
167 ol_platform_handle_t Platform;
168 olGetDeviceInfo(Device, OL_DEVICE_INFO_PLATFORM, sizeof(Platform), &Platform);
169 ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN;
170 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND, sizeof(Backend),
171 &Backend);
172 std::string FileExtension;
173 if (Backend == OL_PLATFORM_BACKEND_AMDGPU) {
174 FileExtension = ".amdgpu.bin";
175 } else if (Backend == OL_PLATFORM_BACKEND_CUDA) {
176 FileExtension = ".nvptx64.bin";
177 } else {
178 errs() << "Unsupported platform type for a device binary test.\n";
179 return false;
180 }
181
182 std::string SourcePath =
183 DeviceBinsDirectory + "/" + BinaryName + FileExtension;
184
185 auto SourceFile = MemoryBuffer::getFile(Filename: SourcePath, IsText: false, RequiresNullTerminator: false);
186 if (!SourceFile) {
187 errs() << "failed to read device binary file: " + SourcePath;
188 return false;
189 }
190
191 BinaryOut = std::move(SourceFile.get());
192 return true;
193}
194

source code of offload/unittests/OffloadAPI/common/Environment.cpp