VIS
|
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 }