/*
 * oclh_h_ws_base.h
 *      Author: havock
 */
#ifndef OCLH_H_WS_BASE_H_
#define OCLH_H_WS_BASE_H_ 1
#include <sys/types.h>
#include <stdlib.h>
#include <stdarg.h>
#include <CL/opencl.h>
#include <oclh_h_base_log.h>

#define __GHM_U64STRIPTO2B(___GHMARG_U64STRIPTO2B) \
    (((uint64_t)(___GHMARG_U64STRIPTO2B))&((uint64_t)0x000000000000ffff))

typedef enum _GHE_SOURCE_TYPE {
    _GHE_HL_LISTINGS       = 0,
    _GHE_IR_LISTINGS       = 1,
    _GHE_SEPARATED_OBJECTS = 2,
    _GHE_LINKED_OBJECTS    = 3
} _GHE_SRCTYPE;

typedef enum _GHE_BUILD_LOG_MODE {
    _GHE_NO_BUILD_LOG                 = 0,
    _GHE_BUILD_LOG_IN_WRKSET_LOG      = 1,
    _GHE_BUILD_LOG_IN_SEPARATED_FILES = 2
} _GHE_BUILD_LOG_MODE;

typedef enum _GHE_OUTPUT_NAME_TYPE {
    _GHE_VOLATILE_OUTPUT_NAME = 0,
    _GHE_VERBATIM_OUTPUT_NAME = 1
} _GHE_OUTNAME_TYPE;

#pragma pack(push,1)
typedef struct _GHT_WORKINGSET {
    void*            pwSetAddr;    /* self */
    cl_command_queue Queue;        /* key pointer */
    cl_program       Program;
    size_t           szNofCmpUnits;/* number of  computational units
                                      (a.k.a. processor core) */
    size_t           szNofRPThrds; /* number of real parallel threads */
    size_t           szMaxWGsz;    /* max number of work-items in a work-group
                                      it represents the number of virtual
                                      threads executed on a computational unit
                                      (a.k.a. processor core) */
    size_t           szNofWIinWG;
    size_t           szNofAllWI;
    size_t*          pszMemBytes;
    _GHT_LOG         Log;
    int32_t          i32EigenLogFlag;
    cl_int           APIErr;
    cl_kernel*       pKernels;
    int32_t          KerErr;
    cl_mem           d_pKerErr;
    void*            pvDat;
    int32_t          (*pfnDatCleaner)(const struct _GHT_WORKINGSET);
} _GHT_WRKSET;
#pragma pack(pop)

_GHT_WRKSET _ghf_declWS(void);
int32_t _ghf_genrWS(      _GHT_WRKSET*  const pwSet,
                    const _GHT_LOG            Log,
                    const int32_t             i32ExclusiveLogFlag,
                    const cl_device_id        clWrkDev,
                          char**        const ppcCLProgramSources,
                    const _GHE_SRCTYPE        SourceType,
                    const char*         const pcOCLBuildOpts,
                    const _GHE_LOGLVL         LogLvl,
                    const _GHE_BUILD_LOG_MODE BuildLogMode
#if defined(__OCLH_BUILDER_FLAG) || \
    defined(__OCLH_COMPILER_ONLY_FLAG) || \
    defined(__OCLH_LINKER_ONLY_FLAG)
                  ,       char*        const  pcOutputPrefix
#endif /* defined(__OCLH_BUILDER_FLAG) ||
          defined(__OCLH_COMPILER_ONLY_FLAG) ||
          defined(__OCLH_LINKER_ONLY_FLAG) */
                                                            );
int32_t _ghf_wipeWS(_GHT_WRKSET* const pwSet);

int32_t _ghf_isWS_LogValid(const _GHT_WRKSET wSet);
int32_t _ghf_recalcWS_WIWG_1x1(  _GHT_WRKSET* const pwSet);
int32_t _ghf_recalcWS_WIWG_dense(_GHT_WRKSET* const pwSet,
                           const size_t             szNofAllTasks);
int32_t _ghf_flfnWS(_GHT_WRKSET wSet);

cl_device_id    _ghf_getWS_Dev(        _GHT_WRKSET wSet);
cl_context      _ghf_getWS_Ctx(        _GHT_WRKSET wSet);
cl_build_status _ghf_getWS_BuildStatus(_GHT_WRKSET wSet);
cl_kernel       _ghf_getWS_KernByName( _GHT_WRKSET wSet,const char* pcKernName);
cl_uint         _ghf_getWS_RefCntOfMem(_GHT_WRKSET wSet,const cl_mem clMem);
size_t          _ghf_getWS_MaxWIinWG(  _GHT_WRKSET wSet);
cl_uint         _ghf_getWS_MaxCmpUnits(_GHT_WRKSET wSet);
int32_t         _ghf_saveWS_ProgramBinaries(_GHT_WRKSET wSet,
                                            char* const pcOutputName,
                                            _GHE_OUTNAME_TYPE OutNameType);
int32_t         _ghf_wdcChkWS_APIErr(      _GHT_WRKSET wSet,
                                     const char* const pcAPICall,
                                     const int32_t i32FlashFlag);
int32_t         _ghf_wdcChkWS_KerErr(      _GHT_WRKSET wSet,
                                     const cl_kernel   clKer);
int32_t         _ghf_wdcSetWS_KerErrToZero(_GHT_WRKSET wSet);
int32_t         _ghf_wdcSetWS_KernArgs(    _GHT_WRKSET wSet,
                                     const cl_kernel kr, ...);
int32_t         _ghf_wdcBExecWS_Kern(      _GHT_WRKSET wSet,
                                     const char* const pcKernName, ...);

#pragma pack(push,1)
typedef struct _GHT_LIST_OF_DEVICES_DESCRIPTION {
    cl_uint* pcluIdxs;
    char*    pcWC;
} _GHT_DEVLIST_DESC;
#pragma pack(pop)

_GHT_DEVLIST_DESC _ghf_declDevLstDesc(void);
int32_t _ghf_isDevLstDesc_Valid(const _GHT_DEVLIST_DESC DevLstDesc);
int32_t _ghf_addDevIdxToDevLstDesc(   _GHT_DEVLIST_DESC* const pDevLstDesc,
                                      const cl_uint            cluIdx);
int32_t _ghf_setDevLstDesc_DevNameWC( _GHT_DEVLIST_DESC* const pDevLstDesc,
                                      const char* const pcWC);
int32_t _ghf_wipeDevLstDesc(          _GHT_DEVLIST_DESC* const pDevLstDesc);


#pragma pack(push,1)
typedef struct _GHT_ALL_OF_WORKING_SETS {
    _GHT_WRKSET* pWSet;
    uint64_t u64NofWSs;
    _GHT_LOG Log;
    const void* const pvCLProgramSource;
    const _GHE_SRCTYPE SourceType;
    const _GHE_LOGLVL LogLevel;
    const _GHE_BUILD_LOG_MODE BuildLogMode;
} _GHT_AWSS;
#pragma pack(pop)
_GHT_AWSS _ghf_declAWSs(const _GHE_LOGLVL  LogLvl,
                        const _GHE_BUILD_LOG_MODE BuildLogMode);
int32_t _ghf_genrAWSs(      _GHT_AWSS*   const pAWSs,
                      const _GHT_LOG           Log,
                      const _GHT_DEVLIST_DESC  DevLstDesc,
                            char**       const ppcCLProgramSources,
                      const _GHE_SRCTYPE       SourceType,
                      const char*        const OCLBuildOpts
#if defined(__OCLH_BUILDER_FLAG) || \
    defined(__OCLH_COMPILER_ONLY_FLAG) || \
    defined(__OCLH_LINKER_ONLY_FLAG)
                    ,       char*        const pcOutputPrefix
#endif /* defined(__OCLH_BUILDER_FLAG) ||
          defined(__OCLH_COMPILER_ONLY_FLAG) ||
          defined(__OCLH_LINKER_ONLY_FLAG) */
                                                      );
int32_t _ghf_wipeAWSs(_GHT_AWSS* const pAWSs);

int32_t _ghf_buildDevList(_GHT_WRKSET wSet, cl_device_id** ppDevLst);
int32_t _ghf_wipeDevList(cl_device_id** ppDevLst);







int32_t __ghf_setWS_TextProgramId(_GHT_WRKSET wSet,
                                  char* const pcDst,
                                  char* const pcOutputPrefix);

#endif /* OCLH_H_WS_BASE_H_ */
