VIS
|
00001 00019 #include "resInt.h" 00020 00021 static char rcsid[] UNUSED = "$Id: resCompose.c,v 1.30 2005/04/18 05:00:14 fabio Exp $"; 00022 00023 /*---------------------------------------------------------------------------*/ 00024 /* Constant declarations */ 00025 /*---------------------------------------------------------------------------*/ 00026 00027 /*---------------------------------------------------------------------------*/ 00028 /* Structure declarations */ 00029 /*---------------------------------------------------------------------------*/ 00030 00031 /*---------------------------------------------------------------------------*/ 00032 /* Type declarations */ 00033 /*---------------------------------------------------------------------------*/ 00034 00035 /*---------------------------------------------------------------------------*/ 00036 /* Variable declarations */ 00037 /*---------------------------------------------------------------------------*/ 00038 long Res_composeTime; 00039 long Res_shuffleTime; 00040 long Res_smartVarTime; 00041 long Res_orderTime; 00042 00043 /*---------------------------------------------------------------------------*/ 00044 /* Macro declarations */ 00045 /*---------------------------------------------------------------------------*/ 00046 00049 /*---------------------------------------------------------------------------*/ 00050 /* Static function prototypes */ 00051 /*---------------------------------------------------------------------------*/ 00052 00053 static void UpdateUnassignedNodesWithNewIds(lsList orderList, array_t *newIdArray); 00054 static lsList CreateNodeAndFaninOrderList(array_t *currentLayer); 00055 static lsList ListAppend(Ntk_Node_t *nodePtr, lsList newList, lsList faninList); 00056 static int IdCompare(const void *obj1, const void *obj2); 00057 static int IdListCompare(lsGeneric item1, lsGeneric item2); 00058 static lsList CreateFaninVarSetList(array_t *currentLayer, st_table *faninTable); 00059 static bdd_node * ComposeLayer(bdd_manager *ddManager, bdd_node *residueDd, array_t *currentLayer, bdd_node **functionArray); 00060 static Mvf_Function_t * NodeBuildConstantMvf(Ntk_Node_t * node, mdd_manager *mddMgr); 00061 00065 /*---------------------------------------------------------------------------*/ 00066 /* Definition of exported functions */ 00067 /*---------------------------------------------------------------------------*/ 00068 00069 00070 /*---------------------------------------------------------------------------*/ 00071 /* Definition of internal functions */ 00072 /*---------------------------------------------------------------------------*/ 00073 00074 00090 bdd_node * 00091 BuildBDDforNode(Ntk_Network_t *network, 00092 Ntk_Node_t *nodePtr, 00093 int fanin) 00094 { 00095 bdd_node *function; 00096 st_table *leaves; 00097 array_t *mvfArray; 00098 Mvf_Function_t *nodeFunction; 00099 Ntk_Node_t *faninNodePtr; 00100 lsGen netGen; 00101 array_t *root; 00102 int j; 00103 mdd_manager *mddMgr; 00104 00105 /* if it is a constant, build the mvf for it */ 00106 if( Ntk_NodeTestIsConstant(nodePtr) == 1) { 00107 mddMgr = (mdd_manager *)Ntk_NetworkReadMddManager(network); 00108 nodeFunction = NodeBuildConstantMvf(nodePtr, mddMgr); 00109 } else if (Ntk_NodeTestIsCombInput(nodePtr)) { 00110 /* the Bdd for a latch input is itself */ 00111 mddMgr = (mdd_manager *)Ntk_NetworkReadMddManager(network); 00112 nodeFunction = Mvf_FunctionCreateFromVariable(mddMgr, Ntk_NodeReadMddId(nodePtr)); 00113 } else { 00114 00115 /* Set the root to build the Mvf */ 00116 root = array_alloc(Ntk_Node_t *, 1); 00117 array_insert(Ntk_Node_t *, root, 0, nodePtr); 00118 00119 /* Set the leaves depending on the fanin flag*/ 00120 leaves = st_init_table(st_ptrcmp, st_ptrhash); 00121 if (fanin == IMMEDIATE_FANIN) { 00122 Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) { 00123 st_insert(leaves, (char *)faninNodePtr, (char *)NTM_UNUSED); 00124 } 00125 } else if (fanin == PRIMARY_INPUTS) { 00126 Ntk_NetworkForEachCombInput(network, netGen, nodePtr) { 00127 st_insert(leaves, (char *)nodePtr, (char *)NTM_UNUSED); 00128 } 00129 } 00130 00131 /* Effectively compute the function (We are not using don't cares)*/ 00132 mvfArray = Ntm_NetworkBuildMvfs(network, root, leaves, NIL(mdd_t)); 00133 st_free_table(leaves); 00134 array_free(root); 00135 00136 nodeFunction = array_fetch(Mvf_Function_t *, mvfArray, 0); 00137 /* since we built the MDD for only one root */ 00138 array_free(mvfArray); 00139 } /* end of else if not a latch output */ 00140 /* 00141 * The function above returned a Mvf_Function_t, but since we are 00142 * working with binary nodes (so far), we do not need the Mvf 00143 * representation, therefore we only keep one single Bdd and deallocate 00144 * all the memory attached to the rest of the Mvf. 00145 */ 00146 function = (bdd_node *)bdd_extract_node_as_is(Mvf_FunctionReadComponent(nodeFunction, 1)); 00147 if (function != NULL) { 00148 bdd_ref(function); 00149 } 00150 00151 /* Clean up */ 00152 Mvf_FunctionFree(nodeFunction); 00153 return (function); 00154 } 00155 00156 00194 bdd_node * 00195 ComposeLayersIntoResidue(Ntk_Network_t *network, 00196 array_t *layerArray, 00197 bdd_node *residueDd, 00198 array_t *outputArray) 00199 { 00200 bdd_manager *ddManager; /* Dd Manager */ 00201 bdd_node *newResidueDd = NIL(bdd_node); /* final composed Dd */ 00202 bdd_node *currentDd; /* local copy of residue Dd to 00203 * perform composition 00204 */ 00205 lsList outputList, orderList; /* output and layer+fanin node 00206 * list fed to the ordering procedure 00207 */ 00208 lsHandle nodeHandle; /* handle for node list */ 00209 int *invPermArray; /* inverse permutation array 00210 * for the Dd manager 00211 */ 00212 array_t *newIdArray; /* array with new Ids to be 00213 * assigned to each node 00214 */ 00215 Ntk_Node_t *nodePtr; /* variable to store node pointer */ 00216 array_t *currentLayer; /* current layer of nodes */ 00217 int numNodes; /* number of nodes in current layer */ 00218 bdd_node **functionArray; /* array of Adds of the current nodes 00219 * in terms of their fanin 00220 */ 00221 00222 bdd_node *functionBdd; /* Bdds of current layer nodes */ 00223 char *flagValue; /* string that stores flag values */ 00224 int verbose; /* verbosity level */ 00225 int j, k; /* iterators */ 00226 int layerIndex, nodeIndex; /* iterators */ 00227 long tempTime, thisComposeTime; /* local time measurement variables */ 00228 long thisSmartVarTime, thisOrderTime; /* local time measurement variables */ 00229 long thisShuffleTime; /* local time measurement variables */ 00230 int unassignedValue; /* NTK_UNASSIGNED_MDD_ID value holder */ 00231 00232 /* initialize local time measurement variables */ 00233 tempTime = 0; 00234 thisSmartVarTime = 0; 00235 thisOrderTime = 0; 00236 thisShuffleTime = 0; 00237 thisComposeTime = 0; 00238 unassignedValue = NTK_UNASSIGNED_MDD_ID; 00239 00240 /* make a local copy of the residue Dd to compose the network into */ 00241 bdd_ref(currentDd = residueDd); 00242 00243 /* read verbosity flag */ 00244 verbose = 0; 00245 flagValue = Cmd_FlagReadByName("residue_verbosity"); 00246 if (flagValue != NIL(char)) { 00247 verbose = atoi(flagValue); 00248 } 00249 00250 ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network); 00251 /* initialize the variable manager that keeps track of what variables 00252 * are in use in residue verification. 00253 */ 00254 ResResidueInitializeVariableManager(bdd_num_vars(ddManager)); 00255 00256 /* assume the pos are labeled before they come here each time */ 00257 outputList = lsCreate(); 00258 00259 /* outputs do not need to be ordered as the node ids are already 00260 * assigned. Here this list is created just so that the variable 00261 * manager can be updated 00262 */ 00263 00264 arrayForEachItem(Ntk_Node_t *, outputArray, j, nodePtr) { 00265 lsNewEnd(outputList, (lsGeneric)nodePtr, (lsHandle *)&nodeHandle); 00266 } 00267 00268 newIdArray = array_alloc(int, 0); 00269 tempTime = util_cpu_time(); 00270 /* update the variable manager with the output node ids */ 00271 invPermArray = ResResidueVarAllocate(ddManager, outputList, newIdArray); 00272 if (invPermArray == NIL(int)) { 00273 error_append("Unable to update variable manager\n"); 00274 array_free(newIdArray); 00275 ResResidueFreeVariableManager(); 00276 return NULL; 00277 } /* end of error */ 00278 thisSmartVarTime += util_cpu_time() - tempTime; 00279 FREE(invPermArray); 00280 array_free(newIdArray); 00281 lsDestroy(outputList, (void (*)(lsGeneric))0); 00282 00283 /* start the main loop for composition of layers into the residue Add */ 00284 for(layerIndex = 0; layerIndex < array_n(layerArray); layerIndex++) { 00285 /* fetch each layer */ 00286 currentLayer = ResLayerFetchIthLayer(layerArray, layerIndex); 00287 numNodes = ResLayerNumNodes(currentLayer); 00288 if (verbose >= 3) { 00289 fprintf(vis_stdout, "Layer %d being composed", layerIndex); 00290 fprintf(vis_stdout, " with %d nodes\n", numNodes); 00291 } 00292 00293 /* create the order of the nodes in the layer and their fanin 00294 * for composition 00295 */ 00296 tempTime = util_cpu_time(); 00297 orderList = CreateNodeAndFaninOrderList(currentLayer); 00298 thisOrderTime += util_cpu_time() - tempTime; 00299 00300 /* assign new Ids if required and create the corresponding variables 00301 * in the manager 00302 */ 00303 newIdArray = array_alloc(int, 0); 00304 tempTime = util_cpu_time(); 00305 invPermArray = ResResidueVarAllocate(ddManager, orderList, newIdArray); 00306 if (invPermArray == NIL(int)) { 00307 error_append("Unable to update variable manager\n"); 00308 bdd_recursive_deref(ddManager, currentDd); 00309 array_free(newIdArray); 00310 ResResidueFreeVariableManager(); 00311 return NULL; 00312 } /* end of error */ 00313 thisSmartVarTime += util_cpu_time() - tempTime; 00314 00315 /* assign Ids to unassigned fanin nodes */ 00316 if (array_n(newIdArray)) { 00317 UpdateUnassignedNodesWithNewIds(orderList, newIdArray); 00318 } 00319 array_free(newIdArray); 00320 lsDestroy(orderList, (void (*)(lsGeneric))0); 00321 00322 /* shuffle the IDs */ 00323 tempTime = util_cpu_time(); 00324 (void) bdd_shuffle_heap(ddManager, invPermArray); 00325 thisShuffleTime += util_cpu_time() - tempTime; 00326 FREE(invPermArray); 00327 00328 /* array initialized for dd nodes of the current layer */ 00329 tempTime = util_cpu_time(); 00330 functionArray = ALLOC(bdd_node *, numNodes); 00331 LayerForEachNode(currentLayer, nodeIndex, nodePtr) { 00332 00333 /* build the BDD for the function of each node */ 00334 functionBdd = BuildBDDforNode(network, nodePtr, IMMEDIATE_FANIN); 00335 if (functionBdd == NULL) { /* error */ 00336 error_append("Unable to build function for node "); 00337 error_append(Ntk_NodeReadName(nodePtr)); 00338 error_append("\n"); 00339 for (k = 0; k < nodeIndex; k++) { 00340 bdd_recursive_deref(ddManager, functionArray[k]); 00341 } 00342 FREE(functionArray); 00343 bdd_recursive_deref(ddManager, currentDd); 00344 ResResidueFreeVariableManager(); 00345 return NULL; 00346 } /* end of error */ 00347 00348 /* Convert to ADD */ 00349 bdd_ref(functionArray[nodeIndex] = bdd_bdd_to_add(ddManager, functionBdd)); 00350 bdd_recursive_deref(ddManager, functionBdd); 00351 if (functionArray[nodeIndex] == NULL) { /* error */ 00352 error_append("Unable to build add from bdd for node "); 00353 error_append(Ntk_NodeReadName(nodePtr)); 00354 error_append("\n"); 00355 for (k = 0; k < nodeIndex; k++) { 00356 bdd_recursive_deref(ddManager, functionArray[k]); 00357 } 00358 FREE(functionArray); 00359 bdd_recursive_deref(ddManager, currentDd); 00360 ResResidueFreeVariableManager(); 00361 return NULL; 00362 } /* end of error */ 00363 } /* end of iterating over each node in a layer */ 00364 /* compose the array into the residue ADD */ 00365 00366 /* Perform the actual composition of current layer */ 00367 tempTime = util_cpu_time(); 00368 newResidueDd = ComposeLayer(ddManager, currentDd, currentLayer, functionArray); 00369 thisComposeTime += util_cpu_time() - tempTime; 00370 /* free old residue Dd */ 00371 bdd_recursive_deref(ddManager, currentDd); 00372 if (newResidueDd == NULL) { /* error */ 00373 error_append("Unable to do composition for layer\n"); 00374 for (k = 0; k < numNodes; k++) { 00375 bdd_recursive_deref(ddManager, functionArray[k]); 00376 } 00377 FREE(functionArray); 00378 ResResidueFreeVariableManager(); 00379 return NULL; 00380 } /* end of error */ 00381 currentDd = newResidueDd; 00382 if (verbose >= 3) { 00383 mdd_t *fnMddT; 00384 int size; 00385 bdd_ref(currentDd); 00386 fnMddT = bdd_construct_bdd_t(ddManager, currentDd); 00387 size = bdd_size(fnMddT); 00388 bdd_free(fnMddT); 00389 fprintf(vis_stdout, "Layer %d has %d nodes\n", layerIndex, 00390 size); 00391 } 00392 00393 /* free function array */ 00394 for (j = 0; j < numNodes; j++) { 00395 bdd_recursive_deref(ddManager, functionArray[j]); 00396 } 00397 FREE(functionArray); 00398 00399 /* free ids of nodes just composed */ 00400 ResResidueVarDeallocate(currentLayer); 00401 /* reset node Ids of the composed layer */ 00402 LayerForEachNode(currentLayer, j, nodePtr) { 00403 if (!Ntk_NodeTestIsCombInput(nodePtr)) { 00404 Ntk_NodeSetMddId(nodePtr, unassignedValue); 00405 } 00406 } 00407 } /* end of iterating over the layers */ 00408 00409 /* free the variable manager */ 00410 ResResidueFreeVariableManager(); 00411 if (verbose >= 1) { 00412 (void) fprintf(vis_stdout, "ADD Compose Time = %.3f\n",(thisComposeTime)/1000.0); 00413 (void) fprintf(vis_stdout, "Smart variable allocation time = %.3f\n", (thisSmartVarTime)/1000.0); 00414 (void) fprintf(vis_stdout, "Shuffle time = %.3f\n", (thisShuffleTime)/1000.0); 00415 (void) fprintf(vis_stdout, "Order time = %.3f\n", (thisOrderTime)/1000.0); 00416 } 00417 /* update global time variables */ 00418 Res_composeTime += thisComposeTime; 00419 Res_smartVarTime += thisSmartVarTime; 00420 Res_shuffleTime += thisShuffleTime; 00421 Res_orderTime += thisOrderTime; 00422 00423 /* return the composed residue Dd in terms of the primary inputs */ 00424 return(newResidueDd); 00425 00426 } /* End of ComposeLayersIntoResidue */ 00427 00428 /*---------------------------------------------------------------------------*/ 00429 /* Definition of static functions */ 00430 /*---------------------------------------------------------------------------*/ 00431 00447 static void 00448 UpdateUnassignedNodesWithNewIds(lsList orderList, 00449 array_t *newIdArray) 00450 { 00451 int i, id; 00452 lsGen listGen; 00453 Ntk_Node_t *nodePtr; 00454 char *flagValue; 00455 int verbose; 00456 00457 verbose = 0; 00458 flagValue = Cmd_FlagReadByName("residue_verbosity"); 00459 if (flagValue != NIL(char)) { 00460 verbose = atoi(flagValue); 00461 } 00462 00463 /* step through each item in the list to find nodes with unassigned Ids */ 00464 i = 0; 00465 lsForEachItem(orderList, listGen, nodePtr) { 00466 if (Ntk_NodeReadMddId(nodePtr) == NTK_UNASSIGNED_MDD_ID) { 00467 id = array_fetch(int, newIdArray, i); 00468 Ntk_NodeSetMddId(nodePtr, id); 00469 i++; 00470 if (verbose >= 4) { 00471 fprintf(vis_stdout, "Id %d being assigned to node %s\n", id, 00472 Ntk_NodeReadName(nodePtr)); 00473 } 00474 } 00475 } 00476 assert(i == array_n(newIdArray)); 00477 return; 00478 } /* End of UpdateUnassignedNodesWithNewIds */ 00479 00480 00511 static lsList 00512 CreateNodeAndFaninOrderList(array_t *currentLayer) 00513 { 00514 st_table *faninTable; /* table to store fanin */ 00515 lsList layerList; /* list of nodes in layer */ 00516 lsList faninVarSetList; /* list of support corresponding to layer 00517 * nodes. 00518 */ 00519 lsList newList; /* ordered list of nodes and fanins */ 00520 lsGen listGen; /* generator to step through list */ 00521 lsGen layerGen, faninGen; /* generators to step through lists */ 00522 int totalFanins;/* variable to store total number of fanins 00523 * of this layer 00524 */ 00525 int intersect; /* number of elements in the intersection 00526 * of support. 00527 */ 00528 int i, j, faninIndex; /* iterators */ 00529 Ntk_Node_t *nodePtr; /* node pointer variables */ 00530 Ntk_Node_t *faninNodePtr; /* node pointer variables */ 00531 Ntk_Node_t *nextNodePtr; /* node pointer variables */ 00532 lsHandle nodeHandle; /* handle for ls procedure */ 00533 lsHandle varSetHandle; /* handle for ls procedure */ 00534 lsHandle newNodeHandle; /* handle for ls procedure */ 00535 lsHandle maxIntersectNodeHandle; /* handle for ls procedure */ 00536 lsHandle maxIntersectVarSetHandle; /* handle for ls procedure */ 00537 var_set_t *currVarSet; /* support of current node */ 00538 var_set_t *varSetIntersect; /* intersection of support between 2 nodes */ 00539 var_set_t *nextVarSet; /* support of next node */ 00540 array_t *faninArray; /* array of fanin of a node read from network */ 00541 lsList faninList; /* list of fanins of current layer */ 00542 int nodeIndex; /* iterator */ 00543 int verbose; /* verbosity level */ 00544 char *flagValue; /* string to read flag value */ 00545 00546 verbose = 0; 00547 flagValue = Cmd_FlagReadByName("residue_verbosity"); 00548 if (flagValue != NIL(char)) { 00549 verbose = atoi(flagValue); 00550 } 00551 00552 /* sort current layer by position in the dd manager for least number 00553 * of shuffles 00554 */ 00555 LayerSort(currentLayer, IdCompare); 00556 /* create a list to be able to order the list and later manipulation */ 00557 layerList = lsCreate(); 00558 if (verbose >= 4) { 00559 fprintf(vis_stdout, "Nodes in this layer are: "); 00560 } 00561 LayerForEachNode(currentLayer, i, nodePtr) { 00562 lsNewEnd(layerList, (lsGeneric)nodePtr, (lsHandle *)&nodeHandle); 00563 if (verbose >= 4) { 00564 fprintf(vis_stdout, "%s ",Ntk_NodeReadName(nodePtr)); 00565 } 00566 } 00567 if (verbose >= 4) { 00568 fprintf(vis_stdout, "\n"); 00569 } 00570 00571 /* insert all fanins in a table with a unique index. This is to identify 00572 * each fanin as a support variable 00573 */ 00574 faninIndex = 0; 00575 faninTable = st_init_table(st_ptrcmp, st_ptrhash); 00576 00577 LayerForEachNode(currentLayer, nodeIndex, nodePtr) { 00578 Ntk_NodeForEachFanin(nodePtr, j, faninNodePtr) { 00579 /* here constants are omitted, so that they are not assigned an 00580 * Id. The other case to be avoided is when the node in consideration 00581 * is a latch output i.e. a combinational input. Hence it is not 00582 * desirable that the latch data input and latch initial input 00583 * be considered as its fanin. 00584 */ 00585 if ((!st_is_member(faninTable, (char *)faninNodePtr)) && 00586 (!(Ntk_NodeTestIsConstant(faninNodePtr) || 00587 (Ntk_NodeTestIsLatch(nodePtr) && 00588 (Ntk_NodeTestIsLatchDataInput(faninNodePtr) || 00589 Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))) { 00590 st_insert(faninTable, (char *)faninNodePtr, 00591 (char *)(long)faninIndex); 00592 faninIndex++; 00593 } 00594 } 00595 } 00596 /* keep a count of the total number of fanins to this layer */ 00597 totalFanins = faninIndex; 00598 00599 /* Create fanin var set for each node */ 00600 faninVarSetList = CreateFaninVarSetList(currentLayer, faninTable); 00601 st_free_table(faninTable); 00602 00603 /* Main sorting part: Like Insertion Sort*/ 00604 /* initialize to first item from both layer and fanin lists */ 00605 /* starting here, find the list element in the list with max overlap 00606 * with this element. Here each node in the layer is brought up 00607 * neighbor 00608 */ 00609 (void) lsFirstItem(faninVarSetList, &currVarSet, &varSetHandle); 00610 (void) lsFirstItem(layerList, &nodePtr, &nodeHandle); 00611 (void) lsRemoveItem(nodeHandle, &nodePtr); 00612 (void) lsRemoveItem(varSetHandle, &currVarSet); 00613 00614 /* insert first item in new list */ 00615 newList = lsCreate(); 00616 lsNewEnd(newList, (lsGeneric)nodePtr, (lsHandle *)&newNodeHandle); 00617 00618 /* create var set for checking overlap of support */ 00619 varSetIntersect = var_set_new(totalFanins); 00620 /* done when all the nodes in the layerList have been transferred 00621 * to new list. In each iteration of this list, the node with max 00622 * support overlap with the current node is taken out of the list 00623 * and added to the new list. Its corresponding var set is also 00624 * removed, the current var set is freed and the new var set is 00625 * set to the current var set. The var set list has to be manipulated 00626 * simultaneously to keep the correspondence between the node list 00627 * and its support list. 00628 */ 00629 while(lsLength(newList) != ResLayerNumNodes(currentLayer)) { /* while not done */ 00630 /* create generators to step through list */ 00631 faninGen = lsStart(faninVarSetList); 00632 layerGen = lsStart(layerList); 00633 /* initialize */ 00634 intersect = 0; 00635 maxIntersectNodeHandle = NULL; 00636 maxIntersectVarSetHandle = NULL; 00637 while (lsNext(layerGen, &nextNodePtr, &nodeHandle) != LS_NOMORE) { 00638 /* clear result var set */ 00639 var_set_clear(varSetIntersect); 00640 /* position var set corresponding to node in layer list */ 00641 lsNext(faninGen, &nextVarSet, &varSetHandle); 00642 /* get support overlap */ 00643 varSetIntersect = var_set_and(varSetIntersect, currVarSet, nextVarSet); 00644 /* check if current overlap is larger than current max */ 00645 if (var_set_n_elts(varSetIntersect) > intersect) { 00646 /* record current position */ 00647 intersect = var_set_n_elts(varSetIntersect); 00648 maxIntersectNodeHandle = nodeHandle; 00649 maxIntersectVarSetHandle = varSetHandle; 00650 } 00651 } /* end of iterating over layer list */ 00652 00653 /* destroy Generator */ 00654 (void) lsFinish(layerGen); 00655 (void) lsFinish(faninGen); 00656 /* free current var set */ 00657 var_set_free(currVarSet); 00658 /* process differently if there was overlap and if there wasn't */ 00659 if (maxIntersectNodeHandle == NULL) { 00660 /* support overlap was zero with the rest of the nodes */ 00661 /* set current item to first in the lists */ 00662 (void) lsFirstItem(faninVarSetList, &nextVarSet, &maxIntersectVarSetHandle); 00663 (void) lsFirstItem(layerList, &nextNodePtr, &maxIntersectNodeHandle); 00664 } 00665 00666 /* remove max support overlap item from the lists */ 00667 (void) lsRemoveItem(maxIntersectNodeHandle, &nextNodePtr); 00668 (void) lsRemoveItem(maxIntersectVarSetHandle, &nextVarSet); 00669 00670 /* add node to the new list */ 00671 lsNewEnd(newList, (lsGeneric)nextNodePtr, (lsHandle *)&newNodeHandle); 00672 /* move current item to the new item */ 00673 currVarSet = nextVarSet; 00674 00675 } 00676 /* Clean up */ 00677 var_set_free(varSetIntersect); 00678 var_set_free(currVarSet); 00679 lsDestroy(faninVarSetList, (void (*)(lsGeneric))0); 00680 lsDestroy(layerList, (void (*)(lsGeneric))0); 00681 /* end of sorting part */ 00682 00683 /* insert nodes in new order in the current layer */ 00684 i = 0; 00685 lsForEachItem(newList, listGen, nodePtr) { 00686 LayerAddNodeAtIthPosition(currentLayer, i, nodePtr); 00687 i++; 00688 } 00689 assert(lsLength(newList) == array_n(currentLayer)); 00690 00691 /* keep track of running update of the fanins included */ 00692 faninTable = st_init_table(st_ptrcmp, st_ptrhash); 00693 /* insert fanin nodes after the last node in the order */ 00694 nodeIndex = ResLayerNumNodes(currentLayer)-1; 00695 /* while nodes exist that have to be processed and all fanins haven't 00696 * been processed, repeat 00697 */ 00698 while ((nodeIndex >= 0) || (st_count(faninTable) != totalFanins)) { 00699 nodePtr = LayerFetchIthNode(currentLayer, nodeIndex); 00700 faninArray = Ntk_NodeReadFanins(nodePtr); 00701 /* create a fanin list to append to the nodeList */ 00702 faninList = lsCreate(); 00703 arrayForEachItem(Ntk_Node_t *, faninArray, i, faninNodePtr) { 00704 /* only include those fanins that haven't appeared yet. Also 00705 * exclude the cases where the node is a constant and it is 00706 * a latch data/initial input. You don't want to compose a 00707 * latch output i.e. a combinational input with the latch input. 00708 */ 00709 if ((!st_is_member(faninTable, (char *)faninNodePtr)) && 00710 (!(Ntk_NodeTestIsConstant(faninNodePtr) || 00711 (Ntk_NodeTestIsLatch(nodePtr) && 00712 (Ntk_NodeTestIsLatchDataInput(faninNodePtr) || 00713 Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))) { 00714 lsNewEnd(faninList, (lsGeneric)faninNodePtr, (lsHandle *)&nodeHandle); 00715 st_insert(faninTable, (char *)faninNodePtr, NIL(char)); 00716 /* done when all fanins have been processed */ 00717 if (st_count(faninTable) == totalFanins) break; 00718 } 00719 } 00720 /* if list is not empty add fanin behind the node */ 00721 if (lsLength(faninList)) { 00722 /* sort fanins by their level in the ddmanager */ 00723 lsSort(faninList, IdListCompare); 00724 /* append the fanin list to the node list */ 00725 newList = ListAppend(nodePtr, newList, faninList); 00726 } 00727 lsDestroy(faninList, (void (*)(lsGeneric))0); 00728 nodeIndex--; 00729 00730 } /* end of while fanin nodes need to be processed and nodes 00731 * are present in layer */ 00732 st_free_table(faninTable); 00733 assert(lsLength(newList) == (array_n(currentLayer) + totalFanins)); 00734 00735 return(newList); 00736 } /* End of CreateNodeAndFaninOrderList */ 00737 00738 00754 static lsList 00755 ListAppend(Ntk_Node_t *nodePtr, 00756 lsList newList, 00757 lsList faninList) 00758 { 00759 lsGen layerGen, newGen, faninGen; 00760 Ntk_Node_t *currNodePtr, *faninNodePtr; 00761 lsHandle nodeHandle, faninNodeHandle; 00762 lsStatus status; 00763 00764 layerGen = lsEnd(newList); 00765 /* find the spot to insert fanin List */ 00766 while(lsPrev(layerGen, &currNodePtr, &nodeHandle) != LS_NOMORE) { 00767 if (nodePtr == currNodePtr) { 00768 /* when spot found, insert fanin list */ 00769 newGen = lsGenHandle(nodeHandle, &currNodePtr, LS_AFTER); 00770 lsForEachItem(faninList, faninGen, faninNodePtr) { 00771 status = lsInAfter(newGen, (lsGeneric)faninNodePtr, (lsHandle *)&faninNodeHandle); 00772 if (status != LS_OK) { 00773 error_append("Something wrong with fanin list to be appended\n"); 00774 status = lsFinish(layerGen); 00775 status = lsFinish(newGen); 00776 status = lsFinish(faninGen); 00777 return NULL; 00778 } 00779 } /* end of iterating through the fanin list */ 00780 /* done as fanin list has been inserted */ 00781 lsFinish(newGen); 00782 break; 00783 } /* end of if node found in the list */ 00784 } /* end of stepping through the new list */ 00785 00786 /* Clean up generators */ 00787 lsFinish(layerGen); 00788 00789 /* return modified list */ 00790 return (newList); 00791 }/* End of ListAppend */ 00792 00793 00806 static int 00807 IdCompare(const void *obj1, 00808 const void *obj2) 00809 { 00810 Ntk_Node_t *nodePtr1, *nodePtr2; 00811 int id1 , id2; 00812 int level1, level2; 00813 Ntk_Network_t *network; 00814 bdd_manager *ddManager; 00815 00816 nodePtr1 = *(Ntk_Node_t **)obj1; 00817 nodePtr2 = *(Ntk_Node_t **)obj2; 00818 id1 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr1); 00819 id2 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr2); 00820 /* if unassigned Ids return the value before reading the 00821 * position . If equal return -1. 00822 */ 00823 if ((id1 == NTK_UNASSIGNED_MDD_ID) || (id2 == NTK_UNASSIGNED_MDD_ID)) { 00824 if (id1 == NTK_UNASSIGNED_MDD_ID) { 00825 return -1; 00826 } else { 00827 return 1; 00828 } 00829 } 00830 00831 network = Ntk_NodeReadNetwork(nodePtr1); 00832 ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network); 00833 level1 = bdd_get_level_from_id(ddManager, id1); 00834 level2 = bdd_get_level_from_id(ddManager, id2); 00835 if (level1 > level2) { 00836 return 1; 00837 } else if (level1 == level2) { 00838 return 0; 00839 } else { 00840 return -1; 00841 } 00842 } /* End of IdCompare */ 00843 00855 static int 00856 IdListCompare(lsGeneric item1, 00857 lsGeneric item2) 00858 { 00859 Ntk_Node_t *nodePtr1, *nodePtr2; 00860 int id1 , id2; 00861 int level1, level2; 00862 Ntk_Network_t *network; 00863 bdd_manager *ddManager; 00864 00865 00866 nodePtr1 = (Ntk_Node_t *)item1; 00867 nodePtr2 = (Ntk_Node_t *)item2; 00868 id1 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr1); 00869 id2 = Ntk_NodeReadMddId((Ntk_Node_t *)nodePtr2); 00870 /* if unassigned Ids return the value before reading the 00871 * position . If equal return -1. 00872 */ 00873 if ((id1 == NTK_UNASSIGNED_MDD_ID) || (id2 == NTK_UNASSIGNED_MDD_ID)) { 00874 if (id1 == NTK_UNASSIGNED_MDD_ID) { 00875 return -1; 00876 } else { 00877 return 1; 00878 } 00879 } 00880 network = Ntk_NodeReadNetwork(nodePtr1); 00881 ddManager = (bdd_manager *)Ntk_NetworkReadMddManager(network); 00882 level1 = bdd_get_level_from_id(ddManager, id1); 00883 level2 = bdd_get_level_from_id(ddManager, id2); 00884 if (level1 > level2) { 00885 return 1; 00886 } else if (level1 == level2) { 00887 return 0; 00888 } else { 00889 return -1; 00890 } 00891 } /* End of IdListCompare */ 00892 00893 00909 static lsList 00910 CreateFaninVarSetList(array_t *currentLayer, 00911 st_table *faninTable) 00912 { 00913 Ntk_Node_t *nodePtr, *faninNodePtr; /* variables to store nodes */ 00914 array_t *faninArray; /* array of fanin of nodes */ 00915 lsList faninVarSetList; /* list of var set representing 00916 * support of nodes in layer 00917 */ 00918 var_set_t *currVarSet; /* var set indicating current 00919 * node support 00920 */ 00921 lsHandle varSetHandle; /* handle for ls procedure */ 00922 int totalFanins; /* total number of fanins of this 00923 * layer. 00924 */ 00925 int i, j, faninIndex; /* iterators */ 00926 00927 00928 00929 totalFanins = (int)st_count(faninTable); 00930 faninVarSetList = lsCreate(); 00931 /* create var-set of support for each node in this layer */ 00932 arrayForEachItem(Ntk_Node_t *, currentLayer, i, nodePtr) { 00933 faninArray = Ntk_NodeReadFanins(nodePtr); 00934 currVarSet = var_set_new(totalFanins); 00935 /* if the above node is a constant, the var set will be empty 00936 * also if it a latch output(comb. input), then the var set will 00937 * be empty. 00938 */ 00939 arrayForEachItem(Ntk_Node_t *, faninArray, j, faninNodePtr) { 00940 /* process only those fanins in the table, i.e. no constants 00941 * no latch inputs (combinational outputs) are fanins to this array 00942 */ 00943 if (st_lookup_int(faninTable, (char *)faninNodePtr, &faninIndex)) { 00944 /* these aren't supposed to be here */ 00945 assert(!((Ntk_NodeTestIsConstant(faninNodePtr) || 00946 (Ntk_NodeTestIsLatch(nodePtr) && 00947 (Ntk_NodeTestIsLatchDataInput(faninNodePtr) || 00948 Ntk_NodeTestIsLatchInitialInput(faninNodePtr)))))); 00949 /* set the bit in the support according to the index the fanin 00950 * was assigned 00951 */ 00952 var_set_set_elt(currVarSet, faninIndex); 00953 } /* end of if is in the fanin table (has no constants and no 00954 * latch data or initial input. 00955 */ 00956 } /* end of if present in fanin table */ 00957 /* insert var set in fanin var set list */ 00958 lsNewEnd(faninVarSetList, (lsGeneric)currVarSet, (lsHandle *)&varSetHandle); 00959 } 00960 return (faninVarSetList); 00961 } /* End of CreateFaninVarSetList */ 00962 00982 static bdd_node * 00983 ComposeLayer(bdd_manager *ddManager, 00984 bdd_node *residueDd, 00985 array_t *currentLayer, 00986 bdd_node **functionArray) 00987 { 00988 Ntk_Node_t *nodePtr; /* variable to store nodes */ 00989 char *flagValue; /* string to read flag value */ 00990 ResCompositionMethod method; /* type of composition to be performed */ 00991 int i, j, layerIndex; /* iterators */ 00992 int nodeId; /* current node id */ 00993 bdd_node **composeVector; /* vector required for composition */ 00994 bdd_node *new_ = NIL(bdd_node), *andDd,*yDd, *nodeReln, *currentDd; /* temporary Dds */ 00995 int maxLayerSize; /* max size of layers */ 00996 int first, last; /* first and last positions of the array */ 00997 00998 /* read the type of composition to be performed, default is vector 00999 * composition. 01000 */ 01001 flagValue = Cmd_FlagReadByName("residue_composition_method"); 01002 if (flagValue == NIL(char)) { 01003 method = ResDefaultComposeMethod_c; 01004 } else if (strcmp(flagValue, "vector") == 0) { 01005 method = ResVector_c; 01006 } else if (strcmp(flagValue, "onegate") == 0) { 01007 method = ResOneGateAtATime_c; 01008 } else if (strcmp(flagValue, "preimage") == 0) { 01009 method = ResPreimageComputation_c; 01010 } else if (strcmp(flagValue, "superG") == 0) { 01011 method = ResSuperG_c; 01012 } else { 01013 fprintf(vis_stderr, 01014 "** res warning: Unknown composition method, %s, resorting to default.\n", 01015 flagValue); 01016 method = ResDefaultComposeMethod_c; 01017 } 01018 01019 switch(method) { 01020 01021 case ResVector_c: 01022 case ResSuperG_c: 01023 { 01024 /* read the flag for maximum value of layer size */ 01025 flagValue = Cmd_FlagReadByName("residue_layer_size"); 01026 if (flagValue == NIL(char)) { 01027 maxLayerSize = ResLayerNumNodes(currentLayer); 01028 } else { 01029 maxLayerSize = atoi(flagValue); 01030 } 01031 /* if max layer size is within 5 nodes of the length of the 01032 * size of the array, resize it to the size of the array 01033 */ 01034 if (maxLayerSize + 5 >= ResLayerNumNodes(currentLayer)) { 01035 maxLayerSize = ResLayerNumNodes(currentLayer); 01036 } 01037 01038 /* initialize a vector with projection functions */ 01039 composeVector = ALLOC(bdd_node *, bdd_num_vars(ddManager)); 01040 for(i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) { 01041 bdd_ref(composeVector[i] = bdd_add_ith_var(ddManager, i)); 01042 if (composeVector[i] == NIL(bdd_node)) { /* error */ 01043 error_append("Something wrong in obtaining projection functions"); 01044 for(j = 0; j < i; j++) { 01045 bdd_recursive_deref(ddManager, composeVector[j]); 01046 } 01047 return NIL(bdd_node); 01048 } /* end of if error */ 01049 } 01050 /* break this layer up into sub-layers to ease composition 01051 * process. Hence the composition will be performed for several 01052 * subarrays. 01053 */ 01054 /* start at the end of the layer */ 01055 layerIndex = ResLayerNumNodes(currentLayer); 01056 /* make a local copy */ 01057 bdd_ref(currentDd = residueDd); 01058 do { 01059 /* extract sublayers in the size of maxLayerSize starting from the 01060 * end of the layer or a smaller sub-layer (leftover) in the end 01061 */ 01062 01063 /* record last+1 position of the sub-layer in the current layer */ 01064 last = layerIndex; 01065 01066 /* record the position of the beginning of this sub-layer */ 01067 first = (last < maxLayerSize) ? 0 : (last - maxLayerSize); 01068 01069 /* iterate through the layer to find the sublayer */ 01070 while(layerIndex > first) { /* extract sub-layer */ 01071 layerIndex--; 01072 nodePtr = LayerFetchIthNode(currentLayer, layerIndex); 01073 nodeId = Ntk_NodeReadMddId(nodePtr); 01074 bdd_recursive_deref(ddManager, composeVector[nodeId]); 01075 /* plug in the functions of the nodes in the layer instead of 01076 * the projection functions 01077 */ 01078 bdd_ref(composeVector[nodeId] = functionArray[layerIndex]); 01079 } 01080 01081 /* perform composition */ 01082 if (method == ResVector_c) { 01083 bdd_ref(new_ = bdd_add_vector_compose(ddManager, currentDd, composeVector)); 01084 } else { 01085 bdd_ref(new_ = bdd_add_nonsim_compose(ddManager, currentDd, composeVector)); 01086 } 01087 01088 /* free old copy and use new to compose in the next sub-layer, if any */ 01089 bdd_recursive_deref(ddManager, currentDd); 01090 currentDd = new_; 01091 01092 if (new_ == NULL) { /* error */ 01093 error_append("NULL Dd returned on vector or superG compose\n"); 01094 break; 01095 } /* end of error */ 01096 01097 /* undo the compose vector changes for this sub-array to 01098 * prepare it for the next subarray. Replace the function of 01099 * nodes with the projection functions 01100 */ 01101 for (i = first; i < last; i++) { 01102 nodePtr = LayerFetchIthNode(currentLayer, i); 01103 nodeId = Ntk_NodeReadMddId(nodePtr); 01104 bdd_recursive_deref(ddManager, composeVector[nodeId]); 01105 bdd_ref(composeVector[nodeId] = bdd_add_ith_var(ddManager, nodeId)); 01106 } 01107 } while(layerIndex > 0); 01108 01109 /* clean up */ 01110 for(i = 0; (unsigned) i < bdd_num_vars(ddManager); i++) { 01111 bdd_recursive_deref(ddManager, composeVector[i]); 01112 } 01113 FREE(composeVector); 01114 break; 01115 } /* end of cases: ResVector_c, ResSuperG_c */ 01116 case ResOneGateAtATime_c: 01117 { 01118 /* duplicate as current Dd gets freed later */ 01119 bdd_ref(currentDd = residueDd); 01120 /* compose the nodes in one at a time */ 01121 LayerForEachNode(currentLayer, i, nodePtr) { 01122 nodeId = Ntk_NodeReadMddId(nodePtr); 01123 bdd_ref(new_ = bdd_add_compose(ddManager, currentDd, functionArray[i], 01124 nodeId)); 01125 bdd_recursive_deref(ddManager, currentDd); 01126 if (new_ == NULL) { /* error */ 01127 error_append("NULL Dd returned on single gate compose, node: "); 01128 error_append(Ntk_NodeReadName(nodePtr)); 01129 error_append("\n"); 01130 return NULL; 01131 } /* end of error */ 01132 currentDd = new_; 01133 } 01134 break; 01135 } /* end of case Res_OneGateAtATime_c */ 01136 case ResPreimageComputation_c: 01137 { 01138 /* duplicate as current Dd gets freed later */ 01139 bdd_ref(currentDd = residueDd); 01140 /* form the y_i \equiv f_i(x) relation, this would be wrong 01141 * if the node appeared again in the circuit. But here it is 01142 * correct due to the one time rule 01143 */ 01144 LayerForEachNode(currentLayer, i, nodePtr) { 01145 nodeId = Ntk_NodeReadMddId(nodePtr); 01146 /* find the var for this node */ 01147 bdd_ref(yDd = bdd_add_ith_var(ddManager, nodeId)); 01148 if (yDd == NULL) { /* error */ 01149 error_append("Null Dd returned on preimage compose- y_i stage. "); 01150 error_append("Node: "); 01151 error_append(Ntk_NodeReadName(nodePtr)); 01152 bdd_recursive_deref(ddManager, currentDd); 01153 error_append("\n"); 01154 return NULL; 01155 } /* end of error */ 01156 /* construct the relation */ 01157 bdd_ref(nodeReln = bdd_add_apply(ddManager, bdd_add_xnor, yDd, functionArray[i])); 01158 01159 if (nodeReln == NULL) { /* error */ 01160 error_append("Null Dd returned on preimage compose - node reln stage"); 01161 error_append("Node: "); 01162 error_append(Ntk_NodeReadName(nodePtr)); 01163 bdd_recursive_deref(ddManager, yDd); 01164 bdd_recursive_deref(ddManager, currentDd); 01165 error_append("\n"); 01166 return NULL; 01167 } /* end of error */ 01168 /* perform the and of the and-abstract */ 01169 bdd_ref(andDd = bdd_add_apply(ddManager, bdd_add_times, currentDd, nodeReln)); 01170 bdd_recursive_deref(ddManager, currentDd); 01171 bdd_recursive_deref(ddManager, nodeReln); 01172 if (andDd == NULL) { /* error */ 01173 error_append("Null Dd returned on preimage compose - and dd stage"); 01174 error_append("Node: "); 01175 error_append(Ntk_NodeReadName(nodePtr)); 01176 error_append("\n"); 01177 bdd_recursive_deref(ddManager, yDd); 01178 return NULL; 01179 } /* end of error */ 01180 /* perform the abstract of the and-abstract */ 01181 bdd_ref(new_ = bdd_add_exist_abstract(ddManager, andDd, yDd)); 01182 bdd_recursive_deref(ddManager, andDd); 01183 bdd_recursive_deref(ddManager, yDd); 01184 if (new_ == NULL) { /* error */ 01185 error_append("Null Dd returned on preimage compose - and dd stage"); 01186 error_append("Node: "); 01187 error_append((char *)Ntk_NodeReadName(nodePtr)); 01188 error_append("\n"); 01189 return NULL; 01190 } /* end of error */ 01191 currentDd = new_; 01192 } 01193 break; 01194 } /* end of case Res_PreimageComputation_c */ 01195 } /* end of switch(method) */ 01196 01197 /* return the new composed Dd */ 01198 return new_; 01199 } /* End of ComposeLayersIntoResidue */ 01200 01201 01214 static Mvf_Function_t * 01215 NodeBuildConstantMvf( 01216 Ntk_Node_t * node, 01217 mdd_manager *mddMgr) 01218 { 01219 int value = 0; /* initialized to stop lint complaining */ 01220 mdd_t *oneMdd = mdd_one(mddMgr); 01221 Var_Variable_t *variable = Ntk_NodeReadVariable(node); 01222 int numVarValues = Var_VariableReadNumValues(variable); 01223 Mvf_Function_t *mvf = Mvf_FunctionAlloc(mddMgr, numVarValues); 01224 int outputIndex = Ntk_NodeReadOutputIndex(node); 01225 Tbl_Table_t *table = Ntk_NodeReadTable(node); 01226 01227 assert(Ntk_NodeTestIsConstant(node)); 01228 value = Tbl_TableReadConstValue(table, outputIndex); 01229 assert(value != -1); 01230 01231 Mvf_FunctionAddMintermsToComponent(mvf, value, oneMdd); 01232 mdd_free(oneMdd); 01233 return mvf; 01234 }