00001
00021 #include "abc.h"
00022
00026
00027 static DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose );
00028 static DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose );
00029 static DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bRelation, DdNode * bInitial, bool fVerbose );
00030 static Abc_Ntk_t * Abc_NtkConstructExdc ( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach );
00031
00035
00047 int Abc_NtkExtractSequentialDcs( Abc_Ntk_t * pNtk, bool fVerbose )
00048 {
00049 int fReorder = 1;
00050 DdManager * dd;
00051 DdNode * bRelation, * bInitial, * bUnreach;
00052
00053
00054 if ( pNtk->pExdc )
00055 {
00056 Abc_NtkDelete( pNtk->pExdc );
00057 pNtk->pExdc = NULL;
00058 }
00059
00060
00061 dd = Abc_NtkBuildGlobalBdds( pNtk, 10000000, 1, 1, fVerbose );
00062 if ( dd == NULL )
00063 return 0;
00064 if ( fVerbose )
00065 printf( "Shared BDD size = %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
00066
00067
00068 bRelation = Abc_NtkTransitionRelation( dd, pNtk, fVerbose ); Cudd_Ref( bRelation );
00069
00070 bInitial = Abc_NtkInitStateAndVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial );
00071
00072 bUnreach = Abc_NtkComputeUnreachable( dd, pNtk, bRelation, bInitial, fVerbose ); Cudd_Ref( bUnreach );
00073 Cudd_RecursiveDeref( dd, bRelation );
00074 Cudd_RecursiveDeref( dd, bInitial );
00075
00076
00077 if ( fReorder )
00078 {
00079 if ( fVerbose )
00080 fprintf( stdout, "BDD nodes in the unreachable states before reordering %d.\n", Cudd_DagSize(bUnreach) );
00081 Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 1 );
00082 Cudd_AutodynDisable( dd );
00083 if ( fVerbose )
00084 fprintf( stdout, "BDD nodes in the unreachable states after reordering %d.\n", Cudd_DagSize(bUnreach) );
00085 }
00086
00087
00088 Cudd_zddVarsFromBddVars( dd, 2 );
00089
00090 if ( pNtk->pExdc )
00091 Abc_NtkDelete( pNtk->pExdc );
00092 pNtk->pExdc = Abc_NtkConstructExdc( dd, pNtk, bUnreach );
00093 Cudd_RecursiveDeref( dd, bUnreach );
00094 Extra_StopManager( dd );
00095
00096
00097
00098 if ( pNtk->pExdc && !Abc_NtkCheck( pNtk->pExdc ) )
00099 {
00100 printf( "Abc_NtkExtractSequentialDcs: The network check has failed.\n" );
00101 Abc_NtkDelete( pNtk->pExdc );
00102 return 0;
00103 }
00104 return 1;
00105 }
00106
00118 DdNode * Abc_NtkTransitionRelation( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
00119 {
00120 DdNode * bRel, * bTemp, * bProd, * bVar, * bInputs;
00121 Abc_Obj_t * pNode;
00122 int fReorder = 1;
00123 int i;
00124
00125
00126 assert( dd->size == Abc_NtkCiNum(pNtk) );
00127 Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 );
00128
00129
00130 if ( fReorder )
00131 Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
00132 else
00133 Cudd_AutodynDisable( dd );
00134
00135
00136 bRel = b1; Cudd_Ref( bRel );
00137 Abc_NtkForEachLatch( pNtk, pNode, i )
00138 {
00139 bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
00140
00141 bProd = Cudd_bddXnor( dd, bVar, Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( bProd );
00142 bRel = Cudd_bddAnd( dd, bTemp = bRel, bProd ); Cudd_Ref( bRel );
00143 Cudd_RecursiveDeref( dd, bTemp );
00144 Cudd_RecursiveDeref( dd, bProd );
00145 }
00146
00147
00148 Abc_NtkFreeGlobalBdds( pNtk, 0 );
00149
00150
00151 bInputs = Extra_bddComputeRangeCube( dd, 0, Abc_NtkPiNum(pNtk) ); Cudd_Ref( bInputs );
00152 bRel = Cudd_bddExistAbstract( dd, bTemp = bRel, bInputs ); Cudd_Ref( bRel );
00153 Cudd_RecursiveDeref( dd, bTemp );
00154 Cudd_RecursiveDeref( dd, bInputs );
00155
00156
00157 if ( fReorder )
00158 {
00159 if ( fVerbose )
00160 fprintf( stdout, "BDD nodes in the transition relation before reordering %d.\n", Cudd_DagSize(bRel) );
00161 Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
00162 Cudd_AutodynDisable( dd );
00163 if ( fVerbose )
00164 fprintf( stdout, "BDD nodes in the transition relation after reordering %d.\n", Cudd_DagSize(bRel) );
00165 }
00166 Cudd_Deref( bRel );
00167 return bRel;
00168 }
00169
00181 DdNode * Abc_NtkInitStateAndVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
00182 {
00183 DdNode ** pbVarsX, ** pbVarsY;
00184 DdNode * bTemp, * bProd, * bVar;
00185 Abc_Obj_t * pLatch;
00186 int i;
00187
00188
00189 pbVarsX = ALLOC( DdNode *, dd->size );
00190 pbVarsY = ALLOC( DdNode *, dd->size );
00191 bProd = b1; Cudd_Ref( bProd );
00192 Abc_NtkForEachLatch( pNtk, pLatch, i )
00193 {
00194 pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ];
00195 pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
00196
00197 bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) );
00198 bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd );
00199 Cudd_RecursiveDeref( dd, bTemp );
00200 }
00201 Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) );
00202 FREE( pbVarsX );
00203 FREE( pbVarsY );
00204
00205 Cudd_Deref( bProd );
00206 return bProd;
00207 }
00208
00220 DdNode * Abc_NtkComputeUnreachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bTrans, DdNode * bInitial, bool fVerbose )
00221 {
00222 DdNode * bRelation, * bReached, * bCubeCs;
00223 DdNode * bCurrent, * bNext, * bTemp;
00224 int nIters, nMints;
00225
00226
00227 bCurrent = bInitial; Cudd_Ref( bCurrent );
00228 bReached = bInitial; Cudd_Ref( bReached );
00229 bRelation = bTrans; Cudd_Ref( bRelation );
00230 bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs );
00231 for ( nIters = 1; ; nIters++ )
00232 {
00233
00234 bNext = Cudd_bddAndAbstract( dd, bRelation, bCurrent, bCubeCs ); Cudd_Ref( bNext );
00235 Cudd_RecursiveDeref( dd, bCurrent );
00236
00237 bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext );
00238 Cudd_RecursiveDeref( dd, bTemp );
00239
00240 if ( Cudd_bddLeq( dd, bNext, bReached ) )
00241 break;
00242
00243 bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
00244
00245
00246
00247
00248 bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached );
00249 Cudd_RecursiveDeref( dd, bTemp );
00250 Cudd_RecursiveDeref( dd, bNext );
00251
00252
00253
00254 }
00255 Cudd_RecursiveDeref( dd, bRelation );
00256 Cudd_RecursiveDeref( dd, bCubeCs );
00257 Cudd_RecursiveDeref( dd, bNext );
00258
00259 if ( fVerbose )
00260 {
00261 nMints = (int)Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) );
00262 fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
00263 fprintf( stdout, "The number of minterms in the reachable state set = %d. (%6.2f %%)\n", nMints, 100.0*nMints/(1<<Abc_NtkLatchNum(pNtk)) );
00264 }
00265
00266 Cudd_Deref( bReached );
00267 return Cudd_Not( bReached );
00268 }
00269
00281 Abc_Ntk_t * Abc_NtkConstructExdc( DdManager * dd, Abc_Ntk_t * pNtk, DdNode * bUnreach )
00282 {
00283 Abc_Ntk_t * pNtkNew;
00284 Abc_Obj_t * pNode, * pNodeNew;
00285 int * pPermute;
00286 int i;
00287
00288
00289 pNtkNew = Abc_NtkAlloc( ABC_NTK_LOGIC, ABC_FUNC_BDD, 1 );
00290 pNtkNew->pName = Extra_UtilStrsav( "exdc" );
00291 pNtkNew->pSpec = NULL;
00292
00293
00294 Abc_NtkForEachLatchOutput( pNtk, pNode, i )
00295 Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePi(pNtkNew), Abc_ObjName(pNode), NULL );
00296
00297
00298
00299 pNodeNew = Abc_NtkCreateNode(pNtkNew);
00300
00301 Abc_NtkForEachLatchOutput( pNtk, pNode, i )
00302 Abc_ObjAddFanin( pNodeNew, pNode->pCopy );
00303
00304
00305 pPermute = ALLOC( int, dd->size );
00306 for ( i = 0; i < dd->size; i++ )
00307 pPermute[i] = -1;
00308 Abc_NtkForEachLatch( pNtk, pNode, i )
00309 pPermute[Abc_NtkPiNum(pNtk) + i] = i;
00310
00311 pNodeNew->pData = Extra_TransferPermute( dd, pNtkNew->pManFunc, bUnreach, pPermute ); Cudd_Ref( pNodeNew->pData );
00312 free( pPermute );
00313 Abc_NodeMinimumBase( pNodeNew );
00314
00315
00316 Abc_NtkForEachPo( pNtk, pNode, i )
00317 if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
00318 Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
00319 Abc_NtkForEachLatchInput( pNtk, pNode, i )
00320 Abc_ObjAssignName( pNode->pCopy = Abc_NtkCreatePo(pNtkNew), Abc_ObjName(pNode), NULL );
00321
00322
00323 Abc_NtkForEachPo( pNtk, pNode, i )
00324 if ( !Abc_ObjIsCi(Abc_ObjFanin0(pNode)) )
00325 Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
00326 Abc_NtkForEachLatchInput( pNtk, pNode, i )
00327 Abc_ObjAddFanin( pNode->pCopy, pNodeNew );
00328
00329
00330 Abc_AigCleanup( pNtkNew->pManFunc );
00331
00332
00333 Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
00334
00335
00336 if ( !Abc_NtkBddToSop( pNtkNew, 0 ) )
00337 {
00338 printf( "Abc_NtkConstructExdc(): Converting to SOPs has failed.\n" );
00339 return NULL;
00340 }
00341 return pNtkNew;
00342
00343 }
00344
00348
00349