// 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 [Visualizes BDD of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeShowBdd( Abc_Obj_t * pNode ) { FILE * pFile; Vec_Ptr_t * vNamesIn; char FileNameDot[200]; char * pNameOut; assert( Abc_NtkIsBddLogic(pNode->pNtk) ); // create the file name Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } // set the node names vNamesIn = Abc_NodeGetFaninNames( pNode ); pNameOut = Abc_ObjName(pNode); Cudd_DumpDot( pNode->pNtk->pManFunc, 1, (DdNode **)&pNode->pData, (char **)vNamesIn->pArray, &pNameOut, pFile ); Abc_NodeFreeNames( vNamesIn ); Abc_NtkCleanCopy( pNode->pNtk ); fclose( pFile ); // visualize the file Abc_ShowFile( FileNameDot ); }
/**Function************************************************************* Synopsis [Write one network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_NtkWriteEqnOne( FILE * pFile, Abc_Ntk_t * pNtk ) { Vec_Vec_t * vLevels; ProgressBar * pProgress; Abc_Obj_t * pNode, * pFanin; int i, k; // write the PIs fprintf( pFile, "INORDER =" ); Io_NtkWriteEqnCis( pFile, pNtk ); fprintf( pFile, ";\n" ); // write the POs fprintf( pFile, "OUTORDER =" ); Io_NtkWriteEqnCos( pFile, pNtk ); fprintf( pFile, ";\n" ); // write each internal node vLevels = Vec_VecAlloc( 10 ); pProgress = Extra_ProgressBarStart( stdout, Abc_NtkObjNumMax(pNtk) ); Abc_NtkForEachNode( pNtk, pNode, i ) { Extra_ProgressBarUpdate( pProgress, i, NULL ); fprintf( pFile, "%s = ", Abc_ObjName(Abc_ObjFanout0(pNode)) ); // set the input names Abc_ObjForEachFanin( pNode, pFanin, k ) Hop_IthVar((Hop_Man_t *)pNtk->pManFunc, k)->pData = Abc_ObjName(pFanin); // write the formula Hop_ObjPrintEqn( pFile, (Hop_Obj_t *)pNode->pData, vLevels, 0 ); fprintf( pFile, ";\n" ); }
/**Function************************************************************* Synopsis [Inserts one-input node of the type specified between the nodes.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Obj_t * Abc_ObjInsertBetween( Abc_Obj_t * pNodeIn, Abc_Obj_t * pNodeOut, Abc_ObjType_t Type ) { Abc_Obj_t * pNodeNew; int iFanoutIndex, iFaninIndex; // find pNodeOut among the fanouts of pNodeIn if ( (iFanoutIndex = Vec_IntFind( &pNodeIn->vFanouts, pNodeOut->Id )) == -1 ) { printf( "Node %s is not among", Abc_ObjName(pNodeOut) ); printf( " the fanouts of node %s...\n", Abc_ObjName(pNodeIn) ); return NULL; } // find pNodeIn among the fanins of pNodeOut if ( (iFaninIndex = Vec_IntFind( &pNodeOut->vFanins, pNodeIn->Id )) == -1 ) { printf( "Node %s is not among", Abc_ObjName(pNodeIn) ); printf( " the fanins of node %s...\n", Abc_ObjName(pNodeOut) ); return NULL; } // create the new node pNodeNew = Abc_NtkCreateObj( pNodeIn->pNtk, Type ); // add pNodeIn as fanin and pNodeOut as fanout Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanins, pNodeIn->Id ); Vec_IntPushMem( pNodeNew->pNtk->pMmStep, &pNodeNew->vFanouts, pNodeOut->Id ); // update the fanout of pNodeIn Vec_IntWriteEntry( &pNodeIn->vFanouts, iFanoutIndex, pNodeNew->Id ); // update the fanin of pNodeOut Vec_IntWriteEntry( &pNodeOut->vFanins, iFaninIndex, pNodeNew->Id ); return pNodeNew; }
/**Function************************************************************* Synopsis [Symmetry computation using BDDs (both naive and smart).] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Ntk_NetworkSymmsBdd( DdManager * dd, Abc_Ntk_t * pNtk, int fNaive, int fVerbose ) { Extra_SymmInfo_t * pSymms; Abc_Obj_t * pNode; DdNode * bFunc; int nSymms = 0; int nSupps = 0; int i; // compute symmetry info for each PO Abc_NtkForEachCo( pNtk, pNode, i ) { // bFunc = pNtk->vFuncsGlob->pArray[i]; bFunc = Abc_ObjGlobalBdd( pNode ); nSupps += Cudd_SupportSize( dd, bFunc ); if ( Cudd_IsConstant(bFunc) ) continue; if ( fNaive ) pSymms = Extra_SymmPairsComputeNaive( dd, bFunc ); else pSymms = Extra_SymmPairsCompute( dd, bFunc ); nSymms += pSymms->nSymms; if ( fVerbose ) { printf( "Output %6s (%d): ", Abc_ObjName(pNode), pSymms->nSymms ); Ntk_NetworkSymmsPrint( pNtk, pSymms ); } //Extra_SymmPairsPrint( pSymms ); Extra_SymmPairsDissolve( pSymms ); }
/**Function************************************************************* Synopsis [Writes the graph structure of AIG in GML.] Description [Useful for graph visualization using tools such as yEd: http://www.yworks.com/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteGml( Abc_Ntk_t * pNtk, char * pFileName ) { FILE * pFile; Abc_Obj_t * pObj, * pFanin; int i, k; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); // start the output stream pFile = fopen( pFileName, "w" ); if ( pFile == NULL ) { fprintf( stdout, "Io_WriteGml(): Cannot open the output file \"%s\".\n", pFileName ); return; } fprintf( pFile, "# GML for \"%s\" written by ABC on %s\n", pNtk->pName, Extra_TimeStamp() ); fprintf( pFile, "graph [\n" ); // output the POs fprintf( pFile, "\n" ); Abc_NtkForEachPo( pNtk, pObj, i ) { fprintf( pFile, " node [ id %5d label \"%s\"\n", pObj->Id, Abc_ObjName(pObj) ); fprintf( pFile, " graphics [ type \"triangle\" fill \"#00FFFF\" ]\n" ); // blue fprintf( pFile, " ]\n" ); }
/**Function************************************************************* Synopsis [Transform the logic network into a netlist.] Description [The logic network given to this procedure should have exactly the same structure as the resulting netlist. The COs can only point to CIs if they have identical names. Otherwise, they should have a node between them, even if this node is inverter or buffer.] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk ) { Abc_Ntk_t * pNtkNew; Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin; int i, k; assert( Abc_NtkIsLogic(pNtk) ); // remove dangling nodes Abc_NtkCleanup( pNtk, 0 ); // make sure the CO names are unique Abc_NtkCheckUniqueCiNames( pNtk ); Abc_NtkCheckUniqueCoNames( pNtk ); Abc_NtkCheckUniqueCioNames( pNtk ); // assert( Abc_NtkLogicHasSimpleCos(pNtk) ); if ( !Abc_NtkLogicHasSimpleCos(pNtk) ) { printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" ); Abc_NtkLogicMakeSimpleCos( pNtk, 0 ); } // start the netlist by creating PI/PO/Latch objects pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc ); // create the CI nets and remember them in the new CI nodes Abc_NtkForEachCi( pNtk, pObj, i ) { pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; }
static char * retrieveLOName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot, Vec_Ptr_t *vLive, Vec_Ptr_t * vFair ) { Aig_Obj_t *pObjOld, *pObj; Abc_Obj_t *pNode; int index, oldIndex, originalLatchNum = Saig_ManRegNum(pAigOld), strMatch, i; char *dummyStr = (char *)malloc( sizeof(char) * 50 ); assert( Saig_ObjIsLo( pAigNew, pObjPivot ) ); Saig_ManForEachLo( pAigNew, pObj, index ) if( pObj == pObjPivot ) break; if( index < originalLatchNum ) { oldIndex = Saig_ManPiNum( pAigOld ) + index; pObjOld = Aig_ManPi( pAigOld, oldIndex ); pNode = Abc_NtkCi( pNtkOld, oldIndex ); assert( pObjOld->pData == pObjPivot ); return Abc_ObjName( pNode ); } else if( index == originalLatchNum ) return "SAVED_LO"; else if( index > originalLatchNum && index < 2 * originalLatchNum + 1 ) { oldIndex = Saig_ManPiNum( pAigOld ) + index - originalLatchNum - 1; pObjOld = Aig_ManPi( pAigOld, oldIndex ); pNode = Abc_NtkCi( pNtkOld, oldIndex ); sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "SHADOW"); return dummyStr; } else if( index >= 2 * originalLatchNum + 1 && index < 2 * originalLatchNum + 1 + Vec_PtrSize( vLive ) ) { oldIndex = index - 2 * originalLatchNum - 1; strMatch = 0; Saig_ManForEachPo( pAigOld, pObj, i ) { pNode = Abc_NtkPo( pNtkOld, i ); if( strstr( Abc_ObjName( pNode ), "assert_fair" ) != NULL ) { if( strMatch == oldIndex ) { sprintf( dummyStr, "%s__%s", Abc_ObjName( pNode ), "LIVENESS"); return dummyStr; } else strMatch++; } }
/**Function************************************************************* Synopsis [Assigns name with index.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static inline void Abc_NtkConvertAssignName( Abc_Obj_t * pObj, Abc_Obj_t * pNet, int Index ) { char Suffix[16]; assert( Abc_ObjIsTerm(pObj) ); assert( Abc_ObjIsNet(pNet) ); sprintf( Suffix, "[%d]", Index ); Abc_ObjAssignName( pObj, Abc_ObjName(pNet), Suffix ); }
/**Function************************************************************* Synopsis [Tranfers names to the old network.] Description [Assumes that the new nodes are attached using pObj->pCopy.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkTrasferNames( 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( Abc_NtkBoxNum(pNtk) == Abc_NtkBoxNum(pNtkNew) ); assert( Nm_ManNumEntries(pNtk->pManName) > 0 ); assert( Nm_ManNumEntries(pNtkNew->pManName) == 0 ); // copy the CI/CO/box names Abc_NtkForEachCi( pNtk, pObj, i ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0Ntk(pObj)), NULL ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanin0Ntk(pObj)), NULL ); Abc_NtkForEachBox( pNtk, pObj, i ) Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL ); }
// create the missing nets Abc_NtkForEachNode( pNtk, pObj, i ) { if ( pObj->pCopy->pCopy ) // the net of the new object is already created continue; // create the new net pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create ridiculous names net line "n48", where 48 is the ID of the node Abc_ObjAddFanin( pNet, pObj->pCopy ); pObj->pCopy->pCopy = pNet; }
/**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 ); }
/**Function************************************************************* Synopsis [Gets fanin node names.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Abc_NodeGetFaninNames( Abc_Obj_t * pNode ) { Vec_Ptr_t * vNodes; Abc_Obj_t * pFanin; int i; vNodes = Vec_PtrAlloc( 100 ); Abc_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, Abc_UtilStrsav(Abc_ObjName(pFanin)) ); return vNodes; }
/**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 [Prints PIs/POs and LIs/LOs.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkPrintIo( FILE * pFile, Abc_Ntk_t * pNtk ) { Abc_Obj_t * pObj; int i; fprintf( pFile, "Primary inputs (%d): ", Abc_NtkPiNum(pNtk) ); Abc_NtkForEachPi( pNtk, pObj, i ) fprintf( pFile, " %s", Abc_ObjName(pObj) ); // fprintf( pFile, " %s(%d)", Abc_ObjName(pObj), Abc_ObjFanoutNum(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, "Primary outputs (%d):", Abc_NtkPoNum(pNtk) ); Abc_NtkForEachPo( pNtk, pObj, i ) fprintf( pFile, " %s", Abc_ObjName(pObj) ); fprintf( pFile, "\n" ); fprintf( pFile, "Latches (%d): ", Abc_NtkLatchNum(pNtk) ); Abc_NtkForEachLatch( pNtk, pObj, i ) fprintf( pFile, " %s(%s=%s)", Abc_ObjName(pObj), Abc_ObjName(Abc_ObjFanout0(pObj)), Abc_ObjName(Abc_ObjFanin0(pObj)) ); fprintf( pFile, "\n" ); }
/**Function************************************************************* Synopsis [Replaces a fanin of the node.] Description [The node is pObj. An old fanin of this node (pFaninOld) has to be replaced by a new fanin (pFaninNew). Assumes that the node and the old fanin are not complemented. The new fanin can be complemented. In this case, the polarity of the new fanin will change, compared to the polarity of the old fanin.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_ObjPatchFanin( Abc_Obj_t * pObj, Abc_Obj_t * pFaninOld, Abc_Obj_t * pFaninNew ) { Abc_Obj_t * pFaninNewR = Abc_ObjRegular(pFaninNew); int iFanin;//, nLats;//, fCompl; assert( !Abc_ObjIsComplement(pObj) ); assert( !Abc_ObjIsComplement(pFaninOld) ); assert( pFaninOld != pFaninNewR ); // assert( pObj != pFaninOld ); // assert( pObj != pFaninNewR ); assert( pObj->pNtk == pFaninOld->pNtk ); assert( pObj->pNtk == pFaninNewR->pNtk ); if ( (iFanin = Vec_IntFind( &pObj->vFanins, pFaninOld->Id )) == -1 ) { printf( "Node %s is not among", Abc_ObjName(pFaninOld) ); printf( " the fanins of node %s...\n", Abc_ObjName(pObj) ); return; } // remember the attributes of the old fanin // fCompl = Abc_ObjFaninC(pObj, iFanin); // replace the old fanin entry by the new fanin entry (removes attributes) Vec_IntWriteEntry( &pObj->vFanins, iFanin, pFaninNewR->Id ); // set the attributes of the new fanin // if ( fCompl ^ Abc_ObjIsComplement(pFaninNew) ) // Abc_ObjSetFaninC( pObj, iFanin ); if ( Abc_ObjIsComplement(pFaninNew) ) Abc_ObjXorFaninC( pObj, iFanin ); // if ( Abc_NtkIsSeq(pObj->pNtk) && (nLats = Seq_ObjFaninL(pObj, iFanin)) ) // Seq_ObjSetFaninL( pObj, iFanin, nLats ); // update the fanout of the fanin if ( !Vec_IntRemove( &pFaninOld->vFanouts, pObj->Id ) ) { printf( "Node %s is not among", Abc_ObjName(pObj) ); printf( " the fanouts of its old fanin %s...\n", Abc_ObjName(pFaninOld) ); // return; } Vec_IntPushMem( pObj->pNtk->pMmStep, &pFaninNewR->vFanouts, pObj->Id ); }
/**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 [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 [Visualizes a reconvergence driven cut at the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NodeShowCut( Abc_Obj_t * pNode, int nNodeSizeMax, int nConeSizeMax ) { FILE * pFile; char FileNameDot[200]; Abc_ManCut_t * p; Vec_Ptr_t * vCutSmall; Vec_Ptr_t * vCutLarge; Vec_Ptr_t * vInside; Vec_Ptr_t * vNodesTfo; Abc_Obj_t * pTemp; int i; assert( Abc_NtkIsStrash(pNode->pNtk) ); // start the cut computation manager p = Abc_NtkManCutStart( nNodeSizeMax, nConeSizeMax, 2, ABC_INFINITY ); // get the recovergence driven cut vCutSmall = Abc_NodeFindCut( p, pNode, 1 ); // get the containing cut vCutLarge = Abc_NtkManCutReadCutLarge( p ); // get the array for the inside nodes vInside = Abc_NtkManCutReadVisited( p ); // get the inside nodes of the containing cone Abc_NodeConeCollect( &pNode, 1, vCutLarge, vInside, 1 ); // add the nodes in the TFO vNodesTfo = Abc_NodeCollectTfoCands( p, pNode, vCutSmall, ABC_INFINITY ); Vec_PtrForEachEntry( vNodesTfo, pTemp, i ) Vec_PtrPushUnique( vInside, pTemp ); // create the file name Abc_ShowGetFileName( Abc_ObjName(pNode), FileNameDot ); // check that the file can be opened if ( (pFile = fopen( FileNameDot, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", FileNameDot ); return; } // add the root node to the cone (for visualization) Vec_PtrPush( vCutSmall, pNode ); // write the DOT file Io_WriteDotNtk( pNode->pNtk, vInside, vCutSmall, FileNameDot, 0, 0 ); // stop the cut computation manager Abc_NtkManCutStop( p ); // visualize the file Abc_ShowFile( FileNameDot ); }
Aig_Obj_t *readTargetPinSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk) { Aig_Obj_t *pObj; int i; Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "0Liveness_" ) != NULL ) { //return Aig_ObjFanin0(pObj); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } } return NULL; }
/**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 ); }
Aig_Obj_t *readTargetPoutSignal(Aig_Man_t *pAig, Abc_Ntk_t *pNtk, int nonFirstIteration) { Aig_Obj_t *pObj; int i; if( nonFirstIteration == 0 ) return NULL; else Saig_ManForEachPo( pAig, pObj, i ) { if( strstr( Abc_ObjName(Abc_NtkPo( pNtk, i )), "kLiveness_" ) != NULL ) { //return Aig_ObjFanin0(pObj); return Aig_NotCond((Aig_Obj_t *)Aig_ObjFanin0(pObj), Aig_ObjFaninC0(pObj)); } } return NULL; }
static char * retrieveTruePiName( Abc_Ntk_t *pNtkOld, Aig_Man_t *pAigOld, Aig_Man_t *pAigNew, Aig_Obj_t *pObjPivot ) { Aig_Obj_t *pObjOld, *pObj; Abc_Obj_t *pNode; int index; assert( Saig_ObjIsPi( pAigNew, pObjPivot ) ); Aig_ManForEachPi( pAigNew, pObj, index ) if( pObj == pObjPivot ) break; assert( index < Aig_ManPiNum( pAigNew ) - Aig_ManRegNum( pAigNew ) ); if( index == Saig_ManPiNum( pAigNew ) - 1 ) return "SAVE_BIERE"; else { pObjOld = Aig_ManPi( pAigOld, index ); pNode = Abc_NtkPi( pNtkOld, index ); assert( pObjOld->pData == pObjPivot ); return Abc_ObjName( pNode ); } }
/**Function************************************************************* Synopsis [Reorders BDDs of the local functions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkBddReorder( Abc_Ntk_t * pNtk, int fVerbose ) { reo_man * p; Abc_Obj_t * pNode; int i; Abc_NtkRemoveDupFanins( pNtk ); Abc_NtkMinimumBase( pNtk ); p = Extra_ReorderInit( Abc_NtkGetFaninMax(pNtk), 100 ); Abc_NtkForEachNode( pNtk, pNode, i ) { if ( Abc_ObjFaninNum(pNode) < 3 ) continue; if ( fVerbose ) fprintf( stdout, "%10s: ", Abc_ObjName(pNode) ); if ( fVerbose ) fprintf( stdout, "Before = %5d BDD nodes. ", Cudd_DagSize((DdNode *)pNode->pData) ); Abc_NodeBddReorder( p, pNode ); if ( fVerbose ) fprintf( stdout, "After = %5d BDD nodes.\n", Cudd_DagSize((DdNode *)pNode->pData) ); } Extra_ReorderQuit( p ); }
char ** Abc_NtkCollectCioNames( Abc_Ntk_t * pNtk, int fCollectCos ) { Abc_Obj_t * pObj; char ** ppNames; int i; if ( fCollectCos ) { ppNames = ABC_ALLOC( char *, Abc_NtkCoNum(pNtk) ); Abc_NtkForEachCo( pNtk, pObj, i ) ppNames[i] = Abc_ObjName(pObj); } else { ppNames = ABC_ALLOC( char *, Abc_NtkCiNum(pNtk) ); Abc_NtkForEachCi( pNtk, pObj, i ) ppNames[i] = Abc_ObjName(pObj); } return ppNames; } /**Function************************************************************* Synopsis [Orders PIs/POs/latches alphabetically.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/
/**Function************************************************************* Synopsis [Appends suffic to the name.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjNameSuffix( Abc_Obj_t * pObj, char * pSuffix ) { static char Buffer[2000]; sprintf( Buffer, "%s%s", Abc_ObjName(pObj), pSuffix ); return Buffer; }
/**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; }
/**Function************************************************************* Synopsis [Appends name to the prefix] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ char * Abc_ObjNamePrefix( Abc_Obj_t * pObj, char * pPrefix ) { static char Buffer[2000]; sprintf( Buffer, "%s%s", pPrefix, Abc_ObjName(pObj) ); return Buffer; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkNames( Io_ReadBlif_t * p, Vec_Ptr_t ** pvTokens ) { Vec_Ptr_t * vTokens = *pvTokens; Abc_Ntk_t * pNtk = p->pNtkCur; Abc_Obj_t * pNode; char * pToken, Char, ** ppNames; int nFanins, nNames; // create a new node and add it to the network if ( vTokens->nSize < 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .names line has less than two tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the node ppNames = (char **)vTokens->pArray + 1; nNames = vTokens->nSize - 2; pNode = Io_ReadCreateNode( pNtk, ppNames[nNames], ppNames, nNames ); // derive the functionality of the node p->vCubes->nSize = 0; nFanins = vTokens->nSize - 2; if ( nFanins == 0 ) { while ( (vTokens = Io_ReadBlifGetTokens(p)) ) { pToken = (char *)vTokens->pArray[0]; if ( pToken[0] == '.' ) break; // read the cube if ( vTokens->nSize != 1 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of tokens in the constant cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the cube Char = ((char *)vTokens->pArray[0])[0]; Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, Char ); Vec_StrPush( p->vCubes, '\n' ); } } else { while ( (vTokens = Io_ReadBlifGetTokens(p)) ) { pToken = (char *)vTokens->pArray[0]; if ( pToken[0] == '.' ) break; // read the cube if ( vTokens->nSize != 2 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of tokens in the cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // create the cube Vec_StrPrintStr( p->vCubes, (char *)vTokens->pArray[0] ); // check the char Char = ((char *)vTokens->pArray[1])[0]; if ( Char != '0' && Char != '1' && Char != 'x' && Char != 'n' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The output character in the constant cube is wrong." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, Char ); Vec_StrPush( p->vCubes, '\n' ); } } // if there is nothing there if ( p->vCubes->nSize == 0 ) { // create an empty cube Vec_StrPush( p->vCubes, ' ' ); Vec_StrPush( p->vCubes, '0' ); Vec_StrPush( p->vCubes, '\n' ); } Vec_StrPush( p->vCubes, 0 ); // set the pointer to the functionality of the node Abc_ObjSetData( pNode, Abc_SopRegister((Mem_Flex_t *)pNtk->pManFunc, p->vCubes->pArray) ); // check the size if ( Abc_ObjFaninNum(pNode) != Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The number of fanins (%d) of node %s is different from SOP size (%d).", Abc_ObjFaninNum(pNode), Abc_ObjName(Abc_ObjFanout(pNode,0)), Abc_SopGetVarNum((char *)Abc_ObjData(pNode)) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // return the last array of tokens *pvTokens = vTokens; return 0; }