Commit 6e496de7 by Alan Mishchenko

Version abc50817

parent 9b3fa55b
......@@ -181,6 +181,10 @@ SOURCE=.\src\base\abc\abcPrint.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcReconv.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcRefs.c
# End Source File
# Begin Source File
......@@ -193,6 +197,10 @@ SOURCE=.\src\base\abc\abcRes.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcResRef.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcSat.c
# End Source File
# Begin Source File
......@@ -1088,6 +1096,38 @@ SOURCE=.\src\opt\fxu\fxuSingle.c
SOURCE=.\src\opt\fxu\fxuUpdate.c
# End Source File
# End Group
# Begin Group "rwr"
# PROP Default_Filter ""
# Begin Source File
SOURCE=.\src\opt\rwr\rwr.h
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrCut.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrEva.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrExp.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrLib.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrMan.c
# End Source File
# Begin Source File
SOURCE=.\src\opt\rwr\rwrUtil.c
# End Source File
# End Group
# End Group
# Begin Group "map"
......@@ -1427,6 +1467,10 @@ SOURCE=.\src\misc\vec\vecPtr.h
SOURCE=.\src\misc\vec\vecStr.h
# End Source File
# Begin Source File
SOURCE=.\src\misc\vec\vecVec.h
# End Source File
# End Group
# End Group
# End Group
......
No preview for this file type
......@@ -6,13 +6,14 @@
--------------------Configuration: abc - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBEE.tmp" with contents
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP12A1.tmp" with contents
[
/nologo /MLd /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\cmd" /I "src\base\io" /I "src\base\main" /I "src\bdd\cudd" /I "src\bdd\epd" /I "src\bdd\mtr" /I "src\bdd\parse" /I "src\bdd\dsd" /I "src\bdd\reo" /I "src\sop\mvc" /I "src\sop\ft" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\fxa" /I "src\opt\fxu" /I "src\map\fpga" /I "src\map\mapper" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\util" /I "src\misc\vec" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "__STDC__" /D "HAVE_ASSERT_H" /FR"Debug/" /Fp"Debug/abc.pch" /YX /Fo"Debug/" /Fd"Debug/" /FD /GZ /c
"C:\_projects\abc\src\map\mapper\mapperCut.c"
"C:\_projects\abc\src\base\abc\abcStrash.c"
"C:\_projects\abc\src\opt\rwr\rwrUtil.c"
]
Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBEE.tmp"
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBEF.tmp" with contents
Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP12A1.tmp"
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP12A2.tmp" with contents
[
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /incremental:yes /pdb:"Debug/abc.pdb" /debug /machine:I386 /out:"_TEST/abc.exe" /pdbtype:sept
.\Debug\abc.obj
......@@ -269,14 +270,22 @@ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32
.\Debug\safe_mem.obj
.\Debug\strsav.obj
.\Debug\texpand.obj
.\Debug\abcReconv.obj
.\Debug\abcResRef.obj
.\Debug\rwrMan.obj
.\Debug\rwrCut.obj
.\Debug\rwrExp.obj
.\Debug\rwrLib.obj
.\Debug\rwrEva.obj
.\Debug\rwrUtil.obj
]
Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBEF.tmp"
Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP12A2.tmp"
<h3>Output Window</h3>
Compiling...
mapperCut.c
C:\_projects\abc\src\map\mapper\mapperCut.c(927) : warning C4101: 'Place' : unreferenced local variable
abcStrash.c
rwrUtil.c
Linking...
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBF0.tmp" with contents
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP12A3.tmp" with contents
[
/nologo /o"Debug/abc.bsc"
.\Debug\abc.sbr
......@@ -532,15 +541,23 @@ Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBF0.tmp" with conte
.\Debug\pathsearch.sbr
.\Debug\safe_mem.sbr
.\Debug\strsav.sbr
.\Debug\texpand.sbr]
Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSPBF0.tmp"
.\Debug\texpand.sbr
.\Debug\abcReconv.sbr
.\Debug\abcResRef.sbr
.\Debug\rwrMan.sbr
.\Debug\rwrCut.sbr
.\Debug\rwrExp.sbr
.\Debug\rwrLib.sbr
.\Debug\rwrEva.sbr
.\Debug\rwrUtil.sbr]
Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP12A3.tmp"
Creating browse info file...
<h3>Output Window</h3>
<h3>Results</h3>
abc.exe - 0 error(s), 1 warning(s)
abc.exe - 0 error(s), 0 warning(s)
</pre>
</body>
</html>
......@@ -18,6 +18,8 @@ alias rp read_pla
alias rv read_verilog
alias rsup read_super mcnc5_old.super
alias rlib read_library
alias rw rewrite
alias rf refactor
alias sa set autoexec ps
alias so source -x
alias st strash
......
......@@ -45,7 +45,9 @@ static int Abc_CommandRenode ( Abc_Frame_t * pAbc, int argc, char ** argv
static int Abc_CommandCleanup ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFastExtract ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandDisjoint ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRes ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRewrite ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRefactor ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandLogic ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandMiter ( Abc_Frame_t * pAbc, int argc, char ** argv );
......@@ -55,6 +57,7 @@ static int Abc_CommandBdd ( Abc_Frame_t * pAbc, int argc, char ** argv
static int Abc_CommandSat ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandExtSeqDcs ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSplit ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandShortNames ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFraig ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandFraigTrust ( Abc_Frame_t * pAbc, int argc, char ** argv );
......@@ -110,7 +113,9 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Synthesis", "cleanup", Abc_CommandCleanup, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "fx", Abc_CommandFastExtract, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "dsd", Abc_CommandDisjoint, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "res", Abc_CommandRes, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "rewrite", Abc_CommandRewrite, 1 );
Cmd_CommandAdd( pAbc, "Synthesis", "refactor", Abc_CommandRefactor, 1 );
Cmd_CommandAdd( pAbc, "Various", "logic", Abc_CommandLogic, 1 );
Cmd_CommandAdd( pAbc, "Various", "miter", Abc_CommandMiter, 1 );
......@@ -120,6 +125,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Various", "sat", Abc_CommandSat, 0 );
Cmd_CommandAdd( pAbc, "Various", "ext_seq_dcs", Abc_CommandExtSeqDcs, 0 );
Cmd_CommandAdd( pAbc, "Various", "split", Abc_CommandSplit, 1 );
Cmd_CommandAdd( pAbc, "Various", "short_names", Abc_CommandShortNames, 0 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig", Abc_CommandFraig, 1 );
Cmd_CommandAdd( pAbc, "Fraiging", "fraig_trust", Abc_CommandFraigTrust, 1 );
......@@ -142,6 +148,7 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 );
Ft_FactorStartMan();
// Rwt_ManExploreStart();
}
/**Function*************************************************************
......@@ -159,6 +166,7 @@ void Abc_End()
{
Ft_FactorStopMan();
Abc_NtkFraigStoreClean();
// Rwt_ManExplorePrint();
}
/**Function*************************************************************
......@@ -517,7 +525,7 @@ int Abc_CommandPrintLevel( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
if ( !Abc_NtkIsAig(pNtk) )
if ( !fProfile && !Abc_NtkIsAig(pNtk) )
{
fprintf( pErr, "This command works only for AIGs.\n" );
return 1;
......@@ -1309,23 +1317,109 @@ usage:
SeeAlso []
***********************************************************************/
int Abc_CommandRes( Abc_Frame_t * pAbc, int argc, char ** argv )
int Abc_CommandRewrite( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
Abc_ManRes_t * p;
extern int Abc_NtkAigResynthesize( Abc_Ntk_t * pNtk, Abc_ManRes_t * p );
bool fVerbose;
{
Abc_ManRwr_t * p;
int fFlag = 0;
if ( fFlag )
p = Abc_NtkManRwrStart( NULL );
else
p = Abc_NtkManRwrStart( "data.aaa" );
Abc_NtkManRwrStop( p );
return 0;
}
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
p = Abc_NtkManResStart();
p->fVerbose = 0;
p->nNodeSizeMax = 10;
p->nConeSizeMax = 10;
fVerbose = 0;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
{
switch ( c )
{
case 'v':
fVerbose ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
if ( !Abc_NtkIsAig(pNtk) )
{
fprintf( pErr, "This command can only be applied to an AIG.\n" );
return 1;
}
if ( Abc_NtkCountChoiceNodes(pNtk) )
{
fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
return 1;
}
// modify the current network
if ( !Abc_NtkRewrite( pNtk ) )
{
fprintf( pErr, "Rewriting has failed.\n" );
return 1;
}
return 0;
usage:
fprintf( pErr, "usage: rewrite [-vh]\n" );
fprintf( pErr, "\t performs technology-independent rewriting of the AIG\n" );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
Abc_ManRef_t * p;
bool fVerbose;
int nNodeSizeMax;
int nConeSizeMax;
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
p = Abc_NtkManRefStart();
fVerbose = 0;
nNodeSizeMax = 10;
nConeSizeMax = 10;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "ncvh" ) ) != EOF )
{
......@@ -1337,9 +1431,9 @@ int Abc_CommandRes( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Command line switch \"-n\" should be followed by an integer.\n" );
goto usage;
}
p->nNodeSizeMax = atoi(argv[util_optind]);
nNodeSizeMax = atoi(argv[util_optind]);
util_optind++;
if ( p->nNodeSizeMax < 0 )
if ( nNodeSizeMax < 0 )
goto usage;
break;
case 'c':
......@@ -1348,13 +1442,13 @@ int Abc_CommandRes( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Command line switch \"-c\" should be followed by an integer.\n" );
goto usage;
}
p->nConeSizeMax = atoi(argv[util_optind]);
nConeSizeMax = atoi(argv[util_optind]);
util_optind++;
if ( p->nConeSizeMax < 0 )
if ( nConeSizeMax < 0 )
goto usage;
break;
case 'v':
p->fVerbose ^= 1;
fVerbose ^= 1;
break;
case 'h':
goto usage;
......@@ -1366,32 +1460,36 @@ int Abc_CommandRes( Abc_Frame_t * pAbc, int argc, char ** argv )
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
Abc_NtkManResStop( p );
Abc_NtkManRefStop( p );
return 1;
}
if ( !Abc_NtkIsAig(pNtk) )
{
fprintf( pErr, "This command can only be applied to an AIG.\n" );
Abc_NtkManResStop( p );
Abc_NtkManRefStop( p );
return 1;
}
if ( Abc_NtkCountChoiceNodes(pNtk) )
{
fprintf( pErr, "AIG resynthesis cannot be applied to AIGs with choice nodes.\n" );
Abc_NtkManResStop( p );
Abc_NtkManRefStop( p );
return 1;
}
// modify the current network
Abc_NtkAigResynthesize( pNtk, p );
if ( !Abc_NtkRefactor( pNtk, p ) )
{
fprintf( pErr, "Refactoring has failed.\n" );
return 1;
}
return 0;
usage:
fprintf( pErr, "usage: res [-n num] [-c num] [-vh]\n" );
fprintf( pErr, "\t performs technology-independent resynthesis of the AIG\n" );
fprintf( pErr, "\t-n num : the max support of the collapsed node [default = %d]\n", p->nNodeSizeMax );
fprintf( pErr, "\t-c num : the max support of the containing cone [default = %d]\n", p->nConeSizeMax );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", p->fVerbose? "yes": "no" );
fprintf( pErr, "usage: refactor [-n num] [-c num] [-vh]\n" );
fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" );
fprintf( pErr, "\t-n num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax );
fprintf( pErr, "\t-c num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
......@@ -2001,6 +2099,56 @@ usage:
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandShortNames( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "h" ) ) != EOF )
{
switch ( c )
{
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
Abc_NtkShortNames( pNtk );
return 0;
usage:
fprintf( pErr, "usage: short_names [-h]\n" );
fprintf( pErr, "\t replaces PI/PO/latch names by short char strings\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
/**Function*************************************************************
......
......@@ -88,7 +88,9 @@ typedef struct Abc_Obj_t_ Abc_Obj_t;
typedef struct Abc_Ntk_t_ Abc_Ntk_t;
typedef struct Abc_Aig_t_ Abc_Aig_t;
typedef struct Abc_ManTime_t_ Abc_ManTime_t;
typedef struct Abc_ManRes_t_ Abc_ManRes_t;
typedef struct Abc_ManCut_t_ Abc_ManCut_t;
typedef struct Abc_ManRef_t_ Abc_ManRef_t;
typedef struct Abc_ManRwr_t_ Abc_ManRwr_t;
typedef struct Abc_Time_t_ Abc_Time_t;
struct Abc_Time_t_
......@@ -102,8 +104,8 @@ struct Abc_Obj_t_ // 12 words
{
// high-level information
unsigned Type : 4; // the object type
unsigned Unused : 2; // currently unused
unsigned Id : 26; // the ID of the object
unsigned fExor : 1; // marks AIG node that is a root of EXOR
unsigned Id : 27; // the ID of the object
// internal information
unsigned fMarkA : 1; // the multipurpose mark
unsigned fMarkB : 1; // the multipurpose mark
......@@ -163,30 +165,6 @@ struct Abc_Ntk_t_
Extra_MmStep_t * pMmStep; // memory manager for arrays
};
struct Abc_ManRes_t_
{
// user specified parameters
int nNodeSizeMax; // the limit on the size of the supernode
int nConeSizeMax; // the limit on the size of the containing cone
int fVerbose; // the verbosity flag
// internal parameters
DdManager * dd; // the BDD manager
DdNode * bCubeX; // the cube of PI variables
Abc_Obj_t * pNode; // the node currently considered
Vec_Ptr_t * vFaninsNode; // fanins of the supernode
Vec_Ptr_t * vInsideNode; // inside of the supernode
Vec_Ptr_t * vFaninsCone; // fanins of the containing cone
Vec_Ptr_t * vInsideCone; // inside of the containing cone
Vec_Ptr_t * vVisited; // the visited nodes
Vec_Str_t * vCube; // temporary cube for generating covers
Vec_Int_t * vForm; // the factored form (temporary)
// runtime statistics
int time1;
int time2;
int time3;
int time4;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -287,6 +265,7 @@ static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return pObj-
static inline Abc_Obj_t * Abc_ObjFanin0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[0].iFan ]; }
static inline Abc_Obj_t * Abc_ObjFanin1( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[1].iFan ]; }
static inline Abc_Obj_t * Abc_ObjFanin0Ntk( Abc_Obj_t * pObj ) { return Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanin0(pObj) : pObj; }
static inline Abc_Obj_t * Abc_ObjFanout0Ntk( Abc_Obj_t * pObj ) { return Abc_NtkIsNetlist(pObj->pNtk)? Abc_ObjFanout0(pObj) : pObj; }
static inline bool Abc_ObjFaninC( Abc_Obj_t * pObj, int i ){ return pObj->vFanins.pArray[i].fCompl; }
static inline bool Abc_ObjFaninC0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].fCompl; }
static inline bool Abc_ObjFaninC1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].fCompl; }
......@@ -363,24 +342,18 @@ static inline bool Abc_LatchIsInitDc( Abc_Obj_t * pLatch ) { assert(Abc
if ( pObj = Abc_NtkLatch(pNtk, i) )
// inputs and outputs
#define Abc_NtkForEachPi( pNtk, pPi, i ) \
for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) \
if ( pPi = Abc_NtkPi(pNtk, i) )
for ( i = 0; (i < Abc_NtkPiNum(pNtk)) && (((pPi) = Abc_NtkPi(pNtk, i)), 1); i++ )
#define Abc_NtkForEachPo( pNtk, pPo, i ) \
for ( i = 0; i < Abc_NtkPoNum(pNtk); i++ ) \
if ( pPo = Abc_NtkPo(pNtk, i) )
#define Abc_NtkForEachCi( pNtk, pPi, i ) \
for ( i = 0; i < Abc_NtkCiNum(pNtk); i++ ) \
if ( pPi = Abc_NtkCi(pNtk, i) )
#define Abc_NtkForEachCo( pNtk, pPo, i ) \
for ( i = 0; i < Abc_NtkCoNum(pNtk); i++ ) \
if ( pPo = Abc_NtkCo(pNtk, i) )
for ( i = 0; (i < Abc_NtkPoNum(pNtk)) && (((pPo) = Abc_NtkPo(pNtk, i)), 1); i++ )
#define Abc_NtkForEachCi( pNtk, pCi, i ) \
for ( i = 0; (i < Abc_NtkCiNum(pNtk)) && (((pCi) = Abc_NtkCi(pNtk, i)), 1); i++ )
#define Abc_NtkForEachCo( pNtk, pCo, i ) \
for ( i = 0; (i < Abc_NtkCoNum(pNtk)) && (((pCo) = Abc_NtkCo(pNtk, i)), 1); i++ )
// fanin and fanouts
#define Abc_ObjForEachFanin( pObj, pFanin, i ) \
for ( i = 0; i < Abc_ObjFaninNum(pObj); i++ ) \
if ( pFanin = Abc_ObjFanin(pObj, i) )
for ( i = 0; (i < Abc_ObjFaninNum(pObj)) && (((pFanin) = Abc_ObjFanin(pObj, i)), 1); i++ )
#define Abc_ObjForEachFanout( pObj, pFanout, i ) \
for ( i = 0; i < Abc_ObjFanoutNum(pObj); i++ ) \
if ( pFanout = Abc_ObjFanout(pObj, i) )
for ( i = 0; (i < Abc_ObjFanoutNum(pObj)) && (((pFanout) = Abc_ObjFanout(pObj, i)), 1); i++ )
// cubes and literals
#define Abc_SopForEachCube( pSop, nFanins, pCube ) \
for ( pCube = (pSop); *pCube; pCube += (nFanins) + 3 )
......@@ -398,6 +371,7 @@ extern Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, Abc_Aig_t * pManNew );
extern void Abc_AigFree( Abc_Aig_t * pMan );
extern int Abc_AigCleanup( Abc_Aig_t * pMan );
extern bool Abc_AigCheck( Abc_Aig_t * pMan );
extern int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk );
extern Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan );
extern Abc_Obj_t * Abc_AigReset( Abc_Aig_t * pMan );
extern Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
......@@ -405,6 +379,7 @@ extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t
extern Abc_Obj_t * Abc_AigXor( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
extern Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs );
extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew );
extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld );
extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode );
extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode );
/*=== abcAttach.c ==========================================================*/
......@@ -451,8 +426,9 @@ extern Abc_Obj_t * Abc_NodeClone( Abc_Obj_t * pNode );
/*=== abcDfs.c ==========================================================*/
extern Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll );
extern Vec_Ptr_t * Abc_NtkDfsNodes( Abc_Ntk_t * pNtk, Abc_Obj_t ** ppNodes, int nNodes );
extern Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk );
extern Vec_Ptr_t * Abc_AigDfs( Abc_Ntk_t * pNtk, int fCollectAll );
extern Vec_Ptr_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi );
extern Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi );
extern int Abc_NtkGetLevelNum( Abc_Ntk_t * pNtk );
extern bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk );
/*=== abcFanio.c ==========================================================*/
......@@ -517,15 +493,34 @@ extern void Abc_NtkPrintFactor( FILE * pFile, Abc_Ntk_t * pNtk );
extern void Abc_NodePrintFactor( FILE * pFile, Abc_Obj_t * pNode );
extern void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile );
extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode );
/*=== abcReconv.c ==========================================================*/
extern Abc_ManCut_t * Abc_NtkManCutStart();
extern void Abc_NtkManCutStop( Abc_ManCut_t * p );
extern void Abc_NodeFindCut( Abc_ManCut_t * p );
extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited );
extern void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax, Vec_Vec_t * vLevels, Vec_Ptr_t * vResult );
/*=== abcRefs.c ==========================================================*/
extern int Abc_NodeMffcSize( Abc_Obj_t * pNode );
extern int Abc_NodeMffcRemove( Abc_Obj_t * pNode );
extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode );
/*=== abcRenode.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple );
extern DdNode * Abc_NtkRenodeDeriveBdd( DdManager * dd, Abc_Obj_t * pNodeOld, Vec_Ptr_t * vFaninsOld );
/*=== abcRes.c ==========================================================*/
extern Abc_ManRes_t * Abc_NtkManResStart();
extern void Abc_NtkManResStop( Abc_ManRes_t * p );
extern int Abc_NtkRewrite( Abc_Ntk_t * pNtk );
extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, Abc_ManRef_t * p );
/*=== abcResRef.c ==========================================================*/
extern Abc_ManRef_t * Abc_NtkManRefStart();
extern void Abc_NtkManRefStop( Abc_ManRef_t * p );
extern bool Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode );
extern Vec_Int_t * Abc_NtkManRefResult( Abc_ManRef_t * p );
/*=== abcResRwr.c ==========================================================*/
extern Abc_ManRwr_t * Abc_NtkManRwrStart( char * pFileName );
extern void Abc_NtkManRwrStop( Abc_ManRwr_t * p );
extern void Abc_NtkManRwrStartCuts( Abc_ManRwr_t * p, Abc_Ntk_t * pNtk );
extern void Abc_NodeRwrComputeCuts( Abc_ManRwr_t * p, Abc_Obj_t * pNode );
extern int Abc_NodeRwrRewrite( Abc_ManRwr_t * p, Abc_Obj_t * pNode );
extern Vec_Int_t * Abc_NtkManRwrDecs( Abc_ManRwr_t * p );
extern Vec_Ptr_t * Abc_NtkManRwrFanins( Abc_ManRwr_t * p );
/*=== abcSat.c ==========================================================*/
extern bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose );
extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk );
......@@ -565,6 +560,7 @@ extern void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_In
extern void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp );
/*=== abcStrash.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes );
extern Abc_Obj_t * Abc_NodeStrashDec( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * vForm );
extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate );
/*=== abcSweep.c ==========================================================*/
......@@ -607,6 +603,8 @@ extern Abc_Obj_t * Abc_NodeHasUniqueCoFanout( Abc_Obj_t * pNode );
extern bool Abc_NtkLogicHasSimpleCos( Abc_Ntk_t * pNtk );
extern int Abc_NtkLogicMakeSimpleCos( Abc_Ntk_t * pNtk, bool fDuplicate );
extern void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode );
extern int Abc_NtkCountExors( Abc_Ntk_t * pNtk );
extern bool Abc_NodeIsExorType( Abc_Obj_t * pNode );
extern bool Abc_NodeIsMuxType( Abc_Obj_t * pNode );
extern Abc_Obj_t * Abc_NodeRecognizeMux( Abc_Obj_t * pNode, Abc_Obj_t ** ppNodeT, Abc_Obj_t ** ppNodeE );
extern int Abc_NtkCountChoiceNodes( Abc_Ntk_t * pNtk );
......@@ -619,6 +617,7 @@ extern Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode );
extern void Abc_NodeFreeFaninNames( Vec_Ptr_t * vNames );
extern char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos );
extern void Abc_NtkAlphaOrderSignals( Abc_Ntk_t * pNtk, int fComb );
extern void Abc_NtkShortNames( Abc_Ntk_t * pNtk );
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
......@@ -23,18 +23,20 @@
/*
AIG is an And-Inv Graph with structural hashing.
It is always structurally hashed. It means that at any time:
- for each AND gate, there are no other AND gates with the same children
- the constants are propagated
- there is no single-input nodes (inverters/buffers)
- for each AND gate, there are no other AND gates with the same children.
- there are no dangling nodes (the nodes without fanout)
- the level of each AND gate reflects the levels of this fanins
- the EXOR-status of each node is up-to-date
The operations that are performed on AIG:
- building new nodes (Abc_AigAnd)
- elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc)
- propagation of constants (Abc_AigReplace)
- variable substitution (Abc_AigReplace)
- performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc)
- replacing one node by another (Abc_AigReplace)
- propagating constants (Abc_AigReplace)
When AIG is duplicated, the new graph is struturally hashed too.
If this repeated hashing leads to fewer nodes, it means the original
AIG was not strictly hashed (using the three criteria above).
AIG was not strictly hashed (one of the conditions above is violated).
*/
////////////////////////////////////////////////////////////////////////
......@@ -54,6 +56,7 @@ struct Abc_Aig_t_
Vec_Ptr_t * vStackDelete; // the nodes to be deleted
Vec_Ptr_t * vStackReplaceOld; // the nodes to be replaced
Vec_Ptr_t * vStackReplaceNew; // the nodes to be used for replacement
Vec_Vec_t * vLevels; // the nodes to be updated
};
// iterators through the entries in the linked lists of nodes
......@@ -81,6 +84,7 @@ static void Abc_AigResize( Abc_Aig_t * pMan );
// incremental AIG procedures
static void Abc_AigReplace_int( Abc_Aig_t * pMan );
static void Abc_AigDelete_int( Abc_Aig_t * pMan );
static void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -111,6 +115,7 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
pMan->vStackDelete = Vec_PtrAlloc( 100 );
pMan->vStackReplaceOld = Vec_PtrAlloc( 100 );
pMan->vStackReplaceNew = Vec_PtrAlloc( 100 );
pMan->vLevels = Vec_VecAlloc( 100 );
// save the current network
pMan->pNtkAig = pNtkAig;
// allocate constant nodes
......@@ -193,6 +198,7 @@ void Abc_AigFree( Abc_Aig_t * pMan )
assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 );
// free the table
Vec_VecFree( pMan->vLevels );
Vec_PtrFree( pMan->vStackDelete );
Vec_PtrFree( pMan->vStackReplaceOld );
Vec_PtrFree( pMan->vStackReplaceNew );
......@@ -268,12 +274,11 @@ bool Abc_AigCheck( Abc_Aig_t * pMan )
printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" );
return 0;
}
if ( pObj->Level != 1 + ABC_MAX( Abc_ObjFanin0(pObj)->Level, Abc_ObjFanin1(pObj)->Level ) )
printf( "Abc_AigCheck: Node \"%s\" has level that does not agree with the fanin levels.\n", Abc_ObjName(pObj) );
pAnd = Abc_AigAndLookup( pMan, Abc_ObjChild0(pObj), Abc_ObjChild1(pObj) );
if ( pAnd != pObj )
{
printf( "Abc_AigCheck: Node \"%s\" is not in the structural hashing table.\n", Abc_ObjName(pObj) );
return 0;
}
}
// count the number of nodes in the table
Counter = 0;
......@@ -290,6 +295,30 @@ bool Abc_AigCheck( Abc_Aig_t * pMan )
/**Function*************************************************************
Synopsis [Computes the number of logic levels not counting PIs/POs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigGetLevelNum( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, LevelsMax;
assert( Abc_NtkIsAig(pNtk) );
// perform the traversal
LevelsMax = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
if ( LevelsMax < (int)Abc_ObjFanin0(pNode)->Level )
LevelsMax = (int)Abc_ObjFanin0(pNode)->Level;
return LevelsMax;
}
/**Function*************************************************************
Synopsis [Read the constant 1 node.]
Description []
......@@ -349,6 +378,7 @@ Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
pAnd->fExor = Abc_NodeIsExorType(pAnd);
// add the node to the corresponding linked list in the table
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
......@@ -612,6 +642,7 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
Abc_AigReplace_int( pMan );
while ( Vec_PtrSize(pMan->vStackDelete) )
Abc_AigDelete_int( pMan );
Abc_AigUpdateLevel_int( pMan );
}
/**Function*************************************************************
......@@ -627,8 +658,8 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
***********************************************************************/
void Abc_AigReplace_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew;
int k, iFanin;
Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew, * pFanoutFanout;
int k, v, iFanin;
// get the pair of nodes to replace
assert( Vec_PtrSize(pMan->vStackReplaceOld) > 0 );
pOld = Vec_PtrPop( pMan->vStackReplaceOld );
......@@ -668,6 +699,12 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
Abc_ObjRemoveFanins( pFanout );
// update the old fanout with new fanins and add it to the table
Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout );
// schedule the updated node for updating level
Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
// the node has changed, update EXOR status of the fanouts
Abc_ObjForEachFanout( pFanout, pFanoutFanout, v )
if ( Abc_NodeIsAigAnd(pFanoutFanout) )
pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout);
}
// schedule deletion of the old node
if ( Abc_NodeIsAigAnd(pOld) && pOld->fMarkA == 0 )
......@@ -688,6 +725,25 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
SeeAlso []
***********************************************************************/
void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld )
{
assert( Vec_PtrSize(pMan->vStackDelete) == 0 );
Vec_PtrPush( pMan->vStackDelete, pOld );
while ( Vec_PtrSize(pMan->vStackDelete) )
Abc_AigDelete_int( pMan );
}
/**Function*************************************************************
Synopsis [Performs internal deletion step.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigDelete_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pNode, * pFanin;
......@@ -717,6 +773,52 @@ void Abc_AigDelete_int( Abc_Aig_t * pMan )
Abc_NtkDeleteObj( pNode );
}
/**Function*************************************************************
Synopsis [Updates the level of the node after it has changed.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pNode, * pFanout;
Vec_Ptr_t * vVec;
unsigned LevelNew;
int i, k, v;
// go through the nodes and update the level of their fanouts
Vec_VecForEachLevel( pMan->vLevels, vVec, i )
{
if ( Vec_PtrSize(vVec) == 0 )
continue;
Vec_PtrForEachEntry( vVec, pNode, k )
{
assert( Abc_ObjIsNode(pNode) );
Abc_ObjForEachFanout( pNode, pFanout, v )
{
if ( Abc_ObjIsCo(pFanout) )
continue;
// get the new level of this fanout
LevelNew = 1 + ABC_MAX( Abc_ObjFanin0(pFanout)->Level, Abc_ObjFanin1(pFanout)->Level );
if ( pFanout->Level == LevelNew ) // no change
continue;
// update the fanout level
pFanout->Level = LevelNew;
// add the fanout to be updated
Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
}
}
Vec_PtrClear( vVec );
}
}
......@@ -775,6 +877,7 @@ bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
return 0;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -395,7 +395,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
Value = 0;
}
}
/*
// make sure fanins are not duplicated
for ( i = 0; i < pObj->vFanins.nSize; i++ )
for ( k = i + 1; k < pObj->vFanins.nSize; k++ )
......@@ -412,7 +412,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) );
}
*/
return Value;
}
......
......@@ -26,7 +26,8 @@
static void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
static void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
static void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLevels );
static void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes );
static void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels );
static int Abc_NtkGetLevelNum_rec( Abc_Obj_t * pNode );
static bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode );
......@@ -49,23 +50,23 @@ static bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode );
Vec_Ptr_t * Abc_NtkDfs( Abc_Ntk_t * pNtk, int fCollectAll )
{
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode;
Abc_Obj_t * pObj;
int i;
// set the traversal ID
Abc_NtkIncrementTravId( pNtk );
// start the array of nodes
vNodes = Vec_PtrAlloc( 100 );
Abc_NtkForEachCo( pNtk, pNode, i )
Abc_NtkForEachCo( pNtk, pObj, i )
{
Abc_NodeSetTravIdCurrent( pNode );
Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode)), vNodes );
Abc_NodeSetTravIdCurrent( pObj );
Abc_NtkDfs_rec( Abc_ObjFanin0Ntk(Abc_ObjFanin0(pObj)), vNodes );
}
// collect dangling nodes if asked to
if ( fCollectAll )
{
Abc_NtkForEachNode( pNtk, pNode, i )
if ( !Abc_NodeIsTravIdCurrent(pNode) )
Abc_NtkDfs_rec( pNode, vNodes );
Abc_NtkForEachNode( pNtk, pObj, i )
if ( !Abc_NodeIsTravIdCurrent(pObj) )
Abc_NtkDfs_rec( pObj, vNodes );
}
return vNodes;
}
......@@ -138,6 +139,75 @@ void Abc_NtkDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
/**Function*************************************************************
Synopsis [Returns the reverse DFS ordered array of logic nodes.]
Description [Collects only the internal nodes, leaving CIs and CO.
However it marks with the current TravId both CIs and COs.]
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abc_NtkDfsReverse( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNodes;
Abc_Obj_t * pObj, * pFanout;
int i, k;
// set the traversal ID
Abc_NtkIncrementTravId( pNtk );
// start the array of nodes
vNodes = Vec_PtrAlloc( 100 );
Abc_NtkForEachCi( pNtk, pObj, i )
{
Abc_NodeSetTravIdCurrent( pObj );
pObj = Abc_ObjFanout0Ntk(pObj);
Abc_ObjForEachFanout( pObj, pFanout, k )
Abc_NtkDfsReverse_rec( pFanout, vNodes );
}
// add constant nodes in the end
Abc_NtkForEachNode( pNtk, pObj, i )
if ( Abc_NodeIsConst(pObj) )
Vec_PtrPush( vNodes, pObj );
return vNodes;
}
/**Function*************************************************************
Synopsis [Performs DFS for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkDfsReverse_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
{
Abc_Obj_t * pFanout;
int i;
assert( !Abc_ObjIsNet(pNode) );
// if this node is already visited, skip
if ( Abc_NodeIsTravIdCurrent( pNode ) )
return;
// mark the node as visited
Abc_NodeSetTravIdCurrent( pNode );
// skip the CI
if ( Abc_ObjIsCo(pNode) )
return;
assert( Abc_ObjIsNode( pNode ) );
// visit the transitive fanin of the node
pNode = Abc_ObjFanout0Ntk(pNode);
Abc_ObjForEachFanout( pNode, pFanout, i )
Abc_NtkDfsReverse_rec( pFanout, vNodes );
// add the node after the fanins have been added
Vec_PtrPush( vNodes, pNode );
}
/**Function*************************************************************
Synopsis [Returns the DFS ordered array of logic nodes.]
Description [Collects only the internal nodes, leaving CIs and CO.
......@@ -220,20 +290,21 @@ void Abc_AigDfs_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vNodes )
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi )
Vec_Vec_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi )
{
Vec_Ptr_t * vLevels;
Vec_Vec_t * vLevels;
Abc_Obj_t * pFanout;
int i;
assert( fTfi == 0 );
assert( !Abc_NtkIsNetlist(pNode->pNtk) );
// set the traversal ID
Abc_NtkIncrementTravId( pNode->pNtk );
vLevels = Vec_PtrAlloc( 100 );
vLevels = Vec_VecAlloc( 100 );
if ( Abc_ObjIsNode(pNode) )
Abc_DfsLevelizedTfo_rec( pNode, vLevels );
else
{
assert( Abc_ObjIsCi(pNode) );
Abc_NodeSetTravIdCurrent( pNode );
Abc_ObjForEachFanout( pNode, pFanout, i )
Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
......@@ -252,7 +323,7 @@ Vec_Ptr_t * Abc_DfsLevelized( Abc_Obj_t * pNode, bool fTfi )
SeeAlso []
***********************************************************************/
void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLevels )
void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Vec_t * vLevels )
{
Abc_Obj_t * pFanout;
int i;
......@@ -266,14 +337,7 @@ void Abc_DfsLevelizedTfo_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vLevels )
return;
assert( Abc_ObjIsNode(pNode) );
// add the node to the structure
if ( vLevels->nSize <= (int)pNode->Level )
{
Vec_PtrGrow( vLevels, pNode->Level + 1 );
for ( i = vLevels->nSize; i <= (int)pNode->Level; i++ )
vLevels->pArray[i] = Vec_PtrAlloc( 16 );
vLevels->nSize = pNode->Level + 1;
}
Vec_PtrPush( vLevels->pArray[pNode->Level], pNode );
Vec_VecPush( vLevels, pNode->Level, pNode );
// visit the TFO
Abc_ObjForEachFanout( pNode, pFanout, i )
Abc_DfsLevelizedTfo_rec( pFanout, vLevels );
......@@ -373,7 +437,7 @@ bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
Abc_NtkIncrementTravId( pNtk );
// pNode->TravId == pNet->nTravIds means "pNode is on the path"
// pNode->TravId == pNet->nTravIds - 1 means "pNode is visited but is not on the path"
// pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
// pNode->TravId < pNet->nTravIds - 1 means "pNode is not visited"
// traverse the network to detect cycles
fAcyclic = 1;
Abc_NtkForEachCo( pNtk, pNode, i )
......@@ -381,12 +445,12 @@ bool Abc_NtkIsAcyclic( Abc_Ntk_t * pNtk )
pNode = Abc_ObjFanin0Ntk(Abc_ObjFanin0(pNode));
if ( Abc_NodeIsTravIdPrevious(pNode) )
continue;
// traverse the output logic cone to detect the combinational loops
if ( ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) ) == 0 )
{ // stop as soon as the first loop is detected
fprintf( stdout, " (the output node)\n" );
break;
}
// traverse the output logic cone
if ( fAcyclic = Abc_NtkIsAcyclic_rec(pNode) )
continue;
// stop as soon as the first loop is detected
fprintf( stdout, " (cone of CO \"%s\")\n", Abc_ObjName(pNode) );
break;
}
return fAcyclic;
}
......@@ -408,7 +472,6 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
Abc_Obj_t * pFanin;
int fAcyclic, i;
assert( !Abc_ObjIsNet(pNode) );
// skip the PI
if ( Abc_ObjIsCi(pNode) )
return 1;
assert( Abc_ObjIsNode( pNode ) );
......@@ -433,14 +496,12 @@ bool Abc_NtkIsAcyclic_rec( Abc_Obj_t * pNode )
// check if the fanin is visited
if ( Abc_NodeIsTravIdPrevious(pFanin) )
continue;
// traverse searching for the loop
fAcyclic = Abc_NtkIsAcyclic_rec( pFanin );
// traverse the fanin's cone searching for the loop
if ( fAcyclic = Abc_NtkIsAcyclic_rec(pFanin) )
continue;
// return as soon as the loop is detected
if ( fAcyclic == 0 )
{
fprintf( stdout, " <-- %s", Abc_ObjName(pNode) );
return 0;
}
fprintf( stdout, " <-- %s", Abc_ObjName(pNode) );
return 0;
}
// mark this node as a visited node
Abc_NodeSetTravIdPrevious( pNode );
......
......@@ -195,7 +195,7 @@ int Abc_NtkBddToSop( Abc_Ntk_t * pNtk )
***********************************************************************/
char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFuncOn, DdNode * bFuncOnDc, int nFanins, Vec_Str_t * vCube, int fMode )
{
int fVerify = 1;
int fVerify = 0;
char * pSop;
DdNode * bFuncNew, * bCover, * zCover, * zCover0, * zCover1;
int nCubes, nCubes0, nCubes1, fPhase;
......
......@@ -42,6 +42,8 @@
***********************************************************************/
void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
{
int Num;
fprintf( pFile, "%-15s:", pNtk->pName );
fprintf( pFile, " i/o = %4d/%4d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
......@@ -58,7 +60,10 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
else if ( Abc_NtkIsAig(pNtk) )
{
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
fprintf( pFile, " choice = %5d", Abc_NtkCountChoiceNodes(pNtk) );
if ( Num = Abc_NtkCountChoiceNodes(pNtk) )
fprintf( pFile, " (choice = %d)", Num );
if ( Num = Abc_NtkCountExors(pNtk) )
fprintf( pFile, " (exor = %d)", Num );
}
else if ( Abc_NtkIsSeq(pNtk) )
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
......@@ -84,7 +89,9 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
assert( 0 );
}
if ( !Abc_NtkIsSeq(pNtk) )
if ( Abc_NtkIsAig(pNtk) )
fprintf( pFile, " lev = %3d", Abc_AigGetLevelNum(pNtk) );
else if ( !Abc_NtkIsSeq(pNtk) )
fprintf( pFile, " lev = %3d", Abc_NtkGetLevelNum(pNtk) );
fprintf( pFile, "\n" );
......@@ -360,14 +367,49 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile )
{
Abc_Obj_t * pNode;
int i, Length;
assert( Abc_NtkIsAig(pNtk) );
// print the delay profile
if ( fProfile )
if ( fProfile && Abc_NtkIsMapped(pNtk) )
{
int nIntervals = 12;
float DelayMax, DelayCur, DelayDelta;
int * pLevelCounts;
int DelayInt, nOutsSum, nOutsTotal;
// get the max delay and delta
DelayMax = Abc_NtkDelayTrace( pNtk );
DelayDelta = DelayMax/nIntervals;
// collect outputs by delay
pLevelCounts = ALLOC( int, nIntervals );
memset( pLevelCounts, 0, sizeof(int) * nIntervals );
Abc_NtkForEachCo( pNtk, pNode, i )
{
DelayCur = Abc_NodeReadArrival( Abc_ObjFanin0(pNode) )->Worst;
DelayInt = (int)(DelayCur / DelayDelta);
if ( DelayInt >= nIntervals )
DelayInt = nIntervals - 1;
pLevelCounts[DelayInt]++;
}
nOutsSum = 0;
nOutsTotal = Abc_NtkCoNum(pNtk);
for ( i = 0; i < nIntervals; i++ )
{
nOutsSum += pLevelCounts[i];
printf( "[%8.2f - %8.2f] : COs = %4d. %5.1f %%\n",
DelayDelta * i, DelayDelta * (i+1), pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
}
free( pLevelCounts );
return;
}
else if ( fProfile )
{
int LevelMax, * pLevelCounts;
int nOutsSum, nOutsTotal;
if ( !Abc_NtkIsAig(pNtk) )
Abc_NtkGetLevelNum(pNtk);
LevelMax = 0;
Abc_NtkForEachCo( pNtk, pNode, i )
if ( LevelMax < (int)Abc_ObjFanin0(pNode)->Level )
......@@ -385,8 +427,10 @@ void Abc_NtkPrintLevel( FILE * pFile, Abc_Ntk_t * pNtk, int fProfile )
nOutsSum += pLevelCounts[i];
printf( "Level = %4d. COs = %4d. %5.1f %%\n", i, pLevelCounts[i], 100.0 * nOutsSum/nOutsTotal );
}
free( pLevelCounts );
return;
}
assert( Abc_NtkIsAig(pNtk) );
// find the longest name
Length = 0;
......
/**CFile****************************************************************
FileName [abcRes.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Reconvergence=driven cut computation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcRes.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
#include "ft.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
struct Abc_ManCut_t_
{
// user specified parameters
int nNodeSizeMax; // the limit on the size of the supernode
int nConeSizeMax; // the limit on the size of the containing cone
// internal parameters
Abc_Obj_t * pNode; // the node currently considered
Vec_Ptr_t * vFaninsNode; // fanins of the supernode
Vec_Ptr_t * vInsideNode; // inside of the supernode
Vec_Ptr_t * vFaninsCone; // fanins of the containing cone
Vec_Ptr_t * vInsideCone; // inside of the containing cone
Vec_Ptr_t * vVisited; // the visited nodes
};
static int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimit );
static int Abc_NodeGetFaninCost( Abc_Obj_t * pNode );
static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
static void Abc_NodeConeMark( Vec_Ptr_t * vVisited );
static void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Finds a reconvergence-driven cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeFindCut( Abc_ManCut_t * p )
{
Abc_Obj_t * pNode = p->pNode;
int i;
// mark TFI using fMarkA
Vec_PtrClear( p->vVisited );
Abc_NodeConeMarkCollect_rec( pNode, p->vVisited );
// start the reconvergence-driven node
Vec_PtrClear( p->vInsideNode );
Vec_PtrClear( p->vFaninsNode );
Vec_PtrPush( p->vFaninsNode, pNode );
pNode->fMarkB = 1;
// compute reconvergence-driven node
while ( Abc_NodeFindCut_int( p->vInsideNode, p->vFaninsNode, p->nNodeSizeMax ) );
// compute reconvergence-driven cone
Vec_PtrClear( p->vInsideCone );
Vec_PtrClear( p->vFaninsCone );
if ( p->nConeSizeMax > p->nNodeSizeMax )
{
// copy the node into the cone
Vec_PtrForEachEntry( p->vInsideNode, pNode, i )
Vec_PtrPush( p->vInsideCone, pNode );
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
Vec_PtrPush( p->vFaninsCone, pNode );
// compute reconvergence-driven cone
while ( Abc_NodeFindCut_int( p->vInsideCone, p->vFaninsCone, p->nConeSizeMax ) );
// unmark the nodes of the sets
Vec_PtrForEachEntry( p->vInsideCone, pNode, i )
pNode->fMarkB = 0;
Vec_PtrForEachEntry( p->vFaninsCone, pNode, i )
pNode->fMarkB = 0;
}
else
{
// unmark the nodes of the sets
Vec_PtrForEachEntry( p->vInsideNode, pNode, i )
pNode->fMarkB = 0;
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
pNode->fMarkB = 0;
}
// unmark TFI using fMarkA
Abc_NodeConeUnmark( p->vVisited );
}
/**Function*************************************************************
Synopsis [Finds a reconvergence-driven cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimit )
{
Abc_Obj_t * pNode, * pFaninBest, * pNext;
int CostBest, CostCur, i;
// find the best fanin
CostBest = 100;
pFaninBest = NULL;
Vec_PtrForEachEntry( vFanins, pNode, i )
{
CostCur = Abc_NodeGetFaninCost( pNode );
if ( CostBest > CostCur )
{
CostBest = CostCur;
pFaninBest = pNode;
}
}
if ( pFaninBest == NULL )
return 0;
assert( CostBest < 3 );
if ( vFanins->nSize - 1 + CostBest > nSizeLimit )
return 0;
assert( Abc_ObjIsNode(pFaninBest) );
// remove the node from the array
Vec_PtrRemove( vFanins, pFaninBest );
// add the node to the set
Vec_PtrPush( vInside, pFaninBest );
// add the left child to the fanins
pNext = Abc_ObjFanin0(pFaninBest);
if ( !pNext->fMarkB )
{
pNext->fMarkB = 1;
Vec_PtrPush( vFanins, pNext );
}
// add the right child to the fanins
pNext = Abc_ObjFanin1(pFaninBest);
if ( !pNext->fMarkB )
{
pNext->fMarkB = 1;
Vec_PtrPush( vFanins, pNext );
}
assert( vFanins->nSize <= nSizeLimit );
// keep doing this
return 1;
}
/**Function*************************************************************
Synopsis [Evaluate the fanin cost.]
Description [Returns the number of fanins that will be brought in.
Returns large number if the node cannot be added.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeGetFaninCost( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout;
int i;
assert( pNode->fMarkA == 1 ); // this node is in the TFI
assert( pNode->fMarkB == 1 ); // this node is in the constructed cone
// check the PI node
if ( !Abc_ObjIsNode(pNode) )
return 999;
// check the fanouts
Abc_ObjForEachFanout( pNode, pFanout, i )
if ( pFanout->fMarkA && pFanout->fMarkB == 0 ) // in the cone but not in the set
return 999;
// the fanouts are in the TFI and inside the constructed cone
// return the number of fanins that will be on the boundary if this node is added
return (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
}
/**Function*************************************************************
Synopsis [Marks the TFI cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
{
if ( pNode->fMarkA == 1 )
return;
// visit transitive fanin
if ( Abc_ObjIsNode(pNode) )
{
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
}
assert( pNode->fMarkA == 0 );
pNode->fMarkA = 1;
Vec_PtrPush( vVisited, pNode );
}
/**Function*************************************************************
Synopsis [Unmarks the TFI cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeConeMark( Vec_Ptr_t * vVisited )
{
int i;
for ( i = 0; i < vVisited->nSize; i++ )
((Abc_Obj_t *)vVisited->pArray)->fMarkA = 1;
}
/**Function*************************************************************
Synopsis [Unmarks the TFI cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited )
{
int i;
for ( i = 0; i < vVisited->nSize; i++ )
((Abc_Obj_t *)vVisited->pArray)->fMarkA = 0;
}
/**Function*************************************************************
Synopsis [Returns BDD representing the logic function of the cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited )
{
DdNode * bFunc0, * bFunc1, * bFunc;
int i;
// mark the fanins of the cone
Abc_NodeConeMark( vFanins );
// collect the nodes in the DFS order
Vec_PtrClear( vVisited );
Abc_NodeConeMarkCollect_rec( pNode, vVisited );
// unmark both sets
Abc_NodeConeUnmark( vFanins );
Abc_NodeConeUnmark( vVisited );
// set the elementary BDDs
Vec_PtrForEachEntry( vFanins, pNode, i )
pNode->pCopy = (Abc_Obj_t *)pbVars[i];
// compute the BDDs for the collected nodes
Vec_PtrForEachEntry( vVisited, pNode, i )
{
bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) );
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
pNode->pCopy = (Abc_Obj_t *)bFunc;
}
Cudd_Ref( bFunc );
// dereference the intermediate ones
Vec_PtrForEachEntry( vVisited, pNode, i )
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
Cudd_Deref( bFunc );
return bFunc;
}
/**Function*************************************************************
Synopsis [Starts the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_ManCut_t * Abc_NtkManCutStart()
{
Abc_ManCut_t * p;
p = ALLOC( Abc_ManCut_t, 1 );
memset( p, 0, sizeof(Abc_ManCut_t) );
p->vFaninsNode = Vec_PtrAlloc( 100 );
p->vInsideNode = Vec_PtrAlloc( 100 );
p->vFaninsCone = Vec_PtrAlloc( 100 );
p->vInsideCone = Vec_PtrAlloc( 100 );
p->vVisited = Vec_PtrAlloc( 100 );
return p;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkManCutStop( Abc_ManCut_t * p )
{
Vec_PtrFree( p->vFaninsNode );
Vec_PtrFree( p->vInsideNode );
Vec_PtrFree( p->vFaninsCone );
Vec_PtrFree( p->vInsideCone );
Vec_PtrFree( p->vVisited );
free( p );
}
/**Function*************************************************************
Synopsis [Collects the TFO of the cut in the topological order.]
Description [TFO of the cut is defined as a set of nodes, for which the cut
is a cut, that is, every path from the collected nodes to the CIs goes through
a node in the cut. The nodes are collected if their level does not exceed
the given number (LevelMax). The nodes are returned in the topological order.
If the root node is given, its MFFC is marked, so that the collected nodes
do not contain any nodes in the MFFC.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot,
Vec_Ptr_t * vFanins, int LevelMax, Vec_Vec_t * vLevels, Vec_Ptr_t * vResult )
{
Vec_Ptr_t * vVec;
Abc_Obj_t * pNode, * pFanout;
int i, k, v, LevelMin;
assert( Abc_NtkIsAig(pNtk) );
// assuming that the structure is clean
Vec_VecForEachLevel( vLevels, vVec, i )
assert( vVec->nSize == 0 );
// put fanins into the structure while labeling them
Abc_NtkIncrementTravId( pNtk );
LevelMin = ABC_INFINITY;
Vec_PtrForEachEntry( vFanins, pNode, i )
{
if ( pNode->Level > (unsigned)LevelMax )
continue;
Abc_NodeSetTravIdCurrent( pNode );
Vec_VecPush( vLevels, pNode->Level, pNode );
if ( LevelMin < (int)pNode->Level )
LevelMin = pNode->Level;
}
assert( LevelMin >= 0 );
// mark MFFC
if ( pRoot )
Abc_NodeMffcLabel( pRoot );
// go through the levels up
Vec_PtrClear( vResult );
Vec_VecForEachEntryStartStop( vLevels, pNode, i, k, LevelMin, LevelMax )
{
// if the node is not marked, it is not a fanin
if ( !Abc_NodeIsTravIdCurrent(pNode) )
{
// check if it belongs to the TFO
if ( !Abc_NodeIsTravIdCurrent(Abc_ObjFanin0(pNode)) ||
!Abc_NodeIsTravIdCurrent(Abc_ObjFanin1(pNode)) )
continue;
// save the node in the TFO and label it
Vec_PtrPush( vResult, pNode );
Abc_NodeSetTravIdCurrent( pNode );
}
// go through the fanouts and add them to the structure if they meet the conditions
Abc_ObjForEachFanout( pNode, pFanout, v )
{
// skip if fanout is a CO or its level exceeds
if ( Abc_ObjIsCo(pFanout) || pFanout->Level > (unsigned)LevelMax )
continue;
// skip if it is already added or if it is in MFFC
if ( Abc_NodeIsTravIdCurrent(pFanout) )
continue;
// add it to the structure but do not mark it (until tested later)
Vec_VecPush( vLevels, pFanout->Level, pFanout );
}
}
// clear the levelized structure
Vec_VecForEachLevelStartStop( vLevels, vVec, i, LevelMin, LevelMax )
Vec_PtrClear( vVec );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -24,7 +24,7 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference );
static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -47,7 +47,7 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
nConeSize2 = Abc_NodeRefDeref( pNode, 0, 1 ); // reference
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
......@@ -55,7 +55,7 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
/**Function*************************************************************
Synopsis [Procedure returns the size of the MFFC of the node.]
Synopsis [Lavels MFFC with the current traversal ID.]
Description []
......@@ -64,11 +64,16 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
int Abc_NodeMffcRemove( Abc_Obj_t * pNode )
int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
{
int nConeSize1, nConeSize2;
assert( !Abc_ObjIsComplement( pNode ) );
assert( Abc_ObjIsNode( pNode ) );
return Abc_NodeRefDeref( pNode, 1, 0 ); // dereference
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 1 ); // reference
assert( nConeSize1 == nConeSize2 );
assert( nConeSize1 > 0 );
return nConeSize1;
}
/**Function*************************************************************
......@@ -82,10 +87,12 @@ int Abc_NodeMffcRemove( Abc_Obj_t * pNode )
SeeAlso []
***********************************************************************/
int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference )
int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel )
{
Abc_Obj_t * pNode0, * pNode1;
int Counter;
if ( fLabel )
Abc_NodeSetTravIdCurrent( pNode );
if ( Abc_ObjIsCi(pNode) )
return 0;
pNode0 = Abc_ObjFanin( pNode, 0 );
......@@ -94,34 +101,18 @@ int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fFanouts, bool fReference )
if ( fReference )
{
if ( pNode0->vFanouts.nSize++ == 0 )
{
Counter += Abc_NodeRefDeref( pNode0, fFanouts, fReference );
if ( fFanouts )
Abc_ObjAddFanin( pNode, pNode0 );
}
Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
if ( pNode1->vFanouts.nSize++ == 0 )
{
Counter += Abc_NodeRefDeref( pNode1, fFanouts, fReference );
if ( fFanouts )
Abc_ObjAddFanin( pNode, pNode1 );
}
Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
}
else
{
assert( pNode0->vFanouts.nSize > 0 );
assert( pNode1->vFanouts.nSize > 0 );
if ( --pNode0->vFanouts.nSize == 0 )
{
Counter += Abc_NodeRefDeref( pNode0, fFanouts, fReference );
if ( fFanouts )
Abc_ObjDeleteFanin( pNode, pNode0 );
}
Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
if ( --pNode1->vFanouts.nSize == 0 )
{
Counter += Abc_NodeRefDeref( pNode1, fFanouts, fReference );
if ( fFanouts )
Abc_ObjDeleteFanin( pNode, pNode1 );
}
Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
}
return Counter;
}
......
......@@ -24,21 +24,8 @@
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Abc_NodeResyn( Abc_ManRes_t * p );
static void Abc_NodeFindCut( Abc_ManRes_t * p );
static int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimit );
static int Abc_NodeGetFaninCost( Abc_Obj_t * pNode );
static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
static void Abc_NodeConeMark( Vec_Ptr_t * vVisited );
static void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited );
static Vec_Int_t * Abc_NodeRefactor( Abc_ManRes_t * p );
static DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited );
static int Abc_NodeDecide( Abc_ManRes_t * p );
static void Abc_NodeUpdate( Abc_ManRes_t * p );
static void Abc_NodeUpdate( Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, int nGain );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -46,422 +33,76 @@ static void Abc_NodeUpdate( Abc_ManRes_t * p );
/**Function*************************************************************
Synopsis [Performs incremental resynthesis of the AIG.]
Synopsis [Performs incremental rewriting of the AIG.]
Description [Starting from each node, computes a reconvergence-driven cut,
derives BDD of the cut function, constructs ISOP, factors the cover,
and replaces the current implementation of the MFFC of the cut by the
new factored form if the number of AIG nodes is reduced. Returns the
number of AIG nodes saved.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkAigResynthesize( Abc_Ntk_t * pNtk, Abc_ManRes_t * p )
int Abc_NtkRewrite( Abc_Ntk_t * pNtk )
{
int fCheck = 1;
ProgressBar * pProgress;
Abc_ManRwr_t * p;
Abc_Obj_t * pNode;
int i, Counter, Approx;
int i, nNodes, nGain;
assert( Abc_NtkIsAig(pNtk) );
// start the rewriting manager
p = Abc_NtkManRwrStart( "data.aaa" );
Abc_NtkManRwrStartCuts( p, pNtk );
// start the BDD manager
p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
Cudd_zddVarsFromBddVars( p->dd, 2 );
p->bCubeX = Extra_bddComputeRangeCube( p->dd, p->nNodeSizeMax, p->dd->size ); Cudd_Ref( p->bCubeX );
// remember the number of nodes
Counter = Abc_NtkNodeNum( pNtk );
// resynthesize each node
pProgress = Extra_ProgressBarStart( stdout, 100 );
// resynthesize each node once
nNodes = Abc_NtkObjNumMax(pNtk);
pProgress = Extra_ProgressBarStart( stdout, nNodes );
Abc_NtkForEachNode( pNtk, pNode, i )
{
Approx = (int)(100.0 * i / Abc_NtkObjNumMax(pNtk) );
Extra_ProgressBarUpdate( pProgress, Approx, NULL );
p->pNode = pNode;
Abc_NodeResyn( p );
Extra_ProgressBarUpdate( pProgress, nNodes, NULL );
// compute the cuts of the node
Abc_NodeRwrComputeCuts( p, pNode );
// for each cut, try to resynthesize it
if ( (nGain = Abc_NodeRwrRewrite( p, pNode )) >= 0 )
Abc_NodeUpdate( pNode, Abc_NtkManRwrFanins(p), Abc_NtkManRwrDecs(p), nGain );
// check the improvement
if ( i == nNodes )
break;
}
Extra_ProgressBarStop( pProgress );
Abc_NtkManResStop( p );
// delete the manager
Abc_NtkManRwrStop( p );
// check
if ( fCheck && !Abc_NtkCheck( pNtk ) )
{
printf( "Abc_NtkAigResynthesize: The network check has failed.\n" );
return -1;
}
return Abc_NtkNodeNum(pNtk) - Counter;
}
/**Function*************************************************************
Synopsis [Performs resynthesis of one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeResyn( Abc_ManRes_t * p )
{
int RetValue;
int clk;
assert( Abc_ObjIsNode(p->pNode) );
clk = clock();
// detect the cut
Abc_NodeFindCut( p );
p->time1 += clock() - clk;
// refactor the cut
clk = clock();
p->vForm = Abc_NodeRefactor( p );
p->time2 += clock() - clk;
// accept or reject the factored form
clk = clock();
RetValue = Abc_NodeDecide( p );
p->time3 += clock() - clk;
// modify the network
clk = clock();
if ( RetValue )
Abc_NodeUpdate( p );
p->time4 += clock() - clk;
// cleanup
Vec_IntFree( p->vForm );
p->vForm = NULL;
}
/**Function*************************************************************
Synopsis [Finds a reconvergence-driven cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeFindCut( Abc_ManRes_t * p )
{
Abc_Obj_t * pNode = p->pNode;
int i;
// mark TFI using fMarkA
Vec_PtrClear( p->vVisited );
Abc_NodeConeMarkCollect_rec( pNode, p->vVisited );
// start the reconvergence-driven node
Vec_PtrClear( p->vInsideNode );
Vec_PtrClear( p->vFaninsNode );
Vec_PtrPush( p->vFaninsNode, pNode );
pNode->fMarkB = 1;
// compute reconvergence-driven node
while ( Abc_NodeFindCut_int( p->vInsideNode, p->vFaninsNode, p->nNodeSizeMax ) );
// compute reconvergence-driven cone
Vec_PtrClear( p->vInsideCone );
Vec_PtrClear( p->vFaninsCone );
if ( p->nConeSizeMax > p->nNodeSizeMax )
{
// copy the node into the cone
Vec_PtrForEachEntry( p->vInsideNode, pNode, i )
Vec_PtrPush( p->vInsideCone, pNode );
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
Vec_PtrPush( p->vFaninsCone, pNode );
// compute reconvergence-driven cone
while ( Abc_NodeFindCut_int( p->vInsideCone, p->vFaninsCone, p->nConeSizeMax ) );
// unmark the nodes of the sets
Vec_PtrForEachEntry( p->vInsideCone, pNode, i )
pNode->fMarkB = 0;
Vec_PtrForEachEntry( p->vFaninsCone, pNode, i )
pNode->fMarkB = 0;
}
else
{
// unmark the nodes of the sets
Vec_PtrForEachEntry( p->vInsideNode, pNode, i )
pNode->fMarkB = 0;
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
pNode->fMarkB = 0;
}
// unmark TFI using fMarkA
Abc_NodeConeUnmark( p->vVisited );
}
/**Function*************************************************************
Synopsis [Finds a reconvergence-driven cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimit )
{
Abc_Obj_t * pNode, * pFaninBest, * pNext;
int CostBest, CostCur, i;
// find the best fanin
CostBest = 100;
pFaninBest = NULL;
Vec_PtrForEachEntry( vFanins, pNode, i )
{
CostCur = Abc_NodeGetFaninCost( pNode );
if ( CostBest > CostCur )
{
CostBest = CostCur;
pFaninBest = pNode;
}
}
if ( pFaninBest == NULL )
return 0;
assert( CostBest < 3 );
if ( vFanins->nSize - 1 + CostBest > nSizeLimit )
printf( "Abc_NtkRewrite: The network check has failed.\n" );
return 0;
assert( Abc_ObjIsNode(pFaninBest) );
// remove the node from the array
Vec_PtrRemove( vFanins, pFaninBest );
// add the node to the set
Vec_PtrPush( vInside, pFaninBest );
// add the left child to the fanins
pNext = Abc_ObjFanin0(pFaninBest);
if ( !pNext->fMarkB )
{
pNext->fMarkB = 1;
Vec_PtrPush( vFanins, pNext );
}
// add the right child to the fanins
pNext = Abc_ObjFanin1(pFaninBest);
if ( !pNext->fMarkB )
{
pNext->fMarkB = 1;
Vec_PtrPush( vFanins, pNext );
}
assert( vFanins->nSize <= nSizeLimit );
// keep doing this
return 1;
}
/**Function*************************************************************
Synopsis [Evaluate the fanin cost.]
Description [Returns the number of fanins that will be brought in.
Returns large number if the node cannot be added.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeGetFaninCost( Abc_Obj_t * pNode )
{
Abc_Obj_t * pFanout;
int i;
assert( pNode->fMarkA == 1 ); // this node is in the TFI
assert( pNode->fMarkB == 1 ); // this node is in the constructed cone
// check the PI node
if ( !Abc_ObjIsNode(pNode) )
return 999;
// check the fanouts
Abc_ObjForEachFanout( pNode, pFanout, i )
if ( pFanout->fMarkA && pFanout->fMarkB == 0 ) // in the cone but not in the set
return 999;
// the fanouts are in the TFI and inside the constructed cone
// return the number of fanins that will be on the boundary if this node is added
return (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
}
/**Function*************************************************************
Synopsis [Marks the TFI cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
{
if ( pNode->fMarkA == 1 )
return;
// visit transitive fanin
if ( Abc_ObjIsNode(pNode) )
{
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
}
assert( pNode->fMarkA == 0 );
pNode->fMarkA = 1;
Vec_PtrPush( vVisited, pNode );
}
/**Function*************************************************************
Synopsis [Unmarks the TFI cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeConeMark( Vec_Ptr_t * vVisited )
{
int i;
for ( i = 0; i < vVisited->nSize; i++ )
((Abc_Obj_t *)vVisited->pArray)->fMarkA = 1;
}
/**Function*************************************************************
Synopsis [Unmarks the TFI cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited )
{
int i;
for ( i = 0; i < vVisited->nSize; i++ )
((Abc_Obj_t *)vVisited->pArray)->fMarkA = 0;
}
/**Function*************************************************************
Synopsis [Derives the factored form of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NodeRefactor( Abc_ManRes_t * p )
{
Vec_Int_t * vForm;
DdManager * dd = p->dd;
DdNode * bFuncNode, * bFuncCone, * bCare, * bFuncOn, * bFuncOnDc;
char * pSop;
int nFanins;
assert( p->vFaninsNode->nSize < p->nNodeSizeMax );
assert( p->vFaninsCone->nSize < p->nConeSizeMax );
// get the function of the node
bFuncNode = Abc_NodeConeBdd( dd, p->dd->vars, p->pNode, p->vFaninsNode, p->vVisited );
Cudd_Ref( bFuncNode );
nFanins = p->vFaninsNode->nSize;
if ( p->nConeSizeMax > p->nNodeSizeMax )
{
// get the function of the cone
bFuncCone = Abc_NodeConeBdd( dd, p->dd->vars + p->nNodeSizeMax, p->pNode, p->vFaninsCone, p->vVisited );
Cudd_Ref( bFuncCone );
// get the care set
bCare = Cudd_bddXorExistAbstract( p->dd, Cudd_Not(bFuncNode), bFuncCone, p->bCubeX ); Cudd_Ref( bCare );
Cudd_RecursiveDeref( dd, bFuncCone );
// compute the on-set and off-set of the function of the node
bFuncOn = Cudd_bddAnd( dd, bFuncNode, bCare ); Cudd_Ref( bFuncOn );
bFuncOnDc = Cudd_bddAnd( dd, Cudd_Not(bFuncNode), bCare ); Cudd_Ref( bFuncOnDc );
bFuncOnDc = Cudd_Not( bFuncOnDc );
Cudd_RecursiveDeref( dd, bCare );
// get the cover
pSop = Abc_ConvertBddToSop( NULL, dd, bFuncOn, bFuncOnDc, nFanins, p->vCube, -1 );
Cudd_RecursiveDeref( dd, bFuncOn );
Cudd_RecursiveDeref( dd, bFuncOnDc );
}
else
{
// get the cover
pSop = Abc_ConvertBddToSop( NULL, dd, bFuncNode, bFuncNode, nFanins, p->vCube, -1 );
}
Cudd_RecursiveDeref( dd, bFuncNode );
// derive the factored form
vForm = Ft_Factor( pSop );
free( pSop );
return vForm;
}
/**Function*************************************************************
Synopsis [Returns BDD representing the logic function of the cone.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited )
{
DdNode * bFunc0, * bFunc1, * bFunc;
int i;
// mark the fanins of the cone
Abc_NodeConeMark( vFanins );
// collect the nodes in the DFS order
Vec_PtrClear( vVisited );
Abc_NodeConeMarkCollect_rec( pNode, vVisited );
// unmark both sets
Abc_NodeConeUnmark( vFanins );
Abc_NodeConeUnmark( vVisited );
// set the elementary BDDs
Vec_PtrForEachEntry( vFanins, pNode, i )
pNode->pCopy = (Abc_Obj_t *)pbVars[i];
// compute the BDDs for the collected nodes
Vec_PtrForEachEntry( vVisited, pNode, i )
{
bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) );
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
pNode->pCopy = (Abc_Obj_t *)bFunc;
}
Cudd_Ref( bFunc );
// dereference the intermediate ones
Vec_PtrForEachEntry( vVisited, pNode, i )
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
Cudd_Deref( bFunc );
return bFunc;
}
/**Function*************************************************************
Synopsis [Decides whether to accept the given factored form.]
Synopsis [Performs incremental resynthesis of the AIG.]
Description []
Description [Starting from each node, computes a reconvergence-driven cut,
derives BDD of the cut function, constructs ISOP, factors the cover,
and replaces the current implementation of the MFFC of the cut by the
new factored form if the number of AIG nodes is reduced. Returns the
number of AIG nodes saved.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeDecide( Abc_ManRes_t * p )
int Abc_NtkRefactor( Abc_Ntk_t * pNtk, Abc_ManRef_t * p )
{
return 0;
int fCheck = 1;
return 1;
}
/**Function*************************************************************
......@@ -475,60 +116,21 @@ int Abc_NodeDecide( Abc_ManRes_t * p )
SeeAlso []
***********************************************************************/
void Abc_NodeUpdate( Abc_ManRes_t * p )
{
}
/**Function*************************************************************
Synopsis [Starts the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_ManRes_t * Abc_NtkManResStart()
void Abc_NodeUpdate( Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, int nGain )
{
Abc_ManRes_t * p;
p = ALLOC( Abc_ManRes_t, 1 );
p->vFaninsNode = Vec_PtrAlloc( 100 );
p->vInsideNode = Vec_PtrAlloc( 100 );
p->vFaninsCone = Vec_PtrAlloc( 100 );
p->vInsideCone = Vec_PtrAlloc( 100 );
p->vVisited = Vec_PtrAlloc( 100 );
p->vCube = Vec_StrAlloc( 100 );
return p;
Abc_Obj_t * pNodeNew;
int nNodesNew, nNodesOld;
nNodesOld = Abc_NtkNodeNum(pNode->pNtk);
// create the new structure of nodes
assert( Vec_PtrSize(vFanins) < Vec_IntSize(vForm) );
pNodeNew = Abc_NodeStrashDec( pNode->pNtk->pManFunc, vFanins, vForm );
// remove the old nodes
Abc_AigReplace( pNode->pNtk->pManFunc, pNode, pNodeNew );
// compare the gains
nNodesNew = Abc_NtkNodeNum(pNode->pNtk);
assert( nGain <= nNodesOld - nNodesNew );
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkManResStop( Abc_ManRes_t * p )
{
if ( p->bCubeX ) Cudd_RecursiveDeref( p->dd, p->bCubeX );
if ( p->dd ) Extra_StopManager( p->dd );
Vec_PtrFree( p->vFaninsNode );
Vec_PtrFree( p->vInsideNode );
Vec_PtrFree( p->vFaninsCone );
Vec_PtrFree( p->vInsideCone );
Vec_PtrFree( p->vVisited );
Vec_StrFree( p->vCube );
free( p );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
/**CFile****************************************************************
FileName [abcResRef.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Resynthesis based on refactoring.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcResRef.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
struct Abc_ManRef_t_
{
// user specified parameters
int nNodeSizeMax; // the limit on the size of the supernode
int nConeSizeMax; // the limit on the size of the containing cone
int fVerbose; // the verbosity flag
// the node currently processed
Abc_Obj_t * pNode; // the node currently considered
// internal parameters
DdManager * dd; // the BDD manager
DdNode * bCubeX; // the cube of PI variables
Vec_Str_t * vCube; // temporary cube for generating covers
Vec_Int_t * vForm; // the factored form (temporary)
// runtime statistics
int time1;
int time2;
int time3;
int time4;
};
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Resynthesizes the node using refactoring.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
bool Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode )
{
return 0;
}
/**Function*************************************************************
Synopsis [Derives the factored form of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
/*
Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p )
{
Vec_Int_t * vForm;
DdManager * dd = p->dd;
DdNode * bFuncNode, * bFuncCone, * bCare, * bFuncOn, * bFuncOnDc;
char * pSop;
int nFanins;
assert( p->vFaninsNode->nSize < p->nNodeSizeMax );
assert( p->vFaninsCone->nSize < p->nConeSizeMax );
// get the function of the node
bFuncNode = Abc_NodeConeBdd( dd, p->dd->vars, p->pNode, p->vFaninsNode, p->vVisited );
Cudd_Ref( bFuncNode );
nFanins = p->vFaninsNode->nSize;
if ( p->nConeSizeMax > p->nNodeSizeMax )
{
// get the function of the cone
bFuncCone = Abc_NodeConeBdd( dd, p->dd->vars + p->nNodeSizeMax, p->pNode, p->vFaninsCone, p->vVisited );
Cudd_Ref( bFuncCone );
// get the care set
bCare = Cudd_bddXorExistAbstract( p->dd, Cudd_Not(bFuncNode), bFuncCone, p->bCubeX ); Cudd_Ref( bCare );
Cudd_RecursiveDeref( dd, bFuncCone );
// compute the on-set and off-set of the function of the node
bFuncOn = Cudd_bddAnd( dd, bFuncNode, bCare ); Cudd_Ref( bFuncOn );
bFuncOnDc = Cudd_bddAnd( dd, Cudd_Not(bFuncNode), bCare ); Cudd_Ref( bFuncOnDc );
bFuncOnDc = Cudd_Not( bFuncOnDc );
Cudd_RecursiveDeref( dd, bCare );
// get the cover
pSop = Abc_ConvertBddToSop( NULL, dd, bFuncOn, bFuncOnDc, nFanins, p->vCube, -1 );
Cudd_RecursiveDeref( dd, bFuncOn );
Cudd_RecursiveDeref( dd, bFuncOnDc );
}
else
{
// get the cover
pSop = Abc_ConvertBddToSop( NULL, dd, bFuncNode, bFuncNode, nFanins, p->vCube, -1 );
}
Cudd_RecursiveDeref( dd, bFuncNode );
// derive the factored form
vForm = Ft_Factor( pSop );
free( pSop );
return vForm;
}
*/
/**Function*************************************************************
Synopsis [Starts the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_ManRef_t * Abc_NtkManRefStart()
{
Abc_ManRef_t * p;
p = ALLOC( Abc_ManRef_t, 1 );
memset( p, 0, sizeof(Abc_ManRef_t) );
p->vCube = Vec_StrAlloc( 100 );
// start the BDD manager
p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
Cudd_zddVarsFromBddVars( p->dd, 2 );
p->bCubeX = Extra_bddComputeRangeCube( p->dd, p->nNodeSizeMax, p->dd->size ); Cudd_Ref( p->bCubeX );
return p;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkManRefStop( Abc_ManRef_t * p )
{
if ( p->bCubeX ) Cudd_RecursiveDeref( p->dd, p->bCubeX );
if ( p->dd ) Extra_StopManager( p->dd );
Vec_StrFree( p->vCube );
free( p );
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NtkManRefResult( Abc_ManRef_t * p )
{
return p->vForm;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -31,6 +31,7 @@ static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig,
static Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode );
static Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
static Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
static Abc_Obj_t * Abc_NodeStrashFactor2( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate );
static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, bool fDuplicate );
......@@ -179,7 +180,7 @@ Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
// decide when to use factoring
if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
return Abc_NodeStrashFactor( pMan, pNode, pSop );
return Abc_NodeStrashFactor2( pMan, pNode, pSop );
return Abc_NodeStrashSop( pMan, pNode, pSop );
}
......@@ -289,6 +290,81 @@ Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pS
/**Function*************************************************************
Synopsis [Strashes one logic node using its SOP.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NodeStrashFactor2( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pSop )
{
Vec_Int_t * vForm;
Vec_Ptr_t * vAnds;
Abc_Obj_t * pAnd, * pFanin;
int i;
// derive the factored form
vForm = Ft_Factor( pSop );
// collect the fanins
vAnds = Vec_PtrAlloc( 20 );
Abc_ObjForEachFanin( pRoot, pFanin, i )
Vec_PtrPush( vAnds, pFanin->pCopy );
// perform strashing
pAnd = Abc_NodeStrashDec( pMan, vAnds, vForm );
Vec_PtrFree( vAnds );
Vec_IntFree( vForm );
return pAnd;
}
/**Function*************************************************************
Synopsis [Strashes one logic node using its SOP.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NodeStrashDec( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * vForm )
{
Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
Ft_Node_t * pFtNode;
int i, nVars;
// sanity checks
nVars = Ft_FactorGetNumVars( vForm );
assert( nVars >= 0 );
assert( vForm->nSize > nVars );
assert( nVars == vFanins->nSize );
// check for constant function
pFtNode = Ft_NodeRead( vForm, 0 );
if ( pFtNode->fConst )
return Abc_ObjNotCond( Abc_AigConst1(pMan), pFtNode->fCompl );
// compute the function of other nodes
for ( i = nVars; i < vForm->nSize; i++ )
{
pFtNode = Ft_NodeRead( vForm, i );
pAnd0 = Abc_ObjNotCond( vFanins->pArray[pFtNode->iFanin0], pFtNode->fCompl0 );
pAnd1 = Abc_ObjNotCond( vFanins->pArray[pFtNode->iFanin1], pFtNode->fCompl1 );
pAnd = Abc_AigAnd( pMan, pAnd0, pAnd1 );
Vec_PtrPush( vFanins, pAnd );
}
assert( vForm->nSize = vFanins->nSize );
// complement the result if necessary
pFtNode = Ft_NodeReadLast( vForm );
pAnd = Abc_ObjNotCond( pAnd, pFtNode->fCompl );
return pAnd;
}
/**Function*************************************************************
Synopsis [Appends the second network to the first.]
Description [Modifies the first network by adding the logic of the second.
......
......@@ -447,9 +447,62 @@ void Abc_VecObjPushUniqueOrderByLevel( Vec_Ptr_t * p, Abc_Obj_t * pNode )
/**Function*************************************************************
Synopsis [Marks and counts the number of exors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCountExors( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
Counter += pNode->fExor;
return Counter;
}
/**Function*************************************************************
Synopsis [Returns 1 if the node is the root of EXOR/NEXOR.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
bool Abc_NodeIsExorType( Abc_Obj_t * pNode )
{
Abc_Obj_t * pNode0, * pNode1;
// check that the node is regular
assert( !Abc_ObjIsComplement(pNode) );
// if the node is not AND, this is not EXOR
if ( !Abc_NodeIsAigAnd(pNode) )
return 0;
// if the children are not complemented, this is not EXOR
if ( !Abc_ObjFaninC0(pNode) || !Abc_ObjFaninC1(pNode) )
return 0;
// get children
pNode0 = Abc_ObjFanin0(pNode);
pNode1 = Abc_ObjFanin1(pNode);
// if the children are not ANDs, this is not EXOR
if ( Abc_ObjFaninNum(pNode0) != 2 || Abc_ObjFaninNum(pNode1) != 2 )
return 0;
// otherwise, the node is EXOR iff its grand-children are the same
return (Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId0(pNode0) == Abc_ObjFaninId1(pNode1)) &&
(Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId0(pNode1) || Abc_ObjFaninId1(pNode0) == Abc_ObjFaninId1(pNode1));
}
/**Function*************************************************************
Synopsis [Returns 1 if the node is the root of MUX or EXOR/NEXOR.]
Description [The node can be complemented.]
Description []
SideEffects []
......@@ -920,6 +973,54 @@ void Abc_NtkAlphaOrderSignals( Abc_Ntk_t * pNtk, int fComb )
pObj->pCopy = NULL;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkShortNames( Abc_Ntk_t * pNtk )
{
stmm_table * tObj2NameNew;
Abc_Obj_t * pObj;
char Buffer[100];
char * pNameNew;
int Length, i;
tObj2NameNew = stmm_init_table(stmm_ptrcmp, stmm_ptrhash);
// create new names and add them to the table
Length = Extra_Base10Log( Abc_NtkPiNum(pNtk) );
Abc_NtkForEachPi( pNtk, pObj, i )
{
sprintf( Buffer, "pi%0*d", Length, i );
pNameNew = Abc_NtkRegisterName( pNtk, Buffer );
stmm_insert( tObj2NameNew, (char *)pObj, pNameNew );
}
// create new names and add them to the table
Length = Extra_Base10Log( Abc_NtkPoNum(pNtk) );
Abc_NtkForEachPo( pNtk, pObj, i )
{
sprintf( Buffer, "po%0*d", Length, i );
pNameNew = Abc_NtkRegisterName( pNtk, Buffer );
stmm_insert( tObj2NameNew, (char *)pObj, pNameNew );
}
// create new names and add them to the table
Length = Extra_Base10Log( Abc_NtkLatchNum(pNtk) );
Abc_NtkForEachLatch( pNtk, pObj, i )
{
sprintf( Buffer, "lat%0*d", Length, i );
pNameNew = Abc_NtkRegisterName( pNtk, Buffer );
stmm_insert( tObj2NameNew, (char *)pObj, pNameNew );
}
stmm_free_table( pNtk->tObj2Name );
pNtk->tObj2Name = tObj2NameNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -88,6 +88,9 @@ PRT( "Time", p->timeMatch );
}
//////////////////////////////////////////////////////////////////////
if ( !p->fAreaRecovery )
return 1;
//////////////////////////////////////////////////////////////////////
// perform area recovery using area flow
clk = clock();
......
......@@ -926,7 +926,7 @@ Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node
Map_Cut_t * pCut;
int Place, i;
// int clk;
/*
// check the cut
Place = Map_CutTableLookup( p, ppNodes, nNodes );
if ( Place == -1 )
......@@ -934,7 +934,6 @@ Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node
assert( nNodes > 0 );
// create the new cut
//clk = clock();
*/
pCut = Map_CutAlloc( pMan );
//pMan->time1 += clock() - clk;
pCut->nLeaves = nNodes;
......@@ -944,15 +943,12 @@ Map_Cut_t * Map_CutTableConsider( Map_Man_t * pMan, Map_CutTable_t * p, Map_Node
pCut->ppLeaves[i] = ppNodes[i];
// pCut->fLevel += ppNodes[i]->Level;
}
/*
// pCut->fLevel /= nNodes;
// add the cut to the table
assert( p->pBins[Place] == NULL );
p->pBins[Place] = pCut;
// add the cut to the new list
p->pCuts[ p->nCuts++ ] = Place;
*/
return pCut;
}
......
......@@ -140,10 +140,13 @@ void Map_SuperLibFree( Map_SuperLib_t * p )
{
// if ( s_pLib == p->pGenlib )
// s_pLib = NULL;
if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == p->pGenlib )
Abc_FrameSetLibGen(Abc_FrameGetGlobalFrame(), NULL);
// if ( Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) == p->pGenlib )
// Abc_FrameSetLibGen(Abc_FrameGetGlobalFrame(), NULL);
// Mio_LibraryDelete( p->pGenlib );
assert( p->pGenlib == Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame()) );
Mio_LibraryDelete( p->pGenlib );
Abc_FrameSetLibGen(Abc_FrameGetGlobalFrame(), NULL);
}
if ( p->tTableC )
Map_SuperTableFree( p->tTableC );
......
......@@ -98,6 +98,9 @@ void Map_TruthsCut( Map_Man_t * p, Map_Cut_t * pCut )
return;
Map_TruthsCutOne( p, pCut, uTruth );
//assert( pCut->nLeaves < 5 );
//Rwt_ManExploreCount( uTruth[0] & 0xFFFF );
// compute the canonical form for the positive phase
Map_CanonComputeSlow( p->uTruths, p->nVarsMax, pCut->nLeaves, uTruth, uPhases, uCanon );
pCut->M[1].pSupers = Map_SuperTableLookupC( p->pSuperLib, uCanon );
......
......@@ -31,8 +31,9 @@
#include "vecFan.h"
#include "vecInt.h"
#include "vecPtr.h"
#include "vecStr.h"
#include "vecPtr.h"
#include "vecVec.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
......
......@@ -48,16 +48,12 @@ struct Vec_Ptr_t_
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
// iterators through entries
#define Vec_PtrForEachEntry( vVec, pEntry, i ) \
for ( i = 0; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryStart( vVec, pEntry, i, Start ) \
for ( i = Start; (i < Vec_PtrSize(vVec)) && (((pEntry) = Vec_PtrEntry(vVec, i)), 1); i++ )
#define Vec_PtrForEachEntryByLevel( vVec, pEntry, i, k ) \
for ( i = 0; i < Vec_PtrSize(vVec); i++ ) \
Vec_PtrForEachEntry( ((Vec_Ptr_t *)Vec_PtrEntry(vVec, i)), pEntry, k )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
......
/**CFile****************************************************************
FileName [vecVec.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Resizable arrays.]
Synopsis [Resizable vector of resizable vectors.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: vecVec.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __VEC_VEC_H__
#define __VEC_VEC_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include "extra.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
typedef struct Vec_Vec_t_ Vec_Vec_t;
struct Vec_Vec_t_
{
int nSize;
int nCap;
void ** pArray;
};
////////////////////////////////////////////////////////////////////////
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
// iterators through levels
#define Vec_VecForEachLevel( vGlob, vVec, i ) \
for ( i = 0; (i < Vec_VecSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelStart( vGlob, vVec, i, LevelStart ) \
for ( i = LevelStart; (i < Vec_PtrSize(vGlob)) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
#define Vec_VecForEachLevelStartStop( vGlob, vVec, i, LevelStart, LevelStop ) \
for ( i = LevelStart; (i <= LevelStop) && (((vVec) = Vec_VecEntry(vGlob, i)), 1); i++ )
// iteratores through entries
#define Vec_VecForEachEntry( vGlob, pEntry, i, k ) \
for ( i = 0; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryStart( vGlob, pEntry, i, k, LevelStart ) \
for ( i = LevelStart; i < Vec_VecSize(vGlob); i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
#define Vec_VecForEachEntryStartStop( vGlob, pEntry, i, k, LevelStart, LevelStop ) \
for ( i = LevelStart; i <= LevelStop; i++ ) \
Vec_PtrForEachEntry( Vec_VecEntry(vGlob, i), pEntry, k )
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Allocates a vector with the given capacity.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline Vec_Vec_t * Vec_VecAlloc( int nCap )
{
Vec_Vec_t * p;
p = ALLOC( Vec_Vec_t, 1 );
if ( nCap > 0 && nCap < 8 )
nCap = 8;
p->nSize = 0;
p->nCap = nCap;
p->pArray = p->nCap? ALLOC( void *, p->nCap ) : NULL;
return p;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_VecSize( Vec_Vec_t * p )
{
return p->nSize;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void * Vec_VecEntry( Vec_Vec_t * p, int i )
{
assert( i >= 0 && i < p->nSize );
return p->pArray[i];
}
/**Function*************************************************************
Synopsis [Frees the vector.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecFree( Vec_Vec_t * p )
{
Vec_Ptr_t * vVec;
int i;
Vec_VecForEachLevel( p, vVec, i )
Vec_PtrFree( vVec );
Vec_PtrFree( (Vec_Ptr_t *)p );
}
/**Function*************************************************************
Synopsis [Frees the vector of vectors.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_VecSizeSize( Vec_Vec_t * p )
{
Vec_Ptr_t * vVec;
int i, Counter = 0;
Vec_VecForEachLevel( p, vVec, i )
Counter += vVec->nSize;
return Counter;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecClear( Vec_Vec_t * p )
{
Vec_Ptr_t * vVec;
int i;
Vec_VecForEachLevel( p, vVec, i )
Vec_PtrClear( vVec );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_VecPush( Vec_Vec_t * p, int Level, void * Entry )
{
if ( p->nSize < Level + 1 )
{
int i;
Vec_PtrGrow( (Vec_Ptr_t *)p, Level + 1 );
for ( i = p->nSize; i < Level + 1; i++ )
p->pArray[i] = Vec_PtrAlloc( 0 );
p->nSize = Level + 1;
}
Vec_PtrPush( p->pArray[Level], Entry );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
#endif
/**CFile****************************************************************
FileName [rwr.h]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [External declarations.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwr.h,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#ifndef __RWR_H__
#define __RWR_H__
////////////////////////////////////////////////////////////////////////
/// INCLUDES ///
////////////////////////////////////////////////////////////////////////
#include "abc.h"
////////////////////////////////////////////////////////////////////////
/// PARAMETERS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// BASIC TYPES ///
////////////////////////////////////////////////////////////////////////
#define RWR_LIMIT 1048576/4 // ((1 << 20)
typedef struct Rwr_Node_t_ Rwr_Node_t;
struct Rwr_Node_t_ // 24 bytes
{
int Id; // ID
int TravId; // traversal ID
unsigned uTruth : 16; // truth table
unsigned Volume : 8; // volume
unsigned Level : 5; // level
unsigned fMark : 1; // mark
unsigned fUsed : 1; // mark
unsigned fExor : 1; // mark
Rwr_Node_t * p0; // first child
Rwr_Node_t * p1; // second child
Rwr_Node_t * pNext; // next in the table
};
typedef struct Rwr_Cut_t_ Rwr_Cut_t;
struct Rwr_Cut_t_ // 24 bytes
{
unsigned nLeaves : 3; // the number of leaves
unsigned fTime : 1; // set to 1 if meets the required times
unsigned fGain : 1; // set to 1 if does not increase nodes
unsigned Volume : 11; // the gain in the number of nodes
unsigned uTruth : 16; // the truth table
Abc_Obj_t * ppLeaves[4]; // the leaves
Rwr_Cut_t * pNext; // the next cut in the list
};
struct Abc_ManRwr_t_
{
// internal lookups
int nFuncs; // the number of four var functions
unsigned short * puCanons; // canonical forms
char * puPhases; // canonical phases
char * pPractical; // practical classes
unsigned short puPerms[256][16]; // permutations for three var functions
// node space
Vec_Ptr_t * vForest; // all the nodes
Rwr_Node_t ** pTable; // the hash table of nodes by their canonical form
Extra_MmFixed_t * pMmNode; // memory for nodes and cuts
int nTravIds; // the counter of traversal IDs
int nConsidered; // the number of nodes considered
int nAdded; // the number of nodes added to lists
int nClasses; // the number of NN classes
// intermediate data
Vec_Int_t * vFanNums; // the number of fanouts of each node (used to free cuts)
Vec_Int_t * vReqTimes; // the required times for each node (used for delay-driven evalution)
// the result of resynthesis
Vec_Int_t * vForm; // the decomposition tree (temporary)
Vec_Ptr_t * vFanins; // the fanins array (temporary)
Vec_Ptr_t * vTfo; // the TFO node array (temporary)
Vec_Vec_t * vLevels; // the levelized structure (temporary)
int nGainMax;
// runtime statistics
int time1;
int time2;
int time3;
int time4;
};
// manipulation of complemented attributes
static inline bool Rwr_IsComplement( Rwr_Node_t * p ) { return (bool)(((unsigned)p) & 01); }
static inline Rwr_Node_t * Rwr_Regular( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) & ~01); }
static inline Rwr_Node_t * Rwr_Not( Rwr_Node_t * p ) { return (Rwr_Node_t *)((unsigned)(p) ^ 01); }
static inline Rwr_Node_t * Rwr_NotCond( Rwr_Node_t * p, int c ) { return (Rwr_Node_t *)((unsigned)(p) ^ (c)); }
////////////////////////////////////////////////////////////////////////
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== rwrLib.c ==========================================================*/
extern void Rwr_ManPrecompute( Abc_ManRwr_t * p );
extern void Rwr_ManWriteToFile( Abc_ManRwr_t * p, char * pFileName );
extern void Rwr_ManLoadFromFile( Abc_ManRwr_t * p, char * pFileName );
extern void Rwr_ManPrint( Abc_ManRwr_t * p );
extern Rwr_Node_t * Rwr_ManAddVar( Abc_ManRwr_t * p, unsigned uTruth );
/*=== rwrMan.c ==========================================================*/
extern unsigned short Rwr_FunctionPhase( unsigned uTruth, unsigned uPhase );
/*=== rwrUtil.c ==========================================================*/
extern Vec_Int_t * Rwt_NtkFanoutCounters( Abc_Ntk_t * pNtk );
extern Vec_Int_t * Rwt_NtkRequiredLevels( Abc_Ntk_t * pNtk );
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
#endif
/**CFile****************************************************************
FileName [rwrCut.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Cut computation.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrCut.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static Rwr_Cut_t * Rwr_CutAlloc( Abc_ManRwr_t * p );
static Rwr_Cut_t * Rwr_CutCreateTriv( Abc_ManRwr_t * p, Abc_Obj_t * pNode );
static Rwr_Cut_t * Rwr_CutsMerge( Abc_ManRwr_t * p, Rwr_Cut_t * pCut0, Rwr_Cut_t * pCut1, int fCompl0, int fCompl1 );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Assigns elementary cuts to the PIs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkManRwrStartCuts( Abc_ManRwr_t * p, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i;
// set the trivial cuts
Abc_NtkCleanCopy( pNtk );
Abc_NtkForEachCi( pNtk, pNode, i )
pNode->pCopy = (Abc_Obj_t *)Rwr_CutCreateTriv( p, pNode );
// precompute the required times for all internal nodes
p->vFanNums = Rwt_NtkFanoutCounters( pNtk );
// save the fanout counters for all internal nodes
p->vReqTimes = Rwt_NtkRequiredLevels( pNtk );
}
/**Function*************************************************************
Synopsis [Computes cuts for one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeRwrComputeCuts( Abc_ManRwr_t * p, Abc_Obj_t * pNode )
{
Rwr_Cut_t * pCuts0, * pCuts1, * pTemp0, * pTemp1, * pCut;
Rwr_Cut_t * pList = NULL, ** ppPlace = &pList; // linked list of cuts
assert( Abc_ObjIsNode(pNode) );
if ( Abc_NodeIsConst(pNode) )
return;
// create the elementary cut
pCut = Rwr_CutCreateTriv( p, pNode );
// add it to the linked list
*ppPlace = pCut; ppPlace = &pCut->pNext;
// create cuts by merging pairwise
pCuts0 = (Rwr_Cut_t *)Abc_ObjFanin0(pNode)->pCopy;
pCuts1 = (Rwr_Cut_t *)Abc_ObjFanin1(pNode)->pCopy;
assert( pCuts0 && pCuts1 );
for ( pTemp0 = pCuts0; pTemp0; pTemp0 = pTemp0->pNext )
for ( pTemp1 = pCuts1; pTemp1; pTemp1 = pTemp1->pNext )
{
pCut = Rwr_CutsMerge( p, pTemp0, pTemp1, Abc_ObjFaninC0(pNode), Abc_ObjFaninC1(pNode) );
if ( pCut == NULL )
continue;
// add it to the linked list
*ppPlace = pCut; ppPlace = &pCut->pNext;
}
// set the linked list
pNode->pCopy = (Abc_Obj_t *)pList;
}
/**Function*************************************************************
Synopsis [Start the cut computation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwr_Cut_t * Rwr_CutsMerge( Abc_ManRwr_t * p, Rwr_Cut_t * pCut0, Rwr_Cut_t * pCut1, int fCompl0, int fCompl1 )
{
Abc_Obj_t * ppNodes[4], * pNodeTemp;
Rwr_Cut_t * pCut;
unsigned uPhase, uTruth0, uTruth1;
int i, k, min, nTotal;
// solve the most typical case: both cuts are four input
if ( pCut0->nLeaves == 4 && pCut1->nLeaves == 4 )
{
for ( i = 0; i < 4; i++ )
if ( pCut0->ppLeaves[i] != pCut1->ppLeaves[i] )
return NULL;
// create the cut
pCut = Rwr_CutAlloc( p );
pCut->nLeaves = 4;
for ( i = 0; i < 4; i++ )
pCut->ppLeaves[i] = pCut0->ppLeaves[i];
pCut->uTruth = (fCompl0? ~pCut0->uTruth : pCut0->uTruth) & (fCompl1? ~pCut1->uTruth : pCut1->uTruth) & 0xFFFF;
return pCut;
}
// create the set of new nodes
// count the number of unique entries in pCut1
nTotal = pCut0->nLeaves;
for ( i = 0; i < (int)pCut1->nLeaves; i++ )
{
// try to find this entry among the leaves of pCut0
for ( k = 0; k < (int)pCut0->nLeaves; k++ )
if ( pCut1->ppLeaves[i] == pCut0->ppLeaves[k] )
break;
if ( k < (int)pCut0->nLeaves ) // found
continue;
// we found a new entry to add
if ( nTotal == 4 )
return NULL;
ppNodes[nTotal++] = pCut1->ppLeaves[i];
}
// we know that the feasible cut exists
// add the starting entries
for ( k = 0; k < (int)pCut0->nLeaves; k++ )
ppNodes[k] = pCut0->ppLeaves[k];
// selection-sort the entries
for ( i = 0; i < nTotal - 1; i++ )
{
min = i;
for ( k = i+1; k < nTotal; k++ )
if ( ppNodes[k]->Id < ppNodes[min]->Id )
min = k;
pNodeTemp = ppNodes[i];
ppNodes[i] = ppNodes[min];
ppNodes[min] = pNodeTemp;
}
// find the mapping from the old nodes to the new
if ( pCut0->nLeaves == 4 )
uTruth0 = pCut0->uTruth;
else
{
uPhase = 0;
for ( i = 0; i < (int)pCut0->nLeaves; i++ )
{
for ( k = 0; k < nTotal; k++ )
if ( pCut0->ppLeaves[i] == ppNodes[k] )
break;
uPhase |= (1 << k);
}
assert( uPhase < 16 );
assert( pCut0->uTruth < 256 );
uTruth0 = p->puPerms[pCut0->uTruth][uPhase];
}
// find the mapping from the old nodes to the new
if ( pCut1->nLeaves == 4 )
uTruth1 = pCut1->uTruth;
else
{
uPhase = 0;
for ( i = 0; i < (int)pCut1->nLeaves; i++ )
{
for ( k = 0; k < nTotal; k++ )
if ( pCut1->ppLeaves[i] == ppNodes[k] )
break;
uPhase |= (1 << k);
}
assert( uPhase < 16 );
assert( pCut1->uTruth < 256 );
uTruth1 = p->puPerms[pCut1->uTruth][uPhase];
}
// create the cut
pCut = Rwr_CutAlloc( p );
pCut->nLeaves = nTotal;
for ( i = 0; i < nTotal; i++ )
pCut->ppLeaves[i] = ppNodes[i];
pCut->uTruth = (fCompl0? ~uTruth0 : uTruth0) & (fCompl1? ~uTruth1 : uTruth1) & 0xFFFF;
return pCut;
}
/**Function*************************************************************
Synopsis [Start the cut computation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwr_Cut_t * Rwr_CutAlloc( Abc_ManRwr_t * p )
{
Rwr_Cut_t * pCut;
pCut = (Rwr_Cut_t *)Extra_MmFixedEntryFetch( p->pMmNode );
memset( pCut, 0, sizeof(Rwr_Cut_t) );
return pCut;
}
/**Function*************************************************************
Synopsis [Start the cut computation.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwr_Cut_t * Rwr_CutCreateTriv( Abc_ManRwr_t * p, Abc_Obj_t * pNode )
{
Rwr_Cut_t * pCut;
pCut = Rwr_CutAlloc( p );
pCut->nLeaves = 1;
pCut->ppLeaves[0] = pNode;
pCut->uTruth = 0xAAAA;
return pCut;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwrDec.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Evaluation and decomposition procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrDec.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Rwr_CutEvaluate( Abc_ManRwr_t * p, Rwr_Cut_t * pCut );
static void Rwr_CutDecompose( Abc_ManRwr_t * p, Rwr_Cut_t * pCut, Vec_Int_t * vForm );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Performs rewriting for one node.]
Description [This procedure considers all the cuts computed for the node
and tries to rewrite each of them using the "forest" of different AIG
structures precomputed and stored in the RWR manager.
Determines the best rewriting and computes the gain in the number of AIG
nodes in the final network. In the end, p->vFanins contains information
about the best cut that can be used for rewriting, while p->vForm gives
the decomposition tree (represented using factored form data structure).
Returns gain in the number of nodes or -1 if node cannot be rewritten.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeRwrRewrite( Abc_ManRwr_t * p, Abc_Obj_t * pNode )
{
Vec_Ptr_t Vector = {0,0,0}, * vFanins = &Vector;
Rwr_Cut_t * pCut, * pCutBest;
int BestGain = -1;
int i, Required = Vec_IntEntry( p->vReqTimes, pNode->Id );
// go through the cuts
for ( pCut = (Rwr_Cut_t *)pNode->pCopy, pCut = pCut->pNext; pCut; pCut = pCut->pNext )
{
// collect the TFO
vFanins->nSize = pCut->nLeaves;
vFanins->pArray = pCut->ppLeaves;
Abc_NodeCollectTfoCands( pNode->pNtk, pNode, vFanins, Required, p->vLevels, p->vTfo );
// evaluate the cut
Rwr_CutEvaluate( p, pCut );
// check if the cut is the best
if ( pCut->fTime && pCut->fGain )
{
pCutBest = pCut;
BestGain = pCut->Volume;
}
}
if ( BestGain == -1 )
return -1;
// we found a good cut
// prepare the fanins
Vec_PtrClear( p->vFanins );
for ( i = 0; i < (int)pCutBest->nLeaves; i++ )
Vec_PtrPush( p->vFanins, pCutBest->ppLeaves[i] );
// collect the TFO again
Abc_NodeCollectTfoCands( pNode->pNtk, pNode, p->vFanins, Required, p->vLevels, p->vTfo );
// perform the decomposition
Rwr_CutDecompose( p, pCutBest, p->vForm );
// the best fanins are in p->vFanins, the result of decomposition is in p->vForm
return BestGain;
}
/**Function*************************************************************
Synopsis [Evaluates one cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_CutEvaluate( Abc_ManRwr_t * p, Rwr_Cut_t * pCut )
{
}
/**Function*************************************************************
Synopsis [Evaluates one cut.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_CutDecompose( Abc_ManRwr_t * p, Rwr_Cut_t * pCut, Vec_Int_t * vForm )
{
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwrExp.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Computation of practically used NN-classes of 4-input cuts.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrExp.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
typedef struct Abc_ManRwrExp_t_ Abc_ManRwrExp_t;
struct Abc_ManRwrExp_t_
{
// internal lookups
int nFuncs; // the number of four-var functions
unsigned short * puCanons; // canonical forms
int * pnCounts; // the counters of functions in each class
int nConsidered; // the number of nodes considered
int nClasses; // the number of NN classes
};
static Abc_ManRwrExp_t * s_pManRwrExp = NULL;
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Collects stats about 4-var functions appearing in netlists.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManExploreStart()
{
Abc_ManRwrExp_t * p;
unsigned uTruth;
int i, k, nClasses;
int clk = clock();
p = ALLOC( Abc_ManRwrExp_t, 1 );
memset( p, 0, sizeof(Abc_ManRwrExp_t) );
// canonical forms
p->nFuncs = (1<<16);
p->puCanons = ALLOC( unsigned short, p->nFuncs );
memset( p->puCanons, 0, sizeof(unsigned short) * p->nFuncs );
// counters
p->pnCounts = ALLOC( int, p->nFuncs );
memset( p->pnCounts, 0, sizeof(int) * p->nFuncs );
// initialize the canonical forms
nClasses = 1;
for ( i = 1; i < p->nFuncs-1; i++ )
{
if ( p->puCanons[i] )
continue;
nClasses++;
for ( k = 0; k < 32; k++ )
{
uTruth = Rwr_FunctionPhase( (unsigned)i, (unsigned)k );
if ( p->puCanons[uTruth] == 0 )
p->puCanons[uTruth] = (unsigned short)i;
else
assert( p->puCanons[uTruth] == (unsigned short)i );
}
}
// set info for constant 1
p->puCanons[p->nFuncs-1] = 0;
printf( "The number of NN-canonical forms = %d.\n", nClasses );
s_pManRwrExp = p;
}
/**Function*************************************************************
Synopsis [Collects stats about 4-var functions appearing in netlists.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManExploreCount( unsigned uTruth )
{
assert( uTruth < (1<<16) );
s_pManRwrExp->pnCounts[ s_pManRwrExp->puCanons[uTruth] ]++;
}
/**Function*************************************************************
Synopsis [Collects stats about 4-var functions appearing in netlists.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwt_ManExplorePrint()
{
FILE * pFile;
int i, CountMax, CountWrite, nCuts, nClasses;
int * pDistrib;
int * pReprs;
// find the max number of occurences
nCuts = nClasses = 0;
CountMax = 0;
for ( i = 0; i < s_pManRwrExp->nFuncs; i++ )
{
if ( CountMax < s_pManRwrExp->pnCounts[i] )
CountMax = s_pManRwrExp->pnCounts[i];
nCuts += s_pManRwrExp->pnCounts[i];
if ( s_pManRwrExp->pnCounts[i] > 0 )
nClasses++;
}
printf( "Number of cuts considered = %8d.\n", nCuts );
printf( "Classes occurring at least once = %8d.\n", nClasses );
// print the distribution of classes
pDistrib = ALLOC( int, CountMax + 1 );
pReprs = ALLOC( int, CountMax + 1 );
memset( pDistrib, 0, sizeof(int)*(CountMax + 1) );
for ( i = 0; i < s_pManRwrExp->nFuncs; i++ )
{
pDistrib[ s_pManRwrExp->pnCounts[i] ]++;
pReprs[ s_pManRwrExp->pnCounts[i] ] = i;
}
printf( "Occurence = %6d. Num classes = %4d. \n", 0, 2288-nClasses );
for ( i = 1; i <= CountMax; i++ )
if ( pDistrib[i] )
{
printf( "Occurence = %6d. Num classes = %4d. Repr = ", i, pDistrib[i] );
Extra_PrintBinary( stdout, (unsigned*)&(pReprs[i]), 16 );
printf( "\n" );
}
free( pDistrib );
free( pReprs );
// write into a file all classes above limit (5)
CountWrite = 0;
pFile = fopen( "nnclass_stats.txt", "w" );
for ( i = 0; i < s_pManRwrExp->nFuncs; i++ )
if ( s_pManRwrExp->pnCounts[i] > 5 )
{
fprintf( pFile, "%d ", i );
CountWrite++;
}
fclose( pFile );
printf( "%d classes written into file \"%s\".\n", CountWrite, "nnclass_stats.txt" );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwrLib.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrLib.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static Rwr_Node_t * Rwr_ManTryNode( Abc_ManRwr_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume );
static Rwr_Node_t * Rwr_ManAddNode( Abc_ManRwr_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume );
static int Rwr_ManNodeVolume( Abc_ManRwr_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 );
static void Rwr_ManIncTravId_int( Abc_ManRwr_t * p );
static inline void Rwr_ManIncTravId( Abc_ManRwr_t * p ) { if ( p->nTravIds++ == 0x8FFFFFFF ) Rwr_ManIncTravId_int( p ); }
static void Rwr_MarkUsed_rec( Abc_ManRwr_t * p, Rwr_Node_t * pNode );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Precomputes the forest in the manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManPrecompute( Abc_ManRwr_t * p )
{
Rwr_Node_t * p0, * p1;
int i, k, Level, Volume;
int LevelOld = -1;
int nNodes;
Vec_PtrForEachEntryStart( p->vForest, p0, i, 1 )
Vec_PtrForEachEntryStart( p->vForest, p1, k, 1 )
{
if ( LevelOld < (int)p0->Level )
{
LevelOld = p0->Level;
printf( "Starting level %d (at %d nodes).\n", LevelOld+1, i );
printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n",
p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i );
}
if ( k == i )
break;
// if ( p0->Level + p1->Level > 6 ) // hard
// break;
if ( p0->Level + p1->Level > 5 ) // easy
break;
// if ( p0->Level + p1->Level > 6 || (p0->Level == 3 && p1->Level == 3) )
// break;
// compute the level and volume of the new nodes
Level = 1 + ABC_MAX( p0->Level, p1->Level );
Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 );
// try four different nodes
Rwr_ManTryNode( p, p0 , p1 , 0, Level, Volume );
Rwr_ManTryNode( p, Rwr_Not(p0), p1 , 0, Level, Volume );
Rwr_ManTryNode( p, p0 , Rwr_Not(p1), 0, Level, Volume );
Rwr_ManTryNode( p, Rwr_Not(p0), Rwr_Not(p1), 0, Level, Volume );
// try EXOR
Rwr_ManTryNode( p, p0 , p1 , 1, Level, Volume + 1 );
// report the progress
if ( p->nConsidered % 50000000 == 0 )
printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n",
p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i );
// quit after some time
if ( p->vForest->nSize == RWR_LIMIT + 5 )
{
printf( "Considered = %5d M. Found = %8d. Classes = %6d. Trying %7d.\n",
p->nConsidered/1000000, p->vForest->nSize, p->nClasses, i );
goto save;
}
}
save :
// mark the relevant ones
Rwr_ManIncTravId( p );
k = 5;
nNodes = 0;
Vec_PtrForEachEntryStart( p->vForest, p0, i, 5 )
if ( p0->uTruth == p->puCanons[p0->uTruth] )
{
Rwr_MarkUsed_rec( p, p0 );
nNodes++;
}
// compact the array by throwing away non-canonical
k = 5;
Vec_PtrForEachEntryStart( p->vForest, p0, i, 5 )
if ( p0->fUsed )
{
p->vForest->pArray[k] = p0;
p0->Id = k;
k++;
}
p->vForest->nSize = k;
printf( "Total canonical = %4d. Total used = %5d.\n", nNodes, p->vForest->nSize );
}
/**Function*************************************************************
Synopsis [Writes to file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManWriteToFile( Abc_ManRwr_t * p, char * pFileName )
{
FILE * pFile;
Rwr_Node_t * pNode;
unsigned * pBuffer;
int i, nEntries, clk = clock();
// prepare the buffer
nEntries = p->vForest->nSize - 5;
pBuffer = ALLOC( unsigned, nEntries * 2 );
for ( i = 0; i < nEntries; i++ )
{
pNode = p->vForest->pArray[i+5];
pBuffer[2*i + 0] = (Rwr_Regular(pNode->p0)->Id << 1) | Rwr_IsComplement(pNode->p0);
pBuffer[2*i + 1] = (Rwr_Regular(pNode->p1)->Id << 1) | Rwr_IsComplement(pNode->p1);
// save EXOR flag
pBuffer[2*i + 0] = (pBuffer[2*i + 0] << 1) | pNode->fExor;
}
pFile = fopen( pFileName, "wb" );
fwrite( &nEntries, sizeof(int), 1, pFile );
fwrite( pBuffer, sizeof(unsigned), nEntries * 2, pFile );
free( pBuffer );
fclose( pFile );
printf( "The number of nodes saved = %d. ", nEntries ); PRT( "Saving", clock() - clk );
}
/**Function*************************************************************
Synopsis [Loads data from file.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManLoadFromFile( Abc_ManRwr_t * p, char * pFileName )
{
FILE * pFile;
Rwr_Node_t * p0, * p1;
unsigned * pBuffer;
int Level, Volume, nEntries, fExor;
int i, clk = clock();
// load the data
pFile = fopen( pFileName, "rb" );
if ( pFile == NULL )
{
printf( "Rwr_ManLoadFromFile: Cannot open file \"%s\".\n", pFileName );
return;
}
fread( &nEntries, sizeof(int), 1, pFile );
pBuffer = ALLOC( unsigned, nEntries * 2 );
fread( pBuffer, sizeof(unsigned), nEntries * 2, pFile );
fclose( pFile );
// reconstruct the forest
for ( i = 0; i < nEntries; i++ )
{
// get EXOR flag
fExor = (pBuffer[2*i + 0] & 1);
pBuffer[2*i + 0] = (pBuffer[2*i + 0] >> 1);
// get the nodes
p0 = p->vForest->pArray[pBuffer[2*i + 0] >> 1];
p1 = p->vForest->pArray[pBuffer[2*i + 1] >> 1];
// compute the level and volume of the new nodes
Level = 1 + ABC_MAX( p0->Level, p1->Level );
Volume = 1 + Rwr_ManNodeVolume( p, p0, p1 );
// set the complemented attributes
p0 = Rwr_NotCond( p0, (pBuffer[2*i + 0] & 1) );
p1 = Rwr_NotCond( p1, (pBuffer[2*i + 1] & 1) );
// add the node
// Rwr_ManTryNode( p, p0, p1, Level, Volume );
Rwr_ManAddNode( p, p0, p1, fExor, Level, Volume + fExor );
}
free( pBuffer );
printf( "The number of classes = %d. Canonical nodes = %d.\n", p->nClasses, p->nAdded );
printf( "The number of nodes loaded = %d. ", nEntries ); PRT( "Loading", clock() - clk );
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManIncTravId_int( Abc_ManRwr_t * p )
{
Rwr_Node_t * pNode;
int i;
Vec_PtrForEachEntry( p->vForest, pNode, i )
pNode->TravId = 0;
p->nTravIds = 1;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_MarkUsed_rec( Abc_ManRwr_t * p, Rwr_Node_t * pNode )
{
if ( pNode->fUsed || pNode->TravId == p->nTravIds )
return;
pNode->TravId = p->nTravIds;
pNode->fUsed = 1;
Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p0) );
Rwr_MarkUsed_rec( p, Rwr_Regular(pNode->p1) );
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_Trav_rec( Abc_ManRwr_t * p, Rwr_Node_t * pNode, int * pVolume )
{
if ( pNode->fMark || pNode->TravId == p->nTravIds )
return;
pNode->TravId = p->nTravIds;
(*pVolume)++;
if ( pNode->fExor )
(*pVolume)++;
Rwr_Trav_rec( p, Rwr_Regular(pNode->p0), pVolume );
Rwr_Trav_rec( p, Rwr_Regular(pNode->p1), pVolume );
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_Trav2_rec( Abc_ManRwr_t * p, Rwr_Node_t * pNode, int * pVolume )
{
if ( pNode->fMark || pNode->TravId == p->nTravIds )
return;
pNode->TravId = p->nTravIds;
(*pVolume)++;
Rwr_Trav2_rec( p, Rwr_Regular(pNode->p0), pVolume );
Rwr_Trav2_rec( p, Rwr_Regular(pNode->p1), pVolume );
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Rwr_ManNodeVolume( Abc_ManRwr_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1 )
{
int Volume = 0;
Rwr_ManIncTravId( p );
Rwr_Trav_rec( p, p0, &Volume );
Rwr_Trav_rec( p, p1, &Volume );
return Volume;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwr_Node_t * Rwr_ManTryNode( Abc_ManRwr_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume )
{
Rwr_Node_t * pOld, * pNew, ** ppPlace;
unsigned uTruth, uCanon;
// compute truth table, level, volume
p->nConsidered++;
if ( fExor )
{
// printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id );
uTruth = (p0->uTruth ^ p1->uTruth);
}
else
uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) &
(Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF;
uCanon = p->puCanons[uTruth];
// skip non-practical classes
if ( Level > 2 && p->pPractical[uCanon] == 0 )
return NULL;
// enumerate through the nodes with the same canonical form
ppPlace = p->pTable + uCanon;
for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext )
{
if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume )
return NULL;
if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume )
return NULL;
// if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume )
// return NULL;
}
// if ( fExor )
// printf( "Adding EXOR of %d and %d.\n", p0->Id, p1->Id );
// create the new node
pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode );
pNew->Id = p->vForest->nSize;
pNew->TravId = 0;
pNew->uTruth = uTruth;
pNew->Level = Level;
pNew->Volume = Volume;
pNew->fMark = 0;
pNew->fUsed = 0;
pNew->fExor = fExor;
pNew->p0 = p0;
pNew->p1 = p1;
pNew->pNext = NULL;
Vec_PtrPush( p->vForest, pNew );
*ppPlace = pNew;
if ( p->pTable[uCanon] == pNew )
p->nClasses++;
return pNew;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwr_Node_t * Rwr_ManAddNode( Abc_ManRwr_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume )
{
Rwr_Node_t * pOld, * pNew;
unsigned uTruth, uCanon;
// compute truth table, leve, volume
p->nConsidered++;
if ( fExor )
uTruth = (p0->uTruth ^ p1->uTruth);
else
uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) &
(Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF;
uCanon = p->puCanons[uTruth];
// skip non-practical classes
// if ( p->pPractical[uCanon] == 0 )
// return NULL;
// create the new node
pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode );
pNew->Id = p->vForest->nSize;
pNew->TravId = 0;
pNew->uTruth = uTruth;
pNew->Level = Level;
pNew->Volume = Volume;
pNew->fMark = 0;
pNew->fUsed = 0;
pNew->fExor = fExor;
pNew->p0 = p0;
pNew->p1 = p1;
pNew->pNext = NULL;
Vec_PtrPush( p->vForest, pNew );
// do not add if the node is not essential
if ( uTruth != uCanon )
return pNew;
// add to the list
p->nAdded++;
pOld = p->pTable[uCanon];
if ( pOld == NULL )
p->nClasses++;
pNew->pNext = pOld;
p->pTable[uCanon] = pNew;
return pNew;
}
/**Function*************************************************************
Synopsis [Adds one node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Rwr_Node_t * Rwr_ManAddVar( Abc_ManRwr_t * p, unsigned uTruth )
{
Rwr_Node_t * pNew;
pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode );
pNew->Id = p->vForest->nSize;
pNew->TravId = 0;
pNew->uTruth = uTruth;
pNew->Level = 0;
pNew->Volume = 0;
pNew->fMark = 1;
pNew->fUsed = 1;
pNew->fExor = 0;
pNew->p0 = NULL;
pNew->p1 = NULL; pNew->pNext = NULL;
Vec_PtrPush( p->vForest, pNew );
assert( p->pTable[p->puCanons[uTruth]] == NULL );
p->pTable[p->puCanons[uTruth]] = pNew;
return pNew;
}
/**Function*************************************************************
Synopsis [Prints one rwr node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_NodePrint_rec( FILE * pFile, Rwr_Node_t * pNode )
{
assert( !Rwr_IsComplement(pNode) );
if ( pNode->Id == 0 )
{
fprintf( pFile, "Const1" );
return;
}
if ( pNode->Id < 5 )
{
fprintf( pFile, "%c", 'a' + pNode->Id - 1 );
return;
}
if ( Rwr_IsComplement(pNode->p0) )
{
if ( Rwr_Regular(pNode->p0)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
fprintf( pFile, "\'" );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
fprintf( pFile, ")\'" );
}
}
else
{
if ( Rwr_Regular(pNode->p0)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p0) );
fprintf( pFile, ")" );
}
}
if ( pNode->fExor )
fprintf( pFile, "+" );
if ( Rwr_IsComplement(pNode->p1) )
{
if ( Rwr_Regular(pNode->p1)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
fprintf( pFile, "\'" );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
fprintf( pFile, ")\'" );
}
}
else
{
if ( Rwr_Regular(pNode->p1)->Id < 5 )
{
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
}
else
{
fprintf( pFile, "(" );
Rwr_NodePrint_rec( pFile, Rwr_Regular(pNode->p1) );
fprintf( pFile, ")" );
}
}
}
/**Function*************************************************************
Synopsis [Prints one rwr node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_NodePrint( FILE * pFile, Abc_ManRwr_t * p, Rwr_Node_t * pNode )
{
unsigned uTruth;
fprintf( pFile, "%5d :", pNode->Id );
fprintf( pFile, " tt=", pNode->Id );
uTruth = pNode->uTruth;
Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, " cn=", pNode->Id );
uTruth = p->puCanons[pNode->uTruth];
Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, " lev=%d", pNode->Level );
fprintf( pFile, " vol=%d", pNode->Volume );
fprintf( pFile, " " );
Rwr_NodePrint_rec( pFile, pNode );
fprintf( pFile, "\n" );
}
/**Function*************************************************************
Synopsis [Prints one rwr node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Rwr_ManPrint( Abc_ManRwr_t * p )
{
/*
Rwr_Node_t * pNode;
unsigned uTruth;
int Limit = 4;
int i;
for ( i = 0; i < p->nFuncs; i++ )
{
if ( p->pTable[i] == NULL )
continue;
if ( Limit-- == 0 )
break;
printf( "\nClass " );
uTruth = i;
Extra_PrintBinary( stdout, &uTruth, 16 );
printf( "\n" );
for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
if ( pNode->uTruth == p->puCanons[pNode->uTruth] )
Rwr_NodePrint( p, pNode );
}
*/
FILE * pFile;
Rwr_Node_t * pNode;
unsigned uTruth;
int Limit = 4;
int Counter;
int i;
pFile = fopen( "graph_lib.txt", "w" );
Counter = 0;
for ( i = 0; i < p->nFuncs; i++ )
{
if ( p->pTable[i] == NULL )
continue;
// if ( Limit-- == 0 )
// break;
fprintf( pFile, "\nClass %3d ", Counter++ );
// count the volume of the bush
{
int Volume = 0;
int nFuncs = 0;
Rwr_ManIncTravId( p );
for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
if ( pNode->uTruth == p->puCanons[pNode->uTruth] )
{
nFuncs++;
Rwr_Trav2_rec( p, pNode, &Volume );
}
fprintf( pFile, "Functions = %2d. Volume = %2d. ", nFuncs, Volume );
}
uTruth = i;
Extra_PrintBinary( pFile, &uTruth, 16 );
fprintf( pFile, "\n" );
for ( pNode = p->pTable[i]; pNode; pNode = pNode->pNext )
if ( pNode->uTruth == p->puCanons[pNode->uTruth] )
Rwr_NodePrint( pFile, p, pNode );
}
fclose( pFile );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwrMan.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrMan.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the following information was derived by computing all 4-input cuts of IWLS, MCNC, and ISCAS benchmarks
#define RWR_NUM_CLASSES 775
static int s_PracticalClasses[RWR_NUM_CLASSES] = {
0, 1, 3, 5, 6, 7, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 51, 53, 54, 55, 60, 61, 63, 85, 86,
87, 90, 91, 95, 102, 103, 105, 107, 111, 119, 123, 125, 126, 127, 255, 257, 258, 259, 260, 261, 262, 263, 264, 265,
266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 281, 282, 284, 286, 287, 288, 289, 290, 291, 293, 297,
298, 299, 300, 302, 303, 304, 305, 306, 307, 308, 310, 311, 312, 313, 315, 316, 317, 319, 320, 321, 323, 324, 325, 329,
332, 334, 335, 336, 337, 338, 340, 341, 342, 343, 345, 347, 349, 351, 352, 357, 358, 359, 361, 367, 368, 369, 371,
373, 375, 379, 381, 383, 384, 385, 386, 388, 389, 392, 393, 395, 397, 399, 400, 404, 408, 409, 416, 417, 419, 420,
421, 424, 425, 426, 427, 431, 433, 443, 448, 449, 451, 453, 456, 457, 459, 460, 461, 462, 463, 465, 476, 477, 480,
481, 483, 489, 492, 493, 494, 495, 496, 497, 499, 500, 501, 506, 507, 508, 509, 510, 771, 773, 774, 775, 780, 781,
783, 785, 786, 787, 788, 790, 791, 792, 796, 797, 799, 816, 817, 819, 820, 821, 834, 835, 836, 837, 838, 839, 840,
844, 847, 848, 849, 850, 851, 852, 853, 854, 855, 856, 859, 860, 861, 863, 864, 867, 870, 871, 876, 878, 880, 883,
884, 885, 887, 967, 973, 975, 979, 984, 988, 989, 990, 1009, 1011, 1012, 1013, 1020, 1285, 1286, 1287, 1290, 1291,
1295, 1297, 1298, 1300, 1301, 1303, 1307, 1308, 1309, 1311, 1314, 1316, 1317, 1318, 1319, 1322, 1325, 1327, 1329,
1330, 1331, 1332, 1333, 1334, 1335, 1336, 1338, 1340, 1341, 1360, 1361, 1363, 1365, 1367, 1380, 1381, 1382, 1383,
1390, 1392, 1395, 1397, 1399, 1440, 1445, 1447, 1450, 1451, 1455, 1458, 1461, 1463, 1467, 1525, 1530, 1542, 1543,
1545, 1547, 1551, 1553, 1554, 1558, 1559, 1561, 1567, 1569, 1570, 1572, 1574, 1576, 1587, 1588, 1590, 1591, 1596,
1618, 1620, 1621, 1623, 1624, 1632, 1638, 1641, 1647, 1654, 1655, 1680, 1686, 1687, 1689, 1695, 1718, 1776, 1782,
1785, 1799, 1803, 1805, 1806, 1807, 1811, 1813, 1815, 1823, 1826, 1831, 1843, 1844, 1847, 1859, 1860, 1863, 1875,
1877, 1879, 1895, 1902, 1904, 1911, 1912, 1927, 1928, 1933, 1935, 1945, 1956, 1957, 1959, 1962, 1964, 1965, 1975,
1979, 1987, 1991, 1995, 1996, 2000, 2002, 2007, 2013, 2023, 2032, 2040, 3855, 3857, 3859, 3861, 3864, 3866, 3867,
3868, 3869, 3870, 3891, 3892, 3893, 3900, 3921, 3925, 3942, 3945, 3956, 3960, 4080, 4369, 4370, 4371, 4372, 4373,
4374, 4375, 4376, 4377, 4378, 4379, 4380, 4381, 4382, 4386, 4387, 4388, 4389, 4391, 4392, 4394, 4396, 4403, 4405,
4408, 4409, 4411, 4420, 4421, 4422, 4423, 4424, 4426, 4428, 4437, 4439, 4445, 4488, 4494, 4505, 4507, 4509, 4522,
4524, 4525, 4526, 4539, 4540, 4542, 4556, 4557, 4573, 4574, 4590, 4626, 4627, 4629, 4630, 4631, 4632, 4634, 4638,
4641, 4643, 4648, 4659, 4680, 4695, 4698, 4702, 4713, 4731, 4740, 4758, 4766, 4773, 4791, 4812, 4830, 4845, 4883,
4885, 4887, 4888, 4891, 4892, 4899, 4903, 4913, 4914, 4915, 4934, 4940, 4945, 4947, 4949, 4951, 4972, 5005, 5011,
5017, 5019, 5029, 5043, 5049, 5058, 5059, 5060, 5068, 5075, 5079, 5083, 5084, 5100, 5140, 5141, 5142, 5143, 5148,
5160, 5171, 5174, 5180, 5182, 5185, 5186, 5187, 5189, 5205, 5207, 5214, 5238, 5245, 5246, 5250, 5270, 5278, 5290,
5310, 5315, 5335, 5355, 5397, 5399, 5401, 5402, 5405, 5413, 5414, 5415, 5418, 5427, 5429, 5445, 5457, 5460, 5461,
5463, 5469, 5482, 5522, 5525, 5533, 5540, 5546, 5557, 5565, 5571, 5580, 5589, 5593, 5605, 5610, 5654, 5673, 5692,
5698, 5729, 5734, 5782, 5790, 5796, 5814, 5826, 5846, 5911, 5931, 5965, 6001, 6066, 6120, 6168, 6174, 6180, 6206,
6210, 6229, 6234, 6270, 6273, 6279, 6363, 6375, 6425, 6427, 6438, 6446, 6451, 6457, 6478, 6482, 6485, 6489, 6502,
6545, 6553, 6564, 6570, 6594, 6617, 6630, 6682, 6683, 6685, 6686, 6693, 6709, 6741, 6746, 6817, 6821, 6826, 6833,
6849, 6885, 6939, 6940, 6951, 6963, 6969, 6990, 6997, 7065, 7077, 7089, 7140, 7196, 7212, 7219, 7220, 7228, 7230,
7251, 7324, 7356, 7361, 7363, 7372, 7377, 7395, 7453, 7470, 7475, 7495, 7509, 7513, 7526, 7619, 7633, 7650, 7710,
7725, 7731, 7740, 7755, 7770, 7800, 7815, 7830, 7845, 7860, 7890, 7905, 13107, 13109, 13110, 13116, 13141, 13146,
13161, 13164, 13621, 13622, 13626, 13651, 13653, 13658, 13669, 13670, 13763, 13765, 13770, 13878, 13881, 13884,
13910, 13923, 13926, 13932, 13971, 13974, 13980, 14022, 14025, 15420, 15445, 15450, 15462, 15465, 15555, 21845,
21846, 21850, 21865, 21866, 21930, 22102, 22105, 22106, 22117, 22118, 22122, 22165, 22166, 22169, 22170, 22181,
22182, 22185, 23130, 23142, 23145, 23205, 26214, 26217, 26985, 27030
};
static unsigned short Rwr_FunctionPerm( unsigned uTruth, int Phase );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Starts the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_ManRwr_t * Abc_NtkManRwrStart( char * pFileName )
{
Abc_ManRwr_t * p;
unsigned uTruth;
int i, k, nClasses;
int clk = clock();
p = ALLOC( Abc_ManRwr_t, 1 );
memset( p, 0, sizeof(Abc_ManRwr_t) );
// canonical forms
p->nFuncs = (1<<16);
p->puCanons = ALLOC( unsigned short, p->nFuncs );
memset( p->puCanons, 0, sizeof(unsigned short) * p->nFuncs );
// permutations
p->puPhases = ALLOC( char, p->nFuncs );
memset( p->puPhases, 0, sizeof(char) * p->nFuncs );
// hash table
p->pTable = ALLOC( Rwr_Node_t *, p->nFuncs );
memset( p->pTable, 0, sizeof(Rwr_Node_t *) * p->nFuncs );
// practical classes
p->pPractical = ALLOC( char, p->nFuncs );
memset( p->pPractical, 0, sizeof(char) * p->nFuncs );
// other stuff
p->vForest = Vec_PtrAlloc( 100 );
p->vForm = Vec_IntAlloc( 50 );
p->vFanins = Vec_PtrAlloc( 50 );
p->vTfo = Vec_PtrAlloc( 50 );
p->vLevels = Vec_VecAlloc( 50 );
p->pMmNode = Extra_MmFixedStart( sizeof(Rwr_Node_t) );
p->nTravIds = 1;
assert( sizeof(Rwr_Node_t) == sizeof(Rwr_Cut_t) );
// initialize the canonical forms
nClasses = 1;
for ( i = 1; i < p->nFuncs-1; i++ )
{
if ( p->puCanons[i] )
continue;
nClasses++;
for ( k = 0; k < 32; k++ )
{
uTruth = Rwr_FunctionPhase( (unsigned)i, (unsigned)k );
if ( p->puCanons[uTruth] == 0 )
{
p->puCanons[uTruth] = (unsigned short)i;
p->puPhases[uTruth] = (char)k;
}
else
assert( p->puCanons[uTruth] == (unsigned short)i );
}
}
// set info for constant 1
p->puCanons[p->nFuncs-1] = 0;
p->puPhases[p->nFuncs-1] = 16;
printf( "The number of NN-canonical forms = %d.\n", nClasses );
// initialize permutations
for ( i = 0; i < 256; i++ )
for ( k = 0; k < 16; k++ )
p->puPerms[i][k] = Rwr_FunctionPerm( i, k );
// initialize practical classes
for ( i = 0; i < RWR_NUM_CLASSES; i++ )
p->pPractical[ s_PracticalClasses[i] ] = 1;
// initialize forest
Rwr_ManAddVar( p, 0xFFFF ); // constant 1
Rwr_ManAddVar( p, 0xAAAA ); // var A
Rwr_ManAddVar( p, 0xCCCC ); // var B
Rwr_ManAddVar( p, 0xF0F0 ); // var C
Rwr_ManAddVar( p, 0xFF00 ); // var D
p->nClasses = 5;
PRT( "Manager startup time", clock() - clk );
// create the nodes
if ( pFileName == NULL )
{ // precompute
Rwr_ManPrecompute( p );
Rwr_ManWriteToFile( p, "data.aaa" );
}
else
{ // load previously saved nodes
Rwr_ManLoadFromFile( p, pFileName );
}
Rwr_ManPrint( p );
return p;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkManRwrStop( Abc_ManRwr_t * p )
{
if ( p->vFanNums ) Vec_IntFree( p->vFanNums );
if ( p->vReqTimes ) Vec_IntFree( p->vReqTimes );
Vec_IntFree( p->vForm );
Vec_PtrFree( p->vFanins );
Vec_PtrFree( p->vTfo );
Vec_VecFree( p->vLevels );
Vec_PtrFree( p->vForest );
Extra_MmFixedStop( p->pMmNode, 0 );
free( p->pPractical );
free( p->puCanons );
free( p->puPhases );
free( p->pTable );
free( p );
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NtkManRwrDecs( Abc_ManRwr_t * p )
{
return p->vForm;
}
/**Function*************************************************************
Synopsis [Stops the resynthesis manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Ptr_t * Abc_NtkManRwrFanins( Abc_ManRwr_t * p )
{
return p->vFanins;
}
/**Function*************************************************************
Synopsis [Computes a phase of the 4-var function.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned short Rwr_FunctionPhase( unsigned uTruth, unsigned uPhase )
{
static unsigned uMasks0[4] = { 0x5555, 0x3333, 0x0F0F, 0x00FF };
static unsigned uMasks1[4] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
int v, Shift;
for ( v = 0, Shift = 1; v < 4; v++, Shift <<= 1 )
if ( uPhase & Shift )
uTruth = (((uTruth & uMasks0[v]) << Shift) | ((uTruth & uMasks1[v]) >> Shift));
if ( uPhase & 16 )
uTruth = ~uTruth & 0xFFFF;
return uTruth;
}
/**Function*************************************************************
Synopsis [Computes a phase of the 3-var function.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
unsigned short Rwr_FunctionPerm( unsigned uTruth, int Phase )
{
static int Perm[16][4] = {
{ 0, 1, 2, 3 }, // 0000 - skip
{ 0, 1, 2, 3 }, // 0001 - skip
{ 1, 0, 2, 3 }, // 0010
{ 0, 1, 2, 3 }, // 0011 - skip
{ 2, 1, 0, 3 }, // 0100
{ 0, 2, 1, 3 }, // 0101
{ 2, 0, 1, 3 }, // 0110
{ 0, 1, 2, 3 }, // 0111 - skip
{ 3, 1, 2, 0 }, // 1000
{ 0, 3, 2, 1 }, // 1001
{ 3, 0, 2, 1 }, // 1010
{ 0, 1, 3, 2 }, // 1011
{ 2, 3, 0, 1 }, // 1100
{ 0, 3, 1, 2 }, // 1101
{ 3, 0, 1, 2 }, // 1110
{ 0, 1, 2, 3 } // 1111 - skip
};
int i, k, iRes;
unsigned uTruthRes;
assert( Phase < 16 );
uTruthRes = 0;
for ( i = 0; i < 16; i++ )
if ( uTruth & (1 << i) )
{
for ( iRes = 0, k = 0; k < 4; k++ )
if ( i & (1 << k) )
iRes |= (1 << Perm[Phase][k]);
uTruthRes |= (1 << iRes);
}
return uTruthRes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [rwrUtil.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [DAG-aware AIG rewriting package.]
Synopsis [Various utilities.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: rwrUtil.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "rwr.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Creates the array of fanout counters.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Rwt_NtkFanoutCounters( Abc_Ntk_t * pNtk )
{
Vec_Int_t * vFanNums;
Abc_Obj_t * pObj;
int i;
vFanNums = Vec_IntAlloc( 0 );
Vec_IntFill( vFanNums, Abc_NtkObjNumMax(pNtk), -1 );
Abc_NtkForEachObj( pNtk, pObj, i )
if ( Abc_ObjIsNode( pObj ) )
Vec_IntWriteEntry( vFanNums, i, Abc_ObjFanoutNum(pObj) );
return vFanNums;
}
/**Function*************************************************************
Synopsis [Creates the array of required times.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Rwt_NtkRequiredLevels( Abc_Ntk_t * pNtk )
{
Vec_Int_t * vReqTimes;
Vec_Ptr_t * vNodes;
Abc_Obj_t * pObj, * pFanout;
int i, k, nLevelsMax, nLevelsCur;
// start the required times
vReqTimes = Vec_IntAlloc( 0 );
Vec_IntFill( vReqTimes, Abc_NtkObjNumMax(pNtk), ABC_INFINITY );
// compute levels in reverse topological order
Abc_NtkForEachCo( pNtk, pObj, i )
Vec_IntWriteEntry( vReqTimes, pObj->Id, 0 );
vNodes = Abc_NtkDfsReverse( pNtk );
Vec_PtrForEachEntry( vNodes, pObj, i )
{
nLevelsCur = 0;
Abc_ObjForEachFanout( pObj, pFanout, k )
if ( nLevelsCur < Vec_IntEntry(vReqTimes, pFanout->Id) )
nLevelsCur = Vec_IntEntry(vReqTimes, pFanout->Id);
Vec_IntWriteEntry( vReqTimes, pObj->Id, nLevelsCur + 1 );
}
Vec_PtrFree( vNodes );
// convert levels into required times: RetTime = NumLevels + 1 - Level
nLevelsMax = Abc_AigGetLevelNum(pNtk) + 1;
Abc_NtkForEachNode( pNtk, pObj, i )
Vec_IntWriteEntry( vReqTimes, pObj->Id, nLevelsMax - Vec_IntEntry(vReqTimes, pObj->Id) );
// Abc_NtkForEachNode( pNtk, pObj, i )
// printf( "(%d,%d)", pObj->Level, Vec_IntEntry(vReqTimes, pObj->Id) );
// printf( "\n" );
return vReqTimes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -136,7 +136,7 @@ int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets )
{
Sim_Pat_t * pPat;
Vec_Int_t * vTargets;
Vec_Ptr_t * vNodesByLevel;
Vec_Vec_t * vNodesByLevel;
Abc_Obj_t * pNodeCi, * pNode;
int i, k, v, Output, LuckyPat, fType0, fType1;
int Counter = 0;
......@@ -147,7 +147,7 @@ int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets )
// complement the simulation info of the selected CI
Sim_UtilFlipSimInfo( p, pNodeCi );
// simulate the levelized structure of nodes
Vec_PtrForEachEntryByLevel( vNodesByLevel, pNode, i, k )
Vec_VecForEachEntry( vNodesByLevel, pNode, i, k )
{
fType0 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin0(pNode) );
fType1 = Abc_NodeIsTravIdCurrent( Abc_ObjFanin1(pNode) );
......@@ -213,7 +213,7 @@ int Sim_ComputeSuppRoundNode( Sim_Man_t * p, int iNumCi, bool fUseTargets )
}
}
}
Vec_PtrFreeFree( vNodesByLevel );
Vec_VecFree( vNodesByLevel );
return Counter;
}
......
......@@ -52,16 +52,17 @@ struct Ft_Node_t_
};
/*
The factored form of a SOP is an array (Vec_Int_t) of entries Ft_Node_t.
The factored form of an SOP is an array (Vec_Int_t) of entries of type Ft_Node_t.
If the SOP has n input variables (some of them may not be in the true support)
the first n entries of the factored form array have 0s. This representation
makes it each to translate the factored form into an AIG.
The node structure contains fanins of the node and their complemented attributes
(using AIG semantics). The elementary variable (buffer or interver) are
represented as a node with the same fanins. For example: x' = AND( x', x' ).
The constant node cannot be represented. Constant functions should be detected
before calling the factoring procedure.
the first n entries of the factored form array are zeros. The other entries of the array
represent the internal AND nodes of the factored form, and possibly the constant node.
This representation makes it easy to translate the factored form into an AIG.
The factored AND nodes contains fanins of the node and their complemented attributes
(using AIG semantics). The elementary variable (buffer or interver) are represented
as a node with the same fanins. For example: x' = AND( x', x' ).
The constant node is represented a special node with the constant flag set.
If the constant node and the elementary variable are present, no other internal
AND nodes are allowed in the factored form.
*/
// working with complemented attributes of objects
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment