VIS

src/ntk/ntkSweep.c

Go to the documentation of this file.
00001 
00036 #include "ntkInt.h"
00037 
00038 static char rcsid[] UNUSED = "$Id: ntkSweep.c,v 1.18 2010/04/09 23:44:05 fabio Exp $";
00039 
00040 /*comment */
00041 
00042 /*---------------------------------------------------------------------------*/
00043 /* Constant declarations                                                     */
00044 /*---------------------------------------------------------------------------*/
00045 
00046 
00047 /*---------------------------------------------------------------------------*/
00048 /* Type declarations                                                         */
00049 /*---------------------------------------------------------------------------*/
00050 
00051 
00052 /*---------------------------------------------------------------------------*/
00053 /* Structure declarations                                                    */
00054 /*---------------------------------------------------------------------------*/
00055 
00056 
00057 /*---------------------------------------------------------------------------*/
00058 /* Variable declarations                                                     */
00059 /*---------------------------------------------------------------------------*/
00060 
00061 
00062 /*---------------------------------------------------------------------------*/
00063 /* Macro declarations                                                        */
00064 /*---------------------------------------------------------------------------*/
00065 
00068 /*---------------------------------------------------------------------------*/
00069 /* Static function prototypes                                                */
00070 /*---------------------------------------------------------------------------*/
00071 
00072 static void NetworkCollapseConstantNode(Ntk_Network_t *network, Ntk_Node_t *node);
00073 static void NetworkCollapseIdentityNode(Ntk_Network_t *network, Ntk_Node_t *node);
00074 static void NetworkCollapseInverterNode(Ntk_Network_t *network, Ntk_Node_t *node);
00075 static int NodeRemoveFanout(Ntk_Node_t *node, Ntk_Node_t *delFanoutNode);
00076 
00080 /*---------------------------------------------------------------------------*/
00081 /* Definition of exported functions                                          */
00082 /*---------------------------------------------------------------------------*/
00083 
00084 
00098 void
00099 Ntk_NetworkSweep(Ntk_Network_t *network, int verbosity)
00100 {
00101   lsList nodeList;
00102   Ntk_Node_t *node;
00103   lsGen gen;
00104   array_t *rootArray = array_alloc(Ntk_Node_t *,
00105                                    Ntk_NetworkReadNumCombOutputs(network));
00106   st_table *leafNodesTable = st_init_table(st_ptrcmp, st_ptrhash);
00107   int count = 0;
00108 
00109   /* Get a topologically sorted list of all nodes so that one pass
00110      through the network is enough to remove all constant nodes. */
00111   Ntk_NetworkForEachNode(network, gen, node) {
00112     if (Ntk_NodeTestIsPrimaryOutput(node)
00113         || Ntk_NodeTestIsLatchDataInput(node)
00114         || Ntk_NodeReadNumFanouts(node) == 0)
00115       array_insert_last(Ntk_Node_t *, rootArray, node);
00116     if (Ntk_NodeTestIsInput(node) || Ntk_NodeReadNumFanins(node) == 0)
00117       st_insert(leafNodesTable, node, NIL(char));
00118   }
00119   nodeList = Ntk_NetworkComputeTopologicalOrder(network, rootArray,
00120                                                 leafNodesTable);
00121   /* Check that all nodes are included. */
00122   assert(lsLength(nodeList) == lsLength(network->nodes));
00123   array_free(rootArray);
00124   st_free_table(leafNodesTable);
00125 
00126   /* Check for constants, identities and inverters. */
00127   lsForEachItem(nodeList, gen, node) {
00128     char *name = Ntk_NodeReadName(node);
00129     /* Try to remove only nodes created by vl2mv. */
00130     if (name[0] != '_' && strstr(name, "._") == NIL(char) &&
00131         strstr(name, "$") == NIL(char)) continue;
00132     if (Ntk_NodeTestIsConstant(node) == TRUE) {
00133       if (Ntk_NodeReadNumFanins(node) == 0) {
00134         NetworkCollapseConstantNode(network, node);
00135         if (Ntk_NodeReadNumFanouts(node) == 0) {
00136           if (Ntk_NodeRemoveFromNetwork(network,node,0,0,verbosity) == TRUE) {
00137             lsDelBefore(gen, &node);
00138             Ntk_NodeFree(node);
00139             count++;
00140           }
00141         }
00142       }
00143     } else if (Ntk_NodeTestIsCombinational(node)) {
00144       if (!Ntk_NodeTestIsCombOutput(node)) {
00145         Tbl_Table_t *table = Ntk_NodeReadTable(node);
00146         if (Tbl_TableIsIdentity(table)) {
00147           NetworkCollapseIdentityNode(network, node);
00148           if (Ntk_NodeRemoveFromNetwork(network,node,1,0,verbosity) == TRUE) {
00149             lsDelBefore(gen, &node);
00150             Ntk_NodeFree(node);
00151             count++;
00152           }
00153         } else if (Tbl_TableIsInverter(table)) {
00154           NetworkCollapseInverterNode(network, node);
00155           if (Ntk_NodeReadNumFanins(node) == 0) {
00156             if (Ntk_NodeRemoveFromNetwork(network,node,0,0,verbosity) == TRUE) {
00157               lsDelBefore(gen, &node);
00158               Ntk_NodeFree(node);
00159               count++;
00160             }
00161           }
00162         }
00163       }
00164     }
00165   }
00166 
00167   if (verbosity > 0) {
00168     fprintf(vis_stderr,"Removed %d node%s\n", count, count == 1 ? "" : "s");
00169   }
00170 
00171   (void) lsDestroy(network->nodes,(void (*) (lsGeneric)) NULL);
00172   network->nodes = nodeList;
00173 
00174   if (verbosity > 0) {
00175     Ntk_NetworkWriteBlifMv(vis_stdout, network, TRUE);
00176   }
00177 
00178 } /* Ntk_NetworkSweep */
00179 
00180 
00194 boolean
00195 Ntk_NodeRemoveFromNetwork(Ntk_Network_t *network, Ntk_Node_t *node,
00196                           int force, boolean removeFromNodeList, int verbosity)
00197 {
00198   if (!force) {
00199     assert(Ntk_NodeReadNumFanins(node) == 0);
00200     assert(Ntk_NodeReadNumFanouts(node) == 0);
00201 
00202     if (Ntk_NodeTestIsPrimaryOutput(node)==TRUE) {
00203       return FALSE;
00204     }
00205     if (Ntk_NodeTestIsLatch(node)==TRUE) {
00206       return FALSE;
00207     }
00208     if (Ntk_NodeTestIsPrimaryInput(node)==TRUE) {
00209       return FALSE;
00210     }
00211   }
00212 
00213   if (verbosity) {
00214     fprintf(vis_stdout, "** ntk info: Node Removed %s\n", node->name);
00215   }
00216 
00217   node->network = NIL(Ntk_Network_t);
00218   if (Ntk_NodeTestIsCombOutput(node)) {
00219     NtkNodeDeleteFromList(network->combOutputs, node);
00220     st_delete(network->combOutputsTable, &node, NULL);
00221   }
00222   if (Ntk_NodeTestIsCombInput(node)) {
00223     NtkNodeDeleteFromList(network->combInputs, node);
00224   }
00225 
00226   st_delete(network->actualNameToNode, &(node->name), NIL(char *));
00227   /* BALA: I don't understand why the following line was not present
00228      earlier. */
00229   /* When this function is called by Ntk_NetworkSweep, it is not
00230      necessary to remove the node from the network's node list because
00231      the node list is re-generated regardless.  In addition, it may
00232      get very expensive.
00233    */
00234   if (removeFromNodeList)
00235     NtkNodeDeleteFromList(network->nodes, node);
00236 
00237   switch(node->type) {
00238     case NtkShadow_c:
00239       break;
00240     case NtkPseudoInput_c:
00241       NtkNodeDeleteFromList(network->inputs, node);
00242       NtkNodeDeleteFromList(network->pseudoInputs, node);
00243       break;
00244     case NtkCombinational_c:
00245       break;
00246     case NtkUnassigned_c:
00247       break;
00248     case NtkLatch_c:
00249       NtkNodeDeleteFromList(network->latches, node);
00250       break;
00251   case NtkPrimaryInput_c:
00252       NtkNodeDeleteFromList(network->primaryInputs, node);
00253       break;
00254       /*
00255     default:
00256     fail("Type cannot be deleted");*/
00257   }
00258 
00259   /* for PO */
00260   if (Ntk_NodeTestIsPrimaryOutput(node)==TRUE)
00261       NtkNodeDeleteFromList(network->primaryOutputs, node);
00262 
00263   return TRUE;
00264 }
00265 
00266 
00267 /*---------------------------------------------------------------------------*/
00268 /* Definition of internal functions                                          */
00269 /*---------------------------------------------------------------------------*/
00270 
00283 boolean
00284 NtkNodeDeleteFromList(
00285   lsList nodeList,
00286   Ntk_Node_t *node)
00287 {
00288 
00289   lsGen gen;
00290   lsGeneric data;
00291   Ntk_Node_t *listnode;
00292   Ntk_Node_t *delNode;
00293   boolean check;
00294   int i;
00295 
00296   check = FALSE;
00297   i = 0;
00298   lsForEachItem(nodeList, gen, listnode) {
00299     if (node == listnode) {
00300       if (i > 0)
00301         lsDelBefore(gen, &data);
00302       else
00303         lsDelBegin(nodeList, &data);
00304       check = TRUE;
00305     }
00306     i++;
00307   }
00308   delNode = (Ntk_Node_t*)data;
00309 
00310   assert(delNode == node);
00311   assert(check);
00312   return check;
00313 }
00314 
00315 /*---------------------------------------------------------------------------*/
00316 /* Definition of static functions                                            */
00317 /*---------------------------------------------------------------------------*/
00332 static void
00333 NetworkCollapseConstantNode(Ntk_Network_t *network, Ntk_Node_t *node)
00334 {
00335   Tbl_Table_t *table, *newtable;
00336   Ntk_Node_t *fanout, *fanin;
00337   int i,j,index;
00338   array_t *newFaninArray;
00339   array_t *tmpFanoutArray;
00340 
00341   table = Ntk_NodeReadTable(node);
00342 
00343   tmpFanoutArray = array_dup(Ntk_NodeReadFanouts(node));
00344   arrayForEachItem(Ntk_Node_t *, tmpFanoutArray, i, fanout) {
00345     if (fanout->type == NtkCombinational_c) {
00346       index = Ntk_NodeReadFaninIndex(fanout,node);
00347       while (index != NTK_UNDEFINED_FANIN_INDEX) {
00348         Tbl_Table_t *fantable = Ntk_NodeReadTable(fanout);
00349 
00350         NodeRemoveFanout(node,fanout);
00351         newtable = Tbl_TableCollapse(fantable,table,index);
00352         Tbl_TableFree(fantable);
00353         Ntk_NodeSetTable(fanout, newtable);
00354 
00355         if (Tbl_TableTestIsConstant(fanout->table, 0)) {
00356           fanout->constant = TRUE;
00357         }
00358 
00359         newFaninArray = array_alloc(Ntk_Node_t*, 0);
00360         Ntk_NodeForEachFanin(fanout, j, fanin) {
00361           if (j != index) {
00362             array_insert_last(Ntk_Node_t*, newFaninArray, fanin);
00363           }
00364         }
00365         array_free(fanout->fanins);
00366         fanout->fanins = newFaninArray;
00367 
00368         index = Ntk_NodeReadFaninIndex(fanout, node);
00369       }
00370     }
00371   }
00372   array_free(tmpFanoutArray);
00373 
00374   Ntk_NodeForEachFanin(node, i, fanin) {
00375     NodeRemoveFanout(fanin, node);
00376   }
00377 
00378   array_free(node->fanins);
00379   node->fanins = array_alloc(Ntk_Node_t*, 0);
00380 
00381 }
00382 
00383 
00398 static void
00399 NetworkCollapseIdentityNode(Ntk_Network_t *network, Ntk_Node_t *node)
00400 {
00401   Ntk_Node_t *fanout, *fanin;
00402   Var_Variable_t *invar, *outvar;
00403   int i;
00404 
00405   fanin = Ntk_NodeReadFaninNode(node, 0);
00406   invar = Ntk_NodeReadVariable(fanin);
00407   outvar = Ntk_NodeReadVariable(node);
00408   NodeRemoveFanout(fanin, node);
00409   /* array_remove_last(Ntk_NodeReadFanins(node)); */
00410 
00411   Ntk_NodeForEachFanout(node, i, fanout) {
00412     int index = Ntk_NodeReadFaninIndex(fanout,node);
00413     /* Since a node may be connected to another node multiple times,
00414      * we iterate until node is not found any more.
00415      */
00416     while (index != NTK_UNDEFINED_FANIN_INDEX) {
00417       if (fanout->type == NtkCombinational_c) {
00418         Tbl_Table_t *fantable = Ntk_NodeReadTable(fanout);
00419         Tbl_TableSubstituteVar(fantable, outvar, invar);
00420       }
00421       /* NodeRemoveFanout(node,fanout); */
00422 
00423       /* Replace node with its input node in the fanins of fanout. */
00424       array_insert(Ntk_Node_t *, Ntk_NodeReadFanins(fanout), index, fanin);
00425       array_insert_last(Ntk_Node_t*, Ntk_NodeReadFanouts(fanin), fanout);
00426 
00427       index = Ntk_NodeReadFaninIndex(fanout, node);
00428     }
00429   }
00430 
00431 } /* NetworkCollapseIdentityNode */
00432 
00433 
00448 static void
00449 NetworkCollapseInverterNode(Ntk_Network_t *network, Ntk_Node_t *node)
00450 {
00451   Ntk_Node_t *fanout, *fanin;
00452   Var_Variable_t *invar, *outvar;
00453   int i;
00454   boolean failure = FALSE;
00455   array_t *dupFanoutArray;
00456 
00457   assert(Ntk_NodeReadNumFanins(node) == 1);
00458   fanin = Ntk_NodeReadFaninNode(node, 0);
00459   invar = Ntk_NodeReadVariable(fanin);
00460   outvar = Ntk_NodeReadVariable(node);
00461 
00462   dupFanoutArray = array_dup(Ntk_NodeReadFanouts(node));
00463   arrayForEachItem(Ntk_Node_t *, dupFanoutArray, i, fanout) {
00464     if (fanout->type == NtkCombinational_c) {
00465       int index = Ntk_NodeReadFaninIndex(fanout,node);
00466       /* Since a node may be connected to another node multiple times,
00467        * we iterate until node is not found any more.
00468        */
00469       while (index != NTK_UNDEFINED_FANIN_INDEX) {
00470         Tbl_Table_t *fantable = Ntk_NodeReadTable(fanout);
00471         Tbl_Table_t *newTable =
00472           Tbl_TableInvertBinaryInputColumn(fantable, index);
00473         if (newTable != NIL(Tbl_Table_t)) {
00474           Tbl_TableFree(fantable);
00475           Tbl_TableSubstituteVar(newTable, outvar, invar);
00476           Ntk_NodeSetTable(fanout, newTable);
00477           NodeRemoveFanout(node, fanout);
00478 
00479           /* Replace node with its input node in the fanins of fanout. */
00480           array_insert(Ntk_Node_t *, Ntk_NodeReadFanins(fanout), index, fanin);
00481           array_insert_last(Ntk_Node_t*, Ntk_NodeReadFanouts(fanin), fanout);
00482         } else {
00483           failure = TRUE;
00484           /* Test: */ fprintf(vis_stdout, "achtung!\n");
00485         }
00486         index = Ntk_NodeReadFaninIndex(fanout, node);
00487       }
00488     } else {
00489       failure = TRUE;
00490     }
00491   }
00492   array_free(dupFanoutArray);
00493 
00494   if (!failure) {
00495     NodeRemoveFanout(fanin, node);
00496     array_remove_last(Ntk_NodeReadFanins(node));
00497   }
00498 
00499 } /* NetworkCollapseInverterNode */
00500 
00501 
00515 static int
00516 NodeRemoveFanout(
00517   Ntk_Node_t *node,
00518   Ntk_Node_t *delFanoutNode)
00519 {
00520   array_t *newFanoutArray;
00521   Ntk_Node_t *fanout, *fanin;
00522   int j;
00523 
00524   if (node == NIL(Ntk_Node_t))
00525     return(0);
00526 
00527   newFanoutArray = array_alloc(Ntk_Node_t*, 0);
00528   Ntk_NodeForEachFanout(node, j, fanout) {
00529     if (fanout != delFanoutNode) {
00530       array_insert_last(Ntk_Node_t*, newFanoutArray, fanout);
00531     }
00532   }
00533   array_free(node->fanouts);
00534   node->fanouts = newFanoutArray;
00535 
00536   Ntk_NodeForEachFanin(delFanoutNode, j, fanin) {
00537     if (fanin == node) {
00538       array_insert(Ntk_Node_t*, delFanoutNode->fanins, j, NIL(Ntk_Node_t));
00539       /* to break not to delete another fanin if any */
00540       j = Ntk_NodeReadNumFanins(delFanoutNode);
00541     }
00542   }
00543 
00544   return(1);
00545 }