VIS

src/grab/grabGrab.c

Go to the documentation of this file.
00001 
00025 #include "grabInt.h"
00026 
00027 
00028 /*---------------------------------------------------------------------------*/
00029 /* Constant declarations                                                     */
00030 /*---------------------------------------------------------------------------*/
00031 
00032 /*---------------------------------------------------------------------------*/
00033 /* Structure declarations                                                    */
00034 /*---------------------------------------------------------------------------*/
00035 
00036 /*---------------------------------------------------------------------------*/
00037 /* Type declarations                                                         */
00038 /*---------------------------------------------------------------------------*/
00039 
00040 /*---------------------------------------------------------------------------*/
00041 /* Variable declarations                                                     */
00042 /*---------------------------------------------------------------------------*/
00043 static st_table *Sel0ScoreTable;
00044 static st_table *SelScoreTable;
00045 static st_table *Sel2ScoreTable;
00046 static st_table *Sel3ScoreTable;
00047 
00048 /*---------------------------------------------------------------------------*/
00049 /* Macro declarations                                                        */
00050 /*---------------------------------------------------------------------------*/
00051 
00054 /*---------------------------------------------------------------------------*/
00055 /* Static function prototypes                                                */
00056 /*---------------------------------------------------------------------------*/
00057 
00058 static array_t * GrabFsmComputeExRings(Fsm_Fsm_t *absFsm, st_table *absVarTable, st_table *absBnvTable, array_t *oldRings, int cexType, int verbose);
00059 static int GrabCompareScores(const void *ptr1, const void *ptr2);
00060 static void GrabMddAppendSupports(mdd_manager *mddManager, mdd_t *mdd1, st_table *supportsTable);
00061 static array_t * ComputeDependence(Ntk_Network_t *network, st_table *vertexTable, array_t *leftVars);
00062 
00065 /*---------------------------------------------------------------------------*/
00066 /* Definition of internal functions                                          */
00067 /*---------------------------------------------------------------------------*/
00068 
00095 void
00096 GrabRefineAbstractionByGrab(
00097   Fsm_Fsm_t *absFsm,
00098   array_t   *SORs,
00099   st_table  *absVarTable,
00100   st_table  *BnvTable,
00101   array_t   *addedVars,
00102   array_t   *addedBnvs,
00103   int       refine_direction,   
00104   st_table  *nodeToFaninNumberTable, 
00105   int verbose)
00106 {
00107   Ntk_Network_t *network = Fsm_FsmReadNetwork(absFsm);
00108   mdd_manager   *mddManager = Ntk_NetworkReadMddManager(network);
00109   array_t       *ExRings;
00110   array_t       *visibleVarMddIds, *invisibleVarMddIds, *allPSVars;
00111   array_t       *tempArray;
00112   mdd_t         *mdd1, *mdd2;
00113   char          *nodeName;
00114   Ntk_Node_t    *node;
00115   double        *Scores, *SelScores, *Sel0Scores, *Sel2Scores, *Sel3Scores;
00116   double        epd, baseNum;
00117   int           i, j, nRow, nCol;
00118   long          mddId, value, value0;
00119   boolean       isSupport, isLatch;
00120   int           max_num_of_added_vars;
00121 
00122   /* compute the preimages (with invisible vars in their support)
00123    */
00124   ExRings = GrabFsmComputeExRings(absFsm, absVarTable, BnvTable, SORs,
00125                                   GRAB_CEX_SOR, verbose);
00126   assert(ExRings != NIL(array_t));
00127 
00128   visibleVarMddIds = GrabGetVisibleVarMddIds(absFsm,absVarTable);
00129   invisibleVarMddIds = GrabGetInvisibleVarMddIds(absFsm,absVarTable,BnvTable);
00130   allPSVars = array_dup(visibleVarMddIds);
00131   array_append(allPSVars, invisibleVarMddIds);
00132   assert(array_n(invisibleVarMddIds) > 0 );
00133   
00134   /* Compute the normalized number of "winning positions" for each individual
00135    * invisibleVar, and store them in 'Scores'!
00136    */
00137   nRow = array_n(ExRings);
00138   nCol = array_n(invisibleVarMddIds);
00139   Scores = ALLOC(double, nRow*nCol);
00140   memset(Scores, 0, sizeof(double)*nRow*nCol);
00141 
00142 
00143   /*********************************************************
00144    * for each set of abstract states in (mdd1, Ring[j+1] )
00145    *********************************************************/
00146   arrayForEachItem(mdd_t *, ExRings, j, mdd1) {
00147     st_table *localSupportsTable = st_init_table(st_numcmp, st_numhash);
00148     GrabMddAppendSupports(mddManager, mdd1, localSupportsTable);
00149 
00150     if (mdd_get_number_of_bdd_vars(mddManager, allPSVars) <= 1023 )
00151       baseNum = mdd_count_onset(mddManager, mdd1, allPSVars);
00152     else {
00153       mdd_t *stateMdd = mdd_smooth(mddManager, mdd1, invisibleVarMddIds);
00154       baseNum = mdd_count_onset(mddManager, stateMdd, visibleVarMddIds);
00155       mdd_free(stateMdd);
00156     }
00157     
00158     /***********************************************************
00159      * compute the impact of refining with each invisible var
00160      ***********************************************************/
00161     arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
00162       /* for debugging purpose. won't affect the algorithm */
00163       Scores[j*nCol+i] = -9E-99;
00164 
00165       /* give credit simply for the appearance */
00166       isSupport = st_is_member(localSupportsTable, (char *)mddId);
00167       if (!isSupport || baseNum==0.0)   continue;
00168       Scores[j*nCol+i] += 0.001;
00169 
00170       node = Ntk_NetworkFindNodeByMddId(network, mddId);
00171       isLatch = (Ntk_NodeTestIsLatch(node));
00172       if (refine_direction==0 && isLatch)  continue;
00173 
00174       {
00175         array_t *universalQVars = array_alloc(int, 0);
00176         /* MX */
00177         array_insert_last(int, universalQVars, mddId);
00178         mdd2 = mdd_consensus(mddManager, mdd1, universalQVars);
00179         array_free(universalQVars);
00180 
00181         if (mdd_get_number_of_bdd_vars(mddManager, allPSVars) <= 1023)
00182           epd = mdd_count_onset(mddManager, mdd2, allPSVars);
00183         else {
00184           mdd_t *stateMdd = mdd_smooth(mddManager, mdd2, invisibleVarMddIds);
00185           epd = mdd_count_onset(mddManager, stateMdd, visibleVarMddIds);
00186           mdd_free(stateMdd);
00187         }
00188         mdd_free(mdd2);
00189 
00190         Scores[j*nCol+i] = (baseNum - epd)/baseNum;
00191       }
00192       
00193       if (j == 0)
00194         Scores[j*nCol+i] /= 10.0;
00195 
00196     }
00197     st_free_table(localSupportsTable);
00198   }
00199 
00200   /* For each column, sum up the score over all the rows. The
00201    * selection of refinement variables will be based mainly on these
00202    * scores.
00203    */
00204   SelScores = ALLOC(double, nCol);
00205   memset(SelScores, 0, sizeof(double)*nCol);
00206   for (i=0; i<nRow; i++) {
00207     for (j=0; j<nCol; j++) { 
00208       SelScores[j] += Scores[i*nCol+j]; 
00209     }
00210   }
00211 
00212   /* Other selection criteria:
00213    * (0) when in the BOOLEAN refinement direction, only add bnvs
00214    * (2) how many absLatches depending on the invisible var?
00215    * (3) how much will the invisible var cost?
00216    */  
00217   Sel0Scores  = ALLOC(double, nCol);
00218   Sel2Scores  = ALLOC(double, nCol);
00219   Sel3Scores  = ALLOC(double, nCol);
00220   tempArray = ComputeDependence(network, absVarTable, invisibleVarMddIds);
00221   value0 = lsLength(Ntk_NetworkReadNodes(network));
00222   for (j=0; j<nCol; j++) {
00223     mddId = array_fetch(int, invisibleVarMddIds, j);
00224     node = Ntk_NetworkFindNodeByMddId(network, mddId);
00225     isLatch = (Ntk_NodeTestIsLatch(node));
00226     /* when refinement is in the BOOLEAN direction, only add bnvs 
00227      * otherwise, add either latches or bnvs 
00228      */
00229     if (refine_direction==0 && !isLatch)
00230       Sel0Scores[j] = 1.0;
00231     else
00232       Sel0Scores[j] = 0.0;      
00233     /* dependence */
00234     value = array_fetch(int, tempArray, j);
00235     Sel2Scores[j] = ((double)value)/st_count(absVarTable);
00236     /* cost */
00237     value = GrabNodeComputeFaninNumberTableItem(network, 
00238                                                 nodeToFaninNumberTable,
00239                                                 node);
00240     Sel3Scores[j] = 1.0 - ((double)value)/value0; 
00241   }
00242   array_free(tempArray);
00243 
00244   /* Print out the 'Scores' matrix when requested
00245    */
00246   if (verbose >= 5) {
00247     /* the entire score table */
00248     fprintf(vis_stdout, "\n Scores[%d][%d] = \n", nRow, nCol);
00249     arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
00250       node = Ntk_NetworkFindNodeByMddId(network, mddId);
00251       fprintf(vis_stdout, "%s ", (Ntk_NodeTestIsLatch(node)?"   L ":"     "));
00252     }
00253     fprintf(vis_stdout, "\n"); 
00254     arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
00255       node = Ntk_NetworkFindNodeByMddId(network, mddId);
00256       fprintf(vis_stdout, "%5d ", i);
00257     }
00258     fprintf(vis_stdout, "\n"); 
00259     for (i=0; i<nRow; i++) {
00260       for (j=0; j<nCol; j++) { 
00261         fprintf(vis_stdout, "%+1.2f ", Scores[i*nCol+j]);  
00262       } 
00263       fprintf(vis_stdout, "\n"); 
00264     }
00265     /* best score in each row */
00266     for (i=0; i<nRow; i++) {
00267       int best_local = 0;
00268       for (j=0; j<nCol; j++) { 
00269         if (Scores[i*nCol+best_local] < Scores[i*nCol+j])
00270           best_local = j;
00271       }
00272       fprintf(vis_stdout, "best_local: Scores[%d][%d] = %5g\n",
00273               i, best_local, Scores[i*nCol+best_local]);
00274     }
00275   }
00276 
00277   /* Sorting the invisibleVarMddIds according to the Selection Scores 
00278    */
00279   Sel0ScoreTable = st_init_table(st_numcmp, st_numhash);
00280   SelScoreTable  = st_init_table(st_numcmp, st_numhash);
00281   Sel2ScoreTable = st_init_table(st_numcmp, st_numhash);
00282   Sel3ScoreTable = st_init_table(st_numcmp, st_numhash);
00283   arrayForEachItem(int, invisibleVarMddIds, j, mddId) {
00284     st_insert(Sel0ScoreTable, (char *)mddId, (char *)(Sel0Scores+j));
00285     st_insert(SelScoreTable,  (char *)mddId, (char *)(SelScores+j));
00286     st_insert(Sel2ScoreTable, (char *)mddId, (char *)(Sel2Scores+j));
00287     st_insert(Sel3ScoreTable, (char *)mddId, (char *)(Sel3Scores+j));
00288   } 
00289 
00290   array_sort(invisibleVarMddIds, GrabCompareScores);
00291 
00292   if (verbose >= 4) {
00293     fprintf(vis_stdout, "       \t  Sel0    Sel     Sel2    Sel3\n");
00294     arrayForEachItem(int, invisibleVarMddIds, j, mddId) {
00295       double *addr;
00296       st_lookup(Sel0ScoreTable, (char *)mddId, &addr);
00297       i = (int)(addr-Sel0Scores);
00298       node = Ntk_NetworkFindNodeByMddId(network, mddId);
00299       isLatch = (Ntk_NodeTestIsLatch(node));
00300       fprintf(vis_stdout, 
00301               "%s[%d]\t %+1.3f  %+1.3f  %+1.3f  %+1.3f   %s\n",
00302               (isLatch? "L":" "), 
00303               i,
00304               Sel0Scores[i], SelScores[i], Sel2Scores[i], Sel3Scores[i],
00305               Ntk_NodeReadName(node)
00306               );
00307       /* only output the top 20 variables */
00308       if (j >= 19) break;
00309     }
00310   }
00311 
00312   st_free_table(Sel0ScoreTable);
00313   st_free_table(SelScoreTable);
00314   st_free_table(Sel2ScoreTable);
00315   st_free_table(Sel3ScoreTable);
00316 
00317   /* Now find the best (largest score) invisible Var   */
00318   {
00319     int num_absBnvs = BnvTable? st_count(BnvTable):0;
00320 
00321     if ((st_count(absVarTable) + num_absBnvs) < 10)
00322       max_num_of_added_vars = 1;
00323     else
00324       max_num_of_added_vars = 2 + (st_count(absVarTable)+num_absBnvs)/30;
00325   }
00326 
00327   arrayForEachItem(int, invisibleVarMddIds, j, mddId) {
00328 
00329     if (j >= max_num_of_added_vars)    break;
00330 
00331     node = Ntk_NetworkFindNodeByMddId(network, mddId);
00332     nodeName = Ntk_NodeReadName(node);
00333     if (Ntk_NodeTestIsLatch(node)) {
00334       assert(!st_is_member(absVarTable, node));
00335       st_insert(absVarTable, node, (char *)(long)st_count(absVarTable));
00336       array_insert_last(int, addedVars, mddId);
00337       CHKPRINT2( (verbose>=3), "         add Latch %s\n", nodeName );
00338     }else if (!Ntk_NodeTestIsLatch(node)) {
00339       assert(!st_is_member(BnvTable, node));
00340       st_insert(BnvTable, node, (char *)0);
00341       array_insert_last(int, addedBnvs, mddId);
00342       CHKPRINT2( (verbose>=3), "         add BNV %s\n", nodeName );
00343     }
00344   }
00345 
00346   /* Clean-ups */
00347   array_free(invisibleVarMddIds);
00348   array_free(visibleVarMddIds);
00349   array_free(allPSVars);
00350   mdd_array_free(ExRings);
00351   FREE(Scores);
00352   FREE(Sel0Scores);
00353   FREE(SelScores);
00354   FREE(Sel2Scores);
00355   FREE(Sel3Scores);
00356 }
00357 
00368 int
00369 GrabNodeComputeFaninNumberTableItem(
00370   Ntk_Network_t   *network,
00371   st_table        *nodeToFaninNumberTable,
00372   Ntk_Node_t      *node)
00373 {
00374   int          count;
00375   array_t      *roots, *supports;
00376 
00377   roots = array_alloc(Ntk_Node_t *, 0);
00378   if (!st_lookup_int(nodeToFaninNumberTable, node, &count)) {
00379     if (Ntk_NodeTestIsLatch(node)) 
00380       array_insert(Ntk_Node_t *, roots, 0, Ntk_LatchReadDataInput(node));
00381     else
00382       array_insert(Ntk_Node_t *, roots, 0, node);
00383 
00384     supports = Ntk_NodeComputeTransitiveFaninNodes(network, roots, TRUE,FALSE);
00385 
00386     count = array_n(supports);
00387     array_free(supports);
00388     st_insert(nodeToFaninNumberTable, node, (char *)(long)count);
00389   }
00390   array_free(roots);
00391 
00392   return count;
00393 }
00394 
00395 /*---------------------------------------------------------------------------*/
00396 /* Definition of static functions                                            */
00397 /*---------------------------------------------------------------------------*/
00398 
00412 static array_t *
00413 GrabFsmComputeExRings(
00414   Fsm_Fsm_t *absFsm,
00415   st_table  *absVarTable,
00416   st_table  *absBnvTable,
00417   array_t   *oldRings,
00418   int       cexType,
00419   int       verbose)
00420 {
00421   Img_ImageInfo_t *imageInfo;
00422   Ntk_Network_t   *network = Fsm_FsmReadNetwork(absFsm);
00423   array_t         *careStatesArray = array_alloc(mdd_t *, 0);
00424   array_t         *allPsVars, *invisibleVarMddIds;
00425   array_t         *onionRings, *synOnionRings;
00426   mdd_t           *mdd1, *mdd2, *mdd3, *mdd4, *initStates;
00427   int             i, j, mddId;
00428   Ntk_Node_t      *node;
00429 
00430   imageInfo = Fsm_FsmReadOrCreateImageInfo(absFsm, 1, 0);
00431 
00432   /* Compute the initial states based on all the related latches
00433    * (i.e. visible latches and invisible ones that are in the
00434    * immediate support)
00435    */
00436   allPsVars = GrabGetVisibleVarMddIds(absFsm, absVarTable);
00437   invisibleVarMddIds = GrabGetInvisibleVarMddIds(absFsm, absVarTable, 
00438                                                  absBnvTable);
00439   arrayForEachItem(int, invisibleVarMddIds, i, mddId) {
00440     node = Ntk_NetworkFindNodeByMddId(network, mddId);
00441     if (Ntk_NodeTestIsLatch(node))
00442       array_insert_last(int, allPsVars, mddId);
00443   }
00444   initStates = GrabComputeInitialStates(network, allPsVars);
00445   array_free(allPsVars);
00446   array_free(invisibleVarMddIds);
00447 
00448   onionRings = oldRings;
00449   if (onionRings == NIL(array_t))
00450     onionRings = Fsm_FsmReadReachabilityOnionRings(absFsm);
00451   assert(onionRings);
00452 
00453   synOnionRings = array_alloc(mdd_t *, array_n(onionRings));
00454 
00455   for (j=array_n(onionRings)-2; j>=0; j--) {
00456     mdd1 = array_fetch(mdd_t *, onionRings, j+1);
00457     mdd2 = array_fetch(mdd_t *, onionRings, j);
00458 
00459     array_insert(mdd_t *, careStatesArray, 0, mdd2);
00460     mdd3 = Img_ImageInfoComputeEXWithDomainVars(imageInfo,
00461                                                 mdd1,
00462                                                 mdd1,
00463                                                 careStatesArray);
00464     mdd4 = mdd_and(mdd2, mdd3, 1, 1);
00465     mdd_free(mdd3);
00466 
00467     array_insert(mdd_t *, synOnionRings, j+1, mdd4);
00468 
00469     /* when the more accurate initial states is available, use it */
00470     if (j == 0) {
00471       mdd1 = mdd_and(mdd4, initStates, 1, 1);
00472       if (mdd_is_tautology(mdd1, 0)) {
00473         mdd_free(mdd1);
00474         mdd1 = mdd_dup(mdd4);
00475       }
00476       array_insert(mdd_t *, synOnionRings, j, mdd1);
00477     }
00478   }
00479   
00480   /* clean-up's */
00481   mdd_free(initStates);
00482   array_free(careStatesArray);
00483 
00484   return synOnionRings;
00485 }
00486 
00502 static int
00503 GrabCompareScores(
00504   const void *ptr1,
00505   const void *ptr2)
00506 {
00507   int  item1 = *((int *)ptr1);
00508   int  item2 = *((int *)ptr2);
00509   double *first0, *first, *first2, *first3;
00510   double *second0, *second, *second2, *second3;
00511   double value0, value, value2, value3;
00512 
00513   st_lookup(Sel0ScoreTable, (char *)(long)item1,  &first0);
00514   st_lookup(SelScoreTable,  (char *)(long)item1,  &first);
00515   st_lookup(Sel2ScoreTable, (char *)(long)item1,  &first2);
00516   st_lookup(Sel3ScoreTable, (char *)(long)item1,  &first3);
00517 
00518   st_lookup(Sel0ScoreTable, (char *)(long)item2,  &second0);
00519   st_lookup(SelScoreTable,  (char *)(long)item2,  &second);
00520   st_lookup(Sel2ScoreTable, (char *)(long)item2,  &second2);
00521   st_lookup(Sel3ScoreTable, (char *)(long)item2,  &second3);
00522   
00523   value0 = *second0 - *first0;
00524   value  = *second  - *first;
00525   value2 = *second2 - *first2;
00526   value3 = *second3 - *first3;
00527   
00528   if (value0 > 0)         return 1;
00529   if (value0 < 0)         return -1;
00530 
00531   if (value > 0)          return 1;
00532   if (value < 0)          return -1;
00533 
00534   return 0;
00535 
00536   /* Chao: The tie-breakers are not used for this release. We achieved
00537    * the best performance on the suite of testing cases at hand
00538    * without the tie-breakers. But the code is retained for the
00539    * purpose of future experiments.
00540    */
00541   
00542   if (value2 > 0)         return 1;
00543   if (value2 < 0)         return -1;
00544 
00545   if (value3 > 0)         return 1;
00546   if (value3 < 0)         return -1;
00547 
00548   return 0;
00549 }
00550   
00551  
00561 static void 
00562 GrabMddAppendSupports( 
00563   mdd_manager *mddManager, 
00564   mdd_t *mdd1, 
00565   st_table *supportsTable) 
00566 {
00567   int mddId, k;
00568   array_t *supports = mdd_get_support(mddManager, mdd1);
00569 
00570   arrayForEachItem(int, supports, k, mddId) {
00571     if (!st_is_member(supportsTable, (char *)(long)mddId)) 
00572         st_insert(supportsTable, (char *)(long)mddId, (char *)0);
00573   }
00574   array_free(supports);
00575 }
00576 
00577 
00589 static array_t * 
00590 ComputeDependence(
00591   Ntk_Network_t *network, 
00592   st_table *vertexTable, 
00593   array_t *leftVars)
00594 {
00595   array_t *roots, *supports;
00596   st_table *supportTable;
00597   st_generator *stgen;
00598   array_t *dependenceArray = array_alloc(int, array_n(leftVars));
00599   int i,mddId;
00600   Ntk_Node_t *node, *node1;
00601   int count;
00602 
00603   /* initialize the scores to 0   */
00604   supportTable = st_init_table(st_ptrcmp, st_ptrhash);
00605   arrayForEachItem(int, leftVars, i, mddId) {
00606     node = Ntk_NetworkFindNodeByMddId(network, mddId);
00607     assert(node);
00608     st_insert(supportTable, node, (char *)0);
00609   }
00610 
00611   /* compute the supports of the absFsm  */
00612   roots = array_alloc(Ntk_Node_t *, 0);
00613   st_foreach_item(vertexTable, stgen,  &node,  0) {
00614     node = Ntk_LatchReadDataInput(node);
00615     array_insert(Ntk_Node_t *, roots, 0, node);
00616 
00617     supports = Ntk_NodeComputeTransitiveFaninNodes(network, roots, TRUE, 
00618                                                    FALSE);
00619 
00620     arrayForEachItem(Ntk_Node_t *, supports, i, node1) {
00621       if (st_lookup_int(supportTable, node1, &count)) {
00622         count++;
00623         st_insert(supportTable, node1, (char *)(long)count);
00624       }
00625     }
00626     array_free(supports);
00627   }
00628   array_free(roots);
00629 
00630   /* put into an array  */
00631   arrayForEachItem(int, leftVars, i, mddId) {
00632     node = Ntk_NetworkFindNodeByMddId(network, mddId);
00633     assert(node);
00634     st_lookup_int(supportTable, node, &count);
00635     array_insert(int, dependenceArray, i, count);
00636   }
00637 
00638   st_free_table(supportTable);
00639 
00640   return dependenceArray;
00641 }
00642 
00643 
00644