← Back to team overview

kicad-developers team mailing list archive

thoughts on hierarchical schematics


Dear list,

some has probably already been discussed here. I'm diving a bit further
into hierarchical schematics at present. I'm trying to creating "module"
schematics that are version controlled in Git, only schematics at this
moment, and I'm missing some things that would be nice to have in that
area. Currently also some behaviour of Kicad is a bit counter intuitive
at that point with regard to where stuff is stored in the files.

The attached file contains some thoughts on this from a user
perspective. Basically some use cases that, I hope, become possible in
the future... (no, not expecting this in 6 or even 7, but some day...)

Any comments are welcome, also on how to formulate this such that it
could become points on the roadmap?

Best regards,

Tjeerd Pinkert
RFC: Hierarchical schematics in Kicad - Thoughts on how it could be...

license: CC BY-SA 4.0

Copyright (add name when editing/extending):
Tjeerd J. Pinkert, 2019
     contact: <t.j.pinkert <AT> alumnus.utwente.nl>

This document may be used as a starting point for further thinking about this
subject from the Kicad users perspective. It is by no means a complete
analysis nor are the use cases mentioned complete. I hope this document will
be picked up and modified / extended with more use cases and that the Kicad
development community may be inspired by it.

This document sketches an imaginative way how Kicad could work with a highly
structured electronics design project where reuseable parts of the project are
developed as modules. The first focus lies on schematic capture as this is the
first part of Kicad where problems were encountered. Later other parts of the
Kicad suite may be added.

With a structured project comes version control. Git is being taken as the
tool of choise for the examples, as many are familiar with it. Each module is
assumed to be version managed in a Git repository and included as a submodule
in a larger project.

Another topic coming up in highly structured design might be flexibility in
configuration of components in the schematic. This might go as far as not
assigning component properties, values or numbering at module level. Treating
components with fully abstract parameter lists  might be a usefull treat when
designing schematics for e.g. (analogue) ASICS.

In order to structure these thoughts, first the current behaviour of Kicad as
it is encountered is described. Then the ideas about how an electronics
project could be structured are described. From these ideas will then follow
what features Kicad should have to handle the use cases sketched in this
document. As last part the technical implementation details of the proposed
features could be treated.

Current situation
At present (and in version 5.0.x used by the author) the schematic capture
tool EEschema allows the reuse of schematics as hierarchical sheets. Such a
schematic can be included multiple times into a larger structure. However, a
means to dynamically adjust e.g. the values in such sheets in not foreseen.

Also the tooling seems not to foresee that hierarchical sheets are kept as a
schematics modules separated from the overarching schematic. This has e.g. the
consequence that when opening an overarching schematic, non-matching
structures such as the project library references are updated in the lower
level file. The same is the case with annotation. This is not saved at the
top level module files where annotation is done, but in the lowest level
files, where several parameter values end up with unique identifier paths.

An issue that might or might not belong to this topic is the abstraction of
components. At current a footprint is assigned at the schematic level already.
This can be a good feature, since the designer might have a specific
technology, THT or SMD with certain standard components or sizes, in mind when
starting the design. However, already including the footprints at this level
might be restricting. E.g. ASIC design does not need footprints at all but
might need other hints to implement a resistor, like the amount of power that
is going to be dissipated in it.

The navigation features are sufficient for normal use. Naming might be
slightly strange. The same schematic sheet is referenced in the schematic
symbol as Sheet: <sheet_name> where the names are different for each
implementation of the circuit on the sheet referenced by <file_name>. An
instance of a circuit could be named Instance: <instance_name>, with
additional information e.g. the circuit title, date and revision from the
referenced sheet under <file_name>.

How a structured development project could look
Lets take an at first sight somewhat simple example to explore a large
development project with multiple layers of abstraction. Imagine a filter
toolkit consisting of modules for a T and PI type LC low pass filters and LC
high pass filters. A Git module for each filter type is created:
  - lc_lpf_t
  - lc_lpf_pi
  - lc_hpf_t
  - lc_hpf_pi
each of these modules can then be used as modules in a larger project e.g. to
create bandpass filters. Let's first concatenate some of the lpf modules to a
higher order low pass filter. At the module level this could look like this:

 |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01

where the construct <sheet_name> --> <file_name> indicates the file the sheet
which points to a certain file.

In the project directory and file structure it could look like:

 |- lc_lpf_9th_order.sch
 |- lc_lpf_t\@commit_01
 |   \- lc_lpf_t.sch
 \- lc_lpf_pi\@commit_02
     \- lc_lpf_pi.sch

where the directories lc_lpf_t and lc_lpf_pi are git submodules of the
lc_lpf_9th_order\ git module.

If it is the goal to implement a specific 9th order Butterworth filter, the L
and C values need to be adjusted not on the lc_lpf_t/pi level but on the
overarching lc_lpf_9th_order level. However if this generic structure is used
as template for the higher order filter used several times in a larger project
the values might need assignment at that level. This means that we would get
either a structured component list, or a flat component list. This could look

 |- lc_lpf_9th_order1 --> lc_lpf_9th_order.sch@commit_02
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_9th_order2 --> lc_lpf_9th_order.sch@commit_02
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_9th_order3 --> lc_lpf_9th_order.sch@commit_02
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_9th_order4 --> lc_lpf_9th_order.sch@commit_02
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01

and in the directory and file structure:

 |- the_product.sch
 |- lc_lpf_9th_order\@commit_02
 |   |- lc_lpf_9th_order.sch
 |   |- lc_lpf_t\@commit_01
 |   |   \- lc_lpf_t.sch
 |   |- lc_lpf_pi\@commit_02
 |   |   \- lc_lpf_pi.sch
 :   :

Where each 9th order filter might need it's own parameter set. But is might
get nastier. If a simulation needs to be done to check the functionality at
the t, pi and 9th order level, schematics need annotation and values for the
simulation, but not for inclusion in the_product. This might be the case if
the schematics are used for a chip design, where a generic opamp design might
be included at various parts of an ASIC, but each of these OPs needs a
separate parametrisation. It might even be the case that a basic
parametrisation is available, but still some components need an override in
a few of the inclusions.

For the use case where some 9th order filters use a higher version of the
design than others there is no place in these schemes. This can of-course be
resolved by inclusion of the same git module as two submodules in the project
e.g. as follows:

 |- lc_lpf_9th_order --> lc_lpf_9th_order.sch@commit_01
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_9th_order --> lc_lpf_9th_order.sch@commit_01
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_9th_order --> lc_lpf_9th_order.sch@commit_02
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01
 |- lc_lpf_9th_order --> lc_lpf_9th_order.sch@commit_02
 |   |- lc_lpf_t1  --> lc_lpf_t.sch@commit_01
 |   |- lc_lpf_pi1 --> lc_lpf_pi.sch@commit_02
 |   \- lc_lpf_t2  --> lc_lpf_t.sch@commit_01

with directory and file structure:

 |- the_product.sch
 |- lc_lpf_9th_order_one\@commit_02
 |   |- lc_lpf_9th_order.sch
 |   |- lc_lpf_t\@commit_01
 |   |   \- lc_lpf_t.sch
 |   |- lc_lpf_pi\@commit_02
 |   |   \- lc_lpf_pi.sch
 |- lc_lpf_9th_order_two\@commit_01
 |   |- lc_lpf_9th_order.sch
 |   |- lc_lpf_t\@commit_01
 |   |   \- lc_lpf_t.sch
 |   |- lc_lpf_pi\@commit_01
 |   |   \- lc_lpf_pi.sch
 :   :

It can thus be seen that editing a schematic in a submodule should only have
consequences at that level. This includes annotation, component value
overrides (treating modules like classes that are inherited and of which
component parameters can be overridden higher up in the structure). In this
way modules can indeed be kept under version control in an easy way and the
submodules are not messed up. This is important since a commit on a submodule
(e.g. after fixing a bug in the schematic sheet) might in this case break the
modules library paths or inadvertedly add higher level information to a lower
level part of the circuit hierarchy.

In that respect it would be favourable to have a hierarchical way of assigning
component values. If a component value is left empty on purpose as a
configurable parameter in the circuit it could be marked as the component name
or if a component has a default value that is intended to be overridden by a
user to tweak a circuit (such as could be the case in the filters example) it
would be favourable to have a way of doing so at each (higher) level in the
schematic diagram hierarchy. Such tooling might be capable of showing at which
levels which values are assigned and/or overridden.

Something that could have a place in such a strategy are components which are
fully specified at an abstract level, is a functional specification of
components instead of already naming MPNs or footprints in the schematic. The
mentioning of the footprint however can make sense when a board design is
already present. With a functional specification the way of matching
components to the schematic might be done based on other methods than
selecting them based on footprint. E.g. when it is known that a certain
resistor needs to dissipate at least 0.5 Watt, it might not be known upfront
which footprint will be needed. However, Kicad currently does not have ways
of selecting components based on such parameters. With transistors this
problem becomes even more difficult since transistors having roughly the same
parameters come in different packages. For a resistor several parameters could
be specified that can be taken into account before / during selection of the
correct footprint, such as:
  * value = "10k"
  * package = <available when a layout is reused>
  * part_type = resistor
  * tolerance_neg = -10%
  * tolerance_pos = +10%
  * voltage_max = 50V
  * power = 0.02W (max power under normal operation)
  * power_max = 0.1W (e.g. when output shorted)
  * temperature_min = -50 (in degrees C)
  * temperature_max = +125
  * temperature_coef_max = 10 (in ppm/deg. C)
  * conductor_type=ceramic oxide (or e.g. metal in low-noise application)

all with the goal of finding (for each production run a potentially
different) MF and MPN, which will then yield a footprint. It is proposed to
allow empty values in the schematics, that could be filled when needed at some
level of abstraction. This could be an interesting feature when capturing
schematics for ASIC design, where references to technology or libraries could
be kept with the schematics at the highest level of abstraction, allowing
reuse of the schematics for multiple chips at multiple processes.

It might be nice to select footprints based on such extended lists. These are
all properties one would normally use to find parts in databases from
suppliers. It is proposed to keep the scheme flexible as it could be used to
interface with databases from e.g. a purchase department. The question is if
this will enhance Kicad and add the capability of creating BOMs more flexible.
E.g. the PN, MPN and footprint could be fixed in the first run, but a
comparison with other components that fit the footprint, and relevant
parameters can be made on starting a next production run to see if the chosen
components are available, and still have the right price. Extended information
could in the future be captured in a database, or interfaces to one or more
ERP softwares could be designed.

Requirements retrieved from the above
Req001: Kicad shall not modify files beyond those needed for the current
        schematic sheet and it's directly related files.
Req002: The sheet shall be treated as the modular unit in Kicad.
Req003: Annotation shall be possible at each level in the hierarchy without
        limiting annotation at higher and lower levels in the hierarchy.
Req004: Deviations in annotation and component parameter values shall be saved
        at the point higher in the hierarchy where they are contrived.

Implementation strategies

Attachment: signature.asc
Description: OpenPGP digital signature

Follow ups