Skip to content

Commit

Permalink
Xclbin to ELF flow migration (#8581)
Browse files Browse the repository at this point in the history
* Enable flow without xclbin using new elf

Signed-off-by: rbramand <[email protected]>

* Address comments on PR

Signed-off-by: rbramand <[email protected]>

* Update copyright files

Signed-off-by: rbramand <[email protected]>

* Fix failure

Signed-off-by: rbramand <[email protected]>

* Add missing comment fixes

Signed-off-by: rbramand <[email protected]>

* Remove unused exported functions

Signed-off-by: rbramand <[email protected]>

* Rebased with master

Signed-off-by: rbramand <[email protected]>

* Update Copyright to use 2025

Signed-off-by: rbramand <[email protected]>

---------

Signed-off-by: rbramand <[email protected]>
Co-authored-by: rbramand <[email protected]>
  • Loading branch information
rbramand-xilinx and rbramand authored Jan 27, 2025
1 parent 613de25 commit fdce01e
Show file tree
Hide file tree
Showing 11 changed files with 1,268 additions and 603 deletions.
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>>*,
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));
}

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

0 comments on commit fdce01e

Please sign in to comment.