VIS

src/grab/grabBMC.c

Go to the documentation of this file.
00001 
00026 #include "grabInt.h"
00027 #include "bmcInt.h"
00028 
00029 /*---------------------------------------------------------------------------*/
00030 /* Constant declarations                                                     */
00031 /*---------------------------------------------------------------------------*/
00032 
00033 /*---------------------------------------------------------------------------*/
00034 /* Structure declarations                                                    */
00035 /*---------------------------------------------------------------------------*/
00036 
00037 /*---------------------------------------------------------------------------*/
00038 /* Type declarations                                                         */
00039 /*---------------------------------------------------------------------------*/
00040 
00041 /*---------------------------------------------------------------------------*/
00042 /* Variable declarations                                                     */
00043 /*---------------------------------------------------------------------------*/
00044 
00045 /*---------------------------------------------------------------------------*/
00046 /* Macro declarations                                                        */
00047 /*---------------------------------------------------------------------------*/
00048 
00051 /*---------------------------------------------------------------------------*/
00052 /* Static function prototypes                                                */
00053 /*---------------------------------------------------------------------------*/
00054 
00055 static bAigEdge_t GrabConvertBddToBaig(bAig_Manager_t *bAigManager, bdd_t *fn, st_table *bddidToNames);
00056 static st_table * GrabBddGetSupportBaigNames(mdd_manager *mddManager, mdd_t *f);
00057 static char * GrabBddIdToBaigNames(mdd_manager *mddManager, int bddid);
00058 
00061 /*---------------------------------------------------------------------------*/
00062 /* Definition of exported functions                                          */
00063 /*---------------------------------------------------------------------------*/
00064 
00076 boolean
00077 Bmc_AbstractCheckAbstractTraces(
00078   Ntk_Network_t *network,
00079   array_t *synOnionRings,
00080   st_table *absLatches,
00081   int verbose, 
00082   int dbgLevel,
00083   int printInputs)
00084 {
00085   int               pathLength = array_n(synOnionRings) -1;
00086   mAig_Manager_t    *maigManager = Ntk_NetworkReadMAigManager(network);
00087   st_table          *nodeToMvfAigTable = NIL(st_table); 
00088   BmcCnfClauses_t   *cnfClauses;
00089   FILE              *cnfFile;
00090   BmcOption_t       *options;
00091   array_t           *result;
00092   int               i;
00093   boolean           CexExit = FALSE;
00094   
00095   nodeToMvfAigTable =
00096     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00097   if (nodeToMvfAigTable == NIL(st_table)){
00098     fprintf(vis_stderr, 
00099             "** bmc error: please run buid_partiton_maigs first\n");
00100     return CexExit;
00101   }
00102 
00103   options = BmcOptionAlloc();
00104   if (verbose) { 
00105     options->dbgLevel = dbgLevel;
00106     options->printInputs = printInputs;
00107   }
00108   options->satInFile = BmcCreateTmpFile();
00109   if (options->satInFile == NIL(char)){
00110     BmcOptionFree(options);
00111     return CexExit;
00112   }
00113 
00114   /* create SAT Solver output file */
00115   options->satOutFile = BmcCreateTmpFile();
00116   if (options->satOutFile == NIL(char)){
00117     BmcOptionFree(options);
00118     fprintf(vis_stderr, "** bmc error: Cannot allocate a temp file name\n");
00119     return CexExit;
00120   }
00121   cnfFile = Cmd_FileOpen(options->satInFile, "w", NIL(char *), 0);  
00122   if (cnfFile == NIL(FILE)) {
00123     BmcOptionFree(options);
00124     fprintf(vis_stderr, "** bmc error: Cannot create CNF output file %s\n",
00125             options->satInFile);
00126     return CexExit;
00127   }
00128 
00129   /* Unroll the model exactly 'pathLength' time frames
00130    */
00131   cnfClauses = BmcCnfClausesAlloc();
00132   BmcCnfGenerateClausesForPath(network, 0, pathLength, BMC_INITIAL_STATES,
00133                                cnfClauses, nodeToMvfAigTable, absLatches);
00134 
00135   /* Generate the constraints from the abstract paths
00136    *   (1) build a bAigEdge_t (graph) for each ring
00137    *   (2) add all the cnf clauses that describe this graph
00138    *   (3) make the output bAigEdge_t equals to 1
00139   */
00140   {
00141     bAigEdge_t  bAigState;
00142     mdd_manager *mddManager = Ntk_NetworkReadMddManager(network);
00143     array_t     *clause = array_alloc(int, 1);
00144     mdd_t       *ring;
00145 
00146     arrayForEachItem(mdd_t *, synOnionRings, i, ring) {
00147       st_table *bddidTobAigNames;
00148       bddidTobAigNames = GrabBddGetSupportBaigNames(mddManager, ring);
00149       bAigState = GrabConvertBddToBaig(maigManager, ring, bddidTobAigNames);
00150       {
00151         st_generator *stgen;
00152         long tmpId;
00153         char *tmpStr;
00154         st_foreach_item(bddidTobAigNames, stgen, &tmpId, &tmpStr) {
00155           FREE(tmpStr);
00156         }
00157         st_free_table(bddidTobAigNames);
00158       }
00159       array_insert(int, clause, 0, BmcGenerateCnfFormulaForAigFunction(
00160                                   maigManager, bAigState, i, cnfClauses));
00161       BmcCnfInsertClause(cnfClauses, clause);
00162     } 
00163    
00164     array_free(clause);
00165   } 
00166 
00167   /* Call the SAT solver 
00168    */
00169   BmcWriteClauses(maigManager, cnfFile, cnfClauses, options); 
00170   fclose(cnfFile);
00171   result = BmcCheckSAT(options);
00172   if(result != NIL(array_t)){
00173     if (verbose >= 1 && dbgLevel ==1) {
00174       fprintf(vis_stdout,"Found Counterexample of length = %d\n", pathLength);
00175       BmcPrintCounterExample(network, nodeToMvfAigTable, cnfClauses,
00176                              result, pathLength+1, absLatches, options, 
00177                              NIL(array_t));
00178     }
00179     if (verbose >=1 && dbgLevel == 2) {
00180       BmcPrintCounterExampleAiger(network, nodeToMvfAigTable, cnfClauses,
00181                              result, pathLength+1, absLatches, options,
00182                              NIL(array_t));
00183     }   
00184     CexExit = TRUE;
00185   }  
00186 
00187   /* free all used memories */
00188   BmcCnfClausesFree(cnfClauses);
00189   array_free(result);
00190   BmcOptionFree(options);
00191 
00192   return CexExit;
00193 }
00194 
00195 
00214 boolean
00215 Bmc_AbstractCheckAbstractTracesWithFineGrain(
00216   Ntk_Network_t *network,
00217   st_table *coiBnvTable,
00218   array_t *synOnionRings,
00219   st_table *absLatches,
00220   st_table *absBnvs)
00221 {
00222   boolean             result;
00223   mAigManagerState_t  oldMaigState;  /* to store the previous AIG */
00224   mAig_Manager_t      *maigManager;
00225   lsGen               lsgen;
00226   Ntk_Node_t          *node;
00227   int                 mAigId;
00228   int                 i;
00229   st_generator        *stgen;
00230   st_table            *leaves;
00231   array_t             *roots, *combInputs;
00232 
00233   /* save the existing maigManager */
00234   oldMaigState.manager = Ntk_NetworkReadMAigManager(network);
00235   oldMaigState.nodeToMvfAigTable =  
00236     (st_table *) Ntk_NetworkReadApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00237   oldMaigState.nodeToMAigIdTable = st_init_table(st_ptrcmp, st_ptrhash);
00238   Ntk_NetworkForEachNode(network, lsgen, node) {
00239     mAigId = Ntk_NodeReadMAigId(node);
00240     st_insert(oldMaigState.nodeToMAigIdTable, node, (char *)(long)mAigId);
00241     Ntk_NodeSetMAigId(node, ntmaig_UNUSED);
00242   }
00243 
00244   /* create a new maigManager */
00245   maigManager = mAig_initAig();
00246   Ntk_NetworkSetMAigManager(network, maigManager);
00247   Ntk_NetworkSetApplInfo(network, MVFAIG_NETWORK_APPL_KEY,
00248                          (Ntk_ApplInfoFreeFn) ntmAig_MvfAigTableFreeCallback,
00249                          (void *) st_init_table(st_ptrcmp, st_ptrhash));
00250 
00251   /* roots are the visible latches, and the visible bnvs (some bnvs
00252    * may not be in the transitive fan-in cone of the visible latches
00253    */
00254   roots = array_alloc(Ntk_Node_t *, 0);
00255   st_foreach_item(absLatches, stgen, &node, NIL(char *)) {
00256     array_insert_last(Ntk_Node_t *, roots, Ntk_LatchReadDataInput(node));
00257     array_insert_last(Ntk_Node_t *, roots, Ntk_LatchReadInitialInput(node));
00258   }
00259   st_foreach_item(absBnvs, stgen, &node, NIL(char *)) {
00260     array_insert_last(Ntk_Node_t *, roots, node);
00261   }
00262 
00263   combInputs = Ntk_NodeComputeTransitiveFaninNodes(network, roots, 
00264                                                    TRUE, /* stopAtLatches */
00265                                                    FALSE /* combInputsOnly*/
00266                                                    );
00267 
00268   /* leaves are the combinational inputs or the invisible bnvs */
00269   leaves = st_init_table(st_ptrcmp, st_ptrhash);
00270   arrayForEachItem(Ntk_Node_t *, combInputs, i, node) {
00271     if ( Ntk_NodeTestIsCombInput(node) ||
00272          ( st_is_member(coiBnvTable, node) &&
00273            !st_is_member(absBnvs, node) ) ) {
00274       st_insert(leaves, node, (char *) ntmaig_UNUSED);
00275       Ntk_NodeSetMAigId(node, mAig_CreateVar(maigManager,
00276                                              Ntk_NodeReadName(node),
00277                    Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
00278     }
00279   }
00280   st_foreach_item(absLatches, stgen, &node, NIL(char *)) {
00281     if (!st_is_member(leaves, node)) {
00282       st_insert(leaves, node, (char *) ntmaig_UNUSED);
00283       Ntk_NodeSetMAigId(node, mAig_CreateVar(maigManager,
00284                                              Ntk_NodeReadName(node),
00285                    Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
00286     }
00287   }
00288   array_free(combInputs);
00289 
00290 #if 1
00291   /* THIS SEEMS UNNECESSARY---IT'S HERE TO AVOID ERRORS IN CALLING
00292    * ntmaig_NetworkBuildMvfAigs()
00293    */
00294   Ntk_NetworkForEachCombInput(network, lsgen, node) {
00295     if (Ntk_NodeReadMAigId(node) == NTK_UNASSIGNED_MAIG_ID) {
00296       Ntk_NodeSetMAigId(node, mAig_CreateVar(maigManager,
00297                                              Ntk_NodeReadName(node),
00298                    Var_VariableReadNumValues(Ntk_NodeReadVariable(node))));
00299     } 
00300   }
00301 #endif
00302 
00303   /* build the new AIG graph */
00304   ntmaig_NetworkBuildMvfAigs(network, roots, leaves);
00305 
00306   array_free(roots);
00307   st_free_table(leaves);
00308 
00309 
00310   /* check the existence of the abstract path on the new AIG graph */
00311   result = Bmc_AbstractCheckAbstractTraces(network,
00312                                            synOnionRings,
00313                                            absLatches,
00314                                            0, 0, 0);
00315 
00316   /* restore the previous maigManager */
00317   mAig_quit(maigManager);
00318   Ntk_NetworkFreeApplInfo(network, MVFAIG_NETWORK_APPL_KEY);
00319   Ntk_NetworkSetMAigManager(network, oldMaigState.manager);
00320   Ntk_NetworkSetApplInfo(network, MVFAIG_NETWORK_APPL_KEY,
00321                          (Ntk_ApplInfoFreeFn) ntmAig_MvfAigTableFreeCallback,
00322                          (void *) oldMaigState.nodeToMvfAigTable);
00323   st_foreach_item(oldMaigState.nodeToMAigIdTable, stgen, &node,
00324                   &mAigId) {
00325     Ntk_NodeSetMAigId(node, mAigId);
00326   }
00327   st_free_table(oldMaigState.nodeToMAigIdTable);
00328 
00329   return result;
00330 }
00331 
00332 /*---------------------------------------------------------------------------*/
00333 /* Definition of static functions                                            */
00334 /*---------------------------------------------------------------------------*/
00335 
00354 static bAigEdge_t
00355 GrabConvertBddToBaig(
00356    bAig_Manager_t *bAigManager,
00357    bdd_t          *fn,
00358    st_table       *bddidToNames)
00359 {
00360   bdd_gen     *gen;
00361   bdd_node    *node, *thenNode, *elseNode, *funcNode;
00362   bdd_manager *bddManager = bdd_get_manager(fn);
00363   bdd_node    *one  = bdd_read_one(bddManager);
00364   /*bdd_node    *zero = bdd_read_logic_zero(bddManager);*/
00365   int         is_complemented;
00366   int         flag;
00367   bAigEdge_t  var, left, right, result;
00368   char        *name;
00369   st_table    *bddTObaigTable;
00370   
00371   bddTObaigTable = st_init_table(st_numcmp, st_numhash);
00372 
00373   if (fn == NULL){
00374     return bAig_NULL;
00375   }
00376   
00377   st_insert(bddTObaigTable, (char *) (long) bdd_regular(one),  
00378             (char *) bAig_One);
00379 
00380   funcNode = bdd_get_node(fn, &is_complemented);
00381   
00382   if (bdd_is_constant(funcNode)){
00383     flag = st_lookup(bddTObaigTable, 
00384                      (char *) (long) (funcNode),
00385                      &result);
00386     assert(flag);
00387     st_free_table(bddTObaigTable);
00388 
00389     if (is_complemented)
00390       return bAig_Not(result);
00391     else
00392       return result;
00393   }
00394   
00395   foreach_bdd_node(fn, gen, node){
00396     /* if the node has been processed, skip it. (the constant ONE
00397      * should be the only node falls into this category).
00398      */
00399     if (st_is_member(bddTObaigTable, (char *) (long) bdd_regular(node)))
00400       continue;
00401     
00402     /*  bdd_node_read_index() return the current level's bddId */
00403     if (bddidToNames) {
00404       flag = st_lookup(bddidToNames, (char *)(long)bdd_node_read_index(node),
00405                        &name);
00406       assert(flag);
00407       name = util_strsav(name);
00408     }else {
00409       char tempString[1024];
00410       sprintf(tempString, "BDD%d", bdd_node_read_index(node));
00411       name = util_strsav(tempString);
00412     }
00413 
00414     /*  Create or Retrieve the bAigEdge_t  w.r.t. 'name' */
00415     var  = bAig_CreateVarNode(bAigManager, name);
00416     FREE(name);
00417 
00418     thenNode  = bdd_bdd_T(node);
00419     flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(thenNode),
00420                      &left);
00421     assert(flag);
00422       
00423     elseNode  = bdd_bdd_E(node);
00424     flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(elseNode),
00425                       &right);
00426     assert(flag);
00427 
00428     /* should we test here whether elseNode is complemented arc? */
00429     if (bdd_is_complement(elseNode))
00430       right = bAig_Not(right);
00431 
00432     result =  bAig_Or(bAigManager, bAig_And(bAigManager, var, left),
00433                                    bAig_And(bAigManager, bAig_Not(var), right));
00434     st_insert(bddTObaigTable, (char *) (long) bdd_regular(node),
00435               (char *) (long) result);
00436   }
00437   flag = st_lookup(bddTObaigTable, (char *) (long) bdd_regular(funcNode),
00438                     &result);  
00439   assert(flag);
00440   st_free_table(bddTObaigTable);
00441 
00442   if (is_complemented){
00443     return bAig_Not(result);
00444   } else {
00445     return result;
00446   }
00447 } /* end of bAig_bddtobAig() */
00448 
00449 
00461 static st_table *
00462 GrabBddGetSupportBaigNames(
00463   mdd_manager *mddManager,
00464   mdd_t *f)
00465 {
00466   int        numOfVars = bdd_num_vars(mddManager);
00467   st_table  *bddidTObaigNames = st_init_table(st_numcmp, st_numhash);
00468   var_set_t *vset;
00469   int        i;
00470 
00471   vset = bdd_get_support(f);
00472   for (i=0; i<numOfVars; i++) {
00473     if (var_set_get_elt(vset, i) == 1) {
00474       st_insert(bddidTObaigNames, (char *)(long)i, 
00475                 GrabBddIdToBaigNames(mddManager, i));
00476     }
00477   }
00478   var_set_free(vset);
00479 
00480   return bddidTObaigNames;
00481 }
00482 
00494 static char *
00495 GrabBddIdToBaigNames(
00496   mdd_manager *mddManager,
00497   int            bddid)
00498 {
00499   array_t *mvar_list = mdd_ret_mvar_list(mddManager);
00500   array_t *bvar_list = mdd_ret_bvar_list(mddManager);
00501   bvar_type bv;
00502   mvar_type mv;
00503   int     mddid, index, id;
00504   char    *nodeName;
00505   char    baigName[1024];
00506 
00507   /* 1. from bddid, get mddid and the index of this bddid in the mddid 
00508    */
00509   bv = array_fetch(bvar_type, bvar_list, bddid);
00510   mddid = bv.mvar_id;
00511   mv = array_fetch(mvar_type, mvar_list, mddid);
00512   arrayForEachItem(int, mv.bvars, index, id) {
00513     if (id == bddid) 
00514       break;
00515   }
00516   assert(index <= mv.encode_length -1);
00517   
00518   /* 2. assumptions: (1) mv.name = nodeName,  
00519    *                 (2) index is the same for MDD and MAIG
00520    */
00521   nodeName = mv.name;
00522   
00523   /* 3. the baigEdge_t's name is ("%s_%d",nodeName,index)
00524    */
00525   sprintf(baigName, "%s_%d", nodeName, index);
00526 
00527   return util_strsav(baigName);
00528 }
00529 
00530 
00531 
00532 
00533 
00534