mirror of https://github.com/YosysHQ/abc.git
Merge remote-tracking branch 'upstream/master' into yosys-experimental
This commit is contained in:
commit
fcd8ac34d6
2
Makefile
2
Makefile
|
|
@ -66,7 +66,7 @@ endif
|
|||
ifdef ABC_USE_NAMESPACE
|
||||
CFLAGS += -DABC_NAMESPACE=$(ABC_USE_NAMESPACE) -fpermissive -x c++
|
||||
CC := $(CXX)
|
||||
$(info $(MSG_PREFIX)Compiling in namespace $(ABC_NAMESPACE))
|
||||
$(info $(MSG_PREFIX)Compiling in namespace $(ABC_USE_NAMESPACE))
|
||||
endif
|
||||
|
||||
# compile CUDD with ABC
|
||||
|
|
|
|||
|
|
@ -270,6 +270,7 @@ struct Gps_Par_t_
|
|||
int fSkipMap;
|
||||
int fSlacks;
|
||||
int fNoColor;
|
||||
int fMapOutStats;
|
||||
char * pDumpFile;
|
||||
};
|
||||
|
||||
|
|
@ -387,6 +388,7 @@ struct Jf_Par_t_
|
|||
float Epsilon;
|
||||
float * pTimesArr;
|
||||
float * pTimesReq;
|
||||
char * ZFile;
|
||||
};
|
||||
|
||||
static inline unsigned Gia_ObjCutSign( unsigned ObjId ) { return (1 << (ObjId & 31)); }
|
||||
|
|
@ -1411,6 +1413,10 @@ extern Gia_Man_t * Gia_ManDemiterToDual( Gia_Man_t * p );
|
|||
extern int Gia_ManDemiterDual( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 );
|
||||
extern int Gia_ManDemiterTwoWords( Gia_Man_t * p, Gia_Man_t ** pp0, Gia_Man_t ** pp1 );
|
||||
extern void Gia_ManProdAdderGen( int nArgA, int nArgB, int Seed, int fSigned, int fCla );
|
||||
typedef struct Gia_ChMan_t_ Gia_ChMan_t;
|
||||
extern Gia_ChMan_t * Gia_ManDupChoicesStart( Gia_Man_t * pGia );
|
||||
extern void Gia_ManDupChoicesAdd( Gia_ChMan_t * pMan, Gia_Man_t * pGia );
|
||||
extern Gia_Man_t * Gia_ManDupChoicesFinish( Gia_ChMan_t * pMan );
|
||||
/*=== giaEdge.c ==========================================================*/
|
||||
extern void Gia_ManEdgeFromArray( Gia_Man_t * p, Vec_Int_t * vArray );
|
||||
extern Vec_Int_t * Gia_ManEdgeToArray( Gia_Man_t * p );
|
||||
|
|
@ -1507,6 +1513,7 @@ extern int Gia_ManHashAndMulti( Gia_Man_t * p, Vec_Int_t * vLits
|
|||
extern int Gia_ManHashAndMulti2( Gia_Man_t * p, Vec_Int_t * vLits );
|
||||
extern int Gia_ManHashDualMiter( Gia_Man_t * p, Vec_Int_t * vOuts );
|
||||
/*=== giaIf.c ===========================================================*/
|
||||
extern void Gia_ManPrintOutputLutStats( Gia_Man_t * p );
|
||||
extern void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile );
|
||||
extern void Gia_ManPrintPackingStats( Gia_Man_t * p );
|
||||
extern void Gia_ManPrintLutStats( Gia_Man_t * p );
|
||||
|
|
@ -1719,6 +1726,7 @@ extern Gia_Man_t * Gia_ManUpdateExtraAig( void * pTime, Gia_Man_t * pAig
|
|||
extern Gia_Man_t * Gia_ManUpdateExtraAig2( void * pTime, Gia_Man_t * pAig, Vec_Int_t * vBoxesLeft );
|
||||
extern Gia_Man_t * Gia_ManDupCollapse( Gia_Man_t * p, Gia_Man_t * pBoxes, Vec_Int_t * vBoxPres, int fSeq );
|
||||
extern int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fSeq, int fDumpFiles, int fVerbose, char * pFileSpec );
|
||||
extern Vec_Int_t * Gia_ManDeriveBoxMapping( Gia_Man_t * pGia );
|
||||
/*=== giaTruth.c ===========================================================*/
|
||||
extern word Gia_LutComputeTruth6( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTruths );
|
||||
extern word Gia_ObjComputeTruthTable6Lut( Gia_Man_t * p, int iObj, Vec_Wrd_t * vTemp );
|
||||
|
|
|
|||
|
|
@ -1168,6 +1168,46 @@ Vec_Ptr_t * Gia_ManMatchCutsMany( Vec_Mem_t * vTtMem, Vec_Int_t * vMap, int nFun
|
|||
return vRes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Function enumeration.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Gia_ManDumpCuts( Gia_Man_t * p, int nCutSize, int nCutNum, int fVerbose )
|
||||
{
|
||||
FILE * pFile = fopen( "input.txt", "wb" ); if ( !pFile ) return;
|
||||
Gia_Sto_t * pSto = Gia_ManMatchCutsInt( p, nCutSize, nCutNum, 0 );
|
||||
Vec_Int_t * vLevel; int i, k, c, * pCut, nCuts = 0, nNodes = 0;
|
||||
Vec_WecForEachLevel( pSto->vCuts, vLevel, i ) if ( Vec_IntSize(vLevel) ) {
|
||||
if ( !Gia_ObjIsAnd(Gia_ManObj(p, i)) )
|
||||
continue;
|
||||
Sdb_ForEachCut( Vec_IntArray(vLevel), pCut, k ) {
|
||||
if ( pCut[0] == 1 )
|
||||
continue;
|
||||
fprintf( pFile, "%d ", i );
|
||||
for ( c = 1; c <= pCut[0]; c++ )
|
||||
fprintf( pFile, "%d ", pCut[c] );
|
||||
fprintf( pFile, "1\n" );
|
||||
nCuts += pCut[0];
|
||||
nNodes++;
|
||||
}
|
||||
}
|
||||
Gia_Obj_t * pObj;
|
||||
Gia_ManForEachCo( p, pObj, i ) {
|
||||
fprintf( pFile, "%d %d 0\n", Gia_ObjId(p, pObj), Gia_ObjFaninId0p(p, pObj) );
|
||||
}
|
||||
fclose( pFile );
|
||||
Gia_StoFree( pSto );
|
||||
if ( fVerbose )
|
||||
printf( "Dumped %d cuts for %d nodes into file \"input.txt\".\n", nCuts, nNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Function enumeration.]
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
#include "misc/tim/tim.h"
|
||||
#include "misc/vec/vecWec.h"
|
||||
#include "proof/cec/cec.h"
|
||||
#include "misc/util/utilTruth.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
|
|
@ -3250,6 +3251,50 @@ Gia_Man_t * Gia_ManDupAndOr( Gia_Man_t * p, int nOuts, int fUseOr, int fCompl )
|
|||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Computes the AND of all POs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Gia_Man_t * Gia_ManDupAndCare( Gia_Man_t * p, Gia_Man_t * pCare )
|
||||
{
|
||||
Gia_Man_t * pNew, * pTemp;
|
||||
Gia_Obj_t * pObj; int i;
|
||||
assert( Gia_ManRegNum(p) == 0 );
|
||||
assert( Gia_ManRegNum(pCare) == 0 );
|
||||
assert( Gia_ManPiNum(p) == Gia_ManPiNum(pCare) );
|
||||
pNew = Gia_ManStart( Gia_ManObjNum(p) );
|
||||
pNew->pName = Abc_UtilStrsav( p->pName );
|
||||
Gia_ManConst0(p)->Value = 0;
|
||||
Gia_ManConst0(pCare)->Value = 0;
|
||||
Gia_ManHashAlloc( pNew );
|
||||
Gia_ManForEachPi( p, pObj, i )
|
||||
pObj->Value = Gia_ManPi(pCare, i)->Value = Gia_ManAppendCi( pNew );
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
Gia_ManForEachAnd( pCare, pObj, i )
|
||||
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
if ( Gia_ManPoNum(pCare) == 1 ) {
|
||||
Gia_ManForEachPo( p, pObj, i )
|
||||
Gia_ManAppendCo( pNew, Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(Gia_ManPo(pCare, 0)) ) );
|
||||
}
|
||||
else if ( Gia_ManPoNum(p) == Gia_ManPoNum(pCare) ) {
|
||||
Gia_ManForEachPo( p, pObj, i )
|
||||
Gia_ManAppendCo( pNew, Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(Gia_ManPo(pCare, i)) ) );
|
||||
}
|
||||
else assert( 0 );
|
||||
Gia_ManHashStop( pNew );
|
||||
pNew = Gia_ManCleanup( pTemp = pNew );
|
||||
Gia_ManStop( pTemp );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Transforms output names.]
|
||||
|
|
@ -5995,11 +6040,11 @@ Vec_Wec_t * Gia_ManCollectIntTfos( Gia_Man_t * p, Vec_Int_t * vVarNums )
|
|||
}
|
||||
Gia_Man_t * Gia_ManDupCofs( Gia_Man_t * p, Vec_Int_t * vVarNums )
|
||||
{
|
||||
Vec_Int_t * vOutLits = Vec_IntStartFull( 1 << Vec_IntSize(vVarNums) );
|
||||
int i, iLit, nMints = 1 << Vec_IntSize(vVarNums);
|
||||
Vec_Int_t * vOutLits = Vec_IntAlloc( nMints * Gia_ManCoNum(p) );
|
||||
Vec_Wec_t * vTfos = Gia_ManCollectIntTfos( p, vVarNums );
|
||||
Gia_Man_t * pNew, * pTemp;
|
||||
Gia_Obj_t * pObj, * pRoot = Gia_ManCo(p, 0); int i, iLit;
|
||||
assert( Gia_ManPoNum(p) == 1 && Gia_ManRegNum(p) == 0 );
|
||||
Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj;
|
||||
assert( Gia_ManRegNum(p) == 0 );
|
||||
pNew = Gia_ManStart( Gia_ManObjNum(p) );
|
||||
pNew->pName = Abc_UtilStrsav( p->pName );
|
||||
Gia_ManFillValue( p );
|
||||
|
|
@ -6011,16 +6056,18 @@ Gia_Man_t * Gia_ManDupCofs( Gia_Man_t * p, Vec_Int_t * vVarNums )
|
|||
Gia_ManHashAlloc( pNew );
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
Vec_IntWriteEntry( vOutLits, 0, Gia_ObjFanin0Copy(pRoot) );
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
Vec_IntPush( vOutLits, Gia_ObjFanin0Copy(pObj) );
|
||||
int m, g, x, b = 0;
|
||||
for ( m = 1; m < Vec_IntSize(vOutLits); m++ )
|
||||
for ( m = 1; m < nMints; m++ )
|
||||
{
|
||||
g = m ^ (m >> 1); x = (b ^ g) == 1 ? 0 : Abc_Base2Log(b ^ g); b = g;
|
||||
Vec_Int_t * vNode = Vec_WecEntry( vTfos, x );
|
||||
Gia_ManPi(p, Vec_IntEntry(vVarNums, x))->Value ^= 1;
|
||||
Gia_ManForEachObjVec( vNode, p, pObj, i )
|
||||
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
Vec_IntWriteEntry( vOutLits, g, Gia_ObjFanin0Copy(pRoot) );
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
Vec_IntPush( vOutLits, Gia_ObjFanin0Copy(pObj) );
|
||||
}
|
||||
assert( Vec_IntFindMin(vOutLits) >= 0 );
|
||||
Vec_IntForEachEntry( vOutLits, iLit, i )
|
||||
|
|
@ -6166,6 +6213,273 @@ void Gia_ManCofClassEnum( Gia_Man_t * p, int nVars )
|
|||
Vec_IntFree( vIns );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Gia_ObjWhichFanout( Gia_Man_t * p, int iFanin, int iFanout )
|
||||
{
|
||||
int i, FanId;
|
||||
Gia_ObjForEachFanoutStaticId( p, iFanin, FanId, i )
|
||||
if ( FanId == iFanout )
|
||||
return i;
|
||||
assert( 0 );
|
||||
return -1;
|
||||
}
|
||||
Gia_Man_t * Gia_ManDupFanouts( Gia_Man_t * p )
|
||||
{
|
||||
assert( Gia_ManRegNum(p) == 0 );
|
||||
Gia_Man_t * pNew; Gia_Obj_t * pObj; int i, f, iLit[2];
|
||||
pNew = Gia_ManStart( Gia_ManObjNum(p)+100 );
|
||||
pNew->pName = Abc_UtilStrsav( p->pName );
|
||||
Gia_ManFillValue( p );
|
||||
Gia_ManConst0(p)->Value = 0;
|
||||
Gia_ManStaticFanoutStart( p );
|
||||
pNew->vNamesIn = Vec_PtrAlloc( 100 );
|
||||
pNew->vNamesOut = Vec_PtrAlloc( 100 );
|
||||
Gia_ManForEachPi( p, pObj, i ) {
|
||||
pObj->Value = Gia_ManAppendCi(pNew);
|
||||
Vec_PtrPush( pNew->vNamesIn, Gia_ObjCiName(p, i) );
|
||||
for ( f = 1; f < Gia_ObjFanoutNum(p, pObj); f++ ) {
|
||||
Gia_ManAppendCi(pNew);
|
||||
Vec_PtrPush( pNew->vNamesIn, Abc_UtilStrsavNum(Gia_ObjCiName(p, i), f) );
|
||||
}
|
||||
}
|
||||
Gia_ManForEachAnd( p, pObj, i ) {
|
||||
iLit[0] = Gia_ObjFanin0Copy(pObj);
|
||||
if ( Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) )
|
||||
iLit[0] += 2 * Gia_ObjWhichFanout(p, Gia_ObjFaninId0(pObj, i), i);
|
||||
iLit[1] = Gia_ObjFanin1Copy(pObj);
|
||||
if ( Gia_ObjIsPi(p, Gia_ObjFanin1(pObj)) )
|
||||
iLit[1] += 2 * Gia_ObjWhichFanout(p, Gia_ObjFaninId1(pObj, i), i);
|
||||
pObj->Value = Gia_ManAppendAnd( pNew, iLit[0], iLit[1] );
|
||||
}
|
||||
Gia_ManForEachPo( p, pObj, i ) {
|
||||
iLit[0] = Gia_ObjFanin0Copy(pObj);
|
||||
if ( Gia_ObjIsPi(p, Gia_ObjFanin0(pObj)) )
|
||||
iLit[0] += 2 * Gia_ObjWhichFanout(p, Gia_ObjFaninId0p(p, pObj), Gia_ObjId(p, pObj));
|
||||
Gia_ManAppendCo( pNew, iLit[0] );
|
||||
Vec_PtrPush( pNew->vNamesOut, Gia_ObjCoName(p, i) );
|
||||
}
|
||||
Gia_ManStaticFanoutStop( p );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Reorders choice nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Gia_ManPrintChoices( Gia_Man_t * p )
|
||||
{
|
||||
Gia_Obj_t * pObj; int i;
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
if ( p->pSibls[i] )
|
||||
printf( "%d -> %d\n", i, p->pSibls[i] );
|
||||
}
|
||||
void Gia_ManReorderChoices_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj )
|
||||
{
|
||||
if ( ~pObj->Value )
|
||||
return;
|
||||
assert( Gia_ObjIsAnd(pObj) );
|
||||
Gia_Obj_t * pSibl = Gia_ObjSiblObj(p, Gia_ObjId(p, pObj));
|
||||
Gia_ManReorderChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
|
||||
Gia_ManReorderChoices_rec( pNew, p, Gia_ObjFanin1(pObj) );
|
||||
if ( pSibl ) Gia_ManReorderChoices_rec( pNew, p, pSibl );
|
||||
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
if ( pSibl ) {
|
||||
int iObjNew = Abc_Lit2Var(pObj->Value);
|
||||
int iNextNew = Abc_Lit2Var(pSibl->Value);
|
||||
assert( iObjNew > iNextNew );
|
||||
assert( Gia_ObjIsAnd(Gia_ManObj(pNew, iNextNew)) );
|
||||
pNew->pSibls[iObjNew] = iNextNew;
|
||||
}
|
||||
}
|
||||
Gia_Man_t * Gia_ManReorderChoices( Gia_Man_t * p )
|
||||
{
|
||||
assert( p->pSibls );
|
||||
Gia_Obj_t * pObj; int i;
|
||||
Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(p) );
|
||||
pNew->pName = Abc_UtilStrsav( p->pName );
|
||||
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
|
||||
pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
|
||||
Gia_ManFillValue(p);
|
||||
Gia_ManForEachCi( p, pObj, i )
|
||||
pObj->Value = Gia_ManAppendCi(pNew);
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
Gia_ManReorderChoices_rec( pNew, p, Gia_ObjFanin0(pObj) );
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
||||
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
|
||||
extern int Gia_ManTestChoices( Gia_Man_t * p );
|
||||
Gia_ManTestChoices( pNew );
|
||||
//Gia_ManPrintChoices( pNew );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Duplicates AIGs while creating choices.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
struct Gia_ChMan_t_
|
||||
{
|
||||
Gia_Man_t * pNew;
|
||||
Vec_Mem_t * vTtMem;
|
||||
Vec_Int_t * vSibls;
|
||||
Vec_Int_t * vObj2Tt;
|
||||
Vec_Int_t * vTt2Obj;
|
||||
Vec_Int_t * vCoLits;
|
||||
word * pTruth;
|
||||
int nWords;
|
||||
};
|
||||
|
||||
int Gia_ManDupChoicesMark_rec( Gia_Man_t * pGia, int iObj, Vec_Int_t * vObj2Tt, int iFunc )
|
||||
{
|
||||
if ( Abc_Lit2Var(Vec_IntEntry(vObj2Tt, iObj)) == iFunc )
|
||||
return 1;
|
||||
if ( Gia_ObjIsTravIdCurrentId(pGia, iObj) )
|
||||
return 0;
|
||||
Gia_ObjSetTravIdCurrentId(pGia, iObj);
|
||||
Gia_Obj_t * pObj = Gia_ManObj(pGia, iObj);
|
||||
if ( !Gia_ObjIsAnd(pObj) )
|
||||
return 0;
|
||||
if ( Gia_ManDupChoicesMark_rec( pGia, Gia_ObjFaninId0(pObj, iObj), vObj2Tt, iFunc ) )
|
||||
return 1;
|
||||
if ( Gia_ManDupChoicesMark_rec( pGia, Gia_ObjFaninId1(pObj, iObj), vObj2Tt, iFunc ) )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
int Gia_ManDupChoicesMark( Gia_Man_t * pGia, int iLit0, int iLit1, Vec_Int_t * vObj2Tt, int iFunc )
|
||||
{
|
||||
Gia_ManIncrementTravId( pGia );
|
||||
if ( Gia_ManDupChoicesMark_rec( pGia, Abc_Lit2Var(iLit0), vObj2Tt, iFunc ) )
|
||||
return 1;
|
||||
if ( Gia_ManDupChoicesMark_rec( pGia, Abc_Lit2Var(iLit1), vObj2Tt, iFunc ) )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
void Gia_ManDupChoicesNode( Gia_ChMan_t * p, Gia_Man_t * pGia, int iObj )
|
||||
{
|
||||
Gia_Obj_t * pObj = Gia_ManObj( pGia, iObj );
|
||||
assert( ~Gia_ObjFanin0(pObj)->Value && ~Gia_ObjFanin1(pObj)->Value );
|
||||
int obLits[2] = { Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) };
|
||||
int ttLits[2] = { Vec_IntEntry(p->vObj2Tt, Abc_Lit2Var(obLits[0])), Vec_IntEntry(p->vObj2Tt, Abc_Lit2Var(obLits[1])) };
|
||||
int fCompl[2] = { Abc_LitIsCompl(ttLits[0]) ^ Abc_LitIsCompl(obLits[0]), Abc_LitIsCompl(ttLits[1]) ^ Abc_LitIsCompl(obLits[1]) };
|
||||
word * pTruth[2] = { Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(ttLits[0])), Vec_MemReadEntry(p->vTtMem, Abc_Lit2Var(ttLits[1])) };
|
||||
Abc_TtAndCompl( p->pTruth, pTruth[0], fCompl[0], pTruth[1], fCompl[1], p->nWords );
|
||||
int fComp = (int)p->pTruth[0] & 1; if ( fComp ) Abc_TtNot( p->pTruth, p->nWords );
|
||||
int nFuncs = Vec_MemEntryNum( p->vTtMem );
|
||||
int iFunc = Vec_MemHashInsert( p->vTtMem, p->pTruth );
|
||||
assert( iFunc <= nFuncs );
|
||||
if ( iFunc == nFuncs ) { // new function
|
||||
pObj->Value = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
Vec_IntPush( p->vObj2Tt, Abc_Var2Lit(iFunc, fComp ^ Abc_LitIsCompl(pObj->Value)) );
|
||||
Vec_IntPush( p->vTt2Obj, Abc_Lit2Var(pObj->Value) );
|
||||
return;
|
||||
}
|
||||
int iRepr = Vec_IntEntry( p->vTt2Obj, iFunc );
|
||||
pObj->Value = Abc_Var2Lit( iRepr, fComp ^ Abc_LitIsCompl(Vec_IntEntry(p->vObj2Tt, iRepr)) );
|
||||
if ( iRepr <= Gia_ManCiNum(pGia) || Gia_ManDupChoicesMark(p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj), p->vObj2Tt, iFunc) )
|
||||
return;
|
||||
int nObjNew = Gia_ManObjNum(p->pNew);
|
||||
int iLitNew = Gia_ManHashAnd( p->pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
if ( Abc_Lit2Var(iLitNew) == nObjNew )
|
||||
Vec_IntPush( p->vObj2Tt, Abc_Var2Lit(iFunc, fComp ^ Abc_LitIsCompl(iLitNew)) );
|
||||
}
|
||||
void Gia_ManDupChoicesAdd( Gia_ChMan_t * p, Gia_Man_t * pGia )
|
||||
{
|
||||
Gia_Obj_t * pObj; int i;
|
||||
assert( Gia_ManCiNum(p->pNew) == Gia_ManCiNum(pGia) );
|
||||
assert( !p->vCoLits || Vec_IntSize(p->vCoLits) == Gia_ManCoNum(pGia) );
|
||||
assert( Gia_ManRegNum(p->pNew) == Gia_ManRegNum(pGia) );
|
||||
Gia_ManFillValue( pGia );
|
||||
Gia_ManForEachCi( pGia, pObj, i )
|
||||
pObj->Value = Gia_ManCiLit( p->pNew, i );
|
||||
Gia_ManForEachAnd( pGia, pObj, i )
|
||||
Gia_ManDupChoicesNode( p, pGia, i );
|
||||
assert( Vec_IntSize(p->vObj2Tt) == Gia_ManObjNum(p->pNew) );
|
||||
assert( Vec_IntSize(p->vTt2Obj) == Vec_MemEntryNum(p->vTtMem) );
|
||||
}
|
||||
Gia_ChMan_t * Gia_ManDupChoicesStart( Gia_Man_t * pGia )
|
||||
{
|
||||
Gia_ChMan_t * p = ABC_CALLOC( Gia_ChMan_t, 1 );
|
||||
p->pNew = Gia_ManStart( 10*Gia_ManObjNum(pGia) );
|
||||
p->pNew->pName = Abc_UtilStrsav( pGia->pName );
|
||||
p->pNew->pSpec = Abc_UtilStrsav( pGia->pSpec );
|
||||
p->vTtMem = Vec_MemAllocWithTTs( Gia_ManCiNum(pGia) );
|
||||
p->vTt2Obj = Vec_IntStartNatural( 1 + Gia_ManCiNum(pGia) );
|
||||
p->vObj2Tt = Vec_IntAlloc( 10*Gia_ManObjNum(pGia) );
|
||||
p->nWords = Abc_TtWordNum( Gia_ManCiNum(pGia) );
|
||||
p->pTruth = ABC_CALLOC( word, p->nWords );
|
||||
Gia_Obj_t * pObj; int i;
|
||||
for ( i = 0; i <= Gia_ManCiNum(pGia); i++ )
|
||||
Vec_IntPush( p->vObj2Tt, Abc_Var2Lit(i, 0) );
|
||||
Gia_ManForEachCi( pGia, pObj, i )
|
||||
Gia_ManAppendCi(p->pNew);
|
||||
Gia_ManSetRegNum( p->pNew, Gia_ManRegNum(pGia) );
|
||||
Gia_ManHashStart( p->pNew );
|
||||
Gia_ManDupChoicesAdd( p, pGia );
|
||||
p->vCoLits = Vec_IntAlloc( Gia_ManCoNum(pGia) );
|
||||
Gia_ManForEachCo( pGia, pObj, i )
|
||||
Vec_IntPush( p->vCoLits, Gia_ObjFanin0Copy(pObj) );
|
||||
return p;
|
||||
}
|
||||
Vec_Int_t * Gia_ManDupChoicesCreateSibls( Gia_ChMan_t * p )
|
||||
{
|
||||
int iObj, ttLit;
|
||||
Vec_Int_t * vSibls = Vec_IntStart( Gia_ManObjNum(p->pNew) );
|
||||
assert( Vec_IntSize(p->vTt2Obj) == Vec_MemEntryNum(p->vTtMem) );
|
||||
Vec_IntForEachEntry( p->vObj2Tt, ttLit, iObj ) {
|
||||
int iPrev = Vec_IntEntry(p->vTt2Obj, Abc_Lit2Var(ttLit));
|
||||
assert( iPrev <= iObj );
|
||||
if ( iPrev == iObj )
|
||||
continue;
|
||||
Vec_IntWriteEntry( vSibls, iPrev, iObj );
|
||||
Vec_IntWriteEntry( p->vTt2Obj, Abc_Lit2Var(ttLit), iObj );
|
||||
}
|
||||
return vSibls;
|
||||
}
|
||||
Gia_Man_t * Gia_ManDupChoicesFinish( Gia_ChMan_t * p )
|
||||
{
|
||||
Gia_Man_t * pTemp, * pNew = p->pNew; int i, iLit;
|
||||
p->vSibls = Gia_ManDupChoicesCreateSibls( p );
|
||||
p->pNew->pSibls = Vec_IntReleaseArray( p->vSibls );
|
||||
Vec_IntForEachEntry( p->vCoLits, iLit, i )
|
||||
Gia_ManAppendCo( p->pNew, iLit );
|
||||
Vec_MemFree( p->vTtMem );
|
||||
Vec_IntFree( p->vSibls );
|
||||
Vec_IntFree( p->vTt2Obj );
|
||||
Vec_IntFree( p->vObj2Tt );
|
||||
Vec_IntFree( p->vCoLits );
|
||||
ABC_FREE( p->pTruth );
|
||||
ABC_FREE( p );
|
||||
pTemp = Gia_ManReorderChoices( pNew );
|
||||
Gia_ManStop( pNew );
|
||||
return pTemp;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1360,6 +1360,130 @@ Gia_Man_t * Gia_ManGenSorter( int LogN )
|
|||
return p;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Generates brand-name adders.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Gia_ManGenPrep( int nVars, int ** p )
|
||||
{
|
||||
int i, k;
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
for ( k = 0; k < nVars; k++ )
|
||||
p[i][k] = -1;
|
||||
}
|
||||
void Gia_ManGenSK( int nVars, int ** p )
|
||||
{
|
||||
int i, k, nBits = Abc_Base2Log(nVars);
|
||||
for ( i = 0; i < nBits; i++ )
|
||||
for ( k = 0; k < nVars; k++ )
|
||||
if ( (k >> i) & 1 )
|
||||
p[i+1][k] = ((1 << i) - 1) | ((k >> (i+1)) << (i+1));
|
||||
}
|
||||
void Gia_ManGenBK( int nVars, int ** p )
|
||||
{
|
||||
int i, k, nBits = Abc_Base2Log(nVars);
|
||||
nVars = 1 << nBits;
|
||||
for ( i = 1; i < nBits; i++ )
|
||||
for ( k = (1 << i) - 1; k < nVars; k += (1 << i) )
|
||||
p[i][k] = k - (1 << (i-1));
|
||||
p[nBits][nVars-1] = (1<<(nBits-1))-1;
|
||||
for ( i = 1; i < nBits; i++ )
|
||||
for ( k = (1 << i) - 1; k < nVars-(1 << i); k += (1 << i) )
|
||||
p[2*nBits-1-i][nVars-1-k+((1<<(i-1))-1)] = nVars-1-k+((1<<(i-1))-1) - (1 << (i-1));
|
||||
}
|
||||
void Gia_ManGenHC( int nVars, int ** p )
|
||||
{
|
||||
int i, k, nBits = Abc_Base2Log(nVars);
|
||||
nVars = 1 << nBits;
|
||||
for ( k = 1; k < nVars; k += 2 )
|
||||
p[1][k] = k - 1;
|
||||
for ( i = 2; i <= nBits; i++ )
|
||||
for ( k = 1 + (1 << (i-1)); k < nVars; k += 2 )
|
||||
p[i][k] = k - (1 << (i-1));
|
||||
for ( k = 2; k < nVars; k += 2 )
|
||||
p[nBits+1][k] = k - 1;
|
||||
}
|
||||
void Gia_ManGenRca( int nVars, int ** p )
|
||||
{
|
||||
int i;
|
||||
for ( i = 1; i < nVars; i++ )
|
||||
p[i][i] = i-1;
|
||||
}
|
||||
void Gia_ManGenPrint( int nVars, int ** p )
|
||||
{
|
||||
int i, k;
|
||||
for ( i = nVars-1; i >= 0; i-- )
|
||||
printf( "%2d ", i );
|
||||
printf( "\n" );
|
||||
for ( i = 0; i < nVars; i++ ) {
|
||||
for ( k = nVars-1; k >= 0; k-- )
|
||||
if ( p[i][k] >= 0 )
|
||||
break;
|
||||
for ( k = nVars-1; k >= 0; k-- )
|
||||
if ( p[i][k] == -1 )
|
||||
printf( " - " );
|
||||
else
|
||||
printf( "%2d ", p[i][k] );
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
void Gia_ManGenPrefix( Gia_Man_t * pNew, int * p, int * g, int p2, int g2 )
|
||||
{
|
||||
*g = Gia_ManHashOr(pNew, *g, Gia_ManHashAnd(pNew, *p, g2));
|
||||
*p = Gia_ManHashAnd(pNew, *p, p2);
|
||||
}
|
||||
Gia_Man_t * Gia_ManGenAdder( int nVars, int fSK, int fBK, int fHC, int fCarries, int fVerbose )
|
||||
{
|
||||
extern void Wlc_BlastFullAdder( Gia_Man_t * pNew, int a, int b, int c, int * pc, int * ps );
|
||||
int i, k, nBits = Abc_Base2Log(nVars), nVarsAlloc = (1 << nBits) + 2;
|
||||
int ** pStore = (int **)Extra_ArrayAlloc( nVarsAlloc, nVarsAlloc, 4 );
|
||||
printf( "Generating %d-bit ", nVars );
|
||||
Gia_ManGenPrep( nVars+2, pStore );
|
||||
if ( fSK )
|
||||
Gia_ManGenSK( nVars, pStore ), printf("Sklansky ");
|
||||
else if ( fBK )
|
||||
Gia_ManGenBK( nVars, pStore ), printf("Brent-Kung ");
|
||||
else if ( fHC )
|
||||
Gia_ManGenHC( nVars, pStore ), printf("Huan-Carlsson ");
|
||||
else
|
||||
Gia_ManGenRca( nVars, pStore ), printf("ripple-carry ");
|
||||
printf( "adder with%s carry-in and carry-out\n", fCarries ? "":"out" );
|
||||
if ( fVerbose ) Gia_ManGenPrint( nVars, pStore );
|
||||
Gia_Man_t * p = Gia_ManStart( 1000 ), * pTemp;
|
||||
p->pName = Abc_UtilStrsav( "adder" );
|
||||
int * pLitsI = ABC_CALLOC( int, 2*nVars+10 );
|
||||
for ( k = 0; k < nVars; k++ )
|
||||
pLitsI[2*k] = Gia_ManAppendCi(p);
|
||||
for ( k = 0; k < nVars; k++ )
|
||||
pLitsI[2*k+1] = Gia_ManAppendCi(p);
|
||||
int Carry = fCarries ? Gia_ManAppendCi(p) : 0;
|
||||
Gia_ManHashStart( p );
|
||||
for ( k = 0; k < nVars; k++ )
|
||||
Wlc_BlastFullAdder( p, pLitsI[2*k], pLitsI[2*k+1], k ? 0 : Carry, &pLitsI[2*k+1], &pLitsI[2*k] );
|
||||
int * pLits = ABC_CALLOC( int, 2*nVars+10 );
|
||||
memcpy( pLits, pLitsI, sizeof(int)*2*nVars );
|
||||
for ( i = 1; i < nVars; i++ )
|
||||
for ( k = 1; k < nVars; k++ )
|
||||
if ( pStore[i][k] >= 0 )
|
||||
Gia_ManGenPrefix( p, &pLits[2*k], &pLits[2*k+1], pLits[2*pStore[i][k]], pLits[2*pStore[i][k]+1] );
|
||||
for ( k = 0; k < nVars; k++ )
|
||||
Gia_ManAppendCo( p, k ? Gia_ManHashXor(p, pLitsI[2*k], pLits[2*(k-1)+1]) : pLitsI[2*k] );
|
||||
if ( fCarries )
|
||||
Gia_ManAppendCo( p, pLits[2*(k-1)+1] );
|
||||
ABC_FREE( pStore );
|
||||
ABC_FREE( pLitsI );
|
||||
ABC_FREE( pLits );
|
||||
p = Gia_ManCleanup( pTemp = p );
|
||||
Gia_ManStop( pTemp );
|
||||
return p;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
|
|
|
|||
|
|
@ -470,6 +470,65 @@ int Gia_ManCountDupLut( Gia_Man_t * p )
|
|||
return nCountDup + nCountPis;
|
||||
}
|
||||
|
||||
void Gia_ManCollectLuts_rec( Gia_Man_t * p, int iObj, Vec_Int_t * vLuts )
|
||||
{
|
||||
if ( Gia_ObjIsTravIdCurrentId( p, iObj ) || !Gia_ObjIsAnd(Gia_ManObj(p, iObj)) )
|
||||
return;
|
||||
Gia_ObjSetTravIdCurrentId( p, iObj );
|
||||
int k, iFan;
|
||||
Gia_LutForEachFanin( p, iObj, iFan, k )
|
||||
Gia_ManCollectLuts_rec( p, iFan, vLuts );
|
||||
Vec_IntPush( vLuts, iObj );
|
||||
}
|
||||
int Gia_ManCountLutLevels( Gia_Man_t * p, Vec_Int_t * vLuts, Vec_Int_t * vLevel )
|
||||
{
|
||||
int i, iObj, k, iFan, LevelMax = 0;
|
||||
Vec_IntForEachEntry( vLuts, iObj, i ) {
|
||||
int Level = 0;
|
||||
Gia_LutForEachFanin( p, iObj, iFan, k )
|
||||
Level = Abc_MaxInt( Level, Vec_IntEntry(vLevel, iFan) );
|
||||
Vec_IntWriteEntry( vLevel, iObj, Level+1 );
|
||||
LevelMax = Abc_MaxInt( LevelMax, Level+1 );
|
||||
}
|
||||
Vec_IntForEachEntry( vLuts, iObj, i )
|
||||
Vec_IntWriteEntry( vLevel, iObj, 0 );
|
||||
return LevelMax;
|
||||
}
|
||||
void Gia_ManPrintOutputLutStats( Gia_Man_t * p )
|
||||
{
|
||||
int Limit = 100000;
|
||||
int nLutSize = Gia_ManLutSizeMax(p);
|
||||
Vec_Int_t * vLuts = Vec_IntAlloc( 1000 );
|
||||
Vec_Int_t * vNodes = Vec_IntStart( Limit );
|
||||
Vec_Int_t * vLevels = Vec_IntStart( Limit );
|
||||
Vec_Int_t * vLevel = Vec_IntStart( Gia_ManObjNum(p) );
|
||||
int i, DriverId, Value, nTotalLuts = 0;
|
||||
Gia_ManForEachCoDriverId( p, DriverId, i ) {
|
||||
Vec_IntClear( vLuts );
|
||||
Gia_ManIncrementTravId(p);
|
||||
Gia_ManCollectLuts_rec( p, DriverId, vLuts );
|
||||
if ( Vec_IntSize(vLuts) < Limit )
|
||||
Vec_IntAddToEntry( vNodes, Vec_IntSize(vLuts), 1 );
|
||||
int Level = Gia_ManCountLutLevels( p, vLuts, vLevel );
|
||||
if ( Level < Limit )
|
||||
Vec_IntAddToEntry( vLevels, Level, 1 );
|
||||
nTotalLuts += Vec_IntSize(vLuts);
|
||||
}
|
||||
printf( "Level count statistics for %d AIG outputs:\n", Gia_ManCoNum(p) );
|
||||
Vec_IntForEachEntry( vLevels, Value, i )
|
||||
if ( Value )
|
||||
printf( " %2d level : Function count = %8d (%6.2f %%)\n", i, Value, 100.0*Value/Gia_ManCoNum(p) );
|
||||
printf( "LUT count statistics for %d AIG outputs:\n", Gia_ManCoNum(p) );
|
||||
Vec_IntForEachEntry( vNodes, Value, i )
|
||||
if ( Value )
|
||||
printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, Value, 100.0*Value/Gia_ManCoNum(p) );
|
||||
printf( "Sum total of LUT counts for all outputs = %d. Shared LUT count = %d.\n", nTotalLuts, Gia_ManLutNum(p) );
|
||||
Vec_IntFree( vLuts );
|
||||
Vec_IntFree( vNodes );
|
||||
Vec_IntFree( vLevels );
|
||||
Vec_IntFree( vLevel );
|
||||
}
|
||||
|
||||
void Gia_ManPrintMappingStats( Gia_Man_t * p, char * pDumpFile )
|
||||
{
|
||||
int fDisable2Lut = 1;
|
||||
|
|
|
|||
|
|
@ -474,6 +474,7 @@ void Gia_ManLogAigStats( Gia_Man_t * p, char * pDumpFile )
|
|||
fprintf( pTable, " \"name\" : \"%s\",\n", p->pName );
|
||||
fprintf( pTable, " \"input\" : %d,\n", Gia_ManCiNum(p) );
|
||||
fprintf( pTable, " \"output\" : %d,\n", Gia_ManCoNum(p) );
|
||||
fprintf( pTable, " \"flop\" : %d,\n", Gia_ManRegNum(p) );
|
||||
fprintf( pTable, " \"and\" : %d,\n", Gia_ManAndNum(p) );
|
||||
fprintf( pTable, " \"level\" : %d\n", Gia_ManLevelNum(p) );
|
||||
fprintf( pTable, "}\n" );
|
||||
|
|
@ -639,6 +640,8 @@ void Gia_ManPrintStats( Gia_Man_t * p, Gps_Par_t * pPars )
|
|||
}
|
||||
if ( pPars && pPars->fSlacks )
|
||||
Gia_ManDfsSlacksPrint( p );
|
||||
if ( Gia_ManHasMapping(p) && pPars->fMapOutStats )
|
||||
Gia_ManPrintOutputLutStats( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
|
|
@ -560,6 +560,7 @@ int * Abc_FrameGiaOutputMiniLutObj( Abc_Frame_t * pAbc )
|
|||
int * pRes = NULL;
|
||||
if ( pAbc == NULL )
|
||||
printf( "ABC framework is not initialized by calling Abc_Start()\n" );
|
||||
pAbc->vMiniLutObjs = Gia_ManDeriveBoxMapping( Abc_FrameReadGia( pAbc ) );
|
||||
if ( pAbc->vMiniLutObjs == NULL )
|
||||
printf( "MiniLut objects are not defined.\n" );
|
||||
pRes = Vec_IntReleaseArray( pAbc->vMiniLutObjs );
|
||||
|
|
|
|||
|
|
@ -2161,6 +2161,90 @@ void Nf_ManFixPoDrivers( Nf_Man_t * p )
|
|||
//printf( "Fixed %d PO drivers.\n", Count );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Dump matches.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Nf_ManDumpMatches( Nf_Man_t * p )
|
||||
{
|
||||
FILE * pFile = fopen( p->pPars->ZFile, "wb" );
|
||||
Gia_Obj_t * pObj; int n, iObj;
|
||||
// output matches
|
||||
Gia_ManForEachCi( p->pGia, pObj, n )
|
||||
fprintf( pFile, "%d input %.2f\n", Abc_Var2Lit(Gia_ObjId(p->pGia, pObj), 0), 0.0 );
|
||||
Gia_ManForEachAnd( p->pGia, pObj, iObj ) {
|
||||
assert( !Gia_ObjIsBuf(pObj) );
|
||||
for ( n = 0; n < 2; n++ ) {
|
||||
int c, * pCut, * pCutSet = Nf_ObjCutSet( p, iObj );
|
||||
Nf_SetForEachCut( pCutSet, pCut, c ) {
|
||||
if ( Abc_Lit2Var(Nf_CutFunc(pCut)) >= Vec_WecSize(p->vTt2Match) )
|
||||
continue;
|
||||
assert( !Nf_CutIsTriv(pCut, iObj) );
|
||||
assert( Nf_CutSize(pCut) <= p->pPars->nLutSize );
|
||||
assert( Abc_Lit2Var(Nf_CutFunc(pCut)) < Vec_WecSize(p->vTt2Match) );
|
||||
int iFuncLit = Nf_CutFunc(pCut);
|
||||
int fComplExt = Abc_LitIsCompl(iFuncLit);
|
||||
Vec_Int_t * v = Vec_WecEntry( p->vTt2Match, Abc_Lit2Var(iFuncLit) );
|
||||
int j, k, Info, Offset, iFanin, fComplF;
|
||||
Vec_IntForEachEntryDouble( v, Info, Offset, j ) {
|
||||
Nf_Cfg_t Cfg = Nf_Int2Cfg(Offset);
|
||||
int fCompl = Cfg.fCompl ^ fComplExt;
|
||||
if ( fCompl != n )
|
||||
continue;
|
||||
Mio_Cell2_t*pC = Nf_ManCell( p, Info );
|
||||
assert( Nf_CutSize(pCut) == (int)pC->nFanins );
|
||||
fprintf( pFile, "%d ", Abc_Var2Lit(iObj, n) );
|
||||
fprintf( pFile, "%s ", pC->pName );
|
||||
fprintf( pFile, "%.2f", pC->AreaF );
|
||||
Nf_CutForEachVarCompl( pCut, Cfg, iFanin, fComplF, k )
|
||||
fprintf( pFile, " %d", Abc_Var2Lit(iFanin, fComplF) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Gia_ManForEachCo( p->pGia, pObj, n )
|
||||
fprintf( pFile, "%d output %.2f %d\n", Abc_Var2Lit(Gia_ObjId(p->pGia, pObj), 0), 0.0, Gia_ObjFaninLit0p(p->pGia, pObj) );
|
||||
// output levels
|
||||
extern int Gia_ManChoiceLevel( Gia_Man_t * p );
|
||||
int LevelMax = Gia_ManChoiceLevel( p->pGia );
|
||||
Gia_ManForEachCiId( p->pGia, iObj, n )
|
||||
fprintf( pFile, "L%d %d\n", Abc_Var2Lit(iObj, 0), 0 );
|
||||
Gia_ManForEachAnd( p->pGia, pObj, iObj )
|
||||
fprintf( pFile, "L%d %d\n", Abc_Var2Lit(iObj, 0), Gia_ObjLevelId(p->pGia, iObj) );
|
||||
Gia_ManForEachCoId( p->pGia, iObj, n )
|
||||
fprintf( pFile, "L%d %d\n", Abc_Var2Lit(iObj, 0), LevelMax+1 );
|
||||
// output mapping
|
||||
Gia_ManForEachCiId( p->pGia, iObj, n )
|
||||
if ( Nf_ObjMapRefNum(p, iObj, 1) )
|
||||
fprintf( pFile, "M%d %s %.2f %d\n", Abc_Var2Lit(iObj, 1), p->pCells[3].pName, p->pCells[3].AreaF, Abc_Var2Lit(iObj, 0) );
|
||||
Gia_ManForEachAnd( p->pGia, pObj, iObj )
|
||||
for ( n = 0; n < 2; n++ )
|
||||
if ( Nf_ObjMapRefNum(p, iObj, n) ) {
|
||||
Nf_Mat_t * pM = Nf_ObjMatchBest(p, iObj, n);
|
||||
if ( pM->fCompl ) {
|
||||
fprintf( pFile, "M%d %s %.2f %d\n", Abc_Var2Lit(iObj, n), p->pCells[3].pName, p->pCells[3].AreaF, Abc_Var2Lit(iObj, !n) );
|
||||
continue;
|
||||
}
|
||||
int k, iVar, fCompl, * pCut = Nf_CutFromHandle( Nf_ObjCutSet(p, iObj), pM->CutH );
|
||||
Mio_Cell2_t*pC = Nf_ManCell( p, pM->Gate );
|
||||
fprintf( pFile, "M%d ", Abc_Var2Lit(iObj, n) );
|
||||
fprintf( pFile, "%s ", pC->pName );
|
||||
fprintf( pFile, "%.2f", pC->AreaF );
|
||||
Nf_CutForEachVarCompl( pCut, pM->Cfg, iVar, fCompl, k )
|
||||
fprintf( pFile, " %d", Abc_Var2Lit(iVar, fCompl) );
|
||||
fprintf( pFile, "\n" );
|
||||
}
|
||||
fclose( pFile );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Deriving mapping.]
|
||||
|
|
@ -2216,6 +2300,8 @@ Gia_Man_t * Nf_ManDeriveMapping( Nf_Man_t * p )
|
|||
}
|
||||
// assert( Vec_IntCap(vMapping) == 16 || Vec_IntSize(vMapping) == Vec_IntCap(vMapping) );
|
||||
p->pGia->vCellMapping = vMapping;
|
||||
if ( p->pPars->ZFile )
|
||||
Nf_ManDumpMatches( p );
|
||||
return p->pGia;
|
||||
}
|
||||
void Nf_ManUpdateStats( Nf_Man_t * p )
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int
|
|||
Par.fOptOnInsert = fOptOnInsert;
|
||||
Par.fGreedy = fGreedy;
|
||||
rrr::Perform(&ntk, &Par);
|
||||
Gia_Man_t *pNew = rrr::CreateGia(&ntk);
|
||||
Gia_Man_t *pNew = rrr::CreateGia(&ntk, false);
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -288,6 +288,21 @@ void Gia_ManSimPatWrite( char * pFileName, Vec_Wrd_t * vSimsIn, int nWords )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Wrd_t * Gia_ManDeriveNodeFuncs( Gia_Man_t * p )
|
||||
{
|
||||
int nWords = Abc_Truth6WordNum( Gia_ManCiNum(p) );
|
||||
Vec_Wrd_t * vSims = Vec_WrdStart( nWords * Gia_ManObjNum(p) );
|
||||
Gia_Obj_t * pObj; int i;
|
||||
Gia_ManForEachCi( p, pObj, i )
|
||||
assert( Gia_ObjId(p, pObj) == i+1 );
|
||||
Vec_Ptr_t * vTruths = Vec_PtrAllocTruthTables( Gia_ManCiNum(p) );
|
||||
Gia_ManForEachCi( p, pObj, i )
|
||||
Abc_TtCopy( Vec_WrdEntryP(vSims, nWords*(i+1)), (word *)Vec_PtrEntry(vTruths, i), nWords, 0 );
|
||||
Vec_PtrFree( vTruths );
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
Gia_ManSimPatSimAnd( p, i, pObj, nWords, vSims );
|
||||
return vSims;
|
||||
}
|
||||
word * Gia_ManDeriveFuncs( Gia_Man_t * p )
|
||||
{
|
||||
int nVars2 = (Gia_ManCiNum(p) + 6)/2;
|
||||
|
|
|
|||
|
|
@ -80,8 +80,9 @@ Gia_Man_t * Gia_StochProcessSingle( Gia_Man_t * p, char * pScript, int Rand, int
|
|||
}
|
||||
return pNew;
|
||||
}
|
||||
void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose )
|
||||
Vec_Int_t * Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int fVerbose )
|
||||
{
|
||||
Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vGias) );
|
||||
Gia_Man_t * pGia, * pNew; int i;
|
||||
Vec_Int_t * vRands = Vec_IntAlloc( Vec_PtrSize(vGias) );
|
||||
Abc_Random(1);
|
||||
|
|
@ -90,10 +91,12 @@ void Gia_StochProcessArray( Vec_Ptr_t * vGias, char * pScript, int TimeSecs, int
|
|||
Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i )
|
||||
{
|
||||
pNew = Gia_StochProcessSingle( pGia, pScript, Vec_IntEntry(vRands, i), TimeSecs );
|
||||
Vec_IntWriteEntry( vGains, i, Gia_ManAndNum(pGia) - Gia_ManAndNum(pNew) );
|
||||
Gia_ManStop( pGia );
|
||||
Vec_PtrWriteEntry( vGias, i, pNew );
|
||||
}
|
||||
Vec_IntFree( vRands );
|
||||
return vGains;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -165,14 +168,14 @@ int Gia_StochProcess1( void * p )
|
|||
return 1;
|
||||
}
|
||||
|
||||
void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose )
|
||||
Vec_Int_t * Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSecs, int fVerbose )
|
||||
{
|
||||
if ( nProcs <= 2 ) {
|
||||
if ( fVerbose )
|
||||
printf( "Running non-concurrent synthesis.\n" ), fflush(stdout);
|
||||
Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose );
|
||||
return;
|
||||
return Gia_StochProcessArray( vGias, pScript, TimeSecs, fVerbose );
|
||||
}
|
||||
Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vGias) );
|
||||
StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vGias) );
|
||||
Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vGias) );
|
||||
Gia_Man_t * pGia; int i;
|
||||
|
|
@ -190,11 +193,13 @@ void Gia_StochProcess( Vec_Ptr_t * vGias, char * pScript, int nProcs, int TimeSe
|
|||
Util_ProcessThreads( Gia_StochProcess1, vData, nProcs, TimeSecs, fVerbose );
|
||||
// replace old AIGs by new AIGs
|
||||
Vec_PtrForEachEntry( Gia_Man_t *, vGias, pGia, i ) {
|
||||
Vec_IntWriteEntry( vGains, i, Gia_ManAndNum(pGia) - Gia_ManAndNum(pData[i].pOut) );
|
||||
Gia_ManStop( pGia );
|
||||
Vec_PtrWriteEntry( vGias, i, pData[i].pOut );
|
||||
}
|
||||
Vec_PtrFree( vData );
|
||||
ABC_FREE( pData );
|
||||
return vGains;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -279,6 +284,428 @@ void Gia_ManStochSynthesis( Vec_Ptr_t * vAigs, char * pScript )
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Gia_ManFilterPartitions( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvNodes, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins, Vec_Int_t * vGains )
|
||||
{
|
||||
int RetValue = Vec_PtrSize(vvIns);
|
||||
Vec_Ptr_t * vvInsNew = Vec_PtrAlloc( 10 );
|
||||
Vec_Ptr_t * vvOutsNew = Vec_PtrAlloc( 10 );
|
||||
Vec_Ptr_t * vvWinsNew = Vec_PtrAlloc( 10 );
|
||||
Gia_ManIncrementTravId( p );
|
||||
while ( 1 ) {
|
||||
int i, Gain, iEntry = Vec_IntArgMax(vGains);
|
||||
if ( iEntry == -1 || Vec_IntEntry(vGains, iEntry) < 0 )
|
||||
break;
|
||||
//printf( "Selecting partition %d with gain %d.\n", iEntry, Vec_IntEntry(vGains, iEntry) );
|
||||
Vec_IntWriteEntry( vGains, iEntry, -1 );
|
||||
Vec_PtrPush( vvInsNew, Vec_IntDup((Vec_Int_t *)Vec_PtrEntry(vvIns, iEntry)) );
|
||||
Vec_PtrPush( vvOutsNew, Vec_IntDup((Vec_Int_t *)Vec_PtrEntry(vvOuts, iEntry)) );
|
||||
Vec_PtrPush( vvWinsNew, Gia_ManDupDfs((Gia_Man_t *)Vec_PtrEntry(vWins, iEntry)) );
|
||||
extern void Gia_ManMarkTfiTfo( Vec_Int_t * vOne, Gia_Man_t * pMan );
|
||||
Gia_ManMarkTfiTfo( (Vec_Int_t *)Vec_PtrEntryLast(vvInsNew), p );
|
||||
Vec_IntForEachEntry( vGains, Gain, i ) {
|
||||
if ( Gain < 0 )
|
||||
continue;
|
||||
Vec_Int_t * vNodes = (Vec_Int_t *)Vec_PtrEntry(vvNodes, i);
|
||||
Gia_Obj_t * pNode; int j;
|
||||
Gia_ManForEachObjVec( vNodes, p, pNode, j )
|
||||
if ( Gia_ObjIsTravIdCurrent(p, pNode) )
|
||||
break;
|
||||
if ( j < Vec_IntSize(vNodes) )
|
||||
Vec_IntWriteEntry( vGains, i, -1 );
|
||||
}
|
||||
}
|
||||
ABC_SWAP( Vec_Ptr_t, *vvInsNew, *vvIns );
|
||||
ABC_SWAP( Vec_Ptr_t, *vvOutsNew, *vvOuts );
|
||||
ABC_SWAP( Vec_Ptr_t, *vvWinsNew, *vWins );
|
||||
Vec_PtrFreeFunc( vvInsNew, (void (*)(void *)) Vec_IntFree );
|
||||
Vec_PtrFreeFunc( vvOutsNew, (void (*)(void *)) Vec_IntFree );
|
||||
Vec_PtrFreeFunc( vvWinsNew, (void (*)(void *)) Gia_ManStop );
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Partitioning.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Gia_ObjDfsMark_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj )
|
||||
{
|
||||
assert( !pObj->fMark0 );
|
||||
if ( Gia_ObjIsTravIdCurrent( pGia, pObj ) )
|
||||
return;
|
||||
Gia_ObjSetTravIdCurrent( pGia, pObj );
|
||||
if ( Gia_ObjIsCi(pObj) )
|
||||
return;
|
||||
assert( Gia_ObjIsAnd(pObj) );
|
||||
Gia_ObjDfsMark_rec( pGia, Gia_ObjFanin0(pObj) );
|
||||
Gia_ObjDfsMark_rec( pGia, Gia_ObjFanin1(pObj) );
|
||||
}
|
||||
void Gia_ObjDfsMark2_rec( Gia_Man_t * pGia, Gia_Obj_t * pObj )
|
||||
{
|
||||
Gia_Obj_t * pFanout; int i;
|
||||
assert( !pObj->fMark0 );
|
||||
if ( Gia_ObjIsTravIdCurrent( pGia, pObj ) )
|
||||
return;
|
||||
Gia_ObjSetTravIdCurrent( pGia, pObj );
|
||||
Gia_ObjForEachFanoutStatic( pGia, pObj, pFanout, i )
|
||||
Gia_ObjDfsMark2_rec( pGia, pFanout );
|
||||
}
|
||||
Vec_Int_t * Gia_ManDeriveWinNodes( Gia_Man_t * pMan, Vec_Int_t * vIns, Vec_Wec_t * vStore )
|
||||
{
|
||||
Vec_Int_t * vLevel, * vNodes = Vec_IntAlloc( 100 );
|
||||
Gia_Obj_t * pObj, * pNext; int i, k, iLevel;
|
||||
Vec_WecForEachLevel( vStore, vLevel, i )
|
||||
Vec_IntClear( vLevel );
|
||||
// mark the TFI cones of the inputs
|
||||
Gia_ManIncrementTravId( pMan );
|
||||
Gia_ManForEachObjVec( vIns, pMan, pObj, i )
|
||||
Gia_ObjDfsMark_rec( pMan, pObj );
|
||||
// add unrelated fanouts of the inputs to storage
|
||||
Gia_ManForEachObjVec( vIns, pMan, pObj, i )
|
||||
Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k )
|
||||
if ( Gia_ObjIsAnd(pNext) && !Gia_ObjIsTravIdCurrent(pMan, pNext) && !pNext->fMark0 ) {
|
||||
pNext->fMark0 = 1;
|
||||
Vec_WecPush( vStore, Gia_ObjLevel(pMan, pNext), Gia_ObjId(pMan, pNext) );
|
||||
}
|
||||
// mark the inputs
|
||||
Gia_ManIncrementTravId( pMan );
|
||||
Gia_ManForEachObjVec( vIns, pMan, pObj, i )
|
||||
Gia_ObjSetTravIdCurrent(pMan, pObj);
|
||||
// collect those fanouts that are completely supported by the inputs
|
||||
Vec_WecForEachLevel( vStore, vLevel, iLevel )
|
||||
Gia_ManForEachObjVec( vLevel, pMan, pObj, i ) {
|
||||
assert( !Gia_ObjIsTravIdCurrent(pMan, pObj) );
|
||||
assert( pObj->fMark0 );
|
||||
pObj->fMark0 = 0;
|
||||
if ( !Gia_ObjIsTravIdCurrent(pMan, Gia_ObjFanin0(pObj)) ||
|
||||
!Gia_ObjIsTravIdCurrent(pMan, Gia_ObjFanin1(pObj)) )
|
||||
continue;
|
||||
Gia_ObjSetTravIdCurrent(pMan, pObj);
|
||||
Vec_IntPush( vNodes, Gia_ObjId(pMan, pObj) );
|
||||
assert( Gia_ObjIsAnd(pObj) );
|
||||
// add fanouts of this node to storage
|
||||
Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k )
|
||||
if ( Gia_ObjIsAnd(pNext) && !Gia_ObjIsTravIdCurrent(pMan, pNext) && !pNext->fMark0 ) {
|
||||
pNext->fMark0 = 1;
|
||||
assert( Gia_ObjLevel(pMan, pNext) > iLevel );
|
||||
Vec_WecPush( vStore, Gia_ObjLevel(pMan, pNext), Gia_ObjId(pMan, pNext) );
|
||||
}
|
||||
}
|
||||
Vec_IntSort( vNodes, 0 );
|
||||
return vNodes;
|
||||
}
|
||||
Vec_Ptr_t * Gia_ManDeriveWinNodesAll( Gia_Man_t * pMan, Vec_Ptr_t * vvIns, Vec_Wec_t * vStore )
|
||||
{
|
||||
Vec_Int_t * vIns; int i;
|
||||
Vec_Ptr_t * vvNodes = Vec_PtrAlloc( Vec_PtrSize(vvIns) );
|
||||
Vec_PtrForEachEntry( Vec_Int_t *, vvIns, vIns, i )
|
||||
Vec_PtrPush( vvNodes, Gia_ManDeriveWinNodes(pMan, vIns, vStore) );
|
||||
return vvNodes;
|
||||
}
|
||||
Vec_Int_t * Gia_ManDeriveWinOuts( Gia_Man_t * pMan, Vec_Int_t * vNodes )
|
||||
{
|
||||
Vec_Int_t * vOuts = Vec_IntAlloc( 100 );
|
||||
Gia_Obj_t * pObj, * pNext; int i, k;
|
||||
// mark the nodes in the window
|
||||
Gia_ManIncrementTravId( pMan );
|
||||
Gia_ManForEachObjVec( vNodes, pMan, pObj, i )
|
||||
Gia_ObjSetTravIdCurrent(pMan, pObj);
|
||||
// collect nodes that have unmarked fanouts
|
||||
Gia_ManForEachObjVec( vNodes, pMan, pObj, i ) {
|
||||
Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k )
|
||||
if ( !Gia_ObjIsTravIdCurrent(pMan, pNext) )
|
||||
break;
|
||||
if ( k < Gia_ObjFanoutNum(pMan, pObj) )
|
||||
Vec_IntPush( vOuts, Gia_ObjId(pMan, pObj) );
|
||||
}
|
||||
if ( Vec_IntSize(vOuts) == 0 )
|
||||
printf( "Window with %d internal nodes has no outputs (are these dangling nodes?).\n", Vec_IntSize(vNodes) );
|
||||
return vOuts;
|
||||
}
|
||||
Vec_Ptr_t * Gia_ManDeriveWinOutsAll( Gia_Man_t * pMan, Vec_Ptr_t * vvNodes )
|
||||
{
|
||||
Vec_Int_t * vNodes; int i;
|
||||
Vec_Ptr_t * vvOuts = Vec_PtrAlloc( Vec_PtrSize(vvNodes) );
|
||||
Vec_PtrForEachEntry( Vec_Int_t *, vvNodes, vNodes, i )
|
||||
Vec_PtrPush( vvOuts, Gia_ManDeriveWinOuts(pMan, vNodes) );
|
||||
return vvOuts;
|
||||
}
|
||||
void Gia_ManPermuteLevel( Gia_Man_t * pMan, int Level )
|
||||
{
|
||||
Gia_Obj_t * pObj, * pNext; int i, k;
|
||||
Gia_ManForEachAnd( pMan, pObj, i ) {
|
||||
int LevelMin = Gia_ObjLevel(pMan, pObj), LevelMax = Level + 1;
|
||||
Gia_ObjForEachFanoutStatic( pMan, pObj, pNext, k )
|
||||
if ( Gia_ObjIsAnd(pNext) )
|
||||
LevelMax = Abc_MinInt( LevelMax, Gia_ObjLevel(pMan, pNext) );
|
||||
if ( LevelMin == LevelMax ) continue;
|
||||
assert( LevelMin < LevelMax );
|
||||
// randomly set level between LevelMin and LevelMax-1
|
||||
Gia_ObjSetLevel( pMan, pObj, LevelMin + (Abc_Random(0) % (LevelMax - LevelMin)) );
|
||||
assert( Gia_ObjLevel(pMan, pObj) < LevelMax );
|
||||
}
|
||||
}
|
||||
Vec_Int_t * Gia_ManCollectObjectsPointedTo( Gia_Man_t * pMan, int Level )
|
||||
{
|
||||
Vec_Int_t * vRes = Vec_IntAlloc( 100 );
|
||||
Gia_Obj_t * pObj, * pFanin; int i, n;
|
||||
Gia_ManIncrementTravId( pMan );
|
||||
Gia_ManForEachAnd( pMan, pObj, i ) {
|
||||
if ( Gia_ObjLevel(pMan, pObj) <= Level )
|
||||
continue;
|
||||
for ( n = 0; n < 2; n++ ) {
|
||||
Gia_Obj_t * pFanin = n ? Gia_ObjFanin1(pObj) : Gia_ObjFanin0(pObj);
|
||||
if ( Gia_ObjLevel(pMan, pFanin) <= Level && !Gia_ObjIsTravIdCurrent(pMan, pFanin) ) {
|
||||
Gia_ObjSetTravIdCurrent(pMan, pFanin);
|
||||
Vec_IntPush( vRes, Gia_ObjId(pMan, pFanin) );
|
||||
}
|
||||
}
|
||||
}
|
||||
Gia_ManForEachCo( pMan, pObj, i ) {
|
||||
pFanin = Gia_ObjFanin0(pObj);
|
||||
if ( Gia_ObjLevel(pMan, pFanin) <= Level && !Gia_ObjIsTravIdCurrent(pMan, pFanin) && Gia_ObjIsAnd(pFanin) ) {
|
||||
Gia_ObjSetTravIdCurrent(pMan, pFanin);
|
||||
Vec_IntPush( vRes, Gia_ObjId(pMan, pFanin) );
|
||||
}
|
||||
}
|
||||
Vec_IntSort( vRes, 0 );
|
||||
return vRes;
|
||||
}
|
||||
Vec_Wec_t * Gia_ManCollectObjectsWithSuppLimit( Gia_Man_t * pMan, int Level, int nSuppMax )
|
||||
{
|
||||
Vec_Wec_t * vResSupps = NULL;
|
||||
Vec_Int_t * vBelow = Gia_ManCollectObjectsPointedTo( pMan, Level );
|
||||
Vec_Wec_t * vSupps = Vec_WecStart( Vec_IntSize(vBelow) );
|
||||
Vec_Int_t * vSuppIds = Vec_IntStartFull( Gia_ManObjNum(pMan) );
|
||||
Vec_Int_t * vTemp = Vec_IntAlloc(100);
|
||||
Gia_Obj_t * pObj; int i, Count = 0;
|
||||
Gia_ManForEachObjVec( vBelow, pMan, pObj, i ) {
|
||||
Vec_IntWriteEntry( vSuppIds, Gia_ObjId(pMan, pObj), i );
|
||||
Vec_IntPush( Vec_WecEntry(vSupps, i), Gia_ObjId(pMan, pObj) );
|
||||
}
|
||||
Gia_ManForEachAnd( pMan, pObj, i ) {
|
||||
if ( Gia_ObjLevel(pMan, pObj) <= Level )
|
||||
continue;
|
||||
int iSuppId0 = Vec_IntEntry( vSuppIds, Gia_ObjFaninId0(pObj, i) );
|
||||
int iSuppId1 = Vec_IntEntry( vSuppIds, Gia_ObjFaninId1(pObj, i) );
|
||||
if ( iSuppId0 == -1 || iSuppId1 == -1 ) {
|
||||
Count++;
|
||||
continue;
|
||||
}
|
||||
Vec_IntClear( vTemp );
|
||||
Vec_IntTwoMerge2( Vec_WecEntry(vSupps, iSuppId0), Vec_WecEntry(vSupps, iSuppId1), vTemp );
|
||||
if ( Vec_IntSize(vTemp) > nSuppMax ) {
|
||||
Count++;
|
||||
continue;
|
||||
}
|
||||
Vec_IntWriteEntry( vSuppIds, i, Vec_WecSize(vSupps) );
|
||||
Vec_IntAppend( Vec_WecPushLevel(vSupps), vTemp );
|
||||
}
|
||||
// remove those supported nodes that are in the TFI cones of others
|
||||
Gia_ManIncrementTravId( pMan );
|
||||
Gia_ManForEachAnd( pMan, pObj, i )
|
||||
if ( Gia_ObjLevel(pMan, pObj) > Level && Vec_IntEntry(vSuppIds, i) >= 0 && !Gia_ObjIsTravIdCurrent(pMan, pObj) ) {
|
||||
Gia_ObjDfsMark_rec(pMan, pObj);
|
||||
Gia_ObjSetTravIdPrevious(pMan, pObj);
|
||||
}
|
||||
// create the result
|
||||
vResSupps = Vec_WecAlloc( 100 );
|
||||
Gia_ManForEachAnd( pMan, pObj, i )
|
||||
if ( Gia_ObjLevel(pMan, pObj) > Level && Vec_IntEntry(vSuppIds, i) >= 0 && !Gia_ObjIsTravIdCurrent(pMan, pObj) ) {
|
||||
Vec_Int_t * vSupp = Vec_WecEntry( vSupps, Vec_IntEntry(vSuppIds, i) );
|
||||
if ( Vec_IntSize(vSupp) < 4 )
|
||||
continue;
|
||||
Vec_Int_t * vThis = Vec_WecPushLevel( vResSupps );
|
||||
Vec_IntGrow( vThis, Vec_IntSize(vSupp) + 1 );
|
||||
Vec_IntAppend( vThis, vSupp );
|
||||
//Vec_IntPush( vThis, Gia_ObjId(pObj) );
|
||||
}
|
||||
//printf( "Inputs = %d. Nodes with %d-support = %d. Nodes with larger support = %d. Selected outputs = %d.\n",
|
||||
// Vec_IntSize(vBelow), nSuppMax, Vec_WecSize(vSupps), Count, Vec_WecSize(vResSupps) );
|
||||
Vec_WecFree( vSupps );
|
||||
Vec_IntFree( vSuppIds );
|
||||
Vec_IntFree( vBelow );
|
||||
Vec_IntFree( vTemp );
|
||||
return vResSupps;
|
||||
}
|
||||
// removes all supports that overlap with this one
|
||||
void Gia_ManSelectRemove( Vec_Wec_t * vSupps, Vec_Int_t * vOne )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i;
|
||||
Vec_WecForEachLevel( vSupps, vLevel, i )
|
||||
if ( Vec_IntTwoCountCommon(vLevel, vOne) > 0 )
|
||||
Vec_IntClear( vLevel );
|
||||
Vec_WecRemoveEmpty( vSupps );
|
||||
}
|
||||
// marks TFI/TFO of this one
|
||||
void Gia_ManMarkTfiTfo( Vec_Int_t * vOne, Gia_Man_t * pMan )
|
||||
{
|
||||
int i; Gia_Obj_t * pObj;
|
||||
Gia_ManForEachObjVec( vOne, pMan, pObj, i ) {
|
||||
//Gia_ObjSetTravIdPrevious(pMan, pObj);
|
||||
//Gia_ObjDfsMark_rec( pMan, pObj );
|
||||
Gia_ObjSetTravIdPrevious(pMan, pObj);
|
||||
Gia_ObjDfsMark2_rec( pMan, pObj );
|
||||
}
|
||||
}
|
||||
// removes all supports that overlap with the TFI/TFO cones of this one
|
||||
void Gia_ManSelectRemove2( Vec_Wec_t * vSupps, Vec_Int_t * vOne, Gia_Man_t * pMan )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k; Gia_Obj_t * pObj;
|
||||
Gia_ManForEachObjVec( vOne, pMan, pObj, i ) {
|
||||
Gia_ObjSetTravIdPrevious(pMan, pObj);
|
||||
Gia_ObjDfsMark_rec( pMan, pObj );
|
||||
Gia_ObjSetTravIdPrevious(pMan, pObj);
|
||||
Gia_ObjDfsMark2_rec( pMan, pObj );
|
||||
}
|
||||
Vec_WecForEachLevel( vSupps, vLevel, i ) {
|
||||
Gia_ManForEachObjVec( vLevel, pMan, pObj, k )
|
||||
if ( Gia_ObjIsTravIdCurrent(pMan, pObj) )
|
||||
break;
|
||||
if ( k < Vec_IntSize(vLevel) )
|
||||
Vec_IntClear( vLevel );
|
||||
}
|
||||
Vec_WecRemoveEmpty( vSupps );
|
||||
}
|
||||
// removes all supports that are contained in this one
|
||||
void Gia_ManSelectRemove3( Vec_Wec_t * vSupps, Vec_Int_t * vOne )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i;
|
||||
Vec_WecForEachLevel( vSupps, vLevel, i )
|
||||
if ( Vec_IntTwoCountCommon(vLevel, vOne) == Vec_IntSize(vLevel) )
|
||||
Vec_IntClear( vLevel );
|
||||
Vec_WecRemoveEmpty( vSupps );
|
||||
}
|
||||
Vec_Ptr_t * Gia_ManDeriveWinInsAll( Vec_Wec_t * vSupps, int nSuppMax, Gia_Man_t * pMan, int fOverlap )
|
||||
{
|
||||
Vec_Ptr_t * vRes = Vec_PtrAlloc( 100 );
|
||||
Gia_ManIncrementTravId( pMan );
|
||||
while ( Vec_WecSize(vSupps) > 0 ) {
|
||||
int i, Item, iRand = Abc_Random(0) % Vec_WecSize(vSupps);
|
||||
Vec_Int_t * vLevel, * vLevel2 = Vec_WecEntry( vSupps, iRand );
|
||||
Vec_Int_t * vCopy = Vec_IntDup( vLevel2 );
|
||||
if ( Vec_IntSize(vLevel2) == nSuppMax ) {
|
||||
Vec_PtrPush( vRes, vCopy );
|
||||
if ( fOverlap )
|
||||
Gia_ManSelectRemove3( vSupps, vCopy );
|
||||
else
|
||||
Gia_ManSelectRemove2( vSupps, vCopy, pMan );
|
||||
continue;
|
||||
}
|
||||
// find another support, which maximizes the union but does not exceed nSuppMax
|
||||
int iBest = iRand, nUnion = Vec_IntSize(vCopy);
|
||||
Vec_WecForEachLevel( vSupps, vLevel, i ) {
|
||||
if ( i == iRand ) continue;
|
||||
int nCommon = Vec_IntTwoCountCommon(vLevel, vCopy);
|
||||
int nUnionCur = Vec_IntSize(vLevel) + Vec_IntSize(vCopy) - nCommon;
|
||||
if ( nUnionCur <= nSuppMax && nUnion < nUnionCur ) {
|
||||
nUnion = nUnionCur;
|
||||
iBest = i;
|
||||
}
|
||||
}
|
||||
vLevel = Vec_WecEntry( vSupps, iBest );
|
||||
Vec_IntForEachEntry( vLevel, Item, i )
|
||||
Vec_IntPushUniqueOrder( vCopy, Item );
|
||||
Vec_PtrPush( vRes, vCopy );
|
||||
if ( fOverlap )
|
||||
Gia_ManSelectRemove3( vSupps, vCopy );
|
||||
else
|
||||
Gia_ManSelectRemove2( vSupps, vCopy, pMan );
|
||||
}
|
||||
return vRes;
|
||||
}
|
||||
Gia_Man_t * Gia_ManDupFromArrays( Gia_Man_t * p, Vec_Int_t * vCis, Vec_Int_t * vAnds, Vec_Int_t * vCos )
|
||||
{
|
||||
Gia_Man_t * pNew;
|
||||
Gia_Obj_t * pObj;
|
||||
int i;
|
||||
pNew = Gia_ManStart( 5000 );
|
||||
pNew->pName = Abc_UtilStrsav( p->pName );
|
||||
pNew->pSpec = Abc_UtilStrsav( p->pSpec );
|
||||
Gia_ManConst0(p)->Value = 0;
|
||||
Gia_ManForEachObjVec( vCis, p, pObj, i )
|
||||
pObj->Value = Gia_ManAppendCi( pNew );
|
||||
Gia_ManForEachObjVec( vAnds, p, pObj, i )
|
||||
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
Gia_ManForEachObjVec( vCos, p, pObj, i )
|
||||
pObj->Value = Gia_ManAppendCo( pNew, pObj->Value );
|
||||
return pNew;
|
||||
}
|
||||
Vec_Ptr_t * Gia_ManDupWindows( Gia_Man_t * pMan, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvNodes, Vec_Ptr_t * vvOuts )
|
||||
{
|
||||
Vec_Int_t * vNodes; int i;
|
||||
Vec_Ptr_t * vWins = Vec_PtrAlloc( Vec_PtrSize(vvIns) );
|
||||
assert( Vec_PtrSize(vvIns) == Vec_PtrSize(vvNodes) );
|
||||
assert( Vec_PtrSize(vvOuts) == Vec_PtrSize(vvNodes) );
|
||||
Gia_ManFillValue( pMan );
|
||||
Gia_ManCleanMark01( pMan );
|
||||
Vec_PtrForEachEntry( Vec_Int_t *, vvNodes, vNodes, i ) {
|
||||
Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i);
|
||||
Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i);
|
||||
Gia_Man_t * pNew = Gia_ManDupFromArrays( pMan, vIns, vNodes, vOuts );
|
||||
Vec_PtrPush( vWins, pNew );
|
||||
}
|
||||
return vWins;
|
||||
}
|
||||
int Gia_ManLevelR( Gia_Man_t * pMan )
|
||||
{
|
||||
int i, LevelMax = Gia_ManLevelRNum( pMan );
|
||||
Gia_Obj_t * pNode;
|
||||
Gia_ManForEachObj( pMan, pNode, i )
|
||||
Gia_ObjSetLevel( pMan, pNode, (int)(LevelMax - Gia_ObjLevel(pMan, pNode) + 1) );
|
||||
Gia_ManForEachCi( pMan, pNode, i )
|
||||
Gia_ObjSetLevel( pMan, pNode, 0 );
|
||||
return LevelMax;
|
||||
}
|
||||
Vec_Ptr_t * Gia_ManExtractPartitions( Gia_Man_t * pMan, int Iter, int nSuppMax, Vec_Ptr_t ** pvIns, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvNodes, int fOverlap )
|
||||
{
|
||||
// if ( Gia_ManCiNum(pMan) <= nSuppMax ) {
|
||||
// Vec_Ptr_t * vWins = Vec_PtrAlloc( 1 );
|
||||
// Vec_PtrPush( vWins, Gia_ManDupDfs(pMan) );
|
||||
// *pvIns = *pvOuts = *pvNodes = NULL;
|
||||
// return vWins;
|
||||
// }
|
||||
// int iUseRevL = Iter % 3 == 0 ? 0 : Abc_Random(0) & 1;
|
||||
int iUseRevL = Abc_Random(0) & 1;
|
||||
int LevelMax = iUseRevL ? Gia_ManLevelR(pMan) : Gia_ManLevelNum(pMan);
|
||||
// int LevelCut = Iter % 3 == 0 ? 0 : LevelMax > 8 ? 2 + (Abc_Random(0) % (LevelMax - 4)) : 0;
|
||||
int LevelCut = LevelMax > 8 ? (Abc_Random(0) % (LevelMax - 4)) : 0;
|
||||
//printf( "Using %s cut level %d (out of %d)\n", iUseRevL ? "reverse": "direct", LevelCut, LevelMax );
|
||||
// Gia_ManPermuteLevel( pMan, LevelMax );
|
||||
Vec_Wec_t * vStore = Vec_WecStart( LevelMax+1 );
|
||||
Vec_Wec_t * vSupps = Gia_ManCollectObjectsWithSuppLimit( pMan, LevelCut, nSuppMax );
|
||||
Vec_Ptr_t * vIns = Gia_ManDeriveWinInsAll( vSupps, nSuppMax, pMan, fOverlap );
|
||||
Vec_Ptr_t * vNodes = Gia_ManDeriveWinNodesAll( pMan, vIns, vStore );
|
||||
Vec_Ptr_t * vOuts = Gia_ManDeriveWinOutsAll( pMan, vNodes );
|
||||
Vec_Ptr_t * vWins = Gia_ManDupWindows( pMan, vIns, vNodes, vOuts );
|
||||
Vec_WecFree( vSupps );
|
||||
Vec_WecFree( vStore );
|
||||
*pvIns = vIns;
|
||||
*pvOuts = vOuts;
|
||||
*pvNodes = vNodes;
|
||||
return vWins;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -358,7 +785,8 @@ Vec_Ptr_t * Gia_ManDupDivide( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds
|
|||
Vec_PtrPush( vAigs, Gia_ManDupDivideOne(p, Vec_WecEntry(vCis, i), Vec_WecEntry(vAnds, i), Vec_WecEntry(vCos, i)) );
|
||||
}
|
||||
//Gia_ManStochSynthesis( vAigs, pScript );
|
||||
Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 );
|
||||
Vec_Int_t * vGains = Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 );
|
||||
Vec_IntFree( vGains );
|
||||
return vAigs;
|
||||
}
|
||||
Gia_Man_t * Gia_ManDupStitch( Gia_Man_t * p, Vec_Wec_t * vCis, Vec_Wec_t * vAnds, Vec_Wec_t * vCos, Vec_Ptr_t * vAigs, int fHash )
|
||||
|
|
@ -554,7 +982,7 @@ Vec_Wec_t * Gia_ManStochOutputs( Gia_Man_t * p, Vec_Wec_t * vAnds )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs )
|
||||
void Gia_ManStochSyn( int nSuppMax, int nMaxSize, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs )
|
||||
{
|
||||
abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0;
|
||||
abctime clkStart = Abc_Clock();
|
||||
|
|
@ -564,43 +992,83 @@ void Gia_ManStochSyn( int nMaxSize, int nIters, int TimeOut, int Seed, int fVerb
|
|||
Abc_Random(1);
|
||||
for ( i = 0; i < 10+Seed; i++ )
|
||||
Abc_Random(0);
|
||||
if ( fVerbose )
|
||||
printf( "Running %d iterations of script \"%s\".\n", nIters, pScript );
|
||||
for ( i = 0; i < nIters; i++ )
|
||||
{
|
||||
abctime clk = Abc_Clock();
|
||||
Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) );
|
||||
Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF );
|
||||
Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds );
|
||||
Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds );
|
||||
Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript, nProcs, TimeOut );
|
||||
Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs );
|
||||
int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew);
|
||||
Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew );
|
||||
if ( fVerbose )
|
||||
printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ",
|
||||
i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia),
|
||||
fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew),
|
||||
fMapped ? "LUTs" : "ANDs" );
|
||||
if ( fVerbose )
|
||||
Abc_PrintTime( 0, "Time", Abc_Clock() - clk );
|
||||
Gia_ManStop( pGia );
|
||||
Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop );
|
||||
Vec_WecFree( vAnds );
|
||||
Vec_WecFree( vIns );
|
||||
Vec_WecFree( vOuts );
|
||||
if ( nTimeToStop && Abc_Clock() > nTimeToStop )
|
||||
if ( fVerbose ) {
|
||||
printf( "Running %d iterations of the script \"%s\"", nIters, pScript );
|
||||
if ( nProcs > 2 )
|
||||
printf( " using %d concurrent threads.\n", nProcs-1 );
|
||||
else
|
||||
printf( " without concurrency.\n" );
|
||||
fflush(stdout);
|
||||
}
|
||||
if ( !nSuppMax ) {
|
||||
for ( i = 0; i < nIters; i++ )
|
||||
{
|
||||
printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i );
|
||||
break;
|
||||
abctime clk = Abc_Clock();
|
||||
Gia_Man_t * pGia = Gia_ManDupWithMapping( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) );
|
||||
Vec_Wec_t * vAnds = Gia_ManStochNodes( pGia, nMaxSize, Abc_Random(0) & 0x7FFFFFFF );
|
||||
Vec_Wec_t * vIns = Gia_ManStochInputs( pGia, vAnds );
|
||||
Vec_Wec_t * vOuts = Gia_ManStochOutputs( pGia, vAnds );
|
||||
Vec_Ptr_t * vAigs = Gia_ManDupDivide( pGia, vIns, vAnds, vOuts, pScript, nProcs, TimeOut );
|
||||
Gia_Man_t * pNew = Gia_ManDupStitchMap( pGia, vIns, vAnds, vOuts, vAigs );
|
||||
int fMapped = Gia_ManHasMapping(pGia) && Gia_ManHasMapping(pNew);
|
||||
Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew );
|
||||
if ( fVerbose )
|
||||
printf( "Iteration %3d : Using %3d partitions. Reducing %6d to %6d %s. ",
|
||||
i, Vec_PtrSize(vAigs), fMapped ? Gia_ManLutNum(pGia) : Gia_ManAndNum(pGia),
|
||||
fMapped ? Gia_ManLutNum(pNew) : Gia_ManAndNum(pNew),
|
||||
fMapped ? "LUTs" : "ANDs" );
|
||||
if ( fVerbose )
|
||||
Abc_PrintTime( 0, "Time", Abc_Clock() - clk );
|
||||
Gia_ManStop( pGia );
|
||||
Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop );
|
||||
Vec_WecFree( vAnds );
|
||||
Vec_WecFree( vIns );
|
||||
Vec_WecFree( vOuts );
|
||||
if ( nTimeToStop && Abc_Clock() > nTimeToStop )
|
||||
{
|
||||
printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
int fOverlap = 1;
|
||||
Vec_Ptr_t * vIns = NULL, * vOuts = NULL, * vNodes = NULL;
|
||||
for ( i = 0; i < nIters; i++ )
|
||||
{
|
||||
extern Gia_Man_t * Gia_ManDupInsertWindows( Gia_Man_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vAigs );
|
||||
abctime clk = Abc_Clock();
|
||||
Gia_Man_t * pGia = Gia_ManDup( Abc_FrameReadGia(Abc_FrameGetGlobalFrame()) ); Gia_ManStaticFanoutStart(pGia);
|
||||
Vec_Ptr_t * vAigs = Gia_ManExtractPartitions( pGia, i, nSuppMax, &vIns, &vOuts, &vNodes, fOverlap );
|
||||
Vec_Int_t * vGains = Gia_StochProcess( vAigs, pScript, nProcs, TimeOut, 0 );
|
||||
int nPartsInit = fOverlap ? Gia_ManFilterPartitions( pGia, vIns, vNodes, vOuts, vAigs, vGains ) : Vec_PtrSize(vIns);
|
||||
Gia_Man_t * pNew = Gia_ManDupInsertWindows( pGia, vIns, vOuts, vAigs ); Gia_ManStaticFanoutStop(pGia);
|
||||
Abc_FrameUpdateGia( Abc_FrameGetGlobalFrame(), pNew );
|
||||
if ( fVerbose )
|
||||
printf( "Iteration %3d : Using %3d -> %3d partitions. Reducing node count from %6d to %6d. ",
|
||||
i, nPartsInit, Vec_PtrSize(vAigs), Gia_ManAndNum(pGia), Gia_ManAndNum(pNew) );
|
||||
if ( fVerbose )
|
||||
Abc_PrintTime( 0, "Time", Abc_Clock() - clk );
|
||||
// cleanup
|
||||
Gia_ManStop( pGia );
|
||||
Vec_PtrFreeFunc( vAigs, (void (*)(void *)) Gia_ManStop );
|
||||
Vec_IntFreeP( &vGains );
|
||||
if ( vIns ) Vec_PtrFreeFunc( vIns, (void (*)(void *)) Vec_IntFree );
|
||||
if ( vOuts ) Vec_PtrFreeFunc( vOuts, (void (*)(void *)) Vec_IntFree );
|
||||
if ( vNodes ) Vec_PtrFreeFunc( vNodes, (void (*)(void *)) Vec_IntFree );
|
||||
if ( nTimeToStop && Abc_Clock() > nTimeToStop )
|
||||
{
|
||||
printf( "Runtime limit (%d sec) is reached after %d iterations.\n", TimeOut, i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
fMapped &= Gia_ManHasMapping(Abc_FrameReadGia(Abc_FrameGetGlobalFrame()));
|
||||
nLutEnd = fMapped ? Gia_ManLutNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame())) : 0;
|
||||
nEnd = Gia_ManAndNum(Abc_FrameReadGia(Abc_FrameGetGlobalFrame()));
|
||||
if ( fVerbose )
|
||||
printf( "Cumulatively reduced %d %s after %d iterations. ",
|
||||
fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "ANDs", nIters );
|
||||
printf( "Cumulatively reduced %d %s (%.2f %%) after %d iterations. ",
|
||||
fMapped ? nLutBeg - nLutEnd : nBeg - nEnd, fMapped ? "LUTs" : "nodes", 100.0*(nBeg - nEnd)/Abc_MaxInt(nBeg, 1), nIters );
|
||||
if ( fVerbose )
|
||||
Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1067,6 +1067,27 @@ int Gia_ManVerifyWithBoxes( Gia_Man_t * pGia, int nBTLimit, int nTimeLim, int fS
|
|||
return Status;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Gia_ManDeriveBoxMapping( Gia_Man_t * pGia )
|
||||
{
|
||||
Tim_Man_t * pTim = (Tim_Man_t *)pGia->pManTime;
|
||||
Vec_Int_t * vRes = Vec_IntAlloc( 100 );
|
||||
int i, nBoxes = Tim_ManBoxNum( pTim );
|
||||
for ( i = 0; i < nBoxes; i++ )
|
||||
Vec_IntPush( vRes, Tim_ManBoxCopy(pTim, i) );
|
||||
return vRes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -755,6 +755,7 @@ extern ABC_DLL void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk );
|
|||
extern ABC_DLL void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk );
|
||||
extern ABC_DLL void Abc_NtkAddDummyBoxNames( Abc_Ntk_t * pNtk );
|
||||
extern ABC_DLL void Abc_NtkShortNames( Abc_Ntk_t * pNtk );
|
||||
extern ABC_DLL void Abc_NtkCharNames( Abc_Ntk_t * pNtk );
|
||||
extern ABC_DLL void Abc_NtkCleanNames( Abc_Ntk_t * pNtk );
|
||||
extern ABC_DLL void Abc_NtkStartNameIds( Abc_Ntk_t * p );
|
||||
extern ABC_DLL void Abc_NtkTransferNameIds( Abc_Ntk_t * p, Abc_Ntk_t * pNew );
|
||||
|
|
|
|||
|
|
@ -125,6 +125,12 @@ char * Abc_ObjNameDummy( char * pPrefix, int Num, int nDigits )
|
|||
sprintf( Buffer, "%s%0*d", pPrefix, nDigits, Num );
|
||||
return Buffer;
|
||||
}
|
||||
char * Abc_ObjNameChar( int Num, int fCap )
|
||||
{
|
||||
static char Buffer[2000];
|
||||
sprintf( Buffer, "%c", (fCap ? 'A':'a') + Num );
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -494,6 +500,12 @@ void Abc_NtkAddDummyPiNames( Abc_Ntk_t * pNtk )
|
|||
Abc_NtkForEachPi( pNtk, pObj, i )
|
||||
Abc_ObjAssignName( pObj, Abc_ObjNameDummy("pi", i, nDigits), NULL );
|
||||
}
|
||||
void Abc_NtkAddCharPiNames( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i;
|
||||
Abc_NtkForEachPi( pNtk, pObj, i )
|
||||
Abc_ObjAssignName( pObj, Abc_ObjNameChar(i, 0), NULL );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -514,6 +526,12 @@ void Abc_NtkAddDummyPoNames( Abc_Ntk_t * pNtk )
|
|||
Abc_NtkForEachPo( pNtk, pObj, i )
|
||||
Abc_ObjAssignName( pObj, Abc_ObjNameDummy("po", i, nDigits), NULL );
|
||||
}
|
||||
void Abc_NtkAddCharPoNames( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i;
|
||||
Abc_NtkForEachPo( pNtk, pObj, i )
|
||||
Abc_ObjAssignName( pObj, Abc_ObjNameChar(i, 1), NULL );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -606,6 +624,14 @@ void Abc_NtkShortNames( Abc_Ntk_t * pNtk )
|
|||
Abc_NtkAddDummyPoNames( pNtk );
|
||||
Abc_NtkAddDummyBoxNames( pNtk );
|
||||
}
|
||||
void Abc_NtkCharNames( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Nm_ManFree( pNtk->pManName );
|
||||
pNtk->pManName = Nm_ManCreate( Abc_NtkCiNum(pNtk) + Abc_NtkCoNum(pNtk) + Abc_NtkBoxNum(pNtk) );
|
||||
Abc_NtkAddCharPiNames( pNtk );
|
||||
Abc_NtkAddCharPoNames( pNtk );
|
||||
Abc_NtkAddDummyBoxNames( pNtk );
|
||||
}
|
||||
void Abc_NtkCleanNames( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pObj; int i;
|
||||
|
|
|
|||
|
|
@ -96,6 +96,52 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan
|
|||
pNtk->AndGateDelay = 0.0;
|
||||
return pNtk;
|
||||
}
|
||||
Abc_Ntk_t * Abc_NtkAllocBdd( Abc_NtkType_t Type, Abc_NtkFunc_t Func, int fUseMemMan, int nVars )
|
||||
{
|
||||
Abc_Ntk_t * pNtk;
|
||||
pNtk = ABC_ALLOC( Abc_Ntk_t, 1 );
|
||||
memset( pNtk, 0, sizeof(Abc_Ntk_t) );
|
||||
pNtk->ntkType = Type;
|
||||
pNtk->ntkFunc = Func;
|
||||
// start the object storage
|
||||
pNtk->vObjs = Vec_PtrAlloc( 100 );
|
||||
pNtk->vPios = Vec_PtrAlloc( 100 );
|
||||
pNtk->vPis = Vec_PtrAlloc( 100 );
|
||||
pNtk->vPos = Vec_PtrAlloc( 100 );
|
||||
pNtk->vCis = Vec_PtrAlloc( 100 );
|
||||
pNtk->vCos = Vec_PtrAlloc( 100 );
|
||||
pNtk->vBoxes = Vec_PtrAlloc( 100 );
|
||||
pNtk->vLtlProperties = Vec_PtrAlloc( 100 );
|
||||
// start the memory managers
|
||||
pNtk->pMmObj = fUseMemMan? Mem_FixedStart( sizeof(Abc_Obj_t) ) : NULL;
|
||||
pNtk->pMmStep = fUseMemMan? Mem_StepStart( ABC_NUM_STEPS ) : NULL;
|
||||
// get ready to assign the first Obj ID
|
||||
pNtk->nTravIds = 1;
|
||||
// start the functionality manager
|
||||
if ( !Abc_NtkIsStrash(pNtk) )
|
||||
Vec_PtrPush( pNtk->vObjs, NULL );
|
||||
if ( Abc_NtkIsStrash(pNtk) )
|
||||
pNtk->pManFunc = Abc_AigAlloc( pNtk );
|
||||
else if ( Abc_NtkHasSop(pNtk) || Abc_NtkHasBlifMv(pNtk) )
|
||||
pNtk->pManFunc = Mem_FlexStart();
|
||||
#ifdef ABC_USE_CUDD
|
||||
else if ( Abc_NtkHasBdd(pNtk) )
|
||||
pNtk->pManFunc = Cudd_Init( nVars, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
|
||||
#endif
|
||||
else if ( Abc_NtkHasAig(pNtk) )
|
||||
pNtk->pManFunc = Hop_ManStart();
|
||||
else if ( Abc_NtkHasMapping(pNtk) )
|
||||
pNtk->pManFunc = Abc_FrameReadLibGen();
|
||||
else if ( !Abc_NtkHasBlackbox(pNtk) )
|
||||
assert( 0 );
|
||||
// name manager
|
||||
pNtk->pManName = Nm_ManCreate( 200 );
|
||||
// attribute manager
|
||||
pNtk->vAttrs = Vec_PtrStart( VEC_ATTR_TOTAL_NUM );
|
||||
// estimated AndGateDelay
|
||||
pNtk->AndGateDelay = 0.0;
|
||||
return pNtk;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -118,7 +164,7 @@ Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_
|
|||
// decide whether to copy the names
|
||||
fCopyNames = ( Type != ABC_NTK_NETLIST );
|
||||
// start the network
|
||||
pNtkNew = Abc_NtkAlloc( Type, Func, 1 );
|
||||
pNtkNew = Func == ABC_FUNC_BDD ? Abc_NtkAllocBdd( Type, Func, 1, Abc_NtkCiNum(pNtk) ) : Abc_NtkAlloc( Type, Func, 1 );
|
||||
pNtkNew->nConstrs = pNtk->nConstrs;
|
||||
pNtkNew->nBarBufs = pNtk->nBarBufs;
|
||||
// duplicate the name and the spec
|
||||
|
|
@ -1518,6 +1564,24 @@ void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk )
|
|||
return;
|
||||
|
||||
// special case
|
||||
pNet = Abc_NtkFindNet( pNtk, "$false" );
|
||||
if ( pNet != NULL && !Abc_ObjFaninNum(pNet) )
|
||||
{
|
||||
pNode = Abc_NtkCreateNodeConst0( pNtk );
|
||||
Abc_ObjAddFanin( pNet, pNode );
|
||||
}
|
||||
pNet = Abc_NtkFindNet( pNtk, "$undef" );
|
||||
if ( pNet != NULL && !Abc_ObjFaninNum(pNet) )
|
||||
{
|
||||
pNode = Abc_NtkCreateNodeConst0( pNtk );
|
||||
Abc_ObjAddFanin( pNet, pNode );
|
||||
}
|
||||
pNet = Abc_NtkFindNet( pNtk, "$true" );
|
||||
if ( pNet != NULL && !Abc_ObjFaninNum(pNet) )
|
||||
{
|
||||
pNode = Abc_NtkCreateNodeConst1( pNtk );
|
||||
Abc_ObjAddFanin( pNet, pNode );
|
||||
}
|
||||
pNet = Abc_NtkFindNet( pNtk, "[_c1_]" );
|
||||
if ( pNet != NULL )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1131,6 +1131,8 @@ Vec_Ptr_t * Abc_SopFromTruthsHex( char * pTruth )
|
|||
char * pToken = strtok( pCopy, " \r\n\t|" );
|
||||
while ( pToken )
|
||||
{
|
||||
if ( pToken[0] == '0' && pToken[1] == 'x' )
|
||||
pToken += 2;
|
||||
if ( !Abc_SopCheckReadTruth( vRes, pToken, 1 ) )
|
||||
break;
|
||||
Vec_PtrPush( vRes, Abc_SopFromTruthHex(pToken) );
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -117,10 +117,222 @@ Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVer
|
|||
return pNtkNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_LutBddTestPrint( DdManager * dd, Vec_Ptr_t * vNodes, Vec_Wrd_t * vMasks, char ** ppNames, int nNames )
|
||||
{
|
||||
DdNode * node; int i, k;
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i )
|
||||
{
|
||||
if (Cudd_IsConstant(node))
|
||||
printf("ID = %2d value = %d ", (int)node->Id, (int)Cudd_V(node) );
|
||||
else
|
||||
printf("ID = %2d level = %2d index = %2d (%s) cof0 = %2d Cof1 = %2d r = %u ",
|
||||
(int)node->Id, Cudd_ReadPerm(dd, node->index), (int)node->index, ppNames[node->index], (int)Cudd_E(node)->Id, (int)Cudd_T(node)->Id, (int)node->ref);
|
||||
if ( Cudd_ReadPerm(dd, node->index) == 0 ) {
|
||||
printf( "\n" );
|
||||
continue;
|
||||
}
|
||||
word Mask = Vec_WrdEntry(vMasks, (int)node->Id);
|
||||
for ( k = 0; k < nNames; k++ ) {
|
||||
if ( Cudd_ReadPerm(dd, k) >= (int)node->index )
|
||||
continue;
|
||||
int Val = (((Mask >> Abc_Var2Lit(k, 0)) & 1) << 1) | ((Mask >> Abc_Var2Lit(k, 1)) & 1);
|
||||
if ( Val == 1 )
|
||||
printf( "%c%s", '-', ppNames[k] );
|
||||
else if ( Val == 2 )
|
||||
printf( "%c%s", '+', ppNames[k] );
|
||||
else if ( Val == 3 )
|
||||
printf( "**" );
|
||||
else if ( Val == 0 )
|
||||
printf( "??" );
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
DdManager * s_ddd = NULL;
|
||||
int Abc_LutBddCompare( DdNode ** pp1, DdNode ** pp2 )
|
||||
{
|
||||
DdNode * pObj1 = *pp1;
|
||||
DdNode * pObj2 = *pp2;
|
||||
return Cudd_ReadPerm(s_ddd, pObj1->index) - Cudd_ReadPerm(s_ddd, pObj2->index);
|
||||
}
|
||||
void Abc_LutBddTest( DdManager * dd, DdNode * bFunc, char ** ppNames, int nNames, int nVars )
|
||||
{
|
||||
DdGen *gen; DdNode *node;
|
||||
Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 );
|
||||
Cudd_ForeachNode(dd,bFunc,gen,node)
|
||||
Vec_PtrPush( vNodes, node );
|
||||
|
||||
s_ddd = dd;
|
||||
Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_LutBddCompare );
|
||||
s_ddd = NULL;
|
||||
|
||||
int i, k, f;
|
||||
Vec_Int_t * vLevels = Vec_IntAlloc( Vec_PtrSize(vNodes) );
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) {
|
||||
node->Id = i;
|
||||
Vec_IntPush( vLevels, Cudd_ReadPerm(dd, node->index) );
|
||||
}
|
||||
assert( Vec_IntSize(vLevels) == Vec_PtrSize(vNodes) );
|
||||
|
||||
printf( "Size = %d. Fanins = %d. Vars = %d. Nodes = %d.\n", dd->size, nNames, nVars, Vec_PtrSize(vNodes) );
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i )
|
||||
{
|
||||
if (Cudd_IsConstant(node))
|
||||
printf("ID = %2d value = %d\n", (int)node->Id, (int)Cudd_V(node) );
|
||||
else
|
||||
printf("ID = %2d level = %2d index = %2d (%s) cof0 = %2d Cof1 = %2d r = %u\n",
|
||||
(int)node->Id, Cudd_ReadPerm(dd, node->index), (int)node->index, ppNames[node->index], (int)Cudd_E(node)->Id, (int)Cudd_T(node)->Id, (int)node->ref);
|
||||
}
|
||||
|
||||
Vec_Wec_t * vCofs = Vec_WecStart( nNames+1 );
|
||||
Vec_WecPush( vCofs, 0, 0 );
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) {
|
||||
if ( Cudd_IsConstant(node) )
|
||||
continue;
|
||||
DdNode * pFans[2] = { Cudd_E(node), Cudd_T(node) };
|
||||
int LevelStart = Vec_IntEntry(vLevels, (int)node->Id);
|
||||
for ( f = 0; f < 2; f++ ) {
|
||||
int Level = Cudd_IsConstant(pFans[f]) ? nNames : Vec_IntEntry(vLevels, (int)pFans[f]->Id);
|
||||
for ( k = LevelStart; k < Level; k++ )
|
||||
Vec_WecPushUnique( vCofs, k+1, pFans[f]->Id );
|
||||
}
|
||||
}
|
||||
Vec_WecPrint( vCofs, 0 );
|
||||
|
||||
assert( nNames < 32 );
|
||||
Vec_Wrd_t * vMasks = Vec_WrdStart( Vec_PtrSize(vNodes) );
|
||||
Vec_Int_t * vLevel; int n, Obj;
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i ) {
|
||||
if ( i == Vec_WecSize(vCofs)-1 )
|
||||
break;
|
||||
|
||||
//printf( "Level %2d : ", i );
|
||||
//Vec_IntPrint( vLevel );
|
||||
printf( "Level %2d : ", i );
|
||||
for ( k = 0; k < nNames; k++ ) {
|
||||
if ( Cudd_ReadPerm(dd, k) >= i )
|
||||
continue;
|
||||
int Counts[2] = {0};
|
||||
for ( f = 0; f < 2; f++ )
|
||||
Vec_IntForEachEntry(vLevel, Obj, n)
|
||||
if ( (Vec_WrdEntry(vMasks, Obj) >> Abc_Var2Lit(k, !f)) & 1 )
|
||||
Counts[f]++;
|
||||
printf( "%s(%d:%d) ", ppNames[k], Counts[0], Counts[1] );
|
||||
}
|
||||
printf( "\n" );
|
||||
|
||||
Vec_IntForEachEntry( vLevel, Obj, n )
|
||||
{
|
||||
DdNode * node = (DdNode *)Vec_PtrEntry( vNodes, Obj );
|
||||
if ( Cudd_IsConstant(node) )
|
||||
continue;
|
||||
DdNode * pFans[2] = { Cudd_E(node), Cudd_T(node) };
|
||||
word * pMask = Vec_WrdEntryP( vMasks, (int)node->Id );
|
||||
int LevelStart = Vec_IntEntry(vLevels, (int)node->Id);
|
||||
assert( LevelStart >= i );
|
||||
if ( LevelStart > i )
|
||||
continue;
|
||||
for ( f = 0; f < 2; f++ ) {
|
||||
int Level = Cudd_IsConstant(pFans[f]) ? nNames : Vec_IntEntry(vLevels, (int)pFans[f]->Id);
|
||||
word * pMaskFan = Vec_WrdEntryP( vMasks, (int)pFans[f]->Id );
|
||||
*pMaskFan |= *pMask | ((word)1 << Abc_Var2Lit((int)node->index, !f));
|
||||
for ( k = LevelStart+1; k < Level; k++ ) {
|
||||
*pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 0));
|
||||
*pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Abc_LutBddTestPrint( dd, vNodes, vMasks, ppNames, nNames );
|
||||
}
|
||||
|
||||
/*
|
||||
assert( nNames < 32 );
|
||||
Vec_Wrd_t * vMasks = Vec_WrdStart( Count );
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i ) {
|
||||
if ( Cudd_IsConstant(node) )
|
||||
continue;
|
||||
DdNode * pFans[2] = { Cudd_E(node), Cudd_T(node) };
|
||||
word * pMask = Vec_WrdEntryP( vMasks, (int)node->Id );
|
||||
int LevelStart = Vec_IntEntry(vLevels, (int)node->Id);
|
||||
for ( f = 0; f < 2; f++ ) {
|
||||
int Level = Cudd_IsConstant(pFans[f]) ? nNames : Vec_IntEntry(vLevels, (int)pFans[f]->Id);
|
||||
word * pMaskFan = Vec_WrdEntryP( vMasks, (int)pFans[f]->Id );
|
||||
*pMaskFan |= *pMask | ((word)1 << Abc_Var2Lit((int)node->index, !f));
|
||||
for ( k = LevelStart+1; k < Level; k++ ) {
|
||||
*pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 0));
|
||||
*pMaskFan |= ((word)1 << Abc_Var2Lit(Cudd_ReadInvPerm(dd, k), 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i )
|
||||
{
|
||||
if (Cudd_IsConstant(node))
|
||||
printf("ID = %2d value = %d ", (int)node->Id, (int)Cudd_V(node) );
|
||||
else
|
||||
printf("ID = %2d level = %2d index = %2d (%s) cof0 = %2d Cof1 = %2d r = %u ",
|
||||
(int)node->Id, Cudd_ReadPerm(dd, node->index), (int)node->index, ppNames[node->index], (int)Cudd_E(node)->Id, (int)Cudd_T(node)->Id, (int)node->ref);
|
||||
if ( Cudd_ReadPerm(dd, node->index) == 0 ) {
|
||||
printf( "\n" );
|
||||
continue;
|
||||
}
|
||||
word Mask = Vec_WrdEntry(vMasks, (int)node->Id);
|
||||
for ( k = 0; k < nNames; k++ ) {
|
||||
if ( Cudd_ReadPerm(dd, k) >= (int)node->index )
|
||||
continue;
|
||||
int Val = (((Mask >> Abc_Var2Lit(k, 0)) & 1) << 1) | ((Mask >> Abc_Var2Lit(k, 1)) & 1);
|
||||
if ( Val == 1 )
|
||||
printf( "%c%s", '-', ppNames[k] );
|
||||
else if ( Val == 2 )
|
||||
printf( "%c%s", '+', ppNames[k] );
|
||||
else if ( Val == 3 )
|
||||
printf( "**" );
|
||||
else if ( Val == 0 )
|
||||
printf( "??" );
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
Vec_Int_t * vLevel; int n, Obj;
|
||||
Vec_WecForEachLevelStart( vCofs, vLevel, i, 1 ) {
|
||||
printf( "Level %2d : ", i );
|
||||
for ( k = 0; k < nNames; k++ ) {
|
||||
if ( Cudd_ReadPerm(dd, k) >= i )
|
||||
continue;
|
||||
int Counts[2] = {0};
|
||||
for ( f = 0; f < 2; f++ )
|
||||
Vec_IntForEachEntry(vLevel, Obj, n)
|
||||
if ( (Vec_WrdEntry(vMasks, Obj) >> Abc_Var2Lit(k, !f)) & 1 )
|
||||
Counts[f]++;
|
||||
printf( "%s(%d:%d) ", ppNames[k], Counts[0], Counts[1] );
|
||||
}
|
||||
printf( "\n" );
|
||||
}
|
||||
*/
|
||||
|
||||
Vec_IntFree( vLevels );
|
||||
Vec_WecFree( vCofs );
|
||||
Vec_PtrFree( vNodes );
|
||||
Vec_WrdFree( vMasks );
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
Abc_Ntk_t * Abc_NtkCascade( Abc_Ntk_t * pNtk, int nLutSize, int fCheck, int fVerbose ) { return NULL; }
|
||||
word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose ) { return NULL; }
|
||||
word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nStages, int nRails, int nIters, int fVerbose ) { return NULL; }
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -171,25 +383,33 @@ word * Abc_LutCascadeGenTest()
|
|||
pLuts[11+7] = ABC_CONST(0xFFFEFFFEFFFEFFFE);
|
||||
return pLuts;
|
||||
}
|
||||
void Abc_LutCascadePrintLut( word * pLuts, int n, int i )
|
||||
char Abc_LutCascadeChar( int iVar, int nVars )
|
||||
{
|
||||
if ( iVar < nVars )
|
||||
return 'a'+iVar;
|
||||
return 'A'+(iVar-nVars);
|
||||
}
|
||||
void Abc_LutCascadePrintLut( word * pLuts, int n, int i, int nLutSize, int nVars )
|
||||
{
|
||||
word nIns = pLuts[i+1];
|
||||
word * pIns = pLuts+i+2;
|
||||
word * pT = pLuts+i+2+nIns+1;
|
||||
word * pT = pLuts+i+2+nIns+1; int k;
|
||||
printf( "LUT%d : ", n );
|
||||
printf( "%c = F( ", 'a'+(int)pIns[nIns] );
|
||||
for ( int k = 0; k < nIns; k++ )
|
||||
printf( "%c ", 'a'+(int)pIns[k] );
|
||||
printf( ") " );
|
||||
printf( "%c = { ", Abc_LutCascadeChar((int)pIns[nIns], nVars) );
|
||||
for ( k = nLutSize-1; k >= nIns; k-- )
|
||||
printf( " " );
|
||||
for ( k = nIns-1; k >= 0; k-- )
|
||||
printf( "%c ", Abc_LutCascadeChar((int)pIns[k], nVars) );
|
||||
printf( "} " );
|
||||
Abc_TtPrintHexRev( stdout, pT, nIns );
|
||||
printf( "\n" );
|
||||
}
|
||||
void Abc_LutCascadePrint( word * pLuts )
|
||||
void Abc_LutCascadePrint( word * pLuts, int nLutSize )
|
||||
{
|
||||
int n, i;
|
||||
int n, i, nVars = pLuts[3+pLuts[2]];
|
||||
printf( "The LUT cascade contains %d LUTs:\n", (int)pLuts[0] );
|
||||
for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] )
|
||||
Abc_LutCascadePrintLut( pLuts, n, i );
|
||||
Abc_LutCascadePrintLut( pLuts, n, i, nLutSize, nVars );
|
||||
}
|
||||
void Abc_LutCascadeGenOne( Vec_Wrd_t * vRes, int nIns, int * pIns, int Out, word * p )
|
||||
{
|
||||
|
|
@ -290,7 +510,7 @@ word * Abc_LutCascadeTruth( word * pLuts, int nVars )
|
|||
word nIns = pLuts[i+1];
|
||||
word * pIns = pLuts+i+2;
|
||||
word * pT = pLuts+i+2+nIns+1;
|
||||
assert( pLuts[i] == 3+nIns+Abc_TtWordNum(nIns) );
|
||||
//assert( pLuts[i] == 3+nIns+Abc_TtWordNum(nIns) );
|
||||
assert( pIns[nIns] < nVars+pLuts[0] );
|
||||
word * pIn[30], * pOut = Vec_WrdEntryP( vFuncs, nWords*pIns[nIns] );
|
||||
for ( v = 0; v < nIns; v++ )
|
||||
|
|
@ -310,6 +530,26 @@ word * Abc_LutCascadeTruth( word * pLuts, int nVars )
|
|||
Vec_WrdFree( vFuncs );
|
||||
return pRes;
|
||||
}
|
||||
void Abc_LutCascadeMinBase( word * pLuts, int nVars )
|
||||
{
|
||||
int i, n, v, pFans[32];
|
||||
for ( n = 0, i = 1; n < pLuts[0]; n++, i += pLuts[i] )
|
||||
{
|
||||
word nIns = pLuts[i+1];
|
||||
word * pIns = pLuts+i+2;
|
||||
word * pT = pLuts+i+2+nIns+1;
|
||||
assert( pLuts[i] == 3+nIns+Abc_TtWordNum(nIns) );
|
||||
assert( pIns[nIns] < nVars+pLuts[0] );
|
||||
for ( v = 0; v < nIns; v++ )
|
||||
pFans[v] = (int)pIns[v];
|
||||
int nFans = Abc_TtMinBase( pT, pFans, (int)nIns, (int)nIns );
|
||||
pLuts[i+1] = (word)nFans;
|
||||
for ( v = 0; v < nFans; v++ )
|
||||
pIns[v] = (word)pFans[v];
|
||||
pIns[nFans] = pIns[nIns];
|
||||
memcpy( pLuts+i+2+nFans+1, pT, sizeof(word)*Abc_TtWordNum(nFans) );
|
||||
}
|
||||
}
|
||||
int Abc_LutCascadeCount( word * pLuts )
|
||||
{
|
||||
return (int)pLuts[0];
|
||||
|
|
@ -317,7 +557,7 @@ int Abc_LutCascadeCount( word * pLuts )
|
|||
word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose )
|
||||
{
|
||||
word * pLuts = Abc_LutCascadeGenTest();
|
||||
Abc_LutCascadePrint( pLuts );
|
||||
Abc_LutCascadePrint( pLuts, nLutSize );
|
||||
return pLuts;
|
||||
}
|
||||
|
||||
|
|
@ -434,7 +674,7 @@ void Abc_LutCascadeDerive( word * p, int nVars, int nBVars, int Myu, word * pRem
|
|||
Abc_TtSetBit(pDec+e*nStep, m);
|
||||
}
|
||||
//printf( "\n" );
|
||||
assert( nFuncs <= Myu );
|
||||
//assert( nFuncs <= Myu );
|
||||
iFunc = nFuncs-1;
|
||||
for ( m = nFuncs; m < (1 << nEVars); m++ )
|
||||
Abc_TtCopy( pRem+m*nFWords, pRem+iFunc*nFWords, nFWords, 0 );
|
||||
|
|
@ -444,18 +684,11 @@ void Abc_LutCascadeDerive( word * p, int nVars, int nBVars, int Myu, word * pRem
|
|||
}
|
||||
|
||||
// performs decomposition of one stage
|
||||
static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * vFuncs[3], Vec_Int_t * vVarIDs, int nRVars, int nRails, int nLutSize, int fVerbose, Vec_Wrd_t * vCas )
|
||||
static inline int Abc_LutCascadeDecStage( word Guide0, char * pGuide, int Iter, Vec_Wrd_t * vFuncs[3], Vec_Int_t * vVarIDs, int nRVars, int nRails, int nLutSize, int nZParam, int fVerbose, Vec_Wrd_t * vCas, int * pMyu )
|
||||
{
|
||||
extern word Abc_TtFindBVarsSVars( word * p, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose );
|
||||
assert( Vec_IntSize(vVarIDs) > nLutSize );
|
||||
assert( Vec_IntSize(vVarIDs) <= 24 );
|
||||
word Guide = pGuide ? 0 : Abc_TtFindBVarsSVars( Vec_WrdArray(vFuncs[0]), Vec_IntSize(vVarIDs), nRVars, nRails, nLutSize, fVerbose );
|
||||
if ( !pGuide && !Guide ) {
|
||||
if ( fVerbose )
|
||||
printf( "The function is not decomposable with %d rails.\n", nRails );
|
||||
Vec_IntClear( vVarIDs );
|
||||
return -1;
|
||||
}
|
||||
word Guide = pGuide ? 0 : Guide0;
|
||||
int m, Myu = pGuide ? 1 << nRails : (Guide >> 48) & 0xFF;
|
||||
int nEVars = Abc_Base2Log(Myu);
|
||||
int nVars = Vec_IntSize(vVarIDs);
|
||||
|
|
@ -504,21 +737,61 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v
|
|||
Vec_IntShrink( vVarIDs, nFVars+nSVars+nEVars );
|
||||
return nEVars;
|
||||
}
|
||||
word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int fVerbose )
|
||||
|
||||
typedef struct Abc_BSEval_t_ Abc_BSEval_t;
|
||||
extern Abc_BSEval_t * Abc_BSEvalAlloc();
|
||||
extern void Abc_BSEvalFree( Abc_BSEval_t * p );
|
||||
|
||||
word * Abc_LutCascadeDec( Abc_BSEval_t * p, char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int nStages, int fUseRand, int nZParam, int fXRail, int fVerbose, int * pnStages, int * pMyu, int nSubsets, int nBest )
|
||||
{
|
||||
extern Vec_Wrd_t * Abc_TtFindBVarsSVars2( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nRails, int nLutSize, int fVerbose, int * pMyu, int nMyuIncrease, int nSubsets, int nBest );
|
||||
word * pRes = NULL; int i, nRVars = 0, nVars = Vec_IntSize(vVarIDs);
|
||||
Vec_Wrd_t * vFuncs[3] = { Vec_WrdStart(Abc_TtWordNum(nVars)), Vec_WrdAlloc(0), Vec_WrdAlloc(0) };
|
||||
Abc_TtCopy( Vec_WrdArray(vFuncs[0]), pTruth, Abc_TtWordNum(nVars), 0 );
|
||||
Vec_Wrd_t * vCas = Vec_WrdAlloc( 100 ); Vec_WrdPush( vCas, nVarsOrig );
|
||||
if ( pnStages ) *pnStages = 0;
|
||||
for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ ) {
|
||||
nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas );
|
||||
if ( nRVars == -1 )
|
||||
int nRVarsOld = nRVars;
|
||||
Vec_Wrd_t * vGuides = Abc_TtFindBVarsSVars2( p, Vec_WrdArray(vFuncs[0]), Vec_IntSize(vVarIDs), nRVars, nRails, nLutSize, fVerbose, pMyu, nZParam, nSubsets, nBest );
|
||||
if ( vGuides ) {
|
||||
int iEntry = fUseRand ? Abc_Random(0) % Vec_WrdSize(vGuides) : 0;
|
||||
nRVars = Abc_LutCascadeDecStage( Vec_WrdEntry(vGuides, iEntry), pGuide, i, vFuncs, vVarIDs, nRVarsOld, nRails, nLutSize, nZParam, fVerbose, vCas, i ? NULL : pMyu );
|
||||
Vec_WrdFree( vGuides );
|
||||
}
|
||||
else
|
||||
nRVars = -1;
|
||||
if ( i+2 > nStages ) {
|
||||
if ( fVerbose )
|
||||
printf( "The length of the cascade (%d) exceeds the max allowed number of stages (%d).\n", i+2, nStages );
|
||||
nRVars = -1;
|
||||
}
|
||||
if ( fXRail && nRVars == -1 && Vec_IntSize(vVarIDs) > nLutSize-1 ) {
|
||||
Vec_Wrd_t * vGuides = Abc_TtFindBVarsSVars2( p, Vec_WrdArray(vFuncs[0]), Vec_IntSize(vVarIDs), nRVarsOld, nRails+1, nLutSize-1, fVerbose, pMyu, nZParam, nSubsets, nBest );
|
||||
if ( vGuides ) {
|
||||
int iEntry = fUseRand ? Abc_Random(0) % Vec_WrdSize(vGuides) : 0;
|
||||
nRVars = Abc_LutCascadeDecStage( Vec_WrdEntry(vGuides, iEntry), pGuide, i, vFuncs, vVarIDs, nRVarsOld, nRails+1, nLutSize-1, nZParam, fVerbose, vCas, NULL );
|
||||
Vec_WrdFree( vGuides );
|
||||
}
|
||||
else
|
||||
nRVars = -1;
|
||||
if ( i+2 > nStages ) {
|
||||
if ( fVerbose )
|
||||
printf( "The length of the cascade (%d) exceeds the max allowed number of stages (%d).\n", i+2, nStages );
|
||||
nRVars = -1;
|
||||
}
|
||||
}
|
||||
if ( nRVars == -1 ) {
|
||||
Vec_IntClear( vVarIDs );
|
||||
if ( fVerbose )
|
||||
printf( "The function is not decomposable with %d rails.\n", nRails );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( nRVars != -1 && Vec_IntSize(vVarIDs) > 0 ) {
|
||||
Abc_LutCascadeGenOne( vCas, Vec_IntSize(vVarIDs), Vec_IntArray(vVarIDs), Vec_WrdEntry(vCas, 0), Vec_WrdArray(vFuncs[0]) );
|
||||
Vec_WrdAddToEntry( vCas, 0, -nVarsOrig );
|
||||
pRes = Vec_WrdReleaseArray(vCas);
|
||||
if ( pnStages ) *pnStages = i+1;
|
||||
}
|
||||
Vec_WrdFree( vCas );
|
||||
for ( i = 0; i < 3; i++ )
|
||||
|
|
@ -602,14 +875,14 @@ Abc_Ntk_t * Abc_NtkLutCascadeFromLuts( word * pLuts, int nVars, Abc_Ntk_t * pNtk
|
|||
}
|
||||
return pNtkNew;
|
||||
}
|
||||
Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose )
|
||||
Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nStages, int nRails, int nIters, int fVerbose )
|
||||
{
|
||||
extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk );
|
||||
extern Mini_Aig_t * Gia_ManToMiniAig( Gia_Man_t * pGia );
|
||||
extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
//extern word * Abc_LutCascade( Mini_Aig_t * p, int nLutSize, int nStages, int nRails, int nIters, int fVerbose );
|
||||
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
|
||||
Mini_Aig_t * pM = Gia_ManToMiniAig( pGia );
|
||||
//word * pLuts = Abc_LutCascade( pM, nLutSize, nLuts, nRails, nIters, fVerbose );
|
||||
//word * pLuts = Abc_LutCascade( pM, nLutSize, nStages, nRails, nIters, fVerbose );
|
||||
word * pLuts = Abc_LutCascadeTest( pM, nLutSize, 0 );
|
||||
Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL;
|
||||
ABC_FREE( pLuts );
|
||||
|
|
@ -617,15 +890,17 @@ Abc_Ntk_t * Abc_NtkLutCascade( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nR
|
|||
Gia_ManStop( pGia );
|
||||
return pNew;
|
||||
}
|
||||
Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, char * pGuide )
|
||||
Abc_Ntk_t * Abc_NtkLutCascadeOne( Abc_Ntk_t * pNtk, int nLutSize, int nStages, int nRails, int nIters, int nJRatio, int nZParam, int fXRail, int Seed, int fVerbose, int fVeryVerbose, char * pGuide, int nSubsets, int nBest )
|
||||
{
|
||||
extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk );
|
||||
extern word * Abc_LutCascade2( word * p, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose );
|
||||
int nWords = Abc_TtWordNum(Abc_NtkCiNum(pNtk));
|
||||
int i, nWords = Abc_TtWordNum(Abc_NtkCiNum(pNtk));
|
||||
word * pCopy = ABC_ALLOC( word, nWords );
|
||||
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
|
||||
Abc_Ntk_t * pNew = NULL;
|
||||
Abc_Random(1);
|
||||
for ( i = 0; i < Seed; i++ )
|
||||
Abc_Random(0);
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
for ( int Iter = 0; Iter < nIters; Iter++ ) {
|
||||
word * pTruth1 = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) );
|
||||
Abc_TtCopy( pCopy, pTruth1, nWords, 0 );
|
||||
|
|
@ -635,6 +910,7 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int n
|
|||
Abc_TtMinimumBase( pTruth1, Vec_IntArray(vVarIDs), Abc_NtkCiNum(pNtk), &nVars );
|
||||
Vec_IntShrink( vVarIDs, nVars );
|
||||
if ( fVerbose ) {
|
||||
printf( "Iter %2d : ", Iter );
|
||||
if ( Abc_NtkCiNum(pNtk) != nVars )
|
||||
printf( "The support of the function is reduced from %d to %d variables.\n", Abc_NtkCiNum(pNtk), nVars );
|
||||
printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs", nVars, nRails, nLutSize );
|
||||
|
|
@ -643,13 +919,14 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int n
|
|||
printf( ".\n" );
|
||||
}
|
||||
|
||||
word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, fVerbose );
|
||||
word * pLuts = Abc_LutCascadeDec( p, pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, nStages, (int)(Iter >= 0), nZParam, fXRail, fVeryVerbose, NULL, NULL, nSubsets, nBest );
|
||||
pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL;
|
||||
Vec_IntFree( vVarIDs );
|
||||
|
||||
if ( pLuts ) {
|
||||
Abc_LutCascadeMinBase( pLuts, Abc_NtkCiNum(pNtk) );
|
||||
if ( fVerbose )
|
||||
Abc_LutCascadePrint( pLuts );
|
||||
Abc_LutCascadePrint( pLuts, nLutSize );
|
||||
word * pTruth2 = Abc_LutCascadeTruth( pLuts, Abc_NtkCiNum(pNtk) );
|
||||
if ( !Abc_TtEqual(pCopy, pTruth2, nWords) ) {
|
||||
printf( "Verification FAILED.\n" );
|
||||
|
|
@ -664,6 +941,7 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int n
|
|||
}
|
||||
//ABC_FREE( pTruth1 );
|
||||
}
|
||||
Abc_BSEvalFree( p );
|
||||
ABC_FREE( pCopy );
|
||||
Gia_ManStop( pGia );
|
||||
return pNew;
|
||||
|
|
@ -673,8 +951,8 @@ Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nSh
|
|||
int nVars = nStages * nLutSize - (nStages-1) * (nRails + nShared);
|
||||
word * pLuts = Abc_LutCascadeGen( nVars, nLutSize, nRails, nShared );
|
||||
Abc_Ntk_t * pNew = Abc_NtkLutCascadeFromLuts( pLuts, nVars, NULL, nLutSize, fVerbose );
|
||||
Abc_LutCascadePrint( pLuts );
|
||||
if ( fVerbose ) {
|
||||
Abc_LutCascadePrint( pLuts, nLutSize );
|
||||
if ( fVerbose ) {
|
||||
word * pTruth = Abc_LutCascadeTruth( pLuts, nVars );
|
||||
if ( nVars <= 10 ) {
|
||||
printf( "Function: "); Abc_TtPrintHexRev( stdout, pTruth, nVars ); printf( "\n" );
|
||||
|
|
@ -684,7 +962,23 @@ Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nSh
|
|||
ABC_FREE( pLuts );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
char * Abc_NtkReadTruth( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
if ( Abc_NtkCiNum(pNtk) > 30 )
|
||||
return NULL;
|
||||
extern Gia_Man_t * Abc_NtkStrashToGia( Abc_Ntk_t * pNtk );
|
||||
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
|
||||
word * pTruth1 = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) );
|
||||
int nWords = Abc_TtWordNum(Abc_NtkCiNum(pNtk));
|
||||
word * pCopy = ABC_ALLOC( word, nWords );
|
||||
Abc_TtCopy( pCopy, pTruth1, nWords, 0 );
|
||||
Gia_ManStop( pGia );
|
||||
int nVars = Abc_NtkCiNum(pNtk);
|
||||
char * pTtStr = ABC_CALLOC( char, nVars > 2 ? (1 << (nVars-2)) + 1 : 2 );
|
||||
Extra_PrintHexadecimalString( pTtStr, (unsigned *)pCopy, nVars );
|
||||
ABC_FREE( pCopy );
|
||||
return pTtStr;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -1156,10 +1450,10 @@ Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarsOrig )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose )
|
||||
void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nStages, int nRails, int nIters, int nJRatio, int nZParam, int Seed, int fVerbose, int fVeryVerbose, int fPrintMyu, int fPrintLev, int fXRail, int nSubsets, int nBest )
|
||||
{
|
||||
abctime clkStart = Abc_Clock();
|
||||
int i, Sum = 0, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig);
|
||||
int i, nErrors = 0, Sum = 0, nStageCount = 0, MyuMin = 0, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig);
|
||||
Vec_Wrd_t * vTruths = NULL;
|
||||
if ( strstr(pFileName, ".txt") )
|
||||
vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarsOrig );
|
||||
|
|
@ -1175,10 +1469,13 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n
|
|||
return;
|
||||
}
|
||||
|
||||
Abc_Random(1);
|
||||
for ( i = 0; i < Seed; i++ )
|
||||
Abc_Random(0);
|
||||
printf( "Considering %d functions having %d variables from file \"%s\".\n", nFuncs, nVarsOrig, pFileName );
|
||||
word * pCopy = ABC_ALLOC( word, nWords );
|
||||
int Iter = 0, LutStats[100] = {0};
|
||||
Abc_Random(1);
|
||||
int Iter = 0, IterReal = 0, LutStats[50] = {0}, StageStats[50] = {0}, MyuStats[50] = {0};
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
for ( i = 0; i < nFuncs; i++ )
|
||||
{
|
||||
word * pTruth = Vec_WrdEntryP( vTruths, i*nWords );
|
||||
|
|
@ -1187,7 +1484,7 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n
|
|||
if ( fVeryVerbose )
|
||||
printf( "\n" );
|
||||
if ( fVerbose || fVeryVerbose )
|
||||
printf( "Function %3d : ", i );
|
||||
printf( "Function %4d : ", i );
|
||||
if ( fVeryVerbose )
|
||||
Abc_TtPrintHexRev( stdout, pTruth, nVarsOrig ), printf( "\n" );
|
||||
//continue;
|
||||
|
|
@ -1202,8 +1499,9 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n
|
|||
printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs.\n", nVars, nRails, nLutSize );
|
||||
}
|
||||
|
||||
word * pLuts = Abc_LutCascadeDec( NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, fVeryVerbose );
|
||||
word * pLuts = Abc_LutCascadeDec( p, NULL, pTruth, nVarsOrig, vVarIDs, nRails, nLutSize, nStages, (int)(Iter >= 0), nZParam, fXRail, fVeryVerbose, &nStageCount, &MyuMin, nSubsets, nBest );
|
||||
Vec_IntFree( vVarIDs );
|
||||
if ( MyuMin < 50 ) MyuStats[MyuMin]++, IterReal++;
|
||||
if ( pLuts == NULL ) {
|
||||
if ( ++Iter < nIters ) {
|
||||
i--;
|
||||
|
|
@ -1217,29 +1515,47 @@ void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int n
|
|||
Iter = 0;
|
||||
Sum++;
|
||||
nTotalLuts += Abc_LutCascadeCount(pLuts);
|
||||
LutStats[Abc_LutCascadeCount(pLuts)]++;
|
||||
if ( Abc_LutCascadeCount(pLuts) < 50 )
|
||||
LutStats[Abc_LutCascadeCount(pLuts)]++;
|
||||
if ( nStageCount < 50) StageStats[nStageCount]++;
|
||||
Abc_LutCascadeMinBase( pLuts, nVarsOrig );
|
||||
word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVarsOrig );
|
||||
if ( fVeryVerbose )
|
||||
Abc_LutCascadePrint( pLuts );
|
||||
Abc_LutCascadePrint( pLuts, nLutSize );
|
||||
if ( fVerbose || fVeryVerbose )
|
||||
printf( "Decomposition exists. " );
|
||||
if ( !Abc_TtEqual(pCopy, pTruth2, nWords) ) {
|
||||
printf( "Verification FAILED for function %d.\n", i );
|
||||
printf( "Before: " ); Abc_TtPrintHexRev( stdout, pCopy, nVarsOrig ), printf( "\n" );
|
||||
printf( "After: " ); Abc_TtPrintHexRev( stdout, pTruth2, nVarsOrig ), printf( "\n" );
|
||||
if ( fVerbose || fVeryVerbose ) printf( "Verification FAILED for function %d.\n", i );
|
||||
if ( fVerbose || fVeryVerbose ) { printf( "Before: " ); Abc_TtPrintHexRev( stdout, pCopy, nVarsOrig ), printf( "\n" ); }
|
||||
if ( fVerbose || fVeryVerbose ) { printf( "After: " ); Abc_TtPrintHexRev( stdout, pTruth2, nVarsOrig ), printf( "\n" ); }
|
||||
nErrors++;
|
||||
}
|
||||
else if ( fVerbose || fVeryVerbose )
|
||||
printf( "Verification passed.\n" );
|
||||
ABC_FREE( pTruth2 );
|
||||
ABC_FREE( pLuts );
|
||||
}
|
||||
Abc_BSEvalFree( p );
|
||||
ABC_FREE( pCopy );
|
||||
Vec_WrdFree( vTruths );
|
||||
printf( "Statistics for %d-rail LUT cascade:\n", nRails );
|
||||
for ( i = 0; i < 100; i++ )
|
||||
if ( fPrintMyu ) {
|
||||
printf( "Column multiplicity statistics for %d-rail LUT cascade:\n", nRails );
|
||||
for ( i = 0; i < 50; i++ )
|
||||
if ( MyuStats[i] )
|
||||
printf( " %2d Myu : Function count = %8d (%6.2f %%)\n", i, MyuStats[i], 100.0*MyuStats[i]/Abc_MaxInt(1, nFuncs)/IterReal );
|
||||
}
|
||||
if ( fPrintLev ) {
|
||||
printf( "Level count statistics for %d-rail LUT cascade:\n", nRails );
|
||||
for ( i = 0; i < 50; i++ )
|
||||
if ( StageStats[i] )
|
||||
printf( " %2d level : Function count = %8d (%6.2f %%)\n", i, StageStats[i], 100.0*StageStats[i]/Abc_MaxInt(1, nFuncs) );
|
||||
}
|
||||
printf( "LUT count statistics for %d-rail LUT cascade:\n", nRails );
|
||||
for ( i = 0; i < 50; i++ )
|
||||
if ( LutStats[i] )
|
||||
printf( " %d LUT6 : Function count = %8d (%6.2f %%)\n", i, LutStats[i], 100.0*LutStats[i]/nFuncs );
|
||||
printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) );
|
||||
printf( " %2d LUT%d : Function count = %8d (%6.2f %%)\n", i, nLutSize, LutStats[i], 100.0*LutStats[i]/Abc_MaxInt(1, nFuncs) );
|
||||
printf( "Non-decomp : Function count = %8d (%6.2f %%)\n", nFuncs-Sum, 100.0*(nFuncs-Sum)/Abc_MaxInt(1, nFuncs) );
|
||||
if ( nErrors ) printf( "Verification ***FAILED*** for %d functions (%6.2f %%)\n", nErrors, 100.0*nErrors/Abc_MaxInt(1, nFuncs) );
|
||||
printf( "Finished %d functions (%.2f LUTs / function; %.2f functions / sec). ",
|
||||
nFuncs, 1.0*nTotalLuts/Sum, 1.0*nFuncs/(((double)(Abc_Clock() - clkStart))/((double)CLOCKS_PER_SEC)) );
|
||||
Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart );
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
|
||||
***********************************************************************/
|
||||
|
||||
//#include <dirent.h>
|
||||
//#include <sys/stat.h>
|
||||
|
||||
#include "base/abc/abc.h"
|
||||
#include "base/main/main.h"
|
||||
#include "aig/gia/giaAig.h"
|
||||
|
|
@ -36,6 +39,7 @@
|
|||
#include "proof/pdr/pdr.h"
|
||||
#include "sat/bmc/bmc.h"
|
||||
#include "map/mio/mio.h"
|
||||
#include "misc/vec/vecMem.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
|
|
@ -4902,6 +4906,275 @@ Abc_Ntk_t * Abc_NtkDarTestNtk( Abc_Ntk_t * pNtk )
|
|||
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Data_ListDirsFilesCompareNames( char ** pp1, char ** pp2 )
|
||||
{
|
||||
return strcmp( *pp1, *pp2 );
|
||||
}
|
||||
char ** Data_ListDirsFiles(const char *path, const char *ext)
|
||||
{
|
||||
int iItems = 0, nItems = 1000;
|
||||
char ** pRes = (char **)calloc( sizeof(char*), nItems );
|
||||
DIR *dir;
|
||||
struct dirent *entry;
|
||||
struct stat statbuf;
|
||||
|
||||
// Open the directory
|
||||
if ((dir = opendir(path)) == NULL) {
|
||||
perror("opendir");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Read each entry in the directory
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
char full_path[1024];
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);
|
||||
|
||||
// Get the status of the entry
|
||||
if (stat(full_path, &statbuf) == -1) {
|
||||
perror("stat");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ext == NULL) {
|
||||
// If no file extension is provided, list subdirectories
|
||||
if (S_ISDIR(statbuf.st_mode)) {
|
||||
// Skip "." and ".." directories
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Print the directory name
|
||||
//printf("%s\n", entry->d_name);
|
||||
assert( iItems < nItems );
|
||||
pRes[iItems] = (char *)calloc( sizeof(char), strlen(entry->d_name)+1 );
|
||||
memcpy( pRes[iItems++], entry->d_name, strlen(entry->d_name) );
|
||||
}
|
||||
} else {
|
||||
// If file extension is provided, list files with that extension
|
||||
if (S_ISREG(statbuf.st_mode)) { // Check if it's a regular file
|
||||
const char *dot = strrchr(entry->d_name, '.');
|
||||
if (dot && strcmp(dot + 1, ext) == 0) {
|
||||
// Print the file name
|
||||
//printf("%s\n", entry->d_name);
|
||||
assert( iItems <= nItems );
|
||||
if ( iItems == nItems ) {
|
||||
pRes = ABC_REALLOC( char *, pRes, nItems *= 2 );
|
||||
memset( pRes + nItems/2, 0, sizeof(char *) * nItems/2 );
|
||||
}
|
||||
pRes[iItems] = (char *)calloc( sizeof(char), strlen(entry->d_name)+1 );
|
||||
memcpy( pRes[iItems++], entry->d_name, strlen(entry->d_name) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qsort( (void *)pRes, (size_t)iItems, sizeof(char *), (int (*)(const void *, const void *)) Data_ListDirsFilesCompareNames );
|
||||
|
||||
// Close the directory
|
||||
closedir(dir);
|
||||
if ( iItems == 0 )
|
||||
ABC_FREE( pRes );
|
||||
return pRes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Gia_ManDeriveNodeClasses( Gia_Man_t * p, Vec_Wrd_t * vSims )
|
||||
{
|
||||
abctime clkStart = Abc_Clock();
|
||||
int nVars = Gia_ManCiNum(p);
|
||||
int nWords = Abc_Truth6WordNum( nVars );
|
||||
Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars );
|
||||
Vec_Int_t * vRes = Vec_IntStartFull( Gia_ManObjNum(p) );
|
||||
Gia_Obj_t * pObj; int i;
|
||||
for ( i = 0; i <= nVars; i++ ) {
|
||||
int iFunc = Vec_MemHashInsert( vTtMem, Vec_WrdEntryP(vSims, i*nWords) );
|
||||
assert( iFunc == i );
|
||||
Vec_IntWriteEntry( vRes, i, i );
|
||||
}
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
{
|
||||
word * pTruth = Vec_WrdEntryP( vSims, i*nWords );
|
||||
if ( pTruth[0] & 1 )
|
||||
for ( int k = 0; k < nWords; k++ )
|
||||
pTruth[k] = ~pTruth[k];
|
||||
int iFunc = Vec_MemHashInsert(vTtMem, pTruth);
|
||||
//assert( iFunc > nVars );
|
||||
Vec_IntWriteEntry( vRes, i, iFunc );
|
||||
}
|
||||
printf( "Detected %d unique functions among %d nodes. ", Vec_MemEntryNum(vTtMem) - nVars - 1, Gia_ManAndNum(p) );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - clkStart );
|
||||
Vec_MemFree( vTtMem );
|
||||
return vRes;
|
||||
}
|
||||
int Gia_ManExploreNode_rec( Gia_Man_t * p, int Obj, int Repr, Vec_Int_t * vFuncs )
|
||||
{
|
||||
if ( Obj == Repr || Vec_IntEntry(vFuncs, Obj) == -1 )
|
||||
return 0;
|
||||
if ( Obj < Repr )
|
||||
return 1;
|
||||
if ( Gia_ObjIsTravIdCurrentId(p, Obj) )
|
||||
return 1;
|
||||
Gia_ObjSetTravIdCurrentId(p, Obj);
|
||||
Gia_Obj_t * pObj = Gia_ManObj(p, Obj);
|
||||
if ( !Gia_ManExploreNode_rec( p, Gia_ObjFaninId0(pObj, Obj), Repr, vFuncs ) )
|
||||
return 0;
|
||||
if ( !Gia_ManExploreNode_rec( p, Gia_ObjFaninId1(pObj, Obj), Repr, vFuncs ) )
|
||||
return 0;
|
||||
if ( Vec_IntEntry(vFuncs, Obj) != Obj ) {
|
||||
if ( !Gia_ManExploreNode_rec( p, Vec_IntEntry(vFuncs, Obj), Repr, vFuncs ) )
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
int Gia_ManChoiceCheck( Gia_Man_t * p, Gia_Obj_t * pObj, int i, Vec_Int_t * vFuncs )
|
||||
{
|
||||
if ( Vec_IntEntry(vFuncs, Gia_ObjFaninId0p(p, pObj)) == -1 || Vec_IntEntry(vFuncs, Gia_ObjFaninId1p(p, pObj)) == -1 )
|
||||
return 0;
|
||||
if ( i == Vec_IntEntry(vFuncs, i) )
|
||||
return 1;
|
||||
assert( i > Vec_IntEntry(vFuncs, i) );
|
||||
Gia_ManIncrementTravId( p );
|
||||
if ( !Gia_ManExploreNode_rec(p, i, Vec_IntEntry(vFuncs, i), vFuncs) )
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
void Gia_ManChoicesClean( Gia_Man_t * p, Vec_Int_t * vFuncs )
|
||||
{
|
||||
Gia_Obj_t * pObj; int i;
|
||||
Gia_ManForEachAnd( p, pObj, i )
|
||||
if ( Vec_IntEntry(vFuncs, i) <= Gia_ManCiNum(p) || !Gia_ManChoiceCheck(p, pObj, i, vFuncs) )
|
||||
Vec_IntWriteEntry( vFuncs, i, -1 );
|
||||
}
|
||||
Gia_Man_t * Gia_ManTransformToChoices( Gia_Man_t * p )
|
||||
{
|
||||
Vec_Wrd_t * Gia_ManDeriveNodeFuncs( Gia_Man_t * p );
|
||||
Vec_Wrd_t * vSims = Gia_ManDeriveNodeFuncs( p );
|
||||
Vec_Int_t * vFuncs = Gia_ManDeriveNodeClasses( p, vSims );
|
||||
Gia_ManChoicesClean( p, vFuncs );
|
||||
Vec_WrdFree( vSims );
|
||||
|
||||
Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(p) );
|
||||
pNew->pName = Abc_UtilStrsav( p->pName );
|
||||
pNew->pSibls = ABC_CALLOC( int, Gia_ManObjNum(p) );
|
||||
Gia_ManHashAlloc( pNew );
|
||||
Gia_Obj_t * pObj; int i;
|
||||
Gia_ManSetPhase(p);
|
||||
Gia_ManConst0(p)->Value = 0;
|
||||
Gia_ManForEachCi( p, pObj, i )
|
||||
pObj->Value = Gia_ManAppendCi( pNew );
|
||||
Gia_ManForEachAnd( p, pObj, i ) {
|
||||
if ( Vec_IntEntry(vFuncs, i) == -1 )
|
||||
continue;
|
||||
else if ( Vec_IntEntry(vFuncs, i) == i )
|
||||
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
else {
|
||||
int iFunc = Vec_IntEntry(vFuncs, i);
|
||||
pNew->pSibls[i] = pNew->pSibls[iFunc];
|
||||
pNew->pSibls[iFunc] = i;
|
||||
pObj->Value = Abc_Var2Lit( iFunc, pObj->fPhase ^ Gia_ManObj(p, iFunc)->fPhase );
|
||||
//printf( "Adding choice %d -> %d\n", iFunc, i );
|
||||
}
|
||||
}
|
||||
Gia_ManForEachCo( p, pObj, i )
|
||||
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
||||
Vec_IntFree( vFuncs );
|
||||
return pNew;
|
||||
}
|
||||
void Gia_ManTestAppend( Gia_Man_t * pNew, Gia_Man_t * pTwo )
|
||||
{
|
||||
Gia_Obj_t * pObj; int i;
|
||||
assert( Gia_ManCiNum(pNew) == Gia_ManCiNum(pTwo) );
|
||||
Gia_ManConst0(pTwo)->Value = 0;
|
||||
Gia_ManForEachCand( pTwo, pObj, i )
|
||||
{
|
||||
if ( Gia_ObjIsAnd(pObj) )
|
||||
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
|
||||
else if ( Gia_ObjIsCi(pObj) )
|
||||
pObj->Value = Gia_Obj2Lit( pNew, Gia_ManCi( pNew, Gia_ObjCioId(pObj) ) );
|
||||
}
|
||||
}
|
||||
Gia_Man_t * Abc_NtkDarTestFiles()
|
||||
{
|
||||
char full_path[1024];
|
||||
const char *directory_path = "temp";
|
||||
const char *ext = "aig";
|
||||
char ** pItems = Data_ListDirsFiles(directory_path, ext);
|
||||
if ( pItems == NULL ) {
|
||||
printf( "There are no files in directory \"%s\".\n", directory_path );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//for ( i = 0; pItems[i]; i++ )
|
||||
// printf( "%d : %s\n", i, pItems[i] );
|
||||
|
||||
Gia_Obj_t * pObj; int i;
|
||||
Gia_Man_t * pNew = NULL;
|
||||
Gia_Man_t * pTemp = NULL;
|
||||
for ( i = 0; pItems[i]; i++ )
|
||||
{
|
||||
snprintf(full_path, sizeof(full_path), "%s/%s", directory_path, pItems[i]);
|
||||
Gia_Man_t * pTwo = Gia_AigerRead( full_path, 0, 0, 0 );
|
||||
if ( i == 0 ) {
|
||||
pNew = Gia_ManStart( 10000 );
|
||||
pNew->pName = Abc_UtilStrsav( pTwo->pName );
|
||||
pNew->pSpec = Abc_UtilStrsav( pTwo->pSpec );
|
||||
for ( int k = 0; k < Gia_ManCiNum(pTwo); k++ )
|
||||
Gia_ManAppendCi( pNew );
|
||||
}
|
||||
Gia_ManTestAppend( pNew, pTwo );
|
||||
if ( i == 0 )
|
||||
pTemp = pTwo;
|
||||
else
|
||||
Gia_ManStop( pTwo );
|
||||
if ( i < 4 )
|
||||
printf( "%d : %s\n", i, pItems[i] );
|
||||
}
|
||||
printf( "Finished reading %d files.\n", i );
|
||||
Gia_ManForEachCo( pTemp, pObj, i )
|
||||
Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
|
||||
Gia_ManStop( pTemp );
|
||||
|
||||
Gia_ManPrintStats( pNew, NULL );
|
||||
|
||||
pNew = Gia_ManTransformToChoices( pTemp = pNew );
|
||||
Gia_ManStop( pTemp );
|
||||
|
||||
Gia_ManPrintStats( pNew, NULL );
|
||||
|
||||
for ( i = 0; pItems[i]; i++ )
|
||||
free( pItems[i] );
|
||||
free( pItems );
|
||||
|
||||
//Gia_AigerWrite( pNew, "all.aig", 0, 0, 0 );
|
||||
//Gia_ManStop( pNew );
|
||||
return pNew;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -574,6 +574,7 @@ Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int
|
|||
return pNodeTop;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -585,27 +586,456 @@ Abc_Obj_t * Abc_NtkBddFindCofactor( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkBddNodeCompareByLevel( DdNode ** pp1, DdNode ** pp2 )
|
||||
{
|
||||
return (*pp1)->Id - (*pp2)->Id;
|
||||
}
|
||||
Vec_Ptr_t * Abc_NtkBddCollectByLevel( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
DdGen *gen; DdNode *node; int i;
|
||||
Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 );
|
||||
Cudd_ForeachNode( dd, aFunc, gen, node )
|
||||
Vec_PtrPush( vNodes, node ), node->Id = Cudd_ReadPerm( dd, (int)node->index );
|
||||
Vec_PtrSort( vNodes, (int (*)(const void *, const void *))Abc_NtkBddNodeCompareByLevel );
|
||||
Vec_PtrForEachEntry( DdNode *, vNodes, node, i )
|
||||
node->Id = i;
|
||||
return vNodes;
|
||||
}
|
||||
void Abc_NtkBddCollectPrint3( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Ptr_t * vNodes = Abc_NtkBddCollectByLevel( dd, aFunc );
|
||||
Vec_PtrPrintPointers( vNodes );
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
Vec_Ptr_t * Abc_NtkBddFetchNodes( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 );
|
||||
DdGen *gen; DdNode *node;
|
||||
Cudd_ForeachNode( dd, aFunc, gen, node)
|
||||
Vec_PtrPush(vNodes, node), node->Id = 0;
|
||||
return vNodes;
|
||||
}
|
||||
void Abc_NtkBddCleanNodes( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
DdGen *gen; DdNode *node;
|
||||
Cudd_ForeachNode( dd, aFunc, gen, node)
|
||||
node->Id = 0;
|
||||
}
|
||||
void Abc_NtkBddCollectPtr_rec( DdManager * dd, DdNode * aFunc, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
if ( aFunc->Id )
|
||||
return;
|
||||
if ( !cuddIsConstant(aFunc) ) {
|
||||
Abc_NtkBddCollectPtr_rec( dd, cuddE(aFunc), vNodes );
|
||||
Abc_NtkBddCollectPtr_rec( dd, cuddT(aFunc), vNodes );
|
||||
}
|
||||
aFunc->Id = Vec_PtrSize(vNodes) + 1;
|
||||
Vec_PtrPush(vNodes, aFunc);
|
||||
}
|
||||
Vec_Ptr_t * Abc_NtkBddCollectPtr( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Ptr_t * vNodes = Vec_PtrAlloc( 100 );
|
||||
Abc_NtkBddCleanNodes( dd, aFunc );
|
||||
Abc_NtkBddCollectPtr_rec( dd, aFunc, vNodes );
|
||||
return vNodes;
|
||||
}
|
||||
void Abc_NtkBddCollectPrint2( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Ptr_t * vNodes = Abc_NtkBddCollectPtr( dd, aFunc );
|
||||
Vec_PtrPrintPointers( vNodes );
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
static inline word Abc_Bdd2Word( DdNode * f ) { union { DdNode * f; word w; } v; v.f = f; return v.w; }
|
||||
static inline DdNode * Abc_Word2Bdd( word w ) { union { DdNode * f; word w; } v; v.w = w; return v.f; }
|
||||
|
||||
static inline int Abc_Bdd2Int( DdNode * F, DdNode * f ) { return (int)(Abc_Bdd2Word(F) ^ Abc_Bdd2Word(f)) >> 3; }
|
||||
static inline DdNode * Abc_Int2Bdd( DdNode * F, int diff ) { return Abc_Word2Bdd(Abc_Bdd2Word(F) ^ (word)(diff << 3)); }
|
||||
|
||||
static inline int Abc_BddIndex( DdManager * dd, DdNode * f ) { return cuddIsConstant(f) ? dd->size : (int)f->index; }
|
||||
static inline int Abc_BddLevel( DdManager * dd, DdNode * f ) { return cuddIsConstant(f) ? dd->size : Cudd_ReadPerm(dd, (int)f->index); }
|
||||
|
||||
void Abc_NtkBddCollectInt_rec( DdManager * dd, DdNode * aRef, DdNode * aFunc, Vec_Wec_t * vNodes )
|
||||
{
|
||||
if ( Cudd_IsComplement(aFunc->next) )
|
||||
return;
|
||||
aFunc->next = Cudd_Not(aFunc->next);
|
||||
if ( !cuddIsConstant(aFunc) ) {
|
||||
Abc_NtkBddCollectInt_rec( dd, aRef, cuddE(aFunc), vNodes );
|
||||
Abc_NtkBddCollectInt_rec( dd, aRef, cuddT(aFunc), vNodes );
|
||||
}
|
||||
//assert( Abc_Bdd2Int(aRef, aFunc) % 8 == 0 );
|
||||
Vec_WecPush( vNodes, Abc_BddLevel(dd, aFunc), Abc_Bdd2Int(aRef, aFunc) );
|
||||
}
|
||||
Vec_Wec_t * Abc_NtkBddCollectInt( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Wec_t * vNodes = Vec_WecStart( dd->size+1 );
|
||||
Abc_NtkBddCollectInt_rec( dd, aFunc, aFunc, vNodes );
|
||||
extern void ddClearFlag2( DdNode * f );
|
||||
ddClearFlag2( aFunc );
|
||||
return vNodes;
|
||||
}
|
||||
void Abc_NtkBddCollectPrint( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Wec_t * vNodes = Abc_NtkBddCollectInt( dd, aFunc );
|
||||
Vec_WecPrint( vNodes, 0 );
|
||||
Vec_WecFree( vNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Abc_NtkBddCollectHighest( DdManager * dd, DdNode * aFunc, Vec_Wec_t * vNodes )
|
||||
{
|
||||
Vec_Int_t * vRes = Vec_IntStartFull( Vec_WecMaxEntry(vNodes)+1 );
|
||||
Vec_Int_t * vLevel; int i, k, Obj, * pEntry;
|
||||
Vec_WecForEachLevelStop( vNodes, vLevel, i, dd->size )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k ) {
|
||||
DdNode * aNode = Abc_Int2Bdd(aFunc, Obj);
|
||||
pEntry = Vec_IntEntryP( vRes, Abc_Bdd2Int(aFunc, cuddE(aNode)) );
|
||||
if ( *pEntry == -1 ) *pEntry = i;
|
||||
pEntry = Vec_IntEntryP( vRes, Abc_Bdd2Int(aFunc, cuddT(aNode)) );
|
||||
if ( *pEntry == -1 ) *pEntry = i;
|
||||
}
|
||||
return vRes;
|
||||
}
|
||||
void Abc_NtkBddCollectProfile( DdManager * dd, DdNode * aFunc, Vec_Wec_t * vNodes, int * pProf )
|
||||
{
|
||||
memset( pProf, 0, sizeof(int)*(dd->size+1) );
|
||||
Vec_Int_t * vHighest = Abc_NtkBddCollectHighest( dd, aFunc, vNodes );
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
pProf[0] = 1;
|
||||
Vec_WecForEachLevelStart( vNodes, vLevel, i, 1 )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k ) {
|
||||
int lev, Start = Vec_IntEntry( vHighest, Obj );
|
||||
for ( lev = Start+1; lev <= i; lev++ )
|
||||
pProf[lev]++;
|
||||
}
|
||||
printf( " Size = %5d ", Vec_IntSize(vHighest) );
|
||||
Vec_IntFree( vHighest );
|
||||
}
|
||||
void Abc_NtkBddTestProfile( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Wec_t * vNodes = Abc_NtkBddCollectInt( dd, aFunc );
|
||||
int i, Total = 0, Profile[100]; assert( dd->size < 100 );
|
||||
Abc_NtkBddCollectProfile( dd, aFunc, vNodes, Profile );
|
||||
printf( " " );
|
||||
for ( i = 0; i <= dd->size; i++ )
|
||||
printf( "%3d", Profile[i] ), Total += Profile[i];
|
||||
printf( " Total = %d\n", Total );
|
||||
Vec_WecFree( vNodes );
|
||||
}
|
||||
Vec_Wec_t * Abc_NtkBddCollectCofs( DdManager * dd, DdNode * aFunc, Vec_Wec_t * vNodes )
|
||||
{
|
||||
Vec_Wec_t * vCofs = Vec_WecStart( dd->size+1 );
|
||||
Vec_Int_t * vHighest = Abc_NtkBddCollectHighest( dd, aFunc, vNodes );
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
Vec_WecPush( vCofs, 0, 0 );
|
||||
Vec_WecForEachLevelStart( vNodes, vLevel, i, 1 )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k ) {
|
||||
int lev, Start = Vec_IntEntry( vHighest, Obj );
|
||||
for ( lev = Start+1; lev <= i; lev++ )
|
||||
Vec_WecPush( vCofs, lev, Obj );
|
||||
}
|
||||
Vec_IntFree( vHighest );
|
||||
return vCofs;
|
||||
}
|
||||
Vec_Wec_t * Abc_NtkBddCollecInfo1( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Wec_t * vInfo = Vec_WecStart( dd->size );
|
||||
Vec_Wec_t * vNodes = Abc_NtkBddCollectInt( dd, aFunc );
|
||||
Vec_Wec_t * vCofs = Abc_NtkBddCollectCofs( dd, aFunc, vNodes );
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
for ( int a = 0; a < dd->size; a++ ) {
|
||||
word Sign = (word)1 << a;
|
||||
for ( int n = 0; n < 2; n++ ) {
|
||||
word Value = (word)n << a;
|
||||
Vec_WecForEachLevel( vNodes, vLevel, i )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
Abc_Int2Bdd(aFunc, Obj)->Id = 0;
|
||||
aFunc->Id = 1;
|
||||
//printf( " %c %d : ", 'a'+a, n );
|
||||
//printf( " %2d", 1 );
|
||||
if ( n == 0 )
|
||||
Vec_IntPush( Vec_WecEntry(vInfo, a), 1 );
|
||||
Vec_WecForEachLevelStop( vNodes, vLevel, i, dd->size ) {
|
||||
Vec_IntForEachEntry( vLevel, Obj, k ) {
|
||||
DdNode * aNode = Abc_Int2Bdd(aFunc, Obj);
|
||||
if ( aNode->Id == 0 )
|
||||
continue;
|
||||
if ( !((Sign >> i) & 1) || ((Value >> i) & 1) == 0 )
|
||||
cuddE(aNode)->Id |= 1;
|
||||
if ( !((Sign >> i) & 1) || ((Value >> i) & 1) == 1 )
|
||||
cuddT(aNode)->Id |= 1;
|
||||
}
|
||||
Vec_Int_t * vCof = Vec_WecEntry(vCofs, i+1);
|
||||
int Counter = 0;
|
||||
Vec_IntForEachEntry( vCof, Obj, k )
|
||||
Counter += (int)Abc_Int2Bdd(aFunc, Obj)->Id;
|
||||
if ( n == 0 )
|
||||
Vec_IntPush( Vec_WecEntry(vInfo, a), Counter );
|
||||
else {
|
||||
int * pEntry = Vec_IntEntryP( Vec_WecEntry(vInfo, a), i+1 );
|
||||
*pEntry = Abc_MaxInt( *pEntry, Counter );
|
||||
}
|
||||
//printf( " %2d", Counter );
|
||||
}
|
||||
//printf( "\n" );
|
||||
}
|
||||
}
|
||||
Vec_WecFree( vCofs );
|
||||
Vec_WecFree( vNodes );
|
||||
return vInfo;
|
||||
}
|
||||
Vec_Wec_t * Abc_NtkBddCollecInfo2( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Wec_t * vInfo = Vec_WecStart( dd->size*(dd->size-1)/2 );
|
||||
Vec_Wec_t * vNodes = Abc_NtkBddCollectInt( dd, aFunc );
|
||||
Vec_Wec_t * vCofs = Abc_NtkBddCollectCofs( dd, aFunc, vNodes );
|
||||
Vec_Int_t * vLevel; int i, k, Obj, c = 0;
|
||||
for ( int a = 0; a < dd->size; a++ )
|
||||
for ( int b = a+1; b < dd->size; b++ ) {
|
||||
Vec_Int_t * vInfo1 = Vec_WecEntry(vInfo, c++);
|
||||
word Sign = ((word)1 << a) | ((word)1 << b);
|
||||
for ( int n = 0; n < 4; n++ ) {
|
||||
word Value = ((word)(n & 1) << a) | ((word)((n >> 1) & 1) << b);
|
||||
Vec_WecForEachLevel( vNodes, vLevel, i )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
Abc_Int2Bdd(aFunc, Obj)->Id = 0;
|
||||
aFunc->Id = 1;
|
||||
if ( n == 0 )
|
||||
Vec_IntPush( vInfo1, 1 );
|
||||
Vec_WecForEachLevelStop( vNodes, vLevel, i, dd->size ) {
|
||||
Vec_IntForEachEntry( vLevel, Obj, k ) {
|
||||
DdNode * aNode = Abc_Int2Bdd(aFunc, Obj);
|
||||
if ( aNode->Id == 0 )
|
||||
continue;
|
||||
if ( !((Sign >> i) & 1) || ((Value >> i) & 1) == 0 )
|
||||
cuddE(aNode)->Id |= 1;
|
||||
if ( !((Sign >> i) & 1) || ((Value >> i) & 1) == 1 )
|
||||
cuddT(aNode)->Id |= 1;
|
||||
}
|
||||
Vec_Int_t * vCof = Vec_WecEntry(vCofs, i+1);
|
||||
int Counter = 0;
|
||||
Vec_IntForEachEntry( vCof, Obj, k )
|
||||
Counter += (int)Abc_Int2Bdd(aFunc, Obj)->Id;
|
||||
if ( n == 0 )
|
||||
Vec_IntPush( vInfo1, Counter );
|
||||
else {
|
||||
int * pEntry = Vec_IntEntryP( vInfo1, i+1 );
|
||||
*pEntry = Abc_MaxInt( *pEntry, Counter );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( c == Vec_WecSize(vInfo) );
|
||||
Vec_WecFree( vCofs );
|
||||
Vec_WecFree( vNodes );
|
||||
return vInfo;
|
||||
}
|
||||
Vec_Wec_t * Abc_NtkBddCollecInfo3( DdManager * dd, DdNode * aFunc )
|
||||
{
|
||||
Vec_Wec_t * vInfo = Vec_WecStart( dd->size*(dd->size-1)*(dd->size-2)/6 );
|
||||
Vec_Wec_t * vNodes = Abc_NtkBddCollectInt( dd, aFunc );
|
||||
Vec_Wec_t * vCofs = Abc_NtkBddCollectCofs( dd, aFunc, vNodes );
|
||||
Vec_Int_t * vLevel; int i, k, Obj, d = 0;
|
||||
for ( int a = 0; a < dd->size; a++ )
|
||||
for ( int b = a+1; b < dd->size; b++ )
|
||||
for ( int c = b+1; c < dd->size; c++ ) {
|
||||
Vec_Int_t * vInfo1 = Vec_WecEntry(vInfo, d++);
|
||||
word Sign = ((word)1 << a) | ((word)1 << b) | ((word)1 << c);
|
||||
for ( int n = 0; n < 8; n++ ) {
|
||||
word Value = ((word)(n & 1) << a) | ((word)((n >> 1) & 1) << b) | ((word)((n >> 2) & 1) << c);
|
||||
Vec_WecForEachLevel( vNodes, vLevel, i )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
Abc_Int2Bdd(aFunc, Obj)->Id = 0;
|
||||
aFunc->Id = 1;
|
||||
if ( n == 0 )
|
||||
Vec_IntPush( vInfo1, 1 );
|
||||
Vec_WecForEachLevelStop( vNodes, vLevel, i, dd->size ) {
|
||||
Vec_IntForEachEntry( vLevel, Obj, k ) {
|
||||
DdNode * aNode = Abc_Int2Bdd(aFunc, Obj);
|
||||
if ( aNode->Id == 0 )
|
||||
continue;
|
||||
if ( !((Sign >> i) & 1) || ((Value >> i) & 1) == 0 )
|
||||
cuddE(aNode)->Id |= 1;
|
||||
if ( !((Sign >> i) & 1) || ((Value >> i) & 1) == 1 )
|
||||
cuddT(aNode)->Id |= 1;
|
||||
}
|
||||
Vec_Int_t * vCof = Vec_WecEntry(vCofs, i+1);
|
||||
int Counter = 0;
|
||||
Vec_IntForEachEntry( vCof, Obj, k )
|
||||
Counter += (int)Abc_Int2Bdd(aFunc, Obj)->Id;
|
||||
if ( n == 0 )
|
||||
Vec_IntPush( vInfo1, Counter );
|
||||
else {
|
||||
int * pEntry = Vec_IntEntryP( vInfo1, i+1 );
|
||||
*pEntry = Abc_MaxInt( *pEntry, Counter );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( d == Vec_WecSize(vInfo) );
|
||||
Vec_WecFree( vCofs );
|
||||
Vec_WecFree( vNodes );
|
||||
return vInfo;
|
||||
}
|
||||
void Abc_NtkBddPrintInfo1( Vec_Wec_t * vInfo, Vec_Wec_t * vCofs )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
printf( "Cofactor counts:\n" );
|
||||
printf( " : " );
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i )
|
||||
printf( " %2d", i );
|
||||
printf( "\n" );
|
||||
printf( " : " );
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i )
|
||||
printf( " %2d", Vec_IntSize(vLevel) );
|
||||
printf( "\n" );
|
||||
Vec_WecForEachLevel( vInfo, vLevel, i ) {
|
||||
printf( "%2d %c : ", i, 'a'+i );
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
if ( k <= i )
|
||||
printf( " -" );
|
||||
else
|
||||
printf( " %2d", Obj );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
void Abc_NtkBddPrintInfo2( Vec_Wec_t * vInfo, Vec_Wec_t * vCofs )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
printf( "Cofactor counts:\n" );
|
||||
printf( " : " );
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i )
|
||||
printf( " %2d", i );
|
||||
printf( "\n" );
|
||||
printf( " : " );
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i )
|
||||
printf( " %2d", Vec_IntSize(vLevel) );
|
||||
printf( "\n" );
|
||||
int c = 0, Limit = Vec_IntSize(Vec_WecEntry(vInfo, 0))-1;
|
||||
for ( int a = 0; a < Limit; a++ )
|
||||
for ( int b = a+1; b < Limit; b++ ) {
|
||||
Vec_Int_t * vLevel = Vec_WecEntry(vInfo, c++);
|
||||
printf( " %c%c : ", 'a'+a, 'a'+b );
|
||||
int Limit = Abc_MaxInt(a,b);
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
if ( k <= Limit )
|
||||
printf( " -" );
|
||||
else
|
||||
printf( " %2d", Obj );
|
||||
printf( "\n" );
|
||||
}
|
||||
assert( c == Vec_WecSize(vInfo) );
|
||||
}
|
||||
void Abc_NtkBddPrintInfo3( Vec_Wec_t * vInfo, Vec_Wec_t * vCofs )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
printf( "Cofactor counts:\n" );
|
||||
printf( " : " );
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i )
|
||||
printf( " %2d", i );
|
||||
printf( "\n" );
|
||||
printf( " : " );
|
||||
Vec_WecForEachLevel( vCofs, vLevel, i )
|
||||
printf( " %2d", Vec_IntSize(vLevel) );
|
||||
printf( "\n" );
|
||||
int d = 0, Limit = Vec_IntSize(Vec_WecEntry(vInfo, 0))-1;
|
||||
for ( int a = 0; a < Limit; a++ )
|
||||
for ( int b = a+1; b < Limit; b++ )
|
||||
for ( int c = b+1; c < Limit; c++ ) {
|
||||
Vec_Int_t * vLevel = Vec_WecEntry(vInfo, d++);
|
||||
printf( " %c%c%c : ", 'a'+a, 'a'+b, 'a'+c );
|
||||
int Limit = Abc_MaxInt(a,Abc_MaxInt(b,c));
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
if ( k <= Limit )
|
||||
printf( " -" );
|
||||
else
|
||||
printf( " %2d", Obj );
|
||||
printf( "\n" );
|
||||
}
|
||||
assert( d == Vec_WecSize(vInfo) );
|
||||
}
|
||||
|
||||
void Abc_NtkBddDecExploreOne( DdManager * dd, DdNode * bFunc, int iOrder )
|
||||
{
|
||||
DdManager * ddNew = Cudd_Init( dd->size, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
|
||||
int i, * pProfile = ABC_CALLOC( int, dd->size + 100 );
|
||||
Cudd_AutodynEnable( ddNew, CUDD_REORDER_SYMM_SIFT );
|
||||
Vec_Int_t * vPerm = Vec_IntStartNatural( dd->size ); if ( iOrder ) Vec_IntRandomizeOrder( vPerm );
|
||||
Vec_Int_t * vPermInv = Vec_IntInvert( vPerm, -1 );
|
||||
DdNode * bFuncNew = Extra_TransferPermute( dd, ddNew, bFunc, Vec_IntArray(vPerm) ); Cudd_Ref(bFuncNew);
|
||||
if ( iOrder ) Cudd_ReduceHeap( ddNew, CUDD_REORDER_SYMM_SIFT, 1 );
|
||||
Vec_IntFree( vPerm );
|
||||
DdNode * aFuncNew = Cudd_BddToAdd( ddNew, bFuncNew ); Cudd_Ref( aFuncNew );
|
||||
Extra_ProfileWidth( ddNew, aFuncNew, pProfile, -1 );
|
||||
//Extra_ProfileWidth( ddNew, aFuncNew, pProfile, -1 );
|
||||
if ( iOrder )
|
||||
printf( "Random order %d:\n", iOrder );
|
||||
printf( "Random order %2d: ", iOrder );
|
||||
else
|
||||
printf( "Natural order:\n" );
|
||||
for ( i = 0; i <= dd->size; i++ )
|
||||
printf( " %d=%d(%d)[%d]", i, pProfile[i], i-Abc_Base2Log(pProfile[i]), ddNew->perm[i] );
|
||||
printf( "Natural order: " );
|
||||
printf( "BDD size = %3d ", Cudd_DagSize(aFuncNew) );
|
||||
for ( i = 0; i < dd->size; i++ )
|
||||
printf( " %c", 'a' + Vec_IntEntry(vPermInv, ddNew->invperm[i]) );
|
||||
printf( "\n" );
|
||||
//Abc_NtkBddTestProfile( ddNew, aFuncNew );
|
||||
|
||||
Vec_Wec_t * vNodes = Abc_NtkBddCollectInt( ddNew, aFuncNew );
|
||||
printf( "Nodes by level:\n" );
|
||||
Vec_WecPrint( vNodes, 0 );
|
||||
Vec_Wec_t * vCofs = Abc_NtkBddCollectCofs( ddNew, aFuncNew, vNodes );
|
||||
printf( "Cofactors by level:\n" );
|
||||
Vec_WecPrint( vCofs, 0 );
|
||||
Vec_Wec_t * vInfo1 = Abc_NtkBddCollecInfo1( ddNew, aFuncNew );
|
||||
Abc_NtkBddPrintInfo1( vInfo1, vCofs );
|
||||
Vec_Wec_t * vInfo2 = Abc_NtkBddCollecInfo2( ddNew, aFuncNew );
|
||||
Abc_NtkBddPrintInfo2( vInfo2, vCofs );
|
||||
Vec_Wec_t * vInfo3 = Abc_NtkBddCollecInfo3( ddNew, aFuncNew );
|
||||
Abc_NtkBddPrintInfo3( vInfo3, vCofs );
|
||||
printf( "\n" );
|
||||
Vec_WecFree( vNodes );
|
||||
Vec_WecFree( vCofs );
|
||||
Vec_WecFree( vInfo1 );
|
||||
Vec_WecFree( vInfo2 );
|
||||
Vec_WecFree( vInfo3 );
|
||||
|
||||
Cudd_RecursiveDeref( ddNew, aFuncNew );
|
||||
Cudd_RecursiveDeref( ddNew, bFuncNew );
|
||||
Cudd_Quit( ddNew );
|
||||
ABC_FREE( pProfile );
|
||||
}
|
||||
void Abc_NtkBddDecExplore( Abc_Obj_t * pNode )
|
||||
{
|
||||
|
|
@ -613,7 +1043,7 @@ void Abc_NtkBddDecExplore( Abc_Obj_t * pNode )
|
|||
DdNode * bFunc = (DdNode *)pNode->pData;
|
||||
int i; Abc_Random(1);
|
||||
if ( Abc_ObjIsNode(pNode) )
|
||||
for ( i = 0; i < 16; i++ )
|
||||
for ( i = 0; i < 4; i++ )
|
||||
Abc_NtkBddDecExploreOne( dd, bFunc, i );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ Mini_Aig_t * Abc_MiniAigFromNtk ( Abc_Ntk_t *pNtk )
|
|||
{
|
||||
Abc_Ntk_t *pNtkRes = NULL;
|
||||
Mini_Aig_t *pAig;
|
||||
if (Abc_NtkHasMapping(pNtk)) {
|
||||
if (!Abc_NtkIsStrash(pNtk)) {
|
||||
pNtk = pNtkRes = Abc_NtkStrash( pNtk, 0, 1, 0 );
|
||||
if ( pNtkRes == NULL )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -433,7 +433,8 @@ void * Abc_NtkBuildGlobalBdds( Abc_Ntk_t * pNtk, int nBddSizeMax, int fDropInter
|
|||
// Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
|
||||
Cudd_AutodynDisable( dd );
|
||||
}
|
||||
// Cudd_PrintInfo( dd, stdout );
|
||||
if ( fVerbose )
|
||||
Cudd_PrintInfo( dd, stdout );
|
||||
return dd;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1219,7 +1219,7 @@ void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams )
|
|||
***********************************************************************/
|
||||
Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
|
||||
{
|
||||
Vec_Int_t * vGains = Vec_IntStart( Vec_PtrSize(vWins) );
|
||||
Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vWins) );
|
||||
Abc_Ntk_t * pNtk, * pNew; int i;
|
||||
Vec_PtrForEachEntry( Abc_Ntk_t *, vWins, pNtk, i )
|
||||
{
|
||||
|
|
@ -1248,7 +1248,7 @@ Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
|
|||
{
|
||||
double Before = Abc_NtkGetMappedArea(pNtk);
|
||||
double After = Abc_NtkGetMappedArea(pNew);
|
||||
if ( After < Before )
|
||||
if ( Before >= After )
|
||||
{
|
||||
Vec_IntWriteEntry( vGains, i, (int)(Before - After) );
|
||||
Abc_NtkDelete( pNtk );
|
||||
|
|
@ -1257,7 +1257,7 @@ Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
|
|||
}
|
||||
else
|
||||
{
|
||||
if ( Abc_NtkNodeNum(pNew) < Abc_NtkNodeNum(pNtk) )
|
||||
if ( Abc_NtkNodeNum(pNtk) >= Abc_NtkNodeNum(pNew) )
|
||||
{
|
||||
Vec_IntWriteEntry( vGains, i, Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNew) );
|
||||
Abc_NtkDelete( pNtk );
|
||||
|
|
@ -1320,7 +1320,7 @@ Abc_Ntk_t * Abc_NtkStochProcessOne( Abc_Ntk_t * p, char * pScript0, int Rand, in
|
|||
ABC_FREE( pScript );
|
||||
pNew = Abc_NtkReadFromFile( FileName );
|
||||
unlink( FileName );
|
||||
if ( pNew && Abc_NtkGetMappedArea(pNew) < Abc_NtkGetMappedArea(p) ) {
|
||||
if ( pNew && Abc_NtkGetMappedArea(pNew) <= Abc_NtkGetMappedArea(p) ) {
|
||||
pNew = Abc_NtkDupDfs( pTemp = pNew );
|
||||
Abc_NtkDelete( pTemp );
|
||||
return pNew;
|
||||
|
|
@ -1343,7 +1343,7 @@ Vec_Int_t * Abc_NtkStochProcess( Vec_Ptr_t * vWins, char * pScript, int nProcs,
|
|||
if ( nProcs <= 2 ) {
|
||||
return Abc_NtkStochSynthesis( vWins, pScript );
|
||||
}
|
||||
Vec_Int_t * vGains = Vec_IntStart( Vec_PtrSize(vWins) );
|
||||
Vec_Int_t * vGains = Vec_IntStartFull( Vec_PtrSize(vWins) );
|
||||
StochSynData_t * pData = ABC_CALLOC( StochSynData_t, Vec_PtrSize(vWins) );
|
||||
Vec_Ptr_t * vData = Vec_PtrAlloc( Vec_PtrSize(vWins) );
|
||||
Abc_Ntk_t * pNtk; int i;
|
||||
|
|
@ -1467,7 +1467,7 @@ void Abc_NtkInsertPartitions_rec( Abc_Ntk_t * pNew, Abc_Obj_t * pObj, Vec_Int_t
|
|||
pNode->pCopy = Abc_ObjFanin0(Abc_NtkPo(pWin, i))->pCopy;
|
||||
assert( pObj->pCopy );
|
||||
}
|
||||
Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins, int fOverlap, Vec_Int_t * vGains )
|
||||
Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t * vvNodes, Vec_Ptr_t * vvOuts, Vec_Ptr_t * vWins, int fOverlap, Vec_Int_t * vGains )
|
||||
{
|
||||
if ( vvIns == NULL ) {
|
||||
assert( vvOuts == NULL );
|
||||
|
|
@ -1481,7 +1481,7 @@ Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t
|
|||
Abc_NtkIncrementTravId( p );
|
||||
while ( 1 ) {
|
||||
int i, Gain, iEntry = Vec_IntArgMax(vGains);
|
||||
if ( Vec_IntEntry(vGains, iEntry) <= 0 )
|
||||
if ( iEntry == -1 || Vec_IntEntry(vGains, iEntry) < 0 )
|
||||
break;
|
||||
//printf( "Selecting partition %d with gain %d.\n", iEntry, Vec_IntEntry(vGains, iEntry) );
|
||||
Vec_IntWriteEntry( vGains, iEntry, -1 );
|
||||
|
|
@ -1491,18 +1491,14 @@ Abc_Ntk_t * Abc_NtkInsertPartitions( Abc_Ntk_t * p, Vec_Ptr_t * vvIns, Vec_Ptr_t
|
|||
extern void Abc_NtKMarkTfiTfo( Vec_Int_t * vOne, Abc_Ntk_t * pNtk );
|
||||
Abc_NtKMarkTfiTfo( (Vec_Int_t *)Vec_PtrEntryLast(vvInsNew), p );
|
||||
Vec_IntForEachEntry( vGains, Gain, i ) {
|
||||
if ( Gain <= 0 )
|
||||
if ( Gain < 0 )
|
||||
continue;
|
||||
Vec_Int_t * vIns = (Vec_Int_t *)Vec_PtrEntry(vvIns, i);
|
||||
Vec_Int_t * vOuts = (Vec_Int_t *)Vec_PtrEntry(vvOuts, i);
|
||||
Abc_Obj_t * pNode; int j, k;
|
||||
Abc_NtkForEachObjVec( vIns, p, pNode, j )
|
||||
Vec_Int_t * vNodes = (Vec_Int_t *)Vec_PtrEntry(vvNodes, i);
|
||||
Abc_Obj_t * pNode; int j;
|
||||
Abc_NtkForEachObjVec( vNodes, p, pNode, j )
|
||||
if ( Abc_NodeIsTravIdCurrent(pNode) )
|
||||
break;
|
||||
Abc_NtkForEachObjVec( vOuts, p, pNode, k )
|
||||
if ( Abc_NodeIsTravIdCurrent(pNode) )
|
||||
break;
|
||||
if ( j < Vec_IntSize(vIns) || k < Vec_IntSize(vOuts) )
|
||||
if ( j < Vec_IntSize(vNodes) )
|
||||
Vec_IntWriteEntry( vGains, i, -1 );
|
||||
}
|
||||
}
|
||||
|
|
@ -1764,8 +1760,8 @@ void Abc_NtKMarkTfiTfo( Vec_Int_t * vOne, Abc_Ntk_t * pNtk )
|
|||
{
|
||||
int i; Abc_Obj_t * pObj;
|
||||
Abc_NtkForEachObjVec( vOne, pNtk, pObj, i ) {
|
||||
Abc_NodeSetTravIdPrevious(pObj);
|
||||
Abc_ObjDfsMark_rec( pObj );
|
||||
//Abc_NodeSetTravIdPrevious(pObj);
|
||||
//Abc_ObjDfsMark_rec( pObj );
|
||||
Abc_NodeSetTravIdPrevious(pObj);
|
||||
Abc_ObjDfsMark2_rec( pObj );
|
||||
}
|
||||
|
|
@ -1939,7 +1935,7 @@ void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOver
|
|||
Abc_Ntk_t * pNtk = Abc_NtkDupDfs(Abc_FrameReadNtk(Abc_FrameGetGlobalFrame()));
|
||||
Vec_Ptr_t * vWins = Abc_NtkExtractPartitions( pNtk, i, nSuppMax, &vIns, &vOuts, &vNodes, fOverlap );
|
||||
Vec_Int_t * vGains = Abc_NtkStochProcess( vWins, pScript, nProcs, 0, 0 ); int nPartsInit = Vec_PtrSize(vWins);
|
||||
Abc_Ntk_t * pNew = Abc_NtkInsertPartitions( pNtk, vIns, vOuts, vWins, fOverlap, vGains );
|
||||
Abc_Ntk_t * pNew = Abc_NtkInsertPartitions( pNtk, vIns, vNodes, vOuts, vWins, fOverlap, vGains );
|
||||
Abc_FrameReplaceCurrentNetwork( Abc_FrameGetGlobalFrame(), pNew );
|
||||
if ( fVerbose )
|
||||
printf( "Iteration %3d : Using %3d -> %3d partitions. Reducing area from %.2f to %.2f. ",
|
||||
|
|
@ -1961,7 +1957,7 @@ void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOver
|
|||
}
|
||||
aEnd = Abc_NtkGetMappedArea(Abc_FrameReadNtk(Abc_FrameGetGlobalFrame()));
|
||||
if ( fVerbose )
|
||||
printf( "Cumulatively reduced area by %.2f %% after %d iterations. ", 100.0*(aBeg - aEnd)/aBeg, nIters );
|
||||
printf( "Cumulatively reduced area by %.2f %% after %d iterations. ", 100.0*(aBeg - aEnd)/Abc_MaxFloat(aBeg, (float)1.0), nIters );
|
||||
if ( fVerbose )
|
||||
Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart );
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1548,6 +1548,24 @@ void Abc_NtkPrintGates( Abc_Ntk_t * pNtk, int fUseLibrary, int fUpdateProfile )
|
|||
if ( fHasBdds )
|
||||
Abc_NtkSopToBdd(pNtk);
|
||||
}
|
||||
void Abc_NtkPrintGates2( Abc_Ntk_t * pNtk )
|
||||
{
|
||||
Abc_Obj_t * pNode; int n, nFaninMax = Abc_NtkGetFaninMax(pNtk);
|
||||
Abc_NtkForEachNode( pNtk, pNode, n )
|
||||
{
|
||||
if ( Abc_ObjFaninNum(pNode) < 2 )
|
||||
continue;
|
||||
word uTruth = Mio_GateReadTruth((Mio_Gate_t *)pNode->pData);
|
||||
printf( "Node %d : ", Abc_ObjId(pNode) );
|
||||
printf( "Fanins %d : ", Abc_ObjFaninNum(pNode) );
|
||||
printf( "Gate %10s : ", Mio_GateReadName((Mio_Gate_t *)pNode->pData) );
|
||||
printf( "Func " );
|
||||
for ( int i = 0; i < (1 << nFaninMax)-(1 << Abc_ObjFaninNum(pNode)); i++ )
|
||||
printf( " " );
|
||||
Extra_PrintBinary( stdout, (unsigned *)&uTruth, 1 << Abc_ObjFaninNum(pNode) );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ void Acb_NtkRunGen( int nInputs, int nMints, int nFuncs, int Seed, int fVerbose,
|
|||
Vec_IntAddToEntry( vNodes, nNodes, 1 );
|
||||
|
||||
if ( fVerbose ) {
|
||||
printf( "Iteration %3d : ", i );
|
||||
printf( "Function %4d : ", i );
|
||||
printf( "Random function has %d positive minterms ", nMints );
|
||||
printf( "and maps into %d nodes.\n", nNodes );
|
||||
if ( fVerbose )
|
||||
|
|
|
|||
162
src/base/io/io.c
162
src/base/io/io.c
|
|
@ -58,9 +58,11 @@ static int IoCommandReadVerilog ( Abc_Frame_t * pAbc, int argc, char **argv );
|
|||
static int IoCommandReadStatus ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadGig ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadJson ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadJsonc ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadSF ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadRom ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadMM ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandReadMMGia ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
|
||||
static int IoCommandWrite ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandWriteHie ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
|
|
@ -92,6 +94,7 @@ static int IoCommandWriteSmv ( Abc_Frame_t * pAbc, int argc, char **argv );
|
|||
static int IoCommandWriteJson ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandWriteResub ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandWriteMM ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
static int IoCommandWriteMMGia ( Abc_Frame_t * pAbc, int argc, char **argv );
|
||||
|
||||
extern void Abc_FrameCopyLTLDataBase( Abc_Frame_t *pAbc, Abc_Ntk_t * pNtk );
|
||||
|
||||
|
|
@ -136,9 +139,11 @@ void Io_Init( Abc_Frame_t * pAbc )
|
|||
Cmd_CommandAdd( pAbc, "I/O", "read_status", IoCommandReadStatus, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "&read_gig", IoCommandReadGig, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "read_json", IoCommandReadJson, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "read_jsonc", IoCommandReadJsonc, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "read_sf", IoCommandReadSF, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "read_rom", IoCommandReadRom, 1 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "read_mm", IoCommandReadMM, 1 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "&read_mm", IoCommandReadMMGia, 1 );
|
||||
|
||||
Cmd_CommandAdd( pAbc, "I/O", "write", IoCommandWrite, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "write_hie", IoCommandWriteHie, 0 );
|
||||
|
|
@ -172,6 +177,7 @@ void Io_Init( Abc_Frame_t * pAbc )
|
|||
Cmd_CommandAdd( pAbc, "I/O", "write_json", IoCommandWriteJson, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "&write_resub", IoCommandWriteResub, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "write_mm", IoCommandWriteMM, 0 );
|
||||
Cmd_CommandAdd( pAbc, "I/O", "&write_mm", IoCommandWriteMMGia, 0 );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -1868,6 +1874,60 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int IoCommandReadJsonc( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern int Jsonc_ReadTest( char * pFileName );
|
||||
char * pFileName;
|
||||
FILE * pFile;
|
||||
int c;
|
||||
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
{
|
||||
goto usage;
|
||||
}
|
||||
|
||||
// get the input file name
|
||||
pFileName = argv[globalUtilOptind];
|
||||
if ( (pFile = fopen( pFileName, "r" )) == NULL )
|
||||
{
|
||||
fprintf( pAbc->Err, "Cannot open input file \"%s\". \n", pFileName );
|
||||
return 1;
|
||||
}
|
||||
fclose( pFile );
|
||||
|
||||
Jsonc_ReadTest( pFileName );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: read_jsonc [-h] <file>\n" );
|
||||
fprintf( pAbc->Err, "\t reads file in JSON format\n" );
|
||||
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
|
||||
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -2048,6 +2108,54 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int IoCommandReadMMGia( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkReadFromFile( char * pFileName );
|
||||
Abc_Ntk_t * pNtk; char * pFileName; int c;
|
||||
Gia_Man_t * pGia = NULL;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
goto usage;
|
||||
pFileName = argv[globalUtilOptind];
|
||||
pNtk = Abc_NtkReadFromFile( pFileName );
|
||||
if ( pNtk == NULL )
|
||||
return 0;
|
||||
Abc_NtkToAig( pNtk );
|
||||
pGia = Abc_NtkAigToGia( pNtk, 0 );
|
||||
Abc_NtkDelete( pNtk );
|
||||
Abc_FrameUpdateGia( pAbc, pGia );
|
||||
Abc_FrameClearVerifStatus( pAbc );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: &read_mm [-h] <file>\n" );
|
||||
fprintf( pAbc->Err, "\t reads mapped network from file\n" );
|
||||
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
|
||||
fprintf( pAbc->Err, "\tfile : the name of a file to read\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -4317,6 +4425,60 @@ usage:
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int IoCommandWriteMMGia( Abc_Frame_t * pAbc, int argc, char **argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p, int fUseBuffs );
|
||||
extern int Abc_NtkWriteToFile( char * pFileName, Abc_Ntk_t * pNtk );
|
||||
Abc_Ntk_t * pNtk = NULL;
|
||||
char * pFileName = NULL; int c;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "h" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
goto usage;
|
||||
}
|
||||
}
|
||||
if ( argc != globalUtilOptind + 1 )
|
||||
goto usage;
|
||||
pFileName = argv[globalUtilOptind];
|
||||
if ( pAbc->pGia == NULL )
|
||||
{
|
||||
Abc_Print( -1, "IoCommandWriteMMGia(): There is no current AIG.\n" );
|
||||
return 1;
|
||||
}
|
||||
if ( !Gia_ManHasCellMapping(pAbc->pGia) )
|
||||
{
|
||||
Abc_Print( -1, "IoCommandWriteMMGia(): Current AIG is not mapped.\n" );
|
||||
return 1;
|
||||
}
|
||||
pNtk = Abc_NtkFromCellMappedGia( pAbc->pGia, 0 );
|
||||
Abc_NtkWriteToFile( pFileName, pNtk );
|
||||
Abc_NtkDelete( pNtk );
|
||||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: &write_mm [-h] <file>\n" );
|
||||
fprintf( pAbc->Err, "\t write cell mapped current AIG into a file\n" );
|
||||
fprintf( pAbc->Err, "\t-h : print the help message\n" );
|
||||
fprintf( pAbc->Err, "\tfile : the name of the file to write\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -0,0 +1,613 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [ioJsonc.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Command processing package.]
|
||||
|
||||
Synopsis [Procedures to read JSON.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: ioJsonc.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "ioAbc.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// JSON value types
|
||||
typedef enum {
|
||||
JSON_NULL,
|
||||
JSON_BOOL,
|
||||
JSON_NUMBER,
|
||||
JSON_STRING,
|
||||
JSON_ARRAY,
|
||||
JSON_OBJECT
|
||||
} json_type_t;
|
||||
|
||||
// Core structure: stores offset and length in the original string
|
||||
typedef struct {
|
||||
uint32_t offset; // Offset in the JSON string
|
||||
uint32_t length; // Length of this value
|
||||
json_type_t type; // Type of JSON value
|
||||
} json_value_t;
|
||||
|
||||
// Key-value pair for objects
|
||||
typedef struct {
|
||||
json_value_t key; // Key (always a string)
|
||||
json_value_t value; // Associated value
|
||||
} json_pair_t;
|
||||
|
||||
// Dynamic array for storing pairs (objects) or values (arrays)
|
||||
typedef struct {
|
||||
union {
|
||||
json_pair_t *pairs; // For objects
|
||||
json_value_t *values; // For arrays
|
||||
} data;
|
||||
uint32_t count; // Number of elements
|
||||
uint32_t capacity; // Allocated capacity
|
||||
} json_container_t;
|
||||
|
||||
// Main JSON structure
|
||||
typedef struct {
|
||||
char *str; // The original JSON string
|
||||
uint32_t str_len; // Length of the string
|
||||
json_value_t root; // Root element
|
||||
json_container_t *containers; // Array of containers
|
||||
uint32_t container_count; // Number of containers
|
||||
uint32_t container_capacity; // Allocated capacity
|
||||
} json_t;
|
||||
|
||||
// Function prototypes
|
||||
json_t* json_create(void);
|
||||
void json_destroy(json_t *json);
|
||||
bool json_load_file(json_t *json, const char *filename);
|
||||
json_value_t json_parse_value(json_t *json, uint32_t *pos);
|
||||
json_container_t* json_add_container(json_t *json);
|
||||
void json_skip_whitespace(const char *str, uint32_t *pos, uint32_t len);
|
||||
json_value_t json_parse_string(json_t *json, uint32_t *pos);
|
||||
json_value_t json_parse_number(json_t *json, uint32_t *pos);
|
||||
json_value_t json_parse_object(json_t *json, uint32_t *pos);
|
||||
json_value_t json_parse_array(json_t *json, uint32_t *pos);
|
||||
void json_print(json_t *json, FILE *fp);
|
||||
void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool format);
|
||||
void json_print_string(json_t *json, json_value_t val, FILE *fp);
|
||||
void json_debug_value(json_t *json, json_value_t val, int indent);
|
||||
|
||||
// Create a new JSON structure
|
||||
json_t* json_create(void) {
|
||||
json_t *json = (json_t*)calloc(1, sizeof(json_t));
|
||||
if (!json) return NULL;
|
||||
|
||||
json->container_capacity = 16;
|
||||
json->containers = (json_container_t*)calloc(json->container_capacity, sizeof(json_container_t));
|
||||
if (!json->containers) {
|
||||
free(json);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
// Destroy JSON structure and free memory
|
||||
void json_destroy(json_t *json) {
|
||||
if (!json) return;
|
||||
|
||||
// Free containers
|
||||
for (uint32_t i = 0; i < json->container_count; i++) {
|
||||
if (json->containers[i].data.pairs) {
|
||||
free(json->containers[i].data.pairs);
|
||||
}
|
||||
}
|
||||
free(json->containers);
|
||||
|
||||
// Free the JSON string
|
||||
free(json->str);
|
||||
|
||||
// Free the structure
|
||||
free(json);
|
||||
}
|
||||
|
||||
// Skip whitespace and comments
|
||||
void json_skip_whitespace(const char *str, uint32_t *pos, uint32_t len) {
|
||||
while (*pos < len) {
|
||||
// Skip whitespace
|
||||
if (str[*pos] == ' ' || str[*pos] == '\t' ||
|
||||
str[*pos] == '\n' || str[*pos] == '\r') {
|
||||
(*pos)++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip single-line comments
|
||||
if (*pos + 1 < len && str[*pos] == '/' && str[*pos + 1] == '/') {
|
||||
*pos += 2;
|
||||
while (*pos < len && str[*pos] != '\n') {
|
||||
(*pos)++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip multi-line comments
|
||||
if (*pos + 1 < len && str[*pos] == '/' && str[*pos + 1] == '*') {
|
||||
*pos += 2;
|
||||
while (*pos + 1 < len) {
|
||||
if (str[*pos] == '*' && str[*pos + 1] == '/') {
|
||||
*pos += 2;
|
||||
break;
|
||||
}
|
||||
(*pos)++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not whitespace or comment
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a new container and return pointer to it
|
||||
json_container_t* json_add_container(json_t *json) {
|
||||
if (json->container_count >= json->container_capacity) {
|
||||
uint32_t new_capacity = json->container_capacity * 2;
|
||||
json_container_t *new_containers = (json_container_t*)realloc(
|
||||
json->containers, new_capacity * sizeof(json_container_t));
|
||||
if (!new_containers) return NULL;
|
||||
|
||||
json->containers = new_containers;
|
||||
json->container_capacity = new_capacity;
|
||||
}
|
||||
|
||||
json_container_t *container = &json->containers[json->container_count];
|
||||
memset(container, 0, sizeof(json_container_t));
|
||||
json->container_count++;
|
||||
return container;
|
||||
}
|
||||
|
||||
// Parse a JSON string
|
||||
json_value_t json_parse_string(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.type = JSON_STRING;
|
||||
val.offset = *pos;
|
||||
|
||||
(*pos)++; // Skip opening quote
|
||||
|
||||
while (*pos < json->str_len && json->str[*pos] != '"') {
|
||||
if (json->str[*pos] == '\\') (*pos)++; // Skip escaped character
|
||||
(*pos)++;
|
||||
}
|
||||
|
||||
(*pos)++; // Skip closing quote
|
||||
val.length = *pos - val.offset;
|
||||
return val;
|
||||
}
|
||||
|
||||
// Parse a JSON number
|
||||
json_value_t json_parse_number(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.type = JSON_NUMBER;
|
||||
val.offset = *pos;
|
||||
|
||||
if (json->str[*pos] == '-') (*pos)++;
|
||||
|
||||
while (*pos < json->str_len &&
|
||||
((json->str[*pos] >= '0' && json->str[*pos] <= '9') ||
|
||||
json->str[*pos] == '.' || json->str[*pos] == 'e' ||
|
||||
json->str[*pos] == 'E' || json->str[*pos] == '+' ||
|
||||
json->str[*pos] == '-')) {
|
||||
(*pos)++;
|
||||
}
|
||||
|
||||
val.length = *pos - val.offset;
|
||||
return val;
|
||||
}
|
||||
|
||||
// Parse a JSON object
|
||||
json_value_t json_parse_object(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.type = JSON_OBJECT;
|
||||
val.offset = *pos;
|
||||
|
||||
(*pos)++; // Skip '{'
|
||||
|
||||
json_container_t *container = json_add_container(json);
|
||||
if (!container) return val;
|
||||
|
||||
container->capacity = 8;
|
||||
container->data.pairs = (json_pair_t*)calloc(container->capacity, sizeof(json_pair_t));
|
||||
if (!container->data.pairs) return val;
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
|
||||
while (*pos < json->str_len && json->str[*pos] != '}') {
|
||||
// Parse key
|
||||
json_value_t key = json_parse_string(json, pos);
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
(*pos)++; // Skip ':'
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
|
||||
// Parse value
|
||||
json_value_t value = json_parse_value(json, pos);
|
||||
|
||||
// Add pair to container
|
||||
if (container->count >= container->capacity) {
|
||||
uint32_t new_capacity = container->capacity * 2;
|
||||
json_pair_t *new_pairs = (json_pair_t*)realloc(
|
||||
container->data.pairs, new_capacity * sizeof(json_pair_t));
|
||||
if (!new_pairs) return val;
|
||||
|
||||
container->data.pairs = new_pairs;
|
||||
container->capacity = new_capacity;
|
||||
}
|
||||
|
||||
container->data.pairs[container->count].key = key;
|
||||
container->data.pairs[container->count].value = value;
|
||||
container->count++;
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
if (json->str[*pos] == ',') {
|
||||
(*pos)++;
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
}
|
||||
}
|
||||
|
||||
(*pos)++; // Skip '}'
|
||||
val.length = *pos - val.offset;
|
||||
return val;
|
||||
}
|
||||
|
||||
// Parse a JSON array
|
||||
json_value_t json_parse_array(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
val.type = JSON_ARRAY;
|
||||
val.offset = *pos;
|
||||
|
||||
(*pos)++; // Skip '['
|
||||
|
||||
json_container_t *container = json_add_container(json);
|
||||
if (!container) return val;
|
||||
|
||||
container->capacity = 8;
|
||||
container->data.values = (json_value_t*)calloc(container->capacity, sizeof(json_value_t));
|
||||
if (!container->data.values) return val;
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
|
||||
while (*pos < json->str_len && json->str[*pos] != ']') {
|
||||
// Parse value
|
||||
json_value_t value = json_parse_value(json, pos);
|
||||
|
||||
// Add value to container
|
||||
if (container->count >= container->capacity) {
|
||||
uint32_t new_capacity = container->capacity * 2;
|
||||
json_value_t *new_values = (json_value_t*)realloc(
|
||||
container->data.values, new_capacity * sizeof(json_value_t));
|
||||
if (!new_values) return val;
|
||||
|
||||
container->data.values = new_values;
|
||||
container->capacity = new_capacity;
|
||||
}
|
||||
|
||||
container->data.values[container->count] = value;
|
||||
container->count++;
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
if (json->str[*pos] == ',') {
|
||||
(*pos)++;
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
}
|
||||
}
|
||||
|
||||
(*pos)++; // Skip ']'
|
||||
val.length = *pos - val.offset;
|
||||
return val;
|
||||
}
|
||||
|
||||
// Parse any JSON value
|
||||
json_value_t json_parse_value(json_t *json, uint32_t *pos) {
|
||||
json_value_t val = {0};
|
||||
|
||||
json_skip_whitespace(json->str, pos, json->str_len);
|
||||
|
||||
if (*pos >= json->str_len) return val;
|
||||
|
||||
char c = json->str[*pos];
|
||||
|
||||
if (c == '"') {
|
||||
return json_parse_string(json, pos);
|
||||
} else if (c == '{') {
|
||||
return json_parse_object(json, pos);
|
||||
} else if (c == '[') {
|
||||
return json_parse_array(json, pos);
|
||||
} else if (c == 'n') {
|
||||
val.type = JSON_NULL;
|
||||
val.offset = *pos;
|
||||
val.length = 4;
|
||||
*pos += 4;
|
||||
return val;
|
||||
} else if (c == 't') {
|
||||
val.type = JSON_BOOL;
|
||||
val.offset = *pos;
|
||||
val.length = 4;
|
||||
*pos += 4;
|
||||
return val;
|
||||
} else if (c == 'f') {
|
||||
val.type = JSON_BOOL;
|
||||
val.offset = *pos;
|
||||
val.length = 5;
|
||||
*pos += 5;
|
||||
return val;
|
||||
} else if ((c >= '0' && c <= '9') || c == '-') {
|
||||
return json_parse_number(json, pos);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
// Load JSON from file
|
||||
bool json_load_file(json_t *json, const char *filename) {
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp) return false;
|
||||
|
||||
// Get file size
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long file_size = ftell(fp);
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
|
||||
if (file_size > INT32_MAX) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allocate buffer
|
||||
json->str = (char*)malloc(file_size + 1);
|
||||
if (!json->str) {
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read file
|
||||
size_t bytes_read = fread(json->str, 1, file_size, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (bytes_read != (size_t)file_size) {
|
||||
free(json->str);
|
||||
json->str = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
json->str[file_size] = '\0';
|
||||
json->str_len = (uint32_t)file_size;
|
||||
|
||||
// Parse JSON
|
||||
uint32_t pos = 0;
|
||||
json->root = json_parse_value(json, &pos);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper function to print a JSON value (for debugging)
|
||||
void json_debug_value(json_t *json, json_value_t val, int indent) {
|
||||
for (int i = 0; i < indent; i++) printf(" ");
|
||||
|
||||
printf("Type: %d, Offset: %u, Length: %u, Content: '",
|
||||
val.type, val.offset, val.length);
|
||||
|
||||
for (uint32_t i = 0; i < val.length && i < 50; i++) {
|
||||
putchar(json->str[val.offset + i]);
|
||||
}
|
||||
if (val.length > 50) printf("...");
|
||||
printf("'\n");
|
||||
}
|
||||
|
||||
// Print a JSON string value with proper escaping
|
||||
void json_print_string(json_t *json, json_value_t val, FILE *fp) {
|
||||
fputc('"', fp);
|
||||
|
||||
// Skip the quotes in the original string
|
||||
uint32_t start = val.offset + 1;
|
||||
uint32_t end = val.offset + val.length - 1;
|
||||
|
||||
for (uint32_t i = start; i < end; i++) {
|
||||
char c = json->str[i];
|
||||
if (c == '\\' && i + 1 < end) {
|
||||
// Handle escape sequences
|
||||
fputc(c, fp);
|
||||
i++;
|
||||
fputc(json->str[i], fp);
|
||||
} else {
|
||||
fputc(c, fp);
|
||||
}
|
||||
}
|
||||
|
||||
fputc('"', fp);
|
||||
}
|
||||
|
||||
// Find the container index for a given value
|
||||
static int find_container_index(json_t *json, json_value_t val) {
|
||||
static int last_container = 0;
|
||||
|
||||
// Check if it's an object or array
|
||||
if (val.type == JSON_OBJECT || val.type == JSON_ARRAY) {
|
||||
int index = last_container++;
|
||||
if (index < json->container_count) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Print a JSON value recursively
|
||||
void json_print_value(json_t *json, json_value_t val, FILE *fp, int indent, bool format) {
|
||||
static int container_index = 0;
|
||||
|
||||
switch (val.type) {
|
||||
case JSON_NULL:
|
||||
fprintf(fp, "null");
|
||||
break;
|
||||
|
||||
case JSON_BOOL:
|
||||
if (json->str[val.offset] == 't') {
|
||||
fprintf(fp, "true");
|
||||
} else {
|
||||
fprintf(fp, "false");
|
||||
}
|
||||
break;
|
||||
|
||||
case JSON_NUMBER:
|
||||
for (uint32_t i = 0; i < val.length; i++) {
|
||||
fputc(json->str[val.offset + i], fp);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSON_STRING:
|
||||
json_print_string(json, val, fp);
|
||||
break;
|
||||
|
||||
case JSON_ARRAY: {
|
||||
fputc('[', fp);
|
||||
|
||||
if (container_index < json->container_count) {
|
||||
json_container_t *container = &json->containers[container_index++];
|
||||
|
||||
for (uint32_t i = 0; i < container->count; i++) {
|
||||
if (format) {
|
||||
fprintf(fp, "\n");
|
||||
for (int j = 0; j < indent + 1; j++) fprintf(fp, " ");
|
||||
}
|
||||
|
||||
json_print_value(json, container->data.values[i], fp, indent + 1, format);
|
||||
|
||||
if (i < container->count - 1) {
|
||||
fputc(',', fp);
|
||||
if (!format) fputc(' ', fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (format && container->count > 0) {
|
||||
fprintf(fp, "\n");
|
||||
for (int j = 0; j < indent; j++) fprintf(fp, " ");
|
||||
}
|
||||
}
|
||||
|
||||
fputc(']', fp);
|
||||
break;
|
||||
}
|
||||
|
||||
case JSON_OBJECT: {
|
||||
fputc('{', fp);
|
||||
|
||||
if (container_index < json->container_count) {
|
||||
json_container_t *container = &json->containers[container_index++];
|
||||
|
||||
for (uint32_t i = 0; i < container->count; i++) {
|
||||
if (format) {
|
||||
fprintf(fp, "\n");
|
||||
for (int j = 0; j < indent + 1; j++) fprintf(fp, " ");
|
||||
}
|
||||
|
||||
json_print_string(json, container->data.pairs[i].key, fp);
|
||||
fprintf(fp, ": ");
|
||||
json_print_value(json, container->data.pairs[i].value, fp, indent + 1, format);
|
||||
|
||||
if (i < container->count - 1) {
|
||||
fputc(',', fp);
|
||||
if (!format) fputc(' ', fp);
|
||||
}
|
||||
}
|
||||
|
||||
if (format && container->count > 0) {
|
||||
fprintf(fp, "\n");
|
||||
for (int j = 0; j < indent; j++) fprintf(fp, " ");
|
||||
}
|
||||
}
|
||||
|
||||
fputc('}', fp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print the entire JSON to a file
|
||||
void json_print(json_t *json, FILE *fp) {
|
||||
// Reset the static container index in json_print_value
|
||||
json_print_value(json, json->root, fp, 0, true);
|
||||
fprintf(fp, "\n");
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Jsonc_ReadTest( char * pFileName )
|
||||
{
|
||||
json_t *json = json_create();
|
||||
if (!json) {
|
||||
fprintf(stderr, "Failed to create JSON structure\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Parsing JSONC file: %s\n", pFileName);
|
||||
if (!json_load_file(json, pFileName)) {
|
||||
fprintf(stderr, "Failed to load JSON file\n");
|
||||
json_destroy(json);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("JSON parsed successfully!\n");
|
||||
printf("String length: %u\n", json->str_len);
|
||||
printf("Container count: %u\n", json->container_count);
|
||||
|
||||
//printf("\nRoot value:\n");
|
||||
//json_debug_value(json, json->root, 0);
|
||||
|
||||
/*
|
||||
// Print the parsed JSON to a file (without comments)
|
||||
FILE *fp = fopen(output_file, "w");
|
||||
if (fp) {
|
||||
printf("\nWriting parsed JSON to: %s\n", output_file);
|
||||
json_print(json, fp);
|
||||
fclose(fp);
|
||||
printf("Output written successfully!\n");
|
||||
} else {
|
||||
fprintf(stderr, "Failed to open output file\n");
|
||||
}
|
||||
*/
|
||||
// Also print to stdout for verification
|
||||
printf("\nParsed JSON output:\n");
|
||||
json_print(json, stdout);
|
||||
|
||||
json_destroy(json);
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
||||
|
|
@ -696,6 +696,35 @@ static char * Io_MvLoadFile( char * pFileName )
|
|||
return pContents;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Io_MvReplaceBuffersByShorts( char * p )
|
||||
{
|
||||
if ( !strstr(p, ".gate") )
|
||||
return;
|
||||
char * q, * pNext, * pShort = (char *)".short"; int i;
|
||||
for ( q = p; *q && (pNext = strstr(q, ".names")); q = pNext ) {
|
||||
for ( i = 0; i < 6; i++ )
|
||||
pNext[i] = pShort[i];
|
||||
while ( *pNext && *pNext++ != '\n' );
|
||||
if ( *pNext == 0 )
|
||||
return;
|
||||
while ( *pNext && *pNext != '\n' )
|
||||
*pNext++ = ' ';
|
||||
if ( *pNext == 0 )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the parsing.]
|
||||
|
|
@ -717,6 +746,8 @@ static void Io_MvReadPreparse( Io_MvMan_t * p )
|
|||
{
|
||||
char * pCur, * pPrev;
|
||||
int i, fComment = 0;
|
||||
Io_MvReplaceBuffersByShorts( p->pBuffer );
|
||||
|
||||
// parse the buffer into lines and remove comments
|
||||
Vec_PtrPush( p->vLines, p->pBuffer );
|
||||
for ( pCur = p->pBuffer; *pCur; pCur++ )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
SRC += src/base/io/io.c \
|
||||
src/base/io/ioJson.c \
|
||||
src/base/io/ioJsonc.c \
|
||||
src/base/io/ioReadAiger.c \
|
||||
src/base/io/ioReadBaf.c \
|
||||
src/base/io/ioReadBblif.c \
|
||||
|
|
|
|||
|
|
@ -337,15 +337,15 @@ void Abc_FrameStorePrint( Abc_Frame_t * pAbc )
|
|||
{
|
||||
if ( pAbc->pHash == NULL )
|
||||
Abc_FrameStoreStart( pAbc );
|
||||
int i, Entry, Max = Vec_IntFindMax( pAbc->pHash->vValue );
|
||||
int i, Entry, nAll = 0, Max = Vec_IntFindMax( pAbc->pHash->vValue );
|
||||
Vec_Int_t * vCounts = Vec_IntStart( Max+1 );
|
||||
Vec_IntForEachEntry( pAbc->pHash->vValue, Entry, i )
|
||||
Vec_IntAddToEntry( vCounts, Entry, 1 );
|
||||
printf( "Distribution of %d stored items by reference count (<ref_count>=<num_items>): ", Hsh_VecSize(pAbc->pHash) );
|
||||
Vec_IntForEachEntry( vCounts, Entry, i )
|
||||
if ( Entry )
|
||||
printf( "%d=%d ", i, Entry );
|
||||
printf( "\n" );
|
||||
printf( "%d=%d ", i, Entry ), nAll += i * Entry;
|
||||
printf( "ALL=%d\n", nAll );
|
||||
Vec_IntFree( vCounts );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1339,12 +1339,26 @@ int Ver_ParseGateStandard( Ver_Man_t * pMan, Abc_Ntk_t * pNtk, Ver_GateType_t Ga
|
|||
return 0;
|
||||
Ver_StreamMove( p );
|
||||
|
||||
// this is gate name - throw it away
|
||||
// assume there is a gate name if the current char is not '(', e.g. xor g1 (z, a, b);
|
||||
if ( Ver_StreamPopChar(p) != '(' )
|
||||
{
|
||||
sprintf( pMan->sError, "Cannot parse a standard gate (expected opening parenthesis)." );
|
||||
Ver_ParsePrintErrorMessage( pMan );
|
||||
return 0;
|
||||
// this is gate name - throw it away
|
||||
pWord = Ver_ParseGetName( pMan );
|
||||
if (pWord == NULL)
|
||||
{
|
||||
sprintf( pMan->sError, "Cannot parse a standard gate (expected a name before an opening parenthesis)." );
|
||||
Ver_ParsePrintErrorMessage( pMan );
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( Ver_StreamPopChar(p) != '(' )
|
||||
{
|
||||
sprintf( pMan->sError, "Cannot parse a standard gate (expected opening parenthesis)." );
|
||||
Ver_ParsePrintErrorMessage( pMan );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ver_ParseSkipComments( pMan );
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "wlc.h"
|
||||
#include "misc/tim/tim.h"
|
||||
#include "base/main/main.h"
|
||||
#include "base/main/mainInt.h"
|
||||
#include "base/cmd/cmd.h"
|
||||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
|
@ -2690,6 +2691,11 @@ Gia_Man_t * Wlc_NtkBitBlast( Wlc_Ntk_t * p, Wlc_BstPar_t * pParIn )
|
|||
Vec_PtrFreeFree( pNew->vNamesOut ); pNew->vNamesOut = NULL;
|
||||
}
|
||||
pNew->vRegClasses = vRegClasses;
|
||||
// save initial box info
|
||||
// if ( pNew->pManTime ) {
|
||||
// Abc_Frame_t * pAbc = Abc_FrameGetGlobalFrame();
|
||||
// pAbc->vMiniLutObjs = Gia_ManDeriveBoxMapping( pNew );
|
||||
// }
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ void Wln_End( Abc_Frame_t * pAbc )
|
|||
******************************************************************************/
|
||||
int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
||||
{
|
||||
extern Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose );
|
||||
extern Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fSkipStrash, int fInvert, int fTechMap, int fLibInDir, int fVerbose );
|
||||
extern Rtl_Lib_t * Wln_ReadSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, int fCollapse, int fVerbose );
|
||||
|
||||
|
|
@ -99,6 +100,7 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
char * pFileName = NULL;
|
||||
char * pTopModule= NULL;
|
||||
char * pDefines = NULL;
|
||||
char * pLibrary = NULL;
|
||||
int fBlast = 0;
|
||||
int fInvert = 0;
|
||||
int fTechMap = 1;
|
||||
|
|
@ -107,7 +109,7 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
int fCollapse = 0;
|
||||
int c, fVerbose = 0;
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "TDbismlcvh" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "TDLbismlcvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -129,6 +131,15 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
pDefines = argv[globalUtilOptind];
|
||||
globalUtilOptind++;
|
||||
break;
|
||||
case 'L':
|
||||
if ( globalUtilOptind >= argc )
|
||||
{
|
||||
Abc_Print( -1, "Command line switch \"-L\" should be followed by a file name.\n" );
|
||||
goto usage;
|
||||
}
|
||||
pLibrary = argv[globalUtilOptind];
|
||||
globalUtilOptind++;
|
||||
break;
|
||||
case 'b':
|
||||
fBlast ^= 1;
|
||||
break;
|
||||
|
|
@ -174,7 +185,21 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
fclose( pFile );
|
||||
|
||||
// perform reading
|
||||
if ( fBlast )
|
||||
if ( pLibrary )
|
||||
{
|
||||
Abc_Ntk_t * pNtk = NULL;
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
pNtk = Wln_ReadMappedSystemVerilog( pFileName, pTopModule, pDefines, pLibrary, fVerbose );
|
||||
else if ( !strcmp( Extra_FileNameExtension(pFileName), "sv" ) )
|
||||
pNtk = Wln_ReadMappedSystemVerilog( pFileName, pTopModule, pDefines, pLibrary, fVerbose );
|
||||
else
|
||||
{
|
||||
printf( "Abc_CommandYosys(): Unknown file extension.\n" );
|
||||
return 0;
|
||||
}
|
||||
Abc_FrameReplaceCurrentNetwork( pAbc, pNtk );
|
||||
}
|
||||
else if ( fBlast )
|
||||
{
|
||||
Gia_Man_t * pNew = NULL;
|
||||
if ( !strcmp( Extra_FileNameExtension(pFileName), "v" ) )
|
||||
|
|
@ -208,10 +233,11 @@ int Abc_CommandYosys( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
}
|
||||
return 0;
|
||||
usage:
|
||||
Abc_Print( -2, "usage: %%yosys [-T <module>] [-D <defines>] [-bismlcvh] <file_name>\n" );
|
||||
Abc_Print( -2, "usage: %%yosys [-T <module>] [-D <defines>] [-L <liberty_file>] [-bismlcvh] <file_name>\n" );
|
||||
Abc_Print( -2, "\t reads Verilog or SystemVerilog using Yosys\n" );
|
||||
Abc_Print( -2, "\t-T : specify the top module name (default uses \"-auto-top\")\n" );
|
||||
Abc_Print( -2, "\t-D : specify defines to be used by Yosys (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-L : specify the Liberty library to read a mapped design (default \"not used\")\n" );
|
||||
Abc_Print( -2, "\t-b : toggle bit-blasting the design into an AIG using Yosys [default = %s]\n", fBlast? "yes": "no" );
|
||||
Abc_Print( -2, "\t-i : toggle inverting the outputs (useful for miters) [default = %s]\n", fInvert? "yes": "no" );
|
||||
Abc_Print( -2, "\t-s : toggle no structural hashing during bit-blasting [default = %s]\n", fSkipStrash? "no strash": "strash" );
|
||||
|
|
|
|||
|
|
@ -211,6 +211,48 @@ Gia_Man_t * Wln_BlastSystemVerilog( char * pFileName, char * pTopModule, char *
|
|||
}
|
||||
return pGia;
|
||||
}
|
||||
Abc_Ntk_t * Wln_ReadMappedSystemVerilog( char * pFileName, char * pTopModule, char * pDefines, char * pLibrary, int fVerbose )
|
||||
{
|
||||
Abc_Ntk_t * pNtk = NULL;
|
||||
char Command[1000];
|
||||
char * pFileTemp = "_temp_.blif";
|
||||
int fSVlog = strstr(pFileName, ".sv") != NULL;
|
||||
sprintf( Command, "%s -qp \"read_liberty -lib %s; read %s %s%s %s; hierarchy %s%s; flatten; proc; write_blif %s%s -impltf -gates %s\"",
|
||||
Wln_GetYosysName(),
|
||||
pLibrary,
|
||||
fSVlog ? "-sv " : "-vlog95",
|
||||
pDefines ? "-D" : "",
|
||||
pDefines ? pDefines : "",
|
||||
pFileName,
|
||||
pTopModule ? "-top " : "-auto-top",
|
||||
pTopModule ? pTopModule : "",
|
||||
pTopModule ? "-top " : "",
|
||||
pTopModule ? pTopModule : "",
|
||||
pFileTemp );
|
||||
if ( fVerbose )
|
||||
printf( "%s\n", Command );
|
||||
if ( !Wln_ConvertToRtl(Command, pFileTemp) )
|
||||
return NULL;
|
||||
sprintf( Command, "read_lib %s", pLibrary );
|
||||
if ( Cmd_CommandExecute( Abc_FrameReadGlobalFrame(), Command ) )
|
||||
{
|
||||
fprintf( stdout, "Cannot execute ABC command \"%s\".\n", Command );
|
||||
unlink( pFileTemp );
|
||||
return NULL;
|
||||
}
|
||||
pNtk = Io_Read( pFileTemp, IO_FILE_BLIF, 1, 0 );
|
||||
if ( pNtk == NULL )
|
||||
{
|
||||
printf( "Reading mapped BLIF from file \"%s\" has failed.\n", pFileTemp );
|
||||
return NULL;
|
||||
}
|
||||
if ( pTopModule ) {
|
||||
ABC_FREE( pNtk->pName );
|
||||
pNtk->pName = Abc_UtilStrsav(pTopModule);
|
||||
}
|
||||
unlink( pFileTemp );
|
||||
return pNtk;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ Cudd_addPlus(
|
|||
res = cuddUniqueConst(dd,value);
|
||||
return(res);
|
||||
}
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -223,7 +223,7 @@ Cudd_addTimes(
|
|||
res = cuddUniqueConst(dd,value);
|
||||
return(res);
|
||||
}
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -405,7 +405,7 @@ Cudd_addMinimum(
|
|||
return(G);
|
||||
}
|
||||
}
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -450,7 +450,7 @@ Cudd_addMaximum(
|
|||
return(G);
|
||||
}
|
||||
}
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -590,7 +590,7 @@ Cudd_addOr(
|
|||
if (cuddIsConstant(F)) return(G);
|
||||
if (cuddIsConstant(G)) return(F);
|
||||
if (F == G) return(F);
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -622,7 +622,7 @@ Cudd_addNand(
|
|||
F = *f; G = *g;
|
||||
if (F == DD_ZERO(dd) || G == DD_ZERO(dd)) return(DD_ONE(dd));
|
||||
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -654,7 +654,7 @@ Cudd_addNor(
|
|||
F = *f; G = *g;
|
||||
if (F == DD_ONE(dd) || G == DD_ONE(dd)) return(DD_ZERO(dd));
|
||||
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ONE(dd));
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -688,7 +688,7 @@ Cudd_addXor(
|
|||
if (F == DD_ONE(dd) && G == DD_ZERO(dd)) return(DD_ONE(dd));
|
||||
if (G == DD_ONE(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
|
||||
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
@ -722,7 +722,7 @@ Cudd_addXnor(
|
|||
if (F == DD_ONE(dd) && G == DD_ONE(dd)) return(DD_ONE(dd));
|
||||
if (G == DD_ZERO(dd) && F == DD_ZERO(dd)) return(DD_ONE(dd));
|
||||
if (cuddIsConstant(F) && cuddIsConstant(G)) return(DD_ZERO(dd));
|
||||
if (F > G) { /* swap f and g */
|
||||
if (cuddF2L(F) > cuddF2L(G)) { /* swap f and g */
|
||||
*f = G;
|
||||
*g = F;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ cuddBddAndAbstractRecur(
|
|||
}
|
||||
/* At this point f, g, and cube are not constant. */
|
||||
|
||||
if (f > g) { /* Try to increase cache efficiency. */
|
||||
if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
|
||||
DdNode *tmp = f;
|
||||
f = g;
|
||||
g = tmp;
|
||||
|
|
|
|||
|
|
@ -331,7 +331,7 @@ cuddBddClippingAndRecur(
|
|||
|
||||
/* Check cache. Try to increase cache efficiency by sorting the
|
||||
** pointers. */
|
||||
if (f > g) {
|
||||
if (cuddF2L(f) > cuddF2L(g)) {
|
||||
DdNode *tmp = f;
|
||||
f = g; g = tmp;
|
||||
}
|
||||
|
|
@ -469,7 +469,7 @@ cuddBddClipAndAbsRecur(
|
|||
distance--;
|
||||
|
||||
/* Check cache. */
|
||||
if (f > g) { /* Try to increase cache efficiency. */
|
||||
if (cuddF2L(f) > cuddF2L(g)) { /* Try to increase cache efficiency. */
|
||||
DdNode *tmp = f;
|
||||
f = g; g = tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -381,6 +381,7 @@ struct DdManager { /* specialized DD symbol table */
|
|||
// double allocated; /* number of nodes allocated */
|
||||
ABC_INT64_T allocated; /* number of nodes allocated */
|
||||
/* (not during reordering) */
|
||||
ABC_INT64_T allocated2; /* number of nodes allocated */
|
||||
double reclaimed; /* number of nodes brought back from the dead */
|
||||
int isolated; /* isolated projection functions */
|
||||
int *perm; /* current variable perm. (index to level) */
|
||||
|
|
@ -715,7 +716,7 @@ typedef struct DdLevelQueue {
|
|||
SeeAlso []
|
||||
|
||||
******************************************************************************/
|
||||
#define cuddF2L(f) ((Cudd_Regular(f)->Id << 1) | Cudd_IsComplement(f))
|
||||
#define cuddF2L(f) ((Cudd_Regular(f)) ? ((Cudd_Regular(f)->Id << 1) | Cudd_IsComplement(f)) : 0)
|
||||
|
||||
|
||||
/**Macro***********************************************************************
|
||||
|
|
|
|||
|
|
@ -500,11 +500,11 @@ cuddLinearInPlace(
|
|||
/* For each element newf1 in collision list ylist[posn]. */
|
||||
previousP = &(ylist[posn]);
|
||||
newf1 = *previousP;
|
||||
while (f11 < cuddT(newf1)) {
|
||||
while (cuddF2L(f11) < cuddF2L(cuddT(newf1))) {
|
||||
previousP = &(newf1->next);
|
||||
newf1 = *previousP;
|
||||
}
|
||||
while (f11 == cuddT(newf1) && f00 < cuddE(newf1)) {
|
||||
while (f11 == cuddT(newf1) && cuddF2L(f00) < cuddF2L(cuddE(newf1))) {
|
||||
previousP = &(newf1->next);
|
||||
newf1 = *previousP;
|
||||
}
|
||||
|
|
@ -554,11 +554,11 @@ cuddLinearInPlace(
|
|||
/* For each element newf0 in collision list ylist[posn]. */
|
||||
previousP = &(ylist[posn]);
|
||||
newf0 = *previousP;
|
||||
while (f01 < cuddT(newf0)) {
|
||||
while (cuddF2L(f01) < cuddF2L(cuddT(newf0))) {
|
||||
previousP = &(newf0->next);
|
||||
newf0 = *previousP;
|
||||
}
|
||||
while (f01 == cuddT(newf0) && f10 < cuddE(newf0)) {
|
||||
while (f01 == cuddT(newf0) && cuddF2L(f10) < cuddF2L(cuddE(newf0))) {
|
||||
previousP = &(newf0->next);
|
||||
newf0 = *previousP;
|
||||
}
|
||||
|
|
@ -595,11 +595,11 @@ cuddLinearInPlace(
|
|||
newxkeys++;
|
||||
previousP = &(xlist[posn]);
|
||||
tmp = *previousP;
|
||||
while (newf1 < cuddT(tmp)) {
|
||||
while (cuddF2L(newf1) < cuddF2L(cuddT(tmp))) {
|
||||
previousP = &(tmp->next);
|
||||
tmp = *previousP;
|
||||
}
|
||||
while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
|
||||
while (newf1 == cuddT(tmp) && cuddF2L(newf0) < cuddF2L(cuddE(tmp))) {
|
||||
previousP = &(tmp->next);
|
||||
tmp = *previousP;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -583,7 +583,7 @@ addTriangleRecur(
|
|||
res = cuddUniqueConst(dd, value);
|
||||
return(res);
|
||||
}
|
||||
if (f < g) {
|
||||
if (cuddF2L(f) < cuddF2L(g)) {
|
||||
DdNode *tmp = f;
|
||||
f = g;
|
||||
g = tmp;
|
||||
|
|
|
|||
|
|
@ -480,7 +480,7 @@ cuddDynamicAllocNode(
|
|||
|
||||
node = table->nextFree;
|
||||
table->nextFree = node->next;
|
||||
//node->Id = 0;
|
||||
node->Id = (++table->allocated2<<4);
|
||||
return (node);
|
||||
|
||||
} /* end of cuddDynamicAllocNode */
|
||||
|
|
@ -937,11 +937,11 @@ cuddSwapInPlace(
|
|||
/* For each element tmp in collision list xlist[posn]. */
|
||||
previousP = &(xlist[posn]);
|
||||
tmp = *previousP;
|
||||
while (f1 < cuddT(tmp)) {
|
||||
while (cuddF2L(f1) < cuddF2L(cuddT(tmp))) {
|
||||
previousP = &(tmp->next);
|
||||
tmp = *previousP;
|
||||
}
|
||||
while (f1 == cuddT(tmp) && f0 < cuddE(tmp)) {
|
||||
while (f1 == cuddT(tmp) && cuddF2L(f0) < cuddF2L(cuddE(tmp))) {
|
||||
previousP = &(tmp->next);
|
||||
tmp = *previousP;
|
||||
}
|
||||
|
|
@ -998,11 +998,11 @@ cuddSwapInPlace(
|
|||
/* For each element newf1 in collision list xlist[posn]. */
|
||||
previousP = &(xlist[posn]);
|
||||
newf1 = *previousP;
|
||||
while (f11 < cuddT(newf1)) {
|
||||
while (cuddF2L(f11) < cuddF2L(cuddT(newf1))) {
|
||||
previousP = &(newf1->next);
|
||||
newf1 = *previousP;
|
||||
}
|
||||
while (f11 == cuddT(newf1) && f01 < cuddE(newf1)) {
|
||||
while (f11 == cuddT(newf1) && cuddF2L(f01) < cuddF2L(cuddE(newf1))) {
|
||||
previousP = &(newf1->next);
|
||||
newf1 = *previousP;
|
||||
}
|
||||
|
|
@ -1052,11 +1052,11 @@ cuddSwapInPlace(
|
|||
/* For each element newf0 in collision list xlist[posn]. */
|
||||
previousP = &(xlist[posn]);
|
||||
newf0 = *previousP;
|
||||
while (f10 < cuddT(newf0)) {
|
||||
while (cuddF2L(f10) < cuddF2L(cuddT(newf0))) {
|
||||
previousP = &(newf0->next);
|
||||
newf0 = *previousP;
|
||||
}
|
||||
while (f10 == cuddT(newf0) && f00 < cuddE(newf0)) {
|
||||
while (f10 == cuddT(newf0) && cuddF2L(f00) < cuddF2L(cuddE(newf0))) {
|
||||
previousP = &(newf0->next);
|
||||
newf0 = *previousP;
|
||||
}
|
||||
|
|
@ -1093,11 +1093,11 @@ cuddSwapInPlace(
|
|||
newykeys++;
|
||||
previousP = &(ylist[posn]);
|
||||
tmp = *previousP;
|
||||
while (newf1 < cuddT(tmp)) {
|
||||
while (cuddF2L(newf1) < cuddF2L(cuddT(tmp))) {
|
||||
previousP = &(tmp->next);
|
||||
tmp = *previousP;
|
||||
}
|
||||
while (newf1 == cuddT(tmp) && newf0 < cuddE(tmp)) {
|
||||
while (newf1 == cuddT(tmp) && cuddF2L(newf0) < cuddF2L(cuddE(tmp))) {
|
||||
previousP = &(tmp->next);
|
||||
tmp = *previousP;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -552,7 +552,7 @@ Cudd_EquivDC(
|
|||
/* From now on, D is non-constant. */
|
||||
|
||||
/* Normalize call to increase cache efficiency. */
|
||||
if (F > G) {
|
||||
if (cuddF2L(F) > cuddF2L(G)) {
|
||||
tmp = F;
|
||||
F = G;
|
||||
G = tmp;
|
||||
|
|
@ -674,7 +674,7 @@ Cudd_bddLeqUnless(
|
|||
/* !g <= D unless !f or !D <= g unless !f */
|
||||
tmp = D;
|
||||
D = Cudd_Not(f);
|
||||
if (g < tmp) {
|
||||
if (cuddF2L(g) < cuddF2L(tmp)) {
|
||||
f = Cudd_Not(g);
|
||||
g = tmp;
|
||||
} else {
|
||||
|
|
@ -717,7 +717,7 @@ Cudd_bddLeqUnless(
|
|||
}
|
||||
} else {
|
||||
/* f <= g unless D or !g <= !f unless D */
|
||||
if (g < f) {
|
||||
if (cuddF2L(g) < cuddF2L(f)) {
|
||||
tmp = g;
|
||||
g = Cudd_Not(f);
|
||||
f = Cudd_Not(tmp);
|
||||
|
|
@ -725,7 +725,7 @@ Cudd_bddLeqUnless(
|
|||
}
|
||||
} else {
|
||||
/* f <= g unless D or f <= D unless g */
|
||||
if (D < g) {
|
||||
if (cuddF2L(D) < cuddF2L(g)) {
|
||||
tmp = D;
|
||||
D = g;
|
||||
g = tmp;
|
||||
|
|
|
|||
|
|
@ -329,7 +329,7 @@ cuddAllocNode(
|
|||
unique->allocated++;
|
||||
node = unique->nextFree;
|
||||
unique->nextFree = node->next;
|
||||
node->Id = (unique->allocated<<4);
|
||||
node->Id = (++unique->allocated2<<4);
|
||||
return(node);
|
||||
|
||||
} /* end of cuddAllocNode */
|
||||
|
|
@ -398,6 +398,7 @@ cuddInitTable(
|
|||
unique->looseUpTo = looseUpTo;
|
||||
unique->gcEnabled = 1;
|
||||
unique->allocated = 0;
|
||||
unique->allocated2 = 0;
|
||||
unique->reclaimed = 0;
|
||||
unique->subtables = ABC_ALLOC(DdSubtable,unique->maxSize);
|
||||
if (unique->subtables == NULL) {
|
||||
|
|
@ -1161,14 +1162,14 @@ cuddUniqueInter(
|
|||
previousP = &(nodelist[pos]);
|
||||
looking = *previousP;
|
||||
|
||||
while (T < cuddT(looking)) {
|
||||
while (cuddF2L(T) < cuddF2L(cuddT(looking))) {
|
||||
previousP = &(looking->next);
|
||||
looking = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
unique->uniqueLinks++;
|
||||
#endif
|
||||
}
|
||||
while (T == cuddT(looking) && E < cuddE(looking)) {
|
||||
while (T == cuddT(looking) && cuddF2L(E) < cuddF2L(cuddE(looking))) {
|
||||
previousP = &(looking->next);
|
||||
looking = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
|
|
@ -1219,14 +1220,14 @@ cuddUniqueInter(
|
|||
previousP = &(nodelist[pos]);
|
||||
looking = *previousP;
|
||||
|
||||
while (T < cuddT(looking)) {
|
||||
while (cuddF2L(T) < cuddF2L(cuddT(looking))) {
|
||||
previousP = &(looking->next);
|
||||
looking = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
unique->uniqueLinks++;
|
||||
#endif
|
||||
}
|
||||
while (T == cuddT(looking) && E < cuddE(looking)) {
|
||||
while (T == cuddT(looking) && cuddF2L(E) < cuddF2L(cuddE(looking))) {
|
||||
previousP = &(looking->next);
|
||||
looking = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
|
|
@ -1250,14 +1251,14 @@ cuddUniqueInter(
|
|||
previousP = &(nodelist[pos]);
|
||||
looking2 = *previousP;
|
||||
|
||||
while (T < cuddT(looking2)) {
|
||||
while (cuddF2L(T) < cuddF2L(cuddT(looking2))) {
|
||||
previousP = &(looking2->next);
|
||||
looking2 = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
unique->uniqueLinks++;
|
||||
#endif
|
||||
}
|
||||
while (T == cuddT(looking2) && E < cuddE(looking2)) {
|
||||
while (T == cuddT(looking2) && cuddF2L(E) < cuddF2L(cuddE(looking2))) {
|
||||
previousP = &(looking2->next);
|
||||
looking2 = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
|
|
@ -1663,7 +1664,7 @@ cuddRehash(
|
|||
while (node != NULL) {
|
||||
next = node->next;
|
||||
split.value = cuddV(node);
|
||||
pos = ddHash(split.bits[0], split.bits[1], shift);
|
||||
pos = ddHash(cuddF2L(split.bits[0]), cuddF2L(split.bits[1]), shift);
|
||||
node->next = nodelist[pos];
|
||||
nodelist[pos] = node;
|
||||
node = next;
|
||||
|
|
@ -1747,14 +1748,14 @@ cuddShrinkSubtable(
|
|||
looking = *previousP;
|
||||
T = cuddT(node);
|
||||
E = cuddE(node);
|
||||
while (T < cuddT(looking)) {
|
||||
while (cuddF2L(T) < cuddF2L(cuddT(looking))) {
|
||||
previousP = &(looking->next);
|
||||
looking = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
unique->uniqueLinks++;
|
||||
#endif
|
||||
}
|
||||
while (T == cuddT(looking) && E < cuddE(looking)) {
|
||||
while (T == cuddT(looking) && cuddF2L(E) < cuddF2L(cuddE(looking))) {
|
||||
previousP = &(looking->next);
|
||||
looking = *previousP;
|
||||
#ifdef DD_UNIQUE_PROFILE
|
||||
|
|
@ -2770,10 +2771,10 @@ cuddFindParent(
|
|||
|
||||
for (j = 0; j < slots; j++) {
|
||||
f = nodelist[j];
|
||||
while (cuddT(f) > node) {
|
||||
while (cuddF2L(cuddT(f)) > cuddF2L(node)) {
|
||||
f = f->next;
|
||||
}
|
||||
while (cuddT(f) == node && Cudd_Regular(cuddE(f)) > node) {
|
||||
while (cuddT(f) == node && cuddF2L(Cudd_Regular(cuddE(f))) > cuddF2L(node)) {
|
||||
f = f->next;
|
||||
}
|
||||
if (cuddT(f) == node && Cudd_Regular(cuddE(f)) == node) {
|
||||
|
|
@ -3125,8 +3126,8 @@ cuddCheckCollisionOrdering(
|
|||
if (node == sentinel) return(1);
|
||||
next = node->next;
|
||||
while (next != sentinel) {
|
||||
if (cuddT(node) < cuddT(next) ||
|
||||
(cuddT(node) == cuddT(next) && cuddE(node) < cuddE(next))) {
|
||||
if (cuddF2L(cuddT(node)) < cuddF2L(cuddT(next)) ||
|
||||
(cuddT(node) == cuddT(next) && cuddF2L(cuddE(node)) < cuddF2L(cuddE(next)))) {
|
||||
(void) fprintf(unique->err,
|
||||
"Unordered list: index %u, position %d\n", i, j);
|
||||
return(0);
|
||||
|
|
|
|||
|
|
@ -3357,10 +3357,10 @@ cuddUniqueLookup(
|
|||
nodelist = subtable->nodelist;
|
||||
looking = nodelist[posn];
|
||||
|
||||
while (T < cuddT(looking)) {
|
||||
while (cuddF2L(T) < cuddF2L(cuddT(looking))) {
|
||||
looking = Cudd_Regular(looking->next);
|
||||
}
|
||||
while (T == cuddT(looking) && E < cuddE(looking)) {
|
||||
while (T == cuddT(looking) && cuddF2L(E) < cuddF2L(cuddE(looking))) {
|
||||
looking = Cudd_Regular(looking->next);
|
||||
}
|
||||
if (cuddT(looking) == T && cuddE(looking) == E) {
|
||||
|
|
|
|||
|
|
@ -137,7 +137,8 @@ Amap_Cut_t * Amap_ManCutCreate( Amap_Man_t * p,
|
|||
|
||||
***********************************************************************/
|
||||
Amap_Cut_t * Amap_ManCutCreate3( Amap_Man_t * p,
|
||||
Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, Amap_Cut_t * pCut2, int iMat )
|
||||
Amap_Cut_t * pCut0, Amap_Cut_t * pCut1, Amap_Cut_t * pCut2, int iMat,
|
||||
int c0, int c1, int c2 )
|
||||
{
|
||||
Amap_Cut_t * pCut;
|
||||
int i, nSize = pCut0->nFans + pCut1->nFans + pCut2->nFans;
|
||||
|
|
@ -146,12 +147,24 @@ Amap_Cut_t * Amap_ManCutCreate3( Amap_Man_t * p,
|
|||
pCut->iMat = iMat;
|
||||
pCut->fInv = 0;
|
||||
pCut->nFans = nSize;
|
||||
if ( c0 )
|
||||
pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
|
||||
for ( i = 0; i < (int)pCut0->nFans; i++ )
|
||||
pCut->Fans[i] = pCut0->Fans[i];
|
||||
if ( c0 )
|
||||
pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
|
||||
if ( c1 )
|
||||
pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
|
||||
for ( i = 0; i < (int)pCut1->nFans; i++ )
|
||||
pCut->Fans[pCut0->nFans+i] = pCut1->Fans[i];
|
||||
if ( c1 )
|
||||
pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
|
||||
if ( c2 )
|
||||
pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]);
|
||||
for ( i = 0; i < (int)pCut2->nFans; i++ )
|
||||
pCut->Fans[pCut0->nFans+pCut1->nFans+i] = pCut2->Fans[i];
|
||||
if ( c2 )
|
||||
pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]);
|
||||
// add it to storage
|
||||
if ( p->ppCutsTemp[ pCut->iMat ] == NULL )
|
||||
Vec_IntPushOrder( p->vTemp, pCut->iMat );
|
||||
|
|
@ -405,21 +418,7 @@ void Amap_ManMergeNodeCutsMux( Amap_Man_t * p, Amap_Obj_t * pNode )
|
|||
if ( pNod->pSets == NULL )
|
||||
continue;
|
||||
// complement literals
|
||||
if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) )
|
||||
pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
|
||||
if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) )
|
||||
pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
|
||||
if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) )
|
||||
pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]);
|
||||
// create new cut
|
||||
Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3) );
|
||||
// uncomplement literals
|
||||
if ( pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0) )
|
||||
pCut0->Fans[0] = Abc_LitNot(pCut0->Fans[0]);
|
||||
if ( pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1) )
|
||||
pCut1->Fans[0] = Abc_LitNot(pCut1->Fans[0]);
|
||||
if ( pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) )
|
||||
pCut2->Fans[0] = Abc_LitNot(pCut2->Fans[0]);
|
||||
Amap_ManCutCreate3( p, pCut0, pCut1, pCut2, Vec_IntEntry(vRules, x+3), pCut0->nFans == 1 && (pCut0->fInv ^ fComplFanin0), pCut1->nFans == 1 && (pCut1->fInv ^ fComplFanin1), pCut2->nFans == 1 && (pCut2->fInv ^ fComplFanin2) );
|
||||
}
|
||||
}
|
||||
Amap_ManCutSaveStored( p, pNode );
|
||||
|
|
|
|||
|
|
@ -377,7 +377,7 @@ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
|
|||
if ( strcmp( pToken, AMAP_STRING_PIN ) )
|
||||
{
|
||||
Amap_LibFree( p );
|
||||
printf( "Cannot parse gate %s.\n", pGate->pName );
|
||||
printf( "Cannot parse cell %s.\n", pGate->pName );
|
||||
return NULL;
|
||||
}
|
||||
// read pin
|
||||
|
|
@ -393,7 +393,7 @@ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
|
|||
else
|
||||
{
|
||||
Amap_LibFree( p );
|
||||
printf( "Cannot read phase of pin %s of gate %s\n", pPin->pName, pGate->pName );
|
||||
printf( "Cannot read phase of pin %s of cell %s\n", pPin->pName, pGate->pName );
|
||||
return NULL;
|
||||
}
|
||||
pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
|
||||
|
|
@ -421,7 +421,7 @@ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
|
|||
Vec_PtrPush( p->vGates, pGate );
|
||||
}
|
||||
pToken = (char *)Vec_PtrEntry(vTokens, iPos++);
|
||||
//printf( "Finished reading gate %s (%s)\n", pGate->pName, pGate->pOutName );
|
||||
//printf( "Finished reading cell %s (%s)\n", pGate->pName, pGate->pOutName );
|
||||
}
|
||||
while ( strcmp( pToken, ".end" ) );
|
||||
|
||||
|
|
@ -432,7 +432,7 @@ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
|
|||
if ( pPrev && !strcmp(pPrev->pName, pGate->pName) )
|
||||
{
|
||||
pPrev->pTwin = pGate, pGate->pTwin = pPrev;
|
||||
// printf( "Warning: Detected multi-output gate \"%s\".\n", pGate->pName );
|
||||
// printf( "Warning: Detected multi-output cell \"%s\".\n", pGate->pName );
|
||||
if ( pMoGate == NULL )
|
||||
pMoGate = pGate->pName;
|
||||
Count++;
|
||||
|
|
@ -440,7 +440,7 @@ Amap_Lib_t * Amap_ParseTokens( Vec_Ptr_t * vTokens, int fVerbose )
|
|||
pPrev = pGate;
|
||||
}
|
||||
if ( Count )
|
||||
printf( "Warning: Detected %d multi-output gates (for example, \"%s\").\n", Count, pMoGate );
|
||||
printf( "Warning: Detected %d multi-output cells (for example, \"%s\").\n", Count, pMoGate );
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -73,6 +73,23 @@ static char * pMcncGenlib[] = {
|
|||
};
|
||||
*/
|
||||
|
||||
// internal version of genlib library
|
||||
static char * pAndGenlib[] = {
|
||||
"GATE zero 0 O=CONST0;\n",
|
||||
"GATE one 0 O=CONST1;\n",
|
||||
"GATE buf 1 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE inv 1 O=!a; PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE and00 1 O=a*b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE and01 1 O=a*!b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE and10 1 O=!a*b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE and11 1 O=!a*!b; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE nand00 1 O=!(a*b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE nand01 1 O=!(a*!b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE nand10 1 O=!(!a*b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
"GATE nand11 1 O=!(!a*!b); PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
|
||||
NULL
|
||||
};
|
||||
|
||||
// internal version of genlib library
|
||||
static char * pSimpleGenlib[] = {
|
||||
"GATE zero 0 O=CONST0;\n",
|
||||
|
|
@ -126,6 +143,20 @@ static char * pSimpleGenlib2[] = {
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Mio_IntallAndLibrary()
|
||||
{
|
||||
extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose );
|
||||
Vec_Str_t * vLibStr = Vec_StrAlloc( 1000 );
|
||||
for ( int i = 0; pAndGenlib[i]; i++ )
|
||||
Vec_StrAppend( vLibStr, pAndGenlib[i] );
|
||||
Vec_Str_t * vLibStr2 = Vec_StrDup( vLibStr );
|
||||
Vec_StrAppend( vLibStr2, ".end\n" );
|
||||
Vec_StrPush( vLibStr2, '\0' );
|
||||
Vec_StrPush( vLibStr, '\0' );
|
||||
Mio_UpdateGenlib2( vLibStr, vLibStr2, "and.genlib", 0 );
|
||||
Vec_StrFree( vLibStr );
|
||||
Vec_StrFree( vLibStr2 );
|
||||
}
|
||||
void Mio_IntallSimpleLibrary()
|
||||
{
|
||||
extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose );
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ void Scl_End( Abc_Frame_t * pAbc )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
SC_Lib * Scl_ReadLibraryFile( Abc_Frame_t * pAbc, char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use )
|
||||
SC_Lib * Scl_ReadLibraryFile( Abc_Frame_t * pAbc, char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts )
|
||||
{
|
||||
SC_Lib * pLib;
|
||||
FILE * pFile;
|
||||
|
|
@ -152,7 +152,7 @@ SC_Lib * Scl_ReadLibraryFile( Abc_Frame_t * pAbc, char * pFileName, int fVerbose
|
|||
}
|
||||
fclose( pFile );
|
||||
// read new library
|
||||
pLib = Abc_SclReadLiberty( pFileName, fVerbose, fVeryVerbose, dont_use);
|
||||
pLib = Abc_SclReadLiberty( pFileName, fVerbose, fVeryVerbose, dont_use, fSkipMultiOuts);
|
||||
if ( pLib == NULL )
|
||||
{
|
||||
fprintf( pAbc->Err, "Reading SCL library from file \"%s\" has failed. \n", pFileName );
|
||||
|
|
@ -186,13 +186,14 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
int fMerge = 0;
|
||||
int fUsePrefix = 0;
|
||||
int fUseAll = 0;
|
||||
int fSkipMultiOuts = 0;
|
||||
|
||||
SC_DontUse dont_use = {0};
|
||||
dont_use.dont_use_list = ABC_ALLOC(char *, argc);
|
||||
dont_use.size = 0;
|
||||
|
||||
Extra_UtilGetoptReset();
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmpah" ) ) != EOF )
|
||||
while ( ( c = Extra_UtilGetopt( argc, argv, "SGMXdnuvwmpash" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -263,6 +264,9 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
case 'a':
|
||||
fUseAll ^= 1;
|
||||
break;
|
||||
case 's':
|
||||
fSkipMultiOuts ^= 1;
|
||||
break;
|
||||
case 'h':
|
||||
goto usage;
|
||||
default:
|
||||
|
|
@ -270,8 +274,8 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
}
|
||||
}
|
||||
if ( argc == globalUtilOptind + 2 ) { // expecting two files
|
||||
SC_Lib * pLib1 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use );
|
||||
SC_Lib * pLib2 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind+1], fVerbose, fVeryVerbose, dont_use );
|
||||
SC_Lib * pLib1 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use, fSkipMultiOuts );
|
||||
SC_Lib * pLib2 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind+1], fVerbose, fVeryVerbose, dont_use, fSkipMultiOuts );
|
||||
ABC_FREE(dont_use.dont_use_list);
|
||||
if ( pLib1 == NULL || pLib2 == NULL ) {
|
||||
if (pLib1) Abc_SclLibFree(pLib1);
|
||||
|
|
@ -283,7 +287,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
Abc_SclLibFree(pLib2);
|
||||
}
|
||||
else if ( argc == globalUtilOptind + 1 ) { // expecting one file
|
||||
SC_Lib * pLib1 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use );
|
||||
SC_Lib * pLib1 = Scl_ReadLibraryFile( pAbc, argv[globalUtilOptind], fVerbose, fVeryVerbose, dont_use, fSkipMultiOuts );
|
||||
|
||||
SC_Lib * pLib_ext = (SC_Lib *)pAbc->pLibScl;
|
||||
if ( fMerge && pLib_ext != NULL && pLib1 != NULL ) {
|
||||
|
|
@ -328,7 +332,7 @@ int Scl_CommandReadLib( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmpah] [-X cell_name] <file> <file2>\n" );
|
||||
fprintf( pAbc->Err, "usage: read_lib [-SG float] [-M num] [-dnuvwmpash] [-X cell_name] <file> <file2>\n" );
|
||||
fprintf( pAbc->Err, "\t reads Liberty library from file\n" );
|
||||
fprintf( pAbc->Err, "\t-S float : the slew parameter used to generate the library [default = %.2f]\n", Slew );
|
||||
fprintf( pAbc->Err, "\t-G float : the gain parameter used to generate the library [default = %.2f]\n", Gain );
|
||||
|
|
@ -340,8 +344,9 @@ usage:
|
|||
fprintf( pAbc->Err, "\t-v : toggle writing verbose information [default = %s]\n", fVerbose? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-w : toggle writing information about skipped gates [default = %s]\n", fVeryVerbose? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-m : toggle merging library with exisiting library [default = %s]\n", fMerge? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-a : toggle using prefix for the cell names [default = %s]\n", fUseAll? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-p : toggle using prefix for the cell names [default = %s]\n", fUsePrefix? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-a : toggle reading all cells when using gain-based modeling [default = %s]\n", fUseAll? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-s : toggle skipping cells with two outputs [default = %s]\n", fSkipMultiOuts? "yes": "no" );
|
||||
fprintf( pAbc->Err, "\t-h : prints the command summary\n" );
|
||||
fprintf( pAbc->Err, "\t<file> : the name of a file to read\n" );
|
||||
fprintf( pAbc->Err, "\t<file2> : the name of a file to read (optional)\n" );
|
||||
|
|
|
|||
|
|
@ -741,7 +741,7 @@ static inline void Scl_LibHandleInputDriver2( SC_Cell * pCell, SC_PairI * pLoadI
|
|||
}
|
||||
|
||||
/*=== sclLiberty.c ===============================================================*/
|
||||
extern SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use );
|
||||
extern SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts );
|
||||
/*=== sclLibScl.c ===============================================================*/
|
||||
extern SC_Lib * Abc_SclReadFromGenlib( void * pLib );
|
||||
extern SC_Lib * Abc_SclReadFromStr( Vec_Str_t * vOut );
|
||||
|
|
|
|||
|
|
@ -875,7 +875,7 @@ SC_Lib * Abc_SclMergeLibraries( SC_Lib * pLib1, SC_Lib * pLib2, int fUsePrefix )
|
|||
SC_Lib * p = Abc_SclReadFromStr( vOut );
|
||||
p->pFileName = Abc_UtilStrsav( pLib1->pFileName );
|
||||
p->pName = ABC_ALLOC( char, strlen(pLib1->pName) + strlen(pLib2->pName) + 10 );
|
||||
sprintf( p->pName, "%s__and__%s", pLib1->pName, pLib2->pName );
|
||||
sprintf( p->pName, "merged_lib_size_%d", p->vCells.nSize );
|
||||
Vec_StrFree( vOut );
|
||||
printf( "Updated library \"%s\" with additional %d cells from library \"%s\".\n", pLib1->pName, n_valid_cells2, pLib2->pName );
|
||||
return p;
|
||||
|
|
|
|||
|
|
@ -897,6 +897,21 @@ Vec_Str_t * Abc_SclProduceGenlibStr( SC_Lib * p, float Slew, float Gain, int nGa
|
|||
if ( nGatesMin && pRepr->n_inputs > 2 && Abc_SclClassCellNum(pRepr) < nGatesMin )
|
||||
continue;
|
||||
SC_CellForEachPinOut( pRepr, pPinOut, j )
|
||||
{
|
||||
SC_CellForEachPinIn( pRepr, pPin, k )
|
||||
{
|
||||
float Delay = Abc_SclComputeDelayClassPin( p, pRepr, k, Slew, Gain );
|
||||
if ( Delay <= 0 ) {
|
||||
printf( "Cell %s cannot be used because delay of a pin is <= 0.\n", pRepr->pName );
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( k < pRepr->n_inputs )
|
||||
break;
|
||||
}
|
||||
if ( j < pRepr->n_outputs )
|
||||
continue;
|
||||
SC_CellForEachPinOut( pRepr, pPinOut, j )
|
||||
{
|
||||
assert( strlen(pRepr->pName) < 200 );
|
||||
Vec_StrPrintStr( vStr, "GATE " );
|
||||
|
|
|
|||
|
|
@ -1500,7 +1500,7 @@ Vec_Ptr_t * Scl_LibertyReadTemplates( Scl_Tree_t * p )
|
|||
// Scl_LibertyPrintTemplates( vRes );
|
||||
return vRes;
|
||||
}
|
||||
Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbose, SC_DontUse dont_use )
|
||||
Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts )
|
||||
{
|
||||
int fUseFirstTable = 0;
|
||||
Vec_Str_t * vOut;
|
||||
|
|
@ -1509,7 +1509,7 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos
|
|||
Vec_Wrd_t * vTruth;
|
||||
char * pFormula, * pName;
|
||||
int i, k, Counter, nOutputs, nCells;
|
||||
int nSkipped[4] = {0};
|
||||
int nSkipped[6] = {0};
|
||||
|
||||
// read delay-table templates
|
||||
vTemples = Scl_LibertyReadTemplates( p );
|
||||
|
|
@ -1561,6 +1561,18 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos
|
|||
nSkipped[2]++;
|
||||
continue;
|
||||
}
|
||||
if ( Counter > 2 )
|
||||
{
|
||||
if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with more than two outputs.\n", Scl_LibertyReadString(p, pCell->Head) );
|
||||
nSkipped[4]++;
|
||||
continue;
|
||||
}
|
||||
if ( fSkipMultiOuts && Counter > 1 )
|
||||
{
|
||||
if ( fVeryVerbose ) printf( "Scl_LibertyReadGenlib() skipped cell \"%s\" with two outputs.\n", Scl_LibertyReadString(p, pCell->Head) );
|
||||
nSkipped[5]++;
|
||||
continue;
|
||||
}
|
||||
nCells++;
|
||||
}
|
||||
// read cells
|
||||
|
|
@ -1577,6 +1589,10 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos
|
|||
continue;
|
||||
if ( (Counter = Scl_LibertyReadCellOutputNum(p, pCell)) == 0 )
|
||||
continue;
|
||||
if ( Counter > 2 )
|
||||
continue;
|
||||
if ( fSkipMultiOuts && Counter > 1 )
|
||||
continue;
|
||||
// top level information
|
||||
Vec_StrPutS_( vOut, Scl_LibertyReadString(p, pCell->Head) );
|
||||
pName = Scl_LibertyReadCellArea(p, pCell);
|
||||
|
|
@ -1742,13 +1758,14 @@ Vec_Str_t * Scl_LibertyReadSclStr( Scl_Tree_t * p, int fVerbose, int fVeryVerbos
|
|||
{
|
||||
printf( "Library \"%s\" from \"%s\" has %d cells ",
|
||||
Scl_LibertyReadString(p, Scl_LibertyRoot(p)->Head), p->pFileName, nCells );
|
||||
printf( "(%d skipped: %d seq; %d tri-state; %d no func; %d dont_use). ",
|
||||
nSkipped[0]+nSkipped[1]+nSkipped[2], nSkipped[0], nSkipped[1], nSkipped[2], nSkipped[3] );
|
||||
printf( "(%d skipped: %d seq; %d tri-state; %d no func; %d dont_use; %d with 2 outputs; %d with 3+ outputs). ",
|
||||
nSkipped[0]+nSkipped[1]+nSkipped[2]+nSkipped[3]+nSkipped[4]+nSkipped[5],
|
||||
nSkipped[0],nSkipped[1],nSkipped[2],nSkipped[3],nSkipped[5],nSkipped[4] );
|
||||
Abc_PrintTime( 1, "Time", Abc_Clock() - p->clkStart );
|
||||
}
|
||||
return vOut;
|
||||
}
|
||||
SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use )
|
||||
SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose, SC_DontUse dont_use, int fSkipMultiOuts )
|
||||
{
|
||||
SC_Lib * pLib;
|
||||
Scl_Tree_t * p;
|
||||
|
|
@ -1758,7 +1775,7 @@ SC_Lib * Abc_SclReadLiberty( char * pFileName, int fVerbose, int fVeryVerbose, S
|
|||
return NULL;
|
||||
// Scl_LibertyParseDump( p, "temp_.lib" );
|
||||
// collect relevant data
|
||||
vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose, dont_use );
|
||||
vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose, dont_use, fSkipMultiOuts );
|
||||
Scl_LibertyStop( p, fVeryVerbose );
|
||||
if ( vStr == NULL )
|
||||
return NULL;
|
||||
|
|
@ -1797,7 +1814,7 @@ void Scl_LibertyTest()
|
|||
return;
|
||||
// Scl_LibertyParseDump( p, "temp_.lib" );
|
||||
SC_DontUse dont_use = {0};
|
||||
vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose, dont_use);
|
||||
vStr = Scl_LibertyReadSclStr( p, fVerbose, fVeryVerbose, dont_use, 0);
|
||||
Scl_LibertyStringDump( "test_scl.lib", vStr );
|
||||
Vec_StrFree( vStr );
|
||||
Scl_LibertyStop( p, fVerbose );
|
||||
|
|
|
|||
|
|
@ -38,19 +38,22 @@ ABC_NAMESPACE_IMPL_START
|
|||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MAX_TT_SIZE 24
|
||||
|
||||
typedef struct Abc_BSEval_t_ Abc_BSEval_t;
|
||||
struct Abc_BSEval_t_
|
||||
{
|
||||
int nVars;
|
||||
int nLVars;
|
||||
int nBVars;
|
||||
Vec_Int_t * vPairs; // perm pairs
|
||||
Vec_Int_t * vCounts; // cofactor counts
|
||||
Vec_Int_t * vTable; // hash table
|
||||
Vec_Int_t * vUsed; // used entries
|
||||
Vec_Wrd_t * vStore; // cofactors
|
||||
Vec_Wec_t * vSets; // sets
|
||||
Vec_Wrd_t * vCofs; // cofactors
|
||||
word * pPat; // patterns
|
||||
Vec_Int_t * vPairs[MAX_TT_SIZE][MAX_TT_SIZE]; // perm pairs
|
||||
Vec_Int_t * vCounts; // cofactor counts
|
||||
Vec_Int_t * vTable; // hash table
|
||||
Vec_Int_t * vUsed; // used entries
|
||||
Vec_Wrd_t * vStore; // cofactors
|
||||
Vec_Wec_t * vSets[MAX_TT_SIZE]; // sets
|
||||
Vec_Wrd_t * vCofs[MAX_TT_SIZE]; // cofactors
|
||||
word * pPat; // patterns
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -561,46 +564,58 @@ Abc_BSEval_t * Abc_BSEvalAlloc()
|
|||
}
|
||||
void Abc_BSEvalFree( Abc_BSEval_t * p )
|
||||
{
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
for ( int i = 0; i < MAX_TT_SIZE; i++ )
|
||||
for ( int k = 0; k < MAX_TT_SIZE; k++ )
|
||||
Vec_IntFreeP( &p->vPairs[i][k] );
|
||||
Vec_IntFree( p->vCounts );
|
||||
Vec_IntFree( p->vTable );
|
||||
Vec_IntFree( p->vUsed );
|
||||
Vec_WrdFree( p->vStore );
|
||||
Vec_WecFreeP( &p->vSets );
|
||||
Vec_WrdFreeP( &p->vCofs );
|
||||
for ( int i = 0; i < MAX_TT_SIZE; i++ )
|
||||
Vec_WecFreeP( &p->vSets[i] );
|
||||
for ( int i = 0; i < MAX_TT_SIZE; i++ )
|
||||
Vec_WrdFreeP( &p->vCofs[i] );
|
||||
ABC_FREE( p->pPat );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose )
|
||||
void Abc_BSEvalOneTest( word * pT, int nVars, int nLVars, int fVerbose )
|
||||
{
|
||||
assert( nVars > nBVars );
|
||||
assert( nVars > nLVars );
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
if ( p->nVars != nVars || p->nBVars != nBVars ) {
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
p->vPairs = Abc_GenChasePairs( nVars, nBVars );
|
||||
if ( p->nVars != nVars || p->nLVars != nLVars ) {
|
||||
p->nVars = nVars;
|
||||
p->nBVars = nBVars;
|
||||
p->nLVars = nLVars;
|
||||
if ( p->vPairs[p->nVars][p->nLVars] == NULL )
|
||||
p->vPairs[p->nVars][p->nLVars] = Abc_GenChasePairs( nVars, nLVars );
|
||||
}
|
||||
int Best = Abc_TtGetCM( pT, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 );
|
||||
int Best = Abc_TtGetCM( pT, nVars, nVars-nLVars, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 );
|
||||
printf( "Function: " ); Extra_PrintHex( stdout, (unsigned *)pT, nVars ); printf( "\n" );
|
||||
printf( "The column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nBVars, Best );
|
||||
printf( "The column multiplicity of the %d-var function with bound-sets of size %d is %d.\n", nVars, nLVars, Best );
|
||||
Abc_BSEvalFree(p);
|
||||
}
|
||||
int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest, int fShared )
|
||||
int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, word * pBest2, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest, int * pPermBest2, int fShared, int nJRatio )
|
||||
{
|
||||
int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32];
|
||||
int nPermVars = nVars-nCVars, Count = 0;
|
||||
assert( p->nVars == nPermVars && p->nBVars == nVars-nFVars );
|
||||
assert( p->nVars == nPermVars && p->nLVars == nVars-nFVars );
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
Pla2Var[i] = Var2Pla[i] = i;
|
||||
if ( pPermBest )
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
pPermBest[i] = i;
|
||||
int CostBest = 1 << nVars;
|
||||
int CostBest2 = 1 << nVars;
|
||||
int iSave = nJRatio ? (Abc_Random(0) % Vec_IntSize(p->vPairs[p->nVars][p->nLVars])/2) : -1;
|
||||
//printf( "The number of pairs = %d.\n", Vec_IntSize(p->vPairs[p->nVars][p->nLVars])/2 );
|
||||
//int Count = 0;
|
||||
Vec_IntForEachEntryDouble( p->vPairs, Var0, Var1, i ) {
|
||||
Vec_IntForEachEntryDouble( p->vPairs[p->nVars][p->nLVars], Var0, Var1, i ) {
|
||||
//Abc_GenChasePrint( Count++, Pla2Var, nVars, nFVars, Var0, Var1 );
|
||||
int CostThis = Abc_TtGetCM( pIn, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, fShared );
|
||||
if ( iSave == i/2 ) {
|
||||
CostBest2 = CostThis;
|
||||
if ( pBest2 ) Abc_TtCopy( pBest2, pIn, Abc_Truth6WordNum(nVars), 0 );
|
||||
if ( pPermBest2 ) memcpy( pPermBest2, Pla2Var, sizeof(int)*nVars );
|
||||
}
|
||||
if ( CostBest > CostThis ) {
|
||||
CostBest = CostThis;
|
||||
if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 );
|
||||
|
|
@ -627,10 +642,10 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n
|
|||
}
|
||||
if ( 0 ) {
|
||||
//word pPat[MAX_PAT_WORD_SIZE];
|
||||
int nRails = 1, Shared = 0;
|
||||
int nRails = 1, Shared = 0, nSetSize = 0;
|
||||
if ( CostThis > (1 << nRails) ) {
|
||||
extern int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, word * pPat );
|
||||
int nRailsMin = Abc_SharedEvalBest( p, pIn, nVars, nCVars, nFVars, CostThis, nRails, 0, &Shared, p->pPat );
|
||||
extern int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, int * pSetSize, word * pPat );
|
||||
int nRailsMin = Abc_SharedEvalBest( p, pIn, nVars, nCVars, nFVars, CostThis, nRails, 0, &Shared, &nSetSize, p->pPat );
|
||||
printf( " RailMin = %d. Shared = %2d. ", nRailsMin, Shared );
|
||||
}
|
||||
}
|
||||
|
|
@ -661,22 +676,28 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n
|
|||
Pla2Var[iPlace1] ^= Pla2Var[iPlace0];
|
||||
Pla2Var[iPlace0] ^= Pla2Var[iPlace1];
|
||||
}
|
||||
if ( nJRatio && Abc_Random(0) % nJRatio == 0 ) {
|
||||
CostBest = CostBest2;
|
||||
if ( pBest2 ) Abc_TtCopy( pBest, pBest2, Abc_Truth6WordNum(nVars), 0 );
|
||||
if ( pPermBest2 ) memcpy( pPermBest, pPermBest2, sizeof(int)*nVars );
|
||||
}
|
||||
return CostBest;
|
||||
}
|
||||
void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVerbose )
|
||||
void Abc_BSEvalBestTest( word * pIn, int nVars, int nLVars, int fShared, int fVerbose )
|
||||
{
|
||||
assert( nVars > nBVars );
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc(); int i, pPerm[32] = {0};
|
||||
if ( p->nVars != nVars || p->nBVars != nBVars ) {
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
p->vPairs = Abc_GenChasePairs( nVars, nBVars );
|
||||
assert( nVars > nLVars );
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc(); int i, pPerm[32] = {0}, pPerm2[32] = {0};
|
||||
if ( p->nVars != nVars || p->nLVars != nLVars ) {
|
||||
p->nVars = nVars;
|
||||
p->nBVars = nBVars;
|
||||
p->nLVars = nLVars;
|
||||
if ( p->vPairs[p->nVars][p->nLVars] == NULL )
|
||||
p->vPairs[p->nVars][p->nLVars] = Abc_GenChasePairs( nVars, nLVars );
|
||||
}
|
||||
word * pFun = ABC_ALLOC( word, Abc_TtWordNum(nVars) );
|
||||
int Best = Abc_BSEvalBest( p, pIn, pFun, nVars, 0, nVars-nBVars, fVerbose, pPerm, fShared );
|
||||
word * pFun2 = ABC_ALLOC( word, Abc_TtWordNum(nVars) );
|
||||
int Best = Abc_BSEvalBest( p, pIn, pFun, pFun2, nVars, 0, nVars-nLVars, fVerbose, pPerm, pPerm2, fShared, 0 );
|
||||
printf( "The minimum %s of the %d-var function with bound-sets of size %d is %d.\n",
|
||||
fShared ? "number of rails" : "column multiplicity", nVars, nBVars, Best );
|
||||
fShared ? "number of rails" : "column multiplicity", nVars, nLVars, Best );
|
||||
printf( "Original: " ); Extra_PrintHex( stdout, (unsigned *)pIn, nVars ); printf( "\n" );
|
||||
printf( "Permuted: " ); Extra_PrintHex( stdout, (unsigned *)pFun, nVars ); printf( "\n" );
|
||||
printf( "Permutation is " );
|
||||
|
|
@ -684,6 +705,7 @@ void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVe
|
|||
printf( "%d ", pPerm[i] );
|
||||
printf( "\n" );
|
||||
ABC_FREE( pFun );
|
||||
ABC_FREE( pFun2 );
|
||||
Abc_BSEvalFree(p);
|
||||
}
|
||||
|
||||
|
|
@ -698,19 +720,20 @@ void Abc_BSEvalBestTest( word * pIn, int nVars, int nBVars, int fShared, int fVe
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryAll, int fShared, int fVerbose )
|
||||
void Abc_BSEvalBestGen( int nVars, int nLVars, int nFuncs, int nMints, int fTryAll, int fShared, int fVerbose )
|
||||
{
|
||||
assert( nVars > nBVars );
|
||||
assert( nVars > nLVars );
|
||||
abctime clkTotal = Abc_Clock();
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
Vec_Int_t * vCounts[2] = { Vec_IntStart(1 << nVars), Vec_IntStart(1 << nVars) };
|
||||
int i, k, Count, nWords = Abc_TtWordNum(nVars);
|
||||
word * pFun = ABC_ALLOC( word, nWords );
|
||||
if ( p->nVars != nVars || p->nBVars != nBVars ) {
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
p->vPairs = Abc_GenChasePairs( nVars, nBVars );
|
||||
word * pFun2 = ABC_ALLOC( word, nWords );
|
||||
if ( p->nVars != nVars || p->nLVars != nLVars ) {
|
||||
p->nVars = nVars;
|
||||
p->nBVars = nBVars;
|
||||
p->nLVars = nLVars;
|
||||
if ( p->vPairs[p->nVars][p->nLVars] == NULL )
|
||||
p->vPairs[p->nVars][p->nLVars] = Abc_GenChasePairs( nVars, nLVars );
|
||||
}
|
||||
Abc_Random(1);
|
||||
for ( i = 0; i < nFuncs; i++ ) {
|
||||
|
|
@ -741,34 +764,35 @@ void Abc_BSEvalBestGen( int nVars, int nBVars, int nFuncs, int nMints, int fTryA
|
|||
}
|
||||
|
||||
if ( fTryAll )
|
||||
Count = Abc_BSEvalBest( p, pFun, NULL, nVars, 0, nVars-nBVars, fVerbose, NULL, fShared );
|
||||
Count = Abc_BSEvalBest( p, pFun, pFun2, NULL, nVars, 0, nVars-nLVars, fVerbose, NULL, NULL, fShared, 0 );
|
||||
else
|
||||
Count = Abc_TtGetCM( pFun, nVars, nVars-nBVars, p->vCounts, p->vTable, p->vStore, p->vUsed, fShared );
|
||||
Count = Abc_TtGetCM( pFun, nVars, nVars-nLVars, p->vCounts, p->vTable, p->vStore, p->vUsed, fShared );
|
||||
if ( fVerbose )
|
||||
printf( "Myu = %d\n", Count );
|
||||
Vec_IntAddToEntry( vCounts[0], Count, 1 );
|
||||
Vec_IntAddToEntry( vCounts[1], Abc_Base2Log(Count), 1 );
|
||||
}
|
||||
ABC_FREE( pFun );
|
||||
ABC_FREE( pFun2 );
|
||||
Abc_BSEvalFree(p);
|
||||
if ( nMints )
|
||||
printf( "Generated %d random %d-var functions with %d positive minterms.\n", nFuncs, nVars, nMints );
|
||||
else
|
||||
printf( "Generated %d random %d-var functions.\n", nFuncs, nVars );
|
||||
if ( fShared ) {
|
||||
printf( "Distribution of the %s number of rails for bound set size %d with one shared variable:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars );
|
||||
printf( "Distribution of the %s number of rails for bound set size %d with one shared variable:\n", fTryAll ? "MINIMUM": "ORIGINAL", nLVars );
|
||||
assert( Vec_IntSum(vCounts[0]) == nFuncs );
|
||||
Vec_IntForEachEntry( vCounts[0], Count, i )
|
||||
if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs );
|
||||
printf( "\n" );
|
||||
}
|
||||
else {
|
||||
printf( "Distribution of the %s column multiplicity for bound set size %d with no shared variables:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars );
|
||||
printf( "Distribution of the %s column multiplicity for bound set size %d with no shared variables:\n", fTryAll ? "MINIMUM": "ORIGINAL", nLVars );
|
||||
assert( Vec_IntSum(vCounts[0]) == nFuncs );
|
||||
Vec_IntForEachEntry( vCounts[0], Count, i )
|
||||
if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs );
|
||||
printf( "\n" );
|
||||
printf( "Distribution of the %s number of rails for bound set size %d with no shared variables:\n", fTryAll ? "MINIMUM": "ORIGINAL", nBVars );
|
||||
printf( "Distribution of the %s number of rails for bound set size %d with no shared variables:\n", fTryAll ? "MINIMUM": "ORIGINAL", nLVars );
|
||||
assert( Vec_IntSum(vCounts[1]) == nFuncs );
|
||||
Vec_IntForEachEntry( vCounts[1], Count, i )
|
||||
if ( Count ) printf( "%d=%d (%.2f %%) ", i, Count, 100.0*Count/nFuncs );
|
||||
|
|
@ -843,25 +867,6 @@ static inline int Abc_BSEvalCountUniqueMax( word * pISets, int nISets, int nBSWo
|
|||
}
|
||||
return CountMax;
|
||||
}
|
||||
int Abc_BSEvalFindShared( int nVars, word * pISets, int nISets, int nBSWords, Vec_Wec_t * vSets, Vec_Wrd_t * vCofs, int nSharedMax )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k, iSet, iStart, nMinMyu = nISets, nMinRails = Abc_Base2Log(nISets), MinShared = 0, MinSet = -1;
|
||||
Vec_WecForEachLevelStartStop( vSets, vLevel, i, 1, nSharedMax+1 ) {
|
||||
Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) {
|
||||
int Count = Abc_BSEvalCountUniqueMax( pISets, nISets, nBSWords, Vec_WrdEntryP(vCofs, iStart), i, 1 << (nMinRails-1) );
|
||||
if ( Count == 0 )
|
||||
continue;
|
||||
int CountRails = Abc_Base2Log(Count);
|
||||
if ( nMinRails > CountRails || (nMinRails == CountRails && nMinMyu > Count && MinShared == i) ) {
|
||||
nMinRails = CountRails;
|
||||
nMinMyu = Count;
|
||||
MinShared = i;
|
||||
MinSet = iSet;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (MinSet << 16) | nMinMyu;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -875,19 +880,19 @@ int Abc_BSEvalFindShared( int nVars, word * pISets, int nISets, int nBSWords, Ve
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, word * pPat )
|
||||
int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nFVars, int MyuMin, int nRails, int fVerbose, int * pSetShared, int * pnSetSize, word * pPat )
|
||||
{
|
||||
int nBSWords = Abc_Truth6WordNum( nVars - nFVars ), CVarMask = nCVars ? Abc_InfoMask(nCVars) << (nVars - nCVars - nFVars) : 0;
|
||||
int MyuCur, Myu = Abc_TtGetCMInt( pTruth, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, pPat );
|
||||
int nRailsCur = Abc_Base2Log( Myu ); Vec_Int_t * vLevel;
|
||||
assert( Myu == MyuMin && nRailsCur > nRails );
|
||||
assert( Myu == MyuMin && nRailsCur >= nRails );
|
||||
int i, k, iSet, iStart, nSharedMax = nVars - nFVars - nRails, nRailsMin = 100;
|
||||
Vec_WecForEachLevelStartStop( p->vSets, vLevel, i, 1, nSharedMax ) {
|
||||
Vec_WecForEachLevelStartStop( p->vSets[p->nBVars], vLevel, i, 1, nSharedMax ) {
|
||||
Vec_IntForEachEntryDouble( vLevel, iSet, iStart, k ) {
|
||||
if ( iSet & CVarMask )
|
||||
continue;
|
||||
//printf( "\nTrying set " ); Extra_PrintBinary( stdout, &iSet, nVars-nFVars ); printf( "\n" );
|
||||
MyuCur = Abc_BSEvalCountUniqueMax( pPat, Myu, nBSWords, Vec_WrdEntryP(p->vCofs, iStart), i, 1 << nRails );
|
||||
MyuCur = Abc_BSEvalCountUniqueMax( pPat, Myu, nBSWords, Vec_WrdEntryP(p->vCofs[p->nBVars], iStart), i, 1 << nRails );
|
||||
//printf( " Res = %d", MyuCur );
|
||||
if ( MyuCur == 0 || MyuCur > (1 << nRails) )
|
||||
continue;
|
||||
|
|
@ -897,6 +902,7 @@ int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars,
|
|||
if ( nRailsMin > nRailsCur ) {
|
||||
nRailsMin = nRailsCur;
|
||||
*pSetShared = iSet;
|
||||
*pnSetSize = i;
|
||||
}
|
||||
}
|
||||
if ( nRailsMin <= nRails )
|
||||
|
|
@ -904,86 +910,6 @@ int Abc_SharedEvalBest( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars,
|
|||
}
|
||||
return nRailsMin;
|
||||
}
|
||||
int Abc_DeriveLutDec( word * pTruth, int nVars, int nCVars, int nFVars, int * pPerm, int nRails, int Shared, int fVerbose, Vec_Wrd_t * vRes )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Decomposing truth table into a K-LUT cascade with R rails.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose )
|
||||
{
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
Vec_Wrd_t * vRes = Vec_WrdStart( 1 ); word * pRes = NULL;
|
||||
word * pTruth = ABC_ALLOC( word, Abc_TtWordNum(nVars) );
|
||||
word * pBest = ABC_ALLOC( word, Abc_TtWordNum(nVars) );
|
||||
Abc_TtCopy( pTruth, pFunc, Abc_TtWordNum(nVars), 0 );
|
||||
int i, r, nVarsCur = nVars, nOutVars = 0;
|
||||
while ( nVarsCur > nLutSize )
|
||||
{
|
||||
int pPerm[32] = {0};
|
||||
if ( p->nVars != nVarsCur || p->nBVars != nLutSize ) {
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
if ( p->nBVars != nLutSize ) {
|
||||
Vec_WecFreeP( &p->vSets );
|
||||
Vec_WrdFreeP( &p->vCofs );
|
||||
p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets );
|
||||
if ( p->nBVars < nLutSize ) {
|
||||
ABC_FREE( p->pPat );
|
||||
p->pPat = ABC_ALLOC( word, (1 << nLutSize)*Abc_TtWordNum(nLutSize) );
|
||||
}
|
||||
}
|
||||
p->vPairs = Abc_GenChasePairs( nVarsCur, nLutSize );
|
||||
p->nVars = nVarsCur;
|
||||
p->nBVars = nLutSize;
|
||||
}
|
||||
int MyuMin = Abc_BSEvalBest( p, pTruth, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, fVerbose, pPerm, 0 );
|
||||
int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin );
|
||||
for ( r = 1; r <= nRails && nRailsMin > r; r++ ) {
|
||||
int nRailsMinNew = Abc_SharedEvalBest( p, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, MyuMin, nRails, fVerbose, &Shared, p->pPat );
|
||||
if ( nRailsMinNew < 100 )
|
||||
nRailsMin = nRailsMinNew;
|
||||
}
|
||||
MyuMin = 1 << nRailsMin;
|
||||
if ( nRailsMin > nRails ) {
|
||||
Vec_WrdFreeP( &vRes );
|
||||
break;
|
||||
}
|
||||
// update nVarsCur, pTruth, nOutVars, and vRes
|
||||
nVarsCur = Abc_DeriveLutDec( pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, pPerm, nRailsMin, Shared, fVerbose, vRes );
|
||||
Abc_TtCopy( pTruth, pBest, Abc_TtWordNum(nVarsCur), 0 );
|
||||
nOutVars = nRailsMin;
|
||||
}
|
||||
if ( vRes ) // decomposition succeeded
|
||||
{
|
||||
// create the last node
|
||||
assert( nVarsCur <= nLutSize );
|
||||
Vec_WrdAddToEntry( vRes, 0, 1 );
|
||||
Vec_WrdPush( vRes, nVarsCur+4 );
|
||||
Vec_WrdPush( vRes, nVarsCur );
|
||||
for ( i = 0; i < nVarsCur; i++ )
|
||||
Vec_WrdPush( vRes, i );
|
||||
Vec_WrdPush( vRes, 0 );
|
||||
Vec_WrdPush( vRes, pTruth[0] );
|
||||
// extract the output array
|
||||
pRes = Vec_WrdReleaseArray( vRes );
|
||||
Vec_WrdFree( vRes );
|
||||
}
|
||||
// cleanup and return
|
||||
Abc_BSEvalFree(p);
|
||||
ABC_FREE( pTruth );
|
||||
ABC_FREE( pBest );
|
||||
return pRes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -996,19 +922,19 @@ word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nR
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose )
|
||||
word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int nLutSize, int fVerbose, int * pMyu, int nJRatio )
|
||||
{
|
||||
Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
int nPermVars = nVars-nRVars;
|
||||
if ( p->nVars != nPermVars ) {
|
||||
Vec_IntFreeP( &p->vPairs );
|
||||
p->vPairs = Abc_GenChasePairs( nPermVars, nLutSize-nRVars );
|
||||
p->nVars = nPermVars;
|
||||
p->nVars = nPermVars;
|
||||
p->nLVars = nLutSize-nRVars;
|
||||
if ( p->vPairs[p->nVars][p->nLVars] == NULL )
|
||||
p->vPairs[p->nVars][p->nLVars] = Abc_GenChasePairs( p->nVars, p->nLVars );
|
||||
}
|
||||
if ( p->nBVars != nLutSize ) {
|
||||
Vec_WecFreeP( &p->vSets );
|
||||
Vec_WrdFreeP( &p->vCofs );
|
||||
p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets );
|
||||
if ( p->vCofs[nLutSize] == NULL )
|
||||
p->vCofs[nLutSize] = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets[nLutSize] );
|
||||
if ( p->nBVars < nLutSize ) {
|
||||
ABC_FREE( p->pPat );
|
||||
p->pPat = ABC_ALLOC( word, (1 << nLutSize)*Abc_TtWordNum(nLutSize) );
|
||||
|
|
@ -1022,10 +948,13 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
|
|||
//word pPat[MAX_PAT_WORD_SIZE];
|
||||
|
||||
int pPermBest[32] = {0};
|
||||
int pPermBest2[32] = {0};
|
||||
word * pBest = ABC_ALLOC( word, nWords );
|
||||
word * pBest2 = ABC_ALLOC( word, nWords );
|
||||
//printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, nVars ); printf( "\n" );
|
||||
int MyuMin = Abc_BSEvalBest( p, pCopy, pBest, nVars, nRVars, nVars-nLutSize, 0, pPermBest, 0 );
|
||||
int MyuMin = Abc_BSEvalBest( p, pCopy, pBest, pBest2, nVars, nRVars, nVars-nLutSize, 0, pPermBest, pPermBest2, 0, nJRatio );
|
||||
//printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, nVars ); printf( "\n" );
|
||||
if ( pMyu ) *pMyu = MyuMin;
|
||||
|
||||
if ( fVerbose ) {
|
||||
printf( "Best perm: " );
|
||||
|
|
@ -1034,9 +963,9 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
|
|||
printf( " Myu = %d. ", MyuMin );
|
||||
}
|
||||
|
||||
int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin );
|
||||
int Shared = 0, nSetSize = 0, nRailsMin = Abc_Base2Log( MyuMin );
|
||||
for ( r = 1; r <= nRails && nRailsMin > r; r++ ) {
|
||||
int nRailsMinNew = Abc_SharedEvalBest( p, pBest, nVars, nRVars, nVars-nLutSize, MyuMin, r, 0, &Shared, p->pPat );
|
||||
int nRailsMinNew = Abc_SharedEvalBest( p, pBest, nVars, nRVars, nVars-nLutSize, MyuMin, r, 0, &Shared, &nSetSize, p->pPat );
|
||||
if ( nRailsMinNew < 100 )
|
||||
nRailsMin = nRailsMinNew;
|
||||
}
|
||||
|
|
@ -1044,6 +973,7 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
|
|||
|
||||
ABC_FREE( pCopy );
|
||||
ABC_FREE( pBest );
|
||||
ABC_FREE( pBest2 );
|
||||
Abc_BSEvalFree(p);
|
||||
|
||||
if ( fVerbose )
|
||||
|
|
@ -1064,6 +994,304 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
|
|||
return ((word)MyuMin << 48) | (mSVars << 24) | mBVars;
|
||||
}
|
||||
|
||||
word Abc_BSEvalEncode( int * pPermBest, int nVars, int nLutSize, int Shared, int MyuMin, int SharedSize )
|
||||
{
|
||||
int v;
|
||||
word mBVars = 0;
|
||||
for ( v = 0; v < nLutSize; v++ )
|
||||
mBVars |= (word)1 << pPermBest[nVars-nLutSize+v];
|
||||
word mSVars = 0;
|
||||
for ( v = 0; v < nLutSize; v++ )
|
||||
if ( (Shared >> v) & 1 )
|
||||
mSVars |= (word)1 << (nVars-nLutSize+v);
|
||||
return ((word)MyuMin << 48) | (mSVars << 24) | mBVars;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Wec_t * Abc_BSFind( Vec_Int_t * vVars, int nLutSize, int nSubsets )
|
||||
{
|
||||
assert( Vec_IntSize(vVars) > nLutSize );
|
||||
Vec_Wec_t * vRes = Vec_WecAlloc( nSubsets ); int i;
|
||||
for ( i = 0; i < nSubsets; i++ ) {
|
||||
Vec_Int_t * vNew = Vec_WecPushLevel( vRes );
|
||||
while ( Vec_IntSize(vNew) < nLutSize )
|
||||
Vec_IntPushUniqueOrder( vNew, Vec_IntEntry(vVars, Abc_Random(0)%Vec_IntSize(vVars)) );
|
||||
}
|
||||
return vRes;
|
||||
}
|
||||
Vec_Int_t * Abc_BSFindNextVars( Vec_Wec_t * vPrev, int nLutSize, int nSubsets, int nBest )
|
||||
{
|
||||
assert( Vec_WecSize(vPrev) == nSubsets );
|
||||
assert( Vec_IntSize(Vec_WecEntry(vPrev,0)) == nLutSize + 1 );
|
||||
Vec_Int_t * vVars = Vec_IntAlloc( 100 );
|
||||
Vec_Int_t * vLevel; int i, k, Var;
|
||||
Vec_WecForEachLevelStop( vPrev, vLevel, i, nBest )
|
||||
Vec_IntForEachEntry( vLevel, Var, k )
|
||||
if ( k < nLutSize )
|
||||
Vec_IntPush( vVars, Var );
|
||||
Vec_IntUniqify( vVars );
|
||||
return vVars;
|
||||
}
|
||||
// this procedure considers boundsets in vSets and adds CM as the last entry in each one
|
||||
void Abc_BSEvalSet( Abc_BSEval_t * p, Vec_Wec_t * vSets, word * pTruth, int nVars, int nCVars, int nLutSize )
|
||||
{
|
||||
int nWords = Abc_TtWordNum(nVars);
|
||||
word * pCopy = ABC_ALLOC( word, nWords );
|
||||
Abc_TtCopy( pCopy, pTruth, nWords, 0 );
|
||||
|
||||
int i, k, Var, Pla2Var[32], Var2Pla[32];
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
Pla2Var[i] = Var2Pla[i] = i;
|
||||
|
||||
Vec_Int_t * vLevel;
|
||||
Vec_WecForEachLevel( vSets, vLevel, i ) {
|
||||
assert( Vec_IntSize(vLevel) == nLutSize-nCVars );
|
||||
Vec_IntForEachEntry( vLevel, Var, k )
|
||||
Abc_TtMoveVar( pCopy, nVars, Var2Pla, Pla2Var, Var, nVars - nLutSize + k );
|
||||
int MyuThis = Abc_TtGetCM( pCopy, nVars, nVars-nLutSize, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 );
|
||||
Vec_IntPush( vLevel, MyuThis );
|
||||
}
|
||||
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
Abc_TtMoveVar( pCopy, nVars, Var2Pla, Pla2Var, i, i );
|
||||
if ( !Abc_TtEqual(pCopy, pTruth, nWords) )
|
||||
printf( "Internal truth table check failed.\n" );
|
||||
}
|
||||
void Vec_WecAppend( Vec_Wec_t * vBase, Vec_Wec_t * vNew )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i;
|
||||
Vec_WecForEachLevel( vNew, vLevel, i )
|
||||
Vec_IntAppend( Vec_WecPushLevel(vBase), vLevel );
|
||||
}
|
||||
Vec_Wec_t * Abc_TtFindBVars3( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nRails, int nLutSize, int fVerbose, int * pMyu, int nMyuIncrease, int nSubsets, int nBest )
|
||||
{
|
||||
Vec_Wec_t * vAllSets = Vec_WecAlloc( 1000 );
|
||||
Vec_Wec_t * vSets = NULL;
|
||||
for ( int Iter = 0; Iter < 3; Iter++ ) {
|
||||
Vec_Int_t * vVars = NULL;
|
||||
if ( Iter == 0 )
|
||||
vVars = Vec_IntStartNatural( nVars-nCVars );
|
||||
else
|
||||
vVars = Abc_BSFindNextVars( vSets, nLutSize-nCVars, nSubsets, nBest );
|
||||
if ( Vec_IntSize(vVars) <= nLutSize-nCVars )
|
||||
break;
|
||||
Vec_WecFreeP( &vSets );
|
||||
vSets = Abc_BSFind( vVars, nLutSize-nCVars, nSubsets );
|
||||
Abc_BSEvalSet( p, vSets, pTruth, nVars, nCVars, nLutSize );
|
||||
Vec_WecSortByLastInt( vSets, 0 );
|
||||
Vec_WecAppend( vAllSets, vSets );
|
||||
if ( 0 )
|
||||
{
|
||||
printf( "Iteration %d :\n", Iter );
|
||||
Vec_WecPrint( vSets, 0 );
|
||||
printf( "Variables: " );
|
||||
Vec_IntPrint( vVars );
|
||||
printf( "\n" );
|
||||
}
|
||||
Vec_IntFree( vVars );
|
||||
}
|
||||
Vec_WecFreeP( &vSets );
|
||||
//Vec_WecPrint( vAllSets, 0 );
|
||||
//Vec_WecFreeP( &vAllSets );
|
||||
return vAllSets;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Wrd_t * Abc_TtFindBVarsSVars2( Abc_BSEval_t * p, word * pTruth, int nVars, int nCVars, int nRails, int nLutSize, int fVerbose, int * pMyu, int nMyuIncrease, int nSubsets, int nBest )
|
||||
{
|
||||
// Abc_BSEval_t * p = Abc_BSEvalAlloc();
|
||||
int nFVars = nVars-nLutSize;
|
||||
int nPermVars = nVars-nCVars;
|
||||
int nBSets = 0;
|
||||
|
||||
if ( p->nVars != nPermVars ) {
|
||||
p->nVars = nPermVars;
|
||||
p->nLVars = nLutSize-nCVars;
|
||||
if ( p->vPairs[p->nVars][p->nLVars] == NULL )
|
||||
p->vPairs[p->nVars][p->nLVars] = Abc_GenChasePairs( p->nVars, p->nLVars );
|
||||
}
|
||||
if ( p->nBVars != nLutSize ) {
|
||||
if ( p->vCofs[nLutSize] == NULL )
|
||||
p->vCofs[nLutSize] = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets[nLutSize] );
|
||||
if ( p->nBVars < nLutSize ) {
|
||||
ABC_FREE( p->pPat );
|
||||
p->pPat = ABC_ALLOC( word, (1 << nLutSize)*Abc_TtWordNum(nLutSize) );
|
||||
}
|
||||
p->nBVars = nLutSize;
|
||||
}
|
||||
|
||||
int nWords = Abc_TtWordNum(nVars);
|
||||
word * pCopy = ABC_ALLOC( word, nWords );
|
||||
Abc_TtCopy( pCopy, pTruth, nWords, 0 );
|
||||
|
||||
Vec_Wrd_t * vRes = Vec_WrdAlloc( 10 );
|
||||
int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32];
|
||||
for ( i = 0; i < nVars; i++ )
|
||||
Pla2Var[i] = Var2Pla[i] = i;
|
||||
int MyuOrigBest = 1 << nVars;
|
||||
int MyuBest = 1 << nVars;
|
||||
int nSetSizeBest = nVars;
|
||||
|
||||
if ( pMyu ) *pMyu = 1 << nVars;
|
||||
if ( nSubsets && nBest && nVars > nLutSize+1 ) {
|
||||
Vec_Wec_t * vAllSets = Abc_TtFindBVars3( p, pTruth, nVars, nCVars, nRails, nLutSize, fVerbose, pMyu, nMyuIncrease, nSubsets, nBest );
|
||||
Vec_WecSortByLastInt( vAllSets, 0 );
|
||||
// Vec_IntForEachEntryDouble( p->vPairs[p->nVars][p->nLVars], Var0, Var1, i ) {
|
||||
// int MyuThis = Abc_TtGetCM( pCopy, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 );
|
||||
Vec_Int_t * vLevel; int Var;
|
||||
Vec_WecForEachLevelStop( vAllSets, vLevel, i, nBest )
|
||||
{
|
||||
int MyuThis = Vec_IntPop( vLevel );
|
||||
MyuOrigBest = Abc_MinInt( MyuOrigBest, MyuThis );
|
||||
if ( pMyu ) *pMyu = Abc_MinInt( *pMyu, MyuThis );
|
||||
|
||||
Vec_IntForEachEntry( vLevel, Var, k )
|
||||
Abc_TtMoveVar( pCopy, nVars, Var2Pla, Pla2Var, Var, nVars - nLutSize + k );
|
||||
//int MyuThis1 = Abc_TtGetCM( pCopy, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 );
|
||||
//assert( MyuThis1 == MyuThis );
|
||||
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "%3d : ", i/2 );
|
||||
for ( k = nCVars-1; k >= 0; k-- )
|
||||
printf( " %d", nVars-nCVars+k );
|
||||
printf( " " );
|
||||
for ( k = nPermVars-1; k >= nFVars; k-- )
|
||||
printf( " %d", Pla2Var[k] );
|
||||
printf( " " );
|
||||
for ( k = nFVars-1; k >= 0; k-- )
|
||||
printf( " %d", Pla2Var[k] );
|
||||
printf( " : Myu = %3d", MyuThis );
|
||||
}
|
||||
if ( MyuThis <= MyuOrigBest + nMyuIncrease ) {
|
||||
int Shared = 0, nSetSize = 0;
|
||||
if ( MyuThis > 2 ) {
|
||||
int SharedThis = 0, nSetSizeThis = 0;
|
||||
int nRailsMin = 100;
|
||||
for ( int r = 1; r <= nRails && nRailsMin > r; r++ ) {
|
||||
int nRailsMinNew = Abc_SharedEvalBest( p, pCopy, nVars, nCVars, nFVars, MyuThis, r, 0, &SharedThis, &nSetSizeThis, p->pPat );
|
||||
if ( nRailsMinNew < 100 )
|
||||
nRailsMin = nRailsMinNew;
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( " RailsMyu = %3d. RailsMin = %3d. Shared = %2d. SetSize = %d.", Abc_Base2Log(MyuThis), nRailsMin, SharedThis, nSetSizeThis );
|
||||
if ( nRailsMin <= nRails ) {
|
||||
MyuThis = 1 << nRailsMin;
|
||||
Shared = SharedThis;
|
||||
nSetSize = nSetSizeThis;
|
||||
}
|
||||
}
|
||||
if ( MyuBest > MyuThis || (MyuBest == MyuThis && nSetSizeBest >= nSetSize) ) {
|
||||
int fSave = (MyuBest == MyuThis && nSetSizeBest == nSetSize);
|
||||
MyuBest = MyuThis;
|
||||
nSetSizeBest = nSetSize;
|
||||
word Result = Abc_BSEvalEncode( Pla2Var, nVars, nLutSize, Shared, MyuBest, nSetSize );
|
||||
if ( fSave )
|
||||
Vec_WrdPush( vRes, Result );
|
||||
else
|
||||
Vec_WrdFill( vRes, 1, Result );
|
||||
if ( fVerbose )
|
||||
printf( " <== best" );
|
||||
}
|
||||
nBSets++;
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( "\n" );
|
||||
}
|
||||
Vec_WecFree( vAllSets );
|
||||
}
|
||||
else {
|
||||
Vec_IntForEachEntryDouble( p->vPairs[p->nVars][p->nLVars], Var0, Var1, i ) {
|
||||
int MyuThis = Abc_TtGetCM( pCopy, nVars, nFVars, p->vCounts, p->vTable, p->vStore, p->vUsed, 0 );
|
||||
MyuOrigBest = Abc_MinInt( MyuOrigBest, MyuThis );
|
||||
if ( pMyu ) *pMyu = Abc_MinInt( *pMyu, MyuThis );
|
||||
if ( fVerbose )
|
||||
{
|
||||
printf( "%3d : ", i/2 );
|
||||
for ( k = nCVars-1; k >= 0; k-- )
|
||||
printf( " %d", nVars-nCVars+k );
|
||||
printf( " " );
|
||||
for ( k = nPermVars-1; k >= nFVars; k-- )
|
||||
printf( " %d", Pla2Var[k] );
|
||||
printf( " " );
|
||||
for ( k = nFVars-1; k >= 0; k-- )
|
||||
printf( " %d", Pla2Var[k] );
|
||||
printf( " : Myu = %3d", MyuThis );
|
||||
}
|
||||
if ( MyuThis <= MyuOrigBest + nMyuIncrease ) {
|
||||
int Shared = 0, nSetSize = 0;
|
||||
if ( MyuThis > 2 ) {
|
||||
int SharedThis = 0, nSetSizeThis = 0;
|
||||
int nRailsMin = 100;
|
||||
for ( int r = 1; r <= nRails && nRailsMin > r; r++ ) {
|
||||
int nRailsMinNew = Abc_SharedEvalBest( p, pCopy, nVars, nCVars, nFVars, MyuThis, r, 0, &SharedThis, &nSetSizeThis, p->pPat );
|
||||
if ( nRailsMinNew < 100 )
|
||||
nRailsMin = nRailsMinNew;
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( " RailsMyu = %3d. RailsMin = %3d. Shared = %2d. SetSize = %d.", Abc_Base2Log(MyuThis), nRailsMin, SharedThis, nSetSizeThis );
|
||||
if ( nRailsMin <= nRails ) {
|
||||
MyuThis = 1 << nRailsMin;
|
||||
Shared = SharedThis;
|
||||
nSetSize = nSetSizeThis;
|
||||
}
|
||||
}
|
||||
if ( MyuBest > MyuThis || (MyuBest == MyuThis && nSetSizeBest >= nSetSize) ) {
|
||||
int fSave = (MyuBest == MyuThis && nSetSizeBest == nSetSize);
|
||||
MyuBest = MyuThis;
|
||||
nSetSizeBest = nSetSize;
|
||||
word Result = Abc_BSEvalEncode( Pla2Var, nVars, nLutSize, Shared, MyuBest, nSetSize );
|
||||
if ( fSave )
|
||||
Vec_WrdPush( vRes, Result );
|
||||
else
|
||||
Vec_WrdFill( vRes, 1, Result );
|
||||
if ( fVerbose )
|
||||
printf( " <== best" );
|
||||
}
|
||||
nBSets++;
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( "\n" );
|
||||
Abc_TtExchangeVars( pCopy, nVars, Var2Pla, Pla2Var, Var0, Var1 );
|
||||
}
|
||||
}
|
||||
for ( i = 0; i < nPermVars; i++ )
|
||||
Abc_TtMoveVar( pCopy, nVars, Var2Pla, Pla2Var, i, i );
|
||||
if ( !Abc_TtEqual(pCopy, pTruth, nWords) )
|
||||
printf( "Internal truth table check failed.\n" );
|
||||
|
||||
// Abc_BSEvalFree(p);
|
||||
if ( MyuBest > (1 << nRails) ) {
|
||||
Vec_WrdFree(vRes);
|
||||
return NULL;
|
||||
}
|
||||
if ( fVerbose )
|
||||
printf( "Tried %d bound-sets and collected %d solutions with MyuMin = %d and SharedSize = %d.\n", nBSets, Vec_WrdSize(vRes), MyuBest, nSetSizeBest );
|
||||
return vRes;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -1987,6 +1987,20 @@ static inline void Abc_TtSwapVars( word * pTruth, int nVars, int iVar, int jVar
|
|||
return;
|
||||
}
|
||||
}
|
||||
// exchanges places of v1 and v2
|
||||
static inline void Abc_TtExchangeVars( word * pF, int nVars, int * V2P, int * P2V, int v1, int v2 )
|
||||
{
|
||||
int iPlace0 = V2P[v1];
|
||||
int iPlace1 = V2P[v2];
|
||||
if ( iPlace0 == iPlace1 )
|
||||
return;
|
||||
Abc_TtSwapVars( pF, nVars, iPlace0, iPlace1 );
|
||||
V2P[P2V[iPlace0]] = iPlace1;
|
||||
V2P[P2V[iPlace1]] = iPlace0;
|
||||
P2V[iPlace0] ^= P2V[iPlace1];
|
||||
P2V[iPlace1] ^= P2V[iPlace0];
|
||||
P2V[iPlace0] ^= P2V[iPlace1];
|
||||
}
|
||||
// moves one var (v) to the given position (p)
|
||||
static inline void Abc_TtMoveVar( word * pF, int nVars, int * V2P, int * P2V, int v, int p )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -420,6 +420,32 @@ static inline Vec_Mem_t * Vec_MemAllocForTT( int nVars, int fCompl )
|
|||
ABC_FREE( uTruth );
|
||||
return vTtMem;
|
||||
}
|
||||
static inline Vec_Mem_t * Vec_MemAllocWithTTs( int nVars )
|
||||
{
|
||||
static word sTruths6[6] = {
|
||||
ABC_CONST(0xAAAAAAAAAAAAAAAA),
|
||||
ABC_CONST(0xCCCCCCCCCCCCCCCC),
|
||||
ABC_CONST(0xF0F0F0F0F0F0F0F0),
|
||||
ABC_CONST(0xFF00FF00FF00FF00),
|
||||
ABC_CONST(0xFFFF0000FFFF0000),
|
||||
ABC_CONST(0xFFFFFFFF00000000)
|
||||
};
|
||||
Vec_Mem_t * vTtMem = Vec_MemAllocForTTSimple( nVars );
|
||||
int i, k, nWords = nVars <= 6 ? 1 : (1 << (nVars - 6));
|
||||
word * pTruth = ABC_CALLOC( word, nWords );
|
||||
int Value = Vec_MemHashInsert( vTtMem, pTruth ); assert( Value == 0 );
|
||||
for ( i = 0; i < nVars; i++ ) {
|
||||
if ( i < 6 )
|
||||
for ( k = 0; k < nWords; k++ )
|
||||
pTruth[k] = sTruths6[i];
|
||||
else
|
||||
for ( k = 0; k < nWords; k++ )
|
||||
pTruth[k] = (k & (1 << (i-6))) ? ~(word)0 : 0;
|
||||
Value = Vec_MemHashInsert( vTtMem, pTruth ); assert( Value == 1+i );
|
||||
}
|
||||
ABC_FREE( pTruth );
|
||||
return vTtMem;
|
||||
}
|
||||
static inline void Vec_MemAddMuxTT( Vec_Mem_t * p, int nVars )
|
||||
{
|
||||
int Value, nWords = (nVars <= 6 ? 1 : (1 << (nVars - 6)));
|
||||
|
|
|
|||
|
|
@ -664,6 +664,13 @@ static inline void Vec_PtrPrintNames( Vec_Ptr_t * p )
|
|||
printf( "%s ", pName );
|
||||
printf( " }\n" );
|
||||
}
|
||||
static inline void Vec_PtrPrintPointers( Vec_Ptr_t * p )
|
||||
{
|
||||
void * pTemp; int i;
|
||||
printf( "Vector has %d pointer entries:\n", Vec_PtrSize(p) );
|
||||
Vec_PtrForEachEntry( void *, p, pTemp, i )
|
||||
printf( "%2d = %p\n", i, pTemp );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -444,6 +444,16 @@ static inline Vec_Wec_t * Vec_WecDup( Vec_Wec_t * p )
|
|||
Vec_WecPush( vNew, i, Entry );
|
||||
return vNew;
|
||||
}
|
||||
static inline Vec_Wec_t * Vec_WecDupSize( Vec_Wec_t * p )
|
||||
{
|
||||
Vec_Wec_t * vNew;
|
||||
Vec_Int_t * vVec;
|
||||
int i;
|
||||
vNew = Vec_WecStart( Vec_WecSize(p) );
|
||||
Vec_WecForEachLevel( p, vVec, i )
|
||||
Vec_IntFill( Vec_WecEntry(vNew, i), Vec_IntSize(vVec), 0 );
|
||||
return vNew;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -683,6 +693,13 @@ static inline int Vec_WecMaxLevelSize( Vec_Wec_t * p )
|
|||
Res = Abc_MaxInt( Res, Vec_IntSize(vTemp) );
|
||||
return Res;
|
||||
}
|
||||
static inline int Vec_WecMaxEntry( Vec_Wec_t * p )
|
||||
{
|
||||
Vec_Int_t * vTemp; int i, Res = 0;
|
||||
Vec_WecForEachLevel( p, vTemp, i )
|
||||
Res = Abc_MaxInt( Res, Vec_IntFindMax(vTemp) );
|
||||
return Res;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ struct Mfs_Par_t_
|
|||
int fGiaSat; // use new SAT solver
|
||||
int fVerbose; // enable basic stats
|
||||
int fVeryVerbose; // enable detailed stats
|
||||
int fPrintCares; // prints careset at each node
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -348,6 +348,17 @@ p->timeSat += Abc_Clock() - clk;
|
|||
p->nTimeOuts++;
|
||||
return 0;
|
||||
}
|
||||
if ( p->pPars->fPrintCares ) {
|
||||
int nFaninMax = Abc_NtkGetFaninMax(pNode->pNtk);
|
||||
printf( "Node %d : ", Abc_ObjId(pNode) );
|
||||
printf( "Fanins %d : ", Abc_ObjFaninNum(pNode) );
|
||||
printf( "Care " );
|
||||
for ( int i = 0; i < (1 << nFaninMax)-(1 << Abc_ObjFaninNum(pNode)); i++ )
|
||||
printf( " " );
|
||||
Extra_PrintBinary( stdout, p->uCare, 1 << Abc_ObjFaninNum(pNode) );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
// minimize the local function of the node using bi-decomposition
|
||||
assert( p->nFanins == Abc_ObjFaninNum(pNode) );
|
||||
dProb = p->pPars->fPower? ((float *)p->vProbs->pArray)[pNode->Id] : -1.0;
|
||||
|
|
|
|||
|
|
@ -21,40 +21,52 @@
|
|||
#include "rewire_rar.h"
|
||||
#include "rewire_miaig.h"
|
||||
|
||||
#define USE_OLD_LEVEL_SORTING 0
|
||||
|
||||
#ifdef RW_ABC
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
#endif // RW_ABC
|
||||
|
||||
#ifdef RW_ABC
|
||||
Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) {
|
||||
Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fChoices, int fVerbose) {
|
||||
Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
|
||||
Gia_ChMan_t *pChMan = fChoices ? Gia_ManDupChoicesStart(pGia) : NULL;
|
||||
|
||||
assert(Gia_ManCiNum(pGia) <= 58);
|
||||
Rewire::Miaig pNtkMiaig(pGia);
|
||||
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fVerbose);
|
||||
if (pExc)
|
||||
pNtkMiaig.setExc(pExc);
|
||||
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fCheck, pChMan, fVerbose);
|
||||
pNew.setName(Gia_ManName(pGia));
|
||||
|
||||
return pNew.toGia();
|
||||
return pChMan ? Gia_ManDupChoicesFinish(pChMan) : pNew.toGia();
|
||||
}
|
||||
|
||||
Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) {
|
||||
Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) {
|
||||
Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
|
||||
|
||||
assert(Abc_NtkCiNum(pNtk) <= 58);
|
||||
int fMapped = nMode == 1;
|
||||
Rewire::Miaig pNtkMiaig(pNtk);
|
||||
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fVerbose);
|
||||
if (pExc)
|
||||
pNtkMiaig.setExc(pExc);
|
||||
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fCheck, NULL, fVerbose);
|
||||
pNew.setName(Abc_NtkName(pNtk));
|
||||
if (nMode == 2) {
|
||||
if (nMode > 0) {
|
||||
pNew.countTransistors(1, nMappedMode);
|
||||
}
|
||||
|
||||
return pNew.toNtk(nMode >= 1);
|
||||
}
|
||||
|
||||
Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) {
|
||||
Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) {
|
||||
Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
|
||||
|
||||
assert(Mini_AigPiNum(pAig) <= 58);
|
||||
Rewire::Miaig pNtkMiaig(pAig);
|
||||
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fVerbose);
|
||||
if (pExc)
|
||||
pNtkMiaig.setExc(pExc);
|
||||
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fCheck, NULL, fVerbose);
|
||||
|
||||
return pNew.toMiniAig();
|
||||
}
|
||||
|
|
@ -95,7 +107,11 @@ void Miaig::setName(char *pName) {
|
|||
if (_data->pName) {
|
||||
free(_data->pName);
|
||||
}
|
||||
_data->pName = strdup(pName);
|
||||
if (pName == NULL || pName[0] == '\0') {
|
||||
_data->pName = strdup("rewire_miaig");
|
||||
} else {
|
||||
_data->pName = strdup(pName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -164,7 +180,7 @@ int Miaig::fromMiniAig(Mini_Aig_t *pMiniAig) {
|
|||
Gia_Man_t *Miaig::toGia(void) {
|
||||
int i, k, iLit, And2 = countAnd2();
|
||||
Gia_Man_t *pGia = Gia_ManStart(1 + nIns() + And2 + nOuts()), *pTemp;
|
||||
pGia->pName = Abc_UtilStrsav( _data->pName );
|
||||
pGia->pName = Abc_UtilStrsav(_data->pName);
|
||||
Gia_ManHashAlloc(pGia);
|
||||
memset(_data->pCopy, 0, sizeof(int) * nObjs());
|
||||
Miaig_ForEachInput(i)
|
||||
|
|
@ -234,6 +250,24 @@ vi *moveVecToVi(Vec_Int_t *v) {
|
|||
free(v);
|
||||
return p;
|
||||
}
|
||||
|
||||
void Miaig::setExc(Gia_Man_t *pExc) {
|
||||
int i;
|
||||
assert(Gia_ManCiNum(pExc) == nIns());
|
||||
assert(Gia_ManCoNum(pExc) == nOuts() || Gia_ManCoNum(pExc) == 1);
|
||||
if (Gia_ManCoNum(pExc) != nOuts() && Gia_ManCoNum(pExc) == 1) {
|
||||
printf("[Warning] The external careset has only a single output that will be applied to all other outputs.\n");
|
||||
}
|
||||
if (!_data->pExc) {
|
||||
_data->pExc = (word *)malloc(sizeof(word) * nWords() * nOuts());
|
||||
}
|
||||
Miaig Exc(pExc);
|
||||
Exc.initializeTruth();
|
||||
for (i = 0; i < nOuts(); ++i) {
|
||||
word *tExc = Exc.objTruth(Exc.nObjs() - Exc.nOuts() + std::min(i, Gia_ManCoNum(pExc)-1), 0);
|
||||
Tt_Dup(_data->pExc + nWords() * i, tExc, nWords());
|
||||
}
|
||||
}
|
||||
#endif // RW_ABC
|
||||
|
||||
// technology mapping
|
||||
|
|
@ -283,7 +317,7 @@ void Miaig::topoCollect_rec(int iObj) {
|
|||
objTravId(iObj) = nTravIds();
|
||||
Vi_PushOrder(_data->vOrder, iObj);
|
||||
Miaig_ForEachObjFanin(iObj, iLit, i)
|
||||
topoCollect_rec(Abc_Lit2Var(iLit));
|
||||
topoCollect_rec(Rw_Lit2Var(iLit));
|
||||
}
|
||||
|
||||
vi *Miaig::topoCollect(void) {
|
||||
|
|
@ -293,7 +327,7 @@ vi *Miaig::topoCollect(void) {
|
|||
Miaig_ForEachConstInput(i)
|
||||
objTravId(i) = nTravIds();
|
||||
Miaig_ForEachOutput(i)
|
||||
topoCollect_rec(Abc_Lit2Var(objFanin0(i)));
|
||||
topoCollect_rec(Rw_Lit2Var(objFanin0(i)));
|
||||
return _data->vOrder;
|
||||
}
|
||||
|
||||
|
|
@ -304,7 +338,7 @@ int Miaig::initializeLevels_rec(int iObj) {
|
|||
return objLevel(iObj);
|
||||
int level = -1;
|
||||
Miaig_ForEachObjFanin(iObj, iLit, i) {
|
||||
level = Abc_MaxInt(initializeLevels_rec(Abc_Lit2Var(iLit)), level);
|
||||
level = Abc_MaxInt(initializeLevels_rec(Rw_Lit2Var(iLit)), level);
|
||||
}
|
||||
return objLevel(iObj) = level + 1;
|
||||
}
|
||||
|
|
@ -321,7 +355,7 @@ void Miaig::initializeLevels(void) {
|
|||
objLevel(i) = 0;
|
||||
}
|
||||
Miaig_ForEachOutput(i) {
|
||||
objLevel(i) = initializeLevels_rec(Abc_Lit2Var(objFanin0(i)));
|
||||
objLevel(i) = initializeLevels_rec(Rw_Lit2Var(objFanin0(i)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -339,7 +373,7 @@ void Miaig::markDistanceN_rec(int iObj, int n, int limit) {
|
|||
if (n == limit)
|
||||
return;
|
||||
Miaig_ForEachObjFanin(iObj, iLit, i)
|
||||
markDistanceN_rec(Abc_Lit2Var(iLit), n + 1, limit);
|
||||
markDistanceN_rec(Rw_Lit2Var(iLit), n + 1, limit);
|
||||
}
|
||||
|
||||
void Miaig::markDistanceN(int iObj, int n) {
|
||||
|
|
@ -351,8 +385,8 @@ void Miaig::markDistanceN(int iObj, int n) {
|
|||
if (objDist(j) >= 0) continue;
|
||||
int minDist = nObjs();
|
||||
Miaig_ForEachObjFanin(j, iLit, k) {
|
||||
if (objDist(Abc_Lit2Var(iLit)) == -1) continue;
|
||||
minDist = Abc_MinInt(minDist, objDist(Abc_Lit2Var(iLit)));
|
||||
if (objDist(Rw_Lit2Var(iLit)) == -1) continue;
|
||||
minDist = Rw_MinInt(minDist, objDist(Rw_Lit2Var(iLit)));
|
||||
}
|
||||
if (minDist != nObjs()) {
|
||||
markDistanceN_rec(j, minDist + 1, n);
|
||||
|
|
@ -361,26 +395,50 @@ void Miaig::markDistanceN(int iObj, int n) {
|
|||
}
|
||||
}
|
||||
|
||||
void Miaig::markCritical(void) {
|
||||
int iObj;
|
||||
int maxRequire = countLevel(0);
|
||||
nTravIds()++;
|
||||
Miaig_ForEachOutput(iObj) {
|
||||
if (objLevel(iObj) != maxRequire) continue;
|
||||
markCritical_rec(iObj);
|
||||
}
|
||||
}
|
||||
|
||||
void Miaig::markCritical_rec(int iObj) {
|
||||
objTravId(iObj) = nTravIds();
|
||||
if (objIsPi(iObj)) return;
|
||||
int iLit, k;
|
||||
int maxFaninLevel = objLevel(Rw_Lit2Var(objFanin0(iObj)));
|
||||
Miaig_ForEachObjFaninStart(iObj, iLit, k, 1) {
|
||||
maxFaninLevel = Rw_MaxInt(maxFaninLevel, objLevel(Rw_Lit2Var(iLit)));
|
||||
}
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k) {
|
||||
if (objLevel(Rw_Lit2Var(iLit)) != maxFaninLevel) continue;
|
||||
markCritical_rec(Rw_Lit2Var(iLit));
|
||||
}
|
||||
}
|
||||
|
||||
// reference counting
|
||||
void Miaig::refObj(int iObj) {
|
||||
int k, iLit;
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k)
|
||||
objRef(Abc_Lit2Var(iLit))++;
|
||||
objRef(Rw_Lit2Var(iLit))++;
|
||||
}
|
||||
|
||||
void Miaig::derefObj(int iObj) {
|
||||
int k, iLit;
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k)
|
||||
objRef(Abc_Lit2Var(iLit))--;
|
||||
objRef(Rw_Lit2Var(iLit))--;
|
||||
}
|
||||
|
||||
void Miaig::derefObj_rec(int iObj, int iLitSkip) {
|
||||
int k, iLit;
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k) {
|
||||
if (iLit != iLitSkip && --objRef(Abc_Lit2Var(iLit)) == 0 && objIsNode(Abc_Lit2Var(iLit))) {
|
||||
derefObj_rec(Abc_Lit2Var(iLit), -1);
|
||||
Vi_Fill(_data->pvFans + Abc_Lit2Var(iLit), 1, 0);
|
||||
refObj(Abc_Lit2Var(iLit));
|
||||
if (iLit != iLitSkip && --objRef(Rw_Lit2Var(iLit)) == 0 && objIsNode(Rw_Lit2Var(iLit))) {
|
||||
derefObj_rec(Rw_Lit2Var(iLit), -1);
|
||||
Vi_Fill(objFanins(Rw_Lit2Var(iLit)), 1, 0);
|
||||
refObj(Rw_Lit2Var(iLit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -396,7 +454,7 @@ void Miaig::verifyRefs(void) {
|
|||
int i;
|
||||
Miaig_ForEachNodeOutput(i)
|
||||
derefObj(i);
|
||||
for (i = 0; i < _data->nObjs; i++)
|
||||
for (i = 0; i < nObjs(); i++)
|
||||
if (objRef(i))
|
||||
printf("Ref count of node %d is incorrect (%d).\n", i, objRef(i));
|
||||
initializeRefs();
|
||||
|
|
@ -409,7 +467,7 @@ void Miaig::markDfs_rec(int iObj) {
|
|||
return;
|
||||
objTravId(iObj) = nTravIds();
|
||||
Miaig_ForEachObjFanin(iObj, iLit, i)
|
||||
markDfs_rec(Abc_Lit2Var(iLit));
|
||||
markDfs_rec(Rw_Lit2Var(iLit));
|
||||
}
|
||||
|
||||
int Miaig::markDfs(void) {
|
||||
|
|
@ -418,7 +476,7 @@ int Miaig::markDfs(void) {
|
|||
Miaig_ForEachConstInput(i)
|
||||
objTravId(i) = nTravIds();
|
||||
Miaig_ForEachOutput(i)
|
||||
markDfs_rec(Abc_Lit2Var(objFanin0(i)));
|
||||
markDfs_rec(Rw_Lit2Var(objFanin0(i)));
|
||||
Miaig_ForEachOutput(i)
|
||||
objTravId(i) = nTravIds();
|
||||
Miaig_ForEachNode(i)
|
||||
|
|
@ -458,7 +516,7 @@ void Miaig::dupDfs_rec(Miaig &pNew, int iObj) {
|
|||
return;
|
||||
// 2. create fanins for a given node
|
||||
Miaig_ForEachObjFanin(iObj, iLit, i)
|
||||
dupDfs_rec(pNew, Abc_Lit2Var(iLit));
|
||||
dupDfs_rec(pNew, Rw_Lit2Var(iLit));
|
||||
assert(objCopy(iObj) < 0); // combinational loop catching
|
||||
assert(objFaninNum(iObj) > 0);
|
||||
// 3. create current node
|
||||
|
|
@ -478,7 +536,7 @@ Miaig Miaig::dupDfs(void) {
|
|||
objCopy(i) = i;
|
||||
// 2. for each primary output we call recursive function for it's fanin
|
||||
Miaig_ForEachOutput(i)
|
||||
dupDfs_rec(pNew, Abc_Lit2Var(objFanin0(i)));
|
||||
dupDfs_rec(pNew, Rw_Lit2Var(objFanin0(i)));
|
||||
// 3. for each primary output append it's fanin
|
||||
Miaig_ForEachOutput(i)
|
||||
pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitV(_data->pCopy, objFanin0(i)));
|
||||
|
|
@ -517,10 +575,10 @@ void Miaig::reduceFanins(vi *v) {
|
|||
|
||||
int Miaig::hashTwo(int l0, int l1, int TableSize) {
|
||||
unsigned Key = 0;
|
||||
Key += Abc_Lit2Var(l0) * 7937;
|
||||
Key += Abc_Lit2Var(l1) * 2971;
|
||||
Key += Abc_LitIsCompl(l0) * 911;
|
||||
Key += Abc_LitIsCompl(l1) * 353;
|
||||
Key += Rw_Lit2Var(l0) * 7937;
|
||||
Key += Rw_Lit2Var(l1) * 2971;
|
||||
Key += Rw_LitIsCompl(l0) * 911;
|
||||
Key += Rw_LitIsCompl(l1) * 353;
|
||||
return Key % TableSize;
|
||||
}
|
||||
|
||||
|
|
@ -546,14 +604,14 @@ int Miaig::buildNode(int l0, int l1, int fCprop, int fStrash) {
|
|||
}
|
||||
int *pPlace = NULL;
|
||||
if (fStrash) {
|
||||
pPlace = hashLookup(_data->pTable, Abc_MinInt(l0, l1), Abc_MaxInt(l0, l1), _data->TableSize);
|
||||
pPlace = hashLookup(_data->pTable, Rw_MinInt(l0, l1), Rw_MaxInt(l0, l1), _data->TableSize);
|
||||
if (*pPlace)
|
||||
return *pPlace;
|
||||
}
|
||||
int iObj = appendObj();
|
||||
appendFanin(iObj, Abc_MinInt(l0, l1));
|
||||
appendFanin(iObj, Abc_MaxInt(l0, l1));
|
||||
return pPlace ? (*pPlace = Abc_Var2Lit(iObj, 0)) : Abc_Var2Lit(iObj, 0);
|
||||
appendFanin(iObj, Rw_MinInt(l0, l1));
|
||||
appendFanin(iObj, Rw_MaxInt(l0, l1));
|
||||
return pPlace ? (*pPlace = Rw_Var2Lit(iObj, 0)) : Rw_Var2Lit(iObj, 0);
|
||||
}
|
||||
|
||||
int Miaig::buildNodeBalance_rec(Miaig &pNew, vi *vFanins, int begin, int end, int fCprop, int fStrash) {
|
||||
|
|
@ -594,13 +652,13 @@ Miaig Miaig::dupStrash(int fCprop, int fStrash, int fCascade) {
|
|||
pNew._data->pTable = (int *)calloc(sizeof(int), 3 * pNew._data->TableSize);
|
||||
}
|
||||
Miaig_ForEachInput(i)
|
||||
objCopy(i) = Abc_Var2Lit(i, 0);
|
||||
objCopy(i) = Rw_Var2Lit(i, 0);
|
||||
Miaig_ForEachNode(i) {
|
||||
assert(objFaninNum(i) > 0);
|
||||
if (fCascade)
|
||||
objCopy(i) = buildNodeCascade(pNew, _data->pvFans + i, fCprop, fStrash);
|
||||
objCopy(i) = buildNodeCascade(pNew, objFanins(i), fCprop, fStrash);
|
||||
else
|
||||
objCopy(i) = buildNodeBalance(pNew, _data->pvFans + i, fCprop, fStrash);
|
||||
objCopy(i) = buildNodeBalance(pNew, objFanins(i), fCprop, fStrash);
|
||||
}
|
||||
Miaig_ForEachOutput(i)
|
||||
pNew.appendFanin(pNew.appendObj(), Rw_Lit2LitL(_data->pCopy, objFanin0(i)));
|
||||
|
|
@ -616,21 +674,21 @@ int *Miaig::createStops(void) {
|
|||
assert(objFaninNum(i) == 2);
|
||||
int iLit0 = objFanin0(i);
|
||||
int iLit1 = objFanin1(i);
|
||||
pStop[Abc_Lit2Var(iLit0)] += 1 + Abc_LitIsCompl(iLit0);
|
||||
pStop[Abc_Lit2Var(iLit1)] += 1 + Abc_LitIsCompl(iLit1);
|
||||
pStop[Rw_Lit2Var(iLit0)] += 1 + Rw_LitIsCompl(iLit0);
|
||||
pStop[Rw_Lit2Var(iLit1)] += 1 + Rw_LitIsCompl(iLit1);
|
||||
}
|
||||
Miaig_ForEachOutput(i)
|
||||
pStop[Abc_Lit2Var(objFanin0(i))] += 2;
|
||||
pStop[Rw_Lit2Var(objFanin0(i))] += 2;
|
||||
return pStop;
|
||||
}
|
||||
|
||||
void Miaig::collectSuper_rec(int iLit, int *pStop, vi *vSuper) {
|
||||
if (pStop[Abc_Lit2Var(iLit)] > 1)
|
||||
if (pStop[Rw_Lit2Var(iLit)] > 1)
|
||||
Vi_Push(vSuper, Rw_Lit2LitL(_data->pCopy, iLit));
|
||||
else {
|
||||
assert(Abc_LitIsCompl(iLit) == 0);
|
||||
collectSuper_rec(objFanin0(Abc_Lit2Var(iLit)), pStop, vSuper);
|
||||
collectSuper_rec(objFanin1(Abc_Lit2Var(iLit)), pStop, vSuper);
|
||||
assert(Rw_LitIsCompl(iLit) == 0);
|
||||
collectSuper_rec(objFanin0(Rw_Lit2Var(iLit)), pStop, vSuper);
|
||||
collectSuper_rec(objFanin1(Rw_Lit2Var(iLit)), pStop, vSuper);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -642,7 +700,7 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) {
|
|||
assert(nFaninMax_ >= 2 && nGrowth >= 1);
|
||||
memset(_data->pCopy, 0, sizeof(int) * nObjs()); // obj2lit
|
||||
Miaig_ForEachConstInput(i)
|
||||
objCopy(i) = Abc_Var2Lit(i, 0);
|
||||
objCopy(i) = Rw_Var2Lit(i, 0);
|
||||
Miaig_ForEachNode(i) {
|
||||
if (pStop[i] == 1)
|
||||
continue;
|
||||
|
|
@ -666,7 +724,7 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) {
|
|||
// create a cascade of nodes
|
||||
while (Vi_Size(vArray) > nFaninMaxLocal) {
|
||||
int iObj = pNew.appendObj();
|
||||
vi *vFanins = pNew._data->pvFans + iObj;
|
||||
vi *vFanins = pNew.objFanins(iObj);
|
||||
assert(vFanins->ptr == NULL);
|
||||
vFanins->cap = nFaninMaxLocal + nGrowthLocal;
|
||||
vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap);
|
||||
|
|
@ -675,18 +733,18 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) {
|
|||
assert(Vi_Space(vFanins) == nGrowthLocal);
|
||||
for (k = 0; k < nFaninMaxLocal; k++)
|
||||
Vi_Drop(vArray, 0);
|
||||
Vi_Push(vArray, Abc_Var2Lit(iObj, 0));
|
||||
Vi_Push(vArray, Rw_Var2Lit(iObj, 0));
|
||||
}
|
||||
// create the last node
|
||||
int iObj = pNew.appendObj();
|
||||
vi *vFanins = pNew._data->pvFans + iObj;
|
||||
vi *vFanins = pNew.objFanins(iObj);
|
||||
assert(vFanins->ptr == NULL);
|
||||
vFanins->cap = Vi_Size(vArray) + nGrowthLocal;
|
||||
vFanins->ptr = (int *)malloc(sizeof(int) * vFanins->cap);
|
||||
Vi_ForEachEntry(vArray, iLit, k)
|
||||
pNew.appendFanin(iObj, iLit);
|
||||
assert(Vi_Space(vFanins) == nGrowthLocal);
|
||||
objCopy(i) = Abc_Var2Lit(iObj, 0);
|
||||
objCopy(i) = Rw_Var2Lit(iObj, 0);
|
||||
}
|
||||
}
|
||||
Miaig_ForEachOutput(i)
|
||||
|
|
@ -700,8 +758,8 @@ Miaig Miaig::dupMulti(int nFaninMax_, int nGrowth) {
|
|||
void Miaig::truthSimNode(int i) {
|
||||
int k, iLit;
|
||||
Miaig_ForEachObjFanin(i, iLit, k) {
|
||||
if (k == 0) Tt_DupC(objTruth(i, objType(i)), objTruth(Abc_Lit2Var(iLit), objType(Abc_Lit2Var(iLit))), Abc_LitIsCompl(iLit), nWords());
|
||||
else Tt_Sharp(objTruth(i, objType(i)), objTruth(Abc_Lit2Var(iLit), objType(Abc_Lit2Var(iLit))), Abc_LitIsCompl(iLit), nWords());
|
||||
if (k == 0) Tt_DupC(objTruth(i, objType(i)), objTruth(Rw_Lit2Var(iLit), objType(Rw_Lit2Var(iLit))), Rw_LitIsCompl(iLit), nWords());
|
||||
else Tt_Sharp(objTruth(i, objType(i)), objTruth(Rw_Lit2Var(iLit), objType(Rw_Lit2Var(iLit))), Rw_LitIsCompl(iLit), nWords());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -712,9 +770,9 @@ word *Miaig::truthSimNodeSubset(int i, int m) {
|
|||
Miaig_ForEachObjFanin(i, iLit, k) {
|
||||
if ((m >> k) & 1) { // fanin is included in the subset
|
||||
if (Counter++ == 0)
|
||||
Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords());
|
||||
Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
|
||||
else
|
||||
Tt_Sharp(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords());
|
||||
Tt_Sharp(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
|
||||
}
|
||||
}
|
||||
assert(Counter == Tt_BitCount16(m));
|
||||
|
|
@ -724,8 +782,8 @@ word *Miaig::truthSimNodeSubset(int i, int m) {
|
|||
word *Miaig::truthSimNodeSubset2(int i, vi *vFanins, int nFanins) {
|
||||
int k, iLit;
|
||||
Vi_ForEachEntryStop(vFanins, iLit, k, nFanins) {
|
||||
if (k == 0) Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords());
|
||||
else Tt_Sharp(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords());
|
||||
if (k == 0) Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
|
||||
else Tt_Sharp(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
|
||||
}
|
||||
return _data->pProd;
|
||||
}
|
||||
|
|
@ -753,15 +811,24 @@ void Miaig::initializeTruth(void) {
|
|||
Tt_Dup(objTruth(i, 2), objTruth(i, 0), nWords());
|
||||
}
|
||||
|
||||
void Miaig::truthUpdate(vi *vTfo) {
|
||||
void Miaig::truthUpdate(vi *vTfo, word *pExc, int fCheck) {
|
||||
int i, iTemp, nFails = 0;
|
||||
nTravIds()++;
|
||||
Vi_ForEachEntry(vTfo, iTemp, i) {
|
||||
truthSimNode(iTemp);
|
||||
if (objIsPo(iTemp) && !Tt_Equal(objTruth(iTemp, 2), objTruth(iTemp, 0), nWords()))
|
||||
printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++;
|
||||
if (!pExc) {
|
||||
Vi_ForEachEntry(vTfo, iTemp, i) {
|
||||
truthSimNode(iTemp);
|
||||
if (fCheck && objIsPo(iTemp) && !Tt_Equal(objTruth(iTemp, 2), objTruth(iTemp, 0), nWords()))
|
||||
printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++;
|
||||
}
|
||||
} else {
|
||||
Vi_ForEachEntry(vTfo, iTemp, i) {
|
||||
truthSimNode(iTemp);
|
||||
if (fCheck && objIsPo(iTemp) && !Tt_EqualOnCare(pExc + objPoIdx(iTemp) * nWords(), objTruth(iTemp, 2), objTruth(iTemp, 0), nWords())) {
|
||||
printf("Verification failed at output %d.\n", iTemp - (nObjs() - nOuts())), nFails++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (nFails)
|
||||
if (fCheck && nFails)
|
||||
printf("Verification failed for %d outputs after updating node %d.\n", nFails, Vi_Read(vTfo, 0));
|
||||
}
|
||||
|
||||
|
|
@ -772,7 +839,7 @@ int Miaig::computeTfo_rec(int iObj) {
|
|||
if (objTravId(iObj) == nTravIds() - 1)
|
||||
return 0;
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k) {
|
||||
Value |= computeTfo_rec(Abc_Lit2Var(iLit));
|
||||
Value |= computeTfo_rec(Rw_Lit2Var(iLit));
|
||||
}
|
||||
objTravId(iObj) = nTravIds() - 1 + Value;
|
||||
if (Value) Vi_Push(_data->vTfo, iObj);
|
||||
|
|
@ -795,15 +862,23 @@ vi *Miaig::computeTfo(int iObj) {
|
|||
return _data->vTfo;
|
||||
}
|
||||
|
||||
word *Miaig::computeCareSet(int iObj) {
|
||||
word *Miaig::computeCareSet(int iObj, word *pExc) {
|
||||
vi *vTfo = computeTfo(iObj);
|
||||
int i, iTemp;
|
||||
Tt_Not(objTruth(iObj, 1), objTruth(iObj, 0), nWords());
|
||||
Tt_Clear(_data->pCare, nWords());
|
||||
Vi_ForEachEntryStart(vTfo, iTemp, i, 1) {
|
||||
truthSimNode(iTemp);
|
||||
if (objIsPo(iTemp))
|
||||
Tt_OrXor(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), nWords());
|
||||
if (!pExc) {
|
||||
Vi_ForEachEntryStart(vTfo, iTemp, i, 1) {
|
||||
truthSimNode(iTemp);
|
||||
if (objIsPo(iTemp))
|
||||
Tt_OrXor(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), nWords());
|
||||
}
|
||||
} else {
|
||||
Vi_ForEachEntryStart(vTfo, iTemp, i, 1) {
|
||||
truthSimNode(iTemp);
|
||||
if (objIsPo(iTemp))
|
||||
Tt_OrXorAnd(_data->pCare, objTruth(iTemp, 0), objTruth(iTemp, 1), pExc + objPoIdx(iTemp) * nWords(), nWords());
|
||||
}
|
||||
}
|
||||
return _data->pCare;
|
||||
}
|
||||
|
|
@ -823,7 +898,6 @@ void Miaig::addPair(vi *vPair, int iFan1, int iFan2) {
|
|||
pArray = Vi_Array(vPair);
|
||||
}
|
||||
pArray[i + 2]++;
|
||||
//printf( "Adding pair (%d, %d)\n", iFan1, iFan2 );
|
||||
}
|
||||
|
||||
// find fanin pair that appears most often
|
||||
|
|
@ -861,11 +935,11 @@ void Miaig::extractBest(vi *vPairs) {
|
|||
int iBest = findPair(vPairs);
|
||||
assert(iBest >= 0);
|
||||
//printf( "Creating node %d with fanins (%d, %d).\n", iObj, pArray[iBest], pArray[iBest+1] );
|
||||
assert(Vi_Size(_data->pvFans + iObj) == 0);
|
||||
assert(Vi_Size(objFanins(iObj)) == 0);
|
||||
appendFanin(iObj, pArray[iBest]);
|
||||
appendFanin(iObj, pArray[iBest + 1]);
|
||||
Miaig_ForEachNode(i)
|
||||
Counter += updateFanins(_data->pvFans + i, pArray[iBest], pArray[iBest + 1], Abc_Var2Lit(iObj, 0));
|
||||
Counter += updateFanins(objFanins(i), pArray[iBest], pArray[iBest + 1], Rw_Var2Lit(iObj, 0));
|
||||
assert(Counter == pArray[iBest + 2]);
|
||||
}
|
||||
|
||||
|
|
@ -874,7 +948,7 @@ vi *Miaig::findPairs(word *pSto, int nWords) {
|
|||
vi *vPairs = Vi_Alloc(30);
|
||||
int i, f1, f2, iFan1, iFan2;
|
||||
Miaig_ForEachNode(i) {
|
||||
vi *vFans = _data->pvFans + i;
|
||||
vi *vFans = objFanins(i);
|
||||
Vi_ForEachEntry(vFans, iFan1, f1) {
|
||||
word *pRowFan1 = pSto + iFan1 * nWords;
|
||||
Vi_ForEachEntryStart(vFans, iFan2, f2, f1 + 1) {
|
||||
|
|
@ -916,35 +990,35 @@ int Miaig::findShared(int nNewNodesMax) {
|
|||
return i;
|
||||
}
|
||||
|
||||
int Miaig::checkConst(int iObj, word *pCare, int fVerbose) {
|
||||
int Miaig::checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbose) {
|
||||
word *pFunc = objTruth(iObj, 0);
|
||||
if (!Tt_IntersectC(pCare, pFunc, 0, nWords())) {
|
||||
derefObj_rec(iObj, -1);
|
||||
Vi_Fill(_data->pvFans + iObj, 1, 0); // const0
|
||||
Vi_Fill(objFanins(iObj), 1, 0); // const0
|
||||
refObj(iObj);
|
||||
truthUpdate(_data->vTfo);
|
||||
truthUpdate(_data->vTfo, pExc, fCheck);
|
||||
if (fVerbose) printf("Detected Const0 at node %d.\n", iObj);
|
||||
return 1;
|
||||
}
|
||||
if (!Tt_IntersectC(pCare, pFunc, 1, nWords())) {
|
||||
derefObj_rec(iObj, -1);
|
||||
Vi_Fill(_data->pvFans + iObj, 1, 1); // const1
|
||||
Vi_Fill(objFanins(iObj), 1, 1); // const1
|
||||
refObj(iObj);
|
||||
truthUpdate(_data->vTfo);
|
||||
truthUpdate(_data->vTfo, pExc, fCheck);
|
||||
if (fVerbose) printf("Detected Const1 at node %d.\n", iObj);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, int fVerbose) {
|
||||
int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
|
||||
int i, k, n, iLit, nAdded = 0;
|
||||
word *pCare = computeCareSet(iObj);
|
||||
word *pCare = computeCareSet(iObj, pExc);
|
||||
assert(nAddedMax > 0);
|
||||
assert(nAddedMax <= Vi_Space(_data->pvFans + iObj));
|
||||
assert(nAddedMax <= Vi_Space(objFanins(iObj)));
|
||||
// mark node's fanins
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k)
|
||||
objTravId(Abc_Lit2Var(iLit)) = nTravIds();
|
||||
objTravId(Rw_Lit2Var(iLit)) = nTravIds();
|
||||
// compute the onset
|
||||
word *pOnset = objTruth(iObj, 0);
|
||||
Tt_Sharp(pOnset, pCare, 0, nWords());
|
||||
|
|
@ -961,14 +1035,37 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, i
|
|||
|
||||
int *pOrderF = Vi_Array(_data->vOrderF);
|
||||
std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
|
||||
return objLevel(Abc_Lit2Var(a)) > objLevel(Abc_Lit2Var(b));
|
||||
return objLevel(Rw_Lit2Var(a)) > objLevel(Rw_Lit2Var(b));
|
||||
});
|
||||
#if USE_OLD_LEVEL_SORTING
|
||||
std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
|
||||
if (objLevel(Abc_Lit2Var(a)) == 0 || objLevel(Abc_Lit2Var(b)) == 0) {
|
||||
if (objLevel(Rw_Lit2Var(a)) == 0 || objLevel(Rw_Lit2Var(b)) == 0) {
|
||||
return false;
|
||||
}
|
||||
return objRef(Abc_Lit2Var(a)) < objRef(Abc_Lit2Var(b));
|
||||
return objRef(Rw_Lit2Var(a)) < objRef(Rw_Lit2Var(b));
|
||||
});
|
||||
#else
|
||||
// Sort all literals by objRef except in the case where they refer to a variable on level zero.
|
||||
// Level zero literals are always sorted before non-level zero literals. Two level zero literals are ordered by their
|
||||
// objRef to maintain strict weak ordering.
|
||||
std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
|
||||
bool a_is_level_0 = (objLevel(Rw_Lit2Var(a)) == 0);
|
||||
bool b_is_level_0 = (objLevel(Rw_Lit2Var(b)) == 0);
|
||||
|
||||
// Always sort level 0 literals before the rest.
|
||||
if (a_is_level_0 && !b_is_level_0) {
|
||||
return true; // a (level 0) comes before b (non-level 0)
|
||||
}
|
||||
if (!a_is_level_0 && b_is_level_0) {
|
||||
return false; // b (level 0) comes before a (non-level 0)
|
||||
}
|
||||
|
||||
// If both are level 0 or none are level 0, then sort by objRef.
|
||||
// If both are level 0 the relative ordering (probably?) doesn't matter,
|
||||
// so we can just order them anyway by objRef such that we maintain the strict weak ordering.
|
||||
return objRef(Rw_Lit2Var(a)) < objRef(Rw_Lit2Var(b));
|
||||
});
|
||||
#endif
|
||||
|
||||
// iterate through candidate fanins (nodes that are not in the TFO of iObj)
|
||||
Vi_ForEachEntry(_data->vOrderF, i, k) {
|
||||
|
|
@ -976,8 +1073,8 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, i
|
|||
// new fanin can be added if its offset does not intersect with the node's onset
|
||||
for (n = 0; n < 2; n++)
|
||||
if (!Tt_IntersectC(pOnset, objTruth(i, 0), !n, nWords())) {
|
||||
if (fVerbose) printf("Adding node %d fanin %d\n", iObj, Abc_Var2Lit(i, n));
|
||||
appendFanin(iObj, Abc_Var2Lit(i, n));
|
||||
if (fVerbose) printf("Adding node %d fanin %d\n", iObj, Rw_Var2Lit(i, n));
|
||||
appendFanin(iObj, Rw_Var2Lit(i, n));
|
||||
objRef(i)++;
|
||||
nAdded++;
|
||||
break;
|
||||
|
|
@ -986,15 +1083,15 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, i
|
|||
break;
|
||||
}
|
||||
//printf( "Updating TFO of node %d: ", iObj ); Vi_Print(_data->vTfo);
|
||||
truthUpdate(_data->vTfo);
|
||||
truthUpdate(_data->vTfo, pExc, fCheck);
|
||||
//assert( objFaninNum(iObj) <= nFaninMax );
|
||||
return nAdded;
|
||||
}
|
||||
|
||||
int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, int fVerbose) {
|
||||
int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, word *pExc, int fCheck, int fVerbose) {
|
||||
int n, k, iLit, nFans = objFaninNum(iObj);
|
||||
word *pCare = computeCareSet(iObj);
|
||||
if (checkConst(iObj, pCare, fVerbose))
|
||||
word *pCare = computeCareSet(iObj, pExc);
|
||||
if (checkConst(iObj, pCare, pExc, fCheck, fVerbose))
|
||||
return nFans;
|
||||
if (fOnlyConst)
|
||||
return 0;
|
||||
|
|
@ -1003,12 +1100,12 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic,
|
|||
// if one fanin can be used, take it
|
||||
word *pFunc = objTruth(iObj, 0);
|
||||
Miaig_ForEachObjFanin(iObj, iLit, k) {
|
||||
Tt_DupC(_data->pProd, objTruth(Abc_Lit2Var(iLit), 0), Abc_LitIsCompl(iLit), nWords());
|
||||
Tt_DupC(_data->pProd, objTruth(Rw_Lit2Var(iLit), 0), Rw_LitIsCompl(iLit), nWords());
|
||||
if (Tt_EqualOnCare(pCare, pFunc, _data->pProd, nWords())) {
|
||||
derefObj(iObj);
|
||||
Vi_Fill(_data->pvFans + iObj, 1, iLit);
|
||||
Vi_Fill(objFanins(iObj), 1, iLit);
|
||||
refObj(iObj);
|
||||
truthUpdate(_data->vTfo);
|
||||
truthUpdate(_data->vTfo, pExc, fCheck);
|
||||
if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj));
|
||||
return nFans - 1;
|
||||
}
|
||||
|
|
@ -1023,14 +1120,38 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic,
|
|||
if (fHeuristic) {
|
||||
int *pOrderF = Vi_Array(_data->vOrderF);
|
||||
std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
|
||||
return objLevel(Abc_Lit2Var(a)) < objLevel(Abc_Lit2Var(b));
|
||||
return objLevel(Rw_Lit2Var(a)) < objLevel(Rw_Lit2Var(b));
|
||||
});
|
||||
#if USE_OLD_LEVEL_SORTING
|
||||
std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
|
||||
if (objLevel(Abc_Lit2Var(a)) == 0 || objLevel(Abc_Lit2Var(b)) == 0) {
|
||||
if (objLevel(Rw_Lit2Var(a)) == 0 || objLevel(Rw_Lit2Var(b)) == 0) {
|
||||
return false;
|
||||
}
|
||||
return objRef(Abc_Lit2Var(a)) > objRef(Abc_Lit2Var(b));
|
||||
return objRef(Rw_Lit2Var(a)) > objRef(Rw_Lit2Var(b));
|
||||
});
|
||||
#else
|
||||
// Sort all literals by objRef except in the case where they refer to a variable on level zero.
|
||||
// Level zero literals are always sorted before non-level zero literals. Two level zero literals are ordered by their
|
||||
// objRef to maintain strict weak ordering.
|
||||
std::stable_sort(pOrderF, pOrderF + Vi_Size(_data->vOrderF), [&](int a, int b) {
|
||||
bool a_is_level_0 = (objLevel(Rw_Lit2Var(a)) == 0);
|
||||
bool b_is_level_0 = (objLevel(Rw_Lit2Var(b)) == 0);
|
||||
|
||||
// Always sort level 0 literals before the rest.
|
||||
if (a_is_level_0 && !b_is_level_0) {
|
||||
return true; // a (level 0) comes before b (non-level 0)
|
||||
}
|
||||
if (!a_is_level_0 && b_is_level_0) {
|
||||
return false; // b (level 0) comes before a (non-level 0)
|
||||
}
|
||||
|
||||
// If both are level 0 or none are level 0, then sort by objRef.
|
||||
// If both are level 0 the relative ordering (probably?) doesn't matter,
|
||||
// so we can just order them anyway by objRef such that we maintain the strict weak ordering.
|
||||
return objRef(Rw_Lit2Var(a)) < objRef(Rw_Lit2Var(b));
|
||||
});
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
assert(Vi_Size(_data->vOrderF) == nFans);
|
||||
|
|
@ -1045,20 +1166,20 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic,
|
|||
// update the node if it is reduced
|
||||
if (Vi_Size(_data->vOrderF) < nFans) {
|
||||
derefObj(iObj);
|
||||
Vi_Shrink(_data->pvFans + iObj, 0);
|
||||
Vi_Shrink(objFanins(iObj), 0);
|
||||
Vi_ForEachEntry(_data->vOrderF, iLit, k)
|
||||
Vi_PushOrder(_data->pvFans + iObj, iLit);
|
||||
Vi_PushOrder(objFanins(iObj), iLit);
|
||||
refObj(iObj);
|
||||
truthUpdate(_data->vTfo);
|
||||
truthUpdate(_data->vTfo, pExc, fCheck);
|
||||
if (fVerbose) printf("Reducing node %d fanin count from %d to %d.\n", iObj, nFans, objFaninNum(iObj));
|
||||
return nFans - Vi_Size(_data->vOrderF);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose) {
|
||||
expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimit), nDist, nExpandableLevel, fVerbose);
|
||||
reduceOne(iNode, 0, 0, 0, fVerbose);
|
||||
int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
|
||||
expandOne(iNode, std::min(Vi_Space(objFanins(iNode)), nFaninAddLimit), nDist, nExpandableLevel, pExc, fCheck, fVerbose);
|
||||
reduceOne(iNode, 0, 0, 0, pExc, fCheck, fVerbose);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1071,7 +1192,7 @@ vi *Miaig::createRandomOrder(void) {
|
|||
return _data->vOrder;
|
||||
}
|
||||
|
||||
Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int fVerbose) {
|
||||
Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
|
||||
int i, iNode, nAdded = 0;
|
||||
assert(nFaninAddLimitAll > 0);
|
||||
vi *vOrder = createRandomOrder();
|
||||
|
|
@ -1081,12 +1202,12 @@ Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int
|
|||
initializeLevels();
|
||||
if (nDist) initializeDists();
|
||||
Vi_ForEachEntry(vOrder, iNode, i) {
|
||||
nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, fVerbose);
|
||||
nAdded += expandOne(iNode, std::min(Vi_Space(objFanins(iNode)), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, pExc, fCheck, fVerbose);
|
||||
if (nAdded >= nFaninAddLimitAll)
|
||||
break;
|
||||
}
|
||||
assert(nAdded <= nFaninAddLimitAll);
|
||||
verifyRefs();
|
||||
if (fCheck) verifyRefs();
|
||||
return dupDfs();
|
||||
}
|
||||
|
||||
|
|
@ -1103,7 +1224,7 @@ Miaig Miaig::share(int nNewNodesMax) {
|
|||
return pNew;
|
||||
}
|
||||
|
||||
Miaig Miaig::reduce(int fVerbose) {
|
||||
Miaig Miaig::reduce(word *pExc, int fCheck, int fVerbose) {
|
||||
int i, iNode;
|
||||
vi *vOrder = topoCollect();
|
||||
|
||||
|
|
@ -1112,12 +1233,12 @@ Miaig Miaig::reduce(int fVerbose) {
|
|||
initializeLevels();
|
||||
// works best for final
|
||||
Vi_ForEachEntry(vOrder, iNode, i)
|
||||
reduceOne(iNode, 0, 0, 1, fVerbose);
|
||||
verifyRefs();
|
||||
reduceOne(iNode, 0, 0, 1, pExc, fCheck, fVerbose);
|
||||
if (fCheck) verifyRefs();
|
||||
return dupStrash(1, 1, 1);
|
||||
}
|
||||
|
||||
Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose) {
|
||||
Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose) {
|
||||
Miaig pTemp;
|
||||
int i, iNode;
|
||||
vi *vOrder = topoCollect();
|
||||
|
|
@ -1127,23 +1248,28 @@ Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLeve
|
|||
initializeLevels();
|
||||
if (nDist) initializeDists();
|
||||
Vi_ForEachEntry(vOrder, iNode, i) {
|
||||
expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, fVerbose);
|
||||
expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, pExc, fCheck, fVerbose);
|
||||
}
|
||||
verifyRefs();
|
||||
if (fCheck) verifyRefs();
|
||||
return dupDfs().dupStrash(1, 1, 1);
|
||||
}
|
||||
|
||||
Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, int nVerbose) {
|
||||
Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose) {
|
||||
// expand
|
||||
Miaig pNew = expand(nFaninAddLimitAll, nDist, nExpandableLevel, nVerbose);
|
||||
Miaig pNew = expand(nFaninAddLimitAll, nDist, nExpandableLevel, pExc, fCheck, nVerbose);
|
||||
// share
|
||||
pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs);
|
||||
// reduce
|
||||
pNew = pNew.reduce(nVerbose);
|
||||
pNew = pNew.reduce(pExc, fCheck, nVerbose);
|
||||
return pNew;
|
||||
}
|
||||
|
||||
void randomAddBest(std::vector<Miaig> &pBests, Miaig pNew, int nBestSave) {
|
||||
void randomAddBest(std::vector<Miaig> &pBests, Miaig pNew, int nBestSave, Gia_ChMan_t *pChMan) {
|
||||
if ( pChMan ) {
|
||||
Gia_Man_t * pGia = pNew.toGia();
|
||||
Gia_ManDupChoicesAdd(pChMan, pGia);
|
||||
Gia_ManStop( pGia );
|
||||
}
|
||||
if (pBests.size() < nBestSave) {
|
||||
pBests.push_back(pNew);
|
||||
} else {
|
||||
|
|
@ -1156,33 +1282,41 @@ Miaig randomRead(std::vector<Miaig> &pBests) {
|
|||
return pBests[Random_Num(0) % pBests.size()];
|
||||
}
|
||||
|
||||
Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nVerbose) {
|
||||
Miaig randomReadExcept(std::vector<Miaig> &pBests, Miaig &pExcept) {
|
||||
int iNum = Random_Num(0) % pBests.size();
|
||||
return (pBests[iNum] == pExcept) ? pBests[(iNum + 1) % pBests.size()] : pBests[iNum];
|
||||
}
|
||||
|
||||
Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, Gia_ChMan_t *pChMan, int nVerbose) {
|
||||
const int nRootSave = 8;
|
||||
const int nBestSave = 4;
|
||||
int nRestart = 5000;
|
||||
std::vector<Miaig> pRoots = {this->dup(0)};
|
||||
std::vector<Miaig> pBests = {this->dup(0)};
|
||||
std::vector<Miaig> pBests = {this->dup(0)}; Miaig pInit = pBests[0];
|
||||
iword clkStart = Time_Clock();
|
||||
Miaig pNew;
|
||||
Miaig pRoot = pRoots[0];
|
||||
Miaig pBest = this->dup(0);
|
||||
Miaig pBest = this->dup(0); int improved = 0;
|
||||
float (Miaig::*Miaig_ObjectiveFunction)(int, int) = (nMode == 0) ? &Miaig::countAnd2 : &Miaig::countTransistors;
|
||||
int maxLevel = levelGrowRatio != 0 ? this->countLevel() * levelGrowRatio : 0;
|
||||
int nExpandableLevel = maxLevel ? maxLevel - this->countLevel() : 0;
|
||||
int fMapped = nMode > 0;
|
||||
word *pExc = _data->pExc;
|
||||
|
||||
float PrevBest = ((&pBest)->*Miaig_ObjectiveFunction)(1, nMappedMode);
|
||||
int iterNotImproveAfterRestart = 0;
|
||||
if (nVerbose && maxLevel) printf("Max level : %5d\n", maxLevel);
|
||||
if (nVerbose) printf("Initial target : %5g (AND2 = %5g Level = %3d)\n", PrevBest, this->countAnd2(1), this->countLevel());
|
||||
for (int i = 0; nIters ? i < nIters : 1; i++) {
|
||||
if (nVerbose) printf("\rIteration %7d : %5g -> ", i + 1, ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode));
|
||||
if (nVerbose) printf("\rIteration %7d(%zu) : %5g -> ", i + 1, pBests.size(), ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode));
|
||||
if (nTimeOut && nTimeOut < 1.0 * (Time_Clock() - clkStart) / CLOCKS_PER_SEC) break;
|
||||
if (PrevBest == 0) break;
|
||||
pNew = pRoot.dupMulti(nFaninMax, nGrowth);
|
||||
|
||||
if (i % 2 == 0) {
|
||||
pNew = pNew.expandThenReduce(nGrowth, nDist, nExpandableLevel, nVerbose > 1);
|
||||
pNew = pNew.expandThenReduce(nGrowth, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1);
|
||||
}
|
||||
pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nExpandableLevel, nVerbose > 1);
|
||||
pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1);
|
||||
|
||||
++iterNotImproveAfterRestart;
|
||||
// report
|
||||
|
|
@ -1194,17 +1328,17 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth,
|
|||
if (nVerbose) Time_PrintEndl("Elapsed time", Time_Clock() - clkStart);
|
||||
PrevBest = newTarget;
|
||||
pBests = {pNew.dup(0), pNew.dup(0)};
|
||||
pBest = pNew.dup(0, 1);
|
||||
pBest = pNew.dup(0, fMapped), improved = 1;
|
||||
iterNotImproveAfterRestart = 0;
|
||||
} else if (PrevBest == newTarget) {
|
||||
randomAddBest(pBests, pNew.dup(0), nBestSave);
|
||||
randomAddBest(pBests, pNew.dup(0), nBestSave, pChMan);
|
||||
}
|
||||
// compare
|
||||
if (maxLevel ? pNew.countLevel() > maxLevel : 0) {
|
||||
} else if (rootTarget < newTarget) {
|
||||
if (iterNotImproveAfterRestart > nRestart) {
|
||||
pNew = randomRead(pBests).dupMulti(nFaninMax, nGrowth);
|
||||
pNew = pNew.expand(nExpands, nDist, nExpandableLevel, nVerbose > 1);
|
||||
pNew = pNew.expand(nExpands, nDist, nExpandableLevel, pExc, fCheck, nVerbose > 1);
|
||||
pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs);
|
||||
pNew = pNew.dupStrash(1, 1, 0);
|
||||
pRoots = {pNew};
|
||||
|
|
@ -1213,14 +1347,14 @@ Miaig Miaig::rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth,
|
|||
pRoots = {pNew};
|
||||
}
|
||||
} else if (rootTarget == newTarget) {
|
||||
randomAddBest(pRoots, pNew, nRootSave);
|
||||
randomAddBest(pRoots, pNew, nRootSave, pChMan);
|
||||
} else {
|
||||
pRoots = {pNew};
|
||||
}
|
||||
pRoot = randomRead(pRoots);
|
||||
}
|
||||
if (nVerbose) Time_PrintEndl("Total solving time", Time_Clock() - clkStart);
|
||||
return pBest;
|
||||
return improved ? pBest : randomReadExcept(pBests, pInit);
|
||||
}
|
||||
|
||||
} // namespace Rewire
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@
|
|||
#include "base/abc/abc.h"
|
||||
#include "aig/miniaig/miniaig.h"
|
||||
#include "rewire_map.h"
|
||||
#define RW_INT_MAX ABC_INT_MAX
|
||||
#define Rw_MaxInt Abc_MaxInt
|
||||
#define Rw_MinInt Abc_MinInt
|
||||
#define Rw_Var2Lit Abc_Var2Lit
|
||||
#define Rw_Lit2Var Abc_Lit2Var
|
||||
#define Rw_LitIsCompl Abc_LitIsCompl
|
||||
#define Rw_LitNot Abc_LitNot
|
||||
#define Rw_LitNotCond Abc_LitNotCond
|
||||
#define Rw_LitRegular Abc_LitRegular
|
||||
#else
|
||||
#ifdef _WIN32
|
||||
typedef unsigned __int64 word; // 32-bit windows
|
||||
|
|
@ -38,6 +47,15 @@ typedef __int64 iword; // 32-bit windows
|
|||
#else
|
||||
typedef long long iword; // other platforms
|
||||
#endif
|
||||
#define RW_INT_MAX (2147483647)
|
||||
static inline int Rw_MaxInt( int a, int b ) { return a > b ? a : b; }
|
||||
static inline int Rw_MinInt( int a, int b ) { return a < b ? a : b; }
|
||||
static inline int Rw_Var2Lit( int Var, int c ) { assert(Var >= 0 && !(c >> 1)); return Var + Var + c; }
|
||||
static inline int Rw_Lit2Var( int Lit ) { assert(Lit >= 0); return Lit >> 1; }
|
||||
static inline int Rw_LitIsCompl( int Lit ) { assert(Lit >= 0); return Lit & 1; }
|
||||
static inline int Rw_LitNot( int Lit ) { assert(Lit >= 0); return Lit ^ 1; }
|
||||
static inline int Rw_LitNotCond( int Lit, int c ) { assert(Lit >= 0); return Lit ^ (int)(c > 0); }
|
||||
static inline int Rw_LitRegular( int Lit ) { assert(Lit >= 0); return Lit & ~01; }
|
||||
#endif // RW_ABC
|
||||
#include "rewire_vec.h"
|
||||
#include "rewire_tt.h"
|
||||
|
|
@ -129,15 +147,16 @@ static inline int RW_XADD(int *addr, int delta) {
|
|||
#define Miaig_ForEachNodeOutputStart(i, s) for (i = s; i < _data->nObjs; i++)
|
||||
#define Miaig_ForEachObj(i) for (i = 0; i < _data->nObjs; i++)
|
||||
#define Miaig_ForEachObjFanin(i, iLit, k) Vi_ForEachEntry(&_data->pvFans[i], iLit, k)
|
||||
#define Miaig_ForEachObjFaninStart(i, iLit, k, s) Vi_ForEachEntryStart(&_data->pvFans[i], iLit, k, s)
|
||||
|
||||
static inline int Rw_Lit2LitV(int *pMapV2V, int Lit) {
|
||||
assert(Lit >= 0);
|
||||
return Abc_Var2Lit(pMapV2V[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit));
|
||||
return Rw_Var2Lit(pMapV2V[Rw_Lit2Var(Lit)], Rw_LitIsCompl(Lit));
|
||||
}
|
||||
|
||||
static inline int Rw_Lit2LitL(int *pMapV2L, int Lit) {
|
||||
assert(Lit >= 0);
|
||||
return Abc_LitNotCond(pMapV2L[Abc_Lit2Var(Lit)], Abc_LitIsCompl(Lit));
|
||||
return Rw_LitNotCond(pMapV2L[Rw_Lit2Var(Lit)], Rw_LitIsCompl(Lit));
|
||||
}
|
||||
|
||||
struct Miaig_Data {
|
||||
|
|
@ -157,6 +176,7 @@ struct Miaig_Data {
|
|||
word *pTruths[3]; // truth tables
|
||||
word *pCare; // careset
|
||||
word *pProd; // product
|
||||
word *pExc; // Exc
|
||||
vi *vOrder; // node order
|
||||
vi *vOrderF; // fanin order
|
||||
vi *vOrderF2; // fanin order
|
||||
|
|
@ -181,9 +201,15 @@ public:
|
|||
Miaig(Mini_Aig_t *pMiniAig);
|
||||
#endif // RW_ABC
|
||||
|
||||
public:
|
||||
#ifdef RW_ABC
|
||||
void setExc(Gia_Man_t *pExc);
|
||||
#endif // RW_ABC
|
||||
|
||||
public:
|
||||
void addref(void);
|
||||
void release(void);
|
||||
bool operator==(const Miaig &m) const;
|
||||
|
||||
private:
|
||||
void create(int nIns, int nOuts, int nObjsAlloc);
|
||||
|
|
@ -200,6 +226,8 @@ public:
|
|||
int objIsPi(int i);
|
||||
int objIsPo(int i);
|
||||
int objIsNode(int i);
|
||||
int objPiIdx(int i); // No check isPi
|
||||
int objPoIdx(int i); // No check isPo
|
||||
void print(void);
|
||||
int appendObj(void);
|
||||
void appendFanin(int i, int iLit);
|
||||
|
|
@ -213,6 +241,7 @@ public:
|
|||
int &objDist(int i);
|
||||
int &nTravIds(void);
|
||||
word *objTruth(int i, int n);
|
||||
vi *objFanins(int i);
|
||||
int objType(int i);
|
||||
int nWords(void);
|
||||
void refObj(int iObj);
|
||||
|
|
@ -233,19 +262,21 @@ private:
|
|||
int markDfs(void);
|
||||
void markDistanceN_rec(int iObj, int n, int limit);
|
||||
void markDistanceN(int Obj, int n);
|
||||
void markCritical(void);
|
||||
void markCritical_rec(int iObj);
|
||||
void topoCollect_rec(int iObj);
|
||||
vi *topoCollect(void);
|
||||
void reduceFanins(vi *v);
|
||||
int *createStops(void);
|
||||
void collectSuper_rec(int iLit, int *pStop, vi *vSuper);
|
||||
int checkConst(int iObj, word *pCare, int fVerbose);
|
||||
int checkConst(int iObj, word *pCare, word *pExc, int fCheck, int fVerbose);
|
||||
void truthSimNode(int i);
|
||||
word *truthSimNodeSubset(int i, int m);
|
||||
word *truthSimNodeSubset2(int i, vi *vFanins, int nFanins);
|
||||
void truthUpdate(vi *vTfo);
|
||||
void truthUpdate(vi *vTfo, word *pExc = NULL, int fCheck = 0);
|
||||
int computeTfo_rec(int iObj);
|
||||
vi *computeTfo(int iObj);
|
||||
word *computeCareSet(int iObj);
|
||||
word *computeCareSet(int iObj, word *pExc = NULL);
|
||||
vi *createRandomOrder(void);
|
||||
void addPair(vi *vPair, int iFan1, int iFan2);
|
||||
int findPair(vi *vPair);
|
||||
|
|
@ -260,7 +291,7 @@ public:
|
|||
float countAnd2(int reset = 0, int fDummy = 0);
|
||||
// 0: amap 1: &nf 2: &simap
|
||||
float countTransistors(int reset = 0, int nMode = 0);
|
||||
int countLevel(void);
|
||||
int countLevel(int min = 0);
|
||||
|
||||
private:
|
||||
void dupDfs_rec(Miaig &pNew, int iObj);
|
||||
|
|
@ -272,22 +303,22 @@ private:
|
|||
int buildNodeCascade(Miaig &pNew, vi *vFanins, int fCprop, int fStrash);
|
||||
|
||||
private:
|
||||
int expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, int fVerbose);
|
||||
int reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, int fVerbose);
|
||||
int expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose);
|
||||
int expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose);
|
||||
int reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic, word *pExc, int fCheck, int fVerbose);
|
||||
int expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose);
|
||||
|
||||
public:
|
||||
Miaig dup(int fRemDangle, int fMapped = 0);
|
||||
Miaig dupDfs(void);
|
||||
Miaig dupStrash(int fCprop, int fStrash, int fCascade);
|
||||
Miaig dupMulti(int nFaninMax_, int nGrowth);
|
||||
Miaig expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int nVerbose);
|
||||
Miaig expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose);
|
||||
Miaig share(int nNewNodesMax);
|
||||
Miaig reduce(int fVerbose);
|
||||
Miaig expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose);
|
||||
Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, int nVerbose);
|
||||
Miaig rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nVerbose);
|
||||
#ifdef RW_ABC
|
||||
Miaig reduce(word *pExc, int fCheck, int fVerbose);
|
||||
Miaig expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, word *pExc, int fCheck, int fVerbose);
|
||||
Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, word *pExc, int fCheck, int nVerbose);
|
||||
Miaig rewire(int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int fCheck, Gia_ChMan_t *pChMan, int nVerbose);
|
||||
#ifdef RW_ABC
|
||||
Gia_Man_t *toGia(void);
|
||||
Abc_Ntk_t *toNtk(int fMapped = 0);
|
||||
Mini_Aig_t *toMiniAig(void);
|
||||
|
|
@ -373,6 +404,7 @@ inline void Miaig::release(void) {
|
|||
free(_data->pTruths[0]);
|
||||
if (_data->pCare) free(_data->pCare);
|
||||
if (_data->pProd) free(_data->pProd);
|
||||
if (_data->pExc) free(_data->pExc);
|
||||
if (_data->pLevel) free(_data->pLevel);
|
||||
if (_data->pDist) free(_data->pDist);
|
||||
if (_data->pTable) free(_data->pTable);
|
||||
|
|
@ -385,6 +417,10 @@ inline void Miaig::release(void) {
|
|||
_refcount = nullptr;
|
||||
}
|
||||
|
||||
inline bool Miaig::operator==(const Miaig &m) const {
|
||||
return (_data == m._data);
|
||||
}
|
||||
|
||||
inline int &Miaig::nIns(void) {
|
||||
return _data->nIns;
|
||||
}
|
||||
|
|
@ -402,37 +438,47 @@ inline int &Miaig::nObjsAlloc(void) {
|
|||
}
|
||||
|
||||
inline int Miaig::objIsPi(int i) {
|
||||
return i > 0 && i <= _data->nIns;
|
||||
return i > 0 && i <= nIns();
|
||||
}
|
||||
|
||||
inline int Miaig::objIsPo(int i) {
|
||||
return i >= _data->nObjs - _data->nOuts;
|
||||
return i >= nObjs() - nOuts();
|
||||
}
|
||||
|
||||
inline int Miaig::objIsNode(int i) {
|
||||
return i > _data->nIns && i < _data->nObjs - _data->nOuts;
|
||||
return i > nIns() && i < nObjs() - nOuts();
|
||||
}
|
||||
|
||||
inline int Miaig::objPiIdx(int i) {
|
||||
// assert(objIsPi(i));
|
||||
return i - 1;
|
||||
}
|
||||
|
||||
inline int Miaig::objPoIdx(int i) {
|
||||
// assert(objIsPo(i));
|
||||
return i - (nObjs() - nOuts());
|
||||
}
|
||||
|
||||
inline int Miaig::appendObj(void) {
|
||||
assert(_data->nObjs < _data->nObjsAlloc);
|
||||
return _data->nObjs++;
|
||||
assert(nObjs() < nObjsAlloc());
|
||||
return nObjs()++;
|
||||
}
|
||||
|
||||
inline void Miaig::appendFanin(int i, int iLit) {
|
||||
Vi_PushOrder(_data->pvFans + i, iLit);
|
||||
Vi_PushOrder(objFanins(i), iLit);
|
||||
}
|
||||
|
||||
inline int Miaig::objFaninNum(int i) {
|
||||
return Vi_Size(_data->pvFans + i);
|
||||
return Vi_Size(objFanins(i));
|
||||
}
|
||||
|
||||
inline int Miaig::objFanin0(int i) {
|
||||
return Vi_Read(_data->pvFans + i, 0);
|
||||
return Vi_Read(objFanins(i), 0);
|
||||
}
|
||||
|
||||
inline int Miaig::objFanin1(int i) {
|
||||
assert(objFaninNum(i) == 2);
|
||||
return Vi_Read(_data->pvFans + i, 1);
|
||||
return Vi_Read(objFanins(i), 1);
|
||||
}
|
||||
|
||||
inline int &Miaig::objLevel(int i) {
|
||||
|
|
@ -471,11 +517,12 @@ inline float Miaig::countAnd2(int reset, int fDummy) {
|
|||
return Counter;
|
||||
}
|
||||
|
||||
inline int Miaig::countLevel(void) {
|
||||
inline int Miaig::countLevel(int min) {
|
||||
initializeLevels();
|
||||
int i, Level = -1;
|
||||
int i, Level = (min) ? RW_INT_MAX : -1;
|
||||
int (*compareFunc)(int, int) = (min) ? Rw_MinInt : Rw_MaxInt;
|
||||
Miaig_ForEachOutput(i) {
|
||||
Level = Abc_MaxInt(Level, objLevel(i));
|
||||
Level = compareFunc(Level, objLevel(i));
|
||||
}
|
||||
return Level;
|
||||
}
|
||||
|
|
@ -484,6 +531,10 @@ inline word *Miaig::objTruth(int i, int n) {
|
|||
return _data->pTruths[n] + nWords() * i;
|
||||
}
|
||||
|
||||
inline vi *Miaig::objFanins(int i) {
|
||||
return _data->pvFans + i;
|
||||
}
|
||||
|
||||
inline int Miaig::objType(int i) {
|
||||
return objTravId(i) == nTravIds();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,16 +22,16 @@
|
|||
|
||||
ABC_NAMESPACE_IMPL_START
|
||||
|
||||
Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) {
|
||||
return Gia_ManRewireInt(pGia, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fVerbose);
|
||||
Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fChoices, int fVerbose) {
|
||||
return Gia_ManRewireInt(pGia, pExc, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, fChoices, fVerbose);
|
||||
}
|
||||
|
||||
Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) {
|
||||
return Abc_ManRewireInt(pNtk, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fVerbose);
|
||||
Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) {
|
||||
return Abc_ManRewireInt(pNtk, pExc, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, fVerbose);
|
||||
}
|
||||
|
||||
Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose) {
|
||||
return MiniAig_ManRewireInt(pAig, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fVerbose);
|
||||
Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose) {
|
||||
return MiniAig_ManRewireInt(pAig, pExc, nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, nSeed, fCheck, fVerbose);
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_IMPL_END
|
||||
|
|
@ -35,12 +35,12 @@
|
|||
|
||||
ABC_NAMESPACE_HEADER_START
|
||||
|
||||
Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose);
|
||||
Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose);
|
||||
Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose);
|
||||
Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose);
|
||||
Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose);
|
||||
Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fVerbose);
|
||||
Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fChoices, int fVerbose);
|
||||
Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fChoices, int fVerbose);
|
||||
Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose);
|
||||
Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose);
|
||||
Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose);
|
||||
Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, Gia_Man_t *pExc, int nIters, float levelGrowRatio, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nMappedMode, int nDist, int nSeed, int fCheck, int fVerbose);
|
||||
|
||||
ABC_NAMESPACE_HEADER_END
|
||||
|
||||
|
|
|
|||
|
|
@ -152,6 +152,12 @@ static inline void Tt_OrXor(word *pOut, word *pIn1, word *pIn2, int nWords) {
|
|||
pOut[w] |= pIn1[w] ^ pIn2[w];
|
||||
}
|
||||
|
||||
static inline void Tt_OrXorAnd(word *pOut, word *pIn1, word *pIn2, word *pIn3, int nWords) {
|
||||
int w;
|
||||
for (w = 0; w < nWords; w++)
|
||||
pOut[w] |= (pIn1[w] ^ pIn2[w]) & pIn3[w];
|
||||
}
|
||||
|
||||
static inline int Tt_WordNum(int n) {
|
||||
return n > 6 ? (1 << (n - 6)) : 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@ namespace rrr {
|
|||
}
|
||||
|
||||
template <typename Ntk>
|
||||
Gia_Man_t *CreateGia(Ntk *pNtk) {
|
||||
Gia_Man_t *CreateGia(Ntk *pNtk, bool fHash = true) {
|
||||
Gia_Man_t *pGia = Gia_ManStart(pNtk->GetNumNodes());
|
||||
Gia_ManHashStart(pGia);
|
||||
if(fHash) {
|
||||
Gia_ManHashStart(pGia);
|
||||
}
|
||||
std::vector<int> v(pNtk->GetNumNodes());
|
||||
v[0] = Gia_ManConst0Lit();
|
||||
pNtk->ForEachPi([&](int id) {
|
||||
|
|
@ -43,8 +45,10 @@ namespace rrr {
|
|||
pNtk->ForEachFanin(id, [&](int fi, bool c) {
|
||||
if(x == -1) {
|
||||
x = Abc_LitNotCond(v[fi], c);
|
||||
} else {
|
||||
} else if(fHash) {
|
||||
x = Gia_ManHashAnd(pGia, x, Abc_LitNotCond(v[fi], c));
|
||||
} else {
|
||||
x = Gia_ManAppendAnd(pGia, x, Abc_LitNotCond(v[fi], c));
|
||||
}
|
||||
});
|
||||
if(x == -1) {
|
||||
|
|
@ -55,7 +59,9 @@ namespace rrr {
|
|||
pNtk->ForEachPoDriver([&](int fi, bool c) {
|
||||
Gia_ManAppendCo(pGia, Abc_LitNotCond(v[fi], c));
|
||||
});
|
||||
Gia_ManHashStop(pGia);
|
||||
if(fHash) {
|
||||
Gia_ManHashStop(pGia);
|
||||
}
|
||||
return pGia;
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +78,7 @@ namespace rrr {
|
|||
assert(r == 0);
|
||||
Abc_FrameSetBatchMode(0);
|
||||
}
|
||||
pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader<Ntk>);
|
||||
pNtk->Read(Abc_FrameReadGia(pAbc), GiaReader<Ntk>, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,11 +23,16 @@ namespace rrr {
|
|||
public:
|
||||
// constructors
|
||||
Analyzer(Parameter const *pPar);
|
||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
||||
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||
|
||||
// checks
|
||||
bool CheckRedundancy(int id, int idx);
|
||||
bool CheckFeasibility(int id, int fi, bool c);
|
||||
|
||||
// summary
|
||||
void ResetSummary();
|
||||
summary<int> GetStatsSummary() const;
|
||||
summary<double> GetTimesSummary() const;
|
||||
};
|
||||
|
||||
/* {{{ Constructors */
|
||||
|
|
@ -39,12 +44,12 @@ namespace rrr {
|
|||
sim(pPar),
|
||||
sol(pPar) {
|
||||
}
|
||||
|
||||
|
||||
template <typename Ntk, typename Sim, typename Sol>
|
||||
void Analyzer<Ntk, Sim, Sol>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
||||
void Analyzer<Ntk, Sim, Sol>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||
pNtk = pNtk_;
|
||||
sim.UpdateNetwork(pNtk, fSame);
|
||||
sol.UpdateNetwork(pNtk, fSame);
|
||||
sim.AssignNetwork(pNtk, fReuse);
|
||||
sol.AssignNetwork(pNtk, fReuse);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -70,6 +75,10 @@ namespace rrr {
|
|||
}
|
||||
sim.AddCex(sol.GetCex());
|
||||
}
|
||||
} else {
|
||||
// if(nVerbose) {
|
||||
// std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is not redundant" << std::endl;
|
||||
// }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -93,11 +102,41 @@ namespace rrr {
|
|||
}
|
||||
sim.AddCex(sol.GetCex());
|
||||
}
|
||||
} else {
|
||||
// if(nVerbose) {
|
||||
// std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is not feasible" << std::endl;
|
||||
// }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Summary */
|
||||
|
||||
template <typename Ntk, typename Sim, typename Sol>
|
||||
void Analyzer<Ntk, Sim, Sol>::ResetSummary() {
|
||||
sim.ResetSummary();
|
||||
sol.ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Sim, typename Sol>
|
||||
summary<int> Analyzer<Ntk, Sim, Sol>::GetStatsSummary() const {
|
||||
summary<int> v = sim.GetStatsSummary();
|
||||
summary<int> v2 = sol.GetStatsSummary();
|
||||
v.insert(v.end(), v2.begin(), v2.end());
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Sim, typename Sol>
|
||||
summary<double> Analyzer<Ntk, Sim, Sol>::GetTimesSummary() const {
|
||||
summary<double> v = sim.GetTimesSummary();
|
||||
summary<double> v2 = sol.GetTimesSummary();
|
||||
v.insert(v.end(), v2.begin(), v2.end());
|
||||
return v;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,13 +64,13 @@ namespace rrr {
|
|||
AndNetwork &operator=(AndNetwork const &x);
|
||||
|
||||
// initialization APIs (should not be called after optimization has started)
|
||||
void Clear();
|
||||
void Clear(bool fClearCallbacks = true);
|
||||
void Reserve(int nReserve);
|
||||
int AddPi();
|
||||
int AddAnd(int id0, int id1, bool c0, bool c1);
|
||||
int AddPo(int id, bool c);
|
||||
template <typename Ntk, typename Reader>
|
||||
void Read(Ntk *pFrom, Reader &reader);
|
||||
void Read(Ntk *pFrom, Reader &reader, bool fNew = true);
|
||||
|
||||
// network properties
|
||||
bool UseComplementedEdges() const;
|
||||
|
|
@ -78,6 +78,7 @@ namespace rrr {
|
|||
int GetNumPis() const;
|
||||
int GetNumInts() const;
|
||||
int GetNumPos() const;
|
||||
int GetNumLevels() const;
|
||||
int GetConst0() const;
|
||||
int GetPi(int idx) const;
|
||||
int GetPo(int idx) const;
|
||||
|
|
@ -272,7 +273,7 @@ namespace rrr {
|
|||
|
||||
/* {{{ Initialization APIs */
|
||||
|
||||
void AndNetwork::Clear() {
|
||||
void AndNetwork::Clear(bool fClearCallbacks) {
|
||||
nNodes = 0;
|
||||
vPis.clear();
|
||||
lInts.clear();
|
||||
|
|
@ -284,7 +285,9 @@ namespace rrr {
|
|||
iTrav = 0;
|
||||
vTrav.clear();
|
||||
fPropagating = false;
|
||||
vCallbacks.clear();
|
||||
if(fClearCallbacks) {
|
||||
vCallbacks.clear();
|
||||
}
|
||||
vBackups.clear();
|
||||
// add constant node
|
||||
vvFaninEdges.emplace_back();
|
||||
|
|
@ -330,9 +333,13 @@ namespace rrr {
|
|||
}
|
||||
|
||||
template <typename Ntk, typename Reader>
|
||||
void AndNetwork::Read(Ntk *pFrom, Reader &reader) {
|
||||
Clear();
|
||||
void AndNetwork::Read(Ntk *pFrom, Reader &reader, bool fNew) {
|
||||
Clear(false);
|
||||
reader(pFrom, this);
|
||||
Action action;
|
||||
action.type = READ;
|
||||
action.fNew = fNew;
|
||||
TakenAction(action);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -359,6 +366,23 @@ namespace rrr {
|
|||
return int_size(vPos);
|
||||
}
|
||||
|
||||
int AndNetwork::GetNumLevels() const {
|
||||
int nMaxLevel = 0;
|
||||
std::vector<int> vLevels(nNodes);
|
||||
ForEachInt([&](int id) {
|
||||
ForEachFanin(id, [&](int fi) {
|
||||
if(vLevels[id] < vLevels[fi]) {
|
||||
vLevels[id] = vLevels[fi];
|
||||
}
|
||||
});
|
||||
vLevels[id] += 1;
|
||||
if(nMaxLevel < vLevels[id]) {
|
||||
nMaxLevel = vLevels[id];
|
||||
}
|
||||
});
|
||||
return nMaxLevel;
|
||||
}
|
||||
|
||||
inline int AndNetwork::GetConst0() const {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace rrr {
|
|||
int nVerbose;
|
||||
|
||||
// data
|
||||
bool fInitialized;
|
||||
NewBdd::Man *pBdd;
|
||||
int target;
|
||||
std::vector<lit> vFs;
|
||||
|
|
@ -35,6 +36,14 @@ namespace rrr {
|
|||
// backups
|
||||
std::vector<BddAnalyzer> vBackups;
|
||||
|
||||
// stats
|
||||
uint64_t nNodesOld;
|
||||
uint64_t nNodesAccumulated;
|
||||
double durationSimulation;
|
||||
double durationPf;
|
||||
double durationCheck;
|
||||
double durationReorder;
|
||||
|
||||
// BDD utils
|
||||
void IncRef(lit x) const;
|
||||
void DecRef(lit x) const;
|
||||
|
|
@ -61,6 +70,10 @@ namespace rrr {
|
|||
void CspfNode(int id);
|
||||
void Cspf(int id = -1, bool fC = true);
|
||||
|
||||
// preparation
|
||||
void Reset(bool fReuse = false);
|
||||
void Initialize();
|
||||
|
||||
// save & load
|
||||
void Save(int slot);
|
||||
void Load(int slot);
|
||||
|
|
@ -71,11 +84,16 @@ namespace rrr {
|
|||
BddAnalyzer();
|
||||
BddAnalyzer(Parameter const *pPar);
|
||||
~BddAnalyzer();
|
||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
||||
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||
|
||||
// checks
|
||||
bool CheckRedundancy(int id, int idx);
|
||||
bool CheckFeasibility(int id, int fi, bool c);
|
||||
|
||||
// summary
|
||||
void ResetSummary();
|
||||
summary<int> GetStatsSummary() const;
|
||||
summary<double> GetTimesSummary() const;
|
||||
};
|
||||
|
||||
/* {{{ BDD utils */
|
||||
|
|
@ -163,103 +181,136 @@ namespace rrr {
|
|||
void BddAnalyzer<Ntk>::ActionCallback(Action const &action) {
|
||||
switch(action.type) {
|
||||
case REMOVE_FANIN:
|
||||
assert(fInitialized);
|
||||
vUpdates[action.id] = true;
|
||||
vGUpdates[action.fi] = true;
|
||||
DecRef(vvCs[action.id][action.idx]);
|
||||
vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
|
||||
if(target != action.id) {
|
||||
// require resimulate before next fesibility check
|
||||
// (this is not mandatory if no pending updates are in TFI of new fanin, but we would rather update than checking every time)
|
||||
target = -1;
|
||||
}
|
||||
break;
|
||||
case REMOVE_UNUSED:
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
if(fInitialized) {
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
for(int fi: action.vFanins) {
|
||||
vGUpdates[fi] = true;
|
||||
}
|
||||
}
|
||||
Assign(vFs[action.id], LitMax);
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
}
|
||||
break;
|
||||
case REMOVE_BUFFER:
|
||||
if(fInitialized) {
|
||||
if(vUpdates[action.id]) {
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
vGUpdates[action.fi] = true;
|
||||
}
|
||||
Assign(vFs[action.id], LitMax);
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
}
|
||||
break;
|
||||
case REMOVE_CONST:
|
||||
if(fInitialized) {
|
||||
if(vUpdates[action.id]) {
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
for(int fi: action.vFanins) {
|
||||
vGUpdates[fi] = true;
|
||||
}
|
||||
Assign(vFs[action.id], LitMax);
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
}
|
||||
Assign(vFs[action.id], LitMax);
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
break;
|
||||
case REMOVE_BUFFER:
|
||||
if(vUpdates[action.id]) {
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
vGUpdates[action.fi] = true;
|
||||
}
|
||||
Assign(vFs[action.id], LitMax);
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
break;
|
||||
case REMOVE_CONST:
|
||||
if(vUpdates[action.id]) {
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
for(int fi: action.vFanins) {
|
||||
vGUpdates[fi] = true;
|
||||
}
|
||||
Assign(vFs[action.id], LitMax);
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
break;
|
||||
case ADD_FANIN:
|
||||
assert(action.id == target);
|
||||
assert(fInitialized);
|
||||
vUpdates[action.id] = true;
|
||||
vCUpdates[action.id] = true;
|
||||
vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
|
||||
break;
|
||||
case TRIVIAL_COLLAPSE: {
|
||||
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
||||
case TRIVIAL_COLLAPSE:
|
||||
if(fInitialized) {
|
||||
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
||||
vCUpdates[action.id] = true;
|
||||
}
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
DecRef(*it);
|
||||
it = vvCs[action.id].erase(it);
|
||||
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
||||
vvCs[action.fi].clear();
|
||||
Assign(vFs[action.fi], LitMax);
|
||||
Assign(vGs[action.fi], LitMax);
|
||||
}
|
||||
break;
|
||||
case TRIVIAL_DECOMPOSE:
|
||||
if(fInitialized) {
|
||||
Allocate();
|
||||
SimulateNode(action.fi, vFs);
|
||||
// time of this simulation is not measured for simplicity sake
|
||||
assert(vGs[action.fi] == LitMax);
|
||||
Assign(vGs[action.fi], vGs[action.id]);
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
assert(vvCs[action.fi].empty());
|
||||
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
||||
vvCs[action.id].erase(it, vvCs[action.id].end());
|
||||
assert(vvCs[action.id].size() == action.idx);
|
||||
vvCs[action.id].resize(action.idx + 1, LitMax);
|
||||
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
||||
vUpdates[action.fi] = false;
|
||||
vGUpdates[action.fi] = false;
|
||||
vCUpdates[action.fi] = vCUpdates[action.id];
|
||||
}
|
||||
break;
|
||||
case SORT_FANINS:
|
||||
if(fInitialized) {
|
||||
std::vector<lit> vCs = vvCs[action.id];
|
||||
vvCs[action.id].clear();
|
||||
for(int index: action.vIndices) {
|
||||
vvCs[action.id].push_back(vCs[index]);
|
||||
}
|
||||
if(!fResim) {
|
||||
fResim = true;
|
||||
/* commenting out the following because it might not be worth checking
|
||||
// if sorted node is in TFO of functionally updated nodes, resimulation is required
|
||||
std::vector<int> vFanouts;
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
if(vUpdates[id]) {
|
||||
pNtk->ForEachFanout(id, false, [&](int fo) {
|
||||
vFanouts.push_back(fo);
|
||||
});
|
||||
}
|
||||
});
|
||||
pNtk->ForEachTfos(vFanouts, false, [&](int fo) {
|
||||
if(fResim) {
|
||||
return;
|
||||
}
|
||||
if(fo == action.id) {
|
||||
fResim = true;
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
vCUpdates[action.id] = true;
|
||||
}
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
DecRef(*it);
|
||||
it = vvCs[action.id].erase(it);
|
||||
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
||||
vvCs[action.fi].clear();
|
||||
Assign(vFs[action.fi], LitMax);
|
||||
Assign(vGs[action.fi], LitMax);
|
||||
break;
|
||||
}
|
||||
case TRIVIAL_DECOMPOSE: {
|
||||
Allocate();
|
||||
SimulateNode(action.fi, vFs);
|
||||
assert(vGs[action.fi] == LitMax);
|
||||
Assign(vGs[action.fi], vGs[action.id]);
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
assert(vvCs[action.fi].empty());
|
||||
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
||||
vvCs[action.id].erase(it, vvCs[action.id].end());
|
||||
assert(vvCs[action.id].size() == action.idx);
|
||||
vvCs[action.id].resize(action.idx + 1, LitMax);
|
||||
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
||||
vUpdates[action.fi] = false;
|
||||
vGUpdates[action.fi] = false;
|
||||
vCUpdates[action.fi] = vCUpdates[action.id];
|
||||
case READ:
|
||||
Reset(!action.fNew);
|
||||
break;
|
||||
}
|
||||
case SORT_FANINS: {
|
||||
std::vector<lit> vCs = vvCs[action.id];
|
||||
vvCs[action.id].clear();
|
||||
for(int index: action.vIndices) {
|
||||
vvCs[action.id].push_back(vCs[index]);
|
||||
}
|
||||
if(!fResim && target != -1 && target != action.id) {
|
||||
pNtk->ForEachTfo(target, false, [&](int fo) {
|
||||
if(fResim) {
|
||||
return;
|
||||
}
|
||||
if(fo == action.id) {
|
||||
fResim = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
vCUpdates[action.id] = true;
|
||||
break;
|
||||
}
|
||||
case SAVE:
|
||||
Save(action.idx);
|
||||
break;
|
||||
|
|
@ -306,6 +357,7 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::Simulate() {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(nVerbose) {
|
||||
std::cout << "symbolic simulation with BDD" << std::endl;
|
||||
}
|
||||
|
|
@ -324,6 +376,7 @@ namespace rrr {
|
|||
vUpdates[id] = false;
|
||||
}
|
||||
});
|
||||
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -410,6 +463,7 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::Cspf(int id, bool fC) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(id != -1) {
|
||||
pNtk->ForEachTfoReverse(id, false, [&](int fo) {
|
||||
CspfNode(fo);
|
||||
|
|
@ -427,10 +481,82 @@ namespace rrr {
|
|||
CspfNode(id);
|
||||
});
|
||||
}
|
||||
durationPf += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Preparation */
|
||||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::Reset(bool fReuse) {
|
||||
while(!vBackups.empty()) {
|
||||
PopBack();
|
||||
}
|
||||
DelVec(vFs);
|
||||
DelVec(vGs);
|
||||
DelVecVec(vvCs);
|
||||
fInitialized = false;
|
||||
target = -1;
|
||||
fResim = false;
|
||||
vUpdates.clear();
|
||||
vGUpdates.clear();
|
||||
vCUpdates.clear();
|
||||
if(!fReuse) {
|
||||
nNodesOld = 0;
|
||||
if(pBdd) {
|
||||
nNodesAccumulated += pBdd->GetNumTotalCreatedNodes();
|
||||
}
|
||||
delete pBdd;
|
||||
pBdd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::Initialize() {
|
||||
bool fUseReo = false;
|
||||
if(!pBdd) {
|
||||
NewBdd::Param Par;
|
||||
Par.nObjsMaxLog = 25;
|
||||
Par.nCacheMaxLog = 20;
|
||||
Par.fCountOnes = false;
|
||||
Par.nGbc = 1;
|
||||
Par.nReo = 4000;
|
||||
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
||||
fUseReo = true;
|
||||
}
|
||||
assert(pBdd->GetNumVars() == pNtk->GetNumPis());
|
||||
Allocate();
|
||||
Assign(vFs[0], pBdd->Const0());
|
||||
int idx = 0;
|
||||
pNtk->ForEachPi([&](int id) {
|
||||
Assign(vFs[id], pBdd->IthVar(idx));
|
||||
idx++;
|
||||
});
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vUpdates[id] = true;
|
||||
});
|
||||
Simulate();
|
||||
if(fUseReo) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
pBdd->Reorder();
|
||||
pBdd->TurnOffReo();
|
||||
durationReorder += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
||||
});
|
||||
pNtk->ForEachPo([&](int id) {
|
||||
vvCs[id].resize(1, LitMax);
|
||||
Assign(vvCs[id][0], pBdd->Const0());
|
||||
int fi = pNtk->GetFanin(id, 0);
|
||||
vGUpdates[fi] = true;
|
||||
});
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Save & load */
|
||||
|
||||
template <typename Ntk>
|
||||
|
|
@ -468,7 +594,7 @@ namespace rrr {
|
|||
vBackups.pop_back();
|
||||
}
|
||||
|
||||
/* }}} Save & load end */
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Constructors */
|
||||
|
||||
|
|
@ -476,93 +602,34 @@ namespace rrr {
|
|||
BddAnalyzer<Ntk>::BddAnalyzer() :
|
||||
pNtk(NULL),
|
||||
nVerbose(0),
|
||||
fInitialized(false),
|
||||
pBdd(NULL),
|
||||
target(-1),
|
||||
fResim(false) {
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
BddAnalyzer<Ntk>::BddAnalyzer(Parameter const *pPar) :
|
||||
pNtk(NULL),
|
||||
nVerbose(pPar->nAnalyzerVerbose),
|
||||
fInitialized(false),
|
||||
pBdd(NULL),
|
||||
target(-1),
|
||||
fResim(false) {
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
||||
// clear
|
||||
while(!vBackups.empty()) {
|
||||
PopBack();
|
||||
}
|
||||
DelVec(vFs);
|
||||
DelVec(vGs);
|
||||
DelVecVec(vvCs);
|
||||
pNtk = pNtk_;
|
||||
target = -1;
|
||||
fResim = false;
|
||||
vUpdates.clear();
|
||||
vGUpdates.clear();
|
||||
vCUpdates.clear();
|
||||
// alloc
|
||||
bool fUseReo = false;
|
||||
if(!pBdd || pBdd->GetNumVars() != pNtk->GetNumPis()) {
|
||||
// need to reset manager
|
||||
delete pBdd;
|
||||
NewBdd::Param Par;
|
||||
Par.nObjsMaxLog = 25;
|
||||
Par.nCacheMaxLog = 20;
|
||||
Par.fCountOnes = true;
|
||||
Par.nGbc = 1;
|
||||
Par.nReo = 4000;
|
||||
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
||||
fUseReo = true;
|
||||
} else if(!fSame) {
|
||||
// turning on reordering if network function changed
|
||||
pBdd->TurnOnReo();
|
||||
fUseReo = true;
|
||||
}
|
||||
Allocate();
|
||||
// prepare
|
||||
Assign(vFs[0], pBdd->Const0());
|
||||
int idx = 0;
|
||||
pNtk->ForEachPi([&](int id) {
|
||||
Assign(vFs[id], pBdd->IthVar(idx));
|
||||
idx++;
|
||||
});
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vUpdates[id] = true;
|
||||
});
|
||||
Simulate();
|
||||
if(fUseReo) {
|
||||
pBdd->Reorder();
|
||||
pBdd->TurnOffReo();
|
||||
}
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
||||
});
|
||||
pNtk->ForEachPo([&](int id) {
|
||||
vvCs[id].resize(1, LitMax);
|
||||
Assign(vvCs[id][0], pBdd->Const0());
|
||||
int fi = pNtk->GetFanin(id, 0);
|
||||
vGUpdates[fi] = true;
|
||||
});
|
||||
pNtk->AddCallback(std::bind(&BddAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
BddAnalyzer<Ntk>::~BddAnalyzer() {
|
||||
while(!vBackups.empty()) {
|
||||
PopBack();
|
||||
}
|
||||
DelVec(vFs);
|
||||
DelVec(vGs);
|
||||
DelVecVec(vvCs);
|
||||
if(pBdd) {
|
||||
pBdd->PrintStats();
|
||||
}
|
||||
delete pBdd;
|
||||
Reset();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||
Reset(fReuse);
|
||||
pNtk = pNtk_;
|
||||
pNtk->AddCallback(std::bind(&BddAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -571,20 +638,22 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
bool BddAnalyzer<Ntk>::CheckRedundancy(int id, int idx) {
|
||||
if(fResim) {
|
||||
if(!fInitialized) {
|
||||
Initialize();
|
||||
} else if(fResim) {
|
||||
Simulate();
|
||||
fResim = false;
|
||||
}
|
||||
Cspf(id);
|
||||
time_point timeStart = GetCurrentTime();
|
||||
bool fRedundant = false;
|
||||
switch(pNtk->GetNodeType(id)) {
|
||||
case AND: {
|
||||
int fi = pNtk->GetFanin(id, idx);
|
||||
bool c = pNtk->GetCompl(id, idx);
|
||||
lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]);
|
||||
if(pBdd->IsConst1(x)) {
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
||||
}
|
||||
return true;
|
||||
fRedundant = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -592,18 +661,30 @@ namespace rrr {
|
|||
assert(0);
|
||||
}
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
||||
if(fRedundant) {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
||||
} else {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||
return fRedundant;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
bool BddAnalyzer<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||
if(target != id) { // simualte if there has been update in non-tfo of this node
|
||||
if(!fInitialized) {
|
||||
Initialize();
|
||||
} else if(target != id && (target == -1 || vUpdates[target])) {
|
||||
// resimulation is required if there are pending updates in TFI of new fanin
|
||||
// but it seems not worthwhile to check that condition every time
|
||||
// so we update if pending updates are not only at current target
|
||||
Simulate();
|
||||
target = id;
|
||||
}
|
||||
target = id;
|
||||
Cspf(id, false);
|
||||
time_point timeStart = GetCurrentTime();
|
||||
bool fFeasible = false;
|
||||
switch(pNtk->GetNodeType(id)) {
|
||||
case AND: {
|
||||
lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]);
|
||||
|
|
@ -611,10 +692,7 @@ namespace rrr {
|
|||
lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
|
||||
DecRef(x);
|
||||
if(pBdd->IsConst1(y)) {
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
||||
}
|
||||
return true;
|
||||
fFeasible = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -622,9 +700,49 @@ namespace rrr {
|
|||
assert(0);
|
||||
}
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
||||
if(fFeasible) {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
||||
} else {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||
return fFeasible;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Summary */
|
||||
|
||||
template <typename Ntk>
|
||||
void BddAnalyzer<Ntk>::ResetSummary() {
|
||||
if(pBdd) {
|
||||
nNodesOld = pBdd->GetNumTotalCreatedNodes();
|
||||
} else {
|
||||
nNodesOld = 0;
|
||||
}
|
||||
nNodesAccumulated = 0;
|
||||
durationSimulation = 0;
|
||||
durationPf = 0;
|
||||
durationCheck = 0;
|
||||
durationReorder = 0;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
summary<int> BddAnalyzer<Ntk>::GetStatsSummary() const {
|
||||
summary<int> v;
|
||||
v.emplace_back("bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
summary<double> BddAnalyzer<Ntk>::GetTimesSummary() const {
|
||||
summary<double> v;
|
||||
v.emplace_back("bdd symbolic simulation", durationSimulation);
|
||||
v.emplace_back("bdd care computation", durationPf);
|
||||
v.emplace_back("bdd check", durationCheck);
|
||||
v.emplace_back("bdd reorder", durationReorder);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
|
|||
|
|
@ -181,6 +181,7 @@ namespace NewBdd {
|
|||
bvar nObjs;
|
||||
bvar nObjsAlloc;
|
||||
bvar nObjsMax;
|
||||
unsigned long long nCreatedTotal;
|
||||
bvar RemovedHead;
|
||||
int nGbc;
|
||||
bvar nReo;
|
||||
|
|
@ -396,6 +397,7 @@ namespace NewBdd {
|
|||
for(; *q; q = vNexts.begin() + *q)
|
||||
if(VarOfBvar(*q) == v && ThenOfBvar(*q) == x1 && ElseOfBvar(*q) == x0)
|
||||
return Bvar2Lit(*q);
|
||||
nCreatedTotal++;
|
||||
bvar next = *p;
|
||||
if(nObjs < nObjsAlloc)
|
||||
*p = nObjs++;
|
||||
|
|
@ -642,6 +644,7 @@ namespace NewBdd {
|
|||
|
||||
public:
|
||||
Man(int nVars_, Param p) {
|
||||
nCreatedTotal = 0;
|
||||
nVerbose = p.nVerbose;
|
||||
// parameter sanity check
|
||||
if(p.nObjsMaxLog < p.nObjsAllocLog)
|
||||
|
|
@ -840,6 +843,9 @@ namespace NewBdd {
|
|||
<< "alloc: " << std::setw(10) << nObjsAlloc
|
||||
<< std::endl;
|
||||
}
|
||||
unsigned long long GetNumTotalCreatedNodes() {
|
||||
return nCreatedTotal;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ namespace rrr {
|
|||
int nVerbose;
|
||||
|
||||
// data
|
||||
bool fInitialized;
|
||||
NewBdd::Man *pBdd;
|
||||
std::vector<lit> vFs;
|
||||
std::vector<lit> vGs;
|
||||
|
|
@ -35,6 +36,14 @@ namespace rrr {
|
|||
// backups
|
||||
std::vector<BddMspfAnalyzer> vBackups;
|
||||
|
||||
// stats
|
||||
uint64_t nNodesOld;
|
||||
uint64_t nNodesAccumulated;
|
||||
double durationSimulation;
|
||||
double durationPf;
|
||||
double durationCheck;
|
||||
double durationReorder;
|
||||
|
||||
// BDD utils
|
||||
void IncRef(lit x) const;
|
||||
void DecRef(lit x) const;
|
||||
|
|
@ -63,6 +72,10 @@ namespace rrr {
|
|||
void MspfNode(int id);
|
||||
void Mspf(int id = -1, bool fC = true);
|
||||
|
||||
// preparation
|
||||
void Reset(bool fReuse = false);
|
||||
void Initialize();
|
||||
|
||||
// save & load
|
||||
void Save(int slot);
|
||||
void Load(int slot);
|
||||
|
|
@ -73,11 +86,16 @@ namespace rrr {
|
|||
BddMspfAnalyzer();
|
||||
BddMspfAnalyzer(Parameter const *pPar);
|
||||
~BddMspfAnalyzer();
|
||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
||||
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||
|
||||
// checks
|
||||
bool CheckRedundancy(int id, int idx);
|
||||
bool CheckFeasibility(int id, int fi, bool c);
|
||||
|
||||
// summary
|
||||
void ResetSummary();
|
||||
summary<int> GetStatsSummary() const;
|
||||
summary<double> GetTimesSummary() const;
|
||||
};
|
||||
|
||||
/* {{{ BDD utils */
|
||||
|
|
@ -165,6 +183,7 @@ namespace rrr {
|
|||
void BddMspfAnalyzer<Ntk>::ActionCallback(Action const &action) {
|
||||
switch(action.type) {
|
||||
case REMOVE_FANIN:
|
||||
assert(fInitialized);
|
||||
fUpdate = true;
|
||||
std::fill(vVisits.begin(), vVisits.end(), false);
|
||||
vUpdates[action.id] = true;
|
||||
|
|
@ -174,103 +193,117 @@ namespace rrr {
|
|||
vvCs[action.id].erase(vvCs[action.id].begin() + action.idx);
|
||||
break;
|
||||
case REMOVE_UNUSED:
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
if(fInitialized) {
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
for(int fi: action.vFanins) {
|
||||
vGUpdates[fi] = true;
|
||||
}
|
||||
}
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
}
|
||||
break;
|
||||
case REMOVE_BUFFER:
|
||||
if(fInitialized) {
|
||||
if(vUpdates[action.id]) {
|
||||
fUpdate = true;
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
vGUpdates[action.fi] = true;
|
||||
}
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
}
|
||||
break;
|
||||
case REMOVE_CONST:
|
||||
if(fInitialized) {
|
||||
if(vUpdates[action.id]) {
|
||||
fUpdate = true;
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
for(int fi: action.vFanins) {
|
||||
vGUpdates[fi] = true;
|
||||
}
|
||||
}
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
break;
|
||||
case REMOVE_BUFFER:
|
||||
if(vUpdates[action.id]) {
|
||||
fUpdate = true;
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
if(vGUpdates[action.id] || vCUpdates[action.id]) {
|
||||
vGUpdates[action.fi] = true;
|
||||
}
|
||||
Assign(vGs[action.id], LitMax);
|
||||
DelVec(vvCs[action.id]);
|
||||
break;
|
||||
case REMOVE_CONST:
|
||||
if(vUpdates[action.id]) {
|
||||
fUpdate = true;
|
||||
for(int fo: action.vFanouts) {
|
||||
vUpdates[fo] = true;
|
||||
vCUpdates[fo] = true;
|
||||
}
|
||||
}
|
||||
for(int fi: action.vFanins) {
|
||||
vGUpdates[fi] = true;
|
||||
}
|
||||
break;
|
||||
case ADD_FANIN:
|
||||
assert(fInitialized);
|
||||
fUpdate = true;
|
||||
std::fill(vVisits.begin(), vVisits.end(), false);
|
||||
vUpdates[action.id] = true;
|
||||
vCUpdates[action.id] = true;
|
||||
vvCs[action.id].insert(vvCs[action.id].begin() + action.idx, LitMax);
|
||||
break;
|
||||
case TRIVIAL_COLLAPSE: {
|
||||
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
||||
vCUpdates[action.id] = true;
|
||||
}
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
DecRef(*it);
|
||||
it = vvCs[action.id].erase(it);
|
||||
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
||||
vvCs[action.fi].clear();
|
||||
Assign(vFs[action.fi], LitMax);
|
||||
Assign(vGs[action.fi], LitMax);
|
||||
break;
|
||||
}
|
||||
case TRIVIAL_DECOMPOSE: {
|
||||
Allocate();
|
||||
SimulateNode(action.fi, vFs);
|
||||
assert(vGs[action.fi] == LitMax);
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
assert(vvCs[action.fi].empty());
|
||||
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
||||
vvCs[action.id].erase(it, vvCs[action.id].end());
|
||||
assert(vvCs[action.id].size() == action.idx);
|
||||
if(!vGUpdates[action.id] && !vCUpdates[action.id]) {
|
||||
// recompute here only when updates are unlikely to happen
|
||||
if(pBdd->IsConst1(vGs[action.id])) {
|
||||
Assign(vGs[action.fi], pBdd->Const1());
|
||||
} else {
|
||||
lit x = pBdd->Const1();
|
||||
IncRef(x);
|
||||
for(int idx2 = 0; idx2 < action.idx; idx2++) {
|
||||
int fi = pNtk->GetFanin(action.id, idx2);
|
||||
bool c = pNtk->GetCompl(action.id, idx2);
|
||||
Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
|
||||
}
|
||||
Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id]));
|
||||
DecRef(x);
|
||||
case TRIVIAL_COLLAPSE:
|
||||
if(fInitialized) {
|
||||
if(vGUpdates[action.fi] || vCUpdates[action.fi]) {
|
||||
vCUpdates[action.id] = true;
|
||||
}
|
||||
} else {
|
||||
// otherwise mark the node for future update
|
||||
vCUpdates[action.id] = true;
|
||||
}
|
||||
vvCs[action.id].resize(action.idx + 1, LitMax);
|
||||
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
||||
vUpdates[action.fi] = false;
|
||||
vGUpdates[action.fi] = false;
|
||||
vCUpdates[action.fi] = false;
|
||||
break;
|
||||
}
|
||||
case SORT_FANINS: {
|
||||
std::vector<lit> vCs = vvCs[action.id];
|
||||
vvCs[action.id].clear();
|
||||
for(int index: action.vIndices) {
|
||||
vvCs[action.id].push_back(vCs[index]);
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
DecRef(*it);
|
||||
it = vvCs[action.id].erase(it);
|
||||
vvCs[action.id].insert(it, vvCs[action.fi].begin(), vvCs[action.fi].end());
|
||||
vvCs[action.fi].clear();
|
||||
Assign(vFs[action.fi], LitMax);
|
||||
Assign(vGs[action.fi], LitMax);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TRIVIAL_DECOMPOSE:
|
||||
if(fInitialized) {
|
||||
Allocate();
|
||||
SimulateNode(action.fi, vFs);
|
||||
// time of this simulation is not measured for simplicity sake
|
||||
assert(vGs[action.fi] == LitMax);
|
||||
std::vector<lit>::iterator it = vvCs[action.id].begin() + action.idx;
|
||||
assert(vvCs[action.fi].empty());
|
||||
vvCs[action.fi].insert(vvCs[action.fi].begin(), it, vvCs[action.id].end());
|
||||
vvCs[action.id].erase(it, vvCs[action.id].end());
|
||||
assert(vvCs[action.id].size() == action.idx);
|
||||
if(!vGUpdates[action.id] && !vCUpdates[action.id]) {
|
||||
// recompute here only when updates are unlikely to happen
|
||||
if(pBdd->IsConst1(vGs[action.id])) {
|
||||
Assign(vGs[action.fi], pBdd->Const1());
|
||||
} else {
|
||||
lit x = pBdd->Const1();
|
||||
IncRef(x);
|
||||
for(int idx2 = 0; idx2 < action.idx; idx2++) {
|
||||
int fi = pNtk->GetFanin(action.id, idx2);
|
||||
bool c = pNtk->GetCompl(action.id, idx2);
|
||||
Assign(x, pBdd->And(x, pBdd->LitNotCond(vFs[fi], c)));
|
||||
}
|
||||
Assign(vGs[action.fi], pBdd->Or(pBdd->LitNot(x), vGs[action.id]));
|
||||
DecRef(x);
|
||||
}
|
||||
} else {
|
||||
// otherwise mark the node for future update
|
||||
vCUpdates[action.id] = true;
|
||||
}
|
||||
vvCs[action.id].resize(action.idx + 1, LitMax);
|
||||
Assign(vvCs[action.id][action.idx], vGs[action.fi]);
|
||||
vUpdates[action.fi] = false;
|
||||
vGUpdates[action.fi] = false;
|
||||
vCUpdates[action.fi] = false;
|
||||
}
|
||||
break;
|
||||
case SORT_FANINS:
|
||||
if(fInitialized) {
|
||||
std::vector<lit> vCs = vvCs[action.id];
|
||||
vvCs[action.id].clear();
|
||||
for(int index: action.vIndices) {
|
||||
vvCs[action.id].push_back(vCs[index]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case READ:
|
||||
Reset(!action.fNew);
|
||||
break;
|
||||
case SAVE:
|
||||
Save(action.idx);
|
||||
break;
|
||||
|
|
@ -326,6 +359,7 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
void BddMspfAnalyzer<Ntk>::Simulate() {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(nVerbose) {
|
||||
std::cout << "symbolic simulation with BDD" << std::endl;
|
||||
}
|
||||
|
|
@ -340,6 +374,7 @@ namespace rrr {
|
|||
vUpdates[id] = false;
|
||||
}
|
||||
});
|
||||
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -507,6 +542,7 @@ namespace rrr {
|
|||
|
||||
template <typename pNtk>
|
||||
void BddMspfAnalyzer<pNtk>::Mspf(int id, bool fC) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(id != -1) {
|
||||
pNtk->ForEachTfoReverse(id, false, [&](int fo) {
|
||||
MspfNode(fo);
|
||||
|
|
@ -524,10 +560,82 @@ namespace rrr {
|
|||
MspfNode(id);
|
||||
});
|
||||
}
|
||||
durationPf += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Preparation */
|
||||
|
||||
template <typename Ntk>
|
||||
void BddMspfAnalyzer<Ntk>::Reset(bool fReuse) {
|
||||
while(!vBackups.empty()) {
|
||||
PopBack();
|
||||
}
|
||||
DelVec(vFs);
|
||||
DelVec(vGs);
|
||||
DelVecVec(vvCs);
|
||||
fInitialized = false;
|
||||
fUpdate = false;
|
||||
vUpdates.clear();
|
||||
vGUpdates.clear();
|
||||
vCUpdates.clear();
|
||||
vVisits.clear();
|
||||
if(!fReuse) {
|
||||
nNodesOld = 0;
|
||||
if(pBdd) {
|
||||
nNodesAccumulated += pBdd->GetNumTotalCreatedNodes();
|
||||
}
|
||||
delete pBdd;
|
||||
pBdd = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void BddMspfAnalyzer<Ntk>::Initialize() {
|
||||
bool fUseReo = false;
|
||||
if(!pBdd) {
|
||||
NewBdd::Param Par;
|
||||
Par.nObjsMaxLog = 25;
|
||||
Par.nCacheMaxLog = 20;
|
||||
Par.fCountOnes = false;
|
||||
Par.nGbc = 1;
|
||||
Par.nReo = 4000;
|
||||
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
||||
fUseReo = true;
|
||||
}
|
||||
assert(pBdd->GetNumVars() == pNtk->GetNumPis());
|
||||
Allocate();
|
||||
Assign(vFs[0], pBdd->Const0());
|
||||
int idx = 0;
|
||||
pNtk->ForEachPi([&](int id) {
|
||||
Assign(vFs[id], pBdd->IthVar(idx));
|
||||
idx++;
|
||||
});
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vUpdates[id] = true;
|
||||
});
|
||||
Simulate();
|
||||
if(fUseReo) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
pBdd->Reorder();
|
||||
pBdd->TurnOffReo();
|
||||
durationReorder += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
||||
});
|
||||
pNtk->ForEachPo([&](int id) {
|
||||
vvCs[id].resize(1, LitMax);
|
||||
Assign(vvCs[id][0], pBdd->Const0());
|
||||
int fi = pNtk->GetFanin(id, 0);
|
||||
vGUpdates[fi] = true;
|
||||
});
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Save & load */
|
||||
|
||||
template <typename Ntk>
|
||||
|
|
@ -575,113 +683,56 @@ namespace rrr {
|
|||
BddMspfAnalyzer<Ntk>::BddMspfAnalyzer() :
|
||||
pNtk(NULL),
|
||||
nVerbose(0),
|
||||
pBdd(NULL) {
|
||||
fInitialized(false),
|
||||
pBdd(NULL),
|
||||
fUpdate(false) {
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
BddMspfAnalyzer<Ntk>::BddMspfAnalyzer(Parameter const *pPar) :
|
||||
pNtk(NULL),
|
||||
nVerbose(pPar->nAnalyzerVerbose),
|
||||
fInitialized(false),
|
||||
pBdd(NULL),
|
||||
fUpdate(false) {
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void BddMspfAnalyzer<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
||||
// clear
|
||||
while(!vBackups.empty()) {
|
||||
PopBack();
|
||||
}
|
||||
DelVec(vFs);
|
||||
DelVec(vGs);
|
||||
DelVecVec(vvCs);
|
||||
BddMspfAnalyzer<Ntk>::~BddMspfAnalyzer() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void BddMspfAnalyzer<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||
Reset(fReuse);
|
||||
pNtk = pNtk_;
|
||||
fUpdate = false;
|
||||
vUpdates.clear();
|
||||
vGUpdates.clear();
|
||||
vCUpdates.clear();
|
||||
vVisits.clear();
|
||||
// alloc
|
||||
bool fUseReo = false;
|
||||
if(!pBdd || pBdd->GetNumVars() != pNtk->GetNumPis()) {
|
||||
// need to reset manager
|
||||
delete pBdd;
|
||||
NewBdd::Param Par;
|
||||
Par.nObjsMaxLog = 25;
|
||||
Par.nCacheMaxLog = 20;
|
||||
Par.fCountOnes = false;
|
||||
Par.nGbc = 1;
|
||||
Par.nReo = 4000;
|
||||
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);
|
||||
fUseReo = true;
|
||||
} else if(!fSame) {
|
||||
// turning on reordering if network function changed
|
||||
pBdd->TurnOnReo();
|
||||
fUseReo = true;
|
||||
}
|
||||
Allocate();
|
||||
// prepare
|
||||
Assign(vFs[0], pBdd->Const0());
|
||||
int idx = 0;
|
||||
pNtk->ForEachPi([&](int id) {
|
||||
Assign(vFs[id], pBdd->IthVar(idx));
|
||||
idx++;
|
||||
});
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vUpdates[id] = true;
|
||||
});
|
||||
Simulate();
|
||||
if(fUseReo) {
|
||||
pBdd->Reorder();
|
||||
pBdd->TurnOffReo();
|
||||
}
|
||||
pNtk->ForEachInt([&](int id) {
|
||||
vvCs[id].resize(pNtk->GetNumFanins(id), LitMax);
|
||||
});
|
||||
pNtk->ForEachPo([&](int id) {
|
||||
vvCs[id].resize(1, LitMax);
|
||||
Assign(vvCs[id][0], pBdd->Const0());
|
||||
int fi = pNtk->GetFanin(id, 0);
|
||||
vGUpdates[fi] = true;
|
||||
});
|
||||
pNtk->AddCallback(std::bind(&BddMspfAnalyzer<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
BddMspfAnalyzer<Ntk>::~BddMspfAnalyzer() {
|
||||
while(!vBackups.empty()) {
|
||||
PopBack();
|
||||
}
|
||||
DelVec(vFs);
|
||||
DelVec(vGs);
|
||||
DelVecVec(vvCs);
|
||||
if(pBdd) {
|
||||
pBdd->PrintStats();
|
||||
}
|
||||
delete pBdd;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Checks */
|
||||
|
||||
template <typename Ntk>
|
||||
bool BddMspfAnalyzer<Ntk>::CheckRedundancy(int id, int idx) {
|
||||
if(fUpdate) {
|
||||
if(!fInitialized) {
|
||||
Initialize();
|
||||
} else if(fUpdate) {
|
||||
Simulate();
|
||||
fUpdate = false;
|
||||
}
|
||||
Mspf(id);
|
||||
time_point timeStart = GetCurrentTime();
|
||||
bool fRedundant = false;
|
||||
switch(pNtk->GetNodeType(id)) {
|
||||
case AND: {
|
||||
int fi = pNtk->GetFanin(id, idx);
|
||||
bool c = pNtk->GetCompl(id, idx);
|
||||
lit x = pBdd->Or(pBdd->LitNotCond(vFs[fi], c), vvCs[id][idx]);
|
||||
if(pBdd->IsConst1(x)) {
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
||||
}
|
||||
return true;
|
||||
fRedundant = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -689,18 +740,27 @@ namespace rrr {
|
|||
assert(0);
|
||||
}
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
||||
if(fRedundant) {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is redundant" << std::endl;
|
||||
} else {
|
||||
std::cout << "node " << id << " fanin " << (pNtk->GetCompl(id, idx)? "!": "") << pNtk->GetFanin(id, idx) << " index " << idx << " is NOT redundant" << std::endl;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||
return fRedundant;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
bool BddMspfAnalyzer<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||
if(fUpdate) {
|
||||
if(!fInitialized) {
|
||||
Initialize();
|
||||
} else if(fUpdate) {
|
||||
Simulate();
|
||||
fUpdate = false;
|
||||
}
|
||||
Mspf(id, false);
|
||||
time_point timeStart = GetCurrentTime();
|
||||
bool fFeasible = false;
|
||||
switch(pNtk->GetNodeType(id)) {
|
||||
case AND: {
|
||||
lit x = pBdd->Or(pBdd->LitNot(vFs[id]), vGs[id]);
|
||||
|
|
@ -708,9 +768,7 @@ namespace rrr {
|
|||
lit y = pBdd->Or(x, pBdd->LitNotCond(vFs[fi], c));
|
||||
DecRef(x);
|
||||
if(pBdd->IsConst1(y)) {
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
||||
}
|
||||
fFeasible = true;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
|
@ -719,9 +777,49 @@ namespace rrr {
|
|||
assert(0);
|
||||
}
|
||||
if(nVerbose) {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
||||
if(fFeasible) {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is feasible" << std::endl;
|
||||
} else {
|
||||
std::cout << "node " << id << " fanin " << (c? "!": "") << fi << " is NOT feasible" << std::endl;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
durationCheck += Duration(timeStart, GetCurrentTime());
|
||||
return fFeasible;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Summary */
|
||||
|
||||
template <typename Ntk>
|
||||
void BddMspfAnalyzer<Ntk>::ResetSummary() {
|
||||
if(pBdd) {
|
||||
nNodesOld = pBdd->GetNumTotalCreatedNodes();
|
||||
} else {
|
||||
nNodesOld = 0;
|
||||
}
|
||||
nNodesAccumulated = 0;
|
||||
durationSimulation = 0;
|
||||
durationPf = 0;
|
||||
durationCheck = 0;
|
||||
durationReorder = 0;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
summary<int> BddMspfAnalyzer<Ntk>::GetStatsSummary() const {
|
||||
summary<int> v;
|
||||
v.emplace_back("bdd node", pBdd->GetNumTotalCreatedNodes() - nNodesOld + nNodesAccumulated);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
summary<double> BddMspfAnalyzer<Ntk>::GetTimesSummary() const {
|
||||
summary<double> v;
|
||||
v.emplace_back("bdd symbolic simulation", durationSimulation);
|
||||
v.emplace_back("bdd care computation", durationPf);
|
||||
v.emplace_back("bdd check", durationCheck);
|
||||
v.emplace_back("bdd reorder", durationReorder);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ namespace rrr {
|
|||
public:
|
||||
// constructors
|
||||
LevelBasePartitioner(Parameter const *pPar);
|
||||
void UpdateNetwork(Ntk *pNtk);
|
||||
void AssignNetwork(Ntk *pNtk);
|
||||
|
||||
// APIs
|
||||
Ntk *Extract(int iSeed);
|
||||
|
|
@ -214,7 +214,7 @@ namespace rrr {
|
|||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void LevelBasePartitioner<Ntk>::UpdateNetwork(Ntk *pNtk_) {
|
||||
void LevelBasePartitioner<Ntk>::AssignNetwork(Ntk *pNtk_) {
|
||||
pNtk = pNtk_;
|
||||
assert(mSubNtk2Io.empty());
|
||||
assert(sBlocked.empty());
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace rrr {
|
|||
using citr = std::vector<int>::const_iterator;
|
||||
using ritr = std::vector<int>::reverse_iterator;
|
||||
using critr = std::vector<int>::const_reverse_iterator;
|
||||
|
||||
|
||||
// pointer to network
|
||||
Ntk *pNtk;
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ namespace rrr {
|
|||
bool fCompatible;
|
||||
bool fGreedy;
|
||||
seconds nTimeout; // assigned upon Run
|
||||
std::string strVerbosePrefix;
|
||||
std::function<void(std::string)> PrintLine;
|
||||
|
||||
// data
|
||||
Ana ana;
|
||||
|
|
@ -52,6 +52,11 @@ namespace rrr {
|
|||
int target;
|
||||
std::vector<bool> vTfoMarks;
|
||||
|
||||
// statistics
|
||||
struct Stats;
|
||||
std::map<std::string, Stats> stats;
|
||||
Stats statsLocal;
|
||||
|
||||
// print
|
||||
template<typename... Args>
|
||||
void Print(int nVerboseLevel, Args... args);
|
||||
|
|
@ -76,17 +81,18 @@ namespace rrr {
|
|||
bool ReduceFaninsOneRandom(int id, bool fRemoveUnused = false);
|
||||
|
||||
// reduce
|
||||
bool Reduce();
|
||||
bool Reduce(bool fSubRoutine = false);
|
||||
void ReduceRandom();
|
||||
|
||||
// remove redundancy
|
||||
void RemoveRedundancy();
|
||||
bool RemoveRedundancy();
|
||||
void RemoveRedundancyRandom();
|
||||
|
||||
// addition
|
||||
template <typename T>
|
||||
T SingleAdd(int id, T begin, T end);
|
||||
int MultiAdd(int id, std::vector<int> const &vCands, int nMax = 0);
|
||||
void Undo();
|
||||
|
||||
// resub
|
||||
void SingleResub(int id, std::vector<int> const &vCands);
|
||||
|
|
@ -108,25 +114,81 @@ namespace rrr {
|
|||
public:
|
||||
// constructors
|
||||
Optimizer(Parameter const *pPar, std::function<double(Ntk *)> CostFunction);
|
||||
void UpdateNetwork(Ntk *pNtk_, bool fSame = false);
|
||||
void AssignNetwork(Ntk *pNtk_, bool fReuse = false);
|
||||
void SetPrintLine(std::function<void(std::string)> const &PrintLine_);
|
||||
|
||||
// run
|
||||
void Run(int iSeed = 0, seconds nTimeout_ = 0);
|
||||
|
||||
|
||||
// summary
|
||||
void ResetSummary();
|
||||
summary<int> GetStatsSummary() const;
|
||||
summary<double> GetTimesSummary() const;
|
||||
};
|
||||
|
||||
/* {{{ Print */
|
||||
/* {{{ Stats */
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
struct Optimizer<Ntk, Ana>::Stats {
|
||||
int nTriedFis = 0;
|
||||
int nAddedFis = 0;
|
||||
int nTried = 0;
|
||||
int nAdded = 0;
|
||||
int nChanged = 0;
|
||||
int nUps = 0;
|
||||
int nEqs = 0;
|
||||
int nDowns = 0;
|
||||
double durationAdd = 0;
|
||||
double durationReduce = 0;
|
||||
|
||||
void Reset() {
|
||||
nTriedFis = 0;
|
||||
nAddedFis = 0;
|
||||
nTried = 0;
|
||||
nAdded = 0;
|
||||
nChanged = 0;
|
||||
nUps = 0;
|
||||
nEqs = 0;
|
||||
nDowns = 0;
|
||||
durationAdd = 0;
|
||||
durationReduce = 0;
|
||||
}
|
||||
|
||||
Stats& operator+=(Stats const &other) {
|
||||
this->nTriedFis += other.nTriedFis;
|
||||
this->nAddedFis += other.nAddedFis;
|
||||
this->nTried += other.nTried;
|
||||
this->nAdded += other.nAdded;
|
||||
this->nChanged += other.nChanged;
|
||||
this->nUps += other.nUps;
|
||||
this->nEqs += other.nEqs;
|
||||
this->nDowns += other.nDowns;
|
||||
this->durationAdd += other.durationAdd;
|
||||
this->durationReduce += other.durationReduce;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string GetString() const {
|
||||
std::stringstream ss;
|
||||
PrintNext(ss, "tried node/fanin", "=", nTried, "/", nTriedFis, ",", "added node/fanin", "=", nAdded, "/", nAddedFis, ",", "changed", "=", nChanged, ",", "up/eq/dn", "=", nUps, "/", nEqs, "/", nDowns);
|
||||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Print */
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
template <typename... Args>
|
||||
inline void Optimizer<Ntk, Ana>::Print(int nVerboseLevel, Args... args) {
|
||||
if(nVerbose > nVerboseLevel) {
|
||||
std::cout << strVerbosePrefix;
|
||||
std::stringstream ss;
|
||||
for(int i = 0; i < nVerboseLevel; i++) {
|
||||
std::cout << "\t";
|
||||
ss << "\t";
|
||||
}
|
||||
PrintNext(std::cout, args...);
|
||||
std::cout << std::endl;
|
||||
PrintNext(ss, args...);
|
||||
PrintLine(ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -136,13 +198,13 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk, typename Ana>
|
||||
void Optimizer<Ntk, Ana>::ActionCallback(Action const &action) {
|
||||
if(nVerbose > 2) {
|
||||
if(nVerbose > 4) {
|
||||
std::stringstream ss = GetActionDescription(action);
|
||||
std::string str;
|
||||
std::getline(ss, str);
|
||||
Print(2, str);
|
||||
Print(4, str);
|
||||
while(std::getline(ss, str)) {
|
||||
Print(3, str);
|
||||
Print(5, str);
|
||||
}
|
||||
}
|
||||
switch(action.type) {
|
||||
|
|
@ -171,6 +233,9 @@ namespace rrr {
|
|||
break;
|
||||
case SORT_FANINS:
|
||||
break;
|
||||
case READ:
|
||||
target = -1;
|
||||
break;
|
||||
case SAVE:
|
||||
break;
|
||||
case LOAD:
|
||||
|
|
@ -482,7 +547,7 @@ namespace rrr {
|
|||
template <typename Ntk, typename Ana>
|
||||
inline bool Optimizer<Ntk, Ana>::ReduceFanins(int id, bool fRemoveUnused) {
|
||||
assert(pNtk->GetNumFanouts(id) > 0);
|
||||
bool fRemoved = false;
|
||||
bool fReduced = false;
|
||||
for(int idx = 0; idx < pNtk->GetNumFanins(id); idx++) {
|
||||
// skip fanins that were just added
|
||||
if(mapNewFanins.count(id)) {
|
||||
|
|
@ -495,14 +560,14 @@ namespace rrr {
|
|||
if(ana.CheckRedundancy(id, idx)) {
|
||||
int fi = pNtk->GetFanin(id, idx);
|
||||
pNtk->RemoveFanin(id, idx);
|
||||
fRemoved = true;
|
||||
fReduced = true;
|
||||
idx--;
|
||||
if(fRemoveUnused && pNtk->GetNumFanouts(fi) == 0) {
|
||||
pNtk->RemoveUnused(fi, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
return fRemoved;
|
||||
return fReduced;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -542,7 +607,8 @@ namespace rrr {
|
|||
/* {{{ Reduce */
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
bool Optimizer<Ntk, Ana>::Reduce() {
|
||||
bool Optimizer<Ntk, Ana>::Reduce(bool fSubRoutine) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
bool fReduced = false;
|
||||
std::vector<int> vInts = pNtk->GetInts();
|
||||
for(critr it = vInts.rbegin(); it != vInts.rend(); it++) {
|
||||
|
|
@ -558,6 +624,10 @@ namespace rrr {
|
|||
pNtk->Propagate(*it);
|
||||
}
|
||||
}
|
||||
if(!fSubRoutine) {
|
||||
time_point timeEnd = GetCurrentTime();
|
||||
statsLocal.durationReduce += Duration(timeStart, timeEnd);
|
||||
}
|
||||
return fReduced;
|
||||
}
|
||||
|
||||
|
|
@ -588,35 +658,42 @@ namespace rrr {
|
|||
/* {{{ Redundancy removal */
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
void Optimizer<Ntk, Ana>::RemoveRedundancy() {
|
||||
bool Optimizer<Ntk, Ana>::RemoveRedundancy() {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
bool fReduced = false;
|
||||
if(fCompatible) {
|
||||
while(Reduce()) {
|
||||
while(Reduce(true)) {
|
||||
fReduced = true;
|
||||
SortFanins();
|
||||
}
|
||||
return;
|
||||
}
|
||||
std::vector<int> vInts = pNtk->GetInts();
|
||||
for(critr it = vInts.rbegin(); it != vInts.rend();) {
|
||||
if(!pNtk->IsInt(*it)) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
if(pNtk->GetNumFanouts(*it) == 0) {
|
||||
pNtk->RemoveUnused(*it);
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
SortFanins(*it);
|
||||
bool fReduced = ReduceFanins(*it);
|
||||
if(pNtk->GetNumFanins(*it) <= 1) {
|
||||
pNtk->Propagate(*it);
|
||||
}
|
||||
if(fReduced) {
|
||||
it = vInts.rbegin();
|
||||
} else {
|
||||
it++;
|
||||
} else {
|
||||
std::vector<int> vInts = pNtk->GetInts();
|
||||
for(critr it = vInts.rbegin(); it != vInts.rend();) {
|
||||
if(!pNtk->IsInt(*it)) {
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
if(pNtk->GetNumFanouts(*it) == 0) {
|
||||
pNtk->RemoveUnused(*it);
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
SortFanins(*it);
|
||||
bool fReduced_ = ReduceFanins(*it);
|
||||
fReduced |= fReduced_;
|
||||
if(pNtk->GetNumFanins(*it) <= 1) {
|
||||
pNtk->Propagate(*it);
|
||||
}
|
||||
if(fReduced_) {
|
||||
it = vInts.rbegin();
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
time_point timeEnd = GetCurrentTime();
|
||||
statsLocal.durationReduce += Duration(timeStart, timeEnd);
|
||||
return fReduced;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -656,6 +733,7 @@ namespace rrr {
|
|||
template <typename Ntk, typename Ana>
|
||||
template <typename T>
|
||||
T Optimizer<Ntk, Ana>::SingleAdd(int id, T begin, T end) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
MarkTfo(id);
|
||||
pNtk->ForEachFanin(id, [&](int fi) {
|
||||
vTfoMarks[fi] = true;
|
||||
|
|
@ -668,10 +746,13 @@ namespace rrr {
|
|||
if(vTfoMarks[*it]) {
|
||||
continue;
|
||||
}
|
||||
statsLocal.nTriedFis++;
|
||||
if(ana.CheckFeasibility(id, *it, false)) {
|
||||
pNtk->AddFanin(id, *it, false);
|
||||
statsLocal.nAddedFis++;
|
||||
} else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, *it, true)) {
|
||||
pNtk->AddFanin(id, *it, true);
|
||||
statsLocal.nAddedFis++;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -681,16 +762,19 @@ namespace rrr {
|
|||
pNtk->ForEachFanin(id, [&](int fi) {
|
||||
vTfoMarks[fi] = false;
|
||||
});
|
||||
time_point timeEnd = GetCurrentTime();
|
||||
statsLocal.durationAdd += Duration(timeStart, timeEnd);
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
int Optimizer<Ntk, Ana>::MultiAdd(int id, std::vector<int> const &vCands, int nMax) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
MarkTfo(id);
|
||||
pNtk->ForEachFanin(id, [&](int fi) {
|
||||
vTfoMarks[fi] = true;
|
||||
});
|
||||
int nAdded = 0;
|
||||
int nAddedFis_ = 0;
|
||||
for(int cand: vCands) {
|
||||
if(!pNtk->IsInt(cand) && !pNtk->IsPi(cand)) {
|
||||
continue;
|
||||
|
|
@ -698,23 +782,39 @@ namespace rrr {
|
|||
if(vTfoMarks[cand]) {
|
||||
continue;
|
||||
}
|
||||
statsLocal.nTriedFis++;
|
||||
if(ana.CheckFeasibility(id, cand, false)) {
|
||||
pNtk->AddFanin(id, cand, false);
|
||||
statsLocal.nAddedFis++;
|
||||
} else if(pNtk->UseComplementedEdges() && ana.CheckFeasibility(id, cand, true)) {
|
||||
pNtk->AddFanin(id, cand, true);
|
||||
statsLocal.nAddedFis++;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
mapNewFanins[id].insert(cand);
|
||||
nAdded++;
|
||||
if(nAdded == nMax) {
|
||||
nAddedFis_++;
|
||||
if(nAddedFis_ == nMax) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pNtk->ForEachFanin(id, [&](int fi) {
|
||||
vTfoMarks[fi] = false;
|
||||
});
|
||||
return nAdded;
|
||||
time_point timeEnd = GetCurrentTime();
|
||||
statsLocal.durationAdd += Duration(timeStart, timeEnd);
|
||||
return nAddedFis_;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
void Optimizer<Ntk, Ana>::Undo() {
|
||||
for(auto const &entry: mapNewFanins) {
|
||||
int id = entry.first;
|
||||
for(int fi: entry.second) {
|
||||
int idx = pNtk->FindFanin(id, fi);
|
||||
pNtk->RemoveFanin(id, idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -731,11 +831,12 @@ namespace rrr {
|
|||
pNtk->TrivialCollapse(id);
|
||||
// save if wanted
|
||||
int slot = -2;
|
||||
if(fGreedy) {
|
||||
if(fGreedy || fCompatible) {
|
||||
slot = pNtk->Save();
|
||||
}
|
||||
double dCost = CostFunction(pNtk);
|
||||
// main loop
|
||||
double cost = CostFunction(pNtk);
|
||||
bool fTried = false, fAdded = false;
|
||||
for(citr it = vCands.begin(); it != vCands.end(); it++) {
|
||||
if(Timeout()) {
|
||||
break;
|
||||
|
|
@ -743,25 +844,44 @@ namespace rrr {
|
|||
if(!pNtk->IsInt(id)) {
|
||||
break;
|
||||
}
|
||||
fTried = true;
|
||||
it = SingleAdd<citr>(id, it, vCands.end());
|
||||
if(it == vCands.end()) {
|
||||
break;
|
||||
}
|
||||
Print(1, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), "):", "cost", "=", dCost);
|
||||
RemoveRedundancy();
|
||||
mapNewFanins.clear();
|
||||
double dNewCost = CostFunction(pNtk);
|
||||
Print(2, "cost:", dCost, "->", dNewCost);
|
||||
if(fGreedy) {
|
||||
if(dNewCost <= dCost) {
|
||||
pNtk->Save(slot);
|
||||
dCost = dNewCost;
|
||||
fAdded = true;
|
||||
Print(2, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), ")", ":", "cost", "=", cost);
|
||||
if(RemoveRedundancy()) {
|
||||
double costNew = CostFunction(pNtk);
|
||||
// stats
|
||||
statsLocal.nChanged++;
|
||||
if(costNew < cost) {
|
||||
statsLocal.nDowns++;
|
||||
} else if (costNew == cost) {
|
||||
statsLocal.nEqs++;
|
||||
} else {
|
||||
pNtk->Load(slot);
|
||||
statsLocal.nUps++;
|
||||
}
|
||||
// greedy
|
||||
if(fGreedy) {
|
||||
if(costNew <= cost) {
|
||||
pNtk->Save(slot);
|
||||
cost = costNew;
|
||||
} else {
|
||||
pNtk->Load(slot);
|
||||
}
|
||||
} else {
|
||||
cost = costNew;
|
||||
}
|
||||
} else {
|
||||
dCost = dNewCost;
|
||||
// assuming addition only always increases cost
|
||||
if(fCompatible) {
|
||||
pNtk->Load(slot);
|
||||
} else {
|
||||
Undo();
|
||||
}
|
||||
}
|
||||
mapNewFanins.clear();
|
||||
}
|
||||
if(pNtk->IsInt(id)) {
|
||||
pNtk->TrivialDecompose(id);
|
||||
|
|
@ -770,9 +890,15 @@ namespace rrr {
|
|||
RemoveRedundancy();
|
||||
}
|
||||
}
|
||||
if(fGreedy) {
|
||||
if(fGreedy || fCompatible) {
|
||||
pNtk->PopBack();
|
||||
}
|
||||
if(fTried) {
|
||||
statsLocal.nTried++;
|
||||
}
|
||||
if(fAdded) {
|
||||
statsLocal.nAdded++;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
|
|
@ -781,24 +907,43 @@ namespace rrr {
|
|||
// let us assume the node is not trivially redundant for now
|
||||
assert(pNtk->GetNumFanouts(id) != 0);
|
||||
assert(pNtk->GetNumFanins(id) > 1);
|
||||
statsLocal.nTried++;
|
||||
// save if wanted
|
||||
int slot = -2;
|
||||
if(fGreedy) {
|
||||
if(fGreedy || fCompatible) {
|
||||
slot = pNtk->Save();
|
||||
}
|
||||
double dCost = CostFunction(pNtk);
|
||||
// collapse
|
||||
pNtk->TrivialCollapse(id);
|
||||
// resub
|
||||
MultiAdd(id, vCands, nMax);
|
||||
RemoveRedundancy();
|
||||
mapNewFanins.clear();
|
||||
// TODO: we could quit here if nothing has been removed
|
||||
RemoveRedundancy();
|
||||
double dNewCost = CostFunction(pNtk);
|
||||
Print(1, "cost:", dCost, "->", dNewCost);
|
||||
if(fGreedy && dNewCost > dCost) {
|
||||
pNtk->Load(slot);
|
||||
double cost = CostFunction(pNtk);
|
||||
if(MultiAdd(id, vCands, nMax)) {
|
||||
statsLocal.nAdded++;
|
||||
if(RemoveRedundancy()) {
|
||||
mapNewFanins.clear();
|
||||
RemoveRedundancy();
|
||||
double costNew = CostFunction(pNtk);
|
||||
// stats
|
||||
statsLocal.nChanged++;
|
||||
if(costNew < cost) {
|
||||
statsLocal.nDowns++;
|
||||
} else if (costNew == cost) {
|
||||
statsLocal.nEqs++;
|
||||
} else {
|
||||
statsLocal.nUps++;
|
||||
}
|
||||
// greedy
|
||||
if(fGreedy && costNew > cost) {
|
||||
pNtk->Load(slot);
|
||||
}
|
||||
} else {
|
||||
if(fCompatible) {
|
||||
pNtk->Load(slot);
|
||||
} else {
|
||||
Undo();
|
||||
}
|
||||
mapNewFanins.clear();
|
||||
}
|
||||
}
|
||||
if(pNtk->IsInt(id)) {
|
||||
pNtk->TrivialDecompose(id);
|
||||
|
|
@ -807,7 +952,7 @@ namespace rrr {
|
|||
RemoveRedundancy();
|
||||
}
|
||||
}
|
||||
if(fGreedy) {
|
||||
if(fGreedy || fCompatible) {
|
||||
pNtk->PopBack();
|
||||
}
|
||||
}
|
||||
|
|
@ -824,57 +969,77 @@ namespace rrr {
|
|||
// let us assume the node is not trivially redundant for now
|
||||
assert(pNtk->GetNumFanouts(id) != 0);
|
||||
assert(pNtk->GetNumFanins(id) > 1);
|
||||
// save before trivial collapse
|
||||
int slot0 = pNtk->Save();
|
||||
Print(2, "method", "=", "single");
|
||||
// collapse
|
||||
pNtk->TrivialCollapse(id);
|
||||
// save after trivial collapse
|
||||
// save
|
||||
int slot = pNtk->Save();
|
||||
double dCost = CostFunction(pNtk);
|
||||
// remember fanins
|
||||
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(2, "extended fanins:", sFanins);
|
||||
Print(3, "extended fanins", ":", sFanins);
|
||||
// main loop
|
||||
bool fChanged = false;
|
||||
double cost = CostFunction(pNtk);
|
||||
bool fTried = false, fAdded = false;
|
||||
for(citr it = vCands.begin(); it != vCands.end(); it++) {
|
||||
if(Timeout()) {
|
||||
break;
|
||||
}
|
||||
assert(pNtk->IsInt(id));
|
||||
fTried = true;
|
||||
it = SingleAdd<citr>(id, it, vCands.end());
|
||||
if(it == vCands.end()) {
|
||||
break;
|
||||
}
|
||||
Print(1, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), "):", "cost", "=", dCost);
|
||||
RemoveRedundancy();
|
||||
mapNewFanins.clear();
|
||||
double dNewCost = CostFunction(pNtk);
|
||||
Print(2, "cost:", dCost, "->", dNewCost);
|
||||
if(dNewCost <= dCost) {
|
||||
bool fChanged = false;
|
||||
if(dNewCost < dCost || !pNtk->IsInt(id)) {
|
||||
fChanged = true;
|
||||
} else {
|
||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(2, "new extended fanins:", sNewFanins);
|
||||
if(sFanins != sNewFanins) {
|
||||
fAdded = true;
|
||||
Print(3, "cand", *it, "(", int_distance(vCands.begin(), it) + 1, "/", int_size(vCands), ")", ":", "cost", "=", cost);
|
||||
if(RemoveRedundancy()) {
|
||||
mapNewFanins.clear();
|
||||
double costNew = CostFunction(pNtk);
|
||||
if(costNew <= cost) {
|
||||
fChanged = false;
|
||||
if(costNew < cost || !pNtk->IsInt(id)) {
|
||||
fChanged = true;
|
||||
} else {
|
||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(3, "new extended fanins", ":", sNewFanins);
|
||||
if(sFanins != sNewFanins) {
|
||||
fChanged = true;
|
||||
}
|
||||
}
|
||||
if(fChanged) {
|
||||
statsLocal.nChanged++;
|
||||
if(costNew < cost) {
|
||||
statsLocal.nDowns++;
|
||||
} else if (costNew == cost) {
|
||||
statsLocal.nEqs++;
|
||||
} else {
|
||||
statsLocal.nUps++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(fChanged) {
|
||||
if(pNtk->IsInt(id)) {
|
||||
pNtk->TrivialDecompose(id);
|
||||
}
|
||||
pNtk->PopBack(); // slot
|
||||
pNtk->PopBack(); // slot0
|
||||
return true;
|
||||
pNtk->Load(slot);
|
||||
} else {
|
||||
if(fCompatible) {
|
||||
pNtk->Load(slot);
|
||||
} else {
|
||||
Undo();
|
||||
}
|
||||
mapNewFanins.clear();
|
||||
}
|
||||
pNtk->Load(slot);
|
||||
}
|
||||
pNtk->PopBack(); // slot
|
||||
pNtk->Load(slot0);
|
||||
pNtk->PopBack(); // slot0
|
||||
return false;
|
||||
if(pNtk->IsInt(id)) {
|
||||
pNtk->TrivialDecompose(id);
|
||||
}
|
||||
pNtk->PopBack();
|
||||
if(fTried) {
|
||||
statsLocal.nTried++;
|
||||
}
|
||||
if(fAdded) {
|
||||
statsLocal.nAdded++;
|
||||
}
|
||||
return fChanged;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
|
|
@ -885,44 +1050,59 @@ namespace rrr {
|
|||
// let us assume the node is not trivially redundant for now
|
||||
assert(pNtk->GetNumFanouts(id) != 0);
|
||||
assert(pNtk->GetNumFanins(id) > 1);
|
||||
Print(2, "method", "=", "multi");
|
||||
statsLocal.nTried++;
|
||||
// save
|
||||
int slot = pNtk->Save();
|
||||
double dCost = CostFunction(pNtk);
|
||||
// remember fanins
|
||||
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(2, "extended fanins:", sFanins);
|
||||
Print(3, "extended fanins", ":", sFanins);
|
||||
// collapse
|
||||
pNtk->TrivialCollapse(id);
|
||||
// resub
|
||||
MultiAdd(id, vCands, nMax);
|
||||
RemoveRedundancy();
|
||||
mapNewFanins.clear();
|
||||
// TODO: we could quit here if nothing has been removed
|
||||
RemoveRedundancy();
|
||||
double dNewCost = CostFunction(pNtk);
|
||||
Print(1, "cost:", dCost, "->", dNewCost);
|
||||
if(!fGreedy || dNewCost <= dCost) {
|
||||
bool fChanged = false;
|
||||
if(dNewCost < dCost || !pNtk->IsInt(id)) {
|
||||
fChanged = true;
|
||||
bool fChanged = false;
|
||||
double cost = CostFunction(pNtk);
|
||||
if(MultiAdd(id, vCands, nMax)) {
|
||||
statsLocal.nAdded++;
|
||||
if(RemoveRedundancy()) {
|
||||
mapNewFanins.clear();
|
||||
RemoveRedundancy();
|
||||
double costNew = CostFunction(pNtk);
|
||||
if(!fGreedy || costNew <= cost) {
|
||||
fChanged = false;
|
||||
if(costNew < cost || !pNtk->IsInt(id)) {
|
||||
fChanged = true;
|
||||
} else {
|
||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(3, "new extended fanins", ":", sNewFanins);
|
||||
if(sFanins != sNewFanins) {
|
||||
fChanged = true;
|
||||
}
|
||||
}
|
||||
if(fChanged) {
|
||||
statsLocal.nChanged++;
|
||||
if(costNew < cost) {
|
||||
statsLocal.nDowns++;
|
||||
} else if (costNew == cost) {
|
||||
statsLocal.nEqs++;
|
||||
} else {
|
||||
statsLocal.nUps++;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(2, "new extended fanins:", sNewFanins);
|
||||
if(sFanins != sNewFanins) {
|
||||
fChanged = true;
|
||||
}
|
||||
}
|
||||
if(fChanged) {
|
||||
if(pNtk->IsInt(id)) {
|
||||
pNtk->TrivialDecompose(id);
|
||||
}
|
||||
pNtk->PopBack();
|
||||
return true;
|
||||
mapNewFanins.clear();
|
||||
}
|
||||
}
|
||||
pNtk->Load(slot);
|
||||
if(fChanged) {
|
||||
if(pNtk->IsInt(id)) {
|
||||
pNtk->TrivialDecompose(id);
|
||||
}
|
||||
} else {
|
||||
pNtk->Load(slot);
|
||||
}
|
||||
pNtk->PopBack();
|
||||
return false;
|
||||
return fChanged;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -948,7 +1128,7 @@ namespace rrr {
|
|||
}
|
||||
}
|
||||
// add while remembering extended fanins
|
||||
Print(1, "targets:", vTargets);
|
||||
Print(2, "targets", ":", vTargets);
|
||||
std::vector<std::set<int>> vsFanins;
|
||||
for(int id: vTargets) {
|
||||
// get candidates
|
||||
|
|
@ -961,7 +1141,7 @@ namespace rrr {
|
|||
std::shuffle(vCands.begin(), vCands.end(), rng);
|
||||
// remember fanins
|
||||
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
|
||||
Print(2, "extended fanins:", sFanins);
|
||||
Print(3, "extended fanins", ":", sFanins);
|
||||
vsFanins.push_back(std::move(sFanins));
|
||||
// add
|
||||
MultiAdd(id, vCands, nMax);
|
||||
|
|
@ -972,7 +1152,7 @@ namespace rrr {
|
|||
// TODO: we could quit here if nothing has been removed
|
||||
RemoveRedundancy();
|
||||
double dNewCost = CostFunction(pNtk);
|
||||
Print(1, "cost:", dCost, "->", dNewCost);
|
||||
Print(2, "cost =", dCost, "->", dNewCost);
|
||||
if(!fGreedy || dNewCost <= dCost) {
|
||||
bool fChanged = false;
|
||||
if(dNewCost < dCost) {
|
||||
|
|
@ -986,7 +1166,7 @@ namespace rrr {
|
|||
}
|
||||
for(int i = 0; !fChanged && i < int_size(vTargets); i++) {
|
||||
std::set<int> sNewFanins = pNtk->GetExtendedFanins(vTargets[i]);
|
||||
Print(2, "new extended fanins:", sNewFanins);
|
||||
Print(3, "new extended fanins", ":", sNewFanins);
|
||||
if(vsFanins[i] != sNewFanins) {
|
||||
fChanged = true;
|
||||
}
|
||||
|
|
@ -1021,7 +1201,7 @@ namespace rrr {
|
|||
if(!pNtk->IsInt(*it)) {
|
||||
continue;
|
||||
}
|
||||
Print(0, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk));
|
||||
Print(1, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), ")", ":", "cost", "=", CostFunction(pNtk));
|
||||
func(*it);
|
||||
}
|
||||
}
|
||||
|
|
@ -1037,7 +1217,7 @@ namespace rrr {
|
|||
if(!pNtk->IsInt(*it)) {
|
||||
continue;
|
||||
}
|
||||
Print(0, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk));
|
||||
Print(1, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), ")", ":", "cost", "=", CostFunction(pNtk));
|
||||
if(func(*it)) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -1048,10 +1228,10 @@ namespace rrr {
|
|||
void Optimizer<Ntk, Ana>::ApplyCombinationRandomlyStop(int k, std::function<bool(std::vector<int> const &)> const &func) {
|
||||
std::vector<int> vInts = pNtk->GetInts();
|
||||
std::shuffle(vInts.begin(), vInts.end(), rng); // order is decided here, so it's not truely exhaustive
|
||||
int nTried = 0;
|
||||
int nTried_ = 0;
|
||||
int nCombs = k * (k - 1) / 2;
|
||||
ForEachCombinationStop(int_size(vInts), k, [&](std::vector<int> const &vIdxs) {
|
||||
Print(0, "comb", vIdxs, "(", ++nTried, "/", nCombs, ")");
|
||||
Print(1, "comb", vIdxs, "(", ++nTried_, "/", nCombs, ")");
|
||||
assert(int_size(vIdxs) == k);
|
||||
if(Timeout()) {
|
||||
return true;
|
||||
|
|
@ -1078,7 +1258,7 @@ namespace rrr {
|
|||
}
|
||||
std::vector<int> vIdxs(sIdxs.begin(), sIdxs.end());
|
||||
std::shuffle(vIdxs.begin(), vIdxs.end(), rng);
|
||||
Print(0, "comb", vIdxs, "(", i + 1, "/", nSamples, ")");
|
||||
Print(1, "comb", vIdxs, "(", i + 1, "/", nSamples, ")");
|
||||
std::vector<int> vTargets(k);
|
||||
for(int i = 0; i < k; i++) {
|
||||
vTargets[i] = vInts[vIdxs[i]];
|
||||
|
|
@ -1109,11 +1289,16 @@ namespace rrr {
|
|||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
void Optimizer<Ntk, Ana>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
||||
void Optimizer<Ntk, Ana>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||
pNtk = pNtk_;
|
||||
target = -1;
|
||||
pNtk->AddCallback(std::bind(&Optimizer<Ntk, Ana>::ActionCallback, this, std::placeholders::_1));
|
||||
ana.UpdateNetwork(pNtk, fSame);
|
||||
ana.AssignNetwork(pNtk, fReuse);
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
void Optimizer<Ntk, Ana>::SetPrintLine(std::function<void(std::string)> const &PrintLine_) {
|
||||
PrintLine = PrintLine_;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -1127,13 +1312,14 @@ namespace rrr {
|
|||
vRandCosts.clear();
|
||||
if(nSortTypeOriginal < 0) {
|
||||
nSortType = rng() % 18;
|
||||
Print(0, "sorttype =", nSortType);
|
||||
Print(0, "fanin cost function =", nSortType);
|
||||
}
|
||||
nTimeout = nTimeout_;
|
||||
start = GetCurrentTime();
|
||||
switch(nFlow) {
|
||||
case 0:
|
||||
RemoveRedundancy();
|
||||
statsLocal.Reset();
|
||||
ApplyReverseTopologically([&](int id) {
|
||||
std::vector<int> vCands;
|
||||
if(nDistance) {
|
||||
|
|
@ -1143,9 +1329,12 @@ namespace rrr {
|
|||
}
|
||||
SingleResub(id, vCands);
|
||||
});
|
||||
stats["single"] += statsLocal;
|
||||
Print(0, statsLocal.GetString());
|
||||
break;
|
||||
case 1:
|
||||
RemoveRedundancy();
|
||||
statsLocal.Reset();
|
||||
ApplyReverseTopologically([&](int id) {
|
||||
std::vector<int> vCands;
|
||||
if(nDistance) {
|
||||
|
|
@ -1155,11 +1344,14 @@ namespace rrr {
|
|||
}
|
||||
MultiResub(id, vCands);
|
||||
});
|
||||
stats["multi"] += statsLocal;
|
||||
Print(0, statsLocal.GetString());
|
||||
break;
|
||||
case 2: {
|
||||
RemoveRedundancy();
|
||||
double dCost = CostFunction(pNtk);
|
||||
while(true) {
|
||||
statsLocal.Reset();
|
||||
ApplyReverseTopologically([&](int id) {
|
||||
std::vector<int> vCands;
|
||||
if(nDistance) {
|
||||
|
|
@ -1169,6 +1361,9 @@ namespace rrr {
|
|||
}
|
||||
SingleResub(id, vCands);
|
||||
});
|
||||
stats["single"] += statsLocal;
|
||||
Print(0, "single", ":", "cost", "=", CostFunction(pNtk), ",", statsLocal.GetString());
|
||||
statsLocal.Reset();
|
||||
ApplyReverseTopologically([&](int id) {
|
||||
std::vector<int> vCands;
|
||||
if(nDistance) {
|
||||
|
|
@ -1179,6 +1374,8 @@ namespace rrr {
|
|||
}
|
||||
MultiResub(id, vCands);
|
||||
});
|
||||
stats["multi"] += statsLocal;
|
||||
Print(0, "multi ", ":", "cost", "=", CostFunction(pNtk), ",", statsLocal.GetString());
|
||||
double dNewCost = CostFunction(pNtk);
|
||||
if(dNewCost < dCost) {
|
||||
dCost = dNewCost;
|
||||
|
|
@ -1195,17 +1392,27 @@ namespace rrr {
|
|||
vCands = pNtk->GetPisInts();
|
||||
std::shuffle(vCands.begin(), vCands.end(), rng);
|
||||
}
|
||||
Stats statsSingle, statsMulti;
|
||||
ApplyRandomlyStop([&](int id) {
|
||||
statsLocal.Reset();
|
||||
if(nDistance) {
|
||||
vCands = pNtk->GetNeighbors(id, true, nDistance);
|
||||
std::shuffle(vCands.begin(), vCands.end(), rng);
|
||||
}
|
||||
bool fChanged;
|
||||
if(rng() & 1) {
|
||||
return SingleResubStop(id, vCands);
|
||||
fChanged = SingleResubStop(id, vCands);
|
||||
statsSingle += statsLocal;
|
||||
} else {
|
||||
return MultiResubStop(id, vCands);
|
||||
fChanged = MultiResubStop(id, vCands);
|
||||
statsMulti += statsLocal;
|
||||
}
|
||||
return fChanged;
|
||||
});
|
||||
stats["single"] += statsSingle;
|
||||
stats["multi"] += statsMulti;
|
||||
Print(0, "single", ":", statsSingle.GetString());
|
||||
Print(0, "multi ", ":", statsMulti.GetString());
|
||||
break;
|
||||
}
|
||||
case 4: {
|
||||
|
|
@ -1221,6 +1428,46 @@ namespace rrr {
|
|||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Summary */
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
void Optimizer<Ntk, Ana>::ResetSummary() {
|
||||
stats.clear();
|
||||
ana.ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
summary<int> Optimizer<Ntk, Ana>::GetStatsSummary() const {
|
||||
summary<int> v;
|
||||
for(auto const &entry: stats) {
|
||||
v.emplace_back("opt " + entry.first + " tried node", entry.second.nTried);
|
||||
v.emplace_back("opt " + entry.first + " tried fanin", entry.second.nTriedFis);
|
||||
v.emplace_back("opt " + entry.first + " added node", entry.second.nAdded);
|
||||
v.emplace_back("opt " + entry.first + " added fanin", entry.second.nAddedFis);
|
||||
v.emplace_back("opt " + entry.first + " changed", entry.second.nChanged);
|
||||
v.emplace_back("opt " + entry.first + " up", entry.second.nUps);
|
||||
v.emplace_back("opt " + entry.first + " eq", entry.second.nEqs);
|
||||
v.emplace_back("opt " + entry.first + " dn", entry.second.nDowns);
|
||||
}
|
||||
summary<int> v2 = ana.GetStatsSummary();
|
||||
v.insert(v.end(), v2.begin(), v2.end());
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Ana>
|
||||
summary<double> Optimizer<Ntk, Ana>::GetTimesSummary() const {
|
||||
summary<double> v;
|
||||
for(auto const &entry: stats) {
|
||||
v.emplace_back("opt " + entry.first + " add", entry.second.durationAdd);
|
||||
v.emplace_back("opt " + entry.first + " reduce", entry.second.durationReduce);
|
||||
}
|
||||
summary<double> v2 = ana.GetTimesSummary();
|
||||
v.insert(v.end(), v2.begin(), v2.end());
|
||||
return v;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ namespace rrr {
|
|||
int iSeed = 0;
|
||||
int nWords = 10;
|
||||
int nTimeout = 0;
|
||||
int nSchedulerVerbose = 1;
|
||||
int nSchedulerVerbose = 0;
|
||||
int nPartitionerVerbose = 0;
|
||||
int nOptimizerVerbose = 0;
|
||||
int nAnalyzerVerbose = 0;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace rrr {
|
|||
public:
|
||||
// constructors
|
||||
Partitioner(Parameter const *pPar);
|
||||
void UpdateNetwork(Ntk *pNtk);
|
||||
void AssignNetwork(Ntk *pNtk);
|
||||
|
||||
// APIs
|
||||
Ntk *Extract(int iSeed);
|
||||
|
|
@ -270,7 +270,7 @@ namespace rrr {
|
|||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void Partitioner<Ntk>::UpdateNetwork(Ntk *pNtk_) {
|
||||
void Partitioner<Ntk>::AssignNetwork(Ntk *pNtk_) {
|
||||
pNtk = pNtk_;
|
||||
assert(mSubNtk2Io.empty());
|
||||
assert(sBlocked.empty());
|
||||
|
|
|
|||
|
|
@ -28,10 +28,12 @@ namespace rrr {
|
|||
std::vector<VarValue> vValues; // values in satisfied problem
|
||||
bool fUpdate;
|
||||
|
||||
// statistics
|
||||
// stats
|
||||
int nCalls;
|
||||
int nSats;
|
||||
int nUnsats;
|
||||
double durationRedundancy;
|
||||
double durationFeasibility;
|
||||
|
||||
// callback
|
||||
void ActionCallback(Action const &action);
|
||||
|
|
@ -45,7 +47,7 @@ namespace rrr {
|
|||
// constructors
|
||||
SatSolver(Parameter const *pPar);
|
||||
~SatSolver();
|
||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
||||
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||
|
||||
// checks
|
||||
SatResult CheckRedundancy(int id, int idx);
|
||||
|
|
@ -53,6 +55,11 @@ namespace rrr {
|
|||
|
||||
// cex
|
||||
std::vector<VarValue> GetCex();
|
||||
|
||||
// stats
|
||||
void ResetSummary();
|
||||
summary<int> GetStatsSummary() const;
|
||||
summary<double> GetTimesSummary() const;
|
||||
};
|
||||
|
||||
/* {{{ Callback */
|
||||
|
|
@ -88,6 +95,11 @@ namespace rrr {
|
|||
break;
|
||||
case SORT_FANINS:
|
||||
break;
|
||||
case READ:
|
||||
status = false;
|
||||
target = -1;
|
||||
fUpdate = false;
|
||||
break;
|
||||
case SAVE:
|
||||
break;
|
||||
case LOAD:
|
||||
|
|
@ -259,25 +271,23 @@ namespace rrr {
|
|||
pSat(sat_solver_new()),
|
||||
status(false),
|
||||
target(-1),
|
||||
fUpdate(false),
|
||||
nCalls(0),
|
||||
nSats(0),
|
||||
nUnsats(0) {
|
||||
fUpdate(false) {
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
SatSolver<Ntk>::~SatSolver() {
|
||||
sat_solver_delete(pSat);
|
||||
std::cout << "SAT solver stats: calls = " << nCalls << " (SAT = " << nSats << ", UNSAT = " << nUnsats << ", UNDET = " << nCalls - nSats - nUnsats << ")" << std::endl;
|
||||
//std::cout << "SAT solver stats: calls = " << nCalls << " (SAT = " << nSats << ", UNSAT = " << nUnsats << ", UNDET = " << nCalls - nSats - nUnsats << ")" << std::endl;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void SatSolver<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
||||
(void)fSame;
|
||||
pNtk = pNtk_;
|
||||
void SatSolver<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||
(void)fReuse;
|
||||
status = false;
|
||||
target = -1;
|
||||
fUpdate = false;
|
||||
pNtk = pNtk_;
|
||||
pNtk->AddCallback(std::bind(&SatSolver<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
|
|
@ -287,11 +297,13 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
SatResult SatSolver<Ntk>::CheckRedundancy(int id, int idx) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
SetTarget(id);
|
||||
if(!status) {
|
||||
if(nVerbose) {
|
||||
std::cout << "trivially UNSATISFIABLE" << std::endl;
|
||||
}
|
||||
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||
return UNSAT;
|
||||
}
|
||||
vLits.clear();
|
||||
|
|
@ -319,12 +331,14 @@ namespace rrr {
|
|||
std::cout << "UNSATISFIABLE" << std::endl;
|
||||
}
|
||||
nUnsats++;
|
||||
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||
return UNSAT;
|
||||
}
|
||||
if(res == l_Undef) {
|
||||
if(nVerbose) {
|
||||
std::cout << "UNDETERMINED" << std::endl;
|
||||
}
|
||||
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||
return UNDET;
|
||||
}
|
||||
assert(res == l_True);
|
||||
|
|
@ -353,16 +367,19 @@ namespace rrr {
|
|||
assert((vValues[fi] == TEMP_TRUE) ^ (idx == idx2) ^ c);
|
||||
vValues[fi] = DecideVarValue(vValues[fi]);
|
||||
});
|
||||
durationRedundancy += Duration(timeStart, GetCurrentTime());
|
||||
return SAT;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
SatResult SatSolver<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
SetTarget(id);
|
||||
if(!status) {
|
||||
if(nVerbose) {
|
||||
std::cout << "trivially UNSATISFIABLE" << std::endl;
|
||||
}
|
||||
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||
return UNSAT;
|
||||
}
|
||||
vLits.clear();
|
||||
|
|
@ -385,12 +402,14 @@ namespace rrr {
|
|||
std::cout << "UNSATISFIABLE" << std::endl;
|
||||
}
|
||||
nUnsats++;
|
||||
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||
return UNSAT;
|
||||
}
|
||||
if(res == l_Undef) {
|
||||
if(nVerbose) {
|
||||
std::cout << "UNDETERMINED" << std::endl;
|
||||
}
|
||||
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||
return UNDET;
|
||||
}
|
||||
assert(res == l_True);
|
||||
|
|
@ -419,6 +438,7 @@ namespace rrr {
|
|||
vValues[id] = DecideVarValue(vValues[id]);
|
||||
assert((vValues[fi] == TEMP_TRUE) ^ !c);
|
||||
vValues[fi] = DecideVarValue(vValues[fi]);
|
||||
durationFeasibility += Duration(timeStart, GetCurrentTime());
|
||||
return SAT;
|
||||
}
|
||||
|
||||
|
|
@ -537,6 +557,36 @@ namespace rrr {
|
|||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Stats */
|
||||
|
||||
template <typename Ntk>
|
||||
void SatSolver<Ntk>::ResetSummary() {
|
||||
nCalls = 0;
|
||||
nSats = 0;
|
||||
nUnsats = 0;
|
||||
durationRedundancy = 0;
|
||||
durationFeasibility = 0;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
summary<int> SatSolver<Ntk>::GetStatsSummary() const {
|
||||
summary<int> v;
|
||||
v.emplace_back("sat call", nCalls);
|
||||
v.emplace_back("sat satisfiable", nSats);
|
||||
v.emplace_back("sat unsatisfiable", nUnsats);
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
summary<double> SatSolver<Ntk>::GetTimesSummary() const {
|
||||
summary<double> v;
|
||||
v.emplace_back("sat redundancy", durationRedundancy);
|
||||
v.emplace_back("sat feasibility", durationFeasibility);
|
||||
return v;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_CXX_HEADER_END
|
||||
|
|
|
|||
|
|
@ -46,10 +46,14 @@ namespace rrr {
|
|||
// data
|
||||
int nCreatedJobs;
|
||||
int nFinishedJobs;
|
||||
time_point start;
|
||||
time_point timeStart;
|
||||
Par par;
|
||||
std::queue<Job *> qPendingJobs;
|
||||
Opt *pOpt; // used only in case of single thread execution
|
||||
std::vector<std::string> vStatsSummaryKeys;
|
||||
std::map<std::string, int> mStatsSummary;
|
||||
std::vector<std::string> vTimesSummaryKeys;
|
||||
std::map<std::string, double> mTimesSummary;
|
||||
#ifdef ABC_USE_PTHREADS
|
||||
bool fTerminate;
|
||||
std::vector<std::thread> vThreads;
|
||||
|
|
@ -57,21 +61,27 @@ namespace rrr {
|
|||
std::mutex mutexAbc;
|
||||
std::mutex mutexPendingJobs;
|
||||
std::mutex mutexFinishedJobs;
|
||||
std::mutex mutexPrint;
|
||||
std::condition_variable condPendingJobs;
|
||||
std::condition_variable condFinishedJobs;
|
||||
#endif
|
||||
|
||||
// print
|
||||
template <typename... Args>
|
||||
void Print(int nVerboseLevel, std::string prefix, Args... args);
|
||||
|
||||
// time
|
||||
seconds GetRemainingTime() const;
|
||||
double GetElapsedTime() const;
|
||||
|
||||
// abc
|
||||
void CallAbc(Ntk *pNtk_, std::string Command);
|
||||
|
||||
// run jobs
|
||||
void RunJob(Opt &opt, Job const *pJob);
|
||||
void RunJob(Opt &opt, Job *pJob);
|
||||
|
||||
// manage jobs
|
||||
void CreateJob(Ntk *pNtk_, int iSeed_);
|
||||
Job *CreateJob(Ntk *pNtk_, int iSeed_, double cost);
|
||||
void OnJobEnd(std::function<void(Job *pJob)> const &func);
|
||||
|
||||
// thread
|
||||
|
|
@ -79,6 +89,10 @@ namespace rrr {
|
|||
void Thread(Parameter const *pPar);
|
||||
#endif
|
||||
|
||||
// summary
|
||||
template <typename T>
|
||||
void AddToSummary(std::vector<std::string> &keys, std::map<std::string, T> &m, summary<T> const &result) const;
|
||||
|
||||
public:
|
||||
// constructors
|
||||
Scheduler(Ntk *pNtk, Parameter const *pPar);
|
||||
|
|
@ -96,12 +110,21 @@ namespace rrr {
|
|||
int id;
|
||||
Ntk *pNtk;
|
||||
int iSeed;
|
||||
double costInitial;
|
||||
std::string prefix;
|
||||
double duration;
|
||||
summary<int> stats;
|
||||
summary<double> times;
|
||||
|
||||
// constructor
|
||||
Job(int id, Ntk *pNtk, int iSeed) :
|
||||
Job(int id, Ntk *pNtk, int iSeed, double cost) :
|
||||
id(id),
|
||||
pNtk(pNtk),
|
||||
iSeed(iSeed) {
|
||||
iSeed(iSeed),
|
||||
costInitial(cost) {
|
||||
std::stringstream ss;
|
||||
PrintNext(ss, "job", id, ":");
|
||||
prefix = ss.str() + " ";
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -115,21 +138,53 @@ namespace rrr {
|
|||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Print */
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
template<typename... Args>
|
||||
inline void Scheduler<Ntk, Opt, Par>::Print(int nVerboseLevel, std::string prefix, Args... args) {
|
||||
if(nVerbose <= nVerboseLevel) {
|
||||
return;
|
||||
}
|
||||
#ifdef ABC_USE_PTHREADS
|
||||
if(fMultiThreading) {
|
||||
{
|
||||
std::unique_lock<std::mutex> l(mutexPrint);
|
||||
std::cout << prefix;
|
||||
PrintNext(std::cout, args...);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
std::cout << prefix;
|
||||
PrintNext(std::cout, args...);
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Time */
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
seconds Scheduler<Ntk, Opt, Par>::GetRemainingTime() const {
|
||||
inline seconds Scheduler<Ntk, Opt, Par>::GetRemainingTime() const {
|
||||
if(nTimeout == 0) {
|
||||
return 0;
|
||||
}
|
||||
time_point current = GetCurrentTime();
|
||||
seconds nRemainingTime = nTimeout - DurationInSeconds(start, current);
|
||||
time_point timeCurrent = GetCurrentTime();
|
||||
seconds nRemainingTime = nTimeout - DurationInSeconds(timeStart, timeCurrent);
|
||||
if(nRemainingTime == 0) { // avoid glitch
|
||||
return -1;
|
||||
}
|
||||
return nRemainingTime;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
inline double Scheduler<Ntk, Opt, Par>::GetElapsedTime() const {
|
||||
time_point timeCurrent = GetCurrentTime();
|
||||
return Duration(timeStart, timeCurrent);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Abc */
|
||||
|
|
@ -153,8 +208,12 @@ namespace rrr {
|
|||
/* {{{ Run jobs */
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
void Scheduler<Ntk, Opt, Par>::RunJob(Opt &opt, Job const *pJob) {
|
||||
opt.UpdateNetwork(pJob->pNtk);
|
||||
void Scheduler<Ntk, Opt, Par>::RunJob(Opt &opt, Job *pJob) {
|
||||
time_point timeStartLocal = GetCurrentTime();
|
||||
opt.AssignNetwork(pJob->pNtk, !fPartitioning); // reuse backend if restarting
|
||||
opt.SetPrintLine([&](std::string str) {
|
||||
Print(-1, pJob->prefix, str);
|
||||
});
|
||||
// start flow
|
||||
switch(nFlow) {
|
||||
case 0:
|
||||
|
|
@ -162,23 +221,17 @@ namespace rrr {
|
|||
break;
|
||||
case 1: { // transtoch
|
||||
std::mt19937 rng(pJob->iSeed);
|
||||
double dCost = CostFunction(pJob->pNtk);
|
||||
double dBestCost = dCost;
|
||||
double cost = pJob->costInitial;
|
||||
double costBest = cost;
|
||||
Ntk best(*(pJob->pNtk));
|
||||
if(nVerbose) {
|
||||
std::cout << "start: cost = " << dCost << std::endl;
|
||||
}
|
||||
for(int i = 0; i < 10; i++) {
|
||||
if(GetRemainingTime() < 0) {
|
||||
break;
|
||||
}
|
||||
if(i != 0) {
|
||||
CallAbc(pJob->pNtk, "&if -K 6; &mfs; &st");
|
||||
dCost = CostFunction(pJob->pNtk);
|
||||
opt.UpdateNetwork(pJob->pNtk, true);
|
||||
if(nVerbose) {
|
||||
std::cout << "hop " << std::setw(3) << i << ": cost = " << dCost << std::endl;
|
||||
}
|
||||
cost = CostFunction(pJob->pNtk);
|
||||
Print(1, pJob->prefix, "hop", i, ":", "cost", "=", cost);
|
||||
}
|
||||
for(int j = 0; true; j++) {
|
||||
if(GetRemainingTime() < 0) {
|
||||
|
|
@ -186,37 +239,28 @@ namespace rrr {
|
|||
}
|
||||
opt.Run(rng(), GetRemainingTime());
|
||||
CallAbc(pJob->pNtk, "&dc2");
|
||||
double dNewCost = CostFunction(pJob->pNtk);
|
||||
if(nVerbose) {
|
||||
std::cout << "\tite " << std::setw(3) << j << ": cost = " << dNewCost << std::endl;
|
||||
}
|
||||
if(dNewCost < dCost) {
|
||||
dCost = dNewCost;
|
||||
opt.UpdateNetwork(pJob->pNtk, true);
|
||||
double costNew = CostFunction(pJob->pNtk);
|
||||
Print(1, pJob->prefix, "ite", j, ":", "cost", "=", costNew);
|
||||
if(costNew < cost) {
|
||||
cost = costNew;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dCost < dBestCost) {
|
||||
dBestCost = dCost;
|
||||
if(cost < costBest) {
|
||||
costBest = cost;
|
||||
best = *(pJob->pNtk);
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
*(pJob->pNtk) = best;
|
||||
if(nVerbose) {
|
||||
std::cout << "end: cost = " << dBestCost << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: { // deep
|
||||
std::mt19937 rng(pJob->iSeed);
|
||||
int n = 0;
|
||||
double dCost = CostFunction(pJob->pNtk);
|
||||
double cost = pJob->costInitial;
|
||||
Ntk best(*(pJob->pNtk));
|
||||
if(nVerbose) {
|
||||
std::cout << "start: cost = " << dCost << std::endl;
|
||||
}
|
||||
for(int i = 0; i < 1000000; i++) {
|
||||
if(GetRemainingTime() < 0) {
|
||||
break;
|
||||
|
|
@ -246,38 +290,30 @@ namespace rrr {
|
|||
Command += "; &fx; &st";
|
||||
Command += pComp;
|
||||
CallAbc(pJob->pNtk, Command);
|
||||
if(nVerbose) {
|
||||
std::cout << "ite " << std::setw(6) << i << ": cost = " << CostFunction(pJob->pNtk) << std::endl;
|
||||
}
|
||||
Print(1, pJob->prefix, "ite", i, ":", "cost", "=", CostFunction(pJob->pNtk));
|
||||
// rrr
|
||||
for(int j = 0; j < n; j++) {
|
||||
if(GetRemainingTime() < 0) {
|
||||
break;
|
||||
}
|
||||
opt.UpdateNetwork(pJob->pNtk, true);
|
||||
opt.Run(rng(), GetRemainingTime());
|
||||
if(rng() & 1) {
|
||||
CallAbc(pJob->pNtk, "&dc2");
|
||||
} else {
|
||||
CallAbc(pJob->pNtk, std::string("&put; ") + pCompress2rs + "; &get");
|
||||
}
|
||||
if(nVerbose) {
|
||||
std::cout << "\trrr " << std::setw(6) << j << ": cost = " << CostFunction(pJob->pNtk) << std::endl;
|
||||
}
|
||||
Print(1, pJob->prefix, "rrr", j, ":", "cost", "=", CostFunction(pJob->pNtk));
|
||||
}
|
||||
// eval
|
||||
double dNewCost = CostFunction(pJob->pNtk);
|
||||
if(dNewCost < dCost) {
|
||||
dCost = dNewCost;
|
||||
double costNew = CostFunction(pJob->pNtk);
|
||||
if(costNew < cost) {
|
||||
cost = costNew;
|
||||
best = *(pJob->pNtk);
|
||||
} else {
|
||||
n++;
|
||||
}
|
||||
}
|
||||
*(pJob->pNtk) = best;
|
||||
if(nVerbose) {
|
||||
std::cout << "end: cost = " << dCost << std::endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
|
|
@ -287,6 +323,11 @@ namespace rrr {
|
|||
default:
|
||||
assert(0);
|
||||
}
|
||||
time_point timeEndLocal = GetCurrentTime();
|
||||
pJob->duration = Duration(timeStartLocal, timeEndLocal);
|
||||
pJob->stats = opt.GetStatsSummary();
|
||||
pJob->times = opt.GetTimesSummary();
|
||||
opt.ResetSummary();
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -294,8 +335,8 @@ namespace rrr {
|
|||
/* {{{ Manage jobs */
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
void Scheduler<Ntk, Opt, Par>::CreateJob(Ntk *pNtk_, int iSeed_) {
|
||||
Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_);
|
||||
typename Scheduler<Ntk, Opt, Par>::Job *Scheduler<Ntk, Opt, Par>::CreateJob(Ntk *pNtk_, int iSeed_, double cost) {
|
||||
Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_, cost);
|
||||
#ifdef ABC_USE_PTHREADS
|
||||
if(fMultiThreading) {
|
||||
{
|
||||
|
|
@ -303,10 +344,11 @@ namespace rrr {
|
|||
qPendingJobs.push(pJob);
|
||||
condPendingJobs.notify_one();
|
||||
}
|
||||
return;
|
||||
return pJob;
|
||||
}
|
||||
#endif
|
||||
qPendingJobs.push(pJob);
|
||||
return pJob;
|
||||
}
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
|
|
@ -324,6 +366,8 @@ namespace rrr {
|
|||
}
|
||||
assert(pJob != NULL);
|
||||
func(pJob);
|
||||
AddToSummary(vStatsSummaryKeys, mStatsSummary, pJob->stats);
|
||||
AddToSummary(vTimesSummaryKeys, mTimesSummary, pJob->times);
|
||||
delete pJob;
|
||||
nFinishedJobs++;
|
||||
return;
|
||||
|
|
@ -335,6 +379,8 @@ namespace rrr {
|
|||
qPendingJobs.pop();
|
||||
RunJob(*pOpt, pJob);
|
||||
func(pJob);
|
||||
AddToSummary(vStatsSummaryKeys, mStatsSummary, pJob->stats);
|
||||
AddToSummary(vTimesSummaryKeys, mTimesSummary, pJob->times);
|
||||
delete pJob;
|
||||
nFinishedJobs++;
|
||||
}
|
||||
|
|
@ -374,6 +420,28 @@ namespace rrr {
|
|||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Summary */
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
template <typename T>
|
||||
void Scheduler<Ntk, Opt, Par>::AddToSummary(std::vector<std::string> &keys, std::map<std::string, T> &m, summary<T> const &result) const {
|
||||
std::vector<std::string>::iterator it = keys.begin();
|
||||
for(auto const &entry: result) {
|
||||
if(m.count(entry.first)) {
|
||||
m[entry.first] += entry.second;
|
||||
it = std::find(it, keys.end(), entry.first);
|
||||
assert(it != keys.end());
|
||||
it++;
|
||||
} else {
|
||||
m[entry.first] = entry.second;
|
||||
it = keys.insert(it, entry.first);
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Constructors */
|
||||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
|
|
@ -439,74 +507,90 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk, typename Opt, typename Par>
|
||||
void Scheduler<Ntk, Opt, Par>::Run() {
|
||||
start = GetCurrentTime();
|
||||
timeStart = GetCurrentTime();
|
||||
double costStart = CostFunction(pNtk);
|
||||
if(fPartitioning) {
|
||||
fDeterministic = false; // it is deterministic anyways as we wait until all jobs finish each round
|
||||
pNtk->Sweep();
|
||||
par.UpdateNetwork(pNtk);
|
||||
par.AssignNetwork(pNtk);
|
||||
while(nCreatedJobs < nJobs) {
|
||||
assert(nParallelPartitions > 0);
|
||||
if(nCreatedJobs < nFinishedJobs + nParallelPartitions) {
|
||||
Ntk *pSubNtk = par.Extract(iSeed + nCreatedJobs);
|
||||
if(pSubNtk) {
|
||||
CreateJob(pSubNtk, iSeed + nCreatedJobs);
|
||||
std::cout << "job " << nCreatedJobs - 1 << " created (size = " << pSubNtk->GetNumInts() << ")" << std::endl;
|
||||
Job *pJob = CreateJob(pSubNtk, iSeed + nCreatedJobs, CostFunction(pSubNtk));
|
||||
Print(1, pJob->prefix, "created ", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", pJob->costInitial);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if(nCreatedJobs == nFinishedJobs) {
|
||||
std::cout << "failed to partition" << std::endl;
|
||||
PrintWarning("failed to partition");
|
||||
break;
|
||||
}
|
||||
while(nFinishedJobs < nCreatedJobs) {
|
||||
OnJobEnd([&](Job *pJob) {
|
||||
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
|
||||
double cost = CostFunction(pJob->pNtk);
|
||||
Print(1, pJob->prefix, "finished", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost);
|
||||
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||
par.Insert(pJob->pNtk);
|
||||
});
|
||||
}
|
||||
if(fOptOnInsert) {
|
||||
time_point timeStartLocal = GetCurrentTime();
|
||||
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
|
||||
par.UpdateNetwork(pNtk);
|
||||
time_point timeEndLocal = GetCurrentTime();
|
||||
par.AssignNetwork(pNtk);
|
||||
double cost = CostFunction(pNtk);
|
||||
Print(0, "", "c2rs; dc2", ":", std::string(34, ' '), "node", "=", pNtk->GetNumInts(), ",", "level", "=", pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - costStart) / costStart, "%", ")", ",", "duration", "=", Duration(timeStartLocal, timeEndLocal), "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||
}
|
||||
}
|
||||
while(nFinishedJobs < nCreatedJobs) {
|
||||
OnJobEnd([&](Job *pJob) {
|
||||
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
|
||||
double cost = CostFunction(pJob->pNtk);
|
||||
Print(1, pJob->prefix, "finished", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", CostFunction(pJob->pNtk));
|
||||
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "i/o", "=", pJob->pNtk->GetNumPis(), "/", pJob->pNtk->GetNumPos(), ",", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||
par.Insert(pJob->pNtk);
|
||||
});
|
||||
}
|
||||
if(fOptOnInsert) {
|
||||
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
|
||||
par.UpdateNetwork(pNtk);
|
||||
par.AssignNetwork(pNtk);
|
||||
}
|
||||
} else if(nJobs > 1) {
|
||||
double dCost = CostFunction(pNtk);
|
||||
double costBest = costStart;
|
||||
for(int i = 0; i < nJobs; i++) {
|
||||
Ntk *pCopy = new Ntk(*pNtk);
|
||||
CreateJob(pCopy, iSeed + i);
|
||||
CreateJob(pCopy, iSeed + i, costBest);
|
||||
}
|
||||
for(int i = 0; i < nJobs; i++) {
|
||||
OnJobEnd([&](Job *pJob) {
|
||||
double dNewCost = CostFunction(pJob->pNtk);
|
||||
if(nVerbose) {
|
||||
std::cout << "run " << pJob->id << ": cost = " << dNewCost << std::endl;
|
||||
}
|
||||
if(dNewCost < dCost) {
|
||||
dCost = dNewCost;
|
||||
double cost = CostFunction(pJob->pNtk);
|
||||
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||
if(cost < costBest) {
|
||||
costBest = cost;
|
||||
*pNtk = *(pJob->pNtk);
|
||||
}
|
||||
delete pJob->pNtk;
|
||||
});
|
||||
}
|
||||
} else {
|
||||
CreateJob(pNtk, iSeed);
|
||||
OnJobEnd([&](Job *pJob) { (void)pJob; });
|
||||
CreateJob(pNtk, iSeed, costStart);
|
||||
OnJobEnd([&](Job *pJob) {
|
||||
double cost = CostFunction(pJob->pNtk);
|
||||
Print(0, "", "job", pJob->id, "(", nFinishedJobs + 1, "/", nJobs, ")", ":", "node", "=", pJob->pNtk->GetNumInts(), ",", "level", "=", pJob->pNtk->GetNumLevels(), ",", "cost", "=", cost, "(", 100 * (cost - pJob->costInitial) / pJob->costInitial, "%", ")", ",", "duration", "=", pJob->duration, "s", ",", "elapsed", "=", GetElapsedTime(), "s");
|
||||
});
|
||||
}
|
||||
time_point end = GetCurrentTime();
|
||||
double elapsed_seconds = Duration(start, end);
|
||||
if(nVerbose) {
|
||||
std::cout << "elapsed: " << std::fixed << std::setprecision(3) << elapsed_seconds << "s" << std::endl;
|
||||
double cost = CostFunction(pNtk);
|
||||
double duration = GetElapsedTime();
|
||||
Print(0, "\n", "stats summary", ":");
|
||||
for(std::string key: vStatsSummaryKeys) {
|
||||
Print(0, "\t", SW{30, true}, key, ":", SW{10}, mStatsSummary[key]);
|
||||
}
|
||||
Print(0, "", "runtime summary", ":");
|
||||
for(std::string key: vTimesSummaryKeys) {
|
||||
Print(0, "\t", SW{30, true}, key, ":", mTimesSummary[key], "s", "(", 100 * mTimesSummary[key] / duration, "%", ")");
|
||||
}
|
||||
Print(0, "", "end", ":", "cost", "=", cost, "(", 100 * (cost - costStart) / costStart, "%", ")", ",", "time", "=", duration, "s");
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ namespace rrr {
|
|||
int nWords;
|
||||
|
||||
// data
|
||||
bool fGenerated;
|
||||
bool fInitialized;
|
||||
int target; // node for which the careset has been computed
|
||||
std::vector<word> vValues;
|
||||
std::vector<word> vValues2; // simulation with an inverter
|
||||
|
|
@ -46,9 +48,14 @@ namespace rrr {
|
|||
// backups
|
||||
std::vector<Simulator> vBackups;
|
||||
|
||||
// statistics
|
||||
int nAdds;
|
||||
int nResets;
|
||||
// stats
|
||||
int nCex;
|
||||
int nDiscarded;
|
||||
int nPackedCountOld;
|
||||
std::vector<int> vPackedCount;
|
||||
std::vector<int> vPackedCountEvicted;
|
||||
double durationSimulation;
|
||||
double durationCare;
|
||||
|
||||
// vector computations
|
||||
void Clear(int n, itr x) const;
|
||||
|
|
@ -77,6 +84,9 @@ namespace rrr {
|
|||
// careset computation
|
||||
void ComputeCare(int id);
|
||||
|
||||
// preparation
|
||||
void Initialize();
|
||||
|
||||
// save & load
|
||||
void Save(int slot);
|
||||
void Load(int slot);
|
||||
|
|
@ -85,8 +95,7 @@ namespace rrr {
|
|||
// constructors
|
||||
Simulator();
|
||||
Simulator(Parameter const *pPar);
|
||||
~Simulator();
|
||||
void UpdateNetwork(Ntk *pNtk_, bool fSame);
|
||||
void AssignNetwork(Ntk *pNtk_, bool fReuse);
|
||||
|
||||
// checks
|
||||
bool CheckRedundancy(int id, int idx);
|
||||
|
|
@ -94,6 +103,11 @@ namespace rrr {
|
|||
|
||||
// cex
|
||||
void AddCex(std::vector<VarValue> const &vCex);
|
||||
|
||||
// summary
|
||||
void ResetSummary();
|
||||
summary<int> GetStatsSummary() const;
|
||||
summary<double> GetTimesSummary() const;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -195,53 +209,71 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::ActionCallback(Action const &action) {
|
||||
if(target == -1) {
|
||||
return;
|
||||
}
|
||||
switch(action.type) {
|
||||
case REMOVE_FANIN:
|
||||
if(action.id == target) {
|
||||
fUpdate = true;
|
||||
} else {
|
||||
sUpdates.insert(action.id);
|
||||
assert(fInitialized);
|
||||
if(target != -1) {
|
||||
if(action.id == target) {
|
||||
fUpdate = true;
|
||||
} else {
|
||||
sUpdates.insert(action.id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case REMOVE_UNUSED:
|
||||
break;
|
||||
case REMOVE_BUFFER:
|
||||
case REMOVE_CONST:
|
||||
if(action.id == target) {
|
||||
if(fUpdate) {
|
||||
for(int fo: action.vFanouts) {
|
||||
sUpdates.insert(fo);
|
||||
}
|
||||
fUpdate = false;
|
||||
}
|
||||
target = -1;
|
||||
} else {
|
||||
if(sUpdates.count(action.id)) {
|
||||
sUpdates.erase(action.id);
|
||||
for(int fo: action.vFanouts) {
|
||||
sUpdates.insert(fo);
|
||||
if(fInitialized) {
|
||||
if(target != -1) {
|
||||
if(action.id == target) {
|
||||
if(fUpdate) {
|
||||
for(int fo: action.vFanouts) {
|
||||
sUpdates.insert(fo);
|
||||
}
|
||||
fUpdate = false;
|
||||
}
|
||||
target = -1;
|
||||
} else {
|
||||
if(sUpdates.count(action.id)) {
|
||||
sUpdates.erase(action.id);
|
||||
for(int fo: action.vFanouts) {
|
||||
sUpdates.insert(fo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ADD_FANIN:
|
||||
if(action.id == target) {
|
||||
fUpdate = true;
|
||||
} else {
|
||||
sUpdates.insert(action.id);
|
||||
assert(fInitialized);
|
||||
if(target != -1) {
|
||||
if(action.id == target) {
|
||||
fUpdate = true;
|
||||
} else {
|
||||
sUpdates.insert(action.id);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TRIVIAL_COLLAPSE:
|
||||
break;
|
||||
case TRIVIAL_DECOMPOSE:
|
||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||
SimulateNode(vValues, action.fi);
|
||||
if(fInitialized) {
|
||||
if(target != -1) {
|
||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||
SimulateNode(vValues, action.fi);
|
||||
// time of this simulation is not measured for simplicity sake
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SORT_FANINS:
|
||||
break;
|
||||
case READ:
|
||||
fInitialized = false;
|
||||
if(action.fNew) {
|
||||
fGenerated = false;
|
||||
}
|
||||
break;
|
||||
case SAVE:
|
||||
Save(action.idx);
|
||||
break;
|
||||
|
|
@ -345,6 +377,7 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::Simulate() {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(nVerbose) {
|
||||
std::cout << "simulating" << std::endl;
|
||||
}
|
||||
|
|
@ -356,10 +389,12 @@ namespace rrr {
|
|||
std::cout << std::endl;
|
||||
}
|
||||
});
|
||||
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::Resimulate() {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(nVerbose) {
|
||||
std::cout << "resimulating" << std::endl;
|
||||
}
|
||||
|
|
@ -382,10 +417,12 @@ namespace rrr {
|
|||
}
|
||||
});
|
||||
*/
|
||||
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::SimulateOneWord(int offset) {
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(nVerbose) {
|
||||
std::cout << "simulating word " << offset << std::endl;
|
||||
}
|
||||
|
|
@ -397,6 +434,7 @@ namespace rrr {
|
|||
std::cout << std::endl;
|
||||
}
|
||||
});
|
||||
durationSimulation += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -440,6 +478,7 @@ namespace rrr {
|
|||
sUpdates.clear();
|
||||
}
|
||||
target = id;
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(nVerbose) {
|
||||
std::cout << "computing careset of " << target << std::endl;
|
||||
}
|
||||
|
|
@ -450,6 +489,7 @@ namespace rrr {
|
|||
Print(nWords, care.begin());
|
||||
std::cout << std::endl;
|
||||
}
|
||||
durationCare += Duration(timeStart, GetCurrentTime());
|
||||
return;
|
||||
}
|
||||
vValues2 = vValues;
|
||||
|
|
@ -484,10 +524,40 @@ namespace rrr {
|
|||
Print(nWords, care.begin());
|
||||
std::cout << std::endl;
|
||||
}
|
||||
durationCare += Duration(timeStart, GetCurrentTime());
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Preparation */
|
||||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::Initialize() {
|
||||
if(!fGenerated) {
|
||||
// TODO: reset nWords to default here maybe, if such a mechanism that changes nWords has been implemneted
|
||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||
iPivot = 0;
|
||||
vAssignedStimuli.clear();
|
||||
vAssignedStimuli.resize(nWords * pNtk->GetNumPis());
|
||||
for(int count: vPackedCount) {
|
||||
if(count) {
|
||||
vPackedCountEvicted.push_back(count);
|
||||
}
|
||||
}
|
||||
vPackedCount.clear();
|
||||
vPackedCount.resize(nWords * 64);
|
||||
GenerateRandomStimuli();
|
||||
fGenerated = true;
|
||||
} else {
|
||||
// use same nWords as we are reusing patterns even if nWords has changed
|
||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||
}
|
||||
Simulate();
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Save & load */
|
||||
|
||||
template <typename Ntk>
|
||||
|
|
@ -517,6 +587,12 @@ namespace rrr {
|
|||
vBackups[slot].iPivot = iPivot;
|
||||
vBackups[slot].vAssignedStimuli = vAssignedStimuli;
|
||||
target = vBackups[slot].target; // assigned to -1 when careset needs updating
|
||||
if(!fKeepStimula) {
|
||||
vBackups[slot].nCex = nCex;
|
||||
vBackups[slot].nPackedCountOld = nPackedCountOld;
|
||||
vBackups[slot].vPackedCount = vPackedCount;
|
||||
vBackups[slot].vPackedCountEvicted = vPackedCountEvicted;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
|
|
@ -532,6 +608,11 @@ namespace rrr {
|
|||
care = vBackups[slot].care;
|
||||
iPivot = vBackups[slot].iPivot;
|
||||
vAssignedStimuli = vBackups[slot].vAssignedStimuli;
|
||||
nDiscarded += nCex - vBackups[slot].nCex;
|
||||
nCex = vBackups[slot].nCex;
|
||||
nPackedCountOld = vBackups[slot].nPackedCountOld;
|
||||
vPackedCount = vBackups[slot].vPackedCount;
|
||||
vPackedCountEvicted = vBackups[slot].vPackedCountEvicted;
|
||||
tmp.resize(nWords);
|
||||
} else {
|
||||
std::vector<int> vOffsets;
|
||||
|
|
@ -567,7 +648,7 @@ namespace rrr {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
// when nWords has changed
|
||||
// TODO: when nWords has changed
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
|
@ -582,11 +663,12 @@ namespace rrr {
|
|||
pNtk(NULL),
|
||||
nVerbose(0),
|
||||
nWords(0),
|
||||
fGenerated(false),
|
||||
fInitialized(false),
|
||||
target(-1),
|
||||
iPivot(0),
|
||||
fUpdate(false),
|
||||
nAdds(0),
|
||||
nResets(0) {
|
||||
fUpdate(false) {
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
|
|
@ -594,38 +676,27 @@ namespace rrr {
|
|||
pNtk(NULL),
|
||||
nVerbose(pPar->nSimulatorVerbose),
|
||||
nWords(pPar->nWords),
|
||||
fGenerated(false),
|
||||
fInitialized(false),
|
||||
target(-1),
|
||||
iPivot(0),
|
||||
fUpdate(false),
|
||||
nAdds(0),
|
||||
nResets(0) {
|
||||
fUpdate(false) {
|
||||
care.resize(nWords);
|
||||
tmp.resize(nWords);
|
||||
ResetSummary();
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
Simulator<Ntk>::~Simulator() {
|
||||
if(pNtk) {
|
||||
std::cout << "simulator stats: added CEXs = " << nAdds << ", resets = " << nResets << std::endl;
|
||||
void Simulator<Ntk>::AssignNetwork(Ntk *pNtk_, bool fReuse) {
|
||||
if(!fReuse) {
|
||||
fGenerated = false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::UpdateNetwork(Ntk *pNtk_, bool fSame) {
|
||||
pNtk = pNtk_;
|
||||
pNtk->AddCallback(std::bind(&Simulator<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||
// TODO: what if nWords has changed? shall we reset it to default?
|
||||
vValues.resize(nWords * pNtk->GetNumNodes());
|
||||
fInitialized = false;
|
||||
target = -1;
|
||||
fUpdate = false;
|
||||
sUpdates.clear();
|
||||
if(!fSame) { // reset stimuli if network function changed
|
||||
iPivot = 0;
|
||||
vAssignedStimuli.clear();
|
||||
vAssignedStimuli.resize(nWords * pNtk->GetNumPis());
|
||||
GenerateRandomStimuli();
|
||||
}
|
||||
Simulate();
|
||||
pNtk = pNtk_;
|
||||
pNtk->AddCallback(std::bind(&Simulator<Ntk>::ActionCallback, this, std::placeholders::_1));
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
|
@ -634,6 +705,9 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
bool Simulator<Ntk>::CheckRedundancy(int id, int idx) {
|
||||
if(!fInitialized) {
|
||||
Initialize();
|
||||
}
|
||||
ComputeCare(id);
|
||||
switch(pNtk->GetNodeType(id)) {
|
||||
case AND: {
|
||||
|
|
@ -671,6 +745,9 @@ namespace rrr {
|
|||
|
||||
template <typename Ntk>
|
||||
bool Simulator<Ntk>::CheckFeasibility(int id, int fi, bool c) {
|
||||
if(!fInitialized) {
|
||||
Initialize();
|
||||
}
|
||||
ComputeCare(id);
|
||||
switch(pNtk->GetNodeType(id)) {
|
||||
case AND: {
|
||||
|
|
@ -768,6 +845,7 @@ namespace rrr {
|
|||
if(nVerbose) {
|
||||
std::cout << "fusing into stimulus word " << iWord << " bit " << iBit << std::endl;
|
||||
}
|
||||
vPackedCount[iWord * 64 + iBit]++;
|
||||
} else {
|
||||
// no bits are compatible, so reset at pivot
|
||||
iWord = iPivot / 64;
|
||||
|
|
@ -775,6 +853,11 @@ namespace rrr {
|
|||
if(nVerbose) {
|
||||
std::cout << "resetting stimulus word " << iWord << " bit " << iBit << std::endl;
|
||||
}
|
||||
if(vPackedCount[iWord * 64 + iBit]) {
|
||||
// this can be zero only when stats has been reset
|
||||
vPackedCountEvicted.push_back(vPackedCount[iWord * 64 + iBit]);
|
||||
}
|
||||
vPackedCount[iWord * 64 + iBit] = 1;
|
||||
word mask = 1ull << iBit;
|
||||
for(int idx = 0; idx < pNtk->GetNumPis(); idx++) {
|
||||
vAssignedStimuli[idx * nWords + iWord] &= ~mask;
|
||||
|
|
@ -783,7 +866,6 @@ namespace rrr {
|
|||
if(iPivot == 64 * nWords) {
|
||||
iPivot = 0;
|
||||
}
|
||||
nResets++;
|
||||
}
|
||||
// update stimulus
|
||||
for(int idx: vCarePiIdxs) {
|
||||
|
|
@ -808,6 +890,7 @@ namespace rrr {
|
|||
// simulate
|
||||
SimulateOneWord(iWord);
|
||||
// recompute care with new stimulus
|
||||
time_point timeStart = GetCurrentTime();
|
||||
if(target != -1 && !pNtk->IsPoDriver(target)) {
|
||||
if(nVerbose) {
|
||||
std::cout << "recomputing careset of " << target << std::endl;
|
||||
|
|
@ -838,10 +921,56 @@ namespace rrr {
|
|||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
nAdds++;
|
||||
durationCare += Duration(timeStart, GetCurrentTime());
|
||||
nCex++;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Summary */
|
||||
|
||||
template <typename Ntk>
|
||||
void Simulator<Ntk>::ResetSummary() {
|
||||
nCex = 0;
|
||||
nDiscarded = 0;
|
||||
nPackedCountOld = 0;
|
||||
for(int count: vPackedCount) {
|
||||
if(count) {
|
||||
nPackedCountOld++;
|
||||
}
|
||||
}
|
||||
vPackedCountEvicted.clear();
|
||||
durationSimulation = 0;
|
||||
durationCare = 0;
|
||||
};
|
||||
|
||||
template <typename Ntk>
|
||||
summary<int> Simulator<Ntk>::GetStatsSummary() const {
|
||||
summary<int> v;
|
||||
v.emplace_back("sim cex", nCex);
|
||||
if(!fKeepStimula) {
|
||||
v.emplace_back("sim discarded cex", nDiscarded);
|
||||
}
|
||||
int nPackedCount = vPackedCountEvicted.size() - nPackedCountOld;
|
||||
for(int count: vPackedCount) {
|
||||
if(count) {
|
||||
nPackedCount++;
|
||||
}
|
||||
}
|
||||
v.emplace_back("sim packed pattern", nPackedCount);
|
||||
v.emplace_back("sim evicted pattern", vPackedCountEvicted.size());
|
||||
return v;
|
||||
};
|
||||
|
||||
template <typename Ntk>
|
||||
summary<double> Simulator<Ntk>::GetTimesSummary() const {
|
||||
summary<double> v;
|
||||
v.emplace_back("sim simulation", durationSimulation);
|
||||
v.emplace_back("sim care computation", durationCare);
|
||||
return v;
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ namespace rrr {
|
|||
TRIVIAL_COLLAPSE,
|
||||
TRIVIAL_DECOMPOSE,
|
||||
SORT_FANINS,
|
||||
READ,
|
||||
SAVE,
|
||||
LOAD,
|
||||
POP_BACK,
|
||||
|
|
@ -51,6 +52,7 @@ namespace rrr {
|
|||
int idx = -1;
|
||||
int fi = -1;
|
||||
bool c = false;
|
||||
bool fNew = false;
|
||||
std::vector<int> vFanins;
|
||||
std::vector<int> vIndices;
|
||||
std::vector<int> vFanouts;
|
||||
|
|
@ -60,6 +62,9 @@ namespace rrr {
|
|||
using clock_type = std::chrono::steady_clock;
|
||||
using time_point = std::chrono::time_point<clock_type>;
|
||||
|
||||
template <typename T>
|
||||
using summary = std::vector<std::pair<std::string, T>>;
|
||||
|
||||
}
|
||||
|
||||
ABC_NAMESPACE_CXX_HEADER_END
|
||||
|
|
|
|||
|
|
@ -97,7 +97,8 @@ namespace rrr {
|
|||
/* {{{ Print next */
|
||||
|
||||
struct SW {
|
||||
int width;
|
||||
int width = 0;
|
||||
bool left = false;
|
||||
};
|
||||
|
||||
struct NS {}; // no space
|
||||
|
|
@ -107,6 +108,16 @@ namespace rrr {
|
|||
template <typename T, typename... Args>
|
||||
void PrintNext(std::ostream &os, T t, Args... args);
|
||||
|
||||
static inline void PrintNext(std::ostream &os, int t) {
|
||||
os << std::setw(4) << t;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static inline void PrintNext(std::ostream &os, int t, Args... args) {
|
||||
os << std::setw(4) << t << " ";
|
||||
PrintNext(os, args...);
|
||||
}
|
||||
|
||||
static inline void PrintNext(std::ostream &os, bool arg) {
|
||||
os << arg;
|
||||
}
|
||||
|
|
@ -121,16 +132,6 @@ namespace rrr {
|
|||
PrintNext(os, args...);
|
||||
}
|
||||
|
||||
static inline void PrintNext(std::ostream &os, int t) {
|
||||
os << std::setw(4) << t;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
static inline void PrintNext(std::ostream &os, int t, Args... args) {
|
||||
os << std::setw(4) << t << " ";
|
||||
PrintNext(os, args...);
|
||||
}
|
||||
|
||||
static inline void PrintNext(std::ostream &os, double t) {
|
||||
os << std::fixed << std::setprecision(2) << std::setw(8) << t;
|
||||
}
|
||||
|
|
@ -143,12 +144,24 @@ namespace rrr {
|
|||
|
||||
template <typename T>
|
||||
static inline void PrintNext(std::ostream &os, SW sw, T arg) {
|
||||
if(sw.left) {
|
||||
os << std::left;
|
||||
}
|
||||
os << std::setw(sw.width) << arg;
|
||||
if(sw.left) {
|
||||
os << std::right;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static inline void PrintNext(std::ostream &os, SW sw, T arg, Args... args) {
|
||||
if(sw.left) {
|
||||
os << std::left;
|
||||
}
|
||||
os << std::setw(sw.width) << arg << " ";
|
||||
if(sw.left) {
|
||||
os << std::right;
|
||||
}
|
||||
PrintNext(os, args...);
|
||||
}
|
||||
|
||||
|
|
@ -161,24 +174,20 @@ namespace rrr {
|
|||
|
||||
template <typename T>
|
||||
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg) {
|
||||
std::string delim;
|
||||
os << "[";
|
||||
os << "[ ";
|
||||
for(T const &e: arg) {
|
||||
os << delim;
|
||||
PrintNext(os, e);
|
||||
delim = ", ";
|
||||
os << " ";
|
||||
}
|
||||
os << "]";
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg, Args... args) {
|
||||
std::string delim;
|
||||
os << "[";
|
||||
os << "[ ";
|
||||
for(T const &e: arg) {
|
||||
os << delim;
|
||||
PrintNext(os, e);
|
||||
delim = ", ";
|
||||
os << " ";
|
||||
}
|
||||
os << "] ";
|
||||
PrintNext(os, args...);
|
||||
|
|
@ -186,24 +195,20 @@ namespace rrr {
|
|||
|
||||
template <typename T>
|
||||
static inline void PrintNext(std::ostream& os, std::set<T> const &arg) {
|
||||
std::string delim;
|
||||
os << "{";
|
||||
os << "{ ";
|
||||
for(T const &e: arg) {
|
||||
os << delim;
|
||||
PrintNext(os, e);
|
||||
delim = ", ";
|
||||
os << " ";
|
||||
}
|
||||
os << "}";
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static inline void PrintNext(std::ostream& os, std::set<T> const &arg, Args... args) {
|
||||
std::string delim;
|
||||
os << "{";
|
||||
os << "{ ";
|
||||
for(T const &e: arg) {
|
||||
os << delim;
|
||||
PrintNext(os, e);
|
||||
delim = ", ";
|
||||
os << " ";
|
||||
}
|
||||
os << "} ";
|
||||
PrintNext(os, args...);
|
||||
|
|
@ -222,6 +227,14 @@ namespace rrr {
|
|||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Print others */
|
||||
|
||||
static inline void PrintWarning(std::string message) {
|
||||
std::cerr << "[w] " << message << std::endl;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* {{{ Combination */
|
||||
|
||||
bool ForEachCombinationStopRec(std::vector<int> &v, int n, int k, std::function<bool(std::vector<int> const &)> const &func) {
|
||||
|
|
@ -306,6 +319,8 @@ namespace rrr {
|
|||
return "trivial decompose";
|
||||
case SORT_FANINS:
|
||||
return "sort fanins";
|
||||
case READ:
|
||||
return "read";
|
||||
case SAVE:
|
||||
return "save";
|
||||
case LOAD:
|
||||
|
|
@ -323,32 +338,35 @@ namespace rrr {
|
|||
static inline std::stringstream GetActionDescription(Action const &action) {
|
||||
std::stringstream ss;
|
||||
ss << GetActionTypeCstr(action);
|
||||
std::string delim = ": ";
|
||||
std::string delim = " : ";
|
||||
if(action.id != -1) {
|
||||
ss << delim;
|
||||
PrintNext(ss, "node", action.id);
|
||||
delim = ", ";
|
||||
delim = " , ";
|
||||
}
|
||||
if(action.fi != -1) {
|
||||
ss << delim;
|
||||
PrintNext(ss, "fanin", (bool)action.c, action.fi);
|
||||
delim = ", ";
|
||||
delim = " , ";
|
||||
}
|
||||
if(action.idx != -1) {
|
||||
ss << delim;
|
||||
PrintNext(ss, "index", action.idx);
|
||||
}
|
||||
if(action.fNew) {
|
||||
ss << " new";
|
||||
}
|
||||
ss << std::endl;
|
||||
if(!action.vFanins.empty()) {
|
||||
ss << "fanins: ";
|
||||
ss << "fanins : ";
|
||||
PrintNext(ss, action.vFanins);
|
||||
}
|
||||
if(!action.vIndices.empty()) {
|
||||
ss << "indices: ";
|
||||
ss << "indices : ";
|
||||
PrintNext(ss, action.vIndices);
|
||||
}
|
||||
if(!action.vFanouts.empty()) {
|
||||
ss << "fanouts: ";
|
||||
ss << "fanouts : ";
|
||||
PrintNext(ss, action.vFanouts);
|
||||
}
|
||||
return ss;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ struct Pdr_Par_t_
|
|||
Vec_Int_t * vOutMap; // in the multi-output mode, contains status for each PO (0 = sat; 1 = unsat; negative = undecided)
|
||||
char * pInvFileName; // invariable file name
|
||||
char * pCexFilePrefix; // CEX output prefix
|
||||
int fBlocking; // clause pushing with blocking
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ void Pdr_ManSetDefaultParams( Pdr_Par_t * pPars )
|
|||
pPars->timeLastSolved = 0; // last one solved
|
||||
pPars->pInvFileName = NULL; // invariant file name
|
||||
pPars->pCexFilePrefix = NULL; // CEX output prefix
|
||||
pPars->fBlocking = 0; // clause pushing with blocking
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -391,6 +392,140 @@ int Pdr_ManPushClauses( Pdr_Man_t * p )
|
|||
return RetValue;
|
||||
}
|
||||
|
||||
int ZPdr_ManDown_Exhaustive( Pdr_Man_t *, int, Pdr_Set_t **, Pdr_Set_t *, Hash_Int_t *, Pdr_Set_t *, int * );
|
||||
int Pdr_ManPushAndBlockClauses( Pdr_Man_t * p )
|
||||
{
|
||||
Pdr_Set_t * pTemp, * pCubeK, * pCubeK1;
|
||||
Vec_Ptr_t * vArrayK, * vArrayK1;
|
||||
int i, j, k, m, RetValue = 0, RetValue2, kMax = Vec_PtrSize(p->vSolvers)-1;
|
||||
int iStartFrame = p->pPars->fShiftStart ? p->iUseFrame : 1;
|
||||
int Counter = 0;
|
||||
|
||||
int blockCount;
|
||||
int blockAttemp;
|
||||
int added;
|
||||
int l;
|
||||
int RetValue3;
|
||||
Pdr_Set_t *pPred = NULL;
|
||||
Pdr_Set_t *pCubeCpy = NULL;
|
||||
|
||||
abctime clk = Abc_Clock();
|
||||
assert( p->iUseFrame > 0 );
|
||||
Vec_VecForEachLevelStartStop( p->vClauses, vArrayK, k, iStartFrame, kMax )
|
||||
{
|
||||
Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare );
|
||||
vArrayK1 = Vec_VecEntry( p->vClauses, k+1 );
|
||||
blockCount = 0;
|
||||
blockAttemp = 0;
|
||||
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
|
||||
{
|
||||
Counter++;
|
||||
|
||||
// remove cubes in the same frame that are contained by pCubeK
|
||||
Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
|
||||
{
|
||||
if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
|
||||
continue;
|
||||
Pdr_SetDeref( pTemp );
|
||||
Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
|
||||
Vec_PtrPop(vArrayK);
|
||||
m--;
|
||||
}
|
||||
|
||||
// check if the clause can be moved to the next frame
|
||||
added = 1;
|
||||
RetValue2 = Pdr_ManCheckCube( p, k, pCubeK, &pPred, 0, 0, 1 ); // ************************
|
||||
if ( RetValue2 == -1 )
|
||||
return -1;
|
||||
if ( !RetValue2 ) // try to block before pushing
|
||||
{
|
||||
if ( blockCount < blockAttemp )
|
||||
continue;
|
||||
else
|
||||
{
|
||||
blockAttemp++;
|
||||
pCubeCpy = Pdr_SetDup(pCubeK);
|
||||
RetValue3 = ZPdr_ManDown_Exhaustive( p, k, &pCubeCpy, pPred, Hash_IntAlloc( 1 ), NULL, &added );
|
||||
if ( RetValue3 == -1 )
|
||||
{
|
||||
Pdr_SetDeref( pCubeCpy );
|
||||
return -1;
|
||||
}
|
||||
if ( RetValue3 == 0 )
|
||||
{
|
||||
Pdr_SetDeref( pCubeCpy );
|
||||
continue;
|
||||
}
|
||||
Pdr_SetDeref( pCubeK );
|
||||
pCubeK = pCubeCpy;
|
||||
|
||||
for ( l = 1; l <= k; l++ )
|
||||
Pdr_ManSolverAddClause( p, l, pCubeK );
|
||||
blockCount++;
|
||||
}
|
||||
}
|
||||
else // directly push
|
||||
{
|
||||
Pdr_Set_t * pCubeMin;
|
||||
pCubeMin = Pdr_ManReduceClause( p, k, pCubeK );
|
||||
if ( pCubeMin != NULL )
|
||||
{
|
||||
// Abc_Print( 1, "%d ", pCubeK->nLits - pCubeMin->nLits );
|
||||
Pdr_SetDeref( pCubeK );
|
||||
pCubeK = pCubeMin;
|
||||
}
|
||||
}
|
||||
|
||||
// if it can be moved, add it to the next frame
|
||||
Pdr_ManSolverAddClause( p, k+1, pCubeK );
|
||||
// check if the clause subsumes others
|
||||
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK1, pCubeK1, i )
|
||||
{
|
||||
if ( !Pdr_SetContains( pCubeK1, pCubeK ) ) // pCubeK contains pCubeK1
|
||||
continue;
|
||||
Pdr_SetDeref( pCubeK1 );
|
||||
Vec_PtrWriteEntry( vArrayK1, i, Vec_PtrEntryLast(vArrayK1) );
|
||||
Vec_PtrPop(vArrayK1);
|
||||
i--;
|
||||
}
|
||||
// add the last clause
|
||||
Vec_PtrPush( vArrayK1, pCubeK );
|
||||
Vec_PtrWriteEntry( vArrayK, j, Vec_PtrEntryLast(vArrayK) );
|
||||
Vec_PtrPop(vArrayK);
|
||||
j--;
|
||||
}
|
||||
// printf("%d, %d\n", blockCount, blockAtemp);
|
||||
if ( Vec_PtrSize(vArrayK) == 0 )
|
||||
RetValue = 1;
|
||||
}
|
||||
|
||||
// clean up the last one
|
||||
vArrayK = Vec_VecEntry( p->vClauses, kMax );
|
||||
Vec_PtrSort( vArrayK, (int (*)(const void *, const void *))Pdr_SetCompare );
|
||||
Vec_PtrForEachEntry( Pdr_Set_t *, vArrayK, pCubeK, j )
|
||||
{
|
||||
// remove cubes in the same frame that are contained by pCubeK
|
||||
Vec_PtrForEachEntryStart( Pdr_Set_t *, vArrayK, pTemp, m, j+1 )
|
||||
{
|
||||
if ( !Pdr_SetContains( pTemp, pCubeK ) ) // pCubeK contains pTemp
|
||||
continue;
|
||||
/*
|
||||
Abc_Print( 1, "===\n" );
|
||||
Pdr_SetPrint( stdout, pCubeK, Aig_ManRegNum(p->pAig), NULL );
|
||||
Abc_Print( 1, "\n" );
|
||||
Pdr_SetPrint( stdout, pTemp, Aig_ManRegNum(p->pAig), NULL );
|
||||
Abc_Print( 1, "\n" );
|
||||
*/
|
||||
Pdr_SetDeref( pTemp );
|
||||
Vec_PtrWriteEntry( vArrayK, m, Vec_PtrEntryLast(vArrayK) );
|
||||
Vec_PtrPop(vArrayK);
|
||||
m--;
|
||||
}
|
||||
}
|
||||
p->tPush += Abc_Clock() - clk;
|
||||
return RetValue;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns 1 if the clause is contained in higher clauses.]
|
||||
|
|
@ -637,6 +772,225 @@ int ZPdr_ManDown( Pdr_Man_t * p, int k, Pdr_Set_t ** ppCube, Pdr_Set_t * pPred,
|
|||
return 1;
|
||||
}
|
||||
|
||||
int ZPdr_ManDown_Exhaustive( Pdr_Man_t * p, int k, Pdr_Set_t ** ppCube, Pdr_Set_t * pPred, Hash_Int_t * keep, Pdr_Set_t * pIndCube, int * added )
|
||||
{
|
||||
int RetValue = 0, CtgRetValue, i, ctgAttempts, l, micResult;
|
||||
int j;
|
||||
int kMax = Vec_PtrSize(p->vSolvers)-1;
|
||||
int kTmp = k;
|
||||
Pdr_Set_t * pCubeTmp, * pCubeMin, * pCtg;
|
||||
Pdr_Set_t * pPredTmp = pPred, * pCubePre = *ppCube;
|
||||
Pdr_Set_t * pCubeMinCopy;
|
||||
while ( RetValue == 0 )
|
||||
{
|
||||
ctgAttempts = 0;
|
||||
while ( RetValue == 0 && kTmp > 1 && ctgAttempts < 3 )
|
||||
{
|
||||
pCtg = Pdr_SetDup( pPredTmp );
|
||||
//Check CTG for inductiveness
|
||||
if ( Pdr_SetIsInit( pCtg, -1 ) )
|
||||
{
|
||||
Pdr_SetDeref( pCtg );
|
||||
break;
|
||||
}
|
||||
if (*added == 0)
|
||||
{
|
||||
for ( i = 1; i <= k; i++ )
|
||||
Pdr_ManSolverAddClause( p, i, pIndCube);
|
||||
*added = 1;
|
||||
}
|
||||
if ( pPredTmp != pPred )
|
||||
Pdr_SetDeref( pPredTmp );
|
||||
CtgRetValue = Pdr_ManCheckCube( p, kTmp-1, pCtg, &pPredTmp, p->pPars->nConfLimit, 0, 1 );
|
||||
if ( CtgRetValue == -1 )
|
||||
{
|
||||
Pdr_SetDeref( pCtg );
|
||||
Pdr_SetDeref( pPred );
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
return -1;
|
||||
}
|
||||
if ( CtgRetValue == 0 )
|
||||
{
|
||||
if (pCubePre != *ppCube)
|
||||
Pdr_SetDeref( pCubePre );
|
||||
if (kTmp == 1)
|
||||
{
|
||||
Pdr_SetDeref( pCtg );
|
||||
ctgAttempts++;
|
||||
kTmp = k;
|
||||
pPredTmp = pPred;
|
||||
pCubePre = *ppCube;
|
||||
}
|
||||
else
|
||||
{
|
||||
pCubePre = pCtg;
|
||||
kTmp = kTmp - 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
pCubeMin = Pdr_ManReduceClause( p, kTmp-1, pCtg );
|
||||
if ( pCubeMin == NULL )
|
||||
pCubeMin = Pdr_SetDup( pCtg );
|
||||
|
||||
pCubeMinCopy = Pdr_SetDup( pCubeMin );
|
||||
// generalize before pushing
|
||||
micResult = ZPdr_ManSimpleMic( p, kTmp-1, &pCubeMin );
|
||||
if ( micResult == -1 )
|
||||
{
|
||||
Pdr_SetDeref( pCtg );
|
||||
Pdr_SetDeref( pCubeMin );
|
||||
Pdr_SetDeref( pCubeMinCopy );
|
||||
Pdr_SetDeref( pPred );
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
return -1;
|
||||
}
|
||||
for ( l = kTmp; l < kMax; l++ )
|
||||
if ( Pdr_ManCheckCube( p, l, pCubeMin, NULL, p->pPars->nConfLimit, 0, 1 ) != 1 )
|
||||
break;
|
||||
// add clause
|
||||
for ( i = 1; i <= l; i++ )
|
||||
Pdr_ManSolverAddClause( p, i, pCubeMin );
|
||||
Vec_VecPush( p->vClauses, l, pCubeMin ); // consume ref
|
||||
p->nCubes++;
|
||||
|
||||
// try to push the original cube farther
|
||||
for ( j = l; j < kMax; j++ )
|
||||
if ( Pdr_ManCheckCube( p, j, pCubeMinCopy, NULL, p->pPars->nConfLimit, 0, 1 ) != 1 )
|
||||
break;
|
||||
if ( j > l )
|
||||
{
|
||||
micResult = ZPdr_ManSimpleMic( p, j-1, &pCubeMinCopy );
|
||||
if ( micResult == -1 )
|
||||
{
|
||||
Pdr_SetDeref( pCtg );
|
||||
Pdr_SetDeref( pCubeMinCopy );
|
||||
Pdr_SetDeref( pPred );
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
return -1;
|
||||
}
|
||||
// add clause
|
||||
for ( i = 1; i <= j; i++ )
|
||||
Pdr_ManSolverAddClause( p, i, pCubeMinCopy );
|
||||
Vec_VecPush( p->vClauses, j, pCubeMinCopy );
|
||||
p->nCubes++;
|
||||
}
|
||||
|
||||
// add new clause
|
||||
if ( p->pPars->fVeryVerbose )
|
||||
{
|
||||
Abc_Print( 1, "Adding cube " );
|
||||
Pdr_SetPrint( stdout, pCubeMin, Aig_ManRegNum(p->pAig), NULL );
|
||||
Abc_Print( 1, " to frame %d.\n", l );
|
||||
}
|
||||
// set priority flops for both cubes
|
||||
for ( i = 0; i < pCubeMin->nLits; i++ )
|
||||
{
|
||||
assert( pCubeMin->Lits[i] >= 0 );
|
||||
assert( (pCubeMin->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
|
||||
if ( (Vec_IntEntry(p->vPrio, pCubeMin->Lits[i] / 2) >> p->nPrioShift) == 0 )
|
||||
p->nAbsFlops++;
|
||||
Vec_IntAddToEntry( p->vPrio, pCubeMin->Lits[i] / 2, 1 << p->nPrioShift );
|
||||
}
|
||||
for ( i = 0; i < pCubeMinCopy->nLits; i++ )
|
||||
{
|
||||
assert( pCubeMinCopy->Lits[i] >= 0 );
|
||||
assert( (pCubeMinCopy->Lits[i] / 2) < Aig_ManRegNum(p->pAig) );
|
||||
if ( (Vec_IntEntry(p->vPrio, pCubeMinCopy->Lits[i] / 2) >> p->nPrioShift) == 0 )
|
||||
p->nAbsFlops++;
|
||||
Vec_IntAddToEntry( p->vPrio, pCubeMinCopy->Lits[i] / 2, 1 << p->nPrioShift );
|
||||
}
|
||||
|
||||
Pdr_SetDeref( pPred );
|
||||
RetValue = Pdr_ManCheckCube( p, k, *ppCube, &pPred, p->pPars->nConfLimit, 0, 1 );
|
||||
if ( RetValue == -1 )
|
||||
{
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
Pdr_SetDeref( pCtg );
|
||||
return -1;
|
||||
}
|
||||
Pdr_SetDeref( pCtg );
|
||||
if ( RetValue == 1 )
|
||||
{
|
||||
//printf ("IT'S A ONE\n");
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
return 1;
|
||||
}
|
||||
RetValue = Pdr_ManCheckCube( p, kTmp, pCubePre, &pPredTmp, p->pPars->nConfLimit, 0, 1 );
|
||||
if ( RetValue == -1 )
|
||||
{
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
Pdr_SetDeref( pPred );
|
||||
return -1;
|
||||
}
|
||||
if (RetValue == 1)
|
||||
{
|
||||
ctgAttempts++;
|
||||
if ( pCubePre != *ppCube )
|
||||
Pdr_SetDeref( pCubePre );
|
||||
kTmp = k;
|
||||
pPredTmp = pPred;
|
||||
pCubePre = *ppCube;
|
||||
}
|
||||
}
|
||||
|
||||
if (pCubePre != *ppCube)
|
||||
Pdr_SetDeref( pCubePre );
|
||||
if ( pPredTmp != pPred )
|
||||
Pdr_SetDeref( pPredTmp );
|
||||
//join
|
||||
if ( p->pPars->fVeryVerbose )
|
||||
{
|
||||
printf("Cube:\n");
|
||||
ZPdr_SetPrint( *ppCube );
|
||||
printf("\nPred:\n");
|
||||
ZPdr_SetPrint( pPred );
|
||||
}
|
||||
*ppCube = ZPdr_SetIntersection( pCubeTmp = *ppCube, pPred, keep );
|
||||
Pdr_SetDeref( pCubeTmp );
|
||||
Pdr_SetDeref( pPred );
|
||||
if ( *ppCube == NULL )
|
||||
return 0;
|
||||
if ( p->pPars->fVeryVerbose )
|
||||
{
|
||||
printf("Intersection:\n");
|
||||
ZPdr_SetPrint( *ppCube );
|
||||
}
|
||||
if ( Pdr_SetIsInit( *ppCube, -1 ) )
|
||||
{
|
||||
if ( p->pPars->fVeryVerbose )
|
||||
printf ("Failed initiation\n");
|
||||
return 0;
|
||||
}
|
||||
RetValue = Pdr_ManCheckCube( p, k, *ppCube, &pPred, p->pPars->nConfLimit, 0, 1 );
|
||||
if ( RetValue == -1 )
|
||||
return -1;
|
||||
if ( RetValue == 1 )
|
||||
{
|
||||
//printf ("*********IT'S A ONE\n");
|
||||
break;
|
||||
}
|
||||
if ( RetValue == 0 && (*ppCube)->nLits == 1)
|
||||
{
|
||||
Pdr_SetDeref( pPred ); // fixed memory leak
|
||||
// A workaround for the incomplete assignment returned by the SAT
|
||||
// solver
|
||||
return 0;
|
||||
}
|
||||
kTmp = k;
|
||||
pPredTmp = pPred;
|
||||
pCubePre = *ppCube;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Specialized sorting of flops based on priority.]
|
||||
|
|
@ -1507,6 +1861,24 @@ int Pdr_ManSolveInt( Pdr_Man_t * p )
|
|||
}
|
||||
// push clauses into this timeframe
|
||||
RetValue = 0;
|
||||
if (p->pPars->fBlocking) // clause pushing with blocking
|
||||
{
|
||||
RetValue = Pdr_ManPushAndBlockClauses( p );
|
||||
if ( RetValue == -1 )
|
||||
{
|
||||
if ( p->pPars->fVerbose )
|
||||
Pdr_ManPrintProgress( p, 1, Abc_Clock() - clkStart );
|
||||
if ( !p->pPars->fSilent )
|
||||
{
|
||||
if ( p->timeToStop && Abc_Clock() > p->timeToStop )
|
||||
Abc_Print( 1, "Reached timeout (%d seconds) in frame %d.\n", p->pPars->nTimeOut, iFrame );
|
||||
else
|
||||
Abc_Print( 1, "Reached conflict limit (%d) in frame %d.\n", p->pPars->nConfLimit, iFrame );
|
||||
}
|
||||
p->pPars->iFrame = iFrame;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ( p->pPars->fAnytime )
|
||||
{
|
||||
RetValue = Pdr_ManPushInfAndRecycledClauses( p );
|
||||
|
|
|
|||
|
|
@ -64,9 +64,11 @@ struct Bmc_EsPar_t_
|
|||
int fQuadrEnc;
|
||||
int fUniqFans;
|
||||
int fLutCascade;
|
||||
int fLutInFixed;
|
||||
int RuntimeLim;
|
||||
int nRandFuncs;
|
||||
int nMintNum;
|
||||
int Seed;
|
||||
int fVerbose;
|
||||
char * pTtStr;
|
||||
char * pSymStr;
|
||||
|
|
|
|||
|
|
@ -1009,6 +1009,7 @@ struct Exa3_Man_t_
|
|||
int VarMarks[MAJ_NOBJS][6][MAJ_NOBJS]; // variable marks
|
||||
int VarVals[MAJ_NOBJS]; // values of the first nVars variables
|
||||
Vec_Wec_t * vOutLits; // output vars
|
||||
Vec_Wec_t * vInVars; // input vars
|
||||
bmcg_sat_solver * pSat; // SAT solver
|
||||
int nUsed[2];
|
||||
};
|
||||
|
|
@ -1040,6 +1041,54 @@ static inline int Exa3_ManIsUsed3( Exa3_Man_t * p, int m, int n, int i, int
|
|||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Wec_t * Exa3_ChooseInputVars_int( int nVars, int nLuts, int nLutSize )
|
||||
{
|
||||
Vec_Wec_t * p = Vec_WecStart( nLuts );
|
||||
Vec_Int_t * vLevel; int i;
|
||||
Vec_WecForEachLevel( p, vLevel, i ) {
|
||||
do {
|
||||
int iVar = (Abc_Random(0) ^ Abc_Random(0) ^ Abc_Random(0)) % nVars;
|
||||
Vec_IntPushUniqueOrder( vLevel, iVar );
|
||||
}
|
||||
while ( Vec_IntSize(vLevel) < nLutSize-(int)(i>0) );
|
||||
}
|
||||
return p;
|
||||
}
|
||||
Vec_Int_t * Exa3_CountInputVars( int nVars, Vec_Wec_t * p )
|
||||
{
|
||||
Vec_Int_t * vLevel; int i, k, Obj;
|
||||
Vec_Int_t * vCounts = Vec_IntStart( nVars );
|
||||
Vec_WecForEachLevel( p, vLevel, i )
|
||||
Vec_IntForEachEntry( vLevel, Obj, k )
|
||||
Vec_IntAddToEntry( vCounts, Obj, 1 );
|
||||
return vCounts;
|
||||
}
|
||||
Vec_Wec_t * Exa3_ChooseInputVars( int nVars, int nLuts, int nLutSize )
|
||||
{
|
||||
for ( int i = 0; i < 1000; i++ ) {
|
||||
Vec_Wec_t * p = Exa3_ChooseInputVars_int( nVars, nLuts, nLutSize );
|
||||
Vec_Int_t * q = Exa3_CountInputVars( nVars, p );
|
||||
int RetValue = Vec_IntFind( q, 0 );
|
||||
Vec_IntFree( q );
|
||||
if ( RetValue == -1 )
|
||||
return p;
|
||||
Vec_WecFree( p );
|
||||
}
|
||||
assert( 0 );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
@ -1102,6 +1151,19 @@ static int Exa3_ManMarkup( Exa3_Man_t * p )
|
|||
}
|
||||
}
|
||||
printf( "The number of parameter variables = %d.\n", p->iVar );
|
||||
if ( p->pPars->fLutCascade && p->pPars->fLutInFixed ) {
|
||||
p->vInVars = Exa3_ChooseInputVars( p->nVars, p->nNodes, p->nLutSize );
|
||||
if ( 1 ) {
|
||||
Vec_Int_t * vLevel; int i, Var;
|
||||
printf( "Using fixed input assignment:\n" );
|
||||
Vec_WecForEachLevelReverse( p->vInVars, vLevel, i ) {
|
||||
printf( "%02d : ", p->nVars+i );
|
||||
Vec_IntForEachEntry( vLevel, Var, k )
|
||||
printf( "%c ", 'a'+Var );
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
}
|
||||
return p->iVar;
|
||||
// printout
|
||||
for ( i = p->nObjs - 1; i >= p->nVars; i-- )
|
||||
|
|
@ -1148,6 +1210,7 @@ static void Exa3_ManFree( Exa3_Man_t * p )
|
|||
Vec_BitFreeP( &p->vUsed2 );
|
||||
Vec_BitFreeP( &p->vUsed3 );
|
||||
Vec_WecFree( p->vOutLits );
|
||||
Vec_WecFreeP( &p->vInVars );
|
||||
ABC_FREE( p );
|
||||
}
|
||||
|
||||
|
|
@ -1396,6 +1459,18 @@ static int Exa3_ManAddCnfStart( Exa3_Man_t * p, int fOnlyAnd )
|
|||
if ( !bmcg_sat_solver_addclause( p->pSat, Vec_IntArray(vArray), Vec_IntSize(vArray) ) )
|
||||
return 0;
|
||||
}
|
||||
if ( p->vInVars ) {
|
||||
Vec_Int_t * vLevel; int Var;
|
||||
Vec_WecForEachLevel( p->vInVars, vLevel, i )
|
||||
{
|
||||
assert( Vec_IntSize(vLevel) > 0 );
|
||||
Vec_IntForEachEntry( vLevel, Var, k ) {
|
||||
pLits[0] = Abc_Var2Lit( p->VarMarks[p->nVars+i][p->nLutSize-1-k][Var], 0 ); assert(pLits[0]);
|
||||
if ( !bmcg_sat_solver_addclause( p->pSat, pLits, 1 ) )
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
static int Exa3_ManAddCnf( Exa3_Man_t * p, int iMint )
|
||||
|
|
@ -1580,25 +1655,26 @@ int Exa3_ManExactSynthesis( Bmc_EsPar_t * pPars )
|
|||
void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars )
|
||||
{
|
||||
int i, k, nDecs = 0, nWords = Abc_TtWordNum(pPars->nVars);
|
||||
word * pFun = ABC_ALLOC( word, nWords );
|
||||
Abc_Random(1);
|
||||
printf( "\n" );
|
||||
word * pFun = ABC_ALLOC( word, nWords );
|
||||
unsigned Rand0 = Abc_Random(1);
|
||||
for ( i = 0; i < pPars->Seed; i++ )
|
||||
Rand0 = Abc_Random(0);
|
||||
for ( i = 0; i < pPars->nRandFuncs; i++ ) {
|
||||
if ( pPars->nMintNum == 0 )
|
||||
for ( k = 0; k < nWords; k++ )
|
||||
pFun[k] = Abc_RandomW(0);
|
||||
pFun[k] = Rand0 ^ Abc_RandomW(0);
|
||||
else {
|
||||
Abc_TtClear( pFun, nWords );
|
||||
for ( k = 0; k < pPars->nMintNum; k++ ) {
|
||||
int iMint = 0;
|
||||
do iMint = Abc_Random(0) % (1 << pPars->nVars);
|
||||
do iMint = (Rand0 ^ Abc_Random(0)) % (1 << pPars->nVars);
|
||||
while ( Abc_TtGetBit(pFun, iMint) );
|
||||
Abc_TtSetBit( pFun, iMint );
|
||||
}
|
||||
}
|
||||
pPars->pTtStr = ABC_CALLOC( char, pPars->nVars > 2 ? (1 << (pPars->nVars-2)) + 1 : 2 );
|
||||
Extra_PrintHexadecimalString( pPars->pTtStr, (unsigned *)pFun, pPars->nVars );
|
||||
printf( "\nIteration %d : ", i );
|
||||
printf( "\nFunction %4d : ", i );
|
||||
if ( pPars->nMintNum )
|
||||
printf( "Random function has %d positive minterms.", pPars->nMintNum );
|
||||
printf( "\n" );
|
||||
|
|
@ -1607,7 +1683,7 @@ void Exa3_ManExactSynthesisRand( Bmc_EsPar_t * pPars )
|
|||
nDecs += Exa3_ManExactSynthesis( pPars );
|
||||
ABC_FREE( pPars->pTtStr );
|
||||
}
|
||||
printf( "Decomposable are %d (out of %d) functions (%.2f %%).\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs );
|
||||
printf( "\nDecomposable are %d (out of %d) functions (%.2f %%).\n\n", nDecs, pPars->nRandFuncs, 100.0*nDecs/pPars->nRandFuncs );
|
||||
ABC_FREE( pFun );
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ int cadical_solver_addclause(cadical_solver* s, int* begin, int* end) {
|
|||
|
||||
Synopsis [solve with resource limits]
|
||||
|
||||
Description [assumptions and inspection limits are not supported.]
|
||||
Description [inspection limits are not supported.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ int cadical_solver_final(cadical_solver* s, int** ppArray) {
|
|||
|
||||
Synopsis [get number of variables]
|
||||
|
||||
Description [emulated using "nVars".]
|
||||
Description [also update "nVars" if added by BVA.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
|
|
@ -201,6 +201,9 @@ int cadical_solver_final(cadical_solver* s, int** ppArray) {
|
|||
|
||||
***********************************************************************/
|
||||
int cadical_solver_nvars(cadical_solver* s) {
|
||||
if(s->nVars < ccadical_vars((CCaDiCaL*)s->p)) {
|
||||
s->nVars = ccadical_vars((CCaDiCaL*)s->p);
|
||||
}
|
||||
return s->nVars;
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +211,7 @@ int cadical_solver_nvars(cadical_solver* s) {
|
|||
|
||||
Synopsis [add new variable]
|
||||
|
||||
Description [emulated using "nVars".]
|
||||
Description [also update "nVars" if added by BVA.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
|
|
@ -216,6 +219,9 @@ int cadical_solver_nvars(cadical_solver* s) {
|
|||
|
||||
***********************************************************************/
|
||||
int cadical_solver_addvar(cadical_solver* s) {
|
||||
if(s->nVars < ccadical_vars((CCaDiCaL*)s->p)) {
|
||||
s->nVars = ccadical_vars((CCaDiCaL*)s->p);
|
||||
}
|
||||
return s->nVars++;
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +229,9 @@ int cadical_solver_addvar(cadical_solver* s) {
|
|||
|
||||
Synopsis [set number of variables]
|
||||
|
||||
Description [not only emulate with "nVars" but also reserve memory.]
|
||||
Description [emulate with "nVars". also reserve as many variables only
|
||||
when no variables have been added yet, as it destroys a
|
||||
satisfying assignment in incremental solving.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
|
|
@ -232,7 +240,9 @@ int cadical_solver_addvar(cadical_solver* s) {
|
|||
***********************************************************************/
|
||||
void cadical_solver_setnvars(cadical_solver* s,int n) {
|
||||
s->nVars = n;
|
||||
ccadical_reserve((CCaDiCaL*)s->p, n);
|
||||
if(ccadical_vars((CCaDiCaL*)s->p) == 0) {
|
||||
ccadical_reserve((CCaDiCaL*)s->p, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
add_executable(gia_test gia_test.cc)
|
||||
|
||||
target_link_libraries(gia_test
|
||||
gtest_main
|
||||
libabc
|
||||
)
|
||||
|
||||
gtest_discover_tests(gia_test
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
)
|
||||
Loading…
Reference in New Issue