- This topic has 4 replies, 2 voices, and was last updated 4 years, 6 months ago by
paul.
-
AuthorPosts
-
20 February 2020 at 13:16 #6012
paul
MemberHello
I’m trying to use the rebuild() method for layer mapping.
I’ve come up with something like this
import nazca as nd with nd.Cell(name='CellA') as cellA: nd.strt(length=10, width=5, layer=1).put() nd.bend(radius=20, width=2, angle=90, layer=2).put() cellA.rebuild(instantiate=True, layermap={1: 3, 2: 4}, layermapmode='all') nd.export_gds(topcells=cellA)
However with Nazca 0.5.7 this returns an
IndexError: list index out of range
error and I’m not too sure why. Is this the correct way of using rebuild() or is there something that I’m missing?Thanks,
Paul
5 March 2020 at 22:23 #6032Ronald
KeymasterDear Paul,
If you would like to map layers upon export to gds you can simply do this:
import nazca as nd with nd.Cell(name='CellA') as cellA: nd.strt(length=10, width=5, layer=1).put() nd.bend(radius=20, width=2, angle=90, layer=2).put() nd.export_gds(topcells=cellA, layermap={1: 3, 2: 4}, layermapmode='all')
The (hiding) rebuild() function was a special case of the cell_iter() in 0.5.7. The cell_iter() has many use cases and it requires several dedicated tutorials to cover it. These will be posted in the near future. But for layermapping you can use the example above, no need for the cell_iter().
Ronald
6 March 2020 at 14:53 #6033paul
MemberHi Ronald,
Thanks for your answer. Yes your solution works and I have been using the same idea so far, only that it isnt very flexible as export_gds() must be called whenever the layermap changes.
Say that I have a cell, CellA, which must be placed at different locations on the wafer and on different layers. My idea was to create a generic CellA on a dummy layer and then instantiate it on the approriate layer.
For instance, if I wanted to create an array of cells based on CellA placed on different layers, the code would look like:
with nd.Cell(name='CellA') as cellA: nd.strt(length=2, width=2, layer=0).put() grid_points = [(0, 0), (4, 0), (0, 4), (4, 4)] for i, (x,y) in enumerate(grid_points): # cellA.put(x,y) new_cell = cellA.rebuild(layermap={0:i}) # this is the intended usage, doesnt currently work new_cell.put(x,y) nd.export_gds()
where each “copy” of cellA would be on a different layer.
Of course, there are more efficient solutions for such a simple design, but I’d like to use this mechanic for importing generic cells from a gds file and do the layermaping in nazca. For now, I’m using something like :generic_cell = 'path_to_generic_cell.gds' # a gds file containing generic cell placed on layer 0 for i, (x,y) in enumerate(grid_points): new_cell = nd.load_gds(generic_cell, layermap={0:i}) new_cell.put(x,y)
This isn’t really efficient as I must reimport the file for each layer. That’s why I thought that importing it once and remapping in Nazca would be a better idea.
Thanks,
Paul
14 March 2020 at 16:27 #6040Ronald
KeymasterDear Paul,
That is an interesting example. Only the last cell in the loop makes it to the final gds layout, because the rebuild reuses the normal export_gds() code base that by default clears all cells at the end. Two ways forward:
Solution 1:
In a call directly to export_gds() the clear setting can be changed by passing
clear=False
. The rebuild() does not have to clear keyword yet up and including 0.5.9. You can add it though by going into Nazca module layout.py and in def rebuild() add the lineexport.clear = False
, somewhere before the lineexport.generate_layout(cell)
.Solution 2:
Another way is to use the code to reconstruct cellA and not clearing any cells. In the example below I use nazca-0.5.9 to make use of the custom suffix option and some variable name improvements. Note that each new cell needs a new unique name. Below that is done using the layer number as a suffix.
import nazca as nd with nd.Cell(name='CellA') as cellA: nd.strt(length=2, width=2, layer=0).put() grid_points = [(0, 0), (4, 0), (0, 4), (4, 4)] def custom_rebuild(cell, layermap, suffix="_new"): ly = nd.layout(layermap=layermap, suffix=suffix) for params in nd.cell_iter(cell): if params.cell_start: if params.cell_open: ly.cell_open(params) ly.add_polygons(params) ly.add_polylines(params) ly.add_annotations(params) ly.add_instances(params) elif params.cell_close: ly.cell_close(params) return ly.topcell for i, (x,y) in enumerate(grid_points): new_cell = custom_rebuild(cellA, layermap={0:i}, suffix=f"_{i}") new_cell.put(x,y) nd.export_gds()
Ronald
1 October 2020 at 12:56 #6253paul
MemberThank you Solution 2 works great! Didnt have an opportunity to test it until now..
I have added a layermapmode argument to
custombuild()
so that it can be passed tond.layout()
for filtering unwanted layers. -
AuthorPosts
- You must be logged in to reply to this topic.