xref: /llvm-project/offload/include/device.h (revision ff12c0061b7dbb8a82681a0e02a513bb84b1d143)
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