order_governor.cc

Go to the documentation of this file.
00001 #include <lestes/backend_v2/workers/order_governor.g.hh>
00002 #include <lestes/backend_v2/intercode/pi.g.hh>
00003 #include <lestes/backend_v2/structs/func_data.g.hh>
00004 #include <lestes/backend_v2/intercode/visitor_pi_pi2pi_operands.g.hh>
00005 #include <lestes/backend_v2/intercode/visitor_pi_pi2id.g.hh>
00006 #include <lestes/backend_v2/structs/pi_operands.g.hh>
00007 #include <lestes/backend_v2/debug/debug.hh>
00008 
00009 package(lestes);
00010 package(backend_v2);
00011 package(workers);
00012 
00013 using namespace ::lestes::backend_v2::intercode;
00014 using namespace ::lestes::backend_v2::structs;
00015 using namespace ::lestes::msg;
00016 
00017 typedef list< srp< pi_pi > > pi_list_type;
00018 typedef list< srp< pi_sp > > sp_list_type;
00019 typedef vector< srp< pi_operand > > operand_vector_type;
00020 typedef map< srp<pi_pi>, bool > pi_bool_map_type;
00021 
00022 
00023 declare_logger(og_log);
00024 initialize_logger( og_log, "order_governor", backend_v2_logger );
00025 
00026 
00027 /*!
00028         \brief Manages linearization.
00029 */
00030 void order_governor::process()
00031 {
00032         og_log << "Process begin\n" << eolog;
00033         
00034         pis_unordered = data_get()->pi_body_get();
00035         
00036         //Find pis with level set to 0.    
00037     identify_level_0();
00038         
00039         //Repeat loop while there are any unordered pis. 
00040     while( !pis_unordered_get()->empty() ) {
00041                 og_log << "Main loop begin.\n" << eolog;
00042                 
00043                 //Find unordered pis with level=1 and move them to the ordered set.
00044                 merge_ordered_with_unordered_level_X(1);
00045                 //Order merged level 0&1 set.
00046                 torder_ordered();
00047                 //Linearize ordered sps.
00048                 linearize_ordered_sps();
00049                 //Move psp and nsp pointers.
00050                 shift_unordered_nsp_psp();
00051                 //Recalculate levels for unordered pis.
00052                 renumber_levels(pis_unordered_get());
00053                 //Recalculate levels for ordered pis.
00054                 renumber_levels(pis_ordered_get());
00055                 
00056                 og_log << "Main loop end.\n" << eolog;
00057     }
00058         
00059         og_log << "Process end.\n" << eolog;
00060 }
00061 
00062 
00063 /*!
00064         \brief Moves pseudoinstructions of level 0 from pis_unordered to pis_ordered list.
00065 */
00066 void order_governor::identify_level_0()
00067 {
00068         //the ordered set is empty. Copy pis with level=0 to it.
00069     merge_ordered_with_unordered_level_X(0);
00070         
00071         //Set is_ordered=true for all pis with level=0.
00072     pi_list_type::iterator it;
00073     for(it=pis_ordered->begin(); it != pis_ordered->end(); it++) { 
00074                 (*is_ordered)[*it] = true;
00075     }
00076         
00077         //Set is_ordered=false for all pis with level>0.
00078     for(it=pis_unordered->begin(); it != pis_unordered->end(); it++) { 
00079                 (*is_ordered)[*it] = false;
00080     }
00081 }
00082 
00083 /*!
00084         \brief Merges unordered pseudoinstructions of given level with ordered pseudoinstructions.
00085         \param level_to_merge The level to be merged.
00086 */
00087 void order_governor::merge_ordered_with_unordered_level_X(level_t level_to_merge)
00088 {
00089         //Go through the unordered set.
00090     for(pi_list_type::iterator it = pis_unordered_get()->begin(); it != pis_unordered_get()->end();) {
00091                 if ( (*it)->level_get() == level_to_merge ) {
00092                         og_log << "Merging L0 with L" << level_to_merge << ": " << (*it)->reflection_get()->back()->name_get() << "(" << (*it)->uid_get() << ")[level=" << (*it)->level_get() << "] added\n" << eolog;;
00093                         
00094                         //Current pi has the right level. Move it to the ordered set.
00095                 pis_ordered->push_back(*it);
00096                         //Delete it from unordered set.
00097                 it = pis_unordered->erase(it);
00098                 } else {
00099                         ++it;
00100                 }
00101     }
00102         
00103 }
00104 
00105 /*!
00106         \brief Linearizes sequencepoints in pis_ordered list.
00107 */
00108 void order_governor::linearize_ordered_sps() {
00109         ptr<visitor_pi_pi2id> identificator = visitor_pi_pi2id::create();
00110         /*
00111                 Go through ordered list and for each pi_sp set psp to the previous one
00112                 and previous one's nsp to this sp.
00113         */
00114         ptr<pi_pi> previous = NULL;
00115         ptr<pi_pi> current = NULL;
00116         pi_list_type::iterator it;
00117     for(it=pis_ordered->begin(); it != pis_ordered->end(); it++) { 
00118         
00119                 //if ( (*it)->accept_visitor_pi_pi2ulint_gen_base(identificator) == visitor_pi_pi2id::PI_SP ) {
00120                         //current pi is type of pi_sp
00121                         current = (*it);
00122                         
00123                         if ( previous ) {
00124                                 previous->nsp_set(current);
00125                         }
00126                         current->psp_set(previous);
00127                         previous = current;
00128                 //}
00129     }
00130         current->nsp_set(NULL);
00131 }
00132 
00133 /*!
00134         \brief Linearizes pis_ordered list.
00135         
00136         Performs topological ordering in directed acyclic graph. Vertices are pseudoinstructions from pis_ordered list.
00137         Incoming edges for pseudoinstruction pi are psp->pi and origin->pi for each pi's operand. Outcoming edge is 
00138         pi->nsp. 
00139 */
00140 void order_governor::torder_ordered()
00141 {
00142 
00143         og_log << "Tordering begin\n" << eolog;
00144         
00145         //The getter can obtain operands from any generic pi.
00146         ptr<visitor_pi_pi2pi_operands> operands_getter = visitor_pi_pi2pi_operands::create();
00147         
00148         //identificator can identify kind of any generic pi
00149         ptr<visitor_pi_pi2id> identificator = visitor_pi_pi2id::create();
00150         
00151         //List of ordered pis. No pi is ordered at the beginning.
00152     ptr<pi_list_type> tordered_list = pi_list_type::create();
00153         //List of unordered pis. Every pi is unordered at the beginning.
00154     ptr<pi_list_type> tunordered_list = pis_ordered_get();
00155     
00156         //Set is_ordered=false for all unordered pis.
00157     pi_list_type::iterator it;
00158     for(it=tunordered_list->begin(); it != tunordered_list->end(); it++) { 
00159                 (*is_ordered)[*it] = false;
00160     }
00161 
00162 #ifdef BACKEND_V2_DEBUG
00163         //infinite loop detection
00164         ulint dbg = 0;    
00165 #endif
00166 
00167         //Repeat loop while there are any unordered pis. 
00168     while( !tunordered_list->empty()) {
00169         
00170 #ifdef BACKEND_V2_DEBUG
00171                 lassert2(dbg<=tunordered_list->size(),"An inifinite loop detected.");
00172                 dbg++;
00173 #endif          
00174 
00175                 //Get first unorderd pi.
00176                 ptr<pi_pi> pi = tunordered_list->front();
00177                 
00178                 //Remove it from unordered set.
00179                 tunordered_list->pop_front();
00180                 
00181                 og_log << "Tordering: trying order " << pi->reflection_get()->back()->name_get() << "(" << pi->uid_get() << ")\n" << eolog;
00182         
00183                 if ( pi->psp_get() && (*is_ordered_get())[pi->psp_get()] == false )  {
00184                         //Psp is unordered. So this pi is also unordered.
00185                 tunordered_list->push_back(pi);
00186                         
00187                         og_log << "\tTordering: current pi can't be ordered (psp is not ordered yet)\n" << eolog;
00188                         
00189                         continue;
00190                 }
00191                 
00192                 //Get it's operands.
00193                 ptr<pi_operands> operands = pi->accept_visitor_pi_pi2pi_operands_gen_base(operands_getter);
00194                 /* Test if every input operand's origin is ordered. 
00195                  ( Do not test output operands - its origin is set to the current pi. )
00196                 */
00197                 
00198             if ( !pi_operands_origins_ordered(operands->operands_input_get()) ) {
00199                         //One of operands hasn't got its origin ordered
00200                         tunordered_list->push_back(pi);
00201                         
00202                         og_log << "\tTordering: current pi can't be ordered (origins of operands are not ordered yet)\n" << eolog;
00203                         
00204                         continue;
00205                 }
00206                 
00207             if ( nsp_for_any(pi, tunordered_list) ) {
00208                         //It is pi_sp and it is nsp for one of unordered pis.
00209                         tunordered_list->push_back(pi);
00210                         
00211                         og_log << "\tTordering: current pi can't be ordered (sp is nsp for unorderd pi)\n" << eolog;
00212                         
00213                         continue;
00214                 }
00215                 
00216                 (*is_ordered_get())[pi] = true;
00217             tordered_list->push_back(pi);
00218                 
00219                 og_log << "\tTordering: " << pi->reflection_get()->back()->name_get() << "(" << pi->uid_get() << ") is set as ordered\n" << eolog;
00220 
00221 #ifdef BACKEND_V2_DEBUG
00222                 dbg = 0;
00223 #endif
00224 
00225     }
00226         
00227         //We have new bigger ordered set.
00228     pis_ordered_set(tordered_list);
00229         
00230         og_log << "Tordering end\n" << eolog;
00231 }
00232 
00233 /*!
00234         \brief Tells whether a sequencepoint is psp for any of pseudoinstructions in a list.
00235         \param sp The sequencepoint.
00236         \param list The list.
00237 */
00238 bool order_governor::nsp_for_any(ptr<pi_pi> sp, ptr<pi_list_type> list) {
00239         //Go through the unordered set and check if sp is nsn for any of them.
00240     pi_list_type::iterator it;
00241     for(it = list->begin(); it != list->end();it++) {
00242                 if ( (*it)->nsp_get()==sp ) {
00243                         return true;
00244                 }
00245         }
00246         return false;
00247 }
00248 
00249 /*!
00250         \brief Tells whether origin of each operand in list is ordered.
00251         \param operand_list The list.
00252 */
00253 bool order_governor::pi_operands_origins_ordered(ptr<operand_vector_type> operand_list) {
00254         lassert(operand_list);  
00255         
00256         //Go through operands and check if everyone is ordered.
00257     operand_vector_type::iterator it;
00258     for(it=operand_list->begin(); it!=operand_list->end(); it++) {
00259                 ptr<pi_pi> origin = (*it)->origin_get();
00260                 
00261                 if ( !origin ) {
00262                         //Operand has not an origin.
00263                         continue;
00264                 }
00265                 
00266                 //Find out if origin is ordered.
00267                 pi_bool_map_type::iterator it1 = is_ordered->find(origin);
00268                 
00269                 //Origin has to be in map.
00270                 lassert(it1!=is_ordered->end());
00271                 
00272                 if ( !it1->second ) {
00273                         //Origin is unordered.
00274                 return false;
00275                 }
00276     }
00277     return true;
00278 }
00279 
00280 /*!
00281         \brief Returns level of a pi_pi pseudoinstruction.
00282         
00283         \param pi The pi_pi.
00284         \return -1 if pi is NULL. Pi's level otherwise.
00285 */
00286 int order_governor::get_pi_level(ptr < pi_pi > pi)
00287 {
00288         return pi ? (int)pi->level_get() : -1;
00289 }
00290 
00291 /*!
00292         Gets last pi_pi pseudoinstruction of chain where two consequent pi_pi point with
00293         psp and nsp to each other.
00294         \param pi Start of the chain.
00295         \return The last pi of chain.
00296 */
00297 ptr<pi_pi> order_governor::conjugated_chain_end_find(ptr<pi_pi> pi) 
00298 {
00299         while(pi->nsp_get() && pi->nsp_get()->psp_get()==pi) {
00300                 pi = pi->nsp_get();
00301         }       
00302         return pi;
00303 }
00304 
00305 /*!
00306         Gets first pi_pi pseudoinstruction of chain where two consequent pi_pi point with
00307         psp and nsp to each other.
00308         \param pi End of the chain.
00309         \return The first pi of chain.
00310 */
00311 ptr<pi_pi> order_governor::conjugated_chain_start_find(ptr<pi_pi> pi) 
00312 {
00313         while(pi->psp_get() && pi->psp_get()->nsp_get()==pi) {
00314                 pi = pi->psp_get();
00315         }       
00316         return pi;
00317 }
00318 
00319 
00320 /*!
00321         \brief Shifts psp and nsp of pis_unordered pseudoinstructions.
00322 */
00323 void order_governor::shift_unordered_nsp_psp()
00324 {
00325         //Move psp and nsp of unordered pis.
00326     pi_list_type::iterator it;
00327     for(it = pis_unordered->begin(); it!=pis_unordered->end(); it++) {
00328                 ptr<pi_pi> pi = (*it);
00329                 
00330                 og_log << "shift_unordered_nsp_psp: pi(" << pi->uid_get() << ").level= " << get_pi_level(pi) << "\n" <<  msg::eolog;
00331                 
00332                 lassert(get_pi_level(pi)>1);
00333                 
00334                 if ( get_pi_level(pi->psp_get())==0 ) {
00335                         ptr<pi_pi> pi_hlp = conjugated_chain_end_find(pi);
00336                         
00337                         og_log << "shift_psp: chain_end(" << pi_hlp->uid_get() << ").nsp.level=" << get_pi_level(pi_hlp->nsp_get()) << "\n" <<  msg::eolog;
00338                         
00339                         lassert(get_pi_level(pi_hlp)==get_pi_level(pi));
00340                         
00341                         if (get_pi_level(pi_hlp->nsp_get())>0){
00342                                 pi->psp_set(pi_hlp->nsp_get()->psp_get());
00343                         }
00344                         
00345                 } else if ( get_pi_level(pi->nsp_get())==0 ) {
00346                         ptr<pi_pi> pi_hlp = conjugated_chain_start_find(pi);
00347 
00348                         og_log << "shift_nsp: chain_begin(" << pi_hlp->uid_get() << ").psp.level=" << get_pi_level(pi_hlp->psp_get()) << "\n" << msg::eolog;
00349 
00350                         lassert(get_pi_level(pi_hlp)==get_pi_level(pi));
00351 
00352                         if (get_pi_level(pi_hlp->psp_get())>0) {
00353                                 pi->nsp_set(pi_hlp->psp_get()->nsp_get());
00354                         }
00355                 }
00356     }
00357 }
00358 
00359 /*!
00360         \brief Decrease by 1 level of pseudoinstructions in a list.
00361         \param pi_list The list.
00362 */
00363 void order_governor::renumber_levels(ptr<pi_list_type> pi_list)
00364 {
00365     lassert(pi_list);
00366         
00367         //Subtract 1 from level for every pi in the list. 
00368     pi_list_type::iterator it;
00369     for(it = pi_list->begin(); it!=pi_list->end(); it++) {
00370                 ptr<pi_pi> pi = (*it);
00371                 
00372                 if ( pi->level_get() > 0 ) {
00373                 pi->level_set(pi->level_get()-1);
00374                 }
00375     }
00376 }
00377 
00378 /*!
00379         \brief Returns func_data with linearized pseudoinstructions.
00380 */
00381 ptr<func_data> order_governor::get_result()
00382 {
00383         lassert(pis_ordered);
00384                 
00385         ptr<visitor_pi_pi2id> pi_id_getter = visitor_pi_pi2id::create();
00386         
00387         /*
00388                 Set psp to the previous pi_sp (now it can also be pi_pi).
00389         */
00390         ptr<pi_sp> tmp_sp = NULL;
00391         for(pi_list_type::iterator it_pi_list = pis_ordered->begin(); it_pi_list!=pis_ordered->end(); ++it_pi_list) {
00392                 ptr<pi_pi> pi = *it_pi_list;
00393 
00394                 visitor_pi_pi2id::kind_type pi_id = (visitor_pi_pi2id::kind_type)pi->accept_visitor_pi_pi2ulint_gen_base(pi_id_getter);
00395                 
00396                 //Set psp to previous sequencepoint (now psp can be pi_sp or pi_pi )
00397                 pi->psp_set(tmp_sp);
00398                 
00399                 //Add pi to an output list
00400                 if ( pi_id==visitor_pi_pi2id::PI_SP ) {
00401                         tmp_sp = pi.dncast<pi_sp>();
00402                 }
00403                 
00404         }
00405         
00406         /*
00407                 Set nsp to the following pi_sp (now it can also be pi_pi). 
00408         */
00409         tmp_sp = NULL;
00410         for(pi_list_type::reverse_iterator it_pi_list = pis_ordered->rbegin(); it_pi_list!=pis_ordered->rend(); ++it_pi_list) {
00411                 ptr<pi_pi> pi = *it_pi_list;
00412                 
00413                 visitor_pi_pi2id::kind_type pi_id = (visitor_pi_pi2id::kind_type)pi->accept_visitor_pi_pi2ulint_gen_base(pi_id_getter);
00414                 
00415                 pi->nsp_set(tmp_sp);
00416                 
00417                 if ( pi_id==visitor_pi_pi2id::PI_SP ) {
00418                         tmp_sp = pi.dncast<pi_sp>();
00419                 }
00420         }       
00421         
00422         data_get()->pi_body_set(pis_ordered);
00423         
00424         return data_get();
00425 }
00426 
00427 end_package(workers);
00428 end_package(backend_v2);
00429 end_package(lestes);
00430 

Generated on Mon Feb 12 18:22:45 2007 for lestes by doxygen 1.5.1-20070107