VIS
|
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 **)®Node,(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,®Node,&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,®Node,&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 */