11#include <CL/cl_ext_xilinx.h>
21 std::vector<cl::Platform> platforms;
23 ATH_CHECK(cl::Platform::get(&platforms) == CL_SUCCESS);
25 for (
const cl::Platform &platform : platforms) {
29 std::string platform_name;
30 ATH_CHECK(platform.getInfo(CL_PLATFORM_NAME, &platform_name) == CL_SUCCESS);
31 if (platform_name !=
"Xilinx") {
37 std::vector<cl::Device> devices;
38 ATH_CHECK(platform.getDevices(CL_DEVICE_TYPE_ACCELERATOR, &devices) ==
40 ATH_MSG_DEBUG(
"Found XRT/OpenCL platform '" << platform_name <<
"' with "
48 for (
const cl::Device &device : devices) {
54 std::string list_device_name;
55 ATH_CHECK(list[0].getInfo(CL_DEVICE_NAME, &list_device_name) ==
57 if (device_name == list_device_name) {
59 list.push_back(device);
64 std::vector<cl::Device> new_list = {device};
76 return StatusCode::FAILURE;
83 return StatusCode::SUCCESS;
96 return StatusCode::FAILURE;
103 "More XCLBIN file(s) specified than "
104 "devices type available ("
109 return StatusCode::FAILURE;
115 if (!std::filesystem::exists(xclbin_path)) {
116 ATH_MSG_ERROR(
"XCLBIN file does not exist: " << xclbin_path);
117 return StatusCode::FAILURE;
125 xrt::xclbin xrt_xclbin(xclbin_path);
126 xclbin_info.
path = xclbin_path;
127 xclbin_info.
xsa_name = xrt_xclbin.get_xsa_name();
129 xclbin_info.
uuid = xrt_xclbin.get_uuid().to_string();
131 for (
const xrt::xclbin::kernel &kernel : xrt_xclbin.get_kernels()) {
132 const std::string& kernelName = kernel.get_name();
138 if (!kernel.get_cus().empty()) {
142 for (
const xrt::xclbin::ip &computeUnit : kernel.get_cus()) {
143 const std::string& computeUnitName = computeUnit.get_name();
144 const std::string computeUnitIsolatedName =
145 computeUnitName.substr(kernelName.size() + 1);
147 const std::string computeUnitUsableName = kernelName +
":{" + computeUnitIsolatedName +
"}";
149 xclbin_info.
cu_names.push_back(std::move(computeUnitUsableName));
152 }
catch (
const std::exception &e) {
154 ATH_MSG_ERROR(
"Could not create xrt::xclbin from " << xclbin_path);
155 return StatusCode::FAILURE;
163 std::set<std::string> uuids;
164 std::set<std::string> fpga_device_names;
166 uuids.insert(info.uuid);
167 fpga_device_names.insert(info.fpga_device_name);
172 return StatusCode::SUCCESS;
181 cl_int err = CL_SUCCESS;
182 std::string device_name;
183 err = device.getInfo(CL_DEVICE_NAME, &device_name);
184 if (err != CL_SUCCESS) {
186 return std::string(
"error");
196 cl_int err = CL_SUCCESS;
197 std::string device_bdf;
198 err = device.getInfo(CL_DEVICE_PCIE_BDF, &device_bdf);
199 if (err != CL_SUCCESS) {
201 return std::string(
"error");
219 while (
count < n && pos != std::string::npos) {
220 pos =
str.find(token, pos + 1);
225 if (pos == std::string::npos) {
230 return str.substr(0, pos + 1);
243 const cl::Device &device)
const {
245 const std::string device_prefix =
247 const std::string xsa_prefix =
249 if (device_prefix == xsa_prefix) {
286 ATH_MSG_DEBUG(
"Case 1: One or multiple identical device(s), one xclbin");
289 ath_cl_context.
devices.push_back(device);
301 "Specified XCLBINs target multiple device types, but only one "
302 "device type is present");
303 return StatusCode::FAILURE;
312 "Case 2: Multiple identical devices, multiple identical xclbins");
327 "Case 3: Multiple identical devices, multiple different XCLBIN "
328 "files, but targeting the same device type");
343 ATH_MSG_DEBUG(
"Case 4: Multiple different devices, multiple xclbins");
345 for (
const std::vector<cl::Device> &device_type : si.
device_types) {
346 for (
const cl::Device &device : device_type) {
348 ath_cl_context.
devices.push_back(device);
351 std::vector<XclbinInfo>::iterator iter;
353 for (iter = unaffected_xclbin_infos.begin();
354 iter != unaffected_xclbin_infos.end();) {
357 iter = unaffected_xclbin_infos.erase(iter);
378 for (
const XclbinInfo &xclbin_info : unaffected_xclbin_infos) {
382 "No compatible device found for XCLBIN: " << xclbin_info.path);
386 return StatusCode::SUCCESS;
398 cl_int err = CL_SUCCESS;
403 ath_cl_context.context = std::make_shared<cl::Context>(
404 ath_cl_context.devices,
nullptr,
nullptr,
nullptr, &err);
405 if (err != CL_SUCCESS) {
407 return StatusCode::FAILURE;
413 file.open(ath_cl_context.xclbin_info.path.c_str(), std::ios::binary);
415 ATH_MSG_ERROR(
"Could not open " << ath_cl_context.xclbin_info.path
417 return StatusCode::FAILURE;
419 std::vector<char> xclbin_buffer((std::istreambuf_iterator<char>(
file)),
420 std::istreambuf_iterator<char>());
425 cl::Program::Binaries binary;
426 for (std::size_t i = 0; i < ath_cl_context.devices.size(); ++i) {
427 binary.push_back({xclbin_buffer.data(), xclbin_buffer.size()});
432 ath_cl_context.program = std::make_shared<cl::Program>(
433 *ath_cl_context.context, ath_cl_context.devices, binary,
nullptr, &err);
434 if (err != CL_SUCCESS) {
436 return StatusCode::FAILURE;
440 std::string bdfs =
"";
441 for (
const cl::Device &device : ath_cl_context.devices) {
445 ATH_MSG_INFO(
"Loaded " << ath_cl_context.xclbin_info.path <<
" on "
446 << ath_cl_context.devices.size() <<
" "
448 <<
" device(s): " << bdfs);
451 return StatusCode::SUCCESS;
482 return StatusCode::SUCCESS;
491 return StatusCode::SUCCESS;
494const std::vector<std::shared_ptr<xrt::device>>
497 std::vector<std::shared_ptr<xrt::device>> devices;
502 if (std::find(ath_cl_context.xclbin_info.kernel_names.begin(),
503 ath_cl_context.xclbin_info.kernel_names.end(),
504 name) != ath_cl_context.xclbin_info.kernel_names.end()) {
505 for (
const cl::Device &device : ath_cl_context.devices) {
506 devices.push_back(std::make_shared<xrt::device>(
507 xrt::opencl::get_xrt_device(device())));
510 else if (std::find(ath_cl_context.xclbin_info.cu_names.begin(),
511 ath_cl_context.xclbin_info.cu_names.end(),
512 name) != ath_cl_context.xclbin_info.cu_names.end()) {
513 for (
const cl::Device &device : ath_cl_context.devices) {
514 devices.push_back(std::make_shared<xrt::device>(
515 xrt::opencl::get_xrt_device(device())));
523const std::vector<IDeviceMgmtSvc::OpenCLHandle>
525 const std::string &name)
const {
527 std::vector<IDeviceMgmtSvc::OpenCLHandle> handles;
532 if (std::find(ath_cl_context.xclbin_info.kernel_names.begin(),
533 ath_cl_context.xclbin_info.kernel_names.end(),
534 name) != ath_cl_context.xclbin_info.kernel_names.end()) {
536 ath_cl_context.program};
537 handles.push_back(handle);
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_WARNING(x)
StatusCode program_devices()
Program the devices with the XCLBIN files and create contexts.
virtual const std::vector< IDeviceMgmtSvc::OpenCLHandle > get_opencl_handles_by_kernel_name(const std::string &name) const override
Get a list of OpenCL handles providing the specified kernel.
std::vector< XclbinInfo > m_xclbin_infos
List of XCLBIN files info configured for the service.
virtual const std::vector< std::shared_ptr< xrt::device > > get_xrt_devices_by_kernel_name(const std::string &name) const override
Get a list of XRT devices providing the specified kernel.
virtual StatusCode finalize() override
Finalise the service.
Gaudi::Property< std::vector< std::string > > m_xclbin_path_list
The list of xclbin files to use.
std::string get_device_name(const cl::Device &device) const
Get the name of a cl::device.
std::vector< AthClContext > m_ath_cl_contexts
List of contexts configured for the service.
StatusCode pair_devices_and_xclbins(const SystemInfo &si)
Pair devices and XCLBINs and create contexts.
StatusCode inspect_xclbins(SystemInfo &si)
Inspect the provided XCLBIN files and fill the SystemInfo structure.
StatusCode inspect_devices(SystemInfo &si)
Inspect the available devices and fill the SystemInfo structure.
bool is_xclbin_compatible_with_device(const DeviceMgmtSvc::XclbinInfo &xclbin_info, const cl::Device &device) const
Helper function to check if an XCLBIN file is compatible with a device.
virtual StatusCode initialize() override
Initialise the service.
std::string get_device_bdf(const cl::Device &device) const
Get the BDF (bus:device:function) string of a cl::device.
int count(std::string s, const std::string ®x)
count how many occurances of a regx are in a string
static std::string getPrefixUpToNthOccurrence(const std::string &str, char token, int n)
Get substring up to the nth occurrence of a token.
Struct to hold information about a context, as well as the devices, the program and XCLBIN file assoc...
std::vector< cl::Device > devices
std::size_t different_xclbin_count
std::size_t different_xclbin_fpga_device_name
std::vector< std::vector< cl::Device > > device_types
Struct to hold information about an XCLBIN file, as well as the kernels it contains.
std::vector< std::string > cu_names
std::vector< std::string > kernel_names
std::string fpga_device_name
Struct holding OpenCL handles for a kernel.