mirror of https://github.com/KLayout/klayout.git
Ruby via PCell sample
This commit is contained in:
parent
e2e4c1a827
commit
cad905eb63
|
|
@ -7,271 +7,291 @@
|
||||||
<show-in-menu>false</show-in-menu>
|
<show-in-menu>false</show-in-menu>
|
||||||
<category>macros</category>
|
<category>macros</category>
|
||||||
<interpreter>ruby</interpreter>
|
<interpreter>ruby</interpreter>
|
||||||
<text>import pya
|
<text># Sample via PCell
|
||||||
import math
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
"""
|
module MyViaLib
|
||||||
Sample via PCell
|
|
||||||
|
|
||||||
This sample PCell implements a library called "MyViaLib" with a single PCell that
|
include RBA
|
||||||
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):
|
|
||||||
|
|
||||||
"""
|
# Extend the ViaType class with some custom attributes
|
||||||
Constructor: provides the PCell parameter definitions
|
class ViaTypeEx < RBA::ViaType
|
||||||
"""
|
|
||||||
|
|
||||||
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 + ")"
|
|
||||||
|
|
||||||
def coerce_parameters_impl(self):
|
def initialize(*args)
|
||||||
"""
|
super(*args)
|
||||||
PCell interface implementation
|
end
|
||||||
"""
|
|
||||||
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 min_dim(self, a, b, da, db):
|
attr_accessor :enc_bottom
|
||||||
"""
|
attr_accessor :enc_top
|
||||||
A helper function to compute the minimum
|
attr_accessor :vwidth
|
||||||
width or height less the enclosure
|
attr_accessor :vspace
|
||||||
(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)
|
|
||||||
|
|
||||||
def getnxy(self, vt):
|
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.
|
|
||||||
"""
|
|
||||||
|
|
||||||
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
|
def via_types
|
||||||
# by either top or bottom:
|
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,
|
w = self.min_dim(self.w_bottom, self.w_top, vt.enc_bottom, vt.enc_top)
|
||||||
max(self.w_top, vt.wtmin) - 2 * vt.enc_top)
|
h = self.min_dim(self.h_bottom, self.h_top, vt.enc_bottom, 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)
|
|
||||||
|
|
||||||
elif mode == 2:
|
end
|
||||||
|
|
||||||
# This implementation delivers the minimum via, ignoring
|
# parameter nx or ny override computed value if > 0
|
||||||
# zero dimensions:
|
|
||||||
|
|
||||||
w = self.min_dim(self.w_bottom, self.w_top, vt.enc_bottom, vt.enc_top)
|
if self.nx > 0
|
||||||
h = self.min_dim(self.h_bottom, self.h_top, vt.enc_bottom, vt.enc_top)
|
nx = self.nx
|
||||||
|
else
|
||||||
# parameter nx or ny override computed value if > 0
|
nx = [1, ((w + vt.vspace) / (vt.vwidth + vt.vspace) + 1e-10).floor.to_i].max
|
||||||
|
end
|
||||||
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)
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
"""
|
return [nx, ny]
|
||||||
Implementation of the PCell interface: generates the layouts
|
|
||||||
"""
|
|
||||||
|
|
||||||
vt = self.via_type()
|
|
||||||
if vt is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
(nx, ny) = self.getnxy(vt)
|
end
|
||||||
|
|
||||||
wcut = nx * vt.vwidth + (nx - 1) * vt.vspace
|
# Implementation of the PCell interface: generates the layouts
|
||||||
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)
|
|
||||||
|
|
||||||
lbottom = self.layout.layer(vt.bottom)
|
def produce_impl
|
||||||
ltop = self.layout.layer(vt.top)
|
|
||||||
lcut = self.layout.layer(vt.cut)
|
|
||||||
|
|
||||||
self.cell.shapes(lbottom).insert(pya.DBox(wbottom, hbottom))
|
vt = self.via_type
|
||||||
self.cell.shapes(ltop).insert(pya.DBox(wtop, htop))
|
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):
|
end
|
||||||
x = (ix - 0.5 * (nx - 1)) * (vt.vwidth + vt.vspace)
|
|
||||||
for iy in range(0, ny):
|
# instantiates the test library
|
||||||
y = (iy - 0.5 * (ny - 1)) * (vt.vwidth + vt.vspace)
|
MyViaLib::new
|
||||||
scut.insert(pya.DBox(vt.vwidth, vt.vwidth).moved(x, y))
|
|
||||||
|
|
||||||
|
end
|
||||||
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()
|
|
||||||
</text>
|
</text>
|
||||||
</klayout-macro>
|
</klayout-macro>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue