/* Appendix A. Source Code Listing. 					*/
/*************************************************************************
**	Project : CIS 629 project #1 Cache Memories.			**
**	Author 	: Sameer Shende 					**
**	Location: /home/grads/sameer/cis629/p10				**
**	File	: transpose.m						**
**	Description : This program runs on MASPAR-1 and calculates the  **
**		      transpose of matrix (64x64) using xnet and router **
*************************************************************************/

#include <stdio.h>
#include <mpl.h>


int  init_matrix(); /* to initialise the matrix */
void get_matrix();  /* to bring the plural matrix to the fe */ 
void transpose_matrix_xnet();   /* transpose the matrix using xnet */
void transpose_matrix_router(); /* transpose the matrix using router */
void show_matrix(); /* display the matrix */
void check_matrix();/* ensure that the matrix is correct */

/* Timer related MASPAR specific calls */
void dpuTimerStart();
unsigned long dpuTimerTicks();
double dpuTimerConst();

plural int dt; 		/* the data - or the matrix to be transposed */
int A[64][64]; 		/* matrix on fe. CHANGE 64 nxproc if running on another
			machine - MASPAR  in UO specific */
main()
{
	init_matrix();	/* to initialise the matrix */
	get_matrix();  /* to bring the plural matrix to the fe */ 

  	dpuTimerStart(); /* TIMER related call - initialises the Timer */
	transpose_matrix_xnet(); /* transpose the matrix using xnet */
 	printf("XNET TRANSPOSE 64x64 DPU cycles: %d\n", dpuTimerTicks());
  	printf("XNET TRANSPOSE 64x64 DPU time:   %f\n", 
		(float)dpuTimerTicks() * (float)dpuTimerConst());
	get_matrix();  /* to bring the plural matrix to the fe */ 

	show_matrix();

	 /* display the matrix */
  
	dpuTimerStart(); /* Start timer */
	transpose_matrix_router(); /* transpose the matrix using router */
  	printf("ROUTER TRANSPOSE 64x64 DPU cycles: %d\n", dpuTimerTicks());
  	printf("ROUTER TRANSPOSE 64x64 DPU time:   %f\n", 
		(float)dpuTimerTicks() * (float)dpuTimerConst());
	get_matrix(); /* to bring the plural matrix to the fe */ 
	show_matrix(); /* display the matrix */
	check_matrix(); /* ensure that the matrix is correct */
}

 /* to bring the plural matrix to the fe */ 
void get_matrix(void)
{
	int i,j,no;
	/* on the front end */

	for(i=0;i<nxproc;i++)
		for(j = 0;j< nyproc; j++)
		{
			no = i*nxproc + j;
			A[i][j] = proc[no].dt;
		}
	
	/* This routine puts dt of every node in the proper ordering in A */
}

int init_matrix(void)
{
/* This routine pits values in dt  - Initialisation */
	dt = iproc; 
}

void transpose_matrix_xnet()
{	 /* transpose the matrix using xnet */
	int hop;
	plural int temp; /* temporary storage */

	

	for (hop=1;hop<nxproc+1; hop++)
	{
		if ((iyproc-ixproc) == hop)
		{ /* switch dt between iproc and the other element hop away */
			temp = xnetNE[hop].dt;
			xnetNE[hop].dt = dt;
			dt = temp;
/*
		p_printf(" After xnet ix = %d, iy=%d, temp = %d, dt = %d\n",
			ixproc, iyproc, temp, dt);
*/
		}
	}
}

void transpose_matrix_router()
{ /* transpose the matrix using router */
	plural int other_no, temp;

	other_no = ixproc * nxproc + iyproc ;

	temp = router[other_no].dt;
/*
	p_printf(" After router ix = %d, iy=%d, temp = %d, dt = %d\n",
			ixproc, iyproc, temp, dt);
*/
	dt = temp; 
	/* Every PE does this. All are active in this simple switch */

}

void show_matrix()
{ /* display the matrix */
int i,j;

	for(i=0;i<nxproc;i++)
	{
		for(j = 0;j< nyproc; j++)
		{ if ((i < 10)&&(j < 10))
			/*
			printf("A[%d][%d] = %d\n", i,j,A[i][j]);
			*/
			printf("%d ", A[i][j]);
		}
		if(i<10)
		printf("\n");
	}	
}

void check_matrix()
{ /* checks to see if it has been transposed correctly */
int i,j;

	for(i=0;i<nxproc;i++)
		for(j = 0;j< nyproc; j++)
		{
			if(A[i][j] != i*nxproc + j)
			printf(" PANIC!!! A[%d][%d] = %d, dt = %d\n", i,j,A[i][j],i*nxproc+j);
		}
	
}
/* EOF transpose.m */

