/**Function************************************************************* Synopsis [Compares the outputs by their arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 ) { Map_Node_t * pNode1 = Map_Regular(*ppNode1); Map_Node_t * pNode2 = Map_Regular(*ppNode2); int fPhase1 = !Map_IsComplement(*ppNode1); int fPhase2 = !Map_IsComplement(*ppNode2); float Arrival1 = pNode1->tArrival[fPhase1].Worst; float Arrival2 = pNode2->tArrival[fPhase2].Worst; if ( Arrival1 < Arrival2 ) return -1; if ( Arrival1 > Arrival2 ) return 1; return 0; }
Abc_Ntk_t * Abc_NtkFromMap( Map_Man_t * pMan, Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Map_Node_t * pNodeMap; Abc_Obj_t * pNode, * pNodeNew; int i, nDupGates; assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); // create the new network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_MAP ); // make the mapper point to the new network Map_ManCleanData( pMan ); Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i >= Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) break; Map_NodeSetData( Map_ManReadInputs(pMan)[i], 1, (char *)pNode->pCopy ); } Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i < Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) continue; Map_NodeSetData( Map_ManReadBufs(pMan)[i - (Abc_NtkCiNum(pNtk) - pNtk->nBarBufs)], 1, (char *)pNode->pCopy ); } // assign the mapping of the required phase to the POs Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i < Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) continue; pNodeMap = Map_ManReadBufDriver( pMan, i - (Abc_NtkCoNum(pNtk) - pNtk->nBarBufs) ); pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); assert( !Abc_ObjIsComplement(pNodeNew) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i >= Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; pNodeMap = Map_ManReadOutputs(pMan)[i]; pNodeNew = Abc_NodeFromMap_rec( pNtkNew, Map_Regular(pNodeMap), !Map_IsComplement(pNodeMap) ); assert( !Abc_ObjIsComplement(pNodeNew) ); Abc_ObjAddFanin( pNode->pCopy, pNodeNew ); } // decouple the PO driver nodes to reduce the number of levels nDupGates = Abc_NtkLogicMakeSimpleCos( pNtkNew, 1 ); // if ( nDupGates && Map_ManReadVerbose(pMan) ) // printf( "Duplicated %d gates to decouple the CO drivers.\n", nDupGates ); return pNtkNew; }
/**Function************************************************************* Synopsis [Computes the array of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_MappingGetSwitching( Map_Man_t * pMan, Map_NodeVec_t * vMapping ) { Map_Node_t * pNode; float Switch; int i; Switch = 0.0; for ( i = 0; i < vMapping->nSize; i++ ) { pNode = vMapping->pArray[i]; // at least one phase has the best cut assigned assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); // at least one phase is used in the mapping assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); // compute the array due to the supergate if ( Map_NodeIsAnd(pNode) ) { // count switching of the negative phase if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) Switch += pNode->Switching; // count switching of the positive phase if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) Switch += pNode->Switching; } // count switching of the interver if we need to implement one phase with another phase if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) Switch += pNode->Switching; // inverter switches the same as the node } // add buffers for each CO driven by a CI for ( i = 0; i < pMan->nOutputs; i++ ) if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) Switch += pMan->pOutputs[i]->Switching; return Switch; }
/**Function************************************************************* Synopsis [Prints a bunch of latest arriving outputs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingPrintOutputArrivals( Map_Man_t * p ) { int pSorted[MAP_CO_LIST_SIZE]; Map_Time_t * pTimes; Map_Node_t * pNode; int fPhase, Limit, i; int MaxNameSize; // determine the number of nodes to print Limit = (p->nOutputs > MAP_CO_LIST_SIZE)? MAP_CO_LIST_SIZE : p->nOutputs; // determine the order Map_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 = Map_Regular(p->pOutputs[pSorted[i]]); fPhase =!Map_IsComplement(p->pOutputs[pSorted[i]]); pTimes = pNode->tArrival + fPhase; // print out the best arrival time printf( "Output %-*s : ", MaxNameSize + 3, p->ppOutputNames[pSorted[i]] ); printf( "Delay = (%5.2f, %5.2f) ", (double)pTimes->Rise, (double)pTimes->Fall ); printf( "%s", fPhase? "POS" : "NEG" ); printf( "\n" ); } }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Reads the actual reference counter of a phase.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeReadRefPhaseAct( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return pNode->nRefAct[fPhase]; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned return pNode->nRefAct[2]; }
/**Function************************************************************* Synopsis [Analyses choice nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingUpdateLevel_rec( Map_Man_t * pMan, Map_Node_t * pNode, int fMaximum ) { Map_Node_t * pTemp; int Level1, Level2, LevelE; assert( !Map_IsComplement(pNode) ); if ( !Map_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 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p1), fMaximum ); Level2 = Map_MappingUpdateLevel_rec( pMan, Map_Regular(pNode->p2), fMaximum ); pNode->Level = 1 + MAP_MAX( Level1, Level2 ); if ( pNode->pNextE ) { LevelE = Map_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 [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingDfsMarked2_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, Map_NodeVec_t * vBoundary, int fFirst ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark1 ) return; if ( pNode->fMark0 || Map_NodeIsVar(pNode) ) { pNode->fMark1 = 1; Map_NodeVecPush(vBoundary, pNode); return; } // visit the transitive fanin if ( Map_NodeIsAnd(pNode) ) { Map_MappingDfsMarked2_rec( Map_Regular(pNode->p1), vNodes, vBoundary, 0 ); Map_MappingDfsMarked2_rec( Map_Regular(pNode->p2), vNodes, vBoundary, 0 ); } // visit the equivalent nodes if ( !fFirst && pNode->pNextE ) Map_MappingDfsMarked2_rec( pNode->pNextE, vNodes, vBoundary, 0 ); // make sure the node is not visited through the equivalent nodes assert( pNode->fMark1 == 0 ); // mark the node as visited pNode->fMark1 = 1; // add the node to the list Map_NodeVecPush( vNodes, pNode ); }
/**Function************************************************************* Synopsis [Increments the actual reference counter of a phase.] Description [Returns the old reference counter.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_NodeIncRefPhaseAct( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return pNode->nRefAct[fPhase]++; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned return pNode->nRefAct[2]++; }
/**Function************************************************************* Synopsis [Reads the estimated reference counter of a phase.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_NodeReadRefPhaseEst( Map_Node_t * pNode, int fPhase ) { assert( !Map_IsComplement(pNode) ); if ( pNode->pCutBest[0] && pNode->pCutBest[1] ) // both assigned return pNode->nRefEst[fPhase]; assert( pNode->pCutBest[0] || pNode->pCutBest[1] ); // at least one assigned // return pNode->nRefEst[0] + pNode->nRefEst[1]; return pNode->nRefEst[2]; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingMark_rec( Map_Node_t * pNode ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark0 == 1 ) return; pNode->fMark0 = 1; if ( !Map_NodeIsAnd(pNode) ) return; // visit the transitive fanin of the selected cut Map_MappingMark_rec( Map_Regular(pNode->p1) ); Map_MappingMark_rec( Map_Regular(pNode->p2) ); }
/**Function************************************************************* Synopsis [Computes actual reference counters.] Description [Collects the nodes used in the mapping in array pMan->vMapping. Nodes are collected in reverse topological order to facilitate the computation of required times.] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingSetRefs_rec( Map_Man_t * pMan, Map_Node_t * pNode ) { Map_Cut_t * pCut; Map_Node_t * pNodeR; unsigned uPhase; int i, fPhase, fInvPin; // get the regular node and its phase pNodeR = Map_Regular(pNode); fPhase = !Map_IsComplement(pNode); pNodeR->nRefAct[2]++; // quit if the node was already visited in this phase if ( pNodeR->nRefAct[fPhase]++ ) return; // quit if this is a PI node if ( Map_NodeIsVar(pNodeR) ) return; // propagate through buffer if ( Map_NodeIsBuf(pNodeR) ) { Map_MappingSetRefs_rec( pMan, Map_NotCond(pNodeR->p1, Map_IsComplement(pNode)) ); return; } assert( Map_NodeIsAnd(pNode) ); // get the cut implementing this or opposite polarity pCut = pNodeR->pCutBest[fPhase]; if ( pCut == NULL ) { fPhase = !fPhase; pCut = pNodeR->pCutBest[fPhase]; } if ( pMan->fUseProfile ) Mio_GateIncProfile2( pCut->M[fPhase].pSuperBest->pRoot ); // visit the transitive fanin uPhase = pCut->M[fPhase].uPhaseBest; for ( i = 0; i < pCut->nLeaves; i++ ) { fInvPin = ((uPhase & (1 << i)) > 0); Map_MappingSetRefs_rec( pMan, Map_NotCond(pCut->ppLeaves[i], fInvPin) ); } }
/**Function************************************************************* Synopsis [Recursively unmarks the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingUnmark_rec( Map_Node_t * pNode ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark0 == 0 ) return; pNode->fMark0 = 0; if ( !Map_NodeIsAnd(pNode) ) return; Map_MappingUnmark_rec( Map_Regular(pNode->p1) ); Map_MappingUnmark_rec( Map_Regular(pNode->p2) ); // visit the equivalent nodes if ( pNode->pNextE ) Map_MappingUnmark_rec( pNode->pNextE ); }
void Map_TimeComputeRequiredGlobal( Map_Man_t * p ) { Map_Time_t * ptTime, * ptTimeA; int fPhase, i; // update the required times according to the target p->fRequiredGlo = Map_TimeComputeArrivalMax( p ); if ( p->DelayTarget != -1 ) { if ( p->fRequiredGlo > p->DelayTarget + p->fEpsilon ) { if ( p->fMappingMode == 1 ) printf( "Cannot meet the target required times (%4.2f). Continue anyway.\n", p->DelayTarget ); } else if ( p->fRequiredGlo < p->DelayTarget - p->fEpsilon ) { if ( p->fMappingMode == 1 && p->fVerbose ) printf( "Relaxing the required times from (%4.2f) to the target (%4.2f).\n", p->fRequiredGlo, p->DelayTarget ); p->fRequiredGlo = p->DelayTarget; } } // clean the required times for ( i = 0; i < p->vMapObjs->nSize; i++ ) { p->vMapObjs->pArray[i]->tRequired[0].Rise = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[0].Fall = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[0].Worst = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[1].Rise = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[1].Fall = MAP_FLOAT_LARGE; p->vMapObjs->pArray[i]->tRequired[1].Worst = MAP_FLOAT_LARGE; } // set the required times for the POs for ( i = 0; i < p->nOutputs; i++ ) { fPhase = !Map_IsComplement(p->pOutputs[i]); ptTime = Map_Regular(p->pOutputs[i])->tRequired + fPhase; ptTimeA = Map_Regular(p->pOutputs[i])->tArrival + fPhase; // if external required time can be achieved, use it if ( p->pOutputRequireds && p->pOutputRequireds[i].Worst > 0 && ptTimeA->Worst <= p->pOutputRequireds[i].Worst )//&& p->pOutputRequireds[i].Worst <= p->fRequiredGlo ) ptTime->Rise = ptTime->Fall = ptTime->Worst = p->pOutputRequireds[i].Worst; // if external required cannot be achieved, set the earliest possible arrival time else if ( p->pOutputRequireds && p->pOutputRequireds[i].Worst > 0 && ptTimeA->Worst > p->pOutputRequireds[i].Worst ) ptTime->Rise = ptTime->Fall = ptTime->Worst = ptTimeA->Worst; // otherwise, set the global required time else ptTime->Rise = ptTime->Fall = ptTime->Worst = p->fRequiredGlo; } // visit nodes in the reverse topological order Map_TimePropagateRequired( p ); }
/**Function************************************************************* Synopsis [Computes the array of mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_MappingGetArea( Map_Man_t * pMan ) { Map_Node_t * pNode; float Area = 0.0; int i; if ( pMan->fUseProfile ) Mio_LibraryCleanProfile2( pMan->pSuperLib->pGenlib ); for ( i = 0; i < pMan->vMapObjs->nSize; i++ ) { pNode = pMan->vMapObjs->pArray[i]; if ( pNode->nRefAct[2] == 0 ) continue; if ( Map_NodeIsBuf(pNode) ) continue; // at least one phase has the best cut assigned assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); // at least one phase is used in the mapping assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); // compute the array due to the supergate if ( Map_NodeIsAnd(pNode) ) { // count area of the negative phase if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) { Area += pNode->pCutBest[0]->M[0].pSuperBest->Area; if ( pMan->fUseProfile ) Mio_GateIncProfile2( pNode->pCutBest[0]->M[0].pSuperBest->pRoot ); } // count area of the positive phase if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) { Area += pNode->pCutBest[1]->M[1].pSuperBest->Area; if ( pMan->fUseProfile ) Mio_GateIncProfile2( pNode->pCutBest[1]->M[1].pSuperBest->pRoot ); } } // count area of the interver if we need to implement one phase with another phase if ( (pNode->pCutBest[0] == NULL && pNode->nRefAct[0] > 0) || (pNode->pCutBest[1] == NULL && pNode->nRefAct[1] > 0) ) Area += pMan->pSuperLib->AreaInv; } // add buffers for each CO driven by a CI for ( i = 0; i < pMan->nOutputs; i++ ) if ( Map_NodeIsVar(pMan->pOutputs[i]) && !Map_IsComplement(pMan->pOutputs[i]) ) Area += pMan->pSuperLib->AreaBuf; return Area; }
/**Function************************************************************* Synopsis [Recursively computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingDfsMarked4_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark1 ) return; // visit the transitive fanin if ( Map_NodeIsAnd(pNode) ) { Map_MappingDfsMarked4_rec( Map_Regular(pNode->p1), vNodes ); Map_MappingDfsMarked4_rec( Map_Regular(pNode->p2), vNodes ); } // make sure the node is not visited through the equivalent nodes assert( pNode->fMark1 == 0 ); // mark the node as visited pNode->fMark1 = 1; // add the node to the list Map_NodeVecPush( vNodes, pNode ); }
/**Function************************************************************* Synopsis [Recursively computes the number of logic levels.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingCountLevels_rec( Map_Node_t * pNode ) { int Level1, Level2; assert( !Map_IsComplement(pNode) ); if ( !Map_NodeIsAnd(pNode) ) { pNode->Level = 0; return 0; } if ( pNode->fMark0 ) return pNode->Level; pNode->fMark0 = 1; // visit the transitive fanin Level1 = Map_MappingCountLevels_rec( Map_Regular(pNode->p1) ); Level2 = Map_MappingCountLevels_rec( Map_Regular(pNode->p2) ); // set the number of levels pNode->Level = 1 + ((Level1>Level2)? Level1: Level2); return pNode->Level; }
/**Function************************************************************* Synopsis [Computes the DFS ordering of the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv ) { assert( !Map_IsComplement(pNode) ); if ( pNode->fMark0 ) return; // visit the transitive fanin if ( Map_NodeIsAnd(pNode) ) { Map_MappingDfs_rec( Map_Regular(pNode->p1), vNodes, fCollectEquiv ); Map_MappingDfs_rec( Map_Regular(pNode->p2), vNodes, fCollectEquiv ); } // visit the equivalent nodes if ( fCollectEquiv && pNode->pNextE ) Map_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 Map_NodeVecPush( vNodes, pNode ); }
/**Function************************************************************* Synopsis [Computes the total are flow of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_MappingGetAreaFlow( Map_Man_t * p ) { Map_Node_t * pNode; Map_Cut_t * pCut; float aFlowFlowTotal = 0; int fPosPol, i; for ( i = 0; i < p->nOutputs; i++ ) { pNode = Map_Regular(p->pOutputs[i]); if ( !Map_NodeIsAnd(pNode) ) continue; fPosPol = !Map_IsComplement(p->pOutputs[i]); pCut = pNode->pCutBest[fPosPol]; if ( pCut == NULL ) { fPosPol = !fPosPol; pCut = pNode->pCutBest[fPosPol]; } aFlowFlowTotal += pNode->pCutBest[fPosPol]->M[fPosPol].AreaFlow; } return aFlowFlowTotal; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes the maximum arrival times.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ float Map_TimeComputeArrivalMax( Map_Man_t * p ) { float tReqMax, tReq; int i, fPhase; // get the critical PO arrival time tReqMax = -MAP_FLOAT_LARGE; for ( i = 0; i < p->nOutputs; i++ ) { if ( Map_NodeIsConst(p->pOutputs[i]) ) continue; fPhase = !Map_IsComplement(p->pOutputs[i]); tReq = Map_Regular(p->pOutputs[i])->tArrival[fPhase].Worst; tReqMax = MAP_MAX( tReqMax, tReq ); } return tReqMax; }
/**Function************************************************************* Synopsis [Computes the required times of all nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_TimePropagateRequired( Map_Man_t * p ) { Map_Node_t * pNode; Map_Time_t tReqOutTest, * ptReqOutTest = &tReqOutTest; Map_Time_t * ptReqIn, * ptReqOut; int fPhase, k; // go through the nodes in the reverse topological order for ( k = p->vMapObjs->nSize - 1; k >= 0; k-- ) { pNode = p->vMapObjs->pArray[k]; if ( pNode->nRefAct[2] == 0 ) continue; // propagate required times through the buffer if ( Map_NodeIsBuf(pNode) ) { assert( pNode->p2 == NULL ); Map_Regular(pNode->p1)->tRequired[ Map_IsComplement(pNode->p1)] = pNode->tRequired[0]; Map_Regular(pNode->p1)->tRequired[!Map_IsComplement(pNode->p1)] = pNode->tRequired[1]; continue; } // this computation works for regular nodes only assert( !Map_IsComplement(pNode) ); // at least one phase should be mapped assert( pNode->pCutBest[0] != NULL || pNode->pCutBest[1] != NULL ); // the node should be used in the currently assigned mapping assert( pNode->nRefAct[0] > 0 || pNode->nRefAct[1] > 0 ); // if one of the cuts is not given, project the required times from the other cut if ( pNode->pCutBest[0] == NULL || pNode->pCutBest[1] == NULL ) { // assert( 0 ); // get the missing phase fPhase = (pNode->pCutBest[1] == NULL); // check if the missing phase is needed in the mapping if ( pNode->nRefAct[fPhase] > 0 ) { // get the pointers to the required times of the missing phase ptReqOut = pNode->tRequired + fPhase; // assert( ptReqOut->Fall < MAP_FLOAT_LARGE ); // get the pointers to the required times of the present phase ptReqIn = pNode->tRequired + !fPhase; // propagate the required times from the missing phase to the present phase // tArrInv.Fall = pMatch->tArrive.Rise + p->pSuperLib->tDelayInv.Fall; // tArrInv.Rise = pMatch->tArrive.Fall + p->pSuperLib->tDelayInv.Rise; ptReqIn->Fall = MAP_MIN( ptReqIn->Fall, ptReqOut->Rise - p->pSuperLib->tDelayInv.Rise ); ptReqIn->Rise = MAP_MIN( ptReqIn->Rise, ptReqOut->Fall - p->pSuperLib->tDelayInv.Fall ); } } // finalize the worst case computation pNode->tRequired[0].Worst = MAP_MIN( pNode->tRequired[0].Fall, pNode->tRequired[0].Rise ); pNode->tRequired[1].Worst = MAP_MIN( pNode->tRequired[1].Fall, pNode->tRequired[1].Rise ); // skip the PIs if ( !Map_NodeIsAnd(pNode) ) continue; // propagate required times of different phases of the node // the ordering of phases does not matter since they are mapped independently if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE ) Map_TimePropagateRequiredPhase( p, pNode, 0 ); if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE ) Map_TimePropagateRequiredPhase( p, pNode, 1 ); } // in the end, we verify the required times // for this, we compute the arrival times of the outputs of each phase // of the supergates using the fanins' required times as the fanins' arrival times // the resulting arrival time of the supergate should be less than the actual required time for ( k = p->vMapObjs->nSize - 1; k >= 0; k-- ) { pNode = p->vMapObjs->pArray[k]; if ( pNode->nRefAct[2] == 0 ) continue; if ( !Map_NodeIsAnd(pNode) ) continue; // verify that the required times are propagated correctly // if ( pNode->pCutBest[0] && (pNode->nRefAct[0] > 0 || pNode->pCutBest[1] == NULL) ) if ( pNode->pCutBest[0] && pNode->tRequired[0].Worst < MAP_FLOAT_LARGE/2 ) { Map_MatchComputeReqTimes( pNode->pCutBest[0], 0, ptReqOutTest ); // assert( ptReqOutTest->Rise < pNode->tRequired[0].Rise + p->fEpsilon ); // assert( ptReqOutTest->Fall < pNode->tRequired[0].Fall + p->fEpsilon ); } // if ( pNode->pCutBest[1] && (pNode->nRefAct[1] > 0 || pNode->pCutBest[0] == NULL) ) if ( pNode->pCutBest[1] && pNode->tRequired[1].Worst < MAP_FLOAT_LARGE/2 ) { Map_MatchComputeReqTimes( pNode->pCutBest[1], 1, ptReqOutTest ); // assert( ptReqOutTest->Rise < pNode->tRequired[1].Rise + p->fEpsilon ); // assert( ptReqOutTest->Fall < pNode->tRequired[1].Fall + p->fEpsilon ); } } }
ABC_NAMESPACE_IMPL_START #ifdef MAP_ALLOCATE_FANOUT //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Add the fanout to the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Map_NodeAddFaninFanout( Map_Node_t * pFanin, Map_Node_t * pFanout ) { Map_Node_t * pPivot; // pFanins is a fanin of pFanout assert( !Map_IsComplement(pFanin) ); assert( !Map_IsComplement(pFanout) ); assert( Map_Regular(pFanout->p1) == pFanin || Map_Regular(pFanout->p2) == pFanin ); pPivot = pFanin->pFanPivot; if ( pPivot == NULL ) { pFanin->pFanPivot = pFanout; return; } if ( Map_Regular(pPivot->p1) == pFanin ) { if ( Map_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } else // if ( Map_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin1; pPivot->pFanFanin1 = pFanout; } } else // if ( Map_Regular(pPivot->p2) == pFanin ) { assert( Map_Regular(pPivot->p2) == pFanin ); if ( Map_Regular(pFanout->p1) == pFanin ) { pFanout->pFanFanin1 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } else // if ( Map_Regular(pFanout->p2) == pFanin ) { pFanout->pFanFanin2 = pPivot->pFanFanin2; pPivot->pFanFanin2 = pFanout; } } }
/**Function************************************************************* Synopsis [Computes the best matches of the nodes.] Description [Uses parameter p->fMappingMode to decide how to assign the matches for both polarities of the node. While the matches are being assigned, one of them may turn out to be better than the other (in terms of delay, for example). In this case, the worse match can be permanently dropped, and the corresponding pointer set to NULL.] SideEffects [] SeeAlso [] ***********************************************************************/ int Map_MappingMatches( Map_Man_t * p ) { ProgressBar * pProgress; Map_Node_t * pNode; int i; assert( p->fMappingMode >= 0 && p->fMappingMode <= 4 ); // use the externally given PI arrival times if ( p->fMappingMode == 0 ) Map_MappingSetPiArrivalTimes( p ); // estimate the fanouts if ( p->fMappingMode == 0 ) Map_MappingEstimateRefsInit( p ); else if ( p->fMappingMode == 1 ) Map_MappingEstimateRefs( p ); // the PI cuts are matched in the cut computation package // in the loop below we match the internal nodes pProgress = Extra_ProgressBarStart( stdout, p->vMapObjs->nSize ); for ( i = 0; i < p->vMapObjs->nSize; i++ ) { pNode = p->vMapObjs->pArray[i]; if ( Map_NodeIsBuf(pNode) ) { assert( pNode->p2 == NULL ); pNode->tArrival[0] = Map_Regular(pNode->p1)->tArrival[ Map_IsComplement(pNode->p1)]; pNode->tArrival[1] = Map_Regular(pNode->p1)->tArrival[!Map_IsComplement(pNode->p1)]; continue; } // skip primary inputs and secondary nodes if mapping with choices if ( !Map_NodeIsAnd( pNode ) || pNode->pRepr ) continue; // make sure that at least one non-trival cut is present if ( pNode->pCuts->pNext == NULL ) { Extra_ProgressBarStop( pProgress ); printf( "\nError: A node in the mapping graph does not have feasible cuts.\n" ); return 0; } // match negative phase if ( !Map_MatchNodePhase( p, pNode, 0 ) ) { Extra_ProgressBarStop( pProgress ); return 0; } // match positive phase if ( !Map_MatchNodePhase( p, pNode, 1 ) ) { Extra_ProgressBarStop( pProgress ); return 0; } // make sure that at least one phase is mapped if ( pNode->pCutBest[0] == NULL && pNode->pCutBest[1] == NULL ) { printf( "\nError: Could not match both phases of AIG node %d.\n", pNode->Num ); printf( "Please make sure that the supergate library has equivalents of AND2 or NAND2.\n" ); printf( "If such supergates exist in the library, report a bug.\n" ); Extra_ProgressBarStop( pProgress ); return 0; } // if both phases are assigned, check if one of them can be dropped Map_NodeTryDroppingOnePhase( p, pNode ); // set the arrival times of the node using the best cuts Map_NodeTransferArrivalTimes( p, pNode ); // update the progress bar Extra_ProgressBarUpdate( pProgress, i, "Matches ..." ); } Extra_ProgressBarStop( pProgress ); return 1; }
int Map_NodeComparePhase( Map_Node_t * p1, Map_Node_t * p2 ) { assert( !Map_IsComplement(p1) ); assert( !Map_IsComplement(p2) ); return p1->fInv ^ p2->fInv; }