Skip to main content

A Python package for textually describing electronic circuit schematics.

Project description

https://img.shields.io/pypi/v/skidl.svg

The SKiDL Python package lets you compactly describe the interconnection of electronic circuits and components. The resulting Python program performs electrical rules checking for common mistakes and outputs a netlist that serves as input to a PCB layout tool.

Features

  • Has a powerful, flexible syntax (because it is Python).

  • Permits compact descriptions of electronic circuits (think about not tracing signals through a multi-page schematic).

  • Allows textual descriptions of electronic circuits (think about using diff and git for circuits).

  • Performs electrical rules checking (ERC) for common mistakes (e.g., unconnected device I/O pins).

  • Supports linear / hierarchical / mixed descriptions of electronic designs.

  • Fosters design reuse (think about using PyPi and Github to distribute electronic designs).

  • Makes possible the creation of smart circuit modules whose behavior / structure are changed parametrically (think about filters whose component values are automatically adjusted based on your desired cutoff frequency).

  • Can work with any ECAD tool (only two methods are needed: one for reading the part libraries and another for outputing the correct netlist format).

  • Can perform SPICE simulations (Python 3 only).

  • Takes advantage of all the benefits of the Python ecosystem (because it is Python).

As a very simple example (see more in the blog), the SKiDL program below describes a two-input AND gate built from discrete transistors:

https://raw.githubusercontent.com/nturley/netlistsvg/master/doc/and.svg?sanitize=true
from skidl import *

# Create part templates.
q = Part("Device", "Q_PNP_CBE", dest=TEMPLATE)
r = Part("Device", "R", dest=TEMPLATE)

# Create nets.
gnd, vcc = Net("GND"), Net("VCC")
a, b, a_and_b = Net("A"), Net("B"), Net("A_AND_B")

# Instantiate parts.
gndt = Part("power", "GND")             # Ground terminal.
vcct = Part("power", "VCC")             # Power terminal.
q1, q2 = q(2)                           # Two transistors.
r1, r2, r3, r4, r5 = r(5, value="10K")  # Five 10K resistors.

# Make connections between parts.
a & r1 & q1["B C"] & r4 & q2["B C"] & a_and_b & r5 & gnd
b & r2 & q1["B"]
q1["C"] & r3 & gnd
vcc += q1["E"], q2["E"], vcct
gnd += gndt

generate_netlist(tool=KICAD8) # Create KICAD version 8 netlist.

And this is the output that can be fed to a program like KiCad’s PCBNEW to create the physical PCB:

(export (version D)
  (design
    (source "/home/devb/projects/KiCad/tools/skidl/tests/examples/svg/simple_and_gate.py")
    (date "07/19/2024 05:54 AM")
    (tool "SKiDL (1.2.2)"))
  (components
    (comp (ref #PWR1)
      (value GND)
      (footprint )
      (fields
        (field (name F0) #PWR)
        (field (name F1) GND))
      (libsource (lib power) (part GND))
      (sheetpath (names /top/18388231966295430075) (tstamps /top/18388231966295430075)))
    (comp (ref #PWR2)
      (value VCC)
      (footprint )
      (fields
        (field (name F0) #PWR)
        (field (name F1) VCC))
      (libsource (lib power) (part VCC))
      (sheetpath (names /top/12673122245445984714) (tstamps /top/12673122245445984714)))
    (comp (ref Q1)
      (value Q_PNP_CBE)
      (footprint )
      (fields
        (field (name F0) Q)
        (field (name F1) Q_PNP_CBE))
      (libsource (lib Device) (part Q_PNP_CBE))
      (sheetpath (names /top/5884947020177711792) (tstamps /top/5884947020177711792)))
    (comp (ref Q2)
      (value Q_PNP_CBE)
      (footprint )
      (fields
        (field (name F0) Q)
        (field (name F1) Q_PNP_CBE))
      (libsource (lib Device) (part Q_PNP_CBE))
      (sheetpath (names /top/12871193304116279102) (tstamps /top/12871193304116279102)))
    (comp (ref R1)
      (value 10K)
      (footprint )
      (fields
        (field (name F0) R)
        (field (name F1) R))
      (libsource (lib Device) (part R))
      (sheetpath (names /top/17200003438453088695) (tstamps /top/17200003438453088695)))
    (comp (ref R2)
      (value 10K)
      (footprint )
      (fields
        (field (name F0) R)
        (field (name F1) R))
      (libsource (lib Device) (part R))
      (sheetpath (names /top/12314015795656540138) (tstamps /top/12314015795656540138)))
    (comp (ref R3)
      (value 10K)
      (footprint )
      (fields
        (field (name F0) R)
        (field (name F1) R))
      (libsource (lib Device) (part R))
      (sheetpath (names /top/11448722674936198910) (tstamps /top/11448722674936198910)))
    (comp (ref R4)
      (value 10K)
      (footprint )
      (fields
        (field (name F0) R)
        (field (name F1) R))
      (libsource (lib Device) (part R))
      (sheetpath (names /top/2224275500810828611) (tstamps /top/2224275500810828611)))
    (comp (ref R5)
      (value 10K)
      (footprint )
      (fields
        (field (name F0) R)
        (field (name F1) R))
      (libsource (lib Device) (part R))
      (sheetpath (names /top/3631169005149914336) (tstamps /top/3631169005149914336))))
  (nets
    (net (code 1) (name A)
      (node (ref R1) (pin 1)))
    (net (code 2) (name A_AND_B)
      (node (ref Q2) (pin 1))
      (node (ref R5) (pin 1)))
    (net (code 3) (name B)
      (node (ref R2) (pin 1)))
    (net (code 4) (name GND)
      (node (ref #PWR1) (pin 1))
      (node (ref R3) (pin 2))
      (node (ref R5) (pin 2)))
    (net (code 5) (name N$1)
      (node (ref Q1) (pin 2))
      (node (ref R1) (pin 2))
      (node (ref R2) (pin 2)))
    (net (code 6) (name N$2)
      (node (ref Q1) (pin 1))
      (node (ref R3) (pin 1))
      (node (ref R4) (pin 1)))
    (net (code 7) (name N$3)
      (node (ref Q2) (pin 2))
      (node (ref R4) (pin 2)))
    (net (code 8) (name VCC)
      (node (ref #PWR2) (pin 1))
      (node (ref Q1) (pin 3))
      (node (ref Q2) (pin 3))))
)

History

2.0.1 (2024-12-11)

  • Fixed #233: Imported active_logger into generate_schematic.py of KiCad 6, 7, 8.

  • Fixed #235: Removed merging of multi-segment nets when generating netlists, XML, SVG, DOT because it removes pins from existing net references. Only merge for schematic generation or SPICE simulation.

2.0.0 (2024-11-27)

  • No longer compatible with Python 2.

  • @package decorator removed.

  • Additional Part` attributes can be specified when exporting libraries.

  • Added unexpio dict to Interface objects for accessing I/O without buses expanded into individual nets.

  • Added connect() and __iadd__() methods to interconnect Interface objects.

  • Part libraries are pickled when first loaded for faster access on subsequent accesses. The directory for storing the pickled library files is specified in the SKiDL configuration file.

  • The KICAD tool identifier now points to KICAD8.

1.2.2 (2024-07-13)

  • Added SVG schematic generation feature for KiCad 6, 7, and 8.

  • Added backend tool identifiers of KICAD5, KICAD6, KICAD7, and KICAD8.

  • For compatibility, KICAD tool identifier points to KICAD5.

1.2.1 (2023-07-26)

  • is_url function fixed to solve problems with search and loading libraries.

1.2.0 (2023-07-14)

  • Added ability to generate an editable schematic from a Circuit object. (Currently only works for KiCad V5.)

  • Added Group object for creating hierarchy without using function calls.

  • generate_pcb now takes an optional list of footprint library directories.

  • If not explicitly declared, Part objects will load the default footprint from their symbol definition.

  • Added empty_footprint_handler() for parts without footprints that logs errors by default but can be overriden by the user.

  • Symbol libraries can now be searched on remote repositories by placing the URL in the lib_search_paths dictionary. KiCad V6 symbols are found at https://gitlab.com/kicad/libraries/kicad-symbols/-/raw/master and V5 symbols are at https://raw.githubusercontent.com/KiCad/kicad-symbols/master/.

  • Part pins can now be sorted and retrieved in order using the ordered_pins property.

1.1.0 (2021-10-22)

  • Added generate_pcb() function to create a PCB file directly from a Circuit object. (Currently only works for KiCad.)

  • Added PartTmplt shortcut which creates a Part template using dest=TEMPLATE implicitly.

1.0.0 (2021-05-09)

  • Buses can now be created without names and a name will be automatically assigned. Or use “name=…” to manually assign a name. Or just place a string in the list of arguments and that will be used.

  • Footprint search can now process directories of footprints without the need for an fp-lib-table file.

  • Part fields can now be accessed using attributes.

  • Creating fields requires use of Part.fields[key] instead of Part.key.

  • Added context manager for Circuit object so Parts/Nets can be joined using a with… statement.

  • Adding/removing Parts to/from a Circuit can now be done using += and -=.

  • Tags can be added to Parts and Circuits for hierarchical naming.

  • Part values can now be assigned arbitrary objects including units from either PySpice or Pint.

  • Multi-function pin names can now be split into a collection of shorter aliases, thus reducing the need to access pins using regexes.

  • Schematics can now be automatically using the KiCad symbol graphics for the parts.

  • The library interface now handles the Skywater 130 SPICE libraries.

0.0.30 (2020-05-16)

  • Added @package decorator to make subcircuits act like Parts.

  • Interfaces now act like dictionaries so the ** operator works as expected.

  • Interface I/O can now be accessed using brackets ([]) and via attributes (e.g., intfc.a).

  • Interface I/O can now be assigned aliases.

  • Added tee() function for creating T-junctions in networks.

  • Custom ERCs can now be added using the erc_assert function.

  • Aliases take precedence over default pin names.

  • Substring matching in pin names can be enabled/disabled (off by default).

0.0.29 (2020-01-30)

  • Added XSPICE parts capability to SPICE simulations.

  • Unconnected XSPICE ports now are set to NULL in SPICE node lists.

  • Added no_files() function to disable output to files of netlists, ERCs, logs, backup libs.

0.0.28 (2019-12-17)

  • The zyc utility was split into a separate repository and placed on PyPi.

  • Fixed slicing of grouped part pins so things like ram['A[1]'] won’t grab A1, A10, A11, etc.

0.0.27 (2019-12-16)

  • Prevent changing the name of net 0 when generating a SPICE netlist.

  • Fixed Pin, Net, Bus and Part iterators so they’ll work in nested loops.

  • Part units are automatically added when a part is parsed.

  • Files are now opened for reading using latin_1 encoding to allow special symbols used by KiCad.

  • Part pins can now be aliased directly, e.g. uc[5].aliases += ‘gp0’.

  • Added class method get() to Part to allow finding a part based on name, reference, description.

  • Refactored ERC functions to allow user-extensibility.

  • Created a base object for Circuit, Part, Pin, Net, and Bus objects.

  • Added an aliases property to the SKiDL base object so all its children could be aliased.

  • Updated to perform simulations with ngspice version 30.

  • Added a notes property to allow attachment of user notes to Parts, Pins, Nets, etc.

  • Added net class to net objects for specifying net-specific design rules in PCBNEW.

  • Ignore multiple pins with the same number in symbols with DeMorgan equivalents.

  • Fixed problem with non-ASCII chars (e.g. Ohms) in strings.

  • Sped-up part/net naming using heap/cache, binary search, sets.

  • Sped-up by storing net traversals to avoid recomputation.

  • Fixed processing of slices in things like sdram[‘A[0:15]’].

  • Sped-up part_search() by eliminating unnecessary part parsing.

  • Improved schematic generation with graphviz.

  • Search now allows AND/OR of parenthesized terms.

  • New GUI for searching for parts and footprints.

  • Footprint libraries to search are now selected from the global fp-lib-table file.

  • KiCad library component field values are now stored in a dict in Part indexed by the field name or F0, F1, F2…

  • KiCad library component field values are also stored as Part attributes using the field name or F0, F1, F2…

  • Added p and n attributes to Part object to permit explicit reference to pin numbers or names.

0.0.26 (2019-01-25)

  • search command no longer looks in backup library because that leads to erroneous hits in all libraries.

  • Part objects will now iterate through their pins and len() will return the number of pins.

  • Updated netlist_to_skidl utility to account for new version of kinparse.

0.0.25 (2018-12-30)

  • Updated website.

  • KISYSMOD is no longer used to find part libraries, only KICAD_SYMBOL_DIR is used now.

0.0.24 (2018-09-15)

  • Fixed an error where creating a backup part library for a design would create extra pins attached to the nets.

0.0.23 (2018-08-25)

  • Added Network objects to make it easy to create serial & parallel combinations of two-pin parts.

  • SKiDL design hierarchy is now embedded in the KiCad netlist that’s generated.

0.0.22 (2018-05-XX)

  • Added Interface objects for storing complicated sets of I/O signals for subsystems.

  • ERC no longer redundantly checks every segment of a multi-segment net and reports multiple errors.

  • copy() function of Part, Bus, Pin, Net objects now returns a scalar object while copy(1) returns a list with one object.

  • Bus, Pin, and Net objects now have iterators.

  • Corrected initialization of KiCad library search paths.


0.0.21 (2018-04-30)

  • Added pull() and fetch() methods for getting/creating existing/new Net and Bus objects.

  • Added drive property to pins to override their default pin function attribute.

  • Part pins and units can now be accessed as attributes.

  • Nets, pins, and buses now support the width property.

  • Indexing with brackets now works equivalently for pins, nets, and buses.

  • Grouped part pins (such as address and data buses) can now be accessed using a slice-like notation, e.g. memory[‘ADDR[0:7]’].

0.0.20 (2018-03-08)

  • Matching of pin lists now begins with normal string matching before using regexes.

  • Added more tests and fixed existing tests.

0.0.19 (2018-02-20)

  • Selecting part pins now looks for exact match before falling back to regex matching.

  • PySpice now needs to be manually installed to perform SPICE simulations.

  • SPICE simulations of subcircuits (.SUBCKT) now supported.

  • Improvements/additions to the library of supported SPICE parts.

0.0.18 (2018-02-07)

  • SPICE simulations of circuits now supported (Python 3 only).

0.0.17 (2018-01-23)

  • Modularized code into separate files.

0.0.16 (2018-01-16)

  • Parsing of KiCad EESchema libraries made more robust.

  • DEFAULT_TOOL replaced with set_default_tool() function.

  • Some code simplification by using a context manager for opening files.

0.0.15 (2018-01-09)

  • Testing made more robust.

0.0.14 (2018-01-05)

  • KiCad netlists are now parsed using the external package kinparse.

  • Cleaned-up pylint-identified issues.

  • Removed absolute file paths to libraries from tests.

0.0.13 (2017-08-20)

  • Fixed problem where the search function was only returning parts found in the last library searched.

0.0.12 (2017-04-20)

  • Use of builtin now works with Python 2 & 3.

  • Started using namedtuple in some places (like net traversal) for clarity.

  • Corrected pin-to-pin connections so if a net is created, it goes into the same Circuit the pins are members of.

  • Part templates can now contain a reference to a Circuit object that will be applied when the template is instantiated.

  • When pins are connected to nets, or nets to nets, the resulting set of connected nets are all given the same name.

  • Buses are not added to a Circuit object if they are already members of it. This fix caused the next problem.

  • Buses weren’t getting added to the Circuit object because they already contained a reference to the Circuit. Fixed by clearing ref before adding to Circuit.

  • Created mini_reset() method to clear circuitry without clearing library cache so the libraries don’t have to be loaded again (slow).

  • search() utility now prints the names of libraries as they are searched so user sees progress.

  • Fixed exceptions if part definition contained non-unicode stuff.

  • Hide exceptions that occur when using the show() utility.

  • More tests added for NC nets and hand-crafted parts.

  • default_circuit and the NC net for the active circuit are now made accessible in all modules using __builtin__.

  • Corrected error messages that referenced wrong/non-existing variable.

  • Inserted NO_LIB for the library if it doesn’t exist when generating KiCad netlists or XML.

  • Attributes can now be passed when creating a Circuit object.

  • Pins are now associated with part when added to the part.

  • Minimum and maximum pins for a part are now computed as needed.

  • Each Circuit object now has its own NC net.

  • Added tests for bus movement and copying.

  • Implemented bus movement between Circuit objects.

  • Additional test cases were created.

  • Nets and Parts can now be removed from Circuits.

  • The circuit that pins and nets are in is now checked before connections are made so cross-circuit connections are not created.

  • Default members were added to Pin and Part objects so they would always exist and not cause errors when missing.

  • Implemented moving Parts and Nets from one circuit to another (almost).

  • Nets with no attached pins are now added to a circuit.

  • Re-wrote some tests to account for the presence of no-pin nets in a circuit.

  • A class method was missing its ‘self’ argument.

  • Fixed @subcircuit decorator so it won’t cause an error if the function it decorates doesn’t have a ‘circuit’ keyword argument.

  • Split the unit tests across multiple files. Added setup/teardown code.

  • Added capability to create multiple, independent Circuit objects to which Parts and Nets can be assigned. The default circuit is still the target if not Circuit is explicitly referenced.

  • Added IOError to exception list for opening a SKiDL part library.

0.0.11 (2017-04-04)

  • Part libraries in SKiDL format are now supported.

  • Parts can now be created on-the-fly and instantiated or added to libraries.

  • The parts used in a circuit can be stored in a backup SKiDL library and used if the original libraries are missing.

  • The KiCad standard part libraries were converted to SKiDL libraries and placed in skidl.libs.

0.0.10 (2017-03-13)

  • Nets without pins can now be merged.

  • Parts and Pins are now sorted when netlists are generated.

  • For an existing Bus, new bus lines can be inserted at any position or the bus can be extended.

0.0.9 (2017-02-16)

  • Use getattr() instead of __class__.__dict__ so that subclasses of SKiDL objects can find attributes named within strings without searching the __mor__.

0.0.8 (2017-01-11)

  • skidl_to_netlist now uses templates.

  • Default operation of search() is now less exacting.

  • Traceback is now suppressed if show() is passed a part name not in a library.

0.0.7 (2016-09-11)

  • Lack of KISYSMOD environment variable no longer causes an exception.

  • requirements.txt file now references the requirements from setup.py.

  • Changed setup so it generates a pckg_info file with version, author, email.

0.0.6 (2016-09-10)

  • Fixed error caused when trying to find script name when SKiDL is run in interactive mode.

  • Silenced errors/warnings when loading KiCad part description (.dcm) files.

0.0.5 (2016-09-07)

  • SKiDL now searches for parts with a user-configurable list of library search paths.

  • Part descriptions and keywords are now loaded from the .dcm file associated with a .lib file.

0.0.4 (2016-08-27)

  • SKiDL scripts can now output netlists in XML format.

0.0.3 (2016-08-25)

  • Added command-line utility to convert netlists into SKiDL programs.

0.0.2 (2016-08-17)

  • Changed the link to the documentation.

0.0.1 (2016-08-16)

  • First release on PyPI.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page