Source code for gf180mcu.cap_mos

import gdsfactory as gf
import numpy as np
from gdsfactory.typings import Float2, LayerSpec

from gf180mcu.layers import layer
from gf180mcu.via_generator import via_generator, via_stack


[docs] @gf.cell def cap_mos_inst( lc: float = 0.1, wc: float = 0.1, cmp_w: float = 0.1, con_w: float = 0.1, pl_l: float = 0.1, cmp_ext: float = 0.1, pl_ext: float = 0.1, implant_layer: LayerSpec = layer["nplus"], implant_enc: Float2 = (0.1, 0.1), label: bool = False, g_label: str = "", ) -> gf.Component: """Returns mos cap simple instance. Args: lc : length of mos_cap. ws : width of mos_cap. cmp_w : width of layer["comp"]. con_w : min width of comp contain contact. pl_l : length od layer["poly2"]. cmp_ext : comp extension beyond poly2. pl_ext : poly2 extension beyond comp. implant_layer : Layer of implant [nplus,pplus]. implant_enc : enclosure of implant_layer to comp. label : 1 to add labels. g_label : gate label. """ c_inst = gf.Component() cmp = c_inst.add_ref(gf.components.rectangle(size=(cmp_w, wc), layer=layer["comp"])) cap_mk = c_inst.add_ref( gf.components.rectangle( size=(cmp.dxsize, cmp.dysize), layer=layer["mos_cap_mk"] ) ) cap_mk.dxmin = cmp.dxmin cap_mk.dymin = cmp.dymin if (column_pitch := cmp_w - con_w) != 0: c_inst.add_ref( component=via_stack( x_range=(cmp.dxmin, cmp.dxmin + con_w), y_range=(cmp.dymin, cmp.dymax), base_layer=layer["comp"], metal_level=1, ), columns=2, column_pitch=column_pitch, ) # comp contact else: c_inst.add_ref( component=via_stack( x_range=(cmp.dxmin, cmp.dxmin + con_w), y_range=(cmp.dymin, cmp.dymax), base_layer=layer["comp"], metal_level=1, ) ) imp_rect = c_inst.add_ref( gf.components.rectangle( size=( cmp.dxsize + (2 * implant_enc[0]), cmp.dysize + (2 * implant_enc[1]), ), layer=implant_layer, ) ) imp_rect.dxmin = cmp.dxmin - implant_enc[0] imp_rect.dymin = cmp.dymin - implant_enc[1] poly = c_inst.add_ref( gf.components.rectangle(size=(lc, pl_l), layer=layer["poly2"]) ) poly.dxmin = cmp.dxmin + cmp_ext poly.dymin = cmp.dymin - pl_ext pl_con_el = via_stack( x_range=(poly.dxmin, poly.dxmax), y_range=(poly.dymin, poly.dymin + con_w), base_layer=layer["poly2"], metal_level=1, ) if (column_pitch := pl_l - con_w) != 0: pl_con = c_inst.add_ref(component=pl_con_el, rows=2, row_pitch=pl_l - con_w) else: pl_con = c_inst.add_ref(component=pl_con_el) # Gate labels_generation if label == 1: c_inst.add_label( g_label, position=( pl_con.dxmin + (pl_con.dxsize / 2), pl_con.dymin + (pl_con_el.dysize / 2), ), layer=layer["metal1_label"], ) pl_m1 = c_inst.add_ref( gf.components.rectangle( size=(pl_con.dxsize, pl_con.dysize), layer=layer["metal1"] ) ) pl_m1.dxmin = pl_con.dxmin pl_m1.dymin = pl_con.dymin return c_inst
[docs] @gf.cell def cap_mos( type: str = "cap_nmos", lc: float = 0.1, wc: float = 0.1, volt: str = "3.3V", deepnwell: bool = False, pcmpgr: bool = False, label: bool = False, g_label: str = "", sd_label: str = "", ) -> gf.Component: """Usage:- used to draw NMOS capacitor (Outside DNWELL) by specifying parameters Arguments:- l : Float of diff length w : Float of diff width. """ c = gf.Component("cap_mos_dev") con_size = 0.22 con_sp = 0.28 con_comp_enc = 0.07 con_pl_enc = 0.07 cmp_ext = 0.15 - con_comp_enc pl_ext = 0.17 - con_pl_enc np_enc_gate: float = 0.23 np_enc_cmp: float = 0.16 dg_enc_cmp = 0.24 dg_enc_poly = 0.4 lvpwell_enc_ncmp = 0.43 dn_enc_lvpwell = 2.5 grw = 0.36 m1_w = 1 pcmpgr_enc_dn = 2.5 m1_ext = 0.82 comp_pp_enc: float = 0.16 dnwell_enc_pcmp = 1.1 # end_cap: float = 0.22 cmp_ed_w = con_size + (2 * con_comp_enc) cmp_w = (2 * (cmp_ed_w + cmp_ext)) + lc end_cap = pl_ext + cmp_ed_w pl_l = wc + (2 * end_cap) if "cap_nmos" in type: implant_layer = layer["nplus"] else: implant_layer = layer["pplus"] c_inst = c.add_ref( cap_mos_inst( cmp_w=cmp_w, lc=lc, wc=wc, pl_l=pl_l, cmp_ext=cmp_ed_w + cmp_ext, con_w=cmp_ed_w, pl_ext=end_cap, implant_layer=implant_layer, implant_enc=(np_enc_cmp, np_enc_gate), label=label, g_label=g_label, ) ) cmp_m1_polys = gf.Component(base=c_inst.cell.base).get_polygons_points()[ layer["metal1"] ] cmp_m1_xmin = np.min(cmp_m1_polys[0][:, 0]) cmp_m1_xmax = np.max(cmp_m1_polys[0][:, 0]) cmp_m1_ymax = np.max(cmp_m1_polys[0][:, 1]) # cmp_m1 = c.add_ref(gf.components.rectangle(size=(m1_w,w+m1_ext),layer=layer["metal1"])) cmp_m1_v = c.add_ref( component=gf.components.rectangle( size=(m1_w, wc + m1_ext), layer=layer["metal1"] ), rows=1, columns=2, column_pitch=m1_w + cmp_w - 2 * cmp_ed_w, ) cmp_m1_v.dxmin = cmp_m1_xmin - (m1_w - (cmp_m1_xmax - cmp_m1_xmin)) cmp_m1_v.dymax = cmp_m1_ymax cmp_m1_h = c.add_ref( gf.components.rectangle(size=(cmp_m1_v.dxsize, m1_w), layer=layer["metal1"]) ) cmp_m1_h.dxmin = cmp_m1_v.dxmin cmp_m1_h.dymax = cmp_m1_v.dymin # sd labels generation if label == 1: c.add_label( sd_label, position=( cmp_m1_h.dxmin + (cmp_m1_h.dxsize / 2), cmp_m1_h.dymin + (cmp_m1_h.dysize / 2), ), layer=layer["metal1_label"], ) # dualgate if volt == "5/6V": dg = c.add_ref( gf.components.rectangle( size=( c_inst.dxsize + (2 * dg_enc_cmp), c_inst.dysize + (2 * dg_enc_poly), ), layer=layer["dualgate"], ) ) dg.dxmin = c_inst.dxmin - dg_enc_cmp dg.dymin = c_inst.dymin - dg_enc_poly cmp_polys = gf.Component(base=c_inst.cell.base).get_polygons_points()[layer["comp"]] cmp_xmin = np.min(cmp_polys[0][:, 0]) cmp_ymin = np.min(cmp_polys[0][:, 1]) cmp_xmax = np.max(cmp_polys[0][:, 0]) cmp_ymax = np.max(cmp_polys[0][:, 1]) if "_b" in type: if "cap_nmos" in type: nwell = c.add_ref( gf.components.rectangle( size=( cmp_xmax - cmp_xmin + (2 * np_enc_cmp), cmp_ymax - cmp_ymin + (2 * np_enc_gate), ), layer=layer["nwell"], ) ) nwell.dxmin = cmp_xmin - np_enc_cmp nwell.dymin = cmp_ymin - np_enc_gate else: lvpwell = c.add_ref( gf.components.rectangle( size=( cmp_xmax - cmp_xmin + (2 * np_enc_cmp), cmp_ymax - cmp_ymin + (2 * np_enc_gate), ), layer=layer["lvpwell"], ) ) lvpwell.dxmin = cmp_xmin - np_enc_cmp lvpwell.dymin = cmp_ymin - np_enc_gate if deepnwell == 1: if type == "cap_nmos": lvp_rect = c.add_ref( gf.components.rectangle( size=( c_inst.dxsize + (2 * lvpwell_enc_ncmp), c_inst.dysize + (2 * lvpwell_enc_ncmp), ), layer=layer["lvpwell"], ) ) lvp_rect.dxmin = c_inst.dxmin - lvpwell_enc_ncmp lvp_rect.dymin = c_inst.dymin - lvpwell_enc_ncmp dn_rect = c.add_ref( gf.components.rectangle( size=( lvp_rect.dxsize + (2 * dn_enc_lvpwell), lvp_rect.dysize + (2 * dn_enc_lvpwell), ), layer=layer["nwell"], ) ) dn_rect.dxmin = lvp_rect.dxmin - dn_enc_lvpwell dn_rect.dymin = lvp_rect.dymin - dn_enc_lvpwell else: dn_rect = c.add_ref( gf.components.rectangle( size=( c_inst.dxsize + (2 * dnwell_enc_pcmp), c_inst.dysize + (2 * dnwell_enc_pcmp), ), layer=layer["nwell"], ) ) dn_rect.dxmin = c_inst.dxmin - dnwell_enc_pcmp dn_rect.dymin = c_inst.dymin - dnwell_enc_pcmp if pcmpgr == 1: c_temp_gr = gf.Component("temp_store guard ring") rect_pcmpgr_in = c_temp_gr.add_ref( gf.components.rectangle( size=( (dn_rect.dxmax - dn_rect.dxmin) + 2 * pcmpgr_enc_dn, (dn_rect.dymax - dn_rect.dymin) + 2 * pcmpgr_enc_dn, ), layer=layer["comp"], ) ) rect_pcmpgr_in.dmove( (dn_rect.dxmin - pcmpgr_enc_dn, dn_rect.dymin - pcmpgr_enc_dn) ) rect_pcmpgr_out = c_temp_gr.add_ref( gf.components.rectangle( size=( (rect_pcmpgr_in.dxmax - rect_pcmpgr_in.dxmin) + 2 * grw, (rect_pcmpgr_in.dymax - rect_pcmpgr_in.dymin) + 2 * grw, ), layer=layer["comp"], ) ) rect_pcmpgr_out.dmove( (rect_pcmpgr_in.dxmin - grw, rect_pcmpgr_in.dymin - grw) ) c.add_ref( gf.boolean( A=rect_pcmpgr_out, B=rect_pcmpgr_in, operation="A-B", layer=layer["comp"], ) ) # guardring Bullk psdm_in = c_temp_gr.add_ref( gf.components.rectangle( size=( (rect_pcmpgr_in.dxmax - rect_pcmpgr_in.dxmin) - 2 * comp_pp_enc, (rect_pcmpgr_in.dymax - rect_pcmpgr_in.dymin) - 2 * comp_pp_enc, ), layer=layer["pplus"], ) ) psdm_in.dmove( ( rect_pcmpgr_in.dxmin + comp_pp_enc, rect_pcmpgr_in.dymin + comp_pp_enc, ) ) psdm_out = c_temp_gr.add_ref( gf.components.rectangle( size=( (rect_pcmpgr_out.dxmax - rect_pcmpgr_out.dxmin) + 2 * comp_pp_enc, (rect_pcmpgr_out.dymax - rect_pcmpgr_out.dymin) + 2 * comp_pp_enc, ), layer=layer["pplus"], ) ) psdm_out.dmove( ( rect_pcmpgr_out.dxmin - comp_pp_enc, rect_pcmpgr_out.dymin - comp_pp_enc, ) ) c.add_ref( gf.boolean(A=psdm_out, B=psdm_in, operation="A-B", layer=layer["pplus"]) ) # psdm # generatingg contacts c.add_ref( via_generator( x_range=( rect_pcmpgr_in.dxmin + con_size, rect_pcmpgr_in.dxmax - con_size, ), y_range=(rect_pcmpgr_out.dymin, rect_pcmpgr_in.dymin), via_enclosure=(con_comp_enc, con_comp_enc), via_layer=layer["contact"], via_size=(con_size, con_size), via_spacing=(con_sp, con_sp), ) ) # bottom contact c.add_ref( via_generator( x_range=( rect_pcmpgr_in.dxmin + con_size, rect_pcmpgr_in.dxmax - con_size, ), y_range=(rect_pcmpgr_in.dymax, rect_pcmpgr_out.dymax), via_enclosure=(con_comp_enc, con_comp_enc), via_layer=layer["contact"], via_size=(con_size, con_size), via_spacing=(con_sp, con_sp), ) ) # upper contact c.add_ref( via_generator( x_range=(rect_pcmpgr_out.dxmin, rect_pcmpgr_in.dxmin), y_range=( rect_pcmpgr_in.dymin + con_size, rect_pcmpgr_in.dymax - con_size, ), via_enclosure=(con_comp_enc, con_comp_enc), via_layer=layer["contact"], via_size=(con_size, con_size), via_spacing=(con_sp, con_sp), ) ) # right contact c.add_ref( via_generator( x_range=(rect_pcmpgr_in.dxmax, rect_pcmpgr_out.dxmax), y_range=( rect_pcmpgr_in.dymin + con_size, rect_pcmpgr_in.dymax - con_size, ), via_enclosure=(con_comp_enc, con_comp_enc), via_layer=layer["contact"], via_size=(con_size, con_size), via_spacing=(con_sp, con_sp), ) ) # left contact comp_m1_in = c_temp_gr.add_ref( gf.components.rectangle( size=(rect_pcmpgr_in.dxsize, rect_pcmpgr_in.dysize), layer=layer["metal1"], ) ) comp_m1_out = c_temp_gr.add_ref( gf.components.rectangle( size=( (comp_m1_in.dxsize) + 2 * grw, (comp_m1_in.dysize) + 2 * grw, ), layer=layer["metal1"], ) ) comp_m1_out.dmove((rect_pcmpgr_in.dxmin - grw, rect_pcmpgr_in.dymin - grw)) c.add_ref( gf.boolean( A=rect_pcmpgr_out, B=rect_pcmpgr_in, operation="A-B", layer=layer["metal1"], ) ) # guardring metal1 return c
if __name__ == "__main__": c = cap_mos() c.show()