199 lines · cpp
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-exception6//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 every19// test, while having sensible lifetime for the platform environment20#ifndef DISABLE_WRAPPER21struct OffloadInitWrapper {22 OffloadInitWrapper() { olInit(); }23 ~OffloadInitWrapper() { olShutDown(); }24};25static OffloadInitWrapper Wrapper{};26#endif27 28static cl::opt<std::string>29 SelectedPlatform("platform", cl::desc("Only test the specified platform"),30 cl::value_desc("platform"));31 32raw_ostream &operator<<(raw_ostream &Out,33 const ol_platform_handle_t &Platform) {34 size_t Size;35 olGetPlatformInfoSize(Platform, OL_PLATFORM_INFO_NAME, &Size);36 std::vector<char> Name(Size);37 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_NAME, Size, Name.data());38 Out << Name.data();39 return Out;40}41 42raw_ostream &operator<<(raw_ostream &Out, const ol_device_handle_t &Device) {43 size_t Size;44 olGetDeviceInfoSize(Device, OL_DEVICE_INFO_PRODUCT_NAME, &Size);45 std::vector<char> Name(Size);46 olGetDeviceInfo(Device, OL_DEVICE_INFO_PRODUCT_NAME, Size, Name.data());47 Out << Name.data();48 return Out;49}50 51void printPlatforms() {52 SmallDenseSet<ol_platform_handle_t> Platforms;53 using DeviceVecT = SmallVector<ol_device_handle_t, 8>;54 DeviceVecT Devices{};55 56 olIterateDevices(57 [](ol_device_handle_t D, void *Data) {58 static_cast<DeviceVecT *>(Data)->push_back(D);59 return true;60 },61 &Devices);62 63 for (auto &Device : Devices) {64 ol_platform_handle_t Platform;65 olGetDeviceInfo(Device, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),66 &Platform);67 Platforms.insert(Platform);68 }69 70 for (const auto &Platform : Platforms) {71 errs() << " * " << Platform << "\n";72 }73}74 75const std::vector<TestEnvironment::Device> &TestEnvironment::getDevices() {76 static std::vector<TestEnvironment::Device> Devices{};77 if (Devices.empty()) {78 // If a specific platform is requested, filter to devices belonging to it.79 if (const char *EnvStr = getenv("OFFLOAD_UNITTEST_PLATFORM")) {80 if (SelectedPlatform != "")81 errs() << "Warning: --platform argument ignored as "82 "OFFLOAD_UNITTEST_PLATFORM env var overrides it.\n";83 SelectedPlatform = EnvStr;84 }85 86 if (SelectedPlatform != "") {87 olIterateDevices(88 [](ol_device_handle_t D, void *Data) {89 ol_platform_handle_t Platform;90 olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),91 &Platform);92 ol_platform_backend_t Backend;93 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,94 sizeof(Backend), &Backend);95 std::string PlatformName;96 raw_string_ostream S(PlatformName);97 S << Platform;98 if (PlatformName == SelectedPlatform &&99 Backend != OL_PLATFORM_BACKEND_HOST) {100 std::string Name;101 raw_string_ostream NameStr(Name);102 NameStr << PlatformName << "_" << D;103 static_cast<std::vector<TestEnvironment::Device> *>(Data)104 ->push_back({D, Name});105 }106 return true;107 },108 &Devices);109 } else {110 // No platform specified, discover every device that isn't the host.111 olIterateDevices(112 [](ol_device_handle_t D, void *Data) {113 ol_platform_handle_t Platform;114 olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),115 &Platform);116 ol_platform_backend_t Backend;117 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND,118 sizeof(Backend), &Backend);119 if (Backend != OL_PLATFORM_BACKEND_HOST) {120 std::string Name;121 raw_string_ostream NameStr(Name);122 NameStr << Platform << "_" << D;123 static_cast<std::vector<TestEnvironment::Device> *>(Data)124 ->push_back({D, Name});125 }126 return true;127 },128 &Devices);129 }130 }131 132 if (Devices.size() == 0)133 errs() << "Warning: No devices found for OffloadAPI tests.\n";134 135 return Devices;136}137 138ol_device_handle_t TestEnvironment::getHostDevice() {139 static ol_device_handle_t HostDevice = nullptr;140 141 if (!HostDevice) {142 olIterateDevices(143 [](ol_device_handle_t D, void *Data) {144 ol_platform_handle_t Platform;145 olGetDeviceInfo(D, OL_DEVICE_INFO_PLATFORM, sizeof(Platform),146 &Platform);147 ol_platform_backend_t Backend;148 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND, sizeof(Backend),149 &Backend);150 151 if (Backend == OL_PLATFORM_BACKEND_HOST) {152 *(static_cast<ol_device_handle_t *>(Data)) = D;153 return false;154 }155 156 return true;157 },158 &HostDevice);159 }160 161 return HostDevice;162}163 164// TODO: Allow overriding via cmd line arg165const std::string DeviceBinsDirectory = DEVICE_CODE_PATH;166 167bool TestEnvironment::loadDeviceBinary(168 const std::string &BinaryName, ol_device_handle_t Device,169 std::unique_ptr<MemoryBuffer> &BinaryOut) {170 171 // Get the platform type172 ol_platform_handle_t Platform;173 olGetDeviceInfo(Device, OL_DEVICE_INFO_PLATFORM, sizeof(Platform), &Platform);174 ol_platform_backend_t Backend = OL_PLATFORM_BACKEND_UNKNOWN;175 olGetPlatformInfo(Platform, OL_PLATFORM_INFO_BACKEND, sizeof(Backend),176 &Backend);177 std::string FileExtension;178 if (Backend == OL_PLATFORM_BACKEND_AMDGPU) {179 FileExtension = ".amdgpu.bin";180 } else if (Backend == OL_PLATFORM_BACKEND_CUDA) {181 FileExtension = ".nvptx64.bin";182 } else {183 errs() << "Unsupported platform type for a device binary test.\n";184 return false;185 }186 187 std::string SourcePath =188 DeviceBinsDirectory + "/" + BinaryName + FileExtension;189 190 auto SourceFile = MemoryBuffer::getFile(SourcePath, false, false);191 if (!SourceFile) {192 errs() << "failed to read device binary file: " + SourcePath;193 return false;194 }195 196 BinaryOut = std::move(SourceFile.get());197 return true;198}199