-- GENERATED by C->Haskell Compiler, version 0.16.6 Crystal Seed, 24 Jan 2009 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "./Foreign/OpenCL/Bindings/Device.chs" #-}
{-# LANGUAGE ForeignFunctionInterface #-}
-- |
-- Module      : Foreign.OpenCL.Bindings.Device
-- Copyright   : (c) 2011, Martin Dybdal
-- License     : BSD3
-- 
-- Maintainer  : Martin Dybdal <dybber@dybber.dk>
-- Stability   : experimental
-- Portability : non-portable (GHC extensions)
--
-- OpenCL bindings for querying a list of available device and
-- information about those devices. See section 4.2 in the OpenCL
-- specification

module Foreign.OpenCL.Bindings.Device (
   getDeviceIDs,

   deviceAddressBits, deviceAvailable, deviceCompilerAvailable,
   deviceEndianLittle, deviceErrorCorrectionSupport,

   deviceExecutionCapabilities,

   deviceExtensions, deviceGlobalMemCacheSize, deviceGlobalMemCacheLineSize,
   deviceGlobalMemSize, deviceGlobalMemCacheType,
   deviceLocalMemSize, deviceLocalMemType,

   deviceImageSupport, deviceImage2DMaxSize, deviceImage3DMaxSize,

   deviceMaxClockFrequency, deviceMaxComputeUnits, deviceMaxConstantArgs,
   deviceMaxConstantBufferSize, deviceMaxMemAllocSize, deviceMaxParameterSize,
   deviceMaxReadImageArgs, deviceMaxSamplers, deviceMaxWorkGroupSize,
   deviceMaxWorkItemDimensions, deviceMaxWorkItemSizes,
   deviceMaxWriteImageArgs, deviceMemBaseAddrAlign, deviceMinDataTypeAlignSize,
   deviceName, devicePlatform, devicePreferredVectorWidthChar,
   devicePreferredVectorWidthShort, devicePreferredVectorWidthInt,
   devicePreferredVectorWidthLong, devicePreferredVectorWidthFloat,
   deviceProfile, deviceProfilingTimerResolution,
   deviceQueueProperties, deviceSingleFPConfig,
   deviceType, deviceVendor, deviceVendorID, deviceVersion, deviceDriverVersion
 ) where



import Control.Monad
import Control.Applicative

import Data.Word

import Foreign.C.Types
import Foreign.Ptr
import Foreign.Storable
import Foreign.Marshal

import Foreign.OpenCL.Bindings.Internal.Types
{-# LINE 54 "./Foreign/OpenCL/Bindings/Device.chs" #-}

import Foreign.OpenCL.Bindings.Internal.Error
import Foreign.OpenCL.Bindings.Internal.Util
import Foreign.OpenCL.Bindings.Internal.Logging as Log

-- | Obtain a list of available devices on a platform.
getDeviceIDs :: [DeviceType] -- ^ The types of devices to query
             -> PlatformID
             -> IO [DeviceID]
getDeviceIDs typ platform = do
  Log.debug "Invoking clGetDeviceIDs"
  getList (clGetDeviceIDs_ platform (enumToBitfield typ))
 where
  clGetDeviceIDs_ pform devtype num_entries devs num_devs =
    checkClError "clGetDeviceIDs" =<< 
      clGetDeviceIDs pform devtype num_entries devs num_devs
   
getDeviceInfo device info =
    getInfo (clGetDeviceInfo_ device) info

clGetDeviceInfo_ device name size value size_ret =
  checkClError "clGetDeviceInfo" =<< 
    clGetDeviceInfo device name size value size_ret

------- Below are the device info query functions --------

-- |The default compute device address space size in bits. (Supported
-- values in OpenCL 1.1.: 32 bits or 64 bits)
deviceAddressBits :: DeviceID -> IO Word32
deviceAddressBits dev = fromIntegral `fmap` (getDeviceInfo dev DeviceAddressBits :: IO ClUInt)

-- |True if the device is available.
deviceAvailable :: DeviceID -> IO Bool
deviceAvailable dev = getDeviceInfo dev DeviceAvailable

-- |True if the compiler is available, can only be false for the embedded
-- profile.
deviceCompilerAvailable :: DeviceID -> IO Bool
deviceCompilerAvailable dev = getDeviceInfo dev DeviceCompilerAvailable

-- |True if the device is little endian.
deviceEndianLittle :: DeviceID -> IO Bool
deviceEndianLittle dev = getDeviceInfo dev DeviceEndianLittle

-- |True if the device supports error connection for memories, cache, and
-- registers.
deviceErrorCorrectionSupport :: DeviceID -> IO Bool
deviceErrorCorrectionSupport dev = getDeviceInfo dev DeviceErrorCorrectionSupport

-- |The execution capabilities of the device
deviceExecutionCapabilities :: DeviceID -> IO [DeviceExecCapabilities]
deviceExecutionCapabilities dev =
   enumFromBitfield caps <$>
     (getDeviceInfo dev DeviceExecutionCapabilities :: IO (CULLong))
 where
   caps = [ExecKernel, ExecNativeKernel]

-- |The extensions supported by the device
deviceExtensions :: DeviceID -> IO [String]
deviceExtensions dev = return . words =<< getDeviceInfo dev DeviceExtensions

-- |The size in bytes of the global memory cache
deviceGlobalMemCacheSize :: DeviceID -> IO ClULong
deviceGlobalMemCacheSize dev = getDeviceInfo dev DeviceGlobalMemCacheSize

-- |Size of global memory cache line size in bytes
deviceGlobalMemCacheLineSize :: DeviceID -> IO ClUInt
deviceGlobalMemCacheLineSize dev = getDeviceInfo dev DeviceGlobalMemCachelineSize

-- |Size of global memory size in bytes
deviceGlobalMemSize :: DeviceID -> IO ClULong
deviceGlobalMemSize dev = getDeviceInfo dev DeviceGlobalMemSize

-- |The type of global memory cache on the device.
deviceGlobalMemCacheType :: DeviceID -> IO DeviceMemCacheType
deviceGlobalMemCacheType dev = do
   typ <- getDeviceInfo dev DeviceGlobalMemCacheType :: IO (CUInt)
{-# LINE 130 "./Foreign/OpenCL/Bindings/Device.chs" #-}

   return . toEnum $ fromIntegral typ

-- |True if images are supported by the device.
deviceImageSupport :: DeviceID -> IO Bool
deviceImageSupport dev = getDeviceInfo dev DeviceImageSupport

-- |Max size of a 2D image (width, height)
deviceImage2DMaxSize :: DeviceID -> IO (CSize, CSize)
deviceImage2DMaxSize dev = do
   w <- getDeviceInfo dev DeviceImage2DMaxWidth
   h <- getDeviceInfo dev DeviceImage2DMaxHeight
   return (w,h)

-- |Max size of a 3D image (width, height, depth)
deviceImage3DMaxSize :: DeviceID -> IO (CSize, CSize, CSize)
deviceImage3DMaxSize dev = do
   w <- getDeviceInfo dev DeviceImage3DMaxWidth
   h <- getDeviceInfo dev DeviceImage3DMaxHeight
   d <- getDeviceInfo dev DeviceImage3DMaxDepth
   return (w, h, d)

-- |The size of the local memory arena in bytes.
deviceLocalMemSize :: DeviceID -> IO ClULong
deviceLocalMemSize dev = getDeviceInfo dev DeviceLocalMemSize

-- |The type of local memory on the device.
deviceLocalMemType :: DeviceID -> IO DeviceLocalMemType
deviceLocalMemType dev = do
   typ <- getDeviceInfo dev DeviceLocalMemType :: IO (CUInt)
{-# LINE 159 "./Foreign/OpenCL/Bindings/Device.chs" #-}

   return . toEnum $ fromIntegral typ

-- |Maximum configured clock frequency of the device in MHz
deviceMaxClockFrequency :: DeviceID -> IO Word32
deviceMaxClockFrequency dev = fromIntegral `fmap` (getDeviceInfo dev DeviceMaxClockFrequency :: IO ClUInt)

-- |The number of parallel compute cos on the device
deviceMaxComputeUnits :: DeviceID -> IO Word32
deviceMaxComputeUnits dev = fromIntegral `fmap` (getDeviceInfo dev DeviceMaxComputeUnits :: IO ClUInt)

-- |Max number of constant arguments to a kernel
deviceMaxConstantArgs :: DeviceID -> IO ClUInt
deviceMaxConstantArgs dev = getDeviceInfo dev DeviceMaxConstantArgs

-- |Max size in bytes of a constant buffer allocation
deviceMaxConstantBufferSize :: DeviceID -> IO ClULong
deviceMaxConstantBufferSize dev = getDeviceInfo dev DeviceMaxConstantBufferSize

-- |Max size of device memory allocation in bytes
deviceMaxMemAllocSize :: DeviceID -> IO ClULong
deviceMaxMemAllocSize dev = getDeviceInfo dev DeviceMaxMemAllocSize

-- |Max size in bytes of the arguments that can be passed to a kernel
deviceMaxParameterSize :: DeviceID -> IO CSize
deviceMaxParameterSize dev = getDeviceInfo dev DeviceMaxParameterSize

-- |Maximum number of simultaneous image objects that can be read by a kernel
deviceMaxReadImageArgs :: DeviceID -> IO ClUInt
deviceMaxReadImageArgs dev = getDeviceInfo dev DeviceMaxReadImageArgs

-- |Maximum number of samplers that can be used in a kernel
deviceMaxSamplers :: DeviceID -> IO ClUInt
deviceMaxSamplers dev = getDeviceInfo dev DeviceMaxSamplers

-- |Maximum number of work-items in a work-group executing a kernel using the
-- data parallel execution model.
deviceMaxWorkGroupSize :: DeviceID -> IO CSize
deviceMaxWorkGroupSize dev = getDeviceInfo dev DeviceMaxWorkGroupSize

-- |Maximum number of dimensions for work-item IDs used by the data parallel
-- execution model.
deviceMaxWorkItemDimensions :: DeviceID -> IO ClUInt
deviceMaxWorkItemDimensions dev = getDeviceInfo dev DeviceMaxWorkItemDimensions

-- |Maximum number of work items that can be specified in each dimension of the
-- work-group when using the data parallel execution model.
deviceMaxWorkItemSizes :: DeviceID -> IO [CSize]
deviceMaxWorkItemSizes dev = do
   dim <- fromIntegral `fmap` deviceMaxWorkItemDimensions dev
   let array_size = fromIntegral $ dim * (fromIntegral $ sizeOf (undefined :: CSize))
   alloca $ \psize ->
     allocaArray dim $ \arr -> do
       _ <- clGetDeviceInfo_ dev (fromIntegral $ fromEnum DeviceMaxWorkItemSizes)
                             array_size (castPtr arr) psize
       size' <- peek psize
       when (array_size /= size') $ error "Size mismatch in element size array"
       mapM (peekElemOff arr) [0 .. dim - 1]

-- |Maximum number of simultaneous image objects that can be written by a kernel
deviceMaxWriteImageArgs :: DeviceID -> IO ClUInt
deviceMaxWriteImageArgs dev = getDeviceInfo dev DeviceMaxWriteImageArgs

-- |Describes the alignment in bits of the base address of any allocated memory
-- object
deviceMemBaseAddrAlign :: DeviceID -> IO ClUInt
deviceMemBaseAddrAlign dev = getDeviceInfo dev DeviceMemBaseAddrAlign

-- |The smallest alignment in bytes which can be used for any data type
deviceMinDataTypeAlignSize :: DeviceID -> IO ClUInt
deviceMinDataTypeAlignSize dev = getDeviceInfo dev DeviceMinDataTypeAlignSize

-- |The name of the device
deviceName :: DeviceID -> IO String
deviceName dev = getDeviceInfo dev DeviceName

-- |The platform associated with this device
devicePlatform :: DeviceID -> IO PlatformID
devicePlatform dev = getDeviceInfo dev DevicePlatform

-- |Preferred native number of elements in char vectors
devicePreferredVectorWidthChar :: DeviceID -> IO ClUInt
devicePreferredVectorWidthChar dev = getDeviceInfo dev DevicePreferredVectorWidthChar

-- |Preferred native number of elements in short vectors
devicePreferredVectorWidthShort :: DeviceID -> IO ClUInt
devicePreferredVectorWidthShort dev = getDeviceInfo dev DevicePreferredVectorWidthShort

-- |Preferred native number of elements in int vectors
devicePreferredVectorWidthInt :: DeviceID -> IO ClUInt
devicePreferredVectorWidthInt dev = getDeviceInfo dev DevicePreferredVectorWidthInt

-- |Preferred native number of elements in long vectors
devicePreferredVectorWidthLong :: DeviceID -> IO ClUInt
devicePreferredVectorWidthLong dev = getDeviceInfo dev DevicePreferredVectorWidthLong

-- |Preferred native number of elements in float vectors
devicePreferredVectorWidthFloat :: DeviceID -> IO ClUInt
devicePreferredVectorWidthFloat dev = getDeviceInfo dev DevicePreferredVectorWidthFloat

-- |The profile supported by the device
deviceProfile :: DeviceID -> IO String
deviceProfile dev = getDeviceInfo dev DeviceProfile :: IO String

-- |The resolution in nanoseconds of the device timer
deviceProfilingTimerResolution :: DeviceID -> IO CSize
deviceProfilingTimerResolution dev = getDeviceInfo dev DeviceProfilingTimerResolution

-- |The command queue properties supported by the device
deviceQueueProperties :: DeviceID -> IO [CommandQueueProperties]
deviceQueueProperties dev =
   enumFromBitfield queue_props <$> 
     (getDeviceInfo dev DeviceQueueProperties :: IO (CULLong))
 where
   queue_props = [QueueOutOfOrderExecModeEnable,
                  QueueProfilingEnable]

-- |Describe the single precision floating point capability of the device
deviceSingleFPConfig :: DeviceID -> IO [DeviceFPConfig]
deviceSingleFPConfig dev =
   enumFromBitfield fps <$> 
     (getDeviceInfo dev DeviceSingleFPConfig :: IO (CULLong))
 where
  fps = [FpDenorm,
         FpInfNan,
         FpRoundToNearest,
         FpRoundToZero,
         FpRoundToInf,
         FpFma,
         FpSoftFloat]

-- |Describe the type of the device
deviceType :: DeviceID -> IO [DeviceType]
deviceType dev =
  enumFromBitfield device_types <$>
    (getDeviceInfo dev DeviceType :: IO (CULLong))
 where
   device_types = [DeviceTypeDefault,
                   DeviceTypeCpu,
                   DeviceTypeGpu,
                   DeviceTypeAccelerator,
                   DeviceTypeAll]

-- |Obtain the device vendor name
deviceVendor :: DeviceID -> IO String
deviceVendor dev = getDeviceInfo dev DeviceVendor

-- |Obtain a unique device vendor indentifier, which may be the PCIe ID.
deviceVendorID :: DeviceID -> IO ClUInt
deviceVendorID dev = getDeviceInfo dev DeviceVendorID

-- |Obtain the OpenCL version supported by the device
deviceVersion :: DeviceID -> IO String
deviceVersion dev = getDeviceInfo dev DeviceVersion

-- |Obtain the OpenCL software driver version string
deviceDriverVersion :: DeviceID -> IO String
deviceDriverVersion dev = getDeviceInfo dev DriverVersion


foreign import ccall unsafe "Foreign/OpenCL/Bindings/Device.chs.h clGetDeviceIDs"
  clGetDeviceIDs :: ((PlatformID) -> (CULLong -> (CUInt -> ((Ptr (DeviceID)) -> ((Ptr CUInt) -> (IO CInt))))))

foreign import ccall unsafe "Foreign/OpenCL/Bindings/Device.chs.h clGetDeviceInfo"
  clGetDeviceInfo :: ((DeviceID) -> (CUInt -> (CULong -> ((Ptr ()) -> ((Ptr CULong) -> (IO CInt))))))