| ################################################################################################ |
| # 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 |
| # |
| # https://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. |
| ################################################################################################ |
| |
| |
| if FEOL |
| |
| #================================================ |
| #---------------------NPLUS---------------------- |
| #================================================ |
| |
| # Rule NP.1: min. nplus width is 0.4µm |
| logger.info('Executing rule NP.1') |
| np1_l1 = nplus.width(0.4.um, euclidian).polygons(0.001) |
| np1_l1.output('NP.1', 'NP.1 : min. nplus width : 0.4µm') |
| np1_l1.forget |
| |
| # Rule NP.2: min. nplus spacing is 0.4µm |
| logger.info('Executing rule NP.2') |
| np2_l1 = nplus.space(0.4.um, euclidian).polygons(0.001) |
| np2_l1.output('NP.2', 'NP.2 : min. nplus spacing : 0.4µm') |
| np2_l1.forget |
| |
| # Rule NP.3a: Space to PCOMP for PCOMP: (1) Inside Nwell (2) Outside LVPWELL but inside DNWELL. is 0.16µm |
| logger.info('Executing rule NP.3a') |
| np3a_l1 = nplus.separation((pcomp.inside(nwell)).or(pcomp.outside(lvpwell).inside(dnwell)), 0.16.um, euclidian).polygons(0.001) |
| np3a_l1.output('NP.3a', 'NP.3a : Space to PCOMP for PCOMP: (1) Inside Nwell (2) Outside LVPWELL but inside DNWELL. : 0.16µm') |
| np3a_l1.forget |
| |
| np_3bi_extend = lvpwell.inside(dnwell).sized(-0.429.um) |
| np_3bi = pcomp.edges.and(lvpwell.inside(dnwell).not(np_3bi_extend)) |
| # Rule NP.3bi: Space to PCOMP: For Inside DNWELL, inside LVPWELL:(i) For PCOMP overlap by LVPWELL < 0.43um. is 0.16µm |
| logger.info('Executing rule NP.3bi') |
| np3bi_l1 = nplus.not_outside(lvpwell).inside(dnwell).edges.separation(np_3bi, 0.16.um, euclidian).polygons(0.001) |
| np3bi_l1.output('NP.3bi', 'NP.3bi : Space to PCOMP: For Inside DNWELL, inside LVPWELL:(i) For PCOMP overlap by LVPWELL < 0.43um. : 0.16µm') |
| np3bi_l1.forget |
| |
| np_3bi_extend.forget |
| |
| np_3bi.forget |
| |
| np_3bii_extend = lvpwell.inside(dnwell).sized(-0.429.um) |
| np_3bii = pcomp.edges.and(np_3bii_extend) |
| # Rule NP.3bii: Space to PCOMP: For Inside DNWELL, inside LVPWELL:(ii) For PCOMP overlap by LVPWELL >= 0.43um. is 0.08µm |
| logger.info('Executing rule NP.3bii') |
| np3bii_l1 = nplus.not_outside(lvpwell).inside(dnwell).edges.separation(np_3bii, 0.08.um, euclidian).polygons(0.001) |
| np3bii_l1.output('NP.3bii', 'NP.3bii : Space to PCOMP: For Inside DNWELL, inside LVPWELL:(ii) For PCOMP overlap by LVPWELL >= 0.43um. : 0.08µm') |
| np3bii_l1.forget |
| |
| np_3bii_extend.forget |
| |
| np_3bii.forget |
| |
| np_3ci = pcomp.edges.and(nwell.outside(dnwell).sized(0.429.um)) |
| # Rule NP.3ci: Space to PCOMP: For Outside DNWELL:(i) For PCOMP space to Nwell < 0.43um. is 0.16µm |
| logger.info('Executing rule NP.3ci') |
| np3ci_l1 = nplus.outside(dnwell).edges.separation(np_3ci, 0.16.um, euclidian).polygons |
| np3ci_l1.output('NP.3ci', 'NP.3ci : Space to PCOMP: For Outside DNWELL:(i) For PCOMP space to Nwell < 0.43um. : 0.16µm') |
| np3ci_l1.forget |
| |
| np_3ci.forget |
| |
| np_3cii = pcomp.edges.not(nwell.outside(dnwell).sized(0.429.um)) |
| # Rule NP.3cii: Space to PCOMP: For Outside DNWELL:(ii) For PCOMP space to Nwell >= 0.43um. is 0.08µm |
| logger.info('Executing rule NP.3cii') |
| np3cii_l1 = nplus.outside(dnwell).edges.separation(np_3cii, 0.08.um, euclidian).polygons |
| np3cii_l1.output('NP.3cii', 'NP.3cii : Space to PCOMP: For Outside DNWELL:(ii) For PCOMP space to Nwell >= 0.43um. : 0.08µm') |
| np3cii_l1.forget |
| |
| np_3cii.forget |
| |
| # Rule NP.3d: Min/max space to a butted PCOMP. |
| logger.info('Executing rule NP.3d') |
| np3d_l1 = nplus.not_outside(pcomp) |
| np3d_l1.output('NP.3d', 'NP.3d : Min/max space to a butted PCOMP.') |
| np3d_l1.forget |
| |
| # Rule NP.3e: Space to related PCOMP edge adjacent to a butting edge. |
| logger.info('Executing rule NP.3e') |
| np3e_l1 = nplus.not_outside(pcomp) |
| np3e_l1.output('NP.3e', 'NP.3e : Space to related PCOMP edge adjacent to a butting edge.') |
| np3e_l1.forget |
| |
| # Rule NP.4a: Space to related P-channel gate at a butting edge parallel to gate. is 0.32µm |
| logger.info('Executing rule NP.4a') |
| np4a_l1 = nplus.edges.and(pcomp.edges).separation(pgate.edges, 0.32.um, projection).polygons(0.001) |
| np4a_l1.output('NP.4a', 'NP.4a : Space to related P-channel gate at a butting edge parallel to gate. : 0.32µm') |
| np4a_l1.forget |
| |
| np_4b_poly = poly2.edges.interacting(pgate.edges.not(pcomp.edges)).centers(0, 0.99).and(pgate.sized(0.32.um)) |
| # Rule NP.4b: Within 0.32um of channel, space to P-channel gate extension perpendicular to the direction of Poly2. |
| logger.info('Executing rule NP.4b') |
| np4b_l1 = nplus.interacting(nplus.edges.separation(np_4b_poly, 0.22.um, projection).polygons(0.001)) |
| np4b_l1.output('NP.4b', 'NP.4b : Within 0.32um of channel, space to P-channel gate extension perpendicular to the direction of Poly2.') |
| np4b_l1.forget |
| |
| np_4b_poly.forget |
| |
| # Rule NP.5a: Overlap of N-channel gate. is 0.23µm |
| logger.info('Executing rule NP.5a') |
| np5a_l1 = nplus.enclosing(ngate, 0.23.um, euclidian).polygons(0.001) |
| np5a_l2 = ngate.not_outside(nplus).not(nplus) |
| np5a_l = np5a_l1.or(np5a_l2) |
| np5a_l.output('NP.5a', 'NP.5a : Overlap of N-channel gate. : 0.23µm') |
| np5a_l1.forget |
| np5a_l2.forget |
| np5a_l.forget |
| |
| # Rule NP.5b: Extension beyond COMP for the COMP (1) inside LVPWELL (2) outside Nwell and DNWELL. is 0.16µm |
| logger.info('Executing rule NP.5b') |
| np5b_l1 = nplus.not_outside(lvpwell).or(nplus.outside(nwell).outside(dnwell)).edges.not(pplus).enclosing(comp.edges, 0.16.um, euclidian).polygons(0.001) |
| np5b_l1.output('NP.5b', 'NP.5b : Extension beyond COMP for the COMP (1) inside LVPWELL (2) outside Nwell and DNWELL. : 0.16µm') |
| np5b_l1.forget |
| |
| np_5ci_background = nplus.not_inside(lvpwell).inside(dnwell).edges |
| np_5ci_foreground = ncomp.not_inside(lvpwell).inside(dnwell).edges.not(pplus.edges).and(lvpwell.inside(dnwell).sized(0.429.um)) |
| # Rule NP.5ci: Extension beyond COMP: For Inside DNWELL: (i)For Nplus < 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. is 0.16µm |
| logger.info('Executing rule NP.5ci') |
| np5ci_l1 = np_5ci_background.enclosing(np_5ci_foreground, 0.16.um, projection).polygons(0.001) |
| np5ci_l1.output('NP.5ci', 'NP.5ci : Extension beyond COMP: For Inside DNWELL: (i)For Nplus < 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. : 0.16µm') |
| np5ci_l1.forget |
| |
| np_5ci_background.forget |
| |
| np_5ci_foreground.forget |
| |
| np_5cii_background = nplus.not_inside(lvpwell).inside(dnwell).edges |
| np_5cii_foreground = ncomp.not_inside(lvpwell).inside(dnwell).edges.not(pplus.edges).not(lvpwell.inside(dnwell).sized(0.429.um)) |
| # Rule NP.5cii: Extension beyond COMP: For Inside DNWELL: (ii) For Nplus >= 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. is 0.02µm |
| logger.info('Executing rule NP.5cii') |
| np5cii_l1 = np_5cii_background.enclosing(np_5cii_foreground, 0.02.um, projection).polygons(0.001) |
| np5cii_l1.output('NP.5cii', 'NP.5cii : Extension beyond COMP: For Inside DNWELL: (ii) For Nplus >= 0.43um from LVPWELL edge for Nwell or DNWELL tap inside DNWELL. : 0.02µm') |
| np5cii_l1.forget |
| |
| np_5cii_background.forget |
| |
| np_5cii_foreground.forget |
| |
| np_5di_background = nplus.not_outside(nwell).outside(dnwell).edges |
| np_5di_extend = nwell.outside(dnwell).not(nwell.outside(dnwell).sized(-0.429.um)) |
| np_5di_foreground = ncomp.not_outside(nwell).outside(dnwell).edges.not(pplus.edges).and(np_5di_extend) |
| # Rule NP.5di: Extension beyond COMP: For Outside DNWELL, inside Nwell: (i) For Nwell overlap of Nplus < 0.43um. is 0.16µm |
| logger.info('Executing rule NP.5di') |
| np5di_l1 = np_5di_background.enclosing(np_5di_foreground, 0.16.um, projection).polygons(0.001) |
| np5di_l1.output('NP.5di', 'NP.5di : Extension beyond COMP: For Outside DNWELL, inside Nwell: (i) For Nwell overlap of Nplus < 0.43um. : 0.16µm') |
| np5di_l1.forget |
| |
| np_5di_background.forget |
| |
| np_5di_extend.forget |
| |
| np_5di_foreground.forget |
| |
| np_5dii_background = nplus.not_outside(nwell).outside(dnwell).edges.not(pplus.edges) |
| np_5dii_extend = nwell.outside(dnwell).sized(-0.429.um) |
| np_5dii_foreground = ncomp.not_outside(nwell).outside(dnwell).edges.not(pplus.edges).and(np_5dii_extend) |
| # Rule NP.5dii: Extension beyond COMP: For Outside DNWELL, inside Nwell: (ii) For Nwell overlap of Nplus >= 0.43um. is 0.02µm |
| logger.info('Executing rule NP.5dii') |
| np5dii_l1 = np_5dii_background.enclosing(np_5dii_foreground, 0.02.um, euclidian).polygons(0.001) |
| np5dii_l1.output('NP.5dii', 'NP.5dii : Extension beyond COMP: For Outside DNWELL, inside Nwell: (ii) For Nwell overlap of Nplus >= 0.43um. : 0.02µm') |
| np5dii_l1.forget |
| |
| np_5dii_background.forget |
| |
| np_5dii_extend.forget |
| |
| np_5dii_foreground.forget |
| |
| # Rule NP.6: Overlap with NCOMP butted to PCOMP. is 0.22µm |
| logger.info('Executing rule NP.6') |
| np6_l1 = comp.interacting(nplus).enclosing(pcomp.interacting(nplus), 0.22.um, projection).polygons |
| np6_l1.output('NP.6', 'NP.6 : Overlap with NCOMP butted to PCOMP. : 0.22µm') |
| np6_l1.forget |
| |
| # Rule NP.7: Space to unrelated unsalicided Poly2. is 0.18µm |
| logger.info('Executing rule NP.7') |
| np7_l1 = nplus.separation(poly2.and(sab), 0.18.um, euclidian).polygons(0.001) |
| np7_l1.output('NP.7', 'NP.7 : Space to unrelated unsalicided Poly2. : 0.18µm') |
| np7_l1.forget |
| |
| # Rule NP.8a: Minimum Nplus area (um2). is 0.35µm² |
| logger.info('Executing rule NP.8a') |
| np8a_l1 = nplus.with_area(nil, 0.35.um) |
| np8a_l1.output('NP.8a', 'NP.8a : Minimum Nplus area (um2). : 0.35µm²') |
| np8a_l1.forget |
| |
| # Rule NP.8b: Minimum area enclosed by Nplus (um2). is 0.35µm² |
| logger.info('Executing rule NP.8b') |
| np8b_l1 = nplus.holes.with_area(nil, 0.35.um) |
| np8b_l1.output('NP.8b', 'NP.8b : Minimum area enclosed by Nplus (um2). : 0.35µm²') |
| np8b_l1.forget |
| |
| # Rule NP.9: Overlap of unsalicided Poly2. is 0.18µm |
| logger.info('Executing rule NP.9') |
| np9_l1 = nplus.enclosing(poly2.and(sab), 0.18.um, euclidian).polygons(0.001) |
| np9_l2 = poly2.and(sab).not_outside(nplus).not(nplus) |
| np9_l = np9_l1.or(np9_l2) |
| np9_l.output('NP.9', 'NP.9 : Overlap of unsalicided Poly2. : 0.18µm') |
| np9_l1.forget |
| np9_l2.forget |
| np9_l.forget |
| |
| # Rule NP.10: Overlap of unsalicided COMP. is 0.18µm |
| logger.info('Executing rule NP.10') |
| np10_l1 = nplus.enclosing(comp.and(sab), 0.18.um, euclidian).polygons(0.001) |
| np10_l1.output('NP.10', 'NP.10 : Overlap of unsalicided COMP. : 0.18µm') |
| np10_l1.forget |
| |
| np_11_in_dnwell = nplus.interacting(nplus.edges.and(pcomp.edges).and(lvpwell.inside(dnwell).not(lvpwell.inside(dnwell).sized(-0.429.um)))) |
| np_11_out_dnwell = nplus.interacting(nplus.edges.and(pcomp.edges).and(nwell.outside(dnwell).sized(0.429.um))) |
| # Rule NP.11: Butting Nplus and PCOMP is forbidden within 0.43um of Nwell edge (for outside DNWELL) and of LVPWELL edge (for inside DNWELL case). |
| logger.info('Executing rule NP.11') |
| np11_l1 = np_11_in_dnwell.or(np_11_out_dnwell) |
| np11_l1.output('NP.11', 'NP.11 : Butting Nplus and PCOMP is forbidden within 0.43um of Nwell edge (for outside DNWELL) and of LVPWELL edge (for inside DNWELL case).') |
| np11_l1.forget |
| |
| np_11_in_dnwell.forget |
| |
| np_11_out_dnwell.forget |
| |
| # Rule NP.12: Overlap with P-channel poly2 gate extension is forbidden within 0.32um of P-channel gate. |
| logger.info('Executing rule NP.12') |
| np12_l1 = nplus.interacting(nplus.edges.separation(pgate.edges.and(pcomp.edges), 0.32.um, euclidian).polygons(0.001)) |
| np12_l1.output('NP.12', 'NP.12 : Overlap with P-channel poly2 gate extension is forbidden within 0.32um of P-channel gate.') |
| np12_l1.forget |
| |
| end #FEOL |