/**Function************************************************************* Synopsis [Converts combinational AIG with latches into sequential AIG.] Description [The const/PI/PO nodes are duplicated. The internal nodes are duplicated in the topological order. The dangling nodes are not duplicated. The choice nodes are duplicated.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkAigToSeq( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFaninNew; Vec_Int_t * vInitValues; Abc_InitType_t Init; int i, k, RetValue; // make sure it is an AIG without self-feeding latches assert( Abc_NtkIsStrash(pNtk) ); assert( Abc_NtkIsDfsOrdered(pNtk) ); if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtk) ) printf( "Modified %d self-feeding latches. The result will not verify.\n", RetValue ); assert( Abc_NtkCountSelfFeedLatches(pNtk) == 0 ); // start the network pNtkNew = Abc_NtkAlloc( ABC_NTK_SEQ, ABC_FUNC_AIG, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // map the constant nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // copy all objects, except the latches and constant Vec_PtrFill( pNtkNew->vObjs, Abc_NtkObjNumMax(pNtk), NULL ); Vec_PtrWriteEntry( pNtkNew->vObjs, 0, Abc_AigConst1(pNtk)->pCopy ); Abc_NtkForEachObj( pNtk, pObj, i ) { if ( i == 0 || Abc_ObjIsLatch(pObj) ) continue; pObj->pCopy = Abc_ObjAlloc( pNtkNew, pObj->Type ); pObj->pCopy->Id = pObj->Id; // the ID is the same for both pObj->pCopy->fPhase = pObj->fPhase; // used to work with choices pObj->pCopy->Level = pObj->Level; // used for upper bound on clock cycle Vec_PtrWriteEntry( pNtkNew->vObjs, pObj->pCopy->Id, pObj->pCopy ); pNtkNew->nObjs++; } pNtkNew->nObjCounts[ABC_OBJ_NODE] = pNtk->nObjCounts[ABC_OBJ_NODE]; // create PI/PO and their names Abc_NtkForEachPi( pNtk, pObj, i ) { Vec_PtrPush( pNtkNew->vPis, pObj->pCopy ); Vec_PtrPush( pNtkNew->vCis, pObj->pCopy ); Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); }
/**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_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) { Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsStrash(pNtk) ); srand( 0x12341234 ); // initialize the values Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 ); // simulate for the given number of timeframes for ( f = 0; f < nFrames; f++ ) { Abc_AigForEachAnd( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); // assign input values Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); } // set the final values Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj)); }
/**Function************************************************************* Synopsis [Performs X-valued simulation of the sequential network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fInputs, int fVerbose ) { Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsStrash(pNtk) ); srand( 0x12341234 ); // start simulation Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); if ( fInputs ) { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, XVSX ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); } else { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX ); } // simulate and print the result fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" ); for ( f = 0; f < nFrames; f++ ) { Abc_AigForEachAnd( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); // print out fprintf( stdout, "%2d : ", f ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); fprintf( stdout, " : " ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) ); fprintf( stdout, " : " ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); fprintf( stdout, "\n" ); // assign input values if ( fInputs ) Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, XVSX ); else Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); } }
/**Function************************************************************* Synopsis [Starts a new network using existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkStartFromNoLatches( Abc_Ntk_t * pNtk, Abc_NtkType_t Type, Abc_NtkFunc_t Func ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj; int i; if ( pNtk == NULL ) return NULL; assert( Type != ABC_NTK_NETLIST ); // start the network pNtkNew = Abc_NtkAlloc( Type, Func, 1 ); // duplicate the name and the spec pNtkNew->pName = Extra_UtilStrsav(pNtk->pName); pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec); // clean the node copy fields Abc_NtkCleanCopy( pNtk ); // map the constant nodes if ( Abc_NtkIsStrash(pNtk) && Abc_NtkIsStrash(pNtkNew) ) Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew); // clone CIs/CIs/boxes Abc_NtkForEachPi( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachAssert( pNtk, pObj, i ) Abc_NtkDupObj( pNtkNew, pObj, 1 ); Abc_NtkForEachBox( pNtk, pObj, i ) { if ( Abc_ObjIsLatch(pObj) ) continue; Abc_NtkDupBox(pNtkNew, pObj, 1); } // transfer the names // Abc_NtkTrasferNamesNoLatches( pNtk, pNtkNew ); Abc_ManTimeDup( pNtk, pNtkNew ); // check that the CI/CO/latches are copied correctly assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); return pNtkNew; }
/**Function************************************************************* Synopsis [Sets up the SAT sat_solver.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkMiterSatCreateInt( sat_solver * pSat, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode, * pFanin, * pNodeC, * pNodeT, * pNodeE; Vec_Ptr_t * vNodes, * vSuper; Vec_Int_t * vVars; int i, k, fUseMuxes = 1; // int fOrderCiVarsFirst = 0; int RetValue = 0; assert( Abc_NtkIsStrash(pNtk) ); // clean the CI node pointers Abc_NtkForEachCi( pNtk, pNode, i ) pNode->pCopy = NULL; // start the data structures vNodes = Vec_PtrAlloc( 1000 ); // the nodes corresponding to vars in the sat_solver vSuper = Vec_PtrAlloc( 100 ); // the nodes belonging to the given implication supergate vVars = Vec_IntAlloc( 100 ); // the temporary array for variables in the clause // add the clause for the constant node pNode = Abc_AigConst1(pNtk); pNode->fMarkA = 1; pNode->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pNode ); Abc_NtkClauseTriv( pSat, pNode, vVars ); /* // add the PI variables first Abc_NtkForEachCi( pNtk, pNode, i ) { pNode->fMarkA = 1; pNode->pCopy = (Abc_Obj_t *)vNodes->nSize; Vec_PtrPush( vNodes, pNode ); } */ // collect the nodes that need clauses and top-level assignments Vec_PtrClear( vSuper ); Abc_NtkForEachCo( pNtk, pNode, i ) { // get the fanin pFanin = Abc_ObjFanin0(pNode); // create the node's variable if ( pFanin->fMarkA == 0 ) { pFanin->fMarkA = 1; pFanin->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)vNodes->nSize; Vec_PtrPush( vNodes, pFanin ); } // add the trivial clause Vec_PtrPush( vSuper, Abc_ObjChild0(pNode) ); }
/**Function************************************************************* Synopsis [Creates miter for the sensitivity analysis.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkSensitivityMiter( Abc_Ntk_t * pNtk, int iVar ) { Abc_Ntk_t * pMiter; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pNext, * pFanin, * pOutput, * pObjNew; int i; assert( Abc_NtkIsStrash(pNtk) ); assert( iVar < Abc_NtkCiNum(pNtk) ); // duplicate the network pMiter = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pMiter->pName = Extra_UtilStrsav(pNtk->pName); pMiter->pSpec = Extra_UtilStrsav(pNtk->pSpec); // assign the PIs Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pMiter); Abc_AigConst1(pNtk)->pData = Abc_AigConst1(pMiter); Abc_NtkForEachCi( pNtk, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi( pMiter ); pObj->pData = pObj->pCopy; }
/**Function************************************************************* Synopsis [Prepares the network for mitering.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMiterPrepare( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, Abc_Ntk_t * pNtkMiter, int fComb, int nPartSize, int fMulti ) { Abc_Obj_t * pObj, * pObjNew; int i; // clean the copy field in all objects // Abc_NtkCleanCopy( pNtk1 ); // Abc_NtkCleanCopy( pNtk2 ); Abc_AigConst1(pNtk1)->pCopy = Abc_AigConst1(pNtkMiter); Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtkMiter); if ( fComb ) { // create new PIs and remember them in the old PIs Abc_NtkForEachCi( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePi( pNtkMiter ); // remember this PI in the old PIs pObj->pCopy = pObjNew; pObj = Abc_NtkCi(pNtk2, i); pObj->pCopy = pObjNew; // add name Abc_ObjAssignName( pObjNew, Abc_ObjName(pObj), NULL ); } if ( nPartSize <= 0 ) { // create POs if ( fMulti ) { Abc_NtkForEachCo( pNtk1, pObj, i ) { pObjNew = Abc_NtkCreatePo( pNtkMiter ); Abc_ObjAssignName( pObjNew, "miter", Abc_ObjName(pObjNew) ); } } else {
/**Function************************************************************* Synopsis [Sets the final nodes to point to the original nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTransferPointers( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkAig ) { Abc_Obj_t * pObj; Ivy_Obj_t * pObjIvy, * pObjFraig; int i; pObj = Abc_AigConst1(pNtk); pObj->pCopy = Abc_AigConst1(pNtkAig); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCi(pNtkAig, i); Abc_NtkForEachCo( pNtk, pObj, i ) pObj->pCopy = Abc_NtkCo(pNtkAig, i); Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pCopy = Abc_NtkBox(pNtkAig, i); Abc_NtkForEachNode( pNtk, pObj, i ) { pObjIvy = (Ivy_Obj_t *)pObj->pCopy; if ( pObjIvy == NULL ) continue; pObjFraig = Ivy_ObjEquiv( pObjIvy ); if ( pObjFraig == NULL ) continue; pObj->pCopy = Abc_EdgeToNode( pNtkAig, Ivy_Regular(pObjFraig)->TravId ); pObj->pCopy = Abc_ObjNotCond( pObj->pCopy, Ivy_IsComplement(pObjFraig) ); }
Abc_Ntk_t * Abc_NtkFromMiniAig( Mini_Aig_t * p ) { Abc_Ntk_t * pNtk; Abc_Obj_t * pObj; Vec_Int_t * vCopies; int i, nNodes; // get the number of nodes nNodes = Mini_AigNodeNum(p); // create ABC network pNtk = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 ); pNtk->pName = Abc_UtilStrsav( "MiniAig" ); // create mapping from MiniAIG objects into ABC objects vCopies = Vec_IntAlloc( nNodes ); Vec_IntPush( vCopies, Abc_LitNot(Abc_ObjToLit(Abc_AigConst1(pNtk))) ); // iterate through the objects for ( i = 1; i < nNodes; i++ ) { if ( Mini_AigNodeIsPi( p, i ) ) pObj = Abc_NtkCreatePi(pNtk); else if ( Mini_AigNodeIsPo( p, i ) ) Abc_ObjAddFanin( (pObj = Abc_NtkCreatePo(pNtk)), Abc_NodeFanin0Copy(pNtk, vCopies, p, i) ); else if ( Mini_AigNodeIsAnd( p, i ) ) pObj = Abc_AigAnd((Abc_Aig_t *)pNtk->pManFunc, Abc_NodeFanin0Copy(pNtk, vCopies, p, i), Abc_NodeFanin1Copy(pNtk, vCopies, p, i)); else assert( 0 ); Vec_IntPush( vCopies, Abc_ObjToLit(pObj) ); } assert( Vec_IntSize(vCopies) == nNodes ); Abc_AigCleanup( (Abc_Aig_t *)pNtk->pManFunc ); Vec_IntFree( vCopies ); Abc_NtkAddDummyPiNames( pNtk ); Abc_NtkAddDummyPoNames( pNtk ); if ( !Abc_NtkCheck( pNtk ) ) fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); // add latches if ( Mini_AigRegNum(p) > 0 ) { extern Abc_Ntk_t * Abc_NtkRestrashWithLatches( Abc_Ntk_t * pNtk, int nLatches ); Abc_Ntk_t * pTemp; pNtk = Abc_NtkRestrashWithLatches( pTemp = pNtk, Mini_AigRegNum(p) ); Abc_NtkDelete( pTemp ); } return pNtk; }
/**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Man_t * Abc_NtkToMini( Abc_Ntk_t * pNtk ) { Hop_Man_t * pMan; Abc_Obj_t * pObj; int i; // create the manager pMan = Hop_ManStart(); // transfer the pointers to the basic nodes Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Hop_ManConst1(pMan); Abc_NtkForEachCi( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Hop_ObjCreatePi(pMan); // perform the conversion of the internal nodes (assumes DFS ordering) Abc_NtkForEachNode( pNtk, pObj, i ) pObj->pCopy = (Abc_Obj_t *)Hop_And( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj), (Hop_Obj_t *)Abc_ObjChild1Copy(pObj) ); // create the POs Abc_NtkForEachCo( pNtk, pObj, i ) Hop_ObjCreatePo( pMan, (Hop_Obj_t *)Abc_ObjChild0Copy(pObj) ); Hop_ManCleanup( pMan ); return pMan; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_Ntk4VarObjPrint_rec( Abc_Obj_t * pObj ) { if ( pObj == Abc_AigConst1(pObj->pNtk) ) { printf( "1" ); return; } if ( Abc_ObjIsPi(pObj) ) { printf( "%c", pObj->Id - 1 + 'a' ); return; } printf( "(" ); Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin0(pObj) ); if ( Abc_ObjFaninC0(pObj) ) printf( "\'" ); Abc_Ntk4VarObjPrint_rec( Abc_ObjFanin1(pObj) ); if ( Abc_ObjFaninC1(pObj) ) printf( "\'" ); printf( ")" ); }
Mini_Aig_t * Abc_NtkToMiniAig( Abc_Ntk_t * pNtk ) { Mini_Aig_t * p; Abc_Obj_t * pObj; int i; assert( Abc_NtkIsStrash(pNtk) ); // create the manager p = Mini_AigStart(); // create mapping from MiniAIG into ABC objects Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->iTemp = Mini_AigLitConst1(); // create primary inputs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = Mini_AigCreatePi(p); // create internal nodes Abc_NtkForEachNode( pNtk, pObj, i ) pObj->iTemp = Mini_AigAnd( p, Abc_NodeFanin0Copy2(pObj), Abc_NodeFanin1Copy2(pObj) ); // create primary outputs Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Mini_AigCreatePo( p, Abc_NodeFanin0Copy2(pObj) ); // set registers Mini_AigSetRegNum( p, Abc_NtkLatchNum(pNtk) ); return p; }
/**Function************************************************************* Synopsis [Converts the network from the AIG manager into ABC.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkFromMini( Abc_Ntk_t * pNtk, Hop_Man_t * pMan ) { Vec_Ptr_t * vNodes; Abc_Ntk_t * pNtkNew; Hop_Obj_t * pObj; int i; // perform strashing pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG ); // transfer the pointers to the basic nodes Hop_ManConst1(pMan)->pData = Abc_AigConst1(pNtkNew); Hop_ManForEachPi( pMan, pObj, i ) pObj->pData = Abc_NtkCi(pNtkNew, i); // rebuild the AIG vNodes = Hop_ManDfs( pMan ); Vec_PtrForEachEntry( Hop_Obj_t *, vNodes, pObj, i ) pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) ); Vec_PtrFree( vNodes ); // connect the PO nodes Hop_ManForEachPo( pMan, pObj, i ) Abc_ObjAddFanin( Abc_NtkCo(pNtkNew, i), (Abc_Obj_t *)Hop_ObjChild0Copy(pObj) ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkFromMini(): Network check has failed.\n" ); return pNtkNew; }
/**Function************************************************************* Synopsis [Transforms the AIG into nodes.] Description [Threhold is the max number of nodes duplicated at a node.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMultiInt( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { ProgressBar * pProgress; Abc_Obj_t * pNode, * pConst1, * pNodeNew; int i; // set the constant node pConst1 = Abc_AigConst1(pNtk); if ( Abc_ObjFanoutNum(pConst1) > 0 ) { pNodeNew = Abc_NtkCreateNode( pNtkNew ); pNodeNew->pData = Cudd_ReadOne( pNtkNew->pManFunc ); Cudd_Ref( pNodeNew->pData ); pConst1->pCopy = pNodeNew; } // perform renoding for POs pProgress = Extra_ProgressBarStart( stdout, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); if ( Abc_ObjIsCi(Abc_ObjFanin0(pNode)) ) continue; Abc_NtkMulti_rec( pNtkNew, Abc_ObjFanin0(pNode) ); }
/**Function************************************************************* Synopsis [Load the network into FPGA manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Fpga_Man_t * Abc_NtkToFpga( Abc_Ntk_t * pNtk, int fRecovery, float * pSwitching, int fLatchPaths, int fVerbose ) { Fpga_Man_t * pMan; ProgressBar * pProgress; Fpga_Node_t * pNodeFpga; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin, * pPrev; float * pfArrivals; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the mapping manager and set its parameters pMan = Fpga_ManCreate( Abc_NtkCiNum(pNtk), Abc_NtkCoNum(pNtk), fVerbose ); if ( pMan == NULL ) return NULL; Fpga_ManSetAreaRecovery( pMan, fRecovery ); Fpga_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); pfArrivals = Abc_NtkGetCiArrivalFloats(pNtk); if ( fLatchPaths ) { for ( i = 0; i < Abc_NtkPiNum(pNtk); i++ ) pfArrivals[i] = -FPGA_FLOAT_LARGE; } Fpga_ManSetInputArrivals( pMan, pfArrivals ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Fpga_ManReadConst1(pMan); Abc_NtkForEachCi( pNtk, pNode, i ) { pNodeFpga = Fpga_ManReadInputs(pMan)[i]; pNode->pCopy = (Abc_Obj_t *)pNodeFpga; if ( pSwitching ) Fpga_NodeSetSwitching( pNodeFpga, pSwitching[pNode->Id] ); }
/**Function************************************************************* Synopsis [Load the network into manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ) { Map_Man_t * pMan; Map_Node_t * pNodeMap; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin, * pPrev; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the mapping manager and set its parameters pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, fVerbose ); if ( pMan == NULL ) return NULL; Map_ManSetAreaRecovery( pMan, fRecovery ); Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); Map_ManSetDelayTarget( pMan, (float)DelayTarget ); Map_ManSetInputArrivals( pMan, Abc_NtkMapCopyCiArrival(pNtk, Abc_NtkGetCiArrivalTimes(pNtk)) ); Map_ManSetOutputRequireds( pMan, Abc_NtkMapCopyCoRequired(pNtk, Abc_NtkGetCoRequiredTimes(pNtk)) ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i == Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) break; pNodeMap = Map_ManReadInputs(pMan)[i]; pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); } // load the AIG into the mapper vNodes = Abc_AigDfsMap( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsLatch(pNode) ) { pFanin = Abc_ObjFanin0(pNode); pNodeMap = Map_NodeBuf( pMan, Map_NotCond( Abc_ObjFanin0(pFanin)->pCopy, (int)Abc_ObjFaninC0(pFanin) ) ); Abc_ObjFanout0(pNode)->pCopy = (Abc_Obj_t *)pNodeMap; continue; } assert( Abc_ObjIsNode(pNode) ); // add the node to the mapper pNodeMap = Map_NodeAnd( pMan, Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ), Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) ); assert( pNode->pCopy == NULL ); // remember the node pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); // set up the choice node if ( Abc_AigNodeIsChoice( pNode ) ) for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData ) { Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); } } assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); Vec_PtrFree( vNodes ); // set the primary outputs in the required phase Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i == Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ); } return pMan; }
//generate a single const node.. Abc_Obj_t * cnv (Abc_Ntk_t * ntk, int v) { return Abc_ObjNotCond (Abc_AigConst1 (ntk), !v); }
/**Function************************************************************* Synopsis [Verifies sequential equivalence by fraiging followed by SAT.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCecFraigPart( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int nSeconds, int nPartSize, int fVerbose ) { extern int Cmd_CommandExecute( void * pAbc, char * sCommand ); extern void * Abc_FrameGetGlobalFrame(); Prove_Params_t Params, * pParams = &Params; Abc_Ntk_t * pMiter, * pMiterPart; Abc_Obj_t * pObj; int i, RetValue, Status, nOutputs; // solve the CNF using the SAT solver Prove_ParamsSetDefault( pParams ); pParams->nItersMax = 5; // pParams->fVerbose = 1; assert( nPartSize > 0 ); // get the miter of the two networks pMiter = Abc_NtkMiter( pNtk1, pNtk2, 1, nPartSize ); if ( pMiter == NULL ) { printf( "Miter computation has failed.\n" ); return; } RetValue = Abc_NtkMiterIsConstant( pMiter ); if ( RetValue == 0 ) { printf( "Networks are NOT EQUIVALENT after structural hashing.\n" ); // report the error pMiter->pModel = Abc_NtkVerifyGetCleanModel( pMiter, 1 ); Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); FREE( pMiter->pModel ); Abc_NtkDelete( pMiter ); return; } if ( RetValue == 1 ) { printf( "Networks are equivalent after structural hashing.\n" ); Abc_NtkDelete( pMiter ); return; } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "unset progressbar" ); // solve the problem iteratively for each output of the miter Status = 1; nOutputs = 0; Abc_NtkForEachPo( pMiter, pObj, i ) { if ( Abc_ObjFanin0(pObj) == Abc_AigConst1(pMiter) ) { if ( Abc_ObjFaninC0(pObj) ) // complemented -> const 0 RetValue = 1; else RetValue = 0; pMiterPart = NULL; } else { // get the cone of this output pMiterPart = Abc_NtkCreateCone( pMiter, Abc_ObjFanin0(pObj), Abc_ObjName(pObj), 0 ); if ( Abc_ObjFaninC0(pObj) ) Abc_ObjXorFaninC( Abc_NtkPo(pMiterPart,0), 0 ); // solve the cone // RetValue = Abc_NtkMiterProve( &pMiterPart, pParams ); RetValue = Abc_NtkIvyProve( &pMiterPart, pParams ); } if ( RetValue == -1 ) { printf( "Networks are undecided (resource limits is reached).\r" ); Status = -1; } else if ( RetValue == 0 ) { int * pSimInfo = Abc_NtkVerifySimulatePattern( pMiterPart, pMiterPart->pModel ); if ( pSimInfo[0] != 1 ) printf( "ERROR in Abc_NtkMiterProve(): Generated counter-example is invalid.\n" ); else printf( "Networks are NOT EQUIVALENT. \n" ); free( pSimInfo ); Status = 0; break; } else { printf( "Finished part %d (out of %d)\r", i+1, Abc_NtkPoNum(pMiter) ); nOutputs += nPartSize; } // if ( pMiter->pModel ) // Abc_NtkVerifyReportError( pNtk1, pNtk2, pMiter->pModel ); if ( pMiterPart ) Abc_NtkDelete( pMiterPart ); } Cmd_CommandExecute( Abc_FrameGetGlobalFrame(), "set progressbar" ); if ( Status == 1 ) printf( "Networks are equivalent. \n" ); else if ( Status == -1 ) printf( "Timed out after verifying %d outputs (out of %d).\n", nOutputs, Abc_NtkCoNum(pNtk1) ); Abc_NtkDelete( pMiter ); }
/**Function************************************************************* Synopsis [Strashes one node in the BLIF-MV netlist.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NodeStrashBlifMv( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj ) { int fAddFreeVars = 1; char * pSop; Abc_Obj_t ** pValues, ** pValuesF, ** pValuesF2; Abc_Obj_t * pTemp, * pTemp2, * pFanin, * pFanin2, * pNet; int k, v, Def, DefIndex, Index, nValues, nValuesF, nValuesF2; // start the output values assert( Abc_ObjIsNode(pObj) ); pNet = Abc_ObjFanout0(pObj); nValues = Abc_ObjMvVarNum(pNet); pValues = ABC_ALLOC( Abc_Obj_t *, nValues ); for ( k = 0; k < nValues; k++ ) pValues[k] = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); // get the BLIF-MV formula pSop = (char *)pObj->pData; // skip the value line // while ( *pSop++ != '\n' ); // handle the constant if ( Abc_ObjFaninNum(pObj) == 0 ) { // skip the default if present if ( *pSop == 'd' ) while ( *pSop++ != '\n' ); // skip space if present if ( *pSop == ' ' ) pSop++; // assume don't-care constant to be zero if ( *pSop == '-' ) Index = 0; else Index = Abc_StringGetNumber( &pSop ); assert( Index < nValues ); //////////////////////////////////////////// // adding free variables for binary ND-constants if ( fAddFreeVars && nValues == 2 && *pSop == '-' ) { pValues[1] = Abc_NtkCreatePi(pNtkNew); pValues[0] = Abc_ObjNot( pValues[1] ); Abc_ObjAssignName( pValues[1], "free_var_", Abc_ObjName(pValues[1]) ); } else pValues[Index] = Abc_AigConst1(pNtkNew); //////////////////////////////////////////// // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; return 1; } // parse the default line Def = DefIndex = -1; if ( *pSop == 'd' ) { pSop++; if ( *pSop == '=' ) { pSop++; DefIndex = Abc_StringGetNumber( &pSop ); assert( DefIndex < Abc_ObjFaninNum(pObj) ); } else if ( *pSop == '-' ) { pSop++; Def = 0; } else { Def = Abc_StringGetNumber( &pSop ); assert( Def < nValues ); } assert( *pSop == '\n' ); pSop++; } // convert the values while ( *pSop ) { // extract the values for each cube pTemp = Abc_AigConst1(pNtkNew); Abc_ObjForEachFanin( pObj, pFanin, k ) { if ( *pSop == '-' ) { pSop += 2; continue; } if ( *pSop == '!' ) { ABC_FREE( pValues ); printf( "Abc_NodeStrashBlifMv(): Cannot handle complement in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); return 0; } if ( *pSop == '{' ) { ABC_FREE( pValues ); printf( "Abc_NodeStrashBlifMv(): Cannot handle braces in the MV function of node %s.\n", Abc_ObjName(Abc_ObjFanout0(pObj)) ); return 0; } // get the value set nValuesF = Abc_ObjMvVarNum(pFanin); pValuesF = (Abc_Obj_t **)pFanin->pCopy; if ( *pSop == '(' ) { pSop++; pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); while ( *pSop != ')' ) { Index = Abc_StringGetNumber( &pSop ); assert( Index < nValuesF ); pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, pValuesF[Index] ); assert( *pSop == ')' || *pSop == ',' ); if ( *pSop == ',' ) pSop++; } assert( *pSop == ')' ); pSop++; } else if ( *pSop == '=' ) { pSop++; // get the fanin index Index = Abc_StringGetNumber( &pSop ); assert( Index < Abc_ObjFaninNum(pObj) ); assert( Index != k ); // get the fanin pFanin2 = Abc_ObjFanin( pObj, Index ); nValuesF2 = Abc_ObjMvVarNum(pFanin2); pValuesF2 = (Abc_Obj_t **)pFanin2->pCopy; // create the sum of products of values assert( nValuesF == nValuesF2 ); pTemp2 = Abc_ObjNot( Abc_AigConst1(pNtkNew) ); for ( v = 0; v < nValues; v++ ) pTemp2 = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp2, Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pValuesF[v], pValuesF2[v]) ); } else { Index = Abc_StringGetNumber( &pSop ); assert( Index < nValuesF ); pTemp2 = pValuesF[Index]; } // compute the compute pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pTemp2 ); // advance the reading point assert( *pSop == ' ' ); pSop++; } // check if the output value is an equal construct if ( *pSop == '=' ) { pSop++; // get the output value Index = Abc_StringGetNumber( &pSop ); assert( Index < Abc_ObjFaninNum(pObj) ); // add values of the given fanin with the given cube pFanin = Abc_ObjFanin( pObj, Index ); nValuesF = Abc_ObjMvVarNum(pFanin); pValuesF = (Abc_Obj_t **)pFanin->pCopy; assert( nValuesF == nValues ); // should be guaranteed by the parser for ( k = 0; k < nValuesF; k++ ) pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) ); } else { // get the output value Index = Abc_StringGetNumber( &pSop ); assert( Index < nValues ); pValues[Index] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[Index], pTemp ); } // advance the reading point assert( *pSop == '\n' ); pSop++; } // compute the default value if ( Def >= 0 || DefIndex >= 0 ) { pTemp = Abc_AigConst1(pNtkNew); for ( k = 0; k < nValues; k++ ) { if ( k == Def ) continue; pTemp = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, pTemp, Abc_ObjNot(pValues[k]) ); } // assign the default value if ( Def >= 0 ) pValues[Def] = pTemp; else { assert( DefIndex >= 0 ); // add values of the given fanin with the given cube pFanin = Abc_ObjFanin( pObj, DefIndex ); nValuesF = Abc_ObjMvVarNum(pFanin); pValuesF = (Abc_Obj_t **)pFanin->pCopy; assert( nValuesF == nValues ); // should be guaranteed by the parser for ( k = 0; k < nValuesF; k++ ) pValues[k] = Abc_AigOr( (Abc_Aig_t *)pNtkNew->pManFunc, pValues[k], Abc_AigAnd((Abc_Aig_t *)pNtkNew->pManFunc, pTemp, pValuesF[k]) ); } } // save the values in the fanout net pNet->pCopy = (Abc_Obj_t *)pValues; return 1; }
pMiter->pSpec = Extra_UtilStrsav(pNtk->pSpec); // assign the PIs Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pMiter); Abc_AigConst1(pNtk)->pData = Abc_AigConst1(pMiter); Abc_NtkForEachCi( pNtk, pObj, i ) { pObj->pCopy = Abc_NtkCreatePi( pMiter ); pObj->pData = pObj->pCopy; } Abc_NtkAddDummyPiNames( pMiter ); // assign the cofactors of the CI node to be constants pObj = Abc_NtkCi( pNtk, iVar ); pObj->pCopy = Abc_ObjNot( Abc_AigConst1(pMiter) ); pObj->pData = Abc_AigConst1(pMiter); // collect the internal nodes vNodes = Abc_NtkDfsReverseNodes( pNtk, &pObj, 1 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { for ( pNext = pObj? pObj->pCopy : pObj; pObj; pObj = pNext, pNext = pObj? pObj->pCopy : pObj ) { pFanin = Abc_ObjFanin0(pObj); if ( !Abc_NodeIsTravIdCurrent(pFanin) ) pFanin->pData = Abc_NtkSensitivityMiter_rec( pMiter, pFanin ); pFanin = Abc_ObjFanin1(pObj); if ( !Abc_NodeIsTravIdCurrent(pFanin) ) pFanin->pData = Abc_NtkSensitivityMiter_rec( pMiter, pFanin ); pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );