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

This commit is contained in:
Miodrag Milanovic 2025-04-08 13:28:24 +02:00
commit 1cdaaadf53
59 changed files with 6934 additions and 705 deletions

View File

@ -3,6 +3,8 @@ cmake_minimum_required(VERSION 3.5.0)
include(CMakeParseArguments)
include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
# Generate compilation database compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Default c++ standard used unless otherwise specified in target_compile_features.
set(CMAKE_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for this project")

View File

@ -27,7 +27,7 @@ MODULES := \
src/misc/mem src/misc/bar src/misc/bbl src/misc/parse \
src/opt/cut src/opt/fxu src/opt/fxch src/opt/rwr src/opt/mfs src/opt/sim \
src/opt/ret src/opt/fret src/opt/res src/opt/lpk src/opt/nwk src/opt/rwt src/opt/rar \
src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd \
src/opt/cgt src/opt/csw src/opt/dar src/opt/dau src/opt/dsc src/opt/sfm src/opt/sbd src/opt/eslim \
src/sat/bsat src/sat/xsat src/sat/satoko src/sat/csat src/sat/msat src/sat/psat src/sat/cnf src/sat/bmc src/sat/glucose src/sat/glucose2 src/sat/kissat src/sat/cadical \
src/bool/bdc src/bool/deco src/bool/dec src/bool/kit src/bool/lucky \
src/bool/rsb src/bool/rpo \

View File

@ -4114,6 +4114,46 @@ SOURCE=.\src\opt\sbd\sbdSat.c
SOURCE=.\src\opt\sbd\sbdWin.c
# End Source File
# End Group
# Begin Group "eslim"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\opt\eslim\eSLIM.cpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\eSLIM.h
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\eSLIMMan.hpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\relationGeneration.cpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\relationGeneration.hpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\satInterfaces.hpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\selectionStrategy.hpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\utils.hpp
# End Source File
# Begin Source File
SOURCE=.\src\opt\eslim\synthesisEngine.hpp
# End Source File
# End Group
# End Group
# Begin Group "map"

View File

@ -1808,7 +1808,7 @@ extern Gia_Man_t * Gia_ManTransductionBdd( Gia_Man_t * pGia, int nType,
extern Gia_Man_t * Gia_ManTransductionTt( Gia_Man_t * pGia, int nType, int fMspf, int nRandom, int nSortType, int nPiShuffle, int nParameter, int fLevel, Gia_Man_t * pExdc, int fNewLine, int nVerbose );
/*=== giaRrr.cpp ===========================================================*/
extern Gia_Man_t * Gia_ManRrr( Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nDistance, int nRestarts, int nThreads, int nWindowSize, int fDeterministic );
extern Gia_Man_t * Gia_ManRrr( Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nPartitionType, int nDistance, int nJobs, int nThreads, int nPartitionSize, int nPartitionSizeMin, int fDeterministic, int nParallelPartitions, int fOptOnInsert, int fGreedy );
/*=== giaCTas.c ===========================================================*/
typedef struct Tas_Man_t_ Tas_Man_t;

View File

@ -406,24 +406,24 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi
if ( *pType == 'i' )
{
if ( vNamesIn == NULL )
vNamesIn = Vec_PtrAlloc( nInputs + nLatches );
if ( Vec_PtrSize(vNamesIn) != iTerm )
vNamesIn = Vec_PtrStart( nInputs );
if ( Vec_PtrSize(vNamesIn) <= iTerm )
{
fError = 1;
break;
}
Vec_PtrPush( vNamesIn, Abc_UtilStrsav(pName) );
Vec_PtrWriteEntry( vNamesIn, iTerm, Abc_UtilStrsav(pName) );
}
else if ( *pType == 'o' )
{
if ( vNamesOut == NULL )
vNamesOut = Vec_PtrAlloc( nOutputs + nLatches );
if ( Vec_PtrSize(vNamesOut) != iTerm )
vNamesOut = Vec_PtrStart( nOutputs );
if ( Vec_PtrSize(vNamesOut) <= iTerm )
{
fError = 1;
break;
}
Vec_PtrPush( vNamesOut, Abc_UtilStrsav(pName) );
Vec_PtrWriteEntry( vNamesOut, iTerm, Abc_UtilStrsav(pName) );
}
else if ( *pType == 'l' )
{
@ -431,16 +431,16 @@ Gia_Man_t * Gia_AigerReadFromMemory( char * pContents, int nFileSize, int fGiaSi
assert( strlen(pName) < 995 );
sprintf( Buffer, "%s_in", pName );
if ( vNamesRegIn == NULL )
vNamesRegIn = Vec_PtrAlloc( nLatches );
vNamesRegIn = Vec_PtrStart( nLatches );
if ( vNamesRegOut == NULL )
vNamesRegOut = Vec_PtrAlloc( nLatches );
if ( Vec_PtrSize(vNamesRegIn) != iTerm )
vNamesRegOut = Vec_PtrStart( nLatches );
if ( Vec_PtrSize(vNamesRegIn) <= iTerm )
{
fError = 1;
break;
}
Vec_PtrPush( vNamesRegIn, Abc_UtilStrsav(Buffer) );
Vec_PtrPush( vNamesRegOut, Abc_UtilStrsav(pName) );
Vec_PtrWriteEntry( vNamesRegIn, iTerm, Abc_UtilStrsav(Buffer) );
Vec_PtrWriteEntry( vNamesRegOut, iTerm, Abc_UtilStrsav(pName) );
}
else if ( *pType == 'n' )
{

View File

@ -2674,6 +2674,9 @@ Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * p, Jf_Par_t * pPars )
pNew = Nf_ManPerformMappingInt( p, pPars );
Gia_ManTransferTiming( pNew, p );
//Gia_ManCellMappingVerify( pNew );
// remove choices after mapping
ABC_FREE( pNew->pReprs );
ABC_FREE( pNew->pNexts );
}
//pNew->MappedDelay = (int)((If_Par_t *)pp)->FinalDelay;
//pNew->MappedArea = (int)((If_Par_t *)pp)->FinalArea;

View File

@ -5,7 +5,7 @@
ABC_NAMESPACE_IMPL_START
Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nDistance, int nRestarts, int nThreads, int nWindowSize, int fDeterministic) {
Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int nSchedulerVerbose, int nPartitionerVerbose, int nOptimizerVerbose, int nAnalyzerVerbose, int nSimulatorVerbose, int nSatSolverVerbose, int fUseBddCspf, int fUseBddMspf, int nConflictLimit, int nSortType, int nOptimizerFlow, int nSchedulerFlow, int nPartitionType, int nDistance, int nJobs, int nThreads, int nPartitionSize, int nPartitionSizeMin, int fDeterministic, int nParallelPartitions, int fOptOnInsert, int fGreedy) {
rrr::AndNetwork ntk;
ntk.Read(pGia, rrr::GiaReader<rrr::AndNetwork>);
rrr::Parameter Par;
@ -24,11 +24,16 @@ Gia_Man_t *Gia_ManRrr(Gia_Man_t *pGia, int iSeed, int nWords, int nTimeout, int
Par.nSortType = nSortType;
Par.nOptimizerFlow = nOptimizerFlow;
Par.nSchedulerFlow = nSchedulerFlow;
Par.nPartitionType = nPartitionType;
Par.nDistance = nDistance;
Par.nRestarts = nRestarts;
Par.nJobs = nJobs;
Par.nThreads = nThreads;
Par.nWindowSize = nWindowSize;
Par.nPartitionSize = nPartitionSize;
Par.nPartitionSizeMin = nPartitionSizeMin;
Par.fDeterministic = fDeterministic;
Par.nParallelPartitions = nParallelPartitions;
Par.fOptOnInsert = fOptOnInsert;
Par.fGreedy = fGreedy;
rrr::Perform(&ntk, &Par);
Gia_Man_t *pNew = rrr::CreateGia(&ntk);
return pNew;

View File

@ -20,6 +20,7 @@
#include "gia.h"
#include "misc/tim/tim.h"
#include "misc/util/utilTruth.h"
#include "sat/bsat/satStore.h"
#include "misc/util/utilNam.h"
#include "map/scl/sclCon.h"
@ -1233,7 +1234,7 @@ void Gia_ManLutSat( Gia_Man_t * pGia, int LutSize, int nNumber, int nImproves, i
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int nBTLimit, int TimeOut, int fVerbose )
Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int Seed, int nBTLimit, int TimeOut, int fVerbose, int * pStatus )
{
extern Vec_Int_t * Exa4_ManParse( char *pFileName );
int fVerboseSolver = 0;
@ -1242,20 +1243,25 @@ Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int nBTLimi
#ifdef _WIN32
char * pKadical = "kadical.exe";
#else
char * pKadical = "kadical";
char * pKadical = "./kadical";
FILE * pFile = fopen( pKadical, "rb" );
if ( pFile == NULL )
pKadical += 2;
else
fclose( pFile );
#endif
char Command[1000], * pCommand = (char *)&Command;
if ( nBTLimit ) {
if ( TimeOut )
sprintf( pCommand, "%s -c %d -t %d %s %s > %s", pKadical, nBTLimit, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
sprintf( pCommand, "%s --seed=%d -c %d -t %d %s %s > %s", pKadical, Seed, nBTLimit, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
else
sprintf( pCommand, "%s -c %d %s %s > %s", pKadical, nBTLimit, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
sprintf( pCommand, "%s --seed=%d -c %d %s %s > %s", pKadical, Seed, nBTLimit, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
}
else {
if ( TimeOut )
sprintf( pCommand, "%s -t %d %s %s > %s", pKadical, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
sprintf( pCommand, "%s --seed=%d -t %d %s %s > %s", pKadical, Seed, TimeOut, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
else
sprintf( pCommand, "%s %s %s > %s", pKadical, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
sprintf( pCommand, "%s --seed=%d %s %s > %s", pKadical, Seed, fVerboseSolver ? "": "-q", pFileNameIn, pFileNameOut );
}
#ifdef __wasm
if ( 1 )
@ -1270,11 +1276,11 @@ Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int nBTLimi
if ( fVerbose )
{
if ( vRes )
printf( "The problem has a solution. " );
printf( "The problem has a solution. " ), *pStatus = 0;
else if ( vRes == NULL && TimeOut == 0 )
printf( "The problem has no solution. " );
printf( "The problem has no solution. " ), *pStatus = 1;
else if ( vRes == NULL )
printf( "The problem has no solution or reached a resource limit after %d sec. ", TimeOut );
printf( "The problem has no solution or reached a resource limit after %d sec. ", TimeOut ), *pStatus = -1;
Abc_PrintTime( 1, "SAT solver time", Abc_Clock() - clkTotal );
}
return vRes;
@ -1535,10 +1541,41 @@ int Gia_ManDumpCnf( char * pFileName, Vec_Str_t * vStr, int nVars )
fclose( pFile );
return 1;
}
int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int nBTLimit, int nTimeout, int fVerbose )
int Gia_ManDumpCnf2( Vec_Str_t * vStr, int nVars, int argc, char ** argv, abctime Time, int Status )
{
char * pFileNameI = (char *)"__temp__.cnf";
char * pFileNameO = (char *)"__temp__.out";
Vec_Str_t * vFileName = Vec_StrAlloc( 100 ); int c;
Vec_StrPrintF( vFileName, "%s", argv[0] + (argv[0][0] == '&') );
for ( c = 1; c < argc; c++ )
Vec_StrPrintF( vFileName, "_%s", argv[c] + (argv[c][0] == '-') );
Vec_StrPrintF( vFileName, ".cnf" );
Vec_StrPush( vFileName, '\0' );
FILE * pFile = fopen( Vec_StrArray(vFileName), "wb" );
if ( pFile == NULL ) { printf( "Cannot open output file \"%s\".\n", Vec_StrArray(vFileName) ); Vec_StrFree(vFileName); return 0; }
Vec_StrFree(vFileName);
fprintf( pFile, "c This file was generated by ABC command: \"" );
fprintf( pFile, "%s", argv[0] );
for ( c = 1; c < argc; c++ )
fprintf( pFile, " %s", argv[c] );
fprintf( pFile, "\" on %s\n", Gia_TimeStamp() );
fprintf( pFile, "c Cardinality CDCL (https://github.com/jreeves3/Cardinality-CDCL) found it to be " );
if ( Status == 1 )
fprintf( pFile, "UNSAT" );
if ( Status == 0 )
fprintf( pFile, "SAT" );
if ( Status == -1 )
fprintf( pFile, "UNDECIDED" );
fprintf( pFile, " in %.2f sec\n", 1.0*((double)(Time))/((double)CLOCKS_PER_SEC) );
fprintf( pFile, "p knf %d %d\n%s\n", nVars, Vec_StrCountEntry(vStr, '\n'), Vec_StrArray(vStr) );
fclose( pFile );
return 1;
}
int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int Seed, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv )
{
abctime clkStart = Abc_Clock();
srand(time(NULL));
int Status, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFFF;
char pFileNameI[32]; sprintf( pFileNameI, "_%06x_.cnf", Rand );
char pFileNameO[32]; sprintf( pFileNameO, "_%06x_.out", Rand );
if ( nBound == 0 )
nBound = 5 * Gia_ManAndNum(p);
Vec_Str_t * vStr = Gia_ManSimpleCnf( p, nBound/2 );
@ -1550,12 +1587,11 @@ int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int nBTLimit, int nTimeout,
if ( fVerbose )
printf( "SAT variables = %d. SAT clauses = %d. Cardinality bound = %d. Conflict limit = %d. Timeout = %d.\n",
nVars, Vec_StrCountEntry(vStr, '\n'), nBound, nBTLimit, nTimeout );
//char pFileName[100]; sprintf( pFileName, "temp%02d.cnf", nBound/2 );
//Gia_ManDumpCnf( pFileName, vStr, nVars );
Vec_StrFree( vStr );
Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, nBTLimit, nTimeout, 1 );
Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, Seed, nBTLimit, nTimeout, fVerbose, &Status );
unlink( pFileNameI );
//unlink( pFileNameO );
if ( fKeepFile ) Gia_ManDumpCnf2( vStr, nVars, argc, argv, Abc_Clock() - clkStart, Status );
Vec_StrFree( vStr );
if ( vRes == NULL )
return 0;
Vec_IntFreeP( &p->vCellMapping );
@ -1564,9 +1600,487 @@ int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int nBTLimit, int nTimeout,
if ( fVerbose ) Gia_ManSimplePrintMapping( vRes, Gia_ManCiNum(p) );
p->vCellMapping = Gia_ManDeriveSimpleMapping( p, vRes );
Vec_IntFree( vRes );
if ( fVerbose ) Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart );
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
#define KSAT_OBJS 24
#define KSAT_MINTS 64
#define KSAT_SPACE (4+3*KSAT_OBJS+3*KSAT_MINTS)
int Gia_KSatVarInv( int * pMap, int i ) { return pMap[i*KSAT_SPACE+0]; }
int Gia_KSatVarAnd( int * pMap, int i ) { return pMap[i*KSAT_SPACE+1]; }
int Gia_KSatVarEqu( int * pMap, int i ) { return pMap[i*KSAT_SPACE+2]; }
int Gia_KSatVarRef( int * pMap, int i ) { return pMap[i*KSAT_SPACE+3]; }
int Gia_KSatVarFan( int * pMap, int i, int f, int k ) { return pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k]; }
int Gia_KSatVarMin( int * pMap, int i, int m, int k ) { return pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k]; }
void Gia_KSatSetInv( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+0] ); pMap[i*KSAT_SPACE+0] = iVar; }
void Gia_KSatSetAnd( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+1] ); pMap[i*KSAT_SPACE+1] = iVar; }
void Gia_KSatSetEqu( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+2] ); pMap[i*KSAT_SPACE+2] = iVar; }
void Gia_KSatSetRef( int * pMap, int i, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+3] ); pMap[i*KSAT_SPACE+3] = iVar; }
void Gia_KSatSetFan( int * pMap, int i, int f, int k, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] = iVar; }
void Gia_KSatSetMin( int * pMap, int i, int m, int k, int iVar ) { assert( -1 == pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] = iVar; }
int Gia_KSatValInv( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+0] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+0] ); }
int Gia_KSatValAnd( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+1] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+1] ); }
int Gia_KSatValEqu( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+2] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+2] ); }
int Gia_KSatValRef( int * pMap, int i, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+3] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+3] ); }
int Gia_KSatValFan( int * pMap, int i, int f, int k, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+4+f*KSAT_OBJS+k] ); }
int Gia_KSatValMin( int * pMap, int i, int m, int k, Vec_Int_t * vRes ) { assert( -1 != pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); return Vec_IntEntry( vRes, pMap[i*KSAT_SPACE+4+3*KSAT_OBJS+3*m+k] ); }
int * Gia_KSatMapInit( int nIns, int nNodes, word Truth, int * pnVars )
{
assert( nIns + nNodes <= KSAT_OBJS );
assert( (1 << nIns) <= KSAT_MINTS );
int n, m, f, k, nVars = 2, * pMap = ABC_FALLOC( int, KSAT_OBJS*KSAT_SPACE );
for ( n = nIns; n < nIns+nNodes; n++ ) {
Gia_KSatSetInv(pMap, n, nVars++);
Gia_KSatSetAnd(pMap, n, nVars++);
Gia_KSatSetEqu(pMap, n, nVars++);
Gia_KSatSetRef(pMap, n, nVars++);
}
for ( n = nIns; n < nIns+nNodes; n++ ) {
for ( f = 0; f < 2; f++ )
for ( k = 0; k < n; k++ )
Gia_KSatSetFan(pMap, n, f, k, nVars++);
for ( k = n+1; k < nIns+nNodes; k++ )
Gia_KSatSetFan(pMap, n, 2, k, nVars++);
}
for ( m = 0; m < (1<<nIns); m++ ) {
for ( n = 0; n < nIns; n++ )
Gia_KSatSetMin(pMap, n, m, 0, (m >> n) & 1 );
Gia_KSatSetMin(pMap, nIns+nNodes-1, m, 0, (Truth >> m) & 1 );
for ( n = nIns; n < nIns+nNodes; n++ )
for ( k = 0; k < 3; k++ )
if ( k || n < nIns+nNodes-1 )
Gia_KSatSetMin(pMap, n, m, k, nVars++);
}
if ( pnVars ) *pnVars = nVars;
return pMap;
}
int Gia_KSatFindFan( int * pMap, int i, int f, Vec_Int_t * vRes )
{
assert( f < 2 );
for ( int k = 0; k < i; k++ )
if ( Gia_KSatValFan( pMap, i, f, k, vRes ) )
return k;
assert( 0 );
return -1;
}
Vec_Int_t * Gia_ManKSatGenLevels( char * pGuide, int nIns, int nNodes )
{
Vec_Int_t * vRes;
int i, k, Count = 0;
for ( i = 0; pGuide[i]; i++ )
Count += pGuide[i] - '0';
if ( Count != nNodes ) {
printf( "Guidance %s has %d nodes while the problem has %d nodes.\n", pGuide, Count, nNodes );
return NULL;
}
int FirstPrev = 0;
int FirstThis = nIns;
int FirstNext = FirstThis;
vRes = Vec_IntStartFull( 2*nIns );
for ( i = 0; pGuide[i]; i++ ) {
FirstNext += pGuide[i] - '0';
for ( k = FirstThis; k < FirstNext; k++ )
Vec_IntPushTwo( vRes, FirstPrev, FirstThis );
FirstPrev = FirstThis;
FirstThis = FirstNext;
}
assert( Vec_IntSize(vRes) == 2*(nIns + nNodes) );
Count = 0;
//int Start, Stop;
//Vec_IntForEachEntryDouble(vRes, Start, Stop, i)
// printf( "%2d : Start %2d Stop %2d\n", Count++, Start, Stop );
return vRes;
}
Vec_Str_t * Gia_ManKSatCnf( int * pMap, int nIns, int nNodes, int nBound, int fMultiLevel, char * pGuide )
{
Vec_Str_t * vStr = Vec_StrAlloc( 10000 );
Vec_Int_t * vRes = pGuide ? Gia_ManKSatGenLevels( pGuide, nIns, nNodes ) : NULL;
int i, j, m, n, f, c, a, Start, Stop, nLits = 0, pLits[256] = {0};
Gia_SatDumpLiteral( vStr, 1 );
Gia_SatDumpLiteral( vStr, 2 );
if ( vRes ) {
n = nIns;
Vec_IntForEachEntryDoubleStart( vRes, Start, Stop, i, 2*nIns ) {
for ( j = 0; j < Start; j++ )
Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 ) );
for ( f = 0; f < 2; f++ )
for ( j = Stop; j < n; j++ )
Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, j), 1 ) );
n++;
}
assert( n == nIns + nNodes );
}
// fanins are connected once
for ( n = nIns; n < nIns+nNodes; n++ )
for ( f = 0; f < 2; f++ ) {
nLits = 0;
for ( i = 0; i < n; i++ )
pLits[nLits++] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 0 );
Gia_SatDumpClause( vStr, pLits, nLits );
/*
for ( i = 0; i < n; i++ )
for ( j = 0; j < i; j++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, j), 1 );
Gia_SatDumpClause( vStr, pLits, 2 );
}
*/
Vec_StrPrintF( vStr, "k %d ", n-1 );
for ( i = 0; i < n; i++ )
pLits[i] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 );
Gia_SatDumpClause( vStr, pLits, n );
}
for ( n = nIns; n < nIns+nNodes; n++ ) {
// fanins are equal
for ( i = 0; i < n; i++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, i), 1 );
pLits[2] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 0 );
Gia_SatDumpClause( vStr, pLits, 3 );
}
for ( i = 0; i < n; i++ )
for ( j = i+1; j < n; j++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 );
pLits[2] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 1 );
Gia_SatDumpClause( vStr, pLits, 3 );
}
// if fanins are equal, inv is used
pLits[0] = Abc_Var2Lit( Gia_KSatVarEqu(pMap, n), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 );
Gia_SatDumpClause( vStr, pLits, 2 );
// fanin ordering
for ( i = 0; i < n; i++ )
for ( j = 0; j < i; j++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 );
Gia_SatDumpClause( vStr, pLits, 2 );
}
}
for ( n = nIns; n < nIns+nNodes-1; n++ ) {
// there is a fanout to the node above
for ( i = n+1; i < nIns+nNodes; i++ ) {
for ( f = 0; f < 2; f++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, f, n), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 0 );
Gia_SatDumpClause( vStr, pLits, 2 );
}
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, 0, n), 0 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, i, 1, n), 0 );
pLits[2] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 1 );
Gia_SatDumpClause( vStr, pLits, 3 );
}
// there is at least one fanout, except the last one
nLits = 0;
for ( i = n+1; i < nIns+nNodes; i++ )
pLits[nLits++] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 0 );
assert( nLits > 0 );
Gia_SatDumpClause( vStr, pLits, nLits );
}
// there is more than one fanout, except the last one
for ( n = nIns; n < nIns+nNodes-1; n++ ) {
for ( i = n+1; i < nIns+nNodes; i++ )
for ( j = i+1; j < nIns+nNodes; j++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 2, j), 1 );
pLits[2] = Abc_Var2Lit( Gia_KSatVarRef(pMap, n), 0 );
Gia_SatDumpClause( vStr, pLits, 3 );
}
// if more than one fanout, inv is used
pLits[0] = Abc_Var2Lit( Gia_KSatVarRef(pMap, n), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 );
Gia_SatDumpClause( vStr, pLits, 2 );
// if inv is not used, its fanins' invs are used
if ( !fMultiLevel ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), 0 );
for ( i = nIns; i < n; i++ )
for ( f = 0; f < 2; f++ ) {
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 );
pLits[2] = Abc_Var2Lit( Gia_KSatVarInv(pMap, i), 0 );
Gia_SatDumpClause( vStr, pLits, 3 );
}
}
}
// the last one always uses inverter
Gia_SatDumpLiteral( vStr, Abc_Var2Lit( Gia_KSatVarInv(pMap, nIns+nNodes-1), 0 ) );
/*
// for each minterm, for each pair of possible fanins, the node's output is determined using and/or and inv (4*N*N*M)
for ( m = 0; m < (1 << nIns); m++ )
for ( n = nIns; n < nIns+nNodes; n++ )
for ( c = 0; c < 2; c++ )
for ( a = 0; a < 2; a++ ) {
// implications: Fan(f) & Mint(m) & !And & !Inv -> Val1
for ( f = 0; f < 2; f++ )
for ( i = 0; i < n; i++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), !a );
pLits[2] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a );
pLits[3] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c );
pLits[4] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a^c );
Gia_SatDumpClause( vStr, pLits, 5 );
}
// large clauses: Fan(0) & Fan(1) & !Mint(m) & !Mint(m) & !And & !Inv -> Val0
for ( i = 0; i < n; i++ )
for ( j = i; j < n; j++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 0, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, 1, j), 1 );
pLits[2] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), a );
pLits[3] = Abc_Var2Lit( Gia_KSatVarMin(pMap, j, m, 0), a );
pLits[4] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a );
pLits[5] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c );
pLits[6] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a==c );
Gia_SatDumpClause( vStr, pLits, 7 );
}
}
*/
// for each minterm, define a fanin variable and use it to get the node's output based on and/or and inv (4*N*N*M)
for ( m = 0; m < (1 << nIns); m++ )
for ( n = nIns; n < nIns+nNodes; n++ ) {
for ( i = 0; i < n; i++ )
for ( f = 0; f < 2; f++ )
for ( c = 0; c < 2; c++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarFan(pMap, n, f, i), 1 );
pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, i, m, 0), c );
pLits[2] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1+f), !c );
Gia_SatDumpClause( vStr, pLits, 3 );
}
for ( c = 0; c < 2; c++ )
for ( a = 0; a < 2; a++ ) {
// implications: Mint(m,f) & !And & !Inv -> Val1
for ( f = 0; f < 2; f++ ) {
pLits[0] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1+f), !a );
pLits[1] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a );
pLits[2] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c );
pLits[3] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a^c );
Gia_SatDumpClause( vStr, pLits, 4 );
}
// large clauses: !Mint(m,0) & !Mint(m,1) & !And & !Inv -> Val0
pLits[0] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 1), a );
pLits[1] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 2), a );
pLits[2] = Abc_Var2Lit( Gia_KSatVarAnd(pMap, n), a );
pLits[3] = Abc_Var2Lit( Gia_KSatVarInv(pMap, n), c );
pLits[4] = Abc_Var2Lit( Gia_KSatVarMin(pMap, n, m, 0), a==c );
Gia_SatDumpClause( vStr, pLits, 5 );
}
}
// the number of nodes with duplicated fanins and without inv is maximized
if ( nBound && 2*nNodes > nBound ) {
Vec_StrPrintF( vStr, "k %d ", 2*nNodes-nBound );
nLits = 0;
for ( n = nIns; n < nIns+nNodes; n++ ) {
pLits[nLits++] = Abc_Var2Lit(Gia_KSatVarEqu(pMap, n), 0);
pLits[nLits++] = Abc_Var2Lit(Gia_KSatVarInv(pMap, n), 1);
}
Gia_SatDumpClause( vStr, pLits, nLits );
}
Vec_StrPush( vStr, '\0' );
Vec_IntFreeP( &vRes );
return vStr;
}
typedef enum {
GIA_GATE2_ZERO, // 0:
GIA_GATE2_ONE, // 1:
GIA_GATE2_BUF, // 2:
GIA_GATE2_INV, // 3:
GIA_GATE2_NAN2, // 4:
GIA_GATE2_NOR2, // 5:
GIA_GATE2_AOI21, // 6:
GIA_GATE2_NAN3, // 7:
GIA_GATE2_NOR3, // 8:
GIA_GATE2_OAI21, // 9:
GIA_GATE2_NOR4, // 10:
GIA_GATE2_AOI211, // 11:
GIA_GATE2_AOI22, // 12:
GIA_GATE2_NAN4, // 13:
GIA_GATE2_OAI211, // 14:
GIA_GATE2_OAI22, // 15:
GIA_GATE2_VOID // 16: unused value
} Gia_ManGate2_t;
Vec_Int_t * Gia_ManDeriveKSatMappingArray( Gia_Man_t * p, Vec_Int_t * vRes )
{
Vec_Int_t * vMapping = Vec_IntStart( 2*Gia_ManObjNum(p) );
int i, Id; Gia_Obj_t * pObj;
Gia_ManForEachCiId( p, Id, i )
if ( Vec_IntEntry(vRes, Id) )
Vec_IntWriteEntry( vMapping, Abc_Var2Lit(Id, 1), -1 );
Gia_ManForEachAnd( p, pObj, i ) {
assert( Vec_IntEntry(vRes, i) > 0 );
if ( (Vec_IntEntry(vRes, i) & 2) == 0 ) {
assert( (Vec_IntEntry(vRes, i) & 1) == 0 );
continue;
}
Gia_Obj_t * pFans[2] = { Gia_ObjFanin0(pObj), Gia_ObjFanin1(pObj) };
int fComp = ((Vec_IntEntry(vRes, i) >> 2) & 1) != 0;
int fFan0 = ((Vec_IntEntry(vRes, Gia_ObjFaninId0(pObj, i)) >> 1) & 1) == 0 && Gia_ObjIsAnd(pFans[0]);
int fFan1 = ((Vec_IntEntry(vRes, Gia_ObjFaninId1(pObj, i)) >> 1) & 1) == 0 && Gia_ObjIsAnd(pFans[1]);
if ( Vec_IntEntry(vRes, i) & 1 )
Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, !fComp), -1 );
Vec_IntWriteEntry( vMapping, Abc_Var2Lit(i, fComp), Vec_IntSize(vMapping) );
if ( fFan0 && fFan1 ) {
Vec_IntPush( vMapping, 4 );
if ( !Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) ) {
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) );
}
else {
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) );
}
if ( Gia_ObjFaninC0(pObj) && Gia_ObjFaninC1(pObj) )
Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI22 : GIA_GATE2_AOI22 );
else if ( !Gia_ObjFaninC0(pObj) && !Gia_ObjFaninC1(pObj) )
Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN4 : GIA_GATE2_NOR4 );
else
Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI211 : GIA_GATE2_AOI211 );
} else if ( fFan0 ) {
Vec_IntPush( vMapping, 3 );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC0(pFans[0]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[0]), !(fComp ^ Gia_ObjFaninC0(pObj) ^ Gia_ObjFaninC1(pFans[0]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) );
if ( Gia_ObjFaninC0(pObj) )
Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI21 : GIA_GATE2_AOI21 );
else
Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN3 : GIA_GATE2_NOR3 );
} else if ( fFan1 ) {
Vec_IntPush( vMapping, 3 );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC0(pFans[1]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pFans[1]), !(fComp ^ Gia_ObjFaninC1(pObj) ^ Gia_ObjFaninC1(pFans[1]))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) );
if ( Gia_ObjFaninC1(pObj) )
Vec_IntPush( vMapping, fComp ? GIA_GATE2_OAI21 : GIA_GATE2_AOI21 );
else
Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN3 : GIA_GATE2_NOR3 );
} else {
Vec_IntPush( vMapping, 2 );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId0p(p, pObj), !(fComp ^ Gia_ObjFaninC0(pObj))) );
Vec_IntPush( vMapping, Abc_Var2Lit(Gia_ObjFaninId1p(p, pObj), !(fComp ^ Gia_ObjFaninC1(pObj))) );
Vec_IntPush( vMapping, fComp ? GIA_GATE2_NAN2 : GIA_GATE2_NOR2 );
}
}
return vMapping;
}
Gia_Man_t * Gia_ManDeriveKSatMapping( Vec_Int_t * vRes, int * pMap, int nIns, int nNodes, int fVerbose )
{
Vec_Int_t * vGuide = Vec_IntStart( 1000 );
Gia_Man_t * pNew = Gia_ManStart( nIns + nNodes + 2 );
pNew->pName = Abc_UtilStrsav( "test" );
int i, nSave = 0, pCopy[256] = {0};
for ( i = 1; i <= nIns; i++ )
pCopy[i] = Gia_ManAppendCi( pNew );
for ( i = nIns; i < nIns+nNodes; i++ ) {
int iFan0 = Gia_KSatFindFan( pMap, i, 0, vRes );
int iFan1 = Gia_KSatFindFan( pMap, i, 1, vRes );
if ( iFan0 == iFan1 )
pCopy[i+1] = pCopy[iFan0+1];
else if ( Gia_KSatValAnd(pMap, i, vRes) )
pCopy[i+1] = Gia_ManAppendAnd( pNew, pCopy[iFan0+1], pCopy[iFan1+1] );
else
pCopy[i+1] = Gia_ManAppendOr( pNew, pCopy[iFan0+1], pCopy[iFan1+1] );
pCopy[i+1] = Abc_LitNotCond( pCopy[i+1], Gia_KSatValInv(pMap, i, vRes) );
if ( iFan0 == iFan1 )
*Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 1;
else if ( Gia_KSatValAnd(pMap, i, vRes) )
*Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 4 | (2*Gia_KSatValInv(pMap, i, vRes));
else
*Vec_IntEntryP(vGuide, Abc_Lit2Var(pCopy[i+1])) ^= 8 | (2*Gia_KSatValInv(pMap, i, vRes));
if ( fVerbose ) {
if ( i == nIns+nNodes-1 )
printf( " F = " );
else
printf( "%2d = ", i );
if ( iFan0 == iFan1 )
printf( "INV( %d )\n", iFan0 );
else if ( Gia_KSatValAnd(pMap, i, vRes) )
printf( "%sAND( %d, %d )\n", Gia_KSatValInv(pMap, i, vRes) ? "N":"", iFan0, iFan1 );
else
printf( "%sOR( %d, %d )\n", Gia_KSatValInv(pMap, i, vRes) ? "N":"", iFan0, iFan1 );
nSave += (iFan0 == iFan1) || !Gia_KSatValInv(pMap, i, vRes);
if ( i == nIns+nNodes-1 )
printf( "Solution cost = %d\n", 2*(2*nNodes - nSave) );
}
}
Gia_ManAppendCo( pNew, pCopy[nIns+nNodes] );
//pNew->vCellMapping = Gia_ManDeriveKSatMappingArray( pNew, vGuide );
Vec_IntFree( vGuide );
return pNew;
}
word Gia_ManGetTruth( Gia_Man_t * p )
{
Gia_Obj_t * pObj; int i, Id;
word pFuncs[256] = {0}, Const[2] = {0, ~(word)0};
assert( Gia_ManObjNum(p) <= 256 );
Gia_ManForEachCiId( p, Id, i )
pFuncs[Id] = s_Truths6[i];
Gia_ManForEachAnd( p, pObj, i )
pFuncs[i] = (Const[Gia_ObjFaninC0(pObj)] ^ pFuncs[Gia_ObjFaninId0(pObj, i)]) & (Const[Gia_ObjFaninC1(pObj)] ^ pFuncs[Gia_ObjFaninId1(pObj, i)]);
pObj = Gia_ManCo(p, 0);
return Const[Gia_ObjFaninC0(pObj)] ^ pFuncs[Gia_ObjFaninId0p(p, pObj)];
}
Gia_Man_t * Gia_ManKSatMapping( word Truth, int nIns, int nNodes, int nBound, int Seed, int fMultiLevel, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv, char * pGuide )
{
abctime clkStart = Abc_Clock();
Gia_Man_t * pNew = NULL;
srand(time(NULL));
int Status, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFFF;
char pFileNameI[32]; sprintf( pFileNameI, "_%06x_.cnf", Rand );
char pFileNameO[32]; sprintf( pFileNameO, "_%06x_.out", Rand );
int nVars = 0, * pMap = Gia_KSatMapInit( nIns, nNodes, Truth, &nVars );
Vec_Str_t * vStr = Gia_ManKSatCnf( pMap, nIns, nNodes, nBound/2, fMultiLevel, pGuide );
if ( !Gia_ManDumpCnf(pFileNameI, vStr, nVars) ) {
Vec_StrFree( vStr );
return NULL;
}
if ( fVerbose )
printf( "Vars = %d. Nodes = %d. Cardinality bound = %d. SAT vars = %d. SAT clauses = %d. Conflict limit = %d. Timeout = %d.\n",
nIns, nNodes, nBound, nVars, Vec_StrCountEntry(vStr, '\n'), nBTLimit, nTimeout );
Vec_Int_t * vRes = Gia_RunKadical( pFileNameI, pFileNameO, Seed, nBTLimit, nTimeout, 1, &Status );
unlink( pFileNameI );
//unlink( pFileNameO );
if ( fKeepFile ) Gia_ManDumpCnf2( vStr, nVars, argc, argv, Abc_Clock() - clkStart, Status );
Vec_StrFree( vStr );
if ( vRes == NULL )
return 0;
Vec_IntDrop( vRes, 0 );
pNew = Gia_ManDeriveKSatMapping( vRes, pMap, nIns, nNodes, fVerbose );
printf( "Verification %s. ", Truth == Gia_ManGetTruth(pNew) ? "passed" : "failed" );
Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart );
Vec_IntFree( vRes );
ABC_FREE( pMap );
return pNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

View File

@ -3199,7 +3199,7 @@ Vec_Int_t * Gia_ManRelDeriveSimple( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t
void Gia_ManRelSolve( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_Int_t * vOuts, Vec_Int_t * vRel, Vec_Int_t * vDivs )
{
extern Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose );
extern Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose, int fCard, char * pGuide );
int i, m, iObj, Entry, iMint = 0, nMints = Vec_IntSize(vRel) - Vec_IntCountEntry(vRel, -1);
Vec_Wrd_t * vSimsIn = Vec_WrdStart( nMints );
@ -3232,7 +3232,7 @@ void Gia_ManRelSolve( Gia_Man_t * p, Vec_Wrd_t * vSims, Vec_Int_t * vIns, Vec_In
}
assert( iMint == nMints );
printf( "Created %d minterms.\n", iMint );
Exa4_ManGenTest( vSimsIn, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), 10, 0, 0, 0, 0, 0, 1 );
Exa4_ManGenTest( vSimsIn, vSimsOut, Vec_IntSize(vIns), Vec_IntSize(vDivs), Vec_IntSize(vOuts), 10, 0, 0, 0, 0, 0, 1, 0, NULL );
Vec_WrdFree( vSimsIn );
Vec_WrdFree( vSimsOut );
}

View File

@ -600,7 +600,7 @@ Aig_Man_t * Iso_ManTest888( Aig_Man_t * pAig1, int fVerbose )
Vec_Int_t * vMap;
pNtk = Abc_NtkFromAigPhase( pAig1 );
Abc_NtkPermute( pNtk, 1, 0, 1, NULL );
Abc_NtkPermute( pNtk, 1, 0, 1, NULL, NULL, NULL );
pAig2 = Abc_NtkToDar( pNtk, 0, 1 );
Abc_NtkDelete( pNtk );

View File

@ -792,7 +792,7 @@ extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateWithNodes( Vec_Ptr_t * vSops );
extern ABC_DLL void Abc_NtkDelete( Abc_Ntk_t * pNtk );
extern ABC_DLL void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk );
extern ABC_DLL void Abc_NtkMakeComb( Abc_Ntk_t * pNtk, int fRemoveLatches );
extern ABC_DLL void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile );
extern ABC_DLL void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pInPermFile, char * pOutPermFile, char * pFlopPermFile );
extern ABC_DLL void Abc_NtkUnpermute( Abc_Ntk_t * pNtk );
extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromSops( char * pName, Vec_Ptr_t * vSops );
extern ABC_DLL Abc_Ntk_t * Abc_NtkCreateFromGias( char * pName, Vec_Ptr_t * vGias, Gia_Man_t * pMulti );

View File

@ -1727,6 +1727,58 @@ void Abc_NtkMakeSeq( Abc_Ntk_t * pNtk, int nLatchesToAdd )
}
/**Function*************************************************************
Synopsis [Keeps POs in the array.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkSelectPos( Abc_Ntk_t * pNtkInit, Vec_Int_t * vPoIds )
{
Abc_Ntk_t * pNtk;
Vec_Ptr_t * vPosLeft;
Vec_Ptr_t * vCosLeft;
Abc_Obj_t * pNodePo;
int i, Index;
assert( !Abc_NtkIsNetlist(pNtkInit) );
assert( Abc_NtkHasOnlyLatchBoxes(pNtkInit) );
pNtk = Abc_NtkDup( pNtkInit );
if ( Abc_NtkPoNum(pNtk) == 1 )
return pNtk;
vPosLeft = Vec_PtrAlloc( Vec_IntSize(vPoIds) );
Vec_IntForEachEntry( vPoIds, Index, i ) {
Vec_PtrPush( vPosLeft, Abc_NtkPo(pNtk, Index) );
Vec_PtrWriteEntry( pNtk->vPos, Index, NULL );
}
// filter COs
vCosLeft = Vec_PtrDup( vPosLeft );
for ( i = Abc_NtkPoNum(pNtk); i < Abc_NtkCoNum(pNtk); i++ )
Vec_PtrPush( vCosLeft, Abc_NtkCo(pNtk, i) );
// remove remaiing POs
Abc_NtkForEachPo( pNtk, pNodePo, i )
if ( pNodePo )
Abc_NtkDeleteObjPo( pNodePo );
// update arrays
Vec_PtrFree( pNtk->vPos ); pNtk->vPos = vPosLeft;
Vec_PtrFree( pNtk->vCos ); pNtk->vCos = vCosLeft;
// clean the network
if ( Abc_NtkIsStrash(pNtk) ) {
Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" );
}
else {
if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" );
}
if ( !Abc_NtkCheck( pNtk ) )
fprintf( stdout, "Abc_NtkMakeComb(): Network check has failed.\n" );
return pNtk;
}
/**Function*************************************************************
Synopsis [Removes all POs, except one.]
@ -1779,11 +1831,11 @@ Abc_Ntk_t * Abc_NtkMakeOnePo( Abc_Ntk_t * pNtkInit, int Output, int nRange )
if ( Abc_NtkIsStrash(pNtk) )
{
Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc );
printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" );
if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"scl\") to get rid of dangling logic.\n" );
}
else
{
printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" );
if ( Abc_NtkLatchNum(pNtk) ) printf( "Run sequential cleanup (\"st; scl\") to get rid of dangling logic.\n" );
}
if ( !Abc_NtkCheck( pNtk ) )
@ -2007,11 +2059,11 @@ void Abc_NtkRemovePo( Abc_Ntk_t * pNtk, int iOutput, int fRemoveConst0 )
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NtkReadFlopPerm( char * pFileName, int nFlops )
Vec_Int_t * Abc_NtkReadSignalPerm2( char * pFileName, int nSignals )
{
char Buffer[1000];
FILE * pFile;
Vec_Int_t * vFlops;
Vec_Int_t * vSignals;
int iFlop = -1;
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
@ -2019,30 +2071,63 @@ Vec_Int_t * Abc_NtkReadFlopPerm( char * pFileName, int nFlops )
printf( "Cannot open input file \"%s\".\n", pFileName );
return NULL;
}
vFlops = Vec_IntAlloc( nFlops );
vSignals = Vec_IntAlloc( nSignals );
while ( fgets( Buffer, 1000, pFile ) != NULL )
{
if ( Buffer[0] == ' ' || Buffer[0] == '\r' || Buffer[0] == '\n' )
continue;
iFlop = atoi( Buffer );
if ( iFlop < 0 || iFlop >= nFlops )
if ( iFlop < 0 || iFlop >= nSignals )
{
printf( "Flop ID (%d) is out of range.\n", iFlop );
printf( "The zero-based signal ID (%d) is out of range.\n", iFlop );
fclose( pFile );
Vec_IntFree( vFlops );
Vec_IntFree( vSignals );
return NULL;
}
Vec_IntPush( vFlops, iFlop );
Vec_IntPush( vSignals, iFlop );
}
fclose( pFile );
if ( Vec_IntSize(vFlops) != nFlops )
if ( Vec_IntSize(vSignals) != nSignals )
{
printf( "The number of flops read in from file (%d) is different from the number of flops in the circuit (%d).\n", iFlop, nFlops );
Vec_IntFree( vFlops );
printf( "The number of indexes read in from file (%d) is different from the number of signals in the circuit (%d).\n", Vec_IntSize(vSignals), nSignals );
Vec_IntFree( vSignals );
return NULL;
}
return vFlops;
return vSignals;
}
Vec_Int_t * Abc_NtkReadSignalPerm( char * pFileName, int nSignals )
{
int Num = -1;
Vec_Int_t * vSignals;
FILE * pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Cannot open input file \"%s\".\n", pFileName );
return NULL;
}
vSignals = Vec_IntAlloc( nSignals );
while ( fscanf( pFile, "%d", &Num ) == 1 )
{
if ( Num <= 0 || Num > nSignals )
{
printf( "The one-based signal ID (%d) is out of range (%d).\n", Num, nSignals );
fclose( pFile );
Vec_IntFree( vSignals );
return NULL;
}
Vec_IntPush( vSignals, Num-1 );
}
fclose( pFile );
if ( Vec_IntSize(vSignals) != nSignals )
{
printf( "The number of indexes read in from file (%d) is different from the number of signals in the circuit (%d).\n", Vec_IntSize(vSignals), nSignals );
Vec_IntFree( vSignals );
return NULL;
}
return vSignals;
}
/**Function*************************************************************
Synopsis []
@ -2054,61 +2139,98 @@ Vec_Int_t * Abc_NtkReadFlopPerm( char * pFileName, int nFlops )
SeeAlso []
***********************************************************************/
void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pFlopPermFile )
void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, char * pInPermFile, char * pOutPermFile, char * pFlopPermFile )
{
Abc_Obj_t * pTemp;
Vec_Int_t * vInputs, * vOutputs, * vFlops, * vTemp;
int i, k, Entry;
// start permutation arrays
if ( pInPermFile )
{
vInputs = Abc_NtkReadSignalPerm( pInPermFile, Abc_NtkPiNum(pNtk) );
if ( vInputs == NULL )
return;
fInputs = 1;
}
else
vInputs = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) );
if ( pOutPermFile )
{
vOutputs = Abc_NtkReadSignalPerm( pOutPermFile, Abc_NtkPoNum(pNtk) );
if ( vOutputs == NULL )
return;
fOutputs = 1;
}
else
vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) );
if ( pFlopPermFile )
{
vFlops = Abc_NtkReadFlopPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) );
vFlops = Abc_NtkReadSignalPerm( pFlopPermFile, Abc_NtkLatchNum(pNtk) );
if ( vFlops == NULL )
return;
fInputs = 0;
fOutputs = 0;
fFlops = 0;
fFlops = 1;
}
else
vFlops = Vec_IntStartNatural( Abc_NtkLatchNum(pNtk) );
vInputs = Vec_IntStartNatural( Abc_NtkPiNum(pNtk) );
vOutputs = Vec_IntStartNatural( Abc_NtkPoNum(pNtk) );
// permute inputs
Vec_Ptr_t * vCis = Vec_PtrDup(pNtk->vCis);
Vec_Ptr_t * vCos = Vec_PtrDup(pNtk->vCos);
Vec_Ptr_t * vFfs = Vec_PtrDup(pNtk->vBoxes);
if ( fInputs )
for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ )
{
k = rand() % Abc_NtkPiNum(pNtk);
// swap indexes
Entry = Vec_IntEntry( vInputs, i );
Vec_IntWriteEntry( vInputs, i, Vec_IntEntry(vInputs, k) );
Vec_IntWriteEntry( vInputs, k, Entry );
// swap PIs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i );
Vec_PtrWriteEntry( pNtk->vPis, i, Vec_PtrEntry(pNtk->vPis, k) );
Vec_PtrWriteEntry( pNtk->vPis, k, pTemp );
// swap CIs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i );
Vec_PtrWriteEntry( pNtk->vCis, i, Vec_PtrEntry(pNtk->vCis, k) );
Vec_PtrWriteEntry( pNtk->vCis, k, pTemp );
if ( pInPermFile )
{
k = Vec_IntEntry( vInputs, i );
pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCis, k );
Vec_PtrWriteEntry( pNtk->vPis, i, pTemp );
Vec_PtrWriteEntry( pNtk->vCis, i, pTemp );
}
else
{
k = rand() % Abc_NtkPiNum(pNtk);
// swap indexes
Entry = Vec_IntEntry( vInputs, i );
Vec_IntWriteEntry( vInputs, i, Vec_IntEntry(vInputs, k) );
Vec_IntWriteEntry( vInputs, k, Entry );
// swap PIs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPis, i );
Vec_PtrWriteEntry( pNtk->vPis, i, Vec_PtrEntry(pNtk->vPis, k) );
Vec_PtrWriteEntry( pNtk->vPis, k, pTemp );
// swap CIs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, i );
Vec_PtrWriteEntry( pNtk->vCis, i, Vec_PtrEntry(pNtk->vCis, k) );
Vec_PtrWriteEntry( pNtk->vCis, k, pTemp );
}
//printf( "Swapping PIs %d and %d.\n", i, k );
}
// permute outputs
if ( fOutputs )
for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ )
{
k = rand() % Abc_NtkPoNum(pNtk);
// swap indexes
Entry = Vec_IntEntry( vOutputs, i );
Vec_IntWriteEntry( vOutputs, i, Vec_IntEntry(vOutputs, k) );
Vec_IntWriteEntry( vOutputs, k, Entry );
// swap POs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i );
Vec_PtrWriteEntry( pNtk->vPos, i, Vec_PtrEntry(pNtk->vPos, k) );
Vec_PtrWriteEntry( pNtk->vPos, k, pTemp );
// swap COs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i );
Vec_PtrWriteEntry( pNtk->vCos, i, Vec_PtrEntry(pNtk->vCos, k) );
Vec_PtrWriteEntry( pNtk->vCos, k, pTemp );
if ( pOutPermFile )
{
k = Vec_IntEntry( vOutputs, i );
pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCos, k );
Vec_PtrWriteEntry( pNtk->vPos, i, pTemp );
Vec_PtrWriteEntry( pNtk->vCos, i, pTemp );
}
else
{
k = rand() % Abc_NtkPoNum(pNtk);
// swap indexes
Entry = Vec_IntEntry( vOutputs, i );
Vec_IntWriteEntry( vOutputs, i, Vec_IntEntry(vOutputs, k) );
Vec_IntWriteEntry( vOutputs, k, Entry );
// swap POs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vPos, i );
Vec_PtrWriteEntry( pNtk->vPos, i, Vec_PtrEntry(pNtk->vPos, k) );
Vec_PtrWriteEntry( pNtk->vPos, k, pTemp );
// swap COs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, i );
Vec_PtrWriteEntry( pNtk->vCos, i, Vec_PtrEntry(pNtk->vCos, k) );
Vec_PtrWriteEntry( pNtk->vCos, k, pTemp );
}
//printf( "Swapping POs %d and %d.\n", i, k );
}
// permute flops
@ -2116,26 +2238,42 @@ void Abc_NtkPermute( Abc_Ntk_t * pNtk, int fInputs, int fOutputs, int fFlops, ch
if ( fFlops )
for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ )
{
k = rand() % Abc_NtkLatchNum(pNtk);
// swap indexes
Entry = Vec_IntEntry( vFlops, i );
Vec_IntWriteEntry( vFlops, i, Vec_IntEntry(vFlops, k) );
Vec_IntWriteEntry( vFlops, k, Entry );
// swap flops
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i );
Vec_PtrWriteEntry( pNtk->vBoxes, i, Vec_PtrEntry(pNtk->vBoxes, k) );
Vec_PtrWriteEntry( pNtk->vBoxes, k, pTemp );
// swap CIs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i );
Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, Vec_PtrEntry(pNtk->vCis, Abc_NtkPiNum(pNtk)+k) );
Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+k, pTemp );
// swap COs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i );
Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, Vec_PtrEntry(pNtk->vCos, Abc_NtkPoNum(pNtk)+k) );
Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+k, pTemp );
if ( pFlopPermFile )
{
k = Vec_IntEntry( vFlops, i );
pTemp = (Abc_Obj_t *)Vec_PtrEntry( vFfs, k );
Vec_PtrWriteEntry( pNtk->vBoxes, i, pTemp );
pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCis, Abc_NtkPiNum(pNtk)+k );
Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, pTemp );
pTemp = (Abc_Obj_t *)Vec_PtrEntry( vCos, Abc_NtkPoNum(pNtk)+k );
Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, pTemp );
}
else
{
k = rand() % Abc_NtkLatchNum(pNtk);
// swap indexes
Entry = Vec_IntEntry( vFlops, i );
Vec_IntWriteEntry( vFlops, i, Vec_IntEntry(vFlops, k) );
Vec_IntWriteEntry( vFlops, k, Entry );
// swap flops
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vBoxes, i );
Vec_PtrWriteEntry( pNtk->vBoxes, i, Vec_PtrEntry(pNtk->vBoxes, k) );
Vec_PtrWriteEntry( pNtk->vBoxes, k, pTemp );
// swap CIs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i );
Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+i, Vec_PtrEntry(pNtk->vCis, Abc_NtkPiNum(pNtk)+k) );
Vec_PtrWriteEntry( pNtk->vCis, Abc_NtkPiNum(pNtk)+k, pTemp );
// swap COs
pTemp = (Abc_Obj_t *)Vec_PtrEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i );
Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+i, Vec_PtrEntry(pNtk->vCos, Abc_NtkPoNum(pNtk)+k) );
Vec_PtrWriteEntry( pNtk->vCos, Abc_NtkPoNum(pNtk)+k, pTemp );
}
//printf( "Swapping flops %d and %d.\n", i, k );
}
Vec_PtrFree(vCis);
Vec_PtrFree(vCos);
Vec_PtrFree(vFfs);
// invert arrays
vInputs = Vec_IntInvert( vTemp = vInputs, -1 );
Vec_IntFree( vTemp );

View File

@ -21,6 +21,11 @@
#include "abc.h"
#include "bool/kit/kit.h"
#ifdef _MSC_VER
# include <intrin.h>
# define __builtin_popcount __popcnt
#endif
ABC_NAMESPACE_IMPL_START
@ -1135,6 +1140,31 @@ Vec_Ptr_t * Abc_SopFromTruthsHex( char * pTruth )
return vRes;
}
Vec_Ptr_t * Abc_SopGenerateCounters( int nVars )
{
int m, i, o, nOuts = Abc_Base2Log( nVars + 1 );
Vec_Ptr_t * vRes = Vec_PtrAlloc( nOuts );
for ( o = 0; o < nOuts; o++ )
{
Vec_Str_t * vStr = Vec_StrAlloc( 1000 );
for ( m = 0; m < (1 << nVars); m++ ) {
int nOnes = __builtin_popcount(m);
if ( !((nOnes >> o) & 1) )
continue;
for ( i = 0; i < nVars; i++ )
Vec_StrPush( vStr, ((m >> i) & 1) ? '1' : '0' );
Vec_StrPush( vStr, ' ' );
Vec_StrPush( vStr, '1' );
Vec_StrPush( vStr, '\n' );
}
Vec_StrPush( vStr, '\0' );
//printf( "%s\n", Vec_StrArray(vStr) );
Vec_PtrPush( vRes, Vec_StrReleaseArray(vStr) );
Vec_StrFree( vStr );
}
return vRes;
}
/**Function*************************************************************
Synopsis [Creates one encoder node.]

View File

@ -24,6 +24,7 @@
#include "bool/dec/dec.h"
#include "opt/fxu/fxu.h"
#include "aig/miniaig/ndr.h"
#include "misc/util/utilTruth.h"
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
@ -3352,6 +3353,211 @@ Abc_Ntk_t * Abc_NtkFromArray()
return pNtkNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_PrintAT( Vec_Int_t * vRanks )
{
int i, Entry;
Vec_IntForEachEntryReverse( vRanks, Entry, i )
if ( Entry == 0 )
printf( " " );
else
printf( "%4d", Entry );
//printf( "\n" );
}
int Abc_NtkMatchGpcPattern( Vec_Int_t * vRanks, int i, char * pGPC )
{
int k, Cur, Min = ABC_INFINITY;
for ( k = 0; pGPC[k] != ':' && i+k < Vec_IntSize(vRanks); k++ ) {
if ( Abc_TtReadHexDigit(pGPC[k]) == 0 )
continue;
Cur = Vec_IntEntry(vRanks, i+k) / Abc_TtReadHexDigit(pGPC[k]);
if ( Min > Cur )
Min = Cur;
}
return Min;
}
void Abc_NtkUpdateGpcPattern( Vec_Int_t * vRank, int i, char * pGPC, int nGpcs, Vec_Int_t * vRank2, Vec_Int_t * vLevel )
{
int k; char * pOut = strstr(pGPC, ":");
assert( pOut && pOut[0] == ':' );
pOut++;
Vec_IntAddToEntry( vLevel, i, nGpcs );
for ( k = 0; pGPC[k] != ':'; k++ )
Vec_IntAddToEntry( vRank, i+k, -nGpcs * Abc_TtReadHexDigit(pGPC[k]) );
for ( k = 0; pOut[k] != ':'; k++ )
Vec_IntAddToEntry( vRank2, i+k, nGpcs * Abc_TtReadHexDigit(pOut[k]) );
}
int Abc_NtkGetGpcLutCount( char * pGPC )
{
char * pOut = strstr(pGPC, ":");
char * pLut = strstr(pOut+1, ":");
return atoi(pLut+1);
}
static inline int Vec_WecSum( Vec_Wec_t * p )
{
Vec_Int_t * vVec;
int i, Counter = 0;
Vec_WecForEachLevel( p, vVec, i )
Counter += Vec_IntSum(vVec);
return Counter;
}
char ** Abc_NtkTransformGPCs( char ** pGPCs, int nGPCs )
{
char * pOut, * pLut, ** pRes = ABC_ALLOC( char *, nGPCs );
int i, k, nLength;
for ( i = 0; i < nGPCs; i++ ) {
pRes[i] = Abc_UtilStrsav(pGPCs[i]);
pOut = strstr(pRes[i], ":");
nLength = (int)(pOut-pRes[i]);
for ( k = 0; k < nLength/2; k++ )
ABC_SWAP( char, pRes[i][k], pRes[i][nLength-1-k] )
pLut = strstr(pOut+1, ":");
nLength = (int)(pLut-pOut-1);
for ( k = 0; k < nLength/2; k++ )
ABC_SWAP( char, pOut[1+k], pOut[1+nLength-1-k] )
}
return pRes;
}
int Abc_NtkCheckGpc( char * pGPC, char * pGPC0 )
{
int RetValue = 0, k, Sum[2] = {0};
char * pOut = strstr(pGPC, ":");
for ( k = 0; pGPC[k] != ':'; k++ )
Sum[0] += (1 << k) * Abc_TtReadHexDigit(pGPC[k]);
for ( k = 0; pOut[1+k] != ':'; k++ )
Sum[1] += (1 << k) * Abc_TtReadHexDigit(pOut[1+k]);
//printf( "GPC %s has input sum %d and output sum %d\n", pGPC0, Sum[0], Sum[1] );
if ( Sum[0]+1 > (1 << Abc_Base2Log(Sum[1]+1)) )
printf( "The largest value of GPC inputs (%d) exceeds the capacity of outputs (%d) for GPC %s.\n", Sum[0], Sum[1], pGPC0 );
else if ( Sum[1]+1 > (1 << Abc_Base2Log(Sum[0]+1)) )
printf( "The largest value of GPC outputs (%d) exceeds the capacity of inputs (%d) for GPC %s.\n", Sum[1], Sum[0], pGPC0 );
else
RetValue = 1;
return RetValue;
}
void Abc_NtkATMap( int nXVars, int nYVars, int nAdder, char ** pGPCs0, int nGPCs, int fReturn, int fVerbose )
{
abctime clkStart = Abc_Clock();
char ** pGPCs = Abc_NtkTransformGPCs(pGPCs0, nGPCs);
int i, nGPCluts[100] = {0};
for ( i = 0; i < nGPCs; i++ )
if ( !Abc_NtkCheckGpc(pGPCs[i], pGPCs0[i]) )
return;
for ( i = 0; i < nGPCs; i++ )
nGPCluts[i] = Abc_NtkGetGpcLutCount(pGPCs[i]);
int x, n, Entry, iLevel = 0, Sum = 0, nGpcs = 0, nBits, fFinished, nRcaLuts = 0, nLuts = 0;
for ( x = 0; x < nXVars; x++ )
Sum += (1 << x) * nYVars;
nBits = Abc_Base2Log( Sum+1 );
printf( "Rectangular adder tree (X=%d Y=%d Sum=%d Out=%d) mapped with", nXVars, nYVars, Sum, nBits );
for ( i = 0; i < nGPCs; i++ )
printf( " GPC%d=%s", i, pGPCs0[i] );
printf( "\n" );
Vec_Int_t * vLevel;
Vec_Int_t * vRank[3] = { Vec_IntAlloc(100), Vec_IntAlloc(100), Vec_IntAlloc(100) };
Vec_Wec_t ** vGPCs = ABC_ALLOC( Vec_Wec_t *, nGPCs );
for ( i = 0; i < nGPCs; i++ )
vGPCs[i] = Vec_WecAlloc(100);
Vec_IntFill( vRank[0], nBits, 0 );
for ( x = 0; x < nXVars; x++ )
Vec_IntAddToEntry( vRank[0], x, nYVars );
if ( fVerbose ) {
printf( "Ranks: " );
for ( i = nBits-1; i >= 0; i-- )
printf( "%4d", i );
printf( " : " );
for ( i = nBits-1; i >= 0; i-- )
printf( "%4d", i );
printf( " LUT6\n" );
}
for ( n = 0; n < nGPCs; n++ )
for ( i = 0, fFinished = 0; !fFinished; i++ )
{
int fAdded = 0;
vLevel = Vec_WecPushLevel( vGPCs[n] );
Vec_IntFill( vLevel, nBits, 0 );
Vec_IntFill( vRank[1], nBits, 0 );
Vec_IntClear( vRank[2] );
Vec_IntAppend( vRank[2], vRank[0] );
fFinished = 1;
if ( Vec_IntFindMax(vRank[0]) > nAdder ) {
for ( x = 0; x < nBits; x++ )
if ( (nGpcs = Abc_NtkMatchGpcPattern(vRank[0], x, pGPCs[n])) )
Abc_NtkUpdateGpcPattern(vRank[0], x, pGPCs[n], nGpcs, vRank[1], vLevel), fFinished = 0, fAdded = 1;
nLuts += Vec_IntSum(vLevel) * nGPCluts[n];
Vec_IntForEachEntry( vRank[1], Entry, x )
Vec_IntAddToEntry( vRank[0], x, Entry );
}
if ( fVerbose && (fAdded || Vec_IntFindMax(vRank[2]) <= nAdder ) ) {
printf( "Lev%02d: ", iLevel++ );
Abc_PrintAT( vRank[2] );
if ( fAdded ) {
printf( " GPC%d: ", n );
Abc_PrintAT( vLevel );
printf( " %4d", Vec_IntSum(vLevel) * nGPCluts[n] );
}
else if ( Vec_IntFindMax(vRank[2]) <= nAdder ) {
printf( " ADD%d: ", nAdder );
for ( x = 0; x < nBits; x++ )
if ( Vec_IntEntry(vRank[2], x) > 1 )
break;
for ( i = nBits-1; i >= x; i-- )
printf( "%4d", 1 );
for ( ; i >= 0; i-- )
printf( " " );
printf( " %4d", (nBits-x)*(nAdder == 4 ? 2 : 1) );
}
printf( "\n" );
}
if ( fAdded ) {
if ( fReturn ) {
fFinished = 1;
n = -1;
}
}
else if ( Vec_IntFindMax(vRank[2]) <= nAdder ) {
fFinished = 1;
n = nGPCs;
}
}
if ( Vec_IntFindMax(vRank[0]) > nAdder )
printf( "Synthesis of the adder tree is incomplete. Try using the full adder \"3:11:1\" as the last GPC.\n" );
else if ( fVerbose && Vec_IntFindMax(vRank[0]) <= nAdder ) {
printf( "Lev%02d: ", iLevel++ );
for ( i = nBits-1; i >= 0; i-- )
printf( "%4d", 1 );
printf( "\n" );
}
printf( "Statistics: " );
for ( n = 0; n < nGPCs; n++ )
printf( "GPC%d = %d. ", n, Vec_WecSum(vGPCs[n]) );
for ( x = 0; x < nBits; x++ )
if ( Vec_IntEntry(vRank[0], x) > 1 )
break;
nRcaLuts = (nBits-x)*(nAdder == 4 ? 2 : 1);
printf( "ADD%d = %d. ", nAdder, nRcaLuts );
printf( "Total LUT count = %d. ", nLuts+nRcaLuts );
for ( i = 0; i < 3; i++ )
Vec_IntFree( vRank[i] );
for ( i = 0; i < nGPCs; i++ )
Vec_WecFree( vGPCs[i] );
ABC_FREE( vGPCs );
for ( i = 0; i < nGPCs; i++ )
ABC_FREE( pGPCs[i] );
ABC_FREE( pGPCs );
Abc_PrintTime( 0, "Total time", Abc_Clock() - clkStart );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

File diff suppressed because it is too large Load Diff

View File

@ -310,7 +310,10 @@ word * Abc_LutCascadeTruth( word * pLuts, int nVars )
Vec_WrdFree( vFuncs );
return pRes;
}
int Abc_LutCascadeCount( word * pLuts )
{
return (int)pLuts[0];
}
word * Abc_LutCascadeTest( Mini_Aig_t * p, int nLutSize, int fVerbose )
{
word * pLuts = Abc_LutCascadeGenTest();
@ -447,13 +450,14 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v
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;
}
int m, Myu = pGuide ? 1 << nRails : (Guide >> 48) & 0xFF;
int nEVars = Abc_Base2Log(Myu);
if ( nEVars > nRails ) {
printf( "Best Myu (%d) requires %d rails that is more than available (%d).\n", Myu, nEVars, nRails );
Vec_IntClear( vVarIDs );
return 0;
}
int nVars = Vec_IntSize(vVarIDs);
int mBVars = pGuide ? Abc_TtGetGuide(pGuide, Iter, vVarIDs, 0) : Guide & 0xFFFFFF;
int nBVars = __builtin_popcount(mBVars);
@ -500,17 +504,20 @@ static inline int Abc_LutCascadeDecStage( char * pGuide, int Iter, Vec_Wrd_t * v
Vec_IntShrink( vVarIDs, nFVars+nSVars+nEVars );
return nEVars;
}
static inline word * Abc_LutCascadeDec( char * pGuide, word * pTruth, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int fVerbose )
word * Abc_LutCascadeDec( char * pGuide, word * pTruth, int nVarsOrig, Vec_Int_t * vVarIDs, int nRails, int nLutSize, int fVerbose )
{
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, nVars );
for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ )
Vec_Wrd_t * vCas = Vec_WrdAlloc( 100 ); Vec_WrdPush( vCas, nVarsOrig );
for ( i = 0; Vec_IntSize(vVarIDs) > nLutSize; i++ ) {
nRVars = Abc_LutCascadeDecStage( pGuide, i, vFuncs, vVarIDs, nRVars, nRails, nLutSize, fVerbose, vCas );
if ( Vec_IntSize(vVarIDs) > 0 ) {
if ( nRVars == -1 )
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, -nVars );
Vec_WrdAddToEntry( vCas, 0, -nVarsOrig );
pRes = Vec_WrdReleaseArray(vCas);
}
Vec_WrdFree( vCas );
@ -614,39 +621,51 @@ Abc_Ntk_t * Abc_NtkLutCascade2( Abc_Ntk_t * pNtk, int nLutSize, int nLuts, int n
{
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));
word * pCopy = ABC_ALLOC( word, nWords );
Gia_Man_t * pGia = Abc_NtkStrashToGia( pNtk );
word * pTruth1 = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) );
Abc_Ntk_t * pNew = NULL;
Abc_Random(1);
for ( int Iter = 0; Iter < nIters; Iter++ ) {
word * pTruth1 = Gia_ObjComputeTruthTable( pGia, Gia_ManCo(pGia, 0) );
Abc_TtCopy( pCopy, pTruth1, nWords, 0 );
int nVars = Abc_NtkCiNum(pNtk);
Vec_Int_t * vVarIDs = Vec_IntStartNatural( nVars );
Abc_TtMinimumBase( pTruth1, Vec_IntArray(vVarIDs), nVars, &nVars );
if ( fVerbose ) {
if ( Vec_IntSize(vVarIDs) != nVars )
printf( "The support of the function is reduced from %d to %d variables.\n", Vec_IntSize(vVarIDs), nVars );
printf( "Decomposing %d-var function into %d-rail cascade of %d-LUTs", nVars, nRails, nLutSize );
if ( pGuide )
printf( " using structural info: %s", pGuide );
printf( ".\n" );
}
Vec_IntShrink( vVarIDs, nVars );
//word * pLuts = Abc_LutCascade2( pTruth1, nVars, nLutSize, nLuts, nRails, nIters, fVerbose );
word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, vVarIDs, nRails, nLutSize, fVerbose );
Abc_Ntk_t * pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, nVars, pNtk, nLutSize, fVerbose ) : NULL;
Vec_IntFree( vVarIDs );
if ( pLuts && fVerbose ) {
word * pTruth2 = Abc_LutCascadeTruth( pLuts, Abc_NtkCiNum(pNtk) );
if ( nVars < 9 ) {
printf("Function before: "); Abc_TtPrintHexRev( stdout, pTruth1, nVars ); printf( "\n" );
printf("Function after: "); Abc_TtPrintHexRev( stdout, pTruth2, nVars ); printf( "\n" );
int nVars = -1;
Vec_Int_t * vVarIDs = Vec_IntStartNatural( Abc_NtkCiNum(pNtk) );
Abc_TtMinimumBase( pTruth1, Vec_IntArray(vVarIDs), Abc_NtkCiNum(pNtk), &nVars );
Vec_IntShrink( vVarIDs, nVars );
if ( fVerbose ) {
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 );
if ( pGuide )
printf( " using structural info: %s", pGuide );
printf( ".\n" );
}
Abc_LutCascadePrint( pLuts );
ABC_FREE( pLuts );
ABC_FREE( pTruth2 );
word * pLuts = Abc_LutCascadeDec( pGuide, pTruth1, Abc_NtkCiNum(pNtk), vVarIDs, nRails, nLutSize, fVerbose );
pNew = pLuts ? Abc_NtkLutCascadeFromLuts( pLuts, Abc_NtkCiNum(pNtk), pNtk, nLutSize, fVerbose ) : NULL;
Vec_IntFree( vVarIDs );
if ( pLuts ) {
if ( fVerbose )
Abc_LutCascadePrint( pLuts );
word * pTruth2 = Abc_LutCascadeTruth( pLuts, Abc_NtkCiNum(pNtk) );
if ( !Abc_TtEqual(pCopy, pTruth2, nWords) ) {
printf( "Verification FAILED.\n" );
printf("Function before: "); Abc_TtPrintHexRev( stdout, pCopy, Abc_NtkCiNum(pNtk) ); printf( "\n" );
printf("Function after: "); Abc_TtPrintHexRev( stdout, pTruth2, Abc_NtkCiNum(pNtk) ); printf( "\n" );
}
else if ( fVerbose )
printf( "Verification passed.\n" );
ABC_FREE( pLuts );
ABC_FREE( pTruth2 );
break;
}
//ABC_FREE( pTruth1 );
}
ABC_FREE( pCopy );
Gia_ManStop( pGia );
//ABC_FREE( pTruth1 );
return pNew;
}
Abc_Ntk_t * Abc_NtkLutCascadeGen( int nLutSize, int nStages, int nRails, int nShared, int fVerbose )
@ -1079,6 +1098,279 @@ Abc_Ntk_t * Abc_NtkLutCascadeMap( Abc_Ntk_t * pNtk, int nLutsMax, int nIters, in
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Wrd_t * Abc_NtkLutCasReadTruths( char * pFileName, int nVarsOrig )
{
Vec_Wrd_t * vTruths = NULL;
int nWords = Abc_TtWordNum(nVarsOrig);
int nFileSize = Gia_FileSize( pFileName );
FILE * pFile = fopen( pFileName, "rb" );
if ( pFile == NULL ) { printf("Cannot open file \"%s\" for reading.\n", pFileName); return NULL; }
word * pTruth = ABC_ALLOC( word, 2*nWords );
char * pToken, * pLine = ABC_ALLOC( char, nFileSize );
for ( int i = 0; fgets(pLine, nFileSize, pFile); i++ ) {
pToken = strtok(pLine, " ,\n\r\r");
if ( pToken == NULL )
continue;
if ( pToken[0] == '0' && pToken[1] == 'x' )
pToken += 2;
if ( strlen(pToken) != (1 << (nVarsOrig-2)) ) {
printf( "Line %d has truth table of size %d while expected size is %d.\n", i, (int)strlen(pToken), 1 << (nVarsOrig-2) );
Vec_WrdFreeP( &vTruths );
break;
}
if ( !Abc_TtReadHex( pTruth, pToken ) ) {
printf( "Line %d has truth table that cannot be read correctly (%s).\n", i, pToken );
Vec_WrdFreeP( &vTruths );
break;
}
if ( vTruths == NULL )
vTruths = Vec_WrdAlloc( 10000 );
for ( int w = 0; w < nWords; w++ )
Vec_WrdPush( vTruths, pTruth[w] );
}
ABC_FREE( pTruth );
ABC_FREE( pLine );
fclose( pFile );
return vTruths;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkLutCascadeFile( char * pFileName, int nVarsOrig, int nLutSize, int nLuts, int nRails, int nIters, int fVerbose, int fVeryVerbose )
{
abctime clkStart = Abc_Clock();
int i, Sum = 0, nTotalLuts = 0, nWords = Abc_TtWordNum(nVarsOrig);
Vec_Wrd_t * vTruths = NULL;
if ( strstr(pFileName, ".txt") )
vTruths = Abc_NtkLutCasReadTruths( pFileName, nVarsOrig );
else
vTruths = Vec_WrdReadBin( pFileName, 0 );
if ( vTruths == NULL )
return;
int nFuncs = Vec_WrdSize(vTruths)/nWords;
if ( Vec_WrdSize(vTruths) != nFuncs * nWords ) {
printf( "The files size (%d bytes) does not match the truth table size (%d) for the given number of functions (%d).\n", 8*Vec_WrdSize(vTruths), 8*nWords, nFuncs );
Vec_WrdFree( vTruths );
return;
}
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);
for ( i = 0; i < nFuncs; i++ )
{
word * pTruth = Vec_WrdEntryP( vTruths, i*nWords );
Abc_TtCopy( pCopy, pTruth, nWords, 0 );
if ( fVeryVerbose )
printf( "\n" );
if ( fVerbose || fVeryVerbose )
printf( "Function %3d : ", i );
if ( fVeryVerbose )
Abc_TtPrintHexRev( stdout, pTruth, nVarsOrig ), printf( "\n" );
//continue;
int nVars = -1;
Vec_Int_t * vVarIDs = Vec_IntStartNatural( nVarsOrig );
Abc_TtMinimumBase( pTruth, Vec_IntArray(vVarIDs), nVarsOrig, &nVars );
Vec_IntShrink( vVarIDs, nVars );
if ( fVeryVerbose ) {
if ( nVarsOrig != nVars )
printf( "The support of the function is reduced from %d to %d variables.\n", nVarsOrig, nVars );
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 );
Vec_IntFree( vVarIDs );
if ( pLuts == NULL ) {
if ( ++Iter < nIters ) {
i--;
continue;
}
Iter = 0;
if ( fVerbose || fVeryVerbose )
printf( "Not decomposable.\n" );
continue;
}
Iter = 0;
Sum++;
nTotalLuts += Abc_LutCascadeCount(pLuts);
LutStats[Abc_LutCascadeCount(pLuts)]++;
word * pTruth2 = Abc_LutCascadeTruth( pLuts, nVarsOrig );
if ( fVeryVerbose )
Abc_LutCascadePrint( pLuts );
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" );
}
else if ( fVerbose || fVeryVerbose )
printf( "Verification passed.\n" );
ABC_FREE( pTruth2 );
ABC_FREE( pLuts );
}
ABC_FREE( pCopy );
Vec_WrdFree( vTruths );
printf( "Statistics for %d-rail LUT cascade:\n", nRails );
for ( i = 0; i < 100; 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( "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 );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Vec_WrdWriteTruthHex( char * pFileName, Vec_Wrd_t * vTruths, int nVars )
{
FILE * pFile = fopen( pFileName, "wb" );
if ( pFile == NULL ) { printf("Cannot open file \"%s\" for reading.\n", pFileName); return; }
int i, nWords = Abc_TtWordNum(nVars), nFuncs = Vec_WrdSize(vTruths)/nWords;
assert( nFuncs * nWords == Vec_WrdSize(vTruths) );
for ( i = 0; i < nFuncs; i++ )
Abc_TtPrintHexRev( pFile, Vec_WrdEntryP(vTruths, i*nWords), nVars ), fprintf( pFile, "\n" );
fclose( pFile );
}
void Abc_NtkSuppMinFile( char * pFileName )
{
int fError = 0, nFileSize = Gia_FileSize( pFileName );
FILE * pFile = fopen( pFileName, "rb" );
if ( pFile == NULL ) { printf("Cannot open file \"%s\" for reading.\n", pFileName); return; }
Vec_Wrd_t ** pvTruths = ABC_CALLOC( Vec_Wrd_t *, 32 );
char * pToken, * pLine = ABC_ALLOC( char, nFileSize );
word * pTruth = ABC_ALLOC( word, nFileSize/16 );
int Len, nVars = -1, nWords = -1, nFuncs = 0, nSuppSums[2] = {0};
for ( int i = 0; fgets(pLine, nFileSize, pFile); i++ ) {
pToken = strtok(pLine, " ,\n\r\r");
if ( pToken == NULL )
continue;
if ( pToken[0] == '0' && pToken[1] == 'x' )
pToken += 2;
Len = strlen(pToken);
nVars = Abc_Base2Log(Len);
if ( Len != (1 << nVars) ) {
printf( "The number of hex characters (%d) in the truth table listed in line %d is not a degree of 2.\n", Len, i );
fError = 1;
break;
}
nVars += 2;
if ( !Abc_TtReadHex( pTruth, pToken ) ) {
printf( "Line %d has truth table that cannot be read correctly (%s).\n", i, pToken );
fError = 1;
break;
}
nSuppSums[0] += nVars;
Abc_TtMinimumBase( pTruth, NULL, nVars, &nVars );
nSuppSums[1] += nVars;
if ( pvTruths[nVars] == NULL )
pvTruths[nVars] = Vec_WrdAlloc( 10000 );
nWords = Abc_TtWordNum(nVars);
for ( int w = 0; w < nWords; w++ )
Vec_WrdPush( pvTruths[nVars], pTruth[w] );
nFuncs++;
}
ABC_FREE( pTruth );
ABC_FREE( pLine );
fclose( pFile );
if ( fError ) {
for ( nVars = 0; nVars < 32; nVars++ )
if ( pvTruths[nVars] )
Vec_WrdFreeP( &pvTruths[nVars] );
ABC_FREE( pvTruths );
return;
}
// dump the resulting truth tables
printf( "Read and support-minimized %d functions. Total support reduction %d -> %d (%.2f %%).\n",
nFuncs, nSuppSums[0], nSuppSums[1], 100.0*(nSuppSums[0]-nSuppSums[1])/Abc_MaxInt(nSuppSums[0], 1) );
printf( "The resulting function statistics:\n" );
for ( nVars = 0; nVars < 32; nVars++ ) {
if ( pvTruths[nVars] == NULL )
continue;
char pFileName2[1000];
sprintf( pFileName2, "%s_%02d.txt", Extra_FileNameGeneric(pFileName), nVars );
Vec_WrdWriteTruthHex( pFileName2, pvTruths[nVars], nVars );
printf( "Support size %2d : Dumped %6d truth tables into file \"%s\".\n",
nVars, Vec_WrdSize(pvTruths[nVars])/Abc_TtWordNum(nVars), pFileName2 );
Vec_WrdFreeP( &pvTruths[nVars] );
}
ABC_FREE( pvTruths );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkRandFile( char * pFileName, int nVars, int nFuncs, int nMints )
{
int i, k, nWords = Abc_TtWordNum(nVars);
Vec_Wrd_t * vTruths = Vec_WrdStart( nWords * nFuncs );
Abc_Random(1);
for ( i = 0; i < nFuncs; i++ ) {
word * pTruth = Vec_WrdEntryP(vTruths, i*nWords);
if ( nMints == 0 )
for ( k = 0; k < nWords; k++ )
pTruth[k] = Abc_RandomW(0);
else {
for ( k = 0; k < nMints; k++ ) {
int iMint = 0;
do iMint = Abc_Random(0) % (1 << nVars);
while ( Abc_TtGetBit(pTruth, iMint) );
Abc_TtSetBit( pTruth, iMint );
}
}
}
Vec_WrdWriteTruthHex( pFileName, vTruths, nVars );
if ( nMints )
printf( "Generated %d random %d-variable functions with %d positive minterms and dumped them into file \"%s\".\n",
nFuncs, nVars, nMints, pFileName );
else
printf( "Generated %d random %d-variable functions and dumped them into file \"%s\".\n",
nFuncs, nVars, pFileName );
Vec_WrdFree( vTruths );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////

View File

@ -930,15 +930,15 @@ Abc_Ntk_t * Abc_NtkFromMiniMapping( int *pArray )
// create pis
for ( i = 0; i < nCis-nFlops; i++ )
Abc_NtkCreatePi( pNtkMapped );
// create nodes
for ( i = 0; i < nNodes; i++ )
Abc_NtkCreateNode( pNtkMapped );
// create pos
for ( i = 0; i < nCos-nFlops; i++ )
Abc_NtkCreatePo( pNtkMapped );
// create flops
for ( i = 0; i < nFlops; i++ )
Abc_NtkAddLatch( pNtkMapped, NULL, ABC_INIT_ZERO );
// create nodes
for ( i = 0; i < nNodes; i++ )
Abc_NtkCreateNode( pNtkMapped );
// connect nodes
for ( i = 0; i < nNodes; i++ )
{

View File

@ -4444,6 +4444,8 @@ Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk );
// skip persistant nodes
if ( Abc_NodeIsPersistant(pNode) )
{
if (!(pGain_res && pGain_ref && pGain_rwr))
return 0;
fprintf(fpt, "%d, %s, %d\n", pNode->Id, "None" , -99);
Vec_IntPush((*pGain_res), -99);
Vec_IntPush((*pGain_ref), -99);
@ -4453,6 +4455,8 @@ Rwr_ManAddTimeCuts( pManRwr, Abc_Clock() - clk );
// skip the nodes with many fanouts
if ( Abc_ObjFanoutNum(pNode) > 1000 )
{
if (!(pGain_res && pGain_ref && pGain_rwr))
return 0;
fprintf(fpt, "%d, %s, %d\n", pNode->Id,"None", -99);
Vec_IntPush((*pGain_res), -99);
Vec_IntPush((*pGain_ref), -99);

View File

@ -1217,8 +1217,9 @@ void Abc_NtkFraigPartitionedTime( Abc_Ntk_t * pNtk, void * pParams )
SeeAlso []
***********************************************************************/
void Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
Vec_Int_t * Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
{
Vec_Int_t * vGains = Vec_IntStart( Vec_PtrSize(vWins) );
Abc_Ntk_t * pNtk, * pNew; int i;
Vec_PtrForEachEntry( Abc_Ntk_t *, vWins, pNtk, i )
{
@ -1228,7 +1229,7 @@ void Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
if ( Cmd_CommandExecute(Abc_FrameGetGlobalFrame(), pScript) )
{
Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript );
return;
return vGains;
}
}
else
@ -1238,15 +1239,18 @@ void Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
{
Abc_Print( 1, "Something did not work out with the command \"%s\".\n", pScript );
Abc_FrameSetBatchMode( 0 );
return;
return vGains;
}
Abc_FrameSetBatchMode( 0 );
}
pNew = Abc_FrameReadNtk(Abc_FrameGetGlobalFrame());
if ( Abc_NtkIsMappedLogic(pNew) && Abc_NtkIsMappedLogic(pNtk) )
{
if ( Abc_NtkGetMappedArea(pNew) < Abc_NtkGetMappedArea(pNtk) )
double Before = Abc_NtkGetMappedArea(pNtk);
double After = Abc_NtkGetMappedArea(pNew);
if ( After < Before )
{
Vec_IntWriteEntry( vGains, i, (int)(Before - After) );
Abc_NtkDelete( pNtk );
pNtk = Abc_NtkDupDfs( pNew );
}
@ -1255,12 +1259,14 @@ void Abc_NtkStochSynthesis( Vec_Ptr_t * vWins, char * pScript )
{
if ( Abc_NtkNodeNum(pNew) < Abc_NtkNodeNum(pNtk) )
{
Vec_IntWriteEntry( vGains, i, Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pNew) );
Abc_NtkDelete( pNtk );
pNtk = Abc_NtkDupDfs( pNew );
}
}
Vec_PtrWriteEntry( vWins, i, pNtk );
}
return vGains;
}
@ -1332,16 +1338,16 @@ int Abc_NtkStochProcess1( void * p )
return 1;
}
Vec_Ptr_t * Abc_NtkStochProcess( Vec_Ptr_t * vWins, char * pScript, int nProcs, int TimeSecs, int fVerbose )
Vec_Int_t * Abc_NtkStochProcess( Vec_Ptr_t * vWins, char * pScript, int nProcs, int TimeSecs, int fVerbose )
{
if ( nProcs <= 2 ) {
Abc_NtkStochSynthesis( vWins, pScript );
return NULL;
return Abc_NtkStochSynthesis( vWins, pScript );
}
Vec_Int_t * vGains = Vec_IntStart( 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;
Abc_Random(1);
//Abc_Random(1);
Vec_PtrForEachEntry( Abc_Ntk_t *, vWins, pNtk, i ) {
pData[i].pIn = pNtk;
pData[i].pOut = NULL;
@ -1353,12 +1359,16 @@ Vec_Ptr_t * Abc_NtkStochProcess( Vec_Ptr_t * vWins, char * pScript, int nProcs,
Util_ProcessThreads( Abc_NtkStochProcess1, vData, nProcs, TimeSecs, fVerbose );
// replace old AIGs by new AIGs
Vec_PtrForEachEntry( Abc_Ntk_t *, vWins, pNtk, i ) {
if ( Abc_NtkIsMappedLogic(pNtk) )
Vec_IntWriteEntry( vGains, i, (int)(Abc_NtkGetMappedArea(pNtk) - Abc_NtkGetMappedArea(pData[i].pOut)) );
else
Vec_IntWriteEntry( vGains, i, Abc_NtkNodeNum(pNtk) - Abc_NtkNodeNum(pData[i].pOut) );
Abc_NtkDelete( pNtk );
Vec_PtrWriteEntry( vWins, i, pData[i].pOut );
}
Vec_PtrFree( vData );
ABC_FREE( pData );
return NULL;
return vGains;
}
/**Function*************************************************************
@ -1457,13 +1467,52 @@ 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 )
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 )
{
if ( vvIns == NULL ) {
assert( vvOuts == NULL );
assert( Vec_PtrSize(vWins) == 1 );
return Abc_NtkDupDfs( (Abc_Ntk_t *)Vec_PtrEntry(vWins, 0) );
}
if ( fOverlap ) {
Vec_Ptr_t * vvInsNew = Vec_PtrAlloc( 10 );
Vec_Ptr_t * vvOutsNew = Vec_PtrAlloc( 10 );
Vec_Ptr_t * vvWinsNew = Vec_PtrAlloc( 10 );
Abc_NtkIncrementTravId( p );
while ( 1 ) {
int i, Gain, iEntry = Vec_IntArgMax(vGains);
if ( 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, Abc_NtkDupDfs((Abc_Ntk_t *)Vec_PtrEntry(vWins, iEntry)) );
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 )
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 )
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) )
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 *)) Abc_NtkDelete );
}
// check consistency of input data
Abc_Ntk_t * pNew, * pTemp; Abc_Obj_t * pObj; int i, k, iNode;
Vec_PtrForEachEntry( Abc_Ntk_t *, vWins, pTemp, i ) {
@ -1612,6 +1661,7 @@ void Abc_NtkPermuteLevel( Abc_Ntk_t * pNtk, int Level )
Abc_ObjForEachFanout( pObj, pNext, k )
if ( Abc_ObjIsNode(pNext) )
LevelMax = Abc_MinInt( LevelMax, Abc_ObjLevel(pNext) );
if ( LevelMin == LevelMax ) continue;
assert( LevelMin < LevelMax );
// randomly set level between LevelMin and LevelMax-1
pObj->Level = LevelMin + (Abc_Random(0) % (LevelMax - LevelMin));
@ -1709,6 +1759,17 @@ void Abc_NtKSelectRemove( Vec_Wec_t * vSupps, Vec_Int_t * vOne )
Vec_IntClear( vLevel );
Vec_WecRemoveEmpty( vSupps );
}
// marks TFI/TFO of this one
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_ObjDfsMark2_rec( pObj );
}
}
// removes all supports that overlap with the TFI/TFO cones of this one
void Abc_NtKSelectRemove2( Vec_Wec_t * vSupps, Vec_Int_t * vOne, Abc_Ntk_t * pNtk )
{
@ -1728,7 +1789,16 @@ void Abc_NtKSelectRemove2( Vec_Wec_t * vSupps, Vec_Int_t * vOne, Abc_Ntk_t * pNt
}
Vec_WecRemoveEmpty( vSupps );
}
Vec_Ptr_t * Abc_NtkDeriveWinInsAll( Vec_Wec_t * vSupps, int nSuppMax, Abc_Ntk_t * pNtk )
// removes all supports that are contained in this one
void Abc_NtKSelectRemove3( 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 * Abc_NtkDeriveWinInsAll( Vec_Wec_t * vSupps, int nSuppMax, Abc_Ntk_t * pNtk, int fOverlap )
{
Vec_Ptr_t * vRes = Vec_PtrAlloc( 100 );
Abc_NtkIncrementTravId( pNtk );
@ -1738,7 +1808,10 @@ Vec_Ptr_t * Abc_NtkDeriveWinInsAll( Vec_Wec_t * vSupps, int nSuppMax, Abc_Ntk_t
Vec_Int_t * vCopy = Vec_IntDup( vLevel2 );
if ( Vec_IntSize(vLevel2) == nSuppMax ) {
Vec_PtrPush( vRes, vCopy );
Abc_NtKSelectRemove2( vSupps, vCopy, pNtk );
if ( fOverlap )
Abc_NtKSelectRemove3( vSupps, vCopy );
else
Abc_NtKSelectRemove2( vSupps, vCopy, pNtk );
continue;
}
// find another support, which maximizes the union but does not exceed nSuppMax
@ -1756,7 +1829,10 @@ Vec_Ptr_t * Abc_NtkDeriveWinInsAll( Vec_Wec_t * vSupps, int nSuppMax, Abc_Ntk_t
Vec_IntForEachEntry( vLevel, Item, i )
Vec_IntPushUniqueOrder( vCopy, Item );
Vec_PtrPush( vRes, vCopy );
Abc_NtKSelectRemove2( vSupps, vCopy, pNtk );
if ( fOverlap )
Abc_NtKSelectRemove3( vSupps, vCopy );
else
Abc_NtKSelectRemove2( vSupps, vCopy, pNtk );
}
return vRes;
}
@ -1799,22 +1875,24 @@ Vec_Ptr_t * Abc_NtkDupWindows( Abc_Ntk_t * pNtk, Vec_Ptr_t * vvIns, Vec_Ptr_t *
}
return vWins;
}
Vec_Ptr_t * Abc_NtkExtractPartitions( Abc_Ntk_t * pNtk, int Iter, int nSuppMax, Vec_Ptr_t ** pvIns, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvNodes )
Vec_Ptr_t * Abc_NtkExtractPartitions( Abc_Ntk_t * pNtk, int Iter, int nSuppMax, Vec_Ptr_t ** pvIns, Vec_Ptr_t ** pvOuts, Vec_Ptr_t ** pvNodes, int fOverlap )
{
if ( Abc_NtkCiNum(pNtk) <= nSuppMax ) {
Vec_Ptr_t * vWins = Vec_PtrAlloc( 1 );
Vec_PtrPush( vWins, Abc_NtkDupDfs(pNtk) );
*pvIns = *pvOuts = *pvNodes = NULL;
return vWins;
}
int iUseRevL = Iter % 3 == 0 ? 0 : Abc_Random(0) & 1;
// if ( Abc_NtkCiNum(pNtk) <= nSuppMax ) {
// Vec_Ptr_t * vWins = Vec_PtrAlloc( 1 );
// Vec_PtrPush( vWins, Abc_NtkDupDfs(pNtk) );
// *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 ? Abc_NtkLevelR(pNtk) : Abc_NtkLevel(pNtk);
int LevelCut = Iter % 3 == 0 ? 0 : LevelMax > 8 ? 2 + (Abc_Random(0) % (LevelMax - 4)) : 0;
//printf( "Using %s cut level %d (out of %d)\n", iUseRevL ? "reverse": "direct", LevelCut, LevelMax );
Abc_NtkPermuteLevel( pNtk, LevelMax );
// 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 );
// Abc_NtkPermuteLevel( pNtk, LevelMax );
Vec_Wec_t * vStore = Vec_WecStart( LevelMax+1 );
Vec_Wec_t * vSupps = Abc_NtkCollectObjectsWithSuppLimit( pNtk, LevelCut, nSuppMax );
Vec_Ptr_t * vIns = Abc_NtkDeriveWinInsAll( vSupps, nSuppMax, pNtk );
Vec_Ptr_t * vIns = Abc_NtkDeriveWinInsAll( vSupps, nSuppMax, pNtk, fOverlap );
Vec_Ptr_t * vNodes = Abc_NtkDeriveWinNodesAll( pNtk, vIns, vStore );
Vec_Ptr_t * vOuts = Abc_NtkDeriveWinOutsAll( pNtk, vNodes );
Vec_Ptr_t * vWins = Abc_NtkDupWindows( pNtk, vIns, vNodes, vOuts );
@ -1837,7 +1915,7 @@ Vec_Ptr_t * Abc_NtkExtractPartitions( Abc_Ntk_t * pNtk, int Iter, int nSuppMax,
SeeAlso []
***********************************************************************/
void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fVerbose, char * pScript, int nProcs )
void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fOverlap, int fVerbose, char * pScript, int nProcs )
{
abctime clkStart = Abc_Clock(); int i;
abctime nTimeToStop = TimeOut ? Abc_Clock() + TimeOut * CLOCKS_PER_SEC : 0;
@ -1859,20 +1937,19 @@ void Abc_NtkStochMap( int nSuppMax, int nIters, int TimeOut, int Seed, int fVerb
{
abctime clk = Abc_Clock();
Abc_Ntk_t * pNtk = Abc_NtkDupDfs(Abc_FrameReadNtk(Abc_FrameGetGlobalFrame()));
Vec_Ptr_t * vWins = Abc_NtkExtractPartitions( pNtk, i, nSuppMax, &vIns, &vOuts, &vNodes );
Vec_Ptr_t * vOpts = Abc_NtkStochProcess( vWins, pScript, nProcs, 0, 0 );
Abc_Ntk_t * pNew = Abc_NtkInsertPartitions( pNtk, vIns, vOuts, vWins );
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_FrameReplaceCurrentNetwork( Abc_FrameGetGlobalFrame(), pNew );
if ( fVerbose )
printf( "Iteration %3d : Using %3d partitions. Reducing area from %.2f to %.2f. ",
i, Vec_PtrSize(vWins), Abc_NtkGetMappedArea(pNtk), Abc_NtkGetMappedArea(pNew) );
printf( "Iteration %3d : Using %3d -> %3d partitions. Reducing area from %.2f to %.2f. ",
i, nPartsInit, Vec_PtrSize(vWins), Abc_NtkGetMappedArea(pNtk), Abc_NtkGetMappedArea(pNew) );
if ( fVerbose )
Abc_PrintTime( 0, "Time", Abc_Clock() - clk );
// cleanup
Abc_NtkDelete( pNtk );
Vec_PtrFreeFunc( vWins, (void (*)(void *)) Abc_NtkDelete );
//Vec_PtrFreeFunc( vOpts, (void (*)(void *)) Abc_NtkDelete );
vOpts = NULL;
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 );

View File

@ -282,8 +282,8 @@ static inline Abc_RData_t * Abc_RData2Rel( Abc_RData_t * p )
Vec_WrdShrink( vTransOut, p->nPats );
Vec_Wrd_t * vTransInCopy = Vec_WrdDup(vTransIn);
Vec_WrdUniqify( vTransInCopy );
if ( Vec_WrdSize(vTransInCopy) == p->nPats )
printf( "This resub problem is not a relation.\n" );
// if ( Vec_WrdSize(vTransInCopy) == p->nPats )
// printf( "This resub problem is not a relation.\n" );
// create the relation
Abc_RData_t * pNew = Abc_RDataStart( p->nIns, 1 << (p->nOuts-1), Vec_WrdSize(vTransInCopy) );
pNew->nOuts = p->nOuts;

View File

@ -248,6 +248,7 @@ void Abc_FrameDeallocate( Abc_Frame_t * p )
Vec_WecFreeP( &s_GlobalFrame->vJsonObjs );
Ndr_Delete( s_GlobalFrame->pNdr );
ABC_FREE( s_GlobalFrame->pNdrArray );
Abc_FrameStoreStop( s_GlobalFrame );
Gia_ManStopP( &p->pGiaMiniAig );
Gia_ManStopP( &p->pGiaMiniLut );

View File

@ -33,6 +33,7 @@
#include "aig/gia/gia.h"
#include "proof/ssw/ssw.h"
#include "proof/fra/fra.h"
#include "misc/vec/vecHsh.h"
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
@ -151,6 +152,7 @@ struct Abc_Frame_t_
void * pAbcPla;
Abc_Nam_t * pJsonStrs;
Vec_Wec_t * vJsonObjs;
Hsh_VecMan_t * pHash;
#ifdef ABC_USE_CUDD
DdManager * dd; // temporary BDD package
#endif
@ -210,7 +212,10 @@ extern ABC_DLL char * Abc_UtilsGetUsersInput( Abc_Frame_t * pAbc );
extern ABC_DLL void Abc_UtilsPrintHello( Abc_Frame_t * pAbc );
extern ABC_DLL void Abc_UtilsPrintUsage( Abc_Frame_t * pAbc, char * ProgName );
extern ABC_DLL void Abc_UtilsSource( Abc_Frame_t * pAbc );
extern ABC_DLL void Abc_FrameStoreStart( Abc_Frame_t * pAbc );
extern ABC_DLL void Abc_FrameStoreStop( Abc_Frame_t * pAbc );
extern ABC_DLL void Abc_FrameStoreAdd( Abc_Frame_t * pAbc, Gia_Man_t * p );
extern ABC_DLL void Abc_FrameStorePrint( Abc_Frame_t * pAbc );
ABC_NAMESPACE_HEADER_END

View File

@ -291,7 +291,63 @@ char * DateReadFromDateString( char * datestr )
}
}
/**Function********************************************************************
Synopsis []
Description []
SideEffects []
******************************************************************************/
void Abc_FrameStoreStop( Abc_Frame_t * pAbc )
{
if ( pAbc->pHash )
Hsh_VecManStop( pAbc->pHash );
pAbc->pHash = NULL;
}
void Abc_FrameStoreStart( Abc_Frame_t * pAbc )
{
Abc_FrameStoreStop( pAbc );
pAbc->pHash = Hsh_VecManStart( 1000 );
pAbc->pHash->vEntry = Vec_IntAlloc( 1000 );
pAbc->pHash->vValue = Vec_IntAlloc( 1000 );
}
void Abc_FrameStoreAdd( Abc_Frame_t * pAbc, Gia_Man_t * pGia )
{
if ( pAbc->pHash == NULL )
Abc_FrameStoreStart( pAbc );
Gia_Man_t * p = Gia_ManIsoCanonicize( pGia, 0 );
Vec_IntClear( pAbc->pHash->vEntry );
Vec_IntPush( pAbc->pHash->vEntry, 0 );
Vec_IntPush( pAbc->pHash->vEntry, Gia_ManPiNum(p) );
Vec_IntPush( pAbc->pHash->vEntry, Gia_ManPoNum(p) );
Vec_IntPush( pAbc->pHash->vEntry, Gia_ManRegNum(p) );
Gia_Obj_t * pObj; int i;
Gia_ManForEachAnd( p, pObj, i )
Vec_IntPushTwo( pAbc->pHash->vEntry, Gia_ObjFaninLit0(pObj, i), Gia_ObjFaninLit1(pObj, i) );
int iEntry = Hsh_VecManAdd( pAbc->pHash, pAbc->pHash->vEntry );
if ( Vec_IntSize(pAbc->pHash->vValue) == iEntry )
Vec_IntPush( pAbc->pHash->vValue, 0 );
Vec_IntAddToEntry( pAbc->pHash->vValue, iEntry, 1 );
assert( Vec_IntSize(pAbc->pHash->vValue) == Hsh_VecSize(pAbc->pHash) );
Gia_ManStop( p );
}
void Abc_FrameStorePrint( Abc_Frame_t * pAbc )
{
if ( pAbc->pHash == NULL )
Abc_FrameStoreStart( pAbc );
int i, Entry, 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" );
Vec_IntFree( vCounts );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///

View File

@ -90,6 +90,27 @@ static char * pSimpleGenlib[] = {
NULL
};
// internal version of genlib library
static char * pSimpleGenlib2[] = {
"GATE zero 0 O=CONST0;\n",
"GATE one 0 O=CONST1;\n",
"GATE buf 4 O=a; PIN * NONINV 1 999 1.0 0.0 1.0 0.0\n",
"GATE inv 2 O=!a; PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE nand2 4 O=!(a*b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE nand3 6 O=!(a*b*c); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE nand4 8 O=!(a*b*c*d); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE nor2 4 O=!(a+b); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE nor3 6 O=!(a+b+c); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE nor4 6 O=!(a+b+c+d); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE aoi21 6 O=!(a*b+c); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE oai21 6 O=!((a+b)*c); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE aoi22 8 O=!(a*b+c*d); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE oai22 8 O=!((a+b)*(c+d)); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE aoi211 8 O=!(a*b+c+d); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
"GATE oai211 8 O=!((a+b)*c*d); PIN * INV 1 999 1.0 0.0 1.0 0.0\n",
NULL
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
@ -118,6 +139,19 @@ void Mio_IntallSimpleLibrary()
Mio_UpdateGenlib( pLib );
Vec_StrFree( vLibStr );
}
void Mio_IntallSimpleLibrary2()
{
extern Mio_Library_t * Mio_LibraryReadBuffer( char * pBuffer, int fExtendedFormat, st__table * tExcludeGate, int nFaninLimit, int fVerbose );
Mio_Library_t * pLib; int i;
Vec_Str_t * vLibStr = Vec_StrAlloc( 1000 );
for ( i = 0; pSimpleGenlib2[i]; i++ )
Vec_StrAppend( vLibStr, pSimpleGenlib2[i] );
Vec_StrPush( vLibStr, '\0' );
pLib = Mio_LibraryReadBuffer( Vec_StrArray(vLibStr), 0, NULL, 0, 0 );
Mio_LibrarySetName( pLib, Abc_UtilStrsav("simple2.genlib") );
Mio_UpdateGenlib( pLib );
Vec_StrFree( vLibStr );
}
/**Function*************************************************************

View File

@ -50,6 +50,7 @@ struct Abc_BSEval_t_
Vec_Wrd_t * vStore; // cofactors
Vec_Wec_t * vSets; // sets
Vec_Wrd_t * vCofs; // cofactors
word * pPat; // patterns
};
////////////////////////////////////////////////////////////////////////
@ -197,7 +198,7 @@ int Abc_TtGetCMCount( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_
return Abc_TtGetCM4( p, nVars, Vec_IntArray(vCounts), vUsed );
if ( nFVars == 5 )
return Abc_TtGetCM5( p, nVars, vTable, vStore, vUsed );
if ( nFVars == 6 )
if ( nFVars >= 6 )
return Abc_TtGetCM6( p, nVars, nFVars, vTable, vStore, vUsed );
assert( 0 );
return 0;
@ -345,7 +346,7 @@ int Abc_TtGetCMInt( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_In
{
int nMintsBS = 1 << (nVars - nFVars);
int nWordsBS = Abc_TtWordNum(nVars - nFVars);
assert( nMintsBS * nWordsBS <= 1024 );
//assert( nMintsBS * nWordsBS <= MAX_PAT_WORD_SIZE );
memset( pPat, 0, 8 * nMintsBS * nWordsBS );
int nMyu = 0;
if ( nFVars == 1 )
@ -358,7 +359,7 @@ int Abc_TtGetCMInt( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_In
nMyu = Abc_TtGetCM4Pat( p, nVars, Vec_IntArray(vCounts), vUsed, pPat );
else if ( nFVars == 5 )
nMyu = Abc_TtGetCM5Pat( p, nVars, vTable, vStore, vUsed, pPat );
else if ( nFVars == 6 )
else if ( nFVars >= 6 )
nMyu = Abc_TtGetCM6Pat( p, nVars, nFVars, vTable, vStore, vUsed, pPat );
else assert( 0 );
return nMyu;
@ -366,12 +367,11 @@ int Abc_TtGetCMInt( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_In
int Abc_TtGetCMPat( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed )
{
word pPat[1024];
int nRails, nMyu = Abc_TtGetCMInt( p, nVars, nFVars, vCounts, vTable, vStore, vUsed, pPat );
int nRails, nMyu = Abc_TtGetCMInt( p, nVars, nFVars, vCounts, vTable, vStore, vUsed, NULL );
if ( nMyu <= 2 )
nRails = 1;
else
nRails = Abc_TtCheck1Shared( pPat, nVars, nFVars, nMyu );
nRails = Abc_TtCheck1Shared( NULL, nVars, nFVars, nMyu );
return nRails;
}
int Abc_TtGetCM( word * p, int nVars, int nFVars, Vec_Int_t * vCounts, Vec_Int_t * vTable, Vec_Wrd_t * vStore, Vec_Int_t * vUsed, int fShared )
@ -567,7 +567,8 @@ void Abc_BSEvalFree( Abc_BSEval_t * p )
Vec_IntFree( p->vUsed );
Vec_WrdFree( p->vStore );
Vec_WecFreeP( &p->vSets );
Vec_WrdFreeP( &p->vCofs );
Vec_WrdFreeP( &p->vCofs );
ABC_FREE( p->pPat );
ABC_FREE( p );
}
void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose )
@ -588,8 +589,8 @@ void Abc_BSEvalOneTest( word * pT, int nVars, int nBVars, int fVerbose )
int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int nCVars, int nFVars, int fVerbose, int * pPermBest, int fShared )
{
int i, k, Var0, Var1, Pla2Var[32], Var2Pla[32];
int nPermVars = nVars-nCVars;
assert( p->nVars == nPermVars && p->nBVars == nPermVars-nFVars );
int nPermVars = nVars-nCVars, Count = 0;
assert( p->nVars == nPermVars && p->nBVars == nVars-nFVars );
for ( i = 0; i < nVars; i++ )
Pla2Var[i] = Var2Pla[i] = i;
if ( pPermBest )
@ -604,6 +605,11 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n
CostBest = CostThis;
if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 );
if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nVars );
Count = 1;
}
else if ( CostBest == CostThis && (Abc_Random(0) % ++Count) == 0 ) {
if ( pBest ) Abc_TtCopy( pBest, pIn, Abc_Truth6WordNum(nVars), 0 );
if ( pPermBest ) memcpy( pPermBest, Pla2Var, sizeof(int)*nVars );
}
if ( fVerbose )
{
@ -617,8 +623,20 @@ int Abc_BSEvalBest( Abc_BSEval_t * p, word * pIn, word * pBest, int nVars, int n
for ( k = nFVars-1; k >= 0; k-- )
printf( " %d", Pla2Var[k] );
printf( " : Myu = %3d", CostThis );
printf( "\n" );
//printf( "\n" );
}
if ( 0 ) {
//word pPat[MAX_PAT_WORD_SIZE];
int nRails = 1, Shared = 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 );
printf( " RailMin = %d. Shared = %2d. ", nRailsMin, Shared );
}
}
if ( fVerbose )
printf( "\n" );
int iPlace0 = Var2Pla[Var0];
int iPlace1 = Var2Pla[Var1];
if ( iPlace0 == iPlace1 )
@ -815,7 +833,7 @@ static inline int Abc_BSEvalCountUnique( word * pISets, int nISets, int nBSWords
static inline int Abc_BSEvalCountUniqueMax( word * pISets, int nISets, int nBSWords, word * pCofs, int nOnes, int nISetsMaxHave )
{
int m, nMints = (1 << nOnes), CountMax = 0;
assert( nOnes > 0 && nOnes < 5 );
//assert( nOnes > 0 && nOnes < 5 );
for ( m = 0; m < nMints; m++ )
{
int Count = Abc_BSEvalCountUnique( pISets, nISets, nBSWords, pCofs + m * nBSWords );
@ -859,17 +877,19 @@ int Abc_BSEvalFindShared( int nVars, word * pISets, int nISets, int nBSWords, Ve
***********************************************************************/
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 nBSWords = Abc_Truth6WordNum( nVars - nFVars ), CVarMask = Abc_InfoMask(nCVars) << (nVars - nFVars - nCVars);
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 );
int i, k, iSet, iStart, nSharedMax = nVars - nFVars - 1, nRailsMin = 100;
Vec_WecForEachLevelStartStop( p->vSets, vLevel, i, 1, nSharedMax+1 ) {
int i, k, iSet, iStart, nSharedMax = nVars - nFVars - nRails, nRailsMin = 100;
Vec_WecForEachLevelStartStop( p->vSets, 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 );
if ( MyuCur == 0 )
//printf( " Res = %d", MyuCur );
if ( MyuCur == 0 || MyuCur > (1 << nRails) )
continue;
nRailsCur = Abc_Base2Log(MyuCur);
if ( nRailsCur > nRails )
@ -907,7 +927,7 @@ word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nR
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, nVarsCur = nVars, nOutVars = 0; word pPat[1024];
int i, r, nVarsCur = nVars, nOutVars = 0;
while ( nVarsCur > nLutSize )
{
int pPerm[32] = {0};
@ -917,6 +937,10 @@ word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nR
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;
@ -924,8 +948,12 @@ word * Abc_LutCascade2( word * pFunc, int nVars, int nLutSize, int nLuts, int nR
}
int MyuMin = Abc_BSEvalBest( p, pTruth, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, fVerbose, pPerm, 0 );
int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin );
if ( nRailsMin > nRails )
nRailsMin = Abc_SharedEvalBest( p, pBest, nVarsCur, nOutVars, nVarsCur-nLutSize, MyuMin, nRails, fVerbose, &Shared, pPat );
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;
@ -972,23 +1000,26 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
{
Abc_BSEval_t * p = Abc_BSEvalAlloc();
int nPermVars = nVars-nRVars;
if ( p->nVars != nPermVars || p->nBVars != nLutSize ) {
if ( p->nBVars != nLutSize ) {
Vec_WecFreeP( &p->vSets );
Vec_WrdFreeP( &p->vCofs );
p->vCofs = Abc_BSEvalCreateCofactorSets( nLutSize, &p->vSets );
}
if ( p->nVars != nPermVars ) {
Vec_IntFreeP( &p->vPairs );
p->vPairs = Abc_GenChasePairs( nPermVars, nLutSize );
p->nVars = nPermVars;
p->nBVars = nLutSize;
p->vPairs = Abc_GenChasePairs( nPermVars, nLutSize-nRVars );
p->nVars = nPermVars;
}
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->nBVars = nLutSize;
}
int v, nWords = Abc_TtWordNum(nVars);
int v, r, nWords = Abc_TtWordNum(nVars);
word * pCopy = ABC_ALLOC( word, nWords );
Abc_TtCopy( pCopy, pTruth, nWords, 0 );
word pPat[1024];
//word pPat[MAX_PAT_WORD_SIZE];
int pPermBest[32] = {0};
word * pBest = ABC_ALLOC( word, nWords );
@ -1004,14 +1035,23 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
}
int Shared = 0, nRailsMin = Abc_Base2Log( MyuMin );
if ( nRailsMin > nRails ) {
nRailsMin = Abc_SharedEvalBest( p, pBest, nVars, nRVars, nVars-nLutSize, MyuMin, nRails, 0, &Shared, pPat );
MyuMin = 1 << nRailsMin;
for ( r = 1; r <= nRails && nRailsMin > r; r++ ) {
int nRailsMinNew = Abc_SharedEvalBest( p, pBest, nVars, nRVars, nVars-nLutSize, MyuMin, r, 0, &Shared, p->pPat );
if ( nRailsMinNew < 100 )
nRailsMin = nRailsMinNew;
}
MyuMin = 1 << nRailsMin;
ABC_FREE( pCopy );
ABC_FREE( pBest );
Abc_BSEvalFree(p);
if ( fVerbose )
printf( "Myu min = %d. Rail min = %d. Shared = %x.\n", MyuMin, nRailsMin, Shared );
if ( nRailsMin > nRails )
return 0;
word mBVars = 0;
for ( v = 0; v < nLutSize; v++ )
mBVars |= (word)1 << pPermBest[nVars-nLutSize+v];
@ -1021,9 +1061,6 @@ word Abc_TtFindBVarsSVars( word * pTruth, int nVars, int nRVars, int nRails, int
if ( (Shared >> v) & 1 )
mSVars |= (word)1 << (nVars-nLutSize+v);
ABC_FREE( pCopy );
ABC_FREE( pBest );
Abc_BSEvalFree(p);
return ((word)MyuMin << 48) | (mSVars << 24) | mBVars;
}

View File

@ -87,7 +87,9 @@ struct Hsh_VecMan_t_
{
Vec_Int_t * vTable; // hash table
Vec_Int_t * vData; // data storage
Vec_Int_t * vMap; // mapping entries into data;
Vec_Int_t * vMap; // mapping entries into data
Vec_Int_t * vValue; // mapping entries into values
Vec_Int_t * vEntry; // temporary entry
Vec_Int_t vTemp; // temporary array
Vec_Int_t vTemp1; // temporary array
Vec_Int_t vTemp2; // temporary array
@ -461,6 +463,8 @@ static inline void Hsh_VecManStop( Hsh_VecMan_t * p )
Vec_IntFree( p->vTable );
Vec_IntFree( p->vData );
Vec_IntFree( p->vMap );
Vec_IntFreeP( &p->vValue );
Vec_IntFreeP( &p->vEntry );
ABC_FREE( p );
}
static inline int * Hsh_VecReadArray( Hsh_VecMan_t * p, int i )

215
src/opt/eslim/eSLIM.cpp Normal file
View File

@ -0,0 +1,215 @@
/**CFile****************************************************************
FileName [eSLIM.cpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Interface to the eSLIM package.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: eSLIM.cpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#include "utils.hpp"
#include "eSLIMMan.hpp"
#include "relationGeneration.hpp"
#include "selectionStrategy.hpp"
#include "misc/util/abc_namespaces.h"
#include "eSLIM.h"
ABC_NAMESPACE_HEADER_START
Gia_Man_t * Gia_ManDeepSyn( Gia_Man_t * pGia, int nIters, int nNoImpr, int TimeOut, int nAnds, int Seed, int fUseTwo, int fVerbose );
ABC_NAMESPACE_HEADER_END
ABC_NAMESPACE_IMPL_START
eSLIM::eSLIMConfig getCfg(const eSLIM_ParamStruct* params) {
eSLIM::eSLIMConfig config;
config.extended_normality_processing = params->extended_normality_processing;
config.apply_strash = params->apply_strash;
config.fill_subcircuits = params->fill_subcircuits;
config.fix_seed = params->fix_seed;
config.trial_limit_active = params->trial_limit_active;
config.timeout = params->timeout;
config.iterations = params->iterations;
config.subcircuit_size_bound = params->subcircuit_size_bound;
config.strash_intervall = params->strash_intervall;
config.nselection_trials = params->nselection_trials;
config.seed = params->seed;
config.verbosity_level = params->verbosity_level;
config.expansion_probability = params->expansion_probability;
return config;
}
void seteSLIMParams(eSLIM_ParamStruct* params) {
params->forbidden_pairs = 1;
params->extended_normality_processing = 0;
params->fill_subcircuits = 0;
params->apply_strash = 1;
params->fix_seed = 0;
params->trial_limit_active = 1;
params->apply_inprocessing = 1;
params->timeout = 1620;
params->timeout_inprocessing = 180;
params->iterations = 0;
params->subcircuit_size_bound = 6;
params->strash_intervall = 100;
params->nselection_trials = 100;
params->nruns = 1;
params->mode = 0;
params->seed = 0;
params->verbosity_level = 1;
params->expansion_probability = 0.4;
}
Gia_Man_t* selectApproach(Gia_Man_t* pGia, eSLIM::eSLIMConfig params, eSLIM::eSLIMLog& log, int approach, bool allow_forbidden_pairs) {
switch (approach) {
case 0 :
if (allow_forbidden_pairs) {
return eSLIM::eSLIM_Man<eSLIM::CadicalEngine, eSLIM::RelationGeneratorABC, eSLIM::randomizedBFSFP>::applyeSLIM(pGia, params, log);
} else {
return eSLIM::eSLIM_Man<eSLIM::CadicalEngine, eSLIM::RelationGeneratorABC, eSLIM::randomizedBFSnoFP>::applyeSLIM(pGia, params, log);
};
case 1:
if (allow_forbidden_pairs) {
return eSLIM::eSLIM_Man<eSLIM::KissatOneShot, eSLIM::RelationGeneratorABC, eSLIM::randomizedBFSFP>::applyeSLIM(pGia, params, log);
} else {
return eSLIM::eSLIM_Man<eSLIM::KissatOneShot, eSLIM::RelationGeneratorABC, eSLIM::randomizedBFSnoFP>::applyeSLIM(pGia, params, log);
};
case 2:
if (allow_forbidden_pairs) {
return eSLIM::eSLIM_Man<eSLIM::KissatCmdOneShot, eSLIM::RelationGeneratorABC, eSLIM::randomizedBFSFP>::applyeSLIM(pGia, params, log);
} else {
return eSLIM::eSLIM_Man<eSLIM::KissatCmdOneShot, eSLIM::RelationGeneratorABC, eSLIM::randomizedBFSnoFP>::applyeSLIM(pGia, params, log);
};
default:
std::cerr << "eSLIM -- Invalid mode given\n";
assert (false && "Invalid approach selected");
return nullptr;
}
}
Gia_Man_t* runInprocessing(Gia_Man_t * pGia, const eSLIM_ParamStruct* params, unsigned int it) {
Gia_Man_t * tmp = Gia_ManDeepSyn( pGia, 1, ABC_INFINITY, params->timeout_inprocessing, 0, params->seed + it, 0, 0);
if ( Gia_ManAndNum(pGia) > Gia_ManAndNum(tmp) ) {
Gia_ManStop( pGia );
pGia = tmp;
} else {
Gia_ManStop( tmp );
}
return pGia;
}
void printSetting(const eSLIM_ParamStruct* params) {
std::cout << "Apply eSLIM (timeout: " << params->timeout << ") ";
if (params->apply_inprocessing) {
std::cout << "+ deepsyn (timeout: " << params->timeout_inprocessing << ") ";
}
std::cout << params->nruns << " times.\n";
if (params->iterations > 0) {
std::cout << "Stop eSLIM runs after " << params->iterations << " iterations.\n";
}
std::cout << "Consider subcircuits with up to " << params->subcircuit_size_bound << " gates.\n";
printf("When expanding subcircuits, select gates with a probability of %.2f %%.\n", 100 * params->expansion_probability);
if (params->forbidden_pairs) {
std::cout << "Consider subcircuits containing gates, which are connected outside of the subcircuit.\n";
}
if (params->mode == 0) {
std::cout << "Use an incremental SAT encoding for exact synthesis and the SAT solver CaDiCaL.\n";
} else {
std::cout << "Use a one-shot SAT encoding for exact synthesis and the SAT solver Kissat.\n";
}
}
Gia_Man_t* applyeSLIM(Gia_Man_t * pGia, const eSLIM_ParamStruct* params) {
eSLIM::eSLIMConfig config = getCfg(params);
config.verbosity_level = params->verbosity_level;
int eSLIM_reductions = 0;
int deepsyn_reductions = 0;
Gia_Man_t * pThis = Gia_ManDup(pGia);
eSLIM::eSLIMLog log(params->subcircuit_size_bound);
int initial_size = Gia_ManAndNum(pThis);
if (params->verbosity_level > 0) {
printSetting(params);
std::cout << "Initial size: " << initial_size << "\n";
}
for (unsigned int i = 0; i < params->nruns; i++) {
if (config.fix_seed) {
config.seed = params->seed + i;
}
int size_iteration_start = Gia_ManAndNum(pThis);
if (params->verbosity_level > 0) {
std::cout << "Start eslim run " << i + 1 << "\n";
}
pThis = selectApproach(pThis, config, log, params->mode, params->forbidden_pairs);
int size_eslim = Gia_ManAndNum(pThis);
eSLIM_reductions += size_iteration_start - size_eslim;
if (params->apply_inprocessing) {
if (params->verbosity_level > 0) {
std::cout << "Start inprocessing run " << i + 1 << "\n";
}
pThis = runInprocessing(pThis, params, i);
if (params->verbosity_level > 0) {
std::cout << "Inprocessing: Initial size: " << size_eslim << " final size: " << Gia_ManAndNum(pThis) << "\n";
}
deepsyn_reductions += size_eslim - Gia_ManAndNum(pThis);
}
}
if (params->verbosity_level > 0) {
int final_size = Gia_ManAndNum(pThis);
std::cout << "Final size: " << final_size << "\n";
int total_reductions = eSLIM_reductions + deepsyn_reductions;
double reduction_ratio = 100 * static_cast<double>(total_reductions) / initial_size;
printf("Total reduction: %d (%.2f %%)\n", total_reductions, reduction_ratio);
if (params->apply_inprocessing) {
std::cout << "#Gates reduced by eSLIM: " << eSLIM_reductions << " ";
std::cout << "#Gates reduced by deepsyn: " << deepsyn_reductions << "\n";
}
}
if (params->verbosity_level > 1) {
std::cout << "Total #iterations: " << log.iteration_count << "\n";
std::cout << "Total relation generation time (s): " << log.relation_generation_time << "\n";
std::cout << "Total synthesis time (s): " << log.synthesis_time << "\n";
std::cout << "#Iterations with forbidden pairs: " << log.subcircuits_with_forbidden_pairs << "\n";
}
if (params->verbosity_level > 2) {
for (int i = 2; i < log.nof_analyzed_circuits_per_size.size(); i++) {
int replaced = log.nof_replaced_circuits_per_size.size() > i ? log.nof_replaced_circuits_per_size[i] : 0;
int reduced = log.nof_reduced_circuits_per_size.size() > i ? log.nof_reduced_circuits_per_size[i] : 0;
std::cout << "#gates: " << i << " - #analysed: " << log.nof_analyzed_circuits_per_size[i] << " - #replaced: " << replaced << " - #reduced: " << reduced << "\n";
}
if (params->mode == 0) {
for (int i = 0; i < log.nof_sat_calls_per_size.size(); i++) {
if (log.nof_sat_calls_per_size[i] == 0) {
std::cout << "#gates: " << i << " - avg. sat time: -\n";
} else {
std::cout << "#gates: " << i << " - avg. sat time: " << static_cast<double>(log.cummulative_sat_runtimes_per_size[i]) / (1000 * log.nof_sat_calls_per_size[i]) << " sec\n";
}
}
for (int i = 0; i < log.nof_unsat_calls_per_size.size(); i++) {
if (log.nof_unsat_calls_per_size[i] == 0) {
std::cout << "#gates: " << i << " - avg. unsat time: -\n";
} else {
std::cout << "#gates: " << i << " - avg. unsat time: " << static_cast<double>(log.cummulative_unsat_runtimes_per_size[i]) / (1000* log.nof_unsat_calls_per_size[i]) << " sec\n";
}
}
}
}
return pThis;
}
ABC_NAMESPACE_IMPL_END

63
src/opt/eslim/eSLIM.h Normal file
View File

@ -0,0 +1,63 @@
/**CFile****************************************************************
FileName [eSLIM.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Interface to the eSLIM package.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: eSLIM.h,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__ESLIM_h
#define ABC__OPT__ESLIM__ESLIM_h
#include "misc/util/abc_namespaces.h"
#include "aig/gia/gia.h"
ABC_NAMESPACE_HEADER_START
typedef struct eSLIM_ParamStruct_ eSLIM_ParamStruct;
struct eSLIM_ParamStruct_ {
int forbidden_pairs; // Allow forbidden pairs in the selected subcircuits
int extended_normality_processing; // Additional checks for non normal subcircuits
int fill_subcircuits; // If a subcircuit has fewer than subcircuit_size_bound gates, try to fill it with rejected gates.
int apply_strash;
int fix_seed;
int trial_limit_active;
int apply_inprocessing;
unsigned int timeout; // available time in seconds (soft limit)
unsigned int timeout_inprocessing;
unsigned int iterations; // maximal number of iterations. No limit if 0
unsigned int subcircuit_size_bound; // upper bound for the subcircuit sizes
unsigned int strash_intervall;
unsigned int nselection_trials;
unsigned int nruns;
double expansion_probability; // the probability that a node is added to the subcircuit
int mode; // 0: Cadical Incremental, 1: Kissat Oneshot
int seed;
int verbosity_level;
};
void seteSLIMParams(eSLIM_ParamStruct* params);
Gia_Man_t* applyeSLIM(Gia_Man_t * pGia, const eSLIM_ParamStruct* params);
Gia_Man_t* applyeSLIMIncremental(Gia_Man_t * pGia, const eSLIM_ParamStruct* params, unsigned int restarts, unsigned int deepsynTimeout);
ABC_NAMESPACE_HEADER_END
#endif

View File

@ -0,0 +1,94 @@
/**CFile****************************************************************
FileName [eSLIMMan.hpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [eSLIM manager.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: eSLIMMan.hpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__ESLIMMAN_h
#define ABC__OPT__ESLIM__ESLIMMAN_h
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include "misc/util/abc_namespaces.h"
#include "misc/vec/vec.h"
#include "aig/gia/gia.h"
#include "misc/util/utilTruth.h" // ioResub.h depends on utilTruth.h
#include "base/io/ioResub.h"
#include "aig/miniaig/miniaig.h"
#include "utils.hpp"
#include "selectionStrategy.hpp"
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
template<class SynthesisEngine, class RelationEngine, class SelectionEngine>
class eSLIM_Man {
public:
static Gia_Man_t* applyeSLIM(Gia_Man_t * p, const eSLIMConfig& cfg, eSLIMLog& log);
private:
eSLIM_Man(Gia_Man_t * gia_man, const eSLIMConfig& cfg, eSLIMLog& log);
Gia_Man_t* getCircuit();
void minimize();
void findReplacement();
Mini_Aig_t* findMinimumAig(const Subcircuit& subcir);
Vec_Wrd_t* getSimsIn(Abc_RData_t* relation);
Vec_Wrd_t* getSimsOut(Abc_RData_t* relation);
word getAllFalseBehaviour(const Subcircuit& subcir);
bool getAllFalseBehaviourRec(Gia_Obj_t * pObj);
std::pair<int, Mini_Aig_t*> reduce( Vec_Wrd_t* vSimsDiv, Vec_Wrd_t* vSimsOut, const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs,
int nVars, int nDivs, int nOuts, int initial_size);
Mini_Aig_t* computeReplacement( SynthesisEngine& syn_man, int size);
double getDynamicTimeout(int size);
void insertReplacement(Mini_Aig_t* replacement, const Subcircuit& subcir);
std::vector<int> processReplacement(Gia_Man_t* gia_man, Gia_Man_t* pNew, const Subcircuit& subcir, Mini_Aig_t* replacement, std::vector<int>&& to_process, std::vector<int>& replacement_values);
Vec_Int_t * processEncompassing(Gia_Man_t* gia_man, Gia_Man_t* pNew, Vec_Int_t* to_process);
int getInsertionLiteral(Gia_Man_t* gia_man, const Subcircuit& subcir, Mini_Aig_t* replacement, const std::vector<int>& replacement_values, int fanin_lit);
Gia_Man_t* gia_man = nullptr;
const eSLIMConfig& cfg;
eSLIMLog& log;
SelectionEngine subcircuit_selection;
double relation_generation_time ;
double synthesis_time ;
bool stopeSLIM=false;
};
template <typename Y, typename R, typename S>
inline Gia_Man_t* eSLIM_Man<Y, R, S>::getCircuit() {
return gia_man;
}
}
ABC_NAMESPACE_CXX_HEADER_END
#include "eSLIMMan.tpp"
#endif

482
src/opt/eslim/eSLIMMan.tpp Normal file
View File

@ -0,0 +1,482 @@
/**CFile****************************************************************
FileName [eSLIMMan.tpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [eSLIM manager.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: eSLIMMan.tpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#include <cassert>
#include <queue>
#include <vector>
#include <tuple>
#include <unordered_set>
#include <iostream>
#include <climits>
#include "eSLIMMan.hpp"
#include "synthesisEngine.hpp"
#include "relationGeneration.hpp"
ABC_NAMESPACE_HEADER_START
Mini_Aig_t * Mini_AigDupCompl( Mini_Aig_t * p, int ComplIns, int ComplOuts );
int Exa6_ManFindPolar( word First, int nOuts );
Vec_Wrd_t * Exa6_ManTransformInputs( Vec_Wrd_t * vIns );
Vec_Wrd_t * Exa6_ManTransformOutputs( Vec_Wrd_t * vOuts, int nOuts );
ABC_NAMESPACE_HEADER_END
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
template <typename Y, typename R, typename S>
Gia_Man_t* eSLIM_Man<Y, R, S>::applyeSLIM(Gia_Man_t * p, const eSLIMConfig& cfg, eSLIMLog& log) {
eSLIM_Man<Y, R, S> eslim(p, cfg, log);
eslim.minimize();
return eslim.getCircuit();
}
template <typename Y, typename R, typename S>
eSLIM_Man<Y, R, S>::eSLIM_Man(Gia_Man_t * pGia, const eSLIMConfig& cfg, eSLIMLog& log)
: gia_man(pGia), cfg(cfg), log(log),
subcircuit_selection(gia_man, cfg, log) {
if (cfg.fix_seed) {
subcircuit_selection.setSeed(cfg.seed);
}
relation_generation_time = log.relation_generation_time;
synthesis_time = log.synthesis_time;
}
template <typename Y, typename R, typename S>
void eSLIM_Man<Y, R, S>::minimize() {
abctime clkStart = Abc_Clock();
abctime nTimeToStop = clkStart + cfg.timeout * CLOCKS_PER_SEC;
unsigned int iteration = 0;
unsigned int iterMax = cfg.iterations ? cfg.iterations - 1 : UINT_MAX;
int current_size = Gia_ManAndNum(gia_man);
while (Abc_Clock() <= nTimeToStop && iteration <= iterMax && !stopeSLIM) {
iteration++;
findReplacement();
if (Gia_ManHasDangling(gia_man)) {
Gia_Man_t* pTemp = gia_man;
gia_man = Gia_ManCleanup( pTemp );
Gia_ManStop( pTemp );
}
if (cfg.apply_strash && iteration % cfg.strash_intervall == 0) {
Gia_Man_t* pTemp = gia_man;
gia_man = Gia_ManRehash( pTemp, 0 );
Gia_ManStop( pTemp );
}
if (cfg.verbosity_level > 0) {
int sz = Gia_ManAndNum(gia_man);
if (sz < current_size) {
current_size = sz;
printf("\rIteration %8d : #and = %7d elapsed time = %7.2f sec\n", iteration, sz, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC);
} else {
printf("\rIteration %8d", iteration);
fflush(stdout);
}
}
}
log.iteration_count += iteration;
if (cfg.verbosity_level > 0) {
int sz = Gia_ManAndNum(gia_man);
printf("\r#Iterations %8d #and = %7d elapsed time = %7.2f sec\n", iteration, sz, (float)1.0*(Abc_Clock() - clkStart)/CLOCKS_PER_SEC);
if (cfg.verbosity_level > 1) {
printf("Relation generation time: %.2f sec\n", log.relation_generation_time - relation_generation_time);
printf("Synthesis time: %.2f sec\n", log.synthesis_time - synthesis_time);
}
}
}
template <typename Y, typename R, typename S>
Vec_Wrd_t* eSLIM_Man<Y, R, S>::getSimsIn(Abc_RData_t* relation) {
Vec_Wrd_t* vSimsDiv = Vec_WrdStart( relation->nPats );
for (int k = 0; k < relation->nIns; k++) {
for (int i = 0; i < relation->nPats; i++) {
if (Abc_RDataGetIn(relation, k, i)) {
// The first bit corresponds to the constant divisor thus we have +1
Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(vSimsDiv, i), 1+k);
}
}
}
return vSimsDiv;
}
template <typename Y, typename R, typename S>
Vec_Wrd_t* eSLIM_Man<Y, R, S>::getSimsOut(Abc_RData_t* relation) {
Vec_Wrd_t* vSimsOut = Vec_WrdStart(relation->nPats);
for (int k = 0; k < (1 << relation->nOuts); k++) {
for (int i = 0; i < relation->nPats; i++) {
if (Abc_RDataGetOut(relation, k, i)) {
Abc_InfoSetBit((unsigned *)Vec_WrdEntryP(vSimsOut, i), k);
}
}
}
return vSimsOut;
}
template <typename Y, typename R, typename S>
void eSLIM_Man<Y, R, S>::findReplacement() {
Subcircuit subcir = subcircuit_selection.getSubcircuit();
if (!subcircuit_selection.getStatus()) {
if (cfg.trial_limit_active) {
stopeSLIM = true;
}
return;
}
Mini_Aig_t* replacement = findMinimumAig(subcir);
if (replacement != nullptr) {
insertReplacement(replacement, subcir);
Mini_AigStop(replacement);
}
subcir.free();
}
// Based on Exa_ManExactSynthesis6Int and Exa_ManExactSynthesis6
template <typename Y, typename R, typename S>
Mini_Aig_t* eSLIM_Man<Y, R, S>::findMinimumAig(const Subcircuit& subcir) {
if (subcir.forbidden_pairs.size() > 0) {
log.subcircuits_with_forbidden_pairs++;
}
abctime relation_generation_start = Abc_Clock();
Abc_RData_t* relation = RelationGenerator<R>::computeRelation(gia_man, subcir);
log.relation_generation_time += (double)1.0*(Abc_Clock() - relation_generation_start)/CLOCKS_PER_SEC;
int nDivs = 0;
int nOuts = relation->nOuts;
int nVars = relation->nIns;
if ( nVars == 0 ) {
return nullptr;
}
// assert (nVars <= 8);
Vec_Wrd_t* vSimsDiv = getSimsIn(relation);
Vec_Wrd_t* vSimsOut = getSimsOut(relation);
word original_all_false_behaviour = vSimsOut->pArray[0];
// If the original circuit computed a non-normal circuit, but the relations allows to set the outputs to false in the all inputs false case
// ABC does not "negate" the relation but forces the circuit to yield (0,...,0) for (0,...,0).
// As a consequence it is not necessarily possible to find a same sized circuit.
// In order to prevent this behaviour, we first modify the relation such that for the (0,...,0) input pattern only the original output patterns is allowed.
vSimsOut->pArray[0] = getAllFalseBehaviour(subcir);
int DivCompl = (int)Vec_WrdEntry(vSimsDiv, 0) >> 1;
int OutCompl = Exa6_ManFindPolar( Vec_WrdEntry(vSimsOut, 0), nOuts );
Vec_Wrd_t* vSimsDiv2 = Exa6_ManTransformInputs( vSimsDiv );
Vec_Wrd_t* vSimsOut2 = Exa6_ManTransformOutputs( vSimsOut, nOuts );
Mini_Aig_t* pMini = nullptr;
int original_size = Vec_IntSize(subcir.nodes);
int size = original_size;
if (log.nof_analyzed_circuits_per_size.size() < original_size + 1) {
log.nof_analyzed_circuits_per_size.resize(original_size + 1, 0);
log.nof_replaced_circuits_per_size.resize(original_size + 1, 0);
log.nof_reduced_circuits_per_size.resize(original_size + 1, 0);
}
log.nof_analyzed_circuits_per_size[original_size]++;
abctime synthesis_start = Abc_Clock();
std::tie(size, pMini) = reduce(vSimsDiv2, vSimsOut2, subcir.forbidden_pairs, nVars, nDivs, nOuts, size);
log.synthesis_time += (double)1.0*(Abc_Clock() - synthesis_start)/CLOCKS_PER_SEC;
if (size > original_size) {
// Could not find a replacement. This can be caused by a timeout.
Abc_RDataStop(relation);
Vec_WrdFreeP( &vSimsDiv );
Vec_WrdFreeP( &vSimsOut );
Vec_WrdFreeP( &vSimsDiv2 );
Vec_WrdFreeP( &vSimsOut2 );
return nullptr;
}
// It is possible that a better replacement is obtained with a non normal behaviour.
bool check_original_all_false_behaviour = cfg.extended_normality_processing && vSimsOut->pArray[0] != original_all_false_behaviour;
if (check_original_all_false_behaviour) {
vSimsOut->pArray[0] = original_all_false_behaviour;
int OutCompl_alt = Exa6_ManFindPolar( Vec_WrdEntry(vSimsOut, 0), nOuts );
Vec_Wrd_t* vSimsOut2_alt = Exa6_ManTransformOutputs( vSimsOut, nOuts );
abctime synthesis_start = Abc_Clock();
// auto [sz, mini] = reduce(vSimsDiv2, vSimsOut2_alt, subcir.forbidden_pairs, nVars, nDivs, nOuts, size - 1, true);
auto result = reduce(vSimsDiv2, vSimsOut2_alt, subcir.forbidden_pairs, nVars, nDivs, nOuts, size - 1);
int sz = result.first;
Mini_Aig_t* mini = result.second;
log.synthesis_time += (double)1.0*(Abc_Clock() - synthesis_start)/CLOCKS_PER_SEC;
if (mini != nullptr) {
size = sz;
if (pMini) {
Mini_AigStop(pMini);
}
pMini = mini;
OutCompl = OutCompl_alt;
}
}
Abc_RDataStop(relation);
if (pMini != nullptr) {
Mini_Aig_t* pTemp = pMini;
pMini = Mini_AigDupCompl(pTemp, DivCompl, OutCompl);
Mini_AigStop(pTemp);
log.nof_replaced_circuits_per_size[original_size]++;
if (size < original_size) {
log.nof_reduced_circuits_per_size[original_size]++;
}
}
Vec_WrdFreeP( &vSimsDiv );
Vec_WrdFreeP( &vSimsOut );
Vec_WrdFreeP( &vSimsDiv2 );
Vec_WrdFreeP( &vSimsOut2 );
return pMini;
}
template <typename Y, typename R, typename S>
word eSLIM_Man<Y, R, S>::getAllFalseBehaviour(const Subcircuit& subcir) {
Gia_ManIncrementTravId(gia_man);
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObjVec( subcir.nodes, gia_man, pObj, i ) {
Gia_ObjSetTravIdCurrent(gia_man, pObj);
}
long assm_idx = 0;
Gia_ManForEachObjVecStart(subcir.io, gia_man, pObj, i, subcir.nof_inputs) {
int bit_idx = i - subcir.nof_inputs;
if (getAllFalseBehaviourRec(pObj)) {
assm_idx |= (1 << bit_idx);
}
}
return 1L << assm_idx;
}
template <typename Y, typename R, typename S>
bool eSLIM_Man<Y, R, S>::getAllFalseBehaviourRec(Gia_Obj_t * pObj) {
bool valuefanin0, valuefanin1;
if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj))) {
valuefanin0 = getAllFalseBehaviourRec(Gia_ObjFanin0(pObj));
} else {
valuefanin0 = false;
}
valuefanin0 = valuefanin0 != pObj->fCompl0;
if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) {
valuefanin1 = getAllFalseBehaviourRec(Gia_ObjFanin1(pObj));
} else {
valuefanin1 = false;
}
valuefanin1 = valuefanin1 != pObj->fCompl1;
return valuefanin0 && valuefanin1;
}
template <typename Y, typename R, typename S>
int eSLIM_Man<Y, R, S>::getInsertionLiteral(Gia_Man_t* gia_man, const Subcircuit& subcir, Mini_Aig_t* replacement, const std::vector<int>& replacement_values, int fanin_lit) {
int fanin_idx = Abc_Lit2Var(fanin_lit);
bool fanin_negated = Abc_LitIsCompl(fanin_lit);
int fanin_value;
if (fanin_idx == 0) { // constant fanin
fanin_value = 0;
} else if (fanin_idx <= subcir.nof_inputs) {
Gia_Obj_t* pObj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin_idx - 1));
if (Gia_ObjIsTravIdCurrent(gia_man, pObj)) { //the node has already been added
fanin_value = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin_idx - 1))->Value;
} else {
return -1;
}
} else {
if (replacement_values[fanin_idx - subcir.nof_inputs - 1] == -1) {
return -1;
}
fanin_value = replacement_values[fanin_idx - subcir.nof_inputs - 1];
}
return Abc_LitNotCond( fanin_value, fanin_negated );
}
template <typename Y, typename R, typename S>
std::vector<int> eSLIM_Man<Y, R, S>::processReplacement(Gia_Man_t* gia_man, Gia_Man_t* pNew, const Subcircuit& subcir, Mini_Aig_t* replacement, std::vector<int>&& to_process, std::vector<int>& replacement_values) {
std::vector<int> to_process_next_it;
for (int id : to_process) {
int fanin0 = getInsertionLiteral(gia_man, subcir, replacement, replacement_values, Mini_AigNodeFanin0( replacement, id));
int fanin1 = getInsertionLiteral(gia_man, subcir, replacement, replacement_values, Mini_AigNodeFanin1( replacement, id));
if (fanin0 == -1 || fanin1 == -1) {
to_process_next_it.push_back(id);
} else {
int idx = id - subcir.nof_inputs - 1;
replacement_values[idx] = Gia_ManAppendAnd2(pNew, fanin0, fanin1);
}
}
int i, j = 0;
Mini_AigForEachPo(replacement, i) {
int old_id = Vec_IntEntry(subcir.io, j + subcir.nof_inputs);
j++;
Gia_Obj_t* obj = Gia_ManObj(gia_man, old_id);
int fanin0_lit = Mini_AigNodeFanin0( replacement, i);
int fanin0_idx = Abc_Lit2Var(fanin0_lit);
if (fanin0_idx == 0) { // constant fanin
obj->Value = Gia_ManConst0(gia_man)->Value;
} else if (fanin0_idx <= subcir.nof_inputs) {
Gia_Obj_t* fanin_obj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin0_idx - 1));
if (Gia_ObjIsTravIdCurrent(gia_man, fanin_obj)) {
obj->Value = fanin_obj->Value;
} else {
continue;
}
} else {
if (replacement_values[fanin0_idx - subcir.nof_inputs - 1] == -1 ) {
continue;
} else {
obj->Value = replacement_values[fanin0_idx - subcir.nof_inputs - 1];
}
}
Gia_ObjSetTravIdCurrent(gia_man, obj);
bool fanin0_negated = Abc_LitIsCompl(fanin0_lit);
if (fanin0_negated) {
obj->fMark0 = 1;
}
}
return to_process_next_it;
}
template <typename Y, typename R, typename S>
Vec_Int_t * eSLIM_Man<Y, R, S>::processEncompassing(Gia_Man_t* gia_man, Gia_Man_t* pNew, Vec_Int_t * to_process) {
int i;
Gia_Obj_t * pObj;
Vec_Int_t * to_process_remaining = Vec_IntAlloc( Vec_IntSize(to_process) );
Gia_ManForEachObjVec( to_process, gia_man, pObj, i ) {
if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) {
Gia_ObjSetTravIdCurrent(gia_man, pObj);
bool fanin0_negated = Gia_ObjFaninC0(pObj) ^ Gia_ObjFanin0(pObj)->fMark0;
bool fanin1_negated = Gia_ObjFaninC1(pObj) ^ Gia_ObjFanin1(pObj)->fMark0;
int fanin0 = Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, fanin0_negated);
int fanin1 = Abc_LitNotCond(Gia_ObjFanin1(pObj)->Value, fanin1_negated);
pObj->Value = Gia_ManAppendAnd2( pNew, fanin0, fanin1);
} else {
Vec_IntPush(to_process_remaining, Gia_ObjId(gia_man, pObj));
}
}
Vec_IntFree(to_process);
return to_process_remaining;
}
template <typename Y, typename R, typename S>
void eSLIM_Man<Y, R, S>::insertReplacement(Mini_Aig_t* replacement, const Subcircuit& subcir) {
// A miniaig contains a constant node, nodes for each PI/PO and for each and.
int repalcement_size = Mini_AigNodeNum(replacement) - Vec_IntSize(subcir.io) - 1;
int size_diff = Vec_IntSize(subcir.nodes) - repalcement_size;
Gia_Man_t * pNew = Gia_ManStart( Gia_ManObjNum(gia_man) - size_diff );
pNew->pName = Abc_UtilStrsav( gia_man->pName );
pNew->pSpec = Abc_UtilStrsav( gia_man->pSpec );
Gia_Obj_t * pObj;
int i;
Gia_ManConst0(gia_man)->Value = 0;
Gia_ManForEachPi( gia_man, pObj, i ) {
pObj->Value = Gia_ManAppendCi(pNew);
}
Gia_ManIncrementTravId(gia_man);
Gia_ManForEachObjVec( subcir.nodes, gia_man, pObj, i ) {
Gia_ObjSetTravIdCurrent(gia_man, pObj);
}
Gia_ManIncrementTravId(gia_man);
Gia_ManForEachPi( gia_man, pObj, i ) {
Gia_ObjSetTravIdCurrent(gia_man, pObj);
}
Vec_Int_t * to_process_encompassing = Vec_IntAlloc( gia_man->nObjs );
Gia_ManForEachAnd( gia_man, pObj, i ) {
// nodes from the subcircuit shall not be added
if (Gia_ObjIsTravIdPrevious(gia_man, pObj)) {
continue;
} else if (Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)) && Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) {
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ObjSetTravIdCurrent(gia_man, pObj);
} else {
Vec_IntPush(to_process_encompassing, Gia_ObjId(gia_man, pObj));
}
}
std::vector<int> to_process_replacement;
Mini_AigForEachAnd(replacement, i) {
to_process_replacement.push_back(i);
}
std::vector<int> replacement_values(to_process_replacement.size(), -1);
while (Vec_IntSize(to_process_encompassing) > 0 || to_process_replacement.size() > 0) {
to_process_replacement = processReplacement(gia_man, pNew, subcir, replacement, std::move(to_process_replacement), replacement_values);
to_process_encompassing = processEncompassing(gia_man, pNew, to_process_encompassing);
}
Vec_IntFree(to_process_encompassing);
int po_idx = 0;
Mini_AigForEachPo(replacement, i) {
Gia_Obj_t* pObj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, subcir.nof_inputs + po_idx));
if (!Gia_ObjIsTravIdCurrent(gia_man, pObj)) {
int fanin_lit = Mini_AigNodeFanin0( replacement, i);
int fanin_idx = Abc_Lit2Var(fanin_lit);
assert (fanin_idx <= subcir.nof_inputs);
Gia_Obj_t* fanin_obj = Gia_ManObj(gia_man, Vec_IntEntry(subcir.io, fanin_idx - 1));
pObj->Value = fanin_obj->Value;
if (Abc_LitIsCompl(fanin_lit)) {
pObj->fMark0 = 1;
}
Gia_ObjSetTravIdCurrent(gia_man, pObj);
}
po_idx++;
}
Gia_ManForEachPo( gia_man, pObj, i ) {
assert(Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj)));
bool fanin_negated = Gia_ObjFaninC0(pObj) ^ Gia_ObjFanin0(pObj)->fMark0;
int fanin0 = Abc_LitNotCond(Gia_ObjFanin0(pObj)->Value, fanin_negated);
pObj->Value = Gia_ManAppendCo( pNew, fanin0 );
}
Gia_ManStop(gia_man);
gia_man = pNew;
}
template <typename Y, typename R, typename S>
std::pair<int, Mini_Aig_t*> eSLIM_Man<Y, R, S>::reduce(Vec_Wrd_t* vSimsDiv, Vec_Wrd_t* vSimsOut, const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs,
int nVars, int nDivs, int nOuts, int size) {
Y synth_man(vSimsDiv,vSimsOut,nVars,1+nVars+nDivs,nOuts,size, forbidden_pairs, log, cfg);
Mini_Aig_t* result = nullptr;
while (size >= 0) {
Mini_Aig_t* pTemp = computeReplacement(synth_man, size);
if (pTemp) {
if (result) {
Mini_AigStop(result);
}
result = pTemp;
size--;
} else {
break;
}
}
return std::make_pair(size + 1, result);
}
template <typename Y, typename R, typename S>
double eSLIM_Man<Y, R, S>::getDynamicTimeout(int size) {
if (this->log.nof_sat_calls_per_size[size] > cfg.minimum_dynamic_timeout_sample_size) {
return std::max(static_cast<double>(cfg.minimum_sat_timeout), static_cast<double>(log.cummulative_sat_runtimes_per_size[size]) / (1000*log.nof_sat_calls_per_size[size])); //logged timings are given in ms
} else {
return cfg.base_sat_timeout;
}
}
template <typename Y, typename R, typename S>
Mini_Aig_t* eSLIM_Man<Y, R, S>::computeReplacement(Y& syn_man, int size) {
return syn_man.getCircuit(size, getDynamicTimeout(size));
}
}
ABC_NAMESPACE_CXX_HEADER_END

View File

@ -0,0 +1,2 @@
SRC += src/opt/eslim/relationGeneration.cpp \
src/opt/eslim/eSLIM.cpp

View File

@ -0,0 +1,172 @@
/**CFile****************************************************************
FileName [relationGeneration.cpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Procedures for computing Boolean relations.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: relationGeneration.cpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#include <cassert>
#include "misc/vec/vec.h"
#include "sat/cnf/cnf.h"
#include "sat/bsat/satSolver.h"
#include "relationGeneration.hpp"
ABC_NAMESPACE_HEADER_START
void * Mf_ManGenerateCnf( Gia_Man_t * pGia, int nLutSize, int fCnfObjIds, int fAddOrCla, int fMapping, int fVerbose );
void * Cnf_DataWriteIntoSolver( Cnf_Dat_t * p, int nFrames, int fInit );
Vec_Int_t * Gia_ManCollectNodeTfos( Gia_Man_t * p, int * pNodes, int nNodes );
Vec_Int_t * Gia_ManCollectNodeTfis( Gia_Man_t * p, Vec_Int_t * vNodes );
ABC_NAMESPACE_HEADER_END
ABC_NAMESPACE_IMPL_START
namespace eSLIM {
RelationGeneratorABC::RelationGeneratorABC(Gia_Man_t* pGia, const Subcircuit& subcir)
: RelationGenerator(pGia, subcir) {
// for (const auto& [out, inputs] : subcir.forbidden_pairs) {
for (const auto& it: subcir.forbidden_pairs) {
const auto& inputs = it.second;
inputs_in_forbidden_pairs.insert(inputs.begin(), inputs.end());
}
}
Vec_Int_t* RelationGeneratorABC::getRelationImpl() {
abctime clkStart = Abc_Clock();
int nTimeOut = 600, nConfLimit = 1000000;
int i, iNode, iSatVar, Iter, Mask, nSolutions = 0, RetValue = 0;
// --------------- Modification ---------------
Gia_Man_t* pMiter = generateMiter();
// --------------- Modification ---------------
Cnf_Dat_t * pCnf = (Cnf_Dat_t*)Mf_ManGenerateCnf( pMiter, 8, 0, 0, 0, 0 );
sat_solver * pSat = (sat_solver*)Cnf_DataWriteIntoSolver( pCnf, 1, 0 );
int iLit = Abc_Var2Lit( 1, 0 ); // enumerating the care set (the miter output is 1)
int status = sat_solver_addclause( pSat, &iLit, &iLit + 1 ); assert( status );
Vec_Int_t * vSatVars = Vec_IntAlloc( Vec_IntSize(subcir.io) );
Vec_IntForEachEntry( subcir.io, iNode, i )
Vec_IntPush( vSatVars, i < subcir.nof_inputs ? 2+i : pCnf->nVars-Vec_IntSize(subcir.io)+i );
Vec_Int_t * vLits = Vec_IntAlloc( 100 );
Vec_Int_t * vRes = Vec_IntAlloc( 1000 );
for ( Iter = 0; Iter < 1000000; Iter++ )
{
int status = sat_solver_solve( pSat, NULL, NULL, (ABC_INT64_T)nConfLimit, 0, 0, 0 );
if ( status == l_False ) { RetValue = 1; break; }
if ( status == l_Undef ) { RetValue = 0; break; }
nSolutions++;
// extract SAT assignment
Mask = 0;
Vec_IntClear( vLits );
Vec_IntForEachEntry( vSatVars, iSatVar, i ) {
Vec_IntPush( vLits, Abc_Var2Lit(iSatVar, sat_solver_var_value(pSat, iSatVar)) );
if ( sat_solver_var_value(pSat, iSatVar) )
Mask |= 1 << (Vec_IntSize(subcir.io)-1-i);
}
Vec_IntPush( vRes, Mask );
if ( !sat_solver_addclause( pSat, Vec_IntArray(vLits), Vec_IntArray(vLits) + Vec_IntSize(vLits) ) )
{ RetValue = 1; break; }
if ( nTimeOut && (Abc_Clock() - clkStart)/CLOCKS_PER_SEC >= nTimeOut ) { RetValue = 0; break; }
}
// complement the set of input/output minterms
Vec_Int_t * vBits = Vec_IntStart( 1 << Vec_IntSize(subcir.io) );
Vec_IntForEachEntry( vRes, Mask, i )
Vec_IntWriteEntry( vBits, Mask, 1 );
Vec_IntClear( vRes );
Vec_IntForEachEntry( vBits, Mask, i )
if ( !Mask )
Vec_IntPush( vRes, i );
Vec_IntFree( vBits );
// cleanup
Vec_IntFree( vLits );
Vec_IntFree( vSatVars );
sat_solver_delete( pSat );
Gia_ManStop( pMiter );
Cnf_DataFree( pCnf );
if ( RetValue == 0 )
Vec_IntFreeP( &vRes );
return vRes;
}
Gia_Man_t * RelationGeneratorABC::generateMiter() {
Vec_Int_t * vInsOuts = subcir.io;
int nIns = subcir.nof_inputs;
Vec_Int_t * vTfo = Gia_ManCollectNodeTfos( pGia, Vec_IntEntryP(vInsOuts, nIns), Vec_IntSize(vInsOuts)-nIns );
Vec_Int_t * vTfi = Gia_ManCollectNodeTfis( pGia, vTfo );
Vec_Int_t * vInLits = Vec_IntAlloc( nIns );
Vec_Int_t * vOutLits = Vec_IntAlloc( Vec_IntSize(vInsOuts) - nIns );
Gia_Man_t * pNew, * pTemp; Gia_Obj_t * pObj; int i, iLit = 0;
Gia_ManFillValue( pGia );
pNew = Gia_ManStart( 1000 );
pNew->pName = Abc_UtilStrsav( pGia->pName );
Gia_ManHashAlloc( pNew );
Gia_ManForEachObjVec( vTfi, pGia, pObj, i )
if ( Gia_ObjIsCi(pObj) )
pObj->Value = Gia_ManAppendCi(pNew);
for ( i = 0; i < Vec_IntSize(vInsOuts)-nIns; i++ )
Vec_IntPush( vInLits, Gia_ManAppendCi(pNew) );
Gia_ManForEachObjVec( vTfi, pGia, pObj, i )
if ( Gia_ObjIsAnd(pObj) )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachObjVec( vTfo, pGia, pObj, i )
if ( Gia_ObjIsCo(pObj) )
pObj->Value = Gia_ObjFanin0Copy(pObj);
Gia_ManForEachObjVec( vInsOuts, pGia, pObj, i )
if ( i < nIns )
Vec_IntPush( vOutLits, pObj->Value );
else
pObj->Value = Vec_IntEntry( vInLits, i-nIns );
Gia_ManIncrementTravId(pGia);
Gia_ManForEachObjVec( subcir.nodes, pGia, pObj, i ) {
Gia_ObjSetTravIdCurrent(pGia, pObj);
}
Gia_ManForEachObjVec( vTfo, pGia, pObj, i )
// in case there are forbidden pairs we have to ensure that nodes from the sucircuit are not added
if ( Gia_ObjIsAnd(pObj) && !Gia_ObjIsTravIdCurrent(pGia, pObj) )
pObj->Value = Gia_ManHashAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
Gia_ManForEachObjVec( vTfo, pGia, pObj, i )
if ( Gia_ObjIsCo(pObj) )
iLit = Gia_ManHashOr( pNew, iLit, Gia_ManHashXor(pNew, Gia_ObjFanin0Copy(pObj), pObj->Value) );
// --------------- Modification ---------------
// In case there are forbidden pairs, the outputs of the subcircuit influence the inputs of the subcircuit.
// Therefore, we need the values of the inputs in the version of the circuit that is affected by the new outputs.
for (int inp : inputs_in_forbidden_pairs) {
int node_id = Vec_IntEntry(vInsOuts, inp);
pObj = Gia_ManObj(pGia, node_id);
Vec_IntWriteEntry(vOutLits, inp, pObj->Value);
}
// --------------- Modification ---------------
Gia_ManAppendCo( pNew, iLit );
Vec_IntForEachEntry( vOutLits, iLit, i )
Gia_ManAppendCo( pNew, iLit );
Vec_IntFree( vTfo );
Vec_IntFree( vTfi );
Vec_IntFree( vInLits );
Vec_IntFree( vOutLits );
pNew = Gia_ManCleanup( pTemp = pNew );
Gia_ManStop( pTemp );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(pGia) );
return pNew;
}
}
ABC_NAMESPACE_IMPL_END

View File

@ -0,0 +1,195 @@
/**CFile****************************************************************
FileName [relationGeneration.hpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Procedures for computing Boolean relations.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: relationGeneration.hpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__RELATIONGENERATION_h
#define ABC__OPT__ESLIM__RELATIONGENERATION_h
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include "misc/util/abc_namespaces.h"
#include <misc/util/abc_global.h>
#include "aig/gia/gia.h"
#include "misc/util/utilTruth.h" // ioResub.h depends on utilTruth.h
#include "base/io/ioResub.h"
#include "utils.hpp"
// #include "satInterfaces.hpp"
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
template<class Derived>
class RelationGenerator {
public:
static Abc_RData_t* computeRelation(Gia_Man_t* gia_man, const Subcircuit& subcir);
private:
Gia_Man_t* pGia;
const Subcircuit& subcir;
RelationGenerator(Gia_Man_t* pGia, const Subcircuit& subcir);
void setup();
Vec_Int_t* getRelation();
static Abc_RData_t* constructABCRelationRepresentation(Vec_Int_t * patterns, int nof_inputs, int nof_outputs);
// Reimplementation with disabled prints
// We do not want to modify code in other parts of ABC
static Abc_RData_t * Abc_RData2Rel( Abc_RData_t * p );
friend Derived;
};
// The class almost entirely duplicates the functionality provided by Gia_ManGenIoCombs in giaQBF.c
// But the implementation in this class allows to take forbidden pairs into account.
class RelationGeneratorABC : public RelationGenerator<RelationGeneratorABC> {
private:
RelationGeneratorABC(Gia_Man_t* pGia, const Subcircuit& subcir);
void setupImpl() {};
Vec_Int_t* getRelationImpl();
Gia_Man_t * generateMiter();
std::unordered_set<int> inputs_in_forbidden_pairs;
friend RelationGenerator;
};
// Add other engine for the generation of relations
// class MyRelationGenerator : public RelationGenerator<MyRelationGenerator> {
// private:
// void setupImpl()
// Vec_Int_t* getRelationImpl();
// friend RelationGenerator;
// };
template <typename T>
inline RelationGenerator<T>::RelationGenerator(Gia_Man_t* pGia, const Subcircuit& subcir)
: pGia(pGia), subcir(subcir) {
}
template <typename T>
inline Abc_RData_t* RelationGenerator<T>::computeRelation(Gia_Man_t* gia_man, const Subcircuit& subcir) {
T generator(gia_man, subcir);
generator.setup();
Vec_Int_t* relation_patterns_masks = generator.getRelation();
if ( relation_patterns_masks == NULL ) {
return nullptr;
}
int nof_inputs = subcir.nof_inputs;
int nof_outputs = Vec_IntSize(subcir.io) - subcir.nof_inputs;
Abc_RData_t* r = constructABCRelationRepresentation(relation_patterns_masks, nof_inputs, nof_outputs);
Vec_IntFree(relation_patterns_masks);
return r;
}
template <typename T>
inline Abc_RData_t* RelationGenerator<T>::constructABCRelationRepresentation(Vec_Int_t * patterns, int nof_inputs, int nof_outputs) {
int i, mask;
int nof_vars = nof_inputs + nof_outputs;
Abc_RData_t* p = Abc_RDataStart( nof_inputs, nof_outputs, Vec_IntSize(patterns) );
Vec_IntForEachEntry( patterns, mask, i ) {
for ( int k = 0; k < nof_vars; k++ ) {
if ( (mask >> (nof_vars-1-k)) & 1 ) {
if ( k < nof_inputs ) {
Abc_RDataSetIn( p, k, i );
} else {
Abc_RDataSetOut( p, 2*(k-nof_inputs)+1, i );
}
} else {
if ( k >= nof_inputs ) {
Abc_RDataSetOut( p, 2*(k-nof_inputs), i );
}
}
}
}
Abc_RData_t* p2 = Abc_RData2Rel(p);
Abc_RDataStop(p);
return p2;
}
template <typename T>
inline Abc_RData_t * RelationGenerator<T>::Abc_RData2Rel( Abc_RData_t * p ) {
assert( p->nIns < 64 );
assert( p->nOuts < 32 );
int w;
Vec_Wrd_t * vSimsIn2 = Vec_WrdStart( 64*p->nSimWords );
Vec_Wrd_t * vSimsOut2 = Vec_WrdStart( 64*p->nSimWords );
for ( w = 0; w < p->nIns; w++ )
Abc_TtCopy( Vec_WrdEntryP(vSimsIn2, w*p->nSimWords), Vec_WrdEntryP(p->vSimsIn, w*p->nSimWords), p->nSimWords, 0 );
for ( w = 0; w < p->nOuts; w++ )
Abc_TtCopy( Vec_WrdEntryP(vSimsOut2, w*p->nSimWords), Vec_WrdEntryP(p->vSimsOut, (2*w+1)*p->nSimWords), p->nSimWords, 0 );
Vec_Wrd_t * vTransIn = Vec_WrdStart( 64*p->nSimWords );
Vec_Wrd_t * vTransOut = Vec_WrdStart( 64*p->nSimWords );
Extra_BitMatrixTransposeP( vSimsIn2, p->nSimWords, vTransIn, 1 );
Extra_BitMatrixTransposeP( vSimsOut2, p->nSimWords, vTransOut, 1 );
Vec_WrdShrink( vTransIn, p->nPats );
Vec_WrdShrink( vTransOut, p->nPats );
Vec_Wrd_t * vTransInCopy = Vec_WrdDup(vTransIn);
Vec_WrdUniqify( vTransInCopy );
// if ( Vec_WrdSize(vTransInCopy) == p->nPats )
// printf( "This resub problem is not a relation.\n" );
// create the relation
Abc_RData_t * pNew = Abc_RDataStart( p->nIns, 1 << (p->nOuts-1), Vec_WrdSize(vTransInCopy) );
pNew->nOuts = p->nOuts;
int i, k, n, iLine = 0; word Entry, Entry2;
Vec_WrdForEachEntry( vTransInCopy, Entry, i ) {
for ( n = 0; n < p->nIns; n++ )
if ( (Entry >> n) & 1 )
Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(pNew->vSimsIn, n*pNew->nSimWords), iLine );
Vec_WrdForEachEntry( vTransIn, Entry2, k ) {
if ( Entry != Entry2 )
continue;
Entry2 = Vec_WrdEntry( vTransOut, k );
assert( Entry2 < (1 << p->nOuts) );
Abc_InfoSetBit( (unsigned *)Vec_WrdEntryP(pNew->vSimsOut, Entry2*pNew->nSimWords), iLine );
}
iLine++;
}
assert( iLine == pNew->nPats );
Vec_WrdFree( vTransOut );
Vec_WrdFree( vTransInCopy );
Vec_WrdFree( vTransIn );
Vec_WrdFree( vSimsIn2 );
Vec_WrdFree( vSimsOut2 );
return pNew;
}
template <typename T>
inline void RelationGenerator<T>::setup() {
static_cast<T*>(this)->setupImpl();
}
template <typename T>
inline Vec_Int_t* RelationGenerator<T>::getRelation() {
return static_cast<T*>(this)->getRelationImpl();
}
}
ABC_NAMESPACE_CXX_HEADER_END
#endif

View File

@ -0,0 +1,196 @@
/**CFile****************************************************************
FileName [satInterfaces.hpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Interface to SAT solvers.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: satInterfaces.hpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__SATINTERFACE_h
#define ABC__OPT__ESLIM__SATINTERFACE_h
#include <vector>
#include <chrono>
#include <iostream>
#include "misc/util/abc_namespaces.h"
#include "misc/vec/vec.h"
#include "sat/kissat/kissat.h"
#include "sat/cadical/cadical.hpp"
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
class CadicalSolver {
public:
void addClause(int * pLits, int nLits );
void assume(const std::vector<int>& assumptions);
int solve(double timeout);
int solve();
Vec_Int_t* getModelVec();
double getRunTime() const;
private:
int val(int variable);
double last_runtime;
CaDiCaL::Solver solver;
public:
class TimeoutTerminator : public CaDiCaL::Terminator {
public:
TimeoutTerminator(double max_runtime);
bool terminate();
private:
double max_runtime; //in seconds
std::chrono::time_point<std::chrono::steady_clock> start = std::chrono::steady_clock::now();
};
};
class KissatSolver {
public:
KissatSolver();
~KissatSolver();
void init(int max_var);
void addClause(int * pLits, int nLits );
int solve();
// int solve(int timeout);
Vec_Int_t* getModelVec();
private:
int max_var = 0;
int val(int variable);
kissat * solver = nullptr;
};
inline CadicalSolver::TimeoutTerminator::TimeoutTerminator(double max_runtime) : max_runtime(max_runtime) {}
inline bool CadicalSolver::TimeoutTerminator::terminate() {
auto current_time = std::chrono::steady_clock::now();
std::chrono::duration<double> elapsed_seconds = current_time - start;
return elapsed_seconds.count() > max_runtime;
}
inline double CadicalSolver::getRunTime() const {
return last_runtime;
}
inline void CadicalSolver::addClause(int * pLits, int nLits ) {
for ( int i = 0; i < nLits; i++ ) {
if (pLits[i] == 0) {
continue;;
}
solver.add(Abc_LitIsCompl(pLits[i]) ? -Abc_Lit2Var(pLits[i]) : Abc_Lit2Var(pLits[i]));
}
solver.add(0);
}
inline void CadicalSolver::assume(const std::vector<int>& assumptions) {
for (auto& l: assumptions) {
solver.assume(l);
}
}
inline int CadicalSolver::solve() {
std::chrono::time_point<std::chrono::steady_clock> start = std::chrono::steady_clock::now();
int status = solver.solve();
last_runtime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
return status;
}
inline int CadicalSolver::solve(double timeout) {
std::chrono::time_point<std::chrono::steady_clock> start = std::chrono::steady_clock::now();
TimeoutTerminator terminator(timeout);
solver.connect_terminator(&terminator);
int status = solver.solve();
last_runtime = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - start).count();
if (solver.state() == CaDiCaL::INVALID) {
std::cerr<<"Solver is in invalid state"<<std::endl;
return -1;
}
solver.disconnect_terminator();
return status;
}
inline Vec_Int_t* CadicalSolver::getModelVec() {
Vec_Int_t* assignment = Vec_IntAlloc( solver.vars() );
for (int v = 1; v <= solver.vars(); v++) {
Vec_IntSetEntryFull( assignment, Abc_AbsInt(val(v)), val(v) > 0 );
}
return assignment;
}
inline int CadicalSolver::val(int variable) {
auto l = solver.val(variable);
auto v = abs(l);
if (v == variable) {
return l;
} else {
return variable;
}
}
inline KissatSolver::KissatSolver() {
solver = kissat_init();
}
inline KissatSolver::~KissatSolver() {
kissat_release(solver);
}
inline void KissatSolver::init(int max_var) {
this->max_var = max_var;
kissat_reserve(solver, max_var);
}
inline void KissatSolver::addClause(int * pLits, int nLits ) {
for ( int i = 0; i < nLits; i++ ) {
if (pLits[i] == 0) {
continue;
}
kissat_add (solver, Abc_LitIsCompl(pLits[i]) ? -Abc_Lit2Var(pLits[i]) : Abc_Lit2Var(pLits[i]));
}
kissat_add (solver, 0);
}
inline int KissatSolver::solve() {
int status = kissat_solve(solver);
return status;
}
inline int KissatSolver::val(int variable) {
int l = kissat_value (solver, variable);
auto v = abs(l);
if (v == variable) {
return l;
} else {
return variable;
}
}
inline Vec_Int_t* KissatSolver::getModelVec() {
Vec_Int_t* assignment = Vec_IntAlloc( max_var );
for (int v = 1; v <= max_var; v++) {
Vec_IntSetEntryFull( assignment, Abc_AbsInt(val(v)), val(v) > 0 );
}
return assignment;
}
}
ABC_NAMESPACE_CXX_HEADER_END
#endif

View File

@ -0,0 +1,154 @@
/**CFile****************************************************************
FileName [selectionStrategy.hpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Procedures for selecting subcircuits.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: selectionStrategy.hpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__SELECTIONSTRATEGY_h
#define ABC__OPT__ESLIM__SELECTIONSTRATEGY_h
#include <random>
#include <queue>
#include "misc/util/abc_namespaces.h"
#include "misc/vec/vec.h"
#include "aig/gia/gia.h"
#include "utils.hpp"
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
template<typename T>
class SelectionStrategy {
public:
Subcircuit getSubcircuit();
bool getStatus() {return status;};
void setSeed(int seed);
protected:
SelectionStrategy(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log);
unsigned int getUniformRandomNumber(unsigned int lower, unsigned int upper); // requires lower < upper
bool getRandomBool();
int getSubcircuitIO(Vec_Int_t* subcircuit, Vec_Int_t* io);
// The resulting map assigns inputs of the subcircuit to outputs of the subcircuit s.t. each associated input is reachable from the output
std::unordered_map<int, std::unordered_set<int>> computeForbiddenPairs(const Subcircuit& subcir);
Gia_Man_t*& gia_man;
const eSLIMConfig& cfg;
eSLIMLog& log;
private:
bool filterSubcircuit(const Subcircuit& subcir);
void forbiddenPairsRec(Gia_Obj_t * pObj, int input, int min_level, std::unordered_map<int, std::unordered_set<int>>& pairs, const std::unordered_map<int,int>& out_ids );
bool status = true; //set to false if selection fails too often
static constexpr unsigned int min_size = 2;
std::mt19937 rng;
std::bernoulli_distribution bdist;
std::uniform_int_distribution<std::mt19937::result_type> udistr;
};
template<typename T>
class randomizedBFS : public SelectionStrategy<T> {
private:
randomizedBFS(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log);
Subcircuit findSubcircuit();
int selectRoot();
void checkCandidate(Subcircuit& subcircuit, std::queue<int>& candidate, std::queue<int>& rejected, bool add);
const int nPis;
const int nPos;
friend SelectionStrategy<T>;
friend T;
};
class randomizedBFSFP : public randomizedBFS<randomizedBFSFP> {
public :
randomizedBFSFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log);
private:
Subcircuit getSubcircuitImpl();
bool filterSubcircuitImpl(const Subcircuit& subcir);
friend SelectionStrategy<randomizedBFSFP>;
};
class randomizedBFSnoFP : public randomizedBFS<randomizedBFSnoFP> {
public:
randomizedBFSnoFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log);
private:
Subcircuit getSubcircuitImpl() {return findSubcircuit();};
bool filterSubcircuitImpl(const Subcircuit& subcir);
bool filterSubcircuitRec(Gia_Obj_t * pObj, unsigned int min_level);
friend SelectionStrategy<randomizedBFSnoFP>;
};
template<typename T>
SelectionStrategy<T>::SelectionStrategy(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log)
: gia_man(gia_man), cfg(cfg), log(log), rng(std::random_device()()), bdist(cfg.expansion_probability) {
}
template<typename T>
void SelectionStrategy<T>::setSeed(int seed) {
rng.seed(seed);
}
template<typename T>
unsigned int SelectionStrategy<T>::getUniformRandomNumber(unsigned int lower, unsigned int upper) {
udistr.param(std::uniform_int_distribution<std::mt19937::result_type>::param_type(lower, upper));
return udistr(rng);
}
template<typename T>
bool SelectionStrategy<T>::getRandomBool() {
return bdist(rng);
}
template<typename T>
randomizedBFS<T>::randomizedBFS(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log)
: SelectionStrategy<T>(gia_man, cfg, log), nPis(Gia_ManPiNum(gia_man)), nPos(Gia_ManPoNum(gia_man)) {
}
inline randomizedBFSFP::randomizedBFSFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log)
: randomizedBFS<randomizedBFSFP>(gia_man, cfg, log){
}
inline Subcircuit randomizedBFSFP::getSubcircuitImpl() {
Subcircuit subcir = findSubcircuit();
subcir.forbidden_pairs = computeForbiddenPairs(subcir);
return subcir;
}
inline randomizedBFSnoFP::randomizedBFSnoFP(Gia_Man_t*& gia_man, const eSLIMConfig& cfg, eSLIMLog& log)
: randomizedBFS<randomizedBFSnoFP>(gia_man, cfg, log) {
}
inline bool randomizedBFSFP::filterSubcircuitImpl(const Subcircuit& subcir) {
return true;
}
}
ABC_NAMESPACE_CXX_HEADER_END
#include "selectionStrategy.tpp"
#endif

View File

@ -0,0 +1,233 @@
/**CFile****************************************************************
FileName [selectionStrategy.tpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Procedures for selecting subcircuits.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: selectionStrategy.tpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#include <queue>
#include "misc/util/abc_namespaces.h"
#include "selectionStrategy.hpp"
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
template<typename T>
Subcircuit SelectionStrategy<T>::getSubcircuit() {
for (int i = 0; i < cfg.nselection_trials; i++) {
Subcircuit subcir = static_cast<T*>(this)->getSubcircuitImpl();
if (filterSubcircuit(subcir)) {
return subcir;
} else {
subcir.free();
}
}
status = false;
Subcircuit empty_subcir;
return empty_subcir;
}
template<typename T>
bool SelectionStrategy<T>::filterSubcircuit(const Subcircuit& subcir) {
// if (subcir.nof_inputs > 8) {
if (subcir.nof_inputs > 10) {
return false;
}
// ABC internally requires that the subcircuit has not more than 6 outputs (e.g. generateMinterm)
if (Vec_IntSize(subcir.io)-subcir.nof_inputs > 6) {
return false;
}
if (Vec_IntSize(subcir.nodes) < min_size) {
return false;
}
return static_cast<T*>(this)->filterSubcircuitImpl(subcir);
}
template <typename T>
int SelectionStrategy<T>::getSubcircuitIO(Vec_Int_t* subcircuit, Vec_Int_t* io) {
assert(Vec_IntSize(io) == 0);
Gia_ManIncrementTravId(gia_man);
Gia_Obj_t * pObj;
int i;
Gia_ManForEachObjVec( subcircuit, gia_man, pObj, i ) {
Gia_ObjSetTravIdCurrent(gia_man, pObj);
}
Gia_ManIncrementTravId(gia_man);
// inputs
Gia_ManForEachObjVec( subcircuit, gia_man, pObj, i ) {
// fanin0 is not in the subcircuit and was not considered yet
if (!Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin0(pObj)) && !Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin0(pObj))) {
Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin0(pObj));
Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin0(pObj)));
}
// fanin1 is not in the subcircuit and was not considered yet
if (!Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin1(pObj)) && !Gia_ObjIsTravIdCurrent(gia_man, Gia_ObjFanin1(pObj))) {
Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin1(pObj));
Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin1(pObj)));
}
}
int nof_inputs = Vec_IntSize(io);
// outputs
Gia_ManForEachAnd( gia_man, pObj, i ) {
// If there is an object that is not contained in the subcircuit that has a fanin in the subcircuit then this fanin is an output
if (!Gia_ObjIsTravIdPrevious(gia_man, pObj)) {
if (Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin0(pObj))) {
Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin0(pObj));
Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin0(pObj)));
}
if (Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin1(pObj))) {
Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin1(pObj));
Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin1(pObj)));
}
}
}
Gia_ManForEachPo( gia_man, pObj, i ) {
if (Gia_ObjIsTravIdPrevious(gia_man, Gia_ObjFanin0(pObj))) {
Gia_ObjSetTravIdCurrent(gia_man, Gia_ObjFanin0(pObj));
Vec_IntPush(io, Gia_ObjId(gia_man, Gia_ObjFanin0(pObj)));
}
}
return nof_inputs;
}
template <typename T>
std::unordered_map<int, std::unordered_set<int>> SelectionStrategy<T>::computeForbiddenPairs(const Subcircuit& subcir) {
Gia_Obj_t * pObj;
int i;
unsigned int min_output_level = Gia_ManLevelNum(gia_man);
Gia_ManIncrementTravId(gia_man);
std::unordered_map<int,int> out_id;
Gia_ManForEachObjVecStart(subcir.io, gia_man, pObj, i, subcir.nof_inputs) {
min_output_level = Gia_ObjLevel(gia_man, pObj) < min_output_level ? Gia_ObjLevel(gia_man, pObj) : min_output_level;
Gia_ObjSetTravIdCurrent(gia_man, pObj);
auto id = Gia_ObjId(gia_man, pObj);
out_id[id] = i - subcir.nof_inputs;
}
std::unordered_map<int, std::unordered_set<int>> forbidden_pairs;
Gia_ManForEachObjVecStop(subcir.io, gia_man, pObj, i, subcir.nof_inputs) {
forbiddenPairsRec(pObj, i, min_output_level, forbidden_pairs, out_id);
}
return forbidden_pairs;
}
template <typename T>
void SelectionStrategy<T>::forbiddenPairsRec(Gia_Obj_t * pObj, int input, int min_level, std::unordered_map<int, std::unordered_set<int>>& pairs, const std::unordered_map<int,int>& out_id) {
if (Gia_ObjIsTravIdCurrent(gia_man, pObj)) {
auto id = Gia_ObjId(gia_man, pObj);
pairs[out_id.at(id)].insert(input);
return;
}
if (Gia_ObjLevel(gia_man, pObj) < min_level) {
return;
}
forbiddenPairsRec(Gia_ObjFanin0(pObj), input, min_level, pairs, out_id);
forbiddenPairsRec(Gia_ObjFanin1(pObj), input, min_level, pairs, out_id);
}
template<typename T>
int randomizedBFS<T>::selectRoot() {
int nof_objs = Gia_ManObjNum(this->gia_man);
int root_id = this->getUniformRandomNumber(this->nPis + 1, nof_objs - this->nPos - 1);
return root_id;
}
template<typename T>
void randomizedBFS<T>::checkCandidate(Subcircuit& subcircuit, std::queue<int>& candidates, std::queue<int>& rejected, bool add) {
int obj_id = candidates.front();
candidates.pop();
Gia_Obj_t * gia_obj = Gia_ManObj(this->gia_man, obj_id);
if (Gia_ObjIsAnd(gia_obj) && !Gia_ObjIsTravIdCurrent(this->gia_man, gia_obj)) {
if (add) {
Gia_ObjSetTravIdCurrent(this->gia_man, gia_obj);
Vec_IntPush(subcircuit.nodes, obj_id);
candidates.push(Gia_ObjFaninId0(gia_obj, obj_id));
candidates.push(Gia_ObjFaninId1(gia_obj, obj_id));
} else {
rejected.push(obj_id);
}
}
}
template<typename T>
Subcircuit randomizedBFS<T>::findSubcircuit() {
Subcircuit result;
assert (Gia_ManIsNormalized(this->gia_man));
int root_id = selectRoot();
Gia_Obj_t * gia_obj = Gia_ManObj(this->gia_man, root_id);
assert (Gia_ObjIsAnd(gia_obj));
result.nodes = Vec_IntAlloc(this->cfg.subcircuit_size_bound);
result.io = Vec_IntAlloc(this->cfg.subcircuit_size_bound);
Vec_IntPush(result.nodes, root_id);
std::queue<int> candidates;
candidates.push(Gia_ObjFaninId0(gia_obj, root_id));
candidates.push(Gia_ObjFaninId1(gia_obj, root_id));
std::queue<int> rejected_nodes;
Gia_ManIncrementTravId(this->gia_man);
while (!candidates.empty() && Vec_IntSize(result.nodes) < this->cfg.subcircuit_size_bound) {
checkCandidate(result, candidates, rejected_nodes, this->getRandomBool());
}
if (this->cfg.fill_subcircuits) {
while (!rejected_nodes.empty() && Vec_IntSize(result.nodes) < this->cfg.subcircuit_size_bound) {
checkCandidate(result, rejected_nodes, rejected_nodes, true);
}
}
result.nof_inputs = this->getSubcircuitIO(result.nodes, result.io);
return result;
}
inline bool randomizedBFSnoFP::filterSubcircuitImpl(const Subcircuit& subcir) {
Gia_Obj_t * pObj;
int i;
unsigned int min_output_level = Gia_ManLevelNum(gia_man);
Gia_ManIncrementTravId(gia_man);
Gia_ManForEachObjVecStart(subcir.io, gia_man, pObj, i, subcir.nof_inputs) {
min_output_level = Gia_ObjLevel(gia_man, pObj) < min_output_level ? Gia_ObjLevel(gia_man, pObj) : min_output_level;
Gia_ObjSetTravIdCurrent(gia_man, pObj);
}
Gia_ManIncrementTravId(gia_man);
Gia_ManForEachObjVecStop(subcir.io, gia_man, pObj, i, subcir.nof_inputs) {
if (!filterSubcircuitRec(pObj, min_output_level)) {
return false;
}
}
return true;
}
inline bool randomizedBFSnoFP::filterSubcircuitRec(Gia_Obj_t * pObj, unsigned int min_level) {
if (Gia_ObjIsTravIdPrevious(gia_man, pObj)) {
return false;
} else if (Gia_ObjIsTravIdCurrent(gia_man, pObj)) {
return true;
} else if (Gia_ObjLevel(gia_man, pObj) < min_level) {
return true;
}
Gia_ObjSetTravIdCurrent(gia_man, pObj);
return filterSubcircuitRec(Gia_ObjFanin0(pObj), min_level) && filterSubcircuitRec(Gia_ObjFanin1(pObj), min_level);
}
}
ABC_NAMESPACE_CXX_HEADER_END

View File

@ -0,0 +1,240 @@
/**CFile****************************************************************
FileName [synthesisEngine.hpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Procedures for synthesising Boolean relations.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: synthesisEngine.hpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__SYNTHESISENGINE_h
#define ABC__OPT__ESLIM__SYNTHESISENGINE_h
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <memory>
#include "misc/util/abc_namespaces.h"
#include "aig/miniaig/miniaig.h"
#include "misc/vec/vec.h"
#include "satInterfaces.hpp"
ABC_NAMESPACE_CXX_HEADER_START
#define MAJ_NOBJS 64 // Const0 + Const1 + nVars + nNodes
namespace eSLIM {
// Based on Exa6_ManGenStart
template<class Derived>
class exactSynthesisEngine {
private:
Vec_Wrd_t * vSimsIn; // input signatures (nWords = 1, nIns <= 64)
Vec_Wrd_t * vSimsOut; // output signatures (nWords = 1, nOuts <= 6)
int nIns;
int nDivs; // divisors (const + inputs + tfi + sidedivs)
int nNodes;
int nOuts;
int nObjs;
int VarMarks[MAJ_NOBJS][2][MAJ_NOBJS] = {}; // default init the array
int nCnfVars;
int nCnfVars2;
int nCnfClauses;
// Assign outputs to their connectivity variables
std::unordered_map<int, std::vector<int>> connection_variables;
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs;
eSLIMLog& log;
const eSLIMConfig& cfg;
exactSynthesisEngine( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg);
int addClause(int lit1, int lit2, int lit3, int lit4);
static bool isNormalized( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut );
int markup();
int findFanin( Vec_Int_t * vValues, int i, int k, int nof_objs);
Mini_Aig_t * getAig(Vec_Int_t * assignment, int size);
Mini_Aig_t * getAig(Vec_Int_t * assignment);
void generateCNF(int fOrderNodes, int fUniqFans);
int startEncoding(int fOrderNodes, int fUniqFans );
void generateMinterm( int iMint);
int getGateEnablingLiteral(int index, bool negated);
int getAuxilaryVariableCount();
void introduceConnectionVariables();
void setupConnectionVariables();
void addConnectivityConstraints();
void addCombinedCycleConstraints();
std::unordered_map<int, std::unordered_set<int>> computeNotInPair(const std::unordered_map<int, std::unordered_set<int>>& pairs);
int prepareLits(int * pLits, int& nLits);
friend Derived;
};
// applies Cadical incrementally
class CadicalEngine : public exactSynthesisEngine<CadicalEngine> {
public:
CadicalEngine(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg);
Mini_Aig_t* getCircuit(int size, double timeout);
private:
using exactSynthesisEngine::addClause;
std::vector<int> gate_enabling_assumptions;
CadicalSolver solver;
int addClause( int * pLits, int nLits );
Vec_Int_t * solve(int size, double timeout);
int getAuxilaryVariableCountDerived();
int getGateEnablingLiteralImpl(int index, bool negated);
void addAssumptions(int size);
void addGateDeactivatedConstraint(int out);
std::vector<int> getAssumptions(int size);
friend exactSynthesisEngine<CadicalEngine>;
};
class OneshotEngine {
protected:
int getAuxilaryVariableCountDerived() {return 0;};
int getGateEnablingLiteralImpl(int index, bool negated) {return 0;};
// void addAssumptions(int size) {};
void addGateDeactivatedConstraint(int idx) {};
};
template <typename T>
class OneshotManager {
public:
OneshotManager(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int maxnNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg);
Mini_Aig_t* getCircuit(int size, double timeout);
private:
T getOneshotEngine(int size);
Vec_Wrd_t * vSimsIn; // input signatures (nWords = 1, nIns <= 64)
Vec_Wrd_t * vSimsOut; // output signatures (nWords = 1, nOuts <= 6)
int nIns;
int nDivs; // divisors (const + inputs + tfi + sidedivs)
int maxnNodes;
int nOuts;
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs;
eSLIMLog& log;
const eSLIMConfig& cfg;
};
class CadicalEngineOneShot : public exactSynthesisEngine<CadicalEngineOneShot>, public OneshotEngine {
public:
CadicalEngineOneShot( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg);
Mini_Aig_t* getCircuit(int size, double timeout);
private:
using exactSynthesisEngine::addClause;
int addClause( int * pLits, int nLits );
Vec_Int_t * solve(int size, double timeout);
CadicalSolver solver;
friend exactSynthesisEngine<CadicalEngineOneShot>;
};
class KissatEngineOneShot : public exactSynthesisEngine<KissatEngineOneShot>, public OneshotEngine {
public:
KissatEngineOneShot( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg);
Mini_Aig_t* getCircuit(int size, double timeout);
private:
using exactSynthesisEngine::addClause;
int addClause( int * pLits, int nLits );
Vec_Int_t * solve(int size, double timeout);
KissatSolver solver;
friend exactSynthesisEngine<KissatEngineOneShot>;
};
class KissatCmdEngine : public exactSynthesisEngine<KissatCmdEngine>, public OneshotEngine {
public:
KissatCmdEngine( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg);
Mini_Aig_t* getCircuit(int size, double timeout);
private:
using exactSynthesisEngine::addClause;
int addClause( int * pLits, int nLits );
Vec_Int_t * solve(int size, double timeout);
FILE * encoding_file;
// Ensure that there is no file with the same name in the diretory
constexpr static char * pFileNameIn = "_temp_.cnf";
constexpr static char * pFileNameOut = "_temp_out.cnf";
#ifdef WIN32
constexpr static char * pKissat = "kissat.exe";
#else
constexpr static char * pKissat = "kissat";
#endif
friend exactSynthesisEngine<KissatCmdEngine>;
};
template <typename T>
inline int exactSynthesisEngine<T>::addClause(int lit1, int lit2, int lit3, int lit4) {
int clause[4] = {lit1, lit2, lit3, lit4};
return static_cast<T*>(this)->addClause(clause, 4);
}
template <typename T>
inline int exactSynthesisEngine<T>::getGateEnablingLiteral(int index, bool negated) {
return static_cast<T*>(this)->getGateEnablingLiteralImpl(index, negated);
}
template <typename T>
inline int exactSynthesisEngine<T>::getAuxilaryVariableCount() {
int ncvars = connection_variables.empty() ? 0 : connection_variables.begin()->second.size() * connection_variables.size();
return ncvars + static_cast<T*>(this)->getAuxilaryVariableCountDerived();
}
typedef OneshotManager<CadicalEngineOneShot> CadicalOneShot;
typedef OneshotManager<KissatEngineOneShot> KissatOneShot;
typedef OneshotManager<KissatCmdEngine> KissatCmdOneShot;
}
ABC_NAMESPACE_CXX_HEADER_END
#include "synthesisEngine.tpp"
#endif

View File

@ -0,0 +1,628 @@
/**CFile****************************************************************
FileName [synthesisEngine.tpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Procedures for synthesising Boolean relations.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: synthesisEngine.tpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#include <numeric>
#ifdef WIN32
#include <process.h>
#define unlink _unlink
#else
#include <unistd.h>
#endif
#include "misc/util/utilTruth.h"
#include "synthesisEngine.hpp"
#include "utils.hpp"
ABC_NAMESPACE_HEADER_START
Vec_Int_t * Exa4_ManParse( char * pFileName );
ABC_NAMESPACE_HEADER_END
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
template <typename T>
exactSynthesisEngine<T>::exactSynthesisEngine( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg)
: vSimsIn(vSimsIn), vSimsOut(vSimsOut), nIns(nIns), nDivs(nDivs), nNodes(nNodes),
nOuts(nOuts), forbidden_pairs(forbidden_pairs), log(log), cfg(cfg) {
assert( Vec_WrdSize(vSimsIn) == Vec_WrdSize(vSimsOut) );
nObjs = nDivs + nNodes + nOuts;
nCnfVars = markup();
introduceConnectionVariables();
nCnfVars2 = 0;
nCnfClauses = 0;
assert( nObjs < 64 );
}
template <typename T>
bool exactSynthesisEngine<T>::isNormalized( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut ) {
int i, Count = 0; word Temp;
Vec_WrdForEachEntry( vSimsIn, Temp, i ) {
if ( Temp & 1 ) {
Count++;
}
}
if ( Count ) {
return false;
}
if ( !(Vec_WrdEntry(vSimsOut, 0) & 1) ) {
return false;
}
return true;
}
template <typename T>
int exactSynthesisEngine<T>::markup() {
int i, k, j, nVars[3] = {1 + 3*nNodes, 0, 3*nNodes*Vec_WrdSize(vSimsIn)};
assert( nObjs <= MAJ_NOBJS );
for ( i = nDivs; i < nDivs + nNodes; i++ ) {
for ( k = 0; k < 2; k++ ) {
for ( j = 1+!k; j < i-k; j++ ) {
VarMarks[i][k][j] = nVars[0] + nVars[1]++;
}
}
}
for ( i = nDivs + nNodes; i < nObjs; i++ ) {
for ( j = 0; j < nDivs + nNodes; j++ ) {
VarMarks[i][0][j] = nVars[0] + nVars[1]++;
}
}
return nVars[0] + nVars[1] + nVars[2];
}
template <typename T>
int exactSynthesisEngine<T>::findFanin( Vec_Int_t * vValues, int i, int k, int nof_objs ) {
int j, Count = 0, iVar = -1;
for ( j = 0; j < nof_objs; j++ ) {
if ( VarMarks[i][k][j] && Vec_IntEntry(vValues, VarMarks[i][k][j]) ){
iVar = j;
Count++;
}
}
assert( Count == 1 );
return iVar;
}
template <typename T>
Mini_Aig_t * exactSynthesisEngine<T>::getAig(Vec_Int_t * vValues) {
return getAig(vValues, nNodes);
}
template <typename T>
Mini_Aig_t * exactSynthesisEngine<T>::getAig(Vec_Int_t * vValues, int size) {
assert (size >= 0 && size <= nNodes && "Invalid size for AIG construction given.");
int i, k, Compl[MAJ_NOBJS] = {0};
int nof_Objs = nDivs + size + nOuts;
Mini_Aig_t * pMini = Mini_AigStartSupport( nDivs-1, nof_Objs );
for ( i = nDivs; i < nDivs + size; i++ ) {
int iNodes[2] = {0};
int iVarStart = 1 + 3*(i - nDivs);//
int Val1 = Vec_IntEntry(vValues, iVarStart);
int Val2 = Vec_IntEntry(vValues, iVarStart+1);
int Val3 = Vec_IntEntry(vValues, iVarStart+2);
Compl[i] = Val1 && Val2 && Val3;
for ( k = 0; k < 2; k++ ) {
int iNode = findFanin(vValues, i, !k, nof_Objs);
int fComp = k ? !Val1 && Val2 && !Val3 : Val1 && !Val2 && !Val3;
iNodes[k] = Abc_Var2Lit(iNode, fComp ^ Compl[iNode]);
}
if ( Val1 && Val2 ) {
if ( Val3 ) {
Mini_AigOr( pMini, iNodes[0], iNodes[1] );
} else {
Mini_AigXorSpecial( pMini, iNodes[0], iNodes[1] );
}
} else {
Mini_AigAnd( pMini, iNodes[0], iNodes[1] );
}
}
for ( i = nDivs + nNodes; i < nObjs; i++ ) {
int iVar = findFanin( vValues, i, 0, nof_Objs);
Mini_AigCreatePo( pMini, Abc_Var2Lit(iVar, Compl[iVar]) );
}
assert( nof_Objs == Mini_AigNodeNum(pMini) );
return pMini;
}
template <typename T>
void exactSynthesisEngine<T>::generateCNF( int fOrderNodes, int fUniqFans ) {
int m;
startEncoding( fOrderNodes, fUniqFans );
// Ignore pattern for all false input pattern (as we start with m=1)
for ( m = 1; m < Vec_WrdSize(vSimsIn); m++ ) {
generateMinterm( m );
}
if (forbidden_pairs.size() > 0) {
addConnectivityConstraints();
}
}
template <typename T>
void exactSynthesisEngine<T>::introduceConnectionVariables() {
std::unordered_set<int> inputs_in_pairs;
// for (const auto& [out, inputs] : forbidden_pairs) {
for (const auto& it: forbidden_pairs) {
const auto& inputs = it.second;
inputs_in_pairs.insert(inputs.begin(), inputs.end());
}
int nCVars = nObjs - 1; // The constant node does not depend on any node
for (int in : inputs_in_pairs) {
connection_variables.emplace(in, std::vector<int> (nCVars, 0));
std::iota(connection_variables[in].begin(), connection_variables[in].end(), nCnfVars);
nCnfVars += nCVars;
}
}
template <typename T>
void exactSynthesisEngine<T>::setupConnectionVariables() {
// for (const auto& [in, cvars] : connection_variables) {
for (const auto& it: connection_variables) {
const auto& in = it.first;
const auto& cvars = it.second;
addClause(Abc_Var2Lit(cvars[in],0),0,0,0);
for (int i = nDivs; i < nDivs + nNodes; i++ ) {
int gate_idx = i - nDivs;
for (int j = 1; j < i - 1; j++) {
addClause(Abc_Var2Lit(VarMarks[i][0][j + 1], 1), Abc_Var2Lit(cvars[j], 1), Abc_Var2Lit(cvars[i - 1], 0), getGateEnablingLiteral(gate_idx, 1));
addClause(Abc_Var2Lit(VarMarks[i][1][j], 1), Abc_Var2Lit(cvars[j - 1], 1), Abc_Var2Lit(cvars[i - 1], 0), getGateEnablingLiteral(gate_idx, 1));
}
}
for (int i = nDivs + nNodes; i < nObjs; i++) {
for (int j = 1; j < nDivs + nNodes; j++) {
addClause(Abc_Var2Lit(VarMarks[i][0][j], 1), Abc_Var2Lit(cvars[j - 1], 1), Abc_Var2Lit(cvars[i - 1], 0),0);
}
}
}
}
template <typename T>
void exactSynthesisEngine<T>::addConnectivityConstraints() {
assert (forbidden_pairs.size() > 0 && "Connectivity constraints are only needed if there are forbidden pairs.");
setupConnectionVariables();
// If there are forbidden pairs for more than one input it is possible that a loop is obtained via two pairs
if (forbidden_pairs.size() > 1) {
addCombinedCycleConstraints();
}
// for (const auto& [out, inputs] : forbidden_pairs) {
for (const auto& it: forbidden_pairs) {
const auto& out = it.first;
const auto& inputs = it.second;
for (int in : inputs) {
const auto& cvars = connection_variables.at(in);
int out_obj_idx = nDivs + nNodes + out;
addClause(Abc_Var2Lit(cvars[out_obj_idx - 1], 1), 0, 0, 0);
}
}
}
template <typename T>
void exactSynthesisEngine<T>::addCombinedCycleConstraints() {
assert (forbidden_pairs.size() > 1 && "Combined connectivity constraints are only needed if there are forbidden pairs for multiple inputs.");
std::unordered_map<int, std::unordered_set<int>> not_in_pair = computeNotInPair(forbidden_pairs);
// for (const auto& [out, inputs] : not_in_pair) {
for (const auto& it: not_in_pair) {
const auto& out = it.first;
const auto& inputs = it.second;
for (int in : inputs) {
const auto& cvars = connection_variables.at(in);
int out_obj_idx = nDivs + nNodes + out;
for (int in2 : forbidden_pairs.at(out)) {
addClause(Abc_Var2Lit(cvars[out_obj_idx - 1], 1), Abc_Var2Lit(cvars[in2], 0),0,0);
}
}
}
}
template <typename T>
std::unordered_map<int, std::unordered_set<int>> exactSynthesisEngine<T>::computeNotInPair(const std::unordered_map<int, std::unordered_set<int>>& pairs) {
std::unordered_set<int> all_inputs_in_pairs;
// for (const auto& [out, in] : pairs) {
for (const auto& it: pairs) {
const auto& in = it.second;
all_inputs_in_pairs.insert(in.begin(), in.end());
}
std::unordered_map<int, std::unordered_set<int>> not_in_pair;
// for (const auto& [out, in] : pairs) {
for (const auto& it: pairs) {
const auto& out = it.first;
const auto& in = it.second;
if (in.size() == all_inputs_in_pairs.size()) {
continue;
}
for (int i : all_inputs_in_pairs) {
if (in.find(i) == in.end()) {
not_in_pair[out].insert(i);
}
}
}
return not_in_pair;
}
template <typename T>
int exactSynthesisEngine<T>::startEncoding(int fOrderNodes, int fUniqFans )
{
int pLits[2*MAJ_NOBJS], i, j, k, n, m, nLits;
for ( i = nDivs; i < nDivs + nNodes; i++ )
{
int gate_idx = i - nDivs;
int iVarStart = 1 + 3*(i - nDivs);//
for ( k = 0; k < 2; k++ )
{
nLits = 0;
for ( j = 0; j < nObjs; j++ )
if ( VarMarks[i][k][j] )
pLits[nLits++] = Abc_Var2Lit( VarMarks[i][k][j], 0 );
assert( nLits > 0 );
static_cast<T*>(this)->addClause( pLits, nLits );
for ( n = 0; n < nLits; n++ )
for ( m = n+1; m < nLits; m++ )
addClause( Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), getGateEnablingLiteral(gate_idx, 1), 0 );
if ( k == 1 )
break;
for ( j = 0; j < nObjs; j++ ) if ( VarMarks[i][0][j] )
for ( n = j; n < nObjs; n++ ) if ( VarMarks[i][1][n] )
addClause( Abc_Var2Lit(VarMarks[i][0][j], 1), Abc_Var2Lit(VarMarks[i][1][n], 1), getGateEnablingLiteral(gate_idx, 1), 0 );
}
if ( fOrderNodes )
for ( j = nDivs; j < i; j++ )
for ( n = 0; n < nObjs; n++ ) if ( VarMarks[i][0][n] )
for ( m = n+1; m < nObjs; m++ ) if ( VarMarks[j][0][m] )
addClause( Abc_Var2Lit(VarMarks[i][0][n], 1), Abc_Var2Lit(VarMarks[j][0][m], 1), getGateEnablingLiteral(gate_idx, 1), 0 );
for ( j = nDivs; j < i; j++ )
for ( k = 0; k < 2; k++ ) if ( VarMarks[i][k][j] )
for ( n = 0; n < nObjs; n++ ) if ( VarMarks[i][!k][n] )
for ( m = 0; m < 2; m++ ) if ( VarMarks[j][m][n] )
addClause( Abc_Var2Lit(VarMarks[i][k][j], 1), Abc_Var2Lit(VarMarks[i][!k][n], 1), Abc_Var2Lit(VarMarks[j][m][n], 1), getGateEnablingLiteral(gate_idx, 1) );
for ( k = 0; k < 3; k++ )
addClause( Abc_Var2Lit(iVarStart, k==1), Abc_Var2Lit(iVarStart+1, k==2), Abc_Var2Lit(iVarStart+2, k!=0), getGateEnablingLiteral(gate_idx, 1));
if ( !cfg.allow_xors )
addClause( Abc_Var2Lit(iVarStart, 1), Abc_Var2Lit(iVarStart+1, 1), Abc_Var2Lit(iVarStart+2, 0), getGateEnablingLiteral(gate_idx, 1));
}
for ( i = nDivs; i < nDivs + nNodes; i++ )
{
int gate_idx = i - nDivs;
nLits = 0;
for ( k = 0; k < 2; k++ )
for ( j = i+1; j < nObjs; j++ )
if ( VarMarks[j][k][i] )
pLits[nLits++] = Abc_Var2Lit( VarMarks[j][k][i], 0 );
if ( fUniqFans )
for ( n = 0; n < nLits; n++ )
for ( m = n+1; m < nLits; m++ )
addClause( Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), getGateEnablingLiteral(gate_idx, 1), 0 );
}
for ( i = nDivs + nNodes; i < nObjs; i++ )
{
static_cast<T*>(this)->addGateDeactivatedConstraint(i);
nLits = 0;
for ( j = 0; j < nDivs + nNodes; j++ ) if ( VarMarks[i][0][j] ) {
pLits[nLits++] = Abc_Var2Lit( VarMarks[i][0][j], 0 );
}
static_cast<T*>(this)->addClause( pLits, nLits );
for ( n = 0; n < nLits; n++ )
for ( m = n+1; m < nLits; m++ )
addClause( Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 );
}
return 1;
}
template <typename T>
void exactSynthesisEngine<T>::generateMinterm( int iMint) {
int internalCnfVars = nCnfVars - getAuxilaryVariableCount(); // for each gate we add an assumption
int iNodeVar = internalCnfVars + 3*nNodes*(iMint - Vec_WrdSize(vSimsIn));
int iOutMint = Abc_Tt6FirstBit( Vec_WrdEntry(vSimsOut, iMint) );
int fOnlyOne = Abc_TtSuppOnlyOne( (int)Vec_WrdEntry(vSimsOut, iMint) );
int i, k, n, j, VarVals[MAJ_NOBJS];
int fAllOnes = Abc_TtCountOnes( Vec_WrdEntry(vSimsOut, iMint) ) == (1 << nOuts);
if ( fAllOnes )
return;
assert( nObjs <= MAJ_NOBJS );
assert( iMint < Vec_WrdSize(vSimsIn) );
assert( nOuts <= 6 );
for ( i = 0; i < nDivs; i++ ) {
VarVals[i] = (Vec_WrdEntry(vSimsIn, iMint) >> i) & 1;
}
for ( i = 0; i < nNodes; i++ ) {
VarVals[nDivs + i] = Abc_Var2Lit(iNodeVar + 3*i + 2, 0);
}
if ( fOnlyOne ) {
for ( i = 0; i < nOuts; i++ )
VarVals[nDivs + nNodes + i] = (iOutMint >> i) & 1;
} else {
word t = Abc_Tt6Stretch( Vec_WrdEntry(vSimsOut, iMint), nOuts );
int i, c, nCubes = 0, pCover[100], pLits[10];
int iOutVar = nCnfVars + nCnfVars2; nCnfVars2 += nOuts;
for ( i = 0; i < nOuts; i++ ) {
VarVals[nDivs + nNodes + i] = Abc_Var2Lit(iOutVar + i, 0);
}
assert( t );
if ( ~t ) {
Abc_Tt6IsopCover( ~t, ~t, nOuts, pCover, &nCubes );
for ( c = 0; c < nCubes; c++ ) {
int nLits = 0;
for ( i = 0; i < nOuts; i++ ) {
int iLit = (pCover[c] >> (2*i)) & 3;
if ( iLit == 1 || iLit == 2 )
pLits[nLits++] = Abc_Var2Lit(iOutVar + i, iLit != 1);
}
static_cast<T*>(this)->addClause( pLits, nLits );
}
}
}
for ( i = nDivs; i < nDivs + nNodes; i++ ) {
int iVarStart = 1 + 3*(i - nDivs);//
int iBaseVarI = iNodeVar + 3*(i - nDivs);
for ( k = 0; k < 2; k++ ) {
for ( j = 0; j < i; j++ ) {
if ( VarMarks[i][k][j] ) {
for ( n = 0; n < 2; n++ ) {
addClause( Abc_Var2Lit(VarMarks[i][k][j], 1), Abc_Var2Lit(iBaseVarI + k, n), Abc_LitNotCond(VarVals[j], !n), 0);
}
}
}
}
for ( k = 0; k < 4; k++ ) {
for ( n = 0; n < 2; n++ ) {
addClause( Abc_Var2Lit(iBaseVarI + 0, k&1), Abc_Var2Lit(iBaseVarI + 1, k>>1), Abc_Var2Lit(iBaseVarI + 2, !n), Abc_Var2Lit(k ? iVarStart + k-1 : 0, n));
}
}
}
for ( i = nDivs + nNodes; i < nObjs; i++ ) {
for ( j = 0; j < nDivs + nNodes; j++ ) {
if ( VarMarks[i][0][j] ) {
for ( n = 0; n < 2; n++ ) {
addClause( Abc_Var2Lit(VarMarks[i][0][j], 1), Abc_LitNotCond(VarVals[j], n), Abc_LitNotCond(VarVals[i], !n), 0);
}
}
}
}
}
template <typename T>
int exactSynthesisEngine<T>::prepareLits(int * pLits, int& nLits) {
int k = 0;
for ( int i = 0; i < nLits; i++ ) {
if ( pLits[i] == 1 )
return 0;
else if ( pLits[i] == 0 )
continue;
else if ( pLits[i] <= 2*(nCnfVars + nCnfVars2) )
pLits[k++] = pLits[i];
else assert( 0 );
}
nLits = k;
return 1;
}
inline CadicalEngine::CadicalEngine(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg)
: exactSynthesisEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) {
gate_enabling_assumptions.reserve(nNodes);
for (int i = 0; i < nNodes; i++) {
gate_enabling_assumptions.push_back(nCnfVars + i);
}
nCnfVars += nNodes;
generateCNF(0, 0);
}
inline int CadicalEngine::addClause( int * pLits, int nLits ) {
if (prepareLits(pLits, nLits) == 0) {
return 0;
}
assert( nLits > 0 );
solver.addClause(pLits, nLits);
return 1;
}
inline Vec_Int_t * CadicalEngine::solve( int size, double timeout) {
std::vector<int> assumptions = getAssumptions(size);
solver.assume(assumptions);
int status = timeout > 0 ? solver.solve(timeout) : solver.solve();
Vec_Int_t * vRes = status == 10 ? solver.getModelVec() : nullptr;
if (status == 10) {
log.cummulative_sat_runtimes_per_size[size] += solver.getRunTime();
log.nof_sat_calls_per_size[size] ++;
} else if (status == 20) {
log.cummulative_unsat_runtimes_per_size[size] += solver.getRunTime();
log.nof_unsat_calls_per_size[size] ++;
}
return vRes;
}
Mini_Aig_t* CadicalEngine::getCircuit(int size, double timeout) {
addAssumptions(size);
Vec_Int_t * vValues = solve(size, timeout);
Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr;
Vec_IntFreeP( &vValues );
return pMini;
}
inline std::vector<int> CadicalEngine::getAssumptions(int size) {
std::vector<int> assumptions(nNodes);
for (int i = 0; i < size; i++) {
assumptions[i] = gate_enabling_assumptions[i];
}
for (int i = size; i < nNodes; i++) {
assumptions[i] = -gate_enabling_assumptions[i];
}
return assumptions;
}
inline void CadicalEngine::addGateDeactivatedConstraint(int out_idx) {
for (int j = nDivs; j < nDivs + nNodes; j++ ) {
int gate_idx = j - nDivs;
// if a gate is disabled then it shall not be an output
addClause( Abc_Var2Lit(VarMarks[out_idx][0][j],1), Abc_Var2Lit( gate_enabling_assumptions[gate_idx], 0 ), 0, 0 );
}
}
inline int CadicalEngine::getGateEnablingLiteralImpl(int index, bool negated) {
return Abc_Var2Lit( gate_enabling_assumptions[index], negated );
}
inline int CadicalEngine::getAuxilaryVariableCountDerived() {
return nNodes; // We add an assumption for each gate
}
inline void CadicalEngine::addAssumptions(int size) {
solver.assume(getAssumptions(size));
}
template <typename T>
OneshotManager<T>::OneshotManager(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int maxnNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg)
: vSimsIn(vSimsIn), vSimsOut(vSimsOut), nIns(nIns), nDivs(nDivs), maxnNodes(maxnNodes), nOuts(nOuts), forbidden_pairs(forbidden_pairs), log(log), cfg(cfg) {
}
template <typename T>
T OneshotManager<T>::getOneshotEngine(int size) {
assert(size <= maxnNodes);
T oneshotEngine(vSimsIn, vSimsOut, nIns, nDivs, nOuts, size, forbidden_pairs, log, cfg);
return oneshotEngine;
}
template <typename T>
Mini_Aig_t* OneshotManager<T>::getCircuit(int size, double timeout) {
T synth = getOneshotEngine(size);
return synth.getCircuit(size, timeout);
}
inline CadicalEngineOneShot::CadicalEngineOneShot( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg)
: exactSynthesisEngine<CadicalEngineOneShot>(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) {
}
inline Vec_Int_t* CadicalEngineOneShot::solve( int size, double timeout) {
int status = timeout > 0 ? solver.solve(timeout) : solver.solve();
Vec_Int_t * vRes = status != 10 ? nullptr : solver.getModelVec();
return vRes;
}
Mini_Aig_t* CadicalEngineOneShot::getCircuit(int size, double timeout) {
generateCNF(0, 0);
Vec_Int_t * vValues = solve(size, timeout);
Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr;
Vec_IntFreeP( &vValues );
return pMini;
}
inline int CadicalEngineOneShot::addClause( int * pLits, int nLits ) {
if (prepareLits(pLits, nLits) == 0) {
return 0;
}
assert( nLits > 0 );
solver.addClause(pLits, nLits);
return 1;
}
inline KissatEngineOneShot::KissatEngineOneShot(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg)
: exactSynthesisEngine<KissatEngineOneShot>(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) {
}
Mini_Aig_t* KissatEngineOneShot::getCircuit(int size, double timeout) {
solver.init(nCnfVars);
generateCNF(0, 0);
Vec_Int_t * vValues = solve(size, timeout);
Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr;
Vec_IntFreeP( &vValues );
return pMini;
}
inline Vec_Int_t *KissatEngineOneShot::solve( int size, double timeout) {
// TODO: The used interface does not yet allow timeouts
int status = solver.solve();
Vec_Int_t * vRes = status != 10 ? nullptr : solver.getModelVec();
return vRes;
}
inline int KissatEngineOneShot::addClause( int * pLits, int nLits ) {
if (prepareLits(pLits, nLits) == 0) {
return 0;
}
assert( nLits > 0 );
solver.addClause(pLits, nLits);
return 1;
}
inline KissatCmdEngine::KissatCmdEngine(Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes,
const std::unordered_map<int, std::unordered_set<int>>& forbidden_pairs, eSLIMLog& log, const eSLIMConfig& cfg)
: exactSynthesisEngine<KissatCmdEngine>(vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, forbidden_pairs, log, cfg) {
}
Mini_Aig_t* KissatCmdEngine::getCircuit(int size, double timeout) {
encoding_file = fopen( pFileNameIn, "wb" );
fputs( "p cnf \n", encoding_file );
generateCNF(0, 0);
Vec_Int_t * vValues = solve(size, timeout);
Mini_Aig_t * pMini = vValues ? getAig(vValues, size) : nullptr;
Vec_IntFreeP( &vValues );
return pMini;
}
inline int KissatCmdEngine::addClause( int * pLits, int nLits ) {
if (prepareLits(pLits, nLits) == 0) {
return 0;
}
assert( nLits > 0 );
if ( encoding_file ) {
nCnfClauses++;
for ( int i = 0; i < nLits; i++ ) {
fprintf( encoding_file, "%s%d ", Abc_LitIsCompl(pLits[i]) ? "-" : "", Abc_Lit2Var(pLits[i]) );
}
fprintf( encoding_file, "0\n" );
}
return 1;
}
inline Vec_Int_t * KissatCmdEngine::solve(int size, double timeout) {
rewind( encoding_file );
fprintf( encoding_file, "p cnf %d %d", nCnfVars + nCnfVars2, nCnfClauses );
fclose( encoding_file );
encoding_file = nullptr;
char Command[1000], * pCommand = (char *)&Command;
// TODO:
// if ( TimeOut )
// sprintf( pCommand, "%s --time=%d -q %s > %s", pKissat, TimeOut, pFileNameIn, pFileNameOut );
// else
// sprintf( pCommand, "%s -q %s > %s", pKissat, pFileNameIn, pFileNameOut );
sprintf( pCommand, "%s -q %s > %s", pKissat, pFileNameIn, pFileNameOut );
if ( system( pCommand ) == -1 ) {
std::cerr << "Command " << pCommand << " failed\n";
return nullptr;
}
Vec_Int_t * vRes = Exa4_ManParse( pFileNameOut );
unlink( pFileNameIn );
return vRes;
}
}
ABC_NAMESPACE_CXX_HEADER_END

103
src/opt/eslim/utils.hpp Normal file
View File

@ -0,0 +1,103 @@
/**CFile****************************************************************
FileName [utils.hpp]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Using Exact Synthesis with the SAT-based Local Improvement Method (eSLIM).]
Synopsis [Utilities for the eSLIM package.]
Author [Franz-Xaver Reichl]
Affiliation [University of Freiburg]
Date [Ver. 1.0. Started - March 2025.]
Revision [$Id: utils.hpp,v 1.00 2025/03/17 00:00:00 Exp $]
***********************************************************************/
#ifndef ABC__OPT__ESLIM__UTILS_h
#define ABC__OPT__ESLIM__UTILS_h
#include <vector>
#include <unordered_map>
#include <unordered_set>
#include "misc/util/abc_namespaces.h"
#include "misc/vec/vec.h"
#include "aig/gia/gia.h"
ABC_NAMESPACE_CXX_HEADER_START
namespace eSLIM {
struct eSLIMConfig {
bool extended_normality_processing = false;
bool apply_strash = true;
bool fix_seed = false;
bool fill_subcircuits = false;
bool trial_limit_active = true;
bool allow_xors = false;
unsigned int timeout = 3600;
unsigned int iterations = 0;
unsigned int subcircuit_size_bound = 6;
unsigned int strash_intervall = 100;
int seed = 0;
unsigned int nselection_trials = 100;
double expansion_probability = 0.6;
// times given in sec
int minimum_sat_timeout = 1;
int base_sat_timeout = 120;
int minimum_dynamic_timeout_sample_size = 50;
double dynamic_timeout_buffer_factor = 1.4;
int verbosity_level = 0;
};
struct eSLIMLog {
unsigned int iteration_count = 0;
double relation_generation_time = 0;
double synthesis_time = 0;
unsigned int subcircuits_with_forbidden_pairs = 0;
std::vector<int> nof_analyzed_circuits_per_size;
std::vector<int> nof_replaced_circuits_per_size;
std::vector<int> nof_reduced_circuits_per_size;
std::vector<ABC_UINT64_T> cummulative_sat_runtimes_per_size;
std::vector<int> nof_sat_calls_per_size;
std::vector<ABC_UINT64_T> cummulative_unsat_runtimes_per_size;
std::vector<int> nof_unsat_calls_per_size;
eSLIMLog(int size);
};
struct Subcircuit {
Vec_Int_t* nodes;
Vec_Int_t* io;
unsigned int nof_inputs;
std::unordered_map<int, std::unordered_set<int>> forbidden_pairs;
void free();
};
inline void Subcircuit::free() {
Vec_IntFree(nodes);
Vec_IntFree(io);
}
inline eSLIMLog::eSLIMLog(int size)
: nof_analyzed_circuits_per_size(size + 1, 0), nof_replaced_circuits_per_size(size + 1, 0),
nof_reduced_circuits_per_size(size + 1, 0), cummulative_sat_runtimes_per_size(size + 1, 0),
nof_sat_calls_per_size(size + 1, 0), cummulative_unsat_runtimes_per_size(size + 1, 0),
nof_unsat_calls_per_size(size + 1, 0) {
}
}
ABC_NAMESPACE_CXX_HEADER_END
#endif

View File

@ -29,24 +29,49 @@ extern Vec_Int_t * Abc_NtkWriteMiniMapping( Abc_Ntk_t * pNtk );
extern void Abc_NtkPrintMiniMapping( int * pArray );
extern Abc_Ntk_t * Abc_NtkFromMiniMapping( int *vMapping );
extern Mini_Aig_t * Abc_MiniAigFromNtk ( Abc_Ntk_t *pNtk );
extern void Nf_ManSetDefaultPars( Jf_Par_t * pPars );
extern Gia_Man_t * Nf_ManPerformMapping( Gia_Man_t * pGia, Jf_Par_t * pPars );
extern Abc_Ntk_t * Abc_NtkFromMappedGia( Gia_Man_t * p, int fFindEnables, int fUseBuffs );
extern Abc_Ntk_t * Abc_NtkFromCellMappedGia( Gia_Man_t * p, int fUseBuffs );
extern int Gia_ManSimpleMapping( Gia_Man_t * p, int nBound, int Seed, int nBTLimit, int nTimeout, int fVerbose, int fKeepFile, int argc, char ** argv );
Abc_Ntk_t *Gia_ManRewirePut(Gia_Man_t *pGia) {
Aig_Man_t *pMan = Gia_ManToAig(pGia, 0);
Abc_Ntk_t *pNtk = Abc_NtkFromAigPhase(pMan);
Abc_NtkSetName(pNtk, Abc_UtilStrsav(Gia_ManName(pGia)));
Aig_ManStop(pMan);
return pNtk;
}
Abc_Ntk_t *Abc_ManRewireMap(Abc_Ntk_t *pNtk) {
Abc_Ntk_t *Abc_ManRewireMapAmap(Abc_Ntk_t *pNtk) {
Amap_Par_t Pars, *pPars = &Pars;
Amap_ManSetDefaultParams(pPars);
Abc_Ntk_t *pNtkMapped = Abc_NtkDarAmap(pNtk, pPars);
if (pNtkMapped == NULL) {
Abc_NtkDelete(pNtk);
Abc_Print(-1, "Mapping has failed.\n");
return NULL;
}
return pNtkMapped;
}
Abc_Ntk_t *Gia_ManRewireMapNf(Gia_Man_t *pGia) {
Jf_Par_t Pars, * pPars = &Pars;
Nf_ManSetDefaultPars( pPars );
Gia_Man_t *pGiaNew = Nf_ManPerformMapping(pGia, pPars);
if (pGiaNew == NULL) {
Abc_Print(-1, "Mapping has failed.\n");
return NULL;
}
Abc_Ntk_t *pNtkMapped = Abc_NtkFromCellMappedGia(pGiaNew, 0);
return pNtkMapped;
}
Abc_Ntk_t *Gia_ManRewireMapSimap(Gia_Man_t *pGia, int nBound, int nBTLimit, int nTimeout) {
if (!Gia_ManSimpleMapping(pGia, nBound, 0, nBTLimit, nTimeout, 0, 0, 0, NULL)) {
// Abc_Print(-1, "Mapping has failed.\n");
return NULL;
}
Abc_Ntk_t *pNtkMapped = Abc_NtkFromCellMappedGia(pGia, 0);
return pNtkMapped;
}

View File

@ -30,7 +30,9 @@
ABC_NAMESPACE_HEADER_START
Abc_Ntk_t *Gia_ManRewirePut(Gia_Man_t *pGia);
Abc_Ntk_t *Abc_ManRewireMap(Abc_Ntk_t *pNtk);
Abc_Ntk_t *Abc_ManRewireMapAmap(Abc_Ntk_t *pNtk);
Abc_Ntk_t *Gia_ManRewireMapNf(Gia_Man_t *pGia);
Abc_Ntk_t *Gia_ManRewireMapSimap(Gia_Man_t *pGia, int nBound, int nBTLimit, int nTimeout);
Vec_Int_t *Abc_ManRewireNtkWriteMiniMapping(Abc_Ntk_t *pNtk);
Abc_Ntk_t *Abc_ManRewireNtkFromMiniMapping(int *vMapping);
Mini_Aig_t *Abc_ManRewireMiniAigFromNtk(Abc_Ntk_t *pNtk);

View File

@ -26,29 +26,35 @@ ABC_NAMESPACE_IMPL_START
#endif // RW_ABC
#ifdef RW_ABC
Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) {
Random_Num(nSeed);
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) {
Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
Rewire::Miaig pNtkMiaig(pGia);
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, fVerbose);
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fVerbose);
pNew.setName(Gia_ManName(pGia));
return pNew.toGia();
}
Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) {
Random_Num(nSeed);
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) {
Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
int fMapped = nMode == 1;
Rewire::Miaig pNtkMiaig(pNtk);
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, fVerbose);
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, fMapped, nMappedMode, nDist, fVerbose);
pNew.setName(Abc_NtkName(pNtk));
if (nMode == 2) {
pNew.countTransistors(1, nMappedMode);
}
return pNew.toNtk(nMode);
return pNew.toNtk(nMode >= 1);
}
Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) {
Random_Num(nSeed);
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) {
Random_Num(nSeed == 0 ? Abc_Random(0) % 10 : nSeed);
Rewire::Miaig pNtkMiaig(pAig);
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, fVerbose);
Rewire::Miaig pNew = pNtkMiaig.rewire(nIters, levelGrowRatio, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nMappedMode, nDist, fVerbose);
return pNew.toMiniAig();
}
@ -84,6 +90,15 @@ void Miaig::create(int nIns, int nOuts, int nObjsAlloc) {
}
}
void Miaig::setName(char *pName) {
if (_data) {
if (_data->pName) {
free(_data->pName);
}
_data->pName = strdup(pName);
}
}
void Miaig::print(void) {
int i, k, iLit;
printf("\nAIG printout:\n");
@ -149,6 +164,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 );
Gia_ManHashAlloc(pGia);
memset(_data->pCopy, 0, sizeof(int) * nObjs());
Miaig_ForEachInput(i)
@ -197,34 +213,63 @@ Mini_Aig_t *Miaig::toMiniAig(void) {
}
Abc_Ntk_t *Miaig::toNtk(int fMapped) {
Abc_Ntk_t *pNtk;
if (_data->pNtkMapped && fMapped) {
return Abc_ManRewireNtkFromMiniMapping(Vi_Array(_data->pNtkMapped));
pNtk = Abc_ManRewireNtkFromMiniMapping(Vi_Array(_data->pNtkMapped));
ABC_FREE(pNtk->pName);
Abc_NtkSetName(pNtk, Abc_UtilStrsav(_data->pName));
return pNtk;
}
Gia_Man_t *pGia = toGia();
Abc_Ntk_t *pNtk = Gia_ManRewirePut(pGia);
pNtk = Gia_ManRewirePut(pGia);
Gia_ManStop(pGia);
return pNtk;
}
vi *moveVecToVi(Vec_Int_t *v) {
vi *p = (vi *)malloc(sizeof(vi));
p->size = Vec_IntSize(v);
p->cap = Vec_IntCap(v);
p->ptr = Vec_IntArray(v);
free(v);
return p;
}
#endif // RW_ABC
// technology mapping
float Miaig::countTransistors(int reset) {
float Miaig::countTransistors(int reset, int nMappedMode) {
if (!reset && _data->nTransistor) return _data->nTransistor;
#ifdef RW_ABC
Abc_Ntk_t *pNtk = toNtk();
Abc_Ntk_t *pNtkMapped = Abc_ManRewireMap(pNtk);
float area = Abc_NtkGetMappedArea(pNtkMapped);
Vec_Int_t *vMapping = Abc_ManRewireNtkWriteMiniMapping(pNtkMapped);
_data->pNtkMapped = (vi *)malloc(sizeof(vi));
_data->pNtkMapped->size = Vec_IntSize(vMapping);
_data->pNtkMapped->cap = Vec_IntCap(vMapping);
_data->pNtkMapped->ptr = Vec_IntArray(vMapping);
free(vMapping);
Abc_NtkDelete(pNtk);
Abc_NtkDelete(pNtkMapped);
#else
float area = 0;
Abc_Ntk_t *pNtkMapped = NULL, *pNtkMappedTemp = NULL;
if (nMappedMode == 0) { // amap
Abc_Ntk_t *pNtk = toNtk();
pNtkMapped = Abc_ManRewireMapAmap(pNtk);
Abc_NtkDelete(pNtk);
} else if (nMappedMode == 1) { // &nf
Gia_Man_t *pGia = toGia();
pNtkMapped = Gia_ManRewireMapNf(pGia);
Gia_ManStop(pGia);
} else if (nMappedMode == 2) { // &simap
Abc_Ntk_t *pNtk = toNtk();
pNtkMapped = Abc_ManRewireMapAmap(pNtk);
area = Abc_NtkGetMappedArea(pNtkMapped);
Gia_Man_t *pGia = toGia();
while ((pNtkMappedTemp = Gia_ManRewireMapSimap(pGia, area - 2, 0, 40))) {
area -= 2;
Abc_NtkDelete(pNtkMapped);
pNtkMapped = pNtkMappedTemp;
}
Gia_ManStop(pGia);
}
if (pNtkMapped) {
area = Abc_NtkGetMappedArea(pNtkMapped);
Vec_Int_t *vMapping = Abc_ManRewireNtkWriteMiniMapping(pNtkMapped);
_data->pNtkMapped = moveVecToVi(vMapping);
Abc_NtkDelete(pNtkMapped);
}
#else
float area = countAnd2(reset, 0);
#endif // RW_ABC
return _data->nTransistor = area;
@ -892,7 +937,7 @@ int Miaig::checkConst(int iObj, word *pCare, int fVerbose) {
return 0;
}
int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int fVerbose) {
int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int nExpandableLevel, int fVerbose) {
int i, k, n, iLit, nAdded = 0;
word *pCare = computeCareSet(iObj);
assert(nAddedMax > 0);
@ -908,6 +953,7 @@ int Miaig::expandOne(int iObj, int nAddedMax, int nDist, int fVerbose) {
if (nDist) markDistanceN(iObj, nDist);
Miaig_ForEachInputNode(i) {
if (nDist && objDist(i) < 0 && !objIsPi(i)) continue;
// if (nExpandableLevel && objLevel(i) - objLevel(iObj) > nExpandableLevel) continue;
if (objTravId(i) != nTravIds() && (objIsPi(i) || (objFaninNum(i) > 1 && objRef(i) > 0))) // this node is NOT in the TFO
Vi_Push(_data->vOrderF, i);
}
@ -1010,8 +1056,8 @@ int Miaig::reduceOne(int iObj, int fOnlyConst, int fOnlyBuffer, int fHeuristic,
return 0;
}
int Miaig::expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int fVerbose) {
expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimit), nDist, fVerbose);
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);
return 0;
}
@ -1025,7 +1071,7 @@ vi *Miaig::createRandomOrder(void) {
return _data->vOrder;
}
Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int fVerbose) {
Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int fVerbose) {
int i, iNode, nAdded = 0;
assert(nFaninAddLimitAll > 0);
vi *vOrder = createRandomOrder();
@ -1035,7 +1081,7 @@ Miaig Miaig::expand(int nFaninAddLimitAll, int nDist, int fVerbose) {
initializeLevels();
if (nDist) initializeDists();
Vi_ForEachEntry(vOrder, iNode, i) {
nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, fVerbose);
nAdded += expandOne(iNode, Abc_MinInt(Vi_Space(_data->pvFans + iNode), nFaninAddLimitAll - nAdded), nDist, nExpandableLevel, fVerbose);
if (nAdded >= nFaninAddLimitAll)
break;
}
@ -1071,7 +1117,7 @@ Miaig Miaig::reduce(int fVerbose) {
return dupStrash(1, 1, 1);
}
Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int fVerbose) {
Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int nExpandableLevel, int fVerbose) {
Miaig pTemp;
int i, iNode;
vi *vOrder = topoCollect();
@ -1081,15 +1127,15 @@ Miaig Miaig::expandThenReduce(int nFaninAddLimit, int nDist, int fVerbose) {
initializeLevels();
if (nDist) initializeDists();
Vi_ForEachEntry(vOrder, iNode, i) {
expandThenReduceOne(iNode, nFaninAddLimit, nDist, fVerbose);
expandThenReduceOne(iNode, nFaninAddLimit, nDist, nExpandableLevel, fVerbose);
}
verifyRefs();
return dupDfs().dupStrash(1, 1, 1);
}
Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nVerbose) {
Miaig Miaig::expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nExpandableLevel, int nVerbose) {
// expand
Miaig pNew = expand(nFaninAddLimitAll, nDist, nVerbose);
Miaig pNew = expand(nFaninAddLimitAll, nDist, nExpandableLevel, nVerbose);
// share
pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs);
// reduce
@ -1110,7 +1156,7 @@ Miaig randomRead(std::vector<Miaig> &pBests) {
return pBests[Random_Num(0) % pBests.size()];
}
Miaig Miaig::rewire(int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nVerbose) {
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) {
const int nRootSave = 8;
const int nBestSave = 4;
int nRestart = 5000;
@ -1120,26 +1166,30 @@ Miaig Miaig::rewire(int nIters, int nExpands, int nGrowth, int nDivs, int nFanin
Miaig pNew;
Miaig pRoot = pRoots[0];
Miaig pBest = this->dup(0);
float (Miaig::*Miaig_ObjectiveFunction)(int) = (nMode == 0) ? &Miaig::countAnd2 : &Miaig::countTransistors;
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;
float PrevBest = ((&pBest)->*Miaig_ObjectiveFunction)(1);
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; i < nIters; i++) {
if (nVerbose) printf("\rIteration %7d : %5g -> ", i + 1, ((&pRoot)->*Miaig_ObjectiveFunction)(0));
for (int i = 0; nIters ? i < nIters : 1; i++) {
if (nVerbose) printf("\rIteration %7d : %5g -> ", i + 1, ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode));
if (nTimeOut && nTimeOut < 1.0 * (Time_Clock() - clkStart) / CLOCKS_PER_SEC) break;
pNew = pRoot.dupMulti(nFaninMax, nGrowth);
if (i % 2 == 0) {
pNew = pNew.expandThenReduce(nGrowth, nDist, nVerbose > 1);
pNew = pNew.expandThenReduce(nGrowth, nDist, nExpandableLevel, nVerbose > 1);
}
pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nVerbose > 1);
pNew = pNew.expandShareReduce(nExpands, nDivs, nDist, nExpandableLevel, nVerbose > 1);
++iterNotImproveAfterRestart;
// report
float rootTarget = ((&pRoot)->*Miaig_ObjectiveFunction)(0);
float newTarget = ((&pNew)->*Miaig_ObjectiveFunction)(1);
if (PrevBest > newTarget) {
float rootTarget = ((&pRoot)->*Miaig_ObjectiveFunction)(0, nMappedMode);
float newTarget = ((&pNew)->*Miaig_ObjectiveFunction)(1, nMappedMode);
if (maxLevel ? pNew.countLevel() > maxLevel : 0) {
} else if (PrevBest > newTarget) {
if (nVerbose) printf("%5g (AND2 = %5g Level = %3d) ", newTarget, pNew.countAnd2(), pNew.countLevel());
if (nVerbose) Time_PrintEndl("Elapsed time", Time_Clock() - clkStart);
PrevBest = newTarget;
@ -1150,10 +1200,11 @@ Miaig Miaig::rewire(int nIters, int nExpands, int nGrowth, int nDivs, int nFanin
randomAddBest(pBests, pNew.dup(0), nBestSave);
}
// compare
if (rootTarget < newTarget) {
if (maxLevel ? pNew.countLevel() > maxLevel : 0) {
} else if (rootTarget < newTarget) {
if (iterNotImproveAfterRestart > nRestart) {
pNew = randomRead(pBests).dupMulti(nFaninMax, nGrowth);
pNew = pNew.expand(nExpands, nDist, nVerbose > 1);
pNew = pNew.expand(nExpands, nDist, nExpandableLevel, nVerbose > 1);
pNew = pNew.share(nDivs == -1 ? pNew.nObjs() : nDivs);
pNew = pNew.dupStrash(1, 1, 0);
pRoots = {pNew};

View File

@ -141,6 +141,7 @@ static inline int Rw_Lit2LitL(int *pMapV2L, int Lit) {
}
struct Miaig_Data {
char *pName; // network name
int refcount; // Reference counter
int nIns; // primary inputs
int nOuts; // primary outputs
@ -217,6 +218,7 @@ public:
void refObj(int iObj);
void derefObj(int iObj);
void derefObj_rec(int iObj, int iLitSkip);
void setName(char *pName);
private:
int initializeLevels_rec(int iObj);
@ -255,8 +257,9 @@ private:
int *hashLookup(int *pTable, int l0, int l1, int TableSize);
public:
float countAnd2(int reset = 0);
float countTransistors(int reset = 0);
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);
private:
@ -269,21 +272,21 @@ private:
int buildNodeCascade(Miaig &pNew, vi *vFanins, int fCprop, int fStrash);
private:
int expandOne(int iObj, int nAddedMax, int nDist, int fVerbose);
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 fVerbose);
int expandThenReduceOne(int iNode, int nFaninAddLimit, int nDist, int nExpandableLevel, 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 nVerbose);
Miaig expand(int nFaninAddLimitAll, int nDist, int nExpandableLevel, int nVerbose);
Miaig share(int nNewNodesMax);
Miaig reduce(int fVerbose);
Miaig expandThenReduce(int nFaninAddLimit, int nDist, int fVerbose);
Miaig expandShareReduce(int nFaninAddLimitAll, int nDivs, int nDist, int nVerbose);
Miaig rewire(int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nVerbose);
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
Gia_Man_t *toGia(void);
Abc_Ntk_t *toNtk(int fMapped = 0);
@ -355,6 +358,7 @@ inline void Miaig::addref(void) {
inline void Miaig::release(void) {
if (_refcount && RW_XADD(_refcount, -1) == 1) {
if (_data) {
if (_data->pName) free(_data->pName);
for (int i = 0; i < _data->nObjsAlloc; ++i)
if (_data->pvFans[i].ptr)
free(_data->pvFans[i].ptr);
@ -459,7 +463,7 @@ inline int Miaig::nWords(void) {
return _data->nWords;
}
inline float Miaig::countAnd2(int reset) {
inline float Miaig::countAnd2(int reset, int fDummy) {
int i, Counter = 0;
Miaig_ForEachNode(i) {
Counter += objFaninNum(i) - 1;

View File

@ -22,16 +22,16 @@
ABC_NAMESPACE_IMPL_START
Gia_Man_t *Gia_ManRewire(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) {
return Gia_ManRewireInt(pGia, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, fVerbose);
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);
}
Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) {
return Abc_ManRewireInt(pNtk, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, 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);
}
Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose) {
return MiniAig_ManRewireInt(pAig, nIters, nExpands, nGrowth, nDivs, nFaninMax, nTimeOut, nMode, nDist, nSeed, 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);
}
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, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose);
Gia_Man_t *Gia_ManRewireInt(Gia_Man_t *pGia, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose);
Abc_Ntk_t *Abc_ManRewire(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose);
Abc_Ntk_t *Abc_ManRewireInt(Abc_Ntk_t *pNtk, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose);
Mini_Aig_t *MiniAig_ManRewire(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose);
Mini_Aig_t *MiniAig_ManRewireInt(Mini_Aig_t *pAig, int nIters, int nExpands, int nGrowth, int nDivs, int nFaninMax, int nTimeOut, int nMode, int nDist, int nSeed, int fVerbose);
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);
ABC_NAMESPACE_HEADER_END

View File

@ -8,6 +8,8 @@
#include "rrrAnalyzer.h"
#include "rrrSatSolver.h"
#include "rrrSimulator.h"
#include "rrrPartitioner.h"
#include "rrrLevelBasePartitioner.h"
ABC_NAMESPACE_CXX_HEADER_START
@ -16,15 +18,33 @@ namespace rrr {
template <typename Ntk>
void Perform(Ntk *pNtk, Parameter const *pPar) {
assert(!pPar->fUseBddCspf || !pPar->fUseBddMspf);
if(pPar->fUseBddCspf) {
Scheduler<Ntk, rrr::Optimizer<Ntk, rrr::BddAnalyzer<Ntk>>> sch(pNtk, pPar);
sch.Run();
} else if(pPar->fUseBddMspf) {
Scheduler<Ntk, rrr::Optimizer<Ntk, rrr::BddMspfAnalyzer<Ntk>>> sch(pNtk, pPar);
sch.Run();
} else {
Scheduler<Ntk, rrr::Optimizer<Ntk, rrr::Analyzer<Ntk, rrr::Simulator<Ntk>, rrr::SatSolver<Ntk>>>> sch(pNtk, pPar);
sch.Run();
switch(pPar->nPartitionType) {
case 0:
if(pPar->fUseBddCspf) {
Scheduler<Ntk, Optimizer<Ntk, BddAnalyzer<Ntk>>, Partitioner<Ntk>> sch(pNtk, pPar);
sch.Run();
} else if(pPar->fUseBddMspf) {
Scheduler<Ntk, Optimizer<Ntk, BddMspfAnalyzer<Ntk>>, Partitioner<Ntk>> sch(pNtk, pPar);
sch.Run();
} else {
Scheduler<Ntk, Optimizer<Ntk, Analyzer<Ntk, Simulator<Ntk>, SatSolver<Ntk>>>, Partitioner<Ntk>> sch(pNtk, pPar);
sch.Run();
}
break;
case 1:
if(pPar->fUseBddCspf) {
Scheduler<Ntk, Optimizer<Ntk, BddAnalyzer<Ntk>>, LevelBasePartitioner<Ntk>> sch(pNtk, pPar);
sch.Run();
} else if(pPar->fUseBddMspf) {
Scheduler<Ntk, Optimizer<Ntk, BddMspfAnalyzer<Ntk>>, LevelBasePartitioner<Ntk>> sch(pNtk, pPar);
sch.Run();
} else {
Scheduler<Ntk, Optimizer<Ntk, Analyzer<Ntk, Simulator<Ntk>, SatSolver<Ntk>>>, LevelBasePartitioner<Ntk>> sch(pNtk, pPar);
sch.Run();
}
break;
default:
assert(0);
}
}

View File

@ -54,7 +54,7 @@ namespace rrr {
void SortInts(itr it);
unsigned StartTraversal(int n = 1);
void EndTraversal();
void ForEachTfiRec(int id, std::function<void(int)> const &f);
void ForEachTfiRec(int id, std::function<void(int)> const &func);
void TakenAction(Action const &action) const;
public:
@ -102,13 +102,15 @@ namespace rrr {
int FindFanin(int id, int fi) const;
bool IsReconvergent(int id);
std::vector<int> GetNeighbors(int id, bool fPis, int nHops);
template <template <typename...> typename Container, typename ... Ts, template <typename...> typename Container2, typename ... Ts2>
template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
bool IsReachable(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts);
template <template <typename...> typename Container, typename ... Ts, template <typename...> typename Container2, typename ... Ts2>
template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
std::vector<int> GetInners(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts);
std::set<int> GetExtendedFanins(int id);
// network traversal
void ForEachPi(std::function<void(int)> const &func) const;
void ForEachPiIdx(std::function<void(int, int)> const &func) const; // func(index, id)
void ForEachInt(std::function<void(int)> const &func) const;
void ForEachIntReverse(std::function<void(int)> const &func) const;
void ForEachPiInt(std::function<void(int)> const &func) const;
@ -124,18 +126,21 @@ namespace rrr {
template <typename Func>
void ForEachFanoutRidx(int id, bool fPos, Func const &func) const; // func(fo[, c], index of id in fanin list of fo)
void ForEachTfi(int id, bool fPis, std::function<void(int)> const &func);
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
void ForEachTfiEnd(int id, Container<Ts...> const &ends, std::function<void(int)> const &func);
void ForEachTfiUpdate(int id, bool fPis, std::function<bool(int)> const &func);
template <template <typename...> typename Container, typename... Ts>
void ForEachTfisUpdate(Container<Ts...> const &ids, bool fPis, std::function<bool(int)> const &func);
void ForEachTfo(int id, bool fPos, std::function<void(int)> const &func);
void ForEachTfoReverse(int id, bool fPos, std::function<void(int)> const &func);
void ForEachTfoUpdate(int id, bool fPos, std::function<bool(int)> const &func);
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
void ForEachTfos(Container<Ts...> const &ids, bool fPos, std::function<void(int)> const &func);
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
void ForEachTfosUpdate(Container<Ts...> const &ids, bool fPos, std::function<bool(int)> const &func);
// extraction
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
AndNetwork *Extract(Container<Ts...> const &ids, std::vector<int> const &vInputs, std::vector<int> const &vOutputs);
// actions
@ -217,7 +222,7 @@ namespace rrr {
ForEachTfiRec(fi, func);
}
}
inline void AndNetwork::TakenAction(Action const &action) const {
for(Callback const &callback: vCallbacks) {
callback(action);
@ -552,7 +557,7 @@ namespace rrr {
return v;
}
template <template <typename...> typename Container, typename ... Ts, template <typename...> typename Container2, typename ... Ts2>
template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
inline bool AndNetwork::IsReachable(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts) {
if(srcs.empty() || dsts.empty()) {
return false;
@ -607,7 +612,7 @@ namespace rrr {
return false;
}
template <template <typename...> typename Container, typename ... Ts, template <typename...> typename Container2, typename ... Ts2>
template <template <typename...> typename Container, typename... Ts, template <typename...> typename Container2, typename... Ts2>
inline std::vector<int> AndNetwork::GetInners(Container<Ts...> const &srcs, Container2<Ts2...> const &dsts) {
// this includes sources and destinations that are connected
if(srcs.empty() || dsts.empty()) {
@ -665,6 +670,43 @@ namespace rrr {
return vInners;
}
inline std::set<int> AndNetwork::GetExtendedFanins(int id) {
// go to the root of trivially collapsable nodes
while(GetNumFanouts(id) == 1) {
int id_new = -1;
ForEachFanout(id, false, [&](int fo, bool c) {
if(!c) {
id_new = fo;
}
});
if(id_new != -1) {
id = id_new;
} else {
break;
}
}
// emulate trivial collapse
std::vector<int> vFaninEdges = vvFaninEdges[id];
for(int idx = 0; idx < int_size(vFaninEdges);) {
int fi_edge = vFaninEdges[idx];
int fi = Edge2Node(fi_edge);
bool c = EdgeIsCompl(fi_edge);
if(!IsPi(fi) && !c && vRefs[fi] == 1) {
std::vector<int>::iterator it = vFaninEdges.begin() + idx;
it = vFaninEdges.erase(it);
vFaninEdges.insert(it, vvFaninEdges[fi].begin(), vvFaninEdges[fi].end());
} else {
idx++;
}
}
// create set
std::set<int> sFanins;
for(int fi_edge: vFaninEdges) {
sFanins.insert(Edge2Node(fi_edge));
}
return sFanins;
}
/* }}} */
/* {{{ Network traversal */
@ -674,7 +716,13 @@ namespace rrr {
func(pi);
}
}
inline void AndNetwork::ForEachPiIdx(std::function<void(int, int)> const &func) const {
for(int idx = 0; idx < GetNumPis(); idx++) {
func(idx, GetPi(idx));
}
}
inline void AndNetwork::ForEachInt(std::function<void(int)> const &func) const {
for(int id: lInts) {
func(id);
@ -834,7 +882,7 @@ namespace rrr {
EndTraversal();
}
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
inline void AndNetwork::ForEachTfiEnd(int id, Container<Ts...> const &ends, std::function<void(int)> const &func) {
// this does not include id itself
StartTraversal();
@ -845,6 +893,66 @@ namespace rrr {
EndTraversal();
}
inline void AndNetwork::ForEachTfiUpdate(int id, bool fPis, std::function<bool(int)> const &func) {
if(GetNumFanins(id) == 0) {
return;
}
StartTraversal();
for(int fi_edge: vvFaninEdges[id]) {
vTrav[Edge2Node(fi_edge)] = iTrav;
}
critr it = std::find(lInts.rbegin(), lInts.rend(), id);
assert(it != lInts.rend());
it++;
for(; it != lInts.rend(); it++) {
if(vTrav[*it] == iTrav) {
if(func(*it)) {
for(int fi_edge: vvFaninEdges[*it]) {
vTrav[Edge2Node(fi_edge)] = iTrav;
}
}
}
}
if(fPis) {
for(int pi: vPis) {
if(vTrav[pi] == iTrav) {
func(pi);
}
}
}
EndTraversal();
}
template <template <typename...> typename Container, typename... Ts>
inline void AndNetwork::ForEachTfisUpdate(Container<Ts...> const &ids, bool fPis, std::function<bool(int)> const &func) {
// this includes ids themselves
StartTraversal();
for(int id: ids) {
vTrav[id] = iTrav;
}
critr it = lInts.rbegin();
while(vTrav[*it] != iTrav && it != lInts.rend()) {
it++;
}
for(; it != lInts.rend(); it++) {
if(vTrav[*it] == iTrav) {
if(func(*it)) {
for(int fi_edge: vvFaninEdges[*it]) {
vTrav[Edge2Node(fi_edge)] = iTrav;
}
}
}
}
if(fPis) {
for(int pi: vPis) {
if(vTrav[pi] == iTrav) {
func(pi);
}
}
}
EndTraversal();
}
inline void AndNetwork::ForEachTfo(int id, bool fPos, std::function<void(int)> const &func) {
// this does not include id itself
if(vRefs[id] == 0) {
@ -951,7 +1059,7 @@ namespace rrr {
EndTraversal();
}
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
inline void AndNetwork::ForEachTfos(Container<Ts...> const &ids, bool fPos, std::function<void(int)> const &func) {
// this includes ids themselves
StartTraversal();
@ -986,7 +1094,7 @@ namespace rrr {
EndTraversal();
}
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
inline void AndNetwork::ForEachTfosUpdate(Container<Ts...> const &ids, bool fPos, std::function<bool(int)> const &func) {
// this includes ids themselves
StartTraversal();
@ -1033,7 +1141,7 @@ namespace rrr {
/* {{{ Extraction */
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
AndNetwork *AndNetwork::Extract(Container<Ts...> const &ids, std::vector<int> const &vInputs, std::vector<int> const &vOutputs) {
AndNetwork *pNtk = new AndNetwork;
pNtk->Reserve(int_size(vInputs) + int_size(ids) + int_size(vOutputs));

View File

@ -609,7 +609,7 @@ namespace rrr {
NewBdd::Param Par;
Par.nObjsMaxLog = 25;
Par.nCacheMaxLog = 20;
Par.fCountOnes = true;
Par.fCountOnes = false;
Par.nGbc = 1;
Par.nReo = 4000;
pBdd = new NewBdd::Man(pNtk->GetNumPis(), Par);

View File

@ -0,0 +1,293 @@
#pragma once
#include <utility>
#include <map>
#include <tuple>
#include <random>
#include "rrrParameter.h"
#include "rrrUtils.h"
ABC_NAMESPACE_CXX_HEADER_START
namespace rrr {
template <typename Ntk>
class LevelBasePartitioner {
private:
// pointer to network
Ntk *pNtk;
// parameters
int nVerbose;
int nPartitionSize;
int nPartitionSizeMin;
std::string strVerbosePrefix;
// data
int nMaxLevel;
std::vector<int> vLevels;
std::map<Ntk *, std::tuple<std::set<int>, std::vector<int>, std::vector<bool>, std::vector<int>>> mSubNtk2Io;
std::set<int> sBlocked;
std::vector<bool> vFailed;
// print
template<typename... Args>
void Print(int nVerboseLevel, Args... args);
// subroutines
void ComputeLevel();
std::vector<int> GetIOI(int id, int nLevels);
Ntk *ExtractIOI(int id);
public:
// constructors
LevelBasePartitioner(Parameter const *pPar);
void UpdateNetwork(Ntk *pNtk);
// APIs
Ntk *Extract(int iSeed);
void Insert(Ntk *pSubNtk);
};
/* {{{ Print */
template <typename Ntk>
template <typename... Args>
inline void LevelBasePartitioner<Ntk>::Print(int nVerboseLevel, Args... args) {
if(nVerbose > nVerboseLevel) {
std::cout << strVerbosePrefix;
for(int i = 0; i < nVerboseLevel; i++) {
std::cout << "\t";
}
PrintNext(std::cout, args...);
std::cout << std::endl;
}
}
/* }}} */
/* {{{ Subroutines */
template <typename Ntk>
void LevelBasePartitioner<Ntk>::ComputeLevel() {
nMaxLevel = 0;
vLevels.clear();
vLevels.resize(pNtk->GetNumNodes());
pNtk->ForEachInt([&](int id) {
pNtk->ForEachFanin(id, [&](int fi) {
if(vLevels[id] < vLevels[fi]) {
vLevels[id] = vLevels[fi];
}
});
vLevels[id] += 1;
if(nMaxLevel < vLevels[id]) {
nMaxLevel = vLevels[id];
}
});
}
template <typename Ntk>
std::vector<int> LevelBasePartitioner<Ntk>::GetIOI(int id, int nLevels) {
std::vector<int> vNodes, vNodes2;
vNodes.push_back(id);
pNtk->ForEachTfiUpdate(id, false, [&](int fi) {
if(vLevels[fi] < vLevels[id] - nLevels) {
return false;
}
vNodes.push_back(fi);
return true;
});
pNtk->ForEachTfosUpdate(vNodes, false, [&](int fo) {
if(vLevels[fo] > vLevels[id] + nLevels) {
return false;
}
vNodes2.push_back(fo);
return true;
});
vNodes.clear();
pNtk->ForEachTfisUpdate(vNodes2, false, [&](int fi) {
if(vLevels[fi] < vLevels[id] - nLevels) {
return false;
}
vNodes.push_back(fi);
return true;
});
return vNodes;
}
template <typename Ntk>
Ntk *LevelBasePartitioner<Ntk>::ExtractIOI(int id) {
// collect IOI nodes
assert(!sBlocked.count(id));
int nLevels = 1;
std::vector<int> vNodes = GetIOI(id, nLevels);
Print(1, "level", NS(), nLevels, ":", "size =", int_size(vNodes));
std::vector<int> vNodesNew = GetIOI(id, nLevels + 1);
Print(1, "level", NS(), nLevels + 1, ":", "size =", int_size(vNodesNew));
// gradually increase level until it hits partition size limit
while(int_size(vNodesNew) < nPartitionSize) {
if(vLevels[id] - nLevels < 1 && vLevels[id] + nLevels >= nMaxLevel) { // already maximum
break;
}
vNodes = vNodesNew;
nLevels++;
vNodesNew = GetIOI(id, nLevels + 1);
Print(1, "level", NS(), nLevels + 1, ":", "size =", int_size(vNodesNew));
}
std::set<int> sNodes(vNodes.begin(), vNodes.end());
// remove nodes that are already blocked
for(std::set<int>::iterator it = sNodes.begin(); it != sNodes.end();) {
if(sBlocked.count(*it)) {
it = sNodes.erase(it);
} else {
it++;
}
}
Print(1, "checking:", "size =", int_size(sNodes));
// get partition IO
std::set<int> sInputs, sOutputs;
for(int id: sNodes) {
pNtk->ForEachFanin(id, [&](int fi) {
if(!sNodes.count(fi)) {
sInputs.insert(fi);
}
});
bool fOutput = false;
pNtk->ForEachFanout(id, true, [&](int fo) {
if(!sNodes.count(fo)) {
fOutput = true;
}
});
if(fOutput) {
sOutputs.insert(id);
}
}
Print(2, "nodes:", sNodes);
Print(2, "inputs:", sInputs);
Print(2, "outputs:", sOutputs);
if(int_size(sNodes) < nPartitionSizeMin) {
return NULL;
}
// check loops and just give up if any
std::set<int> sFanouts;
for(int id: sOutputs) {
pNtk->ForEachFanout(id, false, [&](int fo) {
if(!sNodes.count(fo)) {
sFanouts.insert(fo);
}
});
}
if(pNtk->IsReachable(sFanouts, sInputs)) {
return NULL;
}
for(auto const &entry: mSubNtk2Io) {
if(!pNtk->IsReachable(sOutputs, std::get<1>(entry.second))) {
continue;
}
if(!pNtk->IsReachable(std::get<3>(entry.second), sInputs)) {
continue;
}
return NULL;
}
// extract by inputs, internals, and outputs (no checks needed in ntk side)
std::vector<int> vInputs(sInputs.begin(), sInputs.end());
std::vector<int> vOutputs(sOutputs.begin(), sOutputs.end());
Ntk *pSubNtk = pNtk->Extract(sNodes, vInputs, vOutputs);
// return subntk to be modified, while remember IOs
for(int id: sNodes) {
sBlocked.insert(id);
}
mSubNtk2Io.emplace(pSubNtk, std::make_tuple(std::move(sNodes), std::move(vInputs), std::vector<bool>(vInputs.size()), std::move(vOutputs)));
return pSubNtk;
}
/* }}} */
/* {{{ Constructors */
template <typename Ntk>
LevelBasePartitioner<Ntk>::LevelBasePartitioner(Parameter const *pPar) :
nVerbose(pPar->nPartitionerVerbose),
nPartitionSize(pPar->nPartitionSize),
nPartitionSizeMin(pPar->nPartitionSizeMin) {
}
template <typename Ntk>
void LevelBasePartitioner<Ntk>::UpdateNetwork(Ntk *pNtk_) {
pNtk = pNtk_;
assert(mSubNtk2Io.empty());
assert(sBlocked.empty());
vFailed.clear();
vLevels.clear();
}
/* }}} */
/* {{{ APIs */
template <typename Ntk>
Ntk *LevelBasePartitioner<Ntk>::Extract(int iSeed) {
// pick a center node from candidates that do not belong to any other ongoing partitions
vFailed.resize(pNtk->GetNumNodes());
if(vLevels.empty()) {
ComputeLevel();
}
std::mt19937 rng(iSeed);
std::vector<int> vInts = pNtk->GetInts();
std::shuffle(vInts.begin(), vInts.end(), rng);
for(int i = 0; i < int_size(vInts); i++) {
int id = vInts[i];
if(vFailed[id]) {
continue;
}
if(!sBlocked.count(id)) {
Print(0, "try partitioning with node", id, "(", i, "/", int_size(vInts), ")");
Ntk *pSubNtk = ExtractIOI(id);
if(pSubNtk) {
return pSubNtk;
}
}
vFailed[id] = true;
}
return NULL;
}
template <typename Ntk>
void LevelBasePartitioner<Ntk>::Insert(Ntk *pSubNtk) {
for(int i: std::get<0>(mSubNtk2Io[pSubNtk])) {
sBlocked.erase(i);
}
std::pair<std::vector<int>, std::vector<bool>> vNewSignals = pNtk->Insert(pSubNtk, std::get<1>(mSubNtk2Io[pSubNtk]), std::get<2>(mSubNtk2Io[pSubNtk]), std::get<3>(mSubNtk2Io[pSubNtk]));
std::vector<int> &vOldOutputs = std::get<3>(mSubNtk2Io[pSubNtk]);
std::vector<int> &vNewOutputs = vNewSignals.first;
std::vector<bool> &vNewCompls = vNewSignals.second;
// need to remap updated outputs that are used as inputs in other partitions
std::map<int, int> mOutput2Idx;
for(int idx = 0; idx < int_size(vOldOutputs); idx++) {
mOutput2Idx[vOldOutputs[idx]] = idx;
}
for(auto &entry: mSubNtk2Io) {
if(entry.first != pSubNtk) {
std::vector<int> &vInputs = std::get<1>(entry.second);
std::vector<bool> &vCompls = std::get<2>(entry.second);
for(int i = 0; i < int_size(vInputs); i++) {
if(mOutput2Idx.count(vInputs[i])) {
int idx = mOutput2Idx[vInputs[i]];
vInputs[i] = vNewOutputs[idx];
vCompls[i] = vCompls[i] ^ vNewCompls[idx];
}
}
}
}
delete pSubNtk;
mSubNtk2Io.erase(pSubNtk);
vFailed.clear(); // clear, there isn't really a way to track
vLevels.clear();
}
/* }}} */
}
ABC_NAMESPACE_CXX_HEADER_END

View File

@ -12,6 +12,7 @@ ABC_NAMESPACE_CXX_HEADER_START
namespace rrr {
// it is assumed that removing redundancy never degrades the cost in this optimizer
template <typename Ntk, typename Ana>
class Optimizer {
private:
@ -27,11 +28,14 @@ namespace rrr {
// parameters
int nVerbose;
std::function<double(Ntk *)> CostFunction;
int nSortTypeOriginal;
int nSortType;
int nFlow;
int nDistance;
bool fCompatible;
bool fGreedy;
seconds nTimeout; // assigned upon Run
std::string strVerbosePrefix;
// data
Ana ana;
@ -47,6 +51,10 @@ namespace rrr {
// marks
int target;
std::vector<bool> vTfoMarks;
// print
template<typename... Args>
void Print(int nVerboseLevel, Args... args);
// callback
void ActionCallback(Action const &action);
@ -81,11 +89,21 @@ namespace rrr {
int MultiAdd(int id, std::vector<int> const &vCands, int nMax = 0);
// resub
void SingleResub(int id, std::vector<int> const &vCands, bool fGreedy = true);
void MultiResub(int id, std::vector<int> const &vCands, bool fGreedy = true, int nMax = 0);
void SingleResub(int id, std::vector<int> const &vCands);
void MultiResub(int id, std::vector<int> const &vCands, int nMax = 0);
// resub stop
bool SingleResubStop(int id, std::vector<int> const &vCands);
bool MultiResubStop(int id, std::vector<int> const &vCands, int nMax = 0);
// multi-target resub
bool MultiTargetResub(std::vector<int> vTargets, int nMax = 0);
// apply
void ApplyReverseTopologically(std::function<void(int)> const &func);
void ApplyRandomlyStop(std::function<bool(int)> const &func);
void ApplyCombinationRandomlyStop(int k, std::function<bool(std::vector<int> const &)> const &func);
void ApplyCombinationSampledRandomlyStop(int k, int nSamples, std::function<bool(std::vector<int> const &)> const &func);
public:
// constructors
@ -93,18 +111,39 @@ namespace rrr {
void UpdateNetwork(Ntk *pNtk_, bool fSame = false);
// run
void Run(seconds nTimeout_ = 0);
void ResetSeed(int iSeed);
void Randomize(int iSeed);
void Run(int iSeed = 0, seconds nTimeout_ = 0);
};
/* {{{ 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;
for(int i = 0; i < nVerboseLevel; i++) {
std::cout << "\t";
}
PrintNext(std::cout, args...);
std::cout << std::endl;
}
}
/* }}} */
/* {{{ Callback */
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::ActionCallback(Action const &action) {
if(nVerbose) {
PrintAction(action);
if(nVerbose > 2) {
std::stringstream ss = GetActionDescription(action);
std::string str;
std::getline(ss, str);
Print(2, str);
while(std::getline(ss, str)) {
Print(3, str);
}
}
switch(action.type) {
case REMOVE_FANIN:
@ -683,7 +722,7 @@ namespace rrr {
/* {{{ Resub */
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::SingleResub(int id, std::vector<int> const &vCands, bool fGreedy) {
void Optimizer<Ntk, Ana>::SingleResub(int id, std::vector<int> const &vCands) {
// NOTE: this assumes trivial collapse/decompose does not change cost
// let us assume the node is not trivially redundant for now
assert(pNtk->GetNumFanouts(id) != 0);
@ -691,7 +730,7 @@ namespace rrr {
// collapse
pNtk->TrivialCollapse(id);
// save if wanted
int slot;
int slot = -2;
if(fGreedy) {
slot = pNtk->Save();
}
@ -708,12 +747,11 @@ namespace rrr {
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);
if(nVerbose) {
std::cout << "cost: " << dCost << " -> " << dNewCost << std::endl;
}
Print(2, "cost:", dCost, "->", dNewCost);
if(fGreedy) {
if(dNewCost <= dCost) {
pNtk->Save(slot);
@ -738,13 +776,13 @@ namespace rrr {
}
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::MultiResub(int id, std::vector<int> const &vCands, bool fGreedy, int nMax) {
void Optimizer<Ntk, Ana>::MultiResub(int id, std::vector<int> const &vCands, int nMax) {
// NOTE: this assumes trivial collapse/decompose does not change cost
// let us assume the node is not trivially redundant for now
assert(pNtk->GetNumFanouts(id) != 0);
assert(pNtk->GetNumFanins(id) > 1);
// save if wanted
int slot;
int slot = -2;
if(fGreedy) {
slot = pNtk->Save();
}
@ -755,16 +793,19 @@ namespace rrr {
MultiAdd(id, vCands, nMax);
RemoveRedundancy();
mapNewFanins.clear();
// TODO: we could quit here if nothing has been removed
RemoveRedundancy();
double dNewCost = CostFunction(pNtk);
if(nVerbose) {
std::cout << "cost: " << dCost << " -> " << dNewCost << std::endl;
}
Print(1, "cost:", dCost, "->", dNewCost);
if(fGreedy && dNewCost > dCost) {
pNtk->Load(slot);
}
if(pNtk->IsInt(id)) {
pNtk->TrivialDecompose(id);
SortFanins();
if(fCompatible) {
RemoveRedundancy();
}
}
if(fGreedy) {
pNtk->PopBack();
@ -773,6 +814,201 @@ namespace rrr {
/* }}} */
/* {{{ Resub stop */
template <typename Ntk, typename Ana>
bool Optimizer<Ntk, Ana>::SingleResubStop(int id, std::vector<int> const &vCands) {
// stop whenever structure has changed without increasing cost and return true
// return false if no candidates are effective
// NOTE: this assumes trivial collapse/decompose does not change cost
// 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();
// collapse
pNtk->TrivialCollapse(id);
// save after trivial collapse
int slot = pNtk->Save();
double dCost = CostFunction(pNtk);
// remember fanins
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
Print(2, "extended fanins:", sFanins);
// main loop
for(citr it = vCands.begin(); it != vCands.end(); it++) {
if(Timeout()) {
break;
}
assert(pNtk->IsInt(id));
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) {
fChanged = true;
}
}
if(fChanged) {
if(pNtk->IsInt(id)) {
pNtk->TrivialDecompose(id);
}
pNtk->PopBack(); // slot
pNtk->PopBack(); // slot0
return true;
}
}
pNtk->Load(slot);
}
pNtk->PopBack(); // slot
pNtk->Load(slot0);
pNtk->PopBack(); // slot0
return false;
}
template <typename Ntk, typename Ana>
bool Optimizer<Ntk, Ana>::MultiResubStop(int id, std::vector<int> const &vCands, int nMax) {
// if structure has changed without increasing cost, return true
// otherwise, return false
// NOTE: this assumes trivial collapse/decompose does not change cost
// let us assume the node is not trivially redundant for now
assert(pNtk->GetNumFanouts(id) != 0);
assert(pNtk->GetNumFanins(id) > 1);
// save
int slot = pNtk->Save();
double dCost = CostFunction(pNtk);
// remember fanins
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
Print(2, "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;
} 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;
}
}
pNtk->Load(slot);
pNtk->PopBack();
return false;
}
/* }}} */
/* {{{ Multi-target resub */
template <typename Ntk, typename Ana>
bool Optimizer<Ntk, Ana>::MultiTargetResub(std::vector<int> vTargets, int nMax) {
// save
int slot = pNtk->Save();
double dCost = CostFunction(pNtk);
// remove targets that are trivially collapsed together
for(int id: vTargets) {
if(pNtk->IsInt(id)) {
pNtk->TrivialCollapse(id);
}
}
for(itr it = vTargets.begin(); it != vTargets.end();) {
if(!pNtk->IsInt(*it)) {
it = vTargets.erase(it);
} else {
it++;
}
}
// add while remembering extended fanins
Print(1, "targets:", vTargets);
std::vector<std::set<int>> vsFanins;
for(int id: vTargets) {
// get candidates
std::vector<int> vCands;
if(nDistance) {
vCands = pNtk->GetNeighbors(id, true, nDistance);
} else {
vCands = pNtk->GetPisInts();
}
std::shuffle(vCands.begin(), vCands.end(), rng);
// remember fanins
std::set<int> sFanins = pNtk->GetExtendedFanins(id);
Print(2, "extended fanins:", sFanins);
vsFanins.push_back(std::move(sFanins));
// add
MultiAdd(id, vCands, nMax);
}
// reduce
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) {
fChanged = true;
} else {
for(int id: vTargets) {
if(!pNtk->IsInt(id)) {
fChanged = true;
break;
}
}
for(int i = 0; !fChanged && i < int_size(vTargets); i++) {
std::set<int> sNewFanins = pNtk->GetExtendedFanins(vTargets[i]);
Print(2, "new extended fanins:", sNewFanins);
if(vsFanins[i] != sNewFanins) {
fChanged = true;
}
}
}
if(fChanged) {
for(int id: vTargets) {
if(pNtk->IsInt(id)) {
pNtk->TrivialDecompose(id);
}
}
pNtk->PopBack();
return true;
}
}
pNtk->Load(slot);
pNtk->PopBack();
return false;
}
/* }}} */
/* {{{ Apply */
template <typename Ntk, typename Ana>
@ -785,12 +1021,73 @@ namespace rrr {
if(!pNtk->IsInt(*it)) {
continue;
}
if(nVerbose) {
std::cout << "node " << *it << " (" << std::distance(vInts.crbegin(), it) + 1 << "/" << vInts.size() << ")" << std::endl;
}
Print(0, "node", *it, "(", int_distance(vInts.crbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk));
func(*it);
}
}
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::ApplyRandomlyStop(std::function<bool(int)> const &func) {
std::vector<int> vInts = pNtk->GetInts();
std::shuffle(vInts.begin(), vInts.end(), rng);
for(citr it = vInts.begin(); it != vInts.end(); it++) {
if(Timeout()) {
break;
}
if(!pNtk->IsInt(*it)) {
continue;
}
Print(0, "node", *it, "(", int_distance(vInts.cbegin(), it) + 1, "/", int_size(vInts), "):", "cost", "=", CostFunction(pNtk));
if(func(*it)) {
break;
}
}
}
template <typename Ntk, typename Ana>
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 nCombs = k * (k - 1) / 2;
ForEachCombinationStop(int_size(vInts), k, [&](std::vector<int> const &vIdxs) {
Print(0, "comb", vIdxs, "(", ++nTried, "/", nCombs, ")");
assert(int_size(vIdxs) == k);
if(Timeout()) {
return true;
}
std::vector<int> vTargets(k);
for(int i = 0; i < k; i++) {
vTargets[i] = vInts[vIdxs[i]];
}
return func(vTargets);
});
}
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::ApplyCombinationSampledRandomlyStop(int k, int nSamples, std::function<bool(std::vector<int> const &)> const &func) {
std::vector<int> vInts = pNtk->GetInts();
for(int i = 0; i < nSamples; i++) {
if(Timeout()) {
break;
}
std::set<int> sIdxs;
while(int_size(sIdxs) < k) {
int idx = rng() % pNtk->GetNumInts();
sIdxs.insert(idx);
}
std::vector<int> vIdxs(sIdxs.begin(), sIdxs.end());
std::shuffle(vIdxs.begin(), vIdxs.end(), rng);
Print(0, "comb", vIdxs, "(", i + 1, "/", nSamples, ")");
std::vector<int> vTargets(k);
for(int i = 0; i < k; i++) {
vTargets[i] = vInts[vIdxs[i]];
}
if(func(vTargets)) {
break;
}
}
}
/* }}} */
@ -801,10 +1098,12 @@ namespace rrr {
pNtk(NULL),
nVerbose(pPar->nOptimizerVerbose),
CostFunction(CostFunction),
nSortTypeOriginal(pPar->nSortType),
nSortType(pPar->nSortType),
nFlow(pPar->nOptimizerFlow),
nDistance(pPar->nDistance),
fCompatible(pPar->fUseBddCspf),
fGreedy(pPar->fGreedy),
ana(pPar),
target(-1) {
}
@ -822,7 +1121,14 @@ namespace rrr {
/* {{{ Run */
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::Run(seconds nTimeout_) {
void Optimizer<Ntk, Ana>::Run(int iSeed, seconds nTimeout_) {
rng.seed(iSeed);
vRandPiOrder.clear();
vRandCosts.clear();
if(nSortTypeOriginal < 0) {
nSortType = rng() % 18;
Print(0, "sorttype =", nSortType);
}
nTimeout = nTimeout_;
start = GetCurrentTime();
switch(nFlow) {
@ -882,23 +1188,37 @@ namespace rrr {
}
break;
}
case 3: {
RemoveRedundancy();
std::vector<int> vCands;
if(!nDistance) {
vCands = pNtk->GetPisInts();
std::shuffle(vCands.begin(), vCands.end(), rng);
}
ApplyRandomlyStop([&](int id) {
if(nDistance) {
vCands = pNtk->GetNeighbors(id, true, nDistance);
std::shuffle(vCands.begin(), vCands.end(), rng);
}
if(rng() & 1) {
return SingleResubStop(id, vCands);
} else {
return MultiResubStop(id, vCands);
}
});
break;
}
case 4: {
RemoveRedundancy();
ApplyCombinationSampledRandomlyStop(3, 100, [&](std::vector<int> const &vTargets) {
return MultiTargetResub(vTargets);
});
break;
}
default:
assert(0);
}
}
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::ResetSeed(int iSeed) {
rng.seed(iSeed);
vRandPiOrder.clear();
vRandCosts.clear();
}
template <typename Ntk, typename Ana>
void Optimizer<Ntk, Ana>::Randomize(int iSeed) {
ResetSeed(iSeed);
nSortType = rng() % 18;
}
/* }}} */

View File

@ -17,14 +17,19 @@ namespace rrr {
bool fUseBddCspf = false;
bool fUseBddMspf = false;
int nConflictLimit = 0;
int nSortType = 12;
int nSortType = -1;
int nOptimizerFlow = 0;
int nSchedulerFlow = 0;
int nPartitionType = 0;
int nDistance = 0;
int nRestarts = 0;
int nJobs = 1;
int nThreads = 1;
int nWindowSize = 0;
int nPartitionSize = 0;
int nPartitionSizeMin = 0;
bool fDeterministic = true;
int nParallelPartitions = 1;
bool fOptOnInsert = false;
bool fGreedy = true;
};
}

View File

@ -20,13 +20,23 @@ namespace rrr {
// parameters
int nVerbose;
int nWindowSize;
int nPartitionSize;
int nPartitionSizeMin;
std::string strVerbosePrefix;
// data
std::map<Ntk *, std::tuple<std::set<int>, std::vector<int>, std::vector<bool>, std::vector<int>>> mSubNtk2Io;
std::set<int> sBlocked;
std::vector<bool> vFailed;
// print
template<typename... Args>
void Print(int nVerboseLevel, Args... args);
// subroutines
void GetIo(std::set<int> const &sNodes, std::set<int> &sInputs, std::set<int> &sOutputs);
std::set<int> GetFanouts(std::set<int> const &sNodes, std::set<int> const &sOutputs);
std::set<int> GetUnblockedNeighborsAndInners(int id, int nRadius);
Ntk *ExtractDisjoint(int id);
public:
@ -39,45 +49,29 @@ namespace rrr {
void Insert(Ntk *pSubNtk);
};
/* {{{ Print */
template <typename Ntk>
template <typename... Args>
inline void Partitioner<Ntk>::Print(int nVerboseLevel, Args... args) {
if(nVerbose > nVerboseLevel) {
std::cout << strVerbosePrefix;
for(int i = 0; i < nVerboseLevel; i++) {
std::cout << "\t";
}
PrintNext(std::cout, args...);
std::cout << std::endl;
}
}
/* }}} */
/* {{{ Subroutines */
template <typename Ntk>
Ntk *Partitioner<Ntk>::ExtractDisjoint(int id) {
// collect neighbor
assert(!sBlocked.count(id));
if(nVerbose) {
std::cout << "extracting with a center node " << id << std::endl;
}
int nRadius = 2;
std::vector<int> vNodes = pNtk->GetNeighbors(id, false, nRadius);
std::vector<int> vNodesNew = pNtk->GetNeighbors(id, false, nRadius + 1);
// gradually increase radius until it hits window size limit
while(int_size(vNodesNew) < nWindowSize) {
if(int_size(vNodes) == int_size(vNodesNew)) { // already maximum
break;
}
vNodes = vNodesNew;
nRadius++;
vNodesNew = pNtk->GetNeighbors(id, false, nRadius + 1);
}
std::set<int> sNodes(vNodes.begin(), vNodes.end());
sNodes.insert(id);
if(nVerbose) {
std::cout << "neighbors: " << sNodes << std::endl;
}
// remove nodes that are already blocked
for(std::set<int>::iterator it = sNodes.begin(); it != sNodes.end();) {
if(sBlocked.count(*it)) {
it = sNodes.erase(it);
} else {
it++;
}
}
if(nVerbose) {
std::cout << "disjoint neighbors: " << sNodes << std::endl;
}
// get tentative window IO
std::set<int> sInputs, sOutputs;
void Partitioner<Ntk>::GetIo(std::set<int> const &sNodes, std::set<int> &sInputs, std::set<int> &sOutputs) {
sInputs.clear();
sOutputs.clear();
for(int id: sNodes) {
pNtk->ForEachFanin(id, [&](int fi) {
if(!sNodes.count(fi)) {
@ -94,12 +88,10 @@ namespace rrr {
sOutputs.insert(id);
}
}
if(nVerbose) {
std::cout << "\tinputs: " << sInputs << std::endl;
std::cout << "\toutputs: " << sOutputs << std::endl;
}
// prevent potential loops while ensuring disjointness
// first by including inner nodes
}
template <typename Ntk>
std::set<int> Partitioner<Ntk>::GetFanouts(std::set<int> const &sNodes, std::set<int> const &sOutputs) {
std::set<int> sFanouts;
for(int id: sOutputs) {
pNtk->ForEachFanout(id, false, [&](int fo) {
@ -108,89 +100,111 @@ namespace rrr {
}
});
}
return sFanouts;
}
template <typename Ntk>
std::set<int> Partitioner<Ntk>::GetUnblockedNeighborsAndInners(int id, int nRadius) {
// return empty set on failure
// get neighbors
std::vector<int> vNodes = pNtk->GetNeighbors(id, false, nRadius);
vNodes.push_back(id);
std::set<int> sNodes(vNodes.begin(), vNodes.end());
Print(2, "radius", NS(), nRadius, ":", "size =", int_size(sNodes));
// remove nodes that are already blocked
for(std::set<int>::iterator it = sNodes.begin(); it != sNodes.end();) {
if(sBlocked.count(*it)) {
it = sNodes.erase(it);
} else {
it++;
}
}
Print(2, "unblocked:", "size =", int_size(sNodes));
if(int_size(sNodes) > nPartitionSize) {
// too large
return std::set<int>();
}
// get tentative partition IO
std::set<int> sInputs, sOutputs;
GetIo(sNodes, sInputs, sOutputs);
Print(3, "nodes:", sNodes);
Print(3, "inputs:", sInputs);
Print(3, "outputs:", sOutputs);
// include inner nodes
std::set<int> sFanouts = GetFanouts(sNodes, sOutputs);
std::vector<int> vInners = pNtk->GetInners(sFanouts, sInputs);
while(!vInners.empty()) {
if(nVerbose) {
std::cout << "inners: " << vInners << std::endl;
}
if(int_size(sNodes) + int_size(vInners) > 2 * nWindowSize) {
// TODO: parametrize
break;
}
bool fOverlap = false;
for(int i: vInners) {
if(sBlocked.count(i)) {
fOverlap = true;
break;
Print(2, "inner size =", int_size(vInners));
// check overlap
for(int id: vInners) {
if(sBlocked.count(id)) {
// overlapped
return std::set<int>();
}
}
if(fOverlap) {
break;
}
// expand
sNodes.insert(vInners.begin(), vInners.end());
if(nVerbose) {
std::cout << "new neighbors: " << sNodes << std::endl;
}
sInputs.clear();
sOutputs.clear();
for(int id: sNodes) {
pNtk->ForEachFanin(id, [&](int fi) {
if(!sNodes.count(fi)) {
sInputs.insert(fi);
}
});
bool fOutput = false;
pNtk->ForEachFanout(id, true, [&](int fo) {
if(!sNodes.count(fo)) {
fOutput = true;
}
});
if(fOutput) {
sOutputs.insert(id);
}
}
if(nVerbose) {
std::cout << "\tnew inputs: " << sInputs << std::endl;
std::cout << "\tnew outputs: " << sOutputs << std::endl;
}
sFanouts.clear();
for(int id: sOutputs) {
pNtk->ForEachFanout(id, false, [&](int fo) {
if(!sNodes.count(fo)) {
sFanouts.insert(fo);
}
});
Print(2, "expanded:", "size =", int_size(sNodes));
if(int_size(sNodes) > nPartitionSize) {
// too large
return std::set<int>();
}
GetIo(sNodes, sInputs, sOutputs);
Print(3, "nodes:", sNodes);
Print(3, "inputs:", sInputs);
Print(3, "outputs:", sOutputs);
// recompute fanouts
sFanouts = GetFanouts(sNodes, sOutputs);
vInners = pNtk->GetInners(sFanouts, sInputs);
}
return sNodes;
}
template <typename Ntk>
Ntk *Partitioner<Ntk>::ExtractDisjoint(int id) {
// collect neighbor
assert(!sBlocked.count(id));
int nRadius = 1;
std::set<int> sNodes = GetUnblockedNeighborsAndInners(id, nRadius);
Print(1, "radius", NS(), nRadius, ":", "size =", int_size(sNodes));
if(sNodes.empty()) {
return NULL;
}
std::set<int> sNodesNew = GetUnblockedNeighborsAndInners(id, nRadius + 1);
Print(1, "radius", NS(), nRadius + 1, ":", "size =", int_size(sNodesNew));
// gradually increase radius until it hits partition size limit
while(!sNodesNew.empty()) {
if(int_size(sNodes) == int_size(sNodesNew)) { // likely already maximum
break;
}
sNodes = sNodesNew;
nRadius++;
sNodesNew = GetUnblockedNeighborsAndInners(id, nRadius + 1);
Print(1, "radius", NS(), nRadius + 1, ":", "size =", int_size(sNodesNew));
}
if(int_size(sNodes) < nPartitionSizeMin) {
// too small
return NULL;
}
std::set<int> sInputs, sOutputs;
GetIo(sNodes, sInputs, sOutputs);
/* fall back method by removing TFI of outputs reachable to inputs
if(!vInners.empty()) {
// fall back method by removing TFI of outputs reachable to inputs
for(int id: sOutputs) {
if(!sNodes.count(id)) { // already removed
continue;
}
sFanouts.clear();
pNtk->ForEachFanout(id, false, [&](int fo) {
if(!sNodes.count(fo)) {
sFanouts.insert(fo);
}
});
std::set<int> sFanouts = GetFanouts(sNodes, sOutputs);
if(pNtk->IsReachable(sFanouts, sInputs)) {
if(nVerbose) {
std::cout << id << " is reachable to inputs" << std::endl;
}
Print(2, "node", id, "is reachable");
sNodes.erase(id);
pNtk->ForEachTfiEnd(id, sInputs, [&](int fi) {
int r = sNodes.erase(fi);
assert(r);
});
if(nVerbose) {
std::cout << "new neighbors: " << sNodes << std::endl;
}
if(sNodes.empty()) {
if(nVerbose) {
std::cout << "IS EMPTY" << std::endl;
}
Print(1, "shrinking:", "size =", int_size(sNodes));
if(int_size(sNodes) < nPartitionSizeMin) {
// too small
return NULL;
}
// recompute inputs
@ -202,9 +216,8 @@ namespace rrr {
}
});
}
if(nVerbose) {
std::cout << "\tnew inputs: " << sInputs << std::endl;
}
Print(3, "nodes:", sNodes);
Print(3, "inputs:", sInputs);
}
}
// recompute outputs
@ -215,11 +228,10 @@ namespace rrr {
it++;
}
}
if(nVerbose) {
std::cout << "\tnew outputs: " << sOutputs << std::endl;
}
Print(3, "new outputs:", sOutputs);
}
// ensure outputs of both windows do not reach each other's inputs at the same time
*/
// ensure outputs of both partitions do not reach each other's inputs at the same time
for(auto const &entry: mSubNtk2Io) {
if(!pNtk->IsReachable(sOutputs, std::get<1>(entry.second))) {
continue;
@ -227,23 +239,20 @@ namespace rrr {
if(!pNtk->IsReachable(std::get<3>(entry.second), sInputs)) {
continue;
}
if(nVerbose) {
std::cout << "POTENTIAL LOOPS" << std::endl;
}
return NULL;
}
if(int_size(sNodes) < nWindowSize / 2) {
// too small
// TODO: fix this parameterized
// if(nVerbose) {
// std::cout << "POTENTIAL LOOPS" << std::endl;
// }
return NULL;
}
assert(int_size(sNodes) <= nPartitionSize);
assert(int_size(sNodes) >= nPartitionSizeMin);
// extract by inputs, internals, and outputs (no checks needed in ntk side)
std::vector<int> vInputs(sInputs.begin(), sInputs.end());
std::vector<int> vOutputs(sOutputs.begin(), sOutputs.end());
Ntk *pSubNtk = pNtk->Extract(sNodes, vInputs, vOutputs);
// return subntk to be modified, while remember IOs
for(int i: sNodes) {
sBlocked.insert(i);
for(int id: sNodes) {
sBlocked.insert(id);
}
mSubNtk2Io.emplace(pSubNtk, std::make_tuple(std::move(sNodes), std::move(vInputs), std::vector<bool>(vInputs.size()), std::move(vOutputs)));
return pSubNtk;
@ -256,12 +265,16 @@ namespace rrr {
template <typename Ntk>
Partitioner<Ntk>::Partitioner(Parameter const *pPar) :
nVerbose(pPar->nPartitionerVerbose),
nWindowSize(pPar->nWindowSize) {
nPartitionSize(pPar->nPartitionSize),
nPartitionSizeMin(pPar->nPartitionSizeMin) {
}
template <typename Ntk>
void Partitioner<Ntk>::UpdateNetwork(Ntk *pNtk_) {
pNtk = pNtk_;
assert(mSubNtk2Io.empty());
assert(sBlocked.empty());
vFailed.clear();
}
/* }}} */
@ -270,17 +283,24 @@ namespace rrr {
template <typename Ntk>
Ntk *Partitioner<Ntk>::Extract(int iSeed) {
// pick a center node from candidates that do not belong to any other ongoing windows
// pick a center node from candidates that do not belong to any other ongoing partitions
vFailed.resize(pNtk->GetNumNodes());
std::mt19937 rng(iSeed);
std::vector<int> vInts = pNtk->GetInts();
std::shuffle(vInts.begin(), vInts.end(), rng);
for(int id: vInts) {
for(int i = 0; i < int_size(vInts); i++) {
int id = vInts[i];
if(vFailed[id]) {
continue;
}
if(!sBlocked.count(id)) {
Print(0, "try partitioning with node", id, "(", i, "/", int_size(vInts), ")");
Ntk *pSubNtk = ExtractDisjoint(id);
if(pSubNtk) {
return pSubNtk;
}
}
vFailed[id] = true;
}
return NULL;
}
@ -294,7 +314,7 @@ namespace rrr {
std::vector<int> &vOldOutputs = std::get<3>(mSubNtk2Io[pSubNtk]);
std::vector<int> &vNewOutputs = vNewSignals.first;
std::vector<bool> &vNewCompls = vNewSignals.second;
// need to remap updated outputs that are used as inputs in other windows
// need to remap updated outputs that are used as inputs in other partitions
std::map<int, int> mOutput2Idx;
for(int idx = 0; idx < int_size(vOldOutputs); idx++) {
mOutput2Idx[vOldOutputs[idx]] = idx;
@ -314,6 +334,7 @@ namespace rrr {
}
delete pSubNtk;
mSubNtk2Io.erase(pSubNtk);
vFailed.clear(); // clear, there isn't really a way to track
}
/* }}} */

View File

@ -108,7 +108,7 @@ namespace rrr {
void SatSolver<Ntk>::EncodeNode(sat_solver *p, std::vector<int> const &v, int id, int to_negate) const {
int RetValue;
int x = -1, y = -1;
bool cx, cy;
bool cx = false, cy = false;
assert(pNtk->GetNodeType(id) == AND);
std::string delim;
if(nVerbose) {

View File

@ -11,16 +11,18 @@
#include "rrrParameter.h"
#include "rrrUtils.h"
#include "rrrPartitioner.h"
#include "rrrAbc.h"
ABC_NAMESPACE_CXX_HEADER_START
namespace rrr {
template <typename Ntk, typename Opt>
template <typename Ntk, typename Opt, typename Par>
class Scheduler {
private:
// aliases
static constexpr char *pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l";
// job
struct Job;
struct CompareJobPointers;
@ -32,18 +34,20 @@ namespace rrr {
int nVerbose;
int iSeed;
int nFlow;
int nRestarts;
int nJobs;
bool fMultiThreading;
bool fPartitioning;
bool fDeterministic;
int nParallelPartitions;
bool fOptOnInsert;
seconds nTimeout;
std::function<double(Ntk *)> CostFunction;
// data
int nJobs;
int nCreatedJobs;
int nFinishedJobs;
time_point start;
Partitioner<Ntk> par;
Par par;
std::queue<Job *> qPendingJobs;
Opt *pOpt; // used only in case of single thread execution
#ifdef ABC_USE_PTHREADS
@ -86,8 +90,8 @@ namespace rrr {
/* {{{ Job */
template <typename Ntk, typename Opt>
struct Scheduler<Ntk, Opt>::Job {
template <typename Ntk, typename Opt, typename Par>
struct Scheduler<Ntk, Opt, Par>::Job {
// data
int id;
Ntk *pNtk;
@ -101,8 +105,8 @@ namespace rrr {
}
};
template <typename Ntk, typename Opt>
struct Scheduler<Ntk, Opt>::CompareJobPointers {
template <typename Ntk, typename Opt, typename Par>
struct Scheduler<Ntk, Opt, Par>::CompareJobPointers {
// smaller id comes first in priority_queue
bool operator()(Job const *lhs, Job const *rhs) const {
return lhs->id > rhs->id;
@ -113,8 +117,8 @@ namespace rrr {
/* {{{ Time */
template <typename Ntk, typename Opt>
seconds Scheduler<Ntk, Opt>::GetRemainingTime() const {
template <typename Ntk, typename Opt, typename Par>
seconds Scheduler<Ntk, Opt, Par>::GetRemainingTime() const {
if(nTimeout == 0) {
return 0;
}
@ -130,8 +134,8 @@ namespace rrr {
/* {{{ Abc */
template <typename Ntk, typename Opt>
inline void Scheduler<Ntk, Opt>::CallAbc(Ntk *pNtk_, std::string Command) {
template <typename Ntk, typename Opt, typename Par>
inline void Scheduler<Ntk, Opt, Par>::CallAbc(Ntk *pNtk_, std::string Command) {
#ifdef ABC_USE_PTHREADS
if(fMultiThreading) {
{
@ -148,14 +152,13 @@ namespace rrr {
/* {{{ Run jobs */
template <typename Ntk, typename Opt>
void Scheduler<Ntk, Opt>::RunJob(Opt &opt, Job const *pJob) {
template <typename Ntk, typename Opt, typename Par>
void Scheduler<Ntk, Opt, Par>::RunJob(Opt &opt, Job const *pJob) {
opt.UpdateNetwork(pJob->pNtk);
// start flow
switch(nFlow) {
case 0:
opt.ResetSeed(pJob->iSeed);
opt.Run(GetRemainingTime());
opt.Run(pJob->iSeed, GetRemainingTime());
break;
case 1: { // transtoch
std::mt19937 rng(pJob->iSeed);
@ -181,8 +184,7 @@ namespace rrr {
if(GetRemainingTime() < 0) {
break;
}
opt.Randomize(rng());
opt.Run(GetRemainingTime());
opt.Run(rng(), GetRemainingTime());
CallAbc(pJob->pNtk, "&dc2");
double dNewCost = CostFunction(pJob->pNtk);
if(nVerbose) {
@ -221,7 +223,6 @@ namespace rrr {
}
// deepsyn
int fUseTwo = 0;
std::string pCompress2rs = "balance -l; resub -K 6 -l; rewrite -l; resub -K 6 -N 2 -l; refactor -l; resub -K 8 -l; balance -l; resub -K 8 -N 2 -l; rewrite -l; resub -K 10 -l; rewrite -z -l; resub -K 10 -N 2 -l; balance -l; resub -K 12 -l; refactor -z -l; resub -K 12 -N 2 -l; rewrite -z -l; balance -l";
unsigned Rand = rng();
int fDch = Rand & 1;
//int fCom = (Rand >> 1) & 3;
@ -230,11 +231,11 @@ namespace rrr {
int KLut = fUseTwo ? 2 + (i % 5) : 3 + (i % 4);
std::string pComp;
if ( fCom == 3 )
pComp = "; &put; " + pCompress2rs + "; " + pCompress2rs + "; " + pCompress2rs + "; &get";
pComp = std::string("; &put; ") + pCompress2rs + "; " + pCompress2rs + "; " + pCompress2rs + "; &get";
else if ( fCom == 2 )
pComp = "; &put; " + pCompress2rs + "; " + pCompress2rs + "; &get";
pComp = std::string("; &put; ") + pCompress2rs + "; " + pCompress2rs + "; &get";
else if ( fCom == 1 )
pComp = "; &put; " + pCompress2rs + "; &get";
pComp = std::string("; &put; ") + pCompress2rs + "; &get";
else if ( fCom == 0 )
pComp = "; &dc2";
std::string Command = "&dch";
@ -254,12 +255,11 @@ namespace rrr {
break;
}
opt.UpdateNetwork(pJob->pNtk, true);
opt.Randomize(rng());
opt.Run(GetRemainingTime());
opt.Run(rng(), GetRemainingTime());
if(rng() & 1) {
CallAbc(pJob->pNtk, "&dc2");
} else {
CallAbc(pJob->pNtk, "&put; " + pCompress2rs + "; &get");
CallAbc(pJob->pNtk, std::string("&put; ") + pCompress2rs + "; &get");
}
if(nVerbose) {
std::cout << "\trrr " << std::setw(6) << j << ": cost = " << CostFunction(pJob->pNtk) << std::endl;
@ -280,6 +280,10 @@ namespace rrr {
}
break;
}
case 3:
opt.Run(pJob->iSeed, GetRemainingTime());
CallAbc(pJob->pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
break;
default:
assert(0);
}
@ -289,9 +293,9 @@ namespace rrr {
/* {{{ Manage jobs */
template <typename Ntk, typename Opt>
void Scheduler<Ntk, Opt>::CreateJob(Ntk *pNtk_, int iSeed_) {
Job *pJob = new Job(nJobs++, pNtk_, iSeed_);
template <typename Ntk, typename Opt, typename Par>
void Scheduler<Ntk, Opt, Par>::CreateJob(Ntk *pNtk_, int iSeed_) {
Job *pJob = new Job(nCreatedJobs++, pNtk_, iSeed_);
#ifdef ABC_USE_PTHREADS
if(fMultiThreading) {
{
@ -305,8 +309,8 @@ namespace rrr {
qPendingJobs.push(pJob);
}
template <typename Ntk, typename Opt>
void Scheduler<Ntk, Opt>::OnJobEnd(std::function<void(Job *pJob)> const &func) {
template <typename Ntk, typename Opt, typename Par>
void Scheduler<Ntk, Opt, Par>::OnJobEnd(std::function<void(Job *pJob)> const &func) {
#ifdef ABC_USE_PTHREADS
if(fMultiThreading) {
Job *pJob = NULL;
@ -340,8 +344,8 @@ namespace rrr {
/* {{{ Thread */
#ifdef ABC_USE_PTHREADS
template <typename Ntk, typename Opt>
void Scheduler<Ntk, Opt>::Thread(Parameter const *pPar) {
template <typename Ntk, typename Opt, typename Par>
void Scheduler<Ntk, Opt, Par>::Thread(Parameter const *pPar) {
Opt opt(pPar, CostFunction);
while(true) {
Job *pJob = NULL;
@ -371,19 +375,21 @@ namespace rrr {
/* }}} */
/* {{{ Constructors */
template <typename Ntk, typename Opt>
Scheduler<Ntk, Opt>::Scheduler(Ntk *pNtk, Parameter const *pPar) :
template <typename Ntk, typename Opt, typename Par>
Scheduler<Ntk, Opt, Par>::Scheduler(Ntk *pNtk, Parameter const *pPar) :
pNtk(pNtk),
nVerbose(pPar->nSchedulerVerbose),
iSeed(pPar->iSeed),
nFlow(pPar->nSchedulerFlow),
nRestarts(pPar->nRestarts),
nJobs(pPar->nJobs),
fMultiThreading(pPar->nThreads > 1),
fPartitioning(pPar->nWindowSize > 0),
fPartitioning(pPar->nPartitionSize > 0),
fDeterministic(pPar->fDeterministic),
nParallelPartitions(pPar->nParallelPartitions),
fOptOnInsert(pPar->fOptOnInsert),
nTimeout(pPar->nTimeout),
nJobs(0),
nCreatedJobs(0),
nFinishedJobs(0),
par(pPar),
pOpt(NULL) {
@ -409,8 +415,8 @@ namespace rrr {
pOpt = new Opt(pPar, CostFunction);
}
template <typename Ntk, typename Opt>
Scheduler<Ntk, Opt>::~Scheduler() {
template <typename Ntk, typename Opt, typename Par>
Scheduler<Ntk, Opt, Par>::~Scheduler() {
#ifdef ABC_USE_PTHREADS
if(fMultiThreading) {
{
@ -430,45 +436,56 @@ namespace rrr {
/* }}} */
/* {{{ Run */
template <typename Ntk, typename Opt>
void Scheduler<Ntk, Opt>::Run() {
template <typename Ntk, typename Opt, typename Par>
void Scheduler<Ntk, Opt, Par>::Run() {
start = GetCurrentTime();
if(fPartitioning) {
fDeterministic = false; // it is deterministic anyways as we wait until all jobs finish each round
pNtk->Sweep();
par.UpdateNetwork(pNtk);
while(nJobs < nRestarts) {
Ntk *pSubNtk = par.Extract(iSeed + nJobs);
if(pSubNtk == NULL) {
if(nJobs == nFinishedJobs) {
std::cout << "failed to extract a window" << std::endl;
break;
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;
continue;
}
while(nFinishedJobs < nJobs) {
OnJobEnd([&](Job *pJob) {
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
par.Insert(pJob->pNtk);
});
}
} else {
CreateJob(pSubNtk, iSeed + nJobs);
std::cout << "job " << nJobs - 1 << " created (size = " << pSubNtk->GetNumInts() << ")" << std::endl;
}
if(nCreatedJobs == nFinishedJobs) {
std::cout << "failed to partition" << std::endl;
break;
}
while(nFinishedJobs < nCreatedJobs) {
OnJobEnd([&](Job *pJob) {
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
par.Insert(pJob->pNtk);
});
}
if(fOptOnInsert) {
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
par.UpdateNetwork(pNtk);
}
}
while(nFinishedJobs < nJobs) {
while(nFinishedJobs < nCreatedJobs) {
OnJobEnd([&](Job *pJob) {
std::cout << "job " << pJob->id << " finished (size = " << pJob->pNtk->GetNumInts() << ")" << std::endl;
par.Insert(pJob->pNtk);
});
}
} else if(nRestarts > 0) {
fDeterministic = false; // it is deterministic anyways
if(fOptOnInsert) {
CallAbc(pNtk, std::string("&put; ") + pCompress2rs + "; dc2; &get");
par.UpdateNetwork(pNtk);
}
} else if(nJobs > 1) {
double dCost = CostFunction(pNtk);
for(int i = 0; i < 1 + nRestarts; i++) {
for(int i = 0; i < nJobs; i++) {
Ntk *pCopy = new Ntk(*pNtk);
CreateJob(pCopy, iSeed + i);
}
for(int i = 0; i < 1 + nRestarts; i++) {
for(int i = 0; i < nJobs; i++) {
OnJobEnd([&](Job *pJob) {
double dNewCost = CostFunction(pJob->pNtk);
if(nVerbose) {

View File

@ -19,6 +19,7 @@ namespace rrr {
using itr = std::vector<word>::iterator;
using citr = std::vector<word>::const_iterator;
static constexpr word one = 0xffffffffffffffff;
static constexpr bool fKeepStimula = true;
// pointer to network
Ntk *pNtk;
@ -522,15 +523,54 @@ namespace rrr {
void Simulator<Ntk>::Load(int slot) {
assert(slot >= 0);
assert(slot < int_size(vBackups));
nWords = vBackups[slot].nWords;
target = vBackups[slot].target;
vValues = vBackups[slot].vValues;
care = vBackups[slot].care;
iPivot = vBackups[slot].iPivot;
vAssignedStimuli = vBackups[slot].vAssignedStimuli;
fUpdate = false;
sUpdates.clear();
tmp.resize(nWords);
if(!fKeepStimula) {
nWords = vBackups[slot].nWords;
target = vBackups[slot].target;
vValues = vBackups[slot].vValues;
care = vBackups[slot].care;
iPivot = vBackups[slot].iPivot;
vAssignedStimuli = vBackups[slot].vAssignedStimuli;
tmp.resize(nWords);
} else {
std::vector<int> vOffsets;
for(int i = 0; i < vBackups[slot].nWords; i++) {
bool fDifferent = false;
pNtk->ForEachPi([&](int id) {
if(vValues[id * vBackups[slot].nWords + i] != vValues[id * nWords + i]) {
fDifferent = true;
}
});
if(fDifferent) {
vOffsets.push_back(i);
}
}
if(nWords == vBackups[slot].nWords) {
if(vOffsets.empty()) {
target = vBackups[slot].target;
vValues = vBackups[slot].vValues;
care = vBackups[slot].care;
} else {
target = -1;
std::vector<std::vector<word>> vInputStimuli(pNtk->GetNumPis());
pNtk->ForEachPiIdx([&](int idx, int id) {
vInputStimuli[idx].resize(nWords);
Copy(nWords, vInputStimuli[idx].begin(), vValues.begin() + id * nWords, false);
});
vValues = vBackups[slot].vValues;
pNtk->ForEachPiIdx([&](int idx, int id) {
Copy(nWords, vValues.begin() + id * nWords, vInputStimuli[idx].begin(), false);
});
for(int i: vOffsets) {
SimulateOneWord(i);
}
}
} else {
// when nWords has changed
assert(0);
}
}
}
/* }}} */
@ -574,12 +614,13 @@ namespace rrr {
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());
target = -1;
iPivot = 0;
fUpdate = false;
sUpdates.clear();
if(!fSame) { // reset stimuli if network function changed
iPivot = 0;
vAssignedStimuli.clear();
vAssignedStimuli.resize(nWords * pNtk->GetNumPis());
GenerateRandomStimuli();
@ -771,6 +812,7 @@ namespace rrr {
if(nVerbose) {
std::cout << "recomputing careset of " << target << std::endl;
}
vValues2.resize(vValues.size());
pNtk->ForEachPi([&](int id) {
vValues2[id * nWords + iWord] = vValues[id * nWords + iWord];
});

View File

@ -2,6 +2,7 @@
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <set>
#include <string>
@ -30,13 +31,13 @@ namespace rrr {
/* {{{ Int size */
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
static inline int int_size(Container<Ts...> const &c) {
assert(c.size() <= (typename Container<Ts...>::size_type)std::numeric_limits<int>::max());
return c.size();
}
template <template <typename...> typename Container, typename ... Ts>
template <template <typename...> typename Container, typename... Ts>
static inline bool check_int_size(Container<Ts...> const &c) {
return c.size() <= (typename Container<Ts...>::size_type)std::numeric_limits<int>::max();
}
@ -44,11 +45,19 @@ namespace rrr {
static inline bool check_int_max(int i) {
return i == std::numeric_limits<int>::max();
}
template <typename Iterator>
static inline int int_distance(Iterator begin, Iterator it) {
typename std::iterator_traits<Iterator>::difference_type d = std::distance(begin, it);
assert(d <= (typename std::iterator_traits<Iterator>::difference_type)std::numeric_limits<int>::max());
assert(d >= (typename std::iterator_traits<Iterator>::difference_type)std::numeric_limits<int>::lowest());
return d;
}
/* }}} */
/* {{{ Print helpers */
/* {{{ Print containers */
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
std::string delim;
@ -83,6 +92,158 @@ namespace rrr {
std::cout << "]";
}
/* }}} */
/* {{{ Print next */
struct SW {
int width;
};
struct NS {}; // no space
template <typename T>
void PrintNext(std::ostream &os, T t);
template <typename T, typename... Args>
void PrintNext(std::ostream &os, T t, Args... args);
static inline void PrintNext(std::ostream &os, bool arg) {
os << arg;
}
template <typename... Args>
static inline void PrintNext(std::ostream &os, bool arg, Args... args) {
if(arg) {
os << "!";
} else {
os << " ";
}
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;
}
template <typename... Args>
static inline void PrintNext(std::ostream &os, double t, Args... args) {
os << std::fixed << std::setprecision(2) << std::setw(8) << t << " ";
PrintNext(os, args...);
}
template <typename T>
static inline void PrintNext(std::ostream &os, SW sw, T arg) {
os << std::setw(sw.width) << arg;
}
template <typename T, typename... Args>
static inline void PrintNext(std::ostream &os, SW sw, T arg, Args... args) {
os << std::setw(sw.width) << arg << " ";
PrintNext(os, args...);
}
template <typename T, typename... Args>
static inline void PrintNext(std::ostream &os, NS ns, T arg, Args... args) {
(void)ns;
os << arg;
PrintNext(os, args...);
}
template <typename T>
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg) {
std::string delim;
os << "[";
for(T const &e: arg) {
os << delim;
PrintNext(os, e);
delim = ", ";
}
os << "]";
}
template <typename T, typename... Args>
static inline void PrintNext(std::ostream& os, std::vector<T> const &arg, Args... args) {
std::string delim;
os << "[";
for(T const &e: arg) {
os << delim;
PrintNext(os, e);
delim = ", ";
}
os << "] ";
PrintNext(os, args...);
}
template <typename T>
static inline void PrintNext(std::ostream& os, std::set<T> const &arg) {
std::string delim;
os << "{";
for(T const &e: arg) {
os << delim;
PrintNext(os, e);
delim = ", ";
}
os << "}";
}
template <typename T, typename... Args>
static inline void PrintNext(std::ostream& os, std::set<T> const &arg, Args... args) {
std::string delim;
os << "{";
for(T const &e: arg) {
os << delim;
PrintNext(os, e);
delim = ", ";
}
os << "} ";
PrintNext(os, args...);
}
template <typename T>
void PrintNext(std::ostream &os, T t) {
os << t;
}
template <typename T, typename... Args>
void PrintNext(std::ostream &os, T t, Args... args) {
os << t << " ";
PrintNext(os, args...);
}
/* }}} */
/* {{{ Combination */
bool ForEachCombinationStopRec(std::vector<int> &v, int n, int k, std::function<bool(std::vector<int> const &)> const &func) {
if(k == 0) {
return func(v);
}
for(int i = v.back() + 1; i < n - k + 1; i++) {
v.push_back(i);
if(ForEachCombinationStopRec(v, n, k-1, func)) {
return true;
}
v.pop_back();
}
return false;
}
static inline void ForEachCombinationStop(int n, int k, std::function<bool(std::vector<int> const &)> const &func) {
std::vector<int> v;
v.reserve(k);
ForEachCombinationStopRec(v, n, k, func);
}
/* }}} */
/* {{{ VarValue functions */
@ -102,6 +263,7 @@ namespace rrr {
default:
assert(0);
}
return UNDEF;
}
static inline char GetVarValueChar(VarValue x) {
@ -119,73 +281,77 @@ namespace rrr {
default:
assert(0);
}
return 'X';
}
/* }}} */
/* {{{ Action functions */
static inline void PrintAction(Action action) {
static inline char const *GetActionTypeCstr(Action const &action) {
switch(action.type) {
case REMOVE_FANIN:
std::cout << "remove fanin";
break;
return "remove fanin";
case REMOVE_UNUSED:
std::cout << "remove unused";
break;
return "remove unused";
case REMOVE_BUFFER:
std::cout << "remove buffer";
break;
return "remove buffer";
case REMOVE_CONST:
std::cout << "remove const";
break;
return "remove const";
case ADD_FANIN:
std::cout << "add fanin";
break;
return "add fanin";
case TRIVIAL_COLLAPSE:
std::cout << "trivial collapse";
break;
return "trivial collapse";
case TRIVIAL_DECOMPOSE:
std::cout << "trivial decompose";
break;
return "trivial decompose";
case SORT_FANINS:
std::cout << "sort fanins";
break;
return "sort fanins";
case SAVE:
std::cout << "save";
break;
return "save";
case LOAD:
std::cout << "load";
break;
return "load";
case POP_BACK:
std::cout << "pop back";
break;
return "pop back";
case INSERT:
std::cout << "insert";
break;
return "insert";
default:
assert(0);
}
std::cout << ":";
return "";
}
static inline std::stringstream GetActionDescription(Action const &action) {
std::stringstream ss;
ss << GetActionTypeCstr(action);
std::string delim = ": ";
if(action.id != -1) {
std::cout << " node " << action.id;
ss << delim;
PrintNext(ss, "node", action.id);
delim = ", ";
}
if(action.fi != -1) {
std::cout << " fanin " << (action.c? "!": "") << action.fi;
ss << delim;
PrintNext(ss, "fanin", (bool)action.c, action.fi);
delim = ", ";
}
if(action.idx != -1) {
std::cout << " index " << action.idx;
ss << delim;
PrintNext(ss, "index", action.idx);
}
std::cout << std::endl;
ss << std::endl;
if(!action.vFanins.empty()) {
std::cout << "\t" << "fanins: " << action.vFanins << std::endl;
ss << "fanins: ";
PrintNext(ss, action.vFanins);
}
if(!action.vIndices.empty()) {
std::cout << "\t" << "indices: " << action.vIndices << std::endl;
ss << "indices: ";
PrintNext(ss, action.vIndices);
}
if(!action.vFanouts.empty()) {
std::cout << "\t" << "fanouts: " << action.vFanouts << std::endl;
ss << "fanouts: ";
PrintNext(ss, action.vFanouts);
}
return ss;
}
/* }}} */

View File

@ -317,9 +317,9 @@ int Cec_GiaProveTest( Gia_Man_t * p, int nProcs, int nTimeOut, int nTimeOut2, in
{
printf( "Problem \"%s\" is ", p->pSpec );
if ( RetValue == 0 )
printf( "SAT (solved by %d).", RetEngine );
printf( "SATISFIABLE (solved by %d).", RetEngine );
else if ( RetValue == 1 )
printf( "UNSAT (solved by %d).", RetEngine );
printf( "UNSATISFIABLE (solved by %d).", RetEngine );
else if ( RetValue == -1 )
printf( "UNDECIDED." );
else assert( 0 );

View File

@ -57,6 +57,7 @@ struct Bmc_EsPar_t_
int fDynConstr;
int fDumpCnf;
int fGlucose;
int fCard;
int fOrderNodes;
int fEnumSols;
int fFewerVars;
@ -69,6 +70,7 @@ struct Bmc_EsPar_t_
int fVerbose;
char * pTtStr;
char * pSymStr;
char * pGuide;
};
static inline void Bmc_EsParSetDefault( Bmc_EsPar_t * pPars )

View File

@ -763,7 +763,28 @@ int Exa_ManSolverSolve( Exa_Man_t * p )
}
int Exa_ManAddCnfStart( Exa_Man_t * p, int fOnlyAnd )
{
int pLits[MAJ_NOBJS], pLits2[3], i, j, k, n, m;
extern Vec_Int_t * Gia_ManKSatGenLevels( char * pGuide, int nIns, int nNodes );
Vec_Int_t * vRes = p->pPars->pGuide ? Gia_ManKSatGenLevels( p->pPars->pGuide, p->nVars, p->nNodes ) : NULL;
int pLits[MAJ_NOBJS], pLits2[3], i, j, k, n, m, Start, Stop;
if ( vRes ) {
n = p->nVars;
Vec_IntForEachEntryDoubleStart( vRes, Start, Stop, i, 2*p->nVars ) {
for ( j = 0; j < Start; j++ )
if ( p->VarMarks[n][0][j] ) {
pLits[0] = Abc_Var2Lit( p->VarMarks[n][0][j], 1 );
Exa_ManAddClause( p, pLits, 1 );
}
for ( k = 0; k < 2; k++ )
for ( j = Stop; j < n; j++ )
if ( p->VarMarks[n][k][j] ) {
pLits[0] = Abc_Var2Lit( p->VarMarks[n][k][j], 1 );
Exa_ManAddClause( p, pLits, 1 );
}
n++;
}
assert( n == p->nVars + p->nNodes );
Vec_IntFreeP( &vRes );
}
// input constraints
for ( i = p->nVars; i < p->nObjs; i++ )
{
@ -1941,9 +1962,26 @@ static inline int Exa4_ManAddClause4( Exa4_Man_t * p, int Lit0, int Lit1, int Li
int pLits[4] = { Lit0, Lit1, Lit2, Lit3 };
return Exa4_ManAddClause( p, pLits, 4 );
}
int Exa4_ManGenStart( Exa4_Man_t * p, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans )
int Exa4_ManGenStart( Exa4_Man_t * p, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fCard, char * pGuide )
{
int pLits[2*MAJ_NOBJS], i, j, k, n, m, nLits;
extern Vec_Int_t * Gia_ManKSatGenLevels( char * pGuide, int nIns, int nNodes );
Vec_Int_t * vRes = pGuide ? Gia_ManKSatGenLevels( pGuide, p->nDivs, p->nNodes ) : NULL;
int pLits[2*MAJ_NOBJS], i, j, k, n, m, nLits, Start, Stop;
if ( vRes ) {
n = p->nDivs;
Vec_IntForEachEntryDoubleStart( vRes, Start, Stop, i, 2*p->nDivs ) {
for ( j = 0; j < Start; j++ )
if ( p->VarMarks[n][0][j] )
Exa4_ManAddClause4( p, Abc_Var2Lit( p->VarMarks[n][0][j], 1 ), 0, 0, 0 );
for ( k = 0; k < 2; k++ )
for ( j = Stop; j < n; j++ )
if ( p->VarMarks[n][k][j] )
Exa4_ManAddClause4( p, Abc_Var2Lit( p->VarMarks[n][k][j], 1 ), 0, 0, 0 );
n++;
}
assert( n == p->nDivs + p->nNodes );
Vec_IntFreeP( &vRes );
}
for ( i = p->nDivs; i < p->nDivs + p->nNodes; i++ )
{
int iVarStart = 1 + 5*(i - p->nDivs);//
@ -1955,9 +1993,17 @@ int Exa4_ManGenStart( Exa4_Man_t * p, int fOnlyAnd, int fFancy, int fOrderNodes,
pLits[nLits++] = Abc_Var2Lit( p->VarMarks[i][k][j], 0 );
assert( nLits > 0 );
Exa4_ManAddClause( p, pLits, nLits );
for ( n = 0; n < nLits; n++ )
for ( m = n+1; m < nLits; m++ )
Exa4_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 );
if ( !fCard ) {
for ( n = 0; n < nLits; n++ )
for ( m = n+1; m < nLits; m++ )
Exa4_ManAddClause4( p, Abc_LitNot(pLits[n]), Abc_LitNot(pLits[m]), 0, 0 );
}
else {
fprintf( p->pFile, "k %d ", nLits-1 );
for ( n = 0; n < nLits; n++ )
pLits[n] = Abc_LitNot(pLits[n]);
Exa4_ManAddClause( p, pLits, nLits );
}
if ( k == 1 )
break;
for ( j = 0; j < p->nObjs; j++ ) if ( p->VarMarks[i][0][j] )
@ -2096,17 +2142,17 @@ void Exa4_ManGenMint( Exa4_Man_t * p, int iMint, int fOnlyAnd, int fFancy )
Exa4_ManAddClause4( p, Abc_Var2Lit(p->VarMarks[i][0][j], 1), Abc_LitNotCond(VarVals[j], n), Abc_LitNotCond(VarVals[i], !n), 0);
}
}
void Exa4_ManGenCnf( Exa4_Man_t * p, char * pFileName, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans )
void Exa4_ManGenCnf( Exa4_Man_t * p, char * pFileName, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fCard, char * pGuide )
{
int m;
assert( p->pFile == NULL );
p->pFile = fopen( pFileName, "wb" );
fputs( "p cnf \n", p->pFile );
Exa4_ManGenStart( p, fOnlyAnd, fFancy, fOrderNodes, fUniqFans );
Exa4_ManGenStart( p, fOnlyAnd, fFancy, fOrderNodes, fUniqFans, fCard, pGuide );
for ( m = 1; m < Vec_WrdSize(p->vSimsIn); m++ )
Exa4_ManGenMint( p, m, fOnlyAnd, fFancy );
rewind( p->pFile );
fprintf( p->pFile, "p cnf %d %d", p->nCnfVars, p->nCnfClauses );
fprintf( p->pFile, "p %cnf %d %d", fCard ? 'k' : 'c', p->nCnfVars, p->nCnfClauses );
fclose( p->pFile );
}
@ -2130,6 +2176,8 @@ static inline int Exa4_ManFindFanin( Exa4_Man_t * p, Vec_Int_t * vValues, int i,
iVar = j;
Count++;
}
if ( Count != 1 )
printf( "Fanin count is %d instead of %d.\n", Count, 1 );
assert( Count == 1 );
return iVar;
}
@ -2268,27 +2316,34 @@ Mini_Aig_t * Exa4_ManMiniAig( Exa4_Man_t * p, Vec_Int_t * vValues, int fFancy )
SeeAlso []
***********************************************************************/
Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose )
Mini_Aig_t * Exa4_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIns, int nDivs, int nOuts, int nNodes, int TimeOut, int fOnlyAnd, int fFancy, int fOrderNodes, int fUniqFans, int fVerbose, int fCard, char * pGuide )
{
extern Vec_Int_t * Gia_RunKadical( char * pFileNameIn, char * pFileNameOut, int Seed, int nBTLimit, int TimeOut, int fVerbose, int * pStatus );
Mini_Aig_t * pMini = NULL;
abctime clkTotal = Abc_Clock();
Vec_Int_t * vValues = NULL;
char * pFileNameIn = "_temp_.cnf";
char * pFileNameOut = "_temp_out.cnf";
srand(time(NULL));
int Status = 0, Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFF;
char pFileNameIn[32]; sprintf( pFileNameIn, "_%05x_.cnf", Rand );
char pFileNameOut[32]; sprintf( pFileNameOut, "_%05x_.out", Rand );
Exa4_Man_t * p = Exa4_ManAlloc( vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, fVerbose );
Exa_ManIsNormalized( vSimsIn, vSimsOut );
Exa4_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans );
Exa4_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans, fCard, pGuide );
if ( fVerbose )
printf( "Timeout = %d. OnlyAnd = %d. Fancy = %d. OrderNodes = %d. UniqueFans = %d. Verbose = %d.\n", TimeOut, fOnlyAnd, fFancy, fOrderNodes, fUniqFans, fVerbose );
if ( fVerbose )
printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", p->nCnfVars, p->nCnfClauses, pFileNameIn );
vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, TimeOut, fVerbose );
if ( fCard )
vValues = Gia_RunKadical( pFileNameIn, pFileNameOut, 0, 0, TimeOut, fVerbose, &Status );
else
vValues = Exa4_ManSolve( pFileNameIn, pFileNameOut, TimeOut, fVerbose );
if ( vValues ) pMini = Exa4_ManMiniAig( p, vValues, fFancy );
//if ( vValues ) Exa4_ManPrintSolution( p, vValues, fFancy );
if ( vValues ) Exa_ManMiniPrint( pMini, p->nIns );
if ( vValues ) Exa_ManMiniVerify( pMini, vSimsIn, vSimsOut );
Vec_IntFreeP( &vValues );
Exa4_ManFree( p );
unlink( pFileNameIn );
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
return pMini;
}
@ -2310,7 +2365,7 @@ void Exa_ManExactSynthesis4_( Bmc_EsPar_t * pPars )
if ( (m >> i) & 1 )
Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, m), 1+i );
}
pMini = Exa4_ManGenTest( vSimsIn, vSimsOut, 3, 4, 2, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose );
pMini = Exa4_ManGenTest( vSimsIn, vSimsOut, 3, 4, 2, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose, 0, pPars->pGuide );
if ( pMini ) Mini_AigStop( pMini );
Vec_WrdFree( vSimsIn );
Vec_WrdFree( vSimsOut );
@ -2332,7 +2387,7 @@ void Exa_ManExactSynthesis4( Bmc_EsPar_t * pPars )
Abc_TtSetBit( Vec_WrdEntryP(vSimsIn, m), 1+i );
}
assert( Vec_WrdSize(vSimsIn) == (1 << pPars->nVars) );
pMini = Exa4_ManGenTest( vSimsIn, vSimsOut, pPars->nVars, 1+pPars->nVars, 1, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose );
pMini = Exa4_ManGenTest( vSimsIn, vSimsOut, pPars->nVars, 1+pPars->nVars, 1, pPars->nNodes, pPars->RuntimeLim, pPars->fOnlyAnd, pPars->fFewerVars, pPars->fOrderNodes, pPars->fUniqFans, pPars->fVerbose, pPars->fCard, pPars->pGuide );
if ( pMini ) Mini_AigStop( pMini );
if ( fCompl ) printf( "The resulting circuit, if computed, will be complemented.\n" );
Vec_WrdFree( vSimsIn );
@ -2797,8 +2852,10 @@ Mini_Aig_t * Exa5_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIn
abctime clkTotal = Abc_Clock();
Mini_Aig_t * pMini = NULL;
Vec_Int_t * vValues = NULL;
char * pFileNameIn = "_temp_.cnf";
char * pFileNameOut = "_temp_out.cnf";
srand(time(NULL));
int Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFF;
char pFileNameIn[32]; sprintf( pFileNameIn, "_%05x_.cnf", Rand );
char pFileNameOut[32]; sprintf( pFileNameOut, "_%05x_.out", Rand );
Exa5_Man_t * p = Exa5_ManAlloc( vSimsIn, vSimsOut, nIns, nDivs, nOuts, nNodes, fVerbose );
Exa_ManIsNormalized( vSimsIn, vSimsOut );
Exa5_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans );
@ -2813,6 +2870,7 @@ Mini_Aig_t * Exa5_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIn
if ( vValues ) Exa_ManMiniVerify( pMini, vSimsIn, vSimsOut );
Vec_IntFreeP( &vValues );
Exa5_ManFree( p );
unlink( pFileNameIn );
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
return pMini;
}
@ -3717,8 +3775,9 @@ Mini_Aig_t * Exa6_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIn
Mini_Aig_t * pMini = NULL;
abctime clkTotal = Abc_Clock();
Vec_Int_t * vValues = NULL;
char * pFileNameIn = "_temp_.cnf";
char * pFileNameOut = "_temp_out.cnf";
int Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFF;
char pFileNameIn[32]; sprintf( pFileNameIn, "_%05x_.cnf", Rand );
char pFileNameOut[32]; sprintf( pFileNameOut, "_%05x_.out", Rand );
Exa6_Man_t * p = Exa6_ManAlloc( vSimsIn, vSimsOut, nIns, 1+nIns+nDivs, nOuts, nNodes, fVerbose );
Exa_ManIsNormalized( vSimsIn, vSimsOut );
Exa6_ManGenCnf( p, pFileNameIn, fOnlyAnd, fFancy, fOrderNodes, fUniqFans );
@ -3733,6 +3792,7 @@ Mini_Aig_t * Exa6_ManGenTest( Vec_Wrd_t * vSimsIn, Vec_Wrd_t * vSimsOut, int nIn
if ( vValues && nIns <= 6 ) Exa_ManMiniVerify( pMini, vSimsIn, vSimsOut );
Vec_IntFreeP( &vValues );
Exa6_ManFree( p );
unlink( pFileNameIn );
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
return pMini;
}
@ -4016,8 +4076,9 @@ void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize )
int nV = pPars->nVars + pPars->nNodes;
word pTruth[16]; Abc_TtReadHex( pTruth, pPars->pTtStr );
Vec_Int_t * vValues = NULL;
char * pFileNameIn = "_temp_.cnf";
char * pFileNameOut = "_temp_out.cnf";
int Rand = ((((unsigned)rand()) << 12) ^ ((unsigned)rand())) & 0xFFFFF;
char pFileNameIn[32]; sprintf( pFileNameIn, "_%05x_.cnf", Rand );
char pFileNameOut[32]; sprintf( pFileNameOut, "_%05x_.out", Rand );
int nClas = Exa7_ManGenCnf( pFileNameIn, pTruth, pPars->nVars, pPars->nNodes, GateSize );
if ( pPars->fVerbose )
printf( "CNF with %d variables and %d clauses was dumped into file \"%s\".\n", nMints * nV * nV, nClas, pFileNameIn );
@ -4036,6 +4097,7 @@ void Exa_ManExactSynthesis7( Bmc_EsPar_t * pPars, int GateSize )
if ( vValues )
Exa_ManDumpVerilog( vValues, pPars->nVars, pPars->nNodes, GateSize, pTruth );
Vec_IntFreeP( &vValues );
unlink( pFileNameIn );
Abc_PrintTime( 1, "Total runtime", Abc_Clock() - clkTotal );
}