It looks like you're new here. If you want to get involved, click one of these buttons!
Hi, Matthias,
Thanks for such a great program that keeps getting even better.
Can you help me with this problem?
I am filling a circular wafer with instances of a square cell which is composed of smaller square cells. When an instance of the large square cell extends past the circle, I want to flatten it (1 hierarchy level) and remove instances of the smaller square cells that fall outside the circle. I can't figure out the correct syntax to flatten the instance from ruby (see code below):
(nr+1).times do |j|
(nc+1).times do |i|
# pattern if any part of reticle is on wafer
centerx = (i-nc/2-0.5)*maincellx
centery = (j-nr/2-0.5)*maincelly
rtl = Math::sqrt((centerx-maincellx/2)**2 + (centery+maincelly/2)**2 )
rbl = Math::sqrt((centerx-maincellx/2)**2 + (centery-maincelly/2)**2 )
rtr = Math::sqrt((centerx+maincellx/2)**2 + (centery+maincelly/2)**2 )
rbr = Math::sqrt((centerx+maincellx/2)**2 + (centery-maincelly/2)**2 )
rcenter = Math::sqrt((centerx)**2 + (centery)**2 )
if rtl < re or rbl < re or rtr < re or rbr < re then
if (j - nro2 == 1 || i - nco2 == 1) && rcenter > ralignmin && rcenter < ralignmax then
thisindex = cell_index2
else
thisindex = cell_index
end
thisinstance = RBA::CellInstArray::new(thisindex,Trans.new(0,(i-nc/2-0.5)*maincellx*dbu,(j-nr/2-0.5)*maincelly*dbu))
thiscell = ly.cell(new_top).insert(thisinstance)
# explode if cell extends past good area
if rtl > re or rbl > re or rtr > re or rbr > re then
# ly.cell(new_top).erase(thiscell) # this worked to delete cell, but not what I want
ly.flatten(thisinstance.cell_index,1,true) # no error, but doesn't work
end
end
end
end
The line that's commented out
# ly.cell(new_top).erase(thiscell) # this worked to delete cell, but not what I want
shows me that I am detecting the instance that I want to flatten (by erasing it) but that's not what I want to do.
The line that's active
ly.flatten(thisinstance.cell_index,1,true) # no error, but doesn't work
runs without producing an error, but doesn't actually flatten the instance that I want to flatten.
Comments
Hello,
The flatten method removed the child hierarchy from a cell. That is, if a cell "A" calls child cells, for example "B" and "C", "A" will look the same after flattening, but "B" and "C" will be gone from "A". The shapes of "B" and "C" will have been propagated to the cell "A" applying a proper transformation to emulate the effect of the instance.
As far as I understand your problem, this is not what you look for. You are looking for a way to flatten a single instance. Right now, there is no direct method to do that yet, but you can emulate this:
This nice example Ruby's capabilities to dynamically modify a class at runtime will extend the "Instance" class, so it provides a new method "flatten_me" which will propagate the contents of the called cell to the parent and remove the instance.
With this definition you can write:
to achieve the desired effect.
Note that this method will not prune the cell called in the instance (thisindex in your case). If it is not instantiated any other way, it will remain as a separate top cell.
There is also a potential performance pitfall here: deleting the instance will invalidate the hierarchy cache and obtaining the parent will refresh it again. So if you observe a poor performance, let me know. I'll look for a different solution then.
Regards,
Matthias
Thanks for your quick response!
I still have a problem. In the code above, thisinstance is a CellInstArray, while the new method you coded is for an Instance.
I think I should be able to create an Instance which can point to the CellInstArray that I want to flatten, but when I try
thisinstpr = RBA::Instance::new
thisinstptr.cell_inst = thisinstance
I get this error:
"Caught the following exception:
Internal error: gsiDeclDbCell.cc:1977 inst->instances() != 0 was not true in
Instance::cel_inst= (Class RuntimeError)"
Part of the problem may be my inexperience with Ruby -- do I need to use a "pointer operator" as in C (like a = &b )?
Line with no spaces in front
Not to answer your question but quick tip -- to format code, use four spaces in front of each code line. (Or more spaces for indents within the code.) You can do this manually or else just paste into something like Notepad++, select all, press tab to indent all lines, copy, and paste in to this web form.
Here is the markdown spec: http://daringfireball.net/projects/markdown/syntax
Matthias, perhaps might be worth putting a link to the Markdown spec right beside the "Markdown" radio button.
Hi all of you,
thanks for the MarkDown suggestion - I'll have to figure out how to make the Vanilla forum system do that ...
Regarding the code issue above: You don't need to create RBA::Instance objects (you can since Ruby does not forbid that, but as you see they don't work). RBA::Instance objects are rather representing an instance inside the database. Instead, you create a RBA::CellInstArray object, fill that with the attributes you require and insert that one into the cell. Only then you get a RBA::Instance object which you can use to access and modify the instance inside the database.
This may look strange, but there is a reason for that twofold identity: due to the constraining requirements for the layout database, an instance inside the database is not an independent object, but a part of a highly optimized data structure. The RBA::Instance class provides a way to manipulate the database (technically spoken, a proxy), while the RBA::CellInstArray is the standalone object to conveniently work with outside the database.
BTW: there is a similar differentiation for shapes - the "outside" objects are RBA::Box, RBA::Path, RBA::Text, RBA::Polygon, the proxy object is RBA::Shape).
Matthias
Thanks, Matthias--that works.
(For completeness, here's the section which uses the new "flatten_me" method from above):
Hi, Matthias,
Thanks for all your work and support of this excellent program!
I've come across a possible bug and am wondering if perhaps there is a better way to accomplish my purpose.
I want to "fill the edge" of a circular wafer with rectangular cells.
So far, I have a square "Reticle" with square "Chips".
I am trying to cover the circular area with instances of the reticle, and then flatten instances which stick out.
I am using the Cell.each_instance method to iterate through all instances, and then using the "flatten_me" method described above when I find an instance which needs to be flattened.
I find that looping through the instances one time is not enough, but if I loop through them 3 times, I get all the edge instances flattened. (This suggests that I am damaging the internal structure of the Cell list by flattening some instances.)
Then I want to loop through all the instances and delete those that are off the wafer.
When I do so, eventually I get a KLayout crash. After proceeding through the crash, I find that the work has been partially done (some instances that are off the wafer have been deleted) but not all.
Is there a better way to loop through the list of instances?
Do I need to modify the "flatten_me" method so I don't damage the instance list?
Here is the script I am running
Here's an example GDSII file that I am running this script on to demonstrate the behavior: gdsfile "simple GDSII example"
Hi devengr,
thanks for the nice testcase! It was very simple to reproduce, but in my case it even got stuck.
I assume there is a different behaviour depending on the mode (edit or viewer), so that may explain the difference (I used edit mode).
Anyway, the explanation is that: when you change the list of instances while you iterate it, you will basically get a mess - maybe you are destroying the instance you are currently at or something like that. The solution is pretty simple: first collect and then delete. Like this:
In my case (edit mode) this solved the problem and a single pass is sufficient.
Regards,
Matthias