/**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 /// ////////////////////////////////////////////////////////////////////////