//test define start
#define _GNU_SOURCE
#include <sched.h>
#include <stddef.h>
#include <string.h>
//#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include "typedef.h"
#include "ospHeap.h"
#include "ucp_printf.h"

/*typedef unsigned char uint8_t;
typedef signed char int8_t;
typedef int	int32_t;
typedef unsigned int uint32_t;
typedef long int int64_t;
typedef unsigned long int uint64_t;*/

extern int32_t g_dev_mem_fd;

static uint64_t get_cycle()
 {
    uint64_t cycle;

    asm volatile("mrs %0, pmccntr_el0" : "=r" (cycle));

    return cycle;
 }

int32_t test_case(uint32_t argc, int32_t* argvp)
//test_case(int argc, char *argv[])
{
    uint64_t stack_len = 0;
    uint32_t memset_len = 0;
    uint32_t ctl = 0,cnt, i = 0, j = 0, temp_len = 0;
    //uint8_t *memset_ptr;
    char *memset_stack_heap_ptr;
    char *memset_msg_heap_ptr;
    char *memset_ape_phy_heap_ptr;
    void *stack_heap_ptr;
    void *stack_static_ptr;
    void *msg_heap_ptr;
    void *msg_static_ptr;
    void *ape_phy_heap_ptr;
    void *ape_phy_static_ptr;
    struct timeval  begin,end,medium;
    uint64_t start_cnt = 0, end_cnt = 0, medium_cnt = 0;

	UCP_PRINT_DEBUG("start running testcase 1.");
	
    if(argc < 3)
    {
        printf("paramete need to be 3: len,ctl,cnt\n");
        return -1;
    }

    memset_len = (uint32_t)argvp[0];
    ctl 	   = (uint32_t)argvp[1];
    cnt		   = (uint32_t)argvp[2];
    
    stack_static_ptr = get_static_mem(ARM_STACK, &stack_len);
    if((void *)OSP_ERROR == stack_static_ptr)
    {
        printf("get_static_mem-ARM_STACK:error\n");
    }
    else
    {
        printf("get_static_mem-ARM_STACK:ok! stack_static_ptr = %lx\n",(uint64_t)stack_static_ptr);
    }
    stack_heap_ptr = osp_heap_mem_init(stack_static_ptr, stack_len, stack_static_ptr, ARM_STACK);
    memset_stack_heap_ptr = (char *)osp_alloc_heap_mem(stack_heap_ptr,memset_len);
    
    msg_static_ptr = get_static_mem(ARM_APE_MSG, &stack_len);
    if((void *)OSP_ERROR == msg_static_ptr)
    {
        printf("get_static_mem-MSG:error\n");
    }
    else
    {
        printf("get_static_mem-MSG:ok! msg_static_ptr = %lx\n",(uint64_t)msg_static_ptr);
    }    
    msg_heap_ptr = osp_heap_mem_init(msg_static_ptr, stack_len, msg_static_ptr, ARM_APE_MSG);
    memset_msg_heap_ptr = (char *)osp_alloc_heap_mem(msg_heap_ptr,memset_len);  

    ape_phy_static_ptr = get_static_mem(APE_PHY, &stack_len);
    if((void *)OSP_ERROR == ape_phy_static_ptr)
    {
        printf("get_static_mem-APE_PHY:error\n");
    }
    else
    {
        printf("get_static_mem-APE_PHY:ok! ape_phy_static_ptr = %lx\n",(uint64_t)ape_phy_static_ptr);
    }    
    ape_phy_heap_ptr = osp_heap_mem_init(ape_phy_static_ptr, stack_len, ape_phy_static_ptr, APE_PHY);
    memset_ape_phy_heap_ptr = (char *)osp_alloc_heap_mem(ape_phy_heap_ptr,memset_len);    
    
    
    if(0 == ctl)
    {
        memset_msg_heap_ptr += 0x20;
        while(1)
        {
            memset(memset_msg_heap_ptr, 0xa5 + i, 0x80);
            i++;
            osp_clean_dcache_area(memset_msg_heap_ptr, 0x54);
            //usleep(300);
        }
    } 
    else if(1 == ctl)  //上行
    {
        for(i = 0; i < cnt; i++) 
        {
            memset(memset_msg_heap_ptr,0xa5 + i,memset_len);
            gettimeofday(&begin, NULL);
            start_cnt = get_cycle();  
            //memset(memset_ptr,0x5A,memset_len);
            //invalid
            osp_invalid_dcache_area(ARM_APE_MSG,(uint64_t)memset_msg_heap_ptr,memset_len); 
            medium_cnt = get_cycle();  
            gettimeofday(&medium, NULL);
            memcpy(memset_stack_heap_ptr,memset_msg_heap_ptr,memset_len);
            end_cnt = get_cycle(); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_msg2stack start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",begin.tv_usec,medium.tv_usec,end.tv_usec,medium.tv_usec - begin.tv_usec,end.tv_usec - begin.tv_usec);
            //printf("gettimeofday_medium start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",medium.tv_usec,medium.tv_usec,medium.tv_usec - begin.tv_usec);
            printf("TSC_msg2stack start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",start_cnt,medium_cnt,end_cnt,medium_cnt - start_cnt,end_cnt - start_cnt);

            memset(memset_ape_phy_heap_ptr,0x55,memset_len);
            gettimeofday(&begin, NULL);
            start_cnt = get_cycle(); 
            memcpy(memset_stack_heap_ptr,memset_ape_phy_heap_ptr,memset_len);
            end_cnt = get_cycle(); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_phy2stack start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);
            printf("TSC_phy2stack start_cnt=%#lx,end_cnt=%#lx,diff=%ld\n\n",start_cnt,end_cnt,end_cnt - start_cnt);
        }
    }
    else if(2 == ctl)  //下行
    {
        for(i = 0; i < cnt; i++) 
        {    
            memset(memset_stack_heap_ptr,0x5a + i,memset_len);
            gettimeofday(&begin, NULL);
            start_cnt = get_cycle(); 
            memcpy(memset_msg_heap_ptr,memset_stack_heap_ptr,memset_len);
            medium_cnt = get_cycle();  
            gettimeofday(&medium, NULL);
            osp_clean_dcache_area(memset_msg_heap_ptr,memset_len);
            end_cnt = get_cycle(); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",begin.tv_usec,medium.tv_usec,end.tv_usec,medium.tv_usec - begin.tv_usec,end.tv_usec - begin.tv_usec);
            //printf("gettimeofday_medium start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",medium.tv_usec,medium.tv_usec,medium.tv_usec - begin.tv_usec);
            printf("TSC_stack2msg start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",start_cnt,medium_cnt,end_cnt,medium_cnt - start_cnt,end_cnt - start_cnt);
            
            gettimeofday(&begin, NULL);
            start_cnt = get_cycle(); 
            memcpy(memset_ape_phy_heap_ptr,memset_stack_heap_ptr,memset_len);
            end_cnt = get_cycle();
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2phy start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);
            printf("TSC_stack2phy start_cnt=%#lx,end_cnt=%#lx,diff=%ld\n\n",start_cnt,end_cnt,end_cnt - start_cnt);
        }
    }
    else if(3 == ctl)  //上行，先invalidate stack、msg，再memcpy
    {
        for(i = 0; i < cnt; i++) 
        {
            memset(memset_msg_heap_ptr,0xa5 + i,memset_len);
            
            //invalid
            gettimeofday(&begin, NULL);
            osp_invalid_dcache_area(ARM_STACK,(uint64_t)memset_stack_heap_ptr,memset_len); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg_invalidate stack buf start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);
            
            //invalid
            gettimeofday(&begin, NULL);
            osp_invalid_dcache_area(ARM_APE_MSG,(uint64_t)memset_msg_heap_ptr,memset_len); 
            gettimeofday(&end, NULL);
            
            printf("gettimeofday_stack2msg_invalidate msg buf start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);
            gettimeofday(&begin, NULL);
            memcpy(memset_stack_heap_ptr,memset_msg_heap_ptr,memset_len);
            gettimeofday(&end, NULL);
            printf("gettimeofday_msg2stack start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",begin.tv_usec,medium.tv_usec,end.tv_usec,medium.tv_usec - begin.tv_usec,end.tv_usec - begin.tv_usec);


            memset(memset_ape_phy_heap_ptr,0x55,memset_len);
            gettimeofday(&begin, NULL);
            osp_invalid_dcache_area(ARM_STACK,(uint64_t)memset_stack_heap_ptr,memset_len); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg_invalidate stack buf start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);

            gettimeofday(&begin, NULL);
            memcpy(memset_stack_heap_ptr,memset_ape_phy_heap_ptr,memset_len);
            gettimeofday(&end, NULL);
            printf("gettimeofday_phy2stack start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);

        }
    }
    else if(4 == ctl)   //下行，先invalidate stack，再memcpy
    {
        memset(memset_stack_heap_ptr, 0x5a + i, memset_len);

        for(i = 0; i < cnt; i++) 
        {
            //invalid
            gettimeofday(&begin, NULL);
            osp_invalid_dcache_area(ARM_STACK,(uint64_t)memset_stack_heap_ptr,memset_len); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg_invalidate stack buf start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);

            temp_len = 0;
            gettimeofday(&begin, NULL);
            for(j = 0; j < 100; j++)
            {
                memcpy(memset_msg_heap_ptr + temp_len, memset_stack_heap_ptr + temp_len, 1400);
                temp_len += 1400;
            }
            gettimeofday(&medium, NULL);
            osp_clean_dcache_area(memset_msg_heap_ptr,memset_len);        
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg start_cnt=%#lx,medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",begin.tv_usec,medium.tv_usec,end.tv_usec,medium.tv_usec - begin.tv_usec,end.tv_usec - begin.tv_usec);


            //invalid
            gettimeofday(&begin, NULL);
            osp_invalid_dcache_area(ARM_STACK,(uint64_t)memset_stack_heap_ptr,memset_len); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg_invalidate stack buf start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);

            temp_len = 0;     
            gettimeofday(&begin, NULL);
            for(j = 0; j < 100; j++)
            {
                memcpy(memset_ape_phy_heap_ptr  + temp_len, memset_stack_heap_ptr  + temp_len, memset_len);
                temp_len += 1400;
            }
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2phy start_cnt=%#lx,end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);
        }

    }   
    else if(5 == ctl)
    {
        for(i = 0; i < cnt; i++) 
        {    
            memset(memset_stack_heap_ptr,0x5a + i,memset_len);
            gettimeofday(&begin, NULL);
            start_cnt = get_cycle(); 
            memcpy(memset_msg_heap_ptr,memset_stack_heap_ptr,memset_len);
            medium_cnt = get_cycle();  
            gettimeofday(&medium, NULL);
            osp_clean_dcache_area(memset_msg_heap_ptr,memset_len);
            end_cnt = get_cycle(); 
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2msg start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",begin.tv_usec,medium.tv_usec,end.tv_usec,medium.tv_usec - begin.tv_usec,end.tv_usec - begin.tv_usec);
            //printf("gettimeofday_medium start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",medium.tv_usec,medium.tv_usec,medium.tv_usec - begin.tv_usec);
            printf("TSC_stack2msg start_cnt=%#lx, medium_cnt=%lx,end_cnt=%#lx,diff0 = %ld,diff1 = %ld\n\n",start_cnt,medium_cnt,end_cnt,medium_cnt - start_cnt,end_cnt - start_cnt);
            
            gettimeofday(&begin, NULL);
            start_cnt = get_cycle(); 
            memcpy(memset_ape_phy_heap_ptr,memset_stack_heap_ptr,memset_len);
            end_cnt = get_cycle();
            gettimeofday(&end, NULL);
            printf("gettimeofday_stack2phy start_cnt=%#lx, end_cnt=%#lx,diff = %ld\n\n",begin.tv_usec,end.tv_usec,end.tv_usec - begin.tv_usec);
            printf("TSC_stack2phy start_cnt=%#lx,end_cnt=%#lx,diff=%ld\n\n",start_cnt,end_cnt,end_cnt - start_cnt);
        }
    }  
    //free(memset_ptr);
    osp_free_heap_mem(stack_heap_ptr,memset_stack_heap_ptr);
    osp_free_heap_mem(msg_heap_ptr,memset_msg_heap_ptr);
    osp_free_heap_mem(ape_phy_heap_ptr,memset_ape_phy_heap_ptr);

	return 0;
}

