/******************************************************************************
*
* Copyright (C) 2009 - 2015 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
#ifndef UNDEFINE_FILE_OPS
#include <errno.h>
#include "xil_types.h"

#ifdef __cplusplus
extern "C" {

}
#endif

/*
 * _open -- open a file descriptor. We don't have a filesystem, so
 *         we return an error.
 */
__attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode)
{
  (void *)buf;
  (void)flags;
  (void)mode;
  errno = EIO;
  return (-1);
}
#endif

__attribute__((weak)) s32 _open(const char8 *buf, s32 flags, s32 mode);


/*
 * main.c: simple test application for Core 1
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "sleep.h"
#include "svm_data_type.h"
#include "testData.h"
#include "testData_int.h"

#include <stdbool.h>
#include "xil_printf.h"
// Add BSP header files
#include <stdlib.h>  // Standard C functions, e.g. exit()
// #include <stdbool.h> // Provides a Boolean data type for ANSI/ISO-C
// #include <arm_neon.h>
#include "xparameters.h" // Parameter definitions for processor periperals
#include "xscugic.h"     // Processor interrupt controller device driver
#include "xsvm_classifier.h"   // Device driver for HLS HW block
#include "xtime_l.h"

#include "sw_tanh_classifier.h"

// HLS svm_classifier HW instance
XSvm_classifier classifier;
//Interrupt Controller Instance
XScuGic ScuGic;
// Global variable definitions - used by ISR
volatile static int classifier_run = 0;
volatile static int classifier_res_vld = 0;

// volatile int data_set_ctr = 0;
// volatile u32 res_hw[TESTDATA_SET_NUM] = {0};

// Setup and helper functions
int setup_interrupt();
int hls_classifier_init(XSvm_classifier *classifier_ptr);
void hls_classifier_start(void *classifier_ptr);
// The ISR prototype
void hls_classifier_isr(void *classifier_ptr);
// Software model of HLS hardware
void sw_cordic_classifier(float ip[DIMENSION], bool *op);

volatile static int data_set_ctr = 0;
volatile static u32 res_hw[TESTDATA_SET_NUM] = {0};
short *classifier_buffer = &testData_int[16*TESTDATA_SET_NUM];

int main()
{
    init_platform();

    print("\r\nCore 1 Build \n");
    	// print("Core 1 Program to test communication with HLS MACC block in PL\n\r");
    	// int data_set_ctr = 0;
    		XTime  start_time = 0;
    		XTime  end_time = 0;
    		int dt = 0;
    		XTime t = 0;
    		int i = 0;

    	   int status;

    	   //Setup the matrix mult
    	   status = hls_classifier_init(&classifier);
    	   if(status != XST_SUCCESS){
    	      print("Core 1 HLS peripheral setup failed\n\r");
    	      exit(-1);
    	   }
    	   //Setup the interrupt
    	   status = setup_interrupt();
    	   if(status != XST_SUCCESS){
    	      print("Core 1 Interrupt setup failed\n\r");
    	      exit(-1);
    	   }

    	   // Get timer offset
    	   XTime_SetTime(0);
    	   XTime_GetTime(&start_time);
    	   XTime_GetTime(&end_time);
    	   dt = end_time - start_time;
    	   /*
    	   printf("Core 1 Precalculation: \n");
    	   printf("Core 1 time test start: %llu \n", start_time);
    	   printf("Core 1 time test end : %llu \n", end_time);
    	   */
    	   // printf("Core 1 time offset : %d \n", dt);

    	   if (XSvm_classifier_IsReady(&classifier))
    	      print("Core 1 HLS peripheral is ready.  Starting... \n");
    	   else {
    	      print("!!! Core 1 HLS peripheral is not ready! Exiting...\n\r");
    	      exit(-1);
    	   }

    	   if (0) {
    		   	 print("\n\r---------------Core 1 Interrupt test-------------- \n\r");

    		     // use interrupt
    		     //classifier_run = 1;
    		     XTime_SetTime(0);
    		     XTime_GetTime(&start_time);
    		     XSvm_classifier_Set_in_V(&classifier, *((XSvm_classifier_In_v *)classifier_buffer));
    		     hls_classifier_start(&classifier);
    		     do{
    		    	 classifier_buffer += 16;
    		    	 XSvm_classifier_Set_in_V(&classifier, *((XSvm_classifier_In_v *)classifier_buffer));

    		    	 while(!classifier_res_vld); // spin
    		    	 classifier_res_vld = 0;

    		    	 res_hw[data_set_ctr] = XSvm_classifier_Get_out_r(&classifier);
    		    	 hls_classifier_start(&classifier);
    		    	 data_set_ctr++;

    	         }while (data_set_ctr < TESTDATA_SET_NUM);

    		     XTime_GetTime(&end_time);
    		     printf("Core 1 HW: \n");
    		     printf("Core 1 time test start: %llu \n", start_time);
    		     printf("Core 1 time test end : %llu \n", end_time);
    		     t = end_time-start_time-dt;
    		     printf("Core 1 time difference : %llu \n", t);
    		     printf("Core 1 Actual hardware time: %f ms.\n", ((float)t)*3e-6);

    	      } else {
    	    	  	  // print("\n\r---------------No interrupt test------------ \n\r");
    	    	  	  XTime_SetTime(0);
    	    	  	  XTime_GetTime(&start_time);
    	    	  	  XSvm_classifier_Set_in_V(&classifier, *((XSvm_classifier_In_v *)classifier_buffer));
    	    	  	  XSvm_classifier_Start(&classifier);
    	    	  	  do
    	    	  	  {
    	    	  		  classifier_buffer += 16;
    	    	  		  XSvm_classifier_Set_in_V(&classifier, *((XSvm_classifier_In_v *)classifier_buffer));
    					  do {
    						  res_hw[data_set_ctr] = XSvm_classifier_Get_out_r(&classifier);
    					  } while (!XSvm_classifier_IsReady(&classifier));
    					  res_hw[data_set_ctr] = XSvm_classifier_Get_out_r(&classifier);
    					  XSvm_classifier_Start(&classifier);
    					  data_set_ctr++;
    	    	  	  }while (data_set_ctr < TESTDATA_SET_NUM);
    	    	  	  XTime_GetTime(&end_time);
    	    	  	  /*

    	      }

    	   	   	 // quick look - deleted later
    	      	 int kk = 0;
    	         for (i = 0; i < TESTDATA_SET_NUM; i++)
    	         {
    	         	   if (res_hw[i] != (u32) testDataLabel[i+TESTDATA_SET_NUM])
    	         		   kk++;
    	         }
    	         printf("Quick look: Core 1 HW error rate: %f\n\r", ((float)kk/1000.0));

    	   // Floating point SW verification process
    	   float *sw_ip = &testData[TESTDATA_SET_NUM*16];
    	   bool res_sw[TESTDATA_SET_NUM] = {0};
    	   bool *sw_op = res_sw;
    	   XTime_SetTime(0);
    	   XTime_GetTime(&start_time);
    	   for (i = 0; i < TESTDATA_SET_NUM; i++)
    	   {
    		   sw_tanh_classifier(sw_ip, sw_op);
    		   sw_ip += 16;
    		   sw_op ++;
    	   }
    	   XTime_GetTime(&end_time);
    	   //printf("Core 1 Floating point SW: \n");
    	   //printf("Core 1 time test start: %llu \n", start_time);
    	   //printf("Core 1 time test end : %llu \n", end_time);
    	   t = end_time-start_time-dt;
    	   //printf("Core 1 time difference : %llu \n", t);
    	   printf("Core 1 software hardware time: %f s.\n", ((float)t)*3e-9);

    	   // Result correctness check
    	   int hw_error = 0;
    	   int sw_error = 0;
    	   for (i = 0; i < TESTDATA_SET_NUM; i++)
    	   {
    	   	   if (res_hw[i] != (u32) testDataLabel[TESTDATA_SET_NUM+i])
    	   		   hw_error++;
    	   	   if (res_sw[i] != (u32) testDataLabel[TESTDATA_SET_NUM+i])
    	   		   sw_error++;
    	   }
    	   // printf("HW error rate: %f\n\r", ((float)hw_error/2000.0));
    	   // printf("SW error rate: %f\n\r", ((float)sw_error/2000.0));

    	   if (hw_error == sw_error) {
    	      printf("*** Core 1 Results match: Error rate = %f ***\n\r", ((float)hw_error/10.0));
    	      status = 0;
    	   }
    	   else {
    	      printf("!!! Core 1 MISMATCH !!!\n\r Error rate = %f \n\r", ((float)hw_error/10.0));
    	      status = -1;
    	   }

    cleanup_platform();
    return 0;
}

int hls_classifier_init(XSvm_classifier *classifier_ptr)
{
	XSvm_classifier_Config *cfgPtr;
   int status;

   cfgPtr = XSvm_classifier_LookupConfig(XPAR_SVM_CLASSIFIER_1_DEVICE_ID);
   if (!cfgPtr) {
      print("ERROR: Lookup of accelerator configuration failed.\n\r");
      return XST_FAILURE;
   }
   status = XSvm_classifier_CfgInitialize(classifier_ptr, cfgPtr);
   if (status != XST_SUCCESS) {
      print("ERROR: Could not initialize accelerator.\n\r");
      return XST_FAILURE;
   }
   return status;
}

void hls_classifier_start(void *classifier_ptr){
	XSvm_classifier *pAccelerator = (XSvm_classifier *)classifier_ptr;
	XSvm_classifier_InterruptEnable(pAccelerator,1);
	XSvm_classifier_InterruptGlobalEnable(pAccelerator);
	XSvm_classifier_Start(pAccelerator);
}

void hls_classifier_isr(void *classifier_ptr){

	XSvm_classifier *pAccelerator = (XSvm_classifier *)classifier_ptr;

   // clear the local interrupt
	XSvm_classifier_InterruptClear(pAccelerator,1);

	// res_hw[data_set_ctr] = XSvm_classifier_Get_out_r(pAccelerator);
	// data_set_ctr++;
    classifier_res_vld = 1;

   // restart the core if it should run again
    /*
   if(classifier_run){
	   input_sw = input_sw ? 0 : 1;
	   XSvm_classifier_Set_input_sw(pAccelerator, (u32) input_sw);
       hls_classifier_start(pAccelerator);
       classifier_buffer += 16;
       if (!input_sw)
       {
        	XSvm_classifier_Set_in_1_V(pAccelerator, *((XSvm_classifier_In_1_v *)classifier_buffer));
        }
        else
        {
          	XSvm_classifier_Set_in_2_V(pAccelerator, *((XSvm_classifier_In_2_v *)classifier_buffer));
        }
   }
   */
}

int setup_interrupt()
{
   //This functions sets up the interrupt on the ARM
   int result;
   XScuGic_Config *pCfg = XScuGic_LookupConfig(XPAR_SCUGIC_SINGLE_DEVICE_ID);
   if (pCfg == NULL){
      print("Core 1 Interrupt Configuration Lookup Failed\n\r");
      return XST_FAILURE;
   }
   result = XScuGic_CfgInitialize(&ScuGic,pCfg,pCfg->CpuBaseAddress);
   if(result != XST_SUCCESS){
      return result;
   }
   // self test
   result = XScuGic_SelfTest(&ScuGic);
   if(result != XST_SUCCESS){
      return result;
   }
   // Initialize the exception handler
   Xil_ExceptionInit();
   // Register the exception handler
   //print("Register the exception handler\n\r");
   Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
   //Enable the exception handler
   Xil_ExceptionEnable();
   // Connect the Adder ISR to the exception table
   //print("Connect the Adder ISR to the Exception handler table\n\r");
   result = XScuGic_Connect(&ScuGic,XPAR_FABRIC_SVM_CLASSIFIER_1_INTERRUPT_INTR,(Xil_InterruptHandler)hls_classifier_isr,&classifier);
   if(result != XST_SUCCESS){
      return result;
   }
   //print("Enable the Adder ISR\n\r");
   XScuGic_Enable(&ScuGic,XPAR_FABRIC_SVM_CLASSIFIER_1_INTERRUPT_INTR);
   return XST_SUCCESS;
}

    	    	  	  printf("Core 1 HW: \n");
    	    	  	  printf("Core 1 time test start: %llu \n", start_time);
    	    	  	  printf("Core 1 time test end : %llu \n", end_time);
    	    	  	  */
    	    	  	  t = end_time-start_time-dt;


/******************************************************************************
*
* Copyright (C) 2009 - 2015 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/****************************************************************************/
/**
*
* @file xil_exception.c
*
* This file contains low-level driver functions for the Cortex A9 exception
* Handler.
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who      Date     Changes
* ----- -------- -------- -----------------------------------------------
* 1.00a ecm/sdm  11/04/09 First release
* 3.05a sdm		 02/02/12 Updated to resiter a null handler only if a handler
*			  		      is not already registered
* 4.2   pkp		 06/19/14 Added default exception handlers for data abort and
*						  prefetch abort using handlers called
*						  DataAbortHandler and PrefetchAbortHandler respectively
*						  Both handlers are registers in vector table entries
*						  using XExc_VectorTable
* 5.1	pkp		 05/13/15 Added debugging message to print address of instruction
*						  causing data abort and prefetch abort
* 5.4	pkp		 12/03/15 Added handler for undefined exception to print the
*						  address of instruction causing exception
* </pre>
*
*****************************************************************************/

/***************************** Include Files ********************************/

#include "xil_types.h"
#include "xil_assert.h"
#include "xil_exception.h"
#include "xpseudo_asm.h"
#include "xdebug.h"
/************************** Constant Definitions ****************************/

/**************************** Type Definitions ******************************/

typedef struct {
	Xil_ExceptionHandler Handler;
	void *Data;
} XExc_VectorTableEntry;

/***************** Macros (Inline Functions) Definitions ********************/

/************************** Function Prototypes *****************************/
static void Xil_ExceptionNullHandler(void *Data);
/************************** Variable Definitions *****************************/
/*
 * Exception vector table to store handlers for each exception vector.
 */
XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] =
{
	{Xil_ExceptionNullHandler, NULL},
	{Xil_UndefinedExceptionHandler, NULL},
	{Xil_ExceptionNullHandler, NULL},
	{Xil_PrefetchAbortHandler, NULL},
	{Xil_DataAbortHandler, NULL},
	{Xil_ExceptionNullHandler, NULL},
	{Xil_ExceptionNullHandler, NULL},
};

u32 UndefinedExceptionAddr;   /* Address of instruction causing Undefined
							 exception */
u32 DataAbortAddr;       /* Address of instruction causing data abort */
u32 PrefetchAbortAddr;   /* Address of instruction causing prefetch abort */

/*****************************************************************************/

/****************************************************************************/
/**
*
* This function is a stub Handler that is the default Handler that gets called
* if the application has not setup a Handler for a specific  exception. The
* function interface has to match the interface specified for a Handler even
* though none of the arguments are used.
*
* @param	Data is unused by this function.
*
* @return	None.
*
* @note		None.
*
*****************************************************************************/
static void Xil_ExceptionNullHandler(void *Data)
{
	(void *)Data;
DieLoop: goto DieLoop;
}

/****************************************************************************/
/**
* The function is a common API used to initialize exception handlers across all
* processors supported. For ARM CortexA9, the exception handlers are being
* initialized statically and hence this function does not do anything.
* However, it is still present to avoid any compilation issues in case an
* application uses this API and also to take care of backward compatibility
* issues (in earlier versions of BSPs, this API was being used to initialize
* exception handlers).
*
* @param	None.
*
* @return	None.
*
* @note		None.
*
*****************************************************************************/
void Xil_ExceptionInit(void)
{
	return;
}

/*****************************************************************************/
/**
*
* Makes the connection between the Id of the exception source and the
* associated Handler that is to run when the exception is recognized. The
* argument provided in this call as the Data is used as the argument
* for the Handler when it is called.
*
* @param	exception_id contains the ID of the exception source and should
*		be in the range of 0 to XIL_EXCEPTION_ID_LAST.
		See xil_exception_l.h for further information.
* @param	Handler to the Handler for that exception.
* @param	Data is a reference to Data that will be passed to the
*		Handler when it gets called.
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void Xil_ExceptionRegisterHandler(u32 Exception_id,
				    Xil_ExceptionHandler Handler,
				    void *Data)
{
	XExc_VectorTable[Exception_id].Handler = Handler;
	XExc_VectorTable[Exception_id].Data = Data;
}

/*****************************************************************************/
/**
*
* Removes the Handler for a specific exception Id. The stub Handler is then
* registered for this exception Id.
*
* @param	exception_id contains the ID of the exception source and should
*		be in the range of 0 to XIL_EXCEPTION_ID_LAST.
*		See xil_exception_l.h for further information.

* @return	None.
*
* @note		None.
*
****************************************************************************/
void Xil_ExceptionRemoveHandler(u32 Exception_id)
{
	Xil_ExceptionRegisterHandler(Exception_id,
				       Xil_ExceptionNullHandler,
				       NULL);
}

/*****************************************************************************/
/**
*
* Default Data abort handler which prints data fault status register through
* which information about data fault can be acquired
*
* @param	None
*
* @return	None.
*
* @note		None.
*
****************************************************************************/

void Xil_DataAbortHandler(void *CallBackRef){
	u32 FaultStatus;
	#ifdef __GNUC__
		FaultStatus = mfcp(XREG_CP15_DATA_FAULT_STATUS);
	#elif defined (__ICCARM__)
		mfcp(XREG_CP15_DATA_FAULT_STATUS,FaultStatus);
	#else
		{ volatile register u32 Reg __asm(XREG_CP15_DATA_FAULT_STATUS);
	  FaultStatus = Reg; }
	#endif
	xdbg_printf(XDBG_DEBUG_GENERAL, "Data abort with Data Fault Status Register  %x\n",FaultStatus);
	xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instrcution causing Data abort %x\n",DataAbortAddr);
	while(1) {
		;
	}
}

/*****************************************************************************/
/**
*
* Default Prefetch abort handler which prints prefetch fault status register through
* which information about instruction prefetch fault can be acquired
*
* @param	None
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void Xil_PrefetchAbortHandler(void *CallBackRef){
	u32 FaultStatus;
	#ifdef __GNUC__
		FaultStatus = mfcp(XREG_CP15_INST_FAULT_STATUS);
	#elif defined (__ICCARM__)
		mfcp(XREG_CP15_INST_FAULT_STATUS,FaultStatus);
	#else

	xdbg_printf(XDBG_DEBUG_GENERAL, "Prefetch abort with Instruction Fault Status Register  %x\n",FaultStatus);
	xdbg_printf(XDBG_DEBUG_GENERAL, "Address of Instrcution causing Prefetch abort %x\n",PrefetchAbortAddr);
	while(1) {
		;
	}
}

/*****************************************************************************/
/**
*
* Default undefined exception handler which prints address of the undefined
* instruction if debug prints are enabled
*
* @param	None
*
* @return	None.
*
* @note		None.
*
****************************************************************************/
void Xil_UndefinedExceptionHandler(void *CallBackRef){

	xdbg_printf(XDBG_DEBUG_GENERAL, "Address of the undefined instruction %x\n",UndefinedExceptionAddr);
	while(1) {
		;
	}
}

		{ volatile register u32 Reg __asm(XREG_CP15_INST_FAULT_STATUS);
	  FaultStatus = Reg; }


/******************************************************************************
*
* Copyright (C) 2009 - 2015 Xilinx, Inc.  All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/
/*****************************************************************************/
/**
* @file xtime_l.h
*
* <pre>
* MODIFICATION HISTORY:
*
* Ver   Who    Date     Changes
* ----- ------ -------- ---------------------------------------------------
* 1.00a rp/sdm 11/03/09 Initial release.
* 3.06a sgd    05/15/12 Upadted get/set time functions to make use Global Timer
* 3.06a asa    06/17/12 Reverted back the changes to make use Global Timer.
* 3.07a sgd    07/05/12 Upadted get/set time functions to make use Global Timer
* </pre>
*
* @note		None.
*
******************************************************************************/

#ifndef XTIME_H /* prevent circular inclusions */
#define XTIME_H /* by using protection macros */

#ifdef __cplusplus
extern "C" {
#endif

/***************************** Include Files *********************************/

#include "xil_types.h"
#include "xparameters.h"

/***************** Macros (Inline Functions) Definitions *********************/

/**************************** Type Definitions *******************************/

typedef u64 XTime;

/************************** Constant Definitions *****************************/
#define GLOBAL_TMR_BASEADDR               XPAR_GLOBAL_TMR_BASEADDR
#define GTIMER_COUNTER_LOWER_OFFSET       0x00U
#define GTIMER_COUNTER_UPPER_OFFSET       0x04U
#define GTIMER_CONTROL_OFFSET             0x08U

/* Global Timer is always clocked at half of the CPU frequency */
#define COUNTS_PER_SECOND          (XPAR_CPU_CORTEXA9_CORE_CLOCK_FREQ_HZ /2)
/************************** Variable Definitions *****************************/

/************************** Function Prototypes ******************************/

void XTime_GetTime(XTime *Xtime_Global);

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* XTIME_H */