#ifndef HIP_TOOLS_HPP
#define HIP_TOOLS_HPP

/*
 *  系统关于HIP的功能函数
 */
 
#include <hip/hip_runtime_api.h>
#include <string>
#include "ilogger.hpp"

#define GPU_BLOCK_THREADS  512


#define KernelPositionBlock											\
	int position = (blockDim.x * blockIdx.x + threadIdx.x);		    \
    if (position >= (edge)) return;


// #define checkHipDriver(call)  sg::check_driver(call, #call, __LINE__, __FILE__)
#define checkHipRuntime(call) sg::check_runtime(call, #call, __LINE__, __FILE__)
#define CHECK(call)                                                                                 \
{                                                                                                   \    
    const hipError_t error = call;                                                                 \    
    if (error != hipSuccess)                                                                       \        
    {                                                                                               \
        printf("Error: %s:%d, ", __FILE__, __LINE__);                                               \    
        printf("code: %d, reason: %s\n", error, hipGetErrorString(error));                         \  
    }                                                                                               \    
}

#define checkHipKernel(...)                                                                         \
    __VA_ARGS__;                                                                                     \
    do{hipError_t cudaStatus = hipPeekAtLastError();                                               \
    if (cudaStatus != hipSuccess){                                                                  \
        printf("launch failed: %s\n", hipGetErrorString(cudaStatus));                                  \
    }} while(0);


#define Assert(op)					 \
	do{                              \
		bool cond = !(!(op));        \
		if(!cond){                   \
			printf("Assert failed, \n" #op);  \
		}                                  \
	}while(false)


struct CUctx_st;
struct CUstream_st;

typedef CUstream_st* ICUStream;
typedef CUctx_st* ICUContext;
typedef void* ICUDeviceptr;
typedef int DeviceID;

namespace sg{
    // bool check_driver(CUresult e, const char* call, int iLine, const char *szFile);
    bool check_runtime(hipError_t e, const char* call, int iLine, const char *szFile);
    bool check_device_id(int device_id);
    int current_device_id();

    dim3 grid_dims(int numJobs);
    dim3 block_dims(int numJobs);

    // return 8.6  etc.
    std::string device_capability(int device_id);
    std::string device_name(int device_id);
    std::string device_description();

    class AutoDevice{
    public:
        AutoDevice(int device_id = 0);
        virtual ~AutoDevice();
    
    private:
        int old_ = -1;
    };
}


#endif // HIP_TOOLS_HPP