/**CFile**************************************************************** FileName [giaSatEdge.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Scalable AIG package.] Synopsis [] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - June 20, 2005.] Revision [$Id: giaSatEdge.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] ***********************************************************************/ #include "gia.h" #include "misc/tim/tim.h" #include "sat/bsat/satStore.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Seg_Man_t_ Seg_Man_t; struct Seg_Man_t_ { sat_solver * pSat; // SAT solver //Vec_Int_t * vCardVars; // candinality variables int nVars; // max vars (edge num) int LogN; // base-2 log of max vars int Power2; // power-2 of LogN int FirstVar; // first variable to be used // parameters int nBTLimit; // conflicts int DelayMax; // external delay int nEdges; // the number of edges int fDelay; // delay mode int fReverse; // reverse windowing int fVerbose; // verbose // window Gia_Man_t * pGia; Vec_Int_t * vPolars; // polarity Vec_Int_t * vToSkip; // edges to skip Vec_Int_t * vEdges; // edges as fanin/fanout pairs Vec_Int_t * vFirsts; // first SAT variable Vec_Int_t * vNvars; // number of SAT variables Vec_Int_t * vLits; // literals int * pLevels; // levels // statistics abctime timeStart; }; extern sat_solver * Sbm_AddCardinSolver( int LogN, Vec_Int_t ** pvVars ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Count the number of edges between internal nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Seg_ManCountIntEdges( Gia_Man_t * p, Vec_Int_t * vPolars, Vec_Int_t * vToSkip, int nFanouts ) { int i, iLut, iFanin; Vec_Int_t * vEdges = Vec_IntAlloc( 1000 ); assert( Gia_ManHasMapping(p) ); Vec_IntClear( vPolars ); Vec_IntClear( vToSkip ); if ( nFanouts ) Gia_ManSetLutRefs( p ); Gia_ManForEachLut( p, iLut ) Gia_LutForEachFanin( p, iLut, iFanin, i ) if ( Gia_ObjIsAnd(Gia_ManObj(p, iFanin)) ) { if ( p->vEdge1 && Gia_ObjCheckEdge(p, iFanin, iLut) ) Vec_IntPush( vPolars, Vec_IntSize(vEdges)/2 ); if ( nFanouts && Gia_ObjLutRefNumId(p, iFanin) >= nFanouts ) Vec_IntPush( vToSkip, Vec_IntSize(vEdges)/2 ); Vec_IntPushTwo( vEdges, iFanin, iLut ); } if ( nFanouts ) ABC_FREE( p->pLutRefs ); return vEdges; } Vec_Wec_t * Seg_ManCollectObjEdges( Vec_Int_t * vEdges, int nObjs ) { int iFanin, iObj, i; Vec_Wec_t * vRes = Vec_WecStart( nObjs ); Vec_IntForEachEntryDouble( vEdges, iFanin, iObj, i ) { Vec_WecPush( vRes, iFanin, i/2 ); Vec_WecPush( vRes, iObj, i/2 ); } return vRes; } int Seg_ManCountIntLevels( Seg_Man_t * p, int iStartVar ) { Gia_Obj_t * pObj; int iLut, nVars; Vec_IntFill( p->vFirsts, Gia_ManObjNum(p->pGia), -1 ); Vec_IntFill( p->vNvars, Gia_ManObjNum(p->pGia), 0 ); ABC_FREE( p->pLevels ); if ( p->pGia->pManTime ) { p->DelayMax = Gia_ManLutLevelWithBoxes( p->pGia ); p->pLevels = Vec_IntReleaseArray( p->pGia->vLevels ); Vec_IntFreeP( &p->pGia->vLevels ); } else p->DelayMax = Gia_ManLutLevel( p->pGia, &p->pLevels ); Gia_ManForEachObj1( p->pGia, pObj, iLut ) { if ( Gia_ObjIsCo(pObj) ) continue; if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsLut(p->pGia, iLut) ) continue; assert( Gia_ObjIsCi(pObj) || Gia_ObjIsLut(p->pGia, iLut) ); Vec_IntWriteEntry( p->vFirsts, iLut, iStartVar ); //assert( p->pLevels[iLut] > 0 ); nVars = p->pLevels[iLut] < 2 ? 0 : p->pLevels[iLut]; Vec_IntWriteEntry( p->vNvars, iLut, nVars ); iStartVar += nVars; } return iStartVar; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Seg_Man_t * Seg_ManAlloc( Gia_Man_t * pGia, int nFanouts ) { int nVarsAll; Seg_Man_t * p = ABC_CALLOC( Seg_Man_t, 1 ); p->vPolars = Vec_IntAlloc( 1000 ); p->vToSkip = Vec_IntAlloc( 1000 ); p->vEdges = Seg_ManCountIntEdges( pGia, p->vPolars, p->vToSkip, nFanouts ); p->nVars = Vec_IntSize(p->vEdges)/2; p->LogN = Abc_Base2Log(p->nVars); p->Power2 = 1 << p->LogN; //p->pSat = Sbm_AddCardinSolver( p->LogN, &p->vCardVars ); p->pSat = sat_solver_new(); sat_solver_setnvars( p->pSat, p->nVars ); p->FirstVar = sat_solver_nvars( p->pSat ); sat_solver_bookmark( p->pSat ); p->pGia = pGia; // internal p->vFirsts = Vec_IntAlloc( 0 ); p->vNvars = Vec_IntAlloc( 0 ); p->vLits = Vec_IntAlloc( 0 ); nVarsAll = Seg_ManCountIntLevels( p, p->FirstVar ); sat_solver_setnvars( p->pSat, nVarsAll ); // other Gia_ManFillValue( pGia ); return p; } void Seg_ManClean( Seg_Man_t * p ) { p->timeStart = Abc_Clock(); sat_solver_rollback( p->pSat ); sat_solver_bookmark( p->pSat ); // internal Vec_IntClear( p->vEdges ); Vec_IntClear( p->vFirsts ); Vec_IntClear( p->vNvars ); Vec_IntClear( p->vLits ); Vec_IntClear( p->vPolars ); Vec_IntClear( p->vToSkip ); // other Gia_ManFillValue( p->pGia ); } void Seg_ManStop( Seg_Man_t * p ) { sat_solver_delete( p->pSat ); //Vec_IntFree( p->vCardVars ); // internal Vec_IntFree( p->vEdges ); Vec_IntFree( p->vFirsts ); Vec_IntFree( p->vNvars ); Vec_IntFree( p->vLits ); Vec_IntFree( p->vPolars ); Vec_IntFree( p->vToSkip ); ABC_FREE( p->pLevels ); // other ABC_FREE( p ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Seg_ManCreateCnf( Seg_Man_t * p, int fTwo, int fVerbose ) { Tim_Man_t * pTim = (Tim_Man_t *)p->pGia->pManTime; Gia_Obj_t * pObj; Vec_Wec_t * vObjEdges; Vec_Int_t * vLevel; int iLut, iFanin, iFirst; int pLits[3], Count = 0; int i, k, nVars, Edge, value; abctime clk = Abc_Clock(); // edge delay constraints int nConstr = sat_solver_nclauses(p->pSat); Gia_ManForEachObj( p->pGia, pObj, iLut ) { int iFirstLut = Vec_IntEntry( p->vFirsts, iLut ); int nVarsLut = Vec_IntEntry( p->vNvars, iLut ); if ( pTim && Gia_ObjIsCi(pObj) ) { int iBox = Tim_ManBoxForCi( pTim, Gia_ObjCioId(pObj) ); if ( nVarsLut > 0 && iBox >= 0 ) { int iCiId = Tim_ManBoxOutputFirst( pTim, iBox ); if ( iCiId == Gia_ObjCioId(pObj) ) // first input { int nIns = Tim_ManBoxInputNum( pTim, iBox ); int iIn0 = Tim_ManBoxInputFirst( pTim, iBox ); for ( i = 0; i < nIns-1; i++ ) // skip carry-in pin { Gia_Obj_t * pOut = Gia_ManCo( p->pGia, iIn0+i ); int iDriverId = Gia_ObjFaninId0p( p->pGia, pOut ); int AddOn; iFirst = Vec_IntEntry( p->vFirsts, iDriverId ); nVars = Vec_IntEntry( p->vNvars, iDriverId ); assert( nVars < nVarsLut ); AddOn = (int)(nVars < nVarsLut); for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut+k+AddOn, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } } else // intermediate input { Gia_Obj_t * pIn = Gia_ManCi( p->pGia, iCiId ); int iObjId = Gia_ObjId( p->pGia, pIn ); iFirst = Vec_IntEntry( p->vFirsts, iObjId ); nVars = Vec_IntEntry( p->vNvars, iObjId ); if ( nVars > 0 ) { for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut+k, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } } } continue; } if ( !Gia_ObjIsLut(p->pGia, iLut) ) continue; Gia_LutForEachFanin( p->pGia, iLut, iFanin, i ) if ( pTim && Gia_ObjIsCi(Gia_ManObj(p->pGia, iFanin)) ) { iFirst = Vec_IntEntry( p->vFirsts, iFanin ); nVars = Vec_IntEntry( p->vNvars, iFanin ); assert( nVars <= nVarsLut ); if ( nVars > 0 ) { for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut+k, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } } else if ( Gia_ObjIsAnd(Gia_ManObj(p->pGia, iFanin)) ) { iFirst = Vec_IntEntry( p->vFirsts, iFanin ); nVars = Vec_IntEntry( p->vNvars, iFanin ); assert( nVars != 1 && nVars < nVarsLut ); // add initial if ( nVars == 0 ) { pLits[0] = Abc_Var2Lit( Count, 1 ); pLits[1] = Abc_Var2Lit( iFirstLut, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); pLits[0] = Abc_Var2Lit( Count, 0 ); pLits[1] = Abc_Var2Lit( iFirstLut+1, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } // add others for ( k = 0; k < nVars; k++ ) { pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( Count, 1 ); pLits[2] = Abc_Var2Lit( iFirstLut+k, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); assert( value ); pLits[0] = Abc_Var2Lit( iFirst+k, 1 ); pLits[1] = Abc_Var2Lit( Count, 0 ); pLits[2] = Abc_Var2Lit( iFirstLut+k+1, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); assert( value ); } Count++; } } assert( Count == p->nVars ); if ( fVerbose ) printf( "Delay constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr ); nConstr = sat_solver_nclauses(p->pSat); /* // delay relationship constraints Vec_IntForEachEntryTwo( p->vFirsts, p->vNvars, iFirst, nVars, iLut ) { if ( nVars < 2 ) continue; for ( i = 1; i < nVars; i++ ) { pLits[0] = Abc_Var2Lit( iFirst + i - 1, 1 ); pLits[1] = Abc_Var2Lit( iFirst + i, 0 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } */ // edge compatibility constraint vObjEdges = Seg_ManCollectObjEdges( p->vEdges, Gia_ManObjNum(p->pGia) ); Vec_WecForEachLevel( vObjEdges, vLevel, i ) { int v1, v2, v3, Var1, Var2, Var3; if ( (!fTwo && Vec_IntSize(vLevel) >= 2) || (fTwo && Vec_IntSize(vLevel) > 10) ) { Vec_IntForEachEntry( vLevel, Var1, v1 ) Vec_IntForEachEntryStart( vLevel, Var2, v2, v1 + 1 ) { pLits[0] = Abc_Var2Lit( Var1, 1 ); pLits[1] = Abc_Var2Lit( Var2, 1 ); value = sat_solver_addclause( p->pSat, pLits, pLits+2 ); assert( value ); } } else if ( fTwo && Vec_IntSize(vLevel) >= 3 ) { Vec_IntForEachEntry( vLevel, Var1, v1 ) Vec_IntForEachEntryStart( vLevel, Var2, v2, v1 + 1 ) Vec_IntForEachEntryStart( vLevel, Var3, v3, v2 + 1 ) { pLits[0] = Abc_Var2Lit( Var1, 1 ); pLits[1] = Abc_Var2Lit( Var2, 1 ); pLits[2] = Abc_Var2Lit( Var3, 1 ); value = sat_solver_addclause( p->pSat, pLits, pLits+3 ); assert( value ); } } } Vec_WecFree( vObjEdges ); // block forbidden edges Vec_IntForEachEntry( p->vToSkip, Edge, i ) { pLits[0] = Abc_Var2Lit( Edge, 1 ); value = sat_solver_addclause( p->pSat, pLits, pLits+1 ); assert( value ); } if ( fVerbose ) printf( "Edge constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr ); if ( fVerbose ) Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Seg_ManConvertResult( Seg_Man_t * p ) { int iFanin, iObj, i; Vec_Int_t * vEdges2 = Vec_IntAlloc( 1000 ); Vec_IntForEachEntryDouble( p->vEdges, iFanin, iObj, i ) if ( sat_solver_var_value(p->pSat, i/2) ) Vec_IntPushTwo( vEdges2, iFanin, iObj ); return vEdges2; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Seg_ManComputeDelay( Gia_Man_t * pGia, int DelayInit, int nFanouts, int fTwo, int fVerbose ) { int nBTLimit = 0; int nTimeOut = 0; int fVeryVerbose = 0; Gia_Obj_t * pObj; abctime clk = Abc_Clock(); Vec_Int_t * vEdges2 = NULL; int i, iLut, iFirst, nVars, status, Delay, nConfs; Seg_Man_t * p = Seg_ManAlloc( pGia, nFanouts ); int DelayStart = DelayInit ? DelayInit : p->DelayMax; if ( fVerbose ) printf( "Running SatEdge with starting delay %d and edge %d (edge vars %d, total vars %d)\n", DelayStart, fTwo+1, p->FirstVar, sat_solver_nvars(p->pSat) ); Seg_ManCreateCnf( p, fTwo, fVerbose ); //Sat_SolverWriteDimacs( p->pSat, "test_edge.cnf", NULL, NULL, 0 ); // set resource limits sat_solver_set_resource_limits( p->pSat, nBTLimit, 0, 0, 0 ); sat_solver_set_runtime_limit( p->pSat, nTimeOut ? nTimeOut * CLOCKS_PER_SEC + Abc_Clock(): 0 ); sat_solver_set_random( p->pSat, 1 ); sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolars), Vec_IntSize(p->vPolars) ); //sat_solver_set_var_activity( p->pSat, NULL, p->nVars ); // increment delay gradually for ( Delay = p->DelayMax; Delay >= 0; Delay-- ) { // we constrain COs, although it would be fine to constrain only POs Gia_ManForEachCoDriver( p->pGia, pObj, i ) { iLut = Gia_ObjId( p->pGia, pObj ); iFirst = Vec_IntEntry( p->vFirsts, iLut ); nVars = Vec_IntEntry( p->vNvars, iLut ); if ( Delay < nVars && !sat_solver_push(p->pSat, Abc_Var2Lit(iFirst + Delay, 1)) ) break; } if ( i < Gia_ManCoNum(p->pGia) ) { printf( "Proved UNSAT for delay %d. ", Delay ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); break; } if ( Delay > DelayStart ) continue; // solve with assumptions //clk = Abc_Clock(); nConfs = sat_solver_nconflicts( p->pSat ); status = sat_solver_solve_internal( p->pSat ); nConfs = sat_solver_nconflicts( p->pSat ) - nConfs; if ( status == l_True ) { if ( fVerbose ) { int Count = 0; for ( i = 0; i < p->nVars; i++ ) Count += sat_solver_var_value(p->pSat, i); printf( "Solution with delay %2d and %5d edges exists. Conf = %8d. ", Delay, Count, nConfs ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } // save the result Vec_IntFreeP( &vEdges2 ); vEdges2 = Seg_ManConvertResult( p ); if ( fVeryVerbose ) { for ( i = 0; i < p->nVars; i++ ) printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); printf( " " ); for ( i = p->nVars; i < sat_solver_nvars(p->pSat); i++ ) printf( "%d=%d ", i, sat_solver_var_value(p->pSat, i) ); printf( "\n" ); } } else { if ( fVerbose ) { if ( status == l_False ) printf( "Proved UNSAT for delay %d. ", Delay ); else printf( "Resource limit reached for delay %d. ", Delay ); Abc_PrintTime( 1, "Time", Abc_Clock() - clk ); } break; } } Gia_ManEdgeFromArray( p->pGia, vEdges2 ); Vec_IntFreeP( &vEdges2 ); Seg_ManStop( p ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END