XCircuit internal structures


Table of Contents

  1. Table of Contents
  2. Notes
  3. Introduction
  4. Overall Architecture
  5. Basic Structures
  6. EXAMPLE
  7. C-Language Routines and Macros
  8. EXAMPLE
  9. CIRCUIT EXAMPLE
  10. EXERCISES
  11. Internal Netlist Routines
  12. Parameters
  13. References

Notes

This text is intended to aid in the understanding of how XCircuit generates and maintains netlists.

Code citations reference XCircuit version 3.1, revision 6.

Introduction

XCircuit was originally written as a purely GUI (graphical user interface) application; that is, graphics routines (based on Xt) were embedded in the routines and no attempt was made to separate the manipulation of internal structures from the graphical display of those structures.

More recently, XCircuit has been redesigned to operate as an extention of Tcl (the interpreter language developed by John Ousterhout, largely originating in the source code of the magic VLSI layout editor program). Because Tcl has its own methods for building GUIs, large parts of XCircuit were rewritten so that the core of the XCircuit program is (almost) a purely command-line oriented application. The GUI is written in Tcl/Tk, and all menu and toolbar buttons generate calls to XCircuit functions through the command-line interface.

This text will reference the Tcl-based version of XCircuit (XCircuit is currently configurable either for the Tcl extension or the original Xt-based version, selectable at compile time). The main reason is to avoid having to deal with issues related to the GUI. However, it should not be necessary to have any knowledge of the Tcl language to understand this text. Any references made to Tcl commands or to the Tcl C-language interface will be fully explained. However, readers interested in a more in-depth understanding of the Tcl language are encouraged to look at the book Practical Programming in Tcl and Tk by Brent Welch (Prentice Hall; 3rd edition, 2000).

The original incentive behind developing XCircuit was the observation that drawing programs are not geared toward drawing schematics (for instance, they have a limited, if any, understanding of hierarchy). Schematic capture programs, on the other hand, tend to go to the other extreme, greatly restricting the style of drawings that can be produced, and generally creating visually poor output.

XCircuit operates on the belief that the onus is on the software to do all the hard work, and that even an application-specific program such as a schematic capture tool should leave the designer free to incorporate style, detail, and anything that the designer might require but which the software designer may not have anticipated.

However, this principle of operation necessitates a rather complicated design of the component and netlist internal structures, and the procedures that generate the netlist.

Types of elements

A summary of the syntax for all element types in the PostScript output file can be found here: XCircuit PostScript reference.

Selection of elements

Color Allocation and Color Inheritance

Memory buffers and their use

Overall Architecture

Understanding the fundamental architecture of XCircuit requires a good understanding of hierarchy and how it is used in circuit schematics. All schematic drawings make use of symbols. A symbol is a representation of some kind of circuit structure. For the purpose of schematic capture, they must represent some physical structure, a specific element or group of elements. For the purpose of visualizing and understanding a circuit, a symbol may not represent any specific structure. A NAND gate, for example, is a commonly used logic symbol for digital circuits. In a VLSI schematic used for schematic capture, it may represent a specific circuit made up of four transistors. But in an FPGA (field-programmable gate array) schematic, it may represent a set of bits used to configure a generic logic block somewhere in a large array, such as an Altera or Xilinx chip. In a PCB (printed circuit board) schematic, it may represent one of four gates available on a 74HCT00 CMOS chip. If the purpose of the schematic is visualization of some digital system, it may represent only the ideal Boolean logic function NOT-AND. A schematic capture program needs to handle all of these situations. Preferably, it should do so with exactly one symbol NAND which allows one schematic drawing to be used for implementing a system in VLSI, on an FPGA, on a printed circuit board, or including the schematic as a figure in an article or book.

XCircuit has two ways of looking at a drawing. Its overall understanding of the structure of a drawing is based on pages, objects, elements, and instances (see the section Basic Structures, below). Its understanding of the netlist of a circuit is based on symbols and schematics (see the section Netlist Structures, below).

Basic Structures

The core structure containing most of the information about a drawing is the object. The object is the structure which contains the list of all drawn elements (lines, text, etc.). The object has its own coordinate system, and the position of each of its elements is specified relative to that local frame of reference. However, when an object is drawn, it is always drawn relative to another frame of reference. For instance, when the library page is shown, each library object will be displayed in some position relative to the library page's frame of reference. When editing the object, however, it will be drawn in the (X11) window's (pixel-based) frame of reference. Due to the presence of the page and library directory, every object (including each top-level page) can be drawn in multiple frames of reference. So every object is referenced by one or more instances. An object instance is one of the six basic XCircuit elements: polygon, label, arc, spline, and path are the other five element types. For the purpose of understanding how XCircuit represents circuit netlists, the types arc, spline, and path will be ignored, as they are principally for drawing and do not represent any part of a circuit netlist.

Object instances are used in many situations in XCircuit where other elements are not. Every page has an object instance which keeps information regarding the zoom and pan (scale and translation) of the object within the X11 window. The libraries, library directory, and page directory all have instances. Because text in XCircuit is drawn with vectors, every letter in the alphabet is an object and so the table of characters (type backslash ('\') while entering or editing text) is another object instance.

Since object instances "contain" objects, and since objects contain lists of drawable elements, and since an object instance is one of those drawable element types, hierarchy is a direct consequence of the data structure. In typical nomenclature for hierarchical systems, it is proper to refer to an object as a "parent" or "ancestor" of another object, or a "child" or "descendent" of another object. It is only necessary to ensure that no object contain an instance of an object that is an ancestor of itself, which would precipitate an infinite recursion if XCircuit attempted to draw such a structure.

The polygon element is self-explanatory, although it should be noted that for the purpose of schematic capture, only unclosed, unfilled polygons (that is, a set of connected lines) are considered to be valid netlist elements. Due to this distinction, closed or filled polygons can be used to box or highlight portions of a circuit and will not affect the resulting netlist.

The remaining netlist element is the label. Labels come in four flavors: plain text, local pins, global pins, and schematic informational labels (otherwise known as info labels). Plain text labels are not considered to be valid netlist elements, and are ignored by the schematic capture system. They may be used to annotate a schematic and will not affect the resulting netlist. The remaining label types are treated differently by the schematic capture routines, as described below. The label structure contains a pointer to a type "stringpart", which is a linked list that allows a label to represent much more than simple text, as the stringpart structure contains a union of data types which can represent font, color, scale, and position changes, and text parameters (text which can be changed on a per-instance basis; more about parameters later). This presents one difficulty for schematic capture, which is that XCircuit's way of representing text is more flexible than the average netlist format, which only handles ASCII strings.

Two other fundamental structures in XCircuit require mentioning, although they are not directly related to netlists: Pages and libraries. The page structure maintains information necessary for formatted output, such as page size, orientation, scaling, and so forth. It also contains a pointer to the object instance which defines the position and scale of the page within the X11 window (the output page frame of reference and the window frame of reference are by necessity unrelated).

A library is a grouping of objects which are not top-level page objects. The library primarily serves the purpose of being a convenient way to "grab" an object (i.e., make a new instance of an object) and to group circuit elements according to function. It also serves a purpose internally as the definitive location of objects when doing an object search. When an object instance is deleted from a page, the object itself (or rather a pointer to it) remains in the library structure. When an object instance is deleted from the library page, the object itself is deleted (which necessitates the rule that no object can be removed from a library while instances of that object exist outside the library page).

EXAMPLE

Figure 1 is an example of a typical XCircuit data structure. At the highest level is the Clientdata structure "areastruct" containing information about the current status of whatever object is currently in the main drawing window. In particular, it contains a pointer (areastruct.topinstance) to the instance structure of the object currently in the main window (note the common use of "topobject" in the source code, which is a macro definition for areastruct.topinstance->thisobject). It also contains the default values for color, style, font, etc., used when creating a new element in the main window.

Also at the highest level is the Globaldata structure "xobjs". Technically, the difference between Clientdata and Globaldata is that when multiple drawing windows are present, each window gets a unique Clientdata structure, whereas one Globaldata structure suffices for the entire application. However, as the capability for multiple drawing windows has never been coded into XCircuit, this distinction is largely meaningless. The items in Globaldata should never be repeated and are only collected in a structure for the convenience of including them in different parts of the source code. In particular, the Globaldata structure contains the list of pages (Pagedata **pagelist), the list of libraries (Library *userlibs), and the list of object instances representing the formatted library pages (objinstptr *libtop). The object hierarchy of a circuit descends from the page list. Note that it does not descend from the library list, as the library contains objects which may not have been used in a given circuit. Objects in the libraries are inserted into the circuit hierarchy via object instances. In Figure 1, library object "Object 1" is a direct descendant of page "Page 1", via "Element 3", which is an object instance. Library objects "Object 2" and "Object 3" are unused. Note that page objects are never found in the library tree (i.e., no paths lead from the library list to a page object). The only path to a page object is directly from the page list, with exactly one object per page structure.

A note about the C-language structures: Heavy use is made of "typedef" to define new data types. The use of the suffix "ptr" on a type name is equivalent to " *"; e.g., "objectptr" is equivalent to "object *". However, this nomenclature is not universally applied. Generally speaking, it is used mostly to avoid overuse of "**" in lists of pointers, such as the element list "genericptr *plist" in an object structure.

More typedef quirks: A couple of structures look like they belong elsewhere. "XfPoint" and "XlPoint" mimic the structure of "XPoint" (defined in the X11 header files), but are defined in "xcircuit.h".

Some preprocessor quirks: A couple of subroutine names are formed by #define statements, although this method is not widely used because it tends to be confusing. To make this clearer, the real C routines are prefixed with "gen" (for "generic"):

C-Language Routines and Macros (for valid netlist elements)

(void) NEW_POLY (polyptr *newpoly, objectptr thisobj)
(a macro) creates a new polygon in object thisobj.
(void) polydefaults (polyptr newpoly, int num_points, int x, int y)
(a subroutine) allocates memory for the list of points in the polygon structure, and sets all points to the same position (x, y). Non-default values, such as individual point positions, should be set immediately after calling polydefaults().
(void) NEW_LABEL (labelptr *newlabel, objectptr thisobj)
(a macro) creates a new label in object thisobj.
(void) labeldefaults (labelptr newlabel, int pin_type, int x, int y)
(a subroutine) allocates memory for the stringpart structure "string" in the label object. The string is initialized with a single part declaring the font, and no text. The label is positioned at (x, y), and its type is set to "pin_type", which may be NORMAL, LOCAL, GLOBAL, or INFO.
(void) NEW_OBJINST(objinstptr *newinst, objectptr thisobj)
(a macro) creates a new object instance in object thisobj.
(void) objectdefaults(objinstptr newinst, objectptr refobj, int x, int y);
(a subroutine) positions the instance at (x, y) and declares the element to be an instance of object refobj.
(objectptr) NameToObject(char *name, objinstptr *libinst_return)
Searches the library for an object with name name. It returns a pointer to the actual object, but also a pointer to the library instance, which is useful for copying the parameter values of library "virtual instances" into a new object instance element.
(void) instcopy(objinstptr newinst, objinstptr oldinst)
Copies all values from instance element oldinst into the instance element newinst. This includes making a copy of all parameter values.
(void) newpage(int page_num)
Switches to page page_num. If page_num does not exist, it is created, and all its properties are initialized.

Netlist Generation

There are several ways to design the internal structure of a circuit netlist in a schematic drawing program such as XCircuit. One is to assume no knowledge of the netlist during drawing, but generate a new netlist every time one is required. This works well for programs where the only useful netlist function is to generate output, and is the easiest method to code.

At the other extreme, every element drawn, moved, reconfigured, or deleted retains all information about its own part in the netlist. It is very convenient to have the netlist set up this way. However, for a flexible schematic capture system like XCircuit, a single change can precipitate a host of changes up and down the schematic hierarchy, which adds noticeable delay to simple tasks such as deleting or editing a line segment in a net.

XCircuit implements a method halfway between these two extremes. Initially, no netlist for a circuit is generated until required. After a netlist has been created, however, all the structures remain in memory (these structures are part of the object definition; see below). When an element which is a valid netlist element (excluding arcs, splines, paths, closed or filled polygons, and plain text labels) is created, moved, edited, or destroyed, the netlist for the object is marked "invalid". The next time a circuit netlist is required, the circuit hierarchy will be checked for invalid netlists, and any netlists which have been marked invalid will be regenerated, then marked "valid".

The internal netlist structure in XCircuit is always hierarchical. That is, for any object with an invalidated netlist, the netlists for all of its ancestors are invalid, but the netlists for all of its descendants remain valid unless otherwise marked. Flattened netlist formats (such as ".sim" files, but also netlist names as reported by the network-highlighting subroutine) are always computed on-the-fly. Only the parts of the network of interest will be flattened.

There is a difference between an "object hierarchy" as described in the Circuit Structures section and a "circuit hierarchy" as described above. In an "object hierarchy" (or equivalently, "page hierarchy"), the only path to an object is from an instance of itself. An equivalent way of saying this is that every descendent of a page object can be viewed on the page, since each object instance draws the object it points to. In a "circuit hierarchy", however, paths may descend from an object instance to another page object, linking together multiple page hierarchies. In terms of circuit function, what this means is that the object instance is a circuit symbol. The symbol points to two different objects: One is the library object, which is the object that is drawn when the page is displayed in the window. The other is a page object, and represents the schematic which is associated with the symbol. It is of course another case of infinite recursion for that symbol to be a descendent of its own associated schematic. However, the case is not disallowed, because it is standard practice to draw an example of a symbol on the schematic page, as a visual reference but not as a circuit element. Consequently, any symbol which is encountered in its own associated schematic is ignored by the netlist generator.

The only way that XCircuit can follow a network between a symbol and its schematic is through ports. XCircuit's implementation of ports is about as flexible as possible to realize. In XCircuit, there is no difference between a "pin" (pin label) and a "port" from the perspective of the end-user (circuit designer). Any pin label which exists on both a symbol and its associated schematic will be treated as a port by the netlist generator. This implementation does not preclude the existance of pins on a symbol which have no counterpart in the schematic (nets attaching to such a pin are simply not connected into the schematic), nor does it preclude the existance of pins on the schematic which have no counterpart in the symbol (such pins can be used, for instance, to assign names to nets or to logically merge parts of a single network which are not physically connected in the drawing.

It is not even necessary for the circuit designer to designate a particular object as a schematic or a symbol. XCircuit determines the use of each object from context. For instance, page objects can be schematics but not symbols. Library objects can be either symbols or schematics. They are assumed to be schematics except under three conditions:

  1. the object is associated with a page,
  2. the object contains an "info label" which precludes any netlist by describing exactly how the object netlist output should be formatted, and
  3. the object contains no instances of objects with netlists.
In the first case, the object is considered to be a "normal symbol". In the second case, the object is considered to be a "fundamental symbol". In the third case, the object is considered to be a "trivial symbol". All symbol types contain a minimal netlist, which contains a list of the pins on the symbol (see the "Netlist Structures" section, below), and is used for constructing ports and for certain simple netlist manipulations. A "trivial" symbol, while not associated with any schematic and not capable of producing any netlist output itself, is nevertheless capable of altering the netlist of its ancestors. This feature is used in the dot and circle objects. The circle symbol, which is typically used to show signals which connect to somewhere outside of the schematic page (i.e., ports and global networks) has two pins with the same name ("out" and "out"). When a circle symbol is placed on a schematic drawing, a wire connected to one "out" port, and a label connected to the other, the network represented by the wire takes the name of the label text. The dot symbol has only one pin ("x"). But because this pin is the port into the symbol, it automatically attaches to any wire passing through the point. Normally, wires that cross in the center are not considered "connected," following the normal convention of schematics which don't use "jumpers" at line crossings not intended to indicate a connection. But when a dot symbol is placed over a wire crossing, both wires are considered to be connected to the port, so their networks are merged. This method allows XCircuit to handle dots, jumpers, I/O tags, and similar things in a general manner, without coding any "exceptional" cases.

The vdd and gnd symbols show that a pin can even be a global network on the symbol. Networks connecting to the vdd and gnd symbols are automatically merged with the global "Vdd" and "GND" nets. These symbols have no other relevant netlist elements and so are "trivial" elements. Note that global networks may be defined anywhere in the circuit hierarchy. The presence of a single gnd symbol anywhere in a circuit makes the "GND" network available everywhere in the circuit.

Netlist Structures

All of the netlist structures in XCircuit are linked lists. That is, there is one pointer to the top of the linked list, and each list structure contains two parts, one for data store, and one which is a pointer to the next structure in the list.

XCircuit produces three main linked list structures to represent the netlist of each object. These are the netlist, the portlist, and the calllist. The netlist contains one structure for each unique net found. The data in each net structure are

  1. a unique index for the network,
  2. a linked list of all label elements connected to the network, and
  3. a linked list of all polygon elements connected to the network.
If any element is discovered to join two networks which have previously been marked as separate, the label and polygon lists of one network are appended to the label and polygon lists of the other, and the index of the (now empty) netlist structure is set to zero. It is subsequently ignored, and finally removed by the mergecleanup() routine.

The portlist and calllist are generated simultaneously. The portlist contains a list of all ports in the object to which networks in the objects ancestors may connect networks to the object. The calllist, on the other hand, is a list of connections that the object makes to its descendents. Each linked structure in the call list keeps three data:

  1. the schematic (object) to which networks in the object attach,
  2. the symbol (object instance) to which networks in the object attach, and
  3. a linked port list enumerating each port in the child and the network index which attaches to that port.
The called (child) object should have a port list to match that in the calling (parent) object, but containing network indexes as they are numbered in the child object. When generating netlist output, the two port lists are matched by matching the port numbers. For hierarchical netlist output, such as SPICE, each subcircuit definition lists ports in order and each call lists ports in order. In flattened netlist output, each network is traced from parent to child through the port list. It is important to note that the port list in the parent may be shorter than the port list in the child, and any mismatch must be resolved when writing an output like SPICE which requires the port list of parent and child to match exactly. The reason that they do not necessarily match is that the netlist generator only creates ports in a child object where some network in the parent object has been found to attach to it. If some circuit connects to only five pins of a six-pin symbol, only five ports will be generated in both the symbol and the schematic which attached to it. If later during the netlist generation, the symbol appears somewhere else with the schematic attaching to all six pins, a sixth port will be added to the symbol's schematic object. The first call to the symbol object, however, will not be updated and so will continue to have only five ports in the call. When writing SPICE output, the output routine will note the undeclared port and generate a unique, unused node name in the parent circuit.

The astute reader may realize that the automatic generation of ports implies that (unlike all other schematic capture programs that I am aware of) there is no way to explicitly declare a port in XCircuit. The presence of a pin on a symbol "probably" indicates a port, but this may not be true if 1) no pin of that name exists on the associated schematic, or 2) no network in any circuit connects to that pin.

A child object does not have to be a symbol. It can be a schematic; any time a group of elements needs to be repeated, the group may be made into an object (select the elements and type the "M" key macro to collect them into a new user library object). When the child object is a schematic instead of a symbol, the use of pins as ports is optional, as network connections into the sub-schematic will be "discovered" during netlist generation.

Trivial symbols are always removed from call lists after any effect on the parent schematic has been taken into account. In the netlist structure of a schematic drawing using the "circle" or "dot" library objects, there will be no calls to either object in the call list. Because they are trivial objects, they do not appear in any netlist output, so there is no reason to incur extra effort in producing the netlist output by keeping them in the call list.

EXAMPLE

Figure 2 is a block-diagram picture representing most of the netlist structures used by XCircuit. The lightly shaded areas represent the circuit description prior to generating a netlist. The darker shaded areas contain all the structures which are created during netlist generation. In the top corner is the netlist of globally-named networks. The global network netlist contains no list of polygons (wires) because it is not associated with any specific schematic and only lists global network names and any aliases for those names.

The diagram also shows a temp label, the only label structure that appears in the set of structures created during netlist generation.

It is fairly easy to see from the figure how structures in the netlist of a schematic refer back to actual elements (labels, polygons, and object instances) in the object. The call list, on the other hand, shows, for a particular call, how the instance record of the call points to an instance element (symbol) in the object, but the object record does not point to the object record of the instance. Instead, it points to another top-level page, which is the schematic associated with the symbol.

CIRCUIT EXAMPLE

The file "sr_ff.ps" is a simple circuit which exemplifies many of the points discussed above. The file contains three pages. The first is the top-level circuit schematic, called "sr_ff_use". This page has one instance of a flip-flop, shown as a symbol, connected to meaningful top-level signals named "Set", "Reset", and "Out". Note that the inverted output is not labeled and connects to no nets on the top-level schematic. The second page is the flip-flop circuit itself, the traditional feedback- connected pair of two-input NOR gates (a circuit which is virtually never used in practice, but that's an unrelated issue). The schematic uses the traditional pin designations "S", "R", "Q", and "!Q" (overline-Q). Here's an interesting aspect of netlist generation: The netlist output is incapable of producing an overline on the Q. So the output produces the standard notation "!Q" to represent overline-Q (derived from the use of "!" in boolean logic to represent the NOT function). In this case, the netlist comparator cannot ignore the "overline" directive in a stringpart structure when comparing two pin names. Another common instance is the use of Greek (Symbol font) letters, especially "mu", which is used for metric unit notation and usually must be converted to "u" or "U" in the netlist output (which is made more complicated by the fact that the ISO character set contains the character "mu" for exactly this purpose, so the netlist generator must look for both cases, and the pin name comparison function must consider them to be equivalent!).

The third page is a VLSI implementation of the NOR gate, using four transistors. This shows how a schematic can contain non- netlist elements, since the page contains text annotation (title, subtitles, and a logic table), and even contains the apparently recursive inclusion of its own symbol (as mentioned above, the recursion is avoided by treating the symbol instances as a non-netlist element).

File "sr_ff_use.spc" is generated by selecting menu option "Netlist->Write SPICE" while the first page is in the XCircuit window. This SPICE deck contains one subcircuit for the NOR gate, one subcircuit for the flip-flop which calls two instances of the NOR gate, and a top-level circuit which makes a call to a single instance of the flip-flop.

The file "netlist.out" is produced by the Tcl command "netlist make" and produces a raw output which is very close to the internal data structure of the XCircuit netlist. It is intended in the future that all formatted output will be generated from this format via Tcl scripts, so that alternate netlist formats and variants of existing formats (hspice vs. spice3, for instance) can be designed without requiring changes to XCircuit's internal C routines. Tcl produces a huge nested list. However, once formatted with indentation, it is quite readable and can be understood without knowing any particular details of Tcl syntax.

File "sr_ff2.ps" is a slightly more complicated version, showing the use of subcircuits which don't have any associated symbols and which don't declare any ports. The flip-flop schematic makes use of the symmetry of the circuit. An object has been made using one NOR gate and some wires. This object is copied and flipped to form the symmetric other half of the circuit, and the pin labels complete the schematic. The SPICE output (see "sr_ff2_use.spc") for this circuit contains an extra subcircuit for the "half_ff" schematic, but otherwise is logically equivalent to "sr_ff_use.spc" (it is left as an exercise for the reader to confirm this equivalence). File "netlist2.out" is the raw output of the Tcl command "netlist make" (formatted for readability). Note the difference between this output and that of "netlist.out".

Note that if the dot symbols are removed from the half_ff object, XCircuit will extract an incorrect netlist, which is a bug in the netlist generation routine. This underscores the difficulty in attempting to automatically determine where ports are in a subschematic. The presence of the dot (a pin label in this position instead of a dot object will also suffice) effectively forces a port to exist at the location.

EXERCISES

  1. Generate flattened SPICE (Netlist->Flattened SPICE) for each of the two circuits and compare them.
  2. Generate a PCB netlist for the device, assuming that the circuit should use two gates on a 7402 chip. Here's the general idea:
    1. The transistor-level schematic should be removed from the file by going to page 3, selecting File->Write XCircuit PS, then clicking on the button beside the message "3 pages" at the top of the dialog window. Clicking on "Cancel" will pop down the dialog without any file writes.
    2. Delete the nor objects from the gate-level schematic of the flip-flop. Replace them with objects quadnor from the "quadparts" library. Use one 7402-1 instance and one 7402-2 instance.
    3. Generate output (Netlist->Write PCB) from the first page.
    4. Examine the output ("sr_ff_use.pcbnet", if the page label has not been changed on Page 1). The output does not take into account the Vdd and GND connections on the 7402 chip, nor does it automatically insert the two unused devices.
  3. Look at the PostScript description of the drawing in the files "sr_ff.ps" and "sr_ff2.ps". Note how the PostScript definitions (/name { body } def) match the structure of library objects in Figure 1. Library objects are always formed by PostScript definitions. Top-level pages are delineated by "%%Page:" markers (which are actually comment lines in the PostScript language but are interpreted by PostScript page-formatting and display programs like GhostScript). A complete description of the PostScript output format can be found on the XCircuit

Internal Netlist Routines

void gennet(char *mode, char *suffix)
  1. Generates a netlist for all objects with nonexisting or invalid netlists
  2. Writes output in the format indicated by mode (spice, sim, pcb) and with a filename suffix of suffix.
void destroynets()
void createnets()
These routines generate and destroy all the netlist information for a circuit schematic, starting with the object currently in the window as the "top-level" schematic. Because of the netlist validation method, these are only called after finding an invalid netlist in an object.
int porttonet(objectptr cschem, int portno)
Converts port number portno in (schematic) object cschem to a corresponding net index. Returns the net index, or zero if no network in cschem connects to the port.
int pointtonet(objectptr cschem, XPoint *testpoint)
Finds a network in object cschem which is on (or near the point, where "near" is defined by the ad-hoc constant ONDIST as 4 internal units. This definition of "near" ensures that if two wires of standard thickness appear to be touching in the display, they will be connected in the netlist. This helps with situations such as objects rotated at 45-degree intervals, where the endpoints do not lie on the snap grid. Returns the net index, or zero if no netlist objects are found at the location of testpoint.
stringpart *nettopin(int netid, objectptr cschem, char *prefix)
Given a net index netid, returns the name (in the XCircuit label format, the linked list "stringpart") of the network netid in object cschem. Because all pins connecting to a network are recorded, there is a procedure for determining which pin name is "definitive" for the network: Global net names always take precedence, followed by names which have been explicity declared by attaching pin labels to a network. Then, local (temp label) names are used. If there are no pin labels attached to the network (netlist->labels == NULL), then a "temp label" is generated. A "temp label" does not appear in an object's list of elements, only in the netlist. It is uniquely defined by the fact that, unlike all other label elements, it does not begin with a font designator (because the label is never drawn, it does not need to declare a font). The stringpart pointed to by the return pointer will be destroyed along with the temp label on the next call to destroynets().
int pintonet(objectptr cschem, objinstptr cinst, labelptr testpin)
Given a pointer to a label structure testpin, returns the net index of the net to which any pin having the same string as testpin is connected (note that this is not the same as searching for a unique label structure attached to a network). String comparison for pins is not rigorous, and essentially ignores embedded font, color, subscripting and superscripting directives, etc., only comparing the text parts of two labels. However, parameter substitutions are considered part of the label text, so it is necessary to pass the object instance cinst so that the correct parameter substitutions will be made.
int nametonet(objectptr cschem, objinstptr cinst, char *netname)
This is similar to routine pintonet() but allows a simple (char *) string to be compared against pin label names in object cschem.
int globalmax()
Global networks in XCircuit are designated by negative numbers. globalmax() returns the largest (negative) index of entries in the list of global networks. Negating the return value yields the total number of global networks in the circuit.
int netmax(objectptr cschem)
Returns the largest index of any network in object cschem.

Parameters

Parameters are one of the trickiest parts of the XCircuit to understand, both in terms of the user interface and in terms of the underlying code. However, the method provides a general way to assign properties to specific instances of objects, which is crucial to proper schematic capture. Schematic symbols use parameters to represent properties such as width and length on transistors (for VLSI schematics), part numbers for PCB schematics, or values for resistors and capacitors. Because the method is general, there is no restriction on the type or number of parameters an object may declare.

There are two types of parameters which are handled in different ways, internally. The most common type of parameter is the substring parameter, in which all or part of a text label is "parameterized". In terms of the XCircuit internal structure, when a label substring is selected to be parameterized, the following actions take place: First, any stringpart containing text which crosses the parameter boundary is split into two pieces, so that the part of the text which is to be parameterized is self-contained in one or more linked stringpart structures. The substring is removed from the label and replaced with a single stringpart structure declaring a type "parameter start" and containing an assigned parameter number as its data. The excised substring has a stringpart structure of type "parameter end" appended to it. A new parameter structure (oparam) is appended to the parameter list of the object, and the substring is moved to the "parameter.string" record of the oparam structure.

The "oparam" structure in the parameter list ("params") of the object represents the default value of the parameter. For any instance of the object that does not declare a value for that parameter number, the default value will be used.

Label parameter substitutions always occur "on the fly". Because of this, all calls to functions manipulating labels require knowing the instance of an object, so that proper parameter substitutions can be made. By manipulating pointers in the label string's linked list structure, a parameter substring is inserted into the linked list when the "parameter start" record is encountered, and removed when the "parameter end" record is encountered.

The parameterization method is flexible enough that it allows pins to be parameterized. So a pin can have one name in one instance of an object and a different name in another instance of the same object. The primary use for parameterized pins is to denote pin numbers on different gates in an integrated circuit for the purpose of writing PCB netlists. For instance, a 74HCT00 chip has four NAND gates. The "quadparts" library in the XCircuit distribution declares four instances of part "quadnand", each representing one of the NAND gates available on the chip. Because the pin names on the gate are the pin numbers on the chip, they are necessarily different for each of the four parts. But only one "quadnand" object exists for all four gates, so it is not necessary to create a different object for each gate on the chip.

The other type of parameter is a numerical parameter. Numerical parameters may be used to let elements in an object have unique values for rotation, position, scale, etc., in each instance of the object. For the purpose of understanding netlists, it is not really necessary to understand numerical parameters. In general, parameterization of object instance scales and polygon and label point positions is highly undesirable for netlists, as it is extremely difficult to deal with a hierarchical netlist description of an object whose networks wander from place to place on a per-instance basis (it is not impossible to deal with parameterized point positions; the method to deal with them is to consider any element with parameterized point position to belong to the parent of the object when generating the netlist. However, this method has never been incorporated into XCircuit). The only existing use of numerical parameters in XCircuit objects is for non-network elements such as plain text labels; for example, the elements in the "analoglib2" library, which display component values, parameterize the rotation and justification of the component value text, so the text can always be displayed upright even when the object instance is rotated.

References

http://xcircuit.ece.jhu.edu/
XCircuit website home page
http://xcircuit.ece.jhu.edu/download.html
XCircuit source distribution
http://xcircuit.ece.jhu.edu/postscript.html
Description of PostScript output
http://xcircuit.ece.jhu.edu/tcl.html
Description of the Tcl command-line interface
http://xcircuit.ece.jhu.edu/tutorial/tutorial.html
Basic XCircuit drawing tutorial
http://xcircuit.ece.jhu.edu/tutorial/tutorial2.html
Circuit drawing and schematic capture tutorial

Last updated: September 2, 2006 at 3:09pm