scheduler.cc

Go to the documentation of this file.
00001 #include <lestes/backend_v2/structs/func_data.g.hh>
00002 #include <lestes/backend_v2/intercode/pi.g.hh>
00003 #include <lestes/backend_v2/intercode/ge.g.hh>
00004 #include <lestes/backend_v2/workers/scheduler.g.hh>
00005 #include <lestes/backend_v2/workers/bb_finder.g.hh>
00006 #include <lestes/md/instructions/tm_instr_base.g.hh>
00007 #include <lestes/md/instructions/execution_info.g.hh>
00008 
00009 #include <lestes/backend_v2/debug/debug.hh>
00010 
00011 package(lestes);
00012 package(backend_v2);
00013 package(workers);
00014 
00015 using namespace ::lestes::backend_v2::debug;
00016 using namespace ::lestes::backend_v2::structs;
00017 using namespace ::lestes::backend_v2::intercode;
00018 using namespace ::lestes::md::instructions;
00019 using namespace ::lestes::msg;
00020 
00021 typedef set< srp<ge_pi> > ge_pi_set__type;
00022 typedef vector< srp<ge_pi> > ge_pi_vector__type;
00023 typedef list< srp<ge_pi> > ge_pi_list__type;
00024 typedef vector< srp<basic_block> > bb_vector__type;
00025 typedef map< srp<ge_pi>, srp<schedule_item> > ge2si__type;
00026 typedef set< srp<schedule_item> > si_set__type;
00027 typedef vector< srp<schedule_item> > si_vector__type;
00028 
00029 declare_logger(schedlog);
00030 initialize_logger( schedlog, "scheduler", backend_v2_logger );
00031 
00032 /*!
00033         \brief Schedules pseudoinstructions of a function body.
00034 */
00035 void scheduler::process() {
00036         schedlog << "process start\n" << eolog;
00037         
00038         ptr<ge_pi_list__type> body = ge_pi_list__type::create();
00039         
00040         current_schedule_pos = 0;
00041         
00042         ptr<bb_vector__type> bbs = data_get()->bbs_get();
00043         
00044         for(bb_vector__type::iterator it = bbs->begin(); it!=bbs->end(); ++it) {
00045                 ptr<basic_block> bb = *it;
00046                 
00047                 //Insert fsp of the basic block to the body
00048                 body->push_back(bb->fsp_get());
00049                 bb->fsp_get()->schedule_pos_set(current_schedule_pos++);
00050                 
00051                 //Insert scheduled instructions of the block to the body
00052                 ptr<ge_pi_vector__type> output = process_bb(bb);
00053                 body->insert(body->end(), output->begin(), output->end());
00054         }
00055         
00056         //Insert the last sequencepoint to the body
00057         ptr<ge_pi> lsp = bbs->back()->lsp_get();
00058         lsp->schedule_pos_set(current_schedule_pos);
00059         body->push_back(lsp);
00060         
00061         data_get()->ge_body_set(body);
00062         
00063         schedlog << "process end\n" << eolog;
00064 }
00065 
00066 /*!
00067         \brief Schedules pseudoinstructions of a basic block.
00068         
00069         \param bb The basic block.
00070         \return The scheduled pseudoinstructions.
00071 */
00072 ptr<ge_pi_vector__type> scheduler::process_bb(ptr<basic_block> bb) {
00073         schedlog << "process_bb start\n" << eolog;
00074         ptr<si_set__type> sch_items = find_schedule_items(bb);
00075         
00076         if ( !dumb_scheduling_get() ) {
00077                 //Do not perform inteligent scheduling. Just select random valid schedule.
00078                 find_critical_paths(sch_items);
00079         }
00080         ptr<ge_pi_vector__type> output = schedule_items(sch_items);
00081         schedlog << "process_bb end\n" << eolog;
00082         return output;
00083 }
00084 
00085 /*!
00086         \brief Compares latest_start_time property of schedule_item instances.
00087 */
00088 bool schedule_items_cmp1(srp<schedule_item> a, srp<schedule_item> b) {
00089         return a->latest_start_time_get() < b->latest_start_time_get();
00090 }
00091 
00092 
00093 /*!
00094         \brief Schedules a list of schedule_item instances.
00095         
00096         \param The list.
00097         \return The scheduled list.
00098 */
00099 ptr<ge_pi_vector__type> scheduler::schedule_items(ptr<si_set__type> items) {
00100         schedlog << "schedule_items start\n" << eolog;
00101         
00102         ptr<ge_pi_vector__type> schedule = ge_pi_vector__type::create();
00103                 
00104         ptr<si_set__type> waiting = items;
00105         ptr<si_vector__type> ready = si_vector__type::create();
00106         
00107         //Find items with no imput dependencies in the waiting set and move them to the ready set.
00108         for(si_set__type::iterator it=waiting->begin(); it!=waiting->end();) {
00109                 ptr<schedule_item> si = *it;
00110                 
00111                 si->out_deps_set(si->out_deps_copy_get());                              
00112                 
00113                 if ( si->in_deps_get()->size()==0 ) {
00114                         si_set__type::iterator del_it = it++; 
00115                         waiting->erase(del_it);
00116                         ready->push_back(si);
00117                 } else {
00118                         ++it;
00119                 }
00120         }
00121 
00122         //Sort ready items by increasing latest_start_time
00123         ::std::sort(ready->begin(),ready->end(),schedule_items_cmp1);
00124                 
00125         while( ready->size()!=0 ) {
00126                 ptr<schedule_item> si = *ready->begin();
00127                 
00128                 schedule->push_back(si->instruction_get());
00129                 si->instruction_get()->schedule_pos_set(current_schedule_pos++);
00130                 ready->erase(ready->begin());
00131                 
00132                 bool b_ready_set_changed = false;
00133                 
00134                 //Remove the item from in_deps of any succeeding item.
00135                 ptr<si_set__type> deps = si->out_deps_get();
00136                 for(si_set__type::iterator it1 = deps->begin(); it1!=deps->end(); ++it1) {
00137                         ptr<schedule_item> dep = *it1;
00138                         dep->in_deps_get()->erase(si);
00139                         
00140                         if ( dep->in_deps_get()->size()==0 ) {
00141                                 //Item has no other in_deps -> move it to the ready set.
00142                                 waiting->erase(dep);
00143                                 ready->push_back(dep);
00144                                 b_ready_set_changed = true;
00145                         }
00146                 }
00147                 
00148                 if ( b_ready_set_changed ) {
00149                         //Sort ready items by increasing latest_start_time
00150                         ::std::sort(ready->begin(),ready->end(),schedule_items_cmp1);
00151                 }
00152         }
00153 
00154         if ( waiting->size()!=0 ) {
00155                 b_dump(waiting,"waiting");
00156         }
00157         lassert(waiting->size()==0);
00158                 
00159         schedlog << "schedule_items end\n" << eolog;
00160         return schedule;
00161 }
00162 
00163 /*!
00164         \brief Checks whether a set of schedule_item instances contains a dependence loop.
00165         
00166         NOTE: For debugging purposes.
00167 */
00168 void scheduler::check_waiting_set(ptr<si_set__type> waiting) {
00169         for(si_set__type::iterator it = waiting->begin(); it!=waiting->end(); ++it) {
00170                 ptr<schedule_item> si = *it;
00171                 
00172                 if ( find_dependence_loop(si,si,0) ) {
00173                         return;
00174                 }               
00175         }
00176 }
00177 
00178 /*!
00179         \brief Recursively searches for a dependence loops.
00180         
00181         NOTE: For debugging purposes.
00182 */
00183 bool scheduler::find_dependence_loop(ptr<schedule_item> start,ptr<schedule_item> curr,ulint depth) {
00184         if ( depth > 4 ) {
00185                 return false;
00186         }
00187         
00188         ptr<si_set__type> deps = curr->in_deps_get();
00189         
00190         for(si_set__type::iterator it = deps->begin(); it!=deps->end(); ++it) {
00191                 ptr<schedule_item> dep = *it;
00192                 
00193                 if ( dep==start || find_dependence_loop(start,dep,depth+1)) {
00194                         schedlog << "find_dependence_loop found:item=" << curr->uid_get() << "\n" << eolog;
00195                         return true;
00196                 }
00197         }
00198         
00199         return false;
00200 }
00201 
00202 /*!
00203         \brief Searches for a critical path within a set of schedule_item instances.
00204 */
00205 void scheduler::find_critical_paths(ptr<si_set__type> items) {
00206         schedlog << "find_critical_paths start\n" << eolog;
00207         
00208         /* Compute length of a critical path */
00209         ulint cp_length = 0;
00210         
00211         ptr<si_set__type> waiting = si_set__type::create(items);
00212         
00213         ulint u_tmp = 0;
00214         
00215         si_set__type::iterator it = waiting->begin();
00216         while( waiting->size()!=0 ) {
00217                 ptr<schedule_item> si = *it;
00218         
00219                 if ( ++u_tmp > 10000 ) {
00220                         lassert2(false,"An infinite loop detected.");
00221                 }       
00222                 
00223                 if (  si->in_deps_get()->size()==0 ) {
00224                         //End time of the item.
00225                         si->end_time_set(si->start_time_get() + si->etime_get());
00226                         
00227                         //Start time of a succeeding item.
00228                         ulint succ_start_time = si->end_time_get() + si->ctime_get();
00229         
00230                         if ( succ_start_time > cp_length ) {
00231                                 cp_length = succ_start_time;
00232                         }               
00233                         
00234                         //Remove the item from in_deps of any succeeding item.
00235                         ptr<si_set__type> deps = si->out_deps_get();
00236                         for(si_set__type::iterator it1 = deps->begin(); it1!=deps->end(); ++it1) {
00237                                 ptr<schedule_item> dep = *it1;
00238                                 
00239                                 dep->in_deps_get()->erase(si);
00240                                 
00241                                 //Recompute start time of the dep.
00242                                 if ( dep->start_time_get()<succ_start_time ) {
00243                                         dep->start_time_set(succ_start_time);
00244                                 }       
00245                         }
00246                         si_set__type::iterator del_it = it++;
00247                         waiting->erase(del_it);
00248                 } else {
00249                         ++it;
00250                 }       
00251                 
00252                 if ( it==waiting->end() ) {
00253                         it = waiting->begin();
00254                 }
00255         }
00256         
00257         /* Set the last possible start time for the output (that not have input dependencies) items */
00258         waiting = si_set__type::create(items);
00259         for(it = waiting->begin(); it!=waiting->end(); ++it) {
00260                 ptr<schedule_item> si = *it;
00261                 
00262                 if ( si->end_time_get() + si->ctime_get() == cp_length ) {
00263                         //The output item.
00264                         si->latest_start_time_set(si->end_time_get() - si->etime_get());
00265                 }
00266 
00267                 si->in_deps_set(si->in_deps_copy_get());                
00268         }
00269         
00270         /* Compute the last possible start time for the items. */
00271         it = waiting->begin();
00272         while( waiting->size()!=0 ) {
00273                 ptr<schedule_item> si = *it;
00274                 
00275                 if (  si->out_deps_get()->size()==0 ) {
00276                         ulint lst = si->latest_start_time_get();
00277                                                 
00278                         //Remove the item from out_deps of any preceeding item.
00279                         ptr<si_set__type> deps = si->in_deps_get();
00280                         for(si_set__type::iterator it1 = deps->begin(); it1!=deps->end(); ++it1) {
00281                                 ptr<schedule_item> dep = *it1;                          
00282                                 dep->out_deps_get()->erase(si);
00283                                 
00284                                 ulint tmp_lst = lst - dep->ctime_get() - dep->etime_get();
00285                                 
00286                                 if ( tmp_lst < dep->latest_start_time_get() ) {
00287                                         dep->latest_start_time_set(tmp_lst);
00288                                 }
00289                         }
00290                         
00291                         si_set__type::iterator del_it = it++;
00292                         waiting->erase(del_it);
00293                 } else {
00294                         ++it;
00295                 }
00296                 
00297                 if ( it==waiting->end() ) {
00298                         it = waiting->begin();
00299                 }
00300         }
00301         
00302         schedlog << "find_critical_paths end\n" << eolog;       
00303 }
00304 
00305 /*!
00306         \brief Creates set of schedule_items for a basic block.
00307         
00308         \param bb The basic block.
00309         \return The set of schedule_items.
00310 */
00311 ptr<si_set__type> scheduler::find_schedule_items(ptr<basic_block> bb) {
00312         schedlog << "find_schedule_items start\n" << eolog;
00313         
00314         ge2si->clear();
00315         
00316         ptr<si_set__type> schedule_items = si_set__type::create();
00317         
00318         ptr<ge_pi_vector__type> instrs = bb->instructions_get();
00319         
00320         //Go through instructions of the block and create corresponding schedule items.
00321         for(ge_pi_vector__type::iterator it = instrs->begin(); it!=instrs->end(); ++it) {
00322                 ptr<ge_pi> ge = *it;
00323                 
00324                 ptr<schedule_item> si;
00325                 
00326                 ge2si__type::iterator si_search = ge2si->find(ge);
00327                 if ( si_search!=ge2si->end() ) {
00328                         si = si_search->second; 
00329                 } else {
00330                         si = create_schedule_item(ge);
00331                         (*ge2si)[ge] = si;
00332                 }               
00333                 
00334                 schedule_items->insert(si);
00335                 
00336                 ptr<ge_pi_set__type> in_deps = ge->dependencies_get();
00337                 for(ge_pi_set__type::iterator it1 = in_deps->begin(); it1!=in_deps->end(); ++it1 ) {
00338                         ptr<ge_pi> dep_ge = *it1;
00339                         
00340                         if ( dep_ge->bb_get()!=bb || dep_ge==ge) {
00341                                 continue;
00342                         }
00343                         
00344                         ptr<schedule_item> dep;
00345                         
00346                         si_search = ge2si->find(dep_ge);
00347                         if ( si_search!=ge2si->end() ) {
00348                                 dep = si_search->second;        
00349                         } else {
00350                                 dep = create_schedule_item(*it1);
00351                                 (*ge2si)[dep_ge] = dep;
00352                         }
00353                         
00354                         si->in_deps_get()->insert(dep);
00355                         dep->out_deps_get()->insert(si);
00356                 }
00357                 
00358         }
00359         
00360         for(si_set__type::iterator it=schedule_items->begin(); it!=schedule_items->end(); ++it) {
00361                 ptr<schedule_item> si = *it;
00362                 si->in_deps_copy_set(si_set__type::create(si->in_deps_get()));
00363                 si->out_deps_copy_set(si_set__type::create(si->out_deps_get()));
00364         }
00365         
00366         schedlog << "find_schedule_items end\n" << eolog;
00367         return schedule_items;
00368 }
00369 
00370 /*!
00371         \brief Creates schedule item for a pseudoinstruction.
00372         
00373         \param ge The pseudoinstruction.
00374         \return The schedule item.
00375 */
00376 ptr<schedule_item> scheduler::create_schedule_item(ptr<ge_pi> ge) {
00377         
00378         ptr<tm_instr_base> tm = ge->instruction_get();
00379                 
00380         ulint et, ct;
00381                 
00382         if ( tm && tm->exec_info_get() ) {
00383                 et = tm->exec_info_get()->etime_get();
00384                 ct = 0;
00385         } else {
00386                 et = 0;
00387                 ct = 0;
00388         }
00389                 
00390         ptr<schedule_item> si = schedule_item::create(ge,et,ct);
00391         
00392         return si;
00393 }
00394 
00395 /*!
00396         \brief Returns data of the processed function with scheduled body.
00397 */
00398 ptr<func_data> scheduler::get_result() {
00399         return data_get();
00400 }
00401 
00402 
00403 end_package(workers);
00404 end_package(backend_v2);
00405 end_package(lestes);
00406 

Generated on Mon Feb 12 18:23:14 2007 for lestes by doxygen 1.5.1-20070107