Skip to content

Commit

Permalink
Merge pull request google#93 from mabrains/adding_moscap_pcells_gdsfa…
Browse files Browse the repository at this point in the history
…ctory_regeneration

adding mos_cap pcells using gdsfactory rather than using klayout base implementation.
  • Loading branch information
atorkmabrains authored Feb 5, 2023
2 parents 2f059dd + a4afcf1 commit bfed737
Show file tree
Hide file tree
Showing 3 changed files with 451 additions and 1,560 deletions.
14 changes: 14 additions & 0 deletions cells/klayout/pymacros/cells/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,19 @@ def __init__(self):
# MIM_CAP DEVICES
self.layout().register_pcell("cap_mim", cap_mim())

# cap_mos
self.layout().register_pcell(
"cap_nmos", cap_nmos()
) # cap_nmos_03v3 , cap_nmos_06v0
self.layout().register_pcell(
"cap_pmos", cap_pmos()
) # cap_pmos_03v3 , cap_pmos_06v0
self.layout().register_pcell(
"cap_nmos_b", cap_nmos_b()
) # cap_nmos_03v3_b , cap_nmos_06v0_b
self.layout().register_pcell(
"cap_pmos_b", cap_pmos_b()
) # cap_pmos_03v3_b , cap_pmos_06v0_b

# Register us with the name "gf180mcu".
self.register("gf180mcu")
166 changes: 79 additions & 87 deletions cells/klayout/pymacros/cells/cap_mos.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
########################################################################################################################

import pya
from .draw_cap_mos import draw_cap_nmos, draw_cap_nmos_b, draw_cap_pmos, draw_cap_pmos_b
from .draw_cap_mos import draw_cap_mos

cap_nmos_w = 1.88
cap_nmos_l = 1
Expand All @@ -31,6 +31,8 @@
cap_pmos_b_w = 1.88
cap_pmos_b_l = 1

poly_spacing = 0.24


class cap_nmos(pya.PCellDeclarationHelper):
"""
Expand All @@ -49,31 +51,25 @@ def __init__(self):
self.Type_handle.add_choice("3.3V", "3.3V")
self.Type_handle.add_choice("5/6V", "5/6V")

self.param("l_gate", self.TypeDouble, "Length", default=cap_nmos_l, unit="um")
self.param("w_gate", self.TypeDouble, "Width", default=cap_nmos_w, unit="um")
self.param("lc", self.TypeDouble, "Length", default=cap_nmos_l, unit="um")
self.param("wc", self.TypeDouble, "Width", default=cap_nmos_w, unit="um")
self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2")
self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um")

def display_text_impl(self):
# Provide a descriptive text for the cell
return (
"cap_nmos(L="
+ ("%.3f" % self.l_gate)
+ ",W="
+ ("%.3f" % self.w_gate)
+ ")"
)
return "cap_nmos(LC=" + ("%.3f" % self.lc) + ",WC=" + ("%.3f" % self.wc) + ")"

def coerce_parameters_impl(self):
# We employ coerce_parameters_impl to decide whether the handle or the numeric parameter has changed.
# We also update the numerical value or the shape, depending on which on has not changed.
self.area = self.w_gate * self.l_gate
self.perim = 2 * (self.w_gate + self.l_gate)
self.area = self.wc * self.lc
self.perim = 2 * (self.wc + self.lc)
# w,l must be larger or equal than min. values.
if (self.l_gate) < cap_nmos_l:
self.l_gate = cap_nmos_l
if (self.w_gate) < cap_nmos_w:
self.w_gate = cap_nmos_w
if (self.lc) < cap_nmos_l:
self.lc = cap_nmos_l
if (self.wc) < cap_nmos_w:
self.wc = cap_nmos_w

def can_create_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we can use any shape which
Expand All @@ -83,22 +79,23 @@ def can_create_from_shape_impl(self):
def parameters_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
self.r = self.shape.bbox().width() * self.l_gateayout.dbu / 2
self.l_gate = self.l_gateayout.get_info(self.l_gateayer)
self.r = self.shape.bbox().width() * self.layout.dbu / 2
self.lc = self.layout.get_info(self.lcayer)

def transformation_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
np_instance = draw_cap_nmos(
self.l_gateayout,
self.l_gate,
self.w_gate,
self.volt,
self.deepnwell,
self.pcmpgr,
np_instance = draw_cap_mos(
self.layout,
type="cap_nmos",
lc=self.lc,
wc=self.wc,
volt=self.volt,
deepnwell=self.deepnwell,
pcmpgr=self.pcmpgr,
)
write_cells = pya.CellInstArray(
np_instance.cell_index(),
Expand Down Expand Up @@ -130,31 +127,25 @@ def __init__(self):
self.Type_handle.add_choice("3.3V", "3.3V")
self.Type_handle.add_choice("5/6V", "5/6V")

self.param("l_gate", self.TypeDouble, "Length", default=cap_pmos_l, unit="um")
self.param("w_gate", self.TypeDouble, "Width", default=cap_pmos_w, unit="um")
self.param("lc", self.TypeDouble, "Length", default=cap_pmos_l, unit="um")
self.param("wc", self.TypeDouble, "Width", default=cap_pmos_w, unit="um")
self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2")
self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um")

def display_text_impl(self):
# Provide a descriptive text for the cell
return (
"cap_pmos(L="
+ ("%.3f" % self.l_gate)
+ ",W="
+ ("%.3f" % self.w_gate)
+ ")"
)
return "cap_pmos(LC=" + ("%.3f" % self.lc) + ",WC=" + ("%.3f" % self.wc) + ")"

def coerce_parameters_impl(self):
# We employ coerce_parameters_impl to decide whether the handle or the numeric parameter has changed.
# We also update the numerical value or the shape, depending on which on has not changed.
self.area = self.w_gate * self.l_gate
self.perim = 2 * (self.w_gate + self.l_gate)
self.area = self.wc * self.lc
self.perim = 2 * (self.wc + self.lc)
# w,l must be larger or equal than min. values.
if (self.l_gate) < cap_pmos_l:
self.l_gate = cap_pmos_l
if (self.w_gate) < cap_pmos_w:
self.w_gate = cap_pmos_w
if (self.lc) < cap_pmos_l:
self.lc = cap_pmos_l
if (self.wc) < cap_pmos_w:
self.wc = cap_pmos_w

def can_create_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we can use any shape which
Expand All @@ -164,22 +155,23 @@ def can_create_from_shape_impl(self):
def parameters_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
self.r = self.shape.bbox().width() * self.l_gateayout.dbu / 2
self.l_gate = self.l_gateayout.get_info(self.l_gateayer)
self.r = self.shape.bbox().width() * self.layout.dbu / 2
self.lc = self.layout.get_info(self.lcayer)

def transformation_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
np_instance = draw_cap_pmos(
self.l_gateayout,
self.l_gate,
self.w_gate,
self.volt,
self.deepnwell,
self.pcmpgr,
np_instance = draw_cap_mos(
self.layout,
type="cap_pmos",
lc=self.lc,
wc=self.wc,
volt=self.volt,
deepnwell=self.deepnwell,
pcmpgr=self.pcmpgr,
)
write_cells = pya.CellInstArray(
np_instance.cell_index(),
Expand Down Expand Up @@ -209,31 +201,25 @@ def __init__(self):
self.Type_handle.add_choice("3.3V", "3.3V")
self.Type_handle.add_choice("5/6V", "5/6V")

self.param("l_gate", self.TypeDouble, "Length", default=cap_nmos_b_l, unit="um")
self.param("w_gate", self.TypeDouble, "Width", default=cap_nmos_b_w, unit="um")
self.param("lc", self.TypeDouble, "Length", default=cap_nmos_b_l, unit="um")
self.param("wc", self.TypeDouble, "Width", default=cap_nmos_b_w, unit="um")
self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2")
self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um")

def display_text_impl(self):
# Provide a descriptive text for the cell
return (
"cap_nmos_b(L="
+ ("%.3f" % self.l_gate)
+ ",W="
+ ("%.3f" % self.w_gate)
+ ")"
)
return "cap_nmos_b(LC=" + ("%.3f" % self.lc) + ",WC=" + ("%.3f" % self.wc) + ")"

def coerce_parameters_impl(self):
# We employ coerce_parameters_impl to decide whether the handle or the numeric parameter has changed.
# We also update the numerical value or the shape, depending on which on has not changed.
self.area = self.w_gate * self.l_gate
self.perim = 2 * (self.w_gate + self.l_gate)
self.area = self.wc * self.lc
self.perim = 2 * (self.wc + self.lc)
# w,l must be larger or equal than min. values.
if (self.l_gate) < cap_nmos_b_l:
self.l_gate = cap_nmos_b_l
if (self.w_gate) < cap_nmos_b_w:
self.w_gate = cap_nmos_b_w
if (self.lc) < cap_nmos_b_l:
self.lc = cap_nmos_b_l
if (self.wc) < cap_nmos_b_w:
self.wc = cap_nmos_b_w

def can_create_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we can use any shape which
Expand All @@ -243,17 +229,23 @@ def can_create_from_shape_impl(self):
def parameters_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
self.r = self.shape.bbox().width() * self.l_gateayout.dbu / 2
self.l_gate = self.l_gateayout.get_info(self.l_gateayer)
self.r = self.shape.bbox().width() * self.layout.dbu / 2
self.lc = self.layout.get_info(self.lcayer)

def transformation_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
np_instance = draw_cap_nmos_b(
self.l_gateayout, self.l_gate, self.w_gate, self.volt
np_instance = draw_cap_mos(
self.layout,
type="cap_nmos_b",
lc=self.lc,
wc=self.wc,
volt=self.volt,
deepnwell=0, # self.deepnwell,
pcmpgr=0, # self.pcmpgr,
)
write_cells = pya.CellInstArray(
np_instance.cell_index(),
Expand Down Expand Up @@ -283,31 +275,25 @@ def __init__(self):
self.Type_handle.add_choice("3.3V", "3.3V")
self.Type_handle.add_choice("5/6V", "5/6V")

self.param("l_gate", self.TypeDouble, "Length", default=cap_pmos_b_l, unit="um")
self.param("w_gate", self.TypeDouble, "Width", default=cap_pmos_b_w, unit="um")
self.param("lc", self.TypeDouble, "Length", default=cap_pmos_b_l, unit="um")
self.param("wc", self.TypeDouble, "Width", default=cap_pmos_b_w, unit="um")
self.param("area", self.TypeDouble, "Area", readonly=True, unit="um^2")
self.param("perim", self.TypeDouble, "Perimeter", readonly=True, unit="um")

def display_text_impl(self):
# Provide a descriptive text for the cell
return (
"cap_pmos_b(L="
+ ("%.3f" % self.l_gate)
+ ",W="
+ ("%.3f" % self.w_gate)
+ ")"
)
return "cap_pmos_b(LC=" + ("%.3f" % self.lc) + ",WC=" + ("%.3f" % self.wc) + ")"

def coerce_parameters_impl(self):
# We employ coerce_parameters_impl to decide whether the handle or the numeric parameter has changed.
# We also update the numerical value or the shape, depending on which on has not changed.
self.area = self.w_gate * self.l_gate
self.perim = 2 * (self.w_gate + self.l_gate)
self.area = self.wc * self.lc
self.perim = 2 * (self.wc + self.lc)
# w,l must be larger or equal than min. values.
if (self.l_gate) < cap_pmos_b_l:
self.l_gate = cap_pmos_b_l
if (self.w_gate) < cap_pmos_b_w:
self.w_gate = cap_pmos_b_w
if (self.lc) < cap_pmos_b_l:
self.lc = cap_pmos_b_l
if (self.wc) < cap_pmos_b_w:
self.wc = cap_pmos_b_w

def can_create_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we can use any shape which
Expand All @@ -317,17 +303,23 @@ def can_create_from_shape_impl(self):
def parameters_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we set r and l from the shape's
# bounding box width and layer
self.r = self.shape.bbox().width() * self.l_gateayout.dbu / 2
self.l_gate = self.l_gateayout.get_info(self.l_gateayer)
self.r = self.shape.bbox().width() * self.layout.dbu / 2
self.lc = self.layout.get_info(self.lcayer)

def transformation_from_shape_impl(self):
# Implement the "Create PCell from shape" protocol: we use the center of the shape's
# bounding box to determine the transformation
return pya.Trans(self.shape.bbox().center())

def produce_impl(self):
np_instance = draw_cap_pmos_b(
self.l_gateayout, self.l_gate, self.w_gate, self.volt
np_instance = draw_cap_mos(
self.layout,
type="cap_pmos_b",
lc=self.lc,
wc=self.wc,
volt=self.volt,
deepnwell=0, # self.deepnwell,
pcmpgr=0, # self.pcmpgr,
)
write_cells = pya.CellInstArray(
np_instance.cell_index(),
Expand Down
Loading

0 comments on commit bfed737

Please sign in to comment.