Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xclbin to ELF flow migration #8581

Merged
merged 8 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/runtime_src/core/common/api/hw_context_int.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// PDX-License-Identifier: Apache-2.0
// Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved.
// Copyright (C) 2022-2025 Advanced Micro Devices, Inc. All rights reserved.
#ifndef XRT_COMMON_API_HW_CONTEXT_INT_H
#define XRT_COMMON_API_HW_CONTEXT_INT_H

#include "core/common/config.h"

// This file defines implementation extensions to the XRT XCLBIN APIs.
#include "core/include/xrt/xrt_hw_context.h"
#include "core/include/xrt/experimental/xrt_module.h"

#include <cstdint>

Expand Down Expand Up @@ -44,6 +45,12 @@ XRT_CORE_COMMON_EXPORT
xrt::hw_context
create_hw_context_from_implementation(void* hwctx_impl);

// Checks all the modules that are registered with given hw context
// and returns the module with the given kernel name
// throws if no module is found with given kernel name
xrt::module
get_module(const xrt::hw_context& hwctx, const std::string& kname);

}} // hw_context_int, xrt_core

#endif
25 changes: 23 additions & 2 deletions src/runtime_src/core/common/api/module_int.h
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
// Copyright (C) 2023-2025 Advanced Micro Devices, Inc. All rights reserved.
//
// Xilinx Runtime (XRT) Experimental APIs

#ifndef _XRT_COMMON_MODULE_INT_H_
#define _XRT_COMMON_MODULE_INT_H_

// This file defines implementation extensions to the XRT Kernel APIs.
#include "core/common/xclbin_parser.h"
#include "core/include/xrt/xrt_bo.h"
#include "core/include/xrt/experimental/xrt_module.h"

#include "ert.h"

#include <string>

namespace xrt_core::module_int {
struct kernel_info {
std::vector<xrt_core::xclbin::kernel_argument> args;
xrt_core::xclbin::kernel_properties props;
};

// Fill in ERT command payload in ELF flow. The payload is after extra_cu_mask
// and before CU arguments.
Expand All @@ -31,9 +38,12 @@ patch(const xrt::module&, const std::string& argnm, size_t index, const xrt::bo&
// Note that if size passed in is 0, real buffer size required will be returned
// without any patching. This is useful if caller wishes to discover the exact size
// of the control code buffer.
// New ELfs pack multiple control codes info in it, to identify which control code
// to run we use index
XRT_CORE_COMMON_EXPORT
void
patch(const xrt::module&, uint8_t*, size_t*, const std::vector<std::pair<std::string, uint64_t>>*);
patch(const xrt::module&, uint8_t*, size_t*, const std::vector<std::pair<std::string, uint64_t>>*,
stsoe marked this conversation as resolved.
Show resolved Hide resolved
uint32_t index = 0);

// Patch scalar into control code at given argument
XRT_CORE_COMMON_EXPORT
Expand All @@ -54,6 +64,17 @@ get_ert_opcode(const xrt::module& module);
void
dump_scratchpad_mem(const xrt::module& module);

// Returns kernel info extracted from demangled kernel signature
// eg : DPU(void*, void*, void*)
// returns kernel name (DPU), kernel args and kernel properties
// throws exception if Elf passed has no kernel info
const kernel_info&
get_kernel_info(const xrt::module& module);

// Get partition size if ELF has the info
uint32_t
get_partition_size(const xrt::module& module);

} // xrt_core::module_int

#endif
127 changes: 110 additions & 17 deletions src/runtime_src/core/common/api/xrt_hw_context.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (C) 2022-2023 Advanced Micro Devices, Inc. All rights reserved.
// Copyright (C) 2022-2025 Advanced Micro Devices, Inc. All rights reserved.

// This file implements XRT xclbin APIs as declared in
// core/include/experimental/xrt_queue.h
#define XRT_API_SOURCE // exporting xrt_hwcontext.h
#define XCL_DRIVER_DLL_EXPORT // exporting xrt_xclbin.h
#define XRT_CORE_COMMON_SOURCE // in same dll as coreutil

#include "core/include/xrt/xrt_hw_context.h"
#include "core/include/xrt/experimental/xrt_module.h"
#include "hw_context_int.h"
#include "module_int.h"
#include "xclbin_int.h"

#include "core/common/device.h"
#include "core/common/trace.h"
Expand All @@ -30,6 +34,8 @@ class hw_context_impl : public std::enable_shared_from_this<hw_context_impl>

std::shared_ptr<xrt_core::device> m_core_device;
xrt::xclbin m_xclbin;
std::map<std::string, xrt::module> m_module_map; // map b/w kernel name and module
uint32_t m_partition_size = 0;
cfg_param_type m_cfg_param;
access_mode m_mode;
std::unique_ptr<xrt_core::hwctx_handle> m_hdl;
Expand All @@ -53,6 +59,28 @@ class hw_context_impl : public std::enable_shared_from_this<hw_context_impl>
, m_hdl{m_core_device->create_hw_context(xclbin_id, m_cfg_param, m_mode)}
{}

hw_context_impl(std::shared_ptr<xrt_core::device> device, cfg_param_type cfg_param, access_mode mode)
: m_core_device{std::move(device)}
, m_cfg_param{std::move(cfg_param)}
, m_mode{mode}
{}

hw_context_impl(std::shared_ptr<xrt_core::device> device, const xrt::elf& elf, cfg_param_type cfg_param, access_mode mode)
: m_core_device{std::move(device)}
, m_cfg_param{std::move(cfg_param)}
, m_mode{mode}
{
// Create module object to parse Elf
auto module = xrt::module(elf);
// Get partition size and pass it to diver for hw ctx creation
m_partition_size = xrt_core::module_int::get_partition_size(module);
m_hdl = m_core_device->create_hw_context(m_partition_size, m_cfg_param, mode);

// creation successful, store the module in the map
auto kernel_name = xrt_core::module_int::get_kernel_info(module).props.name;
m_module_map.emplace(std::move(kernel_name), std::move(module));
}

std::shared_ptr<hw_context_impl>
get_shared_ptr()
{
Expand Down Expand Up @@ -86,6 +114,32 @@ class hw_context_impl : public std::enable_shared_from_this<hw_context_impl>
hw_context_impl& operator=(const hw_context_impl&) = delete;
hw_context_impl& operator=(hw_context_impl&&) = delete;

void
add_config(const xrt::elf& elf)
{
auto module = xrt::module(elf);
auto kernel_name = xrt_core::module_int::get_kernel_info(module).props.name;
auto part_size = xrt_core::module_int::get_partition_size(module);

// create hw ctx handle if not already created
if (!m_hdl) {
m_module_map.emplace(std::move(kernel_name), std::move(module));
m_partition_size = part_size;
m_hdl = m_core_device->create_hw_context(m_partition_size, m_cfg_param, m_mode);
return;
}

// add module only if partition size matches existing configuration
if (m_partition_size != part_size)
throw std::runtime_error("can not add config to ctx with different configuration\n");

// add module to map if kernel name is different, else throw
if (m_module_map.find(kernel_name) != m_module_map.end())
throw std::runtime_error("config with kernel already exists, cannot add this config\n");

m_module_map.emplace(std::move(kernel_name), std::move(module));
stsoe marked this conversation as resolved.
Show resolved Hide resolved
}

void
update_qos(const qos_type& qos)
{
Expand Down Expand Up @@ -134,6 +188,15 @@ class hw_context_impl : public std::enable_shared_from_this<hw_context_impl>
{
return m_usage_logger.get();
}

xrt::module
get_module(const std::string& kname) const
{
if (auto itr = m_module_map.find(kname); itr != m_module_map.end())
return itr->second;

throw std::runtime_error("no module found with given kernel name in ctx");
}
};

} // xrt
Expand Down Expand Up @@ -171,45 +234,58 @@ create_hw_context_from_implementation(void* hwctx_impl)
return xrt::hw_context(impl_ptr->get_shared_ptr());
}

xrt::module
get_module(const xrt::hw_context& ctx, const std::string& kname)
{
return ctx.get_handle()->get_module(kname);
}

} // xrt_core::hw_context_int

////////////////////////////////////////////////////////////////
// xrt_hwcontext C++ API implmentations (xrt_hw_context.h)
////////////////////////////////////////////////////////////////
namespace xrt {

// common function called with hw ctx created from different ways
static std::shared_ptr<hw_context_impl>
alloc_hwctx_from_cfg(const xrt::device& device, const xrt::uuid& xclbin_id, const xrt::hw_context::cfg_param_type& cfg_param)
post_alloc_hwctx(const std::shared_ptr<hw_context_impl>& handle)
{
XRT_TRACE_POINT_SCOPE(xrt_hw_context);
auto handle = std::make_shared<hw_context_impl>(device.get_handle(), xclbin_id, cfg_param);

// Update device is called with a raw pointer to dyanamically
// link to callbacks that exist in XDP via a C-style interface
// The create_hw_context_from_implementation function is then
// called in XDP create a hw_context to the underlying implementation
xrt_core::xdp::update_device(handle.get());

handle->get_usage_logger()->log_hw_ctx_info(handle.get());

return handle;
}

static std::shared_ptr<hw_context_impl>
alloc_hwctx_from_mode(const xrt::device& device, const xrt::uuid& xclbin_id, xrt::hw_context::access_mode mode)
alloc_hwctx_from_cfg(const xrt::device& device, const xrt::uuid& xclbin_id, const xrt::hw_context::cfg_param_type& cfg_param)
{
XRT_TRACE_POINT_SCOPE(xrt_hw_context);
auto handle = std::make_shared<hw_context_impl>(device.get_handle(), xclbin_id, mode);
return post_alloc_hwctx(std::make_shared<hw_context_impl>(device.get_handle(), xclbin_id, cfg_param));
}

// Update device is called with a raw pointer to dyanamically
// link to callbacks that exist in XDP via a C-style interface
// The create_hw_context_from_implementation function is then
// called in XDP create a hw_context to the underlying implementation
xrt_core::xdp::update_device(handle.get());
static std::shared_ptr<hw_context_impl>
alloc_hwctx_from_mode(const xrt::device& device, const xrt::uuid& xclbin_id, xrt::hw_context::access_mode mode)
{
XRT_TRACE_POINT_SCOPE(xrt_hw_context);
return post_alloc_hwctx(std::make_shared<hw_context_impl>(device.get_handle(), xclbin_id, mode));
}

handle->get_usage_logger()->log_hw_ctx_info(handle.get());
static std::shared_ptr<hw_context_impl>
alloc_empty_hwctx(const xrt::device& device, const xrt::hw_context::cfg_param_type& cfg_param, xrt::hw_context::access_mode mode)
{
XRT_TRACE_POINT_SCOPE(xrt_hw_context);
return post_alloc_hwctx(std::make_shared<hw_context_impl>(device.get_handle(), cfg_param, mode));
}

return handle;
static std::shared_ptr<hw_context_impl>
alloc_hwctx_from_elf(const xrt::device& device, const xrt::elf& elf, const xrt::hw_context::cfg_param_type& cfg_param,
xrt::hw_context::access_mode mode)
{
XRT_TRACE_POINT_SCOPE(xrt_hw_context);
return post_alloc_hwctx(std::make_shared<hw_context_impl>(device.get_handle(), elf, cfg_param, mode));
}

hw_context::
Expand All @@ -222,6 +298,23 @@ hw_context(const xrt::device& device, const xrt::uuid& xclbin_id, access_mode mo
: detail::pimpl<hw_context_impl>(alloc_hwctx_from_mode(device, xclbin_id, mode))
{}

hw_context::
hw_context(const xrt::device& device, const xrt::elf& elf, const cfg_param_type& cfg_param, access_mode mode)
: detail::pimpl<hw_context_impl>(alloc_hwctx_from_elf(device, elf, cfg_param, mode))
{}

hw_context::
hw_context(const xrt::device& device, const cfg_param_type& cfg_param, access_mode mode)
: detail::pimpl<hw_context_impl>(alloc_empty_hwctx(device, cfg_param, mode))
{}

void
hw_context::
add_config(const xrt::elf& elf)
{
get_handle()->add_config(elf);
}

void
hw_context::
update_qos(const qos_type& qos)
Expand Down
Loading
Loading