//===-- Device.h - The Device class -----------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// The Device class which represents a single device of a specific platform.
///
//===----------------------------------------------------------------------===//

#ifndef STREAMEXECUTOR_DEVICE_H
#define STREAMEXECUTOR_DEVICE_H

#include <type_traits>

#include "streamexecutor/KernelSpec.h"
#include "streamexecutor/PlatformInterfaces.h"
#include "streamexecutor/Utils/Error.h"

namespace streamexecutor {

class Stream;

class Device {
public:
  explicit Device(PlatformDevice *PDevice);
  virtual ~Device();

  /// Creates a kernel object for this device.
  ///
  /// See \ref CompilerGeneratedKernelExample "Kernel.h" for an example of how
  /// this method is used.
  template <typename KernelT>
  Expected<typename std::enable_if<std::is_base_of<KernelBase, KernelT>::value,
                                   KernelT>::type>
  createKernel(const MultiKernelLoaderSpec &Spec) {
    Expected<std::unique_ptr<PlatformKernelHandle>> MaybeKernelHandle =
        PDevice->createKernel(Spec);
    if (!MaybeKernelHandle) {
      return MaybeKernelHandle.takeError();
    }
    return KernelT(Spec.getKernelName(), std::move(*MaybeKernelHandle));
  }

  /// Creates a stream object for this device.
  Expected<Stream> createStream();

  /// Allocates an array of ElementCount entries of type T in device memory.
  template <typename T>
  Expected<GlobalDeviceMemory<T>> allocateDeviceMemory(size_t ElementCount) {
    Expected<void *> MaybeMemory =
        PDevice->allocateDeviceMemory(ElementCount * sizeof(T));
    if (!MaybeMemory)
      return MaybeMemory.takeError();
    return GlobalDeviceMemory<T>::makeFromElementCount(*MaybeMemory,
                                                       ElementCount);
  }

  /// Frees memory previously allocated with allocateDeviceMemory.
  template <typename T> Error freeDeviceMemory(GlobalDeviceMemory<T> Memory) {
    return PDevice->freeDeviceMemory(Memory.getHandle());
  }

  /// Allocates an array of ElementCount entries of type T in host memory.
  ///
  /// Host memory allocated by this function can be used for asynchronous memory
  /// copies on streams. See Stream::thenCopyD2H and Stream::thenCopyH2D.
  template <typename T> Expected<T *> allocateHostMemory(size_t ElementCount) {
    Expected<void *> MaybeMemory =
        PDevice->allocateHostMemory(ElementCount * sizeof(T));
    if (!MaybeMemory)
      return MaybeMemory.takeError();
    return static_cast<T *>(*MaybeMemory);
  }

  /// Frees memory previously allocated with allocateHostMemory.
  template <typename T> Error freeHostMemory(T *Memory) {
    return PDevice->freeHostMemory(Memory);
  }

  /// Registers a previously allocated host array of type T for asynchronous
  /// memory operations.
  ///
  /// Host memory registered by this function can be used for asynchronous
  /// memory copies on streams. See Stream::thenCopyD2H and Stream::thenCopyH2D.
  template <typename T>
  Error registerHostMemory(T *Memory, size_t ElementCount) {
    return PDevice->registerHostMemory(Memory, ElementCount * sizeof(T));
  }

  /// Unregisters host memory previously registered by registerHostMemory.
  template <typename T> Error unregisterHostMemory(T *Memory) {
    return PDevice->unregisterHostMemory(Memory);
  }

  /// \anchor DeviceHostSyncCopyGroup
  /// \name Host-synchronous device memory copying functions
  ///
  /// These methods block the calling host thread while copying data to or from
  /// device memory. On the device side, these methods do not block any ongoing
  /// device calls.
  ///
  /// There are no restrictions on the host memory that is used as a source or
  /// destination in these copy methods, so there is no need to allocate that
  /// host memory using allocateHostMemory or register it with
  /// registerHostMemory.
  ///
  /// Each of these methods has a single template parameter, T, that specifies
  /// the type of data being copied. The ElementCount arguments specify the
  /// number of objects of type T to be copied.
  ///
  /// For ease of use, each of the methods is overloaded to take either a
  /// GlobalDeviceMemorySlice or a GlobalDeviceMemory argument in the device
  /// memory argument slots, and the GlobalDeviceMemory arguments are just
  /// converted to GlobalDeviceMemorySlice arguments internally by using
  /// GlobalDeviceMemory::asSlice.
  ///
  /// These methods perform bounds checking to make sure that the ElementCount
  /// is not too large for the source or destination. For methods that do not
  /// take an ElementCount argument, an error is returned if the source size
  /// does not exactly match the destination size.
  ///@{

  template <typename T>
  Error synchronousCopyD2H(GlobalDeviceMemorySlice<T> Src,
                           llvm::MutableArrayRef<T> Dst, size_t ElementCount) {
    if (ElementCount > Src.getElementCount())
      return make_error("copying too many elements, " +
                        llvm::Twine(ElementCount) +
                        ", from a device array of element count " +
                        llvm::Twine(Src.getElementCount()));
    if (ElementCount > Dst.size())
      return make_error(
          "copying too many elements, " + llvm::Twine(ElementCount) +
          ", to a host array of element count " + llvm::Twine(Dst.size()));
    return PDevice->synchronousCopyD2H(Src.getBaseMemory().getHandle(),
                                       Src.getElementOffset() * sizeof(T),
                                       Dst.data(), 0, ElementCount * sizeof(T));
  }

  template <typename T>
  Error synchronousCopyD2H(GlobalDeviceMemorySlice<T> Src,
                           llvm::MutableArrayRef<T> Dst) {
    if (Src.getElementCount() != Dst.size())
      return make_error(
          "array size mismatch for D2H, device source has element count " +
          llvm::Twine(Src.getElementCount()) +
          " but host destination has element count " + llvm::Twine(Dst.size()));
    return synchronousCopyD2H(Src, Dst, Src.getElementCount());
  }

  template <typename T>
  Error synchronousCopyD2H(GlobalDeviceMemorySlice<T> Src, T *Dst,
                           size_t ElementCount) {
    return synchronousCopyD2H(Src, llvm::MutableArrayRef<T>(Dst, ElementCount),
                              ElementCount);
  }

  template <typename T>
  Error synchronousCopyD2H(GlobalDeviceMemory<T> Src,
                           llvm::MutableArrayRef<T> Dst, size_t ElementCount) {
    return synchronousCopyD2H(Src.asSlice(), Dst, ElementCount);
  }

  template <typename T>
  Error synchronousCopyD2H(GlobalDeviceMemory<T> Src,
                           llvm::MutableArrayRef<T> Dst) {
    return synchronousCopyD2H(Src.asSlice(), Dst);
  }

  template <typename T>
  Error synchronousCopyD2H(GlobalDeviceMemory<T> Src, T *Dst,
                           size_t ElementCount) {
    return synchronousCopyD2H(Src.asSlice(), Dst, ElementCount);
  }

  template <typename T>
  Error synchronousCopyH2D(llvm::ArrayRef<T> Src,
                           GlobalDeviceMemorySlice<T> Dst,
                           size_t ElementCount) {
    if (ElementCount > Src.size())
      return make_error(
          "copying too many elements, " + llvm::Twine(ElementCount) +
          ", from a host array of element count " + llvm::Twine(Src.size()));
    if (ElementCount > Dst.getElementCount())
      return make_error("copying too many elements, " +
                        llvm::Twine(ElementCount) +
                        ", to a device array of element count " +
                        llvm::Twine(Dst.getElementCount()));
    return PDevice->synchronousCopyH2D(
        Src.data(), 0, Dst.getBaseMemory().getHandle(),
        Dst.getElementOffset() * sizeof(T), ElementCount * sizeof(T));
  }

  template <typename T>
  Error synchronousCopyH2D(llvm::ArrayRef<T> Src,
                           GlobalDeviceMemorySlice<T> Dst) {
    if (Src.size() != Dst.getElementCount())
      return make_error(
          "array size mismatch for H2D, host source has element count " +
          llvm::Twine(Src.size()) +
          " but device destination has element count " +
          llvm::Twine(Dst.getElementCount()));
    return synchronousCopyH2D(Src, Dst, Dst.getElementCount());
  }

  template <typename T>
  Error synchronousCopyH2D(T *Src, GlobalDeviceMemorySlice<T> Dst,
                           size_t ElementCount) {
    return synchronousCopyH2D(llvm::ArrayRef<T>(Src, ElementCount), Dst,
                              ElementCount);
  }

  template <typename T>
  Error synchronousCopyH2D(llvm::ArrayRef<T> Src, GlobalDeviceMemory<T> Dst,
                           size_t ElementCount) {
    return synchronousCopyH2D(Src, Dst.asSlice(), ElementCount);
  }

  template <typename T>
  Error synchronousCopyH2D(llvm::ArrayRef<T> Src, GlobalDeviceMemory<T> Dst) {
    return synchronousCopyH2D(Src, Dst.asSlice());
  }

  template <typename T>
  Error synchronousCopyH2D(T *Src, GlobalDeviceMemory<T> Dst,
                           size_t ElementCount) {
    return synchronousCopyH2D(Src, Dst.asSlice(), ElementCount);
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemorySlice<T> Src,
                           GlobalDeviceMemorySlice<T> Dst,
                           size_t ElementCount) {
    if (ElementCount > Src.getElementCount())
      return make_error("copying too many elements, " +
                        llvm::Twine(ElementCount) +
                        ", from a device array of element count " +
                        llvm::Twine(Src.getElementCount()));
    if (ElementCount > Dst.getElementCount())
      return make_error("copying too many elements, " +
                        llvm::Twine(ElementCount) +
                        ", to a device array of element count " +
                        llvm::Twine(Dst.getElementCount()));
    return PDevice->synchronousCopyD2D(
        Src.getBaseMemory().getHandle(), Src.getElementOffset() * sizeof(T),
        Dst.getBaseMemory().getHandle(), Dst.getElementOffset() * sizeof(T),
        ElementCount * sizeof(T));
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemorySlice<T> Src,
                           GlobalDeviceMemorySlice<T> Dst) {
    if (Src.getElementCount() != Dst.getElementCount())
      return make_error(
          "array size mismatch for D2D, device source has element count " +
          llvm::Twine(Src.getElementCount()) +
          " but device destination has element count " +
          llvm::Twine(Dst.getElementCount()));
    return synchronousCopyD2D(Src, Dst, Src.getElementCount());
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemory<T> Src,
                           GlobalDeviceMemorySlice<T> Dst,
                           size_t ElementCount) {
    return synchronousCopyD2D(Src.asSlice(), Dst, ElementCount);
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemory<T> Src,
                           GlobalDeviceMemorySlice<T> Dst) {
    return synchronousCopyD2D(Src.asSlice(), Dst);
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemorySlice<T> Src,
                           GlobalDeviceMemory<T> Dst, size_t ElementCount) {
    return synchronousCopyD2D(Src, Dst.asSlice(), ElementCount);
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemorySlice<T> Src,
                           GlobalDeviceMemory<T> Dst) {
    return synchronousCopyD2D(Src, Dst.asSlice());
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemory<T> Src, GlobalDeviceMemory<T> Dst,
                           size_t ElementCount) {
    return synchronousCopyD2D(Src.asSlice(), Dst.asSlice(), ElementCount);
  }

  template <typename T>
  Error synchronousCopyD2D(GlobalDeviceMemory<T> Src,
                           GlobalDeviceMemory<T> Dst) {
    return synchronousCopyD2D(Src.asSlice(), Dst.asSlice());
  }

  ///@} End host-synchronous device memory copying functions

private:
  PlatformDevice *PDevice;
};

} // namespace streamexecutor

#endif // STREAMEXECUTOR_DEVICE_H
