/**CFile**************************************************************** FileName [ifMan.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [FPGA mapping based on priority cuts.] Synopsis [Mapping manager.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - November 21, 2006.] Revision [$Id: ifMan.c,v 1.00 2006/11/21 00:00:00 alanmi Exp $] ***********************************************************************/ #include "if.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static If_Obj_t * If_ManSetupObj( If_Man_t * p ); static void If_ManCutSetRecycle( If_Man_t * p, If_Set_t * pSet ) { pSet->pNext = p->pFreeList; p->pFreeList = pSet; } static If_Set_t * If_ManCutSetFetch( If_Man_t * p ) { If_Set_t * pTemp = p->pFreeList; p->pFreeList = p->pFreeList->pNext; return pTemp; } extern clock_t s_TimeComp[4]; //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Man_t * If_ManStart( If_Par_t * pPars ) { If_Man_t * p; // start the manager p = ABC_ALLOC( If_Man_t, 1 ); memset( p, 0, sizeof(If_Man_t) ); p->pPars = pPars; p->fEpsilon = pPars->Epsilon; // allocate arrays for nodes p->vCis = Vec_PtrAlloc( 100 ); p->vCos = Vec_PtrAlloc( 100 ); p->vObjs = Vec_PtrAlloc( 100 ); // p->vMapped = Vec_PtrAlloc( 100 ); p->vTemp = Vec_PtrAlloc( 100 ); // prepare the memory manager p->nTruthWords = p->pPars->fTruth? If_CutTruthWords( p->pPars->nLutSize ) : 0; p->nPermWords = p->pPars->fUsePerm? If_CutPermWords( p->pPars->nLutSize ) : 0; p->nObjBytes = sizeof(If_Obj_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords); p->nCutBytes = sizeof(If_Cut_t) + sizeof(int) * (p->pPars->nLutSize + p->nPermWords + p->nTruthWords); p->nSetBytes = sizeof(If_Set_t) + (sizeof(If_Cut_t *) + p->nCutBytes) * (p->pPars->nCutsMax + 1); p->pMemObj = Mem_FixedStart( p->nObjBytes ); // p->pMemSet = Mem_FixedStart( p->nSetBytes ); // report expected memory usage if ( p->pPars->fVerbose ) Abc_Print( 1, "K = %d. Memory (bytes): Truth = %4d. Cut = %4d. Obj = %4d. Set = %4d. CutMin = %s\n", p->pPars->nLutSize, 4 * p->nTruthWords, p->nCutBytes, p->nObjBytes, p->nSetBytes, p->pPars->fCutMin? "yes":"no" ); // room for temporary truth tables p->puTemp[0] = p->pPars->fTruth? ABC_ALLOC( unsigned, 4 * p->nTruthWords ) : NULL; p->puTemp[1] = p->puTemp[0] + p->nTruthWords; p->puTemp[2] = p->puTemp[1] + p->nTruthWords; p->puTemp[3] = p->puTemp[2] + p->nTruthWords; p->pCutTemp = (If_Cut_t *)ABC_ALLOC( char, p->nCutBytes ); if ( pPars->fUseDsd ) { // p->pNamDsd = Abc_NamStart( 1000, 20 ); // p->iNamVar = Abc_NamStrFindOrAdd( p->pNamDsd, "a", NULL ); p->pDsdMan = Dss_ManAlloc( pPars->nLutSize, pPars->nNonDecLimit ); p->iNamVar = 2; } // create the constant node p->pConst1 = If_ManSetupObj( p ); p->pConst1->Type = IF_CONST1; p->pConst1->fPhase = 1; p->nObjs[IF_CONST1]++; return p; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManRestart( If_Man_t * p ) { ABC_FREE( p->pMemCi ); Vec_PtrClear( p->vCis ); Vec_PtrClear( p->vCos ); Vec_PtrClear( p->vObjs ); // Vec_PtrClear( p->vMapped ); Vec_PtrClear( p->vTemp ); Mem_FixedRestart( p->pMemObj ); // create the constant node p->pConst1 = If_ManSetupObj( p ); p->pConst1->Type = IF_CONST1; p->pConst1->fPhase = 1; // reset the counter of other nodes p->nObjs[IF_CI] = p->nObjs[IF_CO] = p->nObjs[IF_AND] = 0; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManStop( If_Man_t * p ) { { // extern void If_CluHashFindMedian( If_Man_t * p ); // extern void If_CluHashTableCheck( If_Man_t * p ); // If_CluHashFindMedian( p ); // If_CluHashTableCheck( p ); } if ( p->pPars->fVerbose && p->nCutsUselessAll ) { int i; for ( i = 0; i <= 16; i++ ) if ( p->nCutsUseless[i] ) Abc_Print( 1, "Useless cuts %2d = %9d (out of %9d) (%6.2f %%)\n", i, p->nCutsUseless[i], p->nCutsCount[i], 100.0*p->nCutsUseless[i]/(p->nCutsCount[i]+1) ); Abc_Print( 1, "Useless cuts all = %9d (out of %9d) (%6.2f %%)\n", p->nCutsUselessAll, p->nCutsCountAll, 100.0*p->nCutsUselessAll/(p->nCutsCountAll+1) ); } if ( p->pPars->fUseDsd ) { /* if ( p->pPars->fVerbose ) Abc_Print( 1, "Number of unique entries in the DSD table = %d. Memory = %.1f MB.\n", Abc_NamObjNumMax(p->pNamDsd), 1.0*Abc_NamMemAlloc(p->pNamDsd)/(1<<20) ); Abc_PrintTime( 1, "Time0", s_TimeComp[0] ); Abc_PrintTime( 1, "Time1", s_TimeComp[1] ); Abc_PrintTime( 1, "Time2", s_TimeComp[2] ); Abc_PrintTime( 1, "Time3", s_TimeComp[3] ); // Abc_NamPrint( p->pNamDsd ); Abc_NamStop( p->pNamDsd ); */ Dss_ManPrint( NULL, p->pDsdMan ); Dss_ManFree( p->pDsdMan ); } // Abc_PrintTime( 1, "Truth", p->timeTruth ); // Abc_Print( 1, "Small support = %d.\n", p->nSmallSupp ); Vec_IntFreeP( &p->vCoAttrs ); Vec_PtrFree( p->vCis ); Vec_PtrFree( p->vCos ); Vec_PtrFree( p->vObjs ); // Vec_PtrFree( p->vMapped ); Vec_PtrFree( p->vTemp ); Vec_IntFreeP( &p->vCover ); Vec_WrdFreeP( &p->vAnds ); Vec_WrdFreeP( &p->vAndGate ); Vec_WrdFreeP( &p->vOrGate ); if ( p->vObjsRev ) Vec_PtrFree( p->vObjsRev ); if ( p->vLatchOrder ) Vec_PtrFree( p->vLatchOrder ); if ( p->vLags ) Vec_IntFree( p->vLags ); Mem_FixedStop( p->pMemObj, 0 ); ABC_FREE( p->pMemCi ); ABC_FREE( p->pMemAnd ); ABC_FREE( p->puTemp[0] ); ABC_FREE( p->pCutTemp ); // free pars memory ABC_FREE( p->pPars->pTimesArr ); ABC_FREE( p->pPars->pTimesReq ); if ( p->pManTim ) Tim_ManStop( p->pManTim ); if ( p->vSwitching ) Vec_IntFree( p->vSwitching ); // hash table // if ( p->pPars->fVerbose && p->nTableEntries[0] ) // printf( "Hash table 2: Entries = %7d. Size = %7d.\n", p->nTableEntries[0], p->nTableSize[0] ); // if ( p->pPars->fVerbose && p->nTableEntries[1] ) // printf( "Hash table 3: Entries = %7d. Size = %7d.\n", p->nTableEntries[1], p->nTableSize[1] ); ABC_FREE( p->pHashTable[0] ); ABC_FREE( p->pHashTable[1] ); if ( p->pMemEntries ) Mem_FixedStop( p->pMemEntries, 0 ); ABC_FREE( p->pName ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Creates primary input.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateCi( If_Man_t * p ) { If_Obj_t * pObj; pObj = If_ManSetupObj( p ); pObj->Type = IF_CI; pObj->IdPio = Vec_PtrSize( p->vCis ); Vec_PtrPush( p->vCis, pObj ); p->nObjs[IF_CI]++; return pObj; } /**Function************************************************************* Synopsis [Creates primary output with the given driver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateCo( If_Man_t * p, If_Obj_t * pDriver ) { If_Obj_t * pObj; pObj = If_ManSetupObj( p ); pObj->IdPio = Vec_PtrSize( p->vCos ); Vec_PtrPush( p->vCos, pObj ); pObj->Type = IF_CO; pObj->fCompl0 = If_IsComplement(pDriver); pDriver = If_Regular(pDriver); pObj->pFanin0 = pDriver; pDriver->nRefs++; pObj->fPhase = (pObj->fCompl0 ^ pDriver->fPhase); pObj->Level = pDriver->Level; if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; p->nObjs[IF_CO]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateAnd( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) { If_Obj_t * pObj; // perform constant propagation if ( pFan0 == pFan1 ) return pFan0; if ( pFan0 == If_Not(pFan1) ) return If_Not(p->pConst1); if ( If_Regular(pFan0) == p->pConst1 ) return pFan0 == p->pConst1 ? pFan1 : If_Not(p->pConst1); if ( If_Regular(pFan1) == p->pConst1 ) return pFan1 == p->pConst1 ? pFan0 : If_Not(p->pConst1); // get memory for the new object pObj = If_ManSetupObj( p ); pObj->Type = IF_AND; pObj->fCompl0 = If_IsComplement(pFan0); pFan0 = If_Regular(pFan0); pObj->fCompl1 = If_IsComplement(pFan1); pFan1 = If_Regular(pFan1); pObj->pFanin0 = pFan0; pFan0->nRefs++; pFan0->nVisits++; pFan0->nVisitsCopy++; pObj->pFanin1 = pFan1; pFan1->nRefs++; pFan1->nVisits++; pFan1->nVisitsCopy++; pObj->fPhase = (pObj->fCompl0 ^ pFan0->fPhase) & (pObj->fCompl1 ^ pFan1->fPhase); pObj->Level = 1 + IF_MAX( pFan0->Level, pFan1->Level ); if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; p->nObjs[IF_AND]++; return pObj; } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateXor( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1 ) { If_Obj_t * pRes1, * pRes2; pRes1 = If_ManCreateAnd( p, If_Not(pFan0), pFan1 ); pRes2 = If_ManCreateAnd( p, pFan0, If_Not(pFan1) ); return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); } /**Function************************************************************* Synopsis [Create the new node assuming it does not exist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManCreateMux( If_Man_t * p, If_Obj_t * pFan0, If_Obj_t * pFan1, If_Obj_t * pCtrl ) { If_Obj_t * pRes1, * pRes2; pRes1 = If_ManCreateAnd( p, pFan0, If_Not(pCtrl) ); pRes2 = If_ManCreateAnd( p, pFan1, pCtrl ); return If_Not( If_ManCreateAnd( p, If_Not(pRes1), If_Not(pRes2) ) ); } /**Function************************************************************* Synopsis [Creates the choice node.] Description [Should be called after the equivalence class nodes are linked.] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManCreateChoice( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pTemp; // mark the node as a representative if its class assert( pObj->fRepr == 0 ); pObj->fRepr = 1; // update the level of this node (needed for correct required time computation) for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) { pObj->Level = IF_MAX( pObj->Level, pTemp->Level ); pTemp->nVisits++; pTemp->nVisitsCopy++; } // mark the largest level if ( p->nLevelMax < (int)pObj->Level ) p->nLevelMax = (int)pObj->Level; p->nChoices++; } /**Function************************************************************* Synopsis [Prepares memory for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupCut( If_Man_t * p, If_Cut_t * pCut ) { memset( pCut, 0, sizeof(If_Cut_t) ); pCut->nLimit = p->pPars->nLutSize; pCut->pLeaves = (int *)(pCut + 1); if ( p->pPars->fUsePerm ) pCut->pPerm = (char *)(pCut->pLeaves + p->pPars->nLutSize); if ( p->pPars->fTruth ) pCut->pTruth = (unsigned *)pCut->pLeaves + p->pPars->nLutSize + p->nPermWords; } /**Function************************************************************* Synopsis [Prepares memory for one cutset.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupSet( If_Man_t * p, If_Set_t * pSet ) { char * pArray; int i; pSet->nCuts = 0; pSet->nCutsMax = p->pPars->nCutsMax; pSet->ppCuts = (If_Cut_t **)(pSet + 1); pArray = (char *)pSet->ppCuts + sizeof(If_Cut_t *) * (pSet->nCutsMax+1); for ( i = 0; i <= pSet->nCutsMax; i++ ) { pSet->ppCuts[i] = (If_Cut_t *)(pArray + i * p->nCutBytes); If_ManSetupCut( p, pSet->ppCuts[i] ); } // pArray += (pSet->nCutsMax + 1) * p->nCutBytes; // assert( ((char *)pArray) - ((char *)pSet) == p->nSetBytes ); } /**Function************************************************************* Synopsis [Prepares memory for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupCutTriv( If_Man_t * p, If_Cut_t * pCut, int ObjId ) { pCut->fCompl = 0; pCut->nLimit = p->pPars->nLutSize; pCut->nLeaves = 1; pCut->pLeaves[0] = p->pPars->fLiftLeaves? (ObjId << 8) : ObjId; pCut->uSign = If_ObjCutSign( pCut->pLeaves[0] ); if ( p->pPars->fUseDsd ) { pCut->iDsd = p->iNamVar; pCut->pPerm[0] = 0; } // set up elementary truth table of the unit cut if ( p->pPars->fTruth ) { int i, nTruthWords = If_CutTruthWords(pCut->nLimit); for ( i = 0; i < nTruthWords; i++ ) If_CutTruth(pCut)[i] = 0xAAAAAAAA; } assert( pCut->pLeaves[0] < p->vObjs->nSize ); } /**Function************************************************************* Synopsis [Prepares memory for the node with cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ If_Obj_t * If_ManSetupObj( If_Man_t * p ) { If_Obj_t * pObj; // get memory for the object pObj = (If_Obj_t *)Mem_FixedEntryFetch( p->pMemObj ); memset( pObj, 0, sizeof(If_Obj_t) ); If_ManSetupCut( p, &pObj->CutBest ); // assign ID and save pObj->Id = Vec_PtrSize(p->vObjs); Vec_PtrPush( p->vObjs, pObj ); // set the required times pObj->Required = IF_FLOAT_LARGE; return pObj; } /**Function************************************************************* Synopsis [Prepares memory for one cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupCiCutSets( If_Man_t * p ) { If_Obj_t * pObj; int i; assert( p->pMemCi == NULL ); // create elementary cuts for the CIs If_ManForEachCi( p, pObj, i ) If_ManSetupCutTriv( p, &pObj->CutBest, pObj->Id ); // create elementary cutsets for the CIs p->pMemCi = (If_Set_t *)ABC_ALLOC( char, If_ManCiNum(p) * (sizeof(If_Set_t) + sizeof(void *)) ); If_ManForEachCi( p, pObj, i ) { pObj->pCutSet = (If_Set_t *)((char *)p->pMemCi + i * (sizeof(If_Set_t) + sizeof(void *))); pObj->pCutSet->nCuts = 1; pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; pObj->pCutSet->ppCuts = (If_Cut_t **)(pObj->pCutSet + 1); pObj->pCutSet->ppCuts[0] = &pObj->CutBest; } } /**Function************************************************************* Synopsis [Prepares cutset of the node.] Description [Elementary cutset will be added last.] SideEffects [] SeeAlso [] ***********************************************************************/ If_Set_t * If_ManSetupNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) { assert( If_ObjIsAnd(pObj) ); assert( pObj->pCutSet == NULL ); // pObj->pCutSet = (If_Set_t *)Mem_FixedEntryFetch( p->pMemSet ); // If_ManSetupSet( p, pObj->pCutSet ); pObj->pCutSet = If_ManCutSetFetch( p ); pObj->pCutSet->nCuts = 0; pObj->pCutSet->nCutsMax = p->pPars->nCutsMax; return pObj->pCutSet; } /**Function************************************************************* Synopsis [Dereferences cutset of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManDerefNodeCutSet( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pFanin; assert( If_ObjIsAnd(pObj) ); // consider the node assert( pObj->nVisits >= 0 ); if ( pObj->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pObj->pCutSet ); If_ManCutSetRecycle( p, pObj->pCutSet ); pObj->pCutSet = NULL; } // consider the first fanin pFanin = If_ObjFanin0(pObj); assert( pFanin->nVisits > 0 ); if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); If_ManCutSetRecycle( p, pFanin->pCutSet ); pFanin->pCutSet = NULL; } // consider the second fanin pFanin = If_ObjFanin1(pObj); assert( pFanin->nVisits > 0 ); if ( !If_ObjIsCi(pFanin) && --pFanin->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pFanin->pCutSet ); If_ManCutSetRecycle( p, pFanin->pCutSet ); pFanin->pCutSet = NULL; } } /**Function************************************************************* Synopsis [Dereferences cutset of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManDerefChoiceCutSet( If_Man_t * p, If_Obj_t * pObj ) { If_Obj_t * pTemp; assert( If_ObjIsAnd(pObj) ); assert( pObj->fRepr ); assert( pObj->nVisits > 0 ); // consider the nodes in the choice class for ( pTemp = pObj; pTemp; pTemp = pTemp->pEquiv ) { // assert( pTemp == pObj || pTemp->nVisits == 1 ); if ( --pTemp->nVisits == 0 ) { // Mem_FixedEntryRecycle( p->pMemSet, (char *)pTemp->pCutSet ); If_ManCutSetRecycle( p, pTemp->pCutSet ); pTemp->pCutSet = NULL; } } } /**Function************************************************************* Synopsis [Dereferences cutset of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void If_ManSetupSetAll( If_Man_t * p, int nCrossCut ) { If_Set_t * pCutSet; int i, nCutSets; nCutSets = 128 + nCrossCut; p->pFreeList = p->pMemAnd = pCutSet = (If_Set_t *)ABC_ALLOC( char, nCutSets * p->nSetBytes ); for ( i = 0; i < nCutSets; i++ ) { If_ManSetupSet( p, pCutSet ); if ( i == nCutSets - 1 ) pCutSet->pNext = NULL; else pCutSet->pNext = (If_Set_t *)( (char *)pCutSet + p->nSetBytes ); pCutSet = pCutSet->pNext; } assert( pCutSet == NULL ); if ( p->pPars->fVerbose ) { Abc_Print( 1, "Node = %7d. Ch = %5d. Total mem = %7.2f MB. Peak cut mem = %7.2f MB.\n", If_ManAndNum(p), p->nChoices, 1.0 * (p->nObjBytes + 2*sizeof(void *)) * If_ManObjNum(p) / (1<<20), 1.0 * p->nSetBytes * nCrossCut / (1<<20) ); } // Abc_Print( 1, "Cross cut = %d.\n", nCrossCut ); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END