ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
abcReach.c
Go to the documentation of this file.
1
20
21#include "base/abc/abc.h"
22
23#ifdef ABC_USE_CUDD
24#include "bdd/extrab/extraBdd.h"
25#endif
26
28
29
33
37
38#ifdef ABC_USE_CUDD
39
51DdNode * Abc_NtkInitStateVarMap( DdManager * dd, Abc_Ntk_t * pNtk, int fVerbose )
52{
53 DdNode ** pbVarsX, ** pbVarsY;
54 DdNode * bTemp, * bProd, * bVar;
55 Abc_Obj_t * pLatch;
56 int i;
57
58 // set the variable mapping for Cudd_bddVarMap()
59 pbVarsX = ABC_ALLOC( DdNode *, dd->size );
60 pbVarsY = ABC_ALLOC( DdNode *, dd->size );
61 bProd = b1; Cudd_Ref( bProd );
62 Abc_NtkForEachLatch( pNtk, pLatch, i )
63 {
64 pbVarsX[i] = dd->vars[ Abc_NtkPiNum(pNtk) + i ];
65 pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
66 // get the initial value of the latch
67 bVar = Cudd_NotCond( pbVarsX[i], !Abc_LatchIsInit1(pLatch) );
68 bProd = Cudd_bddAnd( dd, bTemp = bProd, bVar ); Cudd_Ref( bProd );
69 Cudd_RecursiveDeref( dd, bTemp );
70 }
71 Cudd_SetVarMap( dd, pbVarsX, pbVarsY, Abc_NtkLatchNum(pNtk) );
72 ABC_FREE( pbVarsX );
73 ABC_FREE( pbVarsY );
74
75 Cudd_Deref( bProd );
76 return bProd;
77}
78
90DdNode ** Abc_NtkCreatePartitions( DdManager * dd, Abc_Ntk_t * pNtk, int fReorder, int fVerbose )
91{
92 DdNode ** pbParts;
93 DdNode * bVar;
94 Abc_Obj_t * pNode;
95 int i;
96
97 // extand the BDD manager to represent NS variables
98 assert( dd->size == Abc_NtkCiNum(pNtk) );
99 Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + Abc_NtkLatchNum(pNtk) - 1 );
100
101 // enable reordering
102 if ( fReorder )
103 Cudd_AutodynEnable( dd, CUDD_REORDER_SYMM_SIFT );
104 else
105 Cudd_AutodynDisable( dd );
106
107 // compute the transition relation
108 pbParts = ABC_ALLOC( DdNode *, Abc_NtkLatchNum(pNtk) );
109 Abc_NtkForEachLatch( pNtk, pNode, i )
110 {
111 bVar = Cudd_bddIthVar( dd, Abc_NtkCiNum(pNtk) + i );
112 pbParts[i] = Cudd_bddXnor( dd, bVar, (DdNode *)Abc_ObjGlobalBdd(Abc_ObjFanin0(pNode)) ); Cudd_Ref( pbParts[i] );
113 }
114 // free the global BDDs
115 Abc_NtkFreeGlobalBdds( pNtk, 0 );
116
117 // reorder and disable reordering
118 if ( fReorder )
119 {
120 if ( fVerbose )
121 fprintf( stdout, "BDD nodes in the partitions before reordering %d.\n", Cudd_SharingSize(pbParts,Abc_NtkLatchNum(pNtk)) );
122 Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
123 Cudd_AutodynDisable( dd );
124 if ( fVerbose )
125 fprintf( stdout, "BDD nodes in the partitions after reordering %d.\n", Cudd_SharingSize(pbParts,Abc_NtkLatchNum(pNtk)) );
126 }
127 return pbParts;
128}
129
141DdNode * Abc_NtkComputeReachable( DdManager * dd, Abc_Ntk_t * pNtk, DdNode ** pbParts, DdNode * bInitial, DdNode * bOutput, int nBddMax, int nIterMax, int fPartition, int fReorder, int fVerbose )
142{
143 int fInternalReorder = 0;
144 Extra_ImageTree_t * pTree = NULL;
145 Extra_ImageTree2_t * pTree2 = NULL;
146 DdNode * bReached, * bCubeCs;
147 DdNode * bCurrent, * bNext = NULL, * bTemp;
148 DdNode ** pbVarsY;
149 Abc_Obj_t * pLatch;
150 int i, nIters, nBddSize;
151 int nThreshold = 10000;
152
153 // collect the NS variables
154 // set the variable mapping for Cudd_bddVarMap()
155 pbVarsY = ABC_ALLOC( DdNode *, dd->size );
156 Abc_NtkForEachLatch( pNtk, pLatch, i )
157 pbVarsY[i] = dd->vars[ Abc_NtkCiNum(pNtk) + i ];
158
159 // start the image computation
160 bCubeCs = Extra_bddComputeRangeCube( dd, Abc_NtkPiNum(pNtk), Abc_NtkCiNum(pNtk) ); Cudd_Ref( bCubeCs );
161 if ( fPartition )
162 pTree = Extra_bddImageStart( dd, bCubeCs, Abc_NtkLatchNum(pNtk), pbParts, Abc_NtkLatchNum(pNtk), pbVarsY, fVerbose );
163 else
164 pTree2 = Extra_bddImageStart2( dd, bCubeCs, Abc_NtkLatchNum(pNtk), pbParts, Abc_NtkLatchNum(pNtk), pbVarsY, fVerbose );
165 ABC_FREE( pbVarsY );
166 Cudd_RecursiveDeref( dd, bCubeCs );
167
168 // perform reachability analisys
169 bCurrent = bInitial; Cudd_Ref( bCurrent );
170 bReached = bInitial; Cudd_Ref( bReached );
171 assert( nIterMax > 1 ); // required to not deref uninitialized bNext
172 for ( nIters = 1; nIters <= nIterMax; nIters++ )
173 {
174 // compute the next states
175 if ( fPartition )
176 bNext = Extra_bddImageCompute( pTree, bCurrent );
177 else
178 bNext = Extra_bddImageCompute2( pTree2, bCurrent );
179 Cudd_Ref( bNext );
180 Cudd_RecursiveDeref( dd, bCurrent );
181 // remap these states into the current state vars
182 bNext = Cudd_bddVarMap( dd, bTemp = bNext ); Cudd_Ref( bNext );
183 Cudd_RecursiveDeref( dd, bTemp );
184 // check if there are any new states
185 if ( Cudd_bddLeq( dd, bNext, bReached ) )
186 break;
187 // check the BDD size
188 nBddSize = Cudd_DagSize(bNext);
189 if ( nBddSize > nBddMax )
190 break;
191 // check the result
192 if ( !Cudd_bddLeq( dd, bNext, Cudd_Not(bOutput) ) )
193 {
194 printf( "The miter is proved REACHABLE in %d iterations. ", nIters );
195 Cudd_RecursiveDeref( dd, bReached );
196 bReached = NULL;
197 break;
198 }
199 // get the new states
200 bCurrent = Cudd_bddAnd( dd, bNext, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
201 // minimize the new states with the reached states
202// bCurrent = Cudd_bddConstrain( dd, bTemp = bCurrent, Cudd_Not(bReached) ); Cudd_Ref( bCurrent );
203// Cudd_RecursiveDeref( dd, bTemp );
204 // add to the reached states
205 bReached = Cudd_bddOr( dd, bTemp = bReached, bNext ); Cudd_Ref( bReached );
206 Cudd_RecursiveDeref( dd, bTemp );
207 Cudd_RecursiveDeref( dd, bNext );
208 if ( fVerbose )
209 fprintf( stdout, "Iteration = %3d. BDD = %5d. ", nIters, nBddSize );
210 if ( fInternalReorder && fReorder && nBddSize > nThreshold )
211 {
212 if ( fVerbose )
213 fprintf( stdout, "Reordering... Before = %5d. ", Cudd_DagSize(bReached) );
214 Cudd_ReduceHeap( dd, CUDD_REORDER_SYMM_SIFT, 100 );
215 Cudd_AutodynDisable( dd );
216 if ( fVerbose )
217 fprintf( stdout, "After = %5d.\r", Cudd_DagSize(bReached) );
218 nThreshold *= 2;
219 }
220 if ( fVerbose )
221 fprintf( stdout, "\r" );
222 }
223 Cudd_RecursiveDeref( dd, bNext );
224 // undo the image tree
225 if ( fPartition )
227 else
229 if ( bReached == NULL )
230 return NULL;
231 // report the stats
232 if ( fVerbose )
233 {
234 double nMints = Cudd_CountMinterm(dd, bReached, Abc_NtkLatchNum(pNtk) );
235 if ( nIters > nIterMax || Cudd_DagSize(bReached) > nBddMax )
236 fprintf( stdout, "Reachability analysis is stopped after %d iterations.\n", nIters );
237 else
238 fprintf( stdout, "Reachability analysis completed in %d iterations.\n", nIters );
239 fprintf( stdout, "Reachable states = %.0f. (Ratio = %.4f %%)\n", nMints, 100.0*nMints/pow(2.0, Abc_NtkLatchNum(pNtk)) );
240 fflush( stdout );
241 }
242//ABC_PRB( dd, bReached );
243 Cudd_Deref( bReached );
244 if ( nIters > nIterMax || Cudd_DagSize(bReached) > nBddMax )
245 printf( "Verified ONLY FOR STATES REACHED in %d iterations. \n", nIters );
246 printf( "The miter is proved unreachable in %d iteration. ", nIters );
247 return bReached;
248}
249
261void Abc_NtkVerifyUsingBdds( Abc_Ntk_t * pNtk, int nBddMax, int nIterMax, int fPartition, int fReorder, int fVerbose )
262{
263 DdManager * dd;
264 DdNode ** pbParts;
265 DdNode * bOutput, * bReached, * bInitial;
266 int i;
267 abctime clk = Abc_Clock();
268
269 assert( Abc_NtkIsStrash(pNtk) );
270 assert( Abc_NtkPoNum(pNtk) == 1 );
271 assert( Abc_ObjFanoutNum(Abc_NtkPo(pNtk,0)) == 0 ); // PO should go first
272
273 // compute the global BDDs of the latches
274 dd = (DdManager *)Abc_NtkBuildGlobalBdds( pNtk, nBddMax, 1, fReorder, 0, fVerbose );
275 if ( dd == NULL )
276 {
277 printf( "The number of intermediate BDD nodes exceeded the limit (%d).\n", nBddMax );
278 return;
279 }
280 if ( fVerbose )
281 printf( "Shared BDD size is %6d nodes.\n", Cudd_ReadKeys(dd) - Cudd_ReadDead(dd) );
282
283 // save the output BDD
284 bOutput = (DdNode *)Abc_ObjGlobalBdd(Abc_NtkPo(pNtk,0)); Cudd_Ref( bOutput );
285
286 // create partitions
287 pbParts = Abc_NtkCreatePartitions( dd, pNtk, fReorder, fVerbose );
288
289 // create the initial state and the variable map
290 bInitial = Abc_NtkInitStateVarMap( dd, pNtk, fVerbose ); Cudd_Ref( bInitial );
291
292 // check the result
293 if ( !Cudd_bddLeq( dd, bInitial, Cudd_Not(bOutput) ) )
294 printf( "The miter is proved REACHABLE in the initial state. " );
295 else
296 {
297 // compute the reachable states
298 bReached = Abc_NtkComputeReachable( dd, pNtk, pbParts, bInitial, bOutput, nBddMax, nIterMax, fPartition, fReorder, fVerbose );
299 if ( bReached != NULL )
300 {
301 Cudd_Ref( bReached );
302 Cudd_RecursiveDeref( dd, bReached );
303 }
304 }
305
306 // cleanup
307 Cudd_RecursiveDeref( dd, bOutput );
308 Cudd_RecursiveDeref( dd, bInitial );
309 for ( i = 0; i < Abc_NtkLatchNum(pNtk); i++ )
310 Cudd_RecursiveDeref( dd, pbParts[i] );
311 ABC_FREE( pbParts );
312 Extra_StopManager( dd );
313
314 // report the runtime
315 ABC_PRT( "Time", Abc_Clock() - clk );
316 fflush( stdout );
317}
318
319#endif
320
324
325
327
struct Abc_Obj_t_ Abc_Obj_t
Definition abc.h:116
#define Abc_NtkForEachLatch(pNtk, pObj, i)
Definition abc.h:500
struct Abc_Ntk_t_ Abc_Ntk_t
Definition abc.h:115
ABC_DLL void * Abc_NtkFreeGlobalBdds(Abc_Ntk_t *pNtk, int fFreeMan)
ABC_DLL void * Abc_NtkBuildGlobalBdds(Abc_Ntk_t *pNtk, int fBddSizeMax, int fDropInternal, int fReorder, int fReverse, int fVerbose)
ABC_INT64_T abctime
Definition abc_global.h:332
#define ABC_PRT(a, t)
Definition abc_global.h:255
#define ABC_ALLOC(type, num)
Definition abc_global.h:264
#define ABC_FREE(obj)
Definition abc_global.h:267
#define ABC_NAMESPACE_IMPL_START
#define ABC_NAMESPACE_IMPL_END
#define b1
Definition bbrImage.c:97
DdNode * Extra_bddImageCompute2(Extra_ImageTree2_t *pTree, DdNode *bCare)
struct Extra_ImageTree_t_ Extra_ImageTree_t
Definition extraBdd.h:146
Extra_ImageTree2_t * Extra_bddImageStart2(DdManager *dd, DdNode *bCare, int nParts, DdNode **pbParts, int nVars, DdNode **pbVars, int fVerbose)
void Extra_StopManager(DdManager *dd)
void Extra_bddImageTreeDelete2(Extra_ImageTree2_t *pTree)
Extra_ImageTree_t * Extra_bddImageStart(DdManager *dd, DdNode *bCare, int nParts, DdNode **pbParts, int nVars, DdNode **pbVars, int fVerbose)
struct Extra_ImageTree2_t_ Extra_ImageTree2_t
Definition extraBdd.h:155
DdNode * Extra_bddComputeRangeCube(DdManager *dd, int iStart, int iStop)
void Extra_bddImageTreeDelete(Extra_ImageTree_t *pTree)
DdNode * Extra_bddImageCompute(Extra_ImageTree_t *pTree, DdNode *bCare)
#define assert(ex)
Definition util_old.h:213