blob: d57cdea53352216925173169692d2061cd600aee [file] [log] [blame]
/**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