Hi guys,
I'm pretty new with layout design but I found klayout great and at the same time really intuitive.
I'm working on a lithography mask design and I was wondering if there is a way to assign automatically an ID to every structure on the mask(for example an incremental number).
Comments
Sure there is, via Ruby/Python script and possibly via the 'rename cells' function, depending on what you are trying to do.
Can you give some more details about how you want to assign the number, or what you want to assign the number to. For example I could interpret your question in multiple ways, each of which has a different script associated. E.g.
Reframing your question like one of the above allows us to help you with a script
Thanks,
David
Thanls a lot for your reply. You are right. The ID has to be printed on the mask itself: I'm doing some semiconductor chip design and, once the wafer processing is performed the ID would be used to retrieve the position of the chip on the semiconductor wafer.
Nino
The easiest way I think is to use "PCell array generator.lym", which is part of TRT. Once you've installed TRT per the instructions at that link, reopen KLayout. Open a new layout. Click the menu at the top and then Cells > PCell array.*
There is an example spreadsheet file in the same "Cells" subfolder, that prints "KLAYOUT RULES" on the wafer three times, three different magnifications. Direct the dialog to point to that file and choose your other parameters then click OK to see the result.
Caveat: That script has not undergone rigorous testing, so if you find problems let me know.
There are other more custom ways. If this is not suitable for you, let us know a more about your requirements.
David
*It's not a true array, it's just some instances at some xy locations.
I'll give it a try. and let you know
Nino
Did you find a good solution or implementation for this. I was thinking of doing something very similar.
Thanks,
Keil
keilboring,
Did "PCell array generator.lym" not work for you?
David
Thanks again,
Keil
You are right, if you want "find and replace" characteristics then this will not work. Not sure exactly how to do that without writing a quite complicated custom script.
Perhaps the simplest quick fix, though this is a bit 'hacky':
You could generate it using PCellArrayGenerator the first time, then whenever you want to change the text label, you first delete them all using a custom script (which you'd need to write) and then regenerate them by running PCellArrayGenerator again (but with an updated Excel file as input).
How to write such a script that deletes all previously-placed instances? Perhaps easiest way is to modify PCellArrayGenerator so that every time it places a PCell it also applies a property. A property is some metadata attached to a cell or shape. It has a key and a value. Something like "MYPCELL" for key and #1 for value would work. ('#' signifies that '1' is an integer instead of a string, '##' signifies a float.) So then your additional custom script that you write would iterate thru all cells in the layout and delete any with property, value pair equal to "MYPCELL" : #1. Then, when they are all deleted you can add them back in again by running PCellArrayGenerator again, as I mentioned earlier.
Anyway that requires some effort in learning Ruby scripting and going down that rabbit hole... But first it is prudent to ask: would that even solve the problem you have? Did I even understand your requirement correctly?
David
Nice idea with the keys. I am not starting on this project right away but will post back if i decide to make some custom scripts around this idea.
Keil
The coordinates are just from a simple delimited text file.
TEXT1,0,0.00,r270,
TEXT2,5.00,10.00,r0,
What i cant figure out is how to run this from command line successfully. I run "klayout_app.exe my_layout.gds -r CreateText.lym". I get "No view selected". How do i select a view? I tried adding Application.instance.main_window.select_view(0) to try and select the first one but get error "layMainWindow.cc:3117 index >= 0 && index < int (views ()) was not true in MainWindow::select_view" .
Also tried "Application.instance.main_window.load_layout("my_layout.gds",0)" but got error "Internal error: dbLayout.cc:2069 ! (manager () && manager ()->transacting()) was not true".
So how do i select the the layout from the the .gds file so this the code below will work from command line? The second one works if i run it twice but i get the error.
Any help would be great.
Thanks
Keil
[code]
module MyMacro
include RBA
RBA::Application.instance.exec
lv = Application.instance.main_window.current_view
raise "No view selected" if lv.nil?
app = Application.instance
mw = app.main_window
ly = lv.active_cellview.layout
#dbu = ly.dbu
#out_cell = lv.active_cellview.cell
top = ly.top_cell.name
# ly = RBA::Layout.new
#top = ly.add_cell("TOP")
lv.transaction("Insert P-cell array")
# Find the lib
lib = RBA::Library.library_by_name("Basic")
lib || raise("Unknown lib 'Basic'")
# Find the pcell
pcell_decl = lib.layout.pcell_declaration("TEXT")
pcell_decl || raise("Unknown PCell 'TEXT'")
File.open("text.txt") do |file|
file.each_line do |line|
if line[0] != "#"
array = line.split(",")
string = array[0]
# assume the coordinates are micron units
x = (array[1].to_f / ly.dbu + 0.5).floor
y = (array[2].to_f / ly.dbu + 0.5).floor
rotation = array[3]
# Set the parameters (text string, layer to 10/0, magnification to 2.5)
param = { "text" => string, "layer" => RBA::LayerInfo::new(10, 0), "mag" => 2.5 }
# Build a param array using the param hash as a source.
# Fill all remaining parameter with default values.
pv = pcell_decl.get_parameters.collect do |p|
param[p.name] || p.default
end
# Create a PCell variant cell
pcell_var = ly.add_pcell_variant(lib, pcell_decl.id, pv)
# Instantiate that cell
if rotation == "r0"
t = RBA::Trans::new(RBA::Trans::r0, x, y)
elsif rotation == "r90"
t = RBA::Trans::new(RBA::Trans::r90, x, y)
elsif rotation == "r180"
t = RBA::Trans::new(RBA::Trans::r180, x, y)
elsif rotation == "r270"
t = RBA::Trans::new(RBA::Trans::r270, x, y)
else
t = RBA::Trans::new(RBA::Trans::r0, x, y)
end
pcell_inst = ly.cell(top).insert(RBA::CellInstArray::new(pcell_var, t))
end
end
end
lv.add_missing_layers # In case you've specified layers in the spreadsheet that don't yet exist
# save the layout
ly.write("my_layout.gds")
#ensure
#lv.commit
end
[/CODE]
Hi Keil,
You should not use "RBA::Application.instance.exec". This will basically execute the application and once you close the main window the application is in terminated state and you can't access the objects any longer. "RBA::Application.exec" is intended to be used as the final statement of certain scripts which provide some setup functionality. But there are better ways to achieve that now (the auto-run flag of macros), so that feature is no longer required.
If you want a pure processing application, you can drop the overhead of MainWindow, LayoutView and so forth. Running KLayout is not only more efficent then, it's also easier to write scripts that way.
Here is a basic recipe:
Create a script that loads a layout directly. The name of the layout will will be given by a global variable that we will define on the command line:
Save this script (for example as "myscript.rb") and execute it in batch mode (-b). Provide the input and output variables using the "-rd" option:
Matthias
Thanks for help. I ended up using this script to add a serial number to each device and change the name of the top cell. Then i use another script to merge all the files together. I am new to klayout and ruby so this might have a few bugs still.
Nice work, it's a good example. I rarely run from command line, so E4K was lacking any examples of this. I just added it, attributed to you of course. I hope this is okay but I presume it is since you've already posted the script publicly here on the forum.
Thanks,
David
Yeah anything I post on a forum is fair game. Also note i accidentally left a useless line "rotation = $rotation" above. It does nothing because i reference $rotation later instead of rotation.