1 /**CFile****************************************************************
2 
3   FileName    [ndr.h]
4 
5   SystemName  [ABC: Logic synthesis and verification system.]
6 
7   PackageName [Format for word-level design representation.]
8 
9   Synopsis    [External declarations.]
10 
11   Author      [Alan Mishchenko]
12 
13   Affiliation [UC Berkeley]
14 
15   Date        [Ver. 1.0. Started - August 22, 2014.]
16 
17   Revision    [$Id: ndr.h,v 1.00 2014/09/12 00:00:00 alanmi Exp $]
18 
19 ***********************************************************************/
20 
21 #ifndef ABC__base__ndr__ndr_h
22 #define ABC__base__ndr__ndr_h
23 
24 
25 ////////////////////////////////////////////////////////////////////////
26 ///                          INCLUDES                                ///
27 ////////////////////////////////////////////////////////////////////////
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33 
34 #include "abcOper.h"
35 
36 ABC_NAMESPACE_HEADER_START
37 
38 #ifdef _WIN32
39 #define inline __inline
40 #endif
41 
42 /*
43     For the lack of a better name, this format is called New Data Representation (NDR).
44 
45     NDR is designed as an interchange format to pass hierarchical word-level designs between the tools.
46     It is relatively simple, uses little memory, and can be easily converted into other ABC data-structures.
47 
48     This tutorial discusses how to construct the NDR representation of a hierarchical word-level design.
49 
50     First, all names used in the design (including the design name, module names, port names, net names,
51     instance names, etc) are hashed into 1-based integers called "name IDs". Nets are not explicitly represented.
52     The connectivity of a design object is established by specifying name IDs of the nets connected to the object.
53     Object inputs are name IDs of the driving nets; object outputs are name IDs of the driven nets.
54 
55     The design is initialized using procedure Ndr_Create(), which takes the design name as an argument.
56     A module in the design is initialized using procedure Ndr_AddModule(), which takes the design and
57     the module name as arguments. Objects are added to a module in any order using procedure Ndr_AddObject().
58 
59     Primary input and primary output objects should be explicitly created, as shown in the examples below.
60 
61     Instances of known operators listed in file "abcOper.h" are assumed to have one output. The only known
62     issue due to this restriction concerns the adder, which produces the sum and the carry-out. To make sure the
63     adder instance has only one output, the carry-out has to be concatenated with the sum before the adder
64     instance is created in the NDR format.
65 
66     Instances of hierarchical modules defined by the user can have multiple outputs.
67 
68     Bit-slice and concatenation operators should be represented as separate objects.
69 
70     If the ordering of inputs/outputs/flops of a module is not provided as a separate record in NDR format,
71     their ordering is determined by the order of their appearance in the NDR description of the module.
72 
73     If left limit and right limit of a bit-range are equal, it is assumed that the range contains one bit
74 
75     Word-level constants are represented as char-strings given in the same way as they would appear in a Verilog
76     file. For example, the 16-bit constant 10 is represented as a string "4'b1010" and is given as an argument
77     (char * pFunction) to the procedure Ndr_AddObject().
78 
79     Currently two types of flops are supported: a simple flop with implicit clock and two fanins (data and init)
80     and a complex flop with 8 fanins (clock, data, reset, set, enable, async, sre, init), as shown in the examples below.
81 
82     The initial value of a flop is represented by input "init", which can be driven by a constant or by a primary
83     input of the module. If it is a primary input, is it assumed that the flop is not initialized. If the input
84     "init" is not driven, it is assumed that the flop is initialized to 0.
85 
86     Memory read and write ports are supported, as shown in the example below.
87 
88     (to be continued)
89 */
90 
91 ////////////////////////////////////////////////////////////////////////
92 ///                         PARAMETERS                               ///
93 ////////////////////////////////////////////////////////////////////////
94 
95 // record types
96 typedef enum {
97     NDR_NONE = 0,          // 0:  unused
98     NDR_DESIGN,            // 1:  design (or library of modules)
99     NDR_MODULE,            // 2:  one module
100     NDR_OBJECT,            // 3:  object
101     NDR_INPUT,             // 4:  input
102     NDR_OUTPUT,            // 5:  output
103     NDR_OPERTYPE,          // 6:  operator type (buffer, shifter, adder, etc)
104     NDR_NAME,              // 7:  name
105     NDR_RANGE,             // 8:  bit range
106     NDR_FUNCTION,          // 9:  specified for some operators (PLAs, etc)
107     NDR_TARGET,            // 10: target
108     NDR_UNKNOWN            // 11: unknown
109 } Ndr_RecordType_t;
110 
111 
112 ////////////////////////////////////////////////////////////////////////
113 ///                         BASIC TYPES                              ///
114 ////////////////////////////////////////////////////////////////////////
115 
116 // this is an internal procedure, which is not seen by the user
117 typedef struct Ndr_Data_t_  Ndr_Data_t;
118 struct Ndr_Data_t_
119 {
120     int                     nSize;
121     int                     nCap;
122     unsigned char *         pHead;
123     unsigned int *          pBody;
124 };
125 
Ndr_DataType(Ndr_Data_t * p,int i)126 static inline int           Ndr_DataType( Ndr_Data_t * p, int i )                { assert( p->pHead[i] ); return (int)p->pHead[i];                }
Ndr_DataSize(Ndr_Data_t * p,int i)127 static inline int           Ndr_DataSize( Ndr_Data_t * p, int i )                { return Ndr_DataType(p, i) > NDR_OBJECT ? 1 : p->pBody[i];      }
Ndr_DataEntry(Ndr_Data_t * p,int i)128 static inline int           Ndr_DataEntry( Ndr_Data_t * p, int i )               { return (int)p->pBody[i];                                       }
Ndr_DataEntryP(Ndr_Data_t * p,int i)129 static inline int *         Ndr_DataEntryP( Ndr_Data_t * p, int i )              { return (int *)p->pBody + i;                                    }
Ndr_DataEnd(Ndr_Data_t * p,int i)130 static inline int           Ndr_DataEnd( Ndr_Data_t * p, int i )                 { return i + p->pBody[i];                                        }
Ndr_DataAddTo(Ndr_Data_t * p,int i,int Add)131 static inline void          Ndr_DataAddTo( Ndr_Data_t * p, int i, int Add )      { assert(Ndr_DataType(p, i) <= NDR_OBJECT); p->pBody[i] += Add;  }
Ndr_DataPush(Ndr_Data_t * p,int Type,int Entry)132 static inline void          Ndr_DataPush( Ndr_Data_t * p, int Type, int Entry )  { p->pHead[p->nSize] = Type; p->pBody[p->nSize++] = Entry;       }
133 
134 #define NDR_ALLOC(type, num)     ((type *) malloc(sizeof(type) * (size_t)(num)))
135 
136 ////////////////////////////////////////////////////////////////////////
137 ///                          ITERATORS                               ///
138 ////////////////////////////////////////////////////////////////////////
139 
140 // iterates over modules in the design
141 #define Ndr_DesForEachMod( p, Mod )                                   \
142     for ( Mod = 1; Mod < Ndr_DataEntry(p, 0); Mod += Ndr_DataSize(p, Mod) ) if (Ndr_DataType(p, Mod) != NDR_MODULE) {} else
143 
144 // iterates over objects in a module
145 #define Ndr_ModForEachObj( p, Mod, Obj )                              \
146     for ( Obj = Mod + 1; Obj < Ndr_DataEnd(p, Mod); Obj += Ndr_DataSize(p, Obj) ) if (Ndr_DataType(p, Obj) != NDR_OBJECT) {} else
147 
148 // iterates over records in an object
149 #define Ndr_ObjForEachEntry( p, Obj, Ent )                            \
150     for ( Ent = Obj + 1; Ent < Ndr_DataEnd(p, Obj); Ent += Ndr_DataSize(p, Ent) )
151 
152 // iterates over primary inputs of a module
153 #define Ndr_ModForEachPi( p, Mod, Obj )                               \
154     Ndr_ModForEachObj( p, Mod, Obj ) if ( !Ndr_ObjIsType(p, Obj, ABC_OPER_CI) ) {} else
155 
156 // iteraots over primary outputs of a module
157 #define Ndr_ModForEachPo( p, Mod, Obj )                               \
158     Ndr_ModForEachObj( p, Mod, Obj ) if ( !Ndr_ObjIsType(p, Obj, ABC_OPER_CO) ) {} else
159 
160 // iterates over internal nodes of a module
161 #define Ndr_ModForEachNode( p, Mod, Obj )                             \
162     Ndr_ModForEachObj( p, Mod, Obj ) if ( Ndr_ObjIsType(p, Obj, ABC_OPER_CI) || Ndr_ObjIsType(p, Obj, ABC_OPER_CO) ) {} else
163 
164 // iterates over target signals of a module
165 #define Ndr_ModForEachTarget( p, Mod, Obj )                           \
166     for ( Obj = Mod + 1; Obj < Ndr_DataEnd(p, Mod); Obj += Ndr_DataSize(p, Obj) ) if (Ndr_DataType(p, Obj) != NDR_TARGET) {} else
167 
168 ////////////////////////////////////////////////////////////////////////
169 ///                    INTERNAL PROCEDURES                           ///
170 ////////////////////////////////////////////////////////////////////////
171 
172 
Ndr_DataResize(Ndr_Data_t * p,int Add)173 static inline void Ndr_DataResize( Ndr_Data_t * p, int Add )
174 {
175     if ( p->nSize + Add <= p->nCap )
176         return;
177     p->nCap  = 2 * p->nCap > p->nSize + Add ? 2 * p->nCap : p->nSize + Add;
178     p->pHead = (unsigned char*)realloc( p->pHead,   p->nCap );
179     p->pBody = (unsigned int *)realloc( p->pBody, 4*p->nCap );
180 }
Ndr_DataPushRange(Ndr_Data_t * p,int RangeLeft,int RangeRight,int fSignedness)181 static inline void Ndr_DataPushRange( Ndr_Data_t * p, int RangeLeft, int RangeRight, int fSignedness )
182 {
183     if ( fSignedness )
184     {
185         Ndr_DataPush( p, NDR_RANGE, RangeLeft );
186         Ndr_DataPush( p, NDR_RANGE, RangeRight );
187         Ndr_DataPush( p, NDR_RANGE, fSignedness );
188         return;
189     }
190     if ( !RangeLeft && !RangeRight )
191         return;
192     if ( RangeLeft == RangeRight )
193         Ndr_DataPush( p, NDR_RANGE, RangeLeft );
194     else
195     {
196         Ndr_DataPush( p, NDR_RANGE, RangeLeft );
197         Ndr_DataPush( p, NDR_RANGE, RangeRight );
198     }
199 }
Ndr_DataPushArray(Ndr_Data_t * p,int Type,int nArray,int * pArray)200 static inline void Ndr_DataPushArray( Ndr_Data_t * p, int Type, int nArray, int * pArray )
201 {
202     if ( !nArray )
203         return;
204     assert( nArray > 0 );
205     Ndr_DataResize( p, nArray );
206     memset( p->pHead + p->nSize, Type, (size_t)nArray );
207     memcpy( p->pBody + p->nSize, pArray, (size_t)4*nArray );
208     p->nSize += nArray;
209 }
Ndr_DataPushString(Ndr_Data_t * p,int ObjType,int Type,char * pFunc)210 static inline void Ndr_DataPushString( Ndr_Data_t * p, int ObjType, int Type, char * pFunc )
211 {
212     int nBuffInts;
213     int * pBuff;
214     if ( !pFunc )
215         return;
216     if ( ObjType == ABC_OPER_LUT )
217     {
218         word Truth = (word)pFunc;
219         Ndr_DataPushArray( p, Type, 2, (int *)&Truth );
220     }
221     else
222     {
223         nBuffInts = ((int)strlen(pFunc) + 4) / 4;
224         pBuff = (int *)calloc( 1, 4*nBuffInts );
225         memcpy( pBuff, pFunc, strlen(pFunc) );
226         Ndr_DataPushArray( p, Type, nBuffInts, pBuff );
227         free( pBuff );
228     }
229 }
230 
231 ////////////////////////////////////////////////////////////////////////
232 ///                     VERILOG WRITING                              ///
233 ////////////////////////////////////////////////////////////////////////
234 
Ndr_ObjReadEntry(Ndr_Data_t * p,int Obj,int Type)235 static inline int Ndr_ObjReadEntry( Ndr_Data_t * p, int Obj, int Type )
236 {
237     int Ent;
238     Ndr_ObjForEachEntry( p, Obj, Ent )
239         if ( Ndr_DataType(p, Ent) == Type )
240             return Ndr_DataEntry(p, Ent);
241     return -1;
242 }
Ndr_ObjReadArray(Ndr_Data_t * p,int Obj,int Type,int ** ppStart)243 static inline int Ndr_ObjReadArray( Ndr_Data_t * p, int Obj, int Type, int ** ppStart )
244 {
245     int Ent, Counter = 0; *ppStart = NULL;
246     Ndr_ObjForEachEntry( p, Obj, Ent )
247         if ( Ndr_DataType(p, Ent) == Type )
248         {
249             Counter++;
250             if ( *ppStart == NULL )
251                 *ppStart = (int *)p->pBody + Ent;
252         }
253         else if ( *ppStart )
254             return Counter;
255     return Counter;
256 }
Ndr_ObjIsType(Ndr_Data_t * p,int Obj,int Type)257 static inline int Ndr_ObjIsType( Ndr_Data_t * p, int Obj, int Type )
258 {
259     int Ent;
260     Ndr_ObjForEachEntry( p, Obj, Ent )
261         if ( Ndr_DataType(p, Ent) == NDR_OPERTYPE )
262             return (int)(Ndr_DataEntry(p, Ent) == Type);
263     return -1;
264 }
Ndr_ObjReadBody(Ndr_Data_t * p,int Obj,int Type)265 static inline int Ndr_ObjReadBody( Ndr_Data_t * p, int Obj, int Type )
266 {
267     int Ent;
268     Ndr_ObjForEachEntry( p, Obj, Ent )
269         if ( Ndr_DataType(p, Ent) == Type )
270             return Ndr_DataEntry(p, Ent);
271     return -1;
272 }
Ndr_ObjReadBodyP(Ndr_Data_t * p,int Obj,int Type)273 static inline int * Ndr_ObjReadBodyP( Ndr_Data_t * p, int Obj, int Type )
274 {
275     int Ent;
276     Ndr_ObjForEachEntry( p, Obj, Ent )
277         if ( Ndr_DataType(p, Ent) == Type )
278             return Ndr_DataEntryP(p, Ent);
279     return NULL;
280 }
Ndr_ObjWriteRange(Ndr_Data_t * p,int Obj,FILE * pFile,int fSkipBin)281 static inline void Ndr_ObjWriteRange( Ndr_Data_t * p, int Obj, FILE * pFile, int fSkipBin )
282 {
283     int * pArray, nArray = Ndr_ObjReadArray( p, Obj, NDR_RANGE, &pArray );
284     if ( (nArray == 0 || nArray == 1) && fSkipBin )
285         return;
286     if ( nArray == 3 && fSkipBin )
287         fprintf( pFile, "signed " );
288     else if ( nArray == 1 )
289     {
290         if ( fSkipBin )
291             fprintf( pFile, "[%d:%d]", pArray[0], pArray[0] );
292         else
293             fprintf( pFile, "[%d]", pArray[0] );
294     }
295     else if ( nArray == 0 )
296     {
297         if ( fSkipBin )
298             fprintf( pFile, "[%d:%d]", 0, 0 );
299         else
300             fprintf( pFile, "[%d]", 0 );
301     }
302     else
303         fprintf( pFile, "[%d:%d]", pArray[0], pArray[1] );
304 }
Ndr_ObjReadOutName(Ndr_Data_t * p,int Obj,char ** pNames)305 static inline char * Ndr_ObjReadOutName( Ndr_Data_t * p, int Obj, char ** pNames )
306 {
307     return pNames[Ndr_ObjReadBody(p, Obj, NDR_OUTPUT)];
308 }
Ndr_ObjReadInName(Ndr_Data_t * p,int Obj,char ** pNames)309 static inline char * Ndr_ObjReadInName( Ndr_Data_t * p, int Obj, char ** pNames )
310 {
311     return pNames[Ndr_ObjReadBody(p, Obj, NDR_INPUT)];
312 }
313 
Ndr_DataCiNum(Ndr_Data_t * p,int Mod)314 static inline int Ndr_DataCiNum( Ndr_Data_t * p, int Mod )
315 {
316     int Obj, Count = 0;
317     Ndr_ModForEachPi( p, Mod, Obj )
318         Count++;
319     return Count;
320 }
Ndr_DataCoNum(Ndr_Data_t * p,int Mod)321 static inline int Ndr_DataCoNum( Ndr_Data_t * p, int Mod )
322 {
323     int Obj, Count = 0;
324     Ndr_ModForEachPo( p, Mod, Obj )
325         Count++;
326     return Count;
327 }
Ndr_DataObjNum(Ndr_Data_t * p,int Mod)328 static inline int Ndr_DataObjNum( Ndr_Data_t * p, int Mod )
329 {
330     int Obj, Count = 0;
331     Ndr_ModForEachObj( p, Mod, Obj )
332         Count++;
333     return Count;
334 }
335 
336 // to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames)
Ndr_WriteVerilogModule(FILE * pFile,void * pDesign,int Mod,char ** pNames)337 static inline void Ndr_WriteVerilogModule( FILE * pFile, void * pDesign, int Mod, char ** pNames )
338 {
339     Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
340     int * pOuts = NDR_ALLOC( int, Ndr_DataCoNum(p, Mod) );
341     int i, k, Obj, nArray, * pArray, fFirst = 1;
342 
343     fprintf( pFile, "\nmodule %s (\n  ", pNames[Ndr_ObjReadEntry(p, Mod, NDR_NAME)] );
344 
345     Ndr_ModForEachPi( p, Mod, Obj )
346         fprintf( pFile, "%s, ", Ndr_ObjReadOutName(p, Obj, pNames) );
347 
348     fprintf( pFile, "\n  " );
349 
350     Ndr_ModForEachPo( p, Mod, Obj )
351         fprintf( pFile, "%s%s", fFirst ? "":", ", Ndr_ObjReadInName(p, Obj, pNames) ), fFirst = 0;
352 
353     fprintf( pFile, "\n);\n\n" );
354 
355     Ndr_ModForEachPi( p, Mod, Obj )
356     {
357         fprintf( pFile, "  input " );
358         Ndr_ObjWriteRange( p, Obj, pFile, 1 );
359         fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) );
360     }
361 
362     i = 0;
363     Ndr_ModForEachPo( p, Mod, Obj )
364     {
365         fprintf( pFile, "  output " );
366         Ndr_ObjWriteRange( p, Obj, pFile, 1 );
367         fprintf( pFile, " %s;\n", Ndr_ObjReadInName(p, Obj, pNames) );
368         pOuts[i++] = Ndr_ObjReadBody(p, Obj, NDR_INPUT);
369     }
370 
371     fprintf( pFile, "\n" );
372 
373     Ndr_ModForEachNode( p, Mod, Obj )
374     {
375         for ( k = 0; k < i; k++ )
376             if ( pOuts[k] == Ndr_ObjReadBody(p, Obj, NDR_OUTPUT) )
377                 break;
378         if ( k < i )
379             continue;
380         fprintf( pFile, "  wire " );
381         Ndr_ObjWriteRange( p, Obj, pFile, 1 );
382         fprintf( pFile, " %s;\n", Ndr_ObjReadOutName(p, Obj, pNames) );
383     }
384     free( pOuts );
385 
386     fprintf( pFile, "\n" );
387 
388     Ndr_ModForEachNode( p, Mod, Obj )
389     {
390         int i, Type = Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE);
391         if ( Type >= 256 )
392         {
393             fprintf( pFile, "  %s ", pNames[Ndr_ObjReadEntry(p, Type-256, NDR_NAME)] );
394             if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
395                 fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
396             fprintf( pFile, "( " );
397             nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
398             for ( i = 0; i < nArray; i++ )
399                 fprintf( pFile, "%s%s ", pNames[pArray[i]], i==nArray-1 ? "":"," );
400             fprintf( pFile, ");\n" );
401             continue;
402         }
403         if ( Type == ABC_OPER_DFF )
404         {
405             fprintf( pFile, "  %s ", "ABC_DFF" );
406             if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
407                 fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
408             fprintf( pFile, "( " );
409             nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
410             fprintf( pFile, ".q(%s), ",    Ndr_ObjReadOutName(p, Obj, pNames) );
411             fprintf( pFile, ".d(%s), ",    pNames[pArray[0]] );
412             fprintf( pFile, ".init(%s) ",  pNames[pArray[1]] );
413             fprintf( pFile, ");\n" );
414             continue;
415         }
416         if ( Type == ABC_OPER_DFFRSE )
417         {
418             fprintf( pFile, "  %s ", "ABC_DFFRSE" );
419             if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
420                 fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
421             fprintf( pFile, "( " );
422             nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
423             fprintf( pFile, ".q(%s), ",      Ndr_ObjReadOutName(p, Obj, pNames) );
424             fprintf( pFile, ".d(%s), ",      pNames[pArray[0]] );
425             fprintf( pFile, ".clk(%s), ",    pNames[pArray[1]] );
426             fprintf( pFile, ".reset(%s), ",  pNames[pArray[2]] );
427             fprintf( pFile, ".set(%s), ",    pNames[pArray[3]] );
428             fprintf( pFile, ".enable(%s), ", pNames[pArray[4]] );
429             fprintf( pFile, ".async(%s), ",  pNames[pArray[5]] );
430             fprintf( pFile, ".sre(%s), ",    pNames[pArray[6]] );
431             fprintf( pFile, ".init(%s) ",    pNames[pArray[7]] );
432             fprintf( pFile, ");\n" );
433             continue;
434         }
435         if ( Type == ABC_OPER_RAMR )
436         {
437             fprintf( pFile, "  %s ", "ABC_READ" );
438             if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
439                 fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
440             fprintf( pFile, "( " );
441             nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
442             fprintf( pFile, ".data(%s), ",   Ndr_ObjReadOutName(p, Obj, pNames) );
443             fprintf( pFile, ".mem_in(%s), ", pNames[pArray[0]] );
444             fprintf( pFile, ".addr(%s) ",    pNames[pArray[1]] );
445             fprintf( pFile, ");\n" );
446             continue;
447         }
448         if ( Type == ABC_OPER_RAMW )
449         {
450             fprintf( pFile, "  %s ", "ABC_WRITE" );
451             if ( Ndr_ObjReadBody(p, Obj, NDR_NAME) > 0 )
452                 fprintf( pFile, "%s ", pNames[Ndr_ObjReadBody(p, Obj, NDR_NAME)] );
453             fprintf( pFile, "( " );
454             nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
455             fprintf( pFile, ".mem_out(%s), ",  Ndr_ObjReadOutName(p, Obj, pNames) );
456             fprintf( pFile, ".mem_in(%s), ",   pNames[pArray[0]] );
457             fprintf( pFile, ".addr(%s), ",     pNames[pArray[1]] );
458             fprintf( pFile, ".data(%s) ",      pNames[pArray[2]] );
459             fprintf( pFile, ");\n" );
460             continue;
461         }
462         fprintf( pFile, "  assign %s = ", Ndr_ObjReadOutName(p, Obj, pNames) );
463         nArray = Ndr_ObjReadArray( p, Obj, NDR_INPUT, &pArray );
464         if ( nArray == 0 )
465             fprintf( pFile, "%s;\n", (char *)Ndr_ObjReadBodyP(p, Obj, NDR_FUNCTION) );
466         else if ( nArray == 1 && Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE) == ABC_OPER_BIT_BUF )
467             fprintf( pFile, "%s;\n", pNames[pArray[0]] );
468         else if ( Type == ABC_OPER_SLICE )
469             fprintf( pFile, "%s", pNames[pArray[0]] ),
470             Ndr_ObjWriteRange( p, Obj, pFile, 0 ),
471             fprintf( pFile, ";\n" );
472         else if ( Type == ABC_OPER_CONCAT )
473         {
474             fprintf( pFile, "{" );
475             for ( i = 0; i < nArray; i++ )
476                 fprintf( pFile, "%s%s", pNames[pArray[i]], i==nArray-1 ? "":", " );
477             fprintf( pFile, "};\n" );
478         }
479         else if ( nArray == 1 )
480             fprintf( pFile, "%s %s;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[0]] );
481         else if ( nArray == 2 )
482             fprintf( pFile, "%s %s %s;\n", pNames[pArray[0]], Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)), pNames[pArray[1]] );
483         else if ( nArray == 3 && Type == ABC_OPER_ARI_ADD )
484             fprintf( pFile, "%s + %s + %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] );
485         else if ( Type == ABC_OPER_BIT_MUX )
486             fprintf( pFile, "%s ? %s : %s;\n", pNames[pArray[0]], pNames[pArray[1]], pNames[pArray[2]] );
487         else
488             fprintf( pFile, "<cannot write operation %s>;\n", Abc_OperName(Ndr_ObjReadBody(p, Obj, NDR_OPERTYPE)) );
489     }
490 
491     fprintf( pFile, "\nendmodule\n\n" );
492 }
493 
494 // to write signal names, this procedure takes a mapping of name IDs into actual char-strings (pNames)
Ndr_WriteVerilog(char * pFileName,void * pDesign,char ** pNames)495 static inline void Ndr_WriteVerilog( char * pFileName, void * pDesign, char ** pNames )
496 {
497     Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int Mod;
498 
499     FILE * pFile = pFileName ? fopen( pFileName, "wb" ) : stdout;
500     if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; }
501 
502     Ndr_DesForEachMod( p, Mod )
503         Ndr_WriteVerilogModule( pFile, p, Mod, pNames );
504 
505     if ( pFileName ) fclose( pFile );
506 }
507 
508 
509 ////////////////////////////////////////////////////////////////////////
510 ///                     EXTERNAL PROCEDURES                          ///
511 ////////////////////////////////////////////////////////////////////////
512 
513 // creating a new module (returns pointer to the memory buffer storing the module info)
Ndr_Create(int Name)514 static inline void * Ndr_Create( int Name )
515 {
516     Ndr_Data_t * p = NDR_ALLOC( Ndr_Data_t, 1 );
517     p->nSize = 0;
518     p->nCap  = 16;
519     p->pHead = NDR_ALLOC( unsigned char, p->nCap );
520     p->pBody = NDR_ALLOC( unsigned int, p->nCap * 4 );
521     Ndr_DataPush( p, NDR_DESIGN, 0 );
522     Ndr_DataPush( p, NDR_NAME, Name );
523     Ndr_DataAddTo( p, 0, p->nSize );
524     assert( p->nSize == 2 );
525     assert( Name );
526     return p;
527 }
528 
529 // creating a new module in an already started design
530 // returns module ID to be used when adding objects to the module
Ndr_AddModule(void * pDesign,int Name)531 static inline int Ndr_AddModule( void * pDesign, int Name )
532 {
533     Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
534     int Mod = p->nSize;
535     Ndr_DataResize( p, 6 );
536     Ndr_DataPush( p, NDR_MODULE, 0 );
537     Ndr_DataPush( p, NDR_NAME, Name );
538     Ndr_DataAddTo( p, Mod, p->nSize - Mod );
539     Ndr_DataAddTo( p, 0, p->nSize - Mod );
540     assert( (int)p->pBody[0] == p->nSize );
541     return Mod + 256;
542 }
543 
544 // adding a new object (input/output/flop/intenal node) to an already started module
545 // this procedure takes the design, the module ID, and the parameters of the boject
546 // (please note that all objects should be added to a given module before starting a new module)
Ndr_AddObject(void * pDesign,int ModuleId,int ObjType,int InstName,int RangeLeft,int RangeRight,int fSignedness,int nInputs,int * pInputs,int nOutputs,int * pOutputs,char * pFunction)547 static inline void Ndr_AddObject( void * pDesign, int ModuleId,
548                                   int ObjType, int InstName,
549                                   int RangeLeft, int RangeRight, int fSignedness,
550                                   int nInputs, int * pInputs,
551                                   int nOutputs, int * pOutputs,
552                                   char * pFunction )
553 {
554     Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
555     int Mod = ModuleId - 256;
556     int Obj = p->nSize;  assert( ObjType != 0 );
557     Ndr_DataResize( p, 6 );
558     Ndr_DataPush( p, NDR_OBJECT, 0 );
559     Ndr_DataPush( p, NDR_OPERTYPE, ObjType );
560     Ndr_DataPushRange( p, RangeLeft, RangeRight, fSignedness );
561     if ( InstName )
562         Ndr_DataPush( p, NDR_NAME, InstName );
563     Ndr_DataPushArray( p, NDR_INPUT, nInputs, pInputs );
564     Ndr_DataPushArray( p, NDR_OUTPUT, nOutputs, pOutputs );
565     Ndr_DataPushString( p, ObjType, NDR_FUNCTION, pFunction );
566     Ndr_DataAddTo( p, Obj, p->nSize - Obj );
567     Ndr_DataAddTo( p, Mod, p->nSize - Obj );
568     Ndr_DataAddTo( p, 0, p->nSize - Obj );
569     assert( (int)p->pBody[0] == p->nSize );
570 }
571 
572 // deallocate the memory buffer
Ndr_Delete(void * pDesign)573 static inline void Ndr_Delete( void * pDesign )
574 {
575     Ndr_Data_t * p = (Ndr_Data_t *)pDesign;
576     if ( !p ) return;
577     free( p->pHead );
578     free( p->pBody );
579     free( p );
580 }
581 
582 
583 ////////////////////////////////////////////////////////////////////////
584 ///                  FILE READING AND WRITING                        ///
585 ////////////////////////////////////////////////////////////////////////
586 
587 // file reading/writing
Ndr_Read(char * pFileName)588 static inline void * Ndr_Read( char * pFileName )
589 {
590     Ndr_Data_t * p; int nFileSize, RetValue;
591     FILE * pFile = fopen( pFileName, "rb" );
592     if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for reading.\n", pFileName ); return NULL; }
593     // check file size
594     fseek( pFile, 0, SEEK_END );
595     nFileSize = ftell( pFile );
596     if ( nFileSize % 5 != 0 )
597         return NULL;
598     assert( nFileSize % 5 == 0 );
599     rewind( pFile );
600     // create structure
601     p = NDR_ALLOC( Ndr_Data_t, 1 );
602     p->nSize = p->nCap = nFileSize / 5;
603     p->pHead = NDR_ALLOC( unsigned char, p->nCap );
604     p->pBody = NDR_ALLOC( unsigned int, p->nCap * 4 );
605     RetValue = (int)fread( p->pBody, 4, p->nCap, pFile );
606     RetValue = (int)fread( p->pHead, 1, p->nCap, pFile );
607     assert( p->nSize == (int)p->pBody[0] );
608     fclose( pFile );
609     //printf( "Read the design from file \"%s\".\n", pFileName );
610     return p;
611 }
Ndr_Write(char * pFileName,void * pDesign)612 static inline void Ndr_Write( char * pFileName, void * pDesign )
613 {
614     Ndr_Data_t * p = (Ndr_Data_t *)pDesign; int RetValue;
615     FILE * pFile = fopen( pFileName, "wb" );
616     if ( pFile == NULL ) { printf( "Cannot open file \"%s\" for writing.\n", pFileName ); return; }
617     RetValue = (int)fwrite( p->pBody, 4, p->pBody[0], pFile );
618     RetValue = (int)fwrite( p->pHead, 1, p->pBody[0], pFile );
619     fclose( pFile );
620     //printf( "Dumped the design into file \"%s\".\n", pFileName );
621 }
622 
623 
624 ////////////////////////////////////////////////////////////////////////
625 ///                     TESTING PROCEDURE                            ///
626 ////////////////////////////////////////////////////////////////////////
627 
628 // This testing procedure creates and writes into a Verilog file
629 // the following design composed of one module
630 
631 // module add10 ( input [3:0] a, output [3:0] s );
632 //   wire [3:0] const10 = 4'b1010;
633 //   assign s = a + const10;
634 // endmodule
635 
Ndr_ModuleTest()636 static inline void Ndr_ModuleTest()
637 {
638     // name IDs
639     int NameIdA = 2;
640     int NameIdS = 3;
641     int NameIdC = 4;
642     // array of fanins of node s
643     int Fanins[2] = { NameIdA, NameIdC };
644     // map name IDs into char strings
645     char * ppNames[5] = { NULL, "add10", "a", "s", "const10" };
646 
647     // create a new module
648     void * pDesign = Ndr_Create( 1 );
649 
650     int ModuleID = Ndr_AddModule( pDesign, 1 );
651 
652     // add objects to the modele
653     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   3, 0, 0,   0, NULL,      1, &NameIdA,   NULL      ); // no fanins
654     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONST,    0,   3, 0, 0,   0, NULL,      1, &NameIdC,   "4'b1010" ); // no fanins
655     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD,  0,   3, 0, 0,   2, Fanins,    1, &NameIdS,   NULL      ); // fanins are a and const10
656     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   3, 0, 0,   1, &NameIdS,  0, NULL,       NULL      ); // fanin is a
657 
658     // write Verilog for verification
659     Ndr_WriteVerilog( NULL, pDesign, ppNames );
660     Ndr_Write( "add4.ndr", pDesign );
661     Ndr_Delete( pDesign );
662 }
663 
664 
665 
666 // This testing procedure creates and writes into a Verilog file
667 // the following design composed of one adder divided into two
668 
669 // module add8 ( input [7:0] a, input [7:0] b, output [7:0] s, output co );
670 //   wire [3:0] a0 = a[3:0];
671 //   wire [3:0] b0 = b[3:0];
672 
673 //   wire [7:4] a1 = a[7:4];
674 //   wire [7:4] b1 = b[7:4];
675 
676 //   wire [4:0] r0 = a0 + b0;
677 //   wire [3:0] s0 = r0[3:0];
678 //   wire rco = r0[4];
679 
680 //   wire [4:0] r1 = a1 + b1 + rco;
681 //   wire [3:0] s1 = r1[3:0];
682 //   assign co = r1[4];
683 
684 //   assign s = {s1, s0};
685 // endmodule
686 
Ndr_ModuleTestAdder()687 static inline void Ndr_ModuleTestAdder()
688 {
689     // map name IDs into char strings
690     char * ppNames[20] = {  NULL,
691                            "a", "b", "s", "co",          // 1,  2,  3,  4
692                            "a0",  "a1",  "b0",  "b1",    // 5,  6,  7,  8
693                            "r0", "s0", "rco",            // 9,  10, 11
694                            "r1", "s1", "add8"            // 12, 13, 14
695                          };
696     // fanins
697     int FaninA        =  1;
698     int FaninB        =  2;
699     int FaninS        =  3;
700     int FaninCO       =  4;
701 
702     int FaninA0       =  5;
703     int FaninA1       =  6;
704     int FaninB0       =  7;
705     int FaninB1       =  8;
706 
707     int FaninR0       =  9;
708     int FaninS0       = 10;
709     int FaninRCO      = 11;
710 
711     int FaninR1       = 12;
712     int FaninS1       = 13;
713 
714     int Fanins1[2]    = { FaninA0, FaninB0 };
715     int Fanins2[3]    = { FaninA1, FaninB1, FaninRCO };
716     int Fanins3[4]    = { FaninS1, FaninS0 };
717 
718     // create a new module
719     void * pDesign = Ndr_Create( 14 );
720 
721     int ModuleID = Ndr_AddModule( pDesign, 14 );
722 
723     // add objects to the modele
724     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   7, 0, 0,   0, NULL,      1, &FaninA,   NULL  );  // no fanins
725     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   7, 0, 0,   0, NULL,      1, &FaninB,   NULL  );  // no fanins
726 
727     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   3, 0, 0,   1, &FaninA,   1, &FaninA0,   NULL );  // wire [3:0] a0 = a[3:0];
728     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   3, 0, 0,   1, &FaninB,   1, &FaninB0,   NULL );  // wire [3:0] b0 = a[3:0];
729 
730     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   7, 4, 0,   1, &FaninA,   1, &FaninA1,   NULL );  // wire [7:4] a1 = a[7:4];
731     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   7, 4, 0,   1, &FaninB,   1, &FaninB1,   NULL );  // wire [7:4] b1 = b[7:4];
732 
733     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD,  0,   4, 0, 0,   2, Fanins1,   1, &FaninR0,   NULL );  // wire [4:0] r0 = a0 + b0;
734     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   3, 0, 0,   1, &FaninR0,  1, &FaninS0,   NULL );  // wire [3:0] s0 = r0[3:0];
735     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   4, 4, 0,   1, &FaninR0,  1, &FaninRCO,  NULL );  // wire rco = r0[4];
736 
737     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADD,  0,   4, 0, 0,   3, Fanins2,   1, &FaninR1,   NULL );  // wire [4:0] r1 = a1 + b1 + rco;
738     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   3, 0, 0,   1, &FaninR1,  1, &FaninS1,   NULL );  // wire [3:0] s1 = r1[3:0];
739     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SLICE,    0,   4, 4, 0,   1, &FaninR1,  1, &FaninCO,   NULL );  // assign co = r1[4];
740 
741     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CONCAT,   0,   7, 0, 0,   2, Fanins3,   1, &FaninS,    NULL );  // s = {s1, s0};
742 
743     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   7, 0, 0,   1, &FaninS,   0, NULL,       NULL );
744     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   0, 0, 0,   1, &FaninCO,  0, NULL,       NULL );
745 
746     // write Verilog for verification
747     Ndr_WriteVerilog( NULL, pDesign, ppNames );
748     Ndr_Write( "add8.ndr", pDesign );
749     Ndr_Delete( pDesign );
750 
751 }
752 
753 // This testing procedure creates and writes into a Verilog file
754 // the following hierarchical design composed of two modules
755 
756 // module mux21w ( input sel, input [3:0] d1, input [3:0] d0, output [3:0] out );
757 //   assign out = sel ? d1 : d0;
758 // endmodule
759 
760 // module mux41w ( input [1:0] sel, input [15:0] d, output [3:0] out );
761 //   wire [3:0] t0, t1;
762 //   wire [3:0] d0 = d[3:0];
763 //   wire [3:0] d1 = d[7:4];
764 //   wire [3:0] d2 = d[11:8];
765 //   wire [3:0] d3 = d[15:12];
766 //   wire sel0 = sel[0];
767 //   wire sel1 = sel[1];
768 //   mux21w i0 ( sel0, d1, d0, t0 );
769 //   mux21w i1 ( sel0, d3, d2, t1 );
770 //   mux21w i2 ( sel1, t1, t0, out );
771 // endmodule
772 
Ndr_ModuleTestHierarchy()773 static inline void Ndr_ModuleTestHierarchy()
774 {
775     // map name IDs into char strings
776     char * ppNames[20] = {  NULL,
777                            "mux21w", "mux41w",     // 1,  2
778                            "sel",  "d",  "out",    // 3,  4,  5
779                            "d0", "d1", "d2", "d3", // 6,  7,  8,  9
780                            "sel0", "sel1",         // 10, 11,
781                            "t0", "t1",             // 12, 13
782                            "i0", "i1", "i2"        // 14, 15, 16
783                          };
784     // fanins
785     int FaninSel      =  3;
786     int FaninSel0     = 10;
787     int FaninSel1     = 11;
788     int FaninD        =  4;
789     int FaninD0       =  6;
790     int FaninD1       =  7;
791     int FaninD2       =  8;
792     int FaninD3       =  9;
793     int FaninT0       = 12;
794     int FaninT1       = 13;
795     int FaninOut      =  5;
796     int Fanins1[3]    = {  FaninSel,  FaninD1, FaninD0 };
797     int Fanins3[3][3] = { {FaninSel0, FaninD1, FaninD0 },
798                           {FaninSel0, FaninD3, FaninD2 },
799                           {FaninSel1, FaninT1, FaninT0 } };
800 
801     // create a new module
802     void * pDesign = Ndr_Create( 2 );
803 
804     int Module21, Module41;
805 
806     Module21 = Ndr_AddModule( pDesign, 1 );
807 
808     Ndr_AddObject( pDesign, Module21, ABC_OPER_CI,        0,   0, 0, 0,   0, NULL,        1, &FaninSel,  NULL );
809     Ndr_AddObject( pDesign, Module21, ABC_OPER_CI,        0,   3, 0, 0,   0, NULL,        1, &FaninD1,   NULL );
810     Ndr_AddObject( pDesign, Module21, ABC_OPER_CI,        0,   3, 0, 0,   0, NULL,        1, &FaninD0,   NULL );
811     Ndr_AddObject( pDesign, Module21, ABC_OPER_BIT_MUX,   0,   3, 0, 0,   3, Fanins1,     1, &FaninOut,  NULL );
812     Ndr_AddObject( pDesign, Module21, ABC_OPER_CO,        0,   3, 0, 0,   1, &FaninOut,   0, NULL,       NULL );
813 
814     Module41 = Ndr_AddModule( pDesign, 2 );
815 
816     Ndr_AddObject( pDesign, Module41, ABC_OPER_CI,        0,   1, 0, 0,   0, NULL,        1, &FaninSel,  NULL );
817     Ndr_AddObject( pDesign, Module41, ABC_OPER_CI,        0,   15,0, 0,   0, NULL,        1, &FaninD,    NULL );
818 
819     Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE,     0,   3, 0, 0,   1, &FaninD,     1, &FaninD0,   NULL );
820     Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE,     0,   7, 4, 0,   1, &FaninD,     1, &FaninD1,   NULL );
821     Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE,     0,   11,8, 0,   1, &FaninD,     1, &FaninD2,   NULL );
822     Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE,     0,   15,12,0,   1, &FaninD,     1, &FaninD3,   NULL );
823 
824     Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE,     0,   0, 0, 0,   1, &FaninSel,   1, &FaninSel0, NULL );
825     Ndr_AddObject( pDesign, Module41, ABC_OPER_SLICE,     0,   1, 1, 0,   1, &FaninSel,   1, &FaninSel1, NULL );
826 
827     Ndr_AddObject( pDesign, Module41, Module21,          14,   3, 0, 0,   3, Fanins3[0],  1, &FaninT0,   NULL );
828     Ndr_AddObject( pDesign, Module41, Module21,          15,   3, 0, 0,   3, Fanins3[1],  1, &FaninT1,   NULL );
829     Ndr_AddObject( pDesign, Module41, Module21,          16,   3, 0, 0,   3, Fanins3[2],  1, &FaninOut,  NULL );
830     Ndr_AddObject( pDesign, Module41, ABC_OPER_CO,        0,   3, 0, 0,   1, &FaninOut,   0, NULL,       NULL );
831 
832     // write Verilog for verification
833     Ndr_WriteVerilog( NULL, pDesign, ppNames );
834     Ndr_Write( "mux41w.ndr", pDesign );
835     Ndr_Delete( pDesign );
836 }
837 
838 
839 // This testing procedure creates and writes into a Verilog file
840 // the following design with read/write memory ports
841 
842 // module test ( input clk, input [8:0] raddr, input [8:0] waddr, input [31:0] data, input [16383:0] mem_init, output out );
843 //
844 //    wire [31:0] read1, read2;
845 //
846 //    wire [16383:0] mem_fo1, mem_fo2,  mem_fi1, mem_fi2;
847 //
848 //    ABC_FF    i_reg1   ( .q(mem_fo1), .d(mem_fi1), .init(mem_init) );
849 //    ABC_FF    i_reg2   ( .q(mem_fo2), .d(mem_fi2), .init(mem_init) );
850 //
851 //    ABC_WRITE i_write1 ( .mem_out(mem_fi1), .mem_in(mem_fo1), .addr(waddr), .data(data) );
852 //    ABC_WRITE i_write2 ( .mem_out(mem_fi2), .mem_in(mem_fo2), .addr(waddr), .data(data) );
853 //
854 //    ABC_READ  i_read1  ( .data(read1), .mem_in(mem_fi1), .addr(raddr) );
855 //    ABC_READ  i_read2  ( .data(read2), .mem_in(mem_fi2), .addr(raddr) );
856 //
857 //    assign out = read1 != read2;
858 //endmodule
859 
Ndr_ModuleTestMemory()860 static inline void Ndr_ModuleTestMemory()
861 {
862     // map name IDs into char strings
863     char * ppNames[20] = {  NULL,
864                            "clk", "raddr", "waddr", "data", "mem_init", "out",  // 1, 2, 3, 4, 5, 6
865                            "read1",  "read2",                                   // 7. 8
866                            "mem_fo1", "mem_fo2", "mem_fi1", "mem_fi2",          // 9, 10, 11, 12
867                            "i_reg1", "i_reg2",                                  // 13, 14
868                            "i_read1", "i_read2",                                // 15, 16
869                            "i_write1", "i_write2", "memtest"                    // 17, 18, 19
870                          };
871     // inputs
872     int NameIdClk     = 1;
873     int NameIdRaddr   = 2;
874     int NameIdWaddr   = 3;
875     int NameIdData    = 4;
876     int NameIdMemInit = 5;
877     // flops
878     int NameIdFF1     =  9;
879     int NameIdFF2     = 10;
880     int FaninsFF1[2]  = { 11, 5 };
881     int FaninsFF2[2]  = { 12, 5 };
882     // writes
883     int NameIdWrite1    = 11;
884     int NameIdWrite2    = 12;
885     int FaninsWrite1[3] = {  9, 3, 4 };
886     int FaninsWrite2[3] = { 10, 3, 4 };
887     // reads
888     int NameIdRead1    =  7;
889     int NameIdRead2    =  8;
890     int FaninsRead1[2] = { 11, 2 };
891     int FaninsRead2[2] = { 12, 2 };
892     // compare
893     int NameIdComp      = 6;
894     int FaninsComp[2]   = { 7, 8 };
895 
896     // create a new module
897     void * pDesign = Ndr_Create( 19 );           // create design named "memtest"
898 
899     int ModuleID = Ndr_AddModule( pDesign, 19 ); // create module named "memtest"
900 
901     // add objects to the module
902     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,           0,     0, 0, 0,   0, NULL,         1, &NameIdClk,     NULL );
903     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,           0,     8, 0, 0,   0, NULL,         1, &NameIdRaddr,   NULL );
904     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,           0,     8, 0, 0,   0, NULL,         1, &NameIdWaddr,   NULL );
905     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,           0,    31, 0, 0,   0, NULL,         1, &NameIdData,    NULL );
906     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,           0, 16383, 0, 0,   0, NULL,         1, &NameIdMemInit, NULL );
907 
908     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,           0,     0, 0, 0,   1, &NameIdComp,  0, NULL,           NULL );
909 
910     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF,         13, 16383, 0, 0,   2, FaninsFF1,    1, &NameIdFF1,     NULL );
911     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFF,         14, 16383, 0, 0,   2, FaninsFF2,    1, &NameIdFF2,     NULL );
912 
913     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW,        17, 16383, 0, 0,   3, FaninsWrite1, 1, &NameIdWrite1,  NULL );
914     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMW,        18, 16383, 0, 0,   3, FaninsWrite2, 1, &NameIdWrite2,  NULL );
915 
916     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR,        15,    31, 0, 0,   2, FaninsRead1,  1, &NameIdRead1,   NULL );
917     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_RAMR,        16,    31, 0, 0,   2, FaninsRead2,  1, &NameIdRead2,   NULL );
918 
919     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_COMP_NOTEQU,  0,     0, 0, 0,   2, FaninsComp,   1, &NameIdComp,    NULL );
920 
921     // write Verilog for verification
922     Ndr_WriteVerilog( NULL, pDesign, ppNames );
923     Ndr_Write( "memtest.ndr", pDesign );
924     Ndr_Delete( pDesign );
925 }
926 
927 // This testing procedure creates and writes into a Verilog file
928 // the following design composed of one word-level flop
929 
930 // module flop ( input [3:0] data, input clk, input reset, input set, input enable, input async, input sre, input [3:0] init, output [3:0] q );
931 //   ABC_DFFRSE reg1 ( .d(data), .clk(clk), .reset(reset), .set(set), .enable(enable), .async(async), .sre(sre), .init(init), .q(q) ) ;
932 // endmodule
933 
Ndr_ModuleTestFlop()934 static inline void Ndr_ModuleTestFlop()
935 {
936     // map name IDs into char strings
937     char * ppNames[12] = { NULL, "flop", "data", "clk", "reset", "set", "enable", "async", "sre", "init", "q" };
938     // name IDs
939     int NameIdData   =  2;
940     int NameIdClk    =  3;
941     int NameIdReset  =  4;
942     int NameIdSet    =  5;
943     int NameIdEnable =  6;
944     int NameIdAsync  =  7;
945     int NameIdSre    =  8;
946     int NameIdInit   =  9;
947     int NameIdQ      = 10;
948     // array of fanins of node s
949     int Fanins[8] = { NameIdData, NameIdClk, NameIdReset, NameIdSet, NameIdEnable, NameIdAsync, NameIdSre, NameIdInit };
950 
951     // create a new module
952     void * pDesign = Ndr_Create( 1 );
953 
954     int ModuleID = Ndr_AddModule( pDesign, 1 );
955 
956     // add objects to the modele
957     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   3, 0, 0,   0, NULL,      1, &NameIdData,   NULL );
958     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   0, 0, 0,   0, NULL,      1, &NameIdClk,    NULL );
959     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   0, 0, 0,   0, NULL,      1, &NameIdReset,  NULL );
960     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   0, 0, 0,   0, NULL,      1, &NameIdSet,    NULL );
961     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   0, 0, 0,   0, NULL,      1, &NameIdEnable, NULL );
962     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   0, 0, 0,   0, NULL,      1, &NameIdAsync,  NULL );
963     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   0, 0, 0,   0, NULL,      1, &NameIdSre,    NULL );
964     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   3, 0, 0,   0, NULL,      1, &NameIdInit,   NULL );
965 
966     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_DFFRSE,   0,   3, 0, 0,   8, Fanins,    1, &NameIdQ,      NULL );
967 
968     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   3, 0, 0,   1, &NameIdQ,  0, NULL,          NULL );
969 
970     // write Verilog for verification
971     Ndr_WriteVerilog( NULL, pDesign, ppNames );
972     Ndr_Write( "flop.ndr", pDesign );
973     Ndr_Delete( pDesign );
974 }
975 
976 
977 // This testing procedure creates and writes into a Verilog file
978 // the following design composed of one selector
979 
980 // module sel ( input [3:0] c, input [2:0] d0, input [2:0] d1, input [2:0] d2, input [2:0] d3, input [2:0] out );
981 //     wire [2:0] s7 ;
982 //     always @( c or d0 or d1 or d2 or d3 )
983 //       begin
984 //         case ( c )
985 //           4'b0001 : s7 = d0 ;
986 //           4'b0010 : s7 = d1 ;
987 //           4'b0100 : s7 = d2 ;
988 //           4'b1000 : s7 = d3 ;
989 //         endcase
990 //       end
991 //     assign  out = s7 ;
992 // endmodule
993 
Ndr_ModuleTestSelSel()994 static inline void Ndr_ModuleTestSelSel()
995 {
996     // map name IDs into char strings
997     //char * ppNames[12] = { NULL, "sel", "c", "d0", "d1", "d2", "d3", "out" };
998     // name IDs
999     int NameIdC      =  2;
1000     int NameIdD0     =  3;
1001     int NameIdD1     =  4;
1002     int NameIdD2     =  5;
1003     int NameIdD3     =  6;
1004     int NameIdOut    =  7;
1005     // array of fanins of node s
1006     int Fanins[8] = { NameIdC, NameIdD0, NameIdD1, NameIdD2, NameIdD3 };
1007 
1008     // create a new module
1009     void * pDesign = Ndr_Create( 1 );
1010 
1011     int ModuleID = Ndr_AddModule( pDesign, 1 );
1012 
1013     // add objects to the modele
1014     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   3, 0, 0,   0, NULL,      1, &NameIdC,      NULL );
1015     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   2, 0, 0,   0, NULL,      1, &NameIdD0,     NULL );
1016     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   2, 0, 0,   0, NULL,      1, &NameIdD1,     NULL );
1017     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   2, 0, 0,   0, NULL,      1, &NameIdD2,     NULL );
1018     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   2, 0, 0,   0, NULL,      1, &NameIdD3,     NULL );
1019 
1020     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_SEL,  0,   2, 0, 0,   5, Fanins,    1, &NameIdOut,    NULL );
1021 
1022     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   2, 0, 0,   1, &NameIdOut,0, NULL,          NULL );
1023 
1024     // write Verilog for verification
1025     //Ndr_WriteVerilog( NULL, pDesign, ppNames );
1026     Ndr_Write( "sel.ndr", pDesign );
1027     Ndr_Delete( pDesign );
1028 }
1029 
1030 // This testing procedure creates and writes into a Verilog file
1031 // the following design composed of one decoder
1032 
1033 // module dec ( input [1:0] in, output [3:0] out );
1034 //     wire out0 = ~in[1] & ~in[0] ;
1035 //     wire out1 = ~in[1] &  in[0] ;
1036 //     wire out2 =  in[1] & ~in[0] ;
1037 //     wire out3 =  in[1] &  in[0] ;
1038 //     assign out = { out3, out2, out1, out0 } ;
1039 // endmodule
1040 
Ndr_ModuleTestDec()1041 static inline void Ndr_ModuleTestDec()
1042 {
1043     // map name IDs into char strings
1044     //char * ppNames[12] = { NULL, "dec", "in", "out" };
1045     // name IDs
1046     int NameIdIn     =  2;
1047     int NameIdOut    =  3;
1048 
1049     // create a new module
1050     void * pDesign = Ndr_Create( 1 );
1051 
1052     int ModuleID = Ndr_AddModule( pDesign, 1 );
1053 
1054     // add objects to the modele
1055     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   1, 0, 0,   0, NULL,       1, &NameIdIn,     NULL );
1056     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_SEL_DEC,  0,   3, 0, 0,   1, &NameIdIn,  1, &NameIdOut,    NULL );
1057     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   3, 0, 0,   1, &NameIdOut, 0, NULL,          NULL );
1058 
1059     Ndr_Write( "dec.ndr", pDesign );
1060     Ndr_Delete( pDesign );
1061 }
1062 
1063 // This testing procedure creates and writes into a Verilog file
1064 // the following design composed of one adder/subtractor
1065 
1066 // module addsub ( input mode, input cin, input [2:0] a, input [2:0] b, output [3:0] out );
1067 //     assign out = mode ? a+b+cin : a-b-cin ;
1068 // endmodule
1069 
Ndr_ModuleTestAddSub()1070 static inline void Ndr_ModuleTestAddSub()
1071 {
1072     // map name IDs into char strings
1073     //char * ppNames[12] = { NULL, "addsub", "mode", "cin", "a", "b", "out" };
1074     // name IDs
1075     int NameIdInMode =  2;
1076     int NameIdInCin  =  3;
1077     int NameIdInA    =  4;
1078     int NameIdInB    =  5;
1079     int NameIdOut    =  6;
1080     int Fanins[8] = { 2, 3, 4, 5 };
1081 
1082     // create a new module
1083     void * pDesign = Ndr_Create( 1 );
1084 
1085     int ModuleID = Ndr_AddModule( pDesign, 1 );
1086 
1087     // add objects to the modele
1088     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,          0,   0, 0, 0,   0, NULL,       1, &NameIdInMode, NULL );
1089     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,          0,   0, 0, 0,   0, NULL,       1, &NameIdInCin,  NULL );
1090     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,          0,   2, 0, 0,   0, NULL,       1, &NameIdInA,    NULL );
1091     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,          0,   2, 0, 0,   0, NULL,       1, &NameIdInB,    NULL );
1092     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_ARI_ADDSUB,  0,   3, 0, 0,   4, Fanins,     1, &NameIdOut,    NULL );
1093     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,          0,   3, 0, 0,   1, &NameIdOut, 0, NULL,          NULL );
1094 
1095     Ndr_Write( "addsub.ndr", pDesign );
1096     Ndr_Delete( pDesign );
1097 }
1098 
1099 // This testing procedure creates and writes into a Verilog file
1100 // the following design composed of one lookup table with function of AND2
1101 
1102 // module lut_test ( input [1:0] in, output out );
1103 //     assign out = LUT #(TT=4'h8) lut_inst { in[0], in[1], out } ;
1104 // endmodule
1105 
Ndr_ModuleTestLut()1106 static inline void Ndr_ModuleTestLut()
1107 {
1108     // map name IDs into char strings
1109     //char * ppNames[12] = { NULL, "lut_test", "in", "out" };
1110     // name IDs
1111     int NameIdIn     =  2;
1112     int NameIdOut    =  3;
1113 
1114     // create a new module
1115     void * pDesign = Ndr_Create( 1 );
1116 
1117     int ModuleID = Ndr_AddModule( pDesign, 1 );
1118 
1119     // add objects to the modele
1120     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CI,       0,   1, 0, 0,   0, NULL,       1, &NameIdIn,     NULL );
1121     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_LUT,      0,   0, 0, 0,   1, &NameIdIn,  1, &NameIdOut,    (char *)(ABC_CONST(0x8)) );
1122     Ndr_AddObject( pDesign, ModuleID, ABC_OPER_CO,       0,   0, 0, 0,   1, &NameIdOut, 0, NULL,          NULL );
1123 
1124     Ndr_Write( "lut_test.ndr", pDesign );
1125     Ndr_Delete( pDesign );
1126 }
1127 
1128 ABC_NAMESPACE_HEADER_END
1129 
1130 #endif
1131 
1132 ////////////////////////////////////////////////////////////////////////
1133 ///                       END OF FILE                                ///
1134 ////////////////////////////////////////////////////////////////////////
1135 
1136