VIS
|
00001 00032 #include "ordInt.h" 00033 00034 static char rcsid[] UNUSED = "$Id: ordMain.c,v 1.17 2005/04/16 06:15:25 fabio Exp $"; 00035 00036 /*---------------------------------------------------------------------------*/ 00037 /* Constant declarations */ 00038 /*---------------------------------------------------------------------------*/ 00039 00040 /*---------------------------------------------------------------------------*/ 00041 /* Structure declarations */ 00042 /*---------------------------------------------------------------------------*/ 00043 00046 /*---------------------------------------------------------------------------*/ 00047 /* Static function prototypes */ 00048 /*---------------------------------------------------------------------------*/ 00049 00050 static int NodesCompareDepth(Ntk_Node_t *node1, Ntk_Node_t *node2); 00051 static long NodeComputeDepth(Ntk_Node_t * node); 00052 static void NetworkAddDanglingNodesToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle); 00053 static void NetworkAddNSVarsToOrderList(Ntk_Network_t * network, lsList nodeOrderList, st_table *nodeToHandle, boolean nsAfterSupport); 00054 static lsList LatchNSListConvertToLatchDataInputList(lsList latchNSList); 00055 static void NodeSetDepth(Ntk_Node_t * node, long depth); 00056 static void MddGroupVariables(mdd_manager *mddMgr, int initMddId, int blockSize); 00057 00061 /*---------------------------------------------------------------------------*/ 00062 /* Definition of exported functions */ 00063 /*---------------------------------------------------------------------------*/ 00064 00109 void 00110 Ord_NetworkOrderVariables( 00111 Ntk_Network_t *network, 00112 Ord_RootMethod rootOrderMethod, 00113 Ord_NodeMethod nodeOrderMethod, 00114 boolean nsAfterSupport, 00115 Ord_OrderType generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */, 00116 Ord_OrderType suppliedOrderType /* no restrictions */, 00117 lsList suppliedNodeList /* list of nodes Ntk_Node_t* from ordering file */, 00118 int verbose) 00119 { 00120 lsList totalOrderList; /* list of nodes (Ntk_Node_t *) */ 00121 long initialTime = util_cpu_time(); 00122 00123 /* 00124 * The condition where suppliedOrderType==InputAndLatch and 00125 * generatedOrderType==All is not currently allowed because we're not sure 00126 * if it's useful. 00127 */ 00128 assert(!((suppliedOrderType == Ord_InputAndLatch_c) 00129 && (generatedOrderType == Ord_All_c))); 00130 00131 /* 00132 * Either get a total ordering of the network nodes from suppliedNodeList, 00133 * or compute it working from the network. 00134 */ 00135 if ((suppliedOrderType == Ord_All_c) 00136 || (suppliedOrderType == Ord_InputAndLatch_c)) { 00137 totalOrderList = lsCopy(suppliedNodeList, 00138 (lsGeneric (*) (lsGeneric)) NULL); 00139 } 00140 else { 00141 totalOrderList = Ord_NetworkOrderNodes(network, rootOrderMethod, 00142 nodeOrderMethod, nsAfterSupport, 00143 generatedOrderType, 00144 suppliedOrderType, 00145 suppliedNodeList, 00146 verbose); 00147 } 00148 00149 00150 OrdNetworkAssignMddIds(network, generatedOrderType, totalOrderList, nsAfterSupport); 00151 (void) lsDestroy(totalOrderList, (void (*) (lsGeneric)) NULL); 00152 00153 /* 00154 * If nsAfterSupport is FALSE, this implies that NS comes right after PS. 00155 * 00156 */ 00157 if ( nsAfterSupport == FALSE ) { 00158 lsGen tmpGen; 00159 Ntk_Node_t *tmpLatch; 00160 00161 /* 00162 * Iterate over each latch, and group the PS variable with the next 00163 * variable in the ordering, which is guaranteed to be the corresponding NS 00164 * variable. 00165 */ 00166 Ntk_NetworkForEachLatch(network, tmpGen, tmpLatch) { 00167 mdd_manager *mddMgr = Ntk_NetworkReadMddManager( network ); 00168 Ntk_Node_t *nsNode = Ntk_NodeReadShadow( tmpLatch ); 00169 int psMddId = Ntk_NodeReadMddId( tmpLatch ); 00170 int nsMddId = Ntk_NodeReadMddId( nsNode ); 00171 00172 /* 00173 * Group size = 2 ( ps and ns ) 00174 */ 00175 if (nsMddId == (psMddId+1)) { 00176 MddGroupVariables(mddMgr, psMddId, 2); 00177 } 00178 /* Adnan's fix: See his mail to vis@ic on Oct 24, 1997 */ 00179 if (nsMddId == (psMddId-1)) { 00180 MddGroupVariables(mddMgr, nsMddId, 2); 00181 } 00182 } 00183 } 00184 00185 if (verbose > 0) { 00186 long finalTime = util_cpu_time(); 00187 (void) fprintf(vis_stdout, "\nTotal ordering time = %2.1f\n", 00188 (finalTime-initialTime)/1000.0); 00189 } 00190 } 00191 00192 00234 lsList 00235 Ord_NetworkOrderNodes( 00236 Ntk_Network_t *network, 00237 Ord_RootMethod rootOrderMethod, 00238 Ord_NodeMethod nodeOrderMethod, 00239 boolean nsAfterSupport, 00240 Ord_OrderType generatedOrderType /* Ord_All_c or Ord_InputAndLatch_c */, 00241 Ord_OrderType suppliedOrderType /* Ord_NextStateNode_c, Ord_Partial_c, or 00242 Ord_Unassigned_c */, 00243 lsList suppliedNodeList /* list of nodes Ntk_Node_t* from ordering file */, 00244 int verbose) 00245 { 00246 lsList partialRootOrder; /* list of nodes (Ntk_Node_t *) */ 00247 lsList roots; /* list of nodes (Ntk_Node_t *) */ 00248 lsList nodeOrderList; /* list of nodes (Ntk_Node_t *) */ 00249 st_table *nodeToHandle; /* Ntk_Node_t* to lsHandle */ 00250 00251 /* 00252 * Check the input arguments. 00253 */ 00254 assert( (generatedOrderType == Ord_All_c) 00255 || (generatedOrderType == Ord_InputAndLatch_c)); 00256 00257 assert( (suppliedOrderType == Ord_NextStateNode_c) 00258 || (suppliedOrderType == Ord_Partial_c) 00259 || (suppliedOrderType == Ord_Unassigned_c)); 00260 00261 00262 /* 00263 * Compute an ordering on the roots. The nodes of the network are explored 00264 * in DFS order from the roots, in the root order computed. If 00265 * suppliedOrderType is Ord_NextStateNode_c, then suppliedNodeList contains 00266 * the next state nodes; this list serves as a seed to compute the root 00267 * ordering. 00268 */ 00269 partialRootOrder = (suppliedOrderType == Ord_NextStateNode_c) 00270 ? LatchNSListConvertToLatchDataInputList(suppliedNodeList) 00271 : (lsList) NULL; 00272 roots = Ord_NetworkOrderRoots(network, rootOrderMethod, 00273 partialRootOrder, verbose); 00274 if (suppliedOrderType == Ord_NextStateNode_c) { 00275 (void) lsDestroy(partialRootOrder, (void (*) (lsGeneric)) NULL); 00276 } 00277 if (verbose > 0) { 00278 (void) fprintf(vis_stdout, "\nOrder in which roots are visited:\n"); 00279 OrdNodeListWrite(vis_stdout, roots); 00280 } 00281 00282 /* 00283 * Compute an order on all nodes in the transitive fanin of roots, including 00284 * the roots themselves. Pass in an empty nodeToHandle table. 00285 */ 00286 nodeToHandle = st_init_table(st_ptrcmp, st_ptrhash); 00287 nodeOrderList = OrdNetworkOrderTFIOfRoots(network, roots, nodeOrderMethod, 00288 nodeToHandle, verbose); 00289 (void) lsDestroy(roots, (void (*) (lsGeneric)) NULL); 00290 00291 if (verbose > 0) { 00292 (void) fprintf(vis_stdout, "\nOrder of network nodes without NS:\n"); 00293 OrdNodeListWrite(vis_stdout, nodeOrderList); 00294 } 00295 00296 /* 00297 * Add in the next state variables (represented by the shadow nodes of 00298 * latches). 00299 */ 00300 NetworkAddNSVarsToOrderList(network, nodeOrderList, nodeToHandle, nsAfterSupport); 00301 if (verbose > 2) { 00302 (void) fprintf(vis_stdout, "\nOrder of network nodes with NS:\n"); 00303 OrdNodeListWrite(vis_stdout, nodeOrderList); 00304 } 00305 00306 00307 /* 00308 * There may be some nodes that are not in the TFI of any root. Put such 00309 * nodes at the end of nodeOrderList (in no particular order). 00310 */ 00311 NetworkAddDanglingNodesToOrderList(network, nodeOrderList, nodeToHandle); 00312 st_free_table(nodeToHandle); 00313 00314 /* 00315 * If the suppliedOrderType is Partial, then merge (left, arbitrarily) the 00316 * computed node order into the supplied node order and return the result. 00317 * Otherwise, just return the nodeOrderList computed. 00318 */ 00319 if (suppliedOrderType == Ord_Partial_c) { 00320 lsList suppliedNodeListCopy = lsCopy(suppliedNodeList, 00321 (lsGeneric (*) (lsGeneric)) NULL); 00322 00323 Ord_ListMergeList(suppliedNodeListCopy, nodeOrderList, Ord_ListMergeLeft_c); 00324 (void) lsDestroy(nodeOrderList, (void (*) (lsGeneric)) NULL); 00325 return suppliedNodeListCopy; 00326 } 00327 else { 00328 return nodeOrderList; 00329 } 00330 } 00331 00332 00350 void 00351 Ord_NetworkAssignMddIdForNode( 00352 Ntk_Network_t *network, 00353 Ntk_Node_t *node) 00354 { 00355 if (Ntk_NodeReadMddId(node) != NTK_UNASSIGNED_MDD_ID) { 00356 return; 00357 } 00358 else { 00359 int mddId; 00360 mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); 00361 array_t *mvarValues = array_alloc(int, 0); 00362 array_t *mvarNames = array_alloc(char *, 0); 00363 00364 /* 00365 * If the network doesn't already have an MDD manager, then create one. In 00366 * any case, set mddId to be the number of variables currently existing in 00367 * the manager. 00368 */ 00369 if (mddManager == NIL(mdd_manager)) { 00370 mddManager = Ntk_NetworkInitializeMddManager(network); 00371 mddId = 0; 00372 } 00373 else { 00374 array_t *mvarArray = mdd_ret_mvar_list(mddManager); 00375 mddId = array_n(mvarArray); 00376 } 00377 00378 Ntk_NodeSetMddId(node, mddId); 00379 00380 array_insert_last(int, mvarValues, 00381 Var_VariableReadNumValues(Ntk_NodeReadVariable(node))); 00382 array_insert_last(char *, mvarNames, Ntk_NodeReadName(node)); 00383 00384 /* 00385 * Create the variable in the MDD manager. The last argument being NIL 00386 * means that the variable will not be interleaved. 00387 */ 00388 mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t)); 00389 00390 array_free(mvarValues); 00391 array_free(mvarNames); 00392 } 00393 } 00394 00395 00431 void 00432 Ord_ListMergeLeftListUsingTable( 00433 lsList list1, 00434 lsList list2, 00435 st_table *dataToHandle1) 00436 { 00437 lsGen gen1; /* generator for list1 */ 00438 lsGen gen2; /* generator for list2 */ 00439 lsHandle handle; /* handle of an item in list1 */ 00440 lsGeneric data; 00441 lsGeneric prevData; 00442 00443 /* 00444 * Walk through list2 forwards, keeping track of the previous item just visited. 00445 */ 00446 gen2 = lsStart(list2); 00447 prevData = NULL; 00448 while (lsNext(gen2, &data, LS_NH) == LS_OK) { 00449 00450 if (!st_is_member(dataToHandle1, (char *) data)) { 00451 /* 00452 * Data is not present in list1, so we must insert it at the proper 00453 * location. 00454 */ 00455 if (prevData == NULL) { 00456 /* 00457 * Data is the head of list2, so insert it at the head of list1. 00458 */ 00459 (void) lsNewBegin(list1, data, &handle); 00460 } 00461 else { 00462 lsGeneric dummyData; 00463 lsHandle prevHandle; 00464 00465 /* 00466 * Data is not the head of list1. Hence, insert it just to the right 00467 * of the location of prevData in list1 (by induction, prevData must 00468 * currently exist in list1). Do this by getting the handle of 00469 * prevData in list1, creating a generator initialized to just after 00470 * prevData, and then inserting data at this point. Note that 00471 * lsInAfter and lsInBefore are equivalent in this case, since we 00472 * immediately kill gen1. 00473 */ 00474 st_lookup(dataToHandle1, prevData, &prevHandle); 00475 gen1 = lsGenHandle(prevHandle, &dummyData, LS_AFTER); 00476 (void) lsInAfter(gen1, data, &handle); 00477 (void) lsFinish(gen1); 00478 } 00479 st_insert(dataToHandle1, data, handle); 00480 00481 } /* else, data already present in list1, so do nothing */ 00482 00483 prevData = data; 00484 00485 } /* end while */ 00486 (void) lsFinish(gen2); 00487 } 00488 00489 00521 void 00522 Ord_ListMergeRightListUsingTable( 00523 lsList list1, 00524 lsList list2, 00525 st_table *dataToHandle1) 00526 { 00527 lsGen gen1; /* generator for list1 */ 00528 lsGen gen2; /* generator for list2 */ 00529 lsHandle handle; /* handle of an item in list1 */ 00530 lsGeneric data; 00531 lsGeneric succData; 00532 00533 /* 00534 * Walk through list2 backwards, keeping track of the successor item just visited. 00535 */ 00536 gen2 = lsEnd(list2); 00537 succData = NULL; 00538 while (lsPrev(gen2, &data, LS_NH) == LS_OK) { 00539 00540 if (!st_is_member(dataToHandle1, (char *) data)) { 00541 /* 00542 * Data is not present in list1, so we must insert it at the proper 00543 * location. 00544 */ 00545 if (succData == NULL) { 00546 /* 00547 * Data is the tail of list2, so insert it at the tail of list1. 00548 */ 00549 (void) lsNewEnd(list1, data, &handle); 00550 } 00551 else { 00552 lsGeneric dummyData; 00553 lsHandle succHandle; 00554 00555 /* 00556 * Data is not the tail of list1. Hence, insert it just to the left 00557 * of the location of succData in list1 (by induction, succData must 00558 * currently exist in list1). Do this by getting the handle of 00559 * succData in list1, creating a generator initialized to just before 00560 * succData, and then inserting data at this point. Note that 00561 * lsInAfter and lsInBefore are equivalent in this case, since we are 00562 * immediately kill gen1. 00563 */ 00564 st_lookup(dataToHandle1, succData, &succHandle); 00565 gen1 = lsGenHandle(succHandle, &dummyData, LS_BEFORE); 00566 (void) lsInAfter(gen1, data, &handle); 00567 (void) lsFinish(gen1); 00568 } 00569 st_insert(dataToHandle1, data, handle); 00570 00571 } /* else, data already present in list1, so do nothing */ 00572 00573 succData = data; 00574 00575 } /* end while */ 00576 (void) lsFinish(gen2); 00577 } 00578 00579 00593 void 00594 Ord_ListMergeListUsingTable( 00595 lsList list1, 00596 lsList list2, 00597 st_table *dataToHandle1, 00598 Ord_ListMergeMethod method) 00599 { 00600 if (method == Ord_ListMergeLeft_c) { 00601 Ord_ListMergeLeftListUsingTable(list1, list2, dataToHandle1); 00602 } 00603 else if (method == Ord_ListMergeRight_c) { 00604 Ord_ListMergeRightListUsingTable(list1, list2, dataToHandle1); 00605 } 00606 else { 00607 fail("unrecognized method"); 00608 } 00609 } 00610 00611 00624 void 00625 Ord_ListMergeList( 00626 lsList list1, 00627 lsList list2, 00628 Ord_ListMergeMethod method) 00629 { 00630 lsGen gen1; /* generator for list1 */ 00631 lsHandle handle; /* handle of an item in list1 */ 00632 lsGeneric data; 00633 st_table *dataToHandle1 = st_init_table(st_ptrcmp, st_ptrhash); 00634 00635 /* 00636 * Load a hash table mapping each item in list1 to its handle in list1. 00637 */ 00638 gen1 = lsStart(list1); 00639 while (lsNext(gen1, &data, &handle) == LS_OK) { 00640 st_insert(dataToHandle1, (char *) data, (char *) handle); 00641 } 00642 (void) lsFinish(gen1); 00643 00644 Ord_ListMergeListUsingTable(list1, list2, dataToHandle1, method); 00645 00646 st_free_table(dataToHandle1); 00647 } 00648 00649 00660 void 00661 Ord_ListAppendList( 00662 lsList list1, 00663 lsList list2) 00664 { 00665 lsGen gen; 00666 lsHandle handle; /* unused */ 00667 lsGeneric data; 00668 00669 /* 00670 * Walk through list2 forwards, inserting each element to the end of list1. 00671 */ 00672 gen = lsStart(list2); 00673 while (lsNext(gen, &data, LS_NH) == LS_OK) { 00674 (void) lsNewEnd(list1, data, &handle); 00675 } 00676 (void) lsFinish(gen); 00677 } 00678 00679 00680 /*---------------------------------------------------------------------------*/ 00681 /* Definition of internal functions */ 00682 /*---------------------------------------------------------------------------*/ 00683 00694 int 00695 OrdNodesFromListCompareDepth( 00696 lsGeneric node1, 00697 lsGeneric node2) 00698 { 00699 return NodesCompareDepth((Ntk_Node_t *) node1, (Ntk_Node_t *) node2); 00700 } 00701 00702 00713 int 00714 OrdNodesFromArrayCompareDepth( 00715 const void * node1, 00716 const void * node2) 00717 { 00718 return NodesCompareDepth(*(Ntk_Node_t **) node1, *(Ntk_Node_t **) node2); 00719 } 00720 00721 00738 void 00739 OrdNetworkComputeNodeDepths( 00740 Ntk_Network_t * network, 00741 lsList roots /* list of Ntk_Node_t */) 00742 { 00743 lsGen gen; 00744 Ntk_Node_t *node; 00745 Ntk_Node_t *root; 00746 00747 /* 00748 * Initialize the depth of each node to unassigned. 00749 */ 00750 Ntk_NetworkForEachNode(network, gen, node) { 00751 NodeSetDepth(node, ORDUNASSIGNED_DEPTH); 00752 } 00753 00754 /* 00755 * Start the recursive computation from each root. 00756 */ 00757 lsForEachItem(roots, gen, root) { 00758 (void) NodeComputeDepth(root); 00759 } 00760 } 00761 00762 00770 void 00771 OrdNodeListWrite( 00772 FILE *fp, 00773 lsList nodeList) 00774 { 00775 lsGen gen; 00776 Ntk_Node_t *node; 00777 00778 lsForEachItem(nodeList, gen, node) { 00779 (void) fprintf(fp, "%s\n", Ntk_NodeReadName(node)); 00780 } 00781 } 00782 00783 00798 long 00799 OrdNodeReadDepth( 00800 Ntk_Node_t * node) 00801 { 00802 return ((long) Ntk_NodeReadUndef(node)); 00803 } 00804 00805 00823 void 00824 OrdNetworkAssignMddIds( 00825 Ntk_Network_t * network, 00826 Ord_OrderType orderType, 00827 lsList orderList, 00828 boolean nsAfterSupport) 00829 { 00830 lsGen gen; 00831 Ntk_Node_t *node; 00832 int mddId; 00833 mdd_manager *mddManager = Ntk_NetworkReadMddManager(network); 00834 array_t *mvarValues = array_alloc(int, lsLength(orderList)); 00835 array_t *mvarNames = array_alloc(char *, lsLength(orderList)); 00836 00837 assert((orderType == Ord_All_c) || (orderType == Ord_InputAndLatch_c)); 00838 00839 /* 00840 * If the network doesn't already have an MDD manager, then create one. In 00841 * any case, set mddId to be the number of variables currently existing in 00842 * the manager. 00843 */ 00844 if (mddManager == NIL(mdd_manager)) { 00845 mddManager = Ntk_NetworkInitializeMddManager(network); 00846 mddId = 0; 00847 } 00848 else { 00849 array_t *mvarArray = mdd_ret_mvar_list(mddManager); 00850 mddId = array_n(mvarArray); 00851 } 00852 00853 lsForEachItem(orderList, gen, node) { 00854 /* 00855 * A node gets an MDD id if node is a combinational input, next state 00856 * node, or orderType is Ord_All_c. 00857 */ 00858 if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsNextStateNode(node) 00859 || (orderType == Ord_All_c) ) { 00860 00861 Ntk_NodeSetMddId(node, mddId); 00862 mddId++; 00863 00864 array_insert_last(int, mvarValues, 00865 Var_VariableReadNumValues(Ntk_NodeReadVariable(node))); 00866 array_insert_last(char *, mvarNames, Ntk_NodeReadName(node)); 00867 } 00868 } 00869 00870 /* 00871 * Create the variables in the MDD manager. The last argument being NIL 00872 * means that the variables will not be interleaved. 00873 */ 00874 mdd_create_variables(mddManager, mvarValues, mvarNames, NIL(array_t)); 00875 00876 array_free(mvarValues); 00877 array_free(mvarNames); 00878 } 00879 00880 00881 /*---------------------------------------------------------------------------*/ 00882 /* Definition of static functions */ 00883 /*---------------------------------------------------------------------------*/ 00884 00894 static int 00895 NodesCompareDepth( 00896 Ntk_Node_t *node1, 00897 Ntk_Node_t *node2) 00898 { 00899 long depth1 = OrdNodeReadDepth(node1); 00900 long depth2 = OrdNodeReadDepth(node2); 00901 00902 if (depth1 > depth2) { 00903 return -1; 00904 } 00905 else if (depth1 < depth2) { 00906 return 1; 00907 } 00908 else { 00909 char *name1 = Ntk_NodeReadName(node1); 00910 char *name2 = Ntk_NodeReadName(node2); 00911 00912 /* 00913 * As a tiebreaker, sort based on name, so that the sorted result is not 00914 * sensitive to the order in which the nodes are passed to the compare 00915 * function. When sorting based on name, the order doesn't really matter, 00916 * but right now it's done so that "foo<i>" will come before "foo<j>" in 00917 * the ordering, where i < j. This is just a little heuristic to put lower 00918 * order bits first. */ 00919 if (strcmp(name1, name2) < 0) { 00920 return -1; 00921 } 00922 else if (strcmp(name1, name2) > 0) { 00923 return 1; 00924 } 00925 else { 00926 return 0; 00927 } 00928 } 00929 } 00930 00931 00941 static long 00942 NodeComputeDepth( 00943 Ntk_Node_t * node) 00944 { 00945 long depth = OrdNodeReadDepth(node); 00946 00947 /* 00948 * If the node's depth has already been computed (i.e. it's not unassigned), 00949 * then just return it below. If it's unassigned, then recursively compute 00950 * it. 00951 */ 00952 if (depth == ORDUNASSIGNED_DEPTH) { 00953 00954 if (Ntk_NodeTestIsCombInput(node) || Ntk_NodeTestIsConstant(node)) { 00955 /* 00956 * Latches, and nodes with no fanins, get depth 0. This is the terminal 00957 * case of recursion. 00958 */ 00959 depth = 0; 00960 } 00961 else { 00962 int i; 00963 Ntk_Node_t *fanin; 00964 /* 00965 * Compute the depth of each fanin node in the support of node, and 00966 * maintain the maximum. We start depth at 0 for max calculation. 00967 */ 00968 depth = 0; 00969 Ntk_NodeForEachFanin(node, i, fanin) { 00970 long faninDepth = NodeComputeDepth(fanin); 00971 00972 depth = (depth > faninDepth) ? depth : faninDepth; 00973 } 00974 00975 /* 00976 * The depth of node is one more than the max depths of its fanins. 00977 */ 00978 depth++; 00979 } 00980 00981 /* 00982 * Store the depth. 00983 */ 00984 NodeSetDepth(node, depth); 00985 } 00986 00987 return depth; 00988 } 00989 00990 01008 static void 01009 NetworkAddDanglingNodesToOrderList( 01010 Ntk_Network_t * network, 01011 lsList nodeOrderList /* of Ntk_Node_t* */, 01012 st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */) 01013 { 01014 lsGen gen; 01015 Ntk_Node_t *node; 01016 01017 /* 01018 * For each network node, if it's not in nodeOrderList, then add it to the 01019 * end of the list. 01020 * (NOTE: may be sensitive to ordering in memory.) 01021 */ 01022 Ntk_NetworkForEachNode(network, gen, node) { 01023 if (!st_is_member(nodeToHandle, (char *) node)) { 01024 lsHandle handle; 01025 01026 (void) lsNewEnd(nodeOrderList, (lsGeneric) node, &handle); 01027 st_insert(nodeToHandle, (char *) node, (char *) handle); 01028 } 01029 } 01030 } 01031 01032 01054 static void 01055 NetworkAddNSVarsToOrderList( 01056 Ntk_Network_t * network, 01057 lsList nodeOrderList /* of Ntk_Node_t */, 01058 st_table *nodeToHandle /* Ntk_Node_t* to lsHandle */, 01059 boolean nsAfterSupport) 01060 { 01061 lsGen gen1; 01062 Ntk_Node_t *latch; 01063 01064 /* 01065 * For each latch, add the latch's corresponding NS node to the ordering. 01066 * (NOTE: may be sensitive to ordering in memory.) 01067 */ 01068 Ntk_NetworkForEachLatch(network, gen1, latch) { 01069 lsHandle handle; 01070 lsGen gen2; 01071 lsGeneric dummyData; 01072 Ntk_Node_t *latchNS = Ntk_NodeReadShadow(latch); 01073 01074 if (nsAfterSupport) { 01075 /* Add just after the latch's dataInput. */ 01076 lsHandle dataInputHandle; 01077 Ntk_Node_t *dataInput = Ntk_LatchReadDataInput(latch); 01078 int status UNUSED = st_lookup(nodeToHandle, dataInput, 01079 &dataInputHandle); 01080 01081 assert(status); 01082 gen2 = lsGenHandle(dataInputHandle, &dummyData, LS_AFTER); 01083 } 01084 else { 01085 /* Add just after the latch. */ 01086 lsHandle latchHandle; 01087 int status = st_lookup(nodeToHandle, latch, &latchHandle); 01088 01089 if (!status) { 01090 /* 01091 * Latch itself is not yet in the ordering. This can happen if the 01092 * latch is not in the TFI of any other latch. So add the latch first 01093 * (at the end of the ordering). 01094 */ 01095 (void) lsNewEnd(nodeOrderList, (lsGeneric) latch, &latchHandle); 01096 st_insert(nodeToHandle, (char *) latch, (char *) latchHandle); 01097 } 01098 01099 gen2 = lsGenHandle(latchHandle, &dummyData, LS_AFTER); 01100 } 01101 01102 /* Actually add to list here. */ 01103 (void) lsInAfter(gen2, (lsGeneric) latchNS, &handle); 01104 st_insert(nodeToHandle, (char *) latchNS, (char *) handle); 01105 (void) lsFinish(gen2); 01106 01107 } 01108 } 01109 01110 01119 static lsList 01120 LatchNSListConvertToLatchDataInputList( 01121 lsList latchNSList) 01122 { 01123 lsGen gen; 01124 Ntk_Node_t *node; 01125 Ntk_Node_t *latch; 01126 lsList latchDataInputList = lsCreate(); 01127 01128 lsForEachItem(latchNSList, gen, node) { 01129 assert(Ntk_NodeTestIsNextStateNode(node)); 01130 latch = Ntk_ShadowReadOrigin(node); 01131 (void) lsNewEnd(latchDataInputList, (lsGeneric) 01132 Ntk_LatchReadDataInput(latch), LS_NH); 01133 } 01134 01135 return latchDataInputList; 01136 } 01137 01138 01148 static void 01149 NodeSetDepth( 01150 Ntk_Node_t * node, 01151 long depth) 01152 { 01153 Ntk_NodeSetUndef(node, (void *) depth); 01154 } 01155 01170 static void 01171 MddGroupVariables( 01172 mdd_manager *mddMgr, 01173 int initMddId, 01174 int blockSize ) 01175 { 01176 int i, j; 01177 int length; 01178 int aIndex; 01179 int startingBddIndex; 01180 int sanityCheck; 01181 mvar_type initMv, anMv; 01182 bvar_type initBvar, aBvar; 01183 array_t *mvar_list, *bvar_list; 01184 bdd_t *bdd; 01185 01186 mvar_list = mdd_ret_mvar_list(mddMgr); 01187 bvar_list = mdd_ret_bvar_list(mddMgr); 01188 01189 /* 01190 * mvar for initMddId 01191 */ 01192 initMv = array_fetch(mvar_type, mvar_list, initMddId); 01193 01194 /* 01195 * bvar for first bdd for initMddId 01196 */ 01197 initBvar = mdd_ret_bvar(&initMv, 0, bvar_list); 01198 01199 /* 01200 * number of bdd variables to group 01201 */ 01202 length = 0; 01203 01204 /* 01205 * startingBddIndex is the level of the first bdd variable 01206 */ 01207 startingBddIndex = bdd_top_var_level( mddMgr, initBvar.node ); 01208 sanityCheck = startingBddIndex; 01209 01210 /* 01211 * in this loop we are simply ensuring that the bdd variables 01212 * corresponding to the mdd vars are infact contiguous. If this 01213 * is not the case we fail. length is the total number of bdd variables 01214 * to be grouped. 01215 */ 01216 for( i = 0; i < blockSize; i++) { 01217 anMv = array_fetch(mvar_type, mvar_list, ( initMddId + i ) ); 01218 for ( j = 0 ; j < anMv.encode_length; j++ ) { 01219 01220 aBvar = mdd_ret_bvar( & anMv, j, bvar_list ); 01221 aIndex = bdd_top_var_level( mddMgr, aBvar.node ); 01222 01223 if ( sanityCheck != aIndex ) { 01224 /* bdd vars are not contiguous!! */ 01225 fprintf(vis_stderr, "Badly formed block - bdd vars for %s (mvar_id = %d) are not contiguous!!\n", 01226 anMv.name, anMv.mvar_id ); 01227 fail("Wont go on\n"); 01228 } 01229 else { 01230 /* number of variables to group increased by one */ 01231 sanityCheck++; 01232 length++; 01233 } 01234 } 01235 } 01236 01237 bdd = bdd_var_with_index(mddMgr, startingBddIndex); 01238 (void) bdd_new_var_block(bdd, length); 01239 bdd_free(bdd); 01240 } 01241 01242