From b3b06fc67dcab0086d851b6a2754770a71b8ffec Mon Sep 17 00:00:00 2001 From: Sherry Yuan Date: Wed, 9 Mar 2022 13:10:41 -0500 Subject: [PATCH] [SYCL] Implement initial host_pipe registration What is this for: pipes expose the concept of a first in first out buffer, this FIFO construct provide link between elements of a design that are accessed through read/write/push/pop APIs. A host pipe is a pipe that links a device kernel with host program. This extension is framed from FPGA perspective. This change add required interface for the integration footer to register the `host_pipe` of a program as well as reading extended info supplied through "SYCL/host pipes" property. Info is stored in a map managed by program manager. The integration header and footer provides a mapping from the host address of each pipe variable to the unique string for that variable. This is required so that sycl runtime can query the pipe address from the given pipe name, and pass both into opencl runtime function calls. Opencl defines pipes, which are FIFO constructs that are consistent with Khronos specification. Spec link: https://github.com/intel/llvm/pull/5838 List of suported properties: https://github.com/intel/llvm/pull/5839 Note: it is the first change to runtime relating to host_pipe, thus the feature is not complete / fully testable. It is intended to add an interface for integration footer as well as consumer for the information sycl-post-link will be generating when future work is added. --- llvm/include/llvm/Support/PropertySetIO.h | 1 + llvm/lib/Support/PropertySetIO.cpp | 1 + sycl/include/CL/sycl/detail/host_pipe_map.hpp | 21 ++++++ sycl/include/CL/sycl/detail/pi.h | 2 + sycl/include/CL/sycl/detail/pi.hpp | 7 ++ sycl/source/CMakeLists.txt | 1 + sycl/source/detail/host_pipe_map.cpp | 24 +++++++ sycl/source/detail/host_pipe_map_entry.hpp | 50 +++++++++++++++ .../program_manager/program_manager.cpp | 64 +++++++++++++++++++ .../program_manager/program_manager.hpp | 22 +++++++ sycl/test/abi/sycl_symbols_linux.dump | 1 + sycl/test/abi/sycl_symbols_windows.dump | 1 + 12 files changed, 195 insertions(+) create mode 100755 sycl/include/CL/sycl/detail/host_pipe_map.hpp create mode 100644 sycl/source/detail/host_pipe_map.cpp create mode 100644 sycl/source/detail/host_pipe_map_entry.hpp diff --git a/llvm/include/llvm/Support/PropertySetIO.h b/llvm/include/llvm/Support/PropertySetIO.h index 310afd5f4cfa3..0a8852357cd36 100644 --- a/llvm/include/llvm/Support/PropertySetIO.h +++ b/llvm/include/llvm/Support/PropertySetIO.h @@ -193,6 +193,7 @@ class PropertySetRegistry { static constexpr char SYCL_ASSERT_USED[] = "SYCL/assert used"; static constexpr char SYCL_EXPORTED_SYMBOLS[] = "SYCL/exported symbols"; static constexpr char SYCL_DEVICE_GLOBALS[] = "SYCL/device globals"; + static constexpr char SYCL_HOST_PIPES[] = "SYCL/host pipes"; // Function for bulk addition of an entire property set under given category // (property set name). diff --git a/llvm/lib/Support/PropertySetIO.cpp b/llvm/lib/Support/PropertySetIO.cpp index 3541c11a8d7d2..4dc6a048e137c 100644 --- a/llvm/lib/Support/PropertySetIO.cpp +++ b/llvm/lib/Support/PropertySetIO.cpp @@ -202,6 +202,7 @@ constexpr char PropertySetRegistry::SYCL_MISC_PROP[]; constexpr char PropertySetRegistry::SYCL_ASSERT_USED[]; constexpr char PropertySetRegistry::SYCL_EXPORTED_SYMBOLS[]; constexpr char PropertySetRegistry::SYCL_DEVICE_GLOBALS[]; +constexpr char PropertySetRegistry::SYCL_HOST_PIPES[]; } // namespace util } // namespace llvm diff --git a/sycl/include/CL/sycl/detail/host_pipe_map.hpp b/sycl/include/CL/sycl/detail/host_pipe_map.hpp new file mode 100755 index 0000000000000..9c82f11bf0a76 --- /dev/null +++ b/sycl/include/CL/sycl/detail/host_pipe_map.hpp @@ -0,0 +1,21 @@ +//==-------------------- host_pipe_map.hpp -----------------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace detail { +namespace host_pipe_map { + +__SYCL_EXPORT void add(const void *HostPipePtr, const char *UniqueId); + +} // namespace host_pipe_map +} // namespace detail +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/detail/pi.h b/sycl/include/CL/sycl/detail/pi.h index 16482c07e1fa5..9bdb4b067da15 100644 --- a/sycl/include/CL/sycl/detail/pi.h +++ b/sycl/include/CL/sycl/detail/pi.h @@ -777,6 +777,8 @@ static const uint8_t PI_DEVICE_BINARY_OFFLOAD_KIND_SYCL = 4; #define __SYCL_PI_PROPERTY_SET_SYCL_EXPORTED_SYMBOLS "SYCL/exported symbols" /// PropertySetRegistry::SYCL_DEVICE_GLOBALS defined in PropertySetIO.h #define __SYCL_PI_PROPERTY_SET_SYCL_DEVICE_GLOBALS "SYCL/device globals" +/// PropertySetRegistry::SYCL_HOST_PIPES defined in PropertySetIO.h +#define __SYCL_PI_PROPERTY_SET_SYCL_HOST_PIPES "SYCL/host pipes" /// Program metadata tags recognized by the PI backends. For kernels the tag /// must appear after the kernel name. diff --git a/sycl/include/CL/sycl/detail/pi.hpp b/sycl/include/CL/sycl/detail/pi.hpp index dbb7adabd2c26..c2e7a96eaf946 100644 --- a/sycl/include/CL/sycl/detail/pi.hpp +++ b/sycl/include/CL/sycl/detail/pi.hpp @@ -383,6 +383,13 @@ class DeviceBinaryImage { DeviceGlobals.init(Bin, __SYCL_PI_PROPERTY_SET_SYCL_DEVICE_GLOBALS); return DeviceGlobals; } + const PropertyRange getHostPipes() const { + // We can't have this variable as a class member, since it would break + // the ABI backwards compatibility. + DeviceBinaryImage::PropertyRange HostPipes; + HostPipes.init(Bin, __SYCL_PI_PROPERTY_SET_SYCL_HOST_PIPES); + return HostPipes; + } virtual ~DeviceBinaryImage() {} protected: diff --git a/sycl/source/CMakeLists.txt b/sycl/source/CMakeLists.txt index b89835c5f4864..60988bb02ca43 100644 --- a/sycl/source/CMakeLists.txt +++ b/sycl/source/CMakeLists.txt @@ -134,6 +134,7 @@ set(SYCL_SOURCES "detail/context_impl.cpp" "detail/device_binary_image.cpp" "detail/device_filter.cpp" + "detail/host_pipe_map.cpp" "detail/device_global_map.cpp" "detail/device_impl.cpp" "detail/error_handling/enqueue_kernel.cpp" diff --git a/sycl/source/detail/host_pipe_map.cpp b/sycl/source/detail/host_pipe_map.cpp new file mode 100644 index 0000000000000..79f7f77f70716 --- /dev/null +++ b/sycl/source/detail/host_pipe_map.cpp @@ -0,0 +1,24 @@ +//==-------------------- host_pipe_map.cpp -----------------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace detail { +namespace host_pipe_map { + +__SYCL_EXPORT void add(const void *HostPipePtr, const char *UniqueId) { + detail::ProgramManager::getInstance().addOrInitHostPipeEntry(HostPipePtr, + UniqueId); +} + +} // namespace host_pipe_map +} // namespace detail +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/source/detail/host_pipe_map_entry.hpp b/sycl/source/detail/host_pipe_map_entry.hpp new file mode 100644 index 0000000000000..2d8dae9f4ba71 --- /dev/null +++ b/sycl/source/detail/host_pipe_map_entry.hpp @@ -0,0 +1,50 @@ +//==----------------- host_pipe_map_entry.hpp --------------------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace detail { + +struct HostPipeMapEntry { + std::string MUniqueId; + // Pointer to the host_pipe on host. + const void *MHostPipePtr; + // Size of the underlying type in the host_pipe. + std::uint32_t MHostPipeTSize; + + // Constructor only initializes with the pointer and ID. + // Other members will be initialized later + HostPipeMapEntry(std::string UniqueId, const void *HostPipePtr) + : MUniqueId(UniqueId), MHostPipePtr(HostPipePtr), MHostPipeTSize(0) {} + + // Constructor only initializes with the size and ID. + // Other members will be initialized later + HostPipeMapEntry(std::string UniqueId, std::uint32_t HostPipeTSize) + : MUniqueId(UniqueId), MHostPipePtr(nullptr), + MHostPipeTSize(HostPipeTSize) {} + + void initialize(std::uint32_t HostPipeTSize) { + assert(HostPipeTSize != 0 && "Host pipe initialized with 0 size."); + assert(MHostPipeTSize == 0 && "Host pipe has already been initialized."); + MHostPipeTSize = HostPipeTSize; + } + + void initialize(const void *HostPipePtr) { + assert(!MHostPipePtr && "Host pipe pointer has already been initialized."); + MHostPipePtr = HostPipePtr; + } +}; + +} // namespace detail +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/source/detail/program_manager/program_manager.cpp b/sycl/source/detail/program_manager/program_manager.cpp index 5efea6c0349ee..51fbf739d697c 100644 --- a/sycl/source/detail/program_manager/program_manager.cpp +++ b/sycl/source/detail/program_manager/program_manager.cpp @@ -1220,6 +1220,40 @@ void ProgramManager::addImages(pi_device_binaries DeviceBinary) { Entry->second.initialize(TypeSize, DeviceImageScopeDecorated); } } + // ... and initialize associated host_pipe information + { + std::lock_guard HostPipesGuard(m_HostPipesMutex); + + auto HostPipes = Img->getHostPipes(); + for (const pi_device_binary_property &HostPipe : HostPipes) { + pi::ByteArray HostPipeInfo = + pi::DeviceBinaryProperty(HostPipe).asByteArray(); + + // The supplied host_pipe info property is expected to contain: + // * 8 bytes - Size of the property. + // * 4 bytes - Size of the underlying type in the host_pipe. + // Note: Property may be padded. + constexpr unsigned int NumPropertySizeBytes = 8; + constexpr unsigned int NumTypeBytes = 4; + assert(HostPipeInfo.size() >= NumPropertySizeBytes + NumTypeBytes && + "Unexpected property size"); + auto TypeSize = *reinterpret_cast( + &HostPipeInfo[NumPropertySizeBytes]); + + auto ExistingHostPipe = m_HostPipes.find(HostPipe->Name); + if (ExistingHostPipe != m_HostPipes.end()) { + // If it has already been registered we update the information. + ExistingHostPipe->second->initialize(TypeSize); + } else { + // If it has not already been registered we create a new entry. + // Note: Pointer to the host pipe is not available here, so it + // cannot be set until registration happens. + auto EntryUPtr = + std::make_unique(HostPipe->Name, TypeSize); + m_HostPipes.emplace(HostPipe->Name, std::move(EntryUPtr)); + } + } + } m_DeviceImages[KSId].reset(new std::vector()); cacheKernelUsesAssertInfo(M, *Img); @@ -1469,6 +1503,36 @@ kernel_id ProgramManager::getBuiltInKernelID(const std::string &KernelName) { return KernelID->second; } +void ProgramManager::addOrInitHostPipeEntry(const void *HostPipePtr, + const char *UniqueId) { + std::lock_guard HostPipesGuard(m_HostPipesMutex); + + auto ExistingHostPipe = m_HostPipes.find(UniqueId); + if (ExistingHostPipe != m_HostPipes.end()) { + ExistingHostPipe->second->initialize(HostPipePtr); + m_Ptr2HostPipe.insert({HostPipePtr, ExistingHostPipe->second.get()}); + return; + } + auto EntryUPtr = std::make_unique(UniqueId, HostPipePtr); + auto NewEntry = m_HostPipes.emplace(UniqueId, std::move(EntryUPtr)); + m_Ptr2HostPipe.insert({HostPipePtr, NewEntry.first->second.get()}); +} + +HostPipeMapEntry * +ProgramManager::getHostPipeEntry(const std::string &UniqueId) { + std::lock_guard HostPipesGuard(m_HostPipesMutex); + auto Entry = m_HostPipes.find(UniqueId); + assert(Entry != m_HostPipes.end() && "Host pipe entry not found"); + return Entry->second.get(); +} + +HostPipeMapEntry *ProgramManager::getHostPipeEntry(const void *HostPipePtr) { + std::lock_guard HostPipesGuard(m_HostPipesMutex); + auto Entry = m_Ptr2HostPipe.find(HostPipePtr); + assert(Entry != m_Ptr2HostPipe.end() && "Host pipe entry not found"); + return Entry->second; +} + void ProgramManager::addDeviceGlobalEntry(void *DeviceGlobalPtr, const char *UniqueId) { std::lock_guard DeviceGlobalsGuard(m_DeviceGlobalsMutex); diff --git a/sycl/source/detail/program_manager/program_manager.hpp b/sycl/source/detail/program_manager/program_manager.hpp index a1bd79bfc106d..1c48379c76251 100644 --- a/sycl/source/detail/program_manager/program_manager.hpp +++ b/sycl/source/detail/program_manager/program_manager.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,7 @@ #include #include #include +#include #include #include @@ -183,6 +185,18 @@ class ProgramManager { // built-in kernel name. kernel_id getBuiltInKernelID(const std::string &KernelName); + // The function inserts or initializes a host_pipe entry into the + // host_pipe map. + void addOrInitHostPipeEntry(const void *HostPipePtr, const char *UniqueId); + + // The function gets a host_pipe entry identified by the unique ID from + // the host_pipe map. + HostPipeMapEntry *getHostPipeEntry(const std::string &UniqueId); + + // The function gets a host_pipe entry identified by the pointer to the + // host_pipe object from the host_pipe map. + HostPipeMapEntry *getHostPipeEntry(const void *HostPipePtr); + // The function inserts a device_global entry into the device_global map. void addDeviceGlobalEntry(void *DeviceGlobalPtr, const char *UniqueId); @@ -392,6 +406,14 @@ class ProgramManager { /// Protects m_DeviceGlobals. std::mutex m_DeviceGlobalsMutex; + + // Maps between host_pipe identifiers and associated information. + std::unordered_map> + m_HostPipes; + std::unordered_map m_Ptr2HostPipe; + + /// Protects m_HostPipes and m_Ptr2HostPipe. + std::mutex m_HostPipesMutex; }; } // namespace detail } // namespace sycl diff --git a/sycl/test/abi/sycl_symbols_linux.dump b/sycl/test/abi/sycl_symbols_linux.dump index 2f2f94e5bcd54..255f02af50006 100644 --- a/sycl/test/abi/sycl_symbols_linux.dump +++ b/sycl/test/abi/sycl_symbols_linux.dump @@ -3881,6 +3881,7 @@ _ZN2cl4sycl6detail13MemoryManager8copy_usmEPKvSt10shared_ptrINS1_10queue_implEEm _ZN2cl4sycl6detail13MemoryManager8copy_usmEPKvSt10shared_ptrINS1_10queue_implEEmPvSt6vectorIP9_pi_eventSaISB_EERSB_ _ZN2cl4sycl6detail13MemoryManager8fill_usmEPvSt10shared_ptrINS1_10queue_implEEmiSt6vectorIP9_pi_eventSaIS9_EEPS9_ _ZN2cl4sycl6detail13MemoryManager8fill_usmEPvSt10shared_ptrINS1_10queue_implEEmiSt6vectorIP9_pi_eventSaIS9_EERS9_ +_ZN2cl4sycl6detail13host_pipe_map3addEPKvPKc _ZN2cl4sycl6detail13make_platformEmNS0_7backendE _ZN2cl4sycl6detail14getBorderColorENS0_19image_channel_orderE _ZN2cl4sycl6detail14host_half_impl4halfC1ERKf diff --git a/sycl/test/abi/sycl_symbols_windows.dump b/sycl/test/abi/sycl_symbols_windows.dump index 5c908b3a3865e..fd8d4b4c80a2e 100644 --- a/sycl/test/abi/sycl_symbols_windows.dump +++ b/sycl/test/abi/sycl_symbols_windows.dump @@ -1090,6 +1090,7 @@ ?acospi@__host_std@cl@@YA?AVhalf@half_impl@detail@sycl@2@V34562@@Z ?acospi@__host_std@cl@@YAMM@Z ?acospi@__host_std@cl@@YANN@Z +?add@host_pipe_map@detail@sycl@cl@@YAXPEBXPEBD@Z ?addHostAccessorAndWait@detail@sycl@cl@@YAXPEAVAccessorImplHost@123@@Z ?addOrReplaceAccessorProperties@SYCLMemObjT@detail@sycl@cl@@QEAAXAEBVproperty_list@34@@Z ?addReduction@handler@sycl@cl@@AEAAXAEBV?$shared_ptr@$$CBX@std@@@Z