I’m going to keep using this post as my sort of research notes about routing improvements…
I am getting surprisingly good results just from combining together seemingly primitive steps.
One thing that I see existing autorouters struggle with again and again is doing a fanout that will provide a good starting point for future routing. I can do that by hand much better and it is highly repetitive. Looking back, a lot of it boils down to turning the 2D pin/pad locations into a linear sequence, so I have decided to extract that out of soupToBus
and turn it into its own function calculatePinOrder
.
Starting the routing with the correct pin order is highly important, because in many of my test cases basic A* pathfinding gives great results if - and only if - pins are routed starting with the most difficult one first and then always routing adjacent pins to prevent the situation where a past trace will block the path for a future trace.
For most connectors, a simple circular order works well, so
b1o = calculatePinOrder("H1", "circular", "H1-15");
generates
ROUTING ORDER 00: NET 06 H1-15
ROUTING ORDER 01: NET 04 H1-13
ROUTING ORDER 02: NET 08 H1-17
ROUTING ORDER 03: NET 02 H1-11
ROUTING ORDER 04: NET 39 H1-9
ROUTING ORDER 05: NET 37 H1-7
ROUTING ORDER 06: NET 10 H1-19
ROUTING ORDER 07: NET 35 H1-5
ROUTING ORDER 08: NET 22 H1-3
ROUTING ORDER 09: NET 00 H1-1
ROUTING ORDER 10: NET 13 H1-21
ROUTING ORDER 11: NET 41 H1-S2
ROUTING ORDER 12: NET 15 H1-23
ROUTING ORDER 13: NET 17 H1-25
ROUTING ORDER 14: NET 11 H1-2
ROUTING ORDER 15: NET 33 H1-4
ROUTING ORDER 16: NET 19 H1-27
ROUTING ORDER 17: NET 36 H1-6
ROUTING ORDER 18: NET 38 H1-8
ROUTING ORDER 19: NET 21 H1-29
ROUTING ORDER 20: NET 01 H1-10
ROUTING ORDER 21: NET 24 H1-31
ROUTING ORDER 22: NET 03 H1-12
ROUTING ORDER 23: NET 26 H1-33
ROUTING ORDER 24: NET 28 H1-35
ROUTING ORDER 25: NET 05 H1-14
ROUTING ORDER 26: NET 30 H1-37
ROUTING ORDER 27: NET 32 H1-39
ROUTING ORDER 28: NET 07 H1-16
ROUTING ORDER 29: NET 09 H1-18
ROUTING ORDER 30: NET 40 H1-S1
ROUTING ORDER 31: NET 12 H1-20
ROUTING ORDER 32: NET 34 H1-40
ROUTING ORDER 33: NET 31 H1-38
ROUTING ORDER 34: NET 29 H1-36
ROUTING ORDER 35: NET 14 H1-22
ROUTING ORDER 36: NET 27 H1-34
ROUTING ORDER 37: NET 25 H1-32
ROUTING ORDER 38: NET 23 H1-30
ROUTING ORDER 39: NET 16 H1-24
ROUTING ORDER 40: NET 20 H1-28
ROUTING ORDER 41: NET 18 H1-26
and then afterwards
b1 = soupToBus("H1", b1o, (800,0), (0,15000))
will do the pathfinding for connector H1
with the ordering from b1o
onto a line with 0.8mm offsets in the x direction and placed 15mm above H1
. And that produces:
I have also had to do some BGA routing on a 8 layer board and despite having 6 signal planes to work with, all 3 of my autorouters failed me again. I even asked an acquaintance with access to all the pro tools and they didn’t do a good job either. I know that BGA fanout is difficult, but for this specific case, I could manually route it with just top and bottom layer, so there is A LOT of room for improvement for those autorouters.
The correct approach to route that BGA was in my opinion:
- route all the pins on the outer ring of pads directly on top, or at least fan them out a bit to make space
- route whatever you can from the 2nd ring of pads directly on top
- place dogbones for everything left, working from the outer to the inner rings and if given the choice, always use the outermost via location
- go ring by ring from inside to outside and route the vias
To me, that seems like one can build a BGA-mode for calculatePinOrder
which will encodify what I do manually anyway. And afterwards, it then boils down to simple pathfinding again.
Now is this going to do routing fully automatically? No. But if instead of spending hours doing manual routing, I can call a few of these functions and have my BGA, connectors, and data bus routed in a sane way, that will save me a lot of time.
Maybe every footprint should have two new parameters, namely an ordering class
and a routing class
to specify default values. My DP12-40 connector would be ordering circular
while the BGA would be ordering BGA 2row direct
or something like that. That should provide tools with enough information to derive a good pin ordering (which is crucial for routing) and it also gives the user control to tweak things, if needed.
As for the routing class
, I find it really irritating that freerouting treats everything as equally valuable. I want it to first do all the length-matched data traces. Then once those are finished, it’ll route auxiliary signals around them. Once that is finished, only then should it do routed power and ground. So to make the autorouted results good and usable, I need a way to specify which pins and which components are important to me.