1//===------- unittests/Plugins/NextgenPluginsTest.cpp - Plugin tests ------===//
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 "Shared/PluginAPI.h"
10#include "omptarget.h"
11#include "gtest/gtest.h"
12
13#include <unordered_set>
14
15const int DEVICE_ID = 0;
16std::unordered_set<int> setup_map;
17
18int init_test_device(int ID) {
19 if (setup_map.find(x: ID) != setup_map.end()) {
20 return OFFLOAD_SUCCESS;
21 }
22 if (__tgt_rtl_init_plugin() == OFFLOAD_FAIL ||
23 __tgt_rtl_init_device(ID) == OFFLOAD_FAIL) {
24 return OFFLOAD_FAIL;
25 }
26 setup_map.insert(x: ID);
27 return OFFLOAD_SUCCESS;
28}
29
30// Test plugin initialization
31TEST(NextgenPluginsTest, PluginInit) {
32 EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID));
33}
34
35// Test GPU allocation and R/W
36TEST(NextgenPluginsTest, PluginAlloc) {
37 int32_t test_value = 23;
38 int32_t host_value = -1;
39 int64_t var_size = sizeof(int32_t);
40
41 // Init plugin and device
42 EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID));
43
44 // Allocate memory
45 void *device_ptr =
46 __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr, TARGET_ALLOC_DEFAULT);
47
48 // Check that the result is not null
49 EXPECT_NE(device_ptr, nullptr);
50
51 // Submit data to device
52 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_submit(DEVICE_ID, device_ptr,
53 &test_value, var_size));
54
55 // Read data from device
56 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_retrieve(DEVICE_ID, &host_value,
57 device_ptr, var_size));
58
59 // Compare values
60 EXPECT_EQ(host_value, test_value);
61
62 // Cleanup data
63 EXPECT_EQ(OFFLOAD_SUCCESS,
64 __tgt_rtl_data_delete(DEVICE_ID, device_ptr, TARGET_ALLOC_DEFAULT));
65}
66
67// Test async GPU allocation and R/W
68TEST(NextgenPluginsTest, PluginAsyncAlloc) {
69 int32_t test_value = 47;
70 int32_t host_value = -1;
71 int64_t var_size = sizeof(int32_t);
72 __tgt_async_info *info;
73
74 // Init plugin and device
75 EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID));
76
77 // Check if device supports async
78 // Platforms like x86_64 don't support it
79 if (__tgt_rtl_init_async_info(DEVICE_ID, &info) == OFFLOAD_SUCCESS) {
80 // Allocate memory
81 void *device_ptr = __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr,
82 TARGET_ALLOC_DEFAULT);
83
84 // Check that the result is not null
85 EXPECT_NE(device_ptr, nullptr);
86
87 // Submit data to device asynchronously
88 EXPECT_EQ(OFFLOAD_SUCCESS,
89 __tgt_rtl_data_submit_async(DEVICE_ID, device_ptr, &test_value,
90 var_size, info));
91
92 // Wait for async request to process
93 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_synchronize(DEVICE_ID, info));
94
95 // Read data from device
96 EXPECT_EQ(OFFLOAD_SUCCESS,
97 __tgt_rtl_data_retrieve_async(DEVICE_ID, &host_value, device_ptr,
98 var_size, info));
99
100 // Wait for async request to process
101 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_synchronize(DEVICE_ID, info));
102
103 // Compare values
104 EXPECT_EQ(host_value, test_value);
105
106 // Cleanup data
107 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_ID, device_ptr,
108 TARGET_ALLOC_DEFAULT));
109 }
110}
111
112// Test GPU data exchange
113TEST(NextgenPluginsTest, PluginDataSwap) {
114 int32_t test_value = 23;
115 int32_t host_value = -1;
116 int64_t var_size = sizeof(int32_t);
117
118 // Look for compatible device
119 int DEVICE_TWO = -1;
120 for (int i = 1; i < __tgt_rtl_number_of_devices(); i++) {
121 if (__tgt_rtl_is_data_exchangable(DEVICE_ID, i)) {
122 DEVICE_TWO = i;
123 break;
124 }
125 }
126
127 // Only run test if we have multiple GPUs to test
128 // GPUs must be compatible for test to work
129 if (DEVICE_TWO >= 1) {
130 // Init both GPUs
131 EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(ID: DEVICE_ID));
132 EXPECT_EQ(OFFLOAD_SUCCESS, init_test_device(DEVICE_TWO));
133
134 // Allocate memory on both GPUs
135 // DEVICE_ID will be the source
136 // DEVICE_TWO will be the destination
137 void *source_ptr = __tgt_rtl_data_alloc(DEVICE_ID, var_size, nullptr,
138 TARGET_ALLOC_DEFAULT);
139 void *dest_ptr = __tgt_rtl_data_alloc(DEVICE_TWO, var_size, nullptr,
140 TARGET_ALLOC_DEFAULT);
141
142 // Check for success in allocation
143 EXPECT_NE(source_ptr, nullptr);
144 EXPECT_NE(dest_ptr, nullptr);
145
146 // Write data to source
147 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_submit(DEVICE_ID, source_ptr,
148 &test_value, var_size));
149
150 // Transfer data between devices
151 EXPECT_EQ(OFFLOAD_SUCCESS,
152 __tgt_rtl_data_exchange(DEVICE_ID, source_ptr, DEVICE_TWO,
153 dest_ptr, var_size));
154
155 // Read from destination device (DEVICE_TWO) memory
156 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_retrieve(DEVICE_TWO, &host_value,
157 dest_ptr, var_size));
158
159 // Ensure match
160 EXPECT_EQ(host_value, test_value);
161
162 // Cleanup
163 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_ID, source_ptr,
164 TARGET_ALLOC_DEFAULT));
165 EXPECT_EQ(OFFLOAD_SUCCESS, __tgt_rtl_data_delete(DEVICE_TWO, dest_ptr,
166 TARGET_ALLOC_DEFAULT));
167 }
168}
169

source code of offload/unittests/Plugins/NextgenPluginsTest.cpp