cschem implementation - 2. Schematics data


{imp2:0} This chapter should try to define the "first-class" objects cschem handles. The list of these objects should be as small as possible and as orthogonal as possible. All extra features and mechanisms, like slotting, hierarchy, name mangling, etc. should be implemented on top of these features (usually by dealing with attributes). This is in accordance with {pol:1}, {pol:2}, {pol:4}, {pol:9}

{imp2:1} The model can be considered as a stack:

   |  output, e.g. netlist  |
      |  abstract model  |
   |    concrete   model    |
|      drawing  primitives     |
|      and data schematics     |

{imp2:2} The main objective should be to keep the abstract model as simple as possible, since most of the complex logics and methods and mechanisms will operate on this model.

{imp2:3} The concrete model can be more redundant, offering alternatives; the most common example is that a network can be realized drawing wire-segments, or drawing bus-segments or implying connections via attributes.

{imp2:4} The input for the concrete model can be even more elaborate; most notably the same concrete model elements can be created graphically or from data, manually or programatically.

{imp2:5} The final output is usually also a larger model that can be derived from the abstract model.

Abstract vs. concrete

{imp2:6} At the end, all that matters is the abstract model. Most plugins, export formats, checkers, etc. are interested in that. That's what really describes the actual circuit. We have concrete objects to provide an easier access for the user to manipulate the abstract model.

{imp2:7} Electronic example: in the abstract model the project needs a quad NAND gate (7400). One of the possible implementations in the concrete model:

{imp2:8} A much simpler example is when a single symbol instance of the concrete model becomes a single component in the abstract model. However, the above steps are all the same, except the 4 or 5 symbols are reduced to 1.

{imp2:9} The UI should present both the concrete and the abstract model. The user should be able to edit the objects of the concrete model and see the effect on the abstract model.

{imp2:10} Letting the user directly edit the abstract model is probably not practical: there are multiple ways the concrete model can be changed to cause the desired change in the abstract model. It is like if we wanted to fix a bug in the executable of a program and expect the debugger or compiler to go and fix the source code accordingly.

{imp2:11} Thus the UI should present the abstract model as read-only. But just like debuggers can assist the user to navigate to the source line(s) that contributed to a specific instruction or runtime situation, cschem UIs should be able to navigate the user to the source(s) in the concrete model that caused a specific effect in the abstract model. How the source references are stored in memory is up to the implementation, but when the model is saved/exported (e.g. to disk), it should use UIDs as specified.

{imp2:12} A common example is (abstract) networks. The user, looking at a PCB or simulation, wants to find the network named "Address6". This information is clearly interpreted in the scope of the abstract model, where there is a network with name "Address6" and a list of ports it connects (and a list of attributes). A search can be made to find all graphical connections, wire-nets, bus-nets, attribute connections and data that contributed to the final list of ports (and attributes) of the network.

{imp2:13} Note the terminology: the same terms are not reused in both the concrete and the abstract models, e.g. a symbol in the concrete model can become (or contribute to) a component in abstract model.

Core attributes

{imp2:14} A very few aspects of the abstract model are implemented through attributes. These attributes are used by the core implementation and are relied upon by all plugins. These attributes are called the core attributes.

{imp2:15} The number of core attributes shall be as small as possible as per {imp2:16}, {imp2:17}, {imp2:18} and {imp2:19}.

{imp2:20} Currently the core attributes are restricted to deal with:

Port implicit network vs. chan connection

{imp2:21} A port (or a channel of a bus-port) can be non-graphically connected to a network using the connect attribute. This always forms a connection (even at the cost of creating the given network).

{imp2:22} Another way is connecting the port graphically, using wire-nets in the concrete model.

{imp2:23} The two methods are orthogonal and can be used in parallel. If the same port is connected to two differently named networks, the usual network collision mechanism is used (will be discussed in a later chapter). If the port is connected to a named network via attribute and an unnamed wire-net, the wire-net automatically joins the named network (via the port).

{imp2:24} The third orthogonal idea is channels of a bus. A channel is really a network, which most often "stays within the scope of the bus", that is, won't have a connect attribute that would make it a globally known network. If a port is connected to a bus, the port's chan attribute determines which channel of the bus is connected.

{imp2:25} But this connection is again orthogonal to the above two. Which means a port can be connected to a network in multiple different ways:

Avoid attribute overloading

{imp2:26} A symbol has a name field for binding it to a component. This seems like redundant to refdes (also, gschem uses refdes for this purpose). The reason for this decision is that refdes is also the identifier printed on a PCB. In a complex hierarchic setup it makes more sense to use a shorter refdes generated from a longer name; the refdes can even be sequential.

{imp2:27} If cschem tried to use refdes for both, it would be sort of overloading the attribute with two different purposes:

{imp2:28} The alternative is to provide separate attributes for the two purposes: name for the logical identification, refdes for the physical. Granting that:

{imp2:29} The same considerations are followed when netname is derived from name in case of networks.

Proper bus support

{imp2:30} Buses are not pure graphical objects; cschem does understand what channels a bus has and does checks when anything is connected to a bus.

{imp2:31} Buses and bus-ports are first-class objects, which means they can be used the same way as networks:

UIDs vs. names

{imp2:32} While working on the back annotation for pcb-rnd -> gschem, I realized that using refdes for element identification is not reliable. Looking at prior art it turned out others struggled with the same problem (e.g. in the renumber plugin). The problem is: it's easy to communicate pin swaps and non-refdes-attribute changes, because we can address those by refdes:pinnum or refdes:attribname. But changing refdes (which should be just a plain attribute) is hard because it's also part of the addressing.

{imp2:33} In a gschem -> pcb-rnd flow this means if only the refdes attribute changes on the schematics e.g. from R15 to R21, pcb-rnd still preceives this as if R15 was removed and R21 was added. Not an attrib change, not a rename, but a full subcircuit removal and a new subcircuit added. The other way around is not easy either: when an subcircuit is renamed in pcb-rnd and needs to be back annotated: we have no other data to identify the subcircuits than its refdes, and the rest of the back annotation data pack also may depend on the refdes (e.g. for pin swaps in the same element).

{imp2:34} To fix this, cschem will have UIDs right from the start. Wherever possible in program-to-program communication, we will try to reference our objects by UIDs instead of names. Of course at the end the names are presented to the user, especially on the user interface, but the internal communication should be UID based. This makes it hard to change the UID of an existing object (which we don't want to do anyway) and makes it easy to change any other attribute, including the name of the object. This is an option; flows can decide to use any other identification from any other attribute specified by the user and/or generated by plugins

{imp2:35} Cschem will use the UIDs generated by libminuid.

{imp2:36} An abstract object is identified by its project-unique name attribute. The name attribute is (derived from) an attribute maintained by the user. This name may not be the same as the visible name on the output; for example in case of components the visible name on a PCB layout would be refdes attribute, in case of networks the PCB-visible name is the netname attribute while the unique name by which all systems identify the component or network is the name attribute. Refdes and netname can be derived automatically from name by plugins - the simplest method is copy.

data/programmed schematics sheets

{imp2:37} Opaque data sheets gives cschem an extra level of flexibility: later on in a hierarchic or multisheet design, parts of a bigger schematics can be specified in:

{imp2:38} Any of these will need a plugin that handles the given format. For plain text, CSV, TSV xml, json, binary data it's just a format parser that then passes on the data to the same code that would handle the extracted concrete objects of a graphical sheet.

{imp2:39} For any kind of script, including vhdl and verilog, the plugin would need to run an external process or depend on a lib to actually execute the source code (that is the data of the sheet) and convert the result into concrete objects which then would be handled the same way as above.

{imp2:40} Since the sheet is opaque for the GUI, cschem is not forced to reproduce hundreds of editors and compilers/interpreters. Since the actual compiler is a plugin, the user can easily add support for a new language/format.

{imp2:41} The difference between a data schematics sheet and an external converter program that would compile the input into a graphical schematics sheet is:

{imp2:42} The data/programmed schematics sheet is an alternative to external conversions. Both methods can be used in parallel, even within the same project, as long as the resulting abstract model is consistent.