| /**CFile**************************************************************** |
| |
| FileName [rwrLib.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [DAG-aware AIG rewriting package.] |
| |
| Synopsis [] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - June 20, 2005.] |
| |
| Revision [$Id: rwrLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "rwr.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| static Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ); |
| static void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ); |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Precomputes the forest in the manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Rwr_ManPrecompute( Rwr_Man_t * p ) |
| { |
| Rwr_Node_t * p0, * p1; |
| int i, k, Level, Volume; |
| int LevelOld = -1; |
| int nNodes; |
| |
| Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 1 ) |
| Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p1, k, 1 ) |
| { |
| if ( LevelOld < (int)p0->Level ) |
| { |
| LevelOld = p0->Level; |
| printf( "Starting level %d (at %d nodes).\n", LevelOld+1, i ); |
| printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", |
| p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); |
| } |
| |
| if ( k == i ) |
| break; |
| // if ( p0->Level + p1->Level > 6 ) // hard |
| // break; |
| |
| if ( p0->Level + p1->Level > 5 ) // easy |
| break; |
| |
| // if ( p0->Level + p1->Level > 6 || (p0->Level == 3 && p1->Level == 3) ) |
| // break; |
| |
| // compute the level and volume of the new nodes |
| Level = 1 + Abc_MaxInt( p0->Level, p1->Level ); |
| Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 ); |
| // try four different AND nodes |
| Rwr_ManTryNode( p, p0 , p1 , 0, Level, Volume ); |
| Rwr_ManTryNode( p, Rwr_Not(p0), p1 , 0, Level, Volume ); |
| Rwr_ManTryNode( p, p0 , Rwr_Not(p1), 0, Level, Volume ); |
| Rwr_ManTryNode( p, Rwr_Not(p0), Rwr_Not(p1), 0, Level, Volume ); |
| // try EXOR |
| Rwr_ManTryNode( p, p0 , p1 , 1, Level, Volume + 1 ); |
| // report the progress |
| if ( p->nConsidered % 50000000 == 0 ) |
| printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", |
| p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); |
| // quit after some time |
| if ( p->vForest->nSize == RWR_LIMIT + 5 ) |
| { |
| printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n", |
| p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i ); |
| goto save; |
| } |
| } |
| save : |
| |
| // mark the relevant ones |
| Rwr_ManIncTravId( p ); |
| k = 5; |
| nNodes = 0; |
| Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 5 ) |
| if ( p0->uTruth == p->puCanons[p0->uTruth] ) |
| { |
| Rwr_MarkUsed_rec( p, p0 ); |
| nNodes++; |
| } |
| |
| // compact the array by throwing away non-canonical |
| k = 5; |
| Vec_PtrForEachEntryStart( Rwr_Node_t *, p->vForest, p0, i, 5 ) |
| if ( p0->fUsed ) |
| { |
| p->vForest->pArray[k] = p0; |
| p0->Id = k++; |
| } |
| p->vForest->nSize = k; |
| printf( "Total canonical = %4d. Total used = %5d.\n", nNodes, p->vForest->nSize ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) |
| { |
| Rwr_Node_t * pOld, * pNew, ** ppPlace; |
| unsigned uTruth; |
| // compute truth table, level, volume |
| p->nConsidered++; |
| if ( fExor ) |
| { |
| // printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id ); |
| uTruth = (p0->uTruth ^ p1->uTruth); |
| } |
| else |
| uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & |
| (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; |
| // skip non-practical classes |
| if ( Level > 2 && !p->pPractical[p->puCanons[uTruth]] ) |
| return NULL; |
| // enumerate through the nodes with the same canonical form |
| ppPlace = p->pTable + uTruth; |
| for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext ) |
| { |
| if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) |
| return NULL; |
| if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) |
| return NULL; |
| // if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) |
| // return NULL; |
| } |
| /* |
| // enumerate through the nodes with the opposite polarity |
| for ( pOld = p->pTable[~uTruth & 0xFFFF]; pOld; pOld = pOld->pNext ) |
| { |
| if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) |
| return NULL; |
| if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) |
| return NULL; |
| // if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) |
| // return NULL; |
| } |
| */ |
| // count the classes |
| if ( p->pTable[uTruth] == NULL && p->puCanons[uTruth] == uTruth ) |
| p->nClasses++; |
| // create the new node |
| pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); |
| pNew->Id = p->vForest->nSize; |
| pNew->TravId = 0; |
| pNew->uTruth = uTruth; |
| pNew->Level = Level; |
| pNew->Volume = Volume; |
| pNew->fUsed = 0; |
| pNew->fExor = fExor; |
| pNew->p0 = p0; |
| pNew->p1 = p1; |
| pNew->pNext = NULL; |
| Vec_PtrPush( p->vForest, pNew ); |
| *ppPlace = pNew; |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) |
| { |
| Rwr_Node_t * pNew; |
| unsigned uTruth; |
| // compute truth table, leve, volume |
| p->nConsidered++; |
| if ( fExor ) |
| uTruth = (p0->uTruth ^ p1->uTruth); |
| else |
| uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & |
| (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; |
| // create the new node |
| pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); |
| pNew->Id = p->vForest->nSize; |
| pNew->TravId = 0; |
| pNew->uTruth = uTruth; |
| pNew->Level = Level; |
| pNew->Volume = Volume; |
| pNew->fUsed = 0; |
| pNew->fExor = fExor; |
| pNew->p0 = p0; |
| pNew->p1 = p1; |
| pNew->pNext = NULL; |
| Vec_PtrPush( p->vForest, pNew ); |
| // do not add if the node is not essential |
| if ( uTruth != p->puCanons[uTruth] ) |
| return pNew; |
| |
| // add to the list |
| p->nAdded++; |
| if ( p->pTable[uTruth] == NULL ) |
| p->nClasses++; |
| Rwr_ListAddToTail( p->pTable + uTruth, pNew ); |
| return pNew; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Rwr_Node_t * Rwr_ManAddVar( Rwr_Man_t * p, unsigned uTruth, int fPrecompute ) |
| { |
| Rwr_Node_t * pNew; |
| pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); |
| pNew->Id = p->vForest->nSize; |
| pNew->TravId = 0; |
| pNew->uTruth = uTruth; |
| pNew->Level = 0; |
| pNew->Volume = 0; |
| pNew->fUsed = 1; |
| pNew->fExor = 0; |
| pNew->p0 = NULL; |
| pNew->p1 = NULL; |
| pNew->pNext = NULL; |
| Vec_PtrPush( p->vForest, pNew ); |
| if ( fPrecompute ) |
| Rwr_ListAddToTail( p->pTable + uTruth, pNew ); |
| return pNew; |
| } |
| |
| |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Rwr_MarkUsed_rec( Rwr_Man_t * p, Rwr_Node_t * pNode ) |
| { |
| if ( pNode->fUsed || pNode->TravId == p->nTravIds ) |
| return; |
| pNode->TravId = p->nTravIds; |
| pNode->fUsed = 1; |
| Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p0) ); |
| Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p1) ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Rwr_Trav_rec( Rwr_Man_t * p, Rwr_Node_t * pNode, int * pVolume ) |
| { |
| if ( pNode->fUsed || pNode->TravId == p->nTravIds ) |
| return; |
| pNode->TravId = p->nTravIds; |
| (*pVolume)++; |
| if ( pNode->fExor ) |
| (*pVolume)++; |
| Rwr_Trav_rec( p, Rwr_Regular(pNode->p0), pVolume ); |
| Rwr_Trav_rec( p, Rwr_Regular(pNode->p1), pVolume ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Rwr_ManNodeVolume( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 ) |
| { |
| int Volume = 0; |
| Rwr_ManIncTravId( p ); |
| Rwr_Trav_rec( p, p0, &Volume ); |
| Rwr_Trav_rec( p, p1, &Volume ); |
| return Volume; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Adds one node.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Rwr_ManIncTravId( Rwr_Man_t * p ) |
| { |
| Rwr_Node_t * pNode; |
| int i; |
| if ( p->nTravIds++ < 0x8FFFFFFF ) |
| return; |
| Vec_PtrForEachEntry( Rwr_Node_t *, p->vForest, pNode, i ) |
| pNode->TravId = 0; |
| p->nTravIds = 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |