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