Closed sebastian-goeldi closed 2 months ago
Hi @sebastian-goeldi,
That is possible of course, but there are many places where layer indexes are used and some don't have a layout.
If you need support for explaining this decision - here is the motivation: There are anonymous layers. Whenever you do some computations, you may encounter cases when you need temporary layers. DRC decks use plenty of them for example. A temporary layer does not have coordinates like layer or datatype number. So LayerInfo is not a good way of identifying them. The layer index is more generic and allows addressing anonymous layers too.
Matthias
Hi Matthias,
Yes, I am fully aware that there are cases.
I am merely requesting this as I think it would be generally a good usability improvement for pure layout work (as in constructing the layout), and less so for any checking/verification work.
It would be nice to have the layoutinfo options as second class citizens alongside the index, purely on the cell functions (and maybe layout functions) where applicable.
But if you think it's not really feasible or out of scope, that's totally fine. To me (from a very surface perspective view), it seems like it wouldn't be a gigantic change, but I could totally be wrong. Feel free to close the issue in that case.
I mean in a few places it is actually easy to implement. Some BTW for cell_index vs. Cell object. It just won't go everywhere, because often, the index is the only information available and there is no Layout object in sight.
Maybe I have a different style of script coding, that it never occurred to me that the LayoutInfo
option would be useful. Almost all scripts I write have some structure like this:
ly = ... # Layout
metal1 = ly.layer(30, 0)
via1 = ly.layer(31, 0)
metal2 = ly.layer(32, 0)
...
# later I write something like this:
cell.shapes(metal1).insert(polygon)
I like having symbolic names for the layers rather than GDS layer numbers.
So the LayerInfo
option would allow me code that is only marginally different:
ly = ... # Layout
metal1 = pya.LayerInfo(30, 0)
via1 = pya.LayerInfo((31, 0)
metal2 = pya.LayerInfo((32, 0)
...
# later I write something like this:
cell.shapes(metal1).insert(polygon)
The only advantage I see is that you can take these constants from some generic module that does not need access to a Layout object. But I solved that with a little trick:
layers = {
"metal1": pya.LayerInfo(30, 0),
"via1": pya.LayerInfo(31, 0),
"metal2": pya.LayerInfo(32, 0),
}
ly = ... # Layout
for k in layers.keys():
locals()[k] = ly.layer(layers[k])
...
# later I write something like this:
cell.shapes(metal1).insert(polygon)
Matthias
Yes, this is something that I essentially did before. I can illustrate in a simplified way why I would love LayerInfos:
In kfactory (and by extension gdsfactory) we have a cell decorator which collects args and kwargs automatically and converts them to MetaInfo objects on write of the gds (and stores them in kfactory:settings:{(kw)arg_name}
. This is the weaker reason why I would love LayerInfo objects.
The bigger reason is the following:
We started using something we now call photonic design kits. You can think of these as you would of a standard cell library in digital. But since we cannot rely on device extraction for LVS, we have to do cell recognition (and build a schematic from there). We usually have a mix of circuits made out of these standard(ized) cells and test structures. In order to facilitate and make recognition easy, I made it so that the design kit has its own layout object and is actually a full library.
Then in the tapeout we instantiate these library cells
cell.create_inst(library_cell_function(width=1000, length=10_000, layer=layer1)
The problem is, if you use layer indexes for this, if you use a layer_index from cell.layout()
and pass it to this function, you will be in trouble as best case you might get the same layer, or a different layer, or worst case nothing because the index doesn't exist in the library.
Therefore, I have rewritten kfactory to allow defining the layers by LayerInfo objects and not (extended) int
enums anymore.
Also, with regards to the tricks. These usually work very nicely if it's contained by scripts, but since we have many people that contribute to our tapeouts, and many of these people are not experienced programmers at all, I need something that is very compatible with IDE autocomplete and ideally also passes static type-checkers like mypy without essentially having to disable them on almost all lines (which will be necessary if you do dictionary comprehension and similar as the type checker will not be able to follow this).
I think I got the point ...
Just a detail: in case the LayerInfo desribes a layer that does not exist yet: should the function create it or raise an error? For const versions the layer can' t be created, but for non-const it can.
I feel the layer should be created (if possible) as in GDS there is no difference between an empty and a missing layer.
I also feel that is a kind of substantial change for a minor release, but it's backward compatible and hell, why not.
Matthias
I would be ok with either of those choices! I lean towards raising an error (to kinda keep it similar to an invalid index), but creating it is also totally ok.
Whether major or minor release, I will also leave it up to you. If you follow the semantic versioning logic, I think it would still qualify for minor release, as it's only adding new API. But again, I think this should be up to you.
Hi Matthias,
I'll cut to the chase directly: Would it be possible to allow
Cell.shapes
to take a LayerInfo object and have it resolve it to the layer_index internally? If easily possible this would also be nice forCell.begin_shapes_rec(...)
and its friends. But those are less affected than shapes due to infrequent use of those.The longer story:
I am currently working on expanding the use of (gds)pdks (well, pdk is a very advanced word for where we are in photonics, but you get the general idea) across multiple layouts (in order to essentially separate cells into more or less standard cells and cells generated specifically for the tapeout such as new structures for tests etc).
One of the big struggles I encountered is that most of my end-users do not really understand why a layer index is kind of bound to the layout. So, I have essentially rewritten (or rather hidden deeper in the code) an enum for the layer indexes to mainly use LayerInfo objects instead.
But now I have the problem of having to explain to users why they have to do
c.shapes(c.layout().find_layer(LayerInfo(...)))
(of course this is a bit less explicit than here, but for illustration purposes it's in pure klayout code).Best, Sebastian