1NETGEN -- An embedded-language netlist specification.
2
3NETGEN consists of a set of C language subroutines intended to facilitate
4the specification of netlists of circuits that are ill-suited to
5conventional schematic-capture paradigms.
6
7Some of the features of the NETGEN system:
8
91)  full hierarchical specification of the circuit in question.
102)  powerful list-based operators that permit rapid declaration
11and subsequent connection of semantic structures such as busses,
12signal vectors, port lists, etc.
133)  optional topology-driven front end, providing connectivity of
14cells according to a composition-by-abuttment paradigm.
154)  dynamic scoping rules governing visibility of ports and nodes.
165)  support for multiple output netlist file formats,
17including .NTK, .EXT (and consequently .SIM), .ACTEL, and .WOMBAT.
18In addition, hierarchical .NTK files can be read, providing an
19alternate mechanism to input cells.
20
21Hierarchical specification of circuits.
22
23The basic unit in defining a circuit is a CELL.  A cell, in turn, can
24contain any number of other cells, called INSTANCES.  A cell has some
25special nodes, called PORTS, that are the connections that can be
26made to the cell when it is instanced.  When a cell is actually
27instanced, these ports are called PINS within the context of the cell
28being constructed.  The ports (of the current cell) and pins (of
29previously defined cells) may connect together directly, or through
30optional NODES.
31
32So much for the definitions.  Now the good news:  within a CELL, there
33are 3 kinds of elements (PORTS, NODES, and PINS);  these are treated
34ABSOLUTELY IDENTICALLY from the user's perspective.  NETGEN has a uniform
35internal representation with a single operator: "connect".  In defining
36a cell, the user "connects" ports, nodes, and pins as required to construct
37the desired circuit.  In particular, there is no real notion of a "wire"
38within NETGEN; situations where named signal lines would be useful can
39be accomodated by using named internal nodes.
40
41In it's simplest form, the user interface to NETGEN consists of
42four procedures:
43
44
45  void CellDef(char *name);
46
47  Declares cell "name", and appends all future commands to the definition
48of that cell.
49
50
51  void Port(char *name);
52
53  Declares a port node called "name" within the current cell.
54
55
56  void Node(char *name);
57
58  Declares an internal node called "name" within the current cell.
59
60
61  void Instance(char *cell, *instancename);
62
63  Incorporates an instance of cell "cell" into the current cell; the
64instance is called "instancename", which must be a unique identifier
65within the context of the current cell (the function Next(cell) is
66often useful in generating this unique identifier).  The Instance()
67procedure generates a set of PINS corresponding to the ports of
68"cell"; these pins are named "instancename"/"portname".
69
70As a (trivial) example, consider the following definition of
71the elements within a CMOS inverter:
72
73    CellDef("inv");
74        PortDef("in");
75        PortDef("out");
76        PortDef("vdd");
77        PortDef("gnd");
78        Instance("p","pullup");
79        Instance("n","pulldown");
80
81Instance() also has some subtle side-effects.  See the section
82below on dynamic scoping for a discussion of how these can be used
83to implicitly connect elements automatically.
84
85Connecting up the circuit;  (or, using wirelists effectively).
86
87We must now specify how the above elements are to be interconnected.
88The most general form of this operator is:
89
90      void Connect(char *list1, *list2);
91
92In its simplest form, list1 and list2 are the names of two elements
93to be connected together.  In the above example,
94
95      Connect("pulldown/source", "gnd");
96      Connect("pullup/source", "vdd");
97      Connect("pulldown/gate", "in");
98      Connect("pullup/gate", "in");
99      Connect("pulldown/drain", "out");
100      Connect("pullup/drain", "out");
101
102completes the specification of the inverter.  However, the same result
103can be obtained more simply by the use of WILDCARDS in the list-constructor
104strings list1 and list2.  Supported wildcards are the UNIX(TM) shell
105wildcards (*,?,{},[]) where:
106   * matches 0 or more characters (unlike csh, "/" is treated
107       identically to any other character).
108   ? matches any single character.
109   {} delimits alternate choices.  For example "c{a,o}t" matches "cat"
110       and "cot".
111   [] delimits ranges for matching a single character.  For example,
112       "cell[1-3]" matches "cell1", "cell2", and "cell3".  Multiple
113       ranges can be specified (e.g. [a-mp-x]), as can excluded
114       ranges ([~a-m]).
115
116Full regular expression pattern matching is also available.  To use this
117form, set the global flag UnixWildcards to 0, and see regexp(3) for
118detailed syntax.
119
120The result of Connecting two lists is the following:
121a) if the lists are the same length, corresponding pairs of elements
122are connected to each other,
123b) if one of the lists has a single element, all elements of the
124other list are connected to that element,
125c) otherwise, the lists are of unequal lengths and an error is reported.
126
127Thus, the inverter can be specified simply by:
128       Connect("*drain", "out");
129       Connect("*gate", "in");
130       Connect("*up/source", "vdd");
131       Connect("*down/source", "gnd");
132
133The ORDER of generated list elements is the same as the order in which
134the elements were added to the cell.  In the above example,
135"*gate" gets expanded to {"pullup/gate","pulldown/gate"}.  It is possible
136to take advantage of wildcards (and this bit of information) even
137further:
138       Connect("*drain", "out");
139       Connect("*gate", "in");
140       Connect("*source","*d");
141
142The user should, however, try to minimize the abuse of wildcards at
143the expense of clarity.  Wildcards are provided to expedite grouping
144of elements with associated semantics (see the section below on
145topological specification of interconnection), NOT to minimize the
146keystrokes required to specify a netlist.
147
148The relationship between placement and interconnect.
149
150NETGEN provides a simple model for VLSI cell placement:  cells are
151rectangular and have ports along the perimeter on 4 sides (N,S,E,W).
152Composition is by abuttment and can occur in either the horizontal
153or vertical direction.  When two cells are placed so that they share
154an edge, the port lists along that edge of the respective cells are
155generated, and the Connect operator is invoked on them.  Ports along
156the othogonal edges are propagated as ports of the cell being defined.
157The (implied) order of ports in cells is bottom-to-top on vertical
158edges, and left-to-right on horizontal edges, corresponding to the
159order of placement of subsequent cells.
160
161  void Place(char *name);
162
163  An instance of cell "name" is generated, and placed in a direction
164corresponding to the "Composition" flag (if Composition==HORIZONTAL,
165the cell is placed to the right of any previously placed cells; if
166Composition==VERTICAL, the cell is placed above; if
167Composition==NONE, a call to Place(name) is equivalent to
168Instance(name,Next(name))).  A unique instance name is generated for
169the cell, by appending an integer (starting at 1) to "name".  Ports
170along abutting edges are "sealed", and ports along orthogonal edges
171are made ports of the cell being defined.  In the first call to Place
172within a cell, the leftmost (or bottom, if Composition==VERTICAL)
173ports of cell "name" are defined to be the corresponding ports of the
174cell being defined.  In order to correctly generate the port list at
175the other end of the cell, the procedure:
176
177   void EndCell();
178
179must be called to end the current cell definition.  It is good form to
180always terminate cell definitions with this statement (even if you
181did not use the implicit composition mechanism) -- one side-effect of
182EndCell() is to arbitrarily connect all otherwise disconnected nodes
183if the global variable NoDisconnectedNodes is set to 1 (the default is 0).
184
185In order to understand the relationship between topology and connectivity,
186the user must adhere to a particular NAMING CONVENTION.  Ports must
187be declared in the correct order (bottom-to-top and left-to-right),
188and with the following syntax:  the side of the port is prepended
189to the port name, separated by a ".".  For example, if the input
190to the inverter is to be on the left (west) side, we would
191replace the previous definition of port "in" by:
192
193      Port("W.in");
194
195Corresponding changes are required for the other ports (for example,
196"E.out", "N.vdd", "S.gnd").  Then, the specification for a chain of 4
197inverters (perhaps an exponential horn for a pad driver) takes the
198form:
199
200    CellDef("exphorn");
201       Composition = HORIZONTAL;
202       for (i=0; i<4; i++) Place("inv");
203       EndCell();
204
205This code fragment specifies a cell "exphorn" that takes a single
206input on the left (west) side, generates a single output on the
207right side, and has 4 ports on the top (which should be connected
208to vdd in the cell that calls "exphorn"), and 4 on the bottom (gnd).
209
210To simplify code fragments such as the above, the procedure
211
212   void Array(char *name, int count)
213
214is provided, and is equivalent to "for (i=0;i<count;i++) Place(name)".
215
216Scoping rules for identifiers;  Implicit (global) connections.
217
218   It is often inconvenient to have to continually declare high
219connectivity nodes (e.g. power rails, bit/word lines, etc.) explicitly
220as parameters to each cell.  Also, the number of ports of generated
221cells (see example above) can be kept managable.
222
223   The solution to this problem takes the form of scoping rules for
224element names; when a cell is instantiated within the context of a
225calling cell, particular elements within the CALLED cell are
226implicitly connected to elements in the PARENT cell.  This binding
227process is exactly analogous to local/global variables within nested
228PASCAL procedure declarations, but the process is slightly different:
229instead of declaring LOCAL variables, and assuming all others to have
230GLOBAL visibility, particular ports (i.e. explicitly global objects)
231are declared to obey certain implicit connection rules by the
232following:
233
234   void Global(char *name);
235
236Semantically, "name" is a PORT that connects itself automatically
237when the cell is instanced.  In particular, a port obtained by a call
238to Global("xxx") in cell B will automatically connect to an element
239named "xxx" in cell A, whenever A instantiates B.  If "xxx" does not
240exist in A, the instantiation of B will CAUSE a global port named
241"xxx" to be declared (by a call to Global("xxx") in A).  The result
242of this action is that the unbound variable "xxx" is now propagated
243to the next level of the hierarchy. This dynamic scoping allows
244cell B (which is instantiated within cell A) to be declared
245BEFORE cell A.
246
247   An example is useful.  Reconsider the "inv" cell above, but this
248time change the definitions of the power ports to :
249
250   Global("vdd");
251   Global("gnd");
252
253The previous code fragment for "exphorn" would now result
254in a cell with 4 ports, named "vdd", "gnd", "W.inv1/W.in" and
255"E.inv4/E.out" (instead of the previous exphorn, which had 10 ports).
256
257Naming conventions:
258
259Within the context of the calling cell:
260
2611) Ports:
262      <instance name> SEPARATOR <port name>
263
2642) Ports - Oriented:
265      <side> { PORT_DELIMITER <instance name> PORT_DELIMITER <side>}*  \
266             PORT_DELIMITER <port name>
267
2683) Ports - Global:
269      <port name>  --  name propagates unchanged, but is bound to
270             locally-declared identifier of same name.
271
2724) Ports - Unique Global:
273      <my class name> INSTANCE_DELIMITER <instance name> SEPARATOR <port name>
274
2755) Flattened cells:
276      <instance name> { SEPARATOR <instance name> }* SEPARATOR <port name>
277
2786) Cells read from NTK:
279      <instance class> INSTANCE_DELIMITER <instance name> SEPARATOR <port name>
280
281
282
283Other Procedures (i.e. what else do I need to know?)
284
285   In order to use the NETGEN package, the user's program must include
286the library, link the correct object module, and initialize the package.
287
288The first is accomplished by the line:
289
290   #include "netgen.h"
291
292at the top of every program.  In practice, "netgen.h" is not likely
293to be found in the current directory, so ask a system guru where it
294is located.  The same goes for the object file "netgen.a"  that must
295be linked in (via a command-line parameter in UNIX; if you are
296running NETGEN on a PC (or maybe even someday on a chipmunk) talk
297to a system mangler).
298
299The NETGEN package is written in ANSI-standard C, and requires
300an ANSI-C compiler.  On many UNIX systems, the GNU C compiler
301is known to work; the incantation to compile a user's main
302program main.c is:
303
304   gcc -o main main.c netgen.a
305
306
307The NETGEN package is initialized via a call to:
308
309   void Initialize();
310
311This procedure sets up the internal data structures, and pre-defines
312two types of cells:  n- and p-channel transistors.  These cells are
313declared by the following code (which is actually inside Initialize()):
314
315     CellDef("p");
316         Primitive();
317         PortDef("gate");
318         PortDef("drain");
319         PortDef("source");
320         EndCell();
321    CellDef("n");
322         Primitive();
323         PortDef("gate");
324         PortDef("drain");
325         PortDef("source");
326         EndCell();
327
328The procedure Primitive() in the above code fragment informs
329NETGEN that the element is a primitive, and not to be further
330decomposed when an output netlist file is written. This mechanism
331assumes that the system READING the netlist understands the
332meaning of the element.
333
334A slightly more powerful initialization routine is:
335
336   void InitializeCommandLine(int argc, char *argv[]);
337
338This routine parses any command-line arguements (interpreted as
339commands to the Query() routine), and processes them first.  A single
340'-' in the command line indicates that interactive operation should
341follow these commands.
342
343For the user's convenience, an alternative to the Instance/Connect
344mechanism is provided; when a cell is instantiated, explicit
345connections may be specified to each of its ports via the procedure:
346
347     void Cell(char *CellName, char *PortNameList, ...);
348
349The strings passed in PortNameList, and any subsequent (assumed char *)
350are of one of two forms:
351
3521) they are a list of "port=element" strings.  In this case, their
353order is unimportant; the ports of the cell are connected to the
354corresponding element.  For example,
355     Cell("n", "drain=n1", "gate=g1", "source=n2");
356does the obvious thing.
357
3582) arguements do not contain "=", but may contain wildcards, in which
359case they are expanded into lists, and this list is sealed with the
360port list obtained when CellName is instanced (and after any "=" ports
361are matched).  For example, an n-channel device in parallel with
362another (named "tran1") can be obtained by:
363     Cell("n", "tran1/*");
364
365In both of these cases, the portnames of CellName are also added to the
366namespace of the current cell, so subsequent calls to Connect()
367operate correctly.
368
369Along the lines of Cell(), two other procedures are defined:
370
371     void N(char *PortNameList, ...);
372     void P(char *PortNameList, ...);
373
374These are merely calls to Cell(), with the CellName arguement
375hard-wired to "n" and "p", respectively.
376
377A slight variant on Cell() is the Wire() procedure:
378
379     void Wire(char *instance_name, ...);
380
381This procedure accepts the name of an instance, and a list of ports
382identical to Cell().  The only difference is that for Wire(), the
383instance name is explicitly required, while for Cell() it is
384totally suppressed (in fact, the user cannot even find out what it was).
385The "=" form of the parameter list can be used in Wire() as well.
386
387Other Useful Functions
388
389Because many element names are derived from others, NETGEN
390provides some useful functions to manipulate temporary strings:
391
392     char *Str(char *format, ...);
393
394This function takes a format string and a variable arguement list
395in a manner identical to printf(), and returns a pointer to a
396temporary string.  There are only a small number of these (statically
397allocated) strings available, so you must use the pointer quickly.
398Typical use is in declaring a "subscripted" cell:  CellDef(Str("array%d", i));
399
400Finally, as a convenience to the user, a procedure:
401
402     void Query(void);
403
404puts NETGEN in an interactive mode, where the user is permitted
405to choose between output netlist formats, input files to read, and
406various other things.  It is a convenient way to end a program.
407
408If your version of NETGEN was compiled with X11 support, a more
409general command parser is available as:
410
411     void X_main_loop(int argc, char *argv[]);
412
413
414Generating Output
415
416The main output format currently supported is the Caltech NTK
417format.  An output file is created by calling:
418
419  void Ntk(char *cellname, char *filename);
420
421All nodes are named, with the following priority given to nodes
422with multiple elements connected to them.  Highest priority
423goes to port names, then to internal node names, and finally
424to instance pin names. Certain shortcomings in the .NTK specification
425(such as the inability to connect two ports within a cell) are
426dealt with correctly. If filename is NULL, or an empty string,
427a file name is generated by appending .ntk to "cellname".
428
429
430Late news flash:  the MAGIC hierarchical extract format
431is now supported to a limited.  To generate .EXT files, call
432
433  void Ext(char *cellname);
434
435This procedure generates a .EXT file for EACH(!) cell class.
436The only thing .EXT is good for is to run EXT2SIM on, in order to
437get the other MAGIC netlist format (flattened list of
438transistors only.).  SIM output can be generated directly by:
439
440  void Sim(char *cellname);
441
442NETGEN also supports the Actel(TM) cell libraries and netlist
443file format.  To access these cells, call the procedure:
444
445   void ActelLib();
446
447These cells are then regular NETGEN objects, whose elements
448are accessed by the names described in the Actel gate catalog.
449For example, the pins on a 2-input NAND gate are
450"thisgate/A", "thisgate/B", and "thisgate/Y", after a call
451to Instance("NAND2","thisgate").
452
453Actel .adl files are written by calling the procedure:
454
455   void Actel(char *cellname, char *filename);
456
457As before, if filename is NULL, or an empty string, a file name is
458generated by appending .adl to "cellname".
459
460NETGEN supports the netlist format required by
461the WOMBAT netlist comparison program.  Such files
462are written by the procedure:
463
464   void Wombat(char *cellname, char *filename);
465
466WOMBAT requires flat (non-hierarchical) netlists.  See the
467Flatten() procedure below.
468
469NETGEN also supports two popular circuit simulator formats:
470
471   void SpiceCell(char *cellname, char *filename);
472   void EsacapCell(char *cellname, char *filename);
473
474Of course, because NETGEN only maintains topological information and
475not device sizing information, writing circuit simulator input files
476generally requires some manual post-processing.
477
478NETGEN also supports an output format that is, in fact, the specification
479of the netlist using the NETGEN C-language embedded interface:
480
481   void Ccode(char *cellname, char *filename);
482
483This procedure creates a file that is suitable for inclusion and compilation
484within a program that, when linked with the netgen libraries, will
485re-create the netlist.
486
487Finally, NETGEN provides a machine-dependent (i.e., nonportable)
488but fast netlist format, based on a binary dump of its internal data
489structures:
490
491   void WriteNetgenFile(char *cellname, char *filename);
492
493
494Other Cell Manipulation commands
495
496  Two routines are also provided to manipulate the cell dictionary
497(the list of defined cells):
498
499    void CellDelete(char *cellname);
500
501This procedure deletes the definition of 'cellname' from the dictionary.
502It does NOT care whether instances of 'cellname' exist within other cells.
503This procedure is useful for remapping sub-cells within a design, by
504deleting the original cells, then subsequently loading in new definitions.
505
506    void CellRename(char *from, char *to);
507
508This procedure deletes the definition of cell 'from', and creates an
509identical cell in 'to'.  If cell 'to' already exists, that cell is overwritten.
510
511    void CellCopy(char *from, char *to);
512
513Copy cell 'from', calling the new cell 'to'.  If 'to' exists already,
514its definition is overwritten.
515
516NETGEN also supports some hierarchy-manipulation functions:
517
518   void Flatten(char *cellname);
519
520The Flatten() procedure actually flattens the internal data
521structure, and is consequently irreversible.  Of course,
522flattened cells can also be written out in any of the
523other netlist formats.
524
525   void FlattenInstancesOf(char *classname);
526
527This procedure flattens all instances of 'classname' within other
528cells.  However, any hierarchy within 'classname' remains.
529
530
531Alternative Input Formats
532
533  In addition to the embedded procedural interface for declaring/defining
534cells, NETGEN is able to read hierarchical .NTK files directly,
535and convert them into the internal element list representation.
536These cells can then be operated on identically to procedurally defined
537cells.  This process facilitates using a (separately generated, perhaps
538by a graphical schematic capture system) cell library, then using
539NETGEN as a composition tool.
540
541In fact, many different input netlist formats are supported:
542
543   char *ReadNtk(char *filename);
544   char *ReadExt(char *filename);
545   char *ReadSim(char *filename);
546   char *ReadSpice(char *filename);
547   char *ReadNetgenFile(char *filename);
548
549All of these procedures return the name of the top-level cell that
550was read.
551
552A general file-reading interface is provided by:
553
554   char *ReadNetlist(char *filename);
555
556This procedure selects one of the above netlist formats, based on
557the file extension of the 'filename' arguement.
558
559Testing graph isomorphism.
560
561NETGEN includes a fast, powerful probabilistic algorithm for
562verifying whether two netlists represent isomorphic graphs.
563The favored interface to this facility is the 'netcomp' program
564that is built along with the 'netgen' interface.  However, advanced
565users may need the additional functionality provided by the C-language
566interface:
567
568   void NETCOMP(void);
569
570This is a primitive command-line interpreter (similar to Query())
571that gives the user access to all the internal capabilities of netcomp.
572A simpler interface is given by:
573
574   int Compare(char *cell1, char *cell2);
575
576This procedure returns 1 if the two cells are isomorphic, and 0 otherwise.
577If you consider MOS transistor sources and drains to be equivalent
578(i.e., permutable), set the integer variable EquivalenceTransistors to 1.
579This is appropriate for extracted outputs of VLSI circuits, but (typically)
580not for asymmetrical circuit-simulator specifications.
581
582
583Command-line interface and X-windows interface.
584
585By default in UNIX, if the DISPLAY environment variable is set, netgen
586starts an X-window application.  Otherwise, a command-line interface
587is executed, running the function Query() described above.  In either case,
588any command-line arguements are passed through Query(); if the last
589command is a single dash ("-"), the regular command parser is started
590AFTER the command-line commands are executed.  Otherwise, netgen
591terminates.
592
593
594Future work:
595
596* 1) have ntk generate file of output
597* 2) capture wildcard query routine into library (returning a string, so
598        user can incorporate it into interactive programs).
599* 3) add "internal ports" to implement scoping rules for variable names.
600* 4) find out what output format WOMBAT requires and generate it.
6015) add simple operators to act on element lists: move, delete, reverse
602* 6) don't forget to mention Initialize() procedure
603* 7) discuss alternatives to Instance() (e.g. Cell(), and N(), P())
604* 8) ability to flatten cells
605* 9) learn to write ACTEL format
606* 10) more streamlined syntax for Global ports
607* 11) don't forget to mention Primitive() procedure.
608