ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLatchIsSelfFeed_rec( Abc_Obj_t * pLatch, Abc_Obj_t * pLatchRoot ) { Abc_Obj_t * pFanin; assert( Abc_ObjIsLatch(pLatch) ); if ( pLatch == pLatchRoot ) return 1; pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) return 0; return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); }
/**Function************************************************************* Synopsis [Checks if latches form self-loop.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkLatchIsSelfFeed( Abc_Obj_t * pLatch ) { Abc_Obj_t * pFanin; assert( Abc_ObjIsLatch(pLatch) ); pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); if ( !Abc_ObjIsBo(pFanin) || !Abc_ObjIsLatch(Abc_ObjFanin0(pFanin)) ) return 0; return Abc_NtkLatchIsSelfFeed_rec( Abc_ObjFanin0(pFanin), pLatch ); }
/**Function************************************************************* Synopsis [Prints statistics about latches.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintLatch( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pLatch, * pFanin; int i, Counter0, Counter1, Counter2; int InitNums[4], Init; assert( !Abc_NtkIsNetlist(pNtk) ); if ( Abc_NtkLatchNum(pNtk) == 0 ) { fprintf( pFile, "The network is combinational.\n" ); return; } for ( i = 0; i < 4; i++ ) InitNums[i] = 0; Counter0 = Counter1 = Counter2 = 0; Abc_NtkForEachLatch( pNtk, pLatch, i ) { Init = Abc_LatchInit( pLatch ); assert( Init < 4 ); InitNums[Init]++; pFanin = Abc_ObjFanin0(Abc_ObjFanin0(pLatch)); if ( Abc_NtkIsLogic(pNtk) ) { if ( !Abc_NodeIsConst(pFanin) ) continue; } else if ( Abc_NtkIsStrash(pNtk) ) { if ( !Abc_AigNodeIsConst(pFanin) ) continue; } else assert( 0 ); // the latch input is a constant node Counter0++; if ( Abc_LatchIsInitDc(pLatch) ) { Counter1++; continue; } // count the number of cases when the constant is equal to the initial value if ( Abc_NtkIsStrash(pNtk) ) { if ( Abc_LatchIsInit1(pLatch) == !Abc_ObjFaninC0(pLatch) ) Counter2++; } else { if ( Abc_LatchIsInit1(pLatch) == Abc_NodeIsConst1(pLatch) ) Counter2++; } }
/**Function************************************************************* Synopsis [Implementation of max-flow/min-cut computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NtkMaxFlow( Abc_Ntk_t * pNtk, int fForward, int fVerbose ) { Vec_Ptr_t * vMinCut; Abc_Obj_t * pLatch; int Flow, FlowCur, RetValue, i; abctime clk = Abc_Clock(); int fUseDirectedFlow = 1; // find the max-flow Abc_NtkCleanCopy( pNtk ); Flow = 0; Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fForward ) { // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); // FlowCur = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); Flow += FlowCur; } else { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); Flow += FlowCur; } if ( FlowCur ) Abc_NtkIncrementTravId(pNtk); } if ( !fUseDirectedFlow ) { Abc_NtkIncrementTravId(pNtk); Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fForward ) { // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); Flow += FlowCur; } else { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); FlowCur = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); Flow += FlowCur; } if ( FlowCur ) Abc_NtkIncrementTravId(pNtk); } }
// insert the PO nodes into the table Abc_NtkForEachPo( pNtk, pObj, i ) { p->nTried++; p->nAdded++; pObj = Abc_ObjFanin0(pObj); pTruth = Vec_PtrEntry( p->vTtNodes, pObj->Id ); // add the resulting truth table to the hash table ppSpot = Abc_NtkRecTableLookup( p, pTruth, p->nVars ); assert( pObj->pEquiv == NULL ); assert( pObj->pCopy == NULL ); if ( *ppSpot == NULL ) { p->nAddedFuncs++; *ppSpot = pObj; } else { pObj->pEquiv = (*ppSpot)->pEquiv; (*ppSpot)->pEquiv = (Hop_Obj_t *)pObj; if ( !Abc_NtkRecAddCutCheckCycle_rec(*ppSpot, pObj) ) printf( "Loop!\n" ); } }
/**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)); }
// first add the nets to the CO drivers Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0(pObj); if ( Abc_ObjIsCi(pDriver) ) { assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); continue; } assert( Abc_ObjIsNode(pDriver) ); // if the CO driver has no net, create it if ( pDriver->pCopy->pCopy == NULL ) { // create the CO net and connect it to CO pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pObj->pCopy, pNet ); // connect the CO net to the new driver and remember it in the new driver Abc_ObjAddFanin( pNet, pDriver->pCopy ); pDriver->pCopy->pCopy = pNet; } else { assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) ); Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy ); } }
/**Function************************************************************* Synopsis [Computes the l-value of the node.] Description [The node can be internal or a PO.] SideEffects [] SeeAlso [] ***********************************************************************/ int Seq_FpgaNodeUpdateLValue( Abc_Obj_t * pObj, int Fi ) { Cut_Cut_t * pCut, * pList; int lValueNew, lValueOld, lValueCut; assert( !Abc_ObjIsPi(pObj) ); assert( Abc_ObjFaninNum(pObj) > 0 ); if ( Abc_ObjIsPo(pObj) ) { lValueNew = Seq_NodeGetLValue(Abc_ObjFanin0(pObj)) - Fi * Seq_ObjFaninL0(pObj); return (lValueNew > Fi)? SEQ_UPDATE_FAIL : SEQ_UPDATE_NO; } // get the arrival time of the best non-trivial cut pList = Abc_NodeReadCuts( Seq_NodeCutMan(pObj), pObj ); // skip the choice nodes if ( pList == NULL ) return SEQ_UPDATE_NO; lValueNew = ABC_INFINITY; for ( pCut = pList->pNext; pCut; pCut = pCut->pNext ) { lValueCut = Seq_FpgaCutUpdateLValue( pCut, pObj, Fi ); if ( lValueNew > lValueCut ) lValueNew = lValueCut; } // compare the arrival time with the previous arrival time lValueOld = Seq_NodeGetLValue(pObj); // if ( lValueNew == lValueOld ) if ( lValueNew <= lValueOld ) return SEQ_UPDATE_NO; Seq_NodeSetLValue( pObj, lValueNew ); //printf( "%d -> %d ", lValueOld, lValueNew ); return SEQ_UPDATE_YES; }
/**Function************************************************************* Synopsis [Computes the transition relation of the network.] Description [Assumes that the global BDDs are computed.] SideEffects [] SeeAlso [] ***********************************************************************/ DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose ) { DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs; Abc_Obj_t * pNode; int fReorder = 1; int i; // extand the BDD manager to represent NS variables assert( dd->size == Abc_NtkCiNum(pNtk) ); Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 ); // enable reordering if ( fReorder ) Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT ); else Cudd_AutodynDisable( dd ); // compute the transition relation bRel = b1; Cudd_Ref( bRel ); Abc_NtkForEachLatch( pNtk, pNode, i ) { bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i ); // bProd = Cudd_bddXnor( dd, bVar, pNtk->vFuncsGlob->pArray[i] ); Cudd_Ref( bProd ); bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd ); bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel ); Cudd_RecursiveDeref( dd, bTemp ); Cudd_RecursiveDeref( dd, bProd ); }
/**Function************************************************************* Synopsis [Transform the netlist into a logic network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pFanin; int i, k; // consider the case of the AIG if ( Abc_NtkIsStrash(pNtk) ) return Abc_NtkAigToLogicSop( pNtk ); assert( Abc_NtkIsNetlist(pNtk) ); // consider simple case when there is hierarchy // assert( pNtk->pDesign == NULL ); assert( Abc_NtkWhiteboxNum(pNtk) == 0 ); assert( Abc_NtkBlackboxNum(pNtk) == 0 ); // start the network pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc ); // duplicate the nodes Abc_NtkForEachNode( pNtk, pObj, i ) Abc_NtkDupObj(pNtkNew, pObj, 0); // reconnect the internal nodes in the new network Abc_NtkForEachNode( pNtk, pObj, i ) Abc_ObjForEachFanin( pObj, pFanin, k ) Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy ); // collect the CO nodes Abc_NtkFinalize( pNtk, pNtkNew ); // fix the problem with CO pointing directly to CIs Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 ); // duplicate EXDC if ( pNtk->pExdc ) pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc ); if ( !Abc_NtkCheck( pNtkNew ) ) fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" ); return pNtkNew; }
/**Function************************************************************* Synopsis [Test-bench for the max-flow computation.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkMaxFlowTest( Abc_Ntk_t * pNtk ) { Vec_Ptr_t * vMinCut; Abc_Obj_t * pObj; int i; // forward flow Abc_NtkForEachPo( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->fMarkA = Abc_ObjFanin0(pObj)->fMarkA = 1; // Abc_ObjFanin0(pObj)->fMarkA = 1; vMinCut = Abc_NtkMaxFlow( pNtk, 1, 1 ); Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); // backward flow Abc_NtkForEachPi( pNtk, pObj, i ) pObj->fMarkA = 1; Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->fMarkA = Abc_ObjFanout0(pObj)->fMarkA = 1; // Abc_ObjFanout0(pObj)->fMarkA = 1; vMinCut = Abc_NtkMaxFlow( pNtk, 0, 1 ); Vec_PtrFree( vMinCut ); Abc_NtkCleanMarkA( pNtk ); }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Copies the topmost levels of the network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_NtkSensitivityMiter_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode ) { assert( !Abc_ObjIsComplement(pNode) ); if ( pNode->pCopy ) return pNode->pCopy; Abc_NtkSensitivityMiter_rec( pNtkNew, Abc_ObjFanin0(pNode) ); Abc_NtkSensitivityMiter_rec( pNtkNew, Abc_ObjFanin1(pNode) ); return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) ); }
// collect the results for the COs; Abc_NtkForEachCo( pNtk, pTemp, i ) { //printf( "Output %d:\n", i ); pTemp = Abc_ObjFanin0(pTemp); if ( Abc_ObjIsCi(pTemp) || Abc_AigNodeIsConst(pTemp) ) continue; Sim_SymmsTransferToMatrix( (Extra_BitMat_t *)Vec_PtrEntry(vMatrs, i), SIM_READ_SYMMS(pTemp), (unsigned *)Vec_PtrEntry(vSuppFun, i) ); }
/**Function************************************************************* Synopsis [Retimes node forward by one latch.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjRetimeForward( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanout; int Init0, Init1, Init, i; assert( Abc_ObjFaninNum(pObj) == 2 ); assert( Seq_ObjFaninL0(pObj) >= 1 ); assert( Seq_ObjFaninL1(pObj) >= 1 ); // remove the init values from the fanins Init0 = Seq_NodeDeleteFirst( pObj, 0 ); Init1 = Seq_NodeDeleteFirst( pObj, 1 ); assert( Init0 != ABC_INIT_NONE ); assert( Init1 != ABC_INIT_NONE ); // take into account the complements in the node if ( Abc_ObjFaninC0(pObj) ) { if ( Init0 == ABC_INIT_ZERO ) Init0 = ABC_INIT_ONE; else if ( Init0 == ABC_INIT_ONE ) Init0 = ABC_INIT_ZERO; } if ( Abc_ObjFaninC1(pObj) ) { if ( Init1 == ABC_INIT_ZERO ) Init1 = ABC_INIT_ONE; else if ( Init1 == ABC_INIT_ONE ) Init1 = ABC_INIT_ZERO; } // compute the value at the output of the node if ( Init0 == ABC_INIT_ZERO || Init1 == ABC_INIT_ZERO ) Init = ABC_INIT_ZERO; else if ( Init0 == ABC_INIT_ONE && Init1 == ABC_INIT_ONE ) Init = ABC_INIT_ONE; else Init = ABC_INIT_DC; // make sure the label is clean Abc_ObjForEachFanout( pObj, pFanout, i ) assert( pFanout->fMarkC == 0 ); // add the init values to the fanouts Abc_ObjForEachFanout( pObj, pFanout, i ) { if ( pFanout->fMarkC ) continue; pFanout->fMarkC = 1; if ( Abc_ObjFaninId0(pFanout) != Abc_ObjFaninId1(pFanout) ) Seq_NodeInsertLast( pFanout, Abc_ObjFanoutEdgeNum(pObj, pFanout), Init ); else { assert( Abc_ObjFanin0(pFanout) == pObj ); Seq_NodeInsertLast( pFanout, 0, Init ); Seq_NodeInsertLast( pFanout, 1, Init ); } } // clean the label Abc_ObjForEachFanout( pObj, pFanout, i ) pFanout->fMarkC = 0; }
/**Function************************************************************* Synopsis [Finalizes the network using the existing network as a model.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkFinalize( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj, * pDriver, * pDriverNew; int i; // set the COs of the strashed network Abc_NtkForEachCo( pNtk, pObj, i ) { pDriver = Abc_ObjFanin0Ntk( Abc_ObjFanin0(pObj) ); pDriverNew = Abc_ObjNotCond(pDriver->pCopy, Abc_ObjFaninC0(pObj)); Abc_ObjAddFanin( pObj->pCopy, pDriverNew ); }
/**Function************************************************************* Synopsis [Create Ptr from Abc_Ntk_t.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Ptr_AbcObjName( Abc_Obj_t * pObj ) { if ( Abc_ObjIsNet(pObj) || Abc_ObjIsBox(pObj) ) return Abc_ObjName(pObj); if ( Abc_ObjIsCi(pObj) || Abc_ObjIsNode(pObj) ) return Ptr_AbcObjName(Abc_ObjFanout0(pObj)); if ( Abc_ObjIsCo(pObj) ) return Ptr_AbcObjName(Abc_ObjFanin0(pObj)); assert( 0 ); return NULL; }
/**Function************************************************************* Synopsis [Create the reset latch with data=1 and init=0.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Io_ReadCreateResetLatch( Abc_Ntk_t * pNtk, int fBlifMv ) { Abc_Obj_t * pLatch, * pNode; Abc_Obj_t * pNetLI, * pNetLO; // create latch with 0 init value // pLatch = Io_ReadCreateLatch( pNtk, "_resetLI_", "_resetLO_" ); pNetLI = Abc_NtkCreateNet( pNtk ); pNetLO = Abc_NtkCreateNet( pNtk ); Abc_ObjAssignName( pNetLI, Abc_ObjName(pNetLI), NULL ); Abc_ObjAssignName( pNetLO, Abc_ObjName(pNetLO), NULL ); pLatch = Io_ReadCreateLatch( pNtk, Abc_ObjName(pNetLI), Abc_ObjName(pNetLO) ); // set the initial value Abc_LatchSetInit0( pLatch ); // feed the latch with constant1- node // pNode = Abc_NtkCreateNode( pNtk ); // pNode->pData = Abc_SopRegister( pNtk->pManFunc, "2\n1\n" ); pNode = Abc_NtkCreateNodeConst1( pNtk ); Abc_ObjAddFanin( Abc_ObjFanin0(Abc_ObjFanin0(pLatch)), pNode ); return pLatch; }
/**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 [Derives GIA manager using special pins to denote box boundaries.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Abc_NtkTestPinDeriveGia( Abc_Ntk_t * pNtk, int fWhiteBoxOnly, int fVerbose ) { Gia_Man_t * pTemp; Gia_Man_t * pGia = NULL; Vec_Ptr_t * vNodes; Abc_Obj_t * pObj, * pFanin; int i, k, iPinLit = 0; // prepare logic network assert( Abc_NtkIsLogic(pNtk) ); Abc_NtkToAig( pNtk ); // construct GIA Abc_NtkFillTemp( pNtk ); pGia = Gia_ManStart( Abc_NtkObjNumMax(pNtk) ); Gia_ManHashAlloc( pGia ); // create primary inputs Abc_NtkForEachCi( pNtk, pObj, i ) pObj->iTemp = Gia_ManAppendCi(pGia); // create internal nodes in a topologic order from white boxes vNodes = Abc_NtkDfs( pNtk, 0 ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i ) { // input side if ( !fWhiteBoxOnly || Abc_NodeIsWhiteBox(pObj) ) { // create special pintype for this node iPinLit = Gia_ManAppendPinType( pGia, 1 ); // create input pins Abc_ObjForEachFanin( pObj, pFanin, k ) pFanin->iTemp = Gia_ManAppendAnd( pGia, pFanin->iTemp, iPinLit ); } // perform GIA construction pObj->iTemp = Abc_NtkTestTimNodeStrash( pGia, pObj ); // output side if ( !fWhiteBoxOnly || Abc_NodeIsWhiteBox(pObj) ) { // create special pintype for this node iPinLit = Gia_ManAppendPinType( pGia, 1 ); // create output pins pObj->iTemp = Gia_ManAppendAnd( pGia, pObj->iTemp, iPinLit ); } } Vec_PtrFree( vNodes ); // create primary outputs Abc_NtkForEachCo( pNtk, pObj, i ) pObj->iTemp = Gia_ManAppendCo( pGia, Abc_ObjFanin0(pObj)->iTemp ); // finalize GIA Gia_ManHashStop( pGia ); Gia_ManSetRegNum( pGia, 0 ); // clean up GIA pGia = Gia_ManCleanup( pTemp = pGia ); Gia_ManStop( pTemp ); return pGia; }
/**Function************************************************************* Synopsis [Returns the maximum latch number on any of the fanouts.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Seq_NtkLevelMax( Abc_Ntk_t * pNtk ) { Abc_Obj_t * pNode; int i, Result; assert( Abc_NtkIsSeq(pNtk) ); Result = 0; Abc_NtkForEachPo( pNtk, pNode, i ) { pNode = Abc_ObjFanin0(pNode); if ( Result < (int)pNode->Level ) Result = pNode->Level; }
Abc_NtkForEachLatch( pNtk, pLatch, i ) { if ( fForward ) { // assert( !Abc_ObjFanout0(pLatch)->fMarkA ); if ( fUseDirectedFlow ) RetValue = Abc_NtkMaxFlowFwdPath2_rec( Abc_ObjFanout0(pLatch) ); // RetValue = Abc_NtkMaxFlowFwdPath3_rec( Abc_ObjFanout0(pLatch), pLatch, 1 ); else RetValue = Abc_NtkMaxFlowFwdPath_rec( Abc_ObjFanout0(pLatch) ); } else { assert( !Abc_ObjFanin0(pLatch)->fMarkA ); if ( fUseDirectedFlow ) RetValue = Abc_NtkMaxFlowBwdPath2_rec( Abc_ObjFanin0(pLatch) ); else RetValue = Abc_NtkMaxFlowBwdPath_rec( Abc_ObjFanin0(pLatch) ); } assert( RetValue == 0 ); }
/**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 [Maps virtual latches into real latches.] Description [Creates new latches and assigns them to virtual latches on the edges of a sequential AIG. The nodes of the new network should be created before this procedure is called.] SideEffects [] SeeAlso [] ***********************************************************************/ void Seq_NtkShareLatches( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj, * pFanin; stmm_table * tLatchMap; int i; assert( Abc_NtkIsSeq( pNtk ) ); tLatchMap = stmm_init_table( stmm_ptrcmp, stmm_ptrhash ); Abc_AigForEachAnd( pNtk, pObj, i ) { pFanin = Abc_ObjFanin0(pObj); Seq_NtkShareLatches_rec( pNtkNew, pFanin->pCopy, Seq_NodeGetRing(pObj,0), Seq_NodeCountLats(pObj,0), tLatchMap ); pFanin = Abc_ObjFanin1(pObj); Seq_NtkShareLatches_rec( pNtkNew, pFanin->pCopy, Seq_NodeGetRing(pObj,1), Seq_NodeCountLats(pObj,1), tLatchMap ); }
/**Function************************************************************* Synopsis [Computes the retiming lags for FPGA mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Seq_FpgaMappingDelays( Abc_Ntk_t * pNtk, int fVerbose ) { Abc_Seq_t * p = pNtk->pManFunc; Cut_Params_t Params, * pParams = &Params; Abc_Obj_t * pObj; int i, clk; // set defaults for cut computation memset( pParams, 0, sizeof(Cut_Params_t) ); pParams->nVarsMax = p->nVarsMax; // the max cut size ("k" of the k-feasible cuts) pParams->nKeepMax = 1000; // the max number of cuts kept at a node pParams->fTruth = 0; // compute truth tables pParams->fFilter = 1; // filter dominated cuts pParams->fSeq = 1; // compute sequential cuts pParams->fVerbose = fVerbose; // the verbosiness flag // compute the cuts clk = clock(); p->pCutMan = Abc_NtkSeqCuts( pNtk, pParams ); // pParams->fSeq = 0; // p->pCutMan = Abc_NtkCuts( pNtk, pParams ); p->timeCuts = clock() - clk; if ( fVerbose ) Cut_ManPrintStats( p->pCutMan ); // compute area flows // Seq_MapComputeAreaFlows( pNtk, fVerbose ); // compute the delays clk = clock(); if ( !Seq_AigRetimeDelayLags( pNtk, fVerbose ) ) return 0; p->timeDelay = clock() - clk; // collect the nodes and cuts used in the mapping p->vMapAnds = Vec_PtrAlloc( 1000 ); p->vMapCuts = Vec_VecAlloc( 1000 ); Abc_NtkIncrementTravId( pNtk ); Abc_NtkForEachPo( pNtk, pObj, i ) Seq_FpgaMappingCollectNode_rec( Abc_ObjFanin0(pObj), p->vMapAnds, p->vMapCuts ); if ( fVerbose ) printf( "The number of LUTs = %d.\n", Vec_PtrSize(p->vMapAnds) ); // remove the cuts Cut_ManStop( p->pCutMan ); p->pCutMan = NULL; return 1; }
/**Function************************************************************* Synopsis [Prepares the network for retiming.] Description [Hash latches into their number in the original network.] SideEffects [] SeeAlso [] ***********************************************************************/ st__table * Abc_NtkRetimePrepareLatches( Abc_Ntk_t * pNtk ) { st__table * tLatches; Abc_Obj_t * pLatch, * pLatchIn, * pLatchOut, * pFanin; int i, nOffSet = Abc_NtkBoxNum(pNtk) - Abc_NtkLatchNum(pNtk); // collect latches and remove CIs/COs tLatches = st__init_table( st__ptrcmp, st__ptrhash ); Abc_NtkForEachLatch( pNtk, pLatch, i ) { // map latch into its true number st__insert( tLatches, (char *)(ABC_PTRUINT_T)pLatch, (char *)(ABC_PTRUINT_T)(i-nOffSet) ); // disconnect LI pLatchIn = Abc_ObjFanin0(pLatch); pFanin = Abc_ObjFanin0(pLatchIn); Abc_ObjTransferFanout( pLatchIn, pFanin ); Abc_ObjDeleteFanin( pLatchIn, pFanin ); // disconnect LO pLatchOut = Abc_ObjFanout0(pLatch); pFanin = Abc_ObjFanin0(pLatchOut); if ( Abc_ObjFanoutNum(pLatchOut) > 0 ) Abc_ObjTransferFanout( pLatchOut, pFanin ); Abc_ObjDeleteFanin( pLatchOut, pFanin ); }
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) ); pObj->pData = Abc_AigAnd( (Abc_Aig_t *)pMiter->pManFunc, Abc_ObjChild0Data(pObj), Abc_ObjChild1Data(pObj) ); } }
/**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 [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned Abc_Ntk4VarObj( Vec_Ptr_t * vNodes ) { Abc_Obj_t * pObj; unsigned uTruth0, uTruth1; int i; Vec_PtrForEachEntry( vNodes, pObj, i ) { uTruth0 = (unsigned)(Abc_ObjFanin0(pObj)->pCopy); uTruth1 = (unsigned)(Abc_ObjFanin1(pObj)->pCopy); if ( Abc_ObjFaninC0(pObj) ) uTruth0 = ~uTruth0; if ( Abc_ObjFaninC1(pObj) ) uTruth1 = ~uTruth1; pObj->pCopy = (void *)(uTruth0 & uTruth1); }
/**Function************************************************************* Synopsis [Reads initial state in BENCH format.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_ReadBenchInit( Abc_Ntk_t * pNtk, char * pFileName ) { char pBuffer[1000]; FILE * pFile; char * pToken; Abc_Obj_t * pObj; int Num; pFile = fopen( pFileName, "r" ); if ( pFile == NULL ) { printf( "Io_ReadBenchInit(): Failed to open file \"%s\".\n", pFileName ); return; } while ( fgets( pBuffer, 999, pFile ) ) { pToken = strtok( pBuffer, " \n\t\r" ); // find the latch output Num = Nm_ManFindIdByName( pNtk->pManName, pToken, ABC_OBJ_BO ); if ( Num < 0 ) { printf( "Io_ReadBenchInit(): Cannot find register with output %s.\n", pToken ); continue; } pObj = Abc_ObjFanin0( Abc_NtkObj( pNtk, Num ) ); if ( !Abc_ObjIsLatch(pObj) ) { printf( "Io_ReadBenchInit(): The signal is not a register output %s.\n", pToken ); continue; } // assign the new init state pToken = strtok( NULL, " \n\t\r" ); if ( pToken[0] == '0' ) Abc_LatchSetInit0( pObj ); else if ( pToken[0] == '1' ) Abc_LatchSetInit1( pObj ); else if ( pToken[0] == '2' ) Abc_LatchSetInitDc( pObj ); else { printf( "Io_ReadBenchInit(): The signal %s has unknown initial value (%s).\n", Abc_ObjName(Abc_ObjFanout0(pObj)), pToken ); continue; } } fclose( pFile ); }
/**Function************************************************************* Synopsis [Tranfers names to the old network.] Description [Assumes that the new nodes are attached using pObj->pCopy.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTrasferNamesNoLatches( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew ) { Abc_Obj_t * pObj; int i; assert( Abc_NtkPiNum(pNtk) == Abc_NtkPiNum(pNtkNew) ); assert( Abc_NtkPoNum(pNtk) == Abc_NtkPoNum(pNtkNew) ); assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); // copy the CI/CO/box name and skip latches and theirs inputs/outputs Abc_NtkForEachCi( pNtk, pObj, i ) if ( Abc_ObjFaninNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanin0(pObj)) ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); Abc_NtkForEachCo( pNtk, pObj, i ) if ( Abc_ObjFanoutNum(pObj) == 0 || !Abc_ObjIsLatch(Abc_ObjFanout0(pObj)) ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); Abc_NtkForEachBox( pNtk, pObj, i ) if ( !Abc_ObjIsLatch(pObj) ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); }