/*  ============================================================================
 *   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.
* ============================================================================
Example to show the performance of Multicore Navigator on KeyStone DSP
* =============================================================================
 *  Revision History
 *  ===============
 *  May 15, 2011 Brighton Feng   File Created
 * ============================================================================
 */

#include <stdio.h>
#include <string.h>
#include <c6x.h>
#include <csl_cacheAux.h>
#include <csl_cache.h>
#include <csl_qm_queue.h>
#include "KeyStone_common.h"
#include "KeyStone_DDR_Init.h"
#include "MNav_QM_Intc_setup.h"
#include "MNav_Test.h"

#define TEST_PA_PACKET_DMA 		1
#define TEST_SRIO_PACKET_DMA 	1

void QueuePushPopTest(Uint32 uiQueueNumber)
{
	Uint32 uiDescriptorNumber;

	uiDescriptorNumber= gpQueueStatusConfigRegs[uiQueueNumber].REG_A_EntryCount;
	if(uiDescriptorNumber>TEST_DESC_BUF_SIZE)
		uiDescriptorNumber=TEST_DESC_BUF_SIZE;

	printf("Queue %d push test through Queue Manage Registers\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageRegs[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug

	printf("Queue %d push test through Queue Manage Proxy Registers\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageProxyRegs[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug

	printf("Queue %d push test through Queue Manage VBUSM Data Space\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageVBUSM[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug

	printf("Queue %d push test through Queue Manage proxy VBUSM Data Space\n", uiQueueNumber);
	QueuePushCycleTest(&gpQueueManageProxyVBUSM[uiQueueNumber], uiDescriptorNumber, &gpQueueManageRegs[uiQueueNumber]);
	checkQueues(); 	//for debug


	printf("Queue %d pop test through Queue Manage Registers\n", uiQueueNumber);
	QueuePopCycleTest(&gpQueueManageRegs[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

	printf("Queue %d pop test through Queue Manage VBUSM Data Space\n", uiQueueNumber);
	QueuePopCycleTest(&gpQueueManageVBUSM[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

	printf("Empty Queue %d pop test through Queue Manage Registers\n", EMPTY_FDQ);
	QueuePopCycleTest(&gpQueueManageRegs[EMPTY_FDQ], uiDescriptorNumber);
	checkQueues(); 	//for debug


	printf("Queue %d push to pop delay test through Queue Manage Registers\n", uiQueueNumber);
	QueuePushToPopDelayTest(&gpQueueManageRegs[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

	printf("Queue %d push to pop delay test through Queue Manage VBUSM Data Space\n", uiQueueNumber);
	QueuePushToPopDelayTest(&gpQueueManageVBUSM[uiQueueNumber], uiDescriptorNumber);
	checkQueues(); 	//for debug

}

void DSPCoreAccessQueueTest()
{
	puts("Queue Push/Pop test on descriptors with internal linking RAM");
	QueuePushPopTest(DDR_MONO_LINK_RAM0_FDQ);

	puts("Queue Push/Pop test on descriptors with external linking RAM");
	QueuePushPopTest(DDR_MONO_LINK_RAM1_FDQ);

}

void QueuePendInterruptTest()
{
	puts("\nQueue pend interrupt test on descriptors with internal linking RAM");
	QueuePushToPendInterruptDelayTest(&gpQueueManageRegs[DDR_MONO_LINK_RAM0_FDQ]);

	puts("Queue pend interrupt test on descriptors with external linking RAM");
	QueuePushToPendInterruptDelayTest(&gpQueueManageRegs[DDR_MONO_LINK_RAM1_FDQ]);
}

void PktDmaThroughputTest(Uint32 uiSrcQuNum, Uint32 uiTxQuNum, 
	Uint32 uiFlowID, Uint32 uiMaxBytes, Uint32 uiNumCh)
{
	int i;

	for(i=8; i<=uiMaxBytes; i*=2)
		PktDmaThroughput(uiSrcQuNum, uiTxQuNum, uiFlowID, i, uiNumCh);
}

void PktDmaTest(Uint32 uiTxQuNum, Uint32 uiNumCh)
{
	printf("host Packet DMA test with %d channels\n", uiNumCh);

	/*Packet DMA transfer from LL2 to another core's LL2*/
	PktDmaThroughputTest(CORE0_LL2_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_LL2_HOST, LL2_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from LL2 to SL2*/
	PktDmaThroughputTest(CORE0_LL2_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_SL2_HOST, LL2_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from LL2 to DDR*/
	PktDmaThroughputTest(CORE0_LL2_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_DDR_HOST, LL2_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from SL2 to LL2*/
	PktDmaThroughputTest(SL2_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_LL2_HOST, LL2_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from SL2 to DDR*/
	PktDmaThroughputTest(SL2_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_DDR_HOST, SL2_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from DDR to LL2*/
	PktDmaThroughputTest(DDR_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_LL2_HOST, LL2_PACKET_BUFFER_SIZE3, uiNumCh);
	/*Packet DMA transfer from DDR to SL2*/
	PktDmaThroughputTest(DDR_HOST_SIZE3_FDQ, uiTxQuNum, RX_FLOW_SL2_HOST, SL2_PACKET_BUFFER_SIZE3, uiNumCh);

	printf("monolithic Packet DMA test with %d channels\n", uiNumCh);

	/*Packet DMA transfer from LL2 to another core's LL2*/
	PktDmaThroughputTest(CORE0_LL2_MONOLITHIC_FDQ, uiTxQuNum, RX_FLOW_LL2_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from LL2 to SL2*/
	PktDmaThroughputTest(CORE0_LL2_MONOLITHIC_FDQ, uiTxQuNum, RX_FLOW_SL2_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from LL2 to DDR*/
	PktDmaThroughputTest(CORE0_LL2_MONOLITHIC_FDQ, uiTxQuNum, RX_FLOW_DDR_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from SL2 to LL2*/
	PktDmaThroughputTest(SL2_MONOLITHIC_FDQ, uiTxQuNum, RX_FLOW_LL2_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from SL2 to DDR*/
	PktDmaThroughputTest(SL2_MONOLITHIC_FDQ, uiTxQuNum, RX_FLOW_DDR_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from DDR to LL2*/
	PktDmaThroughputTest(DDR_MONO_LINK_RAM0_FDQ, uiTxQuNum, RX_FLOW_LL2_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
	/*Packet DMA transfer from DDR to SL2*/
	PktDmaThroughputTest(DDR_MONO_LINK_RAM0_FDQ, uiTxQuNum, RX_FLOW_SL2_MONO, L2_MONO_DESCRIPTOR_SIZE, uiNumCh);
}

void main()
{   
	int i;
	TDSP_Board_Type DSP_Board_Type;
	DDR_ECC_Config DDR_ECC_cfg;

	//Configure L1 as 32KB cache, L2 cache 256KB
	CACHE_setL1PSize(CACHE_L1_32KCACHE);
	CACHE_setL1DSize(CACHE_L1_32KCACHE);
	CACHE_setL2Size(CACHE_256KCACHE);

	TSC_init();

	memset((void *)&DDR_ECC_cfg, 0, sizeof(DDR_ECC_cfg));

	DSP_Board_Type= KeyStone_Get_dsp_board_type();
	if(C6678_EVM==DSP_Board_Type || C6657_EVM==DSP_Board_Type)
	{
		//DSP core speed: 100*10/1=1000MHz
		KeyStone_main_PLL_init(100, 10, 1); 
	}
	else if(TCI6614_EVM==DSP_Board_Type
		||DUAL_NYQUIST_EVM==DSP_Board_Type
		||C6670_EVM==DSP_Board_Type)
	{
		//DSP core speed: 122.88*236/29= 999.9889655MHz
		KeyStone_main_PLL_init(122.88, 236, 29);

		/*DDR ECC is supported on TCI6614 EVM*/
		if(TCI6614_EVM == DSP_Board_Type)
		{
			DDR_ECC_cfg.addressRange[0].startAddr= 0x00000000;
			DDR_ECC_cfg.addressRange[0].byteCnt=   0x10000000;
			DDR_ECC_cfg.rangeMode= EN_ECC_WITHIN_DEFINED_RANGES;
		}
	}
	else
	{
		puts("Unknown DSP board type!");
		return;
	}
	if((C6670_EVM == DSP_Board_Type)
		||(DUAL_NYQUIST_EVM == DSP_Board_Type)
		||(TCI6614_EVM == DSP_Board_Type)
		||(C6678_EVM == DSP_Board_Type))
	{
	    //DDR init 66.66667*20/1= 1333
	    KeyStone_DDR_init (66.66667, 20, 1, NULL);
	}
	else
	{
		//EVM6657 with 50MHz input for DDR
		KeyStone_DDR_init (50, 26, 1, NULL);
	}

	/*enable L1P ED and scrub whole L1P*/
	L1P_EDC_setup();

   	/*enable LL2 EDC and scrub whole LL2*/
	LL2_EDC_setup();

	/*Enable MSMC EDC and setup scrubbing cycle counter= 255*1024*/
	KeyStone_SL2_EDC_enable(255);

	/*make other cores local memory cacheable and prefetchable*/
	for(i=16; i<24; i++)
		gpCGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);	

	/*make other space non-cacheable and non-prefetchable*/
	for(i=24; i<128; i++)
		gpCGEM_regs->MAR[i]=0;	

	/*make DDR cacheable and prefetchable*/
	for(i=128; i<256; i++)
		gpCGEM_regs->MAR[i]=1|(1<<CSL_CGEM_MAR0_PFX_SHIFT);	

	QMSS_init();
	QMSS_PktDMA_init();
	checkQueues(); 	//for debug
	
	QM_Interrupts_Init();

	/* Initialize Time stamp counter to measure cycles*/
	TSC_init();

	KeyStone_Exception_cfg();
#if 1
	DSPCoreAccessQueueTest();
	checkQueues(); 	//for debug

	QueuePendInterruptTest();
	checkQueues(); 	//for debug

	QueueReclamationDelayTest(DDR_HOST_SIZE3_FDQ);
	checkQueues(); 	//for debug

	QueuePushToAccumulationDelayTest(DDR_MONO_LINK_RAM0_FDQ);
	checkQueues(); 	//for debug
#endif
	puts("test Packet DMA in QMSS");
	for(i= 1; i<=4; i*=2)
		PktDmaTest(QMSS_INFRASTRUCTURE_QUEUE_BASE, i);
	checkQueues(); 	//for debug

#ifndef DEVICE_C6657
#if TEST_PA_PACKET_DMA
	//enable PA for test
	KeyStone_enable_PSC_module(CSL_PSC_PD_PASS, CSL_PSC_LPSC_PKTPROC);

	PA_PktDMA_init();

	puts("test Packet DMA in PA");
	PktDmaTest(QMSS_PASS_QUEUE_BASE, 1);
	checkQueues(); 	//for debug
#endif
#endif

#if TEST_SRIO_PACKET_DMA
	//enable SRIO for test
	KeyStone_enable_PSC_module(CSL_PSC_PD_SRIO, CSL_PSC_LPSC_SRIO);

	SRIO_PktDMA_init();

	puts("test Packet DMA in SRIO");
	PktDmaTest(QMSS_SRIO_QUEUE_BASE, 1);
	checkQueues(); 	//for debug
#endif

	puts("Test complete");
    
    return;
}

