VIS

src/spfd/spfdOpt.c

Go to the documentation of this file.
00001 
00021 #include "spfdInt.h"
00022 
00023 /*---------------------------------------------------------------------------*/
00024 /* Constant declarations                                                     */
00025 /*---------------------------------------------------------------------------*/
00026 
00027 
00028 /*---------------------------------------------------------------------------*/
00029 /* Type declarations                                                         */
00030 /*---------------------------------------------------------------------------*/
00031 
00032 
00033 /*---------------------------------------------------------------------------*/
00034 /* Structure declarations                                                    */
00035 /*---------------------------------------------------------------------------*/
00036 
00037 
00038 /*---------------------------------------------------------------------------*/
00039 /* Variable declarations                                                     */
00040 /*---------------------------------------------------------------------------*/
00041 
00042 
00043 /*---------------------------------------------------------------------------*/
00044 /* Macro declarations                                                        */
00045 /*---------------------------------------------------------------------------*/
00046 
00047 
00050 /*---------------------------------------------------------------------------*/
00051 /* Static function prototypes                                                */
00052 /*---------------------------------------------------------------------------*/
00053 
00054 static int CompareConvexFanoutCountAndDepth(const void *obj1, const void *obj2);
00055 static int CompareConvexSwitchedCapAndDepth(const void *obj1, const void *obj2);
00056 
00060 /*---------------------------------------------------------------------------*/
00061 /* Definition of exported functions                                          */
00062 /*---------------------------------------------------------------------------*/
00063 
00064 
00065 /*---------------------------------------------------------------------------*/
00066 /* Definition of internal functions                                          */
00067 /*---------------------------------------------------------------------------*/
00099 int
00100 SpfdNetworkOptimize(
00101   Ntk_Network_t *network,
00102   char *simFile,
00103   int percent,
00104   int frequency,
00105   int regionDepth)
00106 {
00107   SpfdApplData_t *applData;
00108   Ntk_Node_t *node,*maxNode;
00109   int stop,iter,status;
00110   float randomValue;
00111   array_t *nodeArray;
00112   lsGen gen;
00113   st_generator *stGen;
00114   char *dummy;
00115   boolean replRem;
00116   array_t *inputArray,*patternArray,*intPatternArray;
00117   char *optName;
00118   
00119   /* To keep the compiler happy */
00120   inputArray = patternArray = intPatternArray = NIL(array_t);
00121 
00122   /* Check if both wire removal and replacement are to be done */
00123   optName = Cmd_FlagReadByName("spfd_repl_rem");
00124   if (optName && (strcmp(optName,"yes") == 0)) {
00125     replRem = TRUE;
00126   } else {
00127     replRem = FALSE;
00128   }
00129 
00130   /* First initialize the simulation package. This will also levelize
00131      the nodes in the network. The level info is stored in local data
00132      structure of 'truesim' package'. This is needed even if we do not
00133      perform vector simulation. */
00134   Truesim_InitializeSimulation(network,NIL(char),0,-1,0,NIL(st_table));
00135   if (spfdPerfSim) { /* Perform simulation? */
00136     /* Array of primary input nodes */
00137     inputArray = array_alloc(Ntk_Node_t *,0);
00138     /* Array of simulation vectors */
00139     patternArray = array_alloc(char *,0);
00140     status = Truesim_ReadSimulationVectors(network,simFile,
00141                                            inputArray,patternArray);
00142     /* Error while reading simulation vectors */
00143     if (!status) {
00144       array_free(inputArray);
00145       array_free(patternArray);
00146       (void) fprintf(vis_stdout, "** spfd error: Error reading simulation"
00147                      " vector file. \n");
00148       return 0;
00149     }
00150     Truesim_ZeroDelayPatternSimulate(network,inputArray,patternArray);
00151 
00152     /* Select a random start for the set of internal simulation
00153        vectors. We simulate only a portion of vectors (during
00154        optimization iterations) to get a coarse estimate of circuit
00155        node switching activities. */
00156     randomValue = ((double)util_random()/(double)(MODULUS1 - 2));
00157     if (randomValue > (double) (1.0 - ((double)percent)/((double)100)))
00158       randomValue = (1.0 - ((double)percent)/((double)100))/2.0;
00159     /* Partial set of simulation vectors */
00160     intPatternArray = SpfdFetchInternalPatternArray(patternArray,percent,
00161                                                     randomValue);
00162   }
00163   
00164   /* Initialize the package application data structure */
00165   applData = SpfdInitializeApplData(network);
00166   iter = 1;
00167 
00168   do {
00169     if (spfdVerbose > 2) {
00170       (void) fprintf(vis_stdout, "** spfd info: Iteration %d\n",iter);
00171     }
00172     nodeArray = array_alloc(Ntk_Node_t *,0);
00173 
00174     /* Collect circuit nodes, later needed to be sorted. Only the
00175        internal nodes will be sorted.*/
00176     switch (spfdMethod) {
00177     case REDUCE_FANIN_WIRES:
00178     case OPTIMIZE_MAX_NODE:
00179       Ntk_NetworkForEachNode(network,gen,node) {
00180         if (!Ntk_NodeTestIsPrimaryOutput(node) &&
00181             !Ntk_NodeTestIsPrimaryInput(node) &&
00182             !SpfdNodeReadLocked(applData,node)) 
00183           array_insert_last(Ntk_Node_t *,nodeArray,node);
00184       }
00185       break;
00186     case OPTIMIZE_FANIN_NODES:
00187       Ntk_NetworkForEachNode(network,gen,node) {
00188         if (!Ntk_NodeTestIsPrimaryInput(node) &&
00189             !SpfdNodeReadLocked(applData,node)) 
00190           array_insert_last(Ntk_Node_t *,nodeArray,node);
00191       }
00192       break;
00193     case REDUCE_FANOUT_WIRES:
00194       Ntk_NetworkForEachNode(network,gen,node) {
00195         if (!SpfdNodeReadLocked(applData,node)) 
00196           array_insert_last(Ntk_Node_t *,nodeArray,node);
00197       }
00198       break;
00199     }
00200     
00201     /* Find the node with max. fanout/switched cap., or a random node */
00202     maxNode = SpfdFindNode(network,nodeArray);
00203     if (!maxNode)
00204       stop = 1;
00205     else 
00206       stop = 0;
00207     array_free(nodeArray);
00208     
00209     /* Optimize. */
00210     if (!stop) {
00211       switch (spfdMethod) {
00212       case REDUCE_FANIN_WIRES:
00213         SpfdOptimizeFaninWires(network,maxNode,regionDepth,replRem);
00214         break;
00215       case OPTIMIZE_MAX_NODE:
00216         SpfdOptimizeNode(network,maxNode,regionDepth);
00217         break;
00218       case OPTIMIZE_FANIN_NODES:
00219         SpfdOptimizeFaninNodes(network,maxNode,regionDepth);
00220         break;
00221       case REDUCE_FANOUT_WIRES:
00222         SpfdOptimizeFanoutWires(network,maxNode,regionDepth,replRem);
00223         break;
00224       }
00225       /* If the network has changed (structurally), update the depth
00226          information to reflect the change in the network.*/
00227       if (spfdNtkChanged) {
00228         Truesim_NetworkUpdateNodeTopologicalDepth(network);
00229         spfdNtkChanged = FALSE;
00230       }
00231       if (spfdPerfSim && (iter % frequency == 0)) {
00232         Truesim_ZeroDelayPatternSimulate(network,inputArray,intPatternArray);
00233       }
00234     }
00235     iter++;
00236   } while (!stop);
00237   
00238   if (spfdPerfSim) {
00239     /* End simulation; free memory */
00240     Truesim_QuitSimulation(network);
00241     array_free(inputArray);
00242     array_free(patternArray);
00243   }
00244   
00245   /* Print the number of wires removed and delete the sinkTable. */
00246   fprintf(vis_stdout,"** spfd info: # of wires removed = %d\n",
00247           spfdNumWiresRem - spfdWiresAdded);
00248   fprintf(vis_stdout,"** spfd info: # of nodes removed = %d\n",
00249           st_count(applData->nodesRemoved));
00250 
00251   /* Free the memory for each node */
00252   st_foreach_item(applData->nodesRemoved,stGen,&node,&dummy) {
00253     if (node) Ntk_NodeFree(node);
00254   }
00255   
00256   return 1;
00257   
00258 } /* End of SpfdNetworkOptimize */
00259 
00260 #if 0
00261 
00271 void
00272 SpfdProcessFanoutWires(
00273   Ntk_Network_t *network,
00274   Ntk_Node_t *maxNode,
00275   int regionDepth,
00276   boolean replRem)
00277 {
00278   SpfdApplData_t *applData;
00279   array_t *fanoutArray,*replArray;
00280   st_table *wiresRemoved,*sinkTable;
00281   st_generator *stGen;
00282   Ntk_Node_t *ntkNode,*tempNode,*replNode;
00283   int i,num;
00284 
00285   /* Package application data structure */
00286   applData = Ntk_NetworkReadApplInfo(network,SPFD_NETWORK_APPL_KEY);
00287 
00288   fanoutArray = array_dup(Ntk_NodeReadFanouts(maxNode));
00289   for (i = array_n(fanoutArray) - 1; i >=0; i--) {
00290     ntkNode = array_fetch(Ntk_Node_t *,fanoutArray,i);
00291     
00292     /* Skip POs */
00293     if (Ntk_NodeTestIsPrimaryOutput(ntkNode))
00294       continue;
00295 
00296     /* Could be removed during an earlier iteration */
00297     if (!st_lookup(applData->nodesRemoved,(char *)ntkNode,NIL(char *))) {
00298       array_t *regionArray;
00299   
00300       /* regionArray is an array of nodes sorted according to their depth. */
00301       regionArray = SpfdNodeComputeFanoutRegion(applData,ntkNode,regionDepth);
00302 
00303       /* Analyze region's BDD requirements */
00304       SpfdComputeRequiredGlobalBdds(network,applData);
00305 
00306       /* Analyze auxilarry BDD ID requirements */
00307       SpfdAllocateOrReuseAuxVariables(network,applData);
00308 
00309       /* Order the fanin of internal and boundary nodes */
00310       if (spfdPerfSim) {
00311         SpfdOrderFaninOfRegionNodes(network,applData,
00312                                     SpfdSwitchedCapAndDepthCompare);
00313       } else {
00314         SpfdOrderFaninOfRegionNodes(network,applData,
00315                                     SpfdFanoutCountAndDepthCompare);
00316       }
00317     
00318       /* Set the spfds for nodes in the region. The spfds are reduced to a
00319          single pair and the localAlt is set to one of the components of the
00320          single pair SPFD. */
00321       SpfdRegionComputeSinglePairSpfd(network,applData,regionArray);
00322 
00323       /* Now check if the spfd of wire maxNode --> ntkNode is
00324          empty. Remove the spfd of ntkNode as it was not deleted in
00325          SpfdRegionComputeSinglePairSpfd */
00326       /* Compute array of potential candidates for replacement */
00327       if (replRem)
00328         replArray = SpfdNodeComputeTFIUntilDepth(ntkNode,regionDepth);
00329       else
00330         replArray = NIL(array_t);
00331       replNode = SpfdCheckIfWireIsRedundantOrReplaceable(network,applData,
00332                                                          maxNode,ntkNode,
00333                                                          replArray);
00334       /* No longer needed. */
00335       SpfdNodeDeleteSpfd(applData,ntkNode);
00336       if (replArray)
00337         array_free(replArray);
00338       
00339       /* Check to see if wires have been found to be
00340          redundant/replaceable. If no wires are to be
00341          removed/replaced, then decide whether or not to reprogram. */
00342       if (st_count(applData->currWireTable) == 0 &&
00343           st_count(applData->currReplaceTable) == 0 &&
00344           !spfdReprogNoWire) {
00345         /* In this case just clean up currBddReq, localAlt
00346            and globalAlt. */
00347         st_table *currBddReq;
00348         st_generator *stGen;
00349         Ntk_Node_t *regNode;
00350         bdd_node *bdd1;
00351         bdd_manager *ddManager;
00352         int j;
00353 
00354         ddManager = applData->ddManager;
00355         currBddReq = applData->currBddReq;
00356         
00357         /* Clean up currBddReq */
00358         st_foreach_item(currBddReq,stGen,(char **)&regNode,(char **)&bdd1) {
00359           bdd_recursive_deref(ddManager,bdd1);
00360         }
00361         st_free_table(currBddReq);
00362         applData->currBddReq = NIL(st_table);
00363 
00364         /* Clean up localAlt and globalAlt of region nodes */
00365         arrayForEachItem(Ntk_Node_t *,regionArray,j,regNode) {
00366           SpfdNodeDeleteGlobalAlternative(applData,regNode);
00367           SpfdNodeDeleteLocalAlt(applData,regNode);
00368         }
00369       } else {
00370         /* Now reprogram the nodes in the region. */
00371         SpfdReprogramRegionNodes(network,applData,regionArray);
00372       }
00373 
00374       /* In this subroutine we have only a single wire
00375          replaced. Delete just that data */
00376       if (replNode) {
00377         SpfdNodeDeleteGlobalAlternative(applData,replNode);
00378         SpfdNodeSetAuxId(applData,replNode,-1);
00379         st_delete(applData->currReplaceTable,(char **)&ntkNode,
00380                   (char **)&sinkTable);
00381         st_free_table(sinkTable);
00382         
00383         /* A small caveat: sometimes a wire added can be later
00384            removed. Check if the replNode --> ntkNode still exists. If
00385            not set replNode to NULL. */
00386         wiresRemoved = applData->wiresRemoved;
00387         if (st_lookup(wiresRemoved,(char *)replNode,(char **)&sinkTable) &&
00388             st_lookup(sinkTable,(char *)ntkNode,NIL(char *))) {
00389           /* Reduce the number of wires added and delete
00390              replNode->ntkNode from wiresRemoved table */
00391           spfdWiresAdded--;
00392           st_delete(sinkTable,(char **)&ntkNode,NIL(char *));
00393           if (st_count(sinkTable) < 1) {
00394             st_delete(wiresRemoved,(char **)&replNode,(char **)&sinkTable);
00395             st_free_table(sinkTable);
00396           }
00397           replNode = NIL(Ntk_Node_t);
00398         }
00399       }
00400       
00401       /* Clean up auxIds and piAltVars*/
00402       SpfdCleanUpAuxIds(applData);
00403       
00404       /* Free stuff used only for the current iteration */
00405       if (applData->currXCube) {
00406         bdd_recursive_deref(applData->ddManager,applData->currXCube);
00407         applData->currXCube = NIL(bdd_node);
00408       }
00409       if (applData->currRegionNodes) {
00410         st_free_table(applData->currRegionNodes);
00411         applData->currRegionNodes = NIL(st_table);
00412       }
00413       if (applData->currInUseVars) {
00414         st_free_table(applData->currInUseVars);
00415         applData->currInUseVars = NIL(st_table);
00416       }
00417 
00418       num = st_count(applData->currWireTable);
00419       assert(num == 0);
00420 
00421       num = st_count(applData->currReplaceTable);
00422       assert(num == 0);
00423       
00424       /* Update the total number of wires removed */
00425       wiresRemoved = applData->wiresRemoved;
00426       if (st_count(wiresRemoved) > 0) {
00427         st_foreach_item(wiresRemoved,stGen,(char **)&tempNode,
00428                         (char **)&sinkTable){
00429           spfdNumWiresRem += st_count(sinkTable);
00430         }
00431         
00432         /* free the wiresRemoved contents */
00433         st_foreach(wiresRemoved,SpfdStTableClean,NIL(char));
00434       }
00435       
00436       /* Free regionArray (cluster) */
00437       array_free(regionArray);
00438     }
00439   }
00440   array_free(fanoutArray);
00441   
00442   /* Lock the node */
00443   SpfdNodeSetLocked(applData,maxNode,TRUE);
00444   
00445 } /* End of SpfdProcessFanoutWires */
00446 #endif
00447 
00457 Ntk_Node_t *
00458 SpfdCheckIfWireIsRedundantOrReplaceable(
00459   Ntk_Network_t *network,
00460   SpfdApplData_t *applData,
00461   Ntk_Node_t *from,
00462   Ntk_Node_t *to,
00463   array_t *replaceArray)
00464 {
00465   bdd_manager *ddManager = applData->ddManager;
00466   bdd_node *result,*ddTemp,*ddTemp2,*var,*varAux;
00467   bdd_node *toSpfd,*wireSpfd,*logicZero;
00468   int i,index;
00469   Ntk_Node_t *fanin,*tempNode,*replNode;
00470   st_table *wireTable = applData->currWireTable;
00471   st_table *wiresRemoved = applData->wiresRemoved;
00472   st_table *sinkTable;
00473 
00474   /* Possible replacement node */
00475   replNode = NIL(Ntk_Node_t);
00476   logicZero = bdd_read_logic_zero(ddManager);
00477 
00478   /* Check if this wire has already been removed. */
00479   if (!(st_lookup(wiresRemoved,(char *)from,&sinkTable) &&
00480       st_lookup(sinkTable,(char *)to,&tempNode))) {
00481   
00482     bdd_ref(result = bdd_read_one(ddManager));
00483 
00484     /* Compute the characteristic function of pairs of minterms cannot
00485        be distinguished any fanin of 'to'. Let f_i be the ith fanin of
00486        'to'. We compute result = \prod f_i == f'_i, where f_i != from */
00487     Ntk_NodeForEachFanin(to,i,fanin) {
00488       var = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
00489       index = SpfdNodeReadAuxId(applData,fanin);
00490       varAux = bdd_bdd_ith_var(ddManager,index);
00491       
00492       if (fanin != from) {
00493         bdd_ref(ddTemp = bdd_bdd_xnor(ddManager,var,varAux)); /* XNOR */
00494         bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,result,ddTemp));
00495         bdd_recursive_deref(ddManager,result);
00496         bdd_recursive_deref(ddManager,ddTemp);
00497         result = ddTemp2;
00498       }
00499     }
00500     /* Finally put in f_i == f_i', where f_i = from) */
00501     var = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(from));
00502     index = SpfdNodeReadAuxId(applData,from);
00503     varAux = bdd_bdd_ith_var(ddManager,index);
00504     bdd_ref(ddTemp = bdd_bdd_xor(ddManager,var,varAux));
00505     bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,result,ddTemp));
00506     bdd_recursive_deref(ddManager,result);
00507     bdd_recursive_deref(ddManager,ddTemp);
00508     result = ddTemp2;
00509 
00510     /* Compute AND of result and the SPFD of 'to'. */
00511     toSpfd = SpfdNodeReadSpfd(applData,to);
00512     if (toSpfd == NIL(bdd_node)) {
00513       (void) fprintf(vis_stderr,
00514                      "** spfd error: Spfd expected but not found.\n");
00515       exit(0);
00516     }
00517     bdd_ref(wireSpfd = bdd_bdd_and(ddManager,toSpfd,result));
00518     bdd_recursive_deref(ddManager,result);
00519 
00520     if (wireSpfd == logicZero) { /* Can the wire be removed? */
00521       if (spfdVerbose > 1)
00522         (void) fprintf(vis_stdout,
00523                        "** spfd info: Target wire %s --> %s has empty spfd.\n",
00524                        Ntk_NodeReadName(from),Ntk_NodeReadName(to));
00525 
00526       /* Insert the wire into wireTable */
00527       if (st_lookup(wireTable,(char *)from,&sinkTable)) {
00528         st_insert(sinkTable,(char *)to,(char *)to);
00529       } else {
00530         sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
00531         st_insert(sinkTable,(char *)to,(char *)to);
00532         st_insert(wireTable,(char *)from,(char *)sinkTable);
00533       }
00534       bdd_recursive_deref(ddManager,wireSpfd);
00535     } else if (replaceArray != NIL(array_t)) {
00536       /* Try for replacement. Exit after finding the first one. Here the
00537          assumption is that the nodes are sorted according to some
00538          criterion. */
00539       replNode = SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd(network,replaceArray,
00540                                                            from,to,wireSpfd);
00541       bdd_recursive_deref(ddManager,wireSpfd);
00542     } else {
00543       bdd_recursive_deref(ddManager,wireSpfd);
00544     }
00545   }
00546   
00547   return replNode;
00548   
00549 } /* End of SpfdCheckIfWireIsRedundantOrReplaceable */
00550 
00551 
00560 Ntk_Node_t *
00561 SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd(
00562   Ntk_Network_t *network,
00563   array_t *replaceArray,
00564   Ntk_Node_t *from,
00565   Ntk_Node_t *to,
00566   bdd_node *wireSpfd)
00567 {
00568   SpfdApplData_t *applData;
00569   bdd_manager *ddManager;
00570   st_table *leavesTable,*inUseVars,*replaceTable;
00571   st_table *sinkTable,*currBddReq;
00572   bdd_t *mddOne;
00573   lsGen gen;
00574   Ntk_Node_t *fanin,*node,*replNode;
00575   Ntk_Node_t *foundNode;
00576   array_t *nodeMvfs,*nodeBdds;
00577   bdd_node *bdd1,*xCube,*yVar;
00578   bdd_node **tempVars,**firstCompose,**secondCompose;
00579   bdd_node *step1,*step2,*step3,*step4,*step5;
00580   bdd_node *logicZero;
00581   int i,j,size,replId,id,auxId;
00582   
00583   applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
00584                                                         SPFD_NETWORK_APPL_KEY);
00585   ddManager = applData->ddManager;
00586   inUseVars = applData->currInUseVars;
00587   replaceTable = applData->currReplaceTable;
00588   currBddReq = applData->currBddReq;
00589   
00590   mddOne = bdd_one(ddManager);
00591   logicZero = bdd_read_logic_zero(ddManager);
00592   
00593   /* Collect the leaf nodes of the network. */
00594   leavesTable = st_init_table(st_ptrcmp, st_ptrhash);
00595   Ntk_NetworkForEachCombInput(network,gen,node) {
00596     st_insert(leavesTable,(char *)node,(char *) -1);
00597   }
00598 
00599   /* Compute the global MVFs of the nodes in replaceArray */
00600   nodeMvfs = Ntm_NetworkBuildMvfs(network,replaceArray,leavesTable,mddOne);
00601   bdd_free(mddOne);
00602   st_free_table(leavesTable);
00603 
00604   /* Collect node global Bdds */
00605   nodeBdds = array_alloc(bdd_node *,0);
00606   arrayForEachItem(Ntk_Node_t *,replaceArray,i,node) {
00607     Mvf_Function_t *mvf;
00608     mvf = array_fetch(Mvf_Function_t *,nodeMvfs,i);
00609     bdd1 = bdd_extract_node_as_is(array_fetch(bdd_t *,mvf,1));
00610     bdd_ref(bdd1);
00611     array_insert_last(bdd_node *,nodeBdds,bdd1);
00612   }
00613   Mvf_FunctionArrayFree(nodeMvfs);
00614 
00615   /* Now check one at a time if global function satisfies wireSpfd */
00616   foundNode = NIL(Ntk_Node_t);
00617   xCube = applData->currXCube;
00618   arrayForEachItem(Ntk_Node_t *,nodeBdds,i,bdd1) {
00619     int idAllocated;
00620 
00621     idAllocated = 0;
00622     replNode = array_fetch(Ntk_Node_t *,replaceArray,i);
00623     replId = Ntk_NodeReadMddId(replNode);
00624     /* Check if replId is already in use. This is possible is outside
00625        the cluster. */
00626     if (st_lookup(inUseVars,(char *)(long)replId,NIL(char *))) {
00627       /* Allocate yVar and yAuxVar for replNode */
00628       tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,1);
00629       yVar = tempVars[0];
00630       idAllocated = 1;
00631       FREE(tempVars);
00632     } else { /* replId not in use */
00633       yVar = bdd_bdd_ith_var(ddManager,replId);
00634     }
00635 
00636     /* Now perform the following steps, using two compositions. */
00637     /* 1. step1 = yVar == bdd1
00638        2. step2 = wireSpfd(Y,Y') --> wireSpfd(x,Y')
00639        3. step3 = \exists_x step1 * step2
00640        4. step4 = step3(yVar,Y') --> step3(yVar,x)
00641        5. step5 = \exists_x step1 * step4
00642 
00643        If step5 == logicZero, then replNode is a candidate */
00644 
00645     /* Prepare compose arrays for the above steps */
00646     size = bdd_num_vars(ddManager);
00647     firstCompose = ALLOC(bdd_node *,size);
00648     secondCompose = ALLOC(bdd_node *,size);
00649     for (j = 0; j < size; j++) {
00650       firstCompose[j] = bdd_bdd_ith_var(ddManager,j);
00651       secondCompose[j] = bdd_bdd_ith_var(ddManager,j);
00652     }
00653 
00654     Ntk_NodeForEachFanin(to,j,fanin) {
00655       id = Ntk_NodeReadMddId(fanin);
00656       auxId = SpfdNodeReadAuxId(applData,fanin);
00657       st_lookup(currBddReq,(char *)fanin,(char **)&firstCompose[id]);
00658       secondCompose[auxId] = firstCompose[id];
00659     }
00660 
00661     bdd_ref(step1 = bdd_bdd_xnor(ddManager,yVar,bdd1));
00662     bdd_ref(step2 = bdd_bdd_vector_compose(ddManager,wireSpfd,firstCompose));
00663     FREE(firstCompose);
00664     bdd_ref(step3 = bdd_bdd_and_abstract(ddManager,step1,step2,xCube));
00665     bdd_recursive_deref(ddManager,step2);
00666     bdd_ref(step4 = bdd_bdd_vector_compose(ddManager,step3,secondCompose));
00667     bdd_recursive_deref(ddManager,step3);
00668     FREE(secondCompose);
00669     bdd_ref(step5 = bdd_bdd_and_abstract(ddManager,step1,step4,xCube));
00670     bdd_recursive_deref(ddManager,step4);
00671     bdd_recursive_deref(ddManager,step1);
00672 
00673     /* Now if step5 is zero, then return replNode as the candidate. I will use
00674        the globalAlt field of the node to store the global BDD. This way I
00675        don't have to recompute the global BDD later.  */
00676     if (step5 == logicZero) {
00677       bdd_recursive_deref(ddManager,step5);
00678       bdd_ref(bdd1);
00679       SpfdNodeSetGlobalAlternative(applData,replNode,bdd1);
00680 
00681       /* Allocate an auxId for this node. It will be needed during
00682          reprogramming. */
00683       if (idAllocated) {
00684         auxId = bdd_node_read_index(yVar);
00685       } else {
00686         tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,1);
00687         auxId = bdd_node_read_index(tempVars[0]);
00688         FREE(tempVars);
00689       }
00690       SpfdNodeSetAuxId(applData,replNode,auxId);
00691       st_insert(inUseVars,(char *)(long)replId,(char *)-1);
00692       st_insert(inUseVars,(char *)(long)auxId,(char *)-1);
00693       
00694       /* Insert information in replaceTable */
00695       if (st_lookup(replaceTable,(char *)to,&sinkTable)) {
00696         st_insert(sinkTable,(char *)from,(char *)replNode);
00697       } else {
00698         sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
00699         st_insert(sinkTable,(char *)from,(char *)replNode);
00700         st_insert(replaceTable,(char *)to,(char *)sinkTable);
00701       }
00702       foundNode = replNode;
00703       break;
00704     } else {
00705       bdd_recursive_deref(ddManager,step5);
00706       /* release the id */
00707       if (idAllocated) {
00708         id = bdd_node_read_index(yVar);
00709         st_delete(inUseVars, &id, NIL(char *));
00710       }
00711     }
00712   }
00713 
00714   /* Free the nodeBdds */
00715   arrayForEachItem(bdd_node *,nodeBdds,i,bdd1) {
00716     bdd_recursive_deref(ddManager,bdd1);
00717   }
00718   array_free(nodeBdds);
00719 
00720   return foundNode;
00721 } /* End of SpfdTestIfNodeGlobalFuncSatisfiesWireSpfd */
00722 
00723 
00733 void
00734 SpfdOptimizeFaninWires(
00735   Ntk_Network_t *network,
00736   Ntk_Node_t *maxNode,
00737   int regionDepth,
00738   boolean replRem)
00739 {
00740   SpfdApplData_t *applData;
00741   array_t *faninArray;
00742   Ntk_Node_t *ntkNode,*fanout;
00743   char *dummy;
00744   int i,j;
00745 
00746   applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
00747                                                         SPFD_NETWORK_APPL_KEY);
00748   
00749   /* replace/remove the fanin wire of maxNode one at a time. The fanin
00750      node with higher switched capacitance will be optimized first. */
00751   faninArray = array_dup(Ntk_NodeReadFanins(maxNode));
00752   if (spfdPerfSim)
00753     array_sort(faninArray,CompareConvexSwitchedCapAndDepth);
00754   else
00755     array_sort(faninArray,CompareConvexFanoutCountAndDepth);
00756 
00757   for (i = array_n(faninArray) - 1; i >=0; i--) {
00758     boolean skip;
00759     ntkNode = array_fetch(Ntk_Node_t *,faninArray,i);
00760     if (!st_lookup(applData->nodesRemoved,(char *)ntkNode,(char **)&dummy)) {
00761       skip = TRUE;
00762       /* Check if the current fanin node is still in the support of
00763          maxNode. */
00764       Ntk_NodeForEachFanout(ntkNode,j,fanout) {
00765         if (fanout == maxNode) {
00766           skip = FALSE;
00767           break;
00768         }
00769       }
00770     } else {
00771       skip = TRUE;
00772     }
00773     if (!skip)
00774       SpfdOptimizeWire(network,ntkNode,maxNode,regionDepth,replRem);
00775   }
00776   array_free(faninArray);
00777 
00778   /* Lock the node */
00779   SpfdNodeSetLocked(applData,maxNode,TRUE);
00780   
00781   return ;
00782   
00783 } /* End of SpfdOptimizeFaninWires */
00784 
00785 
00795 void
00796 SpfdOptimizeFanoutWires(
00797   Ntk_Network_t *network,
00798   Ntk_Node_t *maxNode,
00799   int regionDepth,
00800   boolean replRem)
00801 {
00802   SpfdApplData_t *applData;
00803   array_t *fanoutArray;
00804   Ntk_Node_t *ntkNode,*fanout;
00805   int i,j;
00806   
00807   applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
00808                                                         SPFD_NETWORK_APPL_KEY);
00809 
00810   /* replace/remove the fanout wires of maxNode one at a time. The fanout
00811      node with higher switched capacitance will be optimized first. */
00812   fanoutArray = array_dup(Ntk_NodeReadFanouts(maxNode));
00813   if (spfdPerfSim)
00814     array_sort(fanoutArray,CompareConvexSwitchedCapAndDepth);
00815   else
00816     array_sort(fanoutArray,CompareConvexFanoutCountAndDepth);
00817 
00818 
00819   for (i = array_n(fanoutArray) - 1; i >=0; i--) {
00820     boolean skip;
00821     ntkNode = array_fetch(Ntk_Node_t *,fanoutArray,i);
00822     skip = TRUE;
00823     /* Check if the maxNode is still in the support of fanout. */
00824     Ntk_NodeForEachFanout(maxNode,j,fanout) {
00825       if (fanout == ntkNode) {
00826         skip = FALSE;
00827         break;
00828       }
00829     }
00830     if (!skip)    
00831       SpfdOptimizeWire(network,maxNode,ntkNode,regionDepth,replRem);
00832   }
00833   array_free(fanoutArray);
00834 
00835   /* Lock the node */
00836   SpfdNodeSetLocked(applData,maxNode,TRUE);
00837   
00838   return ;
00839   
00840 } /* End of SpfdOptimizeFanoutWires */
00841 
00842 
00850 void
00851 SpfdOptimizeFaninNodes(
00852   Ntk_Network_t *network,
00853   Ntk_Node_t *maxNode,
00854   int regionDepth)
00855 {
00856   SpfdApplData_t *applData;
00857   array_t *faninArray;
00858   Ntk_Node_t *ntkNode;
00859   char *dummy;
00860   int i;
00861 
00862   applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
00863                                                         SPFD_NETWORK_APPL_KEY);
00864 
00865   /* Optimize fanin nodes one at a time. The fanin node with higher
00866      switched capacitance will be optimized first. */
00867   faninArray = array_dup(Ntk_NodeReadFanins(maxNode));
00868   if (spfdPerfSim)
00869     array_sort(faninArray,CompareConvexSwitchedCapAndDepth);
00870   else
00871     array_sort(faninArray,CompareConvexFanoutCountAndDepth);
00872 
00873   for (i = array_n(faninArray) - 1; i >=0; i--) {
00874     boolean skip = FALSE;
00875     ntkNode = array_fetch(Ntk_Node_t *,faninArray,i);
00876     if (st_lookup(applData->nodesRemoved,(char *)ntkNode,(char **)&dummy)) {
00877       skip = TRUE;
00878     }
00879     if (!skip)
00880       SpfdOptimizeNode(network,ntkNode,regionDepth);
00881   }
00882   array_free(faninArray);
00883 
00884   /* Lock the node */
00885   SpfdNodeSetLocked(applData,maxNode,TRUE);
00886   
00887   return ;
00888   
00889 } /* End of SpfdOptimizeFaninNodes */
00890 
00891 
00902 void
00903 SpfdOptimizeWire(
00904   Ntk_Network_t *network,
00905   Ntk_Node_t *maxNode,
00906   Ntk_Node_t *ntkNode,
00907   int regionDepth,
00908   boolean replRem)
00909 {
00910   SpfdApplData_t *applData;
00911   array_t *replArray;
00912   st_table *wiresRemoved,*sinkTable;
00913   st_generator *stGen;
00914   Ntk_Node_t *tempNode,*replNode;
00915   array_t *regionArray;
00916   int num;
00917 
00918   /* Package application data structure */
00919   applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
00920                                                         SPFD_NETWORK_APPL_KEY);
00921 
00922   /* Skip POs */
00923   if (Ntk_NodeTestIsPrimaryOutput(ntkNode))
00924     return;
00925   
00926   /* regionArray is an array of nodes sorted according to their depth. */
00927   regionArray = SpfdNodeComputeFanoutRegion(applData,ntkNode,regionDepth);
00928 
00929   /* Analyze region's BDD requirements */
00930   SpfdComputeRequiredGlobalBdds(network,applData);
00931   
00932   /* Analyze auxilarry BDD ID requirements */
00933   SpfdAllocateOrReuseAuxVariables(network,applData);
00934   
00935   /* Order the fanin of internal and boundary nodes */
00936   if (spfdPerfSim) {
00937     SpfdOrderFaninOfRegionNodes(network,applData,
00938                                 SpfdSwitchedCapAndDepthCompare);
00939   } else {
00940     SpfdOrderFaninOfRegionNodes(network,applData,
00941                                 SpfdFanoutCountAndDepthCompare);
00942   }
00943     
00944   /* Set the spfds for nodes in the region. The spfds are reduced to a
00945      single pair and the localAlt is set to one of the components of the
00946      single pair SPFD. */
00947   SpfdRegionComputeSinglePairSpfd(network,applData,regionArray);
00948   
00949   /* Now check if the spfd of wire maxNode --> ntkNode is
00950      empty. Remove the spfd of ntkNode as it was not deleted in
00951      SpfdRegionComputeSinglePairSpfd */
00952   /* Compute array of potential candidates for replacement */
00953   if (replRem)
00954     replArray = SpfdNodeComputeTFIUntilDepth(ntkNode,regionDepth);
00955   else
00956     replArray = NIL(array_t);
00957   replNode = SpfdCheckIfWireIsRedundantOrReplaceable(network,applData,
00958                                                      maxNode,ntkNode,
00959                                                      replArray);
00960   /* SPFD of ntkNode is no longer needed. */
00961   SpfdNodeDeleteSpfd(applData,ntkNode);
00962   if (replArray)
00963     array_free(replArray);
00964       
00965   /* Check to see if wires have been found to be
00966      redundant/replaceable. If no wires are to be
00967      removed/replaced, then decide whether or not to reprogram. */
00968   if (st_count(applData->currWireTable) == 0 &&
00969       st_count(applData->currReplaceTable) == 0 &&
00970       !spfdReprogNoWire) {
00971     /* In this case just clean up currBddReq, localAlt
00972        and globalAlt. */
00973     st_table *currBddReq;
00974     st_generator *stGen;
00975     Ntk_Node_t *regNode;
00976     bdd_node *bdd1;
00977     bdd_manager *ddManager;
00978     int j;
00979     
00980     ddManager = applData->ddManager;
00981     currBddReq = applData->currBddReq;
00982     
00983     /* Clean up currBddReq */
00984     st_foreach_item(currBddReq,stGen,&regNode,&bdd1) {
00985       bdd_recursive_deref(ddManager,bdd1);
00986     }
00987     st_free_table(currBddReq);
00988     applData->currBddReq = NIL(st_table);
00989     
00990     /* Clean up localAlt and globalAlt of region nodes */
00991     arrayForEachItem(Ntk_Node_t *,regionArray,j,regNode) {
00992       SpfdNodeDeleteGlobalAlternative(applData,regNode);
00993       SpfdNodeDeleteLocalAlt(applData,regNode);
00994     }
00995   } else {
00996     /* Now reprogram the nodes in the region. */
00997     SpfdReprogramRegionNodes(network,applData,regionArray);
00998   }
00999   
01000   /* In this subroutine we have only a single wire
01001      replaced. Delete just that data */
01002   if (replNode) {
01003     SpfdNodeDeleteGlobalAlternative(applData,replNode);
01004     SpfdNodeSetAuxId(applData,replNode,-1);
01005     st_delete(applData->currReplaceTable,&ntkNode,
01006               &sinkTable);
01007     st_free_table(sinkTable);
01008     
01009     /* A small caveat: sometimes a wire added can be later
01010        removed. Check if the replNode --> ntkNode still exists. If
01011        not set replNode to NULL. */
01012     wiresRemoved = applData->wiresRemoved;
01013     if (st_lookup(wiresRemoved,(char *)replNode,&sinkTable) &&
01014         st_lookup(sinkTable,(char *)ntkNode,NIL(char *))) {
01015       /* Reduce the number of wires added and delete
01016          replNode->ntkNode from wiresRemoved table */
01017       spfdWiresAdded--;
01018       st_delete(sinkTable,&ntkNode,NIL(char *));
01019       if (st_count(sinkTable) < 1) {
01020         st_delete(wiresRemoved,&replNode,&sinkTable);
01021         st_free_table(sinkTable);
01022       }
01023       replNode = NIL(Ntk_Node_t);
01024     }
01025   }
01026       
01027   /* Clean up auxIds and piAltVars*/
01028   SpfdCleanUpAuxIds(applData);
01029   
01030   /* Free stuff used only for the current wire */
01031   if (applData->currXCube) {
01032     bdd_recursive_deref(applData->ddManager,applData->currXCube);
01033     applData->currXCube = NIL(bdd_node);
01034   }
01035   if (applData->currRegionNodes) {
01036     st_free_table(applData->currRegionNodes);
01037     applData->currRegionNodes = NIL(st_table);
01038   }
01039   if (applData->currInUseVars) {
01040     st_free_table(applData->currInUseVars);
01041     applData->currInUseVars = NIL(st_table);
01042   }
01043   
01044   num = st_count(applData->currWireTable);
01045   assert(num == 0);
01046   
01047   num = st_count(applData->currReplaceTable);
01048   assert(num == 0);
01049   
01050   /* Update the total number of wires removed. */
01051   wiresRemoved = applData->wiresRemoved;
01052   if (st_count(wiresRemoved) > 0) {
01053     st_foreach_item(wiresRemoved,stGen,&tempNode,
01054                     &sinkTable){
01055       spfdNumWiresRem += st_count(sinkTable);
01056     }
01057     
01058     /* free the wiresRemoved contents */
01059     st_foreach(wiresRemoved,SpfdStTableClean,NIL(char));
01060   }
01061   
01062   /* Free regionArray (cluster) */
01063   array_free(regionArray);
01064   
01065   return ;
01066   
01067 } /* End of SpfdOptimizeWire */
01068 
01069 
01080 void
01081 SpfdOptimizeNode(
01082   Ntk_Network_t *network,
01083   Ntk_Node_t *ntkNode,
01084   int regionDepth)
01085 {
01086   SpfdApplData_t *applData;
01087   st_table *wiresRemoved,*sinkTable;
01088   st_generator *stGen;
01089   Ntk_Node_t *tempNode;
01090   array_t *regionArray;
01091   int num;
01092 
01093   /* Package application data structure */
01094   applData = (SpfdApplData_t *) Ntk_NetworkReadApplInfo(network,
01095                                                         SPFD_NETWORK_APPL_KEY);
01096 
01097   /* Skip POs */
01098   if (Ntk_NodeTestIsPrimaryOutput(ntkNode))
01099     return;
01100   
01101   /* regionArray is an array of nodes sorted according to their depth. */
01102   regionArray = SpfdNodeComputeFanoutRegion(applData,ntkNode,regionDepth);
01103 
01104   /* Analyze region's BDD requirements */
01105   SpfdComputeRequiredGlobalBdds(network,applData);
01106   
01107   /* Analyze auxilarry BDD ID requirements */
01108   SpfdAllocateOrReuseAuxVariables(network,applData);
01109   
01110   /* Order the fanin of internal and boundary nodes */
01111   if (spfdPerfSim) {
01112     SpfdOrderFaninOfRegionNodes(network,applData,
01113                                 SpfdSwitchedCapAndDepthCompare);
01114   } else {
01115     SpfdOrderFaninOfRegionNodes(network,applData,
01116                                 SpfdFanoutCountAndDepthCompare);
01117   }
01118     
01119   /* Set the spfds for nodes in the region. The spfds are reduced to a
01120      single pair and the localAlt is set to one of the components of the
01121      single pair SPFD. */
01122   SpfdRegionComputeSinglePairSpfd(network,applData,regionArray);
01123   
01124   /* Remove the spfd of ntkNode as it was not deleted in
01125      SpfdRegionComputeSinglePairSpfd */
01126 
01127   /* SPFD of ntkNode is no longer needed. */
01128   SpfdNodeDeleteSpfd(applData,ntkNode);
01129       
01130   /* Check to see if wires have been found to be
01131      redundant/replaceable. If no wires are to be
01132      removed/replaced, then decide whether or not to reprogram. */
01133   if (st_count(applData->currWireTable) == 0 &&
01134       !spfdReprogNoWire) {
01135     /* In this case just clean up currBddReq, localAlt and
01136        globalAlt. */
01137     st_table *currBddReq;
01138     st_generator *stGen;
01139     Ntk_Node_t *regNode;
01140     bdd_node *bdd1;
01141     bdd_manager *ddManager;
01142     int j;
01143     
01144     ddManager = applData->ddManager;
01145     currBddReq = applData->currBddReq;
01146     
01147     /* Clean up currBddReq */
01148     st_foreach_item(currBddReq,stGen,&regNode,&bdd1) {
01149       bdd_recursive_deref(ddManager,bdd1);
01150     }
01151     st_free_table(currBddReq);
01152     applData->currBddReq = NIL(st_table);
01153     
01154     /* Clean up localAlt and globalAlt of region nodes */
01155     arrayForEachItem(Ntk_Node_t *,regionArray,j,regNode) {
01156       SpfdNodeDeleteGlobalAlternative(applData,regNode);
01157       SpfdNodeDeleteLocalAlt(applData,regNode);
01158     }
01159   } else {
01160     /* Now reprogram the nodes in the region. */
01161     SpfdReprogramRegionNodes(network,applData,regionArray);
01162   }
01163   
01164   /* Clean up auxIds and piAltVars*/
01165   SpfdCleanUpAuxIds(applData);
01166   
01167   /* Free stuff used only for the current wire */
01168   if (applData->currXCube) {
01169     bdd_recursive_deref(applData->ddManager,applData->currXCube);
01170     applData->currXCube = NIL(bdd_node);
01171   }
01172   if (applData->currRegionNodes) {
01173     st_free_table(applData->currRegionNodes);
01174     applData->currRegionNodes = NIL(st_table);
01175   }
01176   if (applData->currInUseVars) {
01177     st_free_table(applData->currInUseVars);
01178     applData->currInUseVars = NIL(st_table);
01179   }
01180   
01181   num = st_count(applData->currWireTable);
01182   assert(num == 0);
01183   
01184   num = st_count(applData->currReplaceTable);
01185   assert(num == 0);
01186   
01187   /* Update the total number of wires removed */
01188   wiresRemoved = applData->wiresRemoved;
01189   if (st_count(wiresRemoved) > 0) {
01190     st_foreach_item(wiresRemoved,stGen,&tempNode,
01191                     &sinkTable){
01192       spfdNumWiresRem += st_count(sinkTable);
01193     }
01194     
01195     /* free the wiresRemoved contents */
01196     st_foreach(wiresRemoved,SpfdStTableClean,NIL(char));
01197   }
01198   
01199   /* Free regionArray (cluster) */
01200   array_free(regionArray);
01201   
01202   /* Lock the node */
01203   SpfdNodeSetLocked(applData,ntkNode,TRUE);
01204 
01205   return ;
01206   
01207 } /* End of SpfdOptimizeNode */
01208 
01209 
01210 /*---------------------------------------------------------------------------*/
01211 /* Definition of static functions                                            */
01212 /*---------------------------------------------------------------------------*/
01221 static int
01222 CompareConvexFanoutCountAndDepth(
01223   const void *obj1,
01224   const void *obj2)
01225 {
01226   Ntk_Node_t *node1,*node2;
01227   Ntk_Network_t *network;
01228   float weight1,weight2;
01229   float load1,load2;
01230   int depth1,depth2;
01231   
01232   node1 = *(Ntk_Node_t **)obj1;
01233   node2 = *(Ntk_Node_t **)obj2;
01234   assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
01235   network = Ntk_NodeReadNetwork(node1);
01236 
01237   if (Ntk_NodeTestIsPrimaryOutput(node1) ||
01238       Ntk_NodeTestIsPrimaryInput(node1)) {
01239     weight1 = -1.0;
01240   } else {
01241     load1 = Ntk_NodeReadNumFanouts(node1);
01242     depth1 = Truesim_NetworkReadNodeDepth(network,node1);
01243     weight1 = spfdAlpha * load1 + (1.0-spfdAlpha)*depth1;
01244   }
01245 
01246   if (Ntk_NodeTestIsPrimaryOutput(node2) ||
01247       Ntk_NodeTestIsPrimaryInput(node2)) {
01248     weight2 = -1.0;
01249   } else {
01250     load2 = Ntk_NodeReadNumFanouts(node2);
01251     depth2 = Truesim_NetworkReadNodeDepth(network,node2);
01252     weight2 = spfdAlpha * load2 + (1.0-spfdAlpha)*depth2;
01253   }
01254   
01255   if (weight1 > weight2)
01256     return -1;
01257   else if (weight1 == weight2)
01258     return 0;
01259   else
01260     return 1;
01261 
01262 } /* End of CompareConvexFanoutCountAndDepth */
01263 
01264 
01273 static int
01274 CompareConvexSwitchedCapAndDepth(
01275   const void *obj1,
01276   const void *obj2)
01277 {
01278   Ntk_Node_t *node1,*node2;
01279   Ntk_Network_t *network;
01280   float weight1,weight2;
01281   float switch1,switch2;
01282   float load1,load2;
01283   int depth1,depth2;
01284   
01285   node1 = *(Ntk_Node_t **)obj1;
01286   node2 = *(Ntk_Node_t **)obj2;
01287   assert(Ntk_NodeReadNetwork(node1) == Ntk_NodeReadNetwork(node2));
01288   network = Ntk_NodeReadNetwork(node1);
01289 
01290   if (Ntk_NodeTestIsPrimaryOutput(node1) ||
01291       Ntk_NodeTestIsPrimaryInput(node1)) {
01292     weight1 = -1.0;
01293   } else {
01294     switch1 = Truesim_NetworkReadNodeSwitchingProb(network,node1);
01295     load1 = Truesim_NetworkReadNodeLoad(network,node1);
01296     depth1 = Truesim_NetworkReadNodeDepth(network,node1);
01297     weight1 = spfdAlpha * load1 * switch1 + (1.0-spfdAlpha)*depth1;
01298   }
01299 
01300   if (Ntk_NodeTestIsPrimaryOutput(node2) ||
01301       Ntk_NodeTestIsPrimaryInput(node2)) {
01302     weight2 = -1.0;
01303   } else {
01304     switch2 = Truesim_NetworkReadNodeSwitchingProb(network,node2);
01305     load2 = Truesim_NetworkReadNodeLoad(network,node2);
01306     depth2 = Truesim_NetworkReadNodeDepth(network,node2);
01307     weight2 = spfdAlpha * load2 * switch2 + (1.0-spfdAlpha)*depth2;
01308   }
01309   
01310   if (weight1 > weight2)
01311     return -1;
01312   else if (weight1 == weight2)
01313     return 0;
01314   else
01315     return 1;
01316 
01317 } /* End of CompareConvexSwitchedCapAndDepth */