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

  Copyright (C), 2014, Texas Instrument.

 ******************************************************************************
  File Name     : CPU_access_test.c
  Version       : Initial Draft
  Author        : Brighton Feng
  Created       : June 5, 2014
  Last Modified : 
  Description   : CPU read/write test functions and definitions
  History       :
  1.Date        : June 5, 2014
    Author      : Brighton Feng
    Modification: Created file
  2.Date        : July 31, 2014
    Author      : Brighton Feng
    Modification: update for ARM Cortex A15

******************************************************************************/
#include "K2_common.h"
#include "CPU_access_test.h"

/*execute LDRD test in "buff" of "uiByteCnt" with different index*/
void LDRDTest(Uint32 buff_addr, Uint32 uiByteCnt, char * mem_type)
{
	unsigned int cycles;
	Uint32 		uiIndex;

	printf("Memory load performance test at 0x%08x(%s)\n", buff_addr, mem_type);
	//EDMA_fill(buff_addr, 1, uiByteCnt, EDMA_CC0_CH0); //fill known pattern for debug
	
	uiIndex=0;
	Asm_LDRD_Test(buff_addr, uiIndex*8, LOAD_STORE_TIMES); 	//warm cache
	while(uiIndex*8*LOAD_STORE_TIMES<uiByteCnt)
	{
		CP15_DCacheCleanInvalidate();

		cycles= CP15_read_CCNT();
		__asm__(" ISB");
		Asm_LDRD_Test(buff_addr, uiIndex*8, LOAD_STORE_TIMES);
		__asm__(" ISB");
		cycles= CCNT_count_cycle_from(cycles)-LD_ST_TEST_OVERHEAD;
		printf("Index=%4d  Cycles/LDRD= %.2f\n", uiIndex, (float)cycles/(LOAD_STORE_TIMES));
		if(uiIndex<8)
			uiIndex++;
		else if(uiIndex<32)
			uiIndex+=2;
		else if(uiIndex<64)
			uiIndex+=8;
		else if(uiIndex<128)
			uiIndex+=32;
		else if(uiIndex<256)
			uiIndex+=64;
		else if(uiIndex<512)
			uiIndex+=128;
		else if(uiIndex<1024)
			uiIndex+=256;
		else if(uiIndex<2048)
			uiIndex+=512;
		else if(uiIndex<4096)
			uiIndex+=1024;
		else if(uiIndex<8192)
			uiIndex+=2048;
		else 
			uiIndex+=4096;
	}
}

/*execute STRD test in "buff" of "uiByteCnt" with different index*/
void STRDTest(Uint32 buff_addr, Uint32 uiByteCnt, char * mem_type)
{
	unsigned int cycles;
	Uint32 		uiIndex;

	printf("Memory store performance test at 0x%08x(%s)\n", buff_addr, mem_type);
	uiIndex=0;
	Asm_STRD_Test(buff_addr, uiIndex*8, LOAD_STORE_TIMES); 	//warm cache
	while(uiIndex*8*LOAD_STORE_TIMES<uiByteCnt)
	{
		CP15_DCacheCleanInvalidate();

		cycles= CP15_read_CCNT();
		__asm__(" ISB");
		Asm_STRD_Test(buff_addr, uiIndex*8, LOAD_STORE_TIMES);
		__asm__(" ISB");
		cycles= CCNT_count_cycle_from(cycles)-LD_ST_TEST_OVERHEAD;
		printf("Index=%4d  Cycles/STRD= %.2f\n", uiIndex, (float)cycles/(LOAD_STORE_TIMES));
		if(uiIndex<8)
			uiIndex++;
		else if(uiIndex<32)
			uiIndex+=2;
		else if(uiIndex<64)
			uiIndex+=8;
		else if(uiIndex<128)
			uiIndex+=32;
		else if(uiIndex<256)
			uiIndex+=64;
		else if(uiIndex<512)
			uiIndex+=128;
		else if(uiIndex<1024)
			uiIndex+=256;
		else if(uiIndex<2048)
			uiIndex+=512;
		else if(uiIndex<4096)
			uiIndex+=1024;
		else if(uiIndex<8192)
			uiIndex+=2048;
		else 
			uiIndex+=4096;
	}
}


void AsmMemCopy8Test(unsigned long long * srcBuff, unsigned long long * dstBuff, Uint32 uiByteCnt,
 	char * srcType, char * dstType)
{
	int i;
	
	unsigned int cycles;
	Uint32 iThroughput;

	/* Initialize data buffers */
	for(i=0; i< uiByteCnt/8; i++)
	{
		srcBuff[i]= (unsigned long long)(dstBuff+i);
		dstBuff[i] = 0xaaaaaaaaaaaaaaaaULL;
	}

	//Clear cache
	CP15_DCacheCleanInvalidate();

	cycles= CP15_read_CCNT();
	AsmMemCopy(dstBuff, srcBuff, uiByteCnt);
	//CP15_DCacheCleanBuff((Uint32)dstBuff, uiByteCnt);
	cycles= CCNT_count_cycle_from(cycles);

	iThroughput= (unsigned long long)uiByteCnt*gARM_Core_Speed_Hz/cycles/1000000;
	printf("%5d MB/s, copy %6d bytes from 0x%08x(%s) to 0x%08x(%s), consumes %d cycles\n", 
		iThroughput, uiByteCnt, (Uint32)srcBuff, srcType, (Uint32)dstBuff, dstType, cycles);

	//verfiry result
	for (i = 0; i < uiByteCnt/8; i++) {
		if(dstBuff[i] != (unsigned long long)(dstBuff+i))
		{
			printf("CPU memory copy failed at 0x%x\n", (Uint32)(dstBuff+i));
			break;
		}
	}
}

