VIS

src/spfd/spfdSpfd.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 * ComputeAuxRel(SpfdApplData_t *applData, bdd_node *faninRel, Ntk_Node_t *from, int piSwap);
00055 
00059 /*---------------------------------------------------------------------------*/
00060 /* Definition of exported functions                                          */
00061 /*---------------------------------------------------------------------------*/
00062 
00063 
00064 /*---------------------------------------------------------------------------*/
00065 /* Definition of internal functions                                          */
00066 /*---------------------------------------------------------------------------*/
00067 
00076 bdd_node *
00077 SpfdNodeComputeSpfdFromOnAndOffSet(
00078   SpfdApplData_t *applData,
00079   Ntk_Node_t *regNode,
00080   bdd_node *bdd1,
00081   bdd_node *bdd0)
00082 {
00083   bdd_manager *ddManager = applData->ddManager;
00084   int numFanin = Ntk_NodeReadNumFanins(regNode);
00085   bdd_node **yVars,**yAuxVars;
00086   bdd_node *ddTemp,*rel,*spfd;
00087   Ntk_Node_t *fanin;
00088   int j,clean;
00089 
00090   /* If bdd1 and bdd0 are not specified, replace bdd1 and bdd0 by the
00091      node's local ON-set and OFF-set respectively */
00092   clean = 0;
00093   if (bdd1 == NIL(bdd_node) ||
00094       bdd0 == NIL(bdd_node)) {
00095     Ntk_Network_t *network;
00096     network = Ntk_NodeReadNetwork(regNode);
00097     bdd_ref(bdd1 = SpfdNodeReadLocalBdd(network,regNode));
00098     bdd_ref(bdd0 = bdd_not_bdd_node(bdd1));
00099     /* Delete bdd1 and bdd0 at the end.*/
00100     clean = 1;
00101   }
00102   
00103   /* Array of variables for swapping */
00104   numFanin = Ntk_NodeReadNumFanins(regNode);
00105   yVars = ALLOC(bdd_node *,numFanin);
00106   yAuxVars = ALLOC(bdd_node *,numFanin);
00107   Ntk_NodeForEachFanin(regNode,j,fanin) {
00108     yVars[j] = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
00109     yAuxVars[j] = bdd_bdd_ith_var(ddManager,
00110                                   SpfdNodeReadAuxId(applData,fanin));
00111   }
00112 
00113   /* spfd is bdd1(y) * bdd0(y') + bdd1(y') * bdd0(y) */
00114   bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,bdd0,
00115                                           yVars,yAuxVars,numFanin));
00116   bdd_ref(rel = bdd_bdd_and(ddManager,bdd1,ddTemp));
00117   bdd_recursive_deref(ddManager,ddTemp);
00118       
00119   bdd_ref(ddTemp = bdd_bdd_swap_variables(ddManager,rel,
00120                                           yVars,yAuxVars,numFanin));
00121   bdd_ref(spfd = bdd_bdd_or(ddManager,rel,ddTemp));
00122   bdd_recursive_deref(ddManager,rel);
00123   bdd_recursive_deref(ddManager,ddTemp);
00124   FREE(yVars);
00125   FREE(yAuxVars);
00126 
00127   if (clean) {
00128     bdd_recursive_deref(ddManager,bdd1);
00129     bdd_recursive_deref(ddManager,bdd0);
00130   }
00131   return spfd;
00132 } /* End of SpfdNodeComputeSpfdFromOnAndOffSet */
00133 
00134 
00143 bdd_node *
00144 SpfdNodeComputeSpfdFromFanouts(
00145   SpfdApplData_t *applData,
00146   Ntk_Node_t *from)
00147 {
00148   bdd_manager *ddManager = applData->ddManager;
00149   st_table *currBddReq;
00150   st_table *wireTable,*wiresRemoved;
00151   array_t *ordArray;
00152   bdd_node *result,*var,*varAux,*ddTemp,*ddTemp2;
00153   bdd_node *wireSpfd,*toSpfd,*fromSpfd,*xCube;
00154   bdd_node *step1,*faninRel,*faninRelAux,*inter,*final;
00155   bdd_node **firstCompose,**secondCompose;
00156   bdd_node *logicZero;
00157   Ntk_Node_t *fanin,*to;
00158   int index,i,j;
00159   int size,piSwap;
00160 
00161 
00162   if (Ntk_NodeReadNumFanouts(from) < 1) {
00163     (void) fprintf(vis_stdout,
00164                    "** spfd error: Node %s has no fanouts.\n",
00165                    Ntk_NodeReadName(from));
00166     return NIL(bdd_node);
00167   }
00168   currBddReq = applData->currBddReq;
00169   xCube = applData->currXCube;
00170   logicZero = bdd_read_logic_zero(ddManager);
00171 
00172   /* Compute the characteristic function of the fanin relation:
00173    faninRel = \prod y_i == f_i(X) */
00174   faninRel = SpfdComputeNodeArrayRelation(applData,currBddReq,NIL(array_t),
00175                                           Ntk_NodeReadFanins(from),
00176                                           TRUE,&piSwap);
00177   
00178   /* Convert faninRel(y,pi) to faninRel(\hat{y},pi) */
00179   faninRelAux = ComputeAuxRel(applData,faninRel,from,piSwap);
00180     
00181   /* Compute SPFD wire by wire according to the order specified for
00182      each fanout node. */
00183   wireTable = applData->currWireTable;
00184   wiresRemoved = applData->wiresRemoved;
00185   bdd_ref(fromSpfd = logicZero);
00186   Ntk_NodeForEachFanout(from,j,to) {
00187 
00188     bdd_ref(result = bdd_read_one(ddManager));
00189     ordArray = SpfdNodeReadFaninOrder(applData,to);
00190     arrayForEachItem(Ntk_Node_t *,ordArray,i,fanin) {
00191       var = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
00192       index = SpfdNodeReadAuxId(applData,fanin);
00193       varAux = bdd_bdd_ith_var(ddManager,index);
00194         
00195       if (fanin != from) {
00196         /* XNOR */
00197         bdd_ref(ddTemp = bdd_bdd_xnor(ddManager,var,varAux));
00198       } else {
00199         /* XOR */
00200         bdd_ref(ddTemp = bdd_bdd_xor(ddManager,var,varAux));
00201       }
00202       bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,result,ddTemp));
00203       bdd_recursive_deref(ddManager,result);
00204       bdd_recursive_deref(ddManager,ddTemp);
00205       result = ddTemp2;
00206         
00207       if (fanin == from)
00208         break;
00209     }
00210       
00211     /* Compute AND of result and the SPFD of 'to'. */
00212     toSpfd = SpfdNodeReadSpfd(applData,to);
00213     if (toSpfd == NIL(bdd_node)) {
00214       (void) fprintf(vis_stderr,
00215                      "** spfd error: Spfd expected but not found.\n");
00216       (void) fprintf(vis_stderr, "To node:\n");
00217       Ntk_NodePrint(vis_stderr, to, TRUE, TRUE);
00218       (void) fprintf(vis_stderr, "From node:\n");
00219       Ntk_NodePrint(vis_stderr, from, TRUE, TRUE);
00220       fflush(vis_stderr);
00221       assert(0);
00222     }
00223     bdd_ref(wireSpfd = bdd_bdd_and(ddManager,toSpfd,result));
00224     bdd_recursive_deref(ddManager,result);
00225 
00226     /* Convert wireSpfd from fanout space to fanin space */
00227     /* Prepare the vectors for composition */
00228     size = bdd_num_vars(ddManager);
00229     firstCompose = ALLOC(bdd_node *,size);
00230     secondCompose = ALLOC(bdd_node *,size);
00231     for (i = 0; i < size; i++) {
00232       firstCompose[i] = bdd_bdd_ith_var(ddManager,i);
00233       secondCompose[i] = bdd_bdd_ith_var(ddManager,i);
00234     }
00235       
00236     arrayForEachItem(Ntk_Node_t *,ordArray,i,fanin) {
00237       int id,auxId;
00238         
00239       id = Ntk_NodeReadMddId(fanin);
00240       auxId = SpfdNodeReadAuxId(applData,fanin);
00241       st_lookup(currBddReq,(char *)fanin,(char **)&firstCompose[id]);
00242       secondCompose[auxId] = firstCompose[id];
00243     }
00244       
00245     /* Perform the steps of compose --> existential abstraction twice */
00246     bdd_ref(step1 = bdd_bdd_vector_compose(ddManager,wireSpfd,firstCompose));
00247     bdd_recursive_deref(ddManager,wireSpfd);
00248     FREE(firstCompose);
00249     bdd_ref(inter = bdd_bdd_and_abstract(ddManager,faninRel,step1,xCube));
00250     bdd_recursive_deref(ddManager,step1);
00251     
00252     /* The second of compose --> existential abstraction steps */
00253     bdd_ref(ddTemp = bdd_bdd_vector_compose(ddManager,inter,secondCompose));
00254     bdd_recursive_deref(ddManager,inter);
00255     FREE(secondCompose);
00256     bdd_ref(final = bdd_bdd_and_abstract(ddManager,faninRelAux,
00257                                          ddTemp,xCube));
00258     bdd_recursive_deref(ddManager,ddTemp);
00259 
00260     /* Now 'final' is in the fanin space */
00261     if (final == logicZero) {
00262       st_table *sinkTable;
00263       Ntk_Node_t *tempNode;
00264       boolean add;
00265 
00266       /* Check if this wire has already been removed. If yes, skip */
00267       add = TRUE;
00268       if (st_lookup(wiresRemoved,(char *)from,&sinkTable) &&
00269           st_lookup(sinkTable,(char *)to,&tempNode)) {
00270         add = FALSE;
00271       }
00272 
00273       if (add) {
00274         if (spfdVerbose > 2)
00275           (void) fprintf(vis_stdout,
00276                          "** spfd info: wire %s --> %s has empty spfd.\n",
00277                          Ntk_NodeReadName(from),Ntk_NodeReadName(to));
00278         
00279         /* Add to the wireTable */
00280         if (st_lookup(wireTable,(char *)from,&sinkTable)) {
00281           st_insert(sinkTable,(char *)to,(char *)to);
00282         } else {
00283           sinkTable = st_init_table(st_ptrcmp,st_ptrhash);
00284           st_insert(sinkTable,(char *)to,(char *)to);
00285           st_insert(wireTable,(char *)from,(char *)sinkTable);
00286         }
00287       }
00288     }
00289     
00290     bdd_ref(ddTemp = bdd_bdd_or(ddManager,fromSpfd,final));
00291     bdd_recursive_deref(ddManager,fromSpfd);
00292     bdd_recursive_deref(ddManager,final);
00293     
00294     fromSpfd = ddTemp;
00295   }
00296   bdd_recursive_deref(ddManager,faninRel);
00297   bdd_recursive_deref(ddManager,faninRelAux);
00298     
00299   /* Swap variables for fromSpfd if necessary */
00300   if (piSwap) { /* If we have used alternate PI ids */
00301     ddTemp = SpfdSwapPiAndAltPi(applData,fromSpfd);
00302     bdd_recursive_deref(ddManager,fromSpfd);
00303     fromSpfd = ddTemp;
00304   }
00305   
00306   return fromSpfd;
00307   
00308 } /* End of SpfdNodeComputeSpfdFromFanouts */
00309 
00310 
00324 st_table *
00325 SpfdNodeComputeSCCs(
00326   SpfdApplData_t *applData,
00327   Ntk_Node_t *regNode,
00328   bdd_node **tempVars)
00329 {
00330   bdd_manager *ddManager = applData->ddManager;
00331   st_table *inUseVars = applData->currInUseVars;
00332   Ntk_Node_t *fanin;
00333   st_table *SCC;
00334   bdd_node *spfd,*spfd2,*auxCube;
00335   bdd_node *ddTemp1,*ddTemp2,*logicZero,*faninCube;
00336   bdd_node *Ny,*E1y,*E0y;
00337   bdd_node *from,*To,*new_,*reached;
00338   bdd_node **faninVars,**auxVars;
00339   int i,numFanin,varsAllocated;
00340 
00341   numFanin = Ntk_NodeReadNumFanins(regNode);
00342   SCC = st_init_table(st_ptrcmp,st_ptrhash);
00343   spfd = SpfdNodeReadSpfd(applData,regNode);
00344   logicZero = bdd_read_logic_zero(ddManager);
00345 
00346   if (spfd == logicZero)
00347     return SCC;
00348   
00349   varsAllocated = 0;
00350   /* Allocate variables if necessary */
00351   if (tempVars == NIL(bdd_node *)) {
00352     tempVars = SpfdAllocateTemporaryVariables(ddManager,inUseVars,numFanin);
00353     varsAllocated = 1;
00354   }
00355   
00356   faninVars = ALLOC(bdd_node *,numFanin);
00357   auxVars = ALLOC(bdd_node *,numFanin);
00358   Ntk_NodeForEachFanin(regNode,i,fanin) {
00359     faninVars[i] = bdd_bdd_ith_var(ddManager,Ntk_NodeReadMddId(fanin));
00360     auxVars[i] = bdd_bdd_ith_var(ddManager,
00361                                  SpfdNodeReadAuxId(applData,fanin));
00362   }
00363 
00364   bdd_ref(auxCube = bdd_bdd_compute_cube(ddManager,auxVars,
00365                                          NIL(int),numFanin));
00366   /* Compute spfd2 = \exists_{\hat{y}} spfd(y,\hat{y}) *
00367      spfd(\hat{y},\tilde{y}) */
00368   bdd_ref(ddTemp1 = bdd_bdd_swap_variables(ddManager,spfd,faninVars,
00369                                            auxVars,numFanin));
00370   bdd_ref(ddTemp2 = bdd_bdd_swap_variables(ddManager,ddTemp1,faninVars,
00371                                            tempVars,numFanin));
00372   bdd_recursive_deref(ddManager,ddTemp1);
00373   bdd_ref(spfd2 = bdd_bdd_and_abstract(ddManager,spfd,ddTemp2,auxCube));
00374   bdd_recursive_deref(ddManager,ddTemp2);
00375 
00376   /* SCC computation */
00377   bdd_ref(faninCube = bdd_bdd_compute_cube(ddManager,faninVars,
00378                                            NIL(int),numFanin));
00379   /* Compute N(y) = \exists_{\hat{y}} spfd(y,\hat{y}) */
00380   bdd_ref(Ny = bdd_bdd_exist_abstract(ddManager,spfd,auxCube));
00381   bdd_recursive_deref(ddManager,auxCube);
00382 
00383   while (Ny != logicZero) {
00384     /* To compute E1(y) perform the fixpoint image computation */
00385     bdd_ref(from = bdd_bdd_pick_one_minterm(ddManager,Ny,faninVars,numFanin));
00386     bdd_ref(reached = from);
00387     do {
00388       bdd_ref(ddTemp1 = bdd_bdd_and_abstract(ddManager,spfd2,from,faninCube));
00389       bdd_recursive_deref(ddManager,from);
00390       bdd_ref(To = bdd_bdd_swap_variables(ddManager,ddTemp1,tempVars,
00391                                           faninVars,numFanin));
00392       bdd_recursive_deref(ddManager,ddTemp1);
00393       bdd_ref(new_ = bdd_bdd_and(ddManager,To,bdd_not_bdd_node(reached)));
00394       bdd_recursive_deref(ddManager,To);
00395       bdd_ref(ddTemp1 = bdd_bdd_or(ddManager,reached,new_));
00396       bdd_recursive_deref(ddManager,reached);
00397       reached = ddTemp1;
00398       from = new_;
00399     } while (new_ != logicZero);
00400 
00401     E1y = reached;
00402     
00403     /* E_0(y) = \exists_{\hat{y}} spfd(y,\hat{y}) * E_1(y) */
00404     bdd_ref(ddTemp1 = bdd_bdd_and_abstract(ddManager,spfd,E1y,faninCube));
00405     bdd_ref(E0y = bdd_bdd_swap_variables(ddManager,ddTemp1,auxVars,
00406                                          faninVars,numFanin));
00407     bdd_recursive_deref(ddManager,ddTemp1);
00408     
00409     /* Update Ny: Ny = Ny * (E1y + E0y)' */
00410     bdd_ref(ddTemp1 = bdd_bdd_or(ddManager,E1y,E0y));
00411     bdd_ref(ddTemp2 = bdd_bdd_and(ddManager,Ny,bdd_not_bdd_node(ddTemp1)));
00412     bdd_recursive_deref(ddManager,ddTemp1);
00413     bdd_recursive_deref(ddManager,Ny);
00414     Ny = ddTemp2;
00415 
00416     /* Store E1y and E0y in an st_table */
00417     st_insert(SCC,(char *)E1y,(char *)E0y);
00418   }
00419   bdd_recursive_deref(ddManager,faninCube);
00420   bdd_recursive_deref(ddManager,Ny);
00421   
00422   FREE(auxVars);
00423   FREE(faninVars);
00424 
00425   if (varsAllocated) {
00426     long id;
00427     for (i = 0; i < numFanin; i++) {
00428       id = (long) bdd_node_read_index(tempVars[i]);
00429       st_delete(inUseVars,&id,NIL(char *));
00430     }
00431     FREE(tempVars);
00432   }
00433   
00434   return SCC;
00435 
00436 } /* End of SpfdNodeComputeSCCs */
00437 
00438 /*---------------------------------------------------------------------------*/
00439 /* Definition of static functions                                            */
00440 /*---------------------------------------------------------------------------*/
00441 
00450 static bdd_node *
00451 ComputeAuxRel(
00452   SpfdApplData_t *applData,
00453   bdd_node *faninRel,
00454   Ntk_Node_t *from,
00455   int piSwap)
00456 {
00457   bdd_node **fromVars,**toVars;
00458   int numFi = Ntk_NodeReadNumFanins(from);
00459   int k,altId;
00460   Ntk_Node_t *fanin;
00461   bdd_node *faninRelAux;
00462   st_table *piAltVars;
00463   bdd_manager *ddManager = applData->ddManager;
00464   
00465   piAltVars = applData->currPiAltVars;
00466   
00467   /* Collect variables for swapping. */
00468   fromVars = ALLOC(bdd_node *,numFi);
00469   toVars = ALLOC(bdd_node *,numFi);
00470   Ntk_NodeForEachFanin(from,k,fanin) {
00471     int id = Ntk_NodeReadMddId(fanin);
00472     if (piSwap && st_lookup(piAltVars,(char *)(long)id,&altId)) {
00473       fromVars[k] = bdd_bdd_ith_var(ddManager,altId);
00474     } else {
00475       fromVars[k] = bdd_bdd_ith_var(ddManager,id);
00476     }
00477     toVars[k] = bdd_bdd_ith_var(ddManager,SpfdNodeReadAuxId(applData,fanin));
00478   }
00479   bdd_ref(faninRelAux = bdd_bdd_swap_variables(ddManager,faninRel,fromVars,
00480                                                toVars,numFi));
00481   FREE(fromVars);
00482   FREE(toVars);
00483 
00484   return faninRelAux;
00485   
00486 } /* End of ComputeAuxRel */