giaSatEdge.c 18.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/**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
36
    //Vec_Int_t *    vCardVars;    // candinality variables
37 38 39 40 41 42 43 44 45 46 47 48 49
    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;
50
    Vec_Int_t *    vPolars;      // polarity
51
    Vec_Int_t *    vToSkip;      // edges to skip
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    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     []

***********************************************************************/
79
Vec_Int_t * Seg_ManCountIntEdges( Gia_Man_t * p, Vec_Int_t * vPolars, Vec_Int_t * vToSkip, int nFanouts )
80 81 82 83
{
    int i, iLut, iFanin;
    Vec_Int_t * vEdges = Vec_IntAlloc( 1000 );
    assert( Gia_ManHasMapping(p) );
84
    Vec_IntClear( vPolars );
85 86 87
    Vec_IntClear( vToSkip );
    if ( nFanouts )
        Gia_ManSetLutRefs( p );
88 89 90
    Gia_ManForEachLut( p, iLut )
        Gia_LutForEachFanin( p, iLut, iFanin, i )
            if ( Gia_ObjIsAnd(Gia_ManObj(p, iFanin)) )
91 92 93
            {
                if ( p->vEdge1 && Gia_ObjCheckEdge(p, iFanin, iLut) )
                    Vec_IntPush( vPolars, Vec_IntSize(vEdges)/2 );
94 95
                if ( nFanouts && Gia_ObjLutRefNumId(p, iFanin) >= nFanouts )
                    Vec_IntPush( vToSkip, Vec_IntSize(vEdges)/2 );
96
                Vec_IntPushTwo( vEdges, iFanin, iLut );
97
            }
98 99
    if ( nFanouts )
        ABC_FREE( p->pLutRefs );
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
    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 )
{
115
    Gia_Obj_t * pObj;
116 117 118 119
    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 );
120 121 122 123 124 125 126 127 128
    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 )
129
    {
130 131 132 133 134
        if ( Gia_ObjIsCo(pObj) )
            continue;
        if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsLut(p->pGia, iLut) )
            continue;
        assert( Gia_ObjIsCi(pObj) || Gia_ObjIsLut(p->pGia, iLut) );
135
        Vec_IntWriteEntry( p->vFirsts, iLut, iStartVar );
136 137
        //assert( p->pLevels[iLut] > 0 );
        nVars = p->pLevels[iLut] < 2 ? 0 : p->pLevels[iLut];
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
        Vec_IntWriteEntry( p->vNvars,  iLut, nVars );
        iStartVar += nVars;
    }
    return iStartVar;
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
155
Seg_Man_t * Seg_ManAlloc( Gia_Man_t * pGia, int nFanouts )
156 157 158
{
    int nVarsAll;
    Seg_Man_t * p = ABC_CALLOC( Seg_Man_t, 1 );
159
    p->vPolars    = Vec_IntAlloc( 1000 ); 
160 161
    p->vToSkip    = Vec_IntAlloc( 1000 ); 
    p->vEdges     = Seg_ManCountIntEdges( pGia, p->vPolars, p->vToSkip, nFanouts );
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
    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 );
191
    Vec_IntClear( p->vPolars );
192
    Vec_IntClear( p->vToSkip );
193 194 195 196 197 198 199 200 201 202 203 204
    // 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 );
205
    Vec_IntFree( p->vPolars );
206
    Vec_IntFree( p->vToSkip );
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
    ABC_FREE( p->pLevels );
    // other
    ABC_FREE( p );
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
223
void Seg_ManCreateCnf( Seg_Man_t * p, int fTwo, int fVerbose )
224
{
225
    Tim_Man_t * pTim = (Tim_Man_t *)p->pGia->pManTime;
226 227 228 229 230
    Gia_Obj_t * pObj;
    Vec_Wec_t * vObjEdges;
    Vec_Int_t * vLevel;
    int iLut, iFanin, iFirst;
    int pLits[3], Count = 0;
231
    int i, k, nVars, Edge, value;
232 233 234 235 236 237 238
    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 );
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
        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;
        }
289 290 291
        if ( !Gia_ObjIsLut(p->pGia, iLut) )
            continue;
        Gia_LutForEachFanin( p->pGia, iLut, iFanin, i )
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
            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)) )
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
            {
                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 );
345
    if ( fVerbose )
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
    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;
368
        if ( (!fTwo && Vec_IntSize(vLevel) >= 2) || (fTwo && Vec_IntSize(vLevel) > 10) )
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
        {
            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 );
394 395 396 397 398 399 400
    // 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 );
    }
401
    if ( fVerbose )
402
    printf( "Edge constraints = %d. ", sat_solver_nclauses(p->pSat) - nConstr );
403
    if ( fVerbose )
404 405 406 407 408 409 410 411 412 413 414 415 416 417
    Abc_PrintTime( 1, "Time", Abc_Clock() - clk );
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
418
Vec_Int_t * Seg_ManConvertResult( Seg_Man_t * p )
419 420 421 422 423 424
{
    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 );
425
    return vEdges2;
426 427 428 429 430 431 432 433 434 435 436 437 438
}

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

  Synopsis    []

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
439
void Seg_ManComputeDelay( Gia_Man_t * pGia, int DelayInit, int nFanouts, int fTwo, int fVerbose )
440
{
441 442 443 444
    int nBTLimit = 0;
    int nTimeOut = 0;
    int fVeryVerbose = 0;

445 446
    Gia_Obj_t * pObj;
    abctime clk = Abc_Clock();
447 448
    Vec_Int_t * vEdges2 = NULL;
    int i, iLut, iFirst, nVars, status, Delay, nConfs;
449
    Seg_Man_t * p = Seg_ManAlloc( pGia, nFanouts );
450
    int DelayStart = DelayInit ? DelayInit : p->DelayMax;
451

452 453 454 455
    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 );
456
    //Sat_SolverWriteDimacs( p->pSat, "test_edge.cnf", NULL, NULL, 0 );
457 458 459 460
    // 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 );
461
    sat_solver_set_polarity( p->pSat, Vec_IntArray(p->vPolars), Vec_IntSize(p->vPolars) );
462
    //sat_solver_set_var_activity( p->pSat, NULL, p->nVars );
463 464
    // increment delay gradually
    for ( Delay = p->DelayMax; Delay >= 0; Delay-- )
465
    {
466
        // we constrain COs, although it would be fine to constrain only POs
467 468 469 470 471
        Gia_ManForEachCoDriver( p->pGia, pObj, i )
        {
            iLut   = Gia_ObjId( p->pGia, pObj );
            iFirst = Vec_IntEntry( p->vFirsts, iLut );
            nVars  = Vec_IntEntry( p->vNvars, iLut );
472 473 474 475 476 477 478 479
            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;
480
        }
481 482
        if ( Delay > DelayStart )
            continue;
483
        // solve with assumptions
484 485 486 487
        //clk = Abc_Clock();
        nConfs = sat_solver_nconflicts( p->pSat );
        status = sat_solver_solve_internal( p->pSat );
        nConfs = sat_solver_nconflicts( p->pSat ) - nConfs;
488 489 490 491
        if ( status == l_True )
        {
            if ( fVerbose )
            {
492 493 494 495 496 497 498 499 500 501 502
                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 )
            {
503 504 505 506 507 508 509 510 511 512 513
                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
        {
514 515 516 517 518 519 520 521 522
            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;
523 524
        }
    }
525 526
    Gia_ManEdgeFromArray( p->pGia, vEdges2 );
    Vec_IntFreeP( &vEdges2 );
527 528 529 530 531 532 533 534 535 536 537
    Seg_ManStop( p );
}


////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


ABC_NAMESPACE_IMPL_END