general true true false ruby # 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 AligneControle include RBA # Remove any definition of our classes (this helps when # reexecuting this code after a change has been applied) AligneControle.constants.member?(:BoxinBox) && remove_const(:BoxinBox) AligneControle.constants.member?(:AligneControle) && remove_const(:AligneControle) # 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(:binv,TypeBoolean, "Box polarité inverse?",:default => false) param(:ibl, TypeLayer, "Layer InBox", :default => LayerInfo::new(1, 0)) param(:ibinv,TypeBoolean, "InBox polarité inverse?",:default => false) # param(:s, TypeShape, "", :default => DPoint::new(0, 0)) # param(:r, TypeDouble, "Radius", :default => 0.1) # param(:n, TypeInt, "Number of points", :default => 64) # this hidden parameter is used to determine whether the radius has changed # or the "s" handle has been moved # param(:ru, TypeDouble, "Radius", :default => 0.0, :hidden => true) # param(:inv,TypeBoolean, "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. # rs = nil # if s.is_a?(DPoint) # compute distance in micron # rs = s.distance(DPoint::new(0, 0)) # end # if rs && (r-ru).abs < 1e-6 # set_ru rs # set_r rs #else # set_ru r #set_s DPoint::new(-r, 0) #end # n must be larger or equal than 4 #n > 4 || (set_n 4) 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 !ibinv param = {"text" => ibl.layer.to_s, "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" => ibl.layer.to_s, "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" => bl.layer.to_s, "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" => bl.layer.to_s, "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 # cell.shapes(l_layer).insert(Polygon.new(pointlist)) end # The library where we will put the PCell into class AligneControle < 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("AligneControle") end end # Instantiate and register the library AligneControle::new end