1330d8983SJohannes Doerfert //===----------- device.h - Target independent OpenMP target RTL ----------===// 2330d8983SJohannes Doerfert // 3330d8983SJohannes Doerfert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4330d8983SJohannes Doerfert // See https://llvm.org/LICENSE.txt for license information. 5330d8983SJohannes Doerfert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6330d8983SJohannes Doerfert // 7330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 8330d8983SJohannes Doerfert // 9330d8983SJohannes Doerfert // Declarations for managing devices that are handled by RTL plugins. 10330d8983SJohannes Doerfert // 11330d8983SJohannes Doerfert //===----------------------------------------------------------------------===// 12330d8983SJohannes Doerfert 13330d8983SJohannes Doerfert #ifndef _OMPTARGET_DEVICE_H 14330d8983SJohannes Doerfert #define _OMPTARGET_DEVICE_H 15330d8983SJohannes Doerfert 16330d8983SJohannes Doerfert #include <cassert> 17330d8983SJohannes Doerfert #include <cstddef> 18330d8983SJohannes Doerfert #include <cstdint> 19330d8983SJohannes Doerfert #include <cstring> 20330d8983SJohannes Doerfert #include <list> 21330d8983SJohannes Doerfert #include <map> 22330d8983SJohannes Doerfert #include <memory> 23330d8983SJohannes Doerfert #include <mutex> 24330d8983SJohannes Doerfert #include <set> 25330d8983SJohannes Doerfert 26330d8983SJohannes Doerfert #include "ExclusiveAccess.h" 27330d8983SJohannes Doerfert #include "OffloadEntry.h" 28330d8983SJohannes Doerfert #include "omptarget.h" 29330d8983SJohannes Doerfert #include "rtl.h" 30330d8983SJohannes Doerfert 31330d8983SJohannes Doerfert #include "OpenMP/Mapping.h" 32330d8983SJohannes Doerfert 33330d8983SJohannes Doerfert #include "llvm/ADT/DenseMap.h" 34330d8983SJohannes Doerfert #include "llvm/ADT/SmallVector.h" 35330d8983SJohannes Doerfert 36fa9e90f5SJoseph Huber #include "PluginInterface.h" 37fa9e90f5SJoseph Huber using GenericPluginTy = llvm::omp::target::plugin::GenericPluginTy; 38fa9e90f5SJoseph Huber 39330d8983SJohannes Doerfert // Forward declarations. 40330d8983SJohannes Doerfert struct __tgt_bin_desc; 41330d8983SJohannes Doerfert struct __tgt_target_table; 42330d8983SJohannes Doerfert 43330d8983SJohannes Doerfert struct DeviceTy { 44330d8983SJohannes Doerfert int32_t DeviceID; 45fa9e90f5SJoseph Huber GenericPluginTy *RTL; 46330d8983SJohannes Doerfert int32_t RTLDeviceID; 47330d8983SJohannes Doerfert 48fa9e90f5SJoseph Huber DeviceTy(GenericPluginTy *RTL, int32_t DeviceID, int32_t RTLDeviceID); 49330d8983SJohannes Doerfert // DeviceTy is not copyable 50330d8983SJohannes Doerfert DeviceTy(const DeviceTy &D) = delete; 51330d8983SJohannes Doerfert DeviceTy &operator=(const DeviceTy &D) = delete; 52330d8983SJohannes Doerfert 53330d8983SJohannes Doerfert ~DeviceTy(); 54330d8983SJohannes Doerfert 55330d8983SJohannes Doerfert /// Try to initialize the device and return any failure. 56330d8983SJohannes Doerfert llvm::Error init(); 57330d8983SJohannes Doerfert 58330d8983SJohannes Doerfert /// Provide access to the mapping handler. 59330d8983SJohannes Doerfert MappingInfoTy &getMappingInfo() { return MappingInfo; } 60330d8983SJohannes Doerfert 61330d8983SJohannes Doerfert llvm::Expected<__tgt_device_binary> loadBinary(__tgt_device_image *Img); 62330d8983SJohannes Doerfert 63330d8983SJohannes Doerfert // device memory allocation/deallocation routines 64330d8983SJohannes Doerfert /// Allocates \p Size bytes on the device, host or shared memory space 65330d8983SJohannes Doerfert /// (depending on \p Kind) and returns the address/nullptr when 66330d8983SJohannes Doerfert /// succeeds/fails. \p HstPtr is an address of the host data which the 67330d8983SJohannes Doerfert /// allocated target data will be associated with. If it is unknown, the 68330d8983SJohannes Doerfert /// default value of \p HstPtr is nullptr. Note: this function doesn't do 69330d8983SJohannes Doerfert /// pointer association. Actually, all the __tgt_rtl_data_alloc 70330d8983SJohannes Doerfert /// implementations ignore \p HstPtr. \p Kind dictates what allocator should 71330d8983SJohannes Doerfert /// be used (host, shared, device). 72330d8983SJohannes Doerfert void *allocData(int64_t Size, void *HstPtr = nullptr, 73330d8983SJohannes Doerfert int32_t Kind = TARGET_ALLOC_DEFAULT); 74330d8983SJohannes Doerfert 75330d8983SJohannes Doerfert /// Deallocates memory which \p TgtPtrBegin points at and returns 76330d8983SJohannes Doerfert /// OFFLOAD_SUCCESS/OFFLOAD_FAIL when succeeds/fails. p Kind dictates what 77330d8983SJohannes Doerfert /// allocator should be used (host, shared, device). 78330d8983SJohannes Doerfert int32_t deleteData(void *TgtPtrBegin, int32_t Kind = TARGET_ALLOC_DEFAULT); 79330d8983SJohannes Doerfert 80330d8983SJohannes Doerfert // Data transfer. When AsyncInfo is nullptr, the transfer will be 81330d8983SJohannes Doerfert // synchronous. 82330d8983SJohannes Doerfert // Copy data from host to device 83330d8983SJohannes Doerfert int32_t submitData(void *TgtPtrBegin, void *HstPtrBegin, int64_t Size, 84330d8983SJohannes Doerfert AsyncInfoTy &AsyncInfo, 85330d8983SJohannes Doerfert HostDataToTargetTy *Entry = nullptr, 86330d8983SJohannes Doerfert MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr); 87330d8983SJohannes Doerfert 88330d8983SJohannes Doerfert // Copy data from device back to host 89330d8983SJohannes Doerfert int32_t retrieveData(void *HstPtrBegin, void *TgtPtrBegin, int64_t Size, 90330d8983SJohannes Doerfert AsyncInfoTy &AsyncInfo, 91330d8983SJohannes Doerfert HostDataToTargetTy *Entry = nullptr, 92330d8983SJohannes Doerfert MappingInfoTy::HDTTMapAccessorTy *HDTTMapPtr = nullptr); 93330d8983SJohannes Doerfert 94330d8983SJohannes Doerfert // Return true if data can be copied to DstDevice directly 95330d8983SJohannes Doerfert bool isDataExchangable(const DeviceTy &DstDevice); 96330d8983SJohannes Doerfert 97330d8983SJohannes Doerfert // Copy data from current device to destination device directly 98330d8983SJohannes Doerfert int32_t dataExchange(void *SrcPtr, DeviceTy &DstDev, void *DstPtr, 99330d8983SJohannes Doerfert int64_t Size, AsyncInfoTy &AsyncInfo); 100330d8983SJohannes Doerfert 101330d8983SJohannes Doerfert /// Notify the plugin about a new mapping starting at the host address 102330d8983SJohannes Doerfert /// \p HstPtr and \p Size bytes. 103330d8983SJohannes Doerfert int32_t notifyDataMapped(void *HstPtr, int64_t Size); 104330d8983SJohannes Doerfert 105330d8983SJohannes Doerfert /// Notify the plugin about an existing mapping being unmapped starting at 106330d8983SJohannes Doerfert /// the host address \p HstPtr. 107330d8983SJohannes Doerfert int32_t notifyDataUnmapped(void *HstPtr); 108330d8983SJohannes Doerfert 109330d8983SJohannes Doerfert // Launch the kernel identified by \p TgtEntryPtr with the given arguments. 110330d8983SJohannes Doerfert int32_t launchKernel(void *TgtEntryPtr, void **TgtVarsPtr, 111330d8983SJohannes Doerfert ptrdiff_t *TgtOffsets, KernelArgsTy &KernelArgs, 112330d8983SJohannes Doerfert AsyncInfoTy &AsyncInfo); 113330d8983SJohannes Doerfert 114330d8983SJohannes Doerfert /// Synchronize device/queue/event based on \p AsyncInfo and return 115330d8983SJohannes Doerfert /// OFFLOAD_SUCCESS/OFFLOAD_FAIL when succeeds/fails. 116330d8983SJohannes Doerfert int32_t synchronize(AsyncInfoTy &AsyncInfo); 117330d8983SJohannes Doerfert 118330d8983SJohannes Doerfert /// Query for device/queue/event based completion on \p AsyncInfo in a 119330d8983SJohannes Doerfert /// non-blocking manner and return OFFLOAD_SUCCESS/OFFLOAD_FAIL when 120330d8983SJohannes Doerfert /// succeeds/fails. Must be called multiple times until AsyncInfo is 121330d8983SJohannes Doerfert /// completed and AsyncInfo.isDone() returns true. 122330d8983SJohannes Doerfert int32_t queryAsync(AsyncInfoTy &AsyncInfo); 123330d8983SJohannes Doerfert 124330d8983SJohannes Doerfert /// Calls the corresponding print device info function in the plugin. 125330d8983SJohannes Doerfert bool printDeviceInfo(); 126330d8983SJohannes Doerfert 127330d8983SJohannes Doerfert /// Event related interfaces. 128330d8983SJohannes Doerfert /// { 129330d8983SJohannes Doerfert /// Create an event. 130330d8983SJohannes Doerfert int32_t createEvent(void **Event); 131330d8983SJohannes Doerfert 132330d8983SJohannes Doerfert /// Record the event based on status in AsyncInfo->Queue at the moment the 133330d8983SJohannes Doerfert /// function is called. 134330d8983SJohannes Doerfert int32_t recordEvent(void *Event, AsyncInfoTy &AsyncInfo); 135330d8983SJohannes Doerfert 136330d8983SJohannes Doerfert /// Wait for an event. This function can be blocking or non-blocking, 137330d8983SJohannes Doerfert /// depending on the implmentation. It is expected to set a dependence on the 138330d8983SJohannes Doerfert /// event such that corresponding operations shall only start once the event 139330d8983SJohannes Doerfert /// is fulfilled. 140330d8983SJohannes Doerfert int32_t waitEvent(void *Event, AsyncInfoTy &AsyncInfo); 141330d8983SJohannes Doerfert 142330d8983SJohannes Doerfert /// Synchronize the event. It is expected to block the thread. 143330d8983SJohannes Doerfert int32_t syncEvent(void *Event); 144330d8983SJohannes Doerfert 145330d8983SJohannes Doerfert /// Destroy the event. 146330d8983SJohannes Doerfert int32_t destroyEvent(void *Event); 147330d8983SJohannes Doerfert /// } 148330d8983SJohannes Doerfert 149330d8983SJohannes Doerfert /// Print all offload entries to stderr. 150330d8983SJohannes Doerfert void dumpOffloadEntries(); 151330d8983SJohannes Doerfert 152330d8983SJohannes Doerfert /// Ask the device whether the runtime should use auto zero-copy. 153330d8983SJohannes Doerfert bool useAutoZeroCopy(); 154330d8983SJohannes Doerfert 155*ff12c006SJohannes Doerfert /// Check if there are pending images for this device. 156*ff12c006SJohannes Doerfert bool hasPendingImages() const { return HasPendingImages; } 157*ff12c006SJohannes Doerfert 158*ff12c006SJohannes Doerfert /// Indicate that there are pending images for this device or not. 159*ff12c006SJohannes Doerfert void setHasPendingImages(bool V) { HasPendingImages = V; } 160*ff12c006SJohannes Doerfert 161330d8983SJohannes Doerfert private: 162330d8983SJohannes Doerfert /// Deinitialize the device (and plugin). 163330d8983SJohannes Doerfert void deinit(); 164330d8983SJohannes Doerfert 165330d8983SJohannes Doerfert /// All offload entries available on this device. 166330d8983SJohannes Doerfert using DeviceOffloadEntriesMapTy = 167330d8983SJohannes Doerfert llvm::DenseMap<llvm::StringRef, OffloadEntryTy>; 168330d8983SJohannes Doerfert ProtectedObj<DeviceOffloadEntriesMapTy> DeviceOffloadEntries; 169330d8983SJohannes Doerfert 170330d8983SJohannes Doerfert /// Handler to collect and organize host-2-device mapping information. 171330d8983SJohannes Doerfert MappingInfoTy MappingInfo; 172*ff12c006SJohannes Doerfert 173*ff12c006SJohannes Doerfert /// Flag to indicate pending images (true after construction). 174*ff12c006SJohannes Doerfert bool HasPendingImages = true; 175330d8983SJohannes Doerfert }; 176330d8983SJohannes Doerfert 177330d8983SJohannes Doerfert #endif 178