| /**CFile**************************************************************** |
| |
| FileName [abcCascade.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Network and node package.] |
| |
| Synopsis [Collapsing the network into two-levels.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: abcCollapse.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| |
| #ifdef ABC_USE_CUDD |
| #include "bdd/reo/reo.h" |
| #include "bdd/extrab/extraBdd.h" |
| #endif |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| #ifdef ABC_USE_CUDD |
| |
| #define BDD_FUNC_MAX 256 |
| |
| //extern void Abc_NodeShowBddOne( DdManager * dd, DdNode * bFunc ); |
| extern DdNode * Abc_ConvertSopToBdd( DdManager * dd, char * pSop, DdNode ** pbVars ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Derive BDD of the characteristic function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_ResBuildBdd( Abc_Ntk_t * pNtk, DdManager * dd ) |
| { |
| Vec_Ptr_t * vNodes, * vBdds, * vLocals; |
| Abc_Obj_t * pObj, * pFanin; |
| DdNode * bFunc, * bPart, * bTemp, * bVar; |
| int i, k; |
| assert( Abc_NtkIsSopLogic(pNtk) ); |
| assert( Abc_NtkCoNum(pNtk) <= 3 ); |
| vBdds = Vec_PtrStart( Abc_NtkObjNumMax(pNtk) ); |
| Abc_NtkForEachCi( pNtk, pObj, i ) |
| Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), Cudd_bddIthVar(dd, i) ); |
| // create internal node BDDs |
| vNodes = Abc_NtkDfs( pNtk, 0 ); |
| vLocals = Vec_PtrAlloc( 6 ); |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| { |
| if ( Abc_ObjFaninNum(pObj) == 0 ) |
| { |
| bFunc = Cudd_NotCond( Cudd_ReadOne(dd), Abc_SopIsConst0((char *)pObj->pData) ); Cudd_Ref( bFunc ); |
| Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); |
| continue; |
| } |
| Vec_PtrClear( vLocals ); |
| Abc_ObjForEachFanin( pObj, pFanin, k ) |
| Vec_PtrPush( vLocals, Vec_PtrEntry(vBdds, Abc_ObjId(pFanin)) ); |
| bFunc = Abc_ConvertSopToBdd( dd, (char *)pObj->pData, (DdNode **)Vec_PtrArray(vLocals) ); Cudd_Ref( bFunc ); |
| Vec_PtrWriteEntry( vBdds, Abc_ObjId(pObj), bFunc ); |
| } |
| Vec_PtrFree( vLocals ); |
| // create char function |
| bFunc = Cudd_ReadOne( dd ); Cudd_Ref( bFunc ); |
| Abc_NtkForEachCo( pNtk, pObj, i ) |
| { |
| bVar = Cudd_bddIthVar( dd, i + Abc_NtkCiNum(pNtk) ); |
| bTemp = (DdNode *)Vec_PtrEntry( vBdds, Abc_ObjFaninId0(pObj) ); |
| bPart = Cudd_bddXnor( dd, bTemp, bVar ); Cudd_Ref( bPart ); |
| bFunc = Cudd_bddAnd( dd, bTemp = bFunc, bPart ); Cudd_Ref( bFunc ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| Cudd_RecursiveDeref( dd, bPart ); |
| } |
| // dereference |
| Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) |
| Cudd_RecursiveDeref( dd, (DdNode *)Vec_PtrEntry(vBdds, Abc_ObjId(pObj)) ); |
| Vec_PtrFree( vBdds ); |
| Vec_PtrFree( vNodes ); |
| // reorder |
| Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 ); |
| Cudd_Deref( bFunc ); |
| return bFunc; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Initializes variable partition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResStartPart( int nInputs, unsigned uParts[], int nParts ) |
| { |
| int i, Group, Left, Shift = 0, Count = 0; |
| Group = nInputs / nParts; |
| Left = nInputs % nParts; |
| for ( i = 0; i < Left; i++ ) |
| { |
| uParts[i] = (~((~0) << (Group+1))) << Shift; |
| Shift += Group+1; |
| } |
| for ( ; i < nParts; i++ ) |
| { |
| uParts[i] = (~((~0) << Group)) << Shift; |
| Shift += Group; |
| } |
| for ( i = 0; i < nParts; i++ ) |
| Count += Extra_WordCountOnes( uParts[i] ); |
| assert( Count == nInputs ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Initializes variable partition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResStartPart2( int nInputs, unsigned uParts[], int nParts ) |
| { |
| int i, Count = 0; |
| for ( i = 0; i < nParts; i++ ) |
| uParts[i] = 0; |
| for ( i = 0; i < nInputs; i++ ) |
| uParts[i % nParts] |= (1 << i); |
| for ( i = 0; i < nParts; i++ ) |
| Count += Extra_WordCountOnes( uParts[i] ); |
| assert( Count == nInputs ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Returns one if unique pattern.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ResCheckUnique( char Pats[], int nPats, int pat ) |
| { |
| int i; |
| for ( i = 0; i < nPats; i++ ) |
| if ( Pats[i] == pat ) |
| return 0; |
| return 1; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Check if pattern is decomposable with non-strict.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ResCheckNonStrict( char Pattern[], int nVars, int nBits ) |
| { |
| static char Pat0[256], Pat1[256]; |
| int v, m, nPats0, nPats1, nNumber = (1 << (nBits - 1)); |
| int Result = 0; |
| for ( v = 0; v < nVars; v++ ) |
| { |
| nPats0 = nPats1 = 0; |
| for ( m = 0; m < (1<<nVars); m++ ) |
| { |
| if ( (m & (1 << v)) == 0 ) |
| { |
| if ( Abc_ResCheckUnique( Pat0, nPats0, Pattern[m] ) ) |
| { |
| Pat0[ nPats0++ ] = Pattern[m]; |
| if ( nPats0 > nNumber ) |
| break; |
| } |
| } |
| else |
| { |
| if ( Abc_ResCheckUnique( Pat1, nPats1, Pattern[m] ) ) |
| { |
| Pat1[ nPats1++ ] = Pattern[m]; |
| if ( nPats1 > nNumber ) |
| break; |
| } |
| } |
| } |
| if ( m == (1<<nVars) ) |
| Result++; |
| } |
| return Result; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ResCofCount( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pCheck ) |
| { |
| static char Pattern[256]; |
| DdNode * pbVars[32]; |
| Vec_Ptr_t * vCofs; |
| DdNode * bCof, * bCube, * bTemp; |
| int i, k, Result, nVars = 0; |
| // collect variables |
| for ( i = 0; i < 32; i++ ) |
| if ( uMask & (1 << i) ) |
| pbVars[nVars++] = dd->vars[i]; |
| assert( nVars <= 8 ); |
| // compute cofactors |
| vCofs = Vec_PtrAlloc( 100 ); |
| for ( i = 0; i < (1 << nVars); i++ ) |
| { |
| bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); |
| bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof ); |
| Cudd_RecursiveDeref( dd, bCube ); |
| Vec_PtrForEachEntry( DdNode *, vCofs, bTemp, k ) |
| if ( bTemp == bCof ) |
| break; |
| if ( k < Vec_PtrSize(vCofs) ) |
| Cudd_RecursiveDeref( dd, bCof ); |
| else |
| Vec_PtrPush( vCofs, bCof ); |
| Pattern[i] = k; |
| } |
| Result = Vec_PtrSize( vCofs ); |
| Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i ) |
| Cudd_RecursiveDeref( dd, bCof ); |
| Vec_PtrFree( vCofs ); |
| if ( pCheck ) |
| { |
| *pCheck = Abc_ResCheckNonStrict( Pattern, nVars, Abc_Base2Log(Result) ); |
| /* |
| if ( *pCheck == 1 && nVars == 4 && Result == 8 ) |
| { |
| for ( i = 0; i < (1 << nVars); i++ ) |
| printf( "%d ", Pattern[i] ); |
| i = 0; |
| } |
| */ |
| } |
| return Result; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes cost of the partition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ResCost( DdManager * dd, DdNode * bFunc, unsigned uMask, int * pnCofs, int * pCheck ) |
| { |
| int nCofs = Abc_ResCofCount( dd, bFunc, uMask, pCheck ); |
| int n2Log = Abc_Base2Log( nCofs ); |
| if ( pnCofs ) *pnCofs = nCofs; |
| return 10000 * n2Log + (nCofs - (1 << (n2Log-1))) * (nCofs - (1 << (n2Log-1))); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Migrates variables between the two groups.] |
| |
| Description [Returns 1 if there is change.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_ResMigrate( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int iPart1, int iPart2 ) |
| { |
| unsigned uParts2[2] = { uParts[iPart1], uParts[iPart2] }; |
| int i, k, CostCur, CostBest, fChange = 0; |
| assert( (uParts[iPart1] & uParts[iPart2]) == 0 ); |
| CostBest = Abc_ResCost( dd, bFunc, uParts[iPart1], NULL, NULL ) |
| + Abc_ResCost( dd, bFunc, uParts[iPart2], NULL, NULL ); |
| for ( i = 0; i < nInputs; i++ ) |
| if ( uParts[iPart1] & (1 << i) ) |
| { |
| for ( k = 0; k < nInputs; k++ ) |
| if ( uParts[iPart2] & (1 << k) ) |
| { |
| if ( i == k ) |
| continue; |
| uParts[iPart1] ^= (1 << i) | (1 << k); |
| uParts[iPart2] ^= (1 << i) | (1 << k); |
| CostCur = Abc_ResCost( dd, bFunc, uParts[iPart1], NULL, NULL ) + Abc_ResCost( dd, bFunc, uParts[iPart2], NULL, NULL ); |
| if ( CostCur < CostBest ) |
| { |
| CostCur = CostBest; |
| uParts2[0] = uParts[iPart1]; |
| uParts2[1] = uParts[iPart2]; |
| fChange = 1; |
| } |
| uParts[iPart1] ^= (1 << i) | (1 << k); |
| uParts[iPart2] ^= (1 << i) | (1 << k); |
| } |
| } |
| uParts[iPart1] = uParts2[0]; |
| uParts[iPart2] = uParts2[1]; |
| return fChange; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Migrates variables between the two groups.] |
| |
| Description [Returns 1 if there is change.] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResPrint( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int nParts ) |
| { |
| int i, k, nCofs, Cost, CostAll = 0, fCheck; |
| for ( i = 0; i < nParts; i++ ) |
| { |
| Cost = Abc_ResCost( dd, bFunc, uParts[i], &nCofs, &fCheck ); |
| CostAll += Cost; |
| for ( k = 0; k < nInputs; k++ ) |
| printf( "%c", (uParts[i] & (1 << k))? 'a' + k : '-' ); |
| printf( " %2d %d-%d %6d ", nCofs, Abc_Base2Log(nCofs), fCheck, Cost ); |
| } |
| printf( "%4d\n", CostAll ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [PrintCompute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResPrintAllCofs( DdManager * dd, DdNode * bFunc, int nInputs, int nCofMax ) |
| { |
| int i, k, nBits, nCofs, Cost, fCheck; |
| for ( i = 0; i < (1<<nInputs); i++ ) |
| { |
| nBits = Extra_WordCountOnes( i ); |
| if ( nBits < 3 || nBits > 6 ) |
| continue; |
| Cost = Abc_ResCost( dd, bFunc, i, &nCofs, &fCheck ); |
| if ( nCofs > nCofMax ) |
| continue; |
| for ( k = 0; k < nInputs; k++ ) |
| printf( "%c", (i & (1 << k))? 'a' + k : '-' ); |
| printf( " n=%2d c=%2d l=%d-%d %6d\n", |
| Extra_WordCountOnes(i), nCofs, Abc_Base2Log(nCofs), fCheck, Cost ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResSwapRandom( DdManager * dd, DdNode * bFunc, int nInputs, unsigned uParts[], int nParts, int nTimes ) |
| { |
| int i, k, n, iPart1, iPart2; |
| for ( n = 0; n < nTimes; ) |
| { |
| // get the vars |
| i = k = 0; |
| while ( i == k ) |
| { |
| i = rand() % nInputs; |
| k = rand() % nInputs; |
| } |
| // find the groups |
| for ( iPart1 = 0; iPart1 < nParts; iPart1++ ) |
| if ( uParts[iPart1] & (1 << i) ) |
| break; |
| for ( iPart2 = 0; iPart2 < nParts; iPart2++ ) |
| if ( uParts[iPart2] & (1 << k) ) |
| break; |
| if ( iPart1 == iPart2 ) |
| continue; |
| // swap the vars |
| uParts[iPart1] ^= (1 << i) | (1 << k); |
| uParts[iPart2] ^= (1 << i) | (1 << k); |
| n++; |
| //printf( " " ); |
| //Abc_ResPrint( dd, bFunc, nInputs, uParts, nParts ); |
| } |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResPartition( DdManager * dd, DdNode * bFunc, int nInputs ) |
| { |
| int nIters = 5; |
| unsigned uParts[10]; |
| int i, fChange = 1; |
| int nSuppSize = Cudd_SupportSize( dd, bFunc ); |
| printf( "Ins =%3d. Outs =%2d. Nodes =%3d. Supp =%2d.\n", |
| nInputs, dd->size-nInputs, Cudd_DagSize(bFunc), nSuppSize ); |
| //Abc_ResPrintAllCofs( dd, bFunc, nInputs, 4 ); |
| |
| if ( nSuppSize <= 6 ) |
| { |
| printf( "Support is less or equal than 6\n" ); |
| return; |
| } |
| if ( nInputs <= 12 ) |
| { |
| Abc_ResStartPart( nInputs, uParts, 2 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 ); |
| for ( i = 0; i < nIters; i++ ) |
| { |
| if ( i ) |
| { |
| printf( "Randomizing... \n" ); |
| Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 2, 20 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 ); |
| } |
| fChange = 1; |
| while ( fChange ) |
| { |
| fChange = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 2 ); |
| } |
| } |
| } |
| else if ( nInputs > 12 && nInputs <= 18 ) |
| { |
| Abc_ResStartPart( nInputs, uParts, 3 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); |
| for ( i = 0; i < nIters; i++ ) |
| { |
| if ( i ) |
| { |
| printf( "Randomizing... \n" ); |
| Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 3, 20 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); |
| } |
| fChange = 1; |
| while ( fChange ) |
| { |
| fChange = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 2 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 2 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 3 ); |
| } |
| } |
| } |
| else if ( nInputs > 18 && nInputs <= 24 ) |
| { |
| Abc_ResStartPart( nInputs, uParts, 4 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| for ( i = 0; i < nIters; i++ ) |
| { |
| if ( i ) |
| { |
| printf( "Randomizing... \n" ); |
| Abc_ResSwapRandom( dd, bFunc, nInputs, uParts, 4, 20 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| } |
| fChange = 1; |
| while ( fChange ) |
| { |
| fChange = Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 1 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 2 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 0, 3 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 2 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 1, 3 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| fChange |= Abc_ResMigrate( dd, bFunc, nInputs, uParts, 2, 3 ); |
| Abc_ResPrint( dd, bFunc, nInputs, uParts, 4 ); |
| } |
| } |
| } |
| // else assert( 0 ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_ResPartitionTest( Abc_Ntk_t * pNtk ) |
| { |
| DdManager * dd; |
| DdNode * bFunc; |
| dd = Cudd_Init( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk), 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); |
| bFunc = Abc_ResBuildBdd( pNtk, dd ); Cudd_Ref( bFunc ); |
| Abc_ResPartition( dd, bFunc, Abc_NtkCiNum(pNtk) ); |
| Cudd_RecursiveDeref( dd, bFunc ); |
| Extra_StopManager( dd ); |
| } |
| |
| |
| |
| |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkBddCofCount( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nVars ) |
| { |
| Vec_Ptr_t * vCofs; |
| DdNode * bCof, * bCube; |
| int i, Result; |
| vCofs = Vec_PtrAlloc( 100 ); |
| for ( i = 0; i < (1 << nVars); i++ ) |
| { |
| bCube = Extra_bddBitsToCube( dd, i, nVars, pbVars, 1 ); Cudd_Ref( bCube ); |
| bCof = Cudd_Cofactor( dd, bFunc, bCube ); Cudd_Ref( bCof ); |
| Cudd_RecursiveDeref( dd, bCube ); |
| if ( Vec_PtrPushUnique( vCofs, bCof ) ) |
| Cudd_RecursiveDeref( dd, bCof ); |
| } |
| Result = Vec_PtrSize( vCofs ); |
| Vec_PtrForEachEntry( DdNode *, vCofs, bCof, i ) |
| Cudd_RecursiveDeref( dd, bCof ); |
| Vec_PtrFree( vCofs ); |
| return Result; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkExploreCofs2( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nIns, int nLutSize ) |
| { |
| int i; |
| printf( "Inputs = %2d. Nodes = %2d. LutSize = %2d.\n", nIns, Cudd_DagSize(bFunc), nLutSize ); |
| for ( i = 0; i <= nIns - nLutSize; i++ ) |
| printf( "[%2d %2d] : %3d\n", i, i+nLutSize-1, Abc_NtkBddCofCount(dd, bFunc, dd->vars+i, nLutSize) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Compute the number of distinct cofactors in the BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Abc_NtkExploreCofs( DdManager * dd, DdNode * bFunc, DdNode ** pbVars, int nIns, int nLutSize ) |
| { |
| DdManager * ddNew; |
| DdNode * bFuncNew; |
| DdNode * pbVarsNew[32]; |
| int i, k, c, nCofs, nBits; |
| |
| ddNew = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 ); |
| Cudd_ShuffleHeap( ddNew, dd->invperm ); |
| bFuncNew = Cudd_bddTransfer( dd, ddNew, bFunc ); Cudd_Ref( bFuncNew ); |
| |
| for ( i = 0; i < (1 << nIns); i++ ) |
| { |
| nBits = Extra_WordCountOnes(i); |
| if ( nBits != nLutSize && nBits != nLutSize -1 && nBits != nLutSize -2 ) |
| continue; |
| for ( c = k = 0; k < nIns; k++ ) |
| { |
| if ( (i & (1 << k)) == 0 ) |
| continue; |
| // pbVarsNew[c++] = pbVars[k]; |
| pbVarsNew[c++] = ddNew->vars[k]; |
| } |
| nCofs = Abc_NtkBddCofCount(ddNew, bFuncNew, pbVarsNew, c); |
| if ( nCofs > 8 ) |
| continue; |
| |
| for ( c = k = 0; k < nIns; k++ ) |
| { |
| if ( (i & (1 << k)) == 0 ) |
| { |
| printf( "-" ); |
| continue; |
| } |
| printf( "%c", k + 'a' ); |
| } |
| printf( " : %2d\n", nCofs ); |
| } |
| |
| Cudd_RecursiveDeref( ddNew, bFuncNew ); |
| Extra_StopManager( ddNew ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Find the constant node corresponding to the encoded output value.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkBddFindAddConst( DdManager * dd, DdNode * bFunc, int nOuts ) |
| { |
| int i, TermMask = 0; |
| DdNode * bFunc0, * bFunc1, * bConst0, * bConst1; |
| bConst0 = Cudd_ReadLogicZero( dd ); |
| bConst1 = Cudd_ReadOne( dd ); |
| for ( i = 0; i < nOuts; i++ ) |
| { |
| if ( Cudd_IsComplement(bFunc) ) |
| { |
| bFunc0 = Cudd_Not(Cudd_E(bFunc)); |
| bFunc1 = Cudd_Not(Cudd_T(bFunc)); |
| } |
| else |
| { |
| bFunc0 = Cudd_E(bFunc); |
| bFunc1 = Cudd_T(bFunc); |
| } |
| assert( bFunc0 == bConst0 || bFunc1 == bConst0 ); |
| if ( bFunc0 == bConst0 ) |
| { |
| TermMask ^= (1 << i); |
| bFunc = bFunc1; |
| } |
| else |
| bFunc = bFunc0; |
| } |
| assert( bFunc == bConst1 ); |
| return Cudd_addConst( dd, TermMask ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively construct ADD for BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkBddToAdd_rec( DdManager * dd, DdNode * bFunc, int nOuts, stmm_table * tTable, int fCompl ) |
| { |
| DdNode * aFunc0, * aFunc1, * aFunc; |
| DdNode ** ppSlot; |
| assert( !Cudd_IsComplement(bFunc) ); |
| if ( stmm_find_or_add( tTable, (char *)bFunc, (char ***)&ppSlot ) ) |
| return *ppSlot; |
| if ( (int)bFunc->index >= Cudd_ReadSize(dd) - nOuts ) |
| { |
| assert( Cudd_ReadPerm(dd, bFunc->index) >= Cudd_ReadSize(dd) - nOuts ); |
| aFunc = Abc_NtkBddFindAddConst( dd, Cudd_NotCond(bFunc, fCompl), nOuts ); Cudd_Ref( aFunc ); |
| } |
| else |
| { |
| aFunc0 = Abc_NtkBddToAdd_rec( dd, Cudd_Regular(cuddE(bFunc)), nOuts, tTable, fCompl ^ Cudd_IsComplement(cuddE(bFunc)) ); |
| aFunc1 = Abc_NtkBddToAdd_rec( dd, cuddT(bFunc), nOuts, tTable, fCompl ); |
| aFunc = Cudd_addIte( dd, Cudd_addIthVar(dd, bFunc->index), aFunc1, aFunc0 ); Cudd_Ref( aFunc ); |
| } |
| return (*ppSlot = aFunc); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [R] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkBddToAdd( DdManager * dd, DdNode * bFunc, int nOuts ) |
| { |
| DdNode * aFunc, * aTemp, * bTemp; |
| stmm_table * tTable; |
| stmm_generator * gen; |
| tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); |
| aFunc = Abc_NtkBddToAdd_rec( dd, Cudd_Regular(bFunc), nOuts, tTable, Cudd_IsComplement(bFunc) ); |
| stmm_foreach_item( tTable, gen, (char **)&bTemp, (char **)&aTemp ) |
| Cudd_RecursiveDeref( dd, aTemp ); |
| stmm_free_table( tTable ); |
| Cudd_Deref( aFunc ); |
| return aFunc; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Recursively construct ADD for BDD.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkAddToBdd_rec( DdManager * dd, DdNode * aFunc, int nIns, int nOuts, stmm_table * tTable ) |
| { |
| DdNode * bFunc0, * bFunc1, * bFunc; |
| DdNode ** ppSlot; |
| assert( !Cudd_IsComplement(aFunc) ); |
| if ( stmm_find_or_add( tTable, (char *)aFunc, (char ***)&ppSlot ) ) |
| return *ppSlot; |
| if ( Cudd_IsConstant(aFunc) ) |
| { |
| assert( Cudd_ReadSize(dd) >= nIns + nOuts ); |
| bFunc = Extra_bddBitsToCube( dd, (int)Cudd_V(aFunc), nOuts, dd->vars + nIns, 1 ); Cudd_Ref( bFunc ); |
| } |
| else |
| { |
| assert( aFunc->index < nIns ); |
| bFunc0 = Abc_NtkAddToBdd_rec( dd, cuddE(aFunc), nIns, nOuts, tTable ); |
| bFunc1 = Abc_NtkAddToBdd_rec( dd, cuddT(aFunc), nIns, nOuts, tTable ); |
| bFunc = Cudd_bddIte( dd, Cudd_bddIthVar(dd, aFunc->index), bFunc1, bFunc0 ); Cudd_Ref( bFunc ); |
| } |
| return (*ppSlot = bFunc); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [R] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkAddToBdd( DdManager * dd, DdNode * aFunc, int nIns, int nOuts ) |
| { |
| DdNode * bFunc, * bTemp, * aTemp; |
| stmm_table * tTable; |
| stmm_generator * gen; |
| tTable = stmm_init_table( st__ptrcmp, st__ptrhash ); |
| bFunc = Abc_NtkAddToBdd_rec( dd, aFunc, nIns, nOuts, tTable ); |
| stmm_foreach_item( tTable, gen, (char **)&aTemp, (char **)&bTemp ) |
| Cudd_RecursiveDeref( dd, bTemp ); |
| stmm_free_table( tTable ); |
| Cudd_Deref( bFunc ); |
| return bFunc; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Computes the characteristic function.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkBddDecCharFunc( DdManager * dd, DdNode ** pFuncs, int nOuts, int Mask, int nBits ) |
| { |
| DdNode * bFunc, * bTemp, * bExor, * bVar; |
| int i, Count = 0; |
| bFunc = Cudd_ReadOne( dd ); Cudd_Ref( bFunc ); |
| for ( i = 0; i < nOuts; i++ ) |
| { |
| if ( (Mask & (1 << i)) == 0 ) |
| continue; |
| Count++; |
| bVar = Cudd_bddIthVar( dd, dd->size - nOuts + i ); |
| bExor = Cudd_bddXor( dd, pFuncs[i], bVar ); Cudd_Ref( bExor ); |
| bFunc = Cudd_bddAnd( dd, bTemp = bFunc, Cudd_Not(bExor) ); Cudd_Ref( bFunc ); |
| Cudd_RecursiveDeref( dd, bTemp ); |
| Cudd_RecursiveDeref( dd, bExor ); |
| } |
| Cudd_Deref( bFunc ); |
| assert( Count == nBits ); |
| return bFunc; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Evaluate Sasao's decomposition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkBddDecTry( reo_man * pReo, DdManager * dd, DdNode ** pFuncs, int nIns, int nOuts, int Mask, int nBits ) |
| { |
| // int fReorder = 0; |
| DdNode * bFunc;//, * aFunc, * aFuncNew; |
| // derive the characteristic function |
| bFunc = Abc_NtkBddDecCharFunc( dd, pFuncs, nOuts, Mask, nBits ); Cudd_Ref( bFunc ); |
| /* |
| // transfer to ADD |
| aFunc = Abc_NtkBddToAdd( dd, bFunc, nOuts ); Cudd_Ref( aFunc ); |
| Cudd_RecursiveDeref( dd, bFunc ); |
| //Abc_NodeShowBddOne( dd, aFunc ); |
| |
| // perform reordering for BDD width |
| if ( fReorder ) |
| { |
| aFuncNew = Extra_Reorder( pReo, dd, aFunc, NULL ); Cudd_Ref( aFuncNew ); |
| printf( "Before = %d. After = %d.\n", Cudd_DagSize(aFunc), Cudd_DagSize(aFuncNew) ); |
| Cudd_RecursiveDeref( dd, aFunc ); |
| } |
| else |
| aFuncNew = aFunc; |
| |
| // get back to BDD |
| bFunc = Abc_NtkAddToBdd( dd, aFuncNew, nIns, nOuts ); Cudd_Ref( bFunc ); |
| Cudd_RecursiveDeref( dd, aFuncNew ); |
| //Abc_NodeShowBddOne( dd, bFunc ); |
| // print the result |
| // reoProfileWidthPrint( pReo ); |
| */ |
| Cudd_Deref( bFunc ); |
| return bFunc; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Evaluate Sasao's decomposition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| DdNode * Abc_NtkBddDecInt( reo_man * pReo, DdManager * dd, DdNode ** pFuncs, int nIns, int nOuts ) |
| { |
| /* |
| int i, k; |
| for ( i = 1; i <= nOuts; i++ ) |
| { |
| for ( k = 0; k < (1<<nOuts); k++ ) |
| if ( Extra_WordCountOnes(k) == i ) |
| { |
| Extra_PrintBinary( stdout, (unsigned *)&k, nOuts ); |
| Abc_NtkBddDecTry( pReo, dd, pFuncs, nOuts, k, i ); |
| printf( "\n" ); |
| } |
| } |
| */ |
| return Abc_NtkBddDecTry( pReo, dd, pFuncs, nIns, nOuts, ~(1<<(32-nOuts)), nOuts ); |
| |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Evaluate Sasao's decomposition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkCreateFromCharFunc( Abc_Ntk_t * pNtk, DdManager * dd, DdNode * bFunc ) |
| { |
| Abc_Ntk_t * pNtkNew; |
| Abc_Obj_t * pNode, * pNodeNew, * pNodePo; |
| int i; |
| // start the network |
| pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 ); |
| pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); |
| // create inputs for CIs |
| pNodeNew = Abc_NtkCreateNode( pNtkNew ); |
| Abc_NtkForEachCi( pNtk, pNode, i ) |
| { |
| pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); |
| Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); |
| Abc_ObjAssignName( pNode->pCopy, Abc_ObjName(pNode), NULL ); |
| } |
| // create inputs for COs |
| Abc_NtkForEachCo( pNtk, pNode, i ) |
| { |
| pNode->pCopy = Abc_NtkCreatePi( pNtkNew ); |
| Abc_ObjAddFanin( pNodeNew, pNode->pCopy ); |
| Abc_ObjAssignName( pNode->pCopy, Abc_ObjName(pNode), NULL ); |
| } |
| // transfer BDD |
| pNodeNew->pData = Extra_TransferLevelByLevel( dd, (DdManager *)pNtkNew->pManFunc, bFunc ); Cudd_Ref( (DdNode *)pNodeNew->pData ); |
| // transfer BDD into to be the local function |
| pNodePo = Abc_NtkCreatePo( pNtkNew ); |
| Abc_ObjAddFanin( pNodePo, pNodeNew ); |
| Abc_ObjAssignName( pNodePo, "out", NULL ); |
| if ( !Abc_NtkCheck( pNtkNew ) ) |
| fprintf( stdout, "Abc_NtkCreateFromCharFunc(): Network check has failed.\n" ); |
| return pNtkNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Evaluate Sasao's decomposition.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Abc_Ntk_t * Abc_NtkBddDec( Abc_Ntk_t * pNtk, int fVerbose ) |
| { |
| int nBddSizeMax = 1000000; |
| int fDropInternal = 0; |
| int fReorder = 1; |
| Abc_Ntk_t * pNtkNew; |
| reo_man * pReo; |
| DdManager * dd; |
| DdNode * pFuncs[BDD_FUNC_MAX]; |
| DdNode * bFunc; |
| Abc_Obj_t * pNode; |
| int i; |
| assert( Abc_NtkIsStrash(pNtk) ); |
| assert( Abc_NtkCoNum(pNtk) <= BDD_FUNC_MAX ); |
| dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddSizeMax, fDropInternal, fReorder, fVerbose ); |
| if ( dd == NULL ) |
| { |
| Abc_Print( -1, "Construction of global BDDs has failed.\n" ); |
| return NULL; |
| } |
| // collect global BDDs |
| Abc_NtkForEachCo( pNtk, pNode, i ) |
| pFuncs[i] = (DdNode *)Abc_ObjGlobalBdd(pNode); |
| |
| // create new variables at the bottom |
| assert( dd->size == Abc_NtkCiNum(pNtk) ); |
| for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) |
| Cudd_addNewVarAtLevel( dd, dd->size ); |
| |
| // prepare reordering engine |
| pReo = Extra_ReorderInit( Abc_NtkCiNum(pNtk), 1000 ); |
| Extra_ReorderSetMinimizationType( pReo, REO_MINIMIZE_WIDTH ); |
| Extra_ReorderSetVerification( pReo, 1 ); |
| Extra_ReorderSetVerbosity( pReo, 1 ); |
| |
| // derive characteristic function |
| bFunc = Abc_NtkBddDecInt( pReo, dd, pFuncs, Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk) ); Cudd_Ref( bFunc ); |
| Extra_ReorderQuit( pReo ); |
| |
| Abc_NtkExploreCofs( dd, bFunc, dd->vars, Abc_NtkCiNum(pNtk), 6 ); |
| |
| // create new network |
| // pNtkNew = Abc_NtkCreateFromCharFunc( pNtk, dd, bFunc ); |
| pNtkNew = Abc_NtkDup( pNtk ); |
| |
| // cleanup |
| Cudd_RecursiveDeref( dd, bFunc ); |
| Abc_NtkFreeGlobalBdds( pNtk, 1 ); |
| return pNtkNew; |
| } |
| |
| #else |
| |
| Abc_Ntk_t * Abc_NtkBddDec( Abc_Ntk_t * pNtk, int fVerbose ) { return NULL; } |
| |
| #endif |
| |
| ABC_NAMESPACE_IMPL_END |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |