void cpuidprint(void) { int t, v; print("PVR: "); t = getpvr()>>16; switch(t){ case 0x01: print("MPC601"); break; case 0x03: print("MPC603"); break; case 0x04: print("MPC604"); break; case 0x06: print("MPC603e"); break; case 0x07: print("MPC603e-v7"); break; case 0x50: print("MPC8xx"); break; default: print("PowerPC version #%x", t); break; } print(", revision #%lux\n", getpvr()&0xffff); print("IMMR: "); v = getimmr() & 0xFFFF; switch(v>>8){ case 0x00: print("MPC860/821"); break; case 0x20: print("MPC823"); break; case 0x21: print("MPC823A"); break; default: print("Type #%lux", v>>8); break; } print(", mask #%lux\n", v&0xFF); print("plprcr=%8.8lux sccr=%8.8lux\n", m->iomem->plprcr, m->iomem->sccr); print("%lud MHz system\n", m->cpuhz/MHz); print("\n"); }
void hthread_mutex_unlock(int lock_number) { volatile int * cmd; int status; // Form proc_interface_t from PVR register proc_interface_t iface; int hwti_base; getpvr(1,hwti_base); initialize_interface(&iface, (int*)hwti_base); cmd = (int*)mutex_cmd( HT_MUTEX_UNLOCK, *(iface.tid_reg), lock_number ); status = *cmd; }
void machinit(void) { int n; n = m->machno; memset(m, 0, sizeof(Mach)); m->machno = n; m->mmask = 1<<m->machno; m->iomem = KADDR(getimmr() & ~0xFFFF); m->cputype = getpvr()>>16; m->delayloop = 20000; /* initial estimate only; set by clockinit */ m->speed = 50; /* initial estimate only; set by archinit */ }
void machninit(int machno) { if (machno >= MAXMACH) panic("machno %d >= MAXMACH %d", machno, MAXMACH); conf.nmach++; m = MACHP(machno); memset(m, 0, sizeof(Mach)); m->machno = machno; m->cputype = getpvr()>>16; /* OWN[0:11] and PCF[12:15] fields */ m->delayloop = 20000; /* initial estimate only; set by clockinit */ m->perf.period = 1; /* other values set by archreset */ }
void delay() { int x; int y = 10 + x; int z; getpvr(1,z); //for (x = 0; x< (1000000); x++) for (x = 0; x < z; x++) { y+=x+z; } }
int hthread_self() { int tid; // Retrieve HWTI pointer proc_interface_t iface; int hwti_base; // Form proc_interface_t from PVR register getpvr(1,hwti_base); initialize_interface(&iface, (int*)hwti_base); // Extract and return TID return *(iface.tid_reg); }
Hint crc (void * list_ptr, Huint size, Huint * done) { // done variable not used for slave accelerator calls Hint result = SUCCESS; // Get VHWTI Huint vhwti_base = 0; // Get VHWTI from PVRs getpvr(1,&vhwti_base); // Increment SW counter Huint sw_counter = _hwti_get_accelerator_sw_counter( vhwti_base ); _hwti_set_accelerator_sw_counter( vhwti_base, ++sw_counter); // if the size is more than 4k words, // grab the amount of iterations you // need to perform. Huint iterations = size / BRAM_SIZE; // If there is a remainder in this // division, round up. if ((size % BRAM_SIZE) != 0) { iterations++; } Huint i = 0; Huint new_size = 0; Huint * new_list_ptr = 0; for (i = 0; i < iterations; i++) { // Calculate the size for this iteration new_size = (size < (BRAM_SIZE*(i+1))) ? size-(BRAM_SIZE*i) : BRAM_SIZE; // Calculate the starting pointer for this iteration. Typcasting // may be repetitive here. new_list_ptr = (Huint *) ((Huint *)list_ptr + BRAM_SIZE*i); // Run crc in software result = (sw_crc((void *) new_list_ptr, new_size)); if (result != SUCCESS) break; } /* end of iterations loop */ return result; }
void * test_PR_thread(void * arg) { Hint success = 0, i, trials = (int) arg; #ifdef PR unsigned char cpuid; getpvr(0,cpuid); for (i = 0; i < trials; i++) { success += perform_PR(cpuid, CRC); success += perform_PR(cpuid, BUBBLESORT); success += perform_PR(cpuid, VECTORADD); success += perform_PR(cpuid, VECTORMUL); success += perform_PR(cpuid, MATRIXMUL); } #endif return (void *) success; }
// Main event loop int main() { proc_interface_t hwti; // Get HWTI base address from user PVR register int hwti_base; getpvr(1,hwti_base); // Enable instruction cache (reduce PLB load) microblaze_init_icache_range(0, 8192); microblaze_enable_icache(); while(1) { // Setup interface // * Perform this upon each iteration, just in case the memory // map for the MB-HWTI is corrupted. initialize_interface(&hwti,(int*)(hwti_base)); // Wait to be "reset" // -- NOTE: Ignore reset as it has no meaning to the MB-HWTI // and it seems causes a race, as the controlling processor // sends a reset, immediately followed by a "go" command. Therefore // the "reset" command can be missed. //wait_for_reset_command(&hwti); // Wait to be "started" wait_for_go_command(&hwti); //xil_printf("Thread started (fcn @ 0x%08x), arg = 0x%08x!!!\r\n",*(hwti.fcn_reg), *(hwti.arg_reg)); // Setup r20 for thread (only needed for PIC code, i.e. print-related functions) mtgpr(r20, *(hwti.fcn_reg)); // Boostrap thread // * Pull out thread argument, and thread start function _bootstrap_thread(&hwti, *(hwti.fcn_reg), *(hwti.arg_reg)); //_bootstrap_thread(&hwti, factorial_thread, *(hwti.arg_reg)); // Use this when hard-coding functionality } return 0; }
int main() { proc_interface_t hwti; // Get HWTI base address from user PVR register int hwti_base; getpvr(1,hwti_base); // Disable instruction and data cache microblaze_invalidate_icache(); microblaze_disable_icache(); microblaze_invalidate_dcache(); microblaze_disable_dcache(); // Nano-kernel loop... while(1) { // Setup interface // * Perform this upon each iteration, just in case the memory // map for the MB-HWTI is corrupted. initialize_interface(&hwti,(int*)(hwti_base)); #if 0 // Commented out as this is not necessary and it creates the opportunity for a race between reset and start commands // Wait to be "reset" // -- NOTE: Ignore reset as it has no meaning to the MB-HWTI // and it seems causes a race, as the controlling processor // sends a reset, immediately followed by a "go" command. Therefore // the "reset" command can be missed. wait_for_reset_command(&hwti); #endif // Wait to be "started" wait_for_go_command(&hwti); //xil_printf("Thread started (fcn @ 0x%08x), arg = 0x%08x!!!\r\n",*(hwti.fcn_reg), *(hwti.arg_reg)); // Setup r20 for thread, this can be used to enforce -fPIC (Position-independent code) for the MB // (r20 is used as part of the GOT, to make things PC-relative) mtgpr(r20, *(hwti.fcn_reg)); // Boostrap thread (wraps up thread execution with a thread exit) // * Pull out thread argument, and thread start function _bootstrap_thread(&hwti, *(hwti.fcn_reg), *(hwti.arg_reg)); } return 0; }
void machinit(void) { memset(m, 0, sizeof(Mach)); m->cputype = getpvr()>>16; /* * For polled uart output at boot, need * a default delay constant. 100000 should * be enough for a while. Cpuidentify will * calculate the real value later. */ m->loopconst = 100000; /* turn on caches */ puthid0(gethid0() | BIT(16) | BIT(17)); active.machs = 1; active.exiting = 0; }
Hint poly_crc (void * list_ptr, Huint size) { Hint result = SUCCESS; // Use Accelerator? Hbool use_accelerator = poly_init(CRC, size); // Start transferring data to BRAM if(transfer_dma( (void *) list_ptr, (void *) ACC_BRAMC, size *4)) return FAILURE; if (use_accelerator) { int e = 0; putfslx( size, 0, FSL_DEFAULT);//send end address putfslx( 0, 0, FSL_DEFAULT); //send start address getfslx(e, 0, FSL_DEFAULT); if (e != 1) return FAILURE; } else { Huint vhwti_base = 0; // Get VHWTI from PVRs getpvr(1,vhwti_base); hthread_time_t start = hthread_time_get(); // Run crc in software result = (sw_crc((void *) ACC_BRAMC, size)); hthread_time_t stop = hthread_time_get(); hthread_time_t diff; hthread_time_diff(diff, stop,start); volatile hthread_time_t * ptr = (hthread_time_t *) (vhwti_base + 0x100); *ptr += diff; } // Start transferring data from BRAM if(transfer_dma( (void *) ACC_BRAMC, (void *) list_ptr, size *4)) return FAILURE; return result; }
void hthread_mutex_lock( int lock_number) { volatile int * cmd; int status; proc_interface_t iface; int hwti_base; // Form proc_interface_t from PVR register getpvr(1,hwti_base); initialize_interface(&iface, (int*)hwti_base); cmd = (int*)mutex_cmd( HT_MUTEX_LOCK, *(iface.tid_reg), lock_number ); status = *cmd; // Check to see if lock was successful if( status == HT_MUTEX_BLOCK ) { // Block until go command comes in wait_for_go_command(&iface); } // Got the lock! return; }
// -------------------------------------------------------------- // // Initialization routine for all polymorphic functions // // -------------------------------------------------------------- // Hbool poly_init(Hint acc, Huint size) { // Get VHWTI Huint vhwti_base = 0; // Get VHWTI from PVRs getpvr(1,vhwti_base); // Use Accelerator? Hbool use_accelerator = useHW(acc,size); if (use_accelerator) { // Increment HW counter Huint hw_counter = _hwti_get_accelerator_hw_counter( vhwti_base ); _hwti_set_accelerator_hw_counter( vhwti_base, ++hw_counter); } else { // Increment SW counter Huint sw_counter = _hwti_get_accelerator_sw_counter( vhwti_base ); _hwti_set_accelerator_sw_counter( vhwti_base, ++sw_counter); } return use_accelerator; }
/* Definitions */ int microblaze_get_pvr (pvr_t *pvr) { if (!pvr) return -1; bzero (pvr, sizeof (pvr_t)); #ifdef MICROBLAZE_PVR_NONE return -1; #else getpvr (0, pvr->pvr[0]); #endif /* MICROBLAZE_PVR_NONE */ #ifdef MICROBLAZE_PVR_FULL getpvr (1, pvr->pvr[1]); getpvr (2, pvr->pvr[2]); getpvr (3, pvr->pvr[3]); getpvr (4, pvr->pvr[4]); getpvr (5, pvr->pvr[5]); getpvr (6, pvr->pvr[6]); getpvr (7, pvr->pvr[7]); getpvr (8, pvr->pvr[8]); getpvr (9, pvr->pvr[9]); getpvr (10, pvr->pvr[10]); getpvr (11, pvr->pvr[11]); /* getpvr (12, pvr->pvr[12]); */ /* getpvr (13, pvr->pvr[13]); */ /* getpvr (14, pvr->pvr[14]); */ /* getpvr (15, pvr->pvr[15]); */ #endif /* MICROBLAZE_PVR_FULL */ return 0; }
// -------------------------------------------------------------- // // Determine if we use HW, PR if necessary // // -------------------------------------------------------------- // Hbool useHW(Huint accelerator_type, Huint size) { // Grab the VHWTI base Huint vhwti_base = 0; getpvr(1,vhwti_base); // Get currently loaded accelerator Huint current_accelerator = _hwti_get_last_accelerator(vhwti_base); // Determine whether this slave has PR Hbool has_PR = (Huint) _hwti_get_PR_flag(vhwti_base); // Immediately return 0 if slave has no PR, and has no // access to the specified "accelerator_type" if (has_PR != PR_FLAG) { if(current_accelerator != accelerator_type) return 0; } // Update the first used accelerator (slaves init this to NO_ACC) if (_hwti_get_first_accelerator(vhwti_base) == NO_ACC) _hwti_set_first_accelerator(vhwti_base, accelerator_type); // if the loaded accelerator matches the specified accelerator, return 1 // Hardware is always faster given the accelerators we currently have if (current_accelerator == accelerator_type) { return 1; } #ifdef PR // Does this processor have PR capabilities? if (has_PR) { // Get tuning table pointer. tuning_table_t (*tuning_table)[NUM_ACCELERATORS][(BRAM_SIZE/BRAM_GRANULARITY_SIZE)] = (void *) _hwti_get_tuning_table_ptr(vhwti_base); // Get Hardware execution time for this size unsigned char slave_num; getpvr(0, slave_num); float hw_time, sw_time; if (accelerator_type != MATRIXMUL) { hw_time = tuning_table[slave_num][accelerator_type][size/BRAM_GRANULARITY_SIZE].hw_time; sw_time = tuning_table[slave_num][accelerator_type][size/BRAM_GRANULARITY_SIZE].sw_time; } else { // Matrix Multiplication entries are insertted in a different way than others hw_time = tuning_table[slave_num][accelerator_type][size].hw_time; sw_time = tuning_table[slave_num][accelerator_type][size].sw_time; } // Calculate if PR is worth it by indexing appropriately // into the table and evaluating the software and hardware // execution times, taking into account PR overhead. if ((hw_time + PR_OVERHEAD + HW_SW_THRESHOLD) < sw_time) { // ----Begin loading the accelerator----// // If performing PR failed, fallback to software // execution. So return false. // Perform PR (which updates last used accelerator) if (perform_PR(slave_num, accelerator_type) != SUCCESS) { return 0; } // Increment PR counter Huint pr_counter = _hwti_get_accelerator_pr_counter( vhwti_base ); _hwti_set_accelerator_pr_counter( vhwti_base, ++pr_counter); // Return immediately indicating to use HW/accelerator return 1; } else return 0; } #endif // As a default, always return 0 // indicating to run in software. return 0; }
void cpuidprint(void) { print("cpu0: %s, rev 0x%lux, cpu hz %lld, bus hz %ld\n", cpuid(), getpvr()&0xffff, m->cpuhz, m->bushz); }
int main() { proc_interface_t hwti; // Get HWTI base address from user PVR register int hwti_base; unsigned char cpu_id; // only 8bits getpvr(1,hwti_base); // Disable instruction and data cache microblaze_invalidate_icache(); microblaze_enable_icache(); microblaze_invalidate_dcache(); microblaze_disable_dcache(); //Determine if uB is first on bus getpvr(0, cpu_id); // Timer pointers volatile unsigned long long * timer = (unsigned long long *) LOCAL_TIMER; volatile unsigned int * timer_reset = (unsigned int *) (LOCAL_TIMER + RESET_REG); // Reset timer *timer_reset = CMD_RESET; // Indicate to CoreTest.c running on host that this processor is running volatile unsigned int * check = (unsigned int *) EXTRA_BRAM; // assign cpus_per_bus offset check = (unsigned int *) ((unsigned int) check + ( ((unsigned int) cpu_id) * 0x100)); // write OKAY_VALUE to common memory (extra_bram) *check = OKAY_VALUE; // Nano-kernel loop... while(1) { // Setup interface // * Perform this upon each iteration, just in case the memory // map for the MB-HWTI is corrupted. initialize_interface(&hwti,(int*)(hwti_base)); #if 0 // Commented out as this is not necessary and it creates the opportunity for a race between reset and start commands // Wait to be "reset" // -- NOTE: Ignore reset as it has no meaning to the MB-HWTI // and it seems causes a race, as the controlling processor // sends a reset, immediately followed by a "go" command. Therefore // the "reset" command can be missed. wait_for_reset_command(&hwti); #endif // Wait to be "started" wait_for_go_command(&hwti); //xil_printf("Thread started (fcn @ 0x%08x), arg = 0x%08x!!!\r\n",*(hwti.fcn_reg), *(hwti.arg_reg)); // Setup r20 for thread, this can be used to enforce -fPIC (Position-independent code) for the MB // (r20 is used as part of the GOT, to make things PC-relative) mtgpr(r20, *(hwti.fcn_reg)); // Boostrap thread (wraps up thread execution with a thread exit) // * Pull out thread argument, and thread start function _bootstrap_thread(&hwti, *(hwti.fcn_reg), *(hwti.arg_reg)); } return 0; }