Commit f2b6b3be by Alan Mishchenko

Version abc50813

parent 80983617
......@@ -197,6 +197,14 @@ SOURCE=.\src\base\abc\abcSat.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcSeq.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcSeqRetime.c
# End Source File
# Begin Source File
SOURCE=.\src\base\abc\abcShow.c
# End Source File
# Begin Source File
......
No preview for this file type
......@@ -6,13 +6,13 @@
--------------------Configuration: abc - Win32 Debug--------------------
</h3>
<h3>Command Lines</h3>
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DC.tmp" with contents
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP60E.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\base\abc\abcMap.c"
"C:\_projects\abc\src\base\abc\abc.c"
]
Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DC.tmp"
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DD.tmp" with contents
Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP60E.tmp"
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP60F.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
......@@ -59,6 +59,8 @@ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32
.\Debug\ioReadBlif.obj
.\Debug\ioReadPla.obj
.\Debug\ioReadVerilog.obj
.\Debug\ioUtil.obj
.\Debug\ioWriteBench.obj
.\Debug\ioWriteBlif.obj
.\Debug\ioWriteCnf.obj
.\Debug\ioWritePla.obj
......@@ -264,15 +266,15 @@ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32
.\Debug\safe_mem.obj
.\Debug\strsav.obj
.\Debug\texpand.obj
.\Debug\ioUtil.obj
.\Debug\ioWriteBench.obj
.\Debug\abcSeq.obj
.\Debug\abcSeqRetime.obj
]
Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DD.tmp"
Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP60F.tmp"
<h3>Output Window</h3>
Compiling...
abcMap.c
abc.c
Linking...
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DE.tmp" with contents
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP610.tmp" with contents
[
/nologo /o"Debug/abc.bsc"
.\Debug\abc.sbr
......@@ -319,6 +321,8 @@ Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DE.tmp" with conte
.\Debug\ioReadBlif.sbr
.\Debug\ioReadPla.sbr
.\Debug\ioReadVerilog.sbr
.\Debug\ioUtil.sbr
.\Debug\ioWriteBench.sbr
.\Debug\ioWriteBlif.sbr
.\Debug\ioWriteCnf.sbr
.\Debug\ioWritePla.sbr
......@@ -524,9 +528,9 @@ Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DE.tmp" with conte
.\Debug\safe_mem.sbr
.\Debug\strsav.sbr
.\Debug\texpand.sbr
.\Debug\ioUtil.sbr
.\Debug\ioWriteBench.sbr]
Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP4DE.tmp"
.\Debug\abcSeq.sbr
.\Debug\abcSeqRetime.sbr]
Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP610.tmp"
Creating browse info file...
<h3>Output Window</h3>
......
......@@ -69,6 +69,9 @@ static int Abc_CommandSuperChoice ( Abc_Frame_t * pAbc, int argc, char ** argv
static int Abc_CommandFpga ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSeq ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandRetime ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandCec ( Abc_Frame_t * pAbc, int argc, char ** argv );
static int Abc_CommandSec ( Abc_Frame_t * pAbc, int argc, char ** argv );
......@@ -130,6 +133,9 @@ void Abc_Init( Abc_Frame_t * pAbc )
Cmd_CommandAdd( pAbc, "FPGA mapping", "fpga", Abc_CommandFpga, 1 );
Cmd_CommandAdd( pAbc, "Sequential", "seq", Abc_CommandSeq, 1 );
Cmd_CommandAdd( pAbc, "Sequential", "retime", Abc_CommandRetime, 1 );
Cmd_CommandAdd( pAbc, "Verification", "cec", Abc_CommandCec, 0 );
Cmd_CommandAdd( pAbc, "Verification", "sec", Abc_CommandSec, 0 );
......@@ -170,21 +176,26 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
Abc_Ntk_t * pNtk;
bool fShort;
int c;
int fFactor;
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set the defaults
fShort = 1;
fShort = 1;
fFactor = 0;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "sh" ) ) != EOF )
while ( ( c = util_getopt( argc, argv, "sfh" ) ) != EOF )
{
switch ( c )
{
case 's':
fShort ^= 1;
break;
case 'f':
fFactor ^= 1;
break;
case 'h':
goto usage;
default:
......@@ -197,12 +208,13 @@ int Abc_CommandPrintStats( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( Abc_FrameReadErr(pAbc), "Empty network\n" );
return 1;
}
Abc_NtkPrintStats( pOut, pNtk );
Abc_NtkPrintStats( pOut, pNtk, fFactor );
return 0;
usage:
fprintf( pErr, "usage: print_stats [-h]\n" );
fprintf( pErr, "usage: print_stats [-fh]\n" );
fprintf( pErr, "\t prints the network statistics and\n" );
fprintf( pErr, "\t-f : toggles printing the literal count in the factored forms [default = %s]\n", fFactor? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
......@@ -2799,6 +2811,147 @@ usage:
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
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;
}
if ( !Abc_NtkIsAig(pNtk) )
{
fprintf( pErr, "Works only for AIG.\n" );
return 1;
}
// get the new network
pNtkRes = Abc_NtkAigToSeq( pNtk );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Converting to sequential AIG has failed.\n" );
return 1;
}
// replace the current network
Abc_FrameReplaceCurrentNetwork( pAbc, pNtkRes );
return 0;
usage:
fprintf( pErr, "usage: seq [-h]\n" );
fprintf( pErr, "\t converts AIG into sequential AIG (while sweeping latches)\n" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_CommandRetime( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk;
int c;
int fForward;
int fBackward;
extern Abc_Ntk_t * Abc_NtkSuperChoice( Abc_Ntk_t * pNtk );
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fForward = 0;
fBackward = 0;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "fbh" ) ) != EOF )
{
switch ( c )
{
case 'f':
fForward ^= 1;
break;
case 'b':
fBackward ^= 1;
break;
case 'h':
goto usage;
default:
goto usage;
}
}
if ( pNtk == NULL )
{
fprintf( pErr, "Empty network.\n" );
return 1;
}
if ( !Abc_NtkIsSeq(pNtk) )
{
fprintf( pErr, "Works only for sequential AIG.\n" );
return 1;
}
// get the new network
if ( fForward )
Abc_NtkSeqRetimeForward( pNtk );
else if ( fBackward )
Abc_NtkSeqRetimeBackward( pNtk );
else
Abc_NtkSeqRetimeDelay( pNtk );
return 0;
usage:
fprintf( pErr, "usage: retime [-fbh]\n" );
fprintf( pErr, "\t retimes sequential AIG (default is Pan's algorithm)\n" );
fprintf( pErr, "\t-f : toggle forward retiming [default = %s]\n", fForward? "yes": "no" );
fprintf( pErr, "\t-b : toggle backward retiming [default = %s]\n", fBackward? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
/**Function*************************************************************
......
......@@ -143,6 +143,7 @@ struct Abc_Ntk_t_
Vec_Ptr_t * vPtrTemp; // the temporary array
Vec_Int_t * vIntTemp; // the temporary array
Vec_Str_t * vStrTemp; // the temporary array
void * pData; // the temporary pointer
// the backup network and the step number
Abc_Ntk_t * pNetBackup; // the pointer to the previous backup network
int iStep; // the generation number for the given network
......@@ -180,6 +181,11 @@ struct Abc_ManRes_t_
/// MACRO DEFITIONS ///
////////////////////////////////////////////////////////////////////////
// maximum/minimum operators
#define ABC_MIN(a,b) (((a) < (b))? (a) : (b))
#define ABC_MAX(a,b) (((a) > (b))? (a) : (b))
#define ABC_INFINITY (10000000)
// reading data members of the network
static inline char * Abc_NtkName( Abc_Ntk_t * pNtk ) { return pNtk->pName; }
static inline char * Abc_NtkSpec( Abc_Ntk_t * pNtk ) { return pNtk->pSpec; }
......@@ -247,31 +253,6 @@ static inline Abc_Obj_t * Abc_ObjRegular( Abc_Obj_t * p ) { return (Abc_
static inline Abc_Obj_t * Abc_ObjNot( Abc_Obj_t * p ) { return (Abc_Obj_t *)((unsigned)(p) ^ 01); }
static inline Abc_Obj_t * Abc_ObjNotCond( Abc_Obj_t * p, int c ) { return (Abc_Obj_t *)((unsigned)(p) ^ (c)); }
// working with fanin/fanout edges
static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; }
static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; }
static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i){ return pObj->vFanins.pArray[i].iFan; }
static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].iFan; }
static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].iFan; }
static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ){ return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i].iFan ]; }
static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0].iFan ]; }
static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i].iFan ]; }
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 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; }
static inline int Abc_ObjFaninL( Abc_Obj_t * pObj, int i ){ return pObj->vFanins.pArray[i].nLats; }
static inline int Abc_ObjFaninL0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].nLats; }
static inline int Abc_ObjFaninL1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].nLats; }
static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) );}
static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) );}
static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl = 1; }
static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl ^= 1; }
static inline void Abc_ObjSetFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats = nLats; }
static inline void Abc_ObjAddFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats += nLats; }
// checking the object type
static inline bool Abc_ObjIsNode( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NODE; }
static inline bool Abc_ObjIsNet( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_NET; }
......@@ -283,6 +264,43 @@ static inline bool Abc_ObjIsCi( Abc_Obj_t * pObj ) { return pObj-
static inline bool Abc_ObjIsCo( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_LATCH; }
static inline bool Abc_ObjIsCio( Abc_Obj_t * pObj ) { return pObj->Type == ABC_OBJ_PI || pObj->Type == ABC_OBJ_PO || pObj->Type == ABC_OBJ_LATCH; }
// working with fanin/fanout edges
static inline int Abc_ObjFaninNum( Abc_Obj_t * pObj ) { return pObj->vFanins.nSize; }
static inline int Abc_ObjFanoutNum( Abc_Obj_t * pObj ) { return pObj->vFanouts.nSize; }
static inline int Abc_ObjFaninId( Abc_Obj_t * pObj, int i){ return pObj->vFanins.pArray[i].iFan; }
static inline int Abc_ObjFaninId0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].iFan; }
static inline int Abc_ObjFaninId1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].iFan; }
static inline Abc_Obj_t * Abc_ObjFanout( Abc_Obj_t * pObj, int i ){ return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[i].iFan ]; }
static inline Abc_Obj_t * Abc_ObjFanout0( Abc_Obj_t * pObj ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanouts.pArray[0].iFan ]; }
static inline Abc_Obj_t * Abc_ObjFanin( Abc_Obj_t * pObj, int i ) { return pObj->pNtk->vObjs->pArray[ pObj->vFanins.pArray[i].iFan ]; }
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 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; }
static inline int Abc_ObjFaninL( Abc_Obj_t * pObj, int i ){ return pObj->vFanins.pArray[i].nLats; }
static inline int Abc_ObjFaninL0( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[0].nLats; }
static inline int Abc_ObjFaninL1( Abc_Obj_t * pObj ) { return pObj->vFanins.pArray[1].nLats; }
static inline int Abc_ObjFaninLMin( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MIN( Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); }
static inline int Abc_ObjFaninLMax( Abc_Obj_t * pObj ) { assert( Abc_ObjIsNode(pObj) ); return ABC_MAX( Abc_ObjFaninL0(pObj), Abc_ObjFaninL1(pObj) ); }
static inline Abc_Obj_t * Abc_ObjChild( Abc_Obj_t * pObj, int i ) { return Abc_ObjNotCond( Abc_ObjFanin(pObj,i), Abc_ObjFaninC(pObj,i) );}
static inline Abc_Obj_t * Abc_ObjChild0( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin0(pObj), Abc_ObjFaninC0(pObj) ); }
static inline Abc_Obj_t * Abc_ObjChild1( Abc_Obj_t * pObj ) { return Abc_ObjNotCond( Abc_ObjFanin1(pObj), Abc_ObjFaninC1(pObj) ); }
static inline void Abc_ObjSetFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl = 1; }
static inline void Abc_ObjXorFaninC( Abc_Obj_t * pObj, int i ){ pObj->vFanins.pArray[i].fCompl ^= 1; }
static inline void Abc_ObjSetFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats = nLats; }
static inline void Abc_ObjSetFaninL0( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[0].nLats = nLats; }
static inline void Abc_ObjSetFaninL1( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[1].nLats = nLats; }
static inline void Abc_ObjAddFaninL( Abc_Obj_t * pObj, int i, int nLats ) { pObj->vFanins.pArray[i].nLats += nLats; }
static inline void Abc_ObjAddFaninL0( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[0].nLats += nLats; }
static inline void Abc_ObjAddFaninL1( Abc_Obj_t * pObj, int nLats ) { pObj->vFanins.pArray[1].nLats += nLats; }
extern int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout );
extern void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats );
extern void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats );
extern int Abc_ObjFanoutLMin( Abc_Obj_t * pObj );
extern int Abc_ObjFanoutLMax( Abc_Obj_t * pObj );
// checking the node type
static inline bool Abc_NodeIsAigAnd( Abc_Obj_t * pNode ) { assert(Abc_NtkIsAig(pNode->pNtk)); return Abc_ObjFaninNum(pNode) == 2; }
static inline bool Abc_NodeIsAigChoice( Abc_Obj_t * pNode ){ assert(Abc_NtkIsAig(pNode->pNtk)); return pNode->pData != NULL && Abc_ObjFanoutNum(pNode) > 0; }
......@@ -299,11 +317,6 @@ static inline void Abc_NodeSetTravIdPrevious( Abc_Obj_t * pNode ) { p
static inline bool Abc_NodeIsTravIdCurrent( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds); }
static inline bool Abc_NodeIsTravIdPrevious( Abc_Obj_t * pNode ) { return (bool)(pNode->TravId == pNode->pNtk->nTravIds - 1); }
// maximum/minimum operators
#define ABC_MIN(a,b) (((a) < (b))? (a) : (b))
#define ABC_MAX(a,b) (((a) > (b))? (a) : (b))
#define ABC_INFINITY (10000000)
// outputs the runtime in seconds
#define PRT(a,t) printf("%s = ", (a)); printf("%6.2f sec\n", (float)(t)/(float)(CLOCKS_PER_SEC))
......@@ -356,13 +369,18 @@ static inline bool Abc_NodeIsTravIdPrevious( Abc_Obj_t * pNode ) { r
////////////////////////////////////////////////////////////////////////
/*=== abcAig.c ==========================================================*/
extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk );
extern Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtk, bool fSeq );
extern Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, bool fSeq );
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 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 );
extern Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
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 bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode );
extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode );
/*=== abcAttach.c ==========================================================*/
......@@ -378,6 +396,7 @@ extern void Abc_NtkFreeGlobalBdds( DdManager * dd, Abc_Ntk_t * pNt
extern Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type );
extern Abc_Ntk_t * Abc_NtkStartFrom( Abc_Ntk_t * pNtk, Abc_NtkType_t Type );
extern void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
extern void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkStartRead( char * pName );
extern void Abc_NtkFinalizeRead( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk );
......@@ -385,6 +404,8 @@ extern Abc_Ntk_t * Abc_NtkSplitOutput( Abc_Ntk_t * pNtk, Abc_Obj_t * pNod
extern void Abc_NtkDelete( Abc_Ntk_t * pNtk );
extern void Abc_NtkFixNonDrivenNets( Abc_Ntk_t * pNtk );
extern Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj );
extern Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew );
extern Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew );
extern void Abc_NtkDeleteObj( Abc_Obj_t * pObj );
extern Abc_Obj_t * Abc_NtkFindNode( Abc_Ntk_t * pNtk, char * pName );
extern Abc_Obj_t * Abc_NtkFindCo( Abc_Ntk_t * pNtk, char * pName );
......@@ -462,7 +483,7 @@ extern Abc_Ntk_t * Abc_NtkLogicSopToNetlist( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk );
/*=== abcPrint.c ==========================================================*/
extern void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk );
extern void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored );
extern void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk );
extern void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk );
extern void Abc_NtkPrintFanio( FILE * pFile, Abc_Ntk_t * pNtk );
......@@ -481,6 +502,13 @@ extern void Abc_NtkManResStop( Abc_ManRes_t * p );
/*=== abcSat.c ==========================================================*/
extern bool Abc_NtkMiterSat( Abc_Ntk_t * pNtk, int fVerbose );
extern solver * Abc_NtkMiterSatCreate( Abc_Ntk_t * pNtk );
/*=== abcSeq.c ==========================================================*/
extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk );
extern int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk );
extern void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk );
extern void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk );
extern void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk );
/*=== abcSop.c ==========================================================*/
extern char * Abc_SopRegister( Extra_MmFlex_t * pMan, char * pName );
extern char * Abc_SopStart( Extra_MmFlex_t * pMan, int nCubes, int nVars );
......
......@@ -20,6 +20,23 @@
#include "abc.h"
/*
AIG is an And-Inv Graph with structural hashing.
It is always structurally hashed. It means that at any time:
- 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.
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)
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).
*/
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -27,12 +44,16 @@
// the simple AIG manager
struct Abc_Aig_t_
{
Abc_Ntk_t * pAig; // the AIG network
Abc_Obj_t * pConst1; // the constant 1 node
Abc_Obj_t ** pBins; // the table bins
int nBins; // the size of the table
int nEntries; // the total number of entries in the table
Vec_Ptr_t * vNodes; // the temporary array of nodes
Abc_Ntk_t * pNtkAig; // the AIG network
Abc_Obj_t * pConst1; // the constant 1 node
Abc_Obj_t * pReset; // the sequential reset node
Abc_Obj_t ** pBins; // the table bins
int nBins; // the size of the table
int nEntries; // the total number of entries in the table
Vec_Ptr_t * vNodes; // the temporary array of nodes
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
};
// iterators through the entries in the linked lists of nodes
......@@ -51,8 +72,15 @@ struct Abc_Aig_t_
static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)(p0) + (unsigned)(p1) * 12582917) % TableSize; }
//static inline unsigned Abc_HashKey2( Abc_Obj_t * p0, Abc_Obj_t * p1, int TableSize ) { return ((unsigned)((a)->Id + (b)->Id) * ((a)->Id + (b)->Id + 1) / 2) % TableSize; }
// static hash table procedures
static void Abc_AigResize( Abc_Aig_t * pMan );
// structural hash table procedures
static Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
static Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd );
static Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 );
static void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis );
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 );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
......@@ -69,7 +97,7 @@ static void Abc_AigResize( Abc_Aig_t * pMan );
SeeAlso []
***********************************************************************/
Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig, bool fSeq )
{
Abc_Aig_t * pMan;
// start the manager
......@@ -80,14 +108,38 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
pMan->pBins = ALLOC( Abc_Obj_t *, pMan->nBins );
memset( pMan->pBins, 0, sizeof(Abc_Obj_t *) * pMan->nBins );
pMan->vNodes = Vec_PtrAlloc( 100 );
pMan->vStackDelete = Vec_PtrAlloc( 100 );
pMan->vStackReplaceOld = Vec_PtrAlloc( 100 );
pMan->vStackReplaceNew = Vec_PtrAlloc( 100 );
// save the current network
pMan->pAig = pNtkAig;
pMan->pConst1 = Abc_NtkCreateNode( pNtkAig );
pMan->pNtkAig = pNtkAig;
pMan->pConst1 = Abc_NtkCreateNode( pNtkAig );
pMan->pReset = fSeq? Abc_NtkCreateNode( pNtkAig ) : NULL;
return pMan;
}
/**Function*************************************************************
Synopsis [Duplicated the AIG manager.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Aig_t * Abc_AigDup( Abc_Aig_t * pMan, bool fSeq )
{
Abc_Aig_t * pManNew;
pManNew = Abc_AigAlloc( pMan->pNtkAig, fSeq );
return pManNew;
}
/**Function*************************************************************
Synopsis [Deallocates the local AIG manager.]
Description []
......@@ -99,7 +151,13 @@ Abc_Aig_t * Abc_AigAlloc( Abc_Ntk_t * pNtkAig )
***********************************************************************/
void Abc_AigFree( Abc_Aig_t * pMan )
{
assert( Vec_PtrSize( pMan->vStackDelete ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceOld ) == 0 );
assert( Vec_PtrSize( pMan->vStackReplaceNew ) == 0 );
// free the table
Vec_PtrFree( pMan->vStackDelete );
Vec_PtrFree( pMan->vStackReplaceOld );
Vec_PtrFree( pMan->vStackReplaceNew );
Vec_PtrFree( pMan->vNodes );
free( pMan->pBins );
free( pMan );
......@@ -107,6 +165,90 @@ void Abc_AigFree( Abc_Aig_t * pMan )
/**Function*************************************************************
Synopsis [Returns the number of dangling nodes removed.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_AigCleanup( Abc_Aig_t * pMan )
{
Abc_Obj_t * pAnd;
int i, Counter;
// collect the AND nodes that do not fanout
assert( Vec_PtrSize( pMan->vStackDelete ) == 0 );
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
if ( Abc_ObjFanoutNum(pAnd) == 0 )
Vec_PtrPush( pMan->vStackDelete, pAnd );
// process the dangling nodes and their MFFCs
for ( Counter = 0; Vec_PtrSize(pMan->vStackDelete) > 0; Counter++ )
Abc_AigDelete_int( pMan );
return Counter;
}
/**Function*************************************************************
Synopsis [Makes sure that every node in the table is in the network and vice versa.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
bool Abc_AigCheck( Abc_Aig_t * pMan )
{
Abc_Obj_t * pObj, * pAnd;
int i, nFanins, Counter;
Abc_NtkForEachNode( pMan->pNtkAig, pObj, i )
{
nFanins = Abc_ObjFaninNum(pObj);
if ( nFanins == 0 )
{
if ( pObj != pMan->pConst1 && pObj != pMan->pReset )
{
printf( "Abc_AigCheck: The AIG has non-standard constant nodes.\n" );
return 0;
}
continue;
}
if ( nFanins == 1 )
{
printf( "Abc_AigCheck: The AIG has single input nodes.\n" );
return 0;
}
if ( nFanins > 2 )
{
printf( "Abc_AigCheck: The AIG has non-standard nodes.\n" );
return 0;
}
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;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
Counter++;
if ( Counter + 1 + Abc_NtkIsSeq(pMan->pNtkAig) != Abc_NtkNodeNum(pMan->pNtkAig) )
{
printf( "Abc_AigCheck: The number of nodes in the structural hashing table is wrong.\n", Counter );
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Read the constant 1 node.]
Description []
......@@ -123,6 +265,24 @@ Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan )
/**Function*************************************************************
Synopsis [Read the reset node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigReset( Abc_Aig_t * pMan )
{
return pMan->pReset;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
......@@ -132,7 +292,71 @@ Abc_Obj_t * Abc_AigConst1( Abc_Aig_t * pMan )
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
Abc_Obj_t * Abc_AigAndCreate( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd;
unsigned Key;
// check if it is a good time for table resizing
if ( pMan->nEntries > 2 * pMan->nBins )
Abc_AigResize( pMan );
// order the arguments
if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
pAnd = p0, p0 = p1, p1 = pAnd;
// create the new node
pAnd = Abc_NtkCreateNode( pMan->pNtkAig );
Abc_ObjAddFanin( pAnd, p0 );
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
// add the node to the corresponding linked list in the table
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
pMan->pBins[Key] = pAnd;
pMan->nEntries++;
return pAnd;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1, Abc_Obj_t * pAnd )
{
unsigned Key;
// order the arguments
if ( Abc_ObjRegular(p0)->Id > Abc_ObjRegular(p1)->Id )
pAnd = p0, p0 = p1, p1 = pAnd;
// create the new node
Abc_ObjAddFanin( pAnd, p0 );
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
// add the node to the corresponding linked list in the table
Key = Abc_HashKey2( p0, p1, pMan->nBins );
pAnd->pNext = pMan->pBins[Key];
pMan->pBins[Key] = pAnd;
return pAnd;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd;
unsigned Key;
......@@ -165,23 +389,106 @@ Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
Abc_ObjFaninC0(pAnd) == Abc_ObjIsComplement(p0) &&
Abc_ObjFaninC1(pAnd) == Abc_ObjIsComplement(p1) )
return pAnd;
// check if it is a good time for table resizing
if ( pMan->nEntries > 2 * pMan->nBins )
{
Abc_AigResize( pMan );
Key = Abc_HashKey2( p0, p1, pMan->nBins );
}
// create the new node
pAnd = Abc_NtkCreateNode( pMan->pAig );
Abc_ObjAddFanin( pAnd, p0 );
Abc_ObjAddFanin( pAnd, p1 );
// set the level of the new node
pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
// add the node to the corresponding linked list in the table
pAnd->pNext = pMan->pBins[Key];
pMan->pBins[Key] = pAnd;
pMan->nEntries++;
return pAnd;
return NULL;
}
/**Function*************************************************************
Synopsis [Deletes an AIG node from the hash table.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis )
{
Abc_Obj_t * pAnd, ** ppPlace;
unsigned Key;
assert( !Abc_ObjIsComplement(pThis) );
assert( Abc_ObjFanoutNum(pThis) == 0 );
assert( pMan->pNtkAig == pThis->pNtk );
// get the hash key for these two nodes
Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins );
// find the mataching node in the table
ppPlace = pMan->pBins + Key;
Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
if ( pAnd != pThis )
ppPlace = &pAnd->pNext;
else
{
*ppPlace = pAnd->pNext;
break;
}
assert( pAnd == pThis );
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigResize( Abc_Aig_t * pMan )
{
Abc_Obj_t ** pBinsNew;
Abc_Obj_t * pEnt, * pEnt2;
int nBinsNew, Counter, i, clk;
unsigned Key;
clk = clock();
// get the new table size
nBinsNew = Cudd_PrimeCopy(2 * pMan->nBins);
// allocate a new array
pBinsNew = ALLOC( Abc_Obj_t *, nBinsNew );
memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
{
Key = Abc_HashKey2( Abc_ObjFanin(pEnt,0), Abc_ObjFanin(pEnt,1), nBinsNew );
pEnt->pNext = pBinsNew[Key];
pBinsNew[Key] = pEnt;
Counter++;
}
assert( Counter == pMan->nEntries );
// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew );
// PRT( "Time", clock() - clk );
// replace the table and the parameters
free( pMan->pBins );
pMan->pBins = pBinsNew;
pMan->nBins = nBinsNew;
}
/**Function*************************************************************
Synopsis [Performs canonicization step.]
Description [The argument nodes can be complemented.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
{
Abc_Obj_t * pAnd;
if ( pAnd = Abc_AigAndLookup( pMan, p0, p1 ) )
return pAnd;
return Abc_AigAndCreate( pMan, p0, p1 );
}
/**Function*************************************************************
......@@ -243,6 +550,131 @@ Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
return pMiter;
}
/**Function*************************************************************
Synopsis [Replaces one AIG node by the other.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
{
assert( Vec_PtrSize(pMan->vStackReplaceOld) == 0 );
assert( Vec_PtrSize(pMan->vStackReplaceNew) == 0 );
assert( Vec_PtrSize(pMan->vStackDelete) == 0 );
Vec_PtrPush( pMan->vStackReplaceOld, pOld );
Vec_PtrPush( pMan->vStackReplaceNew, pNew );
while ( Vec_PtrSize(pMan->vStackReplaceOld) )
Abc_AigReplace_int( pMan );
while ( Vec_PtrSize(pMan->vStackDelete) )
Abc_AigDelete_int( pMan );
}
/**Function*************************************************************
Synopsis [Performs internal replacement step.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigReplace_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pOld, * pNew, * pFanin1, * pFanin2, * pFanout, * pFanoutNew;
int k, iFanin;
// get the pair of nodes to replace
assert( Vec_PtrSize(pMan->vStackReplaceOld) > 0 );
pOld = Vec_PtrPop( pMan->vStackReplaceOld );
pNew = Vec_PtrPop( pMan->vStackReplaceNew );
// make sure the old node is regular and has fanouts
// the new node can be complemented and can have fanouts
assert( !Abc_ObjIsComplement(pOld) == 0 );
assert( Abc_ObjFanoutNum(pOld) > 0 );
// look at the fanouts of old node
Abc_NodeCollectFanouts( pOld, pMan->vNodes );
Vec_PtrForEachEntry( pMan->vNodes, pFanout, k )
{
if ( Abc_ObjIsCo(pFanout) )
{
Abc_ObjPatchFanin( pFanout, pOld, pNew );
continue;
}
// find the old node as a fanin of this fanout
iFanin = Vec_FanFindEntry( &pFanout->vFanins, pOld->Id );
assert( iFanin == 0 || iFanin == 1 );
// get the new fanin
pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) );
// get another fanin
pFanin2 = Abc_ObjChild( pFanout, iFanin ^ 1 );
// check if the node with these fanins exists
if ( pFanoutNew = Abc_AigAndLookup( pMan, pFanin1, pFanin2 ) )
{ // such node exists (it may be a constant)
// schedule replacement of the old fanout by the new fanout
Vec_PtrPush( pMan->vStackReplaceOld, pFanout );
Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew );
continue;
}
// such node does not exist - modify the old fanout
// remove the old fanout from the table
Abc_AigAndDelete( pMan, pFanout );
// remove its old fanins
Abc_ObjRemoveFanins( pFanout );
// update the old fanout with new fanins and add it to the table
Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout );
}
// schedule deletion of the old node
Vec_PtrPush( pMan->vStackDelete, pOld );
}
/**Function*************************************************************
Synopsis [Performs internal deletion step.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigDelete_int( Abc_Aig_t * pMan )
{
Abc_Obj_t * pNode, * pFanin;
int k;
// get the node to delete
assert( Vec_PtrSize(pMan->vStackDelete) > 0 );
pNode = Vec_PtrPop( pMan->vStackDelete );
// make sure the node is regular and dangling
assert( !Abc_ObjIsComplement(pNode) == 0 );
assert( Abc_ObjFanoutNum(pNode) == 0 );
// skip the constant node
if ( pNode == pMan->pConst1 )
return;
// schedule fanins for deletion if they dangle
Abc_ObjForEachFanin( pNode, pFanin, k )
{
assert( Abc_ObjFanoutNum(pFanin) > 0 );
if ( Abc_ObjFanoutNum(pFanin) == 1 )
Vec_PtrPush( pMan->vStackDelete, pFanin );
}
// remove the node from the table
Abc_AigAndDelete( pMan, pNode );
// remove the node fro the network
Abc_NtkDeleteObj( pNode );
}
/**Function*************************************************************
Synopsis [Returns 1 if the node has at least one complemented fanout.]
......@@ -298,51 +730,6 @@ bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
return 0;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_AigResize( Abc_Aig_t * pMan )
{
Abc_Obj_t ** pBinsNew;
Abc_Obj_t * pEnt, * pEnt2;
int nBinsNew, Counter, i, clk;
unsigned Key;
clk = clock();
// get the new table size
nBinsNew = Cudd_PrimeCopy(2 * pMan->nBins);
// allocate a new array
pBinsNew = ALLOC( Abc_Obj_t *, nBinsNew );
memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew );
// rehash the entries from the old table
Counter = 0;
for ( i = 0; i < pMan->nBins; i++ )
Abc_AigBinForEachEntrySafe( pMan->pBins[i], pEnt, pEnt2 )
{
Key = Abc_HashKey2( Abc_ObjFanin(pEnt,0), Abc_ObjFanin(pEnt,1), nBinsNew );
pEnt->pNext = pBinsNew[Key];
pBinsNew[Key] = pEnt;
Counter++;
}
assert( Counter == pMan->nEntries );
// printf( "Increasing the structural table size from %6d to %6d. ", pMan->nBins, nBinsNew );
// PRT( "Time", clock() - clk );
// replace the table and the parameters
free( pMan->pBins );
pMan->pBins = pBinsNew;
pMan->nBins = nBinsNew;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -32,8 +32,6 @@ static Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type );
static void Abc_ObjRecycle( Abc_Obj_t * pObj );
static void Abc_ObjAdd( Abc_Obj_t * pObj );
extern void Extra_StopManager( DdManager * dd );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -78,7 +76,9 @@ Abc_Ntk_t * Abc_NtkAlloc( Abc_NtkType_t Type )
else if ( Abc_NtkIsLogicBdd(pNtk) )
pNtk->pManFunc = Cudd_Init( 20, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
else if ( Abc_NtkIsAig(pNtk) )
pNtk->pManFunc = Abc_AigAlloc( pNtk );
pNtk->pManFunc = Abc_AigAlloc( pNtk, 0 );
else if ( Abc_NtkIsSeq(pNtk) )
pNtk->pManFunc = Abc_AigAlloc( pNtk, 1 );
else if ( Abc_NtkIsMapped(pNtk) )
pNtk->pManFunc = Abc_FrameReadLibGen(Abc_FrameGetGlobalFrame());
else
......@@ -155,6 +155,30 @@ void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
/**Function*************************************************************
Synopsis [Finalizes the network adding latches to CI/CO lists and creates their names.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkFinalizeLatches( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pLatch;
int i;
// set the COs of the strashed network
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
Vec_PtrPush( pNtk->vCis, pLatch );
Vec_PtrPush( pNtk->vCos, pLatch );
Abc_NtkLogicStoreName( pLatch, Abc_ObjNameSuffix(pLatch, "L") );
}
}
/**Function*************************************************************
Synopsis [Starts a new network using existing network as a model.]
Description []
......@@ -564,16 +588,19 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
{
Abc_Obj_t * pObjNew;
pObjNew = Abc_ObjAlloc( pNtkNew, pObj->Type );
if ( Abc_ObjIsNode(pObj) ) // copy the function
if ( Abc_ObjIsNode(pObj) ) // copy the function if network is the same type
{
if ( Abc_NtkIsSop(pNtkNew) )
pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData );
else if ( Abc_NtkIsLogicBdd(pNtkNew) )
pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData);
else if ( Abc_NtkIsMapped(pNtkNew) )
pObjNew->pData = pObj->pData;
else if ( !Abc_NtkIsAig(pNtkNew) )
assert( 0 );
if ( pNtkNew->Type == pObj->pNtk->Type || Abc_NtkIsNetlist(pObj->pNtk) || Abc_NtkIsNetlist(pNtkNew) )
{
if ( Abc_NtkIsSop(pNtkNew) )
pObjNew->pData = Abc_SopRegister( pNtkNew->pManFunc, pObj->pData );
else if ( Abc_NtkIsLogicBdd(pNtkNew) )
pObjNew->pData = Cudd_bddTransfer(pObj->pNtk->pManFunc, pNtkNew->pManFunc, pObj->pData), Cudd_Ref(pObjNew->pData);
else if ( Abc_NtkIsMapped(pNtkNew) )
pObjNew->pData = pObj->pData;
else if ( !Abc_NtkIsAig(pNtkNew) )
assert( 0 );
}
}
else if ( Abc_ObjIsNet(pObj) ) // copy the name
pObjNew->pData = Abc_NtkRegisterName( pNtkNew, pObj->pData );
......@@ -587,6 +614,55 @@ Abc_Obj_t * Abc_NtkDupObj( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj )
/**Function*************************************************************
Synopsis [Creates a new constant node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkDupConst1( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew )
{
Abc_Obj_t * pConst1;
assert( Abc_NtkIsAig(pNtkAig) );
pConst1 = Abc_AigConst1(pNtkAig->pManFunc);
if ( Abc_ObjFanoutNum( pConst1 ) > 0 )
pConst1->pCopy = Abc_NodeCreateConst1( pNtkNew );
return pConst1->pCopy;
}
/**Function*************************************************************
Synopsis [Creates a new constant node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Abc_NtkDupReset( Abc_Ntk_t * pNtkAig, Abc_Ntk_t * pNtkNew )
{
Abc_Obj_t * pReset, * pConst1;
assert( Abc_NtkIsAig(pNtkAig) );
assert( Abc_NtkIsLogicSop(pNtkNew) );
pReset = Abc_AigReset(pNtkAig->pManFunc);
if ( Abc_ObjFanoutNum( pReset ) > 0 )
{
// create new latch with reset value 0
pReset->pCopy = Abc_NtkCreateLatch( pNtkNew );
// add constant node fanin to the latch
pConst1 = Abc_AigConst1(pNtkAig->pManFunc);
Abc_ObjAddFanin( pReset->pCopy, pConst1->pCopy );
}
return pReset->pCopy;
}
/**Function*************************************************************
Synopsis [Deletes the object from the network.]
Description []
......@@ -614,6 +690,7 @@ void Abc_NtkDeleteObj( Abc_Obj_t * pObj )
// remove from the list of objects
Vec_PtrWriteEntry( pNtk->vObjs, pObj->Id, NULL );
pObj->Id = (1<<26)-1;
pNtk->nObjs--;
// perform specialized operations depending on the object type
......@@ -625,8 +702,8 @@ void Abc_NtkDeleteObj( Abc_Obj_t * pObj )
printf( "Error: The net is not in the table...\n" );
assert( 0 );
}
pObj->pData = NULL;
pNtk->nNets--;
assert( !Abc_ObjIsPi(pObj) && !Abc_ObjIsPo(pObj) );
}
else if ( Abc_ObjIsNode(pObj) )
{
......@@ -898,6 +975,8 @@ Abc_Obj_t * Abc_NodeCreateConst0( Abc_Ntk_t * pNtk )
Abc_Obj_t * Abc_NodeCreateConst1( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
if ( Abc_NtkIsAig(pNtk) || Abc_NtkIsSeq(pNtk) )
return Abc_AigConst1(pNtk->pManFunc);
pNode = Abc_NtkCreateNode( pNtk );
if ( Abc_NtkIsSop(pNtk) )
pNode->pData = Abc_SopRegister( pNtk->pManFunc, " 1\n" );
......
......@@ -230,15 +230,21 @@ Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk )
assert( Abc_NtkIsAig(pNtk) );
// start the network
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC_SOP );
// create the constant node
Abc_NtkDupConst1( pNtk, pNtkNew );
// duplicate the nodes and create node functions
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( Abc_NodeIsConst(pObj) )
continue;
Abc_NtkDupObj(pNtkNew, pObj);
pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
}
// create the choice nodes
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( Abc_NodeIsConst(pObj) )
continue;
if ( !Abc_NodeIsAigChoice(pObj) )
continue;
// create an OR gate
......@@ -255,12 +261,10 @@ Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk )
// set the new node
pObj->pCopy = pNodeNew;
}
// connect the objects
// connect the objects, including the COs
Abc_NtkForEachObj( pNtk, pObj, i )
Abc_ObjForEachFanin( pObj, pFanin, k )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
// connect the COs
Abc_NtkFinalize( pNtk, pNtkNew );
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// duplicate the EXDC Ntk
......@@ -299,6 +303,8 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
printf( "Warning: Choice nodes are skipped.\n" );
// start the network
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC_SOP );
// create the constant node
Abc_NtkDupConst1( pNtk, pNtkNew );
// collect the nodes to be used (marks all nodes with current TravId)
vNodes = Abc_NtkDfs( pNtk );
// create inverters for the CI and remember them
......@@ -308,8 +314,11 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
// duplicate the nodes, create node functions, and inverters
Vec_PtrForEachEntry( vNodes, pObj, i )
{
Abc_NtkDupObj( pNtkNew, pObj );
pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2 );
if ( !Abc_NodeIsConst(pObj) )
{
Abc_NtkDupObj( pNtkNew, pObj );
pObj->pCopy->pData = Abc_SopCreateAnd( pNtkNew->pManFunc, 2 );
}
if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
pObj->pCopy->pCopy = Abc_NodeCreateInv( pNtkNew, pObj->pCopy );
}
......@@ -324,7 +333,14 @@ Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
}
Vec_PtrFree( vNodes );
// connect the COs
Abc_NtkFinalize( pNtk, pNtkNew );
Abc_NtkForEachCo( pNtk, pObj, i )
{
pFanin = Abc_ObjFanin0(pObj);
if ( Abc_ObjFaninC0( pObj ) )
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
else
Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
}
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// duplicate the EXDC Ntk
......
......@@ -40,11 +40,15 @@
SeeAlso []
***********************************************************************/
void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk )
void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
{
fprintf( pFile, "%-15s:", pNtk->pName );
fprintf( pFile, " i/o = %3d/%3d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk) );
fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) );
if ( !Abc_NtkIsSeq(pNtk) )
fprintf( pFile, " lat = %4d", Abc_NtkLatchNum(pNtk) );
else
fprintf( pFile, " lat = %4d", Abc_NtkSeqLatchNum(pNtk) );
if ( Abc_NtkIsNetlist(pNtk) )
{
......@@ -56,14 +60,17 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
fprintf( pFile, " choice = %5d", Abc_NtkCountChoiceNodes(pNtk) );
}
else if ( Abc_NtkIsSeq(pNtk) )
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
else
fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
if ( Abc_NtkIsLogicSop(pNtk) )
{
fprintf( pFile, " cube = %5d", Abc_NtkGetCubeNum(pNtk) );
fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) );
fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) );
// fprintf( pFile, " lit(sop) = %5d", Abc_NtkGetLitNum(pNtk) );
if ( fFactored )
fprintf( pFile, " lit(fac) = %5d", Abc_NtkGetLitFactNum(pNtk) );
}
else if ( Abc_NtkIsLogicBdd(pNtk) )
fprintf( pFile, " bdd = %5d", Abc_NtkGetBddNodeNum(pNtk) );
......@@ -72,11 +79,14 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk )
fprintf( pFile, " area = %5.2f", Abc_NtkGetMappedArea(pNtk) );
fprintf( pFile, " delay = %5.2f", Abc_NtkDelayTrace(pNtk) );
}
else if ( !Abc_NtkIsAig(pNtk) )
else if ( !Abc_NtkIsAig(pNtk) && !Abc_NtkIsSeq(pNtk) )
{
assert( 0 );
}
fprintf( pFile, " lev = %2d", Abc_NtkGetLevelNum(pNtk) );
if ( !Abc_NtkIsSeq(pNtk) )
fprintf( pFile, " lev = %2d", Abc_NtkGetLevelNum(pNtk) );
fprintf( pFile, "\n" );
}
......
/**CFile****************************************************************
FileName [abcSeq.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis []
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcSeq.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
/*
A sequential network is an AIG whose edges have number-of-latches attributes,
in addition to the complemented attibutes.
The sets of PIs/POs remain the same as in logic network.
Constant 1 node can only be used as a fanin of a PO node and reset node.
The reset node producing sequence (01111...) is used to create the
initialization logic of all latches.
The latches do not have explicit initial state but they are implicitly
reset by the reset node.
*/
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk );
static void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers );
static void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew );
static void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Converts a normal AIG into a sequential AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
assert( Abc_NtkIsAig(pNtk) );
// start the network
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_SEQ );
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Converts a sequential AIG into a logic SOP network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk )
{
int fCheck = 1;
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pFanin, * pFaninNew;
int i, k;
assert( Abc_NtkIsSeq(pNtk) );
// start the network
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC_SOP );
// create the constant and reset nodes
Abc_NtkDupConst1( pNtk, pNtkNew );
Abc_NtkDupReset( pNtk, pNtkNew );
// duplicate the nodes, create node functions and latches
Abc_NtkForEachNode( pNtk, pObj, i )
{
if ( Abc_NodeIsConst(pObj) )
continue;
Abc_NtkDupObj(pNtkNew, pObj);
pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
}
// create latches for the new nodes
Abc_NtkSeqCreateLatches( pNtk, pNtkNew );
// connect the objects
Abc_NtkForEachObj( pNtk, pObj, i )
Abc_ObjForEachFanin( pObj, pFanin, k )
{
// find the fanin
pFaninNew = pFanin->pCopy;
for ( i = 0; i < Abc_ObjFaninL(pObj, k); i++ )
pFaninNew = pFaninNew->pCopy;
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
}
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
// duplicate the EXDC network
if ( pNtk->pExdc )
fprintf( stdout, "Warning: EXDC network is not copied.\n" );
if ( fCheck && !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkSeqToLogic(): Network check has failed.\n" );
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Finds max number of latches on the fanout edges of each node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Abc_NtkSeqCountLatches( Abc_Ntk_t * pNtk )
{
Vec_Int_t * vNumbers;
Abc_Obj_t * pObj;
int i;
assert( Abc_NtkIsSeq( pNtk ) );
// start the array of counters
vNumbers = Vec_IntAlloc( 0 );
Vec_IntFill( vNumbers, Abc_NtkObjNum(pNtk), 0 );
// count for each edge
Abc_NtkForEachObj( pNtk, pObj, i )
Abc_NodeSeqCountLatches( pObj, vNumbers );
return vNumbers;
}
/**Function*************************************************************
Synopsis [Countes the latch numbers due to the fanins edges of the given node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeSeqCountLatches( Abc_Obj_t * pObj, Vec_Int_t * vNumbers )
{
Abc_Obj_t * pFanin;
int k, nLatches;
// go through each fanin edge
Abc_ObjForEachFanin( pObj, pFanin, k )
{
nLatches = Abc_ObjFaninL( pObj, k );
if ( nLatches == 0 )
continue;
if ( Vec_IntEntry( vNumbers, pFanin->Id ) < nLatches )
Vec_IntWriteEntry( vNumbers, pFanin->Id, nLatches );
}
}
/**Function*************************************************************
Synopsis [Creates latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkSeqCreateLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew )
{
Vec_Int_t * vNumbers;
Abc_Obj_t * pObj;
int i;
assert( Abc_NtkIsSeq( pNtk ) );
// create latches for each new object according to the counters
vNumbers = Abc_NtkSeqCountLatches( pNtk );
Abc_NtkForEachObj( pNtk, pObj, i )
Abc_NodeSeqCreateLatches( pObj->pCopy, Vec_IntEntry(vNumbers, pObj->Id) );
Vec_IntFree( vNumbers );
// add latch to the PI/PO lists, create latch names
Abc_NtkFinalizeLatches( pNtkNew );
}
/**Function*************************************************************
Synopsis [Creates the given number of latches for this object.]
Description [The latches are attached to the node and to each other
through the pCopy field.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NodeSeqCreateLatches( Abc_Obj_t * pObj, int nLatches )
{
Abc_Ntk_t * pNtk = pObj->pNtk;
Abc_Obj_t * pLatch, * pFanin;
int i;
pFanin = pObj;
for ( i = 0, pFanin = pObj; i < nLatches; pFanin = pLatch, i++ )
{
pLatch = Abc_NtkCreateLatch( pNtk );
Abc_ObjAddFanin( pLatch, pFanin );
pFanin->pCopy = pLatch;
}
}
/**Function*************************************************************
Synopsis [Counters the number of latches in the sequential AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkSeqLatchNum( Abc_Ntk_t * pNtk )
{
Vec_Int_t * vNumbers;
Abc_Obj_t * pObj;
int i, Counter;
assert( Abc_NtkIsSeq( pNtk ) );
// create latches for each new object according to the counters
Counter = 0;
vNumbers = Abc_NtkSeqCountLatches( pNtk );
Abc_NtkForEachObj( pNtk, pObj, i )
{
assert( Abc_ObjFanoutLMax(pObj) == Vec_IntEntry(vNumbers, pObj->Id) );
Counter += Vec_IntEntry(vNumbers, pObj->Id);
}
Vec_IntFree( vNumbers );
return Counter;
}
/**Function*************************************************************
Synopsis [Performs forward retiming of the sequential AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkSeqRetimeForward( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode, * pFanout;
int i, k, nLatches;
assert( Abc_NtkIsSeq( pNtk ) );
// assume that all nodes can be retimed
vNodes = Vec_PtrAlloc( 100 );
Abc_NtkForEachNode( pNtk, pNode, i )
{
Vec_PtrPush( vNodes, pNode );
pNode->fMarkA = 1;
}
// process the nodes
Vec_PtrForEachEntry( vNodes, pNode, i )
{
// get the number of latches to retime
nLatches = Abc_ObjFaninLMin(pNode);
if ( nLatches == 0 )
continue;
assert( nLatches > 0 );
// subtract these latches on the fanin side
Abc_ObjAddFaninL0( pNode, -nLatches );
Abc_ObjAddFaninL1( pNode, -nLatches );
// add these latches on the fanout size
Abc_ObjForEachFanout( pNode, pFanout, k )
{
Abc_ObjAddFanoutL( pNode, pFanout, nLatches );
if ( pFanout->fMarkA == 0 )
{ // schedule the node for updating
Vec_PtrPush( vNodes, pFanout );
pFanout->fMarkA = 1;
}
}
// unmark the node as processed
pNode->fMarkA = 0;
}
Vec_PtrFree( vNodes );
// clean the marks
Abc_NtkForEachNode( pNtk, pNode, i )
{
pNode->fMarkA = 0;
assert( Abc_ObjFaninLMin(pNode) == 0 );
}
}
/**Function*************************************************************
Synopsis [Performs forward retiming of the sequential AIG.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNodes;
Abc_Obj_t * pNode, * pFanin, * pFanout;
int i, k, nLatches;
assert( Abc_NtkIsSeq( pNtk ) );
// assume that all nodes can be retimed
vNodes = Vec_PtrAlloc( 100 );
Abc_NtkForEachNode( pNtk, pNode, i )
{
Vec_PtrPush( vNodes, pNode );
pNode->fMarkA = 1;
}
// process the nodes
Vec_PtrForEachEntry( vNodes, pNode, i )
{
// get the number of latches to retime
nLatches = Abc_ObjFanoutLMin(pNode);
if ( nLatches == 0 )
continue;
assert( nLatches > 0 );
// subtract these latches on the fanout side
Abc_ObjForEachFanout( pNode, pFanout, k )
Abc_ObjAddFanoutL( pNode, pFanout, -nLatches );
// add these latches on the fanin size
Abc_ObjForEachFanin( pNode, pFanin, k )
{
Abc_ObjAddFaninL( pNode, k, nLatches );
if ( pFanin->fMarkA == 0 )
{ // schedule the node for updating
Vec_PtrPush( vNodes, pFanin );
pFanin->fMarkA = 1;
}
}
// unmark the node as processed
pNode->fMarkA = 0;
}
Vec_PtrFree( vNodes );
// clean the marks
Abc_NtkForEachNode( pNtk, pNode, i )
{
pNode->fMarkA = 0;
assert( Abc_ObjFanoutLMin(pNode) == 0 );
}
}
/**Function*************************************************************
Synopsis [Returns the latch number of the fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_ObjFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout )
{
assert( Abc_NtkIsSeq(pObj->pNtk) );
if ( Abc_ObjFanin0(pFanout) == pObj )
return Abc_ObjFaninL0(pFanout);
else if ( Abc_ObjFanin1(pFanout) == pObj )
return Abc_ObjFaninL1(pFanout);
else
assert( 0 );
return 0;
}
/**Function*************************************************************
Synopsis [Sets the latch number of the fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ObjSetFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats )
{
assert( Abc_NtkIsSeq(pObj->pNtk) );
if ( Abc_ObjFanin0(pFanout) == pObj )
Abc_ObjSetFaninL0(pFanout, nLats);
else if ( Abc_ObjFanin1(pFanout) == pObj )
Abc_ObjSetFaninL1(pFanout, nLats);
else
assert( 0 );
}
/**Function*************************************************************
Synopsis [Adds to the latch number of the fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_ObjAddFanoutL( Abc_Obj_t * pObj, Abc_Obj_t * pFanout, int nLats )
{
assert( Abc_NtkIsSeq(pObj->pNtk) );
if ( Abc_ObjFanin0(pFanout) == pObj )
Abc_ObjAddFaninL0(pFanout, nLats);
else if ( Abc_ObjFanin1(pFanout) == pObj )
Abc_ObjAddFaninL1(pFanout, nLats);
else
assert( 0 );
}
/**Function*************************************************************
Synopsis [Returns the latch number of the fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_ObjFanoutLMax( Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanout;
int i, nLatch, nLatchRes;
nLatchRes = -1;
Abc_ObjForEachFanout( pObj, pFanout, i )
if ( nLatchRes < (nLatch = Abc_ObjFanoutL(pObj, pFanout)) )
nLatchRes = nLatch;
assert( nLatchRes >= 0 );
return nLatchRes;
}
/**Function*************************************************************
Synopsis [Returns the latch number of the fanout.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_ObjFanoutLMin( Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanout;
int i, nLatch, nLatchRes;
nLatchRes = ABC_INFINITY;
Abc_ObjForEachFanout( pObj, pFanout, i )
if ( nLatchRes > (nLatch = Abc_ObjFanoutL(pObj, pFanout)) )
nLatchRes = nLatch;
assert( nLatchRes < ABC_INFINITY );
return nLatchRes;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
/**CFile****************************************************************
FileName [abcSeqRetime.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Peforms retiming for optimal clock cycle.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcSeqRetime.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// storing arrival times in the nodes
static inline int Abc_NodeReadLValue( Abc_Obj_t * pNode ) { return Vec_IntEntry( (pNode)->pNtk->pData, (pNode)->Id ); }
static inline void Abc_NodeSetLValue( Abc_Obj_t * pNode, int Value ) { Vec_IntWriteEntry( (pNode)->pNtk->pData, (pNode)->Id, (Value) ); }
// the internal procedures
static int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax );
static int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi );
static int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
// node status after updating its arrival time
enum { ABC_UPDATE_FAIL, ABC_UPDATE_NO, ABC_UPDATE_YES };
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Retimes AIG for optimal delay.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk )
{
int FiMax, FiBest;
assert( Abc_NtkIsSeq( pNtk ) );
// start storage for sequential arrival times
assert( pNtk->pData == NULL );
pNtk->pData = Vec_IntAlloc( 0 );
// get the maximum possible clock
FiMax = Abc_NtkNodeNum(pNtk);
// make sure this clock period is feasible
assert( Abc_NtkRetimeForPeriod( pNtk, FiMax ) );
// search for the optimal clock period between 0 and nLevelMax
FiBest = Abc_NtkRetimeSearch_rec( pNtk, 0, FiMax );
// print the result
printf( "The best clock period is %3d.\n", FiBest );
// free storage
Vec_IntFree( pNtk->pData );
pNtk->pData = NULL;
}
/**Function*************************************************************
Synopsis [Performs binary search for the optimal clock period.]
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkRetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax )
{
int Median;
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
return FiMax;
Median = FiMin + (FiMax - FiMin)/2;
if ( Abc_NtkRetimeForPeriod( pNtk, Median ) )
return Abc_NtkRetimeSearch_rec( pNtk, FiMin, Median ); // Median is feasible
else
return Abc_NtkRetimeSearch_rec( pNtk, Median, FiMax ); // Median is infeasible
}
/**Function*************************************************************
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkRetimeForPeriod( Abc_Ntk_t * pNtk, int Fi )
{
Vec_Ptr_t * vFrontier;
Abc_Obj_t * pObj, * pFanout;
int RetValue, i, k;
// set l-values of all nodes to be minus infinity
Vec_IntFill( pNtk->pData, Abc_NtkObjNum(pNtk), -ABC_INFINITY );
// start the frontier by including PI fanouts
vFrontier = Vec_PtrAlloc( 100 );
Abc_NtkForEachPi( pNtk, pObj, i )
{
Abc_NodeSetLValue( pObj, 0 );
Abc_ObjForEachFanout( pObj, pFanout, k )
if ( pFanout->fMarkA == 0 )
{
Vec_PtrPush( vFrontier, pFanout );
pFanout->fMarkA = 1;
}
}
// iterate until convergence
Vec_PtrForEachEntry( vFrontier, pObj, i )
{
RetValue = Abc_NodeUpdateLValue( pObj, Fi );
if ( RetValue == ABC_UPDATE_FAIL )
break;
// unmark the node as processed
pObj->fMarkA = 0;
if ( RetValue == ABC_UPDATE_NO )
continue;
assert( RetValue == ABC_UPDATE_YES );
// arrival times have changed - add fanouts to the frontier
Abc_ObjForEachFanout( pObj, pFanout, k )
if ( pFanout->fMarkA == 0 )
{
Vec_PtrPush( vFrontier, pFanout );
pFanout->fMarkA = 1;
}
}
// clean the nodes
Vec_PtrForEachEntryStart( vFrontier, pObj, k, i )
pObj->fMarkA = 0;
// report the results
if ( RetValue == ABC_UPDATE_FAIL )
printf( "Period = %3d. Updated nodes = %6d. Infeasible\n", Fi, vFrontier->nSize );
else
printf( "Period = %3d. Updated nodes = %6d. Feasible\n", Fi, vFrontier->nSize );
Vec_PtrFree( vFrontier );
return RetValue != ABC_UPDATE_FAIL;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
{
int lValueNew, lValue0, lValue1;
assert( !Abc_ObjIsPi(pObj) );
lValue0 = Abc_NodeReadLValue(Abc_ObjFanin0(pObj)) - Fi * Abc_ObjFaninL0(pObj);
if ( Abc_ObjFaninNum(pObj) == 2 )
lValue1 = Abc_NodeReadLValue(Abc_ObjFanin1(pObj)) - Fi * Abc_ObjFaninL1(pObj);
else
lValue1 = -ABC_INFINITY;
lValueNew = 1 + ABC_MAX( lValue0, lValue1 );
if ( Abc_ObjIsPo(pObj) && lValueNew > Fi )
return ABC_UPDATE_FAIL;
if ( lValueNew == Abc_NodeReadLValue(pObj) )
return ABC_UPDATE_NO;
Abc_NodeSetLValue( pObj, lValueNew );
return ABC_UPDATE_YES;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -22,6 +22,8 @@ SRC += src/base/abc/abc.c \
src/base/abc/abcRenode.c \
src/base/abc/abcRes.c \
src/base/abc/abcSat.c \
src/base/abc/abcSeq.c \
src/base/abc/abcSeqRetime.c \
src/base/abc/abcShow.c \
src/base/abc/abcSop.c \
src/base/abc/abcStrash.c \
......
......@@ -51,6 +51,9 @@ struct Vec_Ptr_t_
#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 )
......
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