blob: 9faf08c91b8593c62b01c0f39807fdb2bc700b5c [file] [log] [blame]
/**CFile****************************************************************
FileName [abcDebug.c]
SystemName [ABC: Logic synthesis and verification system.]
PackageName [Network and node package.]
Synopsis [Automated debugging procedures.]
Author [Alan Mishchenko]
Affiliation [UC Berkeley]
Date [Ver. 1.0. Started - June 20, 2005.]
Revision [$Id: abcDebug.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
***********************************************************************/
#include "base/abc/abc.h"
#include "base/io/ioAbc.h"
ABC_NAMESPACE_IMPL_START
////////////////////////////////////////////////////////////////////////
/// DECLARATIONS ///
////////////////////////////////////////////////////////////////////////
static int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk );
static Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtk, int ObjNum, int fConst1 );
////////////////////////////////////////////////////////////////////////
/// FUNCTION DEFINITIONS ///
////////////////////////////////////////////////////////////////////////
/**Function*************************************************************
Synopsis [Takes a network and a procedure to test.]
Description [The network demonstrates the bug in the procedure.
Procedure should return 1 if the bug is demonstrated.]
SideEffects []
SeeAlso []
***********************************************************************/
void Abc_NtkAutoDebug( Abc_Ntk_t * pNtk, int (*pFuncError) (Abc_Ntk_t *) )
{
Abc_Ntk_t * pNtkMod;
char * pFileName = "bug_found.blif";
int i, nSteps, nIter, ModNum, RandNum = 1;
abctime clk, clkTotal = Abc_Clock();
assert( Abc_NtkIsLogic(pNtk) );
srand( 0x123123 );
// create internal copy of the network
pNtk = Abc_NtkDup(pNtk);
if ( !(*pFuncError)( pNtk ) )
{
printf( "The original network does not cause the bug. Quitting.\n" );
Abc_NtkDelete( pNtk );
return;
}
// perform incremental modifications
for ( nIter = 0; ; nIter++ )
{
clk = Abc_Clock();
// count how many ways of modifying the network exists
nSteps = 2 * Abc_NtkCountFaninsTotal(pNtk);
// try modifying the network as many times
RandNum ^= rand();
for ( i = 0; i < nSteps; i++ )
{
// get the shifted number of bug
ModNum = (i + RandNum) % nSteps;
// get the modified network
pNtkMod = Abc_NtkAutoDebugModify( pNtk, ModNum/2, ModNum%2 );
// write the network
Io_WriteBlifLogic( pNtk, "bug_temp.blif", 1 );
// check if the bug is still there
if ( (*pFuncError)( pNtkMod ) ) // bug is still there
{
Abc_NtkDelete( pNtk );
pNtk = pNtkMod;
break;
}
else // no bug
Abc_NtkDelete( pNtkMod );
}
printf( "Iter %6d : Latches = %6d. Nodes = %6d. Steps = %6d. Error step = %3d. ",
nIter, Abc_NtkLatchNum(pNtk), Abc_NtkNodeNum(pNtk), nSteps, i );
ABC_PRT( "Time", Abc_Clock() - clk );
if ( i == nSteps ) // could not modify it while preserving the bug
break;
}
// write out the final network
Io_WriteBlifLogic( pNtk, pFileName, 1 );
printf( "Final network written into file \"%s\". ", pFileName );
ABC_PRT( "Total time", Abc_Clock() - clkTotal );
Abc_NtkDelete( pNtk );
}
/**Function*************************************************************
Synopsis [Counts the total number of fanins.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkCountFaninsTotal( Abc_Ntk_t * pNtk )
{
Abc_Obj_t * pObj, * pFanin;
int i, k, Counter = 0;
Abc_NtkForEachObj( pNtk, pObj, i )
Abc_ObjForEachFanin( pObj, pFanin, k )
{
if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
continue;
if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
continue;
if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
continue;
Counter++;
}
return Counter;
}
/**Function*************************************************************
Synopsis [Returns the node and fanin to be modified.]
Description []
SideEffects []
SeeAlso []
***********************************************************************/
int Abc_NtkFindGivenFanin( Abc_Ntk_t * pNtk, int Step, Abc_Obj_t ** ppObj, Abc_Obj_t ** ppFanin )
{
Abc_Obj_t * pObj, * pFanin;
int i, k, Counter = 0;
Abc_NtkForEachObj( pNtk, pObj, i )
Abc_ObjForEachFanin( pObj, pFanin, k )
{
if ( !Abc_ObjIsNode(pObj) && !Abc_ObjIsPo(pObj) )
continue;
if ( Abc_ObjIsPo(pObj) && Abc_NtkPoNum(pNtk) == 1 )
continue;
if ( Abc_ObjIsNode(pObj) && Abc_NodeIsConst(pFanin) )
continue;
if ( Counter++ == Step )
{
*ppObj = pObj;
*ppFanin = pFanin;
return 1;
}
}
return 0;
}
/**Function*************************************************************
Synopsis [Perform modification with the given number.]
Description [Modification consists of replacing the node by a constant.]
SideEffects []
SeeAlso []
***********************************************************************/
Abc_Ntk_t * Abc_NtkAutoDebugModify( Abc_Ntk_t * pNtkInit, int Step, int fConst1 )
{
extern void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose );
Abc_Ntk_t * pNtk;
Abc_Obj_t * pObj, * pFanin, * pConst;
// copy the network
pNtk = Abc_NtkDup( pNtkInit );
assert( Abc_NtkNodeNum(pNtk) == Abc_NtkNodeNum(pNtkInit) );
// find the object number
Abc_NtkFindGivenFanin( pNtk, Step, &pObj, &pFanin );
// consider special case
if ( Abc_ObjIsPo(pObj) && Abc_NodeIsConst(pFanin) )
{
Abc_NtkDeleteAll_rec( pObj );
return pNtk;
}
// plug in a constant node
pConst = fConst1? Abc_NtkCreateNodeConst1(pNtk) : Abc_NtkCreateNodeConst0(pNtk);
Abc_ObjTransferFanout( pFanin, pConst );
Abc_NtkDeleteAll_rec( pFanin );
Abc_NtkSweep( pNtk, 0 );
Abc_NtkCleanupSeq( pNtk, 0, 0, 0 );
Abc_NtkToSop( pNtk, -1, ABC_INFINITY );
Abc_NtkCycleInitStateSop( pNtk, 50, 0 );
return pNtk;
}
////////////////////////////////////////////////////////////////////////
/// END OF FILE ///
////////////////////////////////////////////////////////////////////////
ABC_NAMESPACE_IMPL_END