// Big function that handles the array preamble. We first read and // expand the preamble, then loop over all characters, then check // that it ends correctly. If main_fct is false, we are in a multicolumn. // In this case, the array preamble should specify only material // for one cell. We read the content C of the cell, and push back // the {UCV} list (where U and V the optional <u> and <v> parts. // braces are added because cells are assumed to be typeset in a group. void NewArray::run(Xid ID, bool main_fct) { id = ID; if(!main_fct) { Istring x = P->nT_next_arg(); id.add_attribute(the_names[np_cols], x); } preamble = P->mac_arg(); token_ns::expand_star(preamble); token_ns::expand_nct(preamble); if(main_fct) AI = &P->the_stack.new_array_info(id); u_list.clear(); v_list.clear(); ac_cell_no = 0; last_ch_class = chc_start; first_bar = true; bool seen = false; cur_h_pos = np_c_center; if(P->tracing_commands()) the_log << "array preamble parse: "; for(;;) { if(preamble.empty()) break; if(ac_next()) continue; test_pach(); if(P->tracing_commands()) the_log << dump_slot(); switch(ch_class) { case chc_cell: if(main_fct) ac_maybe_finish(); // finish previous else ac_maybe_finish_multi(seen); attribs.push_back(np_halign,cur_h_pos,false); // set attributes cur_h_pos = np_c_center; // add a default current_list.clear(); break; case chc_bar: if(ch_num==chn_c) { if(last_ch_class==chc_start) attribs.push_back(np_leftborder,np_true); else if(last_ch_class==chc_bar) {} else attribs.push_back(np_rightborder,np_true,false); } current_list.clear(); break; case chc_v: // got a <v>list, add it if(!have_token_list) v_list.push_front(current_token); else v_list.splice(v_list.begin(),current_list); break; case chc_u: // got a <u>list, add it. if(!have_token_list) u_list.push_front(current_token); else u_list.splice(u_list.begin(),current_list); break; case chc_start: // preamble empty break; case chc_inter: current_list.clear(); break; case chc_pre_bar: if(last_ch_class==chc_cell) break; else if(last_ch_class==chc_bar) break; else if(last_ch_class==chc_v) break; else if(last_ch_class==chc_u) P->parse_error("illegal ! or @"); break; case chc_pre_inter: if(last_ch_class==chc_u) P->parse_error("illegal ! or @"); break; case chc_pre_v: if(last_ch_class ==chc_cell) break; if(last_ch_class==chc_v) break; P->parse_error("unexpected less-than sign"); ch_class = chc_pre_bar; break; case chc_pre_u: case chc_pre_cell: if(main_fct) ac_maybe_finish(); else ac_maybe_finish_multi(seen); break; } last_ch_class = ch_class; } switch(last_ch_class) { case chc_cell: case chc_bar: case chc_v: case chc_u: case chc_start: case chc_inter: break; default: { static Buffer B; B.reset(); B << "Array preamble: argument missing for " << char_for_error; P->parse_error(B.c_str()); } } if(P->tracing_commands()) the_log << "\n"; if(main_fct) { ac_maybe_finish(); return; } else ac_maybe_finish_multi(seen); // Case of \multicolumn, id.add_attribute(attribs); attribs.reset(); TokenList cell = P->mac_arg(); cell.splice(cell.begin(),u_list); cell.splice(cell.end(),v_list); u_list.clear(); v_list.clear(); P->brace_me(cell); P->back_input(cell); }
//----------------------------------------- // eCos HW scheduling thread //----------------------------------------- void reconos_hw_scheduler(cyg_addrword_t data) { cyg_bool_t retval; rthread_attr_t *t_r; // thread to reconfigure rthread_attr_t *t_y; // yielding thread reconos_slot_t *s_f; // free slot reconos_bitstream_t *t_r_bit; // bitstream for t_r in s_f #ifdef UPBFUN_RECONOS_CHECK_HWTHREAD_SIGNATURE uint32 signature; // hardware thread signature volatile int z; // counter to delay DCR access #endif #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: created\n"); #endif // loop forever for (;;) { // wait for signal (reschedule request) retval = cyg_semaphore_wait( &reconos_hwsched_semaphore ); CYG_ASSERT(retval, "cyg_semaphore_wait returned false"); #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: wakeup\n"); #endif // lock scheduling mutex if (!cyg_mutex_lock(&reconos_hwsched_mutex)) { CYG_FAIL("mutex lock failed, aborting thread\n"); } else { #ifdef UPBDBG_RECONOS_DEBUG { int i; for (i = 0; i < NUM_OSIFS; i++) { dump_slot( &reconos_slots[i] ); } } #endif // find thread t_r that wants to run (FIXME: no priorities or // queuing!) t_r = reconos_hwthread_list; while ( t_r != NULL && ((t_r->flags & RTHREAD_ATTR_RECONFIGURE) == 0) ) { t_r = t_r->next; } if (t_r == NULL) { // no hw threads to reconfigure, nothing to do #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: no threads to reconfigure\n"); #endif // clear all yield requests! while (num_global_yield_requests) { pop_yield_request(); } } else { #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: found thread @ 0x%08X to reconfigure\n", (uint32)t_r); #endif CYG_ASSERT( t_r->flags & RTHREAD_ATTR_IS_DYNAMIC, "trying to load a static thread" ); // find free slot s_f s_f = find_free_slot( t_r ); if ( s_f == NULL ) { // no free slot // try to find thread that yields in a slot we have a // bitstream for #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: no free slots\n"); #endif t_y = reconos_hwthread_list; while ( t_y != NULL && ( ( (t_y->flags & RTHREAD_ATTR_YIELDS ) == 0) || ( get_bit_for_slot( t_r, t_y->slot ) == NULL ) ) ) { t_y = t_y->next; } if (t_y == NULL) { // no yielding thread #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: no yielding threads, sending yield requests to slots\n"); #endif // ask all slots to yield // FIXME: this will also ask slots that t_r possibly // doesn't have a bitstream for push_yield_request(); } else { // if found CYG_ASSERT( t_y->flags & RTHREAD_ATTR_IS_DYNAMIC, "trying to replace a static thread" ); CYG_ASSERT( t_y->slot, "trying to replace a not-resident thread" ); #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: found yielding thread @ 0x%08X in slot %d\n", (uint32)t_y, t_y->slot->num); #endif // use t_y's slot as s_f s_f = t_y->slot; // clear yield flag of t_y t_y->flags = t_y->flags & ~RTHREAD_ATTR_YIELDS; // remove t_y from s_f s_f->thread = NULL; t_y->slot = NULL; s_f->state = FREE; } } else { #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: found free slot %d\n", s_f->num); #endif } if ( s_f != NULL) { // if we found a free slot // one way or the other // get bitstream for t_r in s_f t_r_bit = get_bit_for_slot( t_r, s_f ); CYG_ASSERT( t_r_bit, "no bitstream" ); CYG_ASSERT( s_f->state == FREE || s_f->thread->flags & RTHREAD_ATTR_IS_DYNAMIC, "slot not free or present thread is static" ); #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: configuring thread @ 0x%08X into slot %d using bitstream '%s'\n", (uint32)t_r, s_f->num, t_r_bit->filename); #endif // configure t_r into s_f // NOTE: we don't need to synchronize this with the // slot's mutex, since the slot is yielding and will // not perform any hardware operations while the // scheduling mutex is locked // disable bus macros (just in case) osif_set_busmacro(s_f, OSIF_DATA_BUSMACRO_DISABLE); #ifdef UPBHWR_VIRTEX4_ICAP icap_load( t_r_bit->data, t_r_bit->size ); #endif #ifdef UPBFUN_RECONOS_ECAP_NET ecap_load( t_r_bit ); #endif #ifdef UPBFUN_RECONOS_CHECK_HWTHREAD_SIGNATURE // reset thread, enable busmacros, reset again (to // retrieve signature), read signature, and disable // busmacros osif_reset( s_f ); cyg_thread_delay(1); osif_set_busmacro(s_f, OSIF_DATA_BUSMACRO_ENABLE); // cyg_thread_delay(1); osif_reset( s_f ); cyg_thread_delay(1); osif_read_hwthread_signature(s_f, &signature); // cyg_thread_delay(1); // osif_set_busmacro(s_f, OSIF_DATA_BUSMACRO_DISABLE); // cyg_thread_delay(1); #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: read signature: 0x%08X, expected: 0x%08X.\n", signature, t_r->circuit->signature); #endif // check whether the signatures match CYG_ASSERT(signature == t_r->circuit->signature, "hwthread signatures don't match"); #endif // assign thread to slot and set slot state to READY s_f->thread = t_r; t_r->slot = s_f; s_f->state = READY; // clear t_r's RECONFIGURE bit t_r->flags = t_r->flags & ~RTHREAD_ATTR_RECONFIGURE; // wake any threads waiting for a scheduling change cyg_cond_broadcast( &reconos_hwsched_condvar ); // clear one yield request pop_yield_request(); } } #ifdef UPBDBG_RECONOS_DEBUG diag_printf("hw_sched: done\n"); #endif // unlock scheduling mutex cyg_mutex_unlock(&reconos_hwsched_mutex); } // if (mutex_lock) } // for (;;) }