summaryrefslogtreecommitdiffstats
path: root/src/aig/ivy/ivyMan.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/aig/ivy/ivyMan.c')
-rw-r--r--src/aig/ivy/ivyMan.c546
1 files changed, 546 insertions, 0 deletions
diff --git a/src/aig/ivy/ivyMan.c b/src/aig/ivy/ivyMan.c
new file mode 100644
index 00000000..2d99c4f1
--- /dev/null
+++ b/src/aig/ivy/ivyMan.c
@@ -0,0 +1,546 @@
+/**CFile****************************************************************
+
+ FileName [ivyMan.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [And-Inverter Graph package.]
+
+ Synopsis [AIG manager.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - May 11, 2006.]
+
+ Revision [$Id: ivy_.c,v 1.00 2006/05/11 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "ivy.h"
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis [Starts the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManStart()
+{
+ Ivy_Man_t * p;
+ // start the manager
+ p = ALLOC( Ivy_Man_t, 1 );
+ memset( p, 0, sizeof(Ivy_Man_t) );
+ // perform initializations
+ p->Ghost.Id = -1;
+ p->nTravIds = 1;
+ p->fCatchExor = 1;
+ // allocate arrays for nodes
+ p->vPis = Vec_PtrAlloc( 100 );
+ p->vPos = Vec_PtrAlloc( 100 );
+ p->vBufs = Vec_PtrAlloc( 100 );
+ p->vObjs = Vec_PtrAlloc( 100 );
+ // prepare the internal memory manager
+ Ivy_ManStartMemory( p );
+ // create the constant node
+ p->pConst1 = Ivy_ManFetchMemory( p );
+ p->pConst1->fPhase = 1;
+ Vec_PtrPush( p->vObjs, p->pConst1 );
+ p->nCreated = 1;
+ // start the table
+ p->nTableSize = 10007;
+ p->pTable = ALLOC( int, p->nTableSize );
+ memset( p->pTable, 0, sizeof(int) * p->nTableSize );
+ return p;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManStartFrom( Ivy_Man_t * p )
+{
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj;
+ int i;
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // create the PIs
+ Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew);
+ Ivy_ManForEachPi( p, pObj, i )
+ pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Duplicates the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManDup( Ivy_Man_t * p )
+{
+ Vec_Int_t * vNodes, * vLatches;
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj;
+ int i;
+ // collect latches and nodes in the DFS order
+ vNodes = Ivy_ManDfsSeq( p, &vLatches );
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // create the PIs
+ Ivy_ManConst1(p)->pEquiv = Ivy_ManConst1(pNew);
+ Ivy_ManForEachPi( p, pObj, i )
+ pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+ // create the fake PIs for latches
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ pObj->pEquiv = Ivy_ObjCreatePi(pNew);
+ // duplicate internal nodes
+ Ivy_ManForEachNodeVec( p, vNodes, pObj, i )
+ if ( Ivy_ObjIsBuf(pObj) )
+ pObj->pEquiv = Ivy_ObjChild0Equiv(pObj);
+ else
+ pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ // add the POs
+ Ivy_ManForEachPo( p, pObj, i )
+ Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(pObj) );
+ // transform additional PI nodes into latches and connect them
+ Ivy_ManForEachNodeVec( p, vLatches, pObj, i )
+ {
+ assert( !Ivy_ObjFaninC0(pObj) );
+ pObj->pEquiv->Type = IVY_LATCH;
+ pObj->pEquiv->Init = pObj->Init;
+ Ivy_ObjConnect( pNew, pObj->pEquiv, Ivy_ObjChild0Equiv(pObj), NULL );
+ }
+ // shrink the arrays
+ Vec_PtrShrink( pNew->vPis, Ivy_ManPiNum(p) );
+ // update the counters of different objects
+ pNew->nObjs[IVY_PI] -= Ivy_ManLatchNum(p);
+ pNew->nObjs[IVY_LATCH] += Ivy_ManLatchNum(p);
+ // free arrays
+ Vec_IntFree( vNodes );
+ Vec_IntFree( vLatches );
+ // make sure structural hashing did not change anything
+ assert( Ivy_ManNodeNum(p) == Ivy_ManNodeNum(pNew) );
+ assert( Ivy_ManLatchNum(p) == Ivy_ManLatchNum(pNew) );
+ // check the resulting network
+ if ( !Ivy_ManCheck(pNew) )
+ printf( "Ivy_ManMakeSeq(): The check has failed.\n" );
+ return pNew;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Ivy_Man_t * Ivy_ManFrames( Ivy_Man_t * pMan, int nLatches, int nFrames, int fInit, Vec_Ptr_t ** pvMapping )
+{
+ Vec_Ptr_t * vMapping;
+ Ivy_Man_t * pNew;
+ Ivy_Obj_t * pObj;
+ int i, f, nPis, nPos, nIdMax;
+ assert( Ivy_ManLatchNum(pMan) == 0 );
+ assert( nFrames > 0 );
+ // prepare the mapping
+ nPis = Ivy_ManPiNum(pMan) - nLatches;
+ nPos = Ivy_ManPoNum(pMan) - nLatches;
+ nIdMax = Ivy_ManObjIdMax(pMan);
+ // create the new manager
+ pNew = Ivy_ManStart();
+ // set the starting values of latch inputs
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ManPo(pMan, nPos+i)->pEquiv = fInit? Ivy_Not(Ivy_ManConst1(pNew)) : Ivy_ObjCreatePi(pNew);
+ // add timeframes
+ vMapping = Vec_PtrStart( nIdMax * nFrames + 1 );
+ for ( f = 0; f < nFrames; f++ )
+ {
+ // create PIs
+ Ivy_ManConst1(pMan)->pEquiv = Ivy_ManConst1(pNew);
+ for ( i = 0; i < nPis; i++ )
+ Ivy_ManPi(pMan, i)->pEquiv = Ivy_ObjCreatePi(pNew);
+ // transfer values to latch outputs
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ManPi(pMan, nPis+i)->pEquiv = Ivy_ManPo(pMan, nPos+i)->pEquiv;
+ // perform strashing
+ Ivy_ManForEachNode( pMan, pObj, i )
+ pObj->pEquiv = Ivy_And( pNew, Ivy_ObjChild0Equiv(pObj), Ivy_ObjChild1Equiv(pObj) );
+ // create POs
+ for ( i = 0; i < nPos; i++ )
+ Ivy_ManPo(pMan, i)->pEquiv = Ivy_ObjCreatePo( pNew, Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, i)) );
+ // set the results of latch inputs
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ManPo(pMan, nPos+i)->pEquiv = Ivy_ObjChild0Equiv(Ivy_ManPo(pMan, nPos+i));
+ // save the pointers in this frame
+ Ivy_ManForEachObj( pMan, pObj, i )
+ Vec_PtrWriteEntry( vMapping, f * nIdMax + i, pObj->pEquiv );
+ }
+ // connect latches
+ if ( !fInit )
+ for ( i = 0; i < nLatches; i++ )
+ Ivy_ObjCreatePo( pNew, Ivy_ManPo(pMan, nPos+i)->pEquiv );
+ // remove dangling nodes
+ Ivy_ManCleanup(pNew);
+ *pvMapping = vMapping;
+ // check the resulting network
+ if ( !Ivy_ManCheck(pNew) )
+ printf( "Ivy_ManFrames(): The check has failed.\n" );
+ return pNew;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Stops the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManStop( Ivy_Man_t * p )
+{
+ if ( p->time1 ) { PRT( "Update lev ", p->time1 ); }
+ if ( p->time2 ) { PRT( "Update levR ", p->time2 ); }
+// Ivy_TableProfile( p );
+// if ( p->vFanouts ) Ivy_ManStopFanout( p );
+ if ( p->vChunks ) Ivy_ManStopMemory( p );
+ if ( p->vRequired ) Vec_IntFree( p->vRequired );
+ if ( p->vPis ) Vec_PtrFree( p->vPis );
+ if ( p->vPos ) Vec_PtrFree( p->vPos );
+ if ( p->vBufs ) Vec_PtrFree( p->vBufs );
+ if ( p->vObjs ) Vec_PtrFree( p->vObjs );
+ free( p->pTable );
+ free( p );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes nodes without fanout.]
+
+ Description [Returns the number of dangling nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCleanup( Ivy_Man_t * p )
+{
+ Ivy_Obj_t * pNode;
+ int i, nNodesOld;
+ nNodesOld = Ivy_ManNodeNum(p);
+ Ivy_ManForEachObj( p, pNode, i )
+ if ( Ivy_ObjIsNode(pNode) || Ivy_ObjIsLatch(pNode) || Ivy_ObjIsBuf(pNode) )
+ if ( Ivy_ObjRefs(pNode) == 0 )
+ Ivy_ObjDelete_rec( p, pNode, 1 );
+//printf( "Cleanup removed %d nodes.\n", nNodesOld - Ivy_ManNodeNum(p) );
+ return nNodesOld - Ivy_ManNodeNum(p);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Marks nodes reachable from the given one.]
+
+ Description [Returns the number of dangling nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManCleanupSeq_rec( Ivy_Obj_t * pObj )
+{
+ if ( Ivy_ObjIsMarkA(pObj) )
+ return;
+ Ivy_ObjSetMarkA(pObj);
+ if ( pObj->pFanin0 != NULL )
+ Ivy_ManCleanupSeq_rec( Ivy_ObjFanin0(pObj) );
+ if ( pObj->pFanin1 != NULL )
+ Ivy_ManCleanupSeq_rec( Ivy_ObjFanin1(pObj) );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Removes logic that does not feed into POs.]
+
+ Description [Returns the number of dangling nodes removed.]
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManCleanupSeq( Ivy_Man_t * p )
+{
+ Vec_Ptr_t * vNodes;
+ Ivy_Obj_t * pObj;
+ int i, RetValue;
+ // mark the constant and PIs
+ Ivy_ObjSetMarkA( Ivy_ManConst1(p) );
+ Ivy_ManForEachPi( p, pObj, i )
+ Ivy_ObjSetMarkA( pObj );
+ // mark nodes visited from POs
+ Ivy_ManForEachPo( p, pObj, i )
+ Ivy_ManCleanupSeq_rec( pObj );
+ // collect unmarked nodes
+ vNodes = Vec_PtrAlloc( 100 );
+ Ivy_ManForEachObj( p, pObj, i )
+ {
+ if ( Ivy_ObjIsMarkA(pObj) )
+ Ivy_ObjClearMarkA(pObj);
+ else
+ Vec_PtrPush( vNodes, pObj );
+ }
+ if ( Vec_PtrSize(vNodes) == 0 )
+ {
+ Vec_PtrFree( vNodes );
+//printf( "Sequential sweep cleaned out %d nodes.\n", 0 );
+ return 0;
+ }
+ // disconnect the marked objects
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ Ivy_ObjDisconnect( p, pObj );
+ // remove the dangling objects
+ Vec_PtrForEachEntry( vNodes, pObj, i )
+ {
+ assert( Ivy_ObjIsNode(pObj) || Ivy_ObjIsLatch(pObj) || Ivy_ObjIsBuf(pObj) );
+ assert( Ivy_ObjRefs(pObj) == 0 );
+ // update node counters of the manager
+ p->nObjs[pObj->Type]--;
+ p->nDeleted++;
+ // delete buffer from the array of buffers
+ if ( p->fFanout && Ivy_ObjIsBuf(pObj) )
+ Vec_PtrRemove( p->vBufs, pObj );
+ // free the node
+ Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+ Ivy_ManRecycleMemory( p, pObj );
+ }
+ // return the number of nodes freed
+ RetValue = Vec_PtrSize(vNodes);
+ Vec_PtrFree( vNodes );
+//printf( "Sequential sweep cleaned out %d nodes.\n", RetValue );
+ return RetValue;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Checks if latches form self-loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManLatchIsSelfFeed_rec( Ivy_Obj_t * pLatch, Ivy_Obj_t * pLatchRoot )
+{
+ if ( !Ivy_ObjIsLatch(pLatch) && !Ivy_ObjIsBuf(pLatch) )
+ return 0;
+ if ( pLatch == pLatchRoot )
+ return 1;
+ return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatchRoot );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Checks if latches form self-loop.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManLatchIsSelfFeed( Ivy_Obj_t * pLatch )
+{
+ if ( !Ivy_ObjIsLatch(pLatch) )
+ return 0;
+ return Ivy_ManLatchIsSelfFeed_rec( Ivy_ObjFanin0(pLatch), pLatch );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Returns the number of dangling nodes removed.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Ivy_ManPropagateBuffers( Ivy_Man_t * p, int fUpdateLevel )
+{
+ Ivy_Obj_t * pNode;
+ int LimitFactor = 10;
+ int NodeBeg = Ivy_ManNodeNum(p);
+ int nSteps;
+ for ( nSteps = 0; Vec_PtrSize(p->vBufs) > 0; nSteps++ )
+ {
+ pNode = Vec_PtrEntryLast(p->vBufs);
+ while ( Ivy_ObjIsBuf(pNode) )
+ pNode = Ivy_ObjReadFirstFanout( p, pNode );
+ // check if this buffer should remain
+ if ( Ivy_ManLatchIsSelfFeed(pNode) )
+ {
+ Vec_PtrPop(p->vBufs);
+ continue;
+ }
+//printf( "Propagating buffer %d with input %d and output %d\n", Ivy_ObjFaninId0(pNode), Ivy_ObjFaninId0(Ivy_ObjFanin0(pNode)), pNode->Id );
+//printf( "Latch num %d\n", Ivy_ManLatchNum(p) );
+ Ivy_NodeFixBufferFanins( p, pNode, fUpdateLevel );
+ if ( nSteps > NodeBeg * LimitFactor )
+ {
+ printf( "Structural hashing is not finished after %d forward latch moves.\n", NodeBeg * LimitFactor );
+ printf( "This circuit cannot be forward-retimed completely. Quitting.\n" );
+ break;
+ }
+ }
+// printf( "Number of steps = %d. Nodes beg = %d. Nodes end = %d.\n", nSteps, NodeBeg, Ivy_ManNodeNum(p) );
+ return nSteps;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Stops the AIG manager.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManPrintStats( Ivy_Man_t * p )
+{
+ printf( "PI/PO = %d/%d ", Ivy_ManPiNum(p), Ivy_ManPoNum(p) );
+ printf( "A = %7d. ", Ivy_ManAndNum(p) );
+ printf( "L = %5d. ", Ivy_ManLatchNum(p) );
+// printf( "X = %d. ", Ivy_ManExorNum(p) );
+// printf( "B = %3d. ", Ivy_ManBufNum(p) );
+ printf( "MaxID = %7d. ", Ivy_ManObjIdMax(p) );
+// printf( "Cre = %d. ", p->nCreated );
+// printf( "Del = %d. ", p->nDeleted );
+ printf( "Lev = %3d. ", Ivy_ManLatchNum(p)? -1 : Ivy_ManLevels(p) );
+ printf( "\n" );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Converts a combinational AIG manager into a sequential one.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Ivy_ManMakeSeq( Ivy_Man_t * p, int nLatches, int * pInits )
+{
+ Ivy_Obj_t * pObj, * pLatch;
+ Ivy_Init_t Init;
+ int i;
+ if ( nLatches == 0 )
+ return;
+ assert( nLatches < Ivy_ManPiNum(p) && nLatches < Ivy_ManPoNum(p) );
+ assert( Ivy_ManPiNum(p) == Vec_PtrSize(p->vPis) );
+ assert( Ivy_ManPoNum(p) == Vec_PtrSize(p->vPos) );
+ assert( Vec_PtrSize( p->vBufs ) == 0 );
+ // create fanouts
+ if ( p->fFanout == 0 )
+ Ivy_ManStartFanout( p );
+ // collect the POs to be converted into latches
+ for ( i = 0; i < nLatches; i++ )
+ {
+ // get the latch value
+ Init = pInits? pInits[i] : IVY_INIT_0;
+ // create latch
+ pObj = Ivy_ManPo( p, Ivy_ManPoNum(p) - nLatches + i );
+ pLatch = Ivy_Latch( p, Ivy_ObjChild0(pObj), Init );
+ Ivy_ObjDisconnect( p, pObj );
+ // recycle the old PO object
+ Vec_PtrWriteEntry( p->vObjs, pObj->Id, NULL );
+ Ivy_ManRecycleMemory( p, pObj );
+ // convert the corresponding PI to a buffer and connect it to the latch
+ pObj = Ivy_ManPi( p, Ivy_ManPiNum(p) - nLatches + i );
+ pObj->Type = IVY_BUF;
+ Ivy_ObjConnect( p, pObj, pLatch, NULL );
+ // save the buffer
+ Vec_PtrPush( p->vBufs, pObj );
+ }
+ // shrink the arrays
+ Vec_PtrShrink( p->vPis, Ivy_ManPiNum(p) - nLatches );
+ Vec_PtrShrink( p->vPos, Ivy_ManPoNum(p) - nLatches );
+ // update the counters of different objects
+ p->nObjs[IVY_PI] -= nLatches;
+ p->nObjs[IVY_PO] -= nLatches;
+ p->nObjs[IVY_BUF] += nLatches;
+ p->nDeleted -= 2 * nLatches;
+ // remove dangling nodes
+ Ivy_ManCleanup(p);
+ Ivy_ManCleanupSeq(p);
+/*
+ // check for dangling nodes
+ Ivy_ManForEachObj( p, pObj, i )
+ if ( !Ivy_ObjIsPi(pObj) && !Ivy_ObjIsPo(pObj) && !Ivy_ObjIsConst1(pObj) )
+ {
+ assert( Ivy_ObjRefs(pObj) > 0 );
+ assert( Ivy_ObjRefs(pObj) == Ivy_ObjFanoutNum(p, pObj) );
+ }
+*/
+ // perform hashing by propagating the buffers
+ Ivy_ManPropagateBuffers( p, 0 );
+ if ( Ivy_ManBufNum(p) )
+ printf( "The number of remaining buffers is %d.\n", Ivy_ManBufNum(p) );
+ // fix the levels
+ Ivy_ManResetLevels( p );
+ // check the resulting network
+ if ( !Ivy_ManCheck(p) )
+ printf( "Ivy_ManMakeSeq(): The check has failed.\n" );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+