forked from Xilinx/XRT
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhip_device.cpp
More file actions
314 lines (271 loc) · 9.15 KB
/
hip_device.cpp
File metadata and controls
314 lines (271 loc) · 9.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2023-2026 Advanced Micro Devices, Inc. All rights reserved.
#include "core/include/xrt/experimental/xrt_system.h"
#include "core/common/device.h"
#include "core/common/query_requests.h"
#include "hip/core/common.h"
#include "hip/core/device.h"
#include "hip/core/module.h"
#include <cstring>
#include <mutex>
#include <string>
#ifdef _WIN32
// to disable the compiler worning C4996: 'strncpy': This function or variable may be unsafe
# pragma warning( disable : 4996)
#endif
// forward declaration
namespace xrt::core::hip {
// Defined first so it is initialized before the global x below (same
// TU order).
xrt_core::handle_map<device_handle, std::unique_ptr<device>> device_cache; //NOLINT
static void
device_init();
}
namespace {
//we should override clang-tidy warning by adding NOLINT since device_init_flag is non-const parameter
thread_local std::once_flag device_init_flag; //NOLINT
// Creates devices at library load
// User may not explicitly call init or device create
const struct X {
X() noexcept {
try {
// needed if multi threaded
// or else we can directly call enumerate_devices
std::call_once(device_init_flag, xrt::core::hip::device_init);
}
catch (...) {}
}
} x;
}
namespace xrt::core::hip {
// Function that calls xrt_coreutil library to get the total number of devices
static void
device_init()
{
auto dev_count = xrt::system::enumerate_devices();
// create all devices ahead
// Used when user doesn't explicitly create device
for (uint32_t i = 0; i < dev_count; i++) {
if (device_cache.count(static_cast<device_handle>(i)) > 0)
continue;
auto dev = std::make_unique<xrt::core::hip::device>(i);
device_cache.add(i, std::move(dev));
}
}
static void
hip_init(unsigned int flags)
{
// Flags should be zero as per Hip doc
throw_invalid_value_if(flags != 0, "non zero flags passed to hipinit");
// call device_init function, device enumeration might not have happened
// at library load because of some exception
// std::once_flag ensures init is called only once
std::call_once(device_init_flag, xrt::core::hip::device_init);
}
static int
hip_get_device_count()
{
// Get device count
auto count = xrt::core::hip::device_cache.size();
throw_if(count < 1, hipErrorNoDevice, "No valid device available");
return static_cast<int>(count);
}
inline bool
check(int dev_id)
{
return (dev_id < 0 || device_cache.count(static_cast<device_handle>(dev_id)) == 0);
}
// Returns a handle to compute device
// Throws on error
static int
hip_device_get(int ordinal)
{
throw_invalid_device_if(check(ordinal), "device requested is not available");
return ordinal;
}
static std::string
hip_device_get_name(hipDevice_t device)
{
throw_invalid_device_if(check(device), "device requested is not available");
return (xrt_core::device_query<xrt_core::query::rom_vbnv>((device_cache.get_or_error(device))->get_xrt_device().get_handle()));
}
static hipUUID
hip_device_get_uuid(hipDevice_t device)
{
throw_invalid_device_if(check(device), "device requested is not available");
hipUUID uid = {0};
auto bdf = xrt_core::device_query<xrt_core::query::pcie_bdf>((device_cache.get_or_error(device))->get_xrt_device().get_handle());
auto uuid = xrt_core::query::pcie_bdf::to_uuid(bdf);
std::memcpy(uid.bytes, uuid.get(), sizeof(uid.bytes));
return uid;
}
static void
hip_get_device_properties(hipDeviceProp_t* props, hipDevice_t device)
{
throw_invalid_value_if(!props, "arg passed is nullptr");
throw_invalid_device_if(check(device), "device requested is not available");
hipDeviceProp_t device_props = {};
auto device_handle = (device_cache.get_or_error(device))->get_xrt_device().get_handle();
// Query PCIe BDF (Bus/Device/Function) information
auto uuid = xrt_core::device_query<xrt_core::query::pcie_bdf>(device_handle);
// Query device name using rom_vbnv
// Copy device name to device_props.name, ensuring no buffer overflow
auto name_str = (xrt_core::device_query<xrt_core::query::rom_vbnv>(device_handle));
std::strncpy(device_props.name, name_str.c_str(), sizeof(device_props.name));
device_props.name[sizeof(device_props.name) - 1] = '\0';
// Extract and assign PCI domain, bus, and device IDs from the queried PCIe BDF tuple
device_props.pciDomainID = std::get<0>(uuid);
device_props.pciBusID = std::get<1>(uuid);
device_props.pciDeviceID = std::get<2>(uuid);
device_props.canMapHostMemory = 1;
device_props.computeMode = 0;
device_props.concurrentKernels = 0;
#if HIP_VERSION >= 60000000
device_props.uuid = hip_device_get_uuid(device);
// Query if compute preemption is supported
device_props.computePreemptionSupported = static_cast<int>(xrt_core::device_query<xrt_core::query::preemption>(device_handle));
#endif
*props = device_props;
}
static void
hip_device_get_attribute(int* pi, hipDeviceAttribute_t attr, int device)
{
throw_invalid_value_if(!pi, "arg passed is nullptr");
throw_invalid_device_if(check(device), "device requested is not available");
hipDeviceProp_t prop = {};
hip_get_device_properties(&prop, device);
switch (attr) {
case hipDeviceAttributeCanMapHostMemory:
*pi = prop.canMapHostMemory;
break;
case hipDeviceAttributeComputeMode:
*pi = prop.computeMode;
break;
case hipDeviceAttributeComputePreemptionSupported:
*pi = static_cast<int>(xrt_core::device_query<xrt_core::query::preemption>((device_cache.get_or_error(device))->get_xrt_device().get_handle()));
break;
case hipDeviceAttributeConcurrentKernels:
*pi = prop.concurrentKernels;
break;
case hipDeviceAttributePciBusId:
*pi = prop.pciBusID;
break;
case hipDeviceAttributePciDeviceId:
*pi = prop.pciDeviceID;
break;
case hipDeviceAttributePciDomainID:
*pi = prop.pciDomainID;
break;
default:
throw_hip_error(hipErrorInvalidValue,"unsupported attribute type");
}
}
// Sets thread default device
// Throws on error
static void
hip_set_device(int dev_id)
{
throw_invalid_device_if(check(dev_id), "device to set is not available");
tls_objs.dev_hdl = static_cast<device_handle>(dev_id);
}
const char*
hip_kernel_name_ref(const hipFunction_t f)
{
return (reinterpret_cast<function*>(f))->get_func_name().c_str();
}
} // xrt::core::hip
// =========================================================================
// Device related apis implementation
hipError_t
hipInit(unsigned int flags)
{
return handle_hip_func_error(__func__, hipErrorNotInitialized, [&] {
xrt::core::hip::hip_init(flags); });
}
hipError_t
hipGetDeviceCount(int* count)
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
throw_invalid_value_if(!count, "arg passed is nullptr");
*count = xrt::core::hip::hip_get_device_count();
});
}
hipError_t
hipDeviceGet(hipDevice_t* device, int ordinal)
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
throw_invalid_value_if(!device, "device is nullptr");
*device = xrt::core::hip::hip_device_get(ordinal);
});
}
hipError_t
hipDeviceGetName(char* name, int len, hipDevice_t device)
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
throw_invalid_value_if((!name || len <= 0), "invalid arg");
auto name_str = xrt::core::hip::hip_device_get_name(device);
// Only copy partial name if size of `dest` is smaller than size of `src` including
// trailing \0
auto cpy_size = (static_cast<size_t>(len) <= (name_str.length() + 1) ? (len - 1) : name_str.length());
std::memcpy(name, name_str.c_str(), cpy_size);
name[cpy_size] = '\0';
});
}
#if HIP_VERSION >= 60000000
#undef hipGetDeviceProperties
hipError_t
hipGetDeviceProperties(hipDeviceProp_t* props, hipDevice_t device)
{
return hipErrorNotSupported;
}
hipError_t
hipGetDevicePropertiesR0600(hipDeviceProp_tR0600* props, int device)
#else
using hipDeviceProp_tR0600 = hipDeviceProp_t;
extern "C" hipError_t
hipGetDevicePropertiesR0600(hipDeviceProp_tR0600 *props, int device)
{
return hipErrorNotSupported;
}
hipError_t
hipGetDeviceProperties(hipDeviceProp_t* props, hipDevice_t device)
#endif
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
xrt::core::hip::hip_get_device_properties(props, device);
});
}
hipError_t
hipDeviceGetUuid(hipUUID* uuid, hipDevice_t device)
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
throw_invalid_value_if(!uuid, "arg passed is nullptr");
*uuid = xrt::core::hip::hip_device_get_uuid(device);
});
}
hipError_t
hipDeviceGetAttribute(int* pi, hipDeviceAttribute_t attr, int device)
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
xrt::core::hip::hip_device_get_attribute(pi, attr, device);
});
}
hipError_t
hipSetDevice(int device)
{
return handle_hip_func_error(__func__, hipErrorRuntimeOther, [&] {
xrt::core::hip::hip_set_device(device);
});
}
const char *
hipKernelNameRef(const hipFunction_t f)
{
const char* kname_ref = nullptr;
hipError_t err = handle_hip_func_error(__func__, hipErrorInvalidValue, [&] {
throw_invalid_value_if(!f, "arg passed is nullptr");
kname_ref = xrt::core::hip::hip_kernel_name_ref(f);
});
if (err != hipSuccess)
return nullptr;
return kname_ref;
}