saigRetMin.c 21.9 KB
Newer Older
Alan Mishchenko committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/**CFile****************************************************************

  FileName    [saigRetMin.c]

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Sequential AIG package.]

  Synopsis    [Min-area retiming for the AIG.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

  Date        [Ver. 1.0. Started - June 20, 2005.]

  Revision    [$Id: saigRetMin.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]

***********************************************************************/

#include "saig.h"
Alan Mishchenko committed
22

23
#include "nwk.h"
Alan Mishchenko committed
24
#include "cnf.h"
Alan Mishchenko committed
25 26
#include "satSolver.h"
#include "satStore.h"
Alan Mishchenko committed
27

28 29 30
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
31 32 33 34 35 36 37 38 39 40
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

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

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

Alan Mishchenko committed
41
  Synopsis    [Derives the initial state after backward retiming.]
Alan Mishchenko committed
42 43 44 45 46 47 48 49

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
50
Vec_Int_t * Saig_ManRetimeInitState( Aig_Man_t * p )
Alan Mishchenko committed
51
{
Alan Mishchenko committed
52 53 54 55 56 57 58 59
    int nConfLimit = 1000000;
    Vec_Int_t * vCiIds, * vInit = NULL;
    Cnf_Dat_t * pCnf;
    sat_solver * pSat;
    Aig_Obj_t * pObj;
    int i, RetValue, * pModel;
    // solve the SAT problem
    pCnf = Cnf_DeriveSimpleForRetiming( p );
60
    pSat = (sat_solver *)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
Alan Mishchenko committed
61 62 63 64 65
    if ( pSat == NULL )
    {
        Cnf_DataFree( pCnf );
        return NULL;
    }
Alan Mishchenko committed
66
    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
Alan Mishchenko committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
    assert( RetValue != l_Undef );
    // create counter-example
    if ( RetValue == l_True )
    {
        // accumulate SAT variables of the CIs
        vCiIds = Vec_IntAlloc( Aig_ManPiNum(p) );
        Aig_ManForEachPi( p, pObj, i )
            Vec_IntPush( vCiIds, pCnf->pVarNums[pObj->Id] );
        // create the model
        pModel = Sat_SolverGetModel( pSat, vCiIds->pArray, vCiIds->nSize );
        vInit = Vec_IntAllocArray( pModel, Aig_ManPiNum(p) );
        Vec_IntFree( vCiIds );
    }
    sat_solver_delete( pSat );
    Cnf_DataFree( pCnf );
    return vInit;
Alan Mishchenko committed
83 84 85 86
}

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

Alan Mishchenko committed
87
  Synopsis    [Uses UNSAT core to find the part of AIG to be excluded.]
Alan Mishchenko committed
88

Alan Mishchenko committed
89
  Description [Returns the number of the PO that appears in the UNSAT core.]
Alan Mishchenko committed
90 91 92 93 94 95
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
96
int Saig_ManRetimeUnsatCore( Aig_Man_t * p, int fVerbose )
Alan Mishchenko committed
97
{
Alan Mishchenko committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
    int fVeryVerbose = 0;
    int nConfLimit = 1000000;
    void * pSatCnf = NULL; 
    Intp_Man_t * pManProof;
    Vec_Int_t * vCore = NULL;
    Cnf_Dat_t * pCnf;
    sat_solver * pSat;
    Aig_Obj_t * pObj;
    int * pClause1, * pClause2, * pLit, * pVars;
    int i, RetValue, iBadPo, iClause, nVars, nPos;
    // create the SAT solver
    pCnf = Cnf_DeriveSimpleForRetiming( p );
    pSat = sat_solver_new();
    sat_solver_store_alloc( pSat ); 
    sat_solver_setnvars( pSat, pCnf->nVars );
    for ( i = 0; i < pCnf->nClauses; i++ )
Alan Mishchenko committed
114
    {
Alan Mishchenko committed
115
        if ( !sat_solver_addclause( pSat, pCnf->pClauses[i], pCnf->pClauses[i+1] ) )
Alan Mishchenko committed
116
        {
Alan Mishchenko committed
117 118 119
            Cnf_DataFree( pCnf );
            sat_solver_delete( pSat );
            return -1;
Alan Mishchenko committed
120
        }
Alan Mishchenko committed
121 122 123
    }
    sat_solver_store_mark_roots( pSat ); 
    // solve the problem
Alan Mishchenko committed
124
    RetValue = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, (ABC_INT64_T)0, (ABC_INT64_T)0, (ABC_INT64_T)0 );
Alan Mishchenko committed
125 126 127 128 129 130
    assert( RetValue != l_Undef );
    assert( RetValue == l_False );
    pSatCnf = sat_solver_store_release( pSat ); 
    sat_solver_delete( pSat );
    // derive the UNSAT core
    pManProof = Intp_ManAlloc();
131
    vCore = (Vec_Int_t *)Intp_ManUnsatCore( pManProof, (Sto_Man_t *)pSatCnf, fVeryVerbose );
Alan Mishchenko committed
132
    Intp_ManFree( pManProof );
133
    Sto_ManFree( (Sto_Man_t *)pSatCnf );
Alan Mishchenko committed
134 135 136
    // derive the set of variables on which the core depends
    // collect the variable numbers
    nVars = 0;
Alan Mishchenko committed
137
    pVars = ABC_ALLOC( int, pCnf->nVars );
Alan Mishchenko committed
138 139 140 141 142 143
    memset( pVars, 0, sizeof(int) * pCnf->nVars );
    Vec_IntForEachEntry( vCore, iClause, i )
    {
        pClause1 = pCnf->pClauses[iClause];
        pClause2 = pCnf->pClauses[iClause+1];
        for ( pLit = pClause1; pLit < pClause2; pLit++ )
Alan Mishchenko committed
144
        {
Alan Mishchenko committed
145 146 147 148 149
            if ( pVars[ (*pLit) >> 1 ] == 0 )
                nVars++;
            pVars[ (*pLit) >> 1 ] = 1;
            if ( fVeryVerbose )
            printf( "%s%d ", ((*pLit) & 1)? "-" : "+", (*pLit) >> 1 );
Alan Mishchenko committed
150
        }
Alan Mishchenko committed
151 152
        if ( fVeryVerbose )
        printf( "\n" );
Alan Mishchenko committed
153
    }
Alan Mishchenko committed
154
    // collect the nodes
Alan Mishchenko committed
155 156 157 158 159 160 161 162
    if ( fVeryVerbose ) {
      Aig_ManForEachObj( p, pObj, i )
          if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 )
          {
              Aig_ObjPrint( p, pObj );
              printf( "\n" );
          }
    }
Alan Mishchenko committed
163 164 165 166 167 168 169 170 171 172 173 174
    // pick the first PO in the list
    nPos = 0;
    iBadPo = -1;
    Aig_ManForEachPo( p, pObj, i )
        if ( pCnf->pVarNums[pObj->Id] >= 0 && pVars[ pCnf->pVarNums[pObj->Id] ] == 1 )
        {
            if ( iBadPo == -1 )
                iBadPo = i;
            nPos++;
        }
    if ( fVerbose )
        printf( "UNSAT core: %d clauses, %d variables, %d POs.  ", Vec_IntSize(vCore), nVars, nPos );
Alan Mishchenko committed
175
    ABC_FREE( pVars );
Alan Mishchenko committed
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
    Vec_IntFree( vCore );
    Cnf_DataFree( pCnf );
    return iBadPo;
}

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

  Synopsis    [Marks the TFI cone with the current traversal ID.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Saig_ManMarkCone_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
{
    if ( pObj == NULL )
        return;
    if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
        return;
    Aig_ObjSetTravIdCurrent( p, pObj );
    Saig_ManMarkCone_rec( p, Aig_ObjFanin0(pObj) );
    Saig_ManMarkCone_rec( p, Aig_ObjFanin1(pObj) );
Alan Mishchenko committed
201 202 203 204
}

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

Alan Mishchenko committed
205
  Synopsis    [Counts the number of nodes to get registers after retiming.]
Alan Mishchenko committed
206 207 208 209 210 211 212 213

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
214
int Saig_ManRetimeCountCut( Aig_Man_t * p, Vec_Ptr_t * vCut )
Alan Mishchenko committed
215 216 217
{
    Vec_Ptr_t * vNodes;
    Aig_Obj_t * pObj, * pFanin;
Alan Mishchenko committed
218
    int i, RetValue;
Alan Mishchenko committed
219 220
    // mark the cones
    Aig_ManIncrementTravId( p );
221
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
222 223
        Saig_ManMarkCone_rec( p, pObj );
    // collect the new cut
Alan Mishchenko committed
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
    vNodes = Vec_PtrAlloc( 1000 );
    Aig_ManForEachObj( p, pObj, i )
    {
        if ( Aig_ObjIsTravIdCurrent(p, pObj) )
            continue;
        pFanin = Aig_ObjFanin0( pObj );
        if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) )
        {
            Vec_PtrPush( vNodes, pFanin );
            pFanin->fMarkA = 1;
        }
        pFanin = Aig_ObjFanin1( pObj );
        if ( pFanin && !pFanin->fMarkA && Aig_ObjIsTravIdCurrent(p, pFanin) )
        {
            Vec_PtrPush( vNodes, pFanin );
            pFanin->fMarkA = 1;
        }
    }
242
    Vec_PtrForEachEntry( Aig_Obj_t *, vNodes, pObj, i )
Alan Mishchenko committed
243
        pObj->fMarkA = 0;
Alan Mishchenko committed
244 245 246
    RetValue = Vec_PtrSize( vNodes );
    Vec_PtrFree( vNodes );
    return RetValue;
Alan Mishchenko committed
247 248 249 250
}

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

Alan Mishchenko committed
251
  Synopsis    [Duplicates the AIG recursively.]
Alan Mishchenko committed
252 253 254 255 256 257 258 259

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
260
void Saig_ManRetimeDup_rec( Aig_Man_t * pNew, Aig_Obj_t * pObj )
Alan Mishchenko committed
261 262 263 264
{
    if ( pObj->pData )
        return;
    assert( Aig_ObjIsNode(pObj) );
Alan Mishchenko committed
265 266
    Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
    Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin1(pObj) );
Alan Mishchenko committed
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
    pObj->pData = Aig_And( pNew, Aig_ObjChild0Copy(pObj), Aig_ObjChild1Copy(pObj) );
}

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

  Synopsis    [Duplicates the AIG while retiming the registers to the cut.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Saig_ManRetimeDupForward( Aig_Man_t * p, Vec_Ptr_t * vCut )
{
    Aig_Man_t * pNew;
    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
    int i;
    // mark the cones under the cut
//    assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) );
    // create the new manager
    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
    pNew->pName = Aig_UtilStrsav( p->pName );
    pNew->pSpec = Aig_UtilStrsav( p->pSpec );
    pNew->nRegs = Vec_PtrSize(vCut);
    pNew->nTruePis = p->nTruePis;
    pNew->nTruePos = p->nTruePos;
    // create the true PIs
    Aig_ManCleanData( p );
    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
    Saig_ManForEachPi( p, pObj, i )
        pObj->pData = Aig_ObjCreatePi( pNew );
    // create the registers
301
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
302
        pObj->pData = Aig_NotCond( Aig_ObjCreatePi(pNew), pObj->fPhase );
Alan Mishchenko committed
303
    // duplicate logic above the cut
Alan Mishchenko committed
304
    Aig_ManForEachPo( p, pObj, i )
Alan Mishchenko committed
305
        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
Alan Mishchenko committed
306 307 308 309 310 311 312 313 314 315
    // create the true POs
    Saig_ManForEachPo( p, pObj, i )
        Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
    // remember value in LI
    Saig_ManForEachLi( p, pObj, i )
        pObj->pData = Aig_ObjChild0Copy(pObj);
    // transfer values from the LIs to the LOs
    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
        pObjLo->pData = pObjLi->pData;
    // erase the data values on the internal nodes of the cut
316
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
317
        if ( Aig_ObjIsNode(pObj) )
Alan Mishchenko committed
318
            pObj->pData = NULL;
Alan Mishchenko committed
319
    // duplicate logic below the cut
320
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
321
    {
Alan Mishchenko committed
322
        Saig_ManRetimeDup_rec( pNew, pObj );
323
        Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, pObj->fPhase) );
Alan Mishchenko committed
324
    }
Alan Mishchenko committed
325
    Aig_ManCleanup( pNew );
Alan Mishchenko committed
326 327 328 329 330
    return pNew;
}

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

Alan Mishchenko committed
331
  Synopsis    [Duplicates the AIG while retiming the registers to the cut.]
Alan Mishchenko committed
332 333 334 335 336 337 338 339

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
340
Aig_Man_t * Saig_ManRetimeDupBackward( Aig_Man_t * p, Vec_Ptr_t * vCut, Vec_Int_t * vInit )
Alan Mishchenko committed
341 342
{
    Aig_Man_t * pNew;
Alan Mishchenko committed
343
    Aig_Obj_t * pObj, * pObjLi, * pObjLo;
Alan Mishchenko committed
344 345 346 347 348
    int i;
    // mark the cones under the cut
//    assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) );
    // create the new manager
    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
Alan Mishchenko committed
349 350 351 352 353
    pNew->pName = Aig_UtilStrsav( p->pName );
    pNew->pSpec = Aig_UtilStrsav( p->pSpec );
    pNew->nRegs = Vec_PtrSize(vCut);
    pNew->nTruePis = p->nTruePis;
    pNew->nTruePos = p->nTruePos;
Alan Mishchenko committed
354 355 356
    // create the true PIs
    Aig_ManCleanData( p );
    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
Alan Mishchenko committed
357 358
    Saig_ManForEachPi( p, pObj, i )
        pObj->pData = Aig_ObjCreatePi( pNew );
Alan Mishchenko committed
359
    // create the registers
360
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
361 362
        pObj->pData = Aig_NotCond( Aig_ObjCreatePi(pNew), vInit?Vec_IntEntry(vInit,i):0 );
    // duplicate logic above the cut and remember values
Alan Mishchenko committed
363 364 365
    Saig_ManForEachLi( p, pObj, i )
    {
        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
Alan Mishchenko committed
366 367 368 369 370 371
        pObj->pData = Aig_ObjChild0Copy(pObj);
    }
    // transfer values from the LIs to the LOs
    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
        pObjLo->pData = pObjLi->pData;
    // erase the data values on the internal nodes of the cut
372
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
373 374 375 376 377 378 379 380 381 382 383
        if ( Aig_ObjIsNode(pObj) )
            pObj->pData = NULL;
    // replicate the data on the constant node and the PIs
    pObj = Aig_ManConst1(p);
    pObj->pData = Aig_ManConst1(pNew);
    Saig_ManForEachPi( p, pObj, i )
        pObj->pData = Aig_ManPi( pNew, i );
    // duplicate logic below the cut
    Saig_ManForEachPo( p, pObj, i )
    {
        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
Alan Mishchenko committed
384 385
        Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
    }
386
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
387 388
    {
        Saig_ManRetimeDup_rec( pNew, pObj );
389
        Aig_ObjCreatePo( pNew, Aig_NotCond((Aig_Obj_t *)pObj->pData, vInit?Vec_IntEntry(vInit,i):0) );
Alan Mishchenko committed
390 391
    }
    Aig_ManCleanup( pNew );
Alan Mishchenko committed
392 393 394 395 396
    return pNew;
}

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

Alan Mishchenko committed
397
  Synopsis    [Derives AIG for the initial state computation.]
Alan Mishchenko committed
398 399 400 401 402 403 404 405

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
406
Aig_Man_t * Saig_ManRetimeDupInitState( Aig_Man_t * p, Vec_Ptr_t * vCut )
Alan Mishchenko committed
407
{
Alan Mishchenko committed
408
    Aig_Man_t * pNew;
Alan Mishchenko committed
409
    Aig_Obj_t * pObj;
Alan Mishchenko committed
410 411 412 413 414 415 416 417 418
    int i;
    // mark the cones under the cut
//    assert( Vec_PtrSize(vCut) == Saig_ManRetimeCountCut(p, vCut) );
    // create the new manager
    pNew = Aig_ManStart( Aig_ManObjNumMax(p) );
    // create the true PIs
    Aig_ManCleanData( p );
    Aig_ManConst1(p)->pData = Aig_ManConst1(pNew);
    // create the registers
419
    Vec_PtrForEachEntry( Aig_Obj_t *, vCut, pObj, i )
Alan Mishchenko committed
420 421 422
        pObj->pData = Aig_ObjCreatePi(pNew);
    // duplicate logic above the cut and create POs
    Saig_ManForEachLi( p, pObj, i )
Alan Mishchenko committed
423
    {
Alan Mishchenko committed
424 425
        Saig_ManRetimeDup_rec( pNew, Aig_ObjFanin0(pObj) );
        Aig_ObjCreatePo( pNew, Aig_ObjChild0Copy(pObj) );
Alan Mishchenko committed
426
    }
Alan Mishchenko committed
427
    return pNew;
Alan Mishchenko committed
428 429 430 431 432 433 434 435 436 437 438 439 440 441 442
}

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

  Synopsis    [Returns the array of bad registers.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Ptr_t * Saig_ManGetRegistersToExclude( Aig_Man_t * p )
{
Alan Mishchenko committed
443
    Vec_Ptr_t * vNodes;
Alan Mishchenko committed
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460
    Aig_Obj_t * pObj, * pFanin;
    int i, Diffs;
    assert( Saig_ManRegNum(p) > 0 );
    Saig_ManForEachLi( p, pObj, i )
    {
        pFanin = Aig_ObjFanin0(pObj);
        if ( !Aig_ObjFaninC0(pObj) )
            pFanin->fMarkA = 1;
        else
            pFanin->fMarkB = 1;
    }
    Diffs = 0;
    Saig_ManForEachLi( p, pObj, i )
    {
        pFanin = Aig_ObjFanin0(pObj);
        Diffs += pFanin->fMarkA && pFanin->fMarkB;
    }
Alan Mishchenko committed
461
    vNodes = Vec_PtrAlloc( 100 );
Alan Mishchenko committed
462
    if ( Diffs > 0 )
Alan Mishchenko committed
463 464 465 466 467 468 469 470 471
    {
        Saig_ManForEachLi( p, pObj, i )
        {
            pFanin = Aig_ObjFanin0(pObj);
            if ( pFanin->fMarkA && pFanin->fMarkB )
                Vec_PtrPush( vNodes, pObj );
        }
        assert( Vec_PtrSize(vNodes) == Diffs );
    }
Alan Mishchenko committed
472 473 474 475 476 477 478 479 480 481
    Saig_ManForEachLi( p, pObj, i )
    {
        pFanin = Aig_ObjFanin0(pObj);
        pFanin->fMarkA = pFanin->fMarkB = 0;
    }
    return vNodes;
}

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

Alan Mishchenko committed
482
  Synopsis    [Hides the registers that cannot be backward retimed.]
Alan Mishchenko committed
483 484 485 486 487 488 489 490

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
491
int Saig_ManHideBadRegs( Aig_Man_t * p, Vec_Ptr_t * vBadRegs )
Alan Mishchenko committed
492
{
Alan Mishchenko committed
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507
    Vec_Ptr_t * vPisNew, * vPosNew;
    Aig_Obj_t * pObjLi, * pObjLo;
    int nTruePi, nTruePo, nBadRegs, i;
    if ( Vec_PtrSize(vBadRegs) == 0 )
        return 0;
    // attached LOs to LIs
    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
        pObjLi->pData = pObjLo;
    // reorder them by putting bad registers first
    vPisNew = Vec_PtrDup( p->vPis );
    vPosNew = Vec_PtrDup( p->vPos );
    nTruePi = Aig_ManPiNum(p) - Aig_ManRegNum(p);
    nTruePo = Aig_ManPoNum(p) - Aig_ManRegNum(p);
    assert( nTruePi == p->nTruePis );
    assert( nTruePo == p->nTruePos );
508
    Vec_PtrForEachEntry( Aig_Obj_t *, vBadRegs, pObjLi, i )
Alan Mishchenko committed
509
    {
Alan Mishchenko committed
510 511 512
        Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLi->pData );
        Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi );
        pObjLi->fMarkA = 1;
Alan Mishchenko committed
513 514 515
    }
    Saig_ManForEachLiLo( p, pObjLi, pObjLo, i )
    {
Alan Mishchenko committed
516 517 518 519 520 521 522
        if ( pObjLi->fMarkA )
        {
            pObjLi->fMarkA = 0;
            continue;
        }
        Vec_PtrWriteEntry( vPisNew, nTruePi++, pObjLo );
        Vec_PtrWriteEntry( vPosNew, nTruePo++, pObjLi );
Alan Mishchenko committed
523
    }
Alan Mishchenko committed
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
    // check the sizes
    assert( nTruePi == Aig_ManPiNum(p) );
    assert( nTruePo == Aig_ManPoNum(p) );
    // transfer the arrays
    Vec_PtrFree( p->vPis ); p->vPis = vPisNew;
    Vec_PtrFree( p->vPos ); p->vPos = vPosNew;
    // update the PIs
    nBadRegs = Vec_PtrSize(vBadRegs);
    p->nRegs -= nBadRegs;
    p->nTruePis += nBadRegs;
    p->nTruePos += nBadRegs;
    return nBadRegs;
}

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

  Synopsis    [Exposes bad registers.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Saig_ManExposeBadRegs( Aig_Man_t * p, int nBadRegs )
{
    p->nRegs += nBadRegs;
    p->nTruePis -= nBadRegs;
    p->nTruePos -= nBadRegs;
}

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

  Synopsis    [Performs min-area retiming backward with initial state.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Aig_Man_t * Saig_ManRetimeMinAreaBackward( Aig_Man_t * pNew, int fVerbose )
{
    Aig_Man_t * pInit, * pFinal;
    Vec_Ptr_t * vBadRegs, * vCut;
    Vec_Int_t * vInit;
    int iBadReg;
    // transform the AIG to have no bad registers
    vBadRegs = Saig_ManGetRegistersToExclude( pNew );
    if ( fVerbose && Vec_PtrSize(vBadRegs) )
        printf( "Excluding %d registers that cannot be backward retimed.\n", Vec_PtrSize(vBadRegs) ); 
    while ( 1 )
Alan Mishchenko committed
578
    {
Alan Mishchenko committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
        Saig_ManHideBadRegs( pNew, vBadRegs );
        Vec_PtrFree( vBadRegs );
        // compute cut
        vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose );
        if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) )
        {
            Vec_PtrFree( vCut );
            return NULL;
        }
        // derive the initial state
        pInit = Saig_ManRetimeDupInitState( pNew, vCut );
        vInit = Saig_ManRetimeInitState( pInit );
        if ( vInit != NULL )
        {
            pFinal = Saig_ManRetimeDupBackward( pNew, vCut, vInit );
            Vec_IntFree( vInit );
            Vec_PtrFree( vCut );
            Aig_ManStop( pInit );
            return pFinal;
        }
        Vec_PtrFree( vCut );
        // there is no initial state - find the offending output
        iBadReg = Saig_ManRetimeUnsatCore( pInit, fVerbose );
        Aig_ManStop( pInit );
        if ( fVerbose )
            printf( "Excluding register %d.\n", iBadReg ); 
        // prepare to remove this output
        vBadRegs = Vec_PtrAlloc( 1 );
        Vec_PtrPush( vBadRegs, Aig_ManPo( pNew, Saig_ManPoNum(pNew) + iBadReg ) );
Alan Mishchenko committed
608
    }
Alan Mishchenko committed
609
    return NULL;
Alan Mishchenko committed
610 611 612 613 614 615 616 617 618 619 620 621 622
}

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

  Synopsis    [Performs min-area retiming.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
623
Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose )
Alan Mishchenko committed
624 625
{
    Vec_Ptr_t * vCut;
Alan Mishchenko committed
626
    Aig_Man_t * pNew, * pTemp, * pCopy;
Alan Mishchenko committed
627
    int i, fChanges;
Alan Mishchenko committed
628
    pNew = Aig_ManDupSimple( p );
Alan Mishchenko committed
629
    // perform several iterations of forward retiming
Alan Mishchenko committed
630
    fChanges = 0;
Alan Mishchenko committed
631
    if ( !fBackwardOnly )
Alan Mishchenko committed
632
    for ( i = 0; i < nMaxIters; i++ )
Alan Mishchenko committed
633
    {
Alan Mishchenko committed
634 635
        if ( Saig_ManRegNum(pNew) == 0 )
            break;
Alan Mishchenko committed
636 637 638
        vCut = Nwk_ManDeriveRetimingCut( pNew, 1, fVerbose );
        if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) )
        {
Alan Mishchenko committed
639 640
            if ( fVerbose && !fChanges )
                printf( "Forward retiming cannot reduce registers.\n" );
Alan Mishchenko committed
641 642 643 644 645 646
            Vec_PtrFree( vCut );
            break;
        }
        pNew = Saig_ManRetimeDupForward( pTemp = pNew, vCut );
        Aig_ManStop( pTemp );
        Vec_PtrFree( vCut );
Alan Mishchenko committed
647 648 649
        if ( fVerbose )
            Aig_ManReportImprovement( p, pNew );
        fChanges = 1;
Alan Mishchenko committed
650
    }
Alan Mishchenko committed
651 652 653
    // perform several iterations of backward retiming
    fChanges = 0;
    if ( !fForwardOnly && !fInitial )
Alan Mishchenko committed
654
    for ( i = 0; i < nMaxIters; i++ )
Alan Mishchenko committed
655
    {
Alan Mishchenko committed
656 657
        if ( Saig_ManRegNum(pNew) == 0 )
            break;
Alan Mishchenko committed
658
        vCut = Nwk_ManDeriveRetimingCut( pNew, 0, fVerbose );
Alan Mishchenko committed
659
        if ( Vec_PtrSize(vCut) >= Aig_ManRegNum(pNew) )
Alan Mishchenko committed
660
        {
Alan Mishchenko committed
661 662 663 664
            if ( fVerbose && !fChanges )
                printf( "Backward retiming cannot reduce registers.\n" );
            Vec_PtrFree( vCut );
            break;
Alan Mishchenko committed
665
        }
Alan Mishchenko committed
666 667
        pNew = Saig_ManRetimeDupBackward( pTemp = pNew, vCut, NULL );
        Aig_ManStop( pTemp );
Alan Mishchenko committed
668
        Vec_PtrFree( vCut );
Alan Mishchenko committed
669 670 671 672 673
        if ( fVerbose )
            Aig_ManReportImprovement( p, pNew );
        fChanges = 1;
    }
    else if ( !fForwardOnly && fInitial )
Alan Mishchenko committed
674
    for ( i = 0; i < nMaxIters; i++ )
Alan Mishchenko committed
675
    {
Alan Mishchenko committed
676 677
        if ( Saig_ManRegNum(pNew) == 0 )
            break;
Alan Mishchenko committed
678
        pCopy = Aig_ManDupSimple( pNew );
Alan Mishchenko committed
679 680 681 682 683 684 685 686 687 688 689 690 691 692
        pTemp = Saig_ManRetimeMinAreaBackward( pCopy, fVerbose );
        Aig_ManStop( pCopy );
        if ( pTemp == NULL )
        {
            if ( fVerbose && !fChanges )
                printf( "Backward retiming cannot reduce registers.\n" );
            break;
        }
        Saig_ManExposeBadRegs( pTemp, Saig_ManPoNum(pTemp) - Saig_ManPoNum(pNew) );
        Aig_ManStop( pNew );
        pNew = pTemp;
        if ( fVerbose )
            Aig_ManReportImprovement( p, pNew );
        fChanges = 1;
Alan Mishchenko committed
693
    }
Alan Mishchenko committed
694 695
    if ( !fForwardOnly && !fInitial && fChanges )
        printf( "Assuming const-0 init-state after backward retiming. Result will not verify.\n" );
Alan Mishchenko committed
696 697 698 699 700 701 702 703
    return pNew;
}

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


704 705
ABC_NAMESPACE_IMPL_END