Programmatically generating schematic


I am working on a discrete (transistor based) CPU and for the ALU, I’ll intend to use part of the flow Tim demonstrated:
A netlist of for example NOT/NAND/NOR gates is generated by the verilog synthesizer and I’d like to create a KiCad schematic from that netlist. As RTL NAND/NOR gates consist of just two transistors and one resistor, I’d hard-code that in the converter and just place resistors (all 1k), transistors (MOSFET) and labels automatically. For the ALU, I’d implement a 1 bit slice this way, put in in a hierarchic diagram and integrate it from there.
So how do I generate a schematic? The API seems to have been pushed to V7. Schematic files are text so could be easy, but:
(symbol (lib_id “Transistor_FET:2N7002”) (at 50.8 90.17 0) (unit 1)
(in_bom yes) (on_board yes)
(uuid 00000000-0000-0000-0000-000061edac7b)
(property “Reference” “Q105” (id 0) (at 55.9816 89.0016 0)
(effects (font (size 1.27 1.27)) (justify left))
(property “Value” “RUM001L002” (id 1) (at 55.9816 91.313 0)
(effects (font (size 1.27 1.27)) (justify left) hide)
(property “Footprint” “Package_TO_SOT_SMD:SOT-723” (id 2) (at 55.88 92.075 0)
(effects (font (size 1.27 1.27) italic) (justify left) hide)
(property “Datasheet” “” (id 3) (at 50.8 90.17 0)
(effects (font (size 1.27 1.27)) (justify left) hide)
(property “JLC” “C253528” (id 4) (at 50.8 90.17 0)
(effects (font (size 1.27 1.27)) hide)
(pin “1” (uuid 4858e9af-4c74-4b84-be6b-43d2fffe3fec))
(pin “2” (uuid 9dc4c419-9dbe-4189-8978-db3449de0725))
(pin “3” (uuid 3c41fa83-bded-4f4d-b3e2-2055a406e982))

This seems easy, except for the uuids. Do I need them (probably)? Is there an easy way to skip them? Is there a proper/quick+dirty way to generate UUIDs?

What about V5:

L Transistor_FET:2N7002 Q111
U 1 1 61CAED75
P 3100 7900
AR Path="/61CAED75" Ref=“Q111” Part=“1”
AR Path="/61B4AA84/61CAED75" Ref=“Q?” Part=“1”
F 0 “Q111” H 3304 7946 50 0000 L CNN
F 1 “RUM001L002” H 3304 7855 50 0001 L CNN
F 2 “Package_TO_SOT_SMD:SOT-723” H 3300 7825 50 0001 L CIN
F 3 “” H 3100 7900 50 0001 L CNN
F 4 “C253528” H 3100 7900 50 0001 C CNN “JLC”
1 3100 7900
1 0 0 -1

Also some “magic” numbers like 61CAED75 there - what about those?

Any other idea? Create Eagle schematic and convert from there?

Thanks! Martin

The UUID’s are important.
They are what “defines” a part, and it is what links a schematic symbol to a footprint on the PCB.

UUID’s are quite universal :slight_smile: and common.

Python 3.8.10 (default, Sep 28 2021, 16:10:42) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import uuid
>>> asdf = uuid.uuid4()
>>> print (asdf)

Possibly you also want to look into the SKiDL project.
It’s a python library that is intended to be used as a replacement for drawing a schematic.
Schematics do not make much sense with VHDL (verilog) or other FPGA synthesis tools.

Also be aware that the the schematic file format has been completely re-designed (to S-expressions) for KiCad V6. All tools designed for older KiCad versions have to be changed (signifcantly) if they have to work with the new file format.

I get 14d5dc4a-d622-43bd-8b72-aa6b110b2e45 when I try your code.
(just joking).
OK - so these are standard UUIDs, not something KiCad specific?
So if I start the schematic from scratch (or from a template, containing the resistor and MOSFET as library symbols already) can I assign any UUID to component and pins?
The PCB that would be created then would simply reference my UUIDs.

Usefulness of gate level schematic: Probably zero, I agree. I’d just pack it into a sub-sheet, maybe add a handful of decoupling capacitors. Then layout by hand, replicate ALU slice 8 or 16 times (replicate plugin, works hopefully in V6).

I am well aware of the UUID concept.
I was just not sure if the “uuid” field is just that or something KiCad specific.

Here’s one explanation of the UUID: Update PCB from Schematic's match methods.

Here’s the internals:

I think KiCad has some mechanism for fixing broken (missing) UUIDs in the schematic. But I’m not sure if it makes your life any easier if you try to create a new schematic backwards from an existing netlist.

As it turns out KiCad is rather tolerant when reading the schematic: A simple

(symbol (lib_id "Transistor_FET:2N7002") (at 33.020000 38.100000 0) (unit 1))

is sufficient for instantiating a transistor. All missing fields and UUIDs are generated by KiCad. However it is a bit more convenient to add more information, so a inverter looks like this:

  (symbol (lib_id "Transistor_FET:2N7002") (at 33.020000 38.100000 0) (unit 1)
  (property "Reference" "T?" (id 0)(effects hide))
  (property "Value" "RUM001" (id 1)(effects hide))
  (property "Footprint" "Package_TO_SOT_SMD:SOT-723" (id 2)(effects hide)))
  (symbol (lib_id "power:VCC") (at 35.560000 25.400000 0) (unit 1)
  (property "Value" "VCC" (id 1) (at 35.560000 25.400000 0)))
  (symbol (lib_id "power:GND") (at 35.560000 43.180000 0) (unit 1)
  (property "Value" "GND" (id 1) (at 35.560000 43.180000 0)))
  (symbol (lib_id "Device:R") (at 35.560000 29.210000 0) (unit 1)
  (property "Value" "1k" (id 1)(effects hide))
  (property "Reference" "R?" (id 0)(effects hide)))
  (label "N_ALU_Sel.0" (at 27.940000 38.100000 0))
  (label "N_1" (at 35.560000 33.020000 0))

Admittedly, the schematic is not much fun:

2021-12-20 17_13_08-DiscTemp DiscTemp_ — Schematic Editor

Just to see if it works I generated the PCB and let Freerouting do the work - routing on a four layer PCB with one ground layer:

Component placement is crap of course and more of a torture test for the autorouter. As Tim suggested I also use a simulated annealing placement algorithm which creates a somhow optimized floorplan:

Next will be to figure out how to get the placement data into KiCad. First idea would be to arrange the cells in an optimal way in the schematic - and then there’s this plugin “copy placement from schematic to layout” I’ll try out (hopefully still there in V6). Plan B would be to write an import function myself or mess with the layout file.

1 Like

Didn’t manage to install the “SchematicPositionsToLayout” plugin.
Fortunately the PCB text format is easy to parse so I exchanged the coordinates of the autoplaced components by the ones from the optimizer:

I’d say you can’t complain… this is autoplaced and autorouted (starting with a spice netlist from yosys) without any manual intervention.
While I fully agree that an autorouter does not make sense for most applications (including commercial and absolutely for KiCad), in this (rather exotic) case it’s extremely helpful!

1 Like

I had to try this.

1300 pads, 555 vias, 251 nets. :grinning:


Not sure if anyone still reads this…
In the meantime I upgraded the ALU code to support more or less all 6502 instructions: Add, sub, inc, dec, and, or, xor, not, shifts. I also increased the bit width to 8 bit - which is what I’ll probably use.
The synthesizer produced a netlist with about 1400 components, giving 3911 pads, 1705 vias and 12659 track segments. I have to say I half expected something to crash - KiCad (update PCB from schematics adding 1400 components?!) or freerouter - nope.
Freerouting has its bugs you need to work around, but apart from that performed well - routing this PCB in roughly 1h20m. KiCad also just worked - I have not edited the layout yet, but DRC and plane refill work without any problems and just a few seconds delay. Quite astonishing! A big thanks to all KiCad devs and also to the Freerouting programmers!

Big question - will this ever work? And if not, how do you find the bug…?


Add test points and use a multimeter.


Add a JTAG test chain with test vectors generated from the input files.

The question was rhetoric (with the implied answer being “you don’t”). But actually I’ll use an FPGA development board as basis for clocking and debugging. So I can easily generate test vectors (loop through all possibilities - not difficult for an 8 bit ALU) and compare the transistor-logic output to the FPGA one. Based on the difference (hopefully none) it might even possible to narrow the error down to a few components.

Yes, I both understood and ignored that. :slight_smile:

Euhm, that may also be caused by limited test vectors.
As this whole thing is mostly for fun, you may want to do it thoroughly just for fun. If your test vectors are thorough, then JTAG can (and should) detect any faulty transistor, and for a lot of faults it can even tell where the fault is (approximately). So the real test is to verify if JTAG can detect all possible faults in your circuit.

100% coverage is not difficult here: It is a purely combinatorial circuit with inputs A, B, Select, Carry in; 21 bits in total. So looping through all 2^21 possibilities should cover it.
I roughly know what JTAG is, but never used it for testing myself. As I understand it, via the JTAG test access port TAP I’d write/read the boundary cells, generating stimuli and verifying the result. How would you, identifying a discrepancy between expected and actual result, identify the bug? Assuming a missing component, one could loop through the netlist, remove components one after another, simulate the schematic and see if the faulty output results. The same for net opens, much more difficult for net shorts.

Working with (digital) electronics and no experience with JTAG…
JTAG is a standardized protocol that can be used for programming and testing of electronics. It can also be used for programming and debugging microcontrollers.

In it’s most basic form, JTAG is a long shift register (and different devices can be chained together, which just makes the shift register longer) Each flipflop (bit) in the shift register can be an output or an input.

In detail it has much more complexity, for examples parts of the long shift register can be shorted (There can be thousands of flipflops in the shift register)

There is an overwhelming amount of info on the 'web about JTAG, and if you’re interested in gate-level workings of digital electronics, then knowing about JTAG is a must, so you really have some more homework to do :slight_smile:

Not necessary for digital design. You spend days/weeks/months with Modelsim, finally download your code and it works… I did mainly a lot of FPGA designs where you could still debug, but with ASIC design you’d better not need to. Also there’s no need to verify if your FPGA works.
As I wrote I am aware of JTAG. I just don’t know how in this (someway both analog and digital) case one would best deduce a potential fault from a mismatch in test vector response. I’d say people doing production testing after PCB assembly knew that and have the appropriate tools - I never did production testing myself, that’s what you pay the assembly house for.


Sure, you can always delegate (If you’re the boss), or pay someone else (If you have the dope) to do the work for you, but those are lame excuses.

Apparently you’re interested in Asics, gate level ectronics, and you can

which may very well use JTAG in the background.

If you’re planning to do (paid) work in this area, and a job interviewer asks you to explain wat JTAG is and how it works, you loose a bunch of points if you can’t explain an overview of what it is and how it works.

Also, a lot of thought has gone into the design of JTAG, and reading more about it’s implementation will broaden your skills.

Maybe, but in all my professional experience, that sounds MOSTLY like gatekeeping. Sure, JTAG is in everything, but mostly in a transparent background capacity you don’t much have to care about. JTAG’s main claim to fame is boundary scan. Boundary scan is very easy to never touch in a practical capacity. Once upon a time, it might have been THE ONLY way to do a connectivity test on a finished board, but these days it’s somewhat of an afterthought, between requisite manufacturing inspection steps and production test requirements that already exceed what boundary scan alone can deliver, in many if not most cases.

Plus, the software to set up and execute a boundary scan test matrix is terribly expensive. Exactly one of my employers has ever cared enough to pay for it, and they make space robots.

1 Like