/**Function************************************************************* Synopsis [Cycles the circuit to create a new initial state.] Description [Simulates the circuit with random input for the given number of timeframes to get a better initial state.] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkCycleInitState( Abc_Ntk_t * pNtk, int nFrames, int fVerbose ) { Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsStrash(pNtk) ); srand( 0x12341234 ); // initialize the values Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchIsInit1(pObj)? XVS1 : XVS0 ); // simulate for the given number of timeframes for ( f = 0; f < nFrames; f++ ) { Abc_AigForEachAnd( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); // assign input values Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); } // set the final values Abc_NtkForEachLatch( pNtk, pObj, i ) pObj->pData = (void *)Abc_ObjGetXsim(Abc_ObjFanout0(pObj)); }
/**Function************************************************************* Synopsis [Performs X-valued simulation of the sequential network.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ void Abc_NtkXValueSimulate( Abc_Ntk_t * pNtk, int nFrames, int fInputs, int fVerbose ) { Abc_Obj_t * pObj; int i, f; assert( Abc_NtkIsStrash(pNtk) ); srand( 0x12341234 ); // start simulation Abc_ObjSetXsim( Abc_AigConst1(pNtk), XVS1 ); if ( fInputs ) { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, XVSX ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_LatchInit(pObj) ); } else { Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), XVSX ); } // simulate and print the result fprintf( stdout, "Frame : Inputs : Latches : Outputs\n" ); for ( f = 0; f < nFrames; f++ ) { Abc_AigForEachAnd( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimAnd(Abc_ObjGetXsimFanin0(pObj), Abc_ObjGetXsimFanin1(pObj)) ); Abc_NtkForEachCo( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_ObjGetXsimFanin0(pObj) ); // print out fprintf( stdout, "%2d : ", f ); Abc_NtkForEachPi( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); fprintf( stdout, " : " ); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(Abc_ObjFanout0(pObj)) ); fprintf( stdout, " : " ); Abc_NtkForEachPo( pNtk, pObj, i ) Abc_XsimPrint( stdout, Abc_ObjGetXsim(pObj) ); fprintf( stdout, "\n" ); // assign input values if ( fInputs ) Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, XVSX ); else Abc_NtkForEachPi( pNtk, pObj, i ) Abc_ObjSetXsim( pObj, Abc_XsimRand2() ); // transfer the latch values Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_ObjSetXsim( Abc_ObjFanout0(pObj), Abc_ObjGetXsim(Abc_ObjFanin0(pObj)) ); } }
/**Function************************************************************* Synopsis [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); } }
/**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 ); }
/**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" ); }
Vec_PtrForEachEntryStart( char *, pNames, pName, i, Start ) { pActual = Io_ReadBlifCleanName(pName); if ( pActual == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot parse formal/actual name pair \"%s\".", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } Length = pActual - pName - 1; pName[Length] = 0; // find the PO net with this name pObj = Abc_NtkFindNet( pNtkModel, pName ); if ( pObj == NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Cannot find formal output \"%s\" as an PO of model \"%s\".", pName, (char*)Vec_PtrEntry(pNames, 0) ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // get the PO pObj = Abc_ObjFanout0(pObj); if ( pObj->pCopy != NULL ) { p->LineCur = (int)(ABC_PTRINT_T)pBox->pCopy; sprintf( p->sError, "Formal output \"%s\" is used more than once.", pName ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pObj->pCopy = (Abc_Obj_t *)pActual; }
/**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; }
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 [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 ); }
/**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 [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 ); }
/**Function************************************************************* Synopsis [] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ int Io_ReadBlifNetworkOutputRequired( Io_ReadBlif_t * p, Vec_Ptr_t * vTokens ) { Abc_Obj_t * pNet; char * pFoo1, * pFoo2; double TimeRise, TimeFall; // make sure this is indeed the .inputs line assert( strncmp( (char *)vTokens->pArray[0], ".output_required", 16 ) == 0 ); if ( vTokens->nSize != 4 ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Wrong number of arguments on .output_required line." ); Io_ReadBlifPrintErrorMessage( p ); return 1; } pNet = Abc_NtkFindNet( p->pNtkCur, (char *)vTokens->pArray[1] ); if ( pNet == NULL ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Cannot find object corresponding to %s on .output_required line.", (char*)vTokens->pArray[1] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } TimeRise = strtod( (char *)vTokens->pArray[2], &pFoo1 ); TimeFall = strtod( (char *)vTokens->pArray[3], &pFoo2 ); if ( *pFoo1 != '\0' || *pFoo2 != '\0' ) { p->LineCur = Extra_FileReaderGetLineNumber(p->pReader, 0); sprintf( p->sError, "Bad value (%s %s) for rise or fall time on .output_required line.", (char*)vTokens->pArray[2], (char*)vTokens->pArray[3] ); Io_ReadBlifPrintErrorMessage( p ); return 1; } // set the arrival time Abc_NtkTimeSetRequired( p->pNtkCur, Abc_ObjFanout0(pNet)->Id, (float)TimeRise, (float)TimeFall ); return 0; }
static inline char * Abc_ObjNameNet( Abc_Obj_t * pObj ) { return (Abc_ObjIsNode(pObj) && Abc_NtkIsNetlist(pObj->pNtk)) ? Abc_ObjName(Abc_ObjFanout0(pObj)) : Abc_ObjName(pObj); }
/**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 [Writes the graph structure of network for DOT.] Description [Useful for graph visualization using tools such as GraphViz: http://www.graphviz.org/] SideEffects [] SeeAlso [] ***********************************************************************/ void Io_WriteDotNtk( Abc_Ntk_t * pNtk, Vec_Ptr_t * vNodes, Vec_Ptr_t * vNodesShow, char * pFileName, int fGateNames, int fUseReverse ) { FILE * pFile; Abc_Obj_t * pNode, * pFanin; char * pSopString; int LevelMin, LevelMax, fHasCos, Level, i, k, fHasBdds, fCompl; int Limit = 300; assert( Abc_NtkIsStrash(pNtk) || Abc_NtkIsLogic(pNtk) ); if ( vNodes->nSize < 1 ) { printf( "The set has no nodes. DOT file is not written.\n" ); return; } if ( vNodes->nSize > Limit ) { printf( "The set has more than %d nodes. DOT file is not written.\n", Limit ); return; } // start the stream if ( (pFile = fopen( pFileName, "w" )) == NULL ) { fprintf( stdout, "Cannot open the intermediate file \"%s\".\n", pFileName ); return; } // transform logic functions from BDD to SOP if ( fHasBdds = Abc_NtkIsBddLogic(pNtk) ) { if ( !Abc_NtkBddToSop(pNtk, 0) ) { printf( "Io_WriteDotNtk(): Converting to SOPs has failed.\n" ); return; } } // mark the nodes from the set Vec_PtrForEachEntry( vNodes, pNode, i ) pNode->fMarkC = 1; if ( vNodesShow ) Vec_PtrForEachEntry( vNodesShow, pNode, i ) pNode->fMarkB = 1; // get the levels of nodes LevelMax = Abc_NtkLevel( pNtk ); if ( fUseReverse ) { LevelMin = Abc_NtkLevelReverse( pNtk ); assert( LevelMax == LevelMin ); Vec_PtrForEachEntry( vNodes, pNode, i ) if ( Abc_ObjIsNode(pNode) ) pNode->Level = LevelMax - pNode->Level + 1; } // find the largest and the smallest levels LevelMin = 10000; LevelMax = -1; fHasCos = 0; Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) { fHasCos = 1; continue; } if ( LevelMin > (int)pNode->Level ) LevelMin = pNode->Level; if ( LevelMax < (int)pNode->Level ) LevelMax = pNode->Level; } // set the level of the CO nodes if ( fHasCos ) { LevelMax++; Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( Abc_ObjIsCo(pNode) ) pNode->Level = LevelMax; } } // write the DOT header fprintf( pFile, "# %s\n", "Network structure generated by ABC" ); fprintf( pFile, "\n" ); fprintf( pFile, "digraph network {\n" ); fprintf( pFile, "size = \"7.5,10\";\n" ); // fprintf( pFile, "size = \"10,8.5\";\n" ); // fprintf( pFile, "size = \"14,11\";\n" ); // fprintf( pFile, "page = \"8,11\";\n" ); // fprintf( pFile, "ranksep = 0.5;\n" ); // fprintf( pFile, "nodesep = 0.5;\n" ); fprintf( pFile, "center = true;\n" ); // fprintf( pFile, "orientation = landscape;\n" ); // fprintf( pFile, "edge [fontsize = 10];\n" ); // fprintf( pFile, "edge [dir = none];\n" ); fprintf( pFile, "edge [dir = back];\n" ); fprintf( pFile, "\n" ); // labels on the left of the picture fprintf( pFile, "{\n" ); fprintf( pFile, " node [shape = plaintext];\n" ); fprintf( pFile, " edge [style = invis];\n" ); fprintf( pFile, " LevelTitle1 [label=\"\"];\n" ); fprintf( pFile, " LevelTitle2 [label=\"\"];\n" ); // generate node names with labels for ( Level = LevelMax; Level >= LevelMin; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); fprintf( pFile, " [label = " ); // label name fprintf( pFile, "\"" ); fprintf( pFile, "\"" ); fprintf( pFile, "];\n" ); } // genetate the sequence of visible/invisible nodes to mark levels fprintf( pFile, " LevelTitle1 -> LevelTitle2 ->" ); for ( Level = LevelMax; Level >= LevelMin; Level-- ) { // the visible node name fprintf( pFile, " Level%d", Level ); // the connector if ( Level != LevelMin ) fprintf( pFile, " ->" ); else fprintf( pFile, ";" ); } fprintf( pFile, "\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate title box on top fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle1;\n" ); fprintf( pFile, " title1 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=20,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); fprintf( pFile, "%s", "Network structure visualized by ABC" ); fprintf( pFile, "\\n" ); fprintf( pFile, "Benchmark \\\"%s\\\". ", pNtk->pName ); fprintf( pFile, "Time was %s. ", Extra_TimeStamp() ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate statistics box fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); fprintf( pFile, " LevelTitle2;\n" ); fprintf( pFile, " title2 [shape=plaintext,\n" ); fprintf( pFile, " fontsize=18,\n" ); fprintf( pFile, " fontname = \"Times-Roman\",\n" ); fprintf( pFile, " label=\"" ); if ( Abc_NtkObjNum(pNtk) == Vec_PtrSize(vNodes) ) fprintf( pFile, "The network contains %d logic nodes and %d latches.", Abc_NtkNodeNum(pNtk), Abc_NtkLatchNum(pNtk) ); else fprintf( pFile, "The set contains %d logic nodes and spans %d levels.", Abc_NtkCountLogicNodes(vNodes), LevelMax - LevelMin + 1 ); fprintf( pFile, "\\n" ); fprintf( pFile, "\"\n" ); fprintf( pFile, " ];\n" ); fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); // generate the POs if ( fHasCos ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMax ); // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( !Abc_ObjIsCo(pNode) ) continue; fprintf( pFile, " Node%d [label = \"%s%s\"", pNode->Id, (Abc_ObjIsBi(pNode)? Abc_ObjName(Abc_ObjFanout0(pNode)):Abc_ObjName(pNode)), (Abc_ObjIsBi(pNode)? "_in":"") ); fprintf( pFile, ", shape = %s", (Abc_ObjIsBi(pNode)? "box":"invtriangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate nodes of each rank for ( Level = LevelMax - fHasCos; Level >= LevelMin && Level > 0; Level-- ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", Level ); Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( (int)pNode->Level != Level ) continue; if ( Abc_ObjFaninNum(pNode) == 0 ) continue; // fprintf( pFile, " Node%d [label = \"%d\"", pNode->Id, pNode->Id ); if ( Abc_NtkIsStrash(pNtk) ) pSopString = ""; else if ( Abc_NtkHasMapping(pNtk) && fGateNames ) pSopString = Mio_GateReadName(pNode->pData); else if ( Abc_NtkHasMapping(pNtk) ) pSopString = Abc_NtkPrintSop(Mio_GateReadSop(pNode->pData)); else pSopString = Abc_NtkPrintSop(pNode->pData); fprintf( pFile, " Node%d [label = \"%d\\n%s\"", pNode->Id, pNode->Id, pSopString ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); } // generate the PI nodes if any if ( LevelMin == 0 ) { fprintf( pFile, "{\n" ); fprintf( pFile, " rank = same;\n" ); // the labeling node of this level fprintf( pFile, " Level%d;\n", LevelMin ); // generate the PO nodes Vec_PtrForEachEntry( vNodes, pNode, i ) { if ( !Abc_ObjIsCi(pNode) ) { // check if the costant node is present if ( Abc_ObjFaninNum(pNode) == 0 && Abc_ObjFanoutNum(pNode) > 0 ) { fprintf( pFile, " Node%d [label = \"Const%d\"", pNode->Id, Abc_NtkIsStrash(pNode->pNtk) || Abc_NodeIsConst1(pNode) ); fprintf( pFile, ", shape = ellipse" ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } continue; } fprintf( pFile, " Node%d [label = \"%s\"", pNode->Id, (Abc_ObjIsBo(pNode)? Abc_ObjName(Abc_ObjFanin0(pNode)):Abc_ObjName(pNode)) ); fprintf( pFile, ", shape = %s", (Abc_ObjIsBo(pNode)? "box":"triangle") ); if ( pNode->fMarkB ) fprintf( pFile, ", style = filled" ); fprintf( pFile, ", color = coral, fillcolor = coral" ); fprintf( pFile, "];\n" ); } fprintf( pFile, "}" ); fprintf( pFile, "\n" ); fprintf( pFile, "\n" ); }
/**Function************************************************************* Synopsis [Performs minimum-register retiming.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Abc_Ntk_t * Abc_FlowRetime_MinReg( Abc_Ntk_t * pNtk, int fVerbose, int fComputeInitState, int fGuaranteeInitState, int fBlockConst, int fForwardOnly, int fBackwardOnly, int nMaxIters, int maxDelay, int fFastButConservative ) { int i; Abc_Obj_t *pObj, *pNext; InitConstraint_t *pData; // create manager pManMR = ALLOC( MinRegMan_t, 1 ); pManMR->pNtk = pNtk; pManMR->fVerbose = fVerbose; pManMR->fComputeInitState = fComputeInitState; pManMR->fGuaranteeInitState = fGuaranteeInitState; pManMR->fBlockConst = fBlockConst; pManMR->fForwardOnly = fForwardOnly; pManMR->fBackwardOnly = fBackwardOnly; pManMR->nMaxIters = nMaxIters; pManMR->maxDelay = maxDelay; pManMR->fComputeInitState = fComputeInitState; pManMR->fConservTimingOnly = fFastButConservative; pManMR->vNodes = Vec_PtrAlloc(100); pManMR->vInitConstraints = Vec_PtrAlloc(2); pManMR->pInitNtk = NULL; pManMR->pInitToOrig = NULL; pManMR->sizeInitToOrig = 0; vprintf("Flow-based minimum-register retiming...\n"); if (!Abc_NtkHasOnlyLatchBoxes(pNtk)) { printf("\tERROR: Can not retime with black/white boxes\n"); return pNtk; } if (maxDelay) { vprintf("\tmax delay constraint = %d\n", maxDelay); if (maxDelay < (i = Abc_NtkLevel(pNtk))) { printf("ERROR: max delay constraint (%d) must be > current max delay (%d)\n", maxDelay, i); return pNtk; } } // print info about type of network vprintf("\tnetlist type = "); if (Abc_NtkIsNetlist( pNtk )) { vprintf("netlist/"); } else if (Abc_NtkIsLogic( pNtk )) { vprintf("logic/"); } else if (Abc_NtkIsStrash( pNtk )) { vprintf("strash/"); } else { vprintf("***unknown***/"); } if (Abc_NtkHasSop( pNtk )) { vprintf("sop\n"); } else if (Abc_NtkHasBdd( pNtk )) { vprintf("bdd\n"); } else if (Abc_NtkHasAig( pNtk )) { vprintf("aig\n"); } else if (Abc_NtkHasMapping( pNtk )) { vprintf("mapped\n"); } else { vprintf("***unknown***\n"); } vprintf("\tinitial reg count = %d\n", Abc_NtkLatchNum(pNtk)); vprintf("\tinitial levels = %d\n", Abc_NtkLevel(pNtk)); // remove bubbles from latch boxes if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk); vprintf("\tpushing bubbles out of latch boxes\n"); Abc_NtkForEachLatch( pNtk, pObj, i ) Abc_FlowRetime_RemoveLatchBubbles(pObj); if (pManMR->fVerbose) Abc_FlowRetime_PrintInitStateInfo(pNtk); // check for box inputs/outputs Abc_NtkForEachLatch( pNtk, pObj, i ) { assert(Abc_ObjFaninNum(pObj) == 1); assert(Abc_ObjFanoutNum(pObj) == 1); assert(!Abc_ObjFaninC0(pObj)); pNext = Abc_ObjFanin0(pObj); assert(Abc_ObjIsBi(pNext)); assert(Abc_ObjFaninNum(pNext) <= 1); if(Abc_ObjFaninNum(pNext) == 0) // every Bi should have a fanin Abc_FlowRetime_AddDummyFanin( pNext ); pNext = Abc_ObjFanout0(pObj); assert(Abc_ObjIsBo(pNext)); assert(Abc_ObjFaninNum(pNext) == 1); assert(!Abc_ObjFaninC0(pNext)); }
/**Function************************************************************* Synopsis [Load the network into manager.] Description [] SideEffects [] SeeAlso [] ***********************************************************************/ Map_Man_t * Abc_NtkToMap( Abc_Ntk_t * pNtk, double DelayTarget, int fRecovery, float * pSwitching, int fVerbose ) { Map_Man_t * pMan; Map_Node_t * pNodeMap; Vec_Ptr_t * vNodes; Abc_Obj_t * pNode, * pFanin, * pPrev; int i; assert( Abc_NtkIsStrash(pNtk) ); // start the mapping manager and set its parameters pMan = Map_ManCreate( Abc_NtkPiNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, Abc_NtkPoNum(pNtk) + Abc_NtkLatchNum(pNtk) - pNtk->nBarBufs, fVerbose ); if ( pMan == NULL ) return NULL; Map_ManSetAreaRecovery( pMan, fRecovery ); Map_ManSetOutputNames( pMan, Abc_NtkCollectCioNames(pNtk, 1) ); Map_ManSetDelayTarget( pMan, (float)DelayTarget ); Map_ManSetInputArrivals( pMan, Abc_NtkMapCopyCiArrival(pNtk, Abc_NtkGetCiArrivalTimes(pNtk)) ); Map_ManSetOutputRequireds( pMan, Abc_NtkMapCopyCoRequired(pNtk, Abc_NtkGetCoRequiredTimes(pNtk)) ); // create PIs and remember them in the old nodes Abc_NtkCleanCopy( pNtk ); Abc_AigConst1(pNtk)->pCopy = (Abc_Obj_t *)Map_ManReadConst1(pMan); Abc_NtkForEachCi( pNtk, pNode, i ) { if ( i == Abc_NtkCiNum(pNtk) - pNtk->nBarBufs ) break; pNodeMap = Map_ManReadInputs(pMan)[i]; pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); } // load the AIG into the mapper vNodes = Abc_AigDfsMap( pNtk ); Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNode, i ) { if ( Abc_ObjIsLatch(pNode) ) { pFanin = Abc_ObjFanin0(pNode); pNodeMap = Map_NodeBuf( pMan, Map_NotCond( Abc_ObjFanin0(pFanin)->pCopy, (int)Abc_ObjFaninC0(pFanin) ) ); Abc_ObjFanout0(pNode)->pCopy = (Abc_Obj_t *)pNodeMap; continue; } assert( Abc_ObjIsNode(pNode) ); // add the node to the mapper pNodeMap = Map_NodeAnd( pMan, Map_NotCond( Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ), Map_NotCond( Abc_ObjFanin1(pNode)->pCopy, (int)Abc_ObjFaninC1(pNode) ) ); assert( pNode->pCopy == NULL ); // remember the node pNode->pCopy = (Abc_Obj_t *)pNodeMap; if ( pSwitching ) Map_NodeSetSwitching( pNodeMap, pSwitching[pNode->Id] ); // set up the choice node if ( Abc_AigNodeIsChoice( pNode ) ) for ( pPrev = pNode, pFanin = (Abc_Obj_t *)pNode->pData; pFanin; pPrev = pFanin, pFanin = (Abc_Obj_t *)pFanin->pData ) { Map_NodeSetNextE( (Map_Node_t *)pPrev->pCopy, (Map_Node_t *)pFanin->pCopy ); Map_NodeSetRepr( (Map_Node_t *)pFanin->pCopy, (Map_Node_t *)pNode->pCopy ); } } assert( Map_ManReadBufNum(pMan) == pNtk->nBarBufs ); Vec_PtrFree( vNodes ); // set the primary outputs in the required phase Abc_NtkForEachCo( pNtk, pNode, i ) { if ( i == Abc_NtkCoNum(pNtk) - pNtk->nBarBufs ) break; Map_ManReadOutputs(pMan)[i] = Map_NotCond( (Map_Node_t *)Abc_ObjFanin0(pNode)->pCopy, (int)Abc_ObjFaninC0(pNode) ); } return pMan; }