//////////////////////////////////////////////////////////////////////////////
// Filename:          C:\School\Project\MPSoC\Multiprocs/drivers/snoopy_if_v1_00_a/src/snoopy_if.c
// Version:           1.00.a
// Description:       snoopy_if Driver Source File
// Date:              Sun Apr 19 20:50:02 2009 (by Create and Import Peripheral Wizard)
//////////////////////////////////////////////////////////////////////////////

#define TOTAL_EXEC_TIME_ADDR_LOWER_WORD 	0x00000000L
#define TOTAL_EXEC_TIME_ADDR_UPPER_WORD 	0x10000000L
#define MEM_WAIT_TIME_ADDR_LOWER_WORD 		0x20000000L
#define MEM_WAIT_TIME_ADDR_UPPER_WORD 		0x30000000L
#define NUM_MEM_ACCESS_ADDR 					0x40000000L
#define TASK_TIME_ADDR_LOWER_WORD			0x60000000L
#define TASK_TIME_ADDR_UPPER_WORD			0x70000000L
#define PROC_IDLE_TIME_ADDR_LOWER_WORD		0x80000000L
#define PROC_IDLE_TIME_ADDR_UPPER_WORD		0x90000000L
#define PROC_TASK_POSITION						24

#define SETTLE_COUNT 100

#define PROC_PERIOD 10 //processor clock period in nanoseconds

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

#include "snoopy_if.h"

/************************** Function Definitions ***************************/


/*******
This function does a bit-wise swap of a Xuint8 
*******/
Xuint8 bit_swap8(Xuint8 num)
{
	Xuint8 i;
	Xuint8 result = 0;
	
	for (i = 0; i < 8; i++)
	{
		result |= ((num >> i) & 0x01) << (7-i);
	}
	
	return result;
}


/***
This function initializes snoopy
***/
void init_snoopy(Xuint32 baseaddr)
{
	SNOOPY_IF_mReset(baseaddr);
}

/****
This function returns the total execution time in nanoseconds * 10
****/
Xuint64 get_total_execution_time(Xuint32 baseaddr)
{
	Xuint16 count = 0;
	Xuint64 value1, value2;
		
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, (Xuint32)TOTAL_EXEC_TIME_ADDR_LOWER_WORD);

	value1.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
			
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);		
		if (value1.Lower == value2.Lower)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Lower = value2.Lower;
	}
		
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, (Xuint32)TOTAL_EXEC_TIME_ADDR_UPPER_WORD);
	
	value1.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1.Upper == value2.Upper)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Upper = value2.Upper;
	}
	
	return value1;
}

/****
This function returns the memory waiting time for a particular processor in nanoseconds * 10
****/
Xuint64 get_memory_waiting_time(Xuint32 baseaddr, Xuint8 processor)
{
	Xuint16 count = 0;
	Xuint64 value1, value2;
		
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)MEM_WAIT_TIME_ADDR_LOWER_WORD | (Xuint32)(processor << PROC_TASK_POSITION)));
	
	value1.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1.Lower == value2.Lower)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Lower = value2.Lower;
	}
	
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)MEM_WAIT_TIME_ADDR_UPPER_WORD | (Xuint32)(processor << PROC_TASK_POSITION)));
	
	value1.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1.Upper == value2.Upper)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Upper = value2.Upper;
	}
	
	return value1;
}

/****
This function returns the number of memory accesses for a particular task in nanoseconds * 10
****/
Xuint32 num_task_mem_accesses(Xuint32 baseaddr, Xuint8 task)
{
	Xuint16 count = 0;
	Xuint32 value1, value2;
	
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)NUM_MEM_ACCESS_ADDR | (Xuint32)(task << PROC_TASK_POSITION)));

	value1 = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2 = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1 == value2)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1 = value2;
	}	
	
	return value1;
}

/****
This function returns the task execution time for a particular task in nanoseconds * 10
****/
Xuint64 get_task_time(Xuint32 baseaddr, Xuint8 task)
{
	Xuint16 count = 0;
	Xuint64 value1, value2;
	
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)TASK_TIME_ADDR_LOWER_WORD | (Xuint32)(task << PROC_TASK_POSITION)));

	value1.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);		
		if (value1.Lower == value2.Lower)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Lower = value2.Lower;
	}
	
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)TASK_TIME_ADDR_UPPER_WORD | (Xuint32)(task << PROC_TASK_POSITION)));
	
	value1.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1.Upper == value2.Upper)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Upper = value2.Upper;
	}
	
	return value1;
}

/****
This function returns the idle time for a particular processor in nanoseconds * 10
****/
Xuint64 get_processor_idle_time(Xuint32 baseaddr, Xuint8 processor)
{
	Xuint16 count = 0;
	Xuint64 value1, value2;
	
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)PROC_IDLE_TIME_ADDR_LOWER_WORD | (Xuint32)(processor << PROC_TASK_POSITION)));

	value1.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Lower = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1.Lower == value2.Lower)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Lower = value2.Lower;
	}
	
	SNOOPY_IF_mWriteSlaveReg0(baseaddr, ((Xuint32)PROC_IDLE_TIME_ADDR_UPPER_WORD | (Xuint32)(processor << PROC_TASK_POSITION)));
	
	value1.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);	
	
	//this count loop is to allow the value to settle
	while (count < SETTLE_COUNT)
	{
		value2.Upper = SNOOPY_IF_mReadSlaveReg1(baseaddr);
		if (value1.Upper == value2.Upper)
		{
			count++;
		}
		else
		{
			count = 0;
		}
		value1.Upper = value2.Upper;
	}
	
	return value1;
}





