← Back to team overview

kicad-developers team mailing list archive

Re: Experiments and considerations for more layer


----- Original Message -----
> From: Lorenzo Marcantonio <l.marcantonio@xxxxxxxxxxxx>
> To: Kicad Developers <kicad-developers@xxxxxxxxxxxxxxxxxxx>
> Cc: 
> Sent: Tuesday, September 3, 2013 10:09 PM
> Subject: Re: [Kicad-developers] Experiments and considerations for more	layer
> On Tue, Sep 03, 2013 at 04:15:39AM -0700, Cirilo Bernardo wrote:
>>  A down side to keeping things manageable (such as merging components into 
> the PCB) would be that there has to be a mapping which KiCAD enforces for the 
> integer layer ID and the usage. That is certainly possible and when implemented 
> I suspect the biggest nuisance would be to people who use custom layers - but 
> even that can be addressed by reserving a block of IDs which KiCAD will never 
> use in the main tree.
> Nothing forbids to reserve a range of layer IDs for that. Eagle for
> example has the first 100 layers 'reserved'. We can decide, for example
> that 0-15 (or maybe 0-31) are copper layers, the next ten or so are the
> special layers and over a 'safe' number (64, or 100) are available to
> the user for his stuff.
> That would simplify the reconciling code a bit and let use integer
> literals for the special layers (with ominous operator definitions,
> obviously). Of course user defined layers would need the stackup object
> help to correlate. Semi-formal example:
> Board A 'domain'
> Stackup object STACKA
>     0 Front
>     ..
>     15 Back
>     16 Silk Front
>     ..
>     100 Peel Mask
> Board B 'domain' (could be for a library module, maybe)
> Stackup object STACKB
>     0 Front
>     ..
>     15 Back
>     16 Silk Front
>     ..
>     150 Peel Mask
>     160 Plating
> The stackup would be vectors or sets, depending on the maximum number of
> layers you want to handle. Also O(1) vs O(log n) performance. The usual
> tradeoff.
> A layer id would be an ordered pair containing the stackup and the layer
> number. A pointer and an integers in other words. Significantly larger
> than an int but still acceptable. These things have to be designed to be
> passed around by value, like numbers (C++ can do that without problems).
> So STACKA:15 is the back copper in the board A domain, STACKB:160 is the
> plating layer in the board B domain.
> Also, a 'small integer' is valid as a layer id for fixed meaning layers.
> So 16 is *always* silk front, 0 is always copper front and so on. 150
> has *no meaning* by itself since it's not a common layer. IIRC you can
> define these implicit constructors, too.
> Then, establish an equivalence relationship same-layer-as where:
> 0 same-layer-as STACKA:0, 
> 0 same-layer-as STACKB:0,
> STACKA:100 same-layer-as STACKB:150
> (things to clarify: should it this be on the name given by the user? also,
> what if a layer with the same name has different attributes on the
> opposite sides? example: STACKA:100 could have a paired layer,
> STACKB:150 not necessarily; an 'incompatible definition' exception
> should be resolved in some way)
> Finally, add an operation change-domain so that:
> 0 change-domain STACKA -> 0 (no need to qualify it!)
> STACKA:100 change-domain STACKB -> STACKB:150 (a lookup)
> STACKB:160 change-domain STACKA -> STACKA:somenewnumber (the merge
>                                    operation)
> obviously after that
> STACKA:thepreviousnumber change-domain STACKB -> STACKB:160
> For the masking issue: as correctly shown *most* operation actually need
> only one layers (or a range, for vias). OTOH pads need a bitmask or
> something similar. These could be represented as vector<bool> or
> set<int> (same consideration as before). Layer masks need to reference
> to a stackup, as layer ids. So valid masks could be:
> STACKA:0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 (a THT pad)
> STACKB:0,160 (a card egde pad, maybe)
> Optional: the 1-14 range could be optimized with a flag 'all inner
> layers', since it's a very common thing and wastes both time to manage
> and space in the mask structure.
> Define on this object the change-domain operation (trivial) and a lookup
> operation for containment (trivial, too, and actually the most frequent
> operation on layer masks). Testing a layer for containment in a mask
> from another domain could simply apply change-domain to the checked
> layer before testing.
> In short, instead of (mask & LAYER_FRONT) use
> mask.contains(LAYER_N_FRONT). Many mask uses actually in a loop like
> this:
> for (i = LAYER_N_FRONT; i <= LAYER_N_BACK; ++i) {
>     LAYER_MASK msk = GetLayerMask(i);
>     if (the_mask & msk) stuff();
> }
> and that becomes (I find it more elegant)
> for (i = LAYER_N_FRONT; i <= LAYER_N_BACK; ++i) {
>     /* i is a reserved layer number so an int is acceptable! */
>     if (the_mask.contains(i)) stuff();
> }
> of course member iteration would be an interesting thing to do, if
> needed. 
> I don't remember if intersection between arbitrary masks is ever
> used... that could be defined as logical/set intersection, no problem
> with that.
> Add useful predicates like: IsFrontLayer (for a layer) or HasFrontLayer
> (for a mask, to check if it contains at least one layer on the front
> side). The list of these predicates has to be determined by inspection
> (i.e. during implementation :D). Some of these are already in use (look
> in the layer header). Also the fliplayer function. A layer can access
> its stackup so it can ask it for its paired layer.
> IIRC these are all the operations needed (well, serialization too but
> that's mostly a loop of layer-in-mask checks or an enumeration of some
> kind)
> That should implement the requested features.
> ALSO, most importantly, add domain changes whenever a pad/module/entity
> changes board (and with board I mean the module editor/library, too!).
> *That* is the real painful thing to do for making this work.
> Have I hit on the mark or have I forgot something? (the time needed to
> do all this of course is out of question:P)
> -- 
> Lorenzo Marcantonio
> Logos Srl

I agree with most of that except for the part about masks. I agree with Brian's idea of linking objects with each layer that they feature in - that's certainly the way I would have designed it. If we were starting from nothing it would take a little more time to implement than the bitmask scheme but the flexibility and maintainability are so much better and for people making very high density boards the performance simply wouldn't compare. Even the representation in the PCB file shouldn't be difficult; copper layers for example would basically contain only track information and we'd need a components section to hold information on what components go where, on which side of the board, and their orientation. When the PCB file is loaded, all component module information can be put into the layer objects. We could also have through holes and via sections and the through holes and vias will be classes of their own to allow correct management of blind/buried
 vias, PTH, NPTH, mounting holes etc.

I would like to know if there are any technical reasons why we wouldn't want to incorporate most (or all) of Brian's work. So if we had the people and time to do the job, are there reasons not to?

- Cirilo