/*
 * This is a simple program to test multi-core microblaze SoC
 */
#include "u_kernel.h"

#include "AVC/DecTest.h"

#define APP_MUTEX_NUM 1
#define STACK_SIZE 4096

volatile kernelTable *KTBL = (kernelTable *) (KERNEL_TABLE_ADDR);
volatile int *main_stack[NUM_CORES];
volatile void *AppThreadPtr[NUM_CORES];


void startApplicationThreads(void);
void stack_init(void);
void core_1_thread(void *parameter);
void core_2_thread(void *parameter);
void core_3_thread(void *parameter);


int main()
{

    unsigned int core_id = getCurrentCoreID();

    enableCaches();
    microblaze_flush_dcache();

    mutex_lock(APP_MUTEX_NUM);
    printf("Core %d: Hello World!\r\n", core_id);
    mutex_unlock(APP_MUTEX_NUM);

    AppThreadPtr[1] = core_1_thread;
    AppThreadPtr[2] = core_2_thread;
    AppThreadPtr[3] = core_3_thread;

    /* lock other core */
    mutex_lock(SYN_MUTEX_NUM);


    startApplicationThreads();


    /* application part */

    int wfState = waveFront();
    if(wfState){
    	mutex_lock(APP_MUTEX_NUM);
    	printf("Decode error");
    	mutex_unlock(APP_MUTEX_NUM);
    }

	mutex_lock(APP_MUTEX_NUM);
		printf("app over\n");
	mutex_unlock(APP_MUTEX_NUM);



    /* end */

    disableCaches();

    return 0;
}


void core_1_thread(void *parameter)
{


    while(1){

    	/* start application */
    	while(1){

    		mutex_lock(SYN_MUTEX_NUM);
    		mutex_unlock(SYN_MUTEX_NUM);

    		int currState = 0;
    		currState = thr_decode_one_row(1);
    		if(currState){
    			mutex_lock(APP_MUTEX_NUM);
    			printf("thr_decode_one_row error\n");
    			mutex_unlock(APP_MUTEX_NUM);
    		}
    		else
    			break;
    	}
    }

    while (1) { /* thread never returns */ };
}


void core_2_thread(void *parameter)
{

    while(1){


    	/* start application */
    	while(1){

    		mutex_lock(SYN_MUTEX_NUM);
    		mutex_unlock(SYN_MUTEX_NUM);

    		int currState = 0;
    		currState = thr_decode_one_row(2);
    		if(currState){
    			mutex_lock(APP_MUTEX_NUM);
    			printf("thr_decode_one_row error\n");
    			mutex_unlock(APP_MUTEX_NUM);
    		}
    		else
    			break;
    	}
    }

    while (1) { /* thread never returns */ };
}


void core_3_thread(void *parameter)
{

	while(1){

		/* start application */
		while(1){

			mutex_lock(SYN_MUTEX_NUM);
    		mutex_unlock(SYN_MUTEX_NUM);

    		/* only main thread (not only do entropy but aslo decode MB )and two thread */

//			int currState = 0;
//			currState = thr_decode_one_row(3);
//			if(currState){
//				mutex_lock(APP_MUTEX_NUM);
//				printf("thr_decode_one_row error\n");
//				mutex_unlock(APP_MUTEX_NUM);
//			}
//			else
//				break;
		}
	}

    while (1) { /* thread never returns */ };
}

void startApplicationThreads(void)
{
    /* Tell the slave cores to start running its thread */
    KTBL->applicationThreadPtr[1] = core_1_thread;
    KTBL->applicationThreadPtr[2] = core_2_thread;
    KTBL->applicationThreadPtr[3] = core_3_thread;
    KTBL->bootSync = MASTER_CPU_SYNC_MAGIC_CODE;
}
