Merge remote-tracking branch 'upstream/master' into yosys-experimental

This commit is contained in:
Miodrag Milanovic 2025-07-29 16:03:11 +02:00
commit fcd8ac34d6
86 changed files with 6850 additions and 1300 deletions

View File

@ -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

View File

@ -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 );

View File

@ -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.]

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 ///

View 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;

View File

@ -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*************************************************************

View File

@ -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 );

View File

@ -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 )

View File

@ -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;
}

View File

@ -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;

View File

@ -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 );
}

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 );

View File

@ -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;

View File

@ -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 )
{

View File

@ -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

View File

@ -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 );

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 );
}

View File

@ -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 )
{

View File

@ -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;
}

View File

@ -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 );
}

View File

@ -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*************************************************************

View File

@ -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 )

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

613
src/base/io/ioJsonc.c Normal file
View 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

View File

@ -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++ )

View File

@ -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 \

View File

@ -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 );
}

View File

@ -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 );

View File

@ -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;
}

View File

@ -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" );

View File

@ -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 ///

View 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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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***********************************************************************

View File

@ -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;
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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 );

View File

@ -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;
}

View File

@ -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 );

View File

@ -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" );

View File

@ -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 );

View File

@ -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;

View File

@ -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 " );

View File

@ -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 );

View File

@ -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 ///
////////////////////////////////////////////////////////////////////////

View 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 )
{

View File

@ -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)));

View File

@ -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*************************************************************

View File

@ -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*************************************************************

View File

@ -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
};
////////////////////////////////////////////////////////////////////////

View File

@ -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;

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}
/* }}} */
}

View File

@ -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;
}

View File

@ -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;
}
/* }}} */

View File

@ -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;
}
};
}

View File

@ -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;
}
/* }}} */

View File

@ -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());

View File

@ -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;
}
/* }}} */
}

View File

@ -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;

View File

@ -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());

View File

@ -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

View File

@ -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");
}
/* }}} */

View File

@ -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;
};
/* }}} */
}

View File

@ -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

View File

@ -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;

View File

@ -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
};
////////////////////////////////////////////////////////////////////////

View File

@ -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 );

View File

@ -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;

View File

@ -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 );
}

View File

@ -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*************************************************************

10
test/gia/CMakeLists.txt Normal file
View File

@ -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}
)