/**CFile**************************************************************** FileName [fpgaCutUtils.c] PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] Synopsis [Generic technology mapping engine.] Author [MVSIS Group] Affiliation [UC Berkeley] Date [Ver. 2.0. Started - August 18, 2004.] Revision [$Id: fpgaCutUtils.h,v 1.0 2003/09/08 00:00:00 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Allocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ) { Fpga_Cut_t * pCut; pCut = (Fpga_Cut_t *)Extra_MmFixedEntryFetch( p->mmCuts ); memset( pCut, 0, sizeof(Fpga_Cut_t) ); return pCut; } /**Function************************************************************* Synopsis [Duplicates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutDup( Fpga_Man_t * p, Fpga_Cut_t * pCutOld ) { Fpga_Cut_t * pCutNew; int i; pCutNew = Fpga_CutAlloc( p ); pCutNew->pRoot = pCutOld->pRoot; pCutNew->nLeaves = pCutOld->nLeaves; for ( i = 0; i < pCutOld->nLeaves; i++ ) pCutNew->ppLeaves[i] = pCutOld->ppLeaves[i]; return pCutNew; } /**Function************************************************************* Synopsis [Deallocates the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutFree( Fpga_Man_t * p, Fpga_Cut_t * pCut ) { if ( pCut ) Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pCut ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutPrint( Fpga_Man_t * p, Fpga_Node_t * pRoot, Fpga_Cut_t * pCut ) { int i; printf( "CUT: Delay = %4.2f. Area = %4.2f. Nodes = %d -> {", pCut->tArrival, pCut->aFlow, pRoot->Num ); for ( i = 0; i < pCut->nLeaves; i++ ) printf( " %d", pCut->ppLeaves[i]->Num ); printf( " } \n" ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutCreateSimple( Fpga_Man_t * p, Fpga_Node_t * pNode ) { Fpga_Cut_t * pCut; pCut = Fpga_CutAlloc( p ); pCut->pRoot = pNode; pCut->nLeaves = 1; pCut->ppLeaves[0] = pNode; pCut->uSign = FPGA_SEQ_SIGN(pCut->ppLeaves[0]); return pCut; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetRootArea( Fpga_Man_t * p, Fpga_Cut_t * pCut ) { return p->pLutLib->pLutAreas[(int)pCut->nLeaves]; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutListAppend( Fpga_Cut_t * pSetAll, Fpga_Cut_t * pSets ) { Fpga_Cut_t * pPrev = NULL; // Suppress "might be used uninitialized" Fpga_Cut_t * pTemp; if ( pSetAll == NULL ) return pSets; if ( pSets == NULL ) return pSetAll; // find the last one for ( pTemp = pSets; pTemp; pTemp = pTemp->pNext ) pPrev = pTemp; // append all the end of the current set assert( pPrev->pNext == NULL ); pPrev->pNext = pSetAll; return pSets; } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutListRecycle( Fpga_Man_t * p, Fpga_Cut_t * pSetList, Fpga_Cut_t * pSave ) { Fpga_Cut_t * pNext, * pTemp; for ( pTemp = pSetList, pNext = pTemp? pTemp->pNext : NULL; pTemp; pTemp = pNext, pNext = pNext? pNext->pNext : NULL ) if ( pTemp != pSave ) Extra_MmFixedEntryRecycle( p->mmCuts, (char *)pTemp ); } /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutListCount( Fpga_Cut_t * pSets ) { Fpga_Cut_t * pTemp; int i; for ( i = 0, pTemp = pSets; pTemp; pTemp = pTemp->pNext, i++ ); return i; } #if 0 /**function************************************************************* synopsis [Removes the fanouts of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ void Fpga_CutRemoveFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) { Fpga_NodeVec_t * vFanouts; int i, k; for ( i = 0; i < pCut->nLeaves; i++ ) { vFanouts = pCut->ppLeaves[i]->vFanouts; for ( k = 0; k < vFanouts->nSize; k++ ) if ( vFanouts->pArray[k] == pNode ) break; assert( k != vFanouts->nSize ); for ( k++; k < vFanouts->nSize; k++ ) vFanouts->pArray[k-1] = vFanouts->pArray[k]; vFanouts->nSize--; } } /**function************************************************************* synopsis [Removes the fanouts of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ void Fpga_CutInsertFanouts( Fpga_Man_t * p, Fpga_Node_t * pNode, Fpga_Cut_t * pCut ) { int i; for ( i = 0; i < pCut->nLeaves; i++ ) Fpga_NodeVecPush( pCut->ppLeaves[i]->vFanouts, pNode ); } #endif /**Function************************************************************* Synopsis [Computes the arrival time and the area flow of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutGetParameters( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { Fpga_Cut_t * pFaninCut; int i; pCut->tArrival = -FPGA_FLOAT_LARGE; pCut->aFlow = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; for ( i = 0; i < pCut->nLeaves; i++ ) { pFaninCut = pCut->ppLeaves[i]->pCutBest; if ( pCut->tArrival < pFaninCut->tArrival ) pCut->tArrival = pFaninCut->tArrival; // if the fanout count is not set, assume it to be 1 if ( pCut->ppLeaves[i]->nRefs == 0 ) pCut->aFlow += pFaninCut->aFlow; else // pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->nRefs; pCut->aFlow += pFaninCut->aFlow / pCut->ppLeaves[i]->aEstFanouts; } // use the first pin to compute the delay of the LUT // (this mapper does not support the variable pin delay model) pCut->tArrival += pMan->pLutLib->pLutDelays[(int)pCut->nLeaves][0]; } /**function************************************************************* synopsis [Computes the area flow of the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetAreaFlow( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { Fpga_Cut_t * pCutFanin; int i; pCut->aFlow = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; for ( i = 0; i < pCut->nLeaves; i++ ) { // get the cut implementing this phase of the fanin pCutFanin = pCut->ppLeaves[i]->pCutBest; assert( pCutFanin ); pCut->aFlow += pCutFanin->aFlow / pCut->ppLeaves[i]->nRefs; } return pCut->aFlow; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetAreaRefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves == 1 ) return 0; aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); return aResult; } /**function************************************************************* synopsis [Computes the exact area associated with the cut.] description [] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutGetAreaDerefed( Fpga_Man_t * pMan, Fpga_Cut_t * pCut ) { float aResult, aResult2; if ( pCut->nLeaves == 1 ) return 0; aResult2 = Fpga_CutRef( pMan, NULL, pCut, 0 ); aResult = Fpga_CutDeref( pMan, NULL, pCut, 0 ); assert( Fpga_FloatEqual( pMan, aResult, aResult2 ) ); return aResult; } /**function************************************************************* synopsis [References the cut.] description [This procedure is similar to the procedure NodeReclaim.] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutRef( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) { Fpga_Node_t * pNodeChild; float aArea; int i; // deref the fanouts // if ( fFanouts ) // Fpga_CutInsertFanouts( pMan, pNode, pCut ); // start the area of this cut aArea = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; assert( pNodeChild->nRefs >= 0 ); if ( pNodeChild->nRefs++ > 0 ) continue; if ( !Fpga_NodeIsAnd(pNodeChild) ) continue; aArea += Fpga_CutRef( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); } return aArea; } /**function************************************************************* synopsis [Dereferences the cut.] description [This procedure is similar to the procedure NodeRecusiveDeref.] sideeffects [] seealso [] ***********************************************************************/ float Fpga_CutDeref( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Cut_t * pCut, int fFanouts ) { Fpga_Node_t * pNodeChild; float aArea; int i; // deref the fanouts // if ( fFanouts ) // Fpga_CutRemoveFanouts( pMan, pNode, pCut ); // start the area of this cut aArea = pMan->pLutLib->pLutAreas[(int)pCut->nLeaves]; // go through the children for ( i = 0; i < pCut->nLeaves; i++ ) { pNodeChild = pCut->ppLeaves[i]; assert( pNodeChild->nRefs > 0 ); if ( --pNodeChild->nRefs > 0 ) continue; if ( !Fpga_NodeIsAnd(pNodeChild) ) continue; aArea += Fpga_CutDeref( pMan, pNodeChild, pNodeChild->pCutBest, fFanouts ); } return aArea; } /**Function************************************************************* Synopsis [Sets the used cuts to be the currently selected ones.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingSetUsedCuts( Fpga_Man_t * pMan ) { int i; for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) if ( pMan->vNodesAll->pArray[i]->pCutOld ) { pMan->vNodesAll->pArray[i]->pCutBest = pMan->vNodesAll->pArray[i]->pCutOld; pMan->vNodesAll->pArray[i]->pCutOld = NULL; } } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END