/**Function*************************************************************

  Synopsis    [Collects internal nodes in the DFS order.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Aig_ManDfsChoices_rec( Aig_Man_t * p, Aig_Obj_t * pObj, Vec_Ptr_t * vNodes )
{
    if ( pObj == NULL )
        return;
    assert( !Aig_IsComplement(pObj) );
    if ( Aig_ObjIsTravIdCurrent(p, pObj) )
        return;
    assert( Aig_ObjIsNode(pObj) );
    Aig_ManDfsChoices_rec( p, Aig_ObjFanin0(pObj), vNodes );
    Aig_ManDfsChoices_rec( p, Aig_ObjFanin1(pObj), vNodes );
    Aig_ManDfsChoices_rec( p, p->pEquivs[pObj->Id], vNodes );
    assert( !Aig_ObjIsTravIdCurrent(p, pObj) ); // loop detection
    Aig_ObjSetTravIdCurrent(p, pObj);
    Vec_PtrPush( vNodes, pObj );
}
/**Function*************************************************************

  Synopsis    [Create the new node assuming it does not exist.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Aig_ObjCreate( Aig_Man_t * p, Aig_Obj_t * pGhost )
{
    Aig_Obj_t * pObj;
    assert( !Aig_IsComplement(pGhost) );
    assert( Aig_ObjIsHash(pGhost) );
    assert( pGhost == &p->Ghost );
    // get memory for the new object
    pObj = Aig_ManFetchMemory( p );
    pObj->Type = pGhost->Type;
    // add connections
    Aig_ObjConnect( p, pObj, pGhost->pFanin0, pGhost->pFanin1 );
    // update node counters of the manager
    p->nObjs[Aig_ObjType(pObj)]++;
    assert( pObj->pData == NULL );
    return pObj;
}
Exemple #3
0
/**Function*************************************************************

  Synopsis    [Counts the number of one's in the patten the object.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ssw_SmlNodeCountOnesReal( Ssw_Sml_t * p, Aig_Obj_t * pObj )
{
    unsigned * pSims;
    int i, Counter = 0;
    pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
    if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
    {
        for ( i = 0; i < p->nWordsTotal; i++ )
            Counter += Aig_WordCountOnes( ~pSims[i] );
    }
    else
    {
        for ( i = 0; i < p->nWordsTotal; i++ )
            Counter += Aig_WordCountOnes( pSims[i] );
    }
    return Counter;
}
Exemple #4
0
Vec_Ptr_t * Dar_BalanceCone( Aig_Obj_t * pObj, Vec_Vec_t * vStore, int Level )
{
    Vec_Ptr_t * vNodes;
    assert( !Aig_IsComplement(pObj) );
    assert( Aig_ObjIsNode(pObj) );
    // extend the storage
    if ( Vec_VecSize( vStore ) <= Level )
        Vec_VecPush( vStore, Level, 0 );
    // get the temporary array of nodes
    vNodes = Vec_VecEntry( vStore, Level );
    Vec_PtrClear( vNodes );
    // collect the nodes in the implication supergate
    Dar_BalanceCone_rec( pObj, pObj, vNodes );
    // remove duplicates
    Dar_BalanceUniqify( pObj, vNodes, Aig_ObjIsExor(pObj) );
    return vNodes;
}
 // update the CO pointers
 Ntl_ManForEachCoNet( p, pNetCo, i )
 {
     if ( pNetCo->fMark )
         continue;
     pNetCo->fMark = 1;
     pNet = (Ntl_Net_t *)Vec_PtrEntry( vCopies, Aig_Regular((Aig_Obj_t *)pNetCo->pCopy)->Id );
     pNode = Ntl_ModelCreateNode( pRoot, 1 );
     pNode->pSop = Aig_IsComplement((Aig_Obj_t *)pNetCo->pCopy)? Ntl_ManStoreSop( p->pMemSops, "0 1\n" ) : Ntl_ManStoreSop( p->pMemSops, "1 1\n" );
     Ntl_ObjSetFanin( pNode, pNet, 0 );
     // update the CO driver net
     assert( pNetCo->pDriver == NULL );
     if ( !Ntl_ModelSetNetDriver( pNode, pNetCo ) )
     {
         printf( "Ntl_ManInsert(): Internal error: PO net has more than one fanin.\n" );
         return 0;
     }
 }
Exemple #6
0
/**Function*************************************************************

  Synopsis    [Labels the nodes in the MFFC.]

  Description [Returns the number of internal nodes in the MFFC.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Aig_NodeMffsLabelCut( Aig_Man_t * p, Aig_Obj_t * pNode, Vec_Ptr_t * vLeaves )
{
    Aig_Obj_t * pObj;
    int i, ConeSize1, ConeSize2;
    assert( !Aig_IsComplement(pNode) );
    assert( Aig_ObjIsNode(pNode) );
    Aig_ManIncrementTravId( p );
    Vec_PtrForEachEntry( vLeaves, pObj, i )
        pObj->nRefs++;
    ConeSize1 = Aig_NodeDeref_rec( pNode, 0 );
    ConeSize2 = Aig_NodeRefLabel_rec( p, pNode, 0 );
    Vec_PtrForEachEntry( vLeaves, pObj, i )
        pObj->nRefs--;
    assert( ConeSize1 == ConeSize2 );
    assert( ConeSize1 > 0 );
    return ConeSize1;
}
/**Function*************************************************************

  Synopsis    [Deletes the MFFC of the node.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Aig_ObjDelete_rec( Aig_Man_t * p, Aig_Obj_t * pObj, int fFreeTop )
{
    Aig_Obj_t * pFanin0, * pFanin1;
    assert( !Aig_IsComplement(pObj) );
    if ( Aig_ObjIsConst1(pObj) || Aig_ObjIsPi(pObj) )
        return;
    assert( !Aig_ObjIsPo(pObj) );
    pFanin0 = Aig_ObjFanin0(pObj);
    pFanin1 = Aig_ObjFanin1(pObj);
    Aig_ObjDisconnect( p, pObj );
    if ( fFreeTop )
        Aig_ObjDelete( p, pObj );
    if ( pFanin0 && !Aig_ObjIsNone(pFanin0) && Aig_ObjRefs(pFanin0) == 0 )
        Aig_ObjDelete_rec( p, pFanin0, 1 );
    if ( pFanin1 && !Aig_ObjIsNone(pFanin1) && Aig_ObjRefs(pFanin1) == 0 )
        Aig_ObjDelete_rec( p, pFanin1, 1 );
}
Exemple #8
0
/**Function*************************************************************

  Synopsis    [Checks if node with the given attributes is in the hash table.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Aig_TableLookup( Aig_Man_t * p, Aig_Obj_t * pGhost )
{
    Aig_Obj_t * pEntry;
    assert( !Aig_IsComplement(pGhost) );
    assert( Aig_ObjIsNode(pGhost) );
    assert( Aig_ObjChild0(pGhost) && Aig_ObjChild1(pGhost) );
    assert( Aig_ObjFanin0(pGhost)->Id < Aig_ObjFanin1(pGhost)->Id );
    if ( p->pTable == NULL || !Aig_ObjRefs(Aig_ObjFanin0(pGhost)) || !Aig_ObjRefs(Aig_ObjFanin1(pGhost)) )
        return NULL;
    for ( pEntry = p->pTable[Aig_Hash(pGhost, p->nTableSize)]; pEntry; pEntry = pEntry->pNext )
    {
        if ( Aig_ObjChild0(pEntry) == Aig_ObjChild0(pGhost) && 
             Aig_ObjChild1(pEntry) == Aig_ObjChild1(pGhost) && 
             Aig_ObjType(pEntry) == Aig_ObjType(pGhost) )
            return pEntry;
    }
    return NULL;
}
Exemple #9
0
/**Function*************************************************************

  Synopsis    [Collects the support of depth-limited MFFC.]

  Description [Returns the number of internal nodes in the MFFC.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Aig_NodeMffcSupp( Aig_Man_t * p, Aig_Obj_t * pNode, int LevelMin, Vec_Ptr_t * vSupp )
{
    int ConeSize1, ConeSize2;
    if ( vSupp ) Vec_PtrClear( vSupp );
    if ( !Aig_ObjIsNode(pNode) )
    {
        if ( Aig_ObjIsCi(pNode) && vSupp )
            Vec_PtrPush( vSupp, pNode );
        return 0;
    }
    assert( !Aig_IsComplement(pNode) );
    assert( Aig_ObjIsNode(pNode) );
    Aig_ManIncrementTravId( p );
    ConeSize1 = Aig_NodeDeref_rec( pNode, LevelMin, NULL, NULL );
    Aig_NodeMffcSupp_rec( p, pNode, LevelMin, vSupp, 1, NULL );
    ConeSize2 = Aig_NodeRef_rec( pNode, LevelMin );
    assert( ConeSize1 == ConeSize2 );
    assert( ConeSize1 > 0 );
    return ConeSize1;
}
/**Function*************************************************************

  Synopsis    [Replaces the first fanin of the node by the new fanin.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Aig_ObjPatchFanin0( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pFaninNew )
{
    Aig_Obj_t * pFaninOld;
    assert( !Aig_IsComplement(pObj) );
    assert( Aig_ObjIsPo(pObj) );
    pFaninOld = Aig_ObjFanin0(pObj);
    // decrement ref and remove fanout
    if ( p->pFanData )
        Aig_ObjRemoveFanout( p, pFaninOld, pObj );
    Aig_ObjDeref( pFaninOld );
    // update the fanin
    pObj->pFanin0 = pFaninNew;
    // increment ref and add fanout
    if ( p->pFanData )
        Aig_ObjAddFanout( p, Aig_ObjFanin0(pObj), pObj );
    Aig_ObjRef( Aig_ObjFanin0(pObj) );
    // get rid of old fanin
    if ( !Aig_ObjIsPi(pFaninOld) && !Aig_ObjIsConst1(pFaninOld) && Aig_ObjRefs(pFaninOld) == 0 )
        Aig_ObjDelete_rec( p, pFaninOld, 1 );
}
Exemple #11
0
/**Function*************************************************************

  Synopsis    [Counts the number of one's in the patten the object.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ssw_SmlNodeCountOnesRealVec( Ssw_Sml_t * p, Vec_Ptr_t * vObjs )
{
    Aig_Obj_t * pObj;
    unsigned * pSims, uWord;
    int i, k, Counter = 0;
    if ( Vec_PtrSize(vObjs) == 0 )
        return 0;
    for ( i = 0; i < p->nWordsTotal; i++ )
    {
        uWord = 0;
        Vec_PtrForEachEntry( Aig_Obj_t *, vObjs, pObj, k )
        {
            pSims = Ssw_ObjSim(p, Aig_Regular(pObj)->Id);
            if ( Aig_Regular(pObj)->fPhase ^ Aig_IsComplement(pObj) )
                uWord |= ~pSims[i];
            else
                uWord |= pSims[i];
        }
        Counter += Aig_WordCountOnes( uWord );
    }
Exemple #12
0
/**Function*************************************************************

  Synopsis    [Counts the number of 1s in the implication.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ssw_SmlCountXorImplication( Ssw_Sml_t * p, Aig_Obj_t * pObjLi, Aig_Obj_t * pObjLo, Aig_Obj_t * pCand )
{
    unsigned * pSimLi, * pSimLo, * pSimCand;
    int k, Counter = 0;
    assert( pObjLo->fPhase == 0 );
    // pObjLi->fPhase may be 1, but the LI simulation data is not complemented!
    pSimCand = Ssw_ObjSim( p, Aig_Regular(pCand)->Id );
    pSimLi   = Ssw_ObjSim( p, pObjLi->Id );
    pSimLo   = Ssw_ObjSim( p, pObjLo->Id );
    if ( Aig_Regular(pCand)->fPhase ^ Aig_IsComplement(pCand) )
    {
        for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
            Counter += Aig_WordCountOnes(~pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
    }
    else
    {
        for ( k = p->nWordsPref; k < p->nWordsTotal; k++ )
            Counter += Aig_WordCountOnes(pSimCand[k] & ~(pSimLi[k] ^ pSimLo[k]));
    }
    return Counter;
}
Exemple #13
0
/**Function*************************************************************

  Synopsis    [Returns 1 if simulation does not filter out this candidate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Cgt_SimulationFilter( Cgt_Man_t * p, Aig_Obj_t * pCandPart, Aig_Obj_t * pMiterPart )
{
    unsigned * pInfoCand, * pInfoMiter;
    int w, nWords = Aig_BitWordNum( p->nPatts );  
    pInfoCand  = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(Aig_Regular(pCandPart)) );
    pInfoMiter = (unsigned *)Vec_PtrEntry( p->vPatts, Aig_ObjId(pMiterPart) );
    // C => !M -- true   is the same as    C & M -- false
    if ( !Aig_IsComplement(pCandPart) )
    {
        for ( w = 0; w < nWords; w++ )
            if ( pInfoCand[w] & pInfoMiter[w] )
                return 0;
    }
    else
    {
        for ( w = 0; w < nWords; w++ )
            if ( ~pInfoCand[w] & pInfoMiter[w] )
                return 0;
    }
    return 1;
}
/**Function*************************************************************

  Synopsis    [Sets variable activities in the cone.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_SetActivityFactors_rec( Fra_Man_t * p, Aig_Obj_t * pObj, int LevelMin, int LevelMax )
{
    Vec_Ptr_t * vFanins;
    Aig_Obj_t * pFanin;
    int i, Counter = 0;
    assert( !Aig_IsComplement(pObj) );
    assert( Fra_ObjSatNum(pObj) );
    // skip visited variables
    if ( Aig_ObjIsTravIdCurrent(p->pManFraig, pObj) )
        return 0;
    Aig_ObjSetTravIdCurrent(p->pManFraig, pObj);
    // add the PI to the list
    if ( pObj->Level <= (unsigned)LevelMin || Aig_ObjIsPi(pObj) )
        return 0;
    // set the factor of this variable
    // (LevelMax-LevelMin) / (pObj->Level-LevelMin) = p->pPars->dActConeBumpMax / ThisBump
    p->pSat->factors[Fra_ObjSatNum(pObj)] = p->pPars->dActConeBumpMax * (pObj->Level - LevelMin)/(LevelMax - LevelMin);
    veci_push(&p->pSat->act_vars, Fra_ObjSatNum(pObj));
    // explore the fanins
    vFanins = Fra_ObjFaninVec( pObj );
    Vec_PtrForEachEntry( vFanins, pFanin, i )
        Counter += Fra_SetActivityFactors_rec( p, Aig_Regular(pFanin), LevelMin, LevelMax );
    return 1 + Counter;
}
/**Function*************************************************************

  Synopsis    [Runs equivalence test for the two nodes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_NodesAreEquiv( Fra_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
{
    int pLits[4], RetValue, RetValue1, nBTLimit, clk, clk2 = clock();
    int status;

    // make sure the nodes are not complemented
    assert( !Aig_IsComplement(pNew) );
    assert( !Aig_IsComplement(pOld) );
    assert( pNew != pOld );

    // if at least one of the nodes is a failed node, perform adjustments:
    // if the backtrack limit is small, simply skip this node
    // if the backtrack limit is > 10, take the quare root of the limit
    nBTLimit = p->pPars->nBTLimitNode;
    if ( !p->pPars->fSpeculate && p->pPars->nFramesK == 0 && (nBTLimit > 0 && (pOld->fMarkB || pNew->fMarkB)) )
    {
        p->nSatFails++;
        // fail immediately
//        return -1;
        if ( nBTLimit <= 10 )
            return -1;
        nBTLimit = (int)pow(nBTLimit, 0.7);
    }

    p->nSatCalls++;

    // make sure the solver is allocated and has enough variables
    if ( p->pSat == NULL )
    {
        p->pSat = sat_solver_new();
        p->nSatVars = 1;
        sat_solver_setnvars( p->pSat, 1000 );
    }

    // if the nodes do not have SAT variables, allocate them
    Fra_NodeAddToSolver( p, pOld, pNew );

    if ( p->pSat->qtail != p->pSat->qhead )
    {
        status = sat_solver_simplify(p->pSat);
        assert( status != 0 );
        assert( p->pSat->qtail == p->pSat->qhead );
    }

    // prepare variable activity
    if ( p->pPars->fConeBias )
        Fra_SetActivityFactors( p, pOld, pNew ); 

    // solve under assumptions
    // A = 1; B = 0     OR     A = 1; B = 1 
clk = clock();
    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 0 );
    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase == pNew->fPhase );
//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
        (sint64)nBTLimit, (sint64)0, 
        p->nBTLimitGlobal, p->nInsLimitGlobal );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
        assert( RetValue );
        // continue solving the other implication
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        Fra_SavePattern( p );
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatFail += clock() - clk;
        // mark the node as the failed node
        if ( pOld != p->pManFraig->pConst1 ) 
            pOld->fMarkB = 1;
        pNew->fMarkB = 1;
        p->nSatFailsReal++;
        return -1;
    }

    // if the old node was constant 0, we already know the answer
    if ( pOld == p->pManFraig->pConst1 )
    {
        p->nSatProof++;
        return 1;
    }

    // solve under assumptions
    // A = 0; B = 1     OR     A = 0; B = 0 
clk = clock();
    pLits[0] = toLitCond( Fra_ObjSatNum(pOld), 1 );
    pLits[1] = toLitCond( Fra_ObjSatNum(pNew), pOld->fPhase ^ pNew->fPhase );
    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
        (sint64)nBTLimit, (sint64)0, 
        p->nBTLimitGlobal, p->nInsLimitGlobal );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
        assert( RetValue );
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        Fra_SavePattern( p );
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatFail += clock() - clk;
        // mark the node as the failed node
        pOld->fMarkB = 1;
        pNew->fMarkB = 1;
        p->nSatFailsReal++;
        return -1;
    }
/*
    // check BDD proof
    {
        int RetVal;
        PRT( "Sat", clock() - clk2 );
        clk2 = clock();
        RetVal = Fra_NodesAreEquivBdd( pOld, pNew );
//        printf( "%d ", RetVal );
        assert( RetVal );
        PRT( "Bdd", clock() - clk2 );
        printf( "\n" );
    }
*/
    // return SAT proof
    p->nSatProof++;
    return 1;
}
/**Function*************************************************************

  Synopsis    [Runs equivalence test for one node.]

  Description [Returns the fraiged node.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_NodeIsConst( Fra_Man_t * p, Aig_Obj_t * pNew )
{
    int pLits[2], RetValue1, RetValue, clk;

    // make sure the nodes are not complemented
    assert( !Aig_IsComplement(pNew) );
    assert( pNew != p->pManFraig->pConst1 );
    p->nSatCalls++;

    // make sure the solver is allocated and has enough variables
    if ( p->pSat == NULL )
    {
        p->pSat = sat_solver_new();
        p->nSatVars = 1;
        sat_solver_setnvars( p->pSat, 1000 );
    }

    // if the nodes do not have SAT variables, allocate them
    Fra_NodeAddToSolver( p, NULL, pNew );

    // prepare variable activity
    if ( p->pPars->fConeBias )
        Fra_SetActivityFactors( p, NULL, pNew ); 

    // solve under assumptions
clk = clock();
    pLits[0] = toLitCond( Fra_ObjSatNum(pNew), pNew->fPhase );
    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 1, 
        (sint64)p->pPars->nBTLimitMiter, (sint64)0, 
        p->nBTLimitGlobal, p->nInsLimitGlobal );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        pLits[0] = lit_neg( pLits[0] );
        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 1 );
        assert( RetValue );
        // continue solving the other implication
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        if ( p->pPatWords )
            Fra_SavePattern( p );
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatFail += clock() - clk;
        // mark the node as the failed node
        pNew->fMarkB = 1;
        p->nSatFailsReal++;
        return -1;
    }

    // return SAT proof
    p->nSatProof++;
    return 1;
}
/**Function*************************************************************

  Synopsis    [Detects constraints using structural methods.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Saig_ManDetectConstr( Aig_Man_t * p, int iOut, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvCons )
{
    Vec_Ptr_t * vSuper, * vSuper2 = NULL, * vUnique;
    Aig_Obj_t * pObj, * pObj2, * pFlop;
    int i, nFlops, RetValue;
    assert( iOut >= 0 && iOut < Saig_ManPoNum(p) );
    *pvOuts = NULL;
    *pvCons = NULL;
    pObj = Aig_ObjChild0( Aig_ManCo(p, iOut) );
    if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) )
    {
        printf( "The output is not an AND.\n" );
        return 0;
    }
    vSuper = Saig_DetectConstrCollectSuper( pObj );
    assert( Vec_PtrSize(vSuper) >= 2 );
    nFlops = 0;
    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
        nFlops += Saig_ObjIsLo( p, Aig_Regular(pObj) );
    if ( nFlops == 0 )
    {
        printf( "There is no flop outputs.\n" );
        Vec_PtrFree( vSuper );
        return 0;
    }
    // try flops 
    vUnique = NULL;
    Vec_PtrForEachEntry( Aig_Obj_t *, vSuper, pObj, i )
    {
        pFlop = Aig_Regular( pObj );
        if ( !Saig_ObjIsLo(p, pFlop) )
            continue;
        pFlop = Saig_ObjLoToLi( p, pFlop );
        pObj2 = Aig_ObjChild0( pFlop );
        if ( !Aig_IsComplement(pObj2) || !Aig_ObjIsNode(Aig_Regular(pObj2)) )
            continue;
        vSuper2 = Saig_DetectConstrCollectSuper( Aig_Regular(pObj2) );
        // every node in vSuper2 should appear in vSuper
        vUnique = Saig_ManDetectConstrCheckCont( vSuper, vSuper2 );
        if ( vUnique != NULL )
        {
///           assert( !Aig_IsComplement(pObj) );
 //           assert( Vec_PtrFind( vSuper2, pObj ) >= 0 );
            if ( Aig_IsComplement(pObj) )
            {
                printf( "Special flop input is complemented.\n" );
                Vec_PtrFreeP( &vUnique );
                Vec_PtrFree( vSuper2 );
                break;
            }
            if ( Vec_PtrFind( vSuper2, pObj ) == -1 )
            {
                printf( "Cannot find special flop about the inputs of OR gate.\n" );
                Vec_PtrFreeP( &vUnique );
                Vec_PtrFree( vSuper2 );
                break;
            }
            // remove the flop output
            Vec_PtrRemove( vSuper2, pObj );
            break;
        }
        Vec_PtrFree( vSuper2 );
    }
ABC_NAMESPACE_IMPL_START

/*
    Property holds iff it is const 0.
    Constraint holds iff it is const 0.

    The following structure is used for folding constraints:
    - the output of OR gate is 0 as long as all constraints hold
    - as soon as one constraint fail, the property output becomes 0 forever
      because the flop becomes 1 and it stays 1 forever


       property output

             |
          |-----|
          | and |
          |-----|
           |   |
           |  / \
           | /inv\
           | -----
       ____|   |_________________________
       |             |                  |
      / \       -----------             |   
     /   \      |   or    |             |
    /     \     -----------             |
   / logic \     |   |   |              |
  /  cone   \    |   |   |              |
 /___________\   |   |   |              |
                 |   | ------           |   
                 |   | |flop| (init=0)  |
                 |   | ------           |
                 |   |   |              |
                 |   |   |______________| 
                 |   |
                 c1  c2 
*/

////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Collects the supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Saig_DetectConstrCollectSuper_rec( Aig_Obj_t * pObj, Vec_Ptr_t * vSuper )
{
    // if the new node is complemented or a PI, another gate begins
    if ( Aig_IsComplement(pObj) || !Aig_ObjIsNode(pObj) )//|| (Aig_ObjRefs(pObj) > 1) )
    {
        Vec_PtrPushUnique( vSuper, Aig_Not(pObj) );
        return;
    }
    // go through the branches
    Saig_DetectConstrCollectSuper_rec( Aig_ObjChild0(pObj), vSuper );
    Saig_DetectConstrCollectSuper_rec( Aig_ObjChild1(pObj), vSuper );
}
Exemple #19
0
/**Function*************************************************************

  Synopsis    [Performs canonicization step.]

  Description [The argument nodes can be complemented.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Obj_t * Aig_And( Aig_Man_t * p, Aig_Obj_t * p0, Aig_Obj_t * p1 )
{
    Aig_Obj_t * pGhost, * pResult;
//    Aig_Obj_t * pFan0, * pFan1;
    // check trivial cases
    if ( p0 == p1 )
        return p0;
    if ( p0 == Aig_Not(p1) )
        return Aig_Not(p->pConst1);
    if ( Aig_Regular(p0) == p->pConst1 )
        return p0 == p->pConst1 ? p1 : Aig_Not(p->pConst1);
    if ( Aig_Regular(p1) == p->pConst1 )
        return p1 == p->pConst1 ? p0 : Aig_Not(p->pConst1);
    // check not so trivial cases
    if ( p->fAddStrash && (Aig_ObjIsNode(Aig_Regular(p0)) || Aig_ObjIsNode(Aig_Regular(p1))) )
    {   // http://fmv.jku.at/papers/BrummayerBiere-MEMICS06.pdf
        Aig_Obj_t * pFanA, * pFanB, * pFanC, * pFanD;
        pFanA = Aig_ObjChild0(Aig_Regular(p0));
        pFanB = Aig_ObjChild1(Aig_Regular(p0));
        pFanC = Aig_ObjChild0(Aig_Regular(p1));
        pFanD = Aig_ObjChild1(Aig_Regular(p1));
        if ( Aig_IsComplement(p0) )
        {
            if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) )
                return p1;
            if ( pFanB == p1 )
                return Aig_And( p, Aig_Not(pFanA), pFanB );
            if ( pFanA == p1 )
                return Aig_And( p, Aig_Not(pFanB), pFanA );
        }
        else
        {
            if ( pFanA == Aig_Not(p1) || pFanB == Aig_Not(p1) )
                return Aig_Not(p->pConst1);
            if ( pFanA == p1 || pFanB == p1 )
                return p0;
        }
        if ( Aig_IsComplement(p1) )
        {
            if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) )
                return p0;
            if ( pFanD == p0 )
                return Aig_And( p, Aig_Not(pFanC), pFanD );
            if ( pFanC == p0 )
                return Aig_And( p, Aig_Not(pFanD), pFanC );
        }
        else
        {
            if ( pFanC == Aig_Not(p0) || pFanD == Aig_Not(p0) )
                return Aig_Not(p->pConst1);
            if ( pFanC == p0 || pFanD == p0 )
                return p1;
        }
        if ( !Aig_IsComplement(p0) && !Aig_IsComplement(p1) )
        {
            if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) )
                return Aig_Not(p->pConst1);
            if ( pFanA == pFanC || pFanB == pFanC )
                return Aig_And( p, p0, pFanD );
            if ( pFanB == pFanC || pFanB == pFanD )
                return Aig_And( p, pFanA, p1 );
            if ( pFanA == pFanD || pFanB == pFanD )
                return Aig_And( p, p0, pFanC );
            if ( pFanA == pFanC || pFanA == pFanD )
                return Aig_And( p, pFanB, p1 );
        }
        else if ( Aig_IsComplement(p0) && !Aig_IsComplement(p1) )
        {
            if ( pFanA == Aig_Not(pFanC) || pFanA == Aig_Not(pFanD) || pFanB == Aig_Not(pFanC) || pFanB == Aig_Not(pFanD) )
                return p1;
            if ( pFanB == pFanC || pFanB == pFanD )
                return Aig_And( p, Aig_Not(pFanA), p1 );
            if ( pFanA == pFanC || pFanA == pFanD )
                return Aig_And( p, Aig_Not(pFanB), p1 );
        }
        else if ( !Aig_IsComplement(p0) && Aig_IsComplement(p1) )
        {
            if ( pFanC == Aig_Not(pFanA) || pFanC == Aig_Not(pFanB) || pFanD == Aig_Not(pFanA) || pFanD == Aig_Not(pFanB) )
                return p0;
            if ( pFanD == pFanA || pFanD == pFanB )
                return Aig_And( p, Aig_Not(pFanC), p0 );
            if ( pFanC == pFanA || pFanC == pFanB )
                return Aig_And( p, Aig_Not(pFanD), p0 );
        }
        else // if ( Aig_IsComplement(p0) && Aig_IsComplement(p1) )
        {
            if ( pFanA == pFanD && pFanB == Aig_Not(pFanC) )
                return Aig_Not(pFanA);
            if ( pFanB == pFanC && pFanA == Aig_Not(pFanD) )
                return Aig_Not(pFanB);
            if ( pFanA == pFanC && pFanB == Aig_Not(pFanD) )
                return Aig_Not(pFanA);
            if ( pFanB == pFanD && pFanA == Aig_Not(pFanC) )
                return Aig_Not(pFanB);
        }
    }
    // check if it can be an EXOR gate
//    if ( Aig_ObjIsExorType( p0, p1, &pFan0, &pFan1 ) )
//        return Aig_Exor( p, pFan0, pFan1 );
    pGhost = Aig_ObjCreateGhost( p, p0, p1, AIG_OBJ_AND );
    pResult = Aig_CanonPair_rec( p, pGhost );
    return pResult;
}
Exemple #20
0
/**Function*************************************************************

  Synopsis    [Constrains two nodes to be equivalent in the SAT solver.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ssw_NodesAreConstrained( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
{
    int pLits[2], RetValue, fComplNew;
    Aig_Obj_t * pTemp;

    // sanity checks
    assert( Aig_Regular(pOld) != Aig_Regular(pNew) );
    assert( p->pPars->fConstrs || Aig_ObjPhaseReal(pOld) == Aig_ObjPhaseReal(pNew) );

    // move constant to the old node
    if ( Aig_Regular(pNew) == Aig_ManConst1(p->pFrames) )
    {
        assert( Aig_Regular(pOld) != Aig_ManConst1(p->pFrames) );
        pTemp = pOld;
        pOld  = pNew;
        pNew  = pTemp;
    }

    // move complement to the new node
    if ( Aig_IsComplement(pOld) )
    {
        pOld = Aig_Regular(pOld);
        pNew = Aig_Not(pNew);
    }
    assert( p->pMSat != NULL );

    // if the nodes do not have SAT variables, allocate them
    Ssw_CnfNodeAddToSolver( p->pMSat, pOld );
    Ssw_CnfNodeAddToSolver( p->pMSat, Aig_Regular(pNew) );

    // transform the new node
    fComplNew = Aig_IsComplement( pNew );
    pNew = Aig_Regular( pNew );

    // consider the constant 1 case
    if ( pOld == Aig_ManConst1(p->pFrames) )
    {
        // add constraint A = 1  ---->  A
        pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew );
        if ( p->pPars->fPolarFlip )
        {
            if ( pNew->fPhase )  pLits[0] = lit_neg( pLits[0] );
        }
        RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 1 );
        assert( RetValue );
    }
    else
    {
        // add constraint A = B  ---->  (A v !B)(!A v B)

        // (A v !B)
        pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 );
        pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), !fComplNew );
        if ( p->pPars->fPolarFlip )
        {
            if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
            if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
        }
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
        assert( RetValue );

        // (!A v B)
        pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 );
        pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), fComplNew);
        if ( p->pPars->fPolarFlip )
        {
            if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
            if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
        }
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
        assert( RetValue );
    }
    return 1;
}
Exemple #21
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

/* 
    Speculating reduction in the sequential case leads to an interesting 
    situation when a counter-ex may not refine any classes. This happens
    for non-constant equivalence classes. In such cases the representative
    of the class (proved by simulation to be non-constant) may be reduced 
    to a constant during the speculative reduction. The fraig-representative 
    of this representative node is a constant node, even though this is a 
    non-constant class. Experiments have shown that this situation happens 
    very often at the beginning of the refinement iteration when there are 
    many spurious candidate equivalence classes (especially if heavy-duty 
    simulatation of BMC was node used at the beginning). As a result, the 
    SAT solver run may return a counter-ex that  distinguishes the given 
    representative node from the constant-1 node but this counter-ex
    does not distinguish the nodes in the non-costant class... This is why 
    there is no check of refinement after a counter-ex in the sequential case.
*/

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Reports the status of the miter.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Fra_FraigMiterStatus( Aig_Man_t * p )
{
    Aig_Obj_t * pObj, * pChild;
    int i, CountConst0 = 0, CountNonConst0 = 0, CountUndecided = 0;
    if ( p->pData )
        return 0;
    Aig_ManForEachPoSeq( p, pObj, i )
    {
        pChild = Aig_ObjChild0(pObj);
        // check if the output is constant 0
        if ( pChild == Aig_ManConst0(p) )
        {
            CountConst0++;
            continue;
        }
        // check if the output is constant 1
        if ( pChild == Aig_ManConst1(p) )
        {
            CountNonConst0++;
            continue;
        }
        // check if the output is a primary input
        if ( p->nRegs == 0 && Aig_ObjIsPi(Aig_Regular(pChild)) )
        {
            CountNonConst0++;
            continue;
        }
        // check if the output can be not constant 0
        if ( Aig_Regular(pChild)->fPhase != (unsigned)Aig_IsComplement(pChild) )
        {
            CountNonConst0++;
            continue;
        }
        CountUndecided++;
    }
Exemple #22
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Runs equivalence test for the two nodes.]

  Description [Both nodes should be regular and different from each other.]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Ssw_NodesAreEquiv( Ssw_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
{
    int nBTLimit = p->pPars->nBTLimit;
    int pLits[3], nLits, RetValue, RetValue1, clk;//, status;
    p->nSatCalls++;
    p->pMSat->nSolverCalls++;

    // sanity checks
    assert( !Aig_IsComplement(pOld) );
    assert( !Aig_IsComplement(pNew) );
    assert( pOld != pNew );
    assert( p->pMSat != NULL );

    // if the nodes do not have SAT variables, allocate them
    Ssw_CnfNodeAddToSolver( p->pMSat, pOld );
    Ssw_CnfNodeAddToSolver( p->pMSat, pNew );

    // solve under assumptions
    // A = 1; B = 0     OR     A = 1; B = 1 
    nLits = 2;
    pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 0 );
    pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase == pNew->fPhase );
    if ( p->iOutputLit > -1 )
        pLits[nLits++] = p->iOutputLit;
    if ( p->pPars->fPolarFlip )
    {
        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
    }
//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );

    if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
    {
        RetValue = sat_solver_simplify(p->pMSat->pSat);
        assert( RetValue != 0 );
    }

clk = clock();
    RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, 
        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        if ( nLits == 2 )
        {
            pLits[0] = lit_neg( pLits[0] );
            pLits[1] = lit_neg( pLits[1] );
            RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
            assert( RetValue );
/*
            if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
            {
                RetValue = sat_solver_simplify(p->pMSat->pSat);
                assert( RetValue != 0 );
            }
*/
        }
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatUndec += clock() - clk;
        p->nSatFailsReal++;
        return -1;
    }

    // if the old node was constant 0, we already know the answer
    if ( pOld == Aig_ManConst1(p->pFrames) )
    {
        p->nSatProof++;
        return 1;
    }

    // solve under assumptions
    // A = 0; B = 1     OR     A = 0; B = 0 
    nLits = 2;
    pLits[0] = toLitCond( Ssw_ObjSatNum(p->pMSat,pOld), 1 );
    pLits[1] = toLitCond( Ssw_ObjSatNum(p->pMSat,pNew), pOld->fPhase ^ pNew->fPhase );
    if ( p->iOutputLit > -1 )
        pLits[nLits++] = p->iOutputLit;
    if ( p->pPars->fPolarFlip )
    {
        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
    }

    if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
    {
        RetValue = sat_solver_simplify(p->pMSat->pSat);
        assert( RetValue != 0 );
    }

clk = clock();
    RetValue1 = sat_solver_solve( p->pMSat->pSat, pLits, pLits + nLits, 
        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        if ( nLits == 2 )
        {
            pLits[0] = lit_neg( pLits[0] );
            pLits[1] = lit_neg( pLits[1] );
            RetValue = sat_solver_addclause( p->pMSat->pSat, pLits, pLits + 2 );
            assert( RetValue );
/*
            if ( p->pMSat->pSat->qtail != p->pMSat->pSat->qhead )
            {
                RetValue = sat_solver_simplify(p->pMSat->pSat);
                assert( RetValue != 0 );
            }
*/
        }
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatUndec += clock() - clk;
        p->nSatFailsReal++;
        return -1;
    }
    // return SAT proof
    p->nSatProof++;
    return 1;
}
Exemple #23
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////


/**Function*************************************************************

  Synopsis    [Runs equivalence test for the two nodes.]

  Description [Both nodes should be regular and different from each other.]

  SideEffects []

  SeeAlso     []

***********************************************************************/
int Cgt_CheckImplication( Cgt_Man_t * p, Aig_Obj_t * pGate, Aig_Obj_t * pMiter )
{
    int nBTLimit = p->pPars->nConfMax;
    int pLits[2], RetValue, clk;
    p->nCalls++;

    // sanity checks
    assert( p->pSat && p->pCnf );
    assert( !Aig_IsComplement(pMiter) );
    assert( Aig_Regular(pGate) != pMiter );

    // solve under assumptions
    // G => !M -- true     G & M -- false
    pLits[0] = toLitCond( p->pCnf->pVarNums[Aig_Regular(pGate)->Id], Aig_IsComplement(pGate) );
    pLits[1] = toLitCond( p->pCnf->pVarNums[pMiter->Id], 0 );

    clk = clock();
    RetValue = sat_solver_solve( p->pSat, pLits, pLits + 2, (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
    p->timeSat += clock() - clk;
    if ( RetValue == l_False )
    {
        p->timeSatUnsat += clock() - clk;
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
        assert( RetValue );
        sat_solver_compress( p->pSat );
        p->nCallsUnsat++;
        return 1;
    }
    else if ( RetValue == l_True )
    {
        p->timeSatSat += clock() - clk;
        p->nCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
        p->timeSatUndec += clock() - clk;
        p->nCallsUndec++;
        return -1;
    }
    return -2;
}
/**Function*************************************************************

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Ref_ObjPrint( Aig_Obj_t * pObj )
{
    printf( "%d", pObj? Aig_Regular(pObj)->Id : -1 );
    if ( pObj )
        printf( "(%d) ", Aig_IsComplement(pObj) );
}
Exemple #25
0
ABC_NAMESPACE_IMPL_START


////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
///                     FUNCTION DEFINITIONS                         ///
////////////////////////////////////////////////////////////////////////

/**Function*************************************************************

  Synopsis    [Runs equivalence test for the two nodes.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
int Dch_NodesAreEquiv( Dch_Man_t * p, Aig_Obj_t * pOld, Aig_Obj_t * pNew )
{
    int nBTLimit = p->pPars->nBTLimit;
    int pLits[2], RetValue, RetValue1, status, clk;
    p->nSatCalls++;

    // sanity checks
    assert( !Aig_IsComplement(pNew) );
    assert( !Aig_IsComplement(pOld) );
    assert( pNew != pOld );

    p->nCallsSince++;  // experiment with this!!!
    
    // check if SAT solver needs recycling
    if ( p->pSat == NULL || 
        (p->pPars->nSatVarMax && 
         p->nSatVars > p->pPars->nSatVarMax && 
         p->nCallsSince > p->pPars->nCallsRecycle) )
        Dch_ManSatSolverRecycle( p );

    // if the nodes do not have SAT variables, allocate them
    Dch_CnfNodeAddToSolver( p, pOld );
    Dch_CnfNodeAddToSolver( p, pNew );

    // propage unit clauses
    if ( p->pSat->qtail != p->pSat->qhead )
    {
        status = sat_solver_simplify(p->pSat);
        assert( status != 0 );
        assert( p->pSat->qtail == p->pSat->qhead );
    }

    // solve under assumptions
    // A = 1; B = 0     OR     A = 1; B = 1 
    pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 0 );
    pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase == pNew->fPhase );
    if ( p->pPars->fPolarFlip )
    {
        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
    }
//Sat_SolverWriteDimacs( p->pSat, "temp.cnf", pLits, pLits + 2, 1 );
clk = clock();
    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
        assert( RetValue );
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatUndec += clock() - clk;
        p->nSatFailsReal++;
        return -1;
    }

    // if the old node was constant 0, we already know the answer
    if ( pOld == Aig_ManConst1(p->pAigFraig) )
    {
        p->nSatProof++;
        return 1;
    }

    // solve under assumptions
    // A = 0; B = 1     OR     A = 0; B = 0 
    pLits[0] = toLitCond( Dch_ObjSatNum(p,pOld), 1 );
    pLits[1] = toLitCond( Dch_ObjSatNum(p,pNew), pOld->fPhase ^ pNew->fPhase );
    if ( p->pPars->fPolarFlip )
    {
        if ( pOld->fPhase )  pLits[0] = lit_neg( pLits[0] );
        if ( pNew->fPhase )  pLits[1] = lit_neg( pLits[1] );
    }
clk = clock();
    RetValue1 = sat_solver_solve( p->pSat, pLits, pLits + 2, 
        (ABC_INT64_T)nBTLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
p->timeSat += clock() - clk;
    if ( RetValue1 == l_False )
    {
p->timeSatUnsat += clock() - clk;
        pLits[0] = lit_neg( pLits[0] );
        pLits[1] = lit_neg( pLits[1] );
        RetValue = sat_solver_addclause( p->pSat, pLits, pLits + 2 );
        assert( RetValue );
        p->nSatCallsUnsat++;
    }
    else if ( RetValue1 == l_True )
    {
p->timeSatSat += clock() - clk;
        p->nSatCallsSat++;
        return 0;
    }
    else // if ( RetValue1 == l_Undef )
    {
p->timeSatUndec += clock() - clk;
        p->nSatFailsReal++;
        return -1;
    }
    // return SAT proof
    p->nSatProof++;
    return 1;
}