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

  Copyright (C), 2001-2013, Texas Instrument.

 ******************************************************************************
  File Name     : TCP3D_test_main.c
  Version       : Initial Draft
  Author        : Andy Yin
  Created       : 2013/10/10
  Last Modified :
  Description   : TCP3D test for LTE and WCDMA

  Function List :
              main

  History       :
  1.Date        : 2013/10/10
    Author      : Andy Yin
    Modification: Created file

* Mode test: LTE, WCDMA;
* Throughput test
* Multicore test
* Multi TCP3D instance test
* Debug mode with test para print (To be added)
* Limitation: The file Keystone_TCP3D.c should be compiled with debug option -g
******************************************************************************/
#include <c6x.h>
#include <tistdtypes.h>
#include <stdio.h>
#include <string.h>
#include <cslr_device.h>
#include "Keystone_common.h"
#include "KeyStone_DDR_Init.h"
#include "Keystone_TCP3D.h"
/*----------------------------------------------*
 * external variables                           *
 *----------------------------------------------*/

/*----------------------------------------------*
 * external routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * internal routine prototypes                  *
 *----------------------------------------------*/

/*----------------------------------------------*
 * project-wide global variables                *
 *----------------------------------------------*/
/*----------------------------------------------*
 * test configuration parameters                *
 *----------------------------------------------*/

/*----------------------------------------------*
 * module-wide global variables                 *
 *----------------------------------------------*/
/*----------------------------------------------*
 * constants                                    *
 *----------------------------------------------*/

/*----------------------------------------------*
 * macros                                       *
 *----------------------------------------------*/
#define TEST_MAX_BLOCK_NUM        20
#define TEST_MAX_UE_NUM           16
#define TEST_MAX_BIT_SIZE         8192
/*----------------------------------------------*
 * routines' implementations                    *
 *----------------------------------------------*/
T_TCP3D_Hdl gtTcp3dHdl[NUM_TCP3D];

/* IC Regs */
T_Tcp3dICCfgParams  gtTcp3dIcCfg[TEST_MAX_BLOCK_NUM];
/* 3 - sys, par1, par2 */
Int8      gscInLLR[TEST_MAX_BLOCK_NUM][3 * TEST_MAX_BIT_SIZE];
Int8      gscTailBits[TEST_MAX_BLOCK_NUM][12];
Uint8     gucOutHardBit[TEST_MAX_BLOCK_NUM][TEST_MAX_BIT_SIZE];
Uint32    gudOutStatus[TEST_MAX_BLOCK_NUM][3]; /* 3words status per CB */
Uint8     gucDecStatus[TEST_MAX_BLOCK_NUM];    /* get the SNR status for 3GPP and Wimax, CRC status for LTE */

T_TCP3D_BlockInfo   gtTcp3dBlockInfo[TEST_MAX_BLOCK_NUM];

/* input test config */
typedef struct
{
    Uint8     ucCrcSel;     /* 0-CB CRC, 1-TB CRC, used for LTE mode */
    Uint16    uwBlockSize;  /* turbo decoder block size in bit, not include the tailing bits */
    Uint8     ucInitSw0Len; /* init value for sliding length cal, default with 64bit, range = {16, 32, 48,  64, 96, 128} */
} T_BLOCK_CFG;

/*****************************************************/
/* need to modify the below para for different test case */
/*****************************************************/
//#define THROUGHPUT_TEST
#define TEST_MODE                 1    /* 1-LTE mode, 2-Wimax, 3-WCDMA split mode */
#define TEST_CUR_UE_NUM           1
#ifdef THROUGHPUT_TEST
T_BLOCK_CFG gtBlockCfg[TEST_MAX_BLOCK_NUM] = {
#if(TEST_MODE == 1)
		{
		    0, 6144, 64
		},
		{
			0, 6144, 64
		},
		{
			0, 6144, 64
		},
#else if(TEST_MODE == 3)
		{
		    0, 2000, 64
		},
		{
		    0, 2000, 64
		},
		{
		    0, 2000, 64
		},
		{
			0, 2000, 64
		},
#endif
};
#else
T_BLOCK_CFG gtBlockCfg[TEST_MAX_BLOCK_NUM] = {
#if(TEST_MODE == 1)
		{
			0, 1120, 64
		},

		{
			0, 40, 64
		},
		{
			0, 6144, 64
		},
#else if(TEST_MODE == 3)
		{
		    0, 100, 64
		},
		{
		    0, 103, 64
		},
		{
		    0, 800, 64
		},
		{
			0, 2000, 64
		},
#endif
};
#endif
Uint8 gucBlockNumPerUe[TEST_CUR_UE_NUM] = {
#if(TEST_MODE == 1)
		3
#else if(TEST_MODE == 3)
		4
#endif
};
#ifdef THROUGHPUT_TEST
#define STOP_SEL  0  /* max iteration stop */
#else
#if(TEST_MODE == 1)

#define STOP_SEL  1  /* LTE CRC stop */

#else if(TEST_MODE == 3)

#define STOP_SEL  2  /* SNR stop */

#endif
#endif

/*****************************************************/
Uint32 gudEndCycle, gudTTICfgCycle;
void main()
{
	int i, j, k;
	Uint8 ucUsedTcpId;
	Uint8 ucFreeTcpId;
	Uint8 ucTotalBlockNum;
	Uint16 uwLLROffset;
	Uint8  ucLastProcBlockNum;

	T_TCP3D_ResInfo tTcp3dResInfo;  /* hardware resource include the EDMA channel, set .etc */
	T_TCP3D_ComAppInfo tTcp3dComAppInfo;  /* common application information */

	Uint32 udStartCycle;

    TSC_init();	//initialize TSC to measure cycle

    IER= 0; 	//disable all interrupts

    /* L1/L2 cache size init */
    CACHE_setL1PSize(CACHE_L1_32KCACHE);
    CACHE_setL1DSize(CACHE_L1_32KCACHE);
    CACHE_setL2Size(CACHE_0KCACHE);
	CACHE_invAllL1p(CACHE_WAIT);
	CACHE_wbInvAllL1d(CACHE_WAIT);
	CACHE_wbInvAllL2(CACHE_WAIT);
#ifndef	SIMULATOR_SUPPORT
	/* protect L1 as cache */
   	L1_cache_protection();

	/*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);


	//DSP core speed: 122.88*236/29= 999.9889655MHz
	//KeyStone_main_PLL_init(122.88, 236, 29);
	KeyStone_main_PLL_init (122.88, 236, 29); 	//for 122.88MHz input clock
	//DDR configuration
	//DDR init 66.66667*20/1= 1333
	KeyStone_DDR_init (66.66667, 20, 1, NULL);
#endif

	/* hardware resource init */
	ucUsedTcpId = 0;
	tTcp3dResInfo.ucTCPId = ucUsedTcpId;
	tTcp3dResInfo.ucInEdmaTpcc = gtTcp3dInstInfo[ucUsedTcpId].ucEdmaCCInst;   /* set the same EDMACC with the TCP3D output channel */
	tTcp3dResInfo.ucInEdmaTc[0] = 0;  /* TC for input channel, set different TC for ping-pong channel */
	tTcp3dResInfo.ucInEdmaTc[1] = 0;
	tTcp3dResInfo.ucOutEdmaTc[0] = 0; /* set the same TC for the in/out channel pair */
	tTcp3dResInfo.ucOutEdmaTc[1] = 0;
	tTcp3dResInfo.ucInEdmaCh[0] = 10;
	tTcp3dResInfo.ucInEdmaCh[1] = 11;
	tTcp3dResInfo.uwInPaRAMSetStartIdx = 10;
	tTcp3dResInfo.uwOutPaRAMSetStartIdx = 50;
    /* common application parameters */
	tTcp3dComAppInfo.ucModeSel = TEST_MODE; /* 1-LTE mode, 3-WCDMA split mode, 2-Wimax double buffer mode */
	tTcp3dComAppInfo.ucStopSel = STOP_SEL; /* 1-CRC stop, 0-max iteration */
	tTcp3dComAppInfo.ucMaxItr = 8;
	tTcp3dComAppInfo.ucSNRVal = 14;

	/* called after cell setup */
    Keystone_TCP3D_Init((void *)&gtTcp3dHdl[ucUsedTcpId],
    		            &tTcp3dResInfo,
    		            &tTcp3dComAppInfo,
    		            gtTcp3dIcCfg,
			            TEST_MAX_BLOCK_NUM);

    /* called per TTI */
    /* initialize all the ue all the block config information */
    k = 0;
    for(i = 0; i < TEST_CUR_UE_NUM; i++)
    {
    	for(j = 0; j < gucBlockNumPerUe[i]; j++)
    	{
    		uwLLROffset = gtBlockCfg[k].uwBlockSize;
    		if(TEST_MODE == 3)
    		{//WCDMA mode ((((uwBlockSize + 3) >> 2) * 4 - uwBlockSize) * 2 + uwBlockSize)
    			uwLLROffset = (((gtBlockCfg[k].uwBlockSize + 3) >> 2) * 4 - gtBlockCfg[k].uwBlockSize) * 2 + gtBlockCfg[k].uwBlockSize;
    		}
    		gtTcp3dBlockInfo[k].ucCrcSel = gtBlockCfg[k].ucCrcSel; /* CB CRC */
    		gtTcp3dBlockInfo[k].uwBlockSize = gtBlockCfg[k].uwBlockSize; /* set the same size for LTE */
    		gtTcp3dBlockInfo[k].ucInitSw0Len = gtBlockCfg[k].ucInitSw0Len;
    		gtTcp3dBlockInfo[k].pscTailBits = (Int8 *)&gscTailBits[k][0];
    		gtTcp3dBlockInfo[k].pscInputSysLLR = (Int8 *)&gscInLLR[k][0];
    		gtTcp3dBlockInfo[k].pscInputP0LLR = (Int8 *)&gscInLLR[k][0 + uwLLROffset];
    		gtTcp3dBlockInfo[k].pscInputP1LLR = (Int8 *)&gscInLLR[k][0 + uwLLROffset * 2];
    		gtTcp3dBlockInfo[k].pucOutHardBit = (Uint8 *)&gucOutHardBit[k][0];
    		gtTcp3dBlockInfo[k].pudOutStatus = (Uint32 *)&gudOutStatus[k][0];
    		gtTcp3dBlockInfo[k].pudInICCfg = (Uint32 *)&gtTcp3dIcCfg[k];
            k++;
    	}
    }
    ucTotalBlockNum = k;

    udStartCycle = TSCL;
    Keystone_TCP3D_TTICfg((void *)&gtTcp3dHdl[ucUsedTcpId],
    		              gtTcp3dBlockInfo,
    		              gucBlockNumPerUe,
    		              TEST_CUR_UE_NUM);
    gudTTICfgCycle = TSCL - udStartCycle;

    udStartCycle = TSCL;
    ucLastProcBlockNum = 0;
    for(i = 0; i < TEST_CUR_UE_NUM; i++)
    {
    	ucFreeTcpId = Keystone_TCP3D_PollFree((void *)&gtTcp3dHdl[ucUsedTcpId], ucLastProcBlockNum);

    	/* get the TCP3D handle according to ucFreeTcpId */
    	Keystone_TCP3D_Submit((void *)&gtTcp3dHdl[ucFreeTcpId],
    			               gucBlockNumPerUe[i]);
    	ucLastProcBlockNum = gucBlockNumPerUe[i];
    }
    /* check all UE's decoder status */
    Keystone_TCP3D_PollFree((void *)&gtTcp3dHdl[ucUsedTcpId], ucLastProcBlockNum);
    gudEndCycle = TSCL - udStartCycle;
  	Keystone_TCP3D_PostProc(gtTcp3dHdl[ucUsedTcpId].ucModeSel, ucTotalBlockNum, (Uint32 *)gudOutStatus, gucDecStatus);
#ifdef THROUGHPUT_TEST
  	if(TEST_MODE == 1) /* LTE mode */
  	{
  		printf ("The decoder cycle number for LTE with 3CB 6144@CB is %d\n", gudEndCycle);
        printf ("The decoder throughput for LTE with 3CB 6144@CB is %fMbps for 1GHz\n", (float)3*6144/gudEndCycle*1000);
  	}
  	if(TEST_MODE == 3) /* WCDMA mode */
  	{
  		printf ("The decoder cycle number for WCDMA with 4CB 2000@CB is %d\n", gudEndCycle);
        printf ("The decoder throughput for WCDMA with 4CB 2000@CB is %fMbps for 1GHz\n", (float)4*2000/gudEndCycle*1000);
  	}
#endif
}

/* include the input test LLR and tail bits */
#ifdef THROUGHPUT_TEST
Int8 gscInLLR[TEST_MAX_BLOCK_NUM][3 * TEST_MAX_BIT_SIZE] = {
#if(TEST_MODE == 1)
	{
        #include "test_vector/LTE/block2_llrs.dat"
	},
	{
        #include "test_vector/LTE/block2_llrs.dat"
	},
	{
        #include "test_vector/LTE/block2_llrs.dat"
	},
#else if(TEST_MODE == 3)
	{
        #include "test_vector/wcdma/block3_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_llrs.dat"
	},
#endif
};
Int8  gscTailBits[TEST_MAX_BLOCK_NUM][12] = {
#if(TEST_MODE == 1)
	{
        #include "test_vector/LTE/block2_tail_llrs.dat"
	},
	{
        #include "test_vector/LTE/block2_tail_llrs.dat"
	},
	{
        #include "test_vector/LTE/block2_tail_llrs.dat"
	},
#else if(TEST_MODE == 3)
	{
        #include "test_vector/wcdma/block3_tail_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_tail_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_tail_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_tail_llrs.dat"
	},
#endif
};
#else
Int8 gscInLLR[TEST_MAX_BLOCK_NUM][3 * TEST_MAX_BIT_SIZE] = {
#if(TEST_MODE == 1)
	{
        #include "test_vector/LTE/block0_llrs.dat"
	},
	{
        #include "test_vector/LTE/block1_llrs.dat"
	},
	{
        #include "test_vector/LTE/block2_llrs.dat"
	},
#else if(TEST_MODE == 3)
	{
        #include "test_vector/wcdma/block0_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block1_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block2_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_llrs.dat"
	},
#endif
};
Int8  gscTailBits[TEST_MAX_BLOCK_NUM][12] = {
#if(TEST_MODE == 1)
	{
        #include "test_vector/LTE/block0_tail_llrs.dat"
	},
	{
        #include "test_vector/LTE/block1_tail_llrs.dat"
	},
	{
        #include "test_vector/LTE/block2_tail_llrs.dat"
	},
#else if(TEST_MODE == 3)
	{
        #include "test_vector/wcdma/block0_tail_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block1_tail_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block2_tail_llrs.dat"
	},
	{
        #include "test_vector/wcdma/block3_tail_llrs.dat"
	},
#endif
};
#endif
/*********************************************************************/
