Fixed several important problems in choice computation (command 'dch').

This commit is contained in:
Alan Mishchenko 2012-10-01 18:25:41 -07:00
parent 73ab6aac1f
commit 7d29663720
7 changed files with 326 additions and 1669 deletions

View File

@ -3475,10 +3475,6 @@ SOURCE=.\src\aig\gia\giaFront.c
# End Source File
# Begin Source File
SOURCE=.\src\aig\gia\giaGiarf.c
# End Source File
# Begin Source File
SOURCE=.\src\aig\gia\giaGlitch.c
# End Source File
# Begin Source File
@ -3487,10 +3483,6 @@ SOURCE=.\src\aig\gia\giaHash.c
# End Source File
# Begin Source File
SOURCE=.\src\aig\gia\giaHcd.c
# End Source File
# Begin Source File
SOURCE=.\src\aig\gia\giaIf.c
# End Source File
# Begin Source File

View File

@ -703,6 +703,7 @@ extern int Gia_ManCounterExampleValueLookup( Gia_Man_t * pGia, i
/*=== giaChoice.c ============================================================*/
extern void Gia_ManVerifyChoices( Gia_Man_t * p );
extern void Gia_ManReverseClasses( Gia_Man_t * p, int fNowIncreasing );
extern int Gia_ManHasChoices( Gia_Man_t * p );
/*=== giaCsatOld.c ============================================================*/
extern Vec_Int_t * Cbs_ManSolveMiter( Gia_Man_t * pGia, int nConfs, Vec_Str_t ** pvStatus, int fVerbose );
/*=== giaCsat.c ============================================================*/
@ -914,7 +915,6 @@ extern int Gia_ObjIsMuxType( Gia_Obj_t * pNode );
extern int Gia_ObjRecognizeExor( Gia_Obj_t * pObj, Gia_Obj_t ** ppFan0, Gia_Obj_t ** ppFan1 );
extern Gia_Obj_t * Gia_ObjRecognizeMux( Gia_Obj_t * pNode, Gia_Obj_t ** ppNodeT, Gia_Obj_t ** ppNodeE );
extern int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode );
extern int Gia_ManHasChoices( Gia_Man_t * p );
extern int Gia_ManHasDangling( Gia_Man_t * p );
extern int Gia_ManMarkDangling( Gia_Man_t * p );
extern Vec_Int_t * Gia_ManGetDangling( Gia_Man_t * p );

View File

@ -51,28 +51,7 @@ void Gia_ManReverseClasses( Gia_Man_t * p, int fNowIncreasing )
// collect classes
vCollected = Vec_IntAlloc( 100 );
Gia_ManForEachClass( p, iRepr )
{
Vec_IntPush( vCollected, iRepr );
/*
// check classes
if ( !fNowIncreasing )
{
iPrev = iRepr;
Gia_ClassForEachObj1( p, iRepr, iNode )
{
if ( iPrev < iNode )
{
printf( "Class %d : ", iRepr );
Gia_ClassForEachObj( p, iRepr, iNode )
printf( " %d", iNode );
printf( "\n" );
break;
}
iPrev = iNode;
}
}
*/
}
// correct each class
vClass = Vec_IntAlloc( 100 );
Vec_IntForEachEntry( vCollected, iRepr, i )
@ -83,14 +62,12 @@ void Gia_ManReverseClasses( Gia_Man_t * p, int fNowIncreasing )
{
if ( fNowIncreasing )
assert( iRepr < iNode );
// else
// assert( iRepr > iNode );
else
assert( iRepr > iNode );
Vec_IntPush( vClass, iNode );
}
if ( !fNowIncreasing )
Vec_IntSort( vClass, 1 );
// if ( iRepr == 129720 || iRepr == 129737 )
// Vec_IntPrint( vClass );
// if ( !fNowIncreasing )
// Vec_IntSort( vClass, 1 );
// reverse the class
iPrev = 0;
iRepr = Vec_IntEntryLast( vClass );
@ -192,9 +169,10 @@ void Gia_ManCheckReprs( Gia_Man_t * p )
printf( "GIA \"%s\": Representive verification successful.\n", Gia_ManName(p) );
}
/**Function*************************************************************
Synopsis [Find minimum level of each node using representatives.]
Synopsis [Returns 1 if AIG has choices.]
Description []
@ -203,290 +181,84 @@ void Gia_ManCheckReprs( Gia_Man_t * p )
SeeAlso []
***********************************************************************/
int Gia_ManMinLevelRepr_rec( Gia_Man_t * p, Gia_Obj_t * pObj )
{
int levMin, levCur, objId, reprId;
// skip visited nodes
if ( Gia_ObjIsTravIdCurrent(p, pObj) )
return Gia_ObjLevel(p, pObj);
Gia_ObjSetTravIdCurrent(p, pObj);
// skip CI nodes
if ( Gia_ObjIsCi(pObj) )
return Gia_ObjLevel(p, pObj);
assert( Gia_ObjIsAnd(pObj) );
objId = Gia_ObjId(p, pObj);
if ( Gia_ObjIsNone(p, objId) )
{
// not part of the equivalence class
Gia_ManMinLevelRepr_rec( p, Gia_ObjFanin0(pObj) );
Gia_ManMinLevelRepr_rec( p, Gia_ObjFanin1(pObj) );
Gia_ObjSetAndLevel( p, pObj );
return Gia_ObjLevel(p, pObj);
}
// has equivalences defined
assert( Gia_ObjHasRepr(p, objId) || Gia_ObjIsHead(p, objId) );
reprId = Gia_ObjHasRepr(p, objId) ? Gia_ObjRepr(p, objId) : objId;
// iterate through objects
levMin = ABC_INFINITY;
Gia_ClassForEachObj( p, reprId, objId )
{
levCur = Gia_ManMinLevelRepr_rec( p, Gia_ManObj(p, objId) );
levMin = Abc_MinInt( levMin, levCur );
}
assert( levMin < ABC_INFINITY );
// assign minimum level to all
Gia_ClassForEachObj( p, reprId, objId )
Gia_ObjSetLevelId( p, objId, levMin );
return levMin;
}
int Gia_ManMinLevelRepr( Gia_Man_t * p )
int Gia_ManHasChoices( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, LevelCur, LevelMax = 0;
assert( Gia_ManRegNum(p) == 0 );
Gia_ManCleanLevels( p, Gia_ManObjNum(p) );
Gia_ManIncrementTravId( p );
Gia_ManForEachAnd( p, pObj, i )
int i, Counter1 = 0, Counter2 = 0;
int nFailNoRepr = 0;
int nFailHaveRepr = 0;
int nChoiceNodes = 0;
int nChoices = 0;
if ( p->pReprs == NULL || p->pNexts == NULL )
return 0;
// check if there are any representatives
Gia_ManForEachObj( p, pObj, i )
{
assert( !Gia_ObjIsConst(p, i) );
LevelCur = Gia_ManMinLevelRepr_rec( p, pObj );
LevelMax = Abc_MaxInt( LevelMax, LevelCur );
}
printf( "Max level %d\n", LevelMax );
return LevelMax;
}
/**Function*************************************************************
Synopsis [Returns mapping of each old repr into new repr.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int * Gia_ManFindMinLevelMap( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int reprId, objId, levFan0, levFan1;
int levMin, levMinOld, levMax, reprBest;
int * pReprMap, * pMinLevels, iFanin;
int i, fChange = 1;
Gia_ManLevelNum( p );
pMinLevels = ABC_ALLOC( int, Gia_ManObjNum(p) );
while ( fChange )
{
fChange = 0;
// clean min-levels
memset( pMinLevels, 0xFF, sizeof(int) * Gia_ManObjNum(p) );
// for each class find min level
Gia_ManForEachClass( p, reprId )
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
{
levMin = ABC_INFINITY;
Gia_ClassForEachObj( p, reprId, objId )
levMin = Abc_MinInt( levMin, Gia_ObjLevelId(p, objId) );
assert( levMin >= 0 && levMin < ABC_INFINITY );
Gia_ClassForEachObj( p, reprId, objId )
{
assert( pMinLevels[objId] == -1 );
pMinLevels[objId] = levMin;
}
// printf( "%d ", i );
Counter1++;
}
// recompute levels
levMax = 0;
Gia_ManForEachAnd( p, pObj, i )
// if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
// Counter2++;
}
// printf( "\n" );
Gia_ManForEachObj( p, pObj, i )
{
// if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
// Counter1++;
if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
{
iFanin = Gia_ObjFaninId0(pObj, i);
if ( Gia_ObjIsNone(p, iFanin) )
levFan0 = Gia_ObjLevelId(p, iFanin);
else if ( Gia_ObjIsConst(p, iFanin) )
levFan0 = 0;
else
{
assert( Gia_ObjIsClass( p, iFanin ) );
assert( pMinLevels[iFanin] >= 0 );
levFan0 = pMinLevels[iFanin];
}
iFanin = Gia_ObjFaninId1(pObj, i);
if ( Gia_ObjIsNone(p, iFanin) )
levFan1 = Gia_ObjLevelId(p, iFanin);
else if ( Gia_ObjIsConst(p, iFanin) )
levFan1 = 0;
else
{
assert( Gia_ObjIsClass( p, iFanin ) );
assert( pMinLevels[iFanin] >= 0 );
levFan1 = pMinLevels[iFanin];
}
levMinOld = Gia_ObjLevelId(p, i);
levMin = 1 + Abc_MaxInt( levFan0, levFan1 );
Gia_ObjSetLevelId( p, i, levMin );
assert( levMin <= levMinOld );
if ( levMin < levMinOld )
fChange = 1;
levMax = Abc_MaxInt( levMax, levMin );
// printf( "%d ", i );
Counter2++;
}
printf( "%d ", levMax );
}
ABC_FREE( pMinLevels );
printf( "\n" );
// create repr map
pReprMap = ABC_FALLOC( int, Gia_ManObjNum(p) );
Gia_ManForEachAnd( p, pObj, i )
if ( Gia_ObjIsConst(p, i) )
pReprMap[i] = 0;
Gia_ManForEachClass( p, reprId )
// printf( "\n" );
if ( Counter1 == 0 )
{
// find min-level repr
reprBest = -1;
levMin = ABC_INFINITY;
Gia_ClassForEachObj( p, reprId, objId )
if ( levMin > Gia_ObjLevelId(p, objId) )
{
levMin = Gia_ObjLevelId(p, objId);
reprBest = objId;
}
assert( reprBest > 0 );
Gia_ClassForEachObj( p, reprId, objId )
pReprMap[objId] = reprBest;
printf( "Warning: AIG has repr data-strucure but not reprs.\n" );
return 0;
}
return pReprMap;
}
/**Function*************************************************************
Synopsis [Find terminal AND nodes]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Vec_Int_t * Gia_ManDanglingAndNodes( Gia_Man_t * p )
{
Vec_Int_t * vTerms;
Gia_Obj_t * pObj;
int i;
Gia_ManCleanMark0( p );
printf( "%d nodes have reprs.\n", Counter1 );
printf( "%d nodes have nexts.\n", Counter2 );
// check if there are any internal nodes without fanout
// make sure all nodes without fanout have representatives
// make sure all nodes with fanout have no representatives
ABC_FREE( p->pRefs );
Gia_ManCreateRefs( p );
Gia_ManForEachAnd( p, pObj, i )
{
Gia_ObjFanin0(pObj)->fMark0 = 1;
Gia_ObjFanin1(pObj)->fMark1 = 1;
if ( Gia_ObjRefs(p, pObj) == 0 )
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) == NULL )
nFailNoRepr++;
else
nChoices++;
}
else
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) != NULL )
nFailHaveRepr++;
if ( Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ) != NULL )
nChoiceNodes++;
}
if ( Gia_ObjReprObj( p, i ) )
assert( Gia_ObjRepr(p, i) < i );
}
vTerms = Vec_IntAlloc( 1000 );
Gia_ManForEachAnd( p, pObj, i )
if ( !pObj->fMark0 )
Vec_IntPush( vTerms, i );
Gia_ManCleanMark0( p );
return vTerms;
}
/**Function*************************************************************
Synopsis [Reconstruct AIG starting with terminals.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManRebuidRepr_rec( Gia_Man_t * pNew, Gia_Man_t * p, Gia_Obj_t * pObj, int * pReprMap )
{
int objId, reprLit = -1;
if ( ~pObj->Value )
return pObj->Value;
assert( Gia_ObjIsAnd(pObj) );
objId = Gia_ObjId( p, pObj );
if ( Gia_ObjIsClass(p, objId) )
if ( nChoices == 0 )
return 0;
if ( nFailNoRepr )
{
assert( pReprMap[objId] > 0 );
reprLit = Gia_ManRebuidRepr_rec( pNew, p, Gia_ManObj(p, pReprMap[objId]), pReprMap );
assert( reprLit > 1 );
printf( "Gia_ManHasChoices(): Error: %d internal nodes have no fanout and no repr.\n", nFailNoRepr );
// return 0;
}
else
assert( Gia_ObjIsNone(p, objId) );
Gia_ManRebuidRepr_rec( pNew, p, Gia_ObjFanin0(pObj), pReprMap );
Gia_ManRebuidRepr_rec( pNew, p, Gia_ObjFanin1(pObj), pReprMap );
pObj->Value = Gia_ManAppendAnd( pNew, Gia_ObjFanin0Copy(pObj), Gia_ObjFanin1Copy(pObj) );
assert( reprLit != (int)pObj->Value );
if ( reprLit > 1 )
pNew->pReprs[ Abc_Lit2Var(pObj->Value) ].iRepr = Abc_Lit2Var(reprLit);
return pObj->Value;
}
Gia_Man_t * Gia_ManRebuidRepr( Gia_Man_t * p, int * pReprMap )
{
Vec_Int_t * vTerms;
Gia_Man_t * pNew;
Gia_Obj_t * pObj;
int i;
Gia_ManFillValue( p );
pNew = Gia_ManStart( Gia_ManObjNum(p) );
Gia_ManConst0(p)->Value = 0;
Gia_ManForEachCi( p, pObj, i )
pObj->Value = Gia_ManAppendCi(pNew);
vTerms = Gia_ManDanglingAndNodes( p );
Gia_ManForEachObjVec( vTerms, p, pObj, i )
Gia_ManRebuidRepr_rec( pNew, p, pObj, pReprMap );
Vec_IntFree( vTerms );
Gia_ManForEachCo( p, pObj, i )
pObj->Value = Gia_ManAppendCo( pNew, Gia_ObjFanin0Copy(pObj) );
Gia_ManSetRegNum( pNew, Gia_ManRegNum(p) );
return pNew;
}
/**Function*************************************************************
Synopsis []
Description []
SideEffects []
SeeAlso []
***********************************************************************/
Aig_Man_t * Gia_ManNormalizeChoices( Aig_Man_t * pAig )
{
int * pReprMap;
Aig_Man_t * pNew;
Gia_Man_t * pGia, * pTemp;
// create GIA with representatives
assert( Aig_ManRegNum(pAig) == 0 );
assert( pAig->pReprs != NULL );
pGia = Gia_ManFromAigSimple( pAig );
Gia_ManReprFromAigRepr2( pAig, pGia );
// verify that representatives are correct
Gia_ManCheckReprs( pGia );
// find min-level repr for each class
pReprMap = Gia_ManFindMinLevelMap( pGia );
// reconstruct using correct order
pGia = Gia_ManRebuidRepr( pTemp = pGia, pReprMap );
Gia_ManStop( pTemp );
ABC_FREE( pReprMap );
// create choices
// verify that choices are correct
// Gia_ManVerifyChoices( pGia );
// copy the result back into AIG
pNew = Gia_ManToAigSimple( pGia );
Gia_ManReprToAigRepr( pNew, pGia );
return pNew;
}
void Gia_ManNormalizeChoicesTest( Aig_Man_t * pAig )
{
Aig_Man_t * pNew = Gia_ManNormalizeChoices( pAig );
Aig_ManStop( pNew );
if ( nFailHaveRepr )
{
printf( "Gia_ManHasChoices(): Error: %d internal nodes have both fanout and repr.\n", nFailHaveRepr );
// return 0;
}
// printf( "Gia_ManHasChoices(): AIG has %d choice nodes with %d choices.\n", nChoiceNodes, nChoices );
return 1;
}
////////////////////////////////////////////////////////////////////////

View File

@ -888,97 +888,6 @@ int Gia_NodeMffcSize( Gia_Man_t * p, Gia_Obj_t * pNode )
return ConeSize1;
}
/**Function*************************************************************
Synopsis [Returns 1 if AIG has choices.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Gia_ManHasChoices( Gia_Man_t * p )
{
Gia_Obj_t * pObj;
int i, Counter1 = 0, Counter2 = 0;
int nFailNoRepr = 0;
int nFailHaveRepr = 0;
int nChoiceNodes = 0;
int nChoices = 0;
if ( p->pReprs == NULL || p->pNexts == NULL )
return 0;
// check if there are any representatives
Gia_ManForEachObj( p, pObj, i )
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
{
// printf( "%d ", i );
Counter1++;
}
// if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
// Counter2++;
}
// printf( "\n" );
Gia_ManForEachObj( p, pObj, i )
{
// if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) )
// Counter1++;
if ( Gia_ObjNext( p, Gia_ObjId(p, pObj) ) )
{
// printf( "%d ", i );
Counter2++;
}
}
// printf( "\n" );
if ( Counter1 == 0 )
{
printf( "Warning: AIG has repr data-strucure but not reprs.\n" );
return 0;
}
printf( "%d nodes have reprs.\n", Counter1 );
printf( "%d nodes have nexts.\n", Counter2 );
// check if there are any internal nodes without fanout
// make sure all nodes without fanout have representatives
// make sure all nodes with fanout have no representatives
ABC_FREE( p->pRefs );
Gia_ManCreateRefs( p );
Gia_ManForEachAnd( p, pObj, i )
{
if ( Gia_ObjRefs(p, pObj) == 0 )
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) == NULL )
nFailNoRepr++;
else
nChoices++;
}
else
{
if ( Gia_ObjReprObj( p, Gia_ObjId(p, pObj) ) != NULL )
nFailHaveRepr++;
if ( Gia_ObjNextObj( p, Gia_ObjId(p, pObj) ) != NULL )
nChoiceNodes++;
}
if ( Gia_ObjReprObj( p, i ) )
assert( Gia_ObjRepr(p, i) < i );
}
if ( nChoices == 0 )
return 0;
if ( nFailNoRepr )
{
printf( "Gia_ManHasChoices(): Error: %d internal nodes have no fanout and no repr.\n", nFailNoRepr );
// return 0;
}
if ( nFailHaveRepr )
{
printf( "Gia_ManHasChoices(): Error: %d internal nodes have both fanout and repr.\n", nFailHaveRepr );
// return 0;
}
// printf( "Gia_ManHasChoices(): AIG has %d choice nodes with %d choices.\n", nChoiceNodes, nChoices );
return 1;
}
/**Function*************************************************************
Synopsis [Returns 1 if AIG has dangling nodes.]

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,36 @@ ABC_NAMESPACE_IMPL_START
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Counts support nodes.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Dch_ObjCountSupp_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
{
int Count;
if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
return 0;
Aig_ObjSetTravIdCurrent( p, pObj );
if ( Aig_ObjIsCi(pObj) )
return 1;
assert( Aig_ObjIsNode(pObj) );
Count = Dch_ObjCountSupp_rec( p, Aig_ObjFanin0(pObj) );
Count += Dch_ObjCountSupp_rec( p, Aig_ObjFanin1(pObj) );
return Count;
}
int Dch_ObjCountSupp( Aig_Man_t * p, Aig_Obj_t * pObj )
{
Aig_ManIncrementTravId( p );
return Dch_ObjCountSupp_rec( p, pObj );
}
/**Function*************************************************************
Synopsis [Counts the number of representatives.]
@ -56,54 +86,72 @@ int Dch_DeriveChoiceCountReprs( Aig_Man_t * pAig )
}
return nReprs;
}
/**Function*************************************************************
Synopsis [Counts the number of equivalences.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
{
Aig_Obj_t * pObj, * pTemp, * pPrev;
int i, nEquivs = 0, Counter = 0;
Aig_Obj_t * pObj, * pEquiv;
int i, nEquivs = 0;
Aig_ManForEachObj( pAig, pObj, i )
{
if ( !Aig_ObjIsChoice(pAig, pObj) )
pEquiv = Aig_ObjEquiv( pAig, pObj );
if ( pEquiv == NULL )
continue;
for ( pPrev = pObj, pTemp = Aig_ObjEquiv(pAig, pObj); pTemp;
pPrev = pTemp, pTemp = Aig_ObjEquiv(pAig, pTemp) )
{
if ( pTemp->nRefs > 0 )
{
// remove referenced node from equivalence class
assert( pAig->pEquivs[pPrev->Id] == pTemp );
pAig->pEquivs[pPrev->Id] = pAig->pEquivs[pTemp->Id];
pAig->pEquivs[pTemp->Id] = NULL;
// how about the need to continue iterating over the list?
// pPrev = pTemp ???
Counter++;
}
nEquivs++;
}
assert( pEquiv->Id > pObj->Id );
nEquivs++;
}
// printf( "Removed %d classes.\n", Counter );
if ( Counter )
Dch_DeriveChoiceCountEquivs( pAig );
// if ( Counter )
// printf( "Removed %d equiv nodes because of non-zero ref counter.\n", Counter );
return nEquivs;
}
/**Function*************************************************************
Synopsis [Returns representatives of fanin in approapriate polarity.]
Synopsis [Marks the TFI of the node.]
Description [Returns 1 if there is a CI not marked with previous ID.]
SideEffects []
SeeAlso []
***********************************************************************/
int Dch_ObjMarkTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
{
int RetValue;
if ( pObj == NULL )
return 0;
if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
return 0;
if ( Aig_ObjIsCi(pObj) )
{
RetValue = !Aig_ObjIsTravIdPrevious( p, pObj );
Aig_ObjSetTravIdCurrent( p, pObj );
return RetValue;
}
assert( Aig_ObjIsNode(pObj) );
Aig_ObjSetTravIdCurrent( p, pObj );
RetValue = Dch_ObjMarkTfi_rec( p, Aig_ObjFanin0(pObj) );
RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjFanin1(pObj) );
// RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjEquiv(p, pObj) );
return (RetValue > 0);
}
int Dch_ObjCheckSuppRed( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
{
// mark support of the representative node (pRepr)
Aig_ManIncrementTravId( p );
Dch_ObjMarkTfi_rec( p, pRepr );
// detect if the new node (pObj) depends on additional variables
Aig_ManIncrementTravId( p );
if ( Dch_ObjMarkTfi_rec( p, pObj ) )
return 1;//, printf( "1" );
// detect if the representative node (pRepr) depends on additional variables
Aig_ManIncrementTravId( p );
if ( Dch_ObjMarkTfi_rec( p, pRepr ) )
return 1;//, printf( "2" );
// skip the choice if this is what is happening
return 0;
}
/**Function*************************************************************
Synopsis [Make sure reprsentative nodes do not have representatives.]
Description []
@ -112,19 +160,88 @@ int Dch_DeriveChoiceCountEquivs( Aig_Man_t * pAig )
SeeAlso []
***********************************************************************/
static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
void Aig_ManCheckReprs( Aig_Man_t * p )
{
Aig_Obj_t * pRepr;
if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) )
return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) );
return pObj;
int fPrintConst = 0;
Aig_Obj_t * pObj;
int i, fProb = 0;
int Class0 = 0, ClassCi = 0;
Aig_ManForEachObj( p, pObj, i )
{
if ( Aig_ObjRepr(p, pObj) == NULL )
continue;
if ( !Aig_ObjIsNode(pObj) )
printf( "Obj %d is not an AND but it has a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)) ), fProb = 1;
else if ( Aig_ObjRepr(p, Aig_ObjRepr(p, pObj)) )
printf( "Obj %d has repr %d with a repr %d.\n", i, Aig_ObjId(Aig_ObjRepr(p, pObj)), Aig_ObjId(Aig_ObjRepr(p, Aig_ObjRepr(p, pObj))) ), fProb = 1;
}
if ( !fProb )
printf( "Representive verification successful.\n" );
else
printf( "Representive verification FAILED.\n" );
if ( !fPrintConst )
return;
// count how many representatives are const0 or a CI
Aig_ManForEachObj( p, pObj, i )
{
if ( Aig_ObjRepr(p, pObj) == Aig_ManConst1(p) )
Class0++;
if ( Aig_ObjRepr(p, pObj) && Aig_ObjIsCi(Aig_ObjRepr(p, pObj)) )
ClassCi++;
}
printf( "Const0 nodes = %d. ConstCI nodes = %d.\n", Class0, ClassCi );
}
static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); }
static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); }
/**Function*************************************************************
Synopsis [Verify correctness of choices.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Dch_CheckChoices( Aig_Man_t * p, int fSkipRedSupps )
{
Aig_Obj_t * pObj;
int i, fProb = 0;
Aig_ManCleanMarkA( p );
Aig_ManForEachNode( p, pObj, i )
{
if ( p->pEquivs[i] != NULL )
{
if ( pObj->fMarkA == 1 )
printf( "node %d participates in more than one choice class\n", i ), fProb = 1;
pObj->fMarkA = 1;
// check redundancy
if ( fSkipRedSupps && Dch_ObjCheckSuppRed( p, pObj, p->pEquivs[i]) )
printf( "node %d and repr %d have diff supports\n", pObj->Id, p->pEquivs[i]->Id );
// consider the next one
pObj = p->pEquivs[i];
if ( p->pEquivs[Aig_ObjId(pObj)] == NULL )
{
if ( pObj->fMarkA == 1 )
printf( "repr %d has final node %d participates in more than one choice class\n", i, pObj->Id ), fProb = 1;
pObj->fMarkA = 1;
}
// consider the non-head ones
if ( pObj->nRefs > 0 )
printf( "node %d belonging to choice has fanout %d\n", pObj->Id, pObj->nRefs );
}
if ( p->pReprs && p->pReprs[i] != NULL )
{
if ( pObj->nRefs > 0 )
printf( "node %d has representative %d and fanout count %d\n", pObj->Id, p->pReprs[i]->Id, pObj->nRefs ), fProb = 1;
}
}
Aig_ManCleanMarkA( p );
if ( !fProb )
printf( "Verification of choice AIG succeeded.\n" );
else
printf( "Verification of choice AIG FAILED.\n" );
}
/**Function*************************************************************
@ -240,104 +357,6 @@ int Aig_ManCheckAcyclic( Aig_Man_t * p, int fVerbose )
return fAcyclic;
}
/**Function*************************************************************
Synopsis [Removes combinational loop.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Aig_ManFixLoopProblem( Aig_Man_t * p, int fVerbose )
{
Aig_Obj_t * pObj;
int i, Counter = 0, Counter2 = 0;
Aig_ManForEachObj( p, pObj, i )
{
if ( !Aig_ObjIsTravIdCurrent(p, pObj) )
continue;
Counter2++;
if ( Aig_ObjRepr(p, pObj) == NULL && Aig_ObjEquiv(p, pObj) != NULL )
{
Aig_ObjSetEquiv(p, pObj, NULL);
Counter++;
}
}
if ( fVerbose )
Abc_Print( 1, "Fixed %d choice nodes on the path with %d objects.\n", Counter, Counter2 );
}
/**Function*************************************************************
Synopsis [Verify correctness of choices.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
void Dch_CheckChoices( Aig_Man_t * p )
{
Aig_Obj_t * pObj;
int i, fProb = 0;
Aig_ManCleanMarkA( p );
Aig_ManForEachNode( p, pObj, i )
if ( p->pEquivs[i] != NULL )
{
if ( pObj->fMarkA == 1 )
printf( "node %d participates in more than one choice class\n", i ), fProb = 1;
pObj->fMarkA = 1;
// consider the last one
pObj = p->pEquivs[i];
if ( p->pEquivs[Aig_ObjId(pObj)] == NULL )
{
if ( pObj->fMarkA == 1 )
printf( "repr %d has final node %d participates in more than one choice class\n", i, pObj->Id ), fProb = 1;
pObj->fMarkA = 1;
}
}
Aig_ManCleanMarkA( p );
if ( !fProb )
printf( "Verification of choice AIG succeeded.\n" );
}
/**Function*************************************************************
Synopsis [Marks the TFI of the node.]
Description [Returns 1 if there is a CI not marked with previous ID.]
SideEffects []
SeeAlso []
***********************************************************************/
int Dch_ObjMarkTfi_rec( Aig_Man_t * p, Aig_Obj_t * pObj )
{
int RetValue;
if ( pObj == NULL )
return 0;
if ( Aig_ObjIsTravIdCurrent( p, pObj ) )
return 0;
if ( Aig_ObjIsCi(pObj) )
{
RetValue = !Aig_ObjIsTravIdPrevious( p, pObj );
Aig_ObjSetTravIdCurrent( p, pObj );
return RetValue;
}
assert( Aig_ObjIsNode(pObj) );
Aig_ObjSetTravIdCurrent( p, pObj );
RetValue = Dch_ObjMarkTfi_rec( p, Aig_ObjFanin0(pObj) );
RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjFanin1(pObj) );
// RetValue += Dch_ObjMarkTfi_rec( p, Aig_ObjEquiv(p, pObj) );
return (RetValue > 0);
}
/**Function*************************************************************
@ -391,7 +410,7 @@ int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
/**Function*************************************************************
Synopsis [Derives the AIG with choices from representatives.]
Synopsis [Returns representatives of fanin in approapriate polarity.]
Description []
@ -400,91 +419,15 @@ int Dch_ObjCheckTfi( Aig_Man_t * p, Aig_Obj_t * pObj, Aig_Obj_t * pRepr )
SeeAlso []
***********************************************************************/
void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps )
static inline Aig_Obj_t * Aig_ObjGetRepr( Aig_Man_t * p, Aig_Obj_t * pObj )
{
Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
// get the new node
assert( pObj->pData == NULL );
pObj->pData = Aig_And( pAigNew,
Aig_ObjChild0CopyRepr(pAigNew, pObj),
Aig_ObjChild1CopyRepr(pAigNew, pObj) );
pRepr = Aig_ObjRepr( pAigOld, pObj );
if ( pRepr == NULL )
return;
assert( pRepr->Id < pObj->Id );
// get the corresponding new nodes
pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
if ( pObjNew == pReprNew )
return;
// skip the earlier nodes
if ( pReprNew->Id > pObjNew->Id )
return;
assert( pReprNew->Id < pObjNew->Id );
// set the representatives
Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
// skip used nodes
if ( pObjNew->nRefs > 0 )
return;
assert( pObjNew->nRefs == 0 );
// update new nodes of the object
if ( !Aig_ObjIsNode(pRepr) )
return;
// skip choices with combinational loops
if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
return;
// don't add choice if structural support of pObjNew and pReprNew differ
if ( fSkipRedSupps )
{
int fSkipChoice = 0;
// mark support of the representative node (pReprNew)
Aig_ManIncrementTravId( pAigNew );
Dch_ObjMarkTfi_rec( pAigNew, pReprNew );
// detect if the new node (pObjNew) depends on any additional variables
Aig_ManIncrementTravId( pAigNew );
if ( Dch_ObjMarkTfi_rec( pAigNew, pObjNew ) )
fSkipChoice = 1;//, printf( "1" );
// detect if the representative node (pReprNew) depends on any additional variables
Aig_ManIncrementTravId( pAigNew );
if ( Dch_ObjMarkTfi_rec( pAigNew, pReprNew ) )
fSkipChoice = 1;//, printf( "2" );
// skip the choice if this is what is happening
if ( fSkipChoice )
return;
}
// add choice
pAigNew->pEquivs[pObjNew->Id] = pAigNew->pEquivs[pReprNew->Id];
pAigNew->pEquivs[pReprNew->Id] = pObjNew;
}
Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
{
Aig_Man_t * pChoices;
Aig_Obj_t * pObj;
int i;
// make sure reprsentative nodes do not have representatives
Aig_ManForEachNode( pAig, pObj, i )
if ( pAig->pReprs[i] != NULL && pAig->pReprs[pAig->pReprs[i]->Id] != NULL )
printf( "Node %d: repr %d has repr %d.\n", i, Aig_ObjId(pAig->pReprs[i]), Aig_ObjId(pAig->pReprs[pAig->pReprs[i]->Id]) );
// start recording equivalences
pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
// map constants and PIs
Aig_ManCleanData( pAig );
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
Aig_ManForEachCi( pAig, pObj, i )
pObj->pData = Aig_ObjCreateCi( pChoices );
// construct choices for the internal nodes
assert( pAig->pReprs != NULL );
Aig_ManForEachNode( pAig, pObj, i )
Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps );
Aig_ManForEachCo( pAig, pObj, i )
Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
Dch_DeriveChoiceCountEquivs( pChoices );
Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
//Dch_CheckChoices( pChoices );
return pChoices;
Aig_Obj_t * pRepr;
if ( (pRepr = Aig_ObjRepr(p, Aig_Regular(pObj))) )
return Aig_NotCond( pRepr, Aig_Regular(pObj)->fPhase ^ pRepr->fPhase ^ Aig_IsComplement(pObj) );
return pObj;
}
static inline Aig_Obj_t * Aig_ObjChild0CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild0Copy(pObj) ); }
static inline Aig_Obj_t * Aig_ObjChild1CopyRepr( Aig_Man_t * p, Aig_Obj_t * pObj ) { return Aig_ObjGetRepr( p, Aig_ObjChild1Copy(pObj) ); }
/**Function*************************************************************
@ -497,24 +440,99 @@ Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
SeeAlso []
***********************************************************************/
void Dch_DeriveChoiceAigNode( Aig_Man_t * pAigNew, Aig_Man_t * pAigOld, Aig_Obj_t * pObj, int fSkipRedSupps )
{
Aig_Obj_t * pRepr, * pObjNew, * pReprNew;
assert( !Aig_IsComplement(pObj) );
// get the representative
pRepr = Aig_ObjRepr( pAigOld, pObj );
if ( pRepr != NULL && (Aig_ObjIsConst1(pRepr) || Aig_ObjIsCi(pRepr)) )
{
assert( pRepr->pData != NULL );
pObj->pData = Aig_NotCond( (Aig_Obj_t *)pRepr->pData, pObj->fPhase ^ pRepr->fPhase );
return;
}
// get the new node
pObjNew = Aig_And( pAigNew,
Aig_ObjChild0CopyRepr(pAigNew, pObj),
Aig_ObjChild1CopyRepr(pAigNew, pObj) );
pObjNew = Aig_ObjGetRepr( pAigNew, pObjNew );
assert( Aig_ObjRepr( pAigNew, pObjNew ) == NULL );
// assign the copy
assert( pObj->pData == NULL );
pObj->pData = pObjNew;
// skip those without reprs
if ( pRepr == NULL )
return;
assert( pRepr->Id < pObj->Id );
assert( Aig_ObjIsNode(pRepr) );
// get the corresponding new nodes
pObjNew = Aig_Regular((Aig_Obj_t *)pObj->pData);
pReprNew = Aig_Regular((Aig_Obj_t *)pRepr->pData);
// skip earlier nodes
if ( pReprNew->Id >= pObjNew->Id )
return;
assert( pReprNew->Id < pObjNew->Id );
// set the representatives
Aig_ObjSetRepr( pAigNew, pObjNew, pReprNew );
// skip used nodes
if ( pObjNew->nRefs > 0 )
return;
assert( pObjNew->nRefs == 0 );
// skip choices that can lead to combo loops
if ( Dch_ObjCheckTfi( pAigNew, pObjNew, pReprNew ) )
return;
// don't add choice if structural support of pObjNew and pReprNew differ
if ( fSkipRedSupps && Dch_ObjCheckSuppRed(pAigNew, pObjNew, pReprNew) )
return;
// add choice to the end of the list
while ( pAigNew->pEquivs[pReprNew->Id] != NULL )
pReprNew = pAigNew->pEquivs[pReprNew->Id];
assert( pAigNew->pEquivs[pReprNew->Id] == NULL );
pAigNew->pEquivs[pReprNew->Id] = pObjNew;
}
Aig_Man_t * Dch_DeriveChoiceAigInt( Aig_Man_t * pAig, int fSkipRedSupps )
{
Aig_Man_t * pChoices;
Aig_Obj_t * pObj;
int i;
// start recording equivalences
pChoices = Aig_ManStart( Aig_ManObjNumMax(pAig) );
pChoices->pEquivs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
pChoices->pReprs = ABC_CALLOC( Aig_Obj_t *, Aig_ManObjNumMax(pAig) );
// map constants and PIs
Aig_ManCleanData( pAig );
Aig_ManConst1(pAig)->pData = Aig_ManConst1(pChoices);
Aig_ManForEachCi( pAig, pObj, i )
pObj->pData = Aig_ObjCreateCi( pChoices );
// construct choices for the internal nodes
assert( pAig->pReprs != NULL );
Aig_ManForEachNode( pAig, pObj, i )
Dch_DeriveChoiceAigNode( pChoices, pAig, pObj, fSkipRedSupps );
Aig_ManForEachCo( pAig, pObj, i )
Aig_ObjCreateCo( pChoices, Aig_ObjChild0CopyRepr(pChoices, pObj) );
Aig_ManSetRegNum( pChoices, Aig_ManRegNum(pAig) );
return pChoices;
}
Aig_Man_t * Dch_DeriveChoiceAig( Aig_Man_t * pAig, int fSkipRedSupps )
{
extern int Aig_ManCheckAcyclic( Aig_Man_t * pAig, int fVerbose );
int fCheck = 0;
Aig_Man_t * pChoices, * pTemp;
int fVerbose = 0;
// verify
if ( fCheck )
Aig_ManCheckReprs( pAig );
// compute choices
pChoices = Dch_DeriveChoiceAigInt( pAig, fSkipRedSupps );
// pChoices = Dch_DeriveChoiceAigInt( pTemp = pChoices );
// Aig_ManStop( pTemp );
// there is no need for cleanup
ABC_FREE( pChoices->pReprs );
while ( !Aig_ManCheckAcyclic( pChoices, fVerbose ) )
{
if ( fVerbose )
Abc_Print( 1, "There is a loop!\n" );
Aig_ManFixLoopProblem( pChoices, fVerbose );
}
// verify
if ( fCheck )
Dch_CheckChoices( pChoices, fSkipRedSupps );
// find correct topo order with choices
pChoices = Aig_ManDupDfs( pTemp = pChoices );
Aig_ManStop( pTemp );
// verify
if ( fCheck )
Dch_CheckChoices( pChoices, fSkipRedSupps );
return pChoices;
}

View File

@ -106,19 +106,13 @@ p->timeSimInit = clock() - clk;
// free memory ahead of time
p->timeTotal = clock() - clkTotal;
Dch_ManStop( p );
// try something different
{
// extern void Gia_ManNormalizeChoicesTest( Aig_Man_t * pAig );
// Gia_ManNormalizeChoicesTest( pAig );
}
// create choices
ABC_FREE( pAig->pTable );
pResult = Dch_DeriveChoiceAig( pAig, pPars->fSkipRedSupp );
// count the number of representatives
if ( pPars->fVerbose )
Abc_Print( 1, "STATS: Reprs = %6d. Equivs = %6d. Choices = %6d.\n",
Dch_DeriveChoiceCountReprs( pAig ),
Dch_DeriveChoiceCountReprs( pResult ),
Dch_DeriveChoiceCountEquivs( pResult ),
Aig_ManChoiceNum( pResult ) );
return pResult;