blob: 3e978bf020fcf965f0741f0c1ed3acfc89bae2f5 [file] [log] [blame]
/**CFile****************************************************************
FileName [abcCheck.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Consistency checking procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "abc.h"
#include "base/main/main.h"
#ifdef ABC_USE_CUDD
#include "bdd/extrab/extraBdd.h"
#endif
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Abc_NtkCheckNames( Abc_Ntk_t * pNtk );
static int Abc_NtkCheckPis( Abc_Ntk_t * pNtk );
static int Abc_NtkCheckPos( Abc_Ntk_t * pNtk );
//static int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj );
static int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet );
static int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode );
static int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch );
static int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
static int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
static int Abc_NtkCompareLatches( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb );
static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); }
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Checks the integrity of the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheck( Abc_Ntk_t * pNtk )
{
return !Abc_FrameIsFlagEnabled( "check" ) || Abc_NtkDoCheck( pNtk );
}
/**Function*************************************************************
Synopsis [Checks the integrity of the network after reading.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckRead( Abc_Ntk_t * pNtk )
{
return !Abc_FrameIsFlagEnabled( "checkread" ) || Abc_NtkDoCheck( pNtk );
}
/**Function*************************************************************
Synopsis [Checks the integrity of the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkDoCheck( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj, * pNet, * pNode;
int i;
// check network types
if ( !Abc_NtkIsNetlist(pNtk) && !Abc_NtkIsLogic(pNtk) && !Abc_NtkIsStrash(pNtk) )
{
fprintf( stdout, "NetworkCheck: Unknown network type.\n" );
return 0;
}
if ( !Abc_NtkHasSop(pNtk) && !Abc_NtkHasBdd(pNtk) && !Abc_NtkHasAig(pNtk) && !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasBlackbox(pNtk) )
{
fprintf( stdout, "NetworkCheck: Unknown functionality type.\n" );
return 0;
}
if ( Abc_NtkHasMapping(pNtk) )
{
if ( pNtk->pManFunc != Abc_FrameReadLibGen() )
{
fprintf( stdout, "NetworkCheck: The library of the mapped network is not the global library.\n" );
return 0;
}
}
if ( Abc_NtkHasOnlyLatchBoxes(pNtk) )
{
// check CI/CO numbers
if ( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCiNum(pNtk) )
{
fprintf( stdout, "NetworkCheck: Number of CIs does not match number of PIs and latches.\n" );
fprintf( stdout, "One possible reason is that latches are added twice:\n" );
fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" );
return 0;
}
if ( Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) != Abc_NtkCoNum(pNtk) )
{
fprintf( stdout, "NetworkCheck: Number of COs does not match number of POs, asserts, and latches.\n" );
fprintf( stdout, "One possible reason is that latches are added twice:\n" );
fprintf( stdout, "in procedure Abc_NtkCreateObj() and in the user's code.\n" );
return 0;
}
}
// check the names
if ( !Abc_NtkCheckNames( pNtk ) )
return 0;
// check PIs and POs
Abc_NtkCleanCopy( pNtk );
if ( !Abc_NtkCheckPis( pNtk ) )
return 0;
if ( !Abc_NtkCheckPos( pNtk ) )
return 0;
if ( Abc_NtkHasBlackbox(pNtk) )
return 1;
// check the connectivity of objects
Abc_NtkForEachObj( pNtk, pObj, i )
if ( !Abc_NtkCheckObj( pNtk, pObj ) )
return 0;
// if it is a netlist change nets and latches
if ( Abc_NtkIsNetlist(pNtk) )
{
if ( Abc_NtkNetNum(pNtk) == 0 )
fprintf( stdout, "NetworkCheck: Warning! Netlist has no nets.\n" );
// check the nets
Abc_NtkForEachNet( pNtk, pNet, i )
if ( !Abc_NtkCheckNet( pNtk, pNet ) )
return 0;
}
else
{
if ( Abc_NtkNetNum(pNtk) != 0 )
{
fprintf( stdout, "NetworkCheck: A network that is not a netlist has nets.\n" );
return 0;
}
}
// check the nodes
if ( Abc_NtkIsStrash(pNtk) )
Abc_AigCheck( (Abc_Aig_t *)pNtk->pManFunc );
else
{
Abc_NtkForEachNode( pNtk, pNode, i )
if ( !Abc_NtkCheckNode( pNtk, pNode ) )
return 0;
}
// check the latches
Abc_NtkForEachLatch( pNtk, pNode, i )
if ( !Abc_NtkCheckLatch( pNtk, pNode ) )
return 0;
// finally, check for combinational loops
// clk = Abc_Clock();
if ( !Abc_NtkIsAcyclic( pNtk ) )
{
fprintf( stdout, "NetworkCheck: Network contains a combinational loop.\n" );
return 0;
}
// ABC_PRT( "Acyclic ", Abc_Clock() - clk );
// check the EXDC network if present
if ( pNtk->pExdc )
Abc_NtkCheck( pNtk->pExdc );
/*
// check the hierarchy
if ( Abc_NtkIsNetlist(pNtk) && pNtk->tName2Model )
{
stmm_generator * gen;
Abc_Ntk_t * pNtkTemp;
char * pName;
// check other networks
stmm_foreach_item( pNtk->tName2Model, gen, &pName, (char **)&pNtkTemp )
{
pNtkTemp->fHiePath = pNtkTemp->fHieVisited = 0;
if ( !Abc_NtkCheck( pNtkTemp ) )
return 0;
}
// check acyclic dependency of the models
if ( !Abc_NtkIsAcyclicHierarchy( pNtk ) )
{
fprintf( stdout, "NetworkCheck: Network hierarchical dependences contains a cycle.\n" );
return 0;
}
}
*/
return 1;
}
/**Function*************************************************************
Synopsis [Checks the names.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckNames( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj = NULL; // Ensure pObj isn't used uninitialized.
Vec_Int_t * vNameIds;
char * pName;
int i, NameId;
if ( Abc_NtkIsNetlist(pNtk) )
return 1;
// check that each CI/CO has a name
Abc_NtkForEachCi( pNtk, pObj, i )
{
pObj = Abc_ObjFanout0Ntk(pObj);
if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL )
{
fprintf( stdout, "NetworkCheck: CI with ID %d is in the network but not in the name table.\n", pObj->Id );
return 0;
}
}
Abc_NtkForEachCo( pNtk, pObj, i )
{
pObj = Abc_ObjFanin0Ntk(pObj);
if ( Nm_ManFindNameById(pObj->pNtk->pManName, pObj->Id) == NULL )
{
fprintf( stdout, "NetworkCheck: CO with ID %d is in the network but not in the name table.\n", pObj->Id );
return 0;
}
}
assert(pObj); // pObj should point to something here.
// return the array of all IDs, which have names
vNameIds = Nm_ManReturnNameIds( pNtk->pManName );
// make sure that these IDs correspond to live objects
Vec_IntForEachEntry( vNameIds, NameId, i )
{
if ( Vec_PtrEntry( pNtk->vObjs, NameId ) == NULL )
{
Vec_IntFree( vNameIds );
pName = Nm_ManFindNameById(pObj->pNtk->pManName, NameId);
fprintf( stdout, "NetworkCheck: Object with ID %d is deleted but its name \"%s\" remains in the name table.\n", NameId, pName );
return 0;
}
}
Vec_IntFree( vNameIds );
// make sure the CI names are unique
if ( !Abc_NtkCheckUniqueCiNames(pNtk) )
return 0;
// make sure the CO names are unique
if ( !Abc_NtkCheckUniqueCoNames(pNtk) )
return 0;
// make sure that if a CO has the same name as a CI, they point directly
if ( !Abc_NtkCheckUniqueCioNames(pNtk) )
return 0;
return 1;
}
/**Function*************************************************************
Synopsis [Checks the PIs of the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckPis( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
int i;
// check that PIs are indeed PIs
Abc_NtkForEachPi( pNtk, pObj, i )
{
if ( !Abc_ObjIsPi(pObj) )
{
fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is in the PI list but is not a PI.\n", Abc_ObjName(pObj), pObj->Id );
return 0;
}
if ( pObj->pData )
{
fprintf( stdout, "NetworkCheck: A PI \"%s\" has a logic function.\n", Abc_ObjName(pObj) );
return 0;
}
if ( Abc_ObjFaninNum(pObj) > 0 )
{
fprintf( stdout, "NetworkCheck: A PI \"%s\" has fanins.\n", Abc_ObjName(pObj) );
return 0;
}
pObj->pCopy = (Abc_Obj_t *)1;
}
Abc_NtkForEachObj( pNtk, pObj, i )
{
if ( pObj->pCopy == NULL && Abc_ObjIsPi(pObj) )
{
fprintf( stdout, "NetworkCheck: Object \"%s\" (id=%d) is a PI but is not in the PI list.\n", Abc_ObjName(pObj), pObj->Id );
return 0;
}
pObj->pCopy = NULL;
}
return 1;
}
/**Function*************************************************************
Synopsis [Checks the POs of the network.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckPos( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj;
int i;
// check that POs are indeed POs
Abc_NtkForEachPo( pNtk, pObj, i )
{
if ( !Abc_ObjIsPo(pObj) )
{
fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in the PO list but is not a PO.\n", Abc_ObjName(pObj), pObj->Id );
return 0;
}
if ( pObj->pData )
{
fprintf( stdout, "NetworkCheck: A PO \"%s\" has a logic function.\n", Abc_ObjName(pObj) );
return 0;
}
if ( Abc_ObjFaninNum(pObj) != 1 )
{
fprintf( stdout, "NetworkCheck: A PO \"%s\" does not have one fanin (but %d).\n", Abc_ObjName(pObj), Abc_ObjFaninNum(pObj) );
return 0;
}
if ( Abc_ObjFanoutNum(pObj) > 0 )
{
fprintf( stdout, "NetworkCheck: A PO \"%s\" has %d fanout(s).\n", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) );
return 0;
}
pObj->pCopy = (Abc_Obj_t *)1;
}
Abc_NtkForEachObj( pNtk, pObj, i )
{
if ( pObj->pCopy == NULL && Abc_ObjIsPo(pObj) )
{
fprintf( stdout, "NetworkCheck: Net \"%s\" (id=%d) is in a PO but is not in the PO list.\n", Abc_ObjName(pObj), pObj->Id );
return 0;
}
pObj->pCopy = NULL;
}
return 1;
}
/**Function*************************************************************
Synopsis [Checks the connectivity of the object.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckObj( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
{
Abc_Obj_t * pFanin, * pFanout;
int Value = 1;
int i, k;
// check the network
if ( pObj->pNtk != pNtk )
{
fprintf( stdout, "NetworkCheck: Object \"%s\" does not belong to the network.\n", Abc_ObjName(pObj) );
return 0;
}
// check the object ID
if ( pObj->Id < 0 || (int)pObj->Id >= Abc_NtkObjNumMax(pNtk) )
{
fprintf( stdout, "NetworkCheck: Object \"%s\" has incorrect ID.\n", Abc_ObjName(pObj) );
return 0;
}
if ( !Abc_FrameIsFlagEnabled("checkfio") )
return Value;
// go through the fanins of the object and make sure fanins have this object as a fanout
Abc_ObjForEachFanin( pObj, pFanin, i )
{
if ( Vec_IntFind( &pFanin->vFanouts, pObj->Id ) == -1 )
{
fprintf( stdout, "NodeCheck: Object \"%s\" has fanin ", Abc_ObjName(pObj) );
fprintf( stdout, "\"%s\" but the fanin does not have it as a fanout.\n", Abc_ObjName(pFanin) );
Value = 0;
}
}
// go through the fanouts of the object and make sure fanouts have this object as a fanin
Abc_ObjForEachFanout( pObj, pFanout, i )
{
if ( Vec_IntFind( &pFanout->vFanins, pObj->Id ) == -1 )
{
fprintf( stdout, "NodeCheck: Object \"%s\" has fanout ", Abc_ObjName(pObj) );
fprintf( stdout, "\"%s\" but the fanout does not have it as a fanin.\n", Abc_ObjName(pFanout) );
Value = 0;
}
}
// make sure fanins are not duplicated
for ( i = 0; i < pObj->vFanins.nSize; i++ )
for ( k = i + 1; k < pObj->vFanins.nSize; k++ )
if ( pObj->vFanins.pArray[k] == pObj->vFanins.pArray[i] )
{
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanin %s.\n", Abc_ObjName(Abc_ObjFanin(pObj,k)) );
}
// save time: do not check large fanout lists
if ( pObj->vFanouts.nSize > 100 )
return Value;
// make sure fanouts are not duplicated
for ( i = 0; i < pObj->vFanouts.nSize; i++ )
for ( k = i + 1; k < pObj->vFanouts.nSize; k++ )
if ( pObj->vFanouts.pArray[k] == pObj->vFanouts.pArray[i] )
{
printf( "Warning: Node %s has", Abc_ObjName(pObj) );
printf( " duplicated fanout %s.\n", Abc_ObjName(Abc_ObjFanout(pObj,k)) );
}
return Value;
}
/**Function*************************************************************
Synopsis [Checks the integrity of a net.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckNet( Abc_Ntk_t * pNtk, Abc_Obj_t * pNet )
{
if ( Abc_ObjFaninNum(pNet) == 0 )
{
fprintf( stdout, "NetworkCheck: Net \"%s\" is not driven.\n", Abc_ObjName(pNet) );
return 0;
}
if ( Abc_ObjFaninNum(pNet) > 1 )
{
fprintf( stdout, "NetworkCheck: Net \"%s\" has more than one driver.\n", Abc_ObjName(pNet) );
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Checks the integrity of a node.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckNode( Abc_Ntk_t * pNtk, Abc_Obj_t * pNode )
{
// detect internal nodes that do not have nets
if ( Abc_NtkIsNetlist(pNtk) && Abc_ObjFanoutNum(pNode) == 0 )
{
fprintf( stdout, "Node (id = %d) has no net to drive.\n", pNode->Id );
return 0;
}
// the node should have a function assigned unless it is an AIG
if ( pNode->pData == NULL )
{
if ( Abc_ObjIsBarBuf(pNode) )
return 1;
fprintf( stdout, "NodeCheck: An internal node \"%s\" does not have a logic function.\n", Abc_ObjNameNet(pNode) );
return 0;
}
// the netlist and SOP logic network should have SOPs
if ( Abc_NtkHasSop(pNtk) )
{
if ( !Abc_SopCheck( (char *)pNode->pData, Abc_ObjFaninNum(pNode) ) )
{
fprintf( stdout, "NodeCheck: SOP check for node \"%s\" has failed.\n", Abc_ObjNameNet(pNode) );
return 0;
}
}
else if ( Abc_NtkHasBdd(pNtk) )
{
#ifdef ABC_USE_CUDD
int nSuppSize = Cudd_SupportSize((DdManager *)pNtk->pManFunc, (DdNode *)pNode->pData);
if ( nSuppSize > Abc_ObjFaninNum(pNode) )
{
fprintf( stdout, "NodeCheck: BDD of the node \"%s\" has incorrect support size.\n", Abc_ObjNameNet(pNode) );
return 0;
}
#endif
}
else if ( !Abc_NtkHasMapping(pNtk) && !Abc_NtkHasBlifMv(pNtk) && !Abc_NtkHasAig(pNtk) )
{
assert( 0 );
}
return 1;
}
/**Function*************************************************************
Synopsis [Checks the integrity of a latch.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckLatch( Abc_Ntk_t * pNtk, Abc_Obj_t * pLatch )
{
int Value = 1;
// check whether the object is a latch
if ( !Abc_ObjIsLatch(pLatch) )
{
fprintf( stdout, "NodeCheck: Latch \"%s\" is in a latch list but is not a latch.\n", Abc_ObjName(pLatch) );
Value = 0;
}
// make sure the latch has a reasonable return value
if ( (int)(ABC_PTRINT_T)pLatch->pData < ABC_INIT_ZERO || (int)(ABC_PTRINT_T)pLatch->pData > ABC_INIT_DC )
{
fprintf( stdout, "NodeCheck: Latch \"%s\" has incorrect reset value (%d).\n",
Abc_ObjName(pLatch), (int)(ABC_PTRINT_T)pLatch->pData );
Value = 0;
}
// make sure the latch has only one fanin
if ( Abc_ObjFaninNum(pLatch) != 1 )
{
fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanins.\n", Abc_ObjName(pLatch), Abc_ObjFaninNum(pLatch) );
Value = 0;
}
// make sure the latch has only one fanout
if ( Abc_ObjFanoutNum(pLatch) != 1 )
{
fprintf( stdout, "NodeCheck: Latch \"%s\" has wrong number (%d) of fanouts.\n", Abc_ObjName(pLatch), Abc_ObjFanoutNum(pLatch) );
Value = 0;
}
// make sure the latch input has only one fanin
if ( Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) != 1 )
{
fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanins.\n",
Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanin0(pLatch)) );
Value = 0;
}
// make sure the latch input has only one fanout
if ( Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) != 1 )
{
fprintf( stdout, "NodeCheck: Input of latch \"%s\" has wrong number (%d) of fanouts.\n",
Abc_ObjName(Abc_ObjFanin0(pLatch)), Abc_ObjFanoutNum(Abc_ObjFanin0(pLatch)) );
Value = 0;
}
// make sure the latch output has only one fanin
if ( Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) != 1 )
{
fprintf( stdout, "NodeCheck: Output of latch \"%s\" has wrong number (%d) of fanins.\n",
Abc_ObjName(Abc_ObjFanout0(pLatch)), Abc_ObjFaninNum(Abc_ObjFanout0(pLatch)) );
Value = 0;
}
return Value;
}
/**Function*************************************************************
Synopsis [Compares the PIs of the two networks.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkComparePis( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
{
Abc_Obj_t * pObj1;
int i;
if ( Abc_NtkPiNum(pNtk1) != Abc_NtkPiNum(pNtk2) )
{
printf( "Networks have different number of primary inputs.\n" );
return 0;
}
// for each PI of pNet1 find corresponding PI of pNet2 and reorder them
Abc_NtkForEachPi( pNtk1, pObj1, i )
{
if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) ) != 0 )
{
printf( "Primary input #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n",
i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPi(pNtk2,i)) );
return 0;
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Compares the POs of the two networks.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkComparePos( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
{
Abc_Obj_t * pObj1;
int i;
if ( Abc_NtkPoNum(pNtk1) != Abc_NtkPoNum(pNtk2) )
{
printf( "Networks have different number of primary outputs.\n" );
return 0;
}
// for each PO of pNet1 find corresponding PO of pNet2 and reorder them
Abc_NtkForEachPo( pNtk1, pObj1, i )
{
if ( strcmp( Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) ) != 0 )
{
printf( "Primary output #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n",
i, Abc_ObjName(pObj1), Abc_ObjName(Abc_NtkPo(pNtk2,i)) );
return 0;
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Compares the latches of the two networks.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCompareBoxes( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fComb )
{
Abc_Obj_t * pObj1;
int i;
assert( Abc_NtkHasOnlyLatchBoxes(pNtk1) );
assert( Abc_NtkHasOnlyLatchBoxes(pNtk2) );
if ( !fComb )
return 1;
if ( Abc_NtkBoxNum(pNtk1) != Abc_NtkBoxNum(pNtk2) )
{
printf( "Networks have different number of latches.\n" );
return 0;
}
// for each PI of pNet1 find corresponding PI of pNet2 and reorder them
Abc_NtkForEachBox( pNtk1, pObj1, i )
{
if ( strcmp( Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) ) != 0 )
{
printf( "Box #%d is different in network 1 ( \"%s\") and in network 2 (\"%s\").\n",
i, Abc_ObjName(Abc_ObjFanout0(pObj1)), Abc_ObjName(Abc_ObjFanout0(Abc_NtkBox(pNtk2,i))) );
return 0;
}
}
return 1;
}
/**Function*************************************************************
Synopsis [Compares the signals of the networks.]
Description []
SideEffects [Ordering POs by name is a very bad idea! It destroys
the natural order of the logic in the circuit.]
SeeAlso []
***********************************************************************/
int Abc_NtkCompareSignals( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fOnlyPis, int fComb )
{
Abc_NtkOrderObjsByName( pNtk1, fComb );
Abc_NtkOrderObjsByName( pNtk2, fComb );
if ( !Abc_NtkComparePis( pNtk1, pNtk2, fComb ) )
return 0;
if ( !fOnlyPis )
{
if ( !Abc_NtkCompareBoxes( pNtk1, pNtk2, fComb ) )
return 0;
if ( !Abc_NtkComparePos( pNtk1, pNtk2, fComb ) )
return 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Returns 0 if the network hierachy contains a cycle.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkIsAcyclicHierarchy_rec( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pNtkNext;
Abc_Obj_t * pObj;
int i;
// return if visited
if ( pNtk->fHieVisited )
return 1;
pNtk->fHieVisited = 1;
// return if black box
if ( Abc_NtkHasBlackbox(pNtk) )
return 1;
assert( Abc_NtkIsNetlist(pNtk) );
// go through all the children networks
Abc_NtkForEachBox( pNtk, pObj, i )
{
if ( Abc_ObjIsLatch(pObj) )
continue;
pNtkNext = (Abc_Ntk_t *)pObj->pData;
assert( pNtkNext != NULL );
if ( pNtkNext->fHiePath )
return 0;
pNtk->fHiePath = 1;
if ( !Abc_NtkIsAcyclicHierarchy_rec( pNtkNext ) )
return 0;
pNtk->fHiePath = 0;
}
return 1;
}
/**Function*************************************************************
Synopsis [Returns 0 if the network hierachy contains a cycle.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkIsAcyclicHierarchy( Abc_Ntk_t * pNtk )
{
Abc_Ntk_t * pTemp;
int i, RetValue;
assert( Abc_NtkIsNetlist(pNtk) && pNtk->pDesign );
// clear the modules
Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
pTemp->fHieVisited = pTemp->fHiePath = 0;
// traverse
pNtk->fHiePath = 1;
RetValue = Abc_NtkIsAcyclicHierarchy_rec( pNtk );
pNtk->fHiePath = 0;
// clear the modules
Vec_PtrForEachEntry( Abc_Ntk_t *, pNtk->pDesign->vModules, pTemp, i )
pTemp->fHieVisited = pTemp->fHiePath = 0;
return RetValue;
}
/**Function*************************************************************
Synopsis [Returns 0 if CI names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkNamesCompare( char ** pName1, char ** pName2 )
{
return strcmp( *pName1, *pName2 );
}
/**Function*************************************************************
Synopsis [Returns 0 if CI names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckUniqueCiNames( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNames;
Abc_Obj_t * pObj;
int i, fRetValue = 1;
assert( !Abc_NtkIsNetlist(pNtk) );
vNames = Vec_PtrAlloc( Abc_NtkCiNum(pNtk) );
Abc_NtkForEachCi( pNtk, pObj, i )
Vec_PtrPush( vNames, Abc_ObjName(pObj) );
Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare );
for ( i = 1; i < Abc_NtkCiNum(pNtk); i++ )
if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) )
{
printf( "Abc_NtkCheck: Repeated CI names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) );
fRetValue = 0;
}
Vec_PtrFree( vNames );
return fRetValue;
}
/**Function*************************************************************
Synopsis [Returns 0 if CO names are repeated.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckUniqueCoNames( Abc_Ntk_t * pNtk )
{
Vec_Ptr_t * vNames;
Abc_Obj_t * pObj;
int i, fRetValue = 1;
assert( !Abc_NtkIsNetlist(pNtk) );
vNames = Vec_PtrAlloc( Abc_NtkCoNum(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
Vec_PtrPush( vNames, Abc_ObjName(pObj) );
Vec_PtrSort( vNames, (int (*)())Abc_NtkNamesCompare );
for ( i = 1; i < Abc_NtkCoNum(pNtk); i++ )
{
// printf( "%s\n", Vec_PtrEntry(vNames,i) );
if ( !strcmp( (const char *)Vec_PtrEntry(vNames,i-1), (const char *)Vec_PtrEntry(vNames,i) ) )
{
printf( "Abc_NtkCheck: Repeated CO names: %s and %s.\n", (char*)Vec_PtrEntry(vNames,i-1), (char*)Vec_PtrEntry(vNames,i) );
fRetValue = 0;
}
}
Vec_PtrFree( vNames );
return fRetValue;
}
/**Function*************************************************************
Synopsis [Returns 0 if there is a pair of CI/CO with the same name and logic in between.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCheckUniqueCioNames( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj, * pObjCi, * pFanin;
int i, nCiId, fRetValue = 1;
assert( !Abc_NtkIsNetlist(pNtk) );
Abc_NtkForEachCo( pNtk, pObj, i )
{
nCiId = Nm_ManFindIdByNameTwoTypes( pNtk->pManName, Abc_ObjName(pObj), ABC_OBJ_PI, ABC_OBJ_BO );
if ( nCiId == -1 )
continue;
pObjCi = Abc_NtkObj( pNtk, nCiId );
assert( !strcmp( Abc_ObjName(pObj), Abc_ObjName(pObjCi) ) );
pFanin = Abc_ObjFanin0(pObj);
if ( pFanin != pObjCi )
{
printf( "Abc_NtkCheck: A CI/CO pair share the name (%s) but do not link directly. The name of the CO fanin is %s.\n",
Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanin0(pObj)) );
fRetValue = 0;
}
}
return fRetValue;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END