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 bdd_node * NodeComputeGeneralProbability(Ntk_Network_t *network, bdd_manager *ddManager, Ntk_Node_t *regNode, bdd_node *result); 00055 00059 /*---------------------------------------------------------------------------*/ 00060 /* Definition of exported functions */ 00061 /*---------------------------------------------------------------------------*/ 00062 00063 00064 /*---------------------------------------------------------------------------*/ 00065 /* Definition of internal functions */ 00066 /*---------------------------------------------------------------------------*/ 00076 void 00077 SpfdRegionComputeSinglePairSpfd( 00078 Ntk_Network_t *network, 00079 SpfdApplData_t *applData, 00080 array_t *regionArray) 00081 { 00082 Ntk_Node_t *node,*fanin,*fanout; 00083 int i,j,bound,maxFanin; 00084 long id; 00085 int numNodes,numFanin; 00086 boolean isPi,boundOrPO; 00087 st_table *nodeCountTable = NIL(st_table); 00088 st_table *regionNodes = applData->currRegionNodes; 00089 st_table *inUseVars = applData->currInUseVars; 00090 bdd_manager *ddManager = applData->ddManager; 00091 bdd_node **tempVars,*spfd,*localAlt; 00092 00093 numFanin = -1; /* To keep compiler happy. */ 00094 /* Delete node spfds when not needed */ 00095 nodeCountTable = st_init_table(st_ptrcmp,st_ptrhash); 00096 arrayForEachItem(Ntk_Node_t *,regionArray,j,node) { 00097 int num = 0; 00098 Ntk_NodeForEachFanin(node,i,fanin) { 00099 /* spfds for boundary nodes, PI, PO are not derived from their 00100 fanouts. */ 00101 if (st_lookup(regionNodes,(char *)fanin,&bound) && 00102 !bound && 00103 !Ntk_NodeTestIsPrimaryInput(fanin) && 00104 !Ntk_NodeTestIsPrimaryOutput(fanin)) { 00105 num++; 00106 } 00107 } 00108 if (num) { 00109 int *count; 00110 count = ALLOC(int,1); 00111 *count = num; 00112 st_insert(nodeCountTable,(char *)node,(char *)count); 00113 } 00114 } 00115 00116 /* Allocate temporary variables that MIGHT BE required during the 00117 computation of SCCs. We will allocate maxFanin temporary 00118 variables. */ 00119 maxFanin = -1; 00120 arrayForEachItem(Ntk_Node_t *,regionArray,i,node) { 00121 numFanin = Ntk_NodeReadNumFanins(node); 00122 if (numFanin > maxFanin) 00123 maxFanin = numFanin; 00124 } 00125 tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,maxFanin); 00126 00127 /* Compute spfd and localAlt for all the nodes in the region. */ 00128 numNodes = array_n(regionArray); 00129 for (i = numNodes-1; i >= 0; i--) { 00130 node = array_fetch(Ntk_Node_t *,regionArray,i); 00131 st_lookup(regionNodes,(char *)node,&bound); 00132 00133 /* Is it a boundary node or is it primary output? For such nodes, 00134 we dont not derive SPFDs from their fanouts. Their SPFDs are 00135 derived from their current function impelementation */ 00136 boundOrPO = (bound || Ntk_NodeTestIsPrimaryOutput(node)); 00137 isPi = Ntk_NodeTestIsPrimaryInput(node); 00138 00139 if (isPi) { 00140 spfd = NIL(bdd_node); 00141 } else if (boundOrPO) { 00142 spfd = SpfdNodeComputeSpfdFromOnAndOffSet(applData,node, 00143 NIL(bdd_node), 00144 NIL(bdd_node)); 00145 } else { /* Internal node */ 00146 spfd = SpfdNodeComputeSpfdFromFanouts(applData,node); 00147 } 00148 /* Set node's spfd */ 00149 SpfdNodeSetSpfd(applData,node,spfd); 00150 /* Set node's localAlt */ 00151 if (isPi) { 00152 SpfdNodeSetLocalAlt(applData,node,NIL(bdd_node)); 00153 } else if (boundOrPO) { 00154 bdd_ref(localAlt = SpfdNodeReadLocalBdd(network,node)); 00155 SpfdNodeSetLocalAlt(applData,node,localAlt); 00156 } else { /* Internal node */ 00157 int numSCC; 00158 st_table *SCC; 00159 SCC = SpfdNodeComputeSCCs(applData,node,tempVars); 00160 numSCC = st_count(SCC); 00161 if (numSCC == 0) { 00162 bdd_node *logicZero; 00163 if (spfdVerbose > 1) 00164 (void) fprintf(vis_stdout, 00165 "** spfd info: node %s is redundant.\n", 00166 Ntk_NodeReadName(node)); 00167 /* Set the localAlt to empty. */ 00168 bdd_ref(logicZero = bdd_read_logic_zero(ddManager)); 00169 SpfdNodeSetLocalAlt(applData,node,logicZero); 00170 } else { 00171 /* Reduce the spfd to a single pair. SCC components are dereferenced in 00172 the function. The localAlt is also set to one of the components of 00173 the single pair */ 00174 SpfdNodeReduceSCCToSinglePair(applData,node,SCC); 00175 } 00176 st_free_table(SCC); 00177 } 00178 /* Clean nodeCountTable if the present node is an internal node. */ 00179 if (!bound && 00180 !Ntk_NodeTestIsPrimaryInput(node) && 00181 !Ntk_NodeTestIsPrimaryOutput(node)) { 00182 Ntk_NodeForEachFanout(node,j,fanout) { 00183 int *count; 00184 if (st_lookup(nodeCountTable,(char *)fanout,&count)) { 00185 (*count)--; 00186 if (*count == 0) { 00187 st_delete(nodeCountTable,&fanout,&count); 00188 SpfdNodeDeleteSpfd(applData,fanout); 00189 FREE(count); 00190 } 00191 } 00192 } 00193 } 00194 } 00195 00196 /* Some of the internal nodes' spfd might not be deleted via 00197 nodeCountTable. Delete them explicitly. SPFD of the first node is 00198 needed. It will be deleted later in the calling function. */ 00199 for (i = 1; i < numNodes; i++) { 00200 node = array_fetch(Ntk_Node_t *,regionArray,i); 00201 SpfdNodeDeleteSpfd(applData,node); 00202 } 00203 /* Delete the fanin order arrays for region nodes */ 00204 arrayForEachItem(Ntk_Node_t *,regionArray,i,node) { 00205 SpfdNodeDeleteFaninOrder(applData,node); 00206 } 00207 for (i = 0; i < numFanin; i++) { 00208 id = (long) bdd_node_read_index(tempVars[i]); 00209 st_delete(inUseVars,&id,NIL(char *)); 00210 } 00211 FREE(tempVars); 00212 00213 /* Assert that nodeCountTable is empty */ 00214 assert(st_count(nodeCountTable) == 0); 00215 st_free_table(nodeCountTable); 00216 00217 return; 00218 00219 } /* End of SpfdRegionComputeSinglePairSpfd */ 00220 00221 00238 bdd_node * 00239 SpfdNodeComputeOptParams( 00240 SpfdApplData_t *applData, 00241 Ntk_Node_t *regNode, 00242 bdd_node *result, 00243 bdd_node **parameters, 00244 int numIsfs) 00245 { 00246 bdd_manager *ddManager = applData->ddManager; 00247 Ntk_Network_t *network = Ntk_NodeReadNetwork(regNode); 00248 bdd_node *genProb,*offGenProb; 00249 bdd_node *diff,*maxDiff,*optComb; 00250 bdd_node *ddTemp,*prevSwitching,*newSwitching; 00251 float prob,switching; 00252 00253 /* Compute the new node probability in terms of parameters introduced */ 00254 genProb = NodeComputeGeneralProbability(network,ddManager,regNode,result); 00255 bdd_ref(offGenProb = bdd_add_apply(ddManager,bdd_add_minus, 00256 bdd_read_one(ddManager),genProb)); 00257 bdd_ref(newSwitching = bdd_add_apply(ddManager,bdd_add_times, 00258 genProb,offGenProb)); 00259 bdd_recursive_deref(ddManager,genProb); 00260 bdd_recursive_deref(ddManager,offGenProb); 00261 00262 /* Compute the previous power dissipated */ 00263 ddTemp = SpfdNodeReadLocalBdd(network,regNode); 00264 prob = Truesim_BddNodeComputeProbability(network,ddTemp); 00265 switching = prob*(1.0-prob); 00266 bdd_ref(prevSwitching = bdd_add_const(ddManager,switching)); 00267 00268 /* Find the combination of parameters that give max power savings, 00269 i.e. max(prevPowerAdd - newPowerAdd) */ 00270 bdd_ref(diff = bdd_add_apply(ddManager,bdd_add_minus,prevSwitching, 00271 newSwitching)); 00272 bdd_recursive_deref(ddManager,prevSwitching); 00273 bdd_recursive_deref(ddManager,newSwitching); 00274 00275 /* Find the max. difference */ 00276 bdd_ref(maxDiff = bdd_add_find_max(ddManager,diff)); 00277 00278 if (bdd_add_value(maxDiff) <= 0.0) { 00279 bdd_recursive_deref(ddManager,diff); 00280 bdd_recursive_deref(ddManager,maxDiff); 00281 00282 optComb = NIL(bdd_node); 00283 } else { 00284 /* Find minterms with max. difference */ 00285 bdd_ref(optComb = bdd_add_apply(ddManager,SpfdAddEqual,maxDiff,diff)); 00286 bdd_recursive_deref(ddManager,maxDiff); 00287 bdd_recursive_deref(ddManager,diff); 00288 00289 /* optComb (an ADD) can be a cube, i.e., more than one 00290 minterm. Pick a minterm. Convert optComb to a BDD */ 00291 bdd_ref(maxDiff = bdd_add_bdd_threshold(ddManager,optComb,(double) 1.0)); 00292 bdd_recursive_deref(ddManager,optComb); 00293 optComb = maxDiff; 00294 00295 /* Pick one cube */ 00296 bdd_ref(maxDiff = bdd_bdd_pick_one_minterm(ddManager,optComb,parameters, 00297 numIsfs)); 00298 bdd_recursive_deref(ddManager,optComb); 00299 optComb = maxDiff; 00300 } 00301 00302 return optComb; 00303 00304 } /* End of SpfdNodeComputeOptParams */ 00305 00306 00315 void 00316 SpfdNodeReduceSCCToSinglePair( 00317 SpfdApplData_t *applData, 00318 Ntk_Node_t *regNode, 00319 st_table *SCC) 00320 { 00321 Ntk_Network_t *network = Ntk_NodeReadNetwork(regNode); 00322 st_table *inUseVars = applData->currInUseVars; 00323 bdd_manager *ddManager = applData->ddManager; 00324 bdd_node **parameters; 00325 bdd_node *bdd1,*bdd0,*result,*spfd; 00326 bdd_node *optComb; 00327 st_generator *stGen; 00328 int numIsfs; 00329 int i; 00330 long lid; 00331 00332 numIsfs = st_count(SCC); 00333 /* Allocate numIsfs binary valued parameters, one for each SCC. */ 00334 parameters = SpfdComputeParameters(applData,SCC); 00335 00336 /* Compute the general form representation for the local alternate 00337 function */ 00338 bdd_ref(result = bdd_read_logic_zero(ddManager)); 00339 i = 0; 00340 st_foreach_item(SCC,stGen,&bdd1,&bdd0) { 00341 bdd_node *ddTemp,*ddTemp2; 00342 bdd_ref(ddTemp = bdd_bdd_ite(ddManager,parameters[i],bdd1,bdd0)); 00343 bdd_recursive_deref(ddManager,bdd1); 00344 bdd_recursive_deref(ddManager,bdd0); 00345 bdd_ref(ddTemp2 = bdd_bdd_or(ddManager,ddTemp,result)); 00346 bdd_recursive_deref(ddManager,ddTemp); 00347 bdd_recursive_deref(ddManager,result); 00348 result = ddTemp2; 00349 i++; 00350 } 00351 00352 if (!spfdPerfSim) { /* No switching activity info. available */ 00353 /* Choose one combination of parameters */ 00354 bdd_ref(optComb = bdd_bdd_compute_cube(ddManager,parameters, 00355 NIL(int),numIsfs)); 00356 } else { 00357 /* Compute the combination of parameters that reduce switching */ 00358 optComb = SpfdNodeComputeOptParams(applData,regNode,result, 00359 parameters,numIsfs); 00360 } 00361 00362 if (optComb) { /* If such a combination exists */ 00363 bdd_node *E1y,*E0y; /* BDDs for the care ON-set and care OFF-set, 00364 respectively, of the optimal ISF found in the 00365 previous step. */ 00366 bdd_node *imgOptComb; 00367 bdd_node **notParams; 00368 int size,i,id; 00369 00370 /* Compute the lhs (care ON-set) of the ISF */ 00371 bdd_ref(E1y = bdd_bdd_cofactor(ddManager,result,optComb)); 00372 /* Compute the rhs (care OFF-set) of the ISF */ 00373 size = bdd_num_vars(ddManager); 00374 notParams = ALLOC(bdd_node *,size); 00375 for (i = 0; i < size; i++) { 00376 bdd_ref(notParams[i] = bdd_bdd_ith_var(ddManager,i)); 00377 } 00378 for (i = 0; i < numIsfs; i++) { 00379 id = bdd_node_read_index(parameters[i]); 00380 bdd_recursive_deref(ddManager,notParams[id]); 00381 bdd_ref(notParams[id] = bdd_not_bdd_node(parameters[i])); 00382 } 00383 bdd_ref(imgOptComb = bdd_bdd_vector_compose(ddManager,optComb,notParams)); 00384 bdd_recursive_deref(ddManager,optComb); 00385 bdd_ref(E0y = bdd_bdd_cofactor(ddManager,result,imgOptComb)); 00386 bdd_recursive_deref(ddManager,result); 00387 bdd_recursive_deref(ddManager,imgOptComb); 00388 00389 /* Compute the spfd of E1y and E0y */ 00390 spfd = SpfdNodeComputeSpfdFromOnAndOffSet(applData,regNode,E1y,E0y); 00391 SpfdNodeDeleteSpfd(applData,regNode); 00392 SpfdNodeSetSpfd(applData,regNode,spfd); 00393 00394 /* Set E1y as the localAlt */ 00395 SpfdNodeSetLocalAlt(applData,regNode,E1y); 00396 bdd_recursive_deref(ddManager,E0y); 00397 00398 /* Free notParams */ 00399 for (i = 0; i < size; i++) { 00400 bdd_recursive_deref(ddManager,notParams[i]); 00401 } 00402 FREE(notParams); 00403 } else { /* Compute alternate spfd from local function */ 00404 bdd_node *bdd1,*bdd0; 00405 bdd_recursive_deref(ddManager,result); 00406 00407 /* Set localAlt Bdd */ 00408 bdd_ref(bdd1 = SpfdNodeReadLocalBdd(network,regNode)); 00409 bdd_ref(bdd0 = bdd_not_bdd_node(bdd1)); 00410 00411 /* Set the new spfd */ 00412 spfd = SpfdNodeComputeSpfdFromOnAndOffSet(applData,regNode,bdd1,bdd0); 00413 SpfdNodeDeleteSpfd(applData,regNode); 00414 SpfdNodeSetSpfd(applData,regNode,spfd); 00415 00416 /* Set bdd1 as the localAlt */ 00417 SpfdNodeSetLocalAlt(applData,regNode,bdd1); 00418 bdd_recursive_deref(ddManager,bdd0); 00419 } 00420 00421 /* Free the parameters */ 00422 for (i = 0; i < numIsfs; i++) { 00423 lid = (long) bdd_node_read_index(parameters[i]); 00424 st_delete(inUseVars,&lid,NIL(char *)); 00425 } 00426 FREE(parameters); 00427 00428 return; 00429 00430 } /* End of SpfdNodeReduceSCCToSinglePair */ 00431 00432 00444 void 00445 SpfdComputeRequiredGlobalBdds( 00446 Ntk_Network_t *network, 00447 SpfdApplData_t *applData) 00448 { 00449 st_table *regionNodes,*rootTable,*leavesTable; 00450 st_table *currBddReq; 00451 array_t *rootArray,*nodeMvfs; 00452 st_generator *stGen; 00453 Ntk_Node_t *node,*fanin; 00454 char *dummy; 00455 int i; 00456 lsGen gen; 00457 bdd_t *mddOne; 00458 bdd_node *bdd1; 00459 bdd_manager *ddManager = applData->ddManager; 00460 mddOne = bdd_one(ddManager); 00461 00462 /* Collect cluster nodes and also their fanin nodes */ 00463 regionNodes = applData->currRegionNodes; 00464 rootTable = st_init_table(st_ptrcmp,st_ptrhash); 00465 st_foreach_item(regionNodes,stGen,&node,&dummy) { 00466 Ntk_NodeForEachFanin(node,i,fanin) { 00467 st_insert(rootTable,(char *)fanin,(char *)-1); 00468 } 00469 } 00470 00471 /* Convert rootTable to rootArray for use by Ntm_NetworkBuildMvfs */ 00472 rootArray = array_alloc(Ntk_Node_t *,0); 00473 st_foreach_item(rootTable,stGen,&node,&dummy) { 00474 array_insert_last(Ntk_Node_t *,rootArray,node); 00475 } 00476 st_free_table(rootTable); 00477 00478 /* Collect the leaf nodes in the network. */ 00479 leavesTable = st_init_table(st_ptrcmp, st_ptrhash); 00480 Ntk_NetworkForEachCombInput(network,gen,node) { 00481 st_insert(leavesTable,(char *)node,(char *) -1); 00482 } 00483 00484 /* Compute the Mvfs for the nodes in rootArray */ 00485 nodeMvfs = Ntm_NetworkBuildMvfs(network,rootArray,leavesTable,mddOne); 00486 bdd_free(mddOne); 00487 st_free_table(leavesTable); 00488 00489 /* Extract the BDDs and put them in currBddReq */ 00490 currBddReq = applData->currBddReq = st_init_table(st_ptrcmp,st_ptrhash); 00491 arrayForEachItem(Ntk_Node_t *,rootArray,i,node) { 00492 Mvf_Function_t *mvf; 00493 mvf = array_fetch(Mvf_Function_t *,nodeMvfs,i); 00494 bdd1 = bdd_extract_node_as_is(array_fetch(bdd_t *,mvf,1)); 00495 bdd_ref(bdd1); 00496 st_insert(currBddReq,(char *)node,(char *)bdd1); 00497 } 00498 array_free(rootArray); 00499 Mvf_FunctionArrayFree(nodeMvfs); 00500 00501 return; 00502 00503 } /* End of SpfdComputeRequiredGlobalBdds */ 00504 00505 /*---------------------------------------------------------------------------*/ 00506 /* Definition of static functions */ 00507 /*---------------------------------------------------------------------------*/ 00517 static bdd_node * 00518 NodeComputeGeneralProbability( 00519 Ntk_Network_t *network, 00520 bdd_manager *ddManager, 00521 Ntk_Node_t *regNode, 00522 bdd_node *result) 00523 { 00524 int size,k,id; 00525 bdd_node **onArray,**offArray; 00526 bdd_node *resultAdd,*genProb; 00527 Ntk_Node_t *fanin; 00528 float prob; 00529 00530 size = bdd_num_vars(ddManager); 00531 onArray = ALLOC(bdd_node *,size); 00532 offArray = ALLOC(bdd_node *,size); 00533 for (k = 0; k < size; k++) { 00534 bdd_ref(onArray[k] = bdd_add_ith_var(ddManager,k)); 00535 bdd_ref(offArray[k] = bdd_add_ite(ddManager,onArray[k], 00536 bdd_read_zero(ddManager), 00537 bdd_read_one(ddManager))); 00538 } 00539 00540 Ntk_NodeForEachFanin(regNode,k,fanin) { 00541 id = Ntk_NodeReadMddId(fanin); 00542 bdd_recursive_deref(ddManager,onArray[id]); 00543 bdd_recursive_deref(ddManager,offArray[id]); 00544 prob = Truesim_NetworkReadNodeProbability(network,fanin); 00545 bdd_ref(onArray[id] = bdd_add_const(ddManager,prob)); 00546 bdd_ref(offArray[id] = bdd_add_const(ddManager,1.0-prob)); 00547 } 00548 00549 bdd_ref(resultAdd = bdd_bdd_to_add(ddManager,result)); 00550 genProb = (bdd_node *)bdd_add_general_vector_compose(ddManager,resultAdd, 00551 onArray,offArray); 00552 bdd_ref(genProb); 00553 bdd_recursive_deref(ddManager,resultAdd); 00554 00555 return genProb; 00556 00557 } /* End of NodeComputeGeneralProbability */