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