| /**CFile**************************************************************** |
| |
| FileName [resCore.c] |
| |
| SystemName [ABC: Logic synthesis and verification system.] |
| |
| PackageName [Resynthesis package.] |
| |
| Synopsis [Top-level resynthesis procedure.] |
| |
| Author [Alan Mishchenko] |
| |
| Affiliation [UC Berkeley] |
| |
| Date [Ver. 1.0. Started - January 15, 2007.] |
| |
| Revision [$Id: resCore.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $] |
| |
| ***********************************************************************/ |
| |
| #include "base/abc/abc.h" |
| #include "resInt.h" |
| #include "bool/kit/kit.h" |
| #include "sat/bsat/satStore.h" |
| |
| ABC_NAMESPACE_IMPL_START |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// DECLARATIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| typedef struct Res_Man_t_ Res_Man_t; |
| struct Res_Man_t_ |
| { |
| // general parameters |
| Res_Par_t * pPars; |
| // specialized manager |
| Res_Win_t * pWin; // windowing manager |
| Abc_Ntk_t * pAig; // the strashed window |
| Res_Sim_t * pSim; // simulation manager |
| Sto_Man_t * pCnf; // the CNF of the SAT problem |
| Int_Man_t * pMan; // interpolation manager; |
| Vec_Int_t * vMem; // memory for intermediate SOPs |
| Vec_Vec_t * vResubs; // resubstitution candidates of the AIG |
| Vec_Vec_t * vResubsW; // resubstitution candidates of the window |
| Vec_Vec_t * vLevels; // levelized structure for updating |
| // statistics |
| int nWins; // the number of windows tried |
| int nWinNodes; // the total number of window nodes |
| int nDivNodes; // the total number of divisors |
| int nWinsTriv; // the total number of trivial windows |
| int nWinsUsed; // the total number of useful windows (with at least one candidate) |
| int nConstsUsed; // the total number of constant nodes under ODC |
| int nCandSets; // the total number of candidates |
| int nProvedSets; // the total number of proved groups |
| int nSimEmpty; // the empty simulation info |
| int nTotalNets; // the total number of nets |
| int nTotalNodes; // the total number of nodess |
| int nTotalNets2; // the total number of nets |
| int nTotalNodes2; // the total number of nodess |
| // runtime |
| abctime timeWin; // windowing |
| abctime timeDiv; // divisors |
| abctime timeAig; // strashing |
| abctime timeSim; // simulation |
| abctime timeCand; // resubstitution candidates |
| abctime timeSatTotal; // SAT solving total |
| abctime timeSatSat; // SAT solving (sat calls) |
| abctime timeSatUnsat; // SAT solving (unsat calls) |
| abctime timeSatSim; // SAT solving (simulation) |
| abctime timeInt; // interpolation |
| abctime timeUpd; // updating |
| abctime timeTotal; // total runtime |
| }; |
| |
| extern Hop_Obj_t * Kit_GraphToHop( Hop_Man_t * pMan, Kit_Graph_t * pGraph ); |
| |
| extern abctime s_ResynTime; |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// FUNCTION DEFINITIONS /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| /**Function************************************************************* |
| |
| Synopsis [Allocate resynthesis manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| Res_Man_t * Res_ManAlloc( Res_Par_t * pPars ) |
| { |
| Res_Man_t * p; |
| p = ABC_ALLOC( Res_Man_t, 1 ); |
| memset( p, 0, sizeof(Res_Man_t) ); |
| assert( pPars->nWindow > 0 && pPars->nWindow < 100 ); |
| assert( pPars->nCands > 0 && pPars->nCands < 100 ); |
| p->pPars = pPars; |
| p->pWin = Res_WinAlloc(); |
| p->pSim = Res_SimAlloc( pPars->nSimWords ); |
| p->pMan = Int_ManAlloc(); |
| p->vMem = Vec_IntAlloc( 0 ); |
| p->vResubs = Vec_VecStart( pPars->nCands ); |
| p->vResubsW = Vec_VecStart( pPars->nCands ); |
| p->vLevels = Vec_VecStart( 32 ); |
| return p; |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Deallocate resynthesis manager.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Res_ManFree( Res_Man_t * p ) |
| { |
| if ( p->pPars->fVerbose ) |
| { |
| printf( "Reduction in nodes = %5d. (%.2f %%) ", |
| p->nTotalNodes-p->nTotalNodes2, |
| 100.0*(p->nTotalNodes-p->nTotalNodes2)/p->nTotalNodes ); |
| printf( "Reduction in edges = %5d. (%.2f %%) ", |
| p->nTotalNets-p->nTotalNets2, |
| 100.0*(p->nTotalNets-p->nTotalNets2)/p->nTotalNets ); |
| printf( "\n" ); |
| |
| printf( "Winds = %d. ", p->nWins ); |
| printf( "Nodes = %d. (Ave = %5.1f) ", p->nWinNodes, 1.0*p->nWinNodes/p->nWins ); |
| printf( "Divs = %d. (Ave = %5.1f) ", p->nDivNodes, 1.0*p->nDivNodes/p->nWins ); |
| printf( "\n" ); |
| printf( "WinsTriv = %d. ", p->nWinsTriv ); |
| printf( "SimsEmpt = %d. ", p->nSimEmpty ); |
| printf( "Const = %d. ", p->nConstsUsed ); |
| printf( "WindUsed = %d. ", p->nWinsUsed ); |
| printf( "Cands = %d. ", p->nCandSets ); |
| printf( "Proved = %d.", p->nProvedSets ); |
| printf( "\n" ); |
| |
| ABC_PRTP( "Windowing ", p->timeWin, p->timeTotal ); |
| ABC_PRTP( "Divisors ", p->timeDiv, p->timeTotal ); |
| ABC_PRTP( "Strashing ", p->timeAig, p->timeTotal ); |
| ABC_PRTP( "Simulation ", p->timeSim, p->timeTotal ); |
| ABC_PRTP( "Candidates ", p->timeCand, p->timeTotal ); |
| ABC_PRTP( "SAT solver ", p->timeSatTotal, p->timeTotal ); |
| ABC_PRTP( " sat ", p->timeSatSat, p->timeTotal ); |
| ABC_PRTP( " unsat ", p->timeSatUnsat, p->timeTotal ); |
| ABC_PRTP( " simul ", p->timeSatSim, p->timeTotal ); |
| ABC_PRTP( "Interpol ", p->timeInt, p->timeTotal ); |
| ABC_PRTP( "Undating ", p->timeUpd, p->timeTotal ); |
| ABC_PRTP( "TOTAL ", p->timeTotal, p->timeTotal ); |
| } |
| Res_WinFree( p->pWin ); |
| if ( p->pAig ) Abc_NtkDelete( p->pAig ); |
| Res_SimFree( p->pSim ); |
| if ( p->pCnf ) Sto_ManFree( p->pCnf ); |
| Int_ManFree( p->pMan ); |
| Vec_IntFree( p->vMem ); |
| Vec_VecFree( p->vResubs ); |
| Vec_VecFree( p->vResubsW ); |
| Vec_VecFree( p->vLevels ); |
| ABC_FREE( p ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Incrementally updates level of the nodes.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| void Res_UpdateNetwork( Abc_Obj_t * pObj, Vec_Ptr_t * vFanins, Hop_Obj_t * pFunc, Vec_Vec_t * vLevels ) |
| { |
| Abc_Obj_t * pObjNew, * pFanin; |
| int k; |
| |
| // create the new node |
| pObjNew = Abc_NtkCreateNode( pObj->pNtk ); |
| pObjNew->pData = pFunc; |
| Vec_PtrForEachEntry( Abc_Obj_t *, vFanins, pFanin, k ) |
| Abc_ObjAddFanin( pObjNew, pFanin ); |
| // replace the old node by the new node |
| //printf( "Replacing node " ); Abc_ObjPrint( stdout, pObj ); |
| //printf( "Inserting node " ); Abc_ObjPrint( stdout, pObjNew ); |
| // update the level of the node |
| Abc_NtkUpdate( pObj, pObjNew, vLevels ); |
| } |
| |
| /**Function************************************************************* |
| |
| Synopsis [Entrace into the resynthesis package.] |
| |
| Description [] |
| |
| SideEffects [] |
| |
| SeeAlso [] |
| |
| ***********************************************************************/ |
| int Abc_NtkResynthesize( Abc_Ntk_t * pNtk, Res_Par_t * pPars ) |
| { |
| ProgressBar * pProgress; |
| Res_Man_t * p; |
| Abc_Obj_t * pObj; |
| Hop_Obj_t * pFunc; |
| Kit_Graph_t * pGraph; |
| Vec_Ptr_t * vFanins; |
| unsigned * puTruth; |
| int i, k, RetValue, nNodesOld, nFanins, nFaninsMax; |
| abctime clk, clkTotal = Abc_Clock(); |
| |
| // start the manager |
| p = Res_ManAlloc( pPars ); |
| p->nTotalNets = Abc_NtkGetTotalFanins(pNtk); |
| p->nTotalNodes = Abc_NtkNodeNum(pNtk); |
| nFaninsMax = Abc_NtkGetFaninMax(pNtk); |
| if ( nFaninsMax > 8 ) |
| nFaninsMax = 8; |
| |
| // perform the network sweep |
| Abc_NtkSweep( pNtk, 0 ); |
| |
| // convert into the AIG |
| if ( !Abc_NtkToAig(pNtk) ) |
| { |
| fprintf( stdout, "Converting to BDD has failed.\n" ); |
| Res_ManFree( p ); |
| return 0; |
| } |
| assert( Abc_NtkHasAig(pNtk) ); |
| |
| // set the number of levels |
| Abc_NtkLevel( pNtk ); |
| Abc_NtkStartReverseLevels( pNtk, pPars->nGrowthLevel ); |
| |
| // try resynthesizing nodes in the topological order |
| nNodesOld = Abc_NtkObjNumMax(pNtk); |
| pProgress = Extra_ProgressBarStart( stdout, nNodesOld ); |
| Abc_NtkForEachObj( pNtk, pObj, i ) |
| { |
| Extra_ProgressBarUpdate( pProgress, i, NULL ); |
| if ( !Abc_ObjIsNode(pObj) ) |
| continue; |
| if ( Abc_ObjFaninNum(pObj) > 8 ) |
| continue; |
| if ( pObj->Id > nNodesOld ) |
| break; |
| |
| // create the window for this node |
| clk = Abc_Clock(); |
| RetValue = Res_WinCompute( pObj, p->pPars->nWindow/10, p->pPars->nWindow%10, p->pWin ); |
| p->timeWin += Abc_Clock() - clk; |
| if ( !RetValue ) |
| continue; |
| p->nWinsTriv += Res_WinIsTrivial( p->pWin ); |
| |
| if ( p->pPars->fVeryVerbose ) |
| { |
| printf( "%5d (lev=%2d) : ", pObj->Id, pObj->Level ); |
| printf( "Win = %3d/%3d/%4d/%3d ", |
| Vec_PtrSize(p->pWin->vLeaves), |
| Vec_PtrSize(p->pWin->vBranches), |
| Vec_PtrSize(p->pWin->vNodes), |
| Vec_PtrSize(p->pWin->vRoots) ); |
| } |
| |
| // collect the divisors |
| clk = Abc_Clock(); |
| Res_WinDivisors( p->pWin, Abc_ObjRequiredLevel(pObj) - 1 ); |
| p->timeDiv += Abc_Clock() - clk; |
| |
| p->nWins++; |
| p->nWinNodes += Vec_PtrSize(p->pWin->vNodes); |
| p->nDivNodes += Vec_PtrSize( p->pWin->vDivs); |
| |
| if ( p->pPars->fVeryVerbose ) |
| { |
| printf( "D = %3d ", Vec_PtrSize(p->pWin->vDivs) ); |
| printf( "D+ = %3d ", p->pWin->nDivsPlus ); |
| } |
| |
| // create the AIG for the window |
| clk = Abc_Clock(); |
| if ( p->pAig ) Abc_NtkDelete( p->pAig ); |
| p->pAig = Res_WndStrash( p->pWin ); |
| p->timeAig += Abc_Clock() - clk; |
| |
| if ( p->pPars->fVeryVerbose ) |
| { |
| printf( "AIG = %4d ", Abc_NtkNodeNum(p->pAig) ); |
| printf( "\n" ); |
| } |
| |
| // prepare simulation info |
| clk = Abc_Clock(); |
| RetValue = Res_SimPrepare( p->pSim, p->pAig, Vec_PtrSize(p->pWin->vLeaves), 0 ); //p->pPars->fVerbose ); |
| p->timeSim += Abc_Clock() - clk; |
| if ( !RetValue ) |
| { |
| p->nSimEmpty++; |
| continue; |
| } |
| |
| // consider the case of constant node |
| if ( p->pSim->fConst0 || p->pSim->fConst1 ) |
| { |
| p->nConstsUsed++; |
| |
| pFunc = p->pSim->fConst1? Hop_ManConst1((Hop_Man_t *)pNtk->pManFunc) : Hop_ManConst0((Hop_Man_t *)pNtk->pManFunc); |
| vFanins = Vec_VecEntry( p->vResubsW, 0 ); |
| Vec_PtrClear( vFanins ); |
| Res_UpdateNetwork( pObj, vFanins, pFunc, p->vLevels ); |
| continue; |
| } |
| |
| // printf( " " ); |
| |
| // find resub candidates for the node |
| clk = Abc_Clock(); |
| if ( p->pPars->fArea ) |
| RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 1 ); |
| else |
| RetValue = Res_FilterCandidates( p->pWin, p->pAig, p->pSim, p->vResubs, p->vResubsW, nFaninsMax, 0 ); |
| p->timeCand += Abc_Clock() - clk; |
| p->nCandSets += RetValue; |
| if ( RetValue == 0 ) |
| continue; |
| |
| // printf( "%d(%d) ", Vec_PtrSize(p->pWin->vDivs), RetValue ); |
| |
| p->nWinsUsed++; |
| |
| // iterate through candidate resubstitutions |
| Vec_VecForEachLevel( p->vResubs, vFanins, k ) |
| { |
| if ( Vec_PtrSize(vFanins) == 0 ) |
| break; |
| |
| // solve the SAT problem and get clauses |
| clk = Abc_Clock(); |
| if ( p->pCnf ) Sto_ManFree( p->pCnf ); |
| p->pCnf = (Sto_Man_t *)Res_SatProveUnsat( p->pAig, vFanins ); |
| if ( p->pCnf == NULL ) |
| { |
| p->timeSatSat += Abc_Clock() - clk; |
| // printf( " Sat\n" ); |
| // printf( "-" ); |
| continue; |
| } |
| p->timeSatUnsat += Abc_Clock() - clk; |
| // printf( "+" ); |
| |
| p->nProvedSets++; |
| // printf( " Unsat\n" ); |
| // continue; |
| // printf( "Proved %d.\n", k ); |
| |
| // write it into a file |
| // Sto_ManDumpClauses( p->pCnf, "trace.cnf" ); |
| |
| // interpolate the problem if it was UNSAT |
| clk = Abc_Clock(); |
| nFanins = Int_ManInterpolate( p->pMan, p->pCnf, 0, &puTruth ); |
| p->timeInt += Abc_Clock() - clk; |
| if ( nFanins != Vec_PtrSize(vFanins) - 2 ) |
| continue; |
| assert( puTruth ); |
| // Extra_PrintBinary( stdout, puTruth, 1 << nFanins ); printf( "\n" ); |
| |
| // transform interpolant into the AIG |
| pGraph = Kit_TruthToGraph( puTruth, nFanins, p->vMem ); |
| |
| // derive the AIG for the decomposition tree |
| pFunc = Kit_GraphToHop( (Hop_Man_t *)pNtk->pManFunc, pGraph ); |
| Kit_GraphFree( pGraph ); |
| |
| // update the network |
| clk = Abc_Clock(); |
| Res_UpdateNetwork( pObj, Vec_VecEntry(p->vResubsW, k), pFunc, p->vLevels ); |
| p->timeUpd += Abc_Clock() - clk; |
| break; |
| } |
| // printf( "\n" ); |
| } |
| Extra_ProgressBarStop( pProgress ); |
| Abc_NtkStopReverseLevels( pNtk ); |
| |
| p->timeSatSim += p->pSim->timeSat; |
| p->timeSatTotal = p->timeSatSat + p->timeSatUnsat + p->timeSatSim; |
| |
| p->nTotalNets2 = Abc_NtkGetTotalFanins(pNtk); |
| p->nTotalNodes2 = Abc_NtkNodeNum(pNtk); |
| |
| // quit resubstitution manager |
| p->timeTotal = Abc_Clock() - clkTotal; |
| Res_ManFree( p ); |
| |
| s_ResynTime += Abc_Clock() - clkTotal; |
| // check the resulting network |
| if ( !Abc_NtkCheck( pNtk ) ) |
| { |
| fprintf( stdout, "Abc_NtkResynthesize(): Network check has failed.\n" ); |
| return 0; |
| } |
| return 1; |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| /// END OF FILE /// |
| //////////////////////////////////////////////////////////////////////// |
| |
| |
| ABC_NAMESPACE_IMPL_END |
| |