mirror of https://github.com/YosysHQ/abc.git
371 lines
11 KiB
C
371 lines
11 KiB
C
/**CFile****************************************************************
|
|
|
|
FileName [ntlCheck.c]
|
|
|
|
SystemName [ABC: Logic synthesis and verification system.]
|
|
|
|
PackageName [Netlist representation.]
|
|
|
|
Synopsis [Checks consistency of the netlist.]
|
|
|
|
Author [Alan Mishchenko]
|
|
|
|
Affiliation [UC Berkeley]
|
|
|
|
Date [Ver. 1.0. Started - June 20, 2005.]
|
|
|
|
Revision [$Id: ntlCheck.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
|
|
|
|
***********************************************************************/
|
|
|
|
#include "ntl.h"
|
|
#include "aig.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// DECLARATIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// FUNCTION DEFINITIONS ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis []
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ntl_ModelCheckCombPoPaths_rec( Ntl_Mod_t * pModel, Ntl_Net_t * pNet )
|
|
{
|
|
Ntl_Net_t * pFanin;
|
|
int i;
|
|
// skip visited nets
|
|
if ( pNet->nVisits == 2 )
|
|
return 1;
|
|
pNet->nVisits = 2;
|
|
// process PIs
|
|
if ( Ntl_ObjIsPi(pNet->pDriver) )
|
|
return 0;
|
|
// process registers
|
|
if ( Ntl_ObjIsLatch(pNet->pDriver) )
|
|
return 1;
|
|
assert( Ntl_ObjIsNode(pNet->pDriver) );
|
|
// call recursively
|
|
Ntl_ObjForEachFanin( pNet->pDriver, pFanin, i )
|
|
if ( !Ntl_ModelCheckCombPoPaths_rec( pModel, pFanin ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks the existence of combinational paths from POs to PIs.]
|
|
|
|
Description [Returns 0 if the path is found.]
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ntl_ModelCheckCombPoPaths( Ntl_Mod_t * pModel )
|
|
{
|
|
Ntl_Obj_t * pObj;
|
|
int i;
|
|
Ntl_ModelClearNets( pModel );
|
|
Ntl_ModelForEachPo( pModel, pObj, i )
|
|
if ( !Ntl_ModelCheckCombPoPaths_rec( pModel, Ntl_ObjFanin0(pObj) ) )
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks one model.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ntl_ModelCheck( Ntl_Mod_t * pModel, int fMain )
|
|
{
|
|
Ntl_Obj_t * pObj;
|
|
Ntl_Net_t * pNet;
|
|
int i, k, fStatus = 1;
|
|
|
|
// check root level model
|
|
if ( fMain )
|
|
{
|
|
if ( Ntl_ModelLatchNum(pModel) > 0 )
|
|
{
|
|
printf( "Root level model %s has %d registers.\n", pModel->pName, Ntl_ModelLatchNum(pModel) );
|
|
fStatus = 0;
|
|
}
|
|
goto checkobjs;
|
|
}
|
|
|
|
// check delay information
|
|
if ( pModel->attrBox && pModel->attrComb )
|
|
{
|
|
if ( pModel->vDelays == NULL )
|
|
{
|
|
printf( "Warning: Comb model %s does not have delay info. Default 1.0 delays are assumed.\n", pModel->pName );
|
|
pModel->vDelays = Vec_IntAlloc( 3 );
|
|
Vec_IntPush( pModel->vDelays, -1 );
|
|
Vec_IntPush( pModel->vDelays, -1 );
|
|
Vec_IntPush( pModel->vDelays, Aig_Float2Int(1.0) );
|
|
}
|
|
if ( pModel->vTimeInputs != NULL )
|
|
{
|
|
printf( "Combinational model %s has input arrival/required time information.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
if ( pModel->vTimeOutputs != NULL )
|
|
{
|
|
printf( "Combinational model %s has output arrival/required time information.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
}
|
|
if ( pModel->attrBox && !pModel->attrComb )
|
|
{
|
|
if ( pModel->vDelays != NULL )
|
|
{
|
|
printf( "Sequential model %s has delay info.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
if ( pModel->vTimeInputs == NULL )
|
|
{
|
|
printf( "Warning: Seq model %s does not have input arrival/required time info. Default 0.0 is assumed.\n", pModel->pName );
|
|
pModel->vTimeInputs = Vec_IntAlloc( 2 );
|
|
Vec_IntPush( pModel->vTimeInputs, -1 );
|
|
Vec_IntPush( pModel->vTimeInputs, Aig_Float2Int(0.0) );
|
|
}
|
|
if ( pModel->vTimeOutputs == NULL )
|
|
{
|
|
// printf( "Warning: Seq model %s does not have output arrival/required time info. Default 0.0 is assumed.\n", pModel->pName );
|
|
pModel->vTimeOutputs = Vec_IntAlloc( 2 );
|
|
Vec_IntPush( pModel->vTimeOutputs, -1 );
|
|
Vec_IntPush( pModel->vTimeOutputs, Aig_Float2Int(0.0) );
|
|
}
|
|
}
|
|
|
|
// check box attributes
|
|
if ( pModel->attrBox )
|
|
{
|
|
if ( !pModel->attrWhite )
|
|
{
|
|
if ( Ntl_ModelNodeNum(pModel) + Ntl_ModelLut1Num(pModel) > 0 )
|
|
{
|
|
printf( "Model %s is a blackbox, yet it has %d nodes.\n", pModel->pName, Ntl_ModelNodeNum(pModel) + Ntl_ModelLut1Num(pModel) );
|
|
fStatus = 0;
|
|
}
|
|
if ( Ntl_ModelLatchNum(pModel) > 0 )
|
|
{
|
|
printf( "Model %s is a blackbox, yet it has %d registers.\n", pModel->pName, Ntl_ModelLatchNum(pModel) );
|
|
fStatus = 0;
|
|
}
|
|
return fStatus;
|
|
}
|
|
// this is a white box
|
|
if ( pModel->attrComb && Ntl_ModelNodeNum(pModel) + Ntl_ModelLut1Num(pModel) == 0 )
|
|
{
|
|
printf( "Model %s is a comb white box, yet it has no nodes.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
if ( pModel->attrComb && Ntl_ModelLatchNum(pModel) > 0 )
|
|
{
|
|
printf( "Model %s is a comb white box, yet it has registers.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
if ( !pModel->attrComb && Ntl_ModelLatchNum(pModel) == 0 )
|
|
{
|
|
printf( "Model %s is a seq white box, yet it has no registers.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
if ( !pModel->attrComb && !Ntl_ModelCheckCombPoPaths(pModel) )
|
|
{
|
|
printf( "Model %s is a seq white box with comb paths from PIs to POs.\n", pModel->pName );
|
|
fStatus = 0;
|
|
}
|
|
}
|
|
|
|
checkobjs:
|
|
// check nets
|
|
Ntl_ModelForEachNet( pModel, pNet, i )
|
|
{
|
|
if ( pNet->pName == NULL )
|
|
{
|
|
printf( "Net in bin %d does not have a name\n", i );
|
|
fStatus = 0;
|
|
}
|
|
if ( pNet->pDriver == NULL )
|
|
{
|
|
printf( "Net %s does not have a driver\n", pNet->pName );
|
|
fStatus = 0;
|
|
}
|
|
}
|
|
|
|
// check objects
|
|
Ntl_ModelForEachObj( pModel, pObj, i )
|
|
{
|
|
Ntl_ObjForEachFanin( pObj, pNet, k )
|
|
if ( pNet == NULL )
|
|
{
|
|
printf( "Object %d does not have fanin net %d\n", i, k );
|
|
fStatus = 0;
|
|
}
|
|
Ntl_ObjForEachFanout( pObj, pNet, k )
|
|
if ( pNet == NULL )
|
|
{
|
|
printf( "Object %d does not have fanout net %d\n", i, k );
|
|
fStatus = 0;
|
|
}
|
|
}
|
|
return fStatus;
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Checks the netlist.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
int Ntl_ManCheck( Ntl_Man_t * pMan )
|
|
{
|
|
Ntl_Mod_t * pMod1;
|
|
int i, fStatus = 1;
|
|
// check that the models have unique names
|
|
Ntl_ManForEachModel( pMan, pMod1, i )
|
|
{
|
|
if ( pMod1->pName == NULL )
|
|
{
|
|
printf( "Model %d does not have a name\n", i );
|
|
fStatus = 0;
|
|
}
|
|
}
|
|
// check that the models (except the first one) do not have boxes
|
|
Ntl_ManForEachModel( pMan, pMod1, i )
|
|
{
|
|
if ( i == 0 )
|
|
continue;
|
|
if ( Ntl_ModelBoxNum(pMod1) > 0 )
|
|
{
|
|
printf( "Non-root model %d (%s) has %d boxes.\n", i, pMod1->pName, Ntl_ModelBoxNum(pMod1) );
|
|
fStatus = 0;
|
|
}
|
|
}
|
|
// check models
|
|
Ntl_ManForEachModel( pMan, pMod1, i )
|
|
{
|
|
if ( !Ntl_ModelCheck( pMod1, i==0 ) )
|
|
fStatus = 0;
|
|
}
|
|
return fStatus;
|
|
}
|
|
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Fixed problems with non-driven nets in the model.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntl_ModelFixNonDrivenNets( Ntl_Mod_t * pModel )
|
|
{
|
|
Vec_Ptr_t * vNets;
|
|
Ntl_Net_t * pNet;
|
|
Ntl_Obj_t * pNode;
|
|
int i;
|
|
|
|
if ( !pModel->attrWhite )
|
|
return;
|
|
|
|
// check for non-driven nets
|
|
vNets = Vec_PtrAlloc( 100 );
|
|
Ntl_ModelForEachNet( pModel, pNet, i )
|
|
{
|
|
if ( pNet->pDriver != NULL )
|
|
continue;
|
|
// add the constant 0 driver
|
|
pNode = Ntl_ModelCreateNode( pModel, 0 );
|
|
pNode->pSop = Ntl_ManStoreSop( pModel->pMan->pMemSops, " 0\n" );
|
|
Ntl_ModelSetNetDriver( pNode, pNet );
|
|
// add the net to those for which the warning will be printed
|
|
Vec_PtrPush( vNets, pNet );
|
|
}
|
|
|
|
// print the warning
|
|
if ( Vec_PtrSize(vNets) > 0 )
|
|
{
|
|
printf( "Warning: Constant-0 drivers added to %d non-driven nets in network \"%s\":\n", Vec_PtrSize(vNets), pModel->pName );
|
|
Vec_PtrForEachEntry( vNets, pNet, i )
|
|
{
|
|
printf( "%s%s", (i? ", ": ""), pNet->pName );
|
|
if ( i == 3 )
|
|
{
|
|
if ( Vec_PtrSize(vNets) > 3 )
|
|
printf( " ..." );
|
|
break;
|
|
}
|
|
}
|
|
printf( "\n" );
|
|
}
|
|
Vec_PtrFree( vNets );
|
|
}
|
|
|
|
/**Function*************************************************************
|
|
|
|
Synopsis [Fixed problems with non-driven nets in the model.]
|
|
|
|
Description []
|
|
|
|
SideEffects []
|
|
|
|
SeeAlso []
|
|
|
|
***********************************************************************/
|
|
void Ntl_ModelTransformLatches( Ntl_Mod_t * pModel )
|
|
{
|
|
Ntl_Mod_t * pMod[3] = { NULL };
|
|
Ntl_Obj_t * pLatch;
|
|
int i, Init;
|
|
if ( Ntl_ModelLatchNum(pModel) == 0 )
|
|
return;
|
|
Ntl_ModelForEachLatch( pModel, pLatch, i )
|
|
{
|
|
Init = pLatch->LatchId.regInit;
|
|
if ( pMod[Init] == NULL )
|
|
pMod[Init] = Ntl_ManCreateLatchModel( pModel->pMan, Init );
|
|
pLatch->pImplem = pMod[Init];
|
|
pLatch->Type = NTL_OBJ_BOX;
|
|
}
|
|
printf( "In the main model \"%s\", %d latches are transformed into white seq boxes.\n", pModel->pName, Ntl_ModelLatchNum(pModel) );
|
|
pModel->nObjs[NTL_OBJ_BOX] += Ntl_ModelLatchNum(pModel);
|
|
pModel->nObjs[NTL_OBJ_LATCH] = 0;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
/// END OF FILE ///
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|