/**CFile**************************************************************** FileName [retInit.c] SystemName [ABC: Logic synthesis and verification system.] PackageName [Retiming package.] Synopsis [Initial state computation for backward retiming.] Author [Alan Mishchenko] Affiliation [UC Berkeley] Date [Ver. 1.0. Started - Oct 31, 2006.] Revision [$Id: retInit.c,v 1.00 2006/10/31 00:00:00 alanmi Exp $] ***********************************************************************/ #include "retInt.h" ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// static int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ); //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Computes initial values of the new latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeInitialValues( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int fVerbose ) { Vec_Int_t * vSolution; Abc_Ntk_t * pNtkMiter, * pNtkLogic; int RetValue; abctime clk; if ( pNtkCone == NULL ) return Vec_IntDup( vValues ); // convert the target network to AIG pNtkLogic = Abc_NtkDup( pNtkCone ); Abc_NtkToAig( pNtkLogic ); // get the miter pNtkMiter = Abc_NtkCreateTarget( pNtkLogic, pNtkLogic->vCos, vValues ); if ( fVerbose ) printf( "The miter for initial state computation has %d AIG nodes. ", Abc_NtkNodeNum(pNtkMiter) ); // solve the miter clk = Abc_Clock(); RetValue = Abc_NtkMiterSat( pNtkMiter, (ABC_INT64_T)500000, (ABC_INT64_T)50000000, 0, NULL, NULL ); if ( fVerbose ) { ABC_PRT( "SAT solving time", Abc_Clock() - clk ); } // analyze the result if ( RetValue == 1 ) printf( "Abc_NtkRetimeInitialValues(): The problem is unsatisfiable. DC latch values are used.\n" ); else if ( RetValue == -1 ) printf( "Abc_NtkRetimeInitialValues(): The SAT problem timed out. DC latch values are used.\n" ); else if ( !Abc_NtkRetimeVerifyModel( pNtkCone, vValues, pNtkMiter->pModel ) ) printf( "Abc_NtkRetimeInitialValues(): The computed counter-example is incorrect.\n" ); // set the values of the latches vSolution = RetValue? NULL : Vec_IntAllocArray( pNtkMiter->pModel, Abc_NtkPiNum(pNtkLogic) ); pNtkMiter->pModel = NULL; Abc_NtkDelete( pNtkMiter ); Abc_NtkDelete( pNtkLogic ); return vSolution; } /**Function************************************************************* Synopsis [Computes the results of simulating one node.] Description [Assumes that fanins have pCopy set to the input values.] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_ObjSopSimulate( Abc_Obj_t * pObj ) { char * pCube, * pSop = (char *)pObj->pData; int nVars, Value, v, ResOr, ResAnd, ResVar; assert( pSop && !Abc_SopIsExorType(pSop) ); // simulate the SOP of the node ResOr = 0; nVars = Abc_SopGetVarNum(pSop); Abc_SopForEachCube( pSop, nVars, pCube ) { ResAnd = 1; Abc_CubeForEachVar( pCube, Value, v ) { if ( Value == '0' ) ResVar = 1 ^ ((int)(ABC_PTRUINT_T)Abc_ObjFanin(pObj, v)->pCopy); else if ( Value == '1' ) ResVar = (int)(ABC_PTRUINT_T)Abc_ObjFanin(pObj, v)->pCopy; else continue; ResAnd &= ResVar; } ResOr |= ResAnd; } // complement the result if necessary if ( !Abc_SopGetPhase(pSop) ) ResOr ^= 1; return ResOr; } /**Function************************************************************* Synopsis [Verifies the counter-example.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkRetimeVerifyModel( Abc_Ntk_t * pNtkCone, Vec_Int_t * vValues, int * pModel ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, Counter = 0; assert( Abc_NtkIsSopLogic(pNtkCone) ); // set the PIs Abc_NtkForEachPi( pNtkCone, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)pModel[i]; // simulate the internal nodes vNodes = Abc_NtkDfs( pNtkCone, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj ); Vec_PtrFree( vNodes ); // compare the outputs Abc_NtkForEachPo( pNtkCone, pObj, i ) pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; Abc_NtkForEachPo( pNtkCone, pObj, i ) Counter += (Vec_IntEntry(vValues, i) != (int)(ABC_PTRUINT_T)pObj->pCopy); if ( Counter > 0 ) printf( "%d outputs (out of %d) have a value mismatch.\n", Counter, Abc_NtkPoNum(pNtkCone) ); return 1; } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeTranferToCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj); } /**Function************************************************************* Synopsis [Transfer latch initial values from pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeTranferFromCopy( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pData = (void *)(ABC_PTRUINT_T)(pObj->pCopy? ABC_INIT_ONE : ABC_INIT_ZERO); } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Int_t * Abc_NtkRetimeCollectLatchValues( Abc_Ntk_t * pNtk ) { Vec_Int_t * vValues; Abc_Obj_t * pObj; int i; vValues = Vec_IntAlloc( Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) Vec_IntPush( vValues, Abc_LatchIsInit1(pObj) ); return vValues; } /**Function************************************************************* Synopsis [Transfer latch initial values from pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeInsertLatchValues( Abc_Ntk_t * pNtk, Vec_Int_t * vValues ) { Abc_Obj_t * pObj; int i, Counter = 0; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Counter++; Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pData = (Abc_Obj_t *)(ABC_PTRUINT_T)(vValues? (Vec_IntEntry(vValues,(int)(ABC_PTRUINT_T)pObj->pCopy)? ABC_INIT_ONE : ABC_INIT_ZERO) : ABC_INIT_DC); } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkRetimeBackwardInitialStart( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int i; // create the network used for the initial state computation pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_SOP, 1 ); // create POs corresponding to the initial values Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) pObj->pCopy = Abc_NtkCreatePo(pNtkNew); return pNtkNew; } /**Function************************************************************* Synopsis [Transfer latch initial values to pCopy.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkRetimeBackwardInitialFinish( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, Vec_Int_t * vValuesOld, int fVerbose ) { Vec_Int_t * vValuesNew; Abc_Obj_t * pObj; int i; // create PIs corresponding to the initial values Abc_NtkForEachObj( pNtk, pObj, i ) if ( Abc_ObjIsLatch(pObj) ) Abc_ObjAddFanin( pObj->pCopy, Abc_NtkCreatePi(pNtkNew) ); // assign dummy node names Abc_NtkAddDummyPiNames( pNtkNew ); Abc_NtkAddDummyPoNames( pNtkNew ); // check the network if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkRetimeBackwardInitialFinish(): Network check has failed.\n" ); // derive new initial values vValuesNew = Abc_NtkRetimeInitialValues( pNtkNew, vValuesOld, fVerbose ); // insert new initial values Abc_NtkRetimeInsertLatchValues( pNtk, vValuesNew ); if ( vValuesNew ) Vec_IntFree( vValuesNew ); } /**Function************************************************************* Synopsis [Cycles the circuit to create a new initial state.] Description [Simulates the circuit with random input for the given number of timeframes to get a better initial state.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCycleInitStateSop( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsSopLogic(pNtk) ); srand( 0x12341234 ); // initialize the values Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(rand() & 1); Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_LatchIsInit1(pObj); // simulate for the given number of timeframes vNodes = Abc_NtkDfs( pNtk, 0 ); for ( f = 0; f < nFrames; f++ ) { // simulate internal nodes Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)Abc_ObjSopSimulate( pObj ); // bring the results to the COs Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_ObjFanin0(pObj)->pCopy; // assign PI values Abc_NtkForEachPi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)(ABC_PTRUINT_T)(rand() & 1); // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjFanout0(pObj)->pCopy = Abc_ObjFanin0(pObj)->pCopy; } Vec_PtrFree( vNodes ); // set the final values Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pData = (void *)(ABC_PTRUINT_T)(Abc_ObjFanout0(pObj)->pCopy ? ABC_INIT_ONE : ABC_INIT_ZERO); } //////////////////////////////////////////////////////////////////////// /// END OF FILE /// //////////////////////////////////////////////////////////////////////// ABC_NAMESPACE_IMPL_END