1 /**CFile****************************************************************
2 
3   FileName    [abcHie.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Network and node package.]
8 
9   Synopsis    [Procedures to handle hierarchy.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: abcHie.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "abc.h"
22 
23 ABC_NAMESPACE_IMPL_START
24 
25 
26 ////////////////////////////////////////////////////////////////////////
27 ///                        DECLARATIONS                              ///
28 ////////////////////////////////////////////////////////////////////////
29 
30 ////////////////////////////////////////////////////////////////////////
31 ///                     FUNCTION DEFINITIONS                         ///
32 ////////////////////////////////////////////////////////////////////////
33 
34 /**Function*************************************************************
35 
36   Synopsis    [Recursively flattens logic hierarchy of the netlist.]
37 
38   Description [When this procedure is called, the PI/PO nets of the old
39   netlist point to the corresponding nets of the flattened netlist.]
40 
41   SideEffects []
42 
43   SeeAlso     []
44 
45 ***********************************************************************/
Abc_NtkFlattenLogicHierarchy2_rec(Abc_Ntk_t * pNtkNew,Abc_Ntk_t * pNtk,int * pCounter)46 void Abc_NtkFlattenLogicHierarchy2_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter )
47 {
48     char Suffix[2000] = {0};
49     Abc_Ntk_t * pNtkModel;
50     Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
51     int i, k;
52 
53     // process the blackbox
54     if ( Abc_NtkHasBlackbox(pNtk) )
55     {
56         // duplicate the blackbox
57         assert( Abc_NtkBoxNum(pNtk) == 1 );
58         pObj = Abc_NtkBox( pNtk, 0 );
59         Abc_NtkDupBox( pNtkNew, pObj, 1 );
60         pObj->pCopy->pData = pNtk;
61 
62         // connect blackbox fanins to the PI nets
63         assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
64         Abc_NtkForEachPi( pNtk, pTerm, i )
65             Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
66 
67         // connect blackbox fanouts to the PO nets
68         assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
69         Abc_NtkForEachPo( pNtk, pTerm, i )
70             Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
71         return;
72     }
73 
74     (*pCounter)++;
75 
76     // create the suffix, which will be appended to the internal names
77     if ( *pCounter )
78         sprintf( Suffix, "_%s_%d", Abc_NtkName(pNtk), *pCounter );
79 
80     // duplicate nets of all boxes, including latches
81     Abc_NtkForEachBox( pNtk, pObj, i )
82     {
83         Abc_ObjForEachFanin( pObj, pTerm, k )
84         {
85             pNet = Abc_ObjFanin0(pTerm);
86             if ( pNet->pCopy )
87                 continue;
88             pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
89         }
90         Abc_ObjForEachFanout( pObj, pTerm, k )
91         {
92             pNet = Abc_ObjFanout0(pTerm);
93             if ( pNet->pCopy )
94                 continue;
95             pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNameSuffix(pNet, Suffix) );
96         }
97     }
98 
99     // mark objects that will not be used
100     Abc_NtkIncrementTravId( pNtk );
101     Abc_NtkForEachPi( pNtk, pTerm, i )
102         Abc_NodeSetTravIdCurrent( pTerm );
103     Abc_NtkForEachPo( pNtk, pTerm, i )
104     {
105         Abc_NodeSetTravIdCurrent( pTerm );
106         // if the netlist has net names beginning with "abc_property_"
107         // these names will be addes as primary outputs of the network
108         pNet = Abc_ObjFanin0(pTerm);
109         if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) )
110             continue;
111         Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy );
112         if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) )
113             Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id);
114         Abc_ObjAssignName( pNet->pCopy, Abc_ObjName(pNet), Suffix );
115     }
116     Abc_NtkForEachBox( pNtk, pObj, i )
117     {
118         if ( Abc_ObjIsLatch(pObj) )
119             continue;
120         Abc_NodeSetTravIdCurrent( pObj );
121         Abc_ObjForEachFanin( pObj, pTerm, k )
122             Abc_NodeSetTravIdCurrent( pTerm );
123         Abc_ObjForEachFanout( pObj, pTerm, k )
124             Abc_NodeSetTravIdCurrent( pTerm );
125     }
126 
127     // duplicate objects that do not have prototypes yet
128     Abc_NtkForEachObj( pNtk, pObj, i )
129     {
130         if ( Abc_NodeIsTravIdCurrent(pObj) )
131             continue;
132         if ( pObj->pCopy )
133             continue;
134         Abc_NtkDupObj( pNtkNew, pObj, 0 );
135     }
136 
137     // connect objects
138     Abc_NtkForEachObj( pNtk, pObj, i )
139         if ( !Abc_NodeIsTravIdCurrent(pObj) )
140             Abc_ObjForEachFanin( pObj, pFanin, k )
141                 if ( !Abc_NodeIsTravIdCurrent(pFanin) )
142                     Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
143 
144     // call recursively
145     Abc_NtkForEachBox( pNtk, pObj, i )
146     {
147         if ( Abc_ObjIsLatch(pObj) )
148             continue;
149         pNtkModel = (Abc_Ntk_t *)pObj->pData;
150         // check the match between the number of actual and formal parameters
151         assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
152         assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
153         // clean the node copy fields
154         Abc_NtkCleanCopy( pNtkModel );
155         // map PIs/POs
156         Abc_ObjForEachFanin( pObj, pTerm, k )
157             Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
158         Abc_ObjForEachFanout( pObj, pTerm, k )
159             Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
160         // call recursively
161         Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtkModel, pCounter );
162     }
163 
164     // if it is a BLIF-MV netlist transfer the values of all nets
165     if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
166     {
167         if ( Abc_NtkMvVar( pNtkNew ) == NULL )
168             Abc_NtkStartMvVars( pNtkNew );
169         Abc_NtkForEachNet( pNtk, pObj, i )
170             Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
171     }
172 }
173 
174 /**Function*************************************************************
175 
176   Synopsis    [Flattens the logic hierarchy of the netlist.]
177 
178   Description []
179 
180   SideEffects []
181 
182   SeeAlso     []
183 
184 ***********************************************************************/
Abc_NtkFlattenLogicHierarchy2(Abc_Ntk_t * pNtk)185 Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy2( Abc_Ntk_t * pNtk )
186 {
187     Abc_Ntk_t * pNtkNew;
188     Abc_Obj_t * pTerm, * pNet;
189     int i, Counter;
190     extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave );
191 
192     assert( Abc_NtkIsNetlist(pNtk) );
193     // start the network
194     pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
195     // duplicate the name and the spec
196     pNtkNew->pName = Abc_UtilStrsav(pNtk->pName);
197     pNtkNew->pSpec = Abc_UtilStrsav(pNtk->pSpec);
198 
199     // clean the node copy fields
200     Abc_NtkCleanCopy( pNtk );
201 
202     // duplicate PIs/POs and their nets
203     Abc_NtkForEachPi( pNtk, pTerm, i )
204     {
205         Abc_NtkDupObj( pNtkNew, pTerm, 0 );
206         pNet = Abc_ObjFanout0( pTerm );
207         pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
208         Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
209     }
210     Abc_NtkForEachPo( pNtk, pTerm, i )
211     {
212         Abc_NtkDupObj( pNtkNew, pTerm, 0 );
213         pNet = Abc_ObjFanin0( pTerm );
214         pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
215         Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
216     }
217 
218     // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
219     Counter = -1;
220     Abc_NtkFlattenLogicHierarchy2_rec( pNtkNew, pNtk, &Counter );
221     printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n",
222         Counter, Abc_NtkBlackboxNum(pNtkNew) );
223 
224     if ( pNtk->pDesign )
225     {
226         // pass on the design
227         assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
228         pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew );
229         // update the pointers
230         Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
231             pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
232     }
233 
234     // we may have added property outputs
235     Abc_NtkOrderCisCos( pNtkNew );
236 
237     // copy the timing information
238 //    Abc_ManTimeDup( pNtk, pNtkNew );
239     // duplicate EXDC
240     if ( pNtk->pExdc )
241         printf( "EXDC is not transformed.\n" );
242     if ( !Abc_NtkCheck( pNtkNew ) )
243     {
244         fprintf( stdout, "Abc_NtkFlattenLogicHierarchy2(): Network check has failed.\n" );
245         Abc_NtkDelete( pNtkNew );
246         return NULL;
247     }
248     return pNtkNew;
249 }
250 
251 
252 
253 /**Function*************************************************************
254 
255   Synopsis    [Recursively flattens logic hierarchy of the netlist.]
256 
257   Description [When this procedure is called, the PI/PO nets of the old
258   netlist point to the corresponding nets of the flattened netlist.]
259 
260   SideEffects []
261 
262   SeeAlso     []
263 
264 ***********************************************************************/
Abc_NtkFlattenLogicHierarchy_rec(Abc_Ntk_t * pNtkNew,Abc_Ntk_t * pNtk,int * pCounter,Vec_Str_t * vPref)265 void Abc_NtkFlattenLogicHierarchy_rec( Abc_Ntk_t * pNtkNew, Abc_Ntk_t * pNtk, int * pCounter, Vec_Str_t * vPref )
266 {
267     Abc_Ntk_t * pNtkModel;
268     Abc_Obj_t * pObj, * pTerm, * pNet, * pFanin;
269     int i, k, Length;
270 
271     // process the blackbox
272     if ( Abc_NtkHasBlackbox(pNtk) )
273     {
274         //printf( "Flatting black box \"%s\".\n", pNtk->pName );
275         // duplicate the blackbox
276         assert( Abc_NtkBoxNum(pNtk) == 1 );
277         pObj = Abc_NtkBox( pNtk, 0 );
278         Abc_NtkDupBox( pNtkNew, pObj, 1 );
279         pObj->pCopy->pData = pNtk;
280 
281         // connect blackbox fanins to the PI nets
282         assert( Abc_ObjFaninNum(pObj->pCopy) == Abc_NtkPiNum(pNtk) );
283         Abc_NtkForEachPi( pNtk, pTerm, i )
284             Abc_ObjAddFanin( Abc_ObjFanin(pObj->pCopy,i), Abc_ObjFanout0(pTerm)->pCopy );
285 
286         // connect blackbox fanouts to the PO nets
287         assert( Abc_ObjFanoutNum(pObj->pCopy) == Abc_NtkPoNum(pNtk) );
288         Abc_NtkForEachPo( pNtk, pTerm, i )
289             Abc_ObjAddFanin( Abc_ObjFanin0(pTerm)->pCopy, Abc_ObjFanout(pObj->pCopy,i) );
290         return;
291     }
292 
293     (*pCounter)++;
294 
295     // create the suffix, which will be appended to the internal names
296     if ( *pCounter )
297     {
298         char Buffer[20];
299         sprintf( Buffer, "(%d)", *pCounter );
300         Vec_StrPrintStr( vPref, Buffer );
301     }
302     Vec_StrPush( vPref, '|' );
303     Vec_StrPush( vPref, 0 );
304 
305     // duplicate nets of all boxes, including latches
306     Abc_NtkForEachBox( pNtk, pObj, i )
307     {
308         Abc_ObjForEachFanin( pObj, pTerm, k )
309         {
310             pNet = Abc_ObjFanin0(pTerm);
311             if ( pNet->pCopy )
312                 continue;
313             pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) );
314         }
315         Abc_ObjForEachFanout( pObj, pTerm, k )
316         {
317             pNet = Abc_ObjFanout0(pTerm);
318             if ( pNet->pCopy )
319                 continue;
320             pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjNamePrefix(pNet, Vec_StrArray(vPref)) );
321         }
322     }
323 
324     // mark objects that will not be used
325     Abc_NtkIncrementTravId( pNtk );
326     Abc_NtkForEachPi( pNtk, pTerm, i )
327         Abc_NodeSetTravIdCurrent( pTerm );
328     Abc_NtkForEachPo( pNtk, pTerm, i )
329     {
330         Abc_NodeSetTravIdCurrent( pTerm );
331         // if the netlist has net names beginning with "abc_property_"
332         // these names will be addes as primary outputs of the network
333         pNet = Abc_ObjFanin0(pTerm);
334         if ( strncmp( Abc_ObjName(pNet), "abc_property", 12 ) )
335             continue;
336         Abc_ObjAddFanin( Abc_NtkCreatePo(pNet->pCopy->pNtk), pNet->pCopy );
337         if ( Nm_ManFindNameById(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id) )
338             Nm_ManDeleteIdName(pNet->pCopy->pNtk->pManName, pNet->pCopy->Id);
339         Abc_ObjAssignName( pNet->pCopy, Vec_StrArray(vPref), Abc_ObjName(pNet) );
340     }
341     Abc_NtkForEachBox( pNtk, pObj, i )
342     {
343         if ( Abc_ObjIsLatch(pObj) )
344             continue;
345         Abc_NodeSetTravIdCurrent( pObj );
346         Abc_ObjForEachFanin( pObj, pTerm, k )
347             Abc_NodeSetTravIdCurrent( pTerm );
348         Abc_ObjForEachFanout( pObj, pTerm, k )
349             Abc_NodeSetTravIdCurrent( pTerm );
350     }
351 
352     // duplicate objects that do not have prototypes yet
353     Abc_NtkForEachObj( pNtk, pObj, i )
354     {
355         if ( Abc_NodeIsTravIdCurrent(pObj) )
356             continue;
357         if ( pObj->pCopy )
358             continue;
359         Abc_NtkDupObj( pNtkNew, pObj, 0 );
360     }
361 
362     // connect objects
363     Abc_NtkForEachObj( pNtk, pObj, i )
364         if ( !Abc_NodeIsTravIdCurrent(pObj) )
365             Abc_ObjForEachFanin( pObj, pFanin, k )
366                 if ( !Abc_NodeIsTravIdCurrent(pFanin) )
367                     Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
368 
369     // call recursively
370     Vec_StrPop( vPref );
371     Length = Vec_StrSize( vPref );
372     Abc_NtkForEachBox( pNtk, pObj, i )
373     {
374         if ( Abc_ObjIsLatch(pObj) )
375             continue;
376         pNtkModel = (Abc_Ntk_t *)pObj->pData;
377         // check the match between the number of actual and formal parameters
378         assert( Abc_ObjFaninNum(pObj) == Abc_NtkPiNum(pNtkModel) );
379         assert( Abc_ObjFanoutNum(pObj) == Abc_NtkPoNum(pNtkModel) );
380         // clean the node copy fields
381         Abc_NtkCleanCopy( pNtkModel );
382         // map PIs/POs
383         Abc_ObjForEachFanin( pObj, pTerm, k )
384             Abc_ObjFanout0( Abc_NtkPi(pNtkModel, k) )->pCopy = Abc_ObjFanin0(pTerm)->pCopy;
385         Abc_ObjForEachFanout( pObj, pTerm, k )
386             Abc_ObjFanin0( Abc_NtkPo(pNtkModel, k) )->pCopy = Abc_ObjFanout0(pTerm)->pCopy;
387         // create name
388         Vec_StrShrink( vPref, Length );
389         Vec_StrPrintStr( vPref, Abc_NtkName(pNtkModel) );
390         // call recursively
391         Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtkModel, pCounter, vPref );
392     }
393 
394     // if it is a BLIF-MV netlist transfer the values of all nets
395     if ( Abc_NtkHasBlifMv(pNtk) && Abc_NtkMvVar(pNtk) )
396     {
397         if ( Abc_NtkMvVar( pNtkNew ) == NULL )
398             Abc_NtkStartMvVars( pNtkNew );
399         Abc_NtkForEachNet( pNtk, pObj, i )
400             Abc_NtkSetMvVarValues( pObj->pCopy, Abc_ObjMvVarNum(pObj) );
401     }
402 }
403 
404 /**Function*************************************************************
405 
406   Synopsis    [Returns 0 if CI names are repeated.]
407 
408   Description []
409 
410   SideEffects []
411 
412   SeeAlso     []
413 
414 ***********************************************************************/
Abc_NtkCompareNames(Abc_Ntk_t ** p1,Abc_Ntk_t ** p2)415 int Abc_NtkCompareNames( Abc_Ntk_t ** p1, Abc_Ntk_t ** p2 )
416 {
417     return strcmp( Abc_NtkName(*p1), Abc_NtkName(*p2) );
418 }
419 
420 /**Function*************************************************************
421 
422   Synopsis    [Prints information about boxes.]
423 
424   Description []
425 
426   SideEffects []
427 
428   SeeAlso     []
429 
430 ***********************************************************************/
Abc_NtkPrintBoxInfo(Abc_Ntk_t * pNtk)431 void Abc_NtkPrintBoxInfo( Abc_Ntk_t * pNtk )
432 {
433     Vec_Ptr_t * vMods;
434     Abc_Ntk_t * pModel, * pBoxModel;
435     Abc_Obj_t * pObj;
436     Vec_Int_t * vCounts;
437     int i, k, Num;
438     if ( pNtk->pDesign == NULL || pNtk->pDesign->vModules == NULL )
439     {
440 //        printf( "There is no hierarchy information.\n" );
441         return;
442     }
443     // sort models by name
444     vMods = pNtk->pDesign->vModules;
445     Vec_PtrSort( vMods, (int(*)())Abc_NtkCompareNames );
446 //    Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
447 //        printf( "%s\n", Abc_NtkName(pModel) );
448 
449     // swap the first model
450     Num = Vec_PtrFind( vMods, pNtk );
451     assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
452     pBoxModel = (Abc_Ntk_t *)Vec_PtrEntry(vMods, 0);
453     Vec_PtrWriteEntry(vMods, 0, (Abc_Ntk_t *)Vec_PtrEntry(vMods, Num) );
454     Vec_PtrWriteEntry(vMods, Num, pBoxModel );
455 
456     // print models
457     vCounts = Vec_IntStart( Vec_PtrSize(vMods) );
458     Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
459     {
460         if ( Abc_NtkBoxNum(pModel) == 0 )
461             continue;
462         Vec_IntFill( vCounts, Vec_IntSize(vCounts), 0 );
463         Abc_NtkForEachBox( pModel, pObj, k )
464         {
465             pBoxModel = (Abc_Ntk_t *)pObj->pData;
466             if ( pBoxModel == NULL )
467                 continue;
468             Num = Vec_PtrFind( vMods, pBoxModel );
469             assert( Num >= 0 && Num < Vec_PtrSize(vMods) );
470             Vec_IntAddToEntry( vCounts, Num, 1 );
471         }
472 
473 //        Abc_NtkPrintStats( pModel, 0, 0, 0, 0, 0, 0, 0, 0, 0 );
474         printf( "MODULE  " );
475         printf( "%-30s : ", Abc_NtkName(pModel) );
476         printf( "PI=%6d ", Abc_NtkPiNum(pModel) );
477         printf( "PO=%6d ", Abc_NtkPoNum(pModel) );
478         printf( "BB=%6d ", Abc_NtkBoxNum(pModel) );
479         printf( "ND=%6d ", Abc_NtkNodeNum(pModel) ); // sans constants
480         printf( "Lev=%5d ", Abc_NtkLevel(pModel) );
481         printf( "\n" );
482 
483         Vec_IntForEachEntry( vCounts, Num, k )
484             if ( Num )
485                 printf( "%15d : %s\n", Num, Abc_NtkName((Abc_Ntk_t *)Vec_PtrEntry(vMods, k)) );
486     }
487     Vec_IntFree( vCounts );
488     Vec_PtrForEachEntry( Abc_Ntk_t *, vMods, pModel, i )
489     {
490         if ( Abc_NtkBoxNum(pModel) != 0 )
491             continue;
492         printf( "MODULE   " );
493         printf( "%-30s : ", Abc_NtkName(pModel) );
494         printf( "PI=%6d ", Abc_NtkPiNum(pModel) );
495         printf( "PO=%6d ", Abc_NtkPoNum(pModel) );
496         printf( "BB=%6d ", Abc_NtkBoxNum(pModel) );
497         printf( "ND=%6d ", Abc_NtkNodeNum(pModel) );
498         printf( "Lev=%5d ", Abc_NtkLevel(pModel) );
499         printf( "\n" );
500     }
501 }
502 
503 /**Function*************************************************************
504 
505   Synopsis    [Flattens the logic hierarchy of the netlist.]
506 
507   Description []
508 
509   SideEffects []
510 
511   SeeAlso     []
512 
513 ***********************************************************************/
Abc_NtkFlattenLogicHierarchy(Abc_Ntk_t * pNtk)514 Abc_Ntk_t * Abc_NtkFlattenLogicHierarchy( Abc_Ntk_t * pNtk )
515 {
516     extern Abc_Des_t * Abc_DesDupBlackboxes( Abc_Des_t * p, Abc_Ntk_t * pNtkSave );
517     Vec_Str_t * vPref;
518     Abc_Ntk_t * pNtkNew;
519     Abc_Obj_t * pTerm, * pNet;
520     int i, Counter = -1;
521 
522     assert( Abc_NtkIsNetlist(pNtk) );
523 //    Abc_NtkPrintBoxInfo( pNtk );
524 
525     // start the network
526     pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
527     // duplicate the name and the spec
528     pNtkNew->pName = Extra_UtilStrsav(pNtk->pName);
529     pNtkNew->pSpec = Extra_UtilStrsav(pNtk->pSpec);
530 
531     // clean the node copy fields
532     Abc_NtkCleanCopy( pNtk );
533 
534     // duplicate PIs/POs and their nets
535     Abc_NtkForEachPi( pNtk, pTerm, i )
536     {
537         Abc_NtkDupObj( pNtkNew, pTerm, 0 );
538         pNet = Abc_ObjFanout0( pTerm );
539         pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
540         Abc_ObjAddFanin( pNet->pCopy, pTerm->pCopy );
541     }
542     Abc_NtkForEachPo( pNtk, pTerm, i )
543     {
544         Abc_NtkDupObj( pNtkNew, pTerm, 0 );
545         pNet = Abc_ObjFanin0( pTerm );
546         pNet->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNet) );
547         Abc_ObjAddFanin( pTerm->pCopy, pNet->pCopy );
548     }
549 
550     // recursively flatten hierarchy, create internal logic, add new PI/PO names if there are black boxes
551     vPref = Vec_StrAlloc( 1000 );
552     Vec_StrPrintStr( vPref, Abc_NtkName(pNtk) );
553     Abc_NtkFlattenLogicHierarchy_rec( pNtkNew, pNtk, &Counter, vPref );
554     printf( "Hierarchy reader flattened %d instances of logic boxes and left %d black boxes.\n",
555         Counter, Abc_NtkBlackboxNum(pNtkNew) );
556     Vec_StrFree( vPref );
557 
558     if ( pNtk->pDesign )
559     {
560         // pass on the design
561         assert( Vec_PtrEntry(pNtk->pDesign->vTops, 0) == pNtk );
562         pNtkNew->pDesign = Abc_DesDupBlackboxes( pNtk->pDesign, pNtkNew );
563         // update the pointers
564         Abc_NtkForEachBlackbox( pNtkNew, pTerm, i )
565             pTerm->pData = ((Abc_Ntk_t *)pTerm->pData)->pCopy;
566     }
567 
568     // we may have added property outputs
569     Abc_NtkOrderCisCos( pNtkNew );
570 
571     // copy the timing information
572 //    Abc_ManTimeDup( pNtk, pNtkNew );
573     // duplicate EXDC
574     if ( pNtk->pExdc )
575         printf( "EXDC is not transformed.\n" );
576     if ( !Abc_NtkCheck( pNtkNew ) )
577     {
578         fprintf( stdout, "Abc_NtkFlattenLogicHierarchy(): Network check has failed.\n" );
579         Abc_NtkDelete( pNtkNew );
580         return NULL;
581     }
582     return pNtkNew;
583 }
584 
585 
586 /**Function*************************************************************
587 
588   Synopsis    [Extracts blackboxes by making them into additional PIs/POs.]
589 
590   Description [The input netlist has not logic hierarchy. The resulting
591   netlist has additional PIs/POs for each blackbox input/output.]
592 
593   SideEffects []
594 
595   SeeAlso     []
596 
597 ***********************************************************************/
Abc_NtkConvertBlackboxes(Abc_Ntk_t * pNtk)598 Abc_Ntk_t * Abc_NtkConvertBlackboxes( Abc_Ntk_t * pNtk )
599 {
600     Abc_Ntk_t * pNtkNew;
601     Abc_Obj_t * pObj, * pNet, * pFanin, * pTerm;
602     int i, k;
603 
604     assert( Abc_NtkIsNetlist(pNtk) );
605     assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
606 
607     // start the network
608     pNtkNew = Abc_NtkAlloc( pNtk->ntkType, pNtk->ntkFunc, 1 );
609     // duplicate the name and the spec
610     pNtkNew->pName = Extra_UtilStrsav( pNtk->pName );
611     pNtkNew->pSpec = Extra_UtilStrsav( pNtk->pSpec );
612 
613     // clean the node copy fields
614     Abc_NtkCleanCopy( pNtk );
615 
616     // mark the nodes that should not be connected
617     Abc_NtkIncrementTravId( pNtk );
618     Abc_NtkForEachBlackbox( pNtk, pObj, i )
619         Abc_NodeSetTravIdCurrent( pObj );
620     Abc_NtkForEachCi( pNtk, pTerm, i )
621         Abc_NodeSetTravIdCurrent( pTerm );
622     Abc_NtkForEachCo( pNtk, pTerm, i )
623         Abc_NodeSetTravIdCurrent( pTerm );
624     // unmark PIs and LIs/LOs
625     Abc_NtkForEachPi( pNtk, pTerm, i )
626         Abc_NodeSetTravIdPrevious( pTerm );
627     Abc_NtkForEachLatchInput( pNtk, pTerm, i )
628         Abc_NodeSetTravIdPrevious( pTerm );
629     Abc_NtkForEachLatchOutput( pNtk, pTerm, i )
630         Abc_NodeSetTravIdPrevious( pTerm );
631     // copy the box outputs
632     Abc_NtkForEachBlackbox( pNtk, pObj, i )
633         Abc_ObjForEachFanout( pObj, pTerm, k )
634             pTerm->pCopy = Abc_NtkCreatePi( pNtkNew );
635 
636     // duplicate other objects
637     Abc_NtkForEachObj( pNtk, pObj, i )
638         if ( !Abc_NodeIsTravIdCurrent(pObj) )
639             Abc_NtkDupObj( pNtkNew, pObj, Abc_ObjIsNet(pObj) );
640 
641     // connect all objects
642     Abc_NtkForEachObj( pNtk, pObj, i )
643         if ( !Abc_NodeIsTravIdCurrent(pObj) )
644             Abc_ObjForEachFanin( pObj, pFanin, k )
645                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
646 
647     // create unique PO for each net feeding into blackboxes or POs
648     Abc_NtkIncrementTravId( pNtk );
649     Abc_NtkForEachCo( pNtk, pTerm, i )
650     {
651         // skip latch inputs
652         assert( Abc_ObjFanoutNum(pTerm) <= 1 );
653         if ( Abc_ObjFanoutNum(pTerm) > 0 && Abc_ObjIsLatch(Abc_ObjFanout0(pTerm)) )
654             continue;
655         // check if the net is visited
656         pNet = Abc_ObjFanin0(pTerm);
657         if ( Abc_NodeIsTravIdCurrent(pNet) )
658             continue;
659         // create PO
660         Abc_NodeSetTravIdCurrent( pNet );
661         Abc_ObjAddFanin( Abc_NtkCreatePo(pNtkNew), pNet->pCopy );
662     }
663 
664     // check integrity
665     if ( !Abc_NtkCheck( pNtkNew ) )
666     {
667         fprintf( stdout, "Abc_NtkConvertBlackboxes(): Network check has failed.\n" );
668         Abc_NtkDelete( pNtkNew );
669         return NULL;
670     }
671     return pNtkNew;
672 }
673 
674 /**Function*************************************************************
675 
676   Synopsis    [Inserts blackboxes into the netlist.]
677 
678   Description [The first arg is the netlist with blackboxes without logic hierarchy.
679   The second arg is a non-hierarchical netlist derived from the above netlist after processing.
680   This procedure create a new netlist, which is comparable to the original netlist with
681   blackboxes, except that it contains logic nodes from the netlist after processing.]
682 
683   SideEffects [This procedure silently assumes that blackboxes appear
684   only in the top-level model. If they appear in other models as well,
685   the name of the model and its number were appended to the names of
686   blackbox inputs/outputs.]
687 
688   SeeAlso     []
689 
690 ***********************************************************************/
Abc_NtkInsertNewLogic(Abc_Ntk_t * pNtkH,Abc_Ntk_t * pNtkL)691 Abc_Ntk_t * Abc_NtkInsertNewLogic( Abc_Ntk_t * pNtkH, Abc_Ntk_t * pNtkL )
692 {
693     Abc_Des_t * pDesign;
694     Abc_Ntk_t * pNtkNew;
695     Abc_Obj_t * pObjH, * pObjL, * pNetH, * pNetL, * pTermH;
696     int i, k;
697 
698     assert( Abc_NtkIsNetlist(pNtkH) );
699     assert( Abc_NtkWhiteboxNum(pNtkH) == 0 );
700     assert( Abc_NtkBlackboxNum(pNtkH) > 0 );
701 
702     assert( Abc_NtkIsNetlist(pNtkL) );
703     assert( Abc_NtkWhiteboxNum(pNtkL) == 0 );
704     assert( Abc_NtkBlackboxNum(pNtkL) == 0 );
705 
706     // prepare the logic network for copying
707     Abc_NtkCleanCopy( pNtkL );
708 
709     // start the network
710     pNtkNew = Abc_NtkAlloc( pNtkL->ntkType, pNtkL->ntkFunc, 1 );
711     // duplicate the name and the spec
712     pNtkNew->pName = Extra_UtilStrsav( pNtkH->pName );
713     pNtkNew->pSpec = Extra_UtilStrsav( pNtkH->pSpec );
714 
715     // make sure every PI/PO has a PI/PO in the processed network
716     Abc_NtkForEachPi( pNtkH, pObjH, i )
717     {
718         pNetH = Abc_ObjFanout0(pObjH);
719         pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
720         if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
721         {
722             printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the PI %s.\n", Abc_ObjName(pNetH) );
723             Abc_NtkDelete( pNtkNew );
724             return NULL;
725         }
726         if ( pNetL->pCopy )
727         {
728             printf( "Error in Abc_NtkInsertNewLogic(): Primary input %s is repeated twice.\n", Abc_ObjName(pNetH) );
729             Abc_NtkDelete( pNtkNew );
730             return NULL;
731         }
732         // create the new net
733         pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
734         Abc_NtkDupObj( pNtkNew, Abc_ObjFanin0(pNetL), 0 );
735     }
736 
737     // make sure every BB has a PI/PO in the processed network
738     Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
739     {
740         // duplicate the box
741         Abc_NtkDupBox( pNtkNew, pObjH, 0 );
742         pObjH->pCopy->pData = pObjH->pData;
743         // create PIs
744         Abc_ObjForEachFanout( pObjH, pTermH, k )
745         {
746             pNetH = Abc_ObjFanout0( pTermH );
747             pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
748             if ( pNetL == NULL || !Abc_ObjIsPi( Abc_ObjFanin0(pNetL) ) )
749             {
750                 printf( "Error in Abc_NtkInsertNewLogic(): There is no PI corresponding to the inpout %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
751                 Abc_NtkDelete( pNtkNew );
752                 return NULL;
753             }
754             if ( pNetL->pCopy )
755             {
756                 printf( "Error in Abc_NtkInsertNewLogic(): Box output %s is repeated twice.\n", Abc_ObjName(pNetH) );
757                 Abc_NtkDelete( pNtkNew );
758                 return NULL;
759             }
760             // create net and map the PI
761             pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
762             Abc_ObjFanin0(pNetL)->pCopy = pTermH->pCopy;
763         }
764     }
765 
766     Abc_NtkForEachPo( pNtkH, pObjH, i )
767     {
768         pNetH = Abc_ObjFanin0(pObjH);
769         pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
770         if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
771         {
772             printf( "Error in Abc_NtkInsertNewLogic(): There is no PO corresponding to the PO %s.\n", Abc_ObjName(pNetH) );
773             Abc_NtkDelete( pNtkNew );
774             return NULL;
775         }
776         if ( pNetL->pCopy )
777             continue;
778         // create the new net
779         pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
780         Abc_NtkDupObj( pNtkNew, Abc_ObjFanout0(pNetL), 0 );
781     }
782     Abc_NtkForEachBlackbox( pNtkH, pObjH, i )
783     {
784         Abc_ObjForEachFanin( pObjH, pTermH, k )
785         {
786             char * pName;
787             pNetH = Abc_ObjFanin0( pTermH );
788             pName = Abc_ObjName(pNetH);
789             pNetL = Abc_NtkFindNet( pNtkL, Abc_ObjName(pNetH) );
790             if ( pNetL == NULL || !Abc_ObjIsPo( Abc_ObjFanout0(pNetL) ) )
791             {
792                 printf( "There is no PO corresponding to the input %s of blackbox %s.\n", Abc_ObjName(pNetH), Abc_ObjName(pObjH) );
793                 Abc_NtkDelete( pNtkNew );
794                 return NULL;
795             }
796             // create net and map the PO
797             if ( pNetL->pCopy )
798             {
799                 if ( Abc_ObjFanout0(pNetL)->pCopy == NULL )
800                     Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
801                 else
802                     Abc_ObjAddFanin( pTermH->pCopy, pNetL->pCopy );
803                 continue;
804             }
805             pNetL->pCopy = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pNetH) );
806             Abc_ObjFanout0(pNetL)->pCopy = pTermH->pCopy;
807         }
808     }
809 
810     // duplicate other objects of the logic network
811     Abc_NtkForEachObj( pNtkL, pObjL, i )
812         if ( pObjL->pCopy == NULL && !Abc_ObjIsPo(pObjL) ) // skip POs feeding into PIs
813             Abc_NtkDupObj( pNtkNew, pObjL, Abc_ObjIsNet(pObjL) );
814 
815     // connect objects
816     Abc_NtkForEachObj( pNtkL, pObjL, i )
817         Abc_ObjForEachFanin( pObjL, pNetL, k )
818             if ( pObjL->pCopy )
819                 Abc_ObjAddFanin( pObjL->pCopy, pNetL->pCopy );
820 
821     // transfer the design
822     pDesign = pNtkH->pDesign;  pNtkH->pDesign = NULL;
823     assert( Vec_PtrEntry( pDesign->vModules, 0 ) == pNtkH );
824     Vec_PtrWriteEntry( pDesign->vModules, 0, pNtkNew );
825     pNtkNew->pDesign = pDesign;
826 
827     // check integrity
828     if ( !Abc_NtkCheck( pNtkNew ) )
829     {
830         fprintf( stdout, "Abc_NtkInsertNewLogic(): Network check has failed.\n" );
831         Abc_NtkDelete( pNtkNew );
832         return NULL;
833     }
834     return pNtkNew;
835 }
836 
837 ////////////////////////////////////////////////////////////////////////
838 ///                       END OF FILE                                ///
839 ////////////////////////////////////////////////////////////////////////
840 
841 
842 ABC_NAMESPACE_IMPL_END
843 
844