void stdio_init( void ) { uartlite_config_t config1; uartlite_config_t config2; if( _get_procid() == 0 ) { // Setup the base address of the UART config1.base = UART1_BASEADDR; // Create the UART Lite device uartlite_create( &(_io_uart1), &config1 ); // Initialize the stdin and stdout flags stdin_flags = 0; stdout_flags = 0; } else { // Setup the base address of the UART config2.base = UART2_BASEADDR; // Create the UART Lite device uartlite_create( &(_io_uart2), &config2 ); // Initialize the stdin and stdout flags stdin_flags = 0; stdout_flags = 0; } }
void* simple_thread(void * arg) { struct simple_test * simple; // Extract thread argument simple = (struct simple_test *) arg; #ifdef PRINT int * pic_0_addr = (void*)0x41200000; int * pic_1_addr = (void*)0x41210000; printf( "\n..................................\n"); printf( "simple_thread: CPUID = %d\n", _get_procid()); printf( "simple_thread: PIC 0 = 0x%8.8x\n",*pic_0_addr); printf( "simple_thread: PIC 1 = 0x%8.8x\n",*pic_1_addr); printf( "simple_thread: Val = %d\n", simple->val ); #endif // Increment value simple->val = simple->val + 10; #ifdef YIELD hthread_yield(); #endif #ifdef SELF hthread_t self_test = hthread_self(); #ifdef PRINT printf("simple_thread: TID VERIFIED %d\n", self_test); #endif #endif return (void*)simple->val; }
int main (int argc, char *argv[]) { unsigned int start = 0; unsigned int stop = 0; hthread_t thread; struct simple_test simple; Huint i, j, ret; for(j = 0; j < ITERATIONS; j++) { #ifdef PRINT printf("\nStarting Simple Test...\n"); #endif simple.val = 110; // Xilinx OPB Timer locations as specified in the .mhs file volatile int *timer_control = (int*)0x73000000; volatile int *timer_value = (int*)0x73000008; // Enable timer and clear interrupt *timer_control = 0x00000510; // Start the timer start = *timer_value; for(i = 0; i < j+1; i++) { hthread_create(&thread, NULL, simple_thread, (void*)&simple); hthread_join(thread, (void*)&ret); #ifdef PRINT printf( "main: CPUID = %d\n",_get_procid()); printf( "main: Val = %d\n", simple.val ); printf( "..................................\n"); #endif } // Stop timer stop = *timer_value; printf("Exec. Time = %d Iteration = %d\n",(stop-start),j); #ifdef PRINT printf("Start Time = %u\n",start); printf("Stop Time = %u\n",stop); printf("Exec. Time = %d\n",(stop-start)); printf( "main: Val = %d\n", simple.val ); printf( "- done -\n\n" ); #endif } return 0; }
/** * \ingroup rpc * \internal * * This sends a message first created with split_call_begin. The archive * pointer is consumed. */ static void split_call_end(dc_dist_object_base* rmi, oarchive* oarc, dc_send* sender, procid_t target, unsigned char flags) { // header points to the location of the blob size argument size_t blobsize_offset = *reinterpret_cast<size_t*>(oarc->buf); (*reinterpret_cast<size_t*>(oarc->buf + blobsize_offset)) = oarc->off - blobsize_offset - sizeof(size_t); // write the packet header packet_hdr* hdr = reinterpret_cast<packet_hdr*>(oarc->buf); hdr->len = oarc->off - sizeof(packet_hdr); hdr->src = _get_procid(); hdr->packet_type_mask = flags; hdr->sequentialization_key = _get_sequentialization_key(); size_t len = hdr->len; write_thread_local_buffer(target, oarc->buf, oarc->off, flags & CONTROL_PACKET); if ((flags & CONTROL_PACKET) == 0) { rmi->inc_bytes_sent(target, len); } delete oarc; }
/** \internal * \brief The Hybrid Threads initialization function. * * This function is the Hybrid Threads initialization function. This function * must be called before any other HThread's functionality is used. */ void hthread_init( void ) { int ret, i; hthread_t main_thread; hthread_t idle_thread; hthread_attr_t attrs; Huint status; #ifdef HTHREADS_SMP int cpuid; if(_get_procid() == 0) { /* Default all stack values to NULL */ for( i = 0; i < MAX_THREADS; i++ ) threads[ i ].stack = NULL; /* Initialize the thread manager */ _init_thread_manager(); // Have to acknowledge the access interrupt generated because // spinlock and semaphore cores cause a failure // Hardcoded...FIXME intr_ack( 0x41200000, ACCESS_INTR_MASK ); intr_ack( 0x41210000, ACCESS_INTR_MASK ); // Must call this function again because we just reset the TM after // already reading CPUID = 0, therefore the next call to _init_cpuid() // will also return zero, giving two cpu's the id of zero _init_cpuid(); // Setup the attributes for the idle thread attrs.detached = Htrue; attrs.stack_size = HT_IDLE_STACK_SIZE; attrs.hardware = Hfalse; attrs.stack_addr = (void*)NULL; attrs.sched_param = 0x0000007F; // Worst possible priority // Create the idle thread _create_system_thread( &idle_thread, &attrs, _idle_thread, NULL ); TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "HThread Init: (IDLE ID(PPC_%d)=%u)\n", _get_procid(), idle_thread ); // Tell the hardware what the idle thread is _set_idle_thread( idle_thread, _get_procid() ); //hthread_spin_lock(&(_sysc_lock)); // Enable PPC specific interrupts //_arch_enable_intr(); // Initialize the Architecture Specific Code TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "Initializing Architecture...\n" ); //_init_arch_specific( idle_thread ); //_init_arch_specific(); // Need to acquire lock here because bootstrap releases lock while(!_get_syscall_lock()); _restore_context( 0 , idle_thread ); } else { // Setup the attributes for the main thread attrs.detached = Htrue; // The Main Thread is Detached attrs.stack_size = HT_MAIN_STACK_SIZE; // Stack Size for Main Thread attrs.hardware = Hfalse; // The Main Thread is not Hardware attrs.stack_addr = (void*)0xFFFFFFFF; // The Main Thread Already Has a Stack attrs.sched_param = HT_DEFAULT_PRI; // Middle of the Road Priority // Create the main thread _create_system_thread( &main_thread, &attrs, NULL, NULL ); TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "HThread Init: (MAIN ID(PPC_%d)=%u)\n", _get_procid(), main_thread ); // Prevent the system from attempting to deallocate the main stack threads[ main_thread ].stack = NULL; // Add the main thread onto the ready-to-run queue status = _add_thread( main_thread ); // Set the next thread to be the current thread. This should place // the main thread into the current thread register. status = _next_thread(); // The main thread is not a new thread threads[ main_thread ].newthread = Hfalse; // Setup the attributes for the idle thread attrs.detached = Htrue; attrs.stack_size = HT_IDLE_STACK_SIZE; attrs.hardware = Hfalse; attrs.stack_addr = (void*)NULL; attrs.sched_param = 0x0000007F; // Worst possible priority // Create the idle thread _create_system_thread( &idle_thread, &attrs, _idle_thread, NULL ); TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "HThread Init: (IDLE ID(PPC_%d)=%u)\n", _get_procid(), idle_thread ); // Tell the hardware what the idle thread is _set_idle_thread( idle_thread, _get_procid() ); // Enable PPC specific interrupts //_arch_enable_intr(); // Initialize the Architecture Specific Code TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "Initializing Architecture...\n" ); //_init_arch_specific( main_thread ); //_init_arch_specific(); // Enter into user mode //_arch_enter_user(); _enable_preemption(); } #else // Initialize all of the thread stacks to NULL TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "Initializing HThreads System...\n" ); for( i = 0; i < MAX_THREADS; i++ ) threads[ i ].stack = NULL; // Initialize the Thread Manager TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "Initializing Thread Manager...\n" ); _init_thread_manager(); // Setup the attributes for the main thread attrs.detached = Htrue; // Main thread is detached attrs.stack_size = HT_MAIN_STACK_SIZE; // Stack size for main thread attrs.hardware = Hfalse; // Main thread is not hardware attrs.stack_addr = (void*)0xFFFFFFFF; // Main thread has a stack attrs.sched_param = HT_DEFAULT_PRI; // Middle of the road priority // Create the main thread ret = _create_system_thread( &main_thread, &attrs, NULL, NULL ); TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "HThread Init: (MAIN ID=%u)\n", main_thread ); if( ret != SUCCESS ) { TRACE_PRINTF(TRACE_FATAL, TRACE_INIT, "HThread Init: create main thread failed\n" ); while(1); } // Initialize the Architecture Specific Code TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "Initializing Architecture...\n" ); //_init_arch_specific(); // Prevent the system from attempting to deallocate the main stack threads[ main_thread ].stack = NULL; // Add the main thread onto the ready-to-run queue status = _add_thread( main_thread ); // Set the next thread to be the current thread. This should place // the main thread into the current thread register. status = _next_thread(); // Setup the attributes for the idle thread attrs.detached = Htrue; attrs.stack_addr = (void*)NULL; attrs.stack_size = HT_IDLE_STACK_SIZE; // Create the idle thread ret = _create_system_thread( &idle_thread, &attrs, _idle_thread, NULL ); TRACE_PRINTF( TRACE_INFO, TRACE_INIT, "HThread Init: (IDLE ID=%u)\n", idle_thread ); if( ret != SUCCESS ) { TRACE_PRINTF(TRACE_FATAL, TRACE_INIT, "HThread Init: create idle thread failed\n" ); while(1); } // Tell the hardware what the idle thread is // FIXME - The CPUID is hardcoded, fix the manager/hardware.h file! _set_idle_thread( idle_thread , 0); // The main thread is not a new thread threads[ main_thread ].newthread = Hfalse; // Enter into user mode //_arch_enable_intr(); //_arch_enter_user(); #endif }
/////////////////////////////////////////////////////////////////////////////// // This function gets a command index with the hba_cmd_alloc function. Then it // registers a command in both the command list and the command table. It // updates the HBA_PXCI register and the hba_active_cmd in descheduling mode. // At the end the command slot is released. // return 0 if success, -1 if error /////////////////////////////////////////////////////////////////////////////// unsigned int _hba_access( unsigned int use_irq, unsigned int to_mem, unsigned int lba, unsigned long long buf_paddr, unsigned int count ) { unsigned int procid = _get_procid(); unsigned int x = procid >> (Y_WIDTH + P_WIDTH); unsigned int y = (procid >> P_WIDTH) & ((1<<Y_WIDTH) - 1); unsigned int p = procid & ((1<<P_WIDTH)-1); #if GIET_DEBUG_IOC if (_get_proctime() > GIET_DEBUG_IOC) _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] enters at cycle %d\n" " use_irq = %d / to_mem = %d / lba = %x / paddr = %l / count = %d\n", x , y , p , _get_proctime() , use_irq , to_mem , lba , buf_paddr, count ); #endif unsigned int cmd_id; // command index unsigned int pxci; // HBA_PXCI register value unsigned int pxis; // HBA_PXIS register value hba_cmd_desc_t* cmd_desc; // command descriptor pointer hba_cmd_table_t* cmd_table; // command table pointer // check buffer alignment if( buf_paddr & 0x3F ) { _printf("\n[HBA ERROR] in _hba_access() : buffer not 64 bytes aligned\n"); return -1; } // get one entry in Command List cmd_id = _hba_cmd_alloc(); // compute pointers on command descriptor and command table cmd_desc = &_hba_cmd_list[cmd_id]; cmd_table = &_hba_cmd_table[cmd_id]; // set buffer descriptor in command table cmd_table->buffer.dba = (unsigned int)(buf_paddr); cmd_table->buffer.dbau = (unsigned int)(buf_paddr >> 32); cmd_table->buffer.dbc = count * 512; // initialize command table header cmd_table->header.lba0 = (char)lba; cmd_table->header.lba1 = (char)(lba>>8); cmd_table->header.lba2 = (char)(lba>>16); cmd_table->header.lba3 = (char)(lba>>24); cmd_table->header.lba4 = 0; cmd_table->header.lba5 = 0; // initialise command descriptor cmd_desc->prdtl[0] = 1; cmd_desc->prdtl[1] = 0; if( to_mem ) cmd_desc->flag[0] = 0x00; else cmd_desc->flag[0] = 0x40; #if USE_IOB // software L2/L3 cache coherence // compute physical addresses unsigned long long cmd_desc_paddr; // command descriptor physical address unsigned long long cmd_table_paddr; // command table header physical address unsigned int flags; // unused if ( _get_mmu_mode() & 0x4 ) { cmd_desc_paddr = _v2p_translate( (unsigned int)cmd_desc , &flags ); cmd_table_paddr = _v2p_translate( (unsigned int)cmd_table , &flags ); } else { cmd_desc_paddr = (unsigned int)cmd_desc; cmd_table_paddr = (unsigned int)cmd_table; } // update external memory for command table _mmc_sync( cmd_table_paddr & (~0x3F) , sizeof(hba_cmd_table_t) ); // update external memory for command descriptor _mmc_sync( cmd_desc_paddr & (~0x3F) , sizeof(hba_cmd_desc_t) ); // inval or synchronize memory buffer if ( to_mem ) _mmc_inval( buf_paddr, count<<9 ); else _mmc_sync( buf_paddr, count<<9 ); #endif // end software L2/L3 cache coherence ///////////////////////////////////////////////////////////////////// // In synchronous mode, we poll the PXCI register until completion ///////////////////////////////////////////////////////////////////// if ( use_irq == 0 ) { // start HBA transfer _hba_set_register( HBA_PXCI, (1<<cmd_id) ); #if GIET_DEBUG_IOC if (_get_proctime() > GIET_DEBUG_IOC) _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] get slot %d in Cmd List " " at cycle %d / polling\n", x , y , p , cmd_id, _get_proctime() ); #endif // disable IRQs in PXIE register _hba_set_register( HBA_PXIE , 0 ); // poll PXCI[cmd_id] until command completed by HBA do { pxci = _hba_get_register( HBA_PXCI ); #if GIET_DEBUG_IOC if (_get_proctime() > GIET_DEBUG_IOC) _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] wait on HBA_PXCI / pxci = %x\n", x , y , p , pxci ); #endif } while( pxci & (1<<cmd_id) ); // get PXIS register pxis = _hba_get_register( HBA_PXIS ); // reset PXIS register _hba_set_register( HBA_PXIS , 0 ); } ///////////////////////////////////////////////////////////////// // in descheduling mode, we deschedule the task // and use an interrupt to reschedule the task. // We need a critical section, because we must set the NORUN bit // before to launch the transfer, and we don't want to be // descheduled between these two operations. ///////////////////////////////////////////////////////////////// else { #if GIET_DEBUG_IOC if (_get_proctime() > GIET_DEBUG_IOC) _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] get slot %d in Cmd List " "at cycle %d / descheduling\n", x , y , p , cmd_id, _get_proctime() ); #endif unsigned int save_sr; unsigned int ltid = _get_current_task_id(); // activates HBA interrupts _hba_set_register( HBA_PXIE , 0x00000001 ); // set _hba_gtid[cmd_id] _hba_gtid[cmd_id] = (procid<<16) + ltid; // enters critical section _it_disable( &save_sr ); // Set NORUN_MASK_IOC bit static_scheduler_t* psched = (static_scheduler_t*)_schedulers[x][y][p]; unsigned int* ptr = &psched->context[ltid][CTX_NORUN_ID]; _atomic_or( ptr , NORUN_MASK_IOC ); // start HBA transfer _hba_set_register( HBA_PXCI, (1<<cmd_id) ); // set _hba_active_cmd[cmd_id] _hba_active_cmd[cmd_id] = 1; // deschedule task _ctx_switch(); #if GIET_DEBUG_IOC if (_get_proctime() > GIET_DEBUG_IOC) _printf("\n[DEBUG HBA] _hba_access() : task %d on P[%d,%d,%d] resume at cycle %d\n", ltid , x , y , p , _get_proctime() ); #endif // restore SR _it_restore( &save_sr ); // get command status pxis = _hba_status; } // release the cmd index unsigned int release_success; release_success = _hba_cmd_release(cmd_id); #if GIET_DEBUG_IOC if (_get_proctime() > GIET_DEBUG_IOC) _printf("\n[DEBUG HBA] _hba_access() : P[%d,%d,%d] release slot %d in Cmd List " "and exit at cycle %d\n", x , y , p, cmd_id, _get_proctime() ); #endif if ( release_success != 0 ) return -1; else if ( pxis & 0x40000000 ) return pxis; else return 0; } // end _hba_access()