Commit e3c40ed6 by Alan Mishchenko

Version abc51126

parent 08d2b310
......@@ -282,6 +282,14 @@ SOURCE=.\src\base\seq\seq.h
# End Source File
# Begin Source File
SOURCE=.\src\base\seq\seqAigCore.c
# End Source File
# Begin Source File
SOURCE=.\src\base\seq\seqAigIter.c
# End Source File
# Begin Source File
SOURCE=.\src\base\seq\seqCreate.c
# End Source File
# Begin Source File
......@@ -1698,10 +1706,6 @@ SOURCE=.\src\misc\vec\vec.h
# End Source File
# Begin Source File
SOURCE=.\src\misc\vec\vecFan.h
# End Source File
# Begin Source File
SOURCE=.\src\misc\vec\vecInt.h
# 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\RSP1416.tmp" with contents
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1A31.tmp" with contents
[
/nologo /MLd /W3 /Gm /GX /ZI /Od /I "src\base\abc" /I "src\base\abci" /I "src\base\abcs" /I "src\base\seq" /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\ft" /I "src\sat\asat" /I "src\sat\msat" /I "src\sat\fraig" /I "src\opt\cut" /I "src\opt\dec" /I "src\opt\fxu" /I "src\opt\sim" /I "src\opt\rwr" /I "src\map\fpga" /I "src\map\pga" /I "src\map\mapper" /I "src\map\mapp" /I "src\map\mio" /I "src\map\super" /I "src\misc\extra" /I "src\misc\st" /I "src\misc\mvc" /I "src\misc\util" /I "src\misc\npn" /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\seq\seqFpgaIter.c"
"C:\_projects\abc\src\base\seq\seqRetCore.c"
]
Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1416.tmp"
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1417.tmp" with contents
Creating command line "cl.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1A31.tmp"
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1A32.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\abcAig.obj
......@@ -64,8 +64,6 @@ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32
.\Debug\seqMan.obj
.\Debug\seqMapCore.obj
.\Debug\seqMapIter.obj
.\Debug\seqRetCore.obj
.\Debug\seqRetIter.obj
.\Debug\seqShare.obj
.\Debug\seqUtil.obj
.\Debug\cmd.obj
......@@ -328,13 +326,17 @@ kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32
.\Debug\mvcPrint.obj
.\Debug\mvcSort.obj
.\Debug\mvcUtils.obj
.\Debug\seqRetCore.obj
.\Debug\seqRetIter.obj
.\Debug\seqAigCore.obj
.\Debug\seqAigIter.obj
]
Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1417.tmp"
Creating command line "link.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1A32.tmp"
<h3>Output Window</h3>
Compiling...
seqFpgaIter.c
seqRetCore.c
Linking...
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1418.tmp" with contents
Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1A33.tmp" with contents
[
/nologo /o"Debug/abc.bsc"
.\Debug\abcAig.sbr
......@@ -386,8 +388,6 @@ Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1418.tmp" with cont
.\Debug\seqMan.sbr
.\Debug\seqMapCore.sbr
.\Debug\seqMapIter.sbr
.\Debug\seqRetCore.sbr
.\Debug\seqRetIter.sbr
.\Debug\seqShare.sbr
.\Debug\seqUtil.sbr
.\Debug\cmd.sbr
......@@ -649,8 +649,12 @@ Creating temporary file "C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1418.tmp" with cont
.\Debug\mvcOpBool.sbr
.\Debug\mvcPrint.sbr
.\Debug\mvcSort.sbr
.\Debug\mvcUtils.sbr]
Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1418.tmp"
.\Debug\mvcUtils.sbr
.\Debug\seqRetCore.sbr
.\Debug\seqRetIter.sbr
.\Debug\seqAigCore.sbr
.\Debug\seqAigIter.sbr]
Creating command line "bscmake.exe @C:\DOCUME~1\alanmi\LOCALS~1\Temp\RSP1A33.tmp"
Creating browse info file...
<h3>Output Window</h3>
......
......@@ -22,6 +22,8 @@ alias clp collapse
alias esd ext_seq_dcs
alias f fraig
alias fs fraig_sweep
alias fsto fraig_store
alias fres fraig_restore
alias ft fraig_trust
alias mu renode -m
alias pex print_exdc -d
......
......@@ -394,13 +394,15 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
***********************************************************************/
void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis )
{
Abc_Obj_t * pAnd, ** ppPlace;
Abc_Obj_t * pAnd, * pAnd0, * pAnd1, ** ppPlace;
unsigned Key;
assert( !Abc_ObjIsComplement(pThis) );
assert( Abc_ObjIsNode(pThis) );
assert( Abc_ObjFaninNum(pThis) == 2 );
assert( pMan->pNtkAig == pThis->pNtk );
// get the hash key for these two nodes
pAnd0 = Abc_ObjRegular( Abc_ObjChild0(pThis) );
pAnd1 = Abc_ObjRegular( Abc_ObjChild1(pThis) );
Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins );
// find the matching node in the table
ppPlace = pMan->pBins + Key;
......@@ -479,7 +481,7 @@ void Abc_AigRehash( Abc_Aig_t * pMan )
{
Abc_Obj_t ** pBinsNew;
Abc_Obj_t * pEnt, * pEnt2;
Abc_Fan_t * pArray;
int * pArray;
unsigned Key;
int Counter, Temp, i;
......@@ -493,14 +495,14 @@ void Abc_AigRehash( Abc_Aig_t * pMan )
{
// swap the fanins if needed
pArray = pEnt->vFanins.pArray;
if ( pArray[0].iFan > pArray[1].iFan )
if ( pArray[0] > pArray[1] )
{
Temp = pArray[0].iFan;
pArray[0].iFan = pArray[1].iFan;
pArray[1].iFan = Temp;
Temp = pArray[0].fCompl;
pArray[0].fCompl = pArray[1].fCompl;
pArray[1].fCompl = Temp;
Temp = pArray[0];
pArray[0] = pArray[1];
pArray[1] = Temp;
Temp = pEnt->fCompl0;
pEnt->fCompl0 = pEnt->fCompl1;
pEnt->fCompl1 = Temp;
}
// rehash the node
Key = Abc_HashKey2( Abc_ObjChild0(pEnt), Abc_ObjChild1(pEnt), pMan->nBins );
......@@ -660,7 +662,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan, int fUpdateLevel )
continue;
}
// find the old node as a fanin of this fanout
iFanin = Vec_FanFindEntry( &pFanout->vFanins, pOld->Id );
iFanin = Vec_IntFind( &pFanout->vFanins, pOld->Id );
assert( iFanin == 0 || iFanin == 1 );
// get the new fanin
pFanin1 = Abc_ObjNotCond( pNew, Abc_ObjFaninC(pFanout, iFanin) );
......@@ -1009,7 +1011,7 @@ bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode )
int i, iFanin;
Abc_ObjForEachFanout( pNode, pFanout, i )
{
iFanin = Vec_FanFindEntry( &pFanout->vFanins, pNode->Id );
iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
assert( iFanin >= 0 );
if ( Abc_ObjFaninC( pFanout, iFanin ) )
return 1;
......@@ -1038,7 +1040,7 @@ bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
{
if ( !Abc_NodeIsTravIdCurrent(pFanout) )
continue;
iFanin = Vec_FanFindEntry( &pFanout->vFanins, pNode->Id );
iFanin = Vec_IntFind( &pFanout->vFanins, pNode->Id );
assert( iFanin >= 0 );
if ( Abc_ObjFaninC( pFanout, iFanin ) )
return 1;
......
......@@ -417,7 +417,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
// go through the fanins of the object and make sure fanins have this object as a fanout
Abc_ObjForEachFanin( pObj, pFanin, i )
{
if ( Vec_FanFindEntry( &pFanin->vFanouts, pObj->Id ) == -1 )
if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 )
{
fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) );
fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) );
......@@ -427,7 +427,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
// go through the fanouts of the object and make sure fanouts have this object as a fanin
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( Vec_FanFindEntry( &pFanout->vFanins, pObj->Id ) == -1 )
if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 )
{
fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) );
fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) );
......@@ -441,7 +441,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
// make sure fanins are not duplicated
for ( i = 0; i < pObj->vFanins.nSize; i++ )
for ( k = i + 1; k < pObj->vFanins.nSize; k++ )
if ( pObj->vFanins.pArray[k].iFan == pObj->vFanins.pArray[i].iFan )
if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] )
{
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) );
......@@ -454,7 +454,7 @@ bool Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
// make sure fanouts are not duplicated
for ( i = 0; i < pObj->vFanouts.nSize; i++ )
for ( k = i + 1; k < pObj->vFanouts.nSize; k++ )
if ( pObj->vFanouts.pArray[k].iFan == pObj->vFanouts.pArray[i].iFan )
if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] )
{
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) );
......
......@@ -221,6 +221,7 @@ bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode, * pFanin;
int i, k;
assert( !Abc_NtkIsSeq(pNtk) );
// set the traversal ID
Abc_NtkIncrementTravId( pNtk );
// mark the CIs
......@@ -229,11 +230,16 @@ bool Abc_NtkIsDfsOrdered( Abc_Ntk_t * pNtk )
// go through the nodes
Abc_NtkForEachNode( pNtk, pNode, i )
{
// check the fanins of the node
Abc_ObjForEachFanin( pNode, pFanin, k )
{
if ( !Abc_NodeIsTravIdCurrent(pFanin) )
return 0;
}
// check the choices of the node
if ( Abc_NtkIsStrash(pNtk) && Abc_NodeIsAigChoice(pNode) )
for ( pFanin = pNode->pData; pFanin; pFanin = pFanin->pData )
if ( !Abc_NodeIsTravIdCurrent(pFanin) )
return 0;
// mark the node as visited
Abc_NodeSetTravIdCurrent( pNode );
}
return 1;
......
......@@ -25,8 +25,6 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
#define ABC_LARGE_ID ((1<<24)-1) // should correspond to value in "vecFan.h"
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
......@@ -48,10 +46,8 @@ void Abc_ObjAddFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
assert( !Abc_ObjIsComplement(pObj) );
assert( pObj->pNtk == pFaninR->pNtk );
assert( pObj->Id >= 0 && pFaninR->Id >= 0 );
assert( pObj->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
assert( pFaninR->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
Vec_FanPush( pObj->pNtk->pMmStep, &pObj->vFanins, Vec_Int2Fan(pFaninR->Id) );
Vec_FanPush( pObj->pNtk->pMmStep, &pFaninR->vFanouts, Vec_Int2Fan(pObj->Id) );
Vec_IntPushMem( pObj->pNtk->pMmStep, &pObj->vFanins, pFaninR->Id );
Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninR->vFanouts, pObj->Id );
if ( Abc_ObjIsComplement(pFanin) )
Abc_ObjSetFaninC( pObj, Abc_ObjFaninNum(pObj)-1 );
}
......@@ -74,14 +70,12 @@ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
assert( !Abc_ObjIsComplement(pFanin) );
assert( pObj->pNtk == pFanin->pNtk );
assert( pObj->Id >= 0 && pFanin->Id >= 0 );
assert( pObj->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
assert( pFanin->Id < ABC_LARGE_ID ); // created but forgot to add it to the network?
if ( !Vec_FanDeleteEntry( &pObj->vFanins, pFanin->Id ) )
if ( !Vec_IntRemove( &pObj->vFanins, pFanin->Id ) )
{
printf( "The obj %d is not found among the fanins of obj %d ...\n", pFanin->Id, pObj->Id );
return;
}
if ( !Vec_FanDeleteEntry( &pFanin->vFanouts, pObj->Id ) )
if ( !Vec_IntRemove( &pFanin->vFanouts, pObj->Id ) )
{
printf( "The obj %d is not found among the fanouts of obj %d ...\n", pObj->Id, pFanin->Id );
return;
......@@ -102,16 +96,19 @@ void Abc_ObjDeleteFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFanin )
***********************************************************************/
void Abc_ObjRemoveFanins( Abc_Obj_t * pObj )
{
Vec_Fan_t * vFaninsOld;
Vec_Int_t * vFaninsOld;
Abc_Obj_t * pFanin;
int k;
// remove old fanins
vFaninsOld = &pObj->vFanins;
for ( k = vFaninsOld->nSize - 1; k >= 0; k-- )
{
pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k].iFan );
pFanin = Abc_NtkObj( pObj->pNtk, vFaninsOld->pArray[k] );
Abc_ObjDeleteFanin( pObj, pFanin );
}
pObj->fCompl0 = 0;
pObj->fCompl1 = 0;
assert( vFaninsOld->nSize == 0 );
}
/**Function*************************************************************
......@@ -131,7 +128,7 @@ void Abc_ObjRemoveFanins( Abc_Obj_t * pObj )
void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew )
{
Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew);
int iFanin, fCompl, nLats;
int iFanin, nLats;//, fCompl;
assert( !Abc_ObjIsComplement(pObj) );
assert( !Abc_ObjIsComplement(pFaninOld) );
assert( pFaninOld != pFaninNewR );
......@@ -139,29 +136,33 @@ void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFa
// assert( pObj != pFaninNewR );
assert( pObj->pNtk == pFaninOld->pNtk );
assert( pObj->pNtk == pFaninNewR->pNtk );
if ( (iFanin = Vec_FanFindEntry( &pObj->vFanins, pFaninOld->Id )) == -1 )
if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 )
{
printf( "Node %s is not among", Abc_ObjName(pFaninOld) );
printf( " the fanins of node %s...\n", Abc_ObjName(pObj) );
return;
}
// remember the attributes of the old fanin
fCompl = Abc_ObjFaninC(pObj, iFanin);
// fCompl = Abc_ObjFaninC(pObj, iFanin);
// replace the old fanin entry by the new fanin entry (removes attributes)
Vec_FanWriteEntry( &pObj->vFanins, iFanin, Vec_Int2Fan(pFaninNewR->Id) );
Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id );
// set the attributes of the new fanin
if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) )
Abc_ObjSetFaninC( pObj, iFanin );
// if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) )
// Abc_ObjSetFaninC( pObj, iFanin );
if ( Abc_ObjIsComplement(pFaninNew) )
Abc_ObjXorFaninC( pObj, iFanin );
if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) )
Seq_ObjSetFaninL( pObj, iFanin, nLats );
// update the fanout of the fanin
if ( !Vec_FanDeleteEntry( &pFaninOld->vFanouts, pObj->Id ) )
if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) )
{
printf( "Node %s is not among", Abc_ObjName(pObj) );
printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) );
// return;
}
Vec_FanPush( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, Vec_Int2Fan(pObj->Id) );
Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id );
}
/**Function*************************************************************
......
......@@ -89,7 +89,38 @@ int Abc_NtkCountSelfFeedLatches( Abc_Ntk_t * pNtk )
int i, Counter;
Counter = 0;
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
// if ( Abc_NtkLatchIsSelfFeed(pLatch) && Abc_ObjFanoutNum(pLatch) > 1 )
// printf( "Fanouts = %d.\n", Abc_ObjFanoutNum(pLatch) );
Counter += Abc_NtkLatchIsSelfFeed( pLatch );
}
return Counter;
}
/**Function*************************************************************
Synopsis [Replaces self-feeding latches by latches with constant inputs.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkRemoveSelfFeedLatches( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pLatch;
int i, Counter;
Counter = 0;
Abc_NtkForEachLatch( pNtk, pLatch, i )
{
if ( Abc_NtkLatchIsSelfFeed( pLatch ) )
{
Abc_ObjPatchFanin( pLatch, Abc_ObjFanin0(pLatch), Abc_NtkConst1(pNtk) );
Counter++;
}
}
return Counter;
}
......
......@@ -326,6 +326,10 @@ Abc_Ntk_t * Abc_NtkDup( Abc_Ntk_t * pNtk )
Seq_NodeDupLats( pObj->pCopy, pObj, k );
}
}
// relink the choice nodes
Abc_AigForEachAnd( pNtk, pObj, i )
if ( pObj->pData )
pObj->pCopy->pData = ((Abc_Obj_t *)pObj->pData)->pCopy;
}
else
{
......
......@@ -47,9 +47,9 @@ Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
Abc_Obj_t * pObj;
pObj = (Abc_Obj_t *)Extra_MmFixedEntryFetch( pNtk->pMmObj );
memset( pObj, 0, sizeof(Abc_Obj_t) );
pObj->Id = -1;
pObj->pNtk = pNtk;
pObj->Type = Type;
pObj->Id = -1;
return pObj;
}
......
......@@ -49,7 +49,7 @@ void Abc_NtkIncrementTravId( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
int i;
if ( pNtk->nTravIds == (1<<12)-1 )
if ( pNtk->nTravIds == (1<<10)-1 )
{
pNtk->nTravIds = 0;
Abc_NtkForEachObj( pNtk, pObj, i )
......@@ -260,7 +260,7 @@ int Abc_NtkGetChoiceNum( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, Counter;
if ( !Abc_NtkIsStrash(pNtk) )
if ( !Abc_NtkHasAig(pNtk) )
return 0;
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
......@@ -966,7 +966,7 @@ void Abc_NtkReassignIds( Abc_Ntk_t * pNtk )
Vec_PtrPush( vObjsNew, pNode );
}
// finally, internal nodes in the DFS order
vNodes = Abc_NtkDfs( pNtk, 1 );
vNodes = Abc_AigDfs( pNtk, 1, 0 );
Vec_PtrForEachEntry( vNodes, pNode, i )
{
if ( pNode == pConst1 )
......@@ -981,9 +981,9 @@ void Abc_NtkReassignIds( Abc_Ntk_t * pNtk )
Abc_NtkForEachObj( pNtk, pNode, i )
{
Abc_ObjForEachFanin( pNode, pTemp, k )
pNode->vFanins.pArray[k].iFan = pTemp->Id;
pNode->vFanins.pArray[k] = pTemp->Id;
Abc_ObjForEachFanout( pNode, pTemp, k )
pNode->vFanouts.pArray[k].iFan = pTemp->Id;
pNode->vFanouts.pArray[k] = pTemp->Id;
}
// replace the array of objs
......
......@@ -4741,7 +4741,7 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c, nLoops;
int c;//, nLoops;
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
......@@ -4778,11 +4778,11 @@ int Abc_CommandSeq( Abc_Frame_t * pAbc, int argc, char ** argv )
return 1;
}
if ( nLoops = Abc_NtkCountSelfFeedLatches(pNtk) )
{
fprintf( pErr, "Cannot create sequential AIG because the network contains %d self-feeding latches.\n", nLoops );
return 0;
}
// if ( nLoops = Abc_NtkCountSelfFeedLatches(pNtk) )
// {
// fprintf( pErr, "Cannot create sequential AIG because the network contains %d self-feeding latches.\n", nLoops );
// return 0;
// }
// get the new network
pNtkRes = Abc_NtkAigToSeq( pNtk );
......@@ -4854,8 +4854,8 @@ int Abc_CommandUnseq( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// share the latches on the fanout edges
if ( fShare )
Seq_NtkShareFanouts(pNtk);
// if ( fShare )
// Seq_NtkShareFanouts(pNtk);
// get the new network
pNtkRes = Abc_NtkSeqToLogicSop( pNtk );
......@@ -4983,7 +4983,7 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
int c, nMaxIters;
int fVerbose;
pNtk = Abc_FrameReadNet(pAbc);
......@@ -4991,12 +4991,24 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 0;
nMaxIters = 15;
fVerbose = 0;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
while ( ( c = util_getopt( argc, argv, "Ivh" ) ) != EOF )
{
switch ( c )
{
case 'I':
if ( util_optind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
goto usage;
}
nMaxIters = atoi(argv[util_optind]);
util_optind++;
if ( nMaxIters < 0 )
goto usage;
break;
case 'v':
fVerbose ^= 1;
break;
......@@ -5020,7 +5032,7 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
}
// get the new network
pNtkRes = Seq_NtkFpgaMapRetime( pNtk, fVerbose );
pNtkRes = Seq_NtkFpgaMapRetime( pNtk, nMaxIters, fVerbose );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Sequential FPGA mapping has failed.\n" );
......@@ -5031,10 +5043,11 @@ int Abc_CommandSeqFpga( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
fprintf( pErr, "usage: sfpga [-vh]\n" );
fprintf( pErr, "\t performs integrated sequential FPGA mapping\n" );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "usage: sfpga [-I num] [-vh]\n" );
fprintf( pErr, "\t performs integrated sequential FPGA mapping\n" );
fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
......@@ -5053,21 +5066,32 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
{
FILE * pOut, * pErr;
Abc_Ntk_t * pNtk, * pNtkRes;
int c;
int c, nMaxIters;
int fVerbose;
extern Abc_Ntk_t * Abc_NtkMapSeq( Abc_Ntk_t * pNtk, int fVerbose );
pNtk = Abc_FrameReadNet(pAbc);
pOut = Abc_FrameReadOut(pAbc);
pErr = Abc_FrameReadErr(pAbc);
// set defaults
fVerbose = 1;
nMaxIters = 15;
fVerbose = 1;
util_getopt_reset();
while ( ( c = util_getopt( argc, argv, "vh" ) ) != EOF )
while ( ( c = util_getopt( argc, argv, "Ivh" ) ) != EOF )
{
switch ( c )
{
case 'I':
if ( util_optind >= argc )
{
fprintf( pErr, "Command line switch \"-I\" should be followed by a positive integer.\n" );
goto usage;
}
nMaxIters = atoi(argv[util_optind]);
util_optind++;
if ( nMaxIters < 0 )
goto usage;
break;
case 'v':
fVerbose ^= 1;
break;
......@@ -5089,17 +5113,14 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
fprintf( pErr, "Sequential standard cell mapping works only for sequential AIG (run \"seq\").\n" );
return 1;
}
printf( "This command is not yet implemented.\n" );
return 0;
// printf( "This command is not yet implemented.\n" );
// return 0;
// get the new network
pNtkRes = Abc_NtkMapSeq( pNtk, fVerbose );
pNtkRes = Seq_MapRetime( pNtk, nMaxIters, fVerbose );
if ( pNtkRes == NULL )
{
fprintf( pErr, "Sequential FPGA mapping has failed.\n" );
fprintf( pErr, "Sequential standard-cell mapping has failed.\n" );
return 1;
}
// replace the current network
......@@ -5107,10 +5128,11 @@ int Abc_CommandSeqMap( Abc_Frame_t * pAbc, int argc, char ** argv )
return 0;
usage:
fprintf( pErr, "usage: smap [-vh]\n" );
fprintf( pErr, "\t performs integrated sequential standard-cell mapping" );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
fprintf( pErr, "usage: smap [-I num] [-vh]\n" );
fprintf( pErr, "\t performs integrated sequential standard-cell mapping" );
fprintf( pErr, "\t-I num : max number of iterations of l-value computation [default = %d]\n", nMaxIters );
fprintf( pErr, "\t-v : toggle verbose output [default = %s]\n", fVerbose? "yes": "no" );
fprintf( pErr, "\t-h : print the command usage\n");
return 1;
}
......
......@@ -187,7 +187,7 @@ int Abc_NodeAttach( Abc_Obj_t * pNode, Mio_Gate_t ** ppGates, unsigned ** puTrut
Abc_ObjForEachFanin( pNode, pFanin, i )
pTempInts[i] = pFanin->Id;
for ( i = 0; i < nFanins; i++ )
pNode->vFanins.pArray[Perm[i]].iFan = pTempInts[i];
pNode->vFanins.pArray[Perm[i]] = pTempInts[i];
// set the gate
pNode->pCopy = (Abc_Obj_t *)pGate;
return 1;
......
......@@ -185,12 +185,14 @@ void Abc_NtkCutsOracle( Abc_Ntk_t * pNtk, Cut_Oracle_t * p )
Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
{
Cut_Man_t * p;
Abc_Obj_t * pObj;
Abc_Obj_t * pObj, * pNode;
int i, nIters, fStatus;
Vec_Int_t * vChoices;
int clk = clock();
assert( Abc_NtkIsSeq(pNtk) );
assert( pParams->fSeq );
// assert( Abc_NtkIsDfsOrdered(pNtk) );
// start the manager
pParams->nIdsMax = Abc_NtkObjNumMax( pNtk );
......@@ -202,7 +204,10 @@ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
if ( Abc_ObjFanoutNum(pObj) > 0 )
Cut_NodeSetTriv( p, pObj->Id );
Abc_NtkForEachPi( pNtk, pObj, i )
{
//printf( "Setting trivial cut %d.\n", pObj->Id );
Cut_NodeSetTriv( p, pObj->Id );
}
// label the cutset nodes and set their number in the array
// assign the elementary cuts to the cutset nodes
Abc_SeqForEachCutsetNode( pNtk, pObj, i )
......@@ -211,27 +216,40 @@ Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams )
pObj->fMarkC = 1;
pObj->pCopy = (Abc_Obj_t *)i;
Cut_NodeSetTriv( p, pObj->Id );
//printf( "Setting trivial cut %d.\n", pObj->Id );
}
// process the nodes
vChoices = Vec_IntAlloc( 100 );
for ( nIters = 0; nIters < 10; nIters++ )
{
//printf( "ITERATION %d:\n", nIters );
// compute the cuts for the internal nodes
Abc_AigForEachAnd( pNtk, pObj, i )
{
Abc_NodeGetCutsSeq( p, pObj, nIters==0 );
// add cuts due to choices
if ( Abc_NodeIsAigChoice(pObj) )
{
Vec_IntClear( vChoices );
for ( pNode = pObj; pNode; pNode = pNode->pData )
Vec_IntPush( vChoices, pNode->Id );
Cut_NodeUnionCutsSeq( p, vChoices, (pObj->fMarkC ? (int)pObj->pCopy : -1), nIters==0 );
}
}
// merge the new cuts with the old cuts
Abc_NtkForEachPi( pNtk, pObj, i )
Cut_NodeNewMergeWithOld( p, pObj->Id );
Abc_AigForEachAnd( pNtk, pObj, i )
Cut_NodeNewMergeWithOld( p, pObj->Id );
// for the cutset, merge temp with new
// for the cutset, transfer temp cuts to new cuts
fStatus = 0;
Abc_SeqForEachCutsetNode( pNtk, pObj, i )
fStatus |= Cut_NodeTempTransferToNew( p, pObj->Id, i );
if ( fStatus == 0 )
break;
}
Vec_IntFree( vChoices );
// if the status is not finished, transfer new to old for the cutset
Abc_SeqForEachCutsetNode( pNtk, pObj, i )
......
......@@ -292,6 +292,7 @@ Abc_Ntk_t * Abc_NtkFromFraig( Fraig_Man_t * pMan, Abc_Ntk_t * pNtk )
Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
}
Extra_ProgressBarStop( pProgress );
Abc_NtkReassignIds( pNtkNew );
return pNtkNew;
}
......@@ -495,6 +496,7 @@ Abc_Ntk_t * Abc_NtkFraigTrust( Abc_Ntk_t * pNtk )
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
Abc_NtkFraigTrustOne( pNtk, pNtkNew );
Abc_NtkFinalize( pNtk, pNtkNew );
Abc_NtkReassignIds( pNtkNew );
// print a warning about choice nodes
printf( "Warning: The resulting AIG contains %d choice nodes.\n", Abc_NtkGetChoiceNum( pNtkNew ) );
......
......@@ -108,7 +108,7 @@ bool Abc_NtkFxuCheck( Abc_Ntk_t * pNtk )
{
Abc_ObjForEachFanin( pNode, pFanin1, i )
{
if ( Abc_ObjFaninC(pNode, i) )
if ( i < 2 && Abc_ObjFaninC(pNode, i) )
return 0;
Abc_ObjForEachFanin( pNode, pFanin2, k )
{
......
......@@ -467,9 +467,9 @@ void Abc_NodeBddReorder( reo_man * p, Abc_Obj_t * pNode )
pNode->pData = bFunc;
// update the fanin order
Abc_ObjForEachFanin( pNode, pFanin, i )
pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ].iFan;
pOrder[i] = pNode->vFanins.pArray[ pOrder[i] ];
Abc_ObjForEachFanin( pNode, pFanin, i )
pNode->vFanins.pArray[i].iFan = pOrder[i];
pNode->vFanins.pArray[i] = pOrder[i];
free( pOrder );
}
......
......@@ -58,7 +58,7 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
fprintf( pFile, " net = %5d", Abc_NtkNetNum(pNtk) );
fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
}
else if ( Abc_NtkIsStrash(pNtk) )
else if ( Abc_NtkHasAig(pNtk) )
{
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
if ( Num = Abc_NtkGetChoiceNum(pNtk) )
......@@ -66,8 +66,6 @@ void Abc_NtkPrintStats( FILE * pFile, Abc_Ntk_t * pNtk, int fFactored )
if ( Num = Abc_NtkGetExorNum(pNtk) )
fprintf( pFile, " (exor = %d)", Num );
}
else if ( Abc_NtkIsSeq(pNtk) )
fprintf( pFile, " and = %5d", Abc_NtkNodeNum(pNtk) );
else
fprintf( pFile, " nd = %5d", Abc_NtkNodeNum(pNtk) );
......
......@@ -607,7 +607,7 @@ void Abc_NodeConstantInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin, bool fConst0
DdNode * bVar, * bTemp;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 )
if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
{
printf( "Node %s should be among", Abc_ObjName(pFanin) );
printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
......@@ -635,7 +635,7 @@ void Abc_NodeComplementInput( Abc_Obj_t * pNode, Abc_Obj_t * pFanin )
DdNode * bVar, * bCof0, * bCof1;
int iFanin;
assert( Abc_NtkIsBddLogic(pNode->pNtk) );
if ( (iFanin = Vec_FanFindEntry( &pNode->vFanins, pFanin->Id )) == -1 )
if ( (iFanin = Vec_IntFind( &pNode->vFanins, pFanin->Id )) == -1 )
{
printf( "Node %s should be among", Abc_ObjName(pFanin) );
printf( " the fanins of node %s...\n", Abc_ObjName(pNode) );
......
......@@ -315,7 +315,7 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
fprintf( pFile, "Node%d%s", Abc_ObjFaninId0(pNode), (Abc_ObjIsLatch(Abc_ObjFanin0(pNode))? "_out":"") );
fprintf( pFile, " [" );
fprintf( pFile, "style = %s", Abc_ObjFaninC0(pNode)? "dotted" : "bold" );
if ( Seq_ObjFaninL0(pNode) > 0 )
if ( Abc_NtkIsSeq(pNode->pNtk) && Seq_ObjFaninL0(pNode) > 0 )
fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,0) );
fprintf( pFile, "]" );
fprintf( pFile, ";\n" );
......@@ -330,7 +330,7 @@ void Io_WriteDot( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow,
fprintf( pFile, "Node%d%s", Abc_ObjFaninId1(pNode), (Abc_ObjIsLatch(Abc_ObjFanin1(pNode))? "_out":"") );
fprintf( pFile, " [" );
fprintf( pFile, "style = %s", Abc_ObjFaninC1(pNode)? "dotted" : "bold" );
if ( Seq_ObjFaninL1(pNode) > 0 )
if ( Abc_NtkIsSeq(pNode->pNtk) && Seq_ObjFaninL1(pNode) > 0 )
fprintf( pFile, ", label = \"%s\"", Seq_ObjFaninGetInitPrintable(pNode,1) );
fprintf( pFile, "]" );
fprintf( pFile, ";\n" );
......
SRC += src/base/seq/seqCreate.c \
SRC += src/base/seq/seqAigCore.c \
src/base/seq/seqAigIter.c \
src/base/seq/seqCreate.c \
src/base/seq/seqFpgaCore.c \
src/base/seq/seqFpgaIter.c \
src/base/seq/seqLatch.c \
......
......@@ -43,8 +43,16 @@ typedef struct Abc_Seq_t_ Abc_Seq_t;
/// FUNCTION DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
/*=== seqAigCore.c ===========================================================*/
extern void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
/*=== seqFpgaCore.c ===============================================================*/
extern Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int fVerbose );
extern Abc_Ntk_t * Seq_NtkFpgaMapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
/*=== seqMapCore.c ===============================================================*/
extern Abc_Ntk_t * Seq_MapRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
/*=== seqRetCore.c ===========================================================*/
extern Abc_Ntk_t * Seq_NtkRetime( Abc_Ntk_t * pNtk, int nMaxIters, int fVerbose );
/*=== seqLatch.c ===============================================================*/
extern void Seq_NodeDupLats( Abc_Obj_t * pObjNew, Abc_Obj_t * pObj, int Edge );
extern int Seq_NodeCompareLats( Abc_Obj_t * pObj1, int Edge1, Abc_Obj_t * pObj2, int Edge2 );
......@@ -57,10 +65,8 @@ extern Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk );
extern Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk );
/*=== seqShare.c =============================================================*/
extern void Seq_NtkShareFanouts( Abc_Ntk_t * pNtk );
/*=== seqRetCore.c ===========================================================*/
extern void Seq_NtkSeqRetimeDelay( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeForward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkSeqRetimeBackward( Abc_Ntk_t * pNtk, int fInitial, int fVerbose );
extern void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk );
extern void Seq_NtkShareLatchesFpga( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds );
/*=== seqUtil.c ==============================================================*/
extern char * Seq_ObjFaninGetInitPrintable( Abc_Obj_t * pObj, int Edge );
extern void Seq_NtkLatchSetValues( Abc_Ntk_t * pNtk, Abc_InitType_t Init );
......@@ -69,6 +75,7 @@ extern int Seq_NtkLatchNumMax( Abc_Ntk_t * pNtk );
extern int Seq_NtkLatchNumShared( Abc_Ntk_t * pNtk );
extern void Seq_NtkLatchGetInitNums( Abc_Ntk_t * pNtk, int * pInits );
extern int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk );
extern int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit );
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
/**CFile****************************************************************
FileName [seqRetIter.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Construction and manipulation of sequential AIGs.]
Synopsis [The iterative L-Value computation for retiming procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: seqRetIter.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "seqInt.h"
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
// the internal procedures
static int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose );
static int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose );
static int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Retimes AIG for optimal delay using Pan's algorithm.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_AigRetimeDelayLags( Abc_Ntk_t * pNtk, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pNode;
int i, FiMax, FiBest, RetValue;
char NodeLag;
assert( Abc_NtkIsSeq( pNtk ) );
// get the upper bound on the clock period
FiMax = 2 + Seq_NtkLevelMax(pNtk);
// make sure this clock period is feasible
assert( Seq_RetimeForPeriod( pNtk, FiMax, fVerbose ) );
// search for the optimal clock period between 0 and nLevelMax
FiBest = Seq_RetimeSearch_rec( pNtk, 0, FiMax, fVerbose );
// recompute the best l-values
RetValue = Seq_RetimeForPeriod( pNtk, FiBest, fVerbose );
assert( RetValue );
// write the retiming lags
Vec_StrFill( p->vLags, p->nSize, 0 );
Abc_AigForEachAnd( pNtk, pNode, i )
{
NodeLag = Seq_NodeComputeLag( Seq_NodeGetLValue(pNode), FiBest );
Seq_NodeSetLag( pNode, NodeLag );
}
/*
{
Abc_Obj_t * pFanin, * pFanout;
pNode = Abc_NtkObj( pNtk, 823 );
printf( "Node %d. Lag = %d. LValue = %d. Latches = (%d,%d) (%d,%d).\n", pNode->Id, Seq_NodeGetLag(pNode), Seq_NodeGetLValue(pNode),
Seq_ObjFaninL0(pNode), Seq_ObjFaninL1(pNode), Seq_ObjFanoutL(pNode, Abc_NtkObj(pNtk, 826)), Seq_ObjFanoutL(pNode, Abc_NtkObj(pNtk, 1210)) );
pFanin = Abc_ObjFanin0( pNode );
printf( "Fanin %d. Lag = %d. LValue = %d. Latches = (%d,%d)\n", pFanin->Id, Seq_NodeGetLag(pFanin), Seq_NodeGetLValue(pFanin),
Seq_ObjFaninL0(pFanin), Seq_ObjFaninL1(pFanin) );
pFanin = Abc_ObjFanin1( pNode );
printf( "Fanin %d. Lag = %d. LValue = %d.\n", pFanin->Id, Seq_NodeGetLag(pFanin), Seq_NodeGetLValue(pFanin) );
Abc_ObjForEachFanout( pNode, pFanout, i )
printf( "Fanout %d. Lag = %d. LValue = %d.\n", pFanout->Id, Seq_NodeGetLag(pFanout), Seq_NodeGetLValue(pFanout) );
Abc_ObjForEachFanout( Abc_ObjFanin0(pNode), pFanout, i )
printf( "Fanout %d. Lag = %d. LValue = %d.\n", pFanout->Id, Seq_NodeGetLag(pFanout), Seq_NodeGetLValue(pFanout) );
}
*/
// print the result
if ( fVerbose )
printf( "The best clock period is %3d.\n", FiBest );
/*
printf( "LValues : " );
Abc_AigForEachAnd( pNtk, pNode, i )
printf( "%d=%d ", i, Seq_NodeGetLValue(pNode) );
printf( "\n" );
printf( "Lags : " );
Abc_AigForEachAnd( pNtk, pNode, i )
if ( Vec_StrEntry(p->vLags,i) != 0 )
printf( "%d=%d(%d)(%d) ", i, Vec_StrEntry(p->vLags,i), Seq_NodeGetLValue(pNode), Seq_NodeGetLValue(pNode) - FiBest * Vec_StrEntry(p->vLags,i) );
printf( "\n" );
*/
}
/**Function*************************************************************
Synopsis [Performs binary search for the optimal clock period.]
Description [Assumes that FiMin is infeasible while FiMax is feasible.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_RetimeSearch_rec( Abc_Ntk_t * pNtk, int FiMin, int FiMax, int fVerbose )
{
int Median;
assert( FiMin < FiMax );
if ( FiMin + 1 == FiMax )
return FiMax;
Median = FiMin + (FiMax - FiMin)/2;
if ( Seq_RetimeForPeriod( pNtk, Median, fVerbose ) )
return Seq_RetimeSearch_rec( pNtk, FiMin, Median, fVerbose ); // Median is feasible
else
return Seq_RetimeSearch_rec( pNtk, Median, FiMax, fVerbose ); // Median is infeasible
}
/**Function*************************************************************
Synopsis [Returns 1 if retiming with this clock period is feasible.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_RetimeForPeriod( Abc_Ntk_t * pNtk, int Fi, int fVerbose )
{
Abc_Seq_t * p = pNtk->pManFunc;
Abc_Obj_t * pObj;
int i, c, RetValue, fChange, Counter;
char * pReason = "";
// set l-values of all nodes to be minus infinity
Vec_IntFill( p->vLValues, p->nSize, -ABC_INFINITY );
// set l-values of constants and PIs
pObj = Abc_NtkObj( pNtk, 0 );
Seq_NodeSetLValue( pObj, 0 );
Abc_NtkForEachPi( pNtk, pObj, i )
Seq_NodeSetLValue( pObj, 0 );
// update all values iteratively
Counter = 0;
for ( c = 0; c < p->nMaxIters; c++ )
{
fChange = 0;
Abc_AigForEachAnd( pNtk, pObj, i )
{
Counter++;
if ( Seq_NodeCutMan(pObj) )
RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
else
RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
if ( RetValue == SEQ_UPDATE_YES )
fChange = 1;
}
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( Seq_NodeCutMan(pObj) )
RetValue = Seq_FpgaNodeUpdateLValue( pObj, Fi );
else
RetValue = Seq_RetimeNodeUpdateLValue( pObj, Fi );
if ( RetValue == SEQ_UPDATE_FAIL )
break;
}
if ( RetValue == SEQ_UPDATE_FAIL )
break;
if ( fChange == 0 )
break;
}
if ( c == p->nMaxIters )
{
RetValue = SEQ_UPDATE_FAIL;
pReason = "(timeout)";
}
else
c++;
// report the results
if ( fVerbose )
{
if ( RetValue == SEQ_UPDATE_FAIL )
printf( "Period = %3d. Iterations = %3d. Updates = %10d. Infeasible %s\n", Fi, c, Counter, pReason );
else
printf( "Period = %3d. Iterations = %3d. Updates = %10d. Feasible\n", Fi, c, Counter );
}
return RetValue != SEQ_UPDATE_FAIL;
}
/**Function*************************************************************
Synopsis [Computes the l-value of the node.]
Description [The node can be internal or a PO.]
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_RetimeNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
{
int lValueNew, lValueOld, lValue0, lValue1;
assert( !Abc_ObjIsPi(pObj) );
assert( Abc_ObjFaninNum(pObj) > 0 );
lValue0 = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj);
if ( Abc_ObjIsPo(pObj) )
return (lValue0 > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO;
if ( Abc_ObjFaninNum(pObj) == 2 )
lValue1 = Seq_NodeGetLValue(Abc_ObjFanin1(pObj)) - Fi * Seq_ObjFaninL1(pObj);
else
lValue1 = -ABC_INFINITY;
lValueNew = 1 + ABC_MAX( lValue0, lValue1 );
lValueOld = Seq_NodeGetLValue(pObj);
// if ( lValueNew == lValueOld )
if ( lValueNew <= lValueOld )
return SEQ_UPDATE_NO;
Seq_NodeSetLValue( pObj, lValueNew );
return SEQ_UPDATE_YES;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -75,13 +75,16 @@ Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk )
Abc_Obj_t * pObj, * pFaninNew;
Vec_Int_t * vInitValues;
Abc_InitType_t Init;
int i, k;
int i, k, RetValue;
// make sure it is an AIG without self-feeding latches
assert( Abc_NtkIsStrash(pNtk) );
assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 );
assert( Abc_NtkIsDfsOrdered(pNtk) );
if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) )
printf( "Modified %d self-feeding latches. The result will not verify.\n", RetValue );
assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 );
// start the network
pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG );
// duplicate the name and the spec
......@@ -235,7 +238,6 @@ void Abc_NtkAigCutsetCopy( Abc_Ntk_t * pNtk )
}
}
/**Function*************************************************************
Synopsis [Converts a sequential AIG into a logic SOP network.]
......@@ -251,6 +253,76 @@ Abc_Ntk_t * Abc_NtkSeqToLogicSop( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pObjNew, * pFaninNew;
Seq_Lat_t * pRing;
int i;
assert( Abc_NtkIsSeq(pNtk) );
// start the network without latches
pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
// duplicate the nodes
Abc_AigForEachAnd( pNtk, pObj, i )
{
Abc_NtkDupObj(pNtkNew, pObj);
pObj->pCopy->pData = Abc_SopCreateAnd2( pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
}
// share and create the latches
Seq_NtkShareLatches( pNtkNew, pNtk );
// connect the objects
Abc_AigForEachAnd( pNtk, pObj, i )
{
if ( pRing = Seq_NodeGetRing(pObj,0) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
if ( pRing = Seq_NodeGetRing(pObj,1) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin1(pObj)->pCopy;
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
}
// connect the POs
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( pRing = Seq_NodeGetRing(pObj,0) )
pFaninNew = pRing->pLatch;
else
pFaninNew = Abc_ObjFanin0(pObj)->pCopy;
pFaninNew = Abc_ObjNotCond( pFaninNew, Abc_ObjFaninC0(pObj) );
Abc_ObjAddFanin( pObj->pCopy, pFaninNew );
}
// add the latches and their names
Abc_NtkAddDummyLatchNames( pNtkNew );
Abc_NtkForEachLatch( pNtkNew, pObjNew, i )
{
Vec_PtrPush( pNtkNew->vCis, pObjNew );
Vec_PtrPush( pNtkNew->vCos, pObjNew );
}
// fix the problem with complemented and duplicated CO edges
Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
if ( !Abc_NtkCheck( pNtkNew ) )
fprintf( stdout, "Abc_NtkSeqToLogicSop(): Network check has failed.\n" );
return pNtkNew;
}
/**Function*************************************************************
Synopsis [Converts a sequential AIG into a logic SOP network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkSeqToLogicSop_old( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNew;
Abc_Obj_t * pObj, * pObjNew, * pFaninNew;
int i;
assert( Abc_NtkIsSeq(pNtk) );
......
......@@ -30,6 +30,7 @@ static void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t *
static Cut_Cut_t * Seq_FpgaMappingSelectCut( Abc_Obj_t * pAnd );
extern Cut_Man_t * Abc_NtkSeqCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
extern Cut_Man_t * Abc_NtkCuts( Abc_Ntk_t * pNtk, Cut_Params_t * pParams );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
......@@ -53,9 +54,6 @@ void Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose )
Abc_Obj_t * pObj;
int i, clk;
// get the LUT library
p->nVarsMax = Fpga_LutLibReadVarMax( Abc_FrameReadLibLut() );
// set defaults for cut computation
memset( pParams, 0, sizeof(Cut_Params_t) );
pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts)
......@@ -68,13 +66,16 @@ void Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose )
// compute the cuts
clk = clock();
p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams );
// pParams->fSeq = 0;
// p->pCutMan = Abc_NtkCuts( pNtk, pParams );
p->timeCuts = clock() - clk;
if ( fVerbose )
Cut_ManPrintStats( p->pCutMan );
// compute the delays
clk = clock();
Seq_NtkRetimeDelayLags( pNtk, fVerbose );
Seq_AigRetimeDelayLags( pNtk, fVerbose );
p->timeDelay = clock() - clk;
// collect the nodes and cuts used in the mapping
......@@ -129,8 +130,6 @@ void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec
Vec_PtrPush( vMapping, pAnd );
for ( k = 0; k < (int)pCutBest->nLeaves; k++ )
Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pCutBest->pLeaves[k] );
//printf( "Adding %d.\n", pAnd->Id );
}
/**Function*************************************************************
......@@ -237,6 +236,9 @@ int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
}
// get the arrival time of the best non-trivial cut
pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj );
// skip the choice nodes
if ( pList == NULL )
return SEQ_UPDATE_NO;
lValueNew = ABC_INFINITY;
for ( pCut = pList->pNext; pCut; pCut = pCut->pNext )
{
......@@ -249,8 +251,8 @@ int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi )
// if ( lValueNew == lValueOld )
if ( lValueNew <= lValueOld )
return SEQ_UPDATE_NO;
//printf( "%d ", lValueNew );
Seq_NodeSetLValue( pObj, lValueNew );
//printf( "%d -> %d ", lValueOld, lValueNew );
return SEQ_UPDATE_YES;
}
......
......@@ -49,12 +49,17 @@ Abc_Seq_t * Seq_Create( Abc_Ntk_t * pNtk )
memset( p, 0, sizeof(Abc_Seq_t) );
p->pNtk = pNtk;
p->nSize = 1000;
p->pMmInits = Extra_MmFixedStart( sizeof(Seq_Lat_t) );
p->nMaxIters = 15;
p->pMmInits = Extra_MmFixedStart( sizeof(Seq_Lat_t) );
p->fEpsilon = (float)0.001;
// create internal data structures
p->vNums = Vec_IntStart( 2 * p->nSize );
p->vInits = Vec_PtrStart( 2 * p->nSize );
p->vLValues = Vec_IntStart( p->nSize );
p->vLags = Vec_StrStart( p->nSize );
p->vNums = Vec_IntStart( 2 * p->nSize );
p->vInits = Vec_PtrStart( 2 * p->nSize );
p->vLValues = Vec_IntStart( p->nSize );
p->vLags = Vec_StrStart( p->nSize );
p->vLValuesN = Vec_IntStart( p->nSize );
p->vLagsN = Vec_StrStart( p->nSize );
p->vUses = Vec_StrStart( p->nSize );
return p;
}
......@@ -78,6 +83,9 @@ void Seq_Resize( Abc_Seq_t * p, int nMaxId )
Vec_PtrFill( p->vInits, 2 * p->nSize, NULL );
Vec_IntFill( p->vLValues, p->nSize, 0 );
Vec_StrFill( p->vLags, p->nSize, 0 );
Vec_IntFill( p->vLValuesN, p->nSize, 0 );
Vec_StrFill( p->vLagsN, p->nSize, 0 );
Vec_StrFill( p->vUses, p->nSize, 0 );
}
......@@ -94,10 +102,19 @@ void Seq_Resize( Abc_Seq_t * p, int nMaxId )
***********************************************************************/
void Seq_Delete( Abc_Seq_t * p )
{
if ( p->fStandCells )
{
void * pVoid; int i;
Vec_PtrForEachEntry( p->vMapAnds, pVoid, i )
free( pVoid );
}
if ( p->vMapAnds ) Vec_PtrFree( p->vMapAnds ); // the nodes used in the mapping
if ( p->vMapCuts ) Vec_VecFree( p->vMapCuts ); // the cuts used in the mapping
if ( p->vLValues ) Vec_IntFree( p->vLValues ); // the arrival times (L-Values of nodes)
if ( p->vLags ) Vec_StrFree( p->vLags ); // the lags of the mapped nodes
if ( p->vLValuesN ) Vec_IntFree( p->vLValuesN ); // the arrival times (L-Values of nodes)
if ( p->vLagsN ) Vec_StrFree( p->vLagsN ); // the lags of the mapped nodes
if ( p->vUses ) Vec_StrFree( p->vUses ); // the uses of phases
if ( p->vInits ) Vec_PtrFree( p->vInits ); // the initial values of the latches
if ( p->vNums ) Vec_IntFree( p->vNums ); // the numbers of latches
Extra_MmFixedStop( p->pMmInits, 0 );
......
......@@ -160,8 +160,188 @@ void Seq_NodeShareOne( Abc_Obj_t * pNode, Abc_InitType_t Init, Vec_Ptr_t * vNode
Abc_ObjPatchFanin( pFanout, pNode, pBuffer );
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline unsigned Seq_NtkShareLatchesKey( Abc_Obj_t * pObj, Abc_InitType_t Init )
{
return (pObj->Id << 2) | Init;
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Seq_NtkShareLatches_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj, Seq_Lat_t * pRing, int nLatch, stmm_table * tLatchMap )
{
Abc_Obj_t * pLatch, * pFanin;
Abc_InitType_t Init;
unsigned Key;
if ( nLatch == 0 )
return pObj;
assert( pRing->pLatch == NULL );
// get the latch on the previous level
pFanin = Seq_NtkShareLatches_rec( pNtk, pObj, Seq_LatNext(pRing), nLatch - 1, tLatchMap );
// get the initial state
Init = Seq_LatInit( pRing );
// check if the latch with this initial state exists
Key = Seq_NtkShareLatchesKey( pFanin, Init );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
return pRing->pLatch = pLatch;
// does not exist
if ( Init != ABC_INIT_DC )
{
// check if the don't-care exists
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) ) // yes
{
// update the table
stmm_delete( tLatchMap, (char **)&Key, (char **)&pLatch );
Key = Seq_NtkShareLatchesKey( pFanin, Init );
stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
// change don't-care to the given value
pLatch->pData = (void *)Init;
return pRing->pLatch = pLatch;
}
// add the latch with this value
pLatch = Abc_NtkCreateLatch( pNtk );
pLatch->pData = (void *)Init;
Abc_ObjAddFanin( pLatch, pFanin );
// add it to the table
Key = Seq_NtkShareLatchesKey( pFanin, Init );
stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
return pRing->pLatch = pLatch;
}
// the init value is the don't-care
// check if care values exist
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ZERO );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
{
Seq_LatSetInit( pRing, ABC_INIT_ZERO );
return pRing->pLatch = pLatch;
}
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_ONE );
if ( stmm_lookup( tLatchMap, (char *)Key, (char **)&pLatch ) )
{
Seq_LatSetInit( pRing, ABC_INIT_ONE );
return pRing->pLatch = pLatch;
}
// create the don't-care latch
pLatch = Abc_NtkCreateLatch( pNtk );
pLatch->pData = (void *)ABC_INIT_DC;
Abc_ObjAddFanin( pLatch, pFanin );
// add it to the table
Key = Seq_NtkShareLatchesKey( pFanin, ABC_INIT_DC );
stmm_insert( tLatchMap, (char *)Key, (char *)pLatch );
return pRing->pLatch = pLatch;
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description [Creates new latches and assigns them to virtual latches
on the edges of a sequential AIG. The nodes of the new network should
be created before this procedure is called.]
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
stmm_table * tLatchMap;
int i;
assert( Abc_NtkIsSeq( pNtk ) );
tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash );
Abc_AigForEachAnd( pNtk, pObj, i )
{
Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin0(pObj)->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap );
Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin1(pObj)->pCopy, Seq_NodeGetRing(pObj,1), Seq_NodeCountLats(pObj,1), tLatchMap );
}
Abc_NtkForEachPo( pNtk, pObj, i )
Seq_NtkShareLatches_rec( pNtkNew, Abc_ObjFanin0(pObj)->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap );
stmm_free_table( tLatchMap );
}
/**Function*************************************************************
Synopsis [Maps virtual latches into real latches.]
Description [Creates new latches and assigns them to virtual latches
on the edges of a sequential AIG. The nodes of the new network should
be created before this procedure is called.]
SideEffects []
SeeAlso []
***********************************************************************/
void Seq_NtkShareLatchesFpga( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, Vec_Ptr_t * vMapAnds )
{
Abc_Obj_t * pObj, * pFanout;
stmm_table * tLatchMap;
int i, k, nOldNodes;
assert( Abc_NtkIsSeq( pNtk ) );
// start the table
tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash );
// remember the old nodes
nOldNodes = Vec_PtrSize( vMapAnds );
// add constant and PIs
Vec_PtrPush( vMapAnds, Abc_NtkConst1(pNtk) );
Abc_NtkForEachPi( pNtk, pObj, i )
Vec_PtrPush( vMapAnds, pObj );
// process nodes used in the mapping
Vec_PtrForEachEntry( vMapAnds, pObj, i )
{
// make sure the label is clean
Abc_ObjForEachFanout( pObj, pFanout, k )
assert( pFanout->fMarkC == 0 );
Abc_ObjForEachFanout( pObj, pFanout, k )
{
if ( pFanout->fMarkC )
continue;
pFanout->fMarkC = 1;
if ( Abc_ObjFaninId0(pFanout) == pObj->Id )
Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,0), Seq_NodeCountLats(pFanout,0), tLatchMap );
if ( Abc_ObjFaninId1(pFanout) == pObj->Id )
Seq_NtkShareLatches_rec( pNtkNew, pObj->pCopy, Seq_NodeGetRing(pFanout,1), Seq_NodeCountLats(pFanout,1), tLatchMap );
}
// clean the label
Abc_ObjForEachFanout( pObj, pFanout, k )
pFanout->fMarkC = 0;
}
stmm_free_table( tLatchMap );
// return to the old array
Vec_PtrShrink( vMapAnds, nOldNodes );
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......@@ -39,6 +39,37 @@
SeeAlso []
***********************************************************************/
int Seq_NtkLevelMax( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pNode;
int i, Result;
assert( Abc_NtkIsSeq(pNtk) );
Result = 0;
Abc_NtkForEachPo( pNtk, pNode, i )
{
pNode = Abc_ObjFanin0(pNode);
if ( Result < (int)pNode->Level )
Result = pNode->Level;
}
Abc_SeqForEachCutsetNode( pNtk, pNode, i )
{
if ( Result < (int)pNode->Level )
Result = pNode->Level;
}
return Result;
}
/**Function*************************************************************
Synopsis [Returns the maximum latch number on any of the fanouts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_ObjFanoutLMax( Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanout;
......@@ -363,6 +394,29 @@ int Seq_NtkLatchGetEqualFaninNum( Abc_Ntk_t * pNtk )
return Counter;
}
/**Function*************************************************************
Synopsis [Returns the maximum latch number on any of the fanouts.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Seq_NtkCountNodesAboveLimit( Abc_Ntk_t * pNtk, int Limit )
{
Abc_Obj_t * pNode;
int i, Counter;
assert( !Abc_NtkIsSeq(pNtk) );
Counter = 0;
Abc_NtkForEachNode( pNtk, pNode, i )
if ( Abc_ObjFaninNum(pNode) > Limit )
Counter++;
return Counter;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -57,8 +57,8 @@ void Fpga_Init( Abc_Frame_t * pAbc )
{
// set the default library
//Fpga_LutLib_t s_LutLib = { "lutlib", 6, {0,1,2,4,8,16,32}, {0,1,2,3,4,5,6} };
//Fpga_LutLib_t s_LutLib = { "lutlib", 5, {0,1,1,1,1,1}, {0,1,1,1,1,1} };
Fpga_LutLib_t s_LutLib = { "lutlib", 4, {0,1,1,1,1}, {0,1,1,1,1} };
Fpga_LutLib_t s_LutLib = { "lutlib", 5, {0,1,1,1,1,1}, {0,1,1,1,1,1} };
//Fpga_LutLib_t s_LutLib = { "lutlib", 4, {0,1,1,1,1}, {0,1,1,1,1} };
//Fpga_LutLib_t s_LutLib = { "lutlib", 3, {0,1,1,1}, {0,1,1,1} };
Abc_FrameSetLibLut( Fpga_LutLibDup(&s_LutLib) );
......
......@@ -439,6 +439,9 @@ int Map_LibraryDeriveGateInfo( Map_SuperLib_t * pLib, st_table * tExcludeGate )
pGate->tDelayMax.Fall = pGate->tDelaysF[k].Rise;
if ( pGate->tDelayMax.Fall < pGate->tDelaysF[k].Fall )
pGate->tDelayMax.Fall = pGate->tDelaysF[k].Fall;
pGate->tDelaysF[k].Worst = MAP_MAX( pGate->tDelaysF[k].Fall, pGate->tDelaysF[k].Rise );
pGate->tDelaysR[k].Worst = MAP_MAX( pGate->tDelaysR[k].Fall, pGate->tDelaysR[k].Rise );
}
// count gates and area of the supergate
......
......@@ -90,6 +90,7 @@ extern float Mio_LibraryReadDelayInvMax( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayNand2Max( Mio_Library_t * pLib );
extern float Mio_LibraryReadDelayAnd2Max( Mio_Library_t * pLib );
extern float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib );
extern float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib );
extern float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib );
......
......@@ -53,6 +53,7 @@ float Mio_LibraryReadDelayInvMax ( Mio_Library_t * pLib ) { retur
float Mio_LibraryReadDelayNand2Rise( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockRise : 0.0); }
float Mio_LibraryReadDelayNand2Fall( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockFall : 0.0); }
float Mio_LibraryReadDelayNand2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->pPins->dDelayBlockMax : 0.0); }
float Mio_LibraryReadDelayAnd2Max ( Mio_Library_t * pLib ) { return (float)(pLib->pGateAnd2? pLib->pGateAnd2->pPins->dDelayBlockMax : 0.0); }
float Mio_LibraryReadAreaInv ( Mio_Library_t * pLib ) { return (float)(pLib->pGateInv? pLib->pGateInv->dArea : 0.0); }
float Mio_LibraryReadAreaBuf ( Mio_Library_t * pLib ) { return (float)(pLib->pGateBuf? pLib->pGateBuf->dArea : 0.0); }
float Mio_LibraryReadAreaNand2 ( Mio_Library_t * pLib ) { return (float)(pLib->pGateNand2? pLib->pGateNand2->dArea : 0.0); }
......
......@@ -29,7 +29,6 @@
#define inline __inline // compatible with MS VS 6.0
#endif
#include "vecFan.h"
#include "vecInt.h"
#include "vecStr.h"
#include "vecPtr.h"
......
......@@ -457,6 +457,41 @@ static inline void Vec_IntPush( Vec_Int_t * p, int Entry )
SeeAlso []
***********************************************************************/
static inline void Vec_IntPushMem( Extra_MmStep_t * pMemMan, Vec_Int_t * p, int Entry )
{
if ( p->nSize == p->nCap )
{
int * pArray;
int i;
if ( p->nSize == 0 )
p->nCap = 1;
pArray = (int *)Extra_MmStepEntryFetch( pMemMan, p->nCap * 8 );
// pArray = ALLOC( int, p->nCap * 2 );
if ( p->pArray )
{
for ( i = 0; i < p->nSize; i++ )
pArray[i] = p->pArray[i];
Extra_MmStepEntryRecycle( pMemMan, (char *)p->pArray, p->nCap * 4 );
// free( p->pArray );
}
p->nCap *= 2;
p->pArray = pArray;
}
p->pArray[p->nSize++] = Entry;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline void Vec_IntPushOrder( Vec_Int_t * p, int Entry )
{
int i;
......@@ -516,6 +551,26 @@ static inline int Vec_IntPop( Vec_Int_t * p )
/**Function*************************************************************
Synopsis [Find entry.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
static inline int Vec_IntFind( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
return i;
return -1;
}
/**Function*************************************************************
Synopsis []
Description []
......@@ -525,16 +580,19 @@ static inline int Vec_IntPop( Vec_Int_t * p )
SeeAlso []
***********************************************************************/
static inline void Vec_IntRemove( Vec_Int_t * p, int Entry )
static inline int Vec_IntRemove( Vec_Int_t * p, int Entry )
{
int i;
for ( i = 0; i < p->nSize; i++ )
if ( p->pArray[i] == Entry )
break;
if ( i == p->nSize )
return 0;
assert( i < p->nSize );
for ( i++; i < p->nSize; i++ )
p->pArray[i-1] = p->pArray[i];
p->nSize--;
return 1;
}
/**Function*************************************************************
......
......@@ -69,6 +69,8 @@ struct Cut_CutStruct_t_
unsigned nVarsMax : 4; // the max number of vars [4-6]
unsigned nLeaves : 4; // the number of leaves [4-6]
unsigned uSign; // the signature
unsigned uCanon0; // the canonical form
unsigned uCanon1; // the canonical form
Cut_Cut_t * pNext; // the next cut in the list
int pLeaves[0]; // the array of leaves
};
......@@ -113,6 +115,7 @@ extern int Cut_ManReadVarsMax( Cut_Man_t * p );
/*=== cutNode.c ==========================================================*/
extern Cut_Cut_t * Cut_NodeComputeCuts( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int fTriv );
extern Cut_Cut_t * Cut_NodeUnionCuts( Cut_Man_t * p, Vec_Int_t * vNodes );
extern Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst );
/*=== cutSeq.c ==========================================================*/
extern void Cut_NodeComputeCutsSeq( Cut_Man_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1, int nLat0, int nLat1, int fTriv, int CutSetNum );
extern void Cut_NodeNewMergeWithOld( Cut_Man_t * p, int Node );
......@@ -126,6 +129,8 @@ extern int Cut_OracleReadDrop( Cut_Oracle_t * p );
extern void Cut_OracleNodeSetTriv( Cut_Oracle_t * p, int Node );
extern Cut_Cut_t * Cut_OracleComputeCuts( Cut_Oracle_t * p, int Node, int Node0, int Node1, int fCompl0, int fCompl1 );
extern void Cut_OracleTryDroppingCuts( Cut_Oracle_t * p, int Node );
/*=== cutTruth.c ==========================================================*/
extern void Cut_TruthCanonicize( Cut_Cut_t * pCut );
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
......
......@@ -376,6 +376,7 @@ void Cut_NodeDoComputeCuts( Cut_Man_t * p, Cut_List_t * pSuper, int Node, int fC
// start with the elementary cut
if ( fTriv )
{
// printf( "Creating trivial cut %d.\n", Node );
pTemp0 = Cut_CutCreateTriv( p, Node );
Cut_ListAdd( pSuper, pTemp0 );
p->nNodeCuts++;
......@@ -542,6 +543,189 @@ p->timeUnion += clock() - clk;
return pList;
}
/**Function*************************************************************
Synopsis [Computes the cuts by unioning cuts at a choice node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Cut_Cut_t * Cut_NodeUnionCutsSeq( Cut_Man_t * p, Vec_Int_t * vNodes, int CutSetNum, int fFirst )
{
Cut_List_t Super, * pSuper = &Super;
Cut_Cut_t * pList, * pListStart, * pCut, * pCut2, * pTop;
int i, k, Node, Root, Limit = p->pParams->nVarsMax;
int clk = clock();
// start the new list
Cut_ListStart( pSuper );
// remember the root node to save the resulting cuts
Root = Vec_IntEntry( vNodes, 0 );
p->nNodeCuts = 1;
// store the original lists for comparison
p->pCompareOld = Cut_NodeReadCutsOld( p, Root );
p->pCompareNew = (CutSetNum >= 0)? Cut_NodeReadCutsNew( p, Root ) : NULL;
// get the topmost cut
pTop = NULL;
if ( (pTop = Cut_NodeReadCutsOld( p, Root )) == NULL )
pTop = Cut_NodeReadCutsNew( p, Root );
assert( pTop != NULL );
// collect small cuts first
Vec_PtrClear( p->vTemp );
Vec_IntForEachEntry( vNodes, Node, i )
{
// get the cuts of this node
if ( i == 0 && CutSetNum >= 0 )
{
pList = Cut_NodeReadCutsTemp( p, CutSetNum );
Cut_NodeWriteCutsTemp( p, CutSetNum, NULL );
}
else
{
pList = Cut_NodeReadCutsNew( p, Node );
Cut_NodeWriteCutsNew( p, Node, NULL );
}
if ( pList == NULL )
continue;
// process the cuts
if ( fFirst )
{
// remember the starting point
pListStart = pList->pNext;
pList->pNext = NULL;
// save or recycle the elementary cut
if ( i == 0 )
Cut_ListAdd( pSuper, pList );
else
Cut_CutRecycle( p, pList );
}
else
pListStart = pList;
// save all the cuts that are smaller than the limit
Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
{
if ( pCut->nLeaves == (unsigned)Limit )
{
Vec_PtrPush( p->vTemp, pCut );
break;
}
// check containment
// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
// continue;
if ( p->pParams->fFilter )
{
if ( Cut_CutFilterOne(p, pSuper, pCut) )
continue;
if ( p->pParams->fSeq )
{
if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
continue;
if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
continue;
}
}
// set the complemented bit by comparing the first cut with the current cut
pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
pListStart = pCut->pNext;
pCut->pNext = NULL;
// add to the list
Cut_ListAdd( pSuper, pCut );
if ( ++p->nNodeCuts == p->pParams->nKeepMax )
{
// recycle the rest of the cuts of this node
Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
// recycle all cuts of other nodes
Vec_IntForEachEntryStart( vNodes, Node, k, i+1 )
Cut_NodeFreeCuts( p, Node );
// recycle the saved cuts of other nodes
Vec_PtrForEachEntry( p->vTemp, pList, k )
Cut_ListForEachCutSafe( pList, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
goto finish;
}
}
}
// collect larger cuts next
Vec_PtrForEachEntry( p->vTemp, pList, i )
{
Cut_ListForEachCutSafe( pList, pCut, pCut2 )
{
// check containment
// if ( p->pParams->fFilter && Cut_CutFilterOne( p, pSuper, pCut ) )
// continue;
if ( p->pParams->fFilter )
{
if ( Cut_CutFilterOne(p, pSuper, pCut) )
continue;
if ( p->pParams->fSeq )
{
if ( p->pCompareOld && Cut_CutFilterOld(p, p->pCompareOld, pCut) )
continue;
if ( p->pCompareNew && Cut_CutFilterOld(p, p->pCompareNew, pCut) )
continue;
}
}
// set the complemented bit
pCut->fCompl = pTop->fSimul ^ pCut->fSimul;
pListStart = pCut->pNext;
pCut->pNext = NULL;
// add to the list
Cut_ListAdd( pSuper, pCut );
if ( ++p->nNodeCuts == p->pParams->nKeepMax )
{
// recycle the rest of the cuts
Cut_ListForEachCutSafe( pListStart, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
// recycle the saved cuts of other nodes
Vec_PtrForEachEntryStart( p->vTemp, pList, k, i+1 )
Cut_ListForEachCutSafe( pList, pCut, pCut2 )
Cut_CutRecycle( p, pCut );
goto finish;
}
}
}
finish :
// set the cuts at the node
pList = Cut_ListFinish( pSuper );
// set the lists at the node
// assert( Cut_NodeReadCutsNew(p, Root) == NULL );
// Cut_NodeWriteCutsNew( p, Root, pList );
if ( CutSetNum >= 0 )
{
assert( Cut_NodeReadCutsTemp(p, CutSetNum) == NULL );
Cut_NodeWriteCutsTemp( p, CutSetNum, pList );
}
else
{
assert( Cut_NodeReadCutsNew(p, Root) == NULL );
Cut_NodeWriteCutsNew( p, Root, pList );
}
p->timeUnion += clock() - clk;
// filter the cuts
//clk = clock();
// if ( p->pParams->fFilter )
// Cut_CutFilter( p, pList );
//p->timeFilter += clock() - clk;
// if ( fFirst )
// p->nNodes -= vNodes->nSize - 1;
return pList;
}
/**Function*************************************************************
......
......@@ -107,6 +107,48 @@ void Cut_TruthCompute( Cut_Cut_t * pCut, Cut_Cut_t * pCut0, Cut_Cut_t * pCut1, i
}
}
/**Function*************************************************************
Synopsis [Performs truth table computation.]
Description [This procedure cannot be used while recording oracle
because it will overwrite Num0 and Num1.]
SideEffects []
SeeAlso []
***********************************************************************/
void Cut_TruthCanonicize( Cut_Cut_t * pCut )
{
unsigned uTruth;
unsigned * uCanon2;
char * pPhases2;
assert( pCut->nVarsMax < 6 );
// get the direct truth table
uTruth = *Cut_CutReadTruth(pCut);
// compute the direct truth table
Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
// uCanon[0] = uCanon2[0];
// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
// uPhases[0] = pPhases2[0];
pCut->uCanon0 = uCanon2[0];
pCut->Num0 = pPhases2[0];
// get the complemented truth table
uTruth = ~*Cut_CutReadTruth(pCut);
// compute the direct truth table
Extra_TruthCanonFastN( pCut->nVarsMax, pCut->nLeaves, &uTruth, &uCanon2, &pPhases2 );
// uCanon[0] = uCanon2[0];
// uCanon[1] = (p->nVarsMax == 6)? uCanon2[1] : uCanon2[0];
// uPhases[0] = pPhases2[0];
pCut->uCanon1 = uCanon2[0];
pCut->Num1 = pPhases2[0];
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
......
......@@ -96,6 +96,7 @@ struct Dec_Man_t_
/*=== decAbc.c ========================================================*/
extern Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph );
extern Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph );
extern int Dec_GraphToNetworkCount( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, int NodeMax, int LevelMax );
extern void Dec_GraphUpdateNetwork( Abc_Obj_t * pRoot, Dec_Graph_t * pGraph, bool fUpdateLevel, int nGain );
/*=== decFactor.c ========================================================*/
......
......@@ -63,6 +63,44 @@ Abc_Obj_t * Dec_GraphToNetwork( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
/**Function*************************************************************
Synopsis [Transforms the decomposition graph into the AIG.]
Description [AIG nodes for the fanins should be assigned to pNode->pFunc
of the leaves of the graph before calling this procedure.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Obj_t * Dec_GraphToNetworkNoStrash( Abc_Ntk_t * pNtk, Dec_Graph_t * pGraph )
{
Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
Dec_Node_t * pNode;
int i;
// check for constant function
if ( Dec_GraphIsConst(pGraph) )
return Abc_ObjNotCond( Abc_NtkConst1(pNtk), Dec_GraphIsComplement(pGraph) );
// check for a literal
if ( Dec_GraphIsVar(pGraph) )
return Abc_ObjNotCond( Dec_GraphVar(pGraph)->pFunc, Dec_GraphIsComplement(pGraph) );
// build the AIG nodes corresponding to the AND gates of the graph
Dec_GraphForEachNode( pGraph, pNode, i )
{
pAnd0 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge0.Node)->pFunc, pNode->eEdge0.fCompl );
pAnd1 = Abc_ObjNotCond( Dec_GraphNode(pGraph, pNode->eEdge1.Node)->pFunc, pNode->eEdge1.fCompl );
// pNode->pFunc = Abc_AigAnd( pNtk->pManFunc, pAnd0, pAnd1 );
pAnd = Abc_NtkCreateNode( pNtk );
Abc_ObjAddFanin( pAnd, pAnd0 );
Abc_ObjAddFanin( pAnd, pAnd1 );
pNode->pFunc = pAnd;
}
// complement the result if necessary
return Abc_ObjNotCond( pNode->pFunc, Dec_GraphIsComplement(pGraph) );
}
/**Function*************************************************************
Synopsis [Counts the number of new nodes added when using this graph.]
Description [AIG nodes for the fanins should be assigned to pNode->pFunc
......
......@@ -24,11 +24,11 @@
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder );
static void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder );
static int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY );
static void Fxu_CreateCoversNode( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode, Fxu_Cube * pCubeFirst, Fxu_Cube * pCubeNext );
static Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iNode );
static Abc_Fan_t * s_pLits;
static int * s_pLits;
extern int Fxu_PreprocessCubePairs( Fxu_Matrix * p, Vec_Ptr_t * vCovers, int nPairsTotal, int nPairsMax );
......@@ -53,7 +53,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
Fxu_Var * pVar;
Fxu_Cube * pCubeFirst, * pCubeNew;
Fxu_Cube * pCube1, * pCube2;
Vec_Fan_t * vFanins;
Vec_Int_t * vFanins;
char * pSopCover;
char * pSopCube;
int * pOrder, nBitsMax;
......@@ -151,7 +151,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
pOrder[v] = v;
// reorder the fanins
qsort( (void *)pOrder, nFanins, sizeof(int),(int (*)(const void *, const void *))Fxu_CreateMatrixLitCompare);
assert( s_pLits[ pOrder[0] ].iFan < s_pLits[ pOrder[nFanins-1] ].iFan );
assert( s_pLits[ pOrder[0] ] < s_pLits[ pOrder[nFanins-1] ] );
// create the corresponding cubes in the matrix
pCubeFirst = NULL;
c = 0;
......@@ -214,7 +214,7 @@ Fxu_Matrix * Fxu_CreateMatrix( Fxu_Data_t * pData )
SeeAlso []
***********************************************************************/
void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Fan_t * vFanins, int * pOrder )
void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube, Vec_Int_t * vFanins, int * pOrder )
{
Fxu_Var * pVar;
int Value, i;
......@@ -224,12 +224,12 @@ void Fxu_CreateMatrixAddCube( Fxu_Matrix * p, Fxu_Cube * pCube, char * pSopCube,
Value = pSopCube[pOrder[i]];
if ( Value == '0' )
{
pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan + 1 ]; // CST
pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] + 1 ]; // CST
Fxu_MatrixAddLiteral( p, pCube, pVar );
}
else if ( Value == '1' )
{
pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]].iFan ]; // CST
pVar = p->ppVars[ 2 * vFanins->pArray[pOrder[i]] ]; // CST
Fxu_MatrixAddLiteral( p, pCube, pVar );
}
}
......@@ -409,7 +409,7 @@ Fxu_Cube * Fxu_CreateCoversFirstCube( Fxu_Matrix * p, Fxu_Data_t * pData, int iV
***********************************************************************/
int Fxu_CreateMatrixLitCompare( int * ptrX, int * ptrY )
{
return s_pLits[*ptrX].iFan - s_pLits[*ptrY].iFan;
return s_pLits[*ptrX] - s_pLits[*ptrY];
}
////////////////////////////////////////////////////////////////////////
......
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