/**CFile**************************************************************** FileName [fpgaCut.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: fpgaCut.c,v 1.3 2004/07/06 04:55:57 alanmi Exp $] ***********************************************************************/ #include "fpgaInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// typedef struct Fpga_CutTableStrutct_t Fpga_CutTable_t; struct Fpga_CutTableStrutct_t { Fpga_Cut_t ** pBins; // the table used for linear probing int nBins; // the size of the table int * pCuts; // the array of cuts currently stored int nCuts; // the number of cuts currently stored Fpga_Cut_t ** pArray; // the temporary array of cuts Fpga_Cut_t ** pCuts1; // the temporary array of cuts Fpga_Cut_t ** pCuts2; // the temporary array of cuts }; // the largest number of cuts considered //#define FPGA_CUTS_MAX_COMPUTE 500 #define FPGA_CUTS_MAX_COMPUTE 2000 // the largest number of cuts used //#define FPGA_CUTS_MAX_USE 200 #define FPGA_CUTS_MAX_USE 1000 // primes used to compute the hash key static int s_HashPrimes[10] = { 109, 499, 557, 619, 631, 709, 797, 881, 907, 991 }; static int bit_count[256] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8 }; #define FPGA_COUNT_ONES(u) (bit_count[(u)&255]+bit_count[((u)>>8)&255]+bit_count[((u)>>16)&255]+bit_count[(u)>>24]) static Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ); static void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ); static Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ); static int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ); static Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ); static int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ); extern Fpga_Cut_t * Fpga_CutAlloc( Fpga_Man_t * p ); extern int Fpga_CutCountAll( Fpga_Man_t * pMan ); static void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); static void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ); static void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ); static Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ); static void Fpga_CutTableStop( Fpga_CutTable_t * p ); static unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ); static int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); static Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ); static void Fpga_CutTableRestart( Fpga_CutTable_t * p ); static int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ); static Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ); static int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ); static Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ); // iterator through all the cuts of the list #define Fpga_ListForEachCut( pList, pCut ) \ for ( pCut = pList; \ pCut; \ pCut = pCut->pNext ) #define Fpga_ListForEachCutSafe( pList, pCut, pCut2 ) \ for ( pCut = pList, \ pCut2 = pCut? pCut->pNext: NULL; \ pCut; \ pCut = pCut2, \ pCut2 = pCut? pCut->pNext: NULL ) //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the cuts for each node in the object graph.] Description [The cuts are computed in one sweep over the mapping graph. First, the elementary cuts, which include the node itself, are assigned to the PI nodes. The internal nodes are considered in the DFS order. Each node is two-input AND-gate. So to compute the cuts at a node, we need to merge the sets of cuts of its two predecessors. The merged set contains only unique cuts with the number of inputs equal to k or less. Finally, the elementary cut, composed of the node itself, is added to the set of cuts for the node. This procedure is pretty fast for 5-feasible cuts, but it dramatically slows down on some "dense" networks when computing 6-feasible cuts. The problem is that there are too many cuts in this case. We should think how to heuristically trim the number of cuts in such cases, to have reasonable runtime.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingCuts( Fpga_Man_t * p ) { ProgressBar * pProgress; Fpga_CutTable_t * pTable; Fpga_Node_t * pNode; int nCuts, nNodes, i; clock_t clk = clock(); // set the elementary cuts for the PI variables assert( p->nVarsMax > 1 && p->nVarsMax < 11 ); Fpga_MappingCreatePiCuts( p ); // compute the cuts for the internal nodes nNodes = p->vAnds->nSize; pProgress = Extra_ProgressBarStart( stdout, nNodes ); pTable = Fpga_CutTableStart( p ); for ( i = 0; i < nNodes; i++ ) { Extra_ProgressBarUpdate( pProgress, i, "Cuts ..." ); pNode = p->vAnds->pArray[i]; if ( !Fpga_NodeIsAnd( pNode ) ) continue; Fpga_CutCompute( p, pTable, pNode ); } Extra_ProgressBarStop( pProgress ); Fpga_CutTableStop( pTable ); // report the stats if ( p->fVerbose ) { nCuts = Fpga_CutCountAll(p); printf( "Nodes = %6d. Total %d-cuts = %d. Cuts per node = %.1f. ", p->nNodes, p->nVarsMax, nCuts, ((float)nCuts)/p->nNodes ); ABC_PRT( "Time", clock() - clk ); } // print the cuts for the first primary output // Fpga_CutListPrint( p, Fpga_Regular(p->pOutputs[0]) ); } /**Function************************************************************* Synopsis [Performs technology mapping for variable-size-LUTs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_MappingCreatePiCuts( Fpga_Man_t * p ) { Fpga_Cut_t * pCut; int i; // set the elementary cuts for the PI variables for ( i = 0; i < p->nInputs; i++ ) { pCut = Fpga_CutAlloc( p ); pCut->nLeaves = 1; pCut->ppLeaves[0] = p->pInputs[i]; pCut->uSign = (1 << (i%31)); p->pInputs[i]->pCuts = pCut; p->pInputs[i]->pCutBest = pCut; // set the input arrival times // p->pInputs[i]->pCut[1]->tArrival = p->pInputArrivals[i]; } } /**Function************************************************************* Synopsis [Computes the cuts for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutCompute( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Node_t * pNode ) { Fpga_Node_t * pTemp; Fpga_Cut_t * pList, * pList1, * pList2; Fpga_Cut_t * pCut; int fTree = 0; int fPivot1 = fTree && (Fpga_NodeReadRef(pNode->p1)>2); int fPivot2 = fTree && (Fpga_NodeReadRef(pNode->p2)>2); // if the cuts are computed return them if ( pNode->pCuts ) return pNode->pCuts; // compute the cuts for the children pList1 = Fpga_Regular(pNode->p1)->pCuts; pList2 = Fpga_Regular(pNode->p2)->pCuts; // merge the lists pList = Fpga_CutMergeLists( p, pTable, pList1, pList2, Fpga_IsComplement(pNode->p1), Fpga_IsComplement(pNode->p2), fPivot1, fPivot2 ); // if there are functionally equivalent nodes, union them with this list assert( pList ); // only add to the list of cuts if the node is a representative one if ( pNode->pRepr == NULL ) { for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) { assert( pTemp->pCuts ); pList = Fpga_CutUnionLists( pList, pTemp->pCuts ); assert( pTemp->pCuts ); pList = Fpga_CutSortCuts( p, pTable, pList ); } } // add the new cut pCut = Fpga_CutAlloc( p ); pCut->nLeaves = 1; pCut->ppLeaves[0] = pNode; pCut->uSign = (1 << (pNode->Num%31)); pCut->fLevel = (float)pCut->ppLeaves[0]->Level; // append (it is important that the elementary cut is appended first) pCut->pNext = pList; // set at the node pNode->pCuts = pCut; // remove the dominated cuts // Fpga_CutFilter( p, pNode ); // set the phase correctly if ( pNode->pRepr && Fpga_NodeComparePhase(pNode, pNode->pRepr) ) { Fpga_ListForEachCut( pNode->pCuts, pCut ) pCut->Phase = 1; } /* { Fpga_Cut_t * pPrev; int i, Counter = 0; for ( pCut = pNode->pCuts->pNext, pPrev = pNode->pCuts; pCut; pCut = pCut->pNext ) { for ( i = 0; i < pCut->nLeaves; i++ ) if ( pCut->ppLeaves[i]->Level >= pNode->Level ) break; if ( i != pCut->nLeaves ) pPrev->pNext = pCut->pNext; else pPrev = pCut; } } { int i, Counter = 0;; for ( pCut = pNode->pCuts->pNext; pCut; pCut = pCut->pNext ) for ( i = 0; i < pCut->nLeaves; i++ ) Counter += (pCut->ppLeaves[i]->Level >= pNode->Level); if ( Counter ) printf( " %d", Counter ); } */ return pCut; } /**Function************************************************************* Synopsis [Filter the cuts using dominance.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutFilter( Fpga_Man_t * p, Fpga_Node_t * pNode ) { Fpga_Cut_t * pTemp, * pPrev, * pCut, * pCut2; int i, k, Counter; Counter = 0; pPrev = pNode->pCuts; Fpga_ListForEachCutSafe( pNode->pCuts->pNext, pCut, pCut2 ) { // go through all the previous cuts up to pCut for ( pTemp = pNode->pCuts->pNext; pTemp != pCut; pTemp = pTemp->pNext ) { // check if every node in pTemp is contained in pCut for ( i = 0; i < pTemp->nLeaves; i++ ) { for ( k = 0; k < pCut->nLeaves; k++ ) if ( pTemp->ppLeaves[i] == pCut->ppLeaves[k] ) break; if ( k == pCut->nLeaves ) // node i in pTemp is not contained in pCut break; } if ( i == pTemp->nLeaves ) // every node in pTemp is contained in pCut { Counter++; break; } } if ( pTemp != pCut ) // pTemp contain pCut { pPrev->pNext = pCut->pNext; // skip pCut // recycle pCut Fpga_CutFree( p, pCut ); } else pPrev = pCut; } // printf( "Dominated = %3d. \n", Counter ); } /**Function************************************************************* Synopsis [Merges two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutMergeLists( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) { Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; Fpga_Cut_t ** ppArray1, ** ppArray2, ** ppArray3; int nCuts1, nCuts2, nCuts3, k, fComp3; ppArray1 = pTable->pCuts1; ppArray2 = pTable->pCuts2; nCuts1 = Fpga_CutList2Array( ppArray1, pList1 ); nCuts2 = Fpga_CutList2Array( ppArray2, pList2 ); if ( fPivot1 ) nCuts1 = 1; if ( fPivot2 ) nCuts2 = 1; // swap the lists based on their length if ( nCuts1 > nCuts2 ) { ppArray3 = ppArray1; ppArray1 = ppArray2; ppArray2 = ppArray3; nCuts3 = nCuts1; nCuts1 = nCuts2; nCuts2 = nCuts3; fComp3 = fComp1; fComp1 = fComp2; fComp2 = fComp3; } // pList1 is shorter or equal length compared to pList2 // prepare the manager for the cut computation Fpga_CutTableRestart( pTable ); // go through the cut pairs Counter = 0; // for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) // for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) for ( i = 0; i < nCuts1; i++ ) { for ( k = 0; k <= i; k++ ) { pTemp1 = ppArray1[i]; pTemp2 = ppArray2[k]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // create the signature pCut->uSign = pTemp1->uSign | pTemp2->uSign; // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } for ( k = 0; k < i; k++ ) { pTemp1 = ppArray1[k]; pTemp2 = ppArray2[i]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; } // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // create the signature pCut->uSign = pTemp1->uSign | pTemp2->uSign; // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } } // consider the rest of them for ( i = nCuts1; i < nCuts2; i++ ) for ( k = 0; k < nCuts1; k++ ) { pTemp1 = ppArray1[k]; pTemp2 = ppArray2[i]; if ( pTemp1->nLeaves == p->nVarsMax && pTemp2->nLeaves == p->nVarsMax ) { if ( pTemp1->ppLeaves[0] != pTemp2->ppLeaves[0] ) continue; if ( pTemp1->ppLeaves[1] != pTemp2->ppLeaves[1] ) continue; if ( pTemp1->ppLeaves[2] != pTemp2->ppLeaves[2] ) continue; } // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // create the signature pCut->uSign = pTemp1->uSign | pTemp2->uSign; // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } QUITS : // combine all the lists into one pListNew = NULL; ppListNew = &pListNew; for ( i = 1; i <= p->nVarsMax; i++ ) { if ( pLists[i] == NULL ) continue; // find the last entry for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; pPrev = pCut, pCut = pCut->pNext ); // connect these lists *ppListNew = pLists[i]; ppListNew = &pPrev->pNext; } *ppListNew = NULL; // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); return pListNew; } /**Function************************************************************* Synopsis [Merges two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutMergeLists2( Fpga_Man_t * p, Fpga_CutTable_t * pTable, Fpga_Cut_t * pList1, Fpga_Cut_t * pList2, int fComp1, int fComp2, int fPivot1, int fPivot2 ) { Fpga_Node_t * ppNodes[FPGA_MAX_LEAVES]; Fpga_Cut_t * pListNew, ** ppListNew, * pLists[FPGA_MAX_LEAVES+1] = { NULL }; Fpga_Cut_t * pCut, * pPrev, * pTemp1, * pTemp2; int nNodes, Counter, i; // prepare the manager for the cut computation Fpga_CutTableRestart( pTable ); // go through the cut pairs Counter = 0; for ( pTemp1 = pList1; pTemp1; pTemp1 = fPivot1? NULL: pTemp1->pNext ) for ( pTemp2 = pList2; pTemp2; pTemp2 = fPivot2? NULL: pTemp2->pNext ) { // check if k-feasible cut exists nNodes = Fpga_CutMergeTwo( pTemp1, pTemp2, ppNodes, p->nVarsMax ); if ( nNodes == 0 ) continue; // consider the cut for possible addition to the set of new cuts pCut = Fpga_CutTableConsider( p, pTable, ppNodes, nNodes ); if ( pCut == NULL ) continue; // add data to the cut pCut->pOne = Fpga_CutNotCond( pTemp1, fComp1 ); pCut->pTwo = Fpga_CutNotCond( pTemp2, fComp2 ); // add it to the corresponding list pCut->pNext = pLists[(int)pCut->nLeaves]; pLists[(int)pCut->nLeaves] = pCut; // count this cut and quit if limit is reached Counter++; if ( Counter == FPGA_CUTS_MAX_COMPUTE ) goto QUITS; } QUITS : // combine all the lists into one pListNew = NULL; ppListNew = &pListNew; for ( i = 1; i <= p->nVarsMax; i++ ) { if ( pLists[i] == NULL ) continue; // find the last entry for ( pPrev = pLists[i], pCut = pPrev->pNext; pCut; pPrev = pCut, pCut = pCut->pNext ); // connect these lists *ppListNew = pLists[i]; ppListNew = &pPrev->pNext; } *ppListNew = NULL; // sort the cuts by arrival times and use only the first FPGA_CUTS_MAX_USE pListNew = Fpga_CutSortCuts( p, pTable, pListNew ); return pListNew; } /**Function************************************************************* Synopsis [Merges two cuts.] Description [Returns the number of nodes in the resulting cut, or 0 if the cut is infeasible. Returns the resulting nodes in the array ppNodes[].] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutMergeTwo( Fpga_Cut_t * pCut1, Fpga_Cut_t * pCut2, Fpga_Node_t * ppNodes[], int nNodesMax ) { Fpga_Node_t * pNodeTemp; int nTotal, i, k, min, Counter; unsigned uSign; // use quick prefiltering uSign = pCut1->uSign | pCut2->uSign; Counter = FPGA_COUNT_ONES(uSign); if ( Counter > nNodesMax ) return 0; /* // check the special case when at least of the cuts is the largest if ( pCut1->nLeaves == nNodesMax ) { if ( pCut2->nLeaves == nNodesMax ) { // return 0 if the cuts are different for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i] ) return 0; // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut1->ppLeaves[i]; return nNodesMax; } else if ( pCut2->nLeaves == nNodesMax - 1 ) { // return 0 if the cuts are different fMismatch = 0; for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i] != pCut2->ppLeaves[i - fMismatch] ) { if ( fMismatch == 1 ) return 0; fMismatch = 1; } // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut1->ppLeaves[i]; return nNodesMax; } } else if ( pCut1->nLeaves == nNodesMax - 1 && pCut2->nLeaves == nNodesMax ) { // return 0 if the cuts are different fMismatch = 0; for ( i = 0; i < nNodesMax; i++ ) if ( pCut1->ppLeaves[i - fMismatch] != pCut2->ppLeaves[i] ) { if ( fMismatch == 1 ) return 0; fMismatch = 1; } // return nNodesMax if they are the same for ( i = 0; i < nNodesMax; i++ ) ppNodes[i] = pCut2->ppLeaves[i]; return nNodesMax; } */ // count the number of unique entries in pCut2 nTotal = pCut1->nLeaves; for ( i = 0; i < pCut2->nLeaves; i++ ) { // try to find this entry among the leaves of pCut1 for ( k = 0; k < pCut1->nLeaves; k++ ) if ( pCut2->ppLeaves[i] == pCut1->ppLeaves[k] ) break; if ( k < pCut1->nLeaves ) // found continue; // we found a new entry to add if ( nTotal == nNodesMax ) return 0; ppNodes[nTotal++] = pCut2->ppLeaves[i]; } // we know that the feasible cut exists // add the starting entries for ( k = 0; k < pCut1->nLeaves; k++ ) ppNodes[k] = pCut1->ppLeaves[k]; // selection-sort the entries for ( i = 0; i < nTotal - 1; i++ ) { min = i; for ( k = i+1; k < nTotal; k++ ) // if ( ppNodes[k] < ppNodes[min] ) // reported bug fix (non-determinism!) if ( ppNodes[k]->Num < ppNodes[min]->Num ) min = k; pNodeTemp = ppNodes[i]; ppNodes[i] = ppNodes[min]; ppNodes[min] = pNodeTemp; } return nTotal; } /**Function************************************************************* Synopsis [Computes the union of the two lists of cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutUnionLists( Fpga_Cut_t * pList1, Fpga_Cut_t * pList2 ) { Fpga_Cut_t * pTemp, * pRoot; // find the last cut in the first list pRoot = pList1; Fpga_ListForEachCut( pList1, pTemp ) pRoot = pTemp; // attach the non-trival part of the second cut to the end of the first assert( pRoot->pNext == NULL ); pRoot->pNext = pList2->pNext; pList2->pNext = NULL; return pList1; } /**Function************************************************************* Synopsis [Checks whether the given cut belongs to the list.] Description [This procedure takes most of the runtime in the cut computation.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutBelongsToList( Fpga_Cut_t * pList, Fpga_Node_t * ppNodes[], int nNodes ) { Fpga_Cut_t * pTemp; int i; for ( pTemp = pList; pTemp; pTemp = pTemp->pNext ) { for ( i = 0; i < nNodes; i++ ) if ( pTemp->ppLeaves[i] != ppNodes[i] ) break; if ( i == nNodes ) return 1; } return 0; } /**Function************************************************************* Synopsis [Counts all the cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutCountAll( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i, nCuts; // go through all the nodes in the unique table of the manager nCuts = 0; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) if ( pCut->nLeaves > 1 ) // skip the elementary cuts { // Fpga_CutVolume( pCut ); nCuts++; } return nCuts; } /**Function************************************************************* Synopsis [Clean the signatures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutsCleanSign( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) pCut->uSign = 0; } /**Function************************************************************* Synopsis [Clean the signatures.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutsCleanRoot( Fpga_Man_t * pMan ) { Fpga_Node_t * pNode; Fpga_Cut_t * pCut; int i; for ( i = 0; i < pMan->nBins; i++ ) for ( pNode = pMan->pBins[i]; pNode; pNode = pNode->pNext ) for ( pCut = pNode->pCuts; pCut; pCut = pCut->pNext ) pCut->pRoot = NULL; } /**Function************************************************************* Synopsis [Prints the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutListPrint( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) { Fpga_Cut_t * pTemp; int Counter; for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) { printf( "%2d : ", Counter + 1 ); Fpga_CutPrint_( pMan, pTemp, pRoot ); } } /**Function************************************************************* Synopsis [Prints the cuts in the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutListPrint2( Fpga_Man_t * pMan, Fpga_Node_t * pRoot ) { Fpga_Cut_t * pTemp; int Counter; for ( Counter = 0, pTemp = pRoot->pCuts; pTemp; pTemp = pTemp->pNext, Counter++ ) { printf( "%2d : ", Counter + 1 ); Fpga_CutPrint_( pMan, pTemp, pRoot ); } } /**Function************************************************************* Synopsis [Prints the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutPrint_( Fpga_Man_t * pMan, Fpga_Cut_t * pCut, Fpga_Node_t * pRoot ) { int i; printf( "(%3d) {", pRoot->Num ); for ( i = 0; i < pMan->nVarsMax; i++ ) if ( pCut->ppLeaves[i] ) printf( " %3d", pCut->ppLeaves[i]->Num ); printf( " }\n" ); } /**Function************************************************************* Synopsis [Starts the hash table to canonicize cuts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_CutTable_t * Fpga_CutTableStart( Fpga_Man_t * pMan ) { Fpga_CutTable_t * p; // allocate the table p = ABC_ALLOC( Fpga_CutTable_t, 1 ); memset( p, 0, sizeof(Fpga_CutTable_t) ); p->nBins = Abc_PrimeCudd( 10 * FPGA_CUTS_MAX_COMPUTE ); p->pBins = ABC_ALLOC( Fpga_Cut_t *, p->nBins ); memset( p->pBins, 0, sizeof(Fpga_Cut_t *) * p->nBins ); p->pCuts = ABC_ALLOC( int, 2 * FPGA_CUTS_MAX_COMPUTE ); p->pArray = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); p->pCuts1 = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); p->pCuts2 = ABC_ALLOC( Fpga_Cut_t *, 2 * FPGA_CUTS_MAX_COMPUTE ); return p; } /**Function************************************************************* Synopsis [Stops the hash table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutTableStop( Fpga_CutTable_t * p ) { ABC_FREE( p->pCuts1 ); ABC_FREE( p->pCuts2 ); ABC_FREE( p->pArray ); ABC_FREE( p->pBins ); ABC_FREE( p->pCuts ); ABC_FREE( p ); } /**Function************************************************************* Synopsis [Computes the hash value of the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Fpga_CutTableHash( Fpga_Node_t * ppNodes[], int nNodes ) { unsigned uRes; int i; uRes = 0; for ( i = 0; i < nNodes; i++ ) uRes += s_HashPrimes[i] * ppNodes[i]->Num; return uRes; } /**Function************************************************************* Synopsis [Looks up the table for the available cut.] Description [Returns -1 if the same cut is found. Returns the index of the cell where the cut should be added, if it does not exist.] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutTableLookup( Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) { Fpga_Cut_t * pCut; unsigned Key; int b, i; Key = Fpga_CutTableHash(ppNodes, nNodes) % p->nBins; for ( b = Key; p->pBins[b]; b = (b+1) % p->nBins ) { pCut = p->pBins[b]; if ( pCut->nLeaves != nNodes ) continue; for ( i = 0; i < nNodes; i++ ) if ( pCut->ppLeaves[i] != ppNodes[i] ) break; if ( i == nNodes ) return -1; } return b; } /**Function************************************************************* Synopsis [Starts the hash table to canonicize cuts.] Description [Considers addition of the cut to the hash table.] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutTableConsider( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Node_t * ppNodes[], int nNodes ) { Fpga_Cut_t * pCut; int Place, i; // check the cut Place = Fpga_CutTableLookup( p, ppNodes, nNodes ); if ( Place == -1 ) return NULL; assert( nNodes > 0 ); // create the new cut pCut = Fpga_CutAlloc( pMan ); pCut->nLeaves = nNodes; pCut->fLevel = 0.0; for ( i = 0; i < nNodes; i++ ) { pCut->ppLeaves[i] = ppNodes[i]; pCut->fLevel += ppNodes[i]->Level; } pCut->fLevel /= nNodes; // add the cut to the table assert( p->pBins[Place] == NULL ); p->pBins[Place] = pCut; // add the cut to the new list p->pCuts[ p->nCuts++ ] = Place; return pCut; } /**Function************************************************************* Synopsis [Prepares the table to be used with other cuts.] Description [Restarts the table by cleaning the info about cuts stored when the previous node was considered.] SideEffects [] SeeAlso [] ***********************************************************************/ void Fpga_CutTableRestart( Fpga_CutTable_t * p ) { int i; for ( i = 0; i < p->nCuts; i++ ) { assert( p->pBins[ p->pCuts[i] ] ); p->pBins[ p->pCuts[i] ] = NULL; } p->nCuts = 0; } /**Function************************************************************* Synopsis [Compares the cuts by the number of leaves and then by delay.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutSortCutsCompare( Fpga_Cut_t ** pC1, Fpga_Cut_t ** pC2 ) { if ( (*pC1)->nLeaves < (*pC2)->nLeaves ) return -1; if ( (*pC1)->nLeaves > (*pC2)->nLeaves ) return 1; /* if ( (*pC1)->fLevel > (*pC2)->fLevel ) return -1; if ( (*pC1)->fLevel < (*pC2)->fLevel ) return 1; */ return 0; } /**Function************************************************************* Synopsis [Sorts the cuts by average arrival time.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutSortCuts( Fpga_Man_t * pMan, Fpga_CutTable_t * p, Fpga_Cut_t * pList ) { Fpga_Cut_t * pListNew; int nCuts, i; // move the cuts from the list into the array nCuts = Fpga_CutList2Array( p->pCuts1, pList ); assert( nCuts <= FPGA_CUTS_MAX_COMPUTE ); // sort the cuts qsort( (void *)p->pCuts1, nCuts, sizeof(void *), (int (*)(const void *, const void *)) Fpga_CutSortCutsCompare ); // move them back into the list if ( nCuts > FPGA_CUTS_MAX_USE - 1 ) { // printf( "*" ); // free the remaining cuts for ( i = FPGA_CUTS_MAX_USE - 1; i < nCuts; i++ ) Extra_MmFixedEntryRecycle( pMan->mmCuts, (char *)p->pCuts1[i] ); // update the number of cuts nCuts = FPGA_CUTS_MAX_USE - 1; } pListNew = Fpga_CutArray2List( p->pCuts1, nCuts ); return pListNew; } /**Function************************************************************* Synopsis [Moves the nodes from the list into the array.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fpga_CutList2Array( Fpga_Cut_t ** pArray, Fpga_Cut_t * pList ) { int i; for ( i = 0; pList; pList = pList->pNext, i++ ) pArray[i] = pList; return i; } /**Function************************************************************* Synopsis [Moves the nodes from the array into the list.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Cut_t * Fpga_CutArray2List( Fpga_Cut_t ** pArray, int nCuts ) { Fpga_Cut_t * pListNew, ** ppListNew; int i; pListNew = NULL; ppListNew = &pListNew; for ( i = 0; i < nCuts; i++ ) { // connect these lists *ppListNew = pArray[i]; ppListNew = &pArray[i]->pNext; //printf( " %d(%.2f)", pArray[i]->nLeaves, pArray[i]->fLevel ); } //printf( "\n" ); *ppListNew = NULL; return pListNew; } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END