#ifndef MAGMA_MIC_BINDINGS_H
#define MAGMA_MIC_BINDINGS_H

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <scif.h>
#include <mkl.h>
#include <map>
#include <vector>

#include "magma.h"
#include "magma_z_bindings.h"
#include "magma_c_bindings.h"
#include "magma_d_bindings.h"
#include "magma_s_bindings.h"

#include "magma_zc_bindings.h"
#include "magma_ds_bindings.h"

#define START_OFFSET    0x80000
#define PAGE_SIZE       0x1000
#define VA_GEN_MIN      0x4000000000000000

#define PRINT_dA               50
#define ALLOCATE_MEM          100
#define FREE_MEM              101
#define CLOSE_MIC             200

#define MIC_FAILURE           303

#define READFROM_DEV          400
#define WRITETO_DEV           401

#define magma_mic_SGEMM       500
#define magma_mic_STRSM       501
#define magma_mic_SSYRK       502
#define magma_mic_SLARFT      503
#define magma_mic_SLARFB      504
#define magma_mic_STRANSPOSE  505
#define magma_mic_STRMM       506
#define magma_mic_SYNC        507
#define magma_mic_SLASWP      508
#define magma_mic_SGEMV       509
#define magma_mic_SSYR2K      510
#define magma_mic_SSYMM       511
#define magma_mic_STRSM_GEMM  512
#define magma_mic_SLARFB_GEMM 513
#define magma_mic_SLAG2D      514
#define magma_mic_STRSV       515
#define magma_mic_SSYMV       520
#define magma_mic_SHEMV       521
#define magma_mic_STRMV       522
#define magma_mic_SSYMV2      523
#define magma_mic_SSYRK_MMIC      524
#define magma_mic_SSYR2K_MMIC     525
#define magma_mic_SLASET          526
#define magma_mic_SSWAP           527
#define magma_mic_SCOPY       528

#define magma_mic_DGEMM       600
#define magma_mic_DTRSM       601
#define magma_mic_DSYRK       602
#define magma_mic_DLARFT      603
#define magma_mic_DLARFB      604
#define magma_mic_DTRANSPOSE  605
#define magma_mic_DTRMM       606
#define magma_mic_DYNC        607
#define magma_mic_DLASWP      608
#define magma_mic_DGEMV       609
#define magma_mic_DSYR2K      610
#define magma_mic_DSYMM       611
#define magma_mic_DTRSM_GEMM  612
#define magma_mic_DLARFB_GEMM 613
#define magma_mic_DLAG2S      614
#define magma_mic_DTRSV       615
#define magma_mic_DSGESV      616
#define magma_mic_DSYMV       620
#define magma_mic_DHEMV       621
#define magma_mic_DTRMV       622
#define magma_mic_DSYMV2      623
#define magma_mic_DSYRK_MMIC      624
#define magma_mic_DSYR2K_MMIC     625
#define magma_mic_DLASET          626
#define magma_mic_DSWAP           627
#define magma_mic_DCOPY       628

#define magma_mic_CGEMM       700
#define magma_mic_CTRSM       701
#define magma_mic_CHERK       702
#define magma_mic_CLARFT      703
#define magma_mic_CLARFB      704
#define magma_mic_CTRANSPOSE  705
#define magma_mic_CTRMM       706
#define magma_mic_CYNC        707
#define magma_mic_CLASWP      708
#define magma_mic_CGEMV       709
#define magma_mic_CHER2K      710
#define magma_mic_CHEMM       711
#define magma_mic_CTRSM_GEMM  712
#define magma_mic_CLARFB_GEMM 713
#define magma_mic_CLAG2Z      714
#define magma_mic_CTRSV       715
#define magma_mic_CSYMV       720
#define magma_mic_CHEMV       721
#define magma_mic_CTRMV       722
#define magma_mic_CSYMV2      723
#define magma_mic_CHERK_MMIC      724
#define magma_mic_CHER2K_MMIC     725
#define magma_mic_CLASET          726
#define magma_mic_CSWAP           727
#define magma_mic_CCOPY       728

#define magma_mic_ZGEMM       800
#define magma_mic_ZTRSM       801
#define magma_mic_ZHERK       802
#define magma_mic_ZLARFT      803
#define magma_mic_ZLARFB      804
#define magma_mic_ZTRANSPOSE  805
#define magma_mic_ZTRMM       806
#define magma_mic_ZYNC        807
#define magma_mic_ZLASWP      808
#define magma_mic_ZGEMV       809
#define magma_mic_ZHER2K      810
#define magma_mic_ZHEMM       811
#define magma_mic_ZTRSM_GEMM  812
#define magma_mic_ZLARFB_GEMM 813
#define magma_mic_ZLAG2C      814
#define magma_mic_ZTRSV       815
#define magma_mic_ZCGESV      816
#define magma_mic_ZSYMV       820
#define magma_mic_ZHEMV       821
#define magma_mic_ZTRMV       822
#define magma_mic_ZSYMV2      823
#define magma_mic_ZHERK_MMIC      824
#define magma_mic_ZHER2K_MMIC     825
#define magma_mic_ZLASET          826
#define magma_mic_ZSWAP           827
#define magma_mic_ZCOPY       828

// globals, defined in magma_mic_bindings.cpp
typedef std::map<off_t, size_t> maptypemem;
typedef std::map<off_t, off_t> maptypeoff;

extern std::vector<maptypemem> gHost_nbyte;
extern std::vector<maptypeoff> gHost_offset;

extern std::vector<maptypemem> gDev_nbyte;
extern std::vector<maptypeoff> gDev_offset;

extern scif_epd_t gEpd;
extern scif_epd_t *gEpd_array;
extern int gNumEpd;
extern int gNumEpd;
extern int gCurrID;


typedef struct mic_memory_info {
    off_t address;
    off_t offset;
    size_t nbyte;
} magma_mic_mem_info;


typedef struct mic_print_param {
    int m;
    int n;
    off_t d_A;
    int lda;
} magma_mic_print_param;


void magma_mic_synchronize_kernels();

int magma_mic_fence_mark( magma_event_t *mark );

int magma_mic_fence_wait( magma_event_t mark );

int magma_mic_memcpy2D_async(
          void *dst, size_t dpitch,
    const void *src, size_t spitch,
    magma_int_t width, magma_int_t height, magma_int_t kind,
    magma_queue_t queue, magma_event_t* event );

#endif // MAGMA_MIC_BINDINGS_H
