diff --git a/src/lay/lay/macro_templates/via_pcell_sample.lym b/src/lay/lay/macro_templates/via_pcell_sample.lym
index ada1d58c7..db22d7a76 100644
--- a/src/lay/lay/macro_templates/via_pcell_sample.lym
+++ b/src/lay/lay/macro_templates/via_pcell_sample.lym
@@ -7,271 +7,291 @@
false
macros
ruby
- import pya
-import math
+ # Sample via PCell
+#
+# This sample PCell implements a library called "MyViaLib" with a single PCell that
+# provides two vias for a hypothetical technology with these layers:
+#
+# 1/0 Metal1
+# 2/0 Via1
+# 3/0 Metal2
+# 4/0 Via2
+# 5/0 Metal3
+#
+# The sample demonstrates how to equip a PCell with the necessary declarations,
+# so it can supply vias for the wire (path) tool.
+#
+# It implements simple rectangular via arrays made from squares with a fixed size,
+# pitch and enclosure.
+#
+# 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.
-"""
-Sample via PCell
+module MyViaLib
-This sample PCell implements a library called "MyViaLib" with a single PCell that
-provides two vias for a hypothetical technology with these layers:
-
- 1/0 Metal1
- 2/0 Via1
- 3/0 Metal2
- 4/0 Via2
- 5/0 Metal3
-
-The sample demonstrates how to equip a PCell with the necessary declarations,
-so it can supply vias for the wire (path) tool.
-
-It implements simple rectangular via arrays made from squares with a fixed size,
-pitch and enclosure.
-
-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.
-"""
-
-class ViaPCell(pya.PCellDeclarationHelper):
-
- def __init__(self):
+ include RBA
- """
- Constructor: provides the PCell parameter definitions
- """
-
- super(ViaPCell, self).__init__()
-
- # Every via PCell should declare these parameters:
- #
- # via: the name of the via as declared in the via types
- # w_bottom: the width of the bottom box in micrometers
- # h_bottom: the height of the bottom box in micrometers
- # w_top: the width of the top box in micrometers
- # h_top: the width of the top box in micrometers
- #
- # w_bottom etc. can be zero, indicating that the via
- # does not have a specific extension in this layer.
- # The PCell may chose a dimension in that case.
-
- self.param("via", self.TypeString, "Via type", hidden = False)
- self.param("w_bottom", self.TypeDouble, "Bottom width", hidden = False, default = 0.0)
- self.param("h_bottom", self.TypeDouble, "Bottom height", hidden = False, default = 0.0)
- self.param("w_top", self.TypeDouble, "Top width", hidden = False, default = 0.0)
- self.param("h_top", self.TypeDouble, "Top height", hidden = False, default = 0.0)
-
- # Optional additional parameters: here we allow to override
- # the computed array dimension by setting these parameters
- # to non-zero.
-
- self.param("nx", self.TypeInt, "nx", default = 0)
- self.param("ny", self.TypeInt, "ny", default = 0)
-
- # Build a list of supported vias
-
- self.via_type_list = []
-
- # Via1
- vt = pya.ViaType("V1", "Via1 (0.2x0.2)")
- vt.wbmin = 0.4
- vt.hbmin = 0.4
- vt.wtmin = 0.5
- vt.htmin = 0.5
- vt.bottom = pya.LayerInfo(1, 0)
- vt.cut = pya.LayerInfo(2, 0)
- vt.top = pya.LayerInfo(3, 0)
- vt.bottom_grid = 0.01
- vt.top_grid = 0.01
-
- # foreign attributes (not used by pya, but handy for
- # internal use):
- vt.enc_bottom = 0.1
- vt.enc_top = 0.15
- vt.vwidth = 0.2
- vt.vspace = 0.2
-
- self.via_type_list.append(vt)
-
- # Via2
- vt = pya.ViaType("V2", "Via2 (0.3x0.3)")
- vt.wbmin = 0.5
- vt.hbmin = 0.5
- vt.wtmin = 0.5
- vt.htmin = 0.5
- vt.bottom = pya.LayerInfo(3, 0)
- vt.cut = pya.LayerInfo(4, 0)
- vt.top = pya.LayerInfo(5, 0)
- vt.bottom_grid = 0.01
- vt.top_grid = 0.01
-
- # foreign attributes (not used by pya, but handy for
- # internal use):
- vt.enc_bottom = 0.1
- vt.enc_top = 0.1
- vt.vwidth = 0.3
- vt.vspace = 0.2
-
- self.via_type_list.append(vt)
-
- def via_types(self):
- """
- Implements the "via_types" method from the PCellDeclaration
- interface: delivers the vias supported by this PCell.
- """
- return self.via_type_list
-
- def via_type(self):
- """
- Returns the via with the name given by the "via"
- PCell argument
- """
- for vt in self.via_type_list:
- if vt.name == self.via:
- return vt
- return None
-
- def display_text_impl(self):
- """
- PCell interface implementation
- """
- return "Via(" + self.via + ")"
+ # Extend the ViaType class with some custom attributes
+ class ViaTypeEx < RBA::ViaType
- def coerce_parameters_impl(self):
- """
- PCell interface implementation
- """
- pass
-
- def can_create_from_shape_impl(self):
- """
- PCell interface implementation
- """
- return false
-
- def parameters_from_shape_impl(self):
- """
- PCell interface implementation
- """
- pass
-
- def transformation_from_shape_impl(self):
- """
- PCell interface implementation
- """
- return pya.Trans()
+ def initialize(*args)
+ super(*args)
+ end
- def min_dim(self, a, b, da, db):
- """
- A helper function to compute the minimum
- width or height less the enclosure
- (a = w/h_bottom, b = w/h_top,
- da/b = enclosure for a/b)
- """
- if a < 1e-10 and b < 1e-10:
- return 0.0
- elif a < 1e-10:
- return b - 2.0 * max(da, db)
- elif b < 1e-10:
- return a - 2.0 * max(da, db)
- else:
- return min(a - 2.0 * da, b - 2.0 * db)
+ attr_accessor :enc_bottom
+ attr_accessor :enc_top
+ attr_accessor :vwidth
+ attr_accessor :vspace
- def getnxy(self, vt):
-
- """
- Computes the nx and ny as mandated by the widths and
- heights
-
- w/h_top/bottom can be zero, indicating no specific
- dimension is requested. The implementation can choose
- what to do in this case. It can also decide to provide
- largher vias than given by w_ or h_ or favor square vias
- over rectangular ones.
- """
+ end
- mode = 2 # 1: maximum, 2: minimum
+ class ViaPCell < PCellDeclarationHelper
+
+ # Constructor: provides the PCell parameter definitions
+
+ def initialize
- if mode == 1:
+ # Important: initialize the super class
+ super
+
+ # Every via PCell should declare these parameters:
+ #
+ # via: the name of the via as declared in the via types
+ # w_bottom: the width of the bottom box in micrometers
+ # h_bottom: the height of the bottom box in micrometers
+ # w_top: the width of the top box in micrometers
+ # h_top: the width of the top box in micrometers
+ #
+ # w_bottom etc. can be zero, indicating that the via
+ # does not have a specific extension in this layer.
+ # The PCell may chose a dimension in that case.
+
+ param(:via, TypeString, "Via type", :hidden => false)
+ param(:w_bottom, TypeDouble, "Bottom width", :hidden => false, :default => 0.0)
+ param(:h_bottom, TypeDouble, "Bottom height", :hidden => false, :default => 0.0)
+ param(:w_top, TypeDouble, "Top width", :hidden => false, :default => 0.0)
+ param(:h_top, TypeDouble, "Top height", :hidden => false, :default => 0.0)
+
+ # Optional additional parameters: here we allow to override
+ # the computed array dimension by setting these parameters
+ # to non-zero.
+
+ param(:nx, TypeInt, "nx", :default => 0)
+ param(:ny, TypeInt, "ny", :default => 0)
+
+ # Build a list of supported vias
+
+ @via_type_list = []
+
+ # Via1
+ vt = ViaTypeEx::new("V1", "Via1 (0.2x0.2)")
+ vt.wbmin = 0.4
+ vt.hbmin = 0.4
+ vt.wtmin = 0.5
+ vt.htmin = 0.5
+ vt.bottom = RBA::LayerInfo::new(1, 0)
+ vt.cut = RBA::LayerInfo::new(2, 0)
+ vt.top = RBA::LayerInfo::new(3, 0)
+ vt.bottom_grid = 0.01
+ vt.top_grid = 0.01
+
+ # foreign attributes (not used by RBA, but handy for
+ # internal use):
+ vt.enc_bottom = 0.1
+ vt.enc_top = 0.15
+ vt.vwidth = 0.2
+ vt.vspace = 0.2
+
+ @via_type_list.append(vt)
+
+ # Via2
+ vt = ViaTypeEx::new("V2", "Via2 (0.3x0.3)")
+ vt.wbmin = 0.5
+ vt.hbmin = 0.5
+ vt.wtmin = 0.5
+ vt.htmin = 0.5
+ vt.bottom = RBA::LayerInfo::new(3, 0)
+ vt.cut = RBA::LayerInfo::new(4, 0)
+ vt.top = RBA::LayerInfo::new(5, 0)
+ vt.bottom_grid = 0.01
+ vt.top_grid = 0.01
+
+ # foreign attributes (not used by pya, but handy for
+ # internal use):
+ vt.enc_bottom = 0.1
+ vt.enc_top = 0.1
+ vt.vwidth = 0.3
+ vt.vspace = 0.2
+
+ @via_type_list.append(vt)
+
+ end
+
+ # Implements the "via_types" method from the PCellDeclaration
+ # interface: delivers the vias supported by this PCell.
- # This implementation uses the maximum size requested
- # by either top or bottom:
+ def via_types
+ return @via_type_list
+ end
+
+ # Returns the via with the name given by the "via"
+ # PCell argument
+ def via_type
+ @via_type_list.each do |vt|
+ if vt.name == self.via
+ return vt
+ end
+ end
+ return nil
+ end
+
+ # PCell interface implementation
+ def display_text_impl
+ return "Via(" + self.via + ")"
+ end
+
+ # PCell interface implementation
+ def coerce_parameters_impl
+ end
+
+ # PCell interface implementation
+ def can_create_from_shape_impl
+ return false
+ end
+
+ # PCell interface implementation
+ def parameters_from_shape_impl
+ end
+
+ # PCell interface implementation
+ def transformation_from_shape_impl
+ return RBA::Trans::new
+ end
+
+ # A helper function to compute the minimum
+ # width or height less the enclosure
+ # (a = w/h_bottom, b = w/h_top,
+ # da/b = enclosure for a/b)
+
+ def min_dim(a, b, da, db)
+ if a < 1e-10 && b < 1e-10
+ return 0.0
+ elsif a < 1e-10
+ return b - 2.0 * [da, db].max
+ elsif b < 1e-10
+ return a - 2.0 * [da, db].max
+ else
+ return [a - 2.0 * da, b - 2.0 * db].min
+ end
+ end
+
+ # Computes the nx and ny as mandated by the widths and
+ # heights
+ #
+ # w/h_top/bottom can be zero, indicating no specific
+ # dimension is requested. The implementation can choose
+ # what to do in this case. It can also decide to provide
+ # largher vias than given by w_ or h_ or favor square vias
+ # over rectangular ones.
+
+ def getnxy(vt)
+
+ mode = 2 # 1: maximum, 2: minimum
+
+ if mode == 1
+
+ # This implementation uses the maximum size requested
+ # by either top or bottom:
+
+ w = [[self.w_bottom, vt.wbmin].max - 2 * vt.enc_bottom,
+ [self.w_top, vt.wtmin].max - 2 * vt.enc_top].max
+
+ h = [[self.h_bottom, vt.hbmin].max - 2 * vt.enc_bottom,
+ [self.h_top, vt.htmin].max - 2 * vt.enc_top].max
+
+ elsif mode == 2
+
+ # This implementation delivers the minimum via, ignoring
+ # zero dimensions:
- w = max(max(self.w_bottom, vt.wbmin) - 2 * vt.enc_bottom,
- max(self.w_top, vt.wtmin) - 2 * vt.enc_top)
-
- h = max(max(self.h_bottom, vt.hbmin) - 2 * vt.enc_bottom,
- max(self.h_top, vt.htmin) - 2 * vt.enc_top)
+ w = self.min_dim(self.w_bottom, self.w_top, vt.enc_bottom, vt.enc_top)
+ h = self.min_dim(self.h_bottom, self.h_top, vt.enc_bottom, vt.enc_top)
- elif mode == 2:
-
- # This implementation delivers the minimum via, ignoring
- # zero dimensions:
+ end
+
+ # parameter nx or ny override computed value if > 0
- w = self.min_dim(self.w_bottom, self.w_top, vt.enc_bottom, vt.enc_top)
- h = self.min_dim(self.h_bottom, self.h_top, vt.enc_bottom, vt.enc_top)
-
- # parameter nx or ny override computed value if > 0
-
- if self.nx > 0:
- nx = self.nx
- else:
- nx = max(1, int(math.floor((w + vt.vspace) / (vt.vwidth + vt.vspace) + 1e-10)))
-
- if self.ny > 0:
- ny = self.ny
- else:
- ny = max(1, int(math.floor((h + vt.vspace) / (vt.vwidth + vt.vspace) + 1e-10)))
-
- return (nx, ny)
+ if self.nx > 0
+ nx = self.nx
+ else
+ nx = [1, ((w + vt.vspace) / (vt.vwidth + vt.vspace) + 1e-10).floor.to_i].max
+ end
- def produce_impl(self):
+ if self.ny > 0
+ ny = self.ny
+ else
+ ny = [1, ((h + vt.vspace) / (vt.vwidth + vt.vspace) + 1e-10).floor.to_i].max
+ end
- """
- Implementation of the PCell interface: generates the layouts
- """
-
- vt = self.via_type()
- if vt is None:
- return
+ return [nx, ny]
- (nx, ny) = self.getnxy(vt)
+ end
- wcut = nx * vt.vwidth + (nx - 1) * vt.vspace
- hcut = ny * vt.vwidth + (ny - 1) * vt.vspace
- wbottom = max(max(self.w_bottom, vt.wbmin), vt.enc_bottom * 2.0 + wcut)
- hbottom = max(max(self.h_bottom, vt.hbmin), vt.enc_bottom * 2.0 + hcut)
- wtop = max(max(self.w_top, vt.wtmin), vt.enc_top * 2.0 + wcut)
- htop = max(max(self.h_top, vt.htmin), vt.enc_top * 2.0 + hcut)
+ # Implementation of the PCell interface: generates the layouts
- lbottom = self.layout.layer(vt.bottom)
- ltop = self.layout.layer(vt.top)
- lcut = self.layout.layer(vt.cut)
+ def produce_impl
- self.cell.shapes(lbottom).insert(pya.DBox(wbottom, hbottom))
- self.cell.shapes(ltop).insert(pya.DBox(wtop, htop))
+ vt = self.via_type
+ if !vt
+ return
+ end
+
+ (nx, ny) = self.getnxy(vt)
+
+ wcut = nx * vt.vwidth + (nx - 1) * vt.vspace
+ hcut = ny * vt.vwidth + (ny - 1) * vt.vspace
+ wbottom = [[self.w_bottom, vt.wbmin].max, vt.enc_bottom * 2.0 + wcut].max
+ hbottom = [[self.h_bottom, vt.hbmin].max, vt.enc_bottom * 2.0 + hcut].max
+ wtop = [[self.w_top, vt.wtmin].max, vt.enc_top * 2.0 + wcut].max
+ htop = [[self.h_top, vt.htmin].max, vt.enc_top * 2.0 + hcut].max
+
+ lbottom = self.layout.layer(vt.bottom)
+ ltop = self.layout.layer(vt.top)
+ lcut = self.layout.layer(vt.cut)
+
+ self.cell.shapes(lbottom).insert(RBA::DBox::new(wbottom, hbottom))
+ self.cell.shapes(ltop).insert(RBA::DBox::new(wtop, htop))
+
+ scut = self.cell.shapes(lcut)
+
+ nx.times do |ix|
+ x = (ix - 0.5 * (nx - 1)) * (vt.vwidth + vt.vspace)
+ ny.times do |iy|
+ y = (iy - 0.5 * (ny - 1)) * (vt.vwidth + vt.vspace)
+ scut.insert(RBA::DBox::new(vt.vwidth, vt.vwidth).moved(x, y))
+ end
+ end
+
+ end
- scut = self.cell.shapes(lcut)
+ end
+
+ # A declaration for a test library
+
+ class MyViaLib < RBA::Library
+
+ def initialize
+ self.description = "Via Test Library"
+ self.layout().register_pcell("Via", ViaPCell::new)
+ self.register("MyViaLib")
+ end
- for ix in range(0, nx):
- x = (ix - 0.5 * (nx - 1)) * (vt.vwidth + vt.vspace)
- for iy in range(0, ny):
- y = (iy - 0.5 * (ny - 1)) * (vt.vwidth + vt.vspace)
- scut.insert(pya.DBox(vt.vwidth, vt.vwidth).moved(x, y))
+ end
+
+ # instantiates the test library
+ MyViaLib::new
-
-class MyViaLib(pya.Library):
-
- """
- A declaration for a test library
- """
-
- def __init__(self):
- self.description = "Via Test Library"
- self.layout().register_pcell("Via", ViaPCell())
- self.register("MyViaLib")
-
-# instantiates the test library
-MyViaLib()
+end