/**Function************************************************************* Synopsis [Replaces node with a buffer fanin by a node without them.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_NodeFixBufferFanins( Aig_Man_t * p, Aig_Obj_t * pObj, int fNodesOnly, int fUpdateLevel ) { Aig_Obj_t * pFanReal0, * pFanReal1, * pResult; p->nBufFixes++; if ( Aig_ObjIsPo(pObj) ) { assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) ); pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); assert( Aig_ObjPhaseReal(Aig_ObjChild0(pObj)) == Aig_ObjPhaseReal(pFanReal0) ); Aig_ObjPatchFanin0( p, pObj, pFanReal0 ); return; } assert( Aig_ObjIsNode(pObj) ); assert( Aig_ObjIsBuf(Aig_ObjFanin0(pObj)) || Aig_ObjIsBuf(Aig_ObjFanin1(pObj)) ); // get the real fanins pFanReal0 = Aig_ObjReal_rec( Aig_ObjChild0(pObj) ); pFanReal1 = Aig_ObjReal_rec( Aig_ObjChild1(pObj) ); // get the new node if ( Aig_ObjIsNode(pObj) ) pResult = Aig_Oper( p, pFanReal0, pFanReal1, Aig_ObjType(pObj) ); // else if ( Aig_ObjIsLatch(pObj) ) // pResult = Aig_Latch( p, pFanReal0, Aig_ObjInit(pObj) ); else assert( 0 ); // replace the node with buffer by the node without buffer Aig_ObjReplace( p, pObj, pResult, fNodesOnly, fUpdateLevel ); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Fra_FraigSec( Aig_Man_t * p, Fra_Sec_t * pParSec, Aig_Man_t ** ppResult ) { Ssw_Pars_t Pars2, * pPars2 = &Pars2; Fra_Ssw_t Pars, * pPars = &Pars; Fra_Sml_t * pSml; Aig_Man_t * pNew, * pTemp; int nFrames, RetValue, nIter; abctime clk, clkTotal = Abc_Clock(); int TimeOut = 0; int fLatchCorr = 0; float TimeLeft = 0.0; pParSec->nSMnumber = -1; // try the miter before solving pNew = Aig_ManDupSimple( p ); RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue >= 0 ) goto finish; // prepare parameters memset( pPars, 0, sizeof(Fra_Ssw_t) ); pPars->fLatchCorr = fLatchCorr; pPars->fVerbose = pParSec->fVeryVerbose; if ( pParSec->fVerbose ) { printf( "Original miter: Latches = %5d. Nodes = %6d.\n", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); } //Aig_ManDumpBlif( pNew, "after.blif", NULL, NULL ); // perform sequential cleanup clk = Abc_Clock(); if ( pNew->nRegs ) pNew = Aig_ManReduceLaches( pNew, 0 ); if ( pNew->nRegs ) pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); if ( pParSec->fVerbose ) { printf( "Sequential cleanup: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue >= 0 ) goto finish; // perform phase abstraction clk = Abc_Clock(); if ( pParSec->fPhaseAbstract ) { extern Aig_Man_t * Saig_ManPhaseAbstractAuto( Aig_Man_t * p, int fVerbose ); pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); pNew = Saig_ManPhaseAbstractAuto( pTemp = pNew, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Phase abstraction: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // perform forward retiming if ( pParSec->fRetimeFirst && pNew->nRegs ) { clk = Abc_Clock(); // pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); pNew = Saig_ManRetimeForward( pTemp = pNew, 100, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Forward retiming: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // run latch correspondence clk = Abc_Clock(); if ( pNew->nRegs ) { pNew = Aig_ManDupOrdered( pTemp = pNew ); // pNew = Aig_ManDupDfs( pTemp = pNew ); Aig_ManStop( pTemp ); /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ // pNew = Fra_FraigLatchCorrespondence( pTemp = pNew, 0, 1000, 1, pParSec->fVeryVerbose, &nIter, TimeLeft ); //Aig_ManDumpBlif( pNew, "ex.blif", NULL, NULL ); Ssw_ManSetDefaultParamsLcorr( pPars2 ); pNew = Ssw_LatchCorrespondence( pTemp = pNew, pPars2 ); nIter = pPars2->nIters; // prepare parameters for scorr Ssw_ManSetDefaultParams( pPars2 ); if ( pTemp->pSeqModel ) { if ( !Saig_ManVerifyCex( pTemp, pTemp->pSeqModel ) ) printf( "Fra_FraigSec(): Counter-example verification has FAILED.\n" ); if ( Saig_ManPiNum(p) != Saig_ManPiNum(pTemp) ) printf( "The counter-example is invalid because of phase abstraction.\n" ); else { ABC_FREE( p->pSeqModel ); p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); ABC_FREE( pTemp->pSeqModel ); } } if ( pNew == NULL ) { if ( p->pSeqModel ) { RetValue = 0; if ( !pParSec->fSilent ) { printf( "Networks are NOT EQUIVALENT after simulation. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } Aig_ManStop( pTemp ); return RetValue; } pNew = pTemp; RetValue = -1; TimeOut = 1; goto finish; } Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Latch-corr (I=%3d): Latches = %5d. Nodes = %6d. ", nIter, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ // perform fraiging if ( pParSec->fFraiging ) { clk = Abc_Clock(); pNew = Fra_FraigEquivence( pTemp = pNew, 100, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Fraiging: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } if ( pNew->nRegs == 0 ) RetValue = Fra_FraigCec( &pNew, 100000, 0 ); RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue >= 0 ) goto finish; /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ // perform min-area retiming if ( pParSec->fRetimeRegs && pNew->nRegs ) { // extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); clk = Abc_Clock(); pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); // pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); Aig_ManStop( pTemp ); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } // perform seq sweeping while increasing the number of frames RetValue = Fra_FraigMiterStatus( pNew ); if ( RetValue == -1 && pParSec->fInduction ) for ( nFrames = 1; nFrames <= pParSec->nFramesMax; nFrames *= 2 ) { /* if ( RetValue == -1 && pParSec->TimeLimit ) { TimeLeft = (float)pParSec->TimeLimit - ((float)(Abc_Clock()-clkTotal)/(float)(CLOCKS_PER_SEC)); TimeLeft = Abc_MaxInt( TimeLeft, 0.0 ); if ( TimeLeft == 0.0 ) { if ( !pParSec->fSilent ) printf( "Runtime limit exceeded.\n" ); RetValue = -1; TimeOut = 1; goto finish; } } */ clk = Abc_Clock(); pPars->nFramesK = nFrames; pPars->TimeLimit = TimeLeft; pPars->fSilent = pParSec->fSilent; // pNew = Fra_FraigInduction( pTemp = pNew, pPars ); pPars2->nFramesK = nFrames; pPars2->nBTLimit = pParSec->nBTLimit; pPars2->nBTLimitGlobal = pParSec->nBTLimitGlobal; // pPars2->nBTLimit = 1000 * nFrames; if ( RetValue == -1 && pPars2->nConflicts > pPars2->nBTLimitGlobal ) { if ( !pParSec->fSilent ) printf( "Global conflict limit (%d) exceeded.\n", pPars2->nBTLimitGlobal ); RetValue = -1; TimeOut = 1; goto finish; } Aig_ManSetRegNum( pNew, pNew->nRegs ); // pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); if ( Aig_ManRegNum(pNew) > 0 ) pNew = Ssw_SignalCorrespondence( pTemp = pNew, pPars2 ); else pNew = Aig_ManDupSimpleDfs( pTemp = pNew ); if ( pNew == NULL ) { pNew = pTemp; RetValue = -1; TimeOut = 1; goto finish; } // printf( "Total conflicts = %d.\n", pPars2->nConflicts ); Aig_ManStop( pTemp ); RetValue = Fra_FraigMiterStatus( pNew ); if ( pParSec->fVerbose ) { printf( "K-step (K=%2d,I=%3d): Latches = %5d. Nodes = %6d. ", nFrames, pPars2->nIters, Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( RetValue != -1 ) break; // perform retiming // if ( pParSec->fRetimeFirst && pNew->nRegs ) if ( pNew->nRegs ) { // extern Aig_Man_t * Saig_ManRetimeMinArea( Aig_Man_t * p, int nMaxIters, int fForwardOnly, int fBackwardOnly, int fInitial, int fVerbose ); clk = Abc_Clock(); pNew->nTruePis = Aig_ManCiNum(pNew) - Aig_ManRegNum(pNew); pNew->nTruePos = Aig_ManCoNum(pNew) - Aig_ManRegNum(pNew); // pNew = Rtm_ManRetime( pTemp = pNew, 1, 1000, 0 ); pNew = Saig_ManRetimeMinArea( pTemp = pNew, 1000, 0, 0, 1, 0 ); Aig_ManStop( pTemp ); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Min-reg retiming: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } } if ( pNew->nRegs ) pNew = Aig_ManConstReduce( pNew, 0, -1, -1, 0, 0 ); // perform rewriting clk = Abc_Clock(); pNew = Aig_ManDupOrdered( pTemp = pNew ); Aig_ManStop( pTemp ); // pNew = Dar_ManRewriteDefault( pTemp = pNew ); pNew = Dar_ManCompress2( pTemp = pNew, 1, 0, 1, 0, 0 ); Aig_ManStop( pTemp ); if ( pParSec->fVerbose ) { printf( "Rewriting: Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } // perform sequential simulation if ( pNew->nRegs ) { clk = Abc_Clock(); pSml = Fra_SmlSimulateSeq( pNew, 0, 128 * nFrames, 1 + 16/(1+Aig_ManNodeNum(pNew)/1000), 1 ); if ( pParSec->fVerbose ) { printf( "Seq simulation : Latches = %5d. Nodes = %6d. ", Aig_ManRegNum(pNew), Aig_ManNodeNum(pNew) ); ABC_PRT( "Time", Abc_Clock() - clk ); } if ( pSml->fNonConstOut ) { pNew->pSeqModel = Fra_SmlGetCounterExample( pSml ); // transfer to the original manager if ( Saig_ManPiNum(p) != Saig_ManPiNum(pNew) ) printf( "The counter-example is invalid because of phase abstraction.\n" ); else { ABC_FREE( p->pSeqModel ); p->pSeqModel = Abc_CexDup( pNew->pSeqModel, Aig_ManRegNum(p) ); ABC_FREE( pNew->pSeqModel ); } Fra_SmlStop( pSml ); Aig_ManStop( pNew ); RetValue = 0; if ( !pParSec->fSilent ) { printf( "Networks are NOT EQUIVALENT after simulation. " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } if ( pParSec->fReportSolution && !pParSec->fRecursive ) { printf( "SOLUTION: FAIL " ); ABC_PRT( "Time", Abc_Clock() - clkTotal ); } return RetValue; } Fra_SmlStop( pSml ); } } // get the miter status RetValue = Fra_FraigMiterStatus( pNew ); // try interplation clk = Abc_Clock(); Aig_ManSetRegNum( pNew, Aig_ManRegNum(pNew) ); if ( pParSec->fInterpolation && RetValue == -1 && Aig_ManRegNum(pNew) > 0 ) { Inter_ManParams_t Pars, * pPars = &Pars; int Depth; ABC_FREE( pNew->pSeqModel ); Inter_ManSetDefaultParams( pPars ); // pPars->nBTLimit = 100; pPars->nBTLimit = pParSec->nBTLimitInter; pPars->fVerbose = pParSec->fVeryVerbose; if ( Saig_ManPoNum(pNew) == 1 ) { RetValue = Inter_ManPerformInterpolation( pNew, pPars, &Depth ); } else if ( pParSec->fInterSeparate ) { Abc_Cex_t * pCex = NULL; Aig_Man_t * pTemp, * pAux; Aig_Obj_t * pObjPo; int i, Counter = 0; Saig_ManForEachPo( pNew, pObjPo, i ) { if ( Aig_ObjFanin0(pObjPo) == Aig_ManConst1(pNew) ) continue; if ( pPars->fVerbose ) printf( "Solving output %2d (out of %2d):\n", i, Saig_ManPoNum(pNew) ); pTemp = Aig_ManDupOneOutput( pNew, i, 1 ); pTemp = Aig_ManScl( pAux = pTemp, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pAux ); if ( Saig_ManRegNum(pTemp) > 0 ) { RetValue = Inter_ManPerformInterpolation( pTemp, pPars, &Depth ); if ( pTemp->pSeqModel ) { pCex = p->pSeqModel = Abc_CexDup( pTemp->pSeqModel, Aig_ManRegNum(p) ); pCex->iPo = i; Aig_ManStop( pTemp ); break; } // if solved, remove the output if ( RetValue == 1 ) { Aig_ObjPatchFanin0( pNew, pObjPo, Aig_ManConst0(pNew) ); // printf( "Output %3d : Solved ", i ); } else { Counter++; // printf( "Output %3d : Undec ", i ); } } else Counter++; // Aig_ManPrintStats( pTemp ); Aig_ManStop( pTemp ); printf( "Solving output %3d (out of %3d) using interpolation.\r", i, Saig_ManPoNum(pNew) ); } Aig_ManCleanup( pNew ); if ( pCex == NULL ) { printf( "Interpolation left %d (out of %d) outputs unsolved \n", Counter, Saig_ManPoNum(pNew) ); if ( Counter ) RetValue = -1; } pNew = Aig_ManDupUnsolvedOutputs( pTemp = pNew, 1 ); Aig_ManStop( pTemp ); pNew = Aig_ManScl( pTemp = pNew, 1, 1, 0, -1, -1, 0, 0 ); Aig_ManStop( pTemp ); }