Exemple #1
0
int main()
{
  /*
   * L'adresse de démarrage décodée depuis le fichier S-record n'est pas
   * prise en compte, puisque le processeur PowerPC ne peut démarrer qu'à
   * l'adresse 0xFFFFFFFC. Une fois le fichier S-record chargé en mémoire,
   * on demande au processeur de se reseter pour booter le nouveau programme.
   */
  Xuint32 start_address;
  XStatus status;

  XCache_DisableDCache();
  XCache_DisableICache();
  print("Starting bootloader.\r\n");
  status = load_srec("a:\\boot.me", &start_address);
  if (status == XST_SUCCESS)
  {
    // branchement
    print("All right ! Let's go, girls !\r\n\r\n");
    usleep(100000);
    asm("lis 0,0x3000");
    asm("mtdbcr0 0"); // soft reset powaaa !!
  }
  print("Boot failed.\r\n");
  return 0;
}
Exemple #2
0
int main( int argc, char *argv[] )
{
    Huint           sta;
    void*           retval;
    hthread_t       tid;
    hthread_attr_t  attr;
    int num_ops = 0;
	printf( "\n****Main Thread****... \n" );

    XCache_DisableDCache();

// *************************************************************************************    
    unsigned int *fcn_pointer = (unsigned int*)(HWTI_BASEADDR + 6*sizeof(int));

    int code_offset				= 0;
	FuncPointer fp 				= 0;
	unsigned char * prog_ptr	= 0;
	unsigned int * first_instr = 0;

	// Initialize code offset and program pointer
	code_offset = 0x1f0; //0x1d4;//0x1a8;
	prog_ptr = (unsigned char *)&junk_o;
			
	// Initialize function pointer (actual place to jump to)
	fp = (FuncPointer)(prog_ptr + code_offset);

	// Initialize a pointer that allows one to "look" at the 1st instruction
	first_instr = (unsigned int*)(prog_ptr + code_offset);

    *fcn_pointer = (int)fp;
// *************************************************************************************    


    for( num_ops = 0; num_ops < 5; num_ops++)
    { 
	    // Initialize the attributes for the hardware thread
	    hthread_attr_init( &attr );
	    hthread_attr_sethardware( &attr, HWTI_BASEADDR );
	
	    // Create the hardware thread
		printf( "Starting Hardware Thread... \r" );
	    sta = hthread_create( &tid, &attr, (void*)fp, (void*)(num_ops) );
		printf( "Started Hardware Thread (TID = %d) (ARG = %d)... 0x%8.8x\n", tid, num_ops, sta );
	
	    // Clean up the attribute structure
	    hthread_attr_destroy( &attr );
	
	    // Wait for the hardware thread to exit
		printf( "Waiting for Hardware Thread... \r" );
	    hthread_join( tid, &retval );
		printf( "Joined on  Hardware Thread... 0x%8.8x\n", (Huint)retval );
    }
    // Return from main
    return 0;
}
Exemple #3
0
//! at start enable cache
void cyg_user_start(void){

   
#ifdef USE_CACHE
    printf( "enabling data cache for external ram\n" );
     XCache_EnableDCache( 0xF0000000 );
#else
    printf( "data cache disabled\n" );
    XCache_DisableDCache(  );
#endif   

}
void
disable_caches()
{
#ifdef __PPC__
    XCache_DisableDCache();
    XCache_DisableICache();
#elif __MICROBLAZE__
#ifdef XPAR_MICROBLAZE_USE_DCACHE
#if !XPAR_MICROBLAZE_DCACHE_USE_WRITEBACK
    microblaze_invalidate_dcache();
#endif
    microblaze_disable_dcache();
#endif
#ifdef XPAR_MICROBLAZE_USE_ICACHE
    microblaze_invalidate_icache();
    microblaze_disable_icache();
#endif
#endif
}
Exemple #5
0
int main (void) {


   XCache_EnableICache(0x80000001);
   XCache_EnableDCache(0x80000000);

   /* Initialize RS232 - Set baudrate and number of stop bits */
   XUartNs550_SetBaud(XPAR_RS232_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, 9600);
   XUartNs550_mSetLineControlReg(XPAR_RS232_BASEADDR, XUN_LCR_8_DATA_BITS);
   print("-- Entering main() --\r\n");

   /* 
    * MemoryTest routine will not be run for the memory at 
    * 0x81000000 (FLASH_8Mx16)
    * because it is a read-only memory
    */


   /* 
    * MemoryTest routine will not be run for the memory at 
    * 0x00000000 (DDR_SDRAM_1)
    * because it is being used to hold a part of this application program
    */


   /* 
    * MemoryTest routine will not be run for the memory at 
    * 0xfffff000 (plb_bram_if_cntlr_1)
    * because it is being used to hold a part of this application program
    */


   print("-- Exiting main() --\r\n");
   XCache_DisableDCache();
   XCache_DisableICache();
   return 0;
}
int main (void) {


   XCache_EnableICache(0x00000001);
   XCache_EnableDCache(0x00000001);
	
   XCache_DisableDCache();
   XCache_DisableICache();

   xil_printf("\r\n-- Entering main() --\r\n");
	
	/************************ SDRAM SelfTest **************************/
	xil_printf("Performing SelfTest of SDRAM controller...\r\n");
	
	int iteration = 0;
	while(1)
	{
		xil_printf("*Iteration %d\r\n", iteration++);
	int Status;
	int i;
	volatile a;
	volatile b;
	int TotalErrors;
	Xuint8 dcm_psen, dcm_psincdec, dcm_done;
	
	mySDRAMConfig = XMpmc_LookupConfig(XPAR_MPMC_0_DEVICE_ID);
	if(mySDRAMConfig == NULL)
	{
		xil_printf("Could not find SDRAM based on dev id\r\n");
		return XST_FAILURE;
	}
	else {
		xil_printf("Got SDRAM config\r\n");
	}
	Status = XMpmc_CfgInitialize(&mySDRAM,mySDRAMConfig, XPAR_MPMC_0_MPMC_BASEADDR);
	if(Status != XST_SUCCESS) {
		xil_printf("Initialization Failed!\r\n");
		return XST_FAILURE;
	}
	else {
		xil_printf("Initialization Complete!\r\n");
	}
	Status = XMpmc_SelfTest(&mySDRAM);
	if(Status != XST_SUCCESS) {
		xil_printf("SelfTest Failed!\r\n");
		return XST_FAILURE;
	}
	else {
		xil_printf("SelfTest Complete!\r\n");
	}
	
	
	/***************** START CALIBRATION ***************/
	Status = MpmcCalibrationExample(XPAR_MPMC_0_DEVICE_ID);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
	/***************** END CALIBRATION *****************/
	
	TotalErrors = MpmcMemTestExample(XPAR_MPMC_0_DEVICE_ID);

	if (TotalErrors) {
		xil_printf("\r\n### Program finished with errors ###\r\n");
	} else {
		xil_printf("\r\n### Program finished successfully ###\r\n");
	}
	
	
	ENABLE_ICACHE();
	ENABLE_DCACHE();
	
	Xuint32 memSize = XPAR_MPMC_0_MPMC_HIGHADDR - XPAR_MPMC_0_MPMC_BASEADDR + 1; //get correct SDRAM size
	Xuint32* myAddress = (Xuint32*)XPAR_MPMC_0_MPMC_BASEADDR;
	
	xil_printf("\r\nStarting Wade's special Test...\r\n");
	char wadeSuccess = RunAllMemoryTests(myAddress, memSize);
	
	if (wadeSuccess){
		xil_printf("Wade's test PASSED!");
	}
	else{
		xil_printf("Wade's test FAILED!");
	}	
	
	xil_printf("Total Errors: %d\r\n", TotalErrors);
	}
}
Exemple #7
0
void disable_caches()
{

    XCache_DisableDCache();
    XCache_DisableICache();
}
Exemple #8
0
int main( int argc, char *argv[] )
{

    unsigned int i, start_count = 0, done_count = 0;
    timing_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge =
        0, t_check = 0;
    unsigned int *addr;
    unsigned int dummy;
    int retval;

    printf( "-------------------------------------------------------\n"
            "ReconOS hardware multithreading case study (sort)\n"
            "(c) Computer Engineering Group, University of Paderborn\n\n"
            "eCos/POSIX, multi-threaded hardware version (" __FILE__ ")\n"
            "Compiled on " __DATE__ ", " __TIME__ ".\n"
            "-------------------------------------------------------\n\n" );

#ifdef USE_CACHE
    printf( "enabling data cache for external ram\n" );
    XCache_EnableDCache( 0x80000000 );
#else
    printf( "data cache disabled\n" );
    XCache_DisableDCache(  );
#endif

    data = buf_a;

    //----------------------------------
    //-- GENERATE DATA
    //----------------------------------
    printf( "Generating data..." );
    t_start = gettime(  );
    generate_data( data, SIZE );
    t_stop = gettime(  );
    t_gen = calc_timediff_ms( t_start, t_stop );
    printf( "done\n" );

#ifdef USE_CACHE
    // flush cache contents - the hardware can only read from main memory
    // TODO: storing could be more efficient
    printf( "Flushing cache..." );
    XCache_EnableDCache( 0x80000000 );
    printf( "done\n" );
#endif

    //----------------------------------
    //-- SORT DATA
    //----------------------------------
    // create mail boxes for 'start' and 'complete' messages
    mb_start_attr.mq_flags   = mb_done_attr.mq_flags   = 0;
    mb_start_attr.mq_maxmsg  = mb_done_attr.mq_maxmsg  = 10;
    mb_start_attr.mq_msgsize = mb_done_attr.mq_msgsize = 4;
    mb_start_attr.mq_curmsgs = mb_done_attr.mq_curmsgs = 0;

    // unlink mailboxes, if they exist
    retval = mq_unlink("/mb_start");
    if (retval != 0 && errno != ENOENT) {    // we don't care if it doesn't exist
        diag_printf("unable to unlink mb_start");
    }
    retval = mq_unlink("/mb_done");
    if (retval != 0 && errno != ENOENT) {    // we don't care if it doesn't exist
        diag_printf("unable to unlink mb_done");
    }

    // open/create mailboxes
    mb_start = mq_open("/mb_start",
            O_RDWR | O_CREAT, S_IRWXU | S_IRWXG,
            &mb_start_attr);
    if (mb_start == (mqd_t)-1) {
        diag_printf("unable to create mb_start");
    }
    mb_done = mq_open("/mb_done",
            O_RDWR | O_CREAT, S_IRWXU | S_IRWXG,
            &mb_done_attr);
    if (mb_done == (mqd_t)-1) {
        diag_printf("unable to create mb_done");
    }

    // create sorting sowftware threads
    for ( i = 0; i < MT_HW_NUM_SW_THREADS; i++ ) {
        pthread_attr_init(&thread_sorter_attr[i]);
        pthread_create(&thread_sorter[i],
                &thread_sorter_attr[i],
                sort8k_entry_posix, (void*)i);
    }

    // create sorting hardware thread
    pthread_attr_init(&hwthread_sorter_attr);
    pthread_attr_setstacksize(&hwthread_sorter_attr, STACK_SIZE);
    rthread_attr_init(&hwthread_sorter_hwattr);
    rthread_attr_setslotnum(&hwthread_sorter_hwattr, 0);
    rthread_attr_setresources(&hwthread_sorter_hwattr, hwthread_sorter_resources, 2);
    rthread_create(&hwthread_sorter, &hwthread_sorter_attr, &hwthread_sorter_hwattr, (void*)0);

    printf( "Sorting data..." );
    i = 0;

    t_start = gettime(  );

    // put 9 messages into mb_start
    while ( start_count < 9 ) {
        addr = &data[i];
        if ( mq_send( mb_start, ( void * ) &addr, sizeof(addr), 0 ) == 0 ) {
            start_count++;
            i += N;
        } else {                                                          
            perror("while sending to mq_send");
            break;
        }
    }

    t_stop = gettime(  );
    t_sort += calc_timediff_ms( t_start, t_stop );

    while ( done_count < SIZE / N ) {
        t_start = gettime(  );
        // if we have something to distribute,
        // put one into the start mailbox
        if ( start_count < SIZE / N ) {
            addr = &data[i];
            if ( mq_send( mb_start, ( void * ) &addr, sizeof(addr), 0 ) == 0 ) {
                start_count++;
                i += N;
            } else {                                                          
                perror("while sending to mq_send");
                break;
            }
        }
        // see whether anybody's done
        if ( mq_receive( mb_done, (void*)&dummy, sizeof(dummy), 0 ) == sizeof(dummy) ) {
            done_count++;
        } else {
            perror( "while receiving from mq_done" );
            break;
        }
        t_stop = gettime(  );
        t_sort += calc_timediff_ms( t_start, t_stop );
    }
    printf( "done\n" );

#ifdef USE_CACHE
    // flush cache contents
    // TODO: invalidating would suffice
    printf( "Flushing cache..." );
    XCache_EnableDCache( 0x80000000 );
    printf( "done\n" );
#endif


    //----------------------------------
    //-- MERGE DATA
    //----------------------------------
    printf( "Merging data..." );
    t_start = gettime(  );
    data = recursive_merge( data, buf_b, SIZE, N, simple_merge );
    t_stop = gettime(  );
    t_merge = calc_timediff_ms( t_start, t_stop );
    printf( "done\n" );

    //----------------------------------
    //-- CHECK DATA
    //----------------------------------
    printf( "Checking sorted data..." );
    t_start = gettime(  );
    if ( check_data( data, SIZE ) != 0 )
        printf( "CHECK FAILED!\n" );
    else
        printf( "check successful.\n" );
    t_stop = gettime(  );
    t_check = calc_timediff_ms( t_start, t_stop );

    printf( "\nRunning times (size: %d words):\n"
            "\tGenerate data: %d ms\n"
            "\tSort data    : %d ms\n"
            "\tMerge data   : %d ms\n"
            "\tCheck data   : %d ms\n"
            "\nTotal computation time (sort & merge): %d ms\n",
            SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge );


    return 0;

}
/**
*
* This function gets the calibration value.
*
* @param	InstancePtr is a pointer to an XMpmc instance to be worked on.
*
* @return	XST_SUCCESS if the DCM Phase shift decrement is completed
*		else XST_FAILURE.
*
* @note		None.
*
*****************************************************************************/
int MpmcGetCalibrate(XMpmc *InstancePtr, u32 MemoryStartAddr,
			MpmcCalibReturnValue *CalibStatus)
{
	int Count;
	MpmcCalibValue LocalCalibValue;
	int ValidCount;
	u32 RegValue;
	u8 Toggle = 0;
	u32 Status;

	LocalCalibValue.FoundValid = FALSE;
	RegValue = MPMC_RDEN_DELAY_MIN_VAL;

	/*
	 * Get the initial value from the register.
	 */
	LocalCalibValue.OrigTapValue = XMpmc_GetStaticPhyReg(InstancePtr) &
						XMPMC_SPIR_DCM_TAP_VALUE_MASK;
	if (LocalCalibValue.OrigTapValue > MPMC_MAX_TAPS) {
		LocalCalibValue.OrigTapValue =
				LocalCalibValue.OrigTapValue - 0x100;
	}

	/*
	 * Try to find valid calibration settings.
	 */
	while (LocalCalibValue.FoundValid == FALSE) {

		LocalCalibValue.MinValue = MPMC_MAX_TAPS - 1;
		LocalCalibValue.MaxValue = MPMC_MIN_TAPS + 1;

		/*
		 * Reset DCM to minimum value
		 */
		Status = MpmcResetDcmPhaseShift(InstancePtr);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}


		/*
		 * Read the memory and check that data versus the expected
		 * value.
		 *
		 * If the value matches, read the current calibration value.
		 * Repeat this to ensure that this is not on a transition.
		 * If the value is incorrect in any of these increments, the
		 * value must be re-established.
		 *
		 * If the value at 0 does match then we are probably in a case
		 * where the window is a wrap case.  This means that we are
		 * looking for the upper bound not the lower bound.
		 */
		ValidCount = 0;
		for (Count = MPMC_MIN_TAPS; Count < MPMC_MAX_TAPS; Count++) {

			MpmcWriteTestPattern(MemoryStartAddr, Toggle);


			if (MpmcCheckPattern(MemoryStartAddr, Toggle) !=
						XST_SUCCESS) {

				/*
				 * Found invalid calibration setting.
				 */
				if (ValidCount > MPMC_EDGE_TAPS) {
					LocalCalibValue.MaxValue = Count;
				}
				ValidCount = 0;
			} else {

				/*
				 * Found valid calibration setting
				 * Check to make sure that cache reads work.
				 */

#ifdef __MICROBLAZE__
#if XPAR_MICROBLAZE_0_USE_DCACHE
				/*
				 * Initialize and Enable the data cache.
				 */
				microblaze_init_dcache_range(0,
					XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
				microblaze_enable_dcache();
#endif
#endif

#ifdef __PPC__
				/*
				 * Enable the Dcache for all memory regions
				 * except the boot region of the PPC.
				 */
				XCache_InvalidateDCacheLine(MemoryStartAddr);
				XCache_EnableDCache(0xFFFFFFFE);

#endif
				Status = MpmcCheckPattern(MemoryStartAddr,
								Toggle);

				/*
				 * Disable and reinitialize the data cache.
				 */
#ifdef __MICROBLAZE__
#if XPAR_MICROBLAZE_0_USE_DCACHE
				microblaze_disable_dcache();
				microblaze_init_dcache_range(0,
					XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
#endif
#endif

#ifdef __PPC__
				XCache_DisableDCache();
				XCache_InvalidateDCacheLine(MemoryStartAddr);
#endif


				if (Status != XST_SUCCESS) {
					/*
					 * Found invalid calibration setting
					 */
					if (ValidCount > MPMC_EDGE_TAPS) {
						LocalCalibValue.MaxValue =
								Count;
					}
					ValidCount = 0;
				} else {
					/*
					 * Found valid calibration setting
					 */
					if (ValidCount == MPMC_EDGE_TAPS) {
						LocalCalibValue.MinValue =
							Count - MPMC_EDGE_TAPS;
						LocalCalibValue.MaxValue =
									Count;
					}
					else if (ValidCount > MPMC_EDGE_TAPS) {
						LocalCalibValue.MaxValue =
									Count;
					}
					ValidCount++;
					if (ValidCount>MPMC_EDGE_TAPS) {
						LocalCalibValue.FoundValid =
								TRUE;
					}
				}
			}

			Status = MpmcIncDcmPhaseShift(InstancePtr, RegValue);
			if (Status != XST_SUCCESS) {
				return XST_FAILURE;
			}

			if (Toggle == 0) {
				Toggle = 1;
			} else {
				Toggle = 0;
			}
		}

		if ((LocalCalibValue.FoundValid == FALSE) &&
			(((RegValue & XMPMC_SPIR_RDEN_DELAY_MASK)
					!= MPMC_RDEN_DELAY_MAX_VAL) ||
			((RegValue & XMPMC_SPIR_RDDATA_CLK_SEL_MASK) !=
					XMPMC_SPIR_RDDATA_CLK_SEL_MASK) ||
			((RegValue & XMPMC_SPIR_RDDATA_SWAP_RISE_MASK) !=
					XMPMC_SPIR_RDDATA_SWAP_RISE_MASK))){
			if ((RegValue & XMPMC_SPIR_RDEN_DELAY_MASK) !=
					MPMC_RDEN_DELAY_MAX_VAL) {
				RegValue = RegValue + MPMC_RDEN_DELAY_INC;
			}
			else if ((RegValue & XMPMC_SPIR_RDDATA_CLK_SEL_MASK) !=
					XMPMC_SPIR_RDDATA_CLK_SEL_MASK) {
				RegValue =
					(RegValue |
					XMPMC_SPIR_RDEN_DELAY_MASK) -
					XMPMC_SPIR_RDEN_DELAY_MASK +
					MPMC_RDEN_DELAY_MIN_VAL +
					XMPMC_SPIR_RDDATA_CLK_SEL_MASK;
			}
			else if ((RegValue & XMPMC_SPIR_RDDATA_SWAP_RISE_MASK)
			!=
					XMPMC_SPIR_RDDATA_SWAP_RISE_MASK) {
				RegValue =
					(RegValue |
					XMPMC_SPIR_RDEN_DELAY_MASK) -
					XMPMC_SPIR_RDEN_DELAY_MASK +
					MPMC_RDEN_DELAY_MIN_VAL -
					XMPMC_SPIR_RDDATA_CLK_SEL_MASK +
					XMPMC_SPIR_RDDATA_SWAP_RISE_MASK;
			}
		} else if (LocalCalibValue.FoundValid == FALSE) {
			xil_printf("\r\n ERROR: Could not calibrate.\r\n");
				return XST_FAILURE;
		}
	}

	CalibStatus->FoundValid = LocalCalibValue.FoundValid;
	CalibStatus->MinValue = LocalCalibValue.MinValue;
	CalibStatus->MaxValue = LocalCalibValue.MaxValue;
	CalibStatus->RegValue = RegValue;

	if (LocalCalibValue.MaxValue >= LocalCalibValue.MinValue) {
		CalibStatus->CalibTapValue = (LocalCalibValue.MinValue +
						LocalCalibValue.MaxValue)/2;
	} else {
		CalibStatus->CalibTapValue = (LocalCalibValue.MinValue +
					LocalCalibValue.MaxValue +
					MPMC_NUMBER_TAPS)/2;

		if (CalibStatus->CalibTapValue > MPMC_MAX_TAPS) {
			CalibStatus->CalibTapValue =
				(CalibStatus->CalibTapValue - MPMC_NUMBER_TAPS);
		}
	}

	return XST_SUCCESS;
}
/**
*
* The purpose of this function is to illustrate how to use the MPMC
* driver for the Calibration of the Static Phy.
*
* @param	DeviceId is device ID of the XMpmc Device, typically
*		XPAR_<MPMC_instance>_DEVICE_ID value from xparameters.h.
*
* @return	XST_SUCCESS to indicate success, otherwise XST_FAILURE.
*
* @note		None.
*
******************************************************************************/
int MpmcCalibrationExample(u16 DeviceId)
{
	XMpmc_Config *CfgPtr;
	int Status;
	MpmcCalibReturnValue CalibStatus;

	/*
	 * Disable the data cache and reinitialize it.
	 */
#ifdef __MICROBLAZE__
#if XPAR_MICROBLAZE_0_USE_DCACHE
	microblaze_disable_dcache();
	microblaze_init_dcache_range(0,
			XPAR_MICROBLAZE_0_DCACHE_BYTE_SIZE);
#endif
#endif

#ifdef __PPC__
	XCache_DisableDCache();
	XCache_InvalidateDCacheLine(MPMC_CALIBRATON_STARTADDR);
#endif

	//xil_printf("\r\n Starting the Calibration Example \n\n");

	/*
	 * Initialize the MPMC device.
	 */
	CfgPtr = XMpmc_LookupConfig(DeviceId);
	if (CfgPtr == XNULL) {
		return XST_FAILURE;
	}

	Status = XMpmc_CfgInitialize(&Mpmc, CfgPtr, CfgPtr->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Wait for the initial initialization sequence to be complete.
	 */
	while ((XMpmc_GetStaticPhyReg(&Mpmc) & XMPMC_SPIR_INIT_DONE_MASK) !=
						XMPMC_SPIR_INIT_DONE_MASK);

	/*
	 * Begin Calibration.
	 */
	Status = MpmcGetCalibrate(&Mpmc, MPMC_CALIBRATON_STARTADDR,
					&CalibStatus);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}


	/*
	 * Set the calibrated value in the Static Phy Register.
	 */
	if (CalibStatus.FoundValid == TRUE) {
		/*
		xil_printf("\r Setting the phase shift to %0d. ",
					CalibStatus.CalibTapValue);
		xil_printf("Min Value = %d. Max Value = %d.\r\n",
					CalibStatus.MinValue,
					CalibStatus.MaxValue);
		*/

		MpmcSetCalibrate(&Mpmc, CalibStatus.CalibTapValue,
					CalibStatus.RegValue);
		if (Status != XST_SUCCESS) {
			return XST_FAILURE;
		}

  	}

	//xil_printf("\r\n Calibration is Successful \r\n");

	return XST_SUCCESS;
}
Exemple #11
0
int run_tests()
{
    // Timer variables
    xps_timer_t timer;
    int time_create, time_start, time_unlock, time_stop;

    // Mutex
    hthread_mutex_t * mutex          = (hthread_mutex_t*)malloc( sizeof(hthread_mutex_t) );
    hthread_mutex_init( mutex, NULL );

    float min;

    // Thread attribute structures
    Huint           sta[NUM_THREADS];
    void*           retval[NUM_THREADS];
    hthread_t       tid[NUM_THREADS];
    hthread_attr_t  attr[NUM_THREADS];
    targ_t thread_arg[NUM_THREADS];

    // Setup Cache
    XCache_DisableDCache();
    XCache_EnableICache(0xc0000801);

    // Create timer
    xps_timer_create(&timer, (int*)0x20400000);

    // Start timer
    xps_timer_start(&timer);

// *************************************************************************************    
    extern unsigned char intermediate[];

    extern unsigned int min_handle_offset;
    unsigned int min_handle = (min_handle_offset) + (unsigned int)(&intermediate);


// *************************************************************************************    
    printf("Code start address = 0x%08x\n", (unsigned int)&intermediate);

    int i = 0;
    float main_array[ARRAY_LENGTH];
    printf("Addr of array = 0x%08x\n",(unsigned int)&main_array[0]);
    for (i = 0; i < ARRAY_LENGTH; i++)
    {
        main_array[i] = (i+2)*3.14f;
    }


    int num_items = ARRAY_LENGTH/NUM_THREADS;
    int extra_items = ARRAY_LENGTH - (num_items*NUM_THREADS);
    float * start_addr = &main_array[0];
    for (i = 0; i < NUM_THREADS; i++)
    {
        // Initialize the attributes for the hardware threads
        hthread_attr_init( &attr[i] );
        hthread_attr_sethardware( &attr[i], (void*)base_array[i] );

        // Initialize thread arguments
        thread_arg[i].num_items = num_items;
        thread_arg[i].data_ptr = start_addr;
        thread_arg[i].min_mutex = mutex;
        thread_arg[i].min  = &min;
        start_addr+=num_items;
    }
    // Add in extra items for the last thread if needed
    thread_arg[i-1].num_items += extra_items;

    int num_ops = 0;
    for( num_ops = 0; num_ops < 2; num_ops = num_ops + 1)
    { 

        printf("******* Round %d ********\n",num_ops);
#ifdef USE_MB_THREAD
    printf("**** MB-based Threads ****\n");
#else
    printf("**** PPC-based Threads ****\n");
#endif
        min = 9999999;

        // Lock mutex before hand so that timing will not include thread creation time
        hthread_mutex_lock(mutex);

        // Start timing thread create
        time_create = xps_timer_read_counter(&timer);

        for (i = 0; i < NUM_THREADS; i++)
        {
            // Create the worker threads
#ifdef USE_MB_THREAD

            // Create MB Thread
            sta[i] = hthread_create( &tid[i], &attr[i], (void*)(min_handle), (void*)(&thread_arg[i]) );
#else
            // Create SW Thread
            sta[i] = hthread_create( &tid[i], NULL, min_thread, (void*)(&thread_arg[i]) );
#endif
        }

        // Allow created threads to begin running and start timer
        time_start = xps_timer_read_counter(&timer);
        hthread_mutex_unlock(mutex);
        time_unlock = xps_timer_read_counter(&timer);

        // Wait for the threads to exit
		//printf( "Waiting for thread(s) to complete... \n" );
        for (i = 0; i < NUM_THREADS; i++)
        {
    	    hthread_join( tid[i], &retval[i] );
        }

        time_stop = xps_timer_read_counter(&timer);

        // Display results
        printf("Min = %f\n",min);
        for (i = 0; i < NUM_THREADS; i++)
        {
            printf("TID = 0x%08x, status = 0x%08x, retval = 0x%08x\n",tid[i],sta[i],(Huint)retval[i]);
        }
        printf("*********************************\n");
        printf("Create time  = %u\n",time_create);
        printf("Start time   = %u\n",time_start);
        printf("Unlock time  = %u\n",time_unlock);
        printf("Stop time    = %u\n",time_stop);
        printf("*********************************\n");
        printf("Creation time (|Start - Create|) = %u\n",time_start - time_create);
        printf("Unlock time (|Unlock - Start|)   = %u\n",time_unlock - time_start);
        printf("Elapsed time  (|Stop - Start|)   = %u\n",time_stop - time_start);

    }

    hthread_mutex_destroy( mutex );
    free( mutex );

    // Clean up the attribute structures
    for (i = 0; i < NUM_THREADS; i++)
    {
        hthread_attr_destroy( &attr[i] );
    }
    printf ("-- Complete --\n");

    // Return from main
    return 0;
}
Exemple #12
0
int main (void) {


   XCache_EnableICache(0x80000001);
   XCache_EnableDCache(0x80000001);

   /* Initialize RS232 - Set baudrate and number of stop bits */
   XUartNs550_SetBaud(XPAR_RS232_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, 9600);
   XUartNs550_mSetLineControlReg(XPAR_RS232_BASEADDR, XUN_LCR_8_DATA_BITS);
   print("-- Entering main() --\r\n");

   /* 
    * MemoryTest routine will not be run for the memory at 
    * 0xffff0000 (xps_bram_if_cntlr_1)
    * because it is being used to hold a part of this application program
    */


   /* 
    * MemoryTest routine will not be run for the memory at 
    * 0x86000000 (FLASH_8Mx16)
    * because it is a read-only memory
    */


   /* Testing Memory (DDR2_SDRAM_16Mx32)*/
   {
      XStatus status;

      print("Starting MemoryTest for DDR2_SDRAM_16Mx32:\r\n");
      print("  Running 32-bit test...");
      status = XUtil_MemoryTest32((Xuint32*)XPAR_DDR2_SDRAM_16MX32_MEM_BASEADDR, 1024, 0xAAAA5555, XUT_ALLMEMTESTS);
      if (status == XST_SUCCESS) {
         print("PASSED!\r\n");
      }
      else {
         print("FAILED!\r\n");
      }
      print("  Running 16-bit test...");
      status = XUtil_MemoryTest16((Xuint16*)XPAR_DDR2_SDRAM_16MX32_MEM_BASEADDR, 2048, 0xAA55, XUT_ALLMEMTESTS);
      if (status == XST_SUCCESS) {
         print("PASSED!\r\n");
      }
      else {
         print("FAILED!\r\n");
      }
      print("  Running 8-bit test...");
      status = XUtil_MemoryTest8((Xuint8*)XPAR_DDR2_SDRAM_16MX32_MEM_BASEADDR, 4096, 0xA5, XUT_ALLMEMTESTS);
      if (status == XST_SUCCESS) {
         print("PASSED!\r\n");
      }
      else {
         print("FAILED!\r\n");
      }
   }

   print("-- Exiting main() --\r\n");
   XCache_DisableDCache();
   XCache_DisableICache();
   return 0;
}
Exemple #13
0
int main( int argc, char *argv[] )
{

    unsigned int i, start_count = 0, done_count = 0, j;
    timing_t t_start = 0, t_stop = 0, t_gen = 0, t_sort = 0, t_merge =
                                       0, t_check = 0, t_tmp;

    printf( "-------------------------------------------------------\n"
            "ReconOS hardware multithreading case study (sort)\n"
            "(c) Computer Engineering Group, University of Paderborn\n\n"
            "eCos, single-threaded hardware version (" __FILE__ ")\n"
            "Compiled on " __DATE__ ", " __TIME__ ".\n"
            "-------------------------------------------------------\n\n" );

#ifdef USE_CACHE
    printf( "enabling data cache for external ram\n" );
    XCache_EnableDCache( 0x80000000 );
#else
    printf( "data cache disabled\n" );
    XCache_DisableDCache(  );
#endif

    data = buf_a;

    //----------------------------------
    //-- GENERATE DATA
    //----------------------------------
    printf( "Generating data..." );
    t_start = gettime(  );
    generate_data( data, SIZE );
    t_stop = gettime(  );
    t_gen = calc_timediff_ms( t_start, t_stop );
    printf( "done\n" );

#ifdef USE_CACHE
    // flush cache contents - the hardware can only read from main memory
    // TODO: storing could be more efficient
    printf( "Flushing cache..." );
    XCache_EnableDCache( 0x80000000 );
    printf( "done\n" );
#endif

    //----------------------------------
    //-- SORT DATA
    //----------------------------------
    // create mail boxes for 'start' and 'complete' messages
    cyg_mbox_create( &mb_start_handle, &mb_start );
    cyg_mbox_create( &mb_done_handle, &mb_done );
    // create sorting thread
    reconos_hwthread_create( 16,                                               // priority
                             0,                                                // entry data (not needed)
                             "MT_HW_SORT",                                     // thread name
                             hwthread_sorter_stack,                            // stack
                             STACK_SIZE,                                       // stack size
                             &hwthread_sorter_handle,                          // thread handle
                             &hwthread_sorter,                                 // thread object
                             (void*)UPBHWR_OSIF_0_BASEADDR,
                             XPAR_OPB_INTC_0_OSIF_0_INTERRUPT_INTR+1,
                             //                         ( void * ) XPAR_PLB_RECONOS_SLOT_0_BASEADDR,      // base address
                             //                         XPAR_OPB_INTC_0_PLB_RECONOS_SLOT_0_INTERRUPT_INTR + 1,     // interrupt
                             hwthread_sorter_resources,                        // resource array
                             2,                                                 // number of resources
                             0xFFFFFFFF, 0xFFFFFFFF
                           );
    cyg_thread_resume( hwthread_sorter_handle );

    printf( "Sorting data..." );
    i = 0;
    while ( done_count < SIZE / N ) {
        t_start = gettime(  );
        // if we have something to distribute,
        // put as many as possile into the start mailbox
        while ( start_count < SIZE / N ) {
            if ( cyg_mbox_tryput( mb_start_handle, ( void * ) &data[i] ) ==
                    true ) {
                start_count++;
                i += N;
            } else {                                                           // mailbox full
                break;
            }
        }
        t_stop = gettime(  );
        t_sort += calc_timediff_ms( t_start, t_stop );
        // see whether anybody's done
        t_start = gettime(  );
        if ( ( t_tmp = ( timing_t ) cyg_mbox_get( mb_done_handle ) ) != 0 ) {
            done_count++;
        } else {
            printf( "cyg_mbox_get returned NULL!\n" );
        }
        t_stop = gettime(  );
        t_sort += calc_timediff_ms( t_start, t_stop );
    }
    printf( "done\n" );


#ifdef USE_CACHE
    // flush cache contents
    // TODO: invalidating would suffice
    printf( "Flushing cache..." );
    XCache_EnableDCache( 0x80000000 );
    printf( "done\n" );
#endif


    //----------------------------------
    //-- MERGE DATA
    //----------------------------------
    printf( "Merging data..." );
    t_start = gettime(  );
    data = recursive_merge( data, buf_b, SIZE, N, simple_merge );
    t_stop = gettime(  );
    t_merge = calc_timediff_ms( t_start, t_stop );
    printf( "done\n" );

    //----------------------------------
    //-- CHECK DATA
    //----------------------------------
    printf( "Checking sorted data..." );
    t_start = gettime(  );
    if ( check_data( data, SIZE ) != 0 )
        printf( "CHECK FAILED!\n" );
    else
        printf( "check successful.\n" );
    t_stop = gettime(  );
    t_check = calc_timediff_ms( t_start, t_stop );

    printf( "\nRunning times (size: %d words):\n"
            "\tGenerate data: %d ms\n"
            "\tSort data    : %d ms\n"
            "\tMerge data   : %d ms\n"
            "\tCheck data   : %d ms\n"
            "\nTotal computation time (sort & merge): %d ms\n",
            SIZE, t_gen, t_sort, t_merge, t_check, t_sort + t_merge );


    return 0;

}
int run_tests()
{
    if (NUM_THREADS > NUM_CPUS){
        printf("CANNOT USE MORE THAN (%d) HETEROGENEOUS THREADS!!!!\r\n", NUM_CPUS);
        return (-1);
    }
  
    // Timer variables
    xps_timer_t timer;
    int time_create, time_start, time_stop;

    // Thread attribute structures
    Huint           sta[NUM_THREADS];
    void*           retval[NUM_THREADS];
    hthread_t       tid[NUM_THREADS];
    hthread_attr_t  attr[NUM_THREADS];
    targ_t thread_arg[NUM_THREADS];

    // Setup Cache
    XCache_DisableDCache();
    XCache_EnableICache(0xc0000801);

    // Create timer
    xps_timer_create(&timer, (int*)0x20400000);

    // Start timer
    xps_timer_start(&timer);

// *************************************************************************************    
    extern unsigned char intermediate[];

    extern unsigned int distance_handle_offset;
    unsigned int distance_handle = (distance_handle_offset) + (unsigned int)(&intermediate);
    printf("Code start address = 0x%08x\n", (unsigned int)&intermediate);

// *************************************************************************************    
    int vals_x0[ARR_LENGTH];
    int vals_x1[ARR_LENGTH];

    int vals_y0[ARR_LENGTH];
    int vals_y1[ARR_LENGTH];
    int vals_ds[ARR_LENGTH];

    int j = 0;

    for (j = 0; j < NUM_THREADS; j++)
    {
        // Initialize the attributes for the threads
        hthread_attr_init( &attr[j] );
        hthread_attr_sethardware( &attr[j], (void*)base_array[j] );
    }

    for (j = 0; j < ARR_LENGTH; j++)
    {
        vals_x0[j] = ARR_LENGTH - j;
        vals_y0[j] = ARR_LENGTH - j;

        vals_x1[j] = ARR_LENGTH - j + 1;
        vals_y1[j] = ARR_LENGTH - j;
    }


#ifdef MY_DEBUG
#endif

    int num_ops = 0;
    for( num_ops = 0; num_ops < 2; num_ops = num_ops + 1)
    { 

        printf("******* Round %d ********\n",num_ops);
#ifdef USE_MB_THREAD
        printf("**** MB-based Threads ****\n");
#else
        printf("**** PPC-based Threads ****\n");
#endif

        for (j = 0; j < ARR_LENGTH; j++)
        {
            vals_x0[j]  = ARR_LENGTH - j;
        }

        // Initialize thread arguments
        int num_items = ARR_LENGTH/NUM_THREADS;
        int extra_items = ARR_LENGTH - (num_items*NUM_THREADS);
        for ( j= 0; j < NUM_THREADS; j++)
        {
            thread_arg[j].x0s = &vals_x0[j*(num_items)];
            thread_arg[j].y0s = &vals_y0[j*(num_items)];
            thread_arg[j].x1s = &vals_x1[j*(num_items)];
            thread_arg[j].y1s = &vals_y1[j*(num_items)];
            thread_arg[j].distances = &vals_ds[j*(num_items)];
            thread_arg[j].length = num_items;
        }
        // Add in extra items for the last thread if needed
        thread_arg[j-1].length += extra_items;

        time_create = xps_timer_read_counter(&timer);
        // Create threads
        for (j = 0; j < NUM_THREADS; j++)
        {
            // Create the distance thread
#ifdef USE_MB_THREAD
            // Create MB Thread
            sta[j] = hthread_create( &tid[j], &attr[j], (void*)distance_handle, (void*)(&thread_arg[j]) );
            //printf( "Started MB Thread (TID = %d) \n", tid[j]);
#else
            // Create SW Thread
            sta[j] = hthread_create( &tid[j], NULL, distance_thread, (void*)(&thread_arg[j]) );
            //printf( "Started SW Thread (TID = %d) \n", tid[j]);
#endif
        }


        // Allow created threads to begin running and start timer
        time_start = xps_timer_read_counter(&timer);
        // Join on all threads
        for (j = 0; j < NUM_THREADS; j++)
        {
            hthread_join( tid[j], &retval[j] );
        }

        // Grab stop time
        time_stop = xps_timer_read_counter(&timer);

        // Print out status
        for (j = 0; j < NUM_THREADS; j++)
        {
            printf("TID[%d] = 0x%08x, status = 0x%08x, retval = 0x%08x\n",j,tid[j],sta[j],(unsigned int)retval[j]);
        }

        printf("*********************************\n");
        printf("Create time  = %u\n",time_create);
        printf("Start time   = %u\n",time_start);
        printf("Stop time    = %u\n",time_stop);
        printf("*********************************\n");
        printf("Creation time (|Start - Create|) = %u\n",time_start - time_create);
        printf("Elapsed time  (|Stop - Start|)   = %u\n",time_stop - time_start);
        printf("Total time   (|Create - Stop|)   = %u\n",time_stop - time_create);


    }

#ifdef MY_DEBUG
    for (j = 0; j < ARR_LENGTH; j++)
    {
        printf("D(%d) = %d\n",j,vals_ds[j]);
    }
#endif

    // Clean up the attribute structures
    for (j = 0; j < NUM_THREADS; j++)
    {
        hthread_attr_destroy( &attr[j] );
    }

    printf ("-- Complete --\n");

    // Return from main
    return 0;
}
/******************************************************************************
* Name:        main
* Description: Program entry point
* 
* Returns:     int   - returns 0 if no errors
******************************************************************************/
int main() {

   /* declare a network interface and network addresses */
   struct netif *netif, server_netif;  
   struct ip_addr ipaddr, netmask, gw;

   /* specify a unique MAC address for the board */
   #ifdef XPAR_CPU_PPC440_CORE_CLOCK_FREQ_HZ    /* set MAC on ML507 board */
   unsigned char mac_ethernet_address[] = {0x00, 0x0a, 0x35, 0x01, 0xC9, 0x76};
   #else                                        /* set MAC on ML410 board */
   unsigned char mac_ethernet_address[] = {0x00, 0x0a, 0x35, 0x01, 0x9A, 0xFE};
   #endif

   /* set the network interface pointer */
   netif = &server_netif;

   /* enable caches */
   XCache_EnableICache( INSTR_CACHE );
   XCache_EnableDCache( DATA_CACHE );

   /* setup interrupts */
   setup_interrupts();

   /* initliaze network addresses to be used */
   IP4_ADDR( &ipaddr,  192, 168,  1, 15 );
   IP4_ADDR( &netmask, 255, 255, 255, 0 );
   IP4_ADDR( &gw,      192, 168,  1,  1 );

   /* print the application header and IP settings */
   print_app_header();
   print_ip_settings(&ipaddr, &netmask, &gw);

   /* initialize lwip */
   lwip_init();

   /* add network interface to the netif_list, and set it as default */
   if( !xemac_add( netif, &ipaddr, &netmask, &gw,
                   mac_ethernet_address, EMAC_BASEADDR ) ) {
      xil_printf( "Error adding N/W interface\n\r" );
      return -1;
   }
   netif_set_default( netif );

   /* now enable interrupts */
   enable_interrupts();

   /* specify that the network if is up */
   netif_set_up( netif );

   /* start the application */
   start_application();
   
   /* print debug header if debug mode set */
   #ifdef QMFIR_DEBUG
   debug_menu();
	while( 1) {
		qmfir_debug();
	}
   #endif   

   /* receive and process packets */
   while( 1 ) {
      xemacif_input( netif );
   }

   /* disable caches */
   XCache_DisableDCache();
   XCache_DisableICache();

   return 0;

} /* main */
Exemple #16
0
int main( int argc, char *argv[] )
{
	int i;
	//int s, msg, retval;
	volatile int * src = (volatile int*)(((int)mem/16 + 1)*16 + 4); // align to 8 + 4 bytes
	volatile int * dst = src + MEMSIZE/4;
	
	XCache_DisableDCache();
	
	args[0] = (int)src;
	args[1] = (int)dst;
	args[2] = (int)MEMSIZE;
	
	printf("begin memcopy_test_posix\n");
	/*
	printf("args = 0x%08X\n",(unsigned int)args);
	
	for(i = 0; i < 3; i++){
		printf("args[%d] = 0x%08X\n",i,args[i]);
	}
	*/
	for(i = 0; i < MEMSIZE/4; i++){
		src[i] = i + 1;
		dst[i] = 0;
	}
	/*
	// set message queue attributes to non-blocking, 10 messages with 4 bytes each
	mbox_attr.mq_flags = 0;
	mbox_attr.mq_maxmsg = 10000;
	mbox_attr.mq_msgsize = 4;
	mbox_attr.mq_curmsgs = 0;
	// create mailboxes
	mbox = mq_open("/mbox", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG, &mbox_attr);
	if (mbox == (mqd_t)-1) {
		perror("unable to create mbox");
	}
	*/
	// create hardware thread
	printf("creating hw thread... ");
	POSIX_HWT_CREATE(0,(unsigned int)args,thread_resources);
	printf("ok\n");

	cyg_thread_delay(100);

	/*
	retval = mq_receive(mbox, (char*)&msg, 4, NULL);
	printf("init_data: 0x%08X (retval %d)\n", msg, retval);

	i = 0; s = (unsigned int)src;
	while(1){
		retval = mq_receive(mbox, (char*)&msg, 4, NULL);
		if(msg == 0x0112358D) break; 

		switch(i){
			case 0: printf("SRC"); break;
			case 1: printf("DST"); break;
			case 2: printf("SIZE"); break;
		}

		printf(": 0x%08X (retval %d)", msg, retval);
		if(i == 0){
			int d = (unsigned int)msg - s;
			if(d == 4) printf(" SINGLE");
			else if(d == 128) printf(" *** BURST ***");
			else printf(" chunk size = %u bytes", d);
			s = msg;
		}
		printf("\n");

		i = (i + 1) % 3;
	}
	
	for(i = 0; i < MEMSIZE/4; i++){
		printf("dst[0x%08X] = %d\n", i, dst[i]);
	}
	*/
	for(i = 0; i < MEMSIZE/4; i++){
		if(src[i] != dst[i]){
			printf("memcopy failed.\n");
			printf("error: destination[%d] = %d, should be %d\n",i,dst[i],src[i]);
			return 1;
		}
	}
	
	printf("memcopy ok. (%d bytes copied correctly)\n",MEMSIZE);
	
	printf("memcopy_test_posix done.\n");
	
	return 0;
}
//int main( int argc, char *argv[] )
int run_tests()
{
    if (NUM_THREADS > NUM_CPUS){
        printf("CANNOT USE MORE THAN (%d) HETEROGENEOUS THREADS!!!!\r\n",NUM_CPUS);
        return (-1);
    }
    // Timer variables
    xps_timer_t timer;
    int time_create, time_start, time_stop;

    // Thread attribute structures
    Huint           sta[NUM_THREADS];
    void*           retval[NUM_THREADS];
    hthread_t       tid[NUM_THREADS];
    hthread_attr_t  attr[NUM_THREADS];
    targ_t thread_arg[NUM_THREADS];

    // Setup Cache
    XCache_DisableDCache();
    XCache_EnableICache(0xc0000801);

    // Create timer
    xps_timer_create(&timer, (int*)0x20400000);

    // Start timer
    xps_timer_start(&timer);

// *************************************************************************************    
    extern unsigned char intermediate[];

    extern unsigned int sort_handle_offset;
    unsigned int sort_handle = (sort_handle_offset) + (unsigned int)(&intermediate);

// *************************************************************************************    
    float local_data[ARR_LENGTH];

    int j = 0;
    printf("Code start address = 0x%08x\n", (unsigned int)&intermediate);

    for (j = 0; j < NUM_THREADS; j++)
    {
        // Initialize the attributes for the threads
        hthread_attr_init( &attr[j] );
        hthread_attr_sethardware( &attr[j], (void*)base_array[j] );
    }

    for (j = 0; j < ARR_LENGTH; j++)
    {
        local_data[j] = (ARR_LENGTH - j)*1.00;
    }


#ifdef MY_DEBUG
    show_array(&local_data[0], ARR_LENGTH);
#endif
    int num_ops = 0;
    for( num_ops = 0; num_ops < 2; num_ops = num_ops + 1)
    { 

        printf("******* Round %d ********\n",num_ops);
#ifdef USE_MB_THREAD
        printf("**** MB-based Threads ****\n");
#else
        printf("**** PPC-based Threads ****\n");
#endif

        for (j = 0; j < ARR_LENGTH; j++)
        {
            local_data[j]  = ARR_LENGTH - j;
        }


        // Initialize thread arguments
        for ( j= 0; j < NUM_THREADS; j++)
        {
            thread_arg[j].data = &local_data[j*(ARR_LENGTH/NUM_THREADS)];
            thread_arg[j].length = ARR_LENGTH/NUM_THREADS;
        }

        time_create = xps_timer_read_counter(&timer);
        // Create threads
        for (j = 0; j < NUM_THREADS; j++)
        {
            // Create the sort thread
#ifdef USE_MB_THREAD
            // Create MB Thread
            sta[j] = hthread_create( &tid[j], &attr[j], (void*)sort_handle, (void*)(&thread_arg[j]) );
            //printf( "Started MB Thread (TID = %d) \n", tid[j]);
#else
            // Create SW Thread
            sta[j] = hthread_create( &tid[j], NULL, bubblesort_thread, (void*)(&thread_arg[j]) );
            //printf( "Started SW Thread (TID = %d) \n", tid[j]);
#endif
        }


        // Allow created threads to begin running and start timer
        time_start = xps_timer_read_counter(&timer);

        // Join on all threads
        for (j = 0; j < NUM_THREADS; j++)
        {
            hthread_join( tid[j], &retval[j] );
        }

        // Grab stop time
        time_stop = xps_timer_read_counter(&timer);

        // Print out status
        for (j = 0; j < NUM_THREADS; j++)
        {
            printf("TID[%d] = 0x%08x, status = 0x%08x, retval = 0x%08x\n",j,tid[j],sta[j],(unsigned int)retval[j]);
        }

        printf("*********************************\n");
        printf("Create time  = %u\n",time_create);
        printf("Start time   = %u\n",time_start);
        printf("Stop time    = %u\n",time_stop);
        printf("*********************************\n");
        printf("Creation time (|Start - Create|) = %u\n",time_start - time_create);
        printf("Elapsed time  (|Stop - Start|)   = %u\n",time_stop - time_start);
        printf("Total time   (|Create - Stop|)   = %u\n",time_stop - time_create);


    }

#ifdef MY_DEBUG
    show_array(&local_data[0], ARR_LENGTH);
    check_array(&local_data[0], ARR_LENGTH);    // Note there will be errors as the data set is not merged
#endif

    // Clean up the attribute structures
    for (j = 0; j < NUM_THREADS; j++)
    {
        hthread_attr_destroy( &attr[j] );
    }

    printf ("-- Complete --\n");

    // Return from main
    return 0;
}