summaryrefslogtreecommitdiffstats
path: root/src/aig/gia/giaShrink6.c
diff options
context:
space:
mode:
authorAlan Mishchenko <alanmi@berkeley.edu>2013-03-31 23:09:51 -0700
committerAlan Mishchenko <alanmi@berkeley.edu>2013-03-31 23:09:51 -0700
commit2650f945986192f78af049fc8c11e4be0b327f8b (patch)
tree465a6a8bd54717bf578818778d6523163a46c481 /src/aig/gia/giaShrink6.c
parent017c35baf22da739f29bcafbda2063640bd1e82d (diff)
downloadabc-2650f945986192f78af049fc8c11e4be0b327f8b.tar.gz
abc-2650f945986192f78af049fc8c11e4be0b327f8b.tar.bz2
abc-2650f945986192f78af049fc8c11e4be0b327f8b.zip
Shrink for 6-LUTs.
Diffstat (limited to 'src/aig/gia/giaShrink6.c')
-rw-r--r--src/aig/gia/giaShrink6.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/src/aig/gia/giaShrink6.c b/src/aig/gia/giaShrink6.c
new file mode 100644
index 00000000..0d7f7541
--- /dev/null
+++ b/src/aig/gia/giaShrink6.c
@@ -0,0 +1,481 @@
+/**CFile****************************************************************
+
+ FileName [giaShrink6.c]
+
+ SystemName [ABC: Logic synthesis and verification system.]
+
+ PackageName [Scalable AIG package.]
+
+ Synopsis [Implementation of DAG-aware unmapping for 6-input cuts.]
+
+ Author [Alan Mishchenko]
+
+ Affiliation [UC Berkeley]
+
+ Date [Ver. 1.0. Started - June 20, 2005.]
+
+ Revision [$Id: giaShrink6.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
+
+***********************************************************************/
+
+#include "gia.h"
+#include "bool/bdc/bdc.h"
+#include "bool/rsb/rsb.h"
+//#include "misc/util/utilTruth.h"
+
+ABC_NAMESPACE_IMPL_START
+
+////////////////////////////////////////////////////////////////////////
+/// DECLARATIONS ///
+////////////////////////////////////////////////////////////////////////
+
+static word Truth[8] = {
+ ABC_CONST(0xAAAAAAAAAAAAAAAA),
+ ABC_CONST(0xCCCCCCCCCCCCCCCC),
+ ABC_CONST(0xF0F0F0F0F0F0F0F0),
+ ABC_CONST(0xFF00FF00FF00FF00),
+ ABC_CONST(0xFFFF0000FFFF0000),
+ ABC_CONST(0xFFFFFFFF00000000),
+ ABC_CONST(0x0000000000000000),
+ ABC_CONST(0xFFFFFFFFFFFFFFFF)
+};
+
+// fanout structure
+typedef struct Shr_Fan_t_ Shr_Fan_t;
+struct Shr_Fan_t_
+{
+ int iFan; // fanout ID
+ int Next; // next structure
+};
+
+// operation manager
+typedef struct Shr_Man_t_ Shr_Man_t;
+struct Shr_Man_t_
+{
+ Gia_Man_t * pGia; // user's AIG
+ Gia_Man_t * pNew; // constructed AIG
+ int nDivMax; // max number of divisors
+ int nNewSize; // max growth size
+ // dynamic fanout (can only grow)
+ Vec_Wrd_t * vFanMem; // fanout memory
+ Vec_Int_t * vObj2Fan; // fanout
+ Shr_Fan_t * pFanTemp; // temporary fanout
+ // divisors
+ Vec_Int_t * vDivs; // divisors
+ Vec_Int_t * vPrio; // priority queue
+ Vec_Int_t * vDivResub; // resubstitution
+ Vec_Int_t * vLeaves; // cut leaves
+ // truth tables
+ Vec_Wrd_t * vTruths; // truth tables
+ Vec_Wrd_t * vDivTruths; // truth tables
+ // bidecomposition
+ Rsb_Man_t * pManRsb;
+ Bdc_Man_t * pManDec;
+ Bdc_Par_t Pars;
+};
+
+#define Shr_ObjForEachFanout( p, iNode, iFan ) \
+ for ( iFan = Shr_ManFanIterStart(p, iNode); iFan; iFan = Shr_ManFanIterNext(p) )
+
+////////////////////////////////////////////////////////////////////////
+/// FUNCTION DEFINITIONS ///
+////////////////////////////////////////////////////////////////////////
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Shr_Man_t * Shr_ManAlloc( Gia_Man_t * pGia )
+{
+ Shr_Man_t * p;
+ p = ABC_CALLOC( Shr_Man_t, 1 );
+ p->nDivMax = 64;
+ p->nNewSize = 3 * Gia_ManObjNum(pGia) / 2;
+ p->pGia = pGia;
+ p->vFanMem = Vec_WrdAlloc( 1000 ); Vec_WrdPush(p->vFanMem, -1);
+ p->vObj2Fan = Vec_IntStart( p->nNewSize );
+ p->vDivs = Vec_IntAlloc( 1000 );
+ p->vPrio = Vec_IntAlloc( 1000 );
+ p->vTruths = Vec_WrdStart( p->nNewSize );
+ p->vDivTruths = Vec_WrdAlloc( 100 );
+ p->vDivResub = Vec_IntAlloc( 6 );
+ p->vLeaves = Vec_IntAlloc( 6 );
+ // start new manager
+ p->pNew = Gia_ManStart( p->nNewSize );
+ p->pNew->pName = Abc_UtilStrsav( pGia->pName );
+ p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec );
+ Gia_ManHashAlloc( p->pNew );
+ Gia_ManCleanLevels( p->pNew, p->nNewSize );
+ // allocate traversal IDs
+ p->pNew->nObjs = p->nNewSize;
+ Gia_ManIncrementTravId( p->pNew );
+ p->pNew->nObjs = 1;
+ // start decompostion
+ p->Pars.nVarsMax = 6;
+ p->Pars.fVerbose = 0;
+ p->pManDec = Bdc_ManAlloc( &p->Pars );
+ p->pManRsb = Rsb_ManAlloc( 6, p->nDivMax, 4, 1 );
+ return p;
+}
+Gia_Man_t * Shr_ManFree( Shr_Man_t * p )
+{
+ // prepare the manager
+ Gia_Man_t * pTemp;
+ Gia_ManHashStop( p->pNew );
+ Vec_IntFreeP( &p->pNew->vLevels );
+ if ( Gia_ManHasDangling(p->pNew) )
+ {
+ p->pNew = Gia_ManCleanup( pTemp = p->pNew );
+ if ( Gia_ManAndNum(p->pNew) != Gia_ManAndNum(pTemp) )
+ printf( "Gia_ManShrink6() node reduction after sweep %6d -> %6d.\n", Gia_ManAndNum(pTemp), Gia_ManAndNum(p->pNew) );
+ Gia_ManStop( pTemp );
+ }
+ Gia_ManSetRegNum( p->pNew, Gia_ManRegNum(p->pGia) );
+ pTemp = p->pNew; p->pNew = NULL;
+ // free data structures
+ Rsb_ManFree( p->pManRsb );
+ Bdc_ManFree( p->pManDec );
+ Gia_ManStopP( &p->pNew );
+ Vec_WrdFree( p->vFanMem );
+ Vec_IntFree( p->vObj2Fan );
+ Vec_IntFree( p->vDivs );
+ Vec_IntFree( p->vPrio );
+ Vec_WrdFree( p->vTruths );
+ Vec_WrdFree( p->vDivTruths );
+ Vec_IntFree( p->vDivResub );
+ Vec_IntFree( p->vLeaves );
+ ABC_FREE( p );
+ return pTemp;
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Fanout manipulation.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline void Shr_ManAddFanout( Shr_Man_t * p, int iFanin, int iFanout )
+{
+ Shr_Fan_t FanStr;
+ FanStr.iFan = iFanout;
+ FanStr.Next = Vec_IntEntry(p->vObj2Fan, iFanin);
+ Vec_IntWriteEntry( p->vObj2Fan, iFanin, Vec_WrdSize(p->vFanMem) );
+ Vec_WrdPush(p->vFanMem, *((word *)&FanStr) );
+}
+static inline int Shr_ManFanIterStart( Shr_Man_t * p, int iNode )
+{
+ if ( Vec_IntEntry(p->vObj2Fan, iNode) == 0 )
+ return 0;
+ p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, Vec_IntEntry(p->vObj2Fan, iNode) );
+ return p->pFanTemp->iFan;
+}
+static inline int Shr_ManFanIterNext( Shr_Man_t * p )
+{
+ if ( p->pFanTemp->Next == 0 )
+ return 0;
+ p->pFanTemp = (Shr_Fan_t *)Vec_WrdEntryP( p->vFanMem, p->pFanTemp->Next );
+ return p->pFanTemp->iFan;
+}
+
+/**Function*************************************************************
+
+ Synopsis [Collect divisors.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+static inline int Shr_ManDivPushOrderByLevel( Shr_Man_t * p, int iDiv )
+{
+ int iPlace, * pArray;
+ Vec_IntPush( p->vPrio, iDiv );
+ if ( Vec_IntSize(p->vPrio) == 1 )
+ return 0;
+ pArray = Vec_IntArray(p->vPrio);
+ for ( iPlace = Vec_IntSize(p->vPrio) - 1; iPlace > 0; iPlace-- )
+ if ( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace-1])) >
+ Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, pArray[iPlace])) )
+ ABC_SWAP( int, pArray[iPlace-1], pArray[iPlace] )
+ else
+ break;
+ return iPlace; // the place of the new divisor
+}
+static inline int Shr_ManCollectDivisors( Shr_Man_t * p, Vec_Int_t * vLeaves, int Limit )
+{
+ Gia_Obj_t * pFan;
+ int i, iDiv, iFan, iPlace;
+ assert( Limit > 6 );
+ Vec_IntClear( p->vDivs );
+ Vec_IntClear( p->vPrio );
+ Gia_ManIncrementTravId( p->pNew );
+ Vec_IntForEachEntry( vLeaves, iDiv, i )
+ {
+ Vec_IntPush( p->vDivs, iDiv );
+ Shr_ManDivPushOrderByLevel( p, iDiv );
+ Gia_ObjSetTravIdCurrentId( p->pNew, iDiv );
+ }
+ Vec_IntForEachEntry( p->vPrio, iDiv, i )
+ {
+ assert( Gia_ObjIsTravIdCurrentId(p->pNew, iDiv) );
+ Shr_ObjForEachFanout( p, iDiv, iFan )
+ {
+ if ( Gia_ObjIsTravIdCurrentId(p->pNew, iFan) )
+ continue;
+ pFan = Gia_ManObj( p->pNew, iFan );
+ assert( Gia_ObjIsAnd(pFan) );
+ assert( Gia_ObjLevel(p->pNew, Gia_ManObj(p->pNew, iDiv)) < Gia_ObjLevel(p->pNew, pFan) );
+ if ( !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId0(pFan, iFan)) ||
+ !Gia_ObjIsTravIdCurrentId(p->pNew, Gia_ObjFaninId1(pFan, iFan)) )
+ continue;
+ Vec_IntPush( p->vDivs, iFan );
+ Gia_ObjSetTravIdCurrentId( p->pNew, iFan );
+ iPlace = Shr_ManDivPushOrderByLevel( p, iFan );
+ assert( i < iPlace );
+ if ( Vec_IntSize(p->vDivs) == Limit )
+ return Vec_IntSize(p->vDivs);
+ }
+ }
+ return Vec_IntSize(p->vDivs);
+}
+
+/**Function*************************************************************
+
+ Synopsis [Resynthesizes nodes using bi-decomposition.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+int Shr_ObjPerformBidec( Shr_Man_t * p, Bdc_Man_t * pManDec, Gia_Man_t * pNew, Vec_Int_t * vLeafLits, word uTruth1, word uTruthC )
+{
+ Bdc_Fun_t * pFunc;
+ Gia_Obj_t * pObj;
+ int i, iVar, iLit, nNodes, iLast;
+ int nVars = Vec_IntSize(vLeafLits);
+ assert( uTruth1 != 0 && uTruthC != 0 );
+ Bdc_ManDecompose( pManDec, (unsigned *)&uTruth1, (unsigned *)&uTruthC, nVars, NULL, 1000 );
+ Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, 0), 1 );
+ Vec_IntForEachEntry( vLeafLits, iVar, i )
+ Bdc_FuncSetCopyInt( Bdc_ManFunc(pManDec, i+1), Abc_Var2Lit(iVar, 0) );
+ nNodes = Bdc_ManNodeNum( pManDec );
+ for ( i = nVars + 1; i < nNodes; i++ )
+ {
+ pFunc = Bdc_ManFunc( pManDec, i );
+ iLast = Gia_ManObjNum(pNew);
+ iLit = Gia_ManHashAnd( pNew, Bdc_FunFanin0Copy(pFunc), Bdc_FunFanin1Copy(pFunc) );
+ Bdc_FuncSetCopyInt( pFunc, iLit );
+ if ( iLast == Gia_ManObjNum(pNew) )
+ continue;
+ assert( iLast + 1 == Gia_ManObjNum(pNew) );
+ pObj = Gia_ManObj(pNew, Abc_Lit2Var(iLit));
+ Gia_ObjSetAndLevel( pNew, pObj );
+ Shr_ManAddFanout( p, Gia_ObjFaninId0p(pNew, pObj), Gia_ObjId(pNew, pObj) );
+ Shr_ManAddFanout( p, Gia_ObjFaninId1p(pNew, pObj), Gia_ObjId(pNew, pObj) );
+ assert( Gia_ManObjNum(pNew) < p->nNewSize );
+ }
+ return Bdc_FunObjCopy( Bdc_ManRoot(pManDec) );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis [Compute truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+word Shr_ManComputeTruth6_rec( Gia_Man_t * p, int iNode, Vec_Wrd_t * vTruths )
+{
+ Gia_Obj_t * pObj;
+ word Truth0, Truth1;
+ if ( Gia_ObjIsTravIdCurrentId(p, iNode) )
+ return Vec_WrdEntry(vTruths, iNode);
+ Gia_ObjSetTravIdCurrentId(p, iNode);
+ pObj = Gia_ManObj( p, iNode );
+ assert( Gia_ObjIsAnd(pObj) );
+ Truth0 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId0p(p, pObj), vTruths );
+ Truth1 = Shr_ManComputeTruth6_rec( p, Gia_ObjFaninId1p(p, pObj), vTruths );
+ if ( Gia_ObjFaninC0(pObj) )
+ Truth0 = ~Truth0;
+ if ( Gia_ObjFaninC1(pObj) )
+ Truth1 = ~Truth1;
+ Vec_WrdWriteEntry( vTruths, iNode, Truth0 & Truth1 );
+ return Truth0 & Truth1;
+}
+word Shr_ManComputeTruth6( Gia_Man_t * p, Gia_Obj_t * pObj, Vec_Int_t * vLeaves, Vec_Wrd_t * vTruths )
+{
+ int i, iLeaf;
+ assert( Gia_ObjIsAnd(pObj) );
+ Gia_ManIncrementTravId( p );
+ Vec_IntForEachEntry( vLeaves, iLeaf, i )
+ {
+ Gia_ObjSetTravIdCurrentId( p, iLeaf );
+ Vec_WrdWriteEntry( vTruths, iLeaf, Truth[i] );
+ }
+ return Shr_ManComputeTruth6_rec( p, Gia_ObjId(p, pObj), vTruths );
+}
+
+/**Function*************************************************************
+
+ Synopsis [Compute truth table.]
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+void Shr_ManComputeTruths( Gia_Man_t * p, int nVars, Vec_Int_t * vDivs, Vec_Wrd_t * vDivTruths, Vec_Wrd_t * vTruths )
+{
+ Gia_Obj_t * pObj;
+ word Truth0, Truth1;//, Truthh;
+ int i, iDiv;
+ Vec_WrdClear( vDivTruths );
+ Vec_IntForEachEntryStop( vDivs, iDiv, i, nVars )
+ {
+ Vec_WrdWriteEntry( vTruths, iDiv, Truth[i] );
+ Vec_WrdPush( vDivTruths, Truth[i] );
+ }
+ Vec_IntForEachEntryStart( vDivs, iDiv, i, nVars )
+ {
+ pObj = Gia_ManObj( p, iDiv );
+ Truth0 = Vec_WrdEntry( vTruths, Gia_ObjFaninId0(pObj, iDiv) );
+ Truth1 = Vec_WrdEntry( vTruths, Gia_ObjFaninId1(pObj, iDiv) );
+ if ( Gia_ObjFaninC0(pObj) )
+ Truth0 = ~Truth0;
+ if ( Gia_ObjFaninC1(pObj) )
+ Truth1 = ~Truth1;
+ Vec_WrdWriteEntry( vTruths, iDiv, Truth0 & Truth1 );
+ Vec_WrdPush( vDivTruths, Truth0 & Truth1 );
+
+// Truthh = Truth0 & Truth1;
+// Abc_TtPrintBinary( &Truthh, nVars ); //printf( "\n" );
+// Kit_DsdPrintFromTruth( &Truthh, nVars ); printf( "\n" );
+ }
+// printf( "\n" );
+}
+
+
+/**Function*************************************************************
+
+ Synopsis []
+
+ Description []
+
+ SideEffects []
+
+ SeeAlso []
+
+***********************************************************************/
+Gia_Man_t * Gia_ManMapShrink6( Gia_Man_t * p, int fKeepLevel, int fVerbose )
+{
+ Shr_Man_t * pMan;
+ Gia_Obj_t * pObj, * pFanin;
+ word uTruth, uTruth0, uTruth1;
+ int i, k, nDivs, iNode;
+ int RetValue, Counter1 = 0, Counter2 = 0;
+ clock_t clk = clock();
+ assert( p->pMapping != NULL );
+ pMan = Shr_ManAlloc( p );
+ Gia_ManFillValue( p );
+ Gia_ManConst0(p)->Value = 0;
+ Gia_ManForEachObj1( p, pObj, i )
+ {
+ if ( Gia_ObjIsCi(pObj) )
+ {
+ pObj->Value = Gia_ManAppendCi( pMan->pNew );
+ if ( p->vLevels )
+ Gia_ObjSetLevel( pMan->pNew, Gia_ObjFromLit(pMan->pNew, Gia_ObjValue(pObj)), Gia_ObjLevel(p, pObj) );
+ }
+ else if ( Gia_ObjIsCo(pObj) )
+ {
+ pObj->Value = Gia_ManAppendCo( pMan->pNew, Gia_ObjFanin0Copy(pObj) );
+ }
+ else if ( Gia_ObjIsLut(p, i) )
+ {
+ // collect leaves of this gate
+ Vec_IntClear( pMan->vLeaves );
+ Gia_LutForEachFanin( p, i, iNode, k )
+ Vec_IntPush( pMan->vLeaves, iNode );
+ assert( Vec_IntSize(pMan->vLeaves) <= 6 );
+ // compute truth table
+ uTruth = Shr_ManComputeTruth6( pMan->pGia, pObj, pMan->vLeaves, pMan->vTruths );
+ assert( pObj->Value == ~0 );
+ if ( uTruth == 0 || ~uTruth == 0 )
+ pObj->Value = Abc_LitNotCond( 0, ~uTruth == 0 );
+ else
+ Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k )
+ if ( uTruth == Truth[k] || ~uTruth == Truth[k] )
+ pObj->Value = Abc_LitNotCond( pFanin->Value, ~uTruth == Truth[k] );
+ if ( pObj->Value != ~0 )
+ continue;
+ // translate into new nodes
+ Gia_ManForEachObjVec( pMan->vLeaves, p, pFanin, k )
+ {
+ if ( Abc_LitIsCompl(pFanin->Value) )
+ uTruth = ((uTruth & Truth[k]) >> (1 << k)) | ((uTruth & ~Truth[k]) << (1 << k));
+ Vec_IntWriteEntry( pMan->vLeaves, k, Abc_Lit2Var(pFanin->Value) );
+ }
+ // compute divisors
+ nDivs = Shr_ManCollectDivisors( pMan, pMan->vLeaves, pMan->nDivMax );
+ assert( nDivs <= pMan->nDivMax );
+ // compute truth tables
+ Shr_ManComputeTruths( pMan->pNew, Vec_IntSize(pMan->vLeaves), pMan->vDivs, pMan->vDivTruths, pMan->vTruths );
+ // perform resubstitution
+ RetValue = Rsb_ManPerformResub6( pMan->pManRsb, Vec_IntSize(pMan->vLeaves), uTruth, pMan->vDivTruths, &uTruth0, &uTruth1, 0 );
+ if ( RetValue ) // resub exists
+ {
+ Vec_Int_t * vResult = Rsb_ManGetFanins(pMan->pManRsb);
+ Vec_IntClear( pMan->vDivResub );
+ Vec_IntForEachEntry( vResult, iNode, k )
+ Vec_IntPush( pMan->vDivResub, Vec_IntEntry(pMan->vDivs, iNode) );
+ pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vDivResub, uTruth1, uTruth0 | uTruth1 );
+ Counter1++;
+ }
+ else
+ {
+ pObj->Value = Shr_ObjPerformBidec( pMan, pMan->pManDec, pMan->pNew, pMan->vLeaves, uTruth, ~(word)0 );
+ Counter2++;
+ }
+ }
+ }
+ if ( fVerbose )
+ {
+ printf( "Performed %d resubs and %d decomps. ", Counter1, Counter2 );
+ printf( "Gain in AIG nodes = %d. ", Gia_ManObjNum(p)-Gia_ManObjNum(pMan->pNew) );
+ ABC_PRT( "Runtime", clock() - clk );
+ }
+ return Shr_ManFree( pMan );
+}
+
+////////////////////////////////////////////////////////////////////////
+/// END OF FILE ///
+////////////////////////////////////////////////////////////////////////
+
+
+ABC_NAMESPACE_IMPL_END
+