dag_example.cpp

This is an example of how to use the DAG class.

00001 /***************************************************************************
00002  *   Copyright (C) 2009 by Touati Sid                                      *
00003  *   Sid-nospam.Touati-nospam@univ-cotedazur.fr                                      *
00004  *   Copyright  INRIA and the University of Versailles                     *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  *                                                                         *
00010  *   This program is distributed in the hope that it will be useful,       *
00011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00013  *   GNU General Public License for more details.                          *
00014  *                                                                         *
00015  *   You should have received a copy of the GNU Library General Public     *
00016  *   License along with this program (LGPL); if not, write to the          *
00017  *   Free Software Foundation, Inc.,                                       *
00018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
00019  *   Exception : this software requires a licence  of the LEDA libary.     *
00020  *   If you are from academia, you can get a free leda binary licence 
00021  *   allowing you to use freely our DDG library.                           *
00022  *   Otherwise, you can buy a LEDA licence from algorithmic-solutions      *
00023  *   http://www.algorithmic-solutions.com                                  *
00024  *   LEDA binaries and source codes are excluded from this LGPL.           *
00025  *   Obtaining a LEDA licence is not mandatory to use our GPL software     *
00026  *   If the user wants, he can  create a free source-compatible replacement*
00027  *   for LEDA, and he is allowed to use our software under LGPL.           *
00028  ***************************************************************************/
00029 
00034 #include "DDG.h" // the header file of the DDG library. 
00035         // To be included by the user.
00036 #include "LEDA/graph/graph_misc.h" // Is_Acyclic 
00037 #include <iostream>
00038 #include <cstdlib>
00039 
00040 
00041 using namespace std;
00042 using namespace DDG; // the namespace of the DDG library.
00043 
00044 
00045 
00046 int main(int argc, char *argv[])
00047 {
00048     //int are always usefull
00049     int         i,j,cpt ;
00050     int c; // for getopt
00051     // some strings for file names
00052     char        *ddg_filename=NULL, *arch_filename=NULL;
00053     char        str[MAX_STRING];
00054     REGISTER_TYPES rt;
00055     LEDA::list<REGISTER_TYPES> T;
00056     
00057     // some objects for graphs
00058     //declare a DDG of a loop (cyclic data dependence graph)
00059     DDG::LOOP loop; 
00060     ARCHITECTURE ISA_example;
00061     DDG::DAG dag, dag_copy;  // declare a DDG of a basic block (directed acyclic graph : DAG)
00062     
00063     LEDA::node n,u;
00064     LEDA::edge e;
00065     LEDA::set<node> VR;
00066     LEDA::set<node> MA; // for a maximal antichain computation
00067     LEDA::node_map<int> map; // when duplicating a graph, 
00068                 // we need to save node correspondance between original and new graph
00069     LEDA::node_array<node> killer; // for register saturation examples
00070     array< list<node> > ALN ; // array of sorted chains
00071 
00072     DDG::INSTRUCTIONS_TYPES it; // information attached to an opcode
00073     
00074     LEDA::list<edge> el; 
00075     LEDA::list<node> nl; 
00076     LEDA::set<node> parents, children; // set of parents and children of a node
00077 
00078     while ((c = getopt (argc, argv, "i:a:")) != -1){
00079         switch(c){
00080             case 'a': arch_filename=optarg;
00081                 break;
00082             case 'i': ddg_filename =optarg;
00083                 break;
00084             case '?': 
00085                 cout<<"usage:"<< argv[0] <<" -i ddg_filename.xml [-a isa_desc.xml] "<<endl;
00086                 return EXIT_FAILURE;
00087         }
00088         
00089     }
00090     
00091     //------- the user can define its own ISA ----------------
00092     if (arch_filename!=NULL)  { 
00093         ISA_example.read_from_xml(arch_filename);
00094         if(ISA_example.check()){
00095             loop=LOOP(ISA_example);  //build an empty DDG loop with a user defined architcural (ISA) description
00096             dag=DAG(ISA_example);   //build an empty DAG with a user defined architcural (ISA) description
00097         } else return EXIT_FAILURE;
00098     }
00099      
00100      //---------------- The user can read a DDG from an xml format defined by the DDG library 
00101     
00102     if (ddg_filename != NULL){
00103     
00104         i=loop.read_from_xml(ddg_filename); // reads the DDG loop from a n xml file
00105         
00106         if(i==-1){
00107             return EXIT_FAILURE;
00108         }
00109         
00110         i=dag.read_from_xml(ddg_filename); // reads the DDG loop from a n xml file
00111         
00112         if(i==-1){
00113             return EXIT_FAILURE;
00114         }
00115         
00116     }
00117     else{
00118         cout<<"usage:"<< argv[0] <<" -i ddg_filename.xml [-a isa_desc.xml] "<<endl;
00119         return EXIT_FAILURE;
00120     }
00121 
00122     if(! Is_Acyclic(dag, el)) {
00123         cerr<<"Input Error: Non acyclic graph.\n";
00124         cerr<<"There are "<< el.size() <<" illegal arcs:\n";
00125         forall(e, el){
00126             cerr<<dag.id(dag.source(e))<<" -> "<< dag.id(dag.target(e))<<endl;
00127         }
00128         return EXIT_FAILURE;
00129     }
00130 
00131     
00132      // The user can modify the DDG by many other methods : 
00133     // new_node, new_edge, clear, del_node, del_edge, etc.
00134      // The user can access any information about nodes, edges,
00135      // apply well known algorithms using the LEDA library
00136      // See the LEDA manual : http://www.algorithmic-solutions.info/leda_manual
00137      // See the DDG user manual inside this distribution
00138     
00139 
00140     cout<< "DAG example program: " <<ddg_filename<<endl;
00141     cout<< "-----------------------------" <<endl;
00142     T=dag.T();
00143     
00144     forall(rt,T){
00145             
00146         cout<<"Register Saturation of the DAG (loop body) for register type "<< rt.get_register_typename() <<" is " <<REGISTER_SATURATION (dag, rt.get_register_type_id(), nl)<<endl;
00147         cout<<"Saturating values of type "<<rt.get_register_typename()<<endl;
00148         forall(n, nl){
00149         it= dag.instruction_type(n);
00150         cout<< dag.id(n)<< " with opcode " << it.opcode()<< " ("<<dag.latency(n)<<","<<dag.delta_r(n)<<","<<dag.delta_w(n, rt.get_register_type_id())<<")"<<endl;
00151         }
00152     }
00153     // -------------------- The critical path is the longest path of the DAG
00154     cout<<endl<<"Critical Path ="<<dag.CriticalPath(el)<<endl;
00155 
00156     cout<<"Edges belonging to the critical path"<<endl;
00157     forall(e, el){
00158         n=dag.source(e);
00159         u=dag.target(e);
00160         it= dag.instruction_type(n);
00161         cout<< dag.id(n)<< " -> " << dag.id(u) <<endl;
00162     }
00163 
00164     //----------------------- We can access the DAG in many ways
00165     forall_nodes(u, dag){
00166         parents=dag.get_parents(u);
00167         cout<<"The parents of the node number "<<dag.id(u)<<" are : ";
00168         forall (n, parents){
00169             cout<<dag.id(n)<<" ";
00170         }
00171         cout<<endl;
00172     }
00173     forall_nodes(u, dag){
00174         children=dag.get_children(u);
00175         cout<<"The children of the node number "<<dag.id(u)<<" are : ";
00176         forall (n, children){
00177             cout<<dag.id(n)<<" ";
00178         }
00179         cout<<endl;
00180     }
00181     forall_nodes(u, dag){
00182         parents=dag.get_up(u);
00183         cout<<"The ascendants of the node number "<<dag.id(u)<<" are : ";
00184         forall (n, parents){
00185             cout<<dag.id(n)<<" ";
00186         }
00187         cout<<endl;
00188     }
00189     forall_nodes(u, dag){
00190         children=dag.get_down(u);
00191         cout<<"The descendants of the node number "<<dag.id(u)<<" are : ";
00192         forall (n, children){
00193             cout<<dag.id(n)<<" ";
00194         }
00195         cout<<endl;
00196     }
00197     
00198     // ------------------ The user can visualize the DAG ------------------------
00199     snprintf(str, MAX_STRING, "%s_dag.vcg",ddg_filename); // sets the .vcg filename for the DAG
00200     dag.write_to_vcg(str); //outputs the DAG to a vcg file to be visualized by the xvcg tool
00201     dag_copy.copy(dag); // create an exact copy.
00202     snprintf(str, MAX_STRING, "%s_dag_copy.vcg",ddg_filename); 
00203     dag_copy.write_to_vcg(str); //outputs the copy DAG to a vcg file to be visualized by the xvcg tool
00204     
00205     cout<<endl<<str<< " can be visualized using xvcg."<<endl;
00206 
00207     /*--------------- The user can extract a copy of a loop body -------------- */
00208     
00209     map.init(loop);/* initializes a mapping function from loop nodes to dag nodes.
00210     Forall u a node in the loop, map(u) stores its corresponding node in the exctracted DAG (loop body) */
00211     dag.clear();
00212     forall_nodes(u,loop){
00213         map[u]=dag.new_node((loop.instruction_type(u)).opcode_id());
00214     }
00215     forall_edges(e,loop){
00216         if(loop.lambda(e)==0) { // It is an edge belonging to the loop body ==> insert it into the DAG
00217             dag.new_edge(map[loop.source(e)], map[loop.target(e)],loop[e]);
00218         }
00219     }
00220 
00221     // --- Dilworth decomposition -----------
00222     i=MAXIMAL_ANTI_CHAIN(dag, MA);
00223     cout<<"Maximal antichain in the DAG : "<<i<<endl;
00224     cout<<"Nodes belonging to a maximal antichain "<<endl;
00225     forall(n, MA){
00226         cout<< dag.id(n)<< " with opcode " << it.opcode()<<endl;
00227     }
00228 
00229     //---The user can extract the body of a loop unrolled many times
00230     // (recurrent data dependence edges are preserved) ----------
00231     
00232     cout<<"Unrolling the loop "<<ddg_filename<<" four times and extract its body"<<endl;
00233     unroll (loop, dag, 4);
00234     snprintf(str, MAX_STRING,"%s_dag_unroll_4.vcg",ddg_filename); // sets the .vcg filename for the ddg loop
00235     dag.write_to_vcg(str);
00236     // The user can access any kind of information 
00237     forall(rt,T){
00238         cout <<"The set of values of type "<< rt.get_register_typename() <<" of the body  is :"<<endl;
00239         VR=dag.get_V_R(rt.get_register_type_id());
00240         forall(u, VR){
00241             it=dag.instruction_type(u);
00242             cout<< dag.id(u)<< " with opcode " << it.opcode()<<endl;
00243     
00244         }
00245     }
00246     cout<<endl<< "The set of sources of the body are :"<<endl;
00247     VR=dag.get_Sources();
00248     forall(u, VR){
00249         it=dag.instruction_type(u);
00250         cout<< dag.id(u)<< " with opcode " << it.opcode()<<endl;
00251     }
00252     cout<<endl<< "The set of sinks of the body are :"<<endl;
00253     VR=dag.get_Targets();
00254     forall(u, VR){
00255         it=dag.instruction_type(u);
00256         cout<< dag.id(u)<< " with opcode " << it.opcode()<<endl;
00257     }
00258     
00259     // Computes the critical path of the DAG and puts the list of its nodes in nl
00260     cout<<endl<<"Critical Path of the unrolled body ="<<dag.CriticalPath(nl)<<endl;
00261     cout<<"Nodes belonging the critical path of the unrolled body "<<endl;
00262     forall(n, nl){
00263         it= dag.instruction_type(n);
00264         cout<< dag.id(n)<< " with opcode " << it.opcode()<<endl;
00265     }
00266 
00267     // ------------- Hiding and restoring nodes -------------
00268     // look for two arbitrary values of any register type
00269     forall(rt, T){
00270         if (dag.get_V_R(rt.get_register_type_id()).size()>=2){
00271             dag.hide_node(dag.get_V_R(rt.get_register_type_id()).choose()); // just to hide one node writing into a register
00272                         // note that all adjacent edges are hidden too
00273             dag.hide_node(dag.get_V_R(rt.get_register_type_id()).choose()); // hide another one
00274             break;
00275         }
00276     }
00277     rt=T.front();
00278     cout<<"Register Saturation of the DAG (after hiding two values of type "<< rt.get_register_typename() <<") is : "<<(j=REGISTER_SATURATION (dag, rt.get_register_type_id(), nl, killer))<<endl;
00279     cout<<"Saturating values of type "<< rt.get_register_typename() <<endl;
00280     forall(n, nl){
00281         it= dag.instruction_type(n);
00282         cout<< dag.id(n)<< " with opcode " << it.opcode()<<endl;
00283     }
00284     
00285     dag.restore_all_nodes(); 
00286     dag.restore_all_edges();
00287     dag.build_internal_structures(); // restore the internal state of the DAG
00288 
00289     cout<<"Register Saturation of the DAG (after restoring the two values of type"<< rt.get_register_typename()<<") is : "<<REGISTER_SATURATION (dag, rt.get_register_type_id(), nl, killer)<<endl;
00290     cout<<"Saturating values of type "<< rt.get_register_typename()<<endl;
00291     forall(n, nl){
00292         it= dag.instruction_type(n);
00293         cout<< dag.id(n)<< " with opcode " << it.opcode()<<endl;
00294     }
00295 
00296     //--------------------- Lattices and Orders --------------------------/
00297     cout<<"Lattices and Order Notations:\n";
00298     forall_nodes(u, dag){
00299         forall_nodes(n, dag){
00300             if(lt(u,n)){
00301                 cout<<dag.id(u)<< " < " << dag.id(n) << endl;
00302             }
00303             if(le(u,n)){
00304                 cout<<dag.id(u)<< " <= " << dag.id(n)<< endl;
00305             }
00306             if(gt(u,n)){
00307                 cout<<dag.id(u)<< " > " << dag.id(n)<< endl;
00308             }
00309             if(ge(u,n)){
00310                 cout<<dag.id(u)<< " >= " << dag.id(n)<< endl;
00311             }
00312             if(parallel(u,n)){
00313                 cout<<dag.id(u)<< " || " << dag.id(n)<< endl;
00314             }
00315             if(comparable(u,n)){
00316                 cout<<dag.id(u)<< " ~ " << dag.id(n)<< endl;
00317             }
00318         }
00319     }
00320 
00321 
00322     cout<<"Minimal Chain Decomposition (Dilworth)"<<endl;
00323     cout<<"--------------------------------------"<<endl;
00324     j=MINIMAL_CHAIN(dag, ALN);
00325 
00326     cout<<"There are "<< j <<" chains"<<endl;
00327     cpt=0;
00328     for(i=0;i< j ;i++){
00329         cout<<"Chain["<<i<<"]: ";
00330         forall(u,ALN[i]){
00331             cout<<dag.id(u);
00332             cout<<" ";
00333             cpt++;
00334         }
00335         cout<<endl;
00336     }
00337     cout<<"Total "<< cpt <<" nodes"<<" in this distribution."<<endl;
00338     //--------------------- Many other software opportunities exist. See the reference manual.
00339 
00340     return EXIT_SUCCESS;
00341 }

January 2009, by Sid Touati (Copyright INRIA and University of Versailles)