| # Copyright 2022 GlobalFoundries PDK Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| ######################################################################################################################## |
| ## Diode Pcells Generators for Klayout of GF180MCU |
| ######################################################################################################################## |
| |
| import pya |
| |
| def number_spc_contacts(box_width, min_enc, cont_spacing, cont_width): |
| """ Calculate number of cantacts in a given dimensions and the free space for symmetry. |
| By getting the min enclosure,the width of the box,the width ans spacing of the contacts. |
| Parameters |
| ----- |
| box_width (double) : length you place the via or cont. in |
| min_enc (double) : spacing between the edge of the box and the first contact. |
| cont_spacing (double) : spacing between different contacts |
| cont_width (double) : contacts in the same direction |
| """ |
| spc_cont = box_width - 2 * min_enc |
| num_cont = int((spc_cont + cont_spacing) / (cont_width + cont_spacing)) |
| free_spc = box_width - (num_cont * cont_width + |
| (num_cont - 1) * cont_spacing) |
| return num_cont, free_spc |
| |
| def draw_np_diode(layout, l, w , volt, deepnwell, pcmpgr): |
| ''' |
| Usage:- |
| used to draw N+/LVPWELL diode (Outside DNWELL) by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of diff length |
| w : Float of diff width |
| volt : String of operating voltage of the diode [3.3V, 5V/6V] |
| deepnwell : Boolean of using Deep NWELL device |
| pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only |
| ''' |
| |
| # Define layers |
| dnwell = layout.layer(12 , 0 ) |
| lvpwell = layout.layer(204, 0 ) |
| comp = layout.layer(22 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| dualgate = layout.layer(55 , 0 ) |
| diode_mk = layout.layer(115, 5 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| pcmp2ncmp_spc = 0.48 * dbu_PERCISION |
| ncmp_w = 0.36 * dbu_PERCISION |
| pcmp_w = w * dbu_PERCISION |
| cmp_l = l * dbu_PERCISION |
| implant_comp_enc = 0.16 * dbu_PERCISION |
| comp_cont_enc = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| cont_min_spc = 0.28 * dbu_PERCISION |
| dualgate_cmp_enc = 0.24 * dbu_PERCISION |
| dg_enc_dnwell = 0.5 * dbu_PERCISION |
| dnwell_enc_lvpwell = 2.5 * dbu_PERCISION |
| lvpwell_enc_ncmp = 0.6 * dbu_PERCISION |
| lvpwell_enc_pcmp = 0.16 * dbu_PERCISION |
| min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION |
| tie_violat = 0 * dbu_PERCISION |
| pcmp_gr2dnw = 2.5 * dbu_PERCISION |
| |
| # Inserting np cell |
| cell_index = layout.add_cell("np_diode") |
| np_diode_cell = layout.cell(cell_index) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Inserting diffusion |
| if (cmp_l * ncmp_w) < min_cmp_area: |
| tie_violat = (min_cmp_area/ncmp_w - cmp_l)/2 |
| np_diode_cell.shapes(comp).insert(pya.Box(0, -tie_violat, ncmp_w, cmp_l+tie_violat)) |
| np_diode_cell.shapes(pplus).insert(pya.Box(-implant_comp_enc, -implant_comp_enc-tie_violat, ncmp_w+implant_comp_enc, cmp_l+implant_comp_enc+tie_violat)) |
| |
| np_diode_cell.shapes(comp).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| np_diode_cell.shapes(nplus).insert(pya.Box(ncmp_w+pcmp2ncmp_spc-implant_comp_enc, -implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| # Inserting metal |
| np_diode_cell.shapes(metal1).insert(pya.Box(0, -tie_violat, ncmp_w, cmp_l+tie_violat)) |
| np_diode_cell.shapes(metal1).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| |
| |
| # Inserting pcomp contacts |
| num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(ncmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(cmp_l, comp_cont_enc, cont_min_spc, cont_size) |
| ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_ncmp_con_1, num_ncmp_con_2) |
| np_diode_cell.insert(ncmp_con_arr) |
| |
| # Inserting ncomp contacts |
| num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(cmp_l, comp_cont_enc, cont_min_spc, cont_size) |
| pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_w+pcmp2ncmp_spc+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_pcmp_con_1, num_pcmp_con_2) |
| np_diode_cell.insert(pcmp_con_arr) |
| |
| # Inserting Deep NWELL layers |
| if deepnwell == True: |
| np_diode_cell.shapes(lvpwell).insert(pya.Box(-lvpwell_enc_pcmp, -lvpwell_enc_ncmp, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp, cmp_l+lvpwell_enc_ncmp)) |
| np_diode_cell.shapes(dnwell).insert(pya.Box(-lvpwell_enc_pcmp-dnwell_enc_lvpwell, -lvpwell_enc_ncmp-dnwell_enc_lvpwell, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp+dnwell_enc_lvpwell, cmp_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell)) |
| |
| # Inserting Deep NWELL P+ Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw, cmp_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw) |
| cmp_outer = pya.Box(-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw-ncmp_w, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw-ncmp_w, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+ncmp_w, cmp_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+ncmp_w) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| np_diode_cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw+implant_comp_enc, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw+implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw-implant_comp_enc, cmp_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw-implant_comp_enc) |
| pp_outer = pya.Box(-lvpwell_enc_pcmp-dnwell_enc_lvpwell-pcmp_gr2dnw-ncmp_w-implant_comp_enc, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-pcmp_gr2dnw-ncmp_w-implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+ncmp_w+implant_comp_enc, cmp_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+pcmp_gr2dnw+ncmp_w+implant_comp_enc) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| np_diode_cell.shapes(pplus).insert(pp_gr) |
| |
| if volt == "5/6V": |
| # Inserting marker |
| np_diode_cell.shapes(diode_mk).insert(pya.Box(-dualgate_cmp_enc, -dualgate_cmp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+dualgate_cmp_enc, cmp_l+dualgate_cmp_enc)) |
| # Inserting dualgate |
| if deepnwell == True: |
| np_diode_cell.shapes(dualgate).insert(pya.Box(-lvpwell_enc_pcmp-dnwell_enc_lvpwell-dg_enc_dnwell, -lvpwell_enc_ncmp-dnwell_enc_lvpwell-dg_enc_dnwell, ncmp_w+pcmp2ncmp_spc+pcmp_w+lvpwell_enc_ncmp+dnwell_enc_lvpwell+dg_enc_dnwell, cmp_l+lvpwell_enc_ncmp+dnwell_enc_lvpwell+dg_enc_dnwell)) |
| else: |
| np_diode_cell.shapes(dualgate).insert(pya.Box(-dualgate_cmp_enc, -dualgate_cmp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+dualgate_cmp_enc, cmp_l+dualgate_cmp_enc)) |
| else: |
| np_diode_cell.shapes(diode_mk).insert(pya.Box(-implant_comp_enc, -implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| np_diode_cell.flatten(True) |
| return np_diode_cell |
| |
| def draw_pn_diode(layout, l, w , volt, deepnwell, pcmpgr): |
| ''' |
| Usage:- |
| used to draw 3.3V P+/Nwell diode (Outside DNWELL) by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of diffusion length |
| w : Float of diffusion width |
| volt : String of operating voltage of the diode [3.3V, 5V/6V] |
| deepnwell : Boolean of using Deep NWELL device |
| pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only |
| ''' |
| |
| # Define layers |
| dnwell = layout.layer(12 , 0 ) |
| comp = layout.layer(22 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| nwell = layout.layer(21 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| dualgate = layout.layer(55 , 0 ) |
| diode_mk = layout.layer(115, 5 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| pcmp2ncmp_spc = 0.48 * dbu_PERCISION |
| ncmp_w = 0.36 * dbu_PERCISION |
| pcmp_w = w * dbu_PERCISION |
| cmp_l = l * dbu_PERCISION |
| implant_comp_enc = 0.16 * dbu_PERCISION |
| comp_cont_enc = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| cont_min_spc = 0.28 * dbu_PERCISION |
| |
| nwell_ncmp_enc = 0.12 * dbu_PERCISION |
| nwell_pcmp_enc = 0.43 * dbu_PERCISION |
| dg_enc_dnwell = 0.5 * dbu_PERCISION |
| dnwell_enc_nwell = 0.5 * dbu_PERCISION |
| min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION |
| tie_violat = 0 * dbu_PERCISION |
| pcmp_gr2dnw = 2.5 * dbu_PERCISION |
| dnwell_violat = 0 * dbu_PERCISION |
| |
| if volt == "5/6V" or deepnwell == True: |
| nwell_ncmp_enc = 0.16 * dbu_PERCISION |
| nwell_pcmp_enc = 0.6 * dbu_PERCISION |
| dnwell_violat = 0.12 * dbu_PERCISION |
| |
| # Inserting pn cell |
| cell_index = layout.add_cell("pn_diode") |
| pn_diode_cell = layout.cell(cell_index) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Inserting diffusion |
| if (cmp_l * ncmp_w) < min_cmp_area: |
| tie_violat = (min_cmp_area/ncmp_w - cmp_l)/2 |
| pn_diode_cell.shapes(comp).insert(pya.Box(0, -tie_violat, ncmp_w, cmp_l+tie_violat)) |
| pn_diode_cell.shapes(nplus).insert(pya.Box(-implant_comp_enc, -implant_comp_enc-tie_violat, ncmp_w+implant_comp_enc, cmp_l+implant_comp_enc+tie_violat)) |
| |
| pn_diode_cell.shapes(comp).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| pn_diode_cell.shapes(pplus).insert(pya.Box(ncmp_w+pcmp2ncmp_spc-implant_comp_enc, -implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| # Inserting metal |
| pn_diode_cell.shapes(metal1).insert(pya.Box(0, -tie_violat, ncmp_w, cmp_l+tie_violat)) |
| pn_diode_cell.shapes(metal1).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| |
| # Inserting nwell |
| pn_diode_cell.shapes(nwell).insert(pya.Box(-nwell_ncmp_enc-dnwell_violat, -nwell_pcmp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc, cmp_l+nwell_pcmp_enc)) |
| |
| |
| # Inserting pcomp contacts |
| num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(ncmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(cmp_l, comp_cont_enc, cont_min_spc, cont_size) |
| ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_ncmp_con_1, num_ncmp_con_2) |
| pn_diode_cell.insert(ncmp_con_arr) |
| |
| # Inserting ncomp contacts |
| num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(cmp_l, comp_cont_enc, cont_min_spc, cont_size) |
| pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_w+pcmp2ncmp_spc+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_pcmp_con_1, num_pcmp_con_2) |
| pn_diode_cell.insert(pcmp_con_arr) |
| |
| # Inserting Deep NWELL layers |
| if deepnwell == True: |
| pn_diode_cell.shapes(dnwell).insert(pya.Box(-nwell_ncmp_enc-dnwell_enc_nwell-dnwell_violat, -nwell_pcmp_enc-dnwell_enc_nwell, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc+dnwell_enc_nwell, cmp_l+nwell_pcmp_enc+dnwell_enc_nwell)) |
| |
| # Inserting Deep NWELL P+ Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-nwell_ncmp_enc-dnwell_enc_nwell-pcmp_gr2dnw-dnwell_violat, -nwell_pcmp_enc-dnwell_enc_nwell-pcmp_gr2dnw, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw, cmp_l+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw) |
| cmp_outer = pya.Box(-nwell_ncmp_enc-dnwell_enc_nwell-pcmp_gr2dnw-ncmp_w-dnwell_violat, -nwell_pcmp_enc-dnwell_enc_nwell-pcmp_gr2dnw-ncmp_w, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw+ncmp_w, cmp_l+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw+ncmp_w) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| pn_diode_cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-nwell_ncmp_enc-dnwell_enc_nwell-pcmp_gr2dnw+implant_comp_enc-dnwell_violat, -nwell_pcmp_enc-dnwell_enc_nwell-pcmp_gr2dnw+implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw-implant_comp_enc, cmp_l+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw-implant_comp_enc) |
| pp_outer = pya.Box(-nwell_ncmp_enc-dnwell_enc_nwell-pcmp_gr2dnw-ncmp_w-implant_comp_enc-dnwell_violat, -nwell_pcmp_enc-dnwell_enc_nwell-pcmp_gr2dnw-ncmp_w-implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw+ncmp_w+implant_comp_enc, cmp_l+nwell_pcmp_enc+dnwell_enc_nwell+pcmp_gr2dnw+ncmp_w+implant_comp_enc) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| pn_diode_cell.shapes(pplus).insert(pp_gr) |
| |
| if volt == "5/6V": |
| # Inserting dualgate |
| if deepnwell == True: |
| pn_diode_cell.shapes(dualgate).insert(pya.Box(-nwell_ncmp_enc-dnwell_enc_nwell-dg_enc_dnwell-dnwell_violat, -nwell_pcmp_enc-dnwell_enc_nwell-dg_enc_dnwell, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc+dnwell_enc_nwell+dg_enc_dnwell, cmp_l+nwell_pcmp_enc+dnwell_enc_nwell+dg_enc_dnwell)) |
| else: |
| pn_diode_cell.shapes(dualgate).insert(pya.Box(-nwell_ncmp_enc-dnwell_violat-dnwell_violat, -nwell_pcmp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+nwell_pcmp_enc, cmp_l+nwell_pcmp_enc)) |
| |
| # Inserting marker |
| pn_diode_cell.shapes(diode_mk).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| |
| pn_diode_cell.flatten(True) |
| return pn_diode_cell |
| |
| def draw_nwp_diode(layout, l, w , volt): |
| ''' |
| Usage:- |
| used to draw 3.3V Nwell/Psub diode by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of diff length |
| w : Float of diff width |
| volt : String of operating voltage of the diode [3.3V, 5V/6V] |
| ''' |
| |
| # Define layers |
| comp = layout.layer(22 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| nwell = layout.layer (21 , 0) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| dualgate = layout.layer(55 , 0 ) |
| well_diode_mk = layout.layer(153, 51) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| pcmp2ncmp_spc = 0.44 * dbu_PERCISION |
| ncmp_w = 0.36 * dbu_PERCISION |
| pcmp_w = w * dbu_PERCISION |
| cmp_l = l * dbu_PERCISION |
| implant_comp_enc = 0.16 * dbu_PERCISION |
| comp_cont_enc = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| cont_min_spc = 0.28 * dbu_PERCISION |
| dualgate_cmp_enc = 0.24 * dbu_PERCISION |
| |
| # Inserting nwp cell |
| cell_index = layout.add_cell("nwp_diode") |
| nwp_diode_cell = layout.cell(cell_index) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Inserting diffusion |
| nwp_diode_cell.shapes(comp).insert(pya.Box(0, 0, ncmp_w, cmp_l)) |
| nwp_diode_cell.shapes(pplus).insert(pya.Box(-implant_comp_enc, -implant_comp_enc, ncmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| nwp_diode_cell.shapes(comp).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| nwp_diode_cell.shapes(nplus).insert(pya.Box(ncmp_w+pcmp2ncmp_spc-implant_comp_enc, -implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| # Inserting nwell |
| nwp_diode_cell.shapes(nwell).insert(pya.Box(ncmp_w+pcmp2ncmp_spc-implant_comp_enc, -implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| # Inserting metal |
| nwp_diode_cell.shapes(metal1).insert(pya.Box(0, 0, ncmp_w, cmp_l)) |
| nwp_diode_cell.shapes(metal1).insert(pya.Box(ncmp_w+pcmp2ncmp_spc, 0, ncmp_w+pcmp2ncmp_spc+pcmp_w, cmp_l)) |
| |
| # Inserting pcomp contacts |
| num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(ncmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(cmp_l, comp_cont_enc, cont_min_spc, cont_size) |
| ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_ncmp_con_1, num_ncmp_con_2) |
| nwp_diode_cell.insert(ncmp_con_arr) |
| |
| # Inserting ncomp contacts |
| num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(pcmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(cmp_l, comp_cont_enc, cont_min_spc, cont_size) |
| pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_w+pcmp2ncmp_spc+pcmp_con_free_spc_1 / 2, pcmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_pcmp_con_1, num_pcmp_con_2) |
| nwp_diode_cell.insert(pcmp_con_arr) |
| |
| if volt == "5/6V": |
| # Inserting marker |
| nwp_diode_cell.shapes(well_diode_mk).insert(pya.Box(-dualgate_cmp_enc, -dualgate_cmp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+dualgate_cmp_enc, cmp_l+dualgate_cmp_enc)) |
| # Inserting dualgate |
| nwp_diode_cell.shapes(dualgate).insert(pya.Box(-dualgate_cmp_enc, -dualgate_cmp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+dualgate_cmp_enc, cmp_l+dualgate_cmp_enc)) |
| else: |
| # Inserting marker |
| nwp_diode_cell.shapes(well_diode_mk).insert(pya.Box(-implant_comp_enc, -implant_comp_enc, ncmp_w+pcmp2ncmp_spc+pcmp_w+implant_comp_enc, cmp_l+implant_comp_enc)) |
| |
| nwp_diode_cell.flatten(True) |
| return nwp_diode_cell |
| |
| def draw_dnwpw_diode(layout, l, w , volt): |
| ''' |
| Usage:- |
| used to draw LVPWELL/DNWELL diode by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of diff length |
| w : Float of diff width |
| volt : String of operating voltage of the diode [3.3V, 5V/6V] |
| ''' |
| |
| # Define layers |
| lvpwell = layout.layer(204, 0 ) |
| dnwell = layout.layer(12 , 0 ) |
| comp = layout.layer(22 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| nwell = layout.layer(21 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| dualgate = layout.layer(55 , 0 ) |
| well_diode_mk = layout.layer(153, 51) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| lvpwell_w = w * dbu_PERCISION |
| lvpwell_l = l * dbu_PERCISION |
| dnwell_lvpwell_enc = 2.5 * dbu_PERCISION |
| lvpwell_pcmp_enc = 0.12 * dbu_PERCISION |
| cmp_w = 0.36 * dbu_PERCISION |
| pcmp2ncmp_spc = 0.32 * dbu_PERCISION |
| implant_comp_enc = 0.16 * dbu_PERCISION |
| ncmp_ext = 0.56 * dbu_PERCISION |
| lvpwell_gr_spc = 5 * dbu_PERCISION |
| cont_spc_tol = 0.11 * dbu_PERCISION |
| comp_cont_enc = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| cont_min_spc = 0.25 * dbu_PERCISION |
| dualgate_lvpwell_enc = 3 * dbu_PERCISION |
| pcmp2ncmp_spc = 0.32 * dbu_PERCISION |
| lvpwell_pcmp_enc = 0.12 * dbu_PERCISION |
| |
| if volt == "5/6V": |
| pcmp2ncmp_spc = 0.36 * dbu_PERCISION |
| lvpwell_pcmp_enc = 0.16 * dbu_PERCISION |
| |
| # Inserting dnwpw cell |
| cell_index = layout.add_cell("dnwpw_diode") |
| dnwpw_diode_cell = layout.cell(cell_index) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Inserting lvpwell |
| dnwpw_diode_cell.shapes(lvpwell).insert(pya.Box(0, 0, lvpwell_w, lvpwell_l)) |
| |
| # Inserting dnwell |
| dnwpw_diode_cell.shapes(dnwell).insert(pya.Box(-dnwell_lvpwell_enc, -dnwell_lvpwell_enc, lvpwell_w+dnwell_lvpwell_enc, lvpwell_l+dnwell_lvpwell_enc)) |
| |
| # Inserting p diffusion |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(lvpwell_pcmp_enc, lvpwell_pcmp_enc , lvpwell_pcmp_enc+cmp_w, lvpwell_l-lvpwell_pcmp_enc)) # left |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(lvpwell_pcmp_enc-implant_comp_enc, lvpwell_pcmp_enc-implant_comp_enc , lvpwell_pcmp_enc+cmp_w+implant_comp_enc, lvpwell_l-lvpwell_pcmp_enc+implant_comp_enc)) |
| |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(lvpwell_w-lvpwell_pcmp_enc-cmp_w, lvpwell_pcmp_enc , lvpwell_w-lvpwell_pcmp_enc , lvpwell_l-lvpwell_pcmp_enc)) # right |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(lvpwell_w-lvpwell_pcmp_enc-cmp_w-implant_comp_enc, lvpwell_pcmp_enc-implant_comp_enc , lvpwell_w-lvpwell_pcmp_enc+implant_comp_enc , lvpwell_l-lvpwell_pcmp_enc+implant_comp_enc)) |
| |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(lvpwell_pcmp_enc+cmp_w, lvpwell_l-lvpwell_pcmp_enc-cmp_w , lvpwell_w-lvpwell_pcmp_enc-cmp_w , lvpwell_l-lvpwell_pcmp_enc)) # top |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(lvpwell_pcmp_enc+cmp_w+implant_comp_enc, lvpwell_l-lvpwell_pcmp_enc-cmp_w-implant_comp_enc , lvpwell_w-lvpwell_pcmp_enc-cmp_w-implant_comp_enc , lvpwell_l-lvpwell_pcmp_enc+implant_comp_enc)) # top |
| |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(lvpwell_pcmp_enc+cmp_w, lvpwell_pcmp_enc , lvpwell_w-lvpwell_pcmp_enc-cmp_w , lvpwell_pcmp_enc+cmp_w)) # bottom |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(lvpwell_pcmp_enc+cmp_w+implant_comp_enc, lvpwell_pcmp_enc-implant_comp_enc , lvpwell_w-lvpwell_pcmp_enc-cmp_w-implant_comp_enc, lvpwell_pcmp_enc+cmp_w+implant_comp_enc)) # bottom |
| |
| # Inserting pcomp metal |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(lvpwell_pcmp_enc, lvpwell_pcmp_enc , lvpwell_pcmp_enc+cmp_w, lvpwell_l-lvpwell_pcmp_enc)) # left |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(lvpwell_w-lvpwell_pcmp_enc-cmp_w, lvpwell_pcmp_enc , lvpwell_w-lvpwell_pcmp_enc , lvpwell_l-lvpwell_pcmp_enc)) # right |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(lvpwell_pcmp_enc+cmp_w, lvpwell_l-lvpwell_pcmp_enc-cmp_w , lvpwell_w-lvpwell_pcmp_enc-cmp_w , lvpwell_l-lvpwell_pcmp_enc)) # top |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(lvpwell_pcmp_enc+cmp_w, lvpwell_pcmp_enc , lvpwell_w-lvpwell_pcmp_enc-cmp_w , lvpwell_pcmp_enc+cmp_w)) # bottom |
| |
| # Inserting pcomp contacts |
| num_pcmp_left_con_1, pcmp_left_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_pcmp_left_con_2, pcmp_left_con_free_spc_2 = number_spc_contacts(lvpwell_l-2*lvpwell_pcmp_enc, comp_cont_enc, cont_min_spc, cont_size) |
| pcmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(lvpwell_pcmp_enc+pcmp_left_con_free_spc_1 / 2, lvpwell_pcmp_enc+pcmp_left_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_pcmp_left_con_1, num_pcmp_left_con_2) |
| dnwpw_diode_cell.insert(pcmp_left_con_arr) |
| |
| num_cmp_right_con_1, cmp_right_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_cmp_right_con_2, cmp_right_con_free_spc_2 = number_spc_contacts(lvpwell_l-2*lvpwell_pcmp_enc, comp_cont_enc, cont_min_spc, cont_size) |
| cmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(lvpwell_w-lvpwell_pcmp_enc-cmp_w+cmp_right_con_free_spc_1 / 2, lvpwell_pcmp_enc+cmp_right_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_cmp_right_con_1, num_cmp_right_con_2) |
| dnwpw_diode_cell.insert(cmp_right_con_arr) |
| |
| num_cmp_top_con_1, cmp_top_con_free_spc_1 = number_spc_contacts(lvpwell_w-2*lvpwell_pcmp_enc-2*cmp_w-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_cmp_top_con_2, cmp_top_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| cmp_top_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(lvpwell_pcmp_enc+cmp_w+cont_spc_tol+cmp_top_con_free_spc_1 / 2, lvpwell_l-lvpwell_pcmp_enc-cmp_w+cmp_top_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_cmp_top_con_1, num_cmp_top_con_2) |
| dnwpw_diode_cell.insert(cmp_top_con_arr) |
| |
| num_cmp_bot_con_1, cmp_bot_con_free_spc_1 = number_spc_contacts(lvpwell_w-2*lvpwell_pcmp_enc-2*cmp_w-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_cmp_bot_con_2, cmp_bot_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| cmp_bot_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(lvpwell_pcmp_enc+cmp_w+cont_spc_tol+cmp_bot_con_free_spc_1 / 2, lvpwell_pcmp_enc+cmp_bot_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_cmp_bot_con_1, num_cmp_bot_con_2) |
| dnwpw_diode_cell.insert(cmp_bot_con_arr) |
| |
| # Inserting n diffusion |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(lvpwell_pcmp_enc-pcmp2ncmp_spc-cmp_w, -ncmp_ext , lvpwell_pcmp_enc-pcmp2ncmp_spc, lvpwell_l+ncmp_ext)) |
| dnwpw_diode_cell.shapes(nplus).insert(pya.Box(lvpwell_pcmp_enc-pcmp2ncmp_spc-cmp_w-implant_comp_enc, -ncmp_ext-implant_comp_enc , lvpwell_pcmp_enc-pcmp2ncmp_spc+implant_comp_enc, lvpwell_l+ncmp_ext+implant_comp_enc)) |
| |
| # Inserting ncomp metal |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(lvpwell_pcmp_enc-pcmp2ncmp_spc-cmp_w, -ncmp_ext , lvpwell_pcmp_enc-pcmp2ncmp_spc, lvpwell_l+ncmp_ext)) |
| |
| # Inserting ncomp contacts |
| num_pcmp_con_1, pcmp_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_pcmp_con_2, pcmp_con_free_spc_2 = number_spc_contacts(lvpwell_l+2*ncmp_ext, comp_cont_enc, cont_min_spc, cont_size) |
| pcmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(lvpwell_pcmp_enc-pcmp2ncmp_spc-cmp_w+pcmp_con_free_spc_1 / 2, -ncmp_ext+pcmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_pcmp_con_1, num_pcmp_con_2) |
| dnwpw_diode_cell.insert(pcmp_con_arr) |
| |
| # Inserting GR |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(-lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc , lvpwell_l+lvpwell_gr_spc+cmp_w)) #left |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(-lvpwell_gr_spc-cmp_w-implant_comp_enc, -lvpwell_gr_spc-cmp_w-implant_comp_enc, -lvpwell_gr_spc+implant_comp_enc , lvpwell_l+lvpwell_gr_spc+cmp_w+implant_comp_enc)) |
| |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(lvpwell_w+lvpwell_gr_spc, -lvpwell_gr_spc-cmp_w, lvpwell_w+lvpwell_gr_spc+cmp_w , lvpwell_l+lvpwell_gr_spc+cmp_w)) #right |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(lvpwell_w+lvpwell_gr_spc-implant_comp_enc, -lvpwell_gr_spc-cmp_w-implant_comp_enc, lvpwell_w+lvpwell_gr_spc+cmp_w+implant_comp_enc , lvpwell_l+lvpwell_gr_spc+cmp_w+implant_comp_enc)) |
| |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(-lvpwell_gr_spc , lvpwell_l+lvpwell_gr_spc , lvpwell_w+lvpwell_gr_spc , lvpwell_l+lvpwell_gr_spc+cmp_w)) #top |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(-lvpwell_gr_spc+implant_comp_enc , lvpwell_l+lvpwell_gr_spc-implant_comp_enc , lvpwell_w+lvpwell_gr_spc-implant_comp_enc , lvpwell_l+lvpwell_gr_spc+cmp_w+implant_comp_enc)) |
| |
| dnwpw_diode_cell.shapes(comp).insert(pya.Box(-lvpwell_gr_spc , -lvpwell_gr_spc-cmp_w , lvpwell_w+lvpwell_gr_spc , -lvpwell_gr_spc)) #bot |
| dnwpw_diode_cell.shapes(pplus).insert(pya.Box(-lvpwell_gr_spc+implant_comp_enc , -lvpwell_gr_spc-cmp_w-implant_comp_enc , lvpwell_w+lvpwell_gr_spc-implant_comp_enc , -lvpwell_gr_spc+implant_comp_enc)) |
| |
| # Inserting GR metal |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(-lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc , lvpwell_l+lvpwell_gr_spc+cmp_w)) #left |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(lvpwell_w+lvpwell_gr_spc, -lvpwell_gr_spc-cmp_w, lvpwell_w+lvpwell_gr_spc+cmp_w , lvpwell_l+lvpwell_gr_spc+cmp_w)) #right |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(-lvpwell_gr_spc , lvpwell_l+lvpwell_gr_spc , lvpwell_w+lvpwell_gr_spc , lvpwell_l+lvpwell_gr_spc+cmp_w)) #top |
| dnwpw_diode_cell.shapes(metal1).insert(pya.Box(-lvpwell_gr_spc , -lvpwell_gr_spc-cmp_w , lvpwell_w+lvpwell_gr_spc , -lvpwell_gr_spc)) #bot |
| |
| # Inserting GR contacts |
| num_gr_left_con_1, gr_left_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_left_con_2, gr_left_con_free_spc_2 = number_spc_contacts(lvpwell_l+2*lvpwell_gr_spc+2*cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(-lvpwell_gr_spc-cmp_w+gr_left_con_free_spc_1 / 2, -lvpwell_gr_spc-cmp_w+gr_left_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_left_con_1, num_gr_left_con_2) |
| dnwpw_diode_cell.insert(gr_left_con_arr) |
| |
| num_gr_right_con_1, gr_right_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_right_con_2, gr_right_con_free_spc_2 = number_spc_contacts(lvpwell_l+2*lvpwell_gr_spc+2*cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(lvpwell_w+lvpwell_gr_spc+gr_right_con_free_spc_1 / 2, -lvpwell_gr_spc-cmp_w+gr_right_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_right_con_1, num_gr_right_con_2) |
| dnwpw_diode_cell.insert(gr_right_con_arr) |
| |
| num_gr_top_con_1, gr_top_con_free_spc_1 = number_spc_contacts(lvpwell_w+2*lvpwell_gr_spc-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_top_con_2, gr_top_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_top_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(-lvpwell_gr_spc+cont_spc_tol+gr_top_con_free_spc_1 / 2, lvpwell_l+lvpwell_gr_spc+gr_top_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_top_con_1, num_gr_top_con_2) |
| dnwpw_diode_cell.insert(gr_top_con_arr) |
| |
| num_gr_bot_con_1, gr_bot_con_free_spc_1 = number_spc_contacts(lvpwell_w+2*lvpwell_gr_spc-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_bot_con_2, gr_bot_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_bot_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(-lvpwell_gr_spc+cont_spc_tol+gr_bot_con_free_spc_1 / 2, -lvpwell_gr_spc-cmp_w+gr_bot_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_bot_con_1, num_gr_bot_con_2) |
| dnwpw_diode_cell.insert(gr_bot_con_arr) |
| |
| # Inserting marker |
| dnwpw_diode_cell.shapes(well_diode_mk).insert(pya.Box(0, 0, lvpwell_w, lvpwell_l)) |
| |
| if volt == "5/6V": |
| # Inserting dualgate |
| dnwpw_diode_cell.shapes(dualgate).insert(pya.Box(-dualgate_lvpwell_enc, -dualgate_lvpwell_enc, lvpwell_w+dualgate_lvpwell_enc, lvpwell_l+dualgate_lvpwell_enc)) |
| |
| dnwpw_diode_cell.flatten(True) |
| return dnwpw_diode_cell |
| |
| def draw_dnwps_diode(layout, l, w , volt): |
| ''' |
| Usage:- |
| used to draw LVPWELL/DNWELL diode by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of diff length |
| w : Float of diff width |
| volt : String of operating voltage of the diode [3.3V, 5V/6V] |
| ''' |
| |
| # Define layers |
| lvpwell = layout.layer(204, 0 ) |
| dnwell = layout.layer(12 , 0 ) |
| comp = layout.layer(22 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| nwell = layout.layer (21 , 0) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| dualgate = layout.layer(55 , 0 ) |
| well_diode_mk = layout.layer(153, 51) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| dnwell_w = w * dbu_PERCISION |
| dnwell_l = l * dbu_PERCISION |
| dnwell_pcmp_enc = 0.62 * dbu_PERCISION |
| cmp_w = 0.36 * dbu_PERCISION |
| pcmp2ncmp_spc = 0.32 * dbu_PERCISION |
| implant_comp_enc = 0.03 * dbu_PERCISION |
| ncmp_ext = 0.56 * dbu_PERCISION |
| lvpwell_gr_spc = 2.5 * dbu_PERCISION |
| cont_spc_tol = 0.11 * dbu_PERCISION |
| comp_cont_enc = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| cont_min_spc = 0.25 * dbu_PERCISION |
| dualgate_lvpwell_enc = 0.5 * dbu_PERCISION |
| |
| if volt == "5/6V": |
| dnwell_pcmp_enc = 0.66 * dbu_PERCISION |
| |
| |
| # Inserting dnwps cell |
| cell_index = layout.add_cell("dnwps_diode") |
| dnwps_diode_cell = layout.cell(cell_index) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Inserting dnwell |
| dnwps_diode_cell.shapes(dnwell).insert(pya.Box(0, 0, dnwell_w, dnwell_l)) |
| |
| # Inserting n diffusion |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(dnwell_pcmp_enc, dnwell_pcmp_enc , dnwell_pcmp_enc+cmp_w, dnwell_l-dnwell_pcmp_enc)) # left |
| dnwps_diode_cell.shapes(nplus).insert(pya.Box(dnwell_pcmp_enc-implant_comp_enc, dnwell_pcmp_enc-implant_comp_enc , dnwell_pcmp_enc+cmp_w+implant_comp_enc, dnwell_l-dnwell_pcmp_enc+implant_comp_enc)) |
| |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(dnwell_w-dnwell_pcmp_enc-cmp_w, dnwell_pcmp_enc , dnwell_w-dnwell_pcmp_enc , dnwell_l-dnwell_pcmp_enc)) # right |
| dnwps_diode_cell.shapes(nplus).insert(pya.Box(dnwell_w-dnwell_pcmp_enc-cmp_w-implant_comp_enc, dnwell_pcmp_enc-implant_comp_enc , dnwell_w-dnwell_pcmp_enc+implant_comp_enc , dnwell_l-dnwell_pcmp_enc+implant_comp_enc)) |
| |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(dnwell_pcmp_enc+cmp_w, dnwell_l-dnwell_pcmp_enc-cmp_w , dnwell_w-dnwell_pcmp_enc-cmp_w , dnwell_l-dnwell_pcmp_enc)) # top |
| dnwps_diode_cell.shapes(nplus).insert(pya.Box(dnwell_pcmp_enc+cmp_w+implant_comp_enc, dnwell_l-dnwell_pcmp_enc-cmp_w-implant_comp_enc , dnwell_w-dnwell_pcmp_enc-cmp_w-implant_comp_enc , dnwell_l-dnwell_pcmp_enc+implant_comp_enc)) # top |
| |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(dnwell_pcmp_enc+cmp_w, dnwell_pcmp_enc , dnwell_w-dnwell_pcmp_enc-cmp_w , dnwell_pcmp_enc+cmp_w)) # bottom |
| dnwps_diode_cell.shapes(nplus).insert(pya.Box(dnwell_pcmp_enc+cmp_w+implant_comp_enc, dnwell_pcmp_enc-implant_comp_enc , dnwell_w-dnwell_pcmp_enc-cmp_w-implant_comp_enc, dnwell_pcmp_enc+cmp_w+implant_comp_enc)) # bottom |
| |
| # Inserting ncomp metal |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(dnwell_pcmp_enc, dnwell_pcmp_enc , dnwell_pcmp_enc+cmp_w, dnwell_l-dnwell_pcmp_enc)) # left |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(dnwell_w-dnwell_pcmp_enc-cmp_w, dnwell_pcmp_enc , dnwell_w-dnwell_pcmp_enc , dnwell_l-dnwell_pcmp_enc)) # right |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(dnwell_pcmp_enc+cmp_w, dnwell_l-dnwell_pcmp_enc-cmp_w , dnwell_w-dnwell_pcmp_enc-cmp_w , dnwell_l-dnwell_pcmp_enc)) # top |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(dnwell_pcmp_enc+cmp_w, dnwell_pcmp_enc , dnwell_w-dnwell_pcmp_enc-cmp_w , dnwell_pcmp_enc+cmp_w)) # bottom |
| |
| # Inserting ncomp contacts |
| num_pcmp_left_con_1, pcmp_left_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_pcmp_left_con_2, pcmp_left_con_free_spc_2 = number_spc_contacts(dnwell_l-2*dnwell_pcmp_enc, comp_cont_enc, cont_min_spc, cont_size) |
| pcmp_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(dnwell_pcmp_enc+pcmp_left_con_free_spc_1 / 2, dnwell_pcmp_enc+pcmp_left_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_pcmp_left_con_1, num_pcmp_left_con_2) |
| dnwps_diode_cell.insert(pcmp_left_con_arr) |
| |
| num_cmp_right_con_1, cmp_right_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_cmp_right_con_2, cmp_right_con_free_spc_2 = number_spc_contacts(dnwell_l-2*dnwell_pcmp_enc, comp_cont_enc, cont_min_spc, cont_size) |
| cmp_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(dnwell_w-dnwell_pcmp_enc-cmp_w+cmp_right_con_free_spc_1 / 2, dnwell_pcmp_enc+cmp_right_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_cmp_right_con_1, num_cmp_right_con_2) |
| dnwps_diode_cell.insert(cmp_right_con_arr) |
| |
| num_cmp_top_con_1, cmp_top_con_free_spc_1 = number_spc_contacts(dnwell_w-2*dnwell_pcmp_enc-2*cmp_w-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_cmp_top_con_2, cmp_top_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| cmp_top_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(dnwell_pcmp_enc+cmp_w+cont_spc_tol+cmp_top_con_free_spc_1 / 2, dnwell_l-dnwell_pcmp_enc-cmp_w+cmp_top_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_cmp_top_con_1, num_cmp_top_con_2) |
| dnwps_diode_cell.insert(cmp_top_con_arr) |
| |
| num_cmp_bot_con_1, cmp_bot_con_free_spc_1 = number_spc_contacts(dnwell_w-2*dnwell_pcmp_enc-2*cmp_w-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_cmp_bot_con_2, cmp_bot_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| cmp_bot_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(dnwell_pcmp_enc+cmp_w+cont_spc_tol+cmp_bot_con_free_spc_1 / 2, dnwell_pcmp_enc+cmp_bot_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_cmp_bot_con_1, num_cmp_bot_con_2) |
| dnwps_diode_cell.insert(cmp_bot_con_arr) |
| |
| # Inserting GR |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(-lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc , dnwell_l+lvpwell_gr_spc+cmp_w)) #left |
| dnwps_diode_cell.shapes(pplus).insert(pya.Box(-lvpwell_gr_spc-cmp_w-implant_comp_enc, -lvpwell_gr_spc-cmp_w-implant_comp_enc, -lvpwell_gr_spc+implant_comp_enc , dnwell_l+lvpwell_gr_spc+cmp_w+implant_comp_enc)) |
| |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(dnwell_w+lvpwell_gr_spc, -lvpwell_gr_spc-cmp_w, dnwell_w+lvpwell_gr_spc+cmp_w , dnwell_l+lvpwell_gr_spc+cmp_w)) #right |
| dnwps_diode_cell.shapes(pplus).insert(pya.Box(dnwell_w+lvpwell_gr_spc-implant_comp_enc, -lvpwell_gr_spc-cmp_w-implant_comp_enc, dnwell_w+lvpwell_gr_spc+cmp_w+implant_comp_enc , dnwell_l+lvpwell_gr_spc+cmp_w+implant_comp_enc)) |
| |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(-lvpwell_gr_spc , dnwell_l+lvpwell_gr_spc , dnwell_w+lvpwell_gr_spc , dnwell_l+lvpwell_gr_spc+cmp_w)) #top |
| dnwps_diode_cell.shapes(pplus).insert(pya.Box(-lvpwell_gr_spc+implant_comp_enc , dnwell_l+lvpwell_gr_spc-implant_comp_enc , dnwell_w+lvpwell_gr_spc-implant_comp_enc , dnwell_l+lvpwell_gr_spc+cmp_w+implant_comp_enc)) |
| |
| dnwps_diode_cell.shapes(comp).insert(pya.Box(-lvpwell_gr_spc , -lvpwell_gr_spc-cmp_w , dnwell_w+lvpwell_gr_spc , -lvpwell_gr_spc)) #bot |
| dnwps_diode_cell.shapes(pplus).insert(pya.Box(-lvpwell_gr_spc+implant_comp_enc , -lvpwell_gr_spc-cmp_w-implant_comp_enc , dnwell_w+lvpwell_gr_spc-implant_comp_enc , -lvpwell_gr_spc+implant_comp_enc)) |
| |
| # Inserting GR metal |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(-lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc-cmp_w, -lvpwell_gr_spc , dnwell_l+lvpwell_gr_spc+cmp_w)) #left |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(dnwell_w+lvpwell_gr_spc, -lvpwell_gr_spc-cmp_w, dnwell_w+lvpwell_gr_spc+cmp_w , dnwell_l+lvpwell_gr_spc+cmp_w)) #right |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(-lvpwell_gr_spc , dnwell_l+lvpwell_gr_spc , dnwell_w+lvpwell_gr_spc , dnwell_l+lvpwell_gr_spc+cmp_w)) #top |
| dnwps_diode_cell.shapes(metal1).insert(pya.Box(-lvpwell_gr_spc , -lvpwell_gr_spc-cmp_w , dnwell_w+lvpwell_gr_spc , -lvpwell_gr_spc)) #bot |
| |
| # Inserting GR contacts |
| num_gr_left_con_1, gr_left_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_left_con_2, gr_left_con_free_spc_2 = number_spc_contacts(dnwell_l+2*lvpwell_gr_spc+2*cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_left_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(-lvpwell_gr_spc-cmp_w+gr_left_con_free_spc_1 / 2, -lvpwell_gr_spc-cmp_w+gr_left_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_left_con_1, num_gr_left_con_2) |
| dnwps_diode_cell.insert(gr_left_con_arr) |
| |
| num_gr_right_con_1, gr_right_con_free_spc_1 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_right_con_2, gr_right_con_free_spc_2 = number_spc_contacts(dnwell_l+2*lvpwell_gr_spc+2*cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_right_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(dnwell_w+lvpwell_gr_spc+gr_right_con_free_spc_1 / 2, -lvpwell_gr_spc-cmp_w+gr_right_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_right_con_1, num_gr_right_con_2) |
| dnwps_diode_cell.insert(gr_right_con_arr) |
| |
| num_gr_top_con_1, gr_top_con_free_spc_1 = number_spc_contacts(dnwell_w+2*lvpwell_gr_spc-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_top_con_2, gr_top_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_top_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(-lvpwell_gr_spc+cont_spc_tol+gr_top_con_free_spc_1 / 2, dnwell_l+lvpwell_gr_spc+gr_top_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_top_con_1, num_gr_top_con_2) |
| dnwps_diode_cell.insert(gr_top_con_arr) |
| |
| num_gr_bot_con_1, gr_bot_con_free_spc_1 = number_spc_contacts(dnwell_w+2*lvpwell_gr_spc-2*cont_spc_tol, comp_cont_enc, cont_min_spc, cont_size) |
| num_gr_bot_con_2, gr_bot_con_free_spc_2 = number_spc_contacts(cmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| gr_bot_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(-lvpwell_gr_spc+cont_spc_tol+gr_bot_con_free_spc_1 / 2, -lvpwell_gr_spc-cmp_w+gr_bot_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_gr_bot_con_1, num_gr_bot_con_2) |
| dnwps_diode_cell.insert(gr_bot_con_arr) |
| |
| # Inserting marker |
| dnwps_diode_cell.shapes(well_diode_mk).insert(pya.Box(0, 0, dnwell_w, dnwell_l)) |
| |
| if volt == "5/6V": |
| # Inserting dualgate |
| dnwps_diode_cell.shapes(dualgate).insert(pya.Box(-dualgate_lvpwell_enc, -dualgate_lvpwell_enc, dnwell_w+dualgate_lvpwell_enc, dnwell_l+dualgate_lvpwell_enc)) |
| |
| dnwps_diode_cell.flatten(True) |
| return dnwps_diode_cell |
| |
| def draw_sc_diode(layout, l, w , m, pcmpgr): |
| ''' |
| Usage:- |
| used to draw N+/LVPWELL diode (Outside DNWELL) by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of diff length |
| w : Float of diff width |
| m : Integer of number of fingers |
| pcmpgr : Boolean of using P+ Guard Ring for Deep NWELL devices only |
| ''' |
| |
| # Define layers |
| comp = layout.layer(22 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| dnwell = layout.layer(12 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| sc_diode_mk = layout.layer(241, 0 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| ncmp_metcmp_spc = 0.28 * dbu_PERCISION |
| ncmp_w = 0.36 * dbu_PERCISION |
| sc_w = w * dbu_PERCISION |
| sc_l = l * dbu_PERCISION |
| implant_comp_enc = 0.03 * dbu_PERCISION |
| comp_cont_enc = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| cont_min_spc = 0.25 * dbu_PERCISION |
| |
| metcmp_min_spc = 0.92 * dbu_PERCISION |
| met_cmp_enc_in = 0.23 * dbu_PERCISION |
| met_ncmp_enc = 0.46 * dbu_PERCISION |
| dnwell_cmp_enc_x = 0.76 * dbu_PERCISION |
| dnwell_cmp_enc_y = 1.4 * dbu_PERCISION |
| sc_mk_cmp_enc = 0.16 * dbu_PERCISION |
| met_conn_w = 0.23 * dbu_PERCISION |
| pcmp_gr2dnw = 2.5 * dbu_PERCISION |
| |
| ncmp_min_spc = 2*ncmp_metcmp_spc + sc_w |
| cmp_total_w = (m+1)*ncmp_w + m*ncmp_min_spc |
| |
| # Inserting np cell |
| cell_index = layout.add_cell("sc_diode") |
| sc_diode_cell = layout.cell(cell_index) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Inserting ncomp sc finger cell |
| ncmp_cell_index = layout.add_cell("ncomp") |
| ncmp_cell = layout.cell(ncmp_cell_index) |
| ncmp_cell.shapes(comp).insert(pya.Box.new(0, 0, ncmp_w, sc_l)) |
| ncmp_cell.shapes(nplus).insert(pya.Box.new(-implant_comp_enc, -implant_comp_enc, ncmp_w+implant_comp_enc, sc_l+implant_comp_enc)) |
| ncmp_cell.shapes(metal1).insert(pya.Box.new(0 , -met_cmp_enc_in, ncmp_w, sc_l)) |
| ## Inserting pcomp contacts |
| num_ncmp_con_1, ncmp_con_free_spc_1 = number_spc_contacts(ncmp_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_ncmp_con_2, ncmp_con_free_spc_2 = number_spc_contacts(sc_l, comp_cont_enc, cont_min_spc, cont_size) |
| ncmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_con_free_spc_1 / 2, ncmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_ncmp_con_1, num_ncmp_con_2) |
| ncmp_cell.insert(ncmp_con_arr) |
| |
| # Inserting comp_metal sc finger cell |
| met_cmp_cell_index = layout.add_cell("comp_metal") |
| met_cmp_cell = layout.cell(met_cmp_cell_index) |
| met_cmp_cell.shapes(comp).insert(pya.Box.new(0, 0, sc_w, sc_l)) |
| |
| if m > 1: |
| met_cmp_cell.shapes(metal1).insert(pya.Box.new(0, 0, sc_w, sc_l+met_cmp_enc_in)) |
| else: |
| met_cmp_cell.shapes(metal1).insert(pya.Box.new(0, 0, sc_w, sc_l)) |
| |
| ## Inserting comp_metal contacts |
| num_met_cmp_con_1, met_cmp_con_free_spc_1 = number_spc_contacts(sc_w, comp_cont_enc, cont_min_spc, cont_size) |
| num_met_cmp_con_2, met_cmp_con_free_spc_2 = number_spc_contacts(sc_l, comp_cont_enc, cont_min_spc, cont_size) |
| met_cmp_con_arr = pya.CellInstArray(cont_cell.cell_index(), pya.Trans( |
| pya.Point(met_cmp_con_free_spc_1 / 2, met_cmp_con_free_spc_2/2)), |
| pya.Vector(cont_min_spc + cont_size, 0), pya.Vector(0,cont_min_spc + cont_size), |
| num_met_cmp_con_1, num_met_cmp_con_2) |
| met_cmp_cell.insert(met_cmp_con_arr) |
| |
| # Inserting ncomp fingers |
| ncmp_arr = pya.CellInstArray(ncmp_cell.cell_index(), pya.Trans( |
| pya.Point(0, 0)), |
| pya.Vector(ncmp_min_spc + ncmp_w, 0), pya.Vector(0,ncmp_min_spc + ncmp_w), |
| m+1, 1) |
| sc_diode_cell.insert(ncmp_arr) |
| |
| # Inserting metal comp fingers |
| metcmp_arr = pya.CellInstArray(met_cmp_cell.cell_index(), pya.Trans( |
| pya.Point(ncmp_w+ncmp_metcmp_spc, 0)), |
| pya.Vector(metcmp_min_spc + sc_w, 0), pya.Vector(0,metcmp_min_spc + sc_w), |
| m, 1) |
| sc_diode_cell.insert(metcmp_arr) |
| |
| # Inserting Deep NWELL |
| sc_diode_cell.shapes(dnwell).insert(pya.Box(-dnwell_cmp_enc_x, -dnwell_cmp_enc_y, cmp_total_w+dnwell_cmp_enc_x, sc_l+dnwell_cmp_enc_y)) |
| |
| # Inserting Deep NWELL P+ Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_cmp_enc_x-pcmp_gr2dnw, -dnwell_cmp_enc_y-pcmp_gr2dnw, cmp_total_w+dnwell_cmp_enc_x+pcmp_gr2dnw, sc_l+dnwell_cmp_enc_y+pcmp_gr2dnw) |
| cmp_outer = pya.Box(-dnwell_cmp_enc_x-ncmp_w-pcmp_gr2dnw, -dnwell_cmp_enc_y-ncmp_w-pcmp_gr2dnw, cmp_total_w+dnwell_cmp_enc_x+ncmp_w+pcmp_gr2dnw, sc_l+dnwell_cmp_enc_y+ncmp_w+pcmp_gr2dnw) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| sc_diode_cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_cmp_enc_x+implant_comp_enc-pcmp_gr2dnw, -dnwell_cmp_enc_y+implant_comp_enc-pcmp_gr2dnw, cmp_total_w+dnwell_cmp_enc_x-implant_comp_enc+pcmp_gr2dnw, sc_l+dnwell_cmp_enc_y-implant_comp_enc+pcmp_gr2dnw) |
| pp_outer = pya.Box(-dnwell_cmp_enc_x-ncmp_w-implant_comp_enc-pcmp_gr2dnw, -dnwell_cmp_enc_y-ncmp_w-implant_comp_enc-pcmp_gr2dnw, cmp_total_w+dnwell_cmp_enc_x+ncmp_w+implant_comp_enc+pcmp_gr2dnw, sc_l+dnwell_cmp_enc_y+ncmp_w+implant_comp_enc+pcmp_gr2dnw) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| sc_diode_cell.shapes(pplus).insert(pp_gr) |
| |
| # Inserting sc_marker |
| sc_diode_cell.shapes(sc_diode_mk).insert(pya.Box(-sc_mk_cmp_enc, -sc_mk_cmp_enc, cmp_total_w+sc_mk_cmp_enc, sc_l+sc_mk_cmp_enc)) |
| |
| # Inserting connection metal [bottom] |
| sc_diode_cell.shapes(metal1).insert(pya.Box(0, -met_ncmp_enc, cmp_total_w, -met_ncmp_enc+met_conn_w)) |
| |
| # Inserting connection metal [Top] |
| if m > 1: |
| sc_diode_cell.shapes(metal1).insert(pya.Box(ncmp_w+ncmp_metcmp_spc, sc_l+met_ncmp_enc-met_conn_w, cmp_total_w-ncmp_w-ncmp_metcmp_spc, sc_l+met_ncmp_enc)) |
| |
| sc_diode_cell.flatten(True) |
| return sc_diode_cell |