1 /**CFile****************************************************************
2 
3   FileName    [abcNetlist.c]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Network and node package.]
8 
9   Synopsis    [Transforms netlist into a logic network and vice versa.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - June 20, 2005.]
16 
17   Revision    [$Id: abcNetlist.c,v 1.00 2005/06/20 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #include "abc.h"
22 #include "base/main/main.h"
23 //#include "seq.h"
24 
25 ABC_NAMESPACE_IMPL_START
26 
27 
28 ////////////////////////////////////////////////////////////////////////
29 ///                        DECLARATIONS                              ///
30 ////////////////////////////////////////////////////////////////////////
31 
32 static void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk );
33 static Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk );
34 static Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk );
35 static Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk );
36 
37 ////////////////////////////////////////////////////////////////////////
38 ///                     FUNCTION DEFINITIONS                         ///
39 ////////////////////////////////////////////////////////////////////////
40 
41 /**Function*************************************************************
42 
43   Synopsis    [Transform the netlist into a logic network.]
44 
45   Description []
46 
47   SideEffects []
48 
49   SeeAlso     []
50 
51 ***********************************************************************/
Abc_NtkToLogic(Abc_Ntk_t * pNtk)52 Abc_Ntk_t * Abc_NtkToLogic( Abc_Ntk_t * pNtk )
53 {
54     Abc_Ntk_t * pNtkNew;
55     Abc_Obj_t * pObj, * pFanin;
56     int i, k;
57     // consider the case of the AIG
58     if ( Abc_NtkIsStrash(pNtk) )
59         return Abc_NtkAigToLogicSop( pNtk );
60     assert( Abc_NtkIsNetlist(pNtk) );
61     // consider simple case when there is hierarchy
62 //    assert( pNtk->pDesign == NULL );
63     assert( Abc_NtkWhiteboxNum(pNtk) == 0 );
64     assert( Abc_NtkBlackboxNum(pNtk) == 0 );
65     // start the network
66     pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, pNtk->ntkFunc );
67     // duplicate the nodes
68     Abc_NtkForEachNode( pNtk, pObj, i )
69     {
70         Abc_NtkDupObj(pNtkNew, pObj, 0);
71         Abc_ObjAssignName( pObj->pCopy, Abc_ObjName(Abc_ObjFanout0(pObj)), NULL );
72     }
73     // reconnect the internal nodes in the new network
74     Abc_NtkForEachNode( pNtk, pObj, i )
75         Abc_ObjForEachFanin( pObj, pFanin, k )
76             Abc_ObjAddFanin( pObj->pCopy, Abc_ObjFanin0(pFanin)->pCopy );
77     // collect the CO nodes
78     Abc_NtkFinalize( pNtk, pNtkNew );
79     // fix the problem with CO pointing directly to CIs
80     Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
81     // duplicate EXDC
82     if ( pNtk->pExdc )
83         pNtkNew->pExdc = Abc_NtkToLogic( pNtk->pExdc );
84     if ( !Abc_NtkCheck( pNtkNew ) )
85         fprintf( stdout, "Abc_NtkToLogic(): Network check has failed.\n" );
86     return pNtkNew;
87 }
88 
89 /**Function*************************************************************
90 
91   Synopsis    [Transform the logic network into a netlist.]
92 
93   Description []
94 
95   SideEffects []
96 
97   SeeAlso     []
98 
99 ***********************************************************************/
Abc_NtkToNetlist(Abc_Ntk_t * pNtk)100 Abc_Ntk_t * Abc_NtkToNetlist( Abc_Ntk_t * pNtk )
101 {
102     Abc_Ntk_t * pNtkNew, * pNtkTemp;
103     assert( Abc_NtkIsLogic(pNtk) || Abc_NtkIsStrash(pNtk) );
104     if ( Abc_NtkIsStrash(pNtk) )
105     {
106         pNtkTemp = Abc_NtkAigToLogicSop(pNtk);
107         pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp );
108         Abc_NtkDelete( pNtkTemp );
109         return pNtkNew;
110     }
111     return Abc_NtkLogicToNetlist( pNtk );
112 }
113 
114 /**Function*************************************************************
115 
116   Synopsis    [Converts the AIG into the netlist.]
117 
118   Description [This procedure does not copy the choices.]
119 
120   SideEffects []
121 
122   SeeAlso     []
123 
124 ***********************************************************************/
Abc_NtkToNetlistBench(Abc_Ntk_t * pNtk)125 Abc_Ntk_t * Abc_NtkToNetlistBench( Abc_Ntk_t * pNtk )
126 {
127     Abc_Ntk_t * pNtkNew, * pNtkTemp;
128     assert( Abc_NtkIsStrash(pNtk) );
129     pNtkTemp = Abc_NtkAigToLogicSopBench( pNtk );
130     pNtkNew = Abc_NtkLogicToNetlist( pNtkTemp );
131     Abc_NtkDelete( pNtkTemp );
132     return pNtkNew;
133 }
134 
135 /**Function*************************************************************
136 
137   Synopsis    [Transform the logic network into a netlist.]
138 
139   Description [The logic network given to this procedure should
140   have exactly the same structure as the resulting netlist. The COs
141   can only point to CIs if they have identical names. Otherwise,
142   they should have a node between them, even if this node is
143   inverter or buffer.]
144 
145   SideEffects []
146 
147   SeeAlso     []
148 
149 ***********************************************************************/
Abc_NtkLogicToNetlist(Abc_Ntk_t * pNtk)150 Abc_Ntk_t * Abc_NtkLogicToNetlist( Abc_Ntk_t * pNtk )
151 {
152     Abc_Ntk_t * pNtkNew;
153     Abc_Obj_t * pObj, * pNet, * pDriver, * pFanin;
154     int i, k;
155 
156     assert( Abc_NtkIsLogic(pNtk) );
157 
158     // remove dangling nodes
159     Abc_NtkCleanup( pNtk, 0 );
160 
161     // make sure the CO names are unique
162     Abc_NtkCheckUniqueCiNames( pNtk );
163     Abc_NtkCheckUniqueCoNames( pNtk );
164     Abc_NtkCheckUniqueCioNames( pNtk );
165 
166 //    assert( Abc_NtkLogicHasSimpleCos(pNtk) );
167     if ( !Abc_NtkLogicHasSimpleCos(pNtk) )
168     {
169         if ( !Abc_FrameReadFlag("silentmode") )
170             printf( "Abc_NtkLogicToNetlist() warning: The network is converted to have simple COs.\n" );
171         Abc_NtkLogicMakeSimpleCos( pNtk, 0 );
172     }
173 
174     // start the netlist by creating PI/PO/Latch objects
175     pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_NETLIST, pNtk->ntkFunc );
176     // create the CI nets and remember them in the new CI nodes
177     Abc_NtkForEachCi( pNtk, pObj, i )
178     {
179         pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) );
180         Abc_ObjAddFanin( pNet, pObj->pCopy );
181         pObj->pCopy->pCopy = pNet;
182     }
183     // duplicate all nodes
184     Abc_NtkForEachNode( pNtk, pObj, i )
185         Abc_NtkDupObj(pNtkNew, pObj, 0);
186     // first add the nets to the CO drivers
187     Abc_NtkForEachCo( pNtk, pObj, i )
188     {
189         pDriver = Abc_ObjFanin0(pObj);
190         if ( Abc_ObjIsCi(pDriver) )
191         {
192             assert( !strcmp( Abc_ObjName(pDriver), Abc_ObjName(pObj) ) );
193             Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy );
194             continue;
195         }
196         assert( Abc_ObjIsNode(pDriver) );
197         // if the CO driver has no net, create it
198         if ( pDriver->pCopy->pCopy == NULL )
199         {
200             // create the CO net and connect it to CO
201             //if ( Abc_NtkFindNet(pNtkNew, Abc_ObjName(pDriver)) == NULL )
202             //    pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pDriver) );
203             //else
204             pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) );
205             Abc_ObjAddFanin( pObj->pCopy, pNet );
206             // connect the CO net to the new driver and remember it in the new driver
207             Abc_ObjAddFanin( pNet, pDriver->pCopy );
208             pDriver->pCopy->pCopy = pNet;
209         }
210         else
211         {
212             assert( !strcmp( Abc_ObjName(pDriver->pCopy->pCopy), Abc_ObjName(pObj) ) );
213             Abc_ObjAddFanin( pObj->pCopy, pDriver->pCopy->pCopy );
214         }
215     }
216     // create the missing nets
217     Abc_NtkForEachNode( pNtk, pObj, i )
218     {
219         char Buffer[1000];
220         if ( pObj->pCopy->pCopy ) // the net of the new object is already created
221             continue;
222         // create the new net
223         sprintf( Buffer, "new_%s_", Abc_ObjName(pObj) );
224         //pNet = Abc_NtkFindOrCreateNet( pNtkNew, Abc_ObjName(pObj) ); // here we create net names such as "n48", where 48 is the ID of the node
225         pNet = Abc_NtkFindOrCreateNet( pNtkNew, Buffer );
226         Abc_ObjAddFanin( pNet, pObj->pCopy );
227         pObj->pCopy->pCopy = pNet;
228     }
229     // connect nodes to the fanins nets
230     Abc_NtkForEachNode( pNtk, pObj, i )
231         Abc_ObjForEachFanin( pObj, pFanin, k )
232             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
233     // duplicate EXDC
234     if ( pNtk->pExdc )
235         pNtkNew->pExdc = Abc_NtkToNetlist( pNtk->pExdc );
236     if ( !Abc_NtkCheck( pNtkNew ) )
237         fprintf( stdout, "Abc_NtkLogicToNetlist(): Network check has failed.\n" );
238     return pNtkNew;
239 }
240 
241 /**Function*************************************************************
242 
243   Synopsis    [Converts the AIG into the logic network with SOPs.]
244 
245   Description [Correctly handles the case of choice nodes.]
246 
247   SideEffects []
248 
249   SeeAlso     []
250 
251 ***********************************************************************/
Abc_NtkAigToLogicSop(Abc_Ntk_t * pNtk)252 Abc_Ntk_t * Abc_NtkAigToLogicSop( Abc_Ntk_t * pNtk )
253 {
254     extern int Abc_NtkLogicMakeSimpleCos2( Abc_Ntk_t * pNtk, int fDuplicate );
255 
256     Abc_Ntk_t * pNtkNew;
257     Abc_Obj_t * pObj, * pFanin, * pNodeNew;
258     Vec_Int_t * vInts;
259     int i, k, fChoices = 0;
260     assert( Abc_NtkIsStrash(pNtk) );
261     // start the network
262     pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
263     // if the constant node is used, duplicate it
264     pObj = Abc_AigConst1(pNtk);
265     if ( Abc_ObjFanoutNum(pObj) > 0 )
266         pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
267     // duplicate the nodes and create node functions
268     Abc_NtkForEachNode( pNtk, pObj, i )
269     {
270         Abc_NtkDupObj(pNtkNew, pObj, 0);
271         pObj->pCopy->pData = Abc_SopCreateAnd2( (Mem_Flex_t *)pNtkNew->pManFunc, Abc_ObjFaninC0(pObj), Abc_ObjFaninC1(pObj) );
272     }
273     // create the choice nodes
274     Abc_NtkForEachNode( pNtk, pObj, i )
275     {
276         if ( !Abc_AigNodeIsChoice(pObj) )
277             continue;
278         // create an OR gate
279         pNodeNew = Abc_NtkCreateNode(pNtkNew);
280         // add fanins
281         vInts = Vec_IntAlloc( 10 );
282         for ( pFanin = pObj; pFanin; pFanin = (Abc_Obj_t *)pFanin->pData )
283         {
284             Vec_IntPush( vInts, (int)(pObj->fPhase != pFanin->fPhase) );
285             Abc_ObjAddFanin( pNodeNew, pFanin->pCopy );
286         }
287         // create the logic function
288         pNodeNew->pData = Abc_SopCreateOrMultiCube( (Mem_Flex_t *)pNtkNew->pManFunc, Vec_IntSize(vInts), Vec_IntArray(vInts) );
289         // set the new node
290         pObj->pCopy->pCopy = pNodeNew;
291         Vec_IntFree( vInts );
292         fChoices = 1;
293     }
294     // connect the internal nodes
295     Abc_NtkForEachNode( pNtk, pObj, i )
296         Abc_ObjForEachFanin( pObj, pFanin, k )
297             if ( pFanin->pCopy->pCopy )
298                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
299             else
300                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
301     // connect the COs
302 //    Abc_NtkFinalize( pNtk, pNtkNew );
303     Abc_NtkForEachCo( pNtk, pObj, i )
304     {
305         pFanin = Abc_ObjFanin0(pObj);
306         if ( pFanin->pCopy->pCopy )
307             pNodeNew = Abc_ObjNotCond(pFanin->pCopy->pCopy, Abc_ObjFaninC0(pObj));
308         else
309             pNodeNew = Abc_ObjNotCond(pFanin->pCopy, Abc_ObjFaninC0(pObj));
310         Abc_ObjAddFanin( pObj->pCopy, pNodeNew );
311     }
312 
313     // fix the problem with complemented and duplicated CO edges
314     if ( fChoices )
315         Abc_NtkLogicMakeSimpleCos2( pNtkNew, 0 );
316     else
317         Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
318     // duplicate the EXDC Ntk
319     if ( pNtk->pExdc )
320     {
321         if ( Abc_NtkIsStrash(pNtk->pExdc) )
322             pNtkNew->pExdc = Abc_NtkAigToLogicSop( pNtk->pExdc );
323         else
324             pNtkNew->pExdc = Abc_NtkDup( pNtk->pExdc );
325     }
326     if ( !Abc_NtkCheck( pNtkNew ) )
327         fprintf( stdout, "Abc_NtkAigToLogicSop(): Network check has failed.\n" );
328     return pNtkNew;
329 }
330 
331 /**Function*************************************************************
332 
333   Synopsis    [Converts the AIG into the logic network with SOPs for bench writing.]
334 
335   Description [This procedure does not copy the choices.]
336 
337   SideEffects []
338 
339   SeeAlso     []
340 
341 ***********************************************************************/
Abc_NtkAigToLogicSopBench(Abc_Ntk_t * pNtk)342 Abc_Ntk_t * Abc_NtkAigToLogicSopBench( Abc_Ntk_t * pNtk )
343 {
344     Abc_Ntk_t * pNtkNew;
345     Abc_Obj_t * pObj, * pFanin;
346     Vec_Ptr_t * vNodes;
347     int i, k;
348     assert( Abc_NtkIsStrash(pNtk) );
349     if ( Abc_NtkGetChoiceNum(pNtk) )
350         printf( "Warning: Choice nodes are skipped.\n" );
351     // start the network
352     pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
353     // collect the nodes to be used (marks all nodes with current TravId)
354     vNodes = Abc_NtkDfs( pNtk, 0 );
355     // create inverters for the constant node
356     pObj = Abc_AigConst1(pNtk);
357     if ( Abc_ObjFanoutNum(pObj) > 0 )
358         pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
359     if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
360         pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
361     // create inverters for the CIs
362     Abc_NtkForEachCi( pNtk, pObj, i )
363         if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
364             pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
365     // duplicate the nodes, create node functions, and inverters
366     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
367     {
368         Abc_NtkDupObj( pNtkNew, pObj, 0 );
369         pObj->pCopy->pData = Abc_SopCreateAnd( (Mem_Flex_t *)pNtkNew->pManFunc, 2, NULL );
370         if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
371             pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
372     }
373     // connect the objects
374     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
375         Abc_ObjForEachFanin( pObj, pFanin, k )
376         {
377             if ( Abc_ObjFaninC( pObj, k ) )
378                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
379             else
380                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
381         }
382     Vec_PtrFree( vNodes );
383     // connect the COs
384     Abc_NtkForEachCo( pNtk, pObj, i )
385     {
386         pFanin = Abc_ObjFanin0(pObj);
387         if ( Abc_ObjFaninC0( pObj ) )
388             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
389         else
390             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
391     }
392     // fix the problem with complemented and duplicated CO edges
393     Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
394     // duplicate the EXDC Ntk
395     if ( pNtk->pExdc )
396         printf( "Warning: The EXDc network is skipped.\n" );
397     if ( !Abc_NtkCheck( pNtkNew ) )
398         fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" );
399     return pNtkNew;
400 }
401 
402 /**Function*************************************************************
403 
404   Synopsis    [Converts the AIG into the logic network with SOPs for bench writing.]
405 
406   Description [This procedure does not copy the choices.]
407 
408   SideEffects []
409 
410   SeeAlso     []
411 
412 ***********************************************************************/
Abc_NtkAigToLogicSopNand(Abc_Ntk_t * pNtk)413 Abc_Ntk_t * Abc_NtkAigToLogicSopNand( Abc_Ntk_t * pNtk )
414 {
415     Abc_Ntk_t * pNtkNew;
416     Abc_Obj_t * pObj, * pFanin;
417     Vec_Ptr_t * vNodes;
418     int i, k;
419     assert( Abc_NtkIsStrash(pNtk) );
420     if ( Abc_NtkGetChoiceNum(pNtk) )
421         printf( "Warning: Choice nodes are skipped.\n" );
422     // convert complemented edges
423     Abc_NtkForEachObj( pNtk, pObj, i )
424         Abc_ObjForEachFanin( pObj, pFanin, k )
425             if ( Abc_ObjIsNode(pFanin) )
426                 Abc_ObjXorFaninC( pObj, k );
427     // start the network
428     pNtkNew = Abc_NtkStartFrom( pNtk, ABC_NTK_LOGIC, ABC_FUNC_SOP );
429     // collect the nodes to be used (marks all nodes with current TravId)
430     vNodes = Abc_NtkDfs( pNtk, 0 );
431     // create inverters for the constant node
432     pObj = Abc_AigConst1(pNtk);
433     if ( Abc_ObjFanoutNum(pObj) > 0 )
434         pObj->pCopy = Abc_NtkCreateNodeConst1(pNtkNew);
435     if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
436         pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
437     // create inverters for the CIs
438     Abc_NtkForEachCi( pNtk, pObj, i )
439         if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
440             pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
441     // duplicate the nodes, create node functions, and inverters
442     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
443     {
444         Abc_NtkDupObj( pNtkNew, pObj, 0 );
445         pObj->pCopy->pData = Abc_SopCreateNand( (Mem_Flex_t *)pNtkNew->pManFunc, 2 );
446         if ( Abc_AigNodeHasComplFanoutEdgeTrav(pObj) )
447             pObj->pCopy->pCopy = Abc_NtkCreateNodeInv( pNtkNew, pObj->pCopy );
448     }
449     // connect the objects
450     Vec_PtrForEachEntry( Abc_Obj_t *, vNodes, pObj, i )
451         Abc_ObjForEachFanin( pObj, pFanin, k )
452         {
453             if ( Abc_ObjFaninC( pObj, k ) )
454                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
455             else
456                 Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
457         }
458     Vec_PtrFree( vNodes );
459     // connect the COs
460     Abc_NtkForEachCo( pNtk, pObj, i )
461     {
462         pFanin = Abc_ObjFanin0(pObj);
463         if ( Abc_ObjFaninC0( pObj ) )
464             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy->pCopy );
465         else
466             Abc_ObjAddFanin( pObj->pCopy, pFanin->pCopy );
467     }
468     // fix the problem with complemented and duplicated CO edges
469     Abc_NtkLogicMakeSimpleCos( pNtkNew, 0 );
470     // convert complemented edges
471     Abc_NtkForEachObj( pNtk, pObj, i )
472         Abc_ObjForEachFanin( pObj, pFanin, k )
473             if ( Abc_ObjIsNode(pFanin) )
474                 Abc_ObjXorFaninC( pObj, k );
475     // duplicate the EXDC Ntk
476     if ( pNtk->pExdc )
477         printf( "Warning: The EXDc network is skipped.\n" );
478     if ( !Abc_NtkCheck( pNtkNew ) )
479         fprintf( stdout, "Abc_NtkAigToLogicSopBench(): Network check has failed.\n" );
480     return pNtkNew;
481 }
482 
483 /**Function*************************************************************
484 
485   Synopsis    [Adds buffers for each PO.]
486 
487   Description []
488 
489   SideEffects []
490 
491   SeeAlso     []
492 
493 ***********************************************************************/
Abc_NtkAddPoBuffers(Abc_Ntk_t * pNtk)494 void Abc_NtkAddPoBuffers( Abc_Ntk_t * pNtk )
495 {
496     Abc_Obj_t * pObj, * pFanin, * pFaninNew;
497     int i;
498     assert( Abc_NtkIsStrash(pNtk) );
499     Abc_NtkForEachPo( pNtk, pObj, i )
500     {
501         pFanin = Abc_ObjChild0(pObj);
502         pFaninNew = Abc_NtkCreateNode(pNtk);
503         Abc_ObjAddFanin( pFaninNew, pFanin );
504         Abc_ObjPatchFanin( pObj, pFanin, pFaninNew );
505     }
506 }
507 
508 ////////////////////////////////////////////////////////////////////////
509 ///                       END OF FILE                                ///
510 ////////////////////////////////////////////////////////////////////////
511 
512 
513 ABC_NAMESPACE_IMPL_END
514 
515