VIS

src/spfd/spfdCommon.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 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 */