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