blob: d4088e7bb2f9061086d1caddee38e8449df5a84c [file] [log] [blame]
/**CFile****************************************************************
FileName [resSim.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resynthesis package.]
Synopsis [Simulation engine.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - January 15, 2007.]
Revision [$Id: resSim.c,v 1.00 2007/01/15 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "resInt.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocate simulation engine.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Res_Sim_t * Res_SimAlloc( int nWords )
{
Res_Sim_t * p;
p = ABC_ALLOC( Res_Sim_t, 1 );
memset( p, 0, sizeof(Res_Sim_t) );
// simulation parameters
p->nWords = nWords;
p->nPats = p->nWords * 8 * sizeof(unsigned);
p->nWordsIn = p->nPats;
p->nBytesIn = p->nPats * sizeof(unsigned);
p->nPatsIn = p->nPats * 8 * sizeof(unsigned);
p->nWordsOut = p->nPats * p->nWords;
p->nPatsOut = p->nPats * p->nPats;
// simulation info
p->vPats = Vec_PtrAllocSimInfo( 1024, p->nWordsIn );
p->vPats0 = Vec_PtrAllocSimInfo( 128, p->nWords );
p->vPats1 = Vec_PtrAllocSimInfo( 128, p->nWords );
p->vOuts = Vec_PtrAllocSimInfo( 128, p->nWordsOut );
// resub candidates
p->vCands = Vec_VecStart( 16 );
return p;
}
/**Function*************************************************************
Synopsis [Allocate simulation engine.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimAdjust( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis )
{
srand( 0xABC );
assert( Abc_NtkIsStrash(pAig) );
p->pAig = pAig;
p->nTruePis = nTruePis;
if ( Vec_PtrSize(p->vPats) < Abc_NtkObjNumMax(pAig)+1 )
{
Vec_PtrFree( p->vPats );
p->vPats = Vec_PtrAllocSimInfo( Abc_NtkObjNumMax(pAig)+1, p->nWordsIn );
}
if ( Vec_PtrSize(p->vPats0) < nTruePis )
{
Vec_PtrFree( p->vPats0 );
p->vPats0 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
}
if ( Vec_PtrSize(p->vPats1) < nTruePis )
{
Vec_PtrFree( p->vPats1 );
p->vPats1 = Vec_PtrAllocSimInfo( nTruePis, p->nWords );
}
if ( Vec_PtrSize(p->vOuts) < Abc_NtkPoNum(pAig) )
{
Vec_PtrFree( p->vOuts );
p->vOuts = Vec_PtrAllocSimInfo( Abc_NtkPoNum(pAig), p->nWordsOut );
}
// clean storage info for patterns
Abc_InfoClear( (unsigned *)Vec_PtrEntry(p->vPats0,0), p->nWords * nTruePis );
Abc_InfoClear( (unsigned *)Vec_PtrEntry(p->vPats1,0), p->nWords * nTruePis );
p->nPats0 = 0;
p->nPats1 = 0;
p->fConst0 = 0;
p->fConst1 = 0;
}
/**Function*************************************************************
Synopsis [Free simulation engine.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimFree( Res_Sim_t * p )
{
Vec_PtrFree( p->vPats );
Vec_PtrFree( p->vPats0 );
Vec_PtrFree( p->vPats1 );
Vec_PtrFree( p->vOuts );
Vec_VecFree( p->vCands );
ABC_FREE( p );
}
/**Function*************************************************************
Synopsis [Sets random PI simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_InfoRandomBytes( unsigned * p, int nWords )
{
int i, Num;
for ( i = nWords - 1; i >= 0; i-- )
{
Num = rand();
p[i] = (Num & 1)? 0xff : 0;
p[i] = (p[i] << 8) | ((Num & 2)? 0xff : 0);
p[i] = (p[i] << 8) | ((Num & 4)? 0xff : 0);
p[i] = (p[i] << 8) | ((Num & 8)? 0xff : 0);
}
// Extra_PrintBinary( stdout, p, 32 ); printf( "\n" );
}
/**Function*************************************************************
Synopsis [Sets random PI simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimSetRandomBytes( Res_Sim_t * p )
{
Abc_Obj_t * pObj;
unsigned * pInfo;
int i;
Abc_NtkForEachPi( p->pAig, pObj, i )
{
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
if ( i < p->nTruePis )
Abc_InfoRandomBytes( pInfo, p->nWordsIn );
else
Abc_InfoRandom( pInfo, p->nWordsIn );
}
/*
// double-check that all are byte-patterns
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfoC = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
for ( k = 0; k < p->nBytesIn; k++ )
assert( pInfoC[k] == 0 || pInfoC[k] == 0xff );
}
*/
}
/**Function*************************************************************
Synopsis [Sets random PI simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimSetDerivedBytes( Res_Sim_t * p, int fUseWalk )
{
Vec_Ptr_t * vPatsSource[2];
int nPatsSource[2];
Abc_Obj_t * pObj;
unsigned char * pInfo;
int i, k, z, s, nPats;
// set several random patterns
assert( p->nBytesIn % 32 == 0 );
nPats = p->nBytesIn/8;
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
Abc_InfoRandomBytes( (unsigned *)Vec_PtrEntry(p->vPats, pObj->Id), nPats/4 );
}
// set special patterns
if ( fUseWalk )
{
for ( z = 0; z < 2; z++ )
{
// set the zero pattern
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
pInfo[nPats] = z ? 0xff : 0;
}
if ( ++nPats == p->nBytesIn )
return;
// set the walking zero pattern
for ( k = 0; k < p->nTruePis; k++ )
{
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
pInfo[nPats] = ((i == k) ^ z) ? 0xff : 0;
}
if ( ++nPats == p->nBytesIn )
return;
}
}
}
// decide what patterns to set first
if ( p->nPats0 < p->nPats1 )
{
nPatsSource[0] = p->nPats0;
vPatsSource[0] = p->vPats0;
nPatsSource[1] = p->nPats1;
vPatsSource[1] = p->vPats1;
}
else
{
nPatsSource[0] = p->nPats1;
vPatsSource[0] = p->vPats1;
nPatsSource[1] = p->nPats0;
vPatsSource[1] = p->vPats0;
}
for ( z = 0; z < 2; z++ )
{
for ( s = nPatsSource[z] - 1; s >= 0; s-- )
{
// if ( s == 0 )
// printf( "Patterns:\n" );
// set the given source pattern
for ( k = 0; k < p->nTruePis; k++ )
{
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
if ( (i == k) ^ Abc_InfoHasBit( (unsigned *)Vec_PtrEntry(vPatsSource[z], i), s ) )
{
pInfo[nPats] = 0xff;
// if ( s == 0 )
// printf( "1" );
}
else
{
pInfo[nPats] = 0;
// if ( s == 0 )
// printf( "0" );
}
}
// if ( s == 0 )
// printf( "\n" );
if ( ++nPats == p->nBytesIn )
return;
}
}
}
// clean the rest
for ( z = nPats; z < p->nBytesIn; z++ )
{
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
memset( pInfo + nPats, 0, p->nBytesIn - nPats );
}
}
/*
// double-check that all are byte-patterns
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
for ( k = 0; k < p->nBytesIn; k++ )
assert( pInfo[k] == 0 || pInfo[k] == 0xff );
}
*/
}
/**Function*************************************************************
Synopsis [Sets given PI simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimSetGiven( Res_Sim_t * p, Vec_Ptr_t * vInfo )
{
Abc_Obj_t * pObj;
unsigned * pInfo, * pInfo2;
int i, w;
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
pInfo2 = (unsigned *)Vec_PtrEntry( vInfo, i );
for ( w = 0; w < p->nWords; w++ )
pInfo[w] = pInfo2[w];
}
}
/**Function*************************************************************
Synopsis [Simulates one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimPerformOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
{
unsigned * pInfo, * pInfo1, * pInfo2;
int k, fComp1, fComp2;
// simulate the internal nodes
assert( Abc_ObjIsNode(pNode) );
pInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
pInfo1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
pInfo2 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId1(pNode));
fComp1 = Abc_ObjFaninC0(pNode);
fComp2 = Abc_ObjFaninC1(pNode);
if ( fComp1 && fComp2 )
for ( k = 0; k < nSimWords; k++ )
pInfo[k] = ~pInfo1[k] & ~pInfo2[k];
else if ( fComp1 && !fComp2 )
for ( k = 0; k < nSimWords; k++ )
pInfo[k] = ~pInfo1[k] & pInfo2[k];
else if ( !fComp1 && fComp2 )
for ( k = 0; k < nSimWords; k++ )
pInfo[k] = pInfo1[k] & ~pInfo2[k];
else // if ( fComp1 && fComp2 )
for ( k = 0; k < nSimWords; k++ )
pInfo[k] = pInfo1[k] & pInfo2[k];
}
/**Function*************************************************************
Synopsis [Simulates one CO node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimTransferOne( Abc_Obj_t * pNode, Vec_Ptr_t * vSimInfo, int nSimWords )
{
unsigned * pInfo, * pInfo1;
int k, fComp1;
// simulate the internal nodes
assert( Abc_ObjIsCo(pNode) );
pInfo = (unsigned *)Vec_PtrEntry(vSimInfo, pNode->Id);
pInfo1 = (unsigned *)Vec_PtrEntry(vSimInfo, Abc_ObjFaninId0(pNode));
fComp1 = Abc_ObjFaninC0(pNode);
if ( fComp1 )
for ( k = 0; k < nSimWords; k++ )
pInfo[k] = ~pInfo1[k];
else
for ( k = 0; k < nSimWords; k++ )
pInfo[k] = pInfo1[k];
}
/**Function*************************************************************
Synopsis [Performs one round of simulation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimPerformRound( Res_Sim_t * p, int nWords )
{
Abc_Obj_t * pObj;
int i;
Abc_InfoFill( (unsigned *)Vec_PtrEntry(p->vPats,0), nWords );
Abc_AigForEachAnd( p->pAig, pObj, i )
Res_SimPerformOne( pObj, p->vPats, nWords );
Abc_NtkForEachPo( p->pAig, pObj, i )
Res_SimTransferOne( pObj, p->vPats, nWords );
}
/**Function*************************************************************
Synopsis [Pads the extra space with duplicated simulation info.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimPadSimInfo( Vec_Ptr_t * vPats, int nPats, int nWords )
{
unsigned * pInfo;
int i, w, iWords;
assert( nPats > 0 && nPats < nWords * 8 * (int) sizeof(unsigned) );
// pad the first word
if ( nPats < 8 * sizeof(unsigned) )
{
Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i )
if ( pInfo[0] & 1 )
pInfo[0] |= ((~0) << nPats);
nPats = 8 * sizeof(unsigned);
}
// pad the empty words
iWords = nPats / (8 * sizeof(unsigned));
Vec_PtrForEachEntry( unsigned *, vPats, pInfo, i )
{
for ( w = iWords; w < nWords; w++ )
pInfo[w] = pInfo[0];
}
}
/**Function*************************************************************
Synopsis [Duplicates the simulation info to fill the space.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimDeriveInfoReplicate( Res_Sim_t * p )
{
unsigned * pInfo, * pInfo2;
Abc_Obj_t * pObj;
int i, j, w;
Abc_NtkForEachPo( p->pAig, pObj, i )
{
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i );
for ( j = 0; j < p->nPats; j++ )
for ( w = 0; w < p->nWords; w++ )
*pInfo2++ = pInfo[w];
}
}
/**Function*************************************************************
Synopsis [Complement the simulation info if necessary.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimDeriveInfoComplement( Res_Sim_t * p )
{
unsigned * pInfo, * pInfo2;
Abc_Obj_t * pObj;
int i, j, w;
Abc_NtkForEachPo( p->pAig, pObj, i )
{
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i );
for ( j = 0; j < p->nPats; j++, pInfo2 += p->nWords )
if ( Abc_InfoHasBit( pInfo, j ) )
for ( w = 0; w < p->nWords; w++ )
pInfo2[w] = ~pInfo2[w];
}
}
/**Function*************************************************************
Synopsis [Prints output patterns.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimPrintOutPatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
{
Abc_Obj_t * pObj;
unsigned * pInfo2;
int i;
Abc_NtkForEachPo( pAig, pObj, i )
{
pInfo2 = (unsigned *)Vec_PtrEntry( p->vOuts, i );
Extra_PrintBinary( stdout, pInfo2, p->nPatsOut );
printf( "\n" );
}
}
/**Function*************************************************************
Synopsis [Prints output patterns.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimPrintNodePatterns( Res_Sim_t * p, Abc_Ntk_t * pAig )
{
unsigned * pInfo;
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
Extra_PrintBinary( stdout, pInfo, p->nPats );
printf( "\n" );
}
/**Function*************************************************************
Synopsis [Counts the number of patters of different type.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimCountResults( Res_Sim_t * p, int * pnDcs, int * pnOnes, int * pnZeros, int fVerbose )
{
unsigned char * pInfoCare, * pInfoNode;
int i, nTotal = 0;
pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
for ( i = 0; i < p->nBytesIn; i++ )
{
if ( !pInfoCare[i] )
(*pnDcs)++;
else if ( !pInfoNode[i] )
(*pnZeros)++;
else
(*pnOnes)++;
}
nTotal += *pnDcs;
nTotal += *pnZeros;
nTotal += *pnOnes;
if ( fVerbose )
{
printf( "Dc = %7.2f %% ", 100.0*(*pnDcs) /nTotal );
printf( "On = %7.2f %% ", 100.0*(*pnOnes) /nTotal );
printf( "Off = %7.2f %% ", 100.0*(*pnZeros)/nTotal );
}
}
/**Function*************************************************************
Synopsis [Counts the number of patters of different type.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Res_SimCollectPatterns( Res_Sim_t * p, int fVerbose )
{
Abc_Obj_t * pObj;
unsigned char * pInfoCare, * pInfoNode, * pInfo;
int i, j;
pInfoCare = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 0)->Id );
pInfoNode = (unsigned char *)Vec_PtrEntry( p->vPats, Abc_NtkPo(p->pAig, 1)->Id );
for ( i = 0; i < p->nBytesIn; i++ )
{
// skip don't-care patterns
if ( !pInfoCare[i] )
continue;
// separate offset and onset patterns
assert( pInfoNode[i] == 0 || pInfoNode[i] == 0xff );
if ( !pInfoNode[i] )
{
if ( p->nPats0 >= p->nPats )
continue;
Abc_NtkForEachPi( p->pAig, pObj, j )
{
if ( j == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
assert( pInfo[i] == 0 || pInfo[i] == 0xff );
if ( pInfo[i] )
Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPats0, j), p->nPats0 );
}
p->nPats0++;
}
else
{
if ( p->nPats1 >= p->nPats )
continue;
Abc_NtkForEachPi( p->pAig, pObj, j )
{
if ( j == p->nTruePis )
break;
pInfo = (unsigned char *)Vec_PtrEntry( p->vPats, pObj->Id );
assert( pInfo[i] == 0 || pInfo[i] == 0xff );
if ( pInfo[i] )
Abc_InfoSetBit( (unsigned *)Vec_PtrEntry(p->vPats1, j), p->nPats1 );
}
p->nPats1++;
}
if ( p->nPats0 >= p->nPats && p->nPats1 >= p->nPats )
break;
}
if ( fVerbose )
{
printf( "| " );
printf( "On = %3d ", p->nPats1 );
printf( "Off = %3d ", p->nPats0 );
printf( "\n" );
}
}
/**Function*************************************************************
Synopsis [Verifies the last pattern.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_SimVerifyValue( Res_Sim_t * p, int fOnSet )
{
Abc_Obj_t * pObj;
unsigned * pInfo, * pInfo2;
int i, value;
Abc_NtkForEachPi( p->pAig, pObj, i )
{
if ( i == p->nTruePis )
break;
if ( fOnSet )
{
pInfo2 = (unsigned *)Vec_PtrEntry( p->vPats1, i );
value = Abc_InfoHasBit( pInfo2, p->nPats1 - 1 );
}
else
{
pInfo2 = (unsigned *)Vec_PtrEntry( p->vPats0, i );
value = Abc_InfoHasBit( pInfo2, p->nPats0 - 1 );
}
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
pInfo[0] = value ? ~0 : 0;
}
Res_SimPerformRound( p, 1 );
pObj = Abc_NtkPo( p->pAig, 1 );
pInfo = (unsigned *)Vec_PtrEntry( p->vPats, pObj->Id );
assert( pInfo[0] == 0 || pInfo[0] == ~0 );
return pInfo[0] > 0;
}
/**Function*************************************************************
Synopsis [Prepares simulation info for candidate filtering.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Res_SimPrepare( Res_Sim_t * p, Abc_Ntk_t * pAig, int nTruePis, int fVerbose )
{
int i, nOnes = 0, nZeros = 0, nDcs = 0;
if ( fVerbose )
printf( "\n" );
// prepare the manager
Res_SimAdjust( p, pAig, nTruePis );
// estimate the number of patterns
Res_SimSetRandomBytes( p );
Res_SimPerformRound( p, p->nWordsIn );
Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
// collect the patterns
Res_SimCollectPatterns( p, fVerbose );
// add more patterns using constraint simulation
if ( p->nPats0 < 8 )
{
if ( !Res_SatSimulate( p, 16, 0 ) )
return p->fConst0 || p->fConst1;
// return 0;
// printf( "Value0 = %d\n", Res_SimVerifyValue( p, 0 ) );
}
if ( p->nPats1 < 8 )
{
if ( !Res_SatSimulate( p, 16, 1 ) )
return p->fConst0 || p->fConst1;
// return 0;
// printf( "Value1 = %d\n", Res_SimVerifyValue( p, 1 ) );
}
// generate additional patterns
for ( i = 0; i < 2; i++ )
{
if ( p->nPats0 > p->nPats*7/8 && p->nPats1 > p->nPats*7/8 )
break;
Res_SimSetDerivedBytes( p, i==0 );
Res_SimPerformRound( p, p->nWordsIn );
Res_SimCountResults( p, &nDcs, &nOnes, &nZeros, fVerbose );
Res_SimCollectPatterns( p, fVerbose );
}
// create bit-matrix info
if ( p->nPats0 < p->nPats )
Res_SimPadSimInfo( p->vPats0, p->nPats0, p->nWords );
if ( p->nPats1 < p->nPats )
Res_SimPadSimInfo( p->vPats1, p->nPats1, p->nWords );
// resimulate 0-patterns
Res_SimSetGiven( p, p->vPats0 );
Res_SimPerformRound( p, p->nWords );
//Res_SimPrintNodePatterns( p, pAig );
Res_SimDeriveInfoReplicate( p );
// resimulate 1-patterns
Res_SimSetGiven( p, p->vPats1 );
Res_SimPerformRound( p, p->nWords );
//Res_SimPrintNodePatterns( p, pAig );
Res_SimDeriveInfoComplement( p );
// print output patterns
// Res_SimPrintOutPatterns( p, pAig );
return 1;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END