/*  ============================================================================
 *   Copyright (c) Texas Instruments Inc 2011
 *
 *   Use of this software is controlled by the terms and conditions found in the
 *   license agreement under which this software has been supplied.
 *   ===========================================================================
* ============================================================================
 *   @desc  Example shows the performance of DSP cores share memory
 *  ============================================================================
 *   @n Target Platform: EVM
* =============================================================================
 *  Revision History
 *  ===============
 *  15-Jan-2011 Brighton Feng   File Created
 *  Updated on March 30 2011 for C6678 EVM
 * ============================================================================
 */

#include <csl_cacheAux.h>
#include <stdio.h>
#include <c6x.h>
#include "MEM_Sharing.h"
#include "KeyStone_common.h"

#define REAL_TIME_INFO 	0

Uint32          start_TSC;
CoreTestInfo * coreInfo;
Uint32 size, repeatCount;
Uint32 L2CacheSize;
Uint32 srcAddr, dstAddr;

void DSP_core_mem_share_Test()
{
	Int32 i;
	Uint32 		uiTestTimes;
	Uint32  tscl, tsch;

	if(!coreInfo->enabled)
	{
		for(i=0; i< repeatCount; i++)
			asm(" nop 5"); //wait for a while
		return;
	}
	
	/*configure DSP core priority on SCR*/
	CGEM_regs->MDMAARBU= ((coreInfo->priority)<<CSL_CGEM_MDMAARBU_UPRI_SHIFT)|
		((coreInfo->priority)<<CSL_CGEM_MDMAARBU_PRI_SHIFT);
	/*priority of XMC prefetch is set to same as the DSP core request*/
	XMC_regs->MDMAARBX= (coreInfo->priority)<<CSL_XMC_MDMAARBX_PRI_SHIFT;

	srcAddr= coreInfo->srcAddr;
	dstAddr= coreInfo->dstAddr;
	
	for(i=0; i< repeatCount; i++)
	{
		MemCopy8(dstAddr, srcAddr, size/8);

		//cache coherency operation
		if(dstAddr>=0x0C000000&&dstAddr<0x0C400000)	//SL2
			CACHE_invL1d((void *)dstAddr, size, CACHE_WAIT);
		else if(dstAddr>=0x80000000) 	//DDR
		{
			if(L2CacheSize)
				CACHE_invL2((void *)dstAddr, size, CACHE_WAIT);
			else
				CACHE_invL1d((void *)dstAddr, size, CACHE_WAIT);
		}
		if(srcAddr>=0x0C000000&&srcAddr<0x0C400000)	//SL2
			CACHE_invL1d((void *)srcAddr, size, CACHE_WAIT);
		else if(srcAddr>=0x80000000) 	//DDR
		{
			if(L2CacheSize)
				CACHE_invL2((void *)srcAddr, size, CACHE_WAIT);
			else
				CACHE_invL1d((void *)srcAddr, size, CACHE_WAIT);
		}
		CSL_XMC_invalidatePrefetchBuffer();
		
	}

	if(coreInfo->reStat)		
	{
		/* save the TSC for next iteration */
		tscl= TSCL;
		tsch= TSCH;
		coreInfo->start_TSC = _itoll(tsch, tscl);
		coreInfo->reStat=0;
		coreInfo->testTimes=0;
		coreInfo->averageBandwidth= 0;
	}
	else
	{
		uiTestTimes= coreInfo->testTimes+1;
		coreInfo->testTimes= uiTestTimes;
			
		tscl= TSCL;
		tsch= TSCH;
		coreInfo->last_TSC= _itoll(tsch, tscl);				

		//measure the bandwidth
		coreInfo->averageBandwidth= (unsigned long long)size*repeatCount*uiTestTimes*DSP_Core_Clock_KHz/
			(coreInfo->last_TSC- coreInfo->start_TSC)/1000;
	}

#if REAL_TIME_INFO
	asm(" dint");
	printf("DSP core%d transfer from 0x%8x to 0x%8x, bandwidth= %4d MB/s priority= %d  size= %6d L1dKB= %2d L2KB= %3d TestTimes= %d\n", 
		DNUM, coreInfo->srcAddr, coreInfo->dstAddr, coreInfo->averageBandwidth, 
		coreInfo->priority, coreInfo->size, 
		coreInfo->L1dCacheSize, coreInfo->L2CacheSize, coreInfo->testTimes);
	asm(" rint");
#endif
#if 0
	if(coreInfo->testTimes>65536)
	{ 	/*clear statistic data to avoid overflow*/
		coreInfo->testTimes=0;
		coreInfo->averageBandwidth=0;
	}
#endif
}


void DSP_Core_Test_Start(void)
{   
	coreInfo= &(coreTestInfo[DNUM]);
	//Configure L1 L2 cache
	CACHE_setL1DSize(coreInfo->L1dCacheSize);
	CACHE_setL2Size(coreInfo->L2CacheSize);

	size= coreInfo->size;
	repeatCount= coreInfo->repeatCount;
	L2CacheSize= coreInfo->L2CacheSize;

	start_TSC= 0;
	coreInfo->reStat=1;
	while(1)
		DSP_core_mem_share_Test();
    
}
