/**Function************************************************************* Synopsis [Implementation of retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetime( Abc_Ntk_t * pNtk, int Mode, int fForwardOnly, int fBackwardOnly, int fOneStep, int fVerbose ) { int nLatches = Abc_NtkLatchNum(pNtk); int nLevels = Abc_NtkLevel(pNtk); int RetValue = 0, clkTotal = clock(); int nNodesOld, nLatchesOld; assert( Mode > 0 && Mode < 7 ); assert( !fForwardOnly || !fBackwardOnly ); // cleanup the network nNodesOld = Abc_NtkNodeNum(pNtk); nLatchesOld = Abc_NtkLatchNum(pNtk); Abc_NtkCleanupSeq(pNtk, 0, 0, 0); if ( nNodesOld > Abc_NtkNodeNum(pNtk) || nLatchesOld > Abc_NtkLatchNum(pNtk) ) printf( "Cleanup before retiming removed %d dangling nodes and %d dangling latches.\n", nNodesOld - Abc_NtkNodeNum(pNtk), nLatchesOld - Abc_NtkLatchNum(pNtk) ); // perform retiming switch ( Mode ) { case 1: // forward RetValue = Abc_NtkRetimeIncremental( pNtk, 1, 0, 0, fVerbose ); break; case 2: // backward RetValue = Abc_NtkRetimeIncremental( pNtk, 0, 0, 0, fVerbose ); break; case 3: // min-area RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose ); break; case 4: // min-delay if ( !fBackwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, fOneStep, fVerbose ); if ( !fForwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, fOneStep, fVerbose ); break; case 5: // min-area + min-delay RetValue = Abc_NtkRetimeMinArea( pNtk, fForwardOnly, fBackwardOnly, fVerbose ); if ( !fBackwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, 1, 1, 0, fVerbose ); if ( !fForwardOnly ) RetValue += Abc_NtkRetimeIncremental( pNtk, 0, 1, 0, fVerbose ); break; case 6: // Pan's algorithm RetValue = Abc_NtkRetimeLValue( pNtk, 500, fVerbose ); break; default: printf( "Unknown retiming option.\n" ); break; } if ( fVerbose ) { printf( "Reduction in area = %3d. Reduction in delay = %3d. ", nLatches - Abc_NtkLatchNum(pNtk), nLevels - Abc_NtkLevel(pNtk) ); PRT( "Total runtime", clock() - clkTotal ); } timeRetime = clock() - clkTotal; return RetValue; }
/**Function************************************************************* Synopsis [Computes initial values of the new latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose ) { Vec_Int_t * vSolution; Abc_Ntk_t * pNtkMiter, * pNtkLogic; int RetValue; abctime clk; if ( pNtkCone == NULL ) return Vec_IntDup( vValues ); // convert the target network to AIG pNtkLogic = Abc_NtkDup( pNtkCone ); Abc_NtkToAig( pNtkLogic ); // get the miter pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues ); if ( fVerbose ) printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) ); // solve the miter clk = Abc_Clock(); RetValue = Abc_NtkMiterSat( pNtkMiter, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); if ( fVerbose ) { ABC_PRT( "SAT solving time", Abc_Clock() - clk ); } // analyze the result if ( RetValue == 1 ) printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" ); else if ( RetValue == -1 ) printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" ); else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) ) printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" ); // set the values of the latches vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) ); pNtkMiter->pModel = NULL; Abc_NtkDelete( pNtkMiter ); Abc_NtkDelete( pNtkLogic ); return vSolution; }
/**Function************************************************************* Synopsis [Performs retiming in one direction.] Description [Currently does not retime over black boxes.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeIncremental( Abc_Ntk_t * pNtk, int nDelayLim, int fForward, int fMinDelay, int fOneStep, int fVerbose ) { Abc_Ntk_t * pNtkCopy = NULL; Vec_Ptr_t * vBoxes; st__table * tLatches; int nLatches = Abc_NtkLatchNum(pNtk); int nIdMaxStart = Abc_NtkObjNumMax(pNtk); int RetValue; int nIterLimit = -1; // Suppress "might be used uninitialized" if ( Abc_NtkNodeNum(pNtk) == 0 ) return 0; // reorder CI/CO/latch inputs Abc_NtkOrderCisCos( pNtk ); if ( fMinDelay ) { nIterLimit = fOneStep? 1 : 2 * Abc_NtkLevel(pNtk); pNtkCopy = Abc_NtkDup( pNtk ); tLatches = Abc_NtkRetimePrepareLatches( pNtkCopy ); st__free_table( tLatches ); } // collect latches and remove CIs/COs tLatches = Abc_NtkRetimePrepareLatches( pNtk ); // share the latches Abc_NtkRetimeShareLatches( pNtk, 0 ); // save boxes vBoxes = pNtk->vBoxes; pNtk->vBoxes = NULL; // perform the retiming if ( fMinDelay ) Abc_NtkRetimeMinDelay( pNtk, pNtkCopy, nDelayLim, nIterLimit, fForward, fVerbose ); else Abc_NtkRetimeOneWay( pNtk, fForward, fVerbose ); if ( fMinDelay ) Abc_NtkDelete( pNtkCopy ); // share the latches Abc_NtkRetimeShareLatches( pNtk, 0 ); // restore boxes pNtk->vBoxes = vBoxes; // finalize the latches RetValue = Abc_NtkRetimeFinalizeLatches( pNtk, tLatches, nIdMaxStart ); st__free_table( tLatches ); if ( RetValue == 0 ) return 0; // fix the COs // Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); // check for correctness if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkRetimeForward(): Network check has failed.\n" ); // return the number of latches saved return nLatches - Abc_NtkLatchNum(pNtk); }
Vec_Ptr_t * Abc_NtkAssignIDs2( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = i; vNodes = Vec_PtrAlloc( Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes); Vec_PtrPush( vNodes, pObj ); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMfs( Abc_Ntk_t * pNtk, Mfs_Par_t * pPars ) { extern Aig_Man_t * Abc_NtkToDar( Abc_Ntk_t * pNtk, int fExors, int fRegisters ); Bdc_Par_t Pars = {0}, * pDecPars = &Pars; ProgressBar * pProgress; Mfs_Man_t * p; Abc_Obj_t * pObj; Vec_Vec_t * vLevels; Vec_Ptr_t * vNodes; int i, k, nNodes, nFaninMax; abctime clk = Abc_Clock(), clk2; int nTotalNodesBeg = Abc_NtkNodeNum(pNtk); int nTotalEdgesBeg = Abc_NtkGetTotalFanins(pNtk); assert( Abc_NtkIsLogic(pNtk) ); nFaninMax = Abc_NtkGetFaninMax(pNtk); if ( pPars->fResub ) { if ( nFaninMax > 8 ) { printf( "Nodes with more than %d fanins will not be processed.\n", 8 ); nFaninMax = 8; } } else { if ( nFaninMax > MFS_FANIN_MAX ) { printf( "Nodes with more than %d fanins will not be processed.\n", MFS_FANIN_MAX ); nFaninMax = MFS_FANIN_MAX; } } // perform the network sweep // Abc_NtkSweep( pNtk, 0 ); // convert into the AIG if ( !Abc_NtkToAig(pNtk) ) { fprintf( stdout, "Converting to AIGs has failed.\n" ); return 0; } assert( Abc_NtkHasAig(pNtk) ); // start the manager p = Mfs_ManAlloc( pPars ); p->pNtk = pNtk; p->nFaninMax = nFaninMax; // precomputer power-aware metrics if ( pPars->fPower ) { extern Vec_Int_t * Abc_NtkPowerEstimate( Abc_Ntk_t * pNtk, int fProbOne ); if ( pPars->fResub ) p->vProbs = Abc_NtkPowerEstimate( pNtk, 0 ); else p->vProbs = Abc_NtkPowerEstimate( pNtk, 1 ); #if 0 printf( "Total switching before = %7.2f.\n", Abc_NtkMfsTotalSwitching(pNtk) ); #else p->TotalSwitchingBeg = Abc_NtkMfsTotalSwitching(pNtk); #endif } if ( pNtk->pExcare ) { Abc_Ntk_t * pTemp; if ( Abc_NtkPiNum((Abc_Ntk_t *)pNtk->pExcare) != Abc_NtkCiNum(pNtk) ) printf( "The PI count of careset (%d) and logic network (%d) differ. Careset is not used.\n", Abc_NtkPiNum((Abc_Ntk_t *)pNtk->pExcare), Abc_NtkCiNum(pNtk) ); else { pTemp = Abc_NtkStrash( (Abc_Ntk_t *)pNtk->pExcare, 0, 0, 0 ); p->pCare = Abc_NtkToDar( pTemp, 0, 0 ); Abc_NtkDelete( pTemp ); p->vSuppsInv = Aig_ManSupportsInverse( p->pCare ); } } if ( p->pCare != NULL ) printf( "Performing optimization with %d external care clauses.\n", Aig_ManCoNum(p->pCare) ); // prepare the BDC manager if ( !pPars->fResub ) { pDecPars->nVarsMax = (nFaninMax < 3) ? 3 : nFaninMax; pDecPars->fVerbose = pPars->fVerbose; p->vTruth = Vec_IntAlloc( 0 ); p->pManDec = Bdc_ManAlloc( pDecPars ); } // label the register outputs if ( p->pCare ) { Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)i; } // compute levels Abc_NtkLevel( pNtk ); Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); // compute don't-cares for each node nNodes = 0; p->nTotalNodesBeg = nTotalNodesBeg; p->nTotalEdgesBeg = nTotalEdgesBeg; if ( pPars->fResub ) { #if 0 printf( "TotalSwitching (%7.2f --> ", Abc_NtkMfsTotalSwitching(pNtk) ); #endif if (pPars->fPower) { Abc_NtkMfsPowerResub( p, pPars); } else { pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { if ( p->pPars->nDepthMax && (int)pObj->Level > p->pPars->nDepthMax ) continue; if ( Abc_ObjFaninNum(pObj) < 2 || Abc_ObjFaninNum(pObj) > nFaninMax ) continue; if ( !p->pPars->fVeryVerbose ) Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( pPars->fResub ) Abc_NtkMfsResub( p, pObj ); else Abc_NtkMfsNode( p, pObj ); } Extra_ProgressBarStop( pProgress ); #if 0 printf( " %7.2f )\n", Abc_NtkMfsTotalSwitching(pNtk) ); #endif } } else
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Mfs_ManPrint( Mfs_Man_t * p ) { if ( p->pPars->fResub ) { /* printf( "Reduction in nodes = %5d. (%.2f %%) ", p->nTotalNodesBeg-p->nTotalNodesEnd, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); printf( "Reduction in edges = %5d. (%.2f %%) ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/p->nTotalEdgesBeg ); printf( "\n" ); printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d.\n", Abc_NtkNodeNum(p->pNtk), p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts ); if ( p->pPars->fSwapEdge ) printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n", p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) ); else Abc_NtkMfsPrintResubStats( p ); // printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); */ printf( "@@@------- Node( %4d, %4.2f%% ), ", p->nTotalNodesBeg-p->nTotalNodesEnd, 100.0*(p->nTotalNodesBeg-p->nTotalNodesEnd)/p->nTotalNodesBeg ); printf( "Edge( %4d, %4.2f%% ), ", p->nTotalEdgesBeg-p->nTotalEdgesEnd, 100.0*(p->nTotalEdgesBeg-p->nTotalEdgesEnd)/p->nTotalEdgesBeg ); if (p->pPars->fPower) printf( "Power( %5.2f, %4.2f%%) ", p->TotalSwitchingBeg - p->TotalSwitchingEnd, 100.0*(p->TotalSwitchingBeg-p->TotalSwitchingEnd)/p->TotalSwitchingBeg ); printf( "\n" ); //#if 0 printf( "Nodes = %d. Try = %d. Resub = %d. Div = %d. SAT calls = %d. Timeouts = %d.\n", Abc_NtkNodeNum(p->pNtk), p->nNodesTried, p->nNodesResub, p->nTotalDivs, p->nSatCalls, p->nTimeOuts ); //#endif if ( p->pPars->fSwapEdge ) printf( "Swappable edges = %d. Total edges = %d. Ratio = %5.2f.\n", p->nNodesResub, Abc_NtkGetTotalFanins(p->pNtk), 1.00 * p->nNodesResub / Abc_NtkGetTotalFanins(p->pNtk) ); else Abc_NtkMfsPrintResubStats( p ); // printf( "Average ratio of DCs in the resubed nodes = %.2f.\n", 1.0*p->nDcMints/(64 * p->nNodesResub) ); } else { printf( "Nodes = %d. Try = %d. Total mints = %d. Local DC mints = %d. Ratio = %5.2f.\n", Abc_NtkNodeNum(p->pNtk), p->nNodesTried, p->nMintsTotal, p->nMintsTotal-p->nMintsCare, 1.0 * (p->nMintsTotal-p->nMintsCare) / p->nMintsTotal ); // printf( "Average ratio of sequential DCs in the global space = %5.2f.\n", // 1.0-(p->dTotalRatios/p->nNodesTried) ); printf( "Nodes resyn = %d. Ratio = %5.2f. Total AIG node gain = %d. Timeouts = %d.\n", p->nNodesDec, 1.0 * p->nNodesDec / p->nNodesTried, p->nNodesGained, p->nTimeOuts ); } ABC_PRTP( "Win", p->timeWin , p->timeTotal ); ABC_PRTP( "Div", p->timeDiv , p->timeTotal ); ABC_PRTP( "Aig", p->timeAig , p->timeTotal ); ABC_PRTP( "Gia", p->timeGia , p->timeTotal ); ABC_PRTP( "Cnf", p->timeCnf , p->timeTotal ); ABC_PRTP( "Sat", p->timeSat-p->timeInt , p->timeTotal ); ABC_PRTP( "Int", p->timeInt , p->timeTotal ); ABC_PRTP( "ALL", p->timeTotal , p->timeTotal ); }
/**Function************************************************************* Synopsis [Transfers names from one netlist to the other.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkDress( Abc_Ntk_t * pNtkLogic, char * pFileName, int fVerbose ) { Abc_Ntk_t * pNtkOrig, * pNtkLogicOrig; Abc_Ntk_t * pMiter, * pMiterFraig; stmm_table * tMapping; assert( Abc_NtkIsLogic(pNtkLogic) ); // get the original netlist pNtkOrig = Io_ReadNetlist( pFileName, Io_ReadFileType(pFileName), 1 ); if ( pNtkOrig == NULL ) return; assert( Abc_NtkIsNetlist(pNtkOrig) ); Abc_NtkCleanCopy(pNtkLogic); Abc_NtkCleanCopy(pNtkOrig); // convert it into the logic network pNtkLogicOrig = Abc_NtkToLogic( pNtkOrig ); // check that the networks have the same PIs/POs/latches if ( !Abc_NtkCompareSignals( pNtkLogic, pNtkLogicOrig, 1, 1 ) ) { Abc_NtkDelete( pNtkOrig ); Abc_NtkDelete( pNtkLogicOrig ); return; } // convert the current logic network into an AIG pMiter = Abc_NtkStrash( pNtkLogic, 1, 0, 0 ); // convert it into the AIG and make the netlist point to the AIG Abc_NtkAppend( pMiter, pNtkLogicOrig, 1 ); Abc_NtkTransferCopy( pNtkOrig ); Abc_NtkDelete( pNtkLogicOrig ); if ( fVerbose ) { printf( "After mitering:\n" ); printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); } // fraig the miter (miter nodes point to the fraiged miter) pMiterFraig = Abc_NtkIvyFraig( pMiter, 100, 1, 0, 1, 0 ); // make netlists point to the fraiged miter Abc_NtkTransferCopy( pNtkLogic ); Abc_NtkTransferCopy( pNtkOrig ); Abc_NtkDelete( pMiter ); if ( fVerbose ) { printf( "After fraiging:\n" ); printf( "Logic: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkLogic), Abc_NtkCountCopy(pNtkLogic) ); printf( "Orig: Nodes = %5d. Copy = %5d. \n", Abc_NtkNodeNum(pNtkOrig), Abc_NtkCountCopy(pNtkOrig) ); } // derive mapping from the fraiged nodes into their prototype nodes in the original netlist tMapping = Abc_NtkDressDeriveMapping( pNtkOrig ); // transfer the names to the new netlist Abc_NtkDressTransferNames( pNtkLogic, tMapping, fVerbose ); // clean up stmm_free_table( tMapping ); Abc_NtkDelete( pMiterFraig ); Abc_NtkDelete( pNtkOrig ); }
/**Function************************************************************* Synopsis [Implements the given retiming on the sequential AIG.] Description [Returns 0 of initial state computation fails.] SideEffects [] SeeAlso [] ***********************************************************************/ int Seq_NtkImplementRetimingBackward( Abc_Ntk_t * pNtk, Vec_Ptr_t * vMoves, int fVerbose ) { Seq_RetEdge_t RetEdge; stmm_table * tTable; stmm_generator * gen; Vec_Int_t * vValues; Abc_Ntk_t * pNtkProb, * pNtkMiter, * pNtkCnf; Abc_Obj_t * pNode, * pNodeNew; int * pModel, RetValue, i, clk; // return if the retiming is trivial if ( Vec_PtrSize(vMoves) == 0 ) return 1; // create the network for the initial state computation // start the table and the array of PO values pNtkProb = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); tTable = stmm_init_table( stmm_numcmp, stmm_numhash ); vValues = Vec_IntAlloc( 100 ); // perform the backward moves and build the network for initial state computation RetValue = 0; Vec_PtrForEachEntry( vMoves, pNode, i ) RetValue |= Abc_ObjRetimeBackward( pNode, pNtkProb, tTable, vValues ); // add the PIs corresponding to the white spots stmm_foreach_item( tTable, gen, (char **)&RetEdge, (char **)&pNodeNew ) Abc_ObjAddFanin( pNodeNew, Abc_NtkCreatePi(pNtkProb) ); // add the PI/PO names Abc_NtkAddDummyPiNames( pNtkProb ); Abc_NtkAddDummyPoNames( pNtkProb ); Abc_NtkAddDummyAssertNames( pNtkProb ); // make sure everything is okay with the network structure if ( !Abc_NtkDoCheck( pNtkProb ) ) { printf( "Seq_NtkImplementRetimingBackward: The internal network check has failed.\n" ); Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); Abc_NtkDelete( pNtkProb ); stmm_free_table( tTable ); Vec_IntFree( vValues ); return 0; } // check if conflict is found if ( RetValue ) { printf( "Seq_NtkImplementRetimingBackward: A top level conflict is detected. DC latch values are used.\n" ); Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); Abc_NtkDelete( pNtkProb ); stmm_free_table( tTable ); Vec_IntFree( vValues ); return 0; } // get the miter cone pNtkMiter = Abc_NtkCreateTarget( pNtkProb, pNtkProb->vCos, vValues ); Abc_NtkDelete( pNtkProb ); Vec_IntFree( vValues ); if ( fVerbose ) printf( "The number of ANDs in the AIG = %5d.\n", Abc_NtkNodeNum(pNtkMiter) ); // transform the miter into a logic network for efficient CNF construction // pNtkCnf = Abc_Ntk_Renode( pNtkMiter, 0, 100, 1, 0, 0 ); // Abc_NtkDelete( pNtkMiter ); pNtkCnf = pNtkMiter; // solve the miter clk = clock(); // RetValue = Abc_NtkMiterSat_OldAndRusty( pNtkCnf, 30, 0 ); RetValue = Abc_NtkMiterSat( pNtkCnf, (sint64)500000, (sint64)50000000, 0, 0, NULL, NULL ); if ( fVerbose ) if ( clock() - clk > 100 ) { PRT( "SAT solving time", clock() - clk ); } pModel = pNtkCnf->pModel; pNtkCnf->pModel = NULL; Abc_NtkDelete( pNtkCnf ); // analyze the result if ( RetValue == -1 || RetValue == 1 ) { Abc_NtkRetimeSetInitialValues( pNtk, tTable, NULL ); if ( RetValue == 1 ) printf( "Seq_NtkImplementRetimingBackward: The problem is unsatisfiable. DC latch values are used.\n" ); else printf( "Seq_NtkImplementRetimingBackward: The SAT problem timed out. DC latch values are used.\n" ); stmm_free_table( tTable ); return 0; } // set the values of the latches Abc_NtkRetimeSetInitialValues( pNtk, tTable, pModel ); stmm_free_table( tTable ); free( pModel ); return 1; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p ) { ProgressBar * pProgress; Vec_Ptr_t * vTokens; Abc_Ntk_t * pNtk; Abc_Obj_t * pTermPi, * pTermPo, * pNode; Vec_Str_t ** ppSops; char Buffer[100]; int nInputs = -1, nOutputs = -1, nProducts = -1; char * pCubeIn, * pCubeOut; int i, k, iLine, nDigits, nCubes; // allocate the empty network pNtk = Abc_NtkStartRead( Extra_FileReaderGetFileName(p) ); // go through the lines of the file nCubes = 0; pProgress = Extra_ProgressBarStart( stdout, Extra_FileReaderGetFileSize(p) ); for ( iLine = 0; vTokens = Extra_FileReaderGetTokens(p); iLine++ ) { Extra_ProgressBarUpdate( pProgress, Extra_FileReaderGetCurPosition(p), NULL ); // if it is the end of file, quit the loop if ( strcmp( vTokens->pArray[0], ".e" ) == 0 ) break; if ( vTokens->nSize == 1 ) { printf( "%s (line %d): Wrong number of token.\n", Extra_FileReaderGetFileName(p), iLine+1 ); Abc_NtkDelete( pNtk ); return NULL; } if ( strcmp( vTokens->pArray[0], ".i" ) == 0 ) nInputs = atoi(vTokens->pArray[1]); else if ( strcmp( vTokens->pArray[0], ".o" ) == 0 ) nOutputs = atoi(vTokens->pArray[1]); else if ( strcmp( vTokens->pArray[0], ".p" ) == 0 ) nProducts = atoi(vTokens->pArray[1]); else if ( strcmp( vTokens->pArray[0], ".ilb" ) == 0 ) { if ( vTokens->nSize - 1 != nInputs ) printf( "Warning: Mismatch between the number of PIs on the .i line (%d) and the number of PIs on the .ilb line (%d).\n", nInputs, vTokens->nSize - 1 ); for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePi( pNtk, vTokens->pArray[i] ); } else if ( strcmp( vTokens->pArray[0], ".ob" ) == 0 ) { if ( vTokens->nSize - 1 != nOutputs ) printf( "Warning: Mismatch between the number of POs on the .o line (%d) and the number of POs on the .ob line (%d).\n", nOutputs, vTokens->nSize - 1 ); for ( i = 1; i < vTokens->nSize; i++ ) Io_ReadCreatePo( pNtk, vTokens->pArray[i] ); } else { // check if the input/output names are given if ( Abc_NtkPiNum(pNtk) == 0 ) { if ( nInputs == -1 ) { printf( "%s: The number of inputs is not specified.\n", Extra_FileReaderGetFileName(p) ); Abc_NtkDelete( pNtk ); return NULL; } nDigits = Extra_Base10Log( nInputs ); for ( i = 0; i < nInputs; i++ ) { sprintf( Buffer, "x%0*d", nDigits, i ); Io_ReadCreatePi( pNtk, Buffer ); } } if ( Abc_NtkPoNum(pNtk) == 0 ) { if ( nOutputs == -1 ) { printf( "%s: The number of outputs is not specified.\n", Extra_FileReaderGetFileName(p) ); Abc_NtkDelete( pNtk ); return NULL; } nDigits = Extra_Base10Log( nOutputs ); for ( i = 0; i < nOutputs; i++ ) { sprintf( Buffer, "z%0*d", nDigits, i ); Io_ReadCreatePo( pNtk, Buffer ); } } if ( Abc_NtkNodeNum(pNtk) == 0 ) { // first time here // create the PO drivers and add them // start the SOP covers ppSops = ALLOC( Vec_Str_t *, nOutputs ); Abc_NtkForEachPo( pNtk, pTermPo, i ) { ppSops[i] = Vec_StrAlloc( 100 ); // create the node pNode = Abc_NtkCreateNode(pNtk); // connect the node to the PO net Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode ); // connect the node to the PI nets Abc_NtkForEachPi( pNtk, pTermPi, k ) Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) ); } } // read the cubes if ( vTokens->nSize != 2 ) { printf( "%s (line %d): Input and output cubes are not specified.\n", Extra_FileReaderGetFileName(p), iLine+1 ); Abc_NtkDelete( pNtk ); return NULL; } pCubeIn = vTokens->pArray[0]; pCubeOut = vTokens->pArray[1]; if ( strlen(pCubeIn) != (unsigned)nInputs ) { printf( "%s (line %d): Input cube length (%d) differs from the number of inputs (%d).\n", Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeIn), nInputs ); Abc_NtkDelete( pNtk ); return NULL; } if ( strlen(pCubeOut) != (unsigned)nOutputs ) { printf( "%s (line %d): Output cube length (%d) differs from the number of outputs (%d).\n", Extra_FileReaderGetFileName(p), iLine+1, strlen(pCubeOut), nOutputs ); Abc_NtkDelete( pNtk ); return NULL; } for ( i = 0; i < nOutputs; i++ ) { if ( pCubeOut[i] == '1' ) { Vec_StrAppend( ppSops[i], pCubeIn ); Vec_StrAppend( ppSops[i], " 1\n" ); } } nCubes++; }
// complement the FF if needed if ( fCompl ) Dec_GraphComplement( pGraph ); clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk ); if ( fCompl ) Dec_GraphComplement( pGraph ); // use the array of changed nodes to update placement // if ( fPlaceEnable ) // Abc_PlaceUpdate( vAddedCells, vUpdatedNets ); } Extra_ProgressBarStop( pProgress ); Rwr_ManAddTimeTotal( pManRwr, Abc_Clock() - clkStart ); // print stats pManRwr->nNodesEnd = Abc_NtkNodeNum(pNtk); if ( fVerbose ) Rwr_ManPrintStats( pManRwr ); // Rwr_ManPrintStatsFile( pManRwr ); if ( fVeryVerbose ) Rwr_ScoresReport( pManRwr ); // delete the managers Rwr_ManStop( pManRwr ); Cut_ManStop( pManCut ); pNtk->pManCut = NULL; // start placement package // if ( fPlaceEnable ) // { // Abc_PlaceEnd( pNtk ); // Abc_AigUpdateStop( pNtk->pManFunc );
} Vec_Ptr_t * Abc_NtkAssignIDs2( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i; Abc_NtkCleanCopy( pNtk ); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = i; vNodes = Vec_PtrAlloc( Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachNode( pNtk, pObj, i ) { pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes); Vec_PtrPush( vNodes, pObj ); } assert( Vec_PtrSize(vNodes) == Abc_NtkNodeNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Abc_NtkCiNum(pNtk) + Vec_PtrSize(vNodes) + i; return vNodes; } /**Function************************************************************* Synopsis [Extracts information about the network.] Description [] SideEffects [] SeeAlso []
/**Function************************************************************* Synopsis [Writes the graph structure of network for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) { FILE * pFile; Abc_Obj_t * pNode, * pFanin; char * pSopString; int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; int Limit = 300; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( vNodes->nSize < 1 ) { printf( "The set has no nodes. DOT file is not written.\n" ); return; } if ( vNodes->nSize > Limit ) { printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); return; } // start the stream if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // transform logic functions from BDD to SOP if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, 0) ) { printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); return; } } // mark the nodes from the set Vec_PtrForEachEntry( vNodes, pNode, i ) pNode->fMarkC = 1; if ( vNodesShow ) Vec_PtrForEachEntry( vNodesShow, pNode, i ) pNode->fMarkB = 1; // get the levels of nodes LevelMax = Abc_NtkLevel( pNtk ); if ( fUseReverse ) { LevelMin = Abc_NtkLevelReverse( pNtk ); assert( LevelMax == LevelMin ); Vec_PtrForEachEntry( vNodes, pNode, i ) if ( Abc_ObjIsNode(pNode) ) pNode->Level = LevelMax - pNode->Level + 1; } // find the largest and the smallest levels LevelMin = 10000; LevelMax = -1; fHasCos = 0; Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) { fHasCos = 1; continue; } if ( LevelMin > (int)pNode->Level ) LevelMin = pNode->Level; if ( LevelMax < (int)pNode->Level ) LevelMax = pNode->Level; } // set the level of the CO nodes if ( fHasCos ) { LevelMax++; Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) pNode->Level = LevelMax; } } // write the DOT header fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph network {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "size = \"10,8.5\";\n" ); // fprintf( pFile, "size = \"14,11\";\n" ); // fprintf( pFile, "page = \"8,11\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= LevelMin; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= LevelMin; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != LevelMin ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "Network structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); else fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the POs if ( fHasCos ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( !Abc_ObjIsCo(pNode) ) continue; fprintf( pFile, " Node%d [label = \"%s%s\"", pNode->Id, (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), (Abc_ObjIsBi(pNode)? "_in":"") ); fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate nodes of each rank for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( (int)pNode->Level != Level ) continue; if ( Abc_ObjFaninNum(pNode) == 0 ) continue; // fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); if ( Abc_NtkIsStrash(pNtk) ) pSopString = ""; else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) pSopString = Mio_GateReadName(pNode->pData); else if ( Abc_NtkHasMapping(pNtk) ) pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); else pSopString = Abc_NtkPrintSop(pNode->pData); fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the PI nodes if any if ( LevelMin == 0 ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMin ); // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( !Abc_ObjIsCi(pNode) ) { // check if the costant node is present if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) { fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } continue; } fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); }
/**Function************************************************************* Synopsis [Print the vital stats of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored ) { int Num; // if ( Abc_NtkIsStrash(pNtk) ) // Abc_AigCountNext( pNtk->pManFunc ); fprintf( pFile, "%-13s:", pNtk->pName ); if ( Abc_NtkAssertNum(pNtk) ) fprintf( pFile, " i/o/a = %4d/%4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkAssertNum(pNtk) ); else fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) ); fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) ); if ( Abc_NtkIsNetlist(pNtk) ) { fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) ); fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); fprintf( pFile, " wbox = %3d", Abc_NtkWhiteboxNum(pNtk) ); fprintf( pFile, " bbox = %3d", Abc_NtkBlackboxNum(pNtk) ); } else if ( Abc_NtkIsStrash(pNtk) ) { fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) ); if ( Num = Abc_NtkGetChoiceNum(pNtk) ) fprintf( pFile, " (choice = %d)", Num ); if ( Num = Abc_NtkGetExorNum(pNtk) ) fprintf( pFile, " (exor = %d)", Num ); // if ( Num2 = Abc_NtkGetMuxNum(pNtk) ) // fprintf( pFile, " (mux = %d)", Num2-Num ); // if ( Num2 ) // fprintf( pFile, " (other = %d)", Abc_NtkNodeNum(pNtk)-3*Num2 ); } else { fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) ); fprintf( pFile, " net = %5d", Abc_NtkGetTotalFanins(pNtk) ); } if ( Abc_NtkIsStrash(pNtk) || Abc_NtkIsNetlist(pNtk) ) { } else if ( Abc_NtkHasSop(pNtk) ) { fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) ); // fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) ); if ( fFactored ) fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) ); } else if ( Abc_NtkHasAig(pNtk) ) fprintf( pFile, " aig = %5d", Abc_NtkGetAigNodeNum(pNtk) ); else if ( Abc_NtkHasBdd(pNtk) ) fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) ); else if ( Abc_NtkHasMapping(pNtk) ) { fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) ); fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) ); } else if ( !Abc_NtkHasBlackbox(pNtk) ) { assert( 0 ); } if ( Abc_NtkIsStrash(pNtk) ) fprintf( pFile, " lev = %3d", Abc_AigLevel(pNtk) ); else fprintf( pFile, " lev = %3d", Abc_NtkLevel(pNtk) ); fprintf( pFile, "\n" ); // Abc_NtkCrossCut( pNtk ); // print the statistic into a file /* { FILE * pTable; pTable = fopen( "iscas/seqmap__stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } */ /* // print the statistic into a file { FILE * pTable; pTable = fopen( "stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pSpec ); fprintf( pTable, "%.0f ", Abc_NtkGetMappedArea(pNtk) ); fprintf( pTable, "%.2f ", Abc_NtkDelayTrace(pNtk) ); fprintf( pTable, "\n" ); fclose( pTable ); } */ /* // print the statistic into a file { FILE * pTable; pTable = fopen( "x/stats_new.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkGetTotalFanins(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); // fprintf( pTable, "%.2f ", (float)(s_MappingMem)/(float)(1<<20) ); fprintf( pTable, "%.2f", (float)(s_MappingTime)/(float)(CLOCKS_PER_SEC) ); // fprintf( pTable, "%.2f", (float)(s_ResynTime)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); s_ResynTime = 0; } */ /* // print the statistic into a file { static int Counter = 0; extern int timeRetime; FILE * pTable; Counter++; pTable = fopen( "a/ret__stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkLevel(pNtk) ); fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); if ( Counter % 4 == 0 ) fprintf( pTable, "\n" ); fclose( pTable ); } */ /* // print the statistic into a file { static int Counter = 0; extern int timeRetime; FILE * pTable; Counter++; pTable = fopen( "d/stats.txt", "a+" ); fprintf( pTable, "%s ", pNtk->pName ); // fprintf( pTable, "%d ", Abc_NtkPiNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkPoNum(pNtk) ); // fprintf( pTable, "%d ", Abc_NtkLatchNum(pNtk) ); fprintf( pTable, "%d ", Abc_NtkNodeNum(pNtk) ); fprintf( pTable, "%.2f ", (float)(timeRetime)/(float)(CLOCKS_PER_SEC) ); fprintf( pTable, "\n" ); fclose( pTable ); } */ /* s_TotalNodes += Abc_NtkNodeNum(pNtk); printf( "Total nodes = %6d %6.2f Mb Changes = %6d.\n", s_TotalNodes, s_TotalNodes * 20.0 / (1<<20), s_TotalChanges ); */ }
/**Function************************************************************* Synopsis [Performs incremental rewriting of the AIG.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRewrite( Abc_Ntk_t * pNtk, int fUpdateLevel, int fUseZeros, int fVerbose, int fVeryVerbose, int fPlaceEnable ) { extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int fUpdateLevel, int nGain ); ProgressBar * pProgress; Cut_Man_t * pManCut; Rwr_Man_t * pManRwr; Abc_Obj_t * pNode; // Vec_Ptr_t * vAddedCells = NULL, * vUpdatedNets = NULL; Dec_Graph_t * pGraph; int i, nNodes, nGain, fCompl; abctime clk, clkStart = Abc_Clock(); assert( Abc_NtkIsStrash(pNtk) ); // cleanup the AIG Abc_AigCleanup((Abc_Aig_t *)pNtk->pManFunc); /* { Vec_Vec_t * vParts; vParts = Abc_NtkPartitionSmart( pNtk, 50, 1 ); Vec_VecFree( vParts ); } */ // start placement package // if ( fPlaceEnable ) // { // Abc_PlaceBegin( pNtk ); // vAddedCells = Abc_AigUpdateStart( pNtk->pManFunc, &vUpdatedNets ); // } // start the rewriting manager pManRwr = Rwr_ManStart( 0 ); if ( pManRwr == NULL ) return 0; // compute the reverse levels if level update is requested if ( fUpdateLevel ) Abc_NtkStartReverseLevels( pNtk, 0 ); // start the cut manager clk = Abc_Clock(); pManCut = Abc_NtkStartCutManForRewrite( pNtk ); Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk ); pNtk->pManCut = pManCut; if ( fVeryVerbose ) Rwr_ScoresClean( pManRwr ); // resynthesize each node once pManRwr->nNodesBeg = Abc_NtkNodeNum(pNtk); nNodes = Abc_NtkObjNumMax(pNtk); pProgress = Extra_ProgressBarStart( stdout, nNodes ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); // stop if all nodes have been tried once if ( i >= nNodes ) break; // skip persistant nodes if ( Abc_NodeIsPersistant(pNode) ) continue; // skip the nodes with many fanouts if ( Abc_ObjFanoutNum(pNode) > 1000 ) continue; // for each cut, try to resynthesize it nGain = Rwr_NodeRewrite( pManRwr, pManCut, pNode, fUpdateLevel, fUseZeros, fPlaceEnable ); if ( !(nGain > 0 || (nGain == 0 && fUseZeros)) ) continue; // if we end up here, a rewriting step is accepted // get hold of the new subgraph to be added to the AIG pGraph = (Dec_Graph_t *)Rwr_ManReadDecs(pManRwr); fCompl = Rwr_ManReadCompl(pManRwr); // reset the array of the changed nodes if ( fPlaceEnable ) Abc_AigUpdateReset( (Abc_Aig_t *)pNtk->pManFunc ); // complement the FF if needed if ( fCompl ) Dec_GraphComplement( pGraph ); clk = Abc_Clock(); Dec_GraphUpdateNetwork( pNode, pGraph, fUpdateLevel, nGain ); Rwr_ManAddTimeUpdate( pManRwr, Abc_Clock() - clk ); if ( fCompl ) Dec_GraphComplement( pGraph ); // use the array of changed nodes to update placement // if ( fPlaceEnable ) // Abc_PlaceUpdate( vAddedCells, vUpdatedNets ); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkGate( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Mio_Library_t * pGenlib; Mio_Gate_t * pGate; Abc_Obj_t * pNode; char ** ppNames; int i, nNames; // check that the library is available pGenlib = (Mio_Library_t *)Abc_FrameReadLibGen(); if ( pGenlib == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The current library is not available." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create a new node and add it to the network if ( vTokens->nSize < 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .gate line has less than two tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the gate pGate = Mio_LibraryReadGateByName( pGenlib, (char *)vTokens->pArray[1] ); if ( pGate == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find gate \"%s\" in the library.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // if this is the first line with gate, update the network type if ( Abc_NtkNodeNum(p->pNtkCur) == 0 ) { assert( p->pNtkCur->ntkFunc == ABC_FUNC_SOP ); p->pNtkCur->ntkFunc = ABC_FUNC_MAP; Mem_FlexStop( (Mem_Flex_t *)p->pNtkCur->pManFunc, 0 ); p->pNtkCur->pManFunc = pGenlib; } // reorder the formal inputs to be in the same order as in the gate if ( !Io_ReadBlifReorderFormalNames( vTokens, pGate ) ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Mismatch in the fanins of gate \"%s\".", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // remove the formal parameter names for ( i = 2; i < vTokens->nSize; i++ ) { vTokens->pArray[i] = Io_ReadBlifCleanName( (char *)vTokens->pArray[i] ); if ( vTokens->pArray[i] == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Invalid gate input assignment." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } } // create the node ppNames = (char **)vTokens->pArray + 2; nNames = vTokens->nSize - 3; pNode = Io_ReadCreateNode( p->pNtkCur, ppNames[nNames], ppNames, nNames ); // set the pointer to the functionality of the node Abc_ObjSetData( pNode, pGate ); return 0; }
/**Function************************************************************* Synopsis [Attempts to solve the miter using a number of tricks.] Description [Returns -1 if timed out; 0 if SAT; 1 if UNSAT. Returns a simplified version of the original network (or a constant 0 network). In case the network is not a constant zero and a SAT assignment is found, pNtk->pModel contains a satisfying assignment.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterProve( Abc_Ntk_t ** ppNtk, void * pPars ) { Prove_Params_t * pParams = pPars; Abc_Ntk_t * pNtk, * pNtkTemp; int RetValue, nIter, nSatFails, Counter, clk, timeStart = clock(); sint64 nSatConfs, nSatInspects, nInspectLimit; // get the starting network pNtk = *ppNtk; assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkPoNum(pNtk) == 1 ); if ( pParams->fVerbose ) { printf( "RESOURCE LIMITS: Iterations = %d. Rewriting = %s. Fraiging = %s.\n", pParams->nItersMax, pParams->fUseRewriting? "yes":"no", pParams->fUseFraiging? "yes":"no" ); printf( "Mitering = %d (%3.1f). Rewriting = %d (%3.1f). Fraiging = %d (%3.1f).\n", pParams->nMiteringLimitStart, pParams->nMiteringLimitMulti, pParams->nRewritingLimitStart, pParams->nRewritingLimitMulti, pParams->nFraigingLimitStart, pParams->nFraigingLimitMulti ); printf( "Mitering last = %d.\n", pParams->nMiteringLimitLast ); } // if SAT only, solve without iteration if ( !pParams->fUseRewriting && !pParams->fUseFraiging ) { clk = clock(); RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)0, 0, NULL, NULL ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); *ppNtk = pNtk; return RetValue; } // check the current resource limits for ( nIter = 0; nIter < pParams->nItersMax; nIter++ ) { if ( pParams->fVerbose ) { printf( "ITERATION %2d : Confs = %6d. FraigBTL = %3d. \n", nIter+1, (int)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)) ); fflush( stdout ); } // try brute-force SAT clk = clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; RetValue = Abc_NtkMiterSat( pNtk, (sint64)(pParams->nMiteringLimitStart * pow(pParams->nMiteringLimitMulti,nIter)), (sint64)nInspectLimit, 0, &nSatConfs, &nSatInspects ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); if ( RetValue >= 0 ) break; // add to the number of backtracks and inspects pParams->nTotalBacktracksMade += nSatConfs; pParams->nTotalInspectsMade += nSatInspects; // check if global resource limit is reached if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) { printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); *ppNtk = pNtk; return -1; } // try rewriting if ( pParams->fUseRewriting ) { clk = clock(); Counter = (int)(pParams->nRewritingLimitStart * pow(pParams->nRewritingLimitMulti,nIter)); // Counter = 1; while ( 1 ) { /* extern Abc_Ntk_t * Abc_NtkIvyResyn( Abc_Ntk_t * pNtk, int fUpdateLevel, int fVerbose ); pNtk = Abc_NtkIvyResyn( pNtkTemp = pNtk, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; */ /* Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; */ Abc_NtkRewrite( pNtk, 0, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; Abc_NtkRefactor( pNtk, 10, 16, 0, 0, 0, 0 ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; pNtk = Abc_NtkBalance( pNtkTemp = pNtk, 0, 0, 0 ); Abc_NtkDelete( pNtkTemp ); if ( (RetValue = Abc_NtkMiterIsConstant(pNtk)) >= 0 ) break; if ( --Counter == 0 ) break; } Abc_NtkMiterPrint( pNtk, "Rewriting ", clk, pParams->fVerbose ); } if ( pParams->fUseFraiging ) { // try FRAIGing clk = clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; pNtk = Abc_NtkMiterFraig( pNtkTemp = pNtk, (int)(pParams->nFraigingLimitStart * pow(pParams->nFraigingLimitMulti,nIter)), nInspectLimit, &RetValue, &nSatFails, &nSatConfs, &nSatInspects ); Abc_NtkDelete( pNtkTemp ); Abc_NtkMiterPrint( pNtk, "FRAIGing ", clk, pParams->fVerbose ); // printf( "NumFails = %d\n", nSatFails ); if ( RetValue >= 0 ) break; // add to the number of backtracks and inspects pParams->nTotalBacktracksMade += nSatConfs; pParams->nTotalInspectsMade += nSatInspects; // check if global resource limit is reached if ( (pParams->nTotalBacktrackLimit && pParams->nTotalBacktracksMade >= pParams->nTotalBacktrackLimit) || (pParams->nTotalInspectLimit && pParams->nTotalInspectsMade >= pParams->nTotalInspectLimit) ) { printf( "Reached global limit on conflicts/inspects. Quitting.\n" ); *ppNtk = pNtk; return -1; } } } // try to prove it using brute force SAT if ( RetValue < 0 && pParams->fUseBdds ) { if ( pParams->fVerbose ) { printf( "Attempting BDDs with node limit %d ...\n", pParams->nBddSizeLimit ); fflush( stdout ); } clk = clock(); pNtk = Abc_NtkCollapse( pNtkTemp = pNtk, pParams->nBddSizeLimit, 0, pParams->fBddReorder, 0 ); if ( pNtk ) { Abc_NtkDelete( pNtkTemp ); RetValue = ( (Abc_NtkNodeNum(pNtk) == 1) && (Abc_ObjFanin0(Abc_NtkPo(pNtk,0))->pData == Cudd_ReadLogicZero(pNtk->pManFunc)) ); } else pNtk = pNtkTemp; Abc_NtkMiterPrint( pNtk, "BDD building", clk, pParams->fVerbose ); } if ( RetValue < 0 ) { if ( pParams->fVerbose ) { printf( "Attempting SAT with conflict limit %d ...\n", pParams->nMiteringLimitLast ); fflush( stdout ); } clk = clock(); nInspectLimit = pParams->nTotalInspectLimit? pParams->nTotalInspectLimit - pParams->nTotalInspectsMade : 0; RetValue = Abc_NtkMiterSat( pNtk, (sint64)pParams->nMiteringLimitLast, (sint64)nInspectLimit, 0, NULL, NULL ); Abc_NtkMiterPrint( pNtk, "SAT solving", clk, pParams->fVerbose ); } // assign the model if it was proved by rewriting (const 1 miter) if ( RetValue == 0 && pNtk->pModel == NULL ) { pNtk->pModel = ALLOC( int, Abc_NtkCiNum(pNtk) ); memset( pNtk->pModel, 0, sizeof(int) * Abc_NtkCiNum(pNtk) ); }
/**Function************************************************************* Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecFraigPartAuto( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int fVerbose ) { extern int Abc_NtkCombinePos( Abc_Ntk_t * pNtk, int fAnd ); extern Vec_Ptr_t * Abc_NtkPartitionSmart( Abc_Ntk_t * pNtk, int nPartSizeLimit, int fVerbose ); extern void Abc_NtkConvertCos( Abc_Ntk_t * pNtk, Vec_Int_t * vOuts, Vec_Ptr_t * vOnePtr ); Vec_Ptr_t * vParts, * vOnePtr; Vec_Int_t * vOne; Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pMiter, * pMiterPart; int i, RetValue, Status, nOutputs; // solve the CNF using the SAT solver Prove_ParamsSetDefault( pParams ); pParams->nItersMax = 5; // pParams->fVerbose = 1; // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, 1, 0, 0 ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); ABC_FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { printf( "Networks are equivalent after structural hashing.\n" ); Abc_NtkDelete( pMiter ); return; } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // partition the outputs vParts = Abc_NtkPartitionSmart( pMiter, 300, 0 ); // fraig each partition Status = 1; nOutputs = 0; vOnePtr = Vec_PtrAlloc( 1000 ); Vec_PtrForEachEntry( Vec_Int_t *, vParts, vOne, i ) { // get this part of the miter Abc_NtkConvertCos( pMiter, vOne, vOnePtr ); pMiterPart = Abc_NtkCreateConeArray( pMiter, vOnePtr, 0 ); Abc_NtkCombinePos( pMiterPart, 0 ); // check the miter for being constant RetValue = Abc_NtkMiterIsConstant( pMiterPart ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after partitioning.\n" ); Abc_NtkDelete( pMiterPart ); break; } if ( RetValue == 1 ) { Abc_NtkDelete( pMiterPart ); continue; } printf( "Verifying part %4d (out of %4d) PI = %5d. PO = %5d. And = %6d. Lev = %4d.\r", i+1, Vec_PtrSize(vParts), Abc_NtkPiNum(pMiterPart), Abc_NtkPoNum(pMiterPart), Abc_NtkNodeNum(pMiterPart), Abc_AigLevel(pMiterPart) ); fflush( stdout ); // solve the problem RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); if ( RetValue == -1 ) { printf( "Networks are undecided (resource limits is reached).\r" ); Status = -1; } else if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); if ( pSimInfo[0] != 1 ) printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); else printf( "Networks are NOT EQUIVALENT. \n" ); ABC_FREE( pSimInfo ); Status = 0; Abc_NtkDelete( pMiterPart ); break; } else { // printf( "Finished part %5d (out of %5d)\r", i+1, Vec_PtrSize(vParts) ); nOutputs += Vec_IntSize(vOne); } Abc_NtkDelete( pMiterPart ); }