diff options
Diffstat (limited to 'src/map/fpga/fpgaUtils.c')
-rw-r--r-- | src/map/fpga/fpgaUtils.c | 986 |
1 files changed, 986 insertions, 0 deletions
diff --git a/src/map/fpga/fpgaUtils.c b/src/map/fpga/fpgaUtils.c new file mode 100644 index 00000000..b951fd8f --- /dev/null +++ b/src/map/fpga/fpgaUtils.c @@ -0,0 +1,986 @@ +/**CFile**************************************************************** + + FileName [fpgaUtils.c] + + PackageName [MVSIS 1.3: Multi-valued logic synthesis system.] + + Synopsis [Technology mapping for variable-size-LUT FPGAs.] + + Author [MVSIS Group] + + Affiliation [UC Berkeley] + + Date [Ver. 2.0. Started - August 18, 2004.] + + Revision [$Id: fpgaUtils.c,v 1.3 2004/07/06 04:55:58 alanmi Exp $] + +***********************************************************************/ + +#include "fpgaInt.h" + +//////////////////////////////////////////////////////////////////////// +/// DECLARATIONS /// +//////////////////////////////////////////////////////////////////////// + +#define FPGA_CO_LIST_SIZE 5 + +static void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ); +static void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ); +static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ); +static void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ); +static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ); +static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ); +static Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ); +static Fpga_Man_t * s_pMan = NULL; + +//////////////////////////////////////////////////////////////////////// +/// FUNCTION DEFINITIONS /// +//////////////////////////////////////////////////////////////////////// + + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingDfs( Fpga_Man_t * pMan, int fCollectEquiv ) +{ + Fpga_NodeVec_t * vNodes;//, * vNodesCo; + Fpga_Node_t * pNode; + int i; + // collect the CO nodes by level +// vNodesCo = Fpga_MappingOrderCosByLevel( pMan ); + // start the array + vNodes = Fpga_NodeVecAlloc( 100 ); + // collect the PIs + for ( i = 0; i < pMan->nInputs; i++ ) + { + pNode = pMan->pInputs[i]; + Fpga_NodeVecPush( vNodes, pNode ); + pNode->fMark0 = 1; + } + // perform the traversal + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_MappingDfs_rec( Fpga_Regular(pMan->pOutputs[i]), vNodes, fCollectEquiv ); +// for ( i = vNodesCo->nSize - 1; i >= 0 ; i-- ) +// for ( pNode = vNodesCo->pArray[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) +// Fpga_MappingDfs_rec( pNode, vNodes, fCollectEquiv ); + // clean the node marks + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; +// for ( i = 0; i < pMan->nOutputs; i++ ) +// Fpga_MappingUnmark_rec( Fpga_Regular(pMan->pOutputs[i]) ); +// Fpga_NodeVecFree( vNodesCo ); + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv ) +{ + assert( !Fpga_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + // visit the transitive fanin + if ( Fpga_NodeIsAnd(pNode) ) + { + Fpga_MappingDfs_rec( Fpga_Regular(pNode->p1), vNodes, fCollectEquiv ); + Fpga_MappingDfs_rec( Fpga_Regular(pNode->p2), vNodes, fCollectEquiv ); + } + // visit the equivalent nodes + if ( fCollectEquiv && pNode->pNextE ) + Fpga_MappingDfs_rec( pNode->pNextE, vNodes, fCollectEquiv ); + // make sure the node is not visited through the equivalent nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + Fpga_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingDfsNodes( Fpga_Man_t * pMan, Fpga_Node_t ** ppNodes, int nNodes, int fEquiv ) +{ + Fpga_NodeVec_t * vNodes; + int i; + // perform the traversal + vNodes = Fpga_NodeVecAlloc( 200 ); + for ( i = 0; i < nNodes; i++ ) + Fpga_MappingDfs_rec( ppNodes[i], vNodes, fEquiv ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingGetAreaFlow( Fpga_Man_t * p ) +{ + float aFlowFlowTotal = 0; + int i; + for ( i = 0; i < p->nOutputs; i++ ) + { + if ( Fpga_NodeIsConst(p->pOutputs[i]) ) + continue; + aFlowFlowTotal += Fpga_Regular(p->pOutputs[i])->pCutBest->aFlow; + } + return aFlowFlowTotal; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the current mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingArea( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode; + float aTotal; + int i; + // perform the traversal + aTotal = 0; + for ( i = 0; i < pMan->vMapping->nSize; i++ ) + { + pNode = pMan->vMapping->pArray[i]; + aTotal += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; + } + return aTotal; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes ) +{ + float aArea; + int i; + assert( !Fpga_IsComplement(pNode) ); + if ( !Fpga_NodeIsAnd(pNode) ) + return 0; + if ( pNode->fMark0 ) + return 0; + assert( pNode->pCutBest != NULL ); + // visit the transitive fanin of the selected cut + aArea = 0; + for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) + aArea += Fpga_MappingArea_rec( pMan, pNode->pCutBest->ppLeaves[i], vNodes ); + // make sure the node is not visited through the fanin nodes + assert( pNode->fMark0 == 0 ); + // mark the node as visited + pNode->fMark0 = 1; + // add the node to the list + aArea += pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; + // add the node to the list + Fpga_NodeVecPush( vNodes, pNode ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Computes the area of the current mapping.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingAreaTrav( Fpga_Man_t * pMan ) +{ + Fpga_NodeVec_t * vNodes; + float aTotal; + int i; + // perform the traversal + aTotal = 0; + vNodes = Fpga_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->nOutputs; i++ ) + aTotal += Fpga_MappingArea_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + Fpga_NodeVecFree( vNodes ); + return aTotal; +} + + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingSetRefsAndArea_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, Fpga_Node_t ** ppStore ) +{ + float aArea; + int i; + assert( !Fpga_IsComplement(pNode) ); + if ( pNode->nRefs++ ) + return 0; + if ( !Fpga_NodeIsAnd(pNode) ) + return 0; + assert( pNode->pCutBest != NULL ); + // store the node in the structure by level + pNode->pData0 = (char *)ppStore[pNode->Level]; + ppStore[pNode->Level] = pNode; + // visit the transitive fanin of the selected cut + aArea = pMan->pLutLib->pLutAreas[pNode->pCutBest->nLeaves]; + for ( i = 0; i < pNode->pCutBest->nLeaves; i++ ) + aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode->pCutBest->ppLeaves[i], ppStore ); + return aArea; +} + +/**Function************************************************************* + + Synopsis [Sets the correct reference counts for the mapping.] + + Description [Collects the nodes in reverse topological order + and places in them in array pMan->vMapping.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode, ** ppStore; + float aArea; + int i, LevelMax; + + // clean all references + for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) + pMan->vNodesAll->pArray[i]->nRefs = 0; + + // allocate place to store the nodes + LevelMax = Fpga_MappingMaxLevel( pMan ); + ppStore = ALLOC( Fpga_Node_t *, LevelMax + 1 ); + memset( ppStore, 0, sizeof(Fpga_Node_t *) * (LevelMax + 1) ); + + // collect nodes reachable from POs in the DFS order through the best cuts + aArea = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + { + pNode = Fpga_Regular(pMan->pOutputs[i]); + if ( pNode == pMan->pConst1 ) + continue; + aArea += Fpga_MappingSetRefsAndArea_rec( pMan, pNode, ppStore ); + pNode->nRefs++; + } + + // reconnect the nodes in reverse topological order + pMan->vMapping->nSize = 0; + for ( i = LevelMax; i >= 0; i-- ) + for ( pNode = ppStore[i]; pNode; pNode = (Fpga_Node_t *)pNode->pData0 ) + Fpga_NodeVecPush( pMan->vMapping, pNode ); + free( ppStore ); + return aArea; +} + + +/**Function************************************************************* + + Synopsis [Compares the outputs by their arrival times.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 ) +{ + Fpga_Node_t * pNode1 = Fpga_Regular(*ppNode1); + Fpga_Node_t * pNode2 = Fpga_Regular(*ppNode2); + float Arrival1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0; + float Arrival2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0; + if ( Arrival1 < Arrival2 ) + return -1; + if ( Arrival1 > Arrival2 ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Finds given number of latest arriving COs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax ) +{ + int nNodes, i, k, v; + assert( p->nOutputs >= nNodesMax ); + pNodes[0] = 0; + nNodes = 1; + for ( i = 1; i < p->nOutputs; i++ ) + { + for ( k = nNodes - 1; k >= 0; k-- ) + if ( Fpga_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 ) + break; + if ( k == nNodesMax - 1 ) + continue; + if ( nNodes < nNodesMax ) + nNodes++; + for ( v = nNodes - 1; v > k+1; v-- ) + pNodes[v] = pNodes[v-1]; + pNodes[k+1] = i; + } +} + +/**Function************************************************************* + + Synopsis [Prints a bunch of latest arriving outputs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p ) +{ + Fpga_Node_t * pNode; + int pSorted[FPGA_CO_LIST_SIZE]; + int fCompl, Limit, MaxNameSize, i; + + // determine the number of nodes to print + Limit = (p->nOutputs > FPGA_CO_LIST_SIZE)? FPGA_CO_LIST_SIZE : p->nOutputs; + + // determine the order + Fpga_MappingFindLatest( p, pSorted, Limit ); + + // determine max size of the node's name + MaxNameSize = 0; + for ( i = 0; i < Limit; i++ ) + if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) ) + MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]); + + // print the latest outputs + for ( i = 0; i < Limit; i++ ) + { + // get the i-th latest output + pNode = Fpga_Regular(p->pOutputs[pSorted[i]]); + fCompl = Fpga_IsComplement(p->pOutputs[pSorted[i]]); + // print out the best arrival time + printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); + printf( "Delay = %8.2f ", (double)pNode->pCutBest->tArrival ); + if ( fCompl ) + printf( "NEG" ); + else + printf( "POS" ); + printf( "\n" ); + } +} + + +/**Function************************************************************* + + Synopsis [Sets up the truth tables.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetupTruthTables( unsigned uTruths[][2] ) +{ + int m, v; + // set up the truth tables + for ( m = 0; m < 32; m++ ) + for ( v = 0; v < 5; v++ ) + if ( m & (1 << v) ) + uTruths[v][0] |= (1 << m); + // make adjustments for the case of 6 variables + for ( v = 0; v < 5; v++ ) + uTruths[v][1] = uTruths[v][0]; + uTruths[5][0] = 0; + uTruths[5][1] = FPGA_FULL; +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetupMask( unsigned uMask[], int nVarsMax ) +{ + if ( nVarsMax == 6 ) + uMask[0] = uMask[1] = FPGA_FULL; + else + { + uMask[0] = FPGA_MASK(1 << nVarsMax); + uMask[1] = 0; + } +} + +/**Function************************************************************* + + Synopsis [Verify one useful property.] + + Description [This procedure verifies one useful property. After + the FRAIG construction with choice nodes is over, each primary node + should have fanins that are primary nodes. The primary nodes is the + one that does not have pNode->pRepr set to point to another node.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_ManCheckConsistency( Fpga_Man_t * p ) +{ + Fpga_Node_t * pNode; + Fpga_NodeVec_t * pVec; + int i; + pVec = Fpga_MappingDfs( p, 0 ); + for ( i = 0; i < pVec->nSize; i++ ) + { + pNode = pVec->pArray[i]; + if ( Fpga_NodeIsVar(pNode) ) + { + if ( pNode->pRepr ) + printf( "Primary input %d is a secondary node.\n", pNode->Num ); + } + else if ( Fpga_NodeIsConst(pNode) ) + { + if ( pNode->pRepr ) + printf( "Constant 1 %d is a secondary node.\n", pNode->Num ); + } + else + { + if ( pNode->pRepr ) + printf( "Internal node %d is a secondary node.\n", pNode->Num ); + if ( Fpga_Regular(pNode->p1)->pRepr ) + printf( "Internal node %d has first fanin that is a secondary node.\n", pNode->Num ); + if ( Fpga_Regular(pNode->p2)->pRepr ) + printf( "Internal node %d has second fanin that is a secondary node.\n", pNode->Num ); + } + } + Fpga_NodeVecFree( pVec ); + return 1; +} + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CompareNodesByLevelDecreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) +{ + if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) + return -1; + if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Compares the supergates by their level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CompareNodesByLevelIncreasing( Fpga_Node_t ** ppS1, Fpga_Node_t ** ppS2 ) +{ + if ( Fpga_Regular(*ppS1)->Level < Fpga_Regular(*ppS2)->Level ) + return -1; + if ( Fpga_Regular(*ppS1)->Level > Fpga_Regular(*ppS2)->Level ) + return 1; + return 0; +} + +/**Function************************************************************* + + Synopsis [Orders the nodes in the decreasing order of levels.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSortByLevel( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes, int fIncreasing ) +{ + if ( fIncreasing ) + qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), + (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelIncreasing ); + else + qsort( (void *)vNodes->pArray, vNodes->nSize, sizeof(Fpga_Node_t *), + (int (*)(const void *, const void *)) Fpga_CompareNodesByLevelDecreasing ); +// assert( Fpga_CompareNodesByLevel( vNodes->pArray, vNodes->pArray + vNodes->nSize - 1 ) <= 0 ); +} + +/**Function************************************************************* + + Synopsis [Computes the limited DFS ordering for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_DfsLim( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int nLevels ) +{ + Fpga_NodeVec_t * vNodes; + int i; + // perform the traversal + vNodes = Fpga_NodeVecAlloc( 100 ); + Fpga_DfsLim_rec( pNode, nLevels, vNodes ); + for ( i = 0; i < vNodes->nSize; i++ ) + vNodes->pArray[i]->fMark0 = 0; + return vNodes; +} + +/**Function************************************************************* + + Synopsis [Recursively computes the DFS ordering of the nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes ) +{ + assert( !Fpga_IsComplement(pNode) ); + if ( pNode->fMark0 ) + return; + pNode->fMark0 = 1; + // visit the transitive fanin + Level--; + if ( Level > 0 && Fpga_NodeIsAnd(pNode) ) + { + Fpga_DfsLim_rec( Fpga_Regular(pNode->p1), Level, vNodes ); + Fpga_DfsLim_rec( Fpga_Regular(pNode->p2), Level, vNodes ); + } + // add the node to the list + Fpga_NodeVecPush( vNodes, pNode ); +} + +/**Function************************************************************* + + Synopsis [Computes the limited DFS ordering for one node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManCleanData0( Fpga_Man_t * pMan ) +{ + int i; + for ( i = 0; i < pMan->vNodesAll->nSize; i++ ) + pMan->vNodesAll->pArray[i]->pData0 = 0; +} + +/**Function************************************************************* + + Synopsis [Collects the TFO of the node.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_CollectNodeTfo( Fpga_Man_t * pMan, Fpga_Node_t * pNode ) +{ + Fpga_NodeVec_t * vVisited, * vTfo; + int i; + // perform the traversal + vVisited = Fpga_NodeVecAlloc( 100 ); + vTfo = Fpga_NodeVecAlloc( 100 ); + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_CollectNodeTfo_rec( Fpga_Regular(pMan->pOutputs[i]), pNode, vVisited, vTfo ); + for ( i = 0; i < vVisited->nSize; i++ ) + vVisited->pArray[i]->fMark0 = vVisited->pArray[i]->fMark1 = 0; + Fpga_NodeVecFree( vVisited ); + return vTfo; +} + +/**Function************************************************************* + + Synopsis [Collects the TFO of the node.] + + Description [Returns 1 if the node should be collected.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo ) +{ + int Ret1, Ret2; + assert( !Fpga_IsComplement(pNode) ); + // skip visited nodes + if ( pNode->fMark0 ) + return pNode->fMark1; + pNode->fMark0 = 1; + Fpga_NodeVecPush( vVisited, pNode ); + + // return the pivot node + if ( pNode == pPivot ) + { + pNode->fMark1 = 1; + return 1; + } + if ( pNode->Level < pPivot->Level ) + { + pNode->fMark1 = 0; + return 0; + } + // visit the transitive fanin + assert( Fpga_NodeIsAnd(pNode) ); + Ret1 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p1), pPivot, vVisited, vTfo ); + Ret2 = Fpga_CollectNodeTfo_rec( Fpga_Regular(pNode->p2), pPivot, vVisited, vTfo ); + if ( Ret1 || Ret2 ) + { + pNode->fMark1 = 1; + Fpga_NodeVecPush( vTfo, pNode ); + } + else + pNode->fMark1 = 0; + return pNode->fMark1; +} + +/**Function************************************************************* + + Synopsis [Levelizes the nodes accessible from the POs.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingLevelize( Fpga_Man_t * pMan, Fpga_NodeVec_t * vNodes ) +{ + Fpga_NodeVec_t * vLevels; + Fpga_Node_t ** ppNodes; + Fpga_Node_t * pNode; + int nNodes, nLevelsMax, i; + + // reassign the levels (this may be necessary for networks which choices) + ppNodes = vNodes->pArray; + nNodes = vNodes->nSize; + for ( i = 0; i < nNodes; i++ ) + { + pNode = ppNodes[i]; + if ( !Fpga_NodeIsAnd(pNode) ) + { + pNode->Level = 0; + continue; + } + pNode->Level = 1 + FPGA_MAX( Fpga_Regular(pNode->p1)->Level, Fpga_Regular(pNode->p2)->Level ); + } + + // get the max levels + nLevelsMax = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + nLevelsMax = FPGA_MAX( nLevelsMax, (int)Fpga_Regular(pMan->pOutputs[i])->Level ); + nLevelsMax++; + + // allocate storage for levels + vLevels = Fpga_NodeVecAlloc( nLevelsMax ); + for ( i = 0; i < nLevelsMax; i++ ) + Fpga_NodeVecPush( vLevels, NULL ); + + // go through the nodes and add them to the levels + for ( i = 0; i < nNodes; i++ ) + { + pNode = ppNodes[i]; + pNode->pLevel = NULL; + if ( !Fpga_NodeIsAnd(pNode) ) + continue; + // attach the node to this level + pNode->pLevel = Fpga_NodeVecReadEntry( vLevels, pNode->Level ); + Fpga_NodeVecWriteEntry( vLevels, pNode->Level, pNode ); + } + return vLevels; +} + +/**Function************************************************************* + + Synopsis [Sets up the mask.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingMaxLevel( Fpga_Man_t * pMan ) +{ + int nLevelMax, i; + nLevelMax = 0; + for ( i = 0; i < pMan->nOutputs; i++ ) + nLevelMax = nLevelMax > (int)Fpga_Regular(pMan->pOutputs[i])->Level? + nLevelMax : (int)Fpga_Regular(pMan->pOutputs[i])->Level; + return nLevelMax; +} + + +/**Function************************************************************* + + Synopsis [Analyses choice nodes.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +int Fpga_MappingUpdateLevel_rec( Fpga_Man_t * pMan, Fpga_Node_t * pNode, int fMaximum ) +{ + Fpga_Node_t * pTemp; + int Level1, Level2, LevelE; + assert( !Fpga_IsComplement(pNode) ); + if ( !Fpga_NodeIsAnd(pNode) ) + return pNode->Level; + // skip the visited node + if ( pNode->TravId == pMan->nTravIds ) + return pNode->Level; + pNode->TravId = pMan->nTravIds; + // compute levels of the children nodes + Level1 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p1), fMaximum ); + Level2 = Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pNode->p2), fMaximum ); + pNode->Level = 1 + FPGA_MAX( Level1, Level2 ); + if ( pNode->pNextE ) + { + LevelE = Fpga_MappingUpdateLevel_rec( pMan, pNode->pNextE, fMaximum ); + if ( fMaximum ) + { + if ( pNode->Level < (unsigned)LevelE ) + pNode->Level = LevelE; + } + else + { + if ( pNode->Level > (unsigned)LevelE ) + pNode->Level = LevelE; + } + // set the level of all equivalent nodes to be the same minimum + if ( pNode->pRepr == NULL ) // the primary node + for ( pTemp = pNode->pNextE; pTemp; pTemp = pTemp->pNextE ) + pTemp->Level = pNode->Level; + } + return pNode->Level; +} + +/**Function************************************************************* + + Synopsis [Resets the levels of the nodes in the choice graph.] + + Description [Makes the level of the choice nodes to be equal to the + maximum of the level of the nodes in the equivalence class. This way + sorting by level leads to the reverse topological order, which is + needed for the required time computation.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_MappingSetChoiceLevels( Fpga_Man_t * pMan ) +{ + int i; + pMan->nTravIds++; + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 1 ); +} + +/**Function************************************************************* + + Synopsis [Reports statistics on choice nodes.] + + Description [The number of choice nodes is the number of primary nodes, + which has pNextE set to a pointer. The number of choices is the number + of entries in the equivalent-node lists of the primary nodes.] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +void Fpga_ManReportChoices( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode, * pTemp; + int nChoiceNodes, nChoices; + int i, LevelMax1, LevelMax2; + + // report the number of levels + LevelMax1 = Fpga_MappingMaxLevel( pMan ); + pMan->nTravIds++; + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_MappingUpdateLevel_rec( pMan, Fpga_Regular(pMan->pOutputs[i]), 0 ); + LevelMax2 = Fpga_MappingMaxLevel( pMan ); + + // report statistics about choices + nChoiceNodes = nChoices = 0; + for ( i = 0; i < pMan->vAnds->nSize; i++ ) + { + pNode = pMan->vAnds->pArray[i]; + if ( pNode->pRepr == NULL && pNode->pNextE != NULL ) + { // this is a choice node = the primary node that has equivalent nodes + nChoiceNodes++; + for ( pTemp = pNode; pTemp; pTemp = pTemp->pNextE ) + nChoices++; + } + } + if ( pMan->fVerbose ) + { + printf( "Maximum level: Original = %d. Reduced due to choices = %d.\n", LevelMax1, LevelMax2 ); + printf( "Choice stats: Choice nodes = %d. Total choices = %d.\n", nChoiceNodes, nChoices ); + } +/* + { + FILE * pTable; + pTable = fopen( "stats_choice.txt", "a+" ); + fprintf( pTable, "%s ", pMan->pFileName ); + fprintf( pTable, "%4d ", LevelMax1 ); + fprintf( pTable, "%4d ", pMan->vAnds->nSize - pMan->nInputs ); + fprintf( pTable, "%4d ", LevelMax2 ); + fprintf( pTable, "%7d ", nChoiceNodes ); + fprintf( pTable, "%7d ", nChoices + nChoiceNodes ); + fprintf( pTable, "\n" ); + fclose( pTable ); + } +*/ +} + +/**Function************************************************************* + + Synopsis [Returns the array of CO nodes sorted by level.] + + Description [] + + SideEffects [] + + SeeAlso [] + +***********************************************************************/ +Fpga_NodeVec_t * Fpga_MappingOrderCosByLevel( Fpga_Man_t * pMan ) +{ + Fpga_Node_t * pNode; + Fpga_NodeVec_t * vNodes; + int i, nLevels; + // get the largest level of a CO + nLevels = Fpga_MappingMaxLevel( pMan ); + // allocate the array of nodes + vNodes = Fpga_NodeVecAlloc( nLevels + 1 ); + for ( i = 0; i <= nLevels; i++ ) + Fpga_NodeVecPush( vNodes, NULL ); + // clean the marks + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; + // put the nodes into the structure + for ( i = 0; i < pMan->nOutputs; i++ ) + { + pNode = Fpga_Regular(pMan->pOutputs[i]); + if ( pNode->fMark0 ) + continue; + pNode->fMark0 = 1; + pNode->pData0 = (char *)Fpga_NodeVecReadEntry( vNodes, pNode->Level ); + Fpga_NodeVecWriteEntry( vNodes, pNode->Level, pNode ); + } + for ( i = 0; i < pMan->nOutputs; i++ ) + Fpga_Regular(pMan->pOutputs[i])->fMark0 = 0; + return vNodes; + +} + +//////////////////////////////////////////////////////////////////////// +/// END OF FILE /// +//////////////////////////////////////////////////////////////////////// + + |