1 /**CFile****************************************************************
2 
3   FileName    [abcStrash.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Network and node package.]
8 
9   Synopsis    [Strashing of the current network.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: abcStrash.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "base/abc/abc.h"
22 #include "bool/dec/dec.h"
23 
24 ABC_NAMESPACE_IMPL_START
25 
26 
27 ////////////////////////////////////////////////////////////////////////
28 ///                        DECLARATIONS                              ///
29 ////////////////////////////////////////////////////////////////////////
30 
31 static void Abc_NtkStrashPerform( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord );
32 
33 ////////////////////////////////////////////////////////////////////////
34 ///                     FUNCTION DEFINITIONS                         ///
35 ////////////////////////////////////////////////////////////////////////
36 
37 /**Function*************************************************************
38 
39   Synopsis    [Reapplies structural hashing to the AIG.]
40 
41   Description [Because of the structural hashing, this procedure should not
42   change the number of nodes. It is useful to detect the bugs in the original AIG.]
43 
44   SideEffects []
45 
46   SeeAlso     []
47 
48 ***********************************************************************/
Abc_NtkRestrash(Abc_Ntk_t * pNtk,int fCleanup)49 Abc_Ntk_t * Abc_NtkRestrash( Abc_Ntk_t * pNtk, int fCleanup )
50 {
51 //    extern int timeRetime;
52     Vec_Ptr_t * vNodes;
53     Abc_Ntk_t * pNtkAig;
54     Abc_Obj_t * pObj;
55     int i, nNodes;//, RetValue;
56     assert( Abc_NtkIsStrash(pNtk) );
57 //timeRetime = Abc_Clock();
58     // print warning about choice nodes
59     if ( Abc_NtkGetChoiceNum( pNtk ) )
60         printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
61     // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
62     pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
63     // restrash the nodes (assuming a topological order of the old network)
64     vNodes = Abc_NtkDfs( pNtk, 0 );
65     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
66         pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
67     Vec_PtrFree( vNodes );
68     // finalize the network
69     Abc_NtkFinalize( pNtk, pNtkAig );
70     // print warning about self-feed latches
71 //    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
72 //        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
73     // perform cleanup if requested
74     if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) )
75     {
76 //        printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
77     }
78     // duplicate EXDC
79     if ( pNtk->pExdc )
80         pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
81     // make sure everything is okay
82     if ( !Abc_NtkCheck( pNtkAig ) )
83     {
84         printf( "Abc_NtkStrash: The network check has failed.\n" );
85         Abc_NtkDelete( pNtkAig );
86         return NULL;
87     }
88 //timeRetime = Abc_Clock() - timeRetime;
89 //    if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
90 //        printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
91     return pNtkAig;
92 
93 }
94 
95 /**Function*************************************************************
96 
97   Synopsis    [Performs structural hashing by generating random number.]
98 
99   Description []
100 
101   SideEffects []
102 
103   SeeAlso     []
104 
105 ***********************************************************************/
Abc_NtkRestrashRandom_rec(Abc_Ntk_t * pNtk,Abc_Obj_t * pObj)106 void Abc_NtkRestrashRandom_rec( Abc_Ntk_t * pNtk, Abc_Obj_t * pObj )
107 {
108     if ( Abc_NodeIsTravIdCurrent( pObj ) )
109         return;
110     Abc_NodeSetTravIdCurrent( pObj );
111     if ( !Abc_ObjIsNode(pObj) )
112         return;
113     if ( rand() & 1 )
114     {
115         Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin0(pObj) );
116         Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin1(pObj) );
117     }
118     else
119     {
120         Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin1(pObj) );
121         Abc_NtkRestrashRandom_rec( pNtk, Abc_ObjFanin0(pObj) );
122     }
123     pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
124 }
125 
126 /**Function*************************************************************
127 
128   Synopsis    [Reapplies structural hashing to the AIG.]
129 
130   Description [Because of the structural hashing, this procedure should not
131   change the number of nodes. It is useful to detect the bugs in the original AIG.]
132 
133   SideEffects []
134 
135   SeeAlso     []
136 
137 ***********************************************************************/
Abc_NtkRestrashRandom(Abc_Ntk_t * pNtk)138 Abc_Ntk_t * Abc_NtkRestrashRandom( Abc_Ntk_t * pNtk )
139 {
140     Abc_Ntk_t * pNtkAig;
141     Abc_Obj_t * pObj;
142     int i;
143     assert( Abc_NtkIsStrash(pNtk) );
144     // print warning about choice nodes
145     if ( Abc_NtkGetChoiceNum( pNtk ) )
146         printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
147     // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
148     pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
149     // restrash the nodes (assuming a topological order of the old network)
150     Abc_NtkIncrementTravId( pNtk );
151     Abc_NtkForEachCo( pNtk, pObj, i )
152         Abc_NtkRestrashRandom_rec( pNtkAig, Abc_ObjFanin0(pObj) );
153     // finalize the network
154     Abc_NtkFinalize( pNtk, pNtkAig );
155     // duplicate EXDC
156     if ( pNtk->pExdc )
157         pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
158     // make sure everything is okay
159     if ( !Abc_NtkCheck( pNtkAig ) )
160     {
161         printf( "Abc_NtkStrash: The network check has failed.\n" );
162         Abc_NtkDelete( pNtkAig );
163         return NULL;
164     }
165     return pNtkAig;
166 
167 }
168 
169 /**Function*************************************************************
170 
171   Synopsis    [Reapplies structural hashing to the AIG.]
172 
173   Description [Because of the structural hashing, this procedure should not
174   change the number of nodes. It is useful to detect the bugs in the original AIG.]
175 
176   SideEffects []
177 
178   SeeAlso     []
179 
180 ***********************************************************************/
Abc_NtkRestrashZero(Abc_Ntk_t * pNtk,int fCleanup)181 Abc_Ntk_t * Abc_NtkRestrashZero( Abc_Ntk_t * pNtk, int fCleanup )
182 {
183 //    extern int timeRetime;
184     Abc_Ntk_t * pNtkAig;
185     Abc_Obj_t * pObj;
186     int i, nNodes;//, RetValue;
187     int Counter = 0;
188     assert( Abc_NtkIsStrash(pNtk) );
189 //timeRetime = Abc_Clock();
190     // print warning about choice nodes
191     if ( Abc_NtkGetChoiceNum( pNtk ) )
192         printf( "Warning: The choice nodes in the original AIG are removed by strashing.\n" );
193     // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
194     pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
195     // complement the 1-values registers
196     Abc_NtkForEachLatch( pNtk, pObj, i )
197     {
198         if ( Abc_LatchIsInitDc(pObj) )
199             Counter++;
200         else if ( Abc_LatchIsInit1(pObj) )
201             Abc_ObjFanout0(pObj)->pCopy = Abc_ObjNot(Abc_ObjFanout0(pObj)->pCopy);
202     }
203     if ( Counter )
204     printf( "Converting %d flops from don't-care to zero initial value.\n", Counter );
205     // restrash the nodes (assuming a topological order of the old network)
206     Abc_NtkForEachNode( pNtk, pObj, i )
207         pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
208     // finalize the network
209     Abc_NtkFinalize( pNtk, pNtkAig );
210     // complement the 1-valued registers
211     Abc_NtkForEachLatch( pNtkAig, pObj, i )
212         if ( Abc_LatchIsInit1(pObj) )
213         {
214             Abc_ObjXorFaninC( Abc_ObjFanin0(pObj), 0 );
215             // if latch has PO as one of its fanouts change latch name
216             if ( Abc_NodeFindCoFanout( Abc_ObjFanout0(pObj) ) )
217             {
218                 Nm_ManDeleteIdName( pObj->pNtk->pManName, Abc_ObjFanout0(pObj)->Id );
219                 Abc_ObjAssignName( Abc_ObjFanout0(pObj), Abc_ObjName(Abc_ObjFanout0(pObj)), "_inv" );
220             }
221         }
222     // set all constant-0 values
223     Abc_NtkForEachLatch( pNtkAig, pObj, i )
224         Abc_LatchSetInit0( pObj );
225 
226     // print warning about self-feed latches
227 //    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
228 //        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
229     // perform cleanup if requested
230     if ( fCleanup && (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) )
231         printf( "Abc_NtkRestrash(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
232     // duplicate EXDC
233     if ( pNtk->pExdc )
234         pNtkAig->pExdc = Abc_NtkDup( pNtk->pExdc );
235     // transfer name IDs
236     if ( pNtk->vNameIds )
237         Abc_NtkTransferNameIds( pNtk, pNtkAig );
238     if ( pNtk->vNameIds )
239         Abc_NtkUpdateNameIds( pNtkAig );
240     // make sure everything is okay
241     if ( !Abc_NtkCheck( pNtkAig ) )
242     {
243         printf( "Abc_NtkStrash: The network check has failed.\n" );
244         Abc_NtkDelete( pNtkAig );
245         return NULL;
246     }
247 //timeRetime = Abc_Clock() - timeRetime;
248 //    if ( RetValue = Abc_NtkRemoveSelfFeedLatches(pNtkAig) )
249 //        printf( "Modified %d self-feeding latches. The result may not verify.\n", RetValue );
250     return pNtkAig;
251 
252 }
253 
254 /**Function*************************************************************
255 
256   Synopsis    [Transforms logic network into structurally hashed AIG.]
257 
258   Description []
259 
260   SideEffects []
261 
262   SeeAlso     []
263 
264 ***********************************************************************/
Abc_NtkStrash(Abc_Ntk_t * pNtk,int fAllNodes,int fCleanup,int fRecord)265 Abc_Ntk_t * Abc_NtkStrash( Abc_Ntk_t * pNtk, int fAllNodes, int fCleanup, int fRecord )
266 {
267     Abc_Ntk_t * pNtkAig;
268     int nNodes;
269     assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
270     // consider the special case when the network is already structurally hashed
271     if ( Abc_NtkIsStrash(pNtk) )
272         return Abc_NtkRestrash( pNtk, fCleanup );
273     // convert the node representation in the logic network to the AIG form
274     if ( !Abc_NtkToAig(pNtk) )
275     {
276         printf( "Converting to AIGs has failed.\n" );
277         return NULL;
278     }
279     // perform strashing
280 //    Abc_NtkCleanCopy( pNtk );
281     pNtkAig = Abc_NtkStartFrom( pNtk, ABC_NTK_STRASH, ABC_FUNC_AIG );
282     Abc_NtkStrashPerform( pNtk, pNtkAig, fAllNodes, fRecord );
283     Abc_NtkFinalize( pNtk, pNtkAig );
284     // transfer name IDs
285     if ( pNtk->vNameIds )
286         Abc_NtkTransferNameIds( pNtk, pNtkAig );
287     // print warning about self-feed latches
288 //    if ( Abc_NtkCountSelfFeedLatches(pNtkAig) )
289 //        printf( "Warning: The network has %d self-feeding latches.\n", Abc_NtkCountSelfFeedLatches(pNtkAig) );
290     // perform cleanup if requested
291     nNodes = fCleanup? Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc) : 0;
292 //    if ( nNodes )
293 //        printf( "Warning: AIG cleanup removed %d nodes (this is not a bug).\n", nNodes );
294     // duplicate EXDC
295     if ( pNtk->pExdc )
296         pNtkAig->pExdc = Abc_NtkStrash( pNtk->pExdc, fAllNodes, fCleanup, fRecord );
297     // make sure everything is okay
298     if ( !Abc_NtkCheck( pNtkAig ) )
299     {
300         printf( "Abc_NtkStrash: The network check has failed.\n" );
301         Abc_NtkDelete( pNtkAig );
302         return NULL;
303     }
304     return pNtkAig;
305 }
306 
307 /**Function*************************************************************
308 
309   Synopsis    [Appends the second network to the first.]
310 
311   Description [Modifies the first network by adding the logic of the second.
312   Performs structural hashing while appending the networks. Does not change
313   the second network. Returns 0 if the appending failed, 1 otherise.]
314 
315   SideEffects []
316 
317   SeeAlso     []
318 
319 ***********************************************************************/
Abc_NtkAppend(Abc_Ntk_t * pNtk1,Abc_Ntk_t * pNtk2,int fAddPos)320 int Abc_NtkAppend( Abc_Ntk_t * pNtk1, Abc_Ntk_t * pNtk2, int fAddPos )
321 {
322     Abc_Obj_t * pObj;
323     char * pName;
324     int i, nNewCis;
325     // the first network should be an AIG
326     assert( Abc_NtkIsStrash(pNtk1) );
327     assert( Abc_NtkIsLogic(pNtk2) || Abc_NtkIsStrash(pNtk2) );
328     if ( Abc_NtkIsLogic(pNtk2) && !Abc_NtkToAig(pNtk2) )
329     {
330         printf( "Converting to AIGs has failed.\n" );
331         return 0;
332     }
333     // check that the networks have the same PIs
334     // reorder PIs of pNtk2 according to pNtk1
335     if ( !Abc_NtkCompareSignals( pNtk1, pNtk2, 1, 1 ) )
336         printf( "Abc_NtkAppend(): The union of the network PIs is computed (warning).\n" );
337     // perform strashing
338     nNewCis = 0;
339     Abc_NtkCleanCopy( pNtk2 );
340     if ( Abc_NtkIsStrash(pNtk2) )
341         Abc_AigConst1(pNtk2)->pCopy = Abc_AigConst1(pNtk1);
342     Abc_NtkForEachCi( pNtk2, pObj, i )
343     {
344         pName = Abc_ObjName(pObj);
345         pObj->pCopy = Abc_NtkFindCi(pNtk1, Abc_ObjName(pObj));
346         if ( pObj->pCopy == NULL )
347         {
348             pObj->pCopy = Abc_NtkDupObj(pNtk1, pObj, 1);
349             nNewCis++;
350         }
351     }
352     if ( nNewCis )
353         printf( "Warning: Procedure Abc_NtkAppend() added %d new CIs.\n", nNewCis );
354     // add pNtk2 to pNtk1 while strashing
355     if ( Abc_NtkIsLogic(pNtk2) )
356         Abc_NtkStrashPerform( pNtk2, pNtk1, 1, 0 );
357     else
358         Abc_NtkForEachNode( pNtk2, pObj, i )
359             pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtk1->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
360     // add the COs of the second network
361     if ( fAddPos )
362     {
363         Abc_NtkForEachPo( pNtk2, pObj, i )
364         {
365             Abc_NtkDupObj( pNtk1, pObj, 0 );
366             Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
367             Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(pObj), NULL );
368         }
369     }
370     else
371     {
372         Abc_Obj_t * pObjOld, * pDriverOld, * pDriverNew;
373         int fCompl, iNodeId;
374         // OR the choices
375         Abc_NtkForEachCo( pNtk2, pObj, i )
376         {
377             iNodeId = Nm_ManFindIdByNameTwoTypes( pNtk1->pManName, Abc_ObjName(pObj), ABC_OBJ_PO, ABC_OBJ_BI );
378 //            if ( iNodeId < 0 )
379 //                continue;
380             assert( iNodeId >= 0 );
381             pObjOld = Abc_NtkObj( pNtk1, iNodeId );
382             // derive the new driver
383             pDriverOld = Abc_ObjChild0( pObjOld );
384             pDriverNew = Abc_ObjChild0Copy( pObj );
385             pDriverNew = Abc_AigOr( (Abc_Aig_t *)pNtk1->pManFunc, pDriverOld, pDriverNew );
386             if ( Abc_ObjRegular(pDriverOld) == Abc_ObjRegular(pDriverNew) )
387                 continue;
388             // replace the old driver by the new driver
389             fCompl = Abc_ObjRegular(pDriverOld)->fPhase ^ Abc_ObjRegular(pDriverNew)->fPhase;
390             Abc_ObjPatchFanin( pObjOld, Abc_ObjRegular(pDriverOld), Abc_ObjNotCond(Abc_ObjRegular(pDriverNew), fCompl) );
391         }
392     }
393     // make sure that everything is okay
394     if ( !Abc_NtkCheck( pNtk1 ) )
395     {
396         printf( "Abc_NtkAppend: The network check has failed.\n" );
397         return 0;
398     }
399     return 1;
400 }
401 
402 /**Function*************************************************************
403 
404   Synopsis    [Prepares the network for strashing.]
405 
406   Description []
407 
408   SideEffects []
409 
410   SeeAlso     []
411 
412 ***********************************************************************/
Abc_NtkStrashPerform(Abc_Ntk_t * pNtkOld,Abc_Ntk_t * pNtkNew,int fAllNodes,int fRecord)413 void Abc_NtkStrashPerform( Abc_Ntk_t * pNtkOld, Abc_Ntk_t * pNtkNew, int fAllNodes, int fRecord )
414 {
415     Vec_Ptr_t * vNodes;
416     Abc_Obj_t * pNodeOld;
417     int i; //, clk = Abc_Clock();
418     assert( Abc_NtkIsLogic(pNtkOld) );
419     assert( Abc_NtkIsStrash(pNtkNew) );
420 //    vNodes = Abc_NtkDfs( pNtkOld, fAllNodes );
421     vNodes = Abc_NtkDfsIter( pNtkOld, fAllNodes );
422 //printf( "Nodes = %d. ", Vec_PtrSize(vNodes) );
423 //ABC_PRT( "Time", Abc_Clock() - clk );
424     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pNodeOld, i )
425     {
426         if ( Abc_ObjIsBarBuf(pNodeOld) )
427             pNodeOld->pCopy = Abc_ObjChild0Copy(pNodeOld);
428         else
429             pNodeOld->pCopy = Abc_NodeStrash( pNtkNew, pNodeOld, fRecord );
430     }
431     Vec_PtrFree( vNodes );
432 }
433 
434 /**Function*************************************************************
435 
436   Synopsis    [Transfers the AIG from one manager into another.]
437 
438   Description []
439 
440   SideEffects []
441 
442   SeeAlso     []
443 
444 ***********************************************************************/
Abc_NodeStrash_rec(Abc_Aig_t * pMan,Hop_Obj_t * pObj)445 void Abc_NodeStrash_rec( Abc_Aig_t * pMan, Hop_Obj_t * pObj )
446 {
447     assert( !Hop_IsComplement(pObj) );
448     if ( !Hop_ObjIsNode(pObj) || Hop_ObjIsMarkA(pObj) )
449         return;
450     Abc_NodeStrash_rec( pMan, Hop_ObjFanin0(pObj) );
451     Abc_NodeStrash_rec( pMan, Hop_ObjFanin1(pObj) );
452     pObj->pData = Abc_AigAnd( pMan, (Abc_Obj_t *)Hop_ObjChild0Copy(pObj), (Abc_Obj_t *)Hop_ObjChild1Copy(pObj) );
453     assert( !Hop_ObjIsMarkA(pObj) ); // loop detection
454     Hop_ObjSetMarkA( pObj );
455 }
456 
457 /**Function*************************************************************
458 
459   Synopsis    [Strashes one logic node.]
460 
461   Description [Assume the network is in the AIG form]
462 
463   SideEffects []
464 
465   SeeAlso     []
466 
467 ***********************************************************************/
Abc_NodeStrash(Abc_Ntk_t * pNtkNew,Abc_Obj_t * pNodeOld,int fRecord)468 Abc_Obj_t * Abc_NodeStrash( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNodeOld, int fRecord )
469 {
470     Hop_Man_t * pMan;
471     Hop_Obj_t * pRoot;
472     Abc_Obj_t * pFanin;
473     int i;
474     assert( Abc_ObjIsNode(pNodeOld) );
475     assert( Abc_NtkHasAig(pNodeOld->pNtk) && !Abc_NtkIsStrash(pNodeOld->pNtk) );
476     // get the local AIG manager and the local root node
477     pMan = (Hop_Man_t *)pNodeOld->pNtk->pManFunc;
478     pRoot = (Hop_Obj_t *)pNodeOld->pData;
479     // check the constant case
480     if ( Abc_NodeIsConst(pNodeOld) || Hop_Regular(pRoot) == Hop_ManConst1(pMan) )
481         return Abc_ObjNotCond( Abc_AigConst1(pNtkNew), Hop_IsComplement(pRoot) );
482     // perform special case-strashing using the record of AIG subgraphs
483 /*
484     if ( fRecord && Abc_NtkRecIsRunning() && Abc_ObjFaninNum(pNodeOld) > 2 && Abc_ObjFaninNum(pNodeOld) <= Abc_NtkRecVarNum() )
485     {
486         extern Vec_Int_t * Abc_NtkRecMemory();
487         extern int Abc_NtkRecStrashNode( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pObj, unsigned * pTruth, int nVars );
488         int nVars = Abc_NtkRecVarNum();
489         Vec_Int_t * vMemory = Abc_NtkRecMemory();
490         unsigned * pTruth = Hop_ManConvertAigToTruth( pMan, Hop_Regular(pRoot), nVars, vMemory, 0 );
491         assert( Extra_TruthSupportSize(pTruth, nVars) == Abc_ObjFaninNum(pNodeOld) ); // should be swept
492         if ( Hop_IsComplement(pRoot) )
493             Extra_TruthNot( pTruth, pTruth, nVars );
494         if ( Abc_NtkRecStrashNode( pNtkNew, pNodeOld, pTruth, nVars ) )
495             return pNodeOld->pCopy;
496     }
497 */
498     // set elementary variables
499     Abc_ObjForEachFanin( pNodeOld, pFanin, i )
500         Hop_IthVar(pMan, i)->pData = pFanin->pCopy;
501     // strash the AIG of this node
502     Abc_NodeStrash_rec( (Abc_Aig_t *)pNtkNew->pManFunc, Hop_Regular(pRoot) );
503     Hop_ConeUnmark_rec( Hop_Regular(pRoot) );
504     // return the final node
505     return Abc_ObjNotCond( (Abc_Obj_t *)Hop_Regular(pRoot)->pData, Hop_IsComplement(pRoot) );
506 }
507 
508 
509 
510 
511 
512 
513 
514 /**Function*************************************************************
515 
516   Synopsis    [Copies the topmost levels of the network.]
517 
518   Description []
519 
520   SideEffects []
521 
522   SeeAlso     []
523 
524 ***********************************************************************/
Abc_NtkTopmost_rec(Abc_Ntk_t * pNtkNew,Abc_Obj_t * pNode,int LevelCut)525 Abc_Obj_t * Abc_NtkTopmost_rec( Abc_Ntk_t * pNtkNew, Abc_Obj_t * pNode, int LevelCut )
526 {
527     assert( !Abc_ObjIsComplement(pNode) );
528     if ( pNode->pCopy )
529         return pNode->pCopy;
530     if ( pNode->Level <= (unsigned)LevelCut )
531         return pNode->pCopy = Abc_NtkCreatePi( pNtkNew );
532     Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(pNode), LevelCut );
533     Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin1(pNode), LevelCut );
534     return pNode->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkNew->pManFunc, Abc_ObjChild0Copy(pNode), Abc_ObjChild1Copy(pNode) );
535 }
536 
537 /**Function*************************************************************
538 
539   Synopsis    [Copies the topmost levels of the network.]
540 
541   Description []
542 
543   SideEffects []
544 
545   SeeAlso     []
546 
547 ***********************************************************************/
Abc_NtkTopmost(Abc_Ntk_t * pNtk,int nLevels)548 Abc_Ntk_t * Abc_NtkTopmost( Abc_Ntk_t * pNtk, int nLevels )
549 {
550     Abc_Ntk_t * pNtkNew;
551     Abc_Obj_t * pObjNew, * pObjPo;
552     int LevelCut;
553     assert( Abc_NtkIsStrash(pNtk) );
554     assert( Abc_NtkCoNum(pNtk) == 1 );
555     // get the cutoff level
556     LevelCut = Abc_MaxInt( 0, Abc_AigLevel(pNtk) - nLevels );
557     // start the network
558     pNtkNew = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
559     pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
560     Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkNew);
561     // create PIs below the cut and nodes above the cut
562     Abc_NtkCleanCopy( pNtk );
563     pObjNew = Abc_NtkTopmost_rec( pNtkNew, Abc_ObjFanin0(Abc_NtkPo(pNtk, 0)), LevelCut );
564     pObjNew = Abc_ObjNotCond( pObjNew, Abc_ObjFaninC0(Abc_NtkPo(pNtk, 0)) );
565     // add the PO node and name
566     pObjPo = Abc_NtkCreatePo(pNtkNew);
567     Abc_ObjAddFanin( pObjPo, pObjNew );
568     Abc_NtkAddDummyPiNames( pNtkNew );
569     Abc_ObjAssignName( pObjPo, Abc_ObjName(Abc_NtkPo(pNtk, 0)), NULL );
570     // make sure everything is okay
571     if ( !Abc_NtkCheck( pNtkNew ) )
572     {
573         printf( "Abc_NtkTopmost: The network check has failed.\n" );
574         Abc_NtkDelete( pNtkNew );
575         return NULL;
576     }
577     return pNtkNew;
578 }
579 
580 
581 
582 /**Function*************************************************************
583 
584   Synopsis    [Comparison procedure for two integers.]
585 
586   Description []
587 
588   SideEffects []
589 
590   SeeAlso     []
591 
592 ***********************************************************************/
Vec_CompareNodeIds(Abc_Obj_t ** pp1,Abc_Obj_t ** pp2)593 static int Vec_CompareNodeIds( Abc_Obj_t ** pp1, Abc_Obj_t ** pp2 )
594 {
595     if ( Abc_ObjRegular(*pp1)->Id < Abc_ObjRegular(*pp2)->Id )
596         return -1;
597     if ( Abc_ObjRegular(*pp1)->Id > Abc_ObjRegular(*pp2)->Id ) //
598         return 1;
599     return 0;
600 }
601 
602 /**Function*************************************************************
603 
604   Synopsis    [Collects the large supergate.]
605 
606   Description []
607 
608   SideEffects []
609 
610   SeeAlso     []
611 
612 ***********************************************************************/
Abc_NodeGetSuper(Abc_Obj_t * pNode)613 Vec_Ptr_t * Abc_NodeGetSuper( Abc_Obj_t * pNode )
614 {
615     Vec_Ptr_t * vSuper, * vFront;
616     Abc_Obj_t * pAnd, * pFanin;
617     int i;
618     assert( Abc_ObjIsNode(pNode) && !Abc_ObjIsComplement(pNode) );
619     vSuper = Vec_PtrAlloc( 100 );
620     // explore the frontier
621     vFront = Vec_PtrAlloc( 100 );
622     Vec_PtrPush( vFront, pNode );
623     Vec_PtrForEachEntry( Abc_Obj_t *, vFront, pAnd, i )
624     {
625         pFanin = Abc_ObjChild0(pAnd);
626         if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
627             Vec_PtrPush( vFront, pFanin );
628         else
629             Vec_PtrPush( vSuper, pFanin );
630 
631         pFanin = Abc_ObjChild1(pAnd);
632         if ( Abc_ObjIsNode(pFanin) && !Abc_ObjIsComplement(pFanin) && Abc_ObjFanoutNum(pFanin) == 1 )
633             Vec_PtrPush( vFront, pFanin );
634         else
635             Vec_PtrPush( vSuper, pFanin );
636     }
637     Vec_PtrFree( vFront );
638     // reverse the array of pointers to start with lower IDs
639     vFront = Vec_PtrAlloc( Vec_PtrSize(vSuper) );
640     Vec_PtrForEachEntryReverse( Abc_Obj_t *, vSuper, pNode, i )
641         Vec_PtrPush( vFront, pNode );
642     Vec_PtrFree( vSuper );
643     vSuper = vFront;
644     // uniquify and return the frontier
645     Vec_PtrUniqify( vSuper, (int (*)())Vec_CompareNodeIds );
646     return vSuper;
647 }
648 
649 /**Function*************************************************************
650 
651   Synopsis    [Copies the topmost levels of the network.]
652 
653   Description []
654 
655   SideEffects []
656 
657   SeeAlso     []
658 
659 ***********************************************************************/
Abc_NtkTopAnd(Abc_Ntk_t * pNtk)660 Abc_Ntk_t * Abc_NtkTopAnd( Abc_Ntk_t * pNtk )
661 {
662     Vec_Ptr_t * vNodes, * vOrder;
663     Abc_Ntk_t * pNtkAig;
664     Abc_Obj_t * pObj, * pDriver, * pObjPo;
665     int i, nNodes;
666     assert( Abc_NtkIsStrash(pNtk) );
667     // get the first PO
668     pObjPo = Abc_NtkPo(pNtk, 0);
669     vNodes = Abc_NodeGetSuper( Abc_ObjChild0(pObjPo) );
670     assert( Vec_PtrSize(vNodes) >= 2 );
671     // start the new network (constants and CIs of the old network will point to the their counterparts in the new network)
672     Abc_NtkCleanCopy( pNtk );
673     pNtkAig = Abc_NtkAlloc( ABC_NTK_STRASH, ABC_FUNC_AIG, 1 );
674     pNtkAig->pName = Extra_UtilStrsav(pNtk->pName);
675     pNtkAig->pSpec = Extra_UtilStrsav(pNtk->pSpec);
676     Abc_AigConst1(pNtk)->pCopy = Abc_AigConst1(pNtkAig);
677     Abc_NtkForEachPi( pNtk, pObj, i )
678         Abc_NtkDupObj( pNtkAig, pObj, 1 );
679     // restrash the nodes reachable from the roots
680     vOrder = Abc_NtkDfsIterNodes( pNtk, vNodes );
681     Vec_PtrForEachEntry( Abc_Obj_t *, vOrder, pObj, i )
682         pObj->pCopy = Abc_AigAnd( (Abc_Aig_t *)pNtkAig->pManFunc, Abc_ObjChild0Copy(pObj), Abc_ObjChild1Copy(pObj) );
683     Vec_PtrFree( vOrder );
684     // finalize the network
685     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
686     {
687         pObjPo = Abc_NtkCreatePo(pNtkAig);
688         pDriver = Abc_ObjNotCond(Abc_ObjRegular(pObj)->pCopy, Abc_ObjIsComplement(pObj));
689         Abc_ObjAddFanin( pObjPo, pDriver );
690         Abc_ObjAssignName( pObjPo, Abc_ObjName(pObjPo), NULL );
691     }
692     Vec_PtrFree( vNodes );
693     // perform cleanup if requested
694     if ( (nNodes = Abc_AigCleanup((Abc_Aig_t *)pNtkAig->pManFunc)) )
695         printf( "Abc_NtkTopAnd(): AIG cleanup removed %d nodes (this is a bug).\n", nNodes );
696     // make sure everything is okay
697     if ( !Abc_NtkCheck( pNtkAig ) )
698     {
699         printf( "Abc_NtkStrash: The network check has failed.\n" );
700         Abc_NtkDelete( pNtkAig );
701         return NULL;
702     }
703     return pNtkAig;
704 }
705 
706 /**Function*************************************************************
707 
708   Synopsis    [Writes the AIG into a file for parsing.]
709 
710   Description [Ordering: c0, pis, ands, pos. ]
711 
712   SideEffects []
713 
714   SeeAlso     []
715 
716 ***********************************************************************/
Abc_NtkWriteAig(Abc_Ntk_t * pNtk,char * pFileName)717 void Abc_NtkWriteAig( Abc_Ntk_t * pNtk, char * pFileName )
718 {
719     FILE * pFile;
720     Vec_Int_t * vId2Num;
721     Abc_Obj_t * pObj;
722     int i, iLit;
723     assert( Abc_NtkIsStrash(pNtk) );
724     assert( Abc_NtkLatchNum(pNtk) == 0 );
725     if ( pFileName == NULL )
726         pFile = stdout;
727     else
728         pFile = fopen( pFileName, "w" );
729     if ( pFile == NULL )
730     {
731         printf( "Cannot open output file.\n" );
732         return;
733     }
734     vId2Num = Vec_IntAlloc( 2*Abc_NtkObjNumMax(pNtk) );
735     Vec_IntFill( vId2Num, 2*Abc_NtkObjNumMax(pNtk), -1 );
736 
737     iLit = 0;
738     Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+1, iLit++ );
739     Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(Abc_AigConst1(pNtk))+0, iLit++ );
740     Abc_NtkForEachPi( pNtk, pObj, i )
741     {
742         Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ );
743         Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ );
744     }
745     Abc_AigForEachAnd( pNtk, pObj, i )
746     {
747         Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+0, iLit++ );
748         Vec_IntWriteEntry( vId2Num, 2*Abc_ObjId(pObj)+1, iLit++ );
749     }
750     fprintf( pFile, "{\n" );
751     fprintf( pFile, "    \"%s\", ", Abc_NtkName(pNtk) );
752     fprintf( pFile, "//  pi=%d  po=%d  and=%d", Abc_NtkPiNum(pNtk), Abc_NtkPoNum(pNtk), Abc_NtkNodeNum(pNtk) );
753     fprintf( pFile, "\n" );
754     fprintf( pFile, "    { " );
755     Abc_NtkForEachPi( pNtk, pObj, i )
756         fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) );
757     fprintf( pFile, "NULL },\n" );
758     fprintf( pFile, "    { " );
759     Abc_NtkForEachPo( pNtk, pObj, i )
760         fprintf( pFile, "\"%s\",", Abc_ObjName(pObj) );
761     fprintf( pFile, "NULL },\n" );
762     fprintf( pFile, "    { " );
763     Abc_AigForEachAnd( pNtk, pObj, i )
764         fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) );
765     fprintf( pFile, "0 },\n" );
766     fprintf( pFile, "    { " );
767     Abc_AigForEachAnd( pNtk, pObj, i )
768         fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId1(pObj) + Abc_ObjFaninC1(pObj)) );
769     fprintf( pFile, "0 },\n" );
770     fprintf( pFile, "    { " );
771     Abc_NtkForEachPo( pNtk, pObj, i )
772         fprintf( pFile, "%d,", Vec_IntEntry(vId2Num, 2*Abc_ObjFaninId0(pObj) + Abc_ObjFaninC0(pObj)) );
773     fprintf( pFile, "0 },\n" );
774     fprintf( pFile, "},\n" );
775     if ( pFile != stdout )
776         fclose( pFile );
777     Vec_IntFree( vId2Num );
778 }
779 
780 /**Function*************************************************************
781 
782   Synopsis    []
783 
784   Description []
785 
786   SideEffects []
787 
788   SeeAlso     []
789 
790 ***********************************************************************/
Abc_NtkPutOnTop(Abc_Ntk_t * pNtk,Abc_Ntk_t * pNtk2)791 Abc_Ntk_t * Abc_NtkPutOnTop( Abc_Ntk_t * pNtk, Abc_Ntk_t * pNtk2 )
792 {
793     Vec_Ptr_t * vNodes;
794     Abc_Ntk_t * pNtkNew;
795     Abc_Obj_t * pObj, * pFanin;
796     int i, k;
797     assert( Abc_NtkIsLogic(pNtk) );
798     assert( Abc_NtkIsLogic(pNtk2) );
799     assert( Abc_NtkPoNum(pNtk) == Abc_NtkPiNum(pNtk2) );
800     // clean the node copy fields
801     Abc_NtkCleanCopy( pNtk );
802     Abc_NtkCleanCopy( pNtk2 );
803     // duplicate the name and the spec
804     pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
805     pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
806     pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
807     // clone CIs/CIs/boxes
808     Abc_NtkForEachPi( pNtk, pObj, i )
809         Abc_NtkDupObj( pNtkNew, pObj, 1 );
810     // add internal nodes
811     vNodes = Abc_NtkDfs( pNtk, 0 );
812     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
813     {
814         Abc_NtkDupObj( pNtkNew, pObj, 0 );
815         Abc_ObjForEachFanin( pObj, pFanin, k )
816             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
817     }
818     Vec_PtrFree( vNodes );
819     // transfer to the POs
820     Abc_NtkForEachPi( pNtk2, pObj, i )
821         pObj->pCopy = Abc_ObjChild0Copy( Abc_NtkPo(pNtk, i) );
822     // add internal nodes
823     vNodes = Abc_NtkDfs( pNtk2, 0 );
824     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
825     {
826         Abc_NtkDupObj( pNtkNew, pObj, 0 );
827         Abc_ObjForEachFanin( pObj, pFanin, k )
828             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
829     }
830     Vec_PtrFree( vNodes );
831     // clone CIs/CIs/boxes
832     Abc_NtkForEachPo( pNtk2, pObj, i )
833     {
834         Abc_NtkDupObj( pNtkNew, pObj, 1 );
835         Abc_ObjAddFanin( pObj->pCopy, Abc_ObjChild0Copy(pObj) );
836     }
837     if ( !Abc_NtkCheck( pNtkNew ) )
838         fprintf( stdout, "Abc_NtkPutOnTop(): Network check has failed.\n" );
839     return pNtkNew;
840 }
841 
842 ////////////////////////////////////////////////////////////////////////
843 ///                       END OF FILE                                ///
844 ////////////////////////////////////////////////////////////////////////
845 
846 
847 ABC_NAMESPACE_IMPL_END
848 
849