VIS

src/part/partFine.c

Go to the documentation of this file.
00001 
00027 #include "partInt.h"
00028 
00029 static char rcsid[] UNUSED = "$Id: partFine.c,v 1.5 2005/04/30 04:00:38 fabio Exp $";
00030 
00031 /*---------------------------------------------------------------------------*/
00032 /* Constant declarations                                                     */
00033 /*---------------------------------------------------------------------------*/
00034 
00035 
00036 /*---------------------------------------------------------------------------*/
00037 /* Structure declarations                                                    */
00038 /*---------------------------------------------------------------------------*/
00039 
00040 
00041 /*---------------------------------------------------------------------------*/
00042 /* Type declarations                                                         */
00043 /*---------------------------------------------------------------------------*/
00044 
00045 
00046 /*---------------------------------------------------------------------------*/
00047 /* Variable declarations                                                     */
00048 /*---------------------------------------------------------------------------*/
00049 
00050 
00051 /*---------------------------------------------------------------------------*/
00052 /* Macro declarations                                                        */
00053 /*---------------------------------------------------------------------------*/
00054 
00055 #define PartVertexReadGeneric(vPtr)  ((PartVertexInfo_t *)(vPtr)->user_data)->generic
00056 #define PartVertexReadGeneric1(vPtr)  ((PartVertexInfo_t *)(vPtr)->user_data)->generic1
00057 #define BASIC_PARTITION_UNIT 15
00058 
00061 /*---------------------------------------------------------------------------*/
00062 /* Static function prototypes                                                */
00063 /*---------------------------------------------------------------------------*/
00064 
00065 static  int             Part_IsFanoutInverter(Ntk_Node_t *node);
00066 
00070 /*---------------------------------------------------------------------------*/
00071 /* Definition of exported functions                                          */
00072 /*---------------------------------------------------------------------------*/
00073 
00074 
00075 /*---------------------------------------------------------------------------*/
00076 /* Definition of internal functions                                          */
00077 /*---------------------------------------------------------------------------*/
00078 
00079 
00092 void
00093 PartPartitionFineGrain(
00094   Ntk_Network_t *network,
00095   graph_t       *partition,
00096   mdd_t         *careSet)
00097 {
00098   Ntk_Node_t     *node;            /* Pointer to iterate over nodes */
00099   Mvf_Function_t *mddFunction;     /* Pointer to a MDD */
00100   mdd_manager    *manager;         /* Mdd manager in the partition */
00101   st_table       *tableOfLeaves;   /* To store the leaves of the graph */
00102   st_table       *mddIdToNodeName; /* For quick lookup of node's name */
00103   array_t        *arrayOfMvf;      /* To store the next state functions */
00104   array_t        *arrayOfRoots;    /* To store the roots of the graph */
00105   lsList         sinkList;         /* Vertices representing comb. outputs */
00106   lsGen          gen;              /* To iterate over lists */
00107   vertex_t       *toVertex;        /* Will hold the current function vertex */
00108   int            i;                /* Index for loops */
00109   long           mddId;            /* Will hold the mddId being processed */
00110   st_table       *mddSupport;      /* To store the support of the Mvf_Function */
00111   st_generator   *stGen;           /* To iterate over the MddIds of the support */
00112   vertex_t       *fromVertex;      /* Will hold the current vertex in the support */
00113   array_t        *singletonMvfArray;
00114   array_t        *singletonArrayOfRoots;
00115   array_t        *tmpArrayOfMvf;
00116   Mvf_Function_t *nodeMvf;
00117   lsList         sortedListOfNodes;     
00118   array_t        *sortedArrayOfPartitionNodes;
00119   array_t        *unsortedArrayOfPartitionNodes;
00120   st_table       *tableOfPartitionNodes;
00121   Ntk_Node_t     *fanin, *fanout;
00122 
00123   manager = PartPartitionReadMddManager(partition);
00124   
00125   /* Make the combinational input  nodes into leaves */
00126   tableOfLeaves = st_init_table(st_ptrcmp, st_ptrhash);
00127   mddIdToNodeName = st_init_table(st_numcmp, st_numhash);
00128   Ntk_NetworkForEachCombInput(network, gen, node) {
00129     if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID)
00130       Ord_NetworkAssignMddIdForNode(network, node);
00131     st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );
00132     st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
00133               Ntk_NodeReadName(node));
00134   }
00135 
00136   unsortedArrayOfPartitionNodes = array_alloc(Ntk_Node_t *, 0);  
00137   tableOfPartitionNodes = st_init_table(st_ptrcmp, st_ptrhash);
00138   /* Make the target node list for partition */
00139   Ntk_NetworkForEachNode(network, gen, node) {
00140     if(Ntk_NodeTestIsShadow(node))      continue;
00141     else if(Ntk_NodeTestIsCombInput(node))      continue;
00142     else if(Ntk_NodeTestIsCombOutput(node))     continue;
00143     else if(Ntk_NodeReadNumFanouts(node) == 1) { 
00144       fanout = Part_GetFanoutFreeLogic(node);
00145       if(Ntk_NodeTestIsCombOutput(fanout));
00146       else if(Ntk_NodeReadNumFanins(node) > 10);
00147       else if(Ntk_NodeReadNumFanins(fanout) == 1)       continue;
00148       else if(!Part_CheckLeafNodeCondition(node, tableOfPartitionNodes, 5, 10)) {
00149         if(Ntk_NodeReadNumFanins(node) == 1) {
00150            fanin = Part_GetFaninFreeLogic(node);
00151            if(!fanin)   continue;
00152            if(Ntk_NodeTestIsCombInput(fanin))   continue;
00153         }
00154         continue;
00155       }
00160     }
00169     array_insert_last(Ntk_Node_t *, unsortedArrayOfPartitionNodes, node);
00170     st_insert(tableOfPartitionNodes, (char *) node, (char *) (long) (-1));
00171   }
00172 
00173   /* create sorted array of partition nodes */
00174   sortedListOfNodes = Ntk_NetworkComputeTopologicalOrder(network, 
00175                                unsortedArrayOfPartitionNodes, tableOfLeaves);
00176 
00177   sortedArrayOfPartitionNodes = array_alloc(Ntk_Node_t *, 0);  
00178   lsForEachItem(sortedListOfNodes, gen, node){
00179     /* sortedListOfNodes includes many internal nodes, need to filter them out */
00180     if(st_is_member(tableOfPartitionNodes, (char *) node)){
00181       array_insert_last(Ntk_Node_t *, sortedArrayOfPartitionNodes, node);
00182       if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID) 
00183         Ord_NetworkAssignMddIdForNode(network, node);
00184     }   
00185   }
00186   array_free(unsortedArrayOfPartitionNodes);
00187   lsDestroy(sortedListOfNodes, (void (*)(lsGeneric))0);  
00188   st_free_table(tableOfPartitionNodes);
00189       
00190 
00191   tmpArrayOfMvf = array_alloc(Mvf_Function_t *, 0);
00192   for(i=0; i < array_n(sortedArrayOfPartitionNodes); i++){
00193     node = array_fetch(Ntk_Node_t *, sortedArrayOfPartitionNodes, i);
00194     singletonArrayOfRoots = array_alloc(Ntk_Node_t *, 0);
00195     array_insert_last(Ntk_Node_t *, singletonArrayOfRoots, node);
00196     singletonMvfArray = Ntm_NetworkBuildMvfs(network, singletonArrayOfRoots, 
00197                                              tableOfLeaves, careSet);
00198     nodeMvf = array_fetch(Mvf_Function_t *, singletonMvfArray, 0);
00199     array_insert_last(Mvf_Function_t *, tmpArrayOfMvf, nodeMvf);
00200     array_free(singletonMvfArray);
00201     array_free(singletonArrayOfRoots);
00202     
00203     if(Ntk_NodeReadMddId(node) == NTK_UNASSIGNED_MDD_ID){
00204       Ord_NetworkAssignMddIdForNode(network, node);
00205     }
00206     st_insert(tableOfLeaves, (char *)node, (char *) (long) (-1) );    
00207     st_insert(mddIdToNodeName, (char *) (long)Ntk_NodeReadMddId(node), 
00208                 Ntk_NodeReadName(node));
00209 
00210   }
00211 
00212 
00213   arrayOfRoots = array_alloc(Ntk_Node_t *, 0);
00214   Ntk_NetworkForEachCombOutput(network, gen, node) {
00215     array_insert_last(Ntk_Node_t *, arrayOfRoots, node);
00216   }
00217   arrayOfMvf = Ntm_NetworkBuildMvfs(network, arrayOfRoots, tableOfLeaves, 
00218                                     careSet);
00219 
00220   array_append(arrayOfRoots, sortedArrayOfPartitionNodes);
00221   array_append(arrayOfMvf, tmpArrayOfMvf);
00222   array_free(sortedArrayOfPartitionNodes);
00223   array_free(tmpArrayOfMvf);
00224 
00225 
00226   /* Create one vertex for every component of arrayOfMvf */
00227   for (i=0; i < array_n(arrayOfRoots); i++) {
00228     node = array_fetch(Ntk_Node_t *, arrayOfRoots, i);
00229     mddId = Ntk_NodeReadMddId(node);
00230 
00231     /* obtain the function attached to the node */
00232     mddFunction = array_fetch(Mvf_Function_t *, arrayOfMvf, i);
00233 
00234 
00235     toVertex = g_add_vertex(partition);
00236     
00237     /* Update the look-up tables in the graph */
00238     st_insert(PartPartitionReadNameToVertex(partition),
00239               Ntk_NodeReadName(node), (char *)toVertex);
00240     if (mddId != -1) {
00241       st_insert(PartPartitionReadMddIdToVertex(partition),
00242                 (char *)(long) mddId, (char *)toVertex);
00243     } 
00244     toVertex->user_data = 
00245       (gGeneric)PartVertexInfoCreateSingle(Ntk_NodeReadName(node), 
00246                                            mddFunction, 
00247                                            mddId);
00248   } 
00249   
00250   /* Read the list of vertices on the graph */
00251   sinkList = lsCopy(g_get_vertices(partition), (lsGeneric (*)(lsGeneric))0);
00252 
00253   /* 
00254    * For every function on every combinational output, compute the
00255    * support and create vertices in the graph when needed 
00256    */
00257   lsForEachItem(sinkList, gen, toVertex) {
00258     mddFunction = PartVertexReadFunction(toVertex);
00259     mddSupport = PartCreateFunctionSupportTable(mddFunction);
00260 
00261     /* 
00262      * Create one edge (and one vertex if necessary) for every element
00263      * in mddSupport 
00264      */
00265     st_foreach_item(mddSupport, stGen, &mddId, NULL) {
00266       char *name;
00267 
00268       /* Create vertex with the information if needed */
00269       if (st_lookup(PartPartitionReadMddIdToVertex(partition), 
00270                     (char *)(long) mddId, &fromVertex) == 0) {
00271         fromVertex = g_add_vertex(partition);
00272         
00273         st_lookup(mddIdToNodeName, (char *)(long) mddId, &name);
00274 
00275         /* Update the look-up tables in the graph */
00276         st_insert(PartPartitionReadNameToVertex(partition), 
00277                   name, (char *)fromVertex);
00278         st_insert(PartPartitionReadMddIdToVertex(partition),
00279                   (char *)(long) mddId, (char *)fromVertex);
00280         
00281         /* Create vertex data */
00282         fromVertex->user_data = 
00283           (gGeneric)PartVertexInfoCreateSingle(name,
00284                                                Mvf_FunctionCreateFromVariable(manager,mddId),
00285                                                mddId);
00286       } 
00287       
00288       /* 
00289        * Add the edge to the graph. Make sure a self loop is not added. The
00290        * self loop may be produced by a mdd that has in its support the same
00291        * variables that represent the mddId of the node.
00292        */
00293       if (fromVertex != toVertex) {
00294         g_add_edge(fromVertex, toVertex);
00295       } /* End of if */
00296       
00297     } /* End of st_foreach_item */
00298     
00299     /* Clean the support table */
00300     st_free_table(mddSupport);
00301   } /* End of lsForEachItem */
00302   
00303   /* Clean up */
00304   st_free_table(mddIdToNodeName);
00305   st_free_table(tableOfLeaves);
00306   array_free(arrayOfRoots);
00307   lsDestroy(sinkList, (void (*)(lsGeneric))0);
00308   /* 
00309    * The contents of this array (array of mdds) is not deallocated because the
00310    * information has been transferred to the partition structure. All the
00311    * functions are stored now as part of the vertex information.
00312    */
00313   array_free(arrayOfMvf);
00314   fprintf(stdout, "NOTICE : current peak memory = %ld\n",
00315   bdd_read_peak_memory(manager));
00316 
00317 } /* End of PartPartitionCut */
00318 
00319 
00331 int 
00332 Part_IsFanoutInverter(Ntk_Node_t *node)
00333 {
00334   Ntk_Node_t *fanout;
00335 
00336   fanout = Part_GetFanoutFreeLogic(node);
00337   if(!fanout)   return(1);
00338   if(Ntk_NodeReadNumFanins(fanout) == 1)        return(1);
00339   else                                  return(0);
00340 
00341 }
00342 
00354 int
00355 Part_CheckLeafNodeCondition(Ntk_Node_t *node, 
00356                             st_table *leafTable,
00357                             int fanoutFreeLimit,
00358                             int numVariableLimit)
00359 {
00360   int nVar, nDepth, i;
00361   Ntk_Node_t *fanout, *tnode, *tfanin;
00362   st_table *ownTable;
00363 
00364 
00365   nVar = Ntk_NodeReadNumFanins(node);
00366   nDepth = 0;
00367   fanout = node;
00368   ownTable = st_init_table(st_ptrcmp, st_ptrhash);
00369   while(1) {
00370     if(nDepth > fanoutFreeLimit)return(1);
00371     if(nVar > numVariableLimit) return(1);
00372 
00373     if(!st_lookup(leafTable, fanout, &tnode)) {
00374        fanout = Part_GetFanoutFreeLogic(fanout);
00375        if(fanout == 0)  break;
00376        if(Ntk_NodeTestIsCombInput(fanout))      break;
00377        if(Ntk_NodeTestIsCombOutput(fanout))     break;
00378     }
00379     else break;
00380     nDepth++;
00381     if(fanout == 0)     break;
00382     nVar += Img_CutCalcTransitiveFanin(leafTable, ownTable, fanout,
00383     node, numVariableLimit);
00384     if(nVar > numVariableLimit) {
00385       st_free_table(ownTable);
00386       return(1);
00387     }
00388   }
00389 
00390   Ntk_NodeForEachFanin(node, i, tfanin) {
00391     if(tfanin == 0)     continue;
00392     if(Ntk_NodeReadNumFanouts(tfanin) != 1)     continue;
00393     nVar += Img_CutCalcTransitiveFanin(leafTable, ownTable, tfanin, 0, numVariableLimit)-1;
00394     if(nVar > numVariableLimit) {       
00395       st_free_table(ownTable);
00396       return(1);
00397     }
00398   }
00399   if(nVar > numVariableLimit) {
00400     st_free_table(ownTable);
00401     return(1);
00402   }
00429   return(0);
00430 }
00431 
00443 int
00444 Img_CutCalcTransitiveFanin(st_table *table, 
00445                            st_table *ownTable,
00446                            Ntk_Node_t *node, 
00447                            Ntk_Node_t *fanin,
00448                            int limit)
00449 {
00450   int i, nVar;
00451   Ntk_Node_t *tfanin, *tnode;
00452 
00453   nVar = 0;
00454   Ntk_NodeForEachFanin(node, i, tfanin) {
00455     if(tfanin == fanin) continue;
00456     if(tfanin == 0)     continue;
00457     if(Ntk_NodeReadNumFanouts(tfanin) != 1){
00458       if(!st_lookup(ownTable, tfanin, &tnode)) {
00459         st_insert(ownTable, tfanin, tfanin);
00460         nVar++;
00461       }
00462       continue;
00463     }
00464     if(Ntk_NodeTestIsCombInput(tfanin)) {
00465       if(!st_lookup(ownTable, tfanin, &tnode)) {
00466         st_insert(ownTable, tfanin, tfanin);
00467         nVar++;
00468       }
00469       continue;
00470     }
00471     if(Ntk_NodeTestIsCombOutput(tfanin)) {
00472       if(!st_lookup(ownTable, tfanin, &tnode)) {
00473         st_insert(ownTable, tfanin, tfanin);
00474         nVar++;
00475       }
00476       continue;
00477     }
00478     if(!st_lookup(table, tfanin, &tnode)) {
00479       nVar += Img_CutCalcTransitiveFanin(table, ownTable, tfanin,  0, limit);
00480     }
00481     else
00482       nVar++;
00483     if(nVar > limit)    return(nVar);
00484   }
00485   return(nVar);
00486 }
00487 
00499 Ntk_Node_t *
00500 Part_GetFaninFreeLogic(Ntk_Node_t *node)
00501 {
00502   int i;
00503   Ntk_Node_t *fanin;
00504 
00505   Ntk_NodeForEachFanin(node, i, fanin) {
00506     if(Ntk_NodeReadNumFanouts(fanin) != 1)      continue;
00507     return(fanin); 
00508   }
00509   return(0);
00510 }
00511 
00523 Ntk_Node_t *
00524 Part_GetFanoutFreeLogic(Ntk_Node_t *node)
00525 {
00526   int i;
00527   Ntk_Node_t *fanout;
00528 
00529   if(Ntk_NodeReadNumFanouts(node) != 1) return(0);
00530   Ntk_NodeForEachFanout(node, i, fanout) {
00531     return(fanout); 
00532   }
00533   return(0);
00534 }