Dear all,
i am facing a little "issue" with a Pcell of my own used in a gds library.
Here is the description of the problem :
i have a library called test in which i use a Pcell (module name is called BiB (see code below) in a cell called test_cell
this give a tree like this:
test_cell
-BiB.BoxInBox(L1=3/0,L2=2/0)
-BiB.BoxInBox(L1=1/0,L2=2/0)
i then use this library test in a gds (say test2/cell_test2)
when doing so i expect to have, for example, a cell tree looking like
cell_test2
-test.test_cell
-test.BiB.BoxInBox(L1=3/0,L2=2/0)
-test.BiB.BoxInBox(L1=1/0,L2=2/0)
(which is the comportment i get using for example Basic Pcells)
however i get :
cell_test2
-test.test_cell
-testBoxInBox
-testBoxInBox$1
This is not a very important "issue", since the PCell in the library file is still kept as Pcell, however it is annoying because i lose(in this case) the information of layers used by each instance of the Pcell.
For what i know it is a recent "issue" i have since migrating to
- klayout 0.24.8 (was 0.23.8)
- a different way of managing library
i used to use the following code snippet
lib = RBA::Library.new
lib.layout.read(libpath)
lib.register(name)
to use a given library
while now i am using the integrated behaviour of Klayout (giving a library name in the gds save option)
but it may be also a pcell code not that clean !!
Is there something wrong in my code? or is it expected behaviour?
For information i tested the simple PCell sample example (drawing a circle) and the behaviour is the same as my Pcell.
Edit: i read that there is a bugfix in 0.24.9 concerning hierarchy tree containing Pcell in the 0.24.9. Does this adress the above issue?
Regards
Joël
----------------------------------
# PCell Pour motif alignement et contr�les
#
# This library contains
# BoxInBox
# sample PCell implements a library called "MyLib" with a single PCell that
# draws a circle. It demonstrates the basic implementation techniques for a PCell
# and how to use the "guiding shape" feature to implement a handle for the circle
# radius.
#
# NOTE: after changing the code, the macro needs to be rerun to install the new
# implementation. The macro is also set to "auto run" to install the PCell
# when KLayout is run.
module BiB
include RBA
# Remove any definition of our classes (this helps when
# reexecuting this code after a change has been applied)
BiB.constants.member?(:BoxinBox) && remove_const(:BoxinBox)
BiB.constants.member?(:BiB) && remove_const(:BiB)
# The PCell declaration for the circle
class BoxinBox < PCellDeclarationHelper
include RBA
def initialize
# Important: initialize the super class
super
# declare the parameters
param(:larg, TypeBoolean, "Large ?",:default=> false)
param(:bl, TypeLayer, "Layer Box", :default => LayerInfo::new(1, 0))
param(:bt, TypeString, "Number Override (<100)", :default => "")
param(:binv,TypeBoolean, "Box polarit� inverse?",:default => false)
param(:ibl, TypeLayer, "Layer InBox", :default => LayerInfo::new(1, 0))
param(:ibt, TypeString, "Number Override (<100)", :default => "")
param(:ibinv,TypeBoolean, "InBox polarit� inverse?",:default => false)
end
def display_text_impl
# Provide a descriptive text for the cell
"BoxInBox(L1=#{bl.to_s},L2=#{ibl.to_s})"
end
def coerce_parameters_impl
# We employ coerce_parameters_impl to decide whether the handle or the
# numeric parameter has changed (by comparing against the effective
# radius ru) and set ru to the effective radius. We also update the
# numerical value or the shape, depending on which on has not changed.
r =25
end
def can_create_from_shape_impl
# Implement the "Create PCell from shape" protocol: we can use any shape which
# has a finite bounding box
shape.is_box? || shape.is_polygon? || shape.is_path?
end
def parameters_from_shape_impl
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
set_r shape.bbox.width*layout.dbu / 2
set_ibl layout.get_info(layer)
set_bl layout.get_info(layer)
end
def transformation_from_shape_impl
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
Trans.new(shape.bbox.center)
end
def produce_impl
# This is the main part of the implementation: create the layout
# fetch the parameters
if larg
f_ib = 3.5
f_b = 3.0
else
f_b = 1.0
f_ib = 1.0
end
# 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'")
layer = ibl.layer
datatype = ibl.datatype
if ibt == "" then
ibtexte=ibl.layer.to_s
else
ibtexte=ibt
end
if bt == "" then
btexte=bl.layer.to_s
else
btexte=bt
end
if !ibinv
param = {"text" => ibtexte, "layer" =>RBA::LayerInfo::new(layer, datatype), "mag"=>f_b*15, "inverse"=> false}
pv = pcell_decl.get_parameters.collect do |p|
param[p.name] || p.default
end
# InBox
pts3 = [ [ [-4.5*f_ib,6*f_ib],[-4.5*f_ib,8*f_ib],[4.5*f_ib,8*f_ib],[4.5*f_ib,6*f_ib] ],
[ [-4.5*f_ib,-6*f_ib],[-4.5*f_ib,-8*f_ib],[4.5*f_ib,-8*f_ib],[4.5*f_ib,-6*f_ib] ],
[ [-6*f_ib,4.5*f_ib],[-8*f_ib,4.5*f_ib],[-8*f_ib,-4.5*f_ib],[-6*f_ib,-4.5*f_ib] ],
[ [6*f_ib,4.5*f_ib],[8*f_ib,4.5*f_ib],[8*f_ib,-4.5*f_ib],[6*f_ib,-4.5*f_ib] ] ]
pts3.each { |pp|
pointlist = []
pp.each { |p| pointlist.push(Point.from_dpoint(DPoint.new( p[0]/layout.dbu, p[1]/layout.dbu ) )) }
cell.shapes(ibl_layer).insert(Polygon.new(pointlist))
}
else
param = {"text" => ibtexte, "layer" =>RBA::LayerInfo::new(layer, datatype), "mag"=>f_b*15, "inverse"=> true}
pv = pcell_decl.get_parameters.collect do |p|
param[p.name] || p.default
end
# InBox inverse
pts3 = [ [-15.00000*f_b,-15.00000*f_b],
[-15.00000*f_b,15.00000*f_b],
[15.00000*f_b,15.00000*f_b],
[15.00000*f_b,8.00000*f_ib],
[-4.50000*f_ib,8.00000*f_ib],
[-4.50000*f_ib,6.00000*f_ib],
[4.50000*f_ib,6.00000*f_ib],
[4.50000*f_ib,8.00000*f_ib],
[15.00000*f_b,8.00000*f_ib],
[15.00000*f_b,4.50000*f_ib],
[-8.00000*f_ib,4.50000*f_ib],
[-8.00000*f_ib,-4.50000*f_ib],
[-6.00000*f_ib,-4.50000*f_ib],
[-6.00000*f_ib,4.50000*f_ib],
[6.00000*f_ib,4.50000*f_ib],
[6.00000*f_ib,-4.50000*f_ib],
[8.00000*f_ib,-4.50000*f_ib],
[8.00000*f_ib,4.50000*f_ib],
[15.00000*f_b,4.50000*f_ib],
[15.00000*f_b,-6.00000*f_ib],
[-4.50000*f_ib,-6.00000*f_ib],
[-4.50000*f_ib,-8.00000*f_ib],
[4.50000*f_ib,-8.00000*f_ib],
[4.50000*f_ib,-6.00000*f_ib],
[15.00000*f_b,-6.00000*f_ib],
[15.00000*f_b,-15.00000*f_b] ]
# pts3.each { |pp|
pointlist = []
pts3.each { |p| pointlist.push(Point.from_dpoint(DPoint.new( p[0]/layout.dbu, p[1]/layout.dbu ) )) }
cell.shapes(ibl_layer).insert(Polygon.new(pointlist))
# }
end
# create a PCell variant cell
pcell_var = cell.layout.add_pcell_variant(lib, pcell_decl.id, pv)
x = f_b*16.5/layout.dbu
y = f_b*3/layout.dbu
t = RBA::Trans::new(0,false, x, y)
pcell_inst = cell.insert(RBA::CellInstArray::new(pcell_var, t))
layerb = bl.layer
datatypeb = bl.datatype
if !binv
param = {"text" => btexte, "layer" =>RBA::LayerInfo::new(layerb, datatypeb), "mag"=>f_b*15, "inverse"=> false}
pv = pcell_decl.get_parameters.collect do |p|
param[p.name] || p.default
end
#Box
pts2 = [ [ [-7.5,10],[-7.5,12],[7.5,12],[7.5,10] ],
[ [-7.5,-10],[-7.5,-12],[7.5,-12],[7.5,-10] ],
[ [-10,7.5],[-12,7.5],[-12,-7.5],[-10,-7.5] ],
[ [10,7.5],[12,7.5],[12,-7.5],[10,-7.5] ] ]
pts2.each { |pp|
pointlist = []
pp.each { |p| pointlist.push(Point.from_dpoint(DPoint.new( f_b*p[0]/layout.dbu, f_b*p[1]/layout.dbu ) )) }
cell.shapes(bl_layer).insert(Polygon.new(pointlist))
}
else
param = {"text" => btexte, "layer" =>RBA::LayerInfo::new(layerb, datatypeb), "mag"=>f_b*15, "inverse"=> true}
pv = pcell_decl.get_parameters.collect do |p|
param[p.name] || p.default
end
#Box inverse
pts2 = [ [-15.00000,-15.00000],
[-15.00000,15.00000],
[-10.00000,15.00000],
[-10.00000,7.500000],
[-12.00000,7.500000],
[-12.00000,-7.500000],
[-10.00000,-7.500000],
[-10.00000,15.00000],
[7.500000,15.00000],
[7.500000,12.00000],
[-7.500000,12.00000],
[-7.500000,10.00000],
[7.500000,10.00000],
[7.500000,-10.00000],
[-7.500000,-10.00000],
[-7.500000,-12.00000],
[7.500000,-12.00000],
[7.500000,15.00000],
[12.00000,15.00000],
[12.00000,7.500000],
[10.00000,7.500000],
[10.00000,-7.500000],
[12.00000,-7.500000],
[12.00000,15.00000],
[15.00000,15.00000],
[15.00000,-15.00000]
]
# pts3.each { |pp|
pointlist = []
pts2.each { |p| pointlist.push(Point.from_dpoint(DPoint.new( f_b*p[0]/layout.dbu,f_b*p[1]/layout.dbu ) )) }
cell.shapes(bl_layer).insert(Polygon.new(pointlist))
# }
end
pcell_var = cell.layout.add_pcell_variant(lib, pcell_decl.id, pv)
x = 16.5*f_b/layout.dbu
y = -13.5*f_b/layout.dbu
t = RBA::Trans::new(0,false, x, y)
pcell_inst = cell.insert(RBA::CellInstArray::new(pcell_var, t))
end
end
class BiB < Library
def initialize
# Set the description
self.description = "Librairie alignement et controles"
# Create the PCell declarations
layout.register_pcell("BoxinBox", BoxinBox::new)
# That would be the place to put in more PCells ...
# Register us with the name "MyLib".
# If a library with that name already existed, it will be replaced then.
register("BiB")
end
end
# Instantiate and register the library
BiB::new
end
Comments
Regards
Joël
Hi Joel,
the bugfix you mention is not related to this issue but only to manual copy/paste in the editor.
If I understand your description correctly you changed the way the "test" library is built. So now, you're loading the library from a file and this file contains PCell's, right?
If that is the case I assume the problem is related to the build order. If for some reason, the BiB PCell is built after the library is loaded, the PCell's inside the library will not be connected to your PCell code.
So the important question is: when do you load the library and when do you load the PCell? If you do both in a .lym file you can try loading the PCell "early on startup" (see macro options) to force it to be loaded before the library.
Regards,
Matthias
Concerning the order of loading when all is done through the macro way, i dunno, i suppose that its follow alphebetic order. In this case, my "old" way of doing should have loaded the Pcell before the library (since my Pcell start with B and my lybrary macro is starting with L) => hence worked the way it should.
Now that i have switch to the "integrated" library feature of klayout (put the gds library in the folder library and give it a name) i believe that klayout is loading first the lib, then the PCell macro. Is it the case?
By the way if i use your simple Pcell macro example (draw a circle, and use the "integrated" library fetaure, i have the same "wrong behaviour"
I will try your suggestion and will come back to you
Joël
have tried your suggestion. works like a charm !! Thanks for your help and for your great work !!
Maybe can i suggest you to put the early startup flag to true by default in your Pcell template?
Regards
Joël
Think i got the real issue here.
Actually i have tried your suggestion with my Pcell being in the local macro folder (identifeid as local in the macro window) and it works ok (even if i put only run on startup )
Now i also have several directories setted in the KLAYOUT_PATH env variable.
these directories appears as global directories in the macro window (the macro in theses directories being not anymore editable or modifyable)
if i move my Pcell macro into the macro directory of one of these global directories, then the macro is not automatically started at klayout launch, whatever the flog startup or early startup is setted. I dunno if it is a behaviour of my klayout installation, but a collegue of mine see the same behaviour on his own computer.
This also occur with the very simple pcell sample you provided...
Regards
JoËl
issue is closed. Everything is working ok. Don't know what happened here, but it may be related to a synchronisation issue with the disk we were working on (network disk)
Joël
Hi Joel,
thanks for this feedback. Let me know if you observe issues that are not network related.
Regards,
Matthias