| # 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. |
| |
| ######################################################################################################################## |
| ## MOSFET Pcells Generators for Klayout of GF180MCU |
| ######################################################################################################################## |
| |
| import pya |
| |
| tol = 1.05 |
| |
| def draw_nmos(layout, l, w, ld, nf, grw, bulk, volt, deepnwell, pcmpgr): |
| ''' |
| Usage:- |
| used to draw NMOS transistor by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of gate length |
| w : Float of gate width |
| ld : Float of diffusion length |
| nf : Integer of number of fingers |
| grw : Float of guard ring width [If enabled] |
| bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] |
| volt : String of operating voltage of the MOSFET [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 ) |
| dualgate = layout.layer(55 , 0 ) |
| v5_xtor = layout.layer(112, 1 ) |
| comp = layout.layer(22 , 0 ) |
| poly2 = layout.layer(30 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| nf = int(nf) |
| grw = grw * dbu_PERCISION |
| ld = ld * dbu_PERCISION |
| l = l * dbu_PERCISION |
| w = w * dbu_PERCISION |
| cmp2cont = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| np_enc_cmp = 0.16 * dbu_PERCISION |
| pp_enc_cmp = 0.16 * dbu_PERCISION |
| cont2ply = 0.15 * dbu_PERCISION |
| ply_ext_cmp = 0.22 * dbu_PERCISION |
| np_enc_gate = 0.23 * dbu_PERCISION |
| cont2cont = 0.28 * dbu_PERCISION |
| dg_enc_ply = 0.4 * dbu_PERCISION |
| dg_enc_cmp = 0.24 * dbu_PERCISION |
| cmp2cmp = 0.28 * dbu_PERCISION |
| ply2gr = 0.1 * dbu_PERCISION |
| ld_violat = 0 * dbu_PERCISION |
| tie_violat = 0 * dbu_PERCISION |
| metal_violat = 0.01 * dbu_PERCISION |
| min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION |
| dg_enc_dnwell = 0.5 * dbu_PERCISION |
| lvpwell_enc_ncmp = 0.43 * dbu_PERCISION |
| lvpwell_enc_pcmp = 0.12 * dbu_PERCISION |
| dnwell_enc_lvpwell = 2.5 * dbu_PERCISION |
| pcmp_gr2dnw = 2.5 * dbu_PERCISION |
| gr_w = 0.36 * dbu_PERCISION |
| |
| if deepnwell == True: |
| cmp2cmp = 0.36 * dbu_PERCISION |
| ply2gr = 0.3 * dbu_PERCISION |
| |
| if volt == "5V" or volt == "6V": |
| lvpwell_enc_ncmp = 0.6 * dbu_PERCISION |
| lvpwell_enc_pcmp = 0.16 * dbu_PERCISION |
| cmp2cmp = 0.36 * dbu_PERCISION |
| ply2gr = 0.3 * dbu_PERCISION |
| cmp2cmp = 0.36 * dbu_PERCISION |
| |
| if w < cont_size+2*cmp2cont: |
| if nf == 1: |
| if volt == "5V" or volt == "6V": |
| ld_violat = 0.22 * dbu_PERCISION |
| else: |
| ld_violat = 0.02 * dbu_PERCISION |
| |
| # Inserting NMOS cell |
| cell_index = layout.add_cell("nmos") |
| cell = layout.cell(cell_index) |
| |
| w_changed = False |
| |
| # Inserting diffusion |
| if w < cont_size+2*cmp2cont: |
| cell.shapes(comp).insert(pya.Box(0, (cont_size+2*cmp2cont - w)/2, (2 * (ld + ld_violat) + l + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), w + (cont_size+2*cmp2cont - w)/2)) |
| w = cont_size+2*cmp2cont |
| w_changed = True |
| else: |
| cell.shapes(comp).insert(pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w)) |
| |
| cell.shapes(nplus).insert(pya.Box(-np_enc_cmp, -np_enc_gate, (2 * (ld + ld_violat) + l + np_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), w + np_enc_gate)) |
| |
| # Inserting gate/s |
| # Inserting a gate cell |
| gate_cell_index = layout.add_cell("gate") |
| gate_cell = layout.cell(gate_cell_index) |
| gate_cell.shapes(poly2).insert(pya.Box(ld + ld_violat, -ply_ext_cmp, (ld + ld_violat + l), (w + ply_ext_cmp))) |
| |
| # adding gate array |
| cell.insert(pya.CellInstArray.new(gate_cell_index, pya.Trans.new(pya.Point.new(0, 0)), |
| pya.Point.new(ld + ld_violat + l + cont2ply - cmp2cont, 0), pya.Point.new(0, 0), int(nf), 1)) |
| |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| |
| # Inserting shapes now into the *contact* cell |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Contact array count and postions |
| nx = int((ld - (cont_size+cmp2cont+cont2ply))/(cont2cont+cont_size)) + 1 |
| ny = int((w - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| dx = (ld - nx * cont_size - (nx - 1) * cont2cont)*cmp2cont/cont_size |
| dy = (w - ny * cont_size - (ny - 1) * cont2cont)/2 |
| |
| # adding contact array and metals |
| # Left contacts |
| if not (w_changed == True and nf > 1) and (ld >= 440): |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dx, dy)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| # Left metal |
| cell.shapes(metal1).insert(pya.Box(-metal_violat, -metal_violat, ld + metal_violat - (cont_size-2*cmp2cont), w + metal_violat)) |
| |
| # Adding diffusion to avoid contact violation |
| if nf == 1 and w_changed == True: |
| cell.shapes(comp).insert(pya.Box(0, 0, ld - (cont_size-2*cmp2cont), w)) |
| |
| # Right contacts and metals for each finger |
| for i in range(nf): |
| # Contacts |
| if not (w_changed == True and nf > 1) and (ld >= 440): |
| cell.insert(pya.CellInstArray.new(cont_cell_index, |
| pya.Trans.new(pya.Point.new(((l + ld + ld_violat + cont2ply - cmp2cont) * i + 2 * (ld + ld_violat) + l - cont_size - dx), dy)), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| # Metals |
| cell.shapes(metal1).insert(pya.Box((ld + 2 * ld_violat + l + cont2ply - cmp2cont)*(i + 1), - metal_violat, |
| ld + metal_violat + ld_violat + (ld + ld_violat + l + cont2ply - cmp2cont)*(i + 1) - (cont_size-2*cmp2cont), w + metal_violat)) |
| |
| # Adding diffusion to avoid contact violation |
| if nf == 1 and w_changed == True: |
| cell.shapes(comp).insert(pya.Box((ld + 2 * ld_violat + l + cont2ply - cmp2cont)*(i + 1), 0, ld + ld_violat + (ld + ld_violat + l + cont2ply - cmp2cont)*(i + 1) - (cont_size-2*cmp2cont), w)) |
| region = pya.Region.new(cell.begin_shapes_rec(comp)) |
| region.merge() |
| cell.clear(comp) |
| cell.shapes(comp).insert(region) |
| |
| if bulk == "Bulk Tie": |
| if deepnwell == True: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld, |
| -dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell)) |
| |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld, |
| -dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell)) |
| |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld, |
| -dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell)) |
| |
| # Inserting LVPWELL |
| cell.shapes(lvpwell).insert(pya.Box(-lvpwell_enc_pcmp-cmp2cmp-ld, -lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp)) |
| |
| # Inserting DNWELL |
| cell.shapes(dnwell).insert(pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld, -dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell)) |
| |
| # Inserting Double Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld-pcmp_gr2dnw, -dnwell_enc_lvpwell-lvpwell_enc_ncmp-pcmp_gr2dnw, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont))+pcmp_gr2dnw, |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell+pcmp_gr2dnw) |
| cmp_outer = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld-pcmp_gr2dnw-gr_w, -dnwell_enc_lvpwell-lvpwell_enc_ncmp-pcmp_gr2dnw-gr_w, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont))+pcmp_gr2dnw+gr_w, |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld-pcmp_gr2dnw+pp_enc_cmp, -dnwell_enc_lvpwell-lvpwell_enc_ncmp-pcmp_gr2dnw+pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont))+pcmp_gr2dnw-pp_enc_cmp, |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell+pcmp_gr2dnw-pp_enc_cmp) |
| pp_outer = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp-ld-pcmp_gr2dnw-gr_w-pp_enc_cmp, -dnwell_enc_lvpwell-lvpwell_enc_ncmp-pcmp_gr2dnw-gr_w-pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont))+pcmp_gr2dnw+gr_w+pp_enc_cmp, |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell+pcmp_gr2dnw+gr_w+pp_enc_cmp) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| cell.shapes(pplus).insert(pp_gr) |
| |
| else: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(- (cmp2cmp+dg_enc_cmp) - ld, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| cell.shapes(dualgate).insert(pya.Box(- (cmp2cmp+dg_enc_cmp) - ld, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(- (cmp2cmp+dg_enc_cmp) - ld, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| |
| # Inserting Tie |
| if (w * ld) < min_cmp_area: |
| tie_violat = (min_cmp_area/ld - w)/2 * tol |
| cell.shapes(comp).insert(pya.Box(- cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat)) |
| cell.shapes(pplus).insert(pya.Box(- cmp2cmp - pp_enc_cmp - ld, -pp_enc_cmp-tie_violat, -cmp2cmp+pp_enc_cmp, w + tie_violat + pp_enc_cmp)) |
| |
| # Tie contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((- (cmp2cmp+cont_size) - dx * cont_size/(2 *cmp2cont)), dy)), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| |
| # Tie metal |
| cell.shapes(metal1).insert(pya.Box(- cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat)) |
| |
| elif bulk == "Guard Ring": |
| if deepnwell == True: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw, |
| -dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + dg_enc_dnwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp + dnwell_enc_lvpwell + dg_enc_dnwell))) |
| |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw, |
| -dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + dg_enc_dnwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp + dnwell_enc_lvpwell + dg_enc_dnwell))) |
| |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw, |
| -dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + dg_enc_dnwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp + dnwell_enc_lvpwell + dg_enc_dnwell))) |
| |
| # Inserting LVPWELL |
| cell.shapes(lvpwell).insert(pya.Box(-lvpwell_enc_pcmp-cmp2cmp - grw, -lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp))) |
| |
| # Inserting DNWELL |
| cell.shapes(dnwell).insert(pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw, |
| -dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + lvpwell_enc_pcmp + dnwell_enc_lvpwell))) |
| |
| # Inserting Double Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw - pcmp_gr2dnw, |
| -dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + pcmp_gr2dnw + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + pcmp_gr2dnw + lvpwell_enc_pcmp + dnwell_enc_lvpwell)) |
| cmp_outer = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw - pcmp_gr2dnw - gr_w, |
| -dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw - gr_w, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + pcmp_gr2dnw + gr_w + lvpwell_enc_pcmp + dnwell_enc_lvpwell)) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw - pcmp_gr2dnw + pp_enc_cmp, |
| -dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw + pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + pcmp_gr2dnw - pp_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + pcmp_gr2dnw + lvpwell_enc_pcmp + dnwell_enc_lvpwell - pp_enc_cmp)) |
| pp_outer = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_pcmp-cmp2cmp - grw - pcmp_gr2dnw - gr_w - pp_enc_cmp, |
| -dnwell_enc_lvpwell-lvpwell_enc_pcmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw - gr_w - pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w + pp_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + pcmp_gr2dnw + gr_w + pp_enc_cmp + lvpwell_enc_pcmp + dnwell_enc_lvpwell)) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| cell.shapes(pplus).insert(pp_gr) |
| |
| else: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-(cmp2cmp+dg_enc_cmp) - grw, -(ply_ext_cmp+ply2gr+dg_enc_cmp) - grw, (2 * (ld + ld_violat) + l + grw + (cmp2cmp+dg_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp+ply2gr+dg_enc_cmp + grw))) |
| cell.shapes(dualgate).insert(pya.Box(-(cmp2cmp+dg_enc_cmp) - grw, -(ply_ext_cmp+ply2gr+dg_enc_cmp) - grw, (2 * (ld + ld_violat) + l + grw + (cmp2cmp+dg_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp+ply2gr+dg_enc_cmp + grw))) |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-(cmp2cmp+dg_enc_cmp) - grw, -(ply_ext_cmp+ply2gr+dg_enc_cmp) - grw, (2 * (ld + ld_violat) + l + grw + (cmp2cmp+dg_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp+ply2gr+dg_enc_cmp + grw))) |
| |
| # Inserting guard ring diffusion |
| cell.shapes(comp).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr) - grw), |
| ], |
| True, |
| ) |
| ) |
| cell.shapes(pplus).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw), |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp-pp_enc_cmp), (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp-pp_enc_cmp), -(ply_ext_cmp + ply2gr - pp_enc_cmp)), |
| pya.Point((2 * (ld + ld_violat) + l + (cmp2cmp-pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr - pp_enc_cmp)), |
| pya.Point((2 * (ld + ld_violat) + l + (cmp2cmp-pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + (cmp2cmp+pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + (cmp2cmp+pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw), |
| ], |
| True, |
| ) |
| ) |
| |
| # Inserting Guard Ring metal |
| cell.shapes(metal1).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr) - grw), |
| ], |
| True, |
| ) |
| ) |
| |
| nxgr = int((grw - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| nygr = int(((2 * grw + w + 2*(ply_ext_cmp + ply2gr)) - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont)/2 |
| dygr = ((2 * grw + w + 2*(ply_ext_cmp + ply2gr)) - nygr * cont_size - (nygr - 1) * cont2cont)/2 |
| nxgr_h = int(((2 * (ld + ld_violat) + l + 2*cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)) - 2*cont2cont)/(cont2cont+cont_size)) + 1 |
| dxgr_h = ((2 * (ld + ld_violat) + l + cont2cont + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)) - nxgr_h * cont_size - (nxgr_h - 1) * cont2cont)/2 |
| |
| # Inserting Guard Ring contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((-cmp2cmp - grw + dxgr), (-(ply_ext_cmp+ply2gr) - grw + dygr))), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr, nygr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(2*cmp2cont) + dxgr_h, -(2*cont_size) - ply2gr - dxgr)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, -(cont2cont+cont_size)), nxgr_h, nxgr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(2 * (ld + ld_violat) + l + grw - dxgr + (cmp2cmp-cont_size) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont), (-(ply_ext_cmp+ply2gr) - grw + dygr))), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr, nygr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((-(2*cmp2cont) + dxgr_h), (w + (ply_ext_cmp+ply2gr) + dxgr))), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr_h, nxgr)) |
| |
| else: |
| if deepnwell == True: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp,-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell)) |
| |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp,-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell)) |
| |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp,-dg_enc_dnwell-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + dg_enc_dnwell)) |
| |
| # Inserting LVPWELL |
| cell.shapes(lvpwell).insert(pya.Box(-lvpwell_enc_ncmp,-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp)) |
| |
| # Inserting DNWELL |
| cell.shapes(dnwell).insert(pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_ncmp,-dnwell_enc_lvpwell-lvpwell_enc_ncmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell)) |
| |
| # Inserting Double Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw, -dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw , |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + pcmp_gr2dnw + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw) |
| cmp_outer = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, -dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + pcmp_gr2dnw + gr_w + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp, -dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw + pp_enc_cmp , |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + pcmp_gr2dnw - pp_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw - pp_enc_cmp) |
| pp_outer = pya.Box(-dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, -dnwell_enc_lvpwell-lvpwell_enc_ncmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_lvpwell + lvpwell_enc_ncmp + pcmp_gr2dnw + gr_w + pp_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + lvpwell_enc_ncmp + dnwell_enc_lvpwell + pcmp_gr2dnw + gr_w + pp_enc_cmp) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| cell.shapes(pplus).insert(pp_gr) |
| |
| else: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(- dg_enc_cmp, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| cell.shapes(dualgate).insert(pya.Box(- dg_enc_cmp, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(- dg_enc_cmp, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| |
| cell.flatten(True) |
| return cell |
| |
| def draw_pmos(layout, l, w, ld, nf, grw, bulk, volt, deepnwell, pcmpgr): |
| ''' |
| Usage:- |
| used to draw PMOS transistor by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of gate length |
| w : Float of gate width |
| ld : Float of diffusion length |
| nf : Integer of number of fingers |
| grw : Float of guard ring width [If enabled] |
| bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] |
| volt : String of operating voltage of the MOSFET [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 ) |
| dualgate = layout.layer(55 , 0 ) |
| v5_xtor = layout.layer(112, 1 ) |
| nwell = layout.layer(21 , 0 ) |
| comp = layout.layer(22 , 0 ) |
| poly2 = layout.layer(30 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| nf = int(nf) |
| grw = grw * dbu_PERCISION |
| ld = ld * dbu_PERCISION |
| l = l * dbu_PERCISION |
| w = w * dbu_PERCISION |
| cmp2cont = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| np_enc_cmp = 0.16 * dbu_PERCISION |
| pp_enc_cmp = 0.16 * dbu_PERCISION |
| cont2ply = 0.15 * dbu_PERCISION |
| ply_ext_cmp = 0.22 * dbu_PERCISION |
| np_enc_gate = 0.23 * dbu_PERCISION |
| cont2cont = 0.28 * dbu_PERCISION |
| dg_enc_ply = 0.4 * dbu_PERCISION |
| dg_enc_cmp = 0.24 * dbu_PERCISION |
| cmp2cmp = 0.28 * dbu_PERCISION |
| ply2gr = 0.1 * dbu_PERCISION |
| nwell_enc_pcomp = 0.43 * dbu_PERCISION |
| nwell_enc_ncomp = 0.12 * dbu_PERCISION |
| ld_violat = 0 * dbu_PERCISION |
| tie_violat = 0 * dbu_PERCISION |
| metal_violat = 0.01 * dbu_PERCISION |
| min_cmp_area = 0.2025 * dbu_PERCISION * dbu_PERCISION |
| dg_enc_dnwell = 0.5 * dbu_PERCISION |
| dnwell_enc_ncmp = 0.62 * dbu_PERCISION |
| dnwell_enc_pcmp = 0.93 * dbu_PERCISION |
| pcmp_gr2dnw = 2.5 * dbu_PERCISION |
| gr_w = 0.36 * dbu_PERCISION |
| |
| if deepnwell == True: |
| cmp2cmp = 0.36 * dbu_PERCISION |
| ply2gr = 0.3 * dbu_PERCISION |
| |
| if volt == "5V" or volt == "6V": |
| cmp2cmp = 0.36 * dbu_PERCISION |
| ply2gr = 0.3 * dbu_PERCISION |
| cmp2cmp = 0.36 * dbu_PERCISION |
| dnwell_enc_ncmp = 0.66 * dbu_PERCISION |
| dnwell_enc_pcmp = 1.1 * dbu_PERCISION |
| nwell_enc_pcomp = 0.6 * dbu_PERCISION |
| nwell_enc_ncomp = 0.16 * dbu_PERCISION |
| |
| if w < cont_size+2*cmp2cont: |
| if nf == 1: |
| if volt == "5V" or volt == "6V": |
| ld_violat = 0.22 * dbu_PERCISION |
| else: |
| ld_violat = 0.02 * dbu_PERCISION |
| |
| # Inserting PMOS cell |
| cell_index = layout.add_cell("pmos") |
| cell = layout.cell(cell_index) |
| |
| w_changed = False |
| |
| # Inserting diffusion |
| if w < cont_size+2*cmp2cont: |
| cell.shapes(comp).insert(pya.Box(0, (cont_size+2*cmp2cont - w)/2, (2 * (ld + ld_violat) + l + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), w + (cont_size+2*cmp2cont - w)/2)) |
| w = cont_size+2*cmp2cont |
| w_changed = True |
| else: |
| cell.shapes(comp).insert(pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w)) |
| |
| cell.shapes(pplus).insert(pya.Box(-np_enc_cmp, -np_enc_gate, (2 * (ld + ld_violat) + l + np_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), w + np_enc_gate)) |
| |
| # Inserting gate/s |
| # Inserting a gate cell |
| gate_cell_index = layout.add_cell("gate") |
| gate_cell = layout.cell(gate_cell_index) |
| gate_cell.shapes(poly2).insert(pya.Box(ld + ld_violat, -ply_ext_cmp, (ld + ld_violat + l), (w + ply_ext_cmp))) |
| |
| # adding gate array |
| cell.insert(pya.CellInstArray.new(gate_cell_index, pya.Trans.new(pya.Point.new(0, 0)), |
| pya.Point.new(ld + ld_violat + l + cont2ply - cmp2cont, 0), pya.Point.new(0, 0), int(nf), 1)) |
| |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| |
| # Inserting shapes now into the *contact* cell |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Contact array count and postions |
| nx = int((ld - (cont_size+cmp2cont+cont2ply))/(cont2cont+cont_size)) + 1 |
| ny = int((w - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| dx = (ld - nx * cont_size - (nx - 1) * cont2cont)*cmp2cont/cont_size |
| dy = (w - ny * cont_size - (ny - 1) * cont2cont)/2 |
| |
| # adding contact array and metals |
| # Left contacts |
| if not (w_changed == True and nf > 1) and (ld >= 440): |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dx, dy)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| # Left metal |
| cell.shapes(metal1).insert(pya.Box(-metal_violat, -metal_violat, ld + metal_violat - (cont_size-2*cmp2cont), w + metal_violat)) |
| |
| # Adding diffusion to avoid contact violation |
| if nf == 1 and w_changed == True: |
| cell.shapes(comp).insert(pya.Box(0, 0, ld - (cont_size-2*cmp2cont), w)) |
| |
| # Right contacts and metals for each finger |
| for i in range(nf): |
| # Contacts |
| if not (w_changed == True and nf > 1) and (ld >= 440): |
| cell.insert(pya.CellInstArray.new(cont_cell_index, |
| pya.Trans.new(pya.Point.new(((l + ld + ld_violat + cont2ply - cmp2cont) * i + 2 * (ld + ld_violat) + l - cont_size - dx), dy)), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| # Metals |
| cell.shapes(metal1).insert(pya.Box((ld + 2 * ld_violat + l + cont2ply - cmp2cont)*(i + 1), - metal_violat, |
| ld + metal_violat + ld_violat + (ld + ld_violat + l + cont2ply - cmp2cont)*(i + 1) - (cont_size-2*cmp2cont), w + metal_violat)) |
| |
| # Adding diffusion to avoid contact violation |
| if nf == 1 and w_changed == True: |
| cell.shapes(comp).insert(pya.Box((ld + 2 * ld_violat + l + cont2ply - cmp2cont)*(i + 1), 0, ld + ld_violat + (ld + ld_violat + l + cont2ply - cmp2cont)*(i + 1) - (cont_size-2*cmp2cont), w)) |
| region = pya.Region.new(cell.begin_shapes_rec(comp)) |
| region.merge() |
| cell.clear(comp) |
| cell.shapes(comp).insert(region) |
| |
| if bulk == "Bulk Tie": |
| if deepnwell == True: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_ncmp-cmp2cmp-ld,-dg_enc_dnwell-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + dg_enc_dnwell)) |
| |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_ncmp-cmp2cmp-ld,-dg_enc_dnwell-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + dg_enc_dnwell)) |
| |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_ncmp-cmp2cmp-ld,-dg_enc_dnwell-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + dg_enc_dnwell)) |
| |
| # Inserting DNWELL |
| cell.shapes(dnwell).insert(pya.Box(-dnwell_enc_ncmp-cmp2cmp-ld,-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp)) |
| |
| # Inserting Double Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_enc_ncmp-cmp2cmp-ld-pcmp_gr2dnw, -dnwell_enc_pcmp-pcmp_gr2dnw, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw) |
| cmp_outer = pya.Box(-dnwell_enc_ncmp-cmp2cmp-ld-pcmp_gr2dnw-gr_w, -dnwell_enc_pcmp-pcmp_gr2dnw-gr_w, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_enc_ncmp-cmp2cmp-ld-pcmp_gr2dnw+pp_enc_cmp, -dnwell_enc_pcmp-pcmp_gr2dnw+pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp) |
| pp_outer = pya.Box(-dnwell_enc_ncmp-cmp2cmp-ld-pcmp_gr2dnw-gr_w- pp_enc_cmp, -dnwell_enc_pcmp-pcmp_gr2dnw-gr_w- pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| cell.shapes(pplus).insert(pp_gr) |
| |
| else: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(- (cmp2cmp+dg_enc_cmp) - ld, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| cell.shapes(dualgate).insert(pya.Box(- (cmp2cmp+dg_enc_cmp) - ld, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(- (cmp2cmp+dg_enc_cmp) - ld, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| |
| # Inserting nwell |
| cell.shapes(nwell).insert(pya.Box(- nwell_enc_ncomp - cmp2cmp - ld, -nwell_enc_pcomp, (2 * (ld + ld_violat) + l + nwell_enc_pcomp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + nwell_enc_pcomp)) |
| |
| # Inserting Tie |
| if (w * ld) < min_cmp_area: |
| tie_violat = (min_cmp_area/ld - w)/2 * tol |
| cell.shapes(comp).insert(pya.Box(- cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat)) |
| cell.shapes(nplus).insert(pya.Box(- cmp2cmp - np_enc_cmp - ld, -np_enc_cmp-tie_violat, -cmp2cmp+np_enc_cmp, w + tie_violat + np_enc_cmp)) |
| |
| # Tie contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((- (cmp2cmp+cont_size) - dx * cont_size/(2 *cmp2cont)), dy)), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| |
| # Tie metal |
| cell.shapes(metal1).insert(pya.Box(- cmp2cmp - ld, -tie_violat, -cmp2cmp, w + tie_violat)) |
| |
| elif bulk == "Guard Ring": |
| if deepnwell == True: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_ncmp-cmp2cmp - grw, |
| -dg_enc_dnwell-dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + dg_enc_dnwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + dg_enc_dnwell))) |
| |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_ncmp-cmp2cmp - grw, |
| -dg_enc_dnwell-dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + dg_enc_dnwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + dg_enc_dnwell))) |
| |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_ncmp-cmp2cmp - grw, |
| -dg_enc_dnwell-dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + dg_enc_dnwell + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + dg_enc_dnwell))) |
| |
| # Inserting DNWELL |
| cell.shapes(dnwell).insert(pya.Box(-dnwell_enc_ncmp-cmp2cmp - grw, |
| -dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp))) |
| |
| # Inserting Double Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_enc_ncmp-cmp2cmp - grw - pcmp_gr2dnw, |
| -dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + pcmp_gr2dnw + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + pcmp_gr2dnw)) |
| cmp_outer = pya.Box(-dnwell_enc_ncmp-cmp2cmp - grw - pcmp_gr2dnw - gr_w, |
| -dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw - gr_w, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + pcmp_gr2dnw + gr_w + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + pcmp_gr2dnw + gr_w)) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_enc_ncmp-cmp2cmp - grw - pcmp_gr2dnw + pp_enc_cmp, |
| -dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw + pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + pcmp_gr2dnw - pp_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + pcmp_gr2dnw - pp_enc_cmp)) |
| pp_outer = pya.Box(-dnwell_enc_ncmp-cmp2cmp - grw - pcmp_gr2dnw - gr_w - pp_enc_cmp, |
| -dnwell_enc_ncmp-(ply_ext_cmp + ply2gr) - grw - pcmp_gr2dnw - gr_w - pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + grw + cmp2cmp + dnwell_enc_ncmp + pcmp_gr2dnw + gr_w + pp_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), |
| (w + (ply_ext_cmp + ply2gr) + grw + dnwell_enc_ncmp + pcmp_gr2dnw + gr_w + pp_enc_cmp)) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| cell.shapes(pplus).insert(pp_gr) |
| |
| else: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-(cmp2cmp+dg_enc_cmp) - grw, -(ply_ext_cmp+ply2gr+dg_enc_cmp) - grw, (2 * (ld + ld_violat) + l + grw + (cmp2cmp+dg_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp+ply2gr+dg_enc_cmp + grw))) |
| cell.shapes(dualgate).insert(pya.Box(-(cmp2cmp+dg_enc_cmp) - grw, -(ply_ext_cmp+ply2gr+dg_enc_cmp) - grw, (2 * (ld + ld_violat) + l + grw + (cmp2cmp+dg_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp+ply2gr+dg_enc_cmp + grw))) |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-(cmp2cmp+dg_enc_cmp) - grw, -(ply_ext_cmp+ply2gr+dg_enc_cmp) - grw, (2 * (ld + ld_violat) + l + grw + (cmp2cmp+dg_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp+ply2gr+dg_enc_cmp + grw))) |
| |
| # Inserting nwell |
| cell.shapes(nwell).insert(pya.Box(- nwell_enc_ncomp - cmp2cmp - grw, - ply_ext_cmp - ply2gr - nwell_enc_ncomp - grw, (2 * (ld + ld_violat) + l + grw + nwell_enc_ncomp + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + ply_ext_cmp + ply2gr + nwell_enc_ncomp + grw))) |
| |
| # Inserting Guard Ring diffusion |
| cell.shapes(comp).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr) - grw), |
| ], |
| True, |
| ) |
| ) |
| cell.shapes(nplus).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw), |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp-pp_enc_cmp), (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp-pp_enc_cmp), -(ply_ext_cmp + ply2gr - pp_enc_cmp)), |
| pya.Point((2 * (ld + ld_violat) + l + (cmp2cmp-pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr - pp_enc_cmp)), |
| pya.Point((2 * (ld + ld_violat) + l + (cmp2cmp-pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, (w + (ply_ext_cmp + ply2gr - pp_enc_cmp))), |
| pya.Point(-(cmp2cmp+pp_enc_cmp) - grw, (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + (cmp2cmp+pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr + pp_enc_cmp) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + (cmp2cmp+pp_enc_cmp) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr + pp_enc_cmp) - grw), |
| ], |
| True, |
| ) |
| ) |
| |
| # Inserting Guard Ring metal |
| cell.shapes(metal1).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-cmp2cmp - grw, -(ply_ext_cmp + ply2gr) - grw), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp, -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr)), |
| pya.Point((2 * (ld + ld_violat) + l + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr))), |
| pya.Point(-cmp2cmp - grw, (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), (w + (ply_ext_cmp + ply2gr) + grw)), |
| pya.Point((2 * (ld + ld_violat) + l + grw + cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), -(ply_ext_cmp + ply2gr) - grw), |
| ], |
| True, |
| ) |
| ) |
| |
| nxgr = int((grw - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| nygr = int(((2 * grw + w + 2*(ply_ext_cmp + ply2gr)) - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont)/2 |
| dygr = ((2 * grw + w + 2*(ply_ext_cmp + ply2gr)) - nygr * cont_size - (nygr - 1) * cont2cont)/2 |
| nxgr_h = int(((2 * (ld + ld_violat) + l + 2*cmp2cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)) - 2*cont2cont)/(cont2cont+cont_size)) + 1 |
| dxgr_h = ((2 * (ld + ld_violat) + l + cont2cont + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)) - nxgr_h * cont_size - (nxgr_h - 1) * cont2cont)/2 |
| |
| # Inserting Guard Ring contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((-cmp2cmp - grw + dxgr), (-(ply_ext_cmp+ply2gr) - grw + dygr))), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr, nygr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(2*cmp2cont) + dxgr_h, -(2*cont_size) - ply2gr - dxgr)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, -(cont2cont+cont_size)), nxgr_h, nxgr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(2 * (ld + ld_violat) + l + grw - dxgr + (cmp2cmp-cont_size) + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont), (-(ply_ext_cmp+ply2gr) - grw + dygr))), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr, nygr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((-(2*cmp2cont) + dxgr_h), (w + (ply_ext_cmp+ply2gr) + dxgr))), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr_h, nxgr)) |
| |
| else: |
| if deepnwell == True: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_pcmp,-dg_enc_dnwell-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + dg_enc_dnwell)) |
| |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_pcmp,-dg_enc_dnwell-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + dg_enc_dnwell)) |
| |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(-dg_enc_dnwell-dnwell_enc_pcmp,-dg_enc_dnwell-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dg_enc_dnwell + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + dg_enc_dnwell)) |
| |
| # Inserting DNWELL |
| cell.shapes(dnwell).insert(pya.Box(-dnwell_enc_pcmp,-dnwell_enc_pcmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp)) |
| |
| # Inserting Double Guard Ring |
| if pcmpgr == True: |
| cmp_inner = pya.Box(-dnwell_enc_pcmp - pcmp_gr2dnw, -dnwell_enc_pcmp - pcmp_gr2dnw, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw) |
| cmp_outer = pya.Box(-dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w) |
| cmp_gr = pya.Region(cmp_outer) - pya.Region(cmp_inner) |
| cell.shapes(comp).insert(cmp_gr) |
| |
| pp_inner = pya.Box(-dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, -dnwell_enc_pcmp - pcmp_gr2dnw + pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw - pp_enc_cmp) |
| pp_outer = pya.Box(-dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, -dnwell_enc_pcmp - pcmp_gr2dnw - gr_w - pp_enc_cmp, |
| (2 * (ld + ld_violat) + l + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp + (nf - 1) * (ld + ld_violat + l + cont2ply - cmp2cont)), |
| w + dnwell_enc_pcmp + pcmp_gr2dnw + gr_w + pp_enc_cmp) |
| pp_gr = pya.Region(pp_outer) - pya.Region(pp_inner) |
| cell.shapes(pplus).insert(pp_gr) |
| |
| else: |
| if volt == "5V": |
| # Inserting 5V layers |
| cell.shapes(v5_xtor).insert(pya.Box(- dg_enc_cmp, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| cell.shapes(dualgate).insert(pya.Box(- dg_enc_cmp, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| elif volt == "6V": |
| # Inserting 6V layers |
| cell.shapes(dualgate).insert(pya.Box(- dg_enc_cmp, -(dg_enc_ply+ply_ext_cmp), (2 * (ld + ld_violat) + l + dg_enc_cmp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + (dg_enc_ply+ply_ext_cmp))) |
| |
| # Inserting NWELL |
| cell.shapes(nwell).insert(pya.Box(- nwell_enc_pcomp, -nwell_enc_pcomp, (2 * (ld + ld_violat) + l + nwell_enc_pcomp + (nf - 1) * ((ld + ld_violat) + l + cont2ply - cmp2cont)), w + nwell_enc_pcomp)) |
| |
| |
| cell.flatten(True) |
| return cell |
| |
| def draw_nmos_6p0_nat(layout, l, w, ld, nf, grw, bulk): |
| ''' |
| Usage:- |
| used to draw Native NMOS 6V transistor by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of gate length |
| w : Float of gate width |
| ld : Float of diffusion length |
| nf : Integer of number of fingers |
| grw : Float of guard ring width [If enabled] |
| bulk : String of bulk connection type [None, Bulk Tie, Guard Ring] |
| ''' |
| |
| # Define layers |
| dualgate = layout.layer(55 , 0 ) |
| nat = layout.layer(5 , 0 ) |
| comp = layout.layer(22 , 0 ) |
| poly2 = layout.layer(30 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| nf = int(nf) |
| grw = grw * dbu_PERCISION |
| ld = ld * dbu_PERCISION |
| l = l * dbu_PERCISION |
| w = w * dbu_PERCISION |
| cmp2cont = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| np_enc_cmp = 0.16 * dbu_PERCISION |
| pp_enc_cmp = 0.16 * dbu_PERCISION |
| cont2ply = 0.15 * dbu_PERCISION |
| ply_ext_cmp = 0.22 * dbu_PERCISION |
| np_enc_gate = 0.23 * dbu_PERCISION |
| cont2cont = 0.28 * dbu_PERCISION |
| cmp2cmp = 0.36 * dbu_PERCISION |
| nat_enc_cmp = 2 * dbu_PERCISION |
| |
| # Inserting NMOS cell |
| cell_index = layout.add_cell("nmos_6p0_nat") |
| cell = layout.cell(cell_index) |
| |
| # Inserting diffusion |
| cell.shapes(comp).insert(pya.Box(0, 0, (2 * ld + l + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w)) |
| cell.shapes(nplus).insert(pya.Box(-np_enc_cmp, -np_enc_gate, (2 * ld + l + np_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w + np_enc_gate)) |
| cell.shapes(nat).insert(pya.Box(-nat_enc_cmp, -nat_enc_cmp, (2 * ld + l + nat_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w + nat_enc_cmp)) |
| cell.shapes(dualgate).insert(pya.Box(-nat_enc_cmp, -nat_enc_cmp, (2 * ld + l + nat_enc_cmp + (nf - 1) * (ld + l + cont2ply - cmp2cont)), w + nat_enc_cmp)) |
| |
| # Inserting gate/s |
| # Inserting a gate cell |
| gate_cell_index = layout.add_cell("gate") |
| gate_cell = layout.cell(gate_cell_index) |
| gate_cell.shapes(poly2).insert(pya.Box(ld, -ply_ext_cmp, (ld + l), (w + ply_ext_cmp))) |
| |
| # adding gate array |
| cell.insert(pya.CellInstArray.new(gate_cell_index, pya.Trans.new(pya.Point.new(0, 0)), |
| pya.Point.new(ld + l + cont2ply - cmp2cont, 0), pya.Point.new(0, 0), int(nf), 1)) |
| |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| |
| # Inserting shapes now into the *contact* cell |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Contact array count and postions |
| nx = int((ld - (cont_size+cmp2cont+cont2ply))/(cont2cont+cont_size)) + 1 |
| ny = int((w - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| dx = (ld - nx * cont_size - (nx - 1) * cont2cont)*cmp2cont/cont_size |
| dy = (w - ny * cont_size - (ny - 1) * cont2cont)/2 |
| |
| # adding contact array and metals |
| # Left contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dx, dy)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| # Left metal |
| cell.shapes(metal1).insert(pya.Box(0, 0, ld - (cont_size-2*cmp2cont), w)) |
| |
| # Right contacts and metals for each finger |
| for i in range(nf): |
| # Contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, |
| pya.Trans.new(pya.Point.new(((l + ld + cont2ply - cmp2cont) * i + 2 * ld + l - cont_size - dx), dy)), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| # Metals |
| cell.shapes(metal1).insert(pya.Box((ld + l + cont2ply - cmp2cont)*(i + 1), 0, ld + (ld + l + cont2ply - cmp2cont)*(i + 1) - (cont_size-2*cmp2cont), w)) |
| |
| if bulk == "Bulk Tie": |
| # Inserting tie |
| cell.shapes(comp).insert(pya.Box(- (nat_enc_cmp + cmp2cmp) - ld, 0, -(nat_enc_cmp + cmp2cmp), w)) |
| cell.shapes(pplus).insert(pya.Box(- (nat_enc_cmp + cmp2cmp + pp_enc_cmp) - ld, -pp_enc_cmp, -(nat_enc_cmp + cmp2cmp - pp_enc_cmp), w + pp_enc_cmp)) |
| |
| # Tie contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((- (nat_enc_cmp + cmp2cmp + cont_size) - dx * cont_size/(2 *cmp2cont)), dy)), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nx, ny)) |
| |
| # Tie metal |
| cell.shapes(metal1).insert(pya.Box(- (nat_enc_cmp + cmp2cmp) - ld, 0, -(nat_enc_cmp + cmp2cmp), w)) |
| |
| elif bulk == "Guard Ring": |
| # Inserting Guard Ring diffusion |
| cell.shapes(comp).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, -(nat_enc_cmp + cmp2cmp) - grw), |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp), (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp), -(nat_enc_cmp + cmp2cmp)), |
| pya.Point((2 * ld + l + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), -(nat_enc_cmp + cmp2cmp)), |
| pya.Point((2 * ld + l + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp) + grw)), |
| pya.Point((2 * ld + l + grw + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), (w + (nat_enc_cmp + cmp2cmp) + grw)), |
| pya.Point((2 * ld + l + grw + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), -(nat_enc_cmp + cmp2cmp) - grw), |
| ], |
| True, |
| ) |
| ) |
| cell.shapes(pplus).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw), |
| pya.Point(-(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp - pp_enc_cmp), (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp - pp_enc_cmp), -(nat_enc_cmp + cmp2cmp - pp_enc_cmp)), |
| pya.Point((2 * ld + l + (nat_enc_cmp + cmp2cmp - pp_enc_cmp) + (nf - 1) * (ld + l)), -(nat_enc_cmp + cmp2cmp - pp_enc_cmp)), |
| pya.Point((2 * ld + l + (nat_enc_cmp + cmp2cmp - pp_enc_cmp) + (nf - 1) * (ld + l)), (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, (w + (nat_enc_cmp + cmp2cmp - pp_enc_cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw, (w + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + grw)), |
| pya.Point((2 * ld + l + grw + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + (nf - 1) * (ld + l)), (w + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + grw)), |
| pya.Point((2 * ld + l + grw + (nat_enc_cmp + cmp2cmp + pp_enc_cmp) + (nf - 1) * (ld + l)), -(nat_enc_cmp + cmp2cmp + pp_enc_cmp) - grw), |
| ], |
| True, |
| ) |
| ) |
| |
| # Inserting Guard Ring metal |
| cell.shapes(metal1).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, -(nat_enc_cmp + cmp2cmp) - grw), |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp), (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp), -(nat_enc_cmp + cmp2cmp)), |
| pya.Point((2 * ld + l + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), -(nat_enc_cmp + cmp2cmp)), |
| pya.Point((2 * ld + l + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp))), |
| pya.Point(-(nat_enc_cmp + cmp2cmp) - grw, (w + (nat_enc_cmp + cmp2cmp) + grw)), |
| pya.Point((2 * ld + l + grw + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), (w + (nat_enc_cmp + cmp2cmp) + grw)), |
| pya.Point((2 * ld + l + grw + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)), -(nat_enc_cmp + cmp2cmp) - grw), |
| ], |
| True, |
| ) |
| ) |
| |
| nxgr = int((grw - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| nygr = int(((2 * grw + w + 2*(nat_enc_cmp + cmp2cmp)) - (cont_size+2*cmp2cont))/(cont2cont+cont_size)) + 1 |
| dxgr = (grw - nxgr * cont_size - (nxgr - 1) * cont2cont)/2 |
| dygr = ((2 * grw + w + 2*(nat_enc_cmp + cmp2cmp)) - nygr * cont_size - (nygr - 1) * cont2cont)/2 |
| nxgr_h = int(((2 * ld + l + 2*(nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l))- 2*cont2cont)/(cont2cont+cont_size)) + 1 |
| dxgr_h = ((2 * ld + l + (nat_enc_cmp + cmp2cmp) + (nf - 1) * (ld + l)) - nxgr_h * cont_size - (nxgr_h - 1) * cont2cont)/2 |
| |
| # Inserting Guard Ring contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((-(nat_enc_cmp + cmp2cmp) - grw + dxgr), (-(nat_enc_cmp + cmp2cmp) - grw + dygr))), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr, nygr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(nat_enc_cmp + cmp2cmp)/2 + dxgr_h, -(nat_enc_cmp + cmp2cmp + cont_size) - dxgr)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, -(cont2cont+cont_size)), nxgr_h, nxgr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(2 * ld + l + grw - dxgr + nat_enc_cmp + cmp2cmp - cont_size + (nf - 1) * (ld + l), (-(nat_enc_cmp + cmp2cmp) - grw + dygr))), |
| pya.Point.new(-(cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr, nygr)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(nat_enc_cmp + cmp2cmp)/2 + dxgr_h, w + (nat_enc_cmp + cmp2cmp) + dxgr)), |
| pya.Point.new((cont2cont+cont_size), 0), pya.Point.new(0, (cont2cont+cont_size)), nxgr_h, nxgr)) |
| |
| cell.flatten(True) |
| return cell |
| |
| def draw_nmos_10p0_asym(layout, l, w): |
| ''' |
| Usage:- |
| used to draw LDNMOS 10V transistor by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of gate length |
| w : Float of gate width |
| ''' |
| |
| # Define layers |
| dualgate = layout.layer(55 , 0 ) |
| ldmos_xtor = layout.layer(226, 0 ) |
| mvsd = layout.layer(210, 0 ) |
| comp = layout.layer(22 , 0 ) |
| poly2 = layout.layer(30 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| l = l * dbu_PERCISION |
| w = w * dbu_PERCISION |
| cmp2cont = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| np_enc_cmp = 0.16 * dbu_PERCISION |
| pp_enc_cmp = 0.16 * dbu_PERCISION |
| cont2ply = 0.15 * dbu_PERCISION |
| metal_w = 0.38 * dbu_PERCISION |
| ply_ext_cmp = 0.4 * dbu_PERCISION |
| ply_fld = 0.2 * dbu_PERCISION |
| np_enc_gate = 0.23 * dbu_PERCISION |
| cont2cont = 0.25 * dbu_PERCISION |
| cmp2cmp = 0.36 * dbu_PERCISION |
| cmp2gr = 0.4 * dbu_PERCISION |
| mvsd_ext_cmp = 0.5 * dbu_PERCISION |
| mvsd_ov_cmp = 0.4 * dbu_PERCISION |
| mvsd2gr = 1 * dbu_PERCISION |
| ply2gr = 0.4 * dbu_PERCISION |
| drain2ply = 0.16 * dbu_PERCISION |
| dg_enc_cmp = 0.5 * dbu_PERCISION |
| |
| |
| # Inserting NMOS cell |
| cell_index = layout.add_cell("nmos_10p0_asym") |
| cell = layout.cell(cell_index) |
| |
| # Inserting layers for LDMOS |
| cell.shapes(dualgate).insert(pya.Box( |
| -(dg_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont2ply+cont_size+cmp2cont+mvsd_ov_cmp+cmp2cmp) - l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+dg_enc_cmp) - w/2, |
| (dg_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont2ply+cont_size+cmp2cont+mvsd_ov_cmp+cmp2cmp) + l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+dg_enc_cmp) + w/2)) |
| cell.shapes(ldmos_xtor).insert(pya.Box( |
| -(dg_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont2ply+cont_size+cmp2cont+mvsd_ov_cmp+cmp2cmp) - l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+dg_enc_cmp) - w/2, |
| (dg_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont2ply+cont_size+cmp2cont+mvsd_ov_cmp+cmp2cmp) + l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+dg_enc_cmp) + w/2)) |
| |
| # Inserting drain diffusion |
| cell.shapes(comp).insert(pya.Box(-cont_size/2, -w/2, cont_size/2, w/2)) |
| cell.shapes(mvsd).insert(pya.Box(-(cont_size/2+cmp2cmp+mvsd_ov_cmp), -w/2 - mvsd_ext_cmp, (cont_size/2+cmp2cmp+mvsd_ov_cmp), w/2 + mvsd_ext_cmp)) |
| |
| # Inserting source diffusion |
| cell.shapes(comp).insert(pya.Box((cont_size/2+cmp2cmp), -w/2, (cont_size/2+cmp2cmp+mvsd_ov_cmp+cont2ply+cont_size+cmp2cont) + l, w/2)) |
| cell.shapes(comp).insert(pya.Box(-(cont_size/2+cmp2cmp), -w/2, -(cont_size/2+cmp2cmp+mvsd_ov_cmp+cont2ply+cont_size+cmp2cont) - l, w/2)) |
| |
| cell.shapes(nplus).insert(pya.Box(-(cont_size/2+cmp2cmp+mvsd_ov_cmp+cont2ply+cont_size+cmp2cont+np_enc_cmp) - l, -w/2 - np_enc_gate, |
| (cont_size/2+cmp2cmp+mvsd_ov_cmp+cont2ply+cont_size+cmp2cont+np_enc_cmp) + l, w/2 + np_enc_gate)) |
| |
| # Inserting gates |
| cell.shapes(poly2).insert(pya.Box((cont_size/2+drain2ply), -w/2 - ply_ext_cmp, (cont_size/2+cmp2cmp+mvsd_ov_cmp) + l, w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr)) |
| cell.shapes(poly2).insert(pya.Box(-(cont_size/2+drain2ply), -w/2 - ply_ext_cmp, -(cont_size/2+cmp2cmp+mvsd_ov_cmp) - l, w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr)) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| |
| # Inserting shapes now into the *contact* cell |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Contact array count and postions |
| ny = int((w - (cont_size+2*cmp2cont))/(cont_size+cont2cont)) + 1 |
| dy = (w - ny * cont_size - (ny - 1) * cont2cont)/2 |
| ng = int(((l + mvsd_ov_cmp + ply_fld) - (cont_size+2*cmp2cont))/(cont_size+cont2cont)) + 1 |
| dg = (l + mvsd_ov_cmp + ply_fld - ng * cont_size - (ng - 1) * cont2cont)/2 |
| |
| # Inserting contact array and metals |
| # gate contacts and metal |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((cont_size/2+drain2ply) + dg, w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr-(metal_w+cont_size)/2)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), ng, 1)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(1.5*cont_size+drain2ply) - dg, w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr-(metal_w+cont_size)/2)), |
| pya.Point.new(-(cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), ng, 1)) |
| cell.shapes(metal1).insert(pya.Box((cont_size/2+drain2ply), w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr-metal_w, |
| (cont_size/2+cmp2cmp+mvsd_ov_cmp) + l, w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr)) |
| cell.shapes(metal1).insert(pya.Box(-(cont_size/2+drain2ply), w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr-metal_w, |
| -(cont_size/2+cmp2cmp+mvsd_ov_cmp) - l, w/2 + mvsd_ext_cmp+mvsd2gr-ply2gr)) |
| |
| # Drain contacts and metal |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-cont_size/2, -w/2 + dy)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, ny)) |
| cell.shapes(metal1).insert(pya.Box(-metal_w/2, -w/2, metal_w/2, w/2)) |
| |
| # Source contacts and metals |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((cont_size/2+cmp2cmp+mvsd_ov_cmp+cont2ply) + l, -w/2 + dy)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, ny)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(1.5*cont_size+cmp2cmp+mvsd_ov_cmp+cont2ply) - l, -w/2 + dy)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, ny)) |
| cell.shapes(metal1).insert(pya.Box((1.5*cont_size+cmp2cmp+mvsd_ov_cmp+cont2ply+cmp2cont-metal_w) + l, -w/2, (1.5*cont_size+cmp2cmp+mvsd_ov_cmp+cont2ply+cmp2cont) + l, w/2)) |
| cell.shapes(metal1).insert(pya.Box(-(1.5*cont_size+cmp2cmp+mvsd_ov_cmp+cont2ply+cmp2cont-metal_w) - l, -w/2, -(1.5*cont_size+cmp2cmp+mvsd_ov_cmp+cont2ply+cmp2cont) - l, w/2)) |
| |
| # Inserting Guard Ring diffusion |
| cell.shapes(comp).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) - w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, -(mvsd_ext_cmp+mvsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, -(mvsd_ext_cmp+mvsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| cell.shapes(pplus).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) - w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, (mvsd_ext_cmp+mvsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp-pp_enc_cmp) - l, (mvsd_ext_cmp+mvsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp-pp_enc_cmp) - l, -(mvsd_ext_cmp+mvsd2gr-pp_enc_cmp) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp-pp_enc_cmp) + l, -(mvsd_ext_cmp+mvsd2gr-pp_enc_cmp) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp-pp_enc_cmp) + l, (mvsd_ext_cmp+mvsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, (mvsd_ext_cmp+mvsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+pp_enc_cmp) + l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+pp_enc_cmp) + l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| cell.shapes(metal1).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) - w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, -(mvsd_ext_cmp+mvsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, -(mvsd_ext_cmp+mvsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, (mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, -(mvsd_ext_cmp+mvsd2gr+2*cmp2cont+cont_size) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| nygr = int((w + 2*(mvsd_ext_cmp+mvsd2gr+cmp2cont+cont_size)+cont2cont)/(cont_size+cont2cont)) |
| dygr = (w + 2*(mvsd_ext_cmp+mvsd2gr+cmp2cont+cont_size) - nygr * (cont_size+cont2cont)+ cont2cont)/2 |
| nxgr_h = int((2 * l + 2*(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+cmp2cont)- cont2cont)/(cont_size+cont2cont)) |
| dxgr_h = (2 * l + 2*(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+cmp2cont) - nxgr_h * (cont_size+cont2cont) + cont2cont)/2 |
| |
| # Inserting Guard Ring contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) - l, |
| dygr - (mvsd_ext_cmp+mvsd2gr+cmp2cont+cont_size) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, nygr)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dxgr_h - (0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+cmp2cont) - l, |
| -(mvsd_ext_cmp+mvsd2gr+cmp2cont+cont_size) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), nxgr_h, 1)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((cmp2cont+0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp) + l, |
| dygr - (mvsd_ext_cmp+mvsd2gr+cmp2cont+cont_size) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, nygr)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dxgr_h - (0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvsd_ov_cmp+cmp2cmp+cmp2cont) - l, |
| (mvsd_ext_cmp+mvsd2gr+cmp2cont) + w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), nxgr_h, 1)) |
| |
| cell.flatten(True) |
| return cell |
| |
| def draw_pmos_10p0_asym(layout, l, w, dgr_en): |
| ''' |
| Usage:- |
| used to draw LDPMOS 10V transistor by specifying parameters |
| Arguments:- |
| layout : Object of layout |
| l : Float of gate length |
| w : Float of gate width |
| dgr_en : Boolean to enable double guard ring |
| ''' |
| |
| # Define layers |
| dnwell = layout.layer(12 , 0 ) |
| dualgate = layout.layer(55 , 0 ) |
| ldmos_xtor = layout.layer(226, 0 ) |
| mvpsd = layout.layer(11 , 39) |
| comp = layout.layer(22 , 0 ) |
| poly2 = layout.layer(30 , 0 ) |
| nplus = layout.layer(32 , 0 ) |
| pplus = layout.layer(31 , 0 ) |
| contact = layout.layer(33 , 0 ) |
| metal1 = layout.layer(34 , 0 ) |
| |
| # Define variables |
| dbu_PERCISION = 1/layout.dbu |
| l = l * dbu_PERCISION |
| w = w * dbu_PERCISION |
| cmp2cont = 0.07 * dbu_PERCISION |
| cont_size = 0.22 * dbu_PERCISION |
| np_enc_cmp = 0.16 * dbu_PERCISION |
| pp_enc_cmp = 0.16 * dbu_PERCISION |
| cont2ply = 0.15 * dbu_PERCISION |
| metal_w = 0.38 * dbu_PERCISION |
| ply_ext_cmp = 0.4 * dbu_PERCISION |
| ply_fld = 0.2 * dbu_PERCISION |
| np_enc_gate = 0.23 * dbu_PERCISION |
| cont2cont = 0.25 * dbu_PERCISION |
| cmp2cmp = 0.36 * dbu_PERCISION |
| cmp2gr = 0.4 * dbu_PERCISION |
| mvpsd_ext_cmp = 0.8 * dbu_PERCISION |
| mvpsd_ov_cmp = 0.4 * dbu_PERCISION |
| mvpsd2gr = 1 * dbu_PERCISION |
| ply2gr = 0.4 * dbu_PERCISION |
| drain2ply = 0.16 * dbu_PERCISION |
| dnw_enc_cmp = 0.66 * dbu_PERCISION |
| dg_enc_pcmp = 0.5 * dbu_PERCISION |
| pcmp_gr2dnw = 2.5 * dbu_PERCISION |
| |
| |
| # Inserting PMOS cell |
| cell_index = layout.add_cell("pmos_10p0_asym") |
| cell = layout.cell(cell_index) |
| |
| # Inserting layers for LDMOS |
| cell.shapes(dnwell).insert(pya.Box( |
| -(dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+dnw_enc_cmp) - w/2, |
| (dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+dnw_enc_cmp) + w/2)) |
| cell.shapes(dualgate).insert(pya.Box( |
| -(dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp) - w/2, |
| (dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp) + w/2)) |
| cell.shapes(ldmos_xtor).insert(pya.Box( |
| -(dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp) - w/2, |
| (dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+dg_enc_pcmp+pcmp_gr2dnw+dnw_enc_cmp) + w/2)) |
| |
| # Inserting drain diffusion |
| cell.shapes(comp).insert(pya.Box(-cont_size/2, -w/2, cont_size/2, w/2)) |
| cell.shapes(mvpsd).insert(pya.Box(-(cont_size/2+cmp2cmp+mvpsd_ov_cmp), -w/2 - mvpsd_ext_cmp, (cont_size/2+cmp2cmp+mvpsd_ov_cmp), w/2 + mvpsd_ext_cmp)) |
| |
| # Inserting source diffusion |
| cell.shapes(comp).insert(pya.Box((cont_size/2+cmp2cmp), -w/2, (cont_size/2+cmp2cmp+mvpsd_ov_cmp+cont2ply+cont_size+cmp2cont) + l, w/2)) |
| cell.shapes(comp).insert(pya.Box(-(cont_size/2+cmp2cmp), -w/2, -(cont_size/2+cmp2cmp+mvpsd_ov_cmp+cont2ply+cont_size+cmp2cont) - l, w/2)) |
| |
| cell.shapes(pplus).insert(pya.Box(-(cont_size/2+cmp2cmp+mvpsd_ov_cmp+cont2ply+cont_size+cmp2cont+np_enc_cmp) - l, -w/2 - np_enc_gate, |
| (cont_size/2+cmp2cmp+mvpsd_ov_cmp+cont2ply+cont_size+cmp2cont+np_enc_cmp) + l, w/2 + np_enc_gate)) |
| |
| # Inserting gates |
| cell.shapes(poly2).insert(pya.Box((cont_size/2+drain2ply), -w/2 - ply_ext_cmp, (cont_size/2+cmp2cmp+mvpsd_ov_cmp) + l, w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr)) |
| cell.shapes(poly2).insert(pya.Box(-(cont_size/2+drain2ply), -w/2 - ply_ext_cmp, -(cont_size/2+cmp2cmp+mvpsd_ov_cmp) - l, w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr)) |
| |
| # Inserting a contact cell |
| cont_cell_index = layout.add_cell("contact") |
| cont_cell = layout.cell(cont_cell_index) |
| |
| # Inserting shapes now into the *contact* cell |
| cont_cell.shapes(contact).insert(pya.Box.new(0, 0, cont_size, cont_size)) |
| |
| # Contact array count and postions |
| ny = int((w - (cont_size+2*cmp2cont))/(cont_size+cont2cont)) + 1 |
| dy = (w - ny * cont_size - (ny - 1) * cont2cont)/2 |
| ng = int(((l + mvpsd_ov_cmp + ply_fld) - (cont_size+2*cmp2cont))/(cont_size+cont2cont)) + 1 |
| dg = (l + mvpsd_ov_cmp + ply_fld - ng * cont_size - (ng - 1) * cont2cont)/2 |
| |
| # Inserting contact array and metals |
| # Gate contacts and metal |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((cont_size/2+drain2ply) + dg, w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr-(metal_w+cont_size)/2)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), ng, 1)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(1.5*cont_size+drain2ply) - dg, w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr-(metal_w+cont_size)/2)), |
| pya.Point.new(-(cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), ng, 1)) |
| cell.shapes(metal1).insert(pya.Box((cont_size/2+drain2ply), w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr-metal_w, |
| (cont_size/2+cmp2cmp+mvpsd_ov_cmp) + l, w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr)) |
| cell.shapes(metal1).insert(pya.Box(-(cont_size/2+drain2ply), w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr-metal_w, |
| -(cont_size/2+cmp2cmp+mvpsd_ov_cmp) - l, w/2 + mvpsd_ext_cmp+mvpsd2gr-ply2gr)) |
| |
| # Drain contacts and metal |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-cont_size/2, -w/2 + dy)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, ny)) |
| cell.shapes(metal1).insert(pya.Box(-metal_w/2, -w/2, metal_w/2, w/2)) |
| |
| # Source contacts and metals |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((cont_size/2+cmp2cmp+mvpsd_ov_cmp+cont2ply) + l, -w/2 + dy)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, ny)) |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(1.5*cont_size+cmp2cmp+mvpsd_ov_cmp+cont2ply) - l, -w/2 + dy)), |
| pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, ny)) |
| cell.shapes(metal1).insert(pya.Box((1.5*cont_size+cmp2cmp+mvpsd_ov_cmp+cont2ply+cmp2cont-metal_w) + l, -w/2, (1.5*cont_size+cmp2cmp+mvpsd_ov_cmp+cont2ply+cmp2cont) + l, w/2)) |
| cell.shapes(metal1).insert(pya.Box(-(1.5*cont_size+cmp2cmp+mvpsd_ov_cmp+cont2ply+cmp2cont-metal_w) - l, -w/2, -(1.5*cont_size+cmp2cmp+mvpsd_ov_cmp+cont2ply+cmp2cont) - l, w/2)) |
| |
| # Inserting Guard Ring diffusion |
| cell.shapes(comp).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) - w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| cell.shapes(nplus).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) - w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-pp_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-pp_enc_cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr-pp_enc_cmp) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-pp_enc_cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr-pp_enc_cmp) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-pp_enc_cmp) + l, (mvpsd_ext_cmp+mvpsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr-pp_enc_cmp) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+pp_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+pp_enc_cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+pp_enc_cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pp_enc_cmp) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| cell.shapes(metal1).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) - w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr) - w/2), |
| pya.Point((0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr) + w/2), |
| pya.Point(-(2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) + w/2), |
| pya.Point((2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| nygr = int((w + 2*(mvpsd_ext_cmp+mvpsd2gr+cmp2cont+cont_size)+cont2cont)/(cont_size+cont2cont)) |
| dygr = (w + 2*(mvpsd_ext_cmp+mvpsd2gr+cmp2cont+cont_size) - nygr * (cont_size+cont2cont)+ cont2cont)/2 |
| nxgr_h = int((2 * l + 2*(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+cmp2cont)- cont2cont)/(cont_size+cont2cont)) |
| dxgr_h = (2 * l + 2*(0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+cmp2cont) - nxgr_h * (cont_size+cont2cont) + cont2cont)/2 |
| |
| # Inserting Guard Ring contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, |
| dygr - (mvpsd_ext_cmp+mvpsd2gr+cmp2cont+cont_size) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, nygr)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dxgr_h - (0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+cmp2cont) - l, |
| -(mvpsd_ext_cmp+mvpsd2gr+cmp2cont+cont_size) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), nxgr_h, 1)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((cmp2cont+0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, |
| dygr - (mvpsd_ext_cmp+mvpsd2gr+cmp2cont+cont_size) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, nygr)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dxgr_h - (0.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+cmp2cont) - l, |
| (mvpsd_ext_cmp+mvpsd2gr+cmp2cont) + w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), nxgr_h, 1)) |
| |
| # Inserting DNWELL Guard Ring |
| if dgr_en: |
| # Inserting DNWELL Guard Ring diffusion |
| cell.shapes(comp).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| cell.shapes(pplus).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+np_enc_cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp+np_enc_cmp) - w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+np_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp-np_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-np_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp-np_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-np_enc_cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp-np_enc_cmp) - w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-np_enc_cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp-np_enc_cmp) - w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp-np_enc_cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp-np_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+np_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp-np_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+np_enc_cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp+np_enc_cmp) + w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+np_enc_cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp+np_enc_cmp) + w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp+np_enc_cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp+np_enc_cmp) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| # Inserting DNWELL Guard Ring metal |
| cell.shapes(metal1).insert( |
| pya.Polygon( |
| [ |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+2*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point(-(pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, (mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) + w/2), |
| pya.Point((pcmp_gr2dnw+dnw_enc_cmp+4*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, -(mvpsd_ext_cmp+mvpsd2gr+4*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2), |
| ], |
| True, |
| ) |
| ) |
| |
| # Inserting DNWELL guard ring contacts |
| nygr = int((w + 2*(mvpsd_ext_cmp+mvpsd2gr+3*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp)+cont2cont)/(cont_size+cont2cont)) |
| dygr = (w + 2*(mvpsd_ext_cmp+mvpsd2gr+3*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - nygr * (cont_size+cont2cont) + cont2cont)/2 |
| nxgr_h = int((2 * l + 2*(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+2*cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp)- cont2cont)/(cont_size+cont2cont)) |
| dxgr_h = (2 * l + 2*(pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+2*cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - nxgr_h * (cont_size+cont2cont) + cont2cont)/2 |
| |
| # Inserting DNWELL Guard Ring contacts |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(-(pcmp_gr2dnw+dnw_enc_cmp+3*cmp2cont+2.5*cont_size+cmp2gr+cont_size+cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, |
| dygr - (mvpsd_ext_cmp+mvpsd2gr+3*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, nygr)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dxgr_h - (pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+2*cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, |
| -(mvpsd_ext_cmp+mvpsd2gr+3*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, -(cont_size+cont2cont)), nxgr_h, 1)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new((pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+2*cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) + l, |
| dygr - (mvpsd_ext_cmp+mvpsd2gr+3*cmp2cont+2*cont_size+pcmp_gr2dnw+dnw_enc_cmp) - w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), 1, nygr)) |
| |
| cell.insert(pya.CellInstArray.new(cont_cell_index, pya.Trans.new(pya.Point.new(dxgr_h - (pcmp_gr2dnw+dnw_enc_cmp+2*cmp2cont+1.5*cont_size+cmp2gr+cont_size+2*cmp2cont+cont2ply+mvpsd_ov_cmp+cmp2cmp) - l, |
| mvpsd_ext_cmp+mvpsd2gr+3*cmp2cont+cont_size+pcmp_gr2dnw+dnw_enc_cmp + w/2)), pya.Point.new((cont_size+cont2cont), 0), pya.Point.new(0, (cont_size+cont2cont)), nxgr_h, 1)) |
| |
| cell.flatten(True) |
| return cell |