2010-11-01 09:35:04 +01:00
|
|
|
/**CFile****************************************************************
|
|
|
|
|
|
|
|
|
|
FileName [cecSynth.c]
|
|
|
|
|
|
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
|
|
|
|
|
|
PackageName [Combinational equivalence checking.]
|
|
|
|
|
|
|
|
|
|
Synopsis [Partitioned sequential synthesis.]
|
|
|
|
|
|
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
|
|
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
|
|
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
|
|
|
|
|
|
Revision [$Id: cecSynth.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "cecInt.h"
|
2012-07-08 05:14:12 +02:00
|
|
|
#include "aig/gia/giaAig.h"
|
2010-11-01 09:35:04 +01:00
|
|
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_START
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// DECLARATIONS ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// FUNCTION DEFINITIONS ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Populate sequential synthesis parameters.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
void Cec_SeqSynthesisSetDefaultParams( Cec_ParSeq_t * p )
|
|
|
|
|
{
|
|
|
|
|
memset( p, 0, sizeof(Cec_ParSeq_t) );
|
|
|
|
|
p->fUseLcorr = 0; // enables latch correspondence
|
|
|
|
|
p->fUseScorr = 0; // enables signal correspondence
|
|
|
|
|
p->nBTLimit = 1000; // (scorr/lcorr) conflict limit at a node
|
|
|
|
|
p->nFrames = 1; // (scorr only) the number of timeframes
|
|
|
|
|
p->nLevelMax = -1; // (scorr only) the max number of levels
|
|
|
|
|
p->fConsts = 1; // (scl only) merging constants
|
|
|
|
|
p->fEquivs = 1; // (scl only) merging equivalences
|
|
|
|
|
p->fUseMiniSat = 0; // enables MiniSat in lcorr/scorr
|
|
|
|
|
p->nMinDomSize = 100; // the size of minimum clock domain
|
|
|
|
|
p->fVeryVerbose = 0; // verbose stats
|
|
|
|
|
p->fVerbose = 0; // verbose stats
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis []
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Cec_SeqReadMinDomSize( Cec_ParSeq_t * p )
|
|
|
|
|
{
|
|
|
|
|
return p->nMinDomSize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis []
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Cec_SeqReadVerbose( Cec_ParSeq_t * p )
|
|
|
|
|
{
|
|
|
|
|
return p->fVerbose;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Computes partitioning of registers.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
Gia_Man_t * Gia_ManRegCreatePart( Gia_Man_t * p, Vec_Int_t * vPart, int * pnCountPis, int * pnCountRegs, int ** ppMapBack )
|
|
|
|
|
{
|
|
|
|
|
Gia_Man_t * pNew;
|
|
|
|
|
Gia_Obj_t * pObj;
|
|
|
|
|
Vec_Int_t * vNodes, * vRoots;
|
|
|
|
|
int i, iOut, nCountPis, nCountRegs;
|
|
|
|
|
int * pMapBack;
|
|
|
|
|
// collect/mark nodes/PIs in the DFS order from the roots
|
|
|
|
|
Gia_ManIncrementTravId( p );
|
|
|
|
|
vRoots = Vec_IntAlloc( Vec_IntSize(vPart) );
|
|
|
|
|
Vec_IntForEachEntry( vPart, iOut, i )
|
|
|
|
|
Vec_IntPush( vRoots, Gia_ObjId(p, Gia_ManCo(p, Gia_ManPoNum(p)+iOut)) );
|
|
|
|
|
vNodes = Gia_ManCollectNodesCis( p, Vec_IntArray(vRoots), Vec_IntSize(vRoots) );
|
|
|
|
|
Vec_IntFree( vRoots );
|
|
|
|
|
// unmark register outputs
|
|
|
|
|
Vec_IntForEachEntry( vPart, iOut, i )
|
|
|
|
|
Gia_ObjSetTravIdPrevious( p, Gia_ManCi(p, Gia_ManPiNum(p)+iOut) );
|
|
|
|
|
// count pure PIs
|
|
|
|
|
nCountPis = nCountRegs = 0;
|
|
|
|
|
Gia_ManForEachPi( p, pObj, i )
|
|
|
|
|
nCountPis += Gia_ObjIsTravIdCurrent(p, pObj);
|
|
|
|
|
// count outputs of other registers
|
|
|
|
|
Gia_ManForEachRo( p, pObj, i )
|
|
|
|
|
nCountRegs += Gia_ObjIsTravIdCurrent(p, pObj); // should be !Gia_... ???
|
|
|
|
|
if ( pnCountPis )
|
|
|
|
|
*pnCountPis = nCountPis;
|
|
|
|
|
if ( pnCountRegs )
|
|
|
|
|
*pnCountRegs = nCountRegs;
|
|
|
|
|
// clean old manager
|
|
|
|
|
Gia_ManFillValue(p);
|
|
|
|
|
Gia_ManConst0(p)->Value = 0;
|
|
|
|
|
// create the new manager
|
|
|
|
|
pNew = Gia_ManStart( Vec_IntSize(vNodes) );
|
|
|
|
|
// create the PIs
|
|
|
|
|
Gia_ManForEachCi( p, pObj, i )
|
|
|
|
|
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
|
|
|
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
|
|
|
// add variables for the register outputs
|
|
|
|
|
// create fake POs to hold the register outputs
|
|
|
|
|
Vec_IntForEachEntry( vPart, iOut, i )
|
|
|
|
|
{
|
|
|
|
|
pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut);
|
|
|
|
|
pObj->Value = Gia_ManAppendCi(pNew);
|
|
|
|
|
Gia_ManAppendCo( pNew, pObj->Value );
|
|
|
|
|
Gia_ObjSetTravIdCurrent( p, pObj ); // added
|
|
|
|
|
}
|
|
|
|
|
// create the nodes
|
|
|
|
|
Gia_ManForEachObjVec( vNodes, p, pObj, i )
|
|
|
|
|
if ( Gia_ObjIsAnd(pObj) )
|
|
|
|
|
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
|
|
|
|
// add real POs for the registers
|
|
|
|
|
Vec_IntForEachEntry( vPart, iOut, i )
|
|
|
|
|
{
|
|
|
|
|
pObj = Gia_ManCo( p, Gia_ManPoNum(p)+iOut );
|
|
|
|
|
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
|
|
|
|
}
|
|
|
|
|
Gia_ManSetRegNum( pNew, Vec_IntSize(vPart) );
|
|
|
|
|
// create map
|
|
|
|
|
if ( ppMapBack )
|
|
|
|
|
{
|
|
|
|
|
pMapBack = ABC_FALLOC( int, Gia_ManObjNum(pNew) );
|
|
|
|
|
// map constant nodes
|
|
|
|
|
pMapBack[0] = 0;
|
|
|
|
|
// logic cones of register outputs
|
|
|
|
|
Gia_ManForEachObjVec( vNodes, p, pObj, i )
|
|
|
|
|
{
|
|
|
|
|
// pObjNew = Aig_Regular(pObj->pData);
|
|
|
|
|
// pMapBack[pObjNew->Id] = pObj->Id;
|
2012-01-21 13:30:10 +01:00
|
|
|
assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 );
|
|
|
|
|
assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) );
|
|
|
|
|
pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj);
|
2010-11-01 09:35:04 +01:00
|
|
|
}
|
|
|
|
|
// map register outputs
|
|
|
|
|
Vec_IntForEachEntry( vPart, iOut, i )
|
|
|
|
|
{
|
|
|
|
|
pObj = Gia_ManCi(p, Gia_ManPiNum(p)+iOut);
|
|
|
|
|
// pObjNew = pObj->pData;
|
|
|
|
|
// pMapBack[pObjNew->Id] = pObj->Id;
|
2012-01-21 13:30:10 +01:00
|
|
|
assert( Abc_Lit2Var(Gia_ObjValue(pObj)) >= 0 );
|
|
|
|
|
assert( Abc_Lit2Var(Gia_ObjValue(pObj)) < Gia_ManObjNum(pNew) );
|
|
|
|
|
pMapBack[ Abc_Lit2Var(Gia_ObjValue(pObj)) ] = Gia_ObjId(p, pObj);
|
2010-11-01 09:35:04 +01:00
|
|
|
}
|
|
|
|
|
*ppMapBack = pMapBack;
|
|
|
|
|
}
|
|
|
|
|
Vec_IntFree( vNodes );
|
|
|
|
|
return pNew;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Transfers the classes.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Gia_TransferMappedClasses( Gia_Man_t * pPart, int * pMapBack, int * pReprs )
|
|
|
|
|
{
|
|
|
|
|
Gia_Obj_t * pObj;
|
|
|
|
|
int i, Id1, Id2, nClasses;
|
|
|
|
|
if ( pPart->pReprs == NULL )
|
|
|
|
|
return 0;
|
|
|
|
|
nClasses = 0;
|
|
|
|
|
Gia_ManForEachObj( pPart, pObj, i )
|
|
|
|
|
{
|
|
|
|
|
if ( Gia_ObjRepr(pPart, i) == GIA_VOID )
|
|
|
|
|
continue;
|
|
|
|
|
assert( i < Gia_ManObjNum(pPart) );
|
|
|
|
|
assert( Gia_ObjRepr(pPart, i) < Gia_ManObjNum(pPart) );
|
|
|
|
|
Id1 = pMapBack[ i ];
|
|
|
|
|
Id2 = pMapBack[ Gia_ObjRepr(pPart, i) ];
|
|
|
|
|
if ( Id1 == Id2 )
|
|
|
|
|
continue;
|
|
|
|
|
if ( Id1 < Id2 )
|
|
|
|
|
pReprs[Id2] = Id1;
|
|
|
|
|
else
|
|
|
|
|
pReprs[Id1] = Id2;
|
|
|
|
|
nClasses++;
|
|
|
|
|
}
|
|
|
|
|
return nClasses;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis []
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Gia_ManFindRepr_rec( int * pReprs, int Id )
|
|
|
|
|
{
|
|
|
|
|
if ( pReprs[Id] == 0 )
|
|
|
|
|
return 0;
|
|
|
|
|
if ( pReprs[Id] == ~0 )
|
|
|
|
|
return Id;
|
|
|
|
|
return Gia_ManFindRepr_rec( pReprs, pReprs[Id] );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Normalizes equivalences.]
|
|
|
|
|
|
|
|
|
|
Description []
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
void Gia_ManNormalizeEquivalences( Gia_Man_t * p, int * pReprs )
|
|
|
|
|
{
|
|
|
|
|
int i, iRepr;
|
|
|
|
|
assert( p->pReprs == NULL );
|
|
|
|
|
assert( p->pNexts == NULL );
|
|
|
|
|
p->pReprs = ABC_CALLOC( Gia_Rpr_t, Gia_ManObjNum(p) );
|
|
|
|
|
for ( i = 0; i < Gia_ManObjNum(p); i++ )
|
|
|
|
|
Gia_ObjSetRepr( p, i, GIA_VOID );
|
|
|
|
|
for ( i = 0; i < Gia_ManObjNum(p); i++ )
|
|
|
|
|
{
|
|
|
|
|
if ( pReprs[i] == ~0 )
|
|
|
|
|
continue;
|
|
|
|
|
iRepr = Gia_ManFindRepr_rec( pReprs, i );
|
|
|
|
|
Gia_ObjSetRepr( p, i, iRepr );
|
|
|
|
|
}
|
|
|
|
|
p->pNexts = Gia_ManDeriveNexts( p );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
|
|
|
|
|
|
Synopsis [Partitioned sequential synthesis.]
|
|
|
|
|
|
|
|
|
|
Description [Returns AIG annotated with equivalence classes.]
|
|
|
|
|
|
|
|
|
|
SideEffects []
|
|
|
|
|
|
|
|
|
|
SeeAlso []
|
|
|
|
|
|
|
|
|
|
***********************************************************************/
|
|
|
|
|
int Cec_SequentialSynthesisPart( Gia_Man_t * p, Cec_ParSeq_t * pPars )
|
|
|
|
|
{
|
|
|
|
|
int fPrintParts = 0;
|
|
|
|
|
char Buffer[100];
|
|
|
|
|
Gia_Man_t * pTemp;
|
|
|
|
|
Vec_Ptr_t * vParts = (Vec_Ptr_t *)p->vClockDoms;
|
|
|
|
|
Vec_Int_t * vPart;
|
|
|
|
|
int * pMapBack, * pReprs;
|
|
|
|
|
int i, nCountPis, nCountRegs;
|
2012-07-08 02:46:54 +02:00
|
|
|
int nClasses;
|
2013-05-28 00:09:23 +02:00
|
|
|
abctime clk = Abc_Clock();
|
2010-11-01 09:35:04 +01:00
|
|
|
|
|
|
|
|
// save parameters
|
|
|
|
|
if ( fPrintParts )
|
|
|
|
|
{
|
|
|
|
|
// print partitions
|
|
|
|
|
Abc_Print( 1, "The following clock domains are used:\n" );
|
|
|
|
|
Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
|
|
|
|
|
{
|
|
|
|
|
pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, NULL );
|
|
|
|
|
sprintf( Buffer, "part%03d.aig", i );
|
2012-12-10 22:56:40 +01:00
|
|
|
Gia_AigerWrite( pTemp, Buffer, 0, 0 );
|
2010-11-01 09:35:04 +01:00
|
|
|
Abc_Print( 1, "part%03d.aig : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d.\n",
|
|
|
|
|
i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp) );
|
|
|
|
|
Gia_ManStop( pTemp );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// perform sequential synthesis for clock domains
|
|
|
|
|
pReprs = ABC_FALLOC( int, Gia_ManObjNum(p) );
|
|
|
|
|
Vec_PtrForEachEntry( Vec_Int_t *, vParts, vPart, i )
|
|
|
|
|
{
|
|
|
|
|
pTemp = Gia_ManRegCreatePart( p, vPart, &nCountPis, &nCountRegs, &pMapBack );
|
|
|
|
|
if ( nCountPis > 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( pPars->fUseScorr )
|
|
|
|
|
{
|
|
|
|
|
Cec_ParCor_t CorPars, * pCorPars = &CorPars;
|
|
|
|
|
Cec_ManCorSetDefaultParams( pCorPars );
|
|
|
|
|
pCorPars->nBTLimit = pPars->nBTLimit;
|
|
|
|
|
pCorPars->nLevelMax = pPars->nLevelMax;
|
|
|
|
|
pCorPars->fVerbose = pPars->fVeryVerbose;
|
|
|
|
|
pCorPars->fUseCSat = 1;
|
|
|
|
|
Cec_ManLSCorrespondenceClasses( pTemp, pCorPars );
|
|
|
|
|
}
|
|
|
|
|
else if ( pPars->fUseLcorr )
|
|
|
|
|
{
|
|
|
|
|
Cec_ParCor_t CorPars, * pCorPars = &CorPars;
|
|
|
|
|
Cec_ManCorSetDefaultParams( pCorPars );
|
|
|
|
|
pCorPars->fLatchCorr = 1;
|
|
|
|
|
pCorPars->nBTLimit = pPars->nBTLimit;
|
|
|
|
|
pCorPars->fVerbose = pPars->fVeryVerbose;
|
|
|
|
|
pCorPars->fUseCSat = 1;
|
|
|
|
|
Cec_ManLSCorrespondenceClasses( pTemp, pCorPars );
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// pNew = Gia_ManSeqStructSweep( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose );
|
|
|
|
|
// Gia_ManStop( pNew );
|
|
|
|
|
Gia_ManSeqCleanupClasses( pTemp, pPars->fConsts, pPars->fEquivs, pPars->fVerbose );
|
|
|
|
|
}
|
|
|
|
|
//Abc_Print( 1, "Part equivalences = %d.\n", Gia_ManEquivCountLitsAll(pTemp) );
|
|
|
|
|
nClasses = Gia_TransferMappedClasses( pTemp, pMapBack, pReprs );
|
|
|
|
|
if ( pPars->fVerbose )
|
|
|
|
|
{
|
|
|
|
|
Abc_Print( 1, "%3d : Reg = %4d. PI = %4d. (True = %4d. Regs = %4d.) And = %5d. Cl = %5d.\n",
|
|
|
|
|
i, Vec_IntSize(vPart), Gia_ManCiNum(pTemp)-Vec_IntSize(vPart), nCountPis, nCountRegs, Gia_ManAndNum(pTemp), nClasses );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Gia_ManStop( pTemp );
|
|
|
|
|
ABC_FREE( pMapBack );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate resulting equivalences
|
|
|
|
|
Gia_ManNormalizeEquivalences( p, pReprs );
|
|
|
|
|
//Abc_Print( 1, "Total equivalences = %d.\n", Gia_ManEquivCountLitsAll(p) );
|
|
|
|
|
ABC_FREE( pReprs );
|
|
|
|
|
if ( pPars->fVerbose )
|
|
|
|
|
{
|
2013-05-28 00:09:23 +02:00
|
|
|
Abc_PrintTime( 1, "Total time", Abc_Clock() - clk );
|
2010-11-01 09:35:04 +01:00
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// END OF FILE ///
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ABC_NAMESPACE_IMPL_END
|
|
|
|
|
|