/**Function************************************************************* Synopsis [Allocates additional memory for the nodes.] Description [Allocates IVY_PAGE_SIZE nodes. Aligns memory by 32 bytes. Records the pointer to the AIG manager in the -1 entry.] SideEffects [] SeeAlso [] ***********************************************************************/ void Ivy_ManAddMemory( Ivy_Man_t * p ) { char * pMemory; int i, nBytes; int EntrySizeMax = 128; assert( sizeof(Ivy_Obj_t) <= EntrySizeMax ); assert( p->pListFree == NULL ); // assert( (Ivy_ManObjNum(p) & IVY_PAGE_MASK) == 0 ); // allocate new memory page nBytes = sizeof(Ivy_Obj_t) * (1<<IVY_PAGE_SIZE) + EntrySizeMax; pMemory = ALLOC( char, nBytes ); Vec_PtrPush( p->vChunks, pMemory ); // align memory at the 32-byte boundary pMemory = pMemory + EntrySizeMax - (((int)pMemory) & (EntrySizeMax-1)); // remember the manager in the first entry Vec_PtrPush( p->vPages, pMemory ); // break the memory down into nodes p->pListFree = (Ivy_Obj_t *)pMemory; for ( i = 1; i <= IVY_PAGE_MASK; i++ ) { *((char **)pMemory) = pMemory + sizeof(Ivy_Obj_t); pMemory += sizeof(Ivy_Obj_t); } *((char **)pMemory) = NULL; }
/**Function************************************************************* Synopsis [Writes reached state BDD into a BLIF file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Llb_ManDumpReached( DdManager * ddG, DdNode * bReached, char * pModel, char * pFileName ) { FILE * pFile; Vec_Ptr_t * vNamesIn, * vNamesOut; char * pName; int i, nDigits; // reorder the BDD Cudd_ReduceHeap( ddG, CUDD_REORDER_SYMM_SIFT, 1 ); // create input names nDigits = Extra_Base10Log( Cudd_ReadSize(ddG) ); vNamesIn = Vec_PtrAlloc( Cudd_ReadSize(ddG) ); for ( i = 0; i < Cudd_ReadSize(ddG); i++ ) { pName = Llb_ManGetDummyName( "ff", i, nDigits ); Vec_PtrPush( vNamesIn, Extra_UtilStrsav(pName) ); } // create output names vNamesOut = Vec_PtrAlloc( 1 ); Vec_PtrPush( vNamesOut, Extra_UtilStrsav("Reached") ); // write the file pFile = fopen( pFileName, "wb" ); Cudd_DumpBlif( ddG, 1, &bReached, (char **)Vec_PtrArray(vNamesIn), (char **)Vec_PtrArray(vNamesOut), pModel, pFile, 0 ); fclose( pFile ); // cleanup Vec_PtrForEachEntry( char *, vNamesIn, pName, i ) ABC_FREE( pName ); Vec_PtrForEachEntry( char *, vNamesOut, pName, i ) ABC_FREE( pName ); Vec_PtrFree( vNamesIn ); Vec_PtrFree( vNamesOut ); }
/**Function************************************************************* Synopsis [Computes supports of the partitions.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ImgSupports( Aig_Man_t * p, Vec_Ptr_t * vDdMans, Vec_Int_t * vStart, Vec_Int_t * vStop, int fAddPis, int fVerbose ) { Vec_Ptr_t * vSupps; Vec_Int_t * vOne; Aig_Obj_t * pObj; DdManager * dd; DdNode * bSupp, * bTemp; int i, Entry, nSize; nSize = Cudd_ReadSize( (DdManager *)Vec_PtrEntry( vDdMans, 0 ) ); vSupps = Vec_PtrAlloc( 100 ); // create initial vOne = Vec_IntStart( nSize ); Vec_IntForEachEntry( vStart, Entry, i ) Vec_IntWriteEntry( vOne, Entry, 1 ); Vec_PtrPush( vSupps, vOne ); // create intermediate Vec_PtrForEachEntry( DdManager *, vDdMans, dd, i ) { vOne = Vec_IntStart( nSize ); bSupp = Cudd_Support( dd, dd->bFunc ); Cudd_Ref( bSupp ); for ( bTemp = bSupp; bTemp != Cudd_ReadOne(dd); bTemp = cuddT(bTemp) ) Vec_IntWriteEntry( vOne, bTemp->index, 1 ); Cudd_RecursiveDeref( dd, bSupp ); Vec_PtrPush( vSupps, vOne ); }
/**Function************************************************************* Synopsis [Gets the tokens taking into account the line breaks.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Io_ReadBlifGetTokens( Io_ReadBlif_t * p ) { Vec_Ptr_t * vTokens; char * pLastToken; int i; // get rid of the old tokens if ( p->vNewTokens->nSize > 0 ) { for ( i = 0; i < p->vNewTokens->nSize; i++ ) ABC_FREE( p->vNewTokens->pArray[i] ); p->vNewTokens->nSize = 0; } // get the new tokens vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader); if ( vTokens == NULL ) return vTokens; // check if there is a transfer to another line pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1]; if ( pLastToken[ strlen(pLastToken)-1 ] != '\\' ) return vTokens; // remove the slash pLastToken[ strlen(pLastToken)-1 ] = 0; if ( pLastToken[0] == 0 ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); // load as long as there is the line break while ( 1 ) { // get the new tokens vTokens = (Vec_Ptr_t *)Extra_FileReaderGetTokens(p->pReader); if ( vTokens->nSize == 0 ) return p->vNewTokens; // check if there is a transfer to another line pLastToken = (char *)vTokens->pArray[vTokens->nSize - 1]; if ( pLastToken[ strlen(pLastToken)-1 ] == '\\' ) { // remove the slash pLastToken[ strlen(pLastToken)-1 ] = 0; if ( pLastToken[0] == 0 ) vTokens->nSize--; // load them into the new array for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); continue; } // otherwise, load them and break for ( i = 0; i < vTokens->nSize; i++ ) Vec_PtrPush( p->vNewTokens, Extra_UtilStrsav((char *)vTokens->pArray[i]) ); break; } return p->vNewTokens; }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifReorderFormalNames( Vec_Ptr_t * vTokens, Mio_Gate_t * pGate ) { Mio_Pin_t * pGatePin; char * pName, * pNamePin; int i, k, nSize, Length; nSize = Vec_PtrSize(vTokens); if ( nSize - 3 != Mio_GateReadInputs(pGate) ) return 0; // check if the names are in order for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); pName = (char *)Vec_PtrEntry(vTokens, i+2); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) continue; break; } if ( i == nSize - 3 ) return 1; // reorder the pins for ( pGatePin = Mio_GateReadPins(pGate), i = 0; pGatePin; pGatePin = Mio_PinReadNext(pGatePin), i++ ) { pNamePin = Mio_PinReadName(pGatePin); Length = strlen(pNamePin); for ( k = 2; k < nSize; k++ ) { pName = (char *)Vec_PtrEntry(vTokens, k); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { Vec_PtrPush( vTokens, pName ); break; } } } pNamePin = Mio_GateReadOutName(pGate); Length = strlen(pNamePin); for ( k = 2; k < nSize; k++ ) { pName = (char *)Vec_PtrEntry(vTokens, k); if ( !strncmp( pNamePin, pName, Length ) && pName[Length] == '=' ) { Vec_PtrPush( vTokens, pName ); break; } } if ( Vec_PtrSize(vTokens) - nSize != nSize - 2 ) return 0; Vec_PtrForEachEntryStart( char *, vTokens, pName, k, nSize ) Vec_PtrWriteEntry( vTokens, k - nSize + 2, pName ); Vec_PtrShrink( vTokens, nSize ); return 1; }
/**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 [Reproduces script "compress2".] Description [Takes AIG manager, consumes it, and produces GIA manager.] SideEffects [] SeeAlso [] ***********************************************************************/ Gia_Man_t * Dar_NewChoiceSynthesis( Aig_Man_t * pAig, int fBalance, int fUpdateLevel, int fPower, int fLightSynth, int fVerbose ) //alias resyn "b; rw; rwz; b; rwz; b" //alias resyn2 "b; rw; rf; b; rw; rwz; b; rfz; rwz; b" { Vec_Ptr_t * vGias; Gia_Man_t * pGia, * pTemp; int i; if ( fUpdateLevel && Dar_NewChoiceSynthesisGuard(pAig) ) { if ( fVerbose ) printf( "Warning: Due to high fanout count of some nodes, level updating is disabled.\n" ); fUpdateLevel = 0; } vGias = Vec_PtrAlloc( 3 ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); pAig = Dar_NewCompress( pAig, fBalance, fUpdateLevel, fPower, fVerbose ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); //Aig_ManPrintStats( pAig ); pAig = Dar_NewCompress2( pAig, fBalance, fUpdateLevel, 1, fPower, fLightSynth, fVerbose ); pGia = Gia_ManFromAig(pAig); Vec_PtrPush( vGias, pGia ); //Aig_ManPrintStats( pAig ); Aig_ManStop( pAig ); // swap around the first and the last pTemp = (Gia_Man_t *)Vec_PtrPop( vGias ); Vec_PtrPush( vGias, Vec_PtrEntry(vGias,0) ); Vec_PtrWriteEntry( vGias, 0, pTemp ); // Aig_Man_t * pAig; // int i; // printf( "Choicing will be performed with %d AIGs:\n", Vec_PtrSize(p->vAigs) ); // Vec_PtrForEachEntry( Aig_Man_t *, p->vAigs, pAig, i ) // Aig_ManPrintStats( pAig ); // derive the miter pGia = Gia_ManChoiceMiter( vGias ); // cleanup Vec_PtrForEachEntry( Gia_Man_t *, vGias, pTemp, i ) Gia_ManStop( pTemp ); Vec_PtrFree( vGias ); return pGia; }
// NOTE: leaves won't be collected // nodes will be collected in dfs order void Mig_CollectNodes( Mig_Man_t * pMan, Mig_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Mig_ObjSetTravIdCurrent( pMan, pNode ); if( Mig_ObjIsPi(pNode) || Mig_ObjIsConst(pNode) ) { Vec_PtrPush( vNodes, pNode ); return; } assert( Mig_ObjIsNode(pNode) ); if( !Mig_ObjIsTravIdCurrent( pMan, Mig_Regular(pNode->pFanin0) ) ) Mig_CollectNodes( pMan, Mig_Regular(pNode->pFanin0), vNodes ); if( !Mig_ObjIsTravIdCurrent( pMan, Mig_Regular(pNode->pFanin1) ) ) Mig_CollectNodes( pMan, Mig_Regular(pNode->pFanin1), vNodes ); if( !Mig_ObjIsTravIdCurrent( pMan, Mig_Regular(pNode->pFanin2) ) ) Mig_CollectNodes( pMan, Mig_Regular(pNode->pFanin2), vNodes ); Vec_PtrPush( vNodes, pNode ); }
/**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 [Reading library from file.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ static void Abc_SclReadSurface( Vec_Str_t * vOut, int * pPos, SC_Surface * p ) { Vec_Flt_t * vVec; int i, j; for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) Vec_FltPush( p->vIndex0, Vec_StrGetF(vOut, pPos) ); for ( i = Vec_StrGetI(vOut, pPos); i != 0; i-- ) Vec_FltPush( p->vIndex1, Vec_StrGetF(vOut, pPos) ); for ( i = 0; i < Vec_FltSize(p->vIndex0); i++ ) { vVec = Vec_FltAlloc( Vec_FltSize(p->vIndex1) ); Vec_PtrPush( p->vData, vVec ); for ( j = 0; j < Vec_FltSize(p->vIndex1); j++ ) Vec_FltPush( vVec, Vec_StrGetF(vOut, pPos) ); } for ( i = 0; i < 3; i++ ) p->approx[0][i] = Vec_StrGetF( vOut, pPos ); for ( i = 0; i < 4; i++ ) p->approx[1][i] = Vec_StrGetF( vOut, pPos ); for ( i = 0; i < 6; i++ ) p->approx[2][i] = Vec_StrGetF( vOut, pPos ); }
/**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwr_Node_t * Rwr_ManAddNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) { Rwr_Node_t * pNew; unsigned uTruth; // compute truth table, leve, volume p->nConsidered++; if ( fExor ) uTruth = (p0->uTruth ^ p1->uTruth); else uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; // create the new node pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = Level; pNew->Volume = Volume; pNew->fUsed = 0; pNew->fExor = fExor; pNew->p0 = p0; pNew->p1 = p1; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); // do not add if the node is not essential if ( uTruth != p->puCanons[uTruth] ) return pNew; // add to the list p->nAdded++; if ( p->pTable[uTruth] == NULL ) p->nClasses++; Rwr_ListAddToTail( p->pTable + uTruth, pNew ); return pNew; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects internal nodes in the DFS order.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Hop_ManDfs_rec( Hop_Obj_t * pObj, Vec_Ptr_t * vNodes ) { assert( !Hop_IsComplement(pObj) ); if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) ) return; Hop_ManDfs_rec( Hop_ObjFanin0(pObj), vNodes ); Hop_ManDfs_rec( Hop_ObjFanin1(pObj), vNodes ); assert( !Hop_ObjIsMarkA(pObj) ); // loop detection Hop_ObjSetMarkA(pObj); Vec_PtrPush( vNodes, pObj ); }
/**Function************************************************************* Synopsis [Performs the operation on the top entries in the stack.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Ver_FormulaParserTopOper( Hop_Man_t * pMan, Vec_Ptr_t * vStackFn, int Oper ) { Hop_Obj_t * bArg0, * bArg1, * bArg2, * bFunc; // perform the given operation bArg2 = (Hop_Obj_t *)Vec_PtrPop( vStackFn ); bArg1 = (Hop_Obj_t *)Vec_PtrPop( vStackFn ); if ( Oper == VER_PARSE_OPER_AND ) bFunc = Hop_And( pMan, bArg1, bArg2 ); else if ( Oper == VER_PARSE_OPER_XOR ) bFunc = Hop_Exor( pMan, bArg1, bArg2 ); else if ( Oper == VER_PARSE_OPER_OR ) bFunc = Hop_Or( pMan, bArg1, bArg2 ); else if ( Oper == VER_PARSE_OPER_EQU ) bFunc = Hop_Not( Hop_Exor( pMan, bArg1, bArg2 ) ); else if ( Oper == VER_PARSE_OPER_MUX ) { bArg0 = (Hop_Obj_t *)Vec_PtrPop( vStackFn ); // bFunc = Cudd_bddIte( dd, bArg0, bArg1, bArg2 ); Cudd_Ref( bFunc ); bFunc = Hop_Mux( pMan, bArg0, bArg1, bArg2 ); // Cudd_RecursiveDeref( dd, bArg0 ); // Cudd_Deref( bFunc ); } else return NULL; // Cudd_Ref( bFunc ); // Cudd_RecursiveDeref( dd, bArg1 ); // Cudd_RecursiveDeref( dd, bArg2 ); Vec_PtrPush( vStackFn, bFunc ); return bFunc; }
/**Function************************************************************* Synopsis [Returns the array of nodes to be combined into one multi-input AND-gate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Abc_NtkCollectSupergate_rec( Abc_Obj_t * pNode, Vec_Ptr_t * vSuper, int fFirst, int fStopAtMux ) { int RetValue1, RetValue2, i; // check if the node is visited if ( Abc_ObjRegular(pNode)->fMarkB ) { // check if the node occurs in the same polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == pNode ) return 1; // check if the node is present in the opposite polarity for ( i = 0; i < vSuper->nSize; i++ ) if ( vSuper->pArray[i] == Abc_ObjNot(pNode) ) return -1; assert( 0 ); return 0; } // if the new node is complemented or a PI, another gate begins if ( !fFirst ) if ( Abc_ObjIsComplement(pNode) || !Abc_ObjIsNode(pNode) || Abc_ObjFanoutNum(pNode) > 1 || (fStopAtMux && Abc_NodeIsMuxType(pNode)) ) { Vec_PtrPush( vSuper, pNode ); Abc_ObjRegular(pNode)->fMarkB = 1; return 0; } assert( !Abc_ObjIsComplement(pNode) ); assert( Abc_ObjIsNode(pNode) ); // go through the branches RetValue1 = Abc_NtkCollectSupergate_rec( Abc_ObjChild0(pNode), vSuper, 0, fStopAtMux ); RetValue2 = Abc_NtkCollectSupergate_rec( Abc_ObjChild1(pNode), vSuper, 0, fStopAtMux ); if ( RetValue1 == -1 || RetValue2 == -1 ) return -1; // return 1 if at least one branch has a duplicate return RetValue1 || RetValue2; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [Collects fanins of the node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Nwk_ObjCollectFanins( Nwk_Obj_t * pNode, Vec_Ptr_t * vNodes ) { Nwk_Obj_t * pFanin; int i; Vec_PtrClear(vNodes); Nwk_ObjForEachFanin( pNode, pFanin, i ) Vec_PtrPush( vNodes, pFanin ); }
/**Function************************************************************* Synopsis [Selects gates useful for area-only mapping.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Amap_LibSelectGates( Amap_Lib_t * p, int fVerbose ) { Vec_Ptr_t * vSelect; Amap_Gat_t * pGate, * pGate2; int i, k;//, clk = Abc_Clock(); p->pGate0 = Amap_LibFindGate( p, 0 ); p->pGate1 = Amap_LibFindGate( p, ~0 ); p->pGateBuf = Amap_LibFindGate( p, 0xAAAAAAAA ); p->pGateInv = Amap_LibFindGate( p, ~0xAAAAAAAA ); vSelect = Vec_PtrAlloc( 100 ); Vec_PtrForEachEntry( Amap_Gat_t *, p->vSorted, pGate, i ) { if ( pGate->pFunc == NULL || pGate->pTwin != NULL ) continue; Vec_PtrForEachEntryStop( Amap_Gat_t *, p->vSorted, pGate2, k, i ) { if ( pGate2->pFunc == NULL || pGate2->pTwin != NULL ) continue; if ( pGate2->nPins != pGate->nPins ) continue; if ( !memcmp( pGate2->pFunc, pGate->pFunc, sizeof(unsigned) * Abc_TruthWordNum(pGate->nPins) ) ) break; } if ( k < i ) continue; Vec_PtrPush( vSelect, pGate ); } return vSelect; }
/**Function************************************************************* Synopsis [Creates the new timing box.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Aig_TManCreateBox( Aig_TMan_t * p, int * pPis, int nPis, int * pPos, int nPos, float * pPiTimes, float * pPoTimes ) { Aig_TBox_t * pBox; int i; pBox = (Aig_TBox_t *)Aig_MmFlexEntryFetch( p->pMemObj, sizeof(Aig_TBox_t) + sizeof(int) * (nPis+nPos) ); memset( pBox, 0, sizeof(Aig_TBox_t) ); pBox->iBox = Vec_PtrSize( p->vBoxes ); Vec_PtrPush( p->vBoxes, pBox ); pBox->nInputs = nPis; pBox->nOutputs = nPos; for ( i = 0; i < nPis; i++ ) { assert( pPis[i] < p->nPis ); pBox->Inouts[i] = pPis[i]; Aig_TManSetPiArrival( p, pPis[i], pPiTimes[i] ); p->pPis[pPis[i]].iObj2Box = pBox->iBox; } for ( i = 0; i < nPos; i++ ) { assert( pPos[i] < p->nPos ); pBox->Inouts[nPis+i] = pPos[i]; Aig_TManSetPoRequired( p, pPos[i], pPoTimes[i] ); p->pPos[pPos[i]].iObj2Box = pBox->iBox; } }
/**Function************************************************************* Synopsis [Builds implication supergate.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Obj_t * Dar_BalanceBuildSuperTop( Aig_Man_t * p, Vec_Ptr_t * vSuper, Aig_Type_t Type, int fUpdateLevel, int nLutSize ) { Vec_Ptr_t * vSubset; Aig_Obj_t * pObj; int i, nBaseSizeAll, nBaseSize; assert( vSuper->nSize > 1 ); // sort the new nodes by level in the decreasing order Vec_PtrSort( vSuper, (int (*)(void))Aig_NodeCompareLevelsDecrease ); // add one LUT at a time while ( Vec_PtrSize(vSuper) > 1 ) { // isolate the group of nodes with nLutSize inputs nBaseSizeAll = 0; vSubset = Vec_PtrAlloc( nLutSize ); Vec_PtrForEachEntryReverse( Aig_Obj_t *, vSuper, pObj, i ) { nBaseSize = Aig_BaseSize( p, pObj, nLutSize ); if ( nBaseSizeAll + nBaseSize > nLutSize && Vec_PtrSize(vSubset) > 1 ) break; nBaseSizeAll += nBaseSize; Vec_PtrPush( vSubset, pObj ); } // remove them from vSuper Vec_PtrShrink( vSuper, Vec_PtrSize(vSuper) - Vec_PtrSize(vSubset) ); // create the new supergate pObj = Dar_BalanceBuildSuper( p, vSubset, Type, fUpdateLevel ); Vec_PtrFree( vSubset ); // add the new output Dar_BalancePushUniqueOrderByLevel( vSuper, pObj, Type == AIG_OBJ_EXOR ); }
/**Function************************************************************* Synopsis [Recursively derives local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int If_ManNodeShapeMap_rec( If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited, Vec_Int_t * vShape ) { If_Cut_t * pCut; If_Obj_t * pTemp; int i, iFunc0, iFunc1; // get the best cut pCut = If_ObjCutBest(pIfObj); // if the cut is visited, return the result if ( If_CutDataInt(pCut) ) return If_CutDataInt(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case If_CutSetDataInt( pCut, ~0 ); // skip in case of primary input if ( If_ObjIsCi(pIfObj) ) return If_CutDataInt(pCut); // compute the functions of the children for ( i = 0, pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv, i++ ) { iFunc0 = If_ManNodeShapeMap_rec( pIfMan, pTemp->pFanin0, vVisited, vShape ); if ( iFunc0 == ~0 ) continue; iFunc1 = If_ManNodeShapeMap_rec( pIfMan, pTemp->pFanin1, vVisited, vShape ); if ( iFunc1 == ~0 ) continue; // both branches are solved Vec_IntPush( vShape, pIfObj->Id ); Vec_IntPush( vShape, pTemp->Id ); If_CutSetDataInt( pCut, 1 ); break; } return If_CutDataInt(pCut); }
/**Function************************************************************* Synopsis [Recursively derives the local AIG for the cut.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Hop_Obj_t * Nwk_NodeIfToHop2_rec( Hop_Man_t * pHopMan, If_Man_t * pIfMan, If_Obj_t * pIfObj, Vec_Ptr_t * vVisited ) { If_Cut_t * pCut; If_Obj_t * pTemp; Hop_Obj_t * gFunc, * gFunc0, * gFunc1; // get the best cut pCut = If_ObjCutBest(pIfObj); // if the cut is visited, return the result if ( If_CutData(pCut) ) return (Hop_Obj_t *)If_CutData(pCut); // mark the node as visited Vec_PtrPush( vVisited, pCut ); // insert the worst case If_CutSetData( pCut, (void *)1 ); // skip in case of primary input if ( If_ObjIsCi(pIfObj) ) return (Hop_Obj_t *)If_CutData(pCut); // compute the functions of the children for ( pTemp = pIfObj; pTemp; pTemp = pTemp->pEquiv ) { gFunc0 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin0, vVisited ); if ( gFunc0 == (void *)1 ) continue; gFunc1 = Nwk_NodeIfToHop2_rec( pHopMan, pIfMan, pTemp->pFanin1, vVisited ); if ( gFunc1 == (void *)1 ) continue; // both branches are solved gFunc = Hop_And( pHopMan, Hop_NotCond(gFunc0, pTemp->fCompl0), Hop_NotCond(gFunc1, pTemp->fCompl1) ); if ( pTemp->fPhase != pIfObj->fPhase ) gFunc = Hop_Not(gFunc); If_CutSetData( pCut, gFunc ); break; } return (Hop_Obj_t *)If_CutData(pCut); }
/**Function************************************************************* Synopsis [Starts the AIG manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Ivy_Man_t * Ivy_ManStart() { Ivy_Man_t * p; // start the manager p = ALLOC( Ivy_Man_t, 1 ); memset( p, 0, sizeof(Ivy_Man_t) ); // perform initializations p->Ghost.Id = -1; p->nTravIds = 1; p->fCatchExor = 1; // allocate arrays for nodes p->vPis = Vec_PtrAlloc( 100 ); p->vPos = Vec_PtrAlloc( 100 ); p->vBufs = Vec_PtrAlloc( 100 ); p->vObjs = Vec_PtrAlloc( 100 ); // prepare the internal memory manager Ivy_ManStartMemory( p ); // create the constant node p->pConst1 = Ivy_ManFetchMemory( p ); p->pConst1->fPhase = 1; Vec_PtrPush( p->vObjs, p->pConst1 ); p->nCreated = 1; // start the table p->nTableSize = 10007; p->pTable = ALLOC( int, p->nTableSize ); memset( p->pTable, 0, sizeof(int) * p->nTableSize ); return p; }
ABC_NAMESPACE_IMPL_START //////////////////////////////////////////////////////////////////////// /// DECLARATIONS /// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /// FUNCTION DEFINITIONS /// //////////////////////////////////////////////////////////////////////// /**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Cmd_HistoryAddCommand( Abc_Frame_t * p, const char * command ) { static char Buffer[MAX_STR]; strcpy( Buffer, command ); if ( command[strlen(command)-1] != '\n' ) strcat( Buffer, "\n" ); Vec_PtrPush( p->aHistory, Extra_UtilStrsav(Buffer) ); }
/**Function************************************************************* Synopsis [Creates a multi-input multi-output box in the hierarchical design.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkSubcircuit( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pBox; Vec_Ptr_t * vNames; char * pName; int i; // create a new node and add it to the network if ( vTokens->nSize < 3 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "The .subcircuit line has less than three tokens." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // store the names of formal/actual inputs/outputs of the box vNames = Vec_PtrAlloc( 10 ); Vec_PtrForEachEntryStart( char *, vTokens, pName, i, 1 ) // Vec_PtrPush( vNames, Abc_NtkRegisterName(p->pNtkCur, pName) ); Vec_PtrPush( vNames, Extra_UtilStrsav(pName) ); // memory leak!!! // create a new box and add it to the network pBox = Abc_NtkCreateBlackbox( p->pNtkCur ); // set the pointer to the node names Abc_ObjSetData( pBox, vNames ); // remember the line of the file pBox->pCopy = (Abc_Obj_t *)(ABC_PTRINT_T)Extra_FileReaderGetLineNumber(p->pReader, 0); return 0; }
/**Function************************************************************* Synopsis [Derives the parameters of the best mapping/retiming for one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Seq_FpgaMappingCollectNode_rec( Abc_Obj_t * pAnd, Vec_Ptr_t * vMapping, Vec_Vec_t * vMapCuts ) { Abc_Obj_t * pFanin; Cut_Cut_t * pCutBest; int k; // skip if this is a non-PI node if ( !Abc_AigNodeIsAnd(pAnd) ) return; // skip a visited node if ( Abc_NodeIsTravIdCurrent(pAnd) ) return; Abc_NodeSetTravIdCurrent(pAnd); // visit the fanins of the node pCutBest = Seq_FpgaMappingSelectCut( pAnd ); for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) { pFanin = Abc_NtkObj( pAnd->pNtk, pCutBest->pLeaves[k] >> 8 ); Seq_FpgaMappingCollectNode_rec( pFanin, vMapping, vMapCuts ); } // add this node Vec_PtrPush( vMapping, pAnd ); for ( k = 0; k < (int)pCutBest->nLeaves; k++ ) Vec_VecPush( vMapCuts, Vec_PtrSize(vMapping)-1, (void *)pCutBest->pLeaves[k] ); }
/**Function************************************************************* Synopsis [For each cut, returns PIs that can be quantified.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Vec_Ptr_t * Llb_ManCutSupps( Aig_Man_t * p, Vec_Ptr_t * vResult ) { Vec_Ptr_t * vSupps, * vOne, * vLower, * vUpper; int i; vSupps = Vec_PtrAlloc( 100 ); Vec_PtrPush( vSupps, Vec_PtrAlloc(0) ); vLower = (Vec_Ptr_t *)Vec_PtrEntry( vResult, 0 ); Vec_PtrForEachEntryStart( Vec_Ptr_t *, vResult, vUpper, i, 1 ) { vOne = Llb_ManCutSupp( p, vLower, vUpper ); Vec_PtrPush( vSupps, vOne ); vLower = vUpper; } assert( Vec_PtrSize(vSupps) == Vec_PtrSize(vResult) ); return vSupps; }
/**Function************************************************************* Synopsis [Adds one node.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Rwr_Node_t * Rwr_ManTryNode( Rwr_Man_t * p, Rwr_Node_t * p0, Rwr_Node_t * p1, int fExor, int Level, int Volume ) { Rwr_Node_t * pOld, * pNew, ** ppPlace; unsigned uTruth; // compute truth table, level, volume p->nConsidered++; if ( fExor ) { // printf( "Considering EXOR of %d and %d.\n", p0->Id, p1->Id ); uTruth = (p0->uTruth ^ p1->uTruth); } else uTruth = (Rwr_IsComplement(p0)? ~Rwr_Regular(p0)->uTruth : Rwr_Regular(p0)->uTruth) & (Rwr_IsComplement(p1)? ~Rwr_Regular(p1)->uTruth : Rwr_Regular(p1)->uTruth) & 0xFFFF; // skip non-practical classes if ( Level > 2 && !p->pPractical[p->puCanons[uTruth]] ) return NULL; // enumerate through the nodes with the same canonical form ppPlace = p->pTable + uTruth; for ( pOld = *ppPlace; pOld; ppPlace = &pOld->pNext, pOld = pOld->pNext ) { if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; // if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) // return NULL; } /* // enumerate through the nodes with the opposite polarity for ( pOld = p->pTable[~uTruth & 0xFFFF]; pOld; pOld = pOld->pNext ) { if ( pOld->Level < (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; if ( pOld->Level == (unsigned)Level && pOld->Volume < (unsigned)Volume ) return NULL; // if ( pOld->Level < (unsigned)Level && pOld->Volume == (unsigned)Volume ) // return NULL; } */ // count the classes if ( p->pTable[uTruth] == NULL && p->puCanons[uTruth] == uTruth ) p->nClasses++; // create the new node pNew = (Rwr_Node_t *)Extra_MmFixedEntryFetch( p->pMmNode ); pNew->Id = p->vForest->nSize; pNew->TravId = 0; pNew->uTruth = uTruth; pNew->Level = Level; pNew->Volume = Volume; pNew->fUsed = 0; pNew->fExor = fExor; pNew->p0 = p0; pNew->p1 = p1; pNew->pNext = NULL; Vec_PtrPush( p->vForest, pNew ); *ppPlace = pNew; return pNew; }
/**Function************************************************************* Synopsis [Reproduces script "compress2".] Description [Consumes the input AIG to reduce memory usage.] SideEffects [] SeeAlso [] ***********************************************************************/ Aig_Man_t * Dar_ManChoiceNewAig( Aig_Man_t * pAig, Dch_Pars_t * pPars ) { // extern Aig_Man_t * Dch_DeriveTotalAig( Vec_Ptr_t * vAigs ); extern Aig_Man_t * Dch_ComputeChoices( Aig_Man_t * pAig, Dch_Pars_t * pPars ); int fVerbose = pPars->fVerbose; Aig_Man_t * pMan, * pTemp; Vec_Ptr_t * vAigs; Vec_Ptr_t * vPios; void * pManTime; char * pName, * pSpec; int i; abctime clk; clk = Abc_Clock(); vAigs = Dar_ManChoiceSynthesis( pAig, 1, 1, pPars->fPower, fVerbose ); pPars->timeSynth = Abc_Clock() - clk; // swap the first and last network // this should lead to the primary choice being "better" because of synthesis // (it is also important when constructing choices) pMan = (Aig_Man_t *)Vec_PtrPop( vAigs ); Vec_PtrPush( vAigs, Vec_PtrEntry(vAigs,0) ); Vec_PtrWriteEntry( vAigs, 0, pMan ); // derive the total AIG pMan = Dch_DeriveTotalAig( vAigs ); // cleanup Vec_PtrForEachEntry( Aig_Man_t *, vAigs, pTemp, i ) Aig_ManStop( pTemp ); Vec_PtrFree( vAigs ); // compute choices pMan = Dch_ComputeChoices( pTemp = pMan, pPars ); Aig_ManStop( pTemp ); // save useful things pManTime = pAig->pManTime; pAig->pManTime = NULL; pName = Abc_UtilStrsav( pAig->pName ); pSpec = Abc_UtilStrsav( pAig->pSpec ); // create guidence vPios = Aig_ManOrderPios( pMan, pAig ); Aig_ManStop( pAig ); // reconstruct the network pMan = Aig_ManDupDfsGuided( pTemp = pMan, vPios ); Aig_ManStop( pTemp ); Vec_PtrFree( vPios ); // reset levels pMan->pManTime = pManTime; Aig_ManChoiceLevel( pMan ); // copy names ABC_FREE( pMan->pName ); ABC_FREE( pMan->pSpec ); pMan->pName = pName; pMan->pSpec = pSpec; return pMan; }
/**Function************************************************************* Synopsis [ Given a node, evaluate its cuts and save the best one ] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Rewrite_NodeRewrite( Mig_Man_t * pMig, Rewrite_Man_t * p, Cut_Man_t * pManCut, Mig_Obj_t * pNode, Cut_Cut_t * pCut, int fUpdateLevel ) { Gra_Graph_t * pGraph; Mig_Obj_t * pFanin; unsigned uPhase; unsigned uTruthBest = 0; unsigned uTruth; char * pPerm; int Required, nNodesSaved, nNodesSaveCur = -1; int i, GainCur = -1, GainBest = -1; Required = fUpdateLevel ? Mig_ObjRequiredLevel(pMig, pNode) : ABC_INFINITY; // triv cut is omitted for ( pCut = pCut->pNext; pCut; pCut = pCut->pNext ) { if ( pCut->nLeaves < 4 ) continue; // NPN conditions uTruth = 0xFFFF & *Cut_CutReadTruth(pCut); pPerm = p->pPerms4[ (int)p->pPerms[uTruth] ]; uPhase = p->pPhases[uTruth]; // collect fanin nodes Vec_PtrClear( p->vFaninsCur ); Vec_PtrFill( p->vFaninsCur, (int)pCut->nLeaves, 0 ); for ( i = 0; i < (int)pCut->nLeaves; i++ ) { pFanin = Mig_ManObj( pMig, pCut->pLeaves[(int)pPerm[i]] ); if( pFanin == NULL ) break; //assert( pFanin ); // bad cut condition-> fanin may be removed pFanin = Mig_NotCond( pFanin, ((uPhase & (1<<i)) > 0) ); Vec_PtrWriteEntry( p->vFaninsCur, i, pFanin ); } if ( i != (int)pCut->nLeaves ) continue; // bad cut: fanin is removed // 1. mark boundary 2. mark MFFC 3.recover boundary Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Mig_Regular(pFanin)->vFanouts.nSize++; Mig_ManIncTravId( pMig ); nNodesSaved = Mig_NodeMffcLabelMig( pMig, pNode ); Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Mig_Regular(pFanin)->vFanouts.nSize--; // evaluate the cut pGraph = Rewrite_CutEvaluate( pMig, p, pNode, pCut, nNodesSaved, &GainCur, Required, 0xFFFF ); if( pGraph != NULL && GainBest < GainCur ) { nNodesSaveCur = nNodesSaved; GainBest = GainCur; p->pGraph = pGraph; p->fCompl = ((uPhase & (1<<4)) > 0 ); uTruthBest = 0xFFFF & *Cut_CutReadTruth(pCut); Vec_PtrClear( p->vFanins ); Vec_PtrForEachEntry( Mig_Obj_t *, p->vFaninsCur, pFanin, i ) Vec_PtrPush( p->vFanins, pFanin ); } }
/**Function************************************************************* Synopsis [Inserts value into the table.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ unsigned * Aig_TsiStateNew( Aig_Tsi_t * p ) { unsigned * pState; pState = (unsigned *)Aig_MmFixedEntryFetch( p->pMem ); memset( pState, 0, sizeof(unsigned) * p->nWords ); Vec_PtrPush( p->vStates, pState ); return pState; }
Vec_Ptr_t * Ptr_AbcDeriveNode( Abc_Obj_t * pObj ) { Abc_Obj_t * pFanin; int i; Vec_Ptr_t * vNode = Vec_PtrAllocExact( 2 + 2 * (1 + Abc_ObjFaninNum(pObj)) ); assert( Abc_ObjIsNode(pObj) ); if ( Abc_NtkHasAig(pObj->pNtk) ) Vec_PtrPush( vNode, Ptr_HopToType(pObj) ); else if ( Abc_NtkHasSop(pObj->pNtk) ) Vec_PtrPush( vNode, Ptr_SopToTypeName((char *)pObj->pData) ); else assert( 0 ); Vec_PtrPush( vNode, Ptr_AbcObjName(pObj) ); assert( Abc_ObjFaninNum(pObj) <= 2 ); Abc_ObjForEachFanin( pObj, pFanin, i ) { Vec_PtrPush( vNode, (void*)(i ? "r" : "l") ); Vec_PtrPush( vNode, Ptr_AbcObjName(pFanin) ); }