mirror of https://github.com/YosysHQ/abc.git
Version abc50824
This commit is contained in:
parent
d01b1a0eee
commit
9093ca5320
4
abc.dsp
4
abc.dsp
|
|
@ -109,6 +109,10 @@ SOURCE=.\src\base\abc\abcAttach.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\abc\abcBalance.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\src\base\abc\abcCheck.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
|||
2
abc.rc
2
abc.rc
|
|
@ -3,6 +3,7 @@ alias clp collapse
|
|||
alias esd ext_seq_dcs
|
||||
alias f fraig
|
||||
alias fs fraig_sweep
|
||||
alias ft fraig_trust
|
||||
alias mu renode -m
|
||||
alias pf print_factor
|
||||
alias pfan print_fanio
|
||||
|
|
@ -20,6 +21,7 @@ alias rsup read_super mcnc5_old.super
|
|||
alias rlib read_library
|
||||
alias rw rewrite
|
||||
alias rf refactor
|
||||
alias rfz refactor -z
|
||||
alias sa set autoexec ps
|
||||
alias so source -x
|
||||
alias st strash
|
||||
|
|
|
|||
|
|
@ -1414,9 +1414,10 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
int c;
|
||||
int nNodeSizeMax;
|
||||
int nConeSizeMax;
|
||||
bool fUseZeros;
|
||||
bool fUseDcs;
|
||||
bool fVerbose;
|
||||
extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose );
|
||||
extern int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose );
|
||||
|
||||
pNtk = Abc_FrameReadNet(pAbc);
|
||||
pOut = Abc_FrameReadOut(pAbc);
|
||||
|
|
@ -1424,11 +1425,12 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
|
||||
// set defaults
|
||||
nNodeSizeMax = 10;
|
||||
nConeSizeMax = 10;
|
||||
nConeSizeMax = 16;
|
||||
fUseZeros = 0;
|
||||
fUseDcs = 0;
|
||||
fVerbose = 0;
|
||||
fVerbose = 1;
|
||||
util_getopt_reset();
|
||||
while ( ( c = util_getopt( argc, argv, "NCdvh" ) ) != EOF )
|
||||
while ( ( c = util_getopt( argc, argv, "NCzdvh" ) ) != EOF )
|
||||
{
|
||||
switch ( c )
|
||||
{
|
||||
|
|
@ -1454,6 +1456,9 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
if ( nConeSizeMax < 0 )
|
||||
goto usage;
|
||||
break;
|
||||
case 'z':
|
||||
fUseZeros ^= 1;
|
||||
break;
|
||||
case 'd':
|
||||
fUseDcs ^= 1;
|
||||
break;
|
||||
|
|
@ -1483,8 +1488,14 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 1;
|
||||
}
|
||||
|
||||
if ( fUseDcs && nNodeSizeMax >= nConeSizeMax )
|
||||
{
|
||||
fprintf( pErr, "For don't-care to work, containing cone should be larger than collapsed node.\n" );
|
||||
return 1;
|
||||
}
|
||||
|
||||
// modify the current network
|
||||
if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose ) )
|
||||
if ( !Abc_NtkRefactor( pNtk, nNodeSizeMax, nConeSizeMax, fUseZeros, fUseDcs, fVerbose ) )
|
||||
{
|
||||
fprintf( pErr, "Refactoring has failed.\n" );
|
||||
return 1;
|
||||
|
|
@ -1492,11 +1503,12 @@ int Abc_CommandRefactor( Abc_Frame_t * pAbc, int argc, char ** argv )
|
|||
return 0;
|
||||
|
||||
usage:
|
||||
fprintf( pErr, "usage: refactor [-N num] [-C num] [-dvh]\n" );
|
||||
fprintf( pErr, "usage: refactor [-N num] [-C num] [-zdvh]\n" );
|
||||
fprintf( pErr, "\t performs technology-independent refactoring of the AIG\n" );
|
||||
fprintf( pErr, "\t-N num : the max support of the collapsed node [default = %d]\n", nNodeSizeMax );
|
||||
fprintf( pErr, "\t-C num : the max support of the containing cone [default = %d]\n", nConeSizeMax );
|
||||
fprintf( pErr, "\t-d : toggle use of don't-cares [default = %s]\n", fUseDcs? "yes": "no" );
|
||||
fprintf( pErr, "\t-z : toggle using zero-cost replacements [default = %s]\n", fUseZeros? "yes": "no" );
|
||||
fprintf( pErr, "\t-d : toggle using don't-cares [default = %s]\n", fUseDcs? "yes": "no" );
|
||||
fprintf( pErr, "\t-v : toggle verbose printout [default = %s]\n", fVerbose? "yes": "no" );
|
||||
fprintf( pErr, "\t-h : print the command usage\n");
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ struct Abc_Time_t_
|
|||
struct Abc_Obj_t_ // 12 words
|
||||
{
|
||||
// high-level information
|
||||
Abc_Ntk_t * pNtk; // the host network
|
||||
unsigned Type : 4; // the object type
|
||||
unsigned fExor : 1; // marks AIG node that is a root of EXOR
|
||||
unsigned Id : 27; // the ID of the object
|
||||
|
|
@ -115,7 +116,6 @@ struct Abc_Obj_t_ // 12 words
|
|||
Vec_Fan_t vFanins; // the array of fanins
|
||||
Vec_Fan_t vFanouts; // the array of fanouts
|
||||
// miscellaneous
|
||||
Abc_Ntk_t * pNtk; // the host network
|
||||
void * pData; // the network specific data (SOP, BDD, gate, equiv class, etc)
|
||||
Abc_Obj_t * pNext; // the next pointer in the hash table
|
||||
Abc_Obj_t * pCopy; // the copy of this object
|
||||
|
|
@ -381,6 +381,7 @@ extern void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Ab
|
|||
extern void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld );
|
||||
extern bool Abc_AigNodeHasComplFanoutEdge( Abc_Obj_t * pNode );
|
||||
extern bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode );
|
||||
extern void Abc_AigPrintNode( Abc_Obj_t * pNode );
|
||||
/*=== abcAttach.c ==========================================================*/
|
||||
extern int Abc_NtkAttach( Abc_Ntk_t * pNtk );
|
||||
/*=== abcCheck.c ==========================================================*/
|
||||
|
|
@ -495,12 +496,15 @@ extern void Abc_NodePrintLevel( FILE * pFile, Abc_Obj_t * pNode );
|
|||
/*=== abcReconv.c ==========================================================*/
|
||||
extern Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax );
|
||||
extern void Abc_NtkManCutStop( Abc_ManCut_t * p );
|
||||
extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot );
|
||||
extern Vec_Ptr_t * Abc_NtkManCutReadLeaves( Abc_ManCut_t * p );
|
||||
extern Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain );
|
||||
extern DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Ptr_t * vVisited );
|
||||
extern DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited );
|
||||
extern void Abc_NodeCollectTfoCands( Abc_Ntk_t * pNtk, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, int LevelMax, Vec_Vec_t * vLevels, Vec_Ptr_t * vResult );
|
||||
/*=== abcRefs.c ==========================================================*/
|
||||
extern int Abc_NodeMffcSize( Abc_Obj_t * pNode );
|
||||
extern int Abc_NodeMffcLabel( Abc_Obj_t * pNode );
|
||||
extern Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode );
|
||||
extern void Abc_NodeUpdate( Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, int nGain );
|
||||
/*=== abcRenode.c ==========================================================*/
|
||||
extern Abc_Ntk_t * Abc_NtkRenode( Abc_Ntk_t * pNtk, int nThresh, int nFaninMax, int fCnf, int fMulti, int fSimple );
|
||||
|
|
@ -531,21 +535,22 @@ extern int Abc_SopGetCubeNum( char * pSop );
|
|||
extern int Abc_SopGetLitNum( char * pSop );
|
||||
extern int Abc_SopGetVarNum( char * pSop );
|
||||
extern int Abc_SopGetPhase( char * pSop );
|
||||
extern int Abc_SopGetIthCareLit( char * pSop, int i );
|
||||
extern void Abc_SopComplement( char * pSop );
|
||||
extern bool Abc_SopIsComplement( char * pSop );
|
||||
extern bool Abc_SopIsConst0( char * pSop );
|
||||
extern bool Abc_SopIsConst1( char * pSop );
|
||||
extern bool Abc_SopIsBuf( char * pSop );
|
||||
extern bool Abc_SopIsInv( char * pSop );
|
||||
extern bool Abc_SopIsAndType( char * pSop );
|
||||
extern bool Abc_SopIsOrType( char * pSop );
|
||||
extern int Abc_SopGetIthCareLit( char * pSop, int i );
|
||||
extern void Abc_SopComplement( char * pSop );
|
||||
extern bool Abc_SopCheck( char * pSop, int nFanins );
|
||||
extern void Abc_SopWriteCnf( FILE * pFile, char * pClauses, Vec_Int_t * vVars );
|
||||
extern void Abc_SopAddCnfToSolver( solver * pSat, char * pClauses, Vec_Int_t * vVars, Vec_Int_t * vTemp );
|
||||
/*=== abcStrash.c ==========================================================*/
|
||||
extern Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes );
|
||||
extern Abc_Obj_t * Abc_NodeStrashDec( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * vForm );
|
||||
extern int Abc_NodeStrashDecCount( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, Vec_Int_t * vLevels, int NodeMax, int LevelMax );
|
||||
extern int Abc_NodeStrashDecCount( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, Vec_Int_t * vLevels, int NodeMax, int LevelMax );
|
||||
extern int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 );
|
||||
extern Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate );
|
||||
/*=== abcSweep.c ==========================================================*/
|
||||
|
|
|
|||
|
|
@ -26,15 +26,16 @@
|
|||
- for each AND gate, there are no other AND gates with the same children
|
||||
- the constants are propagated
|
||||
- there is no single-input nodes (inverters/buffers)
|
||||
Additionally the following invariants are satisfied:
|
||||
- there are no dangling nodes (the nodes without fanout)
|
||||
- the level of each AND gate reflects the levels of this fanins
|
||||
- the EXOR-status of each node is up-to-date
|
||||
The operations that are performed on AIG:
|
||||
The operations that are performed on AIGs:
|
||||
- building new nodes (Abc_AigAnd)
|
||||
- performing elementary Boolean operations (Abc_AigOr, Abc_AigXor, etc)
|
||||
- replacing one node by another (Abc_AigReplace)
|
||||
- propagating constants (Abc_AigReplace)
|
||||
When AIG is duplicated, the new graph is struturally hashed too.
|
||||
When AIG is duplicated, the new graph is structurally hashed too.
|
||||
If this repeated hashing leads to fewer nodes, it means the original
|
||||
AIG was not strictly hashed (one of the conditions above is violated).
|
||||
*/
|
||||
|
|
@ -226,10 +227,7 @@ int Abc_AigCleanup( Abc_Aig_t * pMan )
|
|||
for ( i = 0; i < pMan->nBins; i++ )
|
||||
Abc_AigBinForEachEntry( pMan->pBins[i], pAnd )
|
||||
if ( Abc_ObjFanoutNum(pAnd) == 0 )
|
||||
{
|
||||
Vec_PtrPush( pMan->vStackDelete, pAnd );
|
||||
pAnd->fMarkA = 1;
|
||||
}
|
||||
// process the dangling nodes and their MFFCs
|
||||
for ( Counter = 0; Vec_PtrSize(pMan->vStackDelete) > 0; Counter++ )
|
||||
Abc_AigDelete_int( pMan );
|
||||
|
|
@ -409,6 +407,7 @@ Abc_Obj_t * Abc_AigAndCreateFrom( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t *
|
|||
Abc_ObjAddFanin( pAnd, p1 );
|
||||
// set the level of the new node
|
||||
pAnd->Level = 1 + ABC_MAX( Abc_ObjRegular(p0)->Level, Abc_ObjRegular(p1)->Level );
|
||||
pAnd->fExor = Abc_NodeIsExorType(pAnd);
|
||||
// add the node to the corresponding linked list in the table
|
||||
Key = Abc_HashKey2( p0, p1, pMan->nBins );
|
||||
pAnd->pNext = pMan->pBins[Key];
|
||||
|
|
@ -453,7 +452,7 @@ Abc_Obj_t * Abc_AigAndLookup( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
|
|||
pAnd = p0, p0 = p1, p1 = pAnd;
|
||||
// get the hash key for these two nodes
|
||||
Key = Abc_HashKey2( p0, p1, pMan->nBins );
|
||||
// find the mataching node in the table
|
||||
// find the matching node in the table
|
||||
Abc_AigBinForEachEntry( pMan->pBins[Key], pAnd )
|
||||
if ( p0 == Abc_ObjChild0(pAnd) && p1 == Abc_ObjChild1(pAnd) )
|
||||
return pAnd;
|
||||
|
|
@ -476,25 +475,30 @@ void Abc_AigAndDelete( Abc_Aig_t * pMan, Abc_Obj_t * pThis )
|
|||
Abc_Obj_t * pAnd, ** 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
|
||||
Key = Abc_HashKey2( Abc_ObjChild0(pThis), Abc_ObjChild1(pThis), pMan->nBins );
|
||||
// find the mataching node in the table
|
||||
// find the matching 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;
|
||||
ppPlace = &pAnd->pNext;
|
||||
continue;
|
||||
}
|
||||
*ppPlace = pAnd->pNext;
|
||||
break;
|
||||
}
|
||||
assert( pAnd == pThis );
|
||||
pMan->nEntries--;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
Synopsis [Resizes the hash table of AIG nodes.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -512,7 +516,7 @@ void Abc_AigResize( Abc_Aig_t * pMan )
|
|||
|
||||
clk = clock();
|
||||
// get the new table size
|
||||
nBinsNew = Cudd_PrimeCopy(2 * pMan->nBins);
|
||||
nBinsNew = Cudd_PrimeCopy( 3 * pMan->nBins );
|
||||
// allocate a new array
|
||||
pBinsNew = ALLOC( Abc_Obj_t *, nBinsNew );
|
||||
memset( pBinsNew, 0, sizeof(Abc_Obj_t *) * nBinsNew );
|
||||
|
|
@ -560,7 +564,7 @@ Abc_Obj_t * Abc_AigAnd( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
|
|||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements Boolean AND.]
|
||||
Synopsis [Implements Boolean OR.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -576,7 +580,7 @@ Abc_Obj_t * Abc_AigOr( Abc_Aig_t * pMan, Abc_Obj_t * p0, Abc_Obj_t * p1 )
|
|||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Implements Boolean AND.]
|
||||
Synopsis [Implements Boolean XOR.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -619,6 +623,7 @@ Abc_Obj_t * Abc_AigMiter( Abc_Aig_t * pMan, Vec_Ptr_t * vPairs )
|
|||
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Replaces one AIG node by the other.]
|
||||
|
|
@ -639,8 +644,8 @@ void Abc_AigReplace( Abc_Aig_t * pMan, Abc_Obj_t * pOld, Abc_Obj_t * pNew )
|
|||
Vec_PtrPush( pMan->vStackReplaceNew, pNew );
|
||||
while ( Vec_PtrSize(pMan->vStackReplaceOld) )
|
||||
Abc_AigReplace_int( pMan );
|
||||
while ( Vec_PtrSize(pMan->vStackDelete) )
|
||||
Abc_AigDelete_int( pMan );
|
||||
// while ( Vec_PtrSize(pMan->vStackDelete) )
|
||||
// Abc_AigDelete_int( pMan );
|
||||
Abc_AigUpdateLevel_int( pMan );
|
||||
}
|
||||
|
||||
|
|
@ -664,7 +669,7 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
|
|||
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
|
||||
// (the new node can be complemented and can have fanouts)
|
||||
assert( !Abc_ObjIsComplement(pOld) );
|
||||
assert( Abc_ObjFanoutNum(pOld) > 0 );
|
||||
// look at the fanouts of old node
|
||||
|
|
@ -691,26 +696,25 @@ void Abc_AigReplace_int( Abc_Aig_t * pMan )
|
|||
Vec_PtrPush( pMan->vStackReplaceNew, pFanoutNew );
|
||||
continue;
|
||||
}
|
||||
// such node does not exist - modify the old fanout
|
||||
// remove the old fanout from the table
|
||||
// such node does not exist - modify the old fanout node
|
||||
// (this way the change will not propagate all the way to the COs)
|
||||
assert( Abc_ObjRegular(pFanin1) != Abc_ObjRegular(pFanin2) );
|
||||
// remove the old fanout node from the structural hashing table
|
||||
Abc_AigAndDelete( pMan, pFanout );
|
||||
// remove its old fanins
|
||||
// remove the fanins of the old fanout
|
||||
Abc_ObjRemoveFanins( pFanout );
|
||||
// update the old fanout with new fanins and add it to the table
|
||||
// recreate the old fanout with new fanins and add it to the table
|
||||
Abc_AigAndCreateFrom( pMan, pFanin1, pFanin2, pFanout );
|
||||
// schedule the updated node for updating level
|
||||
// schedule the updated fanout for updating level
|
||||
Vec_VecPush( pMan->vLevels, pFanout->Level, pFanout );
|
||||
// the node has changed, update EXOR status of the fanouts
|
||||
// the fanout has changed, update EXOR status of its fanouts
|
||||
Abc_ObjForEachFanout( pFanout, pFanoutFanout, v )
|
||||
if ( Abc_NodeIsAigAnd(pFanoutFanout) )
|
||||
pFanoutFanout->fExor = Abc_NodeIsExorType(pFanoutFanout);
|
||||
}
|
||||
// schedule deletion of the old node
|
||||
if ( Abc_NodeIsAigAnd(pOld) && pOld->fMarkA == 0 )
|
||||
{
|
||||
Vec_PtrPush( pMan->vStackDelete, pOld );
|
||||
pOld->fMarkA = 1;
|
||||
}
|
||||
// if the node has no fanouts left, remove its MFFC
|
||||
if ( Abc_ObjFanoutNum(pOld) == 0 )
|
||||
Abc_AigDeleteNode( pMan, pOld );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -745,31 +749,33 @@ void Abc_AigDeleteNode( Abc_Aig_t * pMan, Abc_Obj_t * pOld )
|
|||
***********************************************************************/
|
||||
void Abc_AigDelete_int( Abc_Aig_t * pMan )
|
||||
{
|
||||
Abc_Obj_t * pNode, * pFanin;
|
||||
Vec_Ptr_t * vNodes;
|
||||
Abc_Obj_t * pRoot, * pObj;
|
||||
int k;
|
||||
// get the node to delete
|
||||
assert( Vec_PtrSize(pMan->vStackDelete) > 0 );
|
||||
pNode = Vec_PtrPop( pMan->vStackDelete );
|
||||
pRoot = Vec_PtrPop( pMan->vStackDelete );
|
||||
|
||||
// make sure the node is regular and dangling
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
assert( Abc_ObjFanoutNum(pNode) == 0 );
|
||||
assert( pNode != pMan->pConst1 );
|
||||
// schedule fanins for deletion if they dangle
|
||||
Abc_ObjForEachFanin( pNode, pFanin, k )
|
||||
assert( !Abc_ObjIsComplement(pRoot) );
|
||||
assert( Abc_ObjIsNode(pRoot) );
|
||||
assert( Abc_ObjFaninNum(pRoot) == 2 );
|
||||
assert( Abc_ObjFanoutNum(pRoot) == 0 );
|
||||
|
||||
// collect the MFFC
|
||||
vNodes = Abc_NodeMffcCollect( pRoot );
|
||||
Vec_PtrForEachEntry( vNodes, pObj, k )
|
||||
{
|
||||
assert( Abc_ObjFanoutNum(pFanin) > 0 );
|
||||
if ( Abc_ObjFanoutNum(pFanin) == 1 )
|
||||
if ( Abc_NodeIsAigAnd(pFanin) && pFanin->fMarkA == 0 )
|
||||
{
|
||||
Vec_PtrPush( pMan->vStackDelete, pFanin );
|
||||
pFanin->fMarkA = 1;
|
||||
}
|
||||
if ( Abc_ObjIsCi(pObj) )
|
||||
continue;
|
||||
assert( pObj->fMarkA == 0 );
|
||||
// remove the node from the table
|
||||
Abc_AigAndDelete( pMan, pObj );
|
||||
// remove the node from the network
|
||||
//printf( "Removing " ); Abc_AigPrintNode( pObj );
|
||||
Abc_NtkDeleteObj( pObj );
|
||||
}
|
||||
// remove the node from the table
|
||||
Abc_AigAndDelete( pMan, pNode );
|
||||
// remove the node fro the network
|
||||
Abc_NtkDeleteObj( pNode );
|
||||
Vec_PtrFree( vNodes );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
@ -797,7 +803,11 @@ void Abc_AigUpdateLevel_int( Abc_Aig_t * pMan )
|
|||
continue;
|
||||
Vec_PtrForEachEntry( vVec, pNode, k )
|
||||
{
|
||||
assert( Abc_ObjIsNode(pNode) );
|
||||
// assert( Abc_ObjIsNode(pNode) );
|
||||
// for some reason, deleted nodes are encountered here!!!
|
||||
if ( !Abc_ObjIsNode(pNode) )
|
||||
continue;
|
||||
// iterate through the fanouts
|
||||
Abc_ObjForEachFanout( pNode, pFanout, v )
|
||||
{
|
||||
if ( Abc_ObjIsCo(pFanout) )
|
||||
|
|
@ -877,6 +887,39 @@ bool Abc_AigNodeHasComplFanoutEdgeTrav( Abc_Obj_t * pNode )
|
|||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints the AIG node for debugging purposes.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_AigPrintNode( Abc_Obj_t * pNode )
|
||||
{
|
||||
Abc_Obj_t * pNodeR = Abc_ObjRegular(pNode);
|
||||
if ( Abc_ObjIsCi(pNodeR) )
|
||||
{
|
||||
printf( "CI %4s%s.\n", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" );
|
||||
return;
|
||||
}
|
||||
if ( Abc_NodeIsConst(pNodeR) )
|
||||
{
|
||||
printf( "Constant 1 %s.\n", Abc_ObjIsComplement(pNode)? "(complemented)" : "" );
|
||||
return;
|
||||
}
|
||||
// print the node's function
|
||||
printf( "%7s%s", Abc_ObjName(pNodeR), Abc_ObjIsComplement(pNode)? "\'" : "" );
|
||||
printf( " = " );
|
||||
printf( "%7s%s", Abc_ObjName(Abc_ObjFanin0(pNodeR)), Abc_ObjFaninC0(pNodeR)? "\'" : "" );
|
||||
printf( " * " );
|
||||
printf( "%7s%s", Abc_ObjName(Abc_ObjFanin1(pNodeR)), Abc_ObjFaninC1(pNodeR)? "\'" : "" );
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -0,0 +1,236 @@
|
|||
/**CFile****************************************************************
|
||||
|
||||
FileName [abcBalance.c]
|
||||
|
||||
SystemName [ABC: Logic synthesis and verification system.]
|
||||
|
||||
PackageName [Network and node package.]
|
||||
|
||||
Synopsis [Performs global balancing of the AIG by the number of levels.]
|
||||
|
||||
Author [Alan Mishchenko]
|
||||
|
||||
Affiliation [UC Berkeley]
|
||||
|
||||
Date [Ver. 1.0. Started - June 20, 2005.]
|
||||
|
||||
Revision [$Id: abcBalance.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
||||
|
||||
***********************************************************************/
|
||||
|
||||
#include "abc.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate );
|
||||
static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, bool fDuplicate );
|
||||
static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, int fDuplicate );
|
||||
static int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFITIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Balances the AIG network.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate )
|
||||
{
|
||||
int fCheck = 1;
|
||||
Abc_Ntk_t * pNtkAig;
|
||||
assert( Abc_NtkIsAig(pNtk) );
|
||||
// perform balancing
|
||||
pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_AIG );
|
||||
Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate );
|
||||
Abc_NtkFinalize( pNtk, pNtkAig );
|
||||
// make sure everything is okay
|
||||
if ( fCheck && !Abc_NtkCheck( pNtkAig ) )
|
||||
{
|
||||
printf( "Abc_NtkBalance: The network check has failed.\n" );
|
||||
Abc_NtkDelete( pNtkAig );
|
||||
return NULL;
|
||||
}
|
||||
return pNtkAig;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Balances the AIG network.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate )
|
||||
{
|
||||
int fCheck = 1;
|
||||
ProgressBar * pProgress;
|
||||
Abc_Obj_t * pNode, * pDriver;
|
||||
int i;
|
||||
|
||||
// copy the constant node
|
||||
Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkAig->pManFunc);
|
||||
// set the level of PIs of AIG according to the arrival times of the old network
|
||||
Abc_NtkSetNodeLevelsArrival( pNtk );
|
||||
// perform balancing of POs
|
||||
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
// strash the driver node
|
||||
pDriver = Abc_ObjFanin0(pNode);
|
||||
Abc_NodeBalance_rec( pNtkAig, pDriver, fDuplicate );
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Rebalances the multi-input node rooted at pNodeOld.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, bool fDuplicate )
|
||||
{
|
||||
Abc_Aig_t * pMan = pNtkNew->pManFunc;
|
||||
Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
|
||||
Vec_Ptr_t * vSuper;
|
||||
int i;
|
||||
assert( !Abc_ObjIsComplement(pNodeOld) );
|
||||
// return if the result if known
|
||||
if ( pNodeOld->pCopy )
|
||||
return pNodeOld->pCopy;
|
||||
assert( Abc_ObjIsNode(pNodeOld) );
|
||||
// get the implication supergate
|
||||
vSuper = Abc_NodeBalanceCone( pNodeOld, fDuplicate );
|
||||
if ( vSuper->nSize == 0 )
|
||||
{ // it means that the supergate contains two nodes in the opposite polarity
|
||||
Vec_PtrFree( vSuper );
|
||||
pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pMan));
|
||||
return pNodeOld->pCopy;
|
||||
}
|
||||
// for each old node, derive the new well-balanced node
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
{
|
||||
pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), fDuplicate );
|
||||
vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) );
|
||||
}
|
||||
// sort the new nodes by level in the decreasing order
|
||||
Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease );
|
||||
// balance the nodes
|
||||
assert( vSuper->nSize > 1 );
|
||||
while ( vSuper->nSize > 1 )
|
||||
{
|
||||
pNode1 = Vec_PtrPop(vSuper);
|
||||
pNode2 = Vec_PtrPop(vSuper);
|
||||
Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) );
|
||||
}
|
||||
// make sure the balanced node is not assigned
|
||||
assert( pNodeOld->pCopy == NULL );
|
||||
// mark the old node with the new node
|
||||
pNodeOld->pCopy = vSuper->pArray[0];
|
||||
Vec_PtrFree( vSuper );
|
||||
return pNodeOld->pCopy;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes in the cone delimited by fMarkA==1.]
|
||||
|
||||
Description [Returns -1 if the AND-cone has the same node in both polarities.
|
||||
Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
|
||||
if the AND-cone has no repeated nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, int fDuplicate )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
int RetValue, i;
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
vNodes = Vec_PtrAlloc( 4 );
|
||||
RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate );
|
||||
assert( vNodes->nSize > 0 );
|
||||
for ( i = 0; i < vNodes->nSize; i++ )
|
||||
Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
|
||||
if ( RetValue == -1 )
|
||||
vNodes->nSize = 0;
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes in the cone delimited by fMarkA==1.]
|
||||
|
||||
Description [Returns -1 if the AND-cone has the same node in both polarities.
|
||||
Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
|
||||
if the AND-cone has no repeated nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate )
|
||||
{
|
||||
int RetValue1, RetValue2, i;
|
||||
// check if the node is visited
|
||||
if ( Abc_ObjRegular(pNode)->fMarkB )
|
||||
{
|
||||
// check if the node occurs in the same polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == pNode )
|
||||
return 1;
|
||||
// check if the node is present in the opposite polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
|
||||
return -1;
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
// if the new node is complemented or a PI, another gate begins
|
||||
if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && (Abc_ObjFanoutNum(pNode) > 1)) )
|
||||
{
|
||||
Vec_PtrPush( vSuper, pNode );
|
||||
Abc_ObjRegular(pNode)->fMarkB = 1;
|
||||
return 0;
|
||||
}
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
assert( Abc_ObjIsNode(pNode) );
|
||||
// go through the branches
|
||||
RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate );
|
||||
RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate );
|
||||
if ( RetValue1 == -1 || RetValue2 == -1 )
|
||||
return -1;
|
||||
// return 1 if at least one branch has a duplicate
|
||||
return RetValue1 || RetValue2;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
|
@ -504,7 +504,9 @@ Abc_Obj_t * Abc_ObjAlloc( Abc_Ntk_t * pNtk, Abc_ObjType_t Type )
|
|||
***********************************************************************/
|
||||
void Abc_ObjRecycle( Abc_Obj_t * pObj )
|
||||
{
|
||||
Extra_MmFixedEntryRecycle( pObj->pNtk->pMmObj, (char *)pObj );
|
||||
Abc_Ntk_t * pNtk = pObj->pNtk;
|
||||
memset( pObj, 0, sizeof(Abc_Obj_t) );
|
||||
Extra_MmFixedEntryRecycle( pNtk->pMmObj, (char *)pObj );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
|
|
@ -205,7 +205,10 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun
|
|||
{
|
||||
Vec_StrFill( vCube, nFanins, '-' );
|
||||
Vec_StrPush( vCube, '\0' );
|
||||
pSop = Extra_MmFlexEntryFetch( pMan, nFanins + 4 );
|
||||
if ( pMan )
|
||||
pSop = Extra_MmFlexEntryFetch( pMan, nFanins + 4 );
|
||||
else
|
||||
pSop = ALLOC( char, nFanins + 4 );
|
||||
if ( bFuncOn == Cudd_ReadLogicZero(dd) )
|
||||
sprintf( pSop, "%s 0\n", vCube->pArray );
|
||||
else
|
||||
|
|
@ -249,7 +252,7 @@ char * Abc_ConvertBddToSop( Extra_MmFlex_t * pMan, DdManager * dd, DdNode * bFun
|
|||
}
|
||||
else if ( fMode == 0 )
|
||||
{
|
||||
// get the ZDD of the positive polarity
|
||||
// get the ZDD of the negative polarity
|
||||
bCover = Cudd_zddIsop( dd, Cudd_Not(bFuncOnDc), Cudd_Not(bFuncOn), &zCover );
|
||||
Cudd_Ref( zCover );
|
||||
Cudd_Ref( bCover );
|
||||
|
|
|
|||
|
|
@ -73,9 +73,11 @@ char * Abc_NtkRegisterNamePlus( Abc_Ntk_t * pNtk, char * pName, char * pSuffix )
|
|||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Gets the long name of the node.]
|
||||
Synopsis [Gets the long name of the object.]
|
||||
|
||||
Description [This name is the output net's name.]
|
||||
Description [The temporary name is stored in a static buffer inside this
|
||||
procedure. It is important that the name is used before the function is
|
||||
called again!]
|
||||
|
||||
SideEffects []
|
||||
|
||||
|
|
|
|||
|
|
@ -32,17 +32,12 @@ struct Abc_ManCut_t_
|
|||
int nConeSizeMax; // the limit on the size of the containing cone
|
||||
// internal parameters
|
||||
Vec_Ptr_t * vFaninsNode; // fanins of the supernode
|
||||
Vec_Ptr_t * vInsideNode; // inside of the supernode
|
||||
Vec_Ptr_t * vFaninsCone; // fanins of the containing cone
|
||||
Vec_Ptr_t * vInsideCone; // inside of the containing cone
|
||||
Vec_Ptr_t * vVisited; // the visited nodes
|
||||
};
|
||||
|
||||
static int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimit );
|
||||
static int Abc_NodeGetFaninCost( Abc_Obj_t * pNode );
|
||||
static void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
|
||||
static void Abc_NodeConeMark( Vec_Ptr_t * vVisited );
|
||||
static void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited );
|
||||
static int Abc_NodeFindCut_int( Vec_Ptr_t * vFanins, int nSizeLimit );
|
||||
static void Abc_NodesMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFITIONS ///
|
||||
|
|
@ -50,7 +45,7 @@ static void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited );
|
|||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds a reconvergence-driven cut.]
|
||||
Synopsis [Unmarks the TFI cone.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -59,53 +54,140 @@ static void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited );
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot )
|
||||
static inline void Abc_NodesMark( Vec_Ptr_t * vVisited )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
Vec_PtrForEachEntry( vVisited, pNode, i )
|
||||
pNode->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Unmarks the TFI cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Abc_NodesUnmark( Vec_Ptr_t * vVisited )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
Vec_PtrForEachEntry( vVisited, pNode, i )
|
||||
pNode->fMarkA = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Unmarks the TFI cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline void Abc_NodesUnmarkBoth( Vec_Ptr_t * vVisited )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
Vec_PtrForEachEntry( vVisited, pNode, i )
|
||||
pNode->fMarkA = pNode->fMarkB = 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Evaluate the fanin cost.]
|
||||
|
||||
Description [Returns the number of fanins that will be brought in.
|
||||
Returns large number if the node cannot be added.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
static inline int Abc_NodeGetFaninCost( Abc_Obj_t * pNode )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
int i;
|
||||
assert( pNode->fMarkA == 1 ); // this node is in the TFI
|
||||
assert( pNode->fMarkB == 1 ); // this node is in the constructed cone
|
||||
// check the PI node
|
||||
if ( Abc_ObjIsCi(pNode) )
|
||||
return 999;
|
||||
// skip nodes with many fanouts
|
||||
if ( Abc_ObjFanoutNum(pNode) > 5 )
|
||||
return 999;
|
||||
// check the fanouts
|
||||
Abc_ObjForEachFanout( pNode, pFanout, i )
|
||||
if ( pFanout->fMarkA && pFanout->fMarkB == 0 ) // the fanout is in the TFI but not in the cone
|
||||
return 999;
|
||||
// the fanouts are in the TFI and inside the constructed cone
|
||||
// return the number of fanins that will be on the boundary if this node is added
|
||||
return (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds a fanin-limited, reconvergence-driven cut for the node.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot, bool fContain )
|
||||
{
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
|
||||
assert( !Abc_ObjIsComplement(pRoot) );
|
||||
assert( Abc_ObjIsNode(pRoot) );
|
||||
|
||||
// mark TFI using fMarkA
|
||||
Vec_PtrClear( p->vVisited );
|
||||
Abc_NodeConeMarkCollect_rec( pRoot, p->vVisited );
|
||||
Abc_NodesMarkCollect_rec( pRoot, p->vVisited );
|
||||
|
||||
// start the reconvergence-driven node
|
||||
Vec_PtrClear( p->vInsideNode );
|
||||
// start the cut
|
||||
Vec_PtrClear( p->vFaninsNode );
|
||||
Vec_PtrPush( p->vFaninsNode, pRoot );
|
||||
Vec_PtrPush( p->vFaninsNode, Abc_ObjFanin0(pRoot) );
|
||||
Vec_PtrPush( p->vFaninsNode, Abc_ObjFanin1(pRoot) );
|
||||
pRoot->fMarkB = 1;
|
||||
Abc_ObjFanin0(pRoot)->fMarkB = 1;
|
||||
Abc_ObjFanin1(pRoot)->fMarkB = 1;
|
||||
|
||||
// compute reconvergence-driven node
|
||||
while ( Abc_NodeFindCut_int( p->vInsideNode, p->vFaninsNode, p->nNodeSizeMax ) );
|
||||
// compute the cut
|
||||
while ( Abc_NodeFindCut_int( p->vFaninsNode, p->nNodeSizeMax ) );
|
||||
assert( Vec_PtrSize(p->vFaninsNode) <= p->nNodeSizeMax );
|
||||
|
||||
// compute reconvergence-driven cone
|
||||
Vec_PtrClear( p->vInsideCone );
|
||||
// return if containing cut is not requested
|
||||
if ( !fContain )
|
||||
{
|
||||
// unmark TFI using fMarkA and fMarkB
|
||||
Abc_NodesUnmarkBoth( p->vVisited );
|
||||
return p->vFaninsNode;
|
||||
}
|
||||
|
||||
// compute the containing cut
|
||||
assert( p->nNodeSizeMax < p->nConeSizeMax );
|
||||
// copy the current boundary
|
||||
Vec_PtrClear( p->vFaninsCone );
|
||||
if ( p->nConeSizeMax > p->nNodeSizeMax )
|
||||
{
|
||||
// copy the node into the cone
|
||||
Vec_PtrForEachEntry( p->vInsideNode, pNode, i )
|
||||
Vec_PtrPush( p->vInsideCone, pNode );
|
||||
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
|
||||
Vec_PtrPush( p->vFaninsCone, pNode );
|
||||
// compute reconvergence-driven cone
|
||||
while ( Abc_NodeFindCut_int( p->vInsideCone, p->vFaninsCone, p->nConeSizeMax ) );
|
||||
// unmark the nodes of the sets
|
||||
Vec_PtrForEachEntry( p->vInsideCone, pNode, i )
|
||||
pNode->fMarkB = 0;
|
||||
Vec_PtrForEachEntry( p->vFaninsCone, pNode, i )
|
||||
pNode->fMarkB = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unmark the nodes of the sets
|
||||
Vec_PtrForEachEntry( p->vInsideNode, pNode, i )
|
||||
pNode->fMarkB = 0;
|
||||
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
|
||||
pNode->fMarkB = 0;
|
||||
}
|
||||
|
||||
// unmark TFI using fMarkA
|
||||
Abc_NodeConeUnmark( p->vVisited );
|
||||
Vec_PtrForEachEntry( p->vFaninsNode, pNode, i )
|
||||
Vec_PtrPush( p->vFaninsCone, pNode );
|
||||
// compute the containing cut
|
||||
while ( Abc_NodeFindCut_int( p->vFaninsCone, p->nConeSizeMax ) );
|
||||
assert( Vec_PtrSize(p->vFaninsCone) <= p->nConeSizeMax );
|
||||
// unmark TFI using fMarkA and fMarkB
|
||||
Abc_NodesUnmarkBoth( p->vVisited );
|
||||
return p->vFaninsNode;
|
||||
}
|
||||
|
||||
|
|
@ -120,20 +202,37 @@ Vec_Ptr_t * Abc_NodeFindCut( Abc_ManCut_t * p, Abc_Obj_t * pRoot )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimit )
|
||||
int Abc_NodeFindCut_int( Vec_Ptr_t * vFanins, int nSizeLimit )
|
||||
{
|
||||
Abc_Obj_t * pNode, * pFaninBest, * pNext;
|
||||
int CostBest, CostCur, i;
|
||||
// int fFlagProb = (rand() & 1);
|
||||
int fFlagProb = 1;
|
||||
// find the best fanin
|
||||
CostBest = 100;
|
||||
pFaninBest = NULL;
|
||||
Vec_PtrForEachEntry( vFanins, pNode, i )
|
||||
if ( fFlagProb )
|
||||
{
|
||||
CostCur = Abc_NodeGetFaninCost( pNode );
|
||||
if ( CostBest > CostCur )
|
||||
Vec_PtrForEachEntry( vFanins, pNode, i )
|
||||
{
|
||||
CostBest = CostCur;
|
||||
pFaninBest = pNode;
|
||||
CostCur = Abc_NodeGetFaninCost( pNode );
|
||||
if ( CostBest > CostCur )
|
||||
{
|
||||
CostBest = CostCur;
|
||||
pFaninBest = pNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Vec_PtrForEachEntry( vFanins, pNode, i )
|
||||
{
|
||||
CostCur = Abc_NodeGetFaninCost( pNode );
|
||||
if ( CostBest >= CostCur )
|
||||
{
|
||||
CostBest = CostCur;
|
||||
pFaninBest = pNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( pFaninBest == NULL )
|
||||
|
|
@ -144,8 +243,6 @@ int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimi
|
|||
assert( Abc_ObjIsNode(pFaninBest) );
|
||||
// remove the node from the array
|
||||
Vec_PtrRemove( vFanins, pFaninBest );
|
||||
// add the node to the set
|
||||
Vec_PtrPush( vInside, pFaninBest );
|
||||
// add the left child to the fanins
|
||||
pNext = Abc_ObjFanin0(pFaninBest);
|
||||
if ( !pNext->fMarkB )
|
||||
|
|
@ -165,36 +262,6 @@ int Abc_NodeFindCut_int( Vec_Ptr_t * vInside, Vec_Ptr_t * vFanins, int nSizeLimi
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Evaluate the fanin cost.]
|
||||
|
||||
Description [Returns the number of fanins that will be brought in.
|
||||
Returns large number if the node cannot be added.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeGetFaninCost( Abc_Obj_t * pNode )
|
||||
{
|
||||
Abc_Obj_t * pFanout;
|
||||
int i;
|
||||
assert( pNode->fMarkA == 1 ); // this node is in the TFI
|
||||
assert( pNode->fMarkB == 1 ); // this node is in the constructed cone
|
||||
// check the PI node
|
||||
if ( !Abc_ObjIsNode(pNode) )
|
||||
return 999;
|
||||
// check the fanouts
|
||||
Abc_ObjForEachFanout( pNode, pFanout, i )
|
||||
if ( pFanout->fMarkA && pFanout->fMarkB == 0 ) // in the cone but not in the set
|
||||
return 999;
|
||||
// the fanouts are in the TFI and inside the constructed cone
|
||||
// return the number of fanins that will be on the boundary if this node is added
|
||||
return (!Abc_ObjFanin0(pNode)->fMarkB) + (!Abc_ObjFanin1(pNode)->fMarkB);
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Marks the TFI cone.]
|
||||
|
|
@ -206,57 +273,21 @@ int Abc_NodeGetFaninCost( Abc_Obj_t * pNode )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NodeConeMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
|
||||
void Abc_NodesMarkCollect_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vVisited )
|
||||
{
|
||||
if ( pNode->fMarkA == 1 )
|
||||
return;
|
||||
// visit transitive fanin
|
||||
if ( Abc_ObjIsNode(pNode) )
|
||||
{
|
||||
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
|
||||
Abc_NodeConeMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
|
||||
Abc_NodesMarkCollect_rec( Abc_ObjFanin0(pNode), vVisited );
|
||||
Abc_NodesMarkCollect_rec( Abc_ObjFanin1(pNode), vVisited );
|
||||
}
|
||||
assert( pNode->fMarkA == 0 );
|
||||
pNode->fMarkA = 1;
|
||||
Vec_PtrPush( vVisited, pNode );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Unmarks the TFI cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NodeConeMark( Vec_Ptr_t * vVisited )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < vVisited->nSize; i++ )
|
||||
((Abc_Obj_t *)vVisited->pArray)->fMarkA = 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Unmarks the TFI cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NodeConeUnmark( Vec_Ptr_t * vVisited )
|
||||
{
|
||||
int i;
|
||||
for ( i = 0; i < vVisited->nSize; i++ )
|
||||
((Abc_Obj_t *)vVisited->pArray)->fMarkA = 0;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
@ -274,13 +305,13 @@ DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, V
|
|||
DdNode * bFunc0, * bFunc1, * bFunc;
|
||||
int i;
|
||||
// mark the fanins of the cone
|
||||
Abc_NodeConeMark( vFanins );
|
||||
Abc_NodesMark( vFanins );
|
||||
// collect the nodes in the DFS order
|
||||
Vec_PtrClear( vVisited );
|
||||
Abc_NodeConeMarkCollect_rec( pNode, vVisited );
|
||||
Abc_NodesMarkCollect_rec( pNode, vVisited );
|
||||
// unmark both sets
|
||||
Abc_NodeConeUnmark( vFanins );
|
||||
Abc_NodeConeUnmark( vVisited );
|
||||
Abc_NodesUnmark( vFanins );
|
||||
Abc_NodesUnmark( vVisited );
|
||||
// set the elementary BDDs
|
||||
Vec_PtrForEachEntry( vFanins, pNode, i )
|
||||
pNode->pCopy = (Abc_Obj_t *)pbVars[i];
|
||||
|
|
@ -300,6 +331,64 @@ DdNode * Abc_NodeConeBdd( DdManager * dd, DdNode ** pbVars, Abc_Obj_t * pNode, V
|
|||
return bFunc;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns BDD representing the transition relation of the cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
DdNode * Abc_NodeConeDcs( DdManager * dd, DdNode ** pbVarsX, DdNode ** pbVarsY, Vec_Ptr_t * vLeaves, Vec_Ptr_t * vRoots, Vec_Ptr_t * vVisited )
|
||||
{
|
||||
DdNode * bFunc0, * bFunc1, * bFunc, * bTrans, * bTemp, * bCube, * bResult;
|
||||
Abc_Obj_t * pNode;
|
||||
int i;
|
||||
// mark the fanins of the cone
|
||||
Abc_NodesMark( vLeaves );
|
||||
// collect the nodes in the DFS order
|
||||
Vec_PtrClear( vVisited );
|
||||
Vec_PtrForEachEntry( vRoots, pNode, i )
|
||||
Abc_NodesMarkCollect_rec( pNode, vVisited );
|
||||
// unmark both sets
|
||||
Abc_NodesUnmark( vLeaves );
|
||||
Abc_NodesUnmark( vVisited );
|
||||
// set the elementary BDDs
|
||||
Vec_PtrForEachEntry( vLeaves, pNode, i )
|
||||
pNode->pCopy = (Abc_Obj_t *)pbVarsX[i];
|
||||
// compute the BDDs for the collected nodes
|
||||
Vec_PtrForEachEntry( vVisited, pNode, i )
|
||||
{
|
||||
bFunc0 = Cudd_NotCond( Abc_ObjFanin0(pNode)->pCopy, Abc_ObjFaninC0(pNode) );
|
||||
bFunc1 = Cudd_NotCond( Abc_ObjFanin1(pNode)->pCopy, Abc_ObjFaninC1(pNode) );
|
||||
bFunc = Cudd_bddAnd( dd, bFunc0, bFunc1 ); Cudd_Ref( bFunc );
|
||||
pNode->pCopy = (Abc_Obj_t *)bFunc;
|
||||
}
|
||||
// compute the transition relation of the cone
|
||||
bTrans = b1; Cudd_Ref( bTrans );
|
||||
Vec_PtrForEachEntry( vRoots, pNode, i )
|
||||
{
|
||||
bFunc = Cudd_bddXnor( dd, (DdNode *)pNode->pCopy, pbVarsY[i] ); Cudd_Ref( bFunc );
|
||||
bTrans = Cudd_bddAnd( dd, bTemp = bTrans, bFunc ); Cudd_Ref( bTrans );
|
||||
Cudd_RecursiveDeref( dd, bTemp );
|
||||
Cudd_RecursiveDeref( dd, bFunc );
|
||||
}
|
||||
// dereference the intermediate ones
|
||||
Vec_PtrForEachEntry( vVisited, pNode, i )
|
||||
Cudd_RecursiveDeref( dd, (DdNode *)pNode->pCopy );
|
||||
// compute don't-cares
|
||||
bCube = Extra_bddComputeRangeCube( dd, vRoots->nSize, vRoots->nSize + vLeaves->nSize ); Cudd_Ref( bCube );
|
||||
bResult = Cudd_bddExistAbstract( dd, bTrans, bCube ); Cudd_Ref( bResult );
|
||||
bResult = Cudd_Not( bResult );
|
||||
Cudd_RecursiveDeref( dd, bCube );
|
||||
Cudd_RecursiveDeref( dd, bTrans );
|
||||
Cudd_Deref( bResult );
|
||||
return bResult;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the resynthesis manager.]
|
||||
|
|
@ -317,9 +406,7 @@ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax )
|
|||
p = ALLOC( Abc_ManCut_t, 1 );
|
||||
memset( p, 0, sizeof(Abc_ManCut_t) );
|
||||
p->vFaninsNode = Vec_PtrAlloc( 100 );
|
||||
p->vInsideNode = Vec_PtrAlloc( 100 );
|
||||
p->vFaninsCone = Vec_PtrAlloc( 100 );
|
||||
p->vInsideCone = Vec_PtrAlloc( 100 );
|
||||
p->vVisited = Vec_PtrAlloc( 100 );
|
||||
p->nNodeSizeMax = nNodeSizeMax;
|
||||
p->nConeSizeMax = nConeSizeMax;
|
||||
|
|
@ -340,13 +427,26 @@ Abc_ManCut_t * Abc_NtkManCutStart( int nNodeSizeMax, int nConeSizeMax )
|
|||
void Abc_NtkManCutStop( Abc_ManCut_t * p )
|
||||
{
|
||||
Vec_PtrFree( p->vFaninsNode );
|
||||
Vec_PtrFree( p->vInsideNode );
|
||||
Vec_PtrFree( p->vFaninsCone );
|
||||
Vec_PtrFree( p->vInsideCone );
|
||||
Vec_PtrFree( p->vVisited );
|
||||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the leaves of the cone.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Abc_NtkManCutReadLeaves( Abc_ManCut_t * p )
|
||||
{
|
||||
return p->vFaninsCone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -29,25 +29,37 @@ typedef struct Abc_ManRef_t_ Abc_ManRef_t;
|
|||
struct Abc_ManRef_t_
|
||||
{
|
||||
// user specified parameters
|
||||
int nNodeSizeMax; // the limit on the size of the supernode
|
||||
int nConeSizeMax; // the limit on the size of the containing cone
|
||||
int fVerbose; // the verbosity flag
|
||||
// internal parameters
|
||||
DdManager * dd; // the BDD manager
|
||||
Vec_Int_t * vReqTimes; // required times for each node
|
||||
Vec_Str_t * vCube; // temporary
|
||||
Vec_Int_t * vForm; // temporary
|
||||
Vec_Int_t * vLevNums; // temporary
|
||||
Vec_Ptr_t * vVisited; // temporary
|
||||
int nNodeSizeMax; // the limit on the size of the supernode
|
||||
int nConeSizeMax; // the limit on the size of the containing cone
|
||||
int fVerbose; // the verbosity flag
|
||||
// internal data structures
|
||||
DdManager * dd; // the BDD manager
|
||||
Vec_Int_t * vReqTimes; // required times for each node
|
||||
Vec_Str_t * vCube; // temporary
|
||||
Vec_Int_t * vForm; // temporary
|
||||
Vec_Int_t * vLevNums; // temporary
|
||||
Vec_Ptr_t * vVisited; // temporary
|
||||
Vec_Ptr_t * vLeaves; // temporary
|
||||
// node statistics
|
||||
int nLastGain;
|
||||
int nNodesConsidered;
|
||||
int nNodesRefactored;
|
||||
int nNodesGained;
|
||||
// runtime statistics
|
||||
int time1;
|
||||
int time2;
|
||||
int time3;
|
||||
int timeCut;
|
||||
int timeBdd;
|
||||
int timeDcs;
|
||||
int timeSop;
|
||||
int timeFact;
|
||||
int timeRes;
|
||||
int timeNtk;
|
||||
int timeTotal;
|
||||
};
|
||||
|
||||
static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, int fVerbose );
|
||||
|
||||
static void Abc_NtkManRefPrintStats( Abc_ManRef_t * p );
|
||||
static Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose );
|
||||
static void Abc_NtkManRefStop( Abc_ManRef_t * p );
|
||||
static Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins );
|
||||
static Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFITIONS ///
|
||||
|
|
@ -58,9 +70,10 @@ static Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec
|
|||
Synopsis [Performs incremental resynthesis of the AIG.]
|
||||
|
||||
Description [Starting from each node, computes a reconvergence-driven cut,
|
||||
derives BDD of the cut function, constructs ISOP, factors the cover,
|
||||
and replaces the current implementation of the MFFC of the cut by the
|
||||
new factored form if the number of AIG nodes is reduced. Returns the
|
||||
derives BDD of the cut function, constructs ISOP, factors the ISOP,
|
||||
and replaces the current implementation of the MFFC of the node by the
|
||||
new factored form, if the number of AIG nodes is reduced and the total
|
||||
number of levels of the AIG network is not increated. Returns the
|
||||
number of AIG nodes saved.]
|
||||
|
||||
SideEffects []
|
||||
|
|
@ -68,7 +81,7 @@ static Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose )
|
||||
int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool fUseZeros, bool fUseDcs, bool fVerbose )
|
||||
{
|
||||
int fCheck = 1;
|
||||
ProgressBar * pProgress;
|
||||
|
|
@ -78,11 +91,13 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool
|
|||
Vec_Int_t * vForm;
|
||||
Abc_Obj_t * pNode;
|
||||
int i, nNodes;
|
||||
int clk, clkStart = clock();
|
||||
|
||||
assert( Abc_NtkIsAig(pNtk) );
|
||||
// start the managers
|
||||
pManCut = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax );
|
||||
pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fVerbose );
|
||||
pManRef = Abc_NtkManRefStart( nNodeSizeMax, nConeSizeMax, fUseDcs, fVerbose );
|
||||
pManRef->vLeaves = Abc_NtkManCutReadLeaves( pManCut );
|
||||
pManRef->vReqTimes = Abc_NtkGetRequiredLevels( pNtk );
|
||||
|
||||
// resynthesize each node once
|
||||
|
|
@ -90,27 +105,42 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool
|
|||
pProgress = Extra_ProgressBarStart( stdout, nNodes );
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, nNodes, NULL );
|
||||
// compute a reconvergence-driven cut
|
||||
vFanins = Abc_NodeFindCut( pManCut, pNode );
|
||||
// evaluate this cut
|
||||
vForm = Abc_NodeRefactor( pManRef, pNode, vFanins );
|
||||
// if acceptable replacement found, update the graph
|
||||
if ( vForm )
|
||||
Abc_NodeUpdate( pNode, vFanins, vForm, 0 );
|
||||
// check the improvement
|
||||
if ( i == nNodes )
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
// stop if all nodes have been tried once
|
||||
if ( i >= nNodes )
|
||||
break;
|
||||
// skip the constant node
|
||||
if ( Abc_NodeIsConst(pNode) )
|
||||
continue;
|
||||
// compute a reconvergence-driven cut
|
||||
clk = clock();
|
||||
vFanins = Abc_NodeFindCut( pManCut, pNode, fUseDcs );
|
||||
pManRef->timeCut += clock() - clk;
|
||||
// evaluate this cut
|
||||
clk = clock();
|
||||
vForm = Abc_NodeRefactor( pManRef, pNode, vFanins, fUseZeros, fUseDcs, fVerbose );
|
||||
pManRef->timeRes += clock() - clk;
|
||||
if ( vForm == NULL )
|
||||
continue;
|
||||
// acceptable replacement found, update the graph
|
||||
clk = clock();
|
||||
Abc_NodeUpdate( pNode, vFanins, vForm, pManRef->nLastGain );
|
||||
pManRef->timeNtk += clock() - clk;
|
||||
Vec_IntFree( vForm );
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
pManRef->timeTotal = clock() - clkStart;
|
||||
|
||||
// print statistics of the manager
|
||||
if ( fVerbose )
|
||||
Abc_NtkManRefPrintStats( pManRef );
|
||||
// delete the managers
|
||||
Abc_NtkManCutStop( pManCut );
|
||||
Abc_NtkManRefStop( pManRef );
|
||||
// check
|
||||
if ( fCheck && !Abc_NtkCheck( pNtk ) )
|
||||
{
|
||||
printf( "Abc_NtkRewrite: The network check has failed.\n" );
|
||||
printf( "Abc_NtkRefactor: The network check has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
|
@ -127,32 +157,120 @@ int Abc_NtkRefactor( Abc_Ntk_t * pNtk, int nNodeSizeMax, int nConeSizeMax, bool
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins )
|
||||
Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, bool fUseZeros, bool fUseDcs, bool fVerbose )
|
||||
{
|
||||
int fVeryVerbose = 0;
|
||||
Abc_Obj_t * pFanin;
|
||||
Vec_Int_t * vForm;
|
||||
DdNode * bFuncNode;
|
||||
int nNodesSaved, RetValue;
|
||||
DdNode * bNodeFunc, * bNodeDc, * bNodeOn, * bNodeOnDc;
|
||||
char * pSop;
|
||||
int nBddNodes, nFtNodes, nNodesSaved, nNodesAdded;
|
||||
int i, clk;
|
||||
|
||||
// get the cover
|
||||
bFuncNode = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited ); Cudd_Ref( bFuncNode );
|
||||
pSop = Abc_ConvertBddToSop( NULL, p->dd, bFuncNode, bFuncNode, vFanins->nSize, p->vCube, -1 );
|
||||
Cudd_RecursiveDeref( p->dd, bFuncNode );
|
||||
// derive the factored form
|
||||
p->nNodesConsidered++;
|
||||
|
||||
// get the function of the cut
|
||||
clk = clock();
|
||||
bNodeFunc = Abc_NodeConeBdd( p->dd, p->dd->vars, pNode, vFanins, p->vVisited ); Cudd_Ref( bNodeFunc );
|
||||
p->timeBdd += clock() - clk;
|
||||
nBddNodes = Cudd_DagSize(bNodeFunc);
|
||||
|
||||
// if don't-care are used, transform the function into ISOP
|
||||
if ( fUseDcs )
|
||||
{
|
||||
int nMints, nMintsDc;
|
||||
|
||||
clk = clock();
|
||||
// get the don't-cares
|
||||
bNodeDc = Abc_NodeConeDcs( p->dd, p->dd->vars + vFanins->nSize, p->dd->vars, p->vLeaves, vFanins, p->vVisited ); Cudd_Ref( bNodeDc );
|
||||
|
||||
nMints = (1 << vFanins->nSize);
|
||||
nMintsDc = (int)Cudd_CountMinterm( p->dd, bNodeDc, vFanins->nSize );
|
||||
printf( "Percentage of minterms = %5.2f.\n", 100.0 * nMintsDc / nMints );
|
||||
|
||||
// get the ISF
|
||||
bNodeOn = Cudd_bddAnd( p->dd, bNodeFunc, Cudd_Not(bNodeDc) ); Cudd_Ref( bNodeOn );
|
||||
bNodeOnDc = Cudd_bddOr ( p->dd, bNodeFunc, bNodeDc ); Cudd_Ref( bNodeOnDc );
|
||||
Cudd_RecursiveDeref( p->dd, bNodeFunc );
|
||||
Cudd_RecursiveDeref( p->dd, bNodeDc );
|
||||
// get the ISOP
|
||||
bNodeFunc = Cudd_bddIsop( p->dd, bNodeOn, bNodeOnDc ); Cudd_Ref( bNodeFunc );
|
||||
Cudd_RecursiveDeref( p->dd, bNodeOn );
|
||||
Cudd_RecursiveDeref( p->dd, bNodeOnDc );
|
||||
p->timeDcs += clock() - clk;
|
||||
}
|
||||
|
||||
//Extra_bddPrint( p->dd, bNodeFunc ); printf( "\n" );
|
||||
// always accept the case of constant node
|
||||
if ( Cudd_IsConstant(bNodeFunc) )
|
||||
{
|
||||
p->nNodesGained += Abc_NodeMffcSize( pNode );
|
||||
p->nNodesRefactored++;
|
||||
// get the costant node
|
||||
pFanin = Abc_ObjNotCond( Abc_AigConst1(pNode->pNtk->pManFunc), Cudd_IsComplement(bNodeFunc) );
|
||||
Abc_AigReplace( pNode->pNtk->pManFunc, pNode, pFanin );
|
||||
Cudd_RecursiveDeref( p->dd, bNodeFunc );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// get the SOP of the cut
|
||||
clk = clock();
|
||||
pSop = Abc_ConvertBddToSop( NULL, p->dd, bNodeFunc, bNodeFunc, vFanins->nSize, p->vCube, -1 );
|
||||
p->timeSop += clock() - clk;
|
||||
Cudd_RecursiveDeref( p->dd, bNodeFunc );
|
||||
|
||||
// get the factored form
|
||||
clk = clock();
|
||||
vForm = Ft_Factor( pSop );
|
||||
p->timeFact += clock() - clk;
|
||||
nFtNodes = Ft_FactorGetNumNodes( vForm );
|
||||
free( pSop );
|
||||
//Ft_FactorPrint( stdout, vForm, NULL, NULL );
|
||||
|
||||
// label MFFC with current ID
|
||||
// mark the fanin boundary
|
||||
// (can mark only essential fanins, belonging to bNodeFunc!!!)
|
||||
Vec_PtrForEachEntry( vFanins, pFanin, i )
|
||||
pFanin->vFanouts.nSize++;
|
||||
|
||||
// label MFFC with current traversal ID
|
||||
Abc_NtkIncrementTravId( pNode->pNtk );
|
||||
nNodesSaved = Abc_NodeMffcLabel( pNode );
|
||||
// detect how many unlabeled nodes will be reused
|
||||
RetValue = Abc_NodeStrashDecCount( pNode->pNtk->pManFunc, vFanins, vForm,
|
||||
|
||||
// unmark the fanin boundary
|
||||
Vec_PtrForEachEntry( vFanins, pFanin, i )
|
||||
pFanin->vFanouts.nSize--;
|
||||
|
||||
// detect how many new nodes will be added (while taking into account reused nodes)
|
||||
nNodesAdded = Abc_NodeStrashDecCount( pNode->pNtk->pManFunc, pNode, vFanins, vForm,
|
||||
p->vLevNums, nNodesSaved, Vec_IntEntry( p->vReqTimes, pNode->Id ) );
|
||||
if ( RetValue >= 0 )
|
||||
return vForm;
|
||||
Vec_IntFree( vForm );
|
||||
// quit if there is no improvement
|
||||
if ( nNodesAdded == -1 || nNodesAdded == nNodesSaved && !fUseZeros )
|
||||
{
|
||||
Vec_IntFree( vForm );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// compute the total gain in the number of nodes
|
||||
p->nLastGain = nNodesSaved - nNodesAdded;
|
||||
p->nNodesGained += p->nLastGain;
|
||||
p->nNodesRefactored++;
|
||||
|
||||
// report the progress
|
||||
if ( fVeryVerbose )
|
||||
{
|
||||
printf( "Node %6s : ", Abc_ObjName(pNode) );
|
||||
printf( "Cone = %2d. ", vFanins->nSize );
|
||||
printf( "BDD = %2d. ", nBddNodes );
|
||||
printf( "FF = %2d. ", nFtNodes );
|
||||
printf( "MFFC = %2d. ", nNodesSaved );
|
||||
printf( "Add = %2d. ", nNodesAdded );
|
||||
printf( "GAIN = %2d. ", p->nLastGain );
|
||||
printf( "\n" );
|
||||
}
|
||||
return vForm;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Starts the resynthesis manager.]
|
||||
|
|
@ -164,19 +282,22 @@ Vec_Int_t * Abc_NodeRefactor( Abc_ManRef_t * p, Abc_Obj_t * pNode, Vec_Ptr_t * v
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, int fVerbose )
|
||||
Abc_ManRef_t * Abc_NtkManRefStart( int nNodeSizeMax, int nConeSizeMax, bool fUseDcs, bool fVerbose )
|
||||
{
|
||||
Abc_ManRef_t * p;
|
||||
p = ALLOC( Abc_ManRef_t, 1 );
|
||||
memset( p, 0, sizeof(Abc_ManRef_t) );
|
||||
p->vCube = Vec_StrAlloc( 100 );
|
||||
p->vLevNums = Vec_IntAlloc( 100 );
|
||||
p->vVisited = Vec_PtrAlloc( 100 );
|
||||
p->vCube = Vec_StrAlloc( 100 );
|
||||
p->vLevNums = Vec_IntAlloc( 100 );
|
||||
p->vVisited = Vec_PtrAlloc( 100 );
|
||||
p->nNodeSizeMax = nNodeSizeMax;
|
||||
p->nConeSizeMax = nConeSizeMax;
|
||||
p->fVerbose = fVerbose;
|
||||
// start the BDD manager
|
||||
p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
|
||||
if ( fUseDcs )
|
||||
p->dd = Cudd_Init( p->nNodeSizeMax + p->nConeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
|
||||
else
|
||||
p->dd = Cudd_Init( p->nNodeSizeMax, 0, CUDD_UNIQUE_SLOTS, CUDD_CACHE_SLOTS, 0 );
|
||||
Cudd_zddVarsFromBddVars( p->dd, 2 );
|
||||
return p;
|
||||
}
|
||||
|
|
@ -202,6 +323,34 @@ void Abc_NtkManRefStop( Abc_ManRef_t * p )
|
|||
free( p );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Stops the resynthesis manager.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkManRefPrintStats( Abc_ManRef_t * p )
|
||||
{
|
||||
printf( "Refactoring statistics:\n" );
|
||||
printf( "Nodes considered = %6d.\n", p->nNodesConsidered );
|
||||
printf( "Nodes refactored = %6d.\n", p->nNodesRefactored );
|
||||
printf( "Calculated gain = %6d.\n", p->nNodesGained );
|
||||
PRT( "Cuts ", p->timeCut );
|
||||
PRT( "Resynthesis", p->timeRes );
|
||||
PRT( " BDD ", p->timeBdd );
|
||||
PRT( " DCs ", p->timeDcs );
|
||||
PRT( " SOP ", p->timeSop );
|
||||
PRT( " FF ", p->timeFact );
|
||||
PRT( "AIG update ", p->timeNtk );
|
||||
PRT( "TOTAL ", p->timeTotal );
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// END OF FILE ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel );
|
||||
static int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes );
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
/// FUNCTION DEFITIONS ///
|
||||
|
|
@ -48,8 +48,8 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
|
|||
assert( Abc_ObjIsNode( pNode ) );
|
||||
if ( Abc_ObjFaninNum(pNode) == 0 )
|
||||
return 0;
|
||||
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
|
||||
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0 ); // reference
|
||||
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, NULL ); // dereference
|
||||
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
|
||||
assert( nConeSize1 == nConeSize2 );
|
||||
assert( nConeSize1 > 0 );
|
||||
return nConeSize1;
|
||||
|
|
@ -57,7 +57,7 @@ int Abc_NodeMffcSize( Abc_Obj_t * pNode )
|
|||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Lavels MFFC with the current traversal ID.]
|
||||
Synopsis [Labels MFFC with the current traversal ID.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -73,13 +73,40 @@ int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
|
|||
assert( Abc_ObjIsNode( pNode ) );
|
||||
if ( Abc_ObjFaninNum(pNode) == 0 )
|
||||
return 0;
|
||||
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0 ); // dereference
|
||||
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 1 ); // reference
|
||||
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 1, NULL ); // dereference
|
||||
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
|
||||
assert( nConeSize1 == nConeSize2 );
|
||||
assert( nConeSize1 > 0 );
|
||||
return nConeSize1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes in MFFC in the topological order.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Abc_NodeMffcCollect( Abc_Obj_t * pNode )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
int nConeSize1, nConeSize2;
|
||||
assert( !Abc_ObjIsComplement( pNode ) );
|
||||
assert( Abc_ObjIsNode( pNode ) );
|
||||
vNodes = Vec_PtrAlloc( 8 );
|
||||
if ( Abc_ObjFaninNum(pNode) == 0 )
|
||||
return vNodes;
|
||||
nConeSize1 = Abc_NodeRefDeref( pNode, 0, 0, vNodes ); // dereference
|
||||
nConeSize2 = Abc_NodeRefDeref( pNode, 1, 0, NULL ); // reference
|
||||
assert( nConeSize1 == nConeSize2 );
|
||||
assert( nConeSize1 > 0 );
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [References/references the node and returns MFFC size.]
|
||||
|
|
@ -91,39 +118,48 @@ int Abc_NodeMffcLabel( Abc_Obj_t * pNode )
|
|||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel )
|
||||
int Abc_NodeRefDeref( Abc_Obj_t * pNode, bool fReference, bool fLabel, Vec_Ptr_t * vNodes )
|
||||
{
|
||||
Abc_Obj_t * pNode0, * pNode1;
|
||||
int Counter;
|
||||
// label visited nodes
|
||||
if ( fLabel )
|
||||
{
|
||||
Abc_NodeSetTravIdCurrent( pNode );
|
||||
//printf( "Labeling " ); Abc_AigPrintNode( pNode );
|
||||
}
|
||||
// collect visited nodes
|
||||
if ( vNodes )
|
||||
Vec_PtrPush( vNodes, pNode );
|
||||
// skip the CI
|
||||
if ( Abc_ObjIsCi(pNode) )
|
||||
return 0;
|
||||
// process the internal node
|
||||
pNode0 = Abc_ObjFanin( pNode, 0 );
|
||||
pNode1 = Abc_ObjFanin( pNode, 1 );
|
||||
Counter = 1;
|
||||
if ( fReference )
|
||||
{
|
||||
if ( pNode0->vFanouts.nSize++ == 0 )
|
||||
Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
|
||||
Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes );
|
||||
if ( pNode1->vFanouts.nSize++ == 0 )
|
||||
Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
|
||||
Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes );
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( pNode0->vFanouts.nSize > 0 );
|
||||
assert( pNode1->vFanouts.nSize > 0 );
|
||||
if ( --pNode0->vFanouts.nSize == 0 )
|
||||
Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel );
|
||||
Counter += Abc_NodeRefDeref( pNode0, fReference, fLabel, vNodes );
|
||||
if ( --pNode1->vFanouts.nSize == 0 )
|
||||
Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel );
|
||||
Counter += Abc_NodeRefDeref( pNode1, fReference, fLabel, vNodes );
|
||||
}
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Replaces MFFC of the node by the new factored.]
|
||||
Synopsis [Replaces MFFC of the node by the new factored form.]
|
||||
|
||||
Description []
|
||||
|
||||
|
|
@ -138,7 +174,7 @@ void Abc_NodeUpdate( Abc_Obj_t * pNode, Vec_Ptr_t * vFanins, Vec_Int_t * vForm,
|
|||
int nNodesNew, nNodesOld;
|
||||
nNodesOld = Abc_NtkNodeNum(pNode->pNtk);
|
||||
// create the new structure of nodes
|
||||
assert( Vec_PtrSize(vFanins) < Vec_IntSize(vForm) );
|
||||
assert( vForm->nSize == 1 || Vec_PtrSize(vFanins) < Vec_IntSize(vForm) );
|
||||
pNodeNew = Abc_NodeStrashDec( pNode->pNtk->pManFunc, vFanins, vForm );
|
||||
// remove the old nodes
|
||||
Abc_AigReplace( pNode->pNtk->pManFunc, pNode, pNodeNew );
|
||||
|
|
|
|||
|
|
@ -60,13 +60,16 @@ int Abc_NtkRewrite( Abc_Ntk_t * pNtk )
|
|||
pProgress = Extra_ProgressBarStart( stdout, nNodes );
|
||||
Abc_NtkForEachNode( pNtk, pNode, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, nNodes, NULL );
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
// stop if all nodes have been tried once
|
||||
if ( i >= nNodes )
|
||||
break;
|
||||
// skip the constant node
|
||||
if ( Abc_NodeIsConst(pNode) )
|
||||
continue;
|
||||
// for each cut, try to resynthesize it
|
||||
if ( (nGain = Rwr_NodeRewrite( p, pNode )) >= 0 )
|
||||
Abc_NodeUpdate( pNode, Rwr_ManReadFanins(p), Rwr_ManReadDecs(p), nGain );
|
||||
// check the improvement
|
||||
if ( i == nNodes )
|
||||
break;
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
// delete the manager
|
||||
|
|
|
|||
|
|
@ -353,6 +353,82 @@ int Abc_SopGetPhase( char * pSop )
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the i-th literal of the cover.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SopGetIthCareLit( char * pSop, int i )
|
||||
{
|
||||
char * pCube;
|
||||
int nVars, c;
|
||||
nVars = Abc_SopGetVarNum( pSop );
|
||||
for ( c = 0; ; c++ )
|
||||
{
|
||||
// get the cube
|
||||
pCube = pSop + c * (nVars + 3);
|
||||
if ( *pCube == 0 )
|
||||
break;
|
||||
// get the literal
|
||||
if ( pCube[i] != '-' )
|
||||
return pCube[i] - '0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_SopComplement( char * pSop )
|
||||
{
|
||||
char * pCur;
|
||||
for ( pCur = pSop; *pCur; pCur++ )
|
||||
if ( *pCur == '\n' )
|
||||
{
|
||||
if ( *(pCur - 1) == '0' )
|
||||
*(pCur - 1) = '1';
|
||||
else if ( *(pCur - 1) == '1' )
|
||||
*(pCur - 1) = '0';
|
||||
else
|
||||
assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
bool Abc_SopIsComplement( char * pSop )
|
||||
{
|
||||
char * pCur;
|
||||
for ( pCur = pSop; *pCur; pCur++ )
|
||||
if ( *pCur == '\n' )
|
||||
return (int)(*(pCur - 1) == '0');
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Checks if the cover is constant 0.]
|
||||
|
|
@ -479,61 +555,6 @@ bool Abc_SopIsOrType( char * pSop )
|
|||
return 1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Returns the i-th literal of the cover.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_SopGetIthCareLit( char * pSop, int i )
|
||||
{
|
||||
char * pCube;
|
||||
int nVars, c;
|
||||
nVars = Abc_SopGetVarNum( pSop );
|
||||
for ( c = 0; ; c++ )
|
||||
{
|
||||
// get the cube
|
||||
pCube = pSop + c * (nVars + 3);
|
||||
if ( *pCube == 0 )
|
||||
break;
|
||||
// get the literal
|
||||
if ( pCube[i] != '-' )
|
||||
return pCube[i] - '0';
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_SopComplement( char * pSop )
|
||||
{
|
||||
char * pCur;
|
||||
for ( pCur = pSop; *pCur; pCur++ )
|
||||
if ( *pCur == '\n' )
|
||||
{
|
||||
if ( *(pCur - 1) == '0' )
|
||||
*(pCur - 1) = '1';
|
||||
else if ( *(pCur - 1) == '1' )
|
||||
*(pCur - 1) = '0';
|
||||
else
|
||||
assert( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis []
|
||||
|
|
|
|||
|
|
@ -31,11 +31,6 @@ static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig,
|
|||
static Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode );
|
||||
static Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
|
||||
static Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
|
||||
static Abc_Obj_t * Abc_NodeStrashFactor2( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop );
|
||||
|
||||
static void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate );
|
||||
static Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, bool fDuplicate );
|
||||
static Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, int fDuplicate );
|
||||
|
||||
extern char * Mio_GateReadSop( void * pGate );
|
||||
|
||||
|
|
@ -47,7 +42,8 @@ extern char * Mio_GateReadSop( void * pGate );
|
|||
|
||||
Synopsis [Creates the strashed AIG network.]
|
||||
|
||||
Description []
|
||||
Description [Converts the logic network or the AIG into a
|
||||
structurally hashed AIG.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
|
|
@ -91,6 +87,53 @@ Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, bool fAllNodes )
|
|||
return pNtkAig;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Appends the second network to the first.]
|
||||
|
||||
Description [Modifies the first network by adding the logic of the second.
|
||||
Performs structural hashing while appending the networks. Does not add
|
||||
the COs of the second. Does not change the second network. Returns 0
|
||||
if the appending failed, 1 otherise.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
|
||||
{
|
||||
int fCheck = 1;
|
||||
Abc_Obj_t * pObj;
|
||||
int i;
|
||||
// the first network should be an AIG
|
||||
assert( Abc_NtkIsAig(pNtk1) );
|
||||
assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsAig(pNtk2) );
|
||||
if ( Abc_NtkIsLogicBdd(pNtk2) )
|
||||
{
|
||||
// printf( "Converting node functions from BDD to SOP.\n" );
|
||||
Abc_NtkBddToSop(pNtk2);
|
||||
}
|
||||
// check that the networks have the same PIs
|
||||
// reorder PIs of pNtk2 according to pNtk1
|
||||
if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1 ) )
|
||||
return 0;
|
||||
// perform strashing
|
||||
Abc_NtkCleanCopy( pNtk2 );
|
||||
Abc_NtkForEachCi( pNtk2, pObj, i )
|
||||
pObj->pCopy = Abc_NtkCi(pNtk1, i);
|
||||
// add pNtk2 to pNtk1 while strashing
|
||||
Abc_NtkStrashPerform( pNtk2, pNtk1, 1 );
|
||||
// make sure that everything is okay
|
||||
if ( fCheck && !Abc_NtkCheck( pNtk1 ) )
|
||||
{
|
||||
printf( "Abc_NtkAppend: The network check has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prepares the network for strashing.]
|
||||
|
|
@ -121,10 +164,7 @@ void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, bool fAllNodes
|
|||
// strash the node
|
||||
pNodeNew = Abc_NodeStrash( pMan, pNode );
|
||||
// get the old object
|
||||
if ( Abc_NtkIsNetlist(pNtk) )
|
||||
pObj = Abc_ObjFanout0( pNode ); // the fanout net
|
||||
else
|
||||
pObj = vNodes->pArray[i]; // the node itself
|
||||
pObj = Abc_ObjFanout0Ntk( pNode );
|
||||
// make sure the node is not yet strashed
|
||||
assert( pObj->pCopy == NULL );
|
||||
// mark the old object with the new AIG node
|
||||
|
|
@ -180,7 +220,7 @@ Abc_Obj_t * Abc_NodeStrash( Abc_Aig_t * pMan, Abc_Obj_t * pNode )
|
|||
|
||||
// decide when to use factoring
|
||||
if ( fUseFactor && Abc_ObjFaninNum(pNode) > 2 && Abc_SopGetCubeNum(pSop) > 1 )
|
||||
return Abc_NodeStrashFactor2( pMan, pNode, pSop );
|
||||
return Abc_NodeStrashFactor( pMan, pNode, pSop );
|
||||
return Abc_NodeStrashSop( pMan, pNode, pSop );
|
||||
}
|
||||
|
||||
|
|
@ -222,8 +262,7 @@ Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop
|
|||
pSum = Abc_AigOr( pMan, pSum, pAnd );
|
||||
}
|
||||
// decide whether to complement the result
|
||||
pCube = pSop;
|
||||
if ( pCube[nFanins + 1] == '0' )
|
||||
if ( Abc_SopIsComplement(pSop) )
|
||||
pSum = Abc_ObjNot(pSum);
|
||||
return pSum;
|
||||
}
|
||||
|
|
@ -240,66 +279,6 @@ Abc_Obj_t * Abc_NodeStrashSop( Abc_Aig_t * pMan, Abc_Obj_t * pNode, char * pSop
|
|||
|
||||
***********************************************************************/
|
||||
Abc_Obj_t * Abc_NodeStrashFactor( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pSop )
|
||||
{
|
||||
Vec_Int_t * vForm;
|
||||
Vec_Ptr_t * vAnds;
|
||||
Abc_Obj_t * pAnd, * pAnd0, * pAnd1, * pFanin;
|
||||
Ft_Node_t * pFtNode;
|
||||
int i, nVars;
|
||||
|
||||
// derive the factored form
|
||||
vForm = Ft_Factor( pSop );
|
||||
|
||||
// sanity checks
|
||||
nVars = Ft_FactorGetNumVars( vForm );
|
||||
assert( nVars >= 0 );
|
||||
assert( vForm->nSize > nVars );
|
||||
assert( nVars == Abc_ObjFaninNum(pRoot) );
|
||||
|
||||
// check for constant function
|
||||
pFtNode = Ft_NodeRead( vForm, 0 );
|
||||
if ( pFtNode->fConst )
|
||||
{
|
||||
Vec_IntFree( vForm );
|
||||
return Abc_ObjNotCond( Abc_AigConst1(pMan), pFtNode->fCompl );
|
||||
}
|
||||
|
||||
// start the array of elementary variables
|
||||
vAnds = Vec_PtrAlloc( 20 );
|
||||
Abc_ObjForEachFanin( pRoot, pFanin, i )
|
||||
Vec_PtrPush( vAnds, pFanin->pCopy );
|
||||
|
||||
// compute the function of other nodes
|
||||
for ( i = nVars; i < vForm->nSize; i++ )
|
||||
{
|
||||
pFtNode = Ft_NodeRead( vForm, i );
|
||||
pAnd0 = Abc_ObjNotCond( vAnds->pArray[pFtNode->iFanin0], pFtNode->fCompl0 );
|
||||
pAnd1 = Abc_ObjNotCond( vAnds->pArray[pFtNode->iFanin1], pFtNode->fCompl1 );
|
||||
pAnd = Abc_AigAnd( pMan, pAnd0, pAnd1 );
|
||||
Vec_PtrPush( vAnds, pAnd );
|
||||
}
|
||||
assert( vForm->nSize = vAnds->nSize );
|
||||
Vec_PtrFree( vAnds );
|
||||
|
||||
// complement the result if necessary
|
||||
pFtNode = Ft_NodeReadLast( vForm );
|
||||
pAnd = Abc_ObjNotCond( pAnd, pFtNode->fCompl );
|
||||
Vec_IntFree( vForm );
|
||||
return pAnd;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Strashes one logic node using its SOP.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Obj_t * Abc_NodeStrashFactor2( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, char * pSop )
|
||||
{
|
||||
Vec_Int_t * vForm;
|
||||
Vec_Ptr_t * vAnds;
|
||||
|
|
@ -354,6 +333,7 @@ Abc_Obj_t * Abc_NodeStrashDec( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t
|
|||
pAnd1 = Abc_ObjNotCond( vFanins->pArray[pFtNode->iFanin1], pFtNode->fCompl1 );
|
||||
pAnd = Abc_AigAnd( pMan, pAnd0, pAnd1 );
|
||||
Vec_PtrPush( vFanins, pAnd );
|
||||
//printf( "Adding " ); Abc_AigPrintNode( pAnd );
|
||||
}
|
||||
assert( vForm->nSize = vFanins->nSize );
|
||||
|
||||
|
|
@ -367,24 +347,25 @@ Abc_Obj_t * Abc_NodeStrashDec( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t
|
|||
|
||||
Synopsis [Counts the number of new nodes added when using this factored form,]
|
||||
|
||||
Description [Returns -1 if the number of nodes and levels exceeded the given limit.]
|
||||
Description [Returns NodeMax + 1 if the number of nodes and levels exceeded
|
||||
the given limit or the number of levels exceeded the maximum allowed level.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeStrashDecCount( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, Vec_Int_t * vLevels, int NodeMax, int LevelMax )
|
||||
int Abc_NodeStrashDecCount( Abc_Aig_t * pMan, Abc_Obj_t * pRoot, Vec_Ptr_t * vFanins, Vec_Int_t * vForm, Vec_Int_t * vLevels, int NodeMax, int LevelMax )
|
||||
{
|
||||
Abc_Obj_t * pAnd, * pAnd0, * pAnd1;
|
||||
Abc_Obj_t * pAnd, * pAnd0, * pAnd1, * pTop;
|
||||
Ft_Node_t * pFtNode;
|
||||
int i, nVars, Counter, LevelNew;
|
||||
int i, nVars, LevelNew, LevelOld, Counter;
|
||||
|
||||
// sanity checks
|
||||
nVars = Ft_FactorGetNumVars( vForm );
|
||||
assert( nVars >= 0 );
|
||||
assert( vForm->nSize > nVars );
|
||||
assert( nVars == vFanins->nSize );
|
||||
assert( nVars == vFanins->nSize ); // set the fanin number to nVars???
|
||||
|
||||
// check for constant function
|
||||
pFtNode = Ft_NodeRead( vForm, 0 );
|
||||
|
|
@ -401,275 +382,83 @@ int Abc_NodeStrashDecCount( Abc_Aig_t * pMan, Vec_Ptr_t * vFanins, Vec_Int_t * v
|
|||
for ( i = nVars; i < vForm->nSize; i++ )
|
||||
{
|
||||
pFtNode = Ft_NodeRead( vForm, i );
|
||||
pAnd0 = Abc_ObjNotCond( Vec_PtrEntry(vFanins, pFtNode->iFanin0), pFtNode->fCompl0 );
|
||||
if ( pAnd0 )
|
||||
// check for buffer/inverter
|
||||
if ( pFtNode->iFanin0 == pFtNode->iFanin1 )
|
||||
{
|
||||
pAnd1 = Abc_ObjNotCond( Vec_PtrEntry(vFanins, pFtNode->iFanin1), pFtNode->fCompl1 );
|
||||
pAnd = pAnd1? Abc_AigAndLookup( pMan, pAnd0, pAnd1 ) : NULL;
|
||||
assert( vForm->nSize == nVars + 1 );
|
||||
pAnd = Vec_PtrEntry(vFanins, pFtNode->iFanin0);
|
||||
pAnd = Abc_ObjNotCond( pAnd, pFtNode->fCompl );
|
||||
Vec_PtrPush( vFanins, pAnd );
|
||||
break;
|
||||
}
|
||||
|
||||
pAnd0 = Vec_PtrEntry(vFanins, pFtNode->iFanin0);
|
||||
pAnd1 = Vec_PtrEntry(vFanins, pFtNode->iFanin1);
|
||||
if ( pAnd0 && pAnd1 )
|
||||
{
|
||||
pAnd0 = Abc_ObjNotCond( pAnd0, pFtNode->fCompl0 );
|
||||
pAnd1 = Abc_ObjNotCond( pAnd1, pFtNode->fCompl1 );
|
||||
pAnd = Abc_AigAndLookup( pMan, pAnd0, pAnd1 );
|
||||
}
|
||||
else
|
||||
pAnd = NULL;
|
||||
// count the number of added nodes
|
||||
if ( pAnd == NULL || Abc_NodeIsTravIdCurrent(pAnd) )
|
||||
if ( pAnd == NULL || Abc_NodeIsTravIdCurrent( Abc_ObjRegular(pAnd) ) )
|
||||
{
|
||||
if ( pAnd )
|
||||
{
|
||||
//printf( "Reusing labeled " ); Abc_AigPrintNode( pAnd );
|
||||
}
|
||||
Counter++;
|
||||
if ( Counter > NodeMax )
|
||||
{
|
||||
Vec_PtrShrink( vFanins, nVars );
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf( "Reusing " ); Abc_AigPrintNode( pAnd );
|
||||
}
|
||||
|
||||
// count the number of new levels
|
||||
LevelNew = 1 + ABC_MAX( Vec_IntEntry(vLevels, pFtNode->iFanin0), Vec_IntEntry(vLevels, pFtNode->iFanin1) );
|
||||
assert( pAnd == NULL || LevelNew == (int)Abc_ObjRegular(pAnd)->Level );
|
||||
if ( pAnd && Abc_ObjRegular(pAnd) == Abc_AigConst1(pMan) )
|
||||
LevelNew = 0;
|
||||
else
|
||||
LevelNew = 1 + ABC_MAX( Vec_IntEntry(vLevels, pFtNode->iFanin0), Vec_IntEntry(vLevels, pFtNode->iFanin1) );
|
||||
|
||||
// assert( pAnd == NULL || LevelNew == LevelOld );
|
||||
if ( pAnd )
|
||||
{
|
||||
LevelOld = (int)Abc_ObjRegular(pAnd)->Level;
|
||||
if ( LevelNew != LevelOld )
|
||||
{
|
||||
int x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( LevelNew > LevelMax )
|
||||
{
|
||||
Vec_PtrShrink( vFanins, nVars );
|
||||
return -1;
|
||||
}
|
||||
Vec_PtrPush( vFanins, pAnd );
|
||||
Vec_IntPush( vLevels, LevelNew );
|
||||
}
|
||||
assert( vForm->nSize = vFanins->nSize );
|
||||
|
||||
// check if this is the same form
|
||||
pTop = Vec_PtrEntryLast(vFanins);
|
||||
if ( Abc_ObjRegular(pTop) == pRoot )
|
||||
{
|
||||
assert( !Abc_ObjIsComplement(pTop) );
|
||||
Vec_PtrShrink( vFanins, nVars );
|
||||
return -1;
|
||||
}
|
||||
Vec_PtrShrink( vFanins, nVars );
|
||||
return Counter;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Appends the second network to the first.]
|
||||
|
||||
Description [Modifies the first network by adding the logic of the second.
|
||||
Does not add the COs of the second. Does not change the second network.
|
||||
Returns 0 if the appending failed, 1 otherise.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2 )
|
||||
{
|
||||
int fCheck = 1;
|
||||
Abc_Obj_t * pObj;
|
||||
int i;
|
||||
// the first network should be an AIG
|
||||
assert( Abc_NtkIsAig(pNtk1) );
|
||||
assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsAig(pNtk2) );
|
||||
if ( Abc_NtkIsLogicBdd(pNtk2) )
|
||||
{
|
||||
// printf( "Converting node functions from BDD to SOP.\n" );
|
||||
Abc_NtkBddToSop(pNtk2);
|
||||
}
|
||||
// check that the networks have the same PIs
|
||||
// reorder PIs of pNtk2 according to pNtk1
|
||||
if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1 ) )
|
||||
return 0;
|
||||
// perform strashing
|
||||
Abc_NtkCleanCopy( pNtk2 );
|
||||
Abc_NtkForEachCi( pNtk2, pObj, i )
|
||||
pObj->pCopy = Abc_NtkCi(pNtk1, i);
|
||||
// add pNtk2 to pNtk1 while strashing
|
||||
Abc_NtkStrashPerform( pNtk2, pNtk1, 1 );
|
||||
// make sure that everything is okay
|
||||
if ( fCheck && !Abc_NtkCheck( pNtk1 ) )
|
||||
{
|
||||
printf( "Abc_NtkAppend: The network check has failed.\n" );
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Balances the AIG network.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Ntk_t * Abc_NtkBalance( Abc_Ntk_t * pNtk, bool fDuplicate )
|
||||
{
|
||||
int fCheck = 1;
|
||||
Abc_Ntk_t * pNtkAig;
|
||||
assert( Abc_NtkIsAig(pNtk) );
|
||||
// perform balancing
|
||||
pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_AIG );
|
||||
Abc_NtkBalancePerform( pNtk, pNtkAig, fDuplicate );
|
||||
Abc_NtkFinalize( pNtk, pNtkAig );
|
||||
// make sure everything is okay
|
||||
if ( fCheck && !Abc_NtkCheck( pNtkAig ) )
|
||||
{
|
||||
printf( "Abc_NtkBalance: The network check has failed.\n" );
|
||||
Abc_NtkDelete( pNtkAig );
|
||||
return NULL;
|
||||
}
|
||||
return pNtkAig;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Balances the AIG network.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Abc_NtkBalancePerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig, bool fDuplicate )
|
||||
{
|
||||
int fCheck = 1;
|
||||
ProgressBar * pProgress;
|
||||
Abc_Obj_t * pNode, * pDriver;
|
||||
int i;
|
||||
|
||||
// copy the constant node
|
||||
Abc_AigConst1(pNtk->pManFunc)->pCopy = Abc_AigConst1(pNtkAig->pManFunc);
|
||||
// set the level of PIs of AIG according to the arrival times of the old network
|
||||
Abc_NtkSetNodeLevelsArrival( pNtk );
|
||||
// perform balancing of POs
|
||||
pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) );
|
||||
Abc_NtkForEachCo( pNtk, pNode, i )
|
||||
{
|
||||
Extra_ProgressBarUpdate( pProgress, i, NULL );
|
||||
// strash the driver node
|
||||
pDriver = Abc_ObjFanin0(pNode);
|
||||
Abc_NodeBalance_rec( pNtkAig, pDriver, fDuplicate );
|
||||
}
|
||||
Extra_ProgressBarStop( pProgress );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Rebalances the multi-input node rooted at pNodeOld.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Abc_Obj_t * Abc_NodeBalance_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, bool fDuplicate )
|
||||
{
|
||||
Abc_Aig_t * pMan = pNtkNew->pManFunc;
|
||||
Abc_Obj_t * pNodeNew, * pNode1, * pNode2;
|
||||
Vec_Ptr_t * vSuper;
|
||||
int i;
|
||||
assert( !Abc_ObjIsComplement(pNodeOld) );
|
||||
// return if the result if known
|
||||
if ( pNodeOld->pCopy )
|
||||
return pNodeOld->pCopy;
|
||||
assert( Abc_ObjIsNode(pNodeOld) );
|
||||
// get the implication supergate
|
||||
vSuper = Abc_NodeBalanceCone( pNodeOld, fDuplicate );
|
||||
if ( vSuper->nSize == 0 )
|
||||
{ // it means that the supergate contains two nodes in the opposite polarity
|
||||
Vec_PtrFree( vSuper );
|
||||
pNodeOld->pCopy = Abc_ObjNot(Abc_AigConst1(pMan));
|
||||
return pNodeOld->pCopy;
|
||||
}
|
||||
// for each old node, derive the new well-balanced node
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
{
|
||||
pNodeNew = Abc_NodeBalance_rec( pNtkNew, Abc_ObjRegular(vSuper->pArray[i]), fDuplicate );
|
||||
vSuper->pArray[i] = Abc_ObjNotCond( pNodeNew, Abc_ObjIsComplement(vSuper->pArray[i]) );
|
||||
}
|
||||
// sort the new nodes by level in the decreasing order
|
||||
Vec_PtrSort( vSuper, Abc_NodeCompareLevelsDecrease );
|
||||
// balance the nodes
|
||||
assert( vSuper->nSize > 1 );
|
||||
while ( vSuper->nSize > 1 )
|
||||
{
|
||||
pNode1 = Vec_PtrPop(vSuper);
|
||||
pNode2 = Vec_PtrPop(vSuper);
|
||||
Abc_VecObjPushUniqueOrderByLevel( vSuper, Abc_AigAnd(pMan, pNode1, pNode2) );
|
||||
}
|
||||
// make sure the balanced node is not assigned
|
||||
assert( pNodeOld->pCopy == NULL );
|
||||
// mark the old node with the new node
|
||||
pNodeOld->pCopy = vSuper->pArray[0];
|
||||
Vec_PtrFree( vSuper );
|
||||
return pNodeOld->pCopy;
|
||||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes in the cone delimited by fMarkA==1.]
|
||||
|
||||
Description [Returns -1 if the AND-cone has the same node in both polarities.
|
||||
Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
|
||||
if the AND-cone has no repeated nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Abc_NodeBalanceCone_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, bool fFirst, bool fDuplicate )
|
||||
{
|
||||
int RetValue1, RetValue2, i;
|
||||
// check if the node is visited
|
||||
if ( Abc_ObjRegular(pNode)->fMarkB )
|
||||
{
|
||||
// check if the node occurs in the same polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == pNode )
|
||||
return 1;
|
||||
// check if the node is present in the opposite polarity
|
||||
for ( i = 0; i < vSuper->nSize; i++ )
|
||||
if ( vSuper->pArray[i] == Abc_ObjNot(pNode) )
|
||||
return -1;
|
||||
assert( 0 );
|
||||
return 0;
|
||||
}
|
||||
// if the new node is complemented or a PI, another gate begins
|
||||
if ( !fFirst && (Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || !fDuplicate && (Abc_ObjFanoutNum(pNode) > 1)) )
|
||||
{
|
||||
Vec_PtrPush( vSuper, pNode );
|
||||
Abc_ObjRegular(pNode)->fMarkB = 1;
|
||||
return 0;
|
||||
}
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
assert( Abc_ObjIsNode(pNode) );
|
||||
// go through the branches
|
||||
RetValue1 = Abc_NodeBalanceCone_rec( Abc_ObjChild0(pNode), vSuper, 0, fDuplicate );
|
||||
RetValue2 = Abc_NodeBalanceCone_rec( Abc_ObjChild1(pNode), vSuper, 0, fDuplicate );
|
||||
if ( RetValue1 == -1 || RetValue2 == -1 )
|
||||
return -1;
|
||||
// return 1 if at least one branch has a duplicate
|
||||
return RetValue1 || RetValue2;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Collects the nodes in the cone delimited by fMarkA==1.]
|
||||
|
||||
Description [Returns -1 if the AND-cone has the same node in both polarities.
|
||||
Returns 1 if the AND-cone has the same node in the same polarity. Returns 0
|
||||
if the AND-cone has no repeated nodes.]
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
Vec_Ptr_t * Abc_NodeBalanceCone( Abc_Obj_t * pNode, int fDuplicate )
|
||||
{
|
||||
Vec_Ptr_t * vNodes;
|
||||
int RetValue, i;
|
||||
assert( !Abc_ObjIsComplement(pNode) );
|
||||
vNodes = Vec_PtrAlloc( 4 );
|
||||
RetValue = Abc_NodeBalanceCone_rec( pNode, vNodes, 1, fDuplicate );
|
||||
assert( vNodes->nSize > 0 );
|
||||
for ( i = 0; i < vNodes->nSize; i++ )
|
||||
Abc_ObjRegular((Abc_Obj_t *)vNodes->pArray[i])->fMarkB = 0;
|
||||
if ( RetValue == -1 )
|
||||
vNodes->nSize = 0;
|
||||
return vNodes;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p )
|
|||
ProgressBar * pProgress;
|
||||
Vec_Ptr_t * vTokens;
|
||||
Abc_Ntk_t * pNtk;
|
||||
Abc_Obj_t * pTerm, * pNode;
|
||||
Abc_Obj_t * pTermPi, * pTermPo, * pNode;
|
||||
Vec_Str_t ** ppSops;
|
||||
char Buffer[100];
|
||||
int nInputs = -1, nOutputs = -1, nProducts = -1;
|
||||
|
|
@ -169,13 +169,16 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p )
|
|||
// create the PO drivers and add them
|
||||
// start the SOP covers
|
||||
ppSops = ALLOC( Vec_Str_t *, nOutputs );
|
||||
Abc_NtkForEachPo( pNtk, pTerm, i )
|
||||
Abc_NtkForEachPo( pNtk, pTermPo, i )
|
||||
{
|
||||
ppSops[i] = Vec_StrAlloc( 100 );
|
||||
// create the node
|
||||
pNode = Abc_NtkCreateNode(pNtk);
|
||||
for ( k = 0; k < nInputs; k++ )
|
||||
Abc_ObjAddFanin( pNode, Abc_NtkPi(pNtk,k) );
|
||||
Abc_ObjAddFanin( Abc_ObjFanout0(pTerm), pNode );
|
||||
// connect the node to the PO net
|
||||
Abc_ObjAddFanin( Abc_ObjFanin0Ntk(pTermPo), pNode );
|
||||
// connect the node to the PI nets
|
||||
Abc_NtkForEachPi( pNtk, pTermPi, k )
|
||||
Abc_ObjAddFanin( pNode, Abc_ObjFanout0Ntk(pTermPi) );
|
||||
}
|
||||
}
|
||||
// read the cubes
|
||||
|
|
@ -219,9 +222,9 @@ Abc_Ntk_t * Io_ReadPlaNetwork( Extra_FileReader_t * p )
|
|||
nCubes, nProducts );
|
||||
|
||||
// add the SOP covers
|
||||
Abc_NtkForEachPo( pNtk, pTerm, i )
|
||||
Abc_NtkForEachPo( pNtk, pTermPo, i )
|
||||
{
|
||||
pNode = Abc_ObjFanin0Ntk(pTerm);
|
||||
pNode = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pTermPo) );
|
||||
if ( ppSops[i]->nSize == 0 )
|
||||
{
|
||||
Abc_ObjRemoveFanins(pNode);
|
||||
|
|
|
|||
|
|
@ -22,9 +22,12 @@
|
|||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define FPGA_CO_LIST_SIZE 5
|
||||
|
||||
static void Fpga_MappingDfs_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes, int fCollectEquiv );
|
||||
static void Fpga_MappingDfsCuts_rec( Fpga_Node_t * pNode, Fpga_NodeVec_t * vNodes );
|
||||
static int Fpga_MappingCompareOutputDelay( int * pOut1, int * pOut2 );
|
||||
static int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 );
|
||||
static void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax );
|
||||
static void Fpga_DfsLim_rec( Fpga_Node_t * pNode, int Level, Fpga_NodeVec_t * vNodes );
|
||||
static int Fpga_CollectNodeTfo_rec( Fpga_Node_t * pNode, Fpga_Node_t * pPivot, Fpga_NodeVec_t * vVisited, Fpga_NodeVec_t * vTfo );
|
||||
static Fpga_Man_t * s_pMan = NULL;
|
||||
|
|
@ -319,6 +322,62 @@ float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan )
|
|||
}
|
||||
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compares the outputs by their arrival times.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Fpga_MappingCompareOutputDelay( Fpga_Node_t ** ppNode1, Fpga_Node_t ** ppNode2 )
|
||||
{
|
||||
Fpga_Node_t * pNode1 = Fpga_Regular(*ppNode1);
|
||||
Fpga_Node_t * pNode2 = Fpga_Regular(*ppNode2);
|
||||
float Arrival1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0;
|
||||
float Arrival2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0;
|
||||
if ( Arrival1 < Arrival2 )
|
||||
return -1;
|
||||
if ( Arrival1 > Arrival2 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds given number of latest arriving COs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Fpga_MappingFindLatest( Fpga_Man_t * p, int * pNodes, int nNodesMax )
|
||||
{
|
||||
int nNodes, i, k, v;
|
||||
assert( p->nOutputs >= nNodesMax );
|
||||
pNodes[0] = 0;
|
||||
nNodes = 1;
|
||||
for ( i = 1; i < p->nOutputs; i++ )
|
||||
{
|
||||
for ( k = nNodes - 1; k >= 0; k-- )
|
||||
if ( Fpga_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 )
|
||||
break;
|
||||
if ( k == nNodesMax - 1 )
|
||||
continue;
|
||||
if ( nNodes < nNodesMax )
|
||||
nNodes++;
|
||||
for ( v = nNodes - 1; v > k+1; v-- )
|
||||
pNodes[v] = pNodes[v-1];
|
||||
pNodes[k+1] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints a bunch of latest arriving outputs.]
|
||||
|
|
@ -333,22 +392,17 @@ float Fpga_MappingSetRefsAndArea( Fpga_Man_t * pMan )
|
|||
void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p )
|
||||
{
|
||||
Fpga_Node_t * pNode;
|
||||
int pSorted[FPGA_CO_LIST_SIZE];
|
||||
int fCompl, Limit, MaxNameSize, i;
|
||||
int * pSorted;
|
||||
|
||||
// sort outputs by arrival time
|
||||
s_pMan = p;
|
||||
pSorted = ALLOC( int, p->nOutputs );
|
||||
for ( i = 0; i < p->nOutputs; i++ )
|
||||
pSorted[i] = i;
|
||||
qsort( (void *)pSorted, p->nOutputs, sizeof(int),
|
||||
(int (*)(const void *, const void *)) Fpga_MappingCompareOutputDelay );
|
||||
assert( Fpga_MappingCompareOutputDelay( pSorted, pSorted + p->nOutputs - 1 ) <= 0 );
|
||||
s_pMan = NULL;
|
||||
// determine the number of nodes to print
|
||||
Limit = (p->nOutputs > FPGA_CO_LIST_SIZE)? FPGA_CO_LIST_SIZE : p->nOutputs;
|
||||
|
||||
// determine the order
|
||||
Fpga_MappingFindLatest( p, pSorted, Limit );
|
||||
|
||||
// determine max size of the node's name
|
||||
MaxNameSize = 0;
|
||||
Limit = (p->nOutputs > 5)? 5 : p->nOutputs;
|
||||
for ( i = 0; i < Limit; i++ )
|
||||
if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) )
|
||||
MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]);
|
||||
|
|
@ -368,32 +422,8 @@ void Fpga_MappingPrintOutputArrivals( Fpga_Man_t * p )
|
|||
printf( "POS" );
|
||||
printf( "\n" );
|
||||
}
|
||||
free( pSorted );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compares the outputs by their arrival times.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Fpga_MappingCompareOutputDelay( int * pOut1, int * pOut2 )
|
||||
{
|
||||
Fpga_Node_t * pNode1 = Fpga_Regular(s_pMan->pOutputs[*pOut1]);
|
||||
Fpga_Node_t * pNode2 = Fpga_Regular(s_pMan->pOutputs[*pOut2]);
|
||||
float pTime1 = pNode1->pCutBest? pNode1->pCutBest->tArrival : 0;
|
||||
float pTime2 = pNode2->pCutBest? pNode2->pCutBest->tArrival : 0;
|
||||
if ( pTime1 > pTime2 )
|
||||
return -1;
|
||||
if ( pTime1 < pTime2 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@
|
|||
/// DECLARATIONS ///
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define MAP_CO_LIST_SIZE 5
|
||||
|
||||
static void Map_MappingDfs_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes, int fCollectEquiv );
|
||||
static int Map_MappingCountLevels_rec( Map_Node_t * pNode );
|
||||
static float Map_MappingSetRefsAndArea_rec( Map_Man_t * pMan, Map_Node_t * pNode );
|
||||
|
|
@ -29,7 +31,8 @@ static float Map_MappingSetRefsAndSwitch_rec( Map_Man_t * pMan, Map_Node_t * pNo
|
|||
static float Map_MappingSetRefsAndWire_rec( Map_Man_t * pMan, Map_Node_t * pNode );
|
||||
static void Map_MappingDfsCuts_rec( Map_Node_t * pNode, Map_NodeVec_t * vNodes );
|
||||
static float Map_MappingArea_rec( Map_Man_t * pMan, Map_Node_t * pNode, Map_NodeVec_t * vNodes );
|
||||
static int Map_MappingCompareOutputDelay( int * pOut1, int * pOut2 );
|
||||
static int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 );
|
||||
static void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax );
|
||||
static unsigned Map_MappingExpandTruth_rec( unsigned uTruth, int nVars );
|
||||
static void Map_MappingGetChoiceLevels( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2, int * pMin, int * pMax );
|
||||
static float Map_MappingGetChoiceVolumes( Map_Man_t * pMan, Map_Node_t * p1, Map_Node_t * p2 );
|
||||
|
|
@ -389,6 +392,64 @@ void Map_MappingMark_rec( Map_Node_t * pNode )
|
|||
Map_MappingMark_rec( Map_Regular(pNode->p2) );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compares the outputs by their arrival times.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Map_MappingCompareOutputDelay( Map_Node_t ** ppNode1, Map_Node_t ** ppNode2 )
|
||||
{
|
||||
Map_Node_t * pNode1 = Map_Regular(*ppNode1);
|
||||
Map_Node_t * pNode2 = Map_Regular(*ppNode2);
|
||||
int fPhase1 = !Map_IsComplement(*ppNode1);
|
||||
int fPhase2 = !Map_IsComplement(*ppNode2);
|
||||
float Arrival1 = pNode1->tArrival[fPhase1].Worst;
|
||||
float Arrival2 = pNode2->tArrival[fPhase2].Worst;
|
||||
if ( Arrival1 < Arrival2 )
|
||||
return -1;
|
||||
if ( Arrival1 > Arrival2 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Finds given number of latest arriving COs.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
void Map_MappingFindLatest( Map_Man_t * p, int * pNodes, int nNodesMax )
|
||||
{
|
||||
int nNodes, i, k, v;
|
||||
assert( p->nOutputs >= nNodesMax );
|
||||
pNodes[0] = 0;
|
||||
nNodes = 1;
|
||||
for ( i = 1; i < p->nOutputs; i++ )
|
||||
{
|
||||
for ( k = nNodes - 1; k >= 0; k-- )
|
||||
if ( Map_MappingCompareOutputDelay( &p->pOutputs[pNodes[k]], &p->pOutputs[i] ) >= 0 )
|
||||
break;
|
||||
if ( k == nNodesMax - 1 )
|
||||
continue;
|
||||
if ( nNodes < nNodesMax )
|
||||
nNodes++;
|
||||
for ( v = nNodes - 1; v > k+1; v-- )
|
||||
pNodes[v] = pNodes[v-1];
|
||||
pNodes[k+1] = i;
|
||||
}
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Prints a bunch of latest arriving outputs.]
|
||||
|
|
@ -402,30 +463,20 @@ void Map_MappingMark_rec( Map_Node_t * pNode )
|
|||
***********************************************************************/
|
||||
void Map_MappingPrintOutputArrivals( Map_Man_t * p )
|
||||
{
|
||||
int pSorted[MAP_CO_LIST_SIZE];
|
||||
Map_Time_t * pTimes;
|
||||
Map_Node_t * pNode;
|
||||
int fPhase, Limit, i;
|
||||
int nOutputs, MaxNameSize;
|
||||
int * pSorted;
|
||||
int MaxNameSize;
|
||||
|
||||
// sort outputs by arrival time
|
||||
s_pMan = p;
|
||||
pSorted = ALLOC( int, p->nOutputs );
|
||||
nOutputs = 0;
|
||||
for ( i = 0; i < p->nOutputs; i++ )
|
||||
{
|
||||
if ( Map_NodeIsConst(p->pOutputs[i]) )
|
||||
continue;
|
||||
pSorted[nOutputs++] = i;
|
||||
}
|
||||
qsort( (void *)pSorted, nOutputs, sizeof(int),
|
||||
(int (*)(const void *, const void *)) Map_MappingCompareOutputDelay );
|
||||
assert( Map_MappingCompareOutputDelay( pSorted, pSorted + nOutputs - 1 ) <= 0 );
|
||||
s_pMan = NULL;
|
||||
// determine the number of nodes to print
|
||||
Limit = (p->nOutputs > MAP_CO_LIST_SIZE)? MAP_CO_LIST_SIZE : p->nOutputs;
|
||||
|
||||
// determine the order
|
||||
Map_MappingFindLatest( p, pSorted, Limit );
|
||||
|
||||
// determine max size of the node's name
|
||||
MaxNameSize = 0;
|
||||
Limit = (nOutputs > 5)? 5 : nOutputs;
|
||||
for ( i = 0; i < Limit; i++ )
|
||||
if ( MaxNameSize < (int)strlen(p->ppOutputNames[pSorted[i]]) )
|
||||
MaxNameSize = strlen(p->ppOutputNames[pSorted[i]]);
|
||||
|
|
@ -443,33 +494,6 @@ void Map_MappingPrintOutputArrivals( Map_Man_t * p )
|
|||
printf( "%s", fPhase? "POS" : "NEG" );
|
||||
printf( "\n" );
|
||||
}
|
||||
free( pSorted );
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
||||
Synopsis [Compares the outputs by their arrival times.]
|
||||
|
||||
Description []
|
||||
|
||||
SideEffects []
|
||||
|
||||
SeeAlso []
|
||||
|
||||
***********************************************************************/
|
||||
int Map_MappingCompareOutputDelay( int * pOut1, int * pOut2 )
|
||||
{
|
||||
Map_Node_t * pNode1 = Map_Regular(s_pMan->pOutputs[*pOut1]);
|
||||
Map_Node_t * pNode2 = Map_Regular(s_pMan->pOutputs[*pOut2]);
|
||||
int fPhase1 = (pNode1 == s_pMan->pOutputs[*pOut1]);
|
||||
int fPhase2 = (pNode2 == s_pMan->pOutputs[*pOut2]);
|
||||
float Arrival1 = pNode1->tArrival[fPhase1].Worst;
|
||||
float Arrival2 = pNode2->tArrival[fPhase2].Worst;
|
||||
if ( Arrival1 > Arrival2 )
|
||||
return -1;
|
||||
if ( Arrival1 < Arrival2 )
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**Function*************************************************************
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ Vec_Int_t * Rwr_CutEvaluate( Rwr_Man_t * p, Abc_Obj_t * pRoot, Rwr_Cut_t * pCut,
|
|||
vFanins->nSize = pCut->nLeaves;
|
||||
vFanins->pArray = pCut->ppLeaves;
|
||||
// detect how many unlabeled nodes will be reused
|
||||
GainCur = Abc_NodeStrashDecCount( pRoot->pNtk->pManFunc, vFanins, (Vec_Int_t *)pNode->pNext,
|
||||
GainCur = Abc_NodeStrashDecCount( pRoot->pNtk->pManFunc, pRoot, vFanins, (Vec_Int_t *)pNode->pNext,
|
||||
p->vLevNums, NodeMax, LevelMax );
|
||||
if ( GainBest < GainCur )
|
||||
{
|
||||
|
|
|
|||
|
|
@ -320,8 +320,8 @@ Ft_Node_t * Ft_FactorTrivialTree_rec( Vec_Int_t * vForm, Ft_Node_t ** ppNodes, i
|
|||
return ppNodes[0];
|
||||
|
||||
// split the nodes into two parts
|
||||
nNodes1 = nNodes/2;
|
||||
nNodes2 = nNodes - nNodes1;
|
||||
nNodes2 = nNodes/2;
|
||||
nNodes1 = nNodes - nNodes2;
|
||||
|
||||
// recursively construct the tree for the parts
|
||||
pNode1 = Ft_FactorTrivialTree_rec( vForm, ppNodes, nNodes1, fAnd );
|
||||
|
|
|
|||
Loading…
Reference in New Issue