abcStrash.c 25.1 KB
Newer Older
Alan Mishchenko committed
1 2
/**CFile****************************************************************

Alan Mishchenko committed
3
  FileName    [abcStrash.c]
Alan Mishchenko committed
4 5 6 7 8 9 10 11 12 13 14 15 16

  SystemName  [ABC: Logic synthesis and verification system.]

  PackageName [Network and node package.]

  Synopsis    [Strashing of the current network.]

  Author      [Alan Mishchenko]
  
  Affiliation [UC Berkeley]

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

Alan Mishchenko committed
17
  Revision    [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
Alan Mishchenko committed
18 19 20 21 22

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

#include "abc.h"
#include "extra.h"
Alan Mishchenko committed
23
#include "dec.h"
Alan Mishchenko committed
24

25 26 27
ABC_NAMESPACE_IMPL_START


Alan Mishchenko committed
28 29 30 31
////////////////////////////////////////////////////////////////////////
///                        DECLARATIONS                              ///
////////////////////////////////////////////////////////////////////////

Alan Mishchenko committed
32
static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord );
Alan Mishchenko committed
33 34

////////////////////////////////////////////////////////////////////////
Alan Mishchenko committed
35
///                     FUNCTION DEFINITIONS                         ///
Alan Mishchenko committed
36 37 38 39
////////////////////////////////////////////////////////////////////////

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

Alan Mishchenko committed
40
  Synopsis    [Reapplies structural hashing to the AIG.]
Alan Mishchenko committed
41

Alan Mishchenko committed
42 43
  Description [Because of the structural hashing, this procedure should not 
  change the number of nodes. It is useful to detect the bugs in the original AIG.]
Alan Mishchenko committed
44 45 46 47 48 49
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
50
Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup )
Alan Mishchenko committed
51
{
Alan Mishchenko committed
52
//    extern int timeRetime;
Alan Mishchenko committed
53
    Abc_Ntk_t * pNtkAig;
Alan Mishchenko committed
54 55 56 57 58 59 60 61 62 63 64
    Abc_Obj_t * pObj;
    int i, nNodes;//, RetValue;
    assert( Abc_NtkIsStrash(pNtk) );
//timeRetime = clock();
    // print warning about choice nodes
    if ( Abc_NtkGetChoiceNum( pNtk ) )
        printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
    // restrash the nodes (assuming a topological order of the old network)
    Abc_NtkForEachNode( pNtk, pObj, i )
65
        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
Alan Mishchenko committed
66 67 68 69 70 71
    // finalize the network
    Abc_NtkFinalize( pNtk, pNtkAig );
    // print warning about self-feed latches
//    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
//        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
    // perform cleanup if requested
72
    if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) 
Alan Mishchenko committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
        printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
    // duplicate EXDC 
    if ( pNtk->pExdc )
        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
    // make sure everything is okay
    if ( !Abc_NtkCheck( pNtkAig ) )
    {
        printf( "Abc_NtkStrash: The network check has failed.\n" );
        Abc_NtkDelete( pNtkAig );
        return NULL;
    }
//timeRetime = clock() - timeRetime;
//    if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
//        printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
    return pNtkAig;

}

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

  Synopsis    [Reapplies structural hashing to the AIG.]
Alan Mishchenko committed
94

Alan Mishchenko committed
95 96 97 98 99 100 101 102
  Description [Because of the structural hashing, this procedure should not 
  change the number of nodes. It is useful to detect the bugs in the original AIG.]
               
  SideEffects []
 
  SeeAlso     []

***********************************************************************/
103
Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup )
Alan Mishchenko committed
104
{
Alan Mishchenko committed
105
//    extern int timeRetime;
Alan Mishchenko committed
106 107 108
    Abc_Ntk_t * pNtkAig;
    Abc_Obj_t * pObj;
    int i, nNodes;//, RetValue;
Alan Mishchenko committed
109
    int Counter = 0;
Alan Mishchenko committed
110 111
    assert( Abc_NtkIsStrash(pNtk) );
//timeRetime = clock();
Alan Mishchenko committed
112 113
    // print warning about choice nodes
    if ( Abc_NtkGetChoiceNum( pNtk ) )
Alan Mishchenko committed
114 115 116 117 118
        printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
    // complement the 1-values registers
    Abc_NtkForEachLatch( pNtk, pObj, i )
Alan Mishchenko committed
119 120 121 122
    {
        if ( Abc_LatchIsInitDc(pObj) )
            Counter++;
        else if ( Abc_LatchIsInit1(pObj) )
Alan Mishchenko committed
123
            Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
Alan Mishchenko committed
124 125 126
    }
    if ( Counter )
    printf( "Converting %d flops from don't-care to zero initial value.\n", Counter );
Alan Mishchenko committed
127 128
    // restrash the nodes (assuming a topological order of the old network)
    Abc_NtkForEachNode( pNtk, pObj, i )
129
        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
Alan Mishchenko committed
130 131 132 133 134
    // finalize the network
    Abc_NtkFinalize( pNtk, pNtkAig );
    // complement the 1-valued registers
    Abc_NtkForEachLatch( pNtkAig, pObj, i )
        if ( Abc_LatchIsInit1(pObj) )
Alan Mishchenko committed
135
        {
Alan Mishchenko committed
136
            Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 );
Alan Mishchenko committed
137 138 139 140 141 142 143
            // if latch has PO as one of its fanouts change latch name
            if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pObj) ) )
            {
                Nm_ManDeleteIdName( pObj->pNtk->pManName, Abc_ObjFanout0(pObj)->Id );
                Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjName(Abc_ObjFanout0(pObj)), "_inv" );
            }
        }
Alan Mishchenko committed
144 145 146 147 148 149 150 151
    // set all constant-0 values
    Abc_NtkForEachLatch( pNtkAig, pObj, i )
        Abc_LatchSetInit0( pObj );

    // print warning about self-feed latches
//    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
//        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
    // perform cleanup if requested
152
    if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) 
Alan Mishchenko committed
153 154 155 156 157 158 159 160 161 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 191 192 193 194 195
        printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
    // duplicate EXDC 
    if ( pNtk->pExdc )
        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
    // make sure everything is okay
    if ( !Abc_NtkCheck( pNtkAig ) )
    {
        printf( "Abc_NtkStrash: The network check has failed.\n" );
        Abc_NtkDelete( pNtkAig );
        return NULL;
    }
//timeRetime = clock() - timeRetime;
//    if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
//        printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
    return pNtkAig;

}

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

  Synopsis    [Transforms logic network into structurally hashed AIG.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord )
{
    Abc_Ntk_t * pNtkAig;
    int nNodes;
    assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
    // consider the special case when the network is already structurally hashed
    if ( Abc_NtkIsStrash(pNtk) )
        return Abc_NtkRestrash( pNtk, fCleanup );
    // convert the node representation in the logic network to the AIG form
    if ( !Abc_NtkToAig(pNtk) )
    {
        printf( "Converting to AIGs has failed.\n" );
        return NULL;
    }
Alan Mishchenko committed
196
    // perform strashing
Alan Mishchenko committed
197 198 199
//    Abc_NtkCleanCopy( pNtk );
    pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
    Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord );
Alan Mishchenko committed
200 201
    Abc_NtkFinalize( pNtk, pNtkAig );
    // print warning about self-feed latches
Alan Mishchenko committed
202 203 204
//    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
//        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
    // perform cleanup if requested
205
    nNodes = fCleanup? Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc) : 0;
Alan Mishchenko committed
206 207
//    if ( nNodes )
//        printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
Alan Mishchenko committed
208 209
    // duplicate EXDC 
    if ( pNtk->pExdc )
Alan Mishchenko committed
210
        pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
Alan Mishchenko committed
211
    // make sure everything is okay
Alan Mishchenko committed
212
    if ( !Abc_NtkCheck( pNtkAig ) )
Alan Mishchenko committed
213 214 215 216 217 218 219 220 221 222
    {
        printf( "Abc_NtkStrash: The network check has failed.\n" );
        Abc_NtkDelete( pNtkAig );
        return NULL;
    }
    return pNtkAig;
}

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

Alan Mishchenko committed
223 224 225
  Synopsis    [Appends the second network to the first.]

  Description [Modifies the first network by adding the logic of the second. 
Alan Mishchenko committed
226 227
  Performs structural hashing while appending the networks. Does not change 
  the second network. Returns 0 if the appending failed, 1 otherise.]
Alan Mishchenko committed
228 229 230 231 232 233
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
234
int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
Alan Mishchenko committed
235 236
{
    Abc_Obj_t * pObj;
Alan Mishchenko committed
237 238
    char * pName;
    int i, nNewCis;
Alan Mishchenko committed
239
    // the first network should be an AIG
Alan Mishchenko committed
240 241
    assert( Abc_NtkIsStrash(pNtk1) );
    assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) ); 
Alan Mishchenko committed
242 243 244 245 246
    if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) )
    {
        printf( "Converting to AIGs has failed.\n" );
        return 0;
    }
Alan Mishchenko committed
247 248
    // check that the networks have the same PIs
    // reorder PIs of pNtk2 according to pNtk1
Alan Mishchenko committed
249 250
    if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) )
        printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" );
Alan Mishchenko committed
251
    // perform strashing
Alan Mishchenko committed
252
    nNewCis = 0;
Alan Mishchenko committed
253
    Abc_NtkCleanCopy( pNtk2 );
Alan Mishchenko committed
254 255
    if ( Abc_NtkIsStrash(pNtk2) )
        Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1);
Alan Mishchenko committed
256
    Abc_NtkForEachCi( pNtk2, pObj, i )
Alan Mishchenko committed
257 258 259 260 261 262 263 264 265 266 267
    {
        pName = Abc_ObjName(pObj);
        pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
        if ( pObj->pCopy == NULL )
        {
            pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1);
            nNewCis++;
        }
    }
    if ( nNewCis )
        printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
Alan Mishchenko committed
268
    // add pNtk2 to pNtk1 while strashing
Alan Mishchenko committed
269 270 271 272
    if ( Abc_NtkIsLogic(pNtk2) )
        Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 );
    else
        Abc_NtkForEachNode( pNtk2, pObj, i )
273
            pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
Alan Mishchenko committed
274 275 276 277 278 279 280
    // add the COs of the second network
    if ( fAddPos )
    {
        Abc_NtkForEachPo( pNtk2, pObj, i )
        {
            Abc_NtkDupObj( pNtk1, pObj, 0 );
            Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
Alan Mishchenko committed
281
            Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
Alan Mishchenko committed
282 283 284 285 286 287 288 289 290 291
        }
    }
    else
    {
        Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
        int fCompl, iNodeId;
        // OR the choices
        Abc_NtkForEachCo( pNtk2, pObj, i )
        {
            iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
Alan Mishchenko committed
292 293
//            if ( iNodeId < 0 )
//                continue;
Alan Mishchenko committed
294 295 296 297 298
            assert( iNodeId >= 0 );
            pObjOld = Abc_NtkObj( pNtk1, iNodeId );
            // derive the new driver
            pDriverOld = Abc_ObjChild0( pObjOld );
            pDriverNew = Abc_ObjChild0Copy( pObj );
299
            pDriverNew = Abc_AigOr( (Abc_Aig_t *)pNtk1->pManFunc, pDriverOld, pDriverNew );
Alan Mishchenko committed
300 301 302 303 304 305 306
            if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) )
                continue;
            // replace the old driver by the new driver
            fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase;
            Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) );
        }
    }
Alan Mishchenko committed
307
    // make sure that everything is okay
Alan Mishchenko committed
308
    if ( !Abc_NtkCheck( pNtk1 ) )
Alan Mishchenko committed
309 310 311 312 313 314 315 316 317
    {
        printf( "Abc_NtkAppend: The network check has failed.\n" );
        return 0;
    }
    return 1;
}

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

Alan Mishchenko committed
318 319 320 321 322 323 324 325 326
  Synopsis    [Prepares the network for strashing.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
327
void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
Alan Mishchenko committed
328
{
Alan Mishchenko committed
329
//    ProgressBar * pProgress;
Alan Mishchenko committed
330
    Vec_Ptr_t * vNodes;
Alan Mishchenko committed
331
    Abc_Obj_t * pNodeOld;
Alan Mishchenko committed
332
    int i; //, clk = clock();
Alan Mishchenko committed
333 334 335 336 337
    assert( Abc_NtkIsLogic(pNtkOld) );
    assert( Abc_NtkIsStrash(pNtkNew) );
//    vNodes = Abc_NtkDfs( pNtkOld, fAllNodes );
    vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes );
//printf( "Nodes = %d. ", Vec_PtrSize(vNodes) );
Alan Mishchenko committed
338
//ABC_PRT( "Time", clock() - clk );
Alan Mishchenko committed
339
//    pProgress = Extra_ProgressBarStart( stdout, vNodes->nSize );
340
    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNodeOld, i )
Alan Mishchenko committed
341
    {
Alan Mishchenko committed
342
//        Extra_ProgressBarUpdate( pProgress, i, NULL );
Alan Mishchenko committed
343
        pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
Alan Mishchenko committed
344
    }
Alan Mishchenko committed
345
//    Extra_ProgressBarStop( pProgress );
Alan Mishchenko committed
346
    Vec_PtrFree( vNodes );
Alan Mishchenko committed
347 348 349 350
}

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

Alan Mishchenko committed
351
  Synopsis    [Transfers the AIG from one manager into another.]
Alan Mishchenko committed
352 353 354 355 356 357 358 359

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
360
void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj )
Alan Mishchenko committed
361
{
Alan Mishchenko committed
362 363 364 365 366 367 368 369 370 371 372
    assert( !Hop_IsComplement(pObj) );
    if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
        return;
    Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) ); 
    Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) );
    pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
    assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
    Hop_ObjSetMarkA( pObj );
}

/**Function*************************************************************
Alan Mishchenko committed
373

Alan Mishchenko committed
374
  Synopsis    [Strashes one logic node.]
Alan Mishchenko committed
375

Alan Mishchenko committed
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
  Description [Assume the network is in the AIG form]
               
  SideEffects []
 
  SeeAlso     []

***********************************************************************/
Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord )
{
    Hop_Man_t * pMan;
    Hop_Obj_t * pRoot;
    Abc_Obj_t * pFanin;
    int i;
    assert( Abc_ObjIsNode(pNodeOld) );
    assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) );
    // get the local AIG manager and the local root node
392 393
    pMan = (Hop_Man_t *)pNodeOld->pNtk->pManFunc;
    pRoot = (Hop_Obj_t *)pNodeOld->pData;
Alan Mishchenko committed
394 395 396 397
    // check the constant case
    if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
        return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) );
    // perform special case-strashing using the record of AIG subgraphs
Alan Mishchenko committed
398
/*
Alan Mishchenko committed
399
    if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() )
Alan Mishchenko committed
400
    {
Alan Mishchenko committed
401 402 403 404
        extern Vec_Int_t * Abc_NtkRecMemory();
        extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars );
        int nVars = Abc_NtkRecVarNum();
        Vec_Int_t * vMemory = Abc_NtkRecMemory();
Alan Mishchenko committed
405
        unsigned * pTruth = Hop_ManConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 );
Alan Mishchenko committed
406 407 408 409 410
        assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept
        if ( Hop_IsComplement(pRoot) )
            Extra_TruthNot( pTruth, pTruth, nVars );
        if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) )
            return pNodeOld->pCopy;
Alan Mishchenko committed
411
    }
Alan Mishchenko committed
412
*/
Alan Mishchenko committed
413 414 415 416
    // set elementary variables
    Abc_ObjForEachFanin( pNodeOld, pFanin, i )
        Hop_IthVar(pMan, i)->pData = pFanin->pCopy;
    // strash the AIG of this node
417
    Abc_NodeStrash_rec( (Abc_Aig_t *)pNtkNew->pManFunc, Hop_Regular(pRoot) );
Alan Mishchenko committed
418 419
    Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
    // return the final node
420
    return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
Alan Mishchenko committed
421 422 423 424
}



Alan Mishchenko committed
425

Alan Mishchenko committed
426

Alan Mishchenko committed
427 428 429 430


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

Alan Mishchenko committed
431
  Synopsis    [Copies the topmost levels of the network.]
Alan Mishchenko committed
432 433 434 435 436 437 438 439

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
440
Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut )
Alan Mishchenko committed
441
{
Alan Mishchenko committed
442 443 444 445 446 447 448
    assert( !Abc_ObjIsComplement(pNode) );
    if ( pNode->pCopy )
        return pNode->pCopy;
    if ( pNode->Level <= (unsigned)LevelCut )
        return pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
    Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut );
    Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut );
449
    return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
Alan Mishchenko committed
450 451 452 453
}

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

Alan Mishchenko committed
454
  Synopsis    [Copies the topmost levels of the network.]
Alan Mishchenko committed
455 456 457 458 459 460 461 462

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Alan Mishchenko committed
463
Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels )
Alan Mishchenko committed
464
{
Alan Mishchenko committed
465
    Abc_Ntk_t * pNtkNew;
Alan Mishchenko committed
466
    Abc_Obj_t * pObjNew, * pObjPo;
Alan Mishchenko committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480
    int LevelCut;
    assert( Abc_NtkIsStrash(pNtk) );
    assert( Abc_NtkCoNum(pNtk) == 1 );
    // get the cutoff level
    LevelCut = ABC_MAX( 0, Abc_AigLevel(pNtk) - nLevels );
    // start the network
    pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
    pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
    // create PIs below the cut and nodes above the cut
    Abc_NtkCleanCopy( pNtk );
    pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut );
    pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) );
    // add the PO node and name
Alan Mishchenko committed
481 482
    pObjPo = Abc_NtkCreatePo(pNtkNew);
    Abc_ObjAddFanin( pObjPo, pObjNew );
Alan Mishchenko committed
483
    Abc_NtkAddDummyPiNames( pNtkNew );
Alan Mishchenko committed
484
    Abc_ObjAssignName( pObjPo, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL );
Alan Mishchenko committed
485 486 487 488 489 490 491 492
    // make sure everything is okay
    if ( !Abc_NtkCheck( pNtkNew ) )
    {
        printf( "Abc_NtkTopmost: The network check has failed.\n" );
        Abc_NtkDelete( pNtkNew );
        return NULL;
    }
    return pNtkNew;
Alan Mishchenko committed
493 494
}

Alan Mishchenko committed
495

Alan Mishchenko committed
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537

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

  Synopsis    [Comparison procedure for two integers.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
static int Vec_CompareNodeIds( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
{
    if ( Abc_ObjRegular(*pp1)->Id < Abc_ObjRegular(*pp2)->Id )
        return -1;
    if ( Abc_ObjRegular(*pp1)->Id > Abc_ObjRegular(*pp2)->Id ) //
        return 1;
    return 0; 
}

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

  Synopsis    [Collects the large supergate.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Vec_Ptr_t * Abc_NodeGetSuper( Abc_Obj_t * pNode )
{
    Vec_Ptr_t * vSuper, * vFront;
    Abc_Obj_t * pAnd, * pFanin;
    int i;
    assert( Abc_ObjIsNode(pNode) && !Abc_ObjIsComplement(pNode) );
    vSuper = Vec_PtrAlloc( 100 ); 
    // explore the frontier
    vFront = Vec_PtrAlloc( 100 );
    Vec_PtrPush( vFront, pNode );
538
    Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pAnd, i )
Alan Mishchenko committed
539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554
    {
        pFanin = Abc_ObjChild0(pAnd);
        if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
            Vec_PtrPush( vFront, pFanin );
        else
            Vec_PtrPush( vSuper, pFanin );

        pFanin = Abc_ObjChild1(pAnd);
        if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
            Vec_PtrPush( vFront, pFanin );
        else
            Vec_PtrPush( vSuper, pFanin );
    }
    Vec_PtrFree( vFront );
    // reverse the array of pointers to start with lower IDs
    vFront = Vec_PtrAlloc( Vec_PtrSize(vSuper) );
555
    Vec_PtrForEachEntryReverse( Abc_Obj_t *, vSuper, pNode, i )
Alan Mishchenko committed
556 557 558 559
        Vec_PtrPush( vFront, pNode );
    Vec_PtrFree( vSuper );
    vSuper = vFront;
    // uniquify and return the frontier
560
    Vec_PtrUniqify( vSuper, (int (*)())Vec_CompareNodeIds );
Alan Mishchenko committed
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
    return vSuper;
}

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

  Synopsis    [Copies the topmost levels of the network.]

  Description []
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk )
{
    Vec_Ptr_t * vNodes, * vOrder;
    Abc_Ntk_t * pNtkAig;
    Abc_Obj_t * pObj, * pDriver, * pObjPo;
    int i, nNodes;
    assert( Abc_NtkIsStrash(pNtk) );
    // get the first PO
    pObjPo = Abc_NtkPo(pNtk, 0);
    vNodes = Abc_NodeGetSuper( Abc_ObjChild0(pObjPo) );
    assert( Vec_PtrSize(vNodes) >= 2 );
    // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
    Abc_NtkCleanCopy( pNtk );
    pNtkAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
    pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
    pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
    Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkAig);
    Abc_NtkForEachPi( pNtk, pObj, i )
        Abc_NtkDupObj( pNtkAig, pObj, 1 );
    // restrash the nodes reachable from the roots
    vOrder = Abc_NtkDfsIterNodes( pNtk, vNodes );
596 597
    Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
        pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
Alan Mishchenko committed
598 599
    Vec_PtrFree( vOrder );
    // finalize the network
600
    Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
Alan Mishchenko committed
601 602 603 604 605 606 607 608
    {
        pObjPo = Abc_NtkCreatePo(pNtkAig);
        pDriver = Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj));
        Abc_ObjAddFanin( pObjPo, pDriver );
        Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL );
    }
    Vec_PtrFree( vNodes );
    // perform cleanup if requested
609
    if ( (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) ) 
Alan Mishchenko committed
610 611 612 613 614 615 616 617 618 619 620
        printf( "Abc_NtkTopAnd(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
    // make sure everything is okay
    if ( !Abc_NtkCheck( pNtkAig ) )
    {
        printf( "Abc_NtkStrash: The network check has failed.\n" );
        Abc_NtkDelete( pNtkAig );
        return NULL;
    }
    return pNtkAig;
}

621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
/**Function*************************************************************

  Synopsis    [Writes the AIG into a file for parsing.]

  Description [Ordering: c0, pis, ands, pos. ]
               
  SideEffects []

  SeeAlso     []

***********************************************************************/
void Abc_NtkWriteAig( Abc_Ntk_t * pNtk, char * pFileName )
{
    FILE * pFile;
    Vec_Int_t * vId2Num;
    Abc_Obj_t * pObj;
    int i, iLit;
    assert( Abc_NtkIsStrash(pNtk) );
    assert( Abc_NtkLatchNum(pNtk) == 0 );
    if ( pFileName == NULL )
        pFile = stdout;
    else
        pFile = fopen( pFileName, "w" );
    if ( pFile == NULL )
    {
        printf( "Cannot open output file.\n" );
        return;
    }
    vId2Num = Vec_IntAlloc( 2*Abc_NtkObjNumMax(pNtk) );
    Vec_IntFill( vId2Num, 2*Abc_NtkObjNumMax(pNtk), -1 );

    iLit = 0;
    Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+1, iLit++ );
    Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+0, iLit++ );
    Abc_NtkForEachPi( pNtk, pObj, i )
    {
        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ );
        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ );
    }
    Abc_AigForEachAnd( pNtk, pObj, i )
    {
        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ );
        Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ );
    }
    fprintf( pFile, "{\n" );
    fprintf( pFile, "    \"%s\", ", Abc_NtkName(pNtk) );
    fprintf( pFile, "//  pi=%d  po=%d  and=%d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) );
    fprintf( pFile, "\n" );
    fprintf( pFile, "    { " );
    Abc_NtkForEachPi( pNtk, pObj, i )
        fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) );
    fprintf( pFile, "NULL },\n" );
    fprintf( pFile, "    { " );
    Abc_NtkForEachPo( pNtk, pObj, i )
        fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) );
    fprintf( pFile, "NULL },\n" );
    fprintf( pFile, "    { " );
    Abc_AigForEachAnd( pNtk, pObj, i )
        fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) );
    fprintf( pFile, "0 },\n" );
    fprintf( pFile, "    { " );
    Abc_AigForEachAnd( pNtk, pObj, i )
        fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId1(pObj) + Abc_ObjFaninC1(pObj)) );
    fprintf( pFile, "0 },\n" );
    fprintf( pFile, "    { " );
    Abc_NtkForEachPo( pNtk, pObj, i )
        fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) );
    fprintf( pFile, "0 },\n" );
    fprintf( pFile, "},\n" );
    if ( pFile != stdout )
        fclose( pFile );
    Vec_IntFree( vId2Num );
}


Alan Mishchenko committed
696 697 698 699 700
////////////////////////////////////////////////////////////////////////
///                       END OF FILE                                ///
////////////////////////////////////////////////////////////////////////


701 702
ABC_NAMESPACE_IMPL_END