| /**CFile**************************************************************** |
| |
| FileName [sbd.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [SAT-based optimization using internal don't-cares.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: sbd.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "sbdInt.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Constructs SAT solver for the window.] |
| |
| Description [The window for the pivot node (Pivot) is represented as |
| a DFS ordered array of objects (vWinObjs) whose indexed in the array |
| (which will be used as SAT variables) are given in array vObj2Var. |
| The TFO nodes are listed as the last ones in vWinObjs. The root nodes |
| are labeled with Abc_LitIsCompl() in vTfo and also given in vRoots. |
| If fQbf is 1, returns the instance meant for QBF solving. It is using |
| the last variable (LastVar) as the placeholder for the second copy |
| of the pivot node.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| sat_solver * Sbd_ManSatSolver( sat_solver * pSat, Gia_Man_t * p, Vec_Int_t * vMirrors, |
| int Pivot, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, |
| Vec_Int_t * vTfo, Vec_Int_t * vRoots, int fQbf ) |
| { |
| Gia_Obj_t * pObj; |
| int i, iLit = 1, iObj, Fan0, Fan1, Lit0m, Lit1m, Node, fCompl0, fCompl1, RetValue; |
| int TfoStart = Vec_IntSize(vWinObjs) - Vec_IntSize(vTfo); |
| int PivotVar = Vec_IntEntry(vObj2Var, Pivot); |
| int LastVar = Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo) + Vec_IntSize(vRoots); |
| //Vec_IntPrint( vWinObjs ); |
| //Vec_IntPrint( vTfo ); |
| //Vec_IntPrint( vRoots ); |
| // create SAT solver |
| if ( pSat == NULL ) |
| pSat = sat_solver_new(); |
| else |
| sat_solver_restart( pSat ); |
| sat_solver_setnvars( pSat, Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo) + Vec_IntSize(vRoots) + SBD_FVAR_MAX ); |
| // create constant 0 clause |
| sat_solver_addclause( pSat, &iLit, &iLit + 1 ); |
| // add clauses for all nodes |
| Vec_IntForEachEntryStart( vWinObjs, iObj, i, 1 ) |
| { |
| pObj = Gia_ManObj( p, iObj ); |
| if ( Gia_ObjIsCi(pObj) ) |
| continue; |
| assert( Gia_ObjIsAnd(pObj) ); |
| assert( Vec_IntEntry( vMirrors, iObj ) < 0 ); |
| Node = Vec_IntEntry( vObj2Var, iObj ); |
| Lit0m = Vec_IntEntry( vMirrors, Gia_ObjFaninId0(pObj, iObj) ); |
| Lit1m = Vec_IntEntry( vMirrors, Gia_ObjFaninId1(pObj, iObj) ); |
| Fan0 = Lit0m >= 0 ? Abc_Lit2Var(Lit0m) : Gia_ObjFaninId0(pObj, iObj); |
| Fan1 = Lit1m >= 0 ? Abc_Lit2Var(Lit1m) : Gia_ObjFaninId1(pObj, iObj); |
| Fan0 = Vec_IntEntry( vObj2Var, Fan0 ); |
| Fan1 = Vec_IntEntry( vObj2Var, Fan1 ); |
| fCompl0 = Gia_ObjFaninC0(pObj) ^ (Lit0m >= 0 && Abc_LitIsCompl(Lit0m)); |
| fCompl1 = Gia_ObjFaninC1(pObj) ^ (Lit1m >= 0 && Abc_LitIsCompl(Lit1m)); |
| if ( Gia_ObjIsXor(pObj) ) |
| sat_solver_add_xor( pSat, Node, Fan0, Fan1, fCompl0 ^ fCompl1 ); |
| else |
| sat_solver_add_and( pSat, Node, Fan0, Fan1, fCompl0, fCompl1, 0 ); |
| } |
| // add second clauses for the TFO |
| Vec_IntForEachEntryStart( vWinObjs, iObj, i, TfoStart ) |
| { |
| pObj = Gia_ManObj( p, iObj ); |
| assert( Gia_ObjIsAnd(pObj) ); |
| assert( Vec_IntEntry( vMirrors, iObj ) < 0 ); |
| Node = Vec_IntEntry( vObj2Var, iObj ) + Vec_IntSize(vTfo); |
| Lit0m = Vec_IntEntry( vMirrors, Gia_ObjFaninId0(pObj, iObj) ); |
| Lit1m = Vec_IntEntry( vMirrors, Gia_ObjFaninId1(pObj, iObj) ); |
| Fan0 = Lit0m >= 0 ? Abc_Lit2Var(Lit0m) : Gia_ObjFaninId0(pObj, iObj); |
| Fan1 = Lit1m >= 0 ? Abc_Lit2Var(Lit1m) : Gia_ObjFaninId1(pObj, iObj); |
| Fan0 = Vec_IntEntry( vObj2Var, Fan0 ); |
| Fan1 = Vec_IntEntry( vObj2Var, Fan1 ); |
| Fan0 = Fan0 < TfoStart ? Fan0 : Fan0 + Vec_IntSize(vTfo); |
| Fan1 = Fan1 < TfoStart ? Fan1 : Fan1 + Vec_IntSize(vTfo); |
| if ( fQbf ) |
| { |
| Fan0 = Fan0 == PivotVar ? LastVar : Fan0; |
| Fan1 = Fan1 == PivotVar ? LastVar : Fan1; |
| } |
| fCompl0 = Gia_ObjFaninC0(pObj) ^ (!fQbf && Fan0 == PivotVar) ^ (Lit0m >= 0 && Abc_LitIsCompl(Lit0m)); |
| fCompl1 = Gia_ObjFaninC1(pObj) ^ (!fQbf && Fan1 == PivotVar) ^ (Lit1m >= 0 && Abc_LitIsCompl(Lit1m)); |
| if ( Gia_ObjIsXor(pObj) ) |
| sat_solver_add_xor( pSat, Node, Fan0, Fan1, fCompl0 ^ fCompl1 ); |
| else |
| sat_solver_add_and( pSat, Node, Fan0, Fan1, fCompl0, fCompl1, 0 ); |
| } |
| if ( Vec_IntSize(vRoots) > 0 ) |
| { |
| // create XOR clauses for the roots |
| int nVars = Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo); |
| Vec_Int_t * vFaninVars = Vec_IntAlloc( Vec_IntSize(vRoots) ); |
| Vec_IntForEachEntry( vRoots, iObj, i ) |
| { |
| assert( Vec_IntEntry( vMirrors, iObj ) < 0 ); |
| Node = Vec_IntEntry( vObj2Var, iObj ); |
| Vec_IntPush( vFaninVars, Abc_Var2Lit(nVars, 0) ); |
| sat_solver_add_xor( pSat, Node, Node + Vec_IntSize(vTfo), nVars++, 0 ); |
| } |
| // make OR clause for the last nRoots variables |
| RetValue = sat_solver_addclause( pSat, Vec_IntArray(vFaninVars), Vec_IntLimit(vFaninVars) ); |
| Vec_IntFree( vFaninVars ); |
| if ( RetValue == 0 ) |
| { |
| sat_solver_delete( pSat ); |
| return NULL; |
| } |
| assert( sat_solver_nvars(pSat) == nVars + SBD_FVAR_MAX ); |
| } |
| else if ( fQbf ) |
| { |
| int n, pLits[2]; |
| for ( n = 0; n < 2; n++ ) |
| { |
| pLits[0] = Abc_Var2Lit( PivotVar, n ); |
| pLits[1] = Abc_Var2Lit( LastVar, n ); |
| RetValue = sat_solver_addclause( pSat, pLits, pLits + 2 ); |
| assert( RetValue ); |
| } |
| } |
| // finalize |
| RetValue = sat_solver_simplify( pSat ); |
| if ( RetValue == 0 ) |
| { |
| sat_solver_delete( pSat ); |
| return NULL; |
| } |
| return pSat; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Solves one SAT problem.] |
| |
| Description [Computes node function for PivotVar with fanins in vDivSet |
| using don't-care represented in the SAT solver. Uses array vValues to |
| return the values of the first Vec_IntSize(vValues) SAT variables in case |
| the implementation of the node with the given fanins does not exist.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| word Sbd_ManSolve( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivSet, Vec_Int_t * vDivVars, Vec_Int_t * vDivValues, Vec_Int_t * vTemp ) |
| { |
| int nBTLimit = 0; |
| word uCube, uTruth = 0; |
| int status, i, iVar, nFinal, * pFinal, pLits[2], nIter = 0; |
| assert( FreeVar < sat_solver_nvars(pSat) ); |
| assert( Vec_IntSize(vDivVars) == Vec_IntSize(vDivValues) ); |
| pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1 |
| pLits[1] = Abc_Var2Lit( FreeVar, 0 ); // iNewLit |
| while ( 1 ) |
| { |
| // find onset minterm |
| status = sat_solver_solve( pSat, pLits, pLits + 2, nBTLimit, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| return SBD_SAT_UNDEC; |
| if ( status == l_False ) |
| return uTruth; |
| assert( status == l_True ); |
| // remember variable values |
| Vec_IntForEachEntry( vDivVars, iVar, i ) |
| Vec_IntWriteEntry( vDivValues, i, 2*sat_solver_var_value(pSat, iVar) ); |
| // collect divisor literals |
| Vec_IntClear( vTemp ); |
| Vec_IntPush( vTemp, Abc_LitNot(pLits[0]) ); // F = 0 |
| Vec_IntForEachEntry( vDivSet, iVar, i ) |
| Vec_IntPush( vTemp, sat_solver_var_literal(pSat, iVar) ); |
| // check against offset |
| status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp), nBTLimit, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| return SBD_SAT_UNDEC; |
| if ( status == l_True ) |
| break; |
| assert( status == l_False ); |
| // compute cube and add clause |
| nFinal = sat_solver_final( pSat, &pFinal ); |
| uCube = ~(word)0; |
| Vec_IntClear( vTemp ); |
| Vec_IntPush( vTemp, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) |
| for ( i = 0; i < nFinal; i++ ) |
| { |
| if ( pFinal[i] == pLits[0] ) |
| continue; |
| Vec_IntPush( vTemp, pFinal[i] ); |
| iVar = Vec_IntFind( vDivSet, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 ); |
| uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar]; |
| } |
| uTruth |= uCube; |
| status = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp) ); |
| assert( status ); |
| nIter++; |
| } |
| assert( status == l_True ); |
| // store the counter-example |
| Vec_IntForEachEntry( vDivVars, iVar, i ) |
| Vec_IntAddToEntry( vDivValues, i, sat_solver_var_value(pSat, iVar) ); |
| |
| for ( i = 0; i < Vec_IntSize(vDivValues); i++ ) |
| Vec_IntAddToEntry( vDivValues, i, 0xC ); |
| /* |
| // reduce the counter example |
| for ( n = 0; n < 2; n++ ) |
| { |
| Vec_IntClear( vTemp ); |
| Vec_IntPush( vTemp, Abc_Var2Lit(PivotVar, n) ); // n = 0 => F = 1 (expanding offset against onset) |
| for ( i = 0; i < Vec_IntSize(vValues); i++ ) |
| Vec_IntPush( vTemp, Abc_Var2Lit(i, !((Vec_IntEntry(vValues, i) >> n) & 1)) ); |
| status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp), nBTLimit, 0, 0, 0 ); |
| assert( status == l_False ); |
| // compute cube and add clause |
| nFinal = sat_solver_final( pSat, &pFinal ); |
| for ( i = 0; i < nFinal; i++ ) |
| if ( Abc_Lit2Var(pFinal[i]) != PivotVar ) |
| Vec_IntAddToEntry( vValues, Abc_Lit2Var(pFinal[i]), 1 << (n+2) ); |
| } |
| */ |
| return SBD_SAT_SAT; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Sbd_ManSolve2( sat_solver * pSat, int PivotVar, int FreeVar, Vec_Int_t * vDivVars, Vec_Int_t * vDivValues, Vec_Int_t * vTemp, Vec_Int_t * vSop ) |
| { |
| int nBTLimit = 0; |
| int status, i, iVar, nFinal, * pFinal, pLits[2], nIter = 0; |
| assert( FreeVar < sat_solver_nvars(pSat) ); |
| assert( Vec_IntSize(vDivVars) == Vec_IntSize(vDivValues) ); |
| pLits[0] = Abc_Var2Lit( PivotVar, 0 ); // F = 1 |
| pLits[1] = Abc_Var2Lit( FreeVar, 0 ); // iNewLit |
| Vec_IntClear( vSop ); |
| while ( 1 ) |
| { |
| // find onset minterm |
| status = sat_solver_solve( pSat, pLits, pLits + 2, nBTLimit, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| return 0; |
| if ( status == l_False ) |
| return 1; |
| assert( status == l_True ); |
| // remember variable values |
| //for ( i = 0; i < Vec_IntSize(vValues); i++ ) |
| // Vec_IntWriteEntry( vValues, i, 2*sat_solver_var_value(pSat, i) ); |
| // collect divisor literals |
| Vec_IntClear( vTemp ); |
| Vec_IntPush( vTemp, Abc_LitNot(pLits[0]) ); // F = 0 |
| //Vec_IntForEachEntry( vDivSet, iVar, i ) |
| Vec_IntForEachEntry( vDivVars, iVar, i ) |
| Vec_IntPush( vTemp, sat_solver_var_literal(pSat, iVar) ); |
| // check against offset |
| status = sat_solver_solve( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp), nBTLimit, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| return 0; |
| if ( status == l_True ) |
| break; |
| assert( status == l_False ); |
| // compute cube and add clause |
| nFinal = sat_solver_final( pSat, &pFinal ); |
| Vec_IntClear( vTemp ); |
| Vec_IntPush( vTemp, Abc_LitNot(pLits[1]) ); // NOT(iNewLit) |
| for ( i = 0; i < nFinal; i++ ) |
| { |
| if ( pFinal[i] == pLits[0] ) |
| continue; |
| Vec_IntPush( vTemp, pFinal[i] ); |
| iVar = Vec_IntFind( vDivVars, Abc_Lit2Var(pFinal[i]) ); assert( iVar >= 0 ); |
| //uCube &= Abc_LitIsCompl(pFinal[i]) ? s_Truths6[iVar] : ~s_Truths6[iVar]; |
| Vec_IntPush( vSop, Abc_Var2Lit( iVar, !Abc_LitIsCompl(pFinal[i]) ) ); |
| } |
| //uTruth |= uCube; |
| Vec_IntPush( vSop, -1 ); |
| status = sat_solver_addclause( pSat, Vec_IntArray(vTemp), Vec_IntArray(vTemp) + Vec_IntSize(vTemp) ); |
| assert( status ); |
| nIter++; |
| } |
| assert( status == l_True ); |
| // store the counter-example |
| //for ( i = 0; i < Vec_IntSize(vValues); i++ ) |
| // Vec_IntAddToEntry( vValues, i, sat_solver_var_value(pSat, i) ); |
| return 0; |
| } |
| |
| word Sbd_ManSolverSupp( Vec_Int_t * vSop, int * pInds, int * pnVars ) |
| { |
| word Supp = 0; |
| int i, Entry, nVars = 0; |
| Vec_IntForEachEntry( vSop, Entry, i ) |
| { |
| if ( Entry == -1 ) |
| continue; |
| assert( Abc_Lit2Var(Entry) < 64 ); |
| if ( (Supp >> Abc_Lit2Var(Entry)) & 1 ) |
| continue; |
| pInds[Abc_Lit2Var(Entry)] = nVars++; |
| Supp |= (word)1 << Abc_Lit2Var(Entry); |
| } |
| *pnVars = nVars; |
| return Supp; |
| } |
| void Sbd_ManSolverPrint( Vec_Int_t * vSop ) |
| { |
| int v, i, Entry, nVars, pInds[64]; |
| word Supp = Sbd_ManSolverSupp( vSop, pInds, &nVars ); |
| char Cube[65] = {'\0'}; |
| assert( Cube[nVars] == '\0' ); |
| for ( v = 0; v < nVars; v++ ) |
| Cube[v] = '-'; |
| Vec_IntForEachEntry( vSop, Entry, i ) |
| { |
| if ( Entry == -1 ) |
| { |
| printf( "%s\n", Cube ); |
| for ( v = 0; v < nVars; v++ ) |
| Cube[v] = '-'; |
| continue; |
| } |
| Cube[pInds[Abc_Lit2Var(Entry)]] = '1' - (char)Abc_LitIsCompl(Entry); |
| } |
| Supp = 0; |
| } |
| void Sbd_ManSolveSelect( Gia_Man_t * p, Vec_Int_t * vMirrors, int Pivot, Vec_Int_t * vDivVars, Vec_Int_t * vDivValues, Vec_Int_t * vWinObjs, Vec_Int_t * vObj2Var, Vec_Int_t * vTfo, Vec_Int_t * vRoots ) |
| { |
| Vec_Int_t * vSop = Vec_IntAlloc( 100 ); |
| Vec_Int_t * vTemp = Vec_IntAlloc( 100 ); |
| sat_solver * pSat = Sbd_ManSatSolver( NULL, p, vMirrors, Pivot, vWinObjs, vObj2Var, vTfo, vRoots, 0 ); |
| int PivotVar = Vec_IntEntry(vObj2Var, Pivot); |
| int FreeVar = Vec_IntSize(vWinObjs) + Vec_IntSize(vTfo) + Vec_IntSize(vRoots); |
| int Status = Sbd_ManSolve2( pSat, PivotVar, FreeVar, vDivVars, vDivValues, vTemp, vSop ); |
| printf( "Pivot = %4d. Divs = %4d. ", Pivot, Vec_IntSize(vDivVars) ); |
| if ( Status == 0 ) |
| printf( "UNSAT.\n" ); |
| else |
| { |
| int nVars, pInds[64]; |
| word Supp = Sbd_ManSolverSupp( vSop, pInds, &nVars ); |
| //Sbd_ManSolverPrint( vSop ); |
| printf( "SAT with %d vars and %d cubes.\n", nVars, Vec_IntCountEntry(vSop, -1) ); |
| Supp = 0; |
| } |
| Vec_IntFree( vTemp ); |
| Vec_IntFree( vSop ); |
| sat_solver_delete( pSat ); |
| } |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns a bunch of positive/negative random care minterms.] |
| |
| Description [Returns 0/1 if the functions is const 0/1.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| static void sat_solver_random_polarity(sat_solver* s) |
| { |
| int i, k; |
| for ( i = 0; i < s->size; i += 64 ) |
| { |
| word Polar = Gia_ManRandomW(0); |
| for ( k = 0; k < 64 && (i << 6) + k < s->size; k++ ) |
| s->polarity[(i << 6) + k] = Abc_TtGetBit(&Polar, k); |
| } |
| } |
| int Sbd_ManCollectConstants( sat_solver * pSat, int nCareMints[2], int PivotVar, word * pVarSims[], Vec_Int_t * vInds ) |
| { |
| int nBTLimit = 0; |
| int i, Ind; |
| assert( Vec_IntSize(vInds) == nCareMints[0] + nCareMints[1] ); |
| Vec_IntForEachEntry( vInds, Ind, i ) |
| { |
| int fOffSet = (int)(i < nCareMints[0]); |
| int status, k, iLit = Abc_Var2Lit( PivotVar, fOffSet ); |
| sat_solver_random_polarity( pSat ); |
| status = sat_solver_solve( pSat, &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| return -2; |
| if ( status == l_False ) |
| return fOffSet; |
| for ( k = 0; k <= PivotVar; k++ ) |
| if ( Abc_TtGetBit(pVarSims[k], Ind) != sat_solver_var_value(pSat, k) ) |
| Abc_TtXorBit(pVarSims[k], Ind); |
| } |
| return -1; |
| } |
| |
| int Sbd_ManCollectConstantsNew( sat_solver * pSat, Vec_Int_t * vDivVars, int nConsts, int PivotVar, word * pOnset, word * pOffset ) |
| { |
| int nBTLimit = 0; |
| int n, i, k, status, iLit, iVar; |
| word * pPats[2] = {pOnset, pOffset}; |
| assert( Vec_IntSize(vDivVars) < 64 ); |
| for ( n = 0; n < 2; n++ ) |
| for ( i = 0; i < nConsts; i++ ) |
| { |
| sat_solver_random_polarity( pSat ); |
| iLit = Abc_Var2Lit( PivotVar, n ); |
| status = sat_solver_solve( pSat, &iLit, &iLit + 1, nBTLimit, 0, 0, 0 ); |
| if ( status == l_Undef ) |
| return -2; |
| if ( status == l_False ) |
| return n; |
| pPats[n][i] = ((word)!n) << Vec_IntSize(vDivVars); |
| Vec_IntForEachEntry( vDivVars, iVar, k ) |
| if ( sat_solver_var_value(pSat, iVar) ) |
| Abc_TtXorBit(&pPats[n][i], k); |
| } |
| return -1; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |