blob: 5def7dae2451c9b434b55945efbc62a6a0cccc8f [file] [log] [blame]
/**CFile****************************************************************
FileName [simSupp.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Simulation to determine functional support.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: simSupp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "proof/fraig/fraig.h"
#include "sim.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Sim_ComputeSuppRound( Sim_Man_t * p, int fUseTargets );
static int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, int fUseTargets );
static void Sim_ComputeSuppSetTargets( Sim_Man_t * p );
static void Sim_UtilAssignRandom( Sim_Man_t * p );
static void Sim_UtilAssignFromFifo( Sim_Man_t * p );
static void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int nCounters );
static int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Computes structural supports.]
Description [Supports are returned as an array of bit strings, one
for each CO.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Sim_ComputeStrSupp( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vSuppStr;
Abc_Obj_t * pNode;
unsigned * pSimmNode, * pSimmNode1, * pSimmNode2;
int nSuppWords, i, k;
// allocate room for structural supports
nSuppWords = SIM_NUM_WORDS( Abc_NtkCiNum(pNtk) );
vSuppStr = Sim_UtilInfoAlloc( Abc_NtkObjNumMax(pNtk), nSuppWords, 1 );
// assign the structural support to the PIs
Abc_NtkForEachCi( pNtk, pNode, i )
Sim_SuppStrSetVar( vSuppStr, pNode, i );
// derive the structural supports of the internal nodes
Abc_NtkForEachNode( pNtk, pNode, i )
{
// if ( Abc_NodeIsConst(pNode) )
// continue;
pSimmNode = (unsigned *)vSuppStr->pArray[ pNode->Id ];
pSimmNode1 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ];
pSimmNode2 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId1(pNode) ];
for ( k = 0; k < nSuppWords; k++ )
pSimmNode[k] = pSimmNode1[k] | pSimmNode2[k];
}
// set the structural supports of the PO nodes
Abc_NtkForEachCo( pNtk, pNode, i )
{
pSimmNode = (unsigned *)vSuppStr->pArray[ pNode->Id ];
pSimmNode1 = (unsigned *)vSuppStr->pArray[ Abc_ObjFaninId0(pNode) ];
for ( k = 0; k < nSuppWords; k++ )
pSimmNode[k] = pSimmNode1[k];
}
return vSuppStr;
}
/**Function*************************************************************
Synopsis [Compute functional supports.]
Description [Supports are returned as an array of bit strings, one
for each CO.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Sim_ComputeFunSupp( Abc_Ntk_t * pNtk, int fVerbose )
{
Sim_Man_t * p;
Vec_Ptr_t * vResult;
int nSolved, i;
abctime clk = Abc_Clock();
srand( 0xABC );
// start the simulation manager
p = Sim_ManStart( pNtk, 0 );
// compute functional support using one round of random simulation
Sim_UtilAssignRandom( p );
Sim_ComputeSuppRound( p, 0 );
// set the support targets
Sim_ComputeSuppSetTargets( p );
if ( fVerbose )
printf( "Number of support targets after simulation = %5d.\n", Vec_VecSizeSize(p->vSuppTargs) );
if ( Vec_VecSizeSize(p->vSuppTargs) == 0 )
goto exit;
for ( i = 0; i < 1; i++ )
{
// compute patterns using one round of random simulation
Sim_UtilAssignRandom( p );
nSolved = Sim_ComputeSuppRound( p, 1 );
if ( Vec_VecSizeSize(p->vSuppTargs) == 0 )
goto exit;
if ( fVerbose )
printf( "Targets = %5d. Solved = %5d. Fifo = %5d.\n",
Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo) );
}
// try to solve the support targets
while ( Vec_VecSizeSize(p->vSuppTargs) > 0 )
{
// solve targets until the first disproved one (which gives counter-example)
Sim_SolveTargetsUsingSat( p, p->nSimWords/p->nSuppWords );
// compute additional functional support
Sim_UtilAssignFromFifo( p );
nSolved = Sim_ComputeSuppRound( p, 1 );
if ( fVerbose )
printf( "Targets = %5d. Solved = %5d. Fifo = %5d. SAT runs = %3d.\n",
Vec_VecSizeSize(p->vSuppTargs), nSolved, Vec_PtrSize(p->vFifo), p->nSatRuns );
}
exit:
p->timeTotal = Abc_Clock() - clk;
vResult = p->vSuppFun;
// p->vSuppFun = NULL;
Sim_ManStop( p );
return vResult;
}
/**Function*************************************************************
Synopsis [Computes functional support using one round of simulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Sim_ComputeSuppRound( Sim_Man_t * p, int fUseTargets )
{
Vec_Ptr_t * vTargets;
int i, Counter = 0;
abctime clk;
// perform one round of random simulation
clk = Abc_Clock();
Sim_UtilSimulate( p, 0 );
p->timeSim += Abc_Clock() - clk;
// iterate through the CIs and detect COs that depend on them
for ( i = p->iInput; i < p->nInputs; i++ )
{
vTargets = (Vec_Ptr_t *)p->vSuppTargs->pArray[i];
if ( fUseTargets && vTargets->nSize == 0 )
continue;
Counter += Sim_ComputeSuppRoundNode( p, i, fUseTargets );
}
return Counter;
}
/**Function*************************************************************
Synopsis [Computes functional support for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, int fUseTargets )
{
int fVerbose = 0;
Sim_Pat_t * pPat;
Vec_Ptr_t * vTargets;
Vec_Vec_t * vNodesByLevel;
Abc_Obj_t * pNodeCi, * pNode;
int i, k, v, Output, LuckyPat, fType0, fType1;
int Counter = 0;
int fFirst = 1;
abctime clk;
// collect nodes by level in the TFO of the CI
// this procedure does not collect the CIs and COs
// but it increments TravId of the collected nodes and CIs/COs
clk = Abc_Clock();
pNodeCi = Abc_NtkCi( p->pNtk, iNumCi );
vNodesByLevel = Abc_DfsLevelized( pNodeCi, 0 );
p->timeTrav += Abc_Clock() - clk;
// complement the simulation info of the selected CI
Sim_UtilInfoFlip( p, pNodeCi );
// simulate the levelized structure of nodes
Vec_VecForEachEntry( Abc_Obj_t *, vNodesByLevel, pNode, i, k )
{
fType0 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin0(pNode) );
fType1 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin1(pNode) );
clk = Abc_Clock();
Sim_UtilSimulateNode( p, pNode, 1, fType0, fType1 );
p->timeSim += Abc_Clock() - clk;
}
// set the simulation info of the affected COs
if ( fUseTargets )
{
vTargets = (Vec_Ptr_t *)p->vSuppTargs->pArray[iNumCi];
for ( i = vTargets->nSize - 1; i >= 0; i-- )
{
// get the target output
Output = (int)(ABC_PTRUINT_T)vTargets->pArray[i];
// get the target node
pNode = Abc_ObjFanin0( Abc_NtkCo(p->pNtk, Output) );
// the output should be in the cone
assert( Abc_NodeIsTravIdCurrent(pNode) );
// skip if the simulation info is equal
if ( Sim_UtilInfoCompare( p, pNode ) )
continue;
// otherwise, we solved a new target
Vec_PtrRemove( vTargets, vTargets->pArray[i] );
if ( fVerbose )
printf( "(%d,%d) ", iNumCi, Output );
Counter++;
// make sure this variable is not yet detected
assert( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) );
// set this variable
Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi );
// detect the differences in the simulation info
Sim_UtilInfoDetectDiffs( (unsigned *)p->vSim0->pArray[pNode->Id], (unsigned *)p->vSim1->pArray[pNode->Id], p->nSimWords, p->vDiffs );
// create new patterns
if ( !fFirst && p->vFifo->nSize > 1000 )
continue;
Vec_IntForEachEntry( p->vDiffs, LuckyPat, k )
{
// set the new pattern
pPat = Sim_ManPatAlloc( p );
pPat->Input = iNumCi;
pPat->Output = Output;
Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
if ( Sim_SimInfoHasVar( p->vSim0, pNodeCi, LuckyPat ) )
Sim_SetBit( pPat->pData, v );
Vec_PtrPush( p->vFifo, pPat );
fFirst = 0;
break;
}
}
if ( fVerbose && Counter )
printf( "\n" );
}
else
{
Abc_NtkForEachCo( p->pNtk, pNode, Output )
{
if ( !Abc_NodeIsTravIdCurrent( pNode ) )
continue;
if ( !Sim_UtilInfoCompare( p, Abc_ObjFanin0(pNode) ) )
{
if ( !Sim_SuppFunHasVar(p->vSuppFun, Output, iNumCi) )
{
Counter++;
Sim_SuppFunSetVar( p->vSuppFun, Output, iNumCi );
}
}
}
}
Vec_VecFree( vNodesByLevel );
return Counter;
}
/**Function*************************************************************
Synopsis [Sets the simulation targets.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sim_ComputeSuppSetTargets( Sim_Man_t * p )
{
Abc_Obj_t * pNode;
unsigned * pSuppStr, * pSuppFun;
int i, k, Num;
Abc_NtkForEachCo( p->pNtk, pNode, i )
{
pSuppStr = (unsigned *)p->vSuppStr->pArray[pNode->Id];
pSuppFun = (unsigned *)p->vSuppFun->pArray[i];
// find vars in the structural support that are not in the functional support
Sim_UtilInfoDetectNews( pSuppFun, pSuppStr, p->nSuppWords, p->vDiffs );
Vec_IntForEachEntry( p->vDiffs, Num, k )
Vec_VecPush( p->vSuppTargs, Num, (void *)(ABC_PTRUINT_T)i );
}
}
/**Function*************************************************************
Synopsis [Assigns random simulation info to the PIs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sim_UtilAssignRandom( Sim_Man_t * p )
{
Abc_Obj_t * pNode;
unsigned * pSimInfo;
int i, k;
// assign the random/systematic simulation info to the PIs
Abc_NtkForEachCi( p->pNtk, pNode, i )
{
pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id];
for ( k = 0; k < p->nSimWords; k++ )
pSimInfo[k] = SIM_RANDOM_UNSIGNED;
}
}
/**Function*************************************************************
Synopsis [Sets the new patterns from fifo.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sim_UtilAssignFromFifo( Sim_Man_t * p )
{
int fUseOneWord = 0;
Abc_Obj_t * pNode;
Sim_Pat_t * pPat;
unsigned * pSimInfo;
int nWordsNew, iWord, iWordLim, i, w;
int iBeg, iEnd;
int Counter = 0;
// go through the patterns and fill in the dist-1 minterms for each
for ( iWord = 0; p->vFifo->nSize > 0; iWord = iWordLim )
{
++Counter;
// get the pattern
pPat = (Sim_Pat_t *)Vec_PtrPop( p->vFifo );
if ( fUseOneWord )
{
// get the first word of the next series
iWordLim = iWord + 1;
// set the pattern for all PIs from iBit to iWord + p->nInputs
iBeg = p->iInput;
iEnd = Abc_MinInt( iBeg + 32, p->nInputs );
// for ( i = iBeg; i < iEnd; i++ )
Abc_NtkForEachCi( p->pNtk, pNode, i )
{
pNode = Abc_NtkCi(p->pNtk,i);
pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id];
if ( Sim_HasBit(pPat->pData, i) )
pSimInfo[iWord] = SIM_MASK_FULL;
else
pSimInfo[iWord] = 0;
// flip one bit
if ( i >= iBeg && i < iEnd )
Sim_XorBit( pSimInfo + iWord, i-iBeg );
}
}
else
{
// get the number of words for the remaining inputs
nWordsNew = p->nSuppWords;
// nWordsNew = SIM_NUM_WORDS( p->nInputs - p->iInput );
// get the first word of the next series
iWordLim = (iWord + nWordsNew < p->nSimWords)? iWord + nWordsNew : p->nSimWords;
// set the pattern for all CIs from iWord to iWord + nWordsNew
Abc_NtkForEachCi( p->pNtk, pNode, i )
{
pSimInfo = (unsigned *)p->vSim0->pArray[pNode->Id];
if ( Sim_HasBit(pPat->pData, i) )
{
for ( w = iWord; w < iWordLim; w++ )
pSimInfo[w] = SIM_MASK_FULL;
}
else
{
for ( w = iWord; w < iWordLim; w++ )
pSimInfo[w] = 0;
}
Sim_XorBit( pSimInfo + iWord, i );
// flip one bit
// if ( i >= p->iInput )
// Sim_XorBit( pSimInfo + iWord, i-p->iInput );
}
}
Sim_ManPatFree( p, pPat );
// stop if we ran out of room for patterns
if ( iWordLim == p->nSimWords )
break;
// if ( Counter == 1 )
// break;
}
}
/**Function*************************************************************
Synopsis [Get the given number of counter-examples using SAT.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Sim_SolveTargetsUsingSat( Sim_Man_t * p, int Limit )
{
Fraig_Params_t Params;
Fraig_Man_t * pMan;
Abc_Obj_t * pNodeCi;
Abc_Ntk_t * pMiter;
Sim_Pat_t * pPat;
void * pEntry;
int * pModel;
int RetValue, Output, Input, k, v;
int Counter = 0;
abctime clk;
p->nSatRuns = 0;
// put targets into one array
Vec_VecForEachEntryReverse( void *, p->vSuppTargs, pEntry, Input, k )
{
p->nSatRuns++;
Output = (int)(ABC_PTRUINT_T)pEntry;
// set up the miter for the two cofactors of this output w.r.t. this input
pMiter = Abc_NtkMiterForCofactors( p->pNtk, Output, Input, -1 );
// transform the miter into a fraig
Fraig_ParamsSetDefault( &Params );
Params.nSeconds = ABC_INFINITY;
Params.fInternal = 1;
clk = Abc_Clock();
pMan = (Fraig_Man_t *)Abc_NtkToFraig( pMiter, &Params, 0, 0 );
p->timeFraig += Abc_Clock() - clk;
clk = Abc_Clock();
Fraig_ManProveMiter( pMan );
p->timeSat += Abc_Clock() - clk;
// analyze the result
RetValue = Fraig_ManCheckMiter( pMan );
assert( RetValue >= 0 );
if ( RetValue == 1 ) // unsat
{
p->nSatRunsUnsat++;
pModel = NULL;
Vec_PtrRemove( (Vec_Ptr_t *)p->vSuppTargs->pArray[Input], pEntry );
}
else // sat
{
p->nSatRunsSat++;
pModel = Fraig_ManReadModel( pMan );
assert( pModel != NULL );
assert( Sim_SolveSuppModelVerify( p->pNtk, pModel, Input, Output ) );
//printf( "Solved by SAT (%d,%d).\n", Input, Output );
// set the new pattern
pPat = Sim_ManPatAlloc( p );
pPat->Input = Input;
pPat->Output = Output;
Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
if ( pModel[v] )
Sim_SetBit( pPat->pData, v );
Vec_PtrPush( p->vFifo, pPat );
/*
// set the new pattern
pPat = Sim_ManPatAlloc( p );
pPat->Input = Input;
pPat->Output = Output;
Abc_NtkForEachCi( p->pNtk, pNodeCi, v )
if ( pModel[v] )
Sim_SetBit( pPat->pData, v );
Sim_XorBit( pPat->pData, Input ); // add this bit in the opposite polarity
Vec_PtrPush( p->vFifo, pPat );
*/
Counter++;
}
// delete the fraig manager
Fraig_ManFree( pMan );
// delete the miter
Abc_NtkDelete( pMiter );
// makr the input, which we are processing
p->iInput = Input;
// stop when we found enough patterns
// if ( Counter == Limit )
if ( Counter == 1 )
return;
}
}
/**Function*************************************************************
Synopsis [Saves the counter example.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Sim_NtkSimTwoPats_rec( Abc_Obj_t * pNode )
{
int Value0, Value1;
if ( Abc_NodeIsTravIdCurrent( pNode ) )
return (int)(ABC_PTRUINT_T)pNode->pCopy;
Abc_NodeSetTravIdCurrent( pNode );
Value0 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin0(pNode) );
Value1 = Sim_NtkSimTwoPats_rec( Abc_ObjFanin1(pNode) );
if ( Abc_ObjFaninC0(pNode) )
Value0 = ~Value0;
if ( Abc_ObjFaninC1(pNode) )
Value1 = ~Value1;
pNode->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(Value0 & Value1);
return Value0 & Value1;
}
/**Function*************************************************************
Synopsis [Verifies that pModel proves the presence of Input in the support of Output.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Sim_SolveSuppModelVerify( Abc_Ntk_t * pNtk, int * pModel, int Input, int Output )
{
Abc_Obj_t * pNode;
int RetValue, i;
// set the PI values
Abc_NtkIncrementTravId( pNtk );
Abc_NtkForEachCi( pNtk, pNode, i )
{
Abc_NodeSetTravIdCurrent( pNode );
if ( pNode == Abc_NtkCi(pNtk,Input) )
pNode->pCopy = (Abc_Obj_t *)1;
else if ( pModel[i] == 1 )
pNode->pCopy = (Abc_Obj_t *)3;
else
pNode->pCopy = NULL;
}
// perform the traversal
RetValue = 3 & Sim_NtkSimTwoPats_rec( Abc_ObjFanin0( Abc_NtkCo(pNtk,Output) ) );
// assert( RetValue == 1 || RetValue == 2 );
return RetValue == 1 || RetValue == 2;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END